Gehversuche mit SWAT / Death due to DBCS

  • Hallo zusammen

    Keine Ahnung, wann ich SWAT das letzte Mal angeschaut habe. Aber heute war es wieder einmal soweit...

    Dazu habe ich den Quelltext von GeoLadder ins Verzeichnis $ROOT_DIR/Appl kopiert und im $ROOT_DIR/Installed/Appl übersetzt. Das Target / SWAT lässt sich starten (standard DOSBOX, noch nicht Basebox). Die Geode kann mittels send in Target kopiert werden und dann weiter mit cont.

    Soweit alles gut. Bis anhin nur Warnungen bezüglich MemLock von Chunks in Ressourcen mit ui-object Attribute.

    Aber der Patient stirbt, sobald ich die Ctrl- / Strg-Taste drücke:

    Code
    Death due to CANNOT_USE_DOUBLE_BYTE_CHARS_IN_THIS_VERSION
    LocalDowncaseChar+10: MOV     AX, 606 (025eh)
    Execution died in patient geos:
    LocalDowncaseChar+10: MOV     AX, 606 (025eh)
    *** No explanation available ***
    Interrupt 3: Breakpoint trap
    Stopped in FatalError, line 870, "/home/bolle/pcgeos/Library/Kernel/Boot/bootBoot.asm"
           push    bp, si, ds, ax

    Beim Target-Bau habe ich zu DBCS explizit nein gesagt. Aber meine App wurde anscheinend mit DBCS-Unterstützung gebaut. Muss ich hierzu explizit etwas konfigurieren?

    Edited once, last by bolle732 (September 19, 2024 at 4:39 PM).

  • Also, im GeoWrite kann ich z.B. ohne Probleme Strg-F zum Suchen drücken. Irgendwie liegt das an meinem Keyboard-Handling im Code...

    Dieser funktioniert im EC unter SWAT:

    Code
    // Handle escape key
    if (character == 0xFF1B)

    Dieser nicht, wird einfach ignoriert:

    Code
    // Key 'Arrow Up'
    case 0xFF90:

    Wenn ich F3 zum Schliessen drücke, kommt auch die Meldung CANNOT_USE_DOUBLE_BYTE_CHARS_IN_THIS_VERSION... Bei anderen Progammen nicht.

    Muss da wohl einmal das Design der MSG_META_KBD_CHAR durchgehen... Als NC ohne SWAT lief das bisher tadellos.

  • Poste doch mal den Code (mit Variablendefiniton, wenn vorhanden) , der zum CANNOT_USE_DOUBLE_BYTE_CHARS_IN_THIS_VERSION geführt hat. ggf hilft das swat Kommando bt.

    Damit du mit swat vernünftig arbeiten kannst musst du aktuell die EC-Version des Target UND die EC-Geode benutzen.

    Rainer

    Es gibt 10 Arten von Menschen - die einen wissen was binär ist, die anderen nicht.

  • Hallo Rainer

    Ich habe EC Target und auch den GeoLadder wurde mit EC übersetzt.

    Der Backtrace sieht folgendermassen aus:

    Die Methode wäre das (ok, ist etwas grösser...)

    Externe Variablen wären g.ss.XXX. Diese sind aber nur zur Flusssteuerung im Einsatz:

  • Andere Programme machen das auch:

    Code
    $ grep -RI "flags.*SS_LCTRL.*SS_RCTRL"
    Library/FlatFile/Database/ffDatabaseText.goc:            flags &= ~((SS_LCTRL | SS_RCTRL | SS_LSHIFT | SS_RSHIFT) << 8);
    Library/FlatFile/Database/ffDatabaseText.goc:            flags &= ~((SS_LCTRL | SS_RCTRL | SS_LSHIFT | SS_RSHIFT) << 8);
    Appl/EduApps/TAide/SEATING.goc:            ((flags & ((SS_LALT|SS_RALT|SS_LCTRL|SS_RCTRL)<<8))==0))  {
    Appl/Breadbox/NewsRead/UIClass/NApp.goc:            ((flags >> 8) & (SS_LCTRL|SS_RCTRL))
    Appl/Breadbox/NewsRead/UIClass/NApp.goc:    //        !((flags >> 8) & (SS_LCTRL|SS_RCTRL|SS_LSHIFT|SS_RSHIFT))
    Appl/Breadbox/NewsRead/UIClass/NApp.goc:    //        !((flags >> 8) & (SS_LCTRL|SS_RCTRL|SS_LSHIFT|SS_RSHIFT))
    Appl/GeoLadder/Main/process.goc:    if ((flags >> 8) & (SS_LCTRL | SS_RCTRL))
  • Meine Vermutung ist, dass du tolower (resp LocalDonwcaseChar) einen Wert >255 übergibst. character ist ja int und 0xFFxx wenn es ein Steuerzeichen ist. Das interpretiert swat möglicherweise als Double-byte-character. Also Steuerzeichen vorher abfangen oder tolower(character) -> tolower(charachter & 0xFF) oder LocalDonwcaseChar(charachter & 0xFF).

    Rainer

    Es gibt 10 Arten von Menschen - die einen wissen was binär ist, die anderen nicht.

  • Hallo Rainer

    Das macht soweit Sinn. Ich werde das morgen am anderen Rechner mit funktionierendem Swat ausprobieren. Das tolower() im Fall von einer Ctrl-Kombination ist eigentlich überflüssig. Es gibt ja nur Ctrl-[0...2].

    Der mit dem Beenden durch F3 muss ich mal im Backtrace anschauen.

    Gruss
    Andreas

  • Generell bin ich mit dem Handling vom Keyboard noch nicht so ganz glücklich...

    Aktuell ist ja der Prozess zuständig. Aber anstatt mit vielen ifs und switchs zu arbeiten, würde ich lieber die einzelnen Objekte verwenden. In meinem Fall würde sich die LadderScreenClass für die MSG_META_KBD_CHAR anbieten. Wenn ich es richtig verstehe, ist eine Message für jede Klasse fix definiert und man kann nicht pro Objekt-Instanz eine Methode überschreiben, ohne entsprechend weiter Sub-Klassen zu erzeugen. Für mich hiesse das, entsprechnd viele Sub-Klassen zu definieren.

    Was mich auch noch davon abhielt, ist die Vermutung, dass sich dies negativ auf die Latenz auswirkt. Beim GeoLadder ist es schon relativ wichtig, dass die Latenz klein bleibt, noch wichtiger ist aber, dass sie nicht zu sehr schwankt. Es ist einfacher mit einer konstanten grösseren Latenz zu spielen als mit einer schwankenden kleinen.

    Und ich bin mir auch noch nicht absolut sicher, wie genau die Weitergabe eines Tastendrucks in der Objekt-Hirarchie aussieht. War mal der Meinung, dass ein Key-Event dem untersten Objekt übergeben wird und dieses dann den Event dem Parent weiterreicht, wenn der Event nicht behandelt wurde.

    Habe mal eine kleine Zeichnug erstellt, in welcher man die Objekt-Hirarchie sieht:

    Ladder Code Classes & Objects.pdf

  • Meine Vermutung ist, dass du tolower (resp LocalDonwcaseChar) einen Wert >255 übergibst. character ist ja int und 0xFFxx wenn es ein Steuerzeichen ist. Das interpretiert swat möglicherweise als Double-byte-character. Also Steuerzeichen vorher abfangen oder tolower(character) -> tolower(charachter & 0xFF) oder LocalDonwcaseChar(charachter & 0xFF).

    Rainer

    Gibt es einen Unterschied zwischen tolower() und LocalDowncaseChar()?

  • Hallo!

    tolower() ist die normale C-Funktion aus ctype.h. Laut Standarddefinition werden nur die Großbuchstaben A-Z in die Kleinbuchstaben a-z umgewandelt (durch ein +44). Alle anderen Zeichen bleiben, wie sie sind. Ein Ä wird z.B. nicht in ein ä umgewandelt, ebensowenig ein É in ein é. Jedenfalls, wenn sich der Hersteller des Compilers (und der Bibliothek) an den Standard hält.

    LocalDowncaseChar() berücksichtigt hingegen die aktuellen Spracheinstellungen, wandelt also auch ein Ä in ein ä und ein É in ein é um.

    (Das klingt zwar trivial, da das Regelwerk gar nicht von den Ländereinstellungen abhängen sollte. Aber theoretisch könnte es auch Regeln für nicht-lateinische 8Bit-Zeichensätze wie Kyrillisch oder Griechisch implementieren, was bei Geos nicht der Fall sein sollte. Das Gegenstück LocalUppercaseChar() sollte z.B. berücksichtigen, ob aus dem é ein É oder ein E werden soll. Hier gibt es also definitiv „regionale Sonderlocken“.)

    There are two rules in life:
    1. Never give out all of the information.

  • Sodele, das maskieren mit 0xFF bei tolower() war erfolgreich ;) Danke Rainer!

    Das Problem beim Beenden (F3) war, dass Swat beim Aufrufen von ObjMarkDirty() den Block gelockt haben möchte. Auch gelöst.

    Dass die Pfeiltasten nicht funktionierten lag an der Konfiguration der DosBox (im Bereich [sdl] den Eintrag usescancodes=false setzen). Liegt wohl daran, dass ich nur noch mit der DosEmu2 unterwegs war...

    Aktuell ist gerade nur noch die Warnung CANNOT_CALL_MEM_LOCK_ON_AN_OBJECT_BLOCK:

    Code
      // Set the help file name
     MemLock(HandleOf(@LadderHelpFile));
     memcpy(&buf, LMemDeref(@LadderHelpFile), LMemGetChunkSize(@LadderHelpFile));
     @call application::MSG_META_SET_HELP_FILE(buf);
     MemUnlock(HandleOf(@LadderHelpFile));

    Der Chunk @LadderHelpFile liegt beim Application-Objekt in der gleichen Ressource, welche als ui-object klassifiziert ist.

  • Hallo!

    tolower() ist die normale C-Funktion aus ctype.h. Laut Standarddefinition werden nur die Großbuchstaben A-Z in die Kleinbuchstaben a-z umgewandelt (durch ein +44). Alle anderen Zeichen bleiben, wie sie sind. Ein Ä wird z.B. nicht in ein ä umgewandelt, ebensowenig ein É in ein é. Jedenfalls, wenn sich der Hersteller des Compilers (und der Bibliothek) an den Standard hält.

    LocalDowncaseChar() berücksichtigt hingegen die aktuellen Spracheinstellungen, wandelt also auch ein Ä in ein ä und ein É in ein é um.

    (Das klingt zwar trivial, da das Regelwerk gar nicht von den Ländereinstellungen abhängen sollte. Aber theoretisch könnte es auch Regeln für nicht-lateinische 8Bit-Zeichensätze wie Kyrillisch oder Griechisch implementieren, was bei Geos nicht der Fall sein sollte. Das Gegenstück LocalUppercaseChar() sollte z.B. berücksichtigen, ob aus dem é ein É oder ein E werden soll. Hier gibt es also definitiv „regionale Sonderlocken“.)

    Hallo Jörg

    Sehr schön beschrieben und herzlichen Dank für die Aufklärung :thumbup:

    In diesem Fall werde ich bei tolower() bleiben, da es keine Umlaute behandeln muss und entsprechend effizienter sein sollte.

    Schönen Gruss
    Andreas

  • tolower() ist die normale C-Funktion aus ctype.h. Laut Standarddefinition werden nur die Großbuchstaben A-Z in die Kleinbuchstaben a-z umgewandelt (durch ein +44). Alle anderen Zeichen bleiben, wie sie sind. Ein Ä wird z.B. nicht in ein ä umgewandelt, ebensowenig ein É in ein é. Jedenfalls, wenn sich der Hersteller des Compilers (und der Bibliothek) an den Standard hält.

    Ich habe das auch vermutet, aber es scheint nicht zu stimmen. Beim WordMatcher verwenden Sie auch toupper und ich dachte, dass es Probleme gibt. Tut es aber nicht.

    bolle732 Ich würde auf jeden Fall die Localize-Routinen benuzten. Dein Backtrace zeigt, das TOLOWER LocalDowncaseChar ruft, was den Fehler erzeugt, wenn ah != 0 ist.

    Rainer

    Es gibt 10 Arten von Menschen - die einen wissen was binär ist, die anderen nicht.

  • Wenn ich es richtig verstehe, ist eine Message für jede Klasse fix definiert und man kann nicht pro Objekt-Instanz eine Methode überschreiben, ohne entsprechend weiter Sub-Klassen zu erzeugen. Für mich hiesse das, entsprechnd viele Sub-Klassen zu definieren.

    Genau so verstehe ich das auch. Viel subclassen bedeuten aber viel Fixed Speicher. Das würde ich also nicht machen. In R-BASIC hatte ich ähnliche Überlegungen und habe letztlich primär MSG_META_KBD_CHAR der ApplicationClass verwendet.

    Und ich bin mir auch noch nicht absolut sicher, wie genau die Weitergabe eines Tastendrucks in der Objekt-Hirarchie aussieht.

    Da musst du mal in die Doku schauen, da gibts ein ganzes Kapitel dazu. Soweit ich mich erinnere bekommt das Application-Objekt die Tastendrücke als erstes zu sehen.

    Rainer

    Es gibt 10 Arten von Menschen - die einen wissen was binär ist, die anderen nicht.

  • Genau so verstehe ich das auch. Viel subclassen bedeuten aber viel Fixed Speicher. Das würde ich also nicht machen. In R-BASIC hatte ich ähnliche Überlegungen und habe letztlich primär MSG_META_KBD_CHAR der ApplicationClass verwendet.

    Ich tue mich auch schwer, der Schönheitshalber Ressourcen zu vrebrauchen...

    Quote

    Da musst du mal in die Doku schauen, da gibts ein ganzes Kapitel dazu. Soweit ich mich erinnere bekommt das Application-Objekt die Tastendrücke als erstes zu sehen.

    Ja, das habe ich mir auch gedacht. Wollte eben zuerst mal nachfragen, was technisch gesehen Sinn macht oder nicht. Nehme mal an, dass eine ui-object Ressource nicht fixed ist. Dachte, es gäbe eventuell einen anderen Weg, diese zu fixieren.

  • Nehme mal an, dass eine ui-object Ressource nicht fixed ist. Dachte, es gäbe eventuell einen anderen Weg, diese zu fixieren.

    Das Problem ist - falls ich das richtig verstanden habe - beim Locken einer Ressoure mit UI-Objketen ein paar Schritte erfordert, die beim Locken einer reinen Daten-Ressource nicht erforderlich sind. Auf einen Datenchunk in einer UI-Ressource kannst du ohne weitere Probleme zugreifen, bei dem Chunks, die Objekte enthalten wäre ich mir da nicht sicher, sonst würde es die Warnung nicht geben.
    Insofern: Des Verschieben eine Datenchunks in eine Data-Resource ist klein Ressourcenverbrauch sondern nur saubere Programmierung :) Du hast doch ganz bestimmt mehr als einen Daten-Chunk.

    Interessanterweise kann ein Chunk in der gleichen Ressource vom UserStandardDialogOptr problemlos darauf zugreifen. Und ein Pointer in einer anderen ui-object Ressource kann ohne Probleme gelockt werden.

    ? Ok, jetzt kann ich dir nicht mehr folgen.:/

    Rainer

    Es gibt 10 Arten von Menschen - die einen wissen was binär ist, die anderen nicht.