wmii

git clone git://oldgit.suckless.org/wmii/
Log | Files | Refs | README | LICENSE

localefmt.c (2018B)


      1 /* Copyright ©2010 Kris Maglione <maglione.k at Gmail>
      2  * Copyright ©2002 by Lucent Technologies.
      3  * See LICENSE file for license details.
      4  */
      5 #include "fmtdef.h"
      6 
      7 static bool
      8 pad(Fmt *f, int len) {
      9 	if(f->flags & FmtWidth) {
     10 		if(f->runes)
     11 			return __rfmtpad(f, f->width - len) >= 0;
     12 		return __fmtpad(f, f->width - len) >= 0;
     13 	}
     14 	return true;
     15 }
     16 
     17 int
     18 localefmt(Fmt *f) {
     19 	mbstate_t state;
     20 	Rune *rp, *rend;
     21 	char *sp, *send, *str, *end;
     22 	Rune r;
     23 	wchar_t w;
     24 	int res, count, rlen;
     25 
     26 	str = va_arg(f->args, char*);
     27 
     28 	if(utf8locale()) {
     29 		/* We handle precision in bytes, fmtstrcpy in characters */
     30 		if(f->flags & FmtPrec)
     31 			f->prec = utfnlen(str, f->prec);
     32 		return fmtstrcpy(f, str);
     33 	}
     34 
     35 	end = 0;
     36 	if(f->flags & FmtPrec)
     37 		end = str + f->prec;
     38 
     39 	if(!(f->flags & FmtLeft) && !pad(f, localelen(str, end)))
     40 		return -1;
     41 
     42 	sp = f->to;
     43 	send = f->stop;
     44 	rp = (Rune*)f->to;
     45 	rend = (Rune*)f->stop;
     46 
     47 	count = 0;
     48 	for(state = (mbstate_t){0}; ; str += res) {
     49 		switch((res = mbrtowc(&w, str, end ? end - str : MB_LEN_MAX, &state))) {
     50 		case 0:
     51 		case -2:
     52 			break;
     53 		case -1:
     54 			w = Runesync;
     55 			res = 1;
     56 			/* Fallthrough. */
     57 		default:
     58 			count++;
     59 			if(w > Runemax)
     60 				w = Runesync;
     61 			r = w;
     62 			// print("%d %C\n", res, r);
     63 			if(f->runes) {
     64 				if(rp >= rend) {
     65 					// print("flush\n");
     66 					rp = (Rune*)__fmtflush(f, rp, sizeof *rp);
     67 					rend = (Rune*)f->stop;
     68 					if(rp == nil)
     69 						return -1;
     70 				}
     71 				*rp++ = r;
     72 			}else {
     73 				if(sp + UTFmax > send && sp + (rlen = runelen(r)) > send) {
     74 					// print("flush %d\n", rlen);
     75 					sp = __fmtflush(f, sp, rlen);
     76 					send = f->stop;
     77 					if(sp == nil)
     78 						return -1;
     79 				}
     80 				if(r < Runeself)
     81 					*sp++ = (char)r;
     82 				else
     83 					sp += runetochar(sp, &r);
     84 			}
     85 			continue;
     86 		}
     87 		if(f->runes) {
     88 			f->nfmt += rp - (Rune*)f->to;
     89 			f->to = (char*)rp;
     90 		}else {
     91 			f->nfmt += sp - (char*)f->to;
     92 			f->to = sp;
     93 		}
     94 		break;
     95 	}
     96 
     97 	if((f->flags & FmtLeft) && !pad(f, count))
     98 		return -1;
     99 
    100 	return 0;
    101 }
    102 
    103 void
    104 localefmtinstall(void) {
    105 	fmtinstall('L', localefmt);
    106 }
    107