main.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. /* main.c, Ait, BSD 3-Clause, Kevin Bloom, 2023,
  2. Derived from: Atto January 2017
  3. Derived from: Anthony's Editor January 93
  4. */
  5. #include "header.h"
  6. #include "termbox.h"
  7. #include "util.h"
  8. int done;
  9. point_t nscrap;
  10. char_t *scrap;
  11. char_t *input;
  12. int msgflag;
  13. char msgline[TEMPBUF];
  14. char temp[TEMPBUF];
  15. char searchtext[STRBUF_M];
  16. char replace[STRBUF_M];
  17. int found_point = -1;
  18. int search_dir = 1;
  19. int universal_argument = 0;
  20. int numeric_argument = 0;
  21. int negated = FALSE;
  22. int submatch = 0;
  23. uint32_t input_char = 0;
  24. int undoset_flag = FALSE;
  25. char editor_dir[NAME_MAX+1];
  26. int record_input = FALSE;
  27. int record_buffer_index = 0;
  28. int run_buffer_index = 0;
  29. struct tb_event record_buffer[256];
  30. int execute_kbd_macro = FALSE;
  31. int undo_index = -1;
  32. char unicode_buf[7];
  33. char character[1];
  34. int lastcommand = KBD_DEFAULT;
  35. int window_mode = WINDOW_DEFAULT;
  36. keymap_t *key_return;
  37. keymap_t *key_map;
  38. buffer_t *curbp; /* current buffer */
  39. buffer_t *bheadp; /* head of list of buffers */
  40. window_t *curwp;
  41. window_t *wheadp;
  42. buffer_t *lastbp = NULL; /* last active buffer */
  43. int LINES;
  44. int COLS;
  45. int MSGLINE;
  46. static void graceful_exit()
  47. {
  48. tb_shutdown();
  49. exit(1);
  50. }
  51. static void cont()
  52. {
  53. tb_init();
  54. LINES = tb_height();
  55. COLS = tb_width();
  56. MSGLINE = LINES-1;
  57. tb_set_input_mode(TB_INPUT_ALT | TB_INPUT_MOUSE);
  58. tb_clear();
  59. update_display();
  60. }
  61. static void setup_signal_handlers()
  62. {
  63. struct sigaction action;
  64. memset(&action, 0, sizeof(struct sigaction));
  65. action.sa_handler = graceful_exit;
  66. sigaction(SIGTERM, &action, NULL);
  67. sigaction(SIGINT, &action, NULL);
  68. sigaction(SIGQUIT, &action, NULL);
  69. sigaction(SIGHUP, &action, NULL);
  70. action.sa_handler = cont;
  71. sigaction(SIGCONT, &action, NULL);
  72. signal(SIGPIPE, SIG_IGN);
  73. }
  74. int main(int argc, char **argv)
  75. {
  76. int ret, u, buffers = 0;
  77. int line = 0, current = 0, lastln = 0;
  78. point_t p;
  79. if(1 < argc && argv[1][0] == '-') {
  80. if(argv[1][1] == 'v') {
  81. fprintf(stderr, "%s\n", VERSION);
  82. exit(0);
  83. }
  84. if(argv[1][1] == 'h') {
  85. fprintf(stderr, "%s\n\nUsage: ait [options] [file]... +/-line...\n\n\n-h Print help and exit\n-v Print version and exit\n", VERSION);
  86. exit(0);
  87. }
  88. }
  89. ret = tb_init();
  90. LINES = tb_height();
  91. COLS = tb_width();
  92. MSGLINE = LINES-1;
  93. character[0] = '\0';
  94. if (ret) {
  95. fprintf(stderr, "Failed with error code %d", ret);
  96. exit(1);
  97. }
  98. getcwd(editor_dir, sizeof(editor_dir));
  99. strcat(editor_dir, "/");
  100. tb_set_input_mode(TB_INPUT_ALT | TB_INPUT_MOUSE);
  101. tb_clear();
  102. setup_signal_handlers();
  103. if (1 < argc) {
  104. for(int v = 1; v < argc; v++) {
  105. buffers++;
  106. curbp = find_buffer(argv[v], TRUE);
  107. (void) insert_file(argv[v], FALSE);
  108. /* Save filename regardless of load() success. */
  109. if(argv[v][0] == '/') {
  110. strncpy(curbp->b_fname, argv[v], NAME_MAX);
  111. } else {
  112. strncpy(curbp->b_fname, editor_dir, NAME_MAX);
  113. strcat(curbp->b_fname, argv[v]);
  114. cleanup_path(curbp->b_fname, curbp->b_fname);
  115. }
  116. curbp->b_fname[NAME_MAX] = '\0'; /* force truncation */
  117. curbp->b_path = TRUE;
  118. curbp->b_line = 1;
  119. if(argv[v+1]) {
  120. if(argv[v+1][0] == '-' || argv[v+1][0] == '+') {
  121. if(argv[v+1][0] == '+') {
  122. argv[v+1]++;
  123. line = atoi(argv[v+1]);
  124. } else {
  125. argv[v+1]++;
  126. get_line_stats(&current, &lastln, curbp);
  127. line = lastln - atoi(argv[v+1]);
  128. if(line < 0)
  129. line = 0;
  130. }
  131. p = line_to_point(line);
  132. if (p != -1) {
  133. curbp->b_point = p;
  134. if (curbp->b_epage < pos(curbp, curbp->b_ebuf)) curbp->b_reframe = 1;
  135. curbp->b_line = line;
  136. msg("Line %d", line);
  137. } else {
  138. msg("Line %d, not found", line);
  139. }
  140. v++;
  141. }
  142. }
  143. }
  144. } else {
  145. curbp = find_buffer("*scratch*", TRUE);
  146. strncpy(curbp->b_bname, "*scratch*", STRBUF_S);
  147. curbp->b_path = FALSE;
  148. }
  149. wheadp = curwp = new_window();
  150. one_window(curwp);
  151. associate_b2w(curbp, curwp);
  152. if(buffers > 1) {
  153. chop_window();
  154. next_buffer();
  155. }
  156. if (!growgap(curbp, CHUNK))
  157. fatal("%s: Failed to allocate required memory.\n");
  158. movegap(curbp, 0);
  159. key_map = keymap;
  160. submatch = 0;
  161. while (!done) {
  162. update_display();
  163. curbp->b_opoint = curbp->b_point;
  164. input = get_key(key_map, &key_return);
  165. if (key_return != NULL) {
  166. /* TODO: a better way to figure out editing commands */
  167. if((key_return->key_desc[2] == 'd' || key_return->key_desc[4] == '%' ||
  168. key_return->key_desc[2] == 'i' || key_return->key_desc[2] == 'k' ||
  169. key_return->key_desc[2] == '/' || key_return->key_desc[2] == 'm' ||
  170. key_return->key_desc[2] == 't' || key_return->key_desc[2] == 'y' ||
  171. key_return->key_desc[4] == 'd' || key_return->key_desc[4] == 'i' ||
  172. key_return->key_desc[4] == 't' || key_return->key_desc[4] == 'x' ||
  173. key_return->key_desc[4] == 'k' || key_return->key_desc[4] == '/' ||
  174. key_return->key_desc[4] == 'l' || key_return->key_desc[4] == 'c' ||
  175. key_return->key_desc[4] == 'u' || key_return->key_desc[4] == 'z' ||
  176. key_return->key_desc[4] == 'Z' || (key_return->key_desc[4] == 'b'
  177. && key_return->key_desc[5] == 'k') || key_return->key_desc[2] == 'h') &&
  178. is_file_modified(curbp->b_fname)) {
  179. if(!file_was_modified_prompt()) {
  180. continue;
  181. }
  182. }
  183. submatch = 0;
  184. if(execute_kbd_macro) {
  185. (key_return->func)();
  186. } else {
  187. u = numeric_argument > 0 ? numeric_argument : power(4, universal_argument);
  188. if(numeric_argument > 0 &&
  189. key_return->universal_argument_action != UA_PREVENT)
  190. key_return->universal_argument_action = UA_REPEAT;
  191. switch(key_return->universal_argument_action) {
  192. case UA_REPEAT:
  193. for(; u > 0; u--)
  194. (key_return->func)();
  195. universal_argument = 0;
  196. numeric_argument = 0;
  197. /* For gotochar */
  198. character[0] = '\0';
  199. break;
  200. default:
  201. (key_return->func)();
  202. break;
  203. }
  204. }
  205. if(temp[0] != 0)
  206. memset(temp, 0, TEMPBUF);
  207. } else if(submatch > 0) {
  208. // do nothing
  209. } else {
  210. submatch = 0;
  211. if((unicode_buf[0] != '\0' || *input > 31 || *input == 13 || *input == 9)
  212. && is_file_modified(curbp->b_fname)) {
  213. if(!file_was_modified_prompt()) {
  214. continue;
  215. }
  216. }
  217. /* allow TAB and NEWLINE, otherwise any Control Char is 'Not bound' */
  218. if(unicode_buf[0] != '\0')
  219. insert_unicode();
  220. else if (*input > 31 || *input == 13 || *input == 9)
  221. insert();
  222. else
  223. msg("Not bound");
  224. }
  225. if(lastcommand != KBD_DELETE_CHAR && lastcommand != KBD_CUT) {
  226. if(curbp->b_opoint > curbp->b_point) {
  227. curbp->b_opoint--;
  228. while(curbp->b_opoint >= curbp->b_point) {
  229. if(*ptr(curbp, curbp->b_opoint) == '\n')
  230. curbp->b_line--;
  231. curbp->b_opoint--;
  232. }
  233. } else if(curbp->b_opoint < curbp->b_point) {
  234. while(curbp->b_opoint < curbp->b_point) {
  235. if(*ptr(curbp, curbp->b_opoint) == '\n')
  236. curbp->b_line++;
  237. curbp->b_opoint++;
  238. }
  239. }
  240. } else {
  241. // TODO: fix this commit number: 6dcf8f3c
  242. lastcommand = KBD_DEFAULT;
  243. }
  244. }
  245. if (scrap != NULL) free(scrap);
  246. tb_set_cursor(0, LINES-1);
  247. tb_present();
  248. tb_shutdown();
  249. return 0;
  250. }
  251. void fatal(char *msg)
  252. {
  253. tb_present();
  254. fprintf(stderr, msg, PROG_NAME);
  255. exit(1);
  256. }
  257. void msg(char *msg, ...)
  258. {
  259. va_list args;
  260. va_start(args, msg);
  261. (void)vsprintf(msgline, msg, args);
  262. va_end(args);
  263. msgflag = TRUE;
  264. }