menu.c 6.4 KB

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