Mercurial > pidgin.yaz
annotate src/status.c @ 8705:543b19a96ac5
[gaim-migrate @ 9458]
" All preferences in gaim, except for "No sounds when you
log in", are "positive" preferences. For consistency
and to make it a bit easier to understand the
preference I think they should all be "positive"
preferences (there's probably something about this in
some HIG somewhere too)
This patch:
1. changes "No sounds when you log in" to "Sounds when
you log in"
2. adds a helper function for renaming old boolean
prefs and inverting their meaning
(gaim_prefs_rename_boolean_toggle)
3. Moves existing renames from prefs.c to gtkprefs.c
because they all reference gtk preferences.
Default behaviour for new users remains the same (no
sounds during log in), and existing user's preferences
are migrated correctly." --Stu Tomlinson
at one point possitive preferences were policy, i think we should maintain that policy.
committer: Tailor Script <tailor@pidgin.im>
author | Luke Schierer <lschiere@pidgin.im> |
---|---|
date | Sun, 18 Apr 2004 19:30:19 +0000 |
parents | 1a016d979ce0 |
children | 4d05b6e9e9cd |
rev | line source |
---|---|
6065 | 1 /* |
2 * gaim | |
3 * | |
8046 | 4 * Gaim is the legal property of its developers, whose names are too numerous |
5 * to list here. Please refer to the COPYRIGHT file distributed with this | |
6 * source distribution. | |
6065 | 7 * |
8 * This program is free software; you can redistribute it and/or modify | |
9 * it under the terms of the GNU General Public License as published by | |
10 * the Free Software Foundation; either version 2 of the License, or | |
11 * (at your option) any later version. | |
12 * | |
13 * This program is distributed in the hope that it will be useful, | |
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 * GNU General Public License for more details. | |
17 * | |
18 * You should have received a copy of the GNU General Public License | |
19 * along with this program; if not, write to the Free Software | |
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
21 */ | |
22 | |
23 #include "status.h" | |
24 #include "internal.h" | |
25 #include "debug.h" | |
26 #include "util.h" | |
27 | |
6371
8f94cce8faa5
[gaim-migrate @ 6876]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
28 /* XXX CORE/UI */ |
8f94cce8faa5
[gaim-migrate @ 6876]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
29 #include "gtkinternal.h" |
8f94cce8faa5
[gaim-migrate @ 6876]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
30 #include "ui.h" |
8f94cce8faa5
[gaim-migrate @ 6876]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
31 |
8f94cce8faa5
[gaim-migrate @ 6876]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
32 |
6065 | 33 /* for people like myself who are too lazy to add an away msg :) */ |
34 /* I don't know who "myself" is in this context. The exclamation point | |
35 * makes it slightly less boring ;) */ | |
36 #define BORING_DEFAULT_AWAY_MSG _("Sorry, I ran out for a bit!") | |
37 | |
38 /* XML File Saving */ | |
39 | |
40 /* All of this code is adapted from Nathan Walp's. It's adapted all over the place | |
41 * for accounts, the buddy list, pounces, preferences, and the likes. It would be | |
42 * neat if we could somehow make this more generic. */ | |
43 static gboolean status_loaded = FALSE; | |
44 static guint status_save_timer = 0; | |
45 | |
46 | |
47 typedef enum | |
48 { | |
49 TAG_NONE = 0, | |
50 TAG_STATUS, | |
51 TAG_STATE, | |
52 TAG_MESSAGE, | |
53 | |
54 } StatusParserTag; | |
55 | |
56 | |
57 typedef struct | |
58 { | |
59 StatusParserTag tag; | |
60 GString *buffer; | |
61 struct away_message *am; | |
62 | |
63 } StatusParserData; | |
64 | |
65 static void | |
66 free_parser_data(gpointer user_data) | |
67 { | |
68 StatusParserData *data = user_data; | |
69 | |
70 if (data->buffer != NULL) | |
71 g_string_free(data->buffer, TRUE); | |
72 | |
73 g_free(data); | |
74 } | |
75 | |
76 static void gaim_status_write(FILE *fp, struct away_message *am) | |
77 { | |
78 char *esc = NULL; | |
6216 | 79 |
6065 | 80 esc = g_markup_escape_text(am->name, -1); |
6216 | 81 fprintf(fp, "\t<status name=\"%s\">\n", esc); |
6065 | 82 g_free(esc); |
83 | |
6216 | 84 fprintf(fp, "\t\t<state>away</state>\n"); |
85 | |
86 esc = g_markup_escape_text(am->message, -1); | |
87 fprintf(fp, "\t\t<message>%s</message>\n", esc); | |
88 g_free(esc); | |
89 | |
90 fprintf(fp, "\t</status>\n"); | |
6065 | 91 } |
92 | |
93 static gboolean | |
94 status_save_cb(gpointer unused) | |
95 { | |
96 gaim_status_sync(); | |
97 status_save_timer = 0; | |
98 | |
99 return FALSE; | |
100 } | |
101 | |
102 static void | |
103 schedule_status_save() | |
104 { | |
105 if (!status_save_timer) | |
8273
f24172f53650
[gaim-migrate @ 8997]
Christian Hammond <chipx86@chipx86.com>
parents:
8046
diff
changeset
|
106 status_save_timer = gaim_timeout_add(5000, status_save_cb, NULL); |
6065 | 107 } |
108 | |
109 static void | |
110 start_element_handler(GMarkupParseContext *context, | |
111 const gchar *element_name, | |
112 const gchar **attribute_names, | |
113 const gchar **attribute_values, | |
114 gpointer user_data, GError **error) | |
115 { | |
116 const char *value; | |
117 StatusParserData *data = user_data; | |
118 GHashTable *atts; | |
119 int i; | |
120 | |
121 atts = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); | |
122 | |
123 for (i = 0; attribute_names[i] != NULL; i++) { | |
124 g_hash_table_insert(atts, g_strdup(attribute_names[i]), | |
125 g_strdup(attribute_values[i])); | |
126 } | |
127 | |
128 if (data->buffer != NULL) { | |
129 g_string_free(data->buffer, TRUE); | |
130 data->buffer = NULL; | |
131 } | |
132 | |
133 if (!strcmp(element_name, "status")) { | |
134 data->tag = TAG_STATUS; | |
135 if ((value = g_hash_table_lookup(atts, "name")) != NULL) { | |
136 data->am = g_new0(struct away_message, 1); | |
137 g_snprintf(data->am->name, sizeof(data->am->name), "%s", value); | |
138 away_messages = g_slist_append(away_messages, data->am); | |
139 } | |
140 } else if (!strcmp(element_name, "message")) { | |
141 data->tag = TAG_MESSAGE; | |
6216 | 142 |
6065 | 143 } |
6113 | 144 |
145 g_hash_table_destroy(atts); | |
6065 | 146 } |
147 | |
148 static void | |
149 end_element_handler(GMarkupParseContext *context, const gchar *element_name, | |
150 gpointer user_data, GError **error) | |
151 { | |
152 StatusParserData *data = user_data; | |
153 gchar *buffer; | |
154 | |
155 if (data->buffer == NULL) | |
156 return; | |
157 | |
158 buffer = g_string_free(data->buffer, FALSE); | |
159 data->buffer = NULL; | |
160 | |
161 if (data->tag == TAG_MESSAGE) { | |
162 if (*buffer != '\0') | |
163 g_snprintf(data->am->message, sizeof(data->am->message), "%s", buffer); | |
164 } | |
165 | |
166 data->tag = TAG_NONE; | |
167 | |
168 g_free(buffer); | |
169 } | |
170 | |
171 static void | |
172 text_handler(GMarkupParseContext *context, const gchar *text, | |
173 gsize text_len, gpointer user_data, GError **error) | |
174 { | |
175 StatusParserData *data = user_data; | |
176 | |
177 if (data->buffer == NULL) | |
178 data->buffer = g_string_new_len(text, text_len); | |
179 else | |
180 g_string_append_len(data->buffer, text, text_len); | |
181 } | |
182 | |
183 static GMarkupParser status_parser = | |
184 { | |
185 start_element_handler, | |
186 end_element_handler, | |
187 text_handler, | |
188 NULL, | |
189 NULL | |
190 }; | |
191 | |
192 void gaim_status_sync() | |
193 { | |
194 FILE *fp; | |
195 const char *user_dir = gaim_user_dir(); | |
196 char *filename, *filename_real; | |
197 | |
198 if (!status_loaded) { | |
199 gaim_debug(GAIM_DEBUG_WARNING, "status", "Writing status to disk.\n"); | |
200 schedule_status_save(); | |
201 return; | |
202 } | |
203 | |
204 if (user_dir == NULL) | |
205 return; | |
206 | |
207 gaim_debug(GAIM_DEBUG_INFO, "status", "Saving statuses to disk\n"); | |
208 | |
209 fp = fopen(user_dir, "r"); | |
210 | |
211 if (fp == NULL) | |
212 mkdir(user_dir, S_IRUSR | S_IWUSR | S_IXUSR); | |
213 else | |
214 fclose(fp); | |
215 | |
216 filename = g_build_filename(user_dir, "status.xml.save", NULL); | |
217 | |
218 if ((fp = fopen(filename, "w")) != NULL) { | |
219 GSList *l; | |
220 | |
221 fprintf(fp, "<?xml version='1.0' encoding='UTF-8' ?>\n\n"); | |
222 fprintf(fp, "<statuses>\n"); | |
223 | |
224 for (l = away_messages; l != NULL; l = l->next) | |
225 gaim_status_write(fp, l->data); | |
226 | |
227 fprintf(fp, "</statuses>\n"); | |
228 | |
229 fclose(fp); | |
230 chmod(filename, S_IRUSR | S_IWUSR); | |
231 } | |
232 else { | |
233 gaim_debug(GAIM_DEBUG_ERROR, "status", "Unable to write %s\n", | |
234 filename); | |
8549 | 235 g_free(filename); |
236 return; | |
6065 | 237 } |
238 | |
239 filename_real = g_build_filename(user_dir, "status.xml", NULL); | |
240 | |
241 if (rename(filename, filename_real) < 0) { | |
242 gaim_debug(GAIM_DEBUG_ERROR, "status", "Error renaming %s to %s\n", | |
243 filename, filename_real); | |
244 } | |
245 | |
246 g_free(filename); | |
247 g_free(filename_real); | |
248 | |
249 } | |
250 | |
251 void gaim_status_load() | |
252 { | |
253 gchar *filename = g_build_filename(gaim_user_dir(), "status.xml", NULL); | |
254 gchar *contents = NULL; | |
255 gsize length; | |
256 GMarkupParseContext *context; | |
257 GError *error = NULL; | |
258 StatusParserData *parser_data; | |
259 | |
260 if (filename == NULL) { | |
261 status_loaded = TRUE; | |
262 return; | |
263 } | |
264 | |
265 if (!g_file_get_contents(filename, &contents, &length, &error)) { | |
266 gaim_debug(GAIM_DEBUG_ERROR, "status", | |
267 "Error reading statuses: %s\n", error->message); | |
268 g_error_free(error); | |
269 g_free(filename); | |
270 status_loaded = TRUE; | |
271 if (!away_messages) { | |
272 struct away_message *a = g_new0(struct away_message, 1); | |
273 g_snprintf(a->name, sizeof(a->name), _("Slightly less boring default")); | |
6321 | 274 g_snprintf(a->message, sizeof(a->message), "%s", _(BORING_DEFAULT_AWAY_MSG)); |
6065 | 275 away_messages = g_slist_append(away_messages, a); |
276 } | |
277 return; | |
278 } | |
279 | |
280 parser_data = g_new0(StatusParserData, 1); | |
281 | |
282 context = g_markup_parse_context_new(&status_parser, 0, | |
283 parser_data, free_parser_data); | |
284 | |
285 if (!g_markup_parse_context_parse(context, contents, length, NULL)) { | |
286 g_markup_parse_context_free(context); | |
287 g_free(contents); | |
288 g_free(filename); | |
289 status_loaded = TRUE; | |
290 return; | |
291 } | |
292 | |
293 if (!g_markup_parse_context_end_parse(context, NULL)) { | |
294 gaim_debug(GAIM_DEBUG_ERROR, "status", "Error parsing %s\n", | |
295 filename); | |
296 g_markup_parse_context_free(context); | |
297 g_free(contents); | |
298 g_free(filename); | |
299 status_loaded = TRUE; | |
300 return; | |
301 } | |
302 | |
303 g_markup_parse_context_free(context); | |
304 g_free(contents); | |
305 g_free(filename); | |
306 status_loaded = TRUE; | |
307 return; | |
308 } |