mcabber/src/hbuf.c
author mikael
Sun, 01 May 2005 03:09:40 +0000
changeset 150 5647381a7dfb
parent 83 a95e2fc9ea6b
child 153 ae0844311710
permissions -rw-r--r--
[/trunk] Changeset 162 by mikael * Fix a severe bug in hbuf_rebuild()
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
71
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
     1
/*
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
     2
 * hbuf.c       -- History buffer implementation
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
     3
 * 
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
     4
 * Copyright (C) 2005 Mikael Berthe <bmikael@lists.lilotux.net>
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
     5
 *
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
     6
 * This program is free software; you can redistribute it and/or modify
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
     7
 * it under the terms of the GNU General Public License as published by
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
     8
 * the Free Software Foundation; either version 2 of the License, or (at
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
     9
 * your option) any later version.
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    10
 *
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    11
 * This program is distributed in the hope that it will be useful, but
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    12
 * WITHOUT ANY WARRANTY; without even the implied warranty of
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    14
 * General Public License for more details.
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    15
 *
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    16
 * You should have received a copy of the GNU General Public License
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    17
 * along with this program; if not, write to the Free Software
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    18
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    19
 * USA
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    20
 */
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    21
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    22
#include <string.h>
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    23
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    24
#include "hbuf.h"
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    25
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    26
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    27
/* This is a private structure type */
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    28
75
ff119bb11563 [/trunk] Changeset 89 by mikael
mikael
parents: 71
diff changeset
    29
#define PREFIX_LENGTH 32
71
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    30
typedef struct {
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    31
  char *ptr;
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    32
  char *ptr_end;
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    33
  guchar flags;
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    34
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    35
  // XXX This should certainly be a pointer, and be allocated only when needed
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    36
  // (for ex. when HBB_FLAG_PERSISTENT is set).
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    37
  struct { // hbuf_line_info
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    38
    char *ptr_end_alloc;
75
ff119bb11563 [/trunk] Changeset 89 by mikael
mikael
parents: 71
diff changeset
    39
    char prefix[PREFIX_LENGTH];
71
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    40
  } persist;
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    41
} hbuf_block;
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    42
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    43
75
ff119bb11563 [/trunk] Changeset 89 by mikael
mikael
parents: 71
diff changeset
    44
//  hbuf_add_line(p_hbuf, text, prefix, width)
71
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    45
// Add a line to the given buffer.  If width is not null, then lines are
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    46
// wrapped at this length.
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    47
//
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    48
// Note 1: Splitting according to width won't work if there are tabs; they
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    49
//         should be expanded before.
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    50
// Note 2: width does not include the ending \0.
75
ff119bb11563 [/trunk] Changeset 89 by mikael
mikael
parents: 71
diff changeset
    51
void hbuf_add_line(GList **p_hbuf, const char *text, const char *prefix,
ff119bb11563 [/trunk] Changeset 89 by mikael
mikael
parents: 71
diff changeset
    52
        unsigned int width)
71
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    53
{
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    54
  GList *hbuf = *p_hbuf;
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    55
  char *line, *cr, *end;
83
a95e2fc9ea6b [/trunk] Changeset 97 by mikael
mikael
parents: 75
diff changeset
    56
  hbuf_block *hbuf_block_elt;
71
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    57
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    58
  if (!text) return;
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    59
83
a95e2fc9ea6b [/trunk] Changeset 97 by mikael
mikael
parents: 75
diff changeset
    60
  hbuf_block_elt = g_new0(hbuf_block, 1);
75
ff119bb11563 [/trunk] Changeset 89 by mikael
mikael
parents: 71
diff changeset
    61
  if (prefix)
ff119bb11563 [/trunk] Changeset 89 by mikael
mikael
parents: 71
diff changeset
    62
    strncpy(hbuf_block_elt->persist.prefix, prefix, PREFIX_LENGTH-1);
71
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    63
  if (!hbuf) {
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    64
    hbuf_block_elt->ptr    = g_new(char, HBB_BLOCKSIZE);
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    65
    hbuf_block_elt->flags  = HBB_FLAG_ALLOC | HBB_FLAG_PERSISTENT;
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    66
    hbuf_block_elt->persist.ptr_end_alloc = hbuf_block_elt->ptr + HBB_BLOCKSIZE;
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    67
    *p_hbuf = g_list_append(*p_hbuf, hbuf_block_elt);
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    68
  } else {
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    69
    hbuf_block *hbuf_b_prev = g_list_last(hbuf)->data;
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    70
    hbuf_block_elt->ptr    = hbuf_b_prev->ptr_end;
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    71
    hbuf_block_elt->flags  = HBB_FLAG_PERSISTENT;
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    72
    hbuf_block_elt->persist.ptr_end_alloc = hbuf_b_prev->persist.ptr_end_alloc;
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    73
    *p_hbuf = g_list_append(*p_hbuf, hbuf_block_elt);
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    74
  }
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    75
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    76
  if (strlen(text) >= HBB_BLOCKSIZE) {
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    77
    // Too long
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    78
    text = "[ERR:LINE_TOO_LONG]";
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    79
  }
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    80
  if (hbuf_block_elt->ptr + strlen(text) >= hbuf_block_elt->persist.ptr_end_alloc) {
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    81
    // Too long for the current allocated bloc, we need another one
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    82
    hbuf_block_elt->ptr    = g_new0(char, HBB_BLOCKSIZE);
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    83
    hbuf_block_elt->flags  = HBB_FLAG_ALLOC | HBB_FLAG_PERSISTENT;
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    84
    hbuf_block_elt->persist.ptr_end_alloc = hbuf_block_elt->ptr + HBB_BLOCKSIZE;
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    85
  }
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    86
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    87
  line = hbuf_block_elt->ptr;
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    88
  // Ok, now we can copy the text..
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    89
  strcpy(line, text);
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    90
  hbuf_block_elt->ptr_end = line + strlen(line) + 1;
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    91
  end = hbuf_block_elt->ptr_end;
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    92
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    93
  // Let's add non-persistent blocs if necessary
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    94
  // - If there are '\n' in the string
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    95
  // - If length > width (and width != 0)
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    96
  cr = strchr(line, '\n');
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    97
  while (cr || (width && strlen(line) > width)) {
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    98
    hbuf_block *hbuf_b_prev = hbuf_block_elt;
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
    99
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   100
    if (!width || (cr && (cr - line <= (int)width))) {
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   101
      // Carriage return
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   102
      *cr = 0;
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   103
      hbuf_block_elt->ptr_end = cr;
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   104
      // Create another persistent block
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   105
      hbuf_block_elt = g_new0(hbuf_block, 1);
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   106
      hbuf_block_elt->ptr      = hbuf_b_prev->ptr_end + 1; // == cr+1
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   107
      hbuf_block_elt->ptr_end  = end;
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   108
      hbuf_block_elt->flags    = HBB_FLAG_PERSISTENT;
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   109
      hbuf_block_elt->persist.ptr_end_alloc = hbuf_b_prev->persist.ptr_end_alloc;
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   110
      *p_hbuf = g_list_append(*p_hbuf, hbuf_block_elt);
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   111
      line = hbuf_block_elt->ptr;
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   112
    } else {
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   113
      // We need to break where we can find a space char
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   114
      char *br; // break pointer
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   115
      for (br = line + width; br > line && *br != 32 && *br != 9; br--)
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   116
        ;
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   117
      if (br <= line)
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   118
        br = line + width;
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   119
      else
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   120
        br++;
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   121
      hbuf_block_elt->ptr_end = br;
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   122
      // Create another block, non-persistent
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   123
      hbuf_block_elt = g_new0(hbuf_block, 1);
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   124
      hbuf_block_elt->ptr      = hbuf_b_prev->ptr_end; // == br
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   125
      hbuf_block_elt->ptr_end  = end;
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   126
      hbuf_block_elt->flags    = 0;
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   127
      hbuf_block_elt->persist.ptr_end_alloc = hbuf_b_prev->persist.ptr_end_alloc;
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   128
      *p_hbuf = g_list_append(*p_hbuf, hbuf_block_elt);
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   129
      line = hbuf_block_elt->ptr;
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   130
    }
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   131
    cr = strchr(line, '\n');
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   132
  }
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   133
}
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   134
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   135
//  hbuf_free()
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   136
// Destroys all hbuf list.
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   137
void hbuf_free(GList **p_hbuf)
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   138
{
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   139
  hbuf_block *hbuf_b_elt;
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   140
  GList *hbuf_elt;
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   141
  GList *first_elt = g_list_first(*p_hbuf);
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   142
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   143
  for (hbuf_elt = first_elt; hbuf_elt; hbuf_elt = g_list_next(hbuf_elt)) {
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   144
    hbuf_b_elt = (hbuf_block*)(hbuf_elt->data);
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   145
    if (hbuf_b_elt->flags & HBB_FLAG_ALLOC) {
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   146
      g_free(hbuf_b_elt->ptr);
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   147
    }
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   148
  }
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   149
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   150
  g_list_free(*p_hbuf);
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   151
  *p_hbuf = NULL;
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   152
}
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   153
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   154
//  hbuf_rebuild()
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   155
// Rebuild all hbuf list, with the new width.
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   156
// If width == 0, lines are not wrapped.
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   157
void hbuf_rebuild(GList **p_hbuf, unsigned int width)
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   158
{
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   159
  GList *first_elt, *curr_elt, *next_elt;
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   160
  hbuf_block *hbuf_b_curr, *hbuf_b_next;
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   161
150
5647381a7dfb [/trunk] Changeset 162 by mikael
mikael
parents: 83
diff changeset
   162
  // *p_hbuf needs to be the head of the list
5647381a7dfb [/trunk] Changeset 162 by mikael
mikael
parents: 83
diff changeset
   163
  first_elt = *p_hbuf = g_list_first(*p_hbuf);
71
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   164
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   165
  // #1 Remove non-persistent blocks (ptr_end should be updated!)
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   166
  curr_elt = first_elt;
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   167
  while (curr_elt) {
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   168
    next_elt = g_list_next(curr_elt);
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   169
    // Last element?
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   170
    if (!next_elt)
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   171
      break;
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   172
    hbuf_b_curr = (hbuf_block*)(curr_elt->data);
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   173
    hbuf_b_next = (hbuf_block*)(next_elt->data);
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   174
    // Is next line not-persistent?
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   175
    if (!(hbuf_b_next->flags & HBB_FLAG_PERSISTENT)) {
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   176
      hbuf_b_curr->ptr_end = hbuf_b_next->ptr_end;
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   177
      g_list_delete_link(curr_elt, next_elt);
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   178
    } else 
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   179
      curr_elt = next_elt;
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   180
  }
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   181
  // #2 Go back to head and create non-persistent blocks when needed
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   182
  if (width) {
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   183
    char *line, *end;
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   184
    curr_elt = first_elt;
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   185
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   186
    while (curr_elt) {
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   187
      hbuf_b_curr = (hbuf_block*)(curr_elt->data);
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   188
      line = hbuf_b_curr->ptr;
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   189
      if (strlen(line) > width) {
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   190
        hbuf_block *hbuf_b_prev = hbuf_b_curr;
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   191
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   192
        // We need to break where we can find a space char
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   193
        char *br; // break pointer
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   194
        for (br = line + width; br > line && *br != 32 && *br != 9; br--)
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   195
          ;
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   196
        if (br <= line)
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   197
          br = line + width;
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   198
        else
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   199
          br++;
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   200
        end = hbuf_b_curr->ptr_end;
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   201
        hbuf_b_curr->ptr_end = br;
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   202
        // Create another block, non-persistent
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   203
        hbuf_b_curr = g_new0(hbuf_block, 1);
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   204
        hbuf_b_curr->ptr      = hbuf_b_prev->ptr_end; // == br
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   205
        hbuf_b_curr->ptr_end  = end;
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   206
        hbuf_b_curr->flags    = 0;
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   207
        hbuf_b_curr->persist.ptr_end_alloc = hbuf_b_prev->persist.ptr_end_alloc;
150
5647381a7dfb [/trunk] Changeset 162 by mikael
mikael
parents: 83
diff changeset
   208
        // This is OK because insert_before(NULL) == append():
5647381a7dfb [/trunk] Changeset 162 by mikael
mikael
parents: 83
diff changeset
   209
        *p_hbuf = g_list_insert_before(*p_hbuf, curr_elt->next, hbuf_b_curr);
71
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   210
      }
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   211
      curr_elt = g_list_next(curr_elt);
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   212
    }
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   213
  }
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   214
}
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   215
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   216
//  hbuf_get_lines(hbuf, n, where)
75
ff119bb11563 [/trunk] Changeset 89 by mikael
mikael
parents: 71
diff changeset
   217
// Returns an array of 2*n pointers (for n prefixes + n lines from hbuf)
ff119bb11563 [/trunk] Changeset 89 by mikael
mikael
parents: 71
diff changeset
   218
// (prefix line 1, line 1, prefix line 2, line 2, etc.)
71
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   219
// (The first line will be the line currently pointed by hbuf)
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   220
// Note:The caller should free the array after use.
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   221
char **hbuf_get_lines(GList *hbuf, unsigned int n)
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   222
{
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   223
  unsigned int i;
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   224
75
ff119bb11563 [/trunk] Changeset 89 by mikael
mikael
parents: 71
diff changeset
   225
  char **array = g_new0(char*, n*2);
71
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   226
  char **array_elt = array;
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   227
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   228
  for (i=0 ; i < n ; i++) {
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   229
    if (hbuf) {
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   230
      hbuf_block *blk = (hbuf_block*)(hbuf->data);
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   231
      int maxlen;
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   232
      maxlen = blk->ptr_end - blk->ptr;
75
ff119bb11563 [/trunk] Changeset 89 by mikael
mikael
parents: 71
diff changeset
   233
      *array_elt++ = blk->persist.prefix;
71
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   234
      *array_elt++ = g_strndup(blk->ptr, maxlen);
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   235
      hbuf = g_list_next(hbuf);
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   236
    } else
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   237
      *array_elt++ = NULL;
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   238
  }
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   239
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   240
  return array;
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   241
}
1e9d4949bcfd [/trunk] Changeset 85 by mikael
mikael
parents:
diff changeset
   242