vi_rc GetLineRange( range *result, long count, linenum line ) { result->line_based = true; result->start.line = line; line += count - 1; CFindLastLine( &result->end.line ); if( line <= result->end.line ) { result->end.line = line; } return( ERR_NO_ERR ); }
/* * verifyMoveFromPageTop - move a certain amount past the top of page, * verifying that the end of file is not overrun */ static vi_rc verifyMoveFromPageTop( range *r, linenum ln ) { if( CurrentLine == NULL ) { return( ERR_NO_FILE ); } ln += LeftTopPos.line; if( IsPastLastLine( ln ) ) { CFindLastLine( &ln ); } r->line_based = TRUE; r->start.line = ln; return( ERR_NO_ERR ); } /* verifyMoveFromPageTop */
/* * ValidateCurrentLine - make sure current line is valid */ vi_rc ValidateCurrentLine( void ) { vi_rc rc; if( CurrentPos.line < 1 ) { return( SetCurrentLine( 1 ) ); } if( CurrentPos.line > CurrentFile->fcbs.tail->end_line ) { rc = CFindLastLine( &CurrentPos.line ); if( rc != ERR_NO_ERR ) { return( rc ); } } return( SetCurrentLine( CurrentPos.line ) ); } /* ValidateCurrentLine */
/* * MovePageMiddle - move to the middle of the page */ vi_rc MovePageMiddle( range *r, long count ) { linenum ln, lne; if( CurrentLine == NULL ) { return( ERR_NO_FILE ); } count = count; ln = WindowAuxInfo( CurrentWindow, WIND_INFO_TEXT_LINES ) - 1; CFindLastLine( &lne ); lne = lne - LeftTopPos.line + 1; if( ln > lne ) { ln = lne; } return( verifyMoveFromPageTop( r, ln / 2 ) ); } /* MovePageMiddle */
/* * MoveScreenML - screen shifting (mainly for scrolling - used only for mdles) */ vi_rc MoveScreenML( linenum ntop ) { linenum lastline; if( ntop > LeftTopPos.line ) { CFindLastLine( &lastline ); if( ntop > lastline ) { ntop = lastline; } } else { if( ntop < 1 ) { ntop = 1; } } LeftTopPos.line = ntop; return( ERR_NO_ERR ); } /* MoveScreenML */
/* * SelectAll - select the entire contents of the file */ vi_rc SelectAll( void ) { range r; vi_rc rc; r.line_based = TRUE; r.start.line = 1; CFindLastLine( &r.end.line ); rc = SetSelectedRegion( &r ); if( rc != ERR_NO_ERR ) { return( rc ); } rc = GoToLineNoRelCurs( r.end.line ); if( rc != ERR_NO_ERR ) { return( rc ); } return( GoToColumnOK( LineLength( r.end.line ) + 1 ) ); } /* SelectAll */
/* * IsPastLastLine - test if something is past the last line */ bool IsPastLastLine( linenum l ) { linenum ll; if( CurrentFile == NULL ) { return( TRUE ); } ll = CurrentFile->fcbs.tail->end_line; if( l <= ll ) { return( FALSE ); } CFindLastLine( &ll ); if( l > ll ) { return( TRUE ); } return( FALSE ); } /* IsPastLastLine */
vi_rc MovePageBottom( range *r, long count ) { linenum ln; int lines; int amt; if( CurrentLine == NULL ) { return( ERR_NO_FILE ); } lines = WindowAuxInfo( CurrentWindow, WIND_INFO_TEXT_LINES ); if( IsPastLastLine( LeftTopPos.line + lines ) ) { CFindLastLine( &ln ); amt = ln - LeftTopPos.line - count + 1; } else { amt = lines - count; } return( verifyMoveFromPageTop( r, amt ) ); } /* MovePageBottom */
/* * MoveScreenUp - expose top line */ vi_rc MoveScreenUp( void ) { linenum lne, cnt, lines, top, nlne; lines = WindowAuxInfo( CurrentWindow, WIND_INFO_TEXT_LINES ); CFindLastLine( &lne ); cnt = GetRepeatCount(); top = LeftTopPos.line - cnt; if( top < 1 ) { top = 1; } LeftTopPos.line = top; if( CurrentPos.line >= top + lines ) { nlne = top + lines - 1; if( nlne > lne ) { nlne = lne; } GoToLineNoRelCurs( nlne ); } DCDisplayAllLines(); SetWindowCursor(); return( ERR_NO_ERR ); } /* MoveScreenUp */
/* * MoveScreenDown - expose bottom line */ vi_rc MoveScreenDown( void ) { linenum lne, cnt, lines, top, x; CFindLastLine( &lne ); lines = WindowAuxInfo( CurrentWindow, WIND_INFO_TEXT_LINES ); x = lne - lines + 1; if( x <= 0 ) { return( ERR_NO_ERR ); } cnt = GetRepeatCount(); top = LeftTopPos.line + cnt; if( top > x ) { top = x; } LeftTopPos.line = top; if( top >= CurrentPos.line ) { GoToLineNoRelCurs( top ); } DCDisplayAllLines(); SetWindowCursor(); return( ERR_NO_ERR ); } /* MoveScreenDown */
static vi_rc checkLine( linenum *ln ) { vi_rc rc; linenum last; if( CurrentLine == NULL ) { return( ERR_NO_FILE ); } rc = ERR_NO_ERR; if( (*ln) < 1 ) { *ln = 1; rc = ERR_NO_SUCH_LINE; } else { CFindLastLine( &last ); if( (*ln) > last ) { *ln = last; rc = ERR_NO_SUCH_LINE; } } if( (EditFlags.Modeless == TRUE) && (rc == ERR_NO_SUCH_LINE) ) { rc = ERR_NO_ERR; } return( rc ); }
/* * MovePage - move by a number of pages */ vi_rc MovePage( int dir, long repcnt, bool keepselect ) { vi_rc rc; linenum x, top, ll; linenum tmp; if( EditFlags.Modeless && !keepselect ) { UnselectRegion(); } tmp = (repcnt * dir * WindowAuxInfo( CurrentWindow, WIND_INFO_TEXT_LINES )) - (dir * EditVars.PageLinesExposed); #if 0 x = CurrentPos.line + tmp; top = LeftTopPos.line + tmp; CFindLastLine( &ll ); if( top > ll ) { top = ll; } else if( top < 1 ) { top = 1; } if( x > ll ) { x = ll; } else if( x < 1 ) { x = 1; } #else top = LeftTopPos.line + tmp; if( top < 1 ) { top = 1; } rc = CAdvanceToLine( top ); if( rc == ERR_NO_SUCH_LINE ) { rc = CFindLastLine( &ll ); top = ll; } if( rc != ERR_NO_ERR ) { return( rc ); } x = CurrentPos.line + tmp; if( x < 1 ) { x = 1; } rc = CAdvanceToLine( x ); if( rc == ERR_NO_SUCH_LINE ) { rc = CFindLastLine( &ll ); x = ll; } if( rc != ERR_NO_ERR ) { return( rc ); } #endif LeftTopPos.line = top; SetCurrentLineNumber( x ); rc = CGimmeLinePtr( CurrentPos.line, &CurrentFcb, &CurrentLine ); if( rc == ERR_NO_ERR ) { CheckCurrentColumn(); UpdateStatusWindow(); SetWindowCursor(); DCInvalidateAllLines(); DCDisplayAllLines(); } return( rc ); } /* MovePage */
/* * 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 */
/* * setLineCol - set up line and column to start search at */ static vi_rc setLineCol( char *st, i_mark *pos, find_type flags ) { fcb *cfcb; line *cline; bool wrapped; /* * get next position */ if( st[0] == 0 ) { if( lastFind == NULL ) { return( ERR_NO_PREVIOUS_SEARCH_STRING ); } if( lastPos.line != 0 && currPos.column == CurrentPos.column && currPos.line == CurrentPos.line ) { *pos = lastPos; if( flags & FINDFL_FORWARD ) { pos->column += 1; } else { pos->column -= 2; } } else { *pos = CurrentPos; if( flags & FINDFL_FORWARD ) { pos->column += 0; } else { pos->column -= 2; } } AddString2( &sStr, lastFind ); } else { if( !(flags & FINDFL_NOCHANGE) ) { AddString2( &lastFind, st ); } AddString2( &sStr, st ); *pos = CurrentPos; if( flags & FINDFL_FORWARD ) { pos->column += 0; } else { pos->column -= 2; } } /* * wrap if needed */ if( flags & FINDFL_NEXTLINE ) { wrapped = FALSE; if( flags & FINDFL_FORWARD ) { pos->column = 0; pos->line += 1; if( IsPastLastLine( pos->line ) ) { pos->line = 1; wrapped = TRUE; } } else { pos->line -= 1; if( pos->line == 0 ) { CFindLastLine( &pos->line ); wrapped = TRUE; } CGimmeLinePtr( pos->line, &cfcb, &cline ); pos->column = cline->len - 1; if( pos->column < 0 ) { pos->column = 0; } } if( wrapped && !(flags & FINDFL_WRAP) ) { if( flags & FINDFL_FORWARD ) { return( ERR_FIND_END_OF_FILE ); } else { return( ERR_FIND_TOP_OF_FILE ); } } } return( ERR_NO_ERR ); } /* setLineCol */
/* * FindRegularExpressionBackwards - do a reverse search for a regular expression */ vi_rc FindRegularExpressionBackwards( char *pat, i_mark *pos1, char **linedata, linenum termline, find_type flags ) { vi_rc rc; char *data; bool wrapped = false; bool found; linenum ilineno = 0; line *cline; fcb *cfcb; regexp rcpy; int scol; linenum sline; /* * initialize for search */ if( wrapMsgPrinted ) { wrapMsgPrinted = false; ClearWindow( message_window_id ); } sline = pos1->line; rc = CGimmeLinePtr( sline, &cfcb, &cline ); if( rc != ERR_NO_ERR ) { return( rc ); } if( flags & FINDFL_WRAP ) { ilineno = sline; } scol = pos1->column; if( pat != NULL ) { rc = CurrentRegComp( pat ); if( rc != ERR_NO_ERR ) { return( rc ); } } memset( &rcpy, 0, sizeof( rcpy ) ); /* * loop until string found */ for( ;; ) { data = cline->data; found = false; /* * run through all possible matches on the line, accepting * only the last one */ if( scol >= 0 ) { while( *data != '\0' && RegExec( CurrentRegularExpression, data, (data == cline->data) ) ) { int col, len; if( RegExpError != ERR_NO_ERR ) { return( RegExpError ); } col = GetCurrRegExpColumn( cline->data ); len = GetCurrRegExpLength(); if( col + len > scol ) { break; } found = true; memcpy( &rcpy, CurrentRegularExpression, sizeof( regexp ) ); data = &(cline->data[col + 1]); } if( found ) { break; } } /* * get next line */ rc = GimmePrevLinePtr( &cfcb, &cline ); if( rc == ERR_NO_ERR ) { --sline; } else if( rc == ERR_NO_MORE_LINES ) { if( (flags & FINDFL_WRAP) == 0 ) { return( ERR_FIND_TOP_OF_FILE ); } else { Message1( wrapMsg, "top" ); MyBeep(); wrapMsgPrinted = true; } if( wrapped ) { return( ERR_FIND_NOT_FOUND ); } rc = CFindLastLine( &sline ); if( rc != ERR_NO_ERR ) { return( rc ); } rc = CGimmeLinePtr( sline, &cfcb, &cline ); if( rc != ERR_NO_ERR ) { return( rc ); } wrapped = true; } else { return( rc ); } if( sline < termline ) { return( ERR_FIND_PAST_TERM_LINE ); } if( wrapped ) { if( sline < ilineno ) { return( ERR_FIND_NOT_FOUND ); } } scol = cline->len; } *linedata = cline->data; memcpy( CurrentRegularExpression, &rcpy, sizeof( regexp ) ); pos1->column = GetCurrRegExpColumn( cline->data ); pos1->line = sline; return( ERR_NO_ERR ); } /* FindRegularExpressionBackwards */
/* * Global - perform global command */ vi_rc Global( linenum n1, linenum n2, const char *data, int dmt ) { char *sstr, *linedata; bool match; vi_rc rc; vi_rc rc1; long changecnt = 0; linenum ll; fcb *cfcb; line *cline; regexp crx; i_mark pos; /* * get search string and command */ rc = ModificationTest(); if( rc != ERR_NO_ERR ) { return( rc ); } sstr = alloca( MAX_INPUT_LINE ); if( sstr == NULL ) { return( ERR_NO_STACK ); } data = SkipLeadingSpaces( data ); data = GetNextWord( data, sstr, SingleSlash ); if( *sstr == '\0' ) { return( ERR_INVALID_GLOBAL_CMD ); } if( *data == '/' ) ++data; // skip one slash character data = SkipLeadingSpaces( data ); /* * 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 ); } rc = CurrentRegComp( sstr ); if( rc != ERR_NO_ERR ) { return( rc ); } SaveCurrentFilePos(); StartUndoGroup( UndoStack ); EditFlags.DisplayHold = true; /* * pass one - find all matches */ for( pos.line = n1; pos.line <= n2; pos.line++ ) { /* * go thorugh file, marking global lines */ pos.column = 0; rc = FindRegularExpression( NULL, &pos, &linedata, n2, 0 ); if( rc != ERR_NO_ERR ) { if( rc == ERR_FIND_PAST_TERM_LINE || rc == ERR_FIND_NOT_FOUND || rc == ERR_FIND_END_OF_FILE ) { break; } RestoreCurrentFilePos(); EditFlags.DisplayHold = false; return( rc ); } if( pos.line > n2 ) { break; } /* * go to appropriate spot in file */ rc = GoToLineNoRelCurs( pos.line ); if( rc != ERR_NO_ERR ) { RestoreCurrentFilePos(); EditFlags.DisplayHold = false; return( rc ); } /* * mark fcb and line for a match */ CurrentFcb->globalmatch = true; CurrentLine->u.ld.globmatch = true; if( EditFlags.Verbose && EditFlags.EchoOn ) { // WPrintfLine( MessageWindow,1,"Match on line %l",clineno ); Message1( "Match on line %l", pos.line ); } } /* * negate range, if needed */ if( dmt ) { /* * run through each line, flipping globmatch flag on lines */ CGimmeLinePtr( n1, &CurrentFcb, &CurrentLine ); match = false; for( CurrentPos.line = n1; CurrentPos.line <= n2; CurrentPos.line++ ) { if( CurrentLine->u.ld.globmatch ) { CurrentLine->u.ld.globmatch = false; } else { match = true; CurrentLine->u.ld.globmatch = true; } CurrentLine = CurrentLine->next; if( CurrentLine == NULL ) { CurrentFcb->globalmatch = match; CurrentFcb = CurrentFcb->next; FetchFcb( CurrentFcb ); CurrentLine = CurrentFcb->lines.head; match = false; } } } /* * Pass 2: do all changes */ rc = ERR_NO_ERR; EditFlags.GlobalInProgress = true; memcpy( &crx, CurrentRegularExpression, sizeof( crx ) ); for( CurrentFcb = CurrentFile->fcbs.head; CurrentFcb != NULL; CurrentFcb = CurrentFcb->next ) { if( !CurrentFcb->globalmatch ) continue; FetchFcb( CurrentFcb ); CurrentPos.line = CurrentFcb->start_line; for( CurrentLine = CurrentFcb->lines.head; CurrentLine != NULL; CurrentLine = CurrentLine->next, CurrentPos.line++ ) { if( !CurrentLine->u.ld.globmatch ) continue; CurrentLine->u.ld.globmatch = false; changecnt++; CurrentPos.column = 1; ProcessingMessage( CurrentPos.line ); /* * build command line */ rc = RunCommandLine( data ); if( rc > ERR_NO_ERR ) { break; } } if( rc > ERR_NO_ERR ) { break; } CurrentFcb->globalmatch = false; } /* * we have an error, so fix up fcbs */ if( rc > ERR_NO_ERR ) { for( cfcb = CurrentFile->fcbs.head; cfcb != NULL; cfcb = cfcb->next ) { if( cfcb->globalmatch ) { cfcb->globalmatch = false; cfcb->non_swappable = false; for( cline = cfcb->lines.head; cline != NULL; cline = cline->next ) { cline->u.ld.globmatch = false; } } } } /* * display results */ EditFlags.GlobalInProgress = false; EditFlags.DisplayHold = false; EndUndoGroup( UndoStack ); RestoreCurrentFilePos(); rc1 = SetCurrentLine( CurrentPos.line ); if( rc1 != ERR_NO_ERR ) { if( rc1 == ERR_NO_SUCH_LINE ) { SetCurrentLine( 1 ); } else { return( rc1 ); } } Message1( "%l matches found",changecnt ); DCDisplayAllLines(); return( rc ); } /* Global */
/* * 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 */
/* * ParseCommandLine - parse a command line */ vi_rc ParseCommandLine( const char *cmdl, linenum *n1, bool *n1flag, linenum *n2, bool *n2flag, int *token, const char **data ) { char *tres, *tmp; int j; linenum l; vi_rc rc; /* * set up for parse */ tres = alloca( MAX_INPUT_LINE ); tmp = alloca( MAX_INPUT_LINE ); if( tmp == NULL || tres == NULL ) { return( ERR_NO_STACK ); } *n1flag = false; *n2flag = false; *data = ""; /* * change null command to '.' */ cmdl = SkipLeadingSpaces( cmdl ); if( *cmdl == '\0' ) { cmdl = "."; } /* * check for magic '%' - all lines */ if( *cmdl == '%' ) { *n1flag = true; *n2flag = true; *n1 = 1; rc = CFindLastLine( n2 ); if( rc != ERR_NO_ERR ) { return( rc ); } cmdl = SkipLeadingSpaces( cmdl + 1 ); /* * check for magic '#' - selected region */ } else if( *cmdl == '#' || *cmdl == '@' ) { if( !SelRgn.selected ) { if( *cmdl == '#' ) { return( ERR_NO_SELECTION ); } else { // use @ in scripts (eg mcsel.vi) when // we KNOW something was just selected SelRgn.selected = true; } } *n1flag = true; *n2flag = true; if( SelRgn.start.line > SelRgn.end.line ) { *n1 = SelRgn.end.line; *n2 = SelRgn.start.line; } else { *n1 = SelRgn.start.line; *n2 = SelRgn.end.line; } cmdl = SkipLeadingSpaces( cmdl + 1 ); /* * try to get line range */ } else { rc = GetAddress( &cmdl, &l ); if( rc > ERR_NO_ERR || rc == DO_NOT_CLEAR_MESSAGE_WINDOW ) { return( rc ); } if( rc == ERR_NO_ERR ) { *n1flag = true; *n1 = l; cmdl = SkipLeadingSpaces( cmdl ); if( *cmdl == ',' ) { cmdl = SkipLeadingSpaces( cmdl + 1 ); rc = GetAddress( &cmdl, &l ); if( rc > ERR_NO_ERR ) { return( rc ); } if( rc != ERR_NO_ERR ) { return( ERR_INVALID_COMMAND ); } *n2flag = true; /* * swap order (if start > end) */ if( *n1 > l ) { *n2 = *n1; *n1 = l; } else { *n2 = l; } } } } /* * check for system token */ if( *cmdl == '!' ) { *data = cmdl + 1; *token = PCL_T_SYSTEM; return( ERR_NO_ERR ); } /* * get token and data */ cmdl = GetNextWord( cmdl, tres, pkwDelims ); if( *tres == '\0' ) { return( ERR_NO_ERR ); } if( CheckAlias( tres, tmp ) == ERR_NO_ERR ) { strcat( tmp, cmdl ); cmdl = GetNextWord( tmp, tres, pDelims ); if( *tres == '\0' ) { return( ERR_NO_ERR ); } } j = Tokenize( TokensCmdLine, tres, false ); if( j == TOK_INVALID ) { j = Tokenize( TokensEx, tres, false ); if( j != TOK_INVALID ) { j += 1000; } } *token = j; *data = cmdl; return( ERR_NO_ERR ); } /* ParseCommandLine */
/* * 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 */
/* * RunCommandLine - run a command line command */ vi_rc RunCommandLine( const char *cmdl ) { int i, x, y, x2, y2; bool n1f, n2f; int tkn, flag; bool test1; linenum n1, n2; char st[FILENAME_MAX]; info *cinfo; long val; jmp_buf jmpaddr; vi_rc rc; const char *data; /* * parse command string */ tkn = TOK_INVALID; rc = ParseCommandLine( cmdl, &n1, &n1f, &n2, &n2f, &tkn, &data ); if( rc != ERR_NO_ERR ) { return( rc ); } if( !n2f ) { if( !n1f ) { n1 = n2 = CurrentPos.line; } else { n2 = n1; } } /* * process tokens */ rc = ERR_INVALID_COMMAND; test1 = n1f || n2f; switch( tkn ) { case PCL_T_ABOUT: rc = DoAboutBox(); break; case PCL_T_PUSH: rc = PushFileStackAndMsg(); break; case PCL_T_POP: rc = PopFileStack(); break; case PCL_T_EXECUTE: data = SkipLeadingSpaces( data ); if( *data != '\0' ) { key_map scr; rc = AddKeyMap( &scr, data ); if( rc != ERR_NO_ERR ) { break; } rc = RunKeyMap( &scr, 1L ); MemFree( scr.data ); } break; case PCL_T_DELETEMENU: rc = DoMenuDelete( data ); break; case PCL_T_DELETEMENUITEM: rc = DoItemDelete( data ); break; case PCL_T_ADDMENUITEM: rc = AddMenuItem( data ); break; case PCL_T_MAXIMIZE: rc = MaximizeCurrentWindow(); break; case PCL_T_MINIMIZE: rc = MinimizeCurrentWindow(); break; case PCL_T_EXITFILESONLY: if( !ExitWithPrompt( false, false ) ) { rc = ERR_EXIT_ABORTED; } else { rc = ERR_NO_ERR; } break; case PCL_T_EXITALL: if( !ExitWithPrompt( true, false ) ) { rc = ERR_EXIT_ABORTED; } else { rc = ERR_NO_ERR; } break; case PCL_T_QUITALL: ExitWithVerify(); rc = ERR_NO_ERR; break; case PCL_T_KEYADD: data = SkipLeadingSpaces( data ); KeyAddString( data ); rc = ERR_NO_ERR; break; case PCL_T_UNALIAS: rc = UnAlias( data ); break; case PCL_T_UNABBREV: rc = UnAbbrev( data ); break; case PCL_T_UNMAP: case PCL_T_UNMAP_DMT: flag = MAPFLAG_MESSAGE + MAPFLAG_UNMAP; if( tkn == PCL_T_UNMAP_DMT ) { flag |= MAPFLAG_DAMMIT; } rc = MapKey( flag, data ); break; case PCL_T_EVAL: data = Expand( dataBuff, data, NULL ); i = setjmp( jmpaddr ); if( i != 0 ) { rc = (vi_rc)i; } else { StartExprParse( data, jmpaddr ); val = GetConstExpr(); ltoa( val, st, EditVars.Radix ); Message1( "%s", st ); rc = ERR_NO_ERR; } break; case PCL_T_COMPILE: case PCL_T_SOURCE: case PCL_T_LOAD: { char *tstr; srcline sline; data = GetNextWord1( data, st ); if( *st == '\0' ) { rc = ERR_NO_FILE_SPECIFIED; break; } if( tkn == PCL_T_COMPILE ) { EditFlags.CompileScript = true; if( st[0] == '-' ) { if( st[1] == 'a' || st[1] == 'A' ) { EditFlags.CompileAssignments = true; if( st[1] == 'A' ) { EditFlags.CompileAssignmentsDammit = true; } data = GetNextWord1( data, st); if( *st == '\0' ) { rc = ERR_NO_FILE_SPECIFIED; break; } } } } if( tkn == PCL_T_LOAD ) { EditFlags.LoadResidentScript = true; } sline = 0; rc = Source( st, data, &sline ); EditFlags.LoadResidentScript = false; EditFlags.CompileScript = false; EditFlags.CompileAssignments = false; EditFlags.CompileAssignmentsDammit = false; if( EditFlags.SourceScriptActive ) { LastError = rc; } if( rc > ERR_NO_ERR ) { Error( "%s on line %u of \"%s\"", GetErrorMsg( rc ), sline, st ); } else { if( rc != DO_NOT_CLEAR_MESSAGE_WINDOW ) { if( tkn != PCL_T_SOURCE ) { if( tkn == PCL_T_LOAD ) { tstr = strLoad; } else { tstr = strCompile; } Message1( "Script \"%s\" %s, %u lines generated, %d errors", st, tstr, sline, SourceErrCount ); rc = DO_NOT_CLEAR_MESSAGE_WINDOW; } } } break; } case PCL_T_GENCONFIG: #ifndef __WIN__ data = GetNextWord1( data,st ); if( *st != '\0' ) { rc = GenerateConfiguration( st, true ); } else { rc = GenerateConfiguration( NULL, true ); } #else { bool temp = EditFlags.SaveConfig; EditFlags.SaveConfig = true; WriteProfile(); EditFlags.SaveConfig = temp; rc = ERR_NO_ERR; } #endif break; case PCL_T_COMPRESS: rc = CompressWhiteSpace(); break; case PCL_T_EXPAND: rc = ExpandWhiteSpace(); break; case PCL_T_SHOVE: rc = Shift( n1, n2, '>', true ); break; case PCL_T_SUCK: rc = Shift( n1, n2, '<', true ); break; case PCL_T_FILES: if( EditFlags.LineDisplay ) { rc = DisplayFileStatus(); } else { rc = EditFileFromList(); } break; case PCL_T_NEXT: rc = RotateFileForward(); break; case PCL_T_PREV: rc = RotateFileBackwards(); break; case PCL_T_HELP: rc = DoHelp( data ); break; case PCL_T_VIEW: case PCL_T_VIEW_DMT: EditFlags.ViewOnly = true; case PCL_T_EDIT: case PCL_T_EDIT_DMT: rc = EditFile( data, ( tkn == PCL_T_VIEW_DMT || tkn == PCL_T_EDIT_DMT ) ); EditFlags.ViewOnly = false; break; case PCL_T_OPEN: rc = OpenWindowOnFile( data ); break; case PCL_T_HIDE: case PCL_T_HIDE_DMT: rc = HideLineRange( n1, n2, ( tkn == PCL_T_HIDE_DMT ) ); break; case PCL_T_DELETE: rc = SetSavebufNumber( data ); if( rc != ERR_NO_ERR ) { break; } if( SelRgn.selected && !EditFlags.LineBased ) { AddSelRgnToSavebufAndDelete(); rc = ERR_NO_ERR; // @ may have turned this on - it is now definitely off SelRgn.selected = false; } else { rc = DeleteLineRange( n1, n2, SAVEBUF_FLAG ); } if( rc == ERR_NO_ERR ) { DCDisplayAllLines(); LineDeleteMessage( n1, n2 ); } break; case PCL_T_SAVEANDEXIT: data = GetNextWord1( data, st ); if( *st == '\0' ) { rc = SaveAndExit( st ); } else { rc = SaveAndExit( NULL ); } break; case PCL_T_PUT: case PCL_T_PUT_DMT: rc = SetSavebufNumber( data ); if( rc != ERR_NO_ERR ) { break; } rc = SaveAndResetFilePos( n1 ); if( rc == ERR_NO_ERR ) { if( tkn == PCL_T_PUT ) { rc = InsertSavebufAfter(); } else { rc = InsertSavebufBefore(); } RestoreCurrentFilePos(); } break; case PCL_T_YANK: rc = SetSavebufNumber( data ); if( rc != ERR_NO_ERR ) { break; } if( SelRgn.selected && !EditFlags.LineBased ) { rc = YankSelectedRegion(); // @ may have turned this on - it is now definitely off SelRgn.selected = false; } else { rc = YankLineRange( n1, n2 ); } break; case PCL_T_SUBSTITUTE: rc = Substitute( n1, n2, data ); break; case PCL_T_GLOBAL: case PCL_T_GLOBAL_DMT: if( !test1 ) { n1 = 1; rc = CFindLastLine( &n2 ); if( rc != ERR_NO_ERR ) { break; } } rc = Global( n1,n2, data, ( tkn == PCL_T_GLOBAL_DMT ) ); break; case PCL_T_WRITEQUIT: if( CurrentFile == NULL ) { rc = NextFile(); } else { CurrentFile->modified = true; data = GetNextWord1( data, st ); if( *st != '\0' ) { rc = SaveAndExit( st ); } else { rc = SaveAndExit( NULL ); } } break; case PCL_T_WRITE: case PCL_T_WRITE_DMT: data = GetNextWord1( data, st ); if( test1 ) { if( *st == '\0' ) { rc = ERR_NO_FILE_SPECIFIED; } else { rc = SaveFile( st, n1, n2, ( tkn == PCL_T_WRITE_DMT ) ); } } else { if( st[0] != '\0' ) { #ifdef __WIN__ if( st[0] == '?' && st[1] == '\0' ) { rc = SaveFileAs(); break; } else { rc = SaveFile( st, -1, -1, ( tkn == PCL_T_WRITE_DMT ) ); } #else rc = SaveFile( st, -1, -1, ( tkn == PCL_T_WRITE_DMT ) ); #endif } else { rc = SaveFile( NULL, -1, -1, ( tkn == PCL_T_WRITE_DMT ) ); if( rc == ERR_NO_ERR ) { Modified( false ); } } } break; case PCL_T_READ: rc = ReadAFile( n1, data ); break; case PCL_T_QUIT: #ifdef __WIN__ rc = CurFileExitOptionSaveChanges(); #else rc = NextFile(); #endif break; case PCL_T_QUIT_DMT: rc = NextFileDammit(); break; case PCL_T_DATE: GetDateTimeString( st ); Message1( st ); rc = DO_NOT_CLEAR_MESSAGE_WINDOW; break; case PCL_T_CD: data = GetNextWord1( data, st ); if( *st != '\0' ) { rc = SetCWD( st ); } else { rc = ERR_NO_ERR; } if( rc == ERR_NO_ERR ) { Message1( "Current directory is %s",CurrentDirectory ); } break; case PCL_T_SHELL: EVIL_SHELL: { #if defined( __NT__ ) && !defined( __WIN__ ) ExecCmd( NULL, NULL, NULL ); #else char foo[FILENAME_MAX]; strcpy( foo, Comspec ); ExecCmd( NULL, NULL, foo ); #endif DoVersion(); rc = ERR_NO_ERR; } break; case PCL_T_SYSTEM: if( n1f && n2f ) { rc = DoGenericFilter( n1, n2, data ); } else { data = SkipLeadingSpaces( data ); if( *data == '\0' ) { goto EVIL_SHELL; } ExecCmd( NULL, NULL, data ); rc = ERR_NO_ERR; } break; case PCL_T_RESIZE: rc = ResizeCurrentWindowWithKeys(); break; case PCL_T_TILE: data = GetNextWord1( data, st ); if( st[0] != '\0' ) { if( st[0] == 'v' ) { y = 1; for( x = 0, cinfo = InfoHead; cinfo != NULL; cinfo = cinfo->next ) { x++; } } else if( st[0] == 'h' ) { x = 1; for( y = 0, cinfo = InfoHead; cinfo != NULL; cinfo = cinfo->next ) { y++; } } else { x = atoi( st ); data = GetNextWord1( data, st ); if( *st == '\0' ) { break; } else { y = atoi( st ); } } } else { x = EditVars.MaxWindowTileX; y = EditVars.MaxWindowTileY; } if( x > 0 && y > 0) { rc = WindowTile( x, y ); } break; case PCL_T_CASCADE: rc = WindowCascade(); break; case PCL_T_MOVEWIN: rc = MoveCurrentWindowWithKeys(); break; case PCL_T_TAG: data = GetNextWord1( data, st ); if( *st != '\0' ) { rc = TagHunt( st ); } break; case PCL_T_FGREP: { bool ci; data = SkipLeadingSpaces( data ); ci = EditFlags.CaseIgnore; if( data[0] == '-' ) { if( data[1] == 'c' ) { ci = false; data += 2; data = SkipLeadingSpaces( data ); rc = GetStringWithPossibleQuote( &data, st ); } else if( data[1] == 'i' ) { ci = true; data += 2; data = SkipLeadingSpaces( data ); rc = GetStringWithPossibleQuote( &data, st ); } else if( data[1] == 'f' ) { data += 2; data = SkipLeadingSpaces( data ); #ifdef __WIN__ // call fancy grep window { fancy_find *ff; /* ff will be set to point at a static fancy find struct * in the snoop module */ char snoopbuf[FILENAME_MAX]; if( !GetSnoopStringDialog( &ff ) ) { return( ERR_NO_ERR ); } strcpy( snoopbuf, ff->path ); /* assume no string means current directory */ if( strlen( snoopbuf ) && snoopbuf[strlen( snoopbuf ) - 1] != '\\' ){ strcat( snoopbuf, "\\" ); } MySprintf( st, "%s", ff->find ); strcat( snoopbuf, ff->ext ); ci = ff->case_ignore; if( !ff->use_regexp ) { //MakeExpressionNonRegular( st ); rc = DoFGREP( snoopbuf, st, ci ); } else { rc = DoEGREP( snoopbuf, st ); } break; } #endif } } else { rc = GetStringWithPossibleQuote( &data, st ); } if( rc != ERR_NO_STRING ) { rc = DoFGREP( data, st, ci ); } } break; case PCL_T_EGREP: rc = GetStringWithPossibleQuote( &data, st ); if( rc != ERR_NO_STRING ) { rc = DoEGREP( data, st ); } break; case PCL_T_SIZE: data = GetNextWord1( data, st ); if( *st == '\0' ) { break; } x = atoi( st ); data = GetNextWord1( data, st ); if( *st == '\0' ) { break; } y = atoi( st ); data = GetNextWord1( data, st ); if( *st == '\0' ) { break; } x2 = atoi( st ); data = GetNextWord1( data, st ); if( *st == '\0' ) { break; } y2 = atoi( st ); rc = CurrentWindowResize( x, y, x2, y2 ); break; case PCL_T_ECHO: data = GetNextWord1( data, st ); if( *st == '\0' ) { break; } rc = ERR_NO_ERR; if( !stricmp( st, "on" ) ) { EditFlags.EchoOn = true; break; } else if( !stricmp( st, "off" ) ) { EditFlags.EchoOn = false; break; } x = atoi( st ); data = SkipLeadingSpaces( data ); /* * FIXME: This is not good - I will definately have to * fix this code up. But right now I have to get the * editor ready for tomorrow. Brad. */ if( data[0] == '"' || data[0] == '/' ) { GetStringWithPossibleQuote( &data, st ); if( x > 2 ) { /* this is obviously a sick individual */ Error( "Invalid Echo" ); } else if( x == 1 ) { Message1( st ); } else if( x == 2 ) { Message2( st ); } // DisplayLineInWindow( MessageWindow, x, st ); } else { if( x > 2 ) { /* this is obviously a sick individual */ Error( "Invalid Echo" ); } else if( x == 1 ) { Message1( data ); } else if( x == 2 ) { Message2( data ); } // DisplayLineInWindow( MessageWindow, x, data ); } break; #ifdef VI_RCS case PCL_T_CHECKOUT: rc = ERR_NO_ERR; #ifdef __WINDOWS__ if( isOS2() ) break; // OS/2 shell returns before checkout finishes #endif if( CurrentFile != NULL ) { rc = ViRCSCheckout( rc ); } break; case PCL_T_CHECKIN: if( CurrentFile != NULL ) { rc = ViRCSCheckin( rc ); } break; #endif default: if( tkn >= 1000 ) { rc = ProcessEx( n1, n2, n2f, tkn - 1000, data ); break; } rc = TryCompileableToken( tkn, data, true ); if( rc != NOT_COMPILEABLE_TOKEN ) { break; } rc = ProcessWindow( tkn, data ); if( rc >= ERR_NO_ERR ) { break; } case TOK_INVALID: if( n1f && !n2f ) { if( !n1 ) { n1 = 1; } MemorizeCurrentContext(); rc = GoToLineNoRelCurs( n1 ); if( rc == ERR_NO_ERR ) { GoToColumnOnCurrentLine( 1 ); if( EditFlags.LineDisplay ) { MyPrintf( "%s\n", CurrentLine->data ); } } return( rc ); } rc = ERR_INVALID_COMMAND; break; } if( rc == ERR_NO_ERR ) { rc = DO_NOT_CLEAR_MESSAGE_WINDOW; } return( rc ); } /* RunCommandLine */
/* * SaveFile - save data from current file */ vi_rc SaveFile( char *name, linenum start, linenum end, int dammit ) { int i; bool existflag = FALSE, restpath = FALSE, makerw = FALSE; char *fn; fcb *cfcb, *sfcb, *efcb; linenum s, e, lc; long bc = 0; status_type lastst; vi_rc rc; int write_crlf; if( CurrentFile == NULL ) { return( ERR_NO_FILE ); } /* * get file name */ if( name == NULL ) { if( CurrentFile->viewonly ) { return( ERR_FILE_VIEW_ONLY ); } if( CFileReadOnly() ) { rc = readOnlyCheck(); if( rc != ERR_NO_ERR ) { return( ERR_READ_ONLY_FILE ); } makerw = TRUE; } fn = CurrentFile->name; restpath = TRUE; } else { existflag = TRUE; fn = name; } if( fn[0] == 0 ) { return( ERR_NO_FILE_NAME ); } if( SameFile( fn, CurrentFile->name ) ) { if( CurrentFile->viewonly ) { return( ERR_FILE_VIEW_ONLY ); } } if( dammit ) { existflag = FALSE; } /* * get range and fcbs */ if( start == -1L && end == -1L ) { s = 1L; rc = CFindLastLine( &e ); if( rc != ERR_NO_ERR ) { return( rc ); } } else { s = start; e = end; } lc = e - s + 1; rc = FindFcbWithLine( s, CurrentFile, &sfcb ); if( rc != ERR_NO_ERR ) { return( rc ); } rc = FindFcbWithLine( e, CurrentFile, &efcb ); if( rc != ERR_NO_ERR ) { return( rc ); } if( restpath ) { rc = ChangeDirectory( CurrentFile->home ); if( rc != ERR_NO_ERR ) { return( rc ); } } if( !CurrentFile->is_stdio ) { if( makerw ) { chmod( fn, PMODE_RW ); } rc = FileOpen( fn, existflag, O_TRUNC | O_WRONLY | O_BINARY | O_CREAT, WRITEATTRS, &fileHandle); if( rc != ERR_NO_ERR ) { Message1( strerror( errno ) ); return( rc ); } } else { fileHandle = 0; #ifdef __WATCOMC__ setmode( fileno( stdout ), O_BINARY ); #endif } /* * start writing fcbs */ #ifdef __WIN__ ToggleHourglass( TRUE ); #endif if( EditFlags.CRLFAutoDetect ) { write_crlf = CurrentFile->write_crlf; } else { write_crlf = EditFlags.WriteCRLF; } lastst = UpdateCurrentStatus( CSTATUS_WRITING ); for( cfcb = sfcb; cfcb != efcb; cfcb = cfcb->next ) { rc = writeRange( s, cfcb->end_line, cfcb, &bc, write_crlf, TRUE ); if( rc != ERR_NO_ERR ) { #ifdef __WIN__ ToggleHourglass( FALSE ); #endif UpdateCurrentStatus( lastst ); return( rc ); } s = cfcb->end_line + 1; } /* * last bit */ rc = writeRange( s, e, efcb, &bc, write_crlf, EditFlags.LastEOL ); #ifdef __WIN__ ToggleHourglass( FALSE ); #endif UpdateCurrentStatus( lastst ); if( rc != ERR_NO_ERR ) { return( rc ); } if( !CurrentFile->is_stdio ) { i = close( fileHandle ); if( makerw ) { chmod( fn, PMODE_R ); } if( i == -1 ) { Message1( strerror( errno ) ); return( ERR_FILE_CLOSE ); } } if( restpath ) { rc = ChangeDirectory( CurrentDirectory ); if( rc != ERR_NO_ERR ) { return( rc ); } } FileIOMessage( fn, lc, bc ); return( ERR_NO_ERR ); } /* SaveFile */