1
/* Processes user options from the command line or from the option file
4
.gworldclock is an XML file, with default structure:
8
<timeDisplayFormat>%c</timeDisplayFormat>
11
Currently only <timeDisplayFormat> is used, containing the date format string
12
used to display data&time.
14
In case you were wondering whether name/value pairs would have been simpler
15
than XML for storing user options, my simple response is that I wanted to learn
16
how to use XML from within C.
23
#include <unistd.h> /* getopt */
25
#include <libxml/parser.h>
30
#define _(A) gettext(A)
32
#define LOCALE_DEFAULT_DISPLAY "%c"
33
#define SHORT_DISPLAY "%x %l:%M%P"
34
#define SHORT_DISPLAY_24HOUR "%x %R"
36
gchar *defaultOptionFile=".gworldclock";
37
gchar *defaultConfigFilename=".tzlist";
38
gchar *defaultTimeDisplayFormat = LOCALE_DEFAULT_DISPLAY;
41
gboolean changedPreferences = FALSE;
42
GtkEntry *rollYourOwnDisplayFormat=NULL;
44
GString *oldTimeDisplayFormat;
46
#define XMLVERSION "1.0"
47
#define ROOT_NODE "gworldclock"
48
#define TIME_DISPLAY_FORMAT_NODE "timeDisplayFormat"
50
GString *getTimeDisplayFormat( xmlDocPtr optionXML )
56
cur = xmlDocGetRootElement(optionXML);
59
if (xmlStrcmp(cur->name, ROOT_NODE)) {
60
fprintf(stderr,"Options file incorrectly formatted\n");
64
cur = cur->xmlChildrenNode;
65
while ( (cur != NULL) && (format==NULL) )
67
if ((!xmlStrcmp(cur->name, TIME_DISPLAY_FORMAT_NODE)))
69
formatText = xmlNodeListGetString(optionXML,
70
cur->xmlChildrenNode, 1);
71
format = g_string_new(formatText);
82
void GetOptions( int argc, char **argv )
84
extern GString *configfile, *displayFormat, *optionFile;
91
configfile = g_string_new(g_strdup((gchar *) getenv("HOME")));
92
g_string_append(configfile,"/");
93
g_string_append(configfile,defaultConfigFilename);
95
displayFormat = g_string_new( g_strdup( defaultTimeDisplayFormat ) );
98
/* read configuration options from file */
99
optionFile = g_string_new(g_strdup((gchar *) getenv("HOME")));
100
g_string_append(optionFile,"/");
101
g_string_append(optionFile,defaultOptionFile);
102
optionXML = xmlParseFile( optionFile->str );
103
if ( optionXML!=NULL )
105
temp = getTimeDisplayFormat(optionXML);
106
xmlFreeDoc(optionXML);
110
g_string_free( displayFormat, TRUE );
111
displayFormat = temp;
116
/* set command line options */
117
while ((c = getopt (argc, argv, "f:")) != -1)
121
configfile = g_string_new(g_strdup((gchar *)optarg));
129
/* save options to options file (default ~/.gworldclock)
130
- creates the file if it does not already exist
134
extern GString *optionFile, *displayFormat;
136
xmlNodePtr root, cur, foundNode=NULL;
140
optionXML = xmlParseFile( optionFile->str );
141
if ( optionXML==NULL ) /* create new document */
143
optionXML = xmlNewDoc(XMLVERSION);
144
root = xmlNewDocRawNode( optionXML, NULL, ROOT_NODE, NULL );
145
xmlDocSetRootElement( optionXML, root );
149
root = xmlDocGetRootElement(optionXML);
152
cur = root->xmlChildrenNode;
153
while ( (cur != NULL) && (foundNode==NULL) )
155
if ((!xmlStrcmp(cur->name, TIME_DISPLAY_FORMAT_NODE)))
165
foundNode = xmlNewTextChild( root, NULL,
166
TIME_DISPLAY_FORMAT_NODE,
167
displayFormat->str );
171
formatText = xmlNodeListGetString(optionXML,
172
foundNode->xmlChildrenNode, 1);
173
if(strcasecmp(formatText,displayFormat->str))
176
xmlNodeSetContent( foundNode, displayFormat->str );
183
xmlSaveFormatFile( optionFile->str, optionXML, 1 );
186
xmlFreeDoc(optionXML);
191
void StoreOldPreferences()
193
extern GString *displayFormat;
194
if ( oldTimeDisplayFormat == NULL )
196
oldTimeDisplayFormat = g_string_new( displayFormat->str);
200
oldTimeDisplayFormat = g_string_assign( oldTimeDisplayFormat,
205
void RestoreOldPreferences()
207
extern GString *displayFormat;
208
if ( ! g_string_equal( displayFormat, oldTimeDisplayFormat ) )
210
displayFormat = g_string_assign( displayFormat,
211
oldTimeDisplayFormat->str);
212
changedPreferences = TRUE;
216
/* Updates the user's preferences. */
217
void ProcessPreferences( GObject *owner )
219
extern GString *displayFormat;
220
GString *newDisplayFormat;
224
radioGroup = gtk_radio_button_get_group(
225
g_object_get_data(owner, "radioDisplayFormat") );
227
while( radioGroup != NULL )
229
if ( gtk_toggle_button_get_active(
230
GTK_TOGGLE_BUTTON(radioGroup->data) ) )
232
newDisplayFormat = g_string_new(
233
g_object_get_data( G_OBJECT(radioGroup->data),
238
radioGroup = radioGroup->next;
241
if (!strcmp(newDisplayFormat->str, "rollYourOwn") )
243
entry = g_object_get_data(owner, "entryRollYourOwnDisplayFormat");
244
newDisplayFormat = g_string_assign( newDisplayFormat,
245
gtk_entry_get_text( entry ) );
248
if ( ! g_string_equal( displayFormat, newDisplayFormat ) )
250
displayFormat = g_string_assign( displayFormat,
251
newDisplayFormat->str);
252
changedPreferences = TRUE;
254
g_string_free( newDisplayFormat, TRUE );
257
void SavePreferences()
259
extern GString *displayFormat;
261
if (changedPreferences)
264
changedPreferences = FALSE;
268
void ProcessPreferenceResponse( GtkDialog *dialog,
274
case GTK_RESPONSE_OK:
275
/* process preferences and close */
276
ProcessPreferences(G_OBJECT(dialog));
278
gtk_widget_destroy(GTK_WIDGET(dialog));
280
case GTK_RESPONSE_APPLY:
281
/* process preferences, keep dialog box open */
282
ProcessPreferences(G_OBJECT(dialog));
284
case GTK_RESPONSE_CLOSE:
285
case GTK_RESPONSE_DELETE_EVENT:
287
gtk_widget_destroy(GTK_WIDGET(dialog));
289
case GTK_RESPONSE_CANCEL:
290
/* restore original preferences and close */
291
RestoreOldPreferences();
293
gtk_widget_destroy (GTK_WIDGET(dialog));
296
/* unknown response, do nothing */
301
/* Lays out the various display options,
302
as radio buttons inside the container.
303
A reference to the Display Format radio buttons is stored in owner with
304
key "radioDisplayFormat".
305
The user's format Entry Box is stored under "entryRollYourOwnDisplayFormat".
306
The format string for each radio button is stored with it under key
309
void SetDisplayAlternatives( GtkContainer *container, GObject *owner )
311
extern GString *displayFormat;
313
GtkWidget *radio, *entry;
314
gboolean foundFormat = FALSE;
318
char rawTimeDisplay[TIME_DISPLAY_SIZE];
322
tm = (struct tm *) localtime( (time_t *) ¤ttime );
324
strftime (rawTimeDisplay, TIME_DISPLAY_SIZE,
325
LOCALE_DEFAULT_DISPLAY,
327
timeDisplay = g_locale_to_utf8 ( rawTimeDisplay,
328
-1, NULL, NULL, NULL );
329
text = g_string_new( _("Locale default") );
330
text = g_string_append_c( text, ' ' );
331
text = g_string_append( text, _("e.g.") );
332
text = g_string_append_c( text, ' ' );
333
text = g_string_append( text, timeDisplay );
334
radio = gtk_radio_button_new_with_label( NULL, text->str );
335
g_object_set_data( G_OBJECT(radio), "displayFormat",
336
LOCALE_DEFAULT_DISPLAY );
337
gtk_container_add ( container, radio);
338
if( ! strcmp(displayFormat->str, LOCALE_DEFAULT_DISPLAY) )
340
gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(radio), TRUE );
343
g_free( timeDisplay );
344
g_string_free(text, TRUE);
345
g_object_set_data( owner, "radioDisplayFormat", (gpointer) radio );
347
strftime (rawTimeDisplay, TIME_DISPLAY_SIZE,
350
timeDisplay = g_locale_to_utf8 ( rawTimeDisplay,
351
-1, NULL, NULL, NULL );
352
text = g_string_new( _("Short Form") );
353
text = g_string_append_c( text, ' ' );
354
text = g_string_append( text, _("e.g.") );
355
text = g_string_append_c( text, ' ' );
356
text = g_string_append( text, timeDisplay );
357
radio = gtk_radio_button_new_with_label_from_widget( GTK_RADIO_BUTTON(radio), text->str );
358
g_object_set_data( G_OBJECT(radio), "displayFormat",
360
gtk_container_add ( container, radio);
361
if( ! strcmp(displayFormat->str, SHORT_DISPLAY) )
363
gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(radio), TRUE );
366
g_free( timeDisplay );
367
g_string_free(text, TRUE);
369
strftime (rawTimeDisplay, TIME_DISPLAY_SIZE,
370
SHORT_DISPLAY_24HOUR,
372
timeDisplay = g_locale_to_utf8 ( rawTimeDisplay,
373
-1, NULL, NULL, NULL );
374
text = g_string_new( _("Short Form (24 Hour)") );
375
text = g_string_append_c( text, ' ' );
376
text = g_string_append( text, _("e.g.") );
377
text = g_string_append_c( text, ' ' );
378
text = g_string_append( text, timeDisplay );
379
radio = gtk_radio_button_new_with_label_from_widget( GTK_RADIO_BUTTON(radio), text->str );
380
g_object_set_data( G_OBJECT(radio), "displayFormat",
381
SHORT_DISPLAY_24HOUR );
382
gtk_container_add ( container, radio);
383
if( ! strcmp(displayFormat->str, SHORT_DISPLAY_24HOUR) )
385
gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(radio), TRUE );
388
g_free( timeDisplay );
389
g_string_free(text, TRUE);
392
text = g_string_new( _("Roll Your Own") );
393
radio = gtk_radio_button_new_with_label_from_widget( GTK_RADIO_BUTTON(radio), text->str );
394
g_object_set_data( G_OBJECT(radio), "displayFormat",
396
gtk_container_add ( container, radio);
397
g_string_free(text, TRUE);
399
entry = gtk_entry_new();
400
gtk_entry_set_width_chars( GTK_ENTRY(entry), 15 ); /* ignored! why?! ;( */
401
gtk_entry_set_text( GTK_ENTRY(entry), displayFormat->str );
402
gtk_container_add ( container, entry);
403
rollYourOwnDisplayFormat = GTK_ENTRY( entry );
404
gtk_widget_show (entry);
405
g_object_set_data( owner, "entryRollYourOwnDisplayFormat",
406
(gpointer) rollYourOwnDisplayFormat);
408
gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(radio), TRUE );
412
/* dialog box allows user to set preferences
413
e.g. preferred display format for time and date */
414
void ChangePreferences(gpointer clocklist)
416
GtkWidget *dialog, *frame, *box;
418
StoreOldPreferences();
419
dialog = gtk_dialog_new_with_buttons (_("Preferences"),
421
GTK_DIALOG_DESTROY_WITH_PARENT,
428
GTK_STOCK_REVERT_TO_SAVED,
431
g_signal_connect (GTK_OBJECT (dialog),
433
G_CALLBACK (ProcessPreferenceResponse),
434
(gpointer)clocklist);
436
frame = gtk_frame_new( _("Time Display Format") );
437
box = gtk_vbox_new( FALSE, 0 );
438
SetDisplayAlternatives( GTK_CONTAINER( box ), G_OBJECT(dialog) );
439
gtk_container_add (GTK_CONTAINER(frame), box);
440
gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox),
443
gtk_widget_show_all (dialog);