xref: /aosp_15_r20/external/harfbuzz_ng/util/text-options.hh (revision 2d1272b857b1f7575e6e246373e1cb218663db8a)
1*2d1272b8SAndroid Build Coastguard Worker /*
2*2d1272b8SAndroid Build Coastguard Worker  * Copyright © 2011  Google, Inc.
3*2d1272b8SAndroid Build Coastguard Worker  *
4*2d1272b8SAndroid Build Coastguard Worker  *  This is part of HarfBuzz, a text shaping library.
5*2d1272b8SAndroid Build Coastguard Worker  *
6*2d1272b8SAndroid Build Coastguard Worker  * Permission is hereby granted, without written agreement and without
7*2d1272b8SAndroid Build Coastguard Worker  * license or royalty fees, to use, copy, modify, and distribute this
8*2d1272b8SAndroid Build Coastguard Worker  * software and its documentation for any purpose, provided that the
9*2d1272b8SAndroid Build Coastguard Worker  * above copyright notice and the following two paragraphs appear in
10*2d1272b8SAndroid Build Coastguard Worker  * all copies of this software.
11*2d1272b8SAndroid Build Coastguard Worker  *
12*2d1272b8SAndroid Build Coastguard Worker  * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
13*2d1272b8SAndroid Build Coastguard Worker  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
14*2d1272b8SAndroid Build Coastguard Worker  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
15*2d1272b8SAndroid Build Coastguard Worker  * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
16*2d1272b8SAndroid Build Coastguard Worker  * DAMAGE.
17*2d1272b8SAndroid Build Coastguard Worker  *
18*2d1272b8SAndroid Build Coastguard Worker  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
19*2d1272b8SAndroid Build Coastguard Worker  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20*2d1272b8SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
21*2d1272b8SAndroid Build Coastguard Worker  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
22*2d1272b8SAndroid Build Coastguard Worker  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
23*2d1272b8SAndroid Build Coastguard Worker  *
24*2d1272b8SAndroid Build Coastguard Worker  * Google Author(s): Behdad Esfahbod
25*2d1272b8SAndroid Build Coastguard Worker  */
26*2d1272b8SAndroid Build Coastguard Worker 
27*2d1272b8SAndroid Build Coastguard Worker #ifndef TEXT_OPTIONS_HH
28*2d1272b8SAndroid Build Coastguard Worker #define TEXT_OPTIONS_HH
29*2d1272b8SAndroid Build Coastguard Worker 
30*2d1272b8SAndroid Build Coastguard Worker #include "options.hh"
31*2d1272b8SAndroid Build Coastguard Worker 
32*2d1272b8SAndroid Build Coastguard Worker struct text_options_t
33*2d1272b8SAndroid Build Coastguard Worker {
text_options_ttext_options_t34*2d1272b8SAndroid Build Coastguard Worker   text_options_t ()
35*2d1272b8SAndroid Build Coastguard Worker   : gs (g_string_new (nullptr))
36*2d1272b8SAndroid Build Coastguard Worker   {}
~text_options_ttext_options_t37*2d1272b8SAndroid Build Coastguard Worker   ~text_options_t ()
38*2d1272b8SAndroid Build Coastguard Worker   {
39*2d1272b8SAndroid Build Coastguard Worker     g_free (text);
40*2d1272b8SAndroid Build Coastguard Worker     g_free (text_file);
41*2d1272b8SAndroid Build Coastguard Worker     if (gs)
42*2d1272b8SAndroid Build Coastguard Worker       g_string_free (gs, true);
43*2d1272b8SAndroid Build Coastguard Worker     if (in_fp && in_fp != stdin)
44*2d1272b8SAndroid Build Coastguard Worker       fclose (in_fp);
45*2d1272b8SAndroid Build Coastguard Worker   }
46*2d1272b8SAndroid Build Coastguard Worker 
47*2d1272b8SAndroid Build Coastguard Worker   void add_options (option_parser_t *parser);
48*2d1272b8SAndroid Build Coastguard Worker 
post_parsetext_options_t49*2d1272b8SAndroid Build Coastguard Worker   void post_parse (GError **error G_GNUC_UNUSED)
50*2d1272b8SAndroid Build Coastguard Worker   {
51*2d1272b8SAndroid Build Coastguard Worker     if (!text && !text_file)
52*2d1272b8SAndroid Build Coastguard Worker       text_file = g_strdup ("-");
53*2d1272b8SAndroid Build Coastguard Worker 
54*2d1272b8SAndroid Build Coastguard Worker     if (text && text_file)
55*2d1272b8SAndroid Build Coastguard Worker     {
56*2d1272b8SAndroid Build Coastguard Worker       g_set_error (error,
57*2d1272b8SAndroid Build Coastguard Worker 		   G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
58*2d1272b8SAndroid Build Coastguard Worker 		   "Only one of text and text-file can be set");
59*2d1272b8SAndroid Build Coastguard Worker       return;
60*2d1272b8SAndroid Build Coastguard Worker     }
61*2d1272b8SAndroid Build Coastguard Worker 
62*2d1272b8SAndroid Build Coastguard Worker     if (text_file)
63*2d1272b8SAndroid Build Coastguard Worker     {
64*2d1272b8SAndroid Build Coastguard Worker       if (0 != strcmp (text_file, "-"))
65*2d1272b8SAndroid Build Coastguard Worker 	in_fp = fopen (text_file, "r");
66*2d1272b8SAndroid Build Coastguard Worker       else
67*2d1272b8SAndroid Build Coastguard Worker 	in_fp = stdin;
68*2d1272b8SAndroid Build Coastguard Worker 
69*2d1272b8SAndroid Build Coastguard Worker       if (!in_fp)
70*2d1272b8SAndroid Build Coastguard Worker 	g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_FAILED,
71*2d1272b8SAndroid Build Coastguard Worker 		     "Failed opening text file `%s': %s",
72*2d1272b8SAndroid Build Coastguard Worker 		     text_file, strerror (errno));
73*2d1272b8SAndroid Build Coastguard Worker     }
74*2d1272b8SAndroid Build Coastguard Worker   }
75*2d1272b8SAndroid Build Coastguard Worker 
76*2d1272b8SAndroid Build Coastguard Worker   const char *get_line (unsigned int *len);
77*2d1272b8SAndroid Build Coastguard Worker 
78*2d1272b8SAndroid Build Coastguard Worker   int text_len = -1;
79*2d1272b8SAndroid Build Coastguard Worker   char *text = nullptr;
80*2d1272b8SAndroid Build Coastguard Worker   char *text_file = nullptr;
81*2d1272b8SAndroid Build Coastguard Worker 
82*2d1272b8SAndroid Build Coastguard Worker   private:
83*2d1272b8SAndroid Build Coastguard Worker   FILE *in_fp = nullptr;
84*2d1272b8SAndroid Build Coastguard Worker   GString *gs = nullptr;
85*2d1272b8SAndroid Build Coastguard Worker   char *line = nullptr;
86*2d1272b8SAndroid Build Coastguard Worker   unsigned line_len = UINT_MAX;
87*2d1272b8SAndroid Build Coastguard Worker   hb_bool_t single_par = false;
88*2d1272b8SAndroid Build Coastguard Worker };
89*2d1272b8SAndroid Build Coastguard Worker 
90*2d1272b8SAndroid Build Coastguard Worker struct shape_text_options_t : text_options_t
91*2d1272b8SAndroid Build Coastguard Worker {
~shape_text_options_tshape_text_options_t92*2d1272b8SAndroid Build Coastguard Worker   ~shape_text_options_t ()
93*2d1272b8SAndroid Build Coastguard Worker   {
94*2d1272b8SAndroid Build Coastguard Worker     g_free (text_before);
95*2d1272b8SAndroid Build Coastguard Worker     g_free (text_after);
96*2d1272b8SAndroid Build Coastguard Worker   }
97*2d1272b8SAndroid Build Coastguard Worker 
98*2d1272b8SAndroid Build Coastguard Worker   void add_options (option_parser_t *parser);
99*2d1272b8SAndroid Build Coastguard Worker 
100*2d1272b8SAndroid Build Coastguard Worker   char *text_before = nullptr;
101*2d1272b8SAndroid Build Coastguard Worker   char *text_after = nullptr;
102*2d1272b8SAndroid Build Coastguard Worker };
103*2d1272b8SAndroid Build Coastguard Worker 
104*2d1272b8SAndroid Build Coastguard Worker 
105*2d1272b8SAndroid Build Coastguard Worker static gboolean
parse_text(const char * name G_GNUC_UNUSED,const char * arg,gpointer data,GError ** error G_GNUC_UNUSED)106*2d1272b8SAndroid Build Coastguard Worker parse_text (const char *name G_GNUC_UNUSED,
107*2d1272b8SAndroid Build Coastguard Worker 	    const char *arg,
108*2d1272b8SAndroid Build Coastguard Worker 	    gpointer    data,
109*2d1272b8SAndroid Build Coastguard Worker 	    GError    **error G_GNUC_UNUSED)
110*2d1272b8SAndroid Build Coastguard Worker {
111*2d1272b8SAndroid Build Coastguard Worker   text_options_t *text_opts = (text_options_t *) data;
112*2d1272b8SAndroid Build Coastguard Worker 
113*2d1272b8SAndroid Build Coastguard Worker   if (text_opts->text)
114*2d1272b8SAndroid Build Coastguard Worker   {
115*2d1272b8SAndroid Build Coastguard Worker     g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
116*2d1272b8SAndroid Build Coastguard Worker 		 "Either --text or --unicodes can be provided but not both");
117*2d1272b8SAndroid Build Coastguard Worker     return false;
118*2d1272b8SAndroid Build Coastguard Worker   }
119*2d1272b8SAndroid Build Coastguard Worker 
120*2d1272b8SAndroid Build Coastguard Worker   text_opts->text_len = -1;
121*2d1272b8SAndroid Build Coastguard Worker   text_opts->text = g_strdup (arg);
122*2d1272b8SAndroid Build Coastguard Worker   return true;
123*2d1272b8SAndroid Build Coastguard Worker }
124*2d1272b8SAndroid Build Coastguard Worker 
125*2d1272b8SAndroid Build Coastguard Worker static bool
encode_unicodes(const char * unicodes,GString * gs,GError ** error)126*2d1272b8SAndroid Build Coastguard Worker encode_unicodes (const char *unicodes,
127*2d1272b8SAndroid Build Coastguard Worker 		 GString    *gs,
128*2d1272b8SAndroid Build Coastguard Worker 		 GError    **error)
129*2d1272b8SAndroid Build Coastguard Worker {
130*2d1272b8SAndroid Build Coastguard Worker #define DELIMITERS "<+-|>{},;&#\\xXuUnNiI\n\t\v\f\r "
131*2d1272b8SAndroid Build Coastguard Worker 
132*2d1272b8SAndroid Build Coastguard Worker   char *s = (char *) unicodes;
133*2d1272b8SAndroid Build Coastguard Worker   char *p;
134*2d1272b8SAndroid Build Coastguard Worker 
135*2d1272b8SAndroid Build Coastguard Worker   while (s && *s)
136*2d1272b8SAndroid Build Coastguard Worker   {
137*2d1272b8SAndroid Build Coastguard Worker     while (*s && strchr (DELIMITERS, *s))
138*2d1272b8SAndroid Build Coastguard Worker       s++;
139*2d1272b8SAndroid Build Coastguard Worker     if (!*s)
140*2d1272b8SAndroid Build Coastguard Worker       break;
141*2d1272b8SAndroid Build Coastguard Worker 
142*2d1272b8SAndroid Build Coastguard Worker     errno = 0;
143*2d1272b8SAndroid Build Coastguard Worker     hb_codepoint_t u = strtoul (s, &p, 16);
144*2d1272b8SAndroid Build Coastguard Worker     if (errno || s == p)
145*2d1272b8SAndroid Build Coastguard Worker     {
146*2d1272b8SAndroid Build Coastguard Worker       g_string_free (gs, TRUE);
147*2d1272b8SAndroid Build Coastguard Worker       g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
148*2d1272b8SAndroid Build Coastguard Worker 		   "Failed parsing Unicode value at: '%s'", s);
149*2d1272b8SAndroid Build Coastguard Worker       return false;
150*2d1272b8SAndroid Build Coastguard Worker     }
151*2d1272b8SAndroid Build Coastguard Worker 
152*2d1272b8SAndroid Build Coastguard Worker     g_string_append_unichar (gs, u);
153*2d1272b8SAndroid Build Coastguard Worker 
154*2d1272b8SAndroid Build Coastguard Worker     s = p;
155*2d1272b8SAndroid Build Coastguard Worker   }
156*2d1272b8SAndroid Build Coastguard Worker 
157*2d1272b8SAndroid Build Coastguard Worker #undef DELIMITERS
158*2d1272b8SAndroid Build Coastguard Worker 
159*2d1272b8SAndroid Build Coastguard Worker   return true;
160*2d1272b8SAndroid Build Coastguard Worker }
161*2d1272b8SAndroid Build Coastguard Worker 
162*2d1272b8SAndroid Build Coastguard Worker static gboolean
parse_unicodes(const char * name G_GNUC_UNUSED,const char * arg,gpointer data,GError ** error G_GNUC_UNUSED)163*2d1272b8SAndroid Build Coastguard Worker parse_unicodes (const char *name G_GNUC_UNUSED,
164*2d1272b8SAndroid Build Coastguard Worker 		const char *arg,
165*2d1272b8SAndroid Build Coastguard Worker 		gpointer    data,
166*2d1272b8SAndroid Build Coastguard Worker 		GError    **error G_GNUC_UNUSED)
167*2d1272b8SAndroid Build Coastguard Worker {
168*2d1272b8SAndroid Build Coastguard Worker   text_options_t *text_opts = (text_options_t *) data;
169*2d1272b8SAndroid Build Coastguard Worker 
170*2d1272b8SAndroid Build Coastguard Worker   if (text_opts->text)
171*2d1272b8SAndroid Build Coastguard Worker   {
172*2d1272b8SAndroid Build Coastguard Worker     g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
173*2d1272b8SAndroid Build Coastguard Worker 		 "Either --text or --unicodes can be provided but not both");
174*2d1272b8SAndroid Build Coastguard Worker     return false;
175*2d1272b8SAndroid Build Coastguard Worker   }
176*2d1272b8SAndroid Build Coastguard Worker 
177*2d1272b8SAndroid Build Coastguard Worker   GString *gs = g_string_new (nullptr);
178*2d1272b8SAndroid Build Coastguard Worker   if (0 == strcmp (arg, "*"))
179*2d1272b8SAndroid Build Coastguard Worker     g_string_append_c (gs, '*');
180*2d1272b8SAndroid Build Coastguard Worker   else
181*2d1272b8SAndroid Build Coastguard Worker     if (!encode_unicodes (arg, gs, error))
182*2d1272b8SAndroid Build Coastguard Worker       return false;
183*2d1272b8SAndroid Build Coastguard Worker 
184*2d1272b8SAndroid Build Coastguard Worker   text_opts->text_len = gs->len;
185*2d1272b8SAndroid Build Coastguard Worker   text_opts->text = g_string_free (gs, FALSE);
186*2d1272b8SAndroid Build Coastguard Worker   return true;
187*2d1272b8SAndroid Build Coastguard Worker }
188*2d1272b8SAndroid Build Coastguard Worker 
189*2d1272b8SAndroid Build Coastguard Worker static gboolean
parse_text_before(const char * name G_GNUC_UNUSED,const char * arg,gpointer data,GError ** error)190*2d1272b8SAndroid Build Coastguard Worker parse_text_before (const char *name G_GNUC_UNUSED,
191*2d1272b8SAndroid Build Coastguard Worker 		   const char *arg,
192*2d1272b8SAndroid Build Coastguard Worker 		   gpointer    data,
193*2d1272b8SAndroid Build Coastguard Worker 		   GError    **error)
194*2d1272b8SAndroid Build Coastguard Worker {
195*2d1272b8SAndroid Build Coastguard Worker   auto *opts = (shape_text_options_t *) data;
196*2d1272b8SAndroid Build Coastguard Worker 
197*2d1272b8SAndroid Build Coastguard Worker   if (opts->text_before)
198*2d1272b8SAndroid Build Coastguard Worker   {
199*2d1272b8SAndroid Build Coastguard Worker     g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
200*2d1272b8SAndroid Build Coastguard Worker 		 "Either --text-before or --unicodes-before can be provided but not both");
201*2d1272b8SAndroid Build Coastguard Worker     return false;
202*2d1272b8SAndroid Build Coastguard Worker   }
203*2d1272b8SAndroid Build Coastguard Worker 
204*2d1272b8SAndroid Build Coastguard Worker   opts->text_before = g_strdup (arg);
205*2d1272b8SAndroid Build Coastguard Worker   fprintf(stderr, "%s\n", opts->text_before);
206*2d1272b8SAndroid Build Coastguard Worker   return true;
207*2d1272b8SAndroid Build Coastguard Worker }
208*2d1272b8SAndroid Build Coastguard Worker 
209*2d1272b8SAndroid Build Coastguard Worker static gboolean
parse_unicodes_before(const char * name G_GNUC_UNUSED,const char * arg,gpointer data,GError ** error)210*2d1272b8SAndroid Build Coastguard Worker parse_unicodes_before (const char *name G_GNUC_UNUSED,
211*2d1272b8SAndroid Build Coastguard Worker 		       const char *arg,
212*2d1272b8SAndroid Build Coastguard Worker 		       gpointer    data,
213*2d1272b8SAndroid Build Coastguard Worker 		       GError    **error)
214*2d1272b8SAndroid Build Coastguard Worker {
215*2d1272b8SAndroid Build Coastguard Worker   auto *opts = (shape_text_options_t *) data;
216*2d1272b8SAndroid Build Coastguard Worker 
217*2d1272b8SAndroid Build Coastguard Worker   if (opts->text_before)
218*2d1272b8SAndroid Build Coastguard Worker   {
219*2d1272b8SAndroid Build Coastguard Worker     g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
220*2d1272b8SAndroid Build Coastguard Worker 		 "Either --text-before or --unicodes-before can be provided but not both");
221*2d1272b8SAndroid Build Coastguard Worker     return false;
222*2d1272b8SAndroid Build Coastguard Worker   }
223*2d1272b8SAndroid Build Coastguard Worker 
224*2d1272b8SAndroid Build Coastguard Worker   GString *gs = g_string_new (nullptr);
225*2d1272b8SAndroid Build Coastguard Worker   if (!encode_unicodes (arg, gs, error))
226*2d1272b8SAndroid Build Coastguard Worker     return false;
227*2d1272b8SAndroid Build Coastguard Worker 
228*2d1272b8SAndroid Build Coastguard Worker   opts->text_before = g_string_free (gs, FALSE);
229*2d1272b8SAndroid Build Coastguard Worker   return true;
230*2d1272b8SAndroid Build Coastguard Worker }
231*2d1272b8SAndroid Build Coastguard Worker 
232*2d1272b8SAndroid Build Coastguard Worker static gboolean
parse_text_after(const char * name G_GNUC_UNUSED,const char * arg,gpointer data,GError ** error)233*2d1272b8SAndroid Build Coastguard Worker parse_text_after (const char *name G_GNUC_UNUSED,
234*2d1272b8SAndroid Build Coastguard Worker 		  const char *arg,
235*2d1272b8SAndroid Build Coastguard Worker 		  gpointer    data,
236*2d1272b8SAndroid Build Coastguard Worker 		  GError    **error)
237*2d1272b8SAndroid Build Coastguard Worker {
238*2d1272b8SAndroid Build Coastguard Worker   auto *opts = (shape_text_options_t *) data;
239*2d1272b8SAndroid Build Coastguard Worker 
240*2d1272b8SAndroid Build Coastguard Worker   if (opts->text_after)
241*2d1272b8SAndroid Build Coastguard Worker   {
242*2d1272b8SAndroid Build Coastguard Worker     g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
243*2d1272b8SAndroid Build Coastguard Worker 		 "Either --text-after or --unicodes-after can be provided but not both");
244*2d1272b8SAndroid Build Coastguard Worker     return false;
245*2d1272b8SAndroid Build Coastguard Worker   }
246*2d1272b8SAndroid Build Coastguard Worker 
247*2d1272b8SAndroid Build Coastguard Worker   opts->text_after = g_strdup (arg);
248*2d1272b8SAndroid Build Coastguard Worker   return true;
249*2d1272b8SAndroid Build Coastguard Worker }
250*2d1272b8SAndroid Build Coastguard Worker 
251*2d1272b8SAndroid Build Coastguard Worker static gboolean
parse_unicodes_after(const char * name G_GNUC_UNUSED,const char * arg,gpointer data,GError ** error)252*2d1272b8SAndroid Build Coastguard Worker parse_unicodes_after (const char *name G_GNUC_UNUSED,
253*2d1272b8SAndroid Build Coastguard Worker 		      const char *arg,
254*2d1272b8SAndroid Build Coastguard Worker 		      gpointer    data,
255*2d1272b8SAndroid Build Coastguard Worker 		      GError    **error)
256*2d1272b8SAndroid Build Coastguard Worker {
257*2d1272b8SAndroid Build Coastguard Worker   auto *opts = (shape_text_options_t *) data;
258*2d1272b8SAndroid Build Coastguard Worker 
259*2d1272b8SAndroid Build Coastguard Worker   if (opts->text_after)
260*2d1272b8SAndroid Build Coastguard Worker   {
261*2d1272b8SAndroid Build Coastguard Worker     g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
262*2d1272b8SAndroid Build Coastguard Worker 		 "Either --text-after or --unicodes-after can be provided but not both");
263*2d1272b8SAndroid Build Coastguard Worker     return false;
264*2d1272b8SAndroid Build Coastguard Worker   }
265*2d1272b8SAndroid Build Coastguard Worker 
266*2d1272b8SAndroid Build Coastguard Worker   GString *gs = g_string_new (nullptr);
267*2d1272b8SAndroid Build Coastguard Worker   if (!encode_unicodes (arg, gs, error))
268*2d1272b8SAndroid Build Coastguard Worker     return false;
269*2d1272b8SAndroid Build Coastguard Worker 
270*2d1272b8SAndroid Build Coastguard Worker   opts->text_after = g_string_free (gs, FALSE);
271*2d1272b8SAndroid Build Coastguard Worker   return true;
272*2d1272b8SAndroid Build Coastguard Worker }
273*2d1272b8SAndroid Build Coastguard Worker 
274*2d1272b8SAndroid Build Coastguard Worker const char *
get_line(unsigned int * len)275*2d1272b8SAndroid Build Coastguard Worker text_options_t::get_line (unsigned int *len)
276*2d1272b8SAndroid Build Coastguard Worker {
277*2d1272b8SAndroid Build Coastguard Worker   if (text)
278*2d1272b8SAndroid Build Coastguard Worker   {
279*2d1272b8SAndroid Build Coastguard Worker     if (!line)
280*2d1272b8SAndroid Build Coastguard Worker     {
281*2d1272b8SAndroid Build Coastguard Worker       line = text;
282*2d1272b8SAndroid Build Coastguard Worker       line_len = text_len;
283*2d1272b8SAndroid Build Coastguard Worker     }
284*2d1272b8SAndroid Build Coastguard Worker     if (line_len == UINT_MAX)
285*2d1272b8SAndroid Build Coastguard Worker       line_len = strlen (line);
286*2d1272b8SAndroid Build Coastguard Worker 
287*2d1272b8SAndroid Build Coastguard Worker     if (!line_len)
288*2d1272b8SAndroid Build Coastguard Worker     {
289*2d1272b8SAndroid Build Coastguard Worker       *len = 0;
290*2d1272b8SAndroid Build Coastguard Worker       return nullptr;
291*2d1272b8SAndroid Build Coastguard Worker     }
292*2d1272b8SAndroid Build Coastguard Worker 
293*2d1272b8SAndroid Build Coastguard Worker     const char *ret = line;
294*2d1272b8SAndroid Build Coastguard Worker     const char *p = single_par ? nullptr : (const char *) memchr (line, '\n', line_len);
295*2d1272b8SAndroid Build Coastguard Worker     unsigned int ret_len;
296*2d1272b8SAndroid Build Coastguard Worker     if (!p)
297*2d1272b8SAndroid Build Coastguard Worker     {
298*2d1272b8SAndroid Build Coastguard Worker       ret_len = line_len;
299*2d1272b8SAndroid Build Coastguard Worker       line += ret_len;
300*2d1272b8SAndroid Build Coastguard Worker       line_len = 0;
301*2d1272b8SAndroid Build Coastguard Worker     }
302*2d1272b8SAndroid Build Coastguard Worker     else
303*2d1272b8SAndroid Build Coastguard Worker     {
304*2d1272b8SAndroid Build Coastguard Worker       ret_len = p - ret;
305*2d1272b8SAndroid Build Coastguard Worker       line += ret_len + 1;
306*2d1272b8SAndroid Build Coastguard Worker       line_len -= ret_len + 1;
307*2d1272b8SAndroid Build Coastguard Worker     }
308*2d1272b8SAndroid Build Coastguard Worker 
309*2d1272b8SAndroid Build Coastguard Worker     *len = ret_len;
310*2d1272b8SAndroid Build Coastguard Worker     return ret;
311*2d1272b8SAndroid Build Coastguard Worker   }
312*2d1272b8SAndroid Build Coastguard Worker 
313*2d1272b8SAndroid Build Coastguard Worker   g_string_set_size (gs, 0);
314*2d1272b8SAndroid Build Coastguard Worker   char buf[BUFSIZ];
315*2d1272b8SAndroid Build Coastguard Worker   while (fgets (buf, sizeof (buf), in_fp))
316*2d1272b8SAndroid Build Coastguard Worker   {
317*2d1272b8SAndroid Build Coastguard Worker     unsigned bytes = strlen (buf);
318*2d1272b8SAndroid Build Coastguard Worker     if (!single_par && bytes && buf[bytes - 1] == '\n')
319*2d1272b8SAndroid Build Coastguard Worker     {
320*2d1272b8SAndroid Build Coastguard Worker       bytes--;
321*2d1272b8SAndroid Build Coastguard Worker       g_string_append_len (gs, buf, bytes);
322*2d1272b8SAndroid Build Coastguard Worker       break;
323*2d1272b8SAndroid Build Coastguard Worker     }
324*2d1272b8SAndroid Build Coastguard Worker     g_string_append_len (gs, buf, bytes);
325*2d1272b8SAndroid Build Coastguard Worker   }
326*2d1272b8SAndroid Build Coastguard Worker   if (ferror (in_fp))
327*2d1272b8SAndroid Build Coastguard Worker     fail (false, "Failed reading text: %s", strerror (errno));
328*2d1272b8SAndroid Build Coastguard Worker   *len = gs->len;
329*2d1272b8SAndroid Build Coastguard Worker   return !*len && feof (in_fp) ? nullptr : gs->str;
330*2d1272b8SAndroid Build Coastguard Worker }
331*2d1272b8SAndroid Build Coastguard Worker 
332*2d1272b8SAndroid Build Coastguard Worker void
add_options(option_parser_t * parser)333*2d1272b8SAndroid Build Coastguard Worker text_options_t::add_options (option_parser_t *parser)
334*2d1272b8SAndroid Build Coastguard Worker {
335*2d1272b8SAndroid Build Coastguard Worker   GOptionEntry entries[] =
336*2d1272b8SAndroid Build Coastguard Worker   {
337*2d1272b8SAndroid Build Coastguard Worker     {"text",		0, 0, G_OPTION_ARG_CALLBACK,	(gpointer) &parse_text,		"Set input text",			"string"},
338*2d1272b8SAndroid Build Coastguard Worker     {"text-file",	0, 0, G_OPTION_ARG_STRING,	&this->text_file,		"Set input text file-name",		"filename"},
339*2d1272b8SAndroid Build Coastguard Worker     {"unicodes",      'u', 0, G_OPTION_ARG_CALLBACK,	(gpointer) &parse_unicodes,	"Set input Unicode codepoints",		"list of hex numbers"},
340*2d1272b8SAndroid Build Coastguard Worker     {"single-par",	0, 0, G_OPTION_ARG_NONE,	&this->single_par,		"Treat text as single paragraph",	nullptr},
341*2d1272b8SAndroid Build Coastguard Worker     {nullptr}
342*2d1272b8SAndroid Build Coastguard Worker   };
343*2d1272b8SAndroid Build Coastguard Worker   parser->add_group (entries,
344*2d1272b8SAndroid Build Coastguard Worker 		     "text",
345*2d1272b8SAndroid Build Coastguard Worker 		     "Text options:\n\nIf no text is provided, standard input is used for input.\n",
346*2d1272b8SAndroid Build Coastguard Worker 		     "Options for the input text",
347*2d1272b8SAndroid Build Coastguard Worker 		     this);
348*2d1272b8SAndroid Build Coastguard Worker }
349*2d1272b8SAndroid Build Coastguard Worker 
350*2d1272b8SAndroid Build Coastguard Worker void
add_options(option_parser_t * parser)351*2d1272b8SAndroid Build Coastguard Worker shape_text_options_t::add_options (option_parser_t *parser)
352*2d1272b8SAndroid Build Coastguard Worker {
353*2d1272b8SAndroid Build Coastguard Worker   text_options_t::add_options (parser);
354*2d1272b8SAndroid Build Coastguard Worker 
355*2d1272b8SAndroid Build Coastguard Worker   GOptionEntry entries[] =
356*2d1272b8SAndroid Build Coastguard Worker   {
357*2d1272b8SAndroid Build Coastguard Worker     {"text-before",	0, 0, G_OPTION_ARG_CALLBACK,	(gpointer) &parse_text_before,		"Set text context before each line",	"string"},
358*2d1272b8SAndroid Build Coastguard Worker     {"text-after",	0, 0, G_OPTION_ARG_CALLBACK,	(gpointer) &parse_text_after,		"Set text context after each line",	"string"},
359*2d1272b8SAndroid Build Coastguard Worker     {"unicodes-before",	0, 0, G_OPTION_ARG_CALLBACK,	(gpointer) &parse_unicodes_before,	"Set Unicode codepoints context before each line",	"list of hex numbers"},
360*2d1272b8SAndroid Build Coastguard Worker     {"unicodes-after",	0, 0, G_OPTION_ARG_CALLBACK,	(gpointer) &parse_unicodes_after,	"Set Unicode codepoints context after each line",	"list of hex numbers"},
361*2d1272b8SAndroid Build Coastguard Worker     {nullptr}
362*2d1272b8SAndroid Build Coastguard Worker   };
363*2d1272b8SAndroid Build Coastguard Worker   parser->add_group (entries,
364*2d1272b8SAndroid Build Coastguard Worker 		     "text-context",
365*2d1272b8SAndroid Build Coastguard Worker 		     "Textual context options:",
366*2d1272b8SAndroid Build Coastguard Worker 		     "Options for the input context text",
367*2d1272b8SAndroid Build Coastguard Worker 		     this);
368*2d1272b8SAndroid Build Coastguard Worker }
369*2d1272b8SAndroid Build Coastguard Worker 
370*2d1272b8SAndroid Build Coastguard Worker #endif
371