;
;    Mecrisp - A native code Forth implementation for MSP430 microcontrollers
;    Copyright (C) 2011  Matthias Koch
;
;    This program is free software: you can redistribute it and/or modify
;    it under the terms of the GNU General Public License as published by
;    the Free Software Foundation, either version 3 of the License, or
;    (at your option) any later version.
;
;    This program is distributed in the hope that it will be useful,
;    but WITHOUT ANY WARRANTY; without even the implied warranty of
;    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;    GNU General Public License for more details.
;
;    You should have received a copy of the GNU General Public License
;    along with this program.  If not, see <http://www.gnu.org/licenses/>.
;

; Eingaberoutine Query - mit Unicodeunterstützung.

;------------------------------------------------------------------------------
  Wortbirne Flag_visible, "query"
query: ; ehemals:  ( Pufferadresse -- Pufferadresse ) jetzt: ( -- )
       ; Holt einen String von der Tastatur ab
       ; und legt ihn in den Eingabe-Puffer.
;------------------------------------------------------------------------------
  push r10 ; r10 ist das Zeichen.
  push r11 ; r11 Pufferadresse
           ; r7 dient zum Finden des Pufferendes, wenn ein Zeichen hinzugefügt wird.

  mov.b #-1, &Eingabepuffergesamtlaenge ; Markiert die frische Füllung !
  mov #Eingabepuffer, r11  ; Pufferadresse holen, um Platz zu sparen.
  clr.b @r11               ; Puffer leeren

QuerySchleife:
  call #key   ; Tastendruck abwarten
  popda r10         ; und holen.

  ; Prüfe, ob das ein Steuerzeichen ist.

  cmp #32, r10 ; ASCII 0-31 sind Steuerzeichen, 32 ist Space. Die Steuerzeichen müssten einzeln behandelt werden.
               ; Space wird hier einfach so mit aufgenommen.
  jhs QueryZeichen ; Sprung zur ersten Aufnahme eines gewünschten Zeichens
  ; -----------------------------------------------------------------
  ; Ja, das ist ein Steuerzeichen ! 10, 13 Zeilenumbrüche; 8 Backspace.
    ; write " Steuerzeichen "
    ; pushda r10
    ; call #udot
    ; write " "

 ; Tab in Leerzeichen umwandeln und in Puffer legen
  cmp #9, r10
  jne +
    mov #32, r10
    jmp QueryZeichen
+ 

  ; Prüfe auf Zeilenumbruch, Return...
  cmp #10, r10 ; Zeilenumbruch, Variante 1
  je +
  cmp #13, r10 ; Zeilenumbruch, Variante 2
  jne ++

+ ; Return:
    write " "   ; Leerzeichen anstelle des Zeilenumbruchs ausgeben
    pop r11     ; Fertig !
    pop r10
    ret

+ ; Andere Steuerzeichen
  cmp #8, r10
  jne QuerySchleife ; Wenn es auch nicht Backspace ist, wird das Zeichen schlichtweg ignoriert.

    ; Wenn der Puffer nicht leer ist, muss ich nun das letzte Zeichen aus dem Puffer nehmen und visuell löschen.
    tst.b @r11        ; Pufferlänge prüfen
    je QuerySchleife  ; Wenn Pufferlänge Null, ist nichts zu tun.

    call #dotgaensefuesschen ; Zeichen visuell löschen
    .byte 3, 8, 32, 8        ; Cursor einen Schritt zurück. Mit Leerzeichen überschreiben. Nochmal zurück.

    ; Zeichen aus Puffer entfernen (hier Unicode-Besonderheit beachten.)
    ifdef unicodebeachten ; Unicode-Beachtung: Vielleicht wird auch mehr als ein Byte aus dem Eingabepuffer entfernt.
      ; Unicode-Zeichen sind so aufgebaut:
      ; 11xx xxxx,  10xx xxxx,  10xx xxxx......
      ; Wenn das letzte Zeichen also vorne ein 10 hat,
      ; muss ich so lange weiterlöschen, bis ich eins mit 11 vorne erwische.
      ; Prüfe natürlich immer, ob der Puffer vielleicht schon leer ist. Ausgetrickst !

-     tst.b @r11 ; Längenbyte lesen
      je QuerySchleife ; Null ? Nichts zum Abhängen da.

      ; Prüfe das letzte Zeichen.
      mov.b @r11, r10     ; Längenbyte in r10 holen,
      mov.b Eingabepuffer(r10), r10 ; Zeichen holen
      dec.b @r11          ;   und abschneiden.

      ; Teste das Zeichen auf Unicode, oberstes Bit gesetzt ?
      bit #10000000b, r10
      jnc QuerySchleife ; Wenn nein, dann war das ein normales Zeichen und ich bin schon fertig.

      ; Ansonsten könnten noch mehr Unicode-Zeichen folgen.
      ; Zeichen das erste Byte eines Unicode-Zeichens ?
      bit #01000000b, r10
      jnc - ; Wenn nein, lösche ein weiteres Zeichen.
      ; Wenn ja, fertig. Dann habe ich soeben das erste Byte eines Unicode-Zeichens entfernt.
      jmp QuerySchleife

    else
      dec.b @r11 ; Einfach ein Byte weniger. Keine Unicode-Beachtung.
      jmp QuerySchleife
    endif

QueryZeichen:
+ ; -----------------------------------------------------------------
  ; Ein ganz normales Zeichen. Anhängen, und wenn erfolgreich: Ausgeben.

  cmp.b #MaximaleEingabe, @r11 ; Füllstand des Puffers testen.
  jhs QuerySchleife ; Wenn der Puffer schon voll ist, tue nichts mehr.

  ; Puffer hat noch Platz, hänge also an:
  ; r11 darf nicht verloren gehen !

  inc.b @r11   ; Stringlänge erhöhen, Länge wurde eben schon überprüft !

  mov.b @r11, r7 ; Hole die Länge
  mov.b r10, Eingabepuffer(r7) ; Zeichen ans Ende des Strings hineinschieben

  pushda r10 ; Zeichen
  call #emit ; ausgeben

  jmp QuerySchleife
