/* * Set the index of the currently selected item. The menu will scroll when * necessary. When "n" is out of range don't scroll. * This may be repeated when the preview window is used: * "repeat" == 0: open preview window normally * "repeat" == 1: open preview window but don't set the size * "repeat" == 2: don't open preview window * Returns TRUE when the window was resized and the location of the popup menu * must be recomputed. */ static int pum_set_selected(int n, int repeat) { int resized = FALSE; int context = pum_height / 2; pum_selected = n; if (pum_selected >= 0 && pum_selected < pum_size) { if (pum_first > pum_selected - 4) { /* scroll down; when we did a jump it's probably a PageUp then * scroll a whole page */ if (pum_first > pum_selected - 2) { pum_first -= pum_height - 2; if (pum_first < 0) pum_first = 0; else if (pum_first > pum_selected) pum_first = pum_selected; } else pum_first = pum_selected; } else if (pum_first < pum_selected - pum_height + 5) { /* scroll up; when we did a jump it's probably a PageDown then * scroll a whole page */ if (pum_first < pum_selected - pum_height + 1 + 2) { pum_first += pum_height - 2; if (pum_first < pum_selected - pum_height + 1) pum_first = pum_selected - pum_height + 1; } else pum_first = pum_selected - pum_height + 1; } /* Give a few lines of context when possible. */ if (context > 3) context = 3; if (pum_height > 2) { if (pum_first > pum_selected - context) { /* scroll down */ pum_first = pum_selected - context; if (pum_first < 0) pum_first = 0; } else if (pum_first < pum_selected + context - pum_height + 1) { /* scroll up */ pum_first = pum_selected + context - pum_height + 1; } } /* * Show extra info in the preview window if there is something and * 'completeopt' contains "preview". * Skip this when tried twice already. * Skip this also when there is not much room. * NOTE: Be very careful not to sync undo! */ if (pum_array[pum_selected].pum_info != NULL && Rows > 10 && repeat <= 1 && vim_strchr(p_cot, 'p') != NULL) { win_T *curwin_save = curwin; int res = OK; /* Open a preview window. 3 lines by default. Prefer * 'previewheight' if set and smaller. */ g_do_tagpreview = 3; if (p_pvh > 0 && p_pvh < g_do_tagpreview) g_do_tagpreview = p_pvh; resized = prepare_tagpreview(FALSE); g_do_tagpreview = 0; if (curwin->w_p_pvw) { if (curbuf->b_fname == NULL && curbuf->b_p_bt[0] == 'n' && curbuf->b_p_bt[2] == 'f' && curbuf->b_p_bh[0] == 'w') { /* Already a "wipeout" buffer, make it empty. */ while (!bufempty()) ml_delete((linenr_T)1, FALSE); } else { /* Don't want to sync undo in the current buffer. */ ++no_u_sync; res = do_ecmd(0, NULL, NULL, NULL, ECMD_ONE, 0, NULL); --no_u_sync; if (res == OK) { /* Edit a new, empty buffer. Set options for a "wipeout" * buffer. */ set_option_value((char_u *)"swf", 0L, NULL, OPT_LOCAL); set_option_value((char_u *)"bt", 0L, (char_u *)"nofile", OPT_LOCAL); set_option_value((char_u *)"bh", 0L, (char_u *)"wipe", OPT_LOCAL); set_option_value((char_u *)"diff", 0L, NULL, OPT_LOCAL); } } if (res == OK) { char_u *p, *e; linenr_T lnum = 0; for (p = pum_array[pum_selected].pum_info; *p != NUL; ) { e = vim_strchr(p, '\n'); if (e == NULL) { ml_append(lnum++, p, 0, FALSE); break; } else { *e = NUL; ml_append(lnum++, p, (int)(e - p + 1), FALSE); *e = '\n'; p = e + 1; } } /* Increase the height of the preview window to show the * text, but no more than 'previewheight' lines. */ if (repeat == 0) { if (lnum > p_pvh) lnum = p_pvh; if (curwin->w_height < lnum) { win_setheight((int)lnum); resized = TRUE; } } curbuf->b_changed = 0; curbuf->b_p_ma = FALSE; curwin->w_cursor.lnum = 1; curwin->w_cursor.col = 0; if (curwin != curwin_save && win_valid(curwin_save)) { /* Return cursor to where we were */ validate_cursor(); redraw_later(SOME_VALID); /* When the preview window was resized we need to * update the view on the buffer. Only go back to * the window when needed, otherwise it will always be * redraw. */ if (resized) { win_enter(curwin_save, TRUE); update_topline(); } /* Update the screen before drawing the popup menu. * Enable updating the status lines. */ pum_do_redraw = TRUE; update_screen(0); pum_do_redraw = FALSE; if (!resized && win_valid(curwin_save)) win_enter(curwin_save, TRUE); /* May need to update the screen again when there are * autocommands involved. */ pum_do_redraw = TRUE; update_screen(0); pum_do_redraw = FALSE; } } } } } if (!resized) pum_redraw(); return resized; }
/// Set the index of the currently selected item. The menu will scroll when /// necessary. When "n" is out of range don't scroll. /// This may be repeated when the preview window is used: /// "repeat" == 0: open preview window normally /// "repeat" == 1: open preview window but don't set the size /// "repeat" == 2: don't open preview window /// /// @param n /// @param repeat /// /// @returns TRUE when the window was resized and the location of the popup /// menu must be recomputed. static int pum_set_selected(int n, int repeat) { int resized = FALSE; int context = pum_height / 2; pum_selected = n; if ((pum_selected >= 0) && (pum_selected < pum_size)) { if (pum_first > pum_selected - 4) { // scroll down; when we did a jump it's probably a PageUp then // scroll a whole page if (pum_first > pum_selected - 2) { pum_first -= pum_height - 2; if (pum_first < 0) { pum_first = 0; } else if (pum_first > pum_selected) { pum_first = pum_selected; } } else { pum_first = pum_selected; } } else if (pum_first < pum_selected - pum_height + 5) { // scroll up; when we did a jump it's probably a PageDown then // scroll a whole page if (pum_first < pum_selected - pum_height + 1 + 2) { pum_first += pum_height - 2; if (pum_first < pum_selected - pum_height + 1) { pum_first = pum_selected - pum_height + 1; } } else { pum_first = pum_selected - pum_height + 1; } } // Give a few lines of context when possible. if (context > 3) { context = 3; } if (pum_height > 2) { if (pum_first > pum_selected - context) { // scroll down pum_first = pum_selected - context; if (pum_first < 0) { pum_first = 0; } } else if (pum_first < pum_selected + context - pum_height + 1) { // scroll up pum_first = pum_selected + context - pum_height + 1; } } // Show extra info in the preview window if there is something and // 'completeopt' contains "preview". // Skip this when tried twice already. // Skip this also when there is not much room. // NOTE: Be very careful not to sync undo! if ((pum_array[pum_selected].pum_info != NULL) && (Rows > 10) && (repeat <= 1) && (vim_strchr(p_cot, 'p') != NULL)) { win_T *curwin_save = curwin; int res = OK; // Open a preview window. 3 lines by default. Prefer // 'previewheight' if set and smaller. g_do_tagpreview = 3; if ((p_pvh > 0) && (p_pvh < g_do_tagpreview)) { g_do_tagpreview = (int)p_pvh; } RedrawingDisabled++; // Prevent undo sync here, if an autocommand syncs undo weird // things can happen to the undo tree. no_u_sync++; resized = prepare_tagpreview(false); no_u_sync--; RedrawingDisabled--; g_do_tagpreview = 0; if (curwin->w_p_pvw) { if (!resized && (curbuf->b_nwindows == 1) && (curbuf->b_fname == NULL) && (curbuf->b_p_bt[0] == 'n') && (curbuf->b_p_bt[2] == 'f') && (curbuf->b_p_bh[0] == 'w')) { // Already a "wipeout" buffer, make it empty. while (!bufempty()) { ml_delete((linenr_T)1, FALSE); } } else { // Don't want to sync undo in the current buffer. no_u_sync++; res = do_ecmd(0, NULL, NULL, NULL, ECMD_ONE, 0, NULL); no_u_sync--; if (res == OK) { // Edit a new, empty buffer. Set options for a "wipeout" // buffer. set_option_value("swf", 0L, NULL, OPT_LOCAL); set_option_value("bt", 0L, "nofile", OPT_LOCAL); set_option_value("bh", 0L, "wipe", OPT_LOCAL); set_option_value("diff", 0L, NULL, OPT_LOCAL); } } if (res == OK) { char_u *p, *e; linenr_T lnum = 0; for (p = pum_array[pum_selected].pum_info; *p != NUL;) { e = vim_strchr(p, '\n'); if (e == NULL) { ml_append(lnum++, p, 0, FALSE); break; } else { *e = NUL; ml_append(lnum++, p, (int)(e - p + 1), FALSE); *e = '\n'; p = e + 1; } } // Increase the height of the preview window to show the // text, but no more than 'previewheight' lines. if (repeat == 0) { if (lnum > p_pvh) { lnum = p_pvh; } if (curwin->w_height < lnum) { win_setheight((int)lnum); resized = TRUE; } } curbuf->b_changed = false; curbuf->b_p_ma = FALSE; curwin->w_cursor.lnum = 1; curwin->w_cursor.col = 0; if ((curwin != curwin_save) && win_valid(curwin_save)) { // When the first completion is done and the preview // window is not resized, skip the preview window's // status line redrawing. if (ins_compl_active() && !resized) { curwin->w_redr_status = FALSE; } // Return cursor to where we were validate_cursor(); redraw_later(SOME_VALID); // When the preview window was resized we need to // update the view on the buffer. Only go back to // the window when needed, otherwise it will always be // redraw. if (resized) { no_u_sync++; win_enter(curwin_save, true); no_u_sync--; update_topline(); } // Update the screen before drawing the popup menu. // Enable updating the status lines. pum_is_visible = false; update_screen(0); pum_is_visible = true; if (!resized && win_valid(curwin_save)) { no_u_sync++; win_enter(curwin_save, true); no_u_sync--; } // May need to update the screen again when there are // autocommands involved. pum_is_visible = false; update_screen(0); pum_is_visible = true; } } } } } if (!resized) { pum_redraw(); } return resized; }
void cursupdate() { LPTR *p; int inc, c, nlines; int i; int didinc; if (bufempty()) { /* special case - file is empty */ *Topchar = *Filemem; *Curschar = *Filemem; } else if ( LINEOF(Curschar) < LINEOF(Topchar) ) { nlines = cntllines(Curschar,Topchar); /* if the cursor is above the top of */ /* the screen, put it at the top of the screen.. */ *Topchar = *Curschar; Topchar->index = 0; /* ... and, if we weren't very close to begin with, */ /* we scroll so that the line is close to the middle. */ if ( nlines > Rows/3 ) { for (i=0, p = Topchar; i < Rows/3 ;i++, *Topchar = *p) if ((p = prevline(p)) == NULL) break; } else s_ins(0, nlines-1); updatescreen(); } else if (LINEOF(Curschar) >= LINEOF(Botchar)) { nlines = cntllines(Botchar,Curschar); /* If the cursor is off the bottom of the screen, */ /* put it at the top of the screen.. */ /* ... and back up */ if ( nlines > Rows/3 ) { p = Curschar; for (i=0; i < (2*Rows)/3 ;i++) if ((p = prevline(p)) == NULL) break; *Topchar = *p; } else { scrollup(nlines); } updatescreen(); } Cursrow = Curscol = Cursvcol = 0; for ( p=Topchar; p->linep != Curschar->linep ;p = nextline(p) ) Cursrow += plines(p); Cline_row = Cursrow; Cline_size = plines(p); for (i=0; i <= Curschar->index ;i++) { c = Curschar->linep->s[i]; /* A tab gets expanded, depending on the current column */ if ( c == TAB && !P(P_LS) ) inc = P(P_TS) - (Curscol % P(P_TS)); else inc = chars[(unsigned)(c & 0xff)].ch_size; Curscol += inc; Cursvcol += inc; if ( Curscol >= Columns ) { Curscol -= Columns; Cursrow++; didinc = TRUE; } else didinc = FALSE; } if (didinc) Cursrow--; if (c == TAB && State == NORMAL && !P(P_LS)) { Curscol--; Cursvcol--; } else { Curscol -= inc; Cursvcol -= inc; } if (Curscol < 0) Curscol += Columns; if (set_want_col) { Curswant = Cursvcol; set_want_col = FALSE; } }