00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150 #ifndef DaVinci_INCLUDED
00151 #define DaVinci_INCLUDED
00152
00153
00154
00155 #if defined(defs_INCLUDED) && !defined(USE_STANDARD_TYPES)
00156 #undef short
00157 #undef int
00158 #undef long
00159 #endif // defined(defs_INCLUDED) && !defined(USE_STANDARD_TYPES)
00160
00161 #include <stdio.h>
00162 #include <assert.h>
00163 #include <sys/types.h>
00164 #include <queue>
00165 #if (__GNUC__==2)
00166 #include <hash_map>
00167 using std::hash_map;
00168 #else
00169 #include <ext/hash_map>
00170 using __gnu_cxx::hash_map;
00171 using __gnu_cxx::hash;
00172 #endif
00173 #include <set>
00174
00175 #include "defs.h"
00176 #include "errors.h"
00177 #include "cxx_memory.h"
00178
00179 typedef void *NODE_ID;
00180 #define MAX_VIEW_NUM 64
00181
00182 struct EDGE_ID {
00183 NODE_ID src;
00184 NODE_ID dst;
00185
00186 EDGE_ID(NODE_ID s, NODE_ID d) : src(s), dst(d) {}
00187 };
00188
00189
00190
00191
00192
00193 class DaVinci_Callback {
00194 public:
00195 virtual void Node_Select(const INT n_ids, const NODE_ID id_array[]);
00196 virtual void Edge_Select(const EDGE_ID& edge_id);
00197 virtual void Menu_Select(const char *menu_id);
00198 };
00199
00200 class DaVinci;
00201
00202 typedef enum {
00203 NS_UNSET,
00204 NS_BOX,
00205 NS_CIRCLE,
00206 NS_ELLIPSE,
00207 NS_RHOMBUS,
00208 NS_TEXT
00209
00210 } NODE_SHAPE;
00211
00212 typedef enum {
00213 NB_UNSET,
00214 NB_SINGLE,
00215 NB_DOUBLE
00216 } NODE_BORDER;
00217
00218 typedef enum {
00219 NH_UNSET,
00220 NH_HIDE,
00221 NH_SHOW
00222 } NODE_HIDE;
00223
00224 class NODE_TYPE {
00225 private:
00226 char _type_name[20];
00227 char _node_color[30];
00228 NODE_SHAPE _node_shape;
00229 NODE_BORDER _border;
00230 NODE_HIDE _hide;
00231
00232
00233 friend class DaVinci;
00234 public:
00235 NODE_TYPE() {
00236 _type_name[0] = '\0';
00237 _node_color[0] = '\0';
00238 _node_shape = NS_UNSET;
00239 _border = NB_UNSET;
00240 _hide = NH_UNSET;
00241 }
00242 NODE_TYPE& Name(const char *typ_name);
00243 NODE_TYPE& Color(const char *rgb);
00244 NODE_TYPE& Shape(NODE_SHAPE ns) {
00245 _node_shape = ns; return *this;
00246 }
00247 NODE_TYPE& Boarder(NODE_BORDER nb) {
00248 _border = nb; return *this;
00249 }
00250 NODE_TYPE& Hidden(NODE_HIDE nh) {
00251 _hide = nh; return *this;
00252 }
00253 };
00254
00255 typedef enum {
00256 EP_UNSET,
00257 EP_SOLID,
00258 EP_DOTTED,
00259 EP_DASHED,
00260 EP_THICK,
00261 EP_DOUBLE
00262 } EDGE_PATTERN;
00263
00264 typedef enum {
00265 ED_UNSET,
00266 ED_NORMAL,
00267 ED_INVERSE,
00268 ED_BOTH,
00269 ED_NONE
00270 } EDGE_DIR;
00271
00272 class EDGE_TYPE {
00273 private:
00274 char _type_name[20];
00275 char _edge_color[30];
00276 EDGE_PATTERN _edge_pattern;
00277 EDGE_DIR _edge_dir;
00278
00279 friend class DaVinci;
00280 public:
00281 EDGE_TYPE() {
00282 _type_name[0] = '\0';
00283 _edge_color[0] = '\0';
00284 _edge_pattern = EP_UNSET;
00285 _edge_dir = ED_UNSET;
00286 }
00287 EDGE_TYPE& Name(const char *typ_name);
00288 EDGE_TYPE& Color(const char *rgb);
00289 EDGE_TYPE& Pattern(EDGE_PATTERN pat) { _edge_pattern = pat; return *this; }
00290 EDGE_TYPE& Direction(EDGE_DIR dir) { _edge_dir = dir; return *this; }
00291 };
00292
00293 struct MENU_INFO {
00294 const char *id;
00295 const char *label;
00296 bool initially_active;
00297 INT n_subitems;
00298 MENU_INFO *subitems;
00299 };
00300
00301 typedef enum {
00302 EK_COM_ERROR,
00303 EK_OK,
00304 EK_SEL_EDGE,
00305 EK_SEL_MENU,
00306 EK_SEL_NODES,
00307 EK_QUIT,
00308 EK_CLOSE,
00309 EK_DISCONNECT
00310
00311 } EVENT_KIND;
00312
00313 typedef enum{
00314 CONTEX_UNUSE,
00315 CONTEX_ACTIVE
00316 }CONTEX_TYPE;
00317
00318 struct EVENT_T {
00319 EVENT_KIND kind;
00320 union {
00321 struct {
00322 const char *msg;
00323 } com_error;
00324
00325 struct {
00326 NODE_ID edge_src;
00327 NODE_ID edge_dst;
00328 } sel_edge;
00329
00330 struct {
00331 const char *label;
00332 } sel_menu;
00333
00334 struct {
00335 INT n_nodes;
00336 NODE_ID *node_ids;
00337 } sel_nodes;
00338 } u;
00339 };
00340
00341 struct Equal_obj {
00342 bool operator()(const char* s1, const char* s2) const {
00343 return strcmp(s1, s2) == 0;
00344 }
00345 };
00346
00347 typedef enum {
00348 DM_ACTIVE,
00349 DM_INACTIVE,
00350 DM_UNKNOWN
00351 } Item_status;
00352
00353 typedef hash_map< const char *, Item_status,
00354 hash<const char *>, Equal_obj > Item_info;
00355
00356 class Menu_info {
00357 private:
00358 MEM_POOL *_m;
00359 public:
00360 Item_info items;
00361
00362 Menu_info(MEM_POOL *m) : _m(m) {}
00363 ~Menu_info() {}
00364 void operator=(Menu_info&);
00365 Menu_info(Menu_info&);
00366
00367 const char *Add(const char *cp);
00368 void Set(const char *cp, Item_status status);
00369 };
00370
00371 typedef const char *DA_ACK;
00372
00373 class DaVinci {
00374 private:
00375 class IO {
00376 private:
00377 FILE *_to_fp;
00378 FILE *_from_fp;
00379 FILE *_trace_fp;
00380 bool _trace_tagged;
00381 public:
00382 IO() {
00383 _to_fp = _from_fp = _trace_fp = NULL;
00384 _trace_tagged = false;
00385 }
00386 void Trace(FILE *tfp) { _trace_fp = tfp; }
00387 ~IO();
00388
00389 void Init(FILE *to, FILE *from) {
00390 _to_fp = to;
00391 _from_fp = from;
00392 }
00393 void Close();
00394 void Out_Fmt(const char *fmt, ...);
00395 char *In_Line();
00396 };
00397 typedef UINT32 FTAG;
00398 typedef FTAG FTAGS;
00399
00400 IO _io;
00401 MEM_POOL *_m;
00402 std::queue<EVENT_T> _event_q;
00403 std::set<NODE_ID> _node_def_set;
00404 std::set<NODE_ID> _node_ref_set;
00405 Menu_info _menu_state;
00406 bool _basic_menu_added;
00407 bool _in_event_loop;
00408 bool _display_ok;
00409 bool _usage_check;
00410 FTAG _ftag_last;
00411 INT _node_cnt;
00412 INT _edge_cnt;
00413 pid_t _pid;
00414 INT _contex;
00415 static std::queue<EVENT_T> _event_q_socket[MAX_VIEW_NUM];
00416 static INT _tcp_socket ;
00417 static INT _davinci_count ;
00418 static INT _contex_count ;
00419 static CONTEX_TYPE _contex_use_array[MAX_VIEW_NUM];
00420 static INT _current_contex ;
00421 static bool _use_socket;
00422
00423 const char *Ft_Str(const FTAG ftag);
00424 void Usage_Error(FTAG curr, FTAGS prereq);
00425
00426 bool Usage_Ok(FTAG curr, FTAGS prereq) {
00427 if ( _display_ok && (prereq == 0 || (_ftag_last & prereq)) ) {
00428 _ftag_last = curr;
00429 return true;
00430 }
00431 Usage_Error(curr, prereq);
00432 return false;
00433 }
00434 DA_ACK Wait_For_Ack();
00435
00436 DA_ACK Emit_Ack(const char *line) {
00437 assert( strchr( line, '\n' ) == NULL );
00438 _io.Out_Fmt( line );
00439 _io.Out_Fmt( "\n" );
00440 return Wait_For_Ack();
00441 }
00442 void Emit_Do(const char *line) {
00443 DA_ACK msg = Emit_Ack( line );
00444 if ( msg ) {
00445 fprintf(stderr, "Unexpected DaVinci error: %s\n", msg);
00446 }
00447 }
00448 const char *Parse_Menu_Label(const char *epfx);
00449 bool Parse_Event(const char *line, EVENT_T *event);
00450 bool Parse_Node_Ids(const char *epfx,
00451 INT *n_nodes, NODE_ID **node_ids);
00452
00453 void Emit_Menu(INT n_items, const MENU_INFO *items);
00454 void Emit_Attr(const NODE_TYPE& nt, const char **comma);
00455 void Emit_Attr(const EDGE_TYPE& et);
00456
00457 void Menu_Basic_Do( const char *label );
00458 DA_ACK Menu_Set_Active();
00459
00460 void Kill_Davinci();
00461 public:
00462 static bool enabled(bool msg) {
00463 bool is_enabled = ( getenv("DAVINCIHOME") != NULL );
00464 if(!is_enabled) {
00465 _use_socket = true;
00466 is_enabled = (getenv("UDRAWIP") != NULL);
00467 }
00468 if ( ! is_enabled ) {
00469 static bool msg_given = false;
00470 if ( ! msg_given ) {
00471 DevWarn("daVinci not enabled; %s\n",
00472 "must set DAVINCIHOME and put daVinci on path.");
00473 msg_given = true;
00474 }
00475 }
00476 return is_enabled;
00477 }
00478
00479 DaVinci(MEM_POOL *m, FILE *trace_fp = NULL, bool usage_check = false);
00480 ~DaVinci();
00481
00482 bool is_ok() const { return _display_ok; }
00483
00484 DaVinci(const DaVinci&);
00485 void operator=(const DaVinci&);
00486
00487 void Event_Loop(DaVinci_Callback *cb_hook);
00488 void Exit_Event_Loop();
00489
00490 DA_ACK Title(const char *title);
00491 DA_ACK Show_Status(const char *status);
00492 DA_ACK Show_Message(const char *msg);
00493
00494 DA_ACK Menu_Create(INT n_items, const MENU_INFO *items);
00495 DA_ACK Menu_Activate(INT n_ids, const char *ids[]);
00496 DA_ACK Menu_Deactivate(INT n_ids, const char *ids[]);
00497
00498 void Graph_Begin();
00499 void Node_Begin(NODE_ID id, const char *label, const NODE_TYPE& node_type);
00500 void Out_Edge(const EDGE_ID& edge_id,
00501 const EDGE_TYPE& edge_type,
00502 const NODE_ID dest_id);
00503 void Node_End();
00504 DA_ACK Graph_End();
00505
00506 DA_ACK Change_Attr(const NODE_ID node_id,
00507 const NODE_TYPE& nt,
00508 const char *new_label = NULL);
00509
00510 DA_ACK Change_Attr(const EDGE_ID& edge_id, const EDGE_TYPE& et);
00511
00512 void Update_Begin();
00513 void New_Node(NODE_ID id, const char *label, const NODE_TYPE& nt );
00514 void New_Edge(const EDGE_ID& id, const EDGE_TYPE& et,
00515 NODE_ID src, NODE_ID dst);
00516 void Delete_Edge(const EDGE_ID& id);
00517 DA_ACK Update_End();
00518 };
00519
00520 #endif