printg() { int oldvid = _video; int c, c2; if (oldvid==INVERSE) togvid(); sync(); escseq(NONE); outstr("\33&p4d5u0C"); outchar('\21'); /* test handshaking fix */ /* * The terminal sometimes sends back S<cr> or F<cr>. * Ignore them. */ fflush(stdout); c = getchar(); if (c=='F' || c=='S') { c2 = getchar(); if (c2 != '\r' && c2 != '\n') ungetc(c2, stdin); } else { ungetc(c, stdin); } if (oldvid==INVERSE) togvid(); }
rawchar() { char c; sync(); escseq(NONE); fflush(stdout); if (_pb_front && _on2648) { c = *_pb_front++; #ifdef TRACE if (trace) fprintf(trace, "%s from queue, front=%d, back=%d\n", rdchar(c), _pb_front-_pushback, _pb_back-_pushback); #endif if (_pb_front > _pb_back) { _pb_front = _pb_back = NULL; #ifdef TRACE if (trace) fprintf(trace, "reset pushback to null\n"); #endif } return (c); } _outcount = 0; c = getchar(); #ifdef TRACE if (trace) fprintf(trace, "rawchar '%s'\n", rdchar(c)); #endif return (c); }
curoff() { if (!_cursoron) return; sync(); escseq(ESCD); outchar('l'); _cursoron = 0; }
curon() { if (_cursoron) return; sync(); escseq(ESCD); outchar('k'); _cursoron = 1; }
textoff() { sync(); /* * The following is needed because going into text mode * leaves the pen where the cursor last was. */ _penx = -40; _peny = 40; escseq(ESCP); outchar('a'); motion(_supx, _supy); _penx = _supx; _peny = _supy; }
sync() { if (_supx != _penx || _supy != _peny) { escseq(ESCP); outchar('a'); motion(_supx, _supy); } if (_supsmode != _actsmode) { escseq(ESCM); switch (_actsmode = _supsmode) { case MX: outchar('3'); break; case MC: outchar('1'); break; case MS: outchar('2'); break; } outchar('a'); } }
/* parse_cmd: split cmdstr into argv of c */ int parse_cmd(char *cmdstr, struct command *c) { int i; char *s; c->argc = 0; for (s = cmdstr; *s; ++s) { switch (*s) { case '\\': if (!escseq(s)) return 0; break; case '\'': case '"': if (!(s = readquotes(s))) return 0; break; case ' ': case '\t': c->argc++; *s = '\0'; break; default: break; } } c->argc++; c->argv = malloc((c->argc + 1) * sizeof(*(c->argv))); s = cmdstr; for (i = 0; i < c->argc; ++i) { c->argv[i] = s; s = strchr(s, '\0') + 1; } c->argv[i] = NULL; err[0] = '\0'; return 1; }
texton() { sync(); escseq(TEXT); }
/* * reads a configuration file and constructs the configuration data * * A tricky construct using do-while for reading lines from a file is to allow for a configuration * file that does not end with a newline. Asserting that BUFLEN is greater than 1 is necessary to * prevent fgets() from returning an empty string even if there are still characters unread. * TODO: * - some adjustment on arguments to table_new() is necessary */ size_t (conf_init)(FILE *fp, int ctrl) { char *p; size_t buflen, len; size_t lineno, nlineno; const char *hkey; table_t *tab; struct valnode_t *pnode; assert(fp); assert(preset || !section); assert(!current); assert(BUFLEN > 1); if (!preset) { control = ctrl; /* if preset, ctrl ignored */ section = table_new(0, NULL, NULL); } tab = NULL; errcode = CONF_ERR_OK; lineno = nlineno = 0; len = 0; p = MEM_ALLOC(buflen=BUFLEN); *p = '\0'; do { assert(buflen - len > 1); fgets(p+len, buflen-len, fp); if (ferror(fp)) { errcode = CONF_ERR_IO; break; } len += strlen(p+len); if (len == 0) /* EOF and no remaining data */ break; if (len > 2 && p[len-2] == '\\' && p[len-1] == '\n') { /* line splicing */ int c; nlineno++; len -= 2; if (len > 0 && isspace(p[len-1])) { while (--len > 0 && isspace(p[len-1])) continue; p[len++] = ' '; } if ((c = getc(fp)) != EOF && c != '\n' && isspace(c)) { if (p[len-1] != ' ') p[len++] = ' '; while ((c = getc(fp)) != EOF && c != '\n' && isspace(c)) continue; } else if (c == EOF) { /* no following line for slicing */ lineno += nlineno; errcode = CONF_ERR_BSLASH; goto retcode; } ungetc(c, fp); p[len] = '\0'; /* at worst, backslash is replaced with space and newline with null, thus room for two characters, which guarantees buflen-len greater than 1 */ } else if (p[len-1] == '\n' || feof(fp)) { /* line completed */ int type; char *s, *t, *var, *val; lineno++; if (p[len-1] == '\n') p[--len] = '\0'; /* in fact, no need to adjust len */ var = triml(p); switch(*var) { case '[': /* section specification */ cmtrem(++var); s = strchr(var, ']'); if (!s) { errcode = CONF_ERR_LINE; goto retcode; } *s = '\0'; if (sepunit(var, &var) != CONF_ERR_OK) goto retcode; /* sepunit sets errcode */ hkey = hash_string((control & CONF_OPT_CASE)? var: lower(var)); tab = table_get(section, hkey); if (!tab) { if (preset) { errcode = CONF_ERR_SEC; goto retcode; } tab = table_new(0, NULL, NULL); } table_put(section, hkey, tab); /* no break */ case '\0': /* empty line */ case '#': /* comment-only line */ case ';': break; /* reuses existing buffer */ default: /* variable = value */ val = p + strcspn(p, "#;"); s = strchr(var, '='); if (!s || val < s) { errcode = CONF_ERR_LINE; goto retcode; } *s = '\0'; if (sepunit(var, &var) != CONF_ERR_OK) goto retcode; /* sepunit() sets errcode */ if (*(unsigned char *)var == '\0') { /* empty variable name */ errcode = CONF_ERR_VAR; goto retcode; } val = triml(++s); if (*val == '"' || *val == '\'') { /* quoted */ char end = *val; /* remembers for match */ t = s = ++val; /* starts copying from s to t */ do { switch(*s) { case '\\': /* escape sequence */ if (control & CONF_OPT_ESC) *(unsigned char *)t++ = escseq(*(unsigned char *)++s); else { *t++ = '\\'; *(unsigned char *)t++ = *(unsigned char *)++s; } break; case '\0': /* unclosed ' or " */ errcode = CONF_ERR_LINE; goto retcode; case '\'': case '\"': if (*s == end) { *t = '\0'; break; } /* no break */ default: /* literal copy */ *(unsigned char *)t++ = *(unsigned char *)s; break; } s++; } while(*(unsigned char *)t != '\0'); /* checks if any trailing invalid char */ cmtrem(s); trimt(s); if (*(unsigned char *)s != '\0') { errcode = CONF_ERR_LINE; goto retcode; } } else { /* unquoted */ cmtrem(val); trimt(val); } if (!tab) { /* global section */ hkey = hash_string(""); tab = table_get(section, hkey); if (!tab) { if (preset) { errcode = CONF_ERR_SEC; goto retcode; } tab = table_new(0, NULL, NULL); } table_put(section, hkey, tab); } hkey = hash_string((control & CONF_OPT_CASE)? var: lower(var)); if (preset) { pnode = table_get(tab, hkey); if (!pnode) { errcode = CONF_ERR_VAR; goto retcode; } type = pnode->type; } else type = CONF_TYPE_STR; MEM_NEW(pnode); pnode->freep = p; pnode->type = type; pnode->val = val; pnode = table_put(tab, hkey, pnode); if (pnode) { /* value overwritten, thus free */ MEM_FREE(pnode->freep); MEM_FREE(pnode); } p = MEM_ALLOC(buflen=BUFLEN); /* uses new buffer */ break; } len = 0; *p = '\0'; lineno += nlineno; /* adjusts line number */ nlineno = 0; } else /* expands buffer */ MEM_RESIZE(p, buflen+=BUFLEN); } while(!feof(fp)); retcode: MEM_FREE(p); return (errcode != CONF_ERR_OK)? lineno: 0; }