git.y1.nz

lwl

Less with links.
download: http://git.y1.nz/archives/lwl.tar.gz
README | Files | Log | Refs

main.c

      1 #include <stdio.h> /* printf, stdin/out/err, etc */
      2 #include <termios.h> /* termios struct, tsetattr */
      3 #include <stdlib.h> /* exit, popen */
      4 #include <unistd.h> /* exec */
      5 #include <sys/wait.h> /* waitpid */
      6 
      7 #include "config.h"
      8 #include "term.h"
      9 #include "text.h"
     10 #include "draw.h"
     11 #include "state.h"
     12 
     13 /* helper macros, for specifying keybindings in config.h */
     14 #define START_MODE(m)  if (state->mode == m) { \
     15 	switch (ch) {
     16 #define END_MODE  \
     17 	} \
     18 	return 0; \
     19 }
     20 #define ESCAPE  return 1
     21 #define SCROLL_TO(index)  scroll_to(state, wrap, (index))
     22 #define SCROLL_BY(step)  scroll_to(state, wrap, state->line_offset + (step))
     23 #define STEP_BY(step)  next_markup(state, wrap, (step))
     24 #define SET_MODE(new_mode)  set_mode(state, (new_mode))
     25 #define FORK_COMMAND(command)  fork_command(state, (command))
     26 #define EXEC_COMMAND(command)  exec_command(state, (command))
     27 #define TYPE_CHAR  type_input_char(state, wrap, ch)
     28 #define TYPE_BACKSPACE  type_input_backspace(state)
     29 #define DO_SEARCH  do_search(contents, state, wrap)
     30 #define WRAP_END  wrap->line_count
     31 #define WRAP_H  wrap->height
     32 #define ACTION(trigger, action)  case trigger: action; break;
     33 #define DEFAULT_ACTION(action)  default: action; break;
     34 
     35 /* GLOBAL VARS (sowwy,, ill cwean dis up l8r >w<) */
     36 struct termios termios0;
     37 FileContents *contents;
     38 Wrap *wrap;
     39 State *state;
     40 
     41 void
     42 set_termios_raw(FILE *fd)
     43 {
     44 	struct termios termios1;
     45 	tcgetattr(fileno(fd), &termios0);
     46 	tcgetattr(fileno(fd), &termios1);
     47 	cfmakeraw(&termios1);
     48 	tcsetattr(fileno(fd), TCSANOW, &termios1);
     49 }
     50 
     51 void
     52 reset_termios(FILE *fd)
     53 {
     54 	tcsetattr(fileno(stdin), TCSANOW, &termios0);
     55 }
     56 
     57 // TODO catch SIGWINCH and trigger this
     58 void
     59 change_width(int nw, int nh)
     60 {
     61 	int w = wrap->width, h = wrap->height;
     62 	free(wrap);
     63 	wrap = wrap_to(contents, nw, nh);
     64 }
     65 
     66 // TODO move these to proc (?) module
     67 void
     68 exec_command(State *state, char *command)
     69 {
     70 	char *link = state->markups[state->markup_index]->data;
     71 	setenv("INPUT", state->input, 1);
     72 	setenv("LINK", link, 1);
     73 	// TODO how can this be made safer...
     74 
     75 	reset_termios(stdin);
     76 	printf("\n");
     77 
     78 	execlp("/bin/sh", "/bin/sh", "-c", command, NULL);
     79 }
     80 
     81 void
     82 fork_command(State *state, char *command)
     83 {
     84 	/* fork and execute in child */
     85 	pid_t pid = fork();
     86 	if (!pid) exec_command(state, command);
     87 
     88 	/* parent: wait for child, then wait for keypress */
     89 	waitpid(pid, NULL, 0);
     90 	printf("\033[0;1m" "[process terminated]" "\033[0m");
     91 	set_termios_raw(stdin);
     92 	fflush(stdout);
     93 	fgetc(stdin);
     94 	state->mode = MODE_GROUND;
     95 }
     96 
     97 int
     98 handle_input(char ch)
     99 {
    100 	ACTIONS;
    101 	return 0;
    102 }
    103 
    104 int
    105 main(int argc, const char *argv[])
    106 {
    107 	FILE *fin;
    108 	int result;
    109 	int screen_width, screen_height;
    110 
    111 	state = init_state();
    112 
    113 	// TODO use getopt prolly
    114 	if (argc != 2) {
    115 		printf("Usage: %s FILENAME" "\n", argv[0]);
    116 		exit(1);
    117 	}
    118 
    119 	result = get_root_size(stdin, stdout, &screen_width, &screen_height);
    120 	if (screen_width > 80) screen_width = 80;
    121 	screen_height--; /* accounts for status line */
    122 	if (!result) {
    123 		printf("Failed to measure terminal :(" "\n");
    124 		exit(1);
    125 	}
    126 
    127 	fin = fopen(argv[1], "r");
    128 	if (fin == NULL) {
    129 		printf("Failed to open \"%s\"." "\n", argv[1]);
    130 		exit(1);
    131 	}
    132 	state->message = state->filename = argv[1];
    133 	contents = read_contents(fin);
    134 	wrap = wrap_to(contents, screen_width, screen_height);
    135 	fclose(fin);
    136 
    137 	set_markups(state, contents->links, contents->link_count);
    138 	set_termios_raw(stdin);
    139 
    140 	redraw(contents, wrap, state);
    141 
    142 	char ch;
    143 	for (;;) {
    144 		redraw(contents, wrap, state);
    145 
    146 		ch = fgetc(stdin);
    147 		/* clear message on input. */
    148 		state->message = NULL;
    149 
    150 		result = handle_input(ch);
    151 		if (result > 0) break;
    152 	}
    153 
    154 	reset_termios(stdin);
    155 
    156 	/* clear the line and move cursor to left */
    157 	printf("\033[2K" "\033[9999D");
    158 }

This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.