2 * Copyright (C) 2008 Diego Hernan Borghetti.
20 E_Line
*e_line_alloc(void)
24 ln
= (E_Line
*)malloc(sizeof(E_Line
));
30 ln
->text
= (char *)malloc(16);
34 void e_line_realloc(E_Line
*ln
)
37 ln
->text
= (char *)realloc((void *)ln
->text
, ln
->size
);
40 void e_line_free(E_Line
*ln
)
42 free((void *)ln
->text
);
46 void e_line_add(E_Buffer
*bf
, E_Line
*ln
)
48 ln
->next
= bf
->line
->next
;
58 void e_line_add_first(E_Buffer
*bf
, E_Line
*ln
)
67 bf
->first
= ln
; /* auto-reframe. */
71 void e_line_remove(E_Buffer
*bf
, E_Line
*ln
)
74 ln
->next
->prev
= ln
->prev
;
76 ln
->prev
->next
= ln
->next
;
81 if (bf
->first
== ln
) {
83 bf
->first
= bf
->first
->prev
;
85 bf
->first
= bf
->first
->next
;
90 bf
->line
= bf
->line
->next
;
92 bf
->line
= bf
->line
->prev
;
100 E_Buffer
*e_buffer_new(char *file
)
104 bf
= (E_Buffer
*)malloc(sizeof(E_Buffer
));
106 bf
->paths
= e_file_get_paths(file
);
113 if (!bf
->paths
->path
) {
114 free((void *)bf
->paths
);
119 if (!bf
->paths
->file
) {
120 free((void *)bf
->paths
->path
);
121 free((void *)bf
->paths
);
125 /* remove the full path, only show the name. */
126 bf
->name
= strrchr(bf
->paths
->file
, '/');
128 bf
->name
= bf
->paths
->file
;
132 e_debug_printf("path: %s\n", bf
->paths
->path
);
133 e_debug_printf("file: %s\n", bf
->paths
->file
);
134 e_debug_printf("name: %s\n", bf
->name
);
136 bf
->lines
= e_line_alloc();
137 bf
->first
= bf
->lines
;
147 void e_buffer_free(E_Buffer
*bf
)
151 /* only remove the lock when we free the buffer. */
152 e_file_lock_rem(bf
->paths
);
154 free((void *)bf
->paths
->path
);
155 free((void *)bf
->paths
->file
);
156 free((void *)bf
->paths
->lock_file
);
157 free((void *)bf
->paths
);
161 e_line_free(bf
->lines
);
167 void e_buffer_recalc(E_Buffer
*bf
)
181 /* Add a new line at the current position in the buffer. */
182 void e_buffer_newline(E_Buffer
*bf
)
186 BUFFER_SET(bf
, BUFFER_FLUSH
);
191 /* Always clean the current position, the new line don't
198 /* Add a new line at the begin of the buffer. */
199 void e_buffer_newline_first(E_Buffer
*bf
)
203 BUFFER_SET(bf
, BUFFER_FLUSH
);
206 e_line_add_first(bf
, ln
);
211 /* Split the current line in two line, the starting
212 * point for split is the current cursor position.
214 void e_buffer_splitline(E_Buffer
*bf
)
219 /* save the current line. */
222 /* and the cursor position. */
225 /* insert a new line and add all the character
226 * from the current position, to the end.
228 e_buffer_newline(bf
);
229 for (i
= dot
; i
< ln
->used
; i
++)
230 e_buffer_insert(bf
, ln
->text
[i
]);
234 /* Always go to the begin of the line. */
238 /* Join two line, the source line is the current line and
239 * the dest line is the prev.
241 void e_buffer_joinline(E_Buffer
*bf
)
246 /* if we are at the begin, return. */
250 /* save the current line. */
253 /* move to the previous. */
256 /* put the cursor to the end of the line. */
257 bf
->dot
= bf
->line
->used
;
259 /* and save the position. */
262 /* insert all the characters. */
263 for (i
= 0; i
< ln
->used
; i
++)
264 e_buffer_insert(bf
, ln
->text
[i
]);
266 /* remove the unused line. */
267 e_line_remove(bf
, ln
);
270 /* restore the original cursor position. */
275 /* Remove the current line from the buffer, this also
276 * can save the line in the cut-buffer.
278 void e_buffer_killline(E_Buffer
*bf
, int cut
)
283 e_kill_cut(bf
->line
);
285 if ((!bf
->line
->prev
) && (!bf
->line
->next
)) {
286 /* If we don't have previous or next line,
287 * the only thing to do is clean the
290 e_buffer_cleanline(bf
);
293 else if (!bf
->line
->next
) {
294 /* If we don't have next line, only clean. */
295 e_buffer_cleanline(bf
);
299 if (bf
->line
->used
) {
300 /* This work like emacs, if the line have text
301 * first clean the text.
303 e_buffer_cleanline(bf
);
307 /* And if the line don't have text, remove it. */
308 BUFFER_SET(bf
, BUFFER_FLUSH
);
312 e_line_remove(bf
, ln
);
317 /* Insert a character in the current line at the current
320 void e_buffer_insert(E_Buffer
*bf
, int c
)
324 BUFFER_SET(bf
, BUFFER_FLUSH
);
326 /* check if we need reallocate the line. */
327 if ((bf
->line
->used
+1) >= bf
->line
->size
)
328 e_line_realloc(bf
->line
);
330 /* if the cursor is not at the end of the line,
331 * we need scroll the text to the right.
333 if (bf
->dot
!= bf
->line
->used
) {
334 for (i
= bf
->line
->used
; i
> bf
->dot
; i
--)
335 bf
->line
->text
[i
]= bf
->line
->text
[i
-1];
338 /* insert the new character. */
339 bf
->line
->text
[bf
->dot
]= c
;
344 /* Just that, insert a backspace ;) */
345 void e_buffer_backspace(E_Buffer
*bf
)
349 /* The only case that we have here is if the cursor position
350 * is at the begin of the line, in that case we need join
354 BUFFER_SET(bf
, BUFFER_FLUSH
);
356 /* If the cursor is not at the end of the line,
357 * we need scroll the text.
359 for (i
= bf
->dot
; i
< bf
->line
->used
; i
++)
360 bf
->line
->text
[i
-1]= bf
->line
->text
[i
];
365 e_buffer_joinline(bf
);
368 void e_buffer_del(E_Buffer
*bf
)
370 if (bf
->dot
+1 < bf
->line
->used
) {
372 e_buffer_backspace(bf
);
376 void e_buffer_up(E_Buffer
*bf
)
378 if (bf
->line
->prev
) {
379 bf
->line
= bf
->line
->prev
;
380 if (bf
->dot
> bf
->line
->used
)
381 bf
->dot
= bf
->line
->used
;
386 void e_buffer_down(E_Buffer
*bf
)
388 if (bf
->line
->next
) {
389 bf
->line
= bf
->line
->next
;
390 if (bf
->dot
> bf
->line
->used
)
391 bf
->dot
= bf
->line
->used
;
396 void e_buffer_left(E_Buffer
*bf
)
406 void e_buffer_right(E_Buffer
*bf
)
408 if (bf
->dot
< bf
->line
->used
)
416 void e_buffer_goto_begin(E_Buffer
*bf
)
423 void e_buffer_goto_end(E_Buffer
*bf
)
433 bf
->nl
= bf
->nlines
+1; /* zero */
436 void e_buffer_bol(E_Buffer
*bf
)
441 void e_buffer_eol(E_Buffer
*bf
)
443 bf
->dot
= bf
->line
->used
;
446 void e_buffer_scroll(E_Buffer
*bf
, int nline
, int dir
)
450 for(i
= 0; i
< nline
; i
++) {
452 if (!bf
->first
->prev
)
454 bf
->first
= bf
->first
->prev
;
457 if (!bf
->first
->next
)
459 bf
->first
= bf
->first
->next
;
463 if (bf
->dot
> bf
->line
->used
)
464 bf
->dot
= bf
->line
->used
;
468 void e_buffer_goto(E_Buffer
*bf
, int line
)
487 if (bf
->dot
> bf
->line
->used
)
491 void e_buffer_cleanline(E_Buffer
*bf
)
493 BUFFER_SET(bf
, BUFFER_FLUSH
);
499 E_Line
*__e_buffer_search(E_Buffer
*bf
, char *pattern
, int *dot_found
, int dir
)
502 int i
, e
, a
, len
, dot
, found
;
504 len
= strlen(pattern
);
508 /* I know.. this is not the best backward.. but work. */
509 if (dir
== BUFFER_SEARCH_FORWARD
)
515 if (dir
== BUFFER_SEARCH_FORWARD
&& ln
== bf
->line
)
520 for (; i
< ln
->used
; i
++) {
521 if (ln
->text
[i
] == pattern
[0]) {
522 /* save the current position of the cursor. */
527 for (e
= 0; e
< len
; e
++) {
528 if (ln
->text
[i
] != pattern
[e
]) {
550 if (dir
== BUFFER_SEARCH_FORWARD
)
556 if (dir
== BUFFER_SEARCH_FORWARD
)
557 *dot_found
= (dot
+len
);
564 void e_buffer_search(E_Buffer
*bf
, char *pattern
, int dir
)
569 ln
= __e_buffer_search(bf
, pattern
, &dot
, dir
);
578 int e_buffer_replace(E_Buffer
*bf
, char *pattern
, char *replace
)
581 int i
, c
, len
, ncount
, dot
;
584 len
= strlen(replace
);
587 ln
= __e_buffer_search(bf
, pattern
, &dot
, BUFFER_SEARCH_FORWARD
);
589 /* first set the line, so all the next call
597 /* now remove the pattern. */
598 for (i
= 0; i
< c
; i
++)
599 e_buffer_backspace(bf
);
601 /* and now insert the new string. */
602 for (i
= 0; i
< len
; i
++)
603 e_buffer_insert(bf
, replace
[i
]);
606 ln
= __e_buffer_search(bf
, pattern
, &dot
, BUFFER_SEARCH_FORWARD
);