From add7c1605dfc6bb65c5165f87fec40f61df22bda Mon Sep 17 00:00:00 2001 From: deuce <> Date: Tue, 28 Apr 2020 07:58:49 +0000 Subject: [PATCH] Add macro and rectangular area checksum functions. --- src/conio/GNUmakefile | 2 +- src/conio/cterm.c | 76 +++++++++++++++++++++++++++++++++++++++++-- src/conio/cterm.txt | 25 ++++++++++++-- 3 files changed, 96 insertions(+), 7 deletions(-) diff --git a/src/conio/GNUmakefile b/src/conio/GNUmakefile index fdd301bf4d..d0f1a428bc 100644 --- a/src/conio/GNUmakefile +++ b/src/conio/GNUmakefile @@ -2,7 +2,7 @@ SRC_ROOT = .. # Cross platform/compiler definitions include $(SRC_ROOT)/build/Common.gmake # defines clean and output directory rules -CFLAGS += $(XPDEV-MT_CFLAGS) $(ENCODE_CFLAGS) $(CIOLIB-MT_CFLAGS) +CFLAGS += $(XPDEV-MT_CFLAGS) $(HASH_CFLAGS) $(ENCODE_CFLAGS) $(CIOLIB-MT_CFLAGS) ifeq ($(os),win32) OBJS += $(MTOBJODIR)$(DIRSEP)SDL_win32_main$(OFILE) diff --git a/src/conio/cterm.c b/src/conio/cterm.c index 8834eb0607..8254f11639 100644 --- a/src/conio/cterm.c +++ b/src/conio/cterm.c @@ -73,6 +73,7 @@ #include "cterm.h" #include "vidmodes.h" #include "base64.h" +#include <crc16.h> #define BUFSIZE 2048 @@ -2557,17 +2558,37 @@ static void do_ansi(struct cterminal *cterm, char *retbuf, size_t retsize, int * else if (seq->param_str[0] == '?' && parse_parameters(seq)) { if(retbuf == NULL) break; - tmp[0] = 0; - if (seq->param_count > 1) - break; seq_default(seq, 0, 1); + tmp[0] = 0; switch(seq->param_int[0]) { case 62: /* Query macro space available */ { + if (seq->param_count > 1) + break; // Just fake it as int16_max strcpy(tmp, "\x1b[32767*{"); break; } + case 63: /* Quero macro space "checksum" */ + { + uint16_t crc = 0; + if (seq->param_count > 2) + break; + seq_default(seq, 1, 1); + for (k = 0; k < (sizeof(cterm->macros) / sizeof(cterm->macros[0])); k++) { + if (cterm->macros[k]) { + for (i = 0; i <= cterm->macro_lens[k]; i++) + crc = ucrc16(cterm->macros[k][i], crc); + } + else + crc = ucrc16(0, crc); + } + *tmp = 0; + snprintf(tmp, sizeof(tmp), "\x1bP%u!%04x\x1b\\", (unsigned)seq->param_int[1], crc); + if(*tmp && strlen(retbuf) + strlen(tmp) < retsize) + strcat(retbuf, tmp); + break; + } } if(*tmp && strlen(retbuf) + strlen(tmp) < retsize) strcat(retbuf, tmp); @@ -3141,6 +3162,55 @@ static void do_ansi(struct cterminal *cterm, char *retbuf, size_t retsize, int * if(newspeed >= 0) *speed = newspeed; } + else if (strcmp(seq->ctrl_func, "*y") == 0) { + if (seq->param_count >= 6) { + if (seq->param_int[0] != UINT64_MAX && + seq->param_int[0] <= UINT16_MAX && + seq->param_int[1] == 1 && + seq->param_int[2] != UINT64_MAX && + seq->param_int[3] != UINT64_MAX && + seq->param_int[4] != UINT64_MAX && + seq->param_int[5] != UINT64_MAX) { + struct ciolib_pixels *pix; + uint16_t crc; + int good = 0; + int vmode; + gettextinfo(&ti); + vmode = find_vmode(ti.currmode); + if (vmode != -1 && + (seq->param_int[3] > 0 && seq->param_int[3] < vparams[vmode].charwidth*cterm->width) && + (seq->param_int[2] > 0 && seq->param_int[2] < vparams[vmode].charwidth*cterm->width) && + (seq->param_int[5] > 0 && seq->param_int[5] < vparams[vmode].charwidth*cterm->width) && + (seq->param_int[4] > 0 && seq->param_int[4] < vparams[vmode].charwidth*cterm->width) && + (seq->param_int[2] <= seq->param_int[4]) && + (seq->param_int[3] <= seq->param_int[5]) && + (pix = getpixels( + (seq->param_int[3] - 1 + cterm->x)*vparams[vmode].charwidth, + (seq->param_int[2] - 1 + cterm->y)*vparams[vmode].charheight, + (seq->param_int[5] + cterm->x)*vparams[vmode].charwidth - 1, + (seq->param_int[4] + cterm->y)*vparams[vmode].charheight - 1)) != NULL) { + crc = crc16((void *)pix->pixels, sizeof(pix->pixels[0])*pix->width*pix->height); + good = 1; + freepixles(pix); + } + else { + size_t sz = sizeof(struct vmem_cell) * (seq->param_int[2] - seq->param_int[4] + 1) * (seq->param_int[3] - seq->param_int[5] + 1); + struct vmem_cell *vm = malloc(sz); + if (vm != NULL) { + vmem_gettext(seq->param_int[3], seq->param_int[2], seq->param_int[5], seq->param_int[4], vm); + crc = crc16((void *)vm, sz); + good = 1; + } + } + if (good) { + *tmp = 0; + snprintf(tmp, sizeof(tmp), "\x1bP%u!~%04x\x1b\\", (unsigned)seq->param_int[0], crc); + if(*tmp && strlen(retbuf) + strlen(tmp) < retsize) + strcat(retbuf, tmp); + } + } + } + } else if (strcmp(seq->ctrl_func, "*z") == 0) { if (seq->param_count > 0 && seq->param_int[0] <= 63) { if (cterm->macros[seq->param_int[0]]) { diff --git a/src/conio/cterm.txt b/src/conio/cterm.txt index 44c4a95546..9834030086 100644 --- a/src/conio/cterm.txt +++ b/src/conio/cterm.txt @@ -1013,16 +1013,21 @@ CSI = Ps n (CTSMRR) SOURCE: CTerm only. -CSI ? Ps n (DECDSR) +CSI ? Ps [ ; Pn ] n (DECDSR) - When Ps is 62 (DECMSR), CTerm will respond with a Mode Report of - the form + When Ps is 62 (DECMSR) and there is no Pn, CTerm will respond + with a Mode Report of the form CSI 32767 * { This indicates that 524,272 bytes are available for macro storage. This is not actually true, SyncTERM will use all available memory for macro storage, but some software checks this value, and some parsers don't allow more than INT16_MAX parameter values. + When Ps is 63 (DECCKSR) Pn defaults to 1, and CTerm will respond + with a checksum of the defined macros in the form + DCS Pn ! xxxx ST + Where xxxx is the hex checksum. + SOURCE: VT420 CSI Pn1 ; Pn2 r (DECSTBM) @@ -1133,6 +1138,20 @@ CSI 2 $ w (DECTABSR) SOURCE: VT320 +CSI Pn1 ; Ps ; Pn2 ; Pn3 ; Pn4 ; Pn5 * y (DECRQCRA) + Request Checksum of Rectangular Area + Returns a checksum for the specified rectangular area. + Pn1 is an ID that is returned in the response. + Ps MUST be 1 + Pn2 specifies the top row of the rectangle + Pn3 specifies the left column of the rectangle + Pn4 specifies the bottom row of the rectangle + Pn5 specifies the right column of the rectangle + The return value is in the format of DCS Pn1 ! ~ xxxx ST + Where xxxx is the hex value of the checksum. + + Source: VT420 + CSI Pn * z Invoke Macro (DECINVM) Invokes a macro. -- GitLab