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