~ubuntu-branches/ubuntu/dapper/gworldclock/dapper

« back to all changes in this revision

Viewing changes to options.c

  • Committer: Bazaar Package Importer
  • Author(s): Drew Parsons
  • Date: 2003-12-23 15:31:20 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20031223153120-1drxus7uk82vk4by
Tags: 1.3-2
Build-depends: libxml2-dev. Closes: #224865.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Processes user options from the command line or from the option file
 
2
~/.gworldclock.
 
3
 
 
4
.gworldclock is an XML file, with default structure:
 
5
 
 
6
<?xml version="1.0"?>
 
7
<gworldclock>
 
8
  <timeDisplayFormat>%c</timeDisplayFormat>
 
9
</gworldclock>
 
10
 
 
11
Currently only <timeDisplayFormat> is used, containing the date format string
 
12
used to display data&time.
 
13
 
 
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.
 
17
 
 
18
*/
 
19
 
 
20
 
 
21
 
 
22
 
 
23
#include <unistd.h> /* getopt */
 
24
#include <gtk/gtk.h>
 
25
#include <libxml/parser.h>
 
26
#include <libintl.h>
 
27
 
 
28
#include "timer.h"
 
29
 
 
30
#define _(A) gettext(A)
 
31
 
 
32
#define LOCALE_DEFAULT_DISPLAY "%c"
 
33
#define SHORT_DISPLAY "%x %l:%M%P"
 
34
#define SHORT_DISPLAY_24HOUR "%x %R"
 
35
 
 
36
gchar *defaultOptionFile=".gworldclock";
 
37
gchar *defaultConfigFilename=".tzlist";
 
38
gchar *defaultTimeDisplayFormat = LOCALE_DEFAULT_DISPLAY;
 
39
 
 
40
 
 
41
gboolean changedPreferences = FALSE;
 
42
GtkEntry *rollYourOwnDisplayFormat=NULL;
 
43
 
 
44
GString *oldTimeDisplayFormat;
 
45
 
 
46
#define XMLVERSION  "1.0"
 
47
#define ROOT_NODE   "gworldclock"
 
48
#define TIME_DISPLAY_FORMAT_NODE "timeDisplayFormat"
 
49
 
 
50
GString *getTimeDisplayFormat( xmlDocPtr optionXML )
 
51
{
 
52
   GString *format=NULL;
 
53
   xmlNodePtr cur;
 
54
   xmlChar *formatText;
 
55
 
 
56
   cur = xmlDocGetRootElement(optionXML);
 
57
   if (cur != NULL) 
 
58
   {
 
59
      if (xmlStrcmp(cur->name, ROOT_NODE)) {
 
60
         fprintf(stderr,"Options file incorrectly formatted\n");
 
61
         return NULL;
 
62
      }
 
63
      
 
64
      cur = cur->xmlChildrenNode;
 
65
      while ( (cur != NULL) && (format==NULL) ) 
 
66
      {
 
67
         if ((!xmlStrcmp(cur->name, TIME_DISPLAY_FORMAT_NODE))) 
 
68
         {
 
69
            formatText = xmlNodeListGetString(optionXML, 
 
70
                                              cur->xmlChildrenNode, 1);
 
71
            format = g_string_new(formatText);
 
72
            xmlFree(formatText);
 
73
         }
 
74
         cur = cur->next;
 
75
      }
 
76
 
 
77
   }   
 
78
 
 
79
   return format;
 
80
}
 
81
 
 
82
void GetOptions( int argc, char **argv )
 
83
{
 
84
  extern GString *configfile, *displayFormat, *optionFile;
 
85
  int c;
 
86
  xmlDocPtr optionXML;
 
87
  GString *temp;
 
88
 
 
89
 
 
90
  /* set defaults */
 
91
  configfile = g_string_new(g_strdup((gchar *) getenv("HOME")));  
 
92
  g_string_append(configfile,"/");
 
93
  g_string_append(configfile,defaultConfigFilename);
 
94
 
 
95
  displayFormat = g_string_new( g_strdup( defaultTimeDisplayFormat ) );
 
96
 
 
97
 
 
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 )
 
104
  {
 
105
     temp = getTimeDisplayFormat(optionXML);
 
106
     xmlFreeDoc(optionXML);
 
107
 
 
108
     if ( temp != NULL ) 
 
109
     {
 
110
        g_string_free( displayFormat, TRUE );
 
111
        displayFormat = temp;
 
112
     }
 
113
  }
 
114
 
 
115
 
 
116
  /* set command line options */
 
117
  while ((c = getopt (argc, argv, "f:")) != -1)
 
118
     switch (c) 
 
119
     {
 
120
        case 'f':
 
121
           configfile = g_string_new(g_strdup((gchar *)optarg));  
 
122
           break;
 
123
           
 
124
        default:
 
125
        break;
 
126
     }
 
127
}
 
128
 
 
129
/* save options to options file (default ~/.gworldclock) 
 
130
   - creates the file if it does not already exist
 
131
*/
 
132
gint SaveOptions()
 
133
{
 
134
   extern GString *optionFile, *displayFormat;
 
135
   xmlDocPtr optionXML;
 
136
   xmlNodePtr root, cur, foundNode=NULL;
 
137
   xmlChar *formatText;
 
138
   gint save = FALSE;
 
139
 
 
140
   optionXML = xmlParseFile( optionFile->str );
 
141
   if ( optionXML==NULL ) /* create new document */
 
142
   {
 
143
      optionXML = xmlNewDoc(XMLVERSION);
 
144
      root = xmlNewDocRawNode( optionXML, NULL, ROOT_NODE, NULL ); 
 
145
      xmlDocSetRootElement( optionXML, root );
 
146
   }
 
147
   else
 
148
   {
 
149
      root = xmlDocGetRootElement(optionXML);
 
150
   }
 
151
   
 
152
   cur = root->xmlChildrenNode;
 
153
   while ( (cur != NULL) && (foundNode==NULL) ) 
 
154
   {
 
155
      if ((!xmlStrcmp(cur->name, TIME_DISPLAY_FORMAT_NODE))) 
 
156
      {
 
157
         foundNode=cur;
 
158
      }
 
159
      cur = cur->next;
 
160
   }
 
161
 
 
162
   if (foundNode==NULL)
 
163
   {
 
164
      save = TRUE;
 
165
      foundNode = xmlNewTextChild( root, NULL, 
 
166
                                   TIME_DISPLAY_FORMAT_NODE,
 
167
                                   displayFormat->str );
 
168
   }
 
169
   else
 
170
   {
 
171
      formatText = xmlNodeListGetString(optionXML, 
 
172
                                        foundNode->xmlChildrenNode, 1);
 
173
      if(strcasecmp(formatText,displayFormat->str))
 
174
      {
 
175
         save = TRUE;
 
176
         xmlNodeSetContent( foundNode, displayFormat->str );
 
177
      }
 
178
      xmlFree(formatText);
 
179
   }
 
180
 
 
181
   if (save)
 
182
   {
 
183
      xmlSaveFormatFile( optionFile->str, optionXML, 1 );
 
184
   }
 
185
 
 
186
   xmlFreeDoc(optionXML);
 
187
   
 
188
   return 1;
 
189
}
 
190
 
 
191
void StoreOldPreferences()
 
192
{
 
193
   extern GString *displayFormat;
 
194
   if ( oldTimeDisplayFormat == NULL )
 
195
   {
 
196
      oldTimeDisplayFormat = g_string_new( displayFormat->str);
 
197
   }
 
198
   else
 
199
   {
 
200
      oldTimeDisplayFormat = g_string_assign( oldTimeDisplayFormat, 
 
201
                                              displayFormat->str);
 
202
   }
 
203
}
 
204
 
 
205
void RestoreOldPreferences()
 
206
{
 
207
   extern GString *displayFormat;
 
208
   if ( ! g_string_equal( displayFormat, oldTimeDisplayFormat ) )
 
209
   {
 
210
      displayFormat = g_string_assign( displayFormat, 
 
211
                                       oldTimeDisplayFormat->str);
 
212
      changedPreferences = TRUE;
 
213
   }
 
214
}
 
215
 
 
216
/* Updates the user's preferences. */ 
 
217
void ProcessPreferences( GObject *owner )
 
218
{
 
219
   extern GString *displayFormat;
 
220
   GString *newDisplayFormat;
 
221
   GSList *radioGroup;
 
222
   GtkEntry *entry;
 
223
 
 
224
   radioGroup =  gtk_radio_button_get_group( 
 
225
      g_object_get_data(owner, "radioDisplayFormat") );
 
226
 
 
227
   while( radioGroup != NULL )
 
228
   {
 
229
      if ( gtk_toggle_button_get_active(
 
230
              GTK_TOGGLE_BUTTON(radioGroup->data) ) )
 
231
      {
 
232
         newDisplayFormat = g_string_new( 
 
233
            g_object_get_data( G_OBJECT(radioGroup->data),
 
234
                               "displayFormat" ) );
 
235
         break;
 
236
      }
 
237
      else
 
238
         radioGroup = radioGroup->next;
 
239
   }
 
240
 
 
241
   if (!strcmp(newDisplayFormat->str, "rollYourOwn") )
 
242
   {
 
243
      entry = g_object_get_data(owner, "entryRollYourOwnDisplayFormat");
 
244
      newDisplayFormat = g_string_assign( newDisplayFormat, 
 
245
                                        gtk_entry_get_text( entry ) );
 
246
   }
 
247
 
 
248
   if ( ! g_string_equal( displayFormat, newDisplayFormat ) )
 
249
   {
 
250
      displayFormat = g_string_assign( displayFormat, 
 
251
                                       newDisplayFormat->str);
 
252
      changedPreferences = TRUE;
 
253
   }
 
254
   g_string_free( newDisplayFormat, TRUE );
 
255
}
 
256
 
 
257
void SavePreferences()
 
258
{
 
259
   extern GString *displayFormat;
 
260
 
 
261
   if (changedPreferences)
 
262
   {
 
263
      SaveOptions();
 
264
      changedPreferences = FALSE;
 
265
   }
 
266
}
 
267
 
 
268
void ProcessPreferenceResponse( GtkDialog *dialog,
 
269
                         gint response,
 
270
                         gpointer clocklist)
 
271
{
 
272
   switch (response)
 
273
   {
 
274
      case GTK_RESPONSE_OK:
 
275
         /* process preferences and close */
 
276
         ProcessPreferences(G_OBJECT(dialog));
 
277
         SavePreferences();
 
278
         gtk_widget_destroy(GTK_WIDGET(dialog));
 
279
         break;
 
280
      case GTK_RESPONSE_APPLY:
 
281
         /* process preferences, keep dialog box open */
 
282
         ProcessPreferences(G_OBJECT(dialog));
 
283
         break;
 
284
      case GTK_RESPONSE_CLOSE:
 
285
      case GTK_RESPONSE_DELETE_EVENT:
 
286
         SavePreferences();
 
287
         gtk_widget_destroy(GTK_WIDGET(dialog));
 
288
         break;
 
289
      case GTK_RESPONSE_CANCEL:
 
290
         /* restore original preferences and close */
 
291
         RestoreOldPreferences();
 
292
         SavePreferences();
 
293
         gtk_widget_destroy (GTK_WIDGET(dialog));
 
294
         break;
 
295
      default:
 
296
         /* unknown response, do nothing */
 
297
         break;
 
298
   }
 
299
}
 
300
 
 
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
 
307
   "displayFormat".
 
308
*/
 
309
void SetDisplayAlternatives( GtkContainer *container, GObject *owner )
 
310
{
 
311
   extern GString *displayFormat;
 
312
 
 
313
   GtkWidget *radio, *entry;
 
314
   gboolean foundFormat = FALSE;
 
315
   GString *text;
 
316
   time_t currenttime;
 
317
   struct tm *tm;
 
318
   char rawTimeDisplay[TIME_DISPLAY_SIZE];
 
319
   gchar *timeDisplay;
 
320
 
 
321
   time(&currenttime);
 
322
   tm = (struct tm *) localtime( (time_t *) &currenttime );
 
323
 
 
324
   strftime (rawTimeDisplay, TIME_DISPLAY_SIZE, 
 
325
             LOCALE_DEFAULT_DISPLAY, 
 
326
             tm      );
 
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) )
 
339
   {
 
340
      gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(radio), TRUE );
 
341
      foundFormat = TRUE;
 
342
   }
 
343
   g_free( timeDisplay );
 
344
   g_string_free(text, TRUE);
 
345
   g_object_set_data( owner, "radioDisplayFormat", (gpointer) radio );
 
346
 
 
347
   strftime (rawTimeDisplay, TIME_DISPLAY_SIZE, 
 
348
             SHORT_DISPLAY, 
 
349
             tm      );
 
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", 
 
359
                      SHORT_DISPLAY );
 
360
   gtk_container_add ( container, radio);
 
361
   if( ! strcmp(displayFormat->str,  SHORT_DISPLAY) )
 
362
   {
 
363
      gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(radio), TRUE );
 
364
      foundFormat = TRUE;
 
365
   }
 
366
   g_free( timeDisplay );
 
367
   g_string_free(text, TRUE);
 
368
 
 
369
   strftime (rawTimeDisplay, TIME_DISPLAY_SIZE, 
 
370
             SHORT_DISPLAY_24HOUR, 
 
371
             tm      );
 
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) )
 
384
   {
 
385
      gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(radio), TRUE );
 
386
      foundFormat = TRUE;
 
387
   }
 
388
   g_free( timeDisplay );
 
389
   g_string_free(text, TRUE);
 
390
 
 
391
 
 
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", 
 
395
                      "rollYourOwn" );
 
396
   gtk_container_add ( container, radio);
 
397
   g_string_free(text, TRUE);
 
398
 
 
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);
 
407
   if( ! foundFormat )
 
408
      gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(radio), TRUE );
 
409
}
 
410
 
 
411
 
 
412
/* dialog box allows user to set preferences
 
413
   e.g. preferred display format for time and date */
 
414
void ChangePreferences(gpointer clocklist)
 
415
{
 
416
   GtkWidget *dialog, *frame, *box;
 
417
 
 
418
   StoreOldPreferences();
 
419
   dialog = gtk_dialog_new_with_buttons (_("Preferences"),
 
420
                                         NULL,
 
421
                                         GTK_DIALOG_DESTROY_WITH_PARENT,
 
422
                                         GTK_STOCK_OK,
 
423
                                         GTK_RESPONSE_OK,
 
424
                                         GTK_STOCK_APPLY,
 
425
                                         GTK_RESPONSE_APPLY,
 
426
                                         GTK_STOCK_CLOSE,
 
427
                                         GTK_RESPONSE_CLOSE,
 
428
                                         GTK_STOCK_REVERT_TO_SAVED,
 
429
                                         GTK_RESPONSE_CANCEL,
 
430
                                         NULL);
 
431
   g_signal_connect (GTK_OBJECT (dialog),
 
432
                     "response",
 
433
                     G_CALLBACK (ProcessPreferenceResponse),
 
434
                     (gpointer)clocklist);
 
435
   
 
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),
 
441
                      frame);
 
442
 
 
443
   gtk_widget_show_all (dialog);
 
444
}