]> git.sur5r.net Git - glabels/blob - glabels2/src/util.c
6d9331b354780b51845c7cabd80a6f56ac9ec664
[glabels] / glabels2 / src / util.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
2
3 /*
4  *  (GLABELS) Label and Business Card Creation program for GNOME
5  *
6  *  util.c:  various small utility functions
7  *
8  *  Copyright (C) 2001  Jim Evins <evins@snaught.com>.
9  *
10  *  This program is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License as published by
12  *  the Free Software Foundation; either version 2 of the License, or
13  *  (at your option) any later version.
14  *
15  *  This program is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU General Public License for more details.
19  *
20  *  You should have received a copy of the GNU General Public License
21  *  along with this program; if not, write to the Free Software
22  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
23  */
24
25 #include <config.h>
26
27 #include "util.h"
28
29 #include <string.h>
30 #include <glib.h>
31 #include <math.h>
32 #include <gtk/gtkliststore.h>
33 #include <gtk/gtkcellrenderertext.h>
34 #include <gtk/gtkcelllayout.h>
35
36 #define FRAC_EPSILON 0.00005
37
38 \f
39 /****************************************************************************/
40 /* Append ".glabels" extension to filename if needed.                       */
41 /****************************************************************************/
42 gchar *
43 gl_util_add_extension (const gchar *orig_filename)
44 {
45         gchar *new_filename, *extension;
46
47         extension = strrchr (orig_filename, '.');
48         if (extension == NULL) {
49                 new_filename = g_strconcat (orig_filename, ".glabels", NULL);
50         } else {
51                 if (g_strcasecmp (extension, ".glabels") != 0) {
52                         new_filename =
53                             g_strconcat (orig_filename, ".glabels", NULL);
54                 } else {
55                         new_filename = g_strdup (orig_filename);
56                 }
57         }
58
59         return new_filename;
60 }
61
62 /****************************************************************************/
63 /* Remove ".glabels" extension from filename if needed.                     */
64 /****************************************************************************/
65 gchar *
66 gl_util_remove_extension (const gchar *orig_filename)
67 {
68         gchar *new_filename, *extension;
69
70         new_filename = g_strdup (orig_filename);
71
72         extension = strrchr (new_filename, '.');
73         if (extension != NULL) {
74                 if (g_strcasecmp (extension, ".glabels") == 0) {
75                         *extension = 0; /* truncate string, rm extension */
76                 }
77         }
78
79         return new_filename;
80 }
81
82 /****************************************************************************/
83 /* Make sure we have an absolute path to filename.                          */
84 /****************************************************************************/
85 gchar *
86 gl_util_make_absolute (const gchar *filename)
87 {
88         gchar *pwd, *absolute_filename;
89
90         if (g_path_is_absolute (filename)) {
91                 absolute_filename = g_strdup (filename);
92         } else {
93                 pwd = g_get_current_dir ();
94                 absolute_filename = g_build_filename (pwd, filename, NULL);
95                 g_free (pwd);
96         }
97
98         return absolute_filename;
99 }
100
101 /****************************************************************************/
102 /* Create fractional representation of number, if possible.                 */
103 /****************************************************************************/
104 gchar *
105 gl_util_fraction (gdouble x)
106 {
107         static gdouble denom[] = { 1., 2., 3., 4., 8., 16., 32., 0. };
108         gint i;
109         gdouble product, remainder;
110         gint n, d;
111
112         for ( i=0; denom[i] != 0.0; i++ ) {
113                 product = x * denom[i];
114                 remainder = fabs(product - ((gint)(product+0.5)));
115                 if ( remainder < FRAC_EPSILON ) break;
116         }
117
118         if ( denom[i] == 0.0 ) {
119                 /* None of our denominators work. */
120                 return g_strdup_printf ("%.5g", x);
121         }
122         if ( denom[i] == 1.0 ) {
123                 /* Simple integer. */
124                 return g_strdup_printf ("%d", (gint)x);
125         }
126         n = (gint)( x * denom[i] + 0.5 );
127         d = (gint)denom[i];
128         if ( n > d ) {
129                 return g_strdup_printf ("%d_%d/%d", (n/d), (n%d), d);
130         } else {
131                 return g_strdup_printf ("%d/%d", (n%d), d);
132         }
133 }
134
135 /****************************************************************************/
136 /* Utilities to deal with PangoAlignment types.                             */
137 /****************************************************************************/
138 const gchar *
139 gl_util_align_to_string (PangoAlignment align)
140 {
141         switch (align) {
142         case PANGO_ALIGN_LEFT:
143                 return "Left";
144         case PANGO_ALIGN_CENTER:
145                 return "Center";
146         case PANGO_ALIGN_RIGHT:
147                 return "Right";
148         default:
149                 return "?";
150         }
151 }
152
153 PangoAlignment
154 gl_util_string_to_align (const gchar *string)
155 {
156
157         if (g_strcasecmp (string, "Left") == 0) {
158                 return PANGO_ALIGN_LEFT;
159         } else if (g_strcasecmp (string, "Center") == 0) {
160                 return PANGO_ALIGN_CENTER;
161         } else if (g_strcasecmp (string, "Right") == 0) {
162                 return PANGO_ALIGN_RIGHT;
163         } else {
164                 return PANGO_ALIGN_LEFT;
165         }
166
167 }
168
169 /****************************************************************************/
170 /* Utilities to deal with PangoWeight types                                 */
171 /****************************************************************************/
172 const gchar *
173 gl_util_weight_to_string (PangoWeight weight)
174 {
175         switch (weight) {
176         case PANGO_WEIGHT_NORMAL:
177                 return "Regular";
178         case PANGO_WEIGHT_BOLD:
179                 return "Bold";
180         default:
181                 return "?";
182         }
183 }
184
185 PangoWeight
186 gl_util_string_to_weight (const gchar *string)
187 {
188
189         if (g_strcasecmp (string, "Regular") == 0) {
190                 return PANGO_WEIGHT_NORMAL;
191         } else if (g_strcasecmp (string, "Bold") == 0) {
192                 return PANGO_WEIGHT_BOLD;
193         } else {
194                 return PANGO_WEIGHT_NORMAL;
195         }
196
197 }
198
199 /****************************************************************************/
200 /* Convienience function to set strings in a text combo_box from a GList    */
201 /****************************************************************************/
202 void
203 gl_util_combo_box_set_strings (GtkComboBox       *combo,
204                                GList             *list)
205 {
206         GtkTreeModel *model;
207         GList        *p;
208
209         g_return_if_fail (list);
210
211         model = gtk_combo_box_get_model(combo);
212         gtk_list_store_clear (GTK_LIST_STORE (model));
213
214         for (p=list; p!=NULL; p=p->next) {
215                 if (p->data) {
216                         gtk_combo_box_append_text (combo, p->data);
217                 }
218         }
219 }
220
221 /*---------------------------------------------------------------------------*/
222 /* PRIVATE.  gl_util_combo_box_set_active_text support.                      */
223 /*---------------------------------------------------------------------------*/
224
225 typedef struct {
226   const gchar *text;
227   GtkTreeIter  iter;
228   gboolean     found;
229 } TextSearchData;
230
231 static gboolean
232 search_text_func (GtkTreeModel *model,
233                   GtkTreePath  *path,
234                   GtkTreeIter  *iter,
235                   gpointer      data)
236 {
237   TextSearchData *search_data = (TextSearchData *)data;
238   gchar          *text = NULL;
239
240   gtk_tree_model_get (model, iter, 0, &text, -1);
241
242   if (strcmp (text,search_data->text) == 0) {
243     search_data->found = TRUE;
244     search_data->iter  = *iter;
245   }
246
247   g_free (text);
248   
249   return FALSE;
250 }
251
252 /****************************************************************************/
253 /* Convienience function to set active text in a text combo_box from text   */
254 /****************************************************************************/
255 void
256 gl_util_combo_box_set_active_text (GtkComboBox       *combo,
257                                    const gchar       *text)
258 {
259         GtkTreeModel   *model = gtk_combo_box_get_model(combo);
260
261         g_return_if_fail (GTK_IS_LIST_STORE (model));
262
263         if (!text) {
264
265                 gtk_combo_box_set_active (combo, -1);
266
267         } else {
268                 TextSearchData  search_data;
269
270                 search_data.text        = text;
271                 search_data.found       = FALSE;
272
273                 gtk_tree_model_foreach (model, search_text_func, &search_data);
274                 if (search_data.found) {
275                         gtk_combo_box_set_active_iter (combo,
276                                                        &search_data.iter);
277                 } else {
278                         gtk_combo_box_set_active (combo, -1);
279                 }    
280
281         }
282
283 }
284
285 /****************************************************************************/
286 /* Convienience function to add a simple text model to an existing          */
287 /* combo_box.  This is needed since combo_boxes created with glade do not   */
288 /* use the gtk_combo_box_new_text() constructor.                            */
289 /****************************************************************************/
290 void
291 gl_util_combo_box_add_text_model (GtkComboBox       *combo)
292 {
293         GtkCellRenderer *cell;
294         GtkListStore *store;
295
296         store = gtk_list_store_new (1, G_TYPE_STRING);
297         gtk_combo_box_set_model (combo, GTK_TREE_MODEL (store));
298         g_object_unref (store);
299
300         cell = gtk_cell_renderer_text_new ();
301         gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), cell, TRUE);
302         gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo), cell,
303                                         "text", 0,
304                                         NULL);
305 }
306
307 /****************************************************************************/
308 /* Get list of available font families.                                     */
309 /****************************************************************************/
310 GList  *
311 gl_util_get_font_family_list (void)
312 {
313         GList                *list = NULL;
314         PangoFontMap         *fontmap;
315         PangoContext         *context;
316         PangoFontFamily     **families;
317         gint                  n;
318         gint                  i;
319         gchar                *name;
320
321         fontmap = pango_cairo_font_map_new ();
322         context = pango_cairo_font_map_create_context (PANGO_CAIRO_FONT_MAP (fontmap));
323
324         pango_context_list_families (context, &families, &n);
325
326         for ( i=0; i<n; i++ )
327         {
328                 name = g_strdup (pango_font_family_get_name (families[i]));
329                 list = g_list_append (list, name);
330         }
331
332         g_free (families);
333
334         g_object_unref (context);
335         g_object_unref (fontmap);
336
337         return list;
338 }
339
340 /****************************************************************************/
341 /* Free previosly allocated list of font families.                          */
342 /****************************************************************************/
343 void    gl_util_font_family_list_free (GList *list)
344 {
345         GList *p;
346
347         for (p = list; p != NULL; p = p->next) {
348                 g_free (p->data);
349                 p->data = NULL;
350         }
351
352         g_list_free (list);
353 }
354
355