Blender  V3.3
numinput.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
7 #include "MEM_guardedalloc.h"
8 
9 #include "BLI_math.h"
10 #include "BLI_string.h"
11 #include "BLI_string_cursor_utf8.h"
12 #include "BLI_string_utf8.h"
13 #include "BLI_utildefines.h"
14 
15 #include "BLT_translation.h"
16 
17 #include "BKE_context.h"
18 #include "BKE_report.h"
19 #include "BKE_scene.h"
20 #include "BKE_unit.h"
21 
22 #include "DNA_scene_types.h"
23 
24 #include "WM_api.h"
25 #include "WM_types.h"
26 
27 #ifdef WITH_PYTHON
28 # include "BPY_extern_run.h"
29 #endif
30 
31 #include "ED_numinput.h"
32 #include "UI_interface.h"
33 
34 /* Numeric input which isn't allowing full numeric editing. */
35 #define USE_FAKE_EDIT
36 
41 enum {
43  NUM_EDIT_FULL = (1 << 9),
44 #ifdef USE_FAKE_EDIT
46  NUM_FAKE_EDITED = (1 << 10),
47 #endif
48 };
49 
50 /* NumInput.val_flag[] */
51 enum {
52  /* (1 << 8) and below are reserved for public flags! */
54  NUM_EDITED = (1 << 9),
56  NUM_INVALID = (1 << 10),
57 #ifdef USE_FAKE_EDIT
59  NUM_NEGATE = (1 << 11),
61  NUM_INVERSE = (1 << 12),
62 #endif
63 };
64 
65 /* ************************** Functions *************************** */
66 
67 /* ************************** NUMINPUT **************************** */
68 
70 {
71  n->idx_max = 0;
74  n->unit_use_radians = false;
75 
76  n->flag = 0;
78  zero_v3(n->val);
81 
82  n->idx = 0;
83  n->str[0] = '\0';
84  n->str_cur = 0;
85 }
86 
87 void outputNumInput(NumInput *n, char *str, UnitSettings *unit_settings)
88 {
89  short j;
90  const int ln = NUM_STR_REP_LEN;
91  int prec = 2; /* draw-only, and avoids too much issues with radian->degrees conversion. */
92 
93  for (j = 0; j <= n->idx_max; j++) {
94  /* if AFFECTALL and no number typed and cursor not on number, use first number */
95  const short i = (n->flag & NUM_AFFECT_ALL && n->idx != j && !(n->val_flag[j] & NUM_EDITED)) ?
96  0 :
97  j;
98 
99  /* Use scale_length if needed! */
100  const float fac = (float)BKE_scene_unit_scale(unit_settings, n->unit_type[j], 1.0);
101 
102  if (n->val_flag[i] & NUM_EDITED) {
103  /* Get the best precision, allows us to draw '10.0001' as '10' instead! */
104  prec = UI_calc_float_precision(prec, (double)n->val[i]);
105  if (i == n->idx) {
106  const char *heading_exp = "", *trailing_exp = "";
107  char before_cursor[NUM_STR_REP_LEN];
108  char val[16];
109 
110 #ifdef USE_FAKE_EDIT
111  if (n->val_flag[i] & NUM_NEGATE) {
112  heading_exp = (n->val_flag[i] & NUM_INVERSE) ? "-1/(" : "-(";
113  trailing_exp = ")";
114  }
115  else if (n->val_flag[i] & NUM_INVERSE) {
116  heading_exp = "1/(";
117  trailing_exp = ")";
118  }
119 #endif
120 
121  if (n->val_flag[i] & NUM_INVALID) {
122  BLI_strncpy(val, "Invalid", sizeof(val));
123  }
124  else {
126  sizeof(val),
127  (double)(n->val[i] * fac),
128  prec,
129  n->unit_sys,
130  n->unit_type[i],
131  true,
132  false);
133  }
134 
135  /* +1 because of trailing '\0' */
136  BLI_strncpy(before_cursor, n->str, n->str_cur + 1);
137  BLI_snprintf(&str[j * ln],
138  ln,
139  "[%s%s|%s%s] = %s",
140  heading_exp,
141  before_cursor,
142  &n->str[n->str_cur],
143  trailing_exp,
144  val);
145  }
146  else {
147  const char *cur = (i == n->idx) ? "|" : "";
148  if (n->unit_use_radians && n->unit_type[i] == B_UNIT_ROTATION) {
149  /* Radian exception... */
150  BLI_snprintf(&str[j * ln], ln, "%s%.6gr%s", cur, n->val[i], cur);
151  }
152  else {
153  char tstr[NUM_STR_REP_LEN];
155  tstr, ln, (double)n->val[i], prec, n->unit_sys, n->unit_type[i], true, false);
156  BLI_snprintf(&str[j * ln], ln, "%s%s%s", cur, tstr, cur);
157  }
158  }
159  }
160  else {
161  const char *cur = (i == n->idx) ? "|" : "";
162  BLI_snprintf(&str[j * ln], ln, "%sNONE%s", cur, cur);
163  }
164  /* We might have cut some multi-bytes utf8 chars
165  * (e.g. trailing '°' of degrees values can become only 'A')... */
166  BLI_str_utf8_invalid_strip(&str[j * ln], strlen(&str[j * ln]));
167  }
168 }
169 
170 bool hasNumInput(const NumInput *n)
171 {
172  short i;
173 
174 #ifdef USE_FAKE_EDIT
175  if (n->flag & NUM_FAKE_EDITED) {
176  return true;
177  }
178 #endif
179 
180  for (i = 0; i <= n->idx_max; i++) {
181  if (n->val_flag[i] & NUM_EDITED) {
182  return true;
183  }
184  }
185 
186  return false;
187 }
188 
189 bool applyNumInput(NumInput *n, float *vec)
190 {
191  short i, j;
192  float val;
193 
194  if (hasNumInput(n)) {
195  for (j = 0; j <= n->idx_max; j++) {
196 #ifdef USE_FAKE_EDIT
197  if (n->flag & NUM_FAKE_EDITED) {
198  val = n->val[j];
199  }
200  else
201 #endif
202  {
203  /* if AFFECTALL and no number typed and cursor not on number, use first number */
204  i = (n->flag & NUM_AFFECT_ALL && n->idx != j && !(n->val_flag[j] & NUM_EDITED)) ? 0 : j;
205  val = (!(n->val_flag[i] & NUM_EDITED) && n->val_flag[i] & NUM_NULL_ONE) ? 1.0f : n->val[i];
206 
207  if (n->val_flag[i] & NUM_NO_NEGATIVE && val < 0.0f) {
208  val = 0.0f;
209  }
210  if (n->val_flag[i] & NUM_NO_FRACTION && val != floorf(val)) {
211  val = floorf(val + 0.5f);
212  if (n->val_flag[i] & NUM_NO_ZERO && val == 0.0f) {
213  val = 1.0f;
214  }
215  }
216  else if (n->val_flag[i] & NUM_NO_ZERO && val == 0.0f) {
217  val = 0.0001f;
218  }
219  }
220  vec[j] = val;
221  }
222 #ifdef USE_FAKE_EDIT
223  n->flag &= ~NUM_FAKE_EDITED;
224 #endif
225  return true;
226  }
227 
228  /* Else, we set the 'org' values for numinput! */
229  for (j = 0; j <= n->idx_max; j++) {
230  n->val[j] = n->val_org[j] = vec[j];
231  }
232  return false;
233 }
234 
235 static void value_to_editstr(NumInput *n, int idx)
236 {
237  const int prec = 6; /* editing, higher precision needed. */
240  (double)n->val[idx],
241  prec,
242  n->unit_sys,
243  n->unit_type[idx],
244  true,
245  false);
246 }
247 
248 static bool editstr_insert_at_cursor(NumInput *n, const char *buf, const int buf_len)
249 {
250  int cur = n->str_cur;
251  int len = strlen(&n->str[cur]) + 1; /* +1 for the trailing '\0'. */
252  int n_cur = cur + buf_len;
253 
254  if (n_cur + len >= NUM_STR_REP_LEN) {
255  return false;
256  }
257 
258  memmove(&n->str[n_cur], &n->str[cur], len);
259  memcpy(&n->str[cur], buf, sizeof(char) * buf_len);
260 
261  n->str_cur = n_cur;
262  return true;
263 }
264 
266  const char *str,
267  const UnitSettings *unit,
268  int type,
269  double *r_value,
270  const bool use_single_line_error,
271  char **r_error)
272 {
273 #ifdef WITH_PYTHON
274  struct BPy_RunErrInfo err_info = {
276  .r_string = r_error,
277  };
278  double unit_scale = BKE_scene_unit_scale(unit, type, 1.0);
280  char str_unit_convert[256];
281  BLI_strncpy(str_unit_convert, str, sizeof(str_unit_convert));
283  str_unit_convert, sizeof(str_unit_convert), str, unit_scale, unit->system, type);
284 
285  return BPY_run_string_as_number(C, NULL, str_unit_convert, &err_info, r_value);
286  }
287 
288  int success = BPY_run_string_as_number(C, NULL, str, &err_info, r_value);
289  *r_value = BKE_unit_apply_preferred_unit(unit, type, *r_value);
290  *r_value /= unit_scale;
291  return success;
292 
293 #else
294  UNUSED_VARS(C, unit, type, use_single_line_error, r_error);
295  *r_value = atof(str);
296  return true;
297 #endif
298 }
299 
300 static bool editstr_is_simple_numinput(const char ascii)
301 {
302  if (ascii >= '0' && ascii <= '9') {
303  return true;
304  }
305  if (ascii == '.') {
306  return true;
307  }
308  return false;
309 }
310 
311 bool handleNumInput(bContext *C, NumInput *n, const wmEvent *event)
312 {
313  const char *utf8_buf = NULL;
314  const char event_ascii = WM_event_utf8_to_ascii(event);
315  char ascii[2] = {'\0', '\0'};
316  bool updated = false;
317  short idx = n->idx, idx_max = n->idx_max;
318  short dir = STRCUR_DIR_NEXT, mode = STRCUR_JUMP_NONE;
319  int cur;
320 
321 #ifdef USE_FAKE_EDIT
322  if (U.flag & USER_FLAG_NUMINPUT_ADVANCED)
323 #endif
324  {
325  if (((event->modifier & (KM_CTRL | KM_ALT)) == 0) && (event_ascii != '\0') &&
326  strchr("01234567890@%^&*-+/{}()[]<>.|", event_ascii)) {
327  if (!(n->flag & NUM_EDIT_FULL)) {
328  n->flag |= NUM_EDITED;
329  n->flag |= NUM_EDIT_FULL;
330  n->val_flag[idx] |= NUM_EDITED;
331  }
332  }
333  }
334 
335 #ifdef USE_FAKE_EDIT
336  /* XXX Hack around keyboards without direct access to '=' nor '*'... */
337  if (ELEM(event_ascii, '=', '*')) {
338  if (!(n->flag & NUM_EDIT_FULL)) {
339  n->flag |= NUM_EDIT_FULL;
340  n->val_flag[idx] |= NUM_EDITED;
341  return true;
342  }
343  if (event->modifier & KM_CTRL) {
344  n->flag &= ~NUM_EDIT_FULL;
345  return true;
346  }
347  }
348 #endif
349 
350  switch (event->type) {
351  case EVT_MODAL_MAP:
353  n->val[idx] += (event->val == NUM_MODAL_INCREMENT_UP) ? n->val_inc[idx] : -n->val_inc[idx];
354  value_to_editstr(n, idx);
355  n->val_flag[idx] |= NUM_EDITED;
356  updated = true;
357  }
358  else {
359  /* might be a char too... */
360  utf8_buf = event->utf8_buf;
361  ascii[0] = event_ascii;
362  }
363  break;
364  case EVT_BACKSPACEKEY:
365  /* Part specific to backspace... */
366  if (!(n->val_flag[idx] & NUM_EDITED)) {
367  copy_v3_v3(n->val, n->val_org);
368  n->val_flag[0] &= ~NUM_EDITED;
369  n->val_flag[1] &= ~NUM_EDITED;
370  n->val_flag[2] &= ~NUM_EDITED;
371 #ifdef USE_FAKE_EDIT
372  n->flag |= NUM_FAKE_EDITED;
373 #else
374  n->flag |= NUM_EDIT_FULL;
375 #endif
376  updated = true;
377  break;
378  }
379  else if ((event->modifier & KM_SHIFT) || !n->str[0]) {
380  n->val[idx] = n->val_org[idx];
381  n->val_flag[idx] &= ~NUM_EDITED;
382  n->str[0] = '\0';
383  n->str_cur = 0;
384  updated = true;
385  break;
386  }
387  /* Else, common behavior with DELKEY,
388  * only difference is remove char(s) before/after the cursor. */
389  dir = STRCUR_DIR_PREV;
391  case EVT_DELKEY:
392  if ((n->val_flag[idx] & NUM_EDITED) && n->str[0]) {
393  int t_cur = cur = n->str_cur;
394  if (event->modifier & KM_CTRL) {
395  mode = STRCUR_JUMP_DELIM;
396  }
397  BLI_str_cursor_step_utf8(n->str, strlen(n->str), &t_cur, dir, mode, true);
398  if (t_cur != cur) {
399  if (t_cur < cur) {
400  SWAP(int, t_cur, cur);
401  n->str_cur = cur;
402  }
403  /* +1 for trailing '\0'. */
404  memmove(&n->str[cur], &n->str[t_cur], strlen(&n->str[t_cur]) + 1);
405  updated = true;
406  }
407  if (!n->str[0]) {
408  n->val[idx] = n->val_org[idx];
409  }
410  }
411  else {
412  return false;
413  }
414  break;
415  case EVT_LEFTARROWKEY:
416  dir = STRCUR_DIR_PREV;
418  case EVT_RIGHTARROWKEY:
419  cur = n->str_cur;
420  if (event->modifier & KM_CTRL) {
421  mode = STRCUR_JUMP_DELIM;
422  }
423  BLI_str_cursor_step_utf8(n->str, strlen(n->str), &cur, dir, mode, true);
424  if (cur != n->str_cur) {
425  n->str_cur = cur;
426  return true;
427  }
428  return false;
429  case EVT_HOMEKEY:
430  if (n->str[0]) {
431  n->str_cur = 0;
432  return true;
433  }
434  return false;
435  case EVT_ENDKEY:
436  if (n->str[0]) {
437  n->str_cur = strlen(n->str);
438  return true;
439  }
440  return false;
441  case EVT_TABKEY:
442 #ifdef USE_FAKE_EDIT
443  n->val_flag[idx] &= ~(NUM_NEGATE | NUM_INVERSE);
444 #endif
445 
446  idx = (idx + idx_max + ((event->modifier & KM_CTRL) ? 0 : 2)) % (idx_max + 1);
447  n->idx = idx;
448  if (n->val_flag[idx] & NUM_EDITED) {
449  value_to_editstr(n, idx);
450  }
451  else {
452  n->str[0] = '\0';
453  n->str_cur = 0;
454  }
455  return true;
456  case EVT_PADPERIOD:
457  case EVT_PERIODKEY:
458  /* Force number-pad "." since some OS's/countries generate a comma char, see: T37992 */
459  ascii[0] = '.';
460  utf8_buf = ascii;
461  break;
462 #if 0
463  /* Those keys are not directly accessible in all layouts,
464  * preventing to generate matching events.
465  * So we use a hack (ascii value) instead, see below.
466  */
467  case EQUALKEY:
468  case PADASTERKEY:
469  if (!(n->flag & NUM_EDIT_FULL)) {
470  n->flag |= NUM_EDIT_FULL;
471  n->val_flag[idx] |= NUM_EDITED;
472  return true;
473  }
474  else if (event->modifier & KM_CTRL) {
475  n->flag &= ~NUM_EDIT_FULL;
476  return true;
477  }
478  break;
479 #endif
480 
481 #ifdef USE_FAKE_EDIT
482  case EVT_PADMINUS:
483  case EVT_MINUSKEY:
484  if ((event->modifier & KM_CTRL) || !(n->flag & NUM_EDIT_FULL)) {
485  n->val_flag[idx] ^= NUM_NEGATE;
486  updated = true;
487  }
488  break;
489  case EVT_PADSLASHKEY:
490  case EVT_SLASHKEY:
491  if ((event->modifier & KM_CTRL) || !(n->flag & NUM_EDIT_FULL)) {
492  n->val_flag[idx] ^= NUM_INVERSE;
493  updated = true;
494  }
495  break;
496 #endif
497  case EVT_CKEY:
498  if (event->modifier & KM_CTRL) {
499  /* Copy current `str` to the copy/paste buffer. */
500  WM_clipboard_text_set(n->str, 0);
501  updated = true;
502  }
503  break;
504  case EVT_VKEY:
505  if (event->modifier & KM_CTRL) {
506  /* extract the first line from the clipboard */
507  int pbuf_len;
508  char *pbuf = WM_clipboard_text_get_firstline(false, &pbuf_len);
509 
510  if (pbuf) {
511  const bool success = editstr_insert_at_cursor(n, pbuf, pbuf_len);
512 
513  MEM_freeN(pbuf);
514  if (!success) {
515  return false;
516  }
517 
518  n->val_flag[idx] |= NUM_EDITED;
519  }
520  updated = true;
521  }
522  break;
523  default:
524  break;
525  }
526 
527  if (!updated && !utf8_buf && event->utf8_buf[0]) {
528  utf8_buf = event->utf8_buf;
529  ascii[0] = event_ascii;
530  }
531 
532  /* Up to this point, if we have a ctrl modifier, skip.
533  * This allows to still access most of modals' shortcuts even in numinput mode.
534  */
535  if (!updated && (event->modifier & KM_CTRL)) {
536  return false;
537  }
538 
539  if ((!utf8_buf || !utf8_buf[0]) && ascii[0]) {
540  /* Fallback to ascii. */
541  utf8_buf = ascii;
542  }
543 
544  if (utf8_buf && utf8_buf[0]) {
545  if (!(n->flag & NUM_EDIT_FULL)) {
546  /* In simple edit mode, we only keep a few chars as valid! */
547  /* no need to decode unicode, ascii is first char only */
548  if (!editstr_is_simple_numinput(utf8_buf[0])) {
549  return false;
550  }
551  }
552 
553  if (!editstr_insert_at_cursor(n, utf8_buf, BLI_str_utf8_size(utf8_buf))) {
554  return false;
555  }
556 
557  n->val_flag[idx] |= NUM_EDITED;
558  }
559  else if (!updated) {
560  return false;
561  }
562 
563  /* At this point, our value has changed, try to interpret it with python
564  * (if str is not empty!). */
565  if (n->str[0]) {
566  const float val_prev = n->val[idx];
567  Scene *sce = CTX_data_scene(C);
568  char *error = NULL;
569 
570  double val;
571  int success = user_string_to_number(
572  C, n->str, &sce->unit, n->unit_type[idx], &val, false, &error);
573 
574  if (error) {
576  printf("%s\n", error);
578  BKE_report(reports, RPT_ERROR, IFACE_("Numeric input evaluation"));
579  MEM_freeN(error);
580  }
581 
582  if (success) {
583  n->val[idx] = (float)val;
584  n->val_flag[idx] &= ~NUM_INVALID;
585  }
586  else {
587  n->val_flag[idx] |= NUM_INVALID;
588  }
589 
590 #ifdef USE_FAKE_EDIT
591  if (n->val_flag[idx] & NUM_NEGATE) {
592  n->val[idx] = -n->val[idx];
593  }
594  if (n->val_flag[idx] & NUM_INVERSE) {
595  val = n->val[idx];
596  /* If we invert on radians when user is in degrees,
597  * you get unexpected results... See T53463. */
598  if (!n->unit_use_radians && n->unit_type[idx] == B_UNIT_ROTATION) {
599  val = RAD2DEG(val);
600  }
601  val = 1.0 / val;
602  if (!n->unit_use_radians && n->unit_type[idx] == B_UNIT_ROTATION) {
603  val = DEG2RAD(val);
604  }
605  n->val[idx] = (float)val;
606  }
607 #endif
608 
609  if (UNLIKELY(!isfinite(n->val[idx]))) {
610  n->val[idx] = val_prev;
611  n->val_flag[idx] |= NUM_INVALID;
612  }
613  }
614 
615  /* REDRAW SINCE NUMBERS HAVE CHANGED */
616  return true;
617 }
typedef float(TangentPoint)[2]
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1090
struct ReportList * CTX_wm_reports(const bContext *C)
Definition: context.c:775
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition: report.c:83
double BKE_scene_unit_scale(const struct UnitSettings *unit, int unit_type, double value)
size_t BKE_unit_value_as_string_adaptive(char *str, int len_max, double value, int prec, int system, int type, bool split, bool pad)
Definition: unit.c:665
@ B_UNIT_ROTATION
Definition: BKE_unit.h:105
@ B_UNIT_NONE
Definition: BKE_unit.h:100
bool BKE_unit_replace_string(char *str, int len_max, const char *str_prev, double scale_pref, int system, int type)
Definition: unit.c:1091
double BKE_unit_apply_preferred_unit(const struct UnitSettings *settings, int type, double value)
Definition: unit.c:1080
bool BKE_unit_string_contains_unit(const char *str, int type)
Definition: unit.c:1063
#define ATTR_FALLTHROUGH
#define DEG2RAD(_deg)
#define RAD2DEG(_rad)
void copy_vn_short(short *array_tar, int size, short val)
Definition: math_vector.c:1232
MINLINE void copy_v3_v3(float r[3], const float a[3])
void copy_vn_fl(float *array_tar, int size, float val)
Definition: math_vector.c:1259
void copy_vn_i(int *array_tar, int size, int val)
Definition: math_vector.c:1223
MINLINE void zero_v3(float r[3])
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL()
Definition: string.c:64
size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
void BLI_str_cursor_step_utf8(const char *str, size_t maxlen, int *pos, eStrCursorJumpDirection direction, eStrCursorJumpType jump, bool use_init_step)
@ STRCUR_DIR_NEXT
@ STRCUR_DIR_PREV
@ STRCUR_JUMP_NONE
@ STRCUR_JUMP_DELIM
int BLI_str_utf8_size(const char *p) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition: string_utf8.c:452
int BLI_str_utf8_invalid_strip(char *str, size_t length) ATTR_NONNULL(1)
Definition: string_utf8.c:181
#define UNUSED_VARS(...)
#define SWAP(type, a, b)
#define UNLIKELY(x)
#define ELEM(...)
#define IFACE_(msgid)
bool BPY_run_string_as_number(struct bContext *C, const char *imports[], const char *expr, struct BPy_RunErrInfo *err_info, double *r_value) ATTR_NONNULL(1
#define USER_UNIT_NONE
@ USER_FLAG_NUMINPUT_ADVANCED
#define NUM_STR_REP_LEN
Definition: ED_numinput.h:13
@ NUM_NO_NEGATIVE
Definition: ED_numinput.h:56
@ NUM_NULL_ONE
Definition: ED_numinput.h:55
@ NUM_NO_ZERO
Definition: ED_numinput.h:57
@ NUM_NO_FRACTION
Definition: ED_numinput.h:58
#define NUM_MODAL_INCREMENT_DOWN
Definition: ED_numinput.h:96
@ NUM_AFFECT_ALL
Definition: ED_numinput.h:48
#define NUM_MAX_ELEMENTS
Definition: ED_numinput.h:14
#define NUM_MODAL_INCREMENT_UP
Definition: ED_numinput.h:95
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
Read Guarded memory(de)allocation.
#define C
Definition: RandGen.cpp:25
int UI_calc_float_precision(int prec, double value)
@ KM_CTRL
Definition: WM_types.h:239
@ KM_ALT
Definition: WM_types.h:240
@ KM_SHIFT
Definition: WM_types.h:238
unsigned int U
Definition: btGjkEpa3.h:78
int len
Definition: draw_manager.c:108
#define str(s)
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
static void error(const char *str)
Definition: meshlaplacian.c:51
#define floorf(x)
Definition: metal/compat.h:224
bool isfinite(uchar)
Definition: scene/image.cpp:31
static void value_to_editstr(NumInput *n, int idx)
Definition: numinput.c:235
void initNumInput(NumInput *n)
Definition: numinput.c:69
void outputNumInput(NumInput *n, char *str, UnitSettings *unit_settings)
Definition: numinput.c:87
bool user_string_to_number(bContext *C, const char *str, const UnitSettings *unit, int type, double *r_value, const bool use_single_line_error, char **r_error)
Definition: numinput.c:265
static bool editstr_is_simple_numinput(const char ascii)
Definition: numinput.c:300
static bool editstr_insert_at_cursor(NumInput *n, const char *buf, const int buf_len)
Definition: numinput.c:248
@ NUM_INVERSE
Definition: numinput.c:61
@ NUM_NEGATE
Definition: numinput.c:59
@ NUM_INVALID
Definition: numinput.c:56
@ NUM_EDITED
Definition: numinput.c:54
@ NUM_FAKE_EDITED
Definition: numinput.c:46
@ NUM_EDIT_FULL
Definition: numinput.c:43
#define USE_FAKE_EDIT
Definition: numinput.c:35
bool handleNumInput(bContext *C, NumInput *n, const wmEvent *event)
Definition: numinput.c:311
bool applyNumInput(NumInput *n, float *vec)
Definition: numinput.c:189
bool hasNumInput(const NumInput *n)
Definition: numinput.c:170
struct ReportList * reports
bool use_single_line_error
short idx_max
Definition: ED_numinput.h:20
float val[NUM_MAX_ELEMENTS]
Definition: ED_numinput.h:31
short val_flag[NUM_MAX_ELEMENTS]
Definition: ED_numinput.h:29
int unit_sys
Definition: ED_numinput.h:21
float val_inc[NUM_MAX_ELEMENTS]
Definition: ED_numinput.h:35
char str[NUM_STR_REP_LEN]
Definition: ED_numinput.h:40
float val_org[NUM_MAX_ELEMENTS]
Definition: ED_numinput.h:33
int unit_type[NUM_MAX_ELEMENTS]
Definition: ED_numinput.h:23
short flag
Definition: ED_numinput.h:27
bool unit_use_radians
Definition: ED_numinput.h:24
int str_cur
Definition: ED_numinput.h:43
short idx
Definition: ED_numinput.h:38
struct UnitSettings unit
short val
Definition: WM_types.h:680
char utf8_buf[6]
Definition: WM_types.h:690
uint8_t modifier
Definition: WM_types.h:693
short type
Definition: WM_types.h:678
char WM_event_utf8_to_ascii(const struct wmEvent *event)
@ EVT_PADPERIOD
@ EVT_MODAL_MAP
@ EVT_VKEY
@ EVT_PERIODKEY
@ EVT_PADSLASHKEY
@ EVT_DELKEY
@ EVT_CKEY
@ EVT_TABKEY
@ EVT_MINUSKEY
@ EVT_RIGHTARROWKEY
@ EVT_HOMEKEY
@ EVT_ENDKEY
@ EVT_PADMINUS
@ EVT_SLASHKEY
@ EVT_LEFTARROWKEY
@ EVT_BACKSPACEKEY
void WM_clipboard_text_set(const char *buf, bool selection)
Definition: wm_window.c:1780
char * WM_clipboard_text_get_firstline(bool selection, int *r_len)
Definition: wm_window.c:1775