mirror of
https://github.com/rfivet/uemacs.git
synced 2024-09-27 07:55:54 -04:00
Fix: avoid extra NL when newline/yank/insert-file at end of last line of non empty buffer.
Refactor yank. Detab before commit.
This commit is contained in:
parent
12d307b5b4
commit
1ee0ebf4b9
204
line.c
204
line.c
@ -38,11 +38,11 @@ static int ldelnewline( void) ;
|
|||||||
* was taken up by the keycode structure).
|
* was taken up by the keycode structure).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define KBLOCK 248 /* sizeof kill buffer chunks */
|
#define KBLOCK 248 /* sizeof kill buffer chunks */
|
||||||
|
|
||||||
typedef struct kill {
|
typedef struct kill {
|
||||||
struct kill *d_next ; /* Link to next chunk, NULL if last. */
|
struct kill *d_next ; /* Link to next chunk, NULL if last. */
|
||||||
char d_chunk[ KBLOCK] ; /* Deleted text. */
|
unsigned char d_chunk[ KBLOCK] ; /* Deleted text. */
|
||||||
} *kill_p ;
|
} *kill_p ;
|
||||||
|
|
||||||
static kill_p kbufp = NULL ; /* current kill buffer chunk pointer */
|
static kill_p kbufp = NULL ; /* current kill buffer chunk pointer */
|
||||||
@ -57,7 +57,7 @@ static char *value = NULL ; /* temp buffer for value */
|
|||||||
const char *getkill( void) {
|
const char *getkill( void) {
|
||||||
/* no kill buffer or no memory .... just return a null string */
|
/* no kill buffer or no memory .... just return a null string */
|
||||||
if( kbufh == NULL
|
if( kbufh == NULL
|
||||||
|| (value = realloc( value, klen + 1)) == NULL)
|
|| (value = realloc( value, klen + 1)) == NULL)
|
||||||
return "" ;
|
return "" ;
|
||||||
|
|
||||||
char *cp = value ;
|
char *cp = value ;
|
||||||
@ -94,26 +94,26 @@ BBINDABLE( backchar) {
|
|||||||
curwp->w_doto = llength( lp) ;
|
curwp->w_doto = llength( lp) ;
|
||||||
curwp->w_flag |= WFMOVE ;
|
curwp->w_flag |= WFMOVE ;
|
||||||
} else {
|
} else {
|
||||||
unsigned pos ;
|
unsigned pos ;
|
||||||
/* move back over combining unicode */
|
/* move back over combining unicode */
|
||||||
combined:
|
combined:
|
||||||
pos = curwp->w_doto -= 1 ;
|
pos = curwp->w_doto -= 1 ;
|
||||||
/* check if at end of unicode */
|
/* check if at end of unicode */
|
||||||
if( pos > 0) {
|
if( pos > 0) {
|
||||||
unsigned delta = utf8_revdelta(
|
unsigned delta = utf8_revdelta(
|
||||||
(unsigned char *) &( (curwp->w_dotp)->l_text[ pos]), pos) ;
|
(unsigned char *) &( (curwp->w_dotp)->l_text[ pos]), pos) ;
|
||||||
if( delta != 0) {
|
if( delta != 0) {
|
||||||
pos = curwp->w_doto -= delta ;
|
pos = curwp->w_doto -= delta ;
|
||||||
if( pos > 0) { /* check if on combining unicode */
|
if( pos > 0) { /* check if on combining unicode */
|
||||||
unicode_t unc ;
|
unicode_t unc ;
|
||||||
|
|
||||||
utf8_to_unicode( curwp->w_dotp->l_text, pos,
|
utf8_to_unicode( curwp->w_dotp->l_text, pos,
|
||||||
llength( curwp->w_dotp), &unc) ;
|
llength( curwp->w_dotp), &unc) ;
|
||||||
if( utf8_width( unc) == 0)
|
if( utf8_width( unc) == 0)
|
||||||
goto combined ;
|
goto combined ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -270,7 +270,7 @@ boolean linstr( char *instr) {
|
|||||||
|
|
||||||
while( (c = (unsigned char) *instr++)) {
|
while( (c = (unsigned char) *instr++)) {
|
||||||
status = (c == '\n') ? lnewline() : linsert_byte( 1, c) ;
|
status = (c == '\n') ? lnewline() : linsert_byte( 1, c) ;
|
||||||
if( status != TRUE) { /* Insertion error? */
|
if( status != TRUE) { /* Insertion error? */
|
||||||
mloutstr( "%Out of memory while inserting") ;
|
mloutstr( "%Out of memory while inserting") ;
|
||||||
break ;
|
break ;
|
||||||
}
|
}
|
||||||
@ -294,12 +294,12 @@ boolean linsert_byte( int n, int c) {
|
|||||||
char *cp1;
|
char *cp1;
|
||||||
char *cp2;
|
char *cp2;
|
||||||
line_p lp2 ;
|
line_p lp2 ;
|
||||||
int i ;
|
int i ;
|
||||||
|
|
||||||
assert( (curbp->b_mode & MDVIEW) == 0) ;
|
assert( (curbp->b_mode & MDVIEW) == 0) ;
|
||||||
|
|
||||||
lchange( WFEDIT) ;
|
lchange( WFEDIT) ;
|
||||||
line_p lp1 = curwp->w_dotp ; /* Current line */
|
line_p lp1 = curwp->w_dotp ; /* Current line */
|
||||||
if( lp1 == curbp->b_linep) { /* At the end: special */
|
if( lp1 == curbp->b_linep) { /* At the end: special */
|
||||||
if( curwp->w_doto != 0)
|
if( curwp->w_doto != 0)
|
||||||
return mloutfail( "bug: linsert") ;
|
return mloutfail( "bug: linsert") ;
|
||||||
@ -308,7 +308,7 @@ boolean linsert_byte( int n, int c) {
|
|||||||
if( lp2 == NULL)
|
if( lp2 == NULL)
|
||||||
return FALSE ;
|
return FALSE ;
|
||||||
|
|
||||||
/* Insert after previous line */
|
/* Insert after previous line */
|
||||||
lp1->l_bp->l_fp = lp2 ;
|
lp1->l_bp->l_fp = lp2 ;
|
||||||
lp2->l_fp = lp1 ;
|
lp2->l_fp = lp1 ;
|
||||||
lp2->l_bp = lp1->l_bp ;
|
lp2->l_bp = lp1->l_bp ;
|
||||||
@ -316,30 +316,30 @@ boolean linsert_byte( int n, int c) {
|
|||||||
for( i = 0 ; i < n ; ++i)
|
for( i = 0 ; i < n ; ++i)
|
||||||
lp2->l_text[ i] = c ;
|
lp2->l_text[ i] = c ;
|
||||||
|
|
||||||
/* update point of current window */
|
/* update point of current window */
|
||||||
curwp->w_dotp = lp2 ;
|
curwp->w_dotp = lp2 ;
|
||||||
curwp->w_doto = n ;
|
curwp->w_doto = n ;
|
||||||
|
|
||||||
/* update all windows displaying current buffer */
|
/* update all windows displaying current buffer */
|
||||||
for( window_p wp = wheadp ; wp != NULL ; wp = wp->w_wndp)
|
for( window_p wp = wheadp ; wp != NULL ; wp = wp->w_wndp)
|
||||||
if( wp->w_bufp == curbp) {
|
if( wp->w_bufp == curbp) {
|
||||||
/* update top window line */
|
/* update top window line */
|
||||||
if( wp->w_linep == lp1)
|
if( wp->w_linep == lp1)
|
||||||
wp->w_linep = lp2 ;
|
wp->w_linep = lp2 ;
|
||||||
|
|
||||||
/* dot at end of buffer is now at beginning of new line */
|
/* dot at end of buffer is now at beginning of new line */
|
||||||
if( wp->w_dotp == lp1)
|
if( wp->w_dotp == lp1)
|
||||||
wp->w_dotp = lp2 ;
|
wp->w_dotp = lp2 ;
|
||||||
|
|
||||||
/* mark at end of buffer is now at beginning of new line */
|
/* mark at end of buffer is now at beginning of new line */
|
||||||
if( wp->w_markp == lp1)
|
if( wp->w_markp == lp1)
|
||||||
wp->w_markp = lp2 ;
|
wp->w_markp = lp2 ;
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE ;
|
return TRUE ;
|
||||||
}
|
}
|
||||||
|
|
||||||
int doto = curwp->w_doto ; /* Save for later. */
|
int doto = curwp->w_doto ; /* Save for later. */
|
||||||
if( lp1->l_used + n > lp1->l_size) { /* Hard: reallocate */
|
if( lp1->l_used + n > lp1->l_size) { /* Hard: reallocate */
|
||||||
lp2 = lalloc( lp1->l_used + n) ;
|
lp2 = lalloc( lp1->l_used + n) ;
|
||||||
if( lp2 == NULL)
|
if( lp2 == NULL)
|
||||||
@ -465,38 +465,48 @@ boolean lnewline( void) {
|
|||||||
#else
|
#else
|
||||||
lchange(WFHARD);
|
lchange(WFHARD);
|
||||||
#endif
|
#endif
|
||||||
line_p lp1 = curwp->w_dotp ; /* Get the address and */
|
line_p lp1 = curwp->w_dotp ; /* Get the address and */
|
||||||
int doto = curwp->w_doto ; /* offset of "." */
|
int doto = curwp->w_doto ; /* offset of "." */
|
||||||
line_p lp2 = lalloc( doto) ; /* New first half line */
|
|
||||||
|
/* at end of last line of non empty buffer */
|
||||||
|
if( lp1->l_fp == curbp->b_linep && lp1 != curbp->b_linep &&
|
||||||
|
doto == lp1->l_used) {
|
||||||
|
/* move dot at end of buffer, no nl inserted */
|
||||||
|
curwp->w_dotp = curbp->b_linep ;
|
||||||
|
curwp->w_doto = 0 ;
|
||||||
|
return TRUE ;
|
||||||
|
}
|
||||||
|
|
||||||
|
line_p lp2 = lalloc( doto) ; /* New first half line */
|
||||||
if( lp2 == NULL)
|
if( lp2 == NULL)
|
||||||
return FALSE ;
|
return FALSE ;
|
||||||
|
|
||||||
memcpy( lp2->l_text, lp1->l_text, doto) ;
|
memcpy( lp2->l_text, lp1->l_text, doto) ;
|
||||||
lp1->l_used -= doto ;
|
lp1->l_used -= doto ;
|
||||||
memmove( lp1->l_text, &lp1->l_text[ doto], lp1->l_used) ;
|
memmove( lp1->l_text, &lp1->l_text[ doto], lp1->l_used) ;
|
||||||
lp2->l_fp = lp1 ;
|
lp2->l_fp = lp1 ;
|
||||||
lp2->l_bp = lp1->l_bp ;
|
lp2->l_bp = lp1->l_bp ;
|
||||||
lp1->l_bp = lp2 ;
|
lp1->l_bp = lp2 ;
|
||||||
lp2->l_bp->l_fp = lp2 ;
|
lp2->l_bp->l_fp = lp2 ;
|
||||||
for( window_p wp = wheadp ; wp != NULL ; wp = wp->w_wndp)
|
for( window_p wp = wheadp ; wp != NULL ; wp = wp->w_wndp)
|
||||||
if( wp->w_bufp == curbp) {
|
if( wp->w_bufp == curbp) {
|
||||||
if( wp->w_linep == lp1)
|
if( wp->w_linep == lp1) /* adjust top line of window */
|
||||||
wp->w_linep = lp2 ;
|
wp->w_linep = lp2 ;
|
||||||
|
|
||||||
if( wp->w_dotp == lp1) {
|
if( wp->w_dotp == lp1) {
|
||||||
if( wp == curwp || wp->w_doto > doto)
|
if( wp == curwp || wp->w_doto > doto)
|
||||||
wp->w_doto -= doto ;
|
wp->w_doto -= doto ;
|
||||||
else
|
else
|
||||||
wp->w_dotp = lp2 ;
|
wp->w_dotp = lp2 ;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( wp->w_markp == lp1) {
|
if( wp->w_markp == lp1) {
|
||||||
if( wp->w_marko > doto)
|
if( wp->w_marko > doto)
|
||||||
wp->w_marko -= doto ;
|
wp->w_marko -= doto ;
|
||||||
else
|
else
|
||||||
wp->w_markp = lp2 ;
|
wp->w_markp = lp2 ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE ;
|
return TRUE ;
|
||||||
}
|
}
|
||||||
@ -506,7 +516,7 @@ boolean lnewline( void) {
|
|||||||
* get unicode value and return UTF-8 size of character at dot.
|
* get unicode value and return UTF-8 size of character at dot.
|
||||||
*/
|
*/
|
||||||
int lgetchar( unicode_t *cp) {
|
int lgetchar( unicode_t *cp) {
|
||||||
if( curwp->w_dotp->l_used == curwp->w_doto) { /* at EOL? */
|
if( curwp->w_dotp->l_used == curwp->w_doto) { /* at EOL? */
|
||||||
*cp = (curbp->b_mode & MDDOS) ? '\r' : '\n' ;
|
*cp = (curbp->b_mode & MDDOS) ? '\r' : '\n' ;
|
||||||
return 1 ;
|
return 1 ;
|
||||||
} else
|
} else
|
||||||
@ -519,28 +529,28 @@ int lgetchar( unicode_t *cp) {
|
|||||||
* return total UTF-8 size of combined character at dot.
|
* return total UTF-8 size of combined character at dot.
|
||||||
*/
|
*/
|
||||||
static int lcombinedsize( void) {
|
static int lcombinedsize( void) {
|
||||||
if( curwp->w_dotp->l_used == curwp->w_doto) /* EOL? */
|
if( curwp->w_dotp->l_used == curwp->w_doto) /* EOL? */
|
||||||
return 1 ;
|
return 1 ;
|
||||||
else {
|
else {
|
||||||
unicode_t c ;
|
unicode_t c ;
|
||||||
|
|
||||||
int pos = curwp->w_doto ;
|
int pos = curwp->w_doto ;
|
||||||
unsigned bytes = utf8_to_unicode( curwp->w_dotp->l_text, pos,
|
unsigned bytes = utf8_to_unicode( curwp->w_dotp->l_text, pos,
|
||||||
llength( curwp->w_dotp), &c) ;
|
llength( curwp->w_dotp), &c) ;
|
||||||
/* check if followed by combining unicode character */
|
/* check if followed by combining unicode character */
|
||||||
pos += bytes ;
|
pos += bytes ;
|
||||||
while( pos < llength( curwp->w_dotp) - 1) { /* at least 2 bytes */
|
while( pos < llength( curwp->w_dotp) - 1) { /* at least 2 bytes */
|
||||||
unsigned cnt = utf8_to_unicode( curwp->w_dotp->l_text, pos,
|
unsigned cnt = utf8_to_unicode( curwp->w_dotp->l_text, pos,
|
||||||
llength( curwp->w_dotp), &c) ;
|
llength( curwp->w_dotp), &c) ;
|
||||||
if( utf8_width( c) == 0) {
|
if( utf8_width( c) == 0) {
|
||||||
bytes += cnt ;
|
bytes += cnt ;
|
||||||
pos += cnt ;
|
pos += cnt ;
|
||||||
} else
|
} else
|
||||||
break ;
|
break ;
|
||||||
}
|
}
|
||||||
|
|
||||||
return bytes ;
|
return bytes ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -576,11 +586,11 @@ boolean ldelete( long n, boolean kflag) {
|
|||||||
|
|
||||||
while( n > 0) {
|
while( n > 0) {
|
||||||
line_p dotp = curwp->w_dotp ;
|
line_p dotp = curwp->w_dotp ;
|
||||||
if( dotp == curbp->b_linep) /* Hit end of buffer. */
|
if( dotp == curbp->b_linep) /* Hit end of buffer. */
|
||||||
return FALSE ;
|
return FALSE ;
|
||||||
|
|
||||||
int doto = curwp->w_doto ;
|
int doto = curwp->w_doto ;
|
||||||
int chunk = dotp->l_used - doto ; /* Size of chunk. */
|
int chunk = dotp->l_used - doto ; /* Size of chunk. */
|
||||||
if( chunk == 0) { /* End of line, merge. */
|
if( chunk == 0) { /* End of line, merge. */
|
||||||
#if SCROLLCODE
|
#if SCROLLCODE
|
||||||
lchange( WFHARD | WFKILLS) ;
|
lchange( WFHARD | WFKILLS) ;
|
||||||
@ -597,7 +607,7 @@ boolean ldelete( long n, boolean kflag) {
|
|||||||
chunk = n ;
|
chunk = n ;
|
||||||
|
|
||||||
lchange( WFEDIT) ;
|
lchange( WFEDIT) ;
|
||||||
char *cp1 = &dotp->l_text[ doto] ; /* Scrunch text. */
|
char *cp1 = &dotp->l_text[ doto] ; /* Scrunch text. */
|
||||||
char *cp2 = cp1 + chunk ;
|
char *cp2 = cp1 + chunk ;
|
||||||
if( kflag != FALSE) { /* Kill? */
|
if( kflag != FALSE) { /* Kill? */
|
||||||
while( cp1 != cp2) {
|
while( cp1 != cp2) {
|
||||||
@ -615,7 +625,7 @@ boolean ldelete( long n, boolean kflag) {
|
|||||||
|
|
||||||
dotp->l_used -= chunk ;
|
dotp->l_used -= chunk ;
|
||||||
|
|
||||||
/* Fix windows */
|
/* Fix windows */
|
||||||
for( window_p wp = wheadp ; wp != NULL ; wp = wp->w_wndp) {
|
for( window_p wp = wheadp ; wp != NULL ; wp = wp->w_wndp) {
|
||||||
if( wp->w_dotp == dotp && wp->w_doto >= doto) {
|
if( wp->w_dotp == dotp && wp->w_doto >= doto) {
|
||||||
wp->w_doto -= chunk ;
|
wp->w_doto -= chunk ;
|
||||||
@ -648,7 +658,7 @@ boolean ldelete( long n, boolean kflag) {
|
|||||||
static int ldelnewline( void) {
|
static int ldelnewline( void) {
|
||||||
char *cp1;
|
char *cp1;
|
||||||
char *cp2;
|
char *cp2;
|
||||||
window_p wp ;
|
window_p wp ;
|
||||||
|
|
||||||
assert( (curbp->b_mode & MDVIEW) == 0) ;
|
assert( (curbp->b_mode & MDVIEW) == 0) ;
|
||||||
|
|
||||||
@ -738,7 +748,7 @@ static int ldelnewline( void) {
|
|||||||
void kdelete( void) {
|
void kdelete( void) {
|
||||||
if( kbufh != NULL) {
|
if( kbufh != NULL) {
|
||||||
/* first, delete all the chunks */
|
/* first, delete all the chunks */
|
||||||
freelist( (list_p) kbufh) ;
|
freelist( (list_p) kbufh) ;
|
||||||
|
|
||||||
/* and reset all the kill buffer pointers */
|
/* and reset all the kill buffer pointers */
|
||||||
kbufh = kbufp = NULL ;
|
kbufh = kbufp = NULL ;
|
||||||
@ -789,40 +799,28 @@ int kinsert( int c) {
|
|||||||
* check for errors. Bound to "C-Y".
|
* check for errors. Bound to "C-Y".
|
||||||
*/
|
*/
|
||||||
BINDABLE( yank) {
|
BINDABLE( yank) {
|
||||||
int c;
|
|
||||||
int i;
|
|
||||||
char *sp; /* pointer into string to insert */
|
|
||||||
kill_p kp; /* pointer into kill buffer */
|
|
||||||
|
|
||||||
assert( !(curbp->b_mode & MDVIEW)) ;
|
assert( !(curbp->b_mode & MDVIEW)) ;
|
||||||
|
|
||||||
if (n < 0)
|
if (n < 0)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
/* make sure there is something to yank */
|
|
||||||
|
/* make sure there is something to yank */
|
||||||
if (kbufh == NULL)
|
if (kbufh == NULL)
|
||||||
return TRUE; /* not an error, just nothing */
|
return TRUE; /* not an error, just nothing */
|
||||||
|
|
||||||
/* for each time.... */
|
/* for each time.... */
|
||||||
while (n--) {
|
while (n--) {
|
||||||
kp = kbufh;
|
for( kill_p kp = kbufh ; kp != NULL ; kp = kp->d_next) {
|
||||||
while (kp != NULL) {
|
unsigned char *sp = kp->d_chunk ;
|
||||||
if (kp->d_next == NULL)
|
int i = (kp->d_next == NULL) ? kused : KBLOCK ;
|
||||||
i = kused;
|
|
||||||
else
|
|
||||||
i = KBLOCK;
|
|
||||||
sp = kp->d_chunk;
|
|
||||||
while (i--) {
|
while (i--) {
|
||||||
if ((c = *sp++) == '\n') {
|
int c = *sp++ ;
|
||||||
if (lnewline() == FALSE)
|
if( FALSE == (( c == '\n') ? lnewline() : linsert_byte( 1, c)))
|
||||||
return FALSE;
|
return FALSE ;
|
||||||
} else {
|
|
||||||
if (linsert_byte(1, c) == FALSE)
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
kp = kp->d_next;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user