12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979 |
- /* $OpenBSD$ */
- /*
- * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
- * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
- * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
- #include <sys/types.h>
- #include <stdlib.h>
- #include <string.h>
- #include <time.h>
- #include "tmux.h"
- /*
- * Based on the description by Paul Williams at:
- *
- * http://vt100.net/emu/dec_ansi_parser
- *
- * With the following changes:
- *
- * - 7-bit only.
- *
- * - Support for UTF-8.
- *
- * - OSC (but not APC) may be terminated by \007 as well as ST.
- *
- * - A state for APC similar to OSC. Some terminals appear to use this to set
- * the title.
- *
- * - A state for the screen \033k...\033\\ sequence to rename a window. This is
- * pretty stupid but not supporting it is more trouble than it is worth.
- *
- * - Special handling for ESC inside a DCS to allow arbitrary byte sequences to
- * be passed to the underlying terminals.
- */
- /* Input parser cell. */
- struct input_cell {
- struct grid_cell cell;
- int set;
- int g0set; /* 1 if ACS */
- int g1set; /* 1 if ACS */
- };
- /* Input parser context. */
- struct input_ctx {
- struct window_pane *wp;
- struct screen_write_ctx ctx;
- struct input_cell cell;
- struct input_cell old_cell;
- u_int old_cx;
- u_int old_cy;
- u_char interm_buf[4];
- size_t interm_len;
- u_char param_buf[64];
- size_t param_len;
- #define INPUT_BUF_START 32
- #define INPUT_BUF_LIMIT 1048576
- u_char *input_buf;
- size_t input_len;
- size_t input_space;
- int param_list[24]; /* -1 not present */
- u_int param_list_len;
- struct utf8_data utf8data;
- int ch;
- int flags;
- #define INPUT_DISCARD 0x1
- const struct input_state *state;
- /*
- * All input received since we were last in the ground state. Sent to
- * control clients on connection.
- */
- struct evbuffer *since_ground;
- };
- /* Helper functions. */
- struct input_transition;
- int input_split(struct input_ctx *);
- int input_get(struct input_ctx *, u_int, int, int);
- void printflike(2, 3) input_reply(struct input_ctx *, const char *, ...);
- void input_set_state(struct window_pane *, const struct input_transition *);
- void input_reset_cell(struct input_ctx *);
- /* Transition entry/exit handlers. */
- void input_clear(struct input_ctx *);
- void input_ground(struct input_ctx *);
- void input_enter_osc(struct input_ctx *);
- void input_exit_osc(struct input_ctx *);
- void input_enter_apc(struct input_ctx *);
- void input_exit_apc(struct input_ctx *);
- void input_enter_rename(struct input_ctx *);
- void input_exit_rename(struct input_ctx *);
- /* Input state handlers. */
- int input_print(struct input_ctx *);
- int input_intermediate(struct input_ctx *);
- int input_parameter(struct input_ctx *);
- int input_input(struct input_ctx *);
- int input_c0_dispatch(struct input_ctx *);
- int input_esc_dispatch(struct input_ctx *);
- int input_csi_dispatch(struct input_ctx *);
- void input_csi_dispatch_rm(struct input_ctx *);
- void input_csi_dispatch_rm_private(struct input_ctx *);
- void input_csi_dispatch_sm(struct input_ctx *);
- void input_csi_dispatch_sm_private(struct input_ctx *);
- void input_csi_dispatch_winops(struct input_ctx *);
- void input_csi_dispatch_sgr_256(struct input_ctx *, int, u_int *);
- void input_csi_dispatch_sgr_rgb(struct input_ctx *, int, u_int *);
- void input_csi_dispatch_sgr(struct input_ctx *);
- int input_dcs_dispatch(struct input_ctx *);
- int input_utf8_open(struct input_ctx *);
- int input_utf8_add(struct input_ctx *);
- int input_utf8_close(struct input_ctx *);
- /* Command table comparison function. */
- int input_table_compare(const void *, const void *);
- /* Command table entry. */
- struct input_table_entry {
- int ch;
- const char *interm;
- int type;
- };
- /* Escape commands. */
- enum input_esc_type {
- INPUT_ESC_DECALN,
- INPUT_ESC_DECKPAM,
- INPUT_ESC_DECKPNM,
- INPUT_ESC_DECRC,
- INPUT_ESC_DECSC,
- INPUT_ESC_HTS,
- INPUT_ESC_IND,
- INPUT_ESC_NEL,
- INPUT_ESC_RI,
- INPUT_ESC_RIS,
- INPUT_ESC_SCSG0_OFF,
- INPUT_ESC_SCSG0_ON,
- INPUT_ESC_SCSG1_OFF,
- INPUT_ESC_SCSG1_ON,
- };
- /* Escape command table. */
- const struct input_table_entry input_esc_table[] = {
- { '0', "(", INPUT_ESC_SCSG0_ON },
- { '0', ")", INPUT_ESC_SCSG1_ON },
- { '7', "", INPUT_ESC_DECSC },
- { '8', "", INPUT_ESC_DECRC },
- { '8', "#", INPUT_ESC_DECALN },
- { '=', "", INPUT_ESC_DECKPAM },
- { '>', "", INPUT_ESC_DECKPNM },
- { 'B', "(", INPUT_ESC_SCSG0_OFF },
- { 'B', ")", INPUT_ESC_SCSG1_OFF },
- { 'D', "", INPUT_ESC_IND },
- { 'E', "", INPUT_ESC_NEL },
- { 'H', "", INPUT_ESC_HTS },
- { 'M', "", INPUT_ESC_RI },
- { 'c', "", INPUT_ESC_RIS },
- };
- /* Control (CSI) commands. */
- enum input_csi_type {
- INPUT_CSI_CBT,
- INPUT_CSI_CNL,
- INPUT_CSI_CPL,
- INPUT_CSI_CUB,
- INPUT_CSI_CUD,
- INPUT_CSI_CUF,
- INPUT_CSI_CUP,
- INPUT_CSI_CUU,
- INPUT_CSI_DA,
- INPUT_CSI_DA_TWO,
- INPUT_CSI_DCH,
- INPUT_CSI_DECSCUSR,
- INPUT_CSI_DECSTBM,
- INPUT_CSI_DL,
- INPUT_CSI_DSR,
- INPUT_CSI_ECH,
- INPUT_CSI_ED,
- INPUT_CSI_EL,
- INPUT_CSI_HPA,
- INPUT_CSI_ICH,
- INPUT_CSI_IL,
- INPUT_CSI_RCP,
- INPUT_CSI_RM,
- INPUT_CSI_RM_PRIVATE,
- INPUT_CSI_SCP,
- INPUT_CSI_SGR,
- INPUT_CSI_SM,
- INPUT_CSI_SM_PRIVATE,
- INPUT_CSI_TBC,
- INPUT_CSI_VPA,
- INPUT_CSI_WINOPS,
- };
- /* Control (CSI) command table. */
- const struct input_table_entry input_csi_table[] = {
- { '@', "", INPUT_CSI_ICH },
- { 'A', "", INPUT_CSI_CUU },
- { 'B', "", INPUT_CSI_CUD },
- { 'C', "", INPUT_CSI_CUF },
- { 'D', "", INPUT_CSI_CUB },
- { 'E', "", INPUT_CSI_CNL },
- { 'F', "", INPUT_CSI_CPL },
- { 'G', "", INPUT_CSI_HPA },
- { 'H', "", INPUT_CSI_CUP },
- { 'J', "", INPUT_CSI_ED },
- { 'K', "", INPUT_CSI_EL },
- { 'L', "", INPUT_CSI_IL },
- { 'M', "", INPUT_CSI_DL },
- { 'P', "", INPUT_CSI_DCH },
- { 'X', "", INPUT_CSI_ECH },
- { 'Z', "", INPUT_CSI_CBT },
- { 'c', "", INPUT_CSI_DA },
- { 'c', ">", INPUT_CSI_DA_TWO },
- { 'd', "", INPUT_CSI_VPA },
- { 'f', "", INPUT_CSI_CUP },
- { 'g', "", INPUT_CSI_TBC },
- { 'h', "", INPUT_CSI_SM },
- { 'h', "?", INPUT_CSI_SM_PRIVATE },
- { 'l', "", INPUT_CSI_RM },
- { 'l', "?", INPUT_CSI_RM_PRIVATE },
- { 'm', "", INPUT_CSI_SGR },
- { 'n', "", INPUT_CSI_DSR },
- { 'q', " ", INPUT_CSI_DECSCUSR },
- { 'r', "", INPUT_CSI_DECSTBM },
- { 's', "", INPUT_CSI_SCP },
- { 't', "", INPUT_CSI_WINOPS },
- { 'u', "", INPUT_CSI_RCP },
- };
- /* Input transition. */
- struct input_transition {
- int first;
- int last;
- int (*handler)(struct input_ctx *);
- const struct input_state *state;
- };
- /* Input state. */
- struct input_state {
- const char *name;
- void (*enter)(struct input_ctx *);
- void (*exit)(struct input_ctx *);
- const struct input_transition *transitions;
- };
- /* State transitions available from all states. */
- #define INPUT_STATE_ANYWHERE \
- { 0x18, 0x18, input_c0_dispatch, &input_state_ground }, \
- { 0x1a, 0x1a, input_c0_dispatch, &input_state_ground }, \
- { 0x1b, 0x1b, NULL, &input_state_esc_enter }
- /* Forward declarations of state tables. */
- const struct input_transition input_state_ground_table[];
- const struct input_transition input_state_esc_enter_table[];
- const struct input_transition input_state_esc_intermediate_table[];
- const struct input_transition input_state_csi_enter_table[];
- const struct input_transition input_state_csi_parameter_table[];
- const struct input_transition input_state_csi_intermediate_table[];
- const struct input_transition input_state_csi_ignore_table[];
- const struct input_transition input_state_dcs_enter_table[];
- const struct input_transition input_state_dcs_parameter_table[];
- const struct input_transition input_state_dcs_intermediate_table[];
- const struct input_transition input_state_dcs_handler_table[];
- const struct input_transition input_state_dcs_escape_table[];
- const struct input_transition input_state_dcs_ignore_table[];
- const struct input_transition input_state_osc_string_table[];
- const struct input_transition input_state_apc_string_table[];
- const struct input_transition input_state_rename_string_table[];
- const struct input_transition input_state_consume_st_table[];
- const struct input_transition input_state_utf8_three_table[];
- const struct input_transition input_state_utf8_two_table[];
- const struct input_transition input_state_utf8_one_table[];
- /* ground state definition. */
- const struct input_state input_state_ground = {
- "ground",
- input_ground, NULL,
- input_state_ground_table
- };
- /* esc_enter state definition. */
- const struct input_state input_state_esc_enter = {
- "esc_enter",
- input_clear, NULL,
- input_state_esc_enter_table
- };
- /* esc_intermediate state definition. */
- const struct input_state input_state_esc_intermediate = {
- "esc_intermediate",
- NULL, NULL,
- input_state_esc_intermediate_table
- };
- /* csi_enter state definition. */
- const struct input_state input_state_csi_enter = {
- "csi_enter",
- input_clear, NULL,
- input_state_csi_enter_table
- };
- /* csi_parameter state definition. */
- const struct input_state input_state_csi_parameter = {
- "csi_parameter",
- NULL, NULL,
- input_state_csi_parameter_table
- };
- /* csi_intermediate state definition. */
- const struct input_state input_state_csi_intermediate = {
- "csi_intermediate",
- NULL, NULL,
- input_state_csi_intermediate_table
- };
- /* csi_ignore state definition. */
- const struct input_state input_state_csi_ignore = {
- "csi_ignore",
- NULL, NULL,
- input_state_csi_ignore_table
- };
- /* dcs_enter state definition. */
- const struct input_state input_state_dcs_enter = {
- "dcs_enter",
- input_clear, NULL,
- input_state_dcs_enter_table
- };
- /* dcs_parameter state definition. */
- const struct input_state input_state_dcs_parameter = {
- "dcs_parameter",
- NULL, NULL,
- input_state_dcs_parameter_table
- };
- /* dcs_intermediate state definition. */
- const struct input_state input_state_dcs_intermediate = {
- "dcs_intermediate",
- NULL, NULL,
- input_state_dcs_intermediate_table
- };
- /* dcs_handler state definition. */
- const struct input_state input_state_dcs_handler = {
- "dcs_handler",
- NULL, NULL,
- input_state_dcs_handler_table
- };
- /* dcs_escape state definition. */
- const struct input_state input_state_dcs_escape = {
- "dcs_escape",
- NULL, NULL,
- input_state_dcs_escape_table
- };
- /* dcs_ignore state definition. */
- const struct input_state input_state_dcs_ignore = {
- "dcs_ignore",
- NULL, NULL,
- input_state_dcs_ignore_table
- };
- /* osc_string state definition. */
- const struct input_state input_state_osc_string = {
- "osc_string",
- input_enter_osc, input_exit_osc,
- input_state_osc_string_table
- };
- /* apc_string state definition. */
- const struct input_state input_state_apc_string = {
- "apc_string",
- input_enter_apc, input_exit_apc,
- input_state_apc_string_table
- };
- /* rename_string state definition. */
- const struct input_state input_state_rename_string = {
- "rename_string",
- input_enter_rename, input_exit_rename,
- input_state_rename_string_table
- };
- /* consume_st state definition. */
- const struct input_state input_state_consume_st = {
- "consume_st",
- NULL, NULL,
- input_state_consume_st_table
- };
- /* utf8_three state definition. */
- const struct input_state input_state_utf8_three = {
- "utf8_three",
- NULL, NULL,
- input_state_utf8_three_table
- };
- /* utf8_two state definition. */
- const struct input_state input_state_utf8_two = {
- "utf8_two",
- NULL, NULL,
- input_state_utf8_two_table
- };
- /* utf8_one state definition. */
- const struct input_state input_state_utf8_one = {
- "utf8_one",
- NULL, NULL,
- input_state_utf8_one_table
- };
- /* ground state table. */
- const struct input_transition input_state_ground_table[] = {
- INPUT_STATE_ANYWHERE,
- { 0x00, 0x17, input_c0_dispatch, NULL },
- { 0x19, 0x19, input_c0_dispatch, NULL },
- { 0x1c, 0x1f, input_c0_dispatch, NULL },
- { 0x20, 0x7e, input_print, NULL },
- { 0x7f, 0x7f, NULL, NULL },
- { 0x80, 0xc1, NULL, NULL },
- { 0xc2, 0xdf, input_utf8_open, &input_state_utf8_one },
- { 0xe0, 0xef, input_utf8_open, &input_state_utf8_two },
- { 0xf0, 0xf4, input_utf8_open, &input_state_utf8_three },
- { 0xf5, 0xff, NULL, NULL },
- { -1, -1, NULL, NULL }
- };
- /* esc_enter state table. */
- const struct input_transition input_state_esc_enter_table[] = {
- INPUT_STATE_ANYWHERE,
- { 0x00, 0x17, input_c0_dispatch, NULL },
- { 0x19, 0x19, input_c0_dispatch, NULL },
- { 0x1c, 0x1f, input_c0_dispatch, NULL },
- { 0x20, 0x2f, input_intermediate, &input_state_esc_intermediate },
- { 0x30, 0x4f, input_esc_dispatch, &input_state_ground },
- { 0x50, 0x50, NULL, &input_state_dcs_enter },
- { 0x51, 0x57, input_esc_dispatch, &input_state_ground },
- { 0x58, 0x58, NULL, &input_state_consume_st },
- { 0x59, 0x59, input_esc_dispatch, &input_state_ground },
- { 0x5a, 0x5a, input_esc_dispatch, &input_state_ground },
- { 0x5b, 0x5b, NULL, &input_state_csi_enter },
- { 0x5c, 0x5c, input_esc_dispatch, &input_state_ground },
- { 0x5d, 0x5d, NULL, &input_state_osc_string },
- { 0x5e, 0x5e, NULL, &input_state_consume_st },
- { 0x5f, 0x5f, NULL, &input_state_apc_string },
- { 0x60, 0x6a, input_esc_dispatch, &input_state_ground },
- { 0x6b, 0x6b, NULL, &input_state_rename_string },
- { 0x6c, 0x7e, input_esc_dispatch, &input_state_ground },
- { 0x7f, 0xff, NULL, NULL },
- { -1, -1, NULL, NULL }
- };
- /* esc_interm state table. */
- const struct input_transition input_state_esc_intermediate_table[] = {
- INPUT_STATE_ANYWHERE,
- { 0x00, 0x17, input_c0_dispatch, NULL },
- { 0x19, 0x19, input_c0_dispatch, NULL },
- { 0x1c, 0x1f, input_c0_dispatch, NULL },
- { 0x20, 0x2f, input_intermediate, NULL },
- { 0x30, 0x7e, input_esc_dispatch, &input_state_ground },
- { 0x7f, 0xff, NULL, NULL },
- { -1, -1, NULL, NULL }
- };
- /* csi_enter state table. */
- const struct input_transition input_state_csi_enter_table[] = {
- INPUT_STATE_ANYWHERE,
- { 0x00, 0x17, input_c0_dispatch, NULL },
- { 0x19, 0x19, input_c0_dispatch, NULL },
- { 0x1c, 0x1f, input_c0_dispatch, NULL },
- { 0x20, 0x2f, input_intermediate, &input_state_csi_intermediate },
- { 0x30, 0x39, input_parameter, &input_state_csi_parameter },
- { 0x3a, 0x3a, NULL, &input_state_csi_ignore },
- { 0x3b, 0x3b, input_parameter, &input_state_csi_parameter },
- { 0x3c, 0x3f, input_intermediate, &input_state_csi_parameter },
- { 0x40, 0x7e, input_csi_dispatch, &input_state_ground },
- { 0x7f, 0xff, NULL, NULL },
- { -1, -1, NULL, NULL }
- };
- /* csi_parameter state table. */
- const struct input_transition input_state_csi_parameter_table[] = {
- INPUT_STATE_ANYWHERE,
- { 0x00, 0x17, input_c0_dispatch, NULL },
- { 0x19, 0x19, input_c0_dispatch, NULL },
- { 0x1c, 0x1f, input_c0_dispatch, NULL },
- { 0x20, 0x2f, input_intermediate, &input_state_csi_intermediate },
- { 0x30, 0x39, input_parameter, NULL },
- { 0x3a, 0x3a, NULL, &input_state_csi_ignore },
- { 0x3b, 0x3b, input_parameter, NULL },
- { 0x3c, 0x3f, NULL, &input_state_csi_ignore },
- { 0x40, 0x7e, input_csi_dispatch, &input_state_ground },
- { 0x7f, 0xff, NULL, NULL },
- { -1, -1, NULL, NULL }
- };
- /* csi_intermediate state table. */
- const struct input_transition input_state_csi_intermediate_table[] = {
- INPUT_STATE_ANYWHERE,
- { 0x00, 0x17, input_c0_dispatch, NULL },
- { 0x19, 0x19, input_c0_dispatch, NULL },
- { 0x1c, 0x1f, input_c0_dispatch, NULL },
- { 0x20, 0x2f, input_intermediate, NULL },
- { 0x30, 0x3f, NULL, &input_state_csi_ignore },
- { 0x40, 0x7e, input_csi_dispatch, &input_state_ground },
- { 0x7f, 0xff, NULL, NULL },
- { -1, -1, NULL, NULL }
- };
- /* csi_ignore state table. */
- const struct input_transition input_state_csi_ignore_table[] = {
- INPUT_STATE_ANYWHERE,
- { 0x00, 0x17, input_c0_dispatch, NULL },
- { 0x19, 0x19, input_c0_dispatch, NULL },
- { 0x1c, 0x1f, input_c0_dispatch, NULL },
- { 0x20, 0x3f, NULL, NULL },
- { 0x40, 0x7e, NULL, &input_state_ground },
- { 0x7f, 0xff, NULL, NULL },
- { -1, -1, NULL, NULL }
- };
- /* dcs_enter state table. */
- const struct input_transition input_state_dcs_enter_table[] = {
- INPUT_STATE_ANYWHERE,
- { 0x00, 0x17, NULL, NULL },
- { 0x19, 0x19, NULL, NULL },
- { 0x1c, 0x1f, NULL, NULL },
- { 0x20, 0x2f, input_intermediate, &input_state_dcs_intermediate },
- { 0x30, 0x39, input_parameter, &input_state_dcs_parameter },
- { 0x3a, 0x3a, NULL, &input_state_dcs_ignore },
- { 0x3b, 0x3b, input_parameter, &input_state_dcs_parameter },
- { 0x3c, 0x3f, input_intermediate, &input_state_dcs_parameter },
- { 0x40, 0x7e, input_input, &input_state_dcs_handler },
- { 0x7f, 0xff, NULL, NULL },
- { -1, -1, NULL, NULL }
- };
- /* dcs_parameter state table. */
- const struct input_transition input_state_dcs_parameter_table[] = {
- INPUT_STATE_ANYWHERE,
- { 0x00, 0x17, NULL, NULL },
- { 0x19, 0x19, NULL, NULL },
- { 0x1c, 0x1f, NULL, NULL },
- { 0x20, 0x2f, input_intermediate, &input_state_dcs_intermediate },
- { 0x30, 0x39, input_parameter, NULL },
- { 0x3a, 0x3a, NULL, &input_state_dcs_ignore },
- { 0x3b, 0x3b, input_parameter, NULL },
- { 0x3c, 0x3f, NULL, &input_state_dcs_ignore },
- { 0x40, 0x7e, input_input, &input_state_dcs_handler },
- { 0x7f, 0xff, NULL, NULL },
- { -1, -1, NULL, NULL }
- };
- /* dcs_interm state table. */
- const struct input_transition input_state_dcs_intermediate_table[] = {
- INPUT_STATE_ANYWHERE,
- { 0x00, 0x17, NULL, NULL },
- { 0x19, 0x19, NULL, NULL },
- { 0x1c, 0x1f, NULL, NULL },
- { 0x20, 0x2f, input_intermediate, NULL },
- { 0x30, 0x3f, NULL, &input_state_dcs_ignore },
- { 0x40, 0x7e, input_input, &input_state_dcs_handler },
- { 0x7f, 0xff, NULL, NULL },
- { -1, -1, NULL, NULL }
- };
- /* dcs_handler state table. */
- const struct input_transition input_state_dcs_handler_table[] = {
- /* No INPUT_STATE_ANYWHERE */
- { 0x00, 0x1a, input_input, NULL },
- { 0x1b, 0x1b, NULL, &input_state_dcs_escape },
- { 0x1c, 0xff, input_input, NULL },
- { -1, -1, NULL, NULL }
- };
- /* dcs_escape state table. */
- const struct input_transition input_state_dcs_escape_table[] = {
- /* No INPUT_STATE_ANYWHERE */
- { 0x00, 0x5b, input_input, &input_state_dcs_handler },
- { 0x5c, 0x5c, input_dcs_dispatch, &input_state_ground },
- { 0x5d, 0xff, input_input, &input_state_dcs_handler },
- { -1, -1, NULL, NULL }
- };
- /* dcs_ignore state table. */
- const struct input_transition input_state_dcs_ignore_table[] = {
- INPUT_STATE_ANYWHERE,
- { 0x00, 0x17, NULL, NULL },
- { 0x19, 0x19, NULL, NULL },
- { 0x1c, 0x1f, NULL, NULL },
- { 0x20, 0xff, NULL, NULL },
- { -1, -1, NULL, NULL }
- };
- /* osc_string state table. */
- const struct input_transition input_state_osc_string_table[] = {
- INPUT_STATE_ANYWHERE,
- { 0x00, 0x06, NULL, NULL },
- { 0x07, 0x07, NULL, &input_state_ground },
- { 0x08, 0x17, NULL, NULL },
- { 0x19, 0x19, NULL, NULL },
- { 0x1c, 0x1f, NULL, NULL },
- { 0x20, 0xff, input_input, NULL },
- { -1, -1, NULL, NULL }
- };
- /* apc_string state table. */
- const struct input_transition input_state_apc_string_table[] = {
- INPUT_STATE_ANYWHERE,
- { 0x00, 0x17, NULL, NULL },
- { 0x19, 0x19, NULL, NULL },
- { 0x1c, 0x1f, NULL, NULL },
- { 0x20, 0xff, input_input, NULL },
- { -1, -1, NULL, NULL }
- };
- /* rename_string state table. */
- const struct input_transition input_state_rename_string_table[] = {
- INPUT_STATE_ANYWHERE,
- { 0x00, 0x17, NULL, NULL },
- { 0x19, 0x19, NULL, NULL },
- { 0x1c, 0x1f, NULL, NULL },
- { 0x20, 0xff, input_input, NULL },
- { -1, -1, NULL, NULL }
- };
- /* consume_st state table. */
- const struct input_transition input_state_consume_st_table[] = {
- INPUT_STATE_ANYWHERE,
- { 0x00, 0x17, NULL, NULL },
- { 0x19, 0x19, NULL, NULL },
- { 0x1c, 0x1f, NULL, NULL },
- { 0x20, 0xff, NULL, NULL },
- { -1, -1, NULL, NULL }
- };
- /* utf8_three state table. */
- const struct input_transition input_state_utf8_three_table[] = {
- /* No INPUT_STATE_ANYWHERE */
- { 0x00, 0x7f, NULL, &input_state_ground },
- { 0x80, 0xbf, input_utf8_add, &input_state_utf8_two },
- { 0xc0, 0xff, NULL, &input_state_ground },
- { -1, -1, NULL, NULL }
- };
- /* utf8_two state table. */
- const struct input_transition input_state_utf8_two_table[] = {
- /* No INPUT_STATE_ANYWHERE */
- { 0x00, 0x7f, NULL, &input_state_ground },
- { 0x80, 0xbf, input_utf8_add, &input_state_utf8_one },
- { 0xc0, 0xff, NULL, &input_state_ground },
- { -1, -1, NULL, NULL }
- };
- /* utf8_one state table. */
- const struct input_transition input_state_utf8_one_table[] = {
- /* No INPUT_STATE_ANYWHERE */
- { 0x00, 0x7f, NULL, &input_state_ground },
- { 0x80, 0xbf, input_utf8_close, &input_state_ground },
- { 0xc0, 0xff, NULL, &input_state_ground },
- { -1, -1, NULL, NULL }
- };
- /* Input table compare. */
- int
- input_table_compare(const void *key, const void *value)
- {
- const struct input_ctx *ictx = key;
- const struct input_table_entry *entry = value;
- if (ictx->ch != entry->ch)
- return (ictx->ch - entry->ch);
- return (strcmp(ictx->interm_buf, entry->interm));
- }
- /* Reset cell state to default. */
- void
- input_reset_cell(struct input_ctx *ictx)
- {
- memcpy(&ictx->cell.cell, &grid_default_cell, sizeof ictx->cell.cell);
- ictx->cell.set = 0;
- ictx->cell.g0set = ictx->cell.g1set = 0;
- memcpy(&ictx->old_cell, &ictx->cell, sizeof ictx->old_cell);
- ictx->old_cx = 0;
- ictx->old_cy = 0;
- }
- /* Initialise input parser. */
- void
- input_init(struct window_pane *wp)
- {
- struct input_ctx *ictx;
- ictx = wp->ictx = xcalloc(1, sizeof *ictx);
- ictx->input_space = INPUT_BUF_START;
- ictx->input_buf = xmalloc(INPUT_BUF_START);
- ictx->since_ground = evbuffer_new();
- input_reset(wp, 0);
- }
- /* Destroy input parser. */
- void
- input_free(struct window_pane *wp)
- {
- struct input_ctx *ictx = wp->ictx;
- free(ictx->input_buf);
- evbuffer_free(ictx->since_ground);
- free (ictx);
- wp->ictx = NULL;
- }
- /* Reset input state and clear screen. */
- void
- input_reset(struct window_pane *wp, int clear)
- {
- struct input_ctx *ictx = wp->ictx;
- input_reset_cell(ictx);
- if (clear) {
- if (wp->mode == NULL)
- screen_write_start(&ictx->ctx, wp, &wp->base);
- else
- screen_write_start(&ictx->ctx, NULL, &wp->base);
- screen_write_reset(&ictx->ctx);
- screen_write_stop(&ictx->ctx);
- }
- *ictx->interm_buf = '\0';
- ictx->interm_len = 0;
- *ictx->param_buf = '\0';
- ictx->param_len = 0;
- *ictx->input_buf = '\0';
- ictx->input_len = 0;
- ictx->state = &input_state_ground;
- ictx->flags = 0;
- }
- /* Return pending data. */
- struct evbuffer *
- input_pending(struct window_pane *wp)
- {
- return (wp->ictx->since_ground);
- }
- /* Change input state. */
- void
- input_set_state(struct window_pane *wp, const struct input_transition *itr)
- {
- struct input_ctx *ictx = wp->ictx;
- if (ictx->state->exit != NULL)
- ictx->state->exit(ictx);
- ictx->state = itr->state;
- if (ictx->state->enter != NULL)
- ictx->state->enter(ictx);
- }
- /* Parse input. */
- void
- input_parse(struct window_pane *wp)
- {
- struct input_ctx *ictx = wp->ictx;
- const struct input_transition *itr;
- struct evbuffer *evb = wp->event->input;
- u_char *buf;
- size_t len, off;
- if (EVBUFFER_LENGTH(evb) == 0)
- return;
- window_update_activity(wp->window);
- wp->flags |= PANE_CHANGED;
- /*
- * Open the screen. Use NULL wp if there is a mode set as don't want to
- * update the tty.
- */
- if (wp->mode == NULL)
- screen_write_start(&ictx->ctx, wp, &wp->base);
- else
- screen_write_start(&ictx->ctx, NULL, &wp->base);
- ictx->wp = wp;
- buf = EVBUFFER_DATA(evb);
- len = EVBUFFER_LENGTH(evb);
- notify_input(wp, evb);
- off = 0;
- log_debug("%s: %%%u %s, %zu bytes: %.*s", __func__, wp->id,
- ictx->state->name, len, (int)len, buf);
- /* Parse the input. */
- while (off < len) {
- ictx->ch = buf[off++];
- /* Find the transition. */
- itr = ictx->state->transitions;
- while (itr->first != -1 && itr->last != -1) {
- if (ictx->ch >= itr->first && ictx->ch <= itr->last)
- break;
- itr++;
- }
- if (itr->first == -1 || itr->last == -1) {
- /* No transition? Eh? */
- fatalx("no transition from state");
- }
- /*
- * Execute the handler, if any. Don't switch state if it
- * returns non-zero.
- */
- if (itr->handler != NULL && itr->handler(ictx) != 0)
- continue;
- /* And switch state, if necessary. */
- if (itr->state != NULL)
- input_set_state(wp, itr);
- /* If not in ground state, save input. */
- if (ictx->state != &input_state_ground)
- evbuffer_add(ictx->since_ground, &ictx->ch, 1);
- }
- /* Close the screen. */
- screen_write_stop(&ictx->ctx);
- evbuffer_drain(evb, len);
- }
- /* Split the parameter list (if any). */
- int
- input_split(struct input_ctx *ictx)
- {
- const char *errstr;
- char *ptr, *out;
- int n;
- ictx->param_list_len = 0;
- if (ictx->param_len == 0)
- return (0);
- ptr = ictx->param_buf;
- while ((out = strsep(&ptr, ";")) != NULL) {
- if (*out == '\0')
- n = -1;
- else {
- n = strtonum(out, 0, INT_MAX, &errstr);
- if (errstr != NULL)
- return (-1);
- }
- ictx->param_list[ictx->param_list_len++] = n;
- if (ictx->param_list_len == nitems(ictx->param_list))
- return (-1);
- }
- return (0);
- }
- /* Get an argument or return default value. */
- int
- input_get(struct input_ctx *ictx, u_int validx, int minval, int defval)
- {
- int retval;
- if (validx >= ictx->param_list_len)
- return (defval);
- retval = ictx->param_list[validx];
- if (retval == -1)
- return (defval);
- if (retval < minval)
- return (minval);
- return (retval);
- }
- /* Reply to terminal query. */
- void
- input_reply(struct input_ctx *ictx, const char *fmt, ...)
- {
- va_list ap;
- char *reply;
- va_start(ap, fmt);
- vasprintf(&reply, fmt, ap);
- va_end(ap);
- bufferevent_write(ictx->wp->event, reply, strlen(reply));
- free(reply);
- }
- /* Clear saved state. */
- void
- input_clear(struct input_ctx *ictx)
- {
- *ictx->interm_buf = '\0';
- ictx->interm_len = 0;
- *ictx->param_buf = '\0';
- ictx->param_len = 0;
- *ictx->input_buf = '\0';
- ictx->input_len = 0;
- ictx->flags &= ~INPUT_DISCARD;
- }
- /* Reset for ground state. */
- void
- input_ground(struct input_ctx *ictx)
- {
- evbuffer_drain(ictx->since_ground, EVBUFFER_LENGTH(ictx->since_ground));
- if (ictx->input_space > INPUT_BUF_START) {
- ictx->input_space = INPUT_BUF_START;
- ictx->input_buf = xrealloc(ictx->input_buf, INPUT_BUF_START);
- }
- }
- /* Output this character to the screen. */
- int
- input_print(struct input_ctx *ictx)
- {
- int set;
- set = ictx->cell.set == 0 ? ictx->cell.g0set : ictx->cell.g1set;
- if (set == 1)
- ictx->cell.cell.attr |= GRID_ATTR_CHARSET;
- else
- ictx->cell.cell.attr &= ~GRID_ATTR_CHARSET;
- utf8_set(&ictx->cell.cell.data, ictx->ch);
- screen_write_cell(&ictx->ctx, &ictx->cell.cell);
- ictx->cell.cell.attr &= ~GRID_ATTR_CHARSET;
- return (0);
- }
- /* Collect intermediate string. */
- int
- input_intermediate(struct input_ctx *ictx)
- {
- if (ictx->interm_len == (sizeof ictx->interm_buf) - 1)
- ictx->flags |= INPUT_DISCARD;
- else {
- ictx->interm_buf[ictx->interm_len++] = ictx->ch;
- ictx->interm_buf[ictx->interm_len] = '\0';
- }
- return (0);
- }
- /* Collect parameter string. */
- int
- input_parameter(struct input_ctx *ictx)
- {
- if (ictx->param_len == (sizeof ictx->param_buf) - 1)
- ictx->flags |= INPUT_DISCARD;
- else {
- ictx->param_buf[ictx->param_len++] = ictx->ch;
- ictx->param_buf[ictx->param_len] = '\0';
- }
- return (0);
- }
- /* Collect input string. */
- int
- input_input(struct input_ctx *ictx)
- {
- size_t available;
- available = ictx->input_space;
- while (ictx->input_len + 1 >= available) {
- available *= 2;
- if (available > INPUT_BUF_LIMIT) {
- ictx->flags |= INPUT_DISCARD;
- return (0);
- }
- ictx->input_buf = xrealloc(ictx->input_buf, available);
- ictx->input_space = available;
- }
- ictx->input_buf[ictx->input_len++] = ictx->ch;
- ictx->input_buf[ictx->input_len] = '\0';
- return (0);
- }
- /* Execute C0 control sequence. */
- int
- input_c0_dispatch(struct input_ctx *ictx)
- {
- struct screen_write_ctx *sctx = &ictx->ctx;
- struct window_pane *wp = ictx->wp;
- struct screen *s = sctx->s;
- log_debug("%s: '%c'", __func__, ictx->ch);
- switch (ictx->ch) {
- case '\000': /* NUL */
- break;
- case '\007': /* BEL */
- alerts_queue(wp->window, WINDOW_BELL);
- break;
- case '\010': /* BS */
- screen_write_backspace(sctx);
- break;
- case '\011': /* HT */
- /* Don't tab beyond the end of the line. */
- if (s->cx >= screen_size_x(s) - 1)
- break;
- /* Find the next tab point, or use the last column if none. */
- do {
- s->cx++;
- if (bit_test(s->tabs, s->cx))
- break;
- } while (s->cx < screen_size_x(s) - 1);
- break;
- case '\012': /* LF */
- case '\013': /* VT */
- case '\014': /* FF */
- screen_write_linefeed(sctx, 0);
- break;
- case '\015': /* CR */
- screen_write_carriagereturn(sctx);
- break;
- case '\016': /* SO */
- ictx->cell.set = 1;
- break;
- case '\017': /* SI */
- ictx->cell.set = 0;
- break;
- default:
- log_debug("%s: unknown '%c'", __func__, ictx->ch);
- break;
- }
- return (0);
- }
- /* Execute escape sequence. */
- int
- input_esc_dispatch(struct input_ctx *ictx)
- {
- struct screen_write_ctx *sctx = &ictx->ctx;
- struct screen *s = sctx->s;
- struct input_table_entry *entry;
- if (ictx->flags & INPUT_DISCARD)
- return (0);
- log_debug("%s: '%c', %s", __func__, ictx->ch, ictx->interm_buf);
- entry = bsearch(ictx, input_esc_table, nitems(input_esc_table),
- sizeof input_esc_table[0], input_table_compare);
- if (entry == NULL) {
- log_debug("%s: unknown '%c'", __func__, ictx->ch);
- return (0);
- }
- switch (entry->type) {
- case INPUT_ESC_RIS:
- input_reset_cell(ictx);
- screen_write_reset(sctx);
- break;
- case INPUT_ESC_IND:
- screen_write_linefeed(sctx, 0);
- break;
- case INPUT_ESC_NEL:
- screen_write_carriagereturn(sctx);
- screen_write_linefeed(sctx, 0);
- break;
- case INPUT_ESC_HTS:
- if (s->cx < screen_size_x(s))
- bit_set(s->tabs, s->cx);
- break;
- case INPUT_ESC_RI:
- screen_write_reverseindex(sctx);
- break;
- case INPUT_ESC_DECKPAM:
- screen_write_mode_set(sctx, MODE_KKEYPAD);
- break;
- case INPUT_ESC_DECKPNM:
- screen_write_mode_clear(sctx, MODE_KKEYPAD);
- break;
- case INPUT_ESC_DECSC:
- memcpy(&ictx->old_cell, &ictx->cell, sizeof ictx->old_cell);
- ictx->old_cx = s->cx;
- ictx->old_cy = s->cy;
- break;
- case INPUT_ESC_DECRC:
- memcpy(&ictx->cell, &ictx->old_cell, sizeof ictx->cell);
- screen_write_cursormove(sctx, ictx->old_cx, ictx->old_cy);
- break;
- case INPUT_ESC_DECALN:
- screen_write_alignmenttest(sctx);
- break;
- case INPUT_ESC_SCSG0_ON:
- ictx->cell.g0set = 1;
- break;
- case INPUT_ESC_SCSG0_OFF:
- ictx->cell.g0set = 0;
- break;
- case INPUT_ESC_SCSG1_ON:
- ictx->cell.g1set = 1;
- break;
- case INPUT_ESC_SCSG1_OFF:
- ictx->cell.g1set = 0;
- break;
- }
- return (0);
- }
- /* Execute control sequence. */
- int
- input_csi_dispatch(struct input_ctx *ictx)
- {
- struct screen_write_ctx *sctx = &ictx->ctx;
- struct screen *s = sctx->s;
- struct input_table_entry *entry;
- int n, m;
- u_int cx;
- if (ictx->flags & INPUT_DISCARD)
- return (0);
- if (input_split(ictx) != 0)
- return (0);
- log_debug("%s: '%c' \"%s\" \"%s\"",
- __func__, ictx->ch, ictx->interm_buf, ictx->param_buf);
- entry = bsearch(ictx, input_csi_table, nitems(input_csi_table),
- sizeof input_csi_table[0], input_table_compare);
- if (entry == NULL) {
- log_debug("%s: unknown '%c'", __func__, ictx->ch);
- return (0);
- }
- switch (entry->type) {
- case INPUT_CSI_CBT:
- /* Find the previous tab point, n times. */
- cx = s->cx;
- if (cx > screen_size_x(s) - 1)
- cx = screen_size_x(s) - 1;
- n = input_get(ictx, 0, 1, 1);
- while (cx > 0 && n-- > 0) {
- do
- cx--;
- while (cx > 0 && !bit_test(s->tabs, cx));
- }
- s->cx = cx;
- break;
- case INPUT_CSI_CUB:
- screen_write_cursorleft(sctx, input_get(ictx, 0, 1, 1));
- break;
- case INPUT_CSI_CUD:
- screen_write_cursordown(sctx, input_get(ictx, 0, 1, 1));
- break;
- case INPUT_CSI_CUF:
- screen_write_cursorright(sctx, input_get(ictx, 0, 1, 1));
- break;
- case INPUT_CSI_CUP:
- n = input_get(ictx, 0, 1, 1);
- m = input_get(ictx, 1, 1, 1);
- screen_write_cursormove(sctx, m - 1, n - 1);
- break;
- case INPUT_CSI_WINOPS:
- input_csi_dispatch_winops(ictx);
- break;
- case INPUT_CSI_CUU:
- screen_write_cursorup(sctx, input_get(ictx, 0, 1, 1));
- break;
- case INPUT_CSI_CNL:
- screen_write_carriagereturn(sctx);
- screen_write_cursordown(sctx, input_get(ictx, 0, 1, 1));
- break;
- case INPUT_CSI_CPL:
- screen_write_carriagereturn(sctx);
- screen_write_cursorup(sctx, input_get(ictx, 0, 1, 1));
- break;
- case INPUT_CSI_DA:
- switch (input_get(ictx, 0, 0, 0)) {
- case 0:
- input_reply(ictx, "\033[?1;2c");
- break;
- default:
- log_debug("%s: unknown '%c'", __func__, ictx->ch);
- break;
- }
- break;
- case INPUT_CSI_DA_TWO:
- switch (input_get(ictx, 0, 0, 0)) {
- case 0:
- input_reply(ictx, "\033[>84;0;0c");
- break;
- default:
- log_debug("%s: unknown '%c'", __func__, ictx->ch);
- break;
- }
- break;
- case INPUT_CSI_ECH:
- screen_write_clearcharacter(sctx, input_get(ictx, 0, 1, 1));
- break;
- case INPUT_CSI_DCH:
- screen_write_deletecharacter(sctx, input_get(ictx, 0, 1, 1));
- break;
- case INPUT_CSI_DECSTBM:
- n = input_get(ictx, 0, 1, 1);
- m = input_get(ictx, 1, 1, screen_size_y(s));
- screen_write_scrollregion(sctx, n - 1, m - 1);
- break;
- case INPUT_CSI_DL:
- screen_write_deleteline(sctx, input_get(ictx, 0, 1, 1));
- break;
- case INPUT_CSI_DSR:
- switch (input_get(ictx, 0, 0, 0)) {
- case 5:
- input_reply(ictx, "\033[0n");
- break;
- case 6:
- input_reply(ictx, "\033[%u;%uR", s->cy + 1, s->cx + 1);
- break;
- default:
- log_debug("%s: unknown '%c'", __func__, ictx->ch);
- break;
- }
- break;
- case INPUT_CSI_ED:
- switch (input_get(ictx, 0, 0, 0)) {
- case 0:
- screen_write_clearendofscreen(sctx);
- break;
- case 1:
- screen_write_clearstartofscreen(sctx);
- break;
- case 2:
- screen_write_clearscreen(sctx);
- break;
- case 3:
- switch (input_get(ictx, 1, 0, 0)) {
- case 0:
- /*
- * Linux console extension to clear history
- * (for example before locking the screen).
- */
- screen_write_clearhistory(sctx);
- break;
- }
- break;
- default:
- log_debug("%s: unknown '%c'", __func__, ictx->ch);
- break;
- }
- break;
- case INPUT_CSI_EL:
- switch (input_get(ictx, 0, 0, 0)) {
- case 0:
- screen_write_clearendofline(sctx);
- break;
- case 1:
- screen_write_clearstartofline(sctx);
- break;
- case 2:
- screen_write_clearline(sctx);
- break;
- default:
- log_debug("%s: unknown '%c'", __func__, ictx->ch);
- break;
- }
- break;
- case INPUT_CSI_HPA:
- n = input_get(ictx, 0, 1, 1);
- screen_write_cursormove(sctx, n - 1, s->cy);
- break;
- case INPUT_CSI_ICH:
- screen_write_insertcharacter(sctx, input_get(ictx, 0, 1, 1));
- break;
- case INPUT_CSI_IL:
- screen_write_insertline(sctx, input_get(ictx, 0, 1, 1));
- break;
- case INPUT_CSI_RCP:
- memcpy(&ictx->cell, &ictx->old_cell, sizeof ictx->cell);
- screen_write_cursormove(sctx, ictx->old_cx, ictx->old_cy);
- break;
- case INPUT_CSI_RM:
- input_csi_dispatch_rm(ictx);
- break;
- case INPUT_CSI_RM_PRIVATE:
- input_csi_dispatch_rm_private(ictx);
- break;
- case INPUT_CSI_SCP:
- memcpy(&ictx->old_cell, &ictx->cell, sizeof ictx->old_cell);
- ictx->old_cx = s->cx;
- ictx->old_cy = s->cy;
- break;
- case INPUT_CSI_SGR:
- input_csi_dispatch_sgr(ictx);
- break;
- case INPUT_CSI_SM:
- input_csi_dispatch_sm(ictx);
- break;
- case INPUT_CSI_SM_PRIVATE:
- input_csi_dispatch_sm_private(ictx);
- break;
- case INPUT_CSI_TBC:
- switch (input_get(ictx, 0, 0, 0)) {
- case 0:
- if (s->cx < screen_size_x(s))
- bit_clear(s->tabs, s->cx);
- break;
- case 3:
- bit_nclear(s->tabs, 0, screen_size_x(s) - 1);
- break;
- default:
- log_debug("%s: unknown '%c'", __func__, ictx->ch);
- break;
- }
- break;
- case INPUT_CSI_VPA:
- n = input_get(ictx, 0, 1, 1);
- screen_write_cursormove(sctx, s->cx, n - 1);
- break;
- case INPUT_CSI_DECSCUSR:
- n = input_get(ictx, 0, 0, 0);
- screen_set_cursor_style(s, n);
- break;
- }
- return (0);
- }
- /* Handle CSI RM. */
- void
- input_csi_dispatch_rm(struct input_ctx *ictx)
- {
- u_int i;
- for (i = 0; i < ictx->param_list_len; i++) {
- switch (input_get(ictx, i, 0, -1)) {
- case 4: /* IRM */
- screen_write_mode_clear(&ictx->ctx, MODE_INSERT);
- break;
- case 34:
- screen_write_mode_set(&ictx->ctx, MODE_BLINKING);
- break;
- default:
- log_debug("%s: unknown '%c'", __func__, ictx->ch);
- break;
- }
- }
- }
- /* Handle CSI private RM. */
- void
- input_csi_dispatch_rm_private(struct input_ctx *ictx)
- {
- struct window_pane *wp = ictx->wp;
- u_int i;
- for (i = 0; i < ictx->param_list_len; i++) {
- switch (input_get(ictx, i, 0, -1)) {
- case 1: /* DECCKM */
- screen_write_mode_clear(&ictx->ctx, MODE_KCURSOR);
- break;
- case 3: /* DECCOLM */
- screen_write_cursormove(&ictx->ctx, 0, 0);
- screen_write_clearscreen(&ictx->ctx);
- break;
- case 7: /* DECAWM */
- screen_write_mode_clear(&ictx->ctx, MODE_WRAP);
- break;
- case 12:
- screen_write_mode_clear(&ictx->ctx, MODE_BLINKING);
- break;
- case 25: /* TCEM */
- screen_write_mode_clear(&ictx->ctx, MODE_CURSOR);
- break;
- case 1000:
- case 1001:
- case 1002:
- screen_write_mode_clear(&ictx->ctx, ALL_MOUSE_MODES);
- break;
- case 1004:
- screen_write_mode_clear(&ictx->ctx, MODE_FOCUSON);
- break;
- case 1005:
- screen_write_mode_clear(&ictx->ctx, MODE_MOUSE_UTF8);
- break;
- case 1006:
- screen_write_mode_clear(&ictx->ctx, MODE_MOUSE_SGR);
- break;
- case 47:
- case 1047:
- window_pane_alternate_off(wp, &ictx->cell.cell, 0);
- break;
- case 1049:
- window_pane_alternate_off(wp, &ictx->cell.cell, 1);
- break;
- case 2004:
- screen_write_mode_clear(&ictx->ctx, MODE_BRACKETPASTE);
- break;
- default:
- log_debug("%s: unknown '%c'", __func__, ictx->ch);
- break;
- }
- }
- }
- /* Handle CSI SM. */
- void
- input_csi_dispatch_sm(struct input_ctx *ictx)
- {
- u_int i;
- for (i = 0; i < ictx->param_list_len; i++) {
- switch (input_get(ictx, i, 0, -1)) {
- case 4: /* IRM */
- screen_write_mode_set(&ictx->ctx, MODE_INSERT);
- break;
- case 34:
- screen_write_mode_clear(&ictx->ctx, MODE_BLINKING);
- break;
- default:
- log_debug("%s: unknown '%c'", __func__, ictx->ch);
- break;
- }
- }
- }
- /* Handle CSI private SM. */
- void
- input_csi_dispatch_sm_private(struct input_ctx *ictx)
- {
- struct window_pane *wp = ictx->wp;
- u_int i;
- for (i = 0; i < ictx->param_list_len; i++) {
- switch (input_get(ictx, i, 0, -1)) {
- case 1: /* DECCKM */
- screen_write_mode_set(&ictx->ctx, MODE_KCURSOR);
- break;
- case 3: /* DECCOLM */
- screen_write_cursormove(&ictx->ctx, 0, 0);
- screen_write_clearscreen(&ictx->ctx);
- break;
- case 7: /* DECAWM */
- screen_write_mode_set(&ictx->ctx, MODE_WRAP);
- break;
- case 12:
- screen_write_mode_set(&ictx->ctx, MODE_BLINKING);
- break;
- case 25: /* TCEM */
- screen_write_mode_set(&ictx->ctx, MODE_CURSOR);
- break;
- case 1000:
- screen_write_mode_clear(&ictx->ctx, ALL_MOUSE_MODES);
- screen_write_mode_set(&ictx->ctx, MODE_MOUSE_STANDARD);
- break;
- case 1002:
- screen_write_mode_clear(&ictx->ctx, ALL_MOUSE_MODES);
- screen_write_mode_set(&ictx->ctx, MODE_MOUSE_BUTTON);
- break;
- case 1004:
- if (ictx->ctx.s->mode & MODE_FOCUSON)
- break;
- screen_write_mode_set(&ictx->ctx, MODE_FOCUSON);
- wp->flags |= PANE_FOCUSPUSH; /* force update */
- break;
- case 1005:
- screen_write_mode_set(&ictx->ctx, MODE_MOUSE_UTF8);
- break;
- case 1006:
- screen_write_mode_set(&ictx->ctx, MODE_MOUSE_SGR);
- break;
- case 47:
- case 1047:
- window_pane_alternate_on(wp, &ictx->cell.cell, 0);
- break;
- case 1049:
- window_pane_alternate_on(wp, &ictx->cell.cell, 1);
- break;
- case 2004:
- screen_write_mode_set(&ictx->ctx, MODE_BRACKETPASTE);
- break;
- default:
- log_debug("%s: unknown '%c'", __func__, ictx->ch);
- break;
- }
- }
- }
- /* Handle CSI window operations. */
- void
- input_csi_dispatch_winops(struct input_ctx *ictx)
- {
- struct window_pane *wp = ictx->wp;
- int n, m;
- m = 0;
- while ((n = input_get(ictx, m, 0, -1)) != -1) {
- switch (n) {
- case 1:
- case 2:
- case 5:
- case 6:
- case 7:
- case 11:
- case 13:
- case 14:
- case 19:
- case 20:
- case 21:
- case 24:
- break;
- case 3:
- case 4:
- case 8:
- m++;
- if (input_get(ictx, m, 0, -1) == -1)
- return;
- /* FALLTHROUGH */
- case 9:
- case 10:
- case 22:
- case 23:
- m++;
- if (input_get(ictx, m, 0, -1) == -1)
- return;
- break;
- case 18:
- input_reply(ictx, "\033[8;%u;%ut", wp->sy, wp->sx);
- break;
- default:
- log_debug("%s: unknown '%c'", __func__, ictx->ch);
- break;
- }
- m++;
- }
- }
- /* Handle CSI SGR for 256 colours. */
- void
- input_csi_dispatch_sgr_256(struct input_ctx *ictx, int fgbg, u_int *i)
- {
- struct grid_cell *gc = &ictx->cell.cell;
- int c;
- (*i)++;
- c = input_get(ictx, *i, 0, -1);
- if (c == -1) {
- if (fgbg == 38) {
- gc->flags &= ~(GRID_FLAG_FG256|GRID_FLAG_FGRGB);
- gc->fg = 8;
- } else if (fgbg == 48) {
- gc->flags &= ~(GRID_FLAG_BG256|GRID_FLAG_BGRGB);
- gc->bg = 8;
- }
- } else {
- if (fgbg == 38) {
- gc->flags |= GRID_FLAG_FG256;
- gc->flags &= ~GRID_FLAG_FGRGB;
- gc->fg = c;
- } else if (fgbg == 48) {
- gc->flags |= GRID_FLAG_BG256;
- gc->flags &= ~GRID_FLAG_BGRGB;
- gc->bg = c;
- }
- }
- }
- /* Handle CSI SGR for RGB colours. */
- void
- input_csi_dispatch_sgr_rgb(struct input_ctx *ictx, int fgbg, u_int *i)
- {
- struct grid_cell *gc = &ictx->cell.cell;
- int r, g, b;
- (*i)++;
- r = input_get(ictx, *i, 0, -1);
- if (r == -1 || r > 255)
- return;
- (*i)++;
- g = input_get(ictx, *i, 0, -1);
- if (g == -1 || g > 255)
- return;
- (*i)++;
- b = input_get(ictx, *i, 0, -1);
- if (b == -1 || b > 255)
- return;
- if (fgbg == 38) {
- gc->flags &= ~GRID_FLAG_FG256;
- gc->flags |= GRID_FLAG_FGRGB;
- gc->fg_rgb.r = r;
- gc->fg_rgb.g = g;
- gc->fg_rgb.b = b;
- } else if (fgbg == 48) {
- gc->flags &= ~GRID_FLAG_BG256;
- gc->flags |= GRID_FLAG_BGRGB;
- gc->bg_rgb.r = r;
- gc->bg_rgb.g = g;
- gc->bg_rgb.b = b;
- }
- }
- /* Handle CSI SGR. */
- void
- input_csi_dispatch_sgr(struct input_ctx *ictx)
- {
- struct grid_cell *gc = &ictx->cell.cell;
- u_int i;
- int n;
- if (ictx->param_list_len == 0) {
- memcpy(gc, &grid_default_cell, sizeof *gc);
- return;
- }
- for (i = 0; i < ictx->param_list_len; i++) {
- n = input_get(ictx, i, 0, 0);
- if (n == 38 || n == 48) {
- i++;
- switch (input_get(ictx, i, 0, -1)) {
- case 2:
- input_csi_dispatch_sgr_rgb(ictx, n, &i);
- break;
- case 5:
- input_csi_dispatch_sgr_256(ictx, n, &i);
- break;
- }
- continue;
- }
- switch (n) {
- case 0:
- case 10:
- memcpy(gc, &grid_default_cell, sizeof *gc);
- break;
- case 1:
- gc->attr |= GRID_ATTR_BRIGHT;
- break;
- case 2:
- gc->attr |= GRID_ATTR_DIM;
- break;
- case 3:
- gc->attr |= GRID_ATTR_ITALICS;
- break;
- case 4:
- gc->attr |= GRID_ATTR_UNDERSCORE;
- break;
- case 5:
- gc->attr |= GRID_ATTR_BLINK;
- break;
- case 7:
- gc->attr |= GRID_ATTR_REVERSE;
- break;
- case 8:
- gc->attr |= GRID_ATTR_HIDDEN;
- break;
- case 22:
- gc->attr &= ~(GRID_ATTR_BRIGHT|GRID_ATTR_DIM);
- break;
- case 23:
- gc->attr &= ~GRID_ATTR_ITALICS;
- break;
- case 24:
- gc->attr &= ~GRID_ATTR_UNDERSCORE;
- break;
- case 25:
- gc->attr &= ~GRID_ATTR_BLINK;
- break;
- case 27:
- gc->attr &= ~GRID_ATTR_REVERSE;
- break;
- case 30:
- case 31:
- case 32:
- case 33:
- case 34:
- case 35:
- case 36:
- case 37:
- gc->flags &= ~(GRID_FLAG_FG256|GRID_FLAG_FGRGB);
- gc->fg = n - 30;
- break;
- case 39:
- gc->flags &= ~(GRID_FLAG_FG256|GRID_FLAG_FGRGB);
- gc->fg = 8;
- break;
- case 40:
- case 41:
- case 42:
- case 43:
- case 44:
- case 45:
- case 46:
- case 47:
- gc->flags &= ~(GRID_FLAG_BG256|GRID_FLAG_BGRGB);
- gc->bg = n - 40;
- break;
- case 49:
- gc->flags &= ~(GRID_FLAG_BG256|GRID_FLAG_BGRGB);
- gc->bg = 8;
- break;
- case 90:
- case 91:
- case 92:
- case 93:
- case 94:
- case 95:
- case 96:
- case 97:
- gc->flags &= ~(GRID_FLAG_FG256|GRID_FLAG_FGRGB);
- gc->fg = n;
- break;
- case 100:
- case 101:
- case 102:
- case 103:
- case 104:
- case 105:
- case 106:
- case 107:
- gc->flags &= ~(GRID_FLAG_BG256|GRID_FLAG_BGRGB);
- gc->bg = n - 10;
- break;
- }
- }
- }
- /* DCS terminator (ST) received. */
- int
- input_dcs_dispatch(struct input_ctx *ictx)
- {
- const char prefix[] = "tmux;";
- const u_int prefix_len = (sizeof prefix) - 1;
- if (ictx->flags & INPUT_DISCARD)
- return (0);
- log_debug("%s: \"%s\"", __func__, ictx->input_buf);
- /* Check for tmux prefix. */
- if (ictx->input_len >= prefix_len &&
- strncmp(ictx->input_buf, prefix, prefix_len) == 0) {
- screen_write_rawstring(&ictx->ctx,
- ictx->input_buf + prefix_len, ictx->input_len - prefix_len);
- }
- return (0);
- }
- /* OSC string started. */
- void
- input_enter_osc(struct input_ctx *ictx)
- {
- log_debug("%s", __func__);
- input_clear(ictx);
- }
- /* OSC terminator (ST) received. */
- void
- input_exit_osc(struct input_ctx *ictx)
- {
- u_char *p = ictx->input_buf;
- u_int option;
- if (ictx->flags & INPUT_DISCARD)
- return;
- if (ictx->input_len < 1 || *p < '0' || *p > '9')
- return;
- log_debug("%s: \"%s\"", __func__, p);
- option = 0;
- while (*p >= '0' && *p <= '9')
- option = option * 10 + *p++ - '0';
- if (*p == ';')
- p++;
- switch (option) {
- case 0:
- case 2:
- screen_set_title(ictx->ctx.s, p);
- server_status_window(ictx->wp->window);
- break;
- case 12:
- if (*p != '?') /* ? is colour request */
- screen_set_cursor_colour(ictx->ctx.s, p);
- break;
- case 112:
- if (*p == '\0') /* no arguments allowed */
- screen_set_cursor_colour(ictx->ctx.s, "");
- break;
- default:
- log_debug("%s: unknown '%u'", __func__, option);
- break;
- }
- }
- /* APC string started. */
- void
- input_enter_apc(struct input_ctx *ictx)
- {
- log_debug("%s", __func__);
- input_clear(ictx);
- }
- /* APC terminator (ST) received. */
- void
- input_exit_apc(struct input_ctx *ictx)
- {
- if (ictx->flags & INPUT_DISCARD)
- return;
- log_debug("%s: \"%s\"", __func__, ictx->input_buf);
- screen_set_title(ictx->ctx.s, ictx->input_buf);
- server_status_window(ictx->wp->window);
- }
- /* Rename string started. */
- void
- input_enter_rename(struct input_ctx *ictx)
- {
- log_debug("%s", __func__);
- input_clear(ictx);
- }
- /* Rename terminator (ST) received. */
- void
- input_exit_rename(struct input_ctx *ictx)
- {
- if (ictx->flags & INPUT_DISCARD)
- return;
- if (!options_get_number(ictx->wp->window->options, "allow-rename"))
- return;
- log_debug("%s: \"%s\"", __func__, ictx->input_buf);
- window_set_name(ictx->wp->window, ictx->input_buf);
- options_set_number(ictx->wp->window->options, "automatic-rename", 0);
- server_status_window(ictx->wp->window);
- }
- /* Open UTF-8 character. */
- int
- input_utf8_open(struct input_ctx *ictx)
- {
- struct utf8_data *ud = &ictx->utf8data;
- if (utf8_open(ud, ictx->ch) != UTF8_MORE)
- fatalx("UTF-8 open invalid %#x", ictx->ch);
- log_debug("%s %hhu", __func__, ud->size);
- return (0);
- }
- /* Append to UTF-8 character. */
- int
- input_utf8_add(struct input_ctx *ictx)
- {
- struct utf8_data *ud = &ictx->utf8data;
- if (utf8_append(ud, ictx->ch) != UTF8_MORE)
- fatalx("UTF-8 add invalid %#x", ictx->ch);
- log_debug("%s", __func__);
- return (0);
- }
- /* Close UTF-8 string. */
- int
- input_utf8_close(struct input_ctx *ictx)
- {
- struct utf8_data *ud = &ictx->utf8data;
- if (utf8_append(ud, ictx->ch) != UTF8_DONE) {
- /*
- * An error here could be invalid UTF-8 or it could be a
- * nonprintable character for which we can't get the
- * width. Drop it.
- */
- return (0);
- }
- log_debug("%s %hhu '%*s' (width %hhu)", __func__, ud->size,
- (int)ud->size, ud->data, ud->width);
- utf8_copy(&ictx->cell.cell.data, ud);
- screen_write_cell(&ictx->ctx, &ictx->cell.cell);
- return (0);
- }
|