• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* xgettext Desktop Entry backend.
2    Copyright (C) 2014, 2018-2020 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 <https://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 "xg-message.h"
35 #include "error.h"
36 #include "error-progname.h"
37 #include "xalloc.h"
38 #include "xvasprintf.h"
39 #include "mem-hash-map.h"
40 #include "gettext.h"
41 #include "read-desktop.h"
42 #include "po-charset.h"
43 #include "c-ctype.h"
44 
45 #define _(s) gettext(s)
46 
47 #define SIZEOF(a) (sizeof(a) / sizeof(a[0]))
48 
49 /* ====================== Keyword set customization.  ====================== */
50 
51 /* The syntax of a Desktop Entry file is defined at
52    https://standards.freedesktop.org/desktop-entry-spec/latest/index.html
53 
54    Basically, values with 'localestring' type can be localized.
55    However, the values of 'Icon', while being localizable, are not supported
56    by xgettext.  See the documentation for more info.
57 
58    The type of a value is determined by looking at the key associated
59    with it.  The list of available keys are listed on:
60    https://standards.freedesktop.org/desktop-entry-spec/latest/ar01s04.html  */
61 
62 static hash_table keywords;
63 static bool default_keywords = true;
64 
65 static void
add_keyword(const char * name,hash_table * keywords,bool is_list)66 add_keyword (const char *name, hash_table *keywords, bool is_list)
67 {
68   if (name == NULL)
69     default_keywords = false;
70   else
71     {
72       if (keywords->table == NULL)
73         hash_init (keywords, 100);
74 
75       desktop_add_keyword (keywords, name, is_list);
76     }
77 }
78 
79 void
x_desktop_keyword(const char * name)80 x_desktop_keyword (const char *name)
81 {
82   add_keyword (name, &keywords, false);
83 }
84 
85 static void
init_keywords(void)86 init_keywords (void)
87 {
88   if (default_keywords)
89     {
90       if (keywords.table == NULL)
91         hash_init (&keywords, 100);
92 
93       desktop_add_default_keywords (&keywords);
94       default_keywords = false;
95     }
96 }
97 
98 typedef struct extract_desktop_reader_ty extract_desktop_reader_ty;
99 struct extract_desktop_reader_ty
100 {
101   DESKTOP_READER_TY
102 
103   message_list_ty *mlp;
104 };
105 
106 static void
extract_desktop_handle_group(struct desktop_reader_ty * reader,const char * group)107 extract_desktop_handle_group (struct desktop_reader_ty *reader,
108                               const char *group)
109 {
110   savable_comment_reset ();
111 }
112 
113 static void
extract_desktop_handle_pair(struct desktop_reader_ty * reader,lex_pos_ty * key_pos,const char * key,const char * locale,const char * value)114 extract_desktop_handle_pair (struct desktop_reader_ty *reader,
115                              lex_pos_ty *key_pos,
116                              const char *key,
117                              const char *locale,
118                              const char *value)
119 {
120   extract_desktop_reader_ty *extract_reader =
121     (extract_desktop_reader_ty *) reader;
122   void *keyword_value;
123 
124   if (!locale                   /* Skip already translated entry.  */
125       && hash_find_entry (&keywords, key, strlen (key), &keyword_value) == 0)
126     {
127       bool is_list = (bool) keyword_value;
128 
129       remember_a_message (extract_reader->mlp, NULL,
130                           desktop_unescape_string (value, is_list), false,
131                           false, null_context, key_pos,
132                           NULL, savable_comment, false);
133     }
134   savable_comment_reset ();
135 }
136 
137 static void
extract_desktop_handle_comment(struct desktop_reader_ty * reader,const char * buffer)138 extract_desktop_handle_comment (struct desktop_reader_ty *reader,
139                                 const char *buffer)
140 {
141   size_t buflen = strlen (buffer);
142   size_t bufpos = 0;
143 
144   while (bufpos < buflen
145          && c_isspace (buffer[bufpos]))
146     ++bufpos;
147   while (buflen >= bufpos
148          && c_isspace (buffer[buflen - 1]))
149     --buflen;
150   if (bufpos < buflen)
151     {
152       char *comment = xstrdup (buffer);
153       comment[buflen] = 0;
154       savable_comment_add (&comment[bufpos]);
155       free (comment);
156     }
157 }
158 
159 static void
extract_desktop_handle_blank(struct desktop_reader_ty * reader,const char * s)160 extract_desktop_handle_blank (struct desktop_reader_ty *reader,
161                               const char *s)
162 {
163   savable_comment_reset ();
164 }
165 
166 desktop_reader_class_ty extract_methods =
167   {
168     sizeof (extract_desktop_reader_ty),
169     NULL,
170     NULL,
171     extract_desktop_handle_group,
172     extract_desktop_handle_pair,
173     extract_desktop_handle_comment,
174     extract_desktop_handle_blank
175   };
176 
177 void
extract_desktop(FILE * f,const char * real_filename,const char * logical_filename,flag_context_list_table_ty * flag_table,msgdomain_list_ty * mdlp)178 extract_desktop (FILE *f,
179                  const char *real_filename, const char *logical_filename,
180                  flag_context_list_table_ty *flag_table,
181                  msgdomain_list_ty *mdlp)
182 {
183   desktop_reader_ty *reader = desktop_reader_alloc (&extract_methods);
184   extract_desktop_reader_ty *extract_reader =
185     (extract_desktop_reader_ty *) reader;
186 
187   init_keywords ();
188   xgettext_current_source_encoding = po_charset_utf8;
189 
190   extract_reader->mlp = mdlp->item[0]->messages;
191 
192   desktop_parse (reader, f, real_filename, logical_filename);
193   desktop_reader_free (reader);
194 
195   reader = NULL;
196 }
197