#include <u.h>
#include <libc.h>
#include <draw.h>
#include <keyboard.h>
#include <cursor.h>
#include <mouse.h>
#include <frame.h>
#include <thread.h>
#include "dat.h"
#include "fns.h"
extern Window *w;
typedef enum {
eZero=0,
eTitle,
eColor,
eInfinite,
} eType;
enum {
ESC = 0x1b,
};
static void
esctitle(const Rune* start, const Rune* end)
{
char* p;
// fprint(2, "esctitle(%.*S)\n", end-start, start);
p = smprint("%.*S", end-start-3, start+3);
if(p){
drawsetlabel(p);
free(w->dir);
w->dir = p;
/* remove trailing /-sysname if present */
p = strrchr(p, '/');
if(p && *(p+1) == '-'){
if(p == w->dir)
p++;
*p = 0;
}
}
}
static void
esctitleonly(const Rune* start, const Rune* end)
{
esctitle(start+1, end);
}
static void
esccolor(const Rune* start, const Rune* end)
{
// fprint(2, "_ecolor(%#.*S)\n", end-start, start);
}
static void
escnop(const Rune* start, const Rune* end)
{
}
/* this parsing method isn't sufficient for every case.
for example erase n characters is ESC [ <n> K
so the color-wacking could eat too much if we get
"ESC [Kwhatever, man" → "an" oops
also, if we match the start, we don't backtrack if
runstrnchar fails.
*/
struct {
Rune start[5];
char end;
eType esc;
void (*fn)(const Rune*, const Rune*);
} esc_tab[] = {
{{0}, 0, 0, escnop},
{{']', ';', 0}, '\007', eTitle, esctitle},
{{']', '1', ';', 0}, '\007', eTitle, escnop}, // set "icon" title only
{{']', '2', ';', 0}, '\007', eTitle, esctitleonly},
{{'[', 0}, 'm', eColor, esccolor},
0
};
static Rune*
runestrnchr(const Rune* r, char c, unsigned long len){
for(; len--; r++){
if (c == *r){
// fprint(2, "→ %.*S, %uld\n", len, r, len);
return (Rune*)r;
}
}
return 0;
}
eType
matchEsc(const Rune* r, const Rune* er, Rune** start, Rune** end)
{
eType i;
int j;
int runesleft;
if (er<r){
return eZero;
}
runesleft = er-r;
for(i=1; esc_tab[i].esc; i++){
for(j=0; j<=runesleft && r[j] == esc_tab[i].start[j]; j++){
if (0 == esc_tab[i].start[j+1])
goto match;
}
}
// fprint(2, "loosing on %uld runesleft %.*S\n", runesleft, runesleft, *start);
return eZero;
match:
*start = (Rune*)r;
r += j+1;
*end = runestrnchr(r, esc_tab[i].end, er-r);
if (!*end)
return eZero;
return esc_tab[i].esc;
}
int
labelcooked(Rune *sr, int n)
{
Rune *sl, *el, *er, *r;
eType esctype;
er = sr+n;
esctype = eZero;
for(r=sr; r<=er; ){
if (*r == ESC){
esctype = matchEsc(r+1, er, &sl, &el);
if (!esctype){
r++;
continue;
}
esc_tab[esctype].fn(r, el);
el++;
runemove(r, el, er-el);
n -= el-r;
er = sr+n;
} else
r++;
}
return n;
}
int
labelnone(Rune *s, int n)
{
return n;
}
|