]> Pileus Git - ~andy/gtk/blob - gtk/gtkstock.c
Fixes #136082 and #135265, patch by Morten Welinder.
[~andy/gtk] / gtk / gtkstock.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 2000 Red Hat, Inc. 
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library 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 GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
22  * file for a list of people on the GTK+ Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
25  */
26
27 #include <config.h>
28 #include <string.h>
29
30 #include "gtkstock.h"
31 #include "gtkiconfactory.h"
32 #include "gtkintl.h"
33 #include <gdk/gdkkeysyms.h>
34
35 static GHashTable *stock_hash = NULL;
36 static void init_stock_hash (void);
37
38 static void
39 real_add (const GtkStockItem *items,
40           guint               n_items,
41           gboolean            copy)
42 {
43   int i;
44
45   init_stock_hash ();
46
47   if (n_items == 0)
48     return;
49
50   i = 0;
51   while (i < n_items)
52     {
53       gpointer old_key, old_value;
54       const GtkStockItem *item = &items[i];
55       if (copy)
56         item = gtk_stock_item_copy (item);
57
58       if (g_hash_table_lookup_extended (stock_hash, item->stock_id,
59                                         &old_key, &old_value))
60         {
61           g_hash_table_remove (stock_hash, old_key);
62           gtk_stock_item_free (old_value);
63         }
64       
65       g_hash_table_insert (stock_hash,
66                            (gchar*)item->stock_id, (GtkStockItem*)item);
67
68       ++i;
69     }
70 }
71
72 /**
73  * gtk_stock_add:
74  * @items: a #GtkStockItem or array of items
75  * @n_items: number of #GtkStockItem in @items
76  *
77  * Registers each of the stock items in @items. If an item already
78  * exists with the same stock ID as one of the @items, the old item
79  * gets replaced. The stock items are copied, so GTK+ does not hold
80  * any pointer into @items and @items can be freed. Use
81  * gtk_stock_add_static() if @items is persistent and GTK+ need not
82  * copy the array.
83  * 
84  **/
85 void
86 gtk_stock_add (const GtkStockItem *items,
87                guint               n_items)
88 {
89   g_return_if_fail (items != NULL);
90
91   real_add (items, n_items, TRUE);
92 }
93
94 /**
95  * gtk_stock_add_static:
96  * @items: a #GtkStockItem or array of #GtkStockItem
97  * @n_items: number of items
98  *
99  * Same as gtk_stock_add(), but doesn't copy @items, so
100  * @items must persist until application exit.
101  * 
102  **/
103 void
104 gtk_stock_add_static (const GtkStockItem *items,
105                       guint               n_items)
106 {
107   g_return_if_fail (items != NULL);
108
109   real_add (items, n_items, FALSE);
110 }
111
112 /**
113  * gtk_stock_lookup:
114  * @stock_id: a stock item name
115  * @item: stock item to initialize with values
116  * 
117  * Fills @item with the registered values for @stock_id, returning %TRUE
118  * if @stock_id was known.
119  * 
120  * 
121  * Return value: %TRUE if @item was initialized
122  **/
123 gboolean
124 gtk_stock_lookup (const gchar  *stock_id,
125                   GtkStockItem *item)
126 {
127   const GtkStockItem *found;
128
129   g_return_val_if_fail (stock_id != NULL, FALSE);
130   g_return_val_if_fail (item != NULL, FALSE);
131
132   init_stock_hash ();
133
134   found = g_hash_table_lookup (stock_hash, stock_id);
135
136   if (found)
137     {
138       *item = *found;
139       if (item->label)
140         item->label = dgettext (item->translation_domain, item->label);
141     }
142
143   return found != NULL;
144 }
145
146 static void
147 listify_foreach (gpointer key, gpointer value, gpointer data)
148 {
149   GSList **list = data;
150
151   *list = g_slist_prepend (*list, key);
152 }
153
154 static GSList *
155 g_hash_table_get_keys (GHashTable *table)
156 {
157   GSList *list = NULL;
158
159   g_hash_table_foreach (table, listify_foreach, &list);
160
161   return list;
162 }
163
164 /**
165  * gtk_stock_list_ids:
166  * 
167  * Retrieves a list of all known stock IDs added to a #GtkIconFactory
168  * or registered with gtk_stock_add(). The list must be freed with g_slist_free(),
169  * and each string in the list must be freed with g_free().
170  * 
171  * Return value: a list of known stock IDs
172  **/
173 GSList*
174 gtk_stock_list_ids (void)
175 {
176   GSList *ids;
177   GSList *icon_ids;
178   GSList *retval;
179   GSList *tmp_list;
180   const gchar *last_id;
181   
182   init_stock_hash ();
183
184   ids = g_hash_table_get_keys (stock_hash);
185   icon_ids = _gtk_icon_factory_list_ids ();
186   ids = g_slist_concat (ids, icon_ids);
187
188   ids = g_slist_sort (ids, (GCompareFunc)strcmp);
189
190   last_id = NULL;
191   retval = NULL;
192   tmp_list = ids;
193   while (tmp_list != NULL)
194     {
195       GSList *next;
196
197       next = g_slist_next (tmp_list);
198
199       if (last_id && strcmp (tmp_list->data, last_id) == 0)
200         {
201           /* duplicate, ignore */
202         }
203       else
204         {
205           retval = g_slist_prepend (retval, g_strdup (tmp_list->data));
206           last_id = tmp_list->data;
207         }
208
209       g_slist_free_1 (tmp_list);
210       
211       tmp_list = next;
212     }
213
214   return retval;
215 }
216
217 /**
218  * gtk_stock_item_copy:
219  * @item: a #GtkStockItem
220  * 
221  * Copies a stock item, mostly useful for language bindings and not in applications.
222  * 
223  * Return value: a new #GtkStockItem
224  **/
225 GtkStockItem *
226 gtk_stock_item_copy (const GtkStockItem *item)
227 {
228   GtkStockItem *copy;
229
230   g_return_val_if_fail (item != NULL, NULL);
231
232   copy = g_new (GtkStockItem, 1);
233
234   *copy = *item;
235
236   copy->stock_id = g_strdup (item->stock_id);
237   copy->label = g_strdup (item->label);
238   copy->translation_domain = g_strdup (item->translation_domain);
239
240   return copy;
241 }
242
243 /**
244  * gtk_stock_item_free:
245  * @item: a #GtkStockItem
246  *
247  * Frees a stock item allocated on the heap, such as one returned by
248  * gtk_stock_item_copy(). Also frees the fields inside the stock item,
249  * if they are not %NULL.
250  * 
251  **/
252 void
253 gtk_stock_item_free (GtkStockItem *item)
254 {
255   g_return_if_fail (item != NULL);
256
257   g_free ((gchar*)item->stock_id);
258   g_free ((gchar*)item->label);
259   g_free ((gchar*)item->translation_domain);
260
261   g_free (item);
262 }
263
264 static const GtkStockItem builtin_items [] =
265 {
266   /* KEEP IN SYNC with gtkiconfactory.c stock icons, when appropriate */ 
267  
268   { GTK_STOCK_DIALOG_INFO, N_("Information"), 0, 0, GETTEXT_PACKAGE },
269   { GTK_STOCK_DIALOG_WARNING, N_("Warning"), 0, 0, GETTEXT_PACKAGE },
270   { GTK_STOCK_DIALOG_ERROR, N_("Error"), 0, 0, GETTEXT_PACKAGE },
271   { GTK_STOCK_DIALOG_QUESTION, N_("Question"), 0, 0, GETTEXT_PACKAGE },
272
273   /*  FIXME these need accelerators when appropriate, and
274    * need the mnemonics to be rationalized
275    */
276   { GTK_STOCK_ADD, N_("_Add"), 0, 0, GETTEXT_PACKAGE },
277   { GTK_STOCK_APPLY, N_("_Apply"), 0, 0, GETTEXT_PACKAGE },
278   { GTK_STOCK_BOLD, N_("_Bold"), 0, 0, GETTEXT_PACKAGE },
279   { GTK_STOCK_CANCEL, N_("_Cancel"), 0, 0, GETTEXT_PACKAGE },
280   { GTK_STOCK_CDROM, N_("_CD-Rom"), 0, 0, GETTEXT_PACKAGE },
281   { GTK_STOCK_CLEAR, N_("_Clear"), 0, 0, GETTEXT_PACKAGE },
282   { GTK_STOCK_CLOSE, N_("_Close"), GDK_CONTROL_MASK, 'w', GETTEXT_PACKAGE },
283   { GTK_STOCK_CONVERT, N_("_Convert"), 0, 0, GETTEXT_PACKAGE },
284   { GTK_STOCK_COPY, N_("_Copy"), GDK_CONTROL_MASK, 'c', GETTEXT_PACKAGE },
285   { GTK_STOCK_CUT, N_("Cu_t"), GDK_CONTROL_MASK, 'x', GETTEXT_PACKAGE },
286   { GTK_STOCK_DELETE, N_("_Delete"), 0, 0, GETTEXT_PACKAGE },
287   { GTK_STOCK_EXECUTE, N_("_Execute"), 0, 0, GETTEXT_PACKAGE },
288   { GTK_STOCK_FIND, N_("_Find"), GDK_CONTROL_MASK, 'f', GETTEXT_PACKAGE },
289   { GTK_STOCK_FIND_AND_REPLACE, N_("Find and _Replace"), GDK_CONTROL_MASK, 'r', GETTEXT_PACKAGE },
290   { GTK_STOCK_FLOPPY, N_("_Floppy"), 0, 0, GETTEXT_PACKAGE },
291   { GTK_STOCK_GOTO_BOTTOM, N_("_Bottom"), 0, 0, GETTEXT_PACKAGE },
292   { GTK_STOCK_GOTO_FIRST, N_("_First"), 0, 0, GETTEXT_PACKAGE },
293   { GTK_STOCK_GOTO_LAST, N_("_Last"), 0, 0, GETTEXT_PACKAGE },
294   { GTK_STOCK_GOTO_TOP, N_("_Top"), 0, 0, GETTEXT_PACKAGE },
295   { GTK_STOCK_GO_BACK, N_("_Back"), 0, 0, GETTEXT_PACKAGE },
296   { GTK_STOCK_GO_DOWN, N_("_Down"), 0, 0, GETTEXT_PACKAGE },
297   { GTK_STOCK_GO_FORWARD, N_("_Forward"), 0, 0, GETTEXT_PACKAGE },
298   { GTK_STOCK_GO_UP, N_("_Up"), 0, 0, GETTEXT_PACKAGE },
299   { GTK_STOCK_HARDDISK, N_("_Harddisk"), 0, 0, GETTEXT_PACKAGE },
300   { GTK_STOCK_HELP, N_("_Help"), GDK_CONTROL_MASK, 'h', GETTEXT_PACKAGE },
301   { GTK_STOCK_HOME, N_("_Home"), 0, 0, GETTEXT_PACKAGE },
302   { GTK_STOCK_INDENT, N_("Increase Indent"), 0, 0, GETTEXT_PACKAGE },
303   { GTK_STOCK_UNINDENT, N_("Decrease Indent"), 0, 0, GETTEXT_PACKAGE },
304   { GTK_STOCK_INDEX, N_("_Index"), 0, 0, GETTEXT_PACKAGE },
305   { GTK_STOCK_ITALIC, N_("_Italic"), 0, 0, GETTEXT_PACKAGE },
306   { GTK_STOCK_JUMP_TO, N_("_Jump to"), 0, 0, GETTEXT_PACKAGE },
307   { GTK_STOCK_JUSTIFY_CENTER, N_("_Center"), 0, 0, GETTEXT_PACKAGE },
308   { GTK_STOCK_JUSTIFY_FILL, N_("_Fill"), 0, 0, GETTEXT_PACKAGE },
309   { GTK_STOCK_JUSTIFY_LEFT, N_("_Left"), 0, 0, GETTEXT_PACKAGE },
310   { GTK_STOCK_JUSTIFY_RIGHT, N_("_Right"), 0, 0, GETTEXT_PACKAGE },
311   { GTK_STOCK_NETWORK, N_("_Network"), 0, 0, GETTEXT_PACKAGE },
312   { GTK_STOCK_NEW, N_("_New"), GDK_CONTROL_MASK, 'n', GETTEXT_PACKAGE },
313   { GTK_STOCK_NO, N_("_No"), 0, 0, GETTEXT_PACKAGE },
314   { GTK_STOCK_OK, N_("_OK"), 0, 0, GETTEXT_PACKAGE },
315   { GTK_STOCK_OPEN, N_("_Open"), GDK_CONTROL_MASK, 'o', GETTEXT_PACKAGE },
316   { GTK_STOCK_PASTE, N_("_Paste"), GDK_CONTROL_MASK, 'v', GETTEXT_PACKAGE },
317   { GTK_STOCK_PREFERENCES, N_("_Preferences"), 0, 0, GETTEXT_PACKAGE },
318   { GTK_STOCK_PRINT, N_("_Print"), 0, 0, GETTEXT_PACKAGE },
319   { GTK_STOCK_PRINT_PREVIEW, N_("Print Pre_view"), 0, 0, GETTEXT_PACKAGE },
320   { GTK_STOCK_PROPERTIES, N_("_Properties"), 0, 0, GETTEXT_PACKAGE },
321   { GTK_STOCK_QUIT, N_("_Quit"), GDK_CONTROL_MASK, 'q', GETTEXT_PACKAGE },
322   { GTK_STOCK_REDO, N_("_Redo"), 0, 0, GETTEXT_PACKAGE },
323   { GTK_STOCK_REFRESH, N_("_Refresh"), 0, 0, GETTEXT_PACKAGE },
324   { GTK_STOCK_REMOVE, N_("_Remove"), 0, 0, GETTEXT_PACKAGE },
325   { GTK_STOCK_REVERT_TO_SAVED, N_("_Revert"), 0, 0, GETTEXT_PACKAGE },
326   { GTK_STOCK_SAVE, N_("_Save"), GDK_CONTROL_MASK, 's', GETTEXT_PACKAGE },
327   { GTK_STOCK_SAVE_AS, N_("Save _As"), 0, 0, GETTEXT_PACKAGE },
328   { GTK_STOCK_SELECT_COLOR, N_("_Color"), 0, 0, GETTEXT_PACKAGE },
329   { GTK_STOCK_SELECT_FONT, N_("_Font"), 0, 0, GETTEXT_PACKAGE },
330   { GTK_STOCK_SORT_ASCENDING, N_("_Ascending"), 0, 0, GETTEXT_PACKAGE },
331   { GTK_STOCK_SORT_DESCENDING, N_("_Descending"), 0, 0, GETTEXT_PACKAGE },
332   { GTK_STOCK_SPELL_CHECK, N_("_Spell Check"), 0, 0, GETTEXT_PACKAGE },
333   { GTK_STOCK_STOP, N_("_Stop"), 0, 0, GETTEXT_PACKAGE },
334   { GTK_STOCK_STRIKETHROUGH, N_("_Strikethrough"), 0, 0, GETTEXT_PACKAGE },
335   { GTK_STOCK_UNDELETE, N_("_Undelete"), 0, 0, GETTEXT_PACKAGE },
336   { GTK_STOCK_UNDERLINE, N_("_Underline"), 0, 0, GETTEXT_PACKAGE },
337   { GTK_STOCK_UNDO, N_("_Undo"), 0, 0, GETTEXT_PACKAGE },
338   { GTK_STOCK_YES, N_("_Yes"), 0, 0, GETTEXT_PACKAGE },
339   { GTK_STOCK_ZOOM_100, N_("_Normal Size"), 0, 0, GETTEXT_PACKAGE },
340   { GTK_STOCK_ZOOM_FIT, N_("Best _Fit"), 0, 0, GETTEXT_PACKAGE },
341   { GTK_STOCK_ZOOM_IN, N_("Zoom _In"), 0, 0, GETTEXT_PACKAGE },
342   { GTK_STOCK_ZOOM_OUT, N_("Zoom _Out"), 0, 0, GETTEXT_PACKAGE }
343 };
344
345 static void
346 init_stock_hash (void)
347 {
348   if (stock_hash == NULL)
349     {
350       stock_hash = g_hash_table_new (g_str_hash, g_str_equal);
351
352       gtk_stock_add_static (builtin_items, G_N_ELEMENTS (builtin_items));
353     }
354 }