📄 timelines.c
字号:
#if !defined(HAVE_STDLIB_H)#include <stdlib.h>#else#if HAVE_STDLIB_H#include <stdlib.h>#endif#endif#include "tcl.h"#include "tk.h"#include "log.h"#include "timelines.h"#include "tclptr.h"#include "str_dup.h"#include "tcl_callargv.h"#include "cvt_args.h"#include "feather.h"#ifdef NEEDS_STDLIB_PROTOTYPES#include "protofix.h"#endif#define DEBUG 0#define DEBUG_ZOOM 0#define DEBUG_VIS 0#define DEBUG_TK_DRAWS 0#define DEBUG_UPDATE 0#define DEBUG_UPDATE_GOOFINESS 0#define DEBUG_NO_CONFIG 0#define DEBUG_EVENTS 0#define DEBUG_DESTROY 0#define DEBUG_RESIZE 1 /* length to use for temporary Tcl commands */#define TMP_CMD_LEN 200#define Pix2Time( tl, pix ) ((pix) * (tl)->totalTime / (tl)->width \ + (tl)->startTime)#define Time2Pix( tl, time ) (((time) - (tl)->startTime) / (tl)->totalTime * \ (tl)->width )#define Pix2Proc( tl, pix ) ((pix) * (tl)->np / (tl)->height)#define Proc2Pix( tl, proc ) ((proc) / (tl)->np * (tl)->height)/* Link all the variable in the tl structure to Tcl variables.*/static int LinkVars ANSI_ARGS(( Tcl_Interp *interp, timeLineInfo *tl ));/* Link all the variable in the tl structure to Tcl variables.*/static int UnlinkVars ANSI_ARGS(( timeLineInfo *tl ));/* Grab the ClientData from a logfile command as a logFile*.*/logFile *logCmd2Ptr ANSI_ARGS(( Tcl_Interp *interp, char *logCmd ));static int SetOverlap ANSI_ARGS(( xpandList /*int*/ *list2 ));/* Draw one state. The void *data is a timeLineInfo*.*//* Obsoletestatic int TimeLineDrawState ANSI_ARGS(( void *data, int idx, int type, int proc, double startTime, double endTime, int parent, int firstChild, int overlapLevel ));*//* Do the C side of a new timeline initialization.*/static int Timeline_Open ANSI_ARGS(( ClientData clientData, Tcl_Interp *interp, int argc, char *argv[] ));/* Tcl hook for calling C canvas commands.*/static int Cmd ANSI_ARGS(( ClientData clientData, Tcl_Interp *interp, int argc, char *argv[] ));/* Allocate Feather_Color's and stuff. Needed before any drawing is done. Should only be called once.*/static int AllocColors ANSI_ARGS(( timeLineInfo* ));/* Free colors allocated by AllocColors.*/static int FreeColors ANSI_ARGS(( timeLineInfo* ));/* Draw all states/messages/etc. that have not been drawn yet.*/static int Draw ANSI_ARGS(( timeLineInfo* ));/* Draw background lines.*/static int DrawBgLines ANSI_ARGS(( timeLineInfo* ));/* Draw events.*/static int DrawEvents ANSI_ARGS(( timeLineInfo *tl, void *canvasPtr, Tk_Window canvasWin ));/* Draw states.*/static int DrawStates ANSI_ARGS(( timeLineInfo *tl, void *canvasPtr, Tk_Window canvasWin ));/* Draw messages.*/static int DrawMsgs ANSI_ARGS(( timeLineInfo *tl, void *canvasPtr, Tk_Window canvasWin ));/* Get timeLineInfo* from a window name. $timeline($win,tl)*//*static timeLineInfo *TlPtrFromWindow ANSI_ARGS(( Tcl_Interp *interp, char *win ));*//* Return descripion of current item.*/static int CurrentItem ANSI_ARGS(( timeLineInfo *tl ));/* Passed to Tk_EventuallyFree to close the widget record.*/static int Destroy ANSI_ARGS(( timeLineInfo *tl ));#if DEBUGstatic int PrintStates ANSI_ARGS(( timeLineInfo* ));#endif#define UPDATES_EVERY_N_STATES 200static int SegFaultCmd( clientData, interp, argc, argv )ClientData clientData;Tcl_Interp *interp;int argc;char *argv[];{ strcpy( (char*)0, "My baloney has a first name, it's O-S-C-A-R." ); return 0;}static int UnsquishCmd( clientData, interp, argc, argv )ClientData clientData;Tcl_Interp *interp;int argc;char **argv;{ void *canvasPtr; Tk_Window canvasWin; if (argc != 2) { Tcl_SetResult( interp, "unsquish <canvas>", TCL_STATIC ); return TCL_ERROR; } if (Feather_GetCanvasPtr( interp, argv[1], &canvasPtr, &canvasWin ) != TCL_OK) { return TCL_ERROR; } return Feather_ReconfigArrows( canvasPtr );}int Timeline_Init( interp )Tcl_Interp *interp;{ Tcl_CreateCommand( interp, "Timeline_C_Init", Timeline_Open, (ClientData)0, (Tcl_CmdDeleteProc*) 0 ); Tcl_CreateCommand( interp, "SegFault", SegFaultCmd, (ClientData)0, (Tcl_CmdDeleteProc*) 0 ); Tcl_CreateCommand( interp, "Timeline_C_Draw", Cmd, (ClientData)0, (Tcl_CmdDeleteProc*) 0 ); Tcl_CreateCommand( interp, "unsquish", UnsquishCmd, (ClientData)0, (Tcl_CmdDeleteProc*) 0 ); return 0;}static int Timeline_Open( clientData, interp, argc, argv )ClientData clientData;Tcl_Interp *interp;int argc;char *argv[];{ int i, n; timeLineInfo *tl; char *logCmd, *canvas_name, *array_name, *idx_prefix; char *cmd_name; /* convert the arguments from strings, put them in the widget record */ if (TCL_OK != ConvertArgs( interp, "timeline <cmd_name> <log> <canvas> <array name> <array index prefix>", "1 sssss", argc, argv, &cmd_name, &logCmd, &canvas_name, &array_name, &idx_prefix )) { goto failed_1; } tl = (timeLineInfo*) malloc( sizeof(timeLineInfo) ); if (!tl) { Tcl_AppendResult( interp, "Failed to allocate memory for timeline ", "widget record.", (char *)0 ); return TCL_ERROR; } /* grab pointer to interpreter */ tl->interp = interp; /* save copy of the canvas name */ tl->canvasName = STRDUP( canvas_name ); tl->array_name = STRDUP( array_name ); tl->idx_prefix = STRDUP( idx_prefix ); /* convert the logfile token to a string, get the logFile* */ if (!(tl->log = LogCmd2Ptr( interp, logCmd ))) { /* LogCmd2Ptr sets interp->result */ goto failed_2; } tl->width = tl->height = -1; tl->visWidth = tl->visHeight = -1; tl->lastVisWidth = tl->lastVisHeight = -1; tl->xleft = tl->xspan = tl->lastXspan = -1; tl->xview = -1; tl->ytop = tl->yspan = tl->lastYspan = -1; tl->yview = -1; tl->startTime = Log_StartTime( tl->log ); tl->endTime = Log_EndTime( tl->log ); tl->np = Log_Np( tl->log ); tl->totalTime = tl->endTime - tl->startTime; /* create visiblity definitions such that everything is visible */ /* might want to declare a special case for the visible object for the sake of speed in which everything is visible, no checking needed */ tl->procVis = Vis_new(); for (i=0, n=Log_Np( tl->log ); i < n; i++) { Vis_add( tl->procVis, i, -1 ); } tl->eventVis = Vis_new(); for (i=0, n=Log_NeventDefs( tl->log ); i < n; i++) { Vis_add( tl->eventVis, i, -1 ); } tl->stateVis = Vis_new(); for (i=0, n=Log_NstateDefs( tl->log ); i < n; i++) { Vis_add( tl->stateVis, i, -1 ); } tl->msgVis = Vis_new(); for (i=0, n=Log_NmsgDefs( tl->log ); i < n; i++) { Vis_add( tl->msgVis, i, -1 ); } /* get the list of overlap levels, you know, how wide to draw a state bar if is is overlapping X other states */ SetOverlap( &tl->overlap.halfWidths ); tl->outlineColor = 0; tl->msgColor = 0; tl->bg = 0; tl->bw = 0; /* Mark the timelines as not being drawn yet. Every time new data, like visWidth or xspan comes in, Draw() will be called. If there is not enough information to draw, it will just return. The first time that enough data has been provided to draw, it will be drawn. Every time after that it will simply stretch or slide the canvas to match changes. */ tl->isdrawn = 0;; /* create list for for state drawing information */ /* don't forget we still need to add messages and events */ ListCreate( tl->stateList, tl_stateInfo, 100 ); tl->msgIds = 0; /* lists of state drawing information. Leave empty until needed */ tl->fillColors = 0; tl->fillStipples = 0; tl->stateTags = 0; tl->procTags = 0; /* allow Tcl to access width, height, visHeight, visWidth, xleft, xspan, ytop, yspan, bg, outlineColor, msgColor, bw, startTime, totalTime, and endTime */ LinkVars( interp, tl ); /* create a command by which the functions int timelines.tcl can call me directly (more convenient to put timeLineInfo* in ClientData than in some TclPtr) */ Tcl_CreateCommand( interp, cmd_name, Cmd, (ClientData)tl, (Tcl_CmdDeleteProc*)0 ); /* like, wow, no errors! */ return TCL_OK; failed_2: free( tl->windowName ); free( tl->canvasName ); free( tl ); failed_1: return TCL_ERROR;}#define LINK_ELEMENT( str_name, name, type ) \ sprintf( tmp, "%s(%s,%s)", tl->array_name, tl->idx_prefix, str_name ); \ Tcl_LinkVar( interp, tmp, (char*)&tl->name, type );/* fprintf( stderr, "Linking tl->%s at address %p.\n", \ str_name, (char*)&tl->name );*/static int LinkVars( interp, tl )Tcl_Interp *interp;timeLineInfo *tl;{ char *tmp; int i = TCL_LINK_INT; int f = TCL_LINK_DOUBLE; int s = TCL_LINK_STRING; /* tmp will get filled with something like "timeline(.win.0,stuff)", or ("%s(%s,%s)", array_name, idx_prefix, element_name ), to be exact. */ int max_element_len = 12; /* "windowUnits" */ tmp = malloc( strlen(tl->array_name) + 1 + strlen(tl->idx_prefix) + 1 + max_element_len + 1 + 1 ); tl->lineColor = 0; tl->outlineColor = 0; tl->msgColor = 0; LINK_ELEMENT( "width", width, f ); LINK_ELEMENT( "height", height, f ); LINK_ELEMENT( "visWidth", visWidth, i ); LINK_ELEMENT( "visHeight", visHeight, i ); LINK_ELEMENT( "xleft", xleft, f ); LINK_ELEMENT( "xspan", xspan, f ); LINK_ELEMENT( "ytop", ytop, f ); LINK_ELEMENT( "yspan", yspan, f ); LINK_ELEMENT( "bg", bg, s ); LINK_ELEMENT( "lineColor", lineColor, s ); LINK_ELEMENT( "outlineColor", outlineColor, s ); LINK_ELEMENT( "msgColor", msgColor, s ); LINK_ELEMENT( "bw", bw, i ); LINK_ELEMENT( "startTime", startTime, f ); LINK_ELEMENT( "totalTime", totalTime, f ); LINK_ELEMENT( "endTime", endTime, f ); LINK_ELEMENT( "np", np, i ); free( tmp ); return 0;}#define UNLINK_ELEMENT( str_name ) \ sprintf( tmp, "%s(%s,%s)", tl->array_name, tl->idx_prefix, str_name ); \ Tcl_UnlinkVar( tl->interp, tmp );static int UnlinkVars( tl )timeLineInfo *tl;{ char *tmp; /* tmp will get filled with something like "tl(.win.0,stuff)", or ("%s(%s,%s)", tl->array_name, tl->idx_prefix, element_name ), to be exact. */ int max_element_len = 12; /* "outlineColor" */ tmp = malloc( strlen(tl->array_name) + 1 + strlen(tl->idx_prefix) + 1 + max_element_len + 1 + 1 ); UNLINK_ELEMENT( "width" ); UNLINK_ELEMENT( "height" ); UNLINK_ELEMENT( "visWidth" ); UNLINK_ELEMENT( "visHeight" ); UNLINK_ELEMENT( "xleft" ); UNLINK_ELEMENT( "xspan" ); UNLINK_ELEMENT( "ytop" ); UNLINK_ELEMENT( "yspan" ); UNLINK_ELEMENT( "bg" ); UNLINK_ELEMENT( "lineColor" ); UNLINK_ELEMENT( "outlineColor" ); UNLINK_ELEMENT( "msgColor" ); UNLINK_ELEMENT( "bw" ); UNLINK_ELEMENT( "startTime" ); UNLINK_ELEMENT( "totalTime" ); UNLINK_ELEMENT( "endTime" ); UNLINK_ELEMENT( "np" ); free( tmp ); return 0;}#if 0static timeLineInfo *TlPtrFromToken( interp, token )Tcl_Interp *interp;char *token;{ timeLineInfo *tl; tl = (timeLineInfo*) GetTclPtr( atoi( token ) ); if (tl) { return tl; } else { Tcl_AppendResult( interp, token, " -- invalid timeline token", (char *)0 ); return 0; }}static timeLineInfo *TlPtrFromWindow( interp, win )Tcl_Interp *interp;char *win;{ char *tmp; char *tl_str; tmp = (char*)malloc( strlen(win) + 4 ); sprintf( tmp, "%s,tl", win ); tl_str = Tcl_GetVar2( interp, "timeline", tmp, TCL_GLOBAL_ONLY ); free( tmp ); if (tl_str) { return TlPtrFromToken( interp, tl_str ); } else { Tcl_AppendResult( interp, "timeline(", win, ",tl) doesn't exist.", (char *)0 ); return 0; }}#endifstatic int Destroy( tl )timeLineInfo *tl;{ ListDestroy( tl->stateList, tl_stateInfo ); UnlinkVars( tl ); if (tl->bg) free( tl->bg ); if (tl->outlineColor) free( tl->outlineColor ); if (tl->msgColor) free( tl->msgColor ); if (tl->canvasName) free( tl->canvasName ); if (tl->array_name) free( tl->array_name ); if (tl->idx_prefix) free( tl->idx_prefix ); Vis_close( tl->procVis ); Vis_close( tl->eventVis ); Vis_close( tl->stateVis ); Vis_close( tl->msgVis ); tl->procVis = tl->eventVis = tl->stateVis = tl->msgVis = 0; /* free colors allocated for this display */ FreeColors( tl ); free( (char*)tl ); /* malloc()'d */ return TCL_OK;}/* Overlap levels are a percentage - 0 to 100, how much of the timeline's allocated region it will use up.*/static int SetOverlap( list2 )xpandList *list2;{ xpandList /*int*/ list;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -