1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
|
/*
* Copyright (C) 2002,2009 Red Hat, Inc.
*
* This is free software; you can redistribute it and/or modify it under
* the terms of the GNU Library General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Red Hat Author(s): Nalin Dahyabhai, Behdad Esfahbod
*/
#include <config.h>
#include "debug.h"
#include "vterowdata.h"
#include <string.h>
/*
* VteCells: A row's cell array
*/
typedef struct _VteCells VteCells;
struct _VteCells {
guint32 alloc_len;
VteCell cells[1];
};
static inline VteCells *
_vte_cells_for_cell_array (VteCell *cells)
{
if (G_UNLIKELY (!cells))
return NULL;
return (VteCells *) (((guchar *) cells) - G_STRUCT_OFFSET (VteCells, cells));
}
static VteCells *
_vte_cells_realloc (VteCells *cells, guint32 len)
{
guint32 alloc_len = (1 << g_bit_storage (MAX (len, 80))) - 1;
_vte_debug_print(VTE_DEBUG_RING, "Enlarging cell array of %d cells to %d cells\n", cells ? cells->alloc_len : 0, alloc_len);
cells = g_realloc (cells, G_STRUCT_OFFSET (VteCells, cells) + alloc_len * sizeof (cells->cells[0]));
cells->alloc_len = alloc_len;
return cells;
}
static void
_vte_cells_free (VteCells *cells)
{
_vte_debug_print(VTE_DEBUG_RING, "Freeing cell array of %d cells\n", cells->alloc_len);
g_free (cells);
}
/*
* VteRowData: A row's data
*/
void
_vte_row_data_init (VteRowData *row)
{
memset (row, 0, sizeof (*row));
}
void
_vte_row_data_clear (VteRowData *row)
{
VteCell *cells = row->cells;
_vte_row_data_init (row);
row->cells = cells;
}
void
_vte_row_data_fini (VteRowData *row)
{
if (row->cells)
_vte_cells_free (_vte_cells_for_cell_array (row->cells));
row->cells = NULL;
}
static inline gboolean
_vte_row_data_ensure (VteRowData *row, gulong len)
{
VteCells *cells = _vte_cells_for_cell_array (row->cells);
if (G_LIKELY (cells && len <= cells->alloc_len))
return TRUE;
if (G_UNLIKELY (len >= 0xFFFF))
return FALSE;
row->cells = _vte_cells_realloc (cells, len)->cells;
return TRUE;
}
void
_vte_row_data_insert (VteRowData *row, gulong col, const VteCell *cell)
{
gulong i;
if (G_UNLIKELY (!_vte_row_data_ensure (row, row->len + 1)))
return;
for (i = row->len; i > col; i--)
row->cells[i] = row->cells[i - 1];
row->cells[col] = *cell;
row->len++;
}
void _vte_row_data_append (VteRowData *row, const VteCell *cell)
{
if (G_UNLIKELY (!_vte_row_data_ensure (row, row->len + 1)))
return;
row->cells[row->len] = *cell;
row->len++;
}
void _vte_row_data_remove (VteRowData *row, gulong col)
{
gulong i;
for (i = col + 1; i < row->len; i++)
row->cells[i - 1] = row->cells[i];
if (G_LIKELY (row->len))
row->len--;
}
void _vte_row_data_fill (VteRowData *row, const VteCell *cell, gulong len)
{
if (row->len < len) {
gulong i = len - row->len;
if (G_UNLIKELY (!_vte_row_data_ensure (row, len)))
return;
for (i = row->len; i < len; i++)
row->cells[i] = *cell;
row->len = len;
}
}
void _vte_row_data_shrink (VteRowData *row, gulong max_len)
{
if (max_len < row->len)
row->len = max_len;
}
|