Mercurial > pidgin
comparison console/libgnt/gnttextview.c @ 14383:5f3058c7a7df
[gaim-migrate @ 17089]
This is a little better than before. But resizing the width of a textview
with a large buffer still takes too much time.
committer: Tailor Script <tailor@pidgin.im>
author | Sadrul Habib Chowdhury <imadil@gmail.com> |
---|---|
date | Wed, 30 Aug 2006 23:29:42 +0000 |
parents | f3137c1faebe |
children | 70f52ff1caec |
comparison
equal
deleted
inserted
replaced
14382:7b590ba06651 | 14383:5f3058c7a7df |
---|---|
8 | 8 |
9 typedef struct | 9 typedef struct |
10 { | 10 { |
11 GntTextFormatFlags tvflag; | 11 GntTextFormatFlags tvflag; |
12 chtype flags; | 12 chtype flags; |
13 char *text; | 13 int start; |
14 int end; /* This is the next byte of the last character of this segment */ | |
14 } GntTextSegment; | 15 } GntTextSegment; |
15 | 16 |
16 typedef struct | 17 typedef struct |
17 { | 18 { |
18 GList *segments; /* A list of GntTextSegments */ | 19 GList *segments; /* A list of GntTextSegments */ |
41 wmove(widget->window, widget->priv.height - 1 - i, 0); | 42 wmove(widget->window, widget->priv.height - 1 - i, 0); |
42 | 43 |
43 for (iter = line->segments; iter; iter = iter->next) | 44 for (iter = line->segments; iter; iter = iter->next) |
44 { | 45 { |
45 GntTextSegment *seg = iter->data; | 46 GntTextSegment *seg = iter->data; |
47 char *end = view->string->str + seg->end; | |
48 char back = *end; | |
49 *end = '\0'; | |
46 wattrset(widget->window, seg->flags); | 50 wattrset(widget->window, seg->flags); |
47 wprintw(widget->window, "%s", seg->text); | 51 wprintw(widget->window, "%s", (view->string->str + seg->start)); |
48 if (!iter->next) | 52 if (!iter->next) |
49 whline(widget->window, ' ' | seg->flags, widget->priv.width - line->length - 1); | 53 whline(widget->window, ' ' | seg->flags, widget->priv.width - line->length - 1); |
54 *end = back; | |
50 } | 55 } |
51 } | 56 } |
52 | 57 |
53 scrcol = widget->priv.width - 1; | 58 scrcol = widget->priv.width - 1; |
54 rows = widget->priv.height - 2; | 59 rows = widget->priv.height - 2; |
113 | 118 |
114 static void | 119 static void |
115 free_text_segment(gpointer data, gpointer null) | 120 free_text_segment(gpointer data, gpointer null) |
116 { | 121 { |
117 GntTextSegment *seg = data; | 122 GntTextSegment *seg = data; |
118 g_free(seg->text); | |
119 g_free(seg); | 123 g_free(seg); |
120 } | 124 } |
121 | 125 |
122 static void | 126 static void |
123 free_text_line(gpointer data, gpointer null) | 127 free_text_line(gpointer data, gpointer null) |
133 { | 137 { |
134 GntTextView *view = GNT_TEXT_VIEW(widget); | 138 GntTextView *view = GNT_TEXT_VIEW(widget); |
135 view->list = g_list_first(view->list); | 139 view->list = g_list_first(view->list); |
136 g_list_foreach(view->list, free_text_line, NULL); | 140 g_list_foreach(view->list, free_text_line, NULL); |
137 g_list_free(view->list); | 141 g_list_free(view->list); |
142 g_string_free(view->string, TRUE); | |
138 } | 143 } |
139 | 144 |
140 static gboolean | 145 static gboolean |
141 gnt_text_view_clicked(GntWidget *widget, GntMouseEvent event, int x, int y) | 146 gnt_text_view_clicked(GntWidget *widget, GntMouseEvent event, int x, int y) |
142 { | 147 { |
153 gnt_text_view_reflow(GntTextView *view) | 158 gnt_text_view_reflow(GntTextView *view) |
154 { | 159 { |
155 /* This is pretty ugly, and inefficient. Someone do something about it. */ | 160 /* This is pretty ugly, and inefficient. Someone do something about it. */ |
156 GntTextLine *line; | 161 GntTextLine *line; |
157 GList *back, *iter, *list; | 162 GList *back, *iter, *list; |
163 GString *string; | |
158 int pos = 0; | 164 int pos = 0; |
159 | 165 |
160 list = view->list; | 166 list = view->list; |
161 while (list->prev) { | 167 while (list->prev) { |
162 line = list->data; | 168 line = list->data; |
165 list = list->prev; | 171 list = list->prev; |
166 } | 172 } |
167 | 173 |
168 back = g_list_last(view->list); | 174 back = g_list_last(view->list); |
169 view->list = NULL; | 175 view->list = NULL; |
176 | |
177 string = view->string; | |
178 view->string = NULL; | |
170 gnt_text_view_clear(view); | 179 gnt_text_view_clear(view); |
180 | |
181 view->string = g_string_set_size(view->string, string->len); | |
182 GNT_WIDGET_SET_FLAGS(GNT_WIDGET(view), GNT_WIDGET_DRAWING); | |
171 | 183 |
172 for (; back; back = back->prev) { | 184 for (; back; back = back->prev) { |
173 line = back->data; | 185 line = back->data; |
174 | 186 if (back->next && !line->soft) { |
175 if (back->next && !line->soft) | 187 GList *llist = g_list_first(view->list); |
176 gnt_text_view_next_line(view); | 188 llist = g_list_prepend(llist, g_new0(GntTextLine, 1)); |
177 | 189 } |
190 | |
178 for (iter = line->segments; iter; iter = iter->next) { | 191 for (iter = line->segments; iter; iter = iter->next) { |
179 GntTextSegment *seg = iter->data; | 192 GntTextSegment *seg = iter->data; |
180 gnt_text_view_append_text_with_flags(view, seg->text, seg->tvflag); | 193 char *start = string->str + seg->start; |
194 char *end = string->str + seg->end; | |
195 char back = *end; | |
196 *end = '\0'; | |
197 gnt_text_view_append_text_with_flags(view, start, seg->tvflag); | |
198 *end = back; | |
181 } | 199 } |
182 | |
183 free_text_line(line, NULL); | 200 free_text_line(line, NULL); |
184 } | 201 } |
185 g_list_free(list); | 202 g_list_free(list); |
186 | 203 |
187 list = view->list = g_list_first(view->list); | 204 list = view->list = g_list_first(view->list); |
189 while (((GntTextLine*)list->data)->soft) | 206 while (((GntTextLine*)list->data)->soft) |
190 list = list->next; | 207 list = list->next; |
191 list = list->next; | 208 list = list->next; |
192 } | 209 } |
193 view->list = list; | 210 view->list = list; |
211 GNT_WIDGET_UNSET_FLAGS(GNT_WIDGET(view), GNT_WIDGET_DRAWING); | |
194 gnt_widget_draw(GNT_WIDGET(view)); | 212 gnt_widget_draw(GNT_WIDGET(view)); |
213 g_string_free(string, TRUE); | |
195 } | 214 } |
196 | 215 |
197 static void | 216 static void |
198 gnt_text_view_size_changed(GntWidget *widget, int w, int h) | 217 gnt_text_view_size_changed(GntWidget *widget, int w, int h) |
199 { | 218 { |
265 GntTextView *view = GNT_TEXT_VIEW(widget); | 284 GntTextView *view = GNT_TEXT_VIEW(widget); |
266 GntTextLine *line = g_new0(GntTextLine, 1); | 285 GntTextLine *line = g_new0(GntTextLine, 1); |
267 | 286 |
268 GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_NO_BORDER | GNT_WIDGET_NO_SHADOW); | 287 GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_NO_BORDER | GNT_WIDGET_NO_SHADOW); |
269 | 288 |
289 view->string = g_string_new(NULL); | |
270 view->list = g_list_append(view->list, line); | 290 view->list = g_list_append(view->list, line); |
271 | 291 |
272 return widget; | 292 return widget; |
273 } | 293 } |
274 | 294 |
275 void gnt_text_view_append_text_with_flags(GntTextView *view, const char *text, GntTextFormatFlags flags) | 295 void gnt_text_view_append_text_with_flags(GntTextView *view, const char *text, GntTextFormatFlags flags) |
276 { | 296 { |
277 GntWidget *widget = GNT_WIDGET(view); | 297 GntWidget *widget = GNT_WIDGET(view); |
278 int fl = 0; | 298 int fl = 0; |
279 char **split; | 299 const char *start, *end; |
280 int i; | |
281 GList *list = view->list; | 300 GList *list = view->list; |
301 GntTextLine *line; | |
302 int len; | |
282 | 303 |
283 if (text == NULL || *text == '\0') | 304 if (text == NULL || *text == '\0') |
284 return; | 305 return; |
285 | 306 |
286 fl = gnt_text_format_flag_to_chtype(flags); | 307 fl = gnt_text_format_flag_to_chtype(flags); |
287 | 308 |
309 len = view->string->len; | |
310 g_string_append(view->string, text); | |
311 | |
288 view->list = g_list_first(view->list); | 312 view->list = g_list_first(view->list); |
289 | 313 |
290 split = g_strsplit(text, "\n", -1); | 314 start = end = view->string->str + len; |
291 for (i = 0; split[i]; i++) | 315 |
292 { | 316 while (*start) { |
293 GntTextLine *line; | 317 GntTextSegment *seg; |
294 char *iter = split[i]; | 318 |
295 int prev = 0; | 319 if (*end == '\n' || *end == '\r') { |
296 | 320 end++; |
297 if (i) | 321 start = end; |
298 { | 322 gnt_text_view_next_line(view); |
323 continue; | |
324 } | |
325 | |
326 line = view->list->data; | |
327 end = gnt_util_onscreen_width_to_pointer(start, | |
328 widget->priv.width - line->length - 1, &len); | |
329 | |
330 seg = g_new0(GntTextSegment, 1); | |
331 seg->start = start - view->string->str; | |
332 seg->end = end - view->string->str; | |
333 seg->tvflag = flags; | |
334 seg->flags = fl; | |
335 line->segments = g_list_append(line->segments, seg); | |
336 line->length += len; | |
337 | |
338 start = end; | |
339 if (*end && *end != '\n' && *end != '\r') { | |
299 line = g_new0(GntTextLine, 1); | 340 line = g_new0(GntTextLine, 1); |
300 view->list = g_list_prepend(g_list_first(view->list), line); | 341 line->soft = TRUE; |
342 view->list = g_list_prepend(view->list, line); | |
301 } | 343 } |
302 | 344 } |
303 line = view->list->data; | 345 |
304 | |
305 while (iter && *iter) | |
306 { | |
307 int len; | |
308 | |
309 len = gnt_util_onscreen_width_to_pointer(iter, widget->priv.width - line->length - 1, &prev) - iter; | |
310 if (len) { | |
311 GntTextSegment *seg = g_new0(GntTextSegment, 1); | |
312 seg->flags = fl; | |
313 seg->tvflag = flags; | |
314 seg->text = g_new0(char, len + 1); | |
315 g_utf8_strncpy(seg->text, iter, g_utf8_pointer_to_offset(iter, iter + len)); | |
316 line->segments = g_list_append(line->segments, seg); | |
317 | |
318 line->length += prev; | |
319 iter += len; | |
320 if (line->length >= widget->priv.width - 1 && *iter) { | |
321 line = g_new0(GntTextLine, 1); | |
322 line->soft = TRUE; | |
323 view->list = g_list_prepend(g_list_first(view->list), line); | |
324 } | |
325 } else { | |
326 line = g_new0(GntTextLine, 1); | |
327 line->soft = TRUE; | |
328 view->list = g_list_prepend(g_list_first(view->list), line); | |
329 } | |
330 } | |
331 } | |
332 | |
333 g_strfreev(split); | |
334 view->list = list; | 346 view->list = list; |
335 | 347 |
336 gnt_widget_draw(widget); | 348 gnt_widget_draw(widget); |
337 } | 349 } |
338 | 350 |
399 g_list_free(view->list); | 411 g_list_free(view->list); |
400 view->list = NULL; | 412 view->list = NULL; |
401 | 413 |
402 line = g_new0(GntTextLine, 1); | 414 line = g_new0(GntTextLine, 1); |
403 view->list = g_list_append(view->list, line); | 415 view->list = g_list_append(view->list, line); |
416 if (view->string) | |
417 g_string_free(view->string, TRUE); | |
418 view->string = g_string_new(NULL); | |
404 | 419 |
405 if (GNT_WIDGET(view)->window) | 420 if (GNT_WIDGET(view)->window) |
406 gnt_widget_draw(GNT_WIDGET(view)); | 421 gnt_widget_draw(GNT_WIDGET(view)); |
407 } | 422 } |
408 | 423 |