/* * markRegion - mark a region as selected/unselected */ static void markRegion( bool val ) { fcb *cfcb; line *cline; linenum ln; linenum s, e; if( SelRgn.start.line > SelRgn.end.line ) { s = SelRgn.end.line; e = SelRgn.start.line; } else { s = SelRgn.start.line; e = SelRgn.end.line; } if( CGimmeLinePtr( s, &cfcb, &cline ) ) { return; } ln= e - s; for( ;; ) { cline->u.ld.hilite = val; ln--; if( ln < 0 ) { break; } if( CGimmeNextLinePtr( &cfcb, &cline ) ) { break; } } } /* markRegion */
/* * GetHiddenLineCount - get number of hidden lines in a range */ linenum GetHiddenLineCount( linenum s, linenum e ) { line *cline; fcb *cfcb; int i; linenum cnt, tmp; if( s > e ) { tmp = s; s = e; e = tmp; } i = CGimmeLinePtr( s, &cfcb, &cline ); if( i ) { return( 0L ); } cnt = 0L; while( s <= e ) { if( cline->u.ld.hidden ) { cnt++; } s++; i = CGimmeNextLinePtr( &cfcb, &cline ); if( i ) { break; } } return( cnt ); } /* GetHiddenLineCount */
/* * GetHiddenRange - get range of lines hidden around a given line */ void GetHiddenRange( linenum l, linenum *s, linenum *e ) { line *cline, *oline; fcb *cfcb, *ofcb; int i; (*s) = (*e) = l; i = CGimmeLinePtr( l, &ofcb, &oline ); if( i ) { return; } /* * go back */ cfcb = ofcb; cline = oline; for( ;; ) { i = GimmePrevLinePtr( &cfcb, &cline ); if( i ) { break; } if( cline->u.ld.hidden ) { (*s)--; continue; } else { break; } } /* * go forwards */ cfcb = ofcb; cline = oline; for( ;; ) { i = CGimmeNextLinePtr( &cfcb, &cline ); if( i ) { break; } if( cline->u.ld.hidden ) { (*e)++; continue; } else { break; } } } /* GetHiddenRange */
static void getLiteral( ss_block *ss_new, char *start, int skip ) { char *text; char lastchar = '\0'; bool empty; bool multiLine = flags.inString; line *line; fcb *fcb; char *data; vi_rc rc; empty = true; for( text = start + skip; *text != '\0'; ++text ) { if( text[0] == '\'' ) { if( text[1] != '\'' ) break; ++text; } empty = false; } flags.inString = false; if( *text == '\0' ) { // if next line a continuation line, then flag flags.inString, else // flag unterminated string rc = CGimmeLinePtr( thisLine + 1, &fcb, &line ); for( ;; ) { if( rc != ERR_NO_ERR ) { break; } data = (line->u.ld.nolinedata) ? WorkLine->data : line->data; if( !iscomment( data[0] ) ) { break; } rc = CGimmeNextLinePtr( &fcb, &line ); } ss_new->type = SE_INVALIDTEXT; if( rc == ERR_NO_ERR && !isInitialLine( line ) ) { ss_new->type = SE_STRING; flags.inString = true; } } else { text++; lastchar = tolower( *text ); switch( lastchar ) { case 'c': text++; ss_new->type = SE_STRING; break; case 'x': text++; ss_new->type = SE_HEX; break; case 'o': text++; ss_new->type = SE_OCTAL; break; default: // hard to say if invalid or not - take a guess if( islower( *text ) ) { text++; ss_new->type = SE_INVALIDTEXT; } else { ss_new->type = SE_STRING; } break; } } ss_new->len = text - start; if( empty && !multiLine ) { ss_new->type = SE_INVALIDTEXT; } }
/* * GenericJoinCurrentLineToNext */ vi_rc GenericJoinCurrentLineToNext( bool remsp ) { line *nline = CurrentLine; fcb *nfcb = CurrentFcb; int i, j, k; vi_rc rc; /* * get next line data */ rc = CGimmeNextLinePtr( &nfcb, &nline ); if( rc != ERR_NO_ERR ) { return( rc ); } if( CurrentLine->len + nline->len + 1 >= EditVars.MaxLine ) { return( ERR_LINE_FULL ); } /* * now, copy in the data */ StartUndoGroup( UndoStack ); CurrentLineReplaceUndoStart(); CurrentLineReplaceUndoEnd( true ); GetCurrentLine(); if( remsp ) { while( WorkLine->len > 0 && WorkLine->data[WorkLine->len - 1] == ' ' ) { WorkLine->data[WorkLine->len - 1] = 0; WorkLine->len--; } j = FindStartOfALine( nline ) - 1; k = 0; if( !(j == 0 && nline->data[0] == ' ') ) { if( WorkLine->len != 0 ) { WorkLine->data[WorkLine->len] = ' '; k = WorkLine->len + 1; } for( i = j; i <= nline->len; i++ ) { WorkLine->data[k + i - j] = nline->data[i]; } } } else { k = WorkLine->len; for( i = 0; i <= nline->len; i++ ) { WorkLine->data[k + i] = nline->data[i]; } } WorkLine->len = strlen( WorkLine->data ); ReplaceCurrentLine(); /* * delete next line */ rc = DeleteLineRange( CurrentPos.line + 1, CurrentPos.line + 1, 0 ); if( rc != ERR_NO_ERR ) { return( rc ); } EndUndoGroup( UndoStack ); if( remsp ) { if( k < 2 ) { k = 2; } rc = GoToColumn( k - 1, CurrentLine->len ); if( rc != ERR_NO_ERR ) { return( rc ); } } DCDisplayAllLines(); return( ERR_NO_ERR ); } /* GenericJoinCurrentLineToNext */
/* * 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 */
void InitRexxFlags( linenum line_no ) { fcb *fcb; char *text; char *starttext; line *thisline; line *topline; char topChar; vi_rc rc; bool withinQuotes = false; line *line; bool inBlock = false; flags.inCComment = false; flags.inCPPComment = false; flags.inString = false; flags.inPreprocessor = false; CGimmeLinePtr( line_no, &fcb, &thisline ); line = thisline; while( (rc = GimmePrevLinePtr( &fcb, &line )) == ERR_NO_ERR ) { if( line->data[line->len - 1] != '\\' ) { break; } inBlock = true; } if( rc == ERR_NO_ERR ) { topline = line; if( inBlock ) { CGimmeNextLinePtr( &fcb, &line ); } } else { topline = NULL; if( inBlock ) { CGimmeLinePtr( 1, &fcb, &line ); } else { return; } } if( inBlock ) { // jot down whether it started with # text = line->data; while( *text != '\0' && isspace( *text ) ) { text++; } topChar = *text; // parse down through lines, noticing /*, */ and " while( line != thisline ) { for( text = line->data; ; ++text ) { for( ; *text != '\0' && *text != '/'; ++text ) { if( text[0] == '"' ) { if( !withinQuotes ) { withinQuotes = true; } else if( text[-1] != '\\' || text[-2] == '\\' ) { withinQuotes = false; } } } if( text[0] == '\0' ) { break; } if( !withinQuotes ) { if( text[-1] == '/' ) { flags.inCPPComment = true; } else if( text[1] == '*' ) { flags.inCComment = true; lenCComment = 100; } } if( text[-1] == '*' && !withinQuotes ) { flags.inCComment = false; } } rc = CGimmeNextLinePtr( &fcb, &line ); } // if not in a comment (and none above), we may be string or pp if( !flags.inCComment ) { if( topChar == '#' && !EditFlags.PPKeywordOnly ) { flags.inPreprocessor = true; } if( withinQuotes ) { flags.inString = true; } } } if( topline == NULL ) { return; } if( !flags.inCComment ) { // keep going above multi-line thing till hit /* or */ line = topline; do { starttext = line->data; for( text = starttext + line->len; ; --text ) { while( text != starttext && *text != '/' ) { text--; } if( text[1] == '*' && text[0] == '/' && text[-1] != '/' ) { if( text == starttext ) { flags.inCComment = true; lenCComment = 100; return; } withinQuotes = false; do { text--; if( text[0] == '"' ) { if( !withinQuotes ) { withinQuotes = true; } else if( text[-1] != '\\' || text[-2] == '\\' ) { withinQuotes = false; } } } while( text != starttext ); if( withinQuotes ) { flags.inString = true; } else { flags.inCComment = true; lenCComment = 100; } return; } if( text == starttext ) { break; } if( text[-1] == '*' ) { // we may actually be in a string, but that's extreme // (if this becomes a problem, count the "s to beginning // of line, check if multiline, etc. etc.) return; } } rc = GimmePrevLinePtr( &fcb, &line ); } while( rc == ERR_NO_ERR ); } }
/* * Shift - shove a tab in/out over a line range */ vi_rc Shift( linenum s, linenum e, char dir, bool msgflag ) { int shv; linenum fullcnt = 0; vi_rc rc; /* * set up undo */ if( rc = ModificationTest() ) { return( rc ); } rc = UndoReplaceLines( s, e ); if( rc != ERR_NO_ERR ) { return( rc ); } /* * now, point to start line */ rc = SaveAndResetFilePos( s ); if( rc != ERR_NO_ERR ) { return( rc ); } /* * process all lines */ for( CurrentPos.line = s; CurrentPos.line <= e; CurrentPos.line++ ) { /* * Add/Subtract leading tab space */ GetCurrentLine(); shv = ShiftWidth; if( dir != '>' ) { shv *= -1; } if( AddLeadingTabSpace( &WorkLine->len, WorkLine->data, shv ) ) { ++fullcnt; } ReplaceCurrentLine(); if( CurrentPos.line != e ) { rc = CGimmeNextLinePtr( &CurrentFcb, &CurrentLine ); if( rc != ERR_NO_ERR ) { RestoreCurrentFilePos(); return( rc ); } } } /* * done, say so and go back */ RestoreCurrentFilePos(); if( msgflag ) { Message1( "%l lines %c'ed", e - s + 1, dir ); if( fullcnt > 0 ) { Message2( "%l full lines not processed", fullcnt ); } } if( CurrentPos.line >= s && CurrentPos.line <= e ) { CheckCurrentColumn(); } DCDisplayAllLines(); SetWindowCursor(); Modified( TRUE ); return( DO_NOT_CLEAR_MESSAGE_WINDOW ); } /* Shift */
void InitPerlFlags( linenum line_no ) { fcb *fcb; char *text; line *thisline; // line *topline; vi_rc rc; bool withinQuotes = false; line *line; bool inBlock = false; flags.inString = false; flags.beforeRegExp = true; flags.doubleRegExp = false; CGimmeLinePtr( line_no, &fcb, &thisline ); line = thisline; rc = GimmePrevLinePtr( &fcb, &line ); while( rc == ERR_NO_ERR ) { if( line->data[line->len - 1] != '\\' ) { break; } inBlock = true; rc = GimmePrevLinePtr( &fcb, &line ); } if( rc == ERR_NO_ERR ) { // topline = line; if( inBlock ) { CGimmeNextLinePtr( &fcb, &line ); } } else { // topline = NULL; if( inBlock ) { CGimmeLinePtr( 1, &fcb, &line ); } else { return; } } if( inBlock ) { // parse down through lines, noticing " while( line != thisline ) { text = line->data; while( *text ) { if( *text == '"' ) { if( !withinQuotes ) { withinQuotes = true; } else if( *(text - 1) != '\\' || *(text - 2) == '\\' ) { withinQuotes = false; } } text++; } rc = CGimmeNextLinePtr( &fcb, &line ); } if( withinQuotes ) { flags.inString = true; } } }
/* * FindRegularExpression - do a forward search for a regular expression */ vi_rc FindRegularExpression( char *pat, i_mark *pos1, char **linedata, linenum termline, find_type flags ) { vi_rc rc; int found; linenum ilineno = 0; bool wrapped = false; char *data; line *cline; fcb *cfcb; int scol; linenum sline; /* * initialize for search */ if( wrapMsgPrinted ) { wrapMsgPrinted = false; ClearWindow( message_window_id ); } sline = pos1->line; if( flags & FINDFL_WRAP ) { ilineno = sline; } rc = CGimmeLinePtr( sline, &cfcb, &cline ); if( rc != ERR_NO_ERR ) { return( rc ); } scol = pos1->column; if( pat != NULL ) { rc = CurrentRegComp( pat ); if( rc != ERR_NO_ERR ) { return( rc ); } } /* * loop until string found */ data = &cline->data[scol]; while( (found = RegExec( CurrentRegularExpression, data, (data == cline->data) )) == 0 ) { if( RegExpError != ERR_NO_ERR ) { return( RegExpError ); } /* * get next line */ rc = CGimmeNextLinePtr( &cfcb, &cline ); if( rc == ERR_NO_ERR ) { ++sline; } else if( rc == ERR_NO_MORE_LINES ) { if( (flags & FINDFL_WRAP) == 0 ) { return( ERR_FIND_END_OF_FILE ); } else { Message1( wrapMsg, "bottom" ); MyBeep(); wrapMsgPrinted = true; } if( wrapped ) { return( ERR_FIND_NOT_FOUND ); } sline = 1; 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 = 0; data = cline->data; } *linedata = cline->data; pos1->column = GetCurrRegExpColumn( cline->data ); pos1->line = sline; return( ERR_NO_ERR ); } /* FindRegularExpression */
vi_rc DCUpdate( void ) { vi_rc rc; int i, nlines; fcb *fcb; line *line; dc dc; bool firstLine, firstTilde; linenum line_no; int displayOffset; char *displayText; #ifdef __WIN__ HDC hdc_wnd; #ifdef BITBLT_BUFFER_DISPLAY HDC hdc_mem; HBITMAP hbitmap; type_style *ws; #endif #else bool hasMouse; unsigned int hdc_wnd = 0; #endif if( EditFlags.Quiet || CurrentInfo == NULL ) { return( ERR_NO_ERR ); } #ifdef __WIN__ MyHideCaret( CurrentWindow ); hdc_wnd = GetDC( CurrentWindow ); #ifdef BITBLT_BUFFER_DISPLAY hdc_mem = CreateCompatibleDC( hdc_wnd ); ws = &(SEType[SE_WHITESPACE]); hbitmap = CreateCompatibleBitmap( hdc_wnd, WindowAuxInfo( CurrentWindow, WIND_INFO_WIDTH ), FontHeight( ws->font ) ); SelectObject( hdc_mem, hbitmap ); SelectObject( hdc_mem, ColorBrush( ws->background ) ); #endif #else hasMouse = DisplayMouse( false ); #endif rc = CGimmeLinePtr( LeftTopPos.line, &fcb, &line ); if( rc != ERR_NO_ERR ) { return( rc ); } nlines = CurrentInfo->dc_size; dc = CurrentInfo->dc; firstLine = true; firstTilde = true; for( i = 0, line_no = LeftTopPos.line; i < nlines; i++, line_no++ ) { if( dc->display ) { if( line ) { if( firstLine ) { if( dc->valid ) { // major speedup SSInitLanguageFlagsGivenValues( &(dc->flags) ); } else { SSInitLanguageFlags( line_no ); } firstLine = false; } displayText = line->data; if( line->u.ld.nolinedata ) { if( WorkLine->len >= 0 ) { displayText = WorkLine->data; } else { displayText = "*** ERR NULL DATA ***"; } } displayOffset = VirtualLineLen( displayText ); if( displayOffset > LeftTopPos.column ) { displayOffset = LeftTopPos.column; } } else { if( EditFlags.DrawTildes ) { displayText = "~"; } else { displayText = ""; if( firstTilde ) { displayText = EditVars.FileEndString; firstTilde = false; } } displayOffset = 0; } #ifdef BITBLT_BUFFER_DISPLAY DisplayLineInWindowWithSyntaxStyle( CurrentWindow, i + 1, line, line_no, displayText, displayOffset, hdc_wnd, hdc_mem ); #else DisplayLineInWindowWithSyntaxStyle( CurrentWindow, i + 1, line, line_no, displayText, displayOffset, hdc_wnd ); #endif dc->display = false; } else { // just in case displaying 2+ blocks in one update firstLine = true; } if( line ) { rc = CGimmeNextLinePtr( &fcb, &line ); } if( rc != ERR_NO_ERR && rc != ERR_NO_MORE_LINES ) { return( rc ); } dc++; } #ifdef __WIN__ #ifdef BITBLT_BUFFER_DISPLAY DeleteDC( hdc_mem ); DeleteObject( hbitmap ); #endif ReleaseDC( CurrentWindow, hdc_wnd ); MyShowCaret( CurrentWindow ); #else DisplayMouse( hasMouse ); #endif return( ERR_NO_ERR ); }
/* * ProcessEx - process an ex command */ vi_rc ProcessEx( linenum n1, linenum n2, bool n2f, int tkn, const char *data ) { vi_rc rc = ERR_INVALID_COMMAND, i; char word[MAX_STR]; linenum addr, tlines; fcb *cfcb; line *cline; fcb_list fcblist; GetNextWord1( data, word ); data = word; if( GetAddress( &data, &addr ) != ERR_NO_ERR ) { addr = -1; } tlines = n2 - n1 + 1; switch( tkn ) { case EX_T_APPEND: if( !EditFlags.ExMode ) { return( ERR_ONLY_VALID_IN_EX_MODE ); } if( !n2f ) { rc = Append( n1, true ); } break; case EX_T_CHANGE: if( !EditFlags.ExMode ) { return( ERR_ONLY_VALID_IN_EX_MODE ); } StartUndoGroup( UndoStack ); rc = DeleteLineRange( n1, n2, 0 ); if( rc != ERR_NO_ERR ) { EndUndoGroup( UndoStack ); break; } rc = Append( n1 - 1, false ); if( rc != ERR_NO_ERR ) { EndUndoGroup( UndoStack ); break; } break; case EX_T_COPY: if( addr < 0 || IsPastLastLine( addr ) ) { return( ERR_INVALID_ADDRESS ); } i = GetCopyOfLineRange( n1, n2, &fcblist ); if( i ) { break; } rc = InsertLines( addr, &fcblist, UndoStack ); GoToLineNoRelCurs( addr ); if( rc == ERR_NO_ERR ) { Message1( strCmmsg, tlines, "copied", addr ); } break; case EX_T_INSERT: if( !EditFlags.ExMode ) { return( ERR_ONLY_VALID_IN_EX_MODE ); } if( !n2f ) { rc = Append( n1 - 1, true ); } break; case EX_T_JOIN: if( SaveAndResetFilePos( n1 ) != ERR_NO_ERR ) { rc = ERR_NO_SUCH_LINE; break; } if( tlines == 1 ) { n2 = n1 + 1; tlines = 2; } SetRepeatCount( tlines - 1 ); rc = JoinCurrentLineToNext(); RestoreCurrentFilePos(); GoToLineNoRelCurs( n1 ); if( rc == ERR_NO_ERR ) { Message1( "lines %l to %l joined", n1, n2 ); } break; case EX_T_LIST: if( !EditFlags.ExMode ) { return( ERR_ONLY_VALID_IN_EX_MODE ); } for( rc = CGimmeLinePtr( n1, &cfcb, &cline ); rc == ERR_NO_ERR; rc = CGimmeNextLinePtr( &cfcb, &cline ) ) { if( EditFlags.LineNumbers ) { MyPrintf( "%M %s\n", n1, cline->data ); } else { MyPrintf( "%s\n", cline->data ); } if( n1 >= n2 ) { break; } n1++; } break; case EX_T_MARK: rc = SetGenericMark( n1, 1, C2VIKEY( word[0] ) ); break; case EX_T_MOVE: if( addr < 0 || IsPastLastLine( addr ) ) { return( ERR_INVALID_ADDRESS ); } SavebufNumber = WORK_SAVEBUF; StartUndoGroup( UndoStack ); rc = DeleteLineRange( n1, n2, SAVEBUF_FLAG ); if( SavebufNumber != WORK_SAVEBUF ) { /* if this changes, the command will fail * this could be caused by checking out a read-only file * so fix the deleted text and give an error message */ DoUndo(); return( ERR_INVALID_COMMAND ); } if( rc != ERR_NO_ERR ) { EndUndoGroup( UndoStack ); break; } if( addr > n2 ) { addr -= tlines; } else if( addr >= n1 && addr <= n2 ) { addr = n1; } rc = InsertLines( addr, &WorkSavebuf->u.fcbs, UndoStack ); EndUndoGroup( UndoStack ); GoToLineNoRelCurs( addr ); if( rc == ERR_NO_ERR ) { Message1( strCmmsg, tlines, "moved", addr ); } break; case EX_T_UNDO: rc = DoUndo(); break; case EX_T_UNDO_DMT: rc = DoUndoUndo(); break; case EX_T_EQUALS: Message1( "%l", n1 ); rc = ERR_NO_ERR; break; case EX_T_VERSION: rc = DoVersion(); break; case EX_T_VISUAL: case EX_T_VISUAL_DMT: if( EditFlags.LineDisplay ) { ScreenPage( -1 ); EditFlags.ExMode = false; EditFlags.LineDisplay = false; EditFlags.ClockActive = true; ReDisplayScreen(); DoVersion(); } if( word[0] != '\0' ) { rc = EditFile( word, ( tkn == EX_T_VISUAL_DMT ) ); } else { rc = ERR_NO_ERR; } break; } return( rc ); } /* ProcessEx */