Programando en SYSTEM RPL
Repetición de teclas

Mario de Lama   malar@arrakis.es
http://www.arrakis.es/~malar

Regresar

En system hay varias formas de conseguir que algo se ejecute mientras estás presionando una tecla, hasta hay implementadas dos rutinas: REPEATER (#40E88) y REPEATERCH (#51735). Ambas precisan de dos argumentos:

2: código de la tecla a repetir
1: secundario u objeto que deseamos que se evalúe repetidamente

Por ejemplo:

::
 ZERO 1LAMBIND
 WaitForKey 2DROP
 REPEATER
 SEVENTEEN
 :: $ "REPETICION " 1GETLAM #1+DUP 1PUTLAM #>$ &$ DISPROW4 ;
 ABND
;

¿Qué diferencia hay entre REPEATER y REPEATERCH? Podéis verla si estudiáis el código asociado a cada una de estas etiquetas o compilando el ejemplo anterior (también bajandoos el ejemplo compilado con REPEATER o con REPEATERCH)
El código SEVENTEEN corresponde al cursor ABAJO que es al que debéis dar tras presionar en la variable en la que guardéis los programas.
Por si no tenéis JAZZ a mano os doy el código de ambos comandos:

REPEATER ( dirección #40E88 )

::
 'R'R DUP EVAL
 OVER REPKEY? NOTcase2DROP
 VERYSLOW
 BEGIN
   2DUPSWAP REPKEY?
 WHILE
   ::  EVAL SLOW ;
 REPEAT
 3DROP
;


REPEATCH ( dirección #51735 )

::
 'R'R DUP EVAL
 OVER REPKEY? NOTcase2DROP
 BEGIN
 2DUPSWAP REPKEY?
 WHILE
   ::
     ::
       PTR 4DCC6
       EVAL
     ;
   ;
 REPEAT
 3DROP
;

REPEATER es más lento, incluso pone un VERYSLOW al principio para que el primer paso sea aún más lento.

Pero esta forma de repetir tecla tiene un gran inconveniente: En los niveles 1 y 2 tenemos siempre el código de la tecla a repetir y un secundario, por ello es bastante complicado usar la pila para hacer operaciones y demás. Prácticamente estamos restringidos a programar rutinas que no alteren la pila.

Para obviar este problema, podemos hacer el siguiente bucle:

BEGIN
  .... ( Código a repetir mientras mantengamos presionada la tecla X)
  NúmeroDeCódigoDeLaTeclaX REPKEY? 
NOT_UNTIL

Un ejemplo de esta forma de repetir la pulsación de una tecla lo tenemos a continuación. En él se toma como argumento un gráfico y se presenta en la pila pudiendo desplazarlo hacia arriba y abajo en saltos de 6 pixeles o hacia derecha e izquierda a saltos de 4 pixeles según mantengamos pulsado alguno de los cursores. Estos incrementos son muy convenientes si el gráfico es el de un texto con la fuente pequeña ya que podemos pasar de línea en línea en vertical o de carácter en carácter en horizontal.
El código de VG está listo para ser compilado con JAZZ y, como veis, tiene definidos previamente cada uno de los códigos de las teclas a usar para dar una mayor legibilidad al ejemplo:

VG ( CHEKSUM #C0Fh, 320 by )


DEFINE kpNoShift	ONE
DEFINE kcUpArrow	ELEVEN
DEFINE kcDownArrow	SEVENTEEN
DEFINE kcLeftArrow	SIXTEEN
DEFINE kcRightArrow	EIGHTEEN
DEFINE kcOn		FORTYFIVE
::
CK1&Dispatch
 TWELVE
 ::
   DUPGROBDIM FALSE {{ Y X TEST }}
   ClrDA1IsStat RECLAIMDISP TURNMENUOFF 
   ZEROZERO ROT XYGROBDISP
   BEGIN
     WaitForKey
     ::
       kpNoShift #=casedrop
       ::
         kcUpArrow #=casedrop
          ::
           BEGIN
            WINDOWCORNER SWAPDUP SIX #>ITE
            DROPZERO #6- SWAP WINDOWXY
            kcUpArrow REPKEY?
           NOT_UNTIL
          ;
         kcDownArrow #=casedrop
          ::
           BINT40h Y #> ?SEMI
           BEGIN
            WINDOWCORNER SWAP #6+ Y OVER #-
            BINT40h #>?SKIP
            :: DROP Y BINT40h #- ;
            SWAP WINDOWXY
            kcDownArrow REPKEY?
           NOT_UNTIL
         ;
         kcLeftArrow #=casedrop
          ::
           BEGIN
            WINDOWCORNER DUP #4 #<ITE
            DROPZERO #4- WINDOWXY
            kcLeftArrow REPKEY?
           NOT_UNTIL
          ;
         kcRightArrow #=casedrop
          ::
           BINT_131d X #> ?SEMI
           BEGIN
            WINDOWCORNER #4+ X OVER #-
            BINT_131d #>?SKIP
            :: DROP X BINT_131d #- ;
            WINDOWXY
            kcRightArrow REPKEY?
           NOT_UNTIL
          ;
         kcOn #=casedrop :: TRUE TEST! ;
         DROP DoBadKey
       ;
      2DROP DoBadKey
     ;
     TEST
   UNTIL
   ABND TURNMENUON RECLAIMDISP ClrDAsOK
 ;
;

La base de este algoritmo es REPKEY? ( #KeyCode -> TRUE/FALSE ) que devuelve TRUE si la tecla #KeyCode está presionándose. Naturalmente también puede hacerse un programa más simple en este caso:

VG2 ( CHEKSUM #E749h, 145 by )


DEFINE kpNoShift	ONE
DEFINE kcUpArrow	ELEVEN
DEFINE kcDownArrow	SEVENTEEN
DEFINE kcLeftArrow	SIXTEEN
DEFINE kcRightArrow	EIGHTEEN
DEFINE kcOn		FORTYFIVE
::
CK1&Dispatch
 TWELVE
 ::
   FALSE {{ TEST }}
   ClrDA1IsStat RECLAIMDISP TURNMENUOFF 
   ZEROZERO ROT XYGROBDISP
   BEGIN
     WaitForKey
     ::
       kpNoShift #=casedrop
       ::
         kcUpArrow #=casedrop :: SCROLLUP ;
         kcDownArrow #=casedrop :: SCROLLDOWN ;
         kcLeftArrow #=casedrop :: SCROLLLEFT ;
         kcRightArrow #=casedrop :: SCROLLRIGHT ;
         kcOn #=casedrop :: TRUE TEST! ;
         DROP DoBadKey
       ;
      2DROP DoBadKey
     ;
     TEST
   UNTIL
   ABND TURNMENUON RECLAIMDISP ClrDAsOK
 ;
;

Ya que los comandos SCROLL tienen incorporados REPEATER en su código. A pesar de ser más corto VG2 que VG si compiláis y ejecutáis ambos programas veréis las ventajas de VG: Mayor rapidez y flexibilidad ya que se puede variar fácilmente el incremento X e Y.

Espero que os sirva de algo.


Regresar