/* * ColorFind - find string and color it */ vi_rc ColorFind( char *data, find_type findfl ) { vi_rc rc; int len; char *buff; i_mark pos; /* * get search string and flags */ buff = StaticAlloc(); if( (len = NextWordSlash( data, buff ) ) <= 0 ) { StaticFree( buff ); return( ERR_INVALID_FIND_CMD ); } /* * go get the match */ GoToLineNoRelCurs( 1 ); rc = GetFind( buff, &pos, &len, FINDFL_FORWARD | findfl ); if( rc == ERR_NO_ERR ) { pos.column += 1; JumpTo( &pos ); DCUpdate(); #ifndef __WIN__ // Windows selects instead HiliteAColumnRange( pos.line, pos.column, pos.column + len - 1 ); #endif EditFlags.ResetDisplayLine = true; } StaticFree( buff ); return( rc ); } /* ColorFind */
/* * insertTextOnOtherLine - open up a different line */ static vi_rc insertTextOnOtherLine( insert_dir type ) { char *buffx; int i, j; linenum a, b; bool above_line = FALSE; vi_rc rc; rc = ModificationTest(); if( rc != ERR_NO_ERR ) { return( rc ); } /* * special case: no data in file */ if( CurrentFcb->nullfcb ) { return( InsertTextAfterCursor() ); } /* * get line deletion and undo crap */ a = b = CurrentPos.line + 1; if( type == INSERT_BEFORE ) { a--; b--; above_line = TRUE; } /* * set up for undo */ StartUndoGroup( UndoStack ); Modified( TRUE ); StartUndoGroup( UndoStack ); UndoInsert( a, a, UndoStack ); currLineRepUndo = FALSE; /* * add extra line, and spaces if needed. */ if( EditFlags.AutoIndent ) { buffx = StaticAlloc(); i = GetAutoIndentAmount( buffx, 0, above_line ); AddNewLineAroundCurrent( buffx, i, type ); StaticFree( buffx ); j = i + 1; } else { AddNewLineAroundCurrent( NULL, 0, type ); j = 1; } GoToLineRelCurs( b ); GoToColumn( j, CurrentLine->len + 1 ); DCDisplayAllLines(); continueInsertText( CurrentPos.column, FALSE ); return( ERR_NO_ERR ); } /* insertTextOnOtherLine */
/* * eSearch - scan a file for a search string (extended) */ static vi_rc eSearch( char *fn, char *res ) { int i; char *buff; FILE *f; /* * init for file i/o */ f = fopen( fn, "r" ); if( f == NULL ) { return( ERR_FILE_NOT_FOUND ); } /* * read lines from the file, and search through them */ buff = StaticAlloc(); while( fgets( buff, EditVars.MaxLine, f ) != NULL ) { for( i = strlen( buff ); i && isEOL( buff[i - 1] ); --i ) { buff[i - 1] = 0; } i = RegExec( cRx, buff, TRUE ); if( RegExpError != ERR_NO_ERR ) { StaticFree( buff ); return( RegExpError ); } if( i ) { for( i = 0; i < MAX_DISP; i++ ) { res[i] = buff[i]; } res[i] = 0; fclose( f ); StaticFree( buff ); return( FGREP_FOUND_STRING ); } } fclose( f ); StaticFree( buff ); return( ERR_NO_ERR ); } /* eSearch */
/* * SplitUpLine - split up a line with SPLIT_CHAR's in them */ linenum SplitUpLine( linenum cl ) { linenum extra = 0; int j, i, k; char *buff; /* * run through, and for every 0x01, make a new line */ for( ;; ) { /* * get current line */ CurrentPos.line = cl + extra; CGimmeLinePtr( CurrentPos.line, &CurrentFcb, &CurrentLine ); GetCurrentLine(); for( i = 0; i <= WorkLine->len; i++ ) { /* * found a place to split. make this line shorter, * and create a new line with the rest of the data * for this line */ if( WorkLine->data[i] == SPLIT_CHAR ) { buff = StaticAlloc(); k = 0; for( j = i + 1; j <= WorkLine->len; j++ ) { buff[k++] = WorkLine->data[j]; } WorkLine->data[i] = 0; WorkLine->len = i; ReplaceCurrentLine(); AddNewLineAroundCurrent( buff, k - 1, INSERT_AFTER ); extra++; StaticFree( buff ); break; } /* * at the very end, undo what we did and go back */ if( WorkLine->data[i] == 0 ) { ReplaceCurrentLine(); UndoInsert( cl + 1, cl + extra, UndoStack ); return( extra ); } } } } /* SplitUpLine */
/* * DisplayLineInWindowWithSyntaxStyle - display wrt syntax lang. settings */ vi_rc DisplayLineInWindowWithSyntaxStyle( window_id wn, int c_line_no, line *line, linenum line_no, char *text, int start_col, unsigned int junk ) { static ss_block ss[MAX_SS_BLOCKS]; int dummy; bool saveRealTabs; int a; vi_rc rc; char *tmp; // dc c_line; junk = junk; if( EditFlags.RealTabs ) { a = strlen( text ); tmp = StaticAlloc(); ExpandTabsInABuffer( text, a, tmp, MaxLinem1 + 2 ); } else { tmp = text; } // this code commented out cause it doesn't quite work. // it should be close considering it mirrors the WINDOWS version. // get the laguage flags state previous to this line // c_line = DCFindLine( c_line_no - 1, wn ); // SSGetLanguageFlags( &(c_line->flags) ); // parse the line (generate new flags as well) ss[0].end = BEYOND_TEXT; SSDifBlock( ss, tmp, start_col, line, line_no, &dummy ); // prevent displayLineInWindowGeneric from expanding tabs - blech saveRealTabs = EditFlags.RealTabs; EditFlags.RealTabs = FALSE; // display the thing rc = displayLineInWindowGeneric( wn, c_line_no, tmp, start_col, ss ); EditFlags.RealTabs = saveRealTabs; // now say that it has been displayed and the flags are OK // DCValidateLine( c_line, start_col, tmp ); if( EditFlags.RealTabs ) { StaticFree( tmp ); } return( rc ); }
/* * MakeExpressionNonRegular - escape out all magical chars */ void MakeExpressionNonRegular( char *str ) { int i, j = 0, k; char *foo; k = strlen( str ); foo = StaticAlloc(); for( i = 0; i < k; i++ ) { if( str[i] == '/' ) { foo[j++] = '\\'; } else if( strchr( META, str[i] ) != NULL ) { foo[j++] = '\\'; if( IsMagicCharRegular( str[i] ) ) { j--; } } foo[j++] = str[i]; } foo[j] = 0; strcpy( str, foo ); StaticFree( foo ); } /* MakeExpressionNonRegular */
/* * IMTabs - handle tabs in insert mode */ vi_rc IMTabs( void ) { char *buff; bool back; int cp, vc, tc, add; int i, j; int len; startNewLineUndo(); CheckAbbrev( abbrevBuff, &abbrevCnt ); abbrevCnt = 0; switch( LastEvent ) { case VI_KEY( TAB ): if( EditFlags.RealTabs ) { if( WorkLine->len + 1 >= EditVars.MaxLine ) { break; } addChar( '\t' ); GoToColumn( CurrentPos.column + 1, WorkLine->len + 1 ); checkWrapMargin(); break; } /* fall through if not real tabs */ case VI_KEY( CTRL_T ): case VI_KEY( SHIFT_TAB ): case VI_KEY( CTRL_D ): /* * get position of cursor on virtual line */ vc = VirtualColumnOnCurrentLine( CurrentPos.column ); if( CurrentPos.column - 1 == WorkLine->len && !EditFlags.Modeless ) { add = 1; } else { add = 0; } j = 0; back = FALSE; switch( LastEvent ) { case VI_KEY( SHIFT_TAB ): j = ShiftTab( vc, EditVars.TabAmount ); back = TRUE; break; case VI_KEY( CTRL_D ): j = ShiftTab( vc, EditVars.ShiftWidth ); back = TRUE; break; case VI_KEY( TAB ): j = Tab( vc, EditVars.TabAmount ); break; case VI_KEY( CTRL_T ): j = Tab( vc, EditVars.ShiftWidth ); break; } if( back && (vc - j < 1) ) { break; } else if( VirtualLineLen( WorkLine->data ) + j >= EditVars.MaxLine ) { break; } /* * create a real version of the line */ buff = StaticAlloc(); ExpandTabsInABufferUpToColumn( CurrentPos.column - 1, WorkLine->data, WorkLine->len, buff, EditVars.MaxLine ); len = strlen( buff ); /* * put in/suck out the tab */ tc = vc - 1; if( back ) { for( i = tc; i <= len + 1; i++ ) { buff[i - j] = buff[i]; } len -= j; } else { for( i = len; i >= tc; i-- ) { buff[i + j] = buff[i]; } for( i = 0; i < j; i++ ) { buff[tc + i] = ' '; } len += j; } /* * put tabs back in */ if( back ) { cp = vc - j; } else { cp = vc + j; } if( EditFlags.RealTabs ) { ConvertSpacesToTabsUpToColumn( cp, buff, len, WorkLine->data, EditVars.MaxLine ); } else { strcpy( WorkLine->data, buff ); } WorkLine->len = strlen( WorkLine->data ); StaticFree( buff ); cp = RealColumnOnCurrentLine( cp ) + add; GoToColumn( cp, WorkLine->len + 1 ); DisplayWorkLine( FALSE ); break; } return( ERR_NO_ERR ); } /* IMTabs */
/* * IMEnter - process the enter key in insert mode */ vi_rc IMEnter( void ) { char *buff, *buffx; int len, col, el; if( CurrentFile == NULL ) { return( ERR_NO_FILE ); } CurrentFile->need_autosave = TRUE; startNewLineUndo(); CheckAbbrev( abbrevBuff, &abbrevCnt ); abbrevCnt = 0; /* * truncate the working line */ buff = StaticAlloc(); buffx = StaticAlloc(); el = WorkLine->len - CurrentPos.column + 1; if( el > 0 && WorkLine->len > 0 ) { memcpy( buff, &WorkLine->data[CurrentPos.column - 1], el + 1 ); WorkLine->len -= el; WorkLine->data[CurrentPos.column - 1] = 0; } else { el = 0; buff[0] = 0; } len = trimWorkLine(); /* * replace the current line with the working copy */ ReplaceCurrentLine(); if( currLineRepUndo ) { CurrentLineReplaceUndoEnd( FALSE ); currLineRepUndo = FALSE; } /* * create a new line, insert leading spaces if needed * and copy in the truncation */ if( EditFlags.AutoIndent ) { len = GetAutoIndentAmount( buffx, len, FALSE ); el += len; strcat( buffx, buff ); AddNewLineAroundCurrent( buffx, el, INSERT_AFTER ); col = len + 1; } else { AddNewLineAroundCurrent( buff, el, INSERT_AFTER ); col = 1; } UndoInsert( CurrentPos.line + 1, CurrentPos.line + 1, UndoStack ); /* * display the result */ DCDisplayAllLines(); GoToLineRelCurs( CurrentPos.line + 1 ); GoToColumnOK( col ); GetCurrentLine(); StaticFree( buff ); StaticFree( buffx ); return( ERR_NO_ERR ); } /* IMEnter */
/* * RegSub - perform substitutions after a regexp match */ int RegSub( regexp *prog, char *source, char *dest, linenum lineno ) { char *src, *dst, c; int no, len, splitit = FALSE; bool upper_flag = FALSE, lower_flag = FALSE, perm_flag = FALSE; char *tmp; char buff[MAX_STR]; int i, j; linenum ll; tmp = StaticAlloc(); src = source; dst = dest; while( (c = *src++) != '\0' ) { if( c == '&' ) { no = 0; } else if( c == '\\' && '0' <= *src && *src <= '9' ) { no = *src++ - '0'; } else { no = -1; } /* * do we have a normal character? */ if( no < 0 ) { /* * is this an escaped character? */ if( c == '\\' && EditFlags.RegSubMagic ) { switch( *src ) { case '|': src++; if( !isdigit( *src ) ) { break; } i = 0; while( isdigit( *src ) ) { buff[i++] = *src++; } buff[i] = 0; j = atoi( buff ) - 1; *dst = 0; i = VirtualLineLen( dest ); while( i < j ) { *dst++ = ' '; i++; } break; case '#': src++; CFindLastLine( &ll ); sprintf( buff, "%ld", ll ); i = strlen( buff ); sprintf( buff, "%ld", lineno ); Lead( '0', i, buff ); for( j = 0; j < i; j++ ) { *dst++ = buff[j]; } break; case 't': src++; if( EditFlags.RealTabs ) { *dst++ = '\t'; } else { *dst++ = 't'; } break; case 'n': src++; if( EditFlags.AllowRegSubNewline ) { *dst++ = SPLIT_CHAR; splitit = TRUE; } else { *dst++ = 'n'; } break; case '\\': case '&': c = *src++; *dst++ = c; break; case 'u': src++; upper_flag = TRUE; perm_flag = FALSE; break; case 'l': src++; lower_flag = TRUE; perm_flag = FALSE; break; case 'L': src++; lower_flag = TRUE; perm_flag = TRUE; break; case 'U': src++; upper_flag = TRUE; perm_flag = TRUE; break; case 'e': case 'E': src++; upper_flag = lower_flag = perm_flag = FALSE; break; default: *dst++ = '\\'; break; } /* * not escaped, so just copy it in */ } else { if( upper_flag ) { c = toupper( c ); if( !perm_flag ) { upper_flag = FALSE; } } else if( lower_flag ) { c = tolower( c ); if( !perm_flag ) { lower_flag = FALSE; } } *dst++ = c; } /* * copy in a sub expression */ } else if( prog->startp[no] != NULL && prog->endp[no] != NULL ) { len = prog->endp[no] - prog->startp[no]; if( upper_flag ) { strcpy( tmp, prog->startp[no] ); strncpy( dst, strupr( tmp ), len ); if( !perm_flag ) { upper_flag = FALSE; } } else if( lower_flag ) { strcpy( tmp, prog->startp[no] ); strncpy( dst, strlwr( tmp ), len ); if( !perm_flag ) { lower_flag = FALSE; } } else { strncpy( dst, prog->startp[no], len ); } dst += len; } } *dst++ = 0; StaticFree( tmp ); return( splitit ); } /* RegSub */
/* * Substitute - perform substitution */ vi_rc Substitute( linenum n1, linenum n2, char *data ) { char *sstr, *rstr, *newr; char flag[20], *linedata; bool iflag = false; bool gflag = false; bool undoflag = false; bool restline = false; bool splitpending = false; bool undoline = false; int i, rlen, slen; bool splitme; long changecnt = 0, linecnt = 0; linenum llineno, ll, lastline = 0, extra; i_mark pos; vi_rc rc; LastSubstituteCancelled = 0; LastChangeCount = 0; LastLineCount = 0; sstr = alloca( MAX_INPUT_LINE ); if( sstr == NULL ) { return( ERR_NO_STACK ); } strcpy( sstr, data ); rc = ModificationTest(); if( rc != ERR_NO_ERR ) { return( rc ); } strcpy( data, sstr ); rstr = alloca( MAX_INPUT_LINE ); if( rstr == NULL ) { return( ERR_NO_STACK ); } if( NextWordSlash( data, sstr ) < 0 ) { return( ERR_INVALID_SUBS_CMD ); } if( NextWordSlash( data, rstr ) < 0 ) { return( ERR_INVALID_SUBS_CMD ); } slen = NextWord1( data, flag ); for( i = 0; i < slen; i++ ) { switch( flag[i] ) { case 'g': gflag = true; break; case 'i': case 'c': iflag = true; break; } } rc = CurrentRegComp( sstr ); if( rc != ERR_NO_ERR ) { return( rc ); } /* * verify last line */ if( n2 > CurrentFile->fcbs.tail->end_line ) { rc = CFindLastLine( &ll ); if( rc != ERR_NO_ERR ) { return( rc ); } if( n2 > ll ) { return( ERR_INVALID_LINE_RANGE ); } } /* * set for start of search */ if( EditFlags.Verbose && EditFlags.EchoOn ) { ClearWindow( MessageWindow ); } SaveCurrentFilePos(); llineno = n1 - 1; EditFlags.AllowRegSubNewline = true; newr = StaticAlloc(); for( pos.column = 0, pos.line = n1; pos.line <= n2; nextSearchStartPos( &pos, gflag, rlen ) ) { /* * get regular expression, and build replacement string */ rc = FindRegularExpression( NULL, &pos, &linedata, n2, 0 ); if( rc != ERR_NO_ERR || pos.line > n2 ) { break; } slen = GetCurrRegExpLength(); splitme = RegSub( CurrentRegularExpression, rstr, newr, pos.line ); rlen = strlen( newr ); ProcessingMessage( pos.line ); /* * if in global mode, see if we already have an undo for * this line */ if( gflag ) { if( lastline != pos.line ) { undoline = false; } } /* * interactive mode? yes, then display text and ask to change */ if( iflag ) { change_resp rsp; if( !restline ) { ClearWindow( MessageWindow ); } restline = true; GoToLineNoRelCurs( pos.line ); if( EditFlags.GlobalInProgress ) { EditFlags.DisplayHold = false; DCDisplayAllLines(); EditFlags.DisplayHold = true; } HilightSearchString( &pos, slen ); rsp = ChangePrompt(); if( rsp == CHANGE_NO ) { ResetDisplayLine(); rlen = 1; continue; } else if( rsp == CHANGE_CANCEL ) { ResetDisplayLine(); LastSubstituteCancelled = 1; break; } else if( rsp == CHANGE_ALL ) { ResetDisplayLine(); iflag = false; } } /* * set up for global undo if we haven't already */ if( !undoflag ) { StartUndoGroup( UndoStack ); undoflag = true; } /* * bump change counts */ changecnt++; if( llineno != pos.line ) { if( splitpending ) { splitpending = false; extra = SplitUpLine( llineno ); n2 += extra; pos.line += extra; } linecnt++; llineno = pos.line; } /* * get copy of line, and verify that new stuff fits */ CurrentPos.line = pos.line; rc = CGimmeLinePtr( pos.line, &CurrentFcb, &CurrentLine ); if( rc != ERR_NO_ERR ) { break; } if( CurrentLine->len + rlen - slen >= EditVars.MaxLine ) { rc = ERR_LINE_FULL; break; } /* * now build the individual undo */ CurrentFcb->non_swappable = true; if( !undoline ) { CurrentLineReplaceUndoStart(); CurrentLineReplaceUndoEnd( true ); if( gflag ) { undoline = true; lastline = pos.line; } } /* * remove the old string */ GetCurrentLine(); WorkLine->len = ReplaceSubString( WorkLine->data, WorkLine->len, pos.column, pos.column + slen - 1, newr, rlen ); if( iflag ) { DisplayWorkLine( true ); } ReplaceCurrentLine(); /* * if not global, only do this change on this line */ if( splitme ) { splitpending = true; } CurrentFcb->non_swappable = false; } StaticFree( newr ); EditFlags.AllowRegSubNewline = false; /* * is there still a split line pending? */ if( splitpending ) { SplitUpLine( llineno ); } RestoreCurrentFilePos(); if( restline ) { SetCurrentLine( CurrentPos.line ); GoToColumnOK( CurrentPos.column ); } if( undoflag ) { EndUndoGroup( UndoStack ); } switch( rc ) { case ERR_NO_ERR: case ERR_LINE_FULL: case ERR_FIND_PAST_TERM_LINE: case ERR_FIND_NOT_FOUND: case ERR_FIND_END_OF_FILE: /* * display results */ if( rc == ERR_LINE_FULL ) { Message1( "Stopped at line %l - line full", pos.line ); } else { Message1( "%l changes on %l lines", changecnt, linecnt ); LastLineCount = linecnt; LastChangeCount = changecnt; } DCDisplayAllLines(); rc = ERR_NO_ERR; break; default: break; } return( rc ); } /* Substitute */
/* * displayLineInWindowGeneric - takes an ss_block directly */ vi_rc displayLineInWindowGeneric( window_id wn, int c_line_no, char *text, int start_col, ss_block *ss ) { wind *w; char_info *txt; char *over, *tmp, *otmp; char_info _FAR *scr; int addr, start, end, a, spend; int cnt1, cnt2, startc, spl; char_info blank, what; #ifdef __VIO__ unsigned oscr; unsigned tbytes; #endif bool has_mouse, write_eol; unsigned ss_i; // index into text, not ss[ss_i] if( EditFlags.Quiet ) { return( ERR_NO_ERR ); } w = Windows[wn]; write_eol = FALSE; if( EditFlags.RealTabs ) { a = strlen( text ); otmp = tmp = StaticAlloc(); ExpandTabsInABuffer( text, a, tmp, MaxLinem1 + 2 ); } else { tmp = text; } tmp += start_col; a = strlen( tmp ); /* * find dimensions of line */ if( w->has_border ) { if( c_line_no < 1 || c_line_no > w->height - 2 ) { if( EditFlags.RealTabs ) { StaticFree( otmp ); } return( ERR_WIND_NO_SUCH_LINE ); } start = 1; spl = c_line_no; spend = end = w->width - 1; if( a < end - 1 ) { end = a + 1; } else if( a >= end ) { write_eol = TRUE; } } else { if( c_line_no < 1 || c_line_no > w->height ) { if( EditFlags.RealTabs ) { StaticFree( otmp ); } return( ERR_WIND_NO_SUCH_LINE ); } start = 0; spl = c_line_no - 1; spend = end = w->width; if( a < end ) { end = a; } else if( a > end ) { write_eol = TRUE; } } startc = start; cnt1 = end - start; cnt2 = spend - end; c_line_no--; w = AccessWindow( wn ); /* * initialize */ addr = startc + spl * w->width; txt = (char_info *) &(w->text[sizeof( char_info ) * addr]); scr = (char_info _FAR *) &Scrn[(w->x1 + startc + (spl + w->y1) * WindMaxWidth) * sizeof(char_info)]; #ifdef __VIO__ oscr = (unsigned) ((char *) scr - Scrn); tbytes = cnt1 + cnt2; #endif ss_i = 0; what.attr = MAKE_ATTR( w, SEType[ss->type].foreground, SEType[ss->type].background ); blank.ch = ' '; has_mouse = DisplayMouse( FALSE ); /* * display line */ if( w->overcnt[spl] ) { over = &(w->overlap[addr]); while( cnt1-- != 0 ) { what.ch = (*tmp); WRITE_SCREEN_DATA( *txt, what ); if( *over++ == NO_CHAR ) { WRITE_SCREEN( *scr, what ); } tmp++; scr++; txt++; if( ++ss_i > ss->end ) { ss++; what.attr = MAKE_ATTR( w, SEType[ss->type].foreground, SEType[ss->type].background ); } } if( write_eol && *(over - 1) == NO_CHAR ) { WriteLongLineMarker( wn, &( SEType[SE_EOFTEXT] ), txt - 1, scr - 1, *(tmp - 1) ); } else { blank.attr = MAKE_ATTR( w, SEType[ss->type].foreground, SEType[ss->type].background ); while( cnt2-- != 0 ) { WRITE_SCREEN_DATA( *txt, blank ); if( *over++ == NO_CHAR ) { WRITE_SCREEN( *scr, blank ); } scr++; txt++; } } } else { while( cnt1-- != 0 ) { what.ch = (*tmp); WRITE_SCREEN_DATA( *txt, what ); WRITE_SCREEN( *scr, what ); scr++; txt++; tmp++; if( ++ss_i > ss->end ) { ss++; what.attr = MAKE_ATTR( w, SEType[ss->type].foreground, SEType[ss->type].background ); } } if( write_eol ) { WriteLongLineMarker( wn, &( SEType[SE_EOFTEXT] ), txt - 1, scr - 1, *(tmp - 1) ); } else { blank.attr = MAKE_ATTR( w, SEType[ss->type].foreground, SEType[ss->type].background ); while( cnt2-- != 0 ) { WRITE_SCREEN_DATA( *txt, blank ); WRITE_SCREEN( *scr, blank ); txt++; scr++; } } } #ifdef __VIO__ MyVioShowBuf( oscr, tbytes ); #endif if( EditFlags.RealTabs ) { StaticFree( otmp ); } ReleaseWindow( w ); DisplayMouse( has_mouse ); return( ERR_NO_ERR ); } /* displayLineInWindowGeneric */
/* * doCompressExpand - convert tabs to spaces, and spaces to tabs */ static vi_rc doCompressExpand( bool compress ) { int k; long bytes_saved = 0; long bytes_added = 0; long otabcnt; linenum linecnt = 0; char *tmp; vi_rc rc; /* * init */ rc = ModificationTest(); if( rc != ERR_NO_ERR ) { return( rc ); } rc = SaveAndResetFilePos( 1 ); if( rc != ERR_NO_ERR ) { return( rc ); } tmp = StaticAlloc(); /* * process all lines */ TabCnt = 0; for( ;; ) { if( compress ) { otabcnt = TabCnt; ExpandTabsInABuffer( CurrentLine->data, CurrentLine->len, tmp, EditVars.MaxLine ); TabCnt = otabcnt; k = strlen( tmp ); ConvertSpacesToTabsUpToColumn( k, tmp, k, WorkLine->data, EditVars.MaxLine ); WorkLine->len = strlen( WorkLine->data ); bytes_saved += CurrentLine->len - WorkLine->len; } else { ExpandTabsInABuffer( CurrentLine->data, CurrentLine->len, WorkLine->data, EditVars.MaxLine ); WorkLine->len = strlen( WorkLine->data ); bytes_added += WorkLine->len - CurrentLine->len; } ReplaceCurrentLine(); /* * get next line */ linecnt++; rc = CGimmeNextLinePtr( &CurrentFcb, &CurrentLine ); if( rc != ERR_NO_ERR ) { if( rc == ERR_NO_MORE_LINES ) { break; } RestoreCurrentFilePos(); StaticFree( tmp ); return( rc ); } } StaticFree( tmp ); RestoreCurrentFilePos(); Modified( TRUE ); DCDisplayAllLines(); Message1( "%l lines processed in \"%s\"", linecnt, CurrentFile->name ); if( compress ) { Message2( " %l tabs added (%l bytes saved)", TabCnt, bytes_saved ); } else { Message2( " %l tabs removed (%l bytes added)", TabCnt, bytes_added ); } return( DO_NOT_CLEAR_MESSAGE_WINDOW ); } /* doCompressExpand */
/* * GetAddress - parse to obtain line number */ vi_rc GetAddress( const char **buffp, linenum *num ) { linenum numstack[NUM_STACK_SIZE]; char currnum[NUM_STACK_SIZE]; linenum sum; int numptr; int nument, csign, numsign; int i, j; bool numinprog, stopnum, endparse; char c; char *tmp, st[2]; int len; find_type fl; i_mark pos; vi_rc rc; const char *buff; /* * check if we have a numeric type thingy here */ buff = *buffp; c = *buff; if( !(c == '/' || c == '?' || c == '+' || c == '-' || c == '\'' || c == '.' || c == '$' || (c >= '0' && c <= '9')) ) { return( NO_NUMBER ); } if( c == '+' || c == '-' ) { sum = CurrentPos.line; } else { sum = 0; } numptr = nument = 0; csign = numsign = 1; numinprog = stopnum = false; endparse = false; while( !endparse ) { c = *buff; switch( c ) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': currnum[numptr++] = c; numinprog = true; break; case '/': case '?': if( numinprog ) { return( NO_NUMBER ); } tmp = StaticAlloc(); st[0] = c; st[1] = '\0'; buff = GetNextWord( buff, tmp, st ); if( c == '?' ) { fl = FINDFL_BACKWARDS | FINDFL_NEXTLINE; } else { fl = FINDFL_FORWARD | FINDFL_NEXTLINE; } rc = GetFind( tmp, &pos, &len, fl ); numstack[nument] = pos.line; stopnum = true; StaticFree( tmp ); if( rc != ERR_NO_ERR ) { return( rc ); } if( *buff == '\0' ) --buff; break; case '\'': if( numinprog ) { return( NO_NUMBER ); } j = buff[1] - 'a'; rc = VerifyMark( j + 1, true ); if( rc != ERR_NO_ERR ) { return( rc ); } numstack[nument] = MarkList[j].p.line; stopnum = true; ++buff; break; case '+': csign = 1; if( numinprog ) { stopnum = true; } else { numsign = 1; } break; case '-': if( numinprog ) { stopnum = true; csign = -1; } else { numsign = -1; csign = 1; } break; case '.': if( numinprog ) { return( NO_NUMBER ); } numstack[nument] = CurrentPos.line; stopnum = true; break; case '$': if( numinprog ) { return( NO_NUMBER ); } rc = CFindLastLine( &numstack[nument] ); if( rc != ERR_NO_ERR ) { return( rc ); } stopnum = true; break; default: --buff; endparse = true; if( numinprog ) { stopnum = true; } break; } ++buff; /* * check if a number was being scanned */ if( stopnum && numinprog ) { currnum[numptr] = '\0'; numptr = 0; numstack[nument] = atol( currnum ); numinprog = false; } if( stopnum ) { numstack[nument] *= numsign; nument++; numsign = csign; csign = 1; stopnum = false; } } *buffp = buff; for( i = 0; i < nument; i++ ) { sum += numstack[i]; } *num = sum; return( ERR_NO_ERR ); } /* GetAddress */