Mercurial > pidgin
annotate libgaim/stringref.c @ 15143:b81e4e44b509
[gaim-migrate @ 17929]
User Info and Tooltips now use the GaimNotifyUserInfo object and methods defined in notify.h. GaimNotifyUserInfo objects encapsulate a list of GaimNotifyUserInfoEntry objects, each of which may have a label, a value, and be specified to be a section header.
This moves the burden of UI generation of user information from the various prpls to the UI. The UI can choose how to display the information rather than being fenced into a particular HTML formatting. Consistency across the prpls' information presentation is now enforced, as well. gaim_notify_user_info_get_text_with_newline() generates text in the:
<b>label</b>: value
<b>label</b>: value
format as was passed by convention from prpls in the past.
committer: Tailor Script <tailor@pidgin.im>
author | Evan Schoenberg <evan.s@dreskin.net> |
---|---|
date | Sun, 10 Dec 2006 02:53:09 +0000 |
parents | 500a8f54354e |
children |
rev | line source |
---|---|
14192 | 1 /** |
2 * @file stringref.c Reference-counted immutable strings | |
3 * @ingroup core | |
4 * | |
5 * gaim | |
6 * | |
7 * Gaim is the legal property of its developers, whose names are too numerous | |
8 * to list here. Please refer to the COPYRIGHT file distributed with this | |
9 * source distribution. | |
10 * | |
11 * This program is free software; you can redistribute it and/or modify | |
12 * it under the terms of the GNU General Public License as published by | |
13 * the Free Software Foundation; either version 2 of the License, or | |
14 * (at your option) any later version. | |
15 * | |
16 * This program is distributed in the hope that it will be useful, | |
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
19 * GNU General Public License for more details. | |
20 * | |
21 * You should have received a copy of the GNU General Public License | |
22 * along with this program; if not, write to the Free Software | |
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
24 * | |
25 */ | |
26 | |
27 #include "internal.h" | |
28 | |
29 #include <string.h> | |
30 #include <stdarg.h> | |
31 | |
32 #include "debug.h" | |
33 #include "stringref.h" | |
34 | |
14926
500a8f54354e
[gaim-migrate @ 17698]
Richard Laager <rlaager@wiktel.com>
parents:
14192
diff
changeset
|
35 /** |
500a8f54354e
[gaim-migrate @ 17698]
Richard Laager <rlaager@wiktel.com>
parents:
14192
diff
changeset
|
36 * The internal representation of a stringref. |
500a8f54354e
[gaim-migrate @ 17698]
Richard Laager <rlaager@wiktel.com>
parents:
14192
diff
changeset
|
37 * |
500a8f54354e
[gaim-migrate @ 17698]
Richard Laager <rlaager@wiktel.com>
parents:
14192
diff
changeset
|
38 * @note For this structure to be useful, the string contained within |
500a8f54354e
[gaim-migrate @ 17698]
Richard Laager <rlaager@wiktel.com>
parents:
14192
diff
changeset
|
39 * it must be immutable -- for this reason, do _not_ access it |
500a8f54354e
[gaim-migrate @ 17698]
Richard Laager <rlaager@wiktel.com>
parents:
14192
diff
changeset
|
40 * directly! |
500a8f54354e
[gaim-migrate @ 17698]
Richard Laager <rlaager@wiktel.com>
parents:
14192
diff
changeset
|
41 */ |
500a8f54354e
[gaim-migrate @ 17698]
Richard Laager <rlaager@wiktel.com>
parents:
14192
diff
changeset
|
42 struct _GaimStringref { |
500a8f54354e
[gaim-migrate @ 17698]
Richard Laager <rlaager@wiktel.com>
parents:
14192
diff
changeset
|
43 guint32 ref; /**< The reference count of this string. |
500a8f54354e
[gaim-migrate @ 17698]
Richard Laager <rlaager@wiktel.com>
parents:
14192
diff
changeset
|
44 * Note that reference counts are only |
500a8f54354e
[gaim-migrate @ 17698]
Richard Laager <rlaager@wiktel.com>
parents:
14192
diff
changeset
|
45 * 31 bits, and the high-order bit |
500a8f54354e
[gaim-migrate @ 17698]
Richard Laager <rlaager@wiktel.com>
parents:
14192
diff
changeset
|
46 * indicates whether this string is up |
500a8f54354e
[gaim-migrate @ 17698]
Richard Laager <rlaager@wiktel.com>
parents:
14192
diff
changeset
|
47 * for GC at the next idle handler... |
500a8f54354e
[gaim-migrate @ 17698]
Richard Laager <rlaager@wiktel.com>
parents:
14192
diff
changeset
|
48 * But you aren't going to touch this |
500a8f54354e
[gaim-migrate @ 17698]
Richard Laager <rlaager@wiktel.com>
parents:
14192
diff
changeset
|
49 * anyway, right? */ |
500a8f54354e
[gaim-migrate @ 17698]
Richard Laager <rlaager@wiktel.com>
parents:
14192
diff
changeset
|
50 char value[1]; /**< The string contained in this ref. |
500a8f54354e
[gaim-migrate @ 17698]
Richard Laager <rlaager@wiktel.com>
parents:
14192
diff
changeset
|
51 * Notice that it is simply "hanging |
500a8f54354e
[gaim-migrate @ 17698]
Richard Laager <rlaager@wiktel.com>
parents:
14192
diff
changeset
|
52 * off the end" of the ref ... this |
500a8f54354e
[gaim-migrate @ 17698]
Richard Laager <rlaager@wiktel.com>
parents:
14192
diff
changeset
|
53 * is to save an allocation. */ |
500a8f54354e
[gaim-migrate @ 17698]
Richard Laager <rlaager@wiktel.com>
parents:
14192
diff
changeset
|
54 }; |
500a8f54354e
[gaim-migrate @ 17698]
Richard Laager <rlaager@wiktel.com>
parents:
14192
diff
changeset
|
55 |
14192 | 56 #define REFCOUNT(x) ((x) & 0x7fffffff) |
57 | |
58 static GList *gclist = NULL; | |
59 | |
60 static void stringref_free(GaimStringref *stringref); | |
61 static gboolean gs_idle_cb(gpointer data); | |
62 | |
63 GaimStringref *gaim_stringref_new(const char *value) | |
64 { | |
65 GaimStringref *newref; | |
66 | |
67 if (value == NULL) | |
68 return NULL; | |
69 | |
70 newref = g_malloc(sizeof(GaimStringref) + strlen(value)); | |
71 strcpy(newref->value, value); | |
72 newref->ref = 1; | |
73 | |
74 return newref; | |
75 } | |
76 | |
77 GaimStringref *gaim_stringref_new_noref(const char *value) | |
78 { | |
79 GaimStringref *newref; | |
80 | |
81 if (value == NULL) | |
82 return NULL; | |
83 | |
84 newref = g_malloc(sizeof(GaimStringref) + strlen(value)); | |
85 strcpy(newref->value, value); | |
86 newref->ref = 0x80000000; | |
87 | |
88 if (gclist == NULL) | |
89 g_idle_add(gs_idle_cb, NULL); | |
90 gclist = g_list_prepend(gclist, newref); | |
91 | |
92 return newref; | |
93 } | |
94 | |
95 GaimStringref *gaim_stringref_printf(const char *format, ...) | |
96 { | |
97 GaimStringref *newref; | |
98 va_list ap; | |
99 | |
100 if (format == NULL) | |
101 return NULL; | |
102 | |
103 va_start(ap, format); | |
104 newref = g_malloc(sizeof(GaimStringref) + g_printf_string_upper_bound(format, ap)); | |
105 vsprintf(newref->value, format, ap); | |
106 va_end(ap); | |
107 newref->ref = 1; | |
108 | |
109 return newref; | |
110 } | |
111 | |
112 GaimStringref *gaim_stringref_ref(GaimStringref *stringref) | |
113 { | |
114 if (stringref == NULL) | |
115 return NULL; | |
116 stringref->ref++; | |
117 return stringref; | |
118 } | |
119 | |
120 void gaim_stringref_unref(GaimStringref *stringref) | |
121 { | |
122 if (stringref == NULL) | |
123 return; | |
124 if (REFCOUNT(--(stringref->ref)) == 0) { | |
125 if (stringref->ref & 0x80000000) | |
126 gclist = g_list_remove(gclist, stringref); | |
127 stringref_free(stringref); | |
128 } | |
129 } | |
130 | |
131 const char *gaim_stringref_value(const GaimStringref *stringref) | |
132 { | |
133 return (stringref == NULL ? NULL : stringref->value); | |
134 } | |
135 | |
136 int gaim_stringref_cmp(const GaimStringref *s1, const GaimStringref *s2) | |
137 { | |
138 return (s1 == s2 ? 0 : strcmp(gaim_stringref_value(s1), gaim_stringref_value(s2))); | |
139 } | |
140 | |
141 size_t gaim_stringref_len(const GaimStringref *stringref) | |
142 { | |
143 return strlen(gaim_stringref_value(stringref)); | |
144 } | |
145 | |
146 static void stringref_free(GaimStringref *stringref) | |
147 { | |
148 #ifdef DEBUG | |
149 if (REFCOUNT(stringref->ref) != 0) { | |
150 gaim_debug(GAIM_DEBUG_ERROR, "stringref", "Free of nonzero (%d) ref stringref!\n", REFCOUNT(stringref->ref)); | |
151 return; | |
152 } | |
153 #endif /* DEBUG */ | |
154 g_free(stringref); | |
155 } | |
156 | |
157 static gboolean gs_idle_cb(gpointer data) | |
158 { | |
159 GaimStringref *ref; | |
160 GList *del; | |
161 | |
162 while (gclist != NULL) { | |
163 ref = gclist->data; | |
164 if (REFCOUNT(ref->ref) == 0) { | |
165 stringref_free(ref); | |
166 } | |
167 del = gclist; | |
168 gclist = gclist->next; | |
169 g_list_free_1(del); | |
170 } | |
171 | |
172 return FALSE; | |
173 } |