curseSplitOutput.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649
  1. /**
  2. * curseSplitOutput.cpp for jsonstroller
  3. *
  4. * Author: isundil <isundill@gmail.com>
  5. **/
  6. #include <sys/ioctl.h>
  7. #include <unistd.h>
  8. #include <signal.h>
  9. #include <curses.h>
  10. #include "searchPattern.hh"
  11. #include "curseSplitOutput.hh"
  12. #include "jsonObject.hh"
  13. #include "jsonArray.hh"
  14. #include "jsonPrimitive.hh"
  15. CurseSplitOutput::CurseSplitOutput(const Params &p): CurseOutput(p)
  16. {
  17. init();
  18. }
  19. CurseSplitOutput::~CurseSplitOutput()
  20. {
  21. shutdown();
  22. }
  23. void CurseSplitOutput::run(const std::deque<std::string> &inputName, const std::deque<JSonElement*> &roots)
  24. {
  25. nbInputs = inputName.size();
  26. selectedWin = 0;
  27. scrollTop.clear();
  28. select_up.clear();
  29. select_down.clear();
  30. selection.clear();
  31. search_result.clear();
  32. for (short i =0; i < nbInputs; i++)
  33. {
  34. this->roots.push_back(roots.at(i));
  35. scrollTop.push_back(0);
  36. selection.push_back(roots.at(i));
  37. select_up.push_back(nullptr);
  38. select_down.push_back(nullptr);
  39. search_result.push_back(std::list<const JSonElement *>());
  40. }
  41. fileNames = inputName;
  42. loop();
  43. }
  44. void CurseSplitOutput::loop()
  45. {
  46. breakLoop = false;
  47. while (!redraw());
  48. while(readInput())
  49. {
  50. while (!redrawCurrent(selectedWin));
  51. }
  52. }
  53. inputResult CurseSplitOutput::selectUp()
  54. {
  55. selection[selectedWin] = select_up[selectedWin];
  56. return inputResult::redraw;
  57. }
  58. inputResult CurseSplitOutput::selectDown()
  59. {
  60. if (selectIsLast)
  61. scrollTop[selectedWin] += 2;
  62. else if (selection != select_down)
  63. selection[selectedWin] = select_down[selectedWin];
  64. else
  65. return inputResult::nextInput;
  66. return inputResult::redraw;
  67. }
  68. inputResult CurseSplitOutput::selectPUp()
  69. {
  70. const JSonElement *_selection = selection[selectedWin];
  71. const JSonElement *brother = _selection->findPrev();
  72. if (brother == nullptr)
  73. {
  74. const JSonElement *parent = _selection->getParent();
  75. if (parent && dynamic_cast<const JSonContainer*>(parent))
  76. {
  77. selection[selectedWin] = _selection = parent;
  78. if (_selection->getParent() && dynamic_cast<const JSonObjectEntry*> (_selection->getParent()))
  79. selection[selectedWin] = _selection->getParent();
  80. }
  81. else
  82. return inputResult::nextInput;
  83. }
  84. else
  85. selection[selectedWin] = brother;
  86. return inputResult::redraw;
  87. }
  88. inputResult CurseSplitOutput::selectPDown()
  89. {
  90. const JSonElement *brother = selection[selectedWin]->findNext();
  91. if (brother)
  92. {
  93. selection[selectedWin] = brother;
  94. return inputResult::redraw;
  95. }
  96. return inputResult::nextInput;
  97. }
  98. inputResult CurseSplitOutput::expandSelection()
  99. {
  100. const JSonElement *_selection = selection[selectedWin];
  101. if (dynamic_cast<const JSonObjectEntry*>(_selection))
  102. _selection = **((const JSonObjectEntry*)_selection);
  103. if (!dynamic_cast<const JSonContainer*>(_selection))
  104. return inputResult::nextInput;
  105. if (collapsed.erase((const JSonContainer *)_selection))
  106. return inputResult::redraw;
  107. if (!((const JSonContainer*)_selection)->size())
  108. return inputResult::nextInput;
  109. selection[selectedWin] = select_down[selectedWin];
  110. return inputResult::redraw;
  111. }
  112. inputResult CurseSplitOutput::collapseSelection()
  113. {
  114. const JSonElement *_selection = selection[selectedWin];
  115. if (dynamic_cast<const JSonObjectEntry*>(_selection))
  116. _selection = **((const JSonObjectEntry*)_selection);
  117. if (_selection->getParent() && (!dynamic_cast<const JSonContainer*>(_selection)
  118. || collapsed.find((const JSonContainer *)_selection) != collapsed.end()
  119. || (dynamic_cast<const JSonContainer*>(_selection) && ((const JSonContainer*)_selection)->size() == 0)))
  120. {
  121. selection[selectedWin] = _selection = selection[selectedWin]->getParent();
  122. if (_selection->getParent() && dynamic_cast<const JSonObjectEntry*>(_selection->getParent()))
  123. selection[selectedWin] = _selection->getParent();
  124. }
  125. else
  126. collapsed.insert((const JSonContainer *)_selection);
  127. return inputResult::redraw;
  128. }
  129. inputResult CurseSplitOutput::initSearch()
  130. {
  131. const SearchPattern *search_pattern = inputSearch();
  132. if (!search_pattern)
  133. return inputResult::redraw;
  134. search_result.clear();
  135. if (search_pattern->isEmpty())
  136. return inputResult::redraw;
  137. search(*search_pattern);
  138. delete search_pattern;
  139. return nextResult();
  140. }
  141. inputResult CurseSplitOutput::nextResult()
  142. {
  143. if (search_result.empty())
  144. CurseOutput::redraw("Pattern not found");
  145. else if (jumpToNextSearch())
  146. return inputResult::redraw;
  147. return inputResult::nextInput;
  148. }
  149. void CurseSplitOutput::checkSelection(const JSonElement *item, const std::pair<int, int> &cursor)
  150. {
  151. if (!selectFound)
  152. {
  153. if (selection[workingWin] == item)
  154. {
  155. if (cursor.second < scrollTop[workingWin]) //Selection is above vp, move scroll pos to selection and start drawing
  156. scrollTop[workingWin] = cursor.second;
  157. selectFound = true;
  158. }
  159. else if (!item->getParent() || !dynamic_cast<const JSonObjectEntry*>(item->getParent()))
  160. select_up[workingWin] = item;
  161. }
  162. else if (!select_down[workingWin])
  163. {
  164. const JSonElement *parent = item->getParent();
  165. if (!dynamic_cast<const JSonContainer*>(item) && parent && selection[workingWin] != parent && dynamic_cast<const JSonObjectEntry*>(parent))
  166. item = parent;
  167. if (!parent || !dynamic_cast<const JSonObjectEntry*>(parent))
  168. select_down[workingWin] = item;
  169. }
  170. }
  171. bool CurseSplitOutput::jumpToNextSearch(const JSonElement *current, bool &selectFound)
  172. {
  173. const JSonContainer *container = dynamic_cast<const JSonContainer *> (current);
  174. const JSonObjectEntry *objEntry = dynamic_cast<const JSonObjectEntry *> (current);
  175. if (selection[selectedWin] == current)
  176. selectFound = true;
  177. if (container)
  178. {
  179. if (!container->empty())
  180. for (const JSonElement *it : *container)
  181. if (jumpToNextSearch(it, selectFound))
  182. return true;
  183. }
  184. else
  185. {
  186. if (current && std::find(search_result[selectedWin].cbegin(), search_result[selectedWin].cend(), current) != search_result[selectedWin].cend() && current != selection[selectedWin] && selectFound)
  187. {
  188. selection[selectedWin] = current;
  189. return true;
  190. }
  191. if (objEntry)
  192. if (jumpToNextSearch(**objEntry, selectFound))
  193. return true;
  194. }
  195. return false;
  196. }
  197. unsigned int CurseSplitOutput::search(const SearchPattern &search_pattern)
  198. {
  199. unsigned int result =0;
  200. for (workingWin =0; workingWin < nbInputs; ++workingWin)
  201. result += search(search_pattern, roots[workingWin]);
  202. return result;
  203. }
  204. unsigned int CurseSplitOutput::search(const SearchPattern &search_pattern, const JSonElement *current)
  205. {
  206. const JSonContainer *container = dynamic_cast<const JSonContainer *> (current);
  207. const JSonObjectEntry *objEntry = dynamic_cast<const JSonObjectEntry *> (current);
  208. if (container)
  209. {
  210. if (!container->empty())
  211. for (const JSonElement *it : *container)
  212. search(search_pattern, it);
  213. }
  214. else
  215. {
  216. if (current && current->match(search_pattern))
  217. {
  218. if (current->getParent() && dynamic_cast<const JSonObjectEntry*>(current->getParent()))
  219. search_result[workingWin].push_back(current->getParent());
  220. else
  221. search_result[workingWin].push_back(current);
  222. }
  223. if (objEntry)
  224. search(search_pattern, **objEntry);
  225. }
  226. return search_result.size();
  227. }
  228. bool CurseSplitOutput::jumpToNextSearch()
  229. {
  230. bool selectFound = false;
  231. bool res = jumpToNextSearch(roots[selectedWin], selectFound);
  232. if (!res)
  233. {
  234. selection[selectedWin] = *(search_result[selectedWin].cbegin());
  235. unfold(selection[selectedWin]);
  236. CurseOutput::redraw("Search hit BOTTOM, continuing at TOP");
  237. return false;
  238. }
  239. unfold(selection[selectedWin]);
  240. return true;
  241. }
  242. bool CurseSplitOutput::redrawCurrent(short selectedWin)
  243. {
  244. const std::pair<unsigned int, unsigned int> screenSize = getScreenSize();
  245. currentWin = subwindows[workingWin = selectedWin];
  246. return redrawCurrent(screenSize);
  247. }
  248. bool CurseSplitOutput::redrawCurrent(const std::pair<unsigned int, unsigned int> &screenSize)
  249. {
  250. std::pair<int, int> cursor(0, 0);
  251. bool result;
  252. select_up[workingWin] = select_down[workingWin] = nullptr;
  253. selectFound = selectIsLast = false;
  254. wclear(currentWin);
  255. box(outerWin[workingWin], 0, 0);
  256. try {
  257. result = redraw(cursor, screenSize, roots[workingWin]);
  258. }
  259. catch (SelectionOutOfRange &e)
  260. {
  261. return false;
  262. }
  263. if (!result && !selectFound)
  264. {
  265. scrollTop[workingWin]++;
  266. return false;
  267. }
  268. if (!result && !select_down[workingWin])
  269. selectIsLast = true;
  270. if (!select_down[workingWin])
  271. {
  272. const JSonContainer *pselect = dynamic_cast<const JSonContainer*>(selection[workingWin]);
  273. if (pselect && !pselect->empty())
  274. select_down[workingWin] = *(pselect->cbegin());
  275. else
  276. {
  277. const JSonElement *next = selection[workingWin]->findNext();
  278. select_down[workingWin] = next ? next : selection[workingWin];
  279. }
  280. }
  281. if (!select_up[workingWin])
  282. select_up[workingWin] = selection[workingWin];
  283. wrefresh(outerWin[workingWin]);
  284. wrefresh(currentWin);
  285. return true;
  286. }
  287. bool CurseSplitOutput::redraw()
  288. {
  289. const std::pair<unsigned int, unsigned int> screenSize = getScreenSize();
  290. destroyAllSubWin();
  291. clear();
  292. refresh();
  293. for (workingWin =0; workingWin < nbInputs; workingWin++)
  294. {
  295. outerWin.push_back(newwin(screenSize.second +2, screenSize.first, 0, workingWin * screenSize.first -workingWin));
  296. currentWin = newwin(screenSize.second, screenSize.first -2, 1, workingWin * screenSize.first -workingWin +1);
  297. subwindows.push_back(currentWin);
  298. if (!redrawCurrent(screenSize))
  299. return false;
  300. }
  301. return true;
  302. }
  303. bool CurseSplitOutput::writeContainer(std::pair<int, int> &cursor, const std::pair<unsigned int, unsigned int> &maxSize, const JSonContainer *item)
  304. {
  305. char childDelimiter[2];
  306. const int scrollTop = this->scrollTop[workingWin];
  307. if (dynamic_cast<const JSonObject *>(item))
  308. memcpy(childDelimiter, "{}", sizeof(*childDelimiter) * 2);
  309. else
  310. memcpy(childDelimiter, "[]", sizeof(*childDelimiter) * 2);
  311. if (collapsed.find((const JSonContainer *)item) != collapsed.end())
  312. {
  313. std::string ss;
  314. ss.append(&childDelimiter[0], 1).append(" ... ").append(&childDelimiter[1], 1);
  315. cursor.second += write(cursor.first, cursor.second, ss, 7, maxSize.first, CurseSplitOutput::getFlag(item));
  316. }
  317. else
  318. {
  319. cursor.second += write(cursor.first, cursor.second, childDelimiter[0], maxSize.first, CurseSplitOutput::getFlag(item));
  320. if (cursor.second - scrollTop > 0 && (unsigned)(cursor.second - scrollTop) > maxSize.second -1)
  321. return false;
  322. if (!writeContent(cursor, maxSize, (std::list<JSonElement *> *)item))
  323. return false;
  324. cursor.second += write(cursor.first, cursor.second, childDelimiter[1], maxSize.first, CurseSplitOutput::getFlag(item));
  325. }
  326. return (cursor.second - scrollTop < 0 || (unsigned)(cursor.second - scrollTop) <= maxSize.second -1);
  327. }
  328. bool CurseSplitOutput::writeContent(std::pair<int, int> &cursor, const std::pair<unsigned int, unsigned int> &maxSize, std::list<JSonElement*> *_item)
  329. {
  330. JSonContainer *item = (JSonContainer *)_item;
  331. bool containerIsObject = (dynamic_cast<JSonObject *>(item) != nullptr);
  332. bool result = true;
  333. cursor.first += INDENT_LEVEL;
  334. const int scrollTop = this->scrollTop[workingWin];
  335. for (JSonElement *i : *item)
  336. {
  337. result = false;
  338. if (containerIsObject)
  339. {
  340. JSonObjectEntry *ent = (JSonObjectEntry*) i;
  341. bool isContainer = (dynamic_cast<JSonContainer *>(**ent) != nullptr);
  342. std::string key = ent->stringify();
  343. checkSelection(ent, cursor);
  344. if (isContainer && collapsed.find((JSonContainer*)(**ent)) != collapsed.cend())
  345. {
  346. if (dynamic_cast<JSonObject *>(**ent))
  347. {
  348. if (!CurseOutput::writeKey(key, ent->lazystrlen(), "{ ... }", cursor, maxSize, CurseSplitOutput::getFlag(ent)) || (cursor.second - scrollTop > 0 && (unsigned)(cursor.second - scrollTop) > maxSize.second -1))
  349. break;
  350. }
  351. else if (!CurseOutput::writeKey(key, ent->lazystrlen(), "[ ... ]", cursor, maxSize, CurseSplitOutput::getFlag(ent)) || (cursor.second - scrollTop > 0 && (unsigned)(cursor.second - scrollTop) > maxSize.second -1))
  352. break;
  353. }
  354. else if (!isContainer)
  355. {
  356. JSonElement *eContent = **ent;
  357. if (!writeKey(key, ent->lazystrlen(), eContent->stringify(), eContent->lazystrlen(), cursor, maxSize, CurseSplitOutput::getFlag(ent)) || (cursor.second - scrollTop > 0 && (unsigned)(cursor.second - scrollTop) > maxSize.second -1))
  358. break;
  359. }
  360. else if (((JSonContainer*)(**ent))->size() == 0)
  361. {
  362. if (dynamic_cast<const JSonObject *>(**ent) )
  363. {
  364. if (!CurseOutput::writeKey(key, ent->lazystrlen(), "{ }", cursor, maxSize, CurseSplitOutput::getFlag(ent)) || (cursor.second - scrollTop > 0 && (unsigned)(cursor.second - scrollTop) > maxSize.second -1))
  365. break;
  366. }
  367. else if (!CurseOutput::writeKey(key, ent->lazystrlen(), "[ ]", cursor, maxSize, CurseSplitOutput::getFlag(ent)) || (cursor.second - scrollTop > 0 && (unsigned)(cursor.second - scrollTop) > maxSize.second -1))
  368. break;
  369. }
  370. else
  371. {
  372. if (!writeKey(key, ent->lazystrlen(), cursor, maxSize, getFlag(ent)))
  373. break;
  374. const JSonElement *saveSelection = selection[workingWin];
  375. if (selection[workingWin] == ent)
  376. selection[workingWin] = **ent;
  377. cursor.first += INDENT_LEVEL /2;
  378. if (!redraw(cursor, maxSize, **ent))
  379. {
  380. selection[workingWin] = saveSelection;
  381. cursor.first -= INDENT_LEVEL /2;
  382. return false;
  383. }
  384. selection[workingWin] = saveSelection;
  385. cursor.first -= INDENT_LEVEL /2;
  386. }
  387. }
  388. else
  389. {
  390. if (!redraw(cursor, maxSize, i))
  391. break;
  392. }
  393. result = true;
  394. }
  395. cursor.first -= INDENT_LEVEL;
  396. //result will be false if for loop break'd at some time, true otherwise
  397. return result;
  398. }
  399. bool CurseSplitOutput::writeKey(const std::string &key, const size_t keylen, std::pair<int, int> &cursor, const std::pair<unsigned int, unsigned int> &maxSize, OutputFlag flags, unsigned int extraLen)
  400. {
  401. if (cursor.second - scrollTop[workingWin] <= 0)
  402. {
  403. cursor.second++;
  404. return true;
  405. }
  406. char oldType = flags.type();
  407. flags.type(OutputFlag::TYPE_OBJKEY);
  408. cursor.second += write(cursor.first, cursor.second, key, keylen, maxSize.first -extraLen -2, flags);
  409. flags.type(OutputFlag::TYPE_OBJ);
  410. write(": ", flags);
  411. flags.type(oldType);
  412. return (cursor.second - scrollTop[workingWin] < 0 || (unsigned)(cursor.second - scrollTop[workingWin]) <= maxSize.second);
  413. }
  414. bool CurseSplitOutput::writeKey(const std::string &key, const size_t keylen, const std::string &after, size_t afterlen, std::pair<int, int> &cursor, const std::pair<unsigned int, unsigned int> &maxSize, OutputFlag flags)
  415. {
  416. if (cursor.second - scrollTop[workingWin] <= 0)
  417. {
  418. cursor.second++;
  419. return true;
  420. }
  421. char oldType = flags.type();
  422. flags.type(OutputFlag::TYPE_OBJKEY);
  423. write(cursor.first, cursor.second, key, 0, 1, flags);
  424. flags.type(OutputFlag::TYPE_OBJ);
  425. write(": ", flags);
  426. flags.type(oldType);
  427. write(after, flags);
  428. cursor.second += getNbLines(cursor.first +keylen +2 +afterlen, maxSize.first);
  429. return (cursor.second - scrollTop[workingWin] < 0 || (unsigned)(cursor.second - scrollTop[workingWin]) <= maxSize.second);
  430. }
  431. bool CurseSplitOutput::redraw(std::pair<int, int> &cursor, const std::pair<unsigned int, unsigned int> &maxSize, JSonElement *item)
  432. {
  433. checkSelection(item, cursor);
  434. if (dynamic_cast<const JSonContainer*>(item))
  435. {
  436. if (!writeContainer(cursor, maxSize, (const JSonContainer *) item))
  437. return false;
  438. }
  439. else
  440. {
  441. cursor.second += CurseOutput::write(cursor.first, cursor.second, item, maxSize.first, CurseSplitOutput::getFlag(item));
  442. if (cursor.second - scrollTop[workingWin] > 0 && (unsigned)(cursor.second - scrollTop[workingWin]) > maxSize.second -1)
  443. return false;
  444. }
  445. return true;
  446. }
  447. unsigned int CurseSplitOutput::write(const int &x, const int &y, const char item, unsigned int maxWidth, OutputFlag flags)
  448. {
  449. int offsetY = y - scrollTop[workingWin];
  450. char color = OutputFlag::SPECIAL_NONE;
  451. if (offsetY < 0)
  452. return 1;
  453. if (flags.selected())
  454. wattron(currentWin, A_REVERSE | A_BOLD);
  455. if (flags.searched())
  456. color = OutputFlag::SPECIAL_SEARCH;
  457. else if (colors.find(flags.type()) != colors.end())
  458. color = flags.type();
  459. if (color != OutputFlag::SPECIAL_NONE)
  460. wattron(currentWin, COLOR_PAIR(color));
  461. mvwprintw(currentWin, offsetY, x, "%c", item);
  462. wattroff(currentWin, A_REVERSE | A_BOLD);
  463. if (color != OutputFlag::SPECIAL_NONE)
  464. wattroff(currentWin, COLOR_PAIR(color));
  465. return getNbLines(x +1, maxWidth);
  466. }
  467. unsigned int CurseSplitOutput::write(const int &x, const int &y, const std::string &str, const size_t strlen, unsigned int maxWidth, const OutputFlag flags)
  468. {
  469. int offsetY = y - scrollTop[workingWin];
  470. if (offsetY < 0)
  471. return 1;
  472. wmove(currentWin, offsetY, x);
  473. write(str, flags);
  474. return getNbLines(strlen +x, maxWidth);
  475. }
  476. void CurseSplitOutput::write(const std::string &str, const OutputFlag flags) const
  477. {
  478. char color = OutputFlag::SPECIAL_NONE;
  479. if (flags.selected())
  480. wattron(currentWin, A_REVERSE | A_BOLD);
  481. if (flags.searched())
  482. color = OutputFlag::SPECIAL_SEARCH;
  483. else if (colors.find(flags.type()) != colors.end())
  484. color = flags.type();
  485. if (color != OutputFlag::SPECIAL_NONE)
  486. wattron(currentWin, COLOR_PAIR(color));
  487. wprintw(currentWin, "%s", str.c_str());
  488. wattroff(currentWin, A_REVERSE | A_BOLD);
  489. if (color != OutputFlag::SPECIAL_NONE)
  490. wattroff(currentWin, COLOR_PAIR(color));
  491. }
  492. void CurseSplitOutput::destroyAllSubWin()
  493. {
  494. for (WINDOW *i: outerWin)
  495. {
  496. wborder(i, ' ', ' ', ' ',' ',' ',' ',' ',' ');
  497. wrefresh(i);
  498. delwin(i);
  499. }
  500. for (WINDOW *i: subwindows)
  501. delwin(i);
  502. subwindows.clear();
  503. outerWin.clear();
  504. }
  505. const std::pair<unsigned int, unsigned int> CurseSplitOutput::getScreenSize() const
  506. {
  507. std::pair<unsigned int, unsigned int> result = CurseOutput::getScreenSize();
  508. result.first /= nbInputs;
  509. result.second -=2 ;
  510. return result;
  511. }
  512. void CurseSplitOutput::init()
  513. {
  514. if (!isatty(fileno(stdin)) || !isatty(fileno(stdout)))
  515. {
  516. screen_fd = fopen("/dev/tty", "r+");
  517. setbuf(screen_fd, nullptr);
  518. screen = newterm(nullptr, screen_fd, screen_fd);
  519. }
  520. else
  521. {
  522. screen = newterm(nullptr, stdout, stdin);
  523. screen_fd = nullptr;
  524. }
  525. wtimeout(stdscr, 150);
  526. cbreak();
  527. clear();
  528. noecho();
  529. curs_set(false);
  530. keypad(stdscr, true);
  531. if (params.colorEnabled())
  532. {
  533. start_color();
  534. init_pair(OutputFlag::TYPE_NUMBER, COLOR_GREEN, COLOR_BLACK);
  535. init_pair(OutputFlag::TYPE_BOOL, COLOR_RED, COLOR_BLACK);
  536. init_pair(OutputFlag::TYPE_NULL, COLOR_RED, COLOR_BLACK);
  537. init_pair(OutputFlag::TYPE_STRING, COLOR_CYAN, COLOR_BLACK);
  538. init_pair(OutputFlag::TYPE_OBJKEY, COLOR_CYAN, COLOR_BLACK);
  539. init_pair(OutputFlag::SPECIAL_SEARCH, COLOR_WHITE, COLOR_BLUE);
  540. init_pair(OutputFlag::SPECIAL_ERROR, COLOR_WHITE, COLOR_RED);
  541. colors.insert(OutputFlag::TYPE_NUMBER);
  542. colors.insert(OutputFlag::TYPE_BOOL);
  543. colors.insert(OutputFlag::TYPE_STRING);
  544. colors.insert(OutputFlag::TYPE_OBJKEY);
  545. colors.insert(OutputFlag::TYPE_NULL);
  546. }
  547. signal(SIGWINCH, _resizeFnc);
  548. signal(SIGINT, _resizeFnc);
  549. signal(SIGTERM, _resizeFnc);
  550. signal(SIGKILL, _resizeFnc);
  551. }
  552. void CurseSplitOutput::shutdown()
  553. {
  554. endwin();
  555. delscreen(screen);
  556. if (screen_fd)
  557. {
  558. fclose(screen_fd);
  559. screen_fd = nullptr;
  560. }
  561. screen = nullptr;
  562. }
  563. const OutputFlag CurseSplitOutput::getFlag(const JSonElement *e) const
  564. {
  565. return getFlag(e, selection[workingWin]);
  566. }
  567. const OutputFlag CurseSplitOutput::getFlag(const JSonElement *item, const JSonElement *selection) const
  568. {
  569. OutputFlag res;
  570. const JSonElement *i = dynamic_cast<const JSonObjectEntry*>(item) ? **((const JSonObjectEntry*)item) : item;
  571. res.selected(item == selection);
  572. res.searched(std::find(search_result[selectedWin].cbegin(), search_result[selectedWin].cend(), item) != search_result[selectedWin].cend());
  573. if (dynamic_cast<const JSonPrimitive<std::string> *>(i))
  574. res.type(OutputFlag::TYPE_STRING);
  575. else if (dynamic_cast<const JSonPrimitive<bool> *>(i))
  576. res.type(OutputFlag::TYPE_BOOL);
  577. else if (dynamic_cast<const JSonPrimitive<Null> *>(i))
  578. res.type(OutputFlag::TYPE_NULL);
  579. else if (dynamic_cast<const AJSonPrimitive *>(i))
  580. res.type(OutputFlag::TYPE_NUMBER);
  581. else if (dynamic_cast<const JSonObject*>(i))
  582. res.type(OutputFlag::TYPE_OBJ);
  583. else if (dynamic_cast<const JSonArray*>(i))
  584. res.type(OutputFlag::TYPE_ARR);
  585. return res;
  586. }