[hackers] [wmii] Add locale charset crud. || Kris Maglione

From: <hg_AT_suckless.org>
Date: Sun, 6 Jun 2010 09:08:11 +0000 (UTC)

changeset: 2709:fc284933e0db
tag: tip
user: Kris Maglione <kris_AT_suckless.org>
date: Sun Jun 06 05:07:24 2010 -0400
files: LICENSE cmd/click/main.c cmd/menu/main.c cmd/menu/menu.c cmd/strut/main.c cmd/tray/main.c cmd/wmii/client.c cmd/wmii/main.c cmd/wmii9menu.c cmd/wmiir.c include/stuff/util.h lib/libstuff/Makefile lib/libstuff/fmt/blprint.c lib/libstuff/fmt/bvlprint.c lib/libstuff/fmt/fmtdef.h lib/libstuff/fmt/localefmt.c lib/libstuff/fmt/localelen.c lib/libstuff/fmt/lprint.c lib/libstuff/fmt/vlprint.c man/wmii.man1 man/wmiir.man1
description:
Add locale charset crud.

diff -r 521fb6b2f8ae -r fc284933e0db LICENSE
--- a/LICENSE Sat Jun 05 14:36:41 2010 -0400
+++ b/LICENSE Sun Jun 06 05:07:24 2010 -0400
@@ -1,6 +1,7 @@
 
-Copyright © 2006-2009 Kris Maglione <maglione.k_AT_gmail.com>
+Copyright © 2006-2010 Kris Maglione <maglione.k_AT_gmail.com>
 Copyright © 2003-2006 Anselm R Garbe <anselm_AT_garbe.us>
+Portions Copyright © 2002 by Lucent Technologies.
 
 Permission is hereby granted, free of charge, to any person obtaining a
 copy of this software and associated documentation files (the "Software"),
diff -r 521fb6b2f8ae -r fc284933e0db cmd/click/main.c
--- a/cmd/click/main.c Sat Jun 05 14:36:41 2010 -0400
+++ b/cmd/click/main.c Sun Jun 06 05:07:24 2010 -0400
@@ -41,8 +41,6 @@
                 usage();
         }ARGEND;
 
- setlocale(LC_CTYPE, "");
-
         initdisplay();
 
         s = ARGF();
diff -r 521fb6b2f8ae -r fc284933e0db cmd/menu/main.c
--- a/cmd/menu/main.c Sat Jun 05 14:36:41 2010 -0400
+++ b/cmd/menu/main.c Sun Jun 06 05:07:24 2010 -0400
@@ -186,8 +186,10 @@
         int i;
         long ndump;
 
+ setlocale(LC_CTYPE, "");
+ fmtinstall('r', errfmt);
         quotefmtinstall();
- fmtinstall('r', errfmt);
+
         screen_hint = PointerScreen;
 
         find = strstr;
@@ -227,7 +229,7 @@
                 cmdsep = EARGF(usage());
                 break;
         case 'v':
- print("%s", version);
+ lprint(1, "%s", version);
                 return 0;
         default:
                 usage();
@@ -236,8 +238,6 @@
         if(argc)
                 usage();
 
- setlocale(LC_CTYPE, "");
-
         initdisplay();
 
         xext_init();
diff -r 521fb6b2f8ae -r fc284933e0db cmd/menu/menu.c
--- a/cmd/menu/menu.c Sat Jun 05 14:36:41 2010 -0400
+++ b/cmd/menu/menu.c Sun Jun 06 05:07:24 2010 -0400
@@ -90,9 +90,9 @@
                 if(input.filter_start == 0 && input.pos == input.end)
                         menu_cmd(CMPL_FIRST, 0);
                 if(!motion && matchidx && !strcmp(input.string, matchidx->string))
- print("%s", matchidx->retstring);
+ lprint(1, "%s", matchidx->retstring);
                 else
- print("%s", input.string);
+ lprint(1, "%s", input.string);
                 break;
         case REJECT:
                 srv.running = false;
diff -r 521fb6b2f8ae -r fc284933e0db cmd/strut/main.c
--- a/cmd/strut/main.c Sat Jun 05 14:36:41 2010 -0400
+++ b/cmd/strut/main.c Sun Jun 06 05:07:24 2010 -0400
@@ -130,6 +130,7 @@
         ulong win;
         char *s;
 
+ setlocale(LC_CTYPE, "");
         fmtinstall('E', fmtevent);
 
         ARGBEGIN{
@@ -140,14 +141,12 @@
                 direction = DVertical;
                 break;
         case 'v':
- print("%s", version);
+ lprint(1, "%s", version);
                 return 0;
         default:
                 usage();
         }ARGEND;
 
- setlocale(LC_CTYPE, "");
-
         initdisplay();
 
         testwin = createwindow(&scr.root, Rect(0, 0, 1, 1), 0,
diff -r 521fb6b2f8ae -r fc284933e0db cmd/tray/main.c
--- a/cmd/tray/main.c Sat Jun 05 14:36:41 2010 -0400
+++ b/cmd/tray/main.c Sun Jun 06 05:07:24 2010 -0400
@@ -116,7 +116,6 @@
         program_args = argv;
 
         setlocale(LC_CTYPE, "");
-
         fmtinstall('r', errfmt);
         fmtinstall('E', fmtevent);
 
@@ -163,7 +162,7 @@
                 debug++;
                 break;
         case 'v':
- print("%s", version);
+ lprint(1, "%s", version);
                 return 0;
         default:
                 usage();
@@ -184,7 +183,7 @@
         if(tray.selection == nil)
                 fatal("Another system tray is already running.");
         if(tray.selection->oldowner)
- print("Replacing currently running system tray.\n");
+ lprint(1, "Replacing currently running system tray.\n");
 
         xext_init();
         tray_init();
diff -r 521fb6b2f8ae -r fc284933e0db cmd/wmii/client.c
--- a/cmd/wmii/client.c Sat Jun 05 14:36:41 2010 -0400
+++ b/cmd/wmii/client.c Sun Jun 06 05:07:24 2010 -0400
@@ -630,7 +630,6 @@
         ulong *pid;
         long n;
 
- c->dead = 1;
         if(!nice) {
                 getprop_textlist(&c->w, "WM_CLIENT_MACHINE", &host);
                 n = getprop_ulong(&c->w, Net("WM_PID"), "CARDINAL", 0, &pid, 1);
@@ -642,6 +641,7 @@
                 XKillClient(display, c->w.xid);
         }
         else if(c->proto & ProtoDelete) {
+ c->dead = 1;
                 client_message(c, "WM_DELETE_WINDOW", 0);
                 ewmh_checkresponsive(c);
         }
diff -r 521fb6b2f8ae -r fc284933e0db cmd/wmii/main.c
--- a/cmd/wmii/main.c Sat Jun 05 14:36:41 2010 -0400
+++ b/cmd/wmii/main.c Sun Jun 06 05:07:24 2010 -0400
@@ -335,12 +335,12 @@
         char *wmiirc, *s;
         int i;
 
- quotefmtinstall();
+ setlocale(LC_CTYPE, "");
         fmtinstall('r', errfmt);
         fmtinstall('a', afmt);
         fmtinstall('C', Cfmt);
-extern int fmtevent(Fmt*);
         fmtinstall('E', fmtevent);
+ quotefmtinstall();
 
         wmiirc = "wmiirc";
 
@@ -353,7 +353,7 @@
                 wmiirc = EARGF(usage());
                 break;
         case 'v':
- print("%s", version);
+ lprint(1, "%s", version);
                 exit(0);
         case 'D':
                 s = EARGF(usage());
@@ -368,7 +368,6 @@
         if(argc)
                 usage();
 
- setlocale(LC_CTYPE, "");
         starting = true;
 
         initdisplay();
diff -r 521fb6b2f8ae -r fc284933e0db cmd/wmii9menu.c
--- a/cmd/wmii9menu.c Sat Jun 05 14:36:41 2010 -0400
+++ b/cmd/wmii9menu.c Sun Jun 06 05:07:24 2010 -0400
@@ -116,7 +116,7 @@
 
         ARGBEGIN{
         case 'v':
- print("%s\n", version);
+ lprint(1, "%s\n", version);
                 return 0;
         case 'a':
                 address = EARGF(usage());
@@ -172,8 +172,8 @@
 void
 usage(void)
 {
- fprintf(stderr, "usage: %s -v\n", argv0);
- fprintf(stderr, " %s [-a <address>] [-i <arg>] menitem[:command] ...\n", argv0);
+ lprint(2, "usage: %s -v\n", argv0);
+ lprint(2, " %s [-a <address>] [-i <arg>] menitem[:command] ...\n", argv0);
         exit(0);
 }
 
@@ -210,8 +210,7 @@
                 XNextEvent(display, &ev);
                 switch (ev.type) {
                 default:
- fprintf(stderr, "%s: unknown ev.type %d\n",
- argv0, ev.type);
+ lprint(2, "%s: unknown ev.type %d\n", argv0, ev.type);
                         break;
                 case ButtonRelease:
                         i = ev.xbutton.y / high;
@@ -220,7 +219,7 @@
                         else if(i < 0 || i >= numitems)
                                 return;
 
- printf("%s\n", commands[i]);
+ lprint(1, "%s\n", commands[i]);
                         return;
                 case ButtonPress:
                 case MotionNotify:
diff -r 521fb6b2f8ae -r fc284933e0db cmd/wmiir.c
--- a/cmd/wmiir.c Sat Jun 05 14:36:41 2010 -0400
+++ b/cmd/wmiir.c Sun Jun 06 05:07:24 2010 -0400
@@ -4,23 +4,28 @@
 #define IXP_NO_P9_
 #define IXP_P9_STRUCTS
 #include <dirent.h>
+#include <limits.h>
+#include <locale.h>
 #include <stdio.h>
 #include <string.h>
 #include <sys/signal.h>
 #include <time.h>
 #include <unistd.h>
+#include <wchar.h>
+
 #include <ixp.h>
 #include <stuff/util.h>
 #include <bio.h>
 #include <fmt.h>
 
-static IxpClient *client;
-static Biobuf *outbuf;
+static IxpClient* client;
+static Biobuf* outbuf;
+static bool binary;
 
 static void
 usage(void) {
- fprint(1,
- "usage: %s [-a <address>] {create | ls [-dlp] | read | remove | write} <file>\n"
+ lprint(1,
+ "usage: %s [-a <address>] [-b] {create | ls [-dlp] | read | remove | write} <file>\n"
                " %s [-a <address>] xwrite <file> <data>\n"
                " %s -v\n", argv0, argv0, argv0);
         exit(1);
@@ -31,21 +36,110 @@
         return fmtstrcpy(f, ixp_errbuf());
 }
 
+static bool
+flush(IxpCFid *fid, char *in, int len, bool binary) {
+ static mbstate_t state;
+ static char buf[IXP_MAX_MSG];
+ static char *out = buf, *outend = buf + sizeof buf;
+ char *inend;
+ wchar_t w;
+ Rune r;
+ int res;
+
+ if(binary)
+ return ixp_write(fid, in, len) == len;
+
+ inend = in + len;
+ do {
+ if(in == nil || out + UTFmax > outend) {
+ if(ixp_write(fid, buf, out - buf) != out - buf)
+ return false;
+ out = buf;
+ }
+ if(in == nil) {
+ state = (mbstate_t){0};
+ return true;
+ }
+
+ switch((res = mbrtowc(&w, in, inend - in, &state))) {
+ case -1:
+ return false;
+ case 0:
+ case -2:
+ return true;
+ default:
+ in += res;
+ r = w < Runemax ? w : Runesync;
+ out += runetochar(out, &r);
+ }
+ } while(in < inend);
+ return true;
+}
+
+static bool
+unflush(int fd, char *in, int len, bool binary) {
+ static mbstate_t state;
+ static char buf[IXP_MAX_MSG], extra[UTFmax];
+ static char *out = buf, *outend = buf + sizeof buf;
+ static int nextra;
+ char *start;
+ Rune r;
+ int res, n;
+
+ if(binary)
+ return write(fd, in, len) == len;
+
+ if(in) {
+ if((n = nextra)) {
+ nextra = 0;
+ while(len > 0 && n < UTFmax && !fullrune(extra, n)) {
+ extra[n++] = *in++;
+ len--;
+ }
+ unflush(fd, extra, n, binary);
+ }
+ n = utfnlen(in, len);
+ }
+
+ start = in;
+ do {
+ if(in == nil || out + MB_LEN_MAX > outend) {
+ if(write(fd, buf, out - buf) != out - buf)
+ return false;
+ out = buf;
+ }
+ if(in == nil || n == 0) {
+ state = (mbstate_t){0};
+ return true;
+ }
+
+ in += chartorune(&r, in);
+ n--;
+ res = wcrtomb(out, r, &state);
+ if(res == -1)
+ *out++ = '?';
+ else
+ out += res;
+ } while(n > 0);
+ if(in < start + len) {
+ nextra = min(sizeof extra, len - (in - start));
+ memcpy(extra, in, nextra);
+ }
+ return true;
+}
+
 /* Utility Functions */
 static void
-write_data(IxpCFid *fid, char *name) {
- void *buf;
+write_data(IxpCFid *fid, char *name, bool binary) {
+ char buf[IXP_MAX_MSG];
         int len;
 
- buf = emalloc(fid->iounit);;
- for(;;) {
- len = read(0, buf, fid->iounit);
- if(len <= 0)
- break;
- if(ixp_write(fid, buf, len) != len)
+ while((len = read(0, buf, fid->iounit)) > 0)
+ if(!flush(fid, buf, len, binary))
                         fatal("cannot write file %q\n", name);
- }
- free(buf);
+
+ if(!binary)
+ flush(fid, nil, 0, binary);
 }
 
 static int
@@ -101,14 +195,14 @@
                 file = "";
 
         if(lflag)
- Bprint(outbuf, "%s %s %s %5llud %s %s%s%s\n",
- modestr(s->mode), s->uid, s->gid, s->length,
- timestr(s->mtime), file, slash, s->name);
+ Blprint(outbuf, "%s %s %s %5llud %s %s%s%s\n",
+ modestr(s->mode), s->uid, s->gid, s->length,
+ timestr(s->mtime), file, slash, s->name);
         else {
                 if((s->mode&P9_DMDIR) && strcmp(s->name, "/"))
- Bprint(outbuf, "%s%s%s/\n", file, slash, s->name);
+ Blprint(outbuf, "%s%s%s/\n", file, slash, s->name);
                 else
- Bprint(outbuf, "%s%s%s\n", file, slash, s->name);
+ Blprint(outbuf, "%s%s%s\n", file, slash, s->name);
         }
 }
 
@@ -128,7 +222,7 @@
         if(fid == nil)
                 fatal("Can't open file '%s': %r\n", file);
 
- write_data(fid, file);
+ write_data(fid, file, binary);
         ixp_close(fid);
         return 0;
 }
@@ -160,7 +254,7 @@
                         strcat(buf, " ");
         }
 
- if(ixp_write(fid, buf, nbuf) == -1)
+ if(!(flush(fid, buf, nbuf, binary) && (binary || flush(fid, 0, 0, binary))))
                 fatal("cannot write file '%s': %r\n", file);
         ixp_close(fid);
         free(buf);
@@ -183,7 +277,7 @@
                 fatal("Can't create file '%s': %r\n", file);
 
         if((fid->qid.type&P9_DMDIR) == 0)
- write_data(fid, file);
+ write_data(fid, file, binary);
         ixp_close(fid);
         return 0;
 }
@@ -200,7 +294,7 @@
         file = EARGF(usage());
         do {
                 if(!ixp_remove(client, file))
- fprint(2, "%s: Can't remove file '%s': %r\n", argv0, file);
+ lprint(2, "%s: Can't remove file '%s': %r\n", argv0, file);
         }while((file = ARGF()));
         return 0;
 }
@@ -226,11 +320,13 @@
 
                 buf = emalloc(fid->iounit);
                 while((count = ixp_read(fid, buf, fid->iounit)) > 0)
- write(1, buf, count);
+ unflush(1, buf, count, binary);
+ if(!binary)
+ unflush(1, 0, 0, binary);
                 ixp_close(fid);
 
                 if(count == -1)
- fprint(2, "%s: cannot read file '%s': %r\n", argv0, file);
+ lprint(2, "%s: cannot read file '%s': %r\n", argv0, file);
         } while((file = ARGF()));
 
         return 0;
@@ -327,7 +423,7 @@
         path = ixp_namespace();
         if(path == nil)
                 fatal("can't find namespace: %r\n");
- Bprint(outbuf, "%s\n", path);
+ Blprint(outbuf, "%s\n", path);
         return 0;
 }
 
@@ -345,6 +441,7 @@
         }ARGEND;
 
         while((dir = ARGF()))
+ /* Don't use Blprint. wimenu expects UTF-8. */
                 if((d = opendir(dir))) {
                         while((de = readdir(d)))
                                 if(access(de->d_name, X_OK))
@@ -418,14 +515,20 @@
         exectab *tab;
         int ret;
 
+ setlocale(LC_ALL, "");
+ binary = utf8locale();
+
         quotefmtinstall();
         fmtinstall('r', errfmt);
 
         address = getenv("WMII_ADDRESS");
 
         ARGBEGIN{
+ case 'b':
+ binary = true;
+ break;
         case 'v':
- print("%s-" VERSION ", " COPYRIGHT "\n", argv0);
+ lprint(1, "%s-" VERSION ", " COPYRIGHT "\n", argv0);
                 exit(0);
         case 'a':
                 address = EARGF(usage());
diff -r 521fb6b2f8ae -r fc284933e0db include/stuff/util.h
--- a/include/stuff/util.h Sat Jun 05 14:36:41 2010 -0400
+++ b/include/stuff/util.h Sun Jun 06 05:07:24 2010 -0400
@@ -3,7 +3,9 @@
  */
 
 #include <stuff/geom.h>
+#include <langinfo.h>
 #include <stdarg.h>
+#include <bio.h>
 #include <fmt.h>
 #include <regexp9.h>
 
@@ -26,6 +28,12 @@
         GInvert = 1<<0,
 };
 
+enum {
+ Runemax = (1 << (sizeof(Rune) * 8)) - 1,
+};
+
+#define utf8locale() (!strcmp(nl_langinfo(CODESET), "UTF-8"))
+
 #ifdef VARARGCK
 # pragma varargck argpos _die 3
 # pragma varargck argpos fatal 1
@@ -35,7 +43,8 @@
 #define strlcat stuff_strlcat
 #define strcasestr stuff_strcasestr
 
-
+int Blprint(Biobuf*, const char*, ...);
+int Bvlprint(Biobuf*, const char*, va_list);
 void _die(char*, int, char*, ...);
 void backtrace(char*);
 void closeexec(int);
@@ -48,12 +57,16 @@
 char* estrndup(const char*, uint);
 void fatal(const char*, ...);
 void* freelater(void*);
-int getbase(const char**, long*);
-bool getint(const char*, int*);
-bool getlong(const char*, long*);
-bool getulong(const char*, ulong*);
+int getbase(const char**, long*);
+bool getint(const char*, int*);
+bool getlong(const char*, long*);
+bool getulong(const char*, ulong*);
 void grep(char**, Reprog*, int);
 char* join(char**, char*, Fmt*);
+int localefmt(Fmt*);
+void localefmtinstall(void);
+int localelen(char*, char*);
+int lprint(int, const char*, ...);
 int max(int, int);
 int min(int, int);
 uvlong nsec(void);
@@ -64,7 +77,7 @@
 int spawn3l(int[3], const char*, ...);
 uint stokenize(char**, uint, char*, char*);
 char* strcasestr(const char*, const char*);
-char* strend(char*, int);
+char* strend(char*, int);
 uint strlcat(char*, const char*, uint);
 int strlcatprint(char*, int, const char*, ...);
 char* sxprint(const char*, ...);
@@ -73,6 +86,7 @@
 void uniq(char**);
 int unquote(char*, char*[], int);
 int utflcpy(char*, const char*, int);
+int vlprint(int, const char*, va_list);
 char* vsxprint(const char*, va_list);
 extern char buffer[8092];
 extern char* _buffer;
diff -r 521fb6b2f8ae -r fc284933e0db lib/libstuff/Makefile
--- a/lib/libstuff/Makefile Sat Jun 05 14:36:41 2010 -0400
+++ b/lib/libstuff/Makefile Sun Jun 06 05:07:24 2010 -0400
@@ -34,6 +34,12 @@
         event/selectionrequest \
         event/unmapnotify \
         event/xtime \
+ fmt/blprint \
+ fmt/bvlprint \
+ fmt/localefmt \
+ fmt/localelen \
+ fmt/lprint \
+ fmt/vlprint \
         geom/get_sticky \
         geom/quadrant \
         geom/rect_contains_p \
diff -r 521fb6b2f8ae -r fc284933e0db lib/libstuff/fmt/blprint.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/libstuff/fmt/blprint.c Sun Jun 06 05:07:24 2010 -0400
@@ -0,0 +1,19 @@
+/* Copyright ©2010 Kris Maglione <maglione.k at Gmail>
+ * Copyright ©2002 by Lucent Technologies.
+ * See LICENSE file for license details.
+ */
+#include "fmtdef.h"
+#include <bio.h>
+
+int
+Blprint(Biobuf *bp, const char *fmt, ...)
+{
+ va_list arg;
+ int n;
+
+ va_start(arg, fmt);
+ n = Bvlprint(bp, fmt, arg);
+ va_end(arg);
+ return n;
+}
+
diff -r 521fb6b2f8ae -r fc284933e0db lib/libstuff/fmt/bvlprint.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/libstuff/fmt/bvlprint.c Sun Jun 06 05:07:24 2010 -0400
@@ -0,0 +1,58 @@
+/* Copyright ©2010 Kris Maglione <maglione.k at Gmail>
+ * Copyright ©2002 by Lucent Technologies.
+ * See LICENSE file for license details.
+ */
+#include "fmtdef.h"
+#include <bio.h>
+
+static int
+fmtBlflush(Fmt *f)
+{
+ mbstate_t state;
+ Biobuf *bp;
+ Rune *rp, *rend;
+ int res;
+
+ bp = f->farg;
+ rend = f->to;
+ state = (mbstate_t){0};
+ for(rp=(Rune*)f->start; rp < rend; rp++) {
+ if(MB_LEN_MAX + bp->ocount > 0 && Bflush(bp) < 0)
+ return 0;
+
+ res = wcrtomb((char*)bp->ebuf + bp->ocount, *rp, &state);
+ if(res == -1)
+ Bputc(bp, '?');
+ else
+ bp->ocount += res;
+ }
+ f->to = f->start;
+ return 1;
+}
+
+int
+Bvlprint(Biobuf *bp, const char *fmt, va_list args)
+{
+ Fmt f;
+ Rune buf[256];
+ int res;
+
+ if(utf8locale())
+ return Bvprint(bp, fmt, args);
+
+ f.runes = 1;
+ f.start = (char*)buf;
+ f.to = (char*)buf;
+ f.stop = (char*)(buf + nelem(buf) - 1);
+ f.flush = fmtBlflush;
+ f.farg = bp;
+ f.nfmt = 0;
+
+ va_copy(f.args, args);
+ res = dofmt(&f, fmt);
+ va_end(f.args);
+ if(res > 0 && fmtBlflush(&f) == 0)
+ return -1;
+ return res;
+}
+
diff -r 521fb6b2f8ae -r fc284933e0db lib/libstuff/fmt/fmtdef.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/libstuff/fmt/fmtdef.h Sun Jun 06 05:07:24 2010 -0400
@@ -0,0 +1,10 @@
+#include <stuff/util.h>
+#include <langinfo.h>
+#include <limits.h>
+#include <string.h>
+#include <wchar.h>
+
+extern void* __fmtflush(Fmt *f, void *t, int len);
+extern int __fmtpad(Fmt *f, int n);
+extern int __rfmtpad(Fmt *f, int n);
+
diff -r 521fb6b2f8ae -r fc284933e0db lib/libstuff/fmt/localefmt.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/libstuff/fmt/localefmt.c Sun Jun 06 05:07:24 2010 -0400
@@ -0,0 +1,107 @@
+/* Copyright ©2010 Kris Maglione <maglione.k at Gmail>
+ * Copyright ©2002 by Lucent Technologies.
+ * See LICENSE file for license details.
+ */
+#include "fmtdef.h"
+
+static bool
+pad(Fmt *f, int len) {
+ if(f->flags & FmtWidth) {
+ if(f->runes)
+ return __rfmtpad(f, f->width - len) >= 0;
+ return __fmtpad(f, f->width - len) >= 0;
+ }
+ return true;
+}
+
+int
+localefmt(Fmt *f) {
+ mbstate_t state;
+ Rune *rp, *rend;
+ char *sp, *send, *str, *end;
+ Rune r;
+ wchar_t w;
+ int res, count, rlen;
+
+ str = va_arg(f->args, char*);
+
+ if(utf8locale()) {
+ /* We handle precision in bytes, fmtstrcpy in characters */
+ if(f->flags & FmtPrec)
+ f->prec = utfnlen(str, f->prec);
+ return fmtstrcpy(f, str);
+ }
+
+ end = 0;
+ if(f->flags & FmtPrec)
+ end = str + f->prec;
+
+ if(!(f->flags & FmtLeft) && !pad(f, localelen(str, end)))
+ return -1;
+
+ sp = f->to;
+ send = f->stop;
+ rp = (Rune*)f->to;
+ rend = (Rune*)f->stop;
+
+ count = 0;
+ for(state = (mbstate_t){0}; ; str += res) {
+ switch((res = mbrtowc(&w, str, end ? end - str : MB_LEN_MAX, &state))) {
+ case 0:
+ case -2:
+ break;
+ case -1:
+ w = Runesync;
+ res = 1;
+ /* Fallthrough. */
+ default:
+ count++;
+ if(w > Runemax)
+ w = Runesync;
+ r = w;
+ // print("%d %C\n", res, r);
+ if(f->runes) {
+ if(rp >= rend) {
+ // print("flush\n");
+ rp = (Rune*)__fmtflush(f, rp, sizeof *rp);
+ rend = (Rune*)f->stop;
+ if(rp == nil)
+ return -1;
+ }
+ *rp++ = r;
+ }else {
+ if(sp + UTFmax > send && sp + (rlen = runelen(r)) > send) {
+ // print("flush %d\n", rlen);
+ sp = __fmtflush(f, sp, rlen);
+ send = f->stop;
+ if(sp == nil)
+ return -1;
+ }
+ if(r < Runeself)
+ *sp++ = (char)r;
+ else
+ sp += runetochar(sp, &r);
+ }
+ continue;
+ }
+ if(f->runes) {
+ f->nfmt += rp - (Rune*)f->to;
+ f->to = (char*)rp;
+ }else {
+ f->nfmt += sp - (char*)f->to;
+ f->to = sp;
+ }
+ break;
+ }
+
+ if((f->flags & FmtLeft) && !pad(f, count))
+ return -1;
+
+ return 0;
+}
+
+void
+localefmtinstall(void) {
+ fmtinstall('L', localefmt);
+}
+
diff -r 521fb6b2f8ae -r fc284933e0db lib/libstuff/fmt/localelen.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/libstuff/fmt/localelen.c Sun Jun 06 05:07:24 2010 -0400
@@ -0,0 +1,33 @@
+/* Copyright ©2010 Kris Maglione <maglione.k at Gmail>
+ * Copyright ©2002 by Lucent Technologies.
+ * See LICENSE file for license details.
+ */
+#include "fmtdef.h"
+
+int
+localelen(char *str, char *end) {
+ mbstate_t state;
+ size_t n, res;
+
+ if(utf8locale()) {
+ if(end)
+ return utfnlen(str, end - str);
+ return utflen(str);
+ }
+
+ state = (mbstate_t){0};
+ n = 0;
+ for(n=0;;)
+ switch((res = mbrtowc(nil, str, end ? end - str : MB_LEN_MAX, &state))) {
+ case -1:
+ return -1;
+ case 0:
+ case -2:
+ return n;
+ default:
+ n++;
+ str += res;
+ }
+ return n; /* Not reached. */
+}
+
diff -r 521fb6b2f8ae -r fc284933e0db lib/libstuff/fmt/lprint.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/libstuff/fmt/lprint.c Sun Jun 06 05:07:24 2010 -0400
@@ -0,0 +1,17 @@
+/* Copyright ©2010 Kris Maglione <maglione.k at Gmail>
+ * Copyright ©2002 by Lucent Technologies.
+ * See LICENSE file for license details.
+ */
+#include "fmtdef.h"
+
+int
+lprint(int fd, const char *fmt, ...) {
+ va_list ap;
+ int res;
+
+ va_start(ap, fmt);
+ res = vlprint(fd, fmt, ap);
+ va_end(ap);
+ return res;
+}
+
diff -r 521fb6b2f8ae -r fc284933e0db lib/libstuff/fmt/vlprint.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/libstuff/fmt/vlprint.c Sun Jun 06 05:07:24 2010 -0400
@@ -0,0 +1,60 @@
+/* Copyright ©2010 Kris Maglione <maglione.k at Gmail>
+ * Copyright ©2002 by Lucent Technologies.
+ * See LICENSE file for license details.
+ */
+#include "fmtdef.h"
+#include <unistd.h>
+
+static int
+fmtlfdflush(Fmt *f) {
+ mbstate_t state;
+ char buf[256];
+ Rune *rp, *rend;
+ char *sp, *send;
+ int res;
+
+ sp = buf;
+ send = buf + sizeof buf - UTFmax;
+ rend = f->to;
+ state = (mbstate_t){0};
+ for(rp=(Rune*)f->start; rp < rend; rp++) {
+ res = wcrtomb(sp, *rp, &state);
+ if(res == -1)
+ *sp++ = '?'; /* Fixme? */
+ else
+ sp += res;
+ if(sp >= send || rp == rend - 1) {
+ if(write((uintptr_t)f->farg, buf, sp - buf) != sp - buf)
+ return 0;
+ sp = buf;
+ }
+ }
+ f->to = f->start;
+ return 1;
+}
+
+int
+vlprint(int fd, const char *fmt, va_list args) {
+ Fmt f;
+ Rune buf[256];
+ int res;
+
+ if(utf8locale())
+ return vfprint(fd, fmt, args);
+
+ f.runes = 1;
+ f.start = (char*)buf;
+ f.to = (char*)buf;
+ f.stop = (char*)(buf + nelem(buf) - 1);
+ f.flush = fmtlfdflush;
+ f.farg = (void*)(uintptr_t)fd;
+ f.nfmt = 0;
+
+ va_copy(f.args, args);
+ res = dofmt(&f, fmt);
+ va_end(f.args);
+ if(res > 0 && fmtlfdflush(&f) == 0)
+ return -1;
+ return res;
+}
+
diff -r 521fb6b2f8ae -r fc284933e0db man/wmii.man1
--- a/man/wmii.man1 Sat Jun 05 14:36:41 2010 -0400
+++ b/man/wmii.man1 Sun Jun 06 05:07:24 2010 -0400
@@ -210,17 +210,19 @@
 It is usually accessed via the wmiir(1) command, but it
 can be accessed by any ``9P``, including plan9port's
 9P[1], and can be mounted natively on Linux via v9fs[1],
-and on Inferno (which man run on top of Linux).
+and on Inferno (which man run on top of Linux). All data in the
+filesystem, including filenames, is UTF-8 encoded. However, when
+accessed via wmiir(1), text is automatically translated to and
+from your locale encoding.
 
 The filesystem is, as are many other 9P filesystems, entirely
 synthetic. The files exist only in memory, and are not written
 to disk. They are generally initiated on wmii startup via a
-script such as rc.wmii or wmiirc. Several files read commands,
-others simply act as if they were ordinary files (their contents
-are updated and returned exactly as written), though writing
-them has side-effects (such as changing key bindings). A
-description of the filesystem layout and control commands
-follows.
+script such as wmiirc. Several files read commands, others
+simply act as if they were ordinary files (their contents are
+updated and returned exactly as written), though writing them
+has side-effects (such as changing key bindings). A description
+of the filesystem layout and control commands follows.
 
 == Hierarchy ==
 
diff -r 521fb6b2f8ae -r fc284933e0db man/wmiir.man1
--- a/man/wmiir.man1 Sat Jun 05 14:36:41 2010 -0400
+++ b/man/wmiir.man1 Sun Jun 06 05:07:24 2010 -0400
@@ -10,8 +10,8 @@
 
 = SYNOPSIS =
 
-wmiir [-a <address>] {create | ls [-dlp] | read | remove | write} <file> +
-wmiir [-a <address>] xwrite <file> <data> ... +
+wmiir [-a <address>] [-b] {create | ls [-dlp] | read | remove | write} <file> +
+wmiir [-a <address>] [-b] xwrite <file> <data> ... +
 wmiir -v
 
 = DESCRIPTION =
@@ -21,10 +21,20 @@
 issue commands to `wmii`, both from the command line and from its `sh`-based
 configuration scripts.
 
+Since the default encoding of 9P filesystems is UTF-8, `wmiir`
+assumes that all data read and written is text data and
+translates to or from your locale character encoding as
+necessary. When working with non-text data in a non-UTF-8
+locale, the _-b_ flag should be specified to disable this
+behavior.
+
 = ARGUMENTS =
 
 : -a
         The address at which to connect to `wmii`.
+: -b
+ With the _-b_ flag, data that you intend to read or
+ write is treated as binary data.
 :
 = COMMANDS =
 
Received on Sun Jun 06 2010 - 09:08:11 UTC

This archive was generated by hypermail 2.2.0 : Sun Jun 06 2010 - 09:12:04 UTC