This source file includes following definitions.
- linenoiseMaskModeEnable
- linenoiseMaskModeDisable
- linenoiseSetMultiLine
- isUnsupportedTerm
- enableRawMode
- disableRawMode
- getCursorPosition
- getColumns
- linenoiseClearScreen
- linenoiseBeep
- freeCompletions
- completeLine
- linenoiseSetCompletionCallback
- linenoiseSetHintsCallback
- linenoiseSetFreeHintsCallback
- linenoiseAddCompletion
- abInit
- abAppend
- abFree
- refreshShowHints
- refreshSingleLine
- refreshMultiLine
- refreshLine
- linenoiseEditInsert
- linenoiseEditMoveLeft
- linenoiseEditMoveRight
- linenoiseEditMoveWordEnd
- linenoiseEditMoveWordStart
- linenoiseEditMoveHome
- linenoiseEditMoveEnd
- linenoiseEditHistoryNext
- linenoiseSearchInHistory
- linenoiseEditDelete
- linenoiseEditBackspace
- linenoiseEditDeletePrevWord
- linenoiseEditDeleteNextWord
- linenoiseEdit
- linenoiseRaw
- linenoiseNoTTY
- linenoise
- linenoiseFree
- freeHistory
- linenoiseAtExit
- linenoiseHistoryAdd
- linenoiseHistorySetMaxLen
- pstrlen
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 
  12 
  13 
  14 
  15 
  16 
  17 
  18 
  19 
  20 
  21 
  22 
  23 
  24 
  25 
  26 
  27 
  28 
  29 
  30 
  31 
  32 
  33 
  34 
  35 
  36 
  37 
  38 
  39 
  40 
  41 
  42 
  43 
  44 
  45 
  46 
  47 
  48 #if !defined(_POSIX_C_SOURCE)
  49 # define _POSIX_C_SOURCE 200809L
  50 #endif 
  51 
  52 #if _POSIX_C_SOURCE < 200809L
  53 # undef _POSIX_C_SOURCE
  54 # define _POSIX_C_SOURCE 200809L
  55 #endif 
  56 
  57 #if !defined(__MINGW32__) && !defined(CROSS_MINGW32) && !defined(CROSS_MINGW64) && \
  58     !defined(__MINGW64__) && !defined(_MSC_VER) && !defined(_MSC_BUILD)
  59 
  60 # if defined(__OpenBSD__)
  61 #  if !defined(_BSD_SOURCE)
  62 #   define _BSD_SOURCE
  63 #  endif
  64 # endif
  65 
  66 # if defined(__sun) && defined(__SVR4)
  67 #  if !defined(__EXTENSIONS__)
  68 #   define __EXTENSIONS__ 1
  69 #  endif 
  70 # endif 
  71 # include <termios.h>
  72 # if defined(__sun) && defined(__SVR4)
  73 #  include <sys/termiox.h>
  74 # endif 
  75 # if defined(__FreeBSD__) || defined(__DragonFly__)
  76 #  if !defined(__BSD_VISIBLE)
  77 #   define __BSD_VISIBLE 1
  78 #  endif
  79 #  include <sys/types.h>
  80 #  include <sys/sysctl.h>
  81 # endif
  82 # include "linehistory.h"
  83 # if !defined(__NetBSD__)
  84 #  include "../dps8/dps8.h"
  85 # endif 
  86 # include <ctype.h>
  87 # include <errno.h>
  88 # include <stdio.h>
  89 # include <stdlib.h>
  90 # include <string.h>
  91 # include <strings.h>
  92 # include <sys/ioctl.h>
  93 # include <sys/stat.h>
  94 # include <sys/types.h>
  95 # include <unistd.h>
  96 
  97 # if defined(FREE)
  98 #  undef FREE
  99 # endif 
 100 # define FREE(p) do  \
 101   {                  \
 102     free((p));       \
 103     (p) = NULL;      \
 104   } while(0)
 105 
 106 # define LINENOISE_DEFAULT_HISTORY_MAX_LEN  100
 107 # define LINENOISE_MAX_LINE                4096
 108 
 109 static char *unsupported_term[] = {
 110   "dumb", "cons25", "emacs", NULL
 111 };
 112 
 113 # if defined(LH_COMPLETION)
 114 static linenoiseCompletionCallback *completionCallback = NULL;
 115 # endif 
 116 
 117 # if defined(LH_HINTS)
 118 static linenoiseHintsCallback *hintsCallback           = NULL;
 119 static linenoiseFreeHintsCallback *freeHintsCallback   = NULL;
 120 # endif 
 121 
 122 static struct termios orig_termios; 
 123 
 124 # if defined(LH_MASKMODE)
 125 static int maskmode          = 0;   
 126 # endif 
 127 
 128 static int rawmode           = 0;
 129 static int mlmode            = 0;   
 130 static int atexit_registered = 0;   
 131 static int history_max_len   = LINENOISE_DEFAULT_HISTORY_MAX_LEN;
 132 static int history_len       = 0;
 133 static char **history        = NULL;
 134 
 135 
 136 
 137 
 138 
 139 
 140 
 141 struct linenoiseState
 142 {
 143   int    ifd;            
 144   int    ofd;            
 145   char   *buf;           
 146   size_t buflen;         
 147   const  char *prompt;   
 148   size_t plen;           
 149   size_t pos;            
 150   size_t oldpos;         
 151   size_t len;            
 152   size_t cols;           
 153   size_t maxrows;        
 154   int    history_index;  
 155 };
 156 
 157 enum KEY_ACTION
 158 {
 159   KEY_NULL  = 0,  
 160   CTRL_A    = 1,  
 161   CTRL_B    = 2,  
 162   CTRL_C    = 3,  
 163   CTRL_D    = 4,  
 164   CTRL_E    = 5,  
 165   CTRL_F    = 6,  
 166   CTRL_H    = 8,  
 167   TAB       = 9,  
 168   CTRL_K    = 11, 
 169   CTRL_L    = 12, 
 170   ENTER     = 13, 
 171   CTRL_N    = 14, 
 172   CTRL_P    = 16, 
 173   CTRL_T    = 20, 
 174   CTRL_U    = 21, 
 175   CTRL_W    = 23, 
 176   ESC       = 27, 
 177   BACKSPACE = 127 
 178 };
 179 
 180 static void linenoiseAtExit(void);
 181 static void refreshLine(struct linenoiseState *l);
 182 size_t pstrlen(const char *s);
 183 
 184 # if defined(LH_MASKMODE)
 185 
 186 
 187 
 188 
 189 
 190 
 191 
 192 
 193 void
 194 linenoiseMaskModeEnable(void)
     
 195 {
 196   maskmode = 1;
 197 }
 198 
 199 
 200 void
 201 linenoiseMaskModeDisable(void)
     
 202 {
 203   maskmode = 0;
 204 }
 205 # endif 
 206 
 207 
 208 void
 209 linenoiseSetMultiLine(int ml)
     
 210 {
 211   mlmode = ml;
 212 }
 213 
 214 
 215 
 216 
 217 
 218 
 219 static int
 220 isUnsupportedTerm(void)
     
 221 {
 222   char *term = getenv("TERM");
 223   int j;
 224 
 225   if (term == NULL)
 226   {
 227     return ( 0 );
 228   }
 229 
 230   for (j = 0; unsupported_term[j]; j++)
 231   {
 232     if (!strcasecmp(term, unsupported_term[j]))
 233     {
 234       return ( 1 );
 235     }
 236   }
 237 
 238   return ( 0 );
 239 }
 240 
 241 
 242 static int
 243 enableRawMode(int fd)
     
 244 {
 245   struct termios raw;
 246 
 247   if (!isatty(STDIN_FILENO))
 248   {
 249     goto fatal;
 250   }
 251 
 252   if (!atexit_registered)
 253   {
 254     atexit(linenoiseAtExit);
 255     atexit_registered = 1;
 256   }
 257 
 258   if (tcgetattr(fd, &orig_termios) == -1)
 259   {
 260     goto fatal;
 261   }
 262 
 263   raw = orig_termios; 
 264   
 265 
 266   raw.c_iflag &= ~( BRKINT | ICRNL | INPCK | ISTRIP | IXON );
 267   
 268   raw.c_cflag |= ( CS8 );
 269   
 270 
 271   raw.c_lflag &= ~( ECHO | ICANON | IEXTEN | ISIG );
 272   
 273 
 274   raw.c_cc[VMIN]  = 1;
 275   raw.c_cc[VTIME] = 0; 
 276 
 277   
 278 # if defined(__ANDROID__)
 279 #  define TCSA_TYPE TCSANOW
 280   (void)fflush(stdout);
 281   (void)fflush(stderr);
 282 # else
 283 #  define TCSA_TYPE TCSAFLUSH
 284 # endif
 285   if (tcsetattr(fd, TCSA_TYPE, &raw) < 0)
 286   {
 287     goto fatal;
 288   }
 289 
 290   rawmode = 1;
 291   return ( 0 );
 292 
 293 fatal:
 294   errno = ENOTTY;
 295   return ( -1 );
 296 }
 297 
 298 static void
 299 disableRawMode(int fd)
     
 300 {
 301   
 302 # if defined(__ANDROID__)
 303   (void)fflush(stdout);
 304   (void)fflush(stderr);
 305 # endif
 306   if (rawmode && tcsetattr(fd, TCSA_TYPE, &orig_termios) != -1)
 307   {
 308     rawmode = 0;
 309   }
 310 }
 311 
 312 
 313 
 314 
 315 
 316 
 317 
 318 static int
 319 getCursorPosition(int ifd, int ofd)
     
 320 {
 321   char     buf[32];
 322   int      cols, rows;
 323   unsigned int i = 0;
 324 
 325   
 326   if (write(ofd, "\x1b[6n", 4) != 4)
 327   {
 328     return ( -1 );
 329   }
 330 
 331   
 332   while (i < sizeof ( buf ) - 1)
 333   {
 334     if (read(ifd, buf + i, 1) != 1)
 335     {
 336       break;
 337     }
 338 
 339     if (buf[i] == 'R')
 340     {
 341       break;
 342     }
 343 
 344     i++;
 345   }
 346   buf[i] = '\0';
 347 
 348   
 349   if (buf[0] != ESC || buf[1] != '[')
 350   {
 351     return ( -1 );
 352   }
 353 
 354   if (sscanf(buf + 2, "%d;%d", &rows, &cols) != 2)
 355   {
 356     return ( -1 );
 357   }
 358 
 359   return ( cols );
 360 }
 361 
 362 
 363 static int
 364 getColumns(int ifd, int ofd)
     
 365 {
 366   struct winsize ws;
 367 
 368   if (ioctl(1, TIOCGWINSZ, &ws) == -1 || ws.ws_col == 0)
 369   {
 370     
 371     int start, cols;
 372 
 373     
 374     start = getCursorPosition(ifd, ofd);
 375     if (start == -1)
 376     {
 377       goto failed;
 378     }
 379 
 380     
 381     if (write(ofd, "\x1b[999C", 6) != 6)
 382     {
 383       goto failed;
 384     }
 385 
 386     cols = getCursorPosition(ifd, ofd);
 387     if (cols == -1)
 388     {
 389       goto failed;
 390     }
 391 
 392     
 393     if (cols > start)
 394     {
 395       char seq[32];
 396       (void)snprintf(seq, sizeof ( seq ), "\x1b[%dD", cols - start);
 397       if (write(ofd, seq, strlen(seq)) == -1) {  }
 398     }
 399 
 400     return ( cols );
 401   }
 402   else
 403   {
 404     return ( ws.ws_col );
 405   }
 406 
 407 failed:
 408   return ( 80 );
 409 }
 410 
 411 
 412 void
 413 linenoiseClearScreen(void)
     
 414 {
 415   if (write(STDOUT_FILENO, "\x1b[H\x1b[2J", 7) <= 0)
 416   { 
 417   }
 418 }
 419 
 420 # if defined(LH_COMPLETION)
 421 
 422 
 423 
 424 
 425 
 426 
 427 static void
 428 linenoiseBeep(void)
     
 429 {
 430   (void)fflush(stdout);
 431   (void)fprintf(stderr, "\x7");
 432   (void)fflush(stderr);
 433 }
 434 
 435 
 436 static void
 437 freeCompletions(const linenoiseCompletions *lc)
     
 438 {
 439   size_t i;
 440 
 441   for (i = 0; i < lc->len; i++)
 442   {
 443     FREE(lc->cvec[i]);
 444   }
 445 
 446   if (lc->cvec != NULL)
 447   {
 448     FREE(lc->cvec);
 449   }
 450 }
 451 
 452 
 453 
 454 
 455 
 456 
 457 
 458 
 459 
 460 
 461 static int
 462 completeLine(struct linenoiseState *ls)
     
 463 {
 464   linenoiseCompletions lc = {
 465     0, NULL
 466   };
 467   int nread, nwritten;
 468   char c = 0;
 469 
 470   completionCallback(ls->buf, &lc);
 471   if (lc.len == 0)
 472   {
 473     linenoiseBeep();
 474   }
 475   else
 476   {
 477     size_t stop = 0, i = 0;
 478 
 479     while (!stop)
 480     {
 481       
 482       if (i < lc.len)
 483       {
 484         struct linenoiseState saved = *ls;
 485 
 486         ls->len = ls->pos = strlen(lc.cvec[i]);
 487         ls->buf = lc.cvec[i];
 488         refreshLine(ls);
 489         ls->len = saved.len;
 490         ls->pos = saved.pos;
 491         ls->buf = saved.buf;
 492       }
 493       else
 494       {
 495         refreshLine(ls);
 496       }
 497 
 498       nread = read(ls->ifd, &c, 1);
 499       if (nread <= 0)
 500       {
 501         freeCompletions(&lc);
 502         return ( -1 );
 503       }
 504 
 505       switch (c)
 506       {
 507       case 9: 
 508         i = ( i + 1 ) % ( lc.len + 1 );
 509         if (i == lc.len)
 510         {
 511           linenoiseBeep();
 512         }
 513 
 514         stop = 1;
 515         break;
 516 
 517       default:
 518         
 519         if (i < lc.len)
 520         {
 521           nwritten = snprintf(ls->buf, ls->buflen, "%s", lc.cvec[i]);
 522           ls->len  = ls->pos = nwritten;
 523         }
 524 
 525         stop = 1;
 526         break;
 527       }
 528     }
 529   }
 530 
 531   freeCompletions(&lc);
 532   return ( c ); 
 533 }
 534 
 535 
 536 void
 537 linenoiseSetCompletionCallback(linenoiseCompletionCallback *fn)
     
 538 {
 539   completionCallback = fn;
 540 }
 541 
 542 # endif 
 543 
 544 # if defined(LH_HINTS)
 545 
 546 
 547 
 548 
 549 
 550 
 551 void
 552 linenoiseSetHintsCallback(linenoiseHintsCallback *fn)
     
 553 {
 554   hintsCallback = fn;
 555 }
 556 
 557 
 558 
 559 
 560 
 561 
 562 void
 563 linenoiseSetFreeHintsCallback(linenoiseFreeHintsCallback *fn)
     
 564 {
 565   freeHintsCallback = fn;
 566 }
 567 
 568 # endif 
 569 
 570 # if defined(LH_COMPLETION)
 571 
 572 
 573 
 574 
 575 
 576 
 577 
 578 void
 579 linenoiseAddCompletion(linenoiseCompletions *lc, const char *str)
     
 580 {
 581   size_t len = strlen(str);
 582   char *copy, **cvec;
 583 
 584   copy = malloc(len + 1);
 585   if (copy == NULL)
 586   {
 587     return;
 588   }
 589 
 590   memcpy(copy, str, len + 1);
 591   cvec = realloc(lc->cvec, sizeof ( char * ) * ( lc->len + 1 ));
 592   if (cvec == NULL)
 593   {
 594     FREE(copy);
 595     return;
 596   }
 597 
 598   lc->cvec            = cvec;
 599   lc->cvec[lc->len++] = copy;
 600 }
 601 
 602 # endif 
 603 
 604 
 605 
 606 
 607 
 608 
 609 
 610 
 611 struct abuf
 612 {
 613   char *b;
 614   int len;
 615 };
 616 
 617 static void
 618 abInit(struct abuf *ab)
     
 619 {
 620   ab->b = NULL;
 621   ab->len = 0;
 622 }
 623 
 624 static void
 625 abAppend(struct abuf *ab, const char *s, int len)
     
 626 {
 627   if (len <= 0)
 628   {
 629     return;
 630   }
 631 
 632   char *new = realloc(ab->b, 1 + ab->len + len);
 633 
 634   if (new == NULL)
 635   {
 636     return;
 637   }
 638 
 639   memcpy(new + ab->len, s, len);
 640   ab->b    = new;
 641   ab->len += len;
 642 }
 643 
 644 static void
 645 abFree(const struct abuf *ab)
     
 646 {
 647   free(ab->b); 
 648 }
 649 
 650 # if defined(LH_HINTS)
 651 
 652 
 653 
 654 
 655 
 656 
 657 static void
 658 refreshShowHints(struct abuf *ab, const struct linenoiseState *l, int plen)
     
 659 {
 660   char seq[64];
 661 
 662   seq[0] = '\0';
 663   if (hintsCallback && plen + l->len < l->cols)
 664   {
 665     int color = -1, bold = 0;
 666     char *hint = hintsCallback(l->buf, &color, &bold);
 667     if (hint)
 668     {
 669       int hintlen    = strlen(hint);
 670       int hintmaxlen = l->cols - ( plen + l->len );
 671       if (hintlen > hintmaxlen)
 672       {
 673         hintlen = hintmaxlen;
 674       }
 675 
 676       if (bold == 1 && color == -1)
 677       {
 678         color = 37;
 679       }
 680 
 681       if (color != -1 || bold != 0)
 682       {
 683         (void)snprintf(seq, sizeof ( seq ), "\033[%d;%d;49m", bold, color);
 684       }
 685       else
 686       {
 687         seq[0] = '\0';
 688       }
 689 
 690       abAppend(ab, seq, strlen(seq));
 691       abAppend(ab, hint, hintlen);
 692       if (color != -1 || bold != 0)
 693       {
 694         abAppend(ab, "\033[0m", 4);
 695       }
 696 
 697       
 698       if (freeHintsCallback)
 699       {
 700         freeHintsCallback(hint);
 701       }
 702     }
 703   }
 704 }
 705 
 706 # endif 
 707 
 708 
 709 
 710 
 711 
 712 
 713 
 714 
 715 static void
 716 refreshSingleLine(const struct linenoiseState *l)
     
 717 {
 718   char   seq[64];
 719   size_t plen = pstrlen(l->prompt);
 720   int    fd   = l->ofd;
 721   char   *buf = l->buf;
 722   size_t len  = l->len;
 723   size_t pos  = l->pos;
 724   struct abuf ab;
 725 
 726   while (( plen + pos ) >= l->cols)
 727   {
 728     buf++;
 729     len--;
 730     pos--;
 731   }
 732   while (plen + len > l->cols)
 733   {
 734     len--;
 735   }
 736 
 737   abInit(&ab);
 738   
 739   (void)snprintf(seq, sizeof ( seq ), "\r");
 740   abAppend(&ab, seq, strlen(seq));
 741   
 742   abAppend(&ab, l->prompt, strlen(l->prompt));
 743 # if defined(LH_MASKMODE)
 744   if (maskmode == 1)
 745   {
 746     while (len--)
 747     {
 748       abAppend(&ab, "*", 1);
 749     }
 750   }
 751   else
 752   {
 753 # endif 
 754   abAppend(&ab, buf, len);
 755 # if defined(LH_MASKMODE)
 756 }
 757 # endif 
 758 # if defined(LH_HINTS)
 759   
 760   refreshShowHints(&ab, l, plen);
 761 # endif 
 762   
 763   (void)snprintf(seq, sizeof ( seq ), "\x1b[0K");
 764   abAppend(&ab, seq, strlen(seq));
 765   
 766   (void)snprintf(seq, sizeof ( seq ), "\r\x1b[%dC", (int)( pos + plen ));
 767   abAppend(&ab, seq, strlen(seq));
 768   if (write(fd, ab.b, ab.len) == -1)
 769   { 
 770   }
 771 
 772   abFree(&ab);
 773 }
 774 
 775 
 776 
 777 
 778 
 779 
 780 
 781 
 782 static void
 783 refreshMultiLine(struct linenoiseState *l)
     
 784 {
 785   char seq[64];
 786   int plen = strlen(l->prompt);
 787   int rows = ( plen + l->len + l->cols - 1 )
 788              / l->cols; 
 789   int rpos = ( plen + l->oldpos + l->cols ) / l->cols; 
 790   int rpos2; 
 791   int col; 
 792   int old_rows = l->maxrows;
 793   int fd = l->ofd, j;
 794   struct abuf ab;
 795 
 796   
 797   if (rows > (int)l->maxrows)
 798   {
 799     l->maxrows = rows;
 800   }
 801 
 802   
 803 
 804 
 805 
 806 
 807   abInit(&ab);
 808   if (old_rows - rpos > 0)
 809   {
 810     (void)snprintf(seq, sizeof ( seq ), "\x1b[%dB", old_rows - rpos);
 811     abAppend(&ab, seq, strlen(seq));
 812   }
 813 
 814   
 815   for (j = 0; j < old_rows - 1; j++)
 816   {
 817     (void)snprintf(seq, sizeof ( seq ), "\r\x1b[0K\x1b[1A");
 818     abAppend(&ab, seq, strlen(seq));
 819   }
 820 
 821   
 822   (void)snprintf(seq, sizeof ( seq ), "\r\x1b[0K");
 823   abAppend(&ab, seq, strlen(seq));
 824 
 825   
 826   abAppend(&ab, l->prompt, strlen(l->prompt));
 827 # if defined(LH_MASKMODE)
 828   if (maskmode == 1)
 829   {
 830     unsigned int i;
 831     for (i = 0; i < l->len; i++)
 832     {
 833       abAppend(&ab, "*", 1);
 834     }
 835   }
 836   else
 837   {
 838 # endif 
 839   abAppend(&ab, l->buf, l->len);
 840 # if defined(LH_MASKMODE)
 841 }
 842 # endif 
 843 
 844 # if defined(LH_HINTS)
 845   
 846   refreshShowHints(&ab, l, plen);
 847 # endif 
 848 
 849   
 850 
 851 
 852 
 853 
 854   if (l->pos && l->pos == l->len && ( l->pos + plen ) % l->cols == 0)
 855   {
 856     abAppend(&ab, "\n", 1); 
 857     (void)snprintf(seq, sizeof ( seq ), "\r"); 
 858     abAppend(&ab, seq, strlen(seq));
 859     rows++;
 860     if (rows > (int)l->maxrows)
 861     {
 862       l->maxrows = rows;
 863     }
 864   }
 865 
 866   
 867   rpos2 = ( plen + l->pos + l->cols ) / l->cols;
 868 
 869   
 870   if (rows - rpos2 > 0)
 871   {
 872     (void)snprintf(seq, sizeof ( seq ), "\x1b[%dA", rows - rpos2);
 873     abAppend(&ab, seq, strlen(seq));
 874   }
 875 
 876   
 877   col = ( plen + (int)l->pos ) % (int)l->cols;
 878   if (col)
 879   {
 880     (void)snprintf(seq, sizeof ( seq ), "\r\x1b[%dC", col);
 881   }
 882   else
 883   {
 884     (void)snprintf(seq, sizeof ( seq ), "\r");
 885   }
 886 
 887   abAppend(&ab, seq, strlen(seq));
 888 
 889   l->oldpos = l->pos;
 890 
 891   if (write(fd, ab.b, ab.len) == -1)
 892   { 
 893   }
 894 
 895   abFree(&ab);
 896 }
 897 
 898 
 899 
 900 
 901 
 902 
 903 static void
 904 refreshLine(struct linenoiseState *l)
     
 905 {
 906   l->cols = getColumns(STDIN_FILENO, STDOUT_FILENO);
 907   if (mlmode)
 908   {
 909     refreshMultiLine(l);
 910   }
 911   else
 912   {
 913     refreshSingleLine(l);
 914   }
 915 }
 916 
 917 
 918 
 919 
 920 
 921 
 922 int
 923 linenoiseEditInsert(struct linenoiseState *l, char c)
     
 924 {
 925   if (l->len < l->buflen)
 926   {
 927     if (l->len == l->pos)
 928     {
 929       l->buf[l->pos] = c;
 930       l->pos++;
 931       l->len++;
 932       l->buf[l->len] = '\0';
 933 # if defined(LH_MASKMODE) && defined(LH_HINTS)
 934       if (( !mlmode && l->plen + l->len < l->cols && !hintsCallback ))
 935       {
 936         
 937         char d = ( maskmode == 1 ) ? '*' : (char)c;
 938         if (write(l->ofd, &d, 1) == -1)
 939         {
 940           return ( -1 );
 941         }
 942       }
 943       else
 944       {
 945 # endif 
 946       refreshLine(l);
 947 # if defined(LH_MASKMODE) && defined(LH_HINTS)
 948       }
 949 # endif 
 950     }
 951     else
 952     {
 953       memmove(l->buf + l->pos + 1, l->buf + l->pos, l->len - l->pos);
 954       l->buf[l->pos] = c;
 955       l->len++;
 956       l->pos++;
 957       l->buf[l->len] = '\0';
 958       refreshLine(l);
 959     }
 960   }
 961 
 962   return ( 0 );
 963 }
 964 
 965 
 966 void
 967 linenoiseEditMoveLeft(struct linenoiseState *l)
     
 968 {
 969   if (l->pos > 0)
 970   {
 971     l->pos--;
 972     refreshLine(l);
 973   }
 974 }
 975 
 976 
 977 void
 978 linenoiseEditMoveRight(struct linenoiseState *l)
     
 979 {
 980   if (l->pos != l->len)
 981   {
 982     l->pos++;
 983     refreshLine(l);
 984   }
 985 }
 986 
 987 
 988 void
 989 linenoiseEditMoveWordEnd(struct linenoiseState *l)
     
 990 {
 991   if (l->len == 0 || l->pos >= l->len)
 992   {
 993     return;
 994   }
 995 
 996   if (l->buf[l->pos] == ' ')
 997   {
 998     while (l->pos < l->len && l->buf[l->pos] == ' ')
 999     {
1000       ++l->pos;
1001     }
1002   }
1003 
1004   while (l->pos < l->len && l->buf[l->pos] != ' ')
1005   {
1006     ++l->pos;
1007   }
1008   refreshLine(l);
1009 }
1010 
1011 
1012 void
1013 linenoiseEditMoveWordStart(struct linenoiseState *l)
     
1014 {
1015   if (l->len == 0)
1016   {
1017     return;
1018   }
1019 
1020   if (l->buf[l->pos - 1] == ' ')
1021   {
1022     --l->pos;
1023   }
1024 
1025   if (l->buf[l->pos] == ' ')
1026   {
1027     while (l->pos > 0 && l->buf[l->pos] == ' ')
1028     {
1029       --l->pos;
1030     }
1031   }
1032 
1033   while (l->pos > 0 && l->buf[l->pos - 1] != ' ')
1034   {
1035     --l->pos;
1036   }
1037   refreshLine(l);
1038 }
1039 
1040 
1041 void
1042 linenoiseEditMoveHome(struct linenoiseState *l)
     
1043 {
1044   if (l->pos != 0)
1045   {
1046     l->pos = 0;
1047     refreshLine(l);
1048   }
1049 }
1050 
1051 
1052 void
1053 linenoiseEditMoveEnd(struct linenoiseState *l)
     
1054 {
1055   if (l->pos != l->len)
1056   {
1057     l->pos = l->len;
1058     refreshLine(l);
1059   }
1060 }
1061 
1062 
1063 
1064 
1065 
1066 
1067 # define LINENOISE_HISTORY_NEXT 0
1068 # define LINENOISE_HISTORY_PREV 1
1069 void
1070 linenoiseEditHistoryNext(struct linenoiseState *l, int dir)
     
1071 {
1072   if (history_len > 1)
1073   {
1074     
1075 
1076 
1077 
1078 
1079     FREE(history[history_len - 1 - l->history_index]);
1080     history[history_len - 1 - l->history_index] = strdup(l->buf);
1081     if (!history[history_len - 1 - l->history_index])
1082       {
1083         (void)fprintf (stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
1084                        __func__, __FILE__, __LINE__);
1085 # if defined(USE_BACKTRACE)
1086 #  if defined(SIGUSR2)
1087         (void)raise(SIGUSR2);
1088          
1089 #  endif 
1090 # endif 
1091         abort();
1092       }
1093     
1094     l->history_index += ( dir == LINENOISE_HISTORY_PREV ) ? 1 : -1;
1095     if (l->history_index < 0)
1096     {
1097       l->history_index = 0;
1098       return;
1099     }
1100     else if (l->history_index >= history_len)
1101     {
1102       l->history_index = history_len - 1;
1103       return;
1104     }
1105 
1106     strncpy(l->buf, history[history_len - 1 - l->history_index], l->buflen);
1107     l->buf[l->buflen - 1] = '\0';
1108     l->len = l->pos = strlen(l->buf);
1109     refreshLine(l);
1110   }
1111 }
1112 
1113 
1114 
1115 
1116 
1117 
1118 # define LINENOISE_SEARCH_HISTORY_FORWARD 0
1119 # define LINENOISE_SEARCH_HISTORY_REVERSE 1
1120 void
1121 linenoiseSearchInHistory(struct linenoiseState *l, int direction)
     
1122 {
1123   if (history_len > 1)
1124   {
1125     
1126 
1127 
1128 
1129 
1130     FREE(history[history_len - 1 - l->history_index]);
1131     history[history_len - 1 - l->history_index] = strdup(l->buf);
1132     if (!history[history_len - 1 - l->history_index])
1133       {
1134         (void)fprintf (stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
1135                        __func__, __FILE__, __LINE__);
1136 # if defined(USE_BACKTRACE)
1137 #  if defined(SIGUSR2)
1138         (void)raise(SIGUSR2);
1139          
1140 #  endif 
1141 # endif 
1142         abort();
1143       }
1144 
1145     
1146     int cnt;
1147     if (direction == LINENOISE_SEARCH_HISTORY_FORWARD)
1148     {
1149       cnt = history_len - 2 - l->history_index;
1150       for (; cnt >= 0; cnt--)
1151       {
1152         
1153 
1154 
1155 
1156 
1157         if (strncmp(l->buf, history[cnt], l->pos) == 0)
1158         {
1159           strncpy(l->buf, history[cnt], l->buflen);
1160           l->buf[l->buflen - 1] = '\0';
1161           
1162           l->len = strlen(l->buf);
1163 
1164           
1165 
1166 
1167 
1168 
1169           l->history_index = history_len - 1 - cnt;
1170           refreshLine(l);
1171           return;
1172         }
1173       }
1174     }
1175     else if (direction == LINENOISE_SEARCH_HISTORY_REVERSE)
1176     {
1177       cnt = history_len - l->history_index;
1178       for (; cnt < history_len; cnt++)
1179       {
1180         
1181 
1182 
1183 
1184 
1185         if (strncmp(l->buf, history[cnt], l->pos) == 0)
1186         {
1187           strncpy(l->buf, history[cnt], l->buflen);
1188           l->buf[l->buflen - 1] = '\0';
1189           
1190           l->len = strlen(l->buf);
1191 
1192           
1193 
1194 
1195 
1196 
1197           l->history_index = history_len - 1 - cnt;
1198           refreshLine(l);
1199           return;
1200         }
1201       }
1202     }
1203   }
1204 }
1205 
1206 
1207 
1208 
1209 
1210 
1211 void
1212 linenoiseEditDelete(struct linenoiseState *l)
     
1213 {
1214   if (l->len > 0 && l->pos < l->len)
1215   {
1216     memmove(l->buf + l->pos, l->buf + l->pos + 1, l->len - l->pos - 1);
1217     l->len--;
1218     l->buf[l->len] = '\0';
1219     refreshLine(l);
1220   }
1221 }
1222 
1223 
1224 void
1225 linenoiseEditBackspace(struct linenoiseState *l)
     
1226 {
1227   if (l->pos > 0 && l->len > 0)
1228   {
1229     memmove(l->buf + l->pos - 1, l->buf + l->pos, l->len - l->pos);
1230     l->pos--;
1231     l->len--;
1232     l->buf[l->len] = '\0';
1233     refreshLine(l);
1234   }
1235 }
1236 
1237 
1238 
1239 
1240 
1241 
1242 void
1243 linenoiseEditDeletePrevWord(struct linenoiseState *l)
     
1244 {
1245   size_t old_pos = l->pos;
1246   size_t diff;
1247 
1248   while (l->pos > 0 && l->buf[l->pos - 1] == ' ')
1249   {
1250     l->pos--;
1251   }
1252   while (l->pos > 0 && l->buf[l->pos - 1] != ' ')
1253   {
1254     l->pos--;
1255   }
1256   diff = old_pos - l->pos;
1257   memmove(l->buf + l->pos, l->buf + old_pos, l->len - old_pos + 1);
1258   l->len -= diff;
1259   refreshLine(l);
1260 }
1261 
1262 
1263 void
1264 linenoiseEditDeleteNextWord(struct linenoiseState *l)
     
1265 {
1266   size_t next_word_end = l->pos;
1267 
1268   while (next_word_end < l->len && l->buf[next_word_end] == ' ')
1269   {
1270     ++next_word_end;
1271   }
1272   while (next_word_end < l->len && l->buf[next_word_end] != ' ')
1273   {
1274     ++next_word_end;
1275   }
1276   memmove(l->buf + l->pos, l->buf + next_word_end, l->len - next_word_end);
1277   l->len -= next_word_end - l->pos;
1278   refreshLine(l);
1279 }
1280 
1281 
1282 
1283 
1284 
1285 
1286 
1287 
1288 
1289 
1290 
1291 
1292 static int
1293 linenoiseEdit(int stdin_fd, int stdout_fd, char *buf, size_t buflen,
     
1294               const char *prompt)
1295 {
1296   struct linenoiseState l;
1297 
1298   
1299 
1300 
1301 
1302 
1303   l.ifd           = stdin_fd;
1304   l.ofd           = stdout_fd;
1305   l.buf           = buf;
1306   l.buflen        = buflen;
1307   l.prompt        = prompt;
1308   l.plen          = pstrlen(prompt);
1309   l.oldpos        = l.pos = 0;
1310   l.len           = 0;
1311   l.cols          = getColumns(stdin_fd, stdout_fd);
1312   l.maxrows       = 0;
1313   l.history_index = 0;
1314 
1315   
1316   l.buf[0] = '\0';
1317   l.buflen--; 
1318 
1319   
1320 
1321 
1322 
1323 
1324   (void)linenoiseHistoryAdd("");
1325 
1326   if (write(l.ofd, prompt, strlen(prompt)) == -1)
1327   {
1328     return ( -1 );
1329   }
1330 
1331   while (1)
1332   {
1333     signed char c;
1334     int    nread;
1335     char   seq[3];
1336 
1337     nread = read(l.ifd, &c, 1);
1338     if (nread <= 0)
1339     {
1340       return ( l.len );
1341     }
1342 
1343 # if defined(LH_COMPLETION)
1344 
1345     
1346 
1347 
1348 
1349 
1350 
1351     if (c == 9 && completionCallback != NULL)
1352     {
1353       int cint = completeLine(&l);
1354       
1355       if (cint < 0)
1356       {
1357         return ( l.len );
1358       }
1359 
1360       
1361       if (cint == 0)
1362       {
1363         continue;
1364       }
1365 
1366       c = (char)cint;
1367     }
1368 
1369 # endif 
1370 
1371     switch (c)
1372     {
1373     case 9:
1374       break;    
1375 
1376     case ENTER: 
1377       history_len--;
1378       FREE(history[history_len]);
1379       if (mlmode)
1380       {
1381         linenoiseEditMoveEnd(&l);
1382       }
1383 
1384 # if defined(LH_HINTS)
1385       if (hintsCallback)
1386       {
1387         
1388 
1389 
1390 
1391 
1392         linenoiseHintsCallback *hc = hintsCallback;
1393         hintsCallback              = NULL;
1394         refreshLine(&l);
1395         hintsCallback              = hc;
1396       }
1397 
1398 # endif 
1399       return ((int)l.len );
1400 
1401     case CTRL_C: 
1402       errno = EAGAIN;
1403       return ( -1 );
1404 
1405     case BACKSPACE: 
1406     case 8:         
1407       linenoiseEditBackspace(&l);
1408       break;
1409 
1410     case CTRL_D:     
1411       if (l.len > 0) 
1412       {
1413         linenoiseEditDelete(&l);
1414       }
1415       else
1416       {
1417         history_len--;
1418         FREE(history[history_len]);
1419         return ( -1 );
1420       }
1421 
1422       break;
1423 
1424     case CTRL_T: 
1425       break;
1426 
1427     case CTRL_B: 
1428       linenoiseEditMoveLeft(&l);
1429       break;
1430 
1431     case CTRL_F: 
1432       linenoiseEditMoveRight(&l);
1433       break;
1434 
1435     case CTRL_P: 
1436       linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_PREV);
1437       break;
1438 
1439     case CTRL_N: 
1440       linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_NEXT);
1441       break;
1442 
1443     case ESC: 
1444 
1445       
1446 
1447 
1448 
1449 
1450 
1451       if (read(l.ifd, seq, 1) == -1)
1452       {
1453         break;
1454       }
1455 
1456       if (read(l.ifd, seq + 1, 1) == -1)
1457       {
1458         break;
1459       }
1460 
1461       
1462       if (seq[0] == '[')
1463       {
1464         if (seq[1] >= '0' && seq[1] <= '9')
1465         {
1466           
1467           if (read(l.ifd, seq + 2, 1) == -1)
1468           {
1469             break;
1470           }
1471 
1472           if (seq[2] == '~')
1473           {
1474             switch (seq[1])
1475             {
1476             case '3': 
1477               linenoiseEditDelete(&l);
1478               break;
1479 
1480             case '6': 
1481               linenoiseSearchInHistory(
1482                 &l,
1483                 LINENOISE_SEARCH_HISTORY_REVERSE);
1484               break;
1485 
1486             case '5': 
1487               linenoiseSearchInHistory(
1488                 &l,
1489                 LINENOISE_SEARCH_HISTORY_FORWARD);
1490               break;
1491             }
1492           }
1493         }
1494         else
1495         {
1496           switch (seq[1])
1497           {
1498           case 'A': 
1499             linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_PREV);
1500             break;
1501 
1502           case 'B': 
1503             linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_NEXT);
1504             break;
1505 
1506           case 'C': 
1507             linenoiseEditMoveRight(&l);
1508             break;
1509 
1510           case 'D': 
1511             linenoiseEditMoveLeft(&l);
1512             break;
1513 
1514           case 'H': 
1515             linenoiseEditMoveHome(&l);
1516             break;
1517 
1518           case 'F': 
1519             linenoiseEditMoveEnd(&l);
1520             break;
1521           }
1522         }
1523       }
1524 
1525       break;
1526 
1527     default:
1528       if (linenoiseEditInsert(&l, c))
1529       {
1530         return ( -1 );
1531       }
1532 
1533       break;
1534 
1535     case CTRL_U: 
1536       buf[0] = '\0';
1537       l.pos  = l.len = 0;
1538       refreshLine(&l);
1539       break;
1540 
1541     case CTRL_K: 
1542       buf[l.pos] = '\0';
1543       l.len      = l.pos;
1544       refreshLine(&l);
1545       break;
1546 
1547     case CTRL_A: 
1548       linenoiseEditMoveHome(&l);
1549       break;
1550 
1551     case CTRL_E: 
1552       linenoiseEditMoveEnd(&l);
1553       break;
1554 
1555     case CTRL_L: 
1556       linenoiseClearScreen();
1557       refreshLine(&l);
1558       break;
1559 
1560     case CTRL_W: 
1561       linenoiseEditDeletePrevWord(&l);
1562       break;
1563     }
1564   }
1565 # if defined(SUNLINT) || !defined(__SUNPRO_C) && !defined(__SUNPRO_CC)
1566   
1567  return ( -1 );
1568 # endif 
1569 }
1570 
1571 
1572 
1573 
1574 
1575 
1576 static int
1577 linenoiseRaw(char *buf, size_t buflen, const char *prompt)
     
1578 {
1579   int count;
1580 
1581   if (buflen == 0)
1582   {
1583     errno = EINVAL;
1584     return ( -1 );
1585   }
1586 
1587   if (enableRawMode(STDIN_FILENO) == -1)
1588   {
1589     return ( -1 );
1590   }
1591 
1592   count = linenoiseEdit(STDIN_FILENO, STDOUT_FILENO, buf, buflen, prompt);
1593   disableRawMode(STDIN_FILENO);
1594   (void)printf("\r\n");
1595   return ( count );
1596 }
1597 
1598 
1599 
1600 
1601 
1602 
1603 
1604 
1605 
1606 static char *
1607 linenoiseNoTTY(void)
     
1608 {
1609   char *line = NULL;
1610   size_t len = 0, maxlen = 0;
1611 
1612   while (1)
1613   {
1614     if (len == maxlen)
1615     {
1616       if (maxlen == 0)
1617       {
1618         maxlen = 16;
1619       }
1620 
1621       maxlen *= 2;
1622       char *oldval = line;
1623       line = realloc(line, maxlen); 
1624       if (line == NULL)
1625       {
1626         if (oldval)
1627         {
1628           FREE(oldval);
1629         }
1630 
1631         return ( NULL );
1632       }
1633     }
1634 
1635     int c = fgetc(stdin);
1636     if (c == EOF || c == '\n')
1637     {
1638       if (c == EOF && len == 0)
1639       {
1640         FREE(line);
1641         return ( NULL );
1642       }
1643       else
1644       {
1645         line[len] = '\0';
1646         return ( line );
1647       }
1648     }
1649     else
1650     {
1651       line[len] = c;
1652       len++;
1653     }
1654   }
1655 # if defined(SUNLINT) || !defined(__SUNPRO_C) && !defined(__SUNPRO_CC)
1656   
1657  return ( NULL );
1658 # endif 
1659 }
1660 
1661 
1662 
1663 
1664 
1665 
1666 
1667 
1668 
1669 char *
1670 linenoise(const char *prompt)
     
1671 {
1672   char buf[LINENOISE_MAX_LINE];
1673   int count;
1674 
1675   if (!isatty(STDIN_FILENO))
1676   {
1677     
1678 
1679 
1680 
1681 
1682     return ( linenoiseNoTTY());
1683   }
1684   else if (isUnsupportedTerm())
1685   {
1686     size_t len;
1687 
1688     (void)fflush(stderr);
1689     (void)printf("%s", prompt);
1690     (void)fflush(stdout);
1691     if (fgets(buf, LINENOISE_MAX_LINE, stdin) == NULL)
1692     {
1693       return ( NULL );
1694     }
1695 
1696     len = strlen(buf);
1697     while (len && ( buf[len - 1] == '\n' || buf[len - 1] == '\r' ))
1698     {
1699       len--;
1700       buf[len] = '\0';
1701     }
1702     return ( strdup(buf));
1703   }
1704   else
1705   {
1706     count = linenoiseRaw(buf, LINENOISE_MAX_LINE, prompt);
1707     if (count == -1)
1708     {
1709       return ( NULL );
1710     }
1711 
1712     return ( strdup(buf));
1713   }
1714 }
1715 
1716 
1717 
1718 
1719 
1720 
1721 
1722 
1723 void
1724 linenoiseFree(void *ptr)
     
1725 {
1726   FREE(ptr);
1727 }
1728 
1729 
1730 
1731 
1732 
1733 
1734 static void
1735 freeHistory(void)
     
1736 {
1737   if (history)
1738   {
1739     int j;
1740 
1741     for (j = 0; j < history_len; j++)
1742     {
1743       FREE(history[j]);
1744     }
1745 
1746     FREE(history);
1747   }
1748 }
1749 
1750 
1751 static void
1752 linenoiseAtExit(void)
     
1753 {
1754   disableRawMode(STDIN_FILENO);
1755   freeHistory();
1756 }
1757 
1758 
1759 
1760 
1761 
1762 
1763 
1764 
1765 
1766 int
1767 linenoiseHistoryAdd(const char *line)
     
1768 {
1769   char *linecopy;
1770 
1771   if (history_max_len == 0)
1772   {
1773     return ( 0 );
1774   }
1775 
1776   
1777   if (history == NULL)
1778   {
1779     history = malloc(sizeof ( char * ) * history_max_len);
1780     if (history == NULL)
1781     {
1782       return ( 0 );
1783     }
1784 
1785     (void)memset(history, 0, ( sizeof ( char * ) * history_max_len ));
1786   }
1787 
1788   
1789   if (( history_len > 0 ) && ( !strcmp(history[history_len - 1], line)))
1790   {
1791     return ( 0 );
1792   }
1793 
1794   
1795 
1796 
1797 
1798 
1799   linecopy = strdup(line);
1800   if (!linecopy)
1801   {
1802     return ( 0 );
1803   }
1804 
1805   if (history_len == history_max_len)
1806   {
1807     FREE(history[0]);
1808     memmove(
1809       history,
1810       history + 1,
1811       sizeof ( char * ) * ( history_max_len - 1 ));
1812     history_len--;
1813   }
1814 
1815   history[history_len] = linecopy;
1816   history_len++;
1817   return ( 1 );
1818 }
1819 
1820 
1821 
1822 
1823 
1824 
1825 
1826 
1827 int
1828 linenoiseHistorySetMaxLen(int len)
     
1829 {
1830   char **new;
1831 
1832   if (len < 1)
1833   {
1834     return ( 0 );
1835   }
1836 
1837   if (history)
1838   {
1839     int tocopy = history_len;
1840 
1841     new = malloc(sizeof ( char * ) * len);
1842     if (new == NULL)
1843     {
1844       return ( 0 );
1845     }
1846 
1847     
1848     if (len < tocopy)
1849     {
1850       int j;
1851 
1852       for (j = 0; j < tocopy - len; j++)
1853       {
1854         FREE(history[j]);
1855       }
1856 
1857       tocopy = len;
1858     }
1859 
1860     (void)memset(new, 0, sizeof ( char * ) * len);
1861     memcpy(
1862       new,
1863       history + ( history_len - tocopy ),
1864       sizeof ( char * ) * tocopy);
1865     FREE(history);
1866     history = new;
1867   }
1868 
1869   history_max_len = len;
1870   if (history_len > history_max_len)
1871   {
1872     history_len = history_max_len;
1873   }
1874 
1875   return ( 1 );
1876 }
1877 
1878 
1879 size_t
1880 pstrlen(const char *s)
     
1881 {
1882   size_t len = 0, i = 0;
1883 
1884   while (s[i] != '\0')
1885   {
1886     if (s[i] == '\033') 
1887     {
1888       i = strpbrk(s + i, "m") - s + 1; 
1889       continue;
1890     }
1891 
1892     len++;
1893     i++;
1894   }
1895   return ( len );
1896 }
1897 
1898 #endif