diff --git a/VERSION b/VERSION index e06d126b..996636a1 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.3.665 +8.3.666 diff --git a/cif/CIFhier.c b/cif/CIFhier.c index d9b36025..8b764140 100644 --- a/cif/CIFhier.c +++ b/cif/CIFhier.c @@ -719,6 +719,20 @@ CIFGenSubcells( SearchContext scx; int cuts, totcuts; float pdone, plast; + bool longTime = FALSE; + +#ifdef MAGIC_WRAPPER + /* This routine may be long-running and events to refresh the + * console will be periodically run to allow the progress status + * to be displayed. Force a restriction on event processing to + * exclude key and button events so that it is not possible to + * corrupt the database during GDS/CIF writes. + */ + Tk_RestrictProc *oldProc; + ClientData oldArg; + + oldProc = Tk_RestrictEvents(RestrictInputProc, (ClientData)NULL, &oldArg); +#endif /* MAGIC_WRAPPER */ UndoDisable(); CIFInitCells(); @@ -847,6 +861,7 @@ CIFGenSubcells( /* Only print something if the 5-second timer has expired */ if (GrDisplayStatus == DISPLAY_BREAK_PENDING) { + longTime = TRUE; TxPrintf("Completed %d%%\n", (int)(pdone + 0.5)); plast = pdone; TxFlushOut(); @@ -865,6 +880,12 @@ CIFGenSubcells( GrDisplayStatus = savedDisplayStatus; SigRemoveTimer(); + if (longTime) TxPrintf("Completed 100%%\n"); + +#ifdef MAGIC_WRAPPER + /* Restore full event access */ + Tk_RestrictEvents(oldProc, oldArg, &oldArg); +#endif /* MAGIC_WRAPPER */ UndoEnable(); } diff --git a/extract/ExtSubtree.c b/extract/ExtSubtree.c index e3dbf2ec..5ae6f5bb 100644 --- a/extract/ExtSubtree.c +++ b/extract/ExtSubtree.c @@ -177,6 +177,20 @@ extSubtree(parentUse, reg, f) float pdone, plast; SearchContext scx; int savedDisplayStatus; + bool longTime = FALSE; + +#ifdef MAGIC_WRAPPER + /* This routine may be long-running and events to refresh the + * console will be periodically run to allow the progress status + * to be displayed. Force a restriction on event processing to + * exclude key and button events so that it is not possible to + * corrupt the database during extraction. + */ + Tk_RestrictProc *oldProc; + ClientData oldArg; + + oldProc = Tk_RestrictEvents(RestrictInputProc, (ClientData)NULL, &oldArg); +#endif /* MAGIC_WRAPPER */ /* Use the display timer to force a 5-second progress check */ savedDisplayStatus = GrDisplayStatus; @@ -299,6 +313,7 @@ extSubtree(parentUse, reg, f) /* Only print something if the 5-second timer has expired */ if (GrDisplayStatus == DISPLAY_BREAK_PENDING) { + longTime = TRUE; TxPrintf("Completed %d%%\n", (int)(pdone + 0.5)); plast = pdone; TxFlushOut(); @@ -309,7 +324,7 @@ extSubtree(parentUse, reg, f) #ifdef MAGIC_WRAPPER /* We need to let Tk paint the console display */ - while (Tcl_DoOneEvent(TCL_DONT_WAIT) != 0); + while (Tcl_DoOneEvent(TCL_WINDOW_EVENTS | TCL_DONT_WAIT) != 0); #endif } } @@ -352,11 +367,27 @@ done: /* Output connections and node adjustments */ extOutputConns(&ha.ha_connHash, f); HashKill(&ha.ha_connHash); - GrDisplayStatus = savedDisplayStatus; - SigRemoveTimer(); /* Clear the CU_SUB_EXTRACTED flag from all children instances */ DBCellEnum(def, extClearUseFlags, (ClientData)NULL); + + /* If this cell took more than 5 seconds to extract and a + * progress update was made, then complete the progress + * update with a 100% complete message. + */ + GrDisplayStatus = savedDisplayStatus; + SigRemoveTimer(); + if (longTime) + { + TxPrintf("Completed 100%%\n"); + TxFlushOut(); + } + +#ifdef MAGIC_WRAPPER + /* Restore full event access */ + Tk_RestrictEvents(oldProc, oldArg, &oldArg); +#endif /* MAGIC_WRAPPER */ + } #ifdef exactinteractions diff --git a/lef/defRead.c b/lef/defRead.c index 5d2554fe..46c59b73 100644 --- a/lef/defRead.c +++ b/lef/defRead.c @@ -2498,6 +2498,11 @@ DefRead( NULL }; +#ifdef MAGIC_WRAPPER + Tk_RestrictProc *oldProc; + ClientData oldArg; +#endif /* MAGIC_WRAPPER */ + /* "annotate" implies "dolabels" whether set or not */ if (annotate) dolabels = TRUE; @@ -2519,6 +2524,17 @@ DefRead( return NULL; } +#ifdef MAGIC_WRAPPER + /* This routine may be long-running and events to refresh the + * console will be periodically run to allow the progress status + * to be displayed. Force a restriction on event processing to + * exclude key and button events so that it is not possible to + * corrupt the database during DEF reads. + */ + + oldProc = Tk_RestrictEvents(RestrictInputProc, (ClientData)NULL, &oldArg); +#endif /* MAGIC_WRAPPER */ + /* Initialize */ TxPrintf("Reading DEF data from file %s.\n", filename); @@ -2739,5 +2755,11 @@ DefRead( if (f != NULL) fclose(f); UndoEnable(); + +#ifdef MAGIC_WRAPPER + /* Restore full event access */ + Tk_RestrictEvents(oldProc, oldArg, &oldArg); +#endif /* MAGIC_WRAPPER */ + return rootDef; } diff --git a/lef/lefRead.c b/lef/lefRead.c index 46668d9a..a083ed15 100644 --- a/lef/lefRead.c +++ b/lef/lefRead.c @@ -132,66 +132,6 @@ LefEstimate( } } -/* This is the original version, which doesn't use the system itimer */ -/* and which is not very good at maintaining constant intervals. */ - -#if 0 -void -LefEstimate( - int processed, - int total, - const char *item_name) -{ - static int check_interval, partition; - static struct timeval tv_start; - static float last_time; - struct timeval tv; - struct timezone tz; - float cur_time, time_left; - - if (!total) return; - - if (processed == 0) /* Initialization */ - { - GrDisplayStatus = DISPLAY_IN_PROGRESS; - - check_interval = 100; - gettimeofday(&tv_start, &tz); - last_time = 0.0; - } - - if (processed > check_interval) - { - gettimeofday(&tv, &tz); - cur_time = (float)(tv.tv_sec - tv_start.tv_sec) - + ((float)(tv.tv_usec - tv_start.tv_usec) / 1.0e6); - time_left = (((float)total / (float)processed) - 1) * cur_time; - - /* not likely to happen, but we don't want a divide-by-0 error */ - if (cur_time == 0.0) cur_time = 1.0e-6; - - partition = (int)((float)processed * (float)PRINT_INTERVAL / cur_time); - - /* partition is never less than 1 nor greater than 5% of the total */ - if (partition == 0) partition = 1; - if (partition > (total / 20)) partition = (total / 20); - - check_interval += partition; - - /* Don't print anything in intervals faster than 1 second */ - if ((cur_time - last_time) < 1.0) return; - last_time = cur_time; - - TxPrintf(" Processed %d of %d %s (%2.1f%%).", processed, total, - item_name, (float)(100 * processed) / (float)total); - TxPrintf(" Est. time remaining: %2.1fs\n", time_left); - TxFlushOut(); - } -} - -#endif /* 0 */ - - /* *------------------------------------------------------------ * diff --git a/tcltk/tclmagic.c b/tcltk/tclmagic.c index 710319ff..72deaeb8 100644 --- a/tcltk/tclmagic.c +++ b/tcltk/tclmagic.c @@ -1515,3 +1515,32 @@ Tclmagic_SafeInit(interp) { return Tclmagic_Init(interp); } + +/* Procedure to set up restricted Tk event processing to allow window + * exposure and updates to occur while deferring key and button press + * events. This allows window updates during potentially long-running + * processes like extraction or GDS writes but prevents commands from + * being executed while the process is still running. + */ + +Tk_RestrictAction +RestrictInputProc( + ClientData clientData, + XEvent *eventPtr) +{ + switch (eventPtr->type) + { + case KeyPress: + case KeyRelease: + case ButtonPress: + case ButtonRelease: + return TK_DEFER_EVENT; + + case MotionNotify: + return TK_DISCARD_EVENT; + + default: + return TK_PROCESS_EVENT; + } +} + diff --git a/tcltk/tclmagic.h b/tcltk/tclmagic.h index 92c587c5..8057026f 100644 --- a/tcltk/tclmagic.h +++ b/tcltk/tclmagic.h @@ -34,5 +34,8 @@ extern const char *Tclmagic_InitStubsVersion; extern void TclmagicRegisterCommands(Tcl_Interp *interp); +extern Tk_RestrictAction RestrictInputProc(ClientData, XEvent *); + + #endif /* MAGIC_WRAPPER */ #endif /* _MAGIC__TCLTK__TCLMAGIC_H */ diff --git a/utils/signals.c b/utils/signals.c index 772c7078..482c4906 100644 --- a/utils/signals.c +++ b/utils/signals.c @@ -724,3 +724,4 @@ sigSetAction(int signo, sigRetVal (*handler)(int)) sigvec(signo, &sv, (struct sigvec *)NULL); #endif } +