Скопируйте и вставьте в неканонический мод - PullRequest
0 голосов
/ 18 февраля 2019

Я создаю программу для реализации оболочки Linux

Я изменил мод терминала на неканонический

void    ft_getch_prepare(void)
{
int             ret;
struct termios  new_opts;

ret = tcgetattr(STDIN_FILENO, &new_opts);
new_opts.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHOK
        | ECHONL | ECHOPRT | ECHOKE | ICRNL);
new_opts.c_cc[VMIN] = 1;
new_opts.c_cc[VTIME] = 1;
ret += tcsetattr(STDIN_FILENO, TCSANOW, &new_opts);
}

int     ft_getch(void)
{
int c;

c = 0;
ft_getch_prepare();
read(0, &c, 4);
return (c);
}

, но когда я хочу скопировать строку и вставить ее, он показывает только первый символ скопированной строки

Например, я хочу вставить эту строку "HELLO WORLD" в мой терминал, но он показывает только первый символ "H"

Ответы [ 2 ]

0 голосов
/ 18 февраля 2019

Если я завершу вашу программу с

int main()
{
    int i = ft_getch();
    printf("%x\n", i);
}

, я получу

$ ./a.out
4c4c4548

, когда попытаюсь вставить HELLO WORLD, чего я и ожидаю.(48 - шестнадцатеричный код для H, 45 для E, 4C для L; он выглядит наоборот, поскольку я использую архитектуру с прямым порядком байтов).

0 голосов
/ 18 февраля 2019

Константа флага ICRNL применяется к c_iflag, а не c_lflag.Вы выключаете его не в том месте.Мне непонятно, почему вы вообще отключаете , но если вы хотите это сделать, вам нужно изменить правильный набор флагов.

The ECHOE,Флаги локального режима ECHOL, ECHONL, ECHOPRT и ECHOKE имеют значение только в каноническом режиме, который вы отключаете.Отключать их тоже не должно быть вредно, но это делает ваш код труднее читать и следовать, чем нужно.

Что касается

, когда я хочучтобы скопировать строку и вставить ее, она показывает только первый символ скопированной строки

, я подозреваю, что вас укусил таймер ввода и / или свойства минимального числа символов неканоническогоРежим.Они управляются элементами c_cc[VTIME] и c_cc[VMIN] массива «специальных символов» в вашей структуре termios.Если вы конфигурируете терминал, который будет поддерживать интерактивный ввод, или для которого в противном случае возможны паузы неограниченной длины на входе, то вам необходимо отключить таймер и убедиться, что блок правильно читает, установив

new_opts.c_cc[VTIME] = 0;
new_opts.c_cc[VMIN] = 1;

.Я не уверен, будет ли этого достаточно для ваших целей, однако, отчасти потому, что я не могу судить, влияет ли способ, которым вы читаете ввод, на проблему.

ОБНОВЛЕНИЕ :

Поскольку вы теперь раскрыли свою функцию ввода, я могу сказать, что у вас действительно есть серьезные проблемы, если предполагается, что она обеспечивает интерфейс, эквивалентный getc().Вы читаете четыре байта за раз вместо одного и неправильно обрабатываете EOF или ошибки.Более того, многобайтовое чтение предоставляет возможность коротких операций чтения, которые вы не можете обнаружить или обработать.

Если вы пытаетесь читать по одному символу за раз, тогда сделать это .Возвращаемое значение getc() равно int вместо char не потому, что уместно попытаться прочитать int s из потока, но чтобы обеспечить значения результата, которые недопустимы char s - в частности, EOF.

Я отказываюсь переписывать ваш код для вас, но для эмуляции getc() необходимо сделать следующее:

  • читать по одному char за раз
  • проверьте возвращаемое значение read.Если это что-то отличное от 1 (для односимвольного чтения), верните EOF
  • , в противном случае верните чтение символа, преобразованное в тип unsigned char.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...