giftcurs-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[giFTcurs-commits] giFTcurs/src format.c format.h parse.c parse.h


From: Christian Häggström
Subject: [giFTcurs-commits] giFTcurs/src format.c format.h parse.c parse.h
Date: Fri, 17 Oct 2003 12:39:00 -0400

CVSROOT:        /cvsroot/giftcurs
Module name:    giFTcurs
Branch:         
Changes by:     Christian Häggström <address@hidden>    03/10/17 12:39:00

Modified files:
        src            : format.c format.h parse.c parse.h 

Log message:
        Format strings now utf-8 clean, almose Wide characters on a boundary 
are not handled yet

Patches:
Index: giFTcurs/src/format.c
diff -u giFTcurs/src/format.c:1.68 giFTcurs/src/format.c:1.69
--- giFTcurs/src/format.c:1.68  Mon Sep 15 17:28:17 2003
+++ giFTcurs/src/format.c       Fri Oct 17 12:38:59 2003
@@ -18,7 +18,7 @@
  * along with giFTcurs; if not, write to the Free Software Foundation,
  * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,  USA.
  *
- * $Id: format.c,v 1.68 2003/09/15 21:28:17 saturn Exp $
+ * $Id: format.c,v 1.69 2003/10/17 16:38:59 saturn Exp $
  */
 #include "giftcurs.h"
 
@@ -32,6 +32,7 @@
 #include "format.h"
 #include "screen.h"
 #include "settings.h"
+#include "ui_draw.h"                   /* for vstrlen */
 
 #if HAVE_STATFS
 # include <sys/types.h>
@@ -141,7 +142,10 @@
                        char scale;
                        unsigned left_justify:1;
                } attr;
-               char *text;
+               struct {
+                       char *text;
+                       int visual_len;
+               } text;
                struct {
                        int color;
                        int bold;
@@ -189,7 +193,11 @@
                switch (getattr(item, fmt, &v)) {
                case ATTR_STRLEN:
                        len = v.strlen.len;
+                       /* fall thru */
                case ATTR_STRING:
+                       /* TODO: find out if strxfrm does the same as
+                        * g_utf8_collate_key in an UTF-8 locale.
+                        */
                        len = strxfrm(bufp, v.string, len) + 1;
                        if (rev) {
                                int i;
@@ -227,11 +235,11 @@
        if (*res && memcmp(*res, buf, bufp - buf) == 0)
                return 0;
        g_free(*res);
-       *res = g_new(char, bufp - buf);
-       memcpy(*res, buf, bufp - buf);
+       *res = g_memdup(buf, bufp - buf);
        return 1;
 }
 
+/* FIXME: Use a hash table here? */
 struct macro {
        char *id;
        format_t expansion;
@@ -311,11 +319,14 @@
        int total_len;
 };
 
-static void spacefill(char *s, int spaces)
+static void spacefill(GString *s, int spaces)
 {
-       while (spaces--)
-               *s++ = ' ';
-       *s = '\0';
+       char *p;
+
+       g_assert(spaces >= 0);
+       g_string_set_size(s, s->len + spaces);
+       for (p = s->str + s->len - spaces; spaces; p++, spaces--)
+               *p = ' ';
 }
 
 static int digits(unsigned int i)
@@ -360,7 +371,7 @@
        case ATTR_STRLEN:
                return v->strlen.len;
        case ATTR_STRING:
-               return strlen(v->string);
+               return vstrlen(v->string);
        case ATTR_INT:
                return digits(v->intval);
        case ATTR_LONG:
@@ -434,7 +445,6 @@
 struct format_counters {
        int spaces;
        int n;
-       int nonprint;
        int variable;
 };
 
@@ -486,8 +496,7 @@
        /* parse string backwards */
        format_t pos = NULL, endif = NULL, pending = NULL, fixedpos = NULL;
        int n = strlen(src);
-       char buf[9256];
-       char *bufp = buf + sizeof buf - 1;
+       GString buf = { 0 };
        int progress_on = 0;
        int fixed_on = 0;
 
@@ -495,30 +504,29 @@
        format_t o_endif = NULL, o_pending = NULL;
        int o_progress_on = 0;
 
-       *bufp = '\0';
-
        while (n >= 0) {
                char *command, *args;
                format_t tmp;
 
                if (n > 0 && src[n - 1] == '\\') {
                        /* escaped character */
-                       *--bufp = src[n];
+                       g_string_prepend_c(&buf, src[n]);
                        n -= 2;
                        continue;
                }
                if (src[n] != '}') {
                        /* ordinary character */
-                       *--bufp = src[n];
+                       g_string_prepend_c(&buf, src[n]);
                        n--;
                        continue;
                }
 
-               if (*bufp) {
+               if (buf.len) {
                        /* ordinary characters to declare */
                        pos = new_node(TEXT, pos);
-                       pos->u.text = g_strdup(bufp);
-                       bufp = buf + sizeof buf - 1;
+                       pos->u.text.text = buf.str;
+                       pos->u.text.visual_len = vstrlen(buf.str);
+                       memset(&buf, 0, sizeof buf);
                }
 
                /* we have a command ending with } */
@@ -718,10 +726,10 @@
                return NULL;
        }
 
-       if (*bufp) {
+       if (buf.len) {
                pos = new_node(TEXT, pos);
-               pos->u.text = g_strdup(bufp);
-               bufp = buf + sizeof buf - 1;
+               pos->u.text.text = buf.str;
+               pos->u.text.visual_len = vstrlen(buf.str);
        }
        return pos;
 }
@@ -743,7 +751,7 @@
                g_free(n->u.attr.name);
                break;
        case TEXT:
-               g_free(n->u.text);
+               g_free(n->u.text.text);
                break;
        case PROGRESS:
                g_free(n->u.progress.total);
@@ -769,7 +777,7 @@
  * total characters, nonprinted (color) characters, and {space}s */
 static struct format_counters format_collect(format_t n, struct format_ctrl *k)
 {
-       struct format_counters c = { 0, 0, 0, 0 };
+       struct format_counters c = { 0, 0, 0 };
 
        while (n) {
                switch (n->type) {
@@ -798,15 +806,13 @@
                        c.n += width;
                        break;
                case TEXT:
-                       c.n += strlen(n->u.text);
+                       c.n += n->u.text.visual_len;
                        break;
                case PROGRESS:
-                       c.nonprint += 4;
                        break;
                case ENDPROGRESS:
                        break;
                case COLOR:
-                       c.nonprint += 2;
                        break;
                case SPACE:
                        c.spaces++;
@@ -816,28 +822,22 @@
                                struct format_counters c2 = 
format_collect(n->u.macro, k);
 
                                c.n += c2.n;
-                               c.nonprint += c2.nonprint;
                                c.spaces += c2.spaces;
                                c.variable += c2.variable;
                        }
                        break;
                case FIXED:
                        {
-                               int old_maxlen = k->total_len;
                                int len = n->u.fixed.width;
 
                                if (n->u.fixed.percent)
-                                       len = len * old_maxlen / 100;
+                                       len = len * k->total_len / 100;
 
-                               k->total_len = len;
-                               c.nonprint += format_collect(n->u.fixed.body, 
k).nonprint;
-                               k->total_len = old_maxlen;
                                c.n += len;
                        }
                        break;
                }
                if (c.n - c.variable > k->total_len) {
-                       c.nonprint += c.n - c.variable - k->total_len;
                        c.n = k->total_len + c.variable;
                        break;
                }
@@ -846,24 +846,44 @@
        return c;
 }
 
+static int utf8_visual_to_offset(const char *str, int visual)
+{
+       const char *p;
+
+       for (p = str; visual > 0; p = g_utf8_next_char(p), visual--) {
+               if (g_unichar_iswide(g_utf8_get_char(p)))
+                       visual--;
+       }
+       return p - str;
+}
+
+static void string_append_len(GString *str, const char *string, int width)
+{
+       if (utf8)
+               width = utf8_visual_to_offset(string, width);
+       g_string_append_len(str, string, width);
+}
+
 /* Fill str with the actual data. All rendering info is provided in k */
-static int format_produce(format_t n, struct format_ctrl *k, char *str, int 
produced,
+/* TODO: The color_stack could be a GString */
+static int format_produce(format_t n, struct format_ctrl *k, GString *str, int 
produced,
                                                  dynarray *color_stack)
 {
-       char *progress_mark = NULL;
+       int progress_mark_visual = -1;
+       int progress_mark_offset = -1;
        float progress_start = 0.0;
        float progress_end = 0.0;
 
        while (n) {
-               str += strlen(str);
+#if 0
                if (produced > k->total_len) {
                        str[k->total_len - produced] = '\0';
                        return k->total_len;
                }
+#endif
                switch (n->type) {
                        int i, width, valwidth, color;
                        char mode;
-                       char *s;
                        const char *string;
                        attr_value v;
                        enum attr_type t;
@@ -922,24 +942,24 @@
                        if (string == NULL)
                                string = value_to_string(t, &v);
                        if (valwidth == -1)
-                               valwidth = strlen(string);
+                               valwidth = vstrlen(string);
 
                        /* output the string s with the given width */
+                       /* TODO: handle wide characters on the cut boundary */
                        if (valwidth >= width) {
-                               strncat(str, string, width);
+                               string_append_len(str, string, width);
                        } else if (n->u.attr.left_justify) {
-                               strncat(str, string, valwidth);
-                               strpad(str, width);
+                               string_append_len(str, string, valwidth);
+                               spacefill(str, width - valwidth);
                        } else {
-                               strpad(str, width - valwidth);
-                               strncat(str, string, valwidth);
+                               spacefill(str, width - valwidth);
+                               string_append_len(str, string, valwidth);
                        }
-                       str[width] = '\0';
                        produced += width;
                        break;
                case TEXT:
-                       strcpy(str, n->u.text);
-                       produced += strlen(str);
+                       g_string_append(str, n->u.text.text);
+                       produced += n->u.text.visual_len;
                        break;
                case PROGRESS:
                        total = attribute_long(n->u.progress.total, k);
@@ -965,27 +985,44 @@
                                else
                                        progress_end = (float) start / (float) 
total;
 
-                               progress_mark = str;
+                               progress_mark_visual = produced;
+                               progress_mark_offset = str->len;
                        }
                        break;
                case ENDPROGRESS:
-                       if (progress_mark) {
-                               i = str - progress_mark;
+                       if (progress_mark_visual >= 0) {
+                               int start, end;
 
-                               s = progress_mark + (int) (progress_end * i);
-                               memmove(s + 2, s, strlen(s) + 1);
-                               s[0] = '\v';
-                               s[1] = 'a' + COLOR_STANDARD - 1;
-
-                               s = progress_mark + (int) (progress_start * i);
-                               memmove(s + 2, s, strlen(s) + 1);
-                               s[0] = '\v';
-                               s[1] = '4';
-                               progress_mark = NULL;
+                               i = produced - progress_mark_visual;
+                               start = (int) (progress_start * i);
+                               end = (int) (progress_end * i);
+
+                               if (start >= end) {
+                                       progress_mark_visual = -1;
+                                       break;
+                               }
+
+                               /* TODO: handle wide characters on the 
boundaries */
+                               if (utf8) {
+                                       start = utf8_visual_to_offset(str->str 
+ progress_mark_offset, start);
+                                       end = utf8_visual_to_offset(str->str + 
progress_mark_offset, end);
+                               }
+                               start += progress_mark_offset;
+                               end += progress_mark_offset;
+                               /* reset to the previous color */
+                               if (color_stack->num)
+                                       color = 
GPOINTER_TO_INT(list_index(color_stack, color_stack->num - 1));
+                               else
+                                       color = 0;      /* {standard} */
+                               g_string_insert_c(str, end, '\v');
+                               g_string_insert_c(str, end + 1, 'a' + color);
+                               g_string_insert_c(str, start, '\v');
+                               g_string_insert_c(str, start + 1, 'a' + 
COLOR_PROGRESS - 1);
+                               progress_mark_visual = -1;
                        }
                        break;
                case COLOR:
-                       str[0] = '\v';
+                       g_string_append_c(str, '\v');
                        color = n->u.color.color;
                        if (color == -1) {
                                /* pop a color from the stack */
@@ -999,10 +1036,9 @@
                                dynarray_append(color_stack, 
GINT_TO_POINTER(color));
                        }
                        if (n->u.color.bold)
-                               str[1] = 'A' + color;
+                               g_string_append_c(str, 'A' + color);
                        else
-                               str[1] = 'a' + color;
-                       str[2] = '\0';
+                               g_string_append_c(str, 'a' + color);
                        break;
                case SPACE:
                        width = k->space_len / k->spaces;
@@ -1023,7 +1059,7 @@
                                        len = len * k->total_len / 100;
 
                                substr = format_expand(n->u.fixed.body, 
k->getattr, len, k->udata);
-                               strcpy(str, substr);
+                               g_string_append(str, substr);
                                g_free(substr);
 
                                produced += len;
@@ -1041,7 +1077,7 @@
        /* size is array size in bytes, lenght is the printed out lenght */
        struct format_ctrl morot;
        struct format_counters c;
-       char *str;
+       GString str = { 0 };
        int slack;
        dynarray color_stack = { 0 };
 
@@ -1063,16 +1099,14 @@
 
        morot.slack = slack;
 
-       str = g_malloc(maxlen + c.nonprint + 1);
-       str[0] = '\0';
+       /* TODO: For performance, str can be allocated to maxlen bytes */
 
        /* Fill the string with actual stuff */
-       format_produce(format, &morot, str, 0, &color_stack);
+       format_produce(format, &morot, &str, 0, &color_stack);
        dynarray_removeall(&color_stack);
+       /*DEBUG("planned length %d, actual lenght %d", maxlen, 
vstrlen(str.str)); */
 
-       g_assert(maxlen + c.nonprint >= strlen(str));
-
-       return str;
+       return str.str;
 }
 
 void format_clear(void)
Index: giFTcurs/src/format.h
diff -u giFTcurs/src/format.h:1.16 giFTcurs/src/format.h:1.17
--- giFTcurs/src/format.h:1.16  Mon Jun 30 04:10:54 2003
+++ giFTcurs/src/format.h       Fri Oct 17 12:39:00 2003
@@ -18,7 +18,7 @@
  * along with giFTcurs; if not, write to the Free Software Foundation,
  * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,  USA.
  *
- * $Id: format.h,v 1.16 2003/06/30 08:10:54 weinholt Exp $
+ * $Id: format.h,v 1.17 2003/10/17 16:39:00 saturn Exp $
  */
 #ifndef _FORMAT_H
 #define _FORMAT_H
@@ -27,10 +27,10 @@
 
 /* This union can hold all kinds of values used by format strings */
 typedef union {
-       const char *string;                     /* type = ATTR_STRING 
(nul-terminated) */
+       const char *string;                     /* type = ATTR_STRING 
(nul-terminated utf-8) */
        unsigned int intval;            /* type = ATTR_INT */
        guint64 longval;                        /* type = ATTR_LONG */
-       struct {                                        /* type = ATTR_STRLEN 
(fixed length) */
+       struct {                                        /* type = ATTR_STRLEN 
(fixed length ascii) */
                const char *string;             /* - pointer to first character 
*/
                int len;                                /* - string length */
        } strlen;
Index: giFTcurs/src/parse.c
diff -u giFTcurs/src/parse.c:1.148 giFTcurs/src/parse.c:1.149
--- giFTcurs/src/parse.c:1.148  Tue Oct 14 15:49:35 2003
+++ giFTcurs/src/parse.c        Fri Oct 17 12:39:00 2003
@@ -18,7 +18,7 @@
  * along with giFTcurs; if not, write to the Free Software Foundation,
  * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,  USA.
  *
- * $Id: parse.c,v 1.148 2003/10/14 19:49:35 weinholt Exp $
+ * $Id: parse.c,v 1.149 2003/10/17 16:39:00 saturn Exp $
  */
 #include "giftcurs.h"
 
@@ -54,16 +54,6 @@
        return fnord;
 }
 
-void strpad(char *s, size_t length)
-{
-       char *p = strchr(s, '\0');
-
-       length -= (p - s);
-       if (length > 0)
-               memset(p, ' ', length);
-       p[length] = '\0';
-}
-
 const char *const suffixchars = "bkMGTPEZY";
 
 const char *humanify_base(guint64 quantity_l, int base, int limit)
@@ -217,7 +207,7 @@
 #endif
 }
 
-char *itoa(int n)
+const char *itoa(int n)
 {
        static char buf[20];
 
Index: giFTcurs/src/parse.h
diff -u giFTcurs/src/parse.h:1.91 giFTcurs/src/parse.h:1.92
--- giFTcurs/src/parse.h:1.91   Tue Oct 14 15:49:35 2003
+++ giFTcurs/src/parse.h        Fri Oct 17 12:39:00 2003
@@ -18,7 +18,7 @@
  * along with giFTcurs; if not, write to the Free Software Foundation,
  * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,  USA.
  *
- * $Id: parse.h,v 1.91 2003/10/14 19:49:35 weinholt Exp $
+ * $Id: parse.h,v 1.92 2003/10/17 16:39:00 saturn Exp $
  */
 #ifndef _PARSE_H
 #define _PARSE_H
@@ -26,9 +26,6 @@
 /* removes extra whitespace */
 char *trim(char *foo);
 
-/* right-pads a string with spaces, until strlen(foo) == length */
-void strpad(char *s, size_t length);
-
 /* translates quantity to a "human-friendly" string, same format as "df -H"
  * for example: 1231424 1000   10000  10239   10240  1023999 1024000
  * becomes    : "1.1M"  "1000" "9.7k" "9.9k"  " 10k" "999k"  "0.9M"
@@ -63,14 +60,14 @@
 unsigned int my_atoi(const char *str);
 
 /* Converts an integer to a static string. (not thread-safe!) */
-char *itoa(int n);
+const char *itoa(int n);
 
 /* This is like atof but gives the result times 2^30, and can handle
    any character as decimal point. */
 guint64 my_giga_atof(const char *foo);
 
 /* Parse a typed query into the real query and the excludes */
-void parse_typed_query(const char *_query, char **includes, char **excludes, 
char **protocols);
+void parse_typed_query(const char *query_, char **includes, char **excludes, 
char **protocols);
 
 #include "list.h"
 




reply via email to

[Prev in Thread] Current Thread [Next in Thread]