menu.c 6.2 KB

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