1 /* $NetBSD: literal.c,v 1.5 2019/07/23 13:10:11 christos Exp $ */ 2 3 /*- 4 * Copyright (c) 2017 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Christos Zoulas. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #include "config.h" 33 #if !defined(lint) && !defined(SCCSID) 34 #if 0 35 __RCSID("$NetBSD: literal.c,v 1.5 2019/07/23 13:10:11 christos Exp $"); 36 #endif 37 #endif /* not lint && not SCCSID */ 38 39 /* 40 * literal.c: Literal sequences handling. 41 */ 42 #include <assert.h> 43 #include <stdio.h> 44 #include <stdlib.h> 45 #include <string.h> 46 #include "el.h" 47 48 libedit_private void 49 literal_init(EditLine *el) 50 { 51 el_literal_t *l = &el->el_literal; 52 53 memset(l, 0, sizeof(*l)); 54 } 55 56 libedit_private void 57 literal_end(EditLine *el) 58 { 59 literal_clear(el); 60 } 61 62 libedit_private void 63 literal_clear(EditLine *el) 64 { 65 el_literal_t *l = &el->el_literal; 66 size_t i; 67 68 if (l->l_len == 0) 69 return; 70 71 for (i = 0; i < l->l_idx; i++) 72 el_free(l->l_buf[i]); 73 el_free(l->l_buf); 74 l->l_buf = NULL; 75 l->l_len = 0; 76 l->l_idx = 0; 77 } 78 79 libedit_private wint_t 80 literal_add(EditLine *el, const wchar_t *buf, const wchar_t *end, int *wp) 81 { 82 el_literal_t *l = &el->el_literal; 83 size_t i, len; 84 ssize_t w, n; 85 char *b; 86 87 w = wcwidth(end[1]); /* column width of the visible char */ 88 *wp = (int)w; 89 90 if (w <= 0) /* we require something to be printed */ 91 return 0; 92 93 len = (size_t)(end - buf); 94 for (w = 0, i = 0; i < len; i++) 95 w += ct_enc_width(buf[i]); 96 w += ct_enc_width(end[1]); 97 98 b = el_malloc((size_t)(w + 1)); 99 if (b == NULL) 100 return 0; 101 102 for (n = 0, i = 0; i < len; i++) 103 n += ct_encode_char(b + n, (size_t)(w - n), buf[i]); 104 n += ct_encode_char(b + n, (size_t)(w - n), end[1]); 105 b[n] = '\0'; 106 107 /* 108 * Then save this literal string in the list of such strings, 109 * and return a "magic character" to put into the terminal buffer. 110 * When that magic char is 'printed' the saved string (which includes 111 * the char that belongs in that position) gets sent instead. 112 */ 113 if (l->l_idx == l->l_len) { 114 char **bp; 115 116 l->l_len += 4; 117 bp = el_realloc(l->l_buf, sizeof(*l->l_buf) * l->l_len); 118 if (bp == NULL) { 119 free(b); 120 l->l_len -= 4; 121 return 0; 122 } 123 l->l_buf = bp; 124 } 125 l->l_buf[l->l_idx++] = b; 126 return EL_LITERAL | (wint_t)(l->l_idx - 1); 127 } 128 129 libedit_private const char * 130 literal_get(EditLine *el, wint_t idx) 131 { 132 el_literal_t *l = &el->el_literal; 133 134 assert(idx & EL_LITERAL); 135 idx &= ~EL_LITERAL; 136 assert(l->l_idx > (size_t)idx); 137 return l->l_buf[idx]; 138 } 139