@@ -2,11 +2,7 @@
* kyle's editor
*
* first version is a run-through of the kilo editor walkthrough as a
* set of guiderails. I've made a lot of changes and did some things
* differently. keep an eye for for kte, kyle's text editor - the
* rewrite that will be coming out... when it comes out.
*
* https://viewsourcecode.org/snaptoken/kilo/
* set of guiderails. I've made a lot of changes.
*/
# include <sys/ioctl.h>
@@ -21,6 +17,7 @@
# include <string.h>
# include <locale.h>
# include <wchar.h>
# include <wctype.h>
# include <termios.h>
# include <time.h>
# include <unistd.h>
@@ -155,6 +152,7 @@ void killring_append_char(unsigned char ch);
void killring_prepend_char ( unsigned char ch ) ;
void toggle_markset ( void ) ;
int cursor_after_mark ( void ) ;
void indent_region ( void ) ;
/* miscellaneous */
void die ( const char * s ) ;
@@ -790,6 +788,50 @@ kill_region(void)
}
void
indent_region ( void )
{
int start_row , end_row ;
int i ;
if ( ! editor . mark_set ) {
return ;
}
if ( editor . mark_cury < editor . cury ) {
start_row = editor . mark_cury ;
end_row = editor . cury ;
} else if ( editor . mark_cury > editor . cury ) {
start_row = editor . cury ;
end_row = editor . mark_cury ;
} else {
start_row = end_row = editor . cury ;
}
/* Ensure bounds are valid */
if ( start_row < 0 ) {
start_row = 0 ;
}
if ( end_row > = editor . nrows ) {
end_row = editor . nrows - 1 ;
}
if ( start_row > = editor . nrows | | end_row < 0 ) {
return ;
}
/* Prepend a tab character to every row in the region */
for ( i = start_row ; i < = end_row ; i + + ) {
row_insert_ch ( & editor . row [ i ] , 0 , ' \t ' ) ;
}
/* Move cursor to beginning of the line it was on */
editor . curx = 0 ;
editor . dirty + + ;
}
/* call after kill_region */
void
delete_region ( void )
@@ -874,11 +916,13 @@ goto_line(void)
if ( lineno < 1 | | lineno > = editor . nrows ) {
editor_set_status ( " Line number must be between 1 and %d. " ,
editor . nrows ) ;
free ( query ) ;
return ;
}
editor . cury = lineno - 1 ;
editor . rowoffs = editor . cury - ( editor . rows / 2 ) ;
free ( query ) ;
}
@@ -1469,7 +1513,7 @@ editor_prompt(char *prompt, void (*cb)(char *, int16_t))
}
return buf ;
}
} else if ( ( c = = TAB_KEY ) | | ( c > = 0x20 & & c ! = 0x7f ) ) {
} else if ( ( c = = TAB_KEY ) | | ( c > = 0x20 & & c < 0x7f ) ) {
if ( buflen = = bufsz - 1 ) {
bufsz * = 2 ;
buf = realloc ( buf , bufsz ) ;
@@ -1587,6 +1631,41 @@ editor_openfile(void)
}
int
first_nonwhitespace ( struct erow * row )
{
int pos ;
wchar_t wc ;
mbstate_t state ;
size_t len ;
if ( row = = NULL ) {
return 0 ;
}
memset ( & state , 0 , sizeof ( state ) ) ;
pos = 0 ;
while ( pos < row - > size ) {
len = mbrtowc ( & wc , & row - > line [ pos ] , row - > size - pos , & state ) ;
if ( len = = ( size_t ) - 1 | | len = = ( size_t ) - 2 ) {
/* Invalid or incomplete sequence, stop here */
break ;
}
if ( len = = 0 ) {
/* Null character, stop here */
break ;
}
if ( ! iswspace ( wc ) ) {
/* Found non-whitespace character */
break ;
}
pos + = len ;
}
return pos ;
}
void
move_cursor ( int16_t c )
{
@@ -1600,12 +1679,20 @@ move_cursor(int16_t c)
case CTRL_KEY ( ' p ' ) :
if ( editor . cury > 0 ) {
editor . cury - - ;
row = ( editor . cury > = editor . nrows )
? NULL
: & editor . row [ editor . cury ] ;
editor . curx = first_nonwhitespace ( row ) ;
}
break ;
case ARROW_DOWN :
case CTRL_KEY ( ' n ' ) :
if ( editor . cury < editor . nrows ) {
editor . cury + + ;
row = ( editor . cury > = editor . nrows )
? NULL
: & editor . row [ editor . cury ] ;
editor . curx = first_nonwhitespace ( row ) ;
}
break ;
case ARROW_RIGHT :
@@ -1620,7 +1707,10 @@ move_cursor(int16_t c)
}
} else if ( row & & editor . curx = = row - > size ) {
editor . cury + + ;
editor . curx = 0 ;
row = ( editor . cury > = editor . nrows )
? NULL
: & editor . row [ editor . cury ] ;
editor . curx = first_nonwhitespace ( row ) ;
}
break ;
case ARROW_LEFT :
@@ -1692,7 +1782,10 @@ newline(void)
{
struct erow * row = NULL ;
if ( editor . curx = = 0 ) {
if ( editor . cury > = editor . nrows ) {
/* At or past end of file, insert empty line */
erow_insert ( editor . cury , " " , 0 ) ;
} else if ( editor . curx = = 0 ) {
erow_insert ( editor . cury , " " , 0 ) ;
} else {
row = & editor . row [ editor . cury ] ;
@@ -1752,13 +1845,11 @@ get_cloc_code_lines(const char* filename)
}
if ( fgets ( buffer , sizeof ( buffer ) , pipe ) ! = NULL ) {
// Remove trailing newline
len = strlen ( buffer ) ;
if ( len > 0 & & buffer [ len - 1 ] = = ' \n ' ) {
buffer [ len - 1 ] = ' \0 ' ;
}
// Allocate and copy the string
result = malloc ( strlen ( buffer ) + 1 ) ;
assert ( result ! = NULL ) ;
if ( result ) {
@@ -1922,8 +2013,13 @@ process_normal(int16_t c)
editor . mode = MODE_ESCAPE ;
break ;
default :
/* Insert any printable byte: ASCII 0x20– 0x7E and all bytes >=0x80. */
if ( ( c = = TAB_KEY ) | | ( c > = 0x20 & & c ! = 0x7f ) ) {
if ( c = = TAB_KEY ) {
if ( editor . mark_set ) {
indent_region ( ) ;
} else {
insertch ( c ) ;
}
} else if ( c > = 0x20 & & c ! = 0x7f ) {
insertch ( c ) ;
}
break ;
@@ -2312,7 +2408,6 @@ loop(void)
int
main ( int argc , char * argv [ ] )
{
// Set locale for proper UTF-8 handling
setlocale ( LC_ALL , " " ) ;
setup_terminal ( ) ;