changeset 943:9ac0d166a85b

hbuf: Refactor line wrapping stuff
author Mikael Berthe <mikael@lilotux.net>
date Sat, 15 Jul 2006 12:46:39 +0200
parents c6bd42119c31
children aec71ebf98fa
files mcabber/src/hbuf.c
diffstat 1 files changed, 72 insertions(+), 93 deletions(-) [+]
line wrap: on
line diff
--- a/mcabber/src/hbuf.c	Sat Jul 15 12:28:42 2006 +0200
+++ b/mcabber/src/hbuf.c	Sat Jul 15 12:46:39 2006 +0200
@@ -43,68 +43,21 @@
 } hbuf_block;
 
 
-//  hbuf_add_line(p_hbuf, text, prefix_flags, width)
-// Add a line to the given buffer.  If width is not null, then lines are
-// wrapped at this length.
-//
-// Note 1: Splitting according to width won't work if there are tabs; they
-//         should be expanded before.
-// Note 2: width does not include the ending \0.
-void hbuf_add_line(GList **p_hbuf, const char *text, time_t timestamp,
-        guint prefix_flags, guint width)
+//  do_wrap(p_hbuf, first_hbuf_elt, width)
+// Wrap hbuf lines with the specified width.
+// '\n' are handled by this routine (they are removed and persistent lines
+// are created).
+// All hbuf elements are processed, starting from first_hbuf_elt.
+static inline void do_wrap(GList **p_hbuf, GList *first_hbuf_elt,
+                           unsigned int width)
 {
-  GList *hbuf = *p_hbuf;
-  GList *curr_elt;
-  char *line, *end;
-  hbuf_block *hbuf_block_elt, *hbuf_b_curr;
-
-  if (!text) return;
-
-  hbuf_block_elt = g_new0(hbuf_block, 1);
-  hbuf_block_elt->prefix.timestamp  = timestamp;
-  hbuf_block_elt->prefix.flags      = prefix_flags;
-  if (!hbuf) {
-    hbuf_block_elt->ptr  = g_new(char, HBB_BLOCKSIZE);
-    hbuf_block_elt->flags  = HBB_FLAG_ALLOC | HBB_FLAG_PERSISTENT;
-    hbuf_block_elt->ptr_end_alloc = hbuf_block_elt->ptr + HBB_BLOCKSIZE;
-    *p_hbuf = g_list_append(*p_hbuf, hbuf_block_elt);
-  } else {
-    hbuf_block *hbuf_b_prev;
-    // Set p_hbuf to the end of the list, to speed up history loading
-    // (or CPU time will be used by g_list_last() for each line)
-    hbuf = *p_hbuf = g_list_last(*p_hbuf);
-    hbuf_b_prev = hbuf->data;
-    hbuf_block_elt->ptr    = hbuf_b_prev->ptr_end;
-    hbuf_block_elt->flags  = HBB_FLAG_PERSISTENT;
-    hbuf_block_elt->ptr_end_alloc = hbuf_b_prev->ptr_end_alloc;
-    *p_hbuf = g_list_append(*p_hbuf, hbuf_block_elt);
-  }
-
-  if (strlen(text) >= HBB_BLOCKSIZE) {
-    // Too long
-    text = "[ERR:LINE_TOO_LONG]";
-    hbuf_block_elt->prefix.flags |= HBB_PREFIX_INFO;
-  }
-  if (hbuf_block_elt->ptr + strlen(text) >= hbuf_block_elt->ptr_end_alloc) {
-    // Too long for the current allocated bloc, we need another one
-    hbuf_block_elt->ptr  = g_new0(char, HBB_BLOCKSIZE);
-    hbuf_block_elt->flags  = HBB_FLAG_ALLOC | HBB_FLAG_PERSISTENT;
-    hbuf_block_elt->ptr_end_alloc = hbuf_block_elt->ptr + HBB_BLOCKSIZE;
-  }
-
-  line = hbuf_block_elt->ptr;
-  // Ok, now we can copy the text..
-  strcpy(line, text);
-  hbuf_block_elt->ptr_end = line + strlen(line) + 1;
-  end = hbuf_block_elt->ptr_end;
-
-  curr_elt = g_list_last(hbuf);
+  GList *curr_elt = first_hbuf_elt;
 
   // Let's add non-persistent blocs if necessary
   // - If there are '\n' in the string
   // - If length > width (and width != 0)
   while (curr_elt) {
-    hbuf_block *hbuf_b_prev;
+    hbuf_block *hbuf_b_curr, *hbuf_b_prev;
     char *c, *end;
     char *br = NULL; // break pointer
     char *cr = NULL; // CR pointer
@@ -154,6 +107,67 @@
   }
 }
 
+//  hbuf_add_line(p_hbuf, text, prefix_flags, width)
+// Add a line to the given buffer.  If width is not null, then lines are
+// wrapped at this length.
+//
+// Note 1: Splitting according to width won't work if there are tabs; they
+//         should be expanded before.
+// Note 2: width does not include the ending \0.
+void hbuf_add_line(GList **p_hbuf, const char *text, time_t timestamp,
+        guint prefix_flags, guint width)
+{
+  GList *hbuf = *p_hbuf;
+  GList *curr_elt;
+  char *line, *end;
+  hbuf_block *hbuf_block_elt;
+
+  if (!text) return;
+
+  hbuf_block_elt = g_new0(hbuf_block, 1);
+  hbuf_block_elt->prefix.timestamp  = timestamp;
+  hbuf_block_elt->prefix.flags      = prefix_flags;
+  if (!hbuf) {
+    hbuf_block_elt->ptr  = g_new(char, HBB_BLOCKSIZE);
+    hbuf_block_elt->flags  = HBB_FLAG_ALLOC | HBB_FLAG_PERSISTENT;
+    hbuf_block_elt->ptr_end_alloc = hbuf_block_elt->ptr + HBB_BLOCKSIZE;
+    *p_hbuf = g_list_append(*p_hbuf, hbuf_block_elt);
+  } else {
+    hbuf_block *hbuf_b_prev;
+    // Set p_hbuf to the end of the list, to speed up history loading
+    // (or CPU time will be used by g_list_last() for each line)
+    hbuf = *p_hbuf = g_list_last(*p_hbuf);
+    hbuf_b_prev = hbuf->data;
+    hbuf_block_elt->ptr    = hbuf_b_prev->ptr_end;
+    hbuf_block_elt->flags  = HBB_FLAG_PERSISTENT;
+    hbuf_block_elt->ptr_end_alloc = hbuf_b_prev->ptr_end_alloc;
+    *p_hbuf = g_list_append(*p_hbuf, hbuf_block_elt);
+  }
+
+  if (strlen(text) >= HBB_BLOCKSIZE) {
+    // Too long
+    text = "[ERR:LINE_TOO_LONG]";
+    hbuf_block_elt->prefix.flags |= HBB_PREFIX_INFO;
+  }
+  if (hbuf_block_elt->ptr + strlen(text) >= hbuf_block_elt->ptr_end_alloc) {
+    // Too long for the current allocated bloc, we need another one
+    hbuf_block_elt->ptr  = g_new0(char, HBB_BLOCKSIZE);
+    hbuf_block_elt->flags  = HBB_FLAG_ALLOC | HBB_FLAG_PERSISTENT;
+    hbuf_block_elt->ptr_end_alloc = hbuf_block_elt->ptr + HBB_BLOCKSIZE;
+  }
+
+  line = hbuf_block_elt->ptr;
+  // Ok, now we can copy the text..
+  strcpy(line, text);
+  hbuf_block_elt->ptr_end = line + strlen(line) + 1;
+  end = hbuf_block_elt->ptr_end;
+
+  curr_elt = g_list_last(hbuf);
+
+  // Wrap lines and handle CRs ('\n')
+  do_wrap(p_hbuf, curr_elt, width);
+}
+
 //  hbuf_free()
 // Destroys all hbuf list.
 void hbuf_free(GList **p_hbuf)
@@ -203,43 +217,8 @@
       curr_elt = next_elt;
   }
   // #2 Go back to head and create non-persistent blocks when needed
-  if (width) {
-    char *end;
-    curr_elt = first_elt;
-
-    while (curr_elt) {
-      hbuf_b_curr = (hbuf_block*)(curr_elt->data);
-      hbuf_block *hbuf_b_prev = hbuf_b_curr;
-
-      // We need to break where we can find a space char
-      char *br = NULL; // break pointer
-      char *c = hbuf_b_curr->ptr;
-      unsigned int cur_w = 0;
-      while (*c && cur_w <= width) {
-        if (iswblank(get_char(c)))
-          br = c;
-        cur_w += get_char_width(c);
-        c = next_char(c);
-      }
-      if (*c && cur_w > width) {
-        if (!br || br == hbuf_b_curr->ptr)
-          br = c;
-        else
-          br = next_char(br);
-        end = hbuf_b_curr->ptr_end;
-        hbuf_b_curr->ptr_end = br;
-        // Create another block, non-persistent
-        hbuf_b_curr = g_new0(hbuf_block, 1);
-        hbuf_b_curr->ptr      = hbuf_b_prev->ptr_end; // == br
-        hbuf_b_curr->ptr_end  = end;
-        hbuf_b_curr->flags    = 0;
-        hbuf_b_curr->ptr_end_alloc = hbuf_b_prev->ptr_end_alloc;
-        // This is OK because insert_before(NULL) == append():
-        *p_hbuf = g_list_insert_before(*p_hbuf, curr_elt->next, hbuf_b_curr);
-      }
-      curr_elt = g_list_next(curr_elt);
-    }
-  }
+  if (width)
+    do_wrap(p_hbuf, first_elt, width);
 }
 
 //  hbuf_previous_persistent()