static TermKeyResult peekkey(TermKey *tk, void *info, TermKeyKey *key, int force, size_t *nbytep) { if(tk->buffcount == 0) return tk->is_closed ? TERMKEY_RES_EOF : TERMKEY_RES_NONE; TermKeyCsi *csi = info; // Now we're sure at least 1 byte is valid unsigned char b0 = CHARAT(0); if(b0 == 0x1b && tk->buffcount > 1 && CHARAT(1) == '[') { return peekkey_csi(tk, csi, 2, key, force, nbytep); } else if(b0 == 0x1b && tk->buffcount > 1 && CHARAT(1) == 'O') { return peekkey_ss3(tk, csi, 2, key, force, nbytep); } else if(b0 == 0x8f) { return peekkey_ss3(tk, csi, 1, key, force, nbytep); } else if(b0 == 0x9b) { return peekkey_csi(tk, csi, 1, key, force, nbytep); } else return TERMKEY_RES_NONE; }
static const char * next_patt(register const char *pattern, int advance) { wchar_t __nlh_char[1]; if (CHARAT(pattern) == '[') { int ch; const char *pp = pattern; ADVANCE(pp); if (CHARAT(pp) == '^') ADVANCE(pp); if (CHARAT(pp) == ']') ADVANCE(pp); char const *np; for (; (ch = next_char(pp, &np)) != '\0'; pp = np) if (ch == ']') return (advance ? np : pp); } next_char(pattern, &pattern); return pattern; }
EC_API const char *ec_string_tokenize( const char **sepp, EcInt *tokenlen, char delim ) { const char *tok_s; EcBool last; #define CHARPTR(pptr) (*(pptr)) #define CHARAT(pptr) (*CHARPTR(pptr)) if (! sepp) return NULL; if (! CHARPTR(sepp)) /* we have finished */ return NULL; tok_s = CHARPTR(sepp); last = FALSE; *tokenlen = 0; /* search */ if (CHARAT(sepp) == '\0') { /* empty last token */ last = TRUE; } else { CHARPTR(sepp) = strchr( CHARPTR(sepp), delim ); if (! CHARPTR(sepp)) { /* last token */ CHARPTR(sepp) = tok_s; while (CHARAT(sepp)) CHARPTR(sepp)++; last = TRUE; } } /* use token */ *tokenlen = CHARPTR(sepp) - tok_s; if (last) { CHARPTR(sepp) = NULL; /* indicate this is the last */ return tok_s; } /* update for next cycle */ CHARPTR(sepp)++; return tok_s; }
// stwpat returns a pointer to the first meta-character if the string // is a pattern, else NULL char * strwpat(register const char *pattern) { register int ch; register char *prev_pattern = (char *)pattern; wchar_t __nlh_char[1]; while ((ch = next_char(pattern, &pattern)) != '\0') { switch (ch) { case '*': return prev_pattern; case '?': return prev_pattern; case '[': { register const char *eop = next_patt(prev_pattern, 0); if (CHARAT(eop) == ']') return prev_pattern; break; } } prev_pattern = (char *)pattern; } return NULL; }
static void print_buffer(TermKey *tk) { int i; for(i = 0; i < tk->buffcount && i < 20; i++) fprintf(stderr, "%02x ", CHARAT(i)); if(tk->buffcount > 20) fprintf(stderr, "..."); }
static TermKeyResult peekkey_mouse(TermKey *tk, TermKeyKey *key, size_t *nbytep) { if(tk->buffcount < 3) return TERMKEY_RES_AGAIN; key->type = TERMKEY_TYPE_MOUSE; key->code.mouse[0] = CHARAT(0) - 0x20; key->code.mouse[1] = CHARAT(1) - 0x20; key->code.mouse[2] = CHARAT(2) - 0x20; key->code.mouse[3] = 0; key->modifiers = (key->code.mouse[0] & 0x1c) >> 2; key->code.mouse[0] &= ~0x1c; *nbytep = 3; return TERMKEY_RES_KEY; }
/* INLINE */ static int next_char(register const char *pattern, const char **cpp = NULL) { register int ret; wchar_t __nlh_char[1]; ret = pattern ? (int)CHARAT(pattern) : '\0'; if (ret != '\0') { ADVANCE(pattern); /* AIX needs line broken to get around macro bug (Temporary Fix) */ if (ret == '\\' && CHARAT(pattern) != '\0') ret = QUOTE | (int)CHARADV(pattern); } if (cpp != NULL) *cpp = pattern; return ret; }
void dump_world(struct plyr *p) { int i,j; for(i = 0; i < SZ_Y; i++){ move_cursor(p->fd, 0, i); for(j = 0; j < SZ_X; j++){ //printf("displaying char @ %d,%d :: %d\n", i,j, CHARAT(p,i,j)); write_byte(p->fd, CHARAT(p,j,i)); } } move_cursor(p->fd, p->x, p->y); }
/* * match will check to see if pattern can successfully be applied to * the beginning of string. */ static int match(register const char *pattern, register const char *string, int depth) { #ifdef DEBUG printf("%smatch(\"%s\", \"%s\")\n", TABS, pattern, string); #endif int ch; const char *cp; wchar_t __nlh_char[1]; while ((ch = next_char(pattern, &cp)) != '\0') { const char *laststr = string; register int testchar = (int)CHARADV(string); switch (ch) { case '*': { pattern = cp; /* skip over '*' */ string = laststr; /* reverse - testchar not used */ const char *s = string; do if (match(pattern, s, depth + 1)) return RETURN(1, depth); while (CHARADV(s) != '\0'); return RETURN(0, depth); } case '?': break; case '[': { int mt = match_class(pattern, testchar); if (mt == 0) return RETURN(0, depth); else if (mt == 2 && ch != testchar) return RETURN(0, depth); break; } default: if ((ch & ~QUOTE) != testchar) return RETURN(0, depth); break; } if (testchar == '\0') string = laststr; // reverse string pattern = next_patt(pattern); } return RETURN(CHARAT(string) == '\0', depth); }
void handle_player(int sock) { int z, prevx, prevy; struct plyr *p = malloc(sizeof(struct plyr)); p->fd = sock; p->x = p->y = p->lastdump = 0; p->worldx = p->worldy = 0; p->location = NULL; p->location = (struct loc *) get_world(p, 0,0); if(p->location == NULL) { printf("FAILED TO GET WORLD!\n"); close(p->fd); return; } startmsg(p->fd); while( read_byte(p->fd) == 0); dump_world(p); while(1){ prevx = p->x; prevy = p->y; //handle input if(handle_input(p)){ printf("disconnecting client\n"); break; } //display if(p->x != prevx || p->y != prevy) { //printf("trying to display @ %d, %d: %d\n", prevx, prevy, CHARAT(p,prevx, prevy)); write_byte(p->fd, CHARAT(p,prevx, prevy)); move_cursor(p->fd, p->x, p->y); //printf("now at %d,%d: %d\n",p->x,p->y, CHARAT(p,p->x,p->y)); } check_updates(p); } send(p->fd, "Goodbye\n", 8, 0); close(p->fd); }
static TermKeyResult peekkey_ss3(TermKey *tk, TermKeyCsi *csi, size_t introlen, TermKeyKey *key, int force, size_t *nbytep) { if(tk->buffcount < introlen + 1) { if(!force) return TERMKEY_RES_AGAIN; (*tk->method.emit_codepoint)(tk, 'O', key); key->modifiers |= TERMKEY_KEYMOD_ALT; *nbytep = tk->buffcount; return TERMKEY_RES_KEY; } unsigned char cmd = CHARAT(introlen); if(cmd < 0x40 || cmd >= 0x80) return TERMKEY_RES_NONE; key->type = csi->csi_ss3s[cmd - 0x40].type; key->code.sym = csi->csi_ss3s[cmd - 0x40].sym; key->modifiers = csi->csi_ss3s[cmd - 0x40].modifier_set; if(key->code.sym == TERMKEY_SYM_UNKNOWN) { if(tk->flags & TERMKEY_FLAG_CONVERTKP && csi->ss3_kpalts[cmd - 0x40]) { key->type = TERMKEY_TYPE_UNICODE; key->code.codepoint = csi->ss3_kpalts[cmd - 0x40]; key->modifiers = 0; key->utf8[0] = key->code.codepoint; key->utf8[1] = 0; } else { key->type = csi->ss3s[cmd - 0x40].type; key->code.sym = csi->ss3s[cmd - 0x40].sym; key->modifiers = csi->ss3s[cmd - 0x40].modifier_set; } } if(key->code.sym == TERMKEY_SYM_UNKNOWN) { #ifdef DEBUG fprintf(stderr, "CSI: Unknown SS3 %c (0x%02x)\n", cmd, cmd); #endif return TERMKEY_RES_NONE; } *nbytep = introlen + 1; return TERMKEY_RES_KEY; }
int handle_input(struct plyr *p){ int z; z = read_byte(p->fd); if(z == -1){ return 1; } if(z == 0 || z == 1) return 0; p->lastinput = time(NULL); printf("user input: @ (%d,%d) = %d\n",p->x,p->y,z); if(z == 0x1b){ handle_escapes(p); } else if(z == 253U) { read_byte(p->fd); //3 } else if(z == 255U){ read_byte(p->fd); //1 dump_world(p); } else if(z == 126 || z == 127) { move_left(p); set_byte(p, ' '); CHARAT(p,p->x,p->y) = ' '; } else if(z == 13) { move_down(p); } else if(z == 10){ } else { set_byte(p, z); move_right(p); } return 0; }
static void lz77_compress(struct LZ77Context *ctx, unsigned char *data, int len, int compress) { struct LZ77InternalContext *st = ctx->ictx; int i, hash, distance, off, nmatch, matchlen, advance; struct Match defermatch, matches[MAXMATCH]; int deferchr; assert(st->npending <= HASHCHARS); /* * Add any pending characters from last time to the window. (We * might not be able to.) * * This leaves st->pending empty in the usual case (when len >= * HASHCHARS); otherwise it leaves st->pending empty enough that * adding all the remaining 'len' characters will not push it past * HASHCHARS in size. */ for (i = 0; i < st->npending; i++) { unsigned char foo[HASHCHARS]; int j; if (len + st->npending - i < HASHCHARS) { /* Update the pending array. */ for (j = i; j < st->npending; j++) st->pending[j - i] = st->pending[j]; break; } for (j = 0; j < HASHCHARS; j++) foo[j] = (i + j < st->npending ? st->pending[i + j] : data[i + j - st->npending]); lz77_advance(st, foo[0], lz77_hash(foo)); } st->npending -= i; defermatch.distance = 0; /* appease compiler */ defermatch.len = 0; deferchr = '\0'; while (len > 0) { /* Don't even look for a match, if we're not compressing. */ if (compress && len >= HASHCHARS) { /* * Hash the next few characters. */ hash = lz77_hash(data); /* * Look the hash up in the corresponding hash chain and see * what we can find. */ nmatch = 0; for (off = st->hashtab[hash].first; off != INVALID; off = st->win[off].next) { /* distance = 1 if off == st->winpos-1 */ /* distance = WINSIZE if off == st->winpos */ distance = WINSIZE - (off + WINSIZE - st->winpos) % WINSIZE; for (i = 0; i < HASHCHARS; i++) if (CHARAT(i) != CHARAT(i - distance)) break; if (i == HASHCHARS) { matches[nmatch].distance = distance; matches[nmatch].len = 3; if (++nmatch >= MAXMATCH) break; } } } else { nmatch = 0; hash = INVALID; } if (nmatch > 0) { /* * We've now filled up matches[] with nmatch potential * matches. Follow them down to find the longest. (We * assume here that it's always worth favouring a * longer match over a shorter one.) */ matchlen = HASHCHARS; while (matchlen < len) { int j; for (i = j = 0; i < nmatch; i++) { if (CHARAT(matchlen) == CHARAT(matchlen - matches[i].distance)) { matches[j++] = matches[i]; } } if (j == 0) break; matchlen++; nmatch = j; } /* * We've now got all the longest matches. We favour the * shorter distances, which means we go with matches[0]. * So see if we want to defer it or throw it away. */ matches[0].len = matchlen; if (defermatch.len > 0) { if (matches[0].len > defermatch.len + 1) { /* We have a better match. Emit the deferred char, * and defer this match. */ ctx->literal(ctx, (unsigned char) deferchr); defermatch = matches[0]; deferchr = data[0]; advance = 1; } else { /* We don't have a better match. Do the deferred one. */ ctx->match(ctx, defermatch.distance, defermatch.len); advance = defermatch.len - 1; defermatch.len = 0; } } else { /* There was no deferred match. Defer this one. */ defermatch = matches[0]; deferchr = data[0]; advance = 1; } } else { /* * We found no matches. Emit the deferred match, if * any; otherwise emit a literal. */ if (defermatch.len > 0) { ctx->match(ctx, defermatch.distance, defermatch.len); advance = defermatch.len - 1; defermatch.len = 0; } else { ctx->literal(ctx, data[0]); advance = 1; } } /* * Now advance the position by `advance' characters, * keeping the window and hash chains consistent. */ while (advance > 0) { if (len >= HASHCHARS) { lz77_advance(st, *data, lz77_hash(data)); } else { assert(st->npending < HASHCHARS); st->pending[st->npending++] = *data; } data++; len--; advance--; } } }
static TermKeyResult peekkey_csi(TermKey *tk, TermKeyCsi *csi, size_t introlen, TermKeyKey *key, int force, size_t *nbytep) { size_t csi_end = introlen; while(csi_end < tk->buffcount) { if(CHARAT(csi_end) >= 0x40 && CHARAT(csi_end) < 0x80) break; csi_end++; } if(csi_end >= tk->buffcount) { if(!force) return TERMKEY_RES_AGAIN; (*tk->method.emit_codepoint)(tk, '[', key); key->modifiers |= TERMKEY_KEYMOD_ALT; *nbytep = introlen; return TERMKEY_RES_KEY; } unsigned char cmd = CHARAT(csi_end); long arg[16]; char present = 0; int args = 0; size_t p = introlen; // Now attempt to parse out up number;number;... separated values while(p < csi_end) { unsigned char c = CHARAT(p); if(c >= '0' && c <= '9') { if(!present) { arg[args] = c - '0'; present = 1; } else { arg[args] = (arg[args] * 10) + c - '0'; } } else if(c == ';') { if(!present) arg[args] = -1; present = 0; args++; if(args > 16) break; } p++; } if(!present) arg[args] = -1; args++; if(args > 1 && arg[1] != -1) key->modifiers = arg[1] - 1; else key->modifiers = 0; if(cmd == '~') { key->type = TERMKEY_TYPE_KEYSYM; if(arg[0] == 27) { int mod = key->modifiers; (*tk->method.emit_codepoint)(tk, arg[2], key); key->modifiers |= mod; } else if(arg[0] >= 0 && arg[0] < csi->ncsifuncs) { key->type = csi->csifuncs[arg[0]].type; key->code.sym = csi->csifuncs[arg[0]].sym; key->modifiers &= ~(csi->csifuncs[arg[0]].modifier_mask); key->modifiers |= csi->csifuncs[arg[0]].modifier_set; } else key->code.sym = TERMKEY_SYM_UNKNOWN; if(key->code.sym == TERMKEY_SYM_UNKNOWN) { #ifdef DEBUG fprintf(stderr, "CSI: Unknown function key %ld\n", arg[0]); #endif return TERMKEY_RES_NONE; } } else if(cmd == 'u') { int mod = key->modifiers; key->type = TERMKEY_TYPE_KEYSYM; (*tk->method.emit_codepoint)(tk, arg[0], key); key->modifiers |= mod; } else if(cmd == 'M') { size_t csi_len = csi_end + 1; tk->buffstart += csi_len; tk->buffcount -= csi_len; TermKeyResult mouse_result = (*tk->method.peekkey_mouse)(tk, key, nbytep); tk->buffstart -= csi_len; tk->buffcount += csi_len; if(mouse_result == TERMKEY_RES_KEY) *nbytep += csi_len; return mouse_result; } else { // We know from the logic above that cmd must be >= 0x40 and < 0x80 key->type = csi->csi_ss3s[cmd - 0x40].type; key->code.sym = csi->csi_ss3s[cmd - 0x40].sym; key->modifiers &= ~(csi->csi_ss3s[cmd - 0x40].modifier_mask); key->modifiers |= csi->csi_ss3s[cmd - 0x40].modifier_set; if(key->code.sym == TERMKEY_SYM_UNKNOWN) { #ifdef DEBUG switch(args) { case 1: fprintf(stderr, "CSI: Unknown arg1=%ld cmd=%c\n", arg[0], cmd); break; case 2: fprintf(stderr, "CSI: Unknown arg1=%ld arg2=%ld cmd=%c\n", arg[0], arg[1], cmd); break; case 3: fprintf(stderr, "CSI: Unknown arg1=%ld arg2=%ld arg3=%ld cmd=%c\n", arg[0], arg[1], arg[2], cmd); break; default: fprintf(stderr, "CSI: Unknown arg1=%ld arg2=%ld arg3=%ld ... args=%d cmd=%c\n", arg[0], arg[1], arg[2], args, cmd); break; } #endif return TERMKEY_RES_NONE; } } *nbytep = csi_end + 1; return TERMKEY_RES_KEY; }
static TermKeyResult peekkey_simple(TermKey *tk, TermKeyKey *key, int force, size_t *nbytep) { if(tk->buffcount == 0) return tk->is_closed ? TERMKEY_RES_EOF : TERMKEY_RES_NONE; unsigned char b0 = CHARAT(0); if(b0 == 0x1b) { // Escape-prefixed value? Might therefore be Alt+key if(tk->buffcount == 1) { // This might be an <Esc> press, or it may want to be part of a longer // sequence if(!force) return TERMKEY_RES_AGAIN; (*tk->method.emit_codepoint)(tk, b0, key); *nbytep = 1; return TERMKEY_RES_KEY; } // Try another key there tk->buffstart++; tk->buffcount--; // Run the full driver TermKeyResult metakey_result = peekkey(tk, key, force, nbytep); tk->buffstart--; tk->buffcount++; switch(metakey_result) { case TERMKEY_RES_KEY: key->modifiers |= TERMKEY_KEYMOD_ALT; (*nbytep)++; break; case TERMKEY_RES_NONE: case TERMKEY_RES_EOF: case TERMKEY_RES_AGAIN: case TERMKEY_RES_ERROR: break; } return metakey_result; } else if(b0 < 0xa0) { // Single byte C0, G0 or C1 - C1 is never UTF-8 initial byte (*tk->method.emit_codepoint)(tk, b0, key); *nbytep = 1; return TERMKEY_RES_KEY; } else if(tk->flags & TERMKEY_FLAG_UTF8) { // Some UTF-8 long codepoint; TermKeyResult res = parse_utf8(tk->buffer + tk->buffstart, tk->buffcount, &codepoint, nbytep); if(res == TERMKEY_RES_AGAIN && force) { /* There weren't enough bytes for a complete UTF-8 sequence but caller * demands an answer. About the best thing we can do here is eat as many * bytes as we have, and emit a UTF8_INVALID. If the remaining bytes * arrive later, they'll be invalid too. */ codepoint = UTF8_INVALID; *nbytep = tk->buffcount; res = TERMKEY_RES_KEY; } key->type = TERMKEY_TYPE_UNICODE; key->modifiers = 0; (*tk->method.emit_codepoint)(tk, codepoint, key); return res; } else { // Non UTF-8 case - just report the raw byte key->type = TERMKEY_TYPE_UNICODE; key->code.codepoint = b0; key->modifiers = 0; key->utf8[0] = key->code.codepoint; key->utf8[1] = 0; *nbytep = 1; return TERMKEY_RES_KEY; } }
static int match_class(register const char *clss, register char testchar) /* * pattern is a pointer to the leading [ of * a shell-type class. testchar is the character to match against * the class. */ { int match = 1; /* false if first char is '!' */ wchar_t __nlh_char[1]; /* find end of class, ie an un-escaped ']' */ register const char *eop = next_patt(clss, 0); ADVANCE(clss); if (CHARAT(eop) != ']') return 2; if (CHARAT(clss) == '!') { match = 0; ADVANCE(clss); } while (clss < eop) { register int ch = next_char(clss, &clss); char const *clss_end = clss; int sep = next_char(clss_end, &clss_end); int ch2 = next_char(clss_end, &clss_end); /* check if next three chars are a range */ if (sep == '-' && ch2 != ']') { /* check range - we have to use strcoll to do it right */ char c1[MB_LEN_MAX+1], c2[MB_LEN_MAX+1], tc[MB_LEN_MAX+1]; memset(c1, 0, sizeof(c1)); memset(c2, 0, sizeof(c2)); memset(tc, 0, sizeof(tc)); ch &= ~QUOTE; WCHAR(ch, c1); ch2 &= ~QUOTE; WCHAR(ch2, c2); WCHAR(testchar, tc); /* if (ch <= testchar && testchar <= ch2) // Original code */ /* Second implementation: * if (nl_strncmp(c1, tc, 1) <= 0 && nl_strncmp(tc, c2, 1) <= 0) * return match; */ /* Third, portable implementation: */ if (strcoll(c1, tc) <= 0 && strcoll(tc, c2) <= 0) return match; clss = clss_end; } else /* they are not a range, check simple match */ { if ((ch & ~QUOTE) == testchar) return match; } } return !match; }
int set_byte(struct plyr *p, unsigned int val) { CHARAT(p,p->x,p->y) = val; p->lastdump = p->location->mtime + 1; p->location->mtime = p->location->mtime + 1; }