build: replace ncurses dependency with local FTX shim

This commit is contained in:
Mario Fetka
2026-06-13 09:07:48 +00:00
committed by Mario Fetka
parent b6764d4d4b
commit 3890b78c3f
2 changed files with 245 additions and 50 deletions

View File

@@ -48,35 +48,8 @@ endif()
find_package(Threads REQUIRED)
find_library(NWFLAIM_RT_LIBRARY rt)
find_library(NWFLAIM_DL_LIBRARY dl)
find_package(Curses QUIET)
if(CURSES_FOUND)
set(_nwflaim_curses_include_dirs "")
if(CURSES_INCLUDE_DIRS)
set(_nwflaim_curses_include_dirs "${CURSES_INCLUDE_DIRS}")
elseif(CURSES_INCLUDE_DIR)
set(_nwflaim_curses_include_dirs "${CURSES_INCLUDE_DIR}")
endif()
message(STATUS "NWFLAIM: curses/ncurses found")
if(_nwflaim_curses_include_dirs)
message(STATUS "NWFLAIM: curses include dirs: ${_nwflaim_curses_include_dirs}")
else()
message(STATUS "NWFLAIM: curses include dirs: <none reported>")
endif()
if(CURSES_LIBRARIES)
message(STATUS "NWFLAIM: curses libraries: ${CURSES_LIBRARIES}")
else()
message(STATUS "NWFLAIM: curses libraries: <none reported>")
endif()
if(NWFLAIM_BUILD_TOOLS)
message(STATUS "NWFLAIM: tools enabled; curses-backed tools will be built")
endif()
else()
message(STATUS "NWFLAIM: curses/ncurses not found")
endif()
if(NWFLAIM_BUILD_TOOLS AND NOT CURSES_FOUND)
message(FATAL_ERROR "NWFLAIM_BUILD_TOOLS requires curses/ncurses")
endif()
message(STATUS "NWFLAIM: using bundled minimal curses compatibility shim; no ncurses dependency")
set(_nwflaim_curses_include_dirs "${CMAKE_CURRENT_SOURCE_DIR}/ftk/src")
set(_nwflaim_ssl_target "")
if(NWFLAIM_WITH_OPENSSL)
@@ -129,11 +102,7 @@ set(NWFLAIM_FTK_SOURCES
ftk/src/ftkwin.cpp
ftk/src/ftkxml.cpp)
if(CURSES_FOUND)
list(APPEND NWFLAIM_FTK_SOURCES ftk/src/ftkftx.cpp)
else()
message(STATUS "Curses not found; building libnwflaimtk without console FTX helpers")
endif()
list(APPEND NWFLAIM_FTK_SOURCES ftk/src/ftkftx.cpp)
set(NWFLAIM_FLAIM_SOURCES
flaim/src/checksum.cpp
@@ -393,14 +362,7 @@ function(nwflaim_common_target target_name public_include_dir install_include_di
"${CMAKE_CURRENT_SOURCE_DIR}/sql/src"
"${CMAKE_CURRENT_SOURCE_DIR}/xflaim/src")
target_link_libraries(${target_name} PUBLIC Threads::Threads)
if(CURSES_INCLUDE_DIRS)
target_include_directories(${target_name} PRIVATE ${CURSES_INCLUDE_DIRS})
elseif(CURSES_INCLUDE_DIR)
target_include_directories(${target_name} PRIVATE ${CURSES_INCLUDE_DIR})
endif()
if(CURSES_LIBRARIES)
target_link_libraries(${target_name} PUBLIC ${CURSES_LIBRARIES})
endif()
target_include_directories(${target_name} PRIVATE ${_nwflaim_curses_include_dirs})
if(NWFLAIM_RT_LIBRARY)
target_link_libraries(${target_name} PUBLIC "${NWFLAIM_RT_LIBRARY}")
endif()
@@ -422,14 +384,7 @@ function(nwflaim_common_private_target target_name)
"${CMAKE_CURRENT_SOURCE_DIR}/xflaim/src"
"${CMAKE_CURRENT_SOURCE_DIR}/xflaim/util")
target_link_libraries(${target_name} PRIVATE Threads::Threads)
if(CURSES_INCLUDE_DIRS)
target_include_directories(${target_name} PRIVATE ${CURSES_INCLUDE_DIRS})
elseif(CURSES_INCLUDE_DIR)
target_include_directories(${target_name} PRIVATE ${CURSES_INCLUDE_DIR})
endif()
if(CURSES_LIBRARIES)
target_link_libraries(${target_name} PRIVATE ${CURSES_LIBRARIES})
endif()
target_include_directories(${target_name} PRIVATE ${_nwflaim_curses_include_dirs})
if(NWFLAIM_RT_LIBRARY)
target_link_libraries(${target_name} PRIVATE "${NWFLAIM_RT_LIBRARY}")
endif()

240
ftk/src/curses.h Normal file
View File

@@ -0,0 +1,240 @@
#ifndef NWFLAIM_CURSES_COMPAT_H
#define NWFLAIM_CURSES_COMPAT_H
/*
* Minimal curses-compatible terminal shim for legacy FLAIM FTX tools.
* This is intentionally not a general curses implementation. It only
* provides the subset used by ftkftx.cpp, so mars-flaim can build its
* historical tools without depending on ncurses.
*/
#include <sys/ioctl.h>
#include <sys/select.h>
#include <termios.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef unsigned int chtype;
typedef struct nwflaim_curses_window { int dummy; } WINDOW;
#define ERR (-1)
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#define A_NORMAL 0x00000000u
#define A_BOLD 0x01000000u
#define A_REVERSE 0x02000000u
#define COLOR_PAIR(n) ((chtype)((n) << 16))
#define COLOR_BLACK 0
#define COLOR_RED 1
#define COLOR_GREEN 2
#define COLOR_YELLOW 3
#define COLOR_BLUE 4
#define COLOR_MAGENTA 5
#define COLOR_CYAN 6
#define COLOR_WHITE 7
#define COLOR_PAIRS 64
#define KEY_F(n) (0x1000 + (n))
#define KEY_BACKSPACE 0x1101
#define KEY_DC 0x1102
#define KEY_FIND 0x1103
#define KEY_HOME 0x1104
#define KEY_END 0x1105
#define KEY_SELECT 0x1106
#define KEY_LL 0x1107
#define KEY_LEFT 0x1108
#define KEY_RIGHT 0x1109
#define KEY_DOWN 0x110a
#define KEY_UP 0x110b
#define KEY_ENTER 0x110c
#define KEY_NPAGE 0x110d
#define KEY_PPAGE 0x110e
#define KEY_IC 0x110f
static WINDOW nwflaim_curses_stdscr_obj = { 0 };
static WINDOW *stdscr = &nwflaim_curses_stdscr_obj;
static int LINES = 25;
static int COLS = 80;
static struct termios nwflaim_curses_saved_termios;
static int nwflaim_curses_have_termios = 0;
static int nwflaim_curses_started = 0;
static int nwflaim_curses_cur_fg = 7;
static int nwflaim_curses_cur_bg = 0;
static int nwflaim_curses_pair_fg[COLOR_PAIRS + 1];
static int nwflaim_curses_pair_bg[COLOR_PAIRS + 1];
static void nwflaim_curses_update_size(void)
{
struct winsize ws;
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == 0) {
if (ws.ws_row > 0) LINES = ws.ws_row;
if (ws.ws_col > 0) COLS = ws.ws_col;
}
}
static int nwflaim_curses_read_byte(int wait)
{
unsigned char ch;
fd_set rfds;
struct timeval tv;
int rc;
FD_ZERO(&rfds);
FD_SET(STDIN_FILENO, &rfds);
tv.tv_sec = wait ? 1 : 0;
tv.tv_usec = wait ? 0 : 0;
rc = select(STDIN_FILENO + 1, &rfds, NULL, NULL, &tv);
if (rc <= 0) return ERR;
if (read(STDIN_FILENO, &ch, 1) != 1) return ERR;
return (int)ch;
}
static int initscr(void)
{
struct termios tio;
nwflaim_curses_update_size();
if (tcgetattr(STDIN_FILENO, &nwflaim_curses_saved_termios) == 0) {
nwflaim_curses_have_termios = 1;
tio = nwflaim_curses_saved_termios;
tio.c_lflag &= (tcflag_t)~(ICANON | ECHO);
tio.c_iflag &= (tcflag_t)~(IXON | ICRNL);
tio.c_cc[VMIN] = 0;
tio.c_cc[VTIME] = 1;
(void)tcsetattr(STDIN_FILENO, TCSANOW, &tio);
}
nwflaim_curses_started = 1;
fputs("\033[?25l", stdout);
fflush(stdout);
return 0;
}
static int endwin(void)
{
if (nwflaim_curses_have_termios) {
(void)tcsetattr(STDIN_FILENO, TCSANOW, &nwflaim_curses_saved_termios);
}
fputs("\033[0m\033[?25h\n", stdout);
fflush(stdout);
nwflaim_curses_started = 0;
return 0;
}
static int noecho(void) { return 0; }
static int cbreak(void) { return 0; }
static int halfdelay(int tenths) { (void)tenths; return 0; }
static int meta(WINDOW *w, int bf) { (void)w; (void)bf; return 0; }
static int keypad(WINDOW *w, int bf) { (void)w; (void)bf; return 0; }
static int scrollok(WINDOW *w, int bf) { (void)w; (void)bf; return 0; }
static int has_colors(void) { return 1; }
static int start_color(void) { return 0; }
static int bkgd(chtype ch) { (void)ch; return 0; }
static int erasechar(void) { return 0x7f; }
static int killchar(void) { return 0x15; }
static int init_pair(short pair, short fg, short bg)
{
if (pair >= 0 && pair <= COLOR_PAIRS) {
nwflaim_curses_pair_fg[pair] = fg;
nwflaim_curses_pair_bg[pair] = bg;
}
return 0;
}
static void nwflaim_curses_apply_attr(chtype ch)
{
int pair = (int)((ch >> 16) & 0xff);
int fg = nwflaim_curses_cur_fg;
int bg = nwflaim_curses_cur_bg;
int bold = (ch & A_BOLD) != 0;
int rev = (ch & A_REVERSE) != 0;
if (pair >= 0 && pair <= COLOR_PAIRS) {
fg = nwflaim_curses_pair_fg[pair];
bg = nwflaim_curses_pair_bg[pair];
}
if (rev) {
int tmp = fg; fg = bg; bg = tmp;
}
fprintf(stdout, "\033[0;%d;%d;%dm", bold ? 1 : 22, 30 + fg, 40 + bg);
}
static int addch(chtype ch)
{
unsigned int c = ch & 0xffu;
nwflaim_curses_apply_attr(ch);
if (c == 0) c = ' ';
fputc((int)c, stdout);
return 0;
}
static int move(int y, int x)
{
if (y < 0) y = 0;
if (x < 0) x = 0;
fprintf(stdout, "\033[%d;%dH", y + 1, x + 1);
return 0;
}
static int refresh(void)
{
fflush(stdout);
return 0;
}
static int clearok(WINDOW *w, int bf)
{
(void)w;
if (bf) fputs("\033[2J\033[H", stdout);
return 0;
}
static int getch(void)
{
int c = nwflaim_curses_read_byte(0);
if (c != 0x1b) return c;
int c2 = nwflaim_curses_read_byte(0);
if (c2 == ERR) return 0x1b;
if (c2 != '[' && c2 != 'O') return c2;
c = nwflaim_curses_read_byte(0);
switch (c) {
case 'A': return KEY_UP;
case 'B': return KEY_DOWN;
case 'C': return KEY_RIGHT;
case 'D': return KEY_LEFT;
case 'H': return KEY_HOME;
case 'F': return KEY_END;
case '1': return KEY_HOME;
case '2': return KEY_IC;
case '3': return KEY_DC;
case '4': return KEY_END;
case '5': return KEY_PPAGE;
case '6': return KEY_NPAGE;
case 'P': return KEY_F(1);
case 'Q': return KEY_F(2);
case 'R': return KEY_F(3);
case 'S': return KEY_F(4);
default: return ERR;
}
}
static int wgetch(WINDOW *w) { (void)w; return getch(); }
static int clear(void) { fputs("\033[2J\033[H", stdout); return 0; }
#ifdef __cplusplus
}
#endif
#endif