Τετάρτη, 2 Δεκεμβρίου 2020

Αναθεώρηση 11, Έκδοση 10

 Σε αυτήν την αναθεώρηση διόρθωσα δυο λάθη, και έβαλα δυο αντικείμενα για χειρισμό json αρχείων. Είχα γράψει έναν parser για Json αρχεία, σε M2000, αλλά τώρα έγραψα έναν πολύ γρήγορο σε VB6, με δυο αντικείμενα, ανάλογα με τι ξεκινάει το αρχείο (πίνακας ή αντικείμενο). Αν δεν ξεκινάει με κάτι από αυτά τότε είναι η λεγόμενη json value, και για να την πάρουμε σωστά πρέπει να την περάσουμε σε πίνακα, δηλαδή να βάλουμε τα "[" και "]" και να την χειριστούμε ως το στοιχείο με το δείκτη 0.

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

Στην επόμενη αναθεώρηση, ήδη έχω κάνει την προετοιμασία, θα βάλω την δυνατότητα να χειριζόμαστε ιδιότητες COM αντικειμένων με περισσότερους από έναν δείκτη.

Σε λίγες μέρες....η επόμενη αναθεώρηση!



Τρίτη, 17 Νοεμβρίου 2020

Αναθεώρηση 9, Έκδοση 10

 Σε αυτήν την αναθεώρηση πρόσθεσα την διαφάνεια του τίτλου μιας φόρμας χρήστη. Εκτός από τη διαφάνεια μπορούμε να ορίσουμε το χρώμα των γραμμάτων του τίτλου και το χρώμα των εικονιδίων για το κλείσιμο, την επέκταση στην οθόνη (maximize), και την απόκρυψη (minimize).

Υπάρχουν παραδείγματα στο info, που προσαρμόστηκαν για να δείχνουν τις νέες δυνατότητες:

Στο List33, έχει περαστεί πίσω ένα φόντο με διαβάθμιση οριζόντια. Μπορούμε να αλλάζουμε το μέγεθος του παράθυρου, και άμεσα αναπροσαρμόσεται το φόντο και η θέση του Hello World. Το στοιχείο Λίστα (ListBox) είναι διάφανο και η μπάρα ολίσθησης είναι κρυμμένη.






Στη ΓΛΩΣΣΑ, το φόντο έχει διαβάθμιση, και έχει αλλαχθεί το χρώμα των εικονιδίων (δείτε τα τρια δεξιά και ένα στα αριστερά στο τίτλο). Επίσης έχει αλλαχθεί το χρώμα του τίτλου.  Επειδή τα στοιχεία ελέγχου παίρνουν το χρώμα από το τίτλο, αν κάναμε την αλλαγή στη αρχή, θα βλέπαμε και στο Κείμενο (EditBox) να άλλαζε το βασικό χρώμα.


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



Παράδειγμα Textonly. Εδώ υπάρχει ένα νήμα που αλλάζει το μέγεθος της μαύρης έλλειψης. Όπως βλέπουμε έχει φτάσει στο τίτλο. Παρόλο που ο τίτλος, το κείμενο (Editbox, σε διαμόρφωση που απλά βλέπουμε κείμενο) και η εισαγωγή (TextBox), δεν είναι πραγματικά διάφανα, αλλά λογικά, δηλαδή αντιγράφουν το φόντο, η αυξομείωση του μεγέθους της μαύρης έλλειψης γίνεται σαν να είναι διάφανα, επειδή η ανανέωση της φόρμας γίνεται ταυτόχρονα για όλα τα στοιχεία. Μποορύμε να γράφουμε ή να ολισθαίνουμε το κείμενο, και η αυξομοίωση θα συμβαίνει χωρίς να έχουμε "αναβοσβήματα" ή flickering (η απουσία flickering, είναι ένα από τα υπερ του στοιχείου που έχω γράψει, εξολοκλήρου, και περιέχεται και στο τίτλο, και στο κείμενο και στη γραμμή εισαγωής, και σε όλα τα στοιχεία για φόρμες της Μ2000, με αντικείμενα που κληρονομούν το βασικό αυτό αντικείμενο).



Κυριακή, 15 Νοεμβρίου 2020

A like record in C# 9.0 object in M2000

Reading https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-9, I found record type that can be emulated in M2000:

In the example bellow, we have a class Person, with 2 readonly properties (they have only the value part, the set part is omitted). A property is a group, and the definition is a syntactic sugar, which define a private variable, so for name$ the private is [name]$  (characters "[" and "]" can be used for names).

We make a synthesized property, the tuple. A group inside a group (a class make a group) can't read parent values, except we explicitly declare and only for parent some linked variables (we can link functions too, but no modules). Here we link the private members. Links are references. So the tuple (name$, last$) return the values of parent [name]$ and [last$].

We make an operator "==" for equality. In the expression person == brother, the calling to operator done to brother, so the Read other is the by value pass of person. We check to see if we have the type Person, so if we don't we get error. We can use push other.[name]$=.[name]$ and other.[last]$=.[last]$ which directly check private variables, because the reading group has the same type (Person) with current group, so the private members of group other exist also as public for this function (operator "=="). The push statement pus the boolean number to the current stack, and this stack reading from the expression evaluator (expect one value, otherwise we get error).

Info: Stack in M2000 is for values only, has nothing to do with return or process stack. A module pass the current stack to any calling module. A function (as those we make with Function {} statement, and the lambda functions) start with a new stack (and any parameter) when call it from expression. There are static functions (created at the end of the code (in any module or non static function) with Function / End Function) which use the current stack and called with @ before the name. Non static functions and modules can change code dynamically (for the next execution), static functions and subs can't change code. Also static functions and subs haven't a namespace, the have the same where they belong. So we have to use Local to make local variables. In modules and standard functions, and lambda functions, all variables are local by default to the name space which computed from the name and the order of execution. To finish this info, we can use GOTO and GOSUB inside module's boundaries (also standard functions). A Gosub call a code by  number or alphanumeric label, and expect to find a bare Return statement, using same namespace, same stack and without introducing local variables (it is just some line of code which we want to execute and we want to not repeat it).

To execute this example: Run m2000.exe, write Edit A, press enter, paste the code, press Esc and write A and press enter. You can save it using Save CSharpLike  so after that give a New or press Break key, and the give a Load CharpLike and with Ctrl+N you get the list of modules in ChsarpLike.gsb (the name of file, which you just load), and this list has one module the A.


Class Person {
      // read only
      property name$ {value}
      property last$ {value}
      // a synthesized property
      group tuple {
            value {
                  link parent [name]$ to name$
                  link parent [last]$ to last$
                  =(name$, last$)
            }
      }
      operator "==" {
            // check the type of other
            read other as Person
            push other.name$=.name$ and other.last$=.last$
      }
Class:
      // class: part. Here anything exist only at contruction
      // .[name]$ is the private variable under .name$ property
      module Person (.[name]$, .[last]$) {
      // no code here,
      // (.[name]$, .[last]$) is a syntactic sugar for statement Read .[name]$, .[last]$
      }
}
Function FirstName(name$) {
      group fake {
      // groups have no types
      // we can use type: Person if we wish to add one type manual
      // or we can put a list of type names: type: Person, Student
      private:
            [name]$=name$
      }
      =fake
}
Function One(what$, value$) {
      // no need to change value$ to  something like "{1}" in format$()
      // because a group definition executed in the same name space where belong,
      // for right expressions, so =value$ read the value$ of function One()
      // for left add a new name space:
      // the expanded name of this namespace with name fake
      // internal interperter compute the namespaces by the calling order, to be short for faster execution
      a$=format$({private: [{0}]$=value$ }, filter$(what$,"$"))
      // this is a way to pass a string as type,
      // not a class type, but in code type, if we use standard string,
      // but here isn't that case, we only pass a computed definition
      group fake type a$
      =fake
}
person=Person("Bill", "Vagner")
Print person.name$, person.last$
// export values as tuple
(first$, last$)=person.tuple
A=person.tuple
Print first$, last$, A#val$(0)=first$
sister = person with FirstName("Susan")
(first$, last$)=sister.tuple
// we can print tuple (not converted to string, Print statement make an iterator automatic and get each item)
Print first$, last$, sister.tuple
brother = person with one("name$","Paul")
(first$, last$)=brother.tuple
Print first$, last$
Print person == person
Print person == sister
Print person == brother



Παρασκευή, 13 Νοεμβρίου 2020

Revision 8, Version 10

 A bug in XMLdata fixed. Additions for Listbox, Editobox, Combo (also with combo we make menu, so this is for menu two). 

1. All lists (including EditBox) now display the part of line if exist in the bottom:



2. We can change color for vertical scroll bar:

      Method Pad, "SetBarStyle", color(50, 100, 200), 5, 15

15 is for white (0 to 15 are the standard colors, color() return a negative number for RGB)

5 is for the hatch type, and white is the hatch color. 


The cs example change colors for editbox, here are the dark colors. So here we have another statement:
        Method Pad, "SetBarStyle", #DD9033, -1
The -1 remove the hatch, so all parts of the bar has one color. The bar is normally hidden and open if we move the mouse pointer over it, or if we use the keyboard page up and page down, or  if we push a line up or down holding the left mouse button down, or if we handle the mouse wheel (is same as page up/page down). In editor page up/down done at half actual page.size). All controls are made from one control. So the title of form, the combo box and the edit box have the same type control, but the have different objects which inherits the base class, the one control.


I am thinking now for adding some controls (that belongs to environment). From the language part, some day I would make an Ast Interpreter. Also I have to make some books, for kids.

For this version (10) I have to put 3D hardware accelerated graphics, using DirectX 11. I am looking for a solution, with a nice interface, so kids may use them without hard maths. There is something interesting here: 

https://www.vbforums.com/showthread.php?889232-VB6-DirectX-11-for-VB6-1-0-Type-Library

Τετάρτη, 11 Νοεμβρίου 2020

Αναθεώρηση 7, Έκδοση 10

 Τελειοποίησα το XMLData αντικείμενο. Η βασική ιδιότητα, xml δίνει το δένδρο σαν κείμενο και παίρνει το δένδρο σαν κείμενο (διαγράφοντας το τρέχον δένδρο). Αυτό γίνεται σε κάθε κλαδί (το οποίο είναι επίσης ένα δένδρο). Μπορούμε να στήνουμε το δένδρο προγραμματιστικά με εντολές αντί να δώσουμε το κείμενο. Τώρα προστέθηκαν και εντολές για διαγραφή. Στο info προστέθηκε το xml2, που δείχνει πως βγάζουμε τα κλαδιά (με δείκτες σε αντικείμενο) σε μια λίστα, όπου τα ταξινομούμε και μετά στήνουμε γρήγορα το δένδρο, αντί να βάζουμε XMLnode, απευθείας με XMLdata.

To XMLNode είναι ένα αντικείμενο που μας δίνει το XMLdata και πάνω σε αυτό κάνουμε προσθήκες σε χαρακτηριστικά (attributes),  προσθήκη σε τιμή, και το βάζουμε σε ένα αρχικά απροετοίμαστο XMLNode του λείπει το XMLNode. Δεν μπορούμε να χειριστούμε κάτι από το XMLNode γιατί είναι κλειστό για μας. Απλά το δίνουμε στο   XMLdata και αυτό το χειρίζεται, μέχρι να το δώσουμε για "πάντα",  και έτσι να κάνουμε το XMLdata να λειτουργεί. Στην ουσία υπάρχει ένα άλλο αντικείμενο εσωτερικά στο XMLData το οποίο έχει διαφορετικό όνομα και αυτό δεν το προσεγγίζουμε άμεσα. Το XMLData εμφανίζεται σαν XMLmono τύπος, είναι ένας Adapter, όπου το αυθεντικό XMLmonoInternal απλά βρίσκεται μέσα του. Όλο το δένδρο είναι φτιαγμένο μόνο με το XMLmonoInternal, αλλά η πρόσβαση σε αυτό γίνεται με τους Adapters. Πχ όταν κάνει αναζήτηση ενός tag (ετικέτας) για να δημιουργήσει μια λίστα, εσωτερικά το XMLmonoInternal χρησιμοποιεί το αντικείμενο Collection (της VB), και το αποτέλεσμα το παίρνει το εξωτερικό αντικείμενο XMLmono, και το μεταγράφει σε αντικείμενο της Μ2000, που μπορούμε να το δουλέψουμε πιο εύκολα (σε αντικείμενο σωρό τιμών). Όταν ζητάμε ένα δείκτη για ένα δένδρο εσωτερικό του δένδρου, τότε το XMLmono φτιάχνει ένα νέο XMLmono (λέγεται και wrapper), και σε αυτό δίνει τον "κρυφό" δείκτη του XMLmonoInternal.

Δείτε πως έχει το πράγμα. Τα αντικείμενα που χειριζόμαστε στη Μ2000 είναι τριών ειδών. Το ένα είναι το Group ή Ομάδα, και λέγεται και αντικείμενο χρήστη γιατί το φτιάχνει όπως θέλει, εδώ χρησιμοποιούμε την τελεία για να δείξουμε τα μέλη της ομάδας που θα χρησιμοποιήσουμε, Το δεύτερο είναι τα αντικείμενα που παρέχει η γλώσσα για να βάζουμε στοιχεία, όπως οι πίνακες, οι δείκτες σε πίνακες (τουπλέ),, οι λίστες, οι σωροί, και άλλα. Αυτά έχουν εντολές που γράφουμε περιφραστικά, είναι ενσωματωμένα στο συντακτικό της γλώσσας. Τέλος έχουμε τα εξωτερικά, τα λεγόμενα COM. Αυτά μπορεί να είναι από το σύστημα ή ιδιωτικά. Ορισμένα αντικείμενα εσωτερικά της Μ2000 μπορούν να χρησιμοποιηθούν από άλλα προγράμματα, όπως η λίστα. Όλα αυτά τα COM αντικείμενα (και οι φόρμες και τα στοιχεία ελέγχου του GUI) τα χειριζόμαστε με τις εντολές Όρισε (Declare), ή και με την Όρισε ΜεΓεγονοτα (Declare WithEvents),   Μέθοδος (Method) και συνδέουμε μεταβλητές με ιδιότητες με την Με (With),. Επειδή αυτά γίνονται ενώ εκτελείται το περιβάλλον, δηλαδή για το περιβάλλον εκτέλεσης είναι Late Bound, η προσπέλαση στα αντικείμενα γίνεται μόνο από τις μεθόδους και τις ιδιότητες που δηλώνονται Pubic στη VB6 ή όποια άλλη γλώσσα (τα COM αντικείμενα μπορούν να γραφτούν σε διάφορες γλώσσες, στην ουσία αυτό που έχουμε είναι γλώσσα μηχανής και σύνδεση με βιβλιοθήκες).  Για να επικοινωνούν τώρα αντικείμενα και κώδικας μέσα από το περιβάλλον (τον εκτελέσιμο κώδικα), υπάρχουν οι μέθοδοι και ιδιότητες που ορίζονται ως Friend, φιλικές, δηλαδή μπορούν να χρησιμοποιηθούν μόνο από τον "ιδιοκτήτη" ή "κατασκευαστή" ενός αντικειμένου. Στην περίπτωσή εδώ από τη Μ2000. Έτσι με αυτό το επίπεδο "ασφάλειας", υπάρχει απομόνωση από το μέρος του προγράμματος σε Μ2000 και του εκτελέσιμου του περιβάλλοντος της Μ2000.

Σκοπός όλης αυτής της πολυπλοκότητας είναι να μπορεί το περιβάλλον να αντιμετωπίζει τα σφάλματα, βάζοντας ένα επιπλέον επίπεδο ελέγχου, και απομονώνοντας λειτουργίες και σε αυτές δεν αφήνει τη πρόσβαση ο χρήστης (και ενδέχεται να δημιουργήσει πρόβλημα).

Παλαιότερα η Μ2000 ήταν πιο στριφνή με τα αντικείμενα, πχ στη λίστα δεν άφηνε να βάλουμε αντικείμενα COM, όπως γίνεται από αυτήν την αναθεώρηση (βάζαμε μόνο τα στάνταρ και τις ομάδες). Τα αντικείμενα COM όταν συνδέονται με γεγονότα δεν θέλουμε να είναι μετακινήσιμα, δηάδή να είναι στατικά. Επίσης όταν έχουμε ιδιότητες μιας φόρμας δεν θέλουμε να κρατάμε δείκτη προς την φόρμα γιατί δεν θα απελευθερώσει ποτέ τη μνήμη (μέχρι να διαγραφεί και το τελευταίος δείκτης. Και εκεί η Μ2000 κάνει την δουλειά wrapper, δηλαδή έχει το mHandler, ένα αντικείμενο που χρησιμοποιεί για πολλά άλλα αντικείμενα, και είτε μεταφέρει κάποιο άλλο αντικείμενο, είτε δηλώνει με αναφορά σε συγκεκριμένη θέση μεταβλητής, όπου μπορεί να υπάρχει, ή και να αλλάξει το αντικείμενο χωρίς το mHandler να έχει θέμα, ή να χρειάζεται ενημέρωση. Έτσι όταν συνδέουμε ιδιότητες, με κάποιο αντικείμενο, αυτές δεν κρατάνε δείκτη στο αντικείμενο (άρα δεν έχουν επίπτωση στη ζωή του),  αλλά μια αναφορά εκεί που βρίσκεται ο δείκτης. Μια συνδεδεμένη ιδιότητα είναι αυτή που έχει περάσει από ένα στάδιο ανίχνευσης κωδικού ιδιότητας για δοσμένο όνομα ιδιότητας (έτσι δουλεύει το COM, μέσω της iDISPATCH διεπαφής). Κάθε φορά που πάμε να εκτελέσουμε την ιδιότητα, για διάβασμα ή για γράψιμο (ότι μας αφήνει το αντικείμενο), χρησιμοποιείται ο κωδικός άμεσα (χωρίς να γίνεται αναζήτηση). Ακόμα και στις μεθόδους που δεν συνδέουμε τμήματα και συναρτήσεις τα ονόματα των κλήσεων κρατούνται σε λίστα και άμεσα δίνουν τον αριθμό εκτέλεσης, από την δεύτερη εκτέλεση (η Μ2000 κρατάει λίστες για όλα τα αντικείμενα στη συγκεκριμένη περίοδο εκτέλεσης).

Γενικά οι γλώσσες όπως η VB6 λειτουργεί με tlb βιβλιοθήκες, τiς λεγόμενες Type Libraries. Τα αντικείμενα COM έχουν για τη διεπαφή iDispatch ενσωματωμένη βιβλιοθήκη και η Μ2000 μπορεί να την δείξει. Δείτε το παράδειγμα FS με ποιο τρόπο εμφανίζουμε στη κονσόλα της Μ2000 τις μεθόδους και τις ιδιότητες ενός αντικειμένου  COM.

Αυτά προς το παρόν.

ΓΚ





Δευτέρα, 9 Νοεμβρίου 2020

Αναθεώρηση 6, Έκδοση 10 - Διορθώσεις και Επεκτάσεις

Στην 6η αναθεώρηση, διόρθωσα τις επιπτώσεις της 5ης στο τμήμα BASEG, στο αρχείο INFO.GSB, με το οποίο έδειχνα πώς διαβάζουμε recordset απευθείας από το αντικείμενο. Τώρα δουλεύει!


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

Το πρόβλημα το βρήκα μέσω του παραδείγματος S1, στο αρχείο INFO.GSB, όπου στη τελευταία λειτουργία της επίδειξης εμφάνιζε λάθος (έχασε το Επόμενο (Next) σε ένα For Next, γιατί λογάριασε το / ως σημείωση και πέταξε τη γραμμή μαζί με το σημάδι...Επόμενο..). Τώρα το παράδειγμα λειτουργεί.

Γενικά όταν κάνω αλλαγές ελέγχω όλα τα προγράμματα στο Info αρχείο, αλλά αρκετές φορές κάνω έλεγχο σε λίγα. Τώρα έγινε στα βασικά (στα μεγάλα προγράμματα, που έχει το Info), και σε μερικά δεύτερης διαλογής, στα οποία όμως βρέθηκαν λάθη και διορθώθηκαν.

Προσθήκη

Επιπλέον σε αυτήν την αναθεώρηση έκανα προσθήκη στο εργαλείο συμπίεσης. Τώρα μπορούμε να συμπιέζουμε στη μνήμη, δηλαδή να έχουμε φτιάξει το Zip , να μην συμπιέσουμε στο δίσκο,  αλλά να το συμπιέσουμε σε στη μνήμη. Ομοίως μπορούμε από ένα Zip, από την μνήμη ή από τον δίσκο να κάνουμε εξαγωγή αρχείου στη μνήμη ή στο δίσκο. Στο πρόγραμμα JukeBox, η εικόνα έχει πια συμπιεστεί σε αρχείο zip και το αρχείο έχει γίνει κείμενο με κωδικοποίηση Base64 και έτσι συμπεριλαμβάνεται στον κώδικα. Υπάρχουν εντολές που διαβάζουν το κείμενο, το κάνουν δυαδικά δεδομένα και το δίνουν στο αντικείμενο που χειρίζεται zip αρχεία (αλλά και μνήμη που έχει ένα zip αρχείο όπως εδώ), και από αυτά εξάγεται το αρχείο της εικόνας σε άλλη μνήμη (αποσυμπιεσμένο). 

Η Μ2000 έχει την Διάρθρωση μνήμης, ένα αντικείμενο που χειρίζεται μνήμη του υπολογιστή για να έχουμε πρόσβαση σε επίπεδο διεύθυνσης μνήμης. Επίσης χρησιμοποιείται για εικόνες, ήχους, για δυαδικά αρχεία και για να φτιάχνουμε δομές τύπου C (stuctures), τις οποίες τις χρησιμοποιούμε για δυαδικά αρχεία και για να παρέχουμε δομές στο λειτουργικό σύστημα..

Δείτε το DEMO1 όπου χρησιμοποιούνται όλα τα ήδη προγραμματισμού! Είναι αυτό που φτιάχνει ένα απλό 3D γραφικό, και το περιστρέφει. Χρησιμοποιεί διάρθρωση μνήμης για να γράφει τα στοιχεία που περνάει άμεσα σε ένα αντικείμενο μαθηματικών (που έχει η Μ2000) για να γίνονται σειρές υπολογισμών πάνω σε διανύσματα τύπου τετραδόνιου (4D) . Το πρόγραμμα χρησιμοποιεί ένα παράθυρο, και νήματα για διάφορες εργασίες. Έτσι ένα νήμα υπολογίζει την νέα θέση, ένα άλλο νήμα κάνει την εμφάνιση σε τακτά διαστήματα, ένα άλλο σταματάει το πρώτο και βάζει μπροστά ένα άλλο για να βλέπουμε το γραφικό να σταματάει και να αναβοσβήνει! Επιπλέον οι γραμμές του γραφήματος είναι σε αντικείμενο, το οποίο καλούμε μια μέθοδο για να εμφανιστεί. Πριν όμως την εμφάνιση κάνουμε ταξινόμηση, για να γράψουμε πρώτα την γραμμή που είναι στο βάθος.


Στην εικόνα φαίνονται οι τρεις γραμμές (γράφονται με GDI+, με ομαλή γραμμή, χωρίς δοντάκια). Δείτε η μπλε γραμμή σχεδιάστηκε τελευταία, είναι πάνω από τις άλλες. Ο αριθμός πάνω αριστερά (μέσα στο παράθυρο) δηλώνει το φόρτο. Όσο μικρότερος είναι τόσο λιγότερος ο φόρτος του υπολογιστή. Αν κάνουμε εργασίες στον υπολογιστή ή ανοίξουμε πολλές φορές τη Μ2000 και τρέξουμε σε κάθε μία το ίδιο πρόγραμμα τότε το σύστημα αφενός θα τα μοιράσει σε επεξεργαστές και θα μοιραστεί το συνολικό τρέχον φορτίο σε όλους (θα μεγαλώνουν τα νούμερα).

Κάτω στη γραμμή αναφοράς υπάρχουν μετρητές των νημάτων, και το ρολόι. Το εικονίδιο με τις τρεις άσπρες γραμμές ανοίγει το σχετικό μενού απ΄ όπου μπορούμε να χειριστούμε το παράθυρο με τα πλήκτρα ή το ποντίκι, ακόμα και να το μετακινήσουμε με τα βελάκια (σε άλλα παράθυρα που αλλάζουν διάσταση μπορούμε να την αλλάξουμε και από αυτό το μενού). Τα μενού αυτά μπαίνουν και δεξιά. Γενικά τα παράθυρα της Μ2000 είναι πραγματικά παράθυρα, γυμνά, και τα γεμίζει η Μ2000 όπως θέλει. Πάνω δεξιά φαίνεται το "_" για ελαχιστοποίηση στη γραμμή εργασίας, και το τετράγωνο για να κλείσει το παράθυρο. Αν γράφουμε κώδικα και αυτός βγάλει πρόβλημα τότε το παράθυρο κλείνει και μας γυρνάει το σύστημα στη κονσόλα της Μ2000. Εδώ η κονσόλα έχει εξαφανιστεί, και θα επανέλθει μόλις τερματίσουμε το πρόγραμμα. Αν το πρόγραμμα το ξεκινούσαμε με διπλό κλικ (εφόσον δηλώσουμε στο λειτουργικό να ανοίγει ο τύπος αρχείου που θέλουμε με τη Μ2000) τότε δεν ανοίγει η κονσόλα αν δεν το θέλουμε και αν έτσι έχουμε "εφαρμογές" που δεν φαίνεται το περιβάλλον Μ2000 πάνω στο οποίο τρέχουν.


Για τις ημέρες της καραντίνας, ακούμε μουσική με το Jukebox της Μ2000!


ΓΚ


Σάββατο, 7 Νοεμβρίου 2020

Revision 5, Version 10

1. A fix in Volume, and some work internal, we have a new example, then Jukebox in info, for playing mp3 like a juke box. We can program by using numbers the tracks we want to play aftet the current one, we can play one or a list in a loop, using a simple interface. In this module we handle the console as window. We can move it around, and using F10 we can maximize or restore it. Except for the movement of console, all other inputs are through keyboard only.

2. I wrote an xml parser in an object (simple one), and works fine. So I made two adapters objects to handle it through the M2000 code.

3. I make an adapter object for cZipArchive, a very good class for handling zip files, using dedicated machine code for the job. ZipArchive


This is the code from XML  module (the demo in info file)

We make this xml

<?xml version="1.0" encoding="UTF16"?>

<names>

    <element Id="69">

        <codename>VB6</codename>

        <sold>2</sold>

    </element>

    <element Id="70" Nobel="yes">

        <codename>C++</codename>

        <sold>3</sold>

    </element>

    <element Id="71">

        <codename>M2000</codename>

        <sold>10</sold>

    </element>

</names>

We use a simple interface to add nodes.


form 80, 48
declare xml xmlData
With xml, "LastChild" as Child
with xml, "xml" as doc$, "beautify" as beautify
with xml, "childcount" as xml.count, "anychild" as xml.child()


print type$(xml)="XmlMono"  ' true
method xml, "PrepareNodeSimple", "xml" as ProcessInstructions
// nodes are not xmlmono types
print type$(ProcessInstructions)="XmlNode"


method xml, "PlaceAttributeToNode", ProcessInstructions, "version", "1.0"
method xml, "PlaceAttributeToNode", ProcessInstructions, "encoding", "UTF16"


// the first node we build used for the processinstructions
method xml, "PlaceProcessingInstructions", ProcessInstructions


method xml, "PrepareNode", "names" as Node
method xml, "InsertNode", Node
// so now our xml has a name "names"


// now we make a new one, pace an attribute and place it as a child
method xml, "PrepareNode", "element" as Node1
method xml, "PlaceAttributeToNode", Node1, "Id", "69"
method xml, "AppendChild", Node1
// we can get the XmlMono from that list child


Print type$(Child)="XmlMono"
// our child hasn't a node, so we have to make one and then insert to it
method xml, "PrepareNode", "codename","VB6" as Node
method Child, "AppendChild", Node
// we can append a child to this child
method xml, "PrepareNode", "sold","2" as Node1
method Child, "AppendChild", Node1 ' see we call AppendChild to Child object


with child, "tag" as child.tag$, "attr" as child.attr$(), "text" as child.text$, "xml" as child.doc$, "anychild" as child.child()
with child,"childcount" as child.count
Print child.tag$
Print child.attr$("Id")
Print child.text$
Print child.doc$
declare anychild xmldata
with anychild, "text" as anychild.text$, "tag" as anychild.tag$
    for i=0 to child.count-1
        anychild=child.child(i)
        Print anychild.tag$;"=";anychild.text$
    next


// we repeat the element here


method xml, "PrepareNode", "element" as Node1
method xml, "PlaceAttributeToNode", Node1, "Id", "70"
// we can place additional attribudes
method xml, "PlaceAttributeToNode", Node1, "Nobel", "yes"
method xml, "AppendChild", Node1
// we can get the XmlMono from that list child


Print type$(Child)="XmlMono"
// our child hasn't a node, so we have to make one and then insert to it
method xml, "PrepareNode", "codename","C++" as Node
method Child, "AppendChild", Node
// we can append a child to this child
method xml, "PrepareNode", "sold","3" as Node1
method Child, "AppendChild", Node1 ' see we call AppendChild to Child object


    for i=0 to child.count-1
        anychild=child.child(i)
        Print anychild.tag$;"=";anychild.text$
    next


// we repeat the element here
method xml, "PrepareNode", "element" as Node1
method xml, "PlaceAttributeToNode", Node1, "Id", "71"
method xml, "AppendChild", Node1
// we can get the XmlMono from that list child
Print type$(Child)="XmlMono"
// our child hasn't a node, so we have to make one and then insert to it
method xml, "PrepareNode", "codename","M2000" as Node
method Child, "AppendChild", Node
// we can append a child to this child
method xml, "PrepareNode", "sold","10" as Node1
method Child, "AppendChild", Node1 ' see we call AppendChild to Child object


    for i=0 to child.count-1
        anychild=child.child(i)
        Print anychild.tag$;"=";anychild.text$
    next


// part2
// we make same new xmlData object
declare Child1 xmlData


declare nChild xmlData
With nChild, "Attr" as nChild.Attr$()


for i=0 to xml.count-1
    nchild=xml.child(i)
    Print nChild.Attr$("Id")
next


function getnextchild(xml, &xmlmono) {
    method xml, "EndOffChilds", &xmlmono as ok
    = ok
}


// Here we get the result from LastChild, if we use AS and not Set we get the property
// but here we need the original pointer
// so when we change the pointer the connected propeties made them with With statement,
// these follows the object ponter.
// (when we use AS we connect the properties with a property of another object, so when we change that object, the other properties follow)
// (you see that in the For Next blocks after each element append to xml)
With xml, "LastChild" set Child1
with child1, "tag" as child1.tag$, "attr" as child1.attr$(), "text" as child1.text$, "xml" as child1.doc$, "anychild" as child1.child()
declare inner xmlData
with inner, "tag" as inner.tag$, "text" as inner.text$


method xml, "ResetChildPointer"
// here we pass a xmlData object and we get another
While getnextchild(xml, &child1)
    method child1, "ResetChildPointer"
    Print child1.attr$("Id"), child1.tag$,
    While getnextchild(child1, &inner)
    Print inner.tag$, inner.text$
    end while
end While


''''''''''''''''''''''aaaaa
Pen 15 {Print "Using negative beautify, we set identation to 0 for first level"}


beautify=-4
Print #-2, doc$
Print "Press a key"
Push key$: Drop
cls
Pen 15 {Print "Using positive beautify, we set identation same for all levels"}
beautify=4
Print #-2, doc$
declare L xmlData
with L, "xml" as L.doc$,"childcount" as childrens
L.doc$=doc$
Pen 15 {Print "By default beautify=0 so we get all text in a row"}
Report 3, L.doc$
Print childrens=3
child1=xml.child(2) ' 3rd
child1=child.child(1) ' 2nd


Print child1.doc$
child1.text$=str$(val( child.text$)+1, "")
Print child1.doc$
method xml, "GetListByTag", "codename" as list_in_a_stack_object
Print "Found: ";Len(list_in_a_stack_object)
For i=1 to Len(list_in_a_stack_object)
    child1=stackitem(list_in_a_stack_object, i)
    Print "codename:";child1.text$
next
// another way
one=each(list_in_a_stack_object)
while one
    child1=stackitem(one)
    Print "codename:"; child1.text$
end while


method xml, "GetListByTag", "element" as list_in_a_stack_object
one=each(list_in_a_stack_object)
with child1, "textFromChild" as child1.child.text$()
while one
    child1=stackitem(one)
    nobel$=child.attr$("Nobel")
    Print "Id="+child1.attr$("Id"), if$(nobel$=""-> "","Nobel="+nobel$)
    Print "codename:"; child1.child.text$("codename"), "sold: ";child1.child.text$("sold")
end while


declare xml nothing