예제 #1
0
파일: termscreen.c 프로젝트: Snaptags/vim
/*
 * Allocate a new screen and return it.
 * Return NULL when out of memory.
 */
static VTermScreen *screen_new(VTerm *vt)
{
  VTermState *state = vterm_obtain_state(vt);
  VTermScreen *screen;
  int rows, cols;

  if (state == NULL)
    return NULL;
  screen = vterm_allocator_malloc(vt, sizeof(VTermScreen));
  if (screen == NULL)
    return NULL;

  vterm_get_size(vt, &rows, &cols);

  screen->vt = vt;
  screen->state = state;

  screen->damage_merge = VTERM_DAMAGE_CELL;
  screen->damaged.start_row = -1;
  screen->pending_scrollrect.start_row = -1;

  screen->rows = rows;
  screen->cols = cols;

  screen->callbacks = NULL;
  screen->cbdata    = NULL;

  screen->buffers[0] = realloc_buffer(screen, NULL, rows, cols);
  screen->buffer = screen->buffers[0];
  screen->sb_buffer = vterm_allocator_malloc(screen->vt, sizeof(VTermScreenCell) * cols);
  if (screen->buffer == NULL || screen->sb_buffer == NULL)
  {
    vterm_screen_free(screen);
    return NULL;
  }

  vterm_state_set_callbacks(screen->state, &state_cbs, screen);

  return screen;
}
예제 #2
0
VTerm *vterm_new_with_allocator(int rows, int cols, VTermAllocatorFunctions *funcs, void *allocdata)
{
  /* Need to bootstrap using the allocator function directly */
  VTerm *vt = (*funcs->malloc)(sizeof(VTerm), allocdata);

  vt->allocator = funcs;
  vt->allocdata = allocdata;

  vt->rows = rows;
  vt->cols = cols;

  vt->parser_state = NORMAL;

  vt->strbuffer_len = 64;
  vt->strbuffer_cur = 0;
  vt->strbuffer = vterm_allocator_malloc(vt, vt->strbuffer_len);

  vt->outbuffer_len = 64;
  vt->outbuffer_cur = 0;
  vt->outbuffer = vterm_allocator_malloc(vt, vt->outbuffer_len);

  return vt;
}
예제 #3
0
파일: termscreen.c 프로젝트: Snaptags/vim
static ScreenCell *realloc_buffer(VTermScreen *screen, ScreenCell *buffer, int new_rows, int new_cols)
{
  ScreenCell *new_buffer = vterm_allocator_malloc(screen->vt, sizeof(ScreenCell) * new_rows * new_cols);
  int row, col;

  for(row = 0; row < new_rows; row++) {
    for(col = 0; col < new_cols; col++) {
      ScreenCell *new_cell = new_buffer + row*new_cols + col;

      if(buffer && row < screen->rows && col < screen->cols)
        *new_cell = buffer[row * screen->cols + col];
      else {
        new_cell->chars[0] = 0;
        new_cell->pen = screen->pen;
      }
    }
  }

  vterm_allocator_free(screen->vt, buffer);

  return new_buffer;
}
예제 #4
0
파일: screen.c 프로젝트: rasilon/vim
static int resize(int new_rows, int new_cols, VTermPos *delta, void *user)
{
  VTermScreen *screen = user;

  int is_altscreen = (screen->buffers[1] && screen->buffer == screen->buffers[1]);

  int old_rows = screen->rows;
  int old_cols = screen->cols;
  int first_blank_row;

  if(!is_altscreen && new_rows < old_rows) {
    /* Fewer rows - determine if we're going to scroll at all, and if so, push
       those lines to scrollback */
    VTermPos pos = { 0, 0 };
    VTermPos cursor = screen->state->pos;
    /* Find the first blank row after the cursor. */
    for(pos.row = old_rows - 1; pos.row >= new_rows; pos.row--)
      if(!vterm_screen_is_eol(screen, pos) || cursor.row == pos.row)
        break;

    first_blank_row = pos.row + 1;
    if(first_blank_row > new_rows) {
      VTermRect rect = {0,0,0,0};
      rect.end_row   = old_rows;
      rect.end_col   = old_cols;
      scrollrect(rect, first_blank_row - new_rows, 0, user);
      vterm_screen_flush_damage(screen);

      delta->row -= first_blank_row - new_rows;
    }
  }

  screen->buffers[0] = realloc_buffer(screen, screen->buffers[0], new_rows, new_cols);
  if(screen->buffers[1])
    screen->buffers[1] = realloc_buffer(screen, screen->buffers[1], new_rows, new_cols);

  screen->buffer = is_altscreen ? screen->buffers[1] : screen->buffers[0];

  screen->rows = new_rows;
  screen->cols = new_cols;

  if(screen->sb_buffer)
    vterm_allocator_free(screen->vt, screen->sb_buffer);

  screen->sb_buffer = vterm_allocator_malloc(screen->vt, sizeof(VTermScreenCell) * new_cols);

  if(new_cols > old_cols) {
    VTermRect rect;
    rect.start_row = 0;
    rect.end_row   = old_rows;
    rect.start_col = old_cols;
    rect.end_col   = new_cols;
    damagerect(screen, rect);
  }

  if(new_rows > old_rows) {
    if(!is_altscreen && screen->callbacks && screen->callbacks->sb_popline) {
      int rows = new_rows - old_rows;
      while(rows) {
        VTermRect rect = {0,0,0,0};
        VTermPos pos = { 0, 0 };
        if(!(screen->callbacks->sb_popline(screen->cols, screen->sb_buffer, screen->cbdata)))
          break;

	rect.end_row   = screen->rows;
	rect.end_col   = screen->cols;
        scrollrect(rect, -1, 0, user);

        for(pos.col = 0; pos.col < screen->cols; pos.col += screen->sb_buffer[pos.col].width)
          vterm_screen_set_cell(screen, pos, screen->sb_buffer + pos.col);

        rect.end_row = 1;
        damagerect(screen, rect);

        vterm_screen_flush_damage(screen);

        rows--;
        delta->row++;
      }
    }

    {
      VTermRect rect;
      rect.start_row = old_rows;
      rect.end_row   = new_rows;
      rect.start_col = 0;
      rect.end_col   = new_cols;
      damagerect(screen, rect);
    }
  }

  if(screen->callbacks && screen->callbacks->resize)
    return (*screen->callbacks->resize)(new_rows, new_cols, screen->cbdata);

  return 1;
}