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