menu.c (6531B)
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" 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 m = menuhit(3, mousectl, &menu3, nil); 132 switch(m){ 133 case -1: 134 break; 135 136 case New: 137 if(!hostlock) 138 sweeptext(1, 0); 139 break; 140 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 else 149 setcursor(mousectl, cursor); 150 buttons(Up); 151 } 152 break; 153 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; 171 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 }else 180 setcursor(mousectl, cursor); 181 buttons(Up); 182 } 183 break; 184 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 do 192 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 } 201 202 203 Text * 204 sweeptext(int new, int tag) 205 { 206 Rectangle r; 207 Text *t; 208 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 } 227 228 int 229 whichmenu(int tg) 230 { 231 int i; 232 233 for(i=0; i<nname; i++) 234 if(tag[i] == tg) 235 return i; 236 return -1; 237 } 238 239 void 240 menuins(int n, uchar *s, Text *t, int m, int tg) 241 { 242 int i; 243 244 if(nname == mname){ 245 if(mname == 0) 246 mname = 32; 247 else 248 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 } 265 266 void 267 menudel(int n) 268 { 269 int i; 270 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 } 278 279 void 280 setpat(char *s) 281 { 282 static char pat[17]; 283 284 pat[0] = '/'; 285 strncpy(pat+1, s, 15); 286 menu2str[Search] = pat; 287 } 288 289 #define NBUF 64 290 static uchar buf[NBUF*UTFmax]={' ', ' ', ' ', ' '}; 291 292 char * 293 paren(char *s) 294 { 295 uchar *t = buf; 296 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 else 325 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; 337 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 }else 394 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 }