split.c 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. /******************************************************************************
  2. * This file is part of TinTin++ *
  3. * *
  4. * Copyright 2004-2019 Igor van den Hoven *
  5. * *
  6. * TinTin++ is free software; you can redistribute it and/or modify *
  7. * it under the terms of the GNU General Public License as published by *
  8. * the Free Software Foundation; either version 3 of the License, or *
  9. * (at your option) any later version. *
  10. * *
  11. * This program is distributed in the hope that it will be useful, *
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  14. * GNU General Public License for more details. *
  15. * *
  16. * *
  17. * You should have received a copy of the GNU General Public License *
  18. * along with TinTin++. If not, see https://www.gnu.org/licenses. *
  19. ******************************************************************************/
  20. /******************************************************************************
  21. * (T)he K(I)cki(N) (T)ickin D(I)kumud Clie(N)t *
  22. * *
  23. * coded by Bill Reiss 1993 *
  24. * recoded by Igor van den Hoven 2004 *
  25. ******************************************************************************/
  26. #include "tintin.h"
  27. DO_COMMAND(do_split)
  28. {
  29. char arg1[BUFFER_SIZE], arg2[BUFFER_SIZE];
  30. arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
  31. arg = sub_arg_in_braces(ses, arg, arg2, GET_ONE, SUB_VAR|SUB_FUN);
  32. if ((*arg1 && !is_math(ses, arg1)) || (*arg2 && !is_math(ses, arg2)))
  33. {
  34. if (*arg == 0)
  35. {
  36. show_error(ses, LIST_COMMAND, "#SYNTAX: #SPLIT {TOP BAR} {BOTTOM BAR}");
  37. }
  38. else
  39. {
  40. show_error(ses, LIST_COMMAND, "#SYNTAX: #SPLIT {TOP BAR} {BOT BAR} {LEFT BAR} {RIGHT BAR}");
  41. }
  42. return ses;
  43. }
  44. ses->split->sav_top_row = *arg1 ? get_number(ses, arg1) : 0;
  45. ses->split->sav_bot_row = *arg2 ? get_number(ses, arg2) : 1;
  46. if (*arg == 0)
  47. {
  48. ses->split->sav_top_col = 0;
  49. ses->split->sav_bot_col = 0;
  50. }
  51. else
  52. {
  53. arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
  54. arg = sub_arg_in_braces(ses, arg, arg2, GET_ONE, SUB_VAR|SUB_FUN);
  55. if ((*arg1 && !is_math(ses, arg1)) || (*arg2 && !is_math(ses, arg2)))
  56. {
  57. show_error(ses, LIST_COMMAND, "#SYNTAX: #SPLIT {TOP BAR} {BOT BAR} {LEFT BAR} {RIGHT BAR}");
  58. return ses;
  59. }
  60. ses->split->sav_top_col = *arg1 ? get_number(ses, arg1) : 1;
  61. ses->split->sav_bot_col = *arg2 ? get_number(ses, arg2) : 0;
  62. }
  63. DEL_BIT(ses->flags, SES_FLAG_SCROLLSPLIT);
  64. SET_BIT(ses->flags, SES_FLAG_SPLIT);
  65. init_split(ses, ses->split->sav_top_row, ses->split->sav_top_col, ses->split->sav_bot_row, ses->split->sav_bot_col);
  66. return ses;
  67. }
  68. DO_COMMAND(do_unsplit)
  69. {
  70. memset(ses->split, 0, sizeof(struct split_data));
  71. ses->wrap = gtd->screen->cols;
  72. reset_screen(ses);
  73. SET_BIT(ses->scroll->flags, SCROLL_FLAG_RESIZE);
  74. if (HAS_BIT(ses->flags, SES_FLAG_SPLIT))
  75. {
  76. if (HAS_BIT(ses->telopts, TELOPT_FLAG_NAWS))
  77. {
  78. client_send_sb_naws(ses, 0, NULL);
  79. }
  80. DEL_BIT(ses->flags, SES_FLAG_SPLIT);
  81. DEL_BIT(ses->flags, SES_FLAG_SCROLLSPLIT);
  82. }
  83. check_all_events(ses, SUB_ARG, 0, 4, "SCREEN UNSPLIT", ntos(ses->split->top_row), ntos(ses->split->top_col), ntos(ses->split->bot_row), ntos(ses->split->bot_col));
  84. return ses;
  85. }
  86. void init_split(struct session *ses, int top_row, int top_col, int bot_row, int bot_col)
  87. {
  88. push_call("init_split(%p,%d,%d,%d,%d)",ses,top_row,top_col,bot_row,bot_col);
  89. SET_BIT(ses->scroll->flags, SCROLL_FLAG_RESIZE);
  90. if (!HAS_BIT(ses->flags, SES_FLAG_SPLIT))
  91. {
  92. ses->split->top_row = 1;
  93. ses->split->top_col = 1;
  94. ses->split->bot_row = gtd->screen->rows;
  95. ses->split->bot_col = gtd->screen->cols;
  96. ses->wrap = gtd->screen->cols;
  97. init_pos(ses, gtd->screen->rows, 1);
  98. if (ses->map && HAS_BIT(ses->map->flags, MAP_FLAG_VTMAP))
  99. {
  100. SET_BIT(ses->flags, SES_FLAG_UPDATEVTMAP);
  101. }
  102. pop_call();
  103. return;
  104. }
  105. if (HAS_BIT(ses->flags, SES_FLAG_SCROLLSPLIT))
  106. {
  107. ses->split->top_row = top_row > 0 ? top_row : top_row < 0 ? gtd->screen->rows + top_row + 1 : 1;
  108. ses->split->top_col = top_col > 0 ? top_col : top_col < 0 ? gtd->screen->cols + top_col + 1 : 1;
  109. ses->split->bot_row = bot_row > 0 ? bot_row : bot_row < 0 ? gtd->screen->rows + bot_row + 1 : gtd->screen->rows - 2;
  110. ses->split->bot_col = bot_col > 0 ? bot_col : bot_col < 0 ? gtd->screen->cols + bot_col + 1 : gtd->screen->cols;
  111. }
  112. else
  113. {
  114. ses->split->top_row = top_row > 0 ? top_row + 1 : top_row < 0 ? gtd->screen->rows + top_row + 1 : 1;
  115. ses->split->top_col = top_col > 0 ? top_col + 1 : top_col < 0 ? gtd->screen->cols + top_col + 1 : 1;
  116. ses->split->bot_row = bot_row > 0 ? gtd->screen->rows - bot_row - 1 : bot_row < 0 ? bot_row * -1 : gtd->screen->rows - 1;
  117. ses->split->bot_col = bot_col > 0 ? gtd->screen->cols - bot_col : bot_col < 0 ? bot_col * -1 : gtd->screen->cols;
  118. }
  119. ses->split->top_row = URANGE(1, ses->split->top_row, gtd->screen->rows -3);
  120. ses->split->bot_row = URANGE(ses->split->top_row + 1, ses->split->bot_row, gtd->screen->rows - 1);
  121. ses->split->top_col = URANGE(1, ses->split->top_col, gtd->screen->cols - 2);
  122. ses->split->bot_col = URANGE(ses->split->top_col + 1, ses->split->bot_col, gtd->screen->cols);
  123. ses->wrap = ses->split->bot_col - (ses->split->top_col - 1);
  124. scroll_region(ses, ses->split->top_row, ses->split->bot_row);
  125. init_pos(ses, gtd->screen->rows, 1);
  126. if (HAS_BIT(ses->telopts, TELOPT_FLAG_NAWS))
  127. {
  128. client_send_sb_naws(ses, 0, NULL);
  129. }
  130. if (ses->map && HAS_BIT(ses->map->flags, MAP_FLAG_VTMAP))
  131. {
  132. SET_BIT(ses->flags, SES_FLAG_UPDATEVTMAP);
  133. }
  134. if (!HAS_BIT(ses->flags, SES_FLAG_SCROLLSPLIT))
  135. {
  136. if (gtd->level->quiet == 0)
  137. {
  138. // if (HAS_BIT(ses->charset, CHARSET_FLAG_UTF8))
  139. {
  140. do_screen(ses, "FILL DEFAULT");
  141. }
  142. /* else
  143. {
  144. fill_split_region(ses, "-");
  145. erase_scroll_region(ses);
  146. fill_split_region(ses, "-");
  147. buffer_end(ses, "");
  148. }*/
  149. }
  150. }
  151. check_all_events(ses, SUB_ARG, 0, 4, "SCREEN SPLIT", ntos(ses->split->top_row), ntos(ses->split->top_col), ntos(ses->split->bot_row), ntos(ses->split->bot_col));
  152. pop_call();
  153. return;
  154. }
  155. /*
  156. unsplit
  157. */
  158. void reset_screen(struct session *ses)
  159. {
  160. reset_scroll_region(ses);
  161. init_pos(ses, gtd->screen->rows, 1);
  162. }
  163. /*
  164. refresh
  165. */
  166. void dirty_screen(struct session *ses)
  167. {
  168. push_call("dirty_screen(%p)",ses);
  169. refresh_session_terminal(ses);
  170. print_stdout("\e=");
  171. if (HAS_BIT(ses->flags, SES_FLAG_SPLIT))
  172. {
  173. init_split(ses, ses->split->sav_top_row, ses->split->sav_top_col, ses->split->sav_bot_row, ses->split->sav_bot_col);
  174. }
  175. else if (IS_SPLIT(ses))
  176. {
  177. scroll_region(ses, ses->split->top_row, ses->split->bot_row);
  178. }
  179. else
  180. {
  181. reset_screen(ses);
  182. }
  183. if (IS_SPLIT(ses) && ses == gtd->ses)
  184. {
  185. init_pos(ses, gtd->screen->rows, 1);
  186. }
  187. pop_call();
  188. return;
  189. }
  190. void split_show(struct session *ses, char *prompt, int row, int col)
  191. {
  192. char buf1[BUFFER_SIZE];
  193. int original_row, original_col, len, clear;
  194. original_row = row;
  195. original_col = col;
  196. if (row < 0)
  197. {
  198. row = 1 + gtd->screen->rows + row;
  199. }
  200. else if (row == 0)
  201. {
  202. row = gtd->screen->rows - 1;
  203. }
  204. clear = 0;
  205. if (col < 0)
  206. {
  207. col = 1 + gtd->screen->cols + col;
  208. }
  209. else if (col == 0)
  210. {
  211. col = 1;
  212. clear = 1;
  213. }
  214. if (row < 1 || row > gtd->screen->rows)
  215. {
  216. show_error(ses, LIST_PROMPT, "#ERROR: PROMPT ROW IS OUTSIDE THE SCREEN: {%s} {%d} {%d}.", prompt, original_row, original_col);
  217. return;
  218. }
  219. if (col < 0 || col > gtd->screen->cols)
  220. {
  221. show_error(ses, LIST_PROMPT, "#ERROR: PROMPT COLUMN IS OUTSIDE THE SCREEN: {%s} {%d} {%d}.", prompt, original_row, original_col);
  222. return;
  223. }
  224. if (row > ses->split->top_row && row <= ses->split->bot_row)
  225. {
  226. if (col >= ses->split->top_col && col <= ses->split->bot_col)
  227. {
  228. show_error(ses, LIST_PROMPT, "#ERROR: PROMPT ROW IS INSIDE THE SCROLLING REGION: {%s} {%d}.", prompt, original_row);
  229. return;
  230. }
  231. }
  232. if (ses != gtd->ses)
  233. {
  234. return;
  235. }
  236. len = strip_vt102_strlen(ses, prompt);
  237. if (len == 0)
  238. {
  239. sprintf(buf1, "%.*s", gtd->screen->cols + 4, "\e[0m--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------");
  240. }
  241. else if (col - 1 + len <= gtd->screen->cols)
  242. {
  243. sprintf(buf1, "%s", prompt);
  244. }
  245. else
  246. {
  247. show_debug(ses, LIST_PROMPT, "#DEBUG PROMPT {%s}", prompt);
  248. sprintf(buf1, "#PROMPT SIZE (%d) LONGER THAN ROW SIZE (%d)", len, gtd->screen->cols);
  249. }
  250. save_pos(ses);
  251. if (row == gtd->screen->rows)
  252. {
  253. gtd->input_off = len + 1;
  254. goto_pos(ses, row, col);
  255. print_stdout("%s%s", buf1, gtd->input_buf);
  256. // bit of a hack
  257. gtd->screen->sav_col[0] = inputline_cur_pos();
  258. }
  259. else
  260. {
  261. goto_pos(ses, row, col);
  262. print_stdout("%s%s", clear ? "\e[2K" : "", buf1);
  263. }
  264. // set_line_screen(buf1, row - 1, col - 1);
  265. restore_pos(ses);
  266. }