summaryrefslogtreecommitdiff
path: root/screen.c
diff options
context:
space:
mode:
authorKatolaZ <katolaz@freaknet.org>2019-07-27 06:57:29 +0100
committerKatolaZ <katolaz@freaknet.org>2019-07-27 06:57:29 +0100
commitf678684b470f02d9fed4818eb92c2a925380c428 (patch)
treefc26ae9768e6c72827b03e973dbf0479b0a0431d /screen.c
parent8b67bd6c5f4e175721b44d4733d1a5a6fc1a2561 (diff)
parent8e3d23b921d9bbcb7c53017bacff8a3050a34b55 (diff)
Merge branch 'devel' into master
Diffstat (limited to 'screen.c')
-rw-r--r--screen.c419
1 files changed, 419 insertions, 0 deletions
diff --git a/screen.c b/screen.c
new file mode 100644
index 0000000..2e61acf
--- /dev/null
+++ b/screen.c
@@ -0,0 +1,419 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <termios.h>
+#include <sys/ioctl.h>
+
+#include "gramscii.h"
+#include "config.h"
+
+/*** screen management functions ***/
+
+
+/*** Status bar ***/
+
+char* mode_str(){
+ switch(mode){
+ case MOVE:
+ return "mov";
+ case TEXT:
+ return "txt";
+ case BOX:
+ return "box";
+ case ARROW:
+ return "arr";
+ case DEL:
+ return "del";
+ case VIS:
+ return "vis";
+ default:
+ return "ERR";
+ }
+ return "ERR";
+}
+
+char get_mark(char dir){
+ switch(dir){
+ case DIR_U:
+ return '^';
+ case DIR_D:
+ return 'v';
+ case DIR_L:
+ return '<';
+ case DIR_R:
+ return '>';
+ }
+ return '>';
+}
+
+
+void status_bar(){
+
+ if (silent)
+ return;
+ printf("\033[%d;1f\033[7m", HEIGHT+1);
+ printf("%*s", WIDTH-1, "");
+ printf("\033[%d;1f\033[7m", HEIGHT+1);
+ printf(" x:%3d y:%3d -- MODE:%4s HL:%c VL:%c CN:%c SP:%c EP:%c %10s",
+ x, y, mode_str(), line_h, line_v, corner, mark_st, mark_end, "");
+ if (!modified)
+ printf(" [%s]", fname );
+ else
+ printf(" *%s*", fname );
+#ifdef DEBUG
+ printf(" '%d' ", screen[y].s[x]);
+#endif
+ printf("\033[0m");
+ fflush(stdout);
+}
+
+char get_key(FILE *fc, char *msg){
+
+ if (silent)
+ return 0;
+ printf("\033[%d;1f\033[7m", HEIGHT+1);
+ printf("%*s", WIDTH, "");
+ printf("\033[%d;1f\033[7m", HEIGHT+1);
+ printf("%s", msg);
+ fflush(stdout);
+ printf("\033[0m");
+ fflush(stdout);
+ return fgetc(fc);
+}
+
+void get_string(FILE *fc, char *msg, char *s, int sz){
+
+ if (!silent){
+ printf("\033[%d;1f\033[7m", HEIGHT+1);
+ printf("%*s", WIDTH, "");
+ printf("\033[%d;1f\033[7m", HEIGHT+1);
+
+ /* We must activate echo now */
+ t3 = t2;
+ t3.c_lflag |= (ECHO | ICANON);
+ tcsetattr(0, TCSANOW, &t3);
+ printf("%s", msg);
+ printf("\033[0m");
+ }
+ fgets(s, sz, fc);
+ s[strlen(s)-1] = '\0';
+ tcsetattr(0, TCSANOW, &t2);
+ if (!silent)
+ fflush(stdout);
+}
+
+int is_yes(char c){
+ return c=='y' ? 1 : c == 'Y'? 1 : 0;
+}
+
+/*** Screen management ***/
+
+void show_cursor(){
+ if (silent)
+ return;
+ printf("\033[%d;%df", y+1, x+1);
+ fflush(stdout);
+}
+
+
+void set_xy(int _x, int _y, char c){
+ line_t *tmp;
+ if (_y >= num_lines){
+ tmp = realloc(screen, (_y + LONG_STEP)* sizeof(line_t));
+ if (tmp == NULL){
+ fprintf(stderr, "Unable to allocate memory for more lines");
+ exit(1);
+ }
+ else while ( num_lines < _y + LONG_STEP){
+ screen[num_lines].sz = WIDTH+1;
+ screen[num_lines].s = malloc((screen[num_lines].sz) * sizeof(char));
+ if (screen[num_lines].s == NULL){
+ perror("allocating screen[num_lines].s");
+ exit(1);
+ }
+ memset(screen[num_lines].s, BG, screen[num_lines].sz);
+ screen[num_lines].lst = 0;
+ screen[num_lines].s[screen[num_lines].lst+1]='\0';
+ num_lines ++;
+ }
+ }
+ if (screen[_y].sz < _x + 2){
+ screen[_y].sz = (_x +2) * 2;
+ screen[_y].s = realloc(screen[_y].s, screen[_y].sz * sizeof(char));
+ }
+ while (screen[_y].lst<_x){
+ screen[_y].lst ++;
+ screen[_y].s[screen[_y].lst] = BG;
+ }
+ screen[_y].s[_x] = c;
+ if (_x == screen[_y].lst)
+ screen[_y].s[_x+1] = '\0';
+}
+
+void set_cur(char c){
+ set_xy(x, y, c);
+}
+
+void draw_xy(int x, int y, char c){
+ /* FIXME: check if x and y are valid!!!! */
+ if (silent)
+ return;
+ printf("\033[%d;%df",y+1,x+1);
+ putchar(c);
+ fflush(stdout);
+}
+
+void update_current(){
+ if (silent)
+ return;
+ printf("\033[%d'%df",y+1,x+1);
+ putchar(screen[y].s[x]);
+ fflush(stdout);
+}
+
+void erase_line(char *s){
+ while(*s){
+ *s = BG;
+ s++;
+ }
+}
+
+void erase_box(int x1, int y1, char c){
+ int x_incr, y_incr, i;
+
+ x_incr = x1 < x? +1: -1;
+ y_incr = y1 < y? +1: -1;
+ do{
+ i = y1;
+ do{
+ set_xy(x1, i, c);
+ } while(i != y && (1 | (i += y_incr)));
+ } while(x1 != x && (1 | (x1 += x_incr)));
+
+}
+
+void erase_screen(){
+ int i;
+ for(i=0;i<HEIGHT; i++)
+ erase_line(screen[i].s);
+}
+
+void check_bound(){
+ if (x<0) x=0;
+ else if (x>=WIDTH) x = WIDTH-1;
+ if (y<0) y=0;
+ else if (y>=HEIGHT) y = HEIGHT -1;
+}
+
+void reset_styles(){
+
+ cur_corn = 0;
+ corner = corners[0];
+ cur_hl = cur_vl = 0;
+ cur_start = cur_end = 0;
+ line_h = hlines[cur_hl];
+ line_v = vlines[cur_vl];
+ mark_st = st_marks[cur_start];
+ mark_end = end_marks[cur_end];
+}
+
+void redraw(){
+ int i;
+
+ if (silent)
+ return;
+ printf("\033[2J\033[1;1H");
+ for (i=0;i<HEIGHT;i++){
+ fprintf(stdout,"%s\n",screen[i].s);
+ }
+ status_bar();
+ show_cursor();
+}
+
+void go_to(int where){
+ switch(where){
+ case HOME:
+ x = y = 0;
+ break;
+ case END:
+ x = WIDTH-1;
+ y = HEIGHT-1;
+ break;
+ case MIDDLE:
+ x = WIDTH/2;
+ y = HEIGHT/2;
+ break;
+ }
+ check_bound();
+ show_cursor();
+}
+
+void handle_goto(){
+ char c;
+ c=getchar();
+ switch(c){
+ case 'h':
+ dir = DIR_L;
+ x = 0;
+ break;
+ case 'l':
+ dir = DIR_R;
+ x = WIDTH - 1;
+ break;
+ case 'j':
+ dir = DIR_D;
+ y = HEIGHT - 1;
+ break;
+ case 'k':
+ dir = DIR_U;
+ y = 0;
+ break;
+ case 'g':
+ dir = DIR_N;
+ go_to(HOME);
+ break;
+ case 'G':
+ dir = DIR_N;
+ go_to(END);
+ break;
+ case 'm':
+ dir = DIR_N;
+ go_to(MIDDLE);
+ break;
+ }
+ check_bound();
+ show_cursor();
+}
+
+
+int get_escape(FILE *fc){
+ char c[4];
+
+ c[0] = fgetc(fc);
+ if (c[0] == '['){
+ c[1] = fgetc(fc);
+ switch(c[1]){
+ case 'D':
+ dir = DIR_L;
+ x -= step;
+ break;
+ case 'B':
+ dir = DIR_D;
+ y += step;
+ break;
+ case 'A':
+ dir = DIR_U;
+ y -= step;
+ break;
+ case 'C':
+ dir = DIR_R;
+ x += step;
+ break;
+ }
+ return 1;
+ }
+ else{
+ ungetc(c[0], fc);
+ return 0;
+ }
+
+}
+
+
+int move_around(char c, FILE *fc){
+
+ if (isdigit(c)){
+ if (mult)
+ mult *=10;
+ mult += c - '0';
+ return 0;
+ }
+ switch(c){
+ case 27: /* control sequence? */
+ c = get_escape(fc);
+ break;
+ case 'H': step = LONG_STEP;/** FALLTHROUGH **/
+ case 'h':
+ dir = DIR_L;
+ if (mult)
+ step *= mult;
+ x -= step;
+ break;
+ case 'J': step = LONG_STEP;/** FALLTHROUGH **/
+ case 'j':
+ if (mult)
+ step *= mult;
+ dir = DIR_D;
+ y += step;
+ break;
+ case 'K': step = LONG_STEP;/** FALLTHROUGH **/
+ case 'k':
+ if (mult)
+ step *= mult;
+ dir = DIR_U;
+ y -= step;
+ break;
+ case 'L': step = LONG_STEP;/** FALLTHROUGH **/
+ case 'l':
+ if (mult)
+ step *= mult;
+ dir = DIR_R;
+ x += step;
+ break;
+ case 'g':
+ handle_goto();
+ break;
+ default:
+ return 0;
+ }
+ mult = 0;
+ return c;
+}
+
+
+void set_video(int v){
+ if (silent)
+ return;
+ printf("\033[%dm", v);
+ fflush(stdout);
+}
+
+
+void init_screen(){
+ int i;
+ struct winsize wsz;
+
+ if (!ioctl(STDIN_FILENO, TIOCGWINSZ, &wsz)){
+ WIDTH=wsz.ws_col - 2;
+ HEIGHT=wsz.ws_row - 1;
+ }
+ else {
+ WIDTH=80;
+ HEIGHT=24;
+ }
+ screen = malloc(HEIGHT * sizeof(line_t));
+ num_lines = HEIGHT;
+ if (screen == NULL){
+ perror("allocating screen");
+ exit(1);
+ }
+ for (i=0; i<HEIGHT; i++){
+ screen[i].sz = WIDTH+1;
+ screen[i].s = malloc((screen[i].sz) * sizeof(char));
+ if (screen[i].s == NULL){
+ perror("allocating screen[i].s");
+ exit(1);
+ }
+ memset(screen[i].s, BG, screen[i].sz);
+ screen[i].lst = 0;
+ screen[i].s[screen[i].lst+1]='\0';
+ }
+ hlines_sz= sizeof(hlines) -1;
+ vlines_sz= sizeof(vlines) -1;
+ corners_sz = sizeof(corners) -1;
+ stmarks_sz = sizeof(st_marks) - 1;
+ endmarks_sz = sizeof(st_marks) - 1;
+ reset_styles();
+}
+