#include "lisp.h"
#include "buffer.h"
#include "charset.h"
+#include "composite.h"
#include "coding.h"
#include "disptab.h"
*p++ = c + 0x20;
}
}
- else if (c < MAX_CHAR)
+ else if (CHAR_VALID_P (c, 0))
{
int charset, c1, c2;
char_printable_p (c)
int c;
{
- int charset, c1, c2, chars;
+ int charset, c1, c2;
if (ASCII_BYTE_P (c))
return 1;
}
/* Update table iso_charset_table. */
- if (iso_final_char >= 0
+ if (XINT (iso_final_char) >= 0
&& ISO_CHARSET_TABLE (dimension, chars, iso_final_char) < 0)
ISO_CHARSET_TABLE (dimension, chars, iso_final_char) = charset;
}
if (dimension == 1)
{
- if (width == 1)
- from = LEADING_CODE_EXT_11, to = LEADING_CODE_EXT_12;
- else
- from = LEADING_CODE_EXT_12, to = LEADING_CODE_EXT_21;
+ from = LEADING_CODE_EXT_11;
+ to = LEADING_CODE_EXT_21;
}
else
{
- if (width == 1)
- from = LEADING_CODE_EXT_21, to = LEADING_CODE_EXT_22;
- else
- from = LEADING_CODE_EXT_22, to = LEADING_CODE_EXT_MAX + 1;
+ from = LEADING_CODE_EXT_21;
+ to = LEADING_CODE_EXT_MAX + 1;
}
for (charset = from; charset < to; charset++)
BEG and END are buffer positions.\n\
Optional arg TABLE if non-nil is a translation table to look up.\n\
\n\
-If the region contains invalid multiybte characters,\n\
+If the region contains invalid multibyte characters,\n\
`unknown' is included in the returned list.\n\
\n\
If the current buffer is unibyte, the returned list may contain\n\
"Return a list of charsets in STR.\n\
Optional arg TABLE if non-nil is a translation table to look up.\n\
\n\
-If the region contains invalid multiybte characters,\n\
+If the string contains invalid multibyte characters,\n\
`unknown' is included in the returned list.\n\
\n\
If STR is unibyte, the returned list may contain\n\
}
else if (charset_id == CHARSET_8_BIT_CONTROL)
{
- if (c1 < 0x80 || c1 > 0x9F)
+ if (NILP (code1))
+ c1 = 0x80;
+ else if (c1 < 0x80 || c1 > 0x9F)
goto invalid_code_posints;
return make_number (c1);
}
else if (charset_id == CHARSET_8_BIT_GRAPHIC)
{
- if (c1 < 0xA0 || c1 > 0xFF)
+ if (NILP (code1))
+ c1 = 0xA0;
+ else if (c1 < 0xA0 || c1 > 0xFF)
goto invalid_code_posints;
return make_number (c1);
}
(ch)
Lisp_Object ch;
{
- Lisp_Object val;
int c, charset, c1, c2;
CHECK_NUMBER (ch, 0);
{
int charset, c1, c2;
- if (c < 0)
+ if (c < 0 || c >= MAX_CHAR)
return 0;
if (SINGLE_BYTE_CHAR_P (c))
return 1;
(ch)
Lisp_Object ch;
{
- Lisp_Object val;
-
CHECK_NUMBER (ch, 0);
return make_number (1);
}
DEFUN ("char-width", Fchar_width, Schar_width, 1, 1, 0,
"Return width of CHAR when displayed in the current buffer.\n\
-The width is measured by how many columns it occupies on the screen.")
+The width is measured by how many columns it occupies on the screen.\n\
+Tab is taken to occupy `tab-width' columns.")
(ch)
Lisp_Object ch;
{
unsigned char *str;
int len;
{
- unsigned char *endp = str + len;
+ return c_string_width (str, len, -1, NULL, NULL);
+}
+
+/* Return width of string STR of length LEN when displayed in the
+ current buffer. The width is measured by how many columns it
+ occupies on the screen. If PRECISION > 0, return the width of
+ longest substring that doesn't exceed PRECISION, and set number of
+ characters and bytes of the substring in *NCHARS and *NBYTES
+ respectively. */
+
+int
+c_string_width (str, len, precision, nchars, nbytes)
+ unsigned char *str;
+ int precision, *nchars, *nbytes;
+{
+ int i = 0, i_byte = 0;
int width = 0;
+ int chars;
struct Lisp_Char_Table *dp = buffer_display_table ();
- while (str < endp)
+ while (i_byte < len)
{
- Lisp_Object disp;
- int thislen;
- int c = STRING_CHAR_AND_LENGTH (str, endp - str, thislen);
+ int bytes, thiswidth;
+ Lisp_Object val;
- /* Get the way the display table would display it. */
if (dp)
- disp = DISP_CHAR_VECTOR (dp, c);
+ {
+ int c = STRING_CHAR_AND_LENGTH (str + i_byte, len - i_byte, bytes);
+
+ chars = 1;
+ val = DISP_CHAR_VECTOR (dp, c);
+ if (VECTORP (val))
+ thiswidth = XVECTOR (val)->size;
+ else
+ thiswidth = ONE_BYTE_CHAR_WIDTH (str[i_byte]);
+ }
else
- disp = Qnil;
+ {
+ chars = 1;
+ PARSE_MULTIBYTE_SEQ (str + i_byte, len - i_byte, bytes);
+ thiswidth = ONE_BYTE_CHAR_WIDTH (str[i_byte]);
+ }
+
+ if (precision > 0
+ && (width + thiswidth > precision))
+ {
+ *nchars = i;
+ *nbytes = i_byte;
+ return width;
+ }
+ i++;
+ i_byte += bytes;
+ width += thiswidth;
+ }
- if (VECTORP (disp))
- width += XVECTOR (disp)->size;
+ if (precision > 0)
+ {
+ *nchars = i;
+ *nbytes = i_byte;
+ }
+
+ return width;
+}
+
+/* Return width of Lisp string STRING when displayed in the current
+ buffer. The width is measured by how many columns it occupies on
+ the screen while paying attention to compositions. If PRECISION >
+ 0, return the width of longest substring that doesn't exceed
+ PRECISION, and set number of characters and bytes of the substring
+ in *NCHARS and *NBYTES respectively. */
+
+int
+lisp_string_width (string, precision, nchars, nbytes)
+ Lisp_Object string;
+ int precision, *nchars, *nbytes;
+{
+ int len = XSTRING (string)->size;
+ int len_byte = STRING_BYTES (XSTRING (string));
+ unsigned char *str = XSTRING (string)->data;
+ int i = 0, i_byte = 0;
+ int width = 0;
+ struct Lisp_Char_Table *dp = buffer_display_table ();
+
+ while (i < len)
+ {
+ int chars, bytes, thiswidth;
+ Lisp_Object val;
+ int cmp_id;
+ int ignore, end;
+
+ if (find_composition (i, -1, &ignore, &end, &val, string)
+ && ((cmp_id = get_composition_id (i, i_byte, end - i, val, string))
+ >= 0))
+ {
+ thiswidth = composition_table[cmp_id]->width;
+ chars = end - i;
+ bytes = string_char_to_byte (string, end) - i_byte;
+ }
+ else if (dp)
+ {
+ int c = STRING_CHAR_AND_LENGTH (str + i_byte, len - i_byte, bytes);
+
+ chars = 1;
+ val = DISP_CHAR_VECTOR (dp, c);
+ if (VECTORP (val))
+ thiswidth = XVECTOR (val)->size;
+ else
+ thiswidth = ONE_BYTE_CHAR_WIDTH (str[i_byte]);
+ }
else
- width += ONE_BYTE_CHAR_WIDTH (*str);
+ {
+ chars = 1;
+ PARSE_MULTIBYTE_SEQ (str + i_byte, len_byte - i_byte, bytes);
+ thiswidth = ONE_BYTE_CHAR_WIDTH (str[i_byte]);
+ }
+
+ if (precision > 0
+ && (width + thiswidth > precision))
+ {
+ *nchars = i;
+ *nbytes = i_byte;
+ return width;
+ }
+ i += chars;
+ i_byte += bytes;
+ width += thiswidth;
+ }
- str += thislen;
+ if (precision > 0)
+ {
+ *nchars = i;
+ *nbytes = i_byte;
}
+
return width;
}
Width is measured by how many columns it occupies on the screen.\n\
When calculating width of a multibyte character in STRING,\n\
only the base leading-code is considered; the validity of\n\
-the following bytes is not checked.")
+the following bytes is not checked. Tabs in STRING are always\n\
+taken to occupy `tab-width' columns.")
(str)
Lisp_Object str;
{
Lisp_Object val;
CHECK_STRING (str, 0);
- XSETFASTINT (val, strwidth (XSTRING (str)->data,
- STRING_BYTES (XSTRING (str))));
+ XSETFASTINT (val, lisp_string_width (str, -1, NULL, NULL));
return val;
}
{
unsigned char *p = str, *endp = str + bytes;
unsigned char *to;
- int c;
while (p < endp && (*p < 0x80 || *p >= 0xA0)) p++;
if (p == endp)