xfnw
856abd2f7d
git-subtree-dir: sys/src/cmd/gopher git-subtree-split: 3680728b631ed65201b397f4ae3e5d1b03be42f9
192 lines
3.9 KiB
C
192 lines
3.9 KiB
C
#include <u.h>
|
|
#include <libc.h>
|
|
#include <draw.h>
|
|
#include <event.h>
|
|
#include <panel.h>
|
|
#include "pldefs.h"
|
|
#include <keyboard.h>
|
|
|
|
typedef struct Entry Entry;
|
|
struct Entry{
|
|
char *entry;
|
|
char *entp;
|
|
char *eent;
|
|
void (*hit)(Panel *, char *);
|
|
Point minsize;
|
|
};
|
|
#define SLACK 7 /* enough for one extra rune and ◀ and a nul */
|
|
char *pl_snarfentry(Panel *p){
|
|
Entry *ep;
|
|
int n;
|
|
|
|
if(p->flags&USERFL) /* no snarfing from password entry */
|
|
return nil;
|
|
ep=p->data;
|
|
n=utfnlen(ep->entry, ep->entp-ep->entry);
|
|
if(n<1) return nil;
|
|
return smprint("%.*s", n, ep->entry);
|
|
}
|
|
void pl_pasteentry(Panel *p, char *s){
|
|
Entry *ep;
|
|
char *e;
|
|
int n, m;
|
|
|
|
ep=p->data;
|
|
n=ep->entp-ep->entry;
|
|
m=strlen(s);
|
|
e=pl_erealloc(ep->entry,n+m+SLACK);
|
|
ep->entry=e;
|
|
e+=n;
|
|
strncpy(e, s, m);
|
|
e+=m;
|
|
*e='\0';
|
|
ep->entp=ep->eent=e;
|
|
pldraw(p, p->b);
|
|
}
|
|
void pl_drawentry(Panel *p){
|
|
Rectangle r;
|
|
Entry *ep;
|
|
char *s;
|
|
|
|
ep=p->data;
|
|
r=pl_box(p->b, p->r, p->state);
|
|
s=ep->entry;
|
|
if(p->flags & USERFL){
|
|
char *p;
|
|
s=strdup(s);
|
|
for(p=s; *p; p++)
|
|
*p='*';
|
|
}
|
|
if(stringwidth(font, s)<=r.max.x-r.min.x)
|
|
pl_drawicon(p->b, r, PLACEW, 0, s);
|
|
else
|
|
pl_drawicon(p->b, r, PLACEE, 0, s);
|
|
if(s != ep->entry)
|
|
free(s);
|
|
}
|
|
int pl_hitentry(Panel *p, Mouse *m){
|
|
if((m->buttons&7)==1){
|
|
plgrabkb(p);
|
|
|
|
p->state=DOWN;
|
|
pldraw(p, p->b);
|
|
while(m->buttons&1){
|
|
int old;
|
|
old=m->buttons;
|
|
if(display->bufp > display->buf)
|
|
flushimage(display, 1);
|
|
*m=emouse();
|
|
if((old&7)==1){
|
|
if((m->buttons&7)==3){
|
|
Entry *ep;
|
|
|
|
plsnarf(p);
|
|
|
|
/* cut */
|
|
ep=p->data;
|
|
ep->entp=ep->entry;
|
|
*ep->entp='\0';
|
|
pldraw(p, p->b);
|
|
}
|
|
if((m->buttons&7)==5)
|
|
plpaste(p);
|
|
}
|
|
}
|
|
p->state=UP;
|
|
pldraw(p, p->b);
|
|
}
|
|
return 0;
|
|
}
|
|
void pl_typeentry(Panel *p, Rune c){
|
|
int n;
|
|
Entry *ep;
|
|
ep=p->data;
|
|
switch(c){
|
|
case '\n':
|
|
case '\r':
|
|
*ep->entp='\0';
|
|
if(ep->hit) ep->hit(p, ep->entry);
|
|
return;
|
|
case Kesc:
|
|
plsnarf(p);
|
|
/* no break */
|
|
case Kdel: /* clear */
|
|
case Knack: /* ^U: erase line */
|
|
ep->entp=ep->entry;
|
|
*ep->entp='\0';
|
|
break;
|
|
case Kbs: /* ^H: erase character */
|
|
while(ep->entp!=ep->entry && !pl_rune1st(ep->entp[-1])) *--ep->entp='\0';
|
|
if(ep->entp!=ep->entry) *--ep->entp='\0';
|
|
break;
|
|
case Ketb: /* ^W: erase word */
|
|
while(ep->entp!=ep->entry && !pl_idchar(ep->entp[-1]))
|
|
--ep->entp;
|
|
while(ep->entp!=ep->entry && pl_idchar(ep->entp[-1]))
|
|
--ep->entp;
|
|
*ep->entp='\0';
|
|
break;
|
|
default:
|
|
if(c < 0x20 || (c & 0xFF00) == KF || (c & 0xFF00) == Spec)
|
|
break;
|
|
ep->entp+=runetochar(ep->entp, &c);
|
|
if(ep->entp>ep->eent){
|
|
n=ep->entp-ep->entry;
|
|
ep->entry=pl_erealloc(ep->entry, n+100+SLACK);
|
|
ep->entp=ep->entry+n;
|
|
ep->eent=ep->entp+100;
|
|
}
|
|
*ep->entp='\0';
|
|
break;
|
|
}
|
|
pldraw(p, p->b);
|
|
}
|
|
Point pl_getsizeentry(Panel *p, Point children){
|
|
USED(children);
|
|
return pl_boxsize(((Entry *)p->data)->minsize, p->state);
|
|
}
|
|
void pl_childspaceentry(Panel *p, Point *ul, Point *size){
|
|
USED(p, ul, size);
|
|
}
|
|
void pl_freeentry(Panel *p){
|
|
Entry *ep;
|
|
ep = p->data;
|
|
free(ep->entry);
|
|
ep->entry = ep->eent = ep->entp = 0;
|
|
}
|
|
void plinitentry(Panel *v, int flags, int wid, char *str, void (*hit)(Panel *, char *)){
|
|
int elen;
|
|
Entry *ep;
|
|
ep=v->data;
|
|
v->flags=flags|LEAF;
|
|
v->state=UP;
|
|
v->draw=pl_drawentry;
|
|
v->hit=pl_hitentry;
|
|
v->type=pl_typeentry;
|
|
v->getsize=pl_getsizeentry;
|
|
v->childspace=pl_childspaceentry;
|
|
ep->minsize=Pt(wid, font->height);
|
|
v->free=pl_freeentry;
|
|
v->snarf=pl_snarfentry;
|
|
v->paste=pl_pasteentry;
|
|
elen=100;
|
|
if(str) elen+=strlen(str);
|
|
ep->entry=pl_erealloc(ep->entry, elen+SLACK);
|
|
ep->eent=ep->entry+elen;
|
|
strecpy(ep->entry, ep->eent, str ? str : "");
|
|
ep->entp=ep->entry+strlen(ep->entry);
|
|
ep->hit=hit;
|
|
v->kind="entry";
|
|
}
|
|
Panel *plentry(Panel *parent, int flags, int wid, char *str, void (*hit)(Panel *, char *)){
|
|
Panel *v;
|
|
v=pl_newpanel(parent, sizeof(Entry));
|
|
plinitentry(v, flags, wid, str, hit);
|
|
return v;
|
|
}
|
|
char *plentryval(Panel *p){
|
|
Entry *ep;
|
|
ep=p->data;
|
|
*ep->entp='\0';
|
|
return ep->entry;
|
|
}
|