⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 getline.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 4 页
字号:
#endif

    /* We'll change the result code only if something happens later. */
    gl_result = GL_OK;

	/* Even if it appears that "vi" is preferred, we
	 * don't start in gl_vi_mode.  They need to hit
	 * ESC to go into vi command mode.
	 */
	gl_vi_mode = 0;
	vi_count = 0;
	vi_delete = 0;
	if (gl_vi_preferred < 0) {
		gl_vi_preferred = 0;
		cp = (char *) getenv("EDITOR");
		if (cp != NULL)
			gl_vi_preferred = (strstr(cp, "vi") != NULL);
		if (gl_vi_preferred == 0)
			gl_check_inputrc_for_vi();
	}

    gl_init();
    gl_prompt = (prompt)? prompt : "";
    gl_buf[0] = 0;
    if (gl_in_hook)
	gl_in_hook(gl_buf);
    gl_fixup(gl_prompt, -2, GL_BUF_SIZE);
    lastch = 0;

#ifdef __windows__
	FlushConsoleInputBuffer(GetStdHandle(STD_INPUT_HANDLE));
#endif

    while ((c = gl_getc()) != (-1)) {
	gl_extent = 0;  	/* reset to full extent */
	/* Note: \n may or may not be considered printable */
	if ((c != '\t') && ((isprint(c) != 0) || ((c & 0x80) != 0))) {
	    if (gl_vi_mode > 0) {
	    	/* "vi" emulation -- far from perfect,
		 * but reasonably functional.
		 */
vi:
		for (count = 0; ; ) {
			if (isdigit(c)) {
				if (vi_countbuf[sizeof(vi_countbuf) - 2] == '\0')
					vi_countbuf[strlen(vi_countbuf)] = (char) c;
			} else if (vi_countbuf[0] != '\0') {
				vi_count = atoi(vi_countbuf);
				memset(vi_countbuf, 0, sizeof(vi_countbuf));
			}
			switch (c) {
				case 'b':
					gl_word(-1);
					break;
				case 'w':
					if (vi_delete) {
						gl_killword(1);
					} else {
						gl_word(1);
					}
					break;
				case 'h':	/* left */
					if (vi_delete) {
						if (gl_pos > 0) {
	      						gl_fixup(gl_prompt, -1, gl_pos-1);
						    	gl_del(0, 1);
						}
					} else {
	      					gl_fixup(gl_prompt, -1, gl_pos-1);
					}
					break;
				case ' ':
				case 'l':	/* right */
					if (vi_delete) {
						gl_del(0, 1);
					} else {
						gl_fixup(gl_prompt, -1, gl_pos+1);
					}
					break;
				case 'k':	/* up */
					strcpy(gl_buf, hist_prev());
					if (gl_in_hook)
					    gl_in_hook(gl_buf);
					gl_fixup(gl_prompt, 0, GL_BUF_SIZE);
					break;
				case 'j':	/* down */
					strcpy(gl_buf, hist_next());
					if (gl_in_hook)
					    gl_in_hook(gl_buf);
					gl_fixup(gl_prompt, 0, GL_BUF_SIZE);
					break;
				case 'd':
					if (vi_delete == 1) {
	      					gl_kill(0);
						vi_count = 1;
						vi_delete = 0;
						gl_vi_mode = 0;
						goto vi_break;
					}
					vi_delete = 1;
					goto vi_break;
				case '^':	/* start of line */
					if (vi_delete) {
						vi_count = gl_pos;
						gl_fixup(gl_prompt, -1, 0);
						for (c = 0; c < vi_count; c++) {
							if (gl_cnt > 0)
								gl_del(0, 0);
						}
						vi_count = 1;
						vi_delete = 0;
					} else {
						gl_fixup(gl_prompt, -1, 0);
					}
					break;
				case '$':	/* end of line */
					if (vi_delete) {
	      					gl_kill(gl_pos);
					} else {
						loc = (int) strlen(gl_buf);
						if (loc > 1)
							loc--;
						gl_fixup(gl_prompt, -1, loc);
					}
					break;
				case 'p':	/* paste after */
					gl_fixup(gl_prompt, -1, gl_pos+1);
	      				gl_yank();
					break;
				case 'P':	/* paste before */
	      				gl_yank();
					break;
				case 'r':	/* replace character */
					gl_buf[gl_pos] = (char) gl_getc();
					gl_fixup(gl_prompt, gl_pos, gl_pos);
					vi_count = 1;
					break;
				case 'R':
					gl_overwrite = 1;
					gl_vi_mode = 0;
					break;
				case 'i':
				case 'I':
					gl_overwrite = 0;
					gl_vi_mode = 0;
					break;
				case 'o':
				case 'O':
				case 'a':
				case 'A':
					gl_overwrite = 0;
					gl_fixup(gl_prompt, -1, gl_pos+1);
					gl_vi_mode = 0;
					break;
			}
			count++;
			if (count >= vi_count)
				break;
		}
		vi_count = 1;
		vi_delete = 0;
vi_break:
		continue;
	    } else if (gl_search_mode) {
	       search_addchar(c);
	    } else {
	       gl_addchar(c);
	    }
	} else {
	    if (gl_search_mode) {
	        if (c == '\033' || c == '\016' || c == '\020') {
	            search_term();
	            c = 0;     		/* ignore the character */
		} else if (c == '\010' || c == '\177') {
		    search_addchar(-1); /* unwind search string */
		    c = 0;
		} else if (c != '\022' && c != '\023') {
		    search_term();	/* terminate and handle char */
		}
	    }
	    switch (c) {
	      case '\n': case '\r': 			/* newline */
		gl_newline();
		gl_cleanup();
		return gl_buf;
	      case '\001': gl_fixup(gl_prompt, -1, 0);		/* ^A */
		break;
	      case '\002': gl_fixup(gl_prompt, -1, gl_pos-1);	/* ^B */
		break;
	      case '\004':					/* ^D */
		if (gl_cnt == 0) {
		    gl_buf[0] = 0;
		    gl_cleanup();
		    gl_putc('\n');
		    gl_result = GL_EOF;
		    return gl_buf;
		} else {
		    gl_del(0, 1);
		}
		break;
	      case '\005': gl_fixup(gl_prompt, -1, gl_cnt);	/* ^E */
		break;
	      case '\006': gl_fixup(gl_prompt, -1, gl_pos+1);	/* ^F */
		break;
	      case '\010': case '\177': gl_del(-1, 0);	/* ^H and DEL */
		break;
	      case '\t':        				/* TAB */
	        if (gl_completion_proc) {
		    tmp = gl_pos;
		    gl_buf[sizeof(gl_buf) - 1] = '\0';
	            loc = gl_do_tab_completion(gl_buf, &tmp, sizeof(gl_buf), (lastch == '\t'));
		    gl_buf[sizeof(gl_buf) - 1] = '\0';
	            if (loc >= 0 || tmp != gl_pos)
	                gl_fixup(gl_prompt, /* loc */ -2, tmp);
		    if (lastch == '\t') {
			    c = 0;
			    lastch = 0;
		    }
		} else if (gl_tab_hook) {
		    tmp = gl_pos;
		    gl_buf[sizeof(gl_buf) - 1] = '\0';
	            loc = gl_tab_hook(gl_buf, (int) gl_strlen(gl_prompt), &tmp, sizeof(gl_buf));
		    gl_buf[sizeof(gl_buf) - 1] = '\0';
	            if (loc >= 0 || tmp != gl_pos)
	                gl_fixup(gl_prompt, loc, tmp);
                }
		break;
	      case '\013': gl_kill(gl_pos);			/* ^K */
		break;
	      case '\014': gl_redraw();				/* ^L */
		break;
	      case '\016': 					/* ^N */
		strcpy(gl_buf, hist_next());
                if (gl_in_hook)
	            gl_in_hook(gl_buf);
		gl_fixup(gl_prompt, 0, GL_BUF_SIZE);
		break;
	      case '\017': gl_overwrite = !gl_overwrite;       	/* ^O */
		break;
	      case '\020': 					/* ^P */
		strcpy(gl_buf, hist_prev());
                if (gl_in_hook)
	            gl_in_hook(gl_buf);
		gl_fixup(gl_prompt, 0, GL_BUF_SIZE);
		break;
	      case '\022': search_back(1);			/* ^R */
		break;
	      case '\023': search_forw(1);			/* ^S */
		break;
	      case '\024': gl_transpose();			/* ^T */
		break;
              case '\025': gl_kill(0);				/* ^U */
		break;
              case '\027': gl_killword(-1);			/* ^W */
		break;
	      case '\031': gl_yank();				/* ^Y */
		break;
	      case '\033':				/* ansi arrow keys */
		c = gl_getcx(3);
		if ((c == '[') || (c == 'O')) {
ansi:
		    switch(c = gl_getc()) {
		      case 'A':             			/* up */
		        strcpy(gl_buf, hist_prev());
                        if (gl_in_hook)
	                    gl_in_hook(gl_buf);
		        gl_fixup(gl_prompt, 0, GL_BUF_SIZE);
		        break;
		      case 'B':                         	/* down */
		        strcpy(gl_buf, hist_next());
                        if (gl_in_hook)
	                    gl_in_hook(gl_buf);
		        gl_fixup(gl_prompt, 0, GL_BUF_SIZE);
		        break;
		      case 'C':
		        gl_fixup(gl_prompt, -1, gl_pos+1); /* right */
		        break;
		      case 'D':
		        gl_fixup(gl_prompt, -1, gl_pos-1); /* left */
		        break;
		      case '0':
		      case '1':
		        goto ansi;
		      default: gl_beep();         /* who knows */
		        break;
		    }
		} else if ((gl_vi_preferred == 0) && ((c == 'f') || (c == 'F'))) {
		    gl_word(1);
		} else if ((gl_vi_preferred == 0) && ((c == 'b') || (c == 'B'))) {
		    gl_word(-1);
		} else if (c != (-1)) {
			/* enter vi command mode */
#if defined(__windows__) || defined(MSDOS)
			if (gl_vi_preferred == 0) {
				/* On Windows, ESC acts like a line kill,
				 * so don't use vi mode unless they prefer
				 * vi mode.
				 */
              			gl_kill(0);
			} else
#endif
			if (gl_vi_mode == 0) {
				gl_vi_mode = 1;
				vi_count = 1;
				vi_delete = 0;
				memset(vi_countbuf, 0, sizeof(vi_countbuf));
				if (gl_pos > 0)
					gl_fixup(gl_prompt, -2, gl_pos-1);	/* left 1 char */
				/* Don't bother if the line is empty and we don't
				 * know for sure if the user wants vi mode.
				 */
				if ((gl_cnt > 0) || (gl_vi_preferred == 1)) {
					/* We still have to use the char read! */
					goto vi;
				}
				gl_vi_mode = 0;
			} else {
				gl_beep();
			}
		}
		break;
	      default:		/* check for a terminal signal */
	        if (c > 0) {	/* ignore 0 (reset above) */
	            if (c == gl_intrc) {
			gl_result = GL_INTERRUPT;
			gl_buf[0] = 0;
	                gl_cleanup();
#ifdef SIGINT
	                raise(SIGINT);
	                gl_init();
	                gl_redraw();
#endif
			return gl_buf;
		    }

	            if (c == gl_quitc) {
			gl_result = GL_INTERRUPT;
			gl_buf[0] = 0;
	                gl_cleanup();
#ifdef SIGQUIT
	                raise(SIGQUIT);
	                gl_init();
	                gl_redraw();
#endif
			return gl_buf;
		    }

#ifdef __unix__
	            if (c == gl_suspc || c == gl_dsuspc) {
#ifdef SIGTSTP
			gl_result = GL_INTERRUPT;
			gl_buf[0] = 0;
			gl_cleanup();
	                sig = SIGTSTP;
	                kill(0, sig);
	                gl_init();
	                gl_redraw();
			return gl_buf;
#endif
		    }
#endif /* __unix__ */
		}
                if (c > 0)
		    gl_beep();
		break;
	    }
	}
	if (c > 0)
	    lastch = c;
    }
    gl_buf[0] = 0;
    gl_cleanup();
    return gl_buf;
}

static void
gl_addchar(int c)

/* adds the character c to the input buffer at current location */
{
    int  i;

    if (gl_cnt >= GL_BUF_SIZE - 1)
	gl_error("\n*** Error: getline(): input buffer overflow\n");
    if (gl_overwrite == 0 || gl_pos == gl_cnt) {
        for (i=gl_cnt; i >= gl_pos; i--)
            gl_buf[i+1] = gl_buf[i];
        gl_buf[gl_pos] = (char) c;
        gl_fixup(gl_prompt, gl_pos, gl_pos+1);
    } else {
	gl_buf[gl_pos] = (char) c;
	gl_extent = 1;
        gl_fixup(gl_prompt, gl_pos, gl_pos+1);
    }
}

static void
gl_yank(void)
/* adds the kill buffer to the input buffer at current location */
{
    int  i, len;

    len = (int) strlen(gl_killbuf);
    if (len > 0) {
	if (gl_overwrite == 0) {
            if (gl_cnt + len >= GL_BUF_SIZE - 1)
	        gl_error("\n*** Error: getline(): input buffer overflow\n");
            for (i=gl_cnt; i >= gl_pos; i--)
                gl_buf[i+len] = gl_buf[i];
	    for (i=0; i < len; i++)
                gl_buf[gl_pos+i] = gl_killbuf[i];
            gl_fixup(gl_prompt, gl_pos, gl_pos+len);
	} else {
	    if (gl_pos + len > gl_cnt) {
                if (gl_pos + len >= GL_BUF_SIZE - 1)
	            gl_error("\n*** Error: getline(): input buffer overflow\n");
		gl_buf[gl_pos + len] = 0;
            }
	    for (i=0; i < len; i++)
                gl_buf[gl_pos+i] = gl_killbuf[i];
	    gl_extent = len;
            gl_fixup(gl_prompt, gl_pos, gl_pos+len);
	}
    } else
	gl_beep();
}

static void
gl_transpose(void)
/* switch character under cursor and to left of cursor */
{
    int    c;

    if (gl_pos > 0 && gl_cnt > gl_pos) {
	c = gl_buf[gl_pos-1];
	gl_buf[gl_pos-1] = gl_buf[gl_pos];
	gl_buf[gl_pos] = (char) c;
	gl_extent = 2;
	gl_fixup(gl_prompt, gl_pos-1, gl_pos);
    } else
	gl_beep();
}

static void
gl_newline(void)
/*
 * Cleans up entire line before returning to caller. A \n is appended.
 * If line longer than screen, we redraw starting at beginning
 */
{
    int change = gl_cnt;
    int len = gl_cnt;
    int loc = gl_width - 5;	/* shifts line back to start position */

    if (gl_cnt >= GL_BUF_SIZE - 1)
        gl_error("\n*** Error: getline(): input buffer overflow\n");
    if (gl_out_hook) {
	change = gl_out_hook(gl_buf);
        len = (int) strlen(gl_buf);
    }
    if (loc > len)
	loc = len;
    gl_fixup(gl_prompt, change, loc);	/* must do this before appending \n */
    gl_buf[len] = '\n';
    gl_buf[len+1] = '\0';
    gl_putc('\n');
}

static void
gl_del(int loc, int killsave)

/*
 * Delete a character.  The loc variable can be:
 *    -1 : delete character to left of cursor
 *     0 : delete character under cursor
 */
{
    int i, j;

    if ((loc == -1 && gl_pos > 0) || (loc == 0 && gl_pos < gl_cnt)) {
        for (j=0, i=gl_pos+loc; i < gl_cnt; i++) {
	    if ((j == 0) && (killsave != 0) && (gl_vi_mode != 0)) {
	    	gl_killbuf[0] = gl_buf[i];
	    	gl_killbuf[1] = '\0';
		j = 1;
	    }
	    gl_buf[i] = gl_buf[i+1];
	}
	gl_fixup(gl_prompt, gl_pos+loc, gl_pos+loc);
    } else
	gl_beep();
}

static void
gl_kill(int pos)

/* delete from pos to the end of line */
{
    if (pos < gl_cnt) {
	strcpy(gl_killbuf, gl_buf + pos);
	gl_buf[pos] = '\0';
	gl_fixup(gl_prompt, pos, pos);
    } else
	gl_beep();
}

static void
gl_killword(int direction)
{
    int pos = gl_pos;
    int startpos = gl_pos;
    int tmp;
    int i;

    if (direction > 0) {		/* forward */
        while (!isspace(gl_buf[pos]) && pos < gl_cnt)
	    pos++;
	while (isspace(gl_buf[pos]) && pos < gl_cnt)
	    pos++;
    } else {				/* backward */
	if (pos > 0)
	    pos--;
	while (isspace(gl_buf[pos]) && pos > 0)
	    pos--;
        while (!isspace(gl_buf[pos]) && pos > 0)
	    pos--;
	if (pos < gl_cnt && isspace(gl_buf[pos]))   /* move onto word */
	    pos++;
    }
    if (pos < startpos) {
    	tmp = pos;
	pos = startpos;
	startpos = tmp;
    }
    memcpy(gl_killbuf, gl_buf + startpos, (size_t) (pos - startpos));
    gl_killbuf[pos - startpos] = '\0';
    if (isspace(gl_killbuf[pos - startpos - 1]))
    	gl_killbuf[pos - startpos - 1] = '\0';
    gl_fixup(gl_prompt, -1, startpos);
    for (i=0, tmp=pos - startpos; i<tmp; i++)
    	gl_del(0, 0);
}	/* gl_killword */

static void
gl_word(int direction)

/* move forward or backword one word */
{
    int pos = gl_pos;

    if (direction > 0) {		/* forward */
        while (!isspace(gl_buf[pos]) && pos < gl_cnt)
	    pos++;
	while (isspace(gl_buf[pos]) && pos < gl_cnt)
	    pos++;
    } else {				/* backword */
	if (pos > 0)
	    pos--;
	while (isspace(gl_buf[pos]) && pos > 0)
	    pos--;
        while (!isspace(gl_buf[pos]) && pos > 0)
	    pos--;
	if (pos < gl_cnt && isspace(gl_buf[pos]))   /* move onto word */
	    pos++;
    }
    gl_fixup(gl_prompt, -1, pos);
}

static void
gl_redraw(void)
/* emit a newline, reset and redraw prompt and current input line */
{
    if (gl_init_done > 0) {
        gl_putc('\n');
        gl_fixup(gl_prompt, -2, gl_pos);
    }
}

static void
gl_fixup(const char *prompt, int change, int cursor)


/*
 * This function is used both for redrawing when input changes or for
 * moving within the input line.  The parameters are:
 *   prompt:  compared to last_prompt[] for changes;
 *   change : the index of the start of changes in the input buffer,
 *            with -1 indicating no changes, -2 indicating we're on
 *            a new line, redraw everything.
 *   cursor : the desired location of the cursor after the call.
 *            A value of GL_BUF_SIZE can be used  to indicate the cursor should
 *            move just past the end of the input line.
 */
{
    static int   gl_shift;	/* index of first on screen character */
    static int   off_right;	/* true if more text right of screen */
    static int   off_left;	/* true if more text left of screen */
    static char  last_prompt[80] = "";
    int          left = 0, right = -1;		/* bounds for redraw */
    int          pad;		/* how much to erase at end of line */
    int          backup;        /* how far to backup before fixing */
    int          new_shift;     /* value of shift based on cursor */
    int          extra;         /* adjusts when shift (scroll) happens */
    int          i;
    int          new_right = -1; /* alternate right bound, using gl_extent */
    int          l1, l2;

    if (change == -2) {   /* reset */
	gl_pos = gl_cnt = gl_shift = off_right = off_left = 0;
	gl_putc('\r');
	gl_puts(prompt);
	strcpy(last_prompt, prompt);
	change = 0;
        gl_width = gl_termw - (int) gl_strlen(prompt);
    } else if (strcmp(prompt, last_prompt) != 0) {
	l1 = (int) gl_strlen(last_prompt);
	l2 = (int) gl_strlen(prompt);
	gl_cnt = gl_cnt + l1 - l2;
	strcpy(last_prompt, prompt);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -