Σάββατο, 8 Φεβρουαρίου 2020

Αναθεώρηση 6, Έκδοση 9.9

Συνεχίζω, πιο αργά, να αναβαθμίζω τη γλώσσα και το περιβάλλον της. Θα ανεβάζω μια νέα αναθεώρηση κάθε μήνα περίπου. Σε αυτήν έκανα τις τελικές διορθώσεις στους επεξεργαστές κειμένου, το εσωτερικό στη κονσόλα και το στοιχείο ελέγχου EditBox (ή Κείμενο). Όταν έχουμε βάλει τον δρομέα ας πούμε στον 30ο χαρακτήρα και πάμε με το βελάκι πάνω, τότε ή θα υπάρχει 30ος χαρακτήρας και θα μένει εκεί ή θα πάει στον τελευταίο της γραμμής (<30) αλλά το 30 θα το θυμάται εκτός αν μεταφέρουμε οριζόντια το δρομέα. Έτσι αν έχουμε το δρομέα σε μια μεγάλη γραμμή και μετά τον κατεβάσουμε σε μια μικρή και πάλι τον ανεβάσουμε πάνω, θα πάμε στο σημείο που ξεκινήσαμε! Αυτό γίνονταν και στην 5 αλλά υπήρχε ένα θέμα με το εξής απίστευτο, αν έκανε κάποιος την κίνηση από τη μεγάλη γραμμή στη μικρή και πάταγε το enter, τότε διαγράφονταν δυο χαρακτήρες! Λύθηκε το πρόβλημα με μια γραμμή κώδικα (από μια για το κάθε στοιχείο).Αυτός ο τρόπος κίνησης του δρομέα υπάρχει και στον διορθωτή αυτού του blog.

Έχω κάνει την προεργασία για ένα αντικείμενο όπως ένα hash table, αλλά με διπλό κλειδί, δηλαδή δυο πίνακες hash, έτσι ώστε να φτιάξω την relational database, πιο απλή αλλά να μην στηρίζεται σε εξωτερικές βιβλιοθήκες. (αν και θα παραμείνει η δυνατότητα να χειριζόμαστε ADO αντικείμενα).


Εδώ είναι κώδικας που δημιουργεί μια βάση δεδομένων στη μνήμη (local). Ακόμα δεν υπάρχει η SQL για αυτή τη βάση. Αυτό που γίνεται είναι να δημιουργηθεί η βάση, και να διαβάσουμε τη δομή της.
Αν αφαιρέσουμε το local μετά το base τότε η βάση θα γίνει στο δίσκο σαν alfa.mdb
Περίπου φαίνεται το ίδιο στην ανάγνωση της δομής στις δυο περιπτώσεις. Θέλει ακόμα δουλειά!


base local "alfa"
table "alfa", "firstTable", "field1",long, -1, "title1", text, 40, "memo1", memo, 0,"mo1", memo, 0, "money", double,0
order "alfa", "firstTable", "title1", descending, "money",  descending
function attrib$(i) {
 if i=-1 then
 ="AutoIncrement"
 else.if i=0 then
 ="Default"
 else
 =str$(i,"")
 end if
}
structure "alfa"
read many
if many>0 then
Print "Tables:"
for i=1 to many
read tablename$, indexnumber
Print i, ") ";tablename$, "indexes:"; indexnumber
structure "alfa", tablename$
read many, indexnumber
if many>0 then
 Print " ", "Fields:"
 for j=1 to many
 read fieldname$, fieldtype$, fieldlen
 Print "",j,") ";fieldname$, @(tab(4)), fieldtype$, attrib$(fieldlen)
 next j
end if
Read indexnumber
if indexnumber>0 then
 Print " ", "Order:"
 for j=1 to indexnumber
 read fieldname$, fieldtype$
 Print "",j,") ";fieldname$, @(tab(4)), fieldtype$
 next j
end if
next i
end if
close base "alfa"
flush

Σάββατο, 28 Δεκεμβρίου 2019

Αναθεώρηση 5, Έκδοση 9.9

Ανέβηκε η αναθεώρηση 5 της έκδοσης 9.9
Σε αυτήν την αναθεώρηση έκανα το EditBox ή Κείμενο, ένα στοιχείο ελέγχου να  δουλεύει για κείμενο RTL (right to left).Όπως ήταν πριν εμφάνιζε κείμενο όπως πρέπει αλλά δεν λειτουργούσε η αλλαγή κατεύθυνσης του δρομέα. Ακόμα υπάρχει δουλειά για το TextBox (δεν το έχω φτιάξει).
Το EditBox έχει μια διαμόρφωση ως TextBox, δηλαδή να εμφανίζει μόνο μια γραμμή πληροφορίας, χωρίς να δέχεται το Enter (το οποίο στο κανονικό EditBox παρεμβάλει μια νέα γραμμή).
Για να γίνει κατανοητό αυτό έχω βάλει ένα πρόγραμμα το SimpleTxt, με ελληνικές εντολές, και το SimpleTxtEn, με αγγλικές εντολές, στο info.
Με την εγκατάσταση της νέας αναθεώρησης (αφού κάνουμε απεγκατάσταση της παλιάς, αν έχουμε ήδη τη Μ2000 στον υπολογιστή μας), θα δώσουμε το Dir Appdir$: Load Info και μόλις φορτωθεί το νέο Info θα πατήσουμε το F1 για να μεταγραφεί στο φάκελο χρήστη..

Το EditBox, έχει τρεις επιμέρους διαμορφώσεις: Να εισάγει αριθμό με δεκαδικά, ή να εισάγει ακέραιο ή να εισάγει μια γραμμή κειμένου. Στο κείμενο μπορούμε να βάζουμε και RTL (πχ εβραϊκά).

Στο παράδειγμα φτιάχνουμε μια φόρμα με τρία στοιχεία ελέγχου τύπου Κείμενο (EditBox). Σε καθένα ορίζουμε την ιδιότητα που θέλουμε, να είναι αληθές, και συνδέουμε μια μεταβλητή με την τιμή που θα διαβάζουμε. Σε κάθε στοιχείο αν πατήσουμε το Ctrl+F1 θα πάρουμε μια νέα εμφάνιση "αποτελέσματος". Αν πατάμε enter ή κάνουμε κλικ πάνω στη φόρμα τότε παίρνουμε νέο αποτέλεσμα. Το αποτέλεσμα είναι να εμφανιστούν πληροφορίες απευθείας πάνω στη φόρμα, από τα στοιχεία, και ένα στοιχείο, το πρώτο να αυξάνει την τιμή του.
Επίσης βλέπουμε πως βάζουμε ετικέτες με την Επιγραφή ή Legend, με στοίχιση δεξιά.




Όρισε Φόρμα1 Φόρμα
Όρισε Κειμ1 Κείμενο Φόρμα Φόρμα1
Όρισε Κειμ2 Κείμενο Φόρμα Φόρμα1
Όρισε Κειμ3 Κείμενο Φόρμα Φόρμα1
θεσηΧ=4000
Μέθοδος Κειμ1, "Move", θεσηΧ,1200,5000,400
Μέθοδος Κειμ2, "Move", θεσηΧ,1800,5000,400
Μέθοδος Κειμ3, "Move", θεσηΧ,2400,5000,400
νγ$={
}
Με Κειμ1, "ShowAlways", Αληθές, "NumberOnly", Αληθές, "Value" ως Τιμ1
Με Κειμ2, "ShowAlways", Αληθές, "NumberIntOnly",Αληθές, "Value" ως Τιμ2
Με Κειμ3, "ShowAlways", Αληθές, "UsedAsTextBox", Αληθές,"Text" ως Τιμ3$
Τιμ1=93.112
Τιμ2=1456
Τιμ3$="Μια γραμμή μόνο"
Συνάρτηση Κειμ1.About {
      Κάλεσε Τοπικά Φόρμα1.About()
}
Συνάρτηση Κειμ2.About {
      Κάλεσε Τοπικά Φόρμα1.About()
}
Συνάρτηση Κειμ3.About {
      Κάλεσε Τοπικά Φόρμα1.About()
}
Συνάρτηση Φόρμα1.About {
      Επίπεδο Φόρμα1 {
            Οθόνη #606060
            Τύπωσε $(Τρόπος),"Κάνε κλικ εδώ ή πάτα Enter"
}
}
Συνάρτηση Φόρμα1.Enter {
      Κάλεσε Τοπικά Φόρμα1.Click()
}
Συνάρτηση Φόρμα1.Click {
      Επίπεδο Φόρμα1 {
            Τιμ1=Τιμ1+1 \\ δεν δουλεύει το Τιμ1++ γιατί είναι αντικείμενο και όχι μεταβλητή
            Οθόνη #606060
            Τύπωσε Τιμ1, Τιμ2, " Ctrl+F1"
            Τύπωσε Πάνω $(9), Τιμ3$
            Ανανέωση
            Μέθοδος Κειμ1, "Show"
}
}
Τρόπος=4
Επίπεδο Φόρμα1 {
      Γραμματοσειρά "Arial Black"
      Παράθυρο 16, 10000,4500
      Πένα 15
      Οθόνη #202020
      Οθόνη #606060, Ύψος-2
      Θέση θεσηΧ, 1200+400
      Επιγραφή "Ετικέτα ", Γραμματοσειρά$, Τύπος, 0, 1
      Θέση θεσηΧ, 1800+400
      Επιγραφή "Άλλη ετικέτα ", Γραμματοσειρά$, Τύπος, 0, 1
      Θέση θεσηΧ, 2400+400
      Επιγραφή "Και άλλη ετικέτα ", Γραμματοσειρά$, Τύπος, 0, 1
      Πένα 13
      Τύπωσε $(Τρόπος),"Κάνε κλικ εδώ ή πάτα Enter"
}
Μέθοδος Φόρμα1, "Show",1
Όρισε Κειμ1 Τίποτα
Όρισε Φόρμα1 Τίποτα


Και στα αγγλικά


Declare Form1 Form
Declare text1 editbox Form Form1
Declare text2 editbox Form Form1
Declare text3 editbox Form Form1
PositionX=4000
Method text1, "Move", PositionX,1200,5000,400
Method text2, "Move", PositionX,1800,5000,400
Method text3, "Move", PositionX,2400,5000,400
nl$={
}

With text1, "ShowAlways", True, "NumberOnly", True, "Value" As Value1
With text2, "ShowAlways", True, "NumberIntOnly", True, "Value" As Value2
With text3, "ShowAlways", True, "UsedAsTextBox", True,"Text" As Value3$
Value1=93.112
Value2=1456
Value3$="One line only"
Function text1.About {
      Call Local Form1.About()
}
Function text2.About {
      Call Local Form1.About()
}
Function text3.About {
      Call Local Form1.About()
}
Function Form1.About {
      Layer Form1 {
            Cls #606060
            Print $(Way),"Press right mouse button or Enter"
}
}
Function Form1.Enter {
      Call Local Form1.Click()
}
Function Form1.Click {
      Layer Form1 {
            Value1=Value1+1 \\  Value1++ not work becaue Value1 is an object (linked property)
            Cls #606060
            Print Value1, Value2, " Ctrl+F1"
            Print Over $(9), Value3$
            Refresh
            Method text1, "Show"
}
}
Way=4
Layer Form1 {
      Font "Arial Black"
      Window 16, 10000,4500
      Pen 15
      Cls #202020
      Cls #606060, Ύψος-2
      Move PositionX, 1200+400
      Legend "Label ", Fontname$, Mode, 0, 1
      Move PositionX, 1800+400
      Legend "Another Label ", Fontname$, Mode, 0, 1
      Move PositionX, 2400+400
      Legend "And another Label ", Fontname$, Mode, 0, 1
      Pen 13
      Print $(Way),"Press right mouse button or Enter"
}
Method Form1, "Show",1
Declare text1 Nothing
Declare Form1 Nothing



Δευτέρα, 16 Δεκεμβρίου 2019

Αναθεώρηση 4 Έκδοση 9.9

Ανέβηκε όση εργασία έχω κάνει μέχρι τώρα στην Μ2000. Ενημερώθηκε και το Dropbox (δεν είχε ενημερωθεί στην αναθεώρηση 3, αλλά υπάρχει στο github για κατέβασμα χωριστά - το master είναι στο 4).

Μπορεί κανείς να δοκιμάσει να γράψει αραβικά ή ισραηλινά (εβραϊκά) στον διορθωτή προγράμματος. Στο info αρχείο υπάρχει το RTL παράδειγμα. Οπότε καλό είναι να κάνουμε το εξής όταν απεγκαταστήσουμε τη προηγούμενη έκδοση και εγκαταστήσουμε την νέα:

Dir Appdir$
load info
(press F1 to save to the info.gsb to user folder)

Έτσι πατώντας το F1 θα σώσουμε το info με όλα τα προγράμματα, στο φάκελο του χρήστη. Την επόμενη φορά θα γράψουμε Load Info και θα φορτώσει από το φάκελο χρήστη.

Οι φόρμες μπορούν να δείξουν αραβικά, αλλά το στοιχείο Κείμενο (EditBox) προς το παρόν εμφανίζει σωστά το κείμενο αλλά δεν έχω φτιάξει το κώδικα όπως στον editor στη κονσόλα για να μετακινείται προς τα πίσω ο δείκτης...και επιπλέον για να μεταφέρουμε με το ποντίκι το δρομέα σωστά πάνω στο RTL κείμενο. Ανοίξτε με το Edti RTL το πρόγραμμα με τα αραβικά και εβραϊκά, και από την αρχή του κειμένου κρατήστε πατημένο το δεξί βελάκι να δείτε πως θα κινηθεί ο δρομέας!

Οι διορθωτές απέκτησαν ένα χαρακτηριστικό που μου άρεσε από άλλους editor, όπως το να ξεκινάμε από την έστω 14 θέση του δρομέα, και μετακινώντας μόνο με τα άνω και κάτω βελάκια δεν αλλάζει η θέση του δρομέα, παρά μόνο φανερά αν η γραμμή έχει λιγότερους χαρακτήρες από 14, και έτσι αν ξαναγυρίσουμε στην ίδια γραμμή θα πάει ο δρομέας στη θέση απ΄όπου ξεκίνησε. Αν μεταφέρουμε με το ποντίκι ή με τα βελάκια αριστερό ή δεξί, τότε αλλάζουμε τη θέση και τη φανερή και την πραγματική. Όταν κάνουμε επικόλληση τότε αυτή γίνεται στη φανερή θέση (εκεί που αναβοσβήνει ο δρομέας). Επίσης το ίδιο γίνεται όταν πατάμε το Tab.

Καλά Χριστούγεννα, Καλές Γιορτές!


Σάββατο, 14 Δεκεμβρίου 2019

Αναθεώρηση 3 έκδοση 9.9

Μια μικρή αναθεώρηση ανέβηκε που διορθώνει ένα πρόβλημα στην Ένωση() ή Cons().

πχ
Ν=ενωση((1,2,3), (4,5,6))
Τύπωσε Ν

δίνει ένα πίνακα με έξι στοιχεία:  1   2   3   4   5  6


Παράλληλα υπάρχει σε αναμονή η αναθεώρηση με τον διερμηνευτή που διαβάζει ένα πρόγραμμα και το μετατρέπει σε ενδιάμεσο κώδικα (προς το παρόν ότι έχει δημοσιευθεί μέχρι και τη τρέχουσα έκδοση δουλεύει με άμεση εκτέλεση, ενώ χρησιμοποιεί κάποιες φορές το "κοίταγμα μπροστά" ή look ahead, το οποίο βρίσκει που τερματίζουν  οι εκφράσεις, η που βρίσκεται το σημείο μεταφοράς της ροής (πχ σε μια Ενώ .... Τέλος Ενώ να βρει το τέλος, ή σε μια Ενώ που ακολουθεί ένα μπλοκ εντολών, να βρει το τέλος του μπλοκ). Θα προχωρήσω αυτή την αναθεώρηση αφού τελειώσω το παρακάτω:

Ετοιμάζω μια νέα αναθεώρηση, που θα πάρει καιρό. Σε αυτήν ασχολούμαι με δυο θέματα: Την χρήση RTL κειμένου (right to left) με αραβικά και ισραηλινά γράμματα. Έχω πετύχει ήδη την αλλαγή του διορθωτή προγράμματος ώστε ο δρομέας να κινείται ανάλογα με το κείμενο. Εδώ να επισημάνω ότι είναι διαφορετικό πράγμα να έχεις διορθωτή για γλώσσες με γραφή από  δεξιά προς τα αριστερά από το να έχεις ταυτόχρονα και τα δυο ήδη μαζί. Οι εντολές της γλώσσας είναι στα αγγλικά και στα ελληνικά οπότε πρέπει να γράφονται από αριστερά προς τα δεξιά (LTR κείμενο). Επίσης ένα άλλο θέμα είναι οι αριθμοί μετά από κείμενο με αραβικά ή ισραηλινά γράμματα. Οι αριθμοί γράφονται με τα νούμερα με τη σειρά που πρέπει αλλά όλο το νούμερο γράφεται προς τα αριστερά! Αν οι χαρακτήρες πριν το νούμερο είναι ελληνικοί θα γραφτούν δεξιά! Ένας τρόπος που σκέφθηκα για να ξεπεράσω το πρόβλημα του τι πρέπει να αντιμετωπιστεί ως RTL κείμενο, είναι η χρήση του χρωματισμού, που είχε ο διορθωτής. Έτσι μια παράγραφος κόβεται σε χρωματισμένο κείμενο και κάθε κοψιά αντιμετωπίζεται ξεχωριστά από κάθε άλλη. Επειδή ο διορθωτής έχει μια λειτουργία (με το F11) που αποχρωματίζει το κείμενο, στη νέα μη δημοσιευμένη αναθεώρηση δείχνει μεν αποχρωματοποιημένο το κείμενο, αλλά εσωτερικά συνεχίζει να είναι, για να "προστατέψει" τα κοψίματα. Αν δεν το έκανε αυτό τότε υπήρχε περίπτωση να γυρίσουν κάποια μέρη του κειμένου με παρουσία RTL κειμένου σε άλλες θέσεις από αυτές που θα θέλαμε να είναι (και είναι όταν είναι φανερό το χρώμα).

Επίσης άλλαξα τον τρόπο εμφάνισης του κειμένου στο διορθωτή (εσωτερικά) με χρήση άλλων ρουτινών του λειτουργικού, και τώρα δεν χρειάζεται όπως έκανα πριν όταν είχαμε tab χαρακτήρα, να τυπώνουμε κάθε ξεχωριστό χρώμα από την αρχή με χρήση "παράθυρου" εμφάνισης. Όταν υπήρχαν πολλά χωριστά κομμάτια, και το tab στην αρχή της γραμμής έπεφτε η ταχύτητα, και φαίνονταν τουλάχιστον σε μένα που καταλάβαινα!

Δυσκολεύτηκα πολύ να βρω πως δουλεύει το σύστημα με τις μεταθέσεις λέξεων στο RTL, και μάλιστα υπάρχει διαφορά μεταξύ αραβικών και ισραηλινών σε σχέση με τα σύμβολα των  πράξεων, των αριθμών και της τελείας, για τα δεκαδικά! Αποφάσισα να το φτάσω σε ένα σημείο, γιατί αλλιώς δεν θα το τελειώσω ποτέ. Υπάρχουν μια σειρά συναρτήσεων του λειτουργικού που ακόμα δεν έχω χρησιμοποιήσει και αυτές υποτίθεται ότι κάνουν τις δυο λειτουργίες, να λένε που θα πάει ο δρομέας για συγκεκριμένο χαρακτήρα, και το ανάποδο, εκεί που δείχνουμε να πάει ο δρομέας να μας δώσει το χαρακτήρα ως αριθμός από την αρχή της γραμμής ή παραγράφου. Έτσι έφτιαξα δικές μου οι οποίες δουλεύουν (επίσης δουλεύουν και με με κάποια αραβικά που "γυρνάνε" πίσω δηλαδή ενώ ξεκινάνε από το 1000 και τερματίζουν στο 1007 pixel το τελείωμά τους είναι στο 1005 για να δέσει με τον επόμενο χαρακτήρα!  (κάπως έτσι, το περιέγραψα στο περίπου). Οπότε τώρα ξεκινάμε το δρομέα με το βελάκι (πχ το αριστερό) και αυτός αρχίζει να κάνει τα παλαβά του ανάλογα με το κείμενο. Όταν για παράδειγμα πατάμε το Backspace όλοι ξέρουμε ότι σβήνει προς τα "πίσω", το οποίο στο LTR είναι προς τα αριστερά, ενώ στο RTL είναι προς τα δεξιά. Επίσης όταν γράφουμε RTL λέξεις ο δρομέας πάει προς το αριστερά. Έχουμε λοιπόν έναν δρομέα που πηγαίνει αφού αναγνωρίσει το "έδαφος".


Στο αλφαριθμητικό η σειρά που γράφονται οι χαρακτήρες έχουν να κάνουν με την ίδια σειρά που πληκτρολογούμε, έτσι ο δεύτερος χαρακτήρας θα είναι πάντα μετά τον πρώτο. Αυτό που αλλάζει είναι το πως εμφανίζονται ανάλογα με το κείμενο. Στην εμφάνιση υποθέτουμε έναν δρομέα. Όμως ο πρώτος χαρακτήρας που θα εμφανιστεί αριστερά μπορεί να είναι κάποιος άλλος από τον πρώτο στο αλφαριθμητικό και όχι υποχρεωτικά ο τελευταίος. Γίνονται "αναδιπλώσεις" όταν έχουμε εναλλαγή RTL σε LTR.

Έχω φτιάξει την Τύπωσε έτσι ώστε όταν το κείμενο έχει RTL χαρακτήρες να το εμφανίζει με αναλογική γραφή εκεί που θα έπρεπε να εμφανίζει τον έναν χαρακτήρα κάτω από τον άλλο, ή όπως λέμε κάθε χαρακτήρας να έχει εμφάνιση σε θέση χαρακτήρα στην κάνναβο των χαρακτήρων στην οθόνη. Αυτό γίνεται γιατί υπάρχουν λέξεις που δεν μπορούν να σπαστούν σε χαρακτήρες, πρέπει να γραφούν με αναλογική γραφή.

Επίσης έχω φτιάξει την Αναφορά να δουλεύει σωστά, με το RTL και το TAB. Υπάρχει ακόμα θέμα με την στοίχιση και από τις δυο πλευρές κειμένου RTL. Παλαιότερα η στοίχιση γίνονταν με σπάσιμο των λέξεων και εμπλουτισμό με διαστήματα, κατά την εμφάνιση. Με το RTL η σειρά εμφάνισης αλλάζει, οπότε αφήνω το σύστημα να το κάνει (βρήκα και έναν τρόπο να ορίζω το μήκος και τον αριθμό παρεμβολών διαστήματος), αλλά δεν δουλεύει όταν στο κείμενο υπάρχει RTL κείμενο (σαν να το ακυρώνει). Οπότε στην επόμενη αναθεώρηση δεν θα έχουμε πλήρη στοίχιση αν στη γραμμή έχουμε χαρακτήρες RTL (μέχρι να βρω κάποια άλλη λύση).

Επίσης πρέπει να φτιάξω την δυνατότητα για RTL κείμενο και για τα στοιχεία φορμών (Edit Box), με μια ιδιότητα για να έχουμε στοίχιση από δεξιά (και να δουλεύει και η μετάθεση του δρομέα με το δείκτη του ποντικιού, με δεξιά στοίχιση). Ενώ στο διορθωτή προγράμματος θέλουμε να έχουμε αριστερή στοίχιση με κάθε τύπο φοράς γραφής, στα στοιχεία που εισάγουν κείμενο ή προβάλουν κείμενο στις φόρμες θέλουμε να έχουμε δεξιά στοίχιση! Θα μπορούμε όμως να βάλουμε ακόμα και με αριστερή στοίχιση λέξεις RTL. Τα σύμβολα στις φόρμες για κλείσιμο, μεγιστοποίηση και ελαχιστοποίηση ήδη μπορούμε να τα έχουμε δεξιά (εξ ορισμού) ή αριστερά (με επιλογή).

Στην εισαγωγή αλφαριθμητικών ακόμα και σε αυτήν την αναθεώρηση, όταν εισάγουμε με μη αναλογική γραφή, δεν αλλάζει η φορά εισαγωγής. Εδώ ίσως το αλλάξω. Δεν το έχω αποφασίσει ακόμα. Μπορούμε να χρησιμοποιήσουμε


Επίσης ένα δεύτερο θέμα σε αυτήν την μη δημοσιευμένη αναθεώρηση είναι οι βάσεις δεδομένων. Έχω ήδη γράψει μια υποτυπώδη παραλλαγή των βάσεων δεδομένων για την μνήμη, όπου δεν χρησιμοποιώ το ADO (το σύστημα που δίνουν τα windows για βάσεις δεδομένων). Σκοπός μου αρχικά ήταν να αλλάξω το τρόπο καταχώρησης της βοήθειας με ένα δικό μου σύστημα βάσης δεδομένων, γιατί παρατήρησα ότι στα Windows 10, σε μια περίπτωση δεν δούλεψε η βοήθεια, ενώ δούλευαν προγράμματα που χρησιμοποιούσαν αρχεία της access. Αυτό με έκανε να καταλάβω ότι δεν μπορώ να εμπιστευθώ το σύστημα της Access (2007) στα Windows 10. Κατά την υλοποίηση άρχισα να σκέφτομαι ότι μπορώ να κάνω δική μου βάση, με πολλούς πίνακες, με ταξινομήσεις και άλλα πολλά. Έφτιαξα μια παραλλαγή της λίστας με Hash πίνακα (ή πίνακα με συνάρτηση κατακερματισμού), όπου υπάρχουν δυο πίνακες hash, δηλαδή διπλά κλειδιά για την ίδια εγγραφή. Έχω σκοπό να γράψω μια SQL με τα βασικά και να μην εξαρτιέται η Μ2000 από την Access.

Καλές Γιορτές και Καλή Χρονιά!

Γιώργος Καρράς


Τρίτη, 15 Οκτωβρίου 2019

Έκδοση 9.9 Αναθεώρηση 1.

Σε αυτήν την αναθεώρηση έγιναν πολλά πράγματα. Διορθώθηκαν ατέλειες της 9.9. Μπήκαν νέα αναγνωριστικά. Ενημερώθηκε η βοήθεια. Νέα προγράμματα στο info.gsb αρχείο.

Υπάρχει το αναγνωριστικό Διαδίκτυο που γυρνάει αληθής αν έχουμε σύνδεση με το διαδίκτυο. Επίσης το Διαδίκτυο$ γυρνάει την ip που βγαίνουμε στο διαδίκτυο. Υπάρχει ένα ωραίο πρόγραμμα επίδειξης στο info.gsb το Combo1 το οποίο δείχνει παράλληλα την χρήση του combobox, και εμφανίζει συνέχεια την κατάσταση σύνδεσης μέχρι να πατήσουμε ένα πλήκτρο πάνω στη φόρμα που εμφανίζει, οπότε εμφανίζει τις δυο ip, αυτή που δίνει το router σε μας και την δημόσια ip.

Στα tuple (πίνακες στη Μ2000), προστέθηκε μια συνάρτηση (διπλή για αριθμούς και αλφαριθμητικά) #Εκφρ(), #Εκφρ$() και στα αγγλικά #Eval() και #Eval$() η οποία εκτελεί αντικείμενα που γυρνάνε τιμές (με ή χωρίς παραμέτρους, ανάλογα την περιπτωση) και βρίσκονται στο tuple. Μπορούσε να γίνει αυτό, με άλλο τρόπο, αλλά εδώ η έξοδος από την συγκεκριμένη συνάρτηση αν είναι πίνακας (άλλο tuple) μπορεί να πάει σε πρόσθετη συνάρτηση τύπου #x() (δεν γίνεται για τις συναρτήσεις που γυρνούν αλφαριθμητικό, πρέπει να είναι τελευταίες στη σειρά). Αντικείμενα που επιστρέφουν τιμές είναι οι λάμδα συναρτήσεις και τα αντικείμενα τύπου ομάδα αν έχει οριστεί ιδιότητα Αξία.
 

Από το αρχείο Readme:

M2000 Interpreter and Environment

Version 9.9 revision 1

1. Update the socket and the client objects. See down4 example in info.gsb.
2. New read only variable Internet$ return the public ip or 127.0.0.1 if no internet connection exist
3. New read only variable Internet return true if there is an internet connection
4. New #Eval() and #Eval$() for tuples.
5. Report statement rewrite for use proper the TAB character when use justification. Also now is faster. Use a variant of code from internal editor to find the proper point to cut the line, using a binary search. The old wwplain function exist as wwplainOLD, for information only.
6. Improved Test form (a bug fixed).
7. Many improvments and bug fixed.
8. Many examples in info.gsb also improved, and new examples added.

Δευτέρα, 7 Οκτωβρίου 2019

Version 9.9

From readme.txt

Version 9.9 active-X
1. Remove of a hard finding bug, which in some OS leave tmp files in %temp% folder. The bug was an abnormal initialization of multimedia player. This bug cause the system to hold the tmp file until the player end. This problem not happen in Windows 8, perhaps is a bug of the external lib, for specific OS.

2. Reorganize the M2000 MessageBoxet, so now we don't get any crash at save.

3. Commands LOAD, SAVE and END check a "dirty" flag to ask for saving. Also REMOVE (with no arguments) now ask before remove the last module/function.

4. Speed improved on calculations (expression evaluation).

5. List of COM object's members, return the type of parameters, and if they are IN, OUT, IN OUT, also the return type if the member return value.

6. New objects., SOCKET, DOWNLOAD, CLIENT for use TCP/IP. Info.gsb have the Down3, a module example to show how to download asynchronous three files, using the DOWNLOAD object.

7. (This break compatibility  with previous versions). Com Events in previous versions internal passed by reference. So all variables in event service function have & before. Now only for those parameters which are ByRef we need to use &. Before we use an event we can just show the stack, and leave it as is, using the Stack statement without parameters. So we can see if we have values or references, because references in M2000 are strings -they are weak references-with name, and for events they have EV at the begin).

8. New info.gsb. Best of all is the chess game (without AI) but import and export FEN strings, and we can play chess with a friend. Also we can replay the game, or move to any previous move. Also there is a Snake board game, only an automatic version (4 players played by computer).

From info.gsb, the down3 module
The example show a running module. This module create a Form, three Download objects, with events, in an array. For this example we create a two item array, and increase by one. From internal side there are two arrays, the second one has the sink objects, the objects for events. We have a thread to display an increasing value. We can move the form, without blocking the refreshing of the form.

About the items in the picture bellow
The magenta colored form, is the M2000 console. M2000 Environment redirect all graphic and text output base on a layer. Console form has 35 layers. The Back, the Layer, and Layer 1 to 32. Here we see the Back or Background with black color behind then Layer, in magenta. The Background is a Vb6 form naked from borders and headers. The Layer is a picturebox vb6 control, the same for 32 layers above (used as "hardware" sprites, or for pages). The 35 layer is the printer page, or Printer layer. Eanch user Form, is a Vb6 form with an array of  gList4 controls. The orange header is a glist4 control. All controls like DropBox, or EditBox actually have a glist4 control. under the hood.

Vb6 (the programming language used for written M2000 interpreter and environment) not allow to place controls in a form, except for expanding a arrays of controls. But a control, from an array can send events to another object, if that object has from design time defined with that capability, for any control with the same type. So a  EditBox can place a real Glist4 control, as the "any control" and handle the events and the control.triggered by a task manager. The task manager triggered from a timer from Kernel. But because we have the interpreter in one thread actually we have a switched execution. So where the switch happen/ We have to give time to system for timer to work. When we place a refresh for a form, we do this, we stop the triggering for task manager, then we perfrom the refresh, then we start the triggering, so we place the threads when we want, not every time.

When we move the user form (handling the orange header), we see the thread to slow down (the scrolling numbers), but continue to work. So the form has another "thread layer". Because interpreter execute in console form, and events from user form "travel" to code in console form, we have a switch, where the interpreter main code stop and a service event function executed, and then the main code continue. Here for the example we don't have any event service function for the form. The form is not opened as modal. When an event occur in form, internal code watch if the event serviced, and if not, excluded from firing. If the form lost the focus and then get the focus, at the activation time, the event black list, erased, and fast constructed again.

So in the picture below we have a trigger from Kenrel, events from two forms, the console form  which are served internal, and user forms where events are for M2000 code, and we have three objects which download files from internet to a directory, sending "com" events.

I found here the cAsyncSocket (which a watch for some time),  written in Visual Basic 6 by Vladimir Vissoultchev, plus some other classes which use jthat object So the cAsynSocket handle a ws2_32.dll the interface (in binary) for Windows Sockets. Here we have a dll which send events, not by using sink objects (like com objects), but in the message loop. What is message loop? Each program which have forms have one message loop, at least. So for using window socket we need to attach it to  message loop. So every cAsyncSocket make a new window, (hidden) get events from Window Sockets, watching the message loop, and generate com objects. The Download object, isn't a ecAsyncSocket, but use one, so events from DownLoad are specific for Download, and generated inside Download. So when we see the number of bytes to increased, we get a progress event from Download, where some other events come from cAsyncSocket, where some specific messages "notify" it from Window Socket system. So behind the Download we have a system in some other thread (actual thread), which get or send bytes over internet. form and to "clients". So cAsyncSocket is a client. We get the events from Download because we have made the sink object at execution time. All the other parts are connected through design time programming. The only thing to think is how the cAsyncSocket watch the message loop. This can be done by sub-classing. Here the sub-classing is different.  Not as the subclassing with EditBox and a glist4 control. For cAsyncSocket the subclassing mean to insert a function between a function call. So when A call B we can pass a C in a way to perform a cal from  A to C and then from C to B. So we inform the A caller to call C and we get the information that A actual want to call B, so we get the B address to call, before setting the A caller to call C. Before we close the thing, we have to restore the sub-classing. This is the idea. If something in C not work fast, then slow down the message loop. For M2000 interpreter there is a programming "switch" who prevents the ghosting screen, which tell us about "the program not responding".  Windows send messages and waiting to return back to check if a message loop respond. So a message has a time stamp. Using the anti ghosting state M2000 may run programs with no refreshing for long time, without problem. But here we want the 3 downloads to work, connecting Internet (other PC, in the World Net, not a Local Net), and not blocking the "actuator", which are us, where we place the three methods, one for each object, for the downloads.

So when we get the progress event, at a speed of a modern PC, the sink created by M2000 interpreter, fire the event, calling a specific function (all the com objects send events, from a specific type sink object which call a specific function give the parameters, of which object send and what, the name of event, and the parameters. At the return of this function the param list send it back, to work for by reference type variables). So the events from com objects just interrupt the main thread when happen, not when the main thread ask a "doevents", So a thread (a M2000 thread) may interrupted, very fast. Because the functions where we serve services, in M2000 are different from normal functions, to access the module's variables/functions/modules (they called using a Call Local, passing the module's name as the name of function, so a X in module is a X in function), we have to make something to ensure that parameters from the call are written in different variables, but with same name. So we declare New before the name's to read from stack of values (each call from an event has own stack of values, so the serving function change name with module name, only to look/handle entities from module.  Normal functions are closed as the modules, only local or global entities are visible. If a Module A has a local Module B, then B can't see A members, and A can't see B members.

Another thing to see here is about layers, and the split screen. On way to change split screen row, is by setting the second  parameter in CLS command. So a CLS ,5 set 6th row as the top row of the down part of screen, then scrolling part. here we set at some stages different split screen row, so the last setting leave the part with numbers.

The printing routine on Layers use text with transparent background. Except the Print Over, which erase the line before print. So we can easy use it to display information to upper part  of split screen, the static part. We have to erase before print, and that happen by  Print Over.

Print Over, Print Part and Print Under are a set of print commands, which have some properties. All of this commands restore colors, columns, print style setting. No one of them insert a new line after the call. Print Under draw a line (as underline) to current line, then insert a new line, then print anything we have as argument list. Print Over erase the line except the horizontal line which Print Under draw. Aldo Print Over set by default one column entire width, and print style 6 (proportional text, center justify). In the picture bellow we see print over three times for progress on console and three for the form. Each time we have change the one column all row, to specific columns.





In info.gsb they are these two modules - games. The Snake (auto play), and Chess for two. The first (snake) use Greek statements, the other English (M2000 has two set of commands, Greek and the English, a command has to be in one language, but we can use commands from any language anywhere in M2000).

The Snake handle the parts of games in any console configuration, here we see the cyan BACK and a print using Console as Layer


Chess is more advanced. The console now is the lines under the chess board. The chess board and the header are drawing in the BACK layer. The BACK layer can be extended to any width and height (respecting then top limits), the LAYER and the 32 layers from LAYER 1 to LAYER 32 (when used as consoles)  they have width a multiple of then base width. Also the height have rows plus line space so for proper handle we get a height smaller than total visible height. But this not happpem fro Back Layer.
For joke we can move the form by holding mouse left button on header. And each time we run the module, form a random number the program decide to change size....
Chess record each position in FEN string.We can go back to any previous move. We can replay the game, We can export the game (we can import too).


Πέμπτη, 26 Σεπτεμβρίου 2019

Chess Board Example

This example use Unicode chess characters. Look the print screen, at the background of  these characters on the board. Normaly the color inside are the same as the font, because only the line of font drawing. So to have white inside pawns, we have to print the characters in white background using a non antialliasing printing (so we get black pixels for black colored characters), and we have to use flood fil in a pixel outside the chess character to fill the square with desired color.

for each board we feed a Forsyth–Edwards Notation (FEN) a string which define a board position.



Just copy this and paste to a module a empty code block.
Cls 15
Pen 0
Form 40,32
Gradient 3,5
Def White$="PNBRQK", Black$="pnbrqk", WhiteDisp$="♙♘♗♖♕♔"
Def BlackDisp$="♟♞♝♜♛♚", empty$="12345678"
Dim emptydisp$(1 to 8)
for i=1 to 8 :emptydisp$(i)=string$(" ",i):next i
Def board$, status$, oldI
dim line$()
Double
OldI=Italic
Italic 1
Pen 14 {Report 2, "Chess Board Example"}
Italic OldI
Normal
SetBoard("rnbqkbnr/pp1ppppp/8/2p5/4P3/8/PPPP1PPP/RNBQKBNR w KQkq c6 0 2")
DrawBoard(1000, 2000, 600, 15)
SetBoard("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1")
DrawBoard(11500, 2000, 300, 15)
SetBoard("rnbqkbnr/pp1ppppp/2p5/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1")
DrawBoard(11500, 8000, 180, 15)
Push Key$
Drop
Cls
end 
Sub DrawBoard(leftmargin, topmargin, squarewidth, labelcolor)
Refresh 10000
Local a=true, z=bold : bold 0
Local l=squarewidth, k=2*l, k1=k*.85, N1=6, N=6, M=4, B=k*8, B1
Local d=0
Repeat
N=N1
N1+=.25
Until K1<size.Y("A", "Arial", N1)
topmargin-=l
leftmargin-=l
move leftmargin+l,topmargin+l
B1=(l div 300)*twipsX
step -B1,-B1
B+=B1*2
Width b1 div 2+1 {
color #666688 , 1{Polygon 0, B, 0, 0, B, -B, 0, 0, -B}
}


M=N*.65
For i=1 to 9
 d=leftmargin
 move d, topmargin
 if i<9 then
  step 0, k
  Pen labelcolor{Legend str$(9-i,""), "Arial", M,0,2}
  step 0, -k
 else
  N=M
 end if
 for j=1 to 8
  If i<9 then
   step l, l
   color  #666688,1 {fill k,k, 15}
   step  -l, -l
   \\ Last parameter is 0 for no antialliasing
   Legend mid$(line$(i),j,1), "Arial", N, 0, 2,0
   step l-twipsX
   if a then floodfill  ,,#666688 else floodfill , , #ccddff
   a~
  else
   step k, k
   pen labelcolor {
    Legend mid$(line$(i),j,1), "Arial", N, 0, 2
   }
  End If
  d+=k
  move d, topmargin
 next
 a~ : topmargin+=k
next
bold z
Refresh 60


end sub
Sub SetBoard(chessboard$)
 board$=leftpart$(chessboard$," ")
 status$=rightpart$(chessboard$," ")
 nl$={
 }
 for i=1 to 6
 board$=replace$(mid$(White$,i,1),mid$(WhiteDisp$,i,1), board$)
 board$=replace$(mid$(Black$,i,1),mid$(BlackDisp$,i,1), board$)
 next
 for j=1 to 8
 board$=replace$(str$(j,""),emptydisp$(j), board$)
 next
 line$()=piece$(board$,"/")
 dim line$(1 to 9)
 line$(9)="abcdefgh"
End Sub