\$\begingroup\$
\$\endgroup\$
2
I've prepared a small C interface so the rest of my program can access relevant system functions. I am not a C programmer, though - just C++ and D, mainly. I want to make sure that everything here is "C-ish" before committing the rest of my code to this interface.
This is just a plain old C file, compiled with a C compiler (as opposed to C++).
/*
* This file provides functions to interface with
* low-level terminal properties such as size and
* input modes. Functions meant to be accessible
* to external "user" code begin with "Terminal."
*/
#include <sys/ioctl.h> // For interfacing with the terminal device.
#include <termios.h> // Ditto.
#include <unistd.h> // For the STDIN_FILENO file descriptor macro.
// This is just used internally, and should not be called directly from D code.
struct winsize Size()
{
struct winsize Size;
ioctl(STDIN_FILENO, TIOCGWINSZ, &Size);
return Size;
}
unsigned short int TerminalColumnCount()
{
return Size().ws_col;
}
unsigned short int TerminalRowCount()
{
return Size().ws_row;
}
// Used to reset the terminal properties to their original state.
// Again, this is only for internal use.
struct termios BackupProperties;
// Removes terminal input buffering so programs can see typed characters before Enter is pressed.
void TerminalMakeRaw() // I wish I could come up with a better name for this.
{
tcgetattr(STDIN_FILENO, &BackupProperties);
struct termios NewProperties;
cfmakeraw(&NewProperties);
tcsetattr(STDIN_FILENO, TCSANOW, &NewProperties);
}
void TerminalReset()
{
tcsetattr(STDIN_FILENO, TCSANOW, &BackupProperties);
}
200_success
145k22 gold badges190 silver badges478 bronze badges
asked Oct 18, 2011 at 3:03
1 Answer 1
\$\begingroup\$
\$\endgroup\$
2
A few quick comments:
- You should declare all internal functions and variables
static
to avoid polluting the global namespace. (You'd do this in a C++ program as well, but would probably use an unnamed namespace. I'm not sure what the D equivalent is). - Since you have state (implicitly and explicitly via
BackupProperties
) I'd recommend using an object oriented approach exposing an opaque pointer to maintain it, even if there is only oneTerminal
instance it's (IMO) a better approach. Otherwise you should at least ensure thatTerminalMakeRaw
isn't called twice without corresponding calls toTerminalReset
. - You should also consider that at some point you'll probably want to have callbacks of some sort to notify the users of your library when/if the window size changes and so on.
answered Oct 18, 2011 at 16:00
-
\$\begingroup\$ Pertaining to your second suggestion, I ended up going with a global state solution. I'm aware that it's often considered bad practice, but in this case I think it makes sense and I'm not going to overcomplicate things just on principle. \$\endgroup\$Maxpm– Maxpm2011年10月19日 19:45:49 +00:00Commented Oct 19, 2011 at 19:45
-
\$\begingroup\$ @Maxpm: As long as you're making an informed decision it's fine by me :) \$\endgroup\$user786653– user7866532011年10月19日 19:55:49 +00:00Commented Oct 19, 2011 at 19:55
lang-c
extern "C"
. \$\endgroup\$gcc
. I'll edit that into the question. \$\endgroup\$