Imported Upstream version 0.19.7
[platform/upstream/gettext.git] / gettext-tools / src / filter-quote.c
1 /* Convert ASCII quotations to Unicode quotations.
2    Copyright (C) 2014-2015 Free Software Foundation, Inc.
3    Written by Daiki Ueno <ueno@gnu.org>, 2014.
4
5    This program is free software: you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 3 of the License, or
8    (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
17
18 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21
22 /* Specification.  */
23 #include "filters.h"
24
25 #include "quote.h"
26 #include <stdbool.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include "xalloc.h"
30
31 #define BOLD_START "\x1b[1m"
32 #define BOLD_END "\x1b[0m"
33
34 struct result
35 {
36   char *output;
37   char *offset;
38   bool bold;
39 };
40
41 static void
42 convert_quote_callback (char quote, const char *quoted, size_t quoted_length,
43                         void *data)
44 {
45   struct result *result = data;
46
47   switch (quote)
48     {
49     case '\0':
50       memcpy (result->offset, quoted, quoted_length);
51       result->offset += quoted_length;
52       break;
53
54     case '"':
55       /* U+201C: LEFT DOUBLE QUOTATION MARK */
56       memcpy (result->offset, "\xe2\x80\x9c", 3);
57       result->offset += 3;
58       if (result->bold)
59         {
60           memcpy (result->offset, BOLD_START, 4);
61           result->offset += 4;
62         }
63       memcpy (result->offset, quoted, quoted_length);
64       result->offset += quoted_length;
65       if (result->bold)
66         {
67           memcpy (result->offset, BOLD_END, 4);
68           result->offset += 4;
69         }
70       /* U+201D: RIGHT DOUBLE QUOTATION MARK */
71       memcpy (result->offset, "\xe2\x80\x9d", 3);
72       result->offset += 3;
73       break;
74
75     case '\'':
76       /* U+2018: LEFT SINGLE QUOTATION MARK */
77       memcpy (result->offset, "\xe2\x80\x98", 3);
78       result->offset += 3;
79       if (result->bold)
80         {
81           memcpy (result->offset, BOLD_START, 4);
82           result->offset += 4;
83         }
84       memcpy (result->offset, quoted, quoted_length);
85       result->offset += quoted_length;
86       if (result->bold)
87         {
88           memcpy (result->offset, BOLD_END, 4);
89           result->offset += 4;
90         }
91       /* U+2019: RIGHT SINGLE QUOTATION MARK */
92       memcpy (result->offset, "\xe2\x80\x99", 3);
93       result->offset += 3;
94       break;
95     }
96 }
97
98 /* This is a direct translation of po/quot.sed and po/boldquot.sed.  */
99 static void
100 convert_ascii_quote_to_unicode (const char *input, size_t input_len,
101                                 char **output_p, size_t *output_len_p,
102                                 bool bold)
103 {
104   const char *p;
105   size_t quote_count;
106   struct result result;
107
108   /* Count the number of quotation characters.  */
109   quote_count = 0;
110   for (p = input; p < input + input_len; p++)
111     {
112       size_t len;
113
114       p = strpbrk (p, "`'\"");
115       if (!p)
116         break;
117
118       len = strspn (p, "`'\"");
119       quote_count += len;
120       p += len;
121     }
122
123   /* Large enough.  */
124   result.output = XNMALLOC (input_len - quote_count
125                             + (bold ? 7 : 3) * quote_count + 1,
126                             char);
127   result.offset = result.output;
128   result.bold = bold;
129
130   scan_quoted (input, input_len, convert_quote_callback, &result);
131
132   *output_p = result.output;
133   *output_len_p = result.offset - result.output;
134 }
135
136 void
137 ascii_quote_to_unicode (const char *input, size_t input_len,
138                         char **output_p, size_t *output_len_p)
139 {
140   convert_ascii_quote_to_unicode (input, input_len,
141                                   output_p, output_len_p,
142                                   false);
143 }
144
145 void
146 ascii_quote_to_unicode_bold (const char *input, size_t input_len,
147                              char **output_p, size_t *output_len_p)
148 {
149   convert_ascii_quote_to_unicode (input, input_len,
150                                   output_p, output_len_p,
151                                   true);
152 }