Add xterm-256color as a valid terminal.
[eco.git] / main.c
blob55ee04b6fd0c063004149df134a12f8ed6fff10c
1 /*
2 * Copyright (C) 2008 Diego Hernan Borghetti.
3 * Eco
4 */
6 #include <sys/ioctl.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <signal.h>
12 #include "debug.h"
13 #include "list.h"
14 #include "time.h"
15 #include "term.h"
16 #include "screen.h"
17 #include "buffer.h"
18 #include "view.h"
19 #include "eco.h"
20 #include "file.h"
21 #include "status.h"
22 #include "update.h"
23 #include "key.h"
24 #include "func.h"
25 #include "cmd.h"
26 #include "config.h"
27 #include "kill.h"
28 #include "syntax.h"
31 /* Function declaration. */
32 static int e_cmode_check(char *ext);
33 static void e_cmode_init(void);
34 static int e_check_unsave(E_Eco *ec);
36 static void e_signal(int num);
37 static void e_signal_size(int num);
38 static void e_quit(E_Eco *ec);
39 static void e_keymap_init(void);
41 /* only global in this file!! */
42 static E_Eco *E= NULL;
45 int main(int argc, char **argv)
47 E_Buffer *bf;
48 E_View *v;
49 int i, st;
51 E= (E_Eco *)malloc(sizeof(E_Eco));
52 if (!E) {
53 perror("malloc");
54 exit(-1);
57 e_debug_init();
58 e_config_init();
60 E->tr= e_term_open();
61 E->sc= e_screen_init(E->tr);
63 /* handler signal. */
64 signal(SIGTERM, e_signal);
65 signal(SIGQUIT, e_signal);
66 signal(SIGWINCH, e_signal_size);
68 /* view list. */
69 E->view_list= NULL;
71 /* buffers list. */
72 E->buffers= NULL;
74 argc--;
75 argv++;
77 for (i= 0; i < argc; i++) {
78 /* parse options here!! */
79 bf= e_file_read(argv[i], &st);
80 if ((!bf) && (!st))
81 bf= e_buffer_new(argv[i]);
83 if (bf) {
84 v= e_view_new(E->sc);
85 v->b= bf;
86 e_main_view_add(E, v);
87 e_main_add(E, bf);
91 if (!E->buffers) {
92 /* default buffer. */
93 bf= e_buffer_new("main");
94 v= e_view_new(E->sc);
95 v->b= bf;
96 e_main_view_add(E, v);
97 e_main_add(E, bf);
100 /* and add to the view. */
101 E->view= E->view_list;
102 e_view_show(E->view);
103 e_view_redraw(E->view);
105 /* name to functions binding. */
106 e_func_add("e_quit", e_quit);
107 e_func_add("e_cmd_write", e_cmd_write);
108 e_func_add("e_cmd_killline", e_cmd_killline);
109 e_func_add("e_cmd_rotate", e_cmd_rotate);
110 e_func_add("e_cmd_goto", e_cmd_goto);
111 e_func_add("e_cmd_cr", e_cmd_cr);
112 e_func_add("e_cmd_ht", e_cmd_ht);
113 e_func_add("e_cmd_backspace", e_cmd_backspace);
114 e_func_add("e_cmd_find_file", e_cmd_find_file);
115 e_func_add("e_cmd_cutline", e_cmd_cutline);
116 e_func_add("e_cmd_paste", e_cmd_paste);
117 e_func_add("e_cmd_cleankill", e_cmd_cleankill);
119 /* load user keymap. */
120 e_keymap_init();
122 /* init the kill buffer. */
123 e_kill_init();
125 /* default colors. */
126 E->fg= E_TR_WHITE;
127 E->bg= E_TR_BLACK;
129 /* clean term and screen. */
130 e_term_move(0, 0);
131 e_term_eeop(E->tr);
133 e_screen_move(E->sc, 0, 0);
134 e_screen_eeop(E->sc);
135 e_update(E);
136 e_status_draw(E);
137 e_screen_swap(E->tr, E->sc, 1);
139 /* register the cmode in the system. */
140 e_cmode_init();
142 /* and start the loop. */
143 E->loop= 1;
144 E->last_ch= 0;
146 while (E->loop) {
147 int c;
149 /* Get the next character. */
150 c= e_term_getc();
153 * Clear the status message, before
154 * call any other functions.
156 E->view->stmsg= 0;
159 * Depend on the character we have three possibilities here:
160 * 1) An escape secuence or command.
161 * 2) Combination of command (for example. CTRL X + C)
162 * 3) Normal text input for the buffer.
164 * First case:
166 if (c == E_TR_ESC) {
167 int c, redraw;
169 c= e_term_getc();
170 redraw= 0;
172 if (c == '[') {
173 c= e_term_getc();
174 if (c == 'D') {
175 e_buffer_left(E->view->b);
176 redraw= 1;
178 else if (c == 'C') {
179 e_buffer_right(E->view->b);
180 redraw= 1;
182 else if (c == 'A') {
183 e_buffer_up(E->view->b);
184 redraw= 1;
186 else if (c == 'B') {
187 e_buffer_down(E->view->b);
188 redraw= 1;
190 else if (c == 'H') {
191 e_buffer_bol(E->view->b);
192 redraw= 1;
194 else if (c == 'F') {
195 e_buffer_eol(E->view->b);
196 redraw= 1;
198 else if (c == '1') {
199 c= e_term_getc();
200 if (c == '~') {
201 e_buffer_bol(E->view->b);
202 redraw= 1;
204 else if (c == '7') {
205 c= e_term_getc();
206 if (c == '7') {
207 if (E->view->b->dot == E->view->b->line->used) {
208 e_buffer_down(E->view->b);
209 e_buffer_joinline(E->view->b);
211 else
212 e_buffer_del(E->view->b);
213 redraw= 1;
217 else if (c == '3') {
218 c= e_term_getc();
219 if (c == '~') {
220 if (E->view->b->dot == E->view->b->line->used) {
221 e_buffer_down(E->view->b);
222 e_buffer_joinline(E->view->b);
224 else
225 e_buffer_del(E->view->b);
226 redraw= 1;
229 else if (c == '4') {
230 c= e_term_getc();
231 if (c == '~') {
232 e_buffer_eol(E->view->b);
233 redraw= 1;
236 else if (c == '5') {
237 c= e_term_getc();
238 if (c == '~') {
239 e_buffer_scroll(E->view->b, E->sc->nrow - 3, 1);
240 redraw= 1;
243 else if (c == '6') {
244 c= e_term_getc();
245 if (c == '~') {
246 e_buffer_scroll(E->view->b, E->sc->nrow - 3, 0);
247 redraw= 1;
250 else if (c == '[') {
251 c= e_term_getc();
252 if (c == '3') {
253 c= e_term_getc();
254 if (c == '~') {
255 if (E->view->b->dot == E->view->b->line->used) {
256 e_buffer_down(E->view->b);
257 e_buffer_joinline(E->view->b);
259 else
260 e_buffer_del(E->view->b);
261 redraw= 1;
266 else if (c == 'O') {
267 c= e_term_getc();
268 if (c == 'F') {
269 e_buffer_eol(E->view->b);
270 redraw= 1;
272 else if (c == 'H') {
273 e_buffer_bol(E->view->b);
274 redraw= 1;
278 if (redraw)
279 e_view_redraw(E->view);
281 /* Second case here. */
282 else if (c > 0x00 && c < 0x20) {
283 short ctrl_x;
284 char exec_cmd;
286 c= c + '@';
287 ctrl_x= 0;
288 exec_cmd= 1;
290 if (c == 'X') {
291 c= e_term_getc();
292 ctrl_x= 1;
294 if (c > 0x00 && c < 0x20)
295 c= c + '@';
297 /* yes, ctrl+G always cancel the command. */
298 if (c == 'G')
299 exec_cmd= 0;
301 if (exec_cmd)
302 e_key_exec(E, c, ctrl_x);
304 /* And normal input text for the buffer. */
305 else if (c > 0x1f && c <= 0x7f) {
306 if (c == 0x7f)
307 e_buffer_backspace(E->view->b);
308 else
309 e_buffer_insert(E->view->b, c, 1);
310 e_view_redraw(E->view);
312 /* update the last character. */
313 E->last_ch= c;
316 e_update(E);
317 e_status_draw(E);
318 e_screen_swap(E->tr, E->sc, 0);
319 e_term_flush();
321 e_sleep_ms(5);
324 while (E->buffers) {
326 * Don't need check for changes, the e_quit
327 * function already handler it.
329 bf= E->buffers->next;
330 e_buffer_free(E->buffers);
331 E->buffers= bf;
334 e_kill_end();
335 e_key_free();
337 while (E->view_list) {
338 v= E->view_list->next;
339 e_view_free(E->view_list);
340 E->view_list= v;
343 e_screen_free(E->sc);
344 e_term_close(E->tr);
345 free((void *)E);
346 e_debug_end();
348 return(0);
351 static int e_check_unsave(E_Eco *ec)
353 E_Buffer *p;
354 char *s, *buf;
356 buf= (char *)malloc(512);
357 p= ec->buffers;
358 while (p) {
359 if (!strcmp(p->paths->file, "main")) {
360 p= p->next;
361 continue;
364 if (p->flag & BUFFER_FLUSH) {
365 sprintf(buf, "Modified buffer (%s), save (y/n/c)? ", p->paths->file);
366 while (!(s= e_status_get_msg(ec, buf)))
369 if (s[0] == 'y')
370 e_file_write(ec, p);
371 else if (s[0] == 'c') {
372 free((void *)buf);
373 return(1);
376 p= p->next;
378 free((void *)buf);
379 return(0);
382 static void e_signal(int num)
384 E->loop= 0;
387 static void e_signal_size(int num)
389 struct winsize ws;
390 E_View *v;
392 if (ioctl(0, TIOCGWINSZ, &ws))
393 return;
395 if (ws.ws_row-1 == E->tr->nrow && ws.ws_col == E->tr->ncol)
396 return;
398 E->tr->nrow= ws.ws_row-1;
399 E->tr->ncol= ws.ws_col;
401 /* yes... fix this. */
402 e_screen_free(E->sc);
403 E->sc= e_screen_init(E->tr);
405 /* ok, we need resize all the view. */
406 v= E->view_list;
407 while (v) {
408 e_view_resize(v, E->sc->nrow, E->sc->ncol);
409 v= v->next;
412 /* clearn term and screen. */
413 e_term_move(0, 0);
414 e_term_eeop(E->tr);
416 e_screen_move(E->sc, 0, 0);
417 e_screen_eeop(E->sc);
418 e_update(E);
419 e_status_draw(E);
420 e_screen_swap(E->tr, E->sc, 1);
421 e_term_flush();
422 signal(SIGWINCH, e_signal_size);
425 static void e_quit(E_Eco *ec)
427 if (e_check_unsave(ec))
428 return;
429 E->loop= 0;
432 static void e_keymap_init(void)
434 e_key_add('C', 1, e_quit);
435 e_key_add('S', 1, e_cmd_write);
436 e_key_add('K', 0, e_cmd_killline);
437 e_key_add('R', 0, e_cmd_rotate);
438 e_key_add('G', 0, e_cmd_goto);
439 e_key_add('F', 1, e_cmd_find_file);
440 e_key_add('U', 0, e_cmd_update);
441 e_key_add('S', 0, e_cmd_search_forward);
442 e_key_add('B', 0, e_cmd_search_backward);
443 e_key_add('R', 1, e_cmd_replace);
445 e_key_add('M', 0, e_cmd_cr);
446 e_key_add('I', 0, e_cmd_ht);
447 e_key_add('H', 0, e_cmd_backspace);
448 e_key_add('C', 0, e_cmd_cutline);
449 e_key_add('Y', 0, e_cmd_paste);
450 e_key_add('L', 0, e_cmd_cleankill);
451 e_key_add('V', 0, e_cmd_copyline);
454 void e_main_rotate(E_Eco *ec)
456 e_view_unshow(ec->view);
457 if (ec->view->next)
458 ec->view= ec->view->next;
459 else
460 ec->view= ec->view_list;
462 e_view_show(ec->view);
463 e_view_redraw(ec->view);
466 E_Buffer *e_main_find(E_Eco *ec, char *name)
468 E_File_Path *paths;
469 E_Buffer *p;
471 /* get the absolute path */
472 paths= e_file_get_paths(name);
473 if (!paths)
474 return(NULL);
476 if (!paths->path) {
477 free((void *)paths);
478 return(NULL);
481 if (!paths->file) {
482 free((void *)paths->path);
483 free((void *)paths);
484 return(NULL);
487 p= ec->buffers;
488 while (p) {
489 if (!strcmp(p->paths->file, paths->file)) {
490 free((void *)paths->path);
491 free((void *)paths->file);
492 free((void *)paths);
493 return(p);
495 p= p->next;
497 free((void *)paths->path);
498 free((void *)paths->file);
499 free((void *)paths);
500 return(NULL);
503 void e_main_add(E_Eco *ec, E_Buffer *bf)
505 bf->next= ec->buffers;
506 ec->buffers= bf;
509 void e_main_remove(E_Eco *ec, E_Buffer *bf)
511 E_Buffer *p, *p1;
513 p= ec->buffers;
514 p1= NULL;
515 while (p) {
516 if (p == bf) {
517 if (p1)
518 p1->next= p->next;
519 else
520 ec->buffers= p->next;
522 bf->next= NULL;
523 return;
525 p1= p;
526 p= p->next;
530 void e_main_view_add(E_Eco *ec, E_View *v)
532 v->next= ec->view_list;
533 v->prev= NULL;
534 if (ec->view_list)
535 ec->view_list->prev= v;
536 ec->view_list= v;
539 void e_main_view_rem(E_Eco *ec, E_View *v)
541 if (v->prev)
542 v->prev->next= v->next;
543 if (v->next)
544 v->next->prev= v->prev;
546 if (v == ec->view_list) {
547 if (v->next)
548 ec->view_list= v->next;
549 else
550 ec->view_list= v->prev;
554 E_View *e_main_view_find(E_Eco *ec, E_Buffer *b)
556 E_View *v;
558 v= ec->view_list;
559 while (v) {
560 if (v->b == b)
561 return(v);
562 v= v->next;
564 return(NULL);
567 /* make a C dictionary! */
568 static int e_cmode_check(char *ext)
570 if (!strcmp(ext, ".c"))
571 return(0);
572 else if (!strcmp(ext, ".C"))
573 return(0);
574 return(1);
577 static void e_cmode_init(void)
579 E_Syntax *sy;
581 sy= e_syntax_new();
582 sy->name= strdup("C Mode");
583 sy->check_type= e_cmode_check;
584 sy->dirs.first= NULL;
585 sy->dirs.last= NULL;
587 e_syntax_word_add(sy, "void", E_TR_RED, E_TR_BLACK);
588 e_syntax_word_add(sy, "int", E_TR_RED, E_TR_BLACK);
589 e_syntax_word_add(sy, "char", E_TR_RED, E_TR_BLACK);
590 e_syntax_word_add(sy, "float", E_TR_RED, E_TR_BLACK);
591 e_syntax_word_add(sy, "double", E_TR_RED, E_TR_BLACK);
592 e_syntax_word_add(sy, "long", E_TR_RED, E_TR_BLACK);
593 e_syntax_word_add(sy, "struct", E_TR_RED, E_TR_BLACK);
594 e_syntax_word_add(sy, "typedef", E_TR_RED, E_TR_BLACK);
595 e_syntax_word_add(sy, "static", E_TR_RED, E_TR_BLACK);
596 e_syntax_word_add(sy, "inline", E_TR_RED, E_TR_BLACK);
598 e_syntax_word_add(sy, "if", E_TR_CYAN, E_TR_BLACK);
599 e_syntax_word_add(sy, "else", E_TR_CYAN, E_TR_BLACK);
600 e_syntax_word_add(sy, "while", E_TR_CYAN, E_TR_BLACK);
601 e_syntax_word_add(sy, "for", E_TR_CYAN, E_TR_BLACK);
602 e_syntax_word_add(sy, "do", E_TR_CYAN, E_TR_BLACK);
603 e_syntax_word_add(sy, "return", E_TR_BLUE, E_TR_BLACK);
604 e_syntax_word_add(sy, "ifndef", E_TR_CYAN, E_TR_BLACK);
605 e_syntax_word_add(sy, "define", E_TR_CYAN, E_TR_BLACK);
606 e_syntax_word_add(sy, "endif", E_TR_CYAN, E_TR_BLACK);
607 e_syntax_word_add(sy, "include", E_TR_GREEN, E_TR_BLACK);
608 e_syntax_word_add(sy, "malloc", E_TR_RED, E_TR_BLACK);
609 e_syntax_word_add(sy, "free", E_TR_RED, E_TR_BLACK);
610 e_syntax_word_add(sy, "realloc", E_TR_RED, E_TR_BLACK);
611 e_syntax_word_add(sy, "++", E_TR_CYAN, E_TR_BLACK);
612 e_syntax_word_add(sy, "--", E_TR_CYAN, E_TR_BLACK);
614 e_syntax_char_add(sy, '{', E_TR_YELLOW, E_TR_BLACK);
615 e_syntax_char_add(sy, '}', E_TR_YELLOW, E_TR_BLACK);
617 e_syntax_char_add(sy, '(', E_TR_YELLOW, E_TR_BLACK);
618 e_syntax_char_add(sy, ')', E_TR_YELLOW, E_TR_BLACK);
619 e_syntax_char_add(sy, '[', E_TR_YELLOW, E_TR_BLACK);
620 e_syntax_char_add(sy, ']', E_TR_YELLOW, E_TR_BLACK);
622 e_syntax_char_add(sy, '=', E_TR_GREEN, E_TR_BLACK);
623 e_syntax_char_add(sy, ',', E_TR_GREEN, E_TR_BLACK);
624 e_syntax_char_add(sy, '.', E_TR_GREEN, E_TR_BLACK);
625 e_syntax_char_add(sy, ';', E_TR_GREEN, E_TR_BLACK);
626 e_syntax_char_add(sy, '*', E_TR_YELLOW, E_TR_BLACK);
627 e_syntax_char_add(sy, '/', E_TR_YELLOW, E_TR_BLACK);
628 e_syntax_char_add(sy, '"', E_TR_GREEN, E_TR_BLACK);
629 e_syntax_char_add(sy, '+', E_TR_CYAN, E_TR_BLACK);
630 e_syntax_char_add(sy, '-', E_TR_CYAN, E_TR_BLACK);
631 e_syntax_char_add(sy, '>', E_TR_CYAN, E_TR_BLACK);
632 e_syntax_char_add(sy, '<', E_TR_CYAN, E_TR_BLACK);
634 e_syntax_add(sy);