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