source: trunk/gtk/util.c @ 204

Last change on this file since 204 was 162, checked in by titer, 16 years ago

Merge from branches/new_api:r161

File size: 5.7 KB
Line 
1/*
2  Copyright (c) 2005-2006 Joshua Elsasser. All rights reserved.
3   
4  Redistribution and use in source and binary forms, with or without
5  modification, are permitted provided that the following conditions
6  are met:
7   
8   1. Redistributions of source code must retain the above copyright
9      notice, this list of conditions and the following disclaimer.
10   2. Redistributions in binary form must reproduce the above copyright
11      notice, this list of conditions and the following disclaimer in the
12      documentation and/or other materials provided with the distribution.
13   
14  THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS "AS IS" AND
15  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
18  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24  POSSIBILITY OF SUCH DAMAGE.
25*/
26
27#include <sys/types.h>
28#include <sys/stat.h>
29#include <errno.h>
30#include <signal.h>
31#include <stdarg.h>
32#include <string.h>
33
34#include <gtk/gtk.h>
35#include <glib/gi18n.h>
36
37#include "util.h"
38
39#define BESTDECIMAL(d)          (10.0 > (d) ? 2 : (100.0 > (d) ? 1 : 0))
40
41static void
42errcb(GtkWidget *wind, int resp, gpointer data);
43
44gboolean
45strbool(const char *str) {
46  switch(str[0]) {
47    case 'y':
48    case 'Y':
49    case '1':
50    case 'j':
51    case 'e':
52      return TRUE;
53    default:
54      if(0 == g_ascii_strcasecmp("on", str))
55        return TRUE;
56      break;
57  }
58
59  return FALSE;
60}
61
62static const char *sizestrs[] = {
63  N_("B"), N_("KiB"), N_("MiB"), N_("GiB"), N_("TiB"), N_("PiB"), N_("EiB"),
64};
65
66char *
67readablesize(guint64 size) {
68  unsigned int ii;
69  double small = size;
70
71  for(ii = 0; ii + 1 < ALEN(sizestrs) && 1024.0 <= small / 1024.0; ii++)
72    small /= 1024.0;
73
74  if(1024.0 <= small) {
75    small /= 1024.0;
76    ii++;
77  }
78
79  return g_strdup_printf("%.*f %s", BESTDECIMAL(small), small,
80                         gettext(sizestrs[ii]));
81}
82
83char *
84ratiostr(guint64 down, guint64 up) {
85  double ratio;
86
87  if(0 == up && 0 == down)
88    return g_strdup(_("N/A"));
89
90  if(0 == down)
91    /* this is a UTF-8 infinity symbol */
92    return g_strdup(_("\xE2\x88\x9E"));
93
94  ratio = (double)up / (double)down;
95
96  return g_strdup_printf("%.*f", (10.0 > ratio ? 2 : (100.0 > ratio ? 1 : 0)),
97                         ratio);
98}
99
100gboolean
101mkdir_p(const char *name, mode_t mode) {
102  struct stat sb;
103  char *parent;
104  gboolean ret;
105  int oerrno;
106
107  if(0 != stat(name, &sb)) {
108    if(ENOENT != errno)
109      return FALSE;
110    parent = g_path_get_dirname(name);
111    ret = mkdir_p(parent, mode);
112    oerrno = errno;
113    g_free(parent);
114    errno = oerrno;
115    return (ret ? (0 == mkdir(name, mode)) : FALSE);
116  }
117
118  if(!S_ISDIR(sb.st_mode)) {
119    errno = ENOTDIR;
120    return FALSE;
121  }
122
123  return TRUE;
124}
125
126char *
127joinstrlist(GList *list, char *sep) {
128  GList *ii;
129  int len;
130  char *ret, *dest;
131
132  if(0 > (len = strlen(sep) * (g_list_length(list) - 1)))
133    return NULL;
134
135  for(ii = g_list_first(list); NULL != ii; ii = ii->next)
136    len += strlen(ii->data);
137
138  dest = ret = g_new(char, len + 1);
139
140  for(ii = g_list_first(list); NULL != ii; ii = ii->next) {
141    dest = g_stpcpy(dest, ii->data);
142    if(NULL != ii->next)
143      dest = g_stpcpy(dest, sep);
144  }
145
146  return ret;
147}
148
149char *
150urldecode(const char *str, int len) {
151  int ii, jj;
152  char *ret;
153  char buf[3];
154
155  if(0 >= len)
156    len = strlen(str);
157
158  for(ii = jj = 0; ii < len; ii++, jj++)
159    if('%' == str[ii])
160      ii += 2;
161
162  ret = g_new(char, jj + 1);
163
164  buf[2] = '\0';
165  for(ii = jj = 0; ii < len; ii++, jj++) {
166    switch(str[ii]) {
167      case '%':
168        if(ii + 2 < len) {
169          buf[0] = str[ii+1];
170          buf[1] = str[ii+2];
171          ret[jj] = g_ascii_strtoull(buf, NULL, 16);
172        }
173        ii += 2;
174        break;
175      case '+':
176        ret[jj] = ' ';
177      default:
178        ret[jj] = str[ii];
179    }
180  }
181  ret[jj] = '\0';
182
183  return ret;
184}
185
186GtkWidget *
187errmsg(GtkWindow *wind, const char *format, ...) {
188  GtkWidget *dialog;
189  va_list ap;
190
191  va_start(ap, format);
192  dialog = verrmsg(wind, NULL, NULL, format, ap);
193  va_end(ap);
194
195  return dialog;
196}
197
198GtkWidget *
199errmsg_full(GtkWindow *wind, callbackfunc_t func, void *data,
200            const char *format, ...) {
201  GtkWidget *dialog;
202  va_list ap;
203
204  va_start(ap, format);
205  dialog = verrmsg(wind, func, data, format, ap);
206  va_end(ap);
207
208  return dialog;
209}
210
211GtkWidget *
212verrmsg(GtkWindow *wind, callbackfunc_t func, void *data,
213        const char *format, va_list ap) {
214  GtkWidget *dialog;
215  char *msg;
216  GList *funcdata;
217
218  msg = g_strdup_vprintf(format, ap);
219
220  if(NULL == wind)
221    dialog = gtk_message_dialog_new(
222      NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "%s", msg);
223  else
224    dialog = gtk_message_dialog_new(wind,
225      GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
226      GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "%s", msg);
227
228  if(NULL == func)
229    funcdata = NULL;
230  else
231    funcdata = g_list_append(g_list_append(NULL, func), data);
232  g_signal_connect(dialog, "response", G_CALLBACK(errcb), funcdata);
233  if(NULL != wind)
234    gtk_widget_show(dialog);
235  g_free(msg);
236
237  return dialog;
238}
239
240static void
241errcb(GtkWidget *widget, int resp SHUTUP, gpointer data) {
242  GList *funcdata;
243  callbackfunc_t func;
244
245  if(NULL != data) {
246    funcdata = g_list_first(data);
247    func = funcdata->data;
248    data = funcdata->next->data;
249    func(data);
250    g_list_free(funcdata);
251  }
252
253  gtk_widget_destroy(widget);
254}
Note: See TracBrowser for help on using the repository browser.