/* * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ #include <u.h>#include <libc.h>#include <draw.h>#include <thread.h>#include <cursor.h>#include <mouse.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}; voidmenu2hit(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; }} voidmenu3hit(void){ Rectangle r; Flayer *l; int m, i; Text *t; mw = -1; switch(m = menuhit(3, mousectl, &menu3, nil)){ 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;} intwhichmenu(int tg){ int i; for(i=0; i<nname; i++) if(tag[i] == tg) return i; return -1;} voidmenuins(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;} voidmenudel(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];} voidsetpat(char *s){ static char pat[17]; pat[0] = '/'; strncpy(pat+1, s, 15); menu2str[Search] = pat;} #define NBUF 64static 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;}
/*
* This file is part of the UCB release of Plan 9. It is subject to the license
* terms in the LICENSE file found in the top-level directory of this
* distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
* part of the UCB release of Plan 9, including this file, may be copied,
* modified, propagated, or distributed except according to the terms contained
* in the LICENSE file.
*/
#include <u.h>
#include <libc.h>
#include <draw.h>
#include <thread.h>
#include <cursor.h>
#include <mouse.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;
switch(m = menuhit(3, mousectl, &menu3, nil)){
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;
}