~ubuntu-branches/debian/jessie/lftp/jessie

« back to all changes in this revision

Viewing changes to lib/mbswidth.c

  • Committer: Bazaar Package Importer
  • Author(s): Noèl Köthe
  • Date: 2004-06-01 04:01:39 UTC
  • Revision ID: james.westby@ubuntu.com-20040601040139-negt39q17jhkv3i4
Tags: upstream-3.0.5
Import upstream version 3.0.5

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Determine the number of screen columns needed for a string.
 
2
   Copyright (C) 2000 Free Software Foundation, Inc.
 
3
 
 
4
   This program is free software; you can redistribute it and/or modify
 
5
   it under the terms of the GNU General Public License as published by
 
6
   the Free Software Foundation; either version 2, or (at your option)
 
7
   any later version.
 
8
 
 
9
   This program is distributed in the hope that it will be useful,
 
10
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
   GNU General Public License for more details.
 
13
 
 
14
   You should have received a copy of the GNU General Public License
 
15
   along with this program; if not, write to the Free Software Foundation,
 
16
   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
17
 
 
18
/* Written by Bruno Haible <haible@clisp.cons.org>.  */
 
19
 
 
20
#ifdef HAVE_CONFIG_H
 
21
# include <config.h>
 
22
#endif
 
23
 
 
24
/* Get MB_LEN_MAX.  */
 
25
#if HAVE_LIMITS_H
 
26
# include <limits.h>
 
27
#endif
 
28
 
 
29
/* Get MB_CUR_MAX.  */
 
30
#if HAVE_STDLIB_H
 
31
# include <stdlib.h>
 
32
#endif
 
33
 
 
34
#if HAVE_STRING_H
 
35
# include <string.h>
 
36
#endif
 
37
 
 
38
/* Get isprint().  */
 
39
#include <ctype.h>
 
40
 
 
41
/* Get mbstate_t, mbrtowc(), mbsinit(), wcwidth().  */
 
42
#if HAVE_WCHAR_H
 
43
# include <wchar.h>
 
44
#endif
 
45
 
 
46
/* Get iswprint().  */
 
47
#if HAVE_WCTYPE_H
 
48
# include <wctype.h>
 
49
#endif
 
50
#if !defined iswprint && !HAVE_ISWPRINT
 
51
# define iswprint(wc) 1
 
52
#endif
 
53
 
 
54
#ifndef HAVE_DECL_WCWIDTH
 
55
"this configure-time declaration test was not run"
 
56
#endif
 
57
#if !HAVE_DECL_WCWIDTH
 
58
int wcwidth ();
 
59
#endif
 
60
 
 
61
#ifndef wcwidth
 
62
# if !HAVE_WCWIDTH
 
63
/* wcwidth doesn't exist, so assume all printable characters have
 
64
   width 1.  */
 
65
#  define wcwidth(wc) ((wc) == 0 ? 0 : iswprint (wc) ? 1 : -1)
 
66
# endif
 
67
#endif
 
68
 
 
69
/* Get ISPRINT.  */
 
70
#if defined (STDC_HEADERS) || (!defined (isascii) && !defined (HAVE_ISASCII))
 
71
# define IN_CTYPE_DOMAIN(c) 1
 
72
#else
 
73
# define IN_CTYPE_DOMAIN(c) isascii(c)
 
74
#endif
 
75
/* Undefine to protect against the definition in wctype.h of solaris2.6.   */
 
76
#undef ISPRINT
 
77
#define ISPRINT(c) (IN_CTYPE_DOMAIN (c) && isprint (c))
 
78
 
 
79
#include "mbswidth.h"
 
80
 
 
81
/* Returns the number of columns needed to represent the multibyte
 
82
   character string pointed to by STRING.  If a non-printable character
 
83
   occurs, -1 is returned, unless MBSW_ACCEPT_UNPRINTABLE is specified.
 
84
   With flags = 0, this is the multibyte analogon of the wcswidth function.  */
 
85
int
 
86
mbswidth (const char *string, int flags)
 
87
{
 
88
  return mbsnwidth (string, strlen (string), flags);
 
89
}
 
90
 
 
91
/* Returns the number of columns needed to represent the multibyte
 
92
   character string pointed to by STRING of length NBYTES.  If a
 
93
   non-printable character occurs, -1 is returned, unless
 
94
   MBSW_ACCEPT_UNPRINTABLE is specified.  */
 
95
int
 
96
mbsnwidth (const char *string, size_t nbytes, int flags)
 
97
{
 
98
  const char *p = string;
 
99
  const char *plimit = p + nbytes;
 
100
  int width;
 
101
 
 
102
  width = 0;
 
103
#if HAVE_MBRTOWC && (MB_LEN_MAX > 1)
 
104
  if (MB_CUR_MAX > 1)
 
105
    {
 
106
      while (p < plimit)
 
107
        switch (*p)
 
108
          {
 
109
            case ' ': case '!': case '"': case '#': case '%':
 
110
            case '&': case '\'': case '(': case ')': case '*':
 
111
            case '+': case ',': case '-': case '.': case '/':
 
112
            case '0': case '1': case '2': case '3': case '4':
 
113
            case '5': case '6': case '7': case '8': case '9':
 
114
            case ':': case ';': case '<': case '=': case '>':
 
115
            case '?':
 
116
            case 'A': case 'B': case 'C': case 'D': case 'E':
 
117
            case 'F': case 'G': case 'H': case 'I': case 'J':
 
118
            case 'K': case 'L': case 'M': case 'N': case 'O':
 
119
            case 'P': case 'Q': case 'R': case 'S': case 'T':
 
120
            case 'U': case 'V': case 'W': case 'X': case 'Y':
 
121
            case 'Z':
 
122
            case '[': case '\\': case ']': case '^': case '_':
 
123
            case 'a': case 'b': case 'c': case 'd': case 'e':
 
124
            case 'f': case 'g': case 'h': case 'i': case 'j':
 
125
            case 'k': case 'l': case 'm': case 'n': case 'o':
 
126
            case 'p': case 'q': case 'r': case 's': case 't':
 
127
            case 'u': case 'v': case 'w': case 'x': case 'y':
 
128
            case 'z': case '{': case '|': case '}': case '~':
 
129
              /* These characters are printable ASCII characters.  */
 
130
              p++;
 
131
              width++;
 
132
              break;
 
133
            default:
 
134
              /* If we have a multibyte sequence, scan it up to its end.  */
 
135
              {
 
136
                mbstate_t mbstate;
 
137
                memset (&mbstate, 0, sizeof mbstate);
 
138
                do
 
139
                  {
 
140
                    wchar_t wc;
 
141
                    size_t bytes;
 
142
                    int w;
 
143
 
 
144
                    bytes = mbrtowc (&wc, p, plimit - p, &mbstate);
 
145
 
 
146
                    if (bytes == (size_t) -1)
 
147
                      /* An invalid multibyte sequence was encountered.  */
 
148
                      {
 
149
                        if (flags & MBSW_ACCEPT_INVALID)
 
150
                          {
 
151
                            p++;
 
152
                            width++;
 
153
                            break;
 
154
                          }
 
155
                        else
 
156
                          return -1;
 
157
                      }
 
158
 
 
159
                    if (bytes == (size_t) -2)
 
160
                      /* An incomplete multibyte character at the end.  */
 
161
                      {
 
162
                        if (flags & MBSW_ACCEPT_INVALID)
 
163
                          {
 
164
                            p = plimit;
 
165
                            width++;
 
166
                            break;
 
167
                          }
 
168
                        else
 
169
                          return -1;
 
170
                      }
 
171
 
 
172
                    if (bytes == 0)
 
173
                      /* A null wide character was encountered.  */
 
174
                      bytes = 1;
 
175
 
 
176
                    w = wcwidth (wc);
 
177
                    if (w >= 0)
 
178
                      /* A printable multibyte character.  */
 
179
                      width += w;
 
180
                    else
 
181
                      /* An unprintable multibyte character.  */
 
182
                      if (flags & MBSW_ACCEPT_UNPRINTABLE)
 
183
                        width += 1;
 
184
                      else
 
185
                        return -1;
 
186
 
 
187
                    p += bytes;
 
188
                  }
 
189
                while (! mbsinit (&mbstate));
 
190
              }
 
191
              break;
 
192
          }
 
193
      return width;
 
194
    }
 
195
#endif
 
196
 
 
197
  while (p < plimit)
 
198
    {
 
199
      unsigned char c = (unsigned char) *p++;
 
200
 
 
201
      if ((flags & MBSW_ACCEPT_UNPRINTABLE) || ISPRINT (c))
 
202
        width++;
 
203
      else
 
204
        return -1;
 
205
    }
 
206
  return width;
 
207
}