Imported Upstream version 0.19.7
[platform/upstream/gettext.git] / gettext-tools / src / x-desktop.c
1 /* xgettext Desktop Entry backend.
2    Copyright (C) 2014-2015 Free Software Foundation, Inc.
3
4    This file was written by Daiki Ueno <ueno@gnu.org>, 2014.
5
6    This program is free software: you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
18
19 #ifdef HAVE_CONFIG_H
20 # include "config.h"
21 #endif
22
23 /* Specification.  */
24 #include "x-desktop.h"
25
26 #include <errno.h>
27 #include <stdbool.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31
32 #include "message.h"
33 #include "xgettext.h"
34 #include "error.h"
35 #include "error-progname.h"
36 #include "xalloc.h"
37 #include "xvasprintf.h"
38 #include "hash.h"
39 #include "gettext.h"
40 #include "read-desktop.h"
41 #include "po-charset.h"
42 #include "c-ctype.h"
43
44 #define _(s) gettext(s)
45
46 #define SIZEOF(a) (sizeof(a) / sizeof(a[0]))
47
48 /* ====================== Keyword set customization.  ====================== */
49
50 /* The syntax of a Desktop Entry file is defined at
51    http://standards.freedesktop.org/desktop-entry-spec/latest/index.html
52
53    Basically, values with 'localestring' type can be translated.
54
55    The type of a value is determined by looking at the key associated
56    with it.  The list of available keys are listed on:
57    http://standards.freedesktop.org/desktop-entry-spec/latest/ar01s05.html  */
58
59 static hash_table keywords;
60 static bool default_keywords = true;
61
62 static void
63 add_keyword (const char *name, hash_table *keywords, bool is_list)
64 {
65   if (name == NULL)
66     default_keywords = false;
67   else
68     {
69       if (keywords->table == NULL)
70         hash_init (keywords, 100);
71
72       desktop_add_keyword (keywords, name, is_list);
73     }
74 }
75
76 void
77 x_desktop_keyword (const char *name)
78 {
79   add_keyword (name, &keywords, false);
80 }
81
82 static void
83 init_keywords (void)
84 {
85   if (default_keywords)
86     {
87       if (keywords.table == NULL)
88         hash_init (&keywords, 100);
89
90       desktop_add_default_keywords (&keywords);
91       default_keywords = false;
92     }
93 }
94
95 typedef struct extract_desktop_reader_ty extract_desktop_reader_ty;
96 struct extract_desktop_reader_ty
97 {
98   DESKTOP_READER_TY
99
100   message_list_ty *mlp;
101 };
102
103 static void
104 extract_desktop_handle_group (struct desktop_reader_ty *reader,
105                               const char *group)
106 {
107   savable_comment_reset ();
108 }
109
110 static void
111 extract_desktop_handle_pair (struct desktop_reader_ty *reader,
112                              lex_pos_ty *key_pos,
113                              const char *key,
114                              const char *locale,
115                              const char *value)
116 {
117   extract_desktop_reader_ty *extract_reader =
118     (extract_desktop_reader_ty *) reader;
119   void *keyword_value;
120
121   if (!locale                   /* Skip already translated entry.  */
122       && hash_find_entry (&keywords, key, strlen (key), &keyword_value) == 0)
123     {
124       bool is_list = (bool) keyword_value;
125
126       remember_a_message (extract_reader->mlp, NULL,
127                           desktop_unescape_string (value, is_list),
128                           null_context, key_pos,
129                           NULL, savable_comment);
130     }
131   savable_comment_reset ();
132 }
133
134 static void
135 extract_desktop_handle_comment (struct desktop_reader_ty *reader,
136                                 const char *buffer)
137 {
138   size_t buflen = strlen (buffer);
139   size_t bufpos = 0;
140
141   while (bufpos < buflen
142          && c_isspace (buffer[bufpos]))
143     ++bufpos;
144   while (buflen >= bufpos
145          && c_isspace (buffer[buflen - 1]))
146     --buflen;
147   if (bufpos < buflen)
148     {
149       char *comment = xstrdup (buffer);
150       comment[buflen] = 0;
151       savable_comment_add (&comment[bufpos]);
152       free (comment);
153     }
154 }
155
156 static void
157 extract_desktop_handle_blank (struct desktop_reader_ty *reader,
158                               const char *s)
159 {
160   savable_comment_reset ();
161 }
162
163 desktop_reader_class_ty extract_methods =
164   {
165     sizeof (extract_desktop_reader_ty),
166     NULL,
167     NULL,
168     extract_desktop_handle_group,
169     extract_desktop_handle_pair,
170     extract_desktop_handle_comment,
171     extract_desktop_handle_blank
172   };
173
174 void
175 extract_desktop (FILE *f,
176                  const char *real_filename, const char *logical_filename,
177                  flag_context_list_table_ty *flag_table,
178                  msgdomain_list_ty *mdlp)
179 {
180   desktop_reader_ty *reader = desktop_reader_alloc (&extract_methods);
181   extract_desktop_reader_ty *extract_reader =
182     (extract_desktop_reader_ty *) reader;
183
184   init_keywords ();
185   xgettext_current_source_encoding = po_charset_utf8;
186
187   extract_reader->mlp = mdlp->item[0]->messages;
188
189   desktop_parse (reader, f, real_filename, logical_filename);
190   desktop_reader_free (reader);
191
192   reader = NULL;
193 }