mcabber/mcabber/hbuf.c
changeset 2337 ffd0e57e9563
parent 2268 f5402d705f67
equal deleted inserted replaced
2336:0dc317b5599d 2337:ffd0e57e9563
    42     time_t timestamp;
    42     time_t timestamp;
    43     unsigned mucnicklen;
    43     unsigned mucnicklen;
    44     guint  flags;
    44     guint  flags;
    45     gpointer xep184;
    45     gpointer xep184;
    46   } prefix;
    46   } prefix;
    47 } hbuf_block;
    47 } hbuf_block_t;
    48 
    48 
    49 
    49 
    50 //  do_wrap(p_hbuf, first_hbuf_elt, width)
    50 //  do_wrap(p_hbuf, first_hbuf_elt, width)
    51 // Wrap hbuf lines with the specified width.
    51 // Wrap hbuf lines with the specified width.
    52 // '\n' are handled by this routine (they are removed and persistent lines
    52 // '\n' are handled by this routine (they are removed and persistent lines
    59 
    59 
    60   // Let's add non-persistent blocs if necessary
    60   // Let's add non-persistent blocs if necessary
    61   // - If there are '\n' in the string
    61   // - If there are '\n' in the string
    62   // - If length > width (and width != 0)
    62   // - If length > width (and width != 0)
    63   while (curr_elt) {
    63   while (curr_elt) {
    64     hbuf_block *hbuf_b_curr, *hbuf_b_prev;
    64     hbuf_block_t *hbuf_b_curr, *hbuf_b_prev;
    65     char *c, *end;
    65     char *c, *end;
    66     char *br = NULL; // break pointer
    66     char *br = NULL; // break pointer
    67     char *cr = NULL; // CR pointer
    67     char *cr = NULL; // CR pointer
    68     unsigned int cur_w = 0;
    68     unsigned int cur_w = 0;
    69 
    69 
    70     // We want to break where we can find a space char or a CR
    70     // We want to break where we can find a space char or a CR
    71 
    71 
    72     hbuf_b_curr = (hbuf_block*)(curr_elt->data);
    72     hbuf_b_curr = (hbuf_block_t*)(curr_elt->data);
    73     hbuf_b_prev = hbuf_b_curr;
    73     hbuf_b_prev = hbuf_b_curr;
    74     c = hbuf_b_curr->ptr;
    74     c = hbuf_b_curr->ptr;
    75 
    75 
    76     while (*c && (!width || cur_w <= width)) {
    76     while (*c && (!width || cur_w <= width)) {
    77       if (*c == '\n') {
    77       if (*c == '\n') {
    91       else
    91       else
    92         br = next_char(br);
    92         br = next_char(br);
    93       end = hbuf_b_curr->ptr_end;
    93       end = hbuf_b_curr->ptr_end;
    94       hbuf_b_curr->ptr_end = br;
    94       hbuf_b_curr->ptr_end = br;
    95       // Create another block
    95       // Create another block
    96       hbuf_b_curr = g_new0(hbuf_block, 1);
    96       hbuf_b_curr = g_new0(hbuf_block_t, 1);
    97       // The block must be persistent after a CR
    97       // The block must be persistent after a CR
    98       if (cr) {
    98       if (cr) {
    99         hbuf_b_curr->ptr    = hbuf_b_prev->ptr_end + 1; // == cr+1
    99         hbuf_b_curr->ptr    = hbuf_b_prev->ptr_end + 1; // == cr+1
   100         hbuf_b_curr->flags  = HBB_FLAG_PERSISTENT;
   100         hbuf_b_curr->flags  = HBB_FLAG_PERSISTENT;
   101       } else {
   101       } else {
   125         unsigned mucnicklen, gpointer xep184)
   125         unsigned mucnicklen, gpointer xep184)
   126 {
   126 {
   127   GList *curr_elt;
   127   GList *curr_elt;
   128   char *line;
   128   char *line;
   129   guint hbb_blocksize, textlen;
   129   guint hbb_blocksize, textlen;
   130   hbuf_block *hbuf_block_elt;
   130   hbuf_block_t *hbuf_block_elt;
   131 
   131 
   132   if (!text) return;
   132   if (!text) return;
   133 
   133 
   134   prefix_flags |= (xep184 ? HBB_PREFIX_RECEIPT : 0);
   134   prefix_flags |= (xep184 ? HBB_PREFIX_RECEIPT : 0);
   135 
   135 
   136   textlen = strlen(text);
   136   textlen = strlen(text);
   137   hbb_blocksize = MAX(textlen+1, HBB_BLOCKSIZE);
   137   hbb_blocksize = MAX(textlen+1, HBB_BLOCKSIZE);
   138 
   138 
   139   hbuf_block_elt = g_new0(hbuf_block, 1);
   139   hbuf_block_elt = g_new0(hbuf_block_t, 1);
   140   hbuf_block_elt->prefix.timestamp  = timestamp;
   140   hbuf_block_elt->prefix.timestamp  = timestamp;
   141   hbuf_block_elt->prefix.flags      = prefix_flags;
   141   hbuf_block_elt->prefix.flags      = prefix_flags;
   142   hbuf_block_elt->prefix.mucnicklen = mucnicklen;
   142   hbuf_block_elt->prefix.mucnicklen = mucnicklen;
   143   hbuf_block_elt->prefix.xep184     = xep184;
   143   hbuf_block_elt->prefix.xep184     = xep184;
   144   if (!*p_hbuf) {
   144   if (!*p_hbuf) {
   148       return;
   148       return;
   149     }
   149     }
   150     hbuf_block_elt->flags  = HBB_FLAG_ALLOC | HBB_FLAG_PERSISTENT;
   150     hbuf_block_elt->flags  = HBB_FLAG_ALLOC | HBB_FLAG_PERSISTENT;
   151     hbuf_block_elt->ptr_end_alloc = hbuf_block_elt->ptr + hbb_blocksize;
   151     hbuf_block_elt->ptr_end_alloc = hbuf_block_elt->ptr + hbb_blocksize;
   152   } else {
   152   } else {
   153     hbuf_block *hbuf_b_prev;
   153     hbuf_block_t *hbuf_b_prev;
   154     // Set p_hbuf to the end of the list, to speed up history loading
   154     // Set p_hbuf to the end of the list, to speed up history loading
   155     // (or CPU time will be used by g_list_last() for each line)
   155     // (or CPU time will be used by g_list_last() for each line)
   156     *p_hbuf = g_list_last(*p_hbuf);
   156     *p_hbuf = g_list_last(*p_hbuf);
   157     hbuf_b_prev = (*p_hbuf)->data;
   157     hbuf_b_prev = (*p_hbuf)->data;
   158     hbuf_block_elt->ptr    = hbuf_b_prev->ptr_end;
   158     hbuf_block_elt->ptr    = hbuf_b_prev->ptr_end;
   170       hbuf_block_elt->ptr  = g_new0(char, hbb_blocksize);
   170       hbuf_block_elt->ptr  = g_new0(char, hbb_blocksize);
   171       hbuf_block_elt->ptr_end_alloc = hbuf_block_elt->ptr + hbb_blocksize;
   171       hbuf_block_elt->ptr_end_alloc = hbuf_block_elt->ptr + hbb_blocksize;
   172       // XXX We should check the return value.
   172       // XXX We should check the return value.
   173     } else {
   173     } else {
   174       GList *hbuf_head, *hbuf_elt;
   174       GList *hbuf_head, *hbuf_elt;
   175       hbuf_block *hbuf_b_elt;
   175       hbuf_block_t *hbuf_b_elt;
   176       guint n = 0;
   176       guint n = 0;
   177       hbuf_head = g_list_first(*p_hbuf);
   177       hbuf_head = g_list_first(*p_hbuf);
   178       // We need at least 2 allocated blocks
   178       // We need at least 2 allocated blocks
   179       if (maxhbufblocks == 1)
   179       if (maxhbufblocks == 1)
   180         maxhbufblocks = 2;
   180         maxhbufblocks = 2;
   181       // Let's count the number of allocated areas
   181       // Let's count the number of allocated areas
   182       for (hbuf_elt = hbuf_head; hbuf_elt; hbuf_elt = g_list_next(hbuf_elt)) {
   182       for (hbuf_elt = hbuf_head; hbuf_elt; hbuf_elt = g_list_next(hbuf_elt)) {
   183         hbuf_b_elt = (hbuf_block*)(hbuf_elt->data);
   183         hbuf_b_elt = (hbuf_block_t*)(hbuf_elt->data);
   184         if (hbuf_b_elt->flags & HBB_FLAG_ALLOC)
   184         if (hbuf_b_elt->flags & HBB_FLAG_ALLOC)
   185           n++;
   185           n++;
   186       }
   186       }
   187       // If we can't allocate a new area, reuse the previous block(s)
   187       // If we can't allocate a new area, reuse the previous block(s)
   188       if (n < maxhbufblocks) {
   188       if (n < maxhbufblocks) {
   193         char *allocated_block = NULL;
   193         char *allocated_block = NULL;
   194         char *end_of_allocated_block = NULL;
   194         char *end_of_allocated_block = NULL;
   195         while (n >= maxhbufblocks) {
   195         while (n >= maxhbufblocks) {
   196           int start_of_block = 1;
   196           int start_of_block = 1;
   197           for (hbuf_elt = hbuf_head; hbuf_elt; hbuf_elt = hbuf_head) {
   197           for (hbuf_elt = hbuf_head; hbuf_elt; hbuf_elt = hbuf_head) {
   198             hbuf_b_elt = (hbuf_block*)(hbuf_elt->data);
   198             hbuf_b_elt = (hbuf_block_t*)(hbuf_elt->data);
   199             if (hbuf_b_elt->flags & HBB_FLAG_ALLOC) {
   199             if (hbuf_b_elt->flags & HBB_FLAG_ALLOC) {
   200               if (start_of_block-- == 0)
   200               if (start_of_block-- == 0)
   201                 break;
   201                 break;
   202               if (n == maxhbufblocks) {
   202               if (n == maxhbufblocks) {
   203                 allocated_block = hbuf_b_elt->ptr;
   203                 allocated_block = hbuf_b_elt->ptr;
   232 
   232 
   233 //  hbuf_free()
   233 //  hbuf_free()
   234 // Destroys all hbuf list.
   234 // Destroys all hbuf list.
   235 void hbuf_free(GList **p_hbuf)
   235 void hbuf_free(GList **p_hbuf)
   236 {
   236 {
   237   hbuf_block *hbuf_b_elt;
   237   hbuf_block_t *hbuf_b_elt;
   238   GList *hbuf_elt;
   238   GList *hbuf_elt;
   239   GList *first_elt = g_list_first(*p_hbuf);
   239   GList *first_elt = g_list_first(*p_hbuf);
   240 
   240 
   241   for (hbuf_elt = first_elt; hbuf_elt; hbuf_elt = g_list_next(hbuf_elt)) {
   241   for (hbuf_elt = first_elt; hbuf_elt; hbuf_elt = g_list_next(hbuf_elt)) {
   242     hbuf_b_elt = (hbuf_block*)(hbuf_elt->data);
   242     hbuf_b_elt = (hbuf_block_t*)(hbuf_elt->data);
   243     if (hbuf_b_elt->flags & HBB_FLAG_ALLOC) {
   243     if (hbuf_b_elt->flags & HBB_FLAG_ALLOC) {
   244       g_free(hbuf_b_elt->ptr);
   244       g_free(hbuf_b_elt->ptr);
   245     }
   245     }
   246     g_free(hbuf_b_elt);
   246     g_free(hbuf_b_elt);
   247   }
   247   }
   254 // Rebuild all hbuf list, with the new width.
   254 // Rebuild all hbuf list, with the new width.
   255 // If width == 0, lines are not wrapped.
   255 // If width == 0, lines are not wrapped.
   256 void hbuf_rebuild(GList **p_hbuf, unsigned int width)
   256 void hbuf_rebuild(GList **p_hbuf, unsigned int width)
   257 {
   257 {
   258   GList *first_elt, *curr_elt, *next_elt;
   258   GList *first_elt, *curr_elt, *next_elt;
   259   hbuf_block *hbuf_b_curr, *hbuf_b_next;
   259   hbuf_block_t *hbuf_b_curr, *hbuf_b_next;
   260 
   260 
   261   // *p_hbuf needs to be the head of the list
   261   // *p_hbuf needs to be the head of the list
   262   first_elt = *p_hbuf = g_list_first(*p_hbuf);
   262   first_elt = *p_hbuf = g_list_first(*p_hbuf);
   263 
   263 
   264   // #1 Remove non-persistent blocks (ptr_end should be updated!)
   264   // #1 Remove non-persistent blocks (ptr_end should be updated!)
   266   while (curr_elt) {
   266   while (curr_elt) {
   267     next_elt = g_list_next(curr_elt);
   267     next_elt = g_list_next(curr_elt);
   268     // Last element?
   268     // Last element?
   269     if (!next_elt)
   269     if (!next_elt)
   270       break;
   270       break;
   271     hbuf_b_curr = (hbuf_block*)(curr_elt->data);
   271     hbuf_b_curr = (hbuf_block_t*)(curr_elt->data);
   272     hbuf_b_next = (hbuf_block*)(next_elt->data);
   272     hbuf_b_next = (hbuf_block_t*)(next_elt->data);
   273     // Is next line not-persistent?
   273     // Is next line not-persistent?
   274     if (!(hbuf_b_next->flags & HBB_FLAG_PERSISTENT)) {
   274     if (!(hbuf_b_next->flags & HBB_FLAG_PERSISTENT)) {
   275       hbuf_b_curr->ptr_end = hbuf_b_next->ptr_end;
   275       hbuf_b_curr->ptr_end = hbuf_b_next->ptr_end;
   276       g_free(hbuf_b_next);
   276       g_free(hbuf_b_next);
   277       curr_elt = g_list_delete_link(curr_elt, next_elt);
   277       curr_elt = g_list_delete_link(curr_elt, next_elt);
   289 // This function is used for example when resizing a buffer.  If the top of the
   289 // This function is used for example when resizing a buffer.  If the top of the
   290 // screen is on a non-persistent block, then a screen resize could destroy this
   290 // screen is on a non-persistent block, then a screen resize could destroy this
   291 // line...
   291 // line...
   292 GList *hbuf_previous_persistent(GList *l_line)
   292 GList *hbuf_previous_persistent(GList *l_line)
   293 {
   293 {
   294   hbuf_block *hbuf_b_elt;
   294   hbuf_block_t *hbuf_b_elt;
   295 
   295 
   296   while (l_line) {
   296   while (l_line) {
   297     hbuf_b_elt = (hbuf_block*)l_line->data;
   297     hbuf_b_elt = (hbuf_block_t*)l_line->data;
   298     if (hbuf_b_elt->flags & HBB_FLAG_PERSISTENT &&
   298     if (hbuf_b_elt->flags & HBB_FLAG_PERSISTENT &&
   299         (hbuf_b_elt->flags & ~HBB_PREFIX_READMARK))
   299         (hbuf_b_elt->flags & ~HBB_PREFIX_READMARK))
   300       return l_line;
   300       return l_line;
   301     l_line = g_list_previous(l_line);
   301     l_line = g_list_previous(l_line);
   302   }
   302   }
   310 // Note: The caller should free the array, the hbb_line pointers and the
   310 // Note: The caller should free the array, the hbb_line pointers and the
   311 // text pointers after use.
   311 // text pointers after use.
   312 hbb_line **hbuf_get_lines(GList *hbuf, unsigned int n)
   312 hbb_line **hbuf_get_lines(GList *hbuf, unsigned int n)
   313 {
   313 {
   314   unsigned int i;
   314   unsigned int i;
   315   hbuf_block *blk;
   315   hbuf_block_t *blk;
   316   guint last_persist_prefixflags = 0;
   316   guint last_persist_prefixflags = 0;
   317   GList *last_persist;  // last persistent flags
   317   GList *last_persist;  // last persistent flags
   318   hbb_line **array, **array_elt;
   318   hbb_line **array, **array_elt;
   319   hbb_line *prev_array_elt = NULL;
   319   hbb_line *prev_array_elt = NULL;
   320 
   320 
   322   // we need to look at the last non-null prefix, which should be the first
   322   // we need to look at the last non-null prefix, which should be the first
   323   // line of the message.  We also need to check if there's a readmark flag
   323   // line of the message.  We also need to check if there's a readmark flag
   324   // somewhere in the message.
   324   // somewhere in the message.
   325   last_persist = hbuf_previous_persistent(hbuf);
   325   last_persist = hbuf_previous_persistent(hbuf);
   326   while (last_persist) {
   326   while (last_persist) {
   327     blk = (hbuf_block*)last_persist->data;
   327     blk = (hbuf_block_t*)last_persist->data;
   328     if ((blk->flags & HBB_FLAG_PERSISTENT) && blk->prefix.flags) {
   328     if ((blk->flags & HBB_FLAG_PERSISTENT) && blk->prefix.flags) {
   329       // This can be either the beginning of the message,
   329       // This can be either the beginning of the message,
   330       // or a persistent line with a readmark flag (or both).
   330       // or a persistent line with a readmark flag (or both).
   331       if (blk->prefix.flags & ~HBB_PREFIX_READMARK) { // First message line
   331       if (blk->prefix.flags & ~HBB_PREFIX_READMARK) { // First message line
   332         last_persist_prefixflags |= blk->prefix.flags;
   332         last_persist_prefixflags |= blk->prefix.flags;
   343 
   343 
   344   for (i = 0 ; i < n ; i++) {
   344   for (i = 0 ; i < n ; i++) {
   345     if (hbuf) {
   345     if (hbuf) {
   346       int maxlen;
   346       int maxlen;
   347 
   347 
   348       blk = (hbuf_block*)(hbuf->data);
   348       blk = (hbuf_block_t*)(hbuf->data);
   349       maxlen = blk->ptr_end - blk->ptr;
   349       maxlen = blk->ptr_end - blk->ptr;
   350       *array_elt = (hbb_line*)g_new(hbb_line, 1);
   350       *array_elt = (hbb_line*)g_new(hbb_line, 1);
   351       (*array_elt)->timestamp  = blk->prefix.timestamp;
   351       (*array_elt)->timestamp  = blk->prefix.timestamp;
   352       (*array_elt)->flags      = blk->prefix.flags;
   352       (*array_elt)->flags      = blk->prefix.flags;
   353       (*array_elt)->mucnicklen = blk->prefix.mucnicklen;
   353       (*array_elt)->mucnicklen = blk->prefix.mucnicklen;
   391 //  hbuf_search(hbuf, direction, string)
   391 //  hbuf_search(hbuf, direction, string)
   392 // Look backward/forward for a line containing string in the history buffer
   392 // Look backward/forward for a line containing string in the history buffer
   393 // Search starts at hbuf, and goes forward if direction == 1, backward if -1
   393 // Search starts at hbuf, and goes forward if direction == 1, backward if -1
   394 GList *hbuf_search(GList *hbuf, int direction, const char *string)
   394 GList *hbuf_search(GList *hbuf, int direction, const char *string)
   395 {
   395 {
   396   hbuf_block *blk;
   396   hbuf_block_t *blk;
   397 
   397 
   398   for (;;) {
   398   for (;;) {
   399     if (direction > 0)
   399     if (direction > 0)
   400       hbuf = g_list_next(hbuf);
   400       hbuf = g_list_next(hbuf);
   401     else
   401     else
   402       hbuf = g_list_previous(hbuf);
   402       hbuf = g_list_previous(hbuf);
   403 
   403 
   404     if (!hbuf) break;
   404     if (!hbuf) break;
   405 
   405 
   406     blk = (hbuf_block*)(hbuf->data);
   406     blk = (hbuf_block_t*)(hbuf->data);
   407     // XXX blk->ptr is (maybe) not really correct, because the match should
   407     // XXX blk->ptr is (maybe) not really correct, because the match should
   408     // not be after ptr_end.  We should check that...
   408     // not be after ptr_end.  We should check that...
   409     if (strcasestr(blk->ptr, string))
   409     if (strcasestr(blk->ptr, string))
   410       break;
   410       break;
   411   }
   411   }
   415 
   415 
   416 //  hbuf_jump_date(hbuf, t)
   416 //  hbuf_jump_date(hbuf, t)
   417 // Return a pointer to the first line after date t in the history buffer
   417 // Return a pointer to the first line after date t in the history buffer
   418 GList *hbuf_jump_date(GList *hbuf, time_t t)
   418 GList *hbuf_jump_date(GList *hbuf, time_t t)
   419 {
   419 {
   420   hbuf_block *blk;
   420   hbuf_block_t *blk;
   421 
   421 
   422   hbuf = g_list_first(hbuf);
   422   hbuf = g_list_first(hbuf);
   423 
   423 
   424   for ( ; hbuf && g_list_next(hbuf); hbuf = g_list_next(hbuf)) {
   424   for ( ; hbuf && g_list_next(hbuf); hbuf = g_list_next(hbuf)) {
   425     blk = (hbuf_block*)(hbuf->data);
   425     blk = (hbuf_block_t*)(hbuf->data);
   426     if (blk->prefix.timestamp >= t) break;
   426     if (blk->prefix.timestamp >= t) break;
   427   }
   427   }
   428 
   428 
   429   return hbuf;
   429   return hbuf;
   430 }
   430 }
   444 //  hbuf_jump_readmark(hbuf)
   444 //  hbuf_jump_readmark(hbuf)
   445 // Return a pointer to the line following the readmark
   445 // Return a pointer to the line following the readmark
   446 // or NULL if no mark was found.
   446 // or NULL if no mark was found.
   447 GList *hbuf_jump_readmark(GList *hbuf)
   447 GList *hbuf_jump_readmark(GList *hbuf)
   448 {
   448 {
   449   hbuf_block *blk;
   449   hbuf_block_t *blk;
   450   GList *r = NULL;
   450   GList *r = NULL;
   451 
   451 
   452   hbuf = g_list_last(hbuf);
   452   hbuf = g_list_last(hbuf);
   453   for ( ; hbuf; hbuf = g_list_previous(hbuf)) {
   453   for ( ; hbuf; hbuf = g_list_previous(hbuf)) {
   454     blk = (hbuf_block*)(hbuf->data);
   454     blk = (hbuf_block_t*)(hbuf->data);
   455     if (blk->prefix.flags & HBB_PREFIX_READMARK)
   455     if (blk->prefix.flags & HBB_PREFIX_READMARK)
   456       return r;
   456       return r;
   457     if ((blk->flags & HBB_FLAG_PERSISTENT) &&
   457     if ((blk->flags & HBB_FLAG_PERSISTENT) &&
   458         (blk->prefix.flags & ~HBB_PREFIX_READMARK))
   458         (blk->prefix.flags & ~HBB_PREFIX_READMARK))
   459       r = hbuf;
   459       r = hbuf;
   464 
   464 
   465 //  hbuf_dump_to_file(hbuf, filename)
   465 //  hbuf_dump_to_file(hbuf, filename)
   466 // Save the buffer to a file.
   466 // Save the buffer to a file.
   467 void hbuf_dump_to_file(GList *hbuf, const char *filename)
   467 void hbuf_dump_to_file(GList *hbuf, const char *filename)
   468 {
   468 {
   469   hbuf_block *blk;
   469   hbuf_block_t *blk;
   470   hbb_line line;
   470   hbb_line line;
   471   guint last_persist_prefixflags = 0;
   471   guint last_persist_prefixflags = 0;
   472   guint prefixwidth;
   472   guint prefixwidth;
   473   char pref[96];
   473   char pref[96];
   474   FILE *fp;
   474   FILE *fp;
   488   prefixwidth = MIN(prefixwidth, sizeof pref);
   488   prefixwidth = MIN(prefixwidth, sizeof pref);
   489 
   489 
   490   for (hbuf = g_list_first(hbuf); hbuf; hbuf = g_list_next(hbuf)) {
   490   for (hbuf = g_list_first(hbuf); hbuf; hbuf = g_list_next(hbuf)) {
   491     int maxlen;
   491     int maxlen;
   492 
   492 
   493     blk = (hbuf_block*)(hbuf->data);
   493     blk = (hbuf_block_t*)(hbuf->data);
   494     maxlen = blk->ptr_end - blk->ptr;
   494     maxlen = blk->ptr_end - blk->ptr;
   495 
   495 
   496     memset(&line, 0, sizeof(line));
   496     memset(&line, 0, sizeof(line));
   497     line.timestamp  = blk->prefix.timestamp;
   497     line.timestamp  = blk->prefix.timestamp;
   498     line.flags      = blk->prefix.flags;
   498     line.flags      = blk->prefix.flags;
   523 //  hbuf_remove_receipt(hbuf, xep184)
   523 //  hbuf_remove_receipt(hbuf, xep184)
   524 // Remove the Receipt Flag for the message with the given xep184 id
   524 // Remove the Receipt Flag for the message with the given xep184 id
   525 // Returns TRUE if it was found and removed, otherwise FALSE
   525 // Returns TRUE if it was found and removed, otherwise FALSE
   526 gboolean hbuf_remove_receipt(GList *hbuf, gconstpointer xep184)
   526 gboolean hbuf_remove_receipt(GList *hbuf, gconstpointer xep184)
   527 {
   527 {
   528   hbuf_block *blk;
   528   hbuf_block_t *blk;
   529 
   529 
   530   hbuf = g_list_last(hbuf);
   530   hbuf = g_list_last(hbuf);
   531 
   531 
   532   for ( ; hbuf; hbuf = g_list_previous(hbuf)) {
   532   for ( ; hbuf; hbuf = g_list_previous(hbuf)) {
   533     blk = (hbuf_block*)(hbuf->data);
   533     blk = (hbuf_block_t*)(hbuf->data);
   534     if (!g_strcmp0(blk->prefix.xep184, xep184)) {
   534     if (!g_strcmp0(blk->prefix.xep184, xep184)) {
   535       g_free(blk->prefix.xep184);
   535       g_free(blk->prefix.xep184);
   536       blk->prefix.xep184 = NULL;
   536       blk->prefix.xep184 = NULL;
   537       blk->prefix.flags ^= HBB_PREFIX_RECEIPT;
   537       blk->prefix.flags ^= HBB_PREFIX_RECEIPT;
   538       return TRUE;
   538       return TRUE;
   545 // Set/Reset the readmark Flag
   545 // Set/Reset the readmark Flag
   546 // If action is TRUE, set a mark to the latest line,
   546 // If action is TRUE, set a mark to the latest line,
   547 // if action is FALSE, remove a previous readmark flag.
   547 // if action is FALSE, remove a previous readmark flag.
   548 void hbuf_set_readmark(GList *hbuf, gboolean action)
   548 void hbuf_set_readmark(GList *hbuf, gboolean action)
   549 {
   549 {
   550   hbuf_block *blk;
   550   hbuf_block_t *blk;
   551 
   551 
   552   if (!hbuf) return;
   552   if (!hbuf) return;
   553 
   553 
   554   hbuf = hbuf_previous_persistent(g_list_last(hbuf));
   554   hbuf = hbuf_previous_persistent(g_list_last(hbuf));
   555 
   555 
   556   if (action) {
   556   if (action) {
   557     // Add a readmark flag
   557     // Add a readmark flag
   558     blk = (hbuf_block*)(hbuf->data);
   558     blk = (hbuf_block_t*)(hbuf->data);
   559     blk->prefix.flags |= HBB_PREFIX_READMARK;
   559     blk->prefix.flags |= HBB_PREFIX_READMARK;
   560 
   560 
   561     // Shift hbuf in order to remove previous flags
   561     // Shift hbuf in order to remove previous flags
   562     // (maybe it can be optimized out, if there's no risk
   562     // (maybe it can be optimized out, if there's no risk
   563     //  we have several marks)
   563     //  we have several marks)
   564     hbuf = g_list_previous(hbuf);
   564     hbuf = g_list_previous(hbuf);
   565   }
   565   }
   566 
   566 
   567   // Remove old mark
   567   // Remove old mark
   568   for ( ; hbuf; hbuf = g_list_previous(hbuf)) {
   568   for ( ; hbuf; hbuf = g_list_previous(hbuf)) {
   569     blk = (hbuf_block*)(hbuf->data);
   569     blk = (hbuf_block_t*)(hbuf->data);
   570     if (blk->prefix.flags & HBB_PREFIX_READMARK) {
   570     if (blk->prefix.flags & HBB_PREFIX_READMARK) {
   571       blk->prefix.flags &= ~HBB_PREFIX_READMARK;
   571       blk->prefix.flags &= ~HBB_PREFIX_READMARK;
   572       break;
   572       break;
   573     }
   573     }
   574   }
   574   }
   576 
   576 
   577 //  hbuf_remove_trailing_readmark(hbuf)
   577 //  hbuf_remove_trailing_readmark(hbuf)
   578 // Unset the buffer readmark if it is on the last line
   578 // Unset the buffer readmark if it is on the last line
   579 void hbuf_remove_trailing_readmark(GList *hbuf)
   579 void hbuf_remove_trailing_readmark(GList *hbuf)
   580 {
   580 {
   581   hbuf_block *blk;
   581   hbuf_block_t *blk;
   582 
   582 
   583   if (!hbuf) return;
   583   if (!hbuf) return;
   584 
   584 
   585   hbuf = g_list_last(hbuf);
   585   hbuf = g_list_last(hbuf);
   586   blk = (hbuf_block*)(hbuf->data);
   586   blk = (hbuf_block_t*)(hbuf->data);
   587   blk->prefix.flags &= ~HBB_PREFIX_READMARK;
   587   blk->prefix.flags &= ~HBB_PREFIX_READMARK;
   588 }
   588 }
   589 
   589 
   590 //  hbuf_get_blocks_number()
   590 //  hbuf_get_blocks_number()
   591 // Returns the number of allocated hbuf_block's.
   591 // Returns the number of allocated hbuf_block_t's.
   592 guint hbuf_get_blocks_number(GList *hbuf)
   592 guint hbuf_get_blocks_number(GList *hbuf)
   593 {
   593 {
   594   hbuf_block *hbuf_b_elt;
   594   hbuf_block_t *hbuf_b_elt;
   595   guint count = 0U;
   595   guint count = 0U;
   596 
   596 
   597   for (hbuf = g_list_first(hbuf); hbuf; hbuf = g_list_next(hbuf)) {
   597   for (hbuf = g_list_first(hbuf); hbuf; hbuf = g_list_next(hbuf)) {
   598     hbuf_b_elt = (hbuf_block*)(hbuf->data);
   598     hbuf_b_elt = (hbuf_block_t*)(hbuf->data);
   599     if (hbuf_b_elt->flags & HBB_FLAG_ALLOC)
   599     if (hbuf_b_elt->flags & HBB_FLAG_ALLOC)
   600       count++;
   600       count++;
   601   }
   601   }
   602   return count;
   602   return count;
   603 }
   603 }