/* * SetWindowCursorForReal - set cursor in current window, if cursorNeedsDisp */ void SetWindowCursorForReal( void ) { if( !cursorNeedsDisplay || EditFlags.DisplayHold ) { return; } if( CurrentFile == NULL ) { HideCursor(); return; } #ifndef __WIN__ SetGenericWindowCursor( CurrentWindow, (int) (CurrentPos.line - LeftTopPos.line + 1), VirtualColumnOnCurrentLine( CurrentPos.column ) - LeftTopPos.column ); #else // for windows assume tabs to be of lenght 1 if( !EditFlags.RealTabs ){ SetGenericWindowCursor( CurrentWindow, (int) (CurrentPos.line - LeftTopPos.line + 1), VirtualColumnOnCurrentLine( CurrentPos.column ) - LeftTopPos.column ); } else { SetGenericWindowCursor( CurrentWindow, (int) (CurrentPos.line - LeftTopPos.line + 1), VirtualColumnOnCurrentLine( CurrentPos.column ) ); } #endif cursorNeedsDisplay = false; } /* SetWindowCursorForReal */
/* * InvokeColSelHook - invoke column hook with specified data */ vi_rc InvokeColSelHook( int sc, int ec ) { int j, i; char wordbuff[MAX_STR]; char data[MAX_STR + 32]; int lne; #ifndef __WIN__ int x1; int has_bord; #endif #ifndef __WIN__ has_bord = WindowAuxInfo( CurrentWindow, WIND_INFO_HAS_BORDER ); x1 = WindowAuxInfo( CurrentWindow, WIND_INFO_X1 ); if( LastEvent != VI_KEY( MOUSEEVENT ) ) { lne = WindowAuxInfo( CurrentWindow, WIND_INFO_Y1 ) + CurrentPos.line - LeftTopPos.line; if( has_bord ) { ++lne; } } else { lne = MouseRow; } #else if( LastEvent != VI_KEY( FAKEMOUSE ) ) { lne = (CurrentPos.line - LeftTopPos.line) * FontHeight( WIN_FONT( &EditWindow ) ); } else { lne = MouseY; } #endif j = 0; if( ec - sc >= MAX_STR ) { ec = sc + MAX_STR - 2; } for( i = sc - 1; i <= ec - 1; i++ ) { wordbuff[j++] = CurrentLine->data[i]; } wordbuff[j] = 0; #ifndef __WIN__ sc = x1 + VirtualColumnOnCurrentLine( sc ) - LeftTopPos.column; ec = x1 + VirtualColumnOnCurrentLine( ec ) - LeftTopPos.column; if( !has_bord ) { sc--; ec--; } #else sc = MyTextExtent( CurrentWindow, WIN_STYLE( &EditWindow ), &CurrentLine->data[0], sc ); ec = MyTextExtent( CurrentWindow, WIN_STYLE( &EditWindow ), &CurrentLine->data[0], ec ); #endif MySprintf( data, "\"%s\" %d %d %d %d", wordbuff, lne, sc, ec, ec - sc + 1 ); return( SourceHookData( SRC_HOOK_MOUSE_CHARSEL, data ) ); } /* InvokeColSelHook */
/* * HiliteAColumnRange - color a specified word on a line */ void HiliteAColumnRange( linenum line, int scol, int ecol ) { int s, e; s = VirtualColumnOnCurrentLine( scol ); e = VirtualColumnOnCurrentLine( ecol + 1 ) - 1; if( scol == 0 ) { s = 0; } changeColorOfDisplayLine( (int) (line - LeftTopPos.line + 1), s - LeftTopPos.column, e - LeftTopPos.column, &editw_info.hilight ); } /* HiliteAColumnRange */
/* * CheckCurrentColumn - check state of current column, return true if need to * redisplay page */ bool CheckCurrentColumn( void ) { int clen, vcp; bool dispall = false; clen = VirtualLineLen( CurrentLine->data ); if( clen == 0 ) { clen = 1; } ValidateCurrentColumn(); vcp = VirtualColumnOnCurrentLine( CurrentPos.column ); if( vcp != VirtualColumnDesired ) { if( clen >= VirtualColumnDesired ) { CurrentPos.column = RealColumnOnCurrentLine( VirtualColumnDesired ); } else { if( EditFlags.InsertModeActive || EditFlags.Modeless ) { CurrentPos.column = CurrentLine->len + 1; } else { CurrentPos.column = CurrentLine->len; } } ValidateCurrentColumn(); dispall = !CheckLeftColumn(); /* changed CurrentPos.column - update horiz scrollbar */ PositionHorizontalScrollThumb( current_window_id, LeftTopPos.column ); } VarAddGlobalLong( "C", (long) CurrentPos.column ); return( dispall ); } /* CheckCurrentColumn */
/* * ColorAColumnRange - color a specified word on a line */ void ColorAColumnRange( int row, int scol, int ecol, type_style *style ) { int s, e, t; s = VirtualColumnOnCurrentLine( scol ); e = VirtualColumnOnCurrentLine( ecol ); if( s > e ) { t = s; s = e; e = t; } s--; e--; changeColorOfDisplayLine( row, s - LeftTopPos.column, e - LeftTopPos.column, style ); } /* ColorAColumnRange */
/* * InitSelectedRegion - set start of selected region */ void InitSelectedRegion( void ) { SelRgn.lines = FALSE; SelRgn.start = CurrentPos; SelRgn.end = CurrentPos; SelRgn.start_col_v = VirtualColumnOnCurrentLine( CurrentPos.column ); #ifdef __WIN__ last_start_line = CurrentPos.line; last_end_line = CurrentPos.line; #endif } /* InitSelectedRegion */
/* * GoToColumn - go to a specified column */ vi_rc GoToColumn( int colno, int maxcol ) { int vc; if( CurrentFile == NULL ) { return( ERR_NO_FILE ); } if( maxcol == 0 ) { maxcol = 1; } if( colno == 0 ) { colno = 1; } if( colno < 1 || colno > maxcol ) { return( ERR_NO_SUCH_COLUMN ); } /* * compute new location, and re-display text if needed */ VirtualColumnDesired = VirtualColumnOnCurrentLine( colno ); CurrentPos.column = colno; if( !CheckLeftColumn() ) { DCDisplayAllLines(); PositionHorizontalScrollThumb( current_window_id, LeftTopPos.column ); } SetWindowCursor(); vc = VirtualColumnOnCurrentLine( CurrentPos.column ); UpdateStatusWindow(); VarAddGlobalLong( "C", (long) vc ); UpdateCursorDrag(); return( ERR_NO_ERR ); } /* GoToColumn */
static void ensureCursorDisplayed( void ) { int len, wc, diff; if( EditFlags.Modeless && ( CurrentFile != NULL ) ) { len = WindowAuxInfo( CurrentWindow, WIND_INFO_TEXT_LINES ); if( CurrentPos.line < LeftTopPos.line || CurrentPos.line > LeftTopPos.line + len - 1 ) { SetCurrentLine( CurrentPos.line ); } wc = VirtualColumnOnCurrentLine( CurrentPos.column ) - LeftTopPos.column; if( !ColumnInWindow( wc, &diff ) ) { SetCurrentColumn( CurrentPos.column ); } } }
/* * InvokeLineSelHook - invoke the mouse selection */ vi_rc InvokeLineSelHook( linenum s, linenum e ) { char tmp[32]; int lne, col; #ifndef __WIN__ int has_bord; #endif #ifndef __WIN__ if( LastEvent != VI_KEY( MOUSEEVENT ) ) { has_bord = WindowAuxInfo( CurrentWindow, WIND_INFO_HAS_BORDER ); lne = WindowAuxInfo( CurrentWindow, WIND_INFO_Y1 ) + CurrentPos.line - LeftTopPos.line; col = WindowAuxInfo( CurrentWindow, WIND_INFO_X1 ) + VirtualColumnOnCurrentLine( CurrentPos.column ) - LeftTopPos.column - 1; if( has_bord ) { ++lne; ++col; } if( col < 0 ) { col = 0; } } else { col = MouseCol; lne = MouseRow; } #else if( LastEvent != VI_KEY( FAKEMOUSE ) ) { /* assume we're not in insert mode *ouch* */ col = PixelFromColumnOnCurrentLine( CurrentPos.column ); lne = (CurrentPos.line - LeftTopPos.line) * FontHeight( WIN_FONT( &EditWindow ) ); } else { col = MouseX; lne = MouseY; } #endif MySprintf( tmp, "%d %d %l %l", lne, col, s, e ); return( SourceHookData( SRC_HOOK_MOUSE_LINESEL, tmp ) ); } /* InvokeLineSelHook */
/* * CheckLeftColumn - check if CurrentPos.column and LeftTopPos.column give a position * in the window; if not, LeftTopPos.column is changed appropriatly */ bool CheckLeftColumn( void ) { int diff, wc, pad; bool rc; wc = VirtualColumnOnCurrentLine( CurrentPos.column ) - LeftTopPos.column; rc = ColumnInWindow( wc, &diff ); if( !rc ) { // |diff| is already at least 1 pad = ( EditFlags.JumpyScroll ) ? SCROLL_HLINE - 1 : 0; if( diff < 0 ) { LeftTopPos.column += diff - pad; } else { LeftTopPos.column += diff + pad; } if( LeftTopPos.column < 0 ) { LeftTopPos.column = 0; } } return( rc ); } /* CheckLeftColumn */
/* * IMCloseBrace - handle '}' in insert mode */ vi_rc IMCloseBrace( void ) { int i, j; int ts; fcb *cfcb; line *cline; vi_rc rc; int newcol; i_mark pos; startNewLineUndo(); insertChar( TRUE, FALSE ); newcol = CurrentPos.column + 1; if( EditFlags.ShowMatch ) { ReplaceCurrentLine(); rc = FindMatch( &pos ); if( rc == ERR_NO_ERR ) { tempMatch( &pos ); } GetCurrentLine(); } if( EditFlags.CMode ) { i = 0; while( isspace( WorkLine->data[i] ) ) { i++; } if( WorkLine->data[i] == '}' ) { /* * added a {, so: * find matching } * find out indentation of that line * shift current line over to that indentation * set current indentation to that */ ReplaceCurrentLine(); rc = findMatchingBrace( &pos ); if( rc == ERR_NO_ERR ) { newcol = VirtualColumnOnCurrentLine( CurrentPos.column ); CGimmeLinePtr( pos.line, &cfcb, &cline ); i = FindStartOfALine( cline ); i = GetVirtualCursorPosition( cline->data, i ); j = i - VirtualColumnOnCurrentLine( CurrentPos.column ); ts = EditVars.ShiftWidth; if( j > 0 ) { EditVars.ShiftWidth = j; Shift( CurrentPos.line, CurrentPos.line, '>', FALSE ); } else if( j < 0 ) { EditVars.ShiftWidth = -j; Shift( CurrentPos.line, CurrentPos.line, '<', FALSE ); } EditVars.ShiftWidth = ts; newcol = 1 + RealColumnOnCurrentLine( j + newcol ); } GetCurrentLine(); } } GoToColumn( newcol, WorkLine->len + 1 ); return( ERR_NO_ERR ); } /* IMCloseBrace */
/* * 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 */
/* * UpdateStatusWindow - update the status window */ void UpdateStatusWindow( void ) { char *str, *ptr; char result[5 * MAX_STR]; char *res; int digits; long num; bool use_num; int line; char numstr[12]; int format; char c; if( BAD_ID( status_window_id ) || EditFlags.DisplayHold || EditFlags.Quiet || !EditFlags.StatusInfo || EditVars.StatusString == NULL ) { return; } res = result; line = 1; format = FMT_LEFT; EditFlags.ModeInStatusLine = false; for( str = EditVars.StatusString; (c = *str) != '\0'; ++str ) { if( c == '$' ) { str++; ptr = str; while( isdigit( *str ) ) { str++; } if( ptr != str ) { digits = strtoul( ptr, NULL, 10 ); } else { digits = 0; } use_num = false; num = 0; c = *str; if( c == '\0' ) break; switch( c ) { case '$': *res++ = '$'; break; case 'c': *res++ = ','; break; case 'n': *res = 0; StatusLine( line, result, format ); res = result; line++; break; case 'L': num = CurrentPos.line; use_num = true; break; case 'C': num = VirtualColumnOnCurrentLine( CurrentPos.column ); use_num = true; break; case 'D': #ifdef __WIN__ GetDateString( res ); #else GetDateTimeString( res ); #endif res += strlen( res ); break; case 'T': GetTimeString( res ); res += strlen( res ); break; case 'M': /* print the desired mode */ EditFlags.ModeInStatusLine = true; GetModeString( res ); res += strlen( res ); break; #ifdef __WIN__ case 'H': GetMenuHelpString( res ); res += strlen( res ); break; case '[': *res++ = STATUS_ESC_CHAR; *res++ = STATUS_NEXT_BLOCK; break; case '|': *res++ = STATUS_ESC_CHAR; *res++ = STATUS_FORMAT_CENTER; break; case '>': *res++ = STATUS_ESC_CHAR; *res++ = STATUS_FORMAT_RIGHT; break; case '<': *res++ = STATUS_ESC_CHAR; *res++ = STATUS_FORMAT_LEFT; break; #else case '|': format = FMT_CENTRE; break; case '>': format = FMT_RIGHT; break; case '<': format = FMT_LEFT; break; #endif } if( use_num ) { ltoa( num, numstr, 10 ); digits -= strlen( numstr ); while( digits > 0 ) { *res++ = ' '; digits--; } ptr = numstr; while( *ptr != '\0' ) { *res++ = *ptr++; } } } else { *res++ = c; } } *res = 0; if( res != result ) { StatusLine( line, result, format ); } } /* UpdateStatusWindow */
static void addSelection( ss_block *ss_start, linenum line_no ) { int sel_start_col, sel_end_col; int sel_start_line, sel_end_line; int tmp, i; bool swap_cols; ss_block *ss, *ss2; static ss_block ss_copy[MAX_SS_BLOCKS]; ss_block ss_save; // don't call me unless something selected assert( SelRgn.selected ); i = 0; // get nicely ordered values from SelRgn sel_end_col = VirtualColumnOnCurrentLine( SelRgn.end.column ) - 1; sel_start_col = SelRgn.start_col_v - 1; #ifdef __WIN__ if( EditFlags.RealTabs ) { sel_end_col = SelRgn.end.column - 1; sel_start_col = SelRgn.start.column - 1; } #endif swap_cols = false; if( SelRgn.start.line > SelRgn.end.line ) { sel_start_line = SelRgn.end.line; sel_end_line = SelRgn.start.line; swap_cols = true; } else { sel_start_line = SelRgn.start.line; sel_end_line = SelRgn.end.line; } if( SelRgn.start.line == SelRgn.end.line && sel_start_col > sel_end_col ) { swap_cols = true; } if( swap_cols ) { tmp = sel_start_col; sel_start_col = sel_end_col; sel_end_col = tmp; } // select entire line if( (sel_start_line < line_no && sel_end_line > line_no) || (SelRgn.lines && (sel_start_line == line_no || sel_end_line == line_no)) ) { ss_start->type = SE_SELECTION; ss_start->end = ss_start->len = BEYOND_TEXT; return; } // select subset within current line if( sel_start_line == sel_end_line && sel_start_line == line_no ) { if( sel_start_col == sel_end_col ) { return; } ss2 = ss_copy; for( ss = ss_start; ss->end < sel_start_col; ++ss ) { *ss2 = *ss; ss2++; } ss_save = *ss; if( (ss == ss_start && sel_start_col > 0) || (ss != ss_start && (ss - 1)->end + 1 != sel_start_col) ) { ss2->type = ss->type; ss2->len = ss->len - (ss->end - sel_start_col + 1); if( ss2->len != 0 ) { ss2->end = sel_start_col - 1; ss2++; } } ss2->type = SE_SELECTION; ss2->len = sel_end_col - sel_start_col; ss2->end = sel_end_col - 1; ss2++; if( ss_save.end >= sel_end_col ) { ss2->type = ss_save.type; ss2->len = ss_save.end - sel_end_col + 1; if( ss2->len != 0 ) { ss2->end = ss_save.end; ss2++; } } else { while( ss->end < sel_end_col ) { ss++; } if( ss->end >= sel_end_col ) { ss2->type = ss->type; ss2->len = ss->end - sel_end_col + 1; if( ss2->len != 0 ) { ss2->end = ss->end; ss2++; } } } if( ss->end != BEYOND_TEXT ) { do { ss++; *ss2 = *ss; ss2++; } while( ss->end != BEYOND_TEXT ); } memcpy( ss_start, ss_copy, MAX_SS_BLOCKS * sizeof( ss_block ) ); return; } // select from start of selection to far right if( sel_start_line == line_no ) { ss = ss_start; while( ss->end < sel_start_col ) { ss++; } if( (ss == ss_start && sel_start_col > 0) || (ss != ss_start && (ss - 1)->end + 1 != sel_start_col) ) { // split block just to the left ss->len -= ss->end - sel_start_col + 1; if( ss->len != 0 ) { ss->end = sel_start_col - 1; ss++; } } ss->type = SE_SELECTION; ss->end = ss->len = BEYOND_TEXT; return; } // select from far left to end of selection if( sel_end_line == line_no && sel_end_col != 0 ) { for( ss = ss_start; ss->end < sel_end_col; ++ss ) { i++; } ss2 = ss_start + 1; ss_save = *ss2; if( ss->end >= sel_end_col ) { ss_save.type = ss->type; ss_save.len = ss->end - sel_end_col + 1; if( ss_save.len != 0 ) { ss_save.end = ss->end; ss2++; i++; } } memmove( ss2, ss + 1, (MAX_SS_BLOCKS - i - 1) * sizeof( ss_block ) ); ss_start->type = SE_SELECTION; ss_start->end = sel_end_col - 1; ss_start->len = sel_end_col; if( ss2 == ss_start + 2 ) { *(ss_start + 1) = ss_save; } return; } // otherwise nothing is selected on this line }
vi_rc Change( range *r ) { int scol, ecol; int tmp; vi_rc rc; vi_key key; #ifndef __WIN__ int vecol; #endif /* * change line ranges */ if( r->start.line != r->end.line ) { StartUndoGroup( UndoStack ); if( !r->line_based ) { rc = Cut( r->start.line, r->start.column, r->end.line, r->end.column, true ); r->end.column = -1; scol = -1; ecol = -1; } else { if( r->start.line == CurrentPos.line ) { r->start.line++; } else { r->end.line--; } if( r->start.line <= r->end.line ) { rc = DeleteLineRange( r->start.line, r->end.line, 0 ); if( rc != ERR_NO_ERR ) { EndUndoGroup( UndoStack ); return( rc ); } } scol = FindStartOfCurrentLine() - 1; ecol = CurrentLine->len - 1; } DCDisplayAllLines(); rc = DeleteAndInsertText( scol, ecol ); EndUndoGroup( UndoStack ); return( rc ); } /* * change text on current line */ rc = ERR_NO_ERR; GoToLineNoRelCurs( r->start.line ); ecol = r->end.column; scol = r->start.column; #ifdef __WIN__ // GetCurrentLine(); strcpy( WorkLine->data, CurrentLine->data ); tmp = WorkLine->data[ecol]; WorkLine->data[ecol] = '$'; #else vecol = VirtualColumnOnCurrentLine( ecol + 1 ); vecol--; ExpandTabsInABuffer( CurrentLine->data, CurrentLine->len, WorkLine->data, EditVars.MaxLine + 1 ); WorkLine->len = strlen( WorkLine->data ); tmp = WorkLine->data[vecol]; WorkLine->data[vecol] = '$'; #endif if( WorkLine->len == 0 ) { WorkLine->data[1] = '\0'; } EditFlags.InsertModeActive = true; GoToColumn( scol + 1, CurrentLine->len ); EditFlags.InsertModeActive = false; DisplayWorkLine( true ); UnselectRegion(); DCUpdate(); #ifndef __WIN__ HiliteAColumnRange( CurrentPos.line, scol, ecol ); #endif /* * now, get ready to do change */ key = GetNextEvent( false ); #ifdef __WIN__ WorkLine->data[ecol] = tmp; #else WorkLine->data[vecol] = tmp; #endif DisplayWorkLine( true ); if( key == VI_KEY( ESC ) && !EditFlags.ChangeLikeVI ) { WorkLine->len = -1; GoToColumn( scol + 1, CurrentLine->len ); } else { KeyAdd( key ); rc = DeleteAndInsertText( scol, ecol ); } return( rc ); } /* Change */