/* * 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 */
/* * LocateCmd - parse a locate command (format: locate r,c[,len]) */ vi_rc LocateCmd( const char *data ) { char tmp[MAX_STR]; linenum r; int c; int len; #ifdef __WIN__ if( BAD_ID( current_window_id ) ) { return( ERR_INVALID_LOCATE ); } #endif data = GetNextWord1( data, tmp ); if( *tmp == '\0' ) { return( ERR_INVALID_LOCATE ); } r = atol( tmp ); data = GetNextWord1( data, tmp ); if( *tmp == '\0' ) { return( ERR_INVALID_LOCATE ); } c = atoi( tmp ); // real selection length while( isspace( *data ) ) { data++; } len = 0; if( *data != 0 ) { data = GetNextWord1( data, tmp ); if( *tmp == '\0' ) { return( ERR_INVALID_LOCATE ); } len = atoi( tmp ); } GoToLineNoRelCurs( r ); c = RealColumnOnCurrentLine( c ); GoToColumnOnCurrentLine( c + len ); #ifdef __WIN__ // likely only called by dde, which doesn't use event loop, // so must ensure cache ok and set cursor here DCInvalidateAllLines(); DCDisplayAllLines(); DCUpdate(); SetWindowCursor(); SetWindowCursorForReal(); #endif if( len > 0 ) { SetSelRegionCols( CurrentPos.line, c, c + len - 1 ); } return( ERR_NO_ERR ); } /* LocateCmd */
/* * 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 */
/* * UpdateDrag - update selected region */ void UpdateDrag( window_id id, int win_x, int win_y ) { int nx, ny, height; int moveCursor; SelRgn.selected = TRUE; moveCursor = 0; height = WindowAuxInfo( CurrentWindow, WIND_INFO_TEXT_LINES ); #ifdef __WIN__ if( id == CurrentWindow && InsideWindow( id, MouseX, MouseY ) ) { #else if( id == CurrentWindow && InsideWindow( id, win_x, win_y ) ) { #endif ny = LeftTopPos.line + win_y - 1; if( ny > CurrentFile->fcbs.tail->end_line ) { ny = CurrentFile->fcbs.tail->end_line; moveCursor = 1; } else if( ny < 1 ) { ny = 1; moveCursor = -1; } GoToLineRelCurs( ny ); win_x += LeftTopPos.column; nx = RealColumnOnCurrentLine( win_x ); GoToColumnOnCurrentLine( nx ); } else { #ifndef __WIN__ if( MouseRow >= WindowAuxInfo( CurrentWindow, WIND_INFO_Y2 ) ) { GoToLineRelCurs( LeftTopPos.line + height ); } else if( MouseRow <= WindowAuxInfo( CurrentWindow, WIND_INFO_Y1 ) ) { GoToLineRelCurs( LeftTopPos.line - 1 ); } else if( MouseCol <= WindowAuxInfo( CurrentWindow, WIND_INFO_X1 ) ) { GoToColumnOnCurrentLine( LeftTopPos.column - 1 ); } else if( MouseCol >= WindowAuxInfo( CurrentWindow, WIND_INFO_X2 ) ) { GoToColumnOnCurrentLine( LeftTopPos.column + WindowAuxInfo( CurrentWindow, WIND_INFO_WIDTH )); } #else { RECT rect; GetClientRect( CurrentWindow, &rect ); if( MouseY > rect.bottom ) { ny = LeftTopPos.line + height; if( ny > CurrentFile->fcbs.tail->end_line ) { ny = CurrentFile->fcbs.tail->end_line; moveCursor = 1; } GoToLineRelCurs( ny ); } else if( MouseY < 0 ) { ny = LeftTopPos.line - 1; if( ny < 1 ) { ny = 1; moveCursor = -1; } GoToLineRelCurs( ny ); } else if( MouseX < 0 ) { GoToColumnOnCurrentLine( LeftTopPos.column - 1 ); } else if( MouseX > rect.right ) { if( EditFlags.Modeless ) { GoToColumnOnCurrentLine( 1 + LeftTopPos.column + WindowAuxInfo( CurrentWindow, WIND_INFO_TEXT_COLS ) ); } else { GoToColumnOnCurrentLine( LeftTopPos.column + WindowAuxInfo( CurrentWindow, WIND_INFO_TEXT_COLS ) ); } } } #endif } if( moveCursor == -1 ) { GoToColumnOnCurrentLine( 1 ); } else if( moveCursor == 1 ) { GoToColumnOnCurrentLine( CurrentFile->fcbs.tail->lines.tail->len + 1 ); } } /* UpdateDrag */ /* * UpdateCursorDrag - update drag after cursor movement */ void UpdateCursorDrag( void ) { if( !EditFlags.Dragging ) { return; } if( SelRgn.end.line == CurrentPos.line && SelRgn.end.column == CurrentPos.column ) { return; } #ifndef __WIN__ markRegion( FALSE ); #endif SelRgn.end = CurrentPos; if( EditFlags.LineBased == FALSE ) { SelRgn.lines = FALSE; } else if( SelRgn.start.line != SelRgn.end.line ) { SelRgn.lines = TRUE; } else if( SelRgn.start.column == SelRgn.end.column ) { SelRgn.lines = TRUE; } else { SelRgn.lines = FALSE; } updateRegion(); } /* UpdateCursorDrag */ /* * SetSelRegionCols - set selected region on a line */ void SetSelRegionCols( linenum sl, int sc, int ec ) { vi_rc rc; line *line; fcb *fcb; char *data; SelRgn.lines = FALSE; SelRgn.selected = TRUE; SelRgn.start.line = SelRgn.end.line = sl; SelRgn.start.column = sc; SelRgn.end.column = ec + 1; SelRgn.start_col_v = 0; rc = CGimmeLinePtr( sl, &fcb, &line ); if( rc == ERR_NO_ERR ) { data = ( line->u.ld.nolinedata ) ? WorkLine->data : line->data; SelRgn.start_col_v = GetVirtualCursorPosition( data, SelRgn.start.column ); } updateRegion(); DCUpdate(); } /* SetSelRegionCols */
static int getCursorInfo( HWND hwnd, int row, int col, int *x, int *width ) { ss_block *ss, *ss_start, *ss_prev; dc dc_line; int len; int old_col = 0; char *str; int funny = 0; col--; // we like base 0 row--; // this section checks if current line is valid. assert( hwnd == CurrentInfo->CurrentWindow ); if( row < 0 || row >= CurrentInfo->dc_size ) { // not on screen -> not displayed *x = -10; *width = 0; return( 0 ); } dc_line = DCFindLine( row, hwnd ); if( dc_line->display != 0 ){ // line has not been drawn yet. Can't set cursor. *x = -10; *width = 0; return( 0 ); } assert( dc_line->valid ); if( dc_line->start_col != LeftTopPos.column ) { // not in cache -> not on screen -> not displayed *x = -10; *width = 0; return( 0 ); } ss_start = ss = dc_line->ss; ss_prev = NULL; // this bit adjusts col for real tabs if( EditFlags.RealTabs ){ // this takes it from the current line!!!! %$#@! // what if row isn't the current line! oops!!! // luckily this works because who wants to know cursor info // for any line but the current one! // if( thisLine == CurrentLine ){ int real_left = RealColumnOnCurrentLine( LeftTopPos.column + 1 ); old_col = col; col = RealColumnOnCurrentLine( col + 1 ) - real_left; // kludge! - Real Cursor position refuses to say cursor is to right // of last character like it ought to when Modeless if( CursorPositionOffRight( old_col + 1 ) && (EditFlags.Modeless == FALSE) ) { col++; } // } else { // int real_left = RealCursorPositionOnLine( thisLine, LeftColumn + 1 ); // old_col = col; // col = RealCursorPositionOnLine( thisLine, col + 1 ) - real_left; // } } // this bit finds the block we want while( ss->end < col ) { ss++; } // handle cursor being off the right of text if( ss->end == BEYOND_TEXT ) { *width = FontAverageWidth( SEType[ss->type].font ); if( ss == ss_start ) { *x = (*width) * col; } else { ss_prev = ss - 1; *x = ((*width) * (col - ss_prev->end - 1)) + ss_prev->offset; } return( 0 ); } // setup to figure out where cursor is within text. if( ss != ss_start ) { ss_prev = ss - 1; str = dc_line->text + ss_prev->end + 1; len = col - ss_prev->end - 1; } else { str = dc_line->text; len = col; } // Magic Tabs positioning if( EditFlags.RealTabs ) { type_style *this_style = &SEType[ss->type]; int no_tab = FALSE; int avg_width = FontAverageWidth( SEType[ss->type].font ); int left, extent, end_tab; char *cur_pos; char *end_str; if( ss != ss_start ) { left = ss_prev->offset; } else { left = 0; } if( len > 0 ) { // Note: this will not work with 16bit chars or embedded chars // but niether will the drawing routines, so not to worry (yet) // Is there a tab in the current block ? end_str = cur_pos = str + len; while( *(--cur_pos) != '\t' ){ if(cur_pos == str){ no_tab = TRUE; break; } } // if so, figure out where the last tab stop is. if( no_tab == FALSE ) { // dist is the virtual curpos - the number of chars before // the first tab. this should be the tab boundry. int dist = (old_col + 1) - (end_str - cur_pos); // unless the end_str was also a tab, So we round down. left = (dist - (dist % EditVars.HardTab) - LeftTopPos.column) * avg_width; cur_pos++; } // now get the extent of the leading chars ... extent = MyTextExtent( hwnd, this_style, cur_pos, end_str - cur_pos ); } else { extent = 0; cur_pos = str; end_str = str; } // ... and find the position and width of the cursor. if( *end_str == '\t' ){ // in strange case, tab may start before end of prev string end_tab = (old_col - LeftTopPos.column + 1) * avg_width; *x = left + extent; if( *x > end_tab ) *x = end_tab; *width = end_tab - *x; if( *width < 1 ) *width = 1; funny = 0; } else { *x = left + extent; *width = MyTextExtent( hwnd, this_style, cur_pos, end_str - cur_pos + 1 ) - extent; funny = (*width) / 2; } } else { type_style *this_style = &SEType[ss->type]; *x = MyTextExtent( hwnd, this_style, str, len ); *width = MyTextExtent( hwnd, this_style, str, len + 1 ) - *x; if( ss != ss_start ) { *x += ss_prev->offset; } funny = (*width) / 2; } if( FontIsFunnyItalic( SEType[ss->type].font ) ) { return( funny ); } else { return( 0 ); } }
/* * HandleMouseEvent - handle main editor mouse events */ vi_rc HandleMouseEvent( void ) { windim win_x, win_y; window_id wid; info *cinfo; window *w; int i; bool diff_word; vi_rc rc; wid = GetMousePosInfo( &win_x, &win_y ); if( BAD_ID( wid ) ) { return( ERR_NO_ERR ); } w = WINDOW_FROM_ID( wid ); if( !w->has_border ) { win_x += 1; win_y += 1; } if( dragThumb ) { if( LastMouseEvent == MOUSE_RELEASE ) { dragThumb = false; } if( wid != current_window_id ) { return( ERR_NO_ERR ); } if( win_x == w->width - 1 ) { return( PositionToNewThumbPosition( w, win_y ) ); } return( ERR_NO_ERR ); } if( EditFlags.Dragging ) { if( LastMouseEvent == MOUSE_DRAG || LastMouseEvent == MOUSE_REPEAT ) { UpdateDrag( wid, win_x, win_y ); } else { if( LastMouseEvent == MOUSE_PRESS_R || LastMouseEvent == MOUSE_PRESS ) { EditFlags.Dragging = false; if( LastMouseEvent == MOUSE_PRESS_R ) { LastMouseEvent = MOUSE_RELEASE_R; } } } } if( LastMouseEvent == MOUSE_RELEASE_R || LastMouseEvent == MOUSE_DCLICK ) { if( wid == current_window_id && InsideWindow( wid, win_x, win_y ) ) { diff_word = (LastMouseEvent == MOUSE_DCLICK); if( GoToLineRelCurs( LeftTopPos.line + win_y - 1 ) ) { return( ERR_NO_ERR ); } win_x += LeftTopPos.column; win_x = RealColumnOnCurrentLine( win_x ); GoToColumnOnCurrentLine( win_x ); if( diff_word ) { InitWordSearch( EditVars.WordAltDefn ); } rc = DoSelectSelection( true ); if( diff_word ) { InitWordSearch( EditVars.WordDefn ); } return( rc ); } } /* * all kinds of stuff to do if the button was pressed */ if( LastMouseEvent == MOUSE_PRESS || LastMouseEvent == MOUSE_PRESS_R ) { if( wid != current_window_id ) { /* * swap to another window */ for( cinfo = InfoHead; cinfo != NULL; cinfo = cinfo->next ) { if( wid == cinfo->current_window_id ) { BringUpFile( cinfo, true ); break; } } } if( wid == current_window_id ) { if( !ShiftDown() ) { UnselectRegion(); } if( w->has_border && LastMouseEvent == MOUSE_PRESS ) { /* * clicked on menu for window */ if( win_x == 0 && win_y == 0 ) { return( DoWindowGadgetMenu() ); } /* * check for resize request */ if( win_x == w->width - 1 && win_y == w->height - 1 ) { return( ResizeCurrentWindowWithMouse() ); } /* * check for move request */ if( win_y == 0 ) { return( MoveCurrentWindowWithMouse() ); } } /* * check for locate cursor */ if( InsideWindow( wid, win_x, win_y ) ) { if( ShiftDown() ) { EditFlags.Dragging = true; } if( GoToLineRelCurs( LeftTopPos.line + win_y - 1 ) ) { return( ERR_NO_ERR ); } win_x += LeftTopPos.column; win_x = RealColumnOnCurrentLine( win_x ); GoToColumnOnCurrentLine( win_x ); if( ShiftDown() ) { EditFlags.Dragging = false; } else { InitSelectedRegion(); } return( ERR_NO_ERR ); } } if( EditFlags.Menus && wid == menu_window_id ) { i = GetMenuIdFromCoord( win_x - 1 ); if( i >= 0 ) { return( SetToMenuId( i ) ); } } } /* * allow double click to close window */ if( wid == current_window_id && LastMouseEvent == MOUSE_DCLICK ) { if( win_y == 0 && win_x == 0 ) { return( NextFile() ); } } /* * try to scroll screen */ if( (LastMouseEvent == MOUSE_REPEAT || LastMouseEvent == MOUSE_DCLICK || LastMouseEvent == MOUSE_PRESS) && w->has_border && wid == current_window_id && win_x == w->width - 1 ) { if( win_y == w->height - 2 ) { return( MoveScreenDown() ); } if( win_y == 1 ) { return( MoveScreenUp() ); } /* * if we have gadgets, then scroll based on position of scroll * thumb. furthermore, if the thumb is selected, then begin * thumb dragging mode */ if( w->has_gadgets ) { if( win_y == w->vert_scroll_pos ) { dragThumb = true; return( ERR_NO_ERR ); } else if( win_y < w->vert_scroll_pos ) { return( MovePageUp() ); } else { return( MovePageDown() ); } } else { if( win_y < w->height / 2 ) { return( MovePageUp() ); } else { return( MovePageDown() ); } } } /* * start dragging */ if( wid == current_window_id && (LastMouseEvent == MOUSE_DRAG || LastMouseEvent == MOUSE_DRAG_R ) && InsideWindow( wid, win_x, win_y ) ) { EditFlags.Dragging = true; UpdateDrag( wid, win_x, win_y ); } return( ERR_NO_ERR ); } /* HandleMouseEvent */