static void prop_callback(void *opaque, prop_event_t event, ...) { glw_keyintercept_t *ki = opaque; const char *str; prop_t *p; int c; va_list ap; va_start(ap, event); switch(event) { case PROP_SET_VOID: ki->buflen = 0; str = NULL; p = va_arg(ap, prop_t *); break; case PROP_SET_RSTRING: str = rstr_get(va_arg(ap, const rstr_t *)); ki->buflen = 0; while((c = utf8_get(&str)) != 0 && ki->buflen < 64) ki->buf[ki->buflen++] = c; p = va_arg(ap, prop_t *); break; default: return; } prop_ref_dec(ki->prop); ki->prop = prop_ref_inc(p); }
static int hc_utf8(http_connection_t *hc, const char *remain, void *opaque, http_cmd_t method) { const char *str = http_arg_get_req(hc, "str"); int c; event_t *e; if(str == NULL) return HTTP_STATUS_BAD_REQUEST; while((c = utf8_get(&str)) != 0) { switch(c) { case 8: e = event_create_action_multi( (const action_type_t[]){ ACTION_BS, ACTION_NAV_BACK}, 2); break; default: e = event_create_int(EVENT_UNICODE, c); break; } event_to_ui(e); }
static uns uni_parser(byte *c, u16 *up) { uns u; byte *cc = (byte*)utf8_get(c, &u); if (*cc || u == UNI_REPLACEMENT) { for (uns i=0; i<4; i++) if (!Cxdigit(c[i])) return 1; else u = (u << 4) | Cxvalue(c[i]); if (c[4]) return 1; } *up = u; return 0; }
static int json_str_read_char(const char **ptr) { const char *s = *ptr; if(*s == 0) return -1; if(*s != '\\') return utf8_get(ptr); s++; *ptr = s + 1; int v = 0, i; switch(*s) { default: return *s; case 0: return -1; case 'b': return '\b'; case 'f': return '\f'; case 'n': return '\n'; case 'r': return '\r'; case 't': return '\t'; case 'u': s++; for(i = 0; i < 4; i++) { v = v << 4; if (*s >= '0' && *s <= '9') v |= *s - '0'; else if (*s >= 'a' && *s <= 'f') v |= *s - 'a' + 10; else if (*s >= 'A' && *s <= 'F') v |= *s - 'F' + 10; else return -2; s++; } *ptr = s; return v; } }
static int glw_text_bitmap_event(glw_t *w, event_t *e) { glw_text_bitmap_t *gtb = (glw_text_bitmap_t *)w; if(event_is_action(e, ACTION_BS)) { del_char(gtb); gtb_notify(gtb); return 1; } else if(event_is_type(e, EVENT_UNICODE)) { event_int_t *eu = (event_int_t *)e; if(insert_char(gtb, eu->val)) gtb_notify(gtb); return 1; } else if(event_is_type(e, EVENT_INSERT_STRING)) { event_payload_t *ep = (event_payload_t *)e; const char *str = ep->payload; int uc; while((uc = utf8_get(&str)) != 0) { insert_char(gtb, uc); } gtb_notify(gtb); return 1; } else if(event_is_action(e, ACTION_LEFT)) { if(gtb->gtb_edit_ptr > 0) { gtb->gtb_edit_ptr--; gtb->gtb_update_cursor = 1; } return 1; } else if(event_is_action(e, ACTION_RIGHT)) { if(gtb->gtb_edit_ptr < gtb->gtb_uc_len) { gtb->gtb_edit_ptr++; gtb->gtb_update_cursor = 1; } return 1; } else if(event_is_action(e, ACTION_ACTIVATE) || event_is_action(e, ACTION_ITEMMENU)) { gtb_caption_refresh(gtb); if(gtb->gtb_flags & (GTB_FILE_REQUEST | GTB_DIR_REQUEST)) { if(gtb->gtb_p == NULL) { TRACE(TRACE_ERROR, "GLW", "File requests on unbound widgets is not supported"); } else { int flags = (gtb->gtb_flags & GTB_FILE_REQUEST ? FILEPICKER_FILES : 0) | (gtb->gtb_flags & GTB_DIR_REQUEST ? FILEPICKER_DIRECTORIES : 0); filepicker_pick_to_prop(gtb->gtb_description, gtb->gtb_p, gtb->gtb_caption, flags); } } else { if(event_is_action(e, ACTION_ACTIVATE) && e->e_flags & EVENT_MOUSE) return 1; w->glw_root->gr_open_osk(w->glw_root, gtb->gtb_description, gtb->gtb_caption, w, gtb->gtb_flags & GTB_PASSWORD); } return 1; } return 0; }
/*---------------------------------------------------------------------- Prepend config'd commands to keyboard input Args: ch -- pointer to storage for returned command Returns: TRUE if we're passing back a useful command, FALSE otherwise ---*/ int process_config_input(UCS *ch) { static char firsttime = (char) 1; int c; unsigned long octets_so_far, remaining_octets, ret = 0; unsigned char *inputp; UCS ucs; unsigned char inputbuf[20]; /* commands in config file */ if(ps_global->initial_cmds && *ps_global->initial_cmds) { /* * There are a few commands that may require keyboard input before * we enter the main command loop. That input should be interactive, * not from our list of initial keystrokes. */ if(ps_global->dont_use_init_cmds) return(ret); c = *ps_global->initial_cmds++; /* * Use enough bytes to make up a character and convert it to UCS-4. */ if(c < 0x80 || c > KEY_BASE){ *ch = (UCS) c; ret = 1; } else{ memset(inputbuf, 0, sizeof(inputbuf)); inputbuf[0] = (0xff & c); octets_so_far = 1; while(!ret){ remaining_octets = octets_so_far; inputp = inputbuf; ucs = (UCS) utf8_get(&inputp, &remaining_octets); switch(ucs){ case U8G_ENDSTRG: /* incomplete character, wait */ case U8G_ENDSTRI: /* incomplete character, wait */ if(!*ps_global->initial_cmds || octets_so_far >= sizeof(inputbuf)){ *ch = BADESC; ret = 1; } else inputbuf[octets_so_far++] = (0xff & *ps_global->initial_cmds++); break; default: if(ucs & U8G_ERROR || ucs == UBOGON) *ch = BADESC; else *ch = ucs; ret = 1; break; } } } if(!*ps_global->initial_cmds && ps_global->free_initial_cmds){ fs_give((void **) &ps_global->free_initial_cmds); ps_global->initial_cmds = NULL; } return(ret); } if(firsttime) { firsttime = 0; if(ps_global->in_init_seq) { ps_global->in_init_seq = 0; ps_global->save_in_init_seq = 0; clear_cursor_pos(); F_SET(F_USE_FK,ps_global,ps_global->orig_use_fkeys); /* draw screen */ *ch = (UCS) ctrl('L'); return(1); } } return(0); }
static int parse_str(uint32_t *output, const char *str, int flags) { int olen = 0, c, p = -1, d; int l = strlen(str); char *tmp = NULL; while((c = utf8_get(&str)) != 0) { if(c == '\r') continue; if(flags & TEXT_PARSE_TAGS && c == '<') { int lp = 0; if(tmp == NULL) tmp = malloc(l); while((d = utf8_get(&str)) != 0) { if(d == '>') break; tmp[lp++] = d; } if(d == 0) break; tmp[lp] = 0; olen = tag_to_code(tmp, output, olen); continue; } if(flags & TEXT_PARSE_HTML_ENTETIES && c == '&') { int lp = 0; if(tmp == NULL) tmp = malloc(l); while((d = utf8_get(&str)) != 0) { if(d == ';') break; tmp[lp++] = d; } if(d == 0) break; tmp[lp] = 0; c = html_entity_lookup(tmp); if(c != -1) { if(output != NULL) output[olen] = c; olen++; } continue; } if(p != -1 && (d = unicode_compose(p, c)) != -1) { if(output != NULL) output[olen-1] = d; p = -1; } else { p = c; if(output != NULL) output[olen] = c; olen++; } } free(tmp); return olen; }
/*---------------------------------------------------------------------- Write a character to the screen, keeping track of cursor position Args: ch -- character to output. The stream of characters coming to this function is expected to be UTF-8. State is kept between calls in order to collect up the octets needed for a single Unicode character. Result: character output cursor position variables updated ----*/ void Writechar(unsigned int ch, int new_esc_len) { static unsigned char cbuf[6]; static unsigned char *cbufp = cbuf; if(cbufp < cbuf+sizeof(cbuf)){ unsigned char *inputp; unsigned long remaining_octets; UCS ucs; *cbufp++ = (unsigned char) ch; inputp = cbuf; remaining_octets = (cbufp - cbuf) * sizeof(unsigned char); ucs = (UCS) utf8_get(&inputp, &remaining_octets); switch(ucs){ case U8G_ENDSTRG: /* incomplete character, wait */ case U8G_ENDSTRI: /* incomplete character, wait */ break; default: if(ucs & U8G_ERROR || ucs == UBOGON){ /* * None of these cases is supposed to happen. If it * does happen then the input stream isn't UTF-8 * so something is wrong. Treat each character in the * input buffer as a separate error character and * print a '?' for each. */ for(inputp = cbuf; inputp < cbufp; inputp++){ int width = 0; if(_col + width <= ps_global->ttyo->screen_cols){ Writewchar('?'); width++; } } cbufp = cbuf; /* start over */ } else{ /* got a good character */ Writewchar(ucs); /* update the input buffer */ if(inputp >= cbufp) /* this should be the case */ cbufp = cbuf; else{ /* extra chars for some reason? */ unsigned char *q, *newcbufp; newcbufp = (cbufp - inputp) + cbuf; q = cbuf; while(inputp < cbufp) *q++ = *inputp++; cbufp = newcbufp; } } break; } } else{ /* error */ Writewchar('?'); cbufp = cbuf; /* start over */ } }
/* * pico_writec - write a char into picotext and advance pointers. * Up to calling routines to keep track of total chars * written. * Incoming text (c) is UTF-8 and written chars are UCS-4. * We need to collect up multiple chars to make a single * UCS-4 char, so there needs to be some state between calls. */ int pico_writec(void *w, int c, int flags) { int rv = 0; if(c == '\r') /* ignore CR's */ rv++; /* so fake it */ else if(c == '\n'){ /* insert newlines on LF */ /* * OK, if there are characters on the current line or * dotp is pointing to the delimiter line, insert a newline * No here's the tricky bit; preserve the implicit EOF newline. */ if(lforw(PT(w)->dotp) == PT(w)->linep && PT(w)->dotp != PT(w)->linep){ PT(w)->dotp = PT(w)->linep; PT(w)->doto = 0; } else{ register LINE *lp; if((lp = lalloc(0)) == NULL){ emlwrite("Can't allocate space for more characters",NULL); return(0); } if(PT(w)->dotp == PT(w)->linep){ lforw(lp) = PT(w)->linep; lback(lp) = lback(PT(w)->linep); lforw(lback(lp)) = lback(PT(w)->linep) = lp; } else{ lforw(lp) = lforw(PT(w)->dotp); lback(lp) = PT(w)->dotp; lback(lforw(lp)) = lforw(PT(w)->dotp) = lp; PT(w)->dotp = lp; PT(w)->doto = 0; } } rv++; } else{ if(flags & PICOREADC_NOUCS){ /* * With this flag we're reverting to the old behavior where no * UTF-8 to UCS-4 translation takes place. We assume nothing * about the incoming byte stream. We just write a byte at a * time. So even though it's being stored in PT each * item is really limited to a single octet value. */ rv = geninsert(&PT(w)->dotp, &PT(w)->doto, PT(w)->linep, c, 0, 1, NULL); } else{ static unsigned char cbuf[6]; static unsigned char *cbufp = cbuf; UCS obuf[MAX(MB_LEN_MAX,32)]; int i, outchars = 0; if(cbufp < cbuf+sizeof(cbuf)){ unsigned char *inputp; unsigned long remaining_octets; UCS ucs; *cbufp++ = (unsigned char) c; inputp = cbuf; remaining_octets = (cbufp - cbuf) * sizeof(unsigned char); ucs = (UCS) utf8_get(&inputp, &remaining_octets); switch(ucs){ case U8G_ENDSTRG: /* incomplete character, wait */ case U8G_ENDSTRI: /* incomplete character, wait */ break; default: if(ucs & U8G_ERROR || ucs == UBOGON){ /* * None of these cases is supposed to happen. If it * does happen then the input stream isn't UTF-8 * so something is wrong. Treat each character in the * input buffer as a separate error character and * print a '?' for each. */ for(inputp = cbuf; inputp < cbufp; inputp++) obuf[outchars++] = '?'; cbufp = cbuf; } else{ /* got a character */ if(ucs >= 0x80 && wcellwidth(ucs) < 0){ /* * This happens when we have a UTF-8 character that * we aren't able to print in our locale. For example, * if the locale is setup with the terminal * expecting ISO-8859-1 characters then there are * lots of UTF-8 characters that can't be printed. * Print a '?' instead. This may be the wrong thing to do. What happens if user is just forwarding and doesn't edit. We are going to lose the original value, aren't we? Maybe we do this only when printing to the screen instead. */ obuf[outchars++] = '?'; } else{ /* * A regular ucs character */ obuf[outchars++] = ucs; } /* update the input buffer */ if(inputp >= cbufp) /* this should be the case */ cbufp = cbuf; else{ /* extra chars for some reason? */ unsigned char *q, *newcbufp; newcbufp = (cbufp - inputp) + cbuf; q = cbuf; while(inputp < cbufp) *q++ = *inputp++; cbufp = newcbufp; } } break; } } else{ /* error */ obuf[0] = '?'; outchars = 1; cbufp = cbuf; /* start over */ } /* * Unless we have trouble translating outchars will be * either 1 or 0. It is the UCS-4 character that we converted * the input to. It's an array just so it can hold ? when * there is trouble. */ rv = 1; for(i = 0; rv && i < outchars; i++) if(!geninsert(&PT(w)->dotp, &PT(w)->doto, PT(w)->linep, obuf[i], 0, 1, NULL)) rv = 0; } } /* * Warning, this is no longer number written, because when we have a * multibyte UTF-8 character we won't write anything until we get all * the bytes. */ return((rv) ? 1 : 0); /* return number written */ }