Linux 使用 ncurses 调整终端大小和滚动问题
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4738803/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Resize terminal and scrolling problem with ncurses
提问by ubuntiano
I'm programming in C using ncurses libraries (it's the first time) and I've two problems. I'm on ubuntu with the default terminal (gnome terminal).
我正在使用 ncurses 库在 C 中编程(这是第一次),我有两个问题。我在 ubuntu 上使用默认终端(gnome 终端)。
1) I need to resize the terminal. I used resizeter() and resize_term(), but they fail.
1)我需要调整终端的大小。我使用了 resizeter() 和 resize_term(),但它们失败了。
2) I use scrollok() function and the problem is that I lose scrolled lines (when I get back with wscrl(), there are blank lines).
2)我使用 scrollok() 函数,问题是我丢失了滚动行(当我使用 wscrl() 返回时,有空行)。
#include <ncurses.h>
int main() {
WINDOW *win, *win2;
int i;
char c;
initscr();
cbreak();
noecho();
win=newwin(8,20,1,1);
box(win,0,0);
win2=newwin(6,18,2,2);
scrollok(win2,1);
wrefresh(win);
wrefresh(win);
for(i=0;i<15;i++){
c=wgetch(win2);
if(c=='u'){
wscrl(win2,-1);
wrefresh(win2);
}
else{
wprintw(win2,"%c\n",c);
wrefresh(win2);
}
}
delwin(win);
delwin(win2);
endwin();
return 0;
}
回答by Fred Foo
You can't resize the terminal window from ncurses. The functions you mention resize the part of the terminal window that is painted on by curses. The idea is you catch the
SIGWINCH
signal and callresizeterm
in the handler when the user resizes the window from outside the application(using the mouse, probably).This is intended behavior, though poorly documented in ncurses and in the Unix standard/POSIX. NetBSD's curses docsstate it explicitly:
If nis positive then
stdscr
is scrolled up. nlines are lost from the top ofstdscr
and nblank lines are inserted at the bottom. If nis negative thenstdscr
is scrolled down. nblank lines are inserted at the top ofstdscr
and nlines are lost from the bottom.So you'll have to manually save input and reprint it when scrolling.
您无法从 ncurses 调整终端窗口的大小。您提到的功能调整了由诅咒绘制的终端窗口部分的大小。这个想法是当用户从应用程序外部(可能使用鼠标)调整窗口大小时,您捕获
SIGWINCH
信号并调用resizeterm
处理程序。这是预期的行为,尽管在 ncurses 和 Unix 标准/POSIX 中记录很少。NetBSD 的 curses 文档明确指出:
如果n为正,则
stdscr
向上滚动。 ñ线从顶部丢失stdscr
和Ñ空白线被在底部插入。如果 n为负,则stdscr
向下滚动。 Ñ空行被插入在顶部stdscr
和 Ñ线从底部丢失。因此,您必须手动保存输入并在滚动时重新打印。
回答by monty_oso
You can't resize the terminal window from ncurses but you can resize the terminal which the resizesystem call.
您不能从 ncurses 调整终端窗口的大小,但您可以调整调整大小系统调用的终端的大小。
#include <ncurses.h>
#include <stdlib.h>
int main(int argc, char *argv[]){
WINDOW *ventana1;
system("resize -s 30 80");
initscr();
start_color();
ventana1 = newwin(15, 50, 0, 0);
init_pair(1,COLOR_YELLOW,COLOR_BLUE);
init_pair(2,COLOR_BLUE, COLOR_YELLOW);
wbkgd(ventana1,COLOR_PAIR(1));
wprintw(ventana1, "POLLO");
wrefresh(ventana1);
wgetch(ventana1);
wgetch(ventana1);
system("resize -s 20 60");
wbkgd(ventana1,COLOR_PAIR(2));
wprintw(ventana1, "POLLO");
wrefresh(ventana1);
wgetch(ventana1);
wgetch(ventana1);
system("resize -s 35 85");
system("clear");
wbkgd(ventana1,COLOR_PAIR(1));
wprintw(ventana1, "POLLO");
wrefresh(ventana1);
wgetch(ventana1);
wgetch(ventana1);
delwin(ventana1);
endwin();
system("resize -s 25 75");
}
回答by Thomas Dickey
POSIX does not cover this case, because the curses document is not part of POSIX. The Open Group happens to maintain documentation for both:
POSIX 不包括这种情况,因为curses 文档不是POSIX 的一部分。Open Group 碰巧维护以下两个方面的文档:
- X/Open CURSES Issue 4 Version 2(overview)
- X/Open Curses, Issue 4 Version 2(documentation)
- The Open Group Base Specifications Issue 7 IEEE Std 1003.1, 2013 Edition(aka "POSIX")
signal.h
(note thatSIGWINCH
is absent)
- X/Open CURSES 第 4 期第 2 版(概述)
- X/Open Curses,第 4 期第 2 版(文档)
- The Open Group Base Specifications Issue 7 IEEE Std 1003.1, 2013 Edition(又名“POSIX”)
signal.h
(注意SIGWINCH
没有)
As noted in the manual page for resizeterm
, you should not call that function from within a signal handler, because it calls "unsafe" functions. The topic of "unsafe" functions is discussed in several places; that in gcc's documentationwould do for a start.
如 的手册页所述resizeterm
,您不应从信号处理程序中调用该函数,因为它调用了“不安全”的函数。“不安全”功能的话题在几个地方讨论过;在 gcc 的文档中可以作为一个开始。
Regarding documentation, @larsmans appears to be quoting from scroll(3)
, but not citing comparable links for ncurses and "POSIX". For what it's worth:
关于文档,@larsmans 似乎引用了scroll(3)
,但没有引用 ncurses 和“POSIX”的类似链接。物有所值:
- ncurses(seems to address the points implied to be unique to NetBSD)
- X/Open(is necessarily more general, as it is intended to cover different implementations)
Back to OP's question:
回到OP的问题:
- the sample program does not show OP's use of
resizeterm
nor ofresize_term
. It is not stated, but presumably OP resized the terminal window and the program did not respond. The manual page forresizeterm
is clear enough that ncurses does not cause the terminal to resize. For that(on some terminals), one can use the-s
option ofresize
(a utility program forxterm
). If successful, that resizes the terminal, which in turn sends aSIGWINCH
. ncurses has a predefined signal handler for that, but at the applicationlevel, handlingKEY_RESIZE
is the recommended way. There are several programs in ncurses-exampleswhich do this. - moving the lines upin a window necessarily moves some outof the window. That implies that lines are shifted intothe window to replacethose which have left. A "window" is just that: a limited-size view of data. For views with different size, the developer is advised to use "pads" (see manual page). The notes in the scroll manual page mention some issues with the color of blanks (the replacement lines). It is up to the application whether to leave the replacements blank or fill them with the application's data. Curses does not do that automatically (not even for pads).
- 示例程序没有显示 OP
resizeterm
对resize_term
. 没有说明,但大概 OP 调整了终端窗口的大小并且程序没有响应。手册页resizeterm
很清楚,ncurses 不会导致终端调整大小。对于该(在某些终端),一个可以使用-s
的选项resize
(公用程序xterm
)。如果成功,则会调整终端的大小,然后终端会发送一个SIGWINCH
. ncurses 有一个预定义的信号处理程序,但在应用程序级别,处理KEY_RESIZE
是推荐的方式。ncurses-examples 中有几个程序可以做到这一点。 - 在窗口中向上移动行必然会将一些移出窗口。这意味着,线转移到该窗口替换那些已经离开。“窗口”就是这样:一个有限大小的数据视图。对于不同尺寸的视图,建议开发者使用“pads”(参见手册页)。滚动手册页中的注释提到了空白颜色(替换行)的一些问题。是将替换项留空还是用应用程序的数据填充它们取决于应用程序。Curses 不会自动执行此操作(即使对于打击垫也不行)。