PageRenderTime 62ms CodeModel.GetById 32ms RepoModel.GetById 1ms app.codeStats 0ms

/xyzzy/src/buffer-bar.cc

http://xyzzy.codeplex.com
C++ | 494 lines | 448 code | 46 blank | 0 comment | 96 complexity | c391c05c89a4e1796995678a6ff65557 MD5 | raw file
Possible License(s): CC-BY-SA-3.0
  1. #include "ed.h"
  2. #include "mainframe.h"
  3. #include "buffer-bar.h"
  4. #include "colors.h"
  5. buffer_bar *buffer_bar::b_bar;
  6. Buffer *buffer_bar::b_last_buffer;
  7. #pragma warning (disable: 4355)
  8. buffer_bar::buffer_bar (dock_frame &frame)
  9. : tab_bar (frame, Vbuffer_bar), b_drop_target (this), b_drop_index (-1)
  10. {
  11. }
  12. #pragma warning (default: 4355)
  13. Buffer *
  14. buffer_bar::current () const
  15. {
  16. int i = get_cursel ();
  17. return i >= 0 ? nth (i) : 0;
  18. }
  19. TCHAR *
  20. buffer_bar::set_buffer_name (const Buffer *bp, TCHAR *buf, int size)
  21. {
  22. TCHAR *b = buf;
  23. if (bp->b_modified)
  24. {
  25. *b++ = _T('*');
  26. *b++ = _T(' ');
  27. }
  28. bp->buffer_name (b, buf + size - 2);
  29. return buf;
  30. }
  31. int
  32. buffer_bar::insert (const Buffer *bp, int i)
  33. {
  34. TC_ITEM ti;
  35. ti.mask = TCIF_TEXT | TCIF_PARAM;
  36. TCHAR buf[BUFFER_NAME_MAX * 2 + 32];
  37. ti.pszText = set_buffer_name (bp, buf, _countof (buf));
  38. ti.lParam = LPARAM (bp);
  39. return insert_item (i, ti);
  40. }
  41. int
  42. buffer_bar::modify (const Buffer *bp, int i)
  43. {
  44. TC_ITEM ti;
  45. ti.mask = TCIF_TEXT | TCIF_PARAM;
  46. TCHAR buf[BUFFER_NAME_MAX * 2 + 32];
  47. ti.pszText = set_buffer_name (bp, buf, _countof (buf));
  48. ti.lParam = LPARAM (bp);
  49. return set_item (i, ti);
  50. }
  51. int
  52. buffer_bar::notify (NMHDR *nm, LRESULT &result)
  53. {
  54. switch (nm->code)
  55. {
  56. default:
  57. return 0;
  58. case TCN_SELCHANGE:
  59. case TCN_SELCHANGING:
  60. if (!app.kbdq.idlep ()
  61. || selected_window ()->minibuffer_window_p ())
  62. {
  63. result = 1; // prevent the selection
  64. return 1;
  65. }
  66. break;
  67. }
  68. if (nm->code != TCN_SELCHANGE)
  69. return 0;
  70. Buffer *bp = current ();
  71. if (bp)
  72. {
  73. try
  74. {
  75. selected_buffer ()->run_hook (Vbuffer_bar_hook, bp->lbp);
  76. }
  77. catch (nonlocal_jump &)
  78. {
  79. print_condition (nonlocal_jump::data ());
  80. }
  81. b_last_buffer = 0;
  82. refresh_screen (1);
  83. }
  84. return 1;
  85. }
  86. int
  87. buffer_bar::need_text (TOOLTIPTEXT &ttt)
  88. {
  89. if (ttt.uFlags & TTF_IDISHWND)
  90. return 0;
  91. Buffer *bp = nth (ttt.hdr.idFrom);
  92. if (!bp)
  93. return 0;
  94. lisp x;
  95. if (stringp (bp->lfile_name))
  96. x = bp->lfile_name;
  97. else if (stringp (bp->lalternate_file_name))
  98. x = bp->lalternate_file_name;
  99. else
  100. x = bp->lbuffer_name;
  101. w2s (b_ttbuf, b_ttbuf + TTBUFSIZE, x);
  102. ttt.lpszText = b_ttbuf;
  103. ttt.hinst = 0;
  104. return 1;
  105. }
  106. void
  107. buffer_bar::tab_color (const Buffer *bp, COLORREF &fg, COLORREF &bg)
  108. {
  109. if (bp == selected_buffer ())
  110. {
  111. fg = get_misc_color (MC_BUFTAB_SEL_FG);
  112. bg = get_misc_color (MC_BUFTAB_SEL_BG);
  113. }
  114. else
  115. {
  116. Window *wp;
  117. for (wp = app.active_frame.windows; wp; wp = wp->w_next)
  118. if (wp->w_bufp == bp)
  119. {
  120. fg = get_misc_color (MC_BUFTAB_DISP_FG);
  121. bg = get_misc_color (MC_BUFTAB_DISP_BG);
  122. break;
  123. }
  124. if (!wp)
  125. {
  126. fg = get_misc_color (MC_BUFTAB_FG);
  127. bg = get_misc_color (MC_BUFTAB_BG);
  128. }
  129. }
  130. }
  131. void
  132. buffer_bar::draw_item (const draw_item_struct &dis)
  133. {
  134. Buffer *bp = (Buffer *)dis.data;
  135. TCHAR buf[BUFFER_NAME_MAX * 2 + 32];
  136. set_buffer_name (bp, buf, _countof (buf));
  137. if (bp->b_modified)
  138. bp->b_buffer_bar_modified |= Buffer::BUFFER_BAR_LAST_MODIFIED_FLAG;
  139. else
  140. bp->b_buffer_bar_modified &= ~Buffer::BUFFER_BAR_LAST_MODIFIED_FLAG;
  141. COLORREF fg, bg;
  142. tab_color (bp, fg, bg);
  143. bp->b_buffer_bar_fg = fg;
  144. bp->b_buffer_bar_bg = bg;
  145. tab_bar::draw_item (dis, buf, _tcslen (buf), fg, bg);
  146. }
  147. void
  148. buffer_bar::insert_buffers ()
  149. {
  150. set_no_redraw ();
  151. int current = -1;
  152. int i = 0;
  153. for (Buffer *bp = Buffer::b_blist; bp; bp = bp->b_next)
  154. if (!bp->internal_buffer_p ())
  155. {
  156. insert (bp, i);
  157. if (bp == selected_buffer ())
  158. current = i;
  159. i++;
  160. bp->b_buffer_bar_modified &= Buffer::BUFFER_BAR_LAST_MODIFIED_FLAG;
  161. }
  162. if (current >= 0)
  163. set_cursel (current);
  164. Buffer::b_buffer_bar_modified_any = 0;
  165. set_redraw ();
  166. }
  167. int
  168. buffer_bar::create (HWND hwnd_parent)
  169. {
  170. if (!tab_bar::create (hwnd_parent))
  171. return 0;
  172. RegisterDragDrop (b_hwnd, &b_drop_target);
  173. return 1;
  174. }
  175. int
  176. buffer_bar::make_instance ()
  177. {
  178. if (!b_bar)
  179. {
  180. b_bar = new buffer_bar (g_frame);
  181. if (!b_bar->create (app.toplev))
  182. return 0;
  183. b_bar->insert_buffers ();
  184. g_frame.add (b_bar);
  185. }
  186. return 1;
  187. }
  188. void
  189. buffer_bar::delete_buffer (Buffer *bp)
  190. {
  191. set_no_redraw ();
  192. int current = -1, found = -1;
  193. int n = item_count ();
  194. for (int i = 0; i < n; i++)
  195. {
  196. Buffer *p = nth (i);
  197. if (p == bp)
  198. found = i;
  199. if (p == selected_buffer ())
  200. current = i;
  201. if (found >= 0 && current >= 0)
  202. break;
  203. }
  204. if (current >= 0)
  205. set_cursel (current);
  206. if (found >= 0)
  207. delete_item (found);
  208. Buffer::b_buffer_bar_modified_any |= Buffer::BUFFER_BAR_DELETED;
  209. }
  210. Buffer *
  211. buffer_bar::next_buffer (Buffer *bp, int dir) const
  212. {
  213. int n = item_count ();
  214. for (int i = 0; i < n; i++)
  215. if (nth (i) == bp)
  216. return nth (dir > 0
  217. ? i == n - 1 ? 0 : i + 1
  218. : i ? i - 1 : n - 1);
  219. return 0;
  220. }
  221. Buffer *
  222. buffer_bar::top_buffer () const
  223. {
  224. return item_count () > 0 ? nth (0) : 0;
  225. }
  226. Buffer *
  227. buffer_bar::bottom_buffer () const
  228. {
  229. int n = item_count ();
  230. return n > 0 ? nth (n - 1) : 0;
  231. }
  232. static int __cdecl
  233. compare_buffer (const void *p1, const void *p2)
  234. {
  235. return (*(Buffer **)p1)->b_create_count - (*(Buffer **)p2)->b_create_count;
  236. }
  237. void
  238. buffer_bar::update_ui ()
  239. {
  240. int n = item_count ();
  241. if (Buffer::b_buffer_bar_modified_any & Buffer::BUFFER_BAR_CREATED)
  242. {
  243. set_no_redraw ();
  244. int nbuffers = 0;
  245. for (Buffer *bp = Buffer::b_blist; bp; bp = bp->b_next)
  246. if (bp->b_buffer_bar_modified & Buffer::BUFFER_BAR_CREATED
  247. && !bp->internal_buffer_p ())
  248. nbuffers++;
  249. if (nbuffers > 0)
  250. {
  251. int i = 0;
  252. Buffer **buffers = (Buffer **)alloca (sizeof *buffers * nbuffers);
  253. for (Buffer *bp = Buffer::b_blist; bp; bp = bp->b_next)
  254. if (bp->b_buffer_bar_modified & Buffer::BUFFER_BAR_CREATED)
  255. {
  256. if (!bp->internal_buffer_p ())
  257. buffers[i++] = bp;
  258. bp->b_buffer_bar_modified &= ~(Buffer::BUFFER_BAR_CREATED
  259. | Buffer::BUFFER_BAR_MODIFIED);
  260. }
  261. qsort (buffers, nbuffers, sizeof *buffers, compare_buffer);
  262. for (i = 0; i < nbuffers; i++)
  263. if (insert (buffers[i], n) >= 0)
  264. n++;
  265. }
  266. }
  267. int cur = -1;
  268. int mod = Buffer::b_buffer_bar_modified_any & Buffer::BUFFER_BAR_DELETED;
  269. if (Buffer::b_buffer_bar_modified_any & Buffer::BUFFER_BAR_MODIFIED
  270. || b_last_buffer != selected_buffer ())
  271. {
  272. for (int i = 0; i < n; i++)
  273. {
  274. Buffer *bp = nth (i);
  275. if (!bp)
  276. continue;
  277. if (bp == selected_buffer ())
  278. cur = i;
  279. if (bp->b_buffer_bar_modified & Buffer::BUFFER_BAR_MODIFIED)
  280. ;
  281. else if (bp->b_modified
  282. ? !(bp->b_buffer_bar_modified & Buffer::BUFFER_BAR_LAST_MODIFIED_FLAG)
  283. : bp->b_buffer_bar_modified & Buffer::BUFFER_BAR_LAST_MODIFIED_FLAG)
  284. ;
  285. else
  286. {
  287. COLORREF fg, bg;
  288. tab_color (bp, fg, bg);
  289. if (bp->b_buffer_bar_fg != fg
  290. || bp->b_buffer_bar_bg != bg)
  291. {
  292. bp->b_buffer_bar_fg = fg;
  293. bp->b_buffer_bar_bg = bg;
  294. set_no_redraw ();
  295. mod = 1;
  296. }
  297. continue;
  298. }
  299. set_no_redraw ();
  300. mod = 1;
  301. bp->b_buffer_bar_modified &= ~Buffer::BUFFER_BAR_MODIFIED;
  302. modify (bp, i);
  303. }
  304. }
  305. else
  306. cur = -2;
  307. if (cur >= 1 && xsymbol_value (Vbuffer_bar_selected_buffer_to_first) != Qnil
  308. && GetFocus () != b_hwnd)
  309. {
  310. Buffer *bp = selected_buffer ();
  311. if (!bp->internal_buffer_p ())
  312. {
  313. set_cursel (0);
  314. delete_item (cur);
  315. insert (bp, 0);
  316. cur = 0;
  317. mod = 1;
  318. }
  319. }
  320. if (mod)
  321. InvalidateRect (b_hwnd, 0, 1);
  322. set_redraw ();
  323. if (cur >= -1)
  324. set_cursel (cur);
  325. b_last_buffer = selected_buffer ();
  326. Buffer::b_buffer_bar_modified_any = 0;
  327. tab_bar::update_ui ();
  328. }
  329. lisp
  330. buffer_bar::context_menu (int i)
  331. {
  332. Buffer *bp;
  333. lisp lbp;
  334. if (i < 0)
  335. {
  336. bp = 0;
  337. lbp = Qnil;
  338. }
  339. else
  340. {
  341. bp = nth (i);
  342. if (!bp)
  343. return Qnil;
  344. lbp = bp->lbp;
  345. }
  346. lisp hook = symbol_value (Vbuffer_bar_context_menu_handler, bp);
  347. return (hook != Qnil && hook != Qunbound
  348. ? funcall_1 (hook, lbp) : Qnil);
  349. }
  350. LRESULT
  351. buffer_bar::wndproc (UINT msg, WPARAM wparam, LPARAM lparam)
  352. {
  353. switch (msg)
  354. {
  355. case WM_DESTROY:
  356. RevokeDragDrop (b_hwnd);
  357. break;
  358. case WM_TIMER:
  359. if (wparam == DROP_TIMER_ID)
  360. {
  361. int index = b_drop_index;
  362. KillTimer (b_hwnd, DROP_TIMER_ID);
  363. b_drop_index = -1;
  364. if (index >= 0
  365. && (app.drag_window || app.kbdq.idlep ())
  366. && !selected_window ()->minibuffer_window_p ())
  367. {
  368. Buffer *bp = nth (index);
  369. if (bp)
  370. {
  371. try
  372. {
  373. selected_buffer ()->run_hook (Vbuffer_bar_hook, bp->lbp);
  374. }
  375. catch (nonlocal_jump &)
  376. {
  377. print_condition (nonlocal_jump::data ());
  378. }
  379. refresh_screen (1);
  380. }
  381. }
  382. return 0;
  383. }
  384. break;
  385. }
  386. return tab_bar::wndproc (msg, wparam, lparam);
  387. }
  388. void
  389. buffer_bar::drag_enter (int x, int y)
  390. {
  391. b_drop_index = -1;
  392. drag_over (x, y);
  393. }
  394. void
  395. buffer_bar::drag_over (int x, int y)
  396. {
  397. TC_HITTESTINFO htinfo;
  398. htinfo.pt.x = x;
  399. htinfo.pt.y = y;
  400. ScreenToClient (b_hwnd, &htinfo.pt);
  401. int index = hit_test (htinfo);
  402. if (index != b_drop_index)
  403. {
  404. KillTimer (b_hwnd, DROP_TIMER_ID);
  405. if (index >= 0 && index != get_cursel ())
  406. {
  407. b_drop_index = index;
  408. SetTimer (b_hwnd, DROP_TIMER_ID, 1000, 0);
  409. }
  410. else
  411. b_drop_index = -1;
  412. }
  413. }
  414. void
  415. buffer_bar::drag_leave ()
  416. {
  417. KillTimer (b_hwnd, DROP_TIMER_ID);
  418. b_drop_index = -1;
  419. }
  420. lisp
  421. buffer_bar::buffer_list () const
  422. {
  423. for (Buffer *bp = Buffer::b_blist; bp; bp = bp->b_next)
  424. bp->b_buffer_bar_modified &= ~Buffer::BUFFER_BAR_MARK;
  425. lisp r = Qnil;
  426. for (int i = 0, n = item_count (); i < n; i++)
  427. {
  428. Buffer *bp = nth (i);
  429. if (bp)
  430. {
  431. r = xcons (bp->lbp, r);
  432. bp->b_buffer_bar_modified |= Buffer::BUFFER_BAR_MARK;
  433. }
  434. }
  435. for (Buffer *bp = Buffer::b_blist; bp; bp = bp->b_next)
  436. if (bp->b_buffer_bar_modified & Buffer::BUFFER_BAR_MARK)
  437. bp->b_buffer_bar_modified &= ~Buffer::BUFFER_BAR_MARK;
  438. else
  439. r = xcons (bp->lbp, r);
  440. return Fnreverse (r);
  441. }
  442. lisp
  443. Fcreate_buffer_bar ()
  444. {
  445. if (!buffer_bar::make_instance ())
  446. FEsimple_error (ECannot_create_toolbar);
  447. return Vbuffer_bar;
  448. }