command.c 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347
  1. /* command.c, Ait, BSD 3-Clause, Kevin Bloom, 2023-2024,
  2. Derived from: Atto January 2017
  3. Derived from: AnthonyEditor January 93
  4. */
  5. #include "header.h"
  6. #include "termbox.h"
  7. #include "util.h"
  8. void quit() { done = 1; }
  9. void up()
  10. {
  11. curbp->b_point = lncolumn(curbp, upup(curbp, curwp, curbp->b_point),curbp->b_pcol - curwp->w_left);
  12. }
  13. void down()
  14. {
  15. curbp->b_point = lncolumn(curbp, dndn(curbp, curwp, curbp->b_point),curbp->b_pcol - curwp->w_left);
  16. }
  17. void lnbegin()
  18. {
  19. char_t *p;
  20. if(curbp->b_point == 0)
  21. return;
  22. p = ptr(curbp, curbp->b_point);
  23. while(*(p = ptr(curbp, curbp->b_point-1)) != '\n' && p > curbp->b_buf)
  24. --curbp->b_point;
  25. if(curbp->b_point != 0 && p == curbp->b_buf)
  26. --curbp->b_point;
  27. curbp->b_pcol = 0 + curwp->w_left;
  28. }
  29. void version() { msg(VERSION); }
  30. void top() { curbp->b_point = 0; curbp->b_pcol = 0 + curwp->w_left; }
  31. void bottom()
  32. {
  33. curbp->b_point = pos(curbp, curbp->b_ebuf);
  34. if (curbp->b_epage < pos(curbp, curbp->b_ebuf))
  35. curbp->b_reframe = 1;
  36. curbp->b_pcol = 0 + curwp->w_left;
  37. }
  38. void block() { curbp->b_mark = curbp->b_point; }
  39. void copy() { copy_cut(FALSE, TRUE, FALSE); }
  40. void cut() { copy_cut(TRUE, TRUE, FALSE); }
  41. void resize_terminal()
  42. {
  43. LINES = tb_height();
  44. COLS = tb_width();
  45. MSGLINE = LINES-1;
  46. one_window(curwp);
  47. }
  48. void print_to_msgline(const char *msg)
  49. {
  50. printf_tb(0, MSGLINE, TB_DEFAULT, TB_DEFAULT, msg);
  51. tb_set_cursor(strlen(msg), MSGLINE);
  52. }
  53. void quit_ask()
  54. {
  55. if (modified_buffers() > 0) {
  56. const char *msg = "Modified buffers exist; really exit (y/N) ?";
  57. print_to_msgline(msg);
  58. clrtoeol(msg, MSGLINE);
  59. if (!yesno(FALSE)) {
  60. clrtoeol("", MSGLINE);
  61. return;
  62. }
  63. }
  64. quit();
  65. }
  66. void redraw()
  67. {
  68. window_t *wp;
  69. for (wp=wheadp; wp != NULL; wp = wp->w_next)
  70. wp->w_update = TRUE;
  71. update_display();
  72. }
  73. void left()
  74. {
  75. int n = prev_utf8_char_size();
  76. if(curbp->b_point == 0)
  77. return;
  78. while (0 < curbp->b_point && n-- > 0)
  79. --curbp->b_point;
  80. }
  81. void right()
  82. {
  83. if(curbp->b_point == pos(curbp, curbp->b_ebuf))
  84. return;
  85. int n = utf8_size(*ptr(curbp,curbp->b_point));
  86. while ((curbp->b_point < pos(curbp, curbp->b_ebuf)) && n-- > 0)
  87. ++curbp->b_point;
  88. }
  89. /* work out number of bytes based on first byte */
  90. int utf8_size(char_t c)
  91. {
  92. if (c >= 192 && c < 224) return 2;
  93. if (c >= 224 && c < 240) return 3;
  94. if (c >= 240 && c < 248) return 4;
  95. return 1; /* if in doubt it is 1 */
  96. }
  97. int prev_utf8_char_size()
  98. {
  99. int n;
  100. for (n=2;n<5;n++)
  101. if (-1 < curbp->b_point - n && (utf8_size(*(ptr(curbp, curbp->b_point - n))) == n))
  102. return n;
  103. return 1;
  104. }
  105. void lnend()
  106. {
  107. char_t *p;
  108. int cols = 0;
  109. lnbegin(); // reset the line so we get the right number for `cols`
  110. while(*(p = ptr(curbp, curbp->b_point)) != '\n' && curbp->b_ebuf > p) {
  111. ++curbp->b_point;
  112. cols++;
  113. }
  114. /* loop until we get to the correct column */
  115. while(cols > curwp->w_cols) {
  116. cols -= curwp->w_cols;
  117. }
  118. curbp->b_pcol = cols + curwp->w_left; // set it for column-memory
  119. }
  120. void wleft()
  121. {
  122. char_t *p;
  123. if ((!isspace(*(p = ptr(curbp, curbp->b_point))) || !is_symbol(*p)) && curbp->b_buf < p)
  124. --curbp->b_point;
  125. while ((isspace(*(p = ptr(curbp, curbp->b_point))) || is_symbol(*p)) && curbp->b_buf < p)
  126. --curbp->b_point;
  127. while (!isspace(*(p = ptr(curbp, curbp->b_point))) && !is_symbol(*p) && curbp->b_buf < p)
  128. --curbp->b_point;
  129. if(isspace(*(p = ptr(curbp, curbp->b_point))) || is_symbol(*p))
  130. ++curbp->b_point;
  131. }
  132. void wleftdelete()
  133. {
  134. currentcommand = KBD_DELETE_CHAR;
  135. iblock();
  136. wleft();
  137. copy_cut(TRUE, TRUE, FALSE);
  138. }
  139. void pgdown()
  140. {
  141. curbp->b_page = curbp->b_point = upup(curbp, curwp, curbp->b_epage);
  142. while (0 < curbp->b_row--)
  143. down();
  144. curbp->b_epage = pos(curbp, curbp->b_ebuf);
  145. curbp->b_pcol = 0 + curwp->w_left;
  146. }
  147. void pgup()
  148. {
  149. int i = curwp->w_rows;
  150. while (0 < --i) {
  151. curbp->b_page = upup(curbp, curwp, curbp->b_page);
  152. up();
  153. }
  154. curbp->b_pcol = 0 + curwp->w_left;
  155. }
  156. void wright()
  157. {
  158. char_t *p;
  159. if ((!isspace(*(p = ptr(curbp, curbp->b_point))) || !is_symbol(*p)) && p < curbp->b_ebuf)
  160. ++curbp->b_point;
  161. while ((isspace(*(p = ptr(curbp, curbp->b_point))) || is_symbol(*p)) && p < curbp->b_ebuf)
  162. ++curbp->b_point;
  163. while (!isspace(*(p = ptr(curbp, curbp->b_point))) && !is_symbol(*p) && p < curbp->b_ebuf)
  164. ++curbp->b_point;
  165. }
  166. void wrightdelete()
  167. {
  168. currentcommand = KBD_DELETE_CHAR;
  169. iblock();
  170. wright();
  171. copy_cut(TRUE, TRUE, FALSE);
  172. }
  173. void insert()
  174. {
  175. assert(curbp->b_gap <= curbp->b_egap);
  176. if (curbp->b_gap == curbp->b_egap && !growgap(curbp, CHUNK))
  177. return;
  178. curbp->b_point = movegap(curbp, curbp->b_point);
  179. /* overwrite if mid line, not EOL or EOF, CR will insert as normal */
  180. if ((curbp->b_flags & B_OVERWRITE) && *input != '\r' && *(ptr(curbp, curbp->b_point)) != '\n' && curbp->b_point < pos(curbp,curbp->b_ebuf) ) {
  181. *(ptr(curbp, curbp->b_point)) = *input;
  182. if (curbp->b_point < pos(curbp, curbp->b_ebuf))
  183. ++curbp->b_point;
  184. } else {
  185. *curbp->b_gap++ = *input == '\r' ? '\n' : *input;
  186. curbp->b_point = pos(curbp, curbp->b_egap);
  187. // force reframe if scrolled off bottom of screen and at EOF
  188. if (curbp->b_point == pos(curbp, curbp->b_ebuf) && curbp->b_point >= curbp->b_epage &&
  189. curwp->w_rows == curwp->w_row)
  190. curbp->b_reframe = 1;
  191. }
  192. curbp->b_flags |= B_MODIFIED;
  193. undoset_flag = TRUE;
  194. currentcommand = KBD_INSERT;
  195. }
  196. void insert_str()
  197. {
  198. int len = strlen((const char *)input);
  199. assert(curbp->b_gap <= curbp->b_egap);
  200. undoset(1, FALSE);
  201. if (curbp->b_gap == curbp->b_egap && !growgap(curbp, CHUNK))
  202. return;
  203. curbp->b_point = movegap(curbp, curbp->b_point);
  204. /* overwrite if mid line, not EOL or EOF, CR will insert as normal */
  205. if ((curbp->b_flags & B_OVERWRITE) && input[0] != '\r' && *(ptr(curbp, curbp->b_point)) != '\n' && curbp->b_point < pos(curbp,curbp->b_ebuf) ) {
  206. *(ptr(curbp, curbp->b_point)) = *input;
  207. if (curbp->b_point < pos(curbp, curbp->b_ebuf))
  208. ++curbp->b_point;
  209. } else {
  210. for(int i = 0; i < len; i++) {
  211. *curbp->b_gap++ = input[i] == '\r' ? '\n' : input[i];
  212. // if(input[i] == '\n' || input[i] == '\r')
  213. // curbp->b_line++;
  214. }
  215. curbp->b_point = pos(curbp, curbp->b_egap);
  216. // force reframe if scrolled off bottom of screen and at EOF
  217. if (curbp->b_point == pos(curbp, curbp->b_ebuf) && curbp->b_point >= curbp->b_epage &&
  218. curwp->w_rows == curwp->w_row)
  219. curbp->b_reframe = 1;
  220. }
  221. curbp->b_flags |= B_MODIFIED;
  222. undoset_flag = TRUE;
  223. }
  224. void insert_unicode()
  225. {
  226. int len = strlen((const char *)unicode_buf);
  227. assert(curbp->b_gap <= curbp->b_egap);
  228. undoset(INSERT, lastcommand == KBD_INSERT);
  229. if (curbp->b_gap == curbp->b_egap && !growgap(curbp, CHUNK))
  230. return;
  231. curbp->b_point = movegap(curbp, curbp->b_point);
  232. /* overwrite if mid line, not EOL or EOF, CR will insert as normal */
  233. for(int i = 0; i < len; i++) {
  234. *curbp->b_gap++ = unicode_buf[i];
  235. }
  236. curbp->b_point = pos(curbp, curbp->b_egap);
  237. // force reframe if scrolled off bottom of screen and at EOF
  238. if (curbp->b_point == pos(curbp, curbp->b_ebuf) && curbp->b_point >= curbp->b_epage &&
  239. curwp->w_rows == curwp->w_row)
  240. curbp->b_reframe = 1;
  241. curbp->b_flags |= B_MODIFIED;
  242. undoset_flag = TRUE;
  243. unicode_buf[0] = '\0';
  244. currentcommand = KBD_INSERT;
  245. }
  246. void backsp()
  247. {
  248. undoset(3, lastcommand == KBD_DELETE_CHAR);
  249. if(curbp->b_point != 0 && *ptr(curbp, curbp->b_point - 1) == '\n')
  250. curbp->b_line--;
  251. curbp->b_point = movegap(curbp, curbp->b_point);
  252. if (curbp->b_buf < curbp->b_gap) {
  253. curbp->b_gap -= prev_utf8_char_size();
  254. curbp->b_flags |= B_MODIFIED;
  255. }
  256. curbp->b_point = pos(curbp, curbp->b_egap);
  257. currentcommand = KBD_DELETE_CHAR;
  258. }
  259. void delete()
  260. {
  261. undoset(2, lastcommand == KBD_DELETE_CHAR);
  262. curbp->b_point = movegap(curbp, curbp->b_point);
  263. if (curbp->b_egap < curbp->b_ebuf) {
  264. curbp->b_egap += utf8_size(*curbp->b_egap);
  265. curbp->b_point = pos(curbp, curbp->b_egap);
  266. curbp->b_flags |= B_MODIFIED;
  267. }
  268. currentcommand = KBD_DELETE_CHAR;
  269. }
  270. void gotoline()
  271. {
  272. int line;
  273. point_t p;
  274. if (getinput("Goto line: ", temp, STRBUF_S, F_CLEAR, FALSE)) {
  275. line = atoi(temp);
  276. p = line_to_point(line);
  277. if (p != -1) {
  278. curbp->b_point = p;
  279. curbp->b_pcol = 0 + curwp->w_left;
  280. if (curbp->b_epage < pos(curbp, curbp->b_ebuf)) curbp->b_reframe = 1;
  281. curwp->w_update = TRUE;
  282. msg("Line %d", line);
  283. } else {
  284. msg("Line %d, not found", line);
  285. }
  286. }
  287. clrtoeol("", MSGLINE);
  288. }
  289. void jumptorow()
  290. {
  291. int line = -1, j = 0, i = 0, current, lastln, pageln;
  292. char num[3] = { 0, 0, 0 };
  293. struct tb_event ev;
  294. char *prompt = "Jump to line reference: ";
  295. int start_col = strlen(prompt), match = FALSE;
  296. char opts[10] = {'f','j','d','k','s','l','g','h', 'a', ';'};
  297. char chars[curwp->w_rows][2];
  298. point_t point;
  299. char_t *p;
  300. char f, s;
  301. int count = 0, fp = 0, sp = 0;
  302. get_line_stats(&current, &lastln, curbp);
  303. pageln = current - curwp->w_row;
  304. point = curbp->b_page;
  305. p = ptr(curbp, point);
  306. for(int i = 0; i < curwp->w_rows && pageln <= lastln; i++) {
  307. f = opts[fp];
  308. s = opts[sp];
  309. chars[i][0] = f;
  310. chars[i][1] = s;
  311. printf_tb(curwp->w_left, curwp->w_top+i, TB_RED, TB_CYAN, "%c%c", f,s);
  312. sp++;
  313. count++;
  314. if(count > 7) {
  315. fp++;
  316. sp = 0;
  317. count = 0;
  318. }
  319. int c = 1;
  320. while(*(p = ptr(curbp, point)) != '\n' &&
  321. curbp->b_ebuf > p && c < curwp->w_cols) {
  322. ++point;
  323. c++;
  324. }
  325. if(*p == '\n' || pageln == lastln)
  326. pageln++;
  327. ++point;
  328. p = ptr(curbp, point);
  329. }
  330. display_prompt_and_response(prompt, num);
  331. tb_present();
  332. while(j < 2) {
  333. display_prompt_and_response(prompt, num);
  334. tb_present();
  335. if(tb_poll_event(&ev) != TB_OK) break;
  336. if(ev.key == TB_KEY_CTRL_G) {
  337. clrtoeol("", MSGLINE);
  338. return;
  339. }
  340. if(j < 2) {
  341. num[j] = ev.ch;
  342. tb_set_cursor(start_col, MSGLINE);
  343. addstr(num);
  344. point = curbp->b_page;
  345. p = ptr(curbp, point);
  346. if(j == 0) {
  347. pageln = current - curwp->w_row;
  348. for(int i = 0; i < curwp->w_rows && pageln <= lastln; i++) {
  349. if(chars[i][0] == ev.ch) {
  350. match = TRUE;
  351. if(*p != '\n')
  352. p = ptr(curbp, point+1);
  353. if(*p == '\0')
  354. *p = ' ';
  355. printf_tb(curwp->w_left, curwp->w_top+i, TB_RED, TB_CYAN, "%c", chars[i][1]);
  356. printf_tb(curwp->w_left+1, curwp->w_top+i, TB_DEFAULT, TB_DEFAULT, "%c", *p == '\n' ? ' ' : *p);
  357. } else {
  358. printf_tb(curwp->w_left, curwp->w_top+i, TB_DEFAULT, TB_DEFAULT, "%c", *p == '\n' ? ' ' : *p);
  359. if(*p != '\n')
  360. p = ptr(curbp, point+1);
  361. if(*p == '\0')
  362. *p = ' ';
  363. printf_tb(curwp->w_left+1, curwp->w_top+i, TB_DEFAULT, TB_DEFAULT, "%c", *p == '\n' ? ' ' : *p);
  364. }
  365. int c = 1;
  366. while(*(p = ptr(curbp, point)) != '\n' &&
  367. curbp->b_ebuf > p && c < curwp->w_cols) {
  368. ++point;
  369. c++;
  370. }
  371. if(*p == '\n' || pageln == lastln)
  372. pageln++;
  373. ++point;
  374. p = ptr(curbp, point);
  375. }
  376. }
  377. j++;
  378. }
  379. if(!match) {
  380. clrtoeol("", MSGLINE);
  381. return;
  382. }
  383. }
  384. for(; i < curwp->w_rows; i++) {
  385. if(chars[i][0] == num[0] && chars[i][1] == num[1]) {
  386. line = curwp->w_row - i;
  387. break;
  388. }
  389. }
  390. if(i == curwp->w_rows) {
  391. msg("Out of bounds");
  392. return;
  393. }
  394. if(line > 0) {
  395. for(; line > 0; line--) {
  396. up();
  397. }
  398. } else {
  399. for(; line < 0; line++) {
  400. down();
  401. }
  402. }
  403. clrtoeol("", MSGLINE);
  404. }
  405. void jumpword()
  406. {
  407. point_t current = curbp->b_page;
  408. char num[3] = { 'f', 'f', 0 };
  409. int j = 0, match = FALSE;
  410. char starting[1];
  411. struct tb_event ev;
  412. char *prompt = "Jump to word starting with: ";
  413. int start_col = strlen(prompt);
  414. char opts[10] = {'f','j','d','k','s','l','g','h', 'a', ';'};
  415. int diff = curbp->b_epage - curbp->b_page;
  416. char chars[diff][2];
  417. point_t point = -1;
  418. int begin = TRUE, is_white = FALSE, is_symb = FALSE, charlen = 0;
  419. char_t *p, *tp;
  420. char f, s;
  421. int count = 0, fp = 0, sp = 0, x = 0, y = 0;
  422. display_prompt_and_response(prompt, starting);
  423. tb_present();
  424. if(tb_poll_event(&ev) != TB_OK) return;
  425. if(ev.key == TB_KEY_CTRL_G) {
  426. clrtoeol("", MSGLINE);
  427. return;
  428. }
  429. starting[0] = (unsigned)ev.ch;
  430. for(; current < curbp->b_epage; current++) {
  431. p = ptr(curbp, current);
  432. is_white = isspace(*p);
  433. is_symb = is_symbol(*p);
  434. if(is_white || is_symb || current == 0)
  435. begin = TRUE;
  436. if(*p == (char_t)starting[0] && begin) {
  437. f = opts[fp];
  438. s = opts[sp];
  439. chars[current-curbp->b_page][0] = f;
  440. chars[current-curbp->b_page][1] = s;
  441. charlen++;
  442. printf_tb(curwp->w_left+x, curwp->w_top+y, TB_RED, TB_CYAN, "%c%c", f,s);
  443. sp++;
  444. count++;
  445. if(count > 7) {
  446. fp++;
  447. sp = 0;
  448. count = 0;
  449. }
  450. begin = FALSE;
  451. }
  452. if(!is_white && !is_symb)
  453. begin = FALSE;
  454. x++;
  455. if(*p == '\t')
  456. x += (TAB_SIZE - 2);
  457. if(*p < 31)
  458. x++;
  459. if(*p == '\n' || x >= curwp->w_cols) {
  460. x = 0;
  461. y++;
  462. }
  463. }
  464. tb_present();
  465. if(charlen > 1) {
  466. display_prompt_and_response(prompt, num);
  467. tb_present();
  468. while(j < 2) {
  469. display_prompt_and_response(prompt, num);
  470. tb_present();
  471. if(tb_poll_event(&ev) != TB_OK) break;
  472. if(ev.key == TB_KEY_CTRL_G) {
  473. clrtoeol("", MSGLINE);
  474. return;
  475. }
  476. if(j < 2) {
  477. num[j] = ev.ch;
  478. tb_set_cursor(start_col, MSGLINE);
  479. addstr(num);
  480. x = 0;
  481. y = 0;
  482. if(j == 0) {
  483. for(current = curbp->b_page; current < curbp->b_epage; current++) {
  484. p = ptr(curbp, current);
  485. tp = ptr(curbp, current);
  486. is_white = isspace(*p);
  487. is_symb = is_symbol(*p);
  488. if(is_white || is_symb || current == 0)
  489. begin = TRUE;
  490. if(*p == (char_t)starting[0] && begin) {
  491. point_t i = current-curbp->b_page;
  492. if(chars[i][0] == ev.ch) {
  493. match = TRUE;
  494. tp = ptr(curbp, current+1);
  495. printf_tb(curwp->w_left+x, curwp->w_top+y, TB_RED, TB_CYAN, "%c", chars[i][1]);
  496. printf_tb(curwp->w_left+x+1, curwp->w_top+y, TB_DEFAULT, TB_DEFAULT, "%c", *tp == '\n' ? ' ' : *tp);
  497. } else {
  498. printf_tb(curwp->w_left+x, curwp->w_top+y, TB_DEFAULT, TB_DEFAULT, "%c", *tp == '\n' ? ' ' : *tp);
  499. tp = ptr(curbp, current+1);
  500. printf_tb(curwp->w_left+x+1, curwp->w_top+y, TB_DEFAULT, TB_DEFAULT, "%c", *tp == '\n' ? ' ' : *tp);
  501. }
  502. begin = FALSE;
  503. }
  504. if(!is_white && !is_symb)
  505. begin = FALSE;
  506. x++;
  507. if(*p == '\t')
  508. x += (TAB_SIZE - 2);
  509. if(*p < 31)
  510. x++;
  511. if(*p == '\n' || x >= curwp->w_cols) {
  512. x = 0;
  513. y++;
  514. }
  515. }
  516. }
  517. j++;
  518. if(!match) {
  519. clrtoeol("", MSGLINE);
  520. return;
  521. }
  522. }
  523. }
  524. }
  525. for(point_t cur = 0; cur < diff; cur++) {
  526. if(chars[cur][0] == num[0] && chars[cur][1] == num[1]) {
  527. point = cur + curbp->b_page;
  528. break;
  529. }
  530. }
  531. if(point == -1) {
  532. msg("Out of bounds.");
  533. } else {
  534. curbp->b_point = point;
  535. int cols = 0;
  536. /* Calculate the pcol value */
  537. lnbegin(); // reset the line so we get the right number for `cols`
  538. while(curbp->b_point != point) {
  539. ++curbp->b_point;
  540. cols++;
  541. }
  542. /* loop until we get to the correct column */
  543. while(cols > curwp->w_cols) {
  544. cols -= curwp->w_cols;
  545. }
  546. curbp->b_pcol = cols + curwp->w_left; // set it for column-memory
  547. clrtoeol("", MSGLINE);
  548. }
  549. /* Clear out the chars array */
  550. for(int i = 0; i < diff; i++) {
  551. chars[i][0] = 0;
  552. chars[i][1] = 0;
  553. }
  554. /* TODO: figure out why this has to be here
  555. Without this printf, the chars array doesn't appear to get
  556. cleared entirely and you end up jumping to the wrong points.
  557. */
  558. printf("%s", chars[0]);
  559. }
  560. void get_current_path(char *cur_path)
  561. {
  562. int cutoff = 0;
  563. for(int i = strlen(curbp->b_fname) - 1; i > -1; i--) {
  564. if(curbp->b_fname[i] == '/') {
  565. cutoff = i;
  566. break;
  567. }
  568. }
  569. for(int i = 0; i <= cutoff; i++)
  570. cur_path[i] = curbp->b_fname[i];
  571. cur_path[cutoff+1] = '\0';
  572. }
  573. void insertfile()
  574. {
  575. char cur_path[PATH_MAX] = "\0";
  576. if(curbp->b_path) {
  577. get_current_path(cur_path);
  578. strcpy(temp, cur_path);
  579. }
  580. else
  581. strcpy(temp, editor_dir);
  582. if (getfilename("Insert file: ", temp, PATH_MAX))
  583. (void)insert_file(temp, TRUE);
  584. }
  585. void readfile()
  586. {
  587. buffer_t *bp;
  588. char cur_path[PATH_MAX];
  589. if(curbp->b_path) {
  590. get_current_path(cur_path);
  591. strcpy(temp, cur_path);
  592. }
  593. else
  594. strcpy(temp, editor_dir);
  595. int result = getfilename("Find file: ", (char*)temp, PATH_MAX);
  596. if (result) {
  597. bp = find_buffer(temp, TRUE);
  598. disassociate_b(curwp);
  599. curbp = bp;
  600. associate_b2w(curbp, curwp);
  601. if (!growgap(curbp, CHUNK))
  602. fatal("%s: Failed to allocate required memory.\n");
  603. movegap(curbp, 0);
  604. /* load the file if not already loaded */
  605. if (bp != NULL && bp->b_fname[0] == '\0') {
  606. if (!load_file(temp)) {
  607. msg("New file %s", temp);
  608. }
  609. strncpy(curbp->b_fname, temp, PATH_MAX);
  610. curbp->b_fname[PATH_MAX] = '\0'; /* truncate if required */
  611. }
  612. }
  613. }
  614. void savebuffer()
  615. {
  616. const char *message = "No newline at the end of file, add one (Y/n) ?";
  617. if(curbp->b_flags & B_MODIFIED) {
  618. /* move the gap to point 0 so that the ebuf is updated. */
  619. (void) movegap(curbp, 0);
  620. if(*(curbp->b_ebuf - 1) != '\n') {
  621. print_to_msgline(message);
  622. clrtoeol(message, MSGLINE);
  623. if (yesno(TRUE)) {
  624. clrtoeol("", MSGLINE);
  625. *curbp->b_ebuf++ = '\n';
  626. }
  627. }
  628. if (curbp->b_fname[0] != '\0') {
  629. save(curbp->b_fname);
  630. return;
  631. } else {
  632. writefile();
  633. }
  634. } else {
  635. msg("(No changes need to be saved.)");
  636. }
  637. }
  638. void writefile()
  639. {
  640. const char *message = "Write file: ";
  641. strncpy(temp, curbp->b_fname, PATH_MAX);
  642. if (getinput((char *)message, temp, PATH_MAX, F_NONE, FALSE))
  643. if (save(temp) == TRUE)
  644. strncpy(curbp->b_fname, temp, PATH_MAX);
  645. clrtoeol(message, MSGLINE);
  646. }
  647. void killbuffer()
  648. {
  649. buffer_t *kill_bp = curbp;
  650. buffer_t *bp;
  651. int bcount = count_buffers();
  652. const char *message = "Discard changes (y/N) ?";
  653. /* do nothing if only buffer left is the scratch buffer */
  654. if (bcount == 1 && 0 == strcmp(get_buffer_name(curbp), "*scratch*"))
  655. return;
  656. if (curbp->b_flags & B_MODIFIED) {
  657. print_to_msgline(message);
  658. clrtoeol(message, MSGLINE);
  659. if (!yesno(FALSE))
  660. return;
  661. }
  662. if (bcount == 1) {
  663. /* create a scratch buffer */
  664. bp = find_buffer("*scratch*", TRUE);
  665. strncpy(bp->b_bname, "*scratch*", STRBUF_S);
  666. bp->b_path = FALSE;
  667. }
  668. next_buffer();
  669. assert(kill_bp != curbp);
  670. delete_buffer(kill_bp);
  671. for(window_t *wp = wheadp; wp != NULL; wp = wp->w_next) {
  672. if(kill_bp == wp->w_bufp) {
  673. wp->w_bufp = curbp;
  674. }
  675. }
  676. }
  677. void iblock()
  678. {
  679. block();
  680. msg("Mark set");
  681. }
  682. void unmark()
  683. {
  684. curbp->b_pmark = curbp->b_mark;
  685. curbp->b_mark = NOMARK;
  686. msg("Mark removed");
  687. }
  688. void toggle_overwrite_mode() {
  689. if (curbp->b_flags & B_OVERWRITE)
  690. curbp->b_flags &= ~B_OVERWRITE;
  691. else
  692. curbp->b_flags |= B_OVERWRITE;
  693. }
  694. void killtoeol()
  695. {
  696. if (curbp->b_point == pos(curbp, curbp->b_ebuf))
  697. return; /* do nothing if at end of file */
  698. if (*(ptr(curbp, curbp->b_point)) == 0xa) {
  699. delete(); /* delete CR if at start of empty line */
  700. } else {
  701. curbp->b_mark = curbp->b_point;
  702. lnend();
  703. if (curbp->b_mark != curbp->b_point) copy_cut(TRUE, TRUE, FALSE);
  704. }
  705. }
  706. void copy_cut(int cut, int displaymsg, int internal)
  707. {
  708. char_t *p;
  709. /* if no mark or point == marker, nothing doing */
  710. if (curbp->b_mark == NOMARK || curbp->b_point == curbp->b_mark)
  711. return;
  712. if (scrap != NULL) {
  713. free(scrap);
  714. scrap = NULL;
  715. }
  716. if(cut && !internal)
  717. undoset(4, FALSE);
  718. if (curbp->b_point < curbp->b_mark) {
  719. /* point above marker: move gap under point, region = marker - point */
  720. (void) movegap(curbp, curbp->b_point);
  721. p = ptr(curbp, curbp->b_point);
  722. nscrap = curbp->b_mark - curbp->b_point;
  723. if(cut && currentcommand == KBD_DELETE_CHAR)
  724. for(point_t pt = curbp->b_mark-1; pt > curbp->b_point; pt--) {
  725. if(*ptr(curbp, pt) == '\n')
  726. curbp->b_line--;
  727. }
  728. } else {
  729. /* if point below marker: move gap under marker, region = point - marker */
  730. (void) movegap(curbp, curbp->b_mark);
  731. p = ptr(curbp, curbp->b_mark);
  732. nscrap = curbp->b_point - curbp->b_mark;
  733. if (cut && currentcommand != KBD_DELETE_CHAR)
  734. for(point_t pt = curbp->b_mark; pt < curbp->b_point; pt++) {
  735. if(*ptr(curbp, pt) == '\n')
  736. curbp->b_line--;
  737. }
  738. }
  739. if ((scrap = (char_t*) malloc(nscrap)) == NULL && displaymsg) {
  740. msg("No more memory available.");
  741. } else {
  742. (void) memcpy(scrap, p, nscrap * sizeof (char_t));
  743. if (cut) {
  744. curbp->b_egap += nscrap; /* if cut expand gap down */
  745. curbp->b_point = pos(curbp, curbp->b_egap); /* set point to after region */
  746. curbp->b_flags |= B_MODIFIED;
  747. if(displaymsg)
  748. msg("%ld bytes cut.", nscrap);
  749. currentcommand = KBD_CUT;
  750. } else {
  751. if(displaymsg)
  752. msg("%ld bytes copied.", nscrap);
  753. }
  754. curbp->b_mark = NOMARK; /* unmark */
  755. }
  756. }
  757. void paste_internal(int internal)
  758. {
  759. int new_rows = 0;
  760. int col = curwp->w_col - curwp->w_left + 1;
  761. point_t opoint = curbp->b_point;
  762. if(curbp->b_flags & B_OVERWRITE)
  763. return;
  764. if (nscrap <= 0) {
  765. msg("Scrap is empty. Nothing to paste.");
  766. } else if (nscrap < curbp->b_egap - curbp->b_gap || growgap(curbp, nscrap)) {
  767. if(!internal)
  768. undoset(5, FALSE);
  769. curbp->b_point = movegap(curbp, curbp->b_point);
  770. memcpy(curbp->b_gap, scrap, nscrap * sizeof (char_t));
  771. curbp->b_gap += nscrap;
  772. curbp->b_point = pos(curbp, curbp->b_egap);
  773. curbp->b_flags |= B_MODIFIED;
  774. /* TODO: this assumes 1 char = 1 point (not always true) */
  775. col += curbp->b_point - opoint;
  776. for(int i = 0, cc = col; scrap[i] != '\0'; i++) {
  777. cc++;
  778. if(scrap[i] == '\n' || cc >= curwp->w_cols) {
  779. new_rows++;
  780. cc = 0;
  781. }
  782. curbp->b_pcol = cc + curwp->w_left;
  783. }
  784. if (curbp->b_row + new_rows >= curwp->w_rows)
  785. curbp->b_reframe = 1;
  786. }
  787. }
  788. void paste()
  789. {
  790. paste_internal(FALSE);
  791. }
  792. void clipboard()
  793. {
  794. int new_rows = 0;
  795. int ntemp = strlen(gtemp);
  796. if(curbp->b_flags & B_OVERWRITE)
  797. return;
  798. if (ntemp <= 0) {
  799. msg("Temp buffer is empty. Nothing to paste.");
  800. } else if (ntemp < curbp->b_egap - curbp->b_gap || growgap(curbp, ntemp)) {
  801. undoset(CLIPBOARD, FALSE);
  802. curbp->b_point = movegap(curbp, curbp->b_point);
  803. memcpy(curbp->b_gap, gtemp, ntemp * sizeof (char_t));
  804. curbp->b_gap += ntemp;
  805. curbp->b_point = pos(curbp, curbp->b_egap);
  806. curbp->b_flags |= B_MODIFIED;
  807. for(int i = 0; gtemp[i] != '\0'; i++) {
  808. if(gtemp[i] == '\n')
  809. new_rows++;
  810. }
  811. if (curbp->b_row + new_rows > curwp->w_rows &&
  812. curbp->b_point >= curbp->b_epage)
  813. curbp->b_reframe = 1;
  814. free(gtemp);
  815. gtemp = malloc(sizeof(char) * TEMPBUF);
  816. }
  817. }
  818. void showpos()
  819. {
  820. int current, lastln;
  821. point_t end_p = pos(curbp, curbp->b_ebuf);
  822. get_line_stats(&current, &lastln, curbp);
  823. if (curbp->b_point == end_p) {
  824. msg("[EOB] Line = %d/%d Point = %d/%d", current, lastln,
  825. curbp->b_point, ((curbp->b_ebuf - curbp->b_buf) - (curbp->b_egap - curbp->b_gap)));
  826. } else {
  827. char c = unctrl(*(ptr(curbp, curbp->b_point)));
  828. msg("Char = %c 0x%x Line = %d/%d Point = %d/%d", c, *(ptr(curbp, curbp->b_point)),
  829. current, lastln,
  830. curbp->b_point, ((curbp->b_ebuf - curbp->b_buf) - (curbp->b_egap - curbp->b_gap)));
  831. }
  832. }
  833. /* Delete whitespace between non-whitespace */
  834. void deletewhitespacebetween()
  835. {
  836. char_t *p;
  837. while (isspace(*(p = ptr(curbp, curbp->b_point - 1))) && curbp->b_buf < p && *p != '\n')
  838. backsp();
  839. while (isspace(*(p = ptr(curbp, curbp->b_point))) && curbp->b_buf < p && *p != '\n')
  840. delete();
  841. }
  842. void insertnewlinebelow()
  843. {
  844. char_t newline[2];
  845. newline[0] = '\n';
  846. newline[1] = '\0';
  847. input = newline;
  848. undoset(1, lastcommand == KBD_INSERT);
  849. insert();
  850. up();
  851. currentcommand = KBD_INSERT;
  852. }
  853. void insertnewline()
  854. {
  855. point_t point;
  856. char_t *p, *space = NULL, *str;
  857. int spaces = 0, i;
  858. point = segstart(curbp, curwp, lnstart(curbp, curbp->b_point), curbp->b_point);
  859. while(point < pos(curbp, curbp->b_ebuf) &&
  860. isspace(*(p = ptr(curbp, point))) &&
  861. *p != '\n' &&
  862. curwp->w_col != 0) {
  863. if(spaces == 0) {
  864. space = p;
  865. }
  866. if(*p != '\n') {
  867. spaces++;
  868. point++;
  869. }
  870. }
  871. str = (char_t *) malloc(sizeof(char_t)*spaces+2);
  872. str[0] = '\n';
  873. for(i = 0; i < spaces; i++) {
  874. str[i+1] = *space;
  875. }
  876. str[i+1] = '\0';
  877. input = str;
  878. insert_str();
  879. curbp->b_pcol = spaces + curwp->w_left;
  880. currentcommand = KBD_INSERT;
  881. free(str);
  882. if(curwp->w_row == curwp->w_rows-1) {
  883. curbp->b_reframe = TRUE;
  884. }
  885. }
  886. void inserttab()
  887. {
  888. input = (char_t *)"\t";
  889. undoset(1, FALSE);
  890. insert();
  891. }
  892. void inserttabasspace()
  893. {
  894. char_t spaces[TAB_SPACE_SIZE+1];
  895. memset(spaces, ' ', sizeof(spaces));
  896. spaces[TAB_SPACE_SIZE] = '\0';
  897. input = spaces;
  898. insert_str();
  899. }
  900. void suspend()
  901. {
  902. tb_shutdown();
  903. raise(SIGTSTP);
  904. }
  905. void transpose()
  906. {
  907. char_t *cur = ptr(curbp, curbp->b_point);
  908. char_t *prev = ptr(curbp, curbp->b_point-1);
  909. char_t replace[3];
  910. if(cur == curbp->b_ebuf) {
  911. return;
  912. }
  913. point_t mark = curbp->b_mark;
  914. replace[0] = *cur;
  915. replace[1] = *prev;
  916. replace[2] = '\0';
  917. curbp->b_point--;
  918. curbp->b_mark = curbp->b_point + 2;
  919. undoset(REPLACE, 2);
  920. curbp->b_mark = mark;
  921. curbp->b_point++;
  922. memcpy(ptr(curbp, curbp->b_point-1), replace, 2 * sizeof (char_t));
  923. curbp->b_flags |= B_MODIFIED;
  924. }
  925. /* Delete a word but don't display any messages. */
  926. void deleteword(int dir) {
  927. block();
  928. if(dir)
  929. wright();
  930. else
  931. wleft();
  932. copy_cut(TRUE, FALSE, TRUE);
  933. }
  934. /* Transpose words and put scrap back to how it was. */
  935. void transposeword()
  936. {
  937. char_t *current_scrap;
  938. int n_scrap = nscrap;
  939. point_t mark = curbp->b_mark, epoint, point;
  940. /* copy the current scrap */
  941. current_scrap = (char_t*) malloc(nscrap);
  942. (void) memcpy(current_scrap, scrap, nscrap * sizeof (char_t));
  943. /* Find all the key points for the undo */
  944. wright();
  945. epoint = curbp->b_point;
  946. wleft();
  947. wleft();
  948. curbp->b_mark = epoint;
  949. point = curbp->b_point;
  950. undoset(REPLACE, curbp->b_mark - point);
  951. /* Cut the word to the left*/
  952. curbp->b_mark = point;
  953. curbp->b_point = point;
  954. wright();
  955. copy_cut(TRUE, FALSE, TRUE);
  956. /* paste the left word */
  957. right();
  958. paste_internal(TRUE);
  959. /* cut the right word */
  960. curbp->b_mark = curbp->b_point;
  961. wright();
  962. copy_cut(TRUE, FALSE, TRUE);
  963. wleft();
  964. /* paste the right word */
  965. left();
  966. paste_internal(TRUE);
  967. /* Put it all back together */
  968. if (scrap != NULL) {
  969. free(scrap);
  970. scrap = NULL;
  971. }
  972. nscrap = n_scrap;
  973. scrap = (char_t*) malloc(nscrap);
  974. (void) memcpy(scrap, current_scrap, nscrap * sizeof (char_t));
  975. curbp->b_mark = mark;
  976. }
  977. void lowercaseword()
  978. {
  979. char_t *p, *word;
  980. char_t c[2];
  981. point_t sword, eword;
  982. int olast = lastcommand;
  983. while ((isspace(*(p = ptr(curbp, curbp->b_point))) || is_symbol(*p)) && p < curbp->b_ebuf)
  984. ++curbp->b_point;
  985. sword = curbp->b_point;
  986. wright();
  987. eword = curbp->b_point;
  988. word = (char_t *) malloc(sizeof(char_t)*(eword - sword));
  989. curbp->b_point = sword;
  990. lastcommand = KBD_DELETE_CHAR;
  991. for(int i = sword, k = 0; i < eword; i++, k++) {
  992. word[k] = *ptr(curbp, curbp->b_point);
  993. delete();
  994. }
  995. lastcommand = olast;
  996. for(int i = sword, k = 0; i < eword; i++, k++) {
  997. c[0] = tolower(word[k]);
  998. c[1] = '\0';
  999. input = c;
  1000. undoset(INSERT, i != 0);
  1001. insert();
  1002. }
  1003. free(word);
  1004. }
  1005. void capitalizeword()
  1006. {
  1007. char_t *p;
  1008. while (isspace(*(p = ptr(curbp, curbp->b_point))) && p < curbp->b_ebuf)
  1009. ++curbp->b_point;
  1010. p = ptr(curbp, curbp->b_point);
  1011. char_t c[1];
  1012. c[0] = toupper(*p);
  1013. input = c;
  1014. delete();
  1015. undoset(INSERT, FALSE);
  1016. insert();
  1017. if(isspace(*(p = ptr(curbp, curbp->b_point+1))) || is_symbol(*p))
  1018. curbp->b_point++;
  1019. else
  1020. wright();
  1021. }
  1022. void uppercaseword()
  1023. {
  1024. char_t *p, *word;
  1025. char_t c[2];
  1026. point_t sword, eword;
  1027. int olast = lastcommand;
  1028. while ((isspace(*(p = ptr(curbp, curbp->b_point))) || is_symbol(*p)) && p < curbp->b_ebuf)
  1029. ++curbp->b_point;
  1030. sword = curbp->b_point;
  1031. wright();
  1032. eword = curbp->b_point;
  1033. word = (char_t *) malloc(sizeof(char_t)*(eword - sword));
  1034. curbp->b_point = sword;
  1035. lastcommand = KBD_DELETE_CHAR;
  1036. for(int i = sword, k = 0; i < eword; i++, k++) {
  1037. word[k] = *ptr(curbp, curbp->b_point);
  1038. delete();
  1039. }
  1040. lastcommand = olast;
  1041. for(int i = sword, k = 0; i < eword; i++, k++) {
  1042. c[0] = toupper(word[k]);
  1043. c[1] = '\0';
  1044. input = c;
  1045. undoset(INSERT, i != 0);
  1046. insert();
  1047. }
  1048. free(word);
  1049. }
  1050. /* type = 0, zap
  1051. type = 1, jump
  1052. */
  1053. /* TODO: Throw error when putting non-char in.
  1054. */
  1055. void gotochar(int type)
  1056. {
  1057. char_t *p;
  1058. point_t opoint = curbp->b_point, eol;
  1059. int c, col = 0;
  1060. struct tb_event ev;
  1061. char *prompt = type == 0 ? "Zap to Char: " : "Jump to Char: ";
  1062. if(character[0] == '\0') {
  1063. display_prompt_and_response(prompt, character);
  1064. tb_present();
  1065. if(tb_poll_event(&ev) != TB_OK) return;
  1066. if(!ev.mod)
  1067. c = ev.ch;
  1068. else
  1069. c = ev.key;
  1070. /* Ignore all control keys other than C-g and ESC*/
  1071. if (c < 32 && c != TB_KEY_CTRL_G && c != TB_KEY_ESC)
  1072. return;
  1073. if(c == TB_KEY_CTRL_G || c == TB_KEY_ESC)
  1074. return;
  1075. else
  1076. character[0] = c;
  1077. display_prompt_and_response(prompt, character);
  1078. tb_present();
  1079. }
  1080. if(type == 0) {
  1081. block();
  1082. }
  1083. if(*ptr(curbp, curbp->b_point) == character[0] || curbp->b_point == 0) {
  1084. if(negated)
  1085. left();
  1086. else
  1087. right();
  1088. }
  1089. while (*(p = ptr(curbp, curbp->b_point)) != character[0] && p < curbp->b_ebuf && curbp->b_point > 0) {
  1090. if(negated)
  1091. left();
  1092. else
  1093. right();
  1094. }
  1095. if(type == 0 && !negated)
  1096. right();
  1097. if(type == 0)
  1098. copy_cut(TRUE, FALSE, FALSE);
  1099. tb_set_cursor(0, MSGLINE);
  1100. clrtoeol("", MSGLINE);
  1101. eol = lnstart(curbp, curbp->b_point);
  1102. for(point_t poi = curbp->b_point; poi > eol; poi -= utf8_size(*ptr(curbp,poi)))
  1103. col++;
  1104. curbp->b_pcol = col + curwp->w_left;
  1105. if(p >= ptr(curbp, curbp->b_epage)) {
  1106. curbp->b_reframe = TRUE;
  1107. }
  1108. if((!negated && p >= curbp->b_ebuf) || (negated && curbp->b_point <= 0)) {
  1109. msg("No match found.");
  1110. curbp->b_point = opoint;
  1111. }
  1112. negated = FALSE;
  1113. }
  1114. void zaptochar()
  1115. {
  1116. gotochar(0);
  1117. }
  1118. void negated_zaptochar()
  1119. {
  1120. negated = TRUE;
  1121. gotochar(0);
  1122. }
  1123. void jumptochar()
  1124. {
  1125. gotochar(1);
  1126. }
  1127. void negated_jumptochar()
  1128. {
  1129. negated = TRUE;
  1130. gotochar(1);
  1131. }
  1132. void poptomark()
  1133. {
  1134. if(curbp->b_mark > -1)
  1135. curbp->b_point = curbp->b_mark;
  1136. else
  1137. curbp->b_point = curbp->b_pmark;
  1138. curbp->b_reframe = TRUE;
  1139. }
  1140. void universal_argument_load()
  1141. {
  1142. universal_argument++;
  1143. msg("C-u %d", universal_argument);
  1144. }
  1145. void numeric_argument_load()
  1146. {
  1147. numeric_argument = (numeric_argument * 10) + atoi((const char *)&input_char);
  1148. msg("C-u %d", numeric_argument);
  1149. }
  1150. void back_to_indentation()
  1151. {
  1152. char_t *p;
  1153. while (isspace(*(p = ptr(curbp, curbp->b_point))) && p < curbp->b_ebuf)
  1154. ++curbp->b_point;
  1155. }
  1156. void negate()
  1157. {
  1158. negated = !negated;
  1159. msg("C-u -");
  1160. }
  1161. void forward_bracket()
  1162. {
  1163. point_t p, eol;
  1164. int col = 0;
  1165. if((p = find_matching_bracket(curbp, curwp, 1, FALSE)) >= 0)
  1166. curbp->b_point = curbp->b_mark == NOMARK ? p : p + 1;
  1167. /* Make sure the column memory updates to the new column */
  1168. eol = lnstart(curbp, curbp->b_point);
  1169. for(p = curbp->b_point; p > eol; p -= utf8_size(*ptr(curbp,p)))
  1170. col++;
  1171. curbp->b_pcol = col + curwp->w_left;
  1172. }
  1173. void backward_bracket()
  1174. {
  1175. point_t p, eol;
  1176. int col = 0;
  1177. if((p = find_matching_bracket(curbp, curwp, -1, FALSE)) >= 0) {
  1178. curbp->b_point = p;
  1179. if(curbp->b_mark != NOMARK)
  1180. curbp->b_mark++;
  1181. }
  1182. /* Make sure the column memory updates to the new column */
  1183. eol = lnstart(curbp, curbp->b_point);
  1184. for(p = curbp->b_point; p > eol; p -= utf8_size(*ptr(curbp,p)))
  1185. col++;
  1186. curbp->b_pcol = col + curwp->w_left;
  1187. }
  1188. void start_kbd_macro()
  1189. {
  1190. record_input = TRUE;
  1191. for(int i = 0; i < record_buffer_index; i++) {
  1192. memset(&record_buffer[i], 0, sizeof(record_buffer[i]));
  1193. }
  1194. record_buffer_index = 0;
  1195. msg("Started keyboard macro...");
  1196. }
  1197. void end_kbd_macro()
  1198. {
  1199. record_input = FALSE;
  1200. msg("Ended keyboard macro.");
  1201. }
  1202. void run_kbd_macro()
  1203. {
  1204. if(numeric_argument > 0)
  1205. numeric_argument--;
  1206. execute_kbd_macro = TRUE;
  1207. }
  1208. void open_file_from_shell()
  1209. {
  1210. get_popen_data(1);
  1211. }
  1212. void insert_from_shell()
  1213. {
  1214. get_popen_data(0);
  1215. }
  1216. void insert_control_char()
  1217. {
  1218. struct tb_event ev;
  1219. char *prompt = "Insert Control Char: ";
  1220. display_prompt_and_response(prompt, character);
  1221. tb_present();
  1222. if(tb_poll_event(&ev) != TB_OK) return;
  1223. tb_set_cursor(0, MSGLINE);
  1224. clrtoeol("", MSGLINE);
  1225. if(ev.key > 0x1a) {
  1226. return;
  1227. }
  1228. input[0] = (char)ev.key;
  1229. input[1] = '\0';
  1230. undoset(1, lastcommand == KBD_INSERT);
  1231. insert();
  1232. currentcommand = KBD_INSERT;
  1233. ignorenotbound = TRUE;
  1234. }