jim

Simple, lightweight, modal, vim-inspired text editor
git clone git://git.janpasierb.com/jim.git
Log | Files | Refs | README | LICENSE

output.c (5254B)


      1 #include"output.h"
      2 #include"jim.h"
      3 #include"appbuf.h"
      4 #include"syntax.h"
      5 #include"row.h"
      6 #include<stdio.h>
      7 #include<ctype.h>
      8 #include<string.h>
      9 #include<stdarg.h>
     10 #include<unistd.h>
     11 
     12 #define ABUF_INIT {NULL, 0}
     13 
     14 #define CLEAR_LINE 			"\x1b[K"
     15 #define CURSOR_HIDE 		"\x1b[?25l"
     16 #define CURSOR_SHOW 		"\x1b[?25h"
     17 #define COLOUR 				"\x1b[%dm"
     18 #define MAKE_BOLD 			"\x1b[1m"
     19 #define INVERT_COLORS 		"\x1b[7m"
     20 #define RESTORE_ATTRIBUTES 	"\x1b[m"
     21 #define RESTORE_COLOURS 	"\x1b[39;49m"
     22 
     23 void editorScroll() {
     24     E.rx = 0;
     25 
     26     if(E.cy < E.numrows) {
     27         E.rx = editorRowCxToRx(&E.row[E.cy], E.cx);
     28     }
     29 
     30     if(E.cy < E.rowoff) {
     31         E.rowoff = E.cy;
     32     }
     33 
     34     if(E.cy >= E.rowoff + E.screenrows) {
     35         E.rowoff = E.cy - E.screenrows + 1;
     36     }
     37 
     38     if(E.rx < E.coloff) {
     39         E.coloff = E.rx;
     40     }
     41 
     42     if(E.rx >= E.coloff + E.screencols) {
     43         E.coloff = E.rx - E.screencols + 1;
     44     }
     45 }
     46 
     47 void editorDrawRows(struct abuf *ab) {
     48     int y;
     49 
     50     for (y = 0; y < E.screenrows; y++) {
     51         int filerow = y + E.rowoff;
     52 
     53         if(filerow >= E.numrows) {
     54             if(E.cx == 0 && E.numrows == 0 && y == E.screenrows / 2) {
     55                 char welcome[80];
     56                 int welcomelen = snprintf(welcome, sizeof(welcome), "JIM editor -- version %s", JIM_VER);
     57                 if(welcomelen > E.screencols) welcomelen = E.screencols;
     58                 int padding = (E.screencols - welcomelen) / 2;
     59                 if(padding) {
     60                     abAppend(ab, EOF_PLACEHOLDER, 1);
     61                     padding--;
     62                 }
     63                 while(padding--) abAppend(ab, " ", 1);
     64                 abAppend(ab, welcome, welcomelen);
     65             } else if(y != 0) {
     66                 abAppend(ab, EOF_PLACEHOLDER, 1);
     67             }
     68         } else {
     69             int len = E.row[filerow].rsize - E.coloff;
     70             if(len < 0 ) len = 0;
     71             if(len > E.screencols) len = E.screencols;
     72             char* c = &E.row[filerow].render[E.coloff];
     73             unsigned char* hl = &E.row[filerow].hl[E.coloff];
     74             int cur_col = -1;
     75             for(int j = 0; j < len; j++) {
     76                 if(iscntrl(c[j])) {
     77                     char symbol = (c[j] <= 26) ? CONTROL + c[j] : NONPRINTABLE;
     78                     abAppend(ab, INVERT_COLORS, 4);
     79                     abAppend(ab, &symbol, 1);
     80                     abAppend(ab, RESTORE_ATTRIBUTES, 3);
     81                     if(cur_col != -1) {
     82                         char buf[16];
     83                         int col_len = snprintf(buf, sizeof(buf), COLOUR, cur_col);
     84                         abAppend(ab, RESTORE_COLOURS, 8);
     85                         abAppend(ab, buf, col_len);
     86                     }
     87                 } else if(hl[j] == HL_NORMAL) {
     88                     if(cur_col != -1) {
     89                         abAppend(ab, RESTORE_COLOURS, 8);
     90                         cur_col = -1;
     91                     }
     92                     abAppend(ab, &c[j], 1);
     93                 } else {
     94                     int colour = editorSyntaxToColour(hl[j]);
     95                     if(colour != cur_col) {
     96                         cur_col = colour;
     97                         char buf[16];
     98                         int col_len = snprintf(buf, sizeof(buf), COLOUR, colour);
     99                         abAppend(ab, RESTORE_COLOURS, 8);
    100                         abAppend(ab, buf, col_len);
    101                     }
    102 
    103                     abAppend(ab, &c[j], 1);
    104                 }
    105             }
    106 
    107             abAppend(ab, RESTORE_COLOURS, 8);
    108         }
    109 
    110         abAppend(ab, CLEAR_LINE, 3);
    111         abAppend(ab, "\r\n", 2);
    112     }
    113 }
    114 
    115 void editorDrawStatusBar(struct abuf *ab) {
    116     abAppend(ab, CLEAR_LINE, 3);
    117     abAppend(ab, INVERT_COLORS, 4);
    118 
    119     char rstatus[80];
    120     int rlen = 0;
    121     int msglen = strlen(E.statusmsg);
    122 
    123     if(msglen > E.screencols) msglen = E.screencols;
    124 
    125     if(E.isbold)
    126         abAppend(ab, MAKE_BOLD, 4);
    127     abAppend(ab, E.statusmsg, msglen);
    128     abAppend(ab, RESTORE_ATTRIBUTES, 3);
    129     abAppend(ab, INVERT_COLORS, 4);
    130 
    131     if(E.isr) {
    132         float posr = ((E.cy + 1) / (float)E.numrows) * 100;
    133         rlen = snprintf(rstatus, sizeof(rstatus), "%d,%d     %.0f%%",
    134             E.cy + 1, E.rx + 1, posr < 1.0 ? 1.0 : posr);
    135     }
    136 
    137     while(msglen < E.screencols) {
    138         if(E.screencols - msglen == rlen) {
    139             abAppend(ab, rstatus, rlen);
    140             break;
    141         } else {
    142             abAppend(ab, " ", 1);
    143             msglen++;
    144         }
    145     }
    146 
    147     abAppend(ab, RESTORE_ATTRIBUTES, 3);
    148 }
    149 
    150 void editorRefreshScreen() {
    151     editorScroll();
    152 
    153     struct abuf ab = ABUF_INIT;
    154 
    155     abAppend(&ab, CURSOR_HIDE, 6);
    156     abAppend(&ab, CURSOR_TOP, 3);
    157 
    158     editorDrawRows(&ab);
    159     editorDrawStatusBar(&ab);
    160 
    161     char buf[32];
    162     snprintf(buf, sizeof(buf), "\x1B[%d;%dH", (E.cy - E.rowoff) + 1, (E.rx - E.coloff) + 1);
    163 
    164     abAppend(&ab, buf, strlen(buf));
    165 
    166     abAppend(&ab, CURSOR_SHOW, 6);
    167 
    168     write(STDOUT_FILENO, ab.b, ab.len);
    169     abFree(&ab);
    170 }
    171 
    172 void editorSetStatusMessage(const char* fmt, ...) {
    173     va_list ap;
    174     va_start(ap, fmt);
    175     vsnprintf(E.statusmsg, sizeof(E.statusmsg), fmt, ap);
    176     va_end(ap);
    177 }
    178 
    179 void editorSetDefaultStatusMessage() {
    180     E.isbold = 0;
    181     E.isr = 1;
    182     editorSetStatusMessage("\"%.20s\" %dL", E.filename ? E.filename : "[No Name]", E.numrows);
    183 }