URI:
       tmenu.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tmenu.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 }