[Back to ENTRY SWAG index] [Back to Main SWAG index] [Original]

    { A good line editor object }

    UNIT EditObj; {  Object_Line_Editor  }

    INTERFACE

    USES Crt, KeyBd;

    TYPE
      LineEdit = OBJECT
        Pos, XPos, YPos : Integer;
        EdLine : String;
        PROCEDURE InitEdit( X, Y: Integer; LineIn: String );
        FUNCTION  GetLine: String;
      END;

    VAR
       Kbd: KeyBoard;   {<<<========== Global definition of OBJECT}

    {***************************************************************}
                            IMPLEMENTATION
    {***************************************************************}

    {-------------------------------------------------
    - Name   : InitEdit                              -
    - Purpose: Set up editor, display line onscreen  -
    -------------------------------------------------}

    PROCEDURE LineEdit.InitEdit;
      BEGIN
        EdLine := LineIn;
        Pos  := Ord( LineIn[0] ) + 1;
        XPos := X;
        YPos := Y;
        GotoXY( X, Y );
        Write( LineIn );
      END;

    {-------------------------------------------------
    - Name   : GetLine                               -
    - Purpose: Process keying from user              -
    -          Maximum 80 characters accepted        -
    -------------------------------------------------}

    FUNCTION  LineEdit.GetLine;
      VAR
        KeyFlags : Byte;
        Ch: Char;
        FunctKey, Finish: Boolean;
      BEGIN
        Finish := FALSE;
        REPEAT
          IF Kbd.GetKey( KeyFlags, FunctKey, Ch ) THEN BEGIN
            IF FunctKey THEN
              CASE Ch OF
    { HOME   }  #$47: Pos := 1;
    { END    }  #$4F: Pos := Ord( EdLine[0] ) + 1;
    { RIGHT  }  #$4D: BEGIN
                        IF Pos < 80 THEN Inc( Pos );
                        IF Pos > Ord( EdLine[0] ) THEN
                          Insert( ' ', EdLine, Pos );
                        END;
    { LEFT   }  #$4B: IF Pos > 1  THEN Dec( Pos );
    { DELETE }  #$53: IF Pos <= Ord( EdLine[0] ) THEN
                         Delete( EdLine, Pos, 1 );
                END {CASE Ch}
              ELSE {IF}
                CASE Ch OF
    { BS }        #$08: IF Pos > 1 THEN BEGIN
                          Delete( EdLine, Pos-1, 1 );
                          Dec( Pos );
                          END;
    { ENTER }     #$0D: Finish := TRUE;
                  ELSE BEGIN
                    IF( ( KeyFlags AND $80 ) <> $80 )
                       THEN Insert( Ch, EdLine, Pos )
                       ELSE EdLine[Pos] := Ch;
                    IF Pos > Ord( EdLine[0] ) THEN
                       EdLine[0] := Chr( Pos );
                    IF Pos < 80 THEN Inc( Pos );
                    END     {CASE CH ELSE}
                  END;    {CASE Ch}
            GotoXY( XPos, YPos );
            Write( EdLine, ' ' );
            GotoXY( XPos+Pos-1, YPos );
            END;  {IF Kbd.GetKey}
          UNTIL Finish;
          GetLine := EdLine;
        END;

    END.

    {  KEYBOARD UNIT }
    UNIT Keybd;  { Keybd.PAS / Keybd.TPU }

    INTERFACE

    USES Crt, Dos;

    TYPE
      CType = ( UBAR, BLOCK );
      Keyboard = OBJECT
        ThisCursor: CType;
        PROCEDURE InitKeyBd;
        PROCEDURE SetCursor( Cursor: CType );
        FUNCTION  GetCursor: CType;
        FUNCTION  GetKbdFlags: Byte;
        FUNCTION  GetKey( VAR KeyFlags: Byte; VAR FunctKey: Boolean;
                                            VAR Ch: Char ): Boolean;
      END;

    {***************************************************************}
                          IMPLEMENTATION
    {***************************************************************}

    {Keyboard}

    {-------------------------------------------------
    - Name   : InitKeyBd                             -
    - Purpose: Set the cursor to underline style     -
    -          and empty keyboard buffer             -
    -------------------------------------------------}

    PROCEDURE Keyboard.InitKeyBd;
      VAR
        Ch : Char;
      BEGIN
        SetCursor( UBAR );
        WHILE( KeyPressed ) DO Ch := ReadKey;
      END;

    {-------------------------------------------------
    - Name   : SetCursor                             -
    - Purpose: Modify number of lines for cursor     -
    -------------------------------------------------}

    PROCEDURE Keyboard.SetCursor;
      VAR
        Regs: Registers;
      BEGIN
        CASE Cursor OF
          UBAR:  Regs.Ch := 6;
          BLOCK: Regs.Ch := 1;
        END;
        Regs.CL := 7;
        Regs.AH := 1;
        Intr( $10, Regs );
      END;

    {-------------------------------------------------
    - Name   : GetKbdFlags                           -
    - Purpose: Monitor the Insert key                -
    - Output : Shift key status flag byte            -
    -------------------------------------------------}

    FUNCTION  Keyboard.GetKbdFlags: Byte;
      VAR
        Regs: Registers;
      BEGIN
        (* FOR enhanced keyboards: AH := $12 *)
        (* FOR normal keyboards:   AH := $02 *)
        Regs.AH := $12;
        Intr( $16, Regs );
        IF( Regs.AX AND $80 = $80 ) THEN SetCursor( BLOCK )
                                    ELSE SetCursor( UBAR );
        GetKbdFlags := Regs.AX;
      END;

    {-------------------------------------------------
    - Name   : GetCursor                             -
    - Purpose: Query current cursor state            -
    -------------------------------------------------}

    FUNCTION  Keyboard.GetCursor;
      BEGIN
        GetCursor := ThisCursor;
      END;

    {-------------------------------------------------
    - Name   : GetKey                                -
    - Purpose: Get a keypress contents if any        -
    -          Updates a function keypressed flag    -
    -------------------------------------------------}

    FUNCTION  Keyboard.GetKey;
      VAR
        Result : Boolean;
      BEGIN
        Result := KeyPressed;
        FunctKey := FALSE;
        Ch := #$00;       {Use this to check for Function key press}
        IF Result THEN BEGIN
          Ch := ReadKey;
          IF( KeyPressed AND ( Ch = #$00 ) ) THEN BEGIN
            Ch := ReadKey;
            FunctKey := TRUE;
            END;
          END;
        KeyFlags := GetKbdFlags;
        GetKey := Result;
        END;

    END.

    {   DEMO PROGRAM  }

    PROGRAM EditDemo;

    {-------------------------------------------------
    -  Show off example of global object use         -
    -------------------------------------------------}

    USES Crt, EditObj;

    VAR
       Editor: LineEdit;           {Instantiation of LineEdit OBJECT}
       ResultStr: String;
    BEGIN
       ClrScr;
       WITH Editor DO
       BEGIN
          InitEdit( 1, 10, 'Edit this sample line');
          ResultStr := GetLine;
          GotoXY( 1, 15 );
          WriteLn( ResultStr );
       END;
       ReadLn;
    END.

[Back to ENTRY SWAG index] [Back to Main SWAG index] [Original]