Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Papercuts and other small, aggravating injuries #73

Merged
merged 9 commits into from
May 23, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@ deploy:
api_key:
secure: A3IZutdvZovr1s7efh66o96sGdY49b4tPg57usx/YyTGgF2LqIUY5M5wfrKRmCuey69v++8WFuODH9djr3y9JI0CI6pem/alFByp9AoL9gdZVeTWcl1k5PCSxux15xMcvd7PSO8UGhVCHq1A6XcBWjyHWDlE1zLAI+tVI6NrWd5clIPe3L+HyREkpK4tXQROD+dQ+htsAdr+6uY5ajcFdfqBM6ORHy4JB78/FO3cTj7Z702EWSwPfuUCSvWt2eEbbIyx8MH1XXczfqKKoSf7fGD60Ykr0hhOJXqbgeXBoHw/nooqxLTepI/nCWpfXU2ThzZV2Qmc86X2rTnja404mKzFxtIL+zJEj243PsCjbIXImiJNVyVP/J3rI0zYcr34pEwWd2cC+2AMf2NK50uh1GpRDtKmb5EmgD6nhnKKoU76mcmAuOJqzwaGLBazEWMjN/7K9Ny1iLb2PYDWPPRjLW06KO+vuZYthJtwH80DZ0JMZR5pbEe1he0kUciBGECLQPoJ+EDMS2eje5m2aOrfMJbd8ItEP4jjXzHd2WWsnbo8QYxU6Mf+yJp5EJzBu/dAmh0wTiI12JgPhKviIYrCmcYV8s+eW107uvj9QBd0J9JXJa5xdSUySdEl5dffIat5k5lJcmUh1X6/dgSfVR5mEiWqajQFXtk0vMMEFWIWhas=
on:
repo: olin/SoftSysCollascii
repo: olin/collascii
tags: true # build on tagged releases only
branch: master
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# COLLASCII

[![Build Status](https://travis-ci.com/olin/SoftSysCollascii.svg?branch=master)](https://travis-ci.com/olin/SoftSysCollascii)
[![Build Status](https://travis-ci.com/olin/collascii.svg?branch=master)](https://travis-ci.com/olin/collascii)

_A collaborative ascii canvas_

Expand Down
6 changes: 4 additions & 2 deletions src/canvas.c
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,7 @@ inline Canvas *canvas_trim(Canvas *orig, int right, int bottom, int left,
* Top left of canvas is (0, 0).
*/
void canvas_scharyx(Canvas *canvas, int y, int x, char c) {
assert(canvas_isin_yx(canvas, y, x));
canvas->rows[y][x] = c;
}

Expand All @@ -369,6 +370,7 @@ void canvas_scharyx(Canvas *canvas, int y, int x, char c) {
* Index starts at 0 at position (0, 0) and increments first horizontally.
*/
void canvas_schari(Canvas *canvas, int i, char c) {
assert(canvas_isin_i(canvas, i));
int row = i / canvas->num_cols;
int col = i % canvas->num_cols;
canvas->rows[row][col] = c;
Expand All @@ -378,15 +380,15 @@ void canvas_schari(Canvas *canvas, int i, char c) {
*
*/
char canvas_gcharyx(Canvas *canvas, int y, int x) {
assert(x <= canvas->num_cols);
assert(y <= canvas->num_rows);
assert(canvas_isin_yx(canvas, y, x));
return canvas->rows[y][x];
}

/* Get the character at index i
*
*/
char canvas_gchari(Canvas *canvas, int i) {
assert(canvas_isin_i(canvas, i));
int row = i / canvas->num_cols;
int col = i % canvas->num_cols;
return canvas->rows[row][col];
Expand Down
51 changes: 29 additions & 22 deletions src/fe_modes.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
#include "mode_id.h"
#include "util.h"

// #define LOG_KEY_EVENTS // `logd` new mouse and key events

editor_mode_t modes[] = {
{"Switcher", "Switch to another mode", mode_picker},
{"Insert", "Insert characters", mode_insert},
Expand Down Expand Up @@ -126,10 +128,23 @@ void switch_mode(Mode_ID new_mode, State *state) {
int master_handler(State *state, WINDOW *canvas_win, WINDOW *status_win) {
// catching keypresses
int c = wgetch(canvas_win); // grab from window
#ifdef LOG_KEYS
#ifdef LOG_KEY_EVENTS
logd("New key: '%c' (%d)\n", c, c);
#endif
if (c == KEY_TAB) { // switching modes
if (c == KEY_MOUSE) {
// handle mouse events
MEVENT event;
if (getmouse(&event) == OK) {
#ifdef LOG_KEY_EVENTS
logd("New mouse event: (%i, %i), %li\n", event.x, event.y, event.bstate);
#endif
// TODO: look into mouse_trafo, wmouse_trafo
// https://invisible-island.net/ncurses/man/curs_mouse.3x.html
state->ch_in = c;
state->mevent_in = &event;
call_mode(state->current_mode, NEW_MOUSE, state);
}
} else if (c == KEY_TAB) { // switching modes
if (state->current_mode == MODE_PICKER &&
state->last_canvas_mode != MODE_PICKER) {
logd("Reverting to last mode\n");
Expand Down Expand Up @@ -404,7 +419,18 @@ int mode_brush(reason_t reason, State *state) {
mode_cfg->state = PAINT_OFF;
}

if (reason == NEW_KEY) {
if (reason == NEW_MOUSE) {
if (state->mevent_in->bstate & BUTTON1_PRESSED) {
mode_cfg->state = PAINT_ON;
} else if (state->mevent_in->bstate & BUTTON1_RELEASED) {
mode_cfg->state = PAINT_OFF;
}
// only update cursor position on mouse move if we're painting
if (mode_cfg->state == PAINT_ON) {
state->cursor->x = state->mevent_in->x - 1;
state->cursor->y = state->mevent_in->y - 1;
}
} else if (reason == NEW_KEY) {
if ((state->ch_in == KEY_LEFT) || (state->ch_in == KEY_RIGHT) ||
(state->ch_in == KEY_UP) || (state->ch_in == KEY_DOWN)) {
// arrow keys - move cursor
Expand All @@ -419,25 +445,6 @@ int mode_brush(reason_t reason, State *state) {
} else if (mode_cfg->state == PAINT_OFF) {
mode_cfg->state = PAINT_ON;
}
} else if (KEY_MOUSE == state->ch_in) {
// handle mouse events
MEVENT event;
if (getmouse(&event) == OK) {
#ifdef LOG_KEYS
logd("New mouse event: (%i, %i), %li\n", event.x, event.y,
(long int)event.bstate);
#endif
if (event.bstate & BUTTON1_PRESSED) {
mode_cfg->state = PAINT_ON;
} else if (event.bstate & BUTTON1_RELEASED) {
mode_cfg->state = PAINT_OFF;
}
// only update cursor position on mouse move if we're painting
if (mode_cfg->state == PAINT_ON) {
state->cursor->x = event.x - 1;
state->cursor->y = event.y - 1;
}
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/fe_modes.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

int mode_master(State *state, WINDOW *canvas_win, WINDOW *status_win);

typedef enum { START, NEW_KEY, END } reason_t;
typedef enum { START, NEW_KEY, NEW_MOUSE, END } reason_t;

// Prototype for mode functions. Note that this is NOT a function pointer type
// (use `mode_function_t*` for that). https://stackoverflow.com/a/5195682
Expand Down
83 changes: 61 additions & 22 deletions src/frontend.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* | (_| (_) | |__| |__ / _ \\__ \ (__ | | | |
* \___\___/|____|____/_/ \_\___/\___|___|___|
*
* Yesterdays future, tomorrow!
* Yesterday's future, tomorrow!
*
* A collaborative ASCII editor, in your terminal.
*
Expand Down Expand Up @@ -52,6 +52,17 @@ bool networked = false;

char *DEFAULT_FILEPATH = "art.txt";

// signals to be caught with finish() function
int caught_signals[] = {SIGINT, SIGTERM, SIGKILL, SIGABRT,
SIGSEGV, SIGQUIT, SIGSTOP};

// #define LOG_TO_FILE // redirect stderr to "out.txt"

// mouse movements options (only use one)
// #define ENABLE_MOUSE_MOVEMENT 1003 // all move updates
#define ENABLE_MOUSE_MOVEMENT 1002 // move updates when buttons are pressed
// #define ENABLE_MOUSE_MOVEMENT 0 // don't send any charcodes

#ifdef DEBUG
#define LOG_TO_FILE
#endif
Expand All @@ -62,6 +73,11 @@ FILE *logfile = NULL;
#endif

int main(int argc, char *argv[]) {
// setup finish() signal handler
for (int i = 0; i < sizeof(caught_signals) / sizeof(int); i++) {
signal(caught_signals[i], finish);
}

#ifdef LOG_TO_FILE
logfile = fopen(logfile_path, "a");
if (logfile == NULL) {
Expand Down Expand Up @@ -131,8 +147,6 @@ int main(int argc, char *argv[]) {

/* initialize your non-curses data structures here */

(void)signal(SIGINT, finish); /* arrange interrupts to terminate */

(void)initscr(); /* initialize the curses library */
keypad(stdscr, TRUE); /* enable keyboard mapping */
(void)nonl(); /* tell curses not to do NL->CR/NL on output */
Expand All @@ -148,16 +162,15 @@ int main(int argc, char *argv[]) {

// ENABLE MOUSE INPUT
// grab only mouse movement and left mouse press/release
#ifndef LOG_KEYS
mousemask(REPORT_MOUSE_POSITION | BUTTON1_PRESSED | BUTTON1_RELEASED, NULL);
#endif
#ifdef LOG_KEYS
mmask_t return_mask = mousemask(
REPORT_MOUSE_POSITION | BUTTON1_PRESSED | BUTTON1_RELEASED, NULL);
logd("Returned mouse mask: %li\n", (long int)return_mask);
mmask_t mmask = BUTTON1_PRESSED | BUTTON1_RELEASED;
#ifdef ENABLE_MOUSE_MOVEMENT
mmask |= REPORT_MOUSE_POSITION;
#endif
mmask_t return_mask = mousemask(mmask, NULL);
logd("Returned mouse mask: %li\n", return_mask);
// get mouse updates faster at the expense of not registering "clicks"
mouseinterval(0);
#ifdef ENABLE_MOUSE_MOVEMENT
// Make the terminal report mouse movement events, in a not-great way.
// Printing the escape code should bump it into `1003` mode, where an update
// is sent whenever the mouse moves between cells. Also of note: `1002` only
Expand All @@ -170,9 +183,13 @@ int main(int argc, char *argv[]) {
// https://stackoverflow.com/q/29020638
// https://stackoverflow.com/q/7462850
//
// Disable mouse events is called in finish(), remove it if you change this.
printf("\033[?1003h\n"); // enable events
// printf("\033[?1003l\n"); // disable events
// disabling mouse event charcodes is done in finish()
if (ENABLE_MOUSE_MOVEMENT == 1002) {
printf("\033[?1002h\n");
} else if (ENABLE_MOUSE_MOVEMENT == 1003) {
printf("\033[?1003h\n");
}
#endif

canvas_win = create_canvas_win();
status_interface = create_status_interface();
Expand Down Expand Up @@ -260,8 +277,7 @@ int main(int argc, char *argv[]) {
}
// Cleanup
cursor_free(cursor);
// TODO: destory status_interface
destroy_win(status_interface->status_win);
destroy_status_interface(status_interface);
destroy_win(canvas_win);
finish(0);
}
Expand Down Expand Up @@ -314,12 +330,12 @@ void redraw_canvas_win() {
// draw fill in rest of window
for (int x = max_x; x < view_max_x; x++) {
for (int y = 0; y < view_max_y; y++) {
mvwaddch(canvas_win, y + 1, x + 1, 'X');
mvwaddch(canvas_win, y + 1, x + 1, ACS_CKBOARD);
}
}
for (int y = max_y; y < view_max_y; y++) {
for (int x = 0; x < view_max_x; x++) {
mvwaddch(canvas_win, y + 1, x + 1, 'X');
for (int x = 0; x < max_x; x++) {
mvwaddch(canvas_win, y + 1, x + 1, ACS_CKBOARD);
}
}
}
Expand Down Expand Up @@ -518,17 +534,40 @@ void update_info_win(Mode_ID current_mode, int x, int y) {
waddnstr(mw, buffer, INFO_WIDTH);
}

/* Signal handler for exiting
*
* Turns of ncurses, disables mouse moves commands, closes the logfile.
*
* If sig is 0 or SIGINT, exits normally, otherwise prints the signal
* information to stderr and exits with sig.
*/
void finish(int sig) {
endwin();

// Disable mouse events
printf("\033[?1003l\n");
// Disable mouse events charcode
#ifdef ENABLE_MOUSE_MOVEMENT
if (ENABLE_MOUSE_MOVEMENT == 1002) {
printf("\033[?1002l\n");
} else if (ENABLE_MOUSE_MOVEMENT == 1003) {
printf("\033[?1003l\n");
}
#endif

/* do your non-curses wrapup here */
#ifdef LOG_TO_FILE
if (logfile != NULL) {
fclose(logfile);
}
#endif
exit(0);
// decide how to exit based on signal
switch (sig) {
case 0: // normal
case SIGINT: // user CTRL-C
eprintf("Exiting\n");
exit(0);
break;
default: // problems
eprintf("Exited with signal %d (%s)\n", sig, strsignal(sig));
exit(sig);
break;
}
}
12 changes: 6 additions & 6 deletions src/state.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@
* Make sure its length is capped.
*/
typedef struct {
int ch_in;
Cursor *cursor;
Mode_ID current_mode;

Mode_ID last_canvas_mode;
int ch_in; // characters read by ncurses
MEVENT *mevent_in; // mouse events read by ncurses
Cursor *cursor; // cursor location on screen, relative to window
View *view; // view of the canvas (also holds the canvas)
Mode_ID current_mode; // the current mode of the interface
Mode_ID last_canvas_mode; // the last mode of the interface
int last_arrow_direction;
View *view;
Cursor *last_cursor;
char *filepath; // path of savefile
} State;
Expand Down