ARB
AW_preset.cxx
Go to the documentation of this file.
1 // ================================================================ //
2 // //
3 // File : AW_preset.cxx //
4 // Purpose : //
5 // //
6 // Institute of Microbiology (Technical University Munich) //
7 // http://www.arb-home.de/ //
8 // //
9 // ================================================================ //
10 
11 #ifndef IN_ARB_WINDOW
12 #error MODULE_... is not known
13 #endif
14 
15 #include <aw_color_groups.hxx>
16 #include "aw_preset.hxx"
17 #include "aw_root.hxx"
18 #include "aw_awar.hxx"
19 #include "aw_device.hxx"
20 #include "aw_advice.hxx"
21 #include "aw_question.hxx"
22 #include "aw_msg.hxx"
23 
24 #include "aw_def.hxx"
25 #include "aw_nawar.hxx"
26 #include "aw_xfont.hxx"
27 #include "aw_rgb.hxx"
28 
29 #include <arbdbt.h>
30 #include <arb_strbuf.h>
31 
32 #include <vector>
33 #include <map>
34 #include <string>
35 
36 #if defined(DEBUG)
37 #include <ctime>
38 #endif
39 
40 
41 using std::string;
42 
43 #define AWAR_RANGE_OVERLAY "tmp/GCS/range/overlay" // global toggle (used for all gc-managers!)
44 #define AWAR_COLOR_GROUPS_PREFIX "colorGroups" // [Note: before arb-7.0 the prefix was "color_groups"]
45 #define AWAR_COLOR_GROUPS_USE AWAR_COLOR_GROUPS_PREFIX "/use" // int : whether to use the colors in display or not
46 
47 #define ATPL_GCMAN_LOCAL "GCS/%s" // awar prefix for awars local to gc-manager
48 #define ATPL_GC_LOCAL ATPL_GCMAN_LOCAL "/MANAGE_GCS/%s" // awar prefix for awars local to a single gc
49 
50 #define ALL_FONTS_ID "all_fonts"
51 
52 #define NO_FONT -1
53 #define NO_SIZE -2
54 
55 // prototypes for motif-only section at bottom of this file:
56 static void aw_create_color_chooser_window(AW_window *aww, const char *awar_name, const char *color_description);
57 static void aw_create_font_chooser_window(AW_window *aww, const char *gc_base_name, const struct gc_desc *gcd);
58 
59 CONSTEXPR_INLINE bool valid_color_group(int color_group) {
60  return color_group>0 && color_group<=AW_COLOR_GROUPS;
61 }
62 
63 inline const char* gcman_specific_awarname(const char *tpl, const char *gcman_id, const char *localpart) {
64  aw_assert(!GB_check_key(gcman_id)); // has to be a key
65  aw_assert(!GB_check_hkey(localpart)); // has to be a key or hierarchical key
66 
67  static SmartCharPtr awar_name;
68  awar_name = GBS_global_string_copy(tpl, gcman_id, localpart);
69  return &*awar_name;
70 }
71 inline const char* gc_awarname(const char *tpl, const char *gcman_id, const string& colname) {
72  return gcman_specific_awarname(tpl, gcman_id, colname.c_str());
73 }
74 inline const char* gcman_awarname(const char* gcman_id, const char *localpart) {
75  return gcman_specific_awarname(ATPL_GCMAN_LOCAL "/%s", gcman_id, localpart);
76 }
77 
78 inline const char* color_awarname (const char* gcman_id, const string& colname) { return gc_awarname(ATPL_GC_LOCAL "/colorname", gcman_id, colname); }
79 inline const char* fontname_awarname(const char* gcman_id, const string& colname) { return gc_awarname(ATPL_GC_LOCAL "/font", gcman_id, colname); }
80 inline const char* fontsize_awarname(const char* gcman_id, const string& colname) { return gc_awarname(ATPL_GC_LOCAL "/size", gcman_id, colname); }
81 inline const char* fontinfo_awarname(const char* gcman_id, const string& colname) { return gc_awarname(ATPL_GC_LOCAL "/info", gcman_id, colname); }
82 
83 // ----------------------
84 // color groups
85 
86 struct ColorGroupDef {
87  const char *description;
88  const char *rgb_nt;
89  const char *rgb_e4;
90 
91  const char *defaultColorgroupName(int color_group) {
92  const char *result = NULp;
93  if (valid_color_group(color_group)) {
94  if (color_group<10) {
95  result = GBS_global_string(AW_COLOR_GROUP_PREFIX "_%i_%s", color_group, description);
96  }
97  else {
98  result = GBS_global_string(AW_COLOR_GROUP_PREFIX "%2i_%s", color_group, description);
99  }
100  }
101  return result;
102  }
103 
104  const char *rgbValue(bool for_edit4) {
105  return for_edit4 ? rgb_e4 : rgb_nt;
106  }
107 };
108 
110  // name NTREE EDIT4
111  // rrggbb rrggbb
112  { "red", "D50000", "FFDCDC" }, // 01
113  { "cyan", "00ffff", "CFFFFF" }, // 02
114  { "green", "00FF77", "B1FFD6" }, // 03
115  { "purple", "c700c7", "F1BFF1" }, // 04
116  { "blue", "0000ff", "D7D7FF" }, // 05
117  { "orange", "FFCE5B", "FFEAB9" }, // 06
118  { "dark_red", "AB2323", "DCB8B8" }, // 07
119  { "petrol", "008888", "8BBBBB" }, // 08
120  { "dark_green", "008800", "97CB97" }, // 09
121  { "dark_purple", "880088", "B177B1" }, // 10
122  { "dark_blue", "000088", "9898E2" }, // 11
123  { "olive", "888800", "C8D98F" }, // 12
124 };
125 
126 inline const char *colorgroupname_awarname(int color_group) {
127  if (!valid_color_group(color_group)) return NULp;
128  return GBS_global_string(AWAR_COLOR_GROUPS_PREFIX "/name%i", color_group);
129 }
130 inline const char* default_colorgroup_name(int color_group) {
131  return color_group_def[color_group-1].defaultColorgroupName(color_group);
132 }
133 
134 
135 const int GC_BACKGROUND = -1;
136 const int GC_INVALID = -2;
137 
138 const int NO_INDEX = -1;
139 
140 enum gc_type {
144 };
145 
146 #define RANGE_INDEX_BITS 4
147 #define RANGE_INDEX_MASK ((1<<RANGE_INDEX_BITS)-1)
148 
149 inline int build_range_gc_number(int range_idx, int color_idx) {
150  aw_assert(range_idx == (range_idx & RANGE_INDEX_MASK));
151  return (color_idx << RANGE_INDEX_BITS) | range_idx;
152 }
153 
154 inline string name2ID(const char *name) { // does not test uniqueness!
155  char *keyCopy = GBS_string_2_key(name);
156  string id = keyCopy;
157  free(keyCopy);
158  return id;
159 }
160 inline string name2ID(const string& name) { return name2ID(name.c_str()); }
161 
162 struct gc_desc {
163  // data for one GC
164  // - used to populate color config windows and
165  // - in change-callbacks
166 
167  int gc; // -1 = background;
168  // if type!=GC_TYPE_RANGE: [0..n-1] (where n=AW_gc_manager::drag_gc_offset if no gc_ranges defined)
169  // if type==GC_TYPE_RANGE: contains range- and color-index
170  string colorlabel; // label to appear next to chooser
171  string key; // key (normally build from colorlabel)
172  bool has_font; // show font selector
173  bool fixed_width_font; // only allow fixed width fonts
174  bool same_line; // no line break after this
176 
177  gc_desc(int gc_, gc_type type_) :
178  gc(gc_),
179  has_font(true),
180  fixed_width_font(false),
181  same_line(false),
182  type(type_)
183  {}
184 
185  bool is_color_group() const { return type == GC_TYPE_GROUP; }
186  bool belongs_to_range() const { return type == GC_TYPE_RANGE; }
187 
189  int get_color_index() const { aw_assert(belongs_to_range()); return gc >> RANGE_INDEX_BITS; }
190 
191 private:
192  bool parse_char(char c) {
193  switch (c) {
194  case '#': fixed_width_font = true; break;
195  case '+': same_line = true; break;
196  case '-': has_font = false; break;
197  default : return false;
198  }
199  return true;
200  }
201 
202  void correct() {
203  if (same_line && has_font) same_line = false; // GC needs full line if defining both color and font
204  }
205 public:
206 
207  const char *parse_decl(const char *decl, const char *id_prefix) {
208  // returns default color
209  int offset = 0;
210  while (decl[offset]) {
211  if (!parse_char(decl[offset])) break;
212  offset++;
213  }
214  correct();
215 
216  decl += offset;
217 
218  const char *split = strchr(decl, '$');
219  const char *default_color = NULp;
220  if (split) { // defines a default color
221  colorlabel = string(decl, split-decl);
222  default_color = split+1;
223  }
224  else {
225  colorlabel = decl;
226  default_color = "black";
227  }
228 
229  key = string(null2empty(id_prefix)) + name2ID(colorlabel);
230 
231  return default_color;
232  }
233 };
234 
235 // --------------------------------
236 // types for color-ranges
237 
244 };
245 
246 class gc_range {
247  string name; // name of range shown in config window
248  string id;
249  gc_range_type type;
250 
251  int index; // in range-array of AW_gc_manager
252  int color_count; // number of support colors (ie. customizable colors)
253  int gc_index; // of first support color in GCs-array of AW_gc_manager
254 
255 public:
256  gc_range(const string& name_, gc_range_type type_, int index_, int gc_index_) :
257  name(name_),
258  id(name2ID(name)),
259  type(type_),
260  index(index_),
261  color_count(0),
262  gc_index(gc_index_)
263  {}
264 
265  void add_color(const string& colordef, AW_gc_manager *gcman);
266  void update_colors(const AW_gc_manager *gcman) const;
267 
268  AW_rgb_normalized get_color(int idx, const AW_gc_manager *gcman) const;
269 
270  const string& get_name() const { return name; }
271  const string& get_id() const { return id; }
272  gc_range_type get_type() const { return type; }
273  int get_dimension() const {
274  switch (type) {
275  case GC_RANGE_LINEAR:
276  case GC_RANGE_CYCLIC: return 1;
277 
278  case GC_RANGE_PLANAR: return 2;
279  case GC_RANGE_SPATIAL: return 3;
280  case GC_RANGE_INVALID: aw_assert(0); break;
281  }
282  return 0;
283  }
284 };
285 
286 // --------------------
287 // GC manager
288 
289 class AW_gc_manager : virtual Noncopyable {
290  const char *gc_base_name;
291  AW_device *device;
292  int drag_gc_offset; // = drag_gc (as used by clients)
293 
294  int first_colorgroup_idx; // index into 'GCs' or NO_INDEX (if no color groups defined)
295 
296  AW_window *aww; // motif only (colors get allocated in window)
297  int colorindex_base; // motif-only (colorindex of background-color)
298 
299  typedef std::vector<gc_desc> gc_container;
300  typedef std::vector<gc_range> gc_range_container;
301 
302  gc_container GCs;
303  gc_range_container color_ranges;
304  unsigned active_range_number; // offset into 'color_ranges'
305 
306  GcChangedCallback changed_cb;
307 
308  mutable bool suppress_changed_cb; // if true -> collect cb-trigger in 'did_suppress_change'
309  mutable GcChange did_suppress_change; // "max" change suppressed so far (will be triggered by delay_changed_callbacks())
310  static const GcChange GC_NOTHING_CHANGED = GcChange(0);
311 
312 #if defined(ASSERTION_USED)
313  bool valid_idx(int idx) const { return idx>=0 && idx<int(GCs.size()); }
314  bool valid_gc(int gc) const {
315  // does not test gc is really valid, just tests whether it is completely out-of-bounds
316  return gc>=GC_BACKGROUND && gc < drag_gc_offset;
317  }
318 #endif
319 
320  AW_color_idx colorindex(int gc) const {
321  aw_assert(valid_gc(gc));
322  return AW_color_idx(colorindex_base+gc+1);
323  }
324  static void ignore_change_cb(GcChange) {}
325 
326  void allocate_gc(int gc) const;
327 
328  void update_gc_color_internal(int gc, const char *color) const;
329  void update_range_colors(const gc_desc& gcd) const;
330  void update_range_font(int fname, int fsize) const;
331 
332 public:
333  static const char **color_group_defaults;
334 
335  static bool use_color_groups;
336  static bool show_range_overlay;
337 
339 
340  AW_gc_manager(const char* name, AW_device* device_, int drag_gc_offset_,
341  AW_window *aww_, int colorindex_base_)
342  : gc_base_name(name),
343  device(device_),
344  drag_gc_offset(drag_gc_offset_),
345  first_colorgroup_idx(NO_INDEX),
346  aww(aww_),
347  colorindex_base(colorindex_base_),
348  active_range_number(-1), // => will be initialized from init_color_ranges
349  changed_cb(makeGcChangedCallback(ignore_change_cb)),
350  suppress_changed_cb(false),
351  did_suppress_change(GC_NOTHING_CHANGED)
352  {}
353 
354  void init_all_fonts() const;
355  void update_all_fonts(bool sizeChanged) const;
356 
357  void init_color_ranges(int& gc);
358  bool has_color_range() const { return !color_ranges.empty(); }
359  int first_range_gc() const { return drag_gc_offset - AW_RANGE_COLORS; }
360 
361  bool has_color_groups() const { return first_colorgroup_idx != NO_INDEX; }
362  bool has_variable_width_font() const;
363 
364  int size() const { return GCs.size(); }
365  const gc_desc& get_gc_desc(int idx) const {
366  aw_assert(valid_idx(idx));
367  return GCs[idx];
368  }
369  const char *get_base_name() const { return gc_base_name; }
370  int get_drag_gc() const { return drag_gc_offset; }
371 
372  void add_gc (const char *gc_description, int& gc, gc_type type, const char *id_prefix = NULp);
373  void add_gc_range(const char *gc_description);
374  void reserve_gcs (const char *gc_description, int& gc);
375  void add_color_groups(int& gc);
376 
377  void update_gc_color(int idx) const;
378  void update_gc_font(int idx) const;
379 
380  void update_range_gc_color(int idx, const char *color) const {
381  update_gc_color_internal(first_range_gc()+idx, color);
382  }
383 
384  void create_gc_buttons(AW_window *aww, gc_type for_gc_type);
385 
386  void set_changed_cb(const GcChangedCallback& ccb) { changed_cb = ccb; }
387  void trigger_changed_cb(GcChange whatChanged) const {
388  if (suppress_changed_cb) {
389  did_suppress_change = GcChange(std::max(whatChanged, did_suppress_change));
390  }
391  else {
392 #if defined(DEBUG) && 0
393  fprintf(stderr, "[changed_cb] @ %zu\n", clock());
394 #endif
395  changed_cb(whatChanged);
396  }
397  }
398 
399  void delay_changed_callbacks(bool suppress) const {
400  aw_assert(suppress != suppress_changed_cb);
401 
402  suppress_changed_cb = suppress;
403  if (suppress) {
404  did_suppress_change = GC_NOTHING_CHANGED;
405  }
406  else if (did_suppress_change>GC_NOTHING_CHANGED) {
407  trigger_changed_cb(did_suppress_change);
408  }
409  }
410 
411  const char *get_current_color(int idx) const {
413  }
414 
415  void getColorRangeNames(int dimension, ConstStrArray& ids, ConstStrArray& names) const;
416  void activateColorRange(const char *id);
417  const char *getActiveColorRangeID(int *dimension) const;
418 
419  const char *awarname_active_range() const { return gcman_awarname(get_base_name(), "range/active"); }
420  void active_range_changed_cb(AW_root *awr);
421 };
422 
424 
427 
428 // ---------------------------
429 // GC awar callbacks
430 
431 void AW_gc_manager::update_gc_font(int idx) const {
432  aw_assert(valid_idx(idx));
433 
434  static bool avoid_recursion = false;
435  if (avoid_recursion) return;
436  LocallyModify<bool> flag(avoid_recursion, true);
437 
438  const gc_desc& gcd0 = GCs[idx];
439  aw_assert(gcd0.gc != GC_BACKGROUND); // background has no font
440 
441  AW_awar *awar_fontname = AW_root::SINGLETON->awar(fontname_awarname(gc_base_name, gcd0.key));
442  AW_awar *awar_fontsize = AW_root::SINGLETON->awar(fontsize_awarname(gc_base_name, gcd0.key));
443  AW_awar *awar_fontinfo = AW_root::SINGLETON->awar(fontinfo_awarname(gc_base_name, gcd0.key));
444 
445  int fname = awar_fontname->read_int();
446  int fsize = awar_fontsize->read_int();
447 
448  if (fname == NO_FONT) return;
449 
450  int found_font_size;
451  device->set_font(gcd0.gc, fname, fsize, &found_font_size);
452  device->set_font(gcd0.gc+drag_gc_offset, fname, fsize, NULp);
453 
454  bool autocorrect_fontsize = (found_font_size != fsize) && (found_font_size != -1);
455  if (autocorrect_fontsize) {
456  awar_fontsize->write_int(found_font_size);
457  fsize = found_font_size;
458  }
459 
460  // set font of all following GCs which do NOT define a font themselves
461  for (int i = idx+1; i<int(GCs.size()); ++i) {
462  const gc_desc& gcd = GCs[i];
463  if (gcd.has_font) break; // abort if GC defines its own font
464  if (gcd.belongs_to_range()) {
465  update_range_font(fname, fsize);
466  break; // all leftover GCs belong to ranges = > stop here
467  }
468 
469  device->set_font(gcd.gc, fname, fsize, NULp);
470  device->set_font(gcd.gc+drag_gc_offset, fname, fsize, NULp);
471  }
472 
473  awar_fontinfo->write_string(GBS_global_string("%s | %i", AW_get_font_shortname(fname), fsize));
474 
476 }
477 static void gc_fontOrSize_changed_cb(AW_root*, AW_gc_manager *mgr, int idx) {
478  mgr->update_gc_font(idx);
479 }
480 inline bool font_has_fixed_width(AW_font aw_font_nr) {
481  return AW_font_2_xfig(aw_font_nr) < 0;
482 }
483 void AW_gc_manager::update_all_fonts(bool sizeChanged) const {
485 
486  int fname = awr->awar(fontname_awarname(gc_base_name, ALL_FONTS_ID))->read_int();
487  int fsize = awr->awar(fontsize_awarname(gc_base_name, ALL_FONTS_ID))->read_int();
488 
489  if (fname == NO_FONT) return;
490 
491  delay_changed_callbacks(true); // temp. disable callbacks
492  for (gc_container::const_iterator g = GCs.begin(); g != GCs.end(); ++g) {
493  if (g->has_font) {
494  if (sizeChanged) {
495  awr->awar(fontsize_awarname(gc_base_name, g->key))->write_int(fsize);
496  }
497  else {
498  bool update = !g->fixed_width_font || font_has_fixed_width(fname);
499  if (update) awr->awar(fontname_awarname(gc_base_name, g->key))->write_int(fname);
500  }
501  }
502  }
504 }
505 static void all_fontsOrSizes_changed_cb(AW_root*, const AW_gc_manager *mgr, bool sizeChanged) {
506  mgr->update_all_fonts(sizeChanged);
507 }
508 
509 void AW_gc_manager::update_gc_color_internal(int gc, const char *color) const {
510  AW_color_idx colorIdx = colorindex(gc);
511  aww->alloc_named_data_color(colorIdx, color);
512 
513  if (gc == GC_BACKGROUND && colorIdx == AW_DATA_BG) {
514  // if background color changes, all drag-gc colors need to be updated
515  // (did not understand why, just refactored existing code --ralf)
516 
517  for (int i = 1; i<size(); ++i) {
518  const gc_desc& gcd = GCs[i];
519  if (gcd.belongs_to_range()) break; // do not update range-GCs here
520 
521  int g = gcd.gc;
522  colorIdx = colorindex(g);
523  device->set_foreground_color(g + drag_gc_offset, colorIdx);
524  }
525  if (has_color_range()) { // update drag GCs of all range GCs
526  for (int i = 0; i<AW_RANGE_COLORS; ++i) {
527  int g = first_range_gc()+i;
528  colorIdx = colorindex(g);
529  device->set_foreground_color(g + drag_gc_offset, colorIdx);
530  }
531  }
532  }
533  else {
534  if (gc == GC_BACKGROUND) gc = 0; // special case: background color of bottom-area (only used by arb_phylo)
535 
536  device->set_foreground_color(gc, colorIdx);
537  device->set_foreground_color(gc + drag_gc_offset, colorIdx);
538  }
539 }
540 
542  aw_assert(idx>=0 && idx<color_count);
543  return AW_rgb_normalized(gcman->get_current_color(gc_index+idx));
544 }
545 
546 STATIC_ASSERT(AW_PLANAR_COLORS*AW_PLANAR_COLORS == AW_RANGE_COLORS); // Note: very strong assertion (could also use less than AW_RANGE_COLORS)
548 
549 void gc_range::update_colors(const AW_gc_manager *gcman) const {
554  // @@@ try HSV color blending as alternative
555 
556  if (type == GC_RANGE_LINEAR) {
557  aw_assert(color_count == 2); // currently exactly 2 support-colors are required for linear ranges
558 
559  AW_rgb_normalized low = get_color(0, gcman);
560  AW_rgb_normalized high = get_color(1, gcman);
561 
562  AW_rgb_diff low2high = high-low;
563  for (int i = 0; i<AW_RANGE_COLORS; ++i) { // blend colors
564  float factor = i/float(AW_RANGE_COLORS-1);
565  gcman->update_range_gc_color(i, AW_rgb16(low + factor*low2high).ascii());
566  }
567  }
568  else if (type == GC_RANGE_CYCLIC) {
569  aw_assert(color_count >= 3); // less than 3 colors does not make sense for cyclic ranges!
570 
571  AW_rgb_normalized low = get_color(0, gcman);
572  int i1 = 0;
573  for (int part = 0; part<color_count; ++part) {
574  AW_rgb_normalized high = get_color((part+1)%color_count, gcman);
575  AW_rgb_diff low2high = high-low;
576 
577  int i2 = AW_RANGE_COLORS * (float(part+1)/color_count);
578  aw_assert(implicated((part+1) == color_count, i2 == AW_RANGE_COLORS));
579 
580  for (int i = i1; i<i2; ++i) { // blend colors
581  int o = i-i1;
582  float factor = o/float(i2-i1-1);
583  gcman->update_range_gc_color(i, AW_rgb16(low + factor*low2high).ascii());
584  }
585 
586  low = high;
587  i1 = i2;
588  }
589  }
590  else if (type == GC_RANGE_PLANAR) {
591  aw_assert(color_count == 3); // currently exactly 3 support-colors are required for planar ranges
592 
593  AW_rgb_normalized low = get_color(0, gcman);
594  AW_rgb_normalized dim1 = get_color(1, gcman);
595  AW_rgb_normalized dim2 = get_color(2, gcman);
596 
597  AW_rgb_diff low2dim1 = dim1-low;
598  AW_rgb_diff low2dim2 = dim2-low;
599 
600  for (int i1 = 0; i1<AW_PLANAR_COLORS; ++i1) {
601  float fact1 = i1/float(AW_PLANAR_COLORS-1);
602  AW_rgb_diff diff1 = fact1*low2dim1;
603 
604  for (int i2 = 0; i2<AW_PLANAR_COLORS; ++i2) {
605  float fact2 = i2/float(AW_PLANAR_COLORS-1);
606  AW_rgb_diff diff2 = fact2*low2dim2;
607 
608  AW_rgb_normalized mixcol = low + (diff1+diff2);
609 
610  gcman->update_range_gc_color(i1*AW_PLANAR_COLORS+i2, AW_rgb16(mixcol).ascii());
611  }
612  }
613  }
614  else if (type == GC_RANGE_SPATIAL) {
615  aw_assert(color_count == 4); // currently exactly 4 support-colors are required for planar ranges
616 
617  AW_rgb_normalized low = get_color(0, gcman);
618  AW_rgb_normalized dim1 = get_color(1, gcman);
619  AW_rgb_normalized dim2 = get_color(2, gcman);
620  AW_rgb_normalized dim3 = get_color(3, gcman);
621 
622  AW_rgb_diff low2dim1 = dim1-low;
623  AW_rgb_diff low2dim2 = dim2-low;
624  AW_rgb_diff low2dim3 = dim3-low;
625 
626  for (int i1 = 0; i1<AW_SPATIAL_COLORS; ++i1) {
627  float fact1 = i1/float(AW_SPATIAL_COLORS-1);
628  AW_rgb_diff diff1 = fact1*low2dim1;
629 
630  for (int i2 = 0; i2<AW_SPATIAL_COLORS; ++i2) {
631  float fact2 = i2/float(AW_SPATIAL_COLORS-1);
632  AW_rgb_diff diff2 = fact2*low2dim2;
633 
634  for (int i3 = 0; i3<AW_SPATIAL_COLORS; ++i3) {
635  float fact3 = i3/float(AW_SPATIAL_COLORS-1);
636  AW_rgb_diff diff3 = fact3*low2dim3;
637 
638  AW_rgb_normalized mixcol = low + (diff1+diff2+diff3);
639  gcman->update_range_gc_color((i1*AW_SPATIAL_COLORS+i2)*AW_SPATIAL_COLORS+i3, AW_rgb16(mixcol).ascii());
640  }
641  }
642  }
643  }
644  else {
645  aw_assert(0); // unsupported range-type
646  }
647 }
648 void AW_gc_manager::update_range_colors(const gc_desc& gcd) const {
649  int defined_ranges = color_ranges.size();
650  int range_idx = gcd.get_range_index();
651 
652  if (range_idx<defined_ranges) {
653  const gc_range& gcr = color_ranges[range_idx];
654  gcr.update_colors(this);
655  }
656 }
657 void AW_gc_manager::update_range_font(int fname, int fsize) const {
658  // set font for all GCs belonging to color-range
659  int first_gc = first_range_gc();
660  for (int i = 0; i<AW_RANGE_COLORS; ++i) {
661  int gc = first_gc+i;
662  device->set_font(gc, fname, fsize, NULp);
663  device->set_font(gc+drag_gc_offset, fname, fsize, NULp);
664  }
665 }
666 
667 void AW_gc_manager::update_gc_color(int idx) const {
668  aw_assert(valid_idx(idx));
669 
670  const gc_desc& gcd = GCs[idx];
671  const char *color = AW_root::SINGLETON->awar(color_awarname(gc_base_name, gcd.key))->read_char_pntr();
672 
673  if (gcd.belongs_to_range()) {
674  update_range_colors(gcd); // @@@ should not happen during startup and only if affected range is the active range
675  }
676  else {
677  update_gc_color_internal(gcd.gc, color);
678  }
679 
681 }
682 static void gc_color_changed_cb(AW_root*, AW_gc_manager *mgr, int idx) {
683  mgr->update_gc_color(idx);
684 }
685 
687  static bool warned = false;
688  if (!warned) {
689  AW_advice("Color group names are used at various places of the interface.\n"
690  "To activate the changed names everywhere, you have to\n"
691  "save properties and restart the program.",
692  AW_ADVICE_TOGGLE, "Color group name has been changed", NULp);
693  warned = true;
694  }
695 
696  for (int i = 1; i <= AW_COLOR_GROUPS; ++i) {
697  const char *awarname = colorgroupname_awarname(i);
698  AW_awar *awar_colorgroupname = awr->awar(awarname);
699  char *content = awar_colorgroupname->read_string();
700  size_t len = strlen(content);
701  if (len>AW_COLOR_GROUP_NAME_LEN) {
702  content[AW_COLOR_GROUP_NAME_LEN] = 0;
703  awar_colorgroupname->write_string(content);
704  aw_message("the colorgroup name was too long and has been truncated.");
705  }
706  free(content);
707  }
708 }
709 
711  AW_gc_manager::use_color_groups = awr->awar(AWAR_COLOR_GROUPS_USE)->read_int();
713 }
714 static void range_overlay_changed_cb(AW_root *awr, AW_gc_manager *gcmgr) {
715  AW_gc_manager::show_range_overlay = awr->awar(AWAR_RANGE_OVERLAY)->read_int();
717 }
718 
719 // ----------------------------
720 // define color-ranges
721 
722 void gc_range::add_color(const string& colordef, AW_gc_manager *gcman) {
723  int gc = build_range_gc_number(index, color_count);
724  gcman->add_gc(colordef.c_str(), gc, GC_TYPE_RANGE, get_id().c_str());
725  color_count++;
726 }
727 
728 void AW_gc_manager::add_gc_range(const char *gc_description) {
729  GB_ERROR error = NULp;
730  const char *comma = strchr(gc_description+1, ',');
731  if (!comma) error = "',' expected";
732  else {
733  string range_name(gc_description+1, comma-gc_description-1);
734  const char *colon = strchr(comma+1, ':');
735  if (!colon) error = "':' expected";
736  else {
738  string range_type(comma+1, colon-comma-1);
739 
740  if (range_type == "linear") rtype = GC_RANGE_LINEAR;
741  else if (range_type == "planar") rtype = GC_RANGE_PLANAR;
742  else if (range_type == "spatial") rtype = GC_RANGE_SPATIAL;
743  else if (range_type == "cyclic") rtype = GC_RANGE_CYCLIC;
744 
745  if (rtype == GC_RANGE_INVALID) {
746  error = GBS_global_string("invalid range-type '%s'", range_type.c_str());
747  }
748 
749  if (!error) {
750  gc_range range(range_name, rtype, color_ranges.size(), GCs.size());
751 
752  const char *color_start = colon+1;
753  comma = strchr(color_start, ',');
754  while (comma) {
755  range.add_color(string(color_start, comma-color_start), this);
756  color_start = comma+1;
757  comma = strchr(color_start, ',');
758  }
759  range.add_color(string(color_start), this);
760 
761  color_ranges.push_back(range); // add to manager
762  }
763  }
764  }
765 
766  if (error) {
767  GBK_terminatef("Failed to parse color range specification '%s'\n(Reason: %s)", gc_description, error);
768  }
769 }
770 
772  // read AWAR (awarname_active_range), compare with 'active_range_number', if differs = > update colors
773  // (triggered by AWAR)
774 
775  unsigned wanted_range_number = awr->awar(awarname_active_range())->read_int();
776  if (wanted_range_number != active_range_number) {
777  aw_assert(wanted_range_number<color_ranges.size());
778 
779  active_range_number = wanted_range_number;
780  const gc_range& active_range = color_ranges[active_range_number];
781  active_range.update_colors(this);
782  }
783 }
784 static void active_range_changed_cb(AW_root *awr, AW_gc_manager *gcman) { gcman->active_range_changed_cb(awr); }
785 
787  if (has_color_range()) {
788  aw_assert(gc == first_range_gc()); // 'drag_gc_offset' is wrong (is passed as 'base_drag' to AW_manage_GC)
789  int last_gc = gc + AW_RANGE_COLORS-1;
790  while (gc<=last_gc) allocate_gc(gc++);
791 
792  active_range_changed_cb(AW_root::SINGLETON); // either initializes default-range (=0) or the range-in-use when saving props
793  }
794 }
795 void AW_gc_manager::activateColorRange(const char *id) {
796  unsigned wanted_range_number = 0;
797  for (gc_range_container::const_iterator r = color_ranges.begin(); r != color_ranges.end(); ++r) {
798  const gc_range& range = *r;
799  if (range.get_id() == id) {
800  aw_assert(wanted_range_number<color_ranges.size());
801  AW_root::SINGLETON->awar(awarname_active_range())->write_int(wanted_range_number); // => will update color range of all identical gc-managers
802  break;
803  }
804  ++wanted_range_number;
805  }
806 }
807 const char *AW_gc_manager::getActiveColorRangeID(int *dimension) const {
808  const gc_range& range = color_ranges[active_range_number];
809  if (dimension) *dimension = range.get_dimension();
810  return range.get_id().c_str();
811 }
812 
813 
815  for (gc_range_container::const_iterator r = color_ranges.begin(); r != color_ranges.end(); ++r) {
816  const gc_range& range = *r;
817  if (range.get_dimension() == dimension) {
818  ids.put(range.get_id().c_str());
819  names.put(range.get_name().c_str());
820  }
821  }
822 }
823 
824 // -------------------------
825 // reserve/add GCs
826 
827 void AW_gc_manager::reserve_gcs(const char *gc_description, int& gc) {
828  aw_assert(gc_description[0] == '!');
829 
830  // just reserve one or several GCs (eg. done in arb_pars)
831  int amount = atoi(gc_description+1);
832  aw_assert(amount>=1);
833 
834  gc += amount;
835 }
836 
837 void AW_gc_manager::allocate_gc(int gc) const {
838  device->new_gc(gc);
839  device->set_line_attributes(gc, 1, AW_SOLID);
840  device->set_function(gc, AW_COPY);
841 
842  int gc_drag = gc + drag_gc_offset;
843  device->new_gc(gc_drag);
844  device->set_line_attributes(gc_drag, 1, AW_SOLID);
845  device->set_function(gc_drag, AW_XOR);
846  device->establish_default(gc_drag);
847 }
848 
849 void AW_gc_manager::add_gc(const char *gc_description, int& gc, gc_type type, const char *id_prefix) {
850  aw_assert(!strchr("*!&", gc_description[0]));
851  aw_assert(implicated(type != GC_TYPE_RANGE, !has_color_range())); // color ranges have to be specified AFTER all other color definition strings (in call to AW_manage_GC)
852 
853  GCs.push_back(gc_desc(gc, type));
854  gc_desc &gcd = GCs.back();
855  int idx = int(GCs.size()-1); // index position where new GC has been added
856 
857  if (gcd.is_color_group() && first_colorgroup_idx == NO_INDEX) {
858  first_colorgroup_idx = idx; // remember index of first color-group
859  }
860 
861  bool is_background = gc == GC_BACKGROUND;
862  bool alloc_gc = (!is_background || colorindex_base != AW_DATA_BG) && !gcd.belongs_to_range();
863  if (alloc_gc) {
864  allocate_gc(gc + is_background); // increment only happens for AW_BOTTOM_AREA defining GCs
865  }
866 
867  const char *default_color = gcd.parse_decl(gc_description, id_prefix);
868 
869  aw_assert(strcmp(gcd.key.c_str(), ALL_FONTS_ID) != 0); // id is reserved
870 #if defined(ASSERTION_USED)
871  {
872  const string& lastId = gcd.key;
873  for (int i = 0; i<idx; ++i) {
874  const gc_desc& check = GCs[i];
875  aw_assert(check.key != lastId); // duplicate GC-ID!
876  }
877  }
878 #endif
879 
880 #if !defined(ARB_OPENGL)
881  // normally the first GC should define a font (wrong for RNA3D)
882  aw_assert(implicated(gc == 0 && type != GC_TYPE_RANGE, gcd.has_font));
883 #endif
884 
885  if (default_color[0] == '{') {
886  // use current value of an already defined color as default for current color:
887  // (e.g. used in SECEDIT)
888  const char *close_brace = strchr(default_color+1, '}');
889  aw_assert(close_brace); // missing '}' in reference!
890  char *referenced_colorlabel = ARB_strpartdup(default_color+1, close_brace-1);
891 
892  IF_ASSERTION_USED(bool found = false);
893 
894  for (gc_container::iterator g = GCs.begin(); g != GCs.end(); ++g) {
895  if (strcmp(g->colorlabel.c_str(), referenced_colorlabel) == 0) {
896  default_color = AW_root::SINGLETON->awar(color_awarname(gc_base_name, g->key))->read_char_pntr(); // @@@ should use default value (not current value)
897  IF_ASSERTION_USED(found = true);
898  break;
899  }
900  }
901 
902  aw_assert(found); // unknown default color!
903  free(referenced_colorlabel);
904  }
905 
906  // @@@ add assertion vs duplicate ids here?
907  AW_root::SINGLETON->awar_string(color_awarname(gc_base_name, gcd.key), default_color)
908  ->add_callback(makeRootCallback(gc_color_changed_cb, this, idx));
909  gc_color_changed_cb(NULp, this, idx);
910 
911  if (!is_background) { // no font for background
912  if (gcd.has_font) {
913  aw_assert(!gcd.belongs_to_range()); // no fonts supported for ranges
914 
916 
917  RootCallback fontChange_cb = makeRootCallback(gc_fontOrSize_changed_cb, this, idx);
918  AW_root::SINGLETON->awar_int(fontname_awarname(gc_base_name, gcd.key), default_font)->add_callback(fontChange_cb);
919  AW_root::SINGLETON->awar_int(fontsize_awarname(gc_base_name, gcd.key), DEF_FONTSIZE)->add_callback(fontChange_cb);
920  AW_root::SINGLETON->awar_string(fontinfo_awarname(gc_base_name, gcd.key), "<select font>");
921  }
922  // Note: fonts are not initialized here. This is done in init_all_fonts() after all GCs have been defined.
923  }
924 
925  gc++;
926 }
928  int ad_font = -1;
929  int ad_size = -1;
931 
932  // initialize fonts of all defined GCs:
933  for (int idx = 0; idx<int(GCs.size()); ++idx) {
934  const gc_desc& gcd = GCs[idx];
935  if (gcd.has_font) {
936  update_gc_font(idx);
937 
938  if (ad_font == -1) {
939  ad_font = awr->awar(fontname_awarname(gc_base_name, gcd.key))->read_int();
940  ad_size = awr->awar(fontsize_awarname(gc_base_name, gcd.key))->read_int();
941  }
942  }
943  }
944 
945  // init global font awars (used to set ALL fonts)
946  AW_root::SINGLETON->awar_int(fontname_awarname(gc_base_name, ALL_FONTS_ID), ad_font)->add_callback(makeRootCallback(all_fontsOrSizes_changed_cb, this, false));
947  AW_root::SINGLETON->awar_int(fontsize_awarname(gc_base_name, ALL_FONTS_ID), ad_size)->add_callback(makeRootCallback(all_fontsOrSizes_changed_cb, this, true));
948 }
949 
951  for (gc_container::const_iterator g = GCs.begin(); g != GCs.end(); ++g) {
952  if (g->has_font && !g->fixed_width_font) return true;
953  }
954  return false;
955 }
956 
959  for (int i = 1; i <= AW_COLOR_GROUPS; ++i) {
961  }
962 
963  const char **color_group_gc_default = AW_gc_manager::color_group_defaults;
964  while (*color_group_gc_default) {
965  add_gc(*color_group_gc_default++, gc, GC_TYPE_GROUP);
966  }
967 }
968 
970  const char *gc_base_name,
971  AW_device *device,
972  int base_drag,
973  AW_GCM_AREA area,
974  const GcChangedCallback& changecb,
975  const char *default_background_color,
976  ...)
977 {
1015  aw_assert(default_background_color[0]);
1016 
1017 #if defined(ASSERTION_USED)
1018  int base_drag_given = base_drag;
1019 #endif
1020 
1021  AW_root *aw_root = AW_root::SINGLETON;
1022 
1023  int colidx_base = area == AW_GCM_DATA_AREA ? AW_DATA_BG : AW_WINDOW_BG;
1024  AW_gc_manager *gcmgr = new AW_gc_manager(gc_base_name, device, base_drag, aww, colidx_base);
1025 
1026  int gc = GC_BACKGROUND; // gets incremented by add_gc
1027  char background[50];
1028  sprintf(background, "-background$%s", default_background_color);
1029  gcmgr->add_gc(background, gc, GC_TYPE_NORMAL);
1030 
1031  va_list parg;
1032  va_start(parg, default_background_color);
1033 
1034  bool defined_color_groups = false;
1035 
1036  const char *id;
1037  while ( (id = va_arg(parg, char*)) ) {
1038  switch (id[0]) {
1039  case '!': gcmgr->reserve_gcs(id, gc); break;
1040  case '*': gcmgr->add_gc_range(id); break;
1041  case '&':
1042  if (strcmp(id, "&color_groups") == 0) { // trigger use of color groups
1043  aw_assert(!defined_color_groups); // color-groups trigger specified twice!
1044  if (!defined_color_groups) {
1045  gcmgr->add_color_groups(gc);
1046  defined_color_groups = true;
1047  }
1048  }
1049  else { aw_assert(0); } // unknown trigger
1050  break;
1051  default: gcmgr->add_gc(id, gc, GC_TYPE_NORMAL); break;
1052  }
1053  }
1054  va_end(parg);
1055 
1056  {
1057  AW_awar *awar_useGroups = aw_root->awar_int(AWAR_COLOR_GROUPS_USE, 1);
1058 
1059  awar_useGroups->add_callback(makeRootCallback(color_group_use_changed_cb, gcmgr));
1060  AW_gc_manager::use_color_groups = awar_useGroups->read_int();
1061  }
1062 
1063  aw_root->awar_int(AWAR_RANGE_OVERLAY, 0)->add_callback(makeRootCallback(range_overlay_changed_cb, gcmgr));
1064  aw_root->awar_int(gcmgr->awarname_active_range(), 0)->add_callback(makeRootCallback(active_range_changed_cb, gcmgr));
1065 
1066  gcmgr->init_color_ranges(gc);
1067  gcmgr->init_all_fonts();
1068 
1069  // installing changed callback here avoids that it gets triggered by initializing GCs
1070  gcmgr->set_changed_cb(changecb);
1071 
1072 #if defined(ASSERTION_USED)
1073  if (strcmp(gc_base_name, "ARB_PARSIMONY") == 0) {
1074  // ARB_PARSIMONY does not define color-ranges, but uses same GCs as ARB_NTREE
1075  // => accept weird 'base_drag_given'
1076  aw_assert(gc == (base_drag_given-AW_RANGE_COLORS));
1077  }
1078  else {
1079  aw_assert(gc == base_drag_given); // parameter 'base_drag' has wrong value
1080  // (has to be next value after last GC or after last color-group-GC)
1081  }
1082 #endif
1083 
1084  // @@@ add check: 1. all range IDs have to be unique
1085  // @@@ add check: 2. all GC IDs have to be unique
1086 
1087  return gcmgr;
1088 }
1089 
1090 void AW_copy_GC_colors(AW_root *aw_root, const char *source_gcman, const char *dest_gcman, const char *id0, ...) {
1091  // read the color values of the specified GCs from 'source_gcman'
1092  // and write the values into same-named GCs of 'dest_gcman'.
1093  //
1094  // 'id0' is the first of a list of color ids.
1095  // Notes:
1096  // - a NULp sentinel has to be passed after the last color
1097  // - the ids (may) differ from the descriptions passed to AW_manage_GC (ids are keys!)
1098 
1099  va_list parg;
1100  va_start(parg, id0);
1101 
1102  const char *id = id0;
1103  while (id) {
1104  const char *value = aw_root->awar(color_awarname(source_gcman, id))->read_char_pntr();
1105  aw_root->awar(color_awarname(dest_gcman, id))->write_string(value);
1106 
1107  id = va_arg(parg, const char*); // another argument?
1108  }
1109 
1110  va_end(parg);
1111 }
1112 
1113 void AW_init_color_group_defaults(const char *for_program) {
1114  // if for_program == NULp defaults of arb_ntree are silently used
1115  // if for_program is unknown a warning is shown
1116 
1117  aw_assert(!AW_gc_manager::color_group_defaults);
1118 
1119  bool for_edit4 = false;
1120  if (for_program) {
1121  if (strcmp(for_program, "arb_edit4") == 0) {
1122  for_edit4 = true;
1123  }
1124 #if defined(ASSERTION_USED)
1125  else {
1126  aw_assert(strcmp(for_program, "arb_ntree") == 0); // you might want to add specific defaults for_program
1127  // alternatively pass NULp to use ARB_NTREE_color_group
1128  }
1129 #endif
1130  }
1131 
1132  const int BUFSIZE = AW_COLOR_GROUPS*40;
1133  const char SEP = '\1';
1134  GBS_strstruct printBuffer(BUFSIZE);
1135 
1136  for (int i = 0; i<AW_COLOR_GROUPS; ++i) {
1137  if (!(i&1)) printBuffer.put('+'); // newline after every 2nd color
1138  printBuffer.put('-');
1139  printBuffer.cat(default_colorgroup_name(i+1));
1140  printBuffer.put('$');
1141  printBuffer.put('#');
1142  printBuffer.cat(color_group_def[i].rgbValue(for_edit4));
1143  printBuffer.put(SEP);
1144  }
1145 
1146  aw_assert(printBuffer.get_position()<BUFSIZE); // avoid need to resize buffer
1147 
1148  static ConstStrArray singleDefs;
1149  {
1150  char *alldefs = printBuffer.release();
1151  GBT_splitNdestroy_string(singleDefs, alldefs, SEP);
1152  }
1153 
1154  static const char *cg_def[AW_COLOR_GROUPS+1];
1155  for (int i = 0; i<AW_COLOR_GROUPS; ++i) {
1156  cg_def[i] = singleDefs[i];
1157  }
1158  cg_def[AW_COLOR_GROUPS] = NULp;
1159 
1160  AW_gc_manager::color_group_defaults = cg_def;
1161 }
1162 
1167 }
1170  return AWAR_COLOR_GROUPS_USE;
1171 }
1172 
1173 char *AW_get_color_group_name(AW_root *awr, int color_group) {
1175  aw_assert(valid_color_group(color_group));
1176  return awr->awar(colorgroupname_awarname(color_group))->read_string();
1177 }
1178 
1179 static void create_color_button(AW_window *aws, const char *awar_name, const char *color_description) {
1180  const char *color = aws->get_root()->awar(awar_name)->read_char_pntr();
1181  char *button_id = GBS_global_string_copy("sel_color[%s]", awar_name);
1182 
1183  aws->callback(makeWindowCallback(aw_create_color_chooser_window, strdup(awar_name), strdup(color_description)));
1184  aws->create_button(button_id, " ", NULp, color);
1185 
1186  free(button_id);
1187 }
1188 
1189 static void create_font_button(AW_window *aws, const char *gc_base_name, const gc_desc& gcd) {
1190  char *button_id = GBS_global_string_copy("sel_font_%s", gcd.key.c_str());
1191 
1192  aws->callback(makeWindowCallback(aw_create_font_chooser_window, gc_base_name, &gcd));
1193  aws->create_button(button_id, fontinfo_awarname(gc_base_name, gcd.key));
1194 
1195  free(button_id);
1196 }
1197 
1198 static const int STD_LABEL_LEN = 15;
1199 static const int COLOR_BUTTON_LEN = 10;
1200 static const int FONT_BUTTON_LEN = COLOR_BUTTON_LEN+STD_LABEL_LEN+1;
1201 // => color+font has ~same length as 2 colors (does not work for color groups)
1202 
1204  for (int idx = 0; idx<int(GCs.size()); ++idx) {
1205  const gc_desc& gcd = GCs[idx];
1206 
1207  if (gcd.is_color_group()) { if (for_gc_type != GC_TYPE_GROUP) continue; }
1208  else if (gcd.belongs_to_range()) { if (for_gc_type != GC_TYPE_RANGE) continue; }
1209  else { if (for_gc_type != GC_TYPE_NORMAL) continue; }
1210 
1211  if (for_gc_type == GC_TYPE_RANGE) {
1212  if (gcd.get_color_index() == 0) { // first color of range
1213  const gc_range& range = color_ranges[gcd.get_range_index()];
1214 
1215  const char *type_info = NULp;
1216  switch (range.get_type()) {
1217  case GC_RANGE_LINEAR: type_info = "linear 1D range"; break;
1218  case GC_RANGE_CYCLIC: type_info = "cyclic 1D range"; break;
1219  case GC_RANGE_PLANAR: type_info = "planar 2D range"; break;
1220  case GC_RANGE_SPATIAL: type_info = "spatial 3D range"; break;
1221  case GC_RANGE_INVALID: type_info = "invalid range "; aw_assert(0); break;
1222  }
1223 
1224  const char *range_headline = GBS_global_string("%s (%s)", range.get_name().c_str(), type_info);
1225  aws->button_length(60);
1226  aws->create_button(NULp, range_headline, NULp, "+");
1227  aws->at_newline();
1228  }
1229  }
1230 
1231  if (for_gc_type == GC_TYPE_GROUP) {
1232  int color_group_no = idx-first_colorgroup_idx+1;
1233  char buf[13];
1234  sprintf(buf, "%2i:", color_group_no); // @@@ shall this short label be stored in gc_desc?
1235  aws->label_length(3);
1236  aws->label(buf);
1237  aws->create_input_field(colorgroupname_awarname(color_group_no), 21);
1238  }
1239  else {
1240  aws->label_length(STD_LABEL_LEN);
1241  aws->label(gcd.colorlabel.c_str());
1242  }
1243 
1244  aws->button_length(COLOR_BUTTON_LEN);
1245  create_color_button(aws, color_awarname(gc_base_name, gcd.key), gcd.colorlabel.c_str());
1246  if (gcd.has_font) {
1247  aws->button_length(FONT_BUTTON_LEN);
1248  create_font_button(aws, gc_base_name, gcd);
1249  }
1250  if (!gcd.same_line) aws->at_newline();
1251  }
1252 }
1253 
1254 typedef std::map<AW_gc_manager*, AW_window_simple*> GroupWindowRegistry;
1255 
1258 
1259  static GroupWindowRegistry existing_window;
1260  GroupWindowRegistry::iterator found = existing_window.find(gcmgr);
1261  AW_window_simple *aws = found == existing_window.end() ? NULp : found->second;
1262 
1263  if (!aws) {
1264  aws = new AW_window_simple;
1265 
1266  aws->init(aww->get_root(), "COLOR_GROUP_DEF2", "Define color groups");
1267 
1268  aws->at(10, 10);
1269  aws->auto_space(1, 1);
1270 
1271  aws->callback(AW_POPDOWN);
1272  aws->create_button("CLOSE", "CLOSE", "C");
1273  aws->callback(makeHelpCallback("color_props_groups.hlp"));
1274  aws->create_button("HELP", "HELP", "H");
1275  aws->at_newline();
1276 
1277  aws->label_length(20);
1278  aws->label("Enable color groups:");
1279  aws->create_toggle(AWAR_COLOR_GROUPS_USE);
1280  aws->at_newline();
1281 
1282  gcmgr->create_gc_buttons(aws, GC_TYPE_GROUP);
1283 
1284  aws->window_fit();
1285  existing_window[gcmgr] = aws;
1286  }
1287 
1288  aws->activate();
1289 }
1290 
1292  static GroupWindowRegistry existing_window;
1293  GroupWindowRegistry::iterator found = existing_window.find(gcmgr);
1294  AW_window_simple *aws = found == existing_window.end() ? NULp : found->second;
1295 
1296  if (!aws) {
1297  aws = new AW_window_simple;
1298 
1299  aws->init(aww->get_root(), "COLOR_RANGE_EDIT", "Edit color ranges");
1300 
1301  aws->at(10, 10);
1302  aws->auto_space(5, 5);
1303 
1304  aws->callback(AW_POPDOWN);
1305  aws->create_button("CLOSE", "CLOSE", "C");
1306  aws->callback(makeHelpCallback("color_ranges.hlp"));
1307  aws->create_button("HELP", "HELP", "H");
1308  aws->at_newline();
1309 
1310  aws->label("Overlay active range");
1311  aws->create_toggle(AWAR_RANGE_OVERLAY);
1312  aws->at_newline();
1313 
1314  gcmgr->create_gc_buttons(aws, GC_TYPE_RANGE);
1315 
1316  aws->window_fit();
1317  existing_window[gcmgr] = aws;
1318  }
1319 
1320  aws->activate();
1321 }
1322 
1323 AW_window *AW_create_gc_window_named(AW_root *aw_root, AW_gc_manager *gcman, const char *wid, const char *windowname) {
1324  // same as AW_create_gc_window, but uses different window id and name
1325  // (use if if there are two or more color def windows in one application,
1326  // otherwise they save the same window properties)
1327 
1328  AW_window_simple *aws = new AW_window_simple;
1329 
1330  aws->init(aw_root, wid, windowname);
1331 
1332  aws->at(10, 10);
1333  aws->auto_space(2, 2);
1334 
1335  aws->callback(AW_POPDOWN);
1336  aws->create_button("CLOSE", "CLOSE", "C");
1337  aws->callback(makeHelpCallback("color_props.hlp"));
1338  aws->create_button("HELP", "HELP", "H");
1339  aws->at_newline();
1340 
1341  // select all fonts:
1342  {
1343  static gc_desc allFont_fake_desc(-1, GC_TYPE_NORMAL);
1344  allFont_fake_desc.colorlabel = "<all fonts>";
1345  allFont_fake_desc.key = ALL_FONTS_ID;
1346  allFont_fake_desc.fixed_width_font = !gcman->has_variable_width_font();
1347  aws->callback(makeWindowCallback(aw_create_font_chooser_window, gcman->get_base_name(), &allFont_fake_desc));
1348  }
1349  aws->label_length(STD_LABEL_LEN);
1350  aws->label("All fonts:");
1351  aws->button_length(COLOR_BUTTON_LEN);
1352  aws->create_button("select_all_fonts", "Select", "s");
1353  aws->at_newline();
1354 
1355  gcman->create_gc_buttons(aws, GC_TYPE_NORMAL);
1356 
1357  bool groups_or_range = false;
1358  if (gcman->has_color_groups()) {
1359  aws->callback(makeWindowCallback(AW_popup_gc_color_groups_window, gcman));
1360  aws->create_autosize_button("EDIT_COLOR_GROUP", "Edit color groups", "E");
1361  groups_or_range = true;
1362  }
1363  if (gcman->has_color_range()) {
1364  aws->callback(makeWindowCallback(AW_popup_gc_color_range_window, gcman));
1365  aws->create_autosize_button("EDIT_COLOR_RANGE", "Edit color ranges", "r");
1366  groups_or_range = true;
1367  }
1368  if (groups_or_range) aws->at_newline();
1369 
1370  aws->window_fit();
1371  return aws;
1372 }
1374  return AW_create_gc_window_named(aw_root, gcman, "COLOR_DEF2", "Colors and Fonts");
1375 }
1376 
1378  return gcman->get_drag_gc();
1379 }
1380 
1381 void AW_displayColorRange(AW_device *device, int first_range_gc, AW::Position start, AW_pos xsize, AW_pos ysize) {
1391  using namespace AW;
1392 
1393  if (AW_gc_manager::show_range_overlay) {
1394  Vector size(xsize, ysize);
1395  for (int x = 0; x<AW_PLANAR_COLORS; ++x) {
1396  for (int y = 0; y<AW_PLANAR_COLORS; ++y) {
1397  int gc = first_range_gc + y*AW_PLANAR_COLORS+x;
1398  Vector toCorner(x*xsize, y*ysize);
1399  Position corner = start+toCorner;
1400  device->box(gc, FillStyle::SOLID, Rectangle(corner, size));
1401  }
1402  }
1403  }
1404 }
1405 
1406 void AW_getColorRangeNames(const AW_gc_manager *gcman, int dimension, ConstStrArray& ids, ConstStrArray& names) {
1413  ids.clear();
1414  names.clear();
1415  gcman->getColorRangeNames(dimension, ids, names);
1416 }
1417 
1418 int AW_getFirstRangeGC(AW_gc_manager *gcman) { return gcman->first_range_gc(); }
1419 void AW_activateColorRange(AW_gc_manager *gcman, const char *id) { gcman->activateColorRange(id); }
1420 
1421 const char *AW_getActiveColorRangeID(AW_gc_manager *gcman, int *dimension) {
1426  return gcman->getActiveColorRangeID(dimension);
1427 }
1428 
1429 #if defined(UNIT_TESTS)
1433  }
1434  AW_gc_manager::use_color_groups = true;
1435 }
1436 #endif
1437 
1438 // @@@ move code below somewhere more sensible
1439 
1441  aw->insert_menu_topic("enable_advices", "Reactivate advices", "R", "advice.hlp", AWM_ALL, AW_reactivate_all_advices);
1442  aw->insert_menu_topic("enable_questions", "Reactivate questions", "q", "questions.hlp", AWM_ALL, AW_reactivate_all_questions);
1443  aw->insert_menu_topic("reset_win_layout", "Reset window layout", "w", "reset_win_layout.hlp", AWM_ALL, AW_forget_all_window_geometry);
1444 }
1447 
1448 void AW_save_specific_properties(AW_window *aw, const char *filename) { // special version for EDIT4
1449  GB_ERROR error = aw->get_root()->save_properties(filename);
1450  if (error) aw_message(error);
1451 }
1454 }
1455 
1456 // --------------------------------
1457 // RGB <-> HSV conversion
1458 
1459 class AW_hsv {
1460  float H, S, V;
1461 public:
1462  AW_hsv(float hue, float saturation, float value) : H(hue), S(saturation), V(value) {
1463  aw_assert(H>=0.0 && H<360.0);
1464  aw_assert(S>=0.0 && S<=1.0);
1465  aw_assert(V>=0.0 && V<=1.0);
1466  }
1468  float R = col.r();
1469  float G = col.g();
1470  float B = col.b();
1471 
1472  float min = std::min(std::min(R, G), B);
1473  float max = std::max(std::max(R, G), B);
1474 
1475  if (min == max) {
1476  H = 0;
1477  }
1478  else {
1479  H = 60;
1480 
1481  if (max == R) { H *= 0 + (G-B)/(max-min); }
1482  else if (max == G) { H *= 2 + (B-R)/(max-min); }
1483  else { H *= 4 + (R-G)/(max-min); }
1484 
1485  if (H<0) H += 360;
1486  }
1487 
1488  S = max ? (max-min)/max : 0;
1489  V = max;
1490  }
1491 #if defined(Cxx11)
1492  AW_hsv(const AW_rgb16& col) : AW_hsv(AW_rgb_normalized(col)) {}
1493 #else // !defined(Cxx11)
1494  AW_hsv(const AW_rgb16& col) { *this = AW_rgb_normalized(col); }
1495 #endif
1496 
1498  int hi = int(H/60);
1499  float f = H/60-hi;
1500 
1501  float p = V*(1-S);
1502  float q = V*(1-S*f);
1503  float t = V*(1-S*(1-f));
1504 
1505  switch (hi) {
1506  case 0: return AW_rgb_normalized(V, t, p); // 0 <= H < 60 (deg)
1507  case 1: return AW_rgb_normalized(q, V, p); // 60 <= H < 120
1508  case 2: return AW_rgb_normalized(p, V, t); // 120 <= H < 180
1509  case 3: return AW_rgb_normalized(p, q, V); // 180 <= H < 240
1510  case 4: return AW_rgb_normalized(t, p, V); // 240 <= H < 300
1511  case 5: return AW_rgb_normalized(V, p, q); // 300 <= H < 360
1512  }
1513  aw_assert(0);
1514  return AW_rgb_normalized(0, 0, 0);
1515  }
1516 
1517  float h() const { return H; }
1518  float s() const { return S; }
1519  float v() const { return V; }
1520 };
1521 
1522 
1523 // --------------------------------------------------------------------------------
1524 
1525 #ifdef UNIT_TESTS
1526 #ifndef TEST_UNIT_H
1527 #include <test_unit.h>
1528 #endif
1529 
1530 void TEST_rgb_hsv_conversion() {
1531  // Note: more related tests in AW_rgb.cxx@RGB_TESTS
1532 
1533  const int tested[] = {
1534  // testing full rgb space takes too long
1535  // just test all combinations of these:
1536 
1537  0, 1, 2, 3, 4, 5,
1538  58, 59, 60, 61, 62,
1539  998, 999, 1000, 1001, 1002,
1540  32766, 32767, 32768, 32769, 32770,
1541  39998, 39999, 40000, 40001, 40002,
1542  65531, 65532, 65533, 65534, 65535
1543  };
1544 
1545  for (unsigned i = 0; i<ARRAY_ELEMS(tested); ++i) {
1546  int r = tested[i];
1547  for (unsigned j = 0; j<ARRAY_ELEMS(tested); ++j) {
1548  int g = tested[j];
1549  for (unsigned k = 0; k<ARRAY_ELEMS(tested); ++k) {
1550  int b = tested[k];
1551 
1552  TEST_ANNOTATE(GBS_global_string("rgb=%i/%i/%i", r, g, b));
1553 
1554  AW_hsv hsv(AW_rgb16(r, g, b));
1555 
1556  // check range overflow
1557  TEST_EXPECT(hsv.h()>=0.0 && hsv.h()<360.0);
1558  TEST_EXPECT(hsv.s()>=0.0 && hsv.s()<=1.0);
1559  TEST_EXPECT(hsv.v()>=0.0 && hsv.v()<=1.0);
1560 
1561  AW_rgb16 RGB(hsv.rgb());
1562 
1563  // fprintf(stderr, "rgb=%i/%i/%i hsv=%i/%i/%i RGB=%i/%i/%i\n", r, g, b, h, s, v, R, G, B);
1564 
1565  // check that rgb->hsv->RGB produces a similar color
1566  const int MAXDIFF = 1; // less than .0015% difference per channel
1567  const int MAXDIFFSUM = 2; // less than .003% difference overall
1568 
1569  TEST_EXPECT(abs(r-RGB.r()) <= MAXDIFF);
1570  TEST_EXPECT(abs(g-RGB.g()) <= MAXDIFF);
1571  TEST_EXPECT(abs(b-RGB.b()) <= MAXDIFF);
1572 
1573  TEST_EXPECT((abs(r-RGB.r())+abs(g-RGB.g())+abs(b-RGB.b())) <= MAXDIFFSUM);
1574  }
1575  }
1576  }
1577 
1578  for (unsigned i = 0; i<ARRAY_ELEMS(tested); ++i) {
1579  int h = tested[i]*320/65535;
1580  for (unsigned j = 0; j<ARRAY_ELEMS(tested); ++j) {
1581  float s = tested[j]/65535.0;
1582  for (unsigned k = 0; k<ARRAY_ELEMS(tested); ++k) {
1583  float v = tested[k]/65535.0;
1584 
1585  TEST_ANNOTATE(GBS_global_string("hsv=%i/%.3f/%.3f", h, s, v));
1586 
1587  AW_rgb16 rgb(AW_hsv(h, s, v).rgb());
1588  AW_rgb16 RGB(AW_hsv(rgb).rgb());
1589 
1590  // fprintf(stderr, "hsv=%i/%i/%i rgb=%i/%i/%i HSV=%i/%i/%i RGB=%i/%i/%i\n", h, s, v, r, g, b, H, S, V, R, G, B);
1591 
1592  // check that hsv->rgb->HSV->RGB produces a similar color (comparing hsv makes no sense)
1593  const int MAXDIFF = 1; // less than .0015% difference per channel
1594  const int MAXDIFFSUM = 2; // less than .003% difference overall
1595 
1596  TEST_EXPECT(abs(rgb.r()-RGB.r()) <= MAXDIFF);
1597  TEST_EXPECT(abs(rgb.g()-RGB.g()) <= MAXDIFF);
1598  TEST_EXPECT(abs(rgb.b()-RGB.b()) <= MAXDIFF);
1599 
1600  TEST_EXPECT((abs(rgb.r()-RGB.r())+abs(rgb.g()-RGB.g())+abs(rgb.b()-RGB.b())) <= MAXDIFFSUM);
1601  }
1602  }
1603  }
1604 
1605  // specific conversion (showed wrong 'hue' and 'saturation' until [14899])
1606  {
1607  AW_hsv hsv(AW_rgb16(0, 0, 14906));
1608 
1609  TEST_EXPECT_SIMILAR(hsv.h(), 240.0, 0.001); //= ~ 240 deg
1610  TEST_EXPECT_SIMILAR(hsv.s(), 1.0, 0.001); //= 100%
1611  TEST_EXPECT_SIMILAR(hsv.v(), 0.227, 0.001); //= ~ 22.7%
1612 
1613  AW_rgb16 rgb(hsv.rgb());
1614 
1615  TEST_EXPECT_EQUAL(rgb.r(), 0);
1616  TEST_EXPECT_EQUAL(rgb.g(), 0);
1617  TEST_EXPECT_EQUAL(rgb.b(), 14906);
1618  }
1619 }
1620 
1621 #endif // UNIT_TESTS
1622 
1623 // --------------------------------------------------------------------------------
1624 
1625 
1626 // ------------------------------
1627 // motif color selector
1628 
1629 #define AWAR_SELECTOR_COLOR_LABEL "tmp/aw/color_label"
1630 
1631 #define AWAR_CV_R "tmp/aw/color_r" // rgb..
1632 #define AWAR_CV_G "tmp/aw/color_g"
1633 #define AWAR_CV_B "tmp/aw/color_b"
1634 #define AWAR_CV_H "tmp/aw/color_h" // hsv..
1635 #define AWAR_CV_S "tmp/aw/color_s"
1636 #define AWAR_CV_V "tmp/aw/color_v"
1637 
1638 static char *current_color_awarname = NULp; // name of the currently modified color-awar
1639 static bool ignore_color_value_change = false;
1641 
1642 static void aw_set_rgb_sliders(AW_root *awr, const AW_rgb_normalized& col) {
1643  color_value_change_was_ignored = false;
1644  {
1645  LocallyModify<bool> delayUpdate(ignore_color_value_change, true);
1646  awr->awar(AWAR_CV_R)->write_float(col.r());
1647  awr->awar(AWAR_CV_G)->write_float(col.g());
1648  awr->awar(AWAR_CV_B)->write_float(col.b());
1649  }
1650  if (color_value_change_was_ignored) awr->awar(AWAR_CV_B)->touch();
1651 }
1652 
1654  const char *color = awr->awar(current_color_awarname)->read_char_pntr();
1656 }
1657 
1658 inline void aw_set_color(AW_root *awr, const char *color_name) {
1659  awr->awar(current_color_awarname)->write_string(color_name);
1661 }
1662 static void aw_set_color(AW_window *aww, const char *color_name) {
1663  aw_set_color(aww->get_root(), color_name);
1664 }
1665 
1666 static void colorslider_changed_cb(AW_root *awr, bool hsv_changed) {
1667  if (ignore_color_value_change) {
1668  color_value_change_was_ignored = true;
1669  }
1670  else {
1671  LocallyModify<bool> noRecursion(ignore_color_value_change, true);
1672 
1673  if (hsv_changed) {
1674  float h = awr->awar(AWAR_CV_H)->read_float();
1675  float s = awr->awar(AWAR_CV_S)->read_float();
1676  float v = awr->awar(AWAR_CV_V)->read_float();
1677 
1678  if (h>=360.0) h -= 360;
1679 
1680  AW_rgb_normalized col(AW_hsv(h, s, v).rgb());
1681  aw_set_color(awr, AW_rgb16(col).ascii());
1682 
1683  awr->awar(AWAR_CV_R)->write_float(col.r());
1684  awr->awar(AWAR_CV_G)->write_float(col.g());
1685  awr->awar(AWAR_CV_B)->write_float(col.b());
1686  }
1687  else {
1689  awr->awar(AWAR_CV_G)->read_float(),
1690  awr->awar(AWAR_CV_B)->read_float());
1691 
1692  aw_set_color(awr, AW_rgb16(col).ascii());
1693 
1694  AW_hsv hsv(col);
1695 
1696  awr->awar(AWAR_CV_H)->write_float(hsv.h());
1697  awr->awar(AWAR_CV_S)->write_float(hsv.s());
1698  awr->awar(AWAR_CV_V)->write_float(hsv.v());
1699  }
1700  }
1701 }
1704  static const char *colorValueAwars[] = {
1708  };
1709 
1710  for (int cv = 0; cv<6; ++cv) {
1711  awr->awar_float(colorValueAwars[cv])
1712  ->set_minmax(0.0, cv == 1 ? 360.0 : 1.0)
1713  ->add_callback(makeRootCallback(colorslider_changed_cb, bool(cv%2)));
1714  }
1715 }
1716 static void aw_create_color_chooser_window(AW_window *aww, const char *awar_name, const char *color_description) {
1717  AW_root *awr = aww->get_root();
1718  static AW_window_simple *aws = NULp;
1719  if (!aws) {
1721 
1722  aws = new AW_window_simple;
1723  aws->init(awr, "COLORS", "Select color");
1724 
1725  int x1 = 10;
1726  int y1 = 10;
1727 
1728  aws->at(x1, y1);
1729  aws->auto_space(3, 3);
1730  aws->callback(AW_POPDOWN);
1731  aws->create_button("CLOSE", "CLOSE", "C");
1732 
1733  aws->button_length(20);
1734  aws->create_button(NULp, AWAR_SELECTOR_COLOR_LABEL);
1735  aws->at_newline();
1736 
1737  int x2, y2;
1738  aws->get_at_position(&x2, &y2);
1739  y2 += 3;
1740 
1741  struct ColorValue {
1742  const char *label;
1743  const char *awar;
1744  } colorValue[] = {
1745  { "R", AWAR_CV_R }, { "H", AWAR_CV_H },
1746  { "G", AWAR_CV_G }, { "S", AWAR_CV_S },
1747  { "B", AWAR_CV_B }, { "V", AWAR_CV_V },
1748  };
1749 
1750  const int INPUTFIELD_WIDTH = 12;
1751  const int SCALERLENGTH = 320;
1752 
1753  for (int row = 0; row<3; ++row) {
1754  aws->at(x1, y1+(row+1)*(y2-y1));
1755  const ColorValue *vc = &colorValue[row*2];
1756  aws->label(vc->label);
1757  aws->create_input_field_with_scaler(vc->awar, INPUTFIELD_WIDTH, SCALERLENGTH, AW_SCALER_LINEAR);
1758  ++vc;
1759  aws->label(vc->label);
1760  aws->create_input_field_with_scaler(vc->awar, INPUTFIELD_WIDTH, SCALERLENGTH, AW_SCALER_LINEAR);
1761  }
1762 
1763  aws->button_length(1);
1764  aws->at_newline();
1765 
1766  const float SATVAL_INCREMENT = 0.2;
1767  const int HUE_INCREMENT = 10;
1768  const int COLORS_PER_ROW = 360/HUE_INCREMENT;
1769 
1770  for (int v = 5; v>=2; --v) {
1771  float val = v*SATVAL_INCREMENT;
1772  bool rev = !(v%2);
1773  for (int s = rev ? 2 : 5; rev ? s<=5 : s>=2; s = rev ? s+1 : s-1) {
1774  float sat = s*SATVAL_INCREMENT;
1775  for (int hue = 0; hue<360; hue += HUE_INCREMENT) {
1776  const char *color_name = AW_rgb16(AW_hsv(hue, sat, val).rgb()).ascii();
1777  aws->callback(makeWindowCallback(aw_set_color, strdup(color_name)));
1778  aws->create_button(color_name, "", NULp, color_name);
1779  }
1780  aws->at_newline();
1781  }
1782  }
1783 
1784  for (int p = 0; p<COLORS_PER_ROW; ++p) {
1785  float grey = (1.0 * p) / (COLORS_PER_ROW-1);
1786  const char *color_name = AW_rgb16(AW_rgb_normalized(grey, grey, grey)).ascii();
1787 
1788  aws->callback(makeWindowCallback(aw_set_color, strdup(color_name)));
1789  aws->create_button(color_name, "=", NULp, color_name);
1790  }
1791  aws->at_newline();
1792 
1793  aws->window_fit();
1794  }
1795  awr->awar(AWAR_SELECTOR_COLOR_LABEL)->write_string(color_description);
1796  freedup(current_color_awarname, awar_name);
1798  aws->activate();
1799 }
1800 
1801 // ----------------------------
1802 // motif font chooser
1803 
1804 #define AWAR_SELECTOR_FONT_LABEL "tmp/aw/font_label"
1805 #define AWAR_SELECTOR_FONT_NAME "tmp/aw/font_name"
1806 #define AWAR_SELECTOR_FONT_SIZE "tmp/aw/font_size"
1807 
1809  awr->awar_string(AWAR_SELECTOR_FONT_LABEL, "<invalid>");
1812 }
1813 
1814 static void aw_create_font_chooser_window(AW_window *aww, const char *gc_base_name, const gc_desc *gcd) {
1815  AW_root *awr = aww->get_root();
1816 
1817  static AW_window_simple *aw_fontChoose[2] = { NULp, NULp }; // one for fixed-width font; one general
1818 
1819  bool fixed_width_only = gcd->fixed_width_font;
1820 
1821  AW_window_simple*& aws = aw_fontChoose[fixed_width_only];
1822  AW_window_simple*& awo = aw_fontChoose[!fixed_width_only];
1823 
1824  if (!aws) {
1826 
1827  aws = new AW_window_simple;
1828  aws->init(awr, "FONT", fixed_width_only ? "Select fixed width font" : "Select font");
1829 
1830  aws->auto_space(10, 10);
1831 
1832  aws->callback(AW_POPDOWN);
1833  aws->create_button("CLOSE", "CLOSE", "C");
1834 
1835  aws->button_length(20);
1836  aws->create_button(NULp, AWAR_SELECTOR_FONT_LABEL);
1837  aws->at_newline();
1838 
1839  aws->label("Font:");
1840  aws->create_option_menu(AWAR_SELECTOR_FONT_NAME);
1841  {
1842  int fonts_inserted = 0;
1843  for (int order = 1; order>=0; order--) {
1844  for (int font_nr = 0; ; font_nr++) {
1845  AW_font aw_font_nr = font_nr;
1846  bool found;
1847  const char *font_string = AW_get_font_specification(aw_font_nr, found);
1848 
1849  if (!font_string) {
1850  fprintf(stderr, "[Font detection: tried=%i, found=%i]\n", font_nr, fonts_inserted);
1851  break;
1852  }
1853 
1854  if (found != bool(order)) continue; // display found fonts at top
1855  if (fixed_width_only && !font_has_fixed_width(aw_font_nr)) continue;
1856 
1857  aws->insert_option(font_string, NULp, font_nr);
1858  ++fonts_inserted;
1859  }
1860  }
1861  if (!fonts_inserted) aws->insert_option("No suitable fonts detected", NULp, 0);
1862  aws->insert_default_option("<no font selected>", NULp, NO_FONT);
1863  aws->update_option_menu();
1864  }
1865 
1866  aws->at_newline();
1867 
1868  aws->label("Size:");
1869  aws->create_input_field_with_scaler(AWAR_SELECTOR_FONT_SIZE, 3, 330);
1870  aws->at_newline();
1871 
1872  aws->window_fit();
1873  }
1874 
1876  awr->awar(AWAR_SELECTOR_FONT_NAME)->map(awr->awar(fontname_awarname(gc_base_name, gcd->key)));
1877  awr->awar(AWAR_SELECTOR_FONT_SIZE)->map(awr->awar(fontsize_awarname(gc_base_name, gcd->key)));
1878 
1879  if (awo) awo->hide(); // both windows use same awars -> hide the other window to avoid chaos
1880  aws->activate();
1881 }
1882 
1883 // -----------------------------------
1884 // frame colors (motif only)
1885 
1886 static void aw_message_reload(AW_root *) {
1887  aw_message("Sorry, to activate new colors:\n"
1888  " save properties\n"
1889  " and restart application");
1890 }
1891 
1892 static void AW_preset_create_font_chooser(AW_window *aws, const char *awar, const char *label, bool message_reload) {
1893  if (message_reload) aws->get_root()->awar(awar)->add_callback(aw_message_reload);
1894 
1895  aws->label(label);
1896  aws->create_option_menu(awar);
1897 
1898  aws->insert_option("5x8", "5", "5x8");
1899  aws->insert_option("6x10", "6", "6x10");
1900  aws->insert_option("7x13", "7", "7x13");
1901  aws->insert_option("7x13bold", "7", "7x13bold");
1902  aws->insert_option("8x13", "8", "8x13");
1903  aws->insert_option("8x13bold", "8", "8x13bold");
1904  aws->insert_option("9x15", "9", "9x15");
1905  aws->insert_option("9x15bold", "9", "9x15bold");
1906  aws->insert_option("helvetica-12", "9", "helvetica-12");
1907  aws->insert_option("helvetica-bold-12", "9", "helvetica-bold-12");
1908  aws->insert_option("helvetica-13", "9", "helvetica-13");
1909  aws->insert_option("helvetica-bold-13", "9", "helvetica-bold-13");
1910 
1911  aws->insert_default_option("other", "o", "");
1912  aws->update_option_menu();
1913 }
1914 static void AW_preset_create_color_button(AW_window *aws, const char *awar_name, const char *label) {
1915  aws->get_root()->awar(awar_name)->add_callback(aw_message_reload);
1916  aws->label(label);
1917  create_color_button(aws, awar_name, label);
1918 }
1919 
1921  AW_window_simple *aws = new AW_window_simple;
1922  const int tabstop = 400;
1923  aws->init(root, "PROPS_FRAME", "WINDOW_PROPERTIES");
1924 
1925  aws->label_length(25);
1926  aws->button_length(20);
1927 
1928  aws->at (10, 10);
1929  aws->auto_space(10, 10);
1930 
1931  aws->callback (AW_POPDOWN);
1932  aws->create_button("CLOSE", "CLOSE", "C");
1933 
1934  aws->callback(makeHelpCallback("props_frame.hlp"));
1935  aws->create_button("HELP", "HELP", "H");
1936 
1937  aws->at_newline();
1938 
1939  AW_preset_create_font_chooser(aws, "window/font", "Main Menu Font", 1);
1940  aws->at_x(tabstop);
1941  aws->create_input_field("window/font", 12);
1942 
1943  aws->at_newline();
1944 
1945  aws->button_length(10);
1946  AW_preset_create_color_button(aws, "window/background", "Application Background");
1947  aws->at_x(tabstop);
1948  aws->create_input_field("window/background", 12);
1949 
1950  aws->at_newline();
1951 
1952  AW_preset_create_color_button(aws, "window/foreground", "Application Foreground");
1953  aws->at_x(tabstop);
1954  aws->create_input_field("window/foreground", 12);
1955 
1956  aws->at_newline();
1957 
1958  AW_preset_create_color_button(aws, "window/color_1", "Color 1");
1959  aws->at_x(tabstop);
1960  aws->create_input_field("window/color_1", 12);
1961 
1962  aws->at_newline();
1963 
1964  AW_preset_create_color_button(aws, "window/color_2", "Color 2");
1965  aws->at_x(tabstop);
1966  aws->create_input_field("window/color_2", 12);
1967 
1968  aws->at_newline();
1969 
1970  AW_preset_create_color_button(aws, "window/color_3", "Color 3");
1971 
1972  aws->at_x(tabstop);
1973  aws->create_input_field("window/color_3", 12);
1974 
1975  aws->at_newline();
1976 
1977  aws->window_fit();
1978  return aws;
1979 }
1980 
static bool ignore_color_value_change
Definition: AW_preset.cxx:1639
#define AWAR_COLOR_GROUPS_PREFIX
Definition: AW_preset.cxx:44
GB_ERROR GB_check_key(const char *key) __ATTR__USERESULT
Definition: adstring.cxx:85
void insert_option(AW_label choice_label, const char *mnemonic, const char *var_value, const char *name_of_color=NULp)
AW_window * AW_create_gc_window_named(AW_root *aw_root, AW_gc_manager *gcman, const char *wid, const char *windowname)
Definition: AW_preset.cxx:1323
#define NO_SIZE
Definition: AW_preset.cxx:53
#define SEP
Definition: xferset.cxx:430
bool font_has_fixed_width(AW_font aw_font_nr)
Definition: AW_preset.cxx:480
void add_gc(const char *gc_description, int &gc, gc_type type, const char *id_prefix=NULp)
Definition: AW_preset.cxx:849
string result
void reserve_gcs(const char *gc_description, int &gc)
Definition: AW_preset.cxx:827
static void gc_color_changed_cb(AW_root *, AW_gc_manager *mgr, int idx)
Definition: AW_preset.cxx:682
const int NO_INDEX
Definition: AW_preset.cxx:138
bool has_variable_width_font() const
Definition: AW_preset.cxx:950
const char * id
Definition: AliAdmin.cxx:17
void put(const char *elem)
Definition: arb_strarray.h:188
void button_length(int length)
Definition: AW_at.cxx:288
#define TEST_EXPECT_SIMILAR(expr, want, epsilon)
Definition: test_unit.h:1298
#define AWAR_SELECTOR_FONT_LABEL
Definition: AW_preset.cxx:1804
const char * fontsize_awarname(const char *gcman_id, const string &colname)
Definition: AW_preset.cxx:80
const char * awarname_active_range() const
Definition: AW_preset.cxx:419
#define implicated(hypothesis, conclusion)
Definition: arb_assert.h:289
static char * y[maxsp+1]
return string(buffer, length)
void insert_menu_topic(const char *id, const char *name, const char *mnemonic, const char *help_text_, AW_active mask, const WindowCallback &wcb)
Definition: AW_window.cxx:595
static void aw_set_rgb_sliders(AW_root *awr, const AW_rgb_normalized &col)
Definition: AW_preset.cxx:1642
#define AWAR_CV_V
Definition: AW_preset.cxx:1636
bool AW_color_groups_active()
Definition: AW_preset.cxx:1163
void init_color_ranges(int &gc)
Definition: AW_preset.cxx:786
const char * defaultColorgroupName(int color_group)
Definition: AW_preset.cxx:91
void set_line_attributes(int gc, short width, AW_linestyle style)
Definition: AW_device.cxx:465
static void colorslider_changed_cb(AW_root *awr, bool hsv_changed)
Definition: AW_preset.cxx:1666
void set_function(int gc, AW_function function)
Definition: AW_device.cxx:468
void establish_default(int gc)
Definition: AW_device.cxx:474
bool belongs_to_range() const
Definition: AW_preset.cxx:186
void AW_popup_gc_color_range_window(AW_window *aww, AW_gc_manager *gcmgr)
Definition: AW_preset.cxx:1291
AW_rgb_normalized get_color(int idx, const AW_gc_manager *gcman) const
Definition: AW_preset.cxx:541
void AW_reactivate_all_advices(AW_window *)
reactivates all advices which were disabled by the user
Definition: AW_advice.cxx:137
static char * current_color_awarname
Definition: AW_preset.cxx:1638
#define ALL_FONTS_ID
Definition: AW_preset.cxx:50
const char * AW_get_font_specification(AW_font font_nr, bool &found)
Definition: AW_xfont.cxx:666
GB_ERROR save_properties(const char *filename=NULp) __ATTR__USERESULT
Definition: AW_root.cxx:675
float s() const
Definition: AW_preset.cxx:1518
void AW_forget_all_window_geometry(AW_window *aww)
Definition: AW_window.cxx:2200
void at(int x, int y)
Definition: AW_at.cxx:93
const char * fontinfo_awarname(const char *gcman_id, const string &colname)
Definition: AW_preset.cxx:81
#define AW_COLOR_GROUPS
static void AW_preset_create_color_button(AW_window *aws, const char *awar_name, const char *label)
Definition: AW_preset.cxx:1914
long read_int() const
Definition: AW_awar.cxx:184
AW_awar * set_minmax(float min, float max)
Definition: AW_awar.cxx:530
static void gc_fontOrSize_changed_cb(AW_root *, AW_gc_manager *mgr, int idx)
Definition: AW_preset.cxx:477
static void aw_create_font_chooser_window(AW_window *aww, const char *gc_base_name, const struct gc_desc *gcd)
const string & get_id() const
Definition: AW_preset.cxx:271
void add_color(const string &colordef, AW_gc_manager *gcman)
Definition: AW_preset.cxx:722
const char * GBS_global_string(const char *templat,...)
Definition: arb_msg.cxx:203
bool has_color_range() const
Definition: AW_preset.cxx:358
void AW_advice(const char *message, AW_Advice_Type type, const char *title, const char *corresponding_help)
Show a message box with an advice for the user.
Definition: AW_advice.cxx:160
int get_range_index() const
Definition: AW_preset.cxx:188
int AW_font_2_xfig(AW_font font_nr)
Definition: AW_xfont.cxx:724
void GBK_terminatef(const char *templat,...)
Definition: arb_msg.cxx:523
void AW_POPDOWN(AW_window *window)
Definition: AW_window.cxx:52
char * release()
Definition: arb_strbuf.h:129
void AW_insert_common_property_menu_entries(AW_window_menu_modes *awmm)
Definition: AW_preset.cxx:1445
static void range_overlay_changed_cb(AW_root *awr, AW_gc_manager *gcmgr)
Definition: AW_preset.cxx:714
AW_color_idx
Definition: aw_base.hxx:83
char * GBS_string_2_key(const char *str)
Definition: adstring.cxx:52
bool fixed_width_font
Definition: AW_preset.cxx:173
void cat(const char *from)
Definition: arb_strbuf.h:199
AW_hsv(float hue, float saturation, float value)
Definition: AW_preset.cxx:1462
const char * AW_getActiveColorRangeID(AW_gc_manager *gcman, int *dimension)
Definition: AW_preset.cxx:1421
char * ARB_strpartdup(const char *start, const char *end)
Definition: arb_string.h:51
void AW_activateColorRange(AW_gc_manager *gcman, const char *id)
Definition: AW_preset.cxx:1419
#define AWAR_COLOR_GROUPS_USE
Definition: AW_preset.cxx:45
void create_gc_buttons(AW_window *aww, gc_type for_gc_type)
Definition: AW_preset.cxx:1203
const gc_desc & get_gc_desc(int idx) const
Definition: AW_preset.cxx:365
void add_color_groups(int &gc)
Definition: AW_preset.cxx:957
const string & get_name() const
Definition: AW_preset.cxx:270
static void color_group_name_changed_cb(AW_root *awr)
Definition: AW_preset.cxx:686
gc_range(const string &name_, gc_range_type type_, int index_, int gc_index_)
Definition: AW_preset.cxx:256
const char * rgbValue(bool for_edit4)
Definition: AW_preset.cxx:104
AW_gc_manager * AW_manage_GC(AW_window *aww, const char *gc_base_name, AW_device *device, int base_drag, AW_GCM_AREA area, const GcChangedCallback &changecb, const char *default_background_color,...)
Definition: AW_preset.cxx:969
#define ARRAY_ELEMS(array)
Definition: arb_defs.h:19
#define AWAR_CV_S
Definition: AW_preset.cxx:1635
void update_option_menu()
#define AWAR_CV_B
Definition: AW_preset.cxx:1633
gc_range_type
Definition: AW_preset.cxx:238
void aw_set_color(AW_root *awr, const char *color_name)
Definition: AW_preset.cxx:1658
static void AW_popup_gc_color_groups_window(AW_window *aww, AW_gc_manager *gcmgr)
Definition: AW_preset.cxx:1256
AW_awar * add_callback(const RootCallback &cb)
Definition: AW_awar.cxx:231
#define AWAR_CV_H
Definition: AW_preset.cxx:1634
const int GC_INVALID
Definition: AW_preset.cxx:136
const char * ascii() const
Definition: AW_rgb.cxx:56
const char * AW_get_color_groups_active_awarname()
Definition: AW_preset.cxx:1168
static HelixNrInfo * start
const char * default_colorgroup_name(int color_group)
Definition: AW_preset.cxx:130
const char * rgb_e4
Definition: AW_preset.cxx:89
bool same_line
Definition: AW_preset.cxx:174
GB_ERROR GB_check_hkey(const char *key) __ATTR__USERESULT
Definition: adstring.cxx:92
static FullNameMap names
const char * read_char_pntr() const
Definition: AW_awar.cxx:168
GcChange
Definition: aw_base.hxx:94
#define AW_PLANAR_COLORS
#define DEF_FONTSIZE
Definition: aw_def.hxx:27
static void create_font_button(AW_window *aws, const char *gc_base_name, const gc_desc &gcd)
Definition: AW_preset.cxx:1189
static AW_root * SINGLETON
Definition: aw_root.hxx:102
double AW_pos
Definition: aw_base.hxx:29
int AW_get_drag_gc(AW_gc_manager *gcman)
Definition: AW_preset.cxx:1377
static const int COLOR_BUTTON_LEN
Definition: AW_preset.cxx:1199
WindowCallback makeHelpCallback(const char *helpfile)
Definition: aw_window.hxx:106
#define TEST_EXPECT(cond)
Definition: test_unit.h:1328
void update_all_fonts(bool sizeChanged) const
Definition: AW_preset.cxx:483
float g() const
Definition: aw_rgb.hxx:95
void set_font(int gc, AW_font fontnr, int size, int *found_size)
Definition: AW_device.cxx:458
#define AWAR_SELECTOR_COLOR_LABEL
Definition: AW_preset.cxx:1629
std::map< AW_gc_manager *, AW_window_simple * > GroupWindowRegistry
Definition: AW_preset.cxx:1254
void set_foreground_color(int gc, AW_color_idx color)
Definition: AW_device.cxx:471
static void active_range_changed_cb(AW_root *awr, AW_gc_manager *gcman)
Definition: AW_preset.cxx:784
static const char * default_color(int cset, int elem)
int get_color_index() const
Definition: AW_preset.cxx:189
const char * awarname(const char *awarname_template, int idx)
Definition: ED4_flags.cxx:37
void set_changed_cb(const GcChangedCallback &ccb)
Definition: AW_preset.cxx:386
static bool color_groups_initialized()
Definition: AW_preset.cxx:338
int size() const
Definition: AW_preset.cxx:364
AW_awar * awar_float(const char *var_name, float default_value=0.0, AW_default default_file=AW_ROOT_DEFAULT)
Definition: AW_root.cxx:560
string colorlabel
Definition: AW_preset.cxx:170
void new_gc(int gc)
Definition: AW_device.cxx:449
#define true
Definition: ureadseq.h:14
void AW_save_properties(AW_window *aw)
Definition: AW_preset.cxx:1452
#define aw_assert(bed)
Definition: aw_position.hxx:29
static void all_fontsOrSizes_changed_cb(AW_root *, const AW_gc_manager *mgr, bool sizeChanged)
Definition: AW_preset.cxx:505
#define false
Definition: ureadseq.h:13
void fake_AW_init_color_groups()
#define AWAR_SELECTOR_FONT_NAME
Definition: AW_preset.cxx:1805
static void aw_set_sliders_from_color(AW_root *awr)
Definition: AW_preset.cxx:1653
AW_window * AW_create_gc_window(AW_root *aw_root, AW_gc_manager *gcman)
Definition: AW_preset.cxx:1373
AW_rgb_normalized rgb() const
Definition: AW_preset.cxx:1497
float h() const
Definition: AW_preset.cxx:1517
const char * parse_decl(const char *decl, const char *id_prefix)
Definition: AW_preset.cxx:207
void touch()
Definition: AW_awar.cxx:207
static void error(const char *msg)
Definition: mkptypes.cxx:96
static void aw_create_colorslider_awars(AW_root *awr)
Definition: AW_preset.cxx:1702
gc_type
Definition: AW_preset.cxx:140
static bool color_value_change_was_ignored
Definition: AW_preset.cxx:1640
const char * fontname_awarname(const char *gcman_id, const string &colname)
Definition: AW_preset.cxx:79
float b() const
Definition: aw_rgb.hxx:96
void add_gc_range(const char *gc_description)
Definition: AW_preset.cxx:728
AW_window * AW_preset_window(AW_root *root)
Definition: AW_preset.cxx:1920
#define CONSTEXPR_INLINE
Definition: cxxforward.h:111
void label(const char *label)
Definition: AW_window.cxx:102
int build_range_gc_number(int range_idx, int color_idx)
Definition: AW_preset.cxx:149
const char * rgb_nt
Definition: AW_preset.cxx:88
AW_hsv(const AW_rgb16 &col)
Definition: AW_preset.cxx:1494
static void add_common_property_menu_entries(AW_window *aw)
Definition: AW_preset.cxx:1440
const int GC_BACKGROUND
Definition: AW_preset.cxx:135
const char * description
Definition: AW_preset.cxx:87
static const char ** color_group_defaults
Definition: AW_preset.cxx:333
float v() const
Definition: AW_preset.cxx:1519
gc_desc(int gc_, gc_type type_)
Definition: AW_preset.cxx:177
void AW_copy_GC_colors(AW_root *aw_root, const char *source_gcman, const char *dest_gcman, const char *id0,...)
Definition: AW_preset.cxx:1090
int get_drag_gc() const
Definition: AW_preset.cxx:370
char * read_string() const
Definition: AW_awar.cxx:198
static bool show_range_overlay
Definition: AW_preset.cxx:336
const char * get_current_color(int idx) const
Definition: AW_preset.cxx:411
#define AW_COLOR_GROUP_NAME_LEN
const char * gcman_specific_awarname(const char *tpl, const char *gcman_id, const char *localpart)
Definition: AW_preset.cxx:63
AW_awar * awar(const char *awar)
Definition: AW_root.cxx:554
void AW_reactivate_all_questions(AW_window *)
bool has_font
Definition: AW_preset.cxx:172
void getColorRangeNames(int dimension, ConstStrArray &ids, ConstStrArray &names) const
Definition: AW_preset.cxx:814
string name2ID(const char *name)
Definition: AW_preset.cxx:154
va_end(argPtr)
#define RANGE_INDEX_BITS
Definition: AW_preset.cxx:146
float read_float() const
Definition: AW_awar.cxx:177
void trigger_changed_cb(GcChange whatChanged) const
Definition: AW_preset.cxx:387
void insert_default_option(AW_label choice_label, const char *mnemonic, const char *var_value, const char *name_of_color=NULp)
#define AWAR_SELECTOR_FONT_SIZE
Definition: AW_preset.cxx:1806
char * AW_get_color_group_name(AW_root *awr, int color_group)
Definition: AW_preset.cxx:1173
long int flag
Definition: f2c.h:39
void delay_changed_callbacks(bool suppress) const
Definition: AW_preset.cxx:399
#define ATPL_GCMAN_LOCAL
Definition: AW_preset.cxx:47
static const int STD_LABEL_LEN
Definition: AW_preset.cxx:1198
static ColorGroupDef color_group_def[AW_COLOR_GROUPS+1]
Definition: AW_preset.cxx:109
int get_dimension() const
Definition: AW_preset.cxx:273
void create_input_field(const char *awar_name, int columns=0)
Definition: AW_button.cxx:857
gc_range_type get_type() const
Definition: AW_preset.cxx:272
const char * colorgroupname_awarname(int color_group)
Definition: AW_preset.cxx:126
AW_awar * awar_int(const char *var_name, long default_value=0, AW_default default_file=AW_ROOT_DEFAULT)
Definition: AW_root.cxx:580
void AW_displayColorRange(AW_device *device, int first_range_gc, AW::Position start, AW_pos xsize, AW_pos ysize)
Definition: AW_preset.cxx:1381
void activateColorRange(const char *id)
Definition: AW_preset.cxx:795
#define IF_ASSERTION_USED(x)
Definition: arb_assert.h:308
void AW_getColorRangeNames(const AW_gc_manager *gcman, int dimension, ConstStrArray &ids, ConstStrArray &names)
Definition: AW_preset.cxx:1406
#define NO_FONT
Definition: AW_preset.cxx:52
void update_gc_color(int idx) const
Definition: AW_preset.cxx:667
#define AW_RANGE_COLORS
static void aw_create_color_chooser_window(AW_window *aww, const char *awar_name, const char *color_description)
Definition: AW_preset.cxx:1716
const char * getActiveColorRangeID(int *dimension) const
Definition: AW_preset.cxx:807
bool is_color_group() const
Definition: AW_preset.cxx:185
bool has_color_groups() const
Definition: AW_preset.cxx:361
static const int FONT_BUTTON_LEN
Definition: AW_preset.cxx:1200
AW_gc_manager(const char *name, AW_device *device_, int drag_gc_offset_, AW_window *aww_, int colorindex_base_)
Definition: AW_preset.cxx:340
#define MAX_FONTSIZE
Definition: aw_def.hxx:28
AW_awar * map(const char *awarn)
Definition: AW_awar.cxx:521
void init_all_fonts() const
Definition: AW_preset.cxx:927
static void aw_message_reload(AW_root *)
Definition: AW_preset.cxx:1886
va_start(argPtr, format)
static void color_group_use_changed_cb(AW_root *awr, AW_gc_manager *gcmgr)
Definition: AW_preset.cxx:710
const char * get_base_name() const
Definition: AW_preset.cxx:369
#define abs(x)
Definition: f2c.h:151
#define ATPL_GC_LOCAL
Definition: AW_preset.cxx:48
STATIC_ASSERT(AW_PLANAR_COLORS *AW_PLANAR_COLORS==AW_RANGE_COLORS)
void aw_message(const char *msg)
Definition: AW_status.cxx:1142
AW_option_menu_struct * create_option_menu(const char *awar_name)
void AW_save_specific_properties(AW_window *aw, const char *filename)
Definition: AW_preset.cxx:1448
void active_range_changed_cb(AW_root *awr)
Definition: AW_preset.cxx:771
AW_root * get_root()
Definition: aw_window.hxx:359
gc_type type
Definition: AW_preset.cxx:175
#define NULp
Definition: cxxforward.h:116
static bool use_color_groups
Definition: AW_preset.cxx:335
#define AWAR_CV_G
Definition: AW_preset.cxx:1632
AW_GCM_AREA
Definition: aw_preset.hxx:37
int first_range_gc() const
Definition: AW_preset.cxx:359
static void aw_create_font_chooser_awars(AW_root *awr)
Definition: AW_preset.cxx:1808
GB_ERROR write_string(const char *aw_string)
#define offset(field)
Definition: GLwDrawA.c:73
float r() const
Definition: aw_rgb.hxx:94
#define AWAR_RANGE_OVERLAY
Definition: AW_preset.cxx:43
void update_range_gc_color(int idx, const char *color) const
Definition: AW_preset.cxx:380
#define RANGE_INDEX_MASK
Definition: AW_preset.cxx:147
#define MIN_FONTSIZE
Definition: aw_def.hxx:26
static void create_color_button(AW_window *aws, const char *awar_name, const char *color_description)
Definition: AW_preset.cxx:1179
void AW_init_color_group_defaults(const char *for_program)
Definition: AW_preset.cxx:1113
void update_gc_font(int idx) const
Definition: AW_preset.cxx:431
void callback(const WindowCallback &cb)
Definition: AW_window.cxx:133
bool box(int gc, AW::FillStyle filled, const AW::Rectangle &rect, AW_bitset filteri=AW_ALL_DEVICES_SCALED)
Definition: aw_device.hxx:471
#define BUFSIZE
Definition: trnsprob.h:20
AW_awar * awar_string(const char *var_name, const char *default_value="", AW_default default_file=AW_ROOT_DEFAULT)
Definition: AW_root.cxx:570
GB_ERROR write_float(float aw_float)
AW_hsv(const AW_rgb_normalized &col)
Definition: AW_preset.cxx:1467
#define AWAR_CV_R
Definition: AW_preset.cxx:1631
const char * gc_awarname(const char *tpl, const char *gcman_id, const string &colname)
Definition: AW_preset.cxx:71
#define min(a, b)
Definition: f2c.h:153
#define AW_SPATIAL_COLORS
void label_length(int length)
Definition: AW_at.cxx:284
void GBT_splitNdestroy_string(ConstStrArray &names, char *&namelist, const char *separator, SplitMode mode)
void at_newline()
Definition: AW_at.cxx:119
void update_colors(const AW_gc_manager *gcman) const
Definition: AW_preset.cxx:549
static void AW_preset_create_font_chooser(AW_window *aws, const char *awar, const char *label, bool message_reload)
Definition: AW_preset.cxx:1892
#define TEST_EXPECT_EQUAL(expr, want)
Definition: test_unit.h:1294
GB_ERROR write_int(long aw_int)
AW_color_idx alloc_named_data_color(int colnum, const char *colorname)
Definition: AW_window.cxx:2071
const char * AW_get_font_shortname(AW_font font_nr)
Definition: AW_xfont.cxx:719
const char * gcman_awarname(const char *gcman_id, const char *localpart)
Definition: AW_preset.cxx:74
size_t get_position() const
Definition: arb_strbuf.h:112
char * GBS_global_string_copy(const char *templat,...)
Definition: arb_msg.cxx:194
const char * label
void put(char c)
Definition: arb_strbuf.h:174
string key
Definition: AW_preset.cxx:171
void create_button(const char *macro_name, AW_label label, const char *mnemonic=NULp, const char *color=NULp)
Definition: AW_button.cxx:448
#define AW_COLOR_GROUP_PREFIX
int AW_getFirstRangeGC(AW_gc_manager *gcman)
Definition: AW_preset.cxx:1418
const char * color_awarname(const char *gcman_id, const string &colname)
Definition: AW_preset.cxx:78
CONSTEXPR_INLINE bool valid_color_group(int color_group)
Definition: AW_preset.cxx:59
GB_write_int const char s
Definition: AW_awar.cxx:154
#define max(a, b)
Definition: f2c.h:154