add tmessage application
This commit is contained in:
parent
b3d186ee92
commit
bf5bfc71da
4
Makefile
4
Makefile
|
@ -44,7 +44,7 @@ sh:
|
||||||
check:
|
check:
|
||||||
shellcheck sh/*
|
shellcheck sh/*
|
||||||
|
|
||||||
mkc: c/scream c/timer c/boid c/anaconda c/colors c/xgetnewwindow
|
mkc: c/scream c/timer c/boid c/anaconda c/colors c/xgetnewwindow c/tmessage
|
||||||
|
|
||||||
c/boid:
|
c/boid:
|
||||||
cc c/boid.c -o c/boid -lm -lX11
|
cc c/boid.c -o c/boid -lm -lX11
|
||||||
|
@ -62,6 +62,7 @@ c:
|
||||||
cp -f c/anaconda $(DESTDIR)$(PREFIX)/bin
|
cp -f c/anaconda $(DESTDIR)$(PREFIX)/bin
|
||||||
cp -f c/colors $(DESTDIR)$(PREFIX)/bin
|
cp -f c/colors $(DESTDIR)$(PREFIX)/bin
|
||||||
cp -f c/xgetnewwindow $(DESTDIR)$(PREFIX)/bin
|
cp -f c/xgetnewwindow $(DESTDIR)$(PREFIX)/bin
|
||||||
|
cp -f c/tmessage $(DESTDIR)$(PREFIX)/bin
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f c/scream
|
rm -f c/scream
|
||||||
|
@ -70,3 +71,4 @@ clean:
|
||||||
rm -f c/anaconda
|
rm -f c/anaconda
|
||||||
rm -f c/simplestatus
|
rm -f c/simplestatus
|
||||||
rm -f c/xgetnewwindow
|
rm -f c/xgetnewwindow
|
||||||
|
rm -f c/tmessage
|
||||||
|
|
|
@ -0,0 +1,148 @@
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <termios.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define ESC_CLEAR "\033[2J"
|
||||||
|
#define ESC_CUSHOME "\033[H"
|
||||||
|
#define ESC_NEWLINE "\033[E\033[1C"
|
||||||
|
|
||||||
|
const char MSG_OK[] = "(O)k";
|
||||||
|
const char MSG_CANCEL[] = "(C)ancel";
|
||||||
|
|
||||||
|
typedef struct winsize ws;
|
||||||
|
|
||||||
|
int lines, cols;
|
||||||
|
char *message;
|
||||||
|
size_t message_len;
|
||||||
|
|
||||||
|
struct termios original_termios;
|
||||||
|
|
||||||
|
void render(char *message, int message_len, int lines, int cols);
|
||||||
|
|
||||||
|
void rawmode_start() {
|
||||||
|
tcgetattr(STDIN_FILENO, &original_termios);
|
||||||
|
struct termios raw = original_termios;
|
||||||
|
raw.c_lflag &= ~(ECHO | ICANON);
|
||||||
|
tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rawmode_stop() {
|
||||||
|
tcsetattr(STDIN_FILENO, TCSAFLUSH, &original_termios);
|
||||||
|
printf("\n\n");
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
ws *getWinSize(void) {
|
||||||
|
/* we're only going to use these values once per invocation,
|
||||||
|
* so it's fine that it's static. */
|
||||||
|
static ws w;
|
||||||
|
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
|
||||||
|
|
||||||
|
return &w;
|
||||||
|
}
|
||||||
|
|
||||||
|
void handler(int signal, siginfo_t *info, void *context) {
|
||||||
|
ws *w = getWinSize();
|
||||||
|
lines = w->ws_row;
|
||||||
|
cols = w->ws_col;
|
||||||
|
|
||||||
|
render(message, message_len, lines, cols);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void termhandler(int signal, siginfo_t *info, void *context) {
|
||||||
|
rawmode_stop();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int calculate_number_of_lines(int length, int cols) {
|
||||||
|
/* cols - 1 accounts for right padding */
|
||||||
|
return length / (cols - 1) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void go_to_initial_message_printing_pos(void) {
|
||||||
|
printf(ESC_CUSHOME "\033[1B\033[1C");
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_message(char *message, int messagelen, int cols) {
|
||||||
|
int linecount = calculate_number_of_lines(messagelen, cols);
|
||||||
|
int adjcols = cols - 2;
|
||||||
|
int offset = 1;
|
||||||
|
for(int character = 0; character < messagelen; character++) {
|
||||||
|
if(character == adjcols * offset) {
|
||||||
|
printf(ESC_NEWLINE);
|
||||||
|
offset++;
|
||||||
|
}
|
||||||
|
putchar(message[character]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void render(char *message, int messagelen, int lines, int cols) {
|
||||||
|
int cancel_length = sizeof(MSG_CANCEL) / sizeof(MSG_CANCEL[0]);
|
||||||
|
|
||||||
|
/* print the stuff */
|
||||||
|
printf(ESC_CLEAR "" ESC_CUSHOME);
|
||||||
|
go_to_initial_message_printing_pos();
|
||||||
|
print_message(message, message_len, cols);
|
||||||
|
|
||||||
|
printf(ESC_NEWLINE);
|
||||||
|
printf(ESC_NEWLINE);
|
||||||
|
printf("%s", MSG_OK);
|
||||||
|
printf("\033[1D\033[%iC\033[%iD%s", cols, cancel_length, MSG_CANCEL);
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
int cancel_length = strlen(MSG_CANCEL);
|
||||||
|
char c;
|
||||||
|
struct sigaction resizeaction = {};
|
||||||
|
struct sigaction termaction = {};
|
||||||
|
ws *w;
|
||||||
|
|
||||||
|
/* check if we have a message */
|
||||||
|
if(argc > 1) {
|
||||||
|
message = argv[1]; /* second argument's a message */
|
||||||
|
message_len = strlen(message);
|
||||||
|
} else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* setup sigaction handlers */
|
||||||
|
resizeaction.sa_sigaction = &handler;
|
||||||
|
if(sigaction(SIGWINCH, &resizeaction, NULL) == -1) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
termaction.sa_sigaction = &termhandler;
|
||||||
|
if(sigaction(SIGTERM, &termaction, NULL) == -1) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rawmode_start();
|
||||||
|
|
||||||
|
/* get window properties */
|
||||||
|
w = getWinSize();
|
||||||
|
lines = w->ws_row;
|
||||||
|
cols = w->ws_col;
|
||||||
|
|
||||||
|
render(message, message_len, lines, cols);
|
||||||
|
|
||||||
|
for(;;) {
|
||||||
|
read(STDIN_FILENO, &c, 1);
|
||||||
|
if(c == 'o') {
|
||||||
|
return 2;
|
||||||
|
rawmode_stop();
|
||||||
|
} else if(c == 'c') {
|
||||||
|
return 3;
|
||||||
|
rawmode_stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue