Fix "del" command at the end of a line.
[eco.git] / update.c
blob8bea1881ed83c0c93ae1900c97f4083a96d0a474
1 /*
2 * Copyright (C) 2008 Diego Hernan Borghetti.
3 * Eco
4 */
6 #include <stdio.h>
8 #include "debug.h"
9 #include "term.h"
10 #include "screen.h"
11 #include "buffer.h"
12 #include "view.h"
13 #include "config.h"
14 #include "eco.h"
17 int e_update_get_tab(E_Eco *ec, int col)
19 int tab;
21 tab= 8 + ec->view->col;
22 while (tab <= col)
23 tab+= 8;
24 return(tab);
27 int e_update_line(E_Eco *ec, E_Line *ln, int row)
29 int i, col, tab, invert;
30 char fgcol, bgcol;
32 if (ec->view->b->line == ln) {
33 /* Mark the current line in the screen. */
34 e_screen_crow(ec->sc, row, 1);
35 invert= 1;
36 i= ec->view->b->dot_pad;
38 else {
39 /* clear the flag if this is not the current line. */
40 e_screen_crow(ec->sc, row, 0);
41 invert= 0;
42 i= 0;
45 if (invert) {
46 fgcol= E_TR_BLACK;
47 bgcol= E_TR_GREEN;
49 else {
50 fgcol= E_TR_WHITE;
51 bgcol= E_TR_BLACK;
54 for (col= ec->view->col; col < ec->view->rcol && i < ln->used; i++, col++) {
55 if (ln->text[i] == '\t') {
56 tab= e_update_get_tab(ec, col);
57 while (col != tab) {
58 e_screen_move(ec->sc, row, col);
59 e_screen_putc(ec->sc, ' ', fgcol, bgcol);
60 col++;
62 col--;
64 else {
65 e_screen_move(ec->sc, row, col);
66 if (ln->text[i] >= 0x20 && ln->text[i] < 0x7f)
67 e_screen_putc(ec->sc, ln->text[i], fgcol, bgcol);
68 else
69 e_screen_putc(ec->sc, ' ', fgcol, bgcol);
73 /* clean the rest of the line. */
74 if (col < ec->view->rcol) {
75 e_screen_move(ec->sc, row, col);
76 e_screen_eeol(ec->sc);
78 return(row);
81 int __get_real_col(E_Eco *ec, E_Line *ln, int dot)
83 int col, i;
85 for (i= dot, col= ec->view->col; i < ec->view->b->dot; i++) {
86 if (ec->view->b->line->text[i] == '\t')
87 col= e_update_get_tab(ec, col);
88 else
89 col++;
91 return(col);
94 void __reframe(E_Eco *ec)
96 E_Line *p;
97 int row, col, found, i;
99 /* check if we need pad the dot. */
100 col= __get_real_col(ec, ec->view->b->line, 0);
101 ec->view->b->dot_pad= 0;
103 while (col > ec->view->rcol) {
104 /* ok we need pad this, but go one-by-one so the
105 * left/right keys work fine.
107 ec->view->b->dot_pad++;
108 col= __get_real_col(ec, ec->view->b->line, ec->view->b->dot_pad);
111 p= ec->view->b->first;
112 row= ec->view->row;
113 found= 0;
114 while (p) {
115 if (p == ec->view->b->line) {
116 found= 1;
117 break;
120 row++;
121 p= p->next;
124 e_debug_printf("Check if need reframe\n");
126 * This can happen, the current line is before
127 * the first line and from the first to the end
128 * is < nrow, so need be sure.
130 if ((row < ec->view->rrow) && (found))
131 return;
133 /* We have 3 case here.
134 * 1) The current line is out of the screen because a "up"
135 * 2) The current line is out of the screen because a "down"
136 * 3) A scroll up/down
138 if (ec->view->b->flag & BUFFER_UP) {
139 /* in this case, the prev line of the current
140 * line is where we need to go.
142 if (ec->view->b->first->prev)
143 ec->view->b->first= ec->view->b->first->prev;
144 e_debug_printf("Reframe up buffer\n");
145 BUFFER_UNSET(ec->view->b, BUFFER_UP);
147 else if (ec->view->b->flag & BUFFER_DOWN) {
148 /* in this case the next line of the last line
149 * is our target, so just move one line ;)
151 if (ec->view->b->first->next)
152 ec->view->b->first= ec->view->b->first->next;
153 e_debug_printf("Reframe down buffer\n");
154 BUFFER_UNSET(ec->view->b, BUFFER_DOWN);
156 else {
157 /* Ok, we are here because page up/down, the normal
158 * scroll with 3+ lines.
160 ec->view->b->first= ec->view->b->line;
161 for (i= 0; i < 3; i++) {
162 if (!ec->view->b->first->prev)
163 break;
164 ec->view->b->first= ec->view->b->first->prev;
166 e_debug_printf("Reframe buffer\n");
170 void e_update_cursor(E_Eco *ec)
172 E_Line *p;
173 int row, col;
176 * This function sync the physical and virtual
177 * cursor position, assume that the buffer don't
178 * need reframe.
180 * First, match the current row.
182 row= ec->view->row;
183 p= ec->view->b->first;
184 while (p) {
185 if (p == ec->view->b->line)
186 break;
188 row++;
189 p= p->next;
192 /* second check if the line is "extend" or not. */
193 col= __get_real_col(ec, ec->view->b->line, 0);
195 if (col > ec->view->rcol)
196 col= __get_real_col(ec, ec->view->b->line, ec->view->b->dot_pad);
198 e_screen_move(ec->sc, row, col);
199 e_term_move(row, col);
202 void e_update(E_Eco *ec)
204 E_View *v, *vp;
205 E_Line *ln;
206 char fgcol, bgcol;
207 int row;
209 fgcol= e_config_get_char("Screen", "empty_char_fg");
210 bgcol= e_config_get_char("Screen", "empty_char_bg");
211 if (fgcol == -1)
212 fgcol= E_TR_BLUE;
213 if (bgcol == -1)
214 bgcol= E_TR_BLACK;
216 /* first save the active view. */
217 v= ec->view;
219 /* now update all the view that are show and need redraw. */
220 vp= ec->view_list;
221 while (vp) {
222 if ((vp->flag & VIEW_REDRAW) && (vp->flag & VIEW_SHOW)) {
223 /* make the active, just for draw. */
224 ec->view= vp;
226 /* check for scroll. */
227 __reframe(ec);
229 ln= ec->view->b->first;
230 row= ec->view->row;
231 while (ln && (row < ec->view->rrow)) {
232 row= e_update_line(ec, ln, row);
233 row++;
234 ln= ln->next;
237 /* fill the unused lines. */
238 while (row < ec->view->rrow) {
239 e_screen_move(ec->sc, row, ec->view->col);
240 e_screen_putc(ec->sc, '~', E_TR_BLUE, E_TR_BLACK);
241 e_screen_move(ec->sc, row, ec->view->col+1);
242 e_screen_eeol(ec->sc);
243 row++;
246 /* always remove the scroll flags or
247 * we can get bad result in the next reframe.
249 if (vp->b->flag & BUFFER_UP) {
250 BUFFER_UNSET(vp->b, BUFFER_UP);
252 if (vp->b->flag & BUFFER_DOWN) {
253 BUFFER_UNSET(vp->b, BUFFER_DOWN);
255 vp->flag &= ~VIEW_REDRAW;
257 vp= vp->next;
260 /* restore the active view. */
261 ec->view= v;
262 e_update_cursor(ec);