Blender  V3.3
text_draw.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2001-2002 NaN Holding BV. All rights reserved. */
3 
8 #include "MEM_guardedalloc.h"
9 
10 #include "BLF_api.h"
11 
12 #include "BLI_blenlib.h"
13 #include "BLI_math.h"
14 
15 #include "DNA_screen_types.h"
16 #include "DNA_space_types.h"
17 #include "DNA_text_types.h"
18 
19 #include "BKE_context.h"
20 #include "BKE_screen.h"
21 #include "BKE_text.h"
22 #include "BKE_text_suggestions.h"
23 
24 #include "ED_text.h"
25 
26 #include "GPU_immediate.h"
27 #include "GPU_state.h"
28 
29 #include "UI_interface.h"
30 #include "UI_resources.h"
31 #include "UI_view2d.h"
32 
33 #include "text_format.h"
34 #include "text_intern.h"
35 
36 #include "WM_api.h"
37 #include "WM_types.h"
38 
39 /* -------------------------------------------------------------------- */
43 typedef struct TextDrawContext {
44  int font_id;
45  int cwidth_px;
49 
51 {
52  tdc->font_id = blf_mono_font;
53  tdc->cwidth_px = 0;
54  tdc->lheight_px = st->runtime.lheight_px;
55  tdc->syntax_highlight = st->showsyntax && ED_text_is_syntax_highlight_supported(st->text);
56 }
57 
58 static void text_font_begin(const TextDrawContext *tdc)
59 {
60  BLF_size(tdc->font_id, (float)tdc->lheight_px, 72);
61 }
62 
63 static void text_font_end(const TextDrawContext *UNUSED(tdc))
64 {
65 }
66 
67 static int text_font_draw(const TextDrawContext *tdc, int x, int y, const char *str)
68 {
69  BLF_position(tdc->font_id, x, y, 0);
70  const int columns = BLF_draw_mono(tdc->font_id, str, BLF_DRAW_STR_DUMMY_MAX, tdc->cwidth_px);
71 
72  return tdc->cwidth_px * columns;
73 }
74 
75 static int text_font_draw_character(const TextDrawContext *tdc, int x, int y, char c)
76 {
77  BLF_position(tdc->font_id, x, y, 0);
78  BLF_draw_mono(tdc->font_id, &c, 1, tdc->cwidth_px);
79 
80  return tdc->cwidth_px;
81 }
82 
84  const TextDrawContext *tdc, int x, int y, const char *c, const int c_len)
85 {
87  BLF_position(tdc->font_id, x, y, 0);
88  const int columns = BLF_draw_mono(tdc->font_id, c, c_len, tdc->cwidth_px);
89 
90  return tdc->cwidth_px * columns;
91 }
92 
93 #if 0
94 /* Formats every line of the current text */
95 static void txt_format_text(SpaceText *st)
96 {
97  TextLine *linep;
98 
99  if (!st->text) {
100  return;
101  }
102 
103  for (linep = st->text->lines.first; linep; linep = linep->next) {
104  txt_format_line(st, linep, 0);
105  }
106 }
107 #endif
108 
109 /* Sets the current drawing color based on the format character specified */
110 static void format_draw_color(const TextDrawContext *tdc, char formatchar)
111 {
112  switch (formatchar) {
113  case FMT_TYPE_WHITESPACE:
114  break;
115  case FMT_TYPE_SYMBOL:
117  break;
118  case FMT_TYPE_COMMENT:
120  break;
121  case FMT_TYPE_NUMERAL:
123  break;
124  case FMT_TYPE_STRING:
126  break;
127  case FMT_TYPE_DIRECTIVE:
129  break;
130  case FMT_TYPE_SPECIAL:
132  break;
133  case FMT_TYPE_RESERVED:
135  break;
136  case FMT_TYPE_KEYWORD:
138  break;
139  case FMT_TYPE_DEFAULT:
140  default:
142  break;
143  }
144 }
145 
148 /* -------------------------------------------------------------------- */
181 int wrap_width(const SpaceText *st, ARegion *region)
182 {
183  int winx = region->winx - TXT_SCROLL_WIDTH;
184  int x, max;
185 
186  x = TXT_BODY_LEFT(st);
187  max = st->runtime.cwidth_px ? (winx - x) / st->runtime.cwidth_px : 0;
188  return max > 8 ? max : 8;
189 }
190 
191 void wrap_offset(
192  const SpaceText *st, ARegion *region, TextLine *linein, int cursin, int *offl, int *offc)
193 {
194  Text *text;
195  TextLine *linep;
196  int i, j, start, end, max, chop;
197  char ch;
198 
199  *offl = *offc = 0;
200 
201  if (!st->text) {
202  return;
203  }
204  if (!st->wordwrap) {
205  return;
206  }
207 
208  text = st->text;
209 
210  /* Move pointer to first visible line (top) */
211  linep = text->lines.first;
212  i = st->top;
213  while (i > 0 && linep) {
214  int lines = text_get_visible_lines(st, region, linep->line);
215 
216  /* Line before top */
217  if (linep == linein) {
218  if (lines <= i) {
219  /* no visible part of line */
220  return;
221  }
222  }
223 
224  if (i - lines < 0) {
225  break;
226  }
227 
228  linep = linep->next;
229  (*offl) += lines - 1;
230  i -= lines;
231  }
232 
233  max = wrap_width(st, region);
234  cursin = BLI_str_utf8_offset_to_column(linein->line, cursin);
235 
236  while (linep) {
237  start = 0;
238  end = max;
239  chop = 1;
240  *offc = 0;
241  for (i = 0, j = 0; linep->line[j]; j += BLI_str_utf8_size_safe(linep->line + j)) {
242  int chars;
243  int columns = BLI_str_utf8_char_width_safe(linep->line + j); /* = 1 for tab */
244 
245  /* Mimic replacement of tabs */
246  ch = linep->line[j];
247  if (ch == '\t') {
248  chars = st->tabnumber - i % st->tabnumber;
249  if (linep == linein && i < cursin) {
250  cursin += chars - 1;
251  }
252  ch = ' ';
253  }
254  else {
255  chars = 1;
256  }
257 
258  while (chars--) {
259  if (i + columns - start > max) {
260  end = MIN2(end, i);
261 
262  if (chop && linep == linein && i >= cursin) {
263  if (i == cursin) {
264  (*offl)++;
265  *offc -= end - start;
266  }
267 
268  return;
269  }
270 
271  (*offl)++;
272  *offc -= end - start;
273 
274  start = end;
275  end += max;
276  chop = 1;
277  }
278  else if (ELEM(ch, ' ', '-')) {
279  end = i + 1;
280  chop = 0;
281  if (linep == linein && i >= cursin) {
282  return;
283  }
284  }
285  i += columns;
286  }
287  }
288  if (linep == linein) {
289  break;
290  }
291  linep = linep->next;
292  }
293 }
294 
296  const SpaceText *st, ARegion *region, TextLine *linein, int cursin, int *offl, int *offc)
297 {
298  int i, j, start, end, chars, max, chop;
299  char ch;
300 
301  *offl = *offc = 0;
302 
303  if (!st->text) {
304  return;
305  }
306  if (!st->wordwrap) {
307  return;
308  }
309 
310  max = wrap_width(st, region);
311 
312  start = 0;
313  end = max;
314  chop = 1;
315  *offc = 0;
316  cursin = BLI_str_utf8_offset_to_column(linein->line, cursin);
317 
318  for (i = 0, j = 0; linein->line[j]; j += BLI_str_utf8_size_safe(linein->line + j)) {
319  int columns = BLI_str_utf8_char_width_safe(linein->line + j); /* = 1 for tab */
320 
321  /* Mimic replacement of tabs */
322  ch = linein->line[j];
323  if (ch == '\t') {
324  chars = st->tabnumber - i % st->tabnumber;
325  if (i < cursin) {
326  cursin += chars - 1;
327  }
328  ch = ' ';
329  }
330  else {
331  chars = 1;
332  }
333 
334  while (chars--) {
335  if (i + columns - start > max) {
336  end = MIN2(end, i);
337 
338  if (chop && i >= cursin) {
339  if (i == cursin) {
340  (*offl)++;
341  *offc -= end - start;
342  }
343 
344  return;
345  }
346 
347  (*offl)++;
348  *offc -= end - start;
349 
350  start = end;
351  end += max;
352  chop = 1;
353  }
354  else if (ELEM(ch, ' ', '-')) {
355  end = i + 1;
356  chop = 0;
357  if (i >= cursin) {
358  return;
359  }
360  }
361  i += columns;
362  }
363  }
364 }
365 
366 int text_get_char_pos(const SpaceText *st, const char *line, int cur)
367 {
368  int a = 0, i;
369 
370  for (i = 0; i < cur && line[i]; i += BLI_str_utf8_size_safe(line + i)) {
371  if (line[i] == '\t') {
372  a += st->tabnumber - a % st->tabnumber;
373  }
374  else {
375  a += BLI_str_utf8_char_width_safe(line + i);
376  }
377  }
378  return a;
379 }
380 
381 static const char *txt_utf8_forward_columns(const char *str, int columns, int *padding)
382 {
383  int col;
384  const char *p = str;
385  while (*p) {
387  if (columns - col < 0) {
388  break;
389  }
390  columns -= col;
391  p += BLI_str_utf8_size_safe(p);
392  if (columns == 0) {
393  break;
394  }
395  }
396  if (padding) {
397  *padding = *p ? columns : 0;
398  }
399  return p;
400 }
401 
402 static int text_draw_wrapped(const SpaceText *st,
403  const TextDrawContext *tdc,
404  const char *str,
405  int x,
406  int y,
407  int w,
408  const char *format,
409  int skip)
410 {
411  const bool use_syntax = (tdc->syntax_highlight && format);
412  FlattenString fs;
413  int basex, lines;
414  int i, wrap, end, max, columns, padding; /* column */
415  /* warning, only valid when 'use_syntax' is set */
416  int a, fstart, fpos; /* utf8 chars */
417  int mi, ma, mstart, mend; /* mem */
418  char fmt_prev = 0xff;
419  /* don't draw lines below this */
420  const int clip_min_y = -(int)(st->runtime.lheight_px - 1);
421 
422  flatten_string(st, &fs, str);
423  str = fs.buf;
424  max = w / st->runtime.cwidth_px;
425  if (max < 8) {
426  max = 8;
427  }
428  basex = x;
429  lines = 1;
430 
431  fpos = fstart = 0;
432  mstart = 0;
433  mend = txt_utf8_forward_columns(str, max, &padding) - str;
434  end = wrap = max - padding;
435 
436  for (i = 0, mi = 0; str[mi]; i += columns, mi += BLI_str_utf8_size_safe(str + mi)) {
437  columns = BLI_str_utf8_char_width_safe(str + mi);
438  if (i + columns > end) {
439  /* skip hidden part of line */
440  if (skip) {
441  skip--;
442  if (use_syntax) {
443  /* currently fpos only used when formatting */
444  fpos += BLI_strnlen_utf8(str + mstart, mend - mstart);
445  }
446  fstart = fpos;
447  mstart = mend;
448  mend = txt_utf8_forward_columns(str + mend, max, &padding) - str;
449  end = (wrap += max - padding);
450  continue;
451  }
452 
453  /* Draw the visible portion of text on the overshot line */
454  for (a = fstart, ma = mstart; ma < mend; a++) {
455  if (use_syntax) {
456  if (fmt_prev != format[a]) {
457  format_draw_color(tdc, fmt_prev = format[a]);
458  }
459  }
460  const int c_len = BLI_str_utf8_size_safe(str + ma);
461  x += text_font_draw_character_utf8(tdc, x, y, str + ma, c_len);
462  ma += c_len;
463  fpos++;
464  }
465  y -= TXT_LINE_HEIGHT(st);
466  x = basex;
467  lines++;
468  fstart = fpos;
469  mstart = mend;
470  mend = txt_utf8_forward_columns(str + mend, max, &padding) - str;
471  end = (wrap += max - padding);
472 
473  if (y <= clip_min_y) {
474  break;
475  }
476  }
477  else if (ELEM(str[mi], ' ', '-')) {
478  wrap = i + 1;
479  mend = mi + 1;
480  }
481  }
482 
483  /* Draw the remaining text */
484  for (a = fstart, ma = mstart; str[ma] && y > clip_min_y; a++) {
485  if (use_syntax) {
486  if (fmt_prev != format[a]) {
487  format_draw_color(tdc, fmt_prev = format[a]);
488  }
489  }
490 
491  const int c_len = BLI_str_utf8_size_safe(str + ma);
492  x += text_font_draw_character_utf8(tdc, x, y, str + ma, c_len);
493  ma += c_len;
494  }
495 
496  flatten_string_free(&fs);
497 
498  return lines;
499 }
500 
501 static void text_draw(const SpaceText *st,
502  const TextDrawContext *tdc,
503  char *str,
504  int cshift,
505  int maxwidth,
506  int x,
507  int y,
508  const char *format)
509 {
510  const bool use_syntax = (tdc->syntax_highlight && format);
511  FlattenString fs;
512  int columns, size, n, w = 0, padding, amount = 0;
513  const char *in = NULL;
514 
515  for (n = flatten_string(st, &fs, str), str = fs.buf; n > 0; n--) {
518 
519  if (!in) {
520  if (w >= cshift) {
521  padding = w - cshift;
522  in = str;
523  }
524  else if (format) {
525  format++;
526  }
527  }
528  if (in) {
529  if (maxwidth && w + columns > cshift + maxwidth) {
530  break;
531  }
532  amount++;
533  }
534 
535  w += columns;
536  str += size;
537  }
538  if (!in) {
539  flatten_string_free(&fs);
540  return; /* String is shorter than shift or ends with a padding */
541  }
542 
543  x += tdc->cwidth_px * padding;
544 
545  if (use_syntax) {
546  int a, str_shift = 0;
547  char fmt_prev = 0xff;
548 
549  for (a = 0; a < amount; a++) {
550  if (format[a] != fmt_prev) {
551  format_draw_color(tdc, fmt_prev = format[a]);
552  }
553  const int c_len = BLI_str_utf8_size_safe(in + str_shift);
554  x += text_font_draw_character_utf8(tdc, x, y, in + str_shift, c_len);
555  str_shift += c_len;
556  }
557  }
558  else {
559  text_font_draw(tdc, x, y, in);
560  }
561 
562  flatten_string_free(&fs);
563 }
564 
567 /* -------------------------------------------------------------------- */
571 typedef struct DrawCache {
572  int *line_height;
573  int total_lines, nlines;
574 
575  /* this is needed to check cache relevance */
576  int winx, wordwrap, showlinenrs, tabnumber;
577  short lheight;
578  char cwidth_px;
579  char text_id[MAX_ID_NAME];
580 
581  /* for partial lines recalculation */
582  short update_flag;
583  int valid_head, valid_tail; /* amount of unchanged lines */
584 } DrawCache;
585 
586 static void text_drawcache_init(SpaceText *st)
587 {
588  DrawCache *drawcache = MEM_callocN(sizeof(DrawCache), "text draw cache");
589 
590  drawcache->winx = -1;
591  drawcache->nlines = BLI_listbase_count(&st->text->lines);
592  drawcache->text_id[0] = '\0';
593 
594  st->runtime.drawcache = drawcache;
595 }
596 
597 static void text_update_drawcache(SpaceText *st, ARegion *region)
598 {
599  DrawCache *drawcache;
600  int full_update = 0, nlines = 0;
601  Text *txt = st->text;
602 
603  if (st->runtime.drawcache == NULL) {
604  text_drawcache_init(st);
605  }
606 
608 
609  drawcache = st->runtime.drawcache;
610  nlines = drawcache->nlines;
611 
612  /* check if full cache update is needed */
613 
614  /* area was resized */
615  full_update |= drawcache->winx != region->winx;
616  /* word-wrapping option was toggled */
617  full_update |= drawcache->wordwrap != st->wordwrap;
618  /* word-wrapping option was toggled */
619  full_update |= drawcache->showlinenrs != st->showlinenrs;
620  /* word-wrapping option was toggled */
621  full_update |= drawcache->tabnumber != st->tabnumber;
622  /* word-wrapping option was toggled */
623  full_update |= drawcache->lheight != st->runtime.lheight_px;
624  /* word-wrapping option was toggled */
625  full_update |= drawcache->cwidth_px != st->runtime.cwidth_px;
626  /* text datablock was changed */
627  full_update |= !STREQLEN(drawcache->text_id, txt->id.name, MAX_ID_NAME);
628 
629  if (st->wordwrap) {
630  /* update line heights */
631  if (full_update || !drawcache->line_height) {
632  drawcache->valid_head = 0;
633  drawcache->valid_tail = 0;
634  drawcache->update_flag = 1;
635  }
636 
637  if (drawcache->update_flag) {
638  TextLine *line = st->text->lines.first;
639  int lineno = 0, size, lines_count;
640  int *fp = drawcache->line_height, *new_tail, *old_tail;
641 
642  nlines = BLI_listbase_count(&txt->lines);
643  size = sizeof(int) * nlines;
644 
645  if (fp) {
646  fp = MEM_reallocN(fp, size);
647  }
648  else {
649  fp = MEM_callocN(size, "text drawcache line_height");
650  }
651 
652  drawcache->valid_tail = drawcache->valid_head = 0;
653  old_tail = fp + drawcache->nlines - drawcache->valid_tail;
654  new_tail = fp + nlines - drawcache->valid_tail;
655  memmove(new_tail, old_tail, drawcache->valid_tail);
656 
657  drawcache->total_lines = 0;
658 
659  if (st->showlinenrs) {
660  st->runtime.line_number_display_digits = integer_digits_i(nlines);
661  }
662 
663  while (line) {
664  if (drawcache->valid_head) { /* we're inside valid head lines */
665  lines_count = fp[lineno];
666  drawcache->valid_head--;
667  }
668  else if (lineno > new_tail - fp) { /* we-re inside valid tail lines */
669  lines_count = fp[lineno];
670  }
671  else {
672  lines_count = text_get_visible_lines(st, region, line->line);
673  }
674 
675  fp[lineno] = lines_count;
676 
677  line = line->next;
678  lineno++;
679  drawcache->total_lines += lines_count;
680  }
681 
682  drawcache->line_height = fp;
683  }
684  }
685  else {
686  MEM_SAFE_FREE(drawcache->line_height);
687 
688  if (full_update || drawcache->update_flag) {
689  nlines = BLI_listbase_count(&txt->lines);
690 
691  if (st->showlinenrs) {
692  st->runtime.line_number_display_digits = integer_digits_i(nlines);
693  }
694  }
695 
696  drawcache->total_lines = nlines;
697  }
698 
699  drawcache->nlines = nlines;
700 
701  /* store settings */
702  drawcache->winx = region->winx;
703  drawcache->wordwrap = st->wordwrap;
704  drawcache->lheight = st->runtime.lheight_px;
705  drawcache->cwidth_px = st->runtime.cwidth_px;
706  drawcache->showlinenrs = st->showlinenrs;
707  drawcache->tabnumber = st->tabnumber;
708 
709  strncpy(drawcache->text_id, txt->id.name, MAX_ID_NAME);
710 
711  /* clear update flag */
712  drawcache->update_flag = 0;
713  drawcache->valid_head = 0;
714  drawcache->valid_tail = 0;
715 }
716 
717 void text_drawcache_tag_update(SpaceText *st, int full)
718 {
719  /* This happens if text editor ops are called from Python. */
720  if (st == NULL) {
721  return;
722  }
723 
724  if (st->runtime.drawcache != NULL) {
725  DrawCache *drawcache = st->runtime.drawcache;
726  Text *txt = st->text;
727 
728  if (drawcache->update_flag) {
729  /* happens when tagging update from space listener */
730  /* should do nothing to prevent locally tagged cache be fully recalculated */
731  return;
732  }
733 
734  if (!full) {
735  int sellno = BLI_findindex(&txt->lines, txt->sell);
736  int curlno = BLI_findindex(&txt->lines, txt->curl);
737 
738  if (curlno < sellno) {
739  drawcache->valid_head = curlno;
740  drawcache->valid_tail = drawcache->nlines - sellno - 1;
741  }
742  else {
743  drawcache->valid_head = sellno;
744  drawcache->valid_tail = drawcache->nlines - curlno - 1;
745  }
746 
747  /* quick cache recalculation is also used in delete operator,
748  * which could merge lines which are adjacent to current selection lines
749  * expand recalculate area to this lines */
750  if (drawcache->valid_head > 0) {
751  drawcache->valid_head--;
752  }
753  if (drawcache->valid_tail > 0) {
754  drawcache->valid_tail--;
755  }
756  }
757  else {
758  drawcache->valid_head = 0;
759  drawcache->valid_tail = 0;
760  }
761 
762  drawcache->update_flag = 1;
763  }
764 }
765 
767 {
768  DrawCache *drawcache = st->runtime.drawcache;
769 
770  if (drawcache) {
771  if (drawcache->line_height) {
772  MEM_freeN(drawcache->line_height);
773  }
774 
775  MEM_freeN(drawcache);
776  }
777 }
778 
781 /* -------------------------------------------------------------------- */
785 /* cache should be updated in caller */
786 static int text_get_visible_lines_no(const SpaceText *st, int lineno)
787 {
788  const DrawCache *drawcache = st->runtime.drawcache;
789 
790  return drawcache->line_height[lineno];
791 }
792 
793 int text_get_visible_lines(const SpaceText *st, ARegion *region, const char *str)
794 {
795  int i, j, start, end, max, lines, chars;
796  char ch;
797 
798  max = wrap_width(st, region);
799  lines = 1;
800  start = 0;
801  end = max;
802  for (i = 0, j = 0; str[j]; j += BLI_str_utf8_size_safe(str + j)) {
803  int columns = BLI_str_utf8_char_width_safe(str + j); /* = 1 for tab */
804 
805  /* Mimic replacement of tabs */
806  ch = str[j];
807  if (ch == '\t') {
808  chars = st->tabnumber - i % st->tabnumber;
809  ch = ' ';
810  }
811  else {
812  chars = 1;
813  }
814 
815  while (chars--) {
816  if (i + columns - start > max) {
817  lines++;
818  start = MIN2(end, i);
819  end += max;
820  }
821  else if (ELEM(ch, ' ', '-')) {
822  end = i + 1;
823  }
824 
825  i += columns;
826  }
827  }
828 
829  return lines;
830 }
831 
832 int text_get_span_wrap(const SpaceText *st, ARegion *region, TextLine *from, TextLine *to)
833 {
834  if (st->wordwrap) {
835  int ret = 0;
836  TextLine *tmp = from;
837 
838  /* Look forwards */
839  while (tmp) {
840  if (tmp == to) {
841  return ret;
842  }
843  ret += text_get_visible_lines(st, region, tmp->line);
844  tmp = tmp->next;
845  }
846 
847  return ret;
848  }
849  return txt_get_span(from, to);
850 }
851 
853 {
854  DrawCache *drawcache;
855 
856  text_update_drawcache(st, region);
857  drawcache = st->runtime.drawcache;
858 
859  return drawcache->total_lines;
860 }
861 
864 /* -------------------------------------------------------------------- */
868 static void calc_text_rcts(SpaceText *st, ARegion *region, rcti *scroll, rcti *back)
869 {
870  int lhlstart, lhlend, ltexth, sell_off, curl_off;
871  short barheight, barstart, hlstart, hlend, blank_lines;
872  short pix_available, pix_top_margin, pix_bottom_margin, pix_bardiff;
873 
874  pix_top_margin = (0.4 * U.widget_unit);
875  pix_bottom_margin = (0.4 * U.widget_unit);
876  pix_available = region->winy - pix_top_margin - pix_bottom_margin;
877  ltexth = text_get_total_lines(st, region);
878  blank_lines = st->runtime.viewlines / 2;
879 
880  /* nicer code: use scroll rect for entire bar */
881  back->xmin = region->winx - (0.6 * U.widget_unit);
882  back->xmax = region->winx;
883  back->ymin = 0;
884  back->ymax = region->winy;
885 
886  scroll->xmax = region->winx - (0.2 * U.widget_unit);
887  scroll->xmin = scroll->xmax - (0.4 * U.widget_unit);
888  scroll->ymin = pix_top_margin;
889  scroll->ymax = pix_available;
890 
891  /* when re-sizing a 2D Viewport with the bar at the bottom to a greater height
892  * more blank lines will be added */
893  if (ltexth + blank_lines < st->top + st->runtime.viewlines) {
894  blank_lines = st->top + st->runtime.viewlines - ltexth;
895  }
896 
897  ltexth += blank_lines;
898 
899  barheight = (ltexth > 0) ? (st->runtime.viewlines * pix_available) / ltexth : 0;
900  pix_bardiff = 0;
901  if (barheight < 20) {
902  pix_bardiff = 20 - barheight; /* take into account the now non-linear sizing of the bar */
903  barheight = 20;
904  }
905  barstart = (ltexth > 0) ? ((pix_available - pix_bardiff) * st->top) / ltexth : 0;
906 
907  st->runtime.scroll_region_handle = *scroll;
908  st->runtime.scroll_region_handle.ymax -= barstart;
909  st->runtime.scroll_region_handle.ymin = st->runtime.scroll_region_handle.ymax - barheight;
910 
911  CLAMP(st->runtime.scroll_region_handle.ymin, pix_bottom_margin, region->winy - pix_top_margin);
912  CLAMP(st->runtime.scroll_region_handle.ymax, pix_bottom_margin, region->winy - pix_top_margin);
913 
914  st->runtime.scroll_px_per_line = (pix_available > 0) ? (float)ltexth / pix_available : 0;
915  if (st->runtime.scroll_px_per_line < 0.1f) {
916  st->runtime.scroll_px_per_line = 0.1f;
917  }
918 
919  curl_off = text_get_span_wrap(st, region, st->text->lines.first, st->text->curl);
920  sell_off = text_get_span_wrap(st, region, st->text->lines.first, st->text->sell);
921  lhlstart = MIN2(curl_off, sell_off);
922  lhlend = MAX2(curl_off, sell_off);
923 
924  if (ltexth > 0) {
925  hlstart = (lhlstart * pix_available) / ltexth;
926  hlend = (lhlend * pix_available) / ltexth;
927 
928  /* The scrollbar is non-linear sized. */
929  if (pix_bardiff > 0) {
930  /* the start of the highlight is in the current viewport */
931  if (st->runtime.viewlines && lhlstart >= st->top &&
932  lhlstart <= st->top + st->runtime.viewlines) {
933  /* Speed the progression of the start of the highlight through the scrollbar. */
934  hlstart = (((pix_available - pix_bardiff) * lhlstart) / ltexth) +
935  (pix_bardiff * (lhlstart - st->top) / st->runtime.viewlines);
936  }
937  else if (lhlstart > st->top + st->runtime.viewlines && hlstart < barstart + barheight &&
938  hlstart > barstart) {
939  /* push hl start down */
940  hlstart = barstart + barheight;
941  }
942  else if (lhlend > st->top && lhlstart < st->top && hlstart > barstart) {
943  /* Fill out start. */
944  hlstart = barstart;
945  }
946 
947  if (hlend <= hlstart) {
948  hlend = hlstart + 2;
949  }
950 
951  /* the end of the highlight is in the current viewport */
952  if (st->runtime.viewlines && lhlend >= st->top &&
953  lhlend <= st->top + st->runtime.viewlines) {
954  /* Speed the progression of the end of the highlight through the scrollbar. */
955  hlend = (((pix_available - pix_bardiff) * lhlend) / ltexth) +
956  (pix_bardiff * (lhlend - st->top) / st->runtime.viewlines);
957  }
958  else if (lhlend < st->top && hlend >= barstart - 2 && hlend < barstart + barheight) {
959  /* push hl end up */
960  hlend = barstart;
961  }
962  else if (lhlend > st->top + st->runtime.viewlines &&
963  lhlstart < st->top + st->runtime.viewlines && hlend < barstart + barheight) {
964  /* fill out end */
965  hlend = barstart + barheight;
966  }
967 
968  if (hlend <= hlstart) {
969  hlstart = hlend - 2;
970  }
971  }
972  }
973  else {
974  hlstart = 0;
975  hlend = 0;
976  }
977 
978  if (hlend - hlstart < 2) {
979  hlend = hlstart + 2;
980  }
981 
982  st->runtime.scroll_region_select = *scroll;
983  st->runtime.scroll_region_select.ymax = region->winy - pix_top_margin - hlstart;
984  st->runtime.scroll_region_select.ymin = region->winy - pix_top_margin - hlend;
985 
986  CLAMP(st->runtime.scroll_region_select.ymin, pix_bottom_margin, region->winy - pix_top_margin);
987  CLAMP(st->runtime.scroll_region_select.ymax, pix_bottom_margin, region->winy - pix_top_margin);
988 }
989 
990 static void draw_textscroll(const SpaceText *st, rcti *scroll, rcti *back)
991 {
992  bTheme *btheme = UI_GetTheme();
993  uiWidgetColors wcol = btheme->tui.wcol_scroll;
994  float col[4];
995  float rad;
996 
997  /* background so highlights don't go behind the scrollbar */
1002  immRecti(pos, back->xmin, back->ymin, back->xmax, back->ymax);
1003  immUnbindProgram();
1004 
1005  UI_draw_widget_scroll(&wcol,
1006  scroll,
1007  &st->runtime.scroll_region_handle,
1008  (st->flags & ST_SCROLL_SELECT) ? UI_SCROLL_PRESSED : 0);
1009 
1011  rad = 0.4f * min_ii(BLI_rcti_size_x(&st->runtime.scroll_region_select),
1012  BLI_rcti_size_y(&st->runtime.scroll_region_select));
1014  col[3] = 0.18f;
1016  &(const rctf){
1017  .xmin = st->runtime.scroll_region_select.xmin + 1,
1018  .xmax = st->runtime.scroll_region_select.xmax - 1,
1019  .ymin = st->runtime.scroll_region_select.ymin,
1020  .ymax = st->runtime.scroll_region_select.ymax,
1021  },
1022  true,
1023  rad,
1024  col);
1025 }
1026 
1029 /* -------------------------------------------------------------------- */
1033 #if 0
1034 
1035 static void draw_documentation(const SpaceText *st, ARegion *region)
1036 {
1037  TextDrawContext tdc = {0};
1038  TextLine *tmp;
1039  char *docs, buf[DOC_WIDTH + 1], *p;
1040  int i, br, lines;
1041  int boxw, boxh, l, x, y /* , top */ /* UNUSED */;
1042 
1043  if (!st || !st->text) {
1044  return;
1045  }
1046  if (!texttool_text_is_active(st->text)) {
1047  return;
1048  }
1049 
1050  docs = texttool_docs_get();
1051 
1052  if (!docs) {
1053  return;
1054  }
1055 
1056  text_draw_context_init(st, &tdc);
1057 
1058  /* Count the visible lines to the cursor */
1059  for (tmp = st->text->curl, l = -st->top; tmp; tmp = tmp->prev, l++) {
1060  /* pass */
1061  }
1062 
1063  if (l < 0) {
1064  return;
1065  }
1066 
1067  x = TXT_BODY_LEFT(st) + (st->runtime.cwidth_px * (st->text->curc - st->left));
1068  if (texttool_suggest_first()) {
1069  x += SUGG_LIST_WIDTH * st->runtime.cwidth_px + 50;
1070  }
1071 
1072  /* top = */ /* UNUSED */ y = region->winy - st->runtime.lheight_px * l - 2;
1073  boxw = DOC_WIDTH * st->runtime.cwidth_px + 20;
1074  boxh = (DOC_HEIGHT + 1) * TXT_LINE_HEIGHT(st);
1075 
1076  /* Draw panel */
1080 
1082  immRecti(pos, x, y, x + boxw, y - boxh);
1085  immVertex2i(pos, x, y);
1086  immVertex2i(pos, x + boxw, y);
1087  immVertex2i(pos, x + boxw, y - boxh);
1088  immVertex2i(pos, x, y - boxh);
1089  immEnd();
1091  immVertex2i(pos, x + boxw - 10, y - 7);
1092  immVertex2i(pos, x + boxw - 4, y - 7);
1093  immVertex2i(pos, x + boxw - 7, y - 2);
1094  immEnd();
1096  immVertex2i(pos, x + boxw - 10, y - boxh + 7);
1097  immVertex2i(pos, x + boxw - 4, y - boxh + 7);
1098  immVertex2i(pos, x + boxw - 7, y - boxh + 2);
1099  immEnd();
1100 
1101  immUnbindProgram();
1102 
1104 
1105  i = 0;
1106  br = DOC_WIDTH;
1107  lines = 0; /* XXX -doc_scroll; */
1108  for (p = docs; *p; p++) {
1109  if (*p == '\r' && *(++p) != '\n') {
1110  *(--p) = '\n'; /* Fix line endings */
1111  }
1112  if (ELEM(*p, ' ', '\t')) {
1113  br = i;
1114  }
1115  else if (*p == '\n') {
1116  buf[i] = '\0';
1117  if (lines >= 0) {
1118  y -= st->runtime.lheight_px;
1119  text_draw(st, &tdc, buf, 0, 0, x + 4, y - 3, NULL);
1120  }
1121  i = 0;
1122  br = DOC_WIDTH;
1123  lines++;
1124  }
1125  buf[i++] = *p;
1126  if (i == DOC_WIDTH) { /* Reached the width, go to last break and wrap there */
1127  buf[br] = '\0';
1128  if (lines >= 0) {
1129  y -= st->runtime.lheight_px;
1130  text_draw(st, &tdc, buf, 0, 0, x + 4, y - 3, NULL);
1131  }
1132  p -= i - br - 1; /* Rewind pointer to last break */
1133  i = 0;
1134  br = DOC_WIDTH;
1135  lines++;
1136  }
1137  if (lines >= DOC_HEIGHT) {
1138  break;
1139  }
1140  }
1141 }
1142 
1143 #endif
1144 
1147 /* -------------------------------------------------------------------- */
1151 static void draw_suggestion_list(const SpaceText *st, const TextDrawContext *tdc, ARegion *region)
1152 {
1153  SuggItem *item, *first, *last, *sel;
1154  char str[SUGG_LIST_WIDTH * BLI_UTF8_MAX + 1];
1155  int offl, offc, vcurl, vcurc;
1156  int w, boxw = 0, boxh, i, x, y, *top;
1157  const int lheight = TXT_LINE_HEIGHT(st);
1158  const int margin_x = 2;
1159 
1160  if (!st->text) {
1161  return;
1162  }
1163  if (!texttool_text_is_active(st->text)) {
1164  return;
1165  }
1166 
1167  first = texttool_suggest_first();
1168  last = texttool_suggest_last();
1169 
1170  if (!first || !last) {
1171  return;
1172  }
1173 
1175  sel = texttool_suggest_selected();
1177 
1178  wrap_offset(st, region, st->text->curl, st->text->curc, &offl, &offc);
1179  vcurl = txt_get_span(st->text->lines.first, st->text->curl) - st->top + offl;
1180  vcurc = text_get_char_pos(st, st->text->curl->line, st->text->curc) - st->left + offc;
1181 
1182  x = TXT_BODY_LEFT(st) + (vcurc * st->runtime.cwidth_px);
1183  y = region->winy - (vcurl + 1) * lheight - 2;
1184 
1185  /* offset back so the start of the text lines up with the suggestions,
1186  * not essential but makes suggestions easier to follow */
1187  x -= st->runtime.cwidth_px *
1188  (st->text->curc - text_find_identifier_start(st->text->curl->line, st->text->curc));
1189 
1190  boxw = SUGG_LIST_WIDTH * st->runtime.cwidth_px + 20;
1191  boxh = SUGG_LIST_SIZE * lheight + 8;
1192 
1193  if (x + boxw > region->winx) {
1194  x = MAX2(0, region->winx - boxw);
1195  }
1196 
1197  /* not needed but stands out nicer */
1199  &(const rctf){
1200  .xmin = x,
1201  .xmax = x + boxw,
1202  .ymin = y - boxh,
1203  .ymax = y,
1204  },
1205  220);
1206 
1210 
1212  immRecti(pos, x - 1, y + 1, x + boxw + 1, y - boxh - 1);
1214  immRecti(pos, x, y, x + boxw, y - boxh);
1215 
1216  immUnbindProgram();
1217 
1218  /* Set the top 'item' of the visible list */
1219  for (i = 0, item = first; i < *top && item->next; i++, item = item->next) {
1220  /* pass */
1221  }
1222 
1223  for (i = 0; i < SUGG_LIST_SIZE && item; i++, item = item->next) {
1224  int len = txt_utf8_forward_columns(item->name, SUGG_LIST_WIDTH, NULL) - item->name;
1225 
1226  y -= lheight;
1227 
1228  BLI_strncpy(str, item->name, len + 1);
1229 
1230  w = st->runtime.cwidth_px * text_get_char_pos(st, str, len);
1231 
1232  if (item == sel) {
1236 
1238  immRecti(posi, x + margin_x, y - 3, x + margin_x + w, y + lheight - 3);
1239 
1240  immUnbindProgram();
1241  }
1242 
1243  format_draw_color(tdc, item->type);
1244  text_draw(st, tdc, str, 0, 0, x + margin_x, y - 1, NULL);
1245 
1246  if (item == last) {
1247  break;
1248  }
1249  }
1250 }
1251 
1254 /* -------------------------------------------------------------------- */
1258 static void draw_text_decoration(SpaceText *st, ARegion *region)
1259 {
1260  Text *text = st->text;
1261  int vcurl, vcurc, vsell, vselc, hidden = 0;
1262  int x, y, w, i;
1263  int offl, offc;
1264  const int lheight = TXT_LINE_HEIGHT(st);
1265 
1266  /* Convert to view space character coordinates to determine if cursor is hidden */
1267  wrap_offset(st, region, text->sell, text->selc, &offl, &offc);
1268  vsell = txt_get_span(text->lines.first, text->sell) - st->top + offl;
1269  vselc = text_get_char_pos(st, text->sell->line, text->selc) - st->left + offc;
1270 
1271  if (vselc < 0) {
1272  vselc = 0;
1273  hidden = 1;
1274  }
1275 
1276  if (text->curl == text->sell && text->curc == text->selc && !st->line_hlight && hidden) {
1277  /* Nothing to draw here */
1278  return;
1279  }
1280 
1284 
1285  /* Draw the selection */
1286  if (text->curl != text->sell || text->curc != text->selc) {
1287  /* Convert all to view space character coordinates */
1288  wrap_offset(st, region, text->curl, text->curc, &offl, &offc);
1289  vcurl = txt_get_span(text->lines.first, text->curl) - st->top + offl;
1290  vcurc = text_get_char_pos(st, text->curl->line, text->curc) - st->left + offc;
1291 
1292  if (vcurc < 0) {
1293  vcurc = 0;
1294  }
1295 
1297 
1298  x = TXT_BODY_LEFT(st);
1299  y = region->winy;
1300  if (st->flags & ST_SCROLL_SELECT) {
1301  y += st->runtime.scroll_ofs_px[1];
1302  }
1303 
1304  if (vcurl == vsell) {
1305  y -= vcurl * lheight;
1306 
1307  if (vcurc < vselc) {
1308  immRecti(pos,
1309  x + vcurc * st->runtime.cwidth_px,
1310  y,
1311  x + vselc * st->runtime.cwidth_px,
1312  y - lheight);
1313  }
1314  else {
1315  immRecti(pos,
1316  x + vselc * st->runtime.cwidth_px,
1317  y,
1318  x + vcurc * st->runtime.cwidth_px,
1319  y - lheight);
1320  }
1321  }
1322  else {
1323  int froml, fromc, tol, toc;
1324 
1325  if (vcurl < vsell) {
1326  froml = vcurl;
1327  tol = vsell;
1328  fromc = vcurc;
1329  toc = vselc;
1330  }
1331  else {
1332  froml = vsell;
1333  tol = vcurl;
1334  fromc = vselc;
1335  toc = vcurc;
1336  }
1337 
1338  y -= froml * lheight;
1339 
1340  immRecti(pos, x + fromc * st->runtime.cwidth_px - U.pixelsize, y, region->winx, y - lheight);
1341  y -= lheight;
1342 
1343  for (i = froml + 1; i < tol; i++) {
1344  immRecti(pos, x - U.pixelsize, y, region->winx, y - lheight);
1345  y -= lheight;
1346  }
1347 
1348  if (x + toc * st->runtime.cwidth_px > x) {
1349  immRecti(pos, x - U.pixelsize, y, x + toc * st->runtime.cwidth_px, y - lheight);
1350  }
1351  y -= lheight;
1352  }
1353  }
1354 
1355  if (st->line_hlight) {
1356  int y1, y2;
1357 
1358  if (st->wordwrap) {
1359  int visible_lines = text_get_visible_lines(st, region, text->sell->line);
1360 
1361  wrap_offset_in_line(st, region, text->sell, text->selc, &offl, &offc);
1362 
1363  y1 = region->winy - (vsell - offl) * lheight;
1364  if (st->flags & ST_SCROLL_SELECT) {
1365  y1 += st->runtime.scroll_ofs_px[1];
1366  }
1367  y2 = y1 - (lheight * visible_lines);
1368  }
1369  else {
1370  y1 = region->winy - vsell * lheight;
1371  if (st->flags & ST_SCROLL_SELECT) {
1372  y1 += st->runtime.scroll_ofs_px[1];
1373  }
1374  y2 = y1 - (lheight);
1375  }
1376 
1377  if (!(y1 < 0 || y2 > region->winy)) { /* check we need to draw */
1378  float highlight_color[4];
1379  UI_GetThemeColor4fv(TH_TEXT, highlight_color);
1380  highlight_color[3] = 0.1f;
1381  immUniformColor4fv(highlight_color);
1383  immRecti(pos, 0, y1, region->winx, y2);
1385  }
1386  }
1387 
1388  if (!hidden) {
1389  /* Draw the cursor itself (we draw the sel. cursor as this is the leading edge) */
1390  x = TXT_BODY_LEFT(st) + (vselc * st->runtime.cwidth_px);
1391  y = region->winy - vsell * lheight;
1392  if (st->flags & ST_SCROLL_SELECT) {
1393  y += st->runtime.scroll_ofs_px[1];
1394  }
1395 
1397 
1398  if (st->overwrite) {
1399  char ch = text->sell->line[text->selc];
1400 
1401  y += TXT_LINE_SPACING(st);
1402  w = st->runtime.cwidth_px;
1403  if (ch == '\t') {
1404  w *= st->tabnumber - (vselc + st->left) % st->tabnumber;
1405  }
1406 
1407  immRecti(
1408  pos, x, y - lheight - U.pixelsize, x + w + U.pixelsize, y - lheight - (3 * U.pixelsize));
1409  }
1410  else {
1411  immRecti(pos, x - U.pixelsize, y, x + U.pixelsize, y - lheight);
1412  }
1413  }
1414 
1415  immUnbindProgram();
1416 }
1417 
1420 /* -------------------------------------------------------------------- */
1424 static void draw_brackets(const SpaceText *st, const TextDrawContext *tdc, ARegion *region)
1425 {
1426  TextLine *startl, *endl, *linep;
1427  Text *text = st->text;
1428  int b, fc, find, stack, viewc, viewl, offl, offc, x, y;
1429  int startc, endc, c;
1430 
1431  char ch;
1432 
1433  /* syntax_highlight must be on or else the format string will be null */
1434  if (!text->curl || !tdc->syntax_highlight) {
1435  return;
1436  }
1437 
1438  startl = text->curl;
1439  startc = text->curc;
1440  b = text_check_bracket(startl->line[startc]);
1441  if (b == 0 && startc > 0) {
1442  b = text_check_bracket(startl->line[--startc]);
1443  }
1444  if (b == 0) {
1445  return;
1446  }
1447 
1448  linep = startl;
1449  c = startc;
1450  fc = BLI_str_utf8_offset_to_index(linep->line, startc);
1451  endl = NULL;
1452  endc = -1;
1453  find = -b;
1454  stack = 0;
1455 
1456  /* Don't highlight brackets if syntax HL is off or bracket in string or comment. */
1457  if (!linep->format || linep->format[fc] == FMT_TYPE_STRING ||
1458  linep->format[fc] == FMT_TYPE_COMMENT) {
1459  return;
1460  }
1461 
1462  if (b > 0) {
1463  /* opening bracket, search forward for close */
1464  fc++;
1465  c += BLI_str_utf8_size_safe(linep->line + c);
1466  while (linep) {
1467  while (c < linep->len) {
1468  if (linep->format && linep->format[fc] != FMT_TYPE_STRING &&
1469  linep->format[fc] != FMT_TYPE_COMMENT) {
1470  b = text_check_bracket(linep->line[c]);
1471  if (b == find) {
1472  if (stack == 0) {
1473  endl = linep;
1474  endc = c;
1475  break;
1476  }
1477  stack--;
1478  }
1479  else if (b == -find) {
1480  stack++;
1481  }
1482  }
1483  fc++;
1484  c += BLI_str_utf8_size_safe(linep->line + c);
1485  }
1486  if (endl) {
1487  break;
1488  }
1489  linep = linep->next;
1490  c = 0;
1491  fc = 0;
1492  }
1493  }
1494  else {
1495  /* closing bracket, search backward for open */
1496  fc--;
1497  if (c > 0) {
1498  c -= linep->line + c - BLI_str_find_prev_char_utf8(linep->line + c, linep->line);
1499  }
1500  while (linep) {
1501  while (fc >= 0) {
1502  if (linep->format && linep->format[fc] != FMT_TYPE_STRING &&
1503  linep->format[fc] != FMT_TYPE_COMMENT) {
1504  b = text_check_bracket(linep->line[c]);
1505  if (b == find) {
1506  if (stack == 0) {
1507  endl = linep;
1508  endc = c;
1509  break;
1510  }
1511  stack--;
1512  }
1513  else if (b == -find) {
1514  stack++;
1515  }
1516  }
1517  fc--;
1518  if (c > 0) {
1519  c -= linep->line + c - BLI_str_find_prev_char_utf8(linep->line + c, linep->line);
1520  }
1521  }
1522  if (endl) {
1523  break;
1524  }
1525  linep = linep->prev;
1526  if (linep) {
1527  if (linep->format) {
1528  fc = strlen(linep->format) - 1;
1529  }
1530  else {
1531  fc = -1;
1532  }
1533  if (linep->len) {
1534  c = BLI_str_find_prev_char_utf8(linep->line + linep->len, linep->line) - linep->line;
1535  }
1536  else {
1537  fc = -1;
1538  }
1539  }
1540  }
1541  }
1542 
1543  if (!endl || endc == -1) {
1544  return;
1545  }
1546 
1548  x = TXT_BODY_LEFT(st);
1549  y = region->winy - st->runtime.lheight_px;
1550  if (st->flags & ST_SCROLL_SELECT) {
1551  y += st->runtime.scroll_ofs_px[1];
1552  }
1553 
1554  /* draw opening bracket */
1555  ch = startl->line[startc];
1556  wrap_offset(st, region, startl, startc, &offl, &offc);
1557  viewc = text_get_char_pos(st, startl->line, startc) - st->left + offc;
1558 
1559  if (viewc >= 0) {
1560  viewl = txt_get_span(text->lines.first, startl) - st->top + offl;
1561 
1563  tdc, x + viewc * st->runtime.cwidth_px, y - viewl * TXT_LINE_HEIGHT(st), ch);
1565  tdc, x + viewc * st->runtime.cwidth_px + 1, y - viewl * TXT_LINE_HEIGHT(st), ch);
1566  }
1567 
1568  /* draw closing bracket */
1569  ch = endl->line[endc];
1570  wrap_offset(st, region, endl, endc, &offl, &offc);
1571  viewc = text_get_char_pos(st, endl->line, endc) - st->left + offc;
1572 
1573  if (viewc >= 0) {
1574  viewl = txt_get_span(text->lines.first, endl) - st->top + offl;
1575 
1577  tdc, x + viewc * st->runtime.cwidth_px, y - viewl * TXT_LINE_HEIGHT(st), ch);
1579  tdc, x + viewc * st->runtime.cwidth_px + 1, y - viewl * TXT_LINE_HEIGHT(st), ch);
1580  }
1581 }
1582 
1585 /* -------------------------------------------------------------------- */
1589 void draw_text_main(SpaceText *st, ARegion *region)
1590 {
1591  TextDrawContext tdc = {0};
1592  Text *text = st->text;
1593  TextFormatType *tft;
1594  TextLine *tmp;
1595  rcti scroll, back;
1596  char linenr[12];
1597  int i, x, y, winx, linecount = 0, lineno = 0;
1598  int wraplinecount = 0, wrap_skip = 0;
1599  int margin_column_x;
1600 
1601  /* if no text, nothing to do */
1602  if (!text) {
1603  return;
1604  }
1605 
1606  /* DPI controlled line height and font size. */
1607  st->runtime.lheight_px = (U.widget_unit * st->lheight) / 20;
1608 
1609  /* don't draw lines below this */
1610  const int clip_min_y = -(int)(st->runtime.lheight_px - 1);
1611 
1612  st->runtime.viewlines = (st->runtime.lheight_px) ?
1613  (int)(region->winy - clip_min_y) / TXT_LINE_HEIGHT(st) :
1614  0;
1615 
1616  text_draw_context_init(st, &tdc);
1617 
1618  text_update_drawcache(st, region);
1619 
1620  /* make sure all the positional pointers exist */
1621  if (!text->curl || !text->sell || !text->lines.first || !text->lines.last) {
1622  txt_clean_text(text);
1623  }
1624 
1625  /* update rects for scroll */
1626  calc_text_rcts(st, region, &scroll, &back); /* scroll will hold the entire bar size */
1627 
1628  /* update syntax formatting if needed */
1629  tft = ED_text_format_get(text);
1630  tmp = text->lines.first;
1631  lineno = 0;
1632  for (i = 0; i < st->top && tmp; i++) {
1633  if (tdc.syntax_highlight && !tmp->format) {
1634  tft->format_line(st, tmp, false);
1635  }
1636 
1637  if (st->wordwrap) {
1638  int lines = text_get_visible_lines_no(st, lineno);
1639 
1640  if (wraplinecount + lines > st->top) {
1641  wrap_skip = st->top - wraplinecount;
1642  break;
1643  }
1644 
1645  wraplinecount += lines;
1646  tmp = tmp->next;
1647  linecount++;
1648  }
1649  else {
1650  tmp = tmp->next;
1651  linecount++;
1652  }
1653 
1654  lineno++;
1655  }
1656 
1657  text_font_begin(&tdc);
1658 
1659  tdc.cwidth_px = max_ii((int)BLF_fixed_width(tdc.font_id), 1);
1660  st->runtime.cwidth_px = tdc.cwidth_px;
1661 
1662  /* draw line numbers background */
1663  if (st->showlinenrs) {
1668  immRecti(pos, 0, 0, TXT_NUMCOL_WIDTH(st), region->winy);
1669  immUnbindProgram();
1670  }
1671  else {
1672  st->runtime.line_number_display_digits = 0; /* not used */
1673  }
1674 
1675  x = TXT_BODY_LEFT(st);
1676  y = region->winy - st->runtime.lheight_px;
1677  int viewlines = st->runtime.viewlines;
1678  if (st->flags & ST_SCROLL_SELECT) {
1679  y += st->runtime.scroll_ofs_px[1];
1680  viewlines += 1;
1681  }
1682 
1683  winx = region->winx - TXT_SCROLL_WIDTH;
1684 
1685  /* draw cursor, margin, selection and highlight */
1686  draw_text_decoration(st, region);
1687 
1688  /* draw the text */
1690 
1691  for (i = 0; y > clip_min_y && i < viewlines && tmp; i++, tmp = tmp->next) {
1692  if (tdc.syntax_highlight && !tmp->format) {
1693  tft->format_line(st, tmp, false);
1694  }
1695 
1696  if (st->showlinenrs && !wrap_skip) {
1697  /* Draw line number. */
1698  UI_FontThemeColor(tdc.font_id, (tmp == text->sell) ? TH_HILITE : TH_LINENUMBERS);
1699  BLI_snprintf(linenr,
1700  sizeof(linenr),
1701  "%*d",
1702  st->runtime.line_number_display_digits,
1703  i + linecount + 1);
1704  text_font_draw(&tdc, TXT_NUMCOL_PAD * st->runtime.cwidth_px, y, linenr);
1705  /* Change back to text color. */
1707  }
1708 
1709  if (st->wordwrap) {
1710  /* draw word wrapped text */
1711  int lines = text_draw_wrapped(st, &tdc, tmp->line, x, y, winx - x, tmp->format, wrap_skip);
1712  y -= lines * TXT_LINE_HEIGHT(st);
1713  }
1714  else {
1715  /* draw unwrapped text */
1716  text_draw(
1717  st, &tdc, tmp->line, st->left, region->winx / st->runtime.cwidth_px, x, y, tmp->format);
1718  y -= TXT_LINE_HEIGHT(st);
1719  }
1720 
1721  wrap_skip = 0;
1722  }
1723 
1724  if (st->flags & ST_SHOW_MARGIN) {
1725  margin_column_x = x + st->runtime.cwidth_px * (st->margin_column - st->left);
1726  if (margin_column_x >= x) {
1730  float margin_color[4];
1731  UI_GetThemeColor4fv(TH_TEXT, margin_color);
1732  margin_color[3] = 0.2f;
1733  immUniformColor4fv(margin_color);
1735  immRecti(pos, margin_column_x, 0, margin_column_x + U.pixelsize, region->winy);
1737  immUnbindProgram();
1738  }
1739  }
1740 
1741  /* draw other stuff */
1742  draw_brackets(st, &tdc, region);
1743  draw_textscroll(st, &scroll, &back);
1744  /* draw_documentation(st, region); - No longer supported */
1745  draw_suggestion_list(st, &tdc, region);
1746 
1747  text_font_end(&tdc);
1748 }
1749 
1752 /* -------------------------------------------------------------------- */
1757 {
1758  TextDrawContext tdc = {0};
1759 
1760  text_draw_context_init(st, &tdc);
1761 
1762  text_font_begin(&tdc);
1763  st->runtime.cwidth_px = BLF_fixed_width(tdc.font_id);
1764  st->runtime.cwidth_px = MAX2(st->runtime.cwidth_px, (char)1);
1765  text_font_end(&tdc);
1766 }
1767 
1769 {
1771  if (area) {
1772  SpaceText *st = area->spacedata.first;
1774  st->text = text;
1775  if (region) {
1776  ED_text_scroll_to_cursor(st, region, true);
1777  }
1779  return true;
1780  }
1781 
1782  return false;
1783 }
1784 
1785 void ED_text_scroll_to_cursor(SpaceText *st, ARegion *region, const bool center)
1786 {
1787  Text *text;
1788  int i, x, winx = region->winx;
1789 
1790  if (ELEM(NULL, st, st->text, st->text->curl)) {
1791  return;
1792  }
1793 
1794  text = st->text;
1795 
1797 
1798  i = txt_get_span(text->lines.first, text->sell);
1799  if (st->wordwrap) {
1800  int offl, offc;
1801  wrap_offset(st, region, text->sell, text->selc, &offl, &offc);
1802  i += offl;
1803  }
1804 
1805  if (center) {
1806  if (st->top + st->runtime.viewlines <= i || st->top > i) {
1807  st->top = i - st->runtime.viewlines / 2;
1808  }
1809  }
1810  else {
1811  if (st->top + st->runtime.viewlines <= i) {
1812  st->top = i - (st->runtime.viewlines - 1);
1813  }
1814  else if (st->top > i) {
1815  st->top = i;
1816  }
1817  }
1818 
1819  if (st->wordwrap) {
1820  st->left = 0;
1821  }
1822  else {
1823  x = st->runtime.cwidth_px * (text_get_char_pos(st, text->sell->line, text->selc) - st->left);
1824  winx -= TXT_BODY_LEFT(st) + TXT_SCROLL_WIDTH;
1825 
1826  if (center) {
1827  if (x <= 0 || x > winx) {
1828  st->left += (x - winx / 2) / st->runtime.cwidth_px;
1829  }
1830  }
1831  else {
1832  if (x <= 0) {
1833  st->left += ((x + 1) / st->runtime.cwidth_px) - 1;
1834  }
1835  else if (x > winx) {
1836  st->left += ((x - (winx + 1)) / st->runtime.cwidth_px) + 1;
1837  }
1838  }
1839  }
1840 
1841  if (st->top < 0) {
1842  st->top = 0;
1843  }
1844  if (st->left < 0) {
1845  st->left = 0;
1846  }
1847 
1848  st->runtime.scroll_ofs_px[0] = 0;
1849  st->runtime.scroll_ofs_px[1] = 0;
1850 }
1851 
1853 {
1854  ARegion *region;
1855 
1856  if (ELEM(NULL, st, st->text, st->text->curl)) {
1857  return;
1858  }
1859 
1861 
1862  if (region) {
1864  }
1865 }
1866 
1868 {
1869  ScrArea *area = CTX_wm_area(C);
1871 
1873 }
1874 
1876  ARegion *region,
1877  const int cursor_co[2],
1878  int r_pixel_co[2])
1879 {
1880  TextLine *line = NULL;
1881 
1882  if (!st->text) {
1883  goto error;
1884  }
1885 
1886  line = BLI_findlink(&st->text->lines, cursor_co[0]);
1887  if (!line || (cursor_co[1] < 0) || (cursor_co[1] > line->len)) {
1888  goto error;
1889  }
1890  else {
1891  int offl, offc;
1892  int linenr_offset = TXT_BODY_LEFT(st);
1893  /* handle tabs as well! */
1894  int char_pos = text_get_char_pos(st, line->line, cursor_co[1]);
1895 
1896  wrap_offset(st, region, line, cursor_co[1], &offl, &offc);
1897  r_pixel_co[0] = (char_pos + offc - st->left) * st->runtime.cwidth_px + linenr_offset;
1898  r_pixel_co[1] = (cursor_co[0] + offl - st->top) * TXT_LINE_HEIGHT(st);
1899  r_pixel_co[1] = (region->winy - (r_pixel_co[1] + (TXT_BODY_LPAD * st->runtime.cwidth_px))) -
1900  st->runtime.lheight_px;
1901  }
1902  return true;
1903 
1904 error:
1905  r_pixel_co[0] = r_pixel_co[1] = -1;
1906  return false;
1907 }
1908 
struct ScrArea * CTX_wm_area(const bContext *C)
Definition: context.c:738
struct bScreen * CTX_wm_screen(const bContext *C)
Definition: context.c:733
struct SpaceText * CTX_wm_space_text(const bContext *C)
Definition: context.c:806
struct ARegion * BKE_area_find_region_type(const struct ScrArea *area, int type)
struct ARegion struct ARegion struct ScrArea struct ScrArea * BKE_screen_find_big_area(struct bScreen *screen, int spacetype, short min)
Definition: screen.c:937
void txt_clean_text(struct Text *text)
Definition: text.c:633
int text_check_bracket(char ch)
Definition: text.c:2276
int txt_get_span(struct TextLine *from, struct TextLine *to)
Definition: text.c:676
int text_find_identifier_start(const char *str, int i)
Definition: text.c:2383
short texttool_text_is_active(struct Text *text)
SuggItem * texttool_suggest_last(void)
char * texttool_docs_get(void)
SuggItem * texttool_suggest_selected(void)
SuggItem * texttool_suggest_first(void)
int * texttool_suggest_top(void)
int BLF_draw_mono(int fontid, const char *str, size_t str_len, int cwidth) ATTR_NONNULL(2)
Definition: blf.c:550
float BLF_fixed_width(int fontid) ATTR_WARN_UNUSED_RESULT
Definition: blf.c:693
#define BLF_DRAW_STR_DUMMY_MAX
Definition: BLF_api.h:356
int blf_mono_font
Definition: blf.c:48
void BLF_size(int fontid, float size, int dpi)
Definition: blf.c:363
void BLF_position(int fontid, float x, float y, float z)
Definition: blf.c:308
#define BLI_assert(a)
Definition: BLI_assert.h:46
int BLI_findindex(const struct ListBase *listbase, const void *vlink) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void * BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
MINLINE int min_ii(int a, int b)
MINLINE int max_ii(int a, int b)
MINLINE int integer_digits_i(int i)
BLI_INLINE int BLI_rcti_size_y(const struct rcti *rct)
Definition: BLI_rect.h:190
BLI_INLINE int BLI_rcti_size_x(const struct rcti *rct)
Definition: BLI_rect.h:186
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
int BLI_str_utf8_char_width(const char *p) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition: string_utf8.c:378
#define BLI_UTF8_MAX
size_t size_t BLI_strnlen_utf8(const char *strc, size_t maxlen) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT
Definition: string_utf8.c:342
int BLI_str_utf8_char_width_safe(const char *p) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition: string_utf8.c:388
int BLI_str_utf8_offset_to_column(const char *str, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition: string_utf8.c:781
const char * BLI_str_find_prev_char_utf8(const char *p, const char *str_start) ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL ATTR_NONNULL(1
int BLI_str_utf8_size_safe(const char *p) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition: string_utf8.c:466
size_t size_t size_t int BLI_str_utf8_offset_to_index(const char *str, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition: string_utf8.c:761
unsigned int uint
Definition: BLI_sys_types.h:67
#define STREQLEN(a, b, n)
#define UNUSED(x)
#define MAX2(a, b)
#define ELEM(...)
#define MIN2(a, b)
#define MAX_ID_NAME
Definition: DNA_ID.h:337
@ RGN_TYPE_WINDOW
@ SPACE_TEXT
@ ST_SCROLL_SELECT
@ ST_SHOW_MARGIN
bool ED_text_activate_in_screen(struct bContext *C, struct Text *text)
bool ED_text_is_syntax_highlight_supported(struct Text *text)
Definition: text_format.c:202
bool ED_text_region_location_from_cursor(struct SpaceText *st, struct ARegion *region, const int cursor_co[2], int r_pixel_co[2])
void ED_text_scroll_to_cursor(struct SpaceText *st, struct ARegion *region, bool center)
NSNotificationCenter * center
void immUnbindProgram(void)
void immUniformThemeColor(int color_id)
void immUniformThemeColorShade(int color_id, int offset)
void immBindBuiltinProgram(eGPUBuiltinShader shader_id)
void immVertex2i(uint attr_id, int x, int y)
void immUniformColor4fv(const float rgba[4])
GPUVertFormat * immVertexFormat(void)
void immBegin(GPUPrimType, uint vertex_len)
void immEnd(void)
void immRecti(uint pos, int x1, int y1, int x2, int y2)
_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 const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble y1
_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 const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
_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 const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble top
@ GPU_PRIM_LINE_LOOP
Definition: GPU_primitive.h:23
@ GPU_SHADER_2D_UNIFORM_COLOR
Definition: GPU_shader.h:201
@ GPU_BLEND_NONE
Definition: GPU_state.h:60
@ GPU_BLEND_ALPHA
Definition: GPU_state.h:62
void GPU_blend(eGPUBlend blend)
Definition: gpu_state.cc:39
@ GPU_FETCH_INT_TO_FLOAT
uint GPU_vertformat_attr_add(GPUVertFormat *, const char *name, GPUVertCompType, uint comp_len, GPUVertFetchMode)
@ GPU_COMP_I32
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
#define MEM_reallocN(vmemh, len)
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position CLAMP
#define C
Definition: RandGen.cpp:25
@ UI_SCROLL_PRESSED
Definition: UI_interface.h:456
void UI_draw_roundbox_corner_set(int type)
void UI_draw_roundbox_aa(const struct rctf *rect, bool filled, float rad, const float color[4])
@ UI_CNR_ALL
void UI_draw_box_shadow(const struct rctf *rect, unsigned char alpha)
void UI_draw_widget_scroll(struct uiWidgetColors *wcol, const struct rcti *rect, const struct rcti *slider, int state)
void UI_GetThemeColor3fv(int colorid, float col[3])
Definition: resources.c:1165
@ TH_SYNTAX_B
Definition: UI_resources.h:123
@ TH_GRID
Definition: UI_resources.h:68
@ TH_BACK
Definition: UI_resources.h:39
@ TH_SYNTAX_C
Definition: UI_resources.h:126
@ TH_SYNTAX_R
Definition: UI_resources.h:125
@ TH_SYNTAX_S
Definition: UI_resources.h:130
@ TH_SHADE2
Definition: UI_resources.h:65
@ TH_LINENUMBERS
Definition: UI_resources.h:131
@ TH_SHADE1
Definition: UI_resources.h:64
@ TH_SYNTAX_D
Definition: UI_resources.h:128
@ TH_HILITE
Definition: UI_resources.h:66
@ TH_SYNTAX_V
Definition: UI_resources.h:124
@ TH_SYNTAX_L
Definition: UI_resources.h:127
@ TH_SYNTAX_N
Definition: UI_resources.h:129
@ TH_TEXT
Definition: UI_resources.h:42
struct bTheme * UI_GetTheme(void)
Definition: resources.c:1067
void UI_GetThemeColor4fv(int colorid, float col[4])
Definition: resources.c:1173
void UI_FontThemeColor(int fontid, int colorid)
Definition: resources.c:1134
#define ND_CURSOR
Definition: WM_types.h:438
#define NC_TEXT
Definition: WM_types.h:336
ATTR_WARN_UNUSED_RESULT const BMLoop * l
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
unsigned int U
Definition: btGjkEpa3.h:78
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition: btQuadWord.h:119
StackEntry * from
int len
Definition: draw_manager.c:108
#define str(s)
uint pos
uint col
uint padding(uint offset, uint alignment)
format
Definition: logImageCore.h:38
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
static void error(const char *str)
Definition: meshlaplacian.c:51
static unsigned c
Definition: RandGen.cpp:83
static unsigned a[3]
Definition: RandGen.cpp:78
static struct PartialUpdateUser * wrap(PartialUpdateUserImpl *user)
static void area(int d1, int d2, int e1, int e2, float weights[2])
static const pxr::TfToken st("st", pxr::TfToken::Immortal)
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
return ret
char name[66]
Definition: DNA_ID.h:378
void * last
Definition: DNA_listBase.h:31
void * first
Definition: DNA_listBase.h:31
struct SuggItem * next
bool syntax_highlight
Definition: text_draw.c:47
void(* format_line)(SpaceText *st, TextLine *line, bool do_next)
Definition: text_format.h:75
char * format
char * line
struct TextLine * prev
struct TextLine * next
ListBase lines
TextLine * curl
int selc
TextLine * sell
int curc
uiWidgetColors wcol_scroll
ThemeUI tui
int ymin
Definition: DNA_vec_types.h:64
int ymax
Definition: DNA_vec_types.h:64
int xmin
Definition: DNA_vec_types.h:63
int xmax
Definition: DNA_vec_types.h:63
void text_pop_suggest_list(void)
static int text_font_draw(const TextDrawContext *tdc, int x, int y, const char *str)
Definition: text_draw.c:67
static void text_font_end(const TextDrawContext *UNUSED(tdc))
Definition: text_draw.c:63
static int text_font_draw_character(const TextDrawContext *tdc, int x, int y, char c)
Definition: text_draw.c:75
struct TextDrawContext TextDrawContext
static int text_font_draw_character_utf8(const TextDrawContext *tdc, int x, int y, const char *c, const int c_len)
Definition: text_draw.c:83
static void text_font_begin(const TextDrawContext *tdc)
Definition: text_draw.c:58
static void text_draw_context_init(const SpaceText *st, TextDrawContext *tdc)
Definition: text_draw.c:50
static void format_draw_color(const TextDrawContext *tdc, char formatchar)
Definition: text_draw.c:110
int flatten_string(const SpaceText *st, FlattenString *fs, const char *in)
Definition: text_format.c:56
void flatten_string_free(FlattenString *fs)
Definition: text_format.c:89
TextFormatType * ED_text_format_get(Text *text)
Definition: text_format.c:172
@ FMT_TYPE_DIRECTIVE
Definition: text_format.h:92
@ FMT_TYPE_STRING
Definition: text_format.h:90
@ FMT_TYPE_COMMENT
Definition: text_format.h:84
@ FMT_TYPE_SPECIAL
Definition: text_format.h:94
@ FMT_TYPE_DEFAULT
Definition: text_format.h:100
@ FMT_TYPE_KEYWORD
Definition: text_format.h:98
@ FMT_TYPE_WHITESPACE
Definition: text_format.h:82
@ FMT_TYPE_NUMERAL
Definition: text_format.h:88
@ FMT_TYPE_RESERVED
Definition: text_format.h:96
@ FMT_TYPE_SYMBOL
Definition: text_format.h:86
#define SUGG_LIST_WIDTH
Definition: text_intern.h:56
int text_get_span_wrap(const struct SpaceText *st, struct ARegion *region, struct TextLine *from, struct TextLine *to)
#define TXT_LINE_SPACING(st)
Definition: text_intern.h:51
void text_free_caches(struct SpaceText *st)
#define TXT_LINE_HEIGHT(st)
Definition: text_intern.h:53
void text_scroll_to_cursor__area(struct SpaceText *st, struct ScrArea *area, bool center)
int text_get_total_lines(struct SpaceText *st, struct ARegion *region)
#define DOC_WIDTH
Definition: text_intern.h:57
#define TXT_NUMCOL_WIDTH(st)
Definition: text_intern.h:36
void text_update_cursor_moved(struct bContext *C)
void wrap_offset_in_line(const struct SpaceText *st, struct ARegion *region, struct TextLine *linein, int cursin, int *offl, int *offc)
#define DOC_HEIGHT
Definition: text_intern.h:58
void wrap_offset(const struct SpaceText *st, struct ARegion *region, struct TextLine *linein, int cursin, int *offl, int *offc)
#define TXT_NUMCOL_PAD
Definition: text_intern.h:34
int wrap_width(const struct SpaceText *st, struct ARegion *region)
#define SUGG_LIST_SIZE
Definition: text_intern.h:55
#define TXT_BODY_LEFT(st)
Definition: text_intern.h:42
#define TXT_SCROLL_WIDTH
Definition: text_intern.h:45
void draw_text_main(struct SpaceText *st, struct ARegion *region)
int text_get_visible_lines(const struct SpaceText *st, struct ARegion *region, const char *str)
#define TXT_BODY_LPAD
Definition: text_intern.h:40
void text_drawcache_tag_update(struct SpaceText *st, int full)
int text_get_char_pos(const struct SpaceText *st, const char *line, int cur)
void text_update_character_width(struct SpaceText *st)
float max
void WM_event_add_notifier(const bContext *C, uint type, void *reference)