menu.c 6.8 KB

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