Pdcurses的resize_term似乎随机工作

时间:2016-10-26 23:10:15

标签: c++ curses pdcurses

#include <iostream>
#include <curses.h>
#include "SourceFiles/generalFunc.h"

int main()
{

    initscr();
    int x = resize_term(51, 79);
    sleepMilli(5000); //sleep for 5 seconds
    endwin();
    std::cout << x << " " << int(ERR) << " " << int(OK);

}

虽然x返回0indicating the resizing was successful),但在这种情况下,我的计算机上的屏幕未调整大小。它与原始终端窗口的大小保持不变。但是,如果我增加79到80,或减少51到50,那么屏幕会像平常一样在我的屏幕上调整大小。我的屏幕大到足以容纳这些尺寸一英里 - 即使如此,从80改为79是窗口尺寸的减少但由于某种原因它不起作用。看起来它不喜欢低于某个宽高比。

是否还有更多信息说明为什么我可以做的调整大小似乎有限制,即使这些数字远不是我的屏幕可以容纳的限制?这是64位Windows上的pdcurses。

1 个答案:

答案 0 :(得分:2)

resize_term是一个ncurses函数。

resize_term功能不会更改终端的大小;它会改变 ncurses假定的大小

由于curses没有显示任何内容,并且(请参阅notes in the manual page),您的示例没有getch,因此诅咒无需显示任何更改。

有趣的是,PDCurses实现了一个具有相同名称的功能(灵感来自ncurses:其中有几个),这些功能的描述不同。引用pdcurses/initscr.c中的评论:

    resize_term() is effectively two functions: When called with  
    nonzero values for nlines and ncols, it attempts to resize the  
    screen to the given size. When called with (0, 0), it merely  
    adjusts the internal structures to match the current size after  
    the screen is resized by the user. On the currently supported  
    platforms, this functionality is mutually exclusive: X11 allows  
    user resizing, while DOS, OS/2 and Win32 allow programmatic  
    resizing. If you want to support user resizing, you should check  
    for getch() returning KEY_RESIZE, and/or call is_termresized()  
    at appropriate times; if either condition occurs, call  
    resize_term(0, 0). Then, with either user or programmatic  
    resizing, you'll have to resize any windows you've created, as  
    appropriate; resize_term() only handles stdscr and curscr. 

并且函数从此开始:

int resize_term(int nlines, int ncols)
{   
    PDC_LOG(("resize_term() - called: nlines %d\n", nlines));

    if (!stdscr || PDC_resize_screen(nlines, ncols) == ERR)
        return ERR;

    SP->lines = PDC_get_rows();
    LINES = SP->lines - SP->linesrippedoff - SP->slklines;
    SP->cols = COLS = PDC_get_columns();

反过来调用Windows控制台:

int PDC_resize_screen(int nlines, int ncols)
{
    SMALL_RECT rect;
    COORD size, max;

    if (nlines < 2 || ncols < 2)
        return ERR;

    max = GetLargestConsoleWindowSize(pdc_con_out);

    rect.Left = rect.Top = 0;
    rect.Right = ncols - 1;

    if (rect.Right > max.X)
        rect.Right = max.X;

    rect.Bottom = nlines - 1;

    if (rect.Bottom > max.Y)
        rect.Bottom = max.Y;

    size.X = rect.Right + 1;
    size.Y = rect.Bottom + 1;

    _fit_console_window(pdc_con_out, &rect);
    SetConsoleScreenBufferSize(pdc_con_out, size);
    _fit_console_window(pdc_con_out, &rect);
    SetConsoleScreenBufferSize(pdc_con_out, size);
    SetConsoleActiveScreenBuffer(pdc_con_out);

    return OK;
}

这样你就可以看到结果是一个不兼容的功能。 (SDL有一个类似的端口)。有一些与PDCurses行为有关的问题:

但是,PDCurses通常会将其头文件安装为 <xcurses.h> ,以表示它与curses(或ncurses)的区别。我认为问题是关于ncurses的,问题是关于库函数的作用的混淆:

回到PDCurses,奇怪的是,它会进行两次相同的两次调用两次。 PDCurses函数可能会进行多次尝试,减少给定值,直到它们适合 - 或者不是:

 /* Calls SetConsoleWindowInfo with the given parameters, but fits them  
    if a scoll bar shrinks the maximum possible value. The rectangle  
    must at least fit in a half-sized window. */

static BOOL _fit_console_window(HANDLE con_out, CONST SMALL_RECT *rect)
{   
    SMALL_RECT run;
    SHORT mx, my;

    if (SetConsoleWindowInfo(con_out, TRUE, rect))
        return TRUE;

    run = *rect;
    run.Right /= 2;
    run.Bottom /= 2;

    mx = run.Right;
    my = run.Bottom;

    if (!SetConsoleWindowInfo(con_out, TRUE, &run))
        return FALSE;

    for (run.Right = rect->Right; run.Right >= mx; run.Right--)
        if (SetConsoleWindowInfo(con_out, TRUE, &run))
            break;

    if (run.Right < mx)
        return FALSE;

    for (run.Bottom = rect->Bottom; run.Bottom >= my; run.Bottom--)
        if (SetConsoleWindowInfo(con_out, TRUE, &run))
            return TRUE;

    return FALSE;
}

代码看起来很奇怪,除了两次做同样的事情。参考SetConsoleWindowInfo的MSDN描述,矩形参数是 in 参数(未修改)。遵循参数,它采取所需的大小,并连续尝试

  1. 设置请求的大小,或
  2. 设置请求的行,同时将列减少到初始大小的一半,或
  3. 设置请求的列,同时将行减少到初始大小的一半。
  4. 也许它两次这样做的原因是因为控制台API中存在一些不确定的行为。代码中的注释没有任何帮助。