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