📄 window.c
字号:
cmove(0, scr_bot);
while (num--)
BputEOLN();
}
/* Scroll the current scroll area backwards num lines */
void scr_rev(num)
int num;
{
cmove(0, scr_top);
while (num--)
cap_normal(s_scr_rev, scr_bot - scr_top + 1);
}
/* Slightly higher-level termcap routines */
/* clear_end - clear to end of line
*
* Optimization is dangerous. Putting a space/backspace combo can
* cause scrolling on the last line of the screen
*/
static void clear_end()
{
Bwritea(s_clreol);
}
/* Clear horizontally a range of rows */
static void clear_space(top, bottom)
int top, bottom;
{
int i;
scroll(0, rows - 1);
cmove(0, top);
Bwritea(s_clreol);
for (i = top; i < bottom; i++) {
BputEOLN();
Bwritea(s_clreol);
}
Bflush;
}
static void move_left(n, new)
int n, new;
{
if (n < 7)
chrpt('\010', n);
else
cmove(new, rows - 1);
}
/* Windowing routines */
/* Ensure that cursor and scroll area are in window */
void curs_window(win)
Unode *win;
{
if (curs_loc == CURS_WINDOW && curs_win == win)
return;
scroll(win->Wtop, win->Wbot);
cmove(win->Wcol, win->Wbot);
Bflush;
curs_loc = CURS_WINDOW;
curs_win = win;
}
/* Ensure that cursor is in input window */
void curs_input()
{
if (curs_loc == CURS_INPUT)
return;
cmove(icol, rows - 1);
Bflush;
curs_loc = CURS_INPUT;
}
static void init_window(win, top, bottom)
Unode *win;
int top, bottom;
{
win->Wtop = top;
win->Wbot = bottom;
win->Wcol = win->Wnl = 0;
win->Wrmt = NULL;
win->Wtermread = NULL;
win->Wobj = NULL;
win->Wghstack = NULL;
win->Wglstack = NULL;
win->Wrstack = NULL;
}
void draw_Divider(win)
Unode *win;
{
scroll(0, rows - 1);
cmove(0, win->Wbot + 1);
Bputch((win == active_win) ? '*' : '_');
chrpt('_', win->next->dummy ? cols - 6 : cols - 1);
if (win->next->dummy)
Bwritea(vtc_mode ? "VTC__" : "Text_");
Bflush;
curs_loc = CURS_ELSEWHERE;
}
void toggle_imode()
{
scroll(0, rows - 1);
vtc_mode = !vtc_mode;
cmove(cols - 5, Divider);
Bwritea(vtc_mode ? "VTC__" : "Text_");
curs_loc = CURS_ELSEWHERE;
if (plen) {
clear_input_window();
draw_prompt();
input_draw();
}
}
static void mark(win, value)
Unode *win;
int value;
{
cmove(0, win->Wbot + 1);
Bputch(value ? '*' : '_');
Bflush;
curs_loc = CURS_ELSEWHERE;
}
void init_screen()
{
Unode *first_win;
int w_bottom; /* bottom of initial window */
w_bottom = rows - 5;
first_win = unalloc();
init_window(first_win, 0, w_bottom);
win_ring.next = win_ring.prev = first_win;
win_ring.dummy = 1;
first_win->next = first_win->prev = &win_ring;
active_win = first_win;
Bwritea(s_clrscr);
draw_Divider(first_win);
}
void redraw_screen()
{
Unode *wp;
Bwritea(s_clrscr);
for (wp = win_ring.next; !wp->dummy; wp = wp->next)
draw_Divider(wp);
cmove(0, rows - 1);
draw_prompt();
input_draw();
}
void auto_redraw()
{
Func *func;
func = find_func("redraw_hook");
if (func && func->cmd)
run_prog(func->cmd);
else
redraw_screen();
}
Unode *split_window(win, loc)
Unode *win;
int loc;
{
Unode *new;
new = unalloc();
init_window(new, win->Wtop, loc - 1);
win->Wtop = loc + 1;
new->prev = win->prev;
new->next = win;
win->prev = win->prev->next = new;
clear_space(new->Wtop, new->Wbot);
draw_Divider(new);
return new;
}
void close_window(win, dir)
Unode *win;
int dir;
{
Unode *into;
if (dir < 0) {
into = win->prev;
scroll(into->Wtop, win->Wbot + 1);
scr_rev(win->Wbot - into->Wbot);
into->Wbot = win->Wbot;
if (win->next->dummy) {
cmove(cols - 5, Divider);
Bwritea(vtc_mode ? "VTC__" : "Text_");
}
Bflush;
} else {
into = win->next;
clear_space(win->Wtop, win->Wbot + 1);
into->Wtop = win->Wtop;
}
if (win->Wrmt)
win->Wrmt->Rwin = NULL;
if (active_win == win) {
active_win = into;
mark(into, 1);
}
if (cur_win == win)
cur_win = NULL;
win->prev->next = win->next;
win->next->prev = win->prev;
destroy_pointers(win->frefs);
break_pipe(win->Wghstack);
break_pipe(win->Wglstack);
break_pipe(win->Wrstack);
discard_unode(win);
curs_loc = CURS_ELSEWHERE;
}
void resize_window(win, row)
Unode *win;
int row;
{
if (row - 1 > win->Wbot) {
scroll(win->Wtop, row);
scr_rev(row - win->Wbot - 1);
} else if (row - 1 < win->Wbot) {
scroll(win->Wtop, win->Wbot + 1);
scr_fwd(win->Wbot - row + 1);
}
Bflush;
win->next->Wtop = row + 1;
win->Wbot = row - 1;
curs_loc = CURS_ELSEWHERE;
}
void new_active_win(win)
Unode *win;
{
if (win == active_win)
return;
mark(active_win, 0);
mark(win, 1);
active_win = win;
curs_loc = CURS_ELSEWHERE;
update_echo_mode();
}
void resize_screen(new_rows, new_cols)
int new_rows, new_cols;
{
int new_Isize, new_ospace, old_ospace, pos = 0, used = 0, overrun;
int num_wins = 0, size, decr = 0;
Unode *w;
if (new_rows < 4 || new_cols < 15)
vtdie("Screen size too small");
for (w = win_ring.next; !w->dummy; w = w->next, num_wins++);
old_ospace = rows - Isize - num_wins;
while (num_wins > (new_rows - 1) / 3) {
w = win_ring.prev;
if (w->Wrmt)
w->Wrmt->Rwin = NULL;
if (active_win == w)
active_win = w->prev;
if (cur_win == w)
cur_win = NULL;
w->prev->next = &win_ring;
win_ring.prev = w->prev;
destroy_pointers(w->frefs);
destroy_pipe(w->Wghstack);
destroy_pipe(w->Wglstack);
destroy_pipe(w->Wrstack);
discard_unode(w);
num_wins--;
}
new_Isize = min(Isize, new_rows - num_wins * 3);
new_ospace = new_rows - new_Isize - num_wins;
for (w = win_ring.next; !w->dummy; w = w->next) {
size = ((w->Wbot - w->Wtop + 1) * new_ospace
+ old_ospace / 2) / old_ospace;
size = max(size, 2);
w->Wtop = pos;
w->Wbot = pos + size - 1;
pos += size + 1;
used += size;
}
overrun = used - new_ospace;
for (w = win_ring.next; !w->dummy; w = w->next) {
w->Wtop -= decr;
w->Wbot -= decr;
if (overrun > 0 && w->Wbot - w->Wtop > 1) {
w->Wbot--;
decr++;
overrun--;
}
}
rows = new_rows;
cols = new_cols;
auto_redraw();
}
/* input routines */
/* draw_prompt - assumes current cursor location is 0. */
static void draw_prompt()
{
int pos = 0;
if (vtc_mode) /* No prompt? */
icol = 0;
else
{
while (pos < plen)
{
IBwritem(&prompt[pos], plen - pos, Margin);
pos += Margin;
if (pos <= plen)
Iscr_fwd;
};
icol = plen % Margin;
IBflush;
};
}
/* clear_input_window - clear input window */
static void clear_input_window()
{
int len = Oplen; /* copy of plen */
if (kpos + Oplen <= Isize * Margin)
{
input_cmove(0); /* Move to start of edit line */
while (len > Margin) { /* Scroll back to first line of prompt */
Iscr_rev;
len -= Margin;
}
icol = 0;
Icmove(0, 1); /* clear line */
IBwritea(s_clreol);
IBflush;
} else /* this line fills the window */
Iclear_space(Itop, 1);
}
/* input_puts - puts a string to the input window
*
* Called when the interpreter sends output (usually due to keyboard
* input). This apparently does not modify kbuf. Any input is
* assumed to be an insertion.
*/
void input_puts(cstr)
Cstr cstr;
{
int n;
if (!echo_mode)
return;
while (cstr.l)
{
n = min(cstr.l, Margin - icol);
IBwriteal(cstr.s, n);
icol = (icol + n) % Margin;
if (0 == icol)
Iscr_fwd;
cstr = cstr_sl(cstr.s + n, cstr.l - n);
}
/* Print everything from current pos to eoln */
n = min(Klen - kpos, Margin - icol);
IBwriteal(&Kptr[kpos], n);
Imove_left(n, icol);
IBflush;
}
/* Move cursor to the new column, updating the screen wrap if necessary
*
* Assumes the current value of icol is valid.
*/
void input_cmove(new)
int new;
{
int offset = new - kpos, pos, n;
assert(new >= 0); /* array bounds error? */
assert(new <= Klen); /* array bounds error? */
if (new == kpos || !echo_mode)
return;
if (new == kpos - 1 && icol) {
Imove_left(1, new);
icol--;
} else if (new == kpos + 1 && icol < Margin - 1) {
IBputch(Kptr[kpos]);
icol++;
}
else if (offset > 0) /* cursor forward? */
{
/* print remainder of this line */
IBwritem(&Kptr[kpos], Margin - icol, Klen - kpos);
n = (icol + offset) / Margin; /* Number of times to scroll */
pos = kpos + Margin - icol; /* beginning of next line */
icol = (icol + offset) % Margin; /* Get future cursor pos */
while (n --)
{
assert(pos <= Klen); /* my mistake */
Iscr_fwd;
if (pos + Margin > Klen) /* Partial line? */
IBwriteal(&Kptr[pos], (Klen + Oplen) % Margin);
else
IBwriteal(&Kptr[pos], Margin); /* fill entire line */
pos += Margin;
};
Icmove(icol, 1);
}
else /* cursor backward. */
{
/* Calculate offset into the prompt array corresponding to the first
* char in the input window.
*/
pos = (kpos + plen - icol); /* start of this line */
pos -= (Isize * Margin); /* start of first line */
icol += offset;
while (icol < 0) /* loop to scroll back */
{
Iscr_rev; /* scroll back */
if (pos >= 0) /* Exposed a line? */
{
cmove(0, Itop);
if (pos < plen) /* Not past end of prompt? */
{
if (plen - pos < Margin) /* Prompt does not fill line? */
{
IBwriteal(&prompt[pos], plen - pos);
IBwriteal(&Kptr[0], Margin - (plen - pos));
}
else
IBwriteal(&prompt[pos], Margin);
}
else /* No prompt showing */
{
n = pos - plen; /* Index into kbuf now */
assert(n <= Klen); /* off end of kbuf array? */
IBwritem(&Kptr[n], Klen - n, Margin);
};
}
else
clear_space(Itop, Itop); /* clear first line */
pos -= Margin;
icol += Margin;
};
Icmove(icol, 1);
}
IBflush;
}
/* input_bdel - Delete previous character
*
* Parameters:
* num - number of characters to delete. Must be >= kpos.
*/
void input_bdel(num)
int num;
{
int n;
assert(num <= kpos /* deleting too far */);
if (!num || !echo_mode)
return;
input_cmove(kpos - num);
n = min(Klen - kpos, Margin - icol);
IBwriteal(&Kptr[kpos], n);
Iclear_end;
Imove_left(n, icol);
IBflush;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -