繁体   English   中英

在非规范模式下,输出的行不能在终端内正确换行

[英]Outputed lines doesn't wrap correctlly within a terminal in Non Canonical mode

我正在尝试使用Termcap功能实现 bash 的迷你版本,现在我正在尝试读取用户的输入并在终端 Stdout 中重新输入。

一切正常,但是在尝试调整终端 window 的大小时会出现问题,正如您在下面的 gif 中看到的那样,当我编写单行然后缩小window并再次展开 Z78E6221F6393D135DZF681DB3 .

在此处输入图像描述

但是当我的文本经过第一行(不按 Enter)时,如果我执行与以前相同的步骤,则 output 换行与我想要的不同。 我需要的是,在缩小 window 时,第一行的最后一个字符必须与第二行字符连接,反之亦然,当我展开 window 时,第二行的第一个字符与第一行字符连接。

在此处输入图像描述

有没有办法让输出的行换行与 bash 完全相同? (相互连接线)

到目前为止,这是我的代码,当你想编译它时使用-ltermcap标志,并提前致谢。

#include <ctype.h>
#include <termcap.h>
#include <termios.h>
# include <sys/ioctl.h>
# include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int     g_screen_width = 0;
int     g_cursor_colm = 0;
int     g_printed = 0;

int     ft_putchar(int c)
{
    int len = write(1, &c, 1);
    return (len);
}

int     ft_isprint(int c)
{
    return (c >= 32 && c < 127);
}

void    update_cursor_position()
{
    g_cursor_colm = g_printed % g_screen_width;
}

void    update_screen_width()
{
    struct winsize w;
    
    ioctl(STDIN_FILENO, TIOCGWINSZ, &w);
    g_screen_width = w.ws_col;
}

void    sigwinch_handler(int signo)
{
    if (signo == SIGWINCH)
    {
        update_screen_width();
        update_cursor_position();
    }
}

void    move_cursor_to_colum(int col)
{
    char    *ch_cap;
    
    ch_cap = tgetstr("ch", NULL);
    tputs(tgoto(ch_cap, 0, col), 1, ft_putchar);
}

void    move_cursor_down_vertically()
{
    char    *do_cap;

    do_cap = tgetstr("do", NULL);
    tputs(do_cap, 1, ft_putchar);
}

void    move_cursor_to_next_line()
{
    move_cursor_to_colum(0);
    move_cursor_down_vertically();
}

void    enable_raw_mode()
{
    struct termios raw;

    tcgetattr(STDIN_FILENO, &raw);
    raw.c_lflag &= ~(ECHO | ICANON);
    tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw);
}

void    disable_raw_mode(struct termios old_termios_state)
{
    tcsetattr(STDIN_FILENO, TCSAFLUSH, &old_termios_state);
}

int main()
{
    struct termios  original_termios_state;
    char            *term_type = getenv("TERM");
    char            c;
    char            *line;

    tgetent(NULL, term_type);
    tcgetattr(STDIN_FILENO, &original_termios_state);
    enable_raw_mode();

    update_screen_width();
    signal(SIGWINCH, sigwinch_handler);
    while (read(STDIN_FILENO, &c, 1))
    {
        if (ft_isprint(c))
        {
            ft_putchar(c);
            g_printed++;
            g_cursor_colm++;
            if (g_cursor_colm == g_screen_width)
            {
                g_cursor_colm = 0;
                move_cursor_to_next_line();
            }
        }
        else if (c == 27) // ESC
        {
            disable_raw_mode(original_termios_state);
            exit(0);
        }
    }
    
    disable_raw_mode(original_termios_state);
    return (0);
}

您的终端会记住实际的换行位置(您在move_cursor_down_vertically()中使用 cursor_down 显式执行的换行),而不是终端由于其有限的宽度而自行执行的换行。

所以:

  • 要么您根本不移动(向下)您的 cursor 并且只在一个虚拟文本行上进行所有处理,让终端根据其宽度包裹该行(这可能是最简单的解决方案);
  • 或者当您收到 SIGWINCH 信号时,您自己在sigwinch_handler()中重绘屏幕。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM