[Top][All Lists]
[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"
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [giFTcurs-commits] giFTcurs/src format.c format.h parse.c parse.h,
Christian Häggström <=