1 /* editor low level data handling and cursor fundamentals.
3 Copyright (C) 1996, 1997 the Free Software Foundation
5 Authors: 1996, 1997 Paul Sheer
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
25 #define _EDIT_C THIS_IS
28 #if defined(NEEDS_IO_H)
31 # define CR_LF_TRANSLATION
36 # include <sys/timeb.h>
37 #endif /* SCO_FLAVOR */
38 #include <time.h> /* for ctime() */
39 #if defined (HAVE_MAD) && ! defined (MIDNIGHT) && ! defined (GTK)
43 #include <../src/dialog.h> /* MSG_ERROR */
45 extern char *edit_one_file
;
49 * here's a quick sketch of the layout: (don't run this through indent.)
51 * (b1 is buffers1 and b2 is buffers2)
54 * \0\0\0\0\0m e _ f i l e . \nf i n . \n|T h i s _ i s _ s o\0\0\0\0\0\0\0\0\0
55 * ______________________________________|______________________________________
57 * ... | b2[2] | b2[1] | b2[0] | b1[0] | b1[1] | b1[2] | ...
58 * |-> |-> |-> |-> |-> |-> |
60 * _<------------------------->|<----------------->_
61 * WEdit->curs2 | WEdit->curs1
66 * file end|||file beginning
78 returns a byte from any location in the file.
79 Returns '\n' if out of bounds.
82 static int push_action_disabled
= 0;
84 #ifndef NO_INLINE_GETBYTE
86 int edit_get_byte (WEdit
* edit
, long byte_index
)
89 if (byte_index
>= (edit
->curs1
+ edit
->curs2
) || byte_index
< 0)
92 if (byte_index
>= edit
->curs1
) {
93 p
= edit
->curs1
+ edit
->curs2
- byte_index
- 1;
94 return edit
->buffers2
[p
>> S_EDIT_BUF_SIZE
][EDIT_BUF_SIZE
- (p
& M_EDIT_BUF_SIZE
) - 1];
96 return edit
->buffers1
[byte_index
>> S_EDIT_BUF_SIZE
][byte_index
& M_EDIT_BUF_SIZE
];
102 char *edit_get_buffer_as_text (WEdit
* e
)
106 l
= e
->curs1
+ e
->curs2
;
108 for (i
= 0; i
< l
; i
++)
109 t
[i
] = edit_get_byte (e
, i
);
115 /* Note on CRLF->LF translation: */
118 #error MY_O_TEXT is depreciated. CR_LF_TRANSLATION must be defined which does CR-LF translation internally. See note in source.
122 The edit_open_file (previously edit_load_file) function uses
123 init_dynamic_edit_buffers to load a file. This is unnecessary
124 since you can just as well fopen the file and insert the
125 characters one by one. The real reason for
126 init_dynamic_edit_buffers (besides allocating the buffers) is
127 as an optimisation - it uses raw block reads and inserts large
128 chunks at a time. It is hence extremely fast at loading files.
129 Where we might not want to use it is if we were doing
130 CRLF->LF translation or if we were reading from a pipe.
133 /* Initialisation routines */
135 /* returns 1 on error */
136 /* loads file OR text into buffers. Only one must be none-NULL. */
137 /* cursor set to start of file */
138 int init_dynamic_edit_buffers (WEdit
* edit
, const char *filename
, const char *text
)
141 int j
, file
= -1, buf2
;
143 for (j
= 0; j
<= MAXBUFF
; j
++) {
144 edit
->buffers1
[j
] = NULL
;
145 edit
->buffers2
[j
] = NULL
;
149 if ((file
= open ((char *) filename
, O_RDONLY
)) == -1) {
150 /* The file-name is printed after the ':' */
151 edit_error_dialog (_ (" Error "), get_sys_error (catstrs (_ (" Failed trying to open file for reading: "), filename
, " ", 0)));
154 edit
->curs2
= edit
->last_byte
;
156 buf2
= edit
->curs2
>> S_EDIT_BUF_SIZE
;
158 edit
->buffers2
[buf2
] = CMalloc (EDIT_BUF_SIZE
);
161 read (file
, (char *) edit
->buffers2
[buf2
] + EDIT_BUF_SIZE
- (edit
->curs2
& M_EDIT_BUF_SIZE
), edit
->curs2
& M_EDIT_BUF_SIZE
);
163 memcpy (edit
->buffers2
[buf2
] + EDIT_BUF_SIZE
- (edit
->curs2
& M_EDIT_BUF_SIZE
), text
, edit
->curs2
& M_EDIT_BUF_SIZE
);
164 text
+= edit
->curs2
& M_EDIT_BUF_SIZE
;
167 for (buf
= buf2
- 1; buf
>= 0; buf
--) {
168 edit
->buffers2
[buf
] = CMalloc (EDIT_BUF_SIZE
);
170 read (file
, (char *) edit
->buffers2
[buf
], EDIT_BUF_SIZE
);
172 memcpy (edit
->buffers2
[buf
], text
, EDIT_BUF_SIZE
);
173 text
+= EDIT_BUF_SIZE
;
183 /* detecting an error on save is easy: just check if every byte has been written. */
184 /* detecting an error on read, is not so easy 'cos there is not way to tell
185 whether you read everything or not. */
186 /* FIXME: add proper `triple_pipe_open' to read, write and check errors. */
187 static const struct edit_filters
{
188 char *read
, *write
, *extension
;
192 "bzip2 -cd %s 2>&1", "bzip2 > %s", ".bz2"
195 "gzip -cd %s 2>&1", "gzip > %s", ".gz"
198 "compress -cd %s 2>&1", "compress > %s", ".Z"
202 static int edit_find_filter (const char *filename
)
207 l
= strlen (filename
);
208 for (i
= 0; i
< sizeof (all_filters
) / sizeof (struct edit_filters
); i
++) {
210 e
= strlen (all_filters
[i
].extension
);
212 if (!strcmp (all_filters
[i
].extension
, filename
+ l
- e
))
218 char *edit_get_filter (const char *filename
)
222 i
= edit_find_filter (filename
);
225 l
= strlen (filename
);
226 p
= malloc (strlen (all_filters
[i
].read
) + l
+ 2);
227 sprintf (p
, all_filters
[i
].read
, filename
);
231 char *edit_get_write_filter (char *writename
, const char *filename
)
235 i
= edit_find_filter (filename
);
238 l
= strlen (writename
);
239 p
= malloc (strlen (all_filters
[i
].write
) + l
+ 2);
240 sprintf (p
, all_filters
[i
].write
, writename
);
244 #ifdef CR_LF_TRANSLATION
245 /* reads into buffer, replace \r\n with \n */
246 long edit_insert_stream (WEdit
* edit
, FILE * f
)
250 while ((b
= fgetc (f
))) {
251 if (a
== '\r' && b
== '\n') {
252 edit_insert (edit
, '\n');
257 edit_insert (edit
, a
);
263 edit_insert (edit
, a
);
266 /* writes buffer, replaces, replace \n with \r\n */
267 long edit_write_stream (WEdit
* edit
, FILE * f
)
271 for (i
= 0; i
< edit
->last_byte
; i
++) {
272 c
= edit_get_byte (edit
, i
);
274 if (fputc ('\r', f
) < 0)
276 if (fputc ('\n', f
) < 0)
279 if (fputc (c
, f
) < 0)
285 #else /* CR_LF_TRANSLATION */
286 long edit_insert_stream (WEdit
* edit
, FILE * f
)
290 while ((c
= fgetc (f
)) >= 0) {
291 edit_insert (edit
, c
);
296 long edit_write_stream (WEdit
* edit
, FILE * f
)
299 for (i
= 0; i
< edit
->last_byte
; i
++)
300 if (fputc (edit_get_byte (edit
, i
), f
) < 0)
304 #endif /* CR_LF_TRANSLATION */
306 #define TEMP_BUF_LEN 1024
308 /* inserts a file at the cursor, returns 1 on success */
309 int edit_insert_file (WEdit
* edit
, const char *filename
)
312 if ((p
= edit_get_filter (filename
))) {
314 long current
= edit
->curs1
;
315 f
= (FILE *) popen (p
, "r");
317 edit_insert_stream (edit
, f
);
318 edit_cursor_move (edit
, current
- edit
->curs1
);
319 if (pclose (f
) > 0) {
320 edit_error_dialog (_ (" Error "), catstrs (_ (" Error reading from pipe: "), p
, " ", 0));
325 edit_error_dialog (_ (" Error "), get_sys_error (catstrs (_ (" Failed trying to open pipe for reading: "), p
, " ", 0)));
330 #ifdef CR_LF_TRANSLATION
333 long current
= edit
->curs1
;
334 f
= fopen (filename
, "r");
336 edit_insert_stream (edit
, f
);
337 edit_cursor_move (edit
, current
- edit
->curs1
);
339 edit_error_dialog (_ (" Error "), get_sys_error (catstrs (_ (" Error reading file: "), filename
, " ", 0)));
343 edit_error_dialog (_ (" Error "), get_sys_error (catstrs (_ (" Failed trying to open file for reading: "), filename
, " ", 0)));
348 int i
, file
, blocklen
;
349 long current
= edit
->curs1
;
351 if ((file
= open ((char *) filename
, O_RDONLY
)) == -1)
353 buf
= malloc (TEMP_BUF_LEN
);
354 while ((blocklen
= read (file
, (char *) buf
, TEMP_BUF_LEN
)) > 0) {
355 for (i
= 0; i
< blocklen
; i
++)
356 edit_insert (edit
, buf
[i
]);
358 edit_cursor_move (edit
, current
- edit
->curs1
);
368 static int check_file_access (WEdit
*edit
, const char *filename
, struct stat
*st
)
371 #if defined(MIDNIGHT) || defined(GTK)
372 if ((file
= open ((char *) filename
, O_RDONLY
)) < 0) {
373 close (creat ((char *) filename
, 0666));
374 if ((file
= open ((char *) filename
, O_RDONLY
)) < 0) {
375 edit_error_dialog (_ (" Error "), get_sys_error (catstrs (_ (" Failed trying to open file for reading: "), filename
, " ", 0)));
380 if ((file
= open ((char *) filename
, O_RDONLY
)) < 0) {
381 edit_error_dialog (_ (" Error "), get_sys_error (catstrs (_ (" Failed trying to open file for reading: "), filename
, " ", 0)));
385 if (stat ((char *) filename
, st
) < 0) {
387 /* The file-name is printed after the ':' */
388 edit_error_dialog (_ (" Error "), get_sys_error (catstrs (_ (" Cannot get size/permissions info on file: "), filename
, " ", 0)));
391 if (S_ISDIR (st
->st_mode
) || S_ISSOCK (st
->st_mode
)
392 || S_ISFIFO (st
->st_mode
)) {
394 /* The file-name is printed after the ':' */
395 edit_error_dialog (_ (" Error "), catstrs (_ (" Not an ordinary file: "), filename
, " ", 0));
398 if (st
->st_size
>= SIZE_LIMIT
) {
400 /* The file-name is printed after the ':' */
401 edit_error_dialog (_ (" Error "), catstrs (_ (" File is too large: "), \
402 filename
, _ (" \n Increase edit.h:MAXBUF and recompile the editor. "), 0));
409 /* returns 1 on error */
410 int edit_open_file (WEdit
* edit
, const char *filename
, const char *text
, unsigned long text_size
)
414 edit
->last_byte
= text_size
;
418 r
= check_file_access (edit
, filename
, &st
);
419 #if defined(MIDNIGHT) || defined(GTK)
421 return edit
->delete_file
= 1;
426 #ifndef CR_LF_TRANSLATION
427 edit
->last_byte
= st
.st_size
;
429 /* going to read the file into the buffer later byte by byte */
435 return init_dynamic_edit_buffers (edit
, filename
, text
);
439 #define space_width 1
442 extern int option_long_whitespace
;
444 void edit_set_space_width (int s
)
449 int (*edit_file_is_open
) (char *) = 0;
453 /* fills in the edit struct. returns 0 on fail. Pass edit as NULL for this */
454 WEdit
*edit_init (WEdit
* edit
, int lines
, int columns
, const char *filename
, const char *text
, const char *dir
, unsigned long text_size
)
460 if (option_long_whitespace
)
461 edit_set_space_width (FONT_PER_CHAR
[' '] * 2);
463 edit_set_space_width (FONT_PER_CHAR
[' ']);
468 * Expand option_whole_chars_search by national letters using
472 static char option_whole_chars_search_buf
[256];
474 if (option_whole_chars_search_buf
!= option_whole_chars_search
) {
476 int len
= strlen (option_whole_chars_search
);
478 strcpy (option_whole_chars_search_buf
, option_whole_chars_search
);
480 for (i
= 1; i
<= sizeof (option_whole_chars_search_buf
); i
++) {
481 if (islower (i
) && !strchr (option_whole_chars_search
, i
)) {
482 option_whole_chars_search_buf
[len
++] = i
;
486 option_whole_chars_search_buf
[len
] = 0;
487 option_whole_chars_search
= option_whole_chars_search_buf
;
489 #endif /* ENABLE_NLS */
490 edit
= malloc (sizeof (WEdit
));
491 memset (edit
, 0, sizeof (WEdit
));
494 memset (&(edit
->from_here
), 0, (unsigned long) &(edit
->to_here
) - (unsigned long) &(edit
->from_here
));
496 edit
->max_column
= columns
* FONT_MEAN_WIDTH
;
498 edit
->num_widget_lines
= lines
;
499 edit
->num_widget_columns
= columns
;
500 edit
->stat
.st_mode
= S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IROTH
;
501 edit
->stat
.st_uid
= getuid ();
502 edit
->stat
.st_gid
= getgid ();
506 f
= (char *) filename
;
508 f
= catstrs (dir
, filename
, 0);
510 if (edit_file_is_open
)
511 if ((*edit_file_is_open
) (f
)) {
518 if (edit_find_filter (f
) < 0) {
519 #ifdef CR_LF_TRANSLATION
522 if (edit_open_file (edit
, f
, text
, text_size
)) {
523 /* edit_load_file already gives an error message */
530 if (edit_open_file (edit
, 0, "", 0)) {
536 edit
->force
|= REDRAW_PAGE
;
538 filename
= catstrs (dir
, filename
, 0);
539 edit_split_filename (edit
, (char *) filename
);
541 edit
->filename
= (char *) strdup ("");
542 edit
->dir
= (char *) strdup (dir
);
544 edit
->stack_size
= START_STACK_SIZE
;
545 edit
->stack_size_mask
= START_STACK_SIZE
- 1;
546 edit
->undo_stack
= malloc ((edit
->stack_size
+ 10) * sizeof (long));
547 edit
->total_lines
= edit_count_lines (edit
, 0, edit
->last_byte
);
550 push_action_disabled
= 1;
551 if (check_file_access (edit
, filename
, &st
)) {
558 if (!edit_insert_file (edit
, f
)) {
564 /* FIXME: this should be an unmodification() function */
565 push_action_disabled
= 0;
568 edit_load_syntax (edit
, 0, 0);
571 edit_get_syntax_color (edit
, -1, &fg
, &bg
);
576 /* clear the edit struct, freeing everything in it. returns 1 on success */
577 int edit_clean (WEdit
* edit
)
581 edit_free_syntax_rules (edit
);
582 book_mark_flush (edit
, -1);
583 for (; j
<= MAXBUFF
; j
++) {
584 if (edit
->buffers1
[j
] != NULL
)
585 free (edit
->buffers1
[j
]);
586 if (edit
->buffers2
[j
] != NULL
)
587 free (edit
->buffers2
[j
]);
590 if (edit
->undo_stack
)
591 free (edit
->undo_stack
);
593 free (edit
->filename
);
596 /* we don't want to clear the widget */
597 memset (&(edit
->from_here
), 0, (unsigned long) &(edit
->to_here
) - (unsigned long) &(edit
->from_here
));
604 /* returns 1 on success */
605 int edit_renew (WEdit
* edit
)
607 int lines
= edit
->num_widget_lines
;
608 int columns
= edit
->num_widget_columns
;
612 dir
= (char *) strdup (edit
->dir
);
617 if (!edit_init (edit
, lines
, columns
, 0, "", dir
, 0))
622 /* returns 1 on success, if returns 0, the edit struct would have been free'd */
623 int edit_reload (WEdit
* edit
, const char *filename
, const char *text
, const char *dir
, unsigned long text_size
)
626 int lines
= edit
->num_widget_lines
;
627 int columns
= edit
->num_widget_columns
;
628 e
= malloc (sizeof (WEdit
));
629 memset (e
, 0, sizeof (WEdit
));
630 e
->widget
= edit
->widget
;
632 if (!edit_init (e
, lines
, columns
, filename
, text
, dir
, text_size
)) {
637 memcpy (edit
, e
, sizeof (WEdit
));
644 Recording stack for undo:
645 The following is an implementation of a compressed stack. Identical
646 pushes are recorded by a negative prefix indicating the number of times the
647 same char was pushed. This saves space for repeated curs-left or curs-right
664 If the stack long int is 0-255 it represents a normal insert (from a backspace),
665 256-512 is an insert ahead (from a delete), If it is betwen 600 and 700 it is one
666 of the cursor functions #define'd in edit.h. 1000 through 700'000'000 is to
667 set edit->mark1 position. 700'000'000 through 1400'000'000 is to set edit->mark2
670 The only way the cursor moves or the buffer is changed is through the routines:
671 insert, backspace, insert_ahead, delete, and cursor_move.
672 These record the reverse undo movements onto the stack each time they are
675 Each key press results in a set of actions (insert; delete ...). So each time
676 a key is pressed the current position of start_display is pushed as
677 KEY_PRESS + start_display. Then for undoing, we pop until we get to a number
678 over KEY_PRESS. We then assign this number less KEY_PRESS to start_display. So undo
679 tracks scrolling and key actions exactly. (KEY_PRESS is about (2^31) * (2/3) = 1400'000'000)
683 void edit_push_action (WEdit
* edit
, long c
,...)
685 unsigned long sp
= edit
->stack_pointer
;
688 /* first enlarge the stack if necessary */
689 if (sp
> edit
->stack_size
- 10) { /* say */
690 if (option_max_undo
< 256)
691 option_max_undo
= 256;
692 if (edit
->stack_size
< option_max_undo
) {
693 t
= malloc ((edit
->stack_size
* 2 + 10) * sizeof (long));
695 memcpy (t
, edit
->undo_stack
, sizeof (long) * edit
->stack_size
);
696 free (edit
->undo_stack
);
697 edit
->undo_stack
= t
;
698 edit
->stack_size
<<= 1;
699 edit
->stack_size_mask
= edit
->stack_size
- 1;
703 spm1
= (edit
->stack_pointer
- 1) & edit
->stack_size_mask
;
704 if (push_action_disabled
)
707 #ifdef FAST_MOVE_CURSOR
708 if (c
== CURS_LEFT_LOTS
|| c
== CURS_RIGHT_LOTS
) {
710 edit
->undo_stack
[sp
] = c
== CURS_LEFT_LOTS
? CURS_LEFT
: CURS_RIGHT
;
711 edit
->stack_pointer
= (edit
->stack_pointer
+ 1) & edit
->stack_size_mask
;
713 c
= -(va_arg (ap
, int));
716 #endif /* ! FAST_MOVE_CURSOR */
717 if (spm1
!= edit
->stack_bottom
&& ((sp
- 2) & edit
->stack_size_mask
) != edit
->stack_bottom
) {
719 if (edit
->undo_stack
[spm1
] < 0) {
720 d
= edit
->undo_stack
[(sp
- 2) & edit
->stack_size_mask
];
722 if (edit
->undo_stack
[spm1
] > -1000000000) {
723 if (c
< KEY_PRESS
) /* --> no need to push multiple do-nothings */
724 edit
->undo_stack
[spm1
]--;
728 /* #define NO_STACK_CURSMOVE_ANIHILATION */
729 #ifndef NO_STACK_CURSMOVE_ANIHILATION
730 else if ((c
== CURS_LEFT
&& d
== CURS_RIGHT
)
731 || (c
== CURS_RIGHT
&& d
== CURS_LEFT
)) { /* a left then a right anihilate each other */
732 if (edit
->undo_stack
[spm1
] == -2)
733 edit
->stack_pointer
= spm1
;
735 edit
->undo_stack
[spm1
]++;
740 d
= edit
->undo_stack
[spm1
];
743 return; /* --> no need to push multiple do-nothings */
744 edit
->undo_stack
[sp
] = -2;
747 #ifndef NO_STACK_CURSMOVE_ANIHILATION
748 else if ((c
== CURS_LEFT
&& d
== CURS_RIGHT
)
749 || (c
== CURS_RIGHT
&& d
== CURS_LEFT
)) { /* a left then a right anihilate each other */
750 edit
->stack_pointer
= spm1
;
756 edit
->undo_stack
[sp
] = c
;
759 edit
->stack_pointer
= (edit
->stack_pointer
+ 1) & edit
->stack_size_mask
;
761 /*if the sp wraps round and catches the stack_bottom then erase the first set of actions on the stack to make space - by moving stack_bottom forward one "key press" */
762 c
= (edit
->stack_pointer
+ 2) & edit
->stack_size_mask
;
763 if (c
== edit
->stack_bottom
|| ((c
+ 1) & edit
->stack_size_mask
) == edit
->stack_bottom
)
765 edit
->stack_bottom
= (edit
->stack_bottom
+ 1) & edit
->stack_size_mask
;
766 } while (edit
->undo_stack
[edit
->stack_bottom
] < KEY_PRESS
&& edit
->stack_bottom
!= edit
->stack_pointer
);
768 /*If a single key produced enough pushes to wrap all the way round then we would notice that the [stack_bottom] does not contain KEY_PRESS. The stack is then initialised: */
769 if (edit
->stack_pointer
!= edit
->stack_bottom
&& edit
->undo_stack
[edit
->stack_bottom
] < KEY_PRESS
)
770 edit
->stack_bottom
= edit
->stack_pointer
= 0;
774 TODO: if the user undos until the stack bottom, and the stack has not wrapped,
775 then the file should be as it was when he loaded up. Then set edit->modified to 0.
777 long pop_action (WEdit
* edit
)
780 unsigned long sp
= edit
->stack_pointer
;
781 if (sp
== edit
->stack_bottom
) {
784 sp
= (sp
- 1) & edit
->stack_size_mask
;
785 if ((c
= edit
->undo_stack
[sp
]) >= 0) {
786 /* edit->undo_stack[sp] = '@'; */
787 edit
->stack_pointer
= (edit
->stack_pointer
- 1) & edit
->stack_size_mask
;
790 if (sp
== edit
->stack_bottom
) {
793 c
= edit
->undo_stack
[(sp
- 1) & edit
->stack_size_mask
];
794 if (edit
->undo_stack
[sp
] == -2) {
795 /* edit->undo_stack[sp] = '@'; */
796 edit
->stack_pointer
= sp
;
798 edit
->undo_stack
[sp
]++;
803 /* is called whenever a modification is made by one of the four routines below */
804 static inline void edit_modification (WEdit
* edit
)
806 edit
->caches_valid
= 0;
808 edit
->screen_modified
= 1;
812 Basic low level single character buffer alterations and movements at the cursor.
813 Returns char passed over, inserted or removed.
816 void edit_insert (WEdit
* edit
, int c
)
818 /* check if file has grown to large */
819 if (edit
->last_byte
>= SIZE_LIMIT
)
822 /* first we must update the position of the display window */
823 if (edit
->curs1
< edit
->start_display
) {
824 edit
->start_display
++;
828 /* now we must update some info on the file and check if a redraw is required */
831 book_mark_inc (edit
, edit
->curs_line
);
834 edit
->force
|= REDRAW_LINE_ABOVE
| REDRAW_AFTER_CURSOR
;
836 /* tell that we've modified the file */
837 edit_modification (edit
);
839 /* save the reverse command onto the undo stack */
840 edit_push_action (edit
, BACKSPACE
);
843 edit
->mark1
+= (edit
->mark1
> edit
->curs1
);
844 edit
->mark2
+= (edit
->mark2
> edit
->curs1
);
845 edit
->last_get_rule
+= (edit
->last_get_rule
> edit
->curs1
);
847 /* add a new buffer if we've reached the end of the last one */
848 if (!(edit
->curs1
& M_EDIT_BUF_SIZE
))
849 edit
->buffers1
[edit
->curs1
>> S_EDIT_BUF_SIZE
] = malloc (EDIT_BUF_SIZE
);
851 /* perfprm the insertion */
852 edit
->buffers1
[edit
->curs1
>> S_EDIT_BUF_SIZE
][edit
->curs1
& M_EDIT_BUF_SIZE
] = (unsigned char) c
;
854 /* update file length */
857 /* update cursor position */
862 /* same as edit_insert and move left */
863 void edit_insert_ahead (WEdit
* edit
, int c
)
865 if (edit
->last_byte
>= SIZE_LIMIT
)
867 if (edit
->curs1
< edit
->start_display
) {
868 edit
->start_display
++;
874 book_mark_inc (edit
, edit
->curs_line
);
876 edit
->force
|= REDRAW_AFTER_CURSOR
;
878 edit_modification (edit
);
879 edit_push_action (edit
, DELETE
);
881 edit
->mark1
+= (edit
->mark1
>= edit
->curs1
);
882 edit
->mark2
+= (edit
->mark2
>= edit
->curs1
);
883 edit
->last_get_rule
+= (edit
->last_get_rule
>= edit
->curs1
);
885 if (!((edit
->curs2
+ 1) & M_EDIT_BUF_SIZE
))
886 edit
->buffers2
[(edit
->curs2
+ 1) >> S_EDIT_BUF_SIZE
] = malloc (EDIT_BUF_SIZE
);
887 edit
->buffers2
[edit
->curs2
>> S_EDIT_BUF_SIZE
][EDIT_BUF_SIZE
- (edit
->curs2
& M_EDIT_BUF_SIZE
) - 1] = c
;
894 int edit_delete (WEdit
* edit
)
900 edit
->mark1
-= (edit
->mark1
> edit
->curs1
);
901 edit
->mark2
-= (edit
->mark2
> edit
->curs1
);
902 edit
->last_get_rule
-= (edit
->last_get_rule
> edit
->curs1
);
904 p
= edit
->buffers2
[(edit
->curs2
- 1) >> S_EDIT_BUF_SIZE
][EDIT_BUF_SIZE
- ((edit
->curs2
- 1) & M_EDIT_BUF_SIZE
) - 1];
906 if (!(edit
->curs2
& M_EDIT_BUF_SIZE
)) {
907 free (edit
->buffers2
[edit
->curs2
>> S_EDIT_BUF_SIZE
]);
908 edit
->buffers2
[edit
->curs2
>> S_EDIT_BUF_SIZE
] = NULL
;
915 book_mark_dec (edit
, edit
->curs_line
);
917 edit
->force
|= REDRAW_AFTER_CURSOR
;
919 edit_push_action (edit
, p
+ 256);
920 if (edit
->curs1
< edit
->start_display
) {
921 edit
->start_display
--;
925 edit_modification (edit
);
931 int edit_backspace (WEdit
* edit
)
937 edit
->mark1
-= (edit
->mark1
>= edit
->curs1
);
938 edit
->mark2
-= (edit
->mark2
>= edit
->curs1
);
939 edit
->last_get_rule
-= (edit
->last_get_rule
>= edit
->curs1
);
941 p
= *(edit
->buffers1
[(edit
->curs1
- 1) >> S_EDIT_BUF_SIZE
] + ((edit
->curs1
- 1) & M_EDIT_BUF_SIZE
));
942 if (!((edit
->curs1
- 1) & M_EDIT_BUF_SIZE
)) {
943 free (edit
->buffers1
[edit
->curs1
>> S_EDIT_BUF_SIZE
]);
944 edit
->buffers1
[edit
->curs1
>> S_EDIT_BUF_SIZE
] = NULL
;
951 book_mark_dec (edit
, edit
->curs_line
);
954 edit
->force
|= REDRAW_AFTER_CURSOR
;
956 edit_push_action (edit
, p
);
958 if (edit
->curs1
< edit
->start_display
) {
959 edit
->start_display
--;
963 edit_modification (edit
);
968 #ifdef FAST_MOVE_CURSOR
970 static void memqcpy (WEdit
* edit
, unsigned char *dest
, unsigned char *src
, int n
)
973 while ((next
= (unsigned long) memccpy (dest
, src
, '\n', n
))) {
975 next
-= (unsigned long) dest
;
982 int edit_move_backward_lots (WEdit
* edit
, long increment
)
987 if (increment
> edit
->curs1
)
988 increment
= edit
->curs1
;
991 edit_push_action (edit
, CURS_RIGHT_LOTS
, increment
);
993 t
= r
= EDIT_BUF_SIZE
- (edit
->curs2
& M_EDIT_BUF_SIZE
);
996 s
= edit
->curs1
& M_EDIT_BUF_SIZE
;
1000 memqcpy (edit
, edit
->buffers2
[edit
->curs2
>> S_EDIT_BUF_SIZE
] + t
- r
,
1001 edit
->buffers1
[edit
->curs1
>> S_EDIT_BUF_SIZE
] + s
- r
, r
);
1004 memqcpy (edit
, edit
->buffers2
[edit
->curs2
>> S_EDIT_BUF_SIZE
] + t
- s
,
1005 edit
->buffers1
[edit
->curs1
>> S_EDIT_BUF_SIZE
], s
);
1006 p
= edit
->buffers1
[edit
->curs1
>> S_EDIT_BUF_SIZE
];
1007 edit
->buffers1
[edit
->curs1
>> S_EDIT_BUF_SIZE
] = 0;
1009 memqcpy (edit
, edit
->buffers2
[edit
->curs2
>> S_EDIT_BUF_SIZE
] + t
- r
,
1010 edit
->buffers1
[(edit
->curs1
>> S_EDIT_BUF_SIZE
) - 1] + EDIT_BUF_SIZE
- (r
- s
), r
- s
);
1015 if (!(edit
->curs2
& M_EDIT_BUF_SIZE
)) {
1017 edit
->buffers2
[edit
->curs2
>> S_EDIT_BUF_SIZE
] = p
;
1019 edit
->buffers2
[edit
->curs2
>> S_EDIT_BUF_SIZE
] = malloc (EDIT_BUF_SIZE
);
1025 s
= edit
->curs1
& M_EDIT_BUF_SIZE
;
1035 edit
->buffers2
[edit
->curs2
>> S_EDIT_BUF_SIZE
] + EDIT_BUF_SIZE
- t
,
1036 edit
->buffers1
[edit
->curs1
>> S_EDIT_BUF_SIZE
] + s
- t
,
1040 p
= edit
->buffers1
[edit
->curs1
>> S_EDIT_BUF_SIZE
];
1041 edit
->buffers1
[edit
->curs1
>> S_EDIT_BUF_SIZE
] = 0;
1044 edit
->buffers2
[edit
->curs2
>> S_EDIT_BUF_SIZE
] + EDIT_BUF_SIZE
- r
,
1045 edit
->buffers1
[(edit
->curs1
>> S_EDIT_BUF_SIZE
) - 1] + EDIT_BUF_SIZE
- (r
- s
),
1051 if (!(edit
->curs2
& M_EDIT_BUF_SIZE
)) {
1053 edit
->buffers2
[edit
->curs2
>> S_EDIT_BUF_SIZE
] = p
;
1055 edit
->buffers2
[edit
->curs2
>> S_EDIT_BUF_SIZE
] = malloc (EDIT_BUF_SIZE
);
1061 return edit_get_byte (edit
, edit
->curs1
);
1064 #endif /* ! FAST_MOVE_CURSOR */
1066 /* moves the cursor right or left: increment positive or negative respectively */
1067 int edit_cursor_move (WEdit
* edit
, long increment
)
1069 /* this is the same as a combination of two of the above routines, with only one push onto the undo stack */
1072 #ifdef FAST_MOVE_CURSOR
1073 if (increment
< -256) {
1074 edit
->force
|= REDRAW_PAGE
;
1075 return edit_move_backward_lots (edit
, -increment
);
1077 #endif /* ! FAST_MOVE_CURSOR */
1079 if (increment
< 0) {
1080 for (; increment
< 0; increment
++) {
1084 edit_push_action (edit
, CURS_RIGHT
);
1086 c
= edit_get_byte (edit
, edit
->curs1
- 1);
1087 if (!((edit
->curs2
+ 1) & M_EDIT_BUF_SIZE
))
1088 edit
->buffers2
[(edit
->curs2
+ 1) >> S_EDIT_BUF_SIZE
] = malloc (EDIT_BUF_SIZE
);
1089 edit
->buffers2
[edit
->curs2
>> S_EDIT_BUF_SIZE
][EDIT_BUF_SIZE
- (edit
->curs2
& M_EDIT_BUF_SIZE
) - 1] = c
;
1091 c
= edit
->buffers1
[(edit
->curs1
- 1) >> S_EDIT_BUF_SIZE
][(edit
->curs1
- 1) & M_EDIT_BUF_SIZE
];
1092 if (!((edit
->curs1
- 1) & M_EDIT_BUF_SIZE
)) {
1093 free (edit
->buffers1
[edit
->curs1
>> S_EDIT_BUF_SIZE
]);
1094 edit
->buffers1
[edit
->curs1
>> S_EDIT_BUF_SIZE
] = NULL
;
1099 edit
->force
|= REDRAW_LINE_BELOW
;
1104 } else if (increment
> 0) {
1105 for (; increment
> 0; increment
--) {
1109 edit_push_action (edit
, CURS_LEFT
);
1111 c
= edit_get_byte (edit
, edit
->curs1
);
1112 if (!(edit
->curs1
& M_EDIT_BUF_SIZE
))
1113 edit
->buffers1
[edit
->curs1
>> S_EDIT_BUF_SIZE
] = malloc (EDIT_BUF_SIZE
);
1114 edit
->buffers1
[edit
->curs1
>> S_EDIT_BUF_SIZE
][edit
->curs1
& M_EDIT_BUF_SIZE
] = c
;
1116 c
= edit
->buffers2
[(edit
->curs2
- 1) >> S_EDIT_BUF_SIZE
][EDIT_BUF_SIZE
- ((edit
->curs2
- 1) & M_EDIT_BUF_SIZE
) - 1];
1117 if (!(edit
->curs2
& M_EDIT_BUF_SIZE
)) {
1118 free (edit
->buffers2
[edit
->curs2
>> S_EDIT_BUF_SIZE
]);
1119 edit
->buffers2
[edit
->curs2
>> S_EDIT_BUF_SIZE
] = 0;
1124 edit
->force
|= REDRAW_LINE_ABOVE
;
1132 /* These functions return positions relative to lines */
1134 /* returns index of last char on line + 1 */
1135 long edit_eol (WEdit
* edit
, long current
)
1137 if (current
< edit
->last_byte
) {
1139 if (edit_get_byte (edit
, current
) == '\n')
1142 return edit
->last_byte
;
1146 /* returns index of first char on line */
1147 long edit_bol (WEdit
* edit
, long current
)
1151 if (edit_get_byte (edit
, current
- 1) == '\n')
1159 int edit_count_lines (WEdit
* edit
, long current
, int upto
)
1162 if (upto
> edit
->last_byte
)
1163 upto
= edit
->last_byte
;
1166 while (current
< upto
)
1167 if (edit_get_byte (edit
, current
++) == '\n')
1173 /* If lines is zero this returns the count of lines from current to upto. */
1174 /* If upto is zero returns index of lines forward current. */
1175 long edit_move_forward (WEdit
* edit
, long current
, int lines
, long upto
)
1178 return edit_count_lines (edit
, current
, upto
);
1184 next
= edit_eol (edit
, current
) + 1;
1185 if (next
> edit
->last_byte
)
1195 /* Returns offset of 'lines' lines up from current */
1196 long edit_move_backward (WEdit
* edit
, long current
, int lines
)
1200 current
= edit_bol (edit
, current
);
1201 while((lines
--) && current
!= 0)
1202 current
= edit_bol (edit
, current
- 1);
1207 /* If cols is zero this returns the count of columns from current to upto. */
1208 /* If upto is zero returns index of cols across from current. */
1209 long edit_move_forward3 (WEdit
* edit
, long current
, int cols
, long upto
)
1218 q
= edit
->last_byte
+ 2;
1220 for (col
= 0, p
= current
; p
< q
; p
++) {
1228 c
= edit_get_byte (edit
, p
);
1233 col
+= TAB_SIZE
- col
% TAB_SIZE
;
1236 /*if(edit->nroff ... */
1248 /* returns the current column position of the cursor */
1249 int edit_get_col (WEdit
* edit
)
1251 return edit_move_forward3 (edit
, edit_bol (edit
, edit
->curs1
), 0, edit
->curs1
);
1255 /* Scrolling functions */
1257 void edit_update_curs_row (WEdit
* edit
)
1259 edit
->curs_row
= edit
->curs_line
- edit
->start_line
;
1262 void edit_update_curs_col (WEdit
* edit
)
1264 edit
->curs_col
= edit_move_forward3(edit
, edit_bol(edit
, edit
->curs1
), 0, edit
->curs1
);
1267 /*moves the display start position up by i lines */
1268 void edit_scroll_upward (WEdit
* edit
, unsigned long i
)
1270 int lines_above
= edit
->start_line
;
1271 if (i
> lines_above
)
1274 edit
->start_line
-= i
;
1275 edit
->start_display
= edit_move_backward (edit
, edit
->start_display
, i
);
1276 edit
->force
|= REDRAW_PAGE
;
1277 edit
->force
&= (0xfff - REDRAW_CHAR_ONLY
);
1281 edit_update_curs_row (edit
);
1285 /* returns 1 if could scroll, 0 otherwise */
1286 void edit_scroll_downward (WEdit
* edit
, int i
)
1289 lines_below
= edit
->total_lines
- edit
->start_line
- (edit
->num_widget_lines
- 1);
1290 if (lines_below
> 0) {
1291 if (i
> lines_below
)
1293 edit
->start_line
+= i
;
1294 edit
->start_display
= edit_move_forward (edit
, edit
->start_display
, i
, 0);
1295 edit
->force
|= REDRAW_PAGE
;
1296 edit
->force
&= (0xfff - REDRAW_CHAR_ONLY
);
1300 edit_update_curs_row (edit
);
1303 void edit_scroll_right (WEdit
* edit
, int i
)
1305 edit
->force
|= REDRAW_PAGE
;
1306 edit
->force
&= (0xfff - REDRAW_CHAR_ONLY
);
1307 edit
->start_col
-= i
;
1310 void edit_scroll_left (WEdit
* edit
, int i
)
1312 if (edit
->start_col
) {
1313 edit
->start_col
+= i
;
1314 if (edit
->start_col
> 0)
1315 edit
->start_col
= 0;
1316 edit
->force
|= REDRAW_PAGE
;
1317 edit
->force
&= (0xfff - REDRAW_CHAR_ONLY
);
1321 /* high level cursor movement commands */
1323 static int is_in_indent (WEdit
*edit
)
1325 long p
= edit_bol (edit
, edit
->curs1
);
1326 while (p
< edit
->curs1
)
1327 if (!strchr (" \t", edit_get_byte (edit
, p
++)))
1332 static int left_of_four_spaces (WEdit
*edit
);
1334 void edit_move_to_prev_col (WEdit
* edit
, long p
)
1336 edit_cursor_move (edit
, edit_move_forward3 (edit
, p
, edit
->prev_col
, 0) - edit
->curs1
);
1338 if (is_in_indent (edit
) && option_fake_half_tabs
) {
1339 edit_update_curs_col (edit
);
1341 if (edit
->curs_col
% (HALF_TAB_SIZE
* space_width
)) {
1342 int q
= edit
->curs_col
;
1343 edit
->curs_col
-= (edit
->curs_col
% (HALF_TAB_SIZE
* space_width
));
1344 p
= edit_bol (edit
, edit
->curs1
);
1345 edit_cursor_move (edit
, edit_move_forward3 (edit
, p
, edit
->curs_col
, 0) - edit
->curs1
);
1346 if (!left_of_four_spaces (edit
))
1347 edit_cursor_move (edit
, edit_move_forward3 (edit
, p
, q
, 0) - edit
->curs1
);
1354 void edit_move_up (WEdit
* edit
, unsigned long i
, int scroll
)
1356 long p
, l
= edit
->curs_line
;
1362 edit
->force
|= REDRAW_PAGE
;
1364 edit_scroll_upward (edit
, i
);
1366 p
= edit_bol (edit
, edit
->curs1
);
1367 edit_cursor_move (edit
, (p
= edit_move_backward (edit
, p
, i
)) - edit
->curs1
);
1368 edit_move_to_prev_col (edit
, p
);
1370 edit
->search_start
= edit
->curs1
;
1371 edit
->found_len
= 0;
1375 int is_blank (WEdit
* edit
, long offset
)
1379 s
= edit_bol (edit
, offset
);
1380 f
= edit_eol (edit
, offset
) - 1;
1382 c
= edit_get_byte (edit
, s
++);
1390 /* returns the offset of line i */
1391 long edit_find_line (WEdit
* edit
, int line
)
1395 if (!edit
->caches_valid
) {
1396 for (i
= 0; i
< N_LINE_CACHES
; i
++)
1397 edit
->line_numbers
[i
] = edit
->line_offsets
[i
] = 0;
1398 /* three offsets that we *know* are line 0 at 0 and these two: */
1399 edit
->line_numbers
[1] = edit
->curs_line
;
1400 edit
->line_offsets
[1] = edit_bol (edit
, edit
->curs1
);
1401 edit
->line_numbers
[2] = edit
->total_lines
;
1402 edit
->line_offsets
[2] = edit_bol (edit
, edit
->last_byte
);
1403 edit
->caches_valid
= 1;
1405 if (line
>= edit
->total_lines
)
1406 return edit
->line_offsets
[2];
1409 /* find the closest known point */
1410 for (i
= 0; i
< N_LINE_CACHES
; i
++) {
1412 n
= abs (edit
->line_numbers
[i
] - line
);
1419 return edit
->line_offsets
[j
]; /* know the offset exactly */
1420 if (m
== 1 && j
>= 3)
1421 i
= j
; /* one line different - caller might be looping, so stay in this cache */
1423 i
= 3 + (rand () % (N_LINE_CACHES
- 3));
1424 if (line
> edit
->line_numbers
[j
])
1425 edit
->line_offsets
[i
] = edit_move_forward (edit
, edit
->line_offsets
[j
], line
- edit
->line_numbers
[j
], 0);
1427 edit
->line_offsets
[i
] = edit_move_backward (edit
, edit
->line_offsets
[j
], edit
->line_numbers
[j
] - line
);
1428 edit
->line_numbers
[i
] = line
;
1429 return edit
->line_offsets
[i
];
1432 int line_is_blank (WEdit
* edit
, long line
)
1434 return is_blank (edit
, edit_find_line (edit
, line
));
1437 /* moves up until a blank line is reached, or until just
1438 before a non-blank line is reached */
1439 static void edit_move_up_paragraph (WEdit
* edit
, int scroll
)
1442 if (edit
->curs_line
<= 1) {
1445 if (line_is_blank (edit
, edit
->curs_line
)) {
1446 if (line_is_blank (edit
, edit
->curs_line
- 1)) {
1447 for (i
= edit
->curs_line
- 1; i
; i
--)
1448 if (!line_is_blank (edit
, i
)) {
1453 for (i
= edit
->curs_line
- 1; i
; i
--)
1454 if (line_is_blank (edit
, i
))
1458 for (i
= edit
->curs_line
- 1; i
; i
--)
1459 if (line_is_blank (edit
, i
))
1463 edit_move_up (edit
, edit
->curs_line
- i
, scroll
);
1467 void edit_move_down (WEdit
* edit
, int i
, int scroll
)
1469 long p
, l
= edit
->total_lines
- edit
->curs_line
;
1475 edit
->force
|= REDRAW_PAGE
;
1477 edit_scroll_downward (edit
, i
);
1478 p
= edit_bol (edit
, edit
->curs1
);
1479 edit_cursor_move (edit
, (p
= edit_move_forward (edit
, p
, i
, 0)) - edit
->curs1
);
1480 edit_move_to_prev_col (edit
, p
);
1482 edit
->search_start
= edit
->curs1
;
1483 edit
->found_len
= 0;
1487 /* moves down until a blank line is reached, or until just
1488 before a non-blank line is reached */
1489 static void edit_move_down_paragraph (WEdit
* edit
, int scroll
)
1492 if (edit
->curs_line
>= edit
->total_lines
- 1) {
1493 i
= edit
->total_lines
;
1495 if (line_is_blank (edit
, edit
->curs_line
)) {
1496 if (line_is_blank (edit
, edit
->curs_line
+ 1)) {
1497 for (i
= edit
->curs_line
+ 1; i
; i
++)
1498 if (!line_is_blank (edit
, i
) || i
> edit
->total_lines
) {
1503 for (i
= edit
->curs_line
+ 1; i
; i
++)
1504 if (line_is_blank (edit
, i
) || i
>= edit
->total_lines
)
1508 for (i
= edit
->curs_line
+ 1; i
; i
++)
1509 if (line_is_blank (edit
, i
) || i
>= edit
->total_lines
)
1513 edit_move_down (edit
, i
- edit
->curs_line
, scroll
);
1516 static void edit_begin_page (WEdit
*edit
)
1518 edit_update_curs_row (edit
);
1519 edit_move_up (edit
, edit
->curs_row
, 0);
1522 static void edit_end_page (WEdit
*edit
)
1524 edit_update_curs_row (edit
);
1525 edit_move_down (edit
, edit
->num_widget_lines
- edit
->curs_row
- 1, 0);
1529 /* goto beginning of text */
1530 static void edit_move_to_top (WEdit
* edit
)
1532 if (edit
->curs_line
) {
1533 edit_cursor_move (edit
, -edit
->curs1
);
1534 edit_move_to_prev_col (edit
, 0);
1535 edit
->force
|= REDRAW_PAGE
;
1536 edit
->search_start
= 0;
1537 edit_update_curs_row(edit
);
1542 /* goto end of text */
1543 static void edit_move_to_bottom (WEdit
* edit
)
1545 if (edit
->curs_line
< edit
->total_lines
) {
1546 edit_cursor_move (edit
, edit
->curs2
);
1547 edit
->start_display
= edit
->last_byte
;
1548 edit
->start_line
= edit
->total_lines
;
1549 edit_update_curs_row(edit
);
1550 edit_scroll_upward (edit
, edit
->num_widget_lines
- 1);
1551 edit
->force
|= REDRAW_PAGE
;
1555 /* goto beginning of line */
1556 static void edit_cursor_to_bol (WEdit
* edit
)
1558 edit_cursor_move (edit
, edit_bol (edit
, edit
->curs1
) - edit
->curs1
);
1559 edit
->search_start
= edit
->curs1
;
1560 edit
->prev_col
= edit_get_col (edit
);
1563 /* goto end of line */
1564 static void edit_cursor_to_eol (WEdit
* edit
)
1566 edit_cursor_move (edit
, edit_eol (edit
, edit
->curs1
) - edit
->curs1
);
1567 edit
->search_start
= edit
->curs1
;
1568 edit
->prev_col
= edit_get_col (edit
);
1571 /* move cursor to line 'line' */
1572 void edit_move_to_line (WEdit
* e
, long line
)
1574 if(line
< e
->curs_line
)
1575 edit_move_up (e
, e
->curs_line
- line
, 0);
1577 edit_move_down (e
, line
- e
->curs_line
, 0);
1578 edit_scroll_screen_over_cursor (e
);
1581 /* scroll window so that first visible line is 'line' */
1582 void edit_move_display (WEdit
* e
, long line
)
1584 if(line
< e
->start_line
)
1585 edit_scroll_upward (e
, e
->start_line
- line
);
1587 edit_scroll_downward (e
, line
- e
->start_line
);
1590 /* save markers onto undo stack */
1591 void edit_push_markers (WEdit
* edit
)
1593 edit_push_action (edit
, MARK_1
+ edit
->mark1
);
1594 edit_push_action (edit
, MARK_2
+ edit
->mark2
);
1597 void free_selections (void)
1600 for (i
= 0; i
< NUM_SELECTION_HISTORY
; i
++)
1601 if (selection_history
[i
].text
) {
1602 free (selection_history
[i
].text
);
1603 selection_history
[i
].text
= 0;
1604 selection_history
[i
].len
= 0;
1606 current_selection
= 0;
1609 /* return -1 on nothing to store or error, zero otherwise */
1610 void edit_get_selection (WEdit
* edit
)
1612 long start_mark
, end_mark
;
1613 if (eval_marks (edit
, &start_mark
, &end_mark
))
1615 if (selection_history
[current_selection
].len
< 4096) /* large selections should not be held -- to save memory */
1616 current_selection
= (current_selection
+ 1) % NUM_SELECTION_HISTORY
;
1617 selection_history
[current_selection
].len
= end_mark
- start_mark
;
1618 if (selection_history
[current_selection
].text
)
1619 free (selection_history
[current_selection
].text
);
1620 selection_history
[current_selection
].text
= malloc (selection_history
[current_selection
].len
+ 1);
1621 if (!selection_history
[current_selection
].text
) {
1622 selection_history
[current_selection
].text
= malloc (1);
1623 *selection_history
[current_selection
].text
= 0;
1624 selection_history
[current_selection
].len
= 0;
1626 unsigned char *p
= selection_history
[current_selection
].text
;
1627 for (; start_mark
< end_mark
; start_mark
++)
1628 *p
++ = edit_get_byte (edit
, start_mark
);
1631 selection
.text
= selection_history
[current_selection
].text
;
1632 selection
.len
= selection_history
[current_selection
].len
;
1635 void edit_set_markers (WEdit
* edit
, long m1
, long m2
, int c1
, int c2
)
1644 /* highlight marker toggle */
1645 void edit_mark_cmd (WEdit
* edit
, int unmark
)
1647 edit_push_markers (edit
);
1649 edit_set_markers (edit
, 0, 0, 0, 0);
1650 edit
->force
|= REDRAW_PAGE
;
1652 if (edit
->mark2
>= 0) {
1653 edit_set_markers (edit
, edit
->curs1
, -1, edit
->curs_col
, edit
->curs_col
);
1654 edit
->force
|= REDRAW_PAGE
;
1656 edit_set_markers (edit
, edit
->mark1
, edit
->curs1
, edit
->column1
, edit
->curs_col
);
1660 static unsigned long my_type_of (int c
)
1667 if (*option_chars_move_whole_word
== '!')
1669 return 0x80000000UL
;
1673 else if (islower (c
))
1675 else if (isalpha (c
))
1677 else if (isdigit (c
))
1679 else if (isspace (c
))
1681 q
= strchr (option_chars_move_whole_word
, c
);
1683 return 0xFFFFFFFFUL
;
1685 for (x
= 1, p
= option_chars_move_whole_word
; (unsigned long) p
< (unsigned long) q
; p
++)
1689 } while ((q
= strchr (q
+ 1, c
)));
1693 void edit_left_word_move (WEdit
* edit
, int s
)
1697 edit_cursor_move (edit
, -1);
1700 c1
= edit_get_byte (edit
, edit
->curs1
- 1);
1701 c2
= edit_get_byte (edit
, edit
->curs1
);
1702 if (!(my_type_of (c1
) & my_type_of (c2
)))
1704 if (isspace (c1
) && !isspace (c2
))
1707 if (!isspace (c1
) && isspace (c2
))
1712 static void edit_left_word_move_cmd (WEdit
* edit
)
1714 edit_left_word_move (edit
, 0);
1715 edit
->force
|= REDRAW_PAGE
;
1718 void edit_right_word_move (WEdit
* edit
, int s
)
1722 edit_cursor_move (edit
, 1);
1723 if (edit
->curs1
>= edit
->last_byte
)
1725 c1
= edit_get_byte (edit
, edit
->curs1
- 1);
1726 c2
= edit_get_byte (edit
, edit
->curs1
);
1727 if (!(my_type_of (c1
) & my_type_of (c2
)))
1729 if (isspace (c1
) && !isspace (c2
))
1732 if (!isspace (c1
) && isspace (c2
))
1737 static void edit_right_word_move_cmd (WEdit
* edit
)
1739 edit_right_word_move (edit
, 0);
1740 edit
->force
|= REDRAW_PAGE
;
1744 static void edit_right_delete_word (WEdit
* edit
)
1748 if (edit
->curs1
>= edit
->last_byte
)
1750 c1
= edit_delete (edit
);
1751 c2
= edit_get_byte (edit
, edit
->curs1
);
1752 if ((isspace (c1
) == 0) != (isspace (c2
) == 0))
1754 if (!(my_type_of (c1
) & my_type_of (c2
)))
1759 static void edit_left_delete_word (WEdit
* edit
)
1763 if (edit
->curs1
<= 0)
1765 c1
= edit_backspace (edit
);
1766 c2
= edit_get_byte (edit
, edit
->curs1
- 1);
1767 if ((isspace (c1
) == 0) != (isspace (c2
) == 0))
1769 if (!(my_type_of (c1
) & my_type_of (c2
)))
1774 extern int column_highlighting
;
1777 the start column position is not recorded, and hence does not
1778 undo as it happed. But who would notice.
1780 void edit_do_undo (WEdit
* edit
)
1785 push_action_disabled
= 1; /* don't record undo's onto undo stack! */
1787 while ((ac
= pop_action (edit
)) < KEY_PRESS
) {
1792 edit_cursor_move (edit
, 1);
1795 edit_cursor_move (edit
, -1);
1798 edit_backspace (edit
);
1804 column_highlighting
= 1;
1807 column_highlighting
= 0;
1810 if (ac
>= 256 && ac
< 512)
1811 edit_insert_ahead (edit
, ac
- 256);
1812 if (ac
>= 0 && ac
< 256)
1813 edit_insert (edit
, ac
);
1815 if (ac
>= MARK_1
- 2 && ac
< MARK_2
- 2) {
1816 edit
->mark1
= ac
- MARK_1
;
1817 edit
->column1
= edit_move_forward3 (edit
, edit_bol (edit
, edit
->mark1
), 0, edit
->mark1
);
1818 } else if (ac
>= MARK_2
- 2 && ac
< KEY_PRESS
) {
1819 edit
->mark2
= ac
- MARK_2
;
1820 edit
->column2
= edit_move_forward3 (edit
, edit_bol (edit
, edit
->mark2
), 0, edit
->mark2
);
1823 edit
->force
|= REDRAW_PAGE
; /* more than one pop usually means something big */
1826 if (edit
->start_display
> ac
- KEY_PRESS
) {
1827 edit
->start_line
-= edit_count_lines (edit
, ac
- KEY_PRESS
, edit
->start_display
);
1828 edit
->force
|= REDRAW_PAGE
;
1829 } else if (edit
->start_display
< ac
- KEY_PRESS
) {
1830 edit
->start_line
+= edit_count_lines (edit
, edit
->start_display
, ac
- KEY_PRESS
);
1831 edit
->force
|= REDRAW_PAGE
;
1833 edit
->start_display
= ac
- KEY_PRESS
; /* see push and pop above */
1834 edit_update_curs_row (edit
);
1837 push_action_disabled
= 0;
1840 static void edit_delete_to_line_end (WEdit
* edit
)
1842 while (edit_get_byte (edit
, edit
->curs1
) != '\n') {
1849 static void edit_delete_to_line_begin (WEdit
* edit
)
1851 while (edit_get_byte (edit
, edit
->curs1
- 1) != '\n') {
1854 edit_backspace (edit
);
1858 void edit_delete_line (WEdit
* edit
)
1862 c
= edit_delete (edit
);
1863 } while (c
!= '\n' && c
);
1865 c
= edit_backspace (edit
);
1866 } while (c
!= '\n' && c
);
1868 edit_insert (edit
, '\n');
1871 static void insert_spaces_tab (WEdit
* edit
, int half
)
1874 edit_update_curs_col (edit
);
1875 i
= ((edit
->curs_col
/ (option_tab_spacing
* space_width
/ (half
+ 1))) + 1) * (option_tab_spacing
* space_width
/ (half
+ 1)) - edit
->curs_col
;
1877 edit_insert (edit
, ' ');
1882 static int is_aligned_on_a_tab (WEdit
* edit
)
1884 edit_update_curs_col (edit
);
1885 if ((edit
->curs_col
% (TAB_SIZE
* space_width
)) && edit
->curs_col
% (TAB_SIZE
* space_width
) != (HALF_TAB_SIZE
* space_width
))
1886 return 0; /* not alligned on a tab */
1890 static int right_of_four_spaces (WEdit
*edit
)
1893 for (i
= 1; i
<= HALF_TAB_SIZE
; i
++)
1894 ch
|= edit_get_byte (edit
, edit
->curs1
- i
);
1896 return is_aligned_on_a_tab (edit
);
1900 static int left_of_four_spaces (WEdit
*edit
)
1903 for (i
= 0; i
< HALF_TAB_SIZE
; i
++)
1904 ch
|= edit_get_byte (edit
, edit
->curs1
+ i
);
1906 return is_aligned_on_a_tab (edit
);
1910 int edit_indent_width (WEdit
* edit
, long p
)
1913 while (strchr ("\t ", edit_get_byte (edit
, q
)) && q
< edit
->last_byte
- 1) /* move to the end of the leading whitespace of the line */
1915 return edit_move_forward3 (edit
, p
, 0, q
); /* count the number of columns of indentation */
1918 void edit_insert_indent (WEdit
* edit
, int indent
)
1921 indent
/= space_width
;
1923 if (!option_fill_tabs_with_spaces
) {
1924 while (indent
>= TAB_SIZE
) {
1925 edit_insert (edit
, '\t');
1929 while (indent
-- > 0)
1930 edit_insert (edit
, ' ');
1933 void edit_auto_indent (WEdit
* edit
, int extra
, int no_advance
)
1938 while (isspace (edit_get_byte (edit
, p
- 1)) && p
> 0) /* move back/up to a line with text */
1940 indent
= edit_indent_width (edit
, edit_bol (edit
, p
));
1941 if (edit
->curs_col
< indent
&& no_advance
)
1942 indent
= edit
->curs_col
;
1943 edit_insert_indent (edit
, indent
+ (option_fake_half_tabs
? HALF_TAB_SIZE
: TAB_SIZE
) * space_width
* extra
);
1946 static void edit_double_newline (WEdit
* edit
)
1948 edit_insert (edit
, '\n');
1949 if (edit_get_byte (edit
, edit
->curs1
) == '\n')
1951 if (edit_get_byte (edit
, edit
->curs1
- 2) == '\n')
1953 edit
->force
|= REDRAW_PAGE
;
1954 edit_insert (edit
, '\n');
1957 static void edit_tab_cmd (WEdit
* edit
)
1961 if (option_fake_half_tabs
) {
1962 if (is_in_indent (edit
)) {
1963 /*insert a half tab (usually four spaces) unless there is a
1964 half tab already behind, then delete it and insert a
1966 if (!option_fill_tabs_with_spaces
&& right_of_four_spaces (edit
)) {
1967 for (i
= 1; i
<= HALF_TAB_SIZE
; i
++)
1968 edit_backspace (edit
);
1969 edit_insert (edit
, '\t');
1971 insert_spaces_tab (edit
, 1);
1976 if (option_fill_tabs_with_spaces
) {
1977 insert_spaces_tab (edit
, 0);
1979 edit_insert (edit
, '\t');
1984 void format_paragraph (WEdit
* edit
, int force
);
1986 static void check_and_wrap_line (WEdit
* edit
)
1989 if (!option_typewriter_wrap
)
1991 edit_update_curs_col (edit
);
1993 if (edit
->curs_col
< option_word_wrap_line_length
)
1996 CPushFont ("editor", 0);
1997 c
= FONT_MEAN_WIDTH
;
1999 if (edit
->curs_col
< option_word_wrap_line_length
* c
)
2005 c
= edit_get_byte (edit
, curs
);
2006 if (c
== '\n' || curs
<= 0) {
2007 edit_insert (edit
, '\n');
2010 if (c
== ' ' || c
== '\t') {
2011 int current
= edit
->curs1
;
2012 edit_cursor_move (edit
, curs
- edit
->curs1
+ 1);
2013 edit_insert (edit
, '\n');
2014 edit_cursor_move (edit
, current
- edit
->curs1
+ 1);
2020 void edit_execute_macro (WEdit
* edit
, struct macro macro
[], int n
);
2022 /* either command or char_for_insertion must be passed as -1 */
2023 int edit_execute_cmd (WEdit
* edit
, int command
, int char_for_insertion
);
2026 int edit_translate_key (WEdit
* edit
, unsigned int x_keycode
, long x_key
, int x_state
, int *cmd
, int *ch
)
2029 int char_for_insertion
= -1;
2031 #include "edit_key_translator.c"
2034 *ch
= char_for_insertion
;
2036 if((command
== -1 || command
== 0) && char_for_insertion
== -1) /* unchanged, key has no function here */
2042 void edit_push_key_press (WEdit
* edit
)
2044 edit_push_action (edit
, KEY_PRESS
+ edit
->start_display
);
2045 if (edit
->mark2
== -1)
2046 edit_push_action (edit
, MARK_1
+ edit
->mark1
);
2049 /* this find the matching bracket in either direction, and sets edit->bracket */
2050 static long edit_get_bracket (WEdit
* edit
, int in_screen
, unsigned long furthest_bracket_search
)
2052 const char *b
= "{}{[][()(", *p
;
2053 int i
= 1, a
, inc
= -1, c
, d
, n
= 0;
2054 unsigned long j
= 0;
2056 edit_update_curs_row (edit
);
2057 c
= edit_get_byte (edit
, edit
->curs1
);
2060 if (!furthest_bracket_search
)
2061 furthest_bracket_search
--;
2062 /* not on a bracket at all */
2065 /* the matching bracket */
2067 /* going left or right? */
2068 if (strchr ("{[(", c
))
2070 for (q
= edit
->curs1
+ inc
;; q
+= inc
) {
2071 /* out of buffer? */
2072 if (q
>= edit
->last_byte
|| q
< 0)
2074 a
= edit_get_byte (edit
, q
);
2075 /* don't want to eat CPU */
2076 if (j
++ > furthest_bracket_search
)
2078 /* out of screen? */
2080 if (q
< edit
->start_display
)
2082 /* count lines if searching downward */
2083 if (inc
> 0 && a
== '\n')
2084 if (n
++ >= edit
->num_widget_lines
- edit
->curs_row
) /* out of screen */
2087 /* count bracket depth */
2088 i
+= (a
== c
) - (a
== d
);
2089 /* return if bracket depth is zero */
2097 static long last_bracket
= -1;
2099 static void edit_find_bracket (WEdit
* edit
)
2101 if (option_find_bracket
) {
2102 edit
->bracket
= edit_get_bracket (edit
, 1, 10000);
2103 if (last_bracket
!= edit
->bracket
)
2104 edit
->force
|= REDRAW_PAGE
;
2105 last_bracket
= edit
->bracket
;
2109 static void edit_goto_matching_bracket (WEdit
*edit
)
2112 q
= edit_get_bracket (edit
, 0, 0);
2115 edit
->bracket
= edit
->curs1
;
2116 edit
->force
|= REDRAW_PAGE
;
2117 edit_cursor_move (edit
, q
- edit
->curs1
);
2120 /* this executes a command as though the user initiated it through a key press. */
2121 /* callback with WIDGET_KEY as a message calls this after translating the key
2123 /* this can be used to pass any command to the editor. Same as sendevent with
2124 msg = WIDGET_COMMAND and par = command except the screen wouldn't update */
2125 /* one of command or char_for_insertion must be passed as -1 */
2126 /* commands are executed, and char_for_insertion is inserted at the cursor */
2127 /* returns 0 if the command is a macro that was not found, 1 otherwise */
2128 int edit_execute_key_command (WEdit
* edit
, int command
, int char_for_insertion
)
2131 if (command
== CK_Begin_Record_Macro
) {
2133 edit
->force
|= REDRAW_CHAR_ONLY
| REDRAW_LINE
;
2136 if (command
== CK_End_Record_Macro
&& edit
->macro_i
!= -1) {
2137 edit
->force
|= REDRAW_COMPLETELY
;
2138 edit_save_macro_cmd (edit
, edit
->macro
, edit
->macro_i
);
2142 if (edit
->macro_i
>= 0 && edit
->macro_i
< MAX_MACRO_LENGTH
- 1) {
2143 edit
->macro
[edit
->macro_i
].command
= command
;
2144 edit
->macro
[edit
->macro_i
++].ch
= char_for_insertion
;
2146 /* record the beginning of a set of editing actions initiated by a key press */
2147 if (command
!= CK_Undo
)
2148 edit_push_key_press (edit
);
2150 r
= edit_execute_cmd (edit
, command
, char_for_insertion
);
2152 if (edit
->stopped
&& edit
->widget
->destroy_me
) {
2153 (*edit
->widget
->destroy_me
) (edit
->widget
->destroy_me_user_data
);
2157 if (column_highlighting
)
2158 edit
->force
|= REDRAW_PAGE
;
2164 static const char *shell_cmd
[] = SHELL_COMMANDS_i
2165 void edit_mail_dialog (WEdit
* edit
);
2168 static void (*user_commamd
) (WEdit
*, int) = 0;
2169 void edit_set_user_command (void (*func
) (WEdit
*, int))
2171 user_commamd
= func
;
2176 This executes a command at a lower level than macro recording.
2177 It also does not push a key_press onto the undo stack. This means
2178 that if it is called many times, a single undo command will undo
2179 all of them. It also does not check for the Undo command.
2180 Returns 0 if the command is a macro that was not found, 1
2183 int edit_execute_cmd (WEdit
* edit
, int command
, int char_for_insertion
)
2186 edit
->force
|= REDRAW_LINE
;
2187 if (edit
->found_len
|| column_highlighting
)
2188 /* the next key press will unhighlight the found string, so update whole page */
2189 edit
->force
|= REDRAW_PAGE
;
2191 if (command
/ 100 == 6) { /* a highlight command like shift-arrow */
2192 column_highlighting
= 0;
2193 if (!edit
->highlight
|| (edit
->mark2
!= -1 && edit
->mark1
!= edit
->mark2
)) {
2194 edit_mark_cmd (edit
, 1); /* clear */
2195 edit_mark_cmd (edit
, 0); /* marking on */
2197 edit
->highlight
= 1;
2198 } else { /* any other command */
2199 if (edit
->highlight
)
2200 edit_mark_cmd (edit
, 0); /* clear */
2201 edit
->highlight
= 0;
2204 /* first check for undo */
2205 if (command
== CK_Undo
) {
2206 edit_do_undo (edit
);
2207 edit
->found_len
= 0;
2208 edit
->prev_col
= edit_get_col (edit
);
2209 edit
->search_start
= edit
->curs1
;
2212 /* An ordinary key press */
2213 if (char_for_insertion
>= 0) {
2214 if (edit
->overwrite
) {
2215 if (edit_get_byte (edit
, edit
->curs1
) != '\n')
2218 edit_insert (edit
, char_for_insertion
);
2219 if (option_auto_para_formatting
) {
2220 format_paragraph (edit
, 0);
2221 edit
->force
|= REDRAW_PAGE
;
2223 check_and_wrap_line (edit
);
2224 edit
->found_len
= 0;
2225 edit
->prev_col
= edit_get_col (edit
);
2226 edit
->search_start
= edit
->curs1
;
2227 edit_find_bracket (edit
);
2228 edit_check_spelling (edit
);
2234 case CK_Begin_Page_Highlight
:
2235 case CK_End_Page_Highlight
:
2240 case CK_Word_Left_Highlight
:
2241 case CK_Word_Right_Highlight
:
2242 case CK_Up_Highlight
:
2243 case CK_Down_Highlight
:
2244 if (edit
->mark2
== -1)
2245 break; /*marking is following the cursor: may need to highlight a whole line */
2248 case CK_Left_Highlight
:
2249 case CK_Right_Highlight
:
2250 edit
->force
|= REDRAW_CHAR_ONLY
;
2253 /* basic cursor key commands */
2256 if (option_backspace_through_tabs
&& is_in_indent (edit
)) {
2257 while (edit_get_byte (edit
, edit
->curs1
- 1) != '\n'
2259 edit_backspace (edit
);
2262 if (option_fake_half_tabs
) {
2264 if (is_in_indent (edit
) && right_of_four_spaces (edit
)) {
2265 for (i
= 0; i
< HALF_TAB_SIZE
; i
++)
2266 edit_backspace (edit
);
2271 edit_backspace (edit
);
2274 if (option_fake_half_tabs
) {
2276 if (is_in_indent (edit
) && left_of_four_spaces (edit
)) {
2277 for (i
= 1; i
<= HALF_TAB_SIZE
; i
++)
2284 case CK_Delete_Word_Left
:
2285 edit_left_delete_word (edit
);
2287 case CK_Delete_Word_Right
:
2288 edit_right_delete_word (edit
);
2290 case CK_Delete_Line
:
2291 edit_delete_line (edit
);
2293 case CK_Delete_To_Line_End
:
2294 edit_delete_to_line_end (edit
);
2296 case CK_Delete_To_Line_Begin
:
2297 edit_delete_to_line_begin (edit
);
2300 if (option_auto_para_formatting
) {
2301 edit_double_newline (edit
);
2302 if (option_return_does_auto_indent
)
2303 edit_auto_indent (edit
, 0, 1);
2304 format_paragraph (edit
, 0);
2306 edit_insert (edit
, '\n');
2307 if (option_return_does_auto_indent
) {
2308 edit_auto_indent (edit
, 0, 1);
2313 edit_insert (edit
, '\n');
2317 case CK_Page_Up_Highlight
:
2318 edit_move_up (edit
, edit
->num_widget_lines
- 1, 1);
2321 case CK_Page_Down_Highlight
:
2322 edit_move_down (edit
, edit
->num_widget_lines
- 1, 1);
2325 case CK_Left_Highlight
:
2326 if (option_fake_half_tabs
) {
2327 if (is_in_indent (edit
) && right_of_four_spaces (edit
)) {
2328 edit_cursor_move (edit
, -HALF_TAB_SIZE
);
2329 edit
->force
&= (0xFFF - REDRAW_CHAR_ONLY
);
2333 edit_cursor_move (edit
, -1);
2336 case CK_Right_Highlight
:
2337 if (option_fake_half_tabs
) {
2338 if (is_in_indent (edit
) && left_of_four_spaces (edit
)) {
2339 edit_cursor_move (edit
, HALF_TAB_SIZE
);
2340 edit
->force
&= (0xFFF - REDRAW_CHAR_ONLY
);
2344 edit_cursor_move (edit
, 1);
2347 case CK_Begin_Page_Highlight
:
2348 edit_begin_page (edit
);
2351 case CK_End_Page_Highlight
:
2352 edit_end_page (edit
);
2355 case CK_Word_Left_Highlight
:
2356 edit_left_word_move_cmd (edit
);
2359 case CK_Word_Right_Highlight
:
2360 edit_right_word_move_cmd (edit
);
2363 case CK_Up_Highlight
:
2364 edit_move_up (edit
, 1, 0);
2367 case CK_Down_Highlight
:
2368 edit_move_down (edit
, 1, 0);
2370 case CK_Paragraph_Up
:
2371 case CK_Paragraph_Up_Highlight
:
2372 edit_move_up_paragraph (edit
, 0);
2374 case CK_Paragraph_Down
:
2375 case CK_Paragraph_Down_Highlight
:
2376 edit_move_down_paragraph (edit
, 0);
2379 case CK_Scroll_Up_Highlight
:
2380 edit_move_up (edit
, 1, 1);
2382 case CK_Scroll_Down
:
2383 case CK_Scroll_Down_Highlight
:
2384 edit_move_down (edit
, 1, 1);
2387 case CK_Home_Highlight
:
2388 edit_cursor_to_bol (edit
);
2391 case CK_End_Highlight
:
2392 edit_cursor_to_eol (edit
);
2396 edit_tab_cmd (edit
);
2397 if (option_auto_para_formatting
) {
2398 format_paragraph (edit
, 0);
2399 edit
->force
|= REDRAW_PAGE
;
2401 check_and_wrap_line (edit
);
2404 case CK_Toggle_Insert
:
2405 edit
->overwrite
= (edit
->overwrite
== 0);
2410 CSetCursorColor (edit
->overwrite
? color_palette (24) : color_palette (19));
2416 if (edit
->mark2
>= 0) {
2417 if (column_highlighting
)
2418 edit_push_action (edit
, COLUMN_ON
);
2419 column_highlighting
= 0;
2421 edit_mark_cmd (edit
, 0);
2423 case CK_Column_Mark
:
2424 if (!column_highlighting
)
2425 edit_push_action (edit
, COLUMN_OFF
);
2426 column_highlighting
= 1;
2427 edit_mark_cmd (edit
, 0);
2430 if (column_highlighting
)
2431 edit_push_action (edit
, COLUMN_ON
);
2432 column_highlighting
= 0;
2433 edit_mark_cmd (edit
, 1);
2436 case CK_Toggle_Bookmark
:
2437 book_mark_clear (edit
, edit
->curs_line
, BOOK_MARK_FOUND_COLOR
);
2438 if (book_mark_query_color (edit
, edit
->curs_line
, BOOK_MARK_COLOR
))
2439 book_mark_clear (edit
, edit
->curs_line
, BOOK_MARK_COLOR
);
2441 book_mark_insert (edit
, edit
->curs_line
, BOOK_MARK_COLOR
);
2443 case CK_Flush_Bookmarks
:
2444 book_mark_flush (edit
, BOOK_MARK_COLOR
);
2445 book_mark_flush (edit
, BOOK_MARK_FOUND_COLOR
);
2446 edit
->force
|= REDRAW_PAGE
;
2448 case CK_Next_Bookmark
:
2449 if (edit
->book_mark
) {
2450 struct _book_mark
*p
;
2451 p
= (struct _book_mark
*) book_mark_find (edit
, edit
->curs_line
);
2454 if (p
->line
>= edit
->start_line
+ edit
->num_widget_lines
|| p
->line
< edit
->start_line
)
2455 edit_move_display (edit
, p
->line
- edit
->num_widget_lines
/ 2);
2456 edit_move_to_line (edit
, p
->line
);
2460 case CK_Prev_Bookmark
:
2461 if (edit
->book_mark
) {
2462 struct _book_mark
*p
;
2463 p
= (struct _book_mark
*) book_mark_find (edit
, edit
->curs_line
);
2464 while (p
->line
== edit
->curs_line
)
2468 if (p
->line
>= edit
->start_line
+ edit
->num_widget_lines
|| p
->line
< edit
->start_line
)
2469 edit_move_display (edit
, p
->line
- edit
->num_widget_lines
/ 2);
2470 edit_move_to_line (edit
, p
->line
);
2475 case CK_Beginning_Of_Text
:
2476 case CK_Beginning_Of_Text_Highlight
:
2477 edit_move_to_top (edit
);
2479 case CK_End_Of_Text
:
2480 case CK_End_Of_Text_Highlight
:
2481 edit_move_to_bottom (edit
);
2485 edit_block_copy_cmd (edit
);
2488 edit_block_delete_cmd (edit
);
2491 edit_block_move_cmd (edit
);
2495 edit_copy_to_X_buf_cmd (edit
);
2498 edit_cut_to_X_buf_cmd (edit
);
2501 edit_paste_from_X_buf_cmd (edit
);
2503 case CK_Selection_History
:
2504 edit_paste_from_history (edit
);
2509 /* if (COptionsOf (edit->widget) & EDITOR_NO_FILE) */
2510 if (edit
->widget
->options
& EDITOR_NO_FILE
)
2513 edit_save_as_cmd (edit
);
2517 if (COptionsOf (edit
->widget
) & EDITOR_NO_FILE
)
2520 edit_save_confirm_cmd (edit
);
2524 if (COptionsOf (edit
->widget
) & EDITOR_NO_FILE
)
2527 edit_load_cmd (edit
);
2530 edit_save_block_cmd (edit
);
2532 case CK_Insert_File
:
2533 edit_insert_file_cmd (edit
);
2537 edit_search_cmd (edit
, 0);
2540 edit_search_cmd (edit
, 1);
2543 edit_replace_cmd (edit
, 0);
2545 case CK_Replace_Again
:
2546 edit_replace_cmd (edit
, 1);
2550 edit_quit_cmd (edit
);
2553 edit_new_cmd (edit
);
2557 edit_help_cmd (edit
);
2561 edit_refresh_cmd (edit
);
2566 #ifdef HAVE_STRFTIME
2570 #ifdef HAVE_STRFTIME
2571 strftime (s
, sizeof (s
), "%c", localtime (&t
));
2572 edit_printf (edit
, s
);
2574 edit_printf (edit
, ctime (&t
));
2576 edit
->force
|= REDRAW_PAGE
;
2580 edit_goto_cmd (edit
);
2582 case CK_Paragraph_Format
:
2583 format_paragraph (edit
, 1);
2584 edit
->force
|= REDRAW_PAGE
;
2586 case CK_Delete_Macro
:
2587 edit_delete_macro_cmd (edit
);
2589 case CK_Match_Bracket
:
2590 edit_goto_matching_bracket (edit
);
2593 if (edit_one_file
) {
2594 message (1, MSG_ERROR
, _("User menu available only in mcedit invoked from mc"));
2602 edit_sort_cmd (edit
);
2605 edit_mail_dialog (edit
);
2609 /* These commands are not handled and must be handled by the user application */
2616 case CK_Terminal_App
:
2620 case CK_Save_Desktop
:
2623 case CK_Save_And_Quit
:
2624 case CK_Check_Save_And_Quit
:
2625 case CK_Run_Another
:
2626 case CK_Debug_Start
:
2628 case CK_Debug_Toggle_Break
:
2629 case CK_Debug_Clear
:
2632 case CK_Debug_Back_Trace
:
2633 case CK_Debug_Continue
:
2634 case CK_Debug_Enter_Command
:
2635 case CK_Debug_Until_Curser
:
2640 if (edit
->widget
->menubar
)
2641 gtk_menu_popup (GTK_MENU(
2642 (GTK_MENU_ITEM (g_list_nth_data (GTK_MENU_BAR (edit
->widget
->menubar
)->menu_shell
.children
, 0)))->submenu
2643 ), 0, 0, 0, 0, 1, 0);
2653 if ((command
/ 1000) == 1) /* a shell command */
2654 edit_block_process_cmd (edit
, shell_cmd
[command
- 1000], 1);
2655 if (command
> CK_Macro (0) && command
<= CK_Last_Macro
) { /* a macro command */
2656 struct macro m
[MAX_MACRO_LENGTH
];
2658 if ((result
= edit_load_macro_cmd (edit
, m
, &nm
, command
- 2000)))
2659 edit_execute_macro (edit
, m
, nm
);
2662 if (IS_USER_COMMAND (command
)) /* a user defined command */
2664 (*user_commamd
) (edit
, command
& 0xFFFF);
2665 if (IS_MACRO_COMMAND (command
)) { /* a macro command */
2666 struct macro m
[MAX_MACRO_LENGTH
];
2668 if ((result
= edit_load_macro_cmd (edit
, m
, &nm
, command
& 0xFFFF)))
2669 edit_execute_macro (edit
, m
, nm
);
2673 /* keys which must set the col position, and the search vars */
2678 case CK_Replace_Again
:
2679 edit
->prev_col
= edit_get_col (edit
);
2683 case CK_Up_Highlight
:
2685 case CK_Down_Highlight
:
2687 case CK_Page_Up_Highlight
:
2689 case CK_Page_Down_Highlight
:
2690 case CK_Beginning_Of_Text
:
2691 case CK_Beginning_Of_Text_Highlight
:
2692 case CK_End_Of_Text
:
2693 case CK_End_Of_Text_Highlight
:
2694 case CK_Paragraph_Up
:
2695 case CK_Paragraph_Up_Highlight
:
2696 case CK_Paragraph_Down
:
2697 case CK_Paragraph_Down_Highlight
:
2699 case CK_Scroll_Up_Highlight
:
2700 case CK_Scroll_Down
:
2701 case CK_Scroll_Down_Highlight
:
2702 edit
->search_start
= edit
->curs1
;
2703 edit
->found_len
= 0;
2704 edit_find_bracket (edit
);
2705 edit_check_spelling (edit
);
2709 edit
->found_len
= 0;
2710 edit
->prev_col
= edit_get_col (edit
);
2711 edit
->search_start
= edit
->curs1
;
2713 edit_find_bracket (edit
);
2714 edit_check_spelling (edit
);
2716 if (option_auto_para_formatting
) {
2720 case CK_Delete_Word_Left
:
2721 case CK_Delete_Word_Right
:
2722 case CK_Delete_To_Line_End
:
2723 case CK_Delete_To_Line_Begin
:
2724 format_paragraph (edit
, 0);
2725 edit
->force
|= REDRAW_PAGE
;
2732 /* either command or char_for_insertion must be passed as -1 */
2733 /* returns 0 if command is a macro that was not found, 1 otherwise */
2734 int edit_execute_command (WEdit
* edit
, int command
, int char_for_insertion
)
2737 r
= edit_execute_cmd (edit
, command
, char_for_insertion
);
2738 edit_update_screen (edit
);
2742 void edit_execute_macro (WEdit
* edit
, struct macro macro
[], int n
)
2745 edit
->force
|= REDRAW_PAGE
;
2746 for (; i
< n
; i
++) {
2747 edit_execute_cmd (edit
, macro
[i
].command
, macro
[i
].ch
);
2749 edit_update_screen (edit
);
2752 /* User edit menu, like user menu (F2) but only in editor. */
2753 void user_menu (WEdit
*edit
)
2758 long start_mark
, end_mark
;
2759 char *block_file
= catstrs (home_dir
, BLOCK_FILE
, 0);
2760 char *error_file
= catstrs (home_dir
, ERROR_FILE
, 0);
2763 nomark
= eval_marks (edit
, &start_mark
, &end_mark
);
2764 if (! nomark
) /* remember marked or not */
2765 edit_save_block (edit
, block_file
= catstrs (home_dir
, BLOCK_FILE
, 0),
2766 start_mark
, end_mark
);
2768 /* run shell scripts from menu */
2769 user_menu_cmd (edit
);
2771 if (stat (error_file
, &status
) == 0) {
2772 if (!status
.st_size
) { /* no error messages */
2773 if (stat (block_file
, &status
) == 0)
2774 if (!status
.st_size
)
2775 return; /* no block messages */
2776 if (! nomark
) /* i.e. we have marked block */
2777 rc
= edit_block_delete_cmd(edit
);
2779 edit_cursor_to_bol (edit
);
2780 edit_insert_file (edit
, block_file
);
2781 edit_cursor_to_eol (edit
);
2782 if ((fd
= fopen (block_file
, "w"))) fclose(fd
);
2784 } else { /* it is error */
2785 edit_cursor_to_bol (edit
);
2786 edit_insert_file (edit
, error_file
);
2787 if ((fd
= fopen (error_file
, "w"))) fclose(fd
);
2788 if ((fd
= fopen (block_file
, "w"))) fclose(fd
);
2791 edit_error_dialog ("",
2792 get_sys_error (catstrs (_ ("Error trying to stat file:"),
2796 edit_refresh_cmd (edit
);
2797 edit
->force
|= REDRAW_COMPLETELY
;