Ctrl+Q
→
→
→
schematic_20261008T094410
Diferencias BufferSortida
~ M3 [par] w: "2u" -> "4u"
~ M3 [par] m: "1" -> "2"
~ M5 [con] G: vbias -> {M5.G M7.D}
+ C1 (analogLib/cap/symbol)
- R2 (analogLib/res/symbol)
Guardar versión actual
Nombre de la vista
Fecha y hora actual
Nombre especial
Nombre especial
schematic_
= OKOKCancel
→ OPAMP/BufferSortida/schematic_RailToRail_0309_20261008T094410
Comparar versiones de BufferSortida
Versión A
schematic_RailToRail_0309_antes_cascode
Versión B
schematic_RailToRail_0309_20261006T114210
- (en edicion)
- vtprev__schematic_RailToRail_0309 [Oct 8 09:12]
- vtcur__schematic_RailToRail_0309 [Oct 8 09:40]
- schematic_RailToRail_0309_20261008T094410 [Oct 8 09:44]
- schematic_RailToRail_0309_20261006T114210 [Oct 6 11:42]
- schematic_RailToRail_0309_antes_cascode [Oct 2 17:05]
OKCancel
Diferencias BufferSortida
+ M9 (PDK/nch/symbol)
+ M10 (PDK/nch/symbol)
~ M1 [con] S: tail -> {M1.S M9.D}
~ M2 [con] S: tail -> {M2.S M10.D}
~ M5 [par] l: "500n" -> "1u"
SeguidorVersiones.il
;; =========================================================================
;; PLUGIN: SEGUIDOR DE VERSIONES DE ESQUEMATICOS
;; Cada vez que se guarda un esquematico (lo detecta por la fecha del sch.oa)
;; rota dos instantaneas dentro de la misma celda:
;; vtprev__<vista> version guardada anterior
;; vtcur__<vista> version guardada actual
;; Version: 2026-10-08
;;
;; Menu "Seguidor de versiones":
;; - Guardar version actual como vista con fecha ISO 8601 o nombre propio
;; Atajo de teclado (vtTeclaGuardar, por defecto Ctrl+Q): abre el
;; dialogo con "Fecha y hora actual" ya marcado; Intro y listo.
;; - Diferencias: anterior vs estado en edicion (incluye cambios sin guardar)
;; - Comparar versiones: dos versiones cualesquiera de la celda (las de
;; fecha, las de nombre especial, la anterior o el estado en edicion)
;; - Volver: intercambia actual y anterior (repetirlo deshace)
;; - Abrir la anterior en solo lectura
;; Los nombres de vista no empiezan por "schematic": el plugin gm/Id no las ve.
;; =========================================================================
;; Se reinicia en cada carga: asi un reload vuelve a crear las instantaneas
;; que falten
vtMtimes = makeTable('vtMtimes nil)
;; hiRegTimer va en decimas de segundo: 10 = 1 s
unless( boundp('vtPeriodo) vtPeriodo = 10 )
unless( boundp('vtDirInforme) vtDirInforme = "/tmp" )
;; Atajo para "Guardar version actual" (sintaxis de hiSetBindKey) y su texto
;; en el menu. Cambialos antes de cargar el archivo si chocan con otro atajo.
unless( boundp('vtTeclaGuardar) vtTeclaGuardar = "Ctrl<Key>q" )
unless( boundp('vtTeclaTexto) vtTeclaTexto = "Ctrl+Q" )
vtBusy = nil
;; -------------------------------------------------------------------------
;; UTILIDADES
;; -------------------------------------------------------------------------
procedure( vtVista(view tag)
sprintf(nil "vt%s__%s" tag view)
)
procedure( vtEsInstantanea(view)
rexMatchp("^vt[a-z]+__" view)
)
procedure( vtClave(lib cell view)
sprintf(nil "%s/%s/%s" lib cell view)
)
procedure( vtExiste(lib cell view)
if( ddGetObj(lib cell view) then t else nil)
)
procedure( vtRutaOa(lib cell view)
let( (obj)
obj = ddGetObj(lib cell view "sch.oa")
if( obj then obj~>readPath else nil)
)
)
procedure( vtMtime(lib cell view)
let( (p)
p = vtRutaOa(lib cell view)
if( p && isFile(p) then fileTimeModified(p) else nil)
)
)
procedure( vtFecha(lib cell view)
let( (mt r)
mt = vtMtime(lib cell view)
r = if( mt then errset(timeToString(mt)) else nil)
if( r then car(r) else "?")
)
)
;; Copia una vista dentro de la misma celda (sobrescribe) via base de datos.
;; Si la vista origen esta abierta en edicion se copia lo que hay en memoria,
;; por eso vtVigilar solo copia cuando no hay cambios sin guardar.
procedure( vtCopiar(lib cell vSrc vDst)
let( (srcRes src r nuevo)
srcRes = errset(dbOpenCellViewByType(lib cell vSrc nil "r") t)
src = if( srcRes then car(srcRes) else nil)
r = if( src then errset(dbCopyCellView(src lib cell vDst nil nil t) t) else nil)
nuevo = if( r then car(r) else nil)
when( nuevo && dbobjectp(nuevo) && nuevo != src
dbClose(nuevo)
)
;; Si src era la vista en edicion, esto solo baja su contador de uso
when( src dbClose(src) )
unless( nuevo
printf("Seguidor de versiones: fallo al copiar %s -> %s en %s/%s\n"
vSrc vDst lib cell))
if( nuevo then t else nil)
)
)
procedure( vtBorrar(lib cell view)
let( (obj)
obj = ddGetObj(lib cell view)
when( obj errset(ddDeleteObj(obj)) )
)
)
;; t si w es una ventana grafica que muestra un esquematico. No llama a
;; ninguna funcion ge*, asi que no genera warnings en otras ventanas.
procedure( vtEsVentanaSch(w)
let( (r)
r = errset(
windowp(w) && dbobjectp(w~>cellView) &&
w~>cellView~>cellViewType == "schematic")
if( r && car(r) then t else nil)
)
)
;; Esquematico en edicion de la ventana actual o, si no es un esquematico,
;; de la primera ventana de esquematico abierta
procedure( vtCvActual()
let( (w res)
w = hiGetCurrentWindow()
if( vtEsVentanaSch(w) then
res = geGetEditCellView(w)
else
res = nil
foreach( x hiGetWindowList()
when( !res && vtEsVentanaSch(x)
res = geGetEditCellView(x)
)
)
)
res
)
)
;; Esquematico editable activo, o nil con mensaje
procedure( vtContexto()
let( (cv)
cv = vtCvActual()
cond(
( !cv || cv~>cellViewType != "schematic"
printf("Seguidor de versiones: abre un esquematico.\n")
nil )
( vtEsInstantanea(cv~>viewName)
printf("Seguidor de versiones: estas en una instantanea, vuelve a la vista de trabajo.\n")
nil )
( t cv )
)
)
)
;; -------------------------------------------------------------------------
;; ROTACION
;; -------------------------------------------------------------------------
procedure( vtRotar(lib cell view)
let( (vPrev vCur)
vPrev = vtVista(view "prev")
vCur = vtVista(view "cur")
when( vtExiste(lib cell vCur)
vtCopiar(lib cell vCur vPrev)
)
vtCopiar(lib cell view vCur)
printf("Seguidor de versiones: %s guardado, versiones rotadas\n"
vtClave(lib cell view))
)
)
;; Detecta guardados comparando la fecha del sch.oa con la ultima vista
procedure( vtVigilar(cv)
let( (lib cell view key mt ant vCur mc)
lib = cv~>libName
cell = cv~>cellName
view = cv~>viewName
unless( vtEsInstantanea(view)
key = vtClave(lib cell view)
mt = vtMtime(lib cell view)
ant = vtMtimes[key]
;; Solo con memoria == disco; si no, se reintenta en el siguiente tick
when( mt && !cv~>modifiedButNotSaved
cond(
;; Primera vez en esta sesion: asegura una instantanea actual
( !ant
vtMtimes[key] = mt
vCur = vtVista(view "cur")
mc = vtMtime(lib cell vCur)
cond(
( !mc vtCopiar(lib cell view vCur) )
( mc < mt vtRotar(lib cell view) )
)
)
( mt != ant
vtMtimes[key] = mt
vtRotar(lib cell view)
)
)
)
)
)
)
;; -------------------------------------------------------------------------
;; DIFERENCIAS
;; -------------------------------------------------------------------------
procedure( vtUnion(a b)
let( (tbl)
tbl = makeTable('vtU nil)
foreach( x append(a b) tbl[x] = t )
sort(tbl~>? 'alphalessp)
)
)
;; Redes con nombre automatico (netNN) se identifican por lo que conectan,
;; para que renombrados internos no aparezcan como cambios
procedure( vtCanonNet(net)
let( (nm miembros)
nm = net~>name
if( rexMatchp("^net[0-9]+$" nm) then
miembros = mapcar(lambda((it) sprintf(nil "%s.%s" it~>inst~>name it~>name))
net~>instTerms)
sprintf(nil "{%s}" buildString(sort(miembros 'alphalessp) " "))
else
nm
)
)
)
;; list(tablaInstancias alistPines)
;; tablaInstancias[nombre] = list(master alistParams alistConexiones)
procedure( vtExtraer(cv)
let( (ti pines params conns)
ti = makeTable('vtInst nil)
foreach( inst cv~>instances
params = nil
foreach( p inst~>prop
params = cons(list(p~>name sprintf(nil "%L" p~>value)) params)
)
conns = nil
foreach( it inst~>instTerms
conns = cons(list(it~>name
if( it~>net then vtCanonNet(it~>net) else "<sin red>")) conns)
)
ti[inst~>name] = list(
sprintf(nil "%s/%s/%s" inst~>libName inst~>cellName inst~>viewName)
params conns)
)
pines = nil
foreach( term cv~>terminals
pines = cons(list(term~>name sprintf(nil "%L" term~>direction)) pines)
)
list(ti pines)
)
)
;; Diferencias entre dos alists (nombre valor) -> lista de lineas
procedure( vtDiffAlist(pref a b)
let( (lin ea eb)
lin = nil
foreach( n vtUnion(mapcar('car a) mapcar('car b))
ea = assoc(n a)
eb = assoc(n b)
cond(
( ea && !eb
lin = cons(sprintf(nil "%s%s: %s -> (eliminado)" pref n cadr(ea)) lin) )
( !ea && eb
lin = cons(sprintf(nil "%s%s: (nuevo) -> %s" pref n cadr(eb)) lin) )
( cadr(ea) != cadr(eb)
lin = cons(sprintf(nil "%s%s: %s -> %s" pref n cadr(ea) cadr(eb)) lin) )
)
)
reverse(lin)
)
)
procedure( vtCompararCv(cvA cvB)
let( (a b ia ib ea eb lin)
a = vtExtraer(cvA)
b = vtExtraer(cvB)
ia = car(a)
ib = car(b)
lin = nil
foreach( n vtUnion(ia~>? ib~>?)
ea = ia[n]
eb = ib[n]
cond(
( ea && !eb
lin = cons(sprintf(nil "- %s (%s)" n car(ea)) lin) )
( !ea && eb
lin = cons(sprintf(nil "+ %s (%s)" n car(eb)) lin) )
( t
when( car(ea) != car(eb)
lin = cons(sprintf(nil "~ %s celda: %s -> %s" n car(ea) car(eb)) lin)
)
foreach( l vtDiffAlist(sprintf(nil "~ %s [par] " n) cadr(ea) cadr(eb))
lin = cons(l lin)
)
foreach( l vtDiffAlist(sprintf(nil "~ %s [con] " n) caddr(ea) caddr(eb))
lin = cons(l lin)
)
)
)
)
foreach( l vtDiffAlist("~ [pin] " cadr(a) cadr(b))
lin = cons(l lin)
)
reverse(lin)
)
)
;; Escribe y abre el informe de diferencias de cvA (version A) a cvB (version B)
procedure( vtEscribirInforme(lib cell etqA cvA etqB cvB sufijo)
let( (lin fich fid)
lin = vtCompararCv(cvA cvB)
fich = sprintf(nil "%s/vt_diff_%s_%s_%s.txt" vtDirInforme lib cell sufijo)
fid = outfile(fich)
when( fid
fprintf(fid "%s/%s\n" lib cell)
fprintf(fid "Version A: %s\n" etqA)
fprintf(fid "Version B: %s\n\n" etqB)
fprintf(fid "De A a B: + anadida - eliminada ~ modificada | [par] parametro [con] conexion [pin] pin\n")
fprintf(fid "{a.D b.G}: red sin nombre, identificada por lo que conecta\n\n")
if( lin
then foreach( l lin fprintf(fid "%s\n" l) )
else fprintf(fid "Sin diferencias.\n"))
close(fid)
view(fich nil sprintf(nil "Diferencias %s" cell))
)
printf("Seguidor de versiones: %d diferencias -> %s\n" length(lin) fich)
)
)
;; Etiqueta de una vista: nombre + fecha de su sch.oa; nil = estado en edicion
procedure( vtEtiqueta(lib cell v cv)
if( v
then sprintf(nil "%s [%s]" v vtFecha(lib cell v))
else sprintf(nil "(en edicion)%s"
if( cv~>modifiedButNotSaved " con cambios sin guardar" "")))
)
procedure( vtDiferencias()
let( (cv lib cell view vPrev prevCv)
cv = vtContexto()
when( cv
lib = cv~>libName
cell = cv~>cellName
view = cv~>viewName
vPrev = vtVista(view "prev")
if( !vtExiste(lib cell vPrev) then
printf("Seguidor de versiones: aun no hay version anterior de %s.\n" cell)
else
prevCv = dbOpenCellViewByType(lib cell vPrev nil "r")
vtEscribirInforme(lib cell
vtEtiqueta(lib cell vPrev cv) prevCv
vtEtiqueta(lib cell nil cv) cv
view)
dbClose(prevCv)
)
)
)
)
;; -------------------------------------------------------------------------
;; COMPARAR DOS VERSIONES CUALESQUIERA
;; -------------------------------------------------------------------------
vtCompararSel = nil
vtCompararOpc = nil
;; Vistas de la celda con sch.oa (versiones), sin la de trabajo ni la temporal:
;; primero anterior y actual, luego el resto de la mas nueva a la mas antigua
;; (las de fecha ISO se ordenan solas por nombre)
procedure( vtVistasVersion(lib cell view)
let( (obj todas fijas resto)
obj = ddGetObj(lib cell)
todas = if( obj then setof(v obj~>views~>name
v != view && v != vtVista(view "tmp") && vtRutaOa(lib cell v)) else nil)
fijas = setof(v list(vtVista(view "prev") vtVista(view "cur")) member(v todas))
resto = reverse(sort(setof(v todas !member(v fijas)) 'alphalessp))
append(fijas resto)
)
)
procedure( vtCompararVersiones()
let( (cv lib cell view vistas labels defA form)
cv = vtContexto()
when( cv
lib = cv~>libName
cell = cv~>cellName
view = cv~>viewName
vistas = vtVistasVersion(lib cell view)
if( !vistas then
printf("Seguidor de versiones: %s aun no tiene versiones guardadas.\n" cell)
else
vtCompararSel = cv
;; alist (etiqueta vista); vista nil = estado en edicion
vtCompararOpc = cons(list(vtEtiqueta(lib cell nil cv) nil)
mapcar(lambda((v) list(vtEtiqueta(lib cell v cv) v)) vistas))
labels = mapcar('car vtCompararOpc)
defA = cadr(labels)
form = hiCreateAppForm(
?name 'vtCompararForm
?formTitle sprintf(nil "Comparar versiones de %s" cell)
?fields list(
hiCreateCyclicField(
?name 'vtCompararA
?prompt "Versión A"
?choices labels
?value defA
)
hiCreateCyclicField(
?name 'vtCompararB
?prompt "Versión B"
?choices labels
?value car(labels)
)
)
?buttonLayout 'OKCancel
?callback "vtCompararVersionesCB()"
)
hiDisplayForm(form)
)
)
)
)
procedure( vtCompararVersionesCB()
let( (f cv lib cell eA eB vA vB cvA cvB)
f = hiGetCurrentForm()
cv = vtCompararSel
lib = cv~>libName
cell = cv~>cellName
eA = (f->vtCompararA)~>value
eB = (f->vtCompararB)~>value
vA = cadr(assoc(eA vtCompararOpc))
vB = cadr(assoc(eB vtCompararOpc))
if( eA == eB then
printf("Seguidor de versiones: has elegido la misma version dos veces.\n")
else
;; nil = el esquematico en edicion (no se abre ni se cierra)
cvA = if( vA then dbOpenCellViewByType(lib cell vA nil "r") else cv)
cvB = if( vB then dbOpenCellViewByType(lib cell vB nil "r") else cv)
vtEscribirInforme(lib cell eA cvA eB cvB
sprintf(nil "%s_vs_%s" or(vA "edicion") or(vB "edicion")))
when( vA dbClose(cvA) )
when( vB dbClose(cvB) )
)
)
)
;; -------------------------------------------------------------------------
;; VOLVER A LA VERSION ANTERIOR (intercambio: repetirlo deshace)
;; -------------------------------------------------------------------------
procedure( vtRestaurar(cv lib cell view vPrev vCur)
let( (vTmp edit ok ref src dst)
vTmp = vtVista(view "tmp")
edit = (cv~>mode != "r")
vtBusy = t
ok = errset(
progn(
;; 1. Intercambiar instantaneas
vtCopiar(lib cell vCur vTmp)
vtCopiar(lib cell vPrev vCur)
vtCopiar(lib cell vTmp vPrev)
vtBorrar(lib cell vTmp)
;; 2. Soltar el bloqueo, escribir el sch.oa y recargar
when( edit dbReopen(cv "r") )
src = vtRutaOa(lib cell vCur)
dst = vtRutaOa(lib cell view)
unless( sh(sprintf(nil "cp -f '%s' '%s'" src dst))
error("cp fallo"))
ref = errset(dbRefreshCellView(cv))
when( edit dbReopen(cv "a") )
t
) t)
vtMtimes[vtClave(lib cell view)] = vtMtime(lib cell view)
vtBusy = nil
foreach( w hiGetWindowList() errset(hiRedraw(w)) )
cond(
( ok && ref
printf("Seguidor de versiones: %s restaurado. Repite la accion para deshacer.\n"
vtClave(lib cell view)) )
( ok
printf("Seguidor de versiones: restaurado en disco; cierra y reabre la celda para verlo.\n") )
( t
printf("Seguidor de versiones: fallo al restaurar. Las versiones estan en %s y %s.\n"
vPrev vCur) )
)
)
)
procedure( vtVolverAnterior()
let( (cv lib cell view vPrev vCur)
cv = vtContexto()
when( cv
lib = cv~>libName
cell = cv~>cellName
view = cv~>viewName
vPrev = vtVista(view "prev")
vCur = vtVista(view "cur")
cond(
( cv~>modifiedButNotSaved
printf("Seguidor de versiones: hay cambios sin guardar. Guarda o usa File > Discard Edits antes de volver.\n") )
( !vtExiste(lib cell vPrev) || !vtExiste(lib cell vCur)
printf("Seguidor de versiones: aun no hay version anterior de %s.\n" cell) )
( hiDisplayAppDBox(
?name 'vtConfirmDBox
?dboxBanner "Seguidor de versiones"
?dboxText sprintf(nil
"Sustituir %s por la version guardada el %s?\nLa actual pasa a ser la anterior: repetir la accion la recupera."
vtClave(lib cell view) vtFecha(lib cell vPrev))
?buttonLayout 'YesNo)
vtRestaurar(cv lib cell view vPrev vCur) )
)
)
)
)
procedure( vtAbrirAnterior()
let( (cv vPrev)
cv = vtContexto()
when( cv
vPrev = vtVista(cv~>viewName "prev")
if( vtExiste(cv~>libName cv~>cellName vPrev)
then geOpen(?lib cv~>libName ?cell cv~>cellName ?view vPrev ?mode "r")
else printf("Seguidor de versiones: aun no hay version anterior.\n"))
)
)
)
;; -------------------------------------------------------------------------
;; GUARDAR VERSION ACTUAL CON NOMBRE
;; Fecha y hora en ISO 8601 formato basico (20261006T114210): sin ":" ni
;; "-", que dan problemas en nombres de vista. Nombre final:
;; <vista>_<fecha> (p.ej. schematic_20261006T114210) o el nombre especial.
;; Se copia el estado en edicion, incluidos los cambios sin guardar.
;; -------------------------------------------------------------------------
vtGuardarCv = nil
;; getCurrentTime() -> "Oct 6 11:42:10 2026" -> "20261006T114210"
procedure( vtFechaIso()
let( (p meses mes)
p = parseString(getCurrentTime() " ")
meses = '("Jan" "Feb" "Mar" "Apr" "May" "Jun" "Jul" "Aug" "Sep" "Oct" "Nov" "Dec")
mes = length(meses) - length(member(car(p) meses)) + 1
sprintf(nil "%s%02d%02dT%s" nth(3 p) mes atoi(cadr(p))
buildString(parseString(caddr(p) ":") ""))
)
)
procedure( vtGuardarVersion()
let( (cv form)
cv = vtContexto()
when( cv
vtGuardarCv = cv
form = hiCreateAppForm(
?name 'vtGuardarForm
?formTitle "Guardar versión actual"
?fields list(
hiCreateRadioField(
?name 'vtGuardarModo
?prompt "Nombre de la vista"
?choices list("Fecha y hora actual" "Nombre especial")
?value "Fecha y hora actual"
)
hiCreateStringField(
?name 'vtGuardarNombre
?prompt "Nombre especial"
?value sprintf(nil "%s_" cv~>viewName)
)
)
?buttonLayout 'OKCancel
?callback "vtGuardarVersionCB()"
)
hiDisplayForm(form)
)
)
)
procedure( vtGuardarVersionCB()
let( (f cv lib cell view modo nombre)
f = hiGetCurrentForm()
cv = vtGuardarCv
lib = cv~>libName
cell = cv~>cellName
view = cv~>viewName
modo = (f->vtGuardarModo)~>value
nombre = if( modo == "Nombre especial"
then (f->vtGuardarNombre)~>value
else sprintf(nil "%s_%s" view vtFechaIso()))
cond(
( !stringp(nombre) || !rexMatchp("^[A-Za-z0-9_]+$" nombre)
printf("Seguidor de versiones: nombre no valido \"%L\" (solo letras, numeros y _).\n" nombre) )
( nombre == view
printf("Seguidor de versiones: el nombre coincide con la vista de trabajo.\n") )
( vtEsInstantanea(nombre)
printf("Seguidor de versiones: los nombres vt*__ estan reservados.\n") )
( vtExiste(lib cell nombre) &&
!hiDisplayAppDBox(
?name 'vtSobrescribirDBox
?dboxBanner "Guardar versión actual"
?dboxText sprintf(nil "La vista %s ya existe en %s/%s. Sobrescribir?" nombre lib cell)
?buttonLayout 'YesNo)
printf("Seguidor de versiones: cancelado.\n") )
( t
when( vtCopiar(lib cell view nombre)
printf("Seguidor de versiones: version guardada como %s%s\n"
vtClave(lib cell nombre)
if( cv~>modifiedButNotSaved " (incluye cambios sin guardar)" ""))
)
)
)
)
)
;; -------------------------------------------------------------------------
;; MENU + TEMPORIZADOR
;; -------------------------------------------------------------------------
;; Quita el menu de las ventanas abiertas para que un reload lo regenere
procedure( vtQuitarMenus()
foreach( w hiGetWindowList()
errset(
let( (menus resto)
menus = hiGetBannerMenus(w)
resto = member('MenuVersiones menus)
when( resto
hiDeleteBannerMenu(w length(menus) - length(resto))
)
)
)
)
)
procedure( vtRegistrarMenu(win)
let( (items menu)
items = list(
hiCreateMenuItem(
?name 'vtItemGuardar
?itemText sprintf(nil "Guardar versión actual (%s)" vtTeclaTexto)
?callback "vtGuardarVersion()"
)
hiCreateMenuItem(
?name 'vtItemDiff
?itemText "Diferencias con la versión anterior"
?callback "vtDiferencias()"
)
hiCreateMenuItem(
?name 'vtItemComparar
?itemText "Comparar versiones..."
?callback "vtCompararVersiones()"
)
hiCreateMenuItem(
?name 'vtItemVolver
?itemText "Volver a la versión anterior"
?callback "vtVolverAnterior()"
)
hiCreateMenuItem(
?name 'vtItemAbrir
?itemText "Abrir versión anterior (lectura)"
?callback "vtAbrirAnterior()"
)
)
menu = hiCreatePulldownMenu('MenuVersiones "Seguidor de versiones" items)
hiInsertBannerMenu(win menu length(hiGetBannerMenus(win)))
)
)
procedure( vtTick(@optional (gen 0))
;; Una llamada sin numero (temporizador de una carga anterior) se para
when( gen == vtTimerGen
unless( vtBusy
errset(
foreach( w hiGetWindowList()
errset(
let( (cv)
;; geGetEditCellView solo en ventanas de esquematico:
;; en el CIW, Library Manager o Maestro (que si tiene
;; cellView, de tipo "maestro") lanza el warning GE-2067
cv = if( vtEsVentanaSch(w) then geGetEditCellView(w) else nil)
when( cv && cv~>cellViewType == "schematic"
unless( member('MenuVersiones hiGetBannerMenus(w))
vtRegistrarMenu(w)
)
vtVigilar(cv)
)
)
)
)
)
)
hiRegTimer(sprintf(nil "vtTick(%d)" gen) vtPeriodo)
)
)
;; Cada carga incrementa vtTimerGen: el temporizador de una carga anterior
;; se para solo, asi recargar el archivo no acumula temporizadores
vtTimerGen = if( boundp('vtTimerGen) && integerp(vtTimerGen) then vtTimerGen + 1 else 1)
;; Atajo de teclado en el editor de esquematicos. El dialogo se abre con
;; "Fecha y hora actual" marcado, asi que basta con pulsar Intro.
;; Prefijos de bindkeys del editor de esquematicos registrados ahora mismo.
;; "Schematics" cubre el editor L; "Schematics XL" solo existe con licencia XL.
procedure( vtAppsEsquematico()
let( (r reg)
r = if( fboundp('hiGetBindKeyPrefixList) then errset(hiGetBindKeyPrefixList()) else nil)
reg = if( r then car(r) else nil)
if( reg
then setof(a '("Schematics" "Schematics XL") member(a reg))
else '("Schematics"))
)
)
;; Si la tecla ya tiene otra funcion asignada no la pisa: avisa en el CIW
;; para que elijas otra en vtTeclaGuardar
procedure( vtRegistrarTecla()
let( (actual r)
;; Solo los prefijos que existen en esta instalacion: consultar uno
;; no registrado (p.ej. "Schematics L") imprime un WARNING en el CIW
foreach( app vtAppsEsquematico()
r = errset(hiGetBindKey(app vtTeclaGuardar))
actual = if( r then car(r) else nil)
if( stringp(actual) && actual != "" && actual != "vtGuardarVersion()" then
printf("Seguidor de versiones: %s ya ejecuta %s en %s; no se reasigna. Cambia vtTeclaGuardar.\n"
vtTeclaTexto actual app)
else
errset(hiSetBindKey(app vtTeclaGuardar "vtGuardarVersion()"))
)
)
)
)
vtRegistrarTecla()
vtQuitarMenus()
vtTick(vtTimerGen)