Skip to content

Commit 7c54db8

Browse files
committed
Use system ncurses C headers
Switch from using D bindings for the ncurses library to using the host system's C headers directly via ImportC. This allows btdu to be automatically built against the same configuration that the system ncurses library was built with, removing compatibility issues due to mismatching configure flags. Note that building btdu now requires the ncurses C headers to be installed on the system. Nix builds take care of this automatically.
1 parent fdbafc7 commit 7c54db8

File tree

6 files changed

+331
-7
lines changed

6 files changed

+331
-7
lines changed

dub-lock.json

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,6 @@
88
"version": "0.0.21",
99
"sha256": "0j7ksngwn8kilbql6p7hh5jvmrxqsr7pniw2n1qlrwdsms6qv72m"
1010
},
11-
"ncurses": {
12-
"version": "1.0.0",
13-
"sha256": "0ivl88vp2dy9rpv6x3f9jlyqa7aps2x1kkyx80w2d4vcs31pzmb2"
14-
},
1511
"emsi_containers": {
1612
"version": "0.9.0",
1713
"sha256": "1viz1fjh6jhfvl0d25bb1q7aclm1hrs0d7hhcx1d9c0gg5k6lcpm"

dub.sdl

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,12 @@ toolchainRequirements frontend=">=2.097"
77

88
dependency "ae" version="==0.0.3701"
99
dependency "btrfs" version="~>0.0.21"
10-
dependency "ncurses" version="~>1.0.0"
1110
dependency "emsi_containers" version="==0.9.0"
1211

12+
// ImportC ncurses shim - captures system ncurses configuration automatically
13+
sourceFiles "source/btdu_ncurses_importc.c"
14+
libs "ncursesw"
15+
1316
// Custom build type for integration tests with extra runtime checks
1417
buildType "checked" {
1518
buildOptions "debugMode" "debugInfo"

flake.nix

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,12 +265,13 @@
265265
266266
# Use the cross-compiler's gcc wrapper for linking
267267
# Note: -I for patched druntime must come first to override host LDC's includes
268+
# -P passes flags to the C preprocessor for ImportC
268269
${pkgs.ldc}/bin/ldc2 \
269270
-mtriple ${targetTriple} \
270271
--gcc=${crossCC}/bin/${crossCC.targetPrefix}cc \
271272
--linker=lld \
272273
-i \
273-
-i=-deimos \
274+
-P-I${ncursesLto}/include/ncursesw \
274275
-of btdu \
275276
-I${ldcSrc}/runtime/druntime/src \
276277
-L-L${ldcRuntime}/lib \

source/btdu/ui/curses.d

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ import ae.utils.text.functor : stringifiable, fmtSeq;
3636
import ae.utils.functor.primitives : functor;
3737
import ae.utils.typecons : require;
3838

39-
import deimos.ncurses;
39+
import btdu.ui.ncurses;
4040

4141
struct Curses
4242
{

source/btdu/ui/ncurses.d

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
/// D wrapper for ncurses via ImportC
2+
/// Re-exports ImportC declarations with original ncurses names
3+
module btdu.ui.ncurses;
4+
5+
// Import the C shim - all ncurses declarations become available
6+
public import btdu_ncurses_importc;
7+
8+
// Re-export wchar_t type for compatibility with existing D code
9+
public import core.stdc.stddef : wchar_t;
10+
11+
// Attributes - alias internal names to standard ncurses names
12+
alias A_NORMAL = _NC_A_NORMAL;
13+
alias A_STANDOUT = _NC_A_STANDOUT;
14+
alias A_UNDERLINE = _NC_A_UNDERLINE;
15+
alias A_REVERSE = _NC_A_REVERSE;
16+
alias A_BLINK = _NC_A_BLINK;
17+
alias A_DIM = _NC_A_DIM;
18+
alias A_BOLD = _NC_A_BOLD;
19+
alias A_ALTCHARSET = _NC_A_ALTCHARSET;
20+
alias A_INVIS = _NC_A_INVIS;
21+
alias A_PROTECT = _NC_A_PROTECT;
22+
alias A_HORIZONTAL = _NC_A_HORIZONTAL;
23+
alias A_LEFT = _NC_A_LEFT;
24+
alias A_LOW = _NC_A_LOW;
25+
alias A_RIGHT = _NC_A_RIGHT;
26+
alias A_TOP = _NC_A_TOP;
27+
alias A_VERTICAL = _NC_A_VERTICAL;
28+
alias A_ITALIC = _NC_A_ITALIC;
29+
30+
// Return codes
31+
alias OK = _NC_OK;
32+
alias ERR = _NC_ERR;
33+
34+
// Configuration
35+
alias CCHARW_MAX = _NC_CCHARW_MAX;
36+
37+
// KEY_F as a CTFE function (matches ncurses KEY_F(n) macro calling convention)
38+
int KEY_F(int n) pure nothrow @nogc @safe
39+
{
40+
return _NC_KEY_F0 + n;
41+
}
42+
43+
// Basic navigation keys
44+
alias KEY_DOWN = _NC_KEY_DOWN;
45+
alias KEY_UP = _NC_KEY_UP;
46+
alias KEY_LEFT = _NC_KEY_LEFT;
47+
alias KEY_RIGHT = _NC_KEY_RIGHT;
48+
alias KEY_HOME = _NC_KEY_HOME;
49+
alias KEY_BACKSPACE = _NC_KEY_BACKSPACE;
50+
alias KEY_DL = _NC_KEY_DL;
51+
alias KEY_IL = _NC_KEY_IL;
52+
alias KEY_DC = _NC_KEY_DC;
53+
alias KEY_IC = _NC_KEY_IC;
54+
alias KEY_EIC = _NC_KEY_EIC;
55+
alias KEY_CLEAR = _NC_KEY_CLEAR;
56+
alias KEY_EOS = _NC_KEY_EOS;
57+
alias KEY_EOL = _NC_KEY_EOL;
58+
alias KEY_SF = _NC_KEY_SF;
59+
alias KEY_SR = _NC_KEY_SR;
60+
alias KEY_NPAGE = _NC_KEY_NPAGE;
61+
alias KEY_PPAGE = _NC_KEY_PPAGE;
62+
alias KEY_STAB = _NC_KEY_STAB;
63+
alias KEY_CTAB = _NC_KEY_CTAB;
64+
alias KEY_CATAB = _NC_KEY_CATAB;
65+
alias KEY_ENTER = _NC_KEY_ENTER;
66+
alias KEY_PRINT = _NC_KEY_PRINT;
67+
alias KEY_LL = _NC_KEY_LL;
68+
alias KEY_A1 = _NC_KEY_A1;
69+
alias KEY_A3 = _NC_KEY_A3;
70+
alias KEY_B2 = _NC_KEY_B2;
71+
alias KEY_C1 = _NC_KEY_C1;
72+
alias KEY_C3 = _NC_KEY_C3;
73+
alias KEY_BTAB = _NC_KEY_BTAB;
74+
alias KEY_BEG = _NC_KEY_BEG;
75+
alias KEY_CANCEL = _NC_KEY_CANCEL;
76+
alias KEY_CLOSE = _NC_KEY_CLOSE;
77+
alias KEY_COMMAND = _NC_KEY_COMMAND;
78+
alias KEY_COPY = _NC_KEY_COPY;
79+
alias KEY_CREATE = _NC_KEY_CREATE;
80+
alias KEY_END = _NC_KEY_END;
81+
alias KEY_EXIT = _NC_KEY_EXIT;
82+
alias KEY_FIND = _NC_KEY_FIND;
83+
alias KEY_HELP = _NC_KEY_HELP;
84+
alias KEY_MARK = _NC_KEY_MARK;
85+
alias KEY_MESSAGE = _NC_KEY_MESSAGE;
86+
alias KEY_MOVE = _NC_KEY_MOVE;
87+
alias KEY_NEXT = _NC_KEY_NEXT;
88+
alias KEY_OPEN = _NC_KEY_OPEN;
89+
alias KEY_OPTIONS = _NC_KEY_OPTIONS;
90+
alias KEY_PREVIOUS = _NC_KEY_PREVIOUS;
91+
alias KEY_REDO = _NC_KEY_REDO;
92+
alias KEY_REFERENCE = _NC_KEY_REFERENCE;
93+
alias KEY_REFRESH = _NC_KEY_REFRESH;
94+
alias KEY_REPLACE = _NC_KEY_REPLACE;
95+
alias KEY_RESTART = _NC_KEY_RESTART;
96+
alias KEY_RESUME = _NC_KEY_RESUME;
97+
alias KEY_SAVE = _NC_KEY_SAVE;
98+
alias KEY_SUSPEND = _NC_KEY_SUSPEND;
99+
alias KEY_UNDO = _NC_KEY_UNDO;
100+
alias KEY_MOUSE = _NC_KEY_MOUSE;
101+
102+
// Shifted keys
103+
alias KEY_SBEG = _NC_KEY_SBEG;
104+
alias KEY_SCANCEL = _NC_KEY_SCANCEL;
105+
alias KEY_SCOMMAND = _NC_KEY_SCOMMAND;
106+
alias KEY_SCOPY = _NC_KEY_SCOPY;
107+
alias KEY_SCREATE = _NC_KEY_SCREATE;
108+
alias KEY_SDC = _NC_KEY_SDC;
109+
alias KEY_SDL = _NC_KEY_SDL;
110+
alias KEY_SELECT = _NC_KEY_SELECT;
111+
alias KEY_SEND = _NC_KEY_SEND;
112+
alias KEY_SEOL = _NC_KEY_SEOL;
113+
alias KEY_SEXIT = _NC_KEY_SEXIT;
114+
alias KEY_SFIND = _NC_KEY_SFIND;
115+
alias KEY_SHELP = _NC_KEY_SHELP;
116+
alias KEY_SHOME = _NC_KEY_SHOME;
117+
alias KEY_SIC = _NC_KEY_SIC;
118+
alias KEY_SLEFT = _NC_KEY_SLEFT;
119+
alias KEY_SMESSAGE = _NC_KEY_SMESSAGE;
120+
alias KEY_SMOVE = _NC_KEY_SMOVE;
121+
alias KEY_SNEXT = _NC_KEY_SNEXT;
122+
alias KEY_SOPTIONS = _NC_KEY_SOPTIONS;
123+
alias KEY_SPREVIOUS = _NC_KEY_SPREVIOUS;
124+
alias KEY_SPRINT = _NC_KEY_SPRINT;
125+
alias KEY_SREDO = _NC_KEY_SREDO;
126+
alias KEY_SREPLACE = _NC_KEY_SREPLACE;
127+
alias KEY_SRIGHT = _NC_KEY_SRIGHT;
128+
alias KEY_SRSUME = _NC_KEY_SRSUME;
129+
alias KEY_SSAVE = _NC_KEY_SSAVE;
130+
alias KEY_SSUSPEND = _NC_KEY_SSUSPEND;
131+
alias KEY_SUNDO = _NC_KEY_SUNDO;
132+
133+
// Function key aliases for convenience
134+
alias KEY_F0 = _NC_KEY_F0;
135+
alias KEY_F1 = _NC_KEY_F1;
136+
alias KEY_F2 = _NC_KEY_F2;
137+
alias KEY_F3 = _NC_KEY_F3;
138+
alias KEY_F4 = _NC_KEY_F4;
139+
alias KEY_F5 = _NC_KEY_F5;
140+
alias KEY_F6 = _NC_KEY_F6;
141+
alias KEY_F7 = _NC_KEY_F7;
142+
alias KEY_F8 = _NC_KEY_F8;
143+
alias KEY_F9 = _NC_KEY_F9;
144+
alias KEY_F10 = _NC_KEY_F10;
145+
alias KEY_F11 = _NC_KEY_F11;
146+
alias KEY_F12 = _NC_KEY_F12;
147+
148+
// NCURSES_PAIRS_T is a macro that expands to 'short'
149+
alias NCURSES_PAIRS_T = short;
150+
151+
// ============================================================================
152+
// Wrapper functions for type compatibility
153+
// ImportC uses raw C types; these wrappers adapt to D's type system
154+
// ============================================================================
155+
156+
import core.sys.posix.stdio : FILE;
157+
158+
// Wrapper for newterm - handles FILE* type difference
159+
// D's std.stdio.File.getFP() returns shared(_IO_FILE)* but ncurses wants _IO_FILE*
160+
SCREEN* newterm(const(char)* term, FILE* outfd, FILE* infd) @trusted
161+
{
162+
return btdu_ncurses_importc.newterm(term,
163+
cast(btdu_ncurses_importc._IO_FILE*) outfd,
164+
cast(btdu_ncurses_importc._IO_FILE*) infd);
165+
}
166+
167+
// Wrapper for setcchar - handles wchar_t type difference
168+
// D uses dchar (wchar_t from core.stdc.stddef), ImportC sees wchar_t as int
169+
int setcchar(cchar_t* wcval, const(wchar_t)* wch, uint attrs, short color_pair, const(void)* opts) @trusted
170+
{
171+
return btdu_ncurses_importc.setcchar(wcval,
172+
cast(const(int)*) wch,
173+
attrs, color_pair, opts);
174+
}

source/btdu_ncurses_importc.c

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
// ImportC shim for ncurses
2+
// Captures system ncurses configuration (NCURSES_OPAQUE, etc.) automatically.
3+
//
4+
// This file is compiled by ImportC to extract ncurses declarations.
5+
// C enums export macro constants as D manifest constants.
6+
7+
// Disable glibc inline functions that cause infinite recursion with ImportC
8+
// These inlines (like wctob) shadow libc functions and call themselves
9+
// __NO_INLINE__ prevents features.h from defining __USE_EXTERN_INLINES
10+
#define __NO_INLINE__ 1
11+
12+
#undef _FORTIFY_SOURCE
13+
#define _FORTIFY_SOURCE 0
14+
#define _XOPEN_SOURCE_EXTENDED 1
15+
#include <ncurses.h>
16+
17+
// Export macro constants as C enums (become D manifest constants)
18+
// Using _NC_ prefix; D wrapper aliases these to original names
19+
enum {
20+
// Attributes
21+
_NC_A_NORMAL = A_NORMAL,
22+
_NC_A_STANDOUT = A_STANDOUT,
23+
_NC_A_UNDERLINE = A_UNDERLINE,
24+
_NC_A_REVERSE = A_REVERSE,
25+
_NC_A_BLINK = A_BLINK,
26+
_NC_A_DIM = A_DIM,
27+
_NC_A_BOLD = A_BOLD,
28+
_NC_A_ALTCHARSET = A_ALTCHARSET,
29+
_NC_A_INVIS = A_INVIS,
30+
_NC_A_PROTECT = A_PROTECT,
31+
_NC_A_HORIZONTAL = A_HORIZONTAL,
32+
_NC_A_LEFT = A_LEFT,
33+
_NC_A_LOW = A_LOW,
34+
_NC_A_RIGHT = A_RIGHT,
35+
_NC_A_TOP = A_TOP,
36+
_NC_A_VERTICAL = A_VERTICAL,
37+
_NC_A_ITALIC = A_ITALIC,
38+
39+
// Return codes
40+
_NC_OK = OK,
41+
_NC_ERR = ERR,
42+
43+
// Configuration (from autoconf)
44+
_NC_CCHARW_MAX = CCHARW_MAX,
45+
46+
// Key codes - basic navigation
47+
_NC_KEY_DOWN = KEY_DOWN,
48+
_NC_KEY_UP = KEY_UP,
49+
_NC_KEY_LEFT = KEY_LEFT,
50+
_NC_KEY_RIGHT = KEY_RIGHT,
51+
_NC_KEY_HOME = KEY_HOME,
52+
_NC_KEY_BACKSPACE = KEY_BACKSPACE,
53+
_NC_KEY_DL = KEY_DL,
54+
_NC_KEY_IL = KEY_IL,
55+
_NC_KEY_DC = KEY_DC,
56+
_NC_KEY_IC = KEY_IC,
57+
_NC_KEY_EIC = KEY_EIC,
58+
_NC_KEY_CLEAR = KEY_CLEAR,
59+
_NC_KEY_EOS = KEY_EOS,
60+
_NC_KEY_EOL = KEY_EOL,
61+
_NC_KEY_SF = KEY_SF,
62+
_NC_KEY_SR = KEY_SR,
63+
_NC_KEY_NPAGE = KEY_NPAGE,
64+
_NC_KEY_PPAGE = KEY_PPAGE,
65+
_NC_KEY_STAB = KEY_STAB,
66+
_NC_KEY_CTAB = KEY_CTAB,
67+
_NC_KEY_CATAB = KEY_CATAB,
68+
_NC_KEY_ENTER = KEY_ENTER,
69+
_NC_KEY_PRINT = KEY_PRINT,
70+
_NC_KEY_LL = KEY_LL,
71+
_NC_KEY_A1 = KEY_A1,
72+
_NC_KEY_A3 = KEY_A3,
73+
_NC_KEY_B2 = KEY_B2,
74+
_NC_KEY_C1 = KEY_C1,
75+
_NC_KEY_C3 = KEY_C3,
76+
_NC_KEY_BTAB = KEY_BTAB,
77+
_NC_KEY_BEG = KEY_BEG,
78+
_NC_KEY_CANCEL = KEY_CANCEL,
79+
_NC_KEY_CLOSE = KEY_CLOSE,
80+
_NC_KEY_COMMAND = KEY_COMMAND,
81+
_NC_KEY_COPY = KEY_COPY,
82+
_NC_KEY_CREATE = KEY_CREATE,
83+
_NC_KEY_END = KEY_END,
84+
_NC_KEY_EXIT = KEY_EXIT,
85+
_NC_KEY_FIND = KEY_FIND,
86+
_NC_KEY_HELP = KEY_HELP,
87+
_NC_KEY_MARK = KEY_MARK,
88+
_NC_KEY_MESSAGE = KEY_MESSAGE,
89+
_NC_KEY_MOVE = KEY_MOVE,
90+
_NC_KEY_NEXT = KEY_NEXT,
91+
_NC_KEY_OPEN = KEY_OPEN,
92+
_NC_KEY_OPTIONS = KEY_OPTIONS,
93+
_NC_KEY_PREVIOUS = KEY_PREVIOUS,
94+
_NC_KEY_REDO = KEY_REDO,
95+
_NC_KEY_REFERENCE = KEY_REFERENCE,
96+
_NC_KEY_REFRESH = KEY_REFRESH,
97+
_NC_KEY_REPLACE = KEY_REPLACE,
98+
_NC_KEY_RESTART = KEY_RESTART,
99+
_NC_KEY_RESUME = KEY_RESUME,
100+
_NC_KEY_SAVE = KEY_SAVE,
101+
_NC_KEY_SUSPEND = KEY_SUSPEND,
102+
_NC_KEY_UNDO = KEY_UNDO,
103+
_NC_KEY_MOUSE = KEY_MOUSE,
104+
105+
// Shifted keys
106+
_NC_KEY_SBEG = KEY_SBEG,
107+
_NC_KEY_SCANCEL = KEY_SCANCEL,
108+
_NC_KEY_SCOMMAND = KEY_SCOMMAND,
109+
_NC_KEY_SCOPY = KEY_SCOPY,
110+
_NC_KEY_SCREATE = KEY_SCREATE,
111+
_NC_KEY_SDC = KEY_SDC,
112+
_NC_KEY_SDL = KEY_SDL,
113+
_NC_KEY_SELECT = KEY_SELECT,
114+
_NC_KEY_SEND = KEY_SEND,
115+
_NC_KEY_SEOL = KEY_SEOL,
116+
_NC_KEY_SEXIT = KEY_SEXIT,
117+
_NC_KEY_SFIND = KEY_SFIND,
118+
_NC_KEY_SHELP = KEY_SHELP,
119+
_NC_KEY_SHOME = KEY_SHOME,
120+
_NC_KEY_SIC = KEY_SIC,
121+
_NC_KEY_SLEFT = KEY_SLEFT,
122+
_NC_KEY_SMESSAGE = KEY_SMESSAGE,
123+
_NC_KEY_SMOVE = KEY_SMOVE,
124+
_NC_KEY_SNEXT = KEY_SNEXT,
125+
_NC_KEY_SOPTIONS = KEY_SOPTIONS,
126+
_NC_KEY_SPREVIOUS = KEY_SPREVIOUS,
127+
_NC_KEY_SPRINT = KEY_SPRINT,
128+
_NC_KEY_SREDO = KEY_SREDO,
129+
_NC_KEY_SREPLACE = KEY_SREPLACE,
130+
_NC_KEY_SRIGHT = KEY_SRIGHT,
131+
_NC_KEY_SRSUME = KEY_SRSUME,
132+
_NC_KEY_SSAVE = KEY_SSAVE,
133+
_NC_KEY_SSUSPEND = KEY_SSUSPEND,
134+
_NC_KEY_SUNDO = KEY_SUNDO,
135+
136+
// Function keys - KEY_F(n) macro
137+
_NC_KEY_F0 = KEY_F(0),
138+
_NC_KEY_F1 = KEY_F(1),
139+
_NC_KEY_F2 = KEY_F(2),
140+
_NC_KEY_F3 = KEY_F(3),
141+
_NC_KEY_F4 = KEY_F(4),
142+
_NC_KEY_F5 = KEY_F(5),
143+
_NC_KEY_F6 = KEY_F(6),
144+
_NC_KEY_F7 = KEY_F(7),
145+
_NC_KEY_F8 = KEY_F(8),
146+
_NC_KEY_F9 = KEY_F(9),
147+
_NC_KEY_F10 = KEY_F(10),
148+
_NC_KEY_F11 = KEY_F(11),
149+
_NC_KEY_F12 = KEY_F(12),
150+
};

0 commit comments

Comments
 (0)