~ubuntu-branches/ubuntu/trusty/grub2/trusty-updates

« back to all changes in this revision

Viewing changes to grub-core/normal/charset.c

  • Committer: Package Import Robot
  • Author(s): Colin Watson
  • Date: 2012-09-13 18:02:04 UTC
  • mfrom: (1.17.15 upstream)
  • mto: (17.6.27 experimental)
  • mto: This revision was merged to the branch mainline in revision 145.
  • Revision ID: package-import@ubuntu.com-20120913180204-mojnmocbimlom4im
Tags: upstream-2.00
ImportĀ upstreamĀ versionĀ 2.00

Show diffs side-by-side

added added

removed removed

Lines of Context:
42
42
  Most underline diacritics aren't displayed in gfxterm
43
43
 */
44
44
 
45
 
/* Convert a (possibly null-terminated) UTF-8 string of at most SRCSIZE
46
 
   bytes (if SRCSIZE is -1, it is ignored) in length to a UTF-16 string.
47
 
   Return the number of characters converted. DEST must be able to hold
48
 
   at least DESTSIZE characters. If an invalid sequence is found, return -1.
49
 
   If SRCEND is not NULL, then *SRCEND is set to the next byte after the
50
 
   last byte used in SRC.  */
51
 
 
52
45
#include <grub/charset.h>
53
46
#include <grub/mm.h>
54
47
#include <grub/misc.h>
60
53
#include "widthspec.h"
61
54
#endif
62
55
 
 
56
/* Returns -2 if not enough space, -1 on invalid character.  */
63
57
grub_ssize_t
64
 
grub_utf8_to_utf16 (grub_uint16_t *dest, grub_size_t destsize,
65
 
                    const grub_uint8_t *src, grub_size_t srcsize,
66
 
                    const grub_uint8_t **srcend)
 
58
grub_encode_utf8_character (grub_uint8_t *dest, grub_uint8_t *destend,
 
59
                            grub_uint32_t code)
67
60
{
68
 
  grub_uint16_t *p = dest;
69
 
  int count = 0;
70
 
  grub_uint32_t code = 0;
71
 
 
72
 
  if (srcend)
73
 
    *srcend = src;
74
 
 
75
 
  while (srcsize && destsize)
76
 
    {
77
 
      grub_uint32_t c = *src++;
78
 
      if (srcsize != (grub_size_t)-1)
79
 
        srcsize--;
80
 
      if (count)
81
 
        {
82
 
          if ((c & GRUB_UINT8_2_LEADINGBITS) != GRUB_UINT8_1_LEADINGBIT)
83
 
            {
84
 
              /* invalid */
85
 
              return -1;
86
 
            }
87
 
          else
88
 
            {
89
 
              code <<= 6;
90
 
              code |= (c & GRUB_UINT8_6_TRAILINGBITS);
91
 
              count--;
92
 
            }
93
 
        }
94
 
      else
95
 
        {
96
 
          if (c == 0)
97
 
            break;
98
 
 
99
 
          if ((c & GRUB_UINT8_1_LEADINGBIT) == 0)
100
 
            code = c;
101
 
          else if ((c & GRUB_UINT8_3_LEADINGBITS) == GRUB_UINT8_2_LEADINGBITS)
102
 
            {
103
 
              count = 1;
104
 
              code = c & GRUB_UINT8_5_TRAILINGBITS;
105
 
            }
106
 
          else if ((c & GRUB_UINT8_4_LEADINGBITS) == GRUB_UINT8_3_LEADINGBITS)
107
 
            {
108
 
              count = 2;
109
 
              code = c & GRUB_UINT8_4_TRAILINGBITS;
110
 
            }
111
 
          else if ((c & GRUB_UINT8_5_LEADINGBITS) == GRUB_UINT8_4_LEADINGBITS)
112
 
            {
113
 
              count = 3;
114
 
              code = c & GRUB_UINT8_3_TRAILINGBITS;
115
 
            }
116
 
          else
117
 
            return -1;
118
 
        }
119
 
 
120
 
      if (count == 0)
121
 
        {
122
 
          if (destsize < 2 && code >= GRUB_UCS2_LIMIT)
123
 
            break;
124
 
          if (code >= GRUB_UCS2_LIMIT)
125
 
            {
126
 
              *p++ = GRUB_UTF16_UPPER_SURROGATE (code);
127
 
              *p++ = GRUB_UTF16_LOWER_SURROGATE (code);
128
 
              destsize -= 2;
129
 
            }
130
 
          else
131
 
            {
132
 
              *p++ = code;
133
 
              destsize--;
134
 
            }
135
 
        }
136
 
    }
137
 
 
138
 
  if (srcend)
139
 
    *srcend = src;
140
 
  return p - dest;
 
61
  if (dest >= destend)
 
62
    return -2;
 
63
  if (code <= 0x007F)
 
64
    {
 
65
      *dest++ = code;
 
66
      return 1;
 
67
    }
 
68
  if (code <= 0x07FF)
 
69
    {
 
70
      if (dest + 1 >= destend)
 
71
        return -2;
 
72
      *dest++ = (code >> 6) | 0xC0;
 
73
      *dest++ = (code & 0x3F) | 0x80;
 
74
      return 2;
 
75
    }
 
76
  if ((code >= 0xDC00 && code <= 0xDFFF)
 
77
      || (code >= 0xD800 && code <= 0xDBFF))
 
78
    {
 
79
      /* No surrogates in UCS-4... */
 
80
      return -1;
 
81
    }
 
82
  if (code < 0x10000)
 
83
    {
 
84
      if (dest + 2 >= destend)
 
85
        return -2;
 
86
      *dest++ = (code >> 12) | 0xE0;
 
87
      *dest++ = ((code >> 6) & 0x3F) | 0x80;
 
88
      *dest++ = (code & 0x3F) | 0x80;
 
89
      return 3;
 
90
    }
 
91
  {
 
92
    if (dest + 3 >= destend)
 
93
      return -2;
 
94
    *dest++ = (code >> 18) | 0xF0;
 
95
    *dest++ = ((code >> 12) & 0x3F) | 0x80;
 
96
    *dest++ = ((code >> 6) & 0x3F) | 0x80;
 
97
    *dest++ = (code & 0x3F) | 0x80;
 
98
    return 4;
 
99
  }
 
100
 
141
101
}
142
102
 
143
103
/* Convert UCS-4 to UTF-8.  */
144
 
void
145
 
grub_ucs4_to_utf8 (grub_uint32_t *src, grub_size_t size,
 
104
grub_size_t
 
105
grub_ucs4_to_utf8 (const grub_uint32_t *src, grub_size_t size,
146
106
                   grub_uint8_t *dest, grub_size_t destsize)
147
107
{
148
108
  /* Keep last char for \0.  */
149
109
  grub_uint8_t *destend = dest + destsize - 1;
 
110
  grub_uint8_t *dest0 = dest;
150
111
 
151
112
  while (size-- && dest < destend)
152
113
    {
153
114
      grub_uint32_t code = *src++;
154
 
 
155
 
      if (code <= 0x007F)
156
 
        *dest++ = code;
157
 
      else if (code <= 0x07FF)
158
 
        {
159
 
          if (dest + 1 >= destend)
160
 
            break;
161
 
          *dest++ = (code >> 6) | 0xC0;
162
 
          *dest++ = (code & 0x3F) | 0x80;
163
 
        }
164
 
      else if ((code >= 0xDC00 && code <= 0xDFFF)
165
 
               || (code >= 0xD800 && code <= 0xDBFF))
166
 
        {
167
 
          /* No surrogates in UCS-4... */
 
115
      grub_ssize_t s;
 
116
      s = grub_encode_utf8_character (dest, destend, code);
 
117
      if (s == -2)
 
118
        break;
 
119
      if (s == -1)
 
120
        {
168
121
          *dest++ = '?';
169
 
        }
170
 
      else if (code < 0x10000)
171
 
        {
172
 
          if (dest + 2 >= destend)
173
 
            break;
174
 
          *dest++ = (code >> 12) | 0xE0;
175
 
          *dest++ = ((code >> 6) & 0x3F) | 0x80;
176
 
          *dest++ = (code & 0x3F) | 0x80;
177
 
        }
178
 
      else
179
 
        {
180
 
          if (dest + 3 >= destend)
181
 
            break;
182
 
          *dest++ = (code >> 18) | 0xF0;
183
 
          *dest++ = ((code >> 12) & 0x3F) | 0x80;
184
 
          *dest++ = ((code >> 6) & 0x3F) | 0x80;
185
 
          *dest++ = (code & 0x3F) | 0x80;
186
 
        }
 
122
          continue;
 
123
        }
 
124
      dest += s;
187
125
    }
188
126
  *dest = 0;
 
127
  return dest - dest0;
189
128
}
190
129
 
191
 
/* Convert UCS-4 to UTF-8.  */
192
 
char *
193
 
grub_ucs4_to_utf8_alloc (grub_uint32_t *src, grub_size_t size)
 
130
/* Returns the number of bytes the string src would occupy is converted
 
131
   to UTF-8, excluding trailing \0.  */
 
132
grub_size_t
 
133
grub_get_num_of_utf8_bytes (const grub_uint32_t *src, grub_size_t size)
194
134
{
195
135
  grub_size_t remaining;
196
 
  grub_uint32_t *ptr;
 
136
  const grub_uint32_t *ptr;
197
137
  grub_size_t cnt = 0;
198
 
  grub_uint8_t *ret;
199
138
 
200
139
  remaining = size;
201
140
  ptr = src;
216
155
      else
217
156
        cnt += 4;
218
157
    }
219
 
  cnt++;
 
158
  return cnt;
 
159
}
 
160
 
 
161
/* Convert UCS-4 to UTF-8.  */
 
162
char *
 
163
grub_ucs4_to_utf8_alloc (const grub_uint32_t *src, grub_size_t size)
 
164
{
 
165
  grub_uint8_t *ret;
 
166
  grub_size_t cnt = grub_get_num_of_utf8_bytes (src, size) + 1;
220
167
 
221
168
  ret = grub_malloc (cnt);
222
169
  if (!ret)
230
177
int
231
178
grub_is_valid_utf8 (const grub_uint8_t *src, grub_size_t srcsize)
232
179
{
 
180
  int count = 0;
233
181
  grub_uint32_t code = 0;
234
 
  int count = 0;
235
182
 
236
183
  while (srcsize)
237
184
    {
238
 
      grub_uint32_t c = *src++;
239
185
      if (srcsize != (grub_size_t)-1)
240
186
        srcsize--;
241
 
      if (count)
242
 
        {
243
 
          if ((c & 0xc0) != 0x80)
244
 
            {
245
 
              /* invalid */
246
 
              return 0;
247
 
            }
248
 
          else
249
 
            {
250
 
              code <<= 6;
251
 
              code |= (c & 0x3f);
252
 
              count--;
253
 
            }
254
 
        }
255
 
      else
256
 
        {
257
 
          if (c == 0)
258
 
            break;
259
 
 
260
 
          if ((c & 0x80) == 0x00)
261
 
            code = c;
262
 
          else if ((c & 0xe0) == 0xc0)
263
 
            {
264
 
              count = 1;
265
 
              code = c & 0x1f;
266
 
            }
267
 
          else if ((c & 0xf0) == 0xe0)
268
 
            {
269
 
              count = 2;
270
 
              code = c & 0x0f;
271
 
            }
272
 
          else if ((c & 0xf8) == 0xf0)
273
 
            {
274
 
              count = 3;
275
 
              code = c & 0x07;
276
 
            }
277
 
          else
278
 
            return 0;
279
 
        }
 
187
      if (!grub_utf8_process (*src++, &code, &count))
 
188
        return 0;
 
189
      if (count != 0)
 
190
        continue;
 
191
      if (code == 0)
 
192
        return 1;
 
193
      if (code > GRUB_UNICODE_LAST_VALID)
 
194
        return 0;
280
195
    }
281
196
 
282
197
  return 1;
283
198
}
284
199
 
285
 
int
 
200
grub_ssize_t
286
201
grub_utf8_to_ucs4_alloc (const char *msg, grub_uint32_t **unicode_msg,
287
 
                        grub_uint32_t **last_position)
 
202
                         grub_uint32_t **last_position)
288
203
{
289
204
  grub_size_t msg_len = grub_strlen (msg);
290
205
 
322
237
 
323
238
  while (srcsize && destsize)
324
239
    {
325
 
      grub_uint32_t c = *src++;
 
240
      int was_count = count;
326
241
      if (srcsize != (grub_size_t)-1)
327
242
        srcsize--;
328
 
      if (count)
329
 
        {
330
 
          if ((c & 0xc0) != 0x80)
331
 
            {
332
 
              /* invalid */
333
 
              code = '?';
334
 
              /* Character c may be valid, don't eat it.  */
335
 
              src--;
336
 
              if (srcsize != (grub_size_t)-1)
337
 
                srcsize++;
338
 
              count = 0;
339
 
            }
340
 
          else
341
 
            {
342
 
              code <<= 6;
343
 
              code |= (c & 0x3f);
344
 
              count--;
345
 
            }
346
 
        }
347
 
      else
348
 
        {
349
 
          if (c == 0)
350
 
            break;
351
 
 
352
 
          if ((c & 0x80) == 0x00)
353
 
            code = c;
354
 
          else if ((c & 0xe0) == 0xc0)
355
 
            {
356
 
              count = 1;
357
 
              code = c & 0x1f;
358
 
            }
359
 
          else if ((c & 0xf0) == 0xe0)
360
 
            {
361
 
              count = 2;
362
 
              code = c & 0x0f;
363
 
            }
364
 
          else if ((c & 0xf8) == 0xf0)
365
 
            {
366
 
              count = 3;
367
 
              code = c & 0x07;
368
 
            }
369
 
          else
370
 
            {
371
 
              /* invalid */
372
 
              code = '?';
373
 
              count = 0;
374
 
            }
375
 
        }
376
 
 
377
 
      if (count == 0)
378
 
        {
379
 
          *p++ = code;
380
 
          destsize--;
381
 
        }
 
243
      if (!grub_utf8_process (*src++, &code, &count))
 
244
        {
 
245
          code = '?';
 
246
          count = 0;
 
247
          /* Character c may be valid, don't eat it.  */
 
248
          if (was_count)
 
249
            src--;
 
250
        }
 
251
      if (count != 0)
 
252
        continue;
 
253
      if (code == 0)
 
254
        break;
 
255
      *p++ = code;
 
256
      destsize--;
382
257
    }
383
258
 
384
259
  if (srcend)
400
275
      grub_errno = GRUB_ERR_NONE;
401
276
      return;
402
277
    }
403
 
  for (cur = grub_unicode_compact; cur->end; cur++)
404
 
    for (i = cur->start; i <= cur->end
405
 
             && i < GRUB_UNICODE_MAX_CACHED_CHAR; i++)
 
278
  for (cur = grub_unicode_compact; cur->len; cur++)
 
279
    for (i = cur->start; i < cur->start + (unsigned) cur->len
 
280
           && i < GRUB_UNICODE_MAX_CACHED_CHAR; i++)
406
281
      join_types[i] = cur->join_type;
407
282
}
408
283
 
420
295
      grub_errno = GRUB_ERR_NONE;
421
296
      return;
422
297
    }
423
 
  for (cur = grub_unicode_compact; cur->end; cur++)
424
 
    for (i = cur->start; i <= cur->end
425
 
             && i < GRUB_UNICODE_MAX_CACHED_CHAR; i++)
 
298
  for (cur = grub_unicode_compact; cur->len; cur++)
 
299
    for (i = cur->start; i < cur->start + (unsigned) cur->len
 
300
           && i < GRUB_UNICODE_MAX_CACHED_CHAR; i++)
426
301
      if (cur->bidi_mirror)
427
302
        bidi_types[i] = cur->bidi_type | 0x80;
428
303
      else
440
315
  if (bidi_types && c < GRUB_UNICODE_MAX_CACHED_CHAR)
441
316
    return bidi_types[c] & 0x7f;
442
317
 
443
 
  for (cur = grub_unicode_compact; cur->end; cur++)
444
 
    if (cur->start <= c && c <= cur->end)
 
318
  for (cur = grub_unicode_compact; cur->len; cur++)
 
319
    if (cur->start <= c && c < cur->start + (unsigned) cur->len)
445
320
      return cur->bidi_type;
446
321
 
447
322
  return GRUB_BIDI_TYPE_L;
458
333
  if (join_types && c < GRUB_UNICODE_MAX_CACHED_CHAR)
459
334
    return join_types[c];
460
335
 
461
 
  for (cur = grub_unicode_compact; cur->end; cur++)
462
 
    if (cur->start <= c && c <= cur->end)
 
336
  for (cur = grub_unicode_compact; cur->len; cur++)
 
337
    if (cur->start <= c && c < cur->start + (unsigned) cur->len)
463
338
      return cur->join_type;
464
339
 
465
340
  return GRUB_JOIN_TYPE_NONJOINING;
476
351
  if (bidi_types && c < GRUB_UNICODE_MAX_CACHED_CHAR)
477
352
    return !!(bidi_types[c] & 0x80);
478
353
 
479
 
  for (cur = grub_unicode_compact; cur->end; cur++)
480
 
    if (cur->start <= c && c <= cur->end)
 
354
  for (cur = grub_unicode_compact; cur->len; cur++)
 
355
    if (cur->start <= c && c < cur->start + (unsigned) cur->len)
481
356
      return cur->bidi_mirror;
482
357
 
483
358
  return 0;
494
369
      unsigned i;
495
370
      comb_types = grub_zalloc (GRUB_UNICODE_MAX_CACHED_CHAR);
496
371
      if (comb_types)
497
 
        for (cur = grub_unicode_compact; cur->end; cur++)
498
 
          for (i = cur->start; i <= cur->end
 
372
        for (cur = grub_unicode_compact; cur->len; cur++)
 
373
          for (i = cur->start; i < cur->start + (unsigned) cur->len
499
374
                 && i < GRUB_UNICODE_MAX_CACHED_CHAR; i++)
500
375
            comb_types[i] = cur->comb_type;
501
376
      else
505
380
  if (comb_types && c < GRUB_UNICODE_MAX_CACHED_CHAR)
506
381
    return comb_types[c];
507
382
 
508
 
  for (cur = grub_unicode_compact; cur->end; cur++)
509
 
    if (cur->start <= c && c <= cur->end)
 
383
  for (cur = grub_unicode_compact; cur->len; cur++)
 
384
    if (cur->start <= c && c < cur->start + (unsigned) cur->len)
510
385
      return cur->comb_type;
511
386
 
512
387
  return GRUB_UNICODE_COMB_NONE;
553
428
 
554
429
  grub_memset (out, 0, sizeof (*out));
555
430
 
 
431
  if (inlen && grub_iscntrl (*in))
 
432
    {
 
433
      out->base = *in;
 
434
      out->variant = 0;
 
435
      out->attributes = 0;
 
436
      out->ncomb = 0;
 
437
      out->estimated_width = 1;
 
438
      out->combining = NULL;
 
439
      return 1;
 
440
    }
 
441
 
556
442
  for (ptr = in; ptr < in + inlen; ptr++)
557
443
    {
558
444
      /* Variation selectors >= 17 are outside of BMP and SMP. 
564
450
          if (haveout)
565
451
            out->variant = *ptr - GRUB_UNICODE_VARIATION_SELECTOR_1 + 1;
566
452
          continue;
567
 
 
568
453
        }
569
454
      if (*ptr >= GRUB_UNICODE_VARIATION_SELECTOR_17
570
455
          && *ptr <= GRUB_UNICODE_VARIATION_SELECTOR_256)
642
527
  {
643
528
    struct grub_unicode_glyph t;
644
529
    unsigned i, tl;
645
 
    for (i = 0; i <= (end - start) / 2; i++)
 
530
    for (i = 0; i < (end - start) / 2 + 1; i++)
646
531
      {
647
532
        t = visual[start + i];
648
533
        visual[start + i] = visual[end - i];
663
548
      if (getcharwidth && k != visual_len)
664
549
        line_width += last_width = getcharwidth (&visual[k]);
665
550
 
666
 
      if (k != visual_len && visual[k].base == ' ')
 
551
      if (k != visual_len && (visual[k].base == ' '
 
552
                              || visual[k].base == '\t'))
667
553
        {
668
554
          last_space = k;
669
555
          last_space_width = line_width;
699
585
          {
700
586
            unsigned j;   
701
587
            /* FIXME: can be optimized.  */
702
 
            for (j = max_level; j >= min_odd_level; j--)
 
588
            for (j = max_level; j > min_odd_level - 1; j--)
703
589
              {
704
 
                unsigned in = 0;
 
590
                unsigned in = line_start;
705
591
                unsigned i;
706
592
                for (i = line_start; i < k; i++)
707
593
                  {
768
654
          {
769
655
            int right_join = 0;
770
656
            signed i;
771
 
            for (i = k - 1; i >= (signed) line_start; i--)
 
657
            for (i = k - 1; i >= 0 && (unsigned) i + 1 > line_start;
 
658
                 i--)
772
659
              {
773
660
                enum grub_join_type join_type = get_join_type (visual[i].base);
774
661
                if (!(visual[i].attributes
939
826
            continue;
940
827
          }
941
828
 
 
829
        /* The tags: deprecated, never used.  */
 
830
        if (*lptr >= GRUB_UNICODE_TAG_START && *lptr <= GRUB_UNICODE_TAG_END)
 
831
          continue;
 
832
 
942
833
        p = grub_unicode_aglomerate_comb (lptr, logical + logical_len - lptr, 
943
834
                                          &visual[visual_len]);
944
835
        
1272
1163
 
1273
1164
  return in;
1274
1165
}
 
1166
 
 
1167
const grub_uint32_t *
 
1168
grub_unicode_get_comb_start (const grub_uint32_t *str, 
 
1169
                             const grub_uint32_t *cur)
 
1170
{
 
1171
  const grub_uint32_t *ptr;
 
1172
  for (ptr = cur; ptr >= str; ptr--)
 
1173
    {
 
1174
      if (*ptr >= GRUB_UNICODE_VARIATION_SELECTOR_1
 
1175
          && *ptr <= GRUB_UNICODE_VARIATION_SELECTOR_16)
 
1176
        continue;
 
1177
 
 
1178
      if (*ptr >= GRUB_UNICODE_VARIATION_SELECTOR_17
 
1179
          && *ptr <= GRUB_UNICODE_VARIATION_SELECTOR_256)
 
1180
        continue;
 
1181
        
 
1182
      enum grub_comb_type comb_type;
 
1183
      comb_type = grub_unicode_get_comb_type (*ptr);
 
1184
      if (comb_type)
 
1185
        continue;
 
1186
      return ptr;
 
1187
    }
 
1188
  return str;
 
1189
}
 
1190