1 /* This file is part of Dico.
2    Copyright (C) 2008-2020 Sergey Poznyakoff
3 
4    Dico is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 3, or (at your option)
7    any later version.
8 
9    Dico is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13 
14    You should have received a copy of the GNU General Public License
15    along with Dico.  If not, see <http://www.gnu.org/licenses/>. */
16 
17 #include <dicod.h>
18 
19 dico_list_t dicod_lang_lazy_prefs;
20 dico_list_t dicod_lang_prefs[2];
21 
22 static int
cmp_string_ci(const void * a,const void * b,void * closure)23 cmp_string_ci(const void *a, const void *b, void *closure)
24 {
25     return c_strcasecmp(a, b);
26 }
27 
28 int
dicod_lang_check(dico_list_t list[2])29 dicod_lang_check(dico_list_t list[2])
30 {
31     if (!list[0] && !list[1])
32 	return 1;
33 
34     if (dicod_lang_lazy_prefs) {
35 	if (list[0] && dico_list_intersect_p(dicod_lang_lazy_prefs, list[0],
36 					     cmp_string_ci, NULL))
37 	    return 1;
38 	if (list[1] && dico_list_intersect_p(dicod_lang_lazy_prefs, list[1],
39 					     cmp_string_ci, NULL))
40 	    return 1;
41 	return 0;
42     }
43 
44     if (dicod_lang_prefs[0] && list[0]
45 	&& !dico_list_intersect_p(dicod_lang_prefs[0], list[0],
46 				  cmp_string_ci, NULL))
47 	return 0;
48     if (dicod_lang_prefs[1] && list[1]
49 	&& !dico_list_intersect_p(dicod_lang_prefs[1], list[1],
50 				  cmp_string_ci, NULL))
51 	return 0;
52     return 1;
53 }
54 
55 void
dicod_lang(dico_stream_t str,int argc,char ** argv)56 dicod_lang(dico_stream_t str, int argc, char **argv)
57 {
58     dico_list_destroy(&dicod_lang_lazy_prefs);
59     dico_list_destroy(&dicod_lang_prefs[0]);
60     dico_list_destroy(&dicod_lang_prefs[1]);
61     if (argc > 2) {
62 	int n = 0;
63 	int i;
64 
65 	for (i = 2; i < argc; i++) {
66 	    if (n == 0 && strcmp(argv[i], ":") == 0)
67 		n = 1;
68 	    else {
69 		if (!dicod_lang_prefs[n]) {
70 		    dicod_lang_prefs[n] = xdico_list_create();
71 		    dico_list_set_free_item(dicod_lang_prefs[n],
72 					    dicod_free_item, NULL);
73 		}
74 		xdico_list_append(dicod_lang_prefs[n], xstrdup(argv[i]));
75 	    }
76 	}
77 	if (n == 0) {
78 	    dicod_lang_lazy_prefs = dicod_lang_prefs[0];
79 	    dicod_lang_prefs[0] = NULL;
80 	}
81     }
82     check_db_visibility();
83     stream_writez(str, "250 ok - set language preferences\n");
84 }
85 
86 static int
_display_pref(void * item,void * data)87 _display_pref(void *item, void *data)
88 {
89     dico_stream_t str = data;
90     stream_writez(str, " ");
91     stream_writez(str, item);
92     return 0;
93 }
94 
95 static void
show_lang_lists(dico_stream_t str,dico_list_t list[2])96 show_lang_lists(dico_stream_t str, dico_list_t list[2])
97 {
98     dico_list_iterate(list[0], _display_pref, str);
99     dico_stream_write(str, " :", 2);
100     dico_list_iterate(list[1], _display_pref, str);
101     dico_stream_write(str, "\n", 1);
102 }
103 
104 void
dicod_show_lang_pref(dico_stream_t str,int argc,char ** argv)105 dicod_show_lang_pref(dico_stream_t str, int argc, char **argv)
106 {
107     stream_writez(str, "280");
108     if (dicod_lang_lazy_prefs) {
109 	dico_list_iterate(dicod_lang_lazy_prefs, _display_pref, str);
110 	dico_stream_write(str, "\n", 1);
111     } else
112 	show_lang_lists(str, dicod_lang_prefs);
113 }
114 
115 void
dicod_show_lang_info(dico_stream_t str,int argc,char ** argv)116 dicod_show_lang_info(dico_stream_t str, int argc, char **argv)
117 {
118     dicod_database_t *db = find_database(argv[3]);
119     if (!db) {
120 	stream_writez(str,
121 		      "550 invalid database, use SHOW DB for a list\n");
122     } else {
123 	dico_list_t langlist[2];
124 
125 	dicod_database_get_languages(db, langlist);
126 	stream_writez(str, "280");
127 	show_lang_lists(str, langlist);
128     }
129 }
130 
131 static int
_show_database_lang(void * item,void * data)132 _show_database_lang(void *item, void *data)
133 {
134     dicod_database_t *db = item;
135     dico_stream_t str = data;
136     dico_list_t langlist[2];
137     dicod_database_get_languages(db, langlist);
138     stream_printf(str, "%s", db->name);
139     show_lang_lists(str, langlist);
140     return 0;
141 }
142 
143 void
dicod_show_lang_db(dico_stream_t str,int argc,char ** argv)144 dicod_show_lang_db(dico_stream_t str, int argc, char **argv)
145 {
146     size_t count = database_count();
147     if (count == 0)
148 	stream_printf(str, "554 No databases present\n");
149     else {
150 	dico_stream_t ostr;
151 
152 	stream_printf(str, "110 %lu databases present\n",
153 		      (unsigned long) count);
154 	ostr = dicod_ostream_create(str, NULL);
155 	database_iterate(_show_database_lang, ostr);
156 	dico_stream_close(ostr);
157 	dico_stream_destroy(&ostr);
158 	stream_writez(str, ".\n");
159 	stream_writez(str, "250 ok\n");
160     }
161 }
162 
163 void
register_lang(void)164 register_lang(void)
165 {
166     static struct dicod_command cmd[] = {
167 	{ "OPTION LANG", 2, DICOD_MAXPARAM_INF, "[list]",
168 	  "define language preferences",
169 	  dicod_lang },
170 	{ "SHOW LANG DB", 3, 3, NULL,
171 	  "show databases with their language preferences",
172 	  dicod_show_lang_db },
173 	{ "SHOW LANG DATABASES", 3, 3, NULL,
174 	  "show databases with their language preferences",
175 	  dicod_show_lang_db },
176 	{ "SHOW LANG INFO", 4, 4, "database",
177 	  "show language preferences of a database",
178 	  dicod_show_lang_info },
179 	{ "SHOW LANG PREF", 3, 3, NULL,
180 	  "show server language preferences",
181 	  dicod_show_lang_pref },
182 	{ NULL }
183     };
184     dicod_capa_register("lang", cmd, NULL, NULL);
185 }
186