Graphviz 13.1.3~dev.20250829.0113
Loading...
Searching...
No Matches
frmobjectui.c
Go to the documentation of this file.
1/*************************************************************************
2 * Copyright (c) 2011 AT&T Intellectual Property
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * https://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors: Details at https://graphviz.org
9 *************************************************************************/
10
11#include <stdbool.h>
12#include <stdio.h>
13
14#include <stdlib.h>
15#include "gui.h"
16#include <glade/glade.h>
17#include <gdk/gdkkeysyms.h>
18#include <gdk/gdk.h>
19#include "viewport.h"
20#include "frmobjectui.h"
21#include <assert.h>
22#include "gvprpipe.h"
23#include <stdint.h>
24#include <string.h>
25#include <util/agxbuf.h>
26#include <util/alloc.h>
27#include <util/strcasecmp.h>
28#include <util/startswith.h>
29#include <util/strview.h>
30#include <util/unreachable.h>
31
32static int sel_node;
33static int sel_edge;
34static int sel_graph;
35
36static char *safestrdup(const char *src) {
37 if (!src)
38 return NULL;
39 else
40 return gv_strdup(src);
41}
42static int get_object_type(void)
43{
44 if (gtk_toggle_button_get_active
45 ((GtkToggleButton *) glade_xml_get_widget(xml, "attrRB0")))
46 return AGRAPH;
47 if (gtk_toggle_button_get_active
48 ((GtkToggleButton *) glade_xml_get_widget(xml, "attrRB1")))
49 return AGNODE;
50 if (gtk_toggle_button_get_active
51 ((GtkToggleButton *) glade_xml_get_widget(xml, "attrRB2")))
52 return AGEDGE;
53 return -1;
54}
55
56static attr_t *new_attr(void) {
57 return gv_alloc(sizeof(attr_t));
58}
59
61{
62 attr_t *a = new_attr();
63 a->name = gv_strdup(sym->name);
64 switch (sym->kind) {
65 case AGRAPH:
66 a->objType[0] = 1;
67 a->defValG = safestrdup(sym->defval);
68 break;
69 case AGNODE:
70 a->objType[1] = 1;
71 a->defValN = safestrdup(sym->defval);
72 break;
73 case AGEDGE:
74 a->objType[2] = 1;
75 a->defValE = safestrdup(sym->defval);
76 break;
77 default:
79 }
80 return a;
81}
82
83static attr_t *new_attr_ref(attr_t * refAttr)
84{
85 attr_t *a = gv_alloc(sizeof(attr_t));
86 *a = *refAttr;
87 a->defValG = safestrdup(refAttr->defValG);
88 a->defValN = safestrdup(refAttr->defValN);
89 a->defValE = safestrdup(refAttr->defValE);
90 a->name = gv_strdup(refAttr->name);
91 a->value = safestrdup(refAttr->value);
92 return a;
93}
94
96{
97 int id;
98 for (id = 0; id < MAX_FILTERED_ATTR_COUNT; id++) {
99 gtk_label_set_text(l->fLabels[id], "");
100 }
101}
102
103// creates a new attr_list
104// attr_list is a basic stack implementation
105// with alphanumeric sorting functions
106// that uses quicksort
107static attr_list *attr_list_new(bool with_widgets) {
108 int id;
109 attr_list *l = gv_alloc(sizeof(attr_list));
110 /*create filter widgets */
111
112 if (with_widgets) {
113 for (id = 0; id < MAX_FILTERED_ATTR_COUNT; id++) {
114 l->fLabels[id] = (GtkLabel *) gtk_label_new("");
115
116 gtk_widget_add_events((GtkWidget *) l->fLabels[id],
117 GDK_BUTTON_MOTION_MASK |
118 GDK_POINTER_MOTION_MASK |
119 GDK_BUTTON_PRESS_MASK | GDK_KEY_PRESS |
120 GDK_BUTTON_RELEASE_MASK |
121 GDK_SCROLL | GDK_VISIBILITY_NOTIFY_MASK);
122
123 gtk_widget_show((GtkWidget *) l->fLabels[id]);
124 Color_Widget_bg("blue", (GtkWidget *) l->fLabels[id]);
125 gtk_fixed_put((GtkFixed *) glade_xml_get_widget(xml, "fixed6"),
126 (GtkWidget *) l->fLabels[id], 10, 110 + id * 13);
127 }
128 }
129 return l;
130}
131
132static int attr_compare_core(const void *key, const void *candidate) {
133 const char *k = key;
134 const attr_t *const *c = candidate;
135 return strcasecmp(k, (*c)->name);
136}
137
138static int attr_compare(const void *x, const void *y) {
139 const attr_t *const *a = x;
140 const attr_t *const *b = y;
141 return attr_compare_core((*a)->name, b);
142}
143
144static void attr_list_add(attr_list *l, attr_t *a) {
145 if (!l || !a)
146 return;
147 LIST_APPEND(&l->attributes, a);
149 /*update indices */
150 for (size_t id = 0; id < LIST_SIZE(&l->attributes); ++id)
151 LIST_GET(&l->attributes, id)->index = id;
152}
153
155{
156 switch (c) {
157 case 'A':
158 return attr_alpha;
159 break;
160 case 'F':
161 return attr_float;
162 break;
163 case 'B':
164 return attr_bool;
165 break;
166 case 'I':
167 return attr_int;
168 break;
169 default:
170 break;
171 }
172 return attr_alpha;
173}
174
175static void object_type_helper(strview_t a, int *t) {
176 if (strview_str_eq(a, "GRAPH"))
177 t[0] = 1;
178 if (strview_str_eq(a, "CLUSTER"))
179 t[0] = 1;
180 if (strview_str_eq(a, "NODE"))
181 t[1] = 1;
182 if (strview_str_eq(a, "EDGE"))
183 t[2] = 1;
184 if (strview_str_eq(a, "ANY_ELEMENT")) {
185 t[0] = 1;
186 t[1] = 1;
187 t[2] = 1;
188 }
189}
190
191static void set_attr_object_type(const char *str, int *t) {
192 strview_t a = strview(str, ' ');
193 object_type_helper(a, t);
194 while (true) {
195 const char *start = a.data + a.size;
196 if (!startswith(start, " or ")) {
197 break;
198 }
199 start += strlen(" or ");
200 const char *end = strstr(start, " or ");
201 if (end == NULL) {
202 a = strview(start, '\0');
203 } else {
204 a = (strview_t){.data = start, .size = (size_t)(end - start)};
205 }
206 object_type_helper(a, t);
207 }
208}
209
210static attr_t *binarySearch(attr_list *l, const char *searchKey) {
212 attr_t **attrp = bsearch(searchKey, LIST_FRONT(&l->attributes),
213 LIST_SIZE(&l->attributes), sizeof(attr_t*),
215 if (attrp != NULL) {
216 return *attrp;
217 }
218 return NULL;
219}
220
221static int cmp(const void *key, const void *candidate) {
222 const attr_t *const a = candidate;
223 return strncasecmp(key, a->name, strlen(key));
224}
225
226static void create_filtered_list(const char *prefix, attr_list *sl,
227 attr_list *tl) {
228 int objKind = get_object_type();
229
230 if (strlen(prefix) == 0)
231 return;
232 /*locate first occurrence */
233 LIST_SYNC(&sl->attributes);
234 attr_t *at = bsearch(prefix, LIST_FRONT(&sl->attributes),
235 LIST_SIZE(&sl->attributes), sizeof(attr_t), cmp);
236 if (!at)
237 return;
238
239 /*go backward to get the first */
240 for (int res = 0; at->index > 0 && res == 0; ) {
241 at = LIST_GET(&sl->attributes, at->index - 1);
242 res = strncasecmp(prefix, at->name, strlen(prefix));
243 }
244 for (int res = 0; at->index < LIST_SIZE(&sl->attributes) && res == 0; ) {
245 at = LIST_GET(&sl->attributes, at->index + 1);
246 res = strncasecmp(prefix, at->name, strlen(prefix));
247 if (res == 0 && at->objType[objKind] == 1)
249 }
250}
251
252static void filter_attributes(const char *prefix, topview *t) {
253 int tmp;
254
255 attr_list *l = t->attributes;
256 int objKind = get_object_type();
257
258 attr_list *fl = attr_list_new(false);
261 for (size_t ind = 0; ind < LIST_SIZE(&fl->attributes); ++ind) {
262 gtk_label_set_text(l->fLabels[ind], LIST_GET(&fl->attributes, ind)->name);
263 }
264
265 Color_Widget_bg("white", glade_xml_get_widget(xml, "txtAttr"));
266 if (LIST_IS_EMPTY(&fl->attributes))
267 Color_Widget_bg("red", glade_xml_get_widget(xml, "txtAttr"));
268 /*a new attribute can be entered */
269
270 gtk_widget_show(glade_xml_get_widget(xml, "txtValue"));
271 gtk_widget_show(glade_xml_get_widget(xml, "txtDefValue"));
272
273 gtk_entry_set_text((GtkEntry *)
274 glade_xml_get_widget(xml, "txtDefValue"), "");
275 gtk_entry_set_text((GtkEntry *) glade_xml_get_widget(xml, "txtValue"),
276 "");
277 gtk_widget_set_sensitive(glade_xml_get_widget(xml, "txtDefValue"), 1);
278 gtk_widget_show(glade_xml_get_widget(xml, "attrAddBtn"));
279 gtk_widget_hide(glade_xml_get_widget(xml, "attrApplyBtn"));
280 gtk_widget_hide(glade_xml_get_widget(xml, "attrApplyAllBtn"));
281 gtk_widget_hide(glade_xml_get_widget(xml, "attrSearchBtn"));
282 gtk_toggle_button_set_active((GtkToggleButton *)
283 glade_xml_get_widget(xml, "attrProg"), 0);
284
285 if (strlen(prefix) == 0) {
286 gtk_widget_hide(glade_xml_get_widget(xml, "attrAddBtn"));
287 gtk_widget_hide(glade_xml_get_widget(xml, "attrApplyBtn"));
288 gtk_widget_hide(glade_xml_get_widget(xml, "attrApplyAllBtn"));
289 gtk_widget_hide(glade_xml_get_widget(xml, "attrSearchBtn"));
290 gtk_widget_hide(glade_xml_get_widget(xml, "attrAddBtn"));
291 gtk_widget_hide(glade_xml_get_widget(xml, "txtValue"));
292 gtk_widget_hide(glade_xml_get_widget(xml, "txtDefValue"));
293 Color_Widget_bg("white", glade_xml_get_widget(xml, "txtAttr"));
294 }
295
296 for (size_t ind = 0; ind < LIST_SIZE(&fl->attributes); ++ind) {
297 if (strcasecmp(prefix, LIST_GET(&fl->attributes, ind)->name) == 0) { // an existing attribute
298
299 Color_Widget_bg("green", glade_xml_get_widget(xml, "txtAttr"));
300
301 if (get_object_type() == AGRAPH)
302 gtk_entry_set_text((GtkEntry *)
303 glade_xml_get_widget(xml,
304 "txtDefValue"),
305 LIST_GET(&fl->attributes, 0)->defValG);
306 if (get_object_type() == AGNODE)
307 gtk_entry_set_text((GtkEntry *)
308 glade_xml_get_widget(xml,
309 "txtDefValue"),
310 LIST_GET(&fl->attributes, 0)->defValN);
311 if (get_object_type() == AGEDGE)
312 gtk_entry_set_text((GtkEntry *)
313 glade_xml_get_widget(xml,
314 "txtDefValue"),
315 LIST_GET(&fl->attributes, 0)->defValE);
316 gtk_widget_set_sensitive(glade_xml_get_widget
317 (xml, "txtDefValue"), 0);
318 gtk_widget_hide(glade_xml_get_widget(xml, "attrAddBtn"));
319 gtk_widget_show(glade_xml_get_widget(xml, "attrApplyBtn"));
320 gtk_widget_show(glade_xml_get_widget(xml, "attrApplyAllBtn"));
321 gtk_widget_show(glade_xml_get_widget(xml, "attrSearchBtn"));
322 gtk_toggle_button_set_active((GtkToggleButton *)
323 glade_xml_get_widget(xml,
324 "attrProg"),
325 LIST_GET(&fl->attributes, 0)->propagate);
326 break;
327 }
328 }
329
330 tmp = (objKind == AGNODE && sel_node)
331 || (objKind == AGEDGE && sel_edge)
332 || (objKind == AGRAPH && sel_graph);
333 gtk_widget_set_sensitive(glade_xml_get_widget(xml, "attrApplyBtn"),
334 tmp);
335}
336
337// attribute text changed call back
338
339_BB void on_txtAttr_changed(GtkWidget *widget, void *user_data) {
340 (void)user_data;
341 filter_attributes(gtk_entry_get_text((GtkEntry*)widget), view->Topview);
342}
343
344static void doApply(void)
345{
346 char *attr_name;
347 int prog;
348 Agnode_t *v;
349 Agedge_t *e;
350 Agraph_t *g;
351 int objKind;
352 Agsym_t *sym;
353 attr_t *attr;
354
355 /*values to be applied to selected objects */
356 attr_name =
357 (char *) gtk_entry_get_text((GtkEntry *)
358 glade_xml_get_widget(xml, "txtAttr"));
359 const char *def_val = gtk_entry_get_text((GtkEntry *)
360 glade_xml_get_widget(xml,
361 "txtDefValue"));
362 const char *value = gtk_entry_get_text((GtkEntry *)
363 glade_xml_get_widget(xml, "txtValue"));
364 prog =
365 gtk_toggle_button_get_active((GtkToggleButton *)
366 glade_xml_get_widget(xml,
367 "attrProg"));
368 g = view->g[view->activeGraph];
369 objKind = get_object_type();
370 attr = binarySearch(view->Topview->attributes, attr_name);
371 assert(attr);
372 attr->propagate = prog;
373 sym = agattr_text(g, objKind, attr_name, NULL);
374 if (!sym) /*it shouldnt be null, just in case it is null */
375 sym = agattr_text(g, objKind, attr_name, def_val);
376 /*graph */
377 if (objKind == AGRAPH)
378 agset(g, attr_name, value);
379 /*nodes */
380 else if (objKind == AGNODE) {
381 for (v = agfstnode(g); v; v = agnxtnode(g, v)) {
382 if (ND_selected(v))
383 agxset(v, sym, value);
384 }
385 }
386 /*edges */
387 else if (objKind == AGEDGE) {
388 for (v = agfstnode(g); v; v = agnxtnode(g, v)) {
389 for (e = agfstout(g, v); e; e = agnxtout(g, e)) {
390 if (ED_selected(e))
391 agxset(e, sym, value);
392 }
393 }
394 } else
395 fprintf(stderr,
396 "on_attrApplyBtn_clicked: unknown object kind %d\n",
397 objKind);
398}
399
400_BB void on_attrApplyBtn_clicked(GtkWidget *widget, void *user_data) {
401 (void)widget;
402 (void)user_data;
403
404 doApply();
405}
406
407_BB void on_attrRB0_clicked(GtkWidget *widget, void *user_data) {
408 (void)widget;
409 (void)user_data;
410
411 filter_attributes(gtk_entry_get_text((GtkEntry*)glade_xml_get_widget(xml,
412 "txtAttr")), view->Topview);
413
414}
415
416/* This is the action attached to the publish button on the attributes
417 * window. What should happen?
418 */
419_BB void on_attrProg_toggled(GtkWidget *widget, void *user_data) {
420 (void)widget;
421 (void)user_data;
422 /* FIX */
423}
424
425_BB void on_attrAddBtn_clicked(GtkWidget *widget, void *user_data) {
426 (void)widget;
427 (void)user_data;
428
429 char *attr_name;
430 int objKind;
431 topview *t;
432 Agraph_t *g;
433 attr_t *attr;
434 objKind = get_object_type();
435
436 /*values to be applied to selected objects */
437 attr_name =
438 (char *) gtk_entry_get_text((GtkEntry *)
439 glade_xml_get_widget(xml, "txtAttr"));
440 const char *defValue = gtk_entry_get_text((GtkEntry *)
441 glade_xml_get_widget(xml,
442 "txtDefValue"));
443 g = view->g[view->activeGraph];
444 t = view->Topview;
445 /*try to find first */
446 attr = binarySearch(t->attributes, attr_name);
447 if (!attr) {
448 attr = new_attr();
449 attr->index = 0;
450 attr->name = safestrdup(attr_name);
451 attr->type = attr_alpha;
452 attr->value = gv_strdup("");
453 attr->widget = NULL;
454 attr_list_add(t->attributes, attr);
455 }
456 attr->propagate = 0;
457
458 if (objKind == AGRAPH) {
459 agattr_text(g, AGRAPH, attr_name, defValue);
460 attr->defValG = safestrdup(defValue);
461 attr->objType[0] = 1;
462 }
463
464 /*nodes */
465 else if (objKind == AGNODE) {
466 agattr_text(g, AGNODE, attr_name, defValue);
467 attr->defValN = safestrdup(defValue);
468 attr->objType[1] = 1;
469 } else if (objKind == AGEDGE) {
470 agattr_text(g, AGEDGE, attr_name, defValue);
471 attr->defValE = safestrdup(defValue);
472 attr->objType[2] = 1;
473 } else
474 fprintf(stderr, "on_attrAddBtn_clicked: unknown object kind %d\n",
475 objKind);
476 filter_attributes(attr_name, view->Topview);
477}
478
480{
481 attr_t *attr;
482 attr_list *l;
483 FILE *file;
484 char buffer[BUFSIZ];
485 static char *smyrna_attrs;
486 char *a;
487
488 if (!smyrna_attrs)
489 smyrna_attrs = smyrnaPath("attrs.txt");
490 g = view->g[view->activeGraph];
491 l = attr_list_new(true);
492 file = fopen(smyrna_attrs, "r");
493 if (file != NULL) {
494 for (size_t i = 0; fgets(buffer, sizeof(buffer), file) != NULL; ++i) {
495 attr = new_attr();
496 a = strtok(buffer, ",");
497 attr->index = i;
498 attr->type = get_attr_data_type(a[0]);
499 for (int idx = 0; (a = strtok(NULL, ",")); ++idx) {
500 /*C,(0)color, (1)black, (2)EDGE Or NODE Or CLUSTER, (3)ALL_ENGINES */
501
502 switch (idx) {
503 case 0:
504 attr->name = gv_strdup(a);
505 break;
506 case 1:
507 attr->defValG = gv_strdup(a);
508 attr->defValN = gv_strdup(a);
509 attr->defValE = gv_strdup(a);
510 break;
511 case 2:
513 break;
514 default:
515 break;
516 }
517 }
518 attr_list_add(l, attr);
519
520 }
521 fclose(file);
522 }
523 for (Agsym_t *sym = NULL; (sym = agnxtattr(g, AGRAPH, sym)); ) {
524 attr = binarySearch(l, sym->name);
525 if (attr)
526 attr->objType[0] = 1;
527 else {
528 attr = new_attr_with_ref(sym);
529 attr_list_add(l, attr);
530 }
531 }
532 for (Agsym_t *sym = NULL; (sym = agnxtattr(g, AGNODE, sym)); ) {
533 attr = binarySearch(l, sym->name);
534 if (attr) {
535 attr->objType[1] = 1;
536
537 } else {
538 attr = new_attr_with_ref(sym);
539 attr_list_add(l, attr);
540 }
541
542 }
543 for (Agsym_t *sym = NULL; (sym = agnxtattr(g, AGEDGE, sym)); ) {
544 attr = binarySearch(l, sym->name);
545 if (attr)
546 attr->objType[2] = 1;
547 else {
548 attr = new_attr_with_ref(sym);
549 attr_list_add(l, attr);
550 }
551 }
552 return l;
553}
554
555static void set_header_text(void)
556{
557 int nodeCnt = 0;
558 int edgeCnt = 0;
559 char buf[512];
560
562 for (Agnode_t *v = agfstnode(g); v; v = agnxtnode(g, v)) {
563 if (ND_selected(v))
564 nodeCnt++;
565 for (Agedge_t *ep = agfstout(g, v); ep; ep = agnxtout(g, ep)) {
566 if (ND_selected(v))
567 edgeCnt++;
568 }
569 }
570 sel_node = nodeCnt;
571 sel_edge = edgeCnt;
572 sel_graph = 1;
573
574 snprintf(buf, sizeof(buf), "%d Nodes and %d edges selected", nodeCnt,
575 edgeCnt);
576 gtk_label_set_text((GtkLabel *) glade_xml_get_widget(xml, "label124"),
577 buf);
578 gtk_entry_set_text((GtkEntry *) glade_xml_get_widget(xml, "txtAttr"),
579 "");
580 Color_Widget_bg("white", glade_xml_get_widget(xml, "fixed6"));
581}
582
583void showAttrsWidget(void) {
584 if (view->activeGraph < 0) {
585 void *const dlg = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL,
586 GTK_MESSAGE_QUESTION, GTK_BUTTONS_OK,
587 "No active graph");
588 (void)gtk_dialog_run(dlg);
589 gtk_widget_destroy(dlg);
590 return;
591 }
592
593 gtk_widget_hide(glade_xml_get_widget(xml, "dlgSettings"));
594 gtk_widget_show(glade_xml_get_widget(xml, "dlgSettings"));
595 gtk_notebook_set_current_page((GtkNotebook *)
596 glade_xml_get_widget(xml, "notebook3"),
600}
601
602static void gvpr_select(const char *attrname, const char *regex_str,
603 int objType) {
604
605 char *bf2;
606 int i, argc;
607
608 agxbuf sf = {0};
609
610 if (objType == AGNODE)
611 agxbprint(&sf, "N[%s==\"%s\"]{selected = \"1\"}", attrname, regex_str);
612 else if (objType == AGEDGE)
613 agxbprint(&sf, "E[%s==\"%s\"]{selected = \"1\"}", attrname, regex_str);
614
615 bf2 = agxbdisown(&sf);
616
617 argc = 1;
618 if (*bf2 != '\0')
619 argc++;
620 char *argv[3] = {0};
621 size_t j = 0;
622 argv[j++] = "smyrna";
623 argv[j++] = bf2;
624
625 run_gvpr(view->g[view->activeGraph], j, argv);
626 for (i = 1; i < argc; i++)
627 free(argv[i]);
629}
630
631_BB void on_attrSearchBtn_clicked(GtkWidget *widget, void *user_data) {
632 (void)widget;
633 (void)user_data;
634
635 const char *attrname = gtk_entry_get_text((GtkEntry *)
636 glade_xml_get_widget(xml, "txtAttr"));
637 const char *regex_str = gtk_entry_get_text((GtkEntry *)
638 glade_xml_get_widget(xml, "txtValue"));
639 gvpr_select(attrname, regex_str, get_object_type());
640
641}
static int agxbprint(agxbuf *xb, const char *fmt,...)
Printf-style output to an agxbuf.
Definition agxbuf.h:233
static char * agxbdisown(agxbuf *xb)
Definition agxbuf.h:326
Memory allocation wrappers that exit on failure.
static char * gv_strdup(const char *original)
Definition alloc.h:101
static void * gv_alloc(size_t size)
Definition alloc.h:47
#define _BB
Definition callbacks.h:20
static void set_attr_object_type(const char *str, int *t)
static void object_type_helper(strview_t a, int *t)
static char * safestrdup(const char *src)
Definition frmobjectui.c:36
static attr_list * attr_list_new(bool with_widgets)
_BB void on_attrApplyBtn_clicked(GtkWidget *widget, void *user_data)
static attr_t * binarySearch(attr_list *l, const char *searchKey)
static void create_filtered_list(const char *prefix, attr_list *sl, attr_list *tl)
static void attr_list_add(attr_list *l, attr_t *a)
static int cmp(const void *key, const void *candidate)
static attr_t * new_attr_with_ref(Agsym_t *sym)
Definition frmobjectui.c:60
static attr_t * new_attr(void)
Definition frmobjectui.c:56
_BB void on_attrSearchBtn_clicked(GtkWidget *widget, void *user_data)
static attr_t * new_attr_ref(attr_t *refAttr)
Definition frmobjectui.c:83
static void reset_attr_list_widgets(attr_list *l)
Definition frmobjectui.c:95
_BB void on_attrProg_toggled(GtkWidget *widget, void *user_data)
void showAttrsWidget(void)
static void doApply(void)
static void set_header_text(void)
static int attr_compare(const void *x, const void *y)
static attr_data_type get_attr_data_type(char c)
static void gvpr_select(const char *attrname, const char *regex_str, int objType)
static int attr_compare_core(const void *key, const void *candidate)
static int sel_node
Definition frmobjectui.c:32
static int get_object_type(void)
Definition frmobjectui.c:42
static int sel_edge
Definition frmobjectui.c:33
_BB void on_txtAttr_changed(GtkWidget *widget, void *user_data)
static void filter_attributes(const char *prefix, topview *t)
static int sel_graph
Definition frmobjectui.c:34
_BB void on_attrAddBtn_clicked(GtkWidget *widget, void *user_data)
_BB void on_attrRB0_clicked(GtkWidget *widget, void *user_data)
attr_list * load_attr_list(Agraph_t *g)
#define ATTR_NOTEBOOK_IDX
Definition frmobjectui.h:15
void free(void *)
require define api prefix
Definition gmlparse.y:17
node NULL
Definition grammar.y:181
Agsym_t * agattr_text(Agraph_t *g, int kind, char *name, const char *value)
creates or looks up text attributes of a graph
Definition attr.c:334
int agset(void *obj, char *name, const char *value)
Definition attr.c:475
Agsym_t * agnxtattr(Agraph_t *g, int kind, Agsym_t *attr)
permits traversing the list of attributes of a given type
Definition attr.c:363
int agxset(void *obj, Agsym_t *sym, const char *value)
Definition attr.c:522
Agedge_t * agfstout(Agraph_t *g, Agnode_t *n)
Definition edge.c:26
Agedge_t * agnxtout(Agraph_t *g, Agedge_t *e)
Definition edge.c:41
Agnode_t * agnxtnode(Agraph_t *g, Agnode_t *n)
Definition node.c:48
Agnode_t * agfstnode(Agraph_t *g)
Definition node.c:41
@ AGEDGE
Definition cgraph.h:207
@ AGNODE
Definition cgraph.h:207
@ AGRAPH
Definition cgraph.h:207
void Color_Widget_bg(char *colorstring, GtkWidget *widget)
Definition gui.c:24
GladeXML * xml
Definition gui.c:22
static uint64_t id
Definition gv2gml.c:40
int run_gvpr(Agraph_t *srcGraph, size_t argc, char *argv[])
Definition gvprpipe.c:41
textitem scanner parser str
Definition htmlparse.y:218
#define LIST_SIZE(list)
Definition list.h:80
#define LIST_APPEND(list, item)
Definition list.h:132
#define LIST_SORT(list, cmp)
Definition list.h:347
#define LIST_FRONT(list)
Definition list.h:190
#define LIST_IS_EMPTY(list)
Definition list.h:90
#define LIST_SYNC(list)
Definition list.h:336
#define LIST_GET(list, index)
Definition list.h:165
char * smyrnaPath(char *suffix)
Definition main.c:51
ViewInfo * view
Definition viewport.c:37
attr_data_type
Definition smyrnadefs.h:58
@ attr_alpha
Definition smyrnadefs.h:58
@ attr_int
Definition smyrnadefs.h:58
@ attr_float
Definition smyrnadefs.h:58
@ attr_bool
Definition smyrnadefs.h:58
#define MAX_FILTERED_ATTR_COUNT
Definition smyrnadefs.h:56
#define ED_selected(e)
Definition smyrnadefs.h:169
#define ND_selected(n)
Definition smyrnadefs.h:156
static bool startswith(const char *s, const char *prefix)
does the string s begin with the string prefix?
Definition startswith.h:11
platform abstraction for case-insensitive string functions
graph or subgraph
Definition cgraph.h:424
string attribute descriptor symbol in Agattr_s.dict
Definition cgraph.h:651
char * name
Definition cgraph.h:653
unsigned char kind
Definition cgraph.h:656
char * defval
Definition cgraph.h:654
topview * Topview
Definition smyrnadefs.h:307
Agraph_t ** g
Definition smyrnadefs.h:290
int activeGraph
Definition smyrnadefs.h:294
GtkLabel * fLabels[MAX_FILTERED_ATTR_COUNT]
Definition smyrnadefs.h:79
attrs_t attributes
Definition smyrnadefs.h:78
char * defValN
Definition smyrnadefs.h:66
char * name
Definition smyrnadefs.h:63
int propagate
Definition smyrnadefs.h:71
size_t index
Definition smyrnadefs.h:62
GtkWidget * widget
Definition smyrnadefs.h:70
char * defValG
Definition smyrnadefs.h:65
char * value
Definition smyrnadefs.h:64
attr_data_type type
Definition smyrnadefs.h:68
int objType[3]
Definition smyrnadefs.h:69
char * defValE
Definition smyrnadefs.h:67
a non-owning string reference
Definition strview.h:20
const char * data
start of the pointed to string
Definition strview.h:21
size_t size
extent of the string in bytes
Definition strview.h:22
attr_list * attributes
Definition smyrnadefs.h:234
Non-owning string references.
static bool strview_str_eq(strview_t a, const char *b)
compare a string reference to a string for equality
Definition strview.h:98
static strview_t strview(const char *referent, char terminator)
create a string reference
Definition strview.h:26
#define UNREACHABLE()
Definition unreachable.h:30