void scr_add(struct scroller *scr, const char *buf, enum ScrInputKind kind) { char *tempbuf = NULL; if (scr->last_inferior_line) { if (kind != SCR_INPUT_INFERIOR) { /* New line coming in isn't from inferior so spew out * last inferior line and carry on */ scr_add_buf(scr, scr->last_inferior_line, SCR_INPUT_INFERIOR); free(scr->last_inferior_line); } else { /* Combine this inferior line with previous inferior line */ tempbuf = (char *)cgdb_realloc(scr->last_inferior_line, strlen(scr->last_inferior_line) + strlen(buf) + 1); strcat(tempbuf, buf); buf = tempbuf; } scr->last_inferior_line = NULL; } scr_add_buf(scr, buf, kind); scr_end(scr); free(tempbuf); }
void stop(const char *why) { if (isset) scr_end(); errx(1, "aborting: %s", why); }
/* gdb_input: Handles user input to the GDB window. * ---------- * * key: Keystroke received. * * Return Value: 0 if internal key was used, * 1 if input to gdb or ... * -1 : Error resizing terminal -- terminal too small */ static int gdb_input(int key) { /* Handle special keys */ switch (key) { case CGDB_KEY_PPAGE: scr_up(gdb_win, get_gdb_height() - 1); break; case CGDB_KEY_NPAGE: scr_down(gdb_win, get_gdb_height() - 1); break; case CGDB_KEY_F11: scr_home(gdb_win); break; case CGDB_KEY_F12: scr_end(gdb_win); break; #if 0 /* I would like to add better support for control-l in the GDB * window, but this patch didn't make me happy enough to release it. * The problem is, when it clears the screen, it adds a lot of * whitespace in the buffer. If you hit page-up to look back in * the buffer, it's visible. This is really unacceptable. * * The approach I believe I would like to take with this, is to * have the GDB window behave more like the terminal. That is, * have GDB start at the top line, and move down as input * becomes available. Then, when you hit ctrl-l, you just move * the prompt to the top line. */ case CGDB_KEY_CTRL_L: { int height = get_gdb_height(), i; /* Allocate and print enough newlines to clear the gdb buffer. */ char *buf = (char *) cgdb_malloc(sizeof (char *) * height); for (i = 0; i < height - 1; ++i) { buf[i] = '\n'; } buf[i] = '\0'; if_print(buf); free(buf); /* Sneaky return 1 here. Basically, this allows tricks readline to think * that gdb did not handle the Ctrl-l. That way readline will also handle * it. Because readline uses TERM=dumb, that means that it will clear a * single line and put out the prompt. */ return 1; break; } #endif default: return 1; } if_draw(); return 0; }
/* tty_input: Handles user input to the tty I/O window. * ---------- * * key: Keystroke received. * * Return Value: 0 if internal key was used, * 2 if input to tty, * -1 : Error resizing terminal -- terminal too small */ static int tty_input(int key) { /* Handle special keys */ switch (key) { case CGDB_KEY_PPAGE: scr_up(tty_win, get_tty_height() - 1); break; case CGDB_KEY_NPAGE: scr_down(tty_win, get_tty_height() - 1); break; case CGDB_KEY_F11: scr_home(tty_win); break; case CGDB_KEY_F12: scr_end(tty_win); break; default: return 2; } if_draw(); return 0; }
static void scr_add_buf(struct scroller *scr, const char *buf, enum ScrInputKind kind) { char *x; int distance; /* Find next newline in the string */ x = strchr((char *)buf, '\n'); distance = x ? x - buf : strlen(buf); /* Append to the last line in the buffer */ if (distance > 0) { int is_crlf = (distance == 1) && (buf[0] == '\r'); if (!is_crlf) { int index = sbcount(scr->lines) - 1; char *orig = scr->lines[index].line; int orig_len = scr->lines[index].line_len; if ((scr->last_inferior_attr != -1) && (kind != scr->lines[index].kind)) { /* Default to 0: Add that color attribute in */ int attr = 0; if (kind == SCR_INPUT_INFERIOR) { attr = scr->last_inferior_attr; scr->last_inferior_attr = -1; } sbpush(scr->lines[index].attrs, hl_line_attr(orig_len, attr)); } scr->lines[index].kind = kind; scr->lines[index].line = parse( scr, &scr->lines[index].attrs, orig, buf, distance, kind); scr->lines[index].line_len = strlen(scr->lines[index].line); scroller_set_last_inferior_attr(scr); free(orig); } } /* Create additional lines if buf contains newlines */ while (x != NULL) { char *line; struct hl_line_attr *attrs = NULL; buf = x + 1; x = strchr((char *)buf, '\n'); distance = x ? x - buf : strlen(buf); /* inferior input with no lf. */ if (!x && (kind == SCR_INPUT_INFERIOR) && distance && (distance < 4096)) { /* Store away and parse when the rest of the line shows up */ scr->last_inferior_line = strdup(buf); /* Add line since we did have a lf */ scr->current.pos = 0; scroller_addline(scr, strdup(""), NULL, kind); break; } /* Expand the buffer */ scr->current.pos = 0; /* Add the new line */ line = parse(scr, &attrs, "", buf, distance, kind); scroller_addline(scr, line, attrs, kind); } /* Don't want to exit scroll mode simply because new data received */ if (!scr->in_scroll_mode) { scr_end(scr); } }
/* gdb_input: Handles user input to the GDB window. * ---------- * * key: Keystroke received. * * Return Value: 0 if internal key was used, * 1 if input to gdb or ... * -1 : Error resizing terminal -- terminal too small */ static int gdb_input(int key, int *last_key) { int result = 0; if (gdb_scroller->in_search_mode) return gdb_input_regex_input(gdb_scroller, key); if (gdb_scroller->in_scroll_mode) { /* Handle setting (mX) and going ('X) to gdb buffer marks */ if (last_key_pressed == 'm' || last_key_pressed == '\'') { int ret = 0; if (last_key_pressed == 'm') ret = scr_set_mark(gdb_scroller, key); else if(last_key_pressed == '\'') ret = scr_goto_mark(gdb_scroller, key); if (ret) { *last_key = 0; if_draw(); } return 0; } /* In scroll mode, all extra characters are not passed to * the active GDB command. result = 0 above ensures that. */ switch (key) { case 'm': case '\'': /* Mark keys - ignore them */ break; case CGDB_KEY_CTRL_U: scr_up(gdb_scroller, get_gdb_height() / 2); break; case CGDB_KEY_PPAGE: scr_up(gdb_scroller, get_gdb_height() - 1); break; case CGDB_KEY_CTRL_D: scr_down(gdb_scroller, get_gdb_height() / 2); break; case CGDB_KEY_NPAGE: scr_down(gdb_scroller, get_gdb_height() - 1); break; case CGDB_KEY_HOME: case CGDB_KEY_F11: scr_home(gdb_scroller); break; case 'G': case CGDB_KEY_END: case CGDB_KEY_F12: scr_end(gdb_scroller); break; case 'k': case CGDB_KEY_UP: case CGDB_KEY_CTRL_P: scr_up(gdb_scroller, 1); break; case 'j': case CGDB_KEY_DOWN: case CGDB_KEY_CTRL_N: scr_down(gdb_scroller, 1); break; case 'g': if (last_key_pressed == 'g') { scr_home(gdb_scroller); } break; case 'q': case 'i': case '\r': case '\n': case CGDB_KEY_CTRL_M: scr_end(gdb_scroller); gdb_scroller->in_scroll_mode = 0; break; case 'n': scr_search_regex(gdb_scroller, ibuf_get(regex_last), 2, regex_direction_last, cgdbrc_get_int(CGDBRC_IGNORECASE)); break; case 'N': scr_search_regex(gdb_scroller, ibuf_get(regex_last), 2, !regex_direction_last, cgdbrc_get_int(CGDBRC_IGNORECASE)); break; case '/': case '?': /* Capturing regular expressions */ regex_cur = ibuf_init(); regex_direction_cur = ('/' == key); orig_line_regex = gdb_scroller->current.r; sbc_kind = SBC_REGEX; scr_search_regex_init(gdb_scroller); break; } } else { switch (key) { case CGDB_KEY_PPAGE: scr_up(gdb_scroller, get_gdb_height() - 1); break; case CGDB_KEY_CTRL_L: scr_clear(gdb_scroller); /* The return 1 tells readline that gdb did not handle the * Ctrl-l. That way readline will handle it. Because * readline uses TERM=dumb, that means that it will clear * a single line and put out the prompt. */ result = 1; break; default: /* This tells the input to go to active GDB command */ result = 1; } } if_draw(); return result; }