void linenoiseEditInsert(struct linenoiseState *l, int c) { if (l->len < l->buflen) { if (l->len == l->pos) { l->buf[l->pos] = c; l->pos++; l->len++; l->buf[l->len] = '\0'; if ((!mlmode && l->plen + l->len < l->cols) /* || mlmode */) { /* Avoid a full update of the line in the * trivial case. */ serial.putc(c); } else { refreshLine(l); } } else { memmove(l->buf + l->pos + 1, l->buf + l->pos, l->len - l->pos); l->buf[l->pos] = c; l->len++; l->pos++; l->buf[l->len] = '\0'; refreshLine(l); } } }
/* Insert the character 'c' at cursor current position. * * On error writing to the terminal -1 is returned, otherwise 0. */ int linenoiseEditInsert(struct linenoiseState *l, char c) { if (l->len < l->buflen) { if (l->len == l->pos) { l->buf[l->pos] = c; l->pos++; l->len++; l->buf[l->len] = '\0'; if ((!mlmode && l->plen+l->len < l->cols) /* || mlmode */) { /* Avoid a full update of the line in the * trivial case. */ if (write(l->ofd,&c,1) == -1) return -1; } else { refreshLine(l); } } else { memmove(l->buf+l->pos+1,l->buf+l->pos,l->len-l->pos); l->buf[l->pos] = c; l->len++; l->pos++; l->buf[l->len] = '\0'; refreshLine(l); } } return 0; }
/* Insert the character 'c' at cursor current position. * * On error writing to the terminal -1 is returned, otherwise 0. */ int linenoiseEditInsert(struct linenoiseState *l, wchar_t c) { if (l->len < l->buflen) { if (l->len == l->pos) { l->buf[l->pos] = c; l->pos++; l->len++; l->buf[l->len] = L'\0'; if ((!mlmode && l->plen+l->len < l->cols) /* || mlmode */) { /* Avoid a full update of the line in the * trivial case. */ console_write_wchar_string(&c, 1); } else { refreshLine(l); } } else { memmove(l->buf+l->pos+1, l->buf+l->pos, sizeof(wchar_t) * (l->len-l->pos)); l->buf[l->pos] = c; l->len++; l->pos++; l->buf[l->len] = L'\0'; refreshLine(l); } } return 0; }
/* This is an helper function for linenoiseEdit() and is called when the * user types the <tab> key in order to complete the string currently in the * input. * * The state of the editing is encapsulated into the pointed linenoiseState * structure as described in the structure definition. */ static int completeLine(struct linenoiseState *ls) { linenoiseCompletions lc = { 0, NULL }; int nread, nwritten; char c = 0; completionCallback(ls->buf,&lc); if (lc.len == 0) { linenoiseBeep(); } else { size_t stop = 0, i = 0; while(!stop) { /* Show completion or original buffer */ if (i < lc.len) { struct linenoiseState saved = *ls; ls->len = ls->pos = strlen(lc.cvec[i]); ls->buf = lc.cvec[i]; refreshLine(ls); ls->len = saved.len; ls->pos = saved.pos; ls->buf = saved.buf; } else { refreshLine(ls); } nread = read(ls->ifd,&c,1); if (nread <= 0) { freeCompletions(&lc); return -1; } switch(c) { case 9: /* tab */ i = (i+1) % (lc.len+1); if (i == lc.len) linenoiseBeep(); break; case 27: /* escape */ /* Re-show original buffer */ if (i < lc.len) refreshLine(ls); stop = 1; break; default: /* Update buffer and return */ if (i < lc.len) { nwritten = snprintf(ls->buf,ls->buflen,"%s",lc.cvec[i]); ls->len = ls->pos = nwritten; } stop = 1; break; } } } freeCompletions(&lc); return c; /* Return last read character */ }
static int completeLine(int fd, const char *prompt, char *buf, size_t buflen, size_t *len, size_t *pos, size_t cols) { linenoiseCompletions lc = { 0, NULL }; int nwritten; char c = 0; completionCallback(buf,&lc); if (lc.len == 0) { beep(); } else { size_t stop = 0, i = 0; size_t clen; while(!stop) { /* Show completion or original buffer */ if (i < lc.len) { clen = strlen(lc.cvec[i]); refreshLine(fd,prompt,lc.cvec[i],clen,clen,cols); } else { refreshLine(fd,prompt,buf,*len,*pos,cols); } do { c = linenoiseReadChar(fd); } while (c == (char)-1); switch(c) { case 0: freeCompletions(&lc); return -1; case 9: /* tab */ i = (i+1) % (lc.len+1); if (i == lc.len) beep(); break; case 27: /* escape */ /* Re-show original buffer */ if (i < lc.len) { refreshLine(fd,prompt,buf,*len,*pos,cols); } stop = 1; break; default: /* Update buffer and return */ if (i < lc.len) { nwritten = snprintf(buf,buflen,"%s",lc.cvec[i]); *len = *pos = nwritten; } stop = 1; break; } } } freeCompletions(&lc); return c; /* Return last read character */ }
static int completeLine(struct current *current) { linenoiseCompletions lc = { 0, NULL }; int c = 0; completionCallback(current->buf,&lc,completionUserdata); if (lc.len == 0) { beep(); } else { size_t stop = 0, i = 0; while(!stop) { /* Show completion or original buffer */ if (i < lc.len) { struct current tmp = *current; tmp.buf = lc.cvec[i]; tmp.pos = tmp.len = strlen(tmp.buf); tmp.chars = utf8_strlen(tmp.buf, tmp.len); refreshLine(current->prompt, &tmp); } else { refreshLine(current->prompt, current); } c = fd_read(current); if (c == -1) { break; } switch(c) { case '\t': /* tab */ i = (i+1) % (lc.len+1); if (i == lc.len) beep(); break; case 27: /* escape */ /* Re-show original buffer */ if (i < lc.len) { refreshLine(current->prompt, current); } stop = 1; break; default: /* Update buffer and return */ if (i < lc.len) { set_current(current,lc.cvec[i]); } stop = 1; break; } } } freeCompletions(&lc); return c; /* Return last read character */ }
void linenoiseEditHistoryNext(struct linenoiseState *l, int dir) { if (history_len > 1) { /* Update the current history entry before to * overwrite it with the next one. */ free(history[history_len - 1 - l->history_index]); history[history_len - 1 - l->history_index] = strdup(l->buf); /* Show the new entry */ l->history_index += (dir == LINENOISE_HISTORY_PREV) ? 1 : -1; if (l->history_index < 0) { l->history_index = 0; return; } else if (l->history_index >= history_len) { l->history_index = history_len - 1; return; } strncpy(l->buf, history[history_len - 1 - l->history_index], l->buflen); l->buf[l->buflen - 1] = '\0'; l->len = l->pos = strlen(l->buf); refreshLine(l); } }
void lineedit_start(wchar_t *buf, size_t buflen, const wchar_t *prompt) { memset(&l, 0, sizeof(l)); /* Populate the linenoise state that we pass to functions implementing * specific editing functionalities. */ l.buf = buf; l.buflen = buflen; l.prompt = prompt; l.plen = wcslen(prompt); l.oldpos = l.pos = 0; l.len = 0; l.cols = CONSOLE_COLS; l.maxrows = 0; l.history_index = 0; /* Buffer starts empty. */ l.buf[0] = L'\0'; l.buflen--; /* Make sure there is always space for the nulterm */ /* The latest history entry is always our current buffer, that * initially is just an empty string. */ linenoiseHistoryAdd(L""); refreshLine(&l); }
void linenoiseEditMoveLeft(struct linenoiseState *l) { if (l->pos > 0) { l->pos--; refreshLine(l); } }
void linenoiseEditMoveRight(struct linenoiseState *l) { if (l->pos != l->len) { l->pos++; refreshLine(l); } }
static retCode completeLine(LineState *ls) { integer cx = 0; strgPo snapShot = stringFromBuffer(ls->lineBuff); integer snapPos = bufferOutPos(ls->lineBuff); do { retCode ret = completionCallback(ls->lineBuff, completionCl, cx++); switch (ret) { case Ok: { char ch; if (rawInChar(&ch) != Ok) { resetBuffer(ls->lineBuff, snapShot, snapPos); decReference(O_OBJECT(snapShot)); return Error; } else { switch (ch) { case TAB: resetBuffer(ls->lineBuff, snapShot, snapPos); continue; case ESC: resetBuffer(ls->lineBuff, snapShot, snapPos); decReference(O_OBJECT(snapShot)); refreshLine(ls->firstPos, ls->lineBuff); return Ok; case SPACE: case ENTER: decReference(O_OBJECT(snapShot)); return Ok; default: beep(); continue; } } } case Eof: resetBuffer(ls->lineBuff, snapShot, snapPos); decReference(O_OBJECT(snapShot)); refreshLine(ls->firstPos, ls->lineBuff); return Ok; default: case Error: return Error; } } while (True); }
/* Delete the character at the right of the cursor without altering the cursor * position. Basically this is what happens with the "Delete" keyboard key. */ void linenoiseEditDelete(struct linenoiseState *l) { if (l->len > 0 && l->pos < l->len) { memmove(l->buf+l->pos,l->buf+l->pos+1,l->len-l->pos-1); l->len--; l->buf[l->len] = '\0'; refreshLine(l); } }
void linenoiseSetPrompt(const char *p){ _current->prompt = p; refreshLine(p, _current); /* Cursor to left edge, then the prompt */ cursorToLeft(_current); outputChars(_current, p, 4); //printf("%s", "hej"); // fflush(stdout); }
/* Backspace implementation. */ void linenoiseEditBackspace(struct linenoiseState *l) { if (l->pos > 0 && l->len > 0) { memmove(l->buf+l->pos-1,l->buf+l->pos,l->len-l->pos); l->pos--; l->len--; l->buf[l->len] = '\0'; refreshLine(l); } }
////////////////////////////////////////////////////////////////////// // Function Name: // Description: // Parameters: // Data IN/OUT: // Return: // Notes: ////////////////////////////////////////////////////////////////////// void CListFrame::scrollLineUp(const int lines) { //TRACE("[CListFrame]->scrollLineUp \r\n"); if( !(m_nMode & SCROLL)) return; if( m_nNrOfLines <= 1) return; if(m_nSelectedLine > 0) m_nSelectedLine--; // check if the cursor moves out of the window if(m_nSelectedLine < m_nCurrentLine ) { // yes, scroll to next page //TRACE("[CListFrame] m_nSelectedLine: %d, \r\n",m_nSelectedLine); scrollPageUp(1); } else { refreshLine(m_nSelectedLine+lines); refreshLine(m_nSelectedLine); } }
void moveInHistory(LineState *l, historyDir dir) { if (vectLength(history) > 0) { l->history_index = clamp(0, l->history_index + dir, vectLength(history) - 1); strgPo entry = O_STRG(getVectEl(history, l->history_index)); clearBuffer(l->lineBuff); stringIntoBuffer(l->lineBuff, entry); refreshLine(l->firstPos, l->lineBuff); } }
int linenoiseEditOverwrite(struct linenoiseState *l, wchar_t c) { if (l->len < l->buflen) { if (l->len == l->pos) { l->buf[l->pos] = c; l->pos++; l->len++; l->buf[l->len] = L'\0'; if (!mlmode && (l->plen + l->len < l->cols)) { console_write_wchar_string(&c, 1); } else { refreshLine(l); } } else { l->buf[l->pos] = c; l->pos ++; refreshLine(l); } } return 0; }
void lineedit_swap_chars() { if (l.pos > 0 && l.pos < l.len) { wchar_t aux = l.buf[l.pos-1]; l.buf[l.pos-1] = l.buf[l.pos]; l.buf[l.pos] = aux; if (l.pos != l.len-1) l.pos ++; refreshLine(&l); } }
/* Delete the previosu word, maintaining the cursor at the start of the * current word. */ void linenoiseEditDeletePrevWord(struct linenoiseState *l) { size_t old_pos = l->pos; size_t diff; while (l->pos > 0 && l->buf[l->pos-1] == ' ') l->pos--; while (l->pos > 0 && l->buf[l->pos-1] != ' ') l->pos--; diff = old_pos - l->pos; memmove(l->buf+l->pos,l->buf+old_pos,l->len-old_pos+1); l->len -= diff; refreshLine(l); }
////////////////////////////////////////////////////////////////////// // Function Name: // Description: // Parameters: // Data IN/OUT: // Return: // Notes: ////////////////////////////////////////////////////////////////////// void CListFrame::scrollLineDown(const int lines) { //TRACE("[CListFrame]->scrollLineDown \r\n"); if( !(m_nMode & SCROLL)) return; if( m_nNrOfLines <= 1) return; if(m_nSelectedLine < m_nNrOfLines - 1 && m_nNrOfLines != 0) m_nSelectedLine++; // check if the cursor moves out of the window if(m_nSelectedLine - m_nCurrentLine > m_nLinesPerPage-1) { // yes, scroll to next page //TRACE("[CListFrame] m_nSelectedLine: %d, \r\n",m_nSelectedLine); scrollPageDown(1); } else { refreshLine(m_nSelectedLine-lines); refreshLine(m_nSelectedLine); } }
/*--------------------------------------------------------------------------*/ void deletePreviousChar(void) { reallocLineBuffer(); if (cur_pos > 0) { int i = 0; cur_pos -= 1; backSpace (); for (i = cur_pos; i < max_pos; i++) cur_line[i] = cur_line[i + 1]; max_pos -= 1; refreshLine(); } else TerminalBeep(); }
/*--------------------------------------------------------------------------*/ void moveForwardSingleWord(void) { reallocLineBuffer(); while ( !isspace(cur_line[cur_pos]) && (cur_pos < max_pos) ) { TerminalPutc(cur_line[cur_pos]); cur_pos++; } while ( isspace(cur_line[cur_pos]) && (cur_pos < max_pos) ) { TerminalPutc(cur_line[cur_pos]); cur_pos++; } refreshLine(); }
/*--------------------------------------------------------------------------*/ void moveBackSingleWord(void) { reallocLineBuffer(); while ((cur_pos > 0) && (isspace(cur_line[cur_pos - 1]) )) { cur_pos -= 1; backSpace (); } while ((cur_pos > 0) && ( !isspace(cur_line[cur_pos - 1]) )) { cur_pos -= 1; backSpace (); } refreshLine(); }
void GraphicsScene::setupScene() { ballCollection.append(ball); ballCollection.append(ballRouge); ballCollection.append(ballJaune); ballCollection.append(ballVerte); ballCollection.append(ballDefault); ballDefault->setStop(false); QPen pen2(Qt::white,1,Qt::SolidLine); QRectF rect(0,10,976,652); addRect(rect,pen2); prisme->setPos( width()/2-prisme->getPixmap()->width()/2, height()/2-prisme->getPixmap()->height()/2); addItem(prisme); //prismeForme->setPen(QPen(QBrush(QColor("red")),2,Qt::SolidLine)); QPolygonF polygon; polygon << QPointF( width()/2, height()/2-prisme->getPixmap()->height()/2) << QPointF( width()/2-prisme->getPixmap()->width()/2, this->height()/2+prisme->getPixmap()->height()/2)<<QPointF(this->width()/2+prisme->getPixmap()->width()/2,this->height()/2+prisme->getPixmap()->height()/2); prismeForme->setPolygon(polygon); addItem(prismeForme); barPlayer->setPos(-barPlayer->getPixmap()->width()/2,( height()/2)-(barPlayer->getPixmap()->height()/2)); addItem(barPlayer); barIA->setPos( width()-barIA->getPixmap()->width()/2,( height()/2)-(barIA->getPixmap()->height()/2)); addItem(barIA); scoreManager->getScoreView2()->setPos(670,560); addItem(scoreManager->getScoreView2()); scoreManager->getScoreView1()->setPos(210,560); addItem(scoreManager->getScoreView1()); initBallBlanche(); timer = new QTimer( this ); timer->setInterval( 20 ); timer->start(); connect( timer, SIGNAL(timeout()), this, SLOT(actualiserScene()) ); timer2 = new QTimer(this); timer2->setInterval(1000); timer2->start(); connect( timer2, SIGNAL(timeout()), this, SLOT(refreshLine()) ); connect( barPlayer, SIGNAL(inactivite()), this, SLOT(stopScene()) ); connect( this, SIGNAL(finPartie()), this, SLOT(stopScene()) ); }
/*--------------------------------------------------------------------------*/ void addCharacterCurrentLine(unsigned char ch) { int i = 0; reallocLineBuffer(); for (i = max_pos; i > cur_pos; i--) cur_line[i] = cur_line[i - 1]; cur_line[cur_pos] = ch; cur_pos += 1; max_pos += 1; cur_line[max_pos] = '\0'; setSearchedTokenInScilabHistory(cur_line); if (cur_pos < max_pos) refreshLine(); }
/*--------------------------------------------------------------------------*/ void deleteCurrentChar(void) { reallocLineBuffer(); if (max_pos == 0) { TerminalBeep(); } else { if (cur_pos < max_pos) { int i =0; for (i = cur_pos; i < max_pos; i++) cur_line[i] = cur_line[i + 1]; max_pos -= 1; refreshLine(); } } }
static int linenoisePrompt(int fd, char *buf, size_t buflen, const char *prompt) { size_t plen = strlen(prompt); size_t pos = 0; size_t len = 0; size_t cols = getColumns(); buf[0] = '\0'; buflen--; /* Make sure there is always space for the nulterm */ /* The latest history entry is always our current buffer, that * initially is just an empty string. */ linenoiseHistoryAdd(""); history_index = history_len-1; if (write(1,prompt,plen) == -1) return -1; while(1) { char c = linenoiseReadChar(fd); if (c == 0) return len; if (c == (char)-1) { refreshLine(fd,prompt,buf,len,pos,cols); continue; } /* Only autocomplete when the callback is set. It returns < 0 when * there was an error reading from fd. Otherwise it will return the * character that should be handled next. */ if (c == 9 && completionCallback != NULL) { c = completeLine(fd,prompt,buf,buflen,&len,&pos,cols); /* Return on errors */ if (c < 0) return len; /* Read next character when 0 */ if (c == 0) continue; } switch(c) { case 13: /* enter */ history_len--; free(history[history_len]); return (int)len; case 3: /* ctrl-c */ errno = EAGAIN; return -1; case 127: /* delete */ if (len > 0 && pos < len) { memmove(buf+pos,buf+pos+1,len-pos-1); len--; buf[len] = '\0'; refreshLine(fd,prompt,buf,len,pos,cols); } break; case 8: /* backspace or ctrl-h */ if (pos > 0 && len > 0) { memmove(buf+pos-1,buf+pos,len-pos); pos--; len--; buf[len] = '\0'; refreshLine(fd,prompt,buf,len,pos,cols); } break; case 4: /* ctrl-d, remove char at right of cursor */ if (len > 1 && pos < (len-1)) { memmove(buf+pos,buf+pos+1,len-pos); len--; buf[len] = '\0'; refreshLine(fd,prompt,buf,len,pos,cols); } else if (len == 0) { history_len--; free(history[history_len]); return -1; } break; case 20: /* ctrl-t */ if (pos > 0 && pos < len) { int aux = buf[pos-1]; buf[pos-1] = buf[pos]; buf[pos] = aux; if (pos != len-1) pos++; refreshLine(fd,prompt,buf,len,pos,cols); } break; case 2: /* ctrl-b */ /* left arrow */ if (pos > 0) { pos--; refreshLine(fd,prompt,buf,len,pos,cols); } break; case 6: /* ctrl-f */ /* right arrow */ if (pos != len) { pos++; refreshLine(fd,prompt,buf,len,pos,cols); } break; case 16: /* ctrl-p */ case 14: /* ctrl-n */ /* up and down arrow: history */ if (history_len > 1) { /* Update the current history entry before to * overwrite it with tne next one. */ free(history[history_index]); history[history_index] = strdup(buf); /* Show the new entry */ history_index += (c == 16) ? -1 : 1; if (history_index < 0) { history_index = 0; break; } else if (history_index >= history_len) { history_index = history_len-1; break; } strncpy(buf,history[history_index],buflen); buf[buflen] = '\0'; len = pos = strlen(buf); refreshLine(fd,prompt,buf,len,pos,cols); } break; case 27: /* escape sequence */ break; /* should be handled by linenoiseReadChar */ default: if (len < buflen) { if (len == pos) { buf[pos] = c; pos++; len++; buf[len] = '\0'; if (plen+len < cols) { /* Avoid a full update of the line in the * trivial case. */ if (write(1,&c,1) == -1) return -1; } else { refreshLine(fd,prompt,buf,len,pos,cols); } } else { memmove(buf+pos+1,buf+pos,len-pos); buf[pos] = c; len++; pos++; buf[len] = '\0'; refreshLine(fd,prompt,buf,len,pos,cols); } } break; case 21: /* Ctrl+u, delete the whole line. */ buf[0] = '\0'; pos = len = 0; refreshLine(fd,prompt,buf,len,pos,cols); break; case 11: /* Ctrl+k, delete from current to end of line. */ buf[pos] = '\0'; len = pos; refreshLine(fd,prompt,buf,len,pos,cols); break; case 1: /* Ctrl+a, go to the start of the line */ pos = 0; refreshLine(fd,prompt,buf,len,pos,cols); break; case 5: /* ctrl+e, go to the end of the line */ pos = len; refreshLine(fd,prompt,buf,len,pos,cols); break; case 12: /* ctrl+l, clear screen */ linenoiseClearScreen(); refreshLine(fd,prompt,buf,len,pos,cols); } } return len; }
static int linenoiseEdit(struct current *current) { int history_index = 0; /* The latest history entry is always our current buffer, that * initially is just an empty string. */ linenoiseHistoryAdd(""); set_current(current, ""); refreshLine(current->prompt, current); while(1) { int dir = -1; int c = fd_read(current); #ifndef NO_COMPLETION /* Only autocomplete when the callback is set. It returns < 0 when * there was an error reading from fd. Otherwise it will return the * character that should be handled next. */ if (c == '\t' && current->pos == current->chars && completionCallback != NULL) { c = completeLine(current); /* Return on errors */ if (c < 0) return current->len; /* Read next character when 0 */ if (c == 0) continue; } #endif process_char: if (c == -1) return current->len; #ifdef USE_TERMIOS if (c == 27) { /* escape sequence */ c = check_special(current->fd); } #endif switch(c) { case '\r': /* enter */ history_len--; free(history[history_len]); return current->len; case ctrl('C'): /* ctrl-c */ errno = EAGAIN; return -1; case 127: /* backspace */ case ctrl('H'): if (remove_char(current, current->pos - 1) == 1) { refreshLine(current->prompt, current); } break; case ctrl('D'): /* ctrl-d */ if (current->len == 0) { /* Empty line, so EOF */ history_len--; free(history[history_len]); return -1; } /* Otherwise fall through to delete char to right of cursor */ case SPECIAL_DELETE: if (remove_char(current, current->pos) == 1) { refreshLine(current->prompt, current); } break; case SPECIAL_INSERT: /* Ignore. Expansion Hook. * Future possibility: Toggle Insert/Overwrite Modes */ break; case ctrl('W'): /* ctrl-w, delete word at left. save deleted chars */ /* eat any spaces on the left */ { int pos = current->pos; while (pos > 0 && get_char(current, pos - 1) == ' ') { pos--; } /* now eat any non-spaces on the left */ while (pos > 0 && get_char(current, pos - 1) != ' ') { pos--; } if (remove_chars(current, pos, current->pos - pos)) { refreshLine(current->prompt, current); } } break; case ctrl('R'): /* ctrl-r */ { /* Display the reverse-i-search prompt and process chars */ char rbuf[50]; char rprompt[80]; int rchars = 0; int rlen = 0; int searchpos = history_len - 1; rbuf[0] = 0; while (1) { int n = 0; const char *p = NULL; int skipsame = 0; int searchdir = -1; snprintf(rprompt, sizeof(rprompt), "(reverse-i-search)'%s': ", rbuf); refreshLine(rprompt, current); c = fd_read(current); if (c == ctrl('H') || c == 127) { if (rchars) { int p = utf8_index(rbuf, --rchars); rbuf[p] = 0; rlen = strlen(rbuf); } continue; } #ifdef USE_TERMIOS if (c == 27) { c = check_special(current->fd); } #endif if (c == ctrl('P') || c == SPECIAL_UP) { /* Search for the previous (earlier) match */ if (searchpos > 0) { searchpos--; } skipsame = 1; } else if (c == ctrl('N') || c == SPECIAL_DOWN) { /* Search for the next (later) match */ if (searchpos < history_len) { searchpos++; } searchdir = 1; skipsame = 1; } else if (c >= ' ') { if (rlen >= (int)sizeof(rbuf) + 3) { continue; } n = utf8_getchars(rbuf + rlen, c); rlen += n; rchars++; rbuf[rlen] = 0; /* Adding a new char resets the search location */ searchpos = history_len - 1; } else { /* Exit from incremental search mode */ break; } /* Now search through the history for a match */ for (; searchpos >= 0 && searchpos < history_len; searchpos += searchdir) { p = strstr(history[searchpos], rbuf); if (p) { /* Found a match */ if (skipsame && strcmp(history[searchpos], current->buf) == 0) { /* But it is identical, so skip it */ continue; } /* Copy the matching line and set the cursor position */ set_current(current,history[searchpos]); current->pos = utf8_strlen(history[searchpos], p - history[searchpos]); break; } } if (!p && n) { /* No match, so don't add it */ rchars--; rlen -= n; rbuf[rlen] = 0; } } if (c == ctrl('G') || c == ctrl('C')) { /* ctrl-g terminates the search with no effect */ set_current(current, ""); c = 0; } else if (c == ctrl('J')) { /* ctrl-j terminates the search leaving the buffer in place */ c = 0; } /* Go process the char normally */ refreshLine(current->prompt, current); goto process_char; } break; case ctrl('T'): /* ctrl-t */ if (current->pos > 0 && current->pos <= current->chars) { /* If cursor is at end, transpose the previous two chars */ int fixer = (current->pos == current->chars); c = get_char(current, current->pos - fixer); remove_char(current, current->pos - fixer); insert_char(current, current->pos - 1, c); refreshLine(current->prompt, current); } break; case ctrl('V'): /* ctrl-v */ if (has_room(current, 3)) { /* Insert the ^V first */ if (insert_char(current, current->pos, c)) { refreshLine(current->prompt, current); /* Now wait for the next char. Can insert anything except \0 */ c = fd_read(current); /* Remove the ^V first */ remove_char(current, current->pos - 1); if (c != -1) { /* Insert the actual char */ insert_char(current, current->pos, c); } refreshLine(current->prompt, current); } } break; case ctrl('B'): case SPECIAL_LEFT: if (current->pos > 0) { current->pos--; refreshLine(current->prompt, current); } break; case ctrl('F'): case SPECIAL_RIGHT: if (current->pos < current->chars) { current->pos++; refreshLine(current->prompt, current); } break; case SPECIAL_PAGE_UP: dir = history_len - history_index - 1; /* move to start of history */ goto history_navigation; case SPECIAL_PAGE_DOWN: dir = -history_index; /* move to 0 == end of history, i.e. current */ goto history_navigation; case ctrl('P'): case SPECIAL_UP: dir = 1; goto history_navigation; case ctrl('N'): case SPECIAL_DOWN: history_navigation: if (history_len > 1) { /* Update the current history entry before to * overwrite it with tne next one. */ free(history[history_len - 1 - history_index]); history[history_len - 1 - history_index] = strdup(current->buf); /* Show the new entry */ history_index += dir; if (history_index < 0) { history_index = 0; break; } else if (history_index >= history_len) { history_index = history_len - 1; break; } set_current(current, history[history_len - 1 - history_index]); refreshLine(current->prompt, current); } break; case ctrl('A'): /* Ctrl+a, go to the start of the line */ case SPECIAL_HOME: current->pos = 0; refreshLine(current->prompt, current); break; case ctrl('E'): /* ctrl+e, go to the end of the line */ case SPECIAL_END: current->pos = current->chars; refreshLine(current->prompt, current); break; case ctrl('U'): /* Ctrl+u, delete to beginning of line, save deleted chars. */ if (remove_chars(current, 0, current->pos)) { refreshLine(current->prompt, current); } break; case ctrl('K'): /* Ctrl+k, delete from current to end of line, save deleted chars. */ if (remove_chars(current, current->pos, current->chars - current->pos)) { refreshLine(current->prompt, current); } break; case ctrl('Y'): /* Ctrl+y, insert saved chars at current position */ if (current->capture && insert_chars(current, current->pos, current->capture)) { refreshLine(current->prompt, current); } break; case ctrl('L'): /* Ctrl+L, clear screen */ linenoiseClearScreen(); /* Force recalc of window size for serial terminals */ current->cols = 0; refreshLine(current->prompt, current); break; default: /* Only tab is allowed without ^V */ if (c == '\t' || c >= ' ') { if (insert_char(current, current->pos, c) == 1) { refreshLine(current->prompt, current); } } break; } } return current->len; }
static int linenoisePrompt(int id, char *buf, size_t buflen, const char *prompt) { size_t plen = strlen(prompt); size_t pos = 0; size_t len = 0; size_t cols = TERM_COLS; int history_index = 0; buf[0] = '\0'; buflen--; /* Make sure there is always space for the nulterm */ /* The latest history entry is always our current buffer, that * initially is just an empty string. */ linenoise_internal_addhistory( id, "", LINENOISE_PUSH_EMPTY ); term_putstr( prompt, plen ); while(1) { int c; c = term_getch( TERM_INPUT_WAIT ); switch(c) { case KC_ENTER: case KC_CTRL_C: case KC_CTRL_Z: history_lengths[ id ] --; free( histories[ id ][history_lengths[ id ]] ); if( c == KC_CTRL_C ) return LINENOISE_CTRL_C; else if( c == KC_CTRL_Z ) return -1; return len; case KC_BACKSPACE: if (pos > 0 && len > 0) { memmove(buf+pos-1,buf+pos,len-pos); pos--; len--; buf[len] = '\0'; refreshLine(prompt,buf,len,pos,cols); } break; case KC_CTRL_T: /* ctrl-t */ // bogdanm: this seems to be rather useless and also a bit buggy, // so it's not enabled /* if (pos > 0 && pos < len) { int aux = buf[pos-1]; buf[pos-1] = buf[pos]; buf[pos] = aux; if (pos != len-1) pos++; refreshLine(prompt,buf,len,pos,cols); }*/ break; case KC_LEFT: /* left arrow */ if (pos > 0) { pos--; refreshLine(prompt,buf,len,pos,cols); } break; case KC_RIGHT: /* right arrow */ if (pos != len) { pos++; refreshLine(prompt,buf,len,pos,cols); } break; case KC_UP: case KC_DOWN: /* up and down arrow: history */ if (history_lengths[ id ] > 1) { /* Update the current history entry before to * overwrite it with tne next one. */ free(histories[ id ][history_lengths[ id ]-1-history_index]); histories[ id ][history_lengths[ id ]-1-history_index] = strdup(buf); /* Show the new entry */ history_index += (c == KC_UP) ? 1 : -1; if (history_index < 0) { history_index = 0; break; } else if (history_index >= history_lengths[ id ]) { history_index = history_lengths[ id ]-1; break; } strncpy(buf,histories[ id ][history_lengths[ id ]-1-history_index],buflen); buf[buflen] = '\0'; len = pos = strlen(buf); refreshLine(prompt,buf,len,pos,cols); } break; case KC_DEL: /* delete */ if (len > 0 && pos < len) { memmove(buf+pos,buf+pos+1,len-pos-1); len--; buf[len] = '\0'; refreshLine(prompt,buf,len,pos,cols); } break; case KC_HOME: /* Ctrl+a, go to the start of the line */ pos = 0; refreshLine(prompt,buf,len,pos,cols); break; case KC_END: /* ctrl+e, go to the end of the line */ pos = len; refreshLine(prompt,buf,len,pos,cols); break; case KC_CTRL_U: /* Ctrl+u, delete the whole line. */ buf[0] = '\0'; pos = len = 0; refreshLine(prompt,buf,len,pos,cols); break; case KC_CTRL_K: /* Ctrl+k, delete from current to end of line. */ buf[pos] = '\0'; len = pos; refreshLine(prompt,buf,len,pos,cols); break; default: if( isprint( c ) && len < buflen ) { if(len == pos) { buf[pos] = c; pos++; len++; buf[len] = '\0'; if (plen+len < cols) { /* Avoid a full update of the line in the * trivial case. */ term_putch( c ); } else { refreshLine(prompt,buf,len,pos,cols); } } else { memmove(buf+pos+1,buf+pos,len-pos); buf[pos] = c; len++; pos++; buf[len] = '\0'; refreshLine(prompt,buf,len,pos,cols); } } break; } } return len; }
static int linenoisePrompt(int fd, char *buf, size_t buflen, const char *prompt) { size_t plen = strlen(prompt); size_t pos = 0; size_t len = 0; size_t cols = getColumns(); int history_index = 0; #ifdef _WIN32 DWORD foo; #endif buf[0] = '\0'; buflen--; /* Make sure there is always space for the nulterm */ /* The latest history entry is always our current buffer, that * initially is just an empty string. */ linenoiseHistoryAdd(""); #ifdef _WIN32 if (!WriteConsole(hOut, prompt, (DWORD)plen, &foo, NULL)) return -1; #else if (write(fd,prompt,plen) == -1) return -1; #endif while(1) { char c; int nread; char seq[2], seq2[2]; #ifdef _WIN32 nread = win32read(&c); #else nread = read(fd,&c,1); #endif if (nread <= 0) return (int)len; /* Only autocomplete when the callback is set. It returns < 0 when * there was an error reading from fd. Otherwise it will return the * character that should be handled next. */ if (c == 9 && completionCallback != NULL) { c = completeLine(fd,prompt,buf,buflen,&len,&pos,cols); /* Return on errors */ if (c < 0) return (int)len; /* Read next character when 0 */ if (c == 0) continue; } switch(c) { case 13: /* enter */ history_len--; free(history[history_len]); return (int)len; case 3: /* ctrl-c */ errno = EAGAIN; return -1; case 127: /* backspace */ #ifdef _WIN32 /* delete in _WIN32*/ /* win32read() will send 127 for DEL and 8 for BS and Ctrl-H */ if (pos < len && len > 0) { memmove(buf+pos,buf+pos+1,len-pos); len--; buf[len] = '\0'; refreshLine(fd,prompt,buf,len,pos,cols); } break; #endif case 8: /* ctrl-h */ if (pos > 0 && len > 0) { memmove(buf+pos-1,buf+pos,len-pos); pos--; len--; buf[len] = '\0'; refreshLine(fd,prompt,buf,len,pos,cols); } break; case 4: /* ctrl-d, remove char at right of cursor */ if (len > 1 && pos < (len-1)) { memmove(buf+pos,buf+pos+1,len-pos); len--; buf[len] = '\0'; refreshLine(fd,prompt,buf,len,pos,cols); } else if (len == 0) { history_len--; free(history[history_len]); return -1; } break; case 20: /* ctrl-t */ if (pos > 0 && pos < len) { int aux = buf[pos-1]; buf[pos-1] = buf[pos]; buf[pos] = aux; if (pos != len-1) pos++; refreshLine(fd,prompt,buf,len,pos,cols); } break; case 2: /* ctrl-b */ goto left_arrow; case 6: /* ctrl-f */ goto right_arrow; case 16: /* ctrl-p */ seq[1] = 65; goto up_down_arrow; case 14: /* ctrl-n */ seq[1] = 66; goto up_down_arrow; break; case 27: /* escape sequence */ if (read(fd,seq,2) == -1) break; if (seq[0] == 91 && seq[1] == 68) { left_arrow: /* left arrow */ if (pos > 0) { pos--; refreshLine(fd,prompt,buf,len,pos,cols); } } else if (seq[0] == 91 && seq[1] == 67) { right_arrow: /* right arrow */ if (pos != len) { pos++; refreshLine(fd,prompt,buf,len,pos,cols); } } else if (seq[0] == 91 && (seq[1] == 65 || seq[1] == 66)) { up_down_arrow: /* up and down arrow: history */ if (history_len > 1) { /* Update the current history entry before to * overwrite it with tne next one. */ free(history[history_len-1-history_index]); history[history_len-1-history_index] = strdup(buf); /* Show the new entry */ history_index += (seq[1] == 65) ? 1 : -1; if (history_index < 0) { history_index = 0; break; } else if (history_index >= history_len) { history_index = history_len-1; break; } strncpy(buf,history[history_len-1-history_index],buflen); buf[buflen] = '\0'; len = pos = strlen(buf); refreshLine(fd,prompt,buf,len,pos,cols); } } else if (seq[0] == 91 && seq[1] > 48 && seq[1] < 55) { /* extended escape */ if (read(fd,seq2,2) == -1) break; if (seq[1] == 51 && seq2[0] == 126) { /* delete */ if (len > 0 && pos < len) { memmove(buf+pos,buf+pos+1,len-pos-1); len--; buf[len] = '\0'; refreshLine(fd,prompt,buf,len,pos,cols); } } } break; default: if (len < buflen) { if (len == pos) { buf[pos] = c; pos++; len++; buf[len] = '\0'; if (plen+len < cols) { /* Avoid a full update of the line in the * trivial case. */ #ifdef _WIN32 if (!WriteConsole(hOut, &c, 1, &foo, NULL)) return -1; #else if (write(fd,&c,1) == -1) return -1; #endif } else { refreshLine(fd,prompt,buf,len,pos,cols); } } else { memmove(buf+pos+1,buf+pos,len-pos); buf[pos] = c; len++; pos++; buf[len] = '\0'; refreshLine(fd,prompt,buf,len,pos,cols); } } break; case 21: /* Ctrl+u, delete the whole line. */ buf[0] = '\0'; pos = len = 0; refreshLine(fd,prompt,buf,len,pos,cols); break; case 11: /* Ctrl+k, delete from current to end of line. */ buf[pos] = '\0'; len = pos; refreshLine(fd,prompt,buf,len,pos,cols); break; case 1: /* Ctrl+a, go to the start of the line */ pos = 0; refreshLine(fd,prompt,buf,len,pos,cols); break; case 5: /* ctrl+e, go to the end of the line */ pos = len; refreshLine(fd,prompt,buf,len,pos,cols); break; case 12: /* ctrl+l, clear screen */ linenoiseClearScreen(); refreshLine(fd,prompt,buf,len,pos,cols); } } return (int)len; }