bfd/
[platform/upstream/binutils.git] / binutils / winduni.c
1 /* winduni.c -- unicode support for the windres program.
2    Copyright 1997, 1998, 2000, 2001, 2003, 2007
3    Free Software Foundation, Inc.
4    Written by Ian Lance Taylor, Cygnus Support.
5
6    This file is part of GNU Binutils.
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
21    02110-1301, USA.  */
22
23 /* This file contains unicode support routines for the windres
24    program.  Ideally, we would have generic unicode support which
25    would work on all systems.  However, we don't.  Instead, on a
26    Windows host, we are prepared to call some Windows routines.  This
27    means that we will generate different output on Windows and Unix
28    hosts, but that seems better than not really supporting unicode at
29    all.  */
30
31 #include "sysdep.h"
32 #include "bfd.h"
33 #include "winduni.h"
34 #include "safe-ctype.h"
35
36 #ifdef _WIN32
37 #include <windows.h>
38 #endif
39
40 /* Convert an ASCII string to a unicode string.  We just copy it,
41    expanding chars to shorts, rather than doing something intelligent.  */
42
43 void
44 unicode_from_ascii (int *length, unichar **unicode, const char *ascii)
45 {
46   int len;
47 #ifndef _WIN32
48   const char *s;
49   unsigned short *w;
50
51   len = strlen (ascii);
52   *unicode = ((unichar *) res_alloc ((len + 1) * sizeof (unichar)));
53   for (s = ascii, w = *unicode; *s != '\0'; s++, w++)
54     *w = *s & 0xff;
55   *w = 0;
56 #else
57   /* We use  MultiByteToWideChar rather than strlen to get the unicode
58      string length to allow multibyte "ascii" chars. The value returned
59      by this function includes the trailing '\0'.  */
60   len = MultiByteToWideChar (CP_ACP, 0, ascii, -1, NULL, 0);
61   if (len)
62     {
63       *unicode = ((unichar *) res_alloc (len * sizeof (unichar)));
64       MultiByteToWideChar (CP_ACP, 0, ascii, -1, *unicode, len);
65     }
66   /* Discount the trailing '/0'.  If MultiByteToWideChar failed,
67      this will set *length to -1.  */
68   len--;
69 #endif
70
71   if (length != NULL)
72     *length = len;
73 }
74
75 /* Print the unicode string UNICODE to the file E.  LENGTH is the
76    number of characters to print, or -1 if we should print until the
77    end of the string.  FIXME: On a Windows host, we should be calling
78    some Windows function, probably WideCharToMultiByte.  */
79
80 void
81 unicode_print (FILE *e, const unichar *unicode, int length)
82 {
83   while (1)
84     {
85       unichar ch;
86
87       if (length == 0)
88         return;
89       if (length > 0)
90         --length;
91
92       ch = *unicode;
93
94       if (ch == 0 && length < 0)
95         return;
96
97       ++unicode;
98
99       if ((ch & 0x7f) == ch)
100         {
101           if (ch == '\\')
102             fputs ("\\", e);
103           else if (ISPRINT (ch))
104             putc (ch, e);
105           else
106             {
107               switch (ch)
108                 {
109                 case ESCAPE_A:
110                   fputs ("\\a", e);
111                   break;
112
113                 case ESCAPE_B:
114                   fputs ("\\b", e);
115                   break;
116
117                 case ESCAPE_F:
118                   fputs ("\\f", e);
119                   break;
120
121                 case ESCAPE_N:
122                   fputs ("\\n", e);
123                   break;
124
125                 case ESCAPE_R:
126                   fputs ("\\r", e);
127                   break;
128
129                 case ESCAPE_T:
130                   fputs ("\\t", e);
131                   break;
132
133                 case ESCAPE_V:
134                   fputs ("\\v", e);
135                   break;
136
137                 default:
138                   fprintf (e, "\\%03o", (unsigned int) ch);
139                   break;
140                 }
141             }
142         }
143       else if ((ch & 0xff) == ch)
144         fprintf (e, "\\%03o", (unsigned int) ch);
145       else
146         fprintf (e, "\\x%x", (unsigned int) ch);
147     }
148 }