diff --git a/src/terminal/itrm.h b/src/terminal/itrm.h index 33b00ec4..ef0df42a 100644 --- a/src/terminal/itrm.h +++ b/src/terminal/itrm.h @@ -7,22 +7,78 @@ struct itrm_queue { unsigned char *data; + + /* The amount of data in the queue, in bytes. This may be + * less than the amount of memory allocated for the buffer; + * struct itrm_queue does not keep track of that, and has + * no global policy on whether the buffer can be resized. */ int len; }; +/* Things coming into an itrm, whether from the terminal or from the + * master. */ struct itrm_in { + /* A file descriptor for the standard input. In some ports, + * this is the terminal device itself; in others, this is a + * pipe from an input thread. In principle, the data format + * depends on the terminal. */ int std; + + /* In a slave process, a file descriptor for a socket from + * which it reads data sent by the master process. The other + * end of the socket connection is terminal.fdout in the + * master process. The format of this data is almost the same + * as could be sent to the terminal (via itrm.out.std), but + * there are special commands that begin with a null byte. + * + * In the master process, @sock is the same as @ctl, but + * nothing actually uses it. */ int sock; + + /* A file descriptor for controlling the standard input. This + * is always the terminal device itself, thus the same as @std + * in some ports. ELinks doesn't read or write with this file + * descriptor; it only does things like tcsetattr. */ int ctl; + + /* Bytes that have been received from @std but not yet + * converted to events. queue.data is allocated for + * ITRM_IN_QUEUE_SIZE bytes and never resized. The itrm + * layer cannot parse control sequences longer than that. */ struct itrm_queue queue; }; +/* Things going out from an itrm, whether to the terminal or to the + * master. */ struct itrm_out { + /* A file descriptor for the standard output. In some ports, + * this is the terminal device itself; in others, this is a + * pipe to an output thread. In principle, the data format + * depends on the terminal; but see bug 96. */ int std; + + /* A file descriptor for a pipe or socket to which this + * process sends input events. The other end of the pipe or + * socket connection is terminal.fdin in the master process. + * If the connection is from the master process to itself, it + * uses a pipe; otherwise a socket. The events are formatted + * as struct term_event, but at the beginning of the + * connection, a struct terminal_info and extra data is also + * sent. */ int sock; + + /* Bytes that should be written to @sock. They will be + * written when select() indicates the write won't block. To + * add data here, call itrm_queue_event(), which reallocates + * queue.data if appropriate. The size of this queue is + * unrelated to ITRM_OUT_QUEUE_SIZE. */ struct itrm_queue queue; }; +/* A connection between a terminal and a master ELinks process. + * Normally, only one struct itrm exists in each master or slave + * process, and the global pointer @ditrm (not declared here) + * points to it. */ struct itrm { struct itrm_in in; /* Input */ struct itrm_out out; /* Output */ diff --git a/src/terminal/kbd.c b/src/terminal/kbd.c index c084d0fd..e39896c1 100644 --- a/src/terminal/kbd.c +++ b/src/terminal/kbd.c @@ -62,6 +62,10 @@ free_all_itrms(void) } +/* A select_handler_T write_func for itrm->out.sock. This is called + * when there is data in itrm->out.queue and it is possible to write + * it to itrm->out.sock. When itrm->out.queue becomes empty, this + * handler is temporarily removed. */ static void itrm_queue_write(struct itrm *itrm) { @@ -230,6 +234,31 @@ setraw(int fd, struct termios *p) return 0; } +/* Construct the struct itrm of this process, make ditrm point to it, + * set up select() handlers, and send the initial interlink packet. + * + * The first five parameters are file descriptors that this function + * saves in submembers of struct itrm, and for which this function may + * set select() handlers. Please see the definitions of struct + * itrm_in and struct itrm_out for further explanations. + * + * param member file if process is master file if process is slave + * ------ ------ ------------------------- ------------------------ + * std_in in.std read tty device (or pipe) read tty device (or pipe) + * std_out out.std write tty device (or pipe) write tty device (or pipe) + * sock_in in.sock ==std_out (masterhood flag) read socket from master + * sock_out out.sock write pipe to same process write socket to master + * ctl_in in.ctl control tty device control tty device + * + * The remaining three parameters control the initial interlink packet. + * + * init_string = A string to be passed to the master process. Need + * not be null-terminated. If remote==0, this is a URI. + * Otherwise, this is a remote command. + * init_len = The length of init_string, in bytes. + * remote = 0 if asking the master to start a new session + * and display it via this process. Otherwise, + * enum remote_session_flags. */ void handle_trm(int std_in, int std_out, int sock_in, int sock_out, int ctl_in, void *init_string, int init_len, int remote) @@ -305,6 +334,9 @@ handle_trm(int std_in, int std_out, int sock_in, int sock_out, int ctl_in, } +/* A select_handler_T read_func and error_func for the pipe (long) h. + * This is called when the subprocess started on the terminal of this + * ELinks process exits. ELinks then resumes using the terminal. */ static void unblock_itrm_x(void *h) { @@ -459,6 +491,9 @@ safe_hard_write(int fd, unsigned char *buf, int len) done_draw(); } +/* A select_handler_T read_func for itrm->in.sock. A slave process + * calls this when the master sends it data to be displayed. The + * master process never calls this. */ static void in_sock(struct itrm *itrm) { @@ -893,6 +928,8 @@ ret: } +/* A select_handler_T read_func for itrm->in.std. This is called when + * characters typed by the user arrive from the terminal. */ static void in_kbd(struct itrm *itrm) {