source: branches/joshe/gtk/util.c @ 77

Last change on this file since 77 was 77, checked in by joshe, 16 years ago

Add internationalization support.

File size: 5.5 KB
Line 
1/*
2  Copyright (c) 2005 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
39static void
40sigexithandler(int sig);
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, int decimals) {
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", decimals, small, gettext(sizestrs[ii]));
80}
81
82gboolean
83mkdir_p(const char *name, mode_t mode) {
84  struct stat sb;
85  char *parent;
86  gboolean ret;
87  int oerrno;
88
89  if(0 != stat(name, &sb)) {
90    if(ENOENT != errno)
91      return FALSE;
92    parent = g_path_get_dirname(name);
93    ret = mkdir_p(parent, mode);
94    oerrno = errno;
95    g_free(parent);
96    errno = oerrno;
97    return (ret ? (0 == mkdir(name, mode)) : FALSE);
98  }
99
100  if(!S_ISDIR(sb.st_mode)) {
101    errno = ENOTDIR;
102    return FALSE;
103  }
104
105  return TRUE;
106}
107
108static int exit_sigs[] = {SIGHUP, SIGINT, SIGQUIT, SIGTERM, SIGUSR1, SIGUSR2};
109static callbackfunc_t exit_func = NULL;
110static void *exit_data = NULL;
111static int exit_block_level = 0;
112
113void
114setuphandlers(callbackfunc_t func, void *data) {
115  struct sigaction sa;
116  unsigned int ii;
117
118  exit_data = data;
119  exit_func = func;
120
121  bzero(&sa, sizeof(sa));
122  sa.sa_handler = sigexithandler;
123  for(ii = 0; ii < ALEN(exit_sigs); ii++)
124    sigaction(exit_sigs[ii], &sa, NULL);
125}
126
127void
128clearhandlers(void) {
129  struct sigaction sa;
130  unsigned int ii;
131
132  bzero(&sa, sizeof(sa));
133  sa.sa_handler = SIG_DFL;
134  for(ii = 0; ii < ALEN(exit_sigs); ii++)
135    sigaction(exit_sigs[ii], &sa, NULL);
136}
137
138static void
139sigexithandler(int sig) {
140  exit_func(exit_data);
141  clearhandlers();
142  raise(sig);
143}
144
145void
146blocksigs(void) {
147  sigset_t mask;
148  unsigned int ii;
149
150  if(0 < (exit_block_level++))
151    return;
152
153  sigemptyset(&mask);
154  for(ii = 0; ii < ALEN(exit_sigs); ii++)
155    sigaddset(&mask, exit_sigs[ii]);
156  sigprocmask(SIG_BLOCK, &mask, NULL);
157}
158
159void
160unblocksigs(void) {
161  sigset_t mask;
162  unsigned int ii;
163
164  if(0 < (--exit_block_level))
165    return;
166
167  sigemptyset(&mask);
168  for(ii = 0; ii < ALEN(exit_sigs); ii++)
169    sigaddset(&mask, exit_sigs[ii]);
170  sigprocmask(SIG_UNBLOCK, &mask, NULL);
171}
172
173GtkWidget *
174errmsg(GtkWindow *wind, const char *format, ...) {
175  GtkWidget *dialog;
176  va_list ap;
177
178  va_start(ap, format);
179  dialog = verrmsg(wind, NULL, NULL, format, ap);
180  va_end(ap);
181
182  return dialog;
183}
184
185GtkWidget *
186errmsg_full(GtkWindow *wind, callbackfunc_t func, void *data,
187            const char *format, ...) {
188  GtkWidget *dialog;
189  va_list ap;
190
191  va_start(ap, format);
192  dialog = verrmsg(wind, func, data, format, ap);
193  va_end(ap);
194
195  return dialog;
196}
197
198GtkWidget *
199verrmsg(GtkWindow *wind, callbackfunc_t func, void *data,
200        const char *format, va_list ap) {
201  GtkWidget *dialog;
202  char *msg;
203  GList *funcdata;
204
205  msg = g_strdup_vprintf(format, ap);
206
207  if(NULL == wind)
208    dialog = gtk_message_dialog_new(
209      NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "%s", msg);
210  else
211    dialog = gtk_message_dialog_new(wind,
212      GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
213      GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "%s", msg);
214
215  if(NULL == func)
216    funcdata = NULL;
217  else
218    funcdata = g_list_append(g_list_append(NULL, func), data);
219  g_signal_connect(dialog, "response", G_CALLBACK(errcb), funcdata);
220  if(NULL != wind)
221    gtk_widget_show(dialog);
222  g_free(msg);
223
224  return dialog;
225}
226
227static void
228errcb(GtkWidget *widget, int resp SHUTUP, gpointer data) {
229  GList *funcdata;
230  callbackfunc_t func;
231
232  if(NULL != data) {
233    funcdata = g_list_first(data);
234    func = funcdata->data;
235    data = funcdata->next->data;
236    func(data);
237    g_list_free(funcdata);
238  }
239
240  gtk_widget_destroy(widget);
241}
Note: See TracBrowser for help on using the repository browser.