Blob
1 #include <u.h>2 #include <libc.h>3 #include <draw.h>4 #include <thread.h>5 #include <mouse.h>6 #include <cursor.h>7 #include <keyboard.h>8 #include <frame.h>9 #include "flayer.h"10 #include "samterm.h"12 uchar **name; /* first byte is ' ' or '\'': modified state */13 Text **text; /* pointer to Text associated with file */14 ushort *tag; /* text[i].tag, even if text[i] not defined */15 int nname;16 int mname;17 int mw;19 char *genmenu3(int);20 char *genmenu2(int);21 char *genmenu2c(int);23 enum Menu224 {25 Cut,26 Paste,27 Snarf,28 Plumb,29 Look,30 Exch,31 Search,32 NMENU2 = Search,33 Send = Search,34 NMENU2C35 };37 enum Menu338 {39 New,40 Zerox,41 Resize,42 Close,43 Write,44 NMENU345 };47 char *menu2str[] = {48 "cut",49 "paste",50 "snarf",51 "plumb",52 "look",53 "<rio>",54 0, /* storage for last pattern */55 };57 char *menu3str[] = {58 "new",59 "zerox",60 "resize",61 "close",62 "write",63 };65 Menu menu2 = {0, genmenu2};66 Menu menu2c ={0, genmenu2c};67 Menu menu3 = {0, genmenu3};69 void70 menu2hit(void)71 {72 Text *t=(Text *)which->user1;73 int w = which-t->l;74 int m;76 if(hversion==0 || plumbfd<0)77 menu2str[Plumb] = "(plumb)";78 m = menuhit(2, mousectl, t==&cmd? &menu2c : &menu2, nil);79 if(hostlock || t->lock)80 return;82 switch(m){83 case Cut:84 cut(t, w, 1, 1);85 break;87 case Paste:88 paste(t, w);89 break;91 case Snarf:92 snarf(t, w);93 break;95 case Plumb:96 if(hversion > 0)97 outTsll(Tplumb, t->tag, which->p0, which->p1);98 break;100 case Exch:101 snarf(t, w);102 outT0(Tstartsnarf);103 setlock();104 break;106 case Look:107 outTsll(Tlook, t->tag, which->p0, which->p1);108 setlock();109 break;111 case Search:112 outcmd();113 if(t==&cmd)114 outTsll(Tsend, 0 /*ignored*/, which->p0, which->p1);115 else116 outT0(Tsearch);117 setlock();118 break;119 }120 }122 void123 menu3hit(void)124 {125 Rectangle r;126 Flayer *l;127 int m, i;128 Text *t;130 mw = -1;131 m = menuhit(3, mousectl, &menu3, nil);132 switch(m){133 case -1:134 break;136 case New:137 if(!hostlock)138 sweeptext(1, 0);139 break;141 case Zerox:142 case Resize:143 if(!hostlock){144 setcursor(mousectl, &bullseye);145 buttons(Down);146 if((mousep->buttons&4) && (l = flwhich(mousep->xy)) && getr(&r))147 duplicate(l, r, l->f.font, m==Resize);148 else149 setcursor(mousectl, cursor);150 buttons(Up);151 }152 break;154 case Close:155 if(!hostlock){156 setcursor(mousectl, &bullseye);157 buttons(Down);158 if((mousep->buttons&4) && (l = flwhich(mousep->xy)) && !hostlock){159 t=(Text *)l->user1;160 if (t->nwin>1)161 closeup(l);162 else if(t!=&cmd) {163 outTs(Tclose, t->tag);164 setlock();165 }166 }167 setcursor(mousectl, cursor);168 buttons(Up);169 }170 break;172 case Write:173 if(!hostlock){174 setcursor(mousectl, &bullseye);175 buttons(Down);176 if((mousep->buttons&4) && (l = flwhich(mousep->xy))){177 outTs(Twrite, ((Text *)l->user1)->tag);178 setlock();179 }else180 setcursor(mousectl, cursor);181 buttons(Up);182 }183 break;185 default:186 if(t = text[m-NMENU3]){187 i = t->front;188 if(t->nwin==0 || t->l[i].textfn==0)189 return; /* not ready yet; try again later */190 if(t->nwin>1 && which==&t->l[i])191 do192 if(++i==NL)193 i = 0;194 while(i!=t->front && t->l[i].textfn==0);195 current(&t->l[i]);196 }else if(!hostlock)197 sweeptext(0, tag[m-NMENU3]);198 break;199 }200 }203 Text *204 sweeptext(int new, int tag)205 {206 Rectangle r;207 Text *t;209 if(getr(&r) && (t = malloc(sizeof(Text)))){210 memset((void*)t, 0, sizeof(Text));211 current((Flayer *)0);212 flnew(&t->l[0], gettext, 0, (char *)t);213 flinit(&t->l[0], r, font, maincols); /*bnl*/214 t->nwin = 1;215 rinit(&t->rasp);216 if(new)217 startnewfile(Tstartnewfile, t);218 else{219 rinit(&t->rasp);220 t->tag = tag;221 startfile(t);222 }223 return t;224 }225 return 0;226 }228 int229 whichmenu(int tg)230 {231 int i;233 for(i=0; i<nname; i++)234 if(tag[i] == tg)235 return i;236 return -1;237 }239 void240 menuins(int n, uchar *s, Text *t, int m, int tg)241 {242 int i;244 if(nname == mname){245 if(mname == 0)246 mname = 32;247 else248 mname *= 2;249 name = realloc(name, sizeof(name[0])*mname);250 text = realloc(text, sizeof(text[0])*mname);251 tag = realloc(tag, sizeof(tag[0])*mname);252 if(name==nil || text==nil || tag==nil)253 panic("realloc");254 }255 for(i=nname; i>n; --i)256 name[i]=name[i-1], text[i]=text[i-1], tag[i]=tag[i-1];257 text[n] = t;258 tag[n] = tg;259 name[n] = alloc(strlen((char*)s)+2);260 name[n][0] = m;261 strcpy((char*)name[n]+1, (char*)s);262 nname++;263 menu3.lasthit = n+NMENU3;264 }266 void267 menudel(int n)268 {269 int i;271 if(nname==0 || n>=nname || text[n])272 panic("menudel");273 free(name[n]);274 --nname;275 for(i = n; i<nname; i++)276 name[i]=name[i+1], text[i]=text[i+1], tag[i]=tag[i+1];277 }279 void280 setpat(char *s)281 {282 static char pat[17];284 pat[0] = '/';285 strncpy(pat+1, s, 15);286 menu2str[Search] = pat;287 }289 #define NBUF 64290 static uchar buf[NBUF*UTFmax]={' ', ' ', ' ', ' '};292 char *293 paren(char *s)294 {295 uchar *t = buf;297 *t++ = '(';298 do; while(*t++ = *s++);299 t[-1] = ')';300 *t = 0;301 return (char *)buf;302 }303 char*304 genmenu2(int n)305 {306 Text *t=(Text *)which->user1;307 char *p;308 if(n>=NMENU2+(menu2str[Search]!=0))309 return 0;310 p = menu2str[n];311 if(!hostlock && !t->lock || n==Search || n==Look)312 return p;313 return paren(p);314 }315 char*316 genmenu2c(int n)317 {318 Text *t=(Text *)which->user1;319 char *p;320 if(n >= NMENU2C)321 return 0;322 if(n == Send)323 p="send";324 else325 p = menu2str[n];326 if(!hostlock && !t->lock)327 return p;328 return paren(p);329 }330 char *331 genmenu3(int n)332 {333 Text *t;334 int c, i, k, l, w;335 Rune r;336 char *p;338 if(n >= NMENU3+nname)339 return 0;340 if(n < NMENU3){341 p = menu3str[n];342 if(hostlock)343 p = paren(p);344 return p;345 }346 n -= NMENU3;347 if(n == 0) /* unless we've been fooled, this is cmd */348 return (char *)&name[n][1];349 if(mw == -1){350 mw = 7; /* strlen("~~sam~~"); */351 for(i=1; i<nname; i++){352 w = utflen((char*)name[i]+1)+4; /* include "'+. " */353 if(w > mw)354 mw = w;355 }356 }357 if(mw > NBUF)358 mw = NBUF;359 t = text[n];360 buf[0] = name[n][0];361 buf[1] = '-';362 buf[2] = ' ';363 buf[3] = ' ';364 if(t){365 if(t->nwin == 1)366 buf[1] = '+';367 else if(t->nwin > 1)368 buf[1] = '*';369 if(work && t==(Text *)work->user1) {370 buf[2]= '.';371 if(modified)372 buf[0] = '\'';373 }374 }375 l = utflen((char*)name[n]+1);376 if(l > NBUF-4-2){377 i = 4;378 k = 1;379 while(i < NBUF/2){380 k += chartorune(&r, (char*)name[n]+k);381 i++;382 }383 c = name[n][k];384 name[n][k] = 0;385 strcpy((char*)buf+4, (char*)name[n]+1);386 name[n][k] = c;387 strcat((char*)buf, "...");388 while((l-i) >= NBUF/2-4){389 k += chartorune(&r, (char*)name[n]+k);390 i++;391 }392 strcat((char*)buf, (char*)name[n]+k);393 }else394 strcpy((char*)buf+4, (char*)name[n]+1);395 i = utflen((char*)buf);396 k = strlen((char*)buf);397 while(i<mw && k<sizeof buf-1){398 buf[k++] = ' ';399 i++;400 }401 buf[k] = 0;402 return (char *)buf;403 }