blob: 7dcf5affcd7c26fee91aa898fabdb43a2adfdfba [file] [log] [blame]
#include <u.h>
#include <libc.h>
#include <draw.h>
#include <thread.h>
#include <mouse.h>
#include <cursor.h>
#include <keyboard.h>
#include <frame.h>
#include "flayer.h"
#include "samterm.h"
uchar **name; /* first byte is ' ' or '\'': modified state */
Text **text; /* pointer to Text associated with file */
ushort *tag; /* text[i].tag, even if text[i] not defined */
int nname;
int mname;
int mw;
char *genmenu3(int);
char *genmenu2(int);
char *genmenu2c(int);
enum Menu2
{
Cut,
Paste,
Snarf,
Plumb,
Look,
Exch,
Search,
NMENU2 = Search,
Send = Search,
NMENU2C
};
enum Menu3
{
New,
Zerox,
Resize,
Close,
Write,
NMENU3
};
char *menu2str[] = {
"cut",
"paste",
"snarf",
"plumb",
"look",
"<rio>",
0, /* storage for last pattern */
};
char *menu3str[] = {
"new",
"zerox",
"resize",
"close",
"write"
};
Menu menu2 = {0, genmenu2};
Menu menu2c ={0, genmenu2c};
Menu menu3 = {0, genmenu3};
void
menu2hit(void)
{
Text *t=(Text *)which->user1;
int w = which-t->l;
int m;
if(hversion==0 || plumbfd<0)
menu2str[Plumb] = "(plumb)";
m = menuhit(2, mousectl, t==&cmd? &menu2c : &menu2, nil);
if(hostlock || t->lock)
return;
switch(m){
case Cut:
cut(t, w, 1, 1);
break;
case Paste:
paste(t, w);
break;
case Snarf:
snarf(t, w);
break;
case Plumb:
if(hversion > 0)
outTsll(Tplumb, t->tag, which->p0, which->p1);
break;
case Exch:
snarf(t, w);
outT0(Tstartsnarf);
setlock();
break;
case Look:
outTsll(Tlook, t->tag, which->p0, which->p1);
setlock();
break;
case Search:
outcmd();
if(t==&cmd)
outTsll(Tsend, 0 /*ignored*/, which->p0, which->p1);
else
outT0(Tsearch);
setlock();
break;
}
}
void
menu3hit(void)
{
Rectangle r;
Flayer *l;
int m, i;
Text *t;
mw = -1;
m = menuhit(3, mousectl, &menu3, nil);
switch(m){
case -1:
break;
case New:
if(!hostlock)
sweeptext(1, 0);
break;
case Zerox:
case Resize:
if(!hostlock){
setcursor(mousectl, &bullseye);
buttons(Down);
if((mousep->buttons&4) && (l = flwhich(mousep->xy)) && getr(&r))
duplicate(l, r, l->f.font, m==Resize);
else
setcursor(mousectl, cursor);
buttons(Up);
}
break;
case Close:
if(!hostlock){
setcursor(mousectl, &bullseye);
buttons(Down);
if((mousep->buttons&4) && (l = flwhich(mousep->xy)) && !hostlock){
t=(Text *)l->user1;
if (t->nwin>1)
closeup(l);
else if(t!=&cmd) {
outTs(Tclose, t->tag);
setlock();
}
}
setcursor(mousectl, cursor);
buttons(Up);
}
break;
case Write:
if(!hostlock){
setcursor(mousectl, &bullseye);
buttons(Down);
if((mousep->buttons&4) && (l = flwhich(mousep->xy))){
outTs(Twrite, ((Text *)l->user1)->tag);
setlock();
}else
setcursor(mousectl, cursor);
buttons(Up);
}
break;
default:
if(t = text[m-NMENU3]){
i = t->front;
if(t->nwin==0 || t->l[i].textfn==0)
return; /* not ready yet; try again later */
if(t->nwin>1 && which==&t->l[i])
do
if(++i==NL)
i = 0;
while(i!=t->front && t->l[i].textfn==0);
current(&t->l[i]);
}else if(!hostlock)
sweeptext(0, tag[m-NMENU3]);
break;
}
}
Text *
sweeptext(int new, int tag)
{
Rectangle r;
Text *t;
if(getr(&r) && (t = malloc(sizeof(Text)))){
memset((void*)t, 0, sizeof(Text));
current((Flayer *)0);
flnew(&t->l[0], gettext, 0, (char *)t);
flinit(&t->l[0], r, font, maincols); /*bnl*/
t->nwin = 1;
rinit(&t->rasp);
if(new)
startnewfile(Tstartnewfile, t);
else{
rinit(&t->rasp);
t->tag = tag;
startfile(t);
}
return t;
}
return 0;
}
int
whichmenu(int tg)
{
int i;
for(i=0; i<nname; i++)
if(tag[i] == tg)
return i;
return -1;
}
void
menuins(int n, uchar *s, Text *t, int m, int tg)
{
int i;
if(nname == mname){
if(mname == 0)
mname = 32;
else
mname *= 2;
name = realloc(name, sizeof(name[0])*mname);
text = realloc(text, sizeof(text[0])*mname);
tag = realloc(tag, sizeof(tag[0])*mname);
if(name==nil || text==nil || tag==nil)
panic("realloc");
}
for(i=nname; i>n; --i)
name[i]=name[i-1], text[i]=text[i-1], tag[i]=tag[i-1];
text[n] = t;
tag[n] = tg;
name[n] = alloc(strlen((char*)s)+2);
name[n][0] = m;
strcpy((char*)name[n]+1, (char*)s);
nname++;
menu3.lasthit = n+NMENU3;
}
void
menudel(int n)
{
int i;
if(nname==0 || n>=nname || text[n])
panic("menudel");
free(name[n]);
--nname;
for(i = n; i<nname; i++)
name[i]=name[i+1], text[i]=text[i+1], tag[i]=tag[i+1];
}
void
setpat(char *s)
{
static char pat[17];
pat[0] = '/';
strncpy(pat+1, s, 15);
menu2str[Search] = pat;
}
#define NBUF 64
static uchar buf[NBUF*UTFmax]={' ', ' ', ' ', ' '};
char *
paren(char *s)
{
uchar *t = buf;
*t++ = '(';
do; while(*t++ = *s++);
t[-1] = ')';
*t = 0;
return (char *)buf;
}
char*
genmenu2(int n)
{
Text *t=(Text *)which->user1;
char *p;
if(n>=NMENU2+(menu2str[Search]!=0))
return 0;
p = menu2str[n];
if(!hostlock && !t->lock || n==Search || n==Look)
return p;
return paren(p);
}
char*
genmenu2c(int n)
{
Text *t=(Text *)which->user1;
char *p;
if(n >= NMENU2C)
return 0;
if(n == Send)
p="send";
else
p = menu2str[n];
if(!hostlock && !t->lock)
return p;
return paren(p);
}
char *
genmenu3(int n)
{
Text *t;
int c, i, k, l, w;
Rune r;
char *p;
if(n >= NMENU3+nname)
return 0;
if(n < NMENU3){
p = menu3str[n];
if(hostlock)
p = paren(p);
return p;
}
n -= NMENU3;
if(n == 0) /* unless we've been fooled, this is cmd */
return (char *)&name[n][1];
if(mw == -1){
mw = 7; /* strlen("~~sam~~"); */
for(i=1; i<nname; i++){
w = utflen((char*)name[i]+1)+4; /* include "'+. " */
if(w > mw)
mw = w;
}
}
if(mw > NBUF)
mw = NBUF;
t = text[n];
buf[0] = name[n][0];
buf[1] = '-';
buf[2] = ' ';
buf[3] = ' ';
if(t){
if(t->nwin == 1)
buf[1] = '+';
else if(t->nwin > 1)
buf[1] = '*';
if(work && t==(Text *)work->user1) {
buf[2]= '.';
if(modified)
buf[0] = '\'';
}
}
l = utflen((char*)name[n]+1);
if(l > NBUF-4-2){
i = 4;
k = 1;
while(i < NBUF/2){
k += chartorune(&r, (char*)name[n]+k);
i++;
}
c = name[n][k];
name[n][k] = 0;
strcpy((char*)buf+4, (char*)name[n]+1);
name[n][k] = c;
strcat((char*)buf, "...");
while((l-i) >= NBUF/2-4){
k += chartorune(&r, (char*)name[n]+k);
i++;
}
strcat((char*)buf, (char*)name[n]+k);
}else
strcpy((char*)buf+4, (char*)name[n]+1);
i = utflen((char*)buf);
k = strlen((char*)buf);
while(i<mw && k<sizeof buf-1){
buf[k++] = ' ';
i++;
}
buf[k] = 0;
return (char *)buf;
}