📄 window.c
字号:
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;
}
/* input_fdel - delete character under cursor
*
* This also updates text to the end of the line.
*
* Parameters:
* num - number of chars to delete. must be >= 0, < kpos
*/
void input_fdel(num)
int num;
{
int n;
assert(num >= 0 /* count may not be negative */);
assert(num <= (Klen - kpos) /* Delete past end of string */);
if (!echo_mode)
return;
n = min(Klen - kpos - num, Margin - icol);
IBwriteal(&Kptr[kpos + num], n);
Iclear_end;
Imove_left(n, icol);
IBflush;
}
/* input_clear - clears the input edit line */
void input_clear()
{
if (!echo_mode)
return;
if (kpos <= Isize * Margin) /* fills entire window? */
{
input_cmove(0);
IBwritea(s_clreol);
icol = Oplen % Margin;
}
else
{
Iclear_space(Itop, 1);
draw_prompt(); /* sets icol */
}
IBflush;
}
/* input_draw - draws the input edit line (no prompt)
*
* Sets icol.
*
* Note:
* This is not easy to get right, so be careful
* to step through every inch of code after modification.
*/
void input_draw()
{
int pos = 0; /* offset in kbuf */
int n, col;
if (!echo_mode)
return;
col = Oplen % Margin; /* initial location */
if (Klen > 0)
{
while (1) /* Loop to write input line */
{
n = min(Klen - pos, Margin - col);
assert(n >= 0); /* Logic error */
IBwriteal(&Kptr[pos], n);
pos += n; /* printed n chars */
assert(pos <= Klen); /* off end of array? */
if (pos > kpos || pos >= Klen) /* Cursor on line? */
break;
else /* not done, scroll forward */
Iscr_fwd;
col = 0; /* beginning of row now */
};
if (n == (Margin - col)) /* write ended at last line on screen? */
Iscr_fwd;
};
icol = (Oplen + kpos) % Margin;
assert(icol >= 0 && icol < cols); /* off screen? */
Iclear_end;
Icmove(icol, 1);
IBflush;
}
void input_newline()
{
input_cmove(Klen);
Iscr_fwd;
icol = 0;
if (plen && !vtc_mode) {
Discardstring(prompt);
prompt = vtstrdup("");
plen = 0;
}
IBflush;
}
/* change_prompt - set a new prompt with length l
*
* Nonprintable characters are ignored.
*/
void change_prompt(new, l)
char *new;
int l;
{
char *p, *q;
Discardstring(prompt);
for (p = new; *p; p++) { /* Get new prompt length */
if (!isprint(*p))
l--;
}
q = prompt = Newarray(char, l + 1); /* copy prompt string */
for (p = new; *p; p++) {
if (isprint(*p))
*q++ = *p;
}
*q = 0;
/* clear and redraw input window */
if (!vtc_mode) {
curs_input();
clear_input_window();
}
plen = l;
if (!vtc_mode) {
draw_prompt();
input_draw();
}
}
void update_echo_mode()
{
int new_mode;
if(0 != ign_echo_mode)
return;
new_mode = (active_win->Wrmt) ? active_win->Wrmt->Recho : 1;
if (echo_mode != new_mode) {
echo_mode = 1;
curs_input();
if (new_mode)
input_draw();
else
input_clear();
echo_mode = new_mode;
}
}
/* Output routines */
void output(win, text)
Unode *win;
char *text;
{
int norm, n;
if (!win) {
win = active_win;
if (win->Wnl)
output(win, "[background] ");
}
curs_window(win);
if (win->Wnl) {
BputEOLN();
win->Wnl = 0;
}
while (1) {
norm = strcspn(text, "\n\b\f\v\t\r");
n = cols - win->Wcol;
for (; norm >= n; text += n, norm -= n, n = cols) {
BputEOLN();
cmove(win->Wcol, win->Wbot - 1);
Bwriteal(text, n);
cmove(0, win->Wbot);
win->Wcol = 0;
}
Bwriteal(text, norm);
win->Wcol = (win->Wcol + norm) % cols;
text += norm;
switch(*text++) {
case '\0':
Bflush;
return;
case '\n':
case '\v':
if (*text)
BputEOLN();
else
win->Wnl = 1;
win->Wcol = 0;
Case '\b':
if (win->Wcol) {
Bputch('\b');
win->Wcol--;
}
Case '\f':
clear_space(win->Wtop, win->Wbot);
win->Wcol = 0;
curs_window(win);
Case '\t':
if (win->Wcol == cols - 1) {
BputEOLN();
win->Wcol = 0;
} else {
do {
Bputch(' ');
win->Wcol++;
} while (win->Wcol % 8 &&
win->Wcol < cols - 1);
}
Case '\r':
Bputch('\r');
win->Wcol = 0;
}
}
}
#ifdef USE_STDARG
void outputf(char *fmt, ...)
#else
void outputf(va_alist)
va_dcl
#endif
{
va_list ap;
char *ptr, *sval, *intstr;
String *buf = &wbufs[1];
int width = 0;
#ifdef USE_STDARG
va_start(ap, fmt);
#else
char *fmt;
va_start(ap);
fmt = va_arg(ap, char *);
#endif
s_term(buf, 0);
ptr = strchr(fmt, '%');
while (ptr) {
s_cat(buf, cstr_sl(fmt, ptr - fmt));
if (isdigit(*++ptr)) {
width = atoi(ptr);
while (isdigit(*++ptr));
}
if (*ptr == 'd') {
intstr = ITOA(va_arg(ap, int));
for (width -= strlen(intstr); width > 0; width--)
s_fadd(buf, ' ');
s_acat(buf, intstr);
} else if (*ptr == 's') {
sval = va_arg(ap, char *);
for (width -= strlen(sval); width > 0; width--)
s_fadd(buf, ' ');
s_acat(buf, sval);
} else
s_fadd(buf, *ptr);
fmt = ptr + 1;
ptr = strchr(fmt, '%');
}
s_acat(buf, fmt);
output(Cur_win, buf->c.s);
va_end(ap);
}
void operror(s, rmt)
char *s;
Unode *rmt;
{
char errbuf[128];
Unode *win = rmt ? rmt->Rwin : Cur_win;
strcpy(errbuf, s);
strcat(errbuf, ": ");
strcat(errbuf, sys_errlist[errno]);
strcat(errbuf, "\n");
output(win, errbuf);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -