/* * mooterm/mootermline.h * * Copyright (C) 2004-2005 by Yevgen Muntyan * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * See COPYING file that comes with this distribution. */ #ifndef MOOTERM_MOOTERMLINE_H #define MOOTERM_MOOTERMLINE_H #ifndef MOOTERM_COMPILATION #error "This file may not be included directly" #endif #include #include G_BEGIN_DECLS typedef struct _MooTermCell MooTermCell; typedef struct _MooTermLine MooTermLine; #define EMPTY_CHAR ' ' static MooTermTextAttr ZERO_ATTR; /* FALSE if equal */ inline static gboolean attr_cmp (MooTermTextAttr *a1, MooTermTextAttr *a2) { return a1->mask != a2->mask || ((a1->mask & MOO_TERM_TEXT_FOREGROUND) && (a1->foreground != a2->foreground)) || ((a1->mask & MOO_TERM_TEXT_BACKGROUND) && (a1->background != a2->background)); } #define TERM_LINE(ar) ((MooTermLine*) (ar)) #define TERM_LINE_ARRAY(line) ((GArray*) (line)) struct _MooTermCell { gunichar ch; MooTermTextAttr attr; }; struct _MooTermLine { MooTermCell *data; guint len; }; inline static MooTermLine *term_line_new (guint len) { return TERM_LINE (g_array_sized_new (FALSE, FALSE, sizeof (MooTermCell), len)); } inline static void term_line_free (MooTermLine *line) { if (line) g_array_free (TERM_LINE_ARRAY (line), TRUE); } inline static guint term_line_len (MooTermLine *line) { return line->len; } inline static void term_line_set_len (MooTermLine *line, guint len) { if (line->len > len) g_array_set_size (TERM_LINE_ARRAY (line), len); } inline static void term_line_erase (MooTermLine *line) { term_line_set_len (line, 0); } inline static void term_line_erase_range (MooTermLine *line, guint pos, guint len) { guint i; if (!len) return; if (pos + len >= line->len) return term_line_set_len (line, pos); for (i = pos; i < pos + len; ++i) { line->data[pos].ch = EMPTY_CHAR; line->data[pos].attr.mask = 0; } } inline static void term_line_delete_range (MooTermLine *line, guint pos, guint len) { if (pos >= line->len) return; else if (pos + len >= line->len) return term_line_set_len (line, pos); else g_array_remove_range (TERM_LINE_ARRAY (line), pos, len); } inline static void term_line_set_unichar (MooTermLine *line, guint pos, gunichar c, guint num, MooTermTextAttr *attr, guint width) { guint i; if (pos >= width) return term_line_set_len (line, width); if (pos + num >= width) num = width - pos; if (!attr || !attr->mask) attr = &ZERO_ATTR; if (!c) c = EMPTY_CHAR; term_line_set_len (line, width); if (pos >= line->len) { MooTermCell cell = {EMPTY_CHAR, ZERO_ATTR}; for (i = 0; i < pos - line->len; ++i) g_array_append_val (TERM_LINE_ARRAY (line), cell); cell.ch = c; cell.attr = *attr; for (i = 0; i < num; ++i) g_array_append_val (TERM_LINE_ARRAY (line), cell); } else if (pos + num > line->len) { MooTermCell cell = {c, *attr}; for (i = pos; i < line->len; ++i) g_array_index (TERM_LINE_ARRAY (line), MooTermCell, i) = cell; for (i = 0; i < pos + num - line->len; ++i) g_array_append_val (TERM_LINE_ARRAY (line), cell); } else { MooTermCell cell = {c, *attr}; for (i = pos; i < pos + num; ++i) g_array_index (TERM_LINE_ARRAY (line), MooTermCell, i) = cell; } } inline static void term_line_insert_unichar (MooTermLine *line, guint pos, gunichar c, guint num, MooTermTextAttr *attr, guint width) { guint i; if (pos >= width) return term_line_set_len (line, width); if (pos + num >= width) return term_line_set_unichar (line, pos, c, num, attr, width); if (!attr || !attr->mask) attr = &ZERO_ATTR; if (!c) c = EMPTY_CHAR; term_line_set_len (line, width); for (i = 0; i < num; ++i) { MooTermCell cell = {c, *attr}; g_array_insert_val (TERM_LINE_ARRAY (line), pos, cell); } } inline static gunichar term_line_get_unichar (MooTermLine *line, guint col) { return g_array_index (TERM_LINE_ARRAY (line), MooTermCell, col).ch; } inline static guint term_line_get_chars (MooTermLine *line, char *buf, guint first, int len) { guint i; guint res = 0; if (!len || first >= line->len) return 0; if (len < 0 || first + len > line->len) len = line->len - first; for (i = first; i < first + len; ++i) { gunichar c = term_line_get_unichar (line, i); guint l = g_unichar_to_utf8 (c, buf); buf += l; res += l; } return res; } G_END_DECLS #endif /* MOOTERM_MOOTERMLINE_H */