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 }