blob: 954020ef29a497a59992fa2eb3787abe952d0fbc [file] [log] [blame]
/*************************************************************************
*
// @@@ START COPYRIGHT @@@
//
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// @@@ END COPYRIGHT @@@
**************************************************************************/
/*
* mreadline - v1.1.0
* vim:hls:ru:scs:si:sm:sw=4:sta:ts=4:tw=0
*
* Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away.
* -- Antoine de Saint Exupéry
*/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <ctype.h>
#define LINE_CHUNK 256 /* line buffer chunks */
#define PRMP_CHUNK 64 /* prompt chunks */
#ifdef __CYGWIN__
#undef WORD
#include <windows.h>
#undef _WIN32
#endif
#ifdef _WIN32
#include <windows.h>
CONSOLE_SCREEN_BUFFER_INFO _wsz; /* used to get terminal size */
#else
#include <termios.h>
#include <unistd.h>
#include <sys/ioctl.h>
struct winsize _wsz; /* used to get terminal size */
struct termios _oattr; /* old terminal attr */
char *_tmpfil = "/tmp/mrXXXXXX"; /* tmp file name template */
#endif
char **_mrhist = 0; /* history records array */
size_t *_mrhll = 0; /* history records length array */
size_t *_mrhms = 0; /* history records allocated array */
unsigned int _mrhsize = 200, /* default history size */
_mrcy = 0, /* Current Y cursor position */
_mrhfirst = 0, /* First (older) history element index */
_mrhcount = 0, /* Number of history records */
_mrchg = 0; /* Change flag: 1=yes, 0=no */
unsigned int mrcol = 80; /* number of screen columns */
unsigned int _mrp = PRMP_CHUNK; /* mrprompt buffer size */
char *_mrprompt = 0; /* mreadline prompt string */
char *_mredit = 0;
char _mrinit = 0; /* init flag is set to 1 during initialization */
/* mrend: end mreadline
*
* input: none
* return: void
*/
void mrend ( void )
{
unsigned int i = 0, /* loop variable */
mx = 0; /* history index */
for ( i = 0 ; i < _mrhcount ; i++ ) {
mx = ( _mrhfirst + i ) % _mrhsize ;
if ( _mrhist[mx] )
free ( _mrhist[mx] ) ;
}
if ( _mrhist[_mrhsize] )
free ( _mrhist[_mrhsize] );
if ( _mrhist[_mrhsize + 1] )
free ( _mrhist[_mrhsize + 1] );
if ( _mrhist )
free ( _mrhist );
if ( _mrhms )
free ( _mrhms );
if ( _mrhll )
free ( _mrhll );
if ( _mrprompt )
free ( _mrprompt ); /* free prompt memory */
#ifndef _WIN32
(void)tcsetattr (0, TCSANOW, &_oattr);
#endif
}
/* mrgetcol: Get nummber of screen columns
*
* input: none
* return: void
*/
void mrgetcol( void )
{
#ifdef _WIN32
if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &_wsz))
mrcol = (unsigned int)(_wsz.srWindow.Right - _wsz.srWindow.Left) - 1;
#else
(void)ioctl(0, TIOCGWINSZ, &_wsz);
if ( _wsz.ws_col > 0 )
mrcol = (unsigned int)_wsz.ws_col;
#endif
}
/* mrinit: initialize mreadline
*
* input: none
* return: 0 = status ok, 1 errors
*/
int mrinit ( void )
{
#ifndef _WIN32
struct termios tattr;
/* Make sure stdin is a terminal. */
if (!isatty (0)) {
fprintf (stderr, "[mrinit (%d)] Not a terminal.\n", __LINE__);
exit ( 2 );
}
/* Get nummber of columns */
mrgetcol();
/* Get current terminal attributes */
(void)tcgetattr (0, &_oattr);
/* Set terminal modes. */
tattr = _oattr; /* dup current settings */
tattr.c_lflag &= ~ICANON; /* No Buffering */
//tattr.c_lflag &= ~ISIG; /* Ignore Ctrl-C */
tattr.c_lflag &= ~ECHO; /* No Echo */
tattr.c_cc[VMIN] = 1; /* min number of read chars */
tattr.c_cc[VTIME] = 0; /* no delay after key press */
(void)tcsetattr (0, TCSAFLUSH, &tattr); /* set new attrs */
#endif
/* Allocate initial prompt memory chunk */
if ( ( _mrprompt = malloc ( PRMP_CHUNK ) ) == (void *) NULL ) {
fprintf(stderr, "[mreadline (%d)] Error %d allocating _mrprompt memory:%s\n",
__LINE__, errno, strerror(errno));
return ( 1 );
}
/* Get editor */
_mredit = getenv("_mredit");
if ( !_mredit )
_mredit = getenv("EDITOR");
return ( 0 );
}
#ifndef _WIN32
/* _mrefresh: refresh input line
*
* prompt: prompt string. If prompt is Null move the cursor without re-printing current line
* pl: prompt length
* line: string to display
* ps: cursor position in line
* return: void
*/
void _mrefresh ( char *prompt, unsigned int pl, char *line, unsigned int ps )
{
unsigned int i = 0, /* loop variable */
j = 0, /* loop variable */
cx = 0, /* new Cursor position X (column from line start) */
cy = 0, /* new Cursor position Y (lines from bottom) */
n = 0; /* number of lines in line */
for ( i = 0, j = 0 ; line[i]; i++, j++) {
if ( line[i] == '\n' || j >= mrcol ||
( i + pl < mrcol && j + pl >= mrcol - 1 ) ) {
n++;
j = 0;
}
if ( ps - 1 == i ) {
cy = n ;
cx = j ;
}
}
if ( prompt ) { /* if we have to re-print the line */
if ( _mrcy ) { /* previous line cy */
if ( !_mrchg || ( _mrchg && n ) )
printf("\033[%uF", _mrcy); /* go up _mrcy lines to col #0 (beginning of the line) */
} else { /* everything on one row */
(void)fputs ("\033[0G", stdout ); /* cursor to the left */
}
(void)fputs ("\033[J", stdout); /* erase below */
(void)fputs ( prompt, stdout ); /* write prompt */
(void)fputs ( line, stdout ); /* write line */
if ( n > cy )
printf("\033[%uF", n - cy); /* go up to the beginning of the line */
} else {
if ( _mrcy > cy )
printf("\033[%uF", _mrcy - cy); /* go up to the beginning of the line */
else if ( _mrcy < cy )
printf("\033[%uE", cy - _mrcy);
(void)fputs ("\033[0G", stdout ); /* cursor to the left */
}
if ( cy ) {
if ( cx )
printf("\033[0G\033[%uC", cx );
else if ( ps == i )
fputc('\n', stdout);
} else {
printf("\033[0G\033[%uC", ps + pl );
}
(void)fflush(stdout); /* flush stdout */
_mrcy = cy; /* save current cursor y position */
}
#endif
/* mrhadd: add history record
*
* hrec: history record to add
* hl: history record length
* return: 0 OK, -1 errors
*/
int mrhadd(char *hrec, size_t hl)
{
#ifndef _WIN32
unsigned int next = 0, /* History record element to use */
last = 0; /* Previous history record */
if ( ! _mrinit ) { /* Not during the initialization */
/* do not store empty commands */
if ( !hl )
return ( 0 );
/* do not store consecutive entry of the same command */
last = ( _mrhfirst + _mrhcount - 1 ) % _mrhsize ;
if ( hl == _mrhll[last] )
if ( !strcmp(hrec, _mrhist[last]) )
return ( 0 ) ;
}
next = ( _mrhfirst + _mrhcount ) % _mrhsize ;
if ( hl >= _mrhms[next] ) { /* new memory to be allocated for this element */
if ( ( _mrhist[next] = realloc ( _mrhist[next], hl + 1 ) ) == (void *)NULL ) {
fprintf(stderr, "[mreadline (%d)] - Error %d allocating _mrhist memory element %d: %s\n",
__LINE__, errno, next, strerror(errno));
return(-1);
}
_mrhms[next] = hl + 1 ; /* Update history memory array */
}
memcpy(_mrhist[next], hrec, hl); /* Copy history element */
_mrhist[next][hl] = '\0'; /* Put a NULL at the end */
_mrhll[next] = hl; /* Update history length array */
if ( _mrhcount < _mrhsize ) /* If history array is NOT full... */
_mrhcount++; /* Increase count (first element unchanged) */
else /* If history array is full... */
_mrhfirst = next + 1; /* Increase first element (count unchanged) */
#endif
return(0);
}
/* mrhinit: history init
*
* hsize: history size. If zero use default _mrhsize
* hfile: history file. If NULL use ./._mrhistory
* return: 0=OK, 1=problems with history file != No such file, 2/3/4 = memory allocation error
*/
int mrhinit(size_t hsize, char *hfile)
{
#ifndef _WIN32
FILE *fh; /* history file pointer */
int ch; /* char read from history file */
char *hrec; /* history record buffer */
#endif
size_t hl = 0; /* history record length */
size_t hrl = LINE_CHUNK; /* history buffer size */
_mrinit = 1; /* switch on initialization flag */
if ( hsize )
_mrhsize = (unsigned int)hsize;
/* history buffer memory allocation (extra '_mrhsize' elements to hold & save current line when browsing hist */
if ( ( _mrhist = (char **)calloc (_mrhsize+2, sizeof(char *))) == (void *)NULL ) {
fprintf(stderr, "[mrhinit (%d)] - Error %d allocating history record array: %s\n",
__LINE__, errno, strerror(errno));
return (2);
}
if ( ( _mrhist[_mrhsize] = malloc (LINE_CHUNK)) == (void *)NULL ) {
fprintf(stderr, "[mrhinit (%d)] - Error %d allocating _mrhist[mrsize]: %s\n",
__LINE__, errno, strerror(errno));
return (2);
}
if ( ( _mrhll = (size_t *)calloc (_mrhsize+2, sizeof(size_t))) == (void *)NULL ) {
fprintf(stderr, "[mrhinit (%d)] - Error %d allocating history lenght array: %s\n",
__LINE__, errno, strerror(errno));
return (3);
}
if ( ( _mrhms = (size_t *)calloc (_mrhsize+2, sizeof(size_t))) == (void *)NULL ) {
fprintf(stderr, "[mrhinit (%d)] - Error %d allocating history memorylenght array: %s\n",
__LINE__, errno, strerror(errno));
return (3);
}
_mrhms[_mrhsize]=LINE_CHUNK;
#ifndef _WIN32
if ( ( fh = fopen(hfile ? hfile : "._mrhistory" , "r" ) ) == (FILE *)NULL ) {
if ( errno == ENOENT ) { /* history file does not exists */
fprintf(stderr, "[mrhinit (%d)] - Warning history file %s does not exist\n",
__LINE__, hfile ? hfile : "._mrhistory" );
return ( 0 );
}
fprintf(stderr, "[mrhinit (%d)] - Error %d opening history file %s: %s\n",
__LINE__, errno, hfile ? hfile : "._mrhistory", strerror(errno) );
return ( 1 );
}
if ( ( hrec = malloc ( hrl ) ) == (void *) NULL ) {
fprintf(stderr, "[mrhinit (%d)] Error %d allocating memory: %s\n",
__LINE__, errno, strerror(errno));
return (4);
}
while ( ( ch = fgetc(fh) ) ) {
if ( ch == 1 ) { /* End of record (CTRL-A) */
if ( mrhadd ( hrec, hl ) )
fprintf(stderr, "[mrhinit (%d)] Error setting history\n", __LINE__);
hl = 0;
} else if ( feof ( fh ) ) { /* End of history file */
if ( hl )
if( mrhadd ( hrec, hl ) )
fprintf(stderr, "[mrhinit (%d)] Error setting history\n", __LINE__);
break;
} else {
if ( ( hl + 1 ) == hrl ) { /* history record needs more memory */
hrl += LINE_CHUNK ;
if ( ( hrec = realloc(hrec, hrl)) == (void *)NULL ) {
fprintf(stderr,
"[mrhinit (%d)] - Error %d reallocating hrec memory: %s\n",
__LINE__, errno, strerror(errno));
return(5);
}
}
hrec[hl++] = (char)ch;
}
}
free ( hrec );
(void)fclose ( fh );
#endif
_mrinit = 0; /* switch off initialization flag */
return(0);
}
/* mrhsave: save history record
*
* hfile: history file. If NULL use ./._mrhistory
* return: void
*/
int mrhsave(char *hfile)
{
#ifndef _WIN32
FILE *fh; /* history file pointer */
unsigned int mx = 0, /* history index */
i = 0; /* loop variable */
if ( ( fh = fopen(hfile ? hfile : "._mrhistory" , "w" ) ) == (FILE *)NULL ) {
fprintf(stderr, "[mrhinit (%d)] - Error %d opening history file %s: %s\n",
__LINE__, errno, hfile ? hfile : "._mrhistory", strerror(errno) );
return (3);
}
for ( i = 0 ; i < _mrhcount ; i++ ) {
mx = ( _mrhfirst + i ) % _mrhsize ;
(void)fputs ( _mrhist[mx] , fh ); /* write history record */
(void)fputc ( 1 , fh ); /* write history record separator */
}
(void)fclose ( fh );
#endif
return ( 0 );
}
/* _mrcpbuff: copy history buffer elements
*
* src: source history buffer index
* tgt: target history buffer index
* return: 0=OK, 1=ERROR
*/
unsigned int _mrcpbuff(unsigned int src, unsigned int tgt)
{
if ( _mrhms[tgt] <= _mrhll[src] ) { /* tgt need more memory */
_mrhms[tgt] = _mrhll[src] + 1 ;
if ( (_mrhist[tgt]=realloc(_mrhist[tgt], _mrhms[tgt])) == (void *)NULL ) {
fprintf(stderr, "[mreadline (%d)] - Error %d reallocating _mrhist[%d] memory: %s\n",
__LINE__, errno, tgt, strerror(errno));
return(1);
}
}
if ( _mrhll[src] ) {
memcpy(_mrhist[tgt], _mrhist[src], _mrhll[src] + 1 ); /* +1 is to copy the ending NULL */
} else {
_mrhist[tgt][0] = '\0';
}
_mrhll[tgt] = _mrhll[src];
return ( 0 );
}
/* mreadline: read next line
*
* input: prompt
* return: line read
*/
char *mreadline ( char *prompt, unsigned int *length )
{
char *mrline = _mrhist[_mrhsize]; /* local pointer to current buffer */
#ifndef _WIN32
int fd = 0; /* tmp file descriptor */
char buff[128]; /* edit buffer */
char tfile[14]; /* temporary file name */
ssize_t ret = 0; /* read return value */
unsigned int ps = 0, /* cursor position in mrline */
pss = 0, /* cursor position in mrline save */
nx = 0, /* to store temporary prev/next index */
mx = 0; /* history index delta respect current buffer */
#endif
unsigned int i = 0, /* loop variable */
q = 0; /* Quoted Text Flag */
size_t ll = 0, /* current buffer (_mrhist[mrsize]) length */
pl = 0, /* prompt length (visible characters) */
j = 0; /* loop variable */
int c; /* read char */
/* Initialize edit flag */
_mrchg = 0 ;
/* Print Prompt */
(void)fflush ( stdout );
for ( i = 0, pl = 0, q = 0 ; prompt[i] ; i++ ) {
if ( prompt[i] == 1 ) {
q = q ? 0 : 1;
} else {
if ( j > _mrp - 1 ) { /* _mrprompt needs more memory */
_mrp += PRMP_CHUNK;
if ( (_mrprompt=realloc(_mrprompt, (size_t)_mrp)) == (void *)NULL ) {
fprintf(stderr, "[mreadline (%d)] - Error %d reallocating _mrprompt memory: %s\n",
__LINE__, errno, strerror(errno));
return((char *)NULL);
}
}
_mrprompt[j++] = prompt[i];
if ( !q )
pl++;
}
}
_mrprompt[j]='\0';
(void)fputs ( _mrprompt, stdout );
/* Main loop */
while ( ( c = fgetc(stdin) ) ) {;
#ifdef _WIN32
if ( c != 3 )
*(mrline + ll++) = c;
#else
switch ( c ) {
case 1: /* CTRL-A: go to line start */
ps = 0;
_mrefresh( (char *)NULL, pl, mrline, ps );
break;
case 2: /* CTRL-B: cursor back */
back:
if ( ps ) {
ps--;
_mrefresh( (char *)NULL, pl, mrline, ps );
}
break;
case 4: /* CTRL-D: EOF */
if ( ll == 0 ) { /* if is the first char... */
return ( (char *) EOF ); /* ...return EOF */
} else if ( ps < ll ) { /* remove to the right */
memmove(mrline+ps, mrline+ps+1, ll - ps);
mrline[--ll] = '\0';
_mrefresh( _mrprompt, pl, mrline, ps );
}
break;
case 5: /* CTRL-E: go to line end */
ps = ll;
_mrefresh( (char *)NULL, pl, mrline, ps );
break;
case 6: /* CTRL-F: cursor forward */
forward:
if ( ps < ll ) {
ps++;
_mrefresh( (char *)NULL, pl, mrline, ps );
}
break;
case 7: /* CTRL-G: go to history record */
mx = (unsigned int) atoi(mrline);
if ( _mrhist[mx] ) {
memcpy ( (void *)mrline, (void *)_mrhist[mx], (size_t)_mrhll[mx] );
ll = ps = _mrhll[mx];
mrline[ll] = '\0';
} else {
fprintf(stderr, "[mrhinit (%d)] - Error. Cannot access history entry %d\n",
__LINE__, mx );
}
_mrefresh( _mrprompt, pl, mrline, ps );
break;
case 8: /* CTRL-H: Back Space */
case 127: /* Delete */
if ( ps ) {
memmove( mrline+ps-1, mrline+ps, ll - ps );
ps--;
mrline[--ll] = '\0';
}
_mrchg = 1 ;
_mrefresh( _mrprompt, pl, mrline, ps );
break;
case 9: /* Horizontal Tab */
break; /* do nothing */
case 10: /* New Line: just echo */
if ( ll ) /* move to buffer end if any */
_mrefresh( (char *)NULL, pl, mrline, ll );
(void)fputc ( c, stdout );
_mrcy = 0; /* reset previous line Y */
break;
case 12: /* CTRL-L: to lower */
for ( i = 0, q = 0 ; i < (unsigned int)ll ; i++ )
if ( mrline[i] == '\'' )
q = q ? 0 : 1 ;
else if ( !q )
mrline[i] = (char)tolower ( (int)mrline[i] );
_mrefresh( _mrprompt, pl, mrline, ps );
break;
case 14: /* CTRL-N: history next */
histnext:
if ( mx )
mx--;
if ( mx ) {
nx = ( _mrhcount + _mrhfirst - mx ) % _mrhsize ;
mrline = _mrhist[ nx ];
ll = ps = _mrhll[ nx ];
} else { /* restore current buffer */
_mrcpbuff(_mrhsize+1, _mrhsize); /* copy saved buffer into current buffer */
ll = _mrhll[ _mrhsize ] ;
ps = pss ;
mrline = _mrhist[_mrhsize];
}
_mrefresh( _mrprompt, pl, mrline, ps );
break;
case 16: /* CTRL-P: history previous */
histprev:
if ( !mx ) {
_mrhll[ _mrhsize ] = ll ;
if ( ll ) {
_mrcpbuff(_mrhsize, _mrhsize+1);/* save current buffer */
pss = ps; /* save current buffer position */
}
}
if ( mx < _mrhcount )
mx++;
nx = ( _mrhcount + _mrhfirst - mx ) % _mrhsize ;
_mrcpbuff(nx, _mrhsize); /* copy buffer nx in current buffer */
ll = ps = _mrhll[ nx ];
mrline = _mrhist[_mrhsize];
_mrefresh( _mrprompt, pl, mrline, ps );
break;
case 23: /* CTRL-W: List History */
(void)fputc ( '\n' , stdout );
for ( i = 0 ; i < _mrhcount ; i++ ) {
nx = ( _mrhfirst + i ) % _mrhsize ;
fprintf(stdout, "%5d: %s\n", nx, _mrhist[nx]);
}
mrline[ll] = '\0';
_mrefresh( _mrprompt, pl, mrline, ps );
break;
case 18: /* CTRL-R: redraw */
mrgetcol();
_mrefresh( _mrprompt, pl, mrline, ps );
break;
case 21: /* CTRL-U: to upper */
for ( i = 0, q = 0 ; i < (unsigned int)ll ; i++ )
if ( mrline[i] == '\'' )
q = q ? 0 : 1 ;
else if ( !q )
mrline[i] = (char)toupper ( (int)mrline[i] );
_mrefresh( _mrprompt, pl, mrline, ps );
break;
case 22: /* CTRL-V: edit current line */
if ( !_mredit ) {
fprintf(stderr, "[mreadline (%d)] - Error: neither _mredit nor EDITOR are set(_mredit=>%s<\n",
__LINE__, _mredit);
break;
}
strncpy ( tfile, _tmpfil, sizeof(tfile) ) ; /* tmp file name */
if ( ( fd = mkstemp(tfile) ) == ( -1 ) ) {
fprintf(stderr, "[mreadline (%d)] - Error %d creating tmp file: %s\n",
__LINE__, errno, strerror(errno));
} else {
if ( (unsigned int)( ret = write ( fd, mrline, (size_t)ll ) ) != ll )
fprintf(stderr, "[mreadline (%d)] - Error %d writing tmp file: %s\n",
__LINE__, errno, strerror(errno));
(void)fsync ( fd );
(void)snprintf(buff, sizeof(buff), "%s %s", _mredit, tfile);
if ( system(buff) < 0 )
fprintf(stderr, "[mreadline (%d)] - Error running %s\n", __LINE__, buff);
mrline[0] = '\0';
ll = 0;
(void)lseek ( fd, (off_t)0, SEEK_SET ) ;
while ( ( ret = read ( fd, buff, sizeof(buff) ) ) ) {
if ( ret == ( -1 ) ) {
fprintf(stderr, "[mreadline (%d)] - Error %d reading tmp file: %s\n",
__LINE__, errno, strerror(errno));
break;
}
while ( ( ll + (unsigned int)ret ) >= _mrhms[_mrhsize] ) { /* mrline needs more memory */
_mrhms[_mrhsize] += LINE_CHUNK;
if ( (_mrhist[_mrhsize]=realloc(_mrhist[_mrhsize], _mrhms[_mrhsize])) == (void *)NULL ) {
fprintf(stderr, "[mreadline (%d)] - Error %d reallocating mrline memory: %s\n",
__LINE__, errno, strerror(errno));
return((char *)NULL);
}
}
mrline = _mrhist[_mrhsize];
strncat ( mrline, buff, (size_t) ret ) ;
ll += ret;
}
(void)close ( fd ); /* close temporary file */
(void)unlink ( tfile ); /* remove temporary file */
if ( mrline[ll-1] == '\n' )
mrline[--ll] = '\0'; /* exclude last \n added by vi */
ps = ll; /* set cursor position to the end */
_mrefresh( _mrprompt, pl, mrline, ps );
}
break;
case 24: /* CTRL-X: Clear line */
ll = 0;
(void)fputc ( '\n' , stdout );
return ((char *)(-2));
case 26: /* CTRL-Z: Return last history entry (repeat command) */
nx = ( _mrhcount + _mrhfirst - 1 ) % _mrhsize ;
*length = ps = _mrhll[nx];
_mrcpbuff(nx, _mrhsize); /* copy buffer nx in current buffer */
_mrefresh( _mrprompt, pl, mrline, ps );
(void)fputc ( '\n' , stdout );
_mrcy = 0; /* reset previous line Y */
return (mrline);
case 27: /* Escape: */
if ( ( c = fgetc(stdin) ) == 91 ) {
switch ( ( c = fgetc(stdin) ) ) {
case 65: /* Up Arrow */
goto histprev;
case 66: /* Down Arrow */
goto histnext;
case 67: /* Right Arrow */
goto forward;
case 68: /* Left Arrow */
goto back;
}
}
break;
default: /* Edit current buffer */
if ( ps != ll ) {
memmove(mrline+ps+1, mrline+ps, ll - ps);
mrline[ps++] = (char)c;
mrline[++ll] = '\0';
_mrefresh( _mrprompt, pl, mrline, ps );
} else {
mrline[ps++] = (char)c;
mrline[++ll] = '\0';
(void)fputc ( c, stdout );
if ( ( ps + pl ) % mrcol == 0 )
(void)fputc ( '\n', stdout );
_mrcy = ( ps + pl ) / mrcol ;
}
}
#endif
if( ll > _mrhms[_mrhsize] ) { /* mrline needs more memory */
_mrhms[_mrhsize] += LINE_CHUNK;
if ( (_mrhist[_mrhsize]=realloc(_mrhist[_mrhsize], _mrhms[_mrhsize])) == (void *)NULL ) {
fprintf(stderr, "[mreadline (%d)] - Error %d reallocating _mrhist[_mrhsize] memory: %s\n",
__LINE__, errno, strerror(errno));
return((char *)NULL);
}
mrline = _mrhist[_mrhsize] ;
}
if ( (char)c == '\n' ) {
break;
}
}
/* End */
#ifdef _WIN32
if ( mrline[ll-1] == '\n' )
ll--;
#endif
*length = (unsigned int) ll ; /* Write line length */
mrline[ll] = '\0';
return ( mrline ); /* return */
}
/* mresize: check if mreadline buffer should be resized
*
* size: new mreadline size
* return: pointer to new (or old if not resized) _mrhist[_mrhsize]
*/
char *mresize(size_t size)
{
if ( size > _mrhms[_mrhsize] ) {
if ( (_mrhist[_mrhsize]=realloc(_mrhist[_mrhsize], size)) == (void *)NULL ) {
fprintf(stderr, "[mreadline (%d)] - Error %d reallocating _mrhist[_mrhsize] memory: %s\n",
__LINE__, errno, strerror(errno));
return((char *)NULL);
}
_mrhms[_mrhsize] = size;
}
return ( _mrhist[_mrhsize] );
}