1*d0ef721eSBaptiste Daroussin /* $NetBSD: hist.c,v 1.34 2019/07/23 10:19:35 christos Exp $ */ 2*d0ef721eSBaptiste Daroussin 3*d0ef721eSBaptiste Daroussin /*- 4*d0ef721eSBaptiste Daroussin * Copyright (c) 1992, 1993 5*d0ef721eSBaptiste Daroussin * The Regents of the University of California. All rights reserved. 6*d0ef721eSBaptiste Daroussin * 7*d0ef721eSBaptiste Daroussin * This code is derived from software contributed to Berkeley by 8*d0ef721eSBaptiste Daroussin * Christos Zoulas of Cornell University. 9*d0ef721eSBaptiste Daroussin * 10*d0ef721eSBaptiste Daroussin * Redistribution and use in source and binary forms, with or without 11*d0ef721eSBaptiste Daroussin * modification, are permitted provided that the following conditions 12*d0ef721eSBaptiste Daroussin * are met: 13*d0ef721eSBaptiste Daroussin * 1. Redistributions of source code must retain the above copyright 14*d0ef721eSBaptiste Daroussin * notice, this list of conditions and the following disclaimer. 15*d0ef721eSBaptiste Daroussin * 2. Redistributions in binary form must reproduce the above copyright 16*d0ef721eSBaptiste Daroussin * notice, this list of conditions and the following disclaimer in the 17*d0ef721eSBaptiste Daroussin * documentation and/or other materials provided with the distribution. 18*d0ef721eSBaptiste Daroussin * 3. Neither the name of the University nor the names of its contributors 19*d0ef721eSBaptiste Daroussin * may be used to endorse or promote products derived from this software 20*d0ef721eSBaptiste Daroussin * without specific prior written permission. 21*d0ef721eSBaptiste Daroussin * 22*d0ef721eSBaptiste Daroussin * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23*d0ef721eSBaptiste Daroussin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24*d0ef721eSBaptiste Daroussin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25*d0ef721eSBaptiste Daroussin * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26*d0ef721eSBaptiste Daroussin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27*d0ef721eSBaptiste Daroussin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28*d0ef721eSBaptiste Daroussin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29*d0ef721eSBaptiste Daroussin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30*d0ef721eSBaptiste Daroussin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31*d0ef721eSBaptiste Daroussin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32*d0ef721eSBaptiste Daroussin * SUCH DAMAGE. 33*d0ef721eSBaptiste Daroussin */ 34*d0ef721eSBaptiste Daroussin 35*d0ef721eSBaptiste Daroussin #include "config.h" 36*d0ef721eSBaptiste Daroussin #if !defined(lint) && !defined(SCCSID) 37*d0ef721eSBaptiste Daroussin #if 0 38*d0ef721eSBaptiste Daroussin static char sccsid[] = "@(#)hist.c 8.1 (Berkeley) 6/4/93"; 39*d0ef721eSBaptiste Daroussin #else 40*d0ef721eSBaptiste Daroussin __RCSID("$NetBSD: hist.c,v 1.34 2019/07/23 10:19:35 christos Exp $"); 41*d0ef721eSBaptiste Daroussin #endif 42*d0ef721eSBaptiste Daroussin #endif /* not lint && not SCCSID */ 43*d0ef721eSBaptiste Daroussin 44*d0ef721eSBaptiste Daroussin /* 45*d0ef721eSBaptiste Daroussin * hist.c: History access functions 46*d0ef721eSBaptiste Daroussin */ 47*d0ef721eSBaptiste Daroussin #include <stdlib.h> 48*d0ef721eSBaptiste Daroussin #include <string.h> 49*d0ef721eSBaptiste Daroussin #include <vis.h> 50*d0ef721eSBaptiste Daroussin 51*d0ef721eSBaptiste Daroussin #include "el.h" 52*d0ef721eSBaptiste Daroussin 53*d0ef721eSBaptiste Daroussin /* hist_init(): 54*d0ef721eSBaptiste Daroussin * Initialization function. 55*d0ef721eSBaptiste Daroussin */ 56*d0ef721eSBaptiste Daroussin libedit_private int 57*d0ef721eSBaptiste Daroussin hist_init(EditLine *el) 58*d0ef721eSBaptiste Daroussin { 59*d0ef721eSBaptiste Daroussin 60*d0ef721eSBaptiste Daroussin el->el_history.fun = NULL; 61*d0ef721eSBaptiste Daroussin el->el_history.ref = NULL; 62*d0ef721eSBaptiste Daroussin el->el_history.buf = el_calloc(EL_BUFSIZ, sizeof(*el->el_history.buf)); 63*d0ef721eSBaptiste Daroussin if (el->el_history.buf == NULL) 64*d0ef721eSBaptiste Daroussin return -1; 65*d0ef721eSBaptiste Daroussin el->el_history.sz = EL_BUFSIZ; 66*d0ef721eSBaptiste Daroussin el->el_history.last = el->el_history.buf; 67*d0ef721eSBaptiste Daroussin return 0; 68*d0ef721eSBaptiste Daroussin } 69*d0ef721eSBaptiste Daroussin 70*d0ef721eSBaptiste Daroussin 71*d0ef721eSBaptiste Daroussin /* hist_end(): 72*d0ef721eSBaptiste Daroussin * clean up history; 73*d0ef721eSBaptiste Daroussin */ 74*d0ef721eSBaptiste Daroussin libedit_private void 75*d0ef721eSBaptiste Daroussin hist_end(EditLine *el) 76*d0ef721eSBaptiste Daroussin { 77*d0ef721eSBaptiste Daroussin 78*d0ef721eSBaptiste Daroussin el_free(el->el_history.buf); 79*d0ef721eSBaptiste Daroussin el->el_history.buf = NULL; 80*d0ef721eSBaptiste Daroussin } 81*d0ef721eSBaptiste Daroussin 82*d0ef721eSBaptiste Daroussin 83*d0ef721eSBaptiste Daroussin /* hist_set(): 84*d0ef721eSBaptiste Daroussin * Set new history interface 85*d0ef721eSBaptiste Daroussin */ 86*d0ef721eSBaptiste Daroussin libedit_private int 87*d0ef721eSBaptiste Daroussin hist_set(EditLine *el, hist_fun_t fun, void *ptr) 88*d0ef721eSBaptiste Daroussin { 89*d0ef721eSBaptiste Daroussin 90*d0ef721eSBaptiste Daroussin el->el_history.ref = ptr; 91*d0ef721eSBaptiste Daroussin el->el_history.fun = fun; 92*d0ef721eSBaptiste Daroussin return 0; 93*d0ef721eSBaptiste Daroussin } 94*d0ef721eSBaptiste Daroussin 95*d0ef721eSBaptiste Daroussin 96*d0ef721eSBaptiste Daroussin /* hist_get(): 97*d0ef721eSBaptiste Daroussin * Get a history line and update it in the buffer. 98*d0ef721eSBaptiste Daroussin * eventno tells us the event to get. 99*d0ef721eSBaptiste Daroussin */ 100*d0ef721eSBaptiste Daroussin libedit_private el_action_t 101*d0ef721eSBaptiste Daroussin hist_get(EditLine *el) 102*d0ef721eSBaptiste Daroussin { 103*d0ef721eSBaptiste Daroussin const wchar_t *hp; 104*d0ef721eSBaptiste Daroussin int h; 105*d0ef721eSBaptiste Daroussin size_t blen, hlen; 106*d0ef721eSBaptiste Daroussin 107*d0ef721eSBaptiste Daroussin if (el->el_history.eventno == 0) { /* if really the current line */ 108*d0ef721eSBaptiste Daroussin (void) wcsncpy(el->el_line.buffer, el->el_history.buf, 109*d0ef721eSBaptiste Daroussin el->el_history.sz); 110*d0ef721eSBaptiste Daroussin el->el_line.lastchar = el->el_line.buffer + 111*d0ef721eSBaptiste Daroussin (el->el_history.last - el->el_history.buf); 112*d0ef721eSBaptiste Daroussin 113*d0ef721eSBaptiste Daroussin #ifdef KSHVI 114*d0ef721eSBaptiste Daroussin if (el->el_map.type == MAP_VI) 115*d0ef721eSBaptiste Daroussin el->el_line.cursor = el->el_line.buffer; 116*d0ef721eSBaptiste Daroussin else 117*d0ef721eSBaptiste Daroussin #endif /* KSHVI */ 118*d0ef721eSBaptiste Daroussin el->el_line.cursor = el->el_line.lastchar; 119*d0ef721eSBaptiste Daroussin 120*d0ef721eSBaptiste Daroussin return CC_REFRESH; 121*d0ef721eSBaptiste Daroussin } 122*d0ef721eSBaptiste Daroussin if (el->el_history.ref == NULL) 123*d0ef721eSBaptiste Daroussin return CC_ERROR; 124*d0ef721eSBaptiste Daroussin 125*d0ef721eSBaptiste Daroussin hp = HIST_FIRST(el); 126*d0ef721eSBaptiste Daroussin 127*d0ef721eSBaptiste Daroussin if (hp == NULL) 128*d0ef721eSBaptiste Daroussin return CC_ERROR; 129*d0ef721eSBaptiste Daroussin 130*d0ef721eSBaptiste Daroussin for (h = 1; h < el->el_history.eventno; h++) 131*d0ef721eSBaptiste Daroussin if ((hp = HIST_NEXT(el)) == NULL) 132*d0ef721eSBaptiste Daroussin goto out; 133*d0ef721eSBaptiste Daroussin 134*d0ef721eSBaptiste Daroussin hlen = wcslen(hp) + 1; 135*d0ef721eSBaptiste Daroussin blen = (size_t)(el->el_line.limit - el->el_line.buffer); 136*d0ef721eSBaptiste Daroussin if (hlen > blen && !ch_enlargebufs(el, hlen)) 137*d0ef721eSBaptiste Daroussin goto out; 138*d0ef721eSBaptiste Daroussin 139*d0ef721eSBaptiste Daroussin memcpy(el->el_line.buffer, hp, hlen * sizeof(*hp)); 140*d0ef721eSBaptiste Daroussin el->el_line.lastchar = el->el_line.buffer + hlen - 1; 141*d0ef721eSBaptiste Daroussin 142*d0ef721eSBaptiste Daroussin if (el->el_line.lastchar > el->el_line.buffer 143*d0ef721eSBaptiste Daroussin && el->el_line.lastchar[-1] == '\n') 144*d0ef721eSBaptiste Daroussin el->el_line.lastchar--; 145*d0ef721eSBaptiste Daroussin if (el->el_line.lastchar > el->el_line.buffer 146*d0ef721eSBaptiste Daroussin && el->el_line.lastchar[-1] == ' ') 147*d0ef721eSBaptiste Daroussin el->el_line.lastchar--; 148*d0ef721eSBaptiste Daroussin #ifdef KSHVI 149*d0ef721eSBaptiste Daroussin if (el->el_map.type == MAP_VI) 150*d0ef721eSBaptiste Daroussin el->el_line.cursor = el->el_line.buffer; 151*d0ef721eSBaptiste Daroussin else 152*d0ef721eSBaptiste Daroussin #endif /* KSHVI */ 153*d0ef721eSBaptiste Daroussin el->el_line.cursor = el->el_line.lastchar; 154*d0ef721eSBaptiste Daroussin 155*d0ef721eSBaptiste Daroussin return CC_REFRESH; 156*d0ef721eSBaptiste Daroussin out: 157*d0ef721eSBaptiste Daroussin el->el_history.eventno = h; 158*d0ef721eSBaptiste Daroussin return CC_ERROR; 159*d0ef721eSBaptiste Daroussin 160*d0ef721eSBaptiste Daroussin } 161*d0ef721eSBaptiste Daroussin 162*d0ef721eSBaptiste Daroussin 163*d0ef721eSBaptiste Daroussin /* hist_command() 164*d0ef721eSBaptiste Daroussin * process a history command 165*d0ef721eSBaptiste Daroussin */ 166*d0ef721eSBaptiste Daroussin libedit_private int 167*d0ef721eSBaptiste Daroussin hist_command(EditLine *el, int argc, const wchar_t **argv) 168*d0ef721eSBaptiste Daroussin { 169*d0ef721eSBaptiste Daroussin const wchar_t *str; 170*d0ef721eSBaptiste Daroussin int num; 171*d0ef721eSBaptiste Daroussin HistEventW ev; 172*d0ef721eSBaptiste Daroussin 173*d0ef721eSBaptiste Daroussin if (el->el_history.ref == NULL) 174*d0ef721eSBaptiste Daroussin return -1; 175*d0ef721eSBaptiste Daroussin 176*d0ef721eSBaptiste Daroussin if (argc == 1 || wcscmp(argv[1], L"list") == 0) { 177*d0ef721eSBaptiste Daroussin size_t maxlen = 0; 178*d0ef721eSBaptiste Daroussin char *buf = NULL; 179*d0ef721eSBaptiste Daroussin int hno = 1; 180*d0ef721eSBaptiste Daroussin /* List history entries */ 181*d0ef721eSBaptiste Daroussin 182*d0ef721eSBaptiste Daroussin for (str = HIST_LAST(el); str != NULL; str = HIST_PREV(el)) { 183*d0ef721eSBaptiste Daroussin char *ptr = 184*d0ef721eSBaptiste Daroussin ct_encode_string(str, &el->el_scratch); 185*d0ef721eSBaptiste Daroussin size_t len = strlen(ptr); 186*d0ef721eSBaptiste Daroussin if (len > 0 && ptr[len - 1] == '\n') 187*d0ef721eSBaptiste Daroussin ptr[--len] = '\0'; 188*d0ef721eSBaptiste Daroussin len = len * 4 + 1; 189*d0ef721eSBaptiste Daroussin if (len >= maxlen) { 190*d0ef721eSBaptiste Daroussin maxlen = len + 1024; 191*d0ef721eSBaptiste Daroussin char *nbuf = el_realloc(buf, maxlen); 192*d0ef721eSBaptiste Daroussin if (nbuf == NULL) { 193*d0ef721eSBaptiste Daroussin el_free(buf); 194*d0ef721eSBaptiste Daroussin return -1; 195*d0ef721eSBaptiste Daroussin } 196*d0ef721eSBaptiste Daroussin buf = nbuf; 197*d0ef721eSBaptiste Daroussin } 198*d0ef721eSBaptiste Daroussin strvis(buf, ptr, VIS_NL); 199*d0ef721eSBaptiste Daroussin (void) fprintf(el->el_outfile, "%d\t%s\n", 200*d0ef721eSBaptiste Daroussin hno++, buf); 201*d0ef721eSBaptiste Daroussin } 202*d0ef721eSBaptiste Daroussin el_free(buf); 203*d0ef721eSBaptiste Daroussin return 0; 204*d0ef721eSBaptiste Daroussin } 205*d0ef721eSBaptiste Daroussin 206*d0ef721eSBaptiste Daroussin if (argc != 3) 207*d0ef721eSBaptiste Daroussin return -1; 208*d0ef721eSBaptiste Daroussin 209*d0ef721eSBaptiste Daroussin num = (int)wcstol(argv[2], NULL, 0); 210*d0ef721eSBaptiste Daroussin 211*d0ef721eSBaptiste Daroussin if (wcscmp(argv[1], L"size") == 0) 212*d0ef721eSBaptiste Daroussin return history_w(el->el_history.ref, &ev, H_SETSIZE, num); 213*d0ef721eSBaptiste Daroussin 214*d0ef721eSBaptiste Daroussin if (wcscmp(argv[1], L"unique") == 0) 215*d0ef721eSBaptiste Daroussin return history_w(el->el_history.ref, &ev, H_SETUNIQUE, num); 216*d0ef721eSBaptiste Daroussin 217*d0ef721eSBaptiste Daroussin return -1; 218*d0ef721eSBaptiste Daroussin } 219*d0ef721eSBaptiste Daroussin 220*d0ef721eSBaptiste Daroussin /* hist_enlargebuf() 221*d0ef721eSBaptiste Daroussin * Enlarge history buffer to specified value. Called from el_enlargebufs(). 222*d0ef721eSBaptiste Daroussin * Return 0 for failure, 1 for success. 223*d0ef721eSBaptiste Daroussin */ 224*d0ef721eSBaptiste Daroussin libedit_private int 225*d0ef721eSBaptiste Daroussin /*ARGSUSED*/ 226*d0ef721eSBaptiste Daroussin hist_enlargebuf(EditLine *el, size_t oldsz, size_t newsz) 227*d0ef721eSBaptiste Daroussin { 228*d0ef721eSBaptiste Daroussin wchar_t *newbuf; 229*d0ef721eSBaptiste Daroussin 230*d0ef721eSBaptiste Daroussin newbuf = el_realloc(el->el_history.buf, newsz * sizeof(*newbuf)); 231*d0ef721eSBaptiste Daroussin if (!newbuf) 232*d0ef721eSBaptiste Daroussin return 0; 233*d0ef721eSBaptiste Daroussin 234*d0ef721eSBaptiste Daroussin (void) memset(&newbuf[oldsz], '\0', (newsz - oldsz) * sizeof(*newbuf)); 235*d0ef721eSBaptiste Daroussin 236*d0ef721eSBaptiste Daroussin el->el_history.last = newbuf + 237*d0ef721eSBaptiste Daroussin (el->el_history.last - el->el_history.buf); 238*d0ef721eSBaptiste Daroussin el->el_history.buf = newbuf; 239*d0ef721eSBaptiste Daroussin el->el_history.sz = newsz; 240*d0ef721eSBaptiste Daroussin 241*d0ef721eSBaptiste Daroussin return 1; 242*d0ef721eSBaptiste Daroussin } 243*d0ef721eSBaptiste Daroussin 244*d0ef721eSBaptiste Daroussin libedit_private wchar_t * 245*d0ef721eSBaptiste Daroussin hist_convert(EditLine *el, int fn, void *arg) 246*d0ef721eSBaptiste Daroussin { 247*d0ef721eSBaptiste Daroussin HistEventW ev; 248*d0ef721eSBaptiste Daroussin if ((*(el)->el_history.fun)((el)->el_history.ref, &ev, fn, arg) == -1) 249*d0ef721eSBaptiste Daroussin return NULL; 250*d0ef721eSBaptiste Daroussin return ct_decode_string((const char *)(const void *)ev.str, 251*d0ef721eSBaptiste Daroussin &el->el_scratch); 252*d0ef721eSBaptiste Daroussin } 253