From cb320a6bdaee9c74d0ebb85cc395c6e588f01d0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrea=20Palmat=C3=A8?= Date: Wed, 17 Aug 2022 18:51:07 +0200 Subject: [PATCH] Fixed (and hacked) some termios functions to work properly with ncurses. Added scandir to dirent. Added termcap.os4 file that is used in ncurses --- libc.gmk | 1 + library/dirent/scandir.c | 58 +++++++++++++++++++++++++++ library/include/dirent.h | 9 +++-- library/termios/console_fdhookentry.c | 36 ++++++++++++++++- library/termios/tcgetattr.c | 14 +++---- specs => misc/specs | 0 misc/termcap.os4 | 58 +++++++++++++++++++++++++++ test_programs/dirent/scandir.c | 21 ++++++++++ 8 files changed, 184 insertions(+), 13 deletions(-) create mode 100644 library/dirent/scandir.c rename specs => misc/specs (100%) create mode 100644 misc/termcap.os4 create mode 100644 test_programs/dirent/scandir.c diff --git a/libc.gmk b/libc.gmk index a9362cd0..3c26c82c 100755 --- a/libc.gmk +++ b/libc.gmk @@ -100,6 +100,7 @@ C_DIRENT := \ dirent/dirfd.o \ dirent/fdopendir.o \ dirent/opendir.o \ + dirent/scandir.o \ dirent/readdir.o \ dirent/readdir_r.o \ dirent/readdir64_r.o \ diff --git a/library/dirent/scandir.c b/library/dirent/scandir.c new file mode 100644 index 00000000..d30e3278 --- /dev/null +++ b/library/dirent/scandir.c @@ -0,0 +1,58 @@ +/* + * $Id: dirent_scandir.c,v 1.0 2022-08-17 12:04:22 clib2devs Exp $ +*/ + +#ifndef _DIRENT_HEADERS_H +#include "dirent_headers.h" +#endif /* _DIRENT_HEADERS_H */ + +#ifndef _STDLIB_MEMORY_H +#include "stdlib_memory.h" +#endif /* _STDLIB_MEMORY_H */ + +int scandir(const char *path, struct dirent ***res, + int (*sel)(const struct dirent *), + int (*cmp)(const struct dirent **, const struct dirent **)) { + DIR *d = opendir(path); + struct dirent *de, **names = 0, **tmp; + size_t cnt = 0, len = 0; + int old_errno = errno; + + if (!d) { + __set_errno(EACCES); + return -1; + } + + while ((errno = 0), (de = readdir(d))) { + if (sel && !sel(de)) + continue; + if (cnt >= len) { + len = 2 * len + 1; + if (len > SIZE_MAX / sizeof *names) + break; + tmp = realloc(names, len * sizeof *names); + if (!tmp) + break; + names = tmp; + } + names[cnt] = malloc(de->d_reclen); + if (!names[cnt]) + break; + memcpy(names[cnt++], de, de->d_reclen); + } + + closedir(d); + + if (errno) { + if (names) + while (cnt-- > 0) free(names[cnt]); + free(names); + return -1; + } + __set_errno(old_errno); + + if (cmp) + qsort(names, cnt, sizeof *names, (int (*)(const void *, const void *)) cmp); + *res = names; + return cnt; +} \ No newline at end of file diff --git a/library/include/dirent.h b/library/include/dirent.h index 1738b04f..de82f3a7 100755 --- a/library/include/dirent.h +++ b/library/include/dirent.h @@ -39,12 +39,13 @@ struct dirent { }; extern DIR *opendir(const char * path_name); -extern struct dirent * readdir(DIR * directory_pointer); +extern struct dirent *readdir(DIR * directory_pointer); extern void rewinddir(DIR * directory_pointer); -extern int closedir(DIR * directory_pointer); +extern int closedir(DIR * directory_pointer); extern DIR *fdopendir(int); -extern int alphasort(const struct dirent **a, const struct dirent **b); -extern int dirfd(DIR *dirp); +extern int alphasort(const struct dirent **a, const struct dirent **b); +extern int dirfd(DIR *dirp); +extern int scandir(const char *, struct dirent ***, int (*)(const struct dirent *), int (*)(const struct dirent **, const struct dirent **)); extern int readdir_r(DIR *dir, struct dirent *buf, struct dirent **result); extern int readdir64_r(DIR *dir, struct dirent *buf, struct dirent **result); diff --git a/library/termios/console_fdhookentry.c b/library/termios/console_fdhookentry.c index 2cda3536..49bfff2a 100644 --- a/library/termios/console_fdhookentry.c +++ b/library/termios/console_fdhookentry.c @@ -33,12 +33,14 @@ LineEditor(BPTR file, char *buf, const int buflen, struct termios *tios) { unsigned char z; int do_edit = 1; int shift_mode = 0; + int esc_mode = 0; SetMode(file, DOSTRUE); /* Set raw mode. */ while (do_edit && len < buflen) { /* 5 seconds. */ - if (WaitForChar(file, 5000000) != DOSFALSE) { + if (WaitForChar(file, 5000000) != DOSFALSE) + { if (Read(file, &z, 1) == ERROR) { len = -1; break; @@ -56,6 +58,10 @@ LineEditor(BPTR file, char *buf, const int buflen, struct termios *tios) { buf[len++] = '\n'; continue; + case 27: /* ESC */ + esc_mode = 1; + continue; + case 155: /* CSI */ shift_mode = 1; continue; @@ -80,8 +86,10 @@ LineEditor(BPTR file, char *buf, const int buflen, struct termios *tios) { continue; } - if (shift_mode) { + + if (shift_mode || esc_mode) { shift_mode = 0; + esc_mode = 0; switch (z) { case 'C': /* Right arrowkey */ @@ -97,6 +105,21 @@ LineEditor(BPTR file, char *buf, const int buflen, struct termios *tios) { pos--; continue; + + case 'A': /* Up arrowkey */ + + if (pos < len) + pos++; + + continue; + + case 'B': /* Down arrowkey */ + + if (pos > 0) + pos--; + + continue; + } } @@ -175,6 +198,15 @@ __termios_console_hook(struct fd *fd, struct file_action_message *fam) { result = LineEditor(file, fam->fam_Data, fam->fam_Size, tios); } else { + /* Well.. this seems an hack to make ncurses works correctly + * I don't know if there are other problems setting STDIO always + * in RAW Mode but I suppose that we are ok since we are using + * a termios hook + */ + if (FLAG_IS_SET(fd->fd_Flags, FDF_STDIO)) { + /* Set raw mode. */ + SetMode(file, DOSTRUE); + } result = Read(file, fam->fam_Data, fam->fam_Size); } } else if (fam->fam_Size > 0) { diff --git a/library/termios/tcgetattr.c b/library/termios/tcgetattr.c index b2de72cd..c505be1b 100644 --- a/library/termios/tcgetattr.c +++ b/library/termios/tcgetattr.c @@ -43,8 +43,7 @@ get_console_termios(struct fd *fd) { if (FLAG_IS_SET(fd->fd_Flags, FDF_READ)) SET_FLAG(tios->c_cflag, CREAD); - /* Set up the initial termios state in RAW mode */ - cfmakeraw(tios); + tios->c_lflag = ISIG|ICANON|ECHO; memcpy(tios->c_cc, def_console_cc, NCCS); @@ -131,17 +130,18 @@ tcgetattr(int file_descriptor, struct termios *user_tios) { __fd_unlock(fd); + /* If someone ask for tcgetattr on STDOUT or STDERR make sure that we set also + * STDIN. This hack fix ncurses library for example */ + if (file_descriptor == STDOUT_FILENO || file_descriptor == STDERR_FILENO) { + tcgetattr(STDIN_FILENO, user_tios); + } + out: __stdio_unlock(); __check_abort(); - /* If someone ask for tcgetattr on STDOUT or STDERR make sure that we set also - * STDIN. This hack fix ncurses library for example */ - if (file_descriptor == STDOUT_FILENO || file_descriptor == STDERR_FILENO) { - tcgetattr(STDIN_FILENO, user_tios); - } return (result); } diff --git a/specs b/misc/specs similarity index 100% rename from specs rename to misc/specs diff --git a/misc/termcap.os4 b/misc/termcap.os4 new file mode 100644 index 00000000..fd1bd8a3 --- /dev/null +++ b/misc/termcap.os4 @@ -0,0 +1,58 @@ +# From: Kent Polk , 30 May 90 +# Added a few more entries, converted caret-type control sequence (^x) entries +# to '\0xx' entries since a couple of people mentioned losing '^x' sequences. +# +# :as:, :ae: Support for alternate character sets. +# :ve=\E[\040p:vi=\E[\060\040p: cursor visible/invisible. +# :xn: vt100 kludginess at column 80/NEWLINE ignore after 80 cols(Concept) +# This one appears to fix a problem I always had with a line ending +# at 'width+1' (I think) followed by a blank line in vi. The blank +# line tended to disappear and reappear depending on how the screen +# was refreshed. Note that this is probably needed only if you use +# something like a Dnet Fterm with the window sized to some peculiar +# dimension larger than 80 columns. +# :k0=\E9~: map F10 to k0 - could have F0-9 -> k0-9, but ... F10 was 'k;' + +# From: Hans Verkuil , 4 Dec 1995 +# (amiga: added empty to suppress a warning --esr) +# Additions by Steven Solie , 24 July 2006 +# Added colors by Andrea Palmate' , 17 August 2022 +amiga-clib2|Amiga ANSI ncurses:\ + :am:bs:bw:ms:xn:mi:cc:\ + :Co#16:NC#3:co#80:li#24:pa#64:\ + :AB=\2334%dm:AF=\2333%dm:AL=\233%dL:DC=\233%dP:\ + :DL=\233%dM:dl=\233M:op=\23339;49m:\ + :DC=\233%dP:DO=\233%dB:IC=\233%d@:LE=\233%dD:RI=\233%dC:\ + :SF=\233%dS:SR=\233%dT:UP=\233%dA:ac=:ae=^O:as=^N:bl=^G:\ + :bt=\233Z:cd=\233J:ce=\233K:cl=\233H\233J:\ + :cm=\233%i%d;%dH:cr=^M:dc=\233P:do=\233B:ec=\233%dP:ei=:\ + :ho=\233H:ic=\233@:im=:is=\23320l:k0=\2339~:k1=\2330~:\ + :k2=\2331~:k3=\2332~:k4=\2333~:k5=\2334~:k6=\2335~:\ + :k7=\2336~:k8=\2337~:k9=\2338~:kD=\177:kb=^H:kd=\233B:\ + :kl=\233D:kr=\233C:ku=\233A:le=\233D:mb=\2337;2m:\ + :md=\2331m:me=\2330m:mh=\2332m:mk=\2338m:mr=\2337m:\ + :nd=\233C:nw=\233B\r:r1=\Ec:se=\2330m:sf=\233S:so=\2337m:\ + :sr=\233T:ta=^I:te=\233?7h:ti=\233?7l:ue=\2330m:up=\233A:\ + :us=\2334m:vb=^G:ve=\233 p:vi=\2330 p:\ + :kI=\23340~:kP=\23341~:kN=\23342~:kh=\23344~:@7=\23345~:\ + :F1=\23320~:F2=\23321~: + +amiga-clib2-mono|Amiga ANSI ncurses:\ + :am:bs:bw:ms:xn:mi:cc:\ + :co#80:li#24:\ + :AB=\2334%dm:AF=\2333%dm:AL=\233%dL:DC=\233%dP:\ + :DL=\233%dM:dl=\233M:op=\23339;49m:\ + :DC=\233%dP:DO=\233%dB:IC=\233%d@:LE=\233%dD:RI=\233%dC:\ + :SF=\233%dS:SR=\233%dT:UP=\233%dA:ac=:ae=^O:as=^N:bl=^G:\ + :bt=\233Z:cd=\233J:ce=\233K:cl=\233H\233J:\ + :cm=\233%i%d;%dH:cr=^M:dc=\233P:do=\233B:ec=\233%dP:ei=:\ + :ho=\233H:ic=\233@:im=:is=\23320l:k0=\2339~:k1=\2330~:\ + :k2=\2331~:k3=\2332~:k4=\2333~:k5=\2334~:k6=\2335~:\ + :k7=\2336~:k8=\2337~:k9=\2338~:kD=\177:kb=^H:kd=\233B~:\ + :kl=\233D:kr=\233C:ku=\233A~:le=\233D:mb=\2337;2m:\ + :md=\2331m:me=\2330m:mh=\2332m:mk=\2338m:mr=\2337m:\ + :nd=\233C:nw=\233B\r:r1=\Ec:se=\2330m:sf=\233S:so=\2337m:\ + :sr=\233T:ta=^I:te=\233?7h:ti=\233?7l:ue=\2330m:up=\233A:\ + :us=\2334m:vb=^G:ve=\233 p:vi=\2330 p:\ + :kI=\23340~:kP=\23341~:kN=\23342~:kh=\23344~:@7=\23345~:\ + :F1=\23320~:F2=\23321~: \ No newline at end of file diff --git a/test_programs/dirent/scandir.c b/test_programs/dirent/scandir.c new file mode 100644 index 00000000..1b3dd720 --- /dev/null +++ b/test_programs/dirent/scandir.c @@ -0,0 +1,21 @@ +#include +#include +#include + +int main() { + struct dirent **namelist; + int i, n; + + n = scandir("T:", &namelist, 0, alphasort); + if (n < 0) + perror("scandir"); + else { + for (i = 0; i < n; i++) { + printf("%s\n", namelist[i]->d_name); + free(namelist[i]); + } + } + free(namelist); + + return 0; +} \ No newline at end of file