/** * @brief Gets the number of characters in text that fit into width. * * @param ft_font Font to use. * @param text Text to check. * @param width Width to match. * @return Number of characters that fit. */ int gl_printWidthForText( const glFont *ft_font, const char *text, const int width ) { int lastspace; size_t i; uint32_t ch; GLfloat n; if (ft_font == NULL) ft_font = &gl_defFont; glFontStash *stsh = gl_fontGetStash( ft_font ); /* limit size per line */ lastspace = 0; /* last ' ' or '\n' in the text */ n = 0.; /* current width */ i = 0; /* current position */ while ((text[i] != '\n') && (text[i] != '\0')) { /* Characters we should ignore. */ if (text[i] == '\t') { i++; continue; } /* Ignore escape sequence. */ if (text[i] == '\a') { if (text[i+1] != '\0') i += 2; else i += 1; continue; } /* Save last space. */ if (text[i] == ' ') lastspace = i; ch = u8_nextchar( text, &i ); /* Unicode. */ glFontGlyph *glyph = gl_fontGetGlyph( stsh, ch ); if (glyph!=NULL) n += glyph->adv_x; /* Check if out of bounds. */ if (n > (GLfloat)width) { if (lastspace > 0) return lastspace; else { u8_dec( text, &i ); return i; } } } return i; }
/** * @brief Limits the text to max. * * @param ft_font Font to calculate width with. * @param width Actual width it takes up. * @param text Text to parse. * @param max Max to look for. * @return Number of characters that fit. */ static size_t font_limitSize( glFontStash *ft_font, int *width, const char *text, const int max ) { int n; size_t i; uint32_t ch; int adv_x; /* Avoid segfaults. */ if ((text == NULL) || (text[0]=='\0')) return 0; /* limit size */ i = 0; n = 0; while ((ch = u8_nextchar( text, &i ))) { /* Ignore escape sequence. */ if (ch == '\a') { if (text[i] != '\0') i++; continue; } /* Count length. */ glFontGlyph *glyph = gl_fontGetGlyph( ft_font, ch ); adv_x = glyph->adv_x; /* See if enough room. */ n += adv_x; if (n > max) { u8_dec( text, &i ); n -= adv_x; /* actual size */ break; } } if (width != NULL) (*width) = n; return i; }
/* * Handle key presses. Fixes state, then looks up the key symbol for the * given keycode, then looks up the key symbol (as UCS-2), converts it to * UTF-8 and stores it in the password array. * */ static void handle_key_press(xcb_key_press_event_t *event) { xkb_keysym_t ksym; char buffer[128]; int n; bool ctrl; bool composed = false; ksym = xkb_state_key_get_one_sym(xkb_state, event->detail); ctrl = xkb_state_mod_name_is_active(xkb_state, XKB_MOD_NAME_CTRL, XKB_STATE_MODS_DEPRESSED); /* The buffer will be null-terminated, so n >= 2 for 1 actual character. */ memset(buffer, '\0', sizeof(buffer)); if (xkb_compose_state && xkb_compose_state_feed(xkb_compose_state, ksym) == XKB_COMPOSE_FEED_ACCEPTED) { switch (xkb_compose_state_get_status(xkb_compose_state)) { case XKB_COMPOSE_NOTHING: break; case XKB_COMPOSE_COMPOSING: return; case XKB_COMPOSE_COMPOSED: /* xkb_compose_state_get_utf8 doesn't include the terminating byte in the return value * as xkb_keysym_to_utf8 does. Adding one makes the variable n consistent. */ n = xkb_compose_state_get_utf8(xkb_compose_state, buffer, sizeof(buffer)) + 1; ksym = xkb_compose_state_get_one_sym(xkb_compose_state); composed = true; break; case XKB_COMPOSE_CANCELLED: xkb_compose_state_reset(xkb_compose_state); return; } } if (!composed) { n = xkb_keysym_to_utf8(ksym, buffer, sizeof(buffer)); } switch (ksym) { case XKB_KEY_Return: case XKB_KEY_KP_Enter: case XKB_KEY_XF86ScreenSaver: if (pam_state == STATE_PAM_WRONG) return; if (skip_without_validation()) { clear_input(); return; } password[input_position] = '\0'; unlock_state = STATE_KEY_PRESSED; redraw_screen(); input_done(); skip_repeated_empty_password = true; return; default: skip_repeated_empty_password = false; } switch (ksym) { case XKB_KEY_u: if (ctrl) { DEBUG("C-u pressed\n"); clear_input(); return; } break; case XKB_KEY_Escape: clear_input(); return; case XKB_KEY_BackSpace: if (input_position == 0) return; /* decrement input_position to point to the previous glyph */ u8_dec(password, &input_position); password[input_position] = '\0'; /* Hide the unlock indicator after a bit if the password buffer is * empty. */ START_TIMER(clear_indicator_timeout, 1.0, clear_indicator_cb); unlock_state = STATE_BACKSPACE_ACTIVE; redraw_screen(); unlock_state = STATE_KEY_PRESSED; return; } if ((input_position + 8) >= sizeof(password)) return; #if 0 /* FIXME: handle all of these? */ printf("is_keypad_key = %d\n", xcb_is_keypad_key(sym)); printf("is_private_keypad_key = %d\n", xcb_is_private_keypad_key(sym)); printf("xcb_is_cursor_key = %d\n", xcb_is_cursor_key(sym)); printf("xcb_is_pf_key = %d\n", xcb_is_pf_key(sym)); printf("xcb_is_function_key = %d\n", xcb_is_function_key(sym)); printf("xcb_is_misc_function_key = %d\n", xcb_is_misc_function_key(sym)); printf("xcb_is_modifier_key = %d\n", xcb_is_modifier_key(sym)); #endif if (n < 2) return; /* store it in the password array as UTF-8 */ memcpy(password + input_position, buffer, n - 1); input_position += n - 1; DEBUG("current password = %.*s\n", input_position, password); if (unlock_indicator) { unlock_state = STATE_KEY_ACTIVE; redraw_screen(); unlock_state = STATE_KEY_PRESSED; struct ev_timer *timeout = NULL; START_TIMER(timeout, TSTAMP_N_SECS(0.25), redraw_timeout); STOP_TIMER(clear_indicator_timeout); } START_TIMER(discard_passwd_timeout, TSTAMP_N_MINS(3), discard_passwd_cb); }
void rtext_key(t_rtext *x, int keynum, t_symbol *keysym) { int w = 0, h = 0, indx, i, newsize, ndel; char *s1, *s2; //fprintf(stderr,"rtext_key keysym=%s\n", keysym->s_name); if (keynum) { int n = keynum; if (n == '\r') n = '\n'; if (n == '\b') /* backspace */ { /* LATER delete the box if all text is selected... this causes reentrancy problems now. */ /* if ((!x->x_selstart) && (x->x_selend == x->x_bufsize)) { .... } */ if (x->x_selstart && (x->x_selstart == x->x_selend)) { u8_dec(x->x_buf, &x->x_selstart); if (glist_isvisible(glist_getcanvas(x->x_glist))) sys_vgui("pdtk_canvas_getscroll .x%lx.c\n", (t_int)glist_getcanvas(x->x_glist)); } } else if (n == 127) /* delete */ { if (x->x_selend < x->x_bufsize && (x->x_selstart == x->x_selend)) u8_inc(x->x_buf, &x->x_selend); if (glist_isvisible(glist_getcanvas(x->x_glist))) sys_vgui("pdtk_canvas_getscroll .x%lx.c\n", (t_int)glist_getcanvas(x->x_glist)); } ndel = x->x_selend - x->x_selstart; for (i = x->x_selend; i < x->x_bufsize; i++) x->x_buf[i- ndel] = x->x_buf[i]; newsize = x->x_bufsize - ndel; x->x_buf = resizebytes(x->x_buf, x->x_bufsize, newsize); x->x_bufsize = newsize; /* at Guenter's suggestion, use 'n>31' to test wither a character might be printable in whatever 8-bit character set we find ourselves. */ /*-- moo: ... but test with "<" rather than "!=" in order to accomodate unicode codepoints for n (which we get since Tk is sending the "%A" substitution for bind <Key>), effectively reducing the coverage of this clause to 7 bits. Case n>127 is covered by the next clause. */ if (n == '\n' || (n > 31 && n < 127)) { //fprintf(stderr,"return or 31-127\n"); newsize = x->x_bufsize+1; x->x_buf = resizebytes(x->x_buf, x->x_bufsize, newsize); for (i = x->x_bufsize; i > x->x_selstart; i--) x->x_buf[i] = x->x_buf[i-1]; x->x_buf[x->x_selstart] = n; x->x_bufsize = newsize; x->x_selstart = x->x_selstart + 1; if (glist_isvisible(glist_getcanvas(x->x_glist))) sys_vgui("pdtk_canvas_getscroll .x%lx.c\n", (t_int)glist_getcanvas(x->x_glist)); } /*--moo: check for unicode codepoints beyond 7-bit ASCII --*/ else if (n > 127) { //fprintf(stderr,">127\n"); int ch_nbytes = u8_wc_nbytes(n); newsize = x->x_bufsize + ch_nbytes; x->x_buf = resizebytes(x->x_buf, x->x_bufsize, newsize); for (i = x->x_bufsize; i > x->x_selstart; i--) x->x_buf[i] = x->x_buf[i-1]; x->x_bufsize = newsize; /*-- moo: assume canvas_key() has encoded keysym as UTF-8 */ strncpy(x->x_buf+x->x_selstart, keysym->s_name, ch_nbytes); x->x_selstart = x->x_selstart + ch_nbytes; } x->x_selend = x->x_selstart; x->x_glist->gl_editor->e_textdirty = 1; } else if (!strcmp(keysym->s_name, "Right")) { if (x->x_selend == x->x_selstart && x->x_selstart < x->x_bufsize) { u8_inc(x->x_buf, &x->x_selstart); x->x_selend = x->x_selstart; } else x->x_selstart = x->x_selend; last_sel = 0; } else if (!strcmp(keysym->s_name, "Left")) { if (x->x_selend == x->x_selstart && x->x_selstart > 0) { u8_dec(x->x_buf, &x->x_selstart); x->x_selend = x->x_selstart; } else x->x_selend = x->x_selstart; last_sel = 0; } else if (!strcmp(keysym->s_name, "ShiftRight")) { if (!last_sel) last_sel = 2; if (last_sel == 1 && x->x_selstart < x->x_selend) { if (x->x_selstart < x->x_bufsize) u8_inc(x->x_buf, &x->x_selstart); } else { last_sel = 2; if (x->x_selend < x->x_bufsize) u8_inc(x->x_buf, &x->x_selend); } } else if (!strcmp(keysym->s_name, "ShiftLeft")) { if (!last_sel) last_sel = 1; if (last_sel == 2 && x->x_selend > x->x_selstart) { x->x_selend = x->x_selend - 1; } else { last_sel = 1; if (x->x_selstart > 0) u8_dec(x->x_buf, &x->x_selstart); } } else if (!strcmp(keysym->s_name, "Up")) { if (x->x_selstart) u8_dec(x->x_buf, &x->x_selstart); while (x->x_selstart > 0 && (x->x_buf[x->x_selstart] != '\n' && x->x_buf[x->x_selstart] != '\v')) u8_dec(x->x_buf, &x->x_selstart); x->x_selend = x->x_selstart; last_sel = 0; } else if (!strcmp(keysym->s_name, "Down")) { while (x->x_selend < x->x_bufsize && (x->x_buf[x->x_selend] != '\n' && x->x_buf[x->x_selend] != '\v')) u8_inc(x->x_buf, &x->x_selend); if (x->x_selend < x->x_bufsize) u8_inc(x->x_buf, &x->x_selend); x->x_selstart = x->x_selend; last_sel = 0; } else if (!strcmp(keysym->s_name, "Home")) { if (x->x_selstart) u8_dec(x->x_buf, &x->x_selstart); while (x->x_selstart > 0 && x->x_buf[x->x_selstart] != '\n') u8_dec(x->x_buf, &x->x_selstart); x->x_selend = x->x_selstart; last_sel = 0; } else if (!strcmp(keysym->s_name, "End")) { while (x->x_selend < x->x_bufsize && x->x_buf[x->x_selend] != '\n') u8_inc(x->x_buf, &x->x_selend); if (x->x_selend < x->x_bufsize) u8_inc(x->x_buf, &x->x_selend); x->x_selstart = x->x_selend; last_sel = 0; } else if (!strcmp(keysym->s_name, "CtrlLeft")) { //fprintf(stderr,"ctrleft\n"); /* first find first non-space char going back */ while (x->x_selstart > 0 && rtext_compare_special_chars(x->x_buf[x->x_selstart-1])) { //fprintf(stderr,"while 1 <%c>\n", x->x_buf[x->x_selstart-1]); u8_dec(x->x_buf, &x->x_selstart); } /* now go back until you find another space or the beginning of the buffer */ while (x->x_selstart > 0 && !rtext_compare_special_chars(x->x_buf[x->x_selstart-1])) { //fprintf(stderr,"while 2 <%c>\n", x->x_buf[x->x_selstart-1]); u8_dec(x->x_buf, &x->x_selstart); } if (x->x_buf[x->x_selstart+1] == ' ' && x->x_buf[x->x_selstart] == ' ') { //fprintf(stderr,"go forward\n"); u8_inc(x->x_buf, &x->x_selstart); } x->x_selend = x->x_selstart; } else if (!strcmp(keysym->s_name, "CtrlRight")) { /* now go forward until you find another space or the end of the buffer */ if (x->x_selend < x->x_bufsize - 1) u8_inc(x->x_buf, &x->x_selend); while (x->x_selend < x->x_bufsize && !rtext_compare_special_chars(x->x_buf[x->x_selend])) u8_inc(x->x_buf, &x->x_selend); /* now skip all the spaces and land before next word */ /*while (x->x_selend < x->x_bufsize && x->x_buf[x->x_selend] == ' ') u8_inc(x->x_buf, &x->x_selend); if (x->x_selend > 0 && x->x_buf[x->x_selend-1] == ' ') u8_dec(x->x_buf, &x->x_selend);*/ x->x_selstart = x->x_selend; } else if (!strcmp(keysym->s_name, "CtrlShiftLeft")) { //fprintf(stderr,"ctrlshiftleft %d %d %d\n", // last_sel, x->x_selstart, x->x_selend); int swap = 0; int *target; if (!last_sel) last_sel = 1; if (last_sel == 2 && x->x_selend > x->x_selstart) target = &x->x_selend; else { last_sel = 1; target = &x->x_selstart; } /* first find first non-space char going back */ while (*target > 0 && rtext_compare_special_chars(x->x_buf[*target-1])) { u8_dec(x->x_buf, target); //(*target)--; } //fprintf(stderr,"%d %d\n", x->x_selstart, x->x_selend); /* now go back until you find another space or the beginning of the buffer */ while (*target > 0 && !rtext_compare_special_chars(x->x_buf[*target-1])) { u8_dec(x->x_buf, target); //(*target)--; } //fprintf(stderr,"%d %d\n", x->x_selstart, x->x_selend); if (x->x_buf[*target+1] == ' ' && x->x_buf[x->x_selstart] == ' ') { u8_inc(x->x_buf, target); //(*target)++; } //fprintf(stderr,"%d %d\n", x->x_selstart, x->x_selend); if (x->x_selstart > x->x_selend) { swap = x->x_selend; x->x_selend = x->x_selstart; x->x_selstart = swap; last_sel = 1; } } else if (!strcmp(keysym->s_name, "CtrlShiftRight")) { //fprintf(stderr,"ctrlshiftright %d %d %d\n", // last_sel, x->x_selstart, x->x_selend); int swap = 0; int *target; if (!last_sel) last_sel = 2; if (last_sel == 1 && x->x_selstart < x->x_selend) target = &x->x_selstart; else { last_sel = 2; target = &x->x_selend; } //fprintf(stderr,"%d %d\n", x->x_selstart, x->x_selend); /* now go forward until you find another space or the end of the buffer */ if (*target < x->x_bufsize - 1) { //fprintf(stderr,"while 1 <%c>\n", x->x_buf[*target]); u8_inc(x->x_buf, target); //(*target)++; } //fprintf(stderr,"%d %d\n", x->x_selstart, x->x_selend); while (*target < x->x_bufsize && !rtext_compare_special_chars(x->x_buf[*target])) { //fprintf(stderr,"while 2 <%c>\n", x->x_buf[*target]); u8_inc(x->x_buf, target); //(*target)++; } /* now skip all the spaces and land before next word */ /*while (*target < x->x_bufsize && x->x_buf[*target] == ' ') { u8_inc(x->x_buf, target); //(*target)++; } if (*target > 0 && x->x_buf[*target-1] == ' ') { u8_dec(x->x_buf, target); //(*target)--; }*/ //fprintf(stderr,"%d %d\n", x->x_selstart, x->x_selend); if (x->x_selstart > x->x_selend) { swap = x->x_selend; x->x_selend = x->x_selstart; x->x_selstart = swap; last_sel = 2; } //fprintf(stderr,"%d %d\n", x->x_selstart, x->x_selend); } rtext_senditup(x, SEND_UPDATE, &w, &h, &indx); }
int trkproperties_get_field_value (char *out, int size, const char *key, DB_playItem_t **tracks, int numtracks) { int multiple = 0; char *out_start = out; int clipped = 0; *out = 0; if (numtracks == 0) { return 0; } deadbeef->pl_lock (); const char **prev = malloc (sizeof (const char *) * numtracks); memset (prev, 0, sizeof (const char *) * numtracks); for (int i = 0; i < numtracks; i++) { DB_metaInfo_t *meta = deadbeef->pl_meta_for_key (tracks[i], key); if (meta && meta->valuesize == 1) { meta = NULL; } if (i > 0) { int n = 0; for (; n < i; n++) { if (prev[n] == (meta ? meta->value : NULL)) { break; } } if (n == i) { multiple = 1; if (meta) { if (out != out_start) { if (size < 3) { clipped = 1; break; } memcpy (out, "; ", 3); out += 2; size -= 2; } int n = string_append_multivalue (out, size, meta, &clipped); out += n; size -= n; } } } else if (meta) { int n = string_append_multivalue (out, size, meta, &clipped); out += n; size -= n; } prev[i] = meta ? meta->value : NULL; if (size < 3) { break; } } deadbeef->pl_unlock (); if (clipped) { // FIXME: This is a hack for strings which don't fit in the preallocated 5K buffer // When the code is converted to use dynamic buffer - this can be removed int idx = (int)(out - 4 - out_start); u8_dec (out_start, &idx); char *prev = out_start + idx; strcpy (prev, "..."); } free (prev); return multiple; }
void TextEdit::Key(const KeyInput &input) { if (!HasFocus()) return; // Process navigation keys. These aren't chars. if (input.flags & KEY_DOWN) { switch (input.keyCode) { case NKCODE_CTRL_LEFT: case NKCODE_CTRL_RIGHT: ctrlDown_ = true; break; case NKCODE_DPAD_LEFT: // ASCII left arrow u8_dec(text_.c_str(), &caret_); break; case NKCODE_DPAD_RIGHT: // ASCII right arrow u8_inc(text_.c_str(), &caret_); break; case NKCODE_MOVE_HOME: case NKCODE_PAGE_UP: caret_ = 0; break; case NKCODE_MOVE_END: case NKCODE_PAGE_DOWN: caret_ = (int)text_.size(); break; case NKCODE_FORWARD_DEL: if (caret_ < (int)text_.size()) { int endCaret = caret_; u8_inc(text_.c_str(), &endCaret); undo_ = text_; text_.erase(text_.begin() + caret_, text_.begin() + endCaret); } break; case NKCODE_DEL: if (caret_ > 0) { int begCaret = caret_; u8_dec(text_.c_str(), &begCaret); undo_ = text_; text_.erase(text_.begin() + begCaret, text_.begin() + caret_); caret_--; } break; } if (ctrlDown_) { switch (input.keyCode) { case NKCODE_C: // Just copy the entire text contents, until we get selection support. System_SendMessage("setclipboardtext", text_.c_str()); break; case NKCODE_V: { std::string clipText = System_GetProperty(SYSPROP_CLIPBOARD_TEXT); clipText = FirstLine(clipText); if (clipText.size()) { // Until we get selection, replace the whole text undo_ = text_; text_.clear(); caret_ = 0; size_t maxPaste = maxLen_ - text_.size(); if (clipText.size() > maxPaste) { int end = 0; while ((size_t)end < maxPaste) { u8_inc(clipText.c_str(), &end); } if (end > 0) { u8_dec(clipText.c_str(), &end); } clipText = clipText.substr(0, end); } InsertAtCaret(clipText.c_str()); } } break; case NKCODE_Z: text_ = undo_; break; } } if (caret_ < 0) { caret_ = 0; } if (caret_ > (int)text_.size()) { caret_ = (int)text_.size(); } } if (input.flags & KEY_UP) { switch (input.keyCode) { case NKCODE_CTRL_LEFT: case NKCODE_CTRL_RIGHT: ctrlDown_ = false; break; } } // Process chars. if (input.flags & KEY_CHAR) { int unichar = input.keyCode; if (unichar >= 0x20 && !ctrlDown_) { // Ignore control characters. // Insert it! (todo: do it with a string insert) char buf[8]; buf[u8_wc_toutf8(buf, unichar)] = '\0'; if (strlen(buf) + text_.size() < maxLen_) { undo_ = text_; InsertAtCaret(buf); } } } }
/* * Handle key presses. Fixes state, then looks up the key symbol for the * given keycode, then looks up the key symbol (as UCS-2), converts it to * UTF-8 and stores it in the password array. * */ static void handle_key_press(xcb_key_press_event_t *event) { xkb_keysym_t ksym; char buffer[128]; int n; bool ctrl; ksym = xkb_state_key_get_one_sym(xkb_state, event->detail); ctrl = xkb_state_mod_name_is_active(xkb_state, "Control", XKB_STATE_MODS_DEPRESSED); xkb_state_update_key(xkb_state, event->detail, XKB_KEY_DOWN); /* The buffer will be null-terminated, so n >= 2 for 1 actual character. */ memset(buffer, '\0', sizeof(buffer)); n = xkb_keysym_to_utf8(ksym, buffer, sizeof(buffer)); switch (ksym) { case XKB_KEY_Return: case XKB_KEY_KP_Enter: case XKB_KEY_XF86ScreenSaver: password[input_position] = '\0'; unlock_state = STATE_KEY_PRESSED; redraw_screen(); input_done(); return; case XKB_KEY_u: if (ctrl) { DEBUG("C-u pressed\n"); clear_input(); return; } break; case XKB_KEY_Escape: clear_input(); return; case XKB_KEY_BackSpace: if (input_position == 0) return; /* decrement input_position to point to the previous glyph */ u8_dec(password, &input_position); password[input_position] = '\0'; /* Hide the unlock indicator after a bit if the password buffer is * empty. */ start_clear_indicator_timeout(); unlock_state = STATE_BACKSPACE_ACTIVE; redraw_screen(); unlock_state = STATE_KEY_PRESSED; return; } if ((input_position + 8) >= sizeof(password)) return; #if 0 /* FIXME: handle all of these? */ printf("is_keypad_key = %d\n", xcb_is_keypad_key(sym)); printf("is_private_keypad_key = %d\n", xcb_is_private_keypad_key(sym)); printf("xcb_is_cursor_key = %d\n", xcb_is_cursor_key(sym)); printf("xcb_is_pf_key = %d\n", xcb_is_pf_key(sym)); printf("xcb_is_function_key = %d\n", xcb_is_function_key(sym)); printf("xcb_is_misc_function_key = %d\n", xcb_is_misc_function_key(sym)); printf("xcb_is_modifier_key = %d\n", xcb_is_modifier_key(sym)); #endif if (n < 2) return; /* store it in the password array as UTF-8 */ memcpy(password+input_position, buffer, n-1); input_position += n-1; DEBUG("current password = %.*s\n", input_position, password); unlock_state = STATE_KEY_ACTIVE; redraw_screen(); unlock_state = STATE_KEY_PRESSED; struct ev_timer *timeout = calloc(sizeof(struct ev_timer), 1); if (timeout) { ev_timer_init(timeout, redraw_timeout, 0.25, 0.); ev_timer_start(main_loop, timeout); } stop_clear_indicator_timeout(); }
/* * Handle key presses. Fixes state, then looks up the key symbol for the * given keycode, then looks up the key symbol (as UCS-2), converts it to * UTF-8 and stores it in the password array. * */ static void handle_key_press(xcb_key_press_event_t *event) { xkb_keysym_t ksym; char buffer[128]; int n; bool ctrl; ksym = xkb_state_key_get_one_sym(xkb_state, event->detail); ctrl = xkb_state_mod_name_is_active(xkb_state, "Control", XKB_STATE_MODS_DEPRESSED); /* The buffer will be null-terminated, so n >= 2 for 1 actual character. */ memset(buffer, '\0', sizeof(buffer)); n = xkb_keysym_to_utf8(ksym, buffer, sizeof(buffer)); switch (ksym) { case XKB_KEY_Return: case XKB_KEY_KP_Enter: case XKB_KEY_XF86ScreenSaver: if (skip_without_validation()) { clear_input(); return; } password[input_position] = '\0'; unlock_state = STATE_KEY_PRESSED; redraw_screen(); input_done(); skip_repeated_empty_password = true; return; default: skip_repeated_empty_password = false; } switch (ksym) { case XKB_KEY_u: if (ctrl) { DEBUG("C-u pressed\n"); clear_input(); return; } break; case XKB_KEY_Escape: clear_input(); return; case XKB_KEY_BackSpace: if (input_position == 0) return; /* decrement input_position to point to the previous glyph */ u8_dec(password, &input_position); password[input_position] = '\0'; /* Hide the unlock indicator after a bit if the password buffer is * empty. */ START_TIMER(clear_indicator_timeout, 1.0, clear_indicator_cb); unlock_state = STATE_BACKSPACE_ACTIVE; redraw_screen(); unlock_state = STATE_KEY_PRESSED; return; } if ((input_position + 8) >= sizeof(password)) return; #if 0 /* FIXME: handle all of these? */ printf("is_keypad_key = %d\n", xcb_is_keypad_key(sym)); printf("is_private_keypad_key = %d\n", xcb_is_private_keypad_key(sym)); printf("xcb_is_cursor_key = %d\n", xcb_is_cursor_key(sym)); printf("xcb_is_pf_key = %d\n", xcb_is_pf_key(sym)); printf("xcb_is_function_key = %d\n", xcb_is_function_key(sym)); printf("xcb_is_misc_function_key = %d\n", xcb_is_misc_function_key(sym)); printf("xcb_is_modifier_key = %d\n", xcb_is_modifier_key(sym)); #endif if (n < 2) return; /* store it in the password array as UTF-8 */ memcpy(password+input_position, buffer, n-1); input_position += n-1; DEBUG("current password = %.*s\n", input_position, password); unlock_state = STATE_KEY_ACTIVE; redraw_screen(); unlock_state = STATE_KEY_PRESSED; struct ev_timer *timeout = NULL; START_TIMER(timeout, TSTAMP_N_SECS(0.25), redraw_timeout); STOP_TIMER(clear_indicator_timeout); START_TIMER(discard_passwd_timeout, TSTAMP_N_MINS(3), discard_passwd_cb); }
void rtext_key(t_rtext *x, int keynum, t_symbol *keysym) { //fprintf(stderr,"rtext_key %d %s\n", keynum, keysym->s_name); int w = 0, h = 0, indx, i, newsize, ndel; if (keynum) { int n = keynum; if (n == '\r' || n == '\v') n = '\n'; if (n == '\b') /* backspace */ { if (x->x_selstart && (x->x_selstart == x->x_selend)) { u8_dec(x->x_buf, &x->x_selstart); if (glist_isvisible(glist_getcanvas(x->x_glist))) canvas_getscroll(glist_getcanvas(x->x_glist)); } } else if (n == 127) /* delete */ { if (x->x_selend < x->x_bufsize && (x->x_selstart == x->x_selend)) u8_inc(x->x_buf, &x->x_selend); if (glist_isvisible(glist_getcanvas(x->x_glist))) canvas_getscroll(glist_getcanvas(x->x_glist)); } ndel = x->x_selend - x->x_selstart; if (ndel) { for (i = x->x_selend; i < x->x_bufsize; i++) x->x_buf[i- ndel] = x->x_buf[i]; newsize = x->x_bufsize - ndel; x->x_buf = resizebytes(x->x_buf, x->x_bufsize, newsize); x->x_bufsize = newsize; } /* at Guenter's suggestion, use 'n>31' to test wither a character might be printable in whatever 8-bit character set we find ourselves. */ /*-- moo: ... but test with "<" rather than "!=" in order to accomodate unicode codepoints for n (which we get since Tk is sending the "%A" substitution for bind <Key>), effectively reducing the coverage of this clause to 7 bits. Case n>127 is covered by the next clause. */ if (n == '\n' || (n > 31 && n < 127)) { newsize = x->x_bufsize+1; x->x_buf = resizebytes(x->x_buf, x->x_bufsize, newsize); for (i = x->x_bufsize; i > x->x_selstart; i--) x->x_buf[i] = x->x_buf[i-1]; x->x_buf[x->x_selstart] = n; x->x_bufsize = newsize; x->x_selstart = x->x_selstart + 1; if (glist_isvisible(glist_getcanvas(x->x_glist))) canvas_getscroll(glist_getcanvas(x->x_glist)); } /*--moo: check for unicode codepoints beyond 7-bit ASCII --*/ else if (n > 127) { int ch_nbytes = u8_wc_nbytes(n); newsize = x->x_bufsize + ch_nbytes; x->x_buf = resizebytes(x->x_buf, x->x_bufsize, newsize); //fprintf(stderr,"x->x_bufsize=%d newsize=%d\n", x->x_bufsize, newsize); //for (i = newsize-1; i >= x->x_selstart; i--) //{ //fprintf(stderr,"%d-%d <%d>\n", i, i-ch_nbytes, x->x_buf[i-ch_nbytes]); //x->x_buf[i] = '\0'; //} x->x_bufsize = newsize; /*-- moo: assume canvas_key() has encoded keysym as UTF-8 */ strncpy(x->x_buf+x->x_selstart, keysym->s_name, ch_nbytes); x->x_selstart = x->x_selstart + ch_nbytes; } x->x_selend = x->x_selstart; x->x_glist->gl_editor->e_textdirty = 1; } else if (!strcmp(keysym->s_name, "Right")) { if (x->x_selend == x->x_selstart && x->x_selstart < x->x_bufsize) { u8_inc(x->x_buf, &x->x_selstart); x->x_selend = x->x_selstart; } else x->x_selstart = x->x_selend; last_sel = 0; } else if (!strcmp(keysym->s_name, "Left")) { if (x->x_selend == x->x_selstart && x->x_selstart > 0) { u8_dec(x->x_buf, &x->x_selstart); x->x_selend = x->x_selstart; } else x->x_selend = x->x_selstart; last_sel = 0; } else if (!strcmp(keysym->s_name, "ShiftRight")) { if (!last_sel) last_sel = 2; if (last_sel == 1 && x->x_selstart < x->x_selend) { if (x->x_selstart < x->x_bufsize) u8_inc(x->x_buf, &x->x_selstart); } else { last_sel = 2; if (x->x_selend < x->x_bufsize) u8_inc(x->x_buf, &x->x_selend); } } else if (!strcmp(keysym->s_name, "ShiftLeft")) { if (!last_sel) last_sel = 1; if (last_sel == 2 && x->x_selend > x->x_selstart) { x->x_selend = x->x_selend - 1; } else { last_sel = 1; if (x->x_selstart > 0) u8_dec(x->x_buf, &x->x_selstart); } } else if (!strcmp(keysym->s_name, "Up")) { if (x->x_selstart != x->x_selend) { x->x_selend = x->x_selstart; last_sel = 0; } else { // we do this twice and then move to the right // as many spots as we had before, this will // allow us to go visually above where we used // to be in multiline situations (e.g. comments) int right = 0; //printf("start: selstart=%d x->x_bufsize=%d\n", x->x_selstart, x->x_bufsize); if (x->x_selstart > 0 && (x->x_selstart == x->x_bufsize || x->x_buf[x->x_selstart] == '\n' || x->x_buf[x->x_selstart] == '\v')) { //printf("found break\n"); u8_dec(x->x_buf, &x->x_selstart); right++; } while (x->x_selstart > 0 && (x->x_buf[x->x_selstart-1] != '\n' && x->x_buf[x->x_selstart-1] != '\v')) { u8_dec(x->x_buf, &x->x_selstart); right++; } if (x->x_selstart == 0) right = 0; //printf("first linebreak: right=%d selstart=%d\n", right, x->x_selstart); if (x->x_selstart > 0) u8_dec(x->x_buf, &x->x_selstart); //printf("decrease by 1: selstart=%d\n", x->x_selstart); while (x->x_selstart > 0 && (x->x_buf[x->x_selstart-1] != '\n' && x->x_buf[x->x_selstart-1] != '\v')) u8_dec(x->x_buf, &x->x_selstart); //printf("second linebreak: selstart=%d\n", x->x_selstart); if (x->x_selstart < x->x_bufsize && right > 0) { u8_inc(x->x_buf, &x->x_selstart); right--; } //printf("increase by 1: selstart=%d\n", x->x_selstart); while (right > 0 && (x->x_buf[x->x_selstart] != '\n' && x->x_buf[x->x_selstart] != '\v')) { u8_inc(x->x_buf, &x->x_selstart); right--; } //printf("final: selstart=%d\n", x->x_selstart); x->x_selend = x->x_selstart; last_sel = 0; } } else if (!strcmp(keysym->s_name, "Down")) { if (x->x_selstart != x->x_selend) { x->x_selstart = x->x_selend; last_sel = 0; } else { // we do this twice and then move to the right // as many spots as we had before, this will // allow us to go visually below where we used // to be in multiline situations (e.g. comments) int right = 0; if (x->x_selstart > 0 && (x->x_buf[x->x_selstart] != '\n' || x->x_buf[x->x_selstart] != '\v')) { while (x->x_selstart > 0 && (x->x_buf[x->x_selstart-1] != '\n' && x->x_buf[x->x_selstart-1] != '\v')) { x->x_selstart--; right++; } } //printf("start: right=%d selstart=%d selend=%d\n", right, x->x_selstart, x->x_selend); if (x->x_selend < x->x_bufsize && (x->x_buf[x->x_selend] == '\n' || x->x_buf[x->x_selend] == '\v')) { //printf("found break\n"); u8_inc(x->x_buf, &x->x_selend); right--; } else while (x->x_selend < x->x_bufsize && (x->x_buf[x->x_selend] != '\n' && x->x_buf[x->x_selend] != '\v')) { u8_inc(x->x_buf, &x->x_selend); } //printf("first linebreak: selend=%d\n", x->x_selend); if (x->x_selend+1 < x->x_bufsize) { u8_inc(x->x_buf, &x->x_selend); } //printf("increase by 1: selend=%d\n", x->x_selend); while (right > 0 && x->x_selend < x->x_bufsize && (x->x_buf[x->x_selend] != '\n' && x->x_buf[x->x_selend] != '\v')) { u8_inc(x->x_buf, &x->x_selend); right--; } //printf("final: selend=%d\n", x->x_selend); x->x_selstart = x->x_selend; last_sel = 0; } } else if (!strcmp(keysym->s_name, "Home")) { if (x->x_selstart) u8_dec(x->x_buf, &x->x_selstart); while (x->x_selstart > 0 && x->x_buf[x->x_selstart] != '\n') u8_dec(x->x_buf, &x->x_selstart); x->x_selend = x->x_selstart; last_sel = 0; } else if (!strcmp(keysym->s_name, "ShiftHome")) { if (x->x_selstart) { if (last_sel == 2) x->x_selend = x->x_selstart; u8_dec(x->x_buf, &x->x_selstart); last_sel = 1; } while (x->x_selstart > 0 && x->x_buf[x->x_selstart] != '\n') u8_dec(x->x_buf, &x->x_selstart); //x->x_selend = x->x_selstart; //last_sel = 1; } else if (!strcmp(keysym->s_name, "End")) { while (x->x_selend < x->x_bufsize && x->x_buf[x->x_selend] != '\n') u8_inc(x->x_buf, &x->x_selend); if (x->x_selend < x->x_bufsize) u8_inc(x->x_buf, &x->x_selend); x->x_selstart = x->x_selend; last_sel = 0; } else if (!strcmp(keysym->s_name, "ShiftEnd")) { if (last_sel == 1) x->x_selstart = x->x_selend; while (x->x_selend < x->x_bufsize && x->x_buf[x->x_selend] != '\n') u8_inc(x->x_buf, &x->x_selend); if (x->x_selend < x->x_bufsize) { u8_inc(x->x_buf, &x->x_selend); } //x->x_selstart = x->x_selend; last_sel = 2; } else if (!strcmp(keysym->s_name, "CtrlLeft")) { /* first find first non-space char going back */ while (x->x_selstart > 0 && rtext_compare_special_chars(x->x_buf[x->x_selstart-1])) { u8_dec(x->x_buf, &x->x_selstart); } /* now go back until you find another space or the beginning of the buffer */ while (x->x_selstart > 0 && !rtext_compare_special_chars(x->x_buf[x->x_selstart-1])) { u8_dec(x->x_buf, &x->x_selstart); } if (x->x_buf[x->x_selstart+1] == ' ' && x->x_buf[x->x_selstart] == ' ') { u8_inc(x->x_buf, &x->x_selstart); } x->x_selend = x->x_selstart; } else if (!strcmp(keysym->s_name, "CtrlRight")) { /* now go forward until you find another space or the end of the buffer */ if (x->x_selend < x->x_bufsize - 1) u8_inc(x->x_buf, &x->x_selend); while (x->x_selend < x->x_bufsize && !rtext_compare_special_chars(x->x_buf[x->x_selend])) u8_inc(x->x_buf, &x->x_selend); x->x_selstart = x->x_selend; } else if (!strcmp(keysym->s_name, "CtrlShiftLeft")) { int swap = 0; int *target; if (!last_sel) last_sel = 1; if (last_sel == 2 && x->x_selend > x->x_selstart) target = &x->x_selend; else { last_sel = 1; target = &x->x_selstart; } /* first find first non-space char going back */ while (*target > 0 && rtext_compare_special_chars(x->x_buf[*target-1])) { u8_dec(x->x_buf, target); } /* now go back until you find another space or the beginning of the buffer */ while (*target > 0 && !rtext_compare_special_chars(x->x_buf[*target-1])) { u8_dec(x->x_buf, target); } if (x->x_buf[*target+1] == ' ' && x->x_buf[x->x_selstart] == ' ') { u8_inc(x->x_buf, target); } if (x->x_selstart > x->x_selend) { swap = x->x_selend; x->x_selend = x->x_selstart; x->x_selstart = swap; last_sel = 1; } } else if (!strcmp(keysym->s_name, "CtrlShiftRight")) { int swap = 0; int *target; if (!last_sel) last_sel = 2; if (last_sel == 1 && x->x_selstart < x->x_selend) target = &x->x_selstart; else { last_sel = 2; target = &x->x_selend; } /* now go forward until you find another space or the end of the buffer */ if (*target < x->x_bufsize - 1) { u8_inc(x->x_buf, target); } while (*target < x->x_bufsize && !rtext_compare_special_chars(x->x_buf[*target])) { u8_inc(x->x_buf, target); } if (x->x_selstart > x->x_selend) { swap = x->x_selend; x->x_selend = x->x_selstart; x->x_selstart = swap; last_sel = 2; } } rtext_senditup(x, SEND_UPDATE, &w, &h, &indx); }