mirror of
				https://github.com/neovim/neovim.git
				synced 2025-11-04 01:34:25 +00:00 
			
		
		
		
	
				
					committed by
					
						
						Justin M. Keyes
					
				
			
			
				
	
			
			
			
						parent
						
							16babc6687
						
					
				
				
					commit
					dd4a5fcbb6
				
			@@ -12,6 +12,7 @@
 | 
			
		||||
#include "nvim/api/private/defs.h"
 | 
			
		||||
#include "nvim/api/private/helpers.h"
 | 
			
		||||
#include "nvim/popupmnu.h"
 | 
			
		||||
#include "nvim/cursor_shape.h"
 | 
			
		||||
 | 
			
		||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
 | 
			
		||||
# include "api/ui.c.generated.h"
 | 
			
		||||
@@ -69,6 +70,7 @@ void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height,
 | 
			
		||||
  ui->clear = remote_ui_clear;
 | 
			
		||||
  ui->eol_clear = remote_ui_eol_clear;
 | 
			
		||||
  ui->cursor_goto = remote_ui_cursor_goto;
 | 
			
		||||
  ui->cursor_style_set = remote_ui_cursor_style_set;
 | 
			
		||||
  ui->update_menu = remote_ui_update_menu;
 | 
			
		||||
  ui->busy_start = remote_ui_busy_start;
 | 
			
		||||
  ui->busy_stop = remote_ui_busy_stop;
 | 
			
		||||
@@ -298,6 +300,14 @@ static void remote_ui_scroll(UI *ui, int count)
 | 
			
		||||
  push_call(ui, "scroll", args);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void remote_ui_cursor_style_set(UI *ui, Dictionary styles)
 | 
			
		||||
{
 | 
			
		||||
  Array args = ARRAY_DICT_INIT;
 | 
			
		||||
  Object copy = copy_object(DICTIONARY_OBJ(styles));
 | 
			
		||||
  ADD(args, copy);
 | 
			
		||||
  push_call(ui, "cursor_style_set", args);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void remote_ui_highlight_set(UI *ui, HlAttrs attrs)
 | 
			
		||||
{
 | 
			
		||||
  Array args = ARRAY_DICT_INIT;
 | 
			
		||||
 
 | 
			
		||||
@@ -7,40 +7,84 @@
 | 
			
		||||
#include "nvim/charset.h"
 | 
			
		||||
#include "nvim/strings.h"
 | 
			
		||||
#include "nvim/syntax.h"
 | 
			
		||||
#include "nvim/api/private/helpers.h"
 | 
			
		||||
#include "nvim/ui.h"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Handling of cursor and mouse pointer shapes in various modes.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/// Handling of cursor and mouse pointer shapes in various modes.
 | 
			
		||||
static cursorentry_T shape_table[SHAPE_IDX_COUNT] =
 | 
			
		||||
{
 | 
			
		||||
  /* The values will be filled in from the 'guicursor' and 'mouseshape'
 | 
			
		||||
   * defaults when Vim starts.
 | 
			
		||||
   * Adjust the SHAPE_IDX_ defines when making changes! */
 | 
			
		||||
  {0, 0, 0, 700L, 400L, 250L, 0, 0, "n", SHAPE_CURSOR+SHAPE_MOUSE},
 | 
			
		||||
  {0, 0, 0, 700L, 400L, 250L, 0, 0, "v", SHAPE_CURSOR+SHAPE_MOUSE},
 | 
			
		||||
  {0, 0, 0, 700L, 400L, 250L, 0, 0, "i", SHAPE_CURSOR+SHAPE_MOUSE},
 | 
			
		||||
  {0, 0, 0, 700L, 400L, 250L, 0, 0, "r", SHAPE_CURSOR+SHAPE_MOUSE},
 | 
			
		||||
  {0, 0, 0, 700L, 400L, 250L, 0, 0, "c", SHAPE_CURSOR+SHAPE_MOUSE},
 | 
			
		||||
  {0, 0, 0, 700L, 400L, 250L, 0, 0, "ci", SHAPE_CURSOR+SHAPE_MOUSE},
 | 
			
		||||
  {0, 0, 0, 700L, 400L, 250L, 0, 0, "cr", SHAPE_CURSOR+SHAPE_MOUSE},
 | 
			
		||||
  {0, 0, 0, 700L, 400L, 250L, 0, 0, "o", SHAPE_CURSOR+SHAPE_MOUSE},
 | 
			
		||||
  {0, 0, 0, 700L, 400L, 250L, 0, 0, "ve", SHAPE_CURSOR+SHAPE_MOUSE},
 | 
			
		||||
  {0, 0, 0,   0L,   0L,   0L, 0, 0, "e", SHAPE_MOUSE},
 | 
			
		||||
  {0, 0, 0,   0L,   0L,   0L, 0, 0, "s", SHAPE_MOUSE},
 | 
			
		||||
  {0, 0, 0,   0L,   0L,   0L, 0, 0, "sd", SHAPE_MOUSE},
 | 
			
		||||
  {0, 0, 0,   0L,   0L,   0L, 0, 0, "vs", SHAPE_MOUSE},
 | 
			
		||||
  {0, 0, 0,   0L,   0L,   0L, 0, 0, "vd", SHAPE_MOUSE},
 | 
			
		||||
  {0, 0, 0,   0L,   0L,   0L, 0, 0, "m", SHAPE_MOUSE},
 | 
			
		||||
  {0, 0, 0,   0L,   0L,   0L, 0, 0, "ml", SHAPE_MOUSE},
 | 
			
		||||
  {0, 0, 0, 100L, 100L, 100L, 0, 0, "sm", SHAPE_CURSOR},
 | 
			
		||||
  // The values will be filled in from the 'guicursor' and 'mouseshape'
 | 
			
		||||
  // defaults when Vim starts.
 | 
			
		||||
  // Adjust the SHAPE_IDX_ defines when making changes!
 | 
			
		||||
  { "normal",
 | 
			
		||||
    0, 0, 0, 700L, 400L, 250L, 0, 0, "n", SHAPE_CURSOR+SHAPE_MOUSE },
 | 
			
		||||
  { "visual",
 | 
			
		||||
    0, 0, 0, 700L, 400L, 250L, 0, 0, "v", SHAPE_CURSOR+SHAPE_MOUSE },
 | 
			
		||||
  { "insert",
 | 
			
		||||
    0, 0, 0, 700L, 400L, 250L, 0, 0, "i", SHAPE_CURSOR+SHAPE_MOUSE },
 | 
			
		||||
  { "replace",
 | 
			
		||||
    0, 0, 0, 700L, 400L, 250L, 0, 0, "r", SHAPE_CURSOR+SHAPE_MOUSE },
 | 
			
		||||
  { "cmd_normal",
 | 
			
		||||
    0, 0, 0, 700L, 400L, 250L, 0, 0, "c", SHAPE_CURSOR+SHAPE_MOUSE },
 | 
			
		||||
  { "cmd_insert", 0,
 | 
			
		||||
    0, 0, 700L, 400L, 250L, 0, 0, "ci", SHAPE_CURSOR+SHAPE_MOUSE },
 | 
			
		||||
  { "cmd_replace",
 | 
			
		||||
    0, 0, 0, 700L, 400L, 250L, 0, 0, "cr", SHAPE_CURSOR+SHAPE_MOUSE },
 | 
			
		||||
  { "pending",
 | 
			
		||||
    0, 0, 0, 700L, 400L, 250L, 0, 0, "o", SHAPE_CURSOR+SHAPE_MOUSE },
 | 
			
		||||
  { "visual_select",
 | 
			
		||||
    0, 0, 0, 700L, 400L, 250L, 0, 0, "ve", SHAPE_CURSOR+SHAPE_MOUSE },
 | 
			
		||||
  { "cmd_line", 0, 0, 0,   0L,   0L,   0L, 0, 0, "e", SHAPE_MOUSE },
 | 
			
		||||
  { "statusline", 0, 0, 0,   0L,   0L,   0L, 0, 0, "s", SHAPE_MOUSE },
 | 
			
		||||
  { "drag_statusline", 0, 0, 0,   0L,   0L,   0L, 0, 0, "sd", SHAPE_MOUSE },
 | 
			
		||||
  { "vsep", 0, 0, 0,   0L,   0L,   0L, 0, 0, "vs", SHAPE_MOUSE },
 | 
			
		||||
  { "vdrag", 0, 0, 0,   0L,   0L,   0L, 0, 0, "vd", SHAPE_MOUSE },
 | 
			
		||||
  { "more", 0, 0, 0,   0L,   0L,   0L, 0, 0, "m", SHAPE_MOUSE },
 | 
			
		||||
  { "more_lastline", 0, 0, 0,   0L,   0L,   0L, 0, 0, "ml", SHAPE_MOUSE },
 | 
			
		||||
  { "match_paren", 0, 0, 0, 100L, 100L, 100L, 0, 0, "sm", SHAPE_CURSOR },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Parse the 'guicursor' option ("what" is SHAPE_CURSOR) or 'mouseshape'
 | 
			
		||||
 * ("what" is SHAPE_MOUSE).
 | 
			
		||||
 * Returns error message for an illegal option, NULL otherwise.
 | 
			
		||||
 */
 | 
			
		||||
/// Converts cursor_shapes into a Dictionary of dictionaries
 | 
			
		||||
/// @return a dictionary of the form {"normal" : { "cursor_shape": ... }, ...}
 | 
			
		||||
Dictionary cursor_shape_dict(void)
 | 
			
		||||
{
 | 
			
		||||
  Dictionary all = ARRAY_DICT_INIT;
 | 
			
		||||
 | 
			
		||||
  for (int i = 0; i < SHAPE_IDX_COUNT; i++) {
 | 
			
		||||
    Dictionary dic = ARRAY_DICT_INIT;
 | 
			
		||||
    cursorentry_T *cur = &shape_table[i];
 | 
			
		||||
    if (cur->used_for & SHAPE_MOUSE) {
 | 
			
		||||
      PUT(dic, "mouse_shape", INTEGER_OBJ(cur->mshape));
 | 
			
		||||
    }
 | 
			
		||||
    if (cur->used_for & SHAPE_CURSOR) {
 | 
			
		||||
      String shape_str;
 | 
			
		||||
      switch (cur->shape) {
 | 
			
		||||
        case SHAPE_BLOCK: shape_str = cstr_to_string("block"); break;
 | 
			
		||||
        case SHAPE_VER: shape_str = cstr_to_string("vertical"); break;
 | 
			
		||||
        case SHAPE_HOR: shape_str = cstr_to_string("horizontal"); break;
 | 
			
		||||
        default: shape_str = cstr_to_string("unknown");
 | 
			
		||||
      }
 | 
			
		||||
      PUT(dic, "cursor_shape", STRING_OBJ(shape_str));
 | 
			
		||||
      PUT(dic, "cell_percentage", INTEGER_OBJ(cur->percentage));
 | 
			
		||||
      PUT(dic, "blinkwait", INTEGER_OBJ(cur->blinkwait));
 | 
			
		||||
      PUT(dic, "blinkon", INTEGER_OBJ(cur->blinkon));
 | 
			
		||||
      PUT(dic, "blinkoff", INTEGER_OBJ(cur->blinkoff));
 | 
			
		||||
      PUT(dic, "hl_id", INTEGER_OBJ(cur->id));
 | 
			
		||||
      PUT(dic, "id_lm", INTEGER_OBJ(cur->id_lm));
 | 
			
		||||
    }
 | 
			
		||||
    PUT(dic, "short_name", STRING_OBJ(cstr_to_string(cur->name)));
 | 
			
		||||
 | 
			
		||||
    PUT(all, cur->full_name, DICTIONARY_OBJ(dic));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return all;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Parse the 'guicursor' option
 | 
			
		||||
///
 | 
			
		||||
/// @param what either SHAPE_CURSOR or SHAPE_MOUSE ('mouseshape')
 | 
			
		||||
///
 | 
			
		||||
/// @returns error message for an illegal option, NULL otherwise.
 | 
			
		||||
char_u *parse_shape_opt(int what)
 | 
			
		||||
{
 | 
			
		||||
  char_u      *modep;
 | 
			
		||||
@@ -71,19 +115,18 @@ char_u *parse_shape_opt(int what)
 | 
			
		||||
        return (char_u *)N_("E546: Illegal mode");
 | 
			
		||||
      commap = vim_strchr(modep, ',');
 | 
			
		||||
 | 
			
		||||
      /*
 | 
			
		||||
       * Repeat for all mode's before the colon.
 | 
			
		||||
       * For the 'a' mode, we loop to handle all the modes.
 | 
			
		||||
       */
 | 
			
		||||
      // Repeat for all mode's before the colon.
 | 
			
		||||
      // For the 'a' mode, we loop to handle all the modes.
 | 
			
		||||
      all_idx = -1;
 | 
			
		||||
      assert(modep < colonp);
 | 
			
		||||
      while (modep < colonp || all_idx >= 0) {
 | 
			
		||||
        if (all_idx < 0) {
 | 
			
		||||
          /* Find the mode. */
 | 
			
		||||
          if (modep[1] == '-' || modep[1] == ':')
 | 
			
		||||
          // Find the mode
 | 
			
		||||
          if (modep[1] == '-' || modep[1] == ':') {
 | 
			
		||||
            len = 1;
 | 
			
		||||
          else
 | 
			
		||||
          } else {
 | 
			
		||||
            len = 2;
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          if (len == 1 && TOLOWER_ASC(modep[0]) == 'a') {
 | 
			
		||||
            all_idx = SHAPE_IDX_COUNT - 1;
 | 
			
		||||
@@ -100,11 +143,11 @@ char_u *parse_shape_opt(int what)
 | 
			
		||||
          modep += len + 1;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (all_idx >= 0)
 | 
			
		||||
        if (all_idx >= 0) {
 | 
			
		||||
          idx = all_idx--;
 | 
			
		||||
        else if (round == 2) {
 | 
			
		||||
        } else if (round == 2) {
 | 
			
		||||
          {
 | 
			
		||||
            /* Set the defaults, for the missing parts */
 | 
			
		||||
            // Set the defaults, for the missing parts
 | 
			
		||||
            shape_table[idx].shape = SHAPE_BLOCK;
 | 
			
		||||
            shape_table[idx].blinkwait = 700L;
 | 
			
		||||
            shape_table[idx].blinkon = 400L;
 | 
			
		||||
@@ -208,6 +251,23 @@ char_u *parse_shape_opt(int what)
 | 
			
		||||
      shape_table[SHAPE_IDX_VE].id_lm = shape_table[SHAPE_IDX_V].id_lm;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ui_cursor_style_set();
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/// Map cursor mode from string to integer
 | 
			
		||||
///
 | 
			
		||||
/// @param mode Fullname of the mode whose id we are looking for
 | 
			
		||||
/// @return -1 in case of failure, else the matching SHAPE_ID* integer
 | 
			
		||||
int cursor_mode_str2int(const char *mode)
 | 
			
		||||
{
 | 
			
		||||
  for (int current_mode = 0; current_mode < SHAPE_IDX_COUNT; current_mode++) {
 | 
			
		||||
    if (strcmp(shape_table[current_mode].full_name, mode) == 0) {
 | 
			
		||||
      return current_mode;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  ELOG("Unknown mode %s", mode);
 | 
			
		||||
  return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,32 +1,34 @@
 | 
			
		||||
#ifndef NVIM_CURSOR_SHAPE_H
 | 
			
		||||
#define NVIM_CURSOR_SHAPE_H
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * struct to store values from 'guicursor' and 'mouseshape'
 | 
			
		||||
 */
 | 
			
		||||
/* Indexes in shape_table[] */
 | 
			
		||||
#define SHAPE_IDX_N     0       /* Normal mode */
 | 
			
		||||
#define SHAPE_IDX_V     1       /* Visual mode */
 | 
			
		||||
#define SHAPE_IDX_I     2       /* Insert mode */
 | 
			
		||||
#define SHAPE_IDX_R     3       /* Replace mode */
 | 
			
		||||
#define SHAPE_IDX_C     4       /* Command line Normal mode */
 | 
			
		||||
#define SHAPE_IDX_CI    5       /* Command line Insert mode */
 | 
			
		||||
#define SHAPE_IDX_CR    6       /* Command line Replace mode */
 | 
			
		||||
#define SHAPE_IDX_O     7       /* Operator-pending mode */
 | 
			
		||||
#define SHAPE_IDX_VE    8       /* Visual mode with 'selection' exclusive */
 | 
			
		||||
#define SHAPE_IDX_CLINE 9       /* On command line */
 | 
			
		||||
#define SHAPE_IDX_STATUS 10     /* A status line */
 | 
			
		||||
#define SHAPE_IDX_SDRAG 11      /* dragging a status line */
 | 
			
		||||
#define SHAPE_IDX_VSEP  12      /* A vertical separator line */
 | 
			
		||||
#define SHAPE_IDX_VDRAG 13      /* dragging a vertical separator line */
 | 
			
		||||
#define SHAPE_IDX_MORE  14      /* Hit-return or More */
 | 
			
		||||
#define SHAPE_IDX_MOREL 15      /* Hit-return or More in last line */
 | 
			
		||||
#define SHAPE_IDX_SM    16      /* showing matching paren */
 | 
			
		||||
#define SHAPE_IDX_COUNT 17
 | 
			
		||||
/// struct to store values from 'guicursor' and 'mouseshape'
 | 
			
		||||
/// Indexes in shape_table[]
 | 
			
		||||
typedef enum {
 | 
			
		||||
SHAPE_IDX_N      = 0,       ///< Normal mode
 | 
			
		||||
SHAPE_IDX_V      = 1,       ///< Visual mode
 | 
			
		||||
SHAPE_IDX_I      = 2,       ///< Insert mode
 | 
			
		||||
SHAPE_IDX_R      = 3,       ///< Replace mode
 | 
			
		||||
SHAPE_IDX_C      = 4,       ///< Command line Normal mode
 | 
			
		||||
SHAPE_IDX_CI     = 5,       ///< Command line Insert mode
 | 
			
		||||
SHAPE_IDX_CR     = 6,       ///< Command line Replace mode
 | 
			
		||||
SHAPE_IDX_O      = 7,       ///< Operator-pending mode
 | 
			
		||||
SHAPE_IDX_VE     = 8,       ///< Visual mode with 'selection' exclusive
 | 
			
		||||
SHAPE_IDX_CLINE  = 9,       ///< On command line
 | 
			
		||||
SHAPE_IDX_STATUS = 10,      ///<  status line
 | 
			
		||||
SHAPE_IDX_SDRAG  = 11,      ///< dragging a status line
 | 
			
		||||
SHAPE_IDX_VSEP   = 12,      ///< A vertical separator line
 | 
			
		||||
SHAPE_IDX_VDRAG  = 13,      ///< dragging a vertical separator line
 | 
			
		||||
SHAPE_IDX_MORE   = 14,      ///< Hit-return or More
 | 
			
		||||
SHAPE_IDX_MOREL  = 15,      ///< Hit-return or More in last line
 | 
			
		||||
SHAPE_IDX_SM     = 16,      ///< showing matching paren
 | 
			
		||||
SHAPE_IDX_COUNT  = 17
 | 
			
		||||
} MouseMode;
 | 
			
		||||
 | 
			
		||||
#define SHAPE_BLOCK     0       /* block cursor */
 | 
			
		||||
#define SHAPE_HOR       1       /* horizontal bar cursor */
 | 
			
		||||
#define SHAPE_VER       2       /* vertical bar cursor */
 | 
			
		||||
typedef enum {
 | 
			
		||||
SHAPE_BLOCK     = 0,       ///< block cursor
 | 
			
		||||
SHAPE_HOR       = 1,       ///< horizontal bar cursor
 | 
			
		||||
SHAPE_VER       = 2        ///< vertical bar cursor
 | 
			
		||||
} CursorShape;
 | 
			
		||||
 | 
			
		||||
#define MSHAPE_NUMBERED 1000    /* offset for shapes identified by number */
 | 
			
		||||
#define MSHAPE_HIDE     1       /* hide mouse pointer */
 | 
			
		||||
@@ -35,16 +37,17 @@
 | 
			
		||||
#define SHAPE_CURSOR    2       /* used for text cursor shape */
 | 
			
		||||
 | 
			
		||||
typedef struct cursor_entry {
 | 
			
		||||
  int shape;                    /* one of the SHAPE_ defines */
 | 
			
		||||
  int mshape;                   /* one of the MSHAPE defines */
 | 
			
		||||
  int percentage;               /* percentage of cell for bar */
 | 
			
		||||
  long blinkwait;               /* blinking, wait time before blinking starts */
 | 
			
		||||
  long blinkon;                 /* blinking, on time */
 | 
			
		||||
  long blinkoff;                /* blinking, off time */
 | 
			
		||||
  int id;                       /* highlight group ID */
 | 
			
		||||
  int id_lm;                    /* highlight group ID for :lmap mode */
 | 
			
		||||
  char        *name;            /* mode name (fixed) */
 | 
			
		||||
  char used_for;                /* SHAPE_MOUSE and/or SHAPE_CURSOR */
 | 
			
		||||
  char *full_name;        ///< mode full name
 | 
			
		||||
  CursorShape shape;      ///< cursor shape: one of the SHAPE_ defines
 | 
			
		||||
  int mshape;             ///< mouse shape: one of the MSHAPE defines
 | 
			
		||||
  int percentage;         ///< percentage of cell for bar
 | 
			
		||||
  long blinkwait;         ///< blinking, wait time before blinking starts
 | 
			
		||||
  long blinkon;           ///< blinking, on time
 | 
			
		||||
  long blinkoff;          ///< blinking, off time
 | 
			
		||||
  int id;                 ///< highlight group ID
 | 
			
		||||
  int id_lm;              ///< highlight group ID for :lmap mode
 | 
			
		||||
  char *name;             ///< mode short name
 | 
			
		||||
  char used_for;          ///< SHAPE_MOUSE and/or SHAPE_CURSOR
 | 
			
		||||
} cursorentry_T;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -42,29 +42,29 @@
 | 
			
		||||
 | 
			
		||||
static bool did_syntax_onoff = false;
 | 
			
		||||
 | 
			
		||||
// Structure that stores information about a highlight group.
 | 
			
		||||
// The ID of a highlight group is also called group ID.  It is the index in
 | 
			
		||||
// the highlight_ga array PLUS ONE.
 | 
			
		||||
/// Structure that stores information about a highlight group.
 | 
			
		||||
/// The ID of a highlight group is also called group ID.  It is the index in
 | 
			
		||||
/// the highlight_ga array PLUS ONE.
 | 
			
		||||
struct hl_group {
 | 
			
		||||
  char_u      *sg_name;         // highlight group name
 | 
			
		||||
  char_u      *sg_name_u;       // uppercase of sg_name
 | 
			
		||||
  int sg_attr;                  // Screen attr
 | 
			
		||||
  int sg_link;                  // link to this highlight group ID
 | 
			
		||||
  int sg_set;                   // combination of SG_* flags
 | 
			
		||||
  scid_T sg_scriptID;           // script in which the group was last set
 | 
			
		||||
  char_u      *sg_name;         ///< highlight group name
 | 
			
		||||
  char_u      *sg_name_u;       ///< uppercase of sg_name
 | 
			
		||||
  int sg_attr;                  ///< Screen attr
 | 
			
		||||
  int sg_link;                  ///< link to this highlight group ID
 | 
			
		||||
  int sg_set;                   ///< combination of SG_* flags
 | 
			
		||||
  scid_T sg_scriptID;           ///< script in which the group was last set
 | 
			
		||||
  // for terminal UIs
 | 
			
		||||
  int sg_cterm;                 // "cterm=" highlighting attr
 | 
			
		||||
  int sg_cterm_fg;              // terminal fg color number + 1
 | 
			
		||||
  int sg_cterm_bg;              // terminal bg color number + 1
 | 
			
		||||
  int sg_cterm_bold;            // bold attr was set for light color
 | 
			
		||||
  int sg_cterm;                 ///< "cterm=" highlighting attr
 | 
			
		||||
  int sg_cterm_fg;              ///< terminal fg color number + 1
 | 
			
		||||
  int sg_cterm_bg;              ///< terminal bg color number + 1
 | 
			
		||||
  int sg_cterm_bold;            ///< bold attr was set for light color
 | 
			
		||||
  // for RGB UIs
 | 
			
		||||
  int sg_gui;                   // "gui=" highlighting attributes
 | 
			
		||||
  RgbValue sg_rgb_fg;           // RGB foreground color
 | 
			
		||||
  RgbValue sg_rgb_bg;           // RGB background color
 | 
			
		||||
  RgbValue sg_rgb_sp;           // RGB special color
 | 
			
		||||
  uint8_t *sg_rgb_fg_name;      // RGB foreground color name
 | 
			
		||||
  uint8_t *sg_rgb_bg_name;      // RGB background color name
 | 
			
		||||
  uint8_t *sg_rgb_sp_name;      // RGB special color name
 | 
			
		||||
  int sg_gui;                   ///< "gui=" highlighting attributes
 | 
			
		||||
  RgbValue sg_rgb_fg;           ///< RGB foreground color
 | 
			
		||||
  RgbValue sg_rgb_bg;           ///< RGB background color
 | 
			
		||||
  RgbValue sg_rgb_sp;           ///< RGB special color
 | 
			
		||||
  uint8_t *sg_rgb_fg_name;      ///< RGB foreground color name
 | 
			
		||||
  uint8_t *sg_rgb_bg_name;      ///< RGB background color name
 | 
			
		||||
  uint8_t *sg_rgb_sp_name;      ///< RGB special color name
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define SG_CTERM        2       // cterm has been set
 | 
			
		||||
@@ -7165,12 +7165,13 @@ int syn_namen2id(char_u *linep, int len)
 | 
			
		||||
  return id;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Find highlight group name in the table and return it's ID.
 | 
			
		||||
 * The argument is a pointer to the name and the length of the name.
 | 
			
		||||
 * If it doesn't exist yet, a new entry is created.
 | 
			
		||||
 * Return 0 for failure.
 | 
			
		||||
 */
 | 
			
		||||
/// Find highlight group name in the table and return it's ID.
 | 
			
		||||
/// If it doesn't exist yet, a new entry is created.
 | 
			
		||||
///
 | 
			
		||||
/// @param pp Highlight group name
 | 
			
		||||
/// @param len length of \p pp
 | 
			
		||||
///
 | 
			
		||||
/// @return 0 for failure else the id of the group
 | 
			
		||||
int syn_check_group(char_u *pp, int len)
 | 
			
		||||
{
 | 
			
		||||
  char_u  *name = vim_strnsave(pp, len);
 | 
			
		||||
 
 | 
			
		||||
@@ -31,6 +31,8 @@
 | 
			
		||||
#include "nvim/ugrid.h"
 | 
			
		||||
#include "nvim/tui/input.h"
 | 
			
		||||
#include "nvim/tui/tui.h"
 | 
			
		||||
#include "nvim/cursor_shape.h"
 | 
			
		||||
#include "nvim/syntax.h"
 | 
			
		||||
 | 
			
		||||
// Space reserved in the output buffer to restore the cursor to normal when
 | 
			
		||||
// flushing. No existing terminal will require 32 bytes to do that.
 | 
			
		||||
@@ -69,12 +71,12 @@ typedef struct {
 | 
			
		||||
  bool can_use_terminal_scroll;
 | 
			
		||||
  bool mouse_enabled;
 | 
			
		||||
  bool busy;
 | 
			
		||||
  cursorentry_T cursor_shapes[SHAPE_IDX_COUNT];
 | 
			
		||||
  HlAttrs print_attrs;
 | 
			
		||||
  int showing_mode;
 | 
			
		||||
  struct {
 | 
			
		||||
    int enable_mouse, disable_mouse;
 | 
			
		||||
    int enable_bracketed_paste, disable_bracketed_paste;
 | 
			
		||||
    int set_cursor_shape_bar, set_cursor_shape_ul, set_cursor_shape_block;
 | 
			
		||||
    int set_rgb_foreground, set_rgb_background;
 | 
			
		||||
    int enable_focus_reporting, disable_focus_reporting;
 | 
			
		||||
  } unibi_ext;
 | 
			
		||||
@@ -97,6 +99,7 @@ UI *tui_start(void)
 | 
			
		||||
  ui->clear = tui_clear;
 | 
			
		||||
  ui->eol_clear = tui_eol_clear;
 | 
			
		||||
  ui->cursor_goto = tui_cursor_goto;
 | 
			
		||||
  ui->cursor_style_set = tui_cursor_style_set;
 | 
			
		||||
  ui->update_menu = tui_update_menu;
 | 
			
		||||
  ui->busy_start = tui_busy_start;
 | 
			
		||||
  ui->busy_stop = tui_busy_stop;
 | 
			
		||||
@@ -131,9 +134,6 @@ static void terminfo_start(UI *ui)
 | 
			
		||||
  data->unibi_ext.disable_mouse = -1;
 | 
			
		||||
  data->unibi_ext.enable_bracketed_paste = -1;
 | 
			
		||||
  data->unibi_ext.disable_bracketed_paste = -1;
 | 
			
		||||
  data->unibi_ext.set_cursor_shape_bar = -1;
 | 
			
		||||
  data->unibi_ext.set_cursor_shape_ul = -1;
 | 
			
		||||
  data->unibi_ext.set_cursor_shape_block = -1;
 | 
			
		||||
  data->unibi_ext.enable_focus_reporting = -1;
 | 
			
		||||
  data->unibi_ext.disable_focus_reporting = -1;
 | 
			
		||||
  data->out_fd = 1;
 | 
			
		||||
@@ -147,7 +147,6 @@ static void terminfo_start(UI *ui)
 | 
			
		||||
  }
 | 
			
		||||
  fix_terminfo(data);
 | 
			
		||||
  // Initialize the cursor shape.
 | 
			
		||||
  unibi_out(ui, data->unibi_ext.set_cursor_shape_block);
 | 
			
		||||
  // Set 't_Co' from the result of unibilium & fix_terminfo.
 | 
			
		||||
  t_colors = unibi_get_num(data->ut, unibi_max_colors);
 | 
			
		||||
  // Enter alternate screen and clear
 | 
			
		||||
@@ -434,6 +433,64 @@ static void tui_cursor_goto(UI *ui, int row, int col)
 | 
			
		||||
  unibi_goto(ui, row, col);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CursorShape tui_cursor_decode_shape(const char *shape_str)
 | 
			
		||||
{
 | 
			
		||||
  CursorShape shape = 0;
 | 
			
		||||
  if (strcmp(shape_str, "block") == 0) {
 | 
			
		||||
    shape = SHAPE_BLOCK;
 | 
			
		||||
  } else if (strcmp(shape_str, "vertical") == 0) {
 | 
			
		||||
    shape = SHAPE_VER;
 | 
			
		||||
  } else if (strcmp(shape_str, "horizontal") == 0) {
 | 
			
		||||
    shape = SHAPE_HOR;
 | 
			
		||||
  } else {
 | 
			
		||||
    EMSG2(_(e_invarg2), shape_str);
 | 
			
		||||
  }
 | 
			
		||||
  return shape;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static cursorentry_T decode_cursor_entry(Dictionary args)
 | 
			
		||||
{
 | 
			
		||||
  cursorentry_T r;
 | 
			
		||||
 | 
			
		||||
  for (size_t i = 0; i < args.size; i++) {
 | 
			
		||||
    char *keyStr = args.items[i].key.data;
 | 
			
		||||
    Object value = args.items[i].value;
 | 
			
		||||
 | 
			
		||||
    if (strcmp(keyStr, "cursor_shape") == 0) {
 | 
			
		||||
      r.shape = tui_cursor_decode_shape(args.items[i].value.data.string.data);
 | 
			
		||||
    } else if (strcmp(keyStr, "blinkon") == 0) {
 | 
			
		||||
      r.blinkon = (int)value.data.integer;
 | 
			
		||||
    } else if (strcmp(keyStr, "blinkoff") == 0) {
 | 
			
		||||
      r.blinkoff = (int)value.data.integer;
 | 
			
		||||
    } else if (strcmp(keyStr, "hl_id") == 0) {
 | 
			
		||||
      r.id = (int)value.data.integer;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void tui_cursor_style_set(UI *ui, Dictionary args)
 | 
			
		||||
{
 | 
			
		||||
  TUIData *data = ui->data;
 | 
			
		||||
 | 
			
		||||
  for (size_t i = 0; i < args.size; i++) {
 | 
			
		||||
    char *mode_name = args.items[i].key.data;
 | 
			
		||||
    const int mode_id = cursor_mode_str2int(mode_name);
 | 
			
		||||
 | 
			
		||||
    if (mode_id < 0) {
 | 
			
		||||
      WLOG("Unknown mode '%s'", mode_name);
 | 
			
		||||
      continue;
 | 
			
		||||
    }
 | 
			
		||||
    cursorentry_T r = decode_cursor_entry(args.items[i].value.data.dictionary);
 | 
			
		||||
    r.full_name = mode_name;
 | 
			
		||||
    data->cursor_shapes[mode_id] = r;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // force redrawal
 | 
			
		||||
  MouseMode cursor_mode = tui_mode2cursor(data->showing_mode);
 | 
			
		||||
  tui_set_cursor(ui, cursor_mode);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void tui_update_menu(UI *ui)
 | 
			
		||||
{
 | 
			
		||||
    // Do nothing; menus are for GUI only
 | 
			
		||||
@@ -467,33 +524,90 @@ static void tui_mouse_off(UI *ui)
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// @param mode one of SHAPE_XXX
 | 
			
		||||
static void tui_set_cursor(UI *ui, MouseMode mode)
 | 
			
		||||
{
 | 
			
		||||
  TUIData *data = ui->data;
 | 
			
		||||
  cursorentry_T c = data->cursor_shapes[mode];
 | 
			
		||||
  int shape = c.shape;
 | 
			
		||||
  bool inside_tmux = os_getenv("TMUX") != NULL;
 | 
			
		||||
  unibi_var_t vars[26 + 26] = { { 0 } };
 | 
			
		||||
 | 
			
		||||
# define TMUX_WRAP(seq) (inside_tmux ? "\x1bPtmux;\x1b" seq "\x1b\\" : seq)
 | 
			
		||||
  // Support changing cursor shape on some popular terminals.
 | 
			
		||||
  const char *term_prog = os_getenv("TERM_PROGRAM");
 | 
			
		||||
  const char *vte_version = os_getenv("VTE_VERSION");
 | 
			
		||||
 | 
			
		||||
  if ((term_prog && !strcmp(term_prog, "Konsole"))
 | 
			
		||||
      || os_getenv("KONSOLE_DBUS_SESSION") != NULL) {
 | 
			
		||||
    // Konsole uses a proprietary escape code to set the cursor shape
 | 
			
		||||
    // and does not support DECSCUSR.
 | 
			
		||||
    switch (shape) {
 | 
			
		||||
      case SHAPE_BLOCK: shape = 0; break;
 | 
			
		||||
      case SHAPE_VER:   shape = 1; break;
 | 
			
		||||
      case SHAPE_HOR:   shape = 3; break;
 | 
			
		||||
      default: WLOG("Unknown shape value %d", shape); break;
 | 
			
		||||
    }
 | 
			
		||||
    printf(TMUX_WRAP("\x1b]50;CursorShape=%d;BlinkingCursorEnabled=%d\x07"),
 | 
			
		||||
           shape, (c.blinkon !=0));
 | 
			
		||||
  } else if (!vte_version || atoi(vte_version) >= 3900) {
 | 
			
		||||
    // Assume that the terminal supports DECSCUSR unless it is an
 | 
			
		||||
    // old VTE based terminal.  This should not get wrapped for tmux,
 | 
			
		||||
    // which will handle it via its Ss/Se terminfo extension - usually
 | 
			
		||||
    // according to its terminal-overrides.
 | 
			
		||||
 | 
			
		||||
    switch (shape) {
 | 
			
		||||
      case SHAPE_BLOCK: shape = 1; break;
 | 
			
		||||
      case SHAPE_VER:   shape = 5; break;
 | 
			
		||||
      case SHAPE_HOR:   shape = 3; break;
 | 
			
		||||
      default: WLOG("Unknown shape value %d", shape); break;
 | 
			
		||||
    }
 | 
			
		||||
    data->params[0].i = shape + (c.blinkon ==0);
 | 
			
		||||
    unibi_format(vars, vars + 26, "\x1b[%p1%d q",
 | 
			
		||||
                 data->params, out, ui, NULL, NULL);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Returns cursor mode from edit mode
 | 
			
		||||
static MouseMode tui_mode2cursor(int mode)
 | 
			
		||||
{
 | 
			
		||||
  switch (mode) {
 | 
			
		||||
    case INSERT:  return SHAPE_IDX_I;
 | 
			
		||||
    case CMDLINE: return SHAPE_IDX_C;
 | 
			
		||||
    case REPLACE: return SHAPE_IDX_R;
 | 
			
		||||
    case NORMAL:
 | 
			
		||||
    default:      return SHAPE_IDX_N;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// @param mode editor mode
 | 
			
		||||
static void tui_mode_change(UI *ui, int mode)
 | 
			
		||||
{
 | 
			
		||||
  TUIData *data = ui->data;
 | 
			
		||||
 | 
			
		||||
  if (mode == INSERT) {
 | 
			
		||||
    if (data->showing_mode != INSERT) {
 | 
			
		||||
      unibi_out(ui, data->unibi_ext.set_cursor_shape_bar);
 | 
			
		||||
      tui_set_cursor(ui, SHAPE_IDX_I);
 | 
			
		||||
    }
 | 
			
		||||
  } else if (mode == CMDLINE) {
 | 
			
		||||
    if (data->showing_mode != CMDLINE) {
 | 
			
		||||
      unibi_out(ui, data->unibi_ext.set_cursor_shape_bar);
 | 
			
		||||
      tui_set_cursor(ui, SHAPE_IDX_C);
 | 
			
		||||
    }
 | 
			
		||||
  } else if (mode == REPLACE) {
 | 
			
		||||
    if (data->showing_mode != REPLACE) {
 | 
			
		||||
      unibi_out(ui, data->unibi_ext.set_cursor_shape_ul);
 | 
			
		||||
      tui_set_cursor(ui, SHAPE_IDX_R);
 | 
			
		||||
    }
 | 
			
		||||
  } else {
 | 
			
		||||
    assert(mode == NORMAL);
 | 
			
		||||
    if (data->showing_mode != NORMAL) {
 | 
			
		||||
      unibi_out(ui, data->unibi_ext.set_cursor_shape_block);
 | 
			
		||||
      tui_set_cursor(ui, SHAPE_IDX_N);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  data->showing_mode = mode;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void tui_set_scroll_region(UI *ui, int top, int bot, int left,
 | 
			
		||||
    int right)
 | 
			
		||||
                                  int right)
 | 
			
		||||
{
 | 
			
		||||
  TUIData *data = ui->data;
 | 
			
		||||
  ugrid_set_scroll_region(&data->grid, top, bot, left, right);
 | 
			
		||||
@@ -831,8 +945,6 @@ static void fix_terminfo(TUIData *data)
 | 
			
		||||
    goto end;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  bool inside_tmux = os_getenv("TMUX") != NULL;
 | 
			
		||||
 | 
			
		||||
#define STARTS_WITH(str, prefix) (!memcmp(str, prefix, sizeof(prefix) - 1))
 | 
			
		||||
 | 
			
		||||
  if (STARTS_WITH(term, "rxvt")) {
 | 
			
		||||
@@ -890,40 +1002,6 @@ static void fix_terminfo(TUIData *data)
 | 
			
		||||
    unibi_set_str(ut, unibi_set_a_background, XTERM_SETAB);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const char * env_cusr_shape = os_getenv("NVIM_TUI_ENABLE_CURSOR_SHAPE");
 | 
			
		||||
  if (env_cusr_shape && strncmp(env_cusr_shape, "0", 1) == 0) {
 | 
			
		||||
    goto end;
 | 
			
		||||
  }
 | 
			
		||||
  bool cusr_blink = env_cusr_shape && strncmp(env_cusr_shape, "2", 1) == 0;
 | 
			
		||||
 | 
			
		||||
#define TMUX_WRAP(seq) (inside_tmux ? "\x1bPtmux;\x1b" seq "\x1b\\" : seq)
 | 
			
		||||
  // Support changing cursor shape on some popular terminals.
 | 
			
		||||
  const char *term_prog = os_getenv("TERM_PROGRAM");
 | 
			
		||||
  const char *vte_version = os_getenv("VTE_VERSION");
 | 
			
		||||
 | 
			
		||||
  if ((term_prog && !strcmp(term_prog, "Konsole"))
 | 
			
		||||
      || os_getenv("KONSOLE_DBUS_SESSION") != NULL) {
 | 
			
		||||
    // Konsole uses a proprietary escape code to set the cursor shape
 | 
			
		||||
    // and does not support DECSCUSR.
 | 
			
		||||
    data->unibi_ext.set_cursor_shape_bar = (int)unibi_add_ext_str(ut, NULL,
 | 
			
		||||
        TMUX_WRAP("\x1b]50;CursorShape=1\x07"));
 | 
			
		||||
    data->unibi_ext.set_cursor_shape_ul = (int)unibi_add_ext_str(ut, NULL,
 | 
			
		||||
        TMUX_WRAP("\x1b]50;CursorShape=2\x07"));
 | 
			
		||||
    data->unibi_ext.set_cursor_shape_block = (int)unibi_add_ext_str(ut, NULL,
 | 
			
		||||
        TMUX_WRAP("\x1b]50;CursorShape=0\x07"));
 | 
			
		||||
  } else if (!vte_version || atoi(vte_version) >= 3900) {
 | 
			
		||||
    // Assume that the terminal supports DECSCUSR unless it is an
 | 
			
		||||
    // old VTE based terminal.  This should not get wrapped for tmux,
 | 
			
		||||
    // which will handle it via its Ss/Se terminfo extension - usually
 | 
			
		||||
    // according to its terminal-overrides.
 | 
			
		||||
    data->unibi_ext.set_cursor_shape_bar =
 | 
			
		||||
      (int)unibi_add_ext_str(ut, NULL, cusr_blink ? "\x1b[5 q" : "\x1b[6 q");
 | 
			
		||||
    data->unibi_ext.set_cursor_shape_ul =
 | 
			
		||||
      (int)unibi_add_ext_str(ut, NULL, cusr_blink ? "\x1b[3 q" : "\x1b[4 q");
 | 
			
		||||
    data->unibi_ext.set_cursor_shape_block =
 | 
			
		||||
      (int)unibi_add_ext_str(ut, NULL, cusr_blink ? "\x1b[1 q" : "\x1b[2 q");
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
end:
 | 
			
		||||
  // Fill some empty slots with common terminal strings
 | 
			
		||||
  data->unibi_ext.enable_mouse = (int)unibi_add_ext_str(ut, NULL,
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,8 @@
 | 
			
		||||
#ifndef NVIM_TUI_TUI_H
 | 
			
		||||
#define NVIM_TUI_TUI_H
 | 
			
		||||
 | 
			
		||||
#include "nvim/cursor_shape.h"
 | 
			
		||||
 | 
			
		||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
 | 
			
		||||
# include "tui/tui.h.generated.h"
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -29,6 +29,7 @@
 | 
			
		||||
#include "nvim/screen.h"
 | 
			
		||||
#include "nvim/syntax.h"
 | 
			
		||||
#include "nvim/window.h"
 | 
			
		||||
#include "nvim/cursor_shape.h"
 | 
			
		||||
#ifdef FEAT_TUI
 | 
			
		||||
# include "nvim/tui/tui.h"
 | 
			
		||||
#else
 | 
			
		||||
@@ -179,6 +180,7 @@ void ui_refresh(void)
 | 
			
		||||
  row = col = 0;
 | 
			
		||||
  screen_resize(width, height);
 | 
			
		||||
  pum_set_external(pum_external);
 | 
			
		||||
  ui_cursor_style_set();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void ui_refresh_event(void **argv)
 | 
			
		||||
@@ -376,6 +378,13 @@ void ui_cursor_goto(int new_row, int new_col)
 | 
			
		||||
  pending_cursor_update = true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ui_cursor_style_set(void)
 | 
			
		||||
{
 | 
			
		||||
  Dictionary style = cursor_shape_dict();
 | 
			
		||||
  UI_CALL(cursor_style_set, style);
 | 
			
		||||
  api_free_dictionary(style);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ui_update_menu(void)
 | 
			
		||||
{
 | 
			
		||||
    UI_CALL(update_menu);
 | 
			
		||||
 
 | 
			
		||||
@@ -22,6 +22,7 @@ struct ui_t {
 | 
			
		||||
  void (*clear)(UI *ui);
 | 
			
		||||
  void (*eol_clear)(UI *ui);
 | 
			
		||||
  void (*cursor_goto)(UI *ui, int row, int col);
 | 
			
		||||
  void (*cursor_style_set)(UI *ui, Dictionary cursor_shapes);
 | 
			
		||||
  void (*update_menu)(UI *ui);
 | 
			
		||||
  void (*busy_start)(UI *ui);
 | 
			
		||||
  void (*busy_stop)(UI *ui);
 | 
			
		||||
 
 | 
			
		||||
@@ -13,6 +13,7 @@
 | 
			
		||||
#include "nvim/memory.h"
 | 
			
		||||
#include "nvim/ui_bridge.h"
 | 
			
		||||
#include "nvim/ugrid.h"
 | 
			
		||||
#include "nvim/api/private/helpers.h"
 | 
			
		||||
 | 
			
		||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
 | 
			
		||||
# include "ui_bridge.c.generated.h"
 | 
			
		||||
@@ -59,6 +60,7 @@ UI *ui_bridge_attach(UI *ui, ui_main_fn ui_main, event_scheduler scheduler)
 | 
			
		||||
  rv->bridge.clear = ui_bridge_clear;
 | 
			
		||||
  rv->bridge.eol_clear = ui_bridge_eol_clear;
 | 
			
		||||
  rv->bridge.cursor_goto = ui_bridge_cursor_goto;
 | 
			
		||||
  rv->bridge.cursor_style_set = ui_bridge_cursor_styleset;
 | 
			
		||||
  rv->bridge.update_menu = ui_bridge_update_menu;
 | 
			
		||||
  rv->bridge.busy_start = ui_bridge_busy_start;
 | 
			
		||||
  rv->bridge.busy_stop = ui_bridge_busy_stop;
 | 
			
		||||
@@ -178,6 +180,23 @@ static void ui_bridge_cursor_goto_event(void **argv)
 | 
			
		||||
  ui->cursor_goto(ui, PTR2INT(argv[1]), PTR2INT(argv[2]));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void ui_bridge_cursor_styleset(UI *b, Dictionary style)
 | 
			
		||||
{
 | 
			
		||||
  Object copy = copy_object(DICTIONARY_OBJ(style));
 | 
			
		||||
  Object *pobj = xmalloc(sizeof(copy));
 | 
			
		||||
  *pobj = copy;
 | 
			
		||||
  UI_CALL(b, cursor_styleset, 2, b, pobj);
 | 
			
		||||
}
 | 
			
		||||
static void ui_bridge_cursor_styleset_event(void **argv)
 | 
			
		||||
{
 | 
			
		||||
  UI *ui = UI(argv[0]);
 | 
			
		||||
  Object *styles = (Object *)argv[1];
 | 
			
		||||
 | 
			
		||||
  ui->cursor_style_set(ui, styles->data.dictionary);
 | 
			
		||||
  api_free_object(*styles);
 | 
			
		||||
  xfree(styles);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void ui_bridge_update_menu(UI *b)
 | 
			
		||||
{
 | 
			
		||||
  UI_CALL(b, update_menu, 1, b);
 | 
			
		||||
 
 | 
			
		||||
@@ -313,6 +313,8 @@ function Screen:_redraw(updates)
 | 
			
		||||
      if handler ~= nil then
 | 
			
		||||
        handler(self, unpack(update[i]))
 | 
			
		||||
      else
 | 
			
		||||
        assert(self._on_event, "Either add an Screen:_handle_XXX method "..
 | 
			
		||||
               " or call Screen:set_on_event_handler")
 | 
			
		||||
        self._on_event(method, update[i])
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
@@ -343,6 +345,10 @@ function Screen:_handle_resize(width, height)
 | 
			
		||||
  }
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function Screen:_handle_cursor_style_set(styles)
 | 
			
		||||
  self._cursor_styles = styles
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function Screen:_handle_clear()
 | 
			
		||||
  self:_clear_block(self._scroll_region.top, self._scroll_region.bot,
 | 
			
		||||
                    self._scroll_region.left, self._scroll_region.right)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user