abandon input libraries and do it ourselves
This commit is contained in:
parent
e9bf4d0986
commit
7d52612b72
@ -1,7 +1,5 @@
|
|||||||
CMAKE_MINIMUM_REQUIRED(VERSION 3.0)
|
CMAKE_MINIMUM_REQUIRED(VERSION 3.0)
|
||||||
|
|
||||||
LIST(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
|
||||||
|
|
||||||
FIND_PACKAGE(PkgConfig)
|
FIND_PACKAGE(PkgConfig)
|
||||||
FIND_PACKAGE(Threads)
|
FIND_PACKAGE(Threads)
|
||||||
|
|
||||||
|
@ -1,49 +0,0 @@
|
|||||||
# Code copied from sethhall@github
|
|
||||||
#
|
|
||||||
# - Try to find readline include dirs and libraries
|
|
||||||
#
|
|
||||||
# Usage of this module as follows:
|
|
||||||
#
|
|
||||||
# find_package(Readline)
|
|
||||||
#
|
|
||||||
# Variables used by this module, they can change the default behaviour and need
|
|
||||||
# to be set before calling find_package:
|
|
||||||
#
|
|
||||||
# Readline_ROOT_DIR Set this variable to the root installation of
|
|
||||||
# readline if the module has problems finding the
|
|
||||||
# proper installation path.
|
|
||||||
#
|
|
||||||
# Variables defined by this module:
|
|
||||||
#
|
|
||||||
# READLINE_FOUND System has readline, include and lib dirs found
|
|
||||||
# Readline_INCLUDE_DIR The readline include directories.
|
|
||||||
# Readline_LIBRARY The readline library.
|
|
||||||
|
|
||||||
find_path(Readline_ROOT_DIR
|
|
||||||
NAMES include/readline/readline.h
|
|
||||||
)
|
|
||||||
|
|
||||||
find_path(Readline_INCLUDE_DIR
|
|
||||||
NAMES readline/readline.h
|
|
||||||
HINTS ${Readline_ROOT_DIR}/include
|
|
||||||
)
|
|
||||||
|
|
||||||
find_library(Readline_LIBRARY
|
|
||||||
NAMES readline
|
|
||||||
HINTS ${Readline_ROOT_DIR}/lib
|
|
||||||
)
|
|
||||||
|
|
||||||
if(Readline_INCLUDE_DIR AND Readline_LIBRARY AND Ncurses_LIBRARY)
|
|
||||||
set(READLINE_FOUND TRUE)
|
|
||||||
else(Readline_INCLUDE_DIR AND Readline_LIBRARY AND Ncurses_LIBRARY)
|
|
||||||
FIND_LIBRARY(Readline_LIBRARY NAMES readline)
|
|
||||||
include(FindPackageHandleStandardArgs)
|
|
||||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(Readline DEFAULT_MSG Readline_INCLUDE_DIR Readline_LIBRARY )
|
|
||||||
MARK_AS_ADVANCED(Readline_INCLUDE_DIR Readline_LIBRARY)
|
|
||||||
endif(Readline_INCLUDE_DIR AND Readline_LIBRARY AND Ncurses_LIBRARY)
|
|
||||||
|
|
||||||
mark_as_advanced(
|
|
||||||
Readline_ROOT_DIR
|
|
||||||
Readline_INCLUDE_DIR
|
|
||||||
Readline_LIBRARY
|
|
||||||
)
|
|
@ -1,16 +1,20 @@
|
|||||||
CMAKE_MINIMUM_REQUIRED(VERSION 3.0)
|
CMAKE_MINIMUM_REQUIRED(VERSION 3.0)
|
||||||
|
|
||||||
PKG_CHECK_MODULES(NCURSES REQUIRED ncurses)
|
PKG_CHECK_MODULES(NCURSES REQUIRED ncursesw)
|
||||||
PKG_CHECK_MODULES(PANEL REQUIRED panel)
|
PKG_CHECK_MODULES(PANEL REQUIRED panel)
|
||||||
FIND_PACKAGE(Readline)
|
PKG_CHECK_MODULES(EDIT REQUIRED libedit)
|
||||||
|
|
||||||
SET(TARGET "ncdc")
|
SET(TARGET "ncdc")
|
||||||
|
|
||||||
SET(SOURCES
|
SET(SOURCES
|
||||||
|
"include/ncdc/input.h"
|
||||||
"include/ncdc/mainwindow.h"
|
"include/ncdc/mainwindow.h"
|
||||||
"include/ncdc/ncdc.h"
|
"include/ncdc/ncdc.h"
|
||||||
|
"src/emacs.c"
|
||||||
|
"src/input.c"
|
||||||
"src/mainwindow.c"
|
"src/mainwindow.c"
|
||||||
"src/ncdc.c"
|
"src/ncdc.c"
|
||||||
|
"src/util.c"
|
||||||
)
|
)
|
||||||
|
|
||||||
INCLUDE_DIRECTORIES(
|
INCLUDE_DIRECTORIES(
|
||||||
@ -22,7 +26,7 @@ INCLUDE_DIRECTORIES(
|
|||||||
${GLIB2_INCLUDE_DIRS}
|
${GLIB2_INCLUDE_DIRS}
|
||||||
${NCURSES_INCLUDE_DIRS}
|
${NCURSES_INCLUDE_DIRS}
|
||||||
${PANEL_INCLUDE_DIRS}
|
${PANEL_INCLUDE_DIRS}
|
||||||
${Readline_INCLUDE_DIR}
|
${EDIT_INCLUDE_DIRS}
|
||||||
)
|
)
|
||||||
|
|
||||||
ADD_EXECUTABLE(${TARGET} ${SOURCES})
|
ADD_EXECUTABLE(${TARGET} ${SOURCES})
|
||||||
@ -31,5 +35,5 @@ TARGET_LINK_LIBRARIES(${TARGET}
|
|||||||
${GLIB2_LIBRARIES}
|
${GLIB2_LIBRARIES}
|
||||||
${NCURSES_LIBRARIES}
|
${NCURSES_LIBRARIES}
|
||||||
${PANEL_LIBRARIES}
|
${PANEL_LIBRARIES}
|
||||||
${Readline_LIBRARY}
|
${EDIT_LIBRARIES}
|
||||||
)
|
)
|
||||||
|
40
ncdc/include/ncdc/input.h
Normal file
40
ncdc/include/ncdc/input.h
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
#ifndef NCDC_INPUT_H
|
||||||
|
#define NCDC_INPUT_H
|
||||||
|
|
||||||
|
#include <ncdc/ncdc.h>
|
||||||
|
|
||||||
|
struct ncdc_input_;
|
||||||
|
typedef struct ncdc_input_ *ncdc_input_t;
|
||||||
|
|
||||||
|
typedef void (*ncdc_keybinding_t)(ncdc_input_t p);
|
||||||
|
|
||||||
|
typedef bool (*ncdc_input_callback_t)(ncdc_input_t p, wchar_t const *str,
|
||||||
|
size_t len, void *data);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char const *key;
|
||||||
|
char const *name;
|
||||||
|
ncdc_keybinding_t handler;
|
||||||
|
} ncdc_input_keybinding_t;
|
||||||
|
|
||||||
|
#define NCDC_BINDING(k, n, f) { k, n, f }
|
||||||
|
|
||||||
|
extern ncdc_input_keybinding_t emacs[];
|
||||||
|
|
||||||
|
ncdc_input_t ncdc_input_new(void);
|
||||||
|
|
||||||
|
void ncdc_input_feed(ncdc_input_t input, wchar_t c);
|
||||||
|
int ncdc_input_cursor(ncdc_input_t input);
|
||||||
|
char const *ncdc_input_buffer(ncdc_input_t input);
|
||||||
|
void ncdc_input_draw(ncdc_input_t input, WINDOW *win);
|
||||||
|
|
||||||
|
void ncdc_input_set_callback(ncdc_input_t i, ncdc_input_callback_t c, void *a);
|
||||||
|
|
||||||
|
/* keybinding functions
|
||||||
|
*/
|
||||||
|
void ncdc_input_backward(ncdc_input_t i);
|
||||||
|
void ncdc_input_forward(ncdc_input_t i);
|
||||||
|
void ncdc_input_delete(ncdc_input_t input);
|
||||||
|
void ncdc_input_delete_backward(ncdc_input_t input);
|
||||||
|
|
||||||
|
#endif
|
@ -6,9 +6,9 @@
|
|||||||
struct ncdc_mainwindow_;
|
struct ncdc_mainwindow_;
|
||||||
typedef struct ncdc_mainwindow_ *ncdc_mainwindow_t;
|
typedef struct ncdc_mainwindow_ *ncdc_mainwindow_t;
|
||||||
|
|
||||||
bool ncdc_mainwindow_init(void);
|
ncdc_mainwindow_t ncdc_mainwindow_new(void);
|
||||||
|
|
||||||
void ncdc_mainwindow_feed(int ch);
|
void ncdc_mainwindow_refresh(ncdc_mainwindow_t n);
|
||||||
void ncdc_mainwindow_refresh(void);
|
void ncdc_mainwindow_input_ready(ncdc_mainwindow_t n);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <wctype.h>
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
@ -23,8 +24,8 @@
|
|||||||
|
|
||||||
#include <curses.h>
|
#include <curses.h>
|
||||||
#include <panel.h>
|
#include <panel.h>
|
||||||
#include <readline/history.h>
|
|
||||||
#include <readline/readline.h>
|
#include <locale.h>
|
||||||
|
|
||||||
#include <dc/refable.h>
|
#include <dc/refable.h>
|
||||||
#include <dc/api.h>
|
#include <dc/api.h>
|
||||||
@ -35,4 +36,7 @@
|
|||||||
|
|
||||||
extern char *ncdc_private_dir;
|
extern char *ncdc_private_dir;
|
||||||
|
|
||||||
|
int strwidth(char const *string);
|
||||||
|
char *read_char(FILE *stream);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
11
ncdc/src/emacs.c
Normal file
11
ncdc/src/emacs.c
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#include <ncdc/input.h>
|
||||||
|
|
||||||
|
ncdc_input_keybinding_t emacs[] = {
|
||||||
|
NCDC_BINDING("KEY_RIGHT", "forward", ncdc_input_forward),
|
||||||
|
NCDC_BINDING("KEY_LEFT", "backward", ncdc_input_backward),
|
||||||
|
NCDC_BINDING("^F", "forward", ncdc_input_forward),
|
||||||
|
NCDC_BINDING("^B", "backward", ncdc_input_backward),
|
||||||
|
NCDC_BINDING("^D", "delete", ncdc_input_delete),
|
||||||
|
NCDC_BINDING("KEY_BACKSPACE", "delete", ncdc_input_delete_backward),
|
||||||
|
NCDC_BINDING(NULL, NULL, NULL)
|
||||||
|
};
|
151
ncdc/src/input.c
Normal file
151
ncdc/src/input.c
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
#include <ncdc/input.h>
|
||||||
|
#include <ncdc/ncdc.h>
|
||||||
|
|
||||||
|
struct ncdc_input_
|
||||||
|
{
|
||||||
|
dc_refable_t ref;
|
||||||
|
|
||||||
|
GArray *buffer;
|
||||||
|
int cursor;
|
||||||
|
ncdc_input_keybinding_t *keys;
|
||||||
|
|
||||||
|
ncdc_input_callback_t callback;
|
||||||
|
void *callback_arg;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void ncdc_input_enter(ncdc_input_t p);
|
||||||
|
|
||||||
|
static void ncdc_input_free(ncdc_input_t p)
|
||||||
|
{
|
||||||
|
g_array_unref(p->buffer);
|
||||||
|
|
||||||
|
free(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
ncdc_input_t ncdc_input_new(void)
|
||||||
|
{
|
||||||
|
ncdc_input_t p = calloc(1, sizeof(struct ncdc_input_));
|
||||||
|
return_if_true(p == NULL, NULL);
|
||||||
|
|
||||||
|
p->ref.cleanup = (dc_cleanup_t)ncdc_input_free;
|
||||||
|
|
||||||
|
p->buffer = g_array_new(TRUE, TRUE, sizeof(wchar_t));
|
||||||
|
p->cursor = 0;
|
||||||
|
|
||||||
|
p->keys = emacs;
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ncdc_keybinding_t has_binding(ncdc_input_t in, wchar_t key)
|
||||||
|
{
|
||||||
|
char const *k = keyname(key);
|
||||||
|
size_t i = 0;
|
||||||
|
|
||||||
|
for (; in->keys[i].name != NULL; i++) {
|
||||||
|
if (strcmp(k, in->keys[i].key) == 0) {
|
||||||
|
return in->keys[i].handler;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ncdc_input_feed(ncdc_input_t input, wchar_t c)
|
||||||
|
{
|
||||||
|
return_if_true(input == NULL,);
|
||||||
|
ncdc_keybinding_t handler = NULL;
|
||||||
|
|
||||||
|
if (c == '\r') {
|
||||||
|
ncdc_input_enter(input);
|
||||||
|
} else if ((handler = has_binding(input, c)) != NULL) {
|
||||||
|
handler(input);
|
||||||
|
} else if (iswprint(c)) {
|
||||||
|
g_array_insert_vals(input->buffer, input->cursor, &c, 1);
|
||||||
|
input->cursor += wcswidth(&c, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ncdc_input_set_callback(ncdc_input_t i, ncdc_input_callback_t c, void *a)
|
||||||
|
{
|
||||||
|
return_if_true(i == NULL,);
|
||||||
|
|
||||||
|
i->callback = c;
|
||||||
|
i->callback_arg = a;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ncdc_input_cursor(ncdc_input_t input)
|
||||||
|
{
|
||||||
|
return_if_true(input == NULL, 0);
|
||||||
|
return input->cursor;
|
||||||
|
}
|
||||||
|
|
||||||
|
char const *ncdc_input_buffer(ncdc_input_t input)
|
||||||
|
{
|
||||||
|
return_if_true(input == NULL, NULL);
|
||||||
|
return (char const *)input->buffer->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ncdc_input_draw(ncdc_input_t input, WINDOW *win)
|
||||||
|
{
|
||||||
|
werase(win);
|
||||||
|
mvwaddwstr(win, 0, 0, (wchar_t const *)input->buffer->data);
|
||||||
|
wmove(win, 0, input->cursor);
|
||||||
|
wrefresh(win);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ncdc_input_enter(ncdc_input_t input)
|
||||||
|
{
|
||||||
|
if (input->buffer->len == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input->callback != NULL) {
|
||||||
|
bool ret = false;
|
||||||
|
|
||||||
|
ret = input->callback(input,
|
||||||
|
(wchar_t const *)input->buffer->data,
|
||||||
|
input->buffer->len,
|
||||||
|
input->callback_arg
|
||||||
|
);
|
||||||
|
if (ret) {
|
||||||
|
/* TODO: add to history
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_array_remove_range(input->buffer, 0, input->buffer->len);
|
||||||
|
input->cursor = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ncdc_input_delete(ncdc_input_t input)
|
||||||
|
{
|
||||||
|
return_if_true(input->cursor == input->buffer->len,);
|
||||||
|
g_array_remove_index(input->buffer, input->cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ncdc_input_delete_backward(ncdc_input_t input)
|
||||||
|
{
|
||||||
|
return_if_true(input->cursor == 0,);
|
||||||
|
|
||||||
|
g_array_remove_index(input->buffer, input->cursor-1);
|
||||||
|
--input->cursor;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ncdc_input_backward(ncdc_input_t input)
|
||||||
|
{
|
||||||
|
return_if_true(input->cursor == 0,);
|
||||||
|
|
||||||
|
wchar_t c = g_array_index(input->buffer, wchar_t, input->cursor-1);
|
||||||
|
int len = wcswidth(&c, 1);
|
||||||
|
input->cursor -= len;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ncdc_input_forward(ncdc_input_t input)
|
||||||
|
{
|
||||||
|
return_if_true(input->cursor >= input->buffer->len,);
|
||||||
|
|
||||||
|
wchar_t c = g_array_index(input->buffer, wchar_t, input->cursor);
|
||||||
|
int len = wcswidth(&c, 1);
|
||||||
|
input->cursor += len;
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
#include <ncdc/mainwindow.h>
|
#include <ncdc/mainwindow.h>
|
||||||
|
#include <ncdc/input.h>
|
||||||
#include <ncdc/ncdc.h>
|
#include <ncdc/ncdc.h>
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@ -28,141 +29,105 @@ struct ncdc_mainwindow_
|
|||||||
int input_h;
|
int input_h;
|
||||||
int input_y;
|
int input_y;
|
||||||
int input_x;
|
int input_x;
|
||||||
|
int input_curs_x;
|
||||||
|
|
||||||
char *cmd;
|
WINDOW *sep1;
|
||||||
int cin;
|
WINDOW *sep2;
|
||||||
bool cin_ready;
|
|
||||||
|
ncdc_input_t in;
|
||||||
|
|
||||||
int focus;
|
int focus;
|
||||||
};
|
};
|
||||||
|
|
||||||
static ncdc_mainwindow_t mainwin = NULL;
|
static void ncdc_mainwindow_resize(ncdc_mainwindow_t n);
|
||||||
|
static void ncdc_mainwindow_update_focus(ncdc_mainwindow_t n);
|
||||||
|
|
||||||
static void mainwin_resize(void);
|
static void ncdc_mainwindow_free(ncdc_mainwindow_t n)
|
||||||
static void mainwin_update_focus(void);
|
|
||||||
static void mainwin_command(char *s);
|
|
||||||
|
|
||||||
static int readline_input_avail(void)
|
|
||||||
{
|
{
|
||||||
return mainwin->cin_ready;
|
return_if_true(n == NULL,);
|
||||||
|
|
||||||
|
delwin(n->guilds);
|
||||||
|
delwin(n->chat);
|
||||||
|
delwin(n->input);
|
||||||
|
|
||||||
|
delwin(n->sep1);
|
||||||
|
delwin(n->sep2);
|
||||||
|
|
||||||
|
dc_unref(n->in);
|
||||||
|
|
||||||
|
free(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int readline_getc(FILE *dummy)
|
ncdc_mainwindow_t ncdc_mainwindow_new(void)
|
||||||
{
|
{
|
||||||
mainwin->cin_ready = false;
|
ncdc_mainwindow_t ptr = calloc(1, sizeof(struct ncdc_mainwindow_));
|
||||||
return mainwin->cin;
|
return_if_true(ptr == NULL, NULL);
|
||||||
|
|
||||||
|
ptr->ref.cleanup = (dc_cleanup_t)ncdc_mainwindow_free;
|
||||||
|
|
||||||
|
ptr->in = ncdc_input_new();
|
||||||
|
|
||||||
|
ptr->guilds = newwin(5, 5, 1, 1);
|
||||||
|
ptr->chat = newwin(5, 5, 4, 4);
|
||||||
|
|
||||||
|
ptr->input = newwin(5, 5, 8, 8);
|
||||||
|
keypad(ptr->input, TRUE);
|
||||||
|
|
||||||
|
ptr->sep1 = newwin(5, 5, 10, 10);
|
||||||
|
ptr->sep2 = newwin(5, 5, 12, 12);
|
||||||
|
|
||||||
|
ncdc_mainwindow_resize(ptr);
|
||||||
|
|
||||||
|
ptr->focus = FOCUS_INPUT;
|
||||||
|
ncdc_mainwindow_update_focus(ptr);
|
||||||
|
|
||||||
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int measure(char const *string)
|
static void ncdc_mainwindow_resize(ncdc_mainwindow_t n)
|
||||||
{
|
{
|
||||||
size_t needed = mbstowcs(NULL, string, 0) + 1;
|
n->guilds_h = LINES - 2;
|
||||||
wchar_t *wcstring = calloc(needed, sizeof(wchar_t));
|
n->guilds_w = (COLS / 5);
|
||||||
size_t ret = 0;
|
n->guilds_y = 0;
|
||||||
|
n->guilds_x = 0;
|
||||||
|
|
||||||
return_if_true(wcstring == NULL, -1);
|
wresize(n->guilds, n->guilds_h, n->guilds_w);
|
||||||
|
mvwin(n->guilds, n->guilds_y, n->guilds_x);
|
||||||
|
wnoutrefresh(n->guilds);
|
||||||
|
|
||||||
ret = mbstowcs(wcstring, string, needed);
|
n->input_h = 1;
|
||||||
if (ret == (size_t)-1) {
|
n->input_w = COLS;
|
||||||
free(wcstring);
|
n->input_y = LINES - n->input_h;
|
||||||
return -1;
|
n->input_x = 0;
|
||||||
}
|
|
||||||
|
|
||||||
int width = wcswidth(wcstring, needed);
|
wresize(n->input, n->input_h, n->input_w);
|
||||||
free(wcstring);
|
mvwin(n->input, n->input_y, n->input_x);
|
||||||
|
wnoutrefresh(n->input);
|
||||||
|
|
||||||
return width;
|
wresize(n->sep1, 1, COLS);
|
||||||
|
mvwin(n->sep1, LINES - 2, 0);
|
||||||
|
wbkgd(n->sep1, COLOR_PAIR(1));
|
||||||
|
wnoutrefresh(n->sep1);
|
||||||
|
|
||||||
|
n->chat_h = LINES - n->input_h - 1;
|
||||||
|
n->chat_w = COLS - n->guilds_w - 1;
|
||||||
|
n->chat_y = 0;
|
||||||
|
n->chat_x = n->guilds_w + 1;
|
||||||
|
|
||||||
|
wresize(n->chat, n->chat_h, n->chat_w);
|
||||||
|
mvwin(n->chat, n->chat_y, n->chat_x);
|
||||||
|
wnoutrefresh(n->chat);
|
||||||
|
|
||||||
|
wresize(n->sep2, LINES - 2, 1);
|
||||||
|
mvwin(n->sep2, 0, n->guilds_w + 1);
|
||||||
|
wnoutrefresh(n->sep2);
|
||||||
|
|
||||||
|
ncdc_mainwindow_update_focus(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void readline_redisplay(void)
|
static void ncdc_mainwindow_update_focus(ncdc_mainwindow_t n)
|
||||||
{
|
{
|
||||||
int len = 0;
|
switch (n->focus) {
|
||||||
char *line = NULL;
|
|
||||||
int diff = 0;
|
|
||||||
|
|
||||||
asprintf(&line, "%s%s",
|
|
||||||
(rl_display_prompt != NULL ? rl_display_prompt : ""),
|
|
||||||
(rl_line_buffer != NULL ? rl_line_buffer : "")
|
|
||||||
);
|
|
||||||
len = measure(line);
|
|
||||||
|
|
||||||
diff = len - mainwin->input_w + 3;
|
|
||||||
if (diff > 0) {
|
|
||||||
memmove(line, line + diff, len - diff);
|
|
||||||
line[len-diff] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
werase(mainwin->input);
|
|
||||||
mvwprintw(mainwin->input, 1, 1, "%s", line);
|
|
||||||
free(line);
|
|
||||||
|
|
||||||
wrefresh(mainwin->input);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ncdc_mainwindow_init(void)
|
|
||||||
{
|
|
||||||
mainwin = calloc(1, sizeof(struct ncdc_mainwindow_));
|
|
||||||
return_if_true(mainwin == NULL, false);
|
|
||||||
|
|
||||||
mainwin->guilds = newwin(5, 5, 1, 1);
|
|
||||||
mainwin->chat = newwin(5, 5, 4, 4);
|
|
||||||
mainwin->input = newwin(5, 5, 8, 8);
|
|
||||||
mainwin_resize();
|
|
||||||
|
|
||||||
mainwin->focus = FOCUS_INPUT;
|
|
||||||
mainwin_update_focus();
|
|
||||||
|
|
||||||
rl_getc_function = readline_getc;
|
|
||||||
rl_input_available_hook = readline_input_avail;
|
|
||||||
rl_redisplay_function = readline_redisplay;
|
|
||||||
rl_callback_handler_install("", mainwin_command);
|
|
||||||
|
|
||||||
rl_catch_signals = 0;
|
|
||||||
rl_catch_sigwinch = 0;
|
|
||||||
rl_deprep_term_function = NULL;
|
|
||||||
rl_prep_term_function = NULL;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void mainwin_resize(void)
|
|
||||||
{
|
|
||||||
mainwin->guilds_h = LINES;
|
|
||||||
mainwin->guilds_w = (COLS / 5);
|
|
||||||
mainwin->guilds_y = 0;
|
|
||||||
mainwin->guilds_x = 0;
|
|
||||||
|
|
||||||
wresize(mainwin->guilds, mainwin->guilds_h, mainwin->guilds_w);
|
|
||||||
mvwin(mainwin->guilds, mainwin->guilds_y, mainwin->guilds_x);
|
|
||||||
wnoutrefresh(mainwin->guilds);
|
|
||||||
|
|
||||||
mainwin->input_h = 3;
|
|
||||||
mainwin->input_w = COLS - mainwin->guilds_w;
|
|
||||||
mainwin->input_y = LINES - mainwin->input_h;
|
|
||||||
mainwin->input_x = mainwin->guilds_w;
|
|
||||||
|
|
||||||
wresize(mainwin->input, mainwin->input_h, mainwin->input_w);
|
|
||||||
mvwin(mainwin->input, mainwin->input_y, mainwin->input_x);
|
|
||||||
wnoutrefresh(mainwin->input);
|
|
||||||
|
|
||||||
mainwin->chat_h = LINES - mainwin->input_h;
|
|
||||||
mainwin->chat_w = COLS - mainwin->guilds_w;
|
|
||||||
mainwin->chat_y = 0;
|
|
||||||
mainwin->chat_x = mainwin->guilds_w;
|
|
||||||
|
|
||||||
wresize(mainwin->chat, mainwin->chat_h, mainwin->chat_w);
|
|
||||||
mvwin(mainwin->chat, mainwin->chat_y, mainwin->chat_x);
|
|
||||||
wnoutrefresh(mainwin->chat);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void mainwin_command(char *s)
|
|
||||||
{
|
|
||||||
free(mainwin->cmd);
|
|
||||||
mainwin->cmd = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void mainwin_update_focus(void)
|
|
||||||
{
|
|
||||||
switch (mainwin->focus) {
|
|
||||||
case FOCUS_GUILDS:
|
case FOCUS_GUILDS:
|
||||||
{
|
{
|
||||||
} break;
|
} break;
|
||||||
@ -173,41 +138,48 @@ static void mainwin_update_focus(void)
|
|||||||
|
|
||||||
case FOCUS_INPUT:
|
case FOCUS_INPUT:
|
||||||
{
|
{
|
||||||
int x = 1, y = 1;
|
wmove(n->input, 0, ncdc_input_cursor(n->in));
|
||||||
wmove(mainwin->input, y, x);
|
wrefresh(n->input);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ncdc_mainwindow_feed(int ch)
|
void ncdc_mainwindow_input_ready(ncdc_mainwindow_t n)
|
||||||
{
|
{
|
||||||
switch (ch) {
|
switch (n->focus) {
|
||||||
case KEY_RESIZE: mainwin_resize(); break;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (mainwin->focus) {
|
|
||||||
case FOCUS_INPUT:
|
case FOCUS_INPUT:
|
||||||
{
|
{
|
||||||
mainwin->cin = ch;
|
wint_t i = 0;
|
||||||
mainwin->cin_ready = true;
|
|
||||||
rl_callback_read_char();
|
if (wget_wch(n->input, &i) == ERR) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == KEY_RESIZE) {
|
||||||
|
ncdc_mainwindow_resize(n);
|
||||||
|
} else {
|
||||||
|
ncdc_input_feed(n->in, (wchar_t)i);
|
||||||
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ncdc_mainwindow_refresh(void)
|
void ncdc_mainwindow_refresh(ncdc_mainwindow_t n)
|
||||||
{
|
{
|
||||||
/* move windows
|
wnoutrefresh(n->guilds);
|
||||||
*/
|
wnoutrefresh(n->chat);
|
||||||
box(mainwin->guilds, 0, 0);
|
|
||||||
box(mainwin->chat, 0, 0);
|
|
||||||
box(mainwin->input, 0, 0);
|
|
||||||
|
|
||||||
wrefresh(mainwin->guilds);
|
ncdc_input_draw(n->in, n->input);
|
||||||
wrefresh(mainwin->chat);
|
wnoutrefresh(n->input);
|
||||||
wrefresh(mainwin->input);
|
|
||||||
|
wbkgd(n->sep1, COLOR_PAIR(1));
|
||||||
|
wnoutrefresh(n->sep1);
|
||||||
|
wbkgd(n->sep2, COLOR_PAIR(1));
|
||||||
|
wnoutrefresh(n->sep2);
|
||||||
|
|
||||||
|
ncdc_mainwindow_update_focus(n);
|
||||||
|
|
||||||
doupdate();
|
doupdate();
|
||||||
}
|
}
|
||||||
|
@ -48,11 +48,8 @@ static void cleanup(void)
|
|||||||
|
|
||||||
static void stdin_handler(int sock, short what, void *data)
|
static void stdin_handler(int sock, short what, void *data)
|
||||||
{
|
{
|
||||||
int ch = 0;
|
|
||||||
|
|
||||||
if ((what & EV_READ) == EV_READ) {
|
if ((what & EV_READ) == EV_READ) {
|
||||||
ch = getch();
|
ncdc_mainwindow_input_ready(mainwin);
|
||||||
ncdc_mainwindow_feed(ch);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,6 +57,8 @@ static bool init_everything(void)
|
|||||||
{
|
{
|
||||||
evthread_use_pthreads();
|
evthread_use_pthreads();
|
||||||
|
|
||||||
|
setlocale(LC_CTYPE, "");
|
||||||
|
|
||||||
loop = dc_loop_new();
|
loop = dc_loop_new();
|
||||||
return_if_true(loop == NULL, false);
|
return_if_true(loop == NULL, false);
|
||||||
|
|
||||||
@ -135,29 +134,34 @@ int main(int ac, char **av)
|
|||||||
done = false;
|
done = false;
|
||||||
|
|
||||||
initscr();
|
initscr();
|
||||||
cbreak();
|
|
||||||
noecho();
|
noecho();
|
||||||
nonl();
|
nonl();
|
||||||
|
keypad(stdscr, TRUE);
|
||||||
intrflush(NULL, FALSE);
|
intrflush(NULL, FALSE);
|
||||||
|
|
||||||
if (has_colors()) {
|
if (has_colors()) {
|
||||||
start_color();
|
start_color();
|
||||||
use_default_colors();
|
use_default_colors();
|
||||||
|
|
||||||
|
init_pair(1, COLOR_WHITE, COLOR_BLUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ncdc_mainwindow_init()) {
|
mainwin = ncdc_mainwindow_new();
|
||||||
|
if (mainwin == NULL) {
|
||||||
fprintf(stderr, "failed to init ncurses\n");
|
fprintf(stderr, "failed to init ncurses\n");
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!done) {
|
while (!done) {
|
||||||
ncdc_mainwindow_refresh();
|
ncdc_mainwindow_refresh(mainwin);
|
||||||
|
doupdate();
|
||||||
|
|
||||||
if (!dc_loop_once(loop)) {
|
if (!dc_loop_once(loop)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dc_unref(mainwin);
|
||||||
endwin();
|
endwin();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
39
ncdc/src/util.c
Normal file
39
ncdc/src/util.c
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#include <ncdc/ncdc.h>
|
||||||
|
|
||||||
|
char *read_char(FILE *stream)
|
||||||
|
{
|
||||||
|
uint8_t str[7] = {0};
|
||||||
|
int len = 0, i = 0;
|
||||||
|
|
||||||
|
/* check if we need more
|
||||||
|
*/
|
||||||
|
str[0] = (uint8_t)fgetc(stream);
|
||||||
|
len = g_utf8_skip[str[0]];
|
||||||
|
|
||||||
|
for (i = 1; i < len; i++) {
|
||||||
|
str[i] = (uint8_t)fgetc(stream);
|
||||||
|
}
|
||||||
|
str[len] = '\0';
|
||||||
|
|
||||||
|
return strdup((char const *)str);
|
||||||
|
}
|
||||||
|
|
||||||
|
int strwidth(char const *string)
|
||||||
|
{
|
||||||
|
size_t needed = mbstowcs(NULL, string, 0) + 1;
|
||||||
|
wchar_t *wcstring = calloc(needed, sizeof(wchar_t));
|
||||||
|
size_t ret = 0;
|
||||||
|
|
||||||
|
return_if_true(wcstring == NULL, -1);
|
||||||
|
|
||||||
|
ret = mbstowcs(wcstring, string, needed);
|
||||||
|
if (ret == (size_t)-1) {
|
||||||
|
free(wcstring);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int width = wcswidth(wcstring, needed);
|
||||||
|
free(wcstring);
|
||||||
|
|
||||||
|
return width;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user