63.20 What happenswhen we create a new object? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 751 63.21 Can we use the attributes by accessing the Getter and Setter methods? . . . . . . . . . . . . . . . . . 752 63.22 Why should a search of global names be made while defining the class attributes? . . . . . . . . . . 753 63.23 Why Ring doesn’t avoid the conflict between Global Variables and Class Attributes Names? . . . . . 754 63.24 Where can I write a program and execute it? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 754 63.25 How to get the file size using ftell() and fseek() functions? . . . . . . . . . . . . . . . . . . . . . . . 755 63.26 How to get the current source file path? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 755 63.27 What about predefined parameters or optional parameters in functions? . . . . . . . . . . . . . . . . 755 63.28 How to print keys or values only in List/Dictionary? . . . . . . . . . . . . . . . . . . . . . . . . . . 756 63.29 Why I get a strange result when printing nl with lists? . . . . . . . . . . . . . . . . . . . . . . . . . 756 63.30 Could you explain the output of the StrCmp() function? . . . . . . . . . . . . . . . . . . . . . . . . 757 63.31 How to use many source code files in the project? . . . . . . . . . . . . . . . . . . . . . . . . . . . . 757 63.32 Why this example use the GetChar() twice? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 758 63.33 How to use NULL and ISNULL() function? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 759 63.34 How to print lists that contains objects? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 760 63.35 How to insert an item to the first position in the list? . . . . . . . . . . . . . . . . . . . . . . . . . . 760 63.36 How to print new lines and other characters? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 761 63.37 Why we don’t use () after the qApp class name? . . . . . . . . . . . . . . . . . . . . . . . . . . . . 761 63.38 Why the window title bar is going outside the screen? . . . . . . . . . . . . . . . . . . . . . . . . . 761 63.39 How to create an array of buttons in GUI applications? . . . . . . . . . . . . . . . . . . . . . . . . . 762 63.40 How to Close a window then displaying another one? . . . . . . . . . . . . . . . . . . . . . . . . . . 763 63.41 How to create a Modal Window? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 763 63.42 How can I disable maximize button and resize window? . . . . . . . . . . . . . . . . . . . . . . . . 764 63.43 How to use SQLite using ODBC? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 765 63.44 Can I connect to dbase/harbour database? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 766 63.45 Why setClickEvent() doesn’t see the object methods directly? . . . . . . . . . . . . . . . . . . . . . 767 63.46 Why I get Calling Function without definition Error? . . . . . . . . . . . . . . . . . . . . . . . . . . 767 63.47 Can Ring work on Windows XP? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 768 63.48 How to extend RingQt and add more classes? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 768 63.49 How to add Combobox and other elements to the cells of a QTableWidget? . . . . . . . . . . . . . . 771 63.50 How to perform some manipulations on selected cells in QTableWidget? . . . . . . . . . . . . . . . 771 64 Language Reference 773 64.1 Language Keywords . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 773 64.2 Language Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 774 64.3 Compiler Errors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 775 64.4 Runtime Errors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 776 64.5 Language Grammar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 777 64.6 Virtual Machine (VM) Instructions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 779 65 Resources 786 65.1 Ring Language Website . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 786 65.2 Ring Group . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 786 65.3 Contact the Authors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 786 Index 787 xix
22.
CHAPTER ONE APPLICATIONS DEVELOPED INLITTLE HOURS Ring is a new programming language that focuses on the Natural Language Programming and Declarative Program- ming paradigms and will let you think different about programming and how to solve your problems in a better way. It’s just released in 2016.01.25! In little days we got thousands of downloads and many developers started learning and using the language. Their feedback are the secret behind the language progress and success. They said that Ring is powerful, beautiful and easy to learn, Some of them provided good examples about what can be done using Ring in little hours. They are very happy with the language productivity. 1.1 Quotes about Ring “I like Smalltalk very much but now I like Ring better!” , Gal Zsolt (Hungary) “I find the language and its syntax very natural and easy to follow.” , Bhudda (United States) “Very nice approach for a new language.” , Matth Moestl (Austria) “Very interesting! I will keep an eye on it.!” , Eslipak (Argentina) “I’d like to see some benchmarks. Otherwise, at first glance, it looks really promising.” , Alex Deva (Sweden) “Excellent” , Liju Sankar (United States) “I wish you the best with this project.” , David O’Neil (United States) “Just fantastic.” , Jose Antonio (Mexico) “This looks like it was developed by some very competent people.” , Jim Clack (United States) “The Ring programming language seems pretty interesting so far.” , Eric Johnson (United States) “Thank you for this awesome language and wonderful ready to use Qt binding.” , Martial FAESSEL “I think it’s great what he does for the community of developers and novice programming.” , Marino Esteban “Ring is just awesome. The language is so cool and fluent. I am sure it’s going to be BIG.” , Ahmed Zain “What a proud, really wish you Eng. Mahmoud Samir and Your Team moving forward ^_^ and from now , considered me a big fan of the Ring programming language.” , Zainab Mahmoud “Well guys I love this language and it appears that you have created perfect language.” , Moemen Ghulmi “Good work Mahmoud, I’ve installed ring pl, and it’s very perfect language.” , Ahmed Omar (Egypt) “Thanks for this great startup programming language. I wish you best of luck.” , Elkhouaja Khalid “Congratulations! I am very happy and I wish you Success and good luck.” , Abobasmla Hassan “Good Features of multi-use language on the Web, Mobile and Desktop.” , Abdelrhman Haider 1
23.
Ring Documentation, Release1.2 “Very interesting effort.” , Giannakakis Kostas (Greece) “I am too lazy to open comment window and write message. But in your case I must say “Perfect” Really, create new remarkable language like your Ring is really perfect job. Even create editor for your language in your language with only few rows... Even noticed in rosettacode.org ! I read your previous articles and I tried these examples a few days ago and I will continue. I love Ring. P.S.: Anders Hejlsberg, Niklaus Wirth, Bjarne Stroustrup, Ada Lovelace Hall of fame is waiting....” , Martin Nedopil (Czech Republic ) “Ring seems very attractive to me through its very easy design and the Qt bindings. I like its declarative approach and the generous documentation.” , Shalok Shalom (Austria) “Ring (and plenty of extension library + Qt) is wonderful.” , Kovacs Attila (Hungary) “Since two days I’m trying Ring and I’m really impressed, in add to power commands and easy use, it’s really very efficient and very fast. Each day I hope to find the couple of the year PWCT+RING ... Maybe for my Christmas gift!!!! HO HO HO HO Continue your fantastic job and congratulations.” , Jose Le Roux (France) “I was taking a tour around Rosettacode and have found Ring. I like the syntax a lot. It’s clean and easy to understand. It looks like a very clean BASIC dialect without sigils. I can say that this is the easiest and the most BASIC-like language I’ve ever tried.” , Tomaaz 1.2 FetchStockData Application URL : https://groups.google.com/forum/#!topic/ring-lang/-fa1U_SXSjo Author : Bert Mariani This App is written in Ring. It will fetch stock data from Yahoo and draw various types of charts. Any valid stock ticker can be entered, or selected from the drop down list - Select Symbol. It will not guarantee that you make money in the stock market. But it will visualize the history of the stock. 1.2. FetchStockData Application 2
24.
Ring Documentation, Release1.2 1.3 Fifteen Puzzle Game URL : https://github.com/CalmoSoft/CalmoSoft-Fifteen-Puzzle-Game/blob/gh-pages/CalmoSoftPuzzle.ring Author : Gal Zsolt (CalmoSoft) 1.4 TicTacToe Game URL : https://github.com/AbdelrahmanGIT/RingSamples/blob/master/src/TecTacToe.ring 1.3. Fifteen Puzzle Game 3
25.
Ring Documentation, Release1.2 Author : Abdelrahman Mohammed 1.5 Squares Puzzle Game URL : https://github.com/MajdiSobain/RingAllegro_SquaresPuzzle Author : Majdi Sobain This project is about (Squares Puzzle) popular game that I have programmed using ring language with its RingAllegro Library. The principle of this game is very known to all of us, which is moving squares to get the real full shape of the original picture. This game could be played using mouse and keyboard as well, showing a message of congratulations at the successful solving. 1.5. Squares Puzzle Game 4
26.
Ring Documentation, Release1.2 1.6 Werdy Application URL : http://werdy.info Source Code : https://github.com/magdy-ragab/werdy Author : Magdy Ragab Quran application includes reading suras, searching and bookmarking. The applcation is provided for Windows, Linux and Android. 1.7 Samples in this book The next samples are developed in little hours and we will introduce them through this book. The next screen shot for he Ring Notepad application 1.6. Werdy Application 5
27.
Ring Documentation, Release1.2 The next screen shot for the Cards Game The next screen shot for the Cards Game (Android) 1.7. Samples in this book 6
28.
Ring Documentation, Release1.2 The next screen shot from the Web Development chapter 1.7. Samples in this book 7
29.
Ring Documentation, Release1.2 The next screen shots for simple 2D Games that we will present in the Game Engine Chapter. Stars Fighter Game Flappy Bird 3000 Game Super Man 2016 Game 1.7. Samples in this book 8
30.
CHAPTER TWO INTRODUCTION Welcome to theRing programming language! The Ring is an Innovative and practical general-purpose multi-paradigm language that can be embedded in C/C++ projects, extended using C/C++ code and/or used as standalone language. The supported programming paradigms are Imperative, Procedural, Object-Oriented, Functional, Meta programming, Declarative programming using nested structures, and Natural programming. The language is portable (Windows, Linux, Mac OS X, Android, etc.) and can be used to create Console, GUI, Web, Games and Mobile applications. The language is designed to be Simple, Small, Flexible and Fast. Its Dynamic Language (Dynamic Typing and Weakly Typed) that compile the source code to byte code then execute it by the Ring Virtual Machine, which is integrated with the Ring Compiler in one program. In this chapter we are going to discuss the goals behind the language design and implementation. 2.1 Motivation In Nov. 2011, I started to think about creating a new version of the Programming Without Coding Technology (PWCT) software from scratch. I was interested in creating multi-platform edition of the software beside adding support for Web & Mobile develop- ment. Most of the PWCT source code was written in VFP and the software comes with a simple scripting language for creating the components called (RPWI). The software contains components that support code generation in pro- gramming languages like Harbour, C, Supernova & Python. What I was looking for is a programming language that can be used to build the development environment, provides multi-platform support, more productivity, better performance, can be used for components scripting & can be used for developing different kinds of applications. Instead of using a mix of programming languages, I decided to use one programming language for creating the devel- opment environment, for components scripting & for creating the applications. I looked at many programming languages like C, C++, Java, C#, Lua, PHP, Python & Ruby. I avoided using C or C++ directly because I want high-level of productivity more than the level provided by these languages, also a language behind visual programming environment for novice programmers or professionals must be easy to use & productive. 9
31.
Ring Documentation, Release1.2 Java & C# are avoided for some reason too! I wanted to use a dynamic programming language and these languages are static typing, Java is multi-platform, also C# through Mono, but the use of huge number of classes and forcing the use of Object-Orientation, using a verbose language is not right for me. I need a small language, but fast and productive, also I need better control on the Garbage Collector (GC), I need a better one that is designed for fast applications. Lua is small and fast, but it’s avoided because I need more powerful language for large applications. PHP is a Web programming language and it’s syntax is very similar to C, this leads to a language not general as I want and not simple as I need to have. Python & Ruby are more like what I need, but I need something more simple, smaller, faster & productive. Python and Ruby are Case-Sensitive, the list index start counting from 0, you have to define the function before calling it, Ruby usage of Object-Orientation and message passing is more than what I need and decrease performance, Python syntax (indentation, using self, :, pass & _) is not good for my goals. All of these languages are successful languages, and very good for their domains, but what I need is a different language that comes with new ideas and intelligent implementation (Innovative, Ready, Simple, Small, Flexible and Fast). 2.2 History In Sept. 2013 I started the design and the implementation of the Ring programming language. After 21 months of development, In May 2015 the language Compiler & Virtual Machine were ready for use! After that I spent three months testing the language again, trying to discover any bug to fix, writing better tests, by the end of August 2015, all know bugs were fixed, Writing many tests and testing automation helped a lot in getting a stable product. In September 12, 2015, most of the documentation was written. Before releasing the language I started the marketing by writing a post in Arabic language about it to my facebook profile page asking for contributors interested in the language idea after reading a short description, In the same day I got a lot of emails from developers and friends interested to contribute! The first version of the language Ring 1.0 is released on January 25, 2016 The second version of the language Ring 1.1 is released on October 6, 2016 The current version of the language Ring 1.2 is released on January 25, 2017 2.3 Features The Ring language comes with the next features Tip: The language is ready for production! • Free Open Source (MIT License) • Hybrid Implementation (Compiler + Virtual Machine) • Declarative programming on the top of Object-Oriented programming • Natural Language programming on the top of Object-Oriented programming • Syntax Flexibility (You can change the language keywords and operators) • Compact Syntax, No explicit end for statements (No ; or ENTER is required) 2.2. History 10
32.
Ring Documentation, Release1.2 • Using braces { } we can access objects and use attributes/methods as variables/functions • Transparent Implementation • Visual Implementation - Developed using Visual Programming (PWCT) • A small language (Around 200,000 lines of code) – The compiler + The Virtual Machine are 15,000 lines of C code – The other 185,000 lines of code are related to libraries! • Writen in ANSI C (The code is generated) • Optional Printing for Tokens/Grammar/Byte-Code during execution • Portable (Windows, Linux & Mac OS X) • Comments (One line & Multi-lines) • Not Case-Sensitive • Dynamic Typing • Weakly typed • Lexical Scoping (Global, Local & Object State) • Default scope for variables inside functions (Local) • Default scope for variables outside functions (global) • Garbage Collector - Automatic Memory Management (Escape Analysis and Reference Counting) • Structure Programming • Rich control structures & Operators • For in get item by reference not value, you can read/edit the item • Use exit to go outside from more than one loop • Procedures/Functions • Main Function (optional) • Call Function before the definition • Recursion • Multi-line literals • Access (read/write) string letter by index • The list index start by 1 • No keyword to end Functions/Classes/Packages • Range operator ex: 1:10 and “a”:”z” • First Class Variables, Lists, Objects and Functions • Store/Copy Lists/Objects by value (Deep Copy) • Pass Lists/Objects by reference • Native Object-Oriented Support – Encapsulation – Setter/Getter (optional) 2.3. Features 11
33.
Ring Documentation, Release1.2 – private state (optional) – Instantiation – Polymorphism – Composition – Inheritance (Single Inheritance) – Operator Overloading – Packages • Reflection and Meta-programming • Clear program structure (Statements then functions then packages & classes) • Exception Handling • Eval() to execute code during run-time • 8-bit clean, work on binary data directly • I/O commands • Math functions • String functions • List functions • File processing functions • Database support (ODBC, SQLite & MySQL) • Security Functions (OpenSSL) • Internet Functions (LibCurl) • CGI Library (Written in Ring) – HTTP Get – HTTP Post – File upload – Cookies – URL Encode – HTML Templates – HTML Special Characters – HTML Generation using Functions – HTML Generation using Classes – CRUD Example (using MVC) – Users Example (Register, Login and Check) • Extension using C/C++ (Simple API) • Embedding the language in C/C++ programs • Comes with code generator (Written in Ring) to quickly wrap C/C++ Libraries – Used to Support Allegro by creating RingAllegro 2.3. Features 12
34.
Ring Documentation, Release1.2 – Used to Support LibSDL by creating RingLibSDL – Used to Support Qt by creating RingQt • Create 2D Games for Desktop and Mobile (Using the Allegro Library or the LibSDL Library) • Comes with simple Game Engine for 2D Games • Create GUI Applications for Desktop and Mobile (Using the Qt Framework) 2.4 License The Ring Programming Language http://ring-lang.net/ Version 1.2 The MIT License (MIT) Copyright (c) Mahmoud Fayed Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documen- tation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PAR- TICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFT- WARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 2.4. License 13
35.
CHAPTER THREE LANGUAGE DESIGN In thischapter we will learn about the basic concepts behind the language design. 3.1 Why Ring? The language is simple, trying to be natural, encourage organization and comes with transparent and visual implemen- tation. It comes with compact syntax and a group of features that enable the programmer to create natural interfaces and declarative domain-specific languages in a fraction of time. It is very small, fast and comes with smart garbage collector that puts the memory under the programmer control. It supports many programming paradigms, comes with useful and practical libraries. The language is designed for productivity and developing high quality solutions that can scale. 3.2 Designed for a Clear Goal • Applications programming language. • Productivity and developing high quality solutions that can scale. • Small and fast language that can be embedded in C/C++ projects. • Simple language that can be used in education and introducing Compiler/VM concepts. • General-Purpose language that can be used for creating domain-specific libraries, frameworks and tools. • Practical language designed for creating the next version of the Programming Without Coding Technology software. 3.3 Simple Ring is a very simple language, and has a very straightforward syntax. It encourages programmers to program without boilerplate code See "Hello, World!" The Main function is optional and will be executed after the statements, and is useful for using the local scope. Func Main See "Hello, World!" 14
36.
Ring Documentation, Release1.2 Uses Dynamic Typing and Lexical scoping. No $ is required before the variable name! You can use the ‘+’ operator for string concatenation and the language is weakly typed and will convert automatically between numbers and strings based on the context. nCount = 10 # Global variable Func Main nID = 1 # Local variable See "Count = " + nCount + nl + " ID = " + nID 3.4 Trying to be natural Ring is not case-sensitive See "Enter your name ? " Give name See "Hello " + Name # Name is the same as name The list index starts from 1 aList = ["one","two","three"] See aList[1] # print one Call functions before definition one() two() three() Func one See "One" + nl Func two See "two" + nl Func three See "three" + nl The assignment operator uses Deep copy (no references in this operation) aList = ["one","two","three"] aList2 = aList aList[1] = 1 see alist[1] # print 1 see aList2[1] # print one Pass numbers and strings by value, but pass lists and objects by reference. The for in loop can update the list items. Func Main aList = [1,2,3] update(aList) see aList # print one two three Func update aList for x in aList switch x on 1 x = "one" on 2 x = "two" on 3 x = "three" off next 3.4. Trying to be natural 15
37.
Ring Documentation, Release1.2 Using Lists during definition aList = [ [1,2,3,4,5] , aList[1] , aList[1] ] see aList # print 1 2 3 4 5 1 2 3 4 5 1 2 3 4 5 Exit from more than one loop for x = 1 to 10 for y = 1 to 10 see "x=" + x + " y=" + y + nl if x = 3 and y = 5 exit 2 # exit from 2 loops ok next next 3.5 Encourage Organization The language encourage organization, Forget bad days using languages where the programmer start with function then class then function and a strange mix between things! Each source file follow the next structure • Load Files • Statements and Global Variables • Functions • Packages and Classes This enable us to use Packages, Classes and Functions without the need to use a keyword to end these components. We can write one line comments and multi-line comments The comment starts with # or // Multi-line comments are written between /* and */ /* Program Name : My first program using Ring Date : 2015.05.08 */ See "What is your name? " # print message on screen give cName # get input from the user see "Hello " + cName # say hello! // See "Bye!" 3.6 Transparent Implementation Ring comes with transparent implementation. We can know what is happening in each compiler stage and what is going on during the run-time by the Virtual Machine Example : ring helloworld.ring -tokens -rules -ic See "Hello, World!" Output 3.5. Encourage Organization 16
38.
Ring Documentation, Release1.2 ================================================================== Tokens - Generated by the Scanner ================================================================== Keyword : SEE Literal : Hello, World! EndLine ================================================================== ================================================================== Grammar Rules Used by The Parser ================================================================== Rule : Program --> {Statement} Line 1 Rule : Factor --> Literal Rule : Range --> Factor Rule : Term --> Range Rule : Arithmetic --> Term Rule : BitShift --> Arithmetic Rule : BitAnd --> BitShift Rule : BitOrXOR --> BitAnd Rule : Compare --> BitOrXOR Rule : EqualOrNot --> Compare Rule : LogicNot -> EqualOrNot Rule : Expr --> LogicNot Rule : Statement --> 'See' Expr ================================================================== ================================================================== Byte Code - Before Execution by the VM ================================================================== PC OPCode Data 1 FuncExE 2 PushC Hello, World! 3 Print 4 ReturnNull ================================================================== Hello, World! 3.7 Visual Implementation The Ring programming language is designed using the PWCT visual programming tool and you will find the visual source of the language in the folder “visualsrc” - *.ssf files and the generated source code (In the C Language) in the src folder and the include folder. The next screen shot from the ring_vm.ssf file (Generate ring_vm.c and ring_vm.h) 3.7. Visual Implementation 17
39.
Ring Documentation, Release1.2 The next screen shot from the ring_list.ssf file (Generate ring_list.c and ring_list.h) 3.8 Compact Syntax The language is not line sensitive, you don’t need to write ; after statements, also you don’t need to press ENTER or TAB, so we can write the next code See "The First Message" See " Another message in the same line! " + nl See "Enter your name?" Give Name See "Hello " + Name 3.8. Compact Syntax 18
40.
Ring Documentation, Release1.2 The next code create a class called Point contains three attributes X,Y and Z. No keywords is used to end the pack- age/class/function definition. Also, we can write the attributes names directly below the class name. Class Point X Y Z We can use classes and functions before their definition, In this example we will create new object, set the object attributes then print the object values. o1 = New point o1.x=10 o1.y=20 o1.z=30 See O1 Class Point X Y Z Instead of using the dot ‘.’ operator to access the object attributes and methods we can use braces { } to access the object, then we can use the object attributes and methods. o1 = New point { x=10 y=20 z=30 } See O1 Class Point X Y Z Now we will call a method after accessing the object using { } oPerson = new Person { Name = "Somebody" Address = "Somewhere" Phone = "0000000" Print() # here we call the Print() method } Class Person Name Address Phone Func Print See "Name :" + name + nl + "Address :" + Address + nl + "Phone : " + phone + nl When we use { } to access the object then write any attribute name, the language will check the class for any set- ter/getter methods that will be called automatically. New Number { See one # Execute GetOne() See two # Execute GetTwo() See three # Execute GetThree() } Class Number one two three Func GetOne See "Number : One" + nl return 1 Func GetTwo See "Number : Two" + nl return 2 Func GetThree See "Number : Three" + nl return 3 3.9 Define Natural Statements After the object access using { } if the class contains a method called BraceEnd() it will be executed! TimeForFun = new journey # The first surprise! TimeForFun { Hello it is me # What a beatiful programming world! } 3.9. Define Natural Statements 19
41.
Ring Documentation, Release1.2 # Our Class Class journey hello=0 it=0 is=0 me=0 func GetHello See "Hello" + nl func braceEnd See "Goodbye!" + nl We can execute code written in strings using the Eval() function cCode = "See 'Code that will be executed later!' " Eval(cCode) # execute the code to print the message We can create a list then execute code generated from that list aWords = ["hello","it","is","me"] for word in aWords cCode=word+"=0" eval(cCode) next We can read text files using the Read(cFileName) function and we can write files using the Write(cFileName,cString) function. See "Enter File Name:" Give cFileName See Read(cFileName) # Print the file content The next example presents how to create a class that defines two instructions The first instruction is : I want window The second instruction is : Window title = Expression Also keywords that can be ignored like the ‘the’ keyword New App { I want window The window title = "hello world" } Class App # Attributes for the instruction I want window i want window nIwantwindow = 0 # Attributes for the instruction Window title # Here we don't define the window attribute again title nWindowTitle = 0 # Keywords to ignore, just give them any value the=0 func geti if nIwantwindow = 0 nIwantwindow++ ok func getwant if nIwantwindow = 1 nIwantwindow++ ok func getwindow if nIwantwindow = 2 nIwantwindow= 0 see "Instruction : I want window" + nl ok 3.9. Define Natural Statements 20
42.
Ring Documentation, Release1.2 if nWindowTitle = 0 nWindowTitle++ ok func settitle cValue if nWindowTitle = 1 nWindowTitle=0 see "Instruction : Window Title = " + cValue + nl ok To complete the previous example, use read() to get the content of a file that contains I want window The window title = "hello world" Then use eval() to execute the content of that file!. Also, you can update the methods GetWindow() and SetTitle() to create Real windows using the GUI Library 3.10 Define Declarative Languages We learned how to use Natural statements to execute our code and using the same features we can use nested structures to execute our code. The next example from the Web library, generate HTML document using the Bootstrap library. No HTML code is written directly in this example, we created a similar language (just as example) Then using this declarative language that uses nested structures, we generated the HTML Document.. The idea in this example is that the GetDiv() and GetH1() methods return an object that we can access using {} and after each object access the method BraceEnd() will be executed to send the generated HTML to the parent object until we reach to the root where BraceEnd() will print the output. Load "weblib.ring" Import System.Web Func Main BootStrapWebPage() { div { classname = :container div { classname = :jumbotron H1 { text("Bootstrap Page") } } div { classname = :row for x = 1 to 3 div { classname = "col-sm-4" H3 { html("Welcome to the Ring programming language") } P { html("Using a scripting language is very fun!") } } next } 3.10. Define Declarative Languages 21
43.
Ring Documentation, Release1.2 } } The classes that power the declarative interface looks like this Class Link from ObjsBase title link Func braceend cOutput = nl+GetTabs() + "<a href='" + Link + "'> "+ Title + " </a> " + nl Class Div from ObjsBase Func braceend cOutput += nl+'<div' addattributes() AddStyle() getobjsdata() cOutput += nl+"</div>" + nl cOutput = TabMLString(cOutput) 3.11 Smart Garbage Collector Avoid memory problems :- • Invalid Memory Access • Memory leaks • Uninitialized Memory Access • Dangling pointer Rules :- • Global variables always stay in the memory, until you delete these variables using the assignment statement. • Local variables always deleted after the end of the function. • The programmer have full control on when to delete the variable from the memory using the Assignment state- ment. Example: aList = [1,2,3,4,5] aList = "nice" After the second line directly, The list [1,2,3,4,5] will be deleted from the memory and we will have a string “nice” • The programmer can call the function callgc() to force running the garbage collector. • If we have a reference to a variable (when we pass objects and lists to functions), then deleting variables will be based on reference counting, if no references everything will be deleted, but if we have a reference, the data will stay in memory. 3.11. Smart Garbage Collector 22
44.
CHAPTER FOUR WHAT IS NEWIN RING 1.2? In this chapter we will learn about the changes and new features in Ring 1.2 release. 4.1 List of changes and new features Ring 1.2 comes with many new features • New Functions • Better Functions • Better Ring Notepad • Better RingQt • Objects Library for RingQt • RingLibCurl • Better Call Command • Using NULL instead of NULLPointer() • Display Warnings Option • Better Quality 4.2 New Functions • PtrCmp() Function is a new function that compare between C pointers like the GUI objects. • PrevFileName() Function is added to return the previous active source file name. • RingVM_CFunctionsList() Function is added to return a list of functions written in C. • RingVM_FunctionsList() Function is added to return a list of functions written in Ring. • RingVM_ClassesList() Function is added to return a list of Classes. • RingVM_PackagesList() Function is added to return a list of Packages. • RingVM_MemoryList() Function is added to return a list of Memory Scopes and Variables. • RingVM_CallList() Function is added to return a list of the functions call list. • RingVM_FilesList() Function is added to return a list of the Ring Files. Example: 23
45.
Ring Documentation, Release1.2 fp = fopen("ptrcmp.ring","r") fp2 = fp fp3 = fopen("ptrcmp.ring","r") see ptrcmp(fp,fp2) + nl see ptrcmp(fp,fp3) + nl fclose(fp) fclose(fp3) Output: 1 0 Also we can compare between them using the ‘=’ operator Example: fp = fopen("ptrcmp2.ring","r") fp2 = fopen("ptrcmp2.ring","r") fp3 = fp see fp = fp2 see nl see fp = fp3 fclose(fp) fclose(fp2) Output: 0 1 Example: The next function in stdlib.ring uses the PrevFileName() to know if the file of the caller function is the main source file of the program or not. Func IsMainSourceFile if PrevFileName() = sysargv[2] return true ok return false 4.3 Better Functions The find() function is updated to support searching in lists using C pointers like GUI Objects. The type() function is updated to display the C pointers types (like the GUI Object Class Name). 4.4 Better Ring Notepad The Ring Notepad will save the current line number of opened files to be restored when we switch between files. Also Ring Notepad will ask the user to save the file if the file content is changed when the user switch between files. 4.3. Better Functions 24
46.
Ring Documentation, Release1.2 4.5 Better RingQt RingQt classes are updated to include methods to get events (The code that will be executed when an event is fired). This is necessary to enable/disable events for some time or to get the events information. For example the next code disable an event then call a method then enable the event again. cEvent = oView.oListResult.getCurrentItemChangedEvent() oView.oListResult.setCurrentItemChangedEvent("") FindValueAction() # Call Method while an event is disabled oView.oListResult.setCurrentItemChangedEvent(cEvent) Also the QAllEvents class is updated where we can set the output from the event function to be true or false using a new method added to the class called setEventOutput. Load "guilib.ring" MyApp = New qApp { win = new qWidget() { setwindowtitle("Hello World") setGeometry(100,100,370,250) lineedit1 = new qlineedit(win) { setGeometry(10,100,350,30) setinputmask("9999;_") oFilter = new qallevents(lineedit1) oFilter.setfocusoutEvent("pMove()") installeventfilter(oFilter) } lineedit2 = new qlineedit(win) { setGeometry(10,150,350,30) } show() } exec() } func pMove win.setWindowTitle("xxxx") oFilter.setEventOutput(False) 4.6 Objects Library for RingQt Ring 1.2 comes with the Objects library for RingQt applications. Instead of using global variables for windows objects and connecting events to objects using the object name, the Objects Library will manage the GUI objects and will provide a more natural API to quickly create one or many windows from the same class and the library provide a way to quickly set methods to be executed when an event is fired. Also the library provide a natural interface to quickly use the parent or the caller windows from the child or sub windows. The Objects Library is designed to be used with the MVC Design Pattern. The Objects Library is merged in RingQt so you can use it directly when you use RingQt Example : load "guilib.ring" new qApp { 4.5. Better RingQt 25
47.
Ring Documentation, Release1.2 open_window( :MainWindowController ) exec() } class MainWindowController from WindowsControllerParent oView = new MainWindowView func SubWindowAction Open_window( :SubWindowController ) Last_Window().SetParentObject(self) class MainWindowView from WindowsViewBase win = new qWidget() { SetWindowTitle("Main Window") btnSub = new qPushButton(win) { setText("Sub Window") setClickEvent( Method( :SubWindowAction ) ) } resize(400,400) } class SubWindowController from WindowsControllerParent oView = new SubWindowView func SetMainWindowTitleAction Parent().oView.win.SetWindowTitle("Message from the Sub Window") oView.win.SetWindowTitle("Click Event Done!") class SubWindowView from WindowsViewBase win = new qWidget() { SetWindowTitle("Sub Window") btnMsg = new qPushButton(win) { setText("Set Main Window Title") setClickEvent( Method( :SetMainWindowTitleAction ) ) } btnClose = new qPushButton(win) { Move(200,0) setText("Close") setClickEvent( Method( :CloseAction ) ) } resize(400,400) } 4.7 RingLibCurl The LibCurl library is used starting from Ring 1.0 for the Download() and SendEmail() functions implementation. In Ring 1.2 more functions are added to provide a powerful library (RingLibCurl) around LibCurl. Example: load "libcurl.ring" curl = curl_easy_init() cPostThis = "page=4&Number1=4&Number2=5" curl_easy_setopt(curl, CURLOPT_URL, "http://localhost/ringapp/index.ring?page=3") curl_easy_setopt(curl, CURLOPT_POSTFIELDS, cPostThis) 4.7. RingLibCurl 26
48.
Ring Documentation, Release1.2 curl_easy_perform(curl) curl_easy_cleanup(curl) 4.8 Better Call Command The Call command is updated to support calling functions from object attributes also (not only variables). For example the next code from the Stars Fighter Game cFunc = oself.keypress call cFunc(oGame,oSelf,Key_Space) Can be written in one line call oself.keypress(oGame,oSelf,Key_Space) 4.9 Using NULL instead of NULLPointer() We can pass NULL to functions instead of using NULLPointer() For example the next code from RingLibSDL SDL_RenderCopy(SDL_ren,tex,NULLPointer(),rect) Can be written as in the next line SDL_RenderCopy(SDL_ren,tex,NULL,rect) 4.10 Display Warnings Option In Ring 1.2 the Ring compiler is updated to include the Display Warnings option (-w) Example: load "stdlib.ring" load "stdlib.ring" compiling the program using the Display Warnings option will display the file duplication warning, While without that option the error will pass silent. This is a warning (not an error) because in large projects you may use the same file more than one time. For example it’s common to start each file with the next code. where the function IsMainSourceFile() is part from the stdlib.ring load "stdlib.ring" if IsMainSourceFile() // Testing ok 4.8. Better Call Command 27
49.
Ring Documentation, Release1.2 4.11 Better Quality Ring 1.2 is more stable, We discovered and fixed more bugs during Ring usage everyday in practical projects. Some functions are optimized to be faster like the SubStr() function. Also the documentation is more better. 4.11. Better Quality 28
50.
CHAPTER FIVE WHAT IS NEWIN RING 1.1? In this chapter we will learn about the changes and new features in Ring 1.1 release. 5.1 List of changes and new features Ring 1.1 comes with many new features • Better Natural Language Programming Support • Generate/Execute Ring Object Files (*.ringo) • Syntax Flexibility and different styles for I/O and Control Structures • New Functions and Changes • StdLib functions and classes written in Ring • RingLibSDL • Demo Project - Game Engine for 2D Games • RingSQLite • Better Code Generator for Extensions • Using Self.Attribute in the Class Region to define new attributes • Using This.Attribute in nested Braces inside the Class Methods • Better Documentation 5.2 Better Natural Language Programming Support Ring is an innovative language because of it’s compact syntax, smart implementation (small, transparent & visual) and it’s ability to create declarative and natural domain specific languages in a fraction of time. This release add support for calling methods when an expression is evaluated check this example: # Natural Code new program { Accept 2 numbers then print the sum } # Natural Code Implementation 29
51.
Ring Documentation, Release1.2 class program # Keywords Accept=0 numbers=0 then=0 print=0 the=0 sum=0 # Execution func braceexpreval x value = x func getnumbers for x=1 to value see "Enter Number ("+x+") :" give nNumber aNumbers + nNumber next func getsum nSUm = 0 for x in aNumbers nSum+= x next see "The Sum : " + nSum private value=0 aNumbers=[] Output: Enter Number (1) :3 Enter Number (2) :4 The Sum : 7 for more information see the “Natural Language Programming” chapter. 5.3 Generate/Execute Ring Object Files (*.ringo) This feature enable you to distribute your applications without distributing the source code. Also it makes application distribution a simple process where you get one Ring object file for the complete project (many source code files). Also using Ring object file remove the loading time required for compiling the application. Check the “command line options” chapter to know more about this feature. 5.4 Syntax Flexibility and different styles for I/O and Control Struc- tures Programmers are sensitive to the programming language syntax. Great programmers know how to work using many different styles but each programmer may have his/her favorite style. Each programming language comes with a style that you may like or not. Ring is just one of these languages, but as a response to many programmers asking for a better syntax we decided to provide more options. Also some of these features are very necessary for Natural Language Programming. Example : We have two commands to change language keywords and operators. ChangeRingOperator + plus ChangeRingKeyword see print Print 5 plus 5 5.3. Generate/Execute Ring Object Files (*.ringo) 30
52.
Ring Documentation, Release1.2 ChangeRingOperator plus + ChangeRingKeyword print see We have new styles (Optional) for Input/Output. Example : Put "What is your name? " Get cName Put "Hello " + cName Example : Load "stdlib.ring" Print("What is your name? ") # print message on screen cName=GetString() # get input from the user print("Hello #{cName}") # say hello! We have new styles (optional) for control structures. Example : While True Put " Main Menu --------- (1) Say Hello (2) About (3) Exit " Get nOption Switch nOption Case 1 Put "Enter your name : " Get name Put "Hello " + name + nl Case 2 Put "Sample : using while loop" + nl Case 3 Bye Else Put "bad option..." + nl End End Example : Load "stdlib.ring" While True { print(" Main Menu --------- (1) Say Hello (2) About (3) Exit 5.4. Syntax Flexibility and different styles for I/O and Control Structures 31
53.
Ring Documentation, Release1.2 ") nOption = GetString() switch nOption { case 1 print("Enter your name : ") name = getstring() print("Hello #{name}n") case 2 print("Sample : using switch statementn") case 3 Bye else print("bad option...n") } } Check the next chapters:- • Getting Started - Second Style • Getting Started - Third Style • Control Structures - Second Style - May looks like Lua and Ruby • Control Structures - Third Style - May looks like C (uses braces) • Syntax Flexibility Note: All of these styles are provided automatically by the compiler at the same time, It’s better to select one style for the same project (you can create your style as a mix from these styles) for example you can use Put/Get and Braces. 5.5 New Functions and Changes Changed: • get() function : changed to sysget() • sort() function : can now work on list of objects • find() function : can now work on list of objects Added: • clockspersecond() • CurrentDir() • ExeFileName() • ChDir() • ExeFolder() • varptr() • space() • nullpointer() 5.5. New Functions and Changes 32
54.
Ring Documentation, Release1.2 • object2pointer() • pointer2object() Check the next chapters • System Functions • Object Oriented Programming (OOP) • Low Level Functions 5.6 StdLib functions and classes written in Ring Ring 1.1 comes with a library called StdLib, it’s written in Ring by the help of Ring Team The library provide a useful group of new functions and classes Example: Load "stdlib.ring" Puts("Test Times()") Times ( 3 , func { see "Hello, World!" + nl } ) Example: Load "stdlib.ring" Puts("Test Map()") See Map( 1:10, func x { return x*x } ) Example: Load "stdlib.ring" Puts("Test Filter()") See Filter( 1:10 , func x { if x <= 5 return true else return false ok } ) Example: Load "stdlib.ring" See "Testing the String Class" + nl oString = new string("Hello, World!") oString.println() oString.upper().println() oString.lower().println() oString.left(5).println() oString.right(6).println() Example: Load "stdlib.ring" oList = new list ( [1,2,3] ) oList.Add(4) oList.print() Example: 5.6. StdLib functions and classes written in Ring 33
55.
Ring Documentation, Release1.2 Load "stdlib.ring" oStack = new Stack oStack.push(1) oStack.push(2) oStack.push(3) see oStack.pop() + nl Example: Load "stdlib.ring" oQueue = new Queue oQueue.add(1) oQueue.add(2) oQueue.add(3) see oQueue.remove() + nl Example: Load "stdlib.ring" ohashtable = new hashtable See "Test the hashtable Class Methods" + nl ohashtable { Add("Egypt","Cairo") Add("KSA","Riyadh") see self["Egypt"] + nl see self["KSA"] + nl see contains("Egypt") + nl see contains("USA") + nl see index("KSA") + NL print() delete(index("KSA")) see copy("*",60) + nl print() } Example: Load "stdlib.ring" otree = new tree See "Test the tree Class Methods" + nl otree { set("The first step") # set the root node value see value() + nl Add("one") Add("two") Add("three") { Add("3.1") Add("3.2") Add("3.3") see children } see children oTree.children[2] { Add("2.1") Add("2.2") Add("2.3") { Add("2.3.1") Add("2.3.2") Add("test") 5.6. StdLib functions and classes written in Ring 34
56.
Ring Documentation, Release1.2 } } oTree.children[2].children[3].children[3].set("2.3.3") } see copy("*",60) + nl oTree.print() Check the next chapters: • StdLib Functions • StdLib Classes 5.7 RingLibSDL Ring 1.0 provided RingAllegro to be able to create games using the Allegro game programming library Now Ring 1.1 provide RingLibSDL also so we can have the choice between Allegro or LibSDL Example: Load "libsdl.ring" SDL_Init(SDL_INIT_EVERYTHING) win = SDL_CreateWindow("Hello World!", 100, 100, 640, 480, SDL_WINDOW_SHOWN) SDL_Delay(2000) SDL_DestroyWindow(win) SDL_Quit() See the RingLibSDL Chapter. 5.8 Demo Project - Game Engine for 2D Games In practice we would create a game engine in a language like C/C++ to get the best performance then provide Ring classes to use the engine. But many 2D Games are simple and creating a game engine in Ring will be fast enough in many cases Also this would be a good demo project to learn about the language concepts where we build things using Object Ori- ented Programming (OOP) then access the power that we have using declarative programming using nested structures or using natural programming. In this project we selected the first way (declarative programming using nested structures) Example: Load "gameengine.ring" # Give Control to the Game Engine func main # Called by the Game Engine oGame = New Game # Create the Game Object { title = "My First Game" text { x = 10 y=50 animate = false size = 20 5.7. RingLibSDL 35
57.
Ring Documentation, Release1.2 file = "fonts/pirulen.ttf" text = "game development using ring is very fun!" color = rgb(0,0,0) # Color = black } text { x = 10 y=150 # Animation Part ====================================== animate = true # Use Animation direction = GE_DIRECTION_INCVERTICAL # Increase y point = 400 # Continue until y=400 nStep = 3 # Each time y+= 3 #====================================================== size = 20 file = "fonts/pirulen.ttf" text = "welcome to the real world!" color = rgb(0,0,255) # Color = Blue } Sound { # Play Sound file = "sound/music1.wav" # Sound File Name } } # Start the Events Loop See the “Demo Project - Game Engine for 2D Games” chapter. 5.9 RingSQLite Ring 1.0 provided support for ODBC to use any database and provided native support for MySQL. Now Ring 1.1 provide native support for SQLite database too. Example: oSQLite = sqlite_init() sqlite_open(oSQLite,"mytest.db") sql = "CREATE TABLE COMPANY(" + "ID INT PRIMARY KEY NOT NULL," + "NAME TEXT NOT NULL," + "AGE INT NOT NULL," + "ADDRESS CHAR(50)," + "SALARY REAL );" sqlite_execute(oSQLite,sql) sql = "INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) " + "VALUES (1, 'Mahmoud', 29, 'Jeddah', 20000.00 ); " + "INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) " + "VALUES (2, 'Ahmed', 27, 'Jeddah', 15000.00 ); " + "INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY)" + "VALUES (3, 'Mohammed', 31, 'Egypt', 20000.00 );" + "INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY)" + "VALUES (4, 'Ibrahim', 24, 'Egypt ', 65000.00 );" sqlite_execute(oSQLite,sql) aResult = sqlite_execute(oSQLite,"select * from COMPANY") 5.9. RingSQLite 36
58.
Ring Documentation, Release1.2 for x in aResult for t in x see t[2] + nl next next see copy("*",50) + nl for x in aResult see x["name"] + nl next sqlite_close(oSQLite) 5.10 Better Code Generator for Extensions We are using the code generator (written in Ring) every day to add new libraries to Ring. The generator is used to create RingQt and RingAllegro Also in Ring 1.1 it’s used to create RingLibSDL. more features are added like • Set/Get structure members (numbers & pointers) • Using constants • Better Generated Code See the Code Generator chapter. 5.11 Using Self.Attribute in the Class Region to define new attributes We can use Self.Attribute in the Class Region (after the class name and before any methods) to define new attributes. class Person name # Define name as attribute if it's not a global variable address phone class person2 self.name # Must Define the attribute self.address self.phone 5.12 Using This.Attribute in nested Braces inside the Class Methods We can use nested braces {} while we are inside methods to access another objects, In this case the current object scope will be changed while we are inside the brace and Self will point to the object that we access using braces {}. In this case we can use This.Attribute and This.Method() to access the object that will be created from the current class. Check the Object Oriented Programming chapter for more information. Also Check the Weight History Application in GUI Development using RingQt chapter. 5.10. Better Code Generator for Extensions 37
59.
Ring Documentation, Release1.2 5.13 Better Documentation Ring 1.1 documentation (800 pages) is better than Ring 1.0 documentation (340 pages) Many chapters are added for providing better information about the language like • Language Reference • Scope Rules • FAQ And more! 5.13. Better Documentation 38
60.
CHAPTER SIX BUILDING FROM SOURCECODE The Ring programming language is a free open source product (MIT License). You can build Ring using CMake or using Scripts (Batch Files or Shell Scripts). The next steps explains building using scripts. 6.1 Building using Microsoft Windows Get the source code git clone http://github.com/ring-lang/ring.git Build Ring (Compiler/VM) cd ring/src buildvccomplete.bat Generate RingAllegro Source Code and Build cd ../extensions/ringallegro gencode.bat buildvc.bat Generate RingLibCurl Source Code and Build cd ../extensions/ringcurl gencode.bat buildvc.bat Install Qt 5.5 : https://download.qt.io/archive/qt/5.5/5.5.1/ Generate RingQt Source Code and Build cd ../ringqt gencode.bat buildmingw32.bat To be able to call ring from any folder cd ../../bin install.bat Add Ring/bin to System path 39
61.
Ring Documentation, Release1.2 Hit "windows key". Type "Edit the System environment variables" Select "Advanced" tab. Click on "Enviroment Variables..." Double click on "Path" Add at the end the new path separated by semicolon. ;C:RingBin Run Ring Notepad cd applications/rnote ring rnote.ring 6.2 Building using Ubuntu Linux Get the source code git clone http://github.com/ring-lang/ring.git Install Libraries cd ring/src ./installdep.sh Build Ring (Compiler/VM) sudo ./buildgcccomplete.sh Generate RingAllegro Source Code and Build cd ../extensions/ringallegro ./gencode.sh ./buildgcc.sh Generate RingLibCurl Source Code and Build cd ../extensions/ringcurl ./gencode.sh ./buildgcc.sh Generate RingQt Source Code and Build cd ../ringqt ./gencode.sh ./buildgcc.sh To be able to call ring from any folder cd ../../bin sudo ./install.sh Run Ring Notepad cd applications/rnote sudo ring rnote.ring 6.2. Building using Ubuntu Linux 40
62.
Ring Documentation, Release1.2 6.3 Building using MacOS X Get the source code git clone http://github.com/ring-lang/ring.git Install homebrew (follow the directions on homebrew’s homepage). Install Libraries brew install unixodbc mysql-connector-c allegro openssl homebrew/versions/qt55 brew link --force qt55 Build Ring (Compiler/VM) cd ring/src ./buildclangcomplete.sh Generate RingAllegro Source Code and Build cd ../extensions/ringallegro ./gencode.sh ./buildclang.sh Generate RingLibCurl Source Code and Build cd ../extensions/ringcurl ./gencode.sh ./buildclang.sh Generate RingQt Source Code and Build cd ../ringqt ./gencode.sh ./buildclang.sh To be able to call ring from any folder cd ../../bin sudo ./install.sh Run Ring Notepad cd applications/rnote sudo ring rnote.ring 6.4 Building using CMake Install libraries (MySQL Client, OpenSSL, LibCurl, Allegro 5 and Qt 5.5) cmake . make 6.3. Building using MacOS X 41
63.
CHAPTER SEVEN HOW TO CONTRIBUTE? Ringis a free-open source project, Everyone is welcome to contribute to Ring. Project Home : https://github.com/ring-lang/ring You can help in many parts in the project • Documentation • Testing • Samples • Applications • Editors Support • Libraries in Ring • Extensions in C/C++ • Compiler and Virtual Machine (VM) • Ideas and suggestions 7.1 Special thanks to contributors Throughout the creation of this project, Ring relied heavily on contributions from experts along with college students. Their input was invaluable, and we want to take a moment to thank them and recognize them for all of their hard work. Ring Team: http://ring-lang.sf.net/team.html 7.2 Documentation You can modify anything in the documentation, by updating the text files (*.txt) in this folder : https://github.com/ring- lang/ring/tree/master/docs/source The documentation is created using Sphinx : http://www.sphinx-doc.org/en/stable/ 7.3 Testing You can write new tests in this folder https://github.com/ring-lang/ring/tree/master/tests/scripts 42
64.
Ring Documentation, Release1.2 7.4 Samples You can add new samples to this folder https://github.com/ring-lang/ring/tree/master/samples/other 7.5 Applications You can add new applications to this folder https://github.com/ring-lang/ring/tree/master/applications 7.6 Editors Support You can help in supporting Ring in different code editors Check the next folder https://github.com/ring-lang/ring/tree/master/editor 7.7 Libraries in Ring You can update and add libraries to this folder https://github.com/ring-lang/ring/tree/master/ringlibs 7.8 Extensions in C/C++ You can add and update extensions in this folder https://github.com/ring-lang/ring/tree/master/extensions 7.9 Compiler and Virtual Machine (VM) • Source Code (C Language) : https://github.com/ring-lang/ring/tree/master/src • Visual Source (PWCT) : https://github.com/ring-lang/ring/tree/master/visualsrc 7.10 Ideas and suggestions You can share your ideas, suggestions and questions in this group https://groups.google.com/forum/#!forum/ring-lang 7.4. Samples 43
65.
CHAPTER EIGHT GETTING STARTED -FIRST STYLE 8.1 Hello World The next program prints the Hello World message on the screen (std-out). see "Hello World" 8.2 Run the program to run the program, save the code in a file, for example : hello.ring then from the command line or terminal, run it using the ring interpreter ring hello.ring 8.3 Not Case-Sensitive Since the Ring language is not case-sensitive, the same program can be written in different styles Tip: It’s better to select one style and use it in all of the program source code SEE "Hello World" See "Hello World" 8.4 Multi-Line literals Using Ring we can write multi-line literal, see the next example See " Hello Welcome to the Ring programming language How are you? " Also you can use the nl constant to insert new line and you can use the + operator to concatenate strings 44
66.
Ring Documentation, Release1.2 Note: nl value means a new line and the actual codes that represent a newline is different between operating systems See "Hello" + nl + "Welcome to the Ring programming language" + nl + "How are you?" 8.5 Getting Input You can get the input from the user using the give command See "What is your name? " Give cName See "Hello " + cName 8.6 No Explicit End For Statements You don’t need to use ‘;’ or press ENTER to separate statements. The previous program can be written in one line. See "What is your name? " give cName see "Hello " + cName 8.7 Writing Comments We can write one line comments and multi-line comments The comment starts with # or // Multi-lines comments are written between /* and */ /* Program Name : My first program using Ring Date : 2016.09.09 Author : Mahmoud Fayed */ See "What is your name? " # print message on screen give cName # get input from the user see "Hello " + cName # say hello! // See "Bye!" Note: Using // to comment a lines of code is just a code style. 8.5. Getting Input 45
67.
CHAPTER NINE GETTING STARTED -SECOND STYLE 9.1 Hello World The next program prints the Hello World message on the screen (std-out). put "Hello World" 9.2 Run the program to run the program, save the code in a file, for example : hello.ring then from the command line or terminal, run it using the ring interpreter ring hello.ring 9.3 Not Case-Sensitive Since the Ring language is not case-sensitive, the same program can be written in different styles Tip: It’s better to select one style and use it in all of the program source code PUT "Hello World" Put "Hello World" 9.4 Multi-Line literals Using Ring we can write multi-line literal, see the next example Put " Hello Welcome to the Ring programming language How are you? " Also you can use the nl constant to insert new line and you can use the + operator to concatenate strings 46
68.
Ring Documentation, Release1.2 Note: nl value means a new line and the actual codes that represent a newline is different between operating systems Put "Hello" + nl + "Welcome to the Ring programming language" + nl + "How are you?" 9.5 Getting Input You can get the input from the user using the get command Put "What is your name? " Get cName Put "Hello " + cName 9.6 No Explicit End For Statements You don’t need to use ‘;’ or press ENTER to separate statements. The previous program can be written in one line. Put "What is your name? " get cName put "Hello " + cName 9.7 Writing Comments We can write one line comments and multi-line comments The comment starts with # or // Multi-lines comments are written between /* and */ /* Program Name : My first program using Ring Date : 2016.09.09 Author : Mahmoud Fayed */ Put "What is your name? " # print message on screen get cName # get input from the user put "Hello " + cName # say hello! // Put "Bye!" Note: Using // to comment a lines of code is just a code style. 9.5. Getting Input 47
69.
CHAPTER TEN GETTING STARTED -THIRD STYLE 10.1 Hello World The next program prints the Hello World message on the screen (std-out). load "stdlib.ring" print("Hello World") 10.2 Run the program to run the program, save the code in a file, for example : hello.ring then from the command line or terminal, run it using the ring interpreter ring hello.ring 10.3 Not Case-Sensitive Since the Ring language is not case-sensitive, the same program can be written in different styles Tip: It’s better to select one style and use it in all of the program source code LOAD "stdlib.ring" PRINT("Hello World") Load "stdlib.ring" Print("Hello World") 10.4 Multi-Line literals Using Ring we can write multi-line literal, see the next example Load "stdlib.ring" Print(" Hello Welcome to the Ring programming language How are you? 48
70.
Ring Documentation, Release1.2 ") Also you can use the n to insert new line and you can use #{variable_name} to insert variables values. Load "stdlib.ring" Print( "HellonWelcome to the Ring programming languagenHow are you?") 10.5 Getting Input You can get the input from the user using the getstring() function Load "stdlib.ring" Print("What is your name? ") cName = GetString() Print("Hello #{cName}") 10.6 No Explicit End For Statements You don’t need to use ‘;’ or press ENTER to separate statements. The previous program can be written in one line. Load "stdlib.ring" Print("What is your name? ") cName=getstring() print("Hello #{cName}") 10.7 Writing Comments We can write one line comments and multi-line comments The comment starts with # or // Multi-lines comments are written between /* and */ /* Program Name : My first program using Ring Date : 2016.09.09 Author : Mahmoud Fayed */ Load "stdlib.ring" Print("What is your name? ") # print message on screen cName=GetString() # get input from the user print("Hello #{cName}") # say hello! // print("Bye!") Note: Using // to comment a lines of code is just a code style. 10.5. Getting Input 49
71.
CHAPTER ELEVEN USING RING NOTEPAD Inthis chapter we will learn about using Ring Notepad to write and execute Ring programs quickly Ring Notepad is just a simple application developed using the Ring language. 11.1 Ring Notepad - Main Window When we run the Ring Notepad we get three dockable windows • Project Files Window : where we can select and open any ring file (*.ring) quickly. • Source Code Window : Where we write the source code. • Web Browser Window : Where we read the documentation or quickly open any website. 11.2 Creating and running your first Console Application At first we will type the source code 50
72.
Ring Documentation, Release1.2 See "Hello, World!" As in the next image Then we will click on the “Save” button from the toolbar (or press CTRL+S) Determine the source code file name and location. For example type : hello This will create a new source code file called : hello.ring 11.2. Creating and running your first Console Application 51
73.
Ring Documentation, Release1.2 To run the program click on “Debug (Run then wait!)” button from the toolbar The next screen shot present the application during the runtime Press Enter to continue and return to the Ring Notepad. 11.2. Creating and running your first Console Application 52
74.
Ring Documentation, Release1.2 11.3 Creating and running your first GUI/Mobile Application To learn how to create GUI applications using Ring check the “Desktop and Mobile development using RingQt” chapter. Source Code: Load "guilib.ring" New qApp { new qWidget() { resize(400,400) setWindowTitle("Hello, World!") show() } exec() } In Ring notepad we have a special button to run GUI applications without displaying the console window. 11.3. Creating and running your first GUI/Mobile Application 53
75.
Ring Documentation, Release1.2 The next screen shot present the application during the runtime 11.4 Creating and running your first Web Application To learn how support Ring in your web server and how to create web applications using Ring check the “Web Devel- opment (CGI Library)” chapter. Note: You need to support the Ring language in your web server to be able to run the next example. Source Code: 11.4. Creating and running your first Web Application 54
76.
Ring Documentation, Release1.2 #!b:ringbinring.exe -cgi load "weblib.ring" Import System.Web new page { text("Hello, World!") } We can run the application in any web browser or in the browser that are embedded in Ring Notepad. 11.5 Creating and running your first Desktop/Mobile Game To learn about creating 2D Games using Ring check the “Demo Project - Game Engine for 2D Games” chapter. Source Code: Load "gameengine.ring" func main oGame = New Game { title = "My First Game" sprite { type = GE_TYPE_PLAYER x=400 y=400 width=100 height=100 file = "images/player.png" transparent = true Animate=false 11.5. Creating and running your first Desktop/Mobile Game 55
77.
Ring Documentation, Release1.2 Move=true Scaled=true } } We can run the application as any GUI application. 11.5. Creating and running your first Desktop/Mobile Game 56
78.
CHAPTER TWELVE USING OTHER CODEEDITORS In the Ring/Editor folder you will find extensions for the next editors • Notepad++ • Geany • Atom • Sublime Text 2 • Visual Studio IDE 12.1 Using Notepad++ Folder : ring/editor/notepad_plus_plus • Open Notepad++ • Open the “Language” menu • Select “Define your language...” • Click “Import...” • select Ring.xml • Select “OK” on the “Import successful” dialog and close the “User Defined Language” dialog/panel • You may need to restart notepad++ 57
79.
Ring Documentation, Release1.2 12.2 Using Geany Folder : ring/editor/geany • Run Geany editor • Click on “Tools -> configuration files -> filetypes_extensions.conf” menu • Add this line “Ring=*.ring;” without quotes after [Extensions] • In unbuntu copy file “filetypes.Ring.conf” to folder “/home/USERNAME/filetypes.Ring.conf” • You can run your files by pressing F5 button 12.2. Using Geany 58
80.
Ring Documentation, Release1.2 12.3 Using Atom Folder : ring/editor/atom Just Copy the folder atom-language-ring to the next path “C:Users{UserName}.atomPackages” 12.3. Using Atom 59
81.
Ring Documentation, Release1.2 12.4 Using Sublime Text 2 Folder : ring/editor/sublime text 2 In the folder Sublime_Text_2 you will find the next three files 1 - ring.json-tmlanguage 2 - ring.sublime-build 3 - ring.tmlanguage Just Copy the files to the next path “C:Users{UserName}AppDataRoamingSublime Text 2PackagesUser” The file ring.sublime-build includes the next line “cmd”: [”B:ringbinring.exe”,”$file”], You can modify it according to the ring.exe path in your machine 12.4. Using Sublime Text 2 60
82.
Ring Documentation, Release1.2 12.5 Using Visual Studio IDE Folder : ring/editor/visualstudio Check the ReadMe file for installation instructions. 12.5. Using Visual Studio IDE 61
83.
CHAPTER THIRTEEN VARIABLES To create anew variable, you just need to determine the variable name & value. The value will determine the variable type and you can change the value to switch between the types using the same variable name. Syntax: <Variable Name> = <Value> Tip: The operator ‘=’ is used here as an Assignment operator and the same operator can be used in conditions, but for testing equality of expressions. Note: The Variable will contains the real value (not a reference). This means that once you change the variable value, the old value will be removed from memory (even if the variable contains a list or object). 13.1 Dynamic Typing Ring is a dynamic programming language that uses Dynamic Typing. x = "Hello" # x is a string see x + nl x = 5 # x is a number (int) see x + nl x = 1.2 # x is a number (double) see x + nl x = [1,2,3,4] # x is a list see x # print list items x = date() # x is a string contains date see x + nl x = time() # x is a string contains time see x + nl x = true # x is a number (logical value = 1) see x + nl x = false # x is a number (logical value = 0) see x + nl 13.2 Deep Copy We can use the assignment operator ‘=’ to copy variables. We can do that to copy values like strings & numbers. Also, we can copy complete lists & objects. The assignment operator will do a complete duplication for us. This operation called Deep Copy 62
84.
Ring Documentation, Release1.2 list = [1,2,3,"four","five"] list2 = list list = [] See list # print the first list - no items to print See "********" + nl See list2 # print the second list - contains 5 items 13.3 Weakly Typed Ring is a weakly typed language, this means that the language can automatically convert between data types (like string & numbers) when that conversion make sense. Rules: <NUMBER> + <STRING> --> <NUMBER> <STRING> + <NUMBER> --> <STRING> Note: The same operator ‘+’ can be used as an arithmetic operator or for string concatenation. Example: x = 10 # x is a number y = "20" # y is a string sum = x + y # sum is a number (y will be converted to a number) Msg = "Sum = " + sum # Msg is a string (sum will be converted to a string) see Msg + nl 13.3. Weakly Typed 63
85.
CHAPTER FOURTEEN OPERATORS In this chapterwe will introduce the operators provided by the Ring programming langauge. 14.1 Arithmetic Operators The next table presents all of the arithmetic operators provided by the Ring language. Assume variable X=50 and variable Y=10 then: Operator Description Example Result + Add x+y 60 - Subtract x-y 40 * Multiplies x*y 500 / Divide x/y 5 % Modulus x%y 0 ++ Increment x++ 51 - - Decrement x- - 49 14.2 Relational Operators The next table presents all of the relational operators provided by the Ring language. Assume variable X=50 and variable Y=10 then: Operator Description Example Result = Equal x = y False != Not Equal x != y True > Greater than x > y True < Less than x < y False >= Greater or Equal x >= y True <= Less than or Equal x <= y False 14.3 Logical Operators The next table presents all of the logical operators provided by the Ring language. Assume variable X=True and variable Y=False then: Operator Description Example Result and Logical AND x and y False or Logical OR x or y True not Logical Not not x False 64
86.
Ring Documentation, Release1.2 14.4 Bitwise Operators The next table presents all of the bitwise operators provided by the Ring language. Assume variable X=8 and variable Y=2 then: Operator Description Example Result & Binary AND x & y 0 | Binary OR x | y 10 ^ Binary XOR x ^ y 10 ~ Binary Ones Complement ~x -9 << Binary Left Shift x << y 32 >> Binary Right Shift x >> y 2 14.5 Assignment Operators The next table presents all of the assignment operators provided by the Ring language. Assume variable X=8 then: Operator Description Example Result = Assignment x = 10 x=10 += Add AND assignment x += 5 x=13 -= Subtract AND assignment x -= 3 x=5 *= Multiply AND assignment x *= 2 x=16 /= Divide AND assignment x /= 3 x=2.67 %= Modulus AND assignment x %= 2 x=0 <<= Left shift AND assignment x <<= 2 x=32 >>= Right shift AND assignment x >>= 2 x=2 &= Bitwise AND assignment x &= 4 x=0 |= Bitwise OR and assignment x |= 3 x=11 ^= Bitwise XOR and assignment x ^= 4 x=12 14.6 Misc Operators Operator Description :literal using : before identifier mean literal Start:End create list contains items from start to end [list items] define list items list[index] access list item obj.name using the dot operator to access object members (attributes/methods). obj {stmts} execute statements with direct access to object attributes & methods func(para,...) call function using parameters separated by comma 14.7 Operators Precedence The next table present operators from higher precedence (Evaluated first) to lower precedence. 14.4. Bitwise Operators 65
87.
Ring Documentation, Release1.2 Operator . [] () {} - ~ :Literal [list items] ++ - - Start:End * / % + - << >> & | ^ < > <= >= = != not and or Assignment = += -= *= /= %=>>= <<= &= ^= |= Example: See 3+5*4 # prints 23 14.7. Operators Precedence 66
88.
CHAPTER FIFTEEN CONTROL STRUCTURES -FIRST STYLE In this chapter we are going to learn about the control structures provided by the Ring programming language. 15.1 Branching • If Statement Syntax: if Expression Block of statements but Expression Block of statements else Block of statements ok Example: see " Main Menu --------- (1) Say Hello (2) About (3) Exit " give nOption if nOption = 1 see "Enter your name : " give name see "Hello " + name + nl but nOption = 2 see "Sample : using if statement" + nl but nOption = 3 bye else see "bad option..." + nl ok • Switch Statement Syntax: switch Expression on Expression Block of statements other Block of statements off 67
89.
Ring Documentation, Release1.2 Example: See " Main Menu --------- (1) Say Hello (2) About (3) Exit " Give nOption Switch nOption On 1 See "Enter your name : " Give name See "Hello " + name + nl On 2 See "Sample : using switch statement" + nl On 3 Bye Other See "bad option..." + nl Off 15.2 Looping • While Loop Syntax: while Expression Block of statements end Example: While True See " Main Menu --------- (1) Say Hello (2) About (3) Exit " Give nOption Switch nOption On 1 See "Enter your name : " Give name See "Hello " + name + nl On 2 See "Sample : using while loop" + nl On 3 Bye Other See "bad option..." + nl Off End • For Loop Syntax: 15.2. Looping 68
90.
Ring Documentation, Release1.2 for identifier=expression to expression [step expression] Block of statements next Example: # print numbers from 1 to 10 for x = 1 to 10 see x + nl next Example: # Dynamic loop See "Start : " give nStart See "End : " give nEnd See "Step : " give nStep For x = nStart to nEnd Step nStep see x + nl Next Example: # print even numbers from 0 to 10 for x = 0 to 10 step 2 see x + nl next Example: # print even numbers from 10 to 0 for x = 10 to 0 step -2 see x + nl next • For in Loop Syntax: for identifier in List/String [step expression] Block of statements next Example: aList = 1:10 # create list contains numbers from 1 to 10 for x in aList see x + nl next # print numbers from 1 to 10 15.3 Using The Step option with For in We can use the Step option with For in to skip number of items in each iteration Example: aList = 1:10 # create list contains numbers from 1 to 10 # print odd items inside the list for x in aList step 2 see x + nl next 15.3. Using The Step option with For in 69
91.
Ring Documentation, Release1.2 15.4 Using For in to modify lists When we use (For in) we get items by reference. This means that we can read/edit items inside the loop. Example: aList = 1:5 # create list contains numbers from 1 to 5 # replace list numbers with strings for x in aList switch x on 1 x = "one" on 2 x = "two" on 3 x = "three" on 4 x = "four" on 5 x = "five" off next see aList # print the list items 15.5 Do Again Loop Syntax: do Block of statements again expression Example: x = 1 do see x + nl x++ again x <= 10 15.6 Exit Command Used to go outside one or more of loops. Syntax: exit [expression] # inside loop Example: for x = 1 to 10 see x + nl if x = 5 exit ok next 15.4. Using For in to modify lists 70
92.
Ring Documentation, Release1.2 15.7 Exit from two loops The next example presents how to use the exit command to exit from two loops in one jump. Example: for x = 1 to 10 for y = 1 to 10 see "x=" + x + " y=" + y + nl if x = 3 and y = 5 exit 2 # exit from 2 loops ok next next • Loop Command Used to jump to the next iteration in the loop. Syntax: loop [expression] # inside loop Example: for x = 1 to 10 if x = 3 see "Number Three" + nl loop ok see x + nl next 15.8 Exit/Loop inside sub functions While we are inside a loop, we can call a function then use the exit and/or loop command inside that function and the command will work on the outer loop. Example: # print numbers from 1 to 10 except number 5. for x = 1 to 10 ignore(x,5) see x + nl next func ignore x,y if x = y loop ok 15.9 Short-circuit evaluation The logical operators and/or follow the short-circuit evaluation. 15.7. Exit from two loops 71
93.
Ring Documentation, Release1.2 If the first argument of the AND operator is zero, then there is no need to evaluate the second argument and the result will be zero. If the first argument of the OR operator is one, then there is no need to evaluate the second argument and the result will be one. Example: /* output ** nice ** nice ** great */ x = 0 y = 10 if (x = 0 and nice()) and (y = 10 and nice()) see "great" + nl ok func nice see "nice" + nl return 1 Example: # No output x = 0 y = 10 if (x = 1 and nice()) and (y = 10 and nice()) see "great" + nl ok func nice see "nice" + nl return 1 Example: /* output ** nice ** great */ x = 0 y = 10 if (x = 0 and nice()) or (y = 10 and nice()) see "great" + nl ok func nice see "nice" + nl return 1 15.10 Comments about evaluation • True, False, nl & NULL are variables defined by the language • True = 1 • False = 0 • nl = new line • NULL = empty string = “” 15.10. Comments about evaluation 72
94.
Ring Documentation, Release1.2 • Everything evaluates to true except 0 (False). Example: # output = message from the if statement if 5 # 5 evaluates to true because it's not zero (0). see "message from the if statement" + nl ok 15.10. Comments about evaluation 73
95.
CHAPTER SIXTEEN CONTROL STRUCTURES -SECOND STYLE In this chapter we are going to learn about the second style of control structures provided by the Ring programming language. 16.1 Branching • If Statement Syntax: if Expression Block of statements elseif Expression Block of statements else Block of statements end Example: put " Main Menu --------- (1) Say Hello (2) About (3) Exit " get nOption if nOption = 1 put "Enter your name : " get name put "Hello " + name + nl elseif nOption = 2 put "Sample : using if statement" + nl elseif nOption = 3 bye else put "bad option..." + nl end • Switch Statement Syntax: switch Expression case Expression Block of statements else Block of statements end 74
96.
Ring Documentation, Release1.2 Example: Put " Main Menu --------- (1) Say Hello (2) About (3) Exit " Get nOption Switch nOption Case 1 Put "Enter your name : " Get name Put "Hello " + name + nl Case 2 Put "Sample : using switch statement" + nl Case 3 Bye Else Put "bad option..." + nl End 16.2 Looping • While Loop Syntax: while Expression Block of statements end Example: While True Put " Main Menu --------- (1) Say Hello (2) About (3) Exit " Get nOption Switch nOption Case 1 Put "Enter your name : " Get name Put "Hello " + name + nl Case 2 Put "Sample : using while loop" + nl Case 3 Bye Else Put "bad option..." + nl End End • For Loop Syntax: 16.2. Looping 75
97.
Ring Documentation, Release1.2 for identifier=expression to expression [step expression] Block of statements end Example: # print numbers from 1 to 10 for x = 1 to 10 put x + nl end Example: # Dynamic loop Put "Start : " get nStart Put "End : " get nEnd Put "Step : " get nStep For x = nStart to nEnd Step nStep Put x + nl End Example: # print even numbers from 0 to 10 for x = 0 to 10 step 2 Put x + nl end Example: # print even numbers from 10 to 0 for x = 10 to 0 step -2 put x + nl end • For in Loop Syntax: for identifier in List/String [step expression] Block of statements end Example: aList = 1:10 # create list contains numbers from 1 to 10 for x in aList put x + nl end # print numbers from 1 to 10 16.3 Exceptions try Block of statements catch Block of statements end 16.3. Exceptions 76
98.
CHAPTER SEVENTEEN CONTROL STRUCTURES -THIRD STYLE In this chapter we are going to learn about the third style of control structures provided by the Ring programming language. 17.1 Branching • If Statement Syntax: if Expression { Block of statements elseif Expression Block of statements else Block of statements } Example: Load "stdlib.ring" print(" Main Menu --------- (1) Say Hello (2) About (3) Exit ") nOption = getnumber() if nOption = 1 { print("Enter your name : ") name = getstring() print("Hello #{name}n") elseif nOption = 2 print("Sample : using if statementn") elseif nOption = 3 bye else print("bad option...n") } 77
99.
Ring Documentation, Release1.2 • Switch Statement Syntax: switch Expression { case Expression Block of statements else Block of statements } Example: Load "stdlib.ring" print(" Main Menu --------- (1) Say Hello (2) About (3) Exit ") nOption = GetString() switch nOption { case 1 print("Enter your name : ") name = getstring() print("Hello #{name}n") case 2 print("Sample : using switch statementn") case 3 Bye else print("bad option...n") } 17.2 Looping • While Loop Syntax: while Expression { Block of statements } Example: Load "stdlib.ring" While True { print(" Main Menu --------- 17.2. Looping 78
100.
Ring Documentation, Release1.2 (1) Say Hello (2) About (3) Exit ") nOption = GetString() switch nOption { case 1 print("Enter your name : ") name = getstring() print("Hello #{name}n") case 2 print("Sample : using switch statementn") case 3 Bye else print("bad option...n") } } • For Loop Syntax: for identifier=expression to expression [step expression] { Block of statements } Example: # print numbers from 1 to 10 load "stdlib.ring" for x = 1 to 10 { print("#{x}n") } Example: load "stdlib.ring" # Dynamic loop print("Start : ") nStart = getnumber() print("End : ") nEnd = getnumber() print("Step : ") nStep = getnumber() for x = nStart to nEnd step nStep { print("#{x}n") } Example: load "stdlib.ring" # print even numbers from 0 to 10 for x = 0 to 10 step 2 { print("#{x}n") } 17.2. Looping 79
101.
Ring Documentation, Release1.2 Example: load "stdlib.ring" # print even numbers from 10 to 0 for x = 10 to 0 step -2 { print("#{x}n") } • For in Loop Syntax: for identifier in List/String [step expression] { Block of statements } Example: load "stdlib.ring" aList = 1:10 # create list contains numbers from 1 to 10 for x in aList { print("#{x}n") } # print numbers from 1 to 10 Example: load "stdlib.ring" aList = 1:10 # create list contains numbers from 1 to 10 # print odd items inside the list for x in aList step 2 { print("#{x}n") } When we use (For in) we get items by reference. This means that we can read/edit items inside the loop. Example: load "stdlib.ring" aList = 1:5 # create list contains numbers from 1 to 5 # replace list numbers with strings for x in aList { switch x { case 1 x = "one" case 2 x = "two" case 3 x = "three" case 4 x = "four" case 5 x = "five" } } print(aList) # print the list items 17.3 Exceptions 17.3. Exceptions 80
CHAPTER EIGHTEEN GETTING INPUT We canget input from the keyboard using • The Give Command • The GetChar() Function • The Input() Function 18.1 Give Command Syntax: Give VariableName Example: See "Enter the first number : " Give nNum1 See "Enter the second number : " Give nNum2 See "Sum : " + ( 0 + nNum1 + nNum2 ) Output: Enter the first number : 3 Enter the second number : 4 Sum : 7 18.2 GetChar() Function We can get one character from the standard input using the GetChar() function Syntax: GetChar() ---> Character Example: While True See " Main Menu (1) Say Hello (2) Exit " Option = GetChar() 82
104.
Ring Documentation, Release1.2 GetChar() GetChar() # End of line # the previous two lines can be replaced with the next line # Give Option if Option = 1 see "Enter your name : " give cName see "Hello " + cName else bye ok End 18.3 Input() Function We can get input from the keyboard using the Input() function Syntax: Input(nCount) ---> string The function will wait until nCount characters (at least) are read Example: See "Enter message (30 characters) : " cMsg = input(30) See "Message : " + cMsg 18.3. Input() Function 83
105.
CHAPTER NINETEEN FUNCTIONS In this chapterwe are going to learn about the next topics :- • Define functions • Call functions • Declare parameters • Send parameters • Main Function • Variables Scope • Return Value • Recursion 19.1 Define Functions To define new function Syntax: func <function_name> [parameters] Block of statements Note: No keyword is required to end the function definition. Example: func hello see "Hello from function" + nl 19.2 Call Functions To call function without parameters, we type the function name then () Tip: We can call the function before the function definition and the function code. Example: 84
106.
Ring Documentation, Release1.2 hello() func hello see "Hello from function" + nl Example: first() second() func first see "message from the first function" + nl func second see "message from the second function" + nl 19.3 Declare parameters To declare the function parameters, after the function name type the list of parameters as a group of identifiers separated by comma. Example: func sum x,y see x+y+nl 19.4 Send Parameters To send parameters to function, type the parameters inside () after the function name Syntax: funcname(parameters) Example: /* output ** 8 ** 3000 */ sum(3,5) sum(1000,2000) func sum x,y see x+y+nl 19.5 Main Function Using the Ring programming language, the Main Function is optional, when it’s defined, it will be executed after the end of other statements. if no other statements comes alone, the main function will be the first entry point Example: 19.3. Declare parameters 85
107.
Ring Documentation, Release1.2 # this program will print the hello world message first then execute the main function See "Hello World!" + nl func main see "Message from the main function" + nl 19.6 Variables Scope The Ring programming language uses lexical scoping to determine the scope of a variable. Variables defined inside functions (including function parameters) are local variables. Variables defined outside func- tions (before any function) are global variables. Inside any function we can access the variables defined inside this function beside the global variables. Example: # the program will print numbers from 10 to 1 x = 10 # x is a global variable. func main for t = 1 to 10 # t is a local variable mycounter() # call function next func mycounter see x + nl # print the global variable value x-- # decrement Note: Using the main function before the for loop declare the t variable as a local variable, It’s recommended to use the main functions instead of typing the instructions directly to set the scope of the new variables to local. 19.7 Return Value The function can return a value using the Return command. Syntax: Return [Expression] Tip: the Expression after the return command is optional and we can use the return command to end the function execution without returning any value. Note: if the function doesn’t return explicit value, it will return NULL (empty string = “” ). Example: 19.6. Variables Scope 86
108.
Ring Documentation, Release1.2 if novalue() = NULL See "the function doesn't return a value" + nl ok func novalue 19.8 Recursion The Ring programming language support Recursion and the function can call itself using different parameters. Example: see fact(5) # output = 120 func fact x if x = 1 return 1 else return x * fact(x-1) ok 19.8. Recursion 87
109.
CHAPTER TWENTY PROGRAM STRUCTURE In thischapter we will learn about using many source code files in the same project. 20.1 Source Code File Sections Each source code file may contains the next sections (in the same order). Source Code File Sections Load Files Statements and Global Variables Functions Packages and Classes The application maybe one or more of files. 20.2 Using Many Source Code Files To include another source file in the project, just use the load command. Syntax: Load "filename.ring" Note: The Load command is executed directly by the compiler in the parsing stage Tip: if you don’t know the file name until the runtime, or you need to use functions to get the file path, just use eval(). Example: # File : Start.ring Load "sub.ring" sayhello("Mahmoud") # File : sub.ring func sayhello cName see "Hello " + cName + nl 88
110.
CHAPTER TWENTYONE LISTS In this chapterwe are going to learn how to deal with lists. 21.1 Create Lists We can create new lists by defining the list items inside square bracts. Example: aList = [1,2,3,4,5] Also we can create new lists using the : operator Example: aList = 1:5 aList2 = "a":"z" Example: aList = 5:1 aList2 = "z":"a" Also we can create lists using the list() function Syntax: list = list(size) Example aList = list(10) # aList contains 10 items Note: the list index start from 1 21.2 Add Items To add new items to the list, we can use the Add() function. Syntax: Add(List,Item) 89
111.
Ring Documentation, Release1.2 Example: aList = ["one","two"] add(aList,"three") see aList Also we can do that using the + operator. Syntax: List + item Example: aList = 1:10 # create list contains numbers from 1 to 10 aList + 11 # add number 11 to the list see aList # print the list 21.3 Get List Size We can get the list size using the len() function Syntax: Len(List) Example: aList = 1:20 see len(aList) # print 20 21.4 Delete Item From List To delete an item from the list, we can use the del() function Syntax: del(list,index) Example: aList = ["one","two","other","three"] Del(aList,3) # delete item number three see aList # print one two three 21.5 Get List Item To get an item from the list, we uses the next syntax List[Index] Example: aList = ["Cairo","Riyadh"] see "Egypt : " + aList[1] + nl + "KSA : " + aList[2] + nl 21.3. Get List Size 90
112.
Ring Documentation, Release1.2 21.6 Set List Item To set the value of an item inside the list, we can use the next syntax List[Index] = Expression Example: aList = list(3) # create list contains three items aList[1] = "one" aList[2] = "two" aList[3] = "three" see aList 21.7 Search To find an item inside the list we can use the find() function Syntax: Find(List,ItemValue) ---> Item Index Find(List,ItemValue,nColumn) ---> Search in nColumn, returns the Item Index Find(List,ItemValue,nColumn,cAttribute) ---> Item Index Example: aList = ["one","two","three","four","five"] see find(aList,"three") # print 3 Example: mylist = [["one",1], ["two",2], ["three",3]] see find(mylist,"two",1) + nl # print 2 see find(mylist,2,2) + nl # print 2 Also we can use the binarysearch() function to search in sorted list. Syntax: BinarySearch(List,ItemValue) ---> Item Index BinarySearch(List,ItemValue,nColumn) ---> Search in nColumn, returns the Item Index Example: aList = ["one","two","three","four","five"] aList = sort(aList) see binarysearch(aList,"three") Output: five four one three two 4 21.6. Set List Item 91
113.
Ring Documentation, Release1.2 21.8 Sort We can sort the list using the sort() function. Syntax: Sort(List) ---> Sorted List Sort(List,nColumn) ---> Sorted List based on nColumn Sort(List,nColumn,cAttribute) ---> Sorted List based on Object Attribute Example: aList = [10,12,3,5,31,15] aList = sort(aList) see aList # print 3 5 10 12 15 31 We can sort list of strings Example: mylist = ["mahmoud","samir","ahmed","ibrahim","mohammed"] see mylist # print list before sorting mylist = sort(mylist) # sort list see "list after sort"+nl see mylist # print ahmed ibrahim mahmoud mohammed samir We can sort a list based on a specific column. Example: aList = [ ["mahmoud",15000] , ["ahmed", 14000 ] , ["samir", 16000 ] , ["mohammed", 12000 ] , ["ibrahim",11000 ] ] aList2 = sort(aList,1) see aList2 Output: ahmed 14000 ibrahim 11000 mahmoud 15000 mohammed 12000 samir 16000 21.9 Reverse We can reverse a list using the reverse() function. Syntax: 21.8. Sort 92
114.
Ring Documentation, Release1.2 Reverse(List) ---> Reversed List Example: aList = [10,20,30,40,50] aList = reverse(aList) see aList # print 50 40 30 20 10 21.10 Insert Items To insert an item in the list we can use the insert() function. Syntax: Insert(List,Index,Item) The inserted item will be AFTER the Index Example: aList = ["A","B","D","E"] insert(aList,2,"C") # Inserts AFTER Index 2, "C" into Position 3 see aList # print A B C D E 21.11 Nested Lists The list may contain other lists Example: aList = [ 1 , [10,20,30] , 5 , [100,1000,5000] ] aList2 = [ "one","two", [3,4], [20,30], ["three", "four", "five",[100,200,300] ] ] see aList[2] # print 10 20 30 see aList[4][3] + nl # print 5000 see aList2[5][2] + nl # print four see aList2[5][4][3] # print 300 21.12 Copy Lists We can copy lists (including nested lists) using the Assignment operator. Example: 21.10. Insert Items 93
115.
Ring Documentation, Release1.2 aList = [ "one","two", [3,4], [20,30], ["three", "four", "five",[100,200,300] ] ] aList2 = aList # Copy aList to aList2 aList2[5] = "other" # modify item number five see aList2[5] + nl # print other see aList[5] # print three four five 100 200 300 21.13 First-class lists Lists are first-class citizens where we can store lists in variables, pass lists to functions, and return lists from functions. Example: aList = duplicate( [1,2,3,4,5] ) see aList[10] + nl # print 5 see mylist() # print 10 20 30 40 50 func duplicate list nMax = len(list) for x = 1 to nMax list + list[x] next return list func mylist return [10,20,30,40,50] 21.14 Using Lists during definition We can use the list items while we are defining the list for the first time. Example: aList = [ [1,2,3,4,5] , aList[1] , aList[1] ] see aList # print 1 2 3 4 5 1 2 3 4 5 1 2 3 4 5 21.15 Passing Lists to Functions Lists are passed to functions by reference, This means that the called function will work on the same list and can modify it. Example: func main aList = [1,2,3,4,5] # create list, local in function main 21.13. First-class lists 94
116.
Ring Documentation, Release1.2 myfunc(aList) # call function, pass list by reference see aList # print 1 2 3 4 5 6 7 8 9 10 func myfunc list list + [6,7,8,9,10] 21.16 Access List Items by String Index Instead of using numbers to determine the item index when we get item value or set item value, We can access items using string index if the item is a list contains two items and the first item is a string. Example: aList = [ ["one",1] , ["two",2] , ["three",3] ] see aList["one"] + nl + aList["two"] + nl + aList["three"] # print 1 2 3 This type of lists can be defined in a better syntax using the : and = operators. Example: aList = [ :one = 1 , :two = 2 , :three = 3 ] see aList["one"] + nl + aList["two"] + nl + aList["three"] + nl # print 1 2 3 see aList[1] # print one 1 Tip: using : before identifier (one word) means literal Note: using = inside list definition create a list of two items where the first item is the left side and the second item is the right side. We can add new items to the list using the string index Example: aList = [] aList["Egypt"] = "Cairo" aList["KSA"] = "Riyadh" see aList["Egypt"] + nl + # print Cairo aList["KSA"] + nl # print Riyadh 21.17 Passing Parameters Using List This type of lists is very good for passing parameters to functions Where the order of parameters will not be important (we can change the order). Also some parameters maybe optional. Example: 21.16. Access List Items by String Index 95
CHAPTER TWENTYTWO STRINGS In this chapterwe are going to learn about strings creation and manipulation. 22.1 String Literals Syntax: cStr = "This is a string" cStr2 = 'Another string' cStr3 = :JustAnotherString cStr4 = `Yet "another" 'string' ! ` 22.2 Get String Length We can get the string length (letters count inside a string) using the len() function Syntax: len(string) ---> string length Example: cStr = "How are you?" see cStr + nl see "String size : " + len(cStr) + nl 22.3 Convert Letters Case Syntax: lower(string) ---> convert string letters to lower case upper(string) ---> convert string letters to UPPER case Example: cStr = "Welcome To The Ring Programming Language" see cStr + nl + upper(cStr) + nl + lower(cStr) 97
119.
Ring Documentation, Release1.2 22.4 Access String Letters We can access a letter inside a string by the letter index Syntax: string[index] ---> get string letter string[index] = letter # set string letter Example: # print user name letter by letter (each letter in new line) See "Hello, Enter your name : " give cName for x = 1 to len(cName) see nl + cName[x] next We can use for in to get string letters. Example: # print user name letter by letter (each letter in new line) See "Hello, Enter your name : " give cName for x in cName see nl + x next We can modify the string letters Example: # convert the first letter to UPPER case See "Enter your name : " give cName cName[1] = upper(cName[1]) see "Hello " + cName 22.5 Left() Function We can get a specified number of characters from a string using the Left() function. The starting position is 1. Syntax: Left(string,count) Example: see left("Hello World!",5) # print Hello 22.6 Right() Function We can get a specified number of characters from a string using the Right() function. 22.4. Access String Letters 98
120.
Ring Documentation, Release1.2 The starting position is the last character on the right. Syntax: Right(string,count) Example: see Right("Hello World!",6) # print World! 22.7 Trim() Function We can remove all leading and trailing spaces from a string using the Trim() function. Syntax: trim(string) Example: cMsg = " Welcome " see trim(cMsg) # print Welcome 22.8 Copy() Function We can duplicate a string more than one time using the copy() function. Syntax: copy(string,nCount) ---> string replicated nCount times Example see copy("***hello***",3) # print ***hello******hello******hello*** 22.9 Lines() Function We can count the number of lines inside a string using the Lines() function. Syntax: lines(string) ---> Number of lines inside the string Example: cStr = "Hello How are you? are you fine?" see lines(cStr) # print 3 22.7. Trim() Function 99
121.
Ring Documentation, Release1.2 22.10 Substr() Function We can work on sub strings inside a string using the substr() function. Using Substr() we can • Find substring • Get substring from position to end • Get Number of characters from position • Transform Substring To Another Substring 22.11 Find substring Syntax: substr(string,substring) ---> the starting position of substring in string Example: cStr = "Welcome to the Ring programming language" see substr(cStr,"Ring") # print 16 22.12 Get substring from position to end Syntax: substr(string,position) ---> Get substring starting from position to end Example: cStr = "Welcome to the Ring programming language" nPos = substr(cStr,"Ring") # nPos = 16 see substr(cStr,nPos) # print Ring programming language 22.13 Get Number of Characters From Position Syntax: substr(string,position,count) ---> Get characters starting from position Example: cStr = "Welcome to the Ring programming language" nPos = substr(cStr,"Ring") # nPos = 16 see substr(cStr,nPos,4) # print Ring 22.14 Transform Substring To Another Substring Syntax: 22.10. Substr() Function 100
122.
Ring Documentation, Release1.2 substr(string,substring,newsubstring) ---> Transformed string (Match case) substr(string,substring,newsubstring,1) ---> Transformed string (Ignore case) Example: cStr = "Welcome to the New programming language" see substr(cStr,"New","Ring") + nl # print Welcome to the Ring programming language see substr(cStr,"new","Ring",1)+ nl # print Welcome to the Ring programming language 22.15 strcmp() Function We can compare between two strings using the strcmp() function. Syntax: strcmp(cString1,cString2) ---> value = 0 if cString1 = cString2 value < 0 if cString1 < cString2 value > 0 if cString1 > cString2 Example: see strcmp("hello","hello") + nl + strcmp("abc","bcd") + nl + strcmp("bcd","abc") + nl Output: 0 -1 1 22.16 str2list() and list2str() Functions We can convert string lines to list items using the str2list() function. Also we can convert the list to a string using list2str() function. Syntax: str2list(string) ---> list contains the string lines list2str(list) ---> string contains the list items Example: /* output: ** Items : 4 ** Item : Hello ** Item : How are you ? ** Item : are you fine ? ** Item : ok ** list2Str result = Hello ** How are you ? ** are you fine ? ** ok ** Done */ 22.15. strcmp() Function 101
123.
Ring Documentation, Release1.2 mystr = "Hello How are you ? are you fine ? ok" mylist = str2list(mystr) see "Items : " + len(mylist) + nl for x in mylist see "Item : " + x + nl next newstr = list2str(mylist) see "list2Str result = " + newstr if mystr = newstr see nl + "Done" else see nl + "Error!" ok 22.16. str2list() and list2str() Functions 102
124.
CHAPTER TWENTYTHREE DATE AND TIME Inthis chapter we are going to learn about the date and time functions. 23.1 Clock() Function Syntax: Clock() ---> The number of clock ticks from program start Example: See "Calculate performance" + nl t1 = clock() for x = 1 to 1000000 next see clock() - t1 23.2 ClocksPerSecond() Function Return how many clocks in one second Syntax: clockspersecond() ---> Number of clocks in one second Example: # Wait 1 second t = clock() while clock() - t <= clockspersecond() end 23.3 Time() Function We can get the system time using the Time() function. Example: See "Time : " + time() 103
125.
Ring Documentation, Release1.2 23.4 Date() Function We can get the date using the Date() function. Syntax: Date() ---> String represent the date "dd/mm/yyyy" Example: See "Date : " + date() # Date : 24/05/2015 23.5 TimeList() Function We can print the date and the time information using the TimeList() function. Syntax: TimeList() ---> List contains the time and date information. The next table presents the list items index value 1 abbreviated weekday name 2 full weekday name 3 abbreviated month name 4 full month name 5 Date & Time 6 Day of the month 7 Hour (24) 8 Hour (12) 9 Day of the year 10 Month of the year 11 Minutes after hour 12 AM or PM 13 Seconds after the hour 14 Week of the year (sun-sat) 15 day of the week 16 date 17 time 18 year of the century 19 year 20 time zone 21 percent sign Example: /* Output: ** Sun abbreviated weekday name ** Sunday full weekday name ** May abbreviated month name ** May full month name ** 05/24/15 09:58:38 Date & Time ** 24 Day of the month ** 09 Hour (24) 23.4. Date() Function 104
126.
Ring Documentation, Release1.2 ** 09 Hour (12) ** 144 Day of the year ** 05 Month of the year ** 58 Minutes after hour ** AM AM or PM ** 38 Seconds after the hour ** 21 Week of the year (sun-sat) ** 0 day of the week ** 05/24/15 date ** 09:58:38 time ** 15 year of the century ** 2015 year ** Arab Standard Time time zone ** % percent sign */ See TimeList() Example: See "Day Name : " + TimeList()[2] # Sunday Example: See "Month Name : " + TimeList()[4] # May 23.6 AddDays() Function Syntax: AddDays(cDate,nDays) ---> Date from cDate and after nDays Example: cDate = date() see cDate + nl # 24/05/2015 cDate = adddays(cDate,10) see cDate + nl # 03/06/2015 23.7 DiffDays() Function Syntax: DiffDays(cDate1,cDate2) ---> number of days (Date1 - Date2) Example: cDate1 = date() see cDate1 + nl # 24/05/2015 cDate2 = adddays(cDate1,10) see cDate2 + nl # 03/06/2015 see "DiffDays = " + diffdays(cDate1,cDate2) + nl # -10 see "DiffDays = " + diffdays(cDate2,cDate1) + nl # 10 23.6. AddDays() Function 105
127.
CHAPTER TWENTYFOUR CHECK DATA TYPEAND CONVERSION In this chapter we are going to learn about the functions that can be used for • Checking Data Type • Checking Character • Conversion 24.1 Check Data Type The next functions can be used to check the data type • isstring() • isnumber() • islist() • type() • isnull() 24.2 IsString() Function Using the IsString() function we can know if the value is a string or not Syntax: IsString(value) ---> 1 if the value is a string or 0 if not Example: see isstring(5) + nl + # print 0 isstring("hello") + nl # print 1 24.3 IsNumber() Function Using the IsNumber() function we can know if the value is a number or not Syntax: 106
128.
Ring Documentation, Release1.2 IsNumber(value) ---> 1 if the value is a number or 0 if not Example: see isnumber(5) + nl + # print 1 isnumber("hello") + nl # print 0 24.4 IsList() Function Using the IsList() function we can know if the value is a list or not Syntax: IsList(value) ---> 1 if the value is a list or 0 if not Example: see islist(5) + nl + # print 0 islist("hello") + nl + # print 0 islist([1,3,5]) # print 1 24.5 Type() Function We can know the type of a value using the Type() Function. Syntax: Type(value) ---> The Type as String Example: see Type(5) + nl + # print NUMBER Type("hello") + nl + # print STRING Type([1,3,5]) # print LIST 24.6 IsNULL() Function We can check the value to know if it’s null or not using the IsNULL() function Syntax: IsNULL(value) ---> 1 if the value is NULL or 0 if not Example: see isnull(5) + nl + # print 0 isnull("hello") + nl + # print 0 isnull([1,3,5]) + nl + # print 0 isnull("") + nl + # print 1 isnull("NULL") # print 1 24.4. IsList() Function 107
129.
Ring Documentation, Release1.2 24.7 Check Character The next functions can be used to check character • isalnum() • isalpha() • iscntrl() • isdigit() • isgraph() • islower() • isprint() • ispunct() • isspace() • isupper() • isxdigit() 24.8 IsAlNum() Function We can test a character or a string using the IsAlNum() Function Syntax: IsAlNum(value) ---> 1 if the value is digit/letter or 0 if not Example: see isalnum("Hello") + nl + # print 1 isalnum("123456") + nl + # print 1 isalnum("ABCabc123") + nl + # print 1 isalnum("How are you") # print 0 because of spaces 24.9 IsAlpha() Function We can test a character or a string using the IsAlpha() Function Syntax: IsAlpha(value) ---> 1 if the value is a letter or 0 if not Example: see isalpha("Hello") + nl + # print 1 isalpha("123456") + nl + # print 0 isalpha("ABCabc123") + nl + # print 0 isalpha("How are you") # print 0 24.7. Check Character 108
130.
Ring Documentation, Release1.2 24.10 IsCntrl() Function We can test a character or a string using the IsCntrl() Function Syntax: IsCntrl(value) ---> 1 if the value is a control character (no printing position) or 0 if not Example: See iscntrl("hello") + nl + # print 0 iscntrl(nl) # print 1 24.11 IsDigit() Function We can test a character or a string using the IsDigit() Function Syntax: IsDigit(value) ---> 1 if the value is a digit or 0 if not Example: see isdigit("0123456789") + nl + # print 1 isdigit("0123a") # print 0 24.12 IsGraph() Function We can test a character or a string using the IsGraph() Function Syntax: IsGraph(value) ---> 1 if the value can be printed (Except space) or 0 if not Example: see isgraph("abcdef") + nl + # print 1 isgraph("abc def") # print 0 24.13 IsLower() Function We can test a character or a string using the IsLower() Function Syntax: IsLower(value) ---> 1 if the value is lowercase letter or 0 if not Example: see islower("abcDEF") + nl + # print 0 islower("ghi") # print 1 24.10. IsCntrl() Function 109
131.
Ring Documentation, Release1.2 24.14 IsPrint() Function We can test a character or a string using the IsPrint() Function Syntax: IsPrint(value) ---> 1 if the value occupies a printing position or 0 if not Example: see isprint("Hello") + nl + # print 1 isprint("Nice to see you") + nl + # print 1 isprint(nl) # print 0 24.15 IsPunct() Function We can test a character or a string using the IsPunct() Function Syntax: IsPunct(value) ---> 1 if the value is a punctuation character or 0 if not Example: see ispunct("hello") + nl + # print 0 ispunct(",") # print 1 24.16 IsSpace() Function We can test a character or a string using the IsSpace() Function Syntax: IsSpace(value) ---> 1 if the value is a white-space or 0 if not Example: see isspace(" ") + nl + # print 1 isspace("test") # print 0 24.17 IsUpper() Function We can test a character or a string using the IsUpper() Function Syntax: IsUpper(value) ---> 1 if the value is an uppercase alphabetic letter or 0 if not Example: see isupper("welcome") + nl + # print 0 isupper("WELCOME") # print 1 24.14. IsPrint() Function 110
132.
Ring Documentation, Release1.2 24.18 IsXdigit() Function We can test a character or a string using the IsXdigit() Function Syntax: IsXdigit(value) ---> 1 if the value is a hexdecimal digit character or 0 if not Example: see isxdigit("0123456789abcdef") + nl + # print 1 isxdigit("123z") # print 0 24.19 Conversion The next functions can be used for conversion • number() • string() • ascii() • char() • hex() • dec() • str2hex() • hex2str() 24.20 Number() Function We can convert strings to numbers using the Number() function or the + operator. Syntax: Number(string) ---> Number 0 + string ---> Number Example: see number("5") + 5 + nl # print 10 see 0 + "10" + 2 # print 12 24.21 String() Function We can convert numbers to strings using the String() function or the + operator. Syntax: String(number) ---> String "" + number ---> String 24.18. IsXdigit() Function 111
133.
Ring Documentation, Release1.2 Example: see string(5) + 5 + nl # print 55 see "" + 10 + 2 # print 102 24.22 Ascii() Function We can get the ASCII code for a letter using the Ascii() function Syntax: Ascii(character) ---> ASCII Code Example: See ascii("m") + nl + # print 109 ascii("M") # print 77 24.23 Char() Function We can convert the ASCII code to character using the Char() function. Syntax: Char(ASCII Code) ---> character Example: See char(109) + nl + # print m char(77) # print M 24.24 Hex() Function We can convert decimal to hexadecimal using the Hex() function. Syntax: Hex(decimal) ---> hexadecimal Example: See hex(10) + nl + # print a hex(200) # print c8 24.25 Dec() Function We can convert hexadecimal to decimal using the Dec() function Syntax: Dec(hexadecimal) ---> decimal 24.22. Ascii() Function 112
134.
Ring Documentation, Release1.2 Example: See dec("a") + nl + # print 10 dec("c8") # print 200 24.26 Str2hex() Function We can convert string characters to hexadecimal characters using the Str2hex() function. Syntax: Str2hex(string) ---> hexadecimal string Example: See str2hex("hello") # print 68656c6c6f 24.27 Hex2str() Function We can convert hexadecimal characters to string using the Hex2str() function Syntax: Hex2Str(Hexadecimal string) ---> string Example: See hex2str("68656c6c6f") # print hello 24.26. Str2hex() Function 113
135.
CHAPTER TWENTYFIVE MATHEMATICAL FUNCTIONS In thischapter we are going to learn about the mathematical functions 25.1 List of functions The Ring programming language comes with the next mathematical functions Function Description sin(x) Returns the sine of an angle of x radians cos(x) Returns the cosine of an angle of x radians tan(x) Returns the tangent of an angle of x radians asin(x) Returns the principal value of the arc sine of x, expressed in radians acos(x) Returns the principal value of the arc cosine of x, expressed in radians atan(x) Returns the principal value of the arc tangent of x, expressed in radians atan2(y,x) Returns the principal arc tangent of y/x, in the interval [-pi,+pi] radians sinh(x) Returns the hyperbolic sine of x radians cosh(x) Returns the hyperbolic cosine of x radians tanh(x) Returns the hyperbolic tangent of x radians exp(x) Returns the value of e raised to the xth power log(x) Returns the natural logarithm of x log10(x) Returns the common logarithm (base-10 logarithm) of x ceil(x) Returns the smallest integer value greater than or equal to x floor(x) Returns the largest integer value less than or equal to x fabs(x) Returns the absolute value of x. pow(x,y) Returns x raised to the power of y sqrt(x) Returns the square root of x random(x) Returns a random number in the range [0,x] unsigned(n,n,c) Perform operation using unsigned numbers decimals(n) Determine the decimals digits after the point in float/double numbers 25.2 Example See "Mathematical Functions" + nl See "Sin(0) = " + sin(0) + nl See "Sin(90) radians = " + sin(90) + nl See "Sin(90) degree = " + sin(90*3.14/180) + nl See "Cos(0) = " + cos(0) + nl See "Cos(90) radians = " + cos(90) + nl 114
136.
Ring Documentation, Release1.2 See "Cos(90) degree = " + cos(90*3.14/180) + nl See "Tan(0) = " + tan(0) + nl See "Tan(90) radians = " + tan(90) + nl See "Tan(90) degree = " + tan(90*3.14/180) + nl See "asin(0) = " + asin(0) + nl See "acos(0) = " + acos(0) + nl See "atan(0) = " + atan(0) + nl See "atan2(1,1) = " + atan2(1,1) + nl See "sinh(0) = " + sinh(0) + nl See "sinh(1) = " + sinh(1) + nl See "cosh(0) = " + cosh(0) + nl See "cosh(1) = " + cosh(1) + nl See "tanh(0) = " + tanh(0) + nl See "tanh(1) = " + tanh(1) + nl See "exp(0) = " + exp(0) + nl See "exp(1) = " + exp(1) + nl See "log(1) = " + log(1) + nl See "log(2) = " + log(2) + nl See "log10(1) = " + log10(1) + nl See "log10(2) = " + log10(2) + nl See "log10(10) = " + log10(10) + nl See "Ceil(1.12) = " + Ceil(1.12) + nl See "Ceil(1.72) = " + Ceil(1.72) + nl See "Floor(1.12) = " + floor(1.12) + nl See "Floor(1.72) = " + floor(1.72) + nl See "fabs(1.12) = " + fabs(1.12) + nl See "fabs(1.72) = " + fabs(1.72) + nl See "pow(2,3) = " + pow(2,3) + nl see "sqrt(16) = " + sqrt(16) + nl Program Output: Mathematical Functions Sin(0) = 0 Sin(90) radians = 0.89 Sin(90) degree = 1.00 Cos(0) = 1 Cos(90) radians = -0.45 Cos(90) degree = 0.00 Tan(0) = 0 Tan(90) radians = -2.00 Tan(90) degree = 1255.77 asin(0) = 0 acos(0) = 1.57 atan(0) = 0 atan2(1,1) = 0.79 sinh(0) = 0 sinh(1) = 1.18 cosh(0) = 1 25.2. Example 115
137.
Ring Documentation, Release1.2 cosh(1) = 1.54 tanh(0) = 0 tanh(1) = 0.76 exp(0) = 1 exp(1) = 2.72 log(1) = 0 log(2) = 0.69 log10(1) = 0 log10(2) = 0.30 log10(10) = 1 Ceil(1.12) = 2 Ceil(1.72) = 2 Floor(1.12) = 1 Floor(1.72) = 1 fabs(1.12) = 1.12 fabs(1.72) = 1.72 pow(2,3) = 8 sqrt(16) = 4 25.3 Random() Function The Random() function generate a random number and we can set the maximum value (optional). Syntax: Random(x) ---> Random number in the range [0,x] Example: for x = 1 to 20 see "Random number : " + random() + nl + "Random number Max (100) : " + random(100) + nl next Program Output: Random number : 31881 Random number Max (100) : 80 Random number : 5573 Random number Max (100) : 63 Random number : 2231 Random number Max (100) : 43 Random number : 12946 Random number Max (100) : 39 Random number : 22934 Random number Max (100) : 48 Random number : 4690 Random number Max (100) : 52 Random number : 13196 Random number Max (100) : 65 Random number : 30390 Random number Max (100) : 87 Random number : 4327 Random number Max (100) : 77 Random number : 12456 Random number Max (100) : 17 Random number : 28438 25.3. Random() Function 116
138.
Ring Documentation, Release1.2 Random number Max (100) : 13 Random number : 30503 Random number Max (100) : 6 Random number : 31769 Random number Max (100) : 94 Random number : 8274 Random number Max (100) : 65 Random number : 14390 Random number Max (100) : 90 Random number : 28866 Random number Max (100) : 12 Random number : 24558 Random number Max (100) : 70 Random number : 29981 Random number Max (100) : 77 Random number : 12847 Random number Max (100) : 63 Random number : 6632 Random number Max (100) : 60 25.4 Unsigned() Function We can use unsigned numbers using the Unsigned() function. Syntax: Unsigned(nNum1,nNum2,cOperator) --> result of cOperator operation on nNum1,nNum2 Example: see oat_hash("hello") + nl # Jenkins hash function - https://en.wikipedia.org/wiki/Jenkins_hash_function func oat_hash cKey h = 0 for x in cKey h = unsigned(h,ascii(x),"+") h = unsigned(h,unsigned(h,10,"<<"),"+") r = unsigned(h,6,">>") h = unsigned(h, r,"^") next h = unsigned(h,unsigned(h,3,"<<"),"+") h = unsigned(h,unsigned(h,11,">>"),"^") h = unsigned(h,unsigned(h,15,"<<"),"+") return h Output: 3372029979.00 25.5 Decimals() Functions We can determine the decimals numbers count after the point in float/double numbers using the decimals() function. Syntax: 25.4. Unsigned() Function 117
139.
Ring Documentation, Release1.2 Decimals(nDecimalsCount) Example: x = 1.1234567890123 for d = 0 to 14 decimals(d) see x + nl next Output: 1 1.1 1.12 1.123 1.1235 1.12346 1.123457 1.1234568 1.12345679 1.123456789 1.1234567890 1.12345678901 1.123456789012 1.1234567890123 1.12345678901230 25.5. Decimals() Functions 118
Ring Documentation, Release1.2 • fwrite() • fexists() 26.1 Read() Function We can read the file content using the Read() function Syntax: Read(cFileName) ---> String contains the file content Example: see read("myfile.txt") The read function can read binary files too Example: see read("myapp.exe") 26.2 Write() Function We can write string to file using the Write() function The write function can write binary data to binary files. Syntax: Write(cFileName,cString) # write string cString to file cFileName Example: # copy file cFile = read("ring.exe") write("ring2.exe",cFile) 26.3 Dir() Function We can get the folder contents (files & sub folders) using the Dir() function. Syntax: Dir(cFolderPath) ---> List contains files & sub folders. This function returns a list and each list item is a list of two items • File/sub folder name • Type (0 = File , 1 = Folder/Directory) Example: 26.1. Read() Function 120
142.
Ring Documentation, Release1.2 see "Testing DIR() " + nl mylist = dir("C:myfolder") for x in mylist if x[2] see "Directory : " + x[1] + nl else see "File : " + x[1] + nl ok next see "Files count : " + len(mylist) 26.4 Rename() Function We can rename files using the Rename() function Syntax: Rename(cOldFileName,cNewFileName) Example: rename("file.txt","help.txt") 26.5 Remove() Function We can delete a file using the Remove() function Syntax: Remove(cFileName) Example: remove("test.txt") 26.6 Fopen() Function We can open a file using the Fopen() function Syntax: Fopen(cFileName,cMode) ---> File Handle Mode Description “r” Reading (The file must exist) “w” Writing (create empty file / overwrite) “a” Appends (create file if it doesn’t exist) “r+” update (reading/writing) “w+” Create empty file (reading/writing) “a+” reading & appending 26.4. Rename() Function 121
143.
Ring Documentation, Release1.2 26.7 Fclose() Function When we open a file using fopen() function, we can close it using the Fclose() function Syntax: Fclose(file handle) 26.8 Fflush() Function We can flushes the output buffer of a stream using the Fflush() function Syntax: Fflush(file handle) 26.9 Freopen() Function We can open another file using the same file handle and at the same file close the old file Syntax: Freopen(cFileName,cMode,file handle) ---> file handle Example: freopen("myprogoutput.txt","w+",stdout) see "welcome" + nl for x = 1 to 10 see x + nl next /* ** Read : https://en.wikipedia.org/wiki/Device_file#Device_files ** The next code is not portable, we can use iswindows() before ** using it and we can write special code for each operating system. */ freopen("CON","w",stdout) # For Microsoft Windows see "Done" + nl # print to stdout again Output: # Output to stdout Done # Output to file : myprogoutput.txt welcome 1 2 3 4 5 6 7 26.7. Fclose() Function 122
144.
Ring Documentation, Release1.2 8 9 10 26.10 Tempfile() Function The function Tempfile() creates a temp. file (binary). The file will be deleted automatically when the stream is closed Syntax: TempFile() ---> file handle 26.11 Tempname() Function We can generate temp. file name using the Tempname() function The generated name will be different from the name of any existing file Syntax: Tempname() ---> generated file name as string 26.12 Fseek() Function We can set the file position of the stream using the Fseek() function Syntax: Fseek(file handle, nOffset, nWhence) ---> zero if successful The next table presents the nWhence values Value Description 0 Beginning of file 1 Current position 2 End of file 26.13 Ftell() Function We can know the current file position of a stream using the Ftell() function Syntax: Ftell(file handle) ---> file position as number 26.10. Tempfile() Function 123
145.
Ring Documentation, Release1.2 26.14 Rewind() Function We can set the file position to the beginning of the file using the Rewind() function Syntax: Rewind(file handle) 26.15 Fgetpos() Function We can get handle to the current file position using the Fgetpos() function Syntax: Fgetpos(file handle) ---> position handle 26.16 Fsetpos() Function We can set the current file position using the Fgetpos() function Syntax: Fsetpos(file handle,position handle) 26.17 Clearerr() Function We can clear the EOF error and the error indicators of a stream using the clearerr() function Syntax: Clearerr(file handle) 26.18 Feof() Function We can test the end-of-file indicator using the Feof() function Syntax: Feof(file handle) ---> returns 1 if EOF and 0 if not 26.19 Ferror() Function We can test the error indicator of a given stream using the Ferror() function Syntax: Ferror(file handle) ---> returns 1 if error and 0 if not 26.14. Rewind() Function 124
146.
Ring Documentation, Release1.2 26.20 Perror() Function We can print error message to the stderr using the Perror() function Syntax: Perror(cErrorMessage) 26.21 Fgetc() Function We can get the next character from the stream using the Fgetc() function Syntax: Fgetc(file handle) ---> returns character or EOF 26.22 Fgets() Function We can read new line from the stream using the Fgets() function Syntax: Fgets(file handle,nSize) ---> string The function stop when nSize characters are read, new line character is read or EOF. 26.23 Fputc() Function We can write a character to the stream using the Fputc() function Syntax: Fputc(file handle,cChar) 26.24 Fputs() Function We can write a string to the stream using the Fputs() function Syntax: Fputs(file handle,cString) 26.25 Ungetc() Function We can push a character to the stream using the Ungetc() function The character will be available for the next read Syntax: 26.20. Perror() Function 125
147.
Ring Documentation, Release1.2 Ungetc(file handle,character) 26.26 Fread() Function We can read data from a stream using the Fread() function Syntax: Fread(file handle,nSize) 26.27 Fwrite() Function We can write data to a stream using the Fwrite() function Syntax: Fwrite(file handle,cString) 26.28 Fexists() Function We can check if a file exists using the Fexists() function Syntax: Fexists(cFileName) ---> returns 1 if the file exists Example: see fexists("b:mahmoudappsringring.exe") + nl + fexists("b:mahmoudappsringring2.exe") + nl Output: 1 0 26.29 Example The next program test some of the file functions See "Testing file functions" + nl See "open file" + nl fp = fopen("testss65.ring","r") See "reopen" + nl fp = freopen("testss78.ring","r",fp) See "close file" + nl fclose(fp) see "temp file" + nl 26.26. Fread() Function 126
148.
Ring Documentation, Release1.2 fp = tempfile() fclose(fp) see "temp name" + nl see tempname() + nl remove("testsmytest1.txt") write("teststest1.txt","hello") rename("teststest1.txt","testsmytest2.txt") see "print file" + nl fp = fopen("testsfile.ring","r") r = fgetc(fp) while isstring(r) see r r = fgetc(fp) end fclose(fp) see nl+"print line from the file" + nl fp = fopen("testsfile.ring","r") r = fgets(fp,100) see r fclose(fp) fp = fopen("testsmyfile.txt","rw+") fseek(fp,0,2) # goto end of file fputc(fp,"t") fputc(fp,"e") fputc(fp,"s") fputc(fp,"t") fputs(fp,"test2") fclose(fp) see "print file" + nl see read("testsmyfile.txt") fp = fopen("testsmyfile.txt","r") see "testing ungetc() " + nl for x = 1 to 3 r = fgetc(fp) see r + nl ungetc(fp,r) next fclose(fp) see "testing fread() " + nl fp = fopen("ring.exe","r") r = fread(fp,100) see r + nl fclose(fp) see "testing fwrite() " + nl fp = fopen("testsmyfile.txt","wb") fwrite(fp,r) fclose(fp) 26.29. Example 127
149.
CHAPTER TWENTYSEVEN SYSTEM FUNCTIONS In thischapter we are going to learn about the system functions • System() • SysGet() • IsMSDOS() • IsWindows() • IsWindows64() • IsUnix() • IsMacOSX() • IsLinux() • IsFreeBSD() • IsAndroid() • Windowsnl() • Get Command Line Arguments • Get Active Source File Name • CurrentDir() • ExeFileName() • ChDir() • ExeFolder() • Version() 27.1 System() Function We can execute system commands using the system() function Syntax: System(cCommand) Example: System("myapp.exe") # Run myapp.exe System("ls") # print list of files 128
150.
Ring Documentation, Release1.2 27.2 SysGet() Function We can get environment variables using the Get() function Syntax: SysGet(cVariable) Example: see sysget("path") # print system path information 27.3 IsMSDOS() Function We can check if the operating system is MSDOS or not using the IsMSDOS() function Syntax: IsMSDOS() ---> Returns 1 if the operating system is MS-DOS, Returns 0 if it's not 27.4 IsWindows() Function We can check if the operating system is Windows or not using the IsWindows() function Syntax: IsWindows() ---> Returns 1 if the operating system is Windows, Returns 0 if it's not 27.5 IsWindows64() Function We can check if the operating system is Windows 64bit or not using the IsWindows64() function Syntax: IsWindows64() ---> Returns 1 if the operating system is Windows64, Returns 0 if it's not 27.6 IsUnix() Function We can check if the operating system is Unix or not using the IsUnix() function Syntax: IsUnix() ---> Returns 1 if the operating system is Unix, Returns 0 if it's not 27.7 IsMacOSX() Function We can check if the operating system is Mac OS X or not using the IsMacOSX() function Syntax: 27.2. SysGet() Function 129
151.
Ring Documentation, Release1.2 IsMacOSX() ---> Returns 1 if the operating system is Mac OS X, Returns 0 if it's not 27.8 IsLinux() Function We can check if the operating system is Linux or not using the IsLinux() function Syntax: IsLinux() ---> Returns 1 if the operating system is Linux, Returns 0 if it's not 27.9 IsFreeBSD() Function We can check if the operating system is FreeBSD or not using the IsFreeBSD() function Syntax: IsFreeBSD() ---> Returns 1 if the operating system is FreeBSD, Returns 0 if it's not 27.10 IsAndroid() Function We can check if the operating system is Android or not using the IsAndroid() function Syntax: IsAndroid() ---> Returns 1 if the operating system is Android, Returns 0 if it's not 27.11 Example see "IsMSDOS() --> " + ismsdos() + nl see "IsWindows() --> " + iswindows() + nl see "IsWindows64() --> " + iswindows64() + nl see "IsUnix() --> " + isunix() + nl see "IsMacOSX() --> " + ismacosx() + nl see "IsLinux() --> " + islinux() + nl see "IsFreeBSD() --> " + isfreebsd() + nl see "IsAndroid() --> " + isandroid() + nl Output: IsMSDOS() --> 0 IsWindows() --> 1 IsWindows64() --> 0 IsUnix() --> 0 IsMacOSX() --> 0 IsLinux() --> 0 IsFreeBSD() --> 0 IsAndroid() --> 0 27.8. IsLinux() Function 130
152.
Ring Documentation, Release1.2 27.12 Windowsnl() Function We can get the windows new line string using the Windowsnl() function. Syntax: WindowsNL() ---> Returns a string contains CR+LF = CHAR(13) + CHAR(10) Example: cStr = read("input.txt") if iswindows() cStr = substr(cStr,windowsnl(),nl) ok aList = str2list(cStr) # to do - list items processing using "for in" cStr = list2str(aList) if iswindows() cStr = substr(cStr,nl,windowsnl()) ok write("ouput.txt",cStr) 27.13 Get Command Line Arguments We can get the command line arguments passed to the ring script using the sysargv variable. The sysargv variable is a list contains the command line parameters. Example see copy("=",30) + nl see "Command Line Parameters" + nl see "Size : " + len(sysargv) + nl see sysargv see copy("=",30) + nl if len(sysargv) < 4 return ok nStart = sysargv[3] nEnd = sysargv[4] for x = nStart to nEnd see x + nl next Output b:mahmoudappsring>ring testssyspara.ring 1 10 ============================== Command Line Parameters Size : 4 ring testssyspara.ring 1 10 ============================== 27.12. Windowsnl() Function 131
153.
Ring Documentation, Release1.2 1 2 3 4 5 6 7 8 9 10 27.14 Get Active Source File Name We can get the active source file name (*.ring) using the filename() function Syntax: filename() ---> String contains the active source file name. Example: see "Active Source File Name : " + filename() + nl Output: Active Source File Name : testsfilename.ring Example: if sysargv[2] = filename() see "I'm the main program file!" + nl # we can run tests here! else see "I'm a sub file in a program" + nl ok 27.15 PrevFileName() Function Using the PrevFileName() function we can get the previous active source file name. The previous file would be the file of the caller function, Or the file of the function that we called before calling PrevFileName(). Syntax: prevfilename() ---> String contains the previous source file name. Example: The next function in stdlib.ring uses the PrevFileName() to know if the file of the caller function is the main source file of the program or not. Func IsMainSourceFile if PrevFileName() = sysargv[2] return true ok return false 27.14. Get Active Source File Name 132
154.
Ring Documentation, Release1.2 27.16 CurrentDir() Function Return the path of the current directory Syntax: CurrenDir() ---> String contains the path of the currect directory 27.17 ExeFileName() Function Return the Ring executable file name Syntax: exefilename() ---> String contains the Ring executable file name 27.18 ChDir() Function Change the current directory Syntax: ChDir(cNewPath) 27.19 ExeFolder() Function Return the Ring executable file path Syntax: exefolder() ---> String contains the Ring executable path 27.20 Version() Function Return the Ring version Syntax: version() ---> String contains the Ring version Output: 1.2 27.16. CurrentDir() Function 133
155.
CHAPTER TWENTYEIGHT EVAL() AND DEBUGGING Inthis chapter we are going to learn about • Error Handling using Try/Catch/Done • Eval() function • Raise() function • Assert() function 28.1 Try/Catch/Done Syntax: Try Statements... Catch Statements... Done The statements in the Try block will be executed, if any error happens then the statements in the catch block will be executed. Inside the catch block we can use the variable cCatchError to get the error message Example: Try see 5/0 Catch see "Catch!" + nl + cCatchError Done Output: Catch! Error (R1) : Cann't divide by zero ! 28.2 Eval() Function We can execute code during the runtime from string using the Eval() function Syntax: 134
156.
Ring Documentation, Release1.2 Eval(cCode) Example: Eval("nOutput = 5+2*5 " ) See "5+2*5 = " + nOutput + nl Eval("for x = 1 to 10 see x + nl next") Eval("func test see 'message from test!' ") test() Output: 5+2*5 = 15 1 2 3 4 5 6 7 8 9 10 message from test! 28.3 Raise() Function We can raise an exception using the Raise() function Syntax: Raise(cErrorMessage) The function will display the error message then end the execution of the program. We can use Try/Catch/Done to avoid exceptions generated by raise() function. Example: nMode = 10 if nMode < 0 or nMode > 5 raise("Error : nMode not in the range 1:4") ok Output: Line 4 Error : nMode not in the range 1:4 In raise in file testsraise.ring Example: try testmode(6) catch see "avoid raise!" done testmode(-1) 28.3. Raise() Function 135
157.
Ring Documentation, Release1.2 func testmode nMode if nMode < 0 or nMode > 5 raise("Error : nMode not in the range 1:4") ok Output: avoid raise! Line 12 Error : nMode not in the range 1:4 In raise In function testmode() in file testsraise2.ring called from line 7 in file testsraise2.ring 28.4 Assert() Function We can use the Assert() function to test conditions before executing the code If the test fail the program will be terminated with an error message contains the assert condition. Syntax: Assert( condition ) Example: x = 10 assert( x = 10) assert( x = 100 ) Output: Line 3 Assertion Failed! In assert in file testsassert.ring 28.4. Assert() Function 136
158.
CHAPTER TWENTYNINE DEMO PROGRAMS In thischapter we will see simple demo programs • Language Shell • Main Menu 29.1 Language Shell We can create simple interactive programming environment using the next program while true see nl + "code:> " give cCode try eval(cCode) catch see cCatchError done end Output: code:> see "hello world" hello world code:> for x = 1 to 10 see x + nl next 1 2 3 4 5 6 7 8 9 10 code:> func test see "Hello from test" + nl code:> test() Hello from test code:> bye 137
159.
Ring Documentation, Release1.2 29.2 Main Menu Example: # Demo Program while true see " Main Menu =========== [1] Say Hello [2] Sum two numbers [3] Stars [4] Fact [5] Exit " give nMenu see nl # we can use Switch-ON-Other-OFF instead of IF-BUT-ELSE-OK Switch nMenu On 1 sayhello() On 2 Sum() On 3 Stars() On 4 see "Enter Number : " give x see "Output : " Try see Fact(number(x)) Catch see "Error in parameters!" + nl Done On "5" return Other see "bad option" + nl Off end func sayhello see "Enter your name ? " give fname see "Hello " + fname + nl func sum see "number 1 : " give num1 see "number 2 : " give num2 see "Sum : " see 0 + num1 + num2 func stars for x = 1 to 10 see space(8) for y = 1 to x see "*" next see nl next func fact x if x = 1 return 1 else return x * fact(x-1) ok 29.2. Main Menu 138
160.
Ring Documentation, Release1.2 func space x y = "" for t=1 to x y += " " next return y Output: Main Menu =========== [1] Say Hello [2] Sum two numbers [3] Stars [4] Fact [5] Exit 1 Enter your name ? Mahmoud Fayed Hello Mahmoud Fayed Main Menu =========== [1] Say Hello [2] Sum two numbers [3] Stars [4] Fact [5] Exit 2 number 1 : 3 number 2 : 4 Sum : 7 Main Menu =========== [1] Say Hello [2] Sum two numbers [3] Stars [4] Fact [5] Exit 3 * ** *** **** ***** ****** ******* ******** ********* ********** Main Menu =========== [1] Say Hello [2] Sum two numbers 29.2. Main Menu 139
161.
Ring Documentation, Release1.2 [3] Stars [4] Fact [5] Exit 4 Enter Number : 5 Output : 120 Main Menu =========== [1] Say Hello [2] Sum two numbers [3] Stars [4] Fact [5] Exit 5 29.2. Main Menu 140
162.
CHAPTER THIRTY ODBC FUNCTIONS This chaptercontains the ODBC functions provided by the Ring programming language. • odbc_init() • odbc_drivers() • odbc_datasources() • odbc_close() • odbc_connect() • odbc_disconnect() • odbc_execute() • odbc_colcount() • odbc_fetch() • odbc_getdata() • odbc_tables() • odbc_columns() • odbc_autocommit() • odbc_commit() • odbc_rollback() 30.1 odbc_init() Function We can create ODBC Handle using the odbc_init() function Syntax: odbc_init() ---> ODBC Handle 30.2 odbc_drivers() Function We can get a list of ODBC drivers using the odbc_drivers() function Syntax: 141
163.
Ring Documentation, Release1.2 odbc_drivers(ODBC Handle) ---> List of Drivers 30.3 odbc_datasources() Function We can get a list of ODBC data sources using the odbc_datasources() function Syntax: odbc_datasources(ODBC Handle) ---> List of Data sources 30.4 odbc_close() Function After the end of using ODBC functions we can free resources using ODBC_Close() function Syntax: odbc_close(ODBC Handle) 30.5 Print List of ODBC Drivers The next example print a list of ODBC drivers. See "ODBC test 1" + nl oODBC = odbc_init() See "Drivers " + nl see odbc_drivers(oODBC) odbc_close(oODBC) Output: ODBC test 1 Drivers Microsoft Access-Treiber (*.mdb) - SQLLevel=0 Driver do Microsoft Paradox (*.db ) - SQLLevel=0 Driver do Microsoft Excel(*.xls) - SQLLevel=0 Microsoft Text Driver (*.txt; *.csv) - SQLLevel=0 Driver da Microsoft para arquivos texto (*.txt; *.csv) - SQLLevel=0 Microsoft dBase-Treiber (*.dbf) - SQLLevel=0 SQL Server - CPTimeout=60 Microsoft Excel Driver (*.xls) - SQLLevel=0 Driver do Microsoft dBase (*.dbf) - SQLLevel=0 Microsoft Paradox-Treiber (*.db ) - SQLLevel=0 Microsoft ODBC for Oracle - CPTimeout=120 Microsoft Text-Treiber (*.txt; *.csv) - SQLLevel=0 Microsoft Excel-Treiber (*.xls) - SQLLevel=0 Microsoft Access Driver (*.mdb) - SQLLevel=0 Driver do Microsoft Access (*.mdb) - SQLLevel=0 Microsoft Paradox Driver (*.db ) - SQLLevel=0 Microsoft dBase Driver (*.dbf) - SQLLevel=0 Microsoft Access Driver (*.mdb, *.accdb) - UsageCount=3 Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb) - UsageCount=3 Microsoft Access Text Driver (*.txt, *.csv) - UsageCount=3 30.3. odbc_datasources() Function 142
164.
Ring Documentation, Release1.2 SQL Server Native Client 10.0 - UsageCount=1 SQL Server Native Client 11.0 - UsageCount=1 Microsoft Access dBASE Driver (*.dbf, *.ndx, *.mdx) - UsageCount=3 Microsoft Access Paradox Driver (*.db) - UsageCount=3 MySQL ODBC 5.3 ANSI Driver - UsageCount=1 MySQL ODBC 5.3 Unicode Driver - UsageCount=1 ODBC Driver 11 for SQL Server - UsageCount=1 Lianja ODBC Driver - CPTimeout=60 Microsoft Visual FoxPro Driver - UsageCount=1 Microsoft Visual FoxPro-Treiber - UsageCount=1 Driver para o Microsoft Visual FoxPro - UsageCount=1 Microsoft FoxPro VFP Driver (*.dbf) - UsageCount=1 30.6 Print List of ODBC Data Sources The next example print a list of ODBC data sources. See "ODBC test 2" + nl pODBC = odbc_init() See "Data Sources " + nl see odbc_datasources(pODBC) odbc_close(pODBC) Output: ODBC test 2 Data Sources Excel Files - Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb) MS Access Database - Microsoft Access Driver (*.mdb, *.accdb) Customer - Microsoft Access Driver (*.mdb) IdCardData - Microsoft Access Driver (*.mdb) MyProjectData2 - Microsoft Access Driver (*.mdb) MyData - Microsoft Access Driver (*.mdb) MonprojetData - Microsoft Access Driver (*.mdb) dBASE Files - Microsoft Access dBASE Driver (*.dbf, *.ndx, *.mdx) myvfpdata - Microsoft Visual FoxPro Driver FACTORYDATA - Microsoft Access Driver (*.mdb) TRAININGSYSDATA - Microsoft Access Driver (*.mdb) RVCSYSDATASQLDB - SQL Server Native Client 11.0 PWCTRVCDATA - Microsoft Access Driver (*.mdb) MyCompany - Microsoft Access Driver (*.mdb) HCS - Microsoft Access Driver (*.mdb) HCS2 - Microsoft Access Driver (*.mdb, *.accdb) MyProjectData - Microsoft Access Driver (*.mdb) Xtreme Sample Database 2008 - Microsoft Access Driver (*.mdb) Lianja_Southwind - Lianja ODBC Driver Visual FoxPro Database - Microsoft Visual FoxPro Driver Visual FoxPro Tables - Microsoft Visual FoxPro Driver 30.7 odbc_connect() Function We can connect to the database using the odbc_connect() function. Syntax: 30.6. Print List of ODBC Data Sources 143
165.
Ring Documentation, Release1.2 odbc_connect(ODBC Handle, cConnectionString) 30.8 odbc_disconnect() Function We can close the connection to the database using the odbc_disconnect() function. Syntax: odbc_disconnect(ODBC Handle) 30.9 Open and Close Connection The next example connect to the database then close the connection See "ODBC test 3" + nl pODBC = odbc_init() See "Connect to database" + nl see odbc_connect(pODBC,"DBQ=test.mdb;Driver={Microsoft Access Driver (*.mdb)}") + nl See "disconnect" + nl odbc_disconnect(pODBC) See "Close database..." + nl odbc_close(pODBC) Output: ODBC test 3 Connect to database 1 disconnect Close database... 30.10 odbc_execute() Function We can execute SQL Statements on the database using the odbc_execute() function. Syntax: odbc_execute(ODBC Handle, cSQLStatement) 30.11 odbc_colcount() Function We can get columns count in the query result using the odbc_colcount() function. Syntax: odbc_colcount(ODBC Handle) ---> Columns Count as Number 30.8. odbc_disconnect() Function 144
166.
Ring Documentation, Release1.2 30.12 odbc_fetch() Function We can fetch a row from the query result using the odbc_fetch() function. Syntax: odbc_fetch(ODBC Handle) 30.13 odbc_getdata() Function We can get column value from the fetched row using the odbc_getdata() function. Syntax: odbc_getdata(ODBC Handle, nColumnNumber) ---> Column Value 30.14 Execute Query and Print Result The next example execute query then print the query result. See "ODBC test 4" + nl pODBC = odbc_init() See "Connect to database" + nl see odbc_connect(pODBC,"DBQ=test.mdb;Driver={Microsoft Access Driver (*.mdb)}") + nl See "Select data" + nl see odbc_execute(pODBC,"select * from person") + nl nMax = odbc_colcount(pODBC) See "Columns Count : " + nMax + nl while odbc_fetch(pODBC) See "Row data:" + nl for x = 1 to nMax see odbc_getdata(pODBC,x) + " - " next end See "Close database..." + nl odbc_disconnect(pODBC) odbc_close(pODBC) 30.15 odbc_tables() Function We can get a list of tables inside the database using the odbc_tables() function. We can access the result of this function as we get any query result. Syntax: odbc_tables(ODBC Handle) Example: See "ODBC test - Get Database Tables" + nl pODBC = odbc_init() See "Connect to database" + nl 30.12. odbc_fetch() Function 145
167.
Ring Documentation, Release1.2 odbc_connect(pODBC,"DBQ=test.mdb;Driver={Microsoft Access Driver (*.mdb)}") + nl See "Select data" + nl odbc_tables(pODBC) + nl nMax = odbc_colcount(pODBC) See "Columns Count : " + nMax + nl while odbc_fetch(pODBC) for x = 1 to nMax see odbc_getdata(pODBC,x) if x != nMax see " - " ok next See nl end See "Close database..." odbc_disconnect(pODBC) odbc_close(pODBC) Output: ODBC test - Get Database Tables Connect to database Select data Columns Count : 5 .test - NULL - Customer - TABLE - NULL .test - NULL - employee - TABLE - NULL .test - NULL - person - TABLE - NULL .test - NULL - tel - TABLE - NULL Close database... 30.16 odbc_columns() Function We can get a list of columns inside the table using the odbc_columns() function. Syntax: odbc_columns(ODBC Handle, cTableName) Example: See "ODBC test - Get Table Columns" + nl pODBC = odbc_init() See "Connect to database" + nl odbc_connect(pODBC,"DBQ=test.mdb;Driver={Microsoft Access Driver (*.mdb)}") + nl See "Get Columns inside the Person Table" + nl odbc_columns(pODBC,"person") + nl while odbc_fetch(pODBC) see odbc_getdata(pODBC,4) + nl end See "Close database..." + nl odbc_disconnect(pODBC) odbc_close(pODBC) Output: ODBC test - Get Table Columns Connect to database Get Columns inside the Person Table FIRST 30.16. odbc_columns() Function 146
168.
Ring Documentation, Release1.2 LAST STREET CITY STATE ZIP HIREDATE MARRIED AGE SALARY NOTES Close database... 30.17 odbc_autocommit() Function We can enable or disable the auto commit feature using the odbc_autocommit() function. Syntax: odbc_autocommit(ODBC Handle, lStatus) # lStatus can be True or False 30.18 odbc_commit() Function We can commit updates to the database using the odbc_commit() function. Syntax: odbc_commit(ODBC Handle) 30.19 odbc_rollback() Function We can rollback updates to the database using the odbc_rollback() function. Syntax: odbc_rollback(ODBC Handle) 30.20 Transactions and Using Commit and Rollback Example: See "ODBC Test - Transactions and using Commit and Rollback" + nl pODBC = odbc_init() See "Connect to database" + nl see odbc_connect(pODBC,"DBQ=test.mdb;Driver={Microsoft Access Driver (*.mdb)}") + nl see "insert data..." + nl odbc_autocommit(pODBC,0) for x = 1 to 10000 odbc_execute(pODBC,"insert into tel values (" + x + ",'mahmoud')") next for x = 10001 to 15000 30.17. odbc_autocommit() Function 147
169.
Ring Documentation, Release1.2 odbc_execute(pODBC,"insert into tel values (" + x + ",'samir')") next odbc_commit(pODBC) for x = 15001 to 20000 odbc_execute(pODBC,"insert into tel values (" + x + ",'fayed')") next ODBC_ROLLBACK(pODBC) odbc_execute(pODBC,"insert into tel values (" + x + ",'fayed')") odbc_commit(pODBC) See "Close database..." + nl odbc_disconnect(pODBC) odbc_close(pODBC) Output: ODBC Test - Transactions and using Commit and Rollback Connect to database 1 insert data... Close database... 30.21 Save and Restore images The next example save an image inside the database See "ODBC test - Save image in the database" + nl pODBC = odbc_init() See "Connect to database" + nl see odbc_connect(pODBC,"DBQ=test.mdb;Driver={Microsoft Access Driver (*.mdb)}") + nl see "Read Image File..." + nl cFile = str2hex(read("testsmahmoud.jpg")) see "size " + len(CFile)+nl see "Save image in the database..." + nl stmt = "insert into tel values (20000,'mahmoud','" + cFile + "');" odbc_execute(pODBC,stmt) See "Close database..." + nl odbc_disconnect(pODBC) odbc_close(pODBC) The next example restore the image from the database See "ODBC Test - Restore image from the database" + nl pODBC = odbc_init() See "Connect to database" + nl see odbc_connect(pODBC,"DBQ=test.mdb;Driver={Microsoft Access Driver (*.mdb)}") + nl See "Select data" + nl see odbc_execute(pODBC,"select * from tel") + nl nMax = odbc_colcount(pODBC) See "Columns Count : " + nMax + nl while odbc_fetch(pODBC) See "Write image file" + nl write("testsgreat.jpg",hex2str( odbc_getdata(pODBC,3) ) ) end See "Close database..." + nl 30.21. Save and Restore images 148
CHAPTER THIRTYONE MYSQL FUNCTIONS In thischapter we are going to learn about the MySQL functions provided by the Ring programming language. • MySQL_Info() • MySQL_Init() • MySQL_Error() • MySQL_Connect() • MySQL_Close() • MySQL_Query() • MySQL_Insert_ID() • MySQL_Result() • MySQL_Next_Result() • MySQL_Columns() • MySQL_Result2() • MySQL_Escape_String() • MySQL_AutoCommit() • MySQL_Commit() • MySQL_Rollback() 31.1 MySQL_Info() Function We can get the MySQL Client version using the MySQL_Info() function. Syntax: MySQL_Info() ---> string contains the MySQL Client version Example: see "MySQL Client Version : " + mysql_info() Output: MySQL Client Version : 6.1.5 150
172.
Ring Documentation, Release1.2 31.2 MySQL_Init() Function We can start using MySQL Client through the MySQL_Init() function. Syntax: MySQL_Init() ---> MySQL Handle 31.3 MySQL_Error() Function We can get the error message from the MySQL Client using the MySQL_Error() function. Syntax: MySQL_Error(MySQL Handle) ---> Error message as string 31.4 MySQL_Connect() Function We can connect to the MySQL database server using the MySQL_Connect() function. Syntax: MySQL_Connect(MySQL Handle, cServer, cUserName, cPassword) ---> lStatus 31.5 MySQL_Close() Function We can close the connection to the MySQL database using the MySQL_Close() function Syntax: MySQL_Close(MySQL Handle) 31.6 MySQL_Query() Function We can execute SQL queries using the MySQL_Query() function Syntax: MySQL_Query(MySQL Handle, cSQLQuery) 31.7 Create Database The next example connect to MySQL Server then create new database. See "MySQL Test - Create Database" + nl con = mysql_init() See "Connect" + nl 31.2. MySQL_Init() Function 151
173.
Ring Documentation, Release1.2 if mysql_connect(con,"localhost","root","root") = 0 see "Cann't connect" + nl see "Error : " + mysql_error(con) + nl mysql_close(con) bye ok See "Create Database..." + nl mysql_query(con,"CREATE DATABASE mahdb") See "Close Connection" + nl mysql_close(con) Output: MySQL Test - Create Database Connect Create Database... Close Connection 31.8 Create Table and Insert Data The next example create new table and insert records func main see "Create Table and Insert Records" + nl con = mysql_init() see "Connect" + nl if mysql_connect(con, "localhost", "root", "root","mahdb") = 0 system_error(con) ok see "Drop table" + nl if mysql_query(con, "DROP TABLE IF EXISTS Employee") system_error(con) ok see "Create table" + nl if mysql_query(con, "CREATE TABLE Employee(Id INT, Name TEXT, Salary INT)") system_error(con) ok see "Insert data" + nl if mysql_query(con, "INSERT INTO Employee VALUES(1,'Mahmoud',15000)") system_error(con) ok if mysql_query(con, "INSERT INTO Employee VALUES(2,'Samir',16000)") system_error(con) ok if mysql_query(con, "INSERT INTO Employee VALUES(3,'Fayed',17000)") system_error(con) ok see "Close connection" + nl mysql_close(con) func system_error con see mysql_error(con) mysql_close(con) bye Output: 31.8. Create Table and Insert Data 152
174.
Ring Documentation, Release1.2 Create Table and Insert Records Connect Drop table Create table Insert data Close connection 31.9 MySQL_Insert_ID() Function We can get the inserted row id using the MySQL_Insert_ID() function Syntax: MySQL_Insert_ID() ---> Inserted row id as number Example: con = mysql_init() see "connect to database" + nl mysql_connect(con,"localhost","root","root","mahdb") see "drop table" + nl mysql_query(con, "DROP TABLE IF EXISTS Customers") see "create table" + nl mysql_query(con, "CREATE TABLE Customers(Id INT PRIMARY KEY AUTO_INCREMENT, Name TEXT)") see "insert record" + nl mysql_query(con, "INSERT INTO Customers(Name) VALUES('Mahmoud')") see "insert record" + nl mysql_query(con, "INSERT INTO Customers(Name) VALUES('Samir')") see "insert record" + nl mysql_query(con, "INSERT INTO Customers(Name) VALUES('Fayed')") see "insert record" + nl mysql_query(con, "INSERT INTO Customers(Name) VALUES('Test 2015')") see "inserted row id : " + mysql_insert_id(con) + nl see "close database" + nl mysql_close(con) Output: connect to database drop table create table insert record insert record insert record insert record inserted row id : 4 close database 31.10 MySQL_Result() Function We can get the query result (data without column names) using the MySQL_Result() function. Syntax: 31.9. MySQL_Insert_ID() Function 153
175.
Ring Documentation, Release1.2 MySQL_Result(MySQL Handle) ---> List contains the query result 31.11 MySQL_Next_Result() Function We can move to the next query result using the MySQL_Next_Result() function. We use this function when we have multiple SQL statements in the same query. Syntax: MySQL_Next_Result(MySQL Handle) 31.12 Print Query Result The next example execute a query on the database then print the result. con = mysql_init() see "Connect to database" + nl mysql_connect(con, "localhost", "root", "root","mahdb") see "Execute Query" + nl mysql_query(con, "SELECT Name FROM Employee WHERE Id=1;"+ "SELECT Name FROM Employee WHERE Id=3") see "Print Result" + nl see mysql_result(con) mysql_next_result(con) see mysql_result(con) see "close database" + nl mysql_close(con) Output: Connect to database Execute Query Print Result Mahmoud Fayed close database 31.13 MySQL_Columns() Function We can get a list of columns names using the MySQL_Columns() function. Syntax: MySQL_Columns(MySQL Handle) ---> List contains columns information Example: con = mysql_init() see "Connect to database" + nl mysql_connect(con, "localhost", "root", "root","mahdb") see "Execute Query" + nl mysql_query(con, "SELECT * FROM Employee") see "Result" + nl 31.11. MySQL_Next_Result() Function 154
176.
Ring Documentation, Release1.2 see mysql_columns(con) see "Close database" + nl mysql_close(con) Output: Connect to database Execute Query Result Id 11 3 32768 Name 65535 252 16 Salary 11 3 32768 Close database 31.14 MySQL_Result2() Function Instead of using MySQL_Result() to get the result data without columns names, we can use the MySQL_Result2() to get all of the column names then the query result in one list. Syntax: MySQL_Result2(MySQL Handle) ---> List (query result starts with columns names) Example: con = mysql_init() see "Connect to database" + nl mysql_connect(con, "localhost", "root", "root","mahdb") see "Execute Query" + nl mysql_query(con, "SELECT * FROM Employee") see "Print Result" + nl see mysql_result2(con) see "Close database" + nl mysql_close(con) Output: Connect to database Execute Query Print Result Id Name Salary 1 Mahmoud 15000 2 Samir 31.14. MySQL_Result2() Function 155
177.
Ring Documentation, Release1.2 16000 3 Fayed 17000 Close database 31.15 MySQL_Escape_String() Function We can store binary data and special characters in the database after processing using MySQL_Escape_String() func- tion Syntax: MySQL_Escape_String(MySQL Handle, cString) ---> String after processing 31.16 Save Image inside the database Example: See "Read file" + nl cFile = read("testsmahmoud.jpg") con = mysql_init() See "Connect to database..." + nl mysql_connect(con, "localhost", "root", "root","mahdb") See "Escape string..." + nl cFile = mysql_escape_string(con,cFile) stmt = "INSERT INTO photo(id, data) VALUES(1, '" + cFile + "')" See "Insert data..." + nl mysql_query(con,stmt) See "Close database..." + nl mysql_close(con) Output: Read file Connect to database... Escape string... Insert data... Close database... 31.17 Restore Image From The Database Example: con = mysql_init() See "Connect to database..." + nl mysql_connect(con, "localhost", "root", "root","mahdb") See "Read data from database..." + nl mysql_query(con,"SELECT data FROM photo WHERE id=1") See "Write new file" + nl result = mysql_result(con) write("testsmahmoud2.jpg",result[1][1]) 31.15. MySQL_Escape_String() Function 156
178.
Ring Documentation, Release1.2 See "Close database..." + nl mysql_close(con) Output: Connect to database... Read data from database... Write new file Close database... 31.18 MySQL_AutoCommit() Function We can enable or disable the auto commit feature using the MySQL_AutoCommit() function. Syntax: MySQL_AutoCommit(MySQL Handle, lStatus) # lstatus can be True/False 31.19 MySQL_Commit() Function We can commit updates to the database using the MySQL_Commit() function. Syntax: MySQL_Commit(MySQL Handle) 31.20 MySQL_Rollback() Function We can rollback updates to the database using the MySQL_Rollback() function. Syntax: MySQL_Rollback(MySQL Handle) 31.21 Transaction Example The next example presents the usage of MySQL_Autocommit(), MySQL_Commit() & MySQL_RollBack() functions. Example: func main con = mysql_init() see "Connect" + nl if mysql_connect(con, "localhost", "root", "root","mahdb") = 0 system_error(con) ok see "Drop table" + nl if mysql_query(con, "DROP TABLE IF EXISTS Employee2") system_error(con) ok 31.18. MySQL_AutoCommit() Function 157
179.
Ring Documentation, Release1.2 see "Create table" + nl if mysql_query(con, "CREATE TABLE Employee2(Id INT, Name TEXT, Salary INT)") system_error(con) ok see "Insert data" + nl if mysql_query(con, "INSERT INTO Employee2 VALUES(1,'Mahmoud',15000)") system_error(con) ok if mysql_query(con, "INSERT INTO Employee2 VALUES(2,'Samir',16000)") system_error(con) ok if mysql_query(con, "INSERT INTO Employee2 VALUES(3,'Fayed',17000)") system_error(con) ok mysql_autocommit(con,False) mysql_query(con, "INSERT INTO Employee2 VALUES(4,'Ahmed',5000)") mysql_query(con, "INSERT INTO Employee2 VALUES(5,'Ibrahim',50000)") mysql_query(con, "INSERT INTO Employee2 VALUES(6,'Mohammed',50000)") See "Save transaction (y/n) " give nChoice if upper(nChoice) = "Y" mysql_commit(con) else mysql_rollback(con) ok see "Close connection" + nl mysql_close(con) func system_error con see mysql_error(con) mysql_close(con) bye Output: Connect Drop table Create table Insert data Save transaction (y/n) y Close connection 31.21. Transaction Example 158
180.
CHAPTER THIRTYTWO SQLITE FUNCTIONS In thischapter we will learn about using the SQLite database in the Ring programming language. 32.1 sqlite_init() function Syntax: sqlite_init() ---> SQLite Object 32.2 sqlite_open() function Syntax: sqlite_open(SQLite Object,cFileName) 32.3 sqlite_execute() function Syntax: sqlite_exexute(SQLite Object,cSQLStatement) 32.4 sqlite_close() function Syntax: sqlite_close(SQLite Object) 32.5 Example The next code create a SQLite database, add new records then display the data. 159
181.
Ring Documentation, Release1.2 oSQLite = sqlite_init() sqlite_open(oSQLite,"mytest.db") sql = "CREATE TABLE COMPANY(" + "ID INT PRIMARY KEY NOT NULL," + "NAME TEXT NOT NULL," + "AGE INT NOT NULL," + "ADDRESS CHAR(50)," + "SALARY REAL );" sqlite_execute(oSQLite,sql) sql = "INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) " + "VALUES (1, 'Mahmoud', 29, 'Jeddah', 20000.00 ); " + "INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) " + "VALUES (2, 'Ahmed', 27, 'Jeddah', 15000.00 ); " + "INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY)" + "VALUES (3, 'Mohammed', 31, 'Egypt', 20000.00 );" + "INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY)" + "VALUES (4, 'Ibrahim', 24, 'Egypt ', 65000.00 );" sqlite_execute(oSQLite,sql) aResult = sqlite_execute(oSQLite,"select * from COMPANY") for x in aResult for t in x see t[2] + nl next next see copy("*",50) + nl for x in aResult see x["name"] + nl next sqlite_close(oSQLite) Output: 1 Mahmoud 29 Jeddah 20000.0 2 Ahmed 27 Jeddah 15000.0 3 Mohammed 31 Egypt 20000.0 4 Ibrahim 24 Egypt 65000.0 32.5. Example 160
182.
Ring Documentation, Release1.2 ************************************************** Mahmoud Ahmed Mohammed Ibrahim 32.5. Example 161
183.
CHAPTER THIRTYTHREE SECURITY AND INTERNETFUNCTIONS This chapter contains the security and internet functions provided by the Ring programming language for Hashing, Encryption & Decryption. • MD5() • SHA1() • SHA256() • SHA512() • SHA384() • SHA224() • Encrypt() • Decrypt() • Randbytes() • Download() • SendEmail() 33.1 MD5() Function We can calculate the MD5 hash using the MD5() Function Syntax: MD5(cString) ---> String contains the MD5 hash of the string cString Example: see "md5('happy') = " + md5("happy") + nl + "md5('Hello') = " + md5("Hello") + nl Output: md5('happy') = 56ab24c15b72a457069c5ea42fcfc640 md5('Hello') = 8b1a9953c4611296a827abf8c47804d7 162
184.
Ring Documentation, Release1.2 33.2 SHA1() Function We can calculate the SHA1 hash using the SHA1() Function Syntax: SHA1(cString) ---> String contains the SHA1 hash of the string cString Example: see "sha1('hello') : " + sha1("hello") + nl + "sha1('apple') : " + sha1("apple") + nl Output: sha1('hello') : aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d sha1('apple') : d0be2dc421be4fcd0172e5afceea3970e2f3d940 33.3 SHA256() Function We can calculate the SHA256 hash using the SHA256() Function Syntax: SHA256(cString) ---> String contains the SHA256 hash of the string cString Example: see "sha256('hello') : " + sha256("hello") + nl + "sha256('apple') : " + sha256("apple") + nl Output: sha256('hello') : 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824 sha256('apple') : 3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b 33.4 SHA512() Function We can calculate the SHA512 hash using the SHA512() Function Syntax: SHA512(cString) ---> String contains the SHA512 hash of the string cString Example: see "sha512('hello') : " + sha512("hello") + nl + "sha512('apple') : " + sha512("apple") + nl + "sha512('hello world') : " + sha512("hello world") + nl Output: sha512('hello') : 9b71d224bd62f3785d96d46ad3ea3d73319bfbc2890caadae2dff72519673c a72323c3d99ba5c11d7c7acc6e14b8c5da0c4663475c2e5c3adef46f73bcdec043 sha512('apple') : 844d8779103b94c18f4aa4cc0c3b4474058580a991fba85d3ca698a0bc9e52 c5940feb7a65a3a290e17e6b23ee943ecc4f73e7490327245b4fe5d5efb590feb2 33.2. SHA1() Function 163
185.
Ring Documentation, Release1.2 sha512('hello world') : 309ecc489c12d6eb4cc40f50c902f2b4d0ed77ee511a7c7a9bcd3ca8 6d4cd86f989dd35bc5ff499670da34255b45b0cfd830e81f605dcf7dc5542e93ae9cd76f 33.5 SHA384() Function We can calculate the SHA384 hash using the SHA384() Function Syntax: SHA384(cString) ---> String contains the SHA384 hash of the string cString Example: see "sha384('hello') : " + sha384("hello") + nl + "sha384('apple') : " + sha384("apple") + nl + "sha384('hello world') : " + sha384("hello world") + nl Output: sha384('hello') : 59e1748777448c69de6b800d7a33bbfb9ff1b463e44354c3553bcdb9c666fa 90125a3c79f90397bdf5f6a13de828684f sha384('apple') : 3d8786fcb588c93348756c6429717dc6c374a14f7029362281a3b21dc10250 ddf0d0578052749822eb08bc0dc1e68b0f sha384('hello world') : fdbd8e75a67f29f701a4e040385e2e23986303ea10239211af907fcb b83578b3e417cb71ce646efd0819dd8c088de1bd 33.6 SHA224() Function We can calculate the SHA224 hash using the SHA224() Function Syntax: SHA224(cString) ---> String contains the SHA224 hash of the string cString Example: see "sha224('hello') : " + sha224("hello") + nl + "sha224('apple') : " + sha224("apple") + nl + "sha224('hello world') : " + sha224("hello world") + nl Output: sha224('hello') : ea09ae9cc6768c50fcee903ed054556e5bfc8347907f12598aa24193 sha224('apple') : b7bbfdf1a1012999b3c466fdeb906a629caa5e3e022428d1eb702281 sha224('hello world') : 2f05477fc24bb4faefd86517156dafdecec45b8ad3cf2522a563582b 33.7 Encrypt() Function We can use the Encrypt() function to encrypts the data using the Blowfish algorithm. Syntax: Encrypt(cString, cKey, cIV) ---> Encrypted string 33.5. SHA384() Function 164
186.
Ring Documentation, Release1.2 33.8 Decrypt() Function We can use the Decrypt() function to decrypt the data encrypted using the Encrypt() function. Syntax: Decrypt(cCipher, cKey, cIV) ---> Decrypted string 33.9 Encryption and Decryption Example The next example demonstrates how to use the Encrypt() and Decrypt() functions. These functions use the Blowfish algorithm. See "Enter a string : " give cStr list = 0:15 cKey="" for x in list cKey += char(x) next list = 1:8 cIV = "" for x in list cIV += char(x) next cStr = Encrypt(cStr,cKey,cIV) See "Cipher Text : " + cStr + nl + "Plain Text : " + Decrypt(cStr,cKey,cIV) + nl 33.10 File Hash The next example demonstrates how to calculate the hash functions for files cStr = read("myapp.exe") see "Size : " + len(cStr) + nl + "md5 : " + md5(cStr) + nl + "sha1 : " + sha1(cStr) + nl + "sha256 : " + sha256(cStr) + nl + "sha224 : " + sha224(cStr) + nl + "sha384 : " + sha384(cStr) + nl + "sha512 : " + sha512(cStr) + nl Output: Size : 58079876 md5 : 762eee15d8d2fd73b71ea52538b28667 sha1 : 9212c0c7258bad89a62bd239e1358a9276a9d070 sha256 : 7d6724e69b6c553da749ba31b6185dddc965129b64d9e9bf3de88f67df3b1cdc sha224 : 5a9c8a7d662bce4f880ba94f90a79362b672528b9efd5abc718c7a3d sha384 : 18e23f973abedbeb3981c423f12aeadecf96f9c6fb28aeabe3be4c484f8540afcc3861b b370ce2b59cf3c99c130b856b sha512 : da3d5e997d06f8b2a7a9964b77f7d82eedb76b245c611082c1639f83f51d83880bcd08f cd53dcab1167bdca0b82fec5071971ac17c76479d76985ced4ab0d18e 33.11 Randbytes() Function We can generate a string of pseudo-random bytes using the Randbytes() function. Syntax: 33.8. Decrypt() Function 165
187.
Ring Documentation, Release1.2 Randbytes(nSize) ---> String contains random bytes (bytes count = nSize) Example: salt = randbytes(32) password = "SecretPassWord@$%123" see salt + nl see sha256("test" + salt) + nl 33.12 Download() Function Syntax: Download(cURL) ---> String contains the server response Example: cStr= download("http://doublesvsoop.sourceforge.net/") see cStr write("download.txt",cStr) 33.13 SendEmail() Function Syntax: SendEmail(cSMTPServer,cEmail,cPassword,cSender,cReceiver,cCC,cTitle,cContent) Example: See "Send email..." + nl sendemail("smtp://smtp.gmail.com:587", "email@gmail.com", "password", "email@gmail.com", "somebody@yahoo.com", "somebodyelse@yahoo.com", "Sending email from Ring", "Hello How are you? Are you fine? Thank you! Greetings, Mahmoud") see "Done.." + nl 33.12. Download() Function 166
188.
CHAPTER THIRTYFOUR OBJECT ORIENTED PROGRAMMING(OOP) In this chapter we are going to learn how to use the Object-Oriented programming paradigm inside the Ring program- ming language. We will learn about • Classes and Objects • Access Objects Using Braces • Composition • Setter and Getter • Private Attributes and Methods • Operator Overloading • Inheritance • Dynamic Attributes • Packages • Printing Objects • Find() and List of Objects • Sort() and List of Objects • Using Self.Attribute and Self.Method() • Using This.Attribute and This.Method() 34.1 Classes and Objects We can define new classes using the next syntax Syntax: Class <Class Name> [From <Parent Class Name>] [Attributes] [Methods] [Private [Attributes] [Methods] ] 167
189.
Ring Documentation, Release1.2 And we can create objects using the next syntax Syntax: New <Object Name> [ (init method parameters) ] | [ { access object data and methods } ] ---> Object Example: New point { x=10 y=20 z=30 print() } Class Point x y z func print see x + nl + y + nl + z + nl Note: We can use { } to access object data and methods. Tip: we can declare the class attributes directly after the class name. Output: 10 20 30 We can rewrite the same program in another style New point # create new object using the point class { # access the new object attributes and methods x = 10 # set the x attribute to 10 y = 20 # set the y attribute to 20 z = 30 # set the z attribute to 30 print() # call the print method } # end of object access Class Point # define the Point class x y z # the class contains three attributes x, y & z func print # define the print method see x + nl + # print the x attribute y + nl + # print the y attribute z + nl # print the z attribute Also we can write the same program in another way P1 = New Point P1.x = 10 P1.y = 20 P1.z = 30 P1.Print() Class Point x y z func print see x + nl + y + nl + z + nl Note: we can use the dot operator after the object name to access object members. Also we can write the same program in another way new point { print() } Class Point x = 10 y = 20 z = 30 func print see x + nl + y + nl + z + nl 34.1. Classes and Objects 168
190.
Ring Documentation, Release1.2 Note: we can set the default values for the class attributes when we declare them. Also we can write the same program in another way new point(10,20,30) Class Point x y z func init p1,p2,p3 x=p1 y=p2 z=p3 print() func print see x + nl + y + nl + z + nl Note: we can call the init method directly using () when we create new objects Also we can write the same program in another way new point( [ :x = 10 , :y = 20 , :z = 30 ] ) Class Point x y z func init aPara x = aPara[:x] y = aPara[:y] z = aPara[:z] print() func print see x + nl + y + nl + z + nl Tip: using Hash for passing method parameters enable us to create optional parameters and change the order of parameters when adding them to the Hash. 34.2 Access Objects Using Braces We can access the object at any time using braces { } Inside the braces we can use the object attributes and methods directly This can be done when we create the object using the New keyword or at any time using the next syntax ObjectName { access object data and methods } Example: See "Creating the Object" + nl o1 = new Point See "Using the Object" + nl o1 { x=5 y=15 z=25 print() } Class Point x y z func print see x + nl + y + nl + z We can use braces to access objects when we call functions or methods Example: o1 = new Point print( o1 { x=10 y=20 z=30 } ) func print object see object.x + nl + object.y + nl + 34.2. Access Objects Using Braces 169
191.
Ring Documentation, Release1.2 object.z Class Point x y z We can mix between using braces and the dot operator to access the object in the same expression. Example: o1 = new Point O1 { x=10 y=20 z=30 }.print() Class Point x y z func print see x + nl + y + nl + z 34.3 Composition The object may contains other objects as attributes. Using braces to access objects can be nested. Example: R1 = New Rectangle { Name = "Rectangle 1" P1 { X = 10 Y = 20 } P2 { X = 200 Y = 300 } Color = "Blue" } see "Name : " + R1.Name + nl + "Color: " + R1.Color + nl + "P1 : (" + R1.P1.X + "," + R1.P1.Y + ")" + nl + "P2 : (" + R1.P2.X + "," + R1.P2.Y + ")" Class Rectangle name color p1 = new Point p2 = new Point Class Point x y Output: 34.3. Composition 170
192.
Ring Documentation, Release1.2 Name : Rectangle 1 Color: Blue P1 : (10,20) P2 : (200,300) 34.4 Setter and Getter We can define methods to be used when we set and get object attributes. Syntax: Class ClassName AttributeName ... Func SetAttributeName ... Func GetAttributeName ... Example: o1 = new person o1.name = "Mahmoud" see o1.name + nl o1 { name = "Ahmed" see name } Class Person name family = "Fayed" func setname value see "Message from SetName() Function!" + nl name = value + " " + family func getname see "Message from GetName() Function!" + nl return "Mr. " + name Output: Message from SetName() Function! Message from GetName() Function! Mr. Mahmoud Fayed Message from SetName() Function! Message from GetName() Function! Mr. Ahmed Fayed 34.5 Private Attributes and Methods We can define private attributes and methods after the keyword private inside the class body 34.4. Setter and Getter 171
193.
Ring Documentation, Release1.2 Example: o1 = new person { name = "Test" age = 20 print() o1.printsalary() } try see o1.salary catch see cCatchError + nl done try o1.increasesalary(1000) catch see cCatchError + nl done Class Person name age func print see "Name : " + name + nl + "Age : " + age + nl func printsalary see "Salary : " + salary + nl private salary = 15000 func increasesalary x salary += x Output: Name : Test Age : 20 Salary : 15000 Error (R27) : Using private attribute from outside the class : salary Error (R26) : Calling private method from outside the class : increasesalary 34.6 Operator Overloading We can add the operator method to our class to enable using operators with the class objects. Syntax: Class ClassName ... 34.6. Operator Overloading 172
194.
Ring Documentation, Release1.2 Func operator cOperator,Para ... The function operator takes two paramters, the first represent the operator and the second represent the second param- eter after the operator. Example: o1 = new point { x = 10 y = 10 print("P1 : ") } o2 = new point { x = 20 y = 40 print("P2 : ") } o3 = o1 + o2 o3.print("P1+P2 : ") class point x y func operator cOperator,Para result = new point switch cOperator on "+" result.x = x + Para.x result.y = y + Para.y on "-" result.x = x - Para.x result.y = y - Para.y off return result func print cPoint see cPoint + "X : " + x + " Y : " + y + nl Output: P1 : X : 10 Y : 10 P2 : X : 20 Y : 40 P1+P2 : X : 30 Y : 50 34.7 Inheritance We can create class from another class in the class definition using the keyword from. Syntax: Class <Class Name> [From <Parent Class Name>] We can call a method in the parent class from the child class using the super object. Syntax: func methodname ... super.methodname() ... Example: 34.7. Inheritance 173
195.
Ring Documentation, Release1.2 Func main e1 = new Employee { Name = "test" age = 20 job = "programmer" salary = 20000000 print() } Class Human Name Age func print see "Name : " + name + nl + "Age : " + age + nl Class Employee from Human Job Salary func print super.print() see "Job : " + job + nl + "Salary : " + salary + nl Output: Name : test Age : 20 Job : programmer Salary : 20000000 34.8 Dynamic Attributes We can write instructions after the class name to be executed when we create new objects Example: o1 = new dynamicClass see o1.var5 + nl # output 5 Class DynamicClass for x = 1 to 10 cStr = "var" + x + " = " + x eval(cStr) next Tip: in the previous example var1, var2, ..., var10 will be defined as attributes. Tip: The problem with the previous example is that x and cStr will be defined as attributes too! Note: we can write class definitions inside a string then using eval() we can execute the string to define the classes 34.9 Packages We can create a package (a group of classes under a common name) using the next syntax 34.8. Dynamic Attributes 174
196.
Ring Documentation, Release1.2 package PackageName Class Class1 ... Class Class2 ... Class Class3 ... ... Example o1 = new System.output.console o1.print("Hello World") Package System.Output Class Console Func Print cText see cText + nl Note: we can use the dot operator as part of the package name Instead of typing the long name PackageName.ClassName we can use the import command When we import a package, we can use any class inside this package directly. Example import system.output o1 = new console { print("Hello World") } Package System.Output Class Console Func Print cText see cText + nl 34.10 Printing Objects We can print the object state (attributes and values) using the see command. Example: see new point { x=10 y=20 z=30 } class point x y z Output: x: 10.000000 y: 20.000000 z: 30.000000 34.11 Find() and List of Objects We can use the find() function to search inside a list of objects. Syntax: 34.10. Printing Objects 175
197.
Ring Documentation, Release1.2 Find(List,ItemValue,nColumn,cAttribute) ---> Item Index Example: myList1 = [new Company {position=3 name="Mahmoud" symbol="MHD"}, new Company {position=2 name="Bert" symbol="BRT"}, new Company {position=1 name="Ring" symbol="RNG"} ] see find(mylist1,"Bert",1,"name") + nl see find(mylist1,"Ring",1,"name") + nl see find(mylist1,"Mahmoud",1,"name") + nl see find(mylist1,"RNG",1,"symbol") + nl see find(mylist1,"MHD",1,"symbol") + nl see find(mylist1,"BRT",1,"symbol") + nl see find(mylist1,3,1,"position") + nl see find(mylist1,1,1,"position") + nl see "Other" + nl see find(mylist1,"test",1,"name") + nl see find(mylist1,"test",0,"name") + nl see find(mylist1,"test",5,"name") + nl class company position name symbol Output: 2 3 1 3 1 2 1 3 Other 0 0 0 34.12 Sort() and list of objects We can sort a list of objects based on an object attribute using the Sort() function. Syntax: Sort(List,nColumn,cAttribute) ---> Sorted List based on Object Attribute Example: myList1 = [ new Company {position=3 name="Mahmoud" symbol="MHD"}, new Company {position=2 name="Bert" symbol="BRT"}, new Company {position=8 name="Charlie" symbol="CHR"}, new Company {position=6 name="Easy" symbol="FEAS"}, new Company {position=7 name="Fox" symbol="EFOX"}, new Company {position=5 name="Dog" symbol="GDOG"}, new Company {position=4 name="George" symbol="DGRG"}, 34.12. Sort() and list of objects 176
198.
Ring Documentation, Release1.2 new Company {position=1 name="Ring" symbol="RNG"} ] see sort(mylist1,1,"name") see copy("*",70) + nl see sort(mylist1,1,"symbol") see copy("*",70) + nl see sort(mylist1,1,"position") class company position name symbol Output: position: 2.000000 name: Bert symbol: BRT position: 8.000000 name: Charlie symbol: CHR position: 5.000000 name: Dog symbol: GDOG position: 6.000000 name: Easy symbol: FEAS position: 7.000000 name: Fox symbol: EFOX position: 4.000000 name: George symbol: DGRG position: 3.000000 name: Mahmoud symbol: MHD position: 1.000000 name: Ring symbol: RNG ********************************************************************** position: 2.000000 name: Bert symbol: BRT position: 8.000000 name: Charlie symbol: CHR position: 4.000000 name: George symbol: DGRG position: 7.000000 name: Fox symbol: EFOX position: 6.000000 name: Easy symbol: FEAS position: 5.000000 name: Dog symbol: GDOG position: 3.000000 name: Mahmoud 34.12. Sort() and list of objects 177
199.
Ring Documentation, Release1.2 symbol: MHD position: 1.000000 name: Ring symbol: RNG ********************************************************************** position: 1.000000 name: Ring symbol: RNG position: 2.000000 name: Bert symbol: BRT position: 3.000000 name: Mahmoud symbol: MHD position: 4.000000 name: George symbol: DGRG position: 5.000000 name: Dog symbol: GDOG position: 6.000000 name: Easy symbol: FEAS position: 7.000000 name: Fox symbol: EFOX position: 8.000000 name: Charlie symbol: CHR 34.13 Using Self.Attribute and Self.Method() Inside the class region (After the class name and before any method) and the class methods we can use self.attribute and self.method() Class Point self.x = 10 self.y = 20 self.z = 30 func print see self.x + nl + self.y + nl + self.z + nl Note: using self.attribute in the class region to define the class attribute protect the class attributes from conflict with global variables. Tip: if you typed the class attributes with self.attribute and there are a global variable with the same name it will be used and the attribute will not be defined. Check the “Scope Rules” chapter to know about the conflict between the global variable name and the attribute name Whay this may happens? Because • Because in the class region we can access global variables. 34.13. Using Self.Attribute and Self.Method() 178
200.
Ring Documentation, Release1.2 • Before defining any variable, Ring try to find the variable and use it if it’s found. Note: Try to avoid the global variables, use the main function and start their names with $ Tip: In large programs protect your classes and define their members using self.attribute 34.14 Using This.Attribute and This.Method() Inside class methods we have access to the object scope directly. we don’t need to use Self.attribute or Self.method to read/write attribute and call methods. But we can use braces {} while we are inside methods to access another object, In this case the current object scope will be changed while we are inside the brace. How we can get access to our class attributes and methods while we are inside braces? This can be done using This.Attribute and This.Method() Example: new point class point x=10 y=20 z=30 print() func print new UI { display(this.x,this.y,this.z) } Class UI func display x,y,z see x + nl + y + nl + z + nl 34.14. Using This.Attribute and This.Method() 179
201.
CHAPTER THIRTYFIVE FUNCTIONAL PROGRAMMING In previouschapters we learned about Functions and Recursion. In this chapter we are going to learn about more Functional Programming (FP) concepts like • Pure Functions • First-class functions • Higher-order functions • Anonymous and nested functions. • Equality of functions 35.1 Pure Functions We can create pure functions (functions that doesn’t change the state) by the help of the assignment operator to copy variables (Lists & Objects) by value to create new variables instead of working on the original data that are passed to the function by reference. Example: Func Main aList = [1,2,3,4,5] aList2 = square(aList) see "aList" + nl see aList see "aList2" + nl see aList2 Func Square aPara a1 = aPara # copy the list for x in a1 x *= x next return a1 # return new list Output: aList 1 2 3 4 5 180
202.
Ring Documentation, Release1.2 aList2 1 4 9 16 25 35.2 First-class Functions Functions inside the Ring programming language are first-class citizens, you can pass functions as parameters, return them as value or store them in variables. We can pass/return the function by typing the function name as literal like “FunctionName” or :FunctionName for example. We can pass/return functions using the variable that contains the function name. We can call function from variables contains the function name using the Call command Syntax: Call Variable([Parameters]) Example: Func Main see "before test2()" + nl f = Test2(:Test) see "after test2()" + nl call f() Func Test see "Message from test!" + nl Func Test2 f1 call f1() See "Message from test2!" + nl return f1 Output: before test2() Message from test! Message from test2! after test2() Message from test! 35.3 Higher-order Functions Higher-order functions are the functions that takes other functions as parameters. Example: Func Main times(5,:test) 35.2. First-class Functions 181
203.
Ring Documentation, Release1.2 Func Test see "Message from the test function!" + nl Func Times nCount,F for x = 1 to nCount Call F() next Output: Message from the test function! Message from the test function! Message from the test function! Message from the test function! Message from the test function! 35.4 Anonymous and Nested Functions Anonymous Functions are functions without names that can be passed as parameters to other functions or stored in variables. Syntax: Func [Parameters] { [statements] } Example: test( func x,y { see "hello" + nl see "Sum : " + (x+y) + nl } ) new great { f1() } times(3, func { see "hello world" + nl } ) func test x call x(3,3) see "wow!" + nl func times n,x for t=1 to n call x() next Class great func f1 f2( func { see "Message from f1" + nl } ) func f2 x call x() Output: hello Sum : 6 35.4. Anonymous and Nested Functions 182
204.
Ring Documentation, Release1.2 wow! Message from f1 hello world hello world hello world Example: Func Main aList = [1,2,3,4] Map (aList , func x { return x*x } ) see aList aList = [4,9,14,25] Map(aList, :myfilter ) see aList aList = [11,12,13,14] Map (aList , func x { if x%2=0 return "even" else return "odd" ok }) see aList Func myfilter x if x = 9 return "True" else return "False" ok Func Map aList,cFunc for x in aList x = call cFunc(x) next Output: 1 4 9 16 False True False False odd even odd even 35.5 Equality of functions We can test if function = function or not using the ‘=’ or ‘!=’ operators 35.5. Equality of functions 183
205.
Ring Documentation, Release1.2 Example: f1 = func { see "hello" + nl } f2 = func { see "how are you?" + nl } f3 = f1 call f1() call f2() call f3() see (f1 = f2) + nl see (f2 = f3) + nl see (f1 = f3) + nl Output: hello how are you? hello 0 0 1 35.5. Equality of functions 184
206.
CHAPTER THIRTYSIX REFLECTION AND META-PROGRAMMING Sincethe Ring programming language is a dynamic language, we can get answers about the program code and we can modify our code during the runtime. In this chapter we will learn about this and the available functions to use. 36.1 locals() Function We can get a list of variables names in the current scope using the locals() function. Syntax: locals() --> a list contains the variables names in the current scope Example: test("hello") func test cMsg see cMsg + nl x = 10 y = 20 z = 30 see locals() Output: hello cmsg x y z 36.2 globals() Function We can get a list of variables names in the global scope using the globals() function. Syntax: 185
207.
Ring Documentation, Release1.2 globals() --> a list contains variables names in the global scope Example: x=10 y=20 z=30 test() func test see "message from test()" + nl + "Global Variables:" + nl see globals() Output: message from test() Global Variables: x y z 36.3 functions() Function We can get a list of functions names written in the Ring language using the functions() function. Syntax: functions() --> a list contains functions names Example: see functions() func f1 see "f1" + nl func f2 see "f2" + nl func f3 see "f3" + nl Output: f1 f2 f3 36.4 cfunctions() Function We can get a list of functions names written in the C language using the cfunctions() function. Syntax: cfunctions() --> a list contains functions names Example: 36.3. functions() Function 186
208.
Ring Documentation, Release1.2 aList = cfunctions() See "Count : " + len(aList) + nl for x in aList see x + "()" + nl next Output: Count : 217 len() add() del() get() clock() ... Note: The complete list is removed from the previous output. 36.5 islocal() Function We can check if a variable is defined in the local scope or not using the islocal() function. Syntax: islocal(cVariableName) --> returns 1 if the variable is defined in the local scope returns 0 if the variable is not defined in the local scope Example: test() func test x=10 y=20 see islocal("x") + nl + islocal("y") + nl + islocal("z") + nl Output: 1 1 0 36.6 isglobal() Function We can check if a variable is defined in the global scope or not using the isglobal() function. Syntax: isglobal(cVariableName) --> returns 1 if the variable is defined in the global scope returns 0 if the variable is not defined in the global scope Example: 36.5. islocal() Function 187
209.
Ring Documentation, Release1.2 x=10 y=20 test() func test see isglobal("x") + nl + isglobal("y") + nl + isglobal("z") + nl Output: 1 1 0 36.7 isfunction() Function We can check if a Ring function is defined or not using the isfunction() function. Syntax: isfunction(cFunctionName) --> returns 1 if the Ring function is defined returns 0 if the Ring function is not defined Example: see isfunction("f1") + nl + isfunction("f2") + nl + isfunction("f3") + nl func f1 see "message from f1()" + nl func f2 see "message from f2()" + nl Output: 1 1 0 36.8 iscfunction() Function We can check if a C function is defined or not using the iscfunction() function. Syntax: iscfunction(cFunctionName) --> returns 1 if the C function is defined returns 0 if the C function is not defined Example: see iscfunction("len") + nl + iscfunction("add") + nl + iscfunction("test") + nl 36.7. isfunction() Function 188
210.
Ring Documentation, Release1.2 Output: 1 1 0 36.9 packages() Function We can get a list of packages names using the packages() function. Syntax: packages() --> a list contains packages names Example: See packages() Package Package1 Class class1 Func f1 Package Package2 Class class1 Func f1 Package Package3 Class class1 Func f1 Package Package4 Class class1 Func f1 Output: package1 package2 package3 package4 36.10 ispackage() Function We can check if a package is defined or not using the ispackage() function. Syntax: ispackage(cPackageName) --> returns 1 if the Package is defined returns 0 if the Package is not defined Example: See ispackage("package1") + nl + ispackage("package4") + nl + ispackage("package5") + nl + ispackage("package3") + nl 36.9. packages() Function 189
211.
Ring Documentation, Release1.2 Package Package1 Class class1 Func f1 Package Package2 Class class1 Func f1 Package Package3 Class class1 Func f1 Package Package4 Class class1 Func f1 Output: 1 1 0 1 36.11 classes() Function We can get a list of classes names using the classes() function. Syntax: classes() --> a list contains classes names Example: See classes() Class class1 Func f1 Class class2 Func f1 Class class3 Func f1 Output: class1 class2 class3 36.12 isclass() Function We can check if a class is defined or not using the isclass() function. Syntax: 36.11. classes() Function 190
212.
Ring Documentation, Release1.2 isclass(cClassName) --> returns 1 if the Class is defined returns 0 if the Class is not defined Example: see isclass("class4") + nl + isclass("class3") + nl + isclass("class2") + nl Class class1 func f1 class class2 func f1 class class3 func f1 Output: 0 1 1 36.13 packageclasses() Function We can get a list of classes names inside a package using the packageclasses() function. Syntax: packageclasses(cPackageName) --> a list contains classes names inside the package Example: see "classes in Package1" + nl see packageclasses("Package1") see "classes in Package2" + nl see packageclasses("Package2") Package Package1 Class class1 Func f1 Package Package2 Class class1 Func f1 Class class2 Func f1 Class class3 func f1 Output: classes in Package1 class1 classes in Package2 class1 36.13. packageclasses() Function 191
213.
Ring Documentation, Release1.2 class2 class3 36.14 ispackageclass() Function We can check if a class is defined inside package or not using the ispackageclass() function. Syntax: ispackageclass(cPackageName,cClassName) --> returns 1 if the Class is defined returns 0 if the Class is not defined Example: see ispackageclass("package1","class1") + nl + ispackageclass("package1","class2") + nl + ispackageclass("package2","class1") + nl + ispackageclass("package2","class2") + nl Package Package1 Class class1 Func f1 Package Package2 Class class1 Func f1 Class class2 Func f1 Class class3 func f1 Output: 1 0 1 1 36.15 classname() Function We can know the class name of an object using the classname() function Syntax: classname(object) --> Returns the object class name Example: o1 = new point o2 = new rect see classname(o1) + nl # print point see classname(o2) + nl # print rect class point class rect 36.14. ispackageclass() Function 192
214.
Ring Documentation, Release1.2 36.16 objectid() Function We can know the object id using the objectid() function Syntax: objectid(object) --> Returns the object id Example: o1 = new point see objectid(o1) + nl test(o1) func test v see objectid(v) + nl Class point x y z Output: 021B5808 021B5808 36.17 isobject() Function We can check the variable to know if it’s an object or not using the isobject() function Syntax: isobject(variable) --> Returns True if it's an object, False if it's not 36.18 attributes() Function We can get the object attributes using the attributes() function Syntax: attributes(object) --> Returns a list contains the object attributes Example: o1 = new point aList = attributes(o1) # we can use see attributes(o1) for t in aList see t next # print xyz Class Point x y z 36.19 methods() Function We can get the object methods using the methods() function Syntax: 36.16. objectid() Function 193
215.
Ring Documentation, Release1.2 methods(object) --> Returns a list contains the object methods Example: o1 = new test aList = methods(o1) for x in aList cCode = "o1."+x+"()" eval(cCode) next Class Test func f1 see "hello from f1" + nl func f2 see "hello from f2" + nl func f3 see "hello from f3" + nl func f4 see "hello from f4" + nl Output: hello from f1 hello from f2 hello from f3 hello from f4 36.20 isattribute() Function We can test if the object contains an attribute or not using the isattribute() function Syntax: isattribute(object,cAttributeName) --> Returns True if the object contains the attribute Example: o1 = new point see isattribute(o1,"x") + nl # print 1 see isattribute(o1,"t") + nl # print 0 see isattribute(o1,"y") + nl # print 1 see isattribute(o1,"z") + nl # print 1 class point x y z 36.21 isprivateattribute() Function We can test if the object contains a private attribute or not using the isprivateattribute() function Syntax: 36.20. isattribute() Function 194
216.
Ring Documentation, Release1.2 isprivateattribute(object,cAttributeName) --> Returns True if the object contains the private attribute Example: o1 = new person see isprivateattribute(o1,"name") + nl + isprivateattribute(o1,"address") + nl + isprivateattribute(o1,"phone") + nl + isprivateattribute(o1,"job") + nl + isprivateattribute(o1,"salary") Class Person name address phone private job salary Output: 0 0 0 1 1 36.22 ismethod() Function We can test if the object class contains a method or not using the ismethod() function Syntax: ismethod(object,cMethodName) --> Returns True if the object class contains the method Example: o1 = new point see ismethod(o1,"print") + nl # print 1 mylist = [] mylist + new point see ismethod(mylist[1],"print") + nl # print 1 class point x y z func print see x + nl + y + nl + z + nl 36.23 isprivatemethod() Function We can test if the object class contains a private method or not using the isprivatemethod() function Syntax: 36.22. ismethod() Function 195
217.
Ring Documentation, Release1.2 isprivatemethod(object,cMethodName) --> Returns True if the object class contains the private method Example: o1 = new Test see isprivatemethod(o1,"f1") + nl + isprivatemethod(o1,"f2") Class Test func f1 see "message from f1()" + nl private func f2 see "message from f2()" + nl Output: 0 1 36.24 addattribute() Function We can add an attribute (or a group of attributes) to the object state (not the class) using the addattribute() function Syntax: AddAttribute(object,cAttributeName|aAttributesList) Example(1): see new point {x=10 y=20 z=30} Class Point AddAttribute(self,["x","y","z"]) Example(2): o1 = new point addattribute(o1,"x") addattribute(o1,"y") addattribute(o1,"z") see o1 {x=10 y=20 z=30} class point Output: x: 10.000000 y: 20.000000 z: 30.000000 36.25 addmethod() Function We can add a method to the object class using the addmethod() function This method can be used with any object from the same class. 36.24. addattribute() Function 196
218.
Ring Documentation, Release1.2 Syntax: AddMethod(Object,cNewMethodName,cMethodName|AnonymousFunction) Example: o1 = new point { x=10 y=20 z=30 } addmethod(o1,"print", func { see x + nl + y + nl + z + nl } ) o1.print() Class point x y z Output: 10 20 30 Instead of using anonymous function to add new method to the class, we can use the function name Example: o1 = new point { x=10 y=20 z=30 } myfunc = func { see x + nl + y + nl + z + nl } addmethod(o1,"print", myfunc ) addmethod(o1,"display", myfunc ) addmethod(o1,"show", myfunc ) o1.print() o1.display() o1.show() Class point x y z Output: 10 20 30 10 20 30 10 20 30 Since we add the method to the class, any object from that class can use this method Example: o1 = new point { x=10 y=20 z=30 } o2 = new point { x=100 y=200 z=300 } o3 = new point { x=50 y=150 z=250 } addmethod(o1,"print", func { see x + nl + y + nl + z + nl } ) 36.25. addmethod() Function 197
219.
Ring Documentation, Release1.2 o1.print() o2.print() o3.print() Class point x y z Output: 10 20 30 100 200 300 50 150 250 36.26 getattribute() function We can get the object attribute value using the getattribute() function Syntax: GetAttribute(oObject,cAttributeName) ---> Attribute Value Example: o1 = new point see getattribute(o1,"name") + nl + getattribute(o1,"x") + nl + getattribute(o1,"y") + nl + getattribute(o1,"z") + nl Class Point x=10 y=20 z=30 name = "3D-Point" Output: 3D-Point 10 20 30 Example: We can Find a Class List Member using GetAttribute() using a function findclass() The Find uses the member name, rather than the column number myList = [new Company {position=3 name="Mahmoud" symbol="MHD"}, new Company {position=2 name="Bert" symbol="BRT"}, new Company {position=1 name="Ring" symbol="RNG"} ] 36.26. getattribute() function 198
220.
Ring Documentation, Release1.2 see myList see nl +"=====================" + nl + nl for i = 1 to len(myList) see "Pos: "+ i +" | "+ myList[i].position +" | "+ myList[i].name + " | "+ myList[i].symbol +" | "+ nl next See findclass(myList, "MHD", "symbol") +nl ### Specify Member class name ###--------------------------------------- func findclass classList, cValue, classMember See nl + "FindClass: " +" "+ cValue + nl + nl for i = 1 to len(classList) result = getattribute( classList[i], classMember ) See "Result-Attr: " + i +" "+ result +nl if result = cValue j = i ok next return j ###-------------------------------------- class company position name symbol Output: Pos: 1 | 3 | Mahmoud | MHD | Pos: 2 | 2 | Bert | BRT | Pos: 3 | 1 | Ring | RNG | FindClass: MHD Result-Attr: 1 MHD Result-Attr: 2 BRT Result-Attr: 3 RNG 1 36.27 setattribute() function We can set the object attribute value using the setattribute() function Syntax: SetAttribute(oObject,cAttributeName,Value) Example: o1 = new person setattribute(o1,"cName","Mahmoud") 36.27. setattribute() function 199
221.
Ring Documentation, Release1.2 setattribute(o1,"nSalary",1000000) setattribute(o1,"aColors",["white","blue","yellow"]) see o1 see o1.aColors Class Person cName nSalary aColors Output: cname: Mahmoud nsalary: 1000000.000000 acolors: List... white blue yellow 36.28 mergemethods() Function We can share methods between classes without inheritance using the MergeMethods() function This function merge class methods to another class. Syntax: MergeMethods(cClassNameDestination,cClassNameSource) Example: mergemethods("count","share") mergemethods("count2","share") o1 = new count { test() } o1 = new count2 { test() } Class Share func one see "one" + nl func two see "two" + nl func three see "three" + nl Class Display Func printline see copy("*",20) + nl Class Count from Display Func test printline() one() two() three() printline() 36.28. mergemethods() Function 200
222.
Ring Documentation, Release1.2 Class Count2 from Display Func test three() two() one() printline() Output: ******************** one two three ******************** three two one ******************** 36.28. mergemethods() Function 201
223.
CHAPTER THIRTYSEVEN STDLIB FUNCTIONS In thischapter we are going to learn about functions in the stdlib.ring 37.1 puts() function print the value then print new line (nl) Syntax: puts(expr) Example: Load "stdlib.ring" Puts("Hello, World!") 37.2 print() function print string - support n,t and r Also we can use #{variable_name} to insert variables values. Syntax: print(string) Example: Load "stdlib.ring" print("nHello, WorldnnHow are you? tt I'm fine!n") x=10 y=20 print("nx value = #{x} , y value = #{y} n") 37.3 getstring() function Get input from the keyboard - return value as string getstring() ---> string 202
224.
Ring Documentation, Release1.2 37.4 getnumber() function Get input from the keyboard - return value as number getnumber() ---> number 37.5 apppath() function Get the path of the application folder Syntax: AppPath() ---> The path as String Example: Load "stdlib.ring" # Application Path Puts("Test AppPath()") See AppPath() + nl 37.6 value() function create a copy from a list or object Syntax: value(List) ---> new list Example: Load "stdlib.ring" aList = 1:10 del(value(aList),1) # delete first item see aList # print numbers from 1 to 10 37.7 times() function Execute a Function nCount times Syntax: Times(nCount,function) Example: Load "stdlib.ring" Puts("Test Times()") Times ( 3 , func { see "Hello, World!" + nl } ) 37.4. getnumber() function 203
225.
Ring Documentation, Release1.2 37.8 map() function Execute a Function on each list item Syntax: Map(alist,function) Example: Load "stdlib.ring" Puts("Test Map()") See Map( 1:10, func x { return x*x } ) 37.9 filter() function Execute a Function on each list item to filter items Syntax: Filter(alist,function) Example: Load "stdlib.ring" Puts("Test Filter()") See Filter( 1:10 , func x { if x <= 5 return true else return false ok } ) 37.10 split() function Convert string words to list items Syntax: Split(cstring,delimiter) Example: Load "stdlib.ring" Puts("Test Split()") See Split("one two three four five"," ") 37.11 newlist() function Create a two dimensional list Syntax: NewList(nRows,nColumns) ---> new list Example: 37.8. map() function 204
226.
Ring Documentation, Release1.2 Load "stdlib.ring" Puts("Test Newlist()") a1 = 3 a2 = 5 chrArray = newlist(a1,a2) numArray = newlist(a1,a2) chrArray[1][1] = "Hello" numArray[1][1] = 987.2 See chrArray[1][1] + nl See numArray[1][1] + nl 37.12 capitalized() function Return a copy of a string with the first letter capitalized Syntax: Capitalized(string) ---> string Example: Load "stdlib.ring" Puts("Test Capitalized()") See capitalized("welcome to the Ring Programming Language") 37.13 isspecial() function Check whether a character is special or not Syntax: IsSpecial(char) ---> True/False Example: Load "stdlib.ring" Puts("Test Isspecial()") See "Isspecial = " + isSpecial("%") + nl 37.14 isvowel() function Check whether a character is vowel or not Syntax: IsVowel(char) ---> True/False Example: 37.12. capitalized() function 205
227.
Ring Documentation, Release1.2 Load "stdlib.ring" Puts("Test Isvowel()") See "Isvowel = " + isVowel("c") + nl 37.15 linecount() function Return the lines count in a text file. Syntax: LineCount(cFileName) ---> Lines Count as number Example: Load "stdlib.ring" Puts("Test Linecount()") See "the number of lines = " + lineCount("test.ring") 37.16 factorial() function Return the factorial of a number Syntax: Factorial(number) ---> number Example: Load "stdlib.ring" Puts("Test Factorial()") see "6 factorial is : " + Factorial(6) 37.17 fibonacci() function Return the fibonacci number Syntax: Fibonacci(number) ---> number Example: Load "stdlib.ring" Puts("Test Fibonacci()") see "6 Fibonacci is : " + Fibonacci(6) 37.15. linecount() function 206
228.
Ring Documentation, Release1.2 37.18 isprime() function Check whether a number is prime or not Syntax: isprime(number) ---> Number Example: Load "stdlib.ring" Puts("Test Isprime()") if isPrime(16) see "16 is a prime number" else see "16 is not a prime number" ok 37.19 sign() function Returns an integer value indicating the sign of a number. Syntax: Sign(number) ---> number ( -1 = negative , 0 , 1 (positive) ) Example: Load "stdlib.ring" Puts("Test Sign()") see "sign of 12 is = " + sign(12) + nl 37.20 list2file() function Write list items to text file (each item in new line). Syntax: List2File(aList,cFileName) Example: Load "stdlib.ring" # Test List2File Puts("Test List2File()") list2file(1:100,"myfile.txt") 37.21 file2list() function Read text file and convert lines to list items Syntax: 37.18. isprime() function 207
229.
Ring Documentation, Release1.2 File2List(cFileName) ---> List Example: Load "stdlib.ring" # Test File2List Puts("Test File2List()") see len(file2list("myfile.txt")) 37.22 startswith() function Returns true if the given string starts with the specified substring. Leading white spaces are ignored. Syntax: StartsWith(string, substring) ---> True/False Example: Load "stdlib.ring" Puts("Test Startswith()") see Startswith("CalmoSoft", "Calmo") + nl 37.23 endswith() function Returns true if the given string ends with the specified substring. Trailing white spaces are ignored. Syntax: Endswith(string, substring) ---> True/False Example: Load "stdlib.ring" Puts("Test Endswith()") see endsWith("CalmoSoft", "Soft") + nl 37.24 gcd() function Finding of the greatest common divisor of two integers. Syntax: Gcd(number,number) ---> number Example: 37.22. startswith() function 208
230.
Ring Documentation, Release1.2 Load "stdlib.ring" Puts("Test Gcd()") see gcd (24, 32) + nl 37.25 lcm() function Compute the least common multiple of two integers. Syntax: lcm(number,number) ---> number Example: Load "stdlib.ring" Puts("Test Lcm()") see Lcm(24,36) + nl 37.26 sumlist() function Compute the sum of a list of integers. Syntax: sumlist(list) ---> number Example: Load "stdlib.ring" Puts("Test Sumlist()") aList = [1,2,3,4,5] see Sumlist(aList) + nl 37.27 prodlist() function Compute the product of a list of integers. Syntax: prodlist(list) ---> number Example: Load "stdlib.ring" Puts("Test Prodlist()") aList = [1,2,3,4,5] see Prodlist(aList) + nl 37.25. lcm() function 209
231.
Ring Documentation, Release1.2 37.28 evenorodd() function Test whether an integer is even or odd. Result of test (1=odd 2=even). Syntax: evenorodd(number) ---> 1 (odd) or 2 (even) Example: Load "stdlib.ring" Puts("Test Evenorodd()") nr = 17 see Evenorodd(nr) + nl 37.29 factors() function Compute the factors of a positive integer. Syntax: factors(list) ---> list Example: Load "stdlib.ring" Puts("Test Factors()") n = 45 aList = factors(n) see "Factors of " + n + " = " for i = 1 to len(aList) see "" + aList[i] + " " next 37.30 palindrome() function Check if a sequence of characters is a palindrome or not. Syntax: Palindrome(String) ---> True/False Example: Load "stdlib.ring" Puts("Test Palindrome()") cString = "radar" see Palindrome(cString) 37.28. evenorodd() function 210
232.
Ring Documentation, Release1.2 37.31 isleapyear() function Check whether a given year is a leap year in the Gregorian calendar. Syntax: Isleapyear(number) ---> True/False Example: Load "stdlib.ring" Puts("Test Isleapyear()") year = 2016 if Isleapyear(year) see "" + year + " is a leap year." else see "" + year + " is not a leap year." ok 37.32 binarydigits() function Compute the sequence of binary digits for a given non-negative integer. Syntax: binarydigits(number) ---> string Example: Load "stdlib.ring" Puts("Test Binarydigits()") b = 35 see "Binary digits of " + b + " = " + Binarydigits(b) 37.33 matrixmulti() function Multiply two matrices together. Syntax: Matrixmulti(List,List) ---> List Example: Load "stdlib.ring" # Multiply two matrices together. Puts("Test Matrixmulti()") A = [[1,2,3], [4,5,6], [7,8,9]] B = [[1,0,0], [0,1,0], [0,0,1]] see Matrixmulti(A, B) 37.34 matrixtrans() function Transpose an arbitrarily sized rectangular Matrix. 37.31. isleapyear() function 211
233.
Ring Documentation, Release1.2 Syntax: Matrixtrans(List) ---> List Example: Load "stdlib.ring" # Transpose an arbitrarily sized rectangular Matrix. Puts("Test Matrixtrans()") matrix = [[78,19,30,12,36], [49,10,65,42,50], [30,93,24,78,10], [39,68,27,64,29]] see Matrixtrans(matrix) 37.35 dayofweek() function Return the day of the week of given date. (yyyy-mm-dd) Syntax: dayofweek(string) ---> string Example: Load "stdlib.ring" # Return the day of the week of given date. Puts("Test Dayofweek()") date = "2016-04-24" see "Data : " + date + " - Day : " + Dayofweek(date) + nl 37.36 permutation() function Generates all permutations of n different numerals. Syntax: permutation(list) Example: Load "stdlib.ring" # Generates all permutations of n different numerals Puts("Test Permutation()") list = [1, 2, 3, 4] for perm = 1 to 24 for i = 1 to len(list) see list[i] + " " next see nl Permutation(list) next 37.35. dayofweek() function 212
234.
Ring Documentation, Release1.2 37.37 readline() function Read line from file Syntax: readline(fp) ---> string Example: Load "stdlib.ring" # Read a file line by line. Puts("Test Readline()") fp = fopen("test.ring","r") while not feof(fp) See Readline(fp) end fclose(fp) 37.38 substring() function Return a position of a substring starting from a given position in a string. Syntax: Substring(str,substr,npos) ---> string Example: Load "stdlib.ring" # Return a position of a substring starting from a given position in a string. Puts("Test Substring()") a = "abcxyzqweabc" b = "abc" i = 4 see substring(a,b,i) 37.39 changestring() function Change substring from given position to a given position with another substring. Syntax: Changestring(cString, nPos1, nPos2, cSubstr) ---> cString Example: Load "stdlib.ring" # Change substring from given position for given position with a substring. Puts("Test Changestring()") see Changestring("Rmasdg",2,5,"in") # Ring 37.37. readline() function 213
235.
Ring Documentation, Release1.2 37.40 sleep() function Sleep for the given amount of time. Syntax: sleep(nSeconds) Example: Load "stdlib.ring" Puts("Test Sleep()") see "Wait 3 Seconds!" Sleep(3) see nl 37.41 ismainsourcefile() function Check if the current file is the main source file Syntax: IsMainSourceFile() ---> True/False Example: Load "stdlib.ring" if ismainsourcefile() # code ok 37.42 direxists() function Check if directory exists Syntax: DirExists(String) ---> True/False Example: Load "stdlib.ring" see "Check dir : b:ring " puts( DirExists("b:ring") ) see "Check dir : C:ring " Puts( DirExists("C:ring") ) 37.43 makedir() function Make Directory 37.40. sleep() function 214
236.
Ring Documentation, Release1.2 Syntax: MakeDir(String) Example: Load "stdlib.ring" # Create Directory puts("create Directory : myfolder") makedir("myfolder") 37.43. makedir() function 215
237.
CHAPTER THIRTYEIGHT STDLIB CLASSES In thischapter we are going to learn about the classes in the stdlib.ring • StdBase Class • String Class • List Class • Stack Class • Queue Class • HashTable Class • Tree Class • Math Class • DateTime Class • File Class • System Class • Debug Class • DataType Class • Conversion Class • ODBC CLass • MySQL Class • SQLite Class • Security Class • Internet Class 38.1 StdBase Class Attributes: • vValue : Object Value Methods: 216
238.
Ring Documentation, Release1.2 Method Description/Output Init(x) Set vValue Attribute to x value Print() Print vValue PrintLn() Print vValue then New Line Size() return number represent the size of vValue Value() return vValue Set(x) Call Init(x) 38.2 String Class Parent Class : StdBase Class Methods: Method Description/Output Init(String|Number|List) Lower() New String - Lower case characters Upper() New String - Upper case characters Left(x) New String - contains x characters from the left Right(x) New String - contains x characters from the right Lines() Number - Lines count Trim() New String - Remove Spaces Copy(x) New String - repeat string x times strcmp(cString) Compare string with cString tolist() List (String Lines to String Items) tofile(cFileName) Write string to file mid(nPos1,nPos2) New String - from nPos1 to nPos2 getfrom(nPos1) New String - from nPos1 to the end of the string replace(cStr1,cStr2,lCase) New String - Replace cStr1 with cStr2 , lCase (True=Math Case) split() List - Each Word as list item startswith(substring) Return true if the start starts with a substring endswith(substring) Return true if the start ends with a substring Example: Load "stdlib.ring" See "Testing the String Class" + nl oString = new string("Hello, World!") oString.println() oString.upper().println() oString.lower().println() oString.left(5).println() oString.right(6).println() oString = new string("Hi" + nl + "Hello" ) See oString.lines() + nl oString = new string(" Welcome ") oString.println() oString.trim().println() oString = new string("Hello! ") oString.copy(3).println() see oString.strcmp("Hello! ") + nl see oString.strcmp("Hello ") + nl see oString.strcmp("Hello!! ") + nl oString = new string(["one","two","three"]) 38.2. String Class 217
239.
Ring Documentation, Release1.2 oString.print() see oString.lines() + nl oString = new String(1234) oString.println() oString = new String("one"+nl+"two"+nl+"three") aList = oString.tolist() see "List Items" + nl See aList oString = new String( "Welcome to the Ring programming language") See "the - position : " + oString.pos("the") + nl oString = oString.getfrom(oString.pos("Ring")) oString.println() oString.mid(1,4).println() oString = oString.replace("Ring","***Ring***",true) oString.println() oString = oString.replace("ring","***Ring***",false) oString.println() oString1 = new string("First") oString2 = new string("Second") oString = oString1 + oString2 oString.println() oString = oString1 * 3 oString.println() for t in ostring see t next oString.tofile("test.txt") oString = new string("one two three") see nl see ostring.split() oString { set("Hello") println() set("How are you?") println() } Output: Testing the String Class Hello, World! HELLO, WORLD! hello, world! Hello World! 2 Welcome Welcome Hello! Hello! Hello! 0 1 -1 one two three 4 1234 List Items one two three the - position : 12 Ring programming language 38.2. String Class 218
240.
Ring Documentation, Release1.2 Ring ***Ring*** programming language ******Ring****** programming language FirstSecond FirstFirstFirst FirstFirstFirst one two three Hello How are you? 38.3 List Class Parent Class : StdBase Class Methods: Method Description/Output Init(String|List) Add(Value) Add item to the list Delete(nIndex) Delete item from the list Item(nIndex) Get item from the list First() Get the first item in the list Last() Get the last item in the list Set(nIndex,Value) Set item value FindInColumn(nCol,Value) Find item in a column Sort() Sort items - return new list Reverse() Reverse items - return new list Insert(nIndex,Value) Inset Item after nIndex example: Load "stdlib.ring" oList = new list ( [1,2,3] ) oList.Add(4) oList.print() see oList.item(1) + nl oList.delete(4) oList.print() see oList.first() + nl see oList.last() + nl oList { set(1,"one") set(2,"two") set(3,"three") print() } see oList.find("two") + nl oList.sort().print() oList.reverse().print() oList.insert(2,"nice") oList.print() oList = new list ( [ [1,"one"],[2,"two"],[3,"three"] ] ) see copy("*",10) + nl oList.print() see "Search two : " + oList.findincolumn(2,"two") + nl see "Search 1 : " + oList.findincolumn(1,1) + nl oList = new list ( [ "Egypt" , "USA" , "KSA" ] ) for x in oList 38.3. List Class 219
241.
Ring Documentation, Release1.2 see x + nl next oList = new list ( [1,2,3,4] ) oList + [5,6,7] oList.print() oList = new list ( ["one","two"] ) oList2 = new list ( ["three","four"] ) oList + oList2 oList.print() output: 1 2 3 4 1 1 2 3 1 3 one two three 2 one three two three two one one two nice three ********** 1 one 2 two 3 three Search two : 2 Search 1 : 1 Egypt USA KSA 1 2 3 4 5 6 7 one two three 38.3. List Class 220
242.
Ring Documentation, Release1.2 four 38.4 Stack Class Parent Class : List Class Methods: Method Description/Output Init(String|Number|List) Push(Value) Push item to the stack Pop() Pop item from the stack Print() Print the stack items example: Load "stdlib.ring" oStack = new Stack oStack.push(1) oStack.push(2) oStack.push(3) see oStack.pop() + nl see oStack.pop() + nl see oStack.pop() + nl oStack.push(4) see oStack.pop() + nl oStack { push("one") push("two") push("three") } oStack.print() output: 3 2 1 4 three two one 38.5 Queue Class Parent Class : List Class Methods: Method Description/Output Init(String|Number|List) Remove() Remove item from the Queue. example: Load "stdlib.ring" oQueue = new Queue oQueue.add(1) 38.4. Stack Class 221
243.
Ring Documentation, Release1.2 oQueue.add(2) oQueue.add(3) see oQueue.remove() + nl see oQueue.remove() + nl see oQueue.remove() + nl oQueue.add(4) see oQueue.remove() + nl oQueue { add("one") add("two") add("three") } oQueue.print() output: 1 2 3 4 one two three 38.6 HashTable Class Parent Class : List Class Methods: Method Description/Output Init(List) Add(cKey,Value) Add item to the HashTable Set(cKey,Value) Set item value using the Key GetValue(cKey) Get item value using the Key Contains(cKey) Check if the HashTable contains item using the Key Index(cKey) Get the item index using the Key example: Load "stdlib.ring" ohashtable = new hashtable See "Test the hashtable Class Methods" + nl ohashtable { Add("Egypt","Cairo") Add("KSA","Riyadh") see self["Egypt"] + nl see self["KSA"] + nl see contains("Egypt") + nl see contains("USA") + nl see index("KSA") + NL print() delete(index("KSA")) see copy("*",60) + nl print() } output: 38.6. HashTable Class 222
244.
Ring Documentation, Release1.2 Test the hashtable Class Methods Cairo Riyadh 1 0 2 Egypt Cairo KSA Riyadh ************************************************************ Egypt Cairo 38.7 Tree Class Data: Attribute Description Data Node Value Children Children List Methods: Method Description/Output set(value) Set the node value. value() Get the node value. Add(value) Add new child. parent() Get the parent node. print() Print the tree nodes. example: Load "stdlib.ring" otree = new tree See "Test the tree Class Methods" + nl otree { set("The first step") # set the root node value see value() + nl Add("one") Add("two") Add("three") { Add("3.1") Add("3.2") Add("3.3") see children } see children oTree.children[2] { Add("2.1") Add("2.2") Add("2.3") { Add("2.3.1") Add("2.3.2") Add("test") } } oTree.children[2].children[3].children[3].set("2.3.3") } 38.7. Tree Class 223
245.
Ring Documentation, Release1.2 see copy("*",60) + nl oTree.print() output: Test the tree Class Methods The first step data: 3.1 parent: List... children: List... data: 3.2 parent: List... children: List... data: 3.3 parent: List... children: List... data: one parent: List... children: List... data: two parent: List... children: List... data: three parent: List... children: List... ************************************************************ one two 2.1 2.2 2.3 2.3.1 2.3.2 2.3.3 three 3.1 3.2 3.3 38.8 Math Class Methods: 38.8. Math Class 224
246.
Ring Documentation, Release1.2 Method Description sin(x) Returns the sine of an angle of x radians cos(x) Returns the cosine of an angle of x radians tan(x) Returns the tangent of an angle of x radians asin(x) Returns the principal value of the arc sine of x, expressed in radians acos(x) Returns the principal value of the arc cosine of x, expressed in radians atan(x) Returns the principal value of the arc tangent of x, expressed in radians atan2(y,x) Returns the principal arc tangent of y/x, in the interval [-pi,+pi] radians sinh(x) Returns the hyperbolic sine of x radians cosh(x) Returns the hyperbolic cosine of x radians tanh(x) Returns the hyperbolic tangent of x radians exp(x) Returns the value of e raised to the xth power log(x) Returns the natural logarithm of x log10(x) Returns the common logarithm (base-10 logarithm) of x ceil(x) Returns the smallest integer value greater than or equal to x floor(x) Returns the largest integer value less than or equal to x fabs(x) Returns the absolute value of x. pow(x,y) Returns x raised to the power of y sqrt(x) Returns the square root of x random(x) Returns a random number in the range [0,x] unsigned(n,n,c) Perform operation using unsigned numbers decimals(n) Determine the decimals digits after the point in float/double numbers example: Load "stdlib.ring" oMath = new Math See "Test the Math Class Methods" + nl See "Sin(0) = " + oMath.sin(0) + nl See "Sin(90) radians = " + oMath.sin(90) + nl See "Sin(90) degree = " + oMath.sin(90*3.14/180) + nl See "Cos(0) = " + oMath.cos(0) + nl See "Cos(90) radians = " + oMath.cos(90) + nl See "Cos(90) degree = " +oMath. cos(90*3.14/180) + nl See "Tan(0) = " + oMath.tan(0) + nl See "Tan(90) radians = " + oMath.tan(90) + nl See "Tan(90) degree = " + oMath.tan(90*3.14/180) + nl See "asin(0) = " + oMath.asin(0) + nl See "acos(0) = " + oMath.acos(0) + nl See "atan(0) = " + oMath.atan(0) + nl See "atan2(1,1) = " +oMath. atan2(1,1) + nl See "sinh(0) = " + oMath.sinh(0) + nl See "sinh(1) = " + oMath.sinh(1) + nl See "cosh(0) = " + oMath.cosh(0) + nl See "cosh(1) = " + oMath.cosh(1) + nl See "tanh(0) = " + oMath.tanh(0) + nl See "tanh(1) = " + oMath.tanh(1) + nl See "exp(0) = " + oMath.exp(0) + nl See "exp(1) = " + oMath.exp(1) + nl See "log(1) = " + oMath.log(1) + nl 38.8. Math Class 225
247.
Ring Documentation, Release1.2 See "log(2) = " + oMath.log(2) + nl See "log10(1) = " + oMath.log10(1) + nl See "log10(2) = " + oMath.log10(2) + nl See "log10(10) = " + oMath.log10(10) + nl See "Ceil(1.12) = " + oMath.Ceil(1.12) + nl See "Ceil(1.72) = " + oMath.Ceil(1.72) + nl See "Floor(1.12) = " + oMath.floor(1.12) + nl See "Floor(1.72) = " + oMath.floor(1.72) + nl See "fabs(1.12) = " + oMath.fabs(1.12) + nl See "fabs(1.72) = " + oMath.fabs(1.72) + nl See "pow(2,3) = " + oMath.pow(2,3) + nl see "sqrt(16) = " + oMath.sqrt(16) + nl for x = 1 to 20 see "Random number Max (100) : " + oMath.random(100) + nl next x = 1.1234567890123 for d = 0 to 14 oMath.decimals(d) see x + nl next cKey = "hello" h = 0 for x in cKey h = oMath.unsigned(h,ascii(x),"+") h = oMath.unsigned(h,oMath.unsigned(h,10,"<<"),"+") r = oMath.unsigned(h,6,">>") h = oMath.unsigned(h, r,"^") next h = oMath.unsigned(h,oMath.unsigned(h,3,"<<"),"+") h = oMath.unsigned(h,oMath.unsigned(h,11,">>"),"^") h = oMath.unsigned(h,oMath.unsigned(h,15,"<<"),"+") see "Hash : " + h output: Test the Math Class Methods Sin(0) = 0 Sin(90) radians = 0.89 Sin(90) degree = 1.00 Cos(0) = 1 Cos(90) radians = -0.45 Cos(90) degree = 0.00 Tan(0) = 0 Tan(90) radians = -2.00 Tan(90) degree = 1255.77 asin(0) = 0 acos(0) = 1.57 atan(0) = 0 atan2(1,1) = 0.79 38.8. Math Class 226
248.
Ring Documentation, Release1.2 sinh(0) = 0 sinh(1) = 1.18 cosh(0) = 1 cosh(1) = 1.54 tanh(0) = 0 tanh(1) = 0.76 exp(0) = 1 exp(1) = 2.72 log(1) = 0 log(2) = 0.69 log10(1) = 0 log10(2) = 0.30 log10(10) = 1 Ceil(1.12) = 2 Ceil(1.72) = 2 Floor(1.12) = 1 Floor(1.72) = 1 fabs(1.12) = 1.12 fabs(1.72) = 1.72 pow(2,3) = 8 sqrt(16) = 4 Random number Max (100) : 87 Random number Max (100) : 49 Random number Max (100) : 99 Random number Max (100) : 58 Random number Max (100) : 15 Random number Max (100) : 46 Random number Max (100) : 37 Random number Max (100) : 64 Random number Max (100) : 73 Random number Max (100) : 35 Random number Max (100) : 89 Random number Max (100) : 80 Random number Max (100) : 20 Random number Max (100) : 33 Random number Max (100) : 44 Random number Max (100) : 89 Random number Max (100) : 82 Random number Max (100) : 94 Random number Max (100) : 83 Random number Max (100) : 68 1 1.1 1.12 1.123 1.1235 1.12346 1.123457 1.1234568 1.12345679 1.123456789 1.1234567890 1.12345678901 1.123456789012 1.1234567890123 1.12345678901230 Hash : 3372029979.00000000000000 38.8. Math Class 227
249.
Ring Documentation, Release1.2 38.9 DateTime Class Methods: Method Description/Output clock() The number of clock ticks from program start. time() Get the system time. date() Get the date. timelist() List contains the date and the time information. adddays(cDate,nDays) Return Date from cDate and after nDays diffdays(cDate1,cDate2) Return the Number of days (cDate1 - cDate2) example: Load "stdlib.ring" oDateTime = new datetime See "Test the datetime Class Methods" + nl See "Calculate performance" + nl t1 = oDateTime.clock() for x = 1 to 1000000 next see oDateTime.clock() - t1 + nl See "Time : " + oDateTime.time() + nl See "Date : " + oDateTime.date() + nl See oDateTime.TimeList() See "Month Name : " + oDateTime.TimeList()[4] cDate = oDateTime.date() see cDate + nl cDate = oDateTime.adddays(cDate,10) see cDate + nl cDate1 = oDateTime.date() see cDate1 + nl cDate2 = oDateTime.adddays(cDate1,10) see cDate2 + nl see "DiffDays = " + oDateTime.diffdays(cDate1,cDate2) + nl see "DiffDays = " + oDateTime.diffdays(cDate2,cDate1) + nl output: Test the datetime Class Methods Calculate performance 85 Time : 02:53:35 Date : 31/08/2016 Wed Wednesday Aug August 08/31/16 02:53:35 31 38.9. DateTime Class 228
250.
Ring Documentation, Release1.2 02 02 244 08 53 AM 35 35 3 08/31/16 02:53:35 16 2016 Arab Standard Time % Month Name : August31/08/2016 10/09/2016 31/08/2016 10/09/2016 DiffDays = -10 DiffDays = 10 38.10 File Class Methods: 38.10. File Class 229
251.
Ring Documentation, Release1.2 Method Description/Output read(cFileName) Read the file content write(cFileName,cStr) Write string to file dir(cFolderPath) Get the folder contents (files & sub folders) rename(cOld,cNew) Rename files using the Rename() function remove(cFileName) Delete a file using the Remove() function open(cFileName,cMode) Open a file using the Fopen() function close() Close file flush() Flushes the output buffer of a stream reopen(cFileName,cMode) Open another file using the same file handle tempfile() Creates a temp. file (binary). seek(noffset,nwhence) Set the file position of the stream tell() Know the current file position of a stream rewind() Set the file position to the beginning of the file getpos() Get handle to the current file position setpos(poshandle) Set the current file position clearerr() Clear the EOF error and the error indicators of a stream eof() Test the end-of-file indicator error() Test the error indicator perror(cErrorMessage) Print error message to the stderr getc() Get the next character from the stream gets(nsize) Read new line from the stream putc(cchar) Write a character to the stream puts(cStr) Write a string to the stream ungetc(cchar) Push a character to the stream fread(nsize) Read data from a stream fwrite(cString) Write data to a stream exists(cFileName) Check if a file exists example: Load "stdlib.ring" ofile = new file See "Test the file Class Methods" + nl see ofile.read(filename()) see nl ofile.open(filename(),"r") see ofile.gets(100) + nl ofile.close() 38.11 System Class Methods: 38.11. System Class 230
252.
Ring Documentation, Release1.2 Method Description/Output system() Execute system commands sysget() Get environment variables ismsdos() Check if the operating system is MSDOS or not iswindows() Check if the operating system is Windows or not iswindows64() Check if the operating system is Windows 64bit or not isunix() Check if the operating system is Unix or not ismacosx() Check if the operating system is Mac OS X or not islinux() Check if the operating system is Linux or not isfreebsd() Check if the operating system is FreeBSD or not isandroid() Check if the operating system is Android or not windowsnl() Get the windows new line string sysargv() Get the command line arguments passed to the ring script filename() Get the active source file example: Load "stdlib.ring" oSystem = new System See "Test the System Class Methods" + nl oSystem.system("dir") see oSystem.sysget("path") + nl see oSystem.ismsdos() + nl see oSystem.iswindows() + nl see oSystem.iswindows64() + nl see oSystem.isunix() + nl see oSystem.ismacosx() + nl see oSystem.islinux() + nl see oSystem.isfreebsd() + nl see oSystem.isandroid() + nl see oSystem.windowsnl() + nl see oSystem.sysargv() + nl see oSystem.filename() + nl 38.12 Debug Class Methods: Method Description/Output eval(cCode) Execute code during the runtime from string. raise(cError) Raise an exception. assert(cCondition) Test condition before executing the code. example: Load "stdlib.ring" oDebug = new Debug See "Test the Debug Class Methods" + nl oDebug.eval("see 'Hello'+nl") try x = 10 oDebug.assert(x=11) 38.12. Debug Class 231
253.
Ring Documentation, Release1.2 catch see "assert" + nl done raise("Error!") 38.13 DataType Class Methods: Method Description/Output isstring(vValue) We can know if the value is a string or not. isnumber(vValue) We can know if the value is a number or not. islist(vValue) We can know if the value is a list or not. type(vValue) Know the type of a value isnull(vValue) Check the value to know if it’s null or not. isalnum(vValue) 1 if the value is digit/letter or 0 if not isalpha(vValue) 1 if the value is a letter or 0 if not iscntrl(vValue) 1 if the value is a control character (no printing position) isdigit(vValue) 1 if the value is a digit or 0 if not isgraph(vValue) 1 if the value can be printed (Except space) or 0 if not islower(vValue) 1 if the value is lowercase letter or 0 if not isprint(vValue) 1 if the value occupies a printing position or 0 if not ispunct(vValue) 1 if the value is a punctuation character or 0 if not isspace(vValue) 1 if the value is a white-space or 0 if not isupper(vValue) 1 if the value is an uppercase alphabetic letter or 0 if not isxdigit(vValue) 1 if the value is a hexdecimal digit character or 0 if not example: Load "stdlib.ring" oDataType = new DataType See "Test the DataType Class Methods" + nl see oDataType.isstring("test") + nl see oDataType.isnumber(1) + nl see oDataType.islist(1:3) + nl see oDataType.type("test") + nl see oDataType.isnull(null) + nl see oDataType.isalnum("Hello") + nl + # print 1 oDataType.isalnum("123456") + nl + # print 1 oDataType.isalnum("ABCabc123") + nl + # print 1 oDataType.isalnum("How are you") + nl # print 0 because of spaces see oDataType.isalpha("Hello") + nl + # print 1 oDataType.isalpha("123456") + nl + # print 0 oDataType.isalpha("ABCabc123") + nl + # print 0 oDataType.isalpha("How are you") + nl # print 0 See oDataType.iscntrl("hello") + nl + # print 0 oDataType.iscntrl(nl) # print 1 see oDataType.isdigit("0123456789") + nl + # print 1 oDataType.isdigit("0123a") + nl see oDataType.isgraph("abcdef") + nl + # print 1 oDataType.isgraph("abc def") + nl # print 0 see oDataType.islower("abcDEF") + nl + # print 0 oDataType.islower("ghi") + nl # print 1 see oDataType.isprint("Hello") + nl + # print 1 oDataType.isprint("Nice to see you") + nl + # print 1 oDataType.isprint(nl) + nl # print 0 38.13. DataType Class 232
254.
Ring Documentation, Release1.2 see oDataType.isprint("Hello") + nl # print 1 see oDataType.isupper("welcome") + nl + # print 0 oDataType.isupper("WELCOME") + nl # print 1 see oDataType.isxdigit("0123456789abcdef") + nl + # print 1 oDataType.isxdigit("123z") # print 0 Output: Test the DataType Class Methods 1 1 1 STRING 1 1 1 1 0 1 0 0 0 0 11 0 1 0 0 1 1 1 0 1 0 1 1 0 38.14 Conversion Class Methods: Method Description/Output number(vValue) Convert strings to numbers. string(vValue) Convert numbers to strings. ascii(vValue) Get the ASCII code for a letter. char(vValue) Convert the ASCII code to character. hex(vValue) Convert decimal to hexadecimal. dec(vValue) Convert hexadecimal to decimal. str2hex(vValue) Convert string characters to hexadecimal characters. hex2str(vValue) Convert hexadecimal characters to string. example: Load "stdlib.ring" 38.14. Conversion Class 233
255.
Ring Documentation, Release1.2 oConversion = new conversion See "Test the conversion Class Methods" + nl See oConversion.number("3") + 5 + nl See oConversion.string(3) + "5" + nl See oConversion.Ascii("m") + nl See oConversion.char(77) + nl see oConversion.hex(162) + nl see oConversion.dec("a2") + nl cHex = oConversion.str2hex("Hello") see cHex + nl see oConversion.hex2str(cHex) + nl Output: Test the conversion Class Methods 8 35 109 M a2 162 48656c6c6f Hello 38.15 ODBC Class Methods: Method Description/Output drivers() Get a list of ODBC drivers. datasources() Get a list of ODBC data sources. close() Free resources. connect(cConString) Connect to the database. disconnect() Close the connection. execute(cSQL) Execute SQL Statements colcount() Get columns count in the query result fetch() Fetch a row from the query result getdata(nCol) Get column value from the fetched row tables() Get a list of tables inside the database columns(cTableName) Get a list of columns inside the table autocommit(lStatus) Enable or disable the auto commit feature commit() Commit updates to the database rollback() Rollback updates to the database example: Load "stdlib.ring" oodbc = new odbc See "Test the odbc Class Methods" + nl oODBC { see drivers() see datasources() See "Connect to database" + nl see connect("DBQ=test.mdb;Driver={Microsoft Access Driver (*.mdb)}") + nl See "Select data" + nl 38.15. ODBC Class 234
256.
Ring Documentation, Release1.2 see execute("select * from person") + nl nMax = colcount() See "Columns Count : " + nMax + nl while fetch() See "Row data:" + nl for x = 1 to nMax see getdata(x) + " - " next end See "Close database..." + nl disconnect() close() } 38.16 MySQL Class Methods: Method Description/Output info() Return string contains the MySQL Client version. error() Get the error message from the MySQL Client. connect(cServer,cUser,cPass,cDatabase) Connect to the MySQL database server. close() Close the connection to the MySQL database. query(cQuery) Execute SQL queries. insert_id() Get the inserted row id. result() Get the query result (data without column names). next_result() Move to the next query result. columns() Get a list of columns names. result2() Get all of the column names then the query result in one list. escape_string(cStr) Before storing binary data and special characters in the database. autocommit(lStatus) Enable or disable the auto commit feature. commit() Commit updates to the database. rollback() Rollback updates to the database. example: Load "stdlib.ring" omysql = new mysql See "Test the MySQL Class Methods" + nl omysql { see info() + nl connect("localhost", "root", "root","mahdb") see "Execute Query" + nl query("SELECT * FROM Employee") see "Print Result" + nl see result2() see "Close database" + nl close() } Output: Test the MySQL Class Methods 5.5.30 38.16. MySQL Class 235
257.
Ring Documentation, Release1.2 Execute Query Print Result Id Name Salary 1 Mahmoud 15000 2 Samir 16000 3 Fayed 17000 Close database 38.17 SQLite Class Methods: Method Description/Output open(cDatabase) Open Database. close() Close Database. errormessage() Get Error Message. execute(cSQL) Execute Query. example: Load "stdlib.ring" osqlite = new sqlite See "Test the sqlite Class Methods" + nl osqlite { open("test.db") sql = "CREATE TABLE COMPANY(" + "ID INT PRIMARY KEY NOT NULL," + "NAME TEXT NOT NULL," + "AGE INT NOT NULL," + "ADDRESS CHAR(50)," + "SALARY REAL );" execute(sql) sql = "INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) " + "VALUES (1, 'Mahmoud', 29, 'Jeddah', 20000.00 ); " + "INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) " + "VALUES (2, 'Ahmed', 27, 'Jeddah', 15000.00 ); " + "INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY)" + "VALUES (3, 'Mohammed', 31, 'Egypt', 20000.00 );" + "INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY)" + "VALUES (4, 'Ibrahim', 24, 'Egypt ', 65000.00 );" execute(sql) aResult = execute("select * from COMPANY") for x in aResult for t in x 38.17. SQLite Class 236
258.
Ring Documentation, Release1.2 see t[2] + nl next next see copy("*",50) + nl for x in aResult see x["name"] + nl next close() } Output: Test the sqlite Class Methods 1 Mahmoud 29 Jeddah 20000.0 2 Ahmed 27 Jeddah 15000.0 3 Mohammed 31 Egypt 20000.0 4 Ibrahim 24 Egypt 65000.0 ************************************************** Mahmoud Ahmed Mohammed Ibrahim 38.18 Security Class Methods: Method Description/Output md5(cString) Calculate the MD5 hash. sha1(cString) Calculate the SHA1 hash. sha256(cString) Calculate the SHA256 hash. sha512(cString) Calculate the SHA512 hash. sha384(cString) Calculate the SHA384 hash. sha224(cString) Calculate the SHA224 hash. encrypt(cString,cKey,cIV) Cncrypts the data using the Blowfish algorithm. decrypt(cString,cKey,cIV) Decrypt the data encrypted using the Encrypt() method. randbytes(nSize) Generate a string of pseudo-random bytes. example: 38.18. Security Class 237
259.
Ring Documentation, Release1.2 Load "stdlib.ring" osecuirty = new secuirty See "Test the secuirty Class Methods" + nl oSecuirty { see md5("hello") + nl + sha1("hello") + nl + sha256("hello") + nl + sha512("hello") + nl + sha384("hello") + nl + sha256("hello") + nl list = 0:15 cKey="" for x in list cKey += char(x) next list = 1:8 cIV = "" for x in list cIV += char(x) next cCipher = encrypt("hello",cKey,cIV) see cCipher + nl + decrypt(cCipher,cKey,cIV) + nl } 38.19 Internet Class Methods: • download(cURL) • sendemail(cSMTPServer,cEmail,cPassword,cSender,cReceiver,cCC,cTitle,cContent) example: Load "stdlib.ring" ointernet = new internet See "Test the internet Class Methods" + nl ointernet { see download("www.ring-lang.sf.net") } 38.19. Internet Class 238
260.
CHAPTER THIRTYNINE DECLARATIVE PROGRAMMING USINGNESTED STRUCTURES In this chapter we are going to learn how to build declarative programming world using nested structures on the top of object oriented. We will learn about • Creating Objects inside Lists • Composition and Returning Objects and Lists by Reference • Executing code after the end of object access • Declarative Programming on the top of Object-Oriented 39.1 Creating Objects inside Lists We can create objects inside lists during list definition. Also we can add objects to the list at any time using the Add() function or the + operator. Example: alist = [new point, new point, new point] # create list contains three objects alist + [1,2,3] # add another item to the list see "Item 4 is a list contains 3 items" + nl see alist[4] add(alist , new point) alist + new point alist[5] { x = 100 y = 200 z = 300 } alist[6] { x = 50 y = 150 z = 250 } see "Object inside item 5" + nl see alist[5] see "Object inside item 6" + nl see alist[6] class point x y z Output: Item 4 is a list contains 3 items 1 2 239
261.
Ring Documentation, Release1.2 3 Object inside item 5 x: 100.000000 y: 200.000000 z: 300.000000 Object inside item 6 x: 50.000000 y: 150.000000 z: 250.000000 39.2 Composition and Returning Objects and Lists by Reference When we use composition and have object as one of the class attributes, when we return that object it will be returned by reference. if the called used the assignment operator, another copy of the object will be created. The caller can avoid using the assignment operator and use the returned reference directly to access the object. The same is done also if the attribute is a list (not object). Note: Objects and Lists are treated using the same rules. When you pass them to function they are passed by reference, when you return them from functions they are returned by value except if it’s an object attribute where a return by reference will be done. Example: o1 = new Container myobj = o1.addobj() # the assignment will create another copy myobj.x = 100 myobj.y = 200 myobj.z = 300 see o1.aobjs[1] # print the object inside the container see myobj # print the copy Class Container aObjs = [] func addobj aobjs + new point return aobjs[len(aobjs)] # return object by reference Class point x = 10 y = 20 z = 30 Output: x: 10.000000 y: 20.000000 z: 30.000000 x: 100.000000 y: 200.000000 z: 300.000000 39.2. Composition and Returning Objects and Lists by Reference 240
262.
Ring Documentation, Release1.2 Example(2): func main o1 = new screen { content[point()] { x = 100 y = 200 z = 300 } content[point()] { x = 50 y = 150 z = 250 } } see o1.content[1] see o1.content[2] Class Screen content = [] func point content + new point return len(content) Class point x = 10 y = 20 z = 30 Output: x: 100.000000 y: 200.000000 z: 300.000000 x: 50.000000 y: 150.000000 z: 250.000000 Example(3): func main o1 = New Screen { point() { # access the object using reference x = 100 y = 200 z = 300 } point() { # access the object using reference x = 50 y = 150 z = 250 } } see o1.content[1] see o1.content[2] Class Screen content = [] func point content + new point 39.2. Composition and Returning Objects and Lists by Reference 241
263.
Ring Documentation, Release1.2 return content[len(content)] # return the object by reference Class point x=10 y=20 z=30 Output: x: 100.000000 y: 200.000000 z: 300.000000 x: 50.000000 y: 150.000000 z: 250.000000 39.3 Executing code after the end of object access We can access an object using { } to use object attributes and methods. if the object contains a method called BraceEnd(), it will be executed before the end of the object access. Example: New Point { See "How are you?" + nl } Class Point x y z func braceend see "I'm fine, Thank you!" + nl Output: How are you? I'm fine, Thank you! 39.4 Declarative Programming on the top of Object-Oriented The next features enable us to build and use declartive programming environment using nested structures on the top of object oriented • using {} to access the object attributes and methods • BraceEnd() Method • returning objects by reference • Setter/Getter Methods (optional) Example: # Declartive Programming (Nested Structures) Screen() { point() { x = 100 y = 200 z = 300 39.3. Executing code after the end of object access 242
264.
Ring Documentation, Release1.2 } point() { x = 50 y = 150 z = 250 } } # Functions and Classes Func screen return new screen Class Screen content = [] func point content + new point return content[len(content)] func braceend see "I have " + len(content) + " points!" Class point x=10 y=20 z=30 func braceend see self Output: x: 100.000000 y: 200.000000 z: 300.000000 x: 50.000000 y: 150.000000 z: 250.000000 I have 2 points! 39.5 More beautiful Code We can get better results and a more beautiful code when we can avoid writing () after the method name when the methods doesn’t take parameters. This feature is not provided directly by the Ring language because there is a difference between object methods and object attributes. We can get a similar effect on the syntax of the code when we define a getter method for the object attribute. For example instead of defining the point() method. we will define the point attribute then the getpoint() method that will be executed once you try to get the value of the point attribute. since we write the variable name direcly without () we can write point instead of point() and the method getpoint() will create the object and return the object reference for us. Example: new Container { 39.5. More beautiful Code 243
265.
Ring Documentation, Release1.2 Point { x=10 y=20 z=30 } } Class Container aObjs = [] point func getpoint aObjs + new Point return aObjs[len(aObjs)] Class Point x y z func braceend see "3D Point" + nl + x + nl + y + nl + z + nl Output 3D Point 10 20 30 39.5. More beautiful Code 244
266.
CHAPTER FORTY NATURAL LANGUAGE PROGRAMMING Usingthe Ring programming language, we can create Natural programming languages based on classes and objects. 40.1 History In 2010, I developed a new programming language called Supernova (developed using PWCT). This language uses a code that looks similar to Natural Language statements to create simple GUI applications. Now after five years, In the Ring programming language, we can get similar results, but now we have the ability to create/use code similar to Natural language statements in any domain that we like or need. The Ring programming language comes with the Supernova sprite, but with more generalization and with mix of other languages sprites. 40.2 Example The next example presents how to create a class that define two instructions The first instruction is : I want window The second instruction is : Window title = <expr> Also keywords that can be ignored like the ‘the’ keyword New App { I want window The window title = "hello world" } Class App # Attributes for the instruction I want window i want window nIwantwindow = 0 # Attributes for the instruction Window title # Here we don't define the window attribute again title nWindowTitle = 0 # Keywords to ignore, just give them any value the=0 func geti 245
267.
Ring Documentation, Release1.2 if nIwantwindow = 0 nIwantwindow++ ok func getwant if nIwantwindow = 1 nIwantwindow++ ok func getwindow if nIwantwindow = 2 nIwantwindow= 0 see "Instruction : I want window" + nl ok if nWindowTitle = 0 nWindowTitle++ ok func settitle cValue if nWindowTitle = 1 nWindowTitle=0 see "Instruction : Window Title = " + cValue + nl ok Output: Instruction : I want window Instruction : Window Title = hello world 40.3 Change the Ring Keyword ‘And’ What if we want to connect between the two instructions using ‘and’ We have a problem because in Ring ‘and’ is a keyword We can change that using the ChangeRingKeyword command. Syntax: ChangeRingKeyword <oldkeyword> <newkeyword> Note: remember to restore the keyword again Tip: The ChangeRingKeyword command is executed in the scanner stage by the compiler (before parsing). Example: ChangeRingKeyword and _and New App { I want window and the window title = "hello world" } Class App 40.3. Change the Ring Keyword ‘And’ 246
268.
Ring Documentation, Release1.2 # Attributes for the instruction I want window i want window nIwantwindow = 0 # Attributes for the instruction Window title # Here we don't define the window attribute again title nWindowTitle = 0 # Keywords to ignore, just give them any value the=0 and=0 ChangeRingKeyword _and and func geti if nIwantwindow = 0 nIwantwindow++ ok func getwant if nIwantwindow = 1 nIwantwindow++ ok func getwindow if nIwantwindow = 2 nIwantwindow= 0 see "Instruction : I want window" + nl ok if nWindowTitle = 0 nWindowTitle++ ok func settitle cValue if nWindowTitle = 1 nWindowTitle=0 see "Instruction : Window Title = " + cValue + nl ok func getand see "Using : and" + nl Output: Instruction : I want window Using : and Instruction : Window Title = hello world 40.4 Change the Ring Operator ‘+’ What if we want to define a new behavior for any operator like the “+” operator. We can do this change using the ChangeRingOperator command to hide operator (change it’s name) Then we can use the operator as identifier that we can handle it’s behaviour Syntax: 40.4. Change the Ring Operator ‘+’ 247
269.
Ring Documentation, Release1.2 ChangeRingOperator <oldoperator> <newoperator> Note: remember to restore the operator again Tip: The ChangeRingOperator command is executed in the scanner stage by the compiler (before parsing). Example: ChangeRingOperator + _+ New App { + } Class App + func get+ see "Plus operator" ChangeRingOperator _+ + Output: Plus operator 40.5 Change the ‘=’ operator to ‘is’ Example: ChangeRingKeyword and _and ChangeRingOperator = is New App { I want window and the window title is "hello world" } ChangeRingOperator is = Class App # Attributes for the instruction I want window i want window nIwantwindow = 0 # Attributes for the instruction Window title # Here we don't define the window attribute again title nWindowTitle = 0 # Keywords to ignore, just give them any value the=0 and=0 ChangeRingKeyword _and and func geti if nIwantwindow = 0 40.5. Change the ‘=’ operator to ‘is’ 248
270.
Ring Documentation, Release1.2 nIwantwindow++ ok func getwant if nIwantwindow = 1 nIwantwindow++ ok func getwindow if nIwantwindow = 2 nIwantwindow= 0 see "Instruction : I want window" + nl ok if nWindowTitle = 0 nWindowTitle++ ok func settitle cValue if nWindowTitle = 1 nWindowTitle=0 see "Instruction : Window Title = " + cValue + nl ok 40.6 Using Eval() with our Natural Code Example: func Main cProgram = ' I want window and the window title is "hello world" ' MyLanguage(cProgram) Func MyLanguage cCode # We add to the code the instructions that change keywords and operators # Because Eval() uses a new Compiler Object (the original keywords and operatos). cCode = ' ChangeRingKeyword and _and ChangeRingOperator = is ' + cCode New App { eval(cCode) } Class App # Attributes for the instruction I want window i want window nIwantwindow = 0 # Attributes for the instruction Window title # Here we don't define the window attribute again 40.6. Using Eval() with our Natural Code 249
271.
Ring Documentation, Release1.2 title nWindowTitle = 0 # Keywords to ignore, just give them any value the=0 ChangeRingKeyword and _and and=0 ChangeRingKeyword _and and func geti if nIwantwindow = 0 nIwantwindow++ ok func getwant if nIwantwindow = 1 nIwantwindow++ ok func getwindow if nIwantwindow = 2 nIwantwindow= 0 see "Instruction : I want window" + nl ok if nWindowTitle = 0 nWindowTitle++ ok func settitle cValue if nWindowTitle = 1 nWindowTitle=0 see "Instruction : Window Title = " + cValue + nl ok 40.7 BraceStart and BraceEnd Methods We can write code that will be executed before/after using { } Example: o1 = new test { see "Hello" + nl } o1 {} class test func bracestart see "start" + nl func braceend see "end" + nl Output: 40.7. BraceStart and BraceEnd Methods 250
272.
Ring Documentation, Release1.2 start Hello end start end 40.8 BraceExprEval Method The next example demonstrates how to use the “BraceExprEval” method to get expressions in Natural code. Example: new natural { create 5 } class natural create=0 lkeyword = false func braceexpreval r if lkeyword lkeyword=false return ok see "expr eval" + nl see "type: " + type(r) see nl see "value : " see r see nl func getcreate lkeyword = true see "create" + nl Output: create expr eval type: NUMBER value : 5 40.9 Real Natural Code The next example is a more advanced example # Natural Code new program { Accept 2 numbers then print the sum } # Natural Code Implementation class program # Keywords Accept=0 numbers=0 then=0 print=0 the=0 sum=0 # Execution func braceexpreval x value = x func getnumbers for x=1 to value see "Enter Number ("+x+") :" give nNumber 40.8. BraceExprEval Method 251
273.
Ring Documentation, Release1.2 aNumbers + nNumber next func getsum nSUm = 0 for x in aNumbers nSum+= x next see "The Sum : " + nSum private value=0 aNumbers=[] Output: Enter Number (1) :3 Enter Number (2) :4 The Sum : 7 40.10 BraceError() Method The next examples demonstrates how to use the “BraceError” method to handle errors when accessing the object using braces {}. Example: func main o1 = new point { x=10 y=20 z=30 TEST SEE test } class point x y z func braceerror see "Handle Error!" + nl SEE "Message :" + cCatchError + nl if ( left(cCatchError,11) = "Error (R24)" ) and not isattribute(self,"test") see "add attribute" + nl addattribute(self,"test") test = 10 ok see "done" + nl return Output: Handle Error! Message :Error (R24) : Using uninitialized variable : test add attribute done 10 Example: new point { x=10 y=20 z=30 test() see "mmm..." + NL } 40.10. BraceError() Method 252
274.
Ring Documentation, Release1.2 class point x y z func braceerror see "Handle Error!" + nl see "Message :" + cCatchError + nl see self see "Done" + NL Output: Handle Error! Message :Error (R3) : Calling Function without definition !: test x: 10.000000 y: 20.000000 z: 30.000000 Done mmm... 40.11 Clean Natural Code Instead of typing the literal as “literal” we can accept the words directly. Example: The next example accept hello world instead of “hello world” ChangeRingKeyword and _and ChangeRingOperator = is New App { I want window and the window title is hello world } ChangeRingOperator is = Class App # Attributes for the instruction I want window i want window nIwantwindow = 0 # Attributes for the instruction Window title # Here we don't define the window attribute again title nWindowTitle = 0 # Keywords to ignore, just give them any value the=0 and=0 # Data literal = "" ChangeRingKeyword _and and func geti if nIwantwindow = 0 nIwantwindow++ ok func getwant 40.11. Clean Natural Code 253
275.
Ring Documentation, Release1.2 if nIwantwindow = 1 nIwantwindow++ ok func getwindow if nIwantwindow = 2 nIwantwindow= 0 see "Instruction : I want window" + nl ok if nWindowTitle = 0 nWindowTitle++ ok func settitle cValue if nWindowTitle = 1 nWindowTitle=2 ok func braceend if nWindowTitle = 2 see "Instruction : Window Title = " + literal + nl nWindowTitle = 0 ok func braceerror c= substr(cCatchError,":") while c > 0 c= substr(cCatchError,":") cCatchError=substr(cCatchError,c+1) end literal += substr(cCatchError,1) 40.11. Clean Natural Code 254
276.
CHAPTER FORTYONE WEB DEVELOPMENT (CGILIBRARY) In this chapter we will learn about developing Web applications using a CGI Library written in the Ring language. 41.1 Configure the Apache web server We can use Ring with any web server that support CGI. In this section we will learn about using Ring with the Apache HTTP Server. You can download Apache from : http://httpd.apache.org/ Or you can get it included with other projects like XAMPP : https://www.apachefriends.org/download.html Install then open the file: xamppapacheconfhttpd.conf search for <Directory /> Then after it add Options FollowSymLinks +ExecCGI So we have <Directory /> Options FollowSymLinks +ExecCGI Search for the next line and be sure that it’s not commented LoadModule cgi_module modules/mod_cgi.so Search for : AddHandler cgi-script Then add ”.ring” to the supported cgi extensions Example AddHandler cgi-script .cgi .ring Example AddHandler cgi-script .cgi .pl .asp .ring 255
277.
Ring Documentation, Release1.2 Run/Start the server Create your web applications in a directory supported by the web server. Example: Apache2.2htdocsmywebapplicationfolder Example: xampphtdocsmywebapplicationfolder Inside the source code file (*.ring), Add this line #!c:ringbinring.exe -cgi Note: Change the previous line based on the path to ring.exe in your machine 41.2 Ring CGI Hello World Program The next program is the Hello World program #!c:ringbinring.exe -cgi See "content-type : text/html" +nl+nl+ "Hello World!" + nl 41.3 Hello World Program using the Web Library We can use the web library to write CGI Web applications quickly Example (1) : #!c:ringbinring.exe -cgi Load "weblib.ring" Import System.Web New Page { Text("Hello World!") } Example (2) : #!c:ringbinring.exe -cgi Load "weblib.ring" Import System.Web WebPage() { Text("Hello World!") } 41.2. Ring CGI Hello World Program 256
278.
Ring Documentation, Release1.2 Tip: the difference between ex. 1 and ex. 2 is using WebPage() function to return the page object instead of creating the object using new statement. 41.4 Web Library Features The next features are provided by the Web library to quickly create web applications. • Generate HTML pages using functions • Generate HTML pages using objects • HTTP Get • HTTP Post • Files Upload • URL Encode • Templates • CRUD MVC Sample • Users Logic & Registration Sample 41.5 HTTP Get Example The Page User Interface #!c:ringbinring.exe -cgi Load "weblib.ring" Import System.Web New Page { Title = "Test HTTP Get" divstart([ :style = StyleSizeFull() ] ) boxstart() text( "Test HTTP GET" ) newline() boxend() divstart([ :style = Styledivcenter("600px","550px") + StyleGradient(21) ]) divstart([:style = stylefloatleft() + stylesize("100px","100%") + stylecolor("black") + stylegradient(58)]) formstart("ex5.ring") tablestart([ :style = stylesize("65%","90%") + stylemarginleft("35%") + stylemargintop("30%") ]) rowstart([]) cellstart([]) text ( "Name : " ) cellend() cellstart([]) cTextboxStyle = StyleMarginLeft("5%") + StyleWidth("250px") + StyleColor("black") + 41.4. Web Library Features 257
Ring Documentation, Release1.2 41.10 Templates Using Templates we can write Ring code inside HTML files Syntax: <%= Ring Expression %> <% Ring Statements %> The HTML Code <h1>Listing Numbers</h1> <table> <tr> <th> <%= myheader.cColumn1 %> </th> <th> <%= myheader.cColumn2 %> </th> <th></th> <th></th> <th></th> </tr> <% for x in aNumbers %> <tr> <td> <%= x.nValue %> </td> <td> <%= x.nSquare %> </td> </tr> <% next %> </table> The Ring Code #!c:ringbinring.exe -cgi Load "weblib.ring" Import System.Web New NumbersController { start() } 41.10. Templates 270
292.
Ring Documentation, Release1.2 Class NumbersController MyHeader aNumbers Func Start MyHeader = New Header { cColumn1 = "Number" cColumn2 = "Square" } aNumbers = list(20) for x = 1 to len(aNumbers) aNumbers[x] = new number { nValue = x nSquare = x*x } next cTemp = Template("mynumbers.html",self) New Page { boxstart() text( "Test Templates" ) newline() boxend() html(cTemp) } Class Header cColumn1 cColumn2 Class Number nValue nSquare Screen Shot: 41.10. Templates 271
293.
Ring Documentation, Release1.2 41.11 HTML Special Characters The text() function display HTML special characters. If you want to write html code, use the html() function. 41.11. HTML Special Characters 272
Ring Documentation, Release1.2 41.13 Random Image #!c:ringbinring.exe -cgi Load "weblib.ring" Import System.Web cUploadPath = "C:/Apache2.2/htdocs/ringapp/upload/" New Page { boxstart() text( "Random Test") newline() boxend() divstart([ :style = styleFloatLeft() + styleWidth("400px") ]) newline() aList = dir(cUploadPath) if len(aList) > 0 nIndex = random(len(aList)) if nindex = 0 nIndex = 1 ok cItem = "upload/" + aList[nIndex][1] newline() image( [ :url = cItem , :alt = :image ] ) else text("No images!") newline() ok divend() } Screen Shot: 41.13. Random Image 275
297.
Ring Documentation, Release1.2 41.14 HTML Lists The next example print a list contains numbers from 1 to 10 Then print a list from Ring List. Finally we have a list of buttons and when we press on a button we get a message contains the clicked button number. To start the list we uses the ulstart() function. To end the list we uses the ulend() function. We uses listart() and liend() to determine the list item. #!c:ringbinring.exe -cgi Load "weblib.ring" Import System.Web Func Main New Page { ulstart([]) for x = 1 to 10 listart([]) text(x) liend() next ulend() list2ul(["one","two","three","four","five"]) ulstart([]) for x = 1 to 10 listart([]) 41.14. HTML Lists 276
298.
Ring Documentation, Release1.2 cFuncName = "btn"+x+"()" button([ :onclick = cFuncName , :value = x]) script(scriptfuncalert(cFuncName,string(x))) liend() next ulend() } Screen Shot: 41.14. HTML Lists 277
299.
Ring Documentation, Release1.2 41.15 HTML Tables In this example we will learn how to generate HTML tables using the tablestart(), tableend(), rowstart(), rowend() ,headerstart(), headerend(), cellstart() and cellend() functions. #!c:ringbinring.exe -cgi Load "weblib.ring" Import System.Web Func Main New Page { divstart([ :style = styledivcenter("400px","500px") ] ) style(styletable() + styletablerows("t01")) tablestart([ :id = :t01 , :style = stylewidth("100%") ]) rowstart([]) headerstart([]) text("Number") headerend() headerstart([]) text("square") headerend() rowend() for x = 1 to 10 rowstart([]) cellstart([]) text(x) cellend() cellstart([]) text(x*x) cellend() rowend() next tableend() divend() } Screen Shot: 41.15. HTML Tables 278
300.
Ring Documentation, Release1.2 41.16 Gradient In this example we will learn how to use the StyleGradient() function. The function takes the style number as input (range from 1 to 60). #!c:ringbinring.exe -cgi Load "weblib.ring" Import System.Web Func Main New Page { boxstart() text("StyleGradient() Function") boxend() for x = 1 to 60 divstart([ :id = x , :align = "center" , :style = stylefloatleft() + stylesize(string(100/60*6)+"%","50px") + stylegradient(x) ]) h3(x) divend() next } Screen Shot: 41.16. Gradient 279
301.
Ring Documentation, Release1.2 41.17 Generating Pages using Objects Instead of using functions/methods to generate HTML pages, we can use an object for each element in the page. This choice means more beautiful code but slower. The fastest method is to print HTML code directly, then using functions then using templates then using objects (slower). #!c:ringbinring.exe -cgi Load "weblib.ring" Import System.Web Func Main WebPage() { Title = "Using objects to create the Web Page content" h1 { text("welcome") } link { Title = "Google" Link = "http://www.google.com" } div { id = "div1" style = stylegradient(30) + stylesize("50%","50%") text("Outer Div") div { id = "div2" color = "white" backgroundcolor = "green" width = "50%" height = "50%" marginleft = "5%" margintop = "5%" text("Inner Div") } } div { id = "div3" color = "black" backgroundcolor = "silver" width = "100%" height = "100%" text("Form") form { method = "POST" Action = "helloworld.ring" Table { style = stylewidth("100%") + stylegradient(24) TR { TD { WIDTH="10%" text("Name : " ) } 41.17. Generating Pages using Objects 280
Ring Documentation, Release1.2 41.18 Using Bootstrap Library using Functions The next example uses the Bootstrap JavaScript Library when generating the HTML page. #!c:ringbinring.exe -cgi Load "weblib.ring" Import System.Web Func Main new BootstrapPage { divstart([ :class = "container" ]) divstart([ :class = "jumbotron" ]) h1("Bootstrap Page") divend() 41.18. Using Bootstrap Library using Functions 284
306.
Ring Documentation, Release1.2 divstart([ :class = :row ]) divstart([ :class = "col-sm-4" ]) h3("Welcome to the Ring programming language") p([ :text = "Using a scripting language is very fun!" ]) divend() divstart([ :class = "col-sm-4" ]) h3("Welcome to the Ring programming language") p([ :text = "using a scripting language is very fun!" ]) divend() divstart([ :class = "col-sm-4" ]) h3("Welcome to the Ring programming language") p([ :text = "using a scripting language is very fun!" ]) divend() divend() divend() } Screen Shot: 41.19 Using Bootstrap Library using Objects The next example uses the Bootstrap JavaScript Library when generating the HTML page. Instead of using functions to generate the HTML elements, we will use objects. #!c:ringbinring.exe -cgi Load "weblib.ring" Import System.Web Func Main 41.19. Using Bootstrap Library using Objects 285
307.
Ring Documentation, Release1.2 BootStrapWebPage() { div { classname = :container div { classname = :jumbotron H1 { text("Bootstrap Page") } } div { classname = :row for x = 1 to 3 div { classname = "col-sm-4" H3 { html("Welcome to the Ring programming language") } P { html("Using a scripting language is very fun!") } } next } div { classname = :row div { classname = "col-sm-4" Button { classname = "btn btn-info btn-lg" datatoggle= "modal" datatarget = "#myModal" text("Open Large Modal") } } div { classname = "col-sm-4" Button { classname = "btn btn-default btn-lg" text("default") } Button { classname = "btn btn-primary btn-md" text("primary") } Button { classname = "btn btn-sucess btn-sm" text("sucess") } Button { classname = "btn btn-info btn-xs" text("info") } Button { classname = "btn btn-warning" text("warning") } Button { classname = "btn btn-danger" text("danger") } Button { classname = "btn btn-link" text("link") } } div { classname = "col-sm-4" Button { classname = "btn btn-default btn-block" text("default") } Button { classname = "btn btn-primary btn-block" text("primary") } Button { classname = "btn btn-sucess btn-block" text("sucess") } Button { classname = "btn btn-info btn-block" text("info") } Button { classname = "btn btn-warning btn-block" text("warning") } Button { classname = "btn btn-danger btn-block" text("danger") } Button { classname = "btn btn-link btn-block" text("link") } } 41.19. Using Bootstrap Library using Objects 286
308.
Ring Documentation, Release1.2 div { classname = "col-sm-4" div { classname = "btn-group" button { classname="btn btn-primary" text("one") } button { classname="btn btn-primary" text("two") } button { classname="btn btn-primary" text("three") } } } div { classname = "col-sm-4" div { classname = "btn-group btn-group-lg" button { classname="btn btn-primary" text("one") } button { classname="btn btn-primary" text("two") } button { classname="btn btn-primary" text("three") } } } div { classname = "col-sm-4" div { classname = "btn-group-vertical btn-group-lg" button { classname="btn btn-primary" text("one") } button { classname="btn btn-primary" text("two") } button { classname="btn btn-primary" text("three") } } } } div { classname="modal fade" id="myModal" role="dialog" div { classname = "modal-dialog modal-lg" div { classname="modal-content" div { classname="modal-header" button { classname="close" datadismiss="modal" html("×") } h4 { classname="modal-title" text("Modal Header") } } div { classname = "modal-body" p { text("This is a large model.") } } div { classname="modal-footer" button { classname = "btn btn-default" datadismiss="modal" text("close") } } } } } } } Screen Shot: 41.19. Using Bootstrap Library using Objects 287
309.
Ring Documentation, Release1.2 41.20 CRUD Example using MVC The next example uses the weblib.ring & datalib.ring. The datalib.ring contains classes for creating database applications using MVC pattern. In this example we create an object from the SalaryController class then call the Routing method. We define the website variable to contains the basic url of the page. When we create the SalaryModel class from the ModelBase class, the salary table will be opened and the columns data will be defined as attributes in the model class. The SalaryView class create an object from the SalaryLanguageEnglish class to be used for translation. The method AddFuncScript is used to call the form for adding/modifying record data. The method FormViewContent is used to determine the controls in the form when we add or modify a record. #!c:ringbinring.exe -cgi Load "weblib.ring" Load "datalib.ring" Import System.Web website = "ex24.ring" New SalaryController { Routing() } 41.20. CRUD Example using MVC 288
310.
Ring Documentation, Release1.2 Class SalaryModel from ModelBase Class SalaryController From ControllerBase Class SalaryView From ViewBase oLanguage = new SalaryLanguageEnglish Func AddFuncScript oPage,oController return oPage.scriptfuncajax("myadd",oController.cMainURL+ oController.cOperation+"=add","mysubpage") Func FormViewContent oController,oTranslation,oPage return [ [ oTranslation.aColumnsTitles[2], "textbox", "name", oController.oModel.Name, oPage.stylewidth("100%") ], [ oTranslation.aColumnsTitles[3], "textbox", "salary", oController.oModel.Salary, oPage.stylewidth("50%") ] ] Class SalaryLanguageEnglish cTitle = "Salary Table" cBack = "back" aColumnsTitles = ["ID","Name","Salary"] cOptions = "Options" cSearch = "Search" comboitems = ["Select Option...","Edit","Delete"] cAddRecord = "Add Record" cEditRecord = "Edit Record" cRecordDeleted = "Record Deleted!" aMovePages = ["First","Prev","Next","Last"] cPage = "Page" cOf = "of" cRecordsCount = "Records Count" cSave = "Save" temp = new page cTextAlign = temp.StyleTextRight() cNoRecords = "No records!" Screen Shot: 41.20. CRUD Example using MVC 289
311.
Ring Documentation, Release1.2 41.21 Users registration and Login We have the users classes (Model, View & Controller) to deal with the users data like username & email. The next code is stored in ex25_users.ring Class UsersModel from ModelBase cSearchColumn = "username" Class UsersController From ControllerBase 41.21. Users registration and Login 290
312.
Ring Documentation, Release1.2 aColumnsNames = ["id","username","email"] Func UpdateRecord oModel.id = aPageVars[cRecID] oModel.updatecolumn("username", aPageVars[:username] ) oModel.updatecolumn("email", aPageVars[:email] ) oView.UpdateView(self) Class UsersView from ViewBase oLanguage = new UsersLanguageEnglish Func AddFuncScript oPage,oController return oPage.scriptfunc("myadd",oPage.scriptredirection("ex26.ring")) Func FormViewContent oController,oTranslation,oPage return [ [oTranslation.aColumnsTitles[2],"textbox","username", oController.oModel.UserName,oPage.stylewidth("100%")], [oTranslation.aColumnsTitles[3],"textbox","email", oController.oModel.Email,oPage.stylewidth("50%")] ] Class UsersLanguageEnglish cTitle = "Users Table" cBack = "back" aColumnsTitles = ["ID","User Name","Email"] cOptions = "Options" cSearch = "Search" comboitems = ["Select Option...","Edit","Delete"] cAddRecord = "Add Record" cEditRecord = "Edit Record" cRecordDeleted = "Record Deleted!" aMovePages = ["First","Prev","Next","Last"] cPage = "Page" cOf = "of" cRecordsCount = "Records Count" cSave = "Save" temp = new page cTextAlign = temp.StyleTextRight() cNoRecords = "No records!" In the file ex25.ring we load ex25_users.ring then create an object from UsersController class. Using the created object, we call the routing method. #!c:ringbinring.exe -cgi Load "weblib.ring" Load "datalib.ring" Load "ex25_users.ring" Import System.Web website = "ex25.ring" New UsersController { Routing() } Screen Shot: 41.21. Users registration and Login 291
Ring Documentation, Release1.2 oUser = new UsersModel oUser.Connect() lResult = oUser.FindWith("username",aPageVars["username"]) new page { if lResult if sha256(aPagevars["password"]+oUser.Salt) = oUser.pwhash text ("Correct Password!") aPageVars["sessionid"] = str2hex(randbytes(32)) oUser.UpdateColumn("sessionid",aPageVars["sessionid"]) cookie("sessionid",aPageVars["sessionid"]) else text ("Bad password!") ok else text("Bad User Name!") ok } oUser.Disconnect() The next code for checking if the user needs to login or not #!c:ringbinring.exe -cgi Load "weblib.ring" Load "datalib.ring" Load "ex25_users.ring" Import System.Web oUser = new UsersModel oUser.Connect() lResult = oUser.FindWith("sessionid",aPageVars["sessionid"]) new page { if lResult text("User Name : " + oUser.username ) else text("Please Login First!") ok } oUser.Disconnect() 41.22 Database, ModelBase & ControllerBase classes In this section we will see some code from datalib.ring The next code presents the Database, ModelBase & ControllerBase classes Import System.Web Class Database cServer = "localhost" cUserName = "root" cPassword = "root" cDatabase = "mahdb" Func Connect 41.22. Database, ModelBase & ControllerBase classes 296
318.
Ring Documentation, Release1.2 con = mysql_init() mysql_connect(con, cServer, cUserName, cPassWord,cDatabase) Func Disconnect mysql_close(con) Func Query cQuery mysql_query(con,cQuery) Func QueryResult return mysql_result(con) Func QueryResultWithColumns # return columns names + query result return mysql_result2(con) Func QueryValue aResult = mysql_result(con) if islist(aResult) and len(aResult) >= 1 aResult = aResult[1] if len(aResult) >= 1 return aResult[1] ok ok return 0 Func EscapeString x if isstring(x) return MySQL_Escape_String(con,x) else return MySQL_Escape_String(con,string(x)) ok Private con = NULL Class ModelBase from Database cTableName = "" cSearchColumn = "name" aColumns = [] aQueryResult = [] ID = 0 # set table name from class name classname = lower(classname(self)) if right(classname,5) = :model cTablename = left(classname,len(classname)-5) ok Func Insert cValues = "" for x in aColumns cValues += "'" + EscapeString(aPageVars[x]) + "'," 41.22. Database, ModelBase & ControllerBase classes 297
319.
Ring Documentation, Release1.2 Next cValues = left(cValues,len(cValues)-1) # remove last comma cColumns = "" for x in aColumns cColumns += x + "," next cColumns = left(cColumns,len(cColumns)-1) query("insert into " + cTableName + "("+cColumns+") values (" + cValues + ")" ) Func Update nID cStr = "" for x in aColumns cStr += x + " = '" + EscapeString(aPageVars[x]) + "' , " # the space after comma is necessary Next cStr = left(cStr,len(cStr)-2) query("update " + cTableName + " set " + cStr + " where id = " + nID ) Func UpdateColumn cColumn,cValue query("update " + cTableName + " set " + cColumn + " = '" + EscapeString(cValue) + "' where id = " + self.ID ) Func Count cValue query("SELECT count(*) FROM " + cTableName + " where "+cSearchColumn+" like '" + EscapeString(cValue) + "%'") return queryValue() Func Read nStart,nRecordsPerPage query("SELECT * FROM "+ cTableName+" limit " + EscapeString(nStart) + "," + EscapeString(nRecordsPerPage) ) aQueryResult = queryResult() Func Search cValue,nStart,nRecordsPerPage query("SELECT * FROM "+ cTableName+" where "+cSearchColumn+" like '" + EscapeString(cValue) + "%'" + " limit " + EscapeString(nStart) + "," + EscapeString(nRecordsPerPage) ) aQueryResult = queryResult() Func Find nID query("select * from " + cTableName + " where id = " + EscapeString(nID) ) aResult = queryResult()[1] # move the result from the array to the object attributes ID = nID cCode = "" for x = 2 to len(aResult) cCode += aColumns[x-1] + " = hex2str('" + str2hex(aResult[x]) + "')" + nl next eval(cCode) Func FindWith cColumn,cValue 41.22. Database, ModelBase & ControllerBase classes 298
320.
Ring Documentation, Release1.2 query("select * from " + cTableName + " where "+cColumn+" = '" + EscapeString(cValue) + "'" ) aResult = queryResult() if len(aResult) > 0 aResult = aResult[1] else return 0 ok # move the result from the array to the object attributes ID = aResult[1] cCode = "" for x = 2 to len(aResult) cCode += aColumns[x-1] + " = hex2str('" + str2hex(aResult[x]) + "')" + nl next eval(cCode) return 1 Func Delete ID query("delete from " + cTableName + " where id = " + EscapeString(ID) ) Func Clear cCode = "" for x in aColumns cCode += x + ' = ""' + nl next eval(cCode) Func LoadModel # create the columns array query("SELECT * FROM "+ cTableName + " limit 0,1") aQueryResult = QueryResultWithColumns()[1] for x = 2 to len(aQueryResult) aColumns + lower(trim(aQueryResult[x])) next # create attribute for each column for x in aColumns addattribute(self,x) next Func Connect Super.Connect() if nLoadModel = 0 nLoadModel = 1 LoadModel() ok private nLoadModel = 0 Class ControllerBase 41.22. Database, ModelBase & ControllerBase classes 299
321.
Ring Documentation, Release1.2 nRecordsPerPage = 5 nRecordsCount = 0 nPagesCount = 0 nActivePage = 0 # Dynamic creation of oView = new tablenameView and oModel = new tablename.Model classname = lower(classname(self)) if right(classname,10) = :controller tablename = left(classname,len(classname)-10) cCode = "oView = new " + tablename+"View" + nl cCode += "oModel = new " + tablename+"Model" + nl eval(cCode) oModel.connect() ok cSearchName = "searchname" cPart = "part" cPageError = "The page number is not correct" cLast = "last" cOperation = "operation" cRecID = "recid" aColumnsNames = ["id"] for t in oModel.aColumns aColumnsNames + t next cMainURL = website + "?" func Routing switch aPageVars[cOperation] on NULL showtable() on :add addrecord() on :save saverecord() on :delete deleterecord() on :edit editrecord() on :update updaterecord() off func ShowTable nRecordsCount = oModel.Count( aPageVars[cSearchName] ) nPagesCount = ceil(nRecordsCount / nRecordsPerPage) if aPageVars[cPart] = cLast aPageVars[cPart] = string(nPagesCount) ok nActivePage = number(aPageVars[cPart]) if nActivePage = 0 nActivePage = 1 ok if ( nActivePage > nPagesCount ) and nRecordsCount > 0 ErrorMsg(cPageError) return ok 41.22. Database, ModelBase & ControllerBase classes 300
322.
Ring Documentation, Release1.2 nStart = (nActivePage-1)*nRecordsPerPage if aPageVars[cSearchName] = NULL oModel.Read( nStart,nRecordsPerPage ) else oModel.Search( aPageVars[cSearchName],nStart,nRecordsPerPage ) ok oView.GridView(self) func AddRecord oModel.clear() oView.FormViewAdd(Self,:save,false) # false mean don't include record id func SaveRecord oModel.Insert() oView.SaveView(self) func EditRecord oModel.Find( aPageVars[cRecID] ) oView.FormViewEdit(Self,:update,true) # true mean include record id func UpdateRecord oModel.update( aPageVars[cRecID] ) oView.UpdateView(self) func DeleteRecord oModel.Delete( aPageVars[cRecID] ) oView.DeleteView() func braceend oModel.Disconnect() 41.23 WebLib API In this section we will see the web library functions, classes and methods. Function Parameters Description LoadVars None Save the request parameters and cookies to aPageVars List WebPage None Create new object from the WebPage Class BootStrapWebPage None Create new object from the BootStrapWebPage Class HTMLSpecialChars cString Encode Special characters to HTML equivalent Template cFile,oObject Execute Ring Code in cFile after accessing oObject using {} Alert cMessage Generate HTML Web Page that display cMessage using JavaScript Alert() HTML2PDF cString Generate and Display PDF File from HTML String (cString) The Package System.Web contains the next classes 41.23. WebLib API 301
323.
Ring Documentation, Release1.2 Class Name Description Application Contains methods for Encoding, Decoding, Cookies & More. Page Contains methods to generate HTML pages. ScriptFunctions Contains methods to generate some JavaScript Functions. StyleFunctions Contains methods to generate CSS. PageBuffer Generate HTML Page in memory (don’t print the output). HTML2PDF Generate PDF File from HTML code. BootStrapPage Using BootStrap Library. WebPage Generate page using objects for each element. BootStrapWebPage Generate page using objects, using BootStrap Library. ObjsBase Parent Class for page objects. NewObjectsFunctions Methods to create new objects in the page or element. H1 Wraps HTML H1. H2 Wraps HTML H2. H3 Wraps HTML H3. H4 Wraps HTML H4. H5 Wraps HTML H5. H6 Wraps HTML H6. P Wraps HTML P. Link Wraps HTML link. NewLine Wraps HTML NewLine. Div Wraps HTML Div. Form Wraps HTML Form. Input Wraps HTML Input. TextArea Wraps HTML TextArea. Select Wraps HTML Select. Option Wraps HTML Option. Image Wraps HTML Image. UL Wraps HTML UL. LI Wraps HTML LI. Table Wraps HTML Table. TR Wraps HTML TR. TD Wraps HTML TD. TH Wraps HTML TH. Audio Wraps HTML Audio. Video Wraps HTML Video. Nav Wraps HTML Nav. Span Wraps HTML Span. Button Wraps HTML Button. 41.23. WebLib API 302
324.
Ring Documentation, Release1.2 41.24 Application Class Method Parameters Description DecodeString cString Decode request parameters Decode cString Decode multipart/form-data GetFileName aArray,cVar Get File Name in aArray using cVar SetCookie name,value,expires,path,domain,secure Set Cookie Cookie name,value Set Cookie using name and value only GetCookies None Get Cookies URLEncode cString URL Encode ScriptLibs None Add JavaScript Libraries like BootStrap Print None Print Page Content Style cStyle Add cStyle to page CSS content StartHTML None Add HTTP Header to page content The method DecodeString is used to get HTTP request parameters. The methods Decode and GetFileName are used for uploading files. The methods SetCookie, Cookie & GetCookies are used for adding and reading cookies. The methods StartHTML, ScriptsLibs, Style & Print are used for page structure and JS/CSS support. The method URLEncode is used to encode a URL to be used in HTML pages. 41.25 Page Class Method Parameters Description text x add HTMLSpecialChars(x) to page content (accept strings and numbers) html cString add html code to page content h1 x add x to page content between <h1> and </h1> h2 x add x to page content between <h2> and </h2> h3 x add x to page content between <h3> and </h3> h4 x add x to page content between <h4> and </h4> h5 x add x to page content between <h5> and </h5> h6 x add x to page content between <h6> and </h6> p aPara HTML <p> </p>, uses aPara List as Hash to get attributes NewLine None add <br /> to page content AddAttributes aPara Convert aPara list as hash to HTML element attributes Link aPara HTML <a href> and </a>, uses aPara List as Hash to get attributes Image aPara HTML <img>, uses aPara List as Hash to get attributes Button aPara HTML <input type=”button”>, uses aPara List as Hash to get attributes ButtonLink aPara HTML <input type=”button”>, uses link attribute to navigate to link Textbox aPara HTML <input type=”text”>, uses aPara List as Hash to get attributes Editbox aPara HTML <textarea> and </textarea>, uses aPara to get attributes Combobox aPara HTML <select>, uses items attribute as list for <option> Listbox aPara HTML <select multiple=’multiple’>, uses items attribute for <option> ulstart aPara HTML <ul> ulend aPara HTML </ul> listart aPara HTML <li> liend aPara HTML </li> Continued on next page 41.24. Application Class 303
325.
Ring Documentation, Release1.2 Table 41.2 – continued from previous page Method Parameters Description List2UL aList Generate HTML <ul> including items from Ring List items DivStart aPara HTML <div>, uses aPara List as Hash to get attributes NavStart aPara HTML <nav>, uses aPara List as Hash to get attributes SpanStart aPara HTML <span>, uses aPara List as Hash to get attributes BoxStart None Generate Div with black background to be used as page header DivEnd None HTML </div> NavEnd None HTML </nav> SpanEnd None HTML </span> BoxEnd None HTML </div>, the same as divend() FormStart cAction HTML <form>, with cAction as the action attribute or an empty value FormPost cAction HTML <form method=”post”> , with cAction as the action attribute FormEnd None HTML </form> Submit aPara HTML <input type=”submit”> Hidden cName,cValue HTML <input type=”hidden”> FormUpload x HTML Form, method=”post” enctype=”multipart/form-data” and x = action UploadFile x HTML <input type=”file”> and name = x Video aPara HTML <video> Audio aPara HTML <audio> GetColor aPara Select Color Radio aPara HTML <input type=”radio”> Checkbox aPara HTML <input type=”checkbox”> Spinner aPara HTML <input type=”number”> Slider aPara HTML <input type=”range”> TableStart aPara HTML <table> TableEnd None HTML </table> RowStart aPara HTML <tr> RowEnd None HTML </tr> CellStart aPara HTML <td> CellEnd None HTML </td> HeaderStart aPara HTML <th> HeaderEnd None HTML </th> aPara in the page methods is a list contains attributes and values. Using aPara we can set values for the next attributes classname id name align style dir value onclick oncontextmenu ondblclick onmousedown onmouseenter onmouseleave onmousemove onmouseover onmouseout onmouseup onkeydown onkeypress onkeyup onabort onbeforeunload onerror onhashchange onload onpageshow onpagehide onresize onscroll onunload onblur onchange onfocus onfocusin onfocusout oninput oninvalid onreset onsearch onselect onsubmit ondrag ondragend ondragenter ondragleave ondragover ondragstart ondrop oncopy oncut onpaste onafterprint onbeforeprint oncanplay oncanplaythrough ondurationchange onemptied onended onloadeddata onloadedmetadata onloadstart onpause onplay onplaying onprogress onratechange onseeked onseeking onstalled onsuspend ontimeupdate onvolumechange onwaiting animationend animationiteration animationstart transitionend onmessage onopen onmousewheel ononline onoffline onpostate onshow onstorage ontoggle onwheel ontouchcancel ontouchend ontouchmove ontouchstart color opacity background backgroundattachment backgroundcolor backgroundimage backgroundposition backgroundrepeat backgroundclip backgroundorigin backgroundsize border borderbottom borderbottomcolor borderbottomleftradius borderbottomrightradius borderbottomstyle borderbottomwidth bordercolor borderimage borderimageoutset borderimagerepeat borderimageslice 41.25. Page Class 304
326.
Ring Documentation, Release1.2 borderimagesource borderimagewidth borderleft borderleftcolor borderleftstyle borderleftwidth borderradius borderright borderrightcolor borderrightstyle borderrightwidth borderstyle bordertop bordertopcolor bordertopleftradius bordertoprightradius bordertopstyle bordertopwidth borderwidth boxdecorationbreak boxshadow bottom clear clip display float height left margin marginbottom marginleft marginright margintop maxheight maxwidth minheight minwidth overflow overflowx overflowy padding paddingbottom paddingleft paddingright paddingtop position right top visibility width verticalalign zindex aligncontent alignitems alignself flex flexbasis flexdirection flexflow flexgrow flexshrink flexwrap justifycontent order hangingpunctuation hyphens letterspacing linebreak lineheight overflowwrap tabsize textalign textalignlast textcombineupright textindent textjustify texttransform whitespace wordbreak wordspacing wordwrap textdecoration textdecorationcolor textdecorationline textdecorationstyle textshadow textunderlineposition @fontface @fontfeaturevalues font fontfamily fontfeaturesettings fontkerning fontlanguageoverride fontsize fontsizeadjust fontstretch fontstyle fontsynthesis fontvariant fontvariantalternates fontvariantcaps fontvarianteastasian fontvariantligatures fontvariantnumeric fontvariantposition fontweight direction textorientation unicodebidi writingmode bordercollapse borderspacing captionside emptycells tablelayout counterincrement counterreset liststyle liststyleimage liststyleposition liststyletype @keyframes animation animationdelay animationdirection animationduration animationfillmode animationiterationcount animationname animationplaystate animationtimingfunction backfacevisibility perspective perspectiveorigin transform transformorigin transformstyle transition transitionproperty transitionduration transitiontimingfunction transitiondelay boxsizing content cursor imemode navdown navindex navleft navright navup outline outlinecolor outlineoffset outlinestyle outlinewidth resize textoverflow breakafter breakbefore breakinside columncount columnfill columngap columnrule columnrulecolor columnrulestyle columnrulewidth columnspan columnwidth columns widows orphans pagebreakafter pagebreakbefore pagebreakinside marks quotes filter imageorientation imagerendering imageresolution objectfit objectposition mask masktype mark markafter markbefore phonemes rest restafter restbefore voicebalance voiceduration voicepitch voicepitchrange voicerate voicestress voicevolume marqueedirection marqueeplaycount marqueespeed marqueestyle datatoggle dataride datatarget dataslideto dataslide datadismiss dataplacement datacontent datatrigger dataspy dataoffset dataoffsettop 41.26 ScriptFunctions Class This class contains methods for adding JavaScript code to the generated web page. The class methods are merged to the Page class, so we can use the next methods with page objects directly. Method Parameters Description Script cCode Add cCode string between <script> and </script> ScriptRedirec- tion cURL set window.location to cURL ScriptFunc cFuncName,cCode Define function cFuncName that contains cCode ScriptFuncAlert cFuncName,cMsg Define function cFuncName that uses alert() to print cMsg ScriptFuncAjax cFuncName,cLink,cDiv Define function cFuncName that load cLink in cDiv ScriptFuncClean cFuncName,cDiv Define function cFuncName that clear the cDiv ScriptFuncSe- lect cF,aL,cD,cR,cGR,cFC,nTO,cL1,cL2 Used to Edit/Delete Grid Record ScriptScroll- Fixed cDiv,nSize Set cDiv as Fixed Div with Size = nSize 41.26. ScriptFunctions Class 305
327.
Ring Documentation, Release1.2 41.27 StyleFunctions Class This class contains methods for adding CSS to the generated web page. Like ScriptFunctions Class, The StyleFunctions class methods are merged to the Page class, so we can use the next methods with page objects directly. Method Parameters Description StyleFloatLeft None Return float: left ; StyleFloatRight None Return float: right ; StyleSizeFull None Return width: 100% ; height: 100% ; Stylecolor x Return ” color: ” + x + ” ; “ Stylebackcolor x Return ” background-color: ” + x + ” ;” StyleTextCenter None Return “text-align: center ;” StyleTextRight None Return “text-align: right ;” StyleTextLeft None Return “text-align: left ;” StyleSize x,y Return ” width: ” + x + ” ; height: ” + y + ” ;” StyleWidth x Return ” width: ” + x + ” ;” StyleHeight x Return ” height: ” + x + ” ;” StyleTop x Return ” top: ” + x + ” ;” StyleLeft x Return ” Left: ” + x + ” ;” StylePos x,y Return ” top: ” + x + ” ;” + ” Left: ” + y + ” ;” StyleHorizontalCenter None Return ” margin-right:auto ; margin-left:auto; “ StyleMarginTop x Return ” margin-top: ” + x + ” ;” StyleMarginRight x Return ” margin-right: ” + x + ” ;” StyleMarginLeft x Return ” margin-left: ” + x + ” ;” StyleDivCenter nWidth,nHeight Create Div in the center of the page StyleAbsolute None Return ” position:absolute ;” StyleFixed None Return ” position:fixed ;” StyleZIndex x Return ” z-index: ” + x + ” ;” StyleFontSize x Return ” font-size: ” + x + ” ;” StyleGradient x Generate Gradient (x values from 1 to 60) StyleTable None Set table properties StyleTableRows id Set different color to even and odd rows in the table StyleTableNoBorder None Return ” border-style: none;” 41.27. StyleFunctions Class 306
328.
CHAPTER FORTYTWO USING RINGLIBCURL In thischapter we will learn about using RingLibCurl 42.1 Get Request Example: load "libcurl.ring" curl = curl_easy_init() curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1) curl_easy_setopt(curl, CURLOPT_URL, "http://ring-lang.sf.net") curl_easy_perform(curl) curl_easy_cleanup(curl) 42.2 Post Request Example: load "libcurl.ring" curl = curl_easy_init() cPostThis = "page=4&Number1=4&Number2=5" curl_easy_setopt(curl, CURLOPT_URL, "http://localhost/ringapp/index.ring?page=3") curl_easy_setopt(curl, CURLOPT_POSTFIELDS, cPostThis) curl_easy_perform(curl) curl_easy_cleanup(curl) 42.3 Facebook Login Example: 307
329.
Ring Documentation, Release1.2 load "libcurl.ring" see "Enter Email : " give $login_email See "Enter Password : " give $login_pass curl = curl_easy_init() curl_easy_setopt(curl, CURLOPT_URL, 'https://www.facebook.com/login.php') curl_easy_setopt(curl, CURLOPT_POSTFIELDS,'charset_test=j u s t a t e s t'+ ' &email='+urlencode($login_email)+'&pass='+ urlencode($login_pass)+'&login=Login') curl_easy_setopt(curl, CURLOPT_POST, 1) curl_easy_setopt(curl, CURLOPT_HEADER, 0) curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1) curl_easy_setopt(curl, CURLOPT_COOKIEJAR, "cookies.txt") curl_easy_setopt(curl, CURLOPT_COOKIEFILE, "cookies.txt") curl_easy_setopt(curl, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U;"+ " Windows NT 5.1; en-US; rv:1.8.1.3) Gecko/20070309 Firefox/2.0.0.3") curl_easy_setopt(curl, CURLOPT_REFERER, "http://www.facebook.com") curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, FALSE) curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2) mylist = curl_slist_append(NULL,'Accept-Charset: utf-8') curl_slist_append(mylist,'Accept-Language: en-us,en;q=0.7,bn-bd;q=0.3') curl_slist_append(mylist,'Accept: text/xml,application/xml,'+ 'application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5') curl_easy_setopt(curl, CURLOPT_HTTPHEADER, mylist) curl_easy_setopt(curl, CURLOPT_COOKIESESSION, false) curl_easy_perform(curl) curl_easy_cleanup(curl) Func URLEncode cStr cOut = "" for x in cStr if isalnum(x) cOut += x but x = " " cOut += "+" else cOut += "%"+str2hex(x) ok next return cOut 42.4 Save Output to String Example: load "libcurl.ring" curl = curl_easy_init() curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1) 42.4. Save Output to String 308
330.
Ring Documentation, Release1.2 curl_easy_setopt(curl, CURLOPT_URL, "http://ring-lang.sf.net") cOutput = curl_easy_perform_silent(curl) See "Output:" + nl see cOutput curl_easy_cleanup(curl) 42.4. Save Output to String 309
331.
CHAPTER FORTYTHREE GRAPHICS AND 2DGAMES PROGRAMMING USING RINGALLEGRO In this chapter we will learn how to use the allegro game programming library in our Ring applications. We have the file gamelib.ring that load the DLL library that contains wrappers for the Allegro functions Load "allegro.rh" Loadlib("ring_allegro.dll") The file gamelib.ring uses the Load instruction to execute the file allegro.rh which is a ring source code file con- tains constants to be used in our programs. Then using the function LoadLib() we can load the DLL library “ring_allegro.dll”. To write portable code we can change the gamelib.ring to check the platform before loading the DLL/So file. 43.1 Drawing, Animation and Input The next example uses the Allegro library for drawing, moving objects on the screen and getting input from the keyboard and the mouse. Load "gamelib.ring" al_init() al_init_image_addon() display = al_create_display(640,480) al_show_native_message_box(display, "Hello", "Welcome", "Using Allegro from the Ring programming language", "", 0); al_clear_to_color(al_map_rgb(0,0,255)) BOUNCER_SIZE = 40 bouncer_x = 10 bouncer_y = 20 bouncer = al_create_bitmap(BOUNCER_SIZE, BOUNCER_SIZE) al_set_target_bitmap(bouncer) al_clear_to_color(al_map_rgb(255,0,255)) for x = 1 to 30 bouncer_x += x bouncer_y += x al_set_target_bitmap(al_get_backbuffer(display)) al_clear_to_color(al_map_rgb(0,0,0)) 310
Ring Documentation, Release1.2 bouncer_dy = -bouncer_dy ok bouncer_x += bouncer_dx bouncer_y += bouncer_dy # Keyboard if key[KEY_UP] and bouncer_y >= 4.0 bouncer_y -= 4.0 ok if key[KEY_DOWN] and bouncer_y <= SCREEN_H - BOUNCER_SIZE - 4.0 bouncer_y += 4.0 ok if key[KEY_LEFT] and bouncer_x >= 4.0 bouncer_x -= 4.0 ok if key[KEY_RIGHT] and bouncer_x <= SCREEN_W - BOUNCER_SIZE - 4.0 bouncer_x += 4.0 ok redraw = true on ALLEGRO_EVENT_MOUSE_AXES bouncer_x = al_get_allegro_event_mouse_x(ev) bouncer_y = al_get_allegro_event_mouse_y(ev) on ALLEGRO_EVENT_MOUSE_ENTER_DISPLAY bouncer_x = al_get_allegro_event_mouse_x(ev) bouncer_y = al_get_allegro_event_mouse_y(ev) on ALLEGRO_EVENT_MOUSE_BUTTON_UP exit on ALLEGRO_EVENT_KEY_DOWN switch al_get_allegro_event_keyboard_keycode(ev) on ALLEGRO_KEY_UP key[KEY_UP] = true on ALLEGRO_KEY_DOWN key[KEY_DOWN] = true on ALLEGRO_KEY_LEFT key[KEY_LEFT] = true on ALLEGRO_KEY_RIGHT key[KEY_RIGHT] = true off on ALLEGRO_EVENT_KEY_UP switch al_get_allegro_event_keyboard_keycode(ev) on ALLEGRO_KEY_UP key[KEY_UP] = false on ALLEGRO_KEY_DOWN key[KEY_DOWN] = false on ALLEGRO_KEY_LEFT key[KEY_LEFT] = false on ALLEGRO_KEY_RIGHT key[KEY_RIGHT] = false on ALLEGRO_KEY_ESCAPE exit off off if redraw and al_is_event_queue_empty(event_queue) redraw = false al_clear_to_color(al_map_rgb(0,0,0)) 43.1. Drawing, Animation and Input 312
334.
Ring Documentation, Release1.2 al_draw_bitmap(bouncer, bouncer_x, bouncer_y, 0) al_flip_display() ok callgc() end al_destroy_timer(timer) al_destroy_allegro_event(ev) al_destroy_allegro_timeout(timeout) al_destroy_event_queue(event_queue) al_destroy_bitmap(bouncer) al_destroy_bitmap(image) al_destroy_display(display) Note: In the previous example we used the function callgc() which is a Ring function to force calling the Garbage collector inside the While/End loop. Program Output: At first the program display a messagebox Then we see two rectangles are moving on the screen 43.1. Drawing, Animation and Input 313
335.
Ring Documentation, Release1.2 Then we see an image displayed on the screen 43.1. Drawing, Animation and Input 314
336.
Ring Documentation, Release1.2 Finally we have one rectangle, and we see it moving all of the time on the screen but we can control it using the Mouse and/or the Keyborad 43.1. Drawing, Animation and Input 315
337.
Ring Documentation, Release1.2 43.2 Using TrueType Fonts In this example we will see how to use TrueType Fonts *.ttf in our Games using Allegro Load "gamelib.ring" al_init() al_init_font_addon() al_init_ttf_addon() display = al_create_display(800,600) al_clear_to_color(al_map_rgb(0,0,255)) font = al_load_ttf_font("pirulen.ttf",14,0 ) al_draw_text(font, al_map_rgb(255,255,255), 10, 10,ALLEGRO_ALIGN_LEFT, "Welcome to the Ring programming language") al_flip_display() al_rest(2) al_destroy_display(display) Screen Shot: 43.2. Using TrueType Fonts 316
338.
Ring Documentation, Release1.2 43.3 Playing Sound Files The next example play a sound file Load "gamelib.ring" al_init() al_install_audio() al_init_acodec_addon() al_reserve_samples(1) sample = al_load_sample( "footstep.wav" ) sampleid = al_new_allegro_sample_id() al_play_sample(sample, 1.0, 0.0,1.0,ALLEGRO_PLAYMODE_LOOP,sampleid) display = al_create_display(640,480) al_clear_to_color(al_map_rgb(0,0,255)) al_flip_display() al_rest(10) al_destroy_allegro_sample_id(sampleid) 43.3. Playing Sound Files 317
339.
Ring Documentation, Release1.2 al_destroy_sample(sample) al_destroy_display(display) al_exit() 43.4 Scaling and Rotating Images The next example display and rotate an image Load "gamelib.ring" al_init() al_init_image_addon() display = al_create_display(640,480) al_set_target_bitmap(al_get_backbuffer(display)) al_clear_to_color(al_map_rgb(255,255,255)) image = al_load_bitmap("man2.jpg") al_draw_rotated_bitmap(image,0,0,250,250,150,0) al_draw_scaled_bitmap(image,0,0,250,250,20,20,400,400,0) al_flip_display() al_rest(2) al_destroy_bitmap(image) al_destroy_display(display) Screen Shot: 43.4. Scaling and Rotating Images 318
340.
Ring Documentation, Release1.2 43.5 Display Transparent Image The next example display image with white background on another image Load "gamelib.ring" al_init() al_init_image_addon() display = al_create_display(640,480) imageback = al_load_bitmap("palace.jpg") al_draw_bitmap(imageback,0,0,0) image = al_load_bitmap("man4.png") al_convert_mask_to_alpha(image,al_map_rgb(255,255,255)) al_draw_bitmap(image,0,0,0) al_flip_display() al_rest(10) al_destroy_bitmap(image) al_destroy_display(display) 43.5. Display Transparent Image 319
341.
Ring Documentation, Release1.2 Screen Shot: 43.6 Using Threads In this example we will learn how to use threads from the Allegro library Load "gamelib.ring" o1 = new mythreads Func Main al_init() for k = 1 to 5 al_create_thread("o1.thread1()") al_create_thread("o1.thread2()") al_create_thread("o1.thread3()") next al_rest(2) Class Mythreads cAppName = "Threads Application" 43.6. Using Threads 320
342.
Ring Documentation, Release1.2 Func Thread1 for x = 1 to 5 see x + nl next See 'Thread(1) : Application Name : ' + cAppName + nl Func Thread2 for x = 1 to 5 see '*****' + x + nl next See 'Thread(2) : Application Name : ' + cAppName + nl Func Thread3 for x = 1 to 5 see '!!!!' + x + nl next See 'Thread(3) : Application Name : ' + cAppName + nl Output: 1 2 3 4 5 Thread(1) : Application Name : Threads Application *****1 *****2 *****3 *****4 *****5 Thread(2) : Application Name : Threads Application !!!!1 !!!!2 !!!!3 !!!!4 !!!!5 Thread(3) : Application Name : Threads Application 1 2 3 4 5 Thread(1) : Application Name : Threads Application !!!!1 !!!!2 !!!!3 !!!!4 !!!!5 Thread(3) : Application Name : Threads Application *****1 *****2 *****3 *****4 *****5 Thread(2) : Application Name : Threads Application *****1 *****2 43.6. Using Threads 321
CHAPTER FORTYFIVE DEMO PROJECT -GAME ENGINE FOR 2D GAMES In this chapter we will learn about using the different programming paradigms in the same project. We will create a simple Game Engine for 2D Games. You can use the Engine directly to create 2D Games for Desktop or Mobile. 45.1 Project Layers The project contains the next layers • Games Layer (Here we will use declarative programming) • Game Engine Classes (Here we will use the Object-Oriented Programming paradigm) • Interface to graphics library (Here we will use procedural programming) • Graphics Library bindings (Here we have RingAllegro and RingLibSDL) 45.2 Graphics Library bindings We already have RingAllegro to use the Allegro game programming library and we have RingLibSDL to use the LibSDL game programming library. Both of RingAllegro and RingLibSDL are created using the C language with the help of the Ring code generator for extensions. Each of them is over 10,000 lines of C code which is generated after writing simple configuration files (That are processed by the code generator). Each configuration file determines the functions names, structures information and constants then the generator process this configuration file to produce the C code and the library that can be loaded from Ring code. Using RingAllegro and RingLibSDL is very similar to using Allegro and LibSDL from C code where you have the same functions but we can build on that using the Ring language features • RingAllegro Source Code : https://github.com/ring-lang/ring/tree/master/extensions/ringallegro • RingLibSDL Source Code : https://github.com/ring-lang/ring/tree/master/extensions/ringsdl 330
352.
Ring Documentation, Release1.2 45.3 Interface to graphics library In this layer we have gl_allegro.ring and gl_libsdl.ring Each library provides the same functions to be used with interacting with the Graphics Library. This layer hides the details and the difference between RingAllegro and RingLibSDL. You have the same functions, Just use it and you can switch between Allegro and LibSDL at anytime. Why ? Allegro is very simple, we can use it to quickly create 2D games for Windows, Linux and MacOS X. In Ring 1.0 we started by supporting Allegro. Also LibSDL is very powerful and popular, very easy to use for Mobile Development. Ring 1.1 comes with support for LibSDL so we can quickly create games for Mobile. Note: We can use just one library for Desktop and Mobile development. • gl_allegro.ring source code : https://github.com/ring-lang/ring/blob/master/ringlibs/gameengine/gl_allegro.ring • gl_libsdl.ring source code : https://github.com/ring-lang/ring/blob/master/ringlibs/gameengine/gl_libsdl.ring 45.4 Game Engine Classes The Engine comes with the next classes • GameBase class • Resources class • Game class • GameObject class • Sprite class • Text class • Animate class • Sound class • Map class • Source Code : https://github.com/ring-lang/ring/blob/master/ringlibs/gameengine/gameengine.ring 45.5 Games Layer In this layer we create our games using the Game Engine classes The classes are designed to be used through Declarative Programming. In our games we will use the next classes • Game class • Sprite class 45.3. Interface to graphics library 331
353.
Ring Documentation, Release1.2 • Text class • Animate class • Sound class • Map class Note: Other classes in the engine are for internal use by the engine. We will introduce some examples and three simple games :- • Stars Fighter Game • Flappy Bird 3000 Game • Super Man 2016 Game 45.6 Game Class The next table present the class attributes. Attributes Description FPS Number determines how many times the draw() method will be called per second. FixedFPS Number determines how many times the animate() method will be called per second. Title String determines the window title of the game. aObjects List contains all objects in the game shutdown True/False value to end the game loop The next table present the class methods. Method Description refresh() Delete objects. settitle(cTitle) Set the window title using a string parameter. shutdown() Close the application. The next table present a group of keywords defined by the class. Keyword Description sprite Create new Sprite object and add it to the game objects. text Create new Text object and add it to the game objects. animate Create new Animate object and add it to the game objects. sound Create new Sound object and add it to the game objects. map Create new Map object and add it ot the game objects. 45.7 GameObject Class The next table present the class attributes. 45.6. Game Class 332
354.
Ring Documentation, Release1.2 Attributes Description enabled True/False determine the state of the object (Active/Not Active) x Number determine the x position of the object. y Number determine the y position of the object. width Number determine the width of the object. height Number determine the height of the object. nIndex Number determine the index of the object in objects list. animate True/False to animate the object or not. move True/False to move the object using the keyboard or not. Scaled True/False to scale the object image or not. draw Function to be called when drawing the object. state Function to be called for object animation. keypress Function to be called when a key is pressed. mouse Function to be called when a mouse event happens. The next table present the class methods. Method Description keyboard(oGame,nkey) Check Keyboard Events mouse(oGame,nType,aMouseList) Check Mouse Events rgb(r,g,b) Return new color using the RGB (Red, Green and Blue) Values. 45.8 Sprite Class Parent Class : GameObject Class The next table present the class attributes. Attributes Description image String determine the image file name. point Number determine the limit of automatic movement of the object. direction Number determine the direction of movement. nstep Number determine the increment/decrement during movement. type Number determine the object type in the game (Optional). transparent True/False value determine if the image is transparent. The next table present the class methods. Method Description Draw(oGame) Draw the object 45.9 Text Class Parent Class : Sprite Class The next table present the class attributes. Attributes Description size Number determine the font size font String determine the font file name text String determine the text to be displayed color Number determine the color The next table present the class methods. 45.8. Sprite Class 333
355.
Ring Documentation, Release1.2 Method Description Draw(oGame) Draw the object 45.10 Animate Class Parent Class : Sprite Class The next table present the class attributes. Attributes Description frames Number determine the number of frames frame Number determine the active frame framewidth Number determine the frame width. animate True/False determine using animate or not. scaled True/False determine scaling image or not. The next table present the class methods. Method Description Draw(oGame) Draw the object 45.11 Sound Class Parent Class : GameObject Class The next table present the class attributes. Attributes Description file String determine the sound file name. once True/False determine to play the file one time or not (loop). The next table present the class methods. Method Description playsound() Play the sound file 45.12 Map Class Parent Class : Sprite Class The next table present the class attributes. Attributes Description aMap List determine the map content using numbers. aImages List determine the image used for each number in the map. BlockWidth Number determine the block width (default = 32). BlockHeight Number determine the block height (default = 32). Animate True/False determine the animation status. The next table present the class methods. Method Description getvalue(x,y) Return the item value in the Map according to the visible part 45.10. Animate Class 334
356.
Ring Documentation, Release1.2 45.13 Using the Game Engine - Creating the Game Window Load "gameengine.ring" # Give Control to the Game Engine func main # Called by the Game Engine oGame = New Game # Create the Game Object { title = "My First Game" } # Start the Events Loop Note: if you want to define global variables, this must be before load “gameengine.ring” because this instruction will give the control to the game engine. Screen Shot: 45.14 Using the Game Engine - Drawing Text Load "gameengine.ring" # Give Control to the Game Engine func main # Called by the Game Engine 45.13. Using the Game Engine - Creating the Game Window 335
357.
Ring Documentation, Release1.2 oGame = New Game # Create the Game Object { title = "My First Game" text { x = 10 y=50 animate = false size = 20 file = "fonts/pirulen.ttf" text = "game development using ring is very fun!" color = rgb(0,0,0) } } # Start the Events Loop Screen Shot: 45.15 Using the Game Engine - Moving Text Load "gameengine.ring" # Give Control to the Game Engine func main # Called by the Game Engine oGame = New Game # Create the Game Object 45.15. Using the Game Engine - Moving Text 336
358.
Ring Documentation, Release1.2 { title = "My First Game" text { x = 10 y=50 animate = false size = 20 file = "fonts/pirulen.ttf" text = "game development using ring is very fun!" color = rgb(0,0,0) # Color = black } text { x = 10 y=150 # Animation Part ===================================== animate = true # Use Animation direction = GE_DIRECTION_INCVERTICAL # Increase y point = 400 # Continue until y=400 nStep = 3 # Each time y+= 3 #===================================================== size = 20 file = "fonts/pirulen.ttf" text = "welcome to the real world!" color = rgb(0,0,255) # Color = Blue } } # Start the Events Loop Screen Shot: 45.15. Using the Game Engine - Moving Text 337
359.
Ring Documentation, Release1.2 45.16 Using the Game Engine - Playing Sound Load "gameengine.ring" # Give Control to the Game Engine func main # Called by the Game Engine oGame = New Game # Create the Game Object { title = "My First Game" text { x = 10 y=50 animate = false size = 20 file = "fonts/pirulen.ttf" text = "game development using ring is very fun!" color = rgb(0,0,0) # Color = black } text { x = 10 y=150 # Animation Part ====================================== animate = true # Use Animation direction = GE_DIRECTION_INCVERTICAL # Increase y 45.16. Using the Game Engine - Playing Sound 338
360.
Ring Documentation, Release1.2 point = 400 # Continue until y=400 nStep = 3 # Each time y+= 3 #====================================================== size = 20 file = "fonts/pirulen.ttf" text = "welcome to the real world!" color = rgb(0,0,255) # Color = Blue } Sound { # Play Sound file = "sound/music1.wav" # Sound File Name } } # Start the Events Loop 45.17 Using the Game Engine - Animation Load "gameengine.ring" # Give Control to the Game Engine func main # Called by the Game Engine oGame = New Game # Create the Game Object { title = "My First Game" animate { file = "images/fire.png" x = 100 y = 200 framewidth = 40 height = 42 nStep = 3 # Used for delay transparent = true state = func oGame,oSelf { # Called by engine each frame oSelf { nStep-- if nStep = 0 nStep = 3 if frame < 13 # we have 13 frames in animation frame++ # move to next frame else oGame.remove(oself.nIndex) # remove object ok ok } } } } # Start the Events Loop 45.17. Using the Game Engine - Animation 339
361.
Ring Documentation, Release1.2 45.18 Using the Game Engine - Animation and Functions Load "gameengine.ring" # Give Control to the Game Engine func main # Called by the Game Engine oGame = New Game # Create the Game Object { title = "My First Game" for x = 70 to 700 step 50 for y = 70 to 500 step 50 showfire(oGame,x,y) next next } # Start the Events Loop func showfire oGame,nX,nY oGame { animate { file = "images/fire.png" x = nX 45.18. Using the Game Engine - Animation and Functions 340
362.
Ring Documentation, Release1.2 y = nY framewidth = 40 height = 42 nStep = 3 # Used for delay transparent = true state = func oGame,oSelf { # Called by engine each frame oSelf { nStep-- if nStep = 0 nStep = 3 if frame < 13 # we have 13 frames in animation frame++ # move to next frame else frame=1 ok ok } } } } 45.18. Using the Game Engine - Animation and Functions 341
363.
Ring Documentation, Release1.2 45.19 Using the Game Engine - Sprite - Automatic Movement using Keyboard Load "gameengine.ring" # Give control to the game engine func main # Called by the Game Engine oGame = New Game # Create the Game Object { title = "My First Game" sprite { type = GE_TYPE_PLAYER # Just for our usage x=400 y=400 width=100 height=100 file = "images/player.png" transparent = true Animate=false Move=true # we can move it using keyboard arrows Scaled=true } } # Start the Events Loop 45.19. Using the Game Engine - Sprite - Automatic Movement using Keyboard 342
364.
Ring Documentation, Release1.2 45.20 Using the Game Engine - Sprite - Keypress event Load "gameengine.ring" # Give control to the game engine func main # Called by the Game Engine oGame = New Game # Create the Game Object { title = "My First Game" sprite { type = GE_TYPE_PLAYER # Just for our usage x=400 y=400 width=100 height=100 file = "images/player.png" transparent = true Animate=false Move=false # Custom Movement Scaled=true keypress = func oGame,oSelf,nKey { oSelf { Switch nKey on KEY_LEFT x -= 10 on KEY_RIGHT x += 10 on KEY_UP y -= 10 on KEY_DOWN y += 10 off } } } } # Start the Events Loop 45.21 Using the Game Engine - Sprite - Mouse event Load "gameengine.ring" # Give control to the game engine func main # Called by the Game Engine oGame = New Game # Create the Game Object { title = "My First Game" sprite { type = GE_TYPE_PLAYER # Just for our usage x=400 y=400 width=100 height=100 file = "images/player.png" transparent = true Animate=false Move=false # Custom Movement Scaled=true keypress = func oGame,oSelf,nKey { oSelf { 45.20. Using the Game Engine - Sprite - Keypress event 343
365.
Ring Documentation, Release1.2 Switch nKey on KEY_LEFT x -= 10 on KEY_RIGHT x += 10 on KEY_UP y -= 10 on KEY_DOWN y += 10 off } } mouse = func oGame,oSelf,nType,aMouseList { if nType = GE_MOUSE_UP oSelf { x = aMouseList[GE_MOUSE_X] y = aMouseList[GE_MOUSE_Y] } ok } } } # Start the Events Loop 45.22 Using the Game Engine - Sprite - State event Load "gameengine.ring" # Give control to the game engine func main # Called by the Game Engine oGame = New Game # Create the Game Object { title = "My First Game" sprite { type = GE_TYPE_PLAYER # Just for our usage x=400 y=400 width=100 height=100 file = "images/player.png" transparent = true Animate=false Move=false # Custom Movement Scaled=true keypress = func oGame,oSelf,nKey { oSelf { Switch nKey on KEY_LEFT x -= 10 on KEY_RIGHT x += 10 on KEY_UP y -= 10 on KEY_DOWN y += 10 off } } mouse = func oGame,oSelf,nType,aMouseList { 45.22. Using the Game Engine - Sprite - State event 344
366.
Ring Documentation, Release1.2 if nType = GE_MOUSE_UP oSelf { x = aMouseList[GE_MOUSE_X] y = aMouseList[GE_MOUSE_Y] } ok } state = func oGame,oSelf { oself { if x < 0 x = 0 ok if y < 0 y = 0 ok if x > ogame.width-width x= ogame.width - width ok if y > ogame.height-height y=ogame.height - height ok } } } } # Start the Events Loop 45.23 Using the Game Engine - Animate - Events Load "gameengine.ring" # Give control to the game engine func main # Called by the Game Engine oGame = New Game # Create the Game Object { title = "My First Game" animate { file = "images/fbbird.png" x = 10 y = 10 framewidth = 20 scaled = true height = 50 width = 50 nStep = 3 transparent = true state = func oGame,oSelf { oSelf { # Animation nStep-- if nStep = 0 nStep = 3 if frame < 3 frame++ else frame=1 ok ok 45.23. Using the Game Engine - Animate - Events 345
367.
Ring Documentation, Release1.2 # Move Down y += 3 if y > 550 y=550 ok } } keypress = func ogame,oself,nKey { oself { if nkey = key_space y -= 55 if y<=0 y=0 ok ok } } mouse = func ogame,oself,nType,aMouseList { if nType = GE_MOUSE_UP cFunc = oself.keypress call cFunc(oGame,oSelf,Key_Space) ok } } } # Start the Events Loop Screen Shot: 45.23. Using the Game Engine - Animate - Events 346
368.
Ring Documentation, Release1.2 45.24 Using the Game Engine - Map Load "gameengine.ring" # Give control to the game engine func main # Called by the Game Engine oGame = New Game # Create the Game Object { title = "My First Game" Map { blockwidth = 80 blockheight = 80 aMap = [ [0,0,0,0,0,0,0,0,0,1,0,0,0,3,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0], [0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0], [0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,2,0,0,0,1,0,0,0], [0,0,0,0,0,0,0,0,0,1,0,0,0,2,0,0,0,3,0,0,0,1,0,0,0,1,0,0,0], [0,0,0,0,0,0,0,0,0,3,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,3,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0], 45.24. Using the Game Engine - Map 347
369.
Ring Documentation, Release1.2 [0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0] ] aImages = ["images/fbwall.png", "images/fbwallup.png", "images/fbwalldown.png"] state = func oGame,oSelf { oSelf { x -= 3 if x < - 2100 x = 0 ok } } } } # Start the Events Loop Screen Shot: 45.24. Using the Game Engine - Map 348
370.
Ring Documentation, Release1.2 45.25 Using the Game Engine - Map Events Load "gameengine.ring" # Give control to the game engine func main # Called by the Game Engine oGame = New Game # Create the Game Object { title = "My First Game" Map { blockwidth = 80 blockheight = 80 aMap = [ [0,0,0,0,0,0,0,0,0,1,0,0,0,3,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0], [0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0], [0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,2,0,0,0,1,0,0,0], [0,0,0,0,0,0,0,0,0,1,0,0,0,2,0,0,0,3,0,0,0,1,0,0,0,1,0,0,0], [0,0,0,0,0,0,0,0,0,3,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,3,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0] ] aImages = ["images/fbwall.png", "images/fbwallup.png", "images/fbwalldown.png"] state = func oGame,oSelf { oSelf { x -= 3 if x < - 2100 x = 0 ok } } mouse = func ogame,oself,nType,aMouseList { if nType = GE_MOUSE_UP oSelf { mX = aMouseList[GE_MOUSE_X] mY = aMouseList[GE_MOUSE_Y] nValue = GetValue(mX,mY) nRow = GetRow(mX,mY) nCol = GetCol(mX,mY) Switch nValue On 1 aMap[nRow][nCol] = 0 On 2 aMap[nRow][nCol] = 0 On 3 aMap[nRow][nCol] = 0 On 0 aMap[nRow][nCol] = 1 Off } ok } } } # Start the Events Loop 45.25. Using the Game Engine - Map Events 349
371.
Ring Documentation, Release1.2 Screen Shot: 45.26 Using the Game Engine - Object and Drawing We can use the Object keyword (defined by the game engine) to create objects from the GameObject class. Example: Load "gameengine.ring" # Give control to the game engine func main # Called by the Game Engine oGame = New Game # Create the Game Object { title = "My First Game" Object { x = 0 y=300 width = 200 height=200 draw = func oGame,oSelf { oSelf { for t = 1 to 210 gl_draw_circle(x,y,t, gl_map_rgb(t*random(255), t*2,t*3),1) 45.26. Using the Game Engine - Object and Drawing 350
372.
Ring Documentation, Release1.2 next } } state = func oGame,oSelf { oSelf { if x <= 800 x+= 3 else x=0 ok } } keypress = func oGame,oSelf,nKey { oSelf { Switch nKey on KEY_LEFT x -= 10 on KEY_RIGHT x += 10 on KEY_UP y -= 10 on KEY_DOWN y += 10 off } } } } # Start the Events Loop Screen Shot: 45.26. Using the Game Engine - Object and Drawing 351
373.
Ring Documentation, Release1.2 Example: Load "gameengine.ring" # Give control to the game engine func main # Called by the Game Engine oGame = New Game # Create the Game Object { title = "My First Game" Object { x = 400 y=300 width = 200 height=200 draw = func oGame,oSelf { oSelf { for t = 1 to 210 gl_draw_rectangle(x+t,y+t, x+t*2,y+t*2, gl_map_rgb(t*random(255), t*2,t*3),1) gl_draw_rectangle(x+t*2,y+t*2, x-t*2,y-t*2, gl_map_rgb(t*random(255), t*2,t*3),1) next } } 45.26. Using the Game Engine - Object and Drawing 352
374.
Ring Documentation, Release1.2 keypress = func oGame,oSelf,nKey { oSelf { Switch nKey on KEY_LEFT x -= 10 on KEY_RIGHT x += 10 on KEY_UP y -= 10 on KEY_DOWN y += 10 off } } } } # Start the Events Loop Screen Shot: 45.27 Stars Fighter Game The Stars Fighter source code 45.27. Stars Fighter Game 353
375.
Ring Documentation, Release1.2 # The Ring Standard Library # Game Engine for 2D Games # 2016, Mahmoud Fayed <msfclipper@yahoo.com> oGameState = NULL load "gameengine.ring" func main oGame = New Game while true oGameState = new GameState oGame { title = "Stars Fighter!" sprite { file = "images/menu1.jpg" x = 0 y=0 width=800 height = 600 scaled = true animate = false keypress = func ogame,oself,nKey { if nkey = key_esc or nKey = GE_AC_BACK ogame.shutdown() but nKey = key_space oGameState.startplay=true ogame.shutdown=true ok } mouse = func ogame,oself,nType,aMouseList { if nType = GE_MOUSE_UP oGameState.startplay=true ogame.shutdown=true ok } } text { animate = false size = 35 file = "fonts/pirulen.ttf" text = "Stars Fighter" x = 10 y=50 } text { animate = false size = 25 file = "fonts/pirulen.ttf" text = "Version 1.0" x = 80 y=100 } text { animate = false size = 16 file = "fonts/pirulen.ttf" text = "(C) 2016, Mahmoud Fayed" x = 45 y=140 } 45.27. Stars Fighter Game 354
376.
Ring Documentation, Release1.2 text { animate = false size = 25 file = "fonts/pirulen.ttf" text = "Press Space to start" x = 190 y=470 } text { animate = false size = 20 file = "fonts/pirulen.ttf" text = "Press Esc to Exit" x = 260 y=510 } Sound { file = "sound/music1.wav" } } if oGameState.startplay oGame.refresh() playstart(oGame) oGame.refresh() ok end func playstart oGame oSound = New Sound { file = "sound/music2.wav" } while true play(oGame) if ogame.shutdown = true and oGameState.value = 0 exit ok ogame.refresh() end oSound.Delete() func play oGame oGame { FPS = 60 FixedFPS = 120 title = "Stars Fighter!" sprite { file = "images/stars.jpg" x = 0 y = 0 point = -370 direction = ge_direction_dec type = ge_type_background 45.27. Stars Fighter Game 355
377.
Ring Documentation, Release1.2 state = func ogame,oself { oself { if x < -350 direction = ge_direction_inc point = 370 but x = 0 and direction = ge_direction_inc direction = ge_direction_dec point = -370 ok } } } sprite { file = "images/player.png" transparent = true type = ge_type_player x = 400 y =400 width=100 height=100 animate=false move=true Scaled=true mouse = func ogame,oself,nType,aMouseList { if not ( aMouseList[GE_MOUSE_X] >= oSelf.x and aMouseList[GE_MOUSE_X] <= oSelf.x+oSelf.width and aMouseList[GE_MOUSE_Y] >= oself.y and aMouseList[GE_MOUSE_Y] <= oSelf.y+oSelf.height ) if nType = GE_MOUSE_DOWN if aMouseList[1] < oSelf.X # left oSelf.X -= 100 else oSelf.X += 100 ok if aMouseList[2] < oSelf.Y # up oSelf.Y -= 100 else oSelf.Y += 100 ok ok else if nType = GE_MOUSE_UP cFunc = oself.keypress call cFunc(oGame,oSelf,Key_Space) ok ok } keypress = func oGame,oself,nkey { if nkey = key_space ogame { sprite { type = ge_type_fire file = "images/rocket.png" transparent = true x = oself.x + 30 y = oself.y - 30 width = 30 height = 30 point = -30 45.27. Stars Fighter Game 356
378.
Ring Documentation, Release1.2 nstep = 20 direction = ge_direction_decvertical state = func oGame,oSelf { for x in oGame.aObjects if x.type = ge_type_enemy if oself.x >= x.x and oself.y >= x.y and oself.x <= x.x + x.width and oself.y <= x.y + x.height showfire(oGame,x.x+40,x.y+40) ogame.remove(x.nindex) oGameState.score+=10 oGameState.enemies-- checkwin(oGame) exit ok ok next } } } but nkey = key_esc or nKey = GE_AC_BACK ogame.shutdown() ok } state = func oGame,oSelf { oself { if x < 0 x = 0 ok if y < 0 y = 0 ok if x > ogame.screen_w-width x= ogame.screen_w - width ok if y > ogame.screen_h-height y=ogame.screen_h-height ok } } } for g = 1 to oGameState.enemies sprite { type = ge_type_enemy file = "images/enemy.png" transparent = true x = g*random(50) y =g width=100 height=100 animate=true Scaled=true direction = ge_direction_random state = func oGame,oSelf { oself { if x < 0 x = 0 ok if y < 0 y = 0 ok if x > ogame.screen_w-width x= ogame.screen_w - width ok if y > ogame.screen_h-height y=ogame.screen_h-height ok } if random(100) = 1 ogame { sprite { type = ge_type_fire file = "images/rocket2.png" transparent = true x = oself.x + 30 y = oself.y + oself.height+ 30 width = 30 height = 30 45.27. Stars Fighter Game 357
379.
Ring Documentation, Release1.2 point = ogame.screen_h+30 nstep = 10 direction = ge_direction_incvertical state = func oGame,oSelf { x = oGame.aObjects[oGameState.playerindex] if oself.x >= x.x and oself.y >= x.y and oself.x <= x.x + x.width and oself.y <= x.y + x.height if oGameState.value > 0 oGameState.value-=10 ok ogame.remove(oself.nindex) checkgameover(oGame) ok } } } ok } } next text { size = 30 file = "fonts/pirulen.ttf" text = "Destroy All Enemies!" nstep = 3 color = GE_COLOR_GREEN x = 100 y=50 direction = ge_direction_incvertical point = 500 } text { animate = false point = 400 size = 30 file = "fonts/pirulen.ttf" text = "Score : " + oGameState.score x = 500 y=10 state = func oGame,oSelf { oSelf { text = "Score : " + oGameState.score } } } text { animate = false point = 400 size = 30 file = "fonts/pirulen.ttf" text = "Energy : " + oGameState.value x = 500 y=50 state = func oGame,oSelf { oSelf { text = "Energy : " + oGameState.value } } } text { animate = false point = 400 size = 30 file = "fonts/pirulen.ttf" text = "Level : " + oGameState.level x = 500 y=90 } } 45.27. Stars Fighter Game 358
380.
Ring Documentation, Release1.2 func checkwin ogame if oGameState.gameresult return ok if oGameState.enemies = 0 oGameState.gameresult = true oGame { if oGameState.level < 30 text { point = 400 size = 30 file = "fonts/pirulen.ttf" text = "Level Completed!" nStep = 3 x = 500 y=10 state = func ogame,oself { if oself.y >= 400 ogame.shutdown = true oGameState.level++ oGameState.enemies = oGameState.level oGameState.gameresult = false ok } } else text { point = 400 size = 30 nStep = 3 file = "fonts/pirulen.ttf" text = "You Win !!!" x = 500 y=10 state = func ogame,oself { if oself.y >= 400 ogame.shutdown = true oGameState.value = 0 ok } } ok } ok func checkgameover ogame if oGameState.gameresult return ok if oGameState.value <= 0 oGameState.gameresult = true oGame { text { point = 400 size = 30 nStep = 3 file = "fonts/pirulen.ttf" text = "Game Over !!!" x = 500 y=10 state = func ogame,oself { if oself.y >= 400 ogame.shutdown = true ok 45.27. Stars Fighter Game 359
381.
Ring Documentation, Release1.2 } } } showfire(oGame,oGame.aObjects[oGameState.PlayerIndex].x+40, oGame.aObjects[oGameState.PlayerIndex].y+40) oGame.aObjects[oGameState.PlayerIndex].enabled = false oGame.remove(oGameState.PlayerIndex) ok func showfire oGame,nX,nY oGame { animate { file = "images/fire.png" x = nX y = nY framewidth = 40 height = 42 nStep = 3 transparent = true state = func oGame,oSelf { oSelf { nStep-- if nStep = 0 nStep = 3 if frame < 13 frame++ else frame=1 oGame.remove(oself.nIndex) ok ok } } } } class gamestate score = 0 level = 1 enemies = 1 value = 100 playerindex = 2 gameresult = false startplay=false Screen Shot: 45.27. Stars Fighter Game 360
382.
Ring Documentation, Release1.2 45.28 Flappy Bird 3000 Game The Flappy Bird 3000 Game source code # The Ring Standard Library # Game Engine for 2D Games # 2016, Mahmoud Fayed <msfclipper@yahoo.com> oGameState = NULL Load "gameengine.ring" func main oGame = New Game while true oGameState = New GameState oGame { 45.28. Flappy Bird 3000 Game 361
383.
Ring Documentation, Release1.2 title = "Flappy Bird 3000" sprite { file = "images/fbback.png" x = 0 y=0 width=800 height = 600 scaled = true animate = false keypress = func ogame,oself,nKey { if nkey = key_esc or nKey = GE_AC_BACK ogame.shutdown() but nKey = key_space oGameState.startplay=true ogame.shutdown=true ok } mouse = func ogame,oself,nType,aMouseList { if nType = GE_MOUSE_UP cFunc = oself.keypress call cFunc(oGame,oSelf,Key_Space) ok } } text { animate = false size = 35 file = "fonts/pirulen.ttf" text = "Flappy Bird 3000" x = 150 y=50 } text { animate = false size = 25 file = "fonts/pirulen.ttf" text = "Version 1.0" x = 280 y=100 } text { animate = false size = 16 file = "fonts/pirulen.ttf" text = "(C) 2016, Mahmoud Fayed" x = 245 y=140 } text { animate = false size = 25 file = "fonts/pirulen.ttf" text = "To Win Get Score = 3000" x = 150 y=270 } text { animate = false size = 25 file = "fonts/pirulen.ttf" text = "Press Space to start" x = 190 y=470 } text { 45.28. Flappy Bird 3000 Game 362
384.
Ring Documentation, Release1.2 animate = false size = 20 file = "fonts/pirulen.ttf" text = "Press Esc to Exit" x = 260 y=510 } animate { file = "images/fbbird.png" x = 200 y = 200 framewidth = 20 scaled = true height = 50 width = 50 nStep = 3 transparent = true animate = true direction = ge_direction_random state = func oGame,oSelf { oSelf { nStep-- if nStep = 0 nStep = 3 if frame < 3 frame++ else frame=1 ok ok if x <= 0 x=0 ok if y <= 0 y=0 ok if x >= 750 x= 750 ok if y > 550 y=550 ok } } } Sound { file = "sound/music2.wav" } } if oGameState.startplay oGame.refresh() playstart(oGame) oGame.refresh() ok end func playstart oGame oGame { FPS = 60 FixedFPS = 120 Title = "Flappy Bird 3000" Sprite { 45.28. Flappy Bird 3000 Game 363
385.
Ring Documentation, Release1.2 file = "images/fbback.png" x = 0 y=0 width=800 height = 600 scaled = true animate = false keypress = func ogame,oself,nKey { if nkey = key_esc or nKey = GE_AC_BACK ogame.shutdown() ok } } Map { blockwidth = 80 blockheight = 80 aMap = [ [0,0,0,0,0,0,0,0,0,1,0,0,0,3,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0], [0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0], [0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,2,0,0,0,1,0,0,0], [0,0,0,0,0,0,0,0,0,1,0,0,0,2,0,0,0,3,0,0,0,1,0,0,0,1,0,0,0], [0,0,0,0,0,0,0,0,0,3,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,3,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0] ] newmap(aMap) aImages = ["images/fbwall.png","images/fbwallup.png", "images/fbwalldown.png"] state = func oGame,oSelf { if oGameState.gameresult = false px = oGame.aObjects[3].x py = oGame.aObjects[3].y oSelf { x -= 3 if x < - 2100 x = 0 newmap(aMap) ok nCol = getcol(px,0) if nCol=11 or nCol=15 or nCol=19 or nCol=23 or nCol=27 if nCol != oGameState.lastcol oGameState.lastcol = nCol oGameState.Score += 100 oGame { Sound { once = true file = "sound/sfx_point.wav" } } checkwin(oGame) ok ok } if oSelf.getvalue(px+40,py) != 0 or oSelf.getvalue(px+40,py+40) != 0 or oSelf.getvalue(px,py) != 0 or oSelf.getvalue(px,py+40) != 0 oGameState.gameresult = true oGame { text { point = 550 size = 30 nStep = 3 45.28. Flappy Bird 3000 Game 364
386.
Ring Documentation, Release1.2 file = "fonts/pirulen.ttf" text = "Game Over !!!" x = 500 y=10 state = func ogame,oself { if oself.y >= 550 ogame.shutdown = true ok if oself.y = 90 ogame { Sound { once = true file = "sound/sfx_die.wav" } } ok } } Sound { once = true file = "sound/sfx_hit.wav" } } ok ok } } animate { file = "images/fbbird.png" x = 10 y = 10 framewidth = 20 scaled = true height = 50 width = 50 nStep = 3 transparent = true state = func oGame,oSelf { oSelf { nStep-- if nStep = 0 nStep = 3 if frame < 3 frame++ else frame=1 ok ok } if not oGameState.playerwin oGameState.down -- if oGameState.down = 0 oGameState.down = 3 oself { y += 25 if y > 550 y=550 ok } 45.28. Flappy Bird 3000 Game 365
387.
Ring Documentation, Release1.2 ok ok } keypress = func ogame,oself,nKey { if oGameState.gameresult = false oself { if nkey = key_space y -= 55 oGameState.down = 60 if y<=0 y=0 ok ok } ok } mouse = func ogame,oself,nType,aMouseList { if nType = GE_MOUSE_UP cFunc = oself.keypress call cFunc(oGame,oSelf,Key_Space) ok } } text { animate = false point = 400 size = 30 file = "fonts/pirulen.ttf" text = "Score : " + oGameState.score x = 500 y=10 state = func oGame,oSelf { oSelf { text = "Score : " + oGameState.score } } } } func newmap aMap aV = [ [1,1,3,0,0,2,1,1], [1,3,0,0,0,2,1,1], [1,1,1,3,0,2,1,1], [1,1,1,3,0,0,0,0], [0,0,0,0,2,1,1,1], [0,0,2,1,1,1,1,1], [0,0,0,2,1,1,1,1], [1,1,1,3,0,2,1,1], [1,1,1,1,1,3,0,0], [3,0,0,2,1,1,1,1], [3,0,0,2,3,0,0,2] ] for x = 10 to 24 step 4 aVar = aV[ (random(10)+1) ] for y = 1 to 8 aMap[y][x] = aVar[y] next next 45.28. Flappy Bird 3000 Game 366
388.
Ring Documentation, Release1.2 func checkwin ogame if oGameState.score = 3000 oGameState.gameresult = true oGameState.playerwin = true oGame { text { point = 400 size = 30 nStep = 3 file = "fonts/pirulen.ttf" text = "You Win !!!" x = 500 y=10 state = func ogame,oself { if oself.y >= 400 ogame.shutdown = true oGameState.value = 0 ok } } } ok Class GameState down = 3 gameresult = false Score = 0 startplay=false lastcol = 0 playerwin = false Screen Shot: 45.28. Flappy Bird 3000 Game 367
389.
Ring Documentation, Release1.2 45.29 Super Man 2016 Game The Super Man 2016 Game source code # The Ring Standard Library # Game Engine for 2D Games # 2016, Mahmoud Fayed <msfclipper@yahoo.com> oGameState = NULL Load "gameengine.ring" func main oGame = New Game while true oGameState = new GameState oGame { title = "Super Man 2016" 45.29. Super Man 2016 Game 368
390.
Ring Documentation, Release1.2 sprite { file = "images/superman.jpg" x = 0 y=0 width=800 height = 600 scaled = true animate = false keypress = func ogame,oself,nKey { if nkey = key_esc or nKey = GE_AC_BACK ogame.shutdown() but nKey = key_space oGameState.startplay=true ogame.shutdown=true ok } mouse = func ogame,oself,nType,aMouseList { if nType = GE_MOUSE_UP oGameState.startplay=true ogame.shutdown=true ok } state = func ogame,oself { oself { if x > -500 x-=1 y-=1 width +=1 height +=4 ok } } } text { animate = false size = 35 file = "fonts/pirulen.ttf" text = "Super Man 2016" x = 20 y=30 } text { animate = false size = 25 file = "fonts/pirulen.ttf" text = "Version 1.0" x = 20 y=80 } text { animate = false size = 16 file = "fonts/pirulen.ttf" text = "(C) 2016, Mahmoud Fayed" x = 20 y=120 } text { animate = false size = 25 file = "fonts/pirulen.ttf" text = "Press Space to start" x = 190 y=470 } 45.29. Super Man 2016 Game 369
391.
Ring Documentation, Release1.2 text { animate = false size = 20 file = "fonts/pirulen.ttf" text = "Press Esc to Exit" x = 260 y=510 } animate { file = "images/superman.png" x = 200 y = 200 framewidth = 68 scaled = true height = 86 width = 60 nStep = 10 transparent = true animate = true direction = ge_direction_random state = func oGame,oSelf { oSelf { nStep-- if nStep = 0 nStep = 10 if frame < 1 frame++ else frame=1 ok ok if x <= 0 x=0 ok if y <= 0 y=0 ok if x >= 750 x= 750 ok if y > 550 y=550 ok } } } Sound { file = "sound/music2.wav" } } if oGameState.startplay oGame.refresh() playstart(oGame) oGame.refresh() ok end func playstart oGame oGame { FPS = 60 FixedFPS = 15 Title = "Super Man 2016" 45.29. Super Man 2016 Game 370
392.
Ring Documentation, Release1.2 Sprite { file = "images/supermancity.jpg" x = 0 y=0 width=800 height = 600 scaled = true animate = false } Map { blockwidth = 80 blockheight = 80 aMap = [ [0,0,0,4,4,4,0,0,0,1,0,0,0,1,4,4,0,1,0,0,0,0,4,4,0,1,4, 4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,1,0,0,0,1,0,0,0,1,0,3,3,3,5,3,3,3,3,0], [0,0,4,0,4,0,4,0,0,1,0,0,0,3,4,4,4,1,0,0,0,0,4,4,0,1,4, 4,4,0,0,4,4,4,4,4,4,4,4,4,4,4,4,1,4,1,0,0,0,1,0,0,0,1,0,4,4,4,4,4,4,4,4,0], [0,0,0,4,4,4,0,0,0,1,0,0,0,4,4,4,4,1,0,0,0,0,0,0,0,3,4, 4,4,0,0,4,0,0,0,0,0,0,4,2,0,0,4,1,4,1,4,2,4,1,0,2,0,1,0,4,4,4,4,4,4,4,4,0], [0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, 0,0,0,0,4,4,4,4,4,4,4,4,1,0,0,4,1,4,1,4,1,4,1,0,1,0,1,0,2,2,2,2,2,2,2,2,0], [0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, 0,0,0,0,2,0,0,0,0,0,2,0,3,0,0,0,1,4,1,4,1,4,1,0,1,0,1,0,1,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,1,0,0,0,2,0,0,0,1,0,0,0,2,0,0,0,0,0, 0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,4,3,4,1,4,3,0,1,0,3,0,1,0,0,0,0,0,0,0,0], [0,0,2,0,0,2,0,0,2,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0, 0,0,0,0,1,0,0,0,0,0,3,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0], [0,0,1,0,0,1,0,0,1,3,0,0,0,1,0,0,0,3,0,0,0,1,0,0,0,0,0, 0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0] ] aImages = ["images/smwall.png","images/smwallup.png", "images/smwalldown.png","images/smstar.png", "images/smkey.png","images/smstar2.png"] } sprite { type = ge_type_enemy animate = false file = "images/smhome.png" x = 5000 y = 400 width = 290 height = 200 transparent = true state = func oGame,oSelf { oself { x = 5000 + oGame.aObjects[2].x if x < 0 or x > SCREEN_W return ok } if oGameState.gameresult or oGameState.DoorKey = false return ok if oGame.aObjects[oGameState.playerindex].x > oself.x + 100 and oGame.aObjects[oGameState.playerindex].y > oself.y + 50 oGameState.gameresult = true oGame { sprite { file = "images/smwin.jpg" x=0 y=0 width=800 height=600 scaled = true animate=false state = func ogame,oself { oself { x-=5 y-=5 45.29. Super Man 2016 Game 371
393.
Ring Documentation, Release1.2 width +=10 height +=10 if x = -300 ogame.shutdown = true ok } } } } ok } } animate { file = "images/superman.png" x = 0 y = 0 framewidth = 60 scaled = true height = 86 width = 60 nStep = 3 transparent = true state = func oGame,oSelf { checkstarskeycol(oGame,oSelf) if not oGameState.playerwin oself { file = "images/superman.png" height = 86 width = 60 for t=1 to 8 if checkwall2(oGame,oSelf,0,5,[2,1]) y += 5 else exit ok next if y > 500 y=500 ok } ok } keypress = func ogame,oself,nKey { if oGameState.gameresult = false oself { if nkey = key_up and checkwall(oGame,oSelf,0,-40) oGameState.value -= 1 checkgameover(oGame) file = "images/supermanup.png" height = 123 dotransparent() y -= 40 oGameState.down = 10 if y<=0 y=0 ok 45.29. Super Man 2016 Game 372
394.
Ring Documentation, Release1.2 but nkey = key_down and checkwall(oGame,oSelf,0,40) file = "images/supermandown.png" dotransparent() y += 40 if y>=500 y=500 ok but nKey = key_right and checkwall(oGame,oSelf,10,0) file = "images/supermanright.png" dotransparent() x += 10 if x >= 440 if oGame.aObjects[2].x > -4500 oGame.aObjects[2].x -= 50 callenemystate(oGame) else if x <= 750 if checkwall(oGame,oSelf,10,0) x += 10 ok else if checkwall(oGame,oSelf,-10,0) x -= 10 ok ok return ok x=400 ok but nKey = key_left and checkwall(oGame,oSelf,-10,0) file = "images/supermanleft.png" dotransparent() x -= 10 if x <= 0 x += 10 if oGame.aObjects[2].x != 0 oGame.aObjects[2].x += 50 callenemystate(oGame) x += 50 ok ok but nkey = key_esc or nKey = GE_AC_BACK ogame.shutdown() ok } ok } mouse = func ogame,oself,nType,aMouseList { if nType = GE_MOUSE_DOWN oGameState.moveplayer = TRUE But nType = GE_MOUSE_UP oGameState.moveplayer = FALSE ok if oGameState.moveplayer = TRUE if aMouseList[GE_MOUSE_X] < oSelf.X # left cFunc = oself.keypress call cFunc(oGame,oSelf,Key_left) else cFunc = oself.keypress call cFunc(oGame,oSelf,Key_right) 45.29. Super Man 2016 Game 373
395.
Ring Documentation, Release1.2 ok if aMouseList[GE_MOUSE_Y] < oSelf.Y # up cFunc = oself.keypress call cFunc(oGame,oSelf,Key_up) else cFunc = oself.keypress call cFunc(oGame,oSelf,Key_down) ok ok } } addenemy(oGame,600) addenemy(oGame,900) addenemy(oGame,1550) addenemy(oGame,2350) addenemy(oGame,3350) addenemy(oGame,3500) addenemy(oGame,3670) addenemy(oGame,3840) text { animate = false point = 400 size = 30 file = "fonts/pirulen.ttf" text = "Score : " + oGameState.score x = 500 y=0 state = func oGame,oSelf { oSelf { text = "Score : " + oGameState.score } } } text { animate = false point = 400 size = 30 file = "fonts/pirulen.ttf" text = "Energy : " + oGameState.value x = 10 y=0 state = func oGame,oSelf { oSelf { text = "Energy : " + oGameState.value } } } } func inlist nValue,aList for x in aList if x = nValue return true ok next return false func checkwall oGame,oself,diffx,diffy alist = [1,2,3] return checkwall2(oGame,oself,diffx,diffy,aList) func checkwall2 oGame,oself,diffx,diffy,aList 45.29. Super Man 2016 Game 374
396.
Ring Documentation, Release1.2 xPos = oSelf.x + diffx yPos = oSelf.y + diffy nValue = oGame.aObjects[2].getvalue(xPos,yPos) nValue = inlist(nValue,aList) nValue = not nValue if nValue = 0 return nValue ok xPos = oSelf.x + diffx yPos = oSelf.y + diffy + oSelf.height nValue = oGame.aObjects[2].getvalue(xPos,yPos) nValue = inlist(nValue,aList) nValue = not nValue if nValue = 0 return nValue ok xPos = oSelf.x + diffx + oSelf.width yPos = oSelf.y + diffy nValue = oGame.aObjects[2].getvalue(xPos,yPos) nValue = inlist(nValue,aList) nValue = not nValue if nValue = 0 return nValue ok xPos = oSelf.x + diffx + oSelf.width yPos = oSelf.y + diffy + oSelf.height nValue = oGame.aObjects[2].getvalue(xPos,yPos) nValue = inlist(nValue,aList) nValue = not nValue if nValue = 0 return nValue ok return nValue func checkopenwall oGame if oGameState.score = 900 oGame.aObjects[2].aMap[3][10] = 3 oGame.aObjects[2].aMap[4][10] = 0 oGame.aObjects[2].aMap[5][10] = 0 oGame.aObjects[2].aMap[6][10] = 0 oGame.aObjects[2].aMap[7][10] = 0 oGame.aObjects[2].aMap[8][10] = 0 but oGameState.score = 1800 oGame.aObjects[2].aMap[3][18] = 3 oGame.aObjects[2].aMap[4][18] = 0 oGame.aObjects[2].aMap[5][18] = 0 oGame.aObjects[2].aMap[6][18] = 0 oGame.aObjects[2].aMap[7][18] = 0 oGame.aObjects[2].aMap[8][18] = 0 but oGameState.score = 5500 oGame.aObjects[2].aMap[1][44] = 0 oGame.aObjects[2].aMap[2][44] = 0 oGame.aObjects[2].aMap[3][44] = 2 ok func checkgameover ogame if oGameState.gameresult return ok if oGameState.value <= 0 oGameState.value = 0 oGameState.gameresult = true oGame { 45.29. Super Man 2016 Game 375
397.
Ring Documentation, Release1.2 text { point = 400 size = 30 nStep = 9 file = "fonts/pirulen.ttf" text = "Game Over !!!" x = 500 y=10 state = func ogame,oself { if oself.y >= 400 ogame.shutdown = true ok } } } showfire(oGame,oGame.aObjects[oGameState.PlayerIndex].x+40, oGame.aObjects[oGameState.PlayerIndex].y+40) oGame.aObjects[oGameState.PlayerIndex].enabled = false oGame.remove(oGameState.PlayerIndex) ok func showfire oGame,nX,nY oGame { animate { file = "images/fire.png" x = nX y = nY framewidth = 40 height = 42 nStep = 3 transparent = true state = func oGame,oSelf { oSelf { nStep-- if nStep = 0 nStep = 3 if frame < 13 frame++ else frame=1 oGame.remove(oself.nIndex) ok ok } } } } func addenemy oGame,xPos oGame { lbraceend = false sprite { type = ge_type_enemy file = "images/smenemy.png" transparent = true x = xPos y =10 width=100 height=100 animate=true Scaled=true direction = GE_DIRECTION_NOMOVE 45.29. Super Man 2016 Game 376
398.
Ring Documentation, Release1.2 temp = xPos state = func oGame,oSelf { oself { x = oSelf.temp + oGame.aObjects[2].x if y < 0 y = 0 ok if y > 100 y=100 ok if x > SCREEN_W or x < 0 return ok } if random(10) = 1 if oGameState.gameresult return ok ogame { sprite { type = ge_type_fire file = "images/smrocket.png" scaled = true transparent = true x = oself.x + 30 y = oself.y + oself.height+ 30 width = 30 height = 30 point = ogame.screen_h+30 nstep = 30 direction = ge_direction_incvertical xvalue = oGame.aObjects[2].x temp = oself.x + 30 - xvalue state = func oGame,oSelf { oself { x = oSelf.temp + oGame.aObjects[2].x } x = oGame.aObjects[oGameState.playerindex] if oself.x >= x.x and oself.y >= x.y and oself.x <= x.x + x.width and oself.y <= x.y + x.height if oGameState.value > 0 oGameState.value-=1000 ok ogame.remove(oself.nindex) checkgameover(oGame) ok } } } ok } } } ogame.lbraceend = true func checkstarskey oGame,oSelf,nValue,nRow,nCol switch nValue on 4 oGame.aObjects[2].aMap[nRow][nCol] = 6 oGameState.Score += 100 checkopenwall(oGame) oGame { Sound { once = true file = "sound/sfx_point.wav" } } 45.29. Super Man 2016 Game 377
399.
Ring Documentation, Release1.2 on 5 oGame.aObjects[2].aMap[nRow][nCol] = 0 oGameState.DoorKey = true oGameState.Score += 500 checkopenwall(oGame) oGame { Sound { once = true file = "sound/sfx_point.wav" } } off func checkstarskeycol oGame,oSelf nValue = oGame.aObjects[2].getvalue(oSelf.x,oSelf.y) nRow = oGame.aObjects[2].getrow(oSelf.x,oSelf.y) nCol = oGame.aObjects[2].getcol(oSelf.x,oSelf.y) checkstarskey(oGame,oSelf,nValue,nRow,nCol) nValue = oGame.aObjects[2].getvalue(oSelf.x+oSelf.width,oSelf.y+oSelf.height) nRow = oGame.aObjects[2].getrow(oSelf.x+oSelf.width,oSelf.y+oSelf.height) nCol = oGame.aObjects[2].getcol(oSelf.x+oSelf.width,oSelf.y+oSelf.height) checkstarskey(oGame,oSelf,nValue,nRow,nCol) nValue = oGame.aObjects[2].getvalue(oSelf.x+oSelf.width,oSelf.y) nRow = oGame.aObjects[2].getrow(oSelf.x+oSelf.width,oSelf.y) nCol = oGame.aObjects[2].getcol(oSelf.x+oSelf.width,oSelf.y) checkstarskey(oGame,oSelf,nValue,nRow,nCol) nValue = oGame.aObjects[2].getvalue(oSelf.x,oSelf.y+oSelf.height) nRow = oGame.aObjects[2].getrow(oSelf.x,oSelf.y+oSelf.height) nCol = oGame.aObjects[2].getcol(oSelf.x,oSelf.y+oSelf.height) checkstarskey(oGame,oSelf,nValue,nRow,nCol) func callenemystate oGame for t in oGame.aObjects t { if type = GE_TYPE_ENEMY call state(oGame,t) ok } next Class GameState down = 3 gameresult = false Score = 0 startplay=false lastcol = 0 playerwin = false DoorKey = false playerindex = 4 value = 1000 moveplayer = false Screen Shot: 45.29. Super Man 2016 Game 378
CHAPTER FORTYSIX BUILDING GAMES FORANDROID In this chapter we will learn about Building RingLibSDL Games for Mobile. So we can create packages (*.apk) for the applications that are developed using Ring Game Engine for 2D Games. 46.1 Download Requirements and Update the Android SDK • The Android SDK Tools https://developer.android.com/studio/index.html • The Android NDK https://developer.android.com/ndk/index.html • Apache Ant v1.8 or later http://ant.apache.org/bindownload.cgi • Java SE Development Kit (JDK) v6 or later http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260.html • Update the Android SDK to get the API and tools packages required for development 46.2 Project Folder Open the project folder : ring/android/ringlibsdl/project 380
402.
Ring Documentation, Release1.2 You can add the source code (*.ring) and Images/Sound Files to the assets folder. You will find the Flappy Bird 3000 Game ready for building. The execution starts from the start.ring file load "game2.ring" 46.3 Building the project Move to the ring/android/ringlibsdl/project folder We can build using the next command (We need to do this for one time only). ndk-build Then we can create the package (*.apk) using the next command. 46.3. Building the project 381
CHAPTER FORTYSEVEN DESKTOP AND MOBILEDEVELOPMENT USING RINGQT In this chapter we will learn how to use the Qt framework classes in our Ring applications to create Desktop and Mobile Applications. 47.1 The First GUI Application In this example we will create an application to ask the user about his/her name. When the user type the name in the textbox then click on “Say Hello” button, the textbox value will be updated by adding “Hello ” to the name. Load "guilib.ring" MyApp = New qApp { win1 = new qWidget() { setwindowtitle("Hello World") setGeometry(100,100,370,250) label1 = new qLabel(win1) { settext("What is your name ?") setGeometry(10,20,350,30) setalignment(Qt_AlignHCenter) } btn1 = new qpushbutton(win1) { setGeometry(10,200,100,30) settext("Say Hello") setclickevent("pHello()") } btn1 = new qpushbutton(win1) { setGeometry(150,200,100,30) settext("Close") setclickevent("pClose()") } lineedit1 = new qlineedit(win1) { setGeometry(10,100,350,30) } show() } 383
405.
Ring Documentation, Release1.2 exec() } Func pHello lineedit1.settext( "Hello " + lineedit1.text()) Func pClose MyApp.quit() Program Output: At first we type the name in the textbox Then we click on the say hello button 47.1. The First GUI Application 384
406.
Ring Documentation, Release1.2 47.2 Using Layout The next example is just an upgrade to the previous application to use the vertical layout. Load "guilib.ring" MyApp = New qApp { win1 = new qWidget() { setwindowtitle("Hello World") setGeometry(100,100,400,130) label1 = new qLabel(win1) { settext("What is your name ?") setGeometry(10,20,350,30) setalignment(Qt_AlignHCenter) } btn1 = new qpushbutton(win1) { setGeometry(10,200,100,30) settext("Say Hello") setclickevent("pHello()") } btn2 = new qpushbutton(win1) { setGeometry(150,200,100,30) settext("Close") setclickevent("pClose()") } lineedit1 = new qlineedit(win1) { setGeometry(10,100,350,30) } layout1 = new qVBoxLayout() { addwidget(label1) addwidget(lineedit1) addwidget(btn1) addwidget(btn2) } win1.setlayout(layout1) show() } exec() } Func pHello lineedit1.settext( "Hello " + lineedit1.text()) Func pClose MyApp.quit() The application during the runtime! 47.2. Using Layout 385
407.
Ring Documentation, Release1.2 47.3 Using the QTextEdit Class In this example we will use the QTextEdit Class Load "guilib.ring" New qApp { win1 = new qWidget() { setwindowtitle("QTextEdit Class") setGeometry(100,100,500,500) new qtextedit(win1) { setGeometry(10,10,480,480) } show() } exec() } During the runtime we can paste rich text in the qtextedit widget 47.3. Using the QTextEdit Class 386
408.
Ring Documentation, Release1.2 47.4 Using the QListWidget Class In this example we will use the QListWidget Class Load "guilib.ring" New qApp { win1 = new qWidget() { setGeometry(100,100,400,400) list1 = new qlistwidget(win1) { setGeometry(150,100,200,200) alist = ["one","two","three","four","five"] for x in alist additem(x) next setcurrentrow(3,2) win1.setwindowtitle("Items Count : " + count() ) } 47.4. Using the QListWidget Class 387
409.
Ring Documentation, Release1.2 btn1 = new qpushbutton(win1) { setGeometry(10,200,100,30) settext("selected item") setclickevent("pWork()") } btn2 = new qpushbutton(win1) { setGeometry(10,240,100,30) settext("Delete item") setclickevent("pWork2()") } show() } exec() } func pWork btn1.settext(string(list1.currentrow())) func pWork2 list1 { takeitem(currentrow()) } The application during the runtime 47.4. Using the QListWidget Class 388
410.
Ring Documentation, Release1.2 Another Example: Load "guilib.ring" New qApp { win1 = new qWidget() { setGeometry(100,100,500,400) list1 = new qlistwidget(win1) { setGeometry(150,100,200,200) alist = ["one","two","three","four","five"] for x in alist additem(x) next setcurrentrow(3,2) win1.setwindowtitle("Items Count : " + count() ) } btn1 = new qpushbutton(win1) { setGeometry(10,200,100,30) settext("selected item") setclickevent("pWork()") } btn2 = new qpushbutton(win1) { setGeometry(10,240,100,30) settext("Delete item") setclickevent("pWork2()") } show() } exec() } func pWork nbrOfItems = list1.count() curItemNbr = list1.currentrow() curValue = list1.item(list1.currentrow()).text() win1.setwindowtitle( "After Select - NbrOfItems: " + nbrOfItems + " CurItemNbr: " + curItemNbr + " CurValue: " + curValue ) btn1.settext( string(list1.currentrow() ) + " --- " + list1.item(list1.currentrow()).text() ) func pWork2 list1 { takeitem(currentrow()) nbrOfItems = count() curItemNbr = currentrow() curValue = item(currentrow()).text() 47.4. Using the QListWidget Class 389
411.
Ring Documentation, Release1.2 win1.setwindowtitle("After Delete - NbrOfItems: " + nbrOfItems + " CurItemNbr: " + curItemNbr +" CurValue: " + curValue ) } 47.5 Using QTreeView and QFileSystemModel In this example we will learn how to use the QTreeView widget to represent the File System Load "guilib.ring" New qApp { win1 = New qWidget() { setwindowtitle("Using QTreeView and QFileSystemModel") setGeometry(100,100,500,400) New qtreeview(win1) { setGeometry(00,00,500,400) oDir = new QDir() ofile = new QFileSystemModel() ofile.setrootpath(oDir.currentpath()) setmodel(ofile) } show() } exec() } The application during the runtime 47.5. Using QTreeView and QFileSystemModel 390
412.
Ring Documentation, Release1.2 47.6 Using QTreeWidget and QTreeWidgetItem In this example we will learn about using the QTreeWidget and QTreeWidgetItem classes Load "guilib.ring" New qApp { win1 = new qWidget() { setwindowtitle("TreeWidget") setGeometry(100,100,400,400) layout1 = new qvboxlayout() tree1 = new qtreewidget(win1) { setGeometry(00,00,400,400) setcolumncount(1) myitem = new qtreewidgetitem() myitem.settext(0,"The First Step") addtoplevelitem(myitem) for x = 1 to 10 myitem2 = new qtreewidgetitem() myitem2.settext(0,"hello"+x) myitem.addchild(myitem2) 47.6. Using QTreeWidget and QTreeWidgetItem 391
413.
Ring Documentation, Release1.2 for y = 1 to 10 myitem3 = new qtreewidgetitem() myitem3.settext(0,"hello"+x) myitem2.addchild(myitem3) next next setheaderlabel("Steps Tree") } layout1.addwidget(tree1) setlayout(layout1) show() } exec() } The application during the runtime 47.7 Using QComboBox Class In this example we will learn about using the QComboBox class 47.7. Using QComboBox Class 392
414.
Ring Documentation, Release1.2 Load "guilib.ring" New qApp { win1 = new qWidget() { setwindowtitle("Using QComboBox") setGeometry(100,100,400,400) New QComboBox(win1) { setGeometry(150,100,200,30) alist = ["one","two","three","four","five"] for x in aList additem(x,0) next } show() } exec() } The application during the runtime 47.8 Creating Menubar In this example we will learn about using the QMenuBar class 47.8. Creating Menubar 393
415.
Ring Documentation, Release1.2 Load "guilib.ring" MyApp = New qApp { win1 = new qWidget() { setwindowtitle("Using QMenubar") setGeometry(100,100,400,400) menu1 = new qmenubar(win1) { sub1 = addmenu("File") sub2 = addmenu("Edit") sub3 = addmenu("Help") sub1 { oAction = new qAction(win1) { settext("New") } addaction(oAction) oAction = new qAction(win1) { settext("Open") } addaction(oAction) oAction = new qAction(win1) { settext("Save") } addaction(oAction) oAction = new qAction(win1) { settext("Save As") } addaction(oAction) addseparator() oAction = new qaction(win1) { settext("Exit") setclickevent("myapp.quit()") } addaction(oAction) } sub2 { oAction = new qAction(win1) { settext("Cut") } addaction(oAction) oAction = new qAction(win1) { settext("Copy") } addaction(oAction) oAction = new qAction(win1) { settext("Paste") } addaction(oAction) addseparator() oAction = new qAction(win1) { settext("Select All") } addaction(oAction) } sub3 { oAction = new qAction(win1) { 47.8. Creating Menubar 394
416.
Ring Documentation, Release1.2 settext("Reference") } addaction(oAction) sub4 = addmenu("Sub Menu") sub4 { oAction = new qAction(win1) { settext("Website") } addaction(oAction) oAction = new qAction(win1) { settext("Forum") } addaction(oAction) oAction = new qAction(win1) { settext("Blog") } addaction(oAction) } addseparator() oAction = new qAction(win1) { settext("About") } addaction(oAction) } } show() } exec() } The application during the runtime 47.8. Creating Menubar 395
417.
Ring Documentation, Release1.2 47.9 Creating Toolbar In this example we will learn about using the QToolBar class Load "guilib.ring" New qApp { win1 = new qMainWindow() { setwindowtitle("Using QToolbar") setGeometry(100,100,600,400) abtns = [ new qpushbutton(win1) { settext("Add") } , new qpushbutton(win1) { settext("Edit") } , new qpushbutton(win1) { settext("Find") } , new qpushbutton(win1) { settext("Delete") } , new qpushbutton(win1) { settext("Exit") setclickevent("win1.close()") } ] tool1 = new qtoolbar(win1) { for x in abtns addwidget(x) addseparator() next setmovable(true) setGeometry(0,0,500,30) 47.9. Creating Toolbar 396
418.
Ring Documentation, Release1.2 setFloatable(true) } show() } exec() } The application during the runtime 47.10 Creating StatusBar In this example we will learn about using the QStatusBar class Load "guilib.ring" New qApp { win1 = new qMainWindow() { setwindowtitle("Using QStatusbar") setGeometry(100,100,400,400) status1 = new qstatusbar(win1) { showmessage("Ready!",0) 47.10. Creating StatusBar 397
419.
Ring Documentation, Release1.2 } setstatusbar(status1) show() } exec() } The application during the runtime 47.11 Using QDockWidget In this example we will learn about using the QDockWidget class Load "guilib.ring" New qApp { win1 = new qMainWindow() { setwindowtitle("QDockWidget") setGeometry(100,100,400,400) label1 = new qlabel(win1) { settext("Hello") 47.11. Using QDockWidget 398
420.
Ring Documentation, Release1.2 setGeometry(300,300,100,100) } label2 = new qlabel(win1) { settext("How are you ?") setGeometry(100,100,100,100) } dock1 = new qdockwidget(win1,0) { setwidget(label1) SetAllowedAreas(1) } dock2 = new qdockwidget(win1,0) { setwidget(label2) SetAllowedAreas(2) } adddockwidget(Qt_LeftDockWidgetArea,dock1,Qt_Horizontal) adddockwidget(Qt_LeftDockWidgetArea,dock2,Qt_Vertical) show() } exec() } The application during the runtime 47.11. Using QDockWidget 399
421.
Ring Documentation, Release1.2 47.12 Using QTabWidget In this example we will learn about using the QTabWidget class Load "guilib.ring" New qApp { win1 = new qMainWindow() { setwindowtitle("Using QTabWidget") setGeometry(100,100,400,400) page1 = new qwidget() { new qpushbutton(page1) { settext("The First Page") } } page2 = new qwidget() { new qpushbutton(page2) { settext("The Second Page") } } page3 = new qwidget() { new qpushbutton(page3) { settext("The Third Page") } } tab1 = new qtabwidget(win1) { inserttab(0,page1,"Page 1") inserttab(1,page2,"Page 2") inserttab(2,page3,"Page 3") setGeometry(100,100,400,400) } status1 = new qstatusbar(win1) { showmessage("Ready!",0) } setstatusbar(status1) showMaximized() } exec() } The application during the runtime 47.12. Using QTabWidget 400
422.
Ring Documentation, Release1.2 47.13 Using QTableWidget In this example we will learn about using the QTableWidget class Load "guilib.ring" New qApp { win1 = new qMainWindow() { setGeometry(100,100,1100,370) setwindowtitle("Using QTableWidget") Table1 = new qTableWidget(win1) { setrowcount(10) setcolumncount(10) setGeometry(0,0,800,400) setselectionbehavior(QAbstractItemView_SelectRows) for x = 1 to 10 for y = 1 to 10 item1 = new qtablewidgetitem("R"+X+"C"+Y) setitem(x-1,y-1,item1) next next } setcentralwidget(table1) show() } 47.13. Using QTableWidget 401
423.
Ring Documentation, Release1.2 exec() } The application during the runtime 47.14 Using QProgressBar In this example we will learn about using the QProgressBar class Load "guilib.ring" New qApp { win1 = new qMainWindow() { setGeometry(100,100,600,150) setwindowtitle("Using QProgressBar") for x = 10 to 100 step 10 new qprogressbar(win1) { setGeometry(100,x,350,30) setvalue(x) } next show() } exec() } The application during the runtime 47.14. Using QProgressBar 402
424.
Ring Documentation, Release1.2 47.15 Using QSpinBox In this example we will learn about using the QSpinBox class Load "guilib.ring" New qApp { win1 = new qMainWindow() { setGeometry(100,100,450,260) setwindowtitle("Using QSpinBox") new qspinbox(win1) { setGeometry(50,100,350,30) setvalue(50) } show() } exec() } The application during the runtime 47.15. Using QSpinBox 403
425.
Ring Documentation, Release1.2 47.16 Using QSlider In this example we will learn about using the QSlider class Load "guilib.ring" New qApp { win1 = new qMainWindow() { setGeometry(100,100,500,400) setwindowtitle("Using QSlider") new qslider(win1) { setGeometry(100,100,50,130) settickinterval(50) } new qslider(win1) { setGeometry(100,250,250,30) settickinterval(50) setorientation(Qt_Horizontal) } show() } exec() } The application during the runtime 47.16. Using QSlider 404
426.
Ring Documentation, Release1.2 47.17 Using QDateEdit In this example we will learn about using the QDateEdit class Load "guilib.ring" New qApp { win1 = new qMainWindow() { setwindowtitle("Using QDateEdit") setGeometry(100,100,250,100) new qdateedit(win1) { setGeometry(20,40,220,30) } show() } exec() } The application during the runtime 47.17. Using QDateEdit 405
427.
Ring Documentation, Release1.2 47.18 Using QDial In this example we will learn about using the QDial class Load "guilib.ring" New qApp { win1 = new qMainWindow() { setGeometry(100,100,450,500) setwindowtitle("Using QDial") new qdial(win1) { setGeometry(100,100,250,300) } show() } exec() } The application during the runtime 47.18. Using QDial 406
428.
Ring Documentation, Release1.2 Another Example Load "guilib.ring" New qApp { win1 = new qMainWindow() { setGeometry(100,100,450,500) setwindowtitle("Using QDial") button1 = new QPushButton(win1){ setGeometry(100,350,100,30) settext("Increment") setClickEvent("pIncrement()") } button2 = new QPushButton(win1){ setGeometry(250,350,100,30) settext("Decrement") setClickEvent("pDecrement()") } pdial = new qdial(win1) { 47.18. Using QDial 407
Ring Documentation, Release1.2 47.19 Using QWebView In this example we will learn about using the QWebView class Load "guilib.ring" New qApp { win1 = new qMainWindow() { setwindowtitle("QWebView") myweb = new qwebview(win1) { setGeometry(10,10,600,600) loadpage(new qurl("http://google.com")) } setcentralwidget(myweb) showMaximized() } exec() } The application during the runtime 47.19. Using QWebView 409
431.
Ring Documentation, Release1.2 47.20 Using QCheckBox In this example we will learn about using the QCheckBox class Load "guilib.ring" New qApp { win1 = new qMainWindow() { setwindowtitle("Using QCheckBox") new qcheckbox(win1) { setGeometry(100,100,100,30) settext("New Customer!") } showMaximized() } exec() } The application during the runtime 47.20. Using QCheckBox 410
432.
Ring Documentation, Release1.2 Another Example: Load "guilib.ring" New qApp { win1 = new qMainWindow() { setGeometry(100,100,400,300) setwindowtitle("Using QCheckBox") ### 0-Unchecked 1-Checked CheckBox = new qcheckbox(win1) { setGeometry(100,100,160,30) settext("New Customer!") setclickedEvent("HandleClickEvent()") } show() } exec() } Func HandleClickEvent if CheckBox.isChecked() = 1 CheckBox.settext("New Customer. Check 1-ON") else CheckBox.settext("New Customer. Check 0-OFF") ok 47.21 Using QRadioButton and QButtonGroup In this example we will learn about using the QRadioButton and QButtonGroup classes Load "guilib.ring" 47.21. Using QRadioButton and QButtonGroup 411
433.
Ring Documentation, Release1.2 New qApp { win1 = new qMainWindow() { setwindowtitle("Using QRadioButton") new qradiobutton(win1) { setGeometry(100,100,100,30) settext("One") } new qradiobutton(win1) { setGeometry(100,150,100,30) settext("Two") } new qradiobutton(win1) { setGeometry(100,200,100,30) settext("Three") } group2 = new qbuttongroup(win1) { btn4 = new qradiobutton(win1) { setGeometry(200,150,100,30) settext("Four") } btn5 = new qradiobutton(win1) { setGeometry(200,200,100,30) settext("Five") } addbutton(btn4,0) addbutton(btn5,0) } showMaximized() } exec() } The application during the runtime 47.21. Using QRadioButton and QButtonGroup 412
434.
Ring Documentation, Release1.2 47.22 Adding Hyperlink to QLabel In this example we will learn about creating Hyperlink using the QLabel class Load "guilib.ring" New qApp { win1 = new qMainWindow() { setwindowtitle("QLabel - Hyperlink") new qlabel(win1) { setGeometry(100,100,100,30) setopenexternallinks(true) settext('<a href="http://google.com">Google</a>') } showMaximized() } exec() } The application during the runtime 47.22. Adding Hyperlink to QLabel 413
435.
Ring Documentation, Release1.2 47.23 QVideoWidget and QMediaPlayer In this example we will learn about using the QVideoWidget and QMediaPlayer classes to play a group of movies from different positions at the same time Load "guilib.ring" New qApp { win1 = new qMainWindow() { setwindowtitle("QVideoWidget") btn1 = new qpushbutton(win1) { setGeometry(0,0,100,30) settext("play") setclickevent("player.play() player2.play() player3.play() player4.play()") } videowidget = new qvideowidget(win1) { setGeometry(50,50,600,300) setstylesheet("background-color: black") } videowidget2 = new qvideowidget(win1) { setGeometry(700,50,600,300) setstylesheet("background-color: black") } videowidget3 = new qvideowidget(win1) { setGeometry(50,370,600,300) setstylesheet("background-color: black") } videowidget4 = new qvideowidget(win1) { 47.23. QVideoWidget and QMediaPlayer 414
436.
Ring Documentation, Release1.2 setGeometry(700,370,600,300) setstylesheet("background-color: black") } player = new qmediaplayer() { setmedia(new qurl("1.mp4")) setvideooutput(videowidget) setposition(35*60*1000) } player2 = new qmediaplayer() { setmedia(new qurl("2.mp4")) setvideooutput(videowidget2) setposition(23*60*1000) } player3 = new qmediaplayer() { setmedia(new qurl("3.mp4")) setvideooutput(videowidget3) setposition(14.22*60*1000) } player4 = new qmediaplayer() { setmedia(new qurl("4.avi")) setvideooutput(videowidget4) setposition(8*60*1000) } showfullscreen() } exec() } The application during the runtime 47.23. QVideoWidget and QMediaPlayer 415
437.
Ring Documentation, Release1.2 47.24 Using QFrame In this example we will learn about using the QFrame class Load "guilib.ring" New qApp { win1 = new qMainWindow() { setwindowtitle("Using QFrame") for x = 0 to 10 frame1 = new qframe(win1,0) { setGeometry(100,20+50*x,400,30) setframestyle(QFrame_Raised | QFrame_WinPanel) } next showMaximized() } exec() } The application during the runtime 47.24. Using QFrame 416
438.
Ring Documentation, Release1.2 47.25 Display Image using QLabel In this example we will learn about displaying an image using the QLabel widget Load "guilib.ring" New qApp { win1 = new qMainWindow() { setwindowtitle("QLabel - Display image") new qlabel(win1) { image = new qpixmap("b:/mahmoud/photo/advice.jpg") setpixmap(image) setGeometry(0,0,image.width(),image.height()) } 47.25. Display Image using QLabel 417
439.
Ring Documentation, Release1.2 showMaximized() } exec() } The application during the runtime 47.26 Menubar and StyleSheet Example In this example we will learn about creating menubar and setting the window stylesheet Load "guilib.ring" New qApp { 47.26. Menubar and StyleSheet Example 418
440.
Ring Documentation, Release1.2 win1 = new qMainWindow() { setwindowtitle("Menubar") menu1 = new qmenubar(win1) { sub1 = addmenu("File") sub1 { oAction = new qAction(win1) { settext("New") setenabled(false) } addaction(oAction) oAction = new qAction(win1) { settext("Open") setcheckable(true) setchecked(true) setstatustip("open new file") } addaction(oAction) oAction = new qAction(win1) { settext("Save") } addaction(oAction) oAction = new qAction(win1) { settext("Save As") } addaction(oAction) addseparator() oAction = new qaction(win1) oAction.settext("Exit") oAction.setclickevent("myapp.quit()") addaction(oAction) } } status1 = new qstatusbar(win1) { showmessage("Ready!",0) } setmenubar(menu1) setmousetracking(true) setstatusbar(status1) setStyleSheet("color: black; selection-color: black; selection-background-color:white ; background: QLinearGradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #eef, stop: 1 #ccf);") showmaximized() } exec() } The application during the runtime 47.26. Menubar and StyleSheet Example 419
441.
Ring Documentation, Release1.2 47.27 QLineEdit Events and QMessageBox In this example we will learn about using QLineEdit Events and displaying a Messagebox Load "guilib.ring" MyApp = New qApp { win1 = new qWidget() { setwindowtitle("Welcome") setGeometry(100,100,400,300) label1 = new qLabel(win1) { settext("What is your name ?") setGeometry(10,20,350,30) setalignment(Qt_AlignHCenter) } btn1 = new qpushbutton(win1) { setGeometry(10,200,100,30) settext("Say Hello") setclickevent("pHello()") } btn1 = new qpushbutton(win1) { setGeometry(150,200,100,30) settext("Close") setclickevent("pClose()") } lineedit1 = new qlineedit(win1) { setGeometry(10,100,350,30) settextchangedevent("pChange()") setreturnpressedevent("penter()") } 47.27. QLineEdit Events and QMessageBox 420
442.
Ring Documentation, Release1.2 show() } exec() } Func pHello lineedit1.settext( "Hello " + lineedit1.text()) Func pClose MyApp.quit() Func pChange win1 { setwindowtitle( lineedit1.text() ) } Func pEnter new qmessagebox(win1) { setwindowtitle("Thanks") settext("Hi " + lineedit1.text() ) setstylesheet("background-color : white") show() } The application during the runtime 47.27. QLineEdit Events and QMessageBox 421
443.
Ring Documentation, Release1.2 47.28 Other Widgets Events Each Qt signal can be used in RingQt, just add Set before the signal name and add event after the signal name to get the method that can be used to determine the event code. For example the QProgressBar class contains a signal named valueChanged() To use it just use the function setVal- ueChangedEvent() Example: Load "guilib.ring" New qApp { win1 = new qMainWindow() { setwindowtitle("QProgressBar valueChanged Event") progress1 = new qprogressbar(win1) { setGeometry(100,100,350,30) setvalue(10) setvaluechangedevent("pChange()") } new qpushbutton(win1) { setGeometry(10,10,100,30) settext("increase") setclickevent("pIncrease()") } showMaximized() } 47.28. Other Widgets Events 422
444.
Ring Documentation, Release1.2 exec() } func pIncrease progress1 { setvalue(value()+1) } func pchange win1.setwindowtitle("value : " + progress1.value() ) The application during the runtime Another example for the stateChanged event of the QCheckBox class Load "guilib.ring" New qApp { win1 = new qMainWindow() { setwindowtitle("QCheckBox") new qcheckbox(win1) { setGeometry(100,100,100,30) settext("New Customer!") setstatechangedevent("pchange()") } showMaximized() } exec() } Func pChange new qMessageBox(Win1) { setWindowTitle("Checkbox") settext("State Changed!") show() } The application during the runtime 47.28. Other Widgets Events 423
445.
Ring Documentation, Release1.2 47.29 Using the QTimer Class In this example we will learn about using the QTimer class Load "guilib.ring" new qApp { win1 = new qwidget() { setgeometry(100,100,200,70) setwindowtitle("Timer") label1 = new qlabel(win1) { setgeometry(10,10,200,30) settext(thetime()) } new qtimer(win1) { setinterval(1000) settimeoutevent("pTime()") start() } show() } exec() } func ptime label1.settext(thetime()) Func thetime return "Time : " + Time() The application during the runtime 47.29. Using the QTimer Class 424
446.
Ring Documentation, Release1.2 47.30 Using QProgressBar and Timer In this example we will learn about using the “animated” QProgressBar class and Timer ###------------------------------------ ### ProgressBar and Timer Example Load "guilib.ring" new qApp { win1 = new qwidget() { setgeometry(100,100,400,100) setwindowtitle("Timer and ProgressBar") LabelMan = new qlabel(win1) { setgeometry(10,10,200,30) settext(theTime()) ### ==>> func } TimerMan = new qtimer(win1) { setinterval(1000) settimeoutevent("pTime()") ### ==>> func start() } BarMan = new qprogressbar(win1) { setGeometry(100,50,300,10) ### Position X y, Length, Thickness setvalue(0) ### Percent filled } show() } exec() } func pTime LabelMan.settext(theTime()) ### ==>> func Increment = 10 if BarMan.value() >= 100 ### ProgressBar start over. BarMan.setvalue(0) ok BarMan{ setvalue(value() + Increment) } 47.30. Using QProgressBar and Timer 425
447.
Ring Documentation, Release1.2 Func theTime return "Time : " + Time() 47.31 Display Scaled Image using QLabel In this example we will learn about displaying and scaling an image so that it looks “animated” using the QLabel widget Load "guilib.ring" #---------------------------------------------------- # REQUIRES: image = "C:RINGbinstock.jpg" # imageStock: start dimensions for growing image imageW = 200 ; imageH = 200 ; GrowBy = 4 ###---------------------------------------------------- ### Window and Box Size dimensions WinWidth = 1280 ; WinHeight = 960 BoxWidth = WinWidth -80 ; BoxHeight = WinHeight -80 ###---------------------------------------------------- New qapp { win1 = new qwidget() { setgeometry(50,50, WinWidth,WinHeight) setwindowtitle("Animated Image - Display Image Scaled and Resized") imageStock = new qlabel(win1) { image = new qpixmap("C:RINGbinstock.jpg") AspectRatio = image.width() / image.height() imageW = 200 imageH = imageH / AspectRatio ### Size-H, Size-V, Aspect, Transform setpixmap(image.scaled(imageW , imageH ,0,0)) PosLeft = (BoxWidth - imageW ) / 2 PosTop = (BoxHeight - imageH ) / 2 47.31. Display Scaled Image using QLabel 426
448.
Ring Documentation, Release1.2 setGeometry(PosLeft,PosTop,imageW,imageH) } TimerMan = new qtimer(win1) { setinterval(100) ### interval 100 millisecs. settimeoutevent("pTime()") ### ==>> func start() } show() } exec() } ###------------------------------------------------------ ### Fuction TimerMan: calling interval 100 milliseconds func pTime ### Stop Timer when image is size of Window area if imageW > BoxWidth TimerMan.stop() imageStock.clear() ### Will clear the image ok ### Grow image imageW += GrowBy imageH = imageW / AspectRatio ### Scaled Image: Size-H, Size-V, Aspect, Transform imageStock.setpixmap(image.scaled(imageW , imageH ,0,0)) ### Center the image PosLeft = (WinWidth - imageW ) / 2 PosTop = (WinHeight - imageH ) / 2 imageStock.setGeometry(PosLeft,PosTop,imageW,imageH) 47.32 Using the QFileDialog Class Example Load "guilib.ring" New qapp { win1 = new qwidget() { setwindowtitle("open file") setgeometry(100,100,400,400) new qpushbutton(win1) { setgeometry(10,10,200,30) settext("open file") setclickevent("pOpen()") } show() } 47.32. Using the QFileDialog Class 427
449.
Ring Documentation, Release1.2 exec() } Func pOpen new qfiledialog(win1) { cName = getopenfilename(win1,"open file","c:","source files(*.ring)") win1.setwindowtitle(cName) } The application during the runtime 47.33 Drawing using QPainter In this example we will learn about drawing using the QPainter class Load "guilib.ring" New qapp { win1 = new qwidget() { setwindowtitle("Drawing using QPainter") setgeometry(100,100,500,500) label1 = new qlabel(win1) { setgeometry(10,10,400,400) settext("") } new qpushbutton(win1) { setgeometry(200,400,100,30) settext("draw") setclickevent("draw()") } show() } 47.33. Drawing using QPainter 428
450.
Ring Documentation, Release1.2 exec() } Func draw p1 = new qpicture() color = new qcolor() { setrgb(0,0,255,255) } pen = new qpen() { setcolor(color) setwidth(10) } new qpainter() { begin(p1) setpen(pen) drawline(500,150,950,450) drawline(950,550,500,150) endpaint() } label1 { setpicture(p1) show() } The application during the runtime 47.33. Drawing using QPainter 429
451.
Ring Documentation, Release1.2 47.34 Printing using QPrinter In this example we will learn how to print to PDF file using QPrinter Load "guilib.ring" new qApp { win1 = new qwidget() { setwindowtitle("Printer") setgeometry(100,100,500,500) myweb = new qwebview(win1) { setgeometry(100,100,1000,500) loadpage(new qurl("http://google.com")) } new qpushbutton(win1) { setGeometry(20,20,100,30) settext("Print") setclickevent("print()") } showmaximized() 47.34. Printing using QPrinter 430
452.
Ring Documentation, Release1.2 } exec() } func print printer1 = new qPrinter(0) { setoutputformat(1) # 1 = pdf setoutputfilename("test.pdf") painter = new qpainter() { begin(printer1) myfont = new qfont("Times",50,-1,0) setfont(myfont) drawtext(100,100,"test") printer1.newpage() drawtext(100,100,"test2") endpaint() } } printer1 = new qPrinter(0) { setoutputformat(1) setoutputfilename("test2.pdf") myweb.print(printer1) myweb.show() } system ("test.pdf") system ("test2.pdf") 47.35 Creating More than one Window The next example demonstrates how to create more than one window Load "guilib.ring" app1 = new qapp { win1 = new qwidget() { setwindowtitle("First") setgeometry(100,100,500,500) new qpushbutton(win1) { setgeometry(100,100,100,30) settext("close") setclickevent("app1.quit()") } new qpushbutton(win1) { setgeometry(250,100,100,30) settext("Second") setclickevent("second()") } showmaximized() } exec() } 47.35. Creating More than one Window 431
453.
Ring Documentation, Release1.2 func second win2 = new qwidget() { setwindowtitle("Second") setgeometry(100,100,500,500) setwindowflags(Qt_dialog) show() } The application during the runtime 47.36 Playing Sound Example: Load "guilib.ring" new qapp { win1 = new qwidget() { setwindowtitle("play sound!") show() } new qmediaplayer() { setmedia(new qurl("footstep.wav")) setvolume(50) play() } exec() } 47.37 Using the QColorDialog Class Example: 47.36. Playing Sound 432
454.
Ring Documentation, Release1.2 Load "guilib.ring" oApp = new myapp { start() } Class MyApp oColor win1 Func start myapp = new qapp win1 = new qMainWindow() { setwindowtitle("Color Dialog") setgeometry(100,100,400,400) } new qpushbutton(win1) { setgeometry(10,10,100,30) settext("Get Color") setclickevent("oApp.pColor()") } win1.show() myapp.exec() Func pColor myobj = new qcolordialog() aColor = myobj.GetColor() r=acolor[1] g=acolor[2] b=acolor[3] win1.setstylesheet("background-color: rgb("+r+", " + g+ "," + b + ")") The application during the runtime 47.37. Using the QColorDialog Class 433
455.
Ring Documentation, Release1.2 47.38 Using qLCDNumber Class In this example we will learn about using the qLCDNumber class Load "guilib.ring" New qApp { win1 = new qWidget() { setwindowtitle("LCD Number") setgeometry(100,100,250,120) new qLCDNumber(win1) { setgeometry(10,10,100,40) display(100) } new qLCDNumber(win1) { setgeometry(10,60,100,40) display(80) } show() } exec() } The application during the runtime 47.39 Movable Label Example Load "guilib.ring" new qApp { win1 = new qWidget() { 47.38. Using qLCDNumber Class 434
456.
Ring Documentation, Release1.2 label1 = new qLabel(win1) { setText("Welcome") setgeometry(10,10,200,50) setstylesheet("color: purple ; font-size: 30pt;") } new qTimer(win1) { setInterVal(10) setTimeOutEvent("pMove()") start() } setWindowTitle("Movable Label") setgeometry(100,100,600,80) setStyleSheet("background-color: white;") show() } exec() } Func pMove label1 { move(x()+1,y()) if x() > 600 move(10,y()) ok } The application during the runtime 47.40 QMessagebox Example In this section we will learn how to check the output of the Message box Load "guilib.ring" new qApp { win1 = new qWidget() { label1 = new qpushbutton(win1) { setText("Test") setgeometry(10,10,200,50) 47.40. QMessagebox Example 435
457.
Ring Documentation, Release1.2 setstylesheet("color: purple ; font-size: 30pt;") setclickevent("pWork()") } setWindowTitle("Messagebox") setgeometry(100,100,600,80) setStyleSheet("background-color: white;") show() } exec() } func pWork new qmessagebox(win1) { setwindowtitle("messagebox title") settext("messagebox text") setInformativeText("Do you want to save your changes?") setstandardbuttons(QMessageBox_Yes | QMessageBox_No | QMessageBox_Close) result = exec() win1 { if result = QMessageBox_Yes setwindowtitle("Yes") but result = QMessageBox_No setwindowtitle("No") but result = QMessageBox_Close setwindowtitle("Close") ok } } The application during the runtime 47.41 Using QInputDialog Class In the next example we will learn about using the QInputDialog class 47.41. Using QInputDialog Class 436
458.
Ring Documentation, Release1.2 Load "guilib.ring" New QApp { Win1 = New QWidget () { SetGeometry(100,100,400,400) SetWindowTitle("Input Dialog") New QPushButton(win1) { SetText ("Input Dialog") SetGeometry(100,100,100,30) SetClickEvent("pWork()") } Show() } exec() } Func pWork oInput = New QInputDialog(win1) { setwindowtitle("What is your name?") setgeometry(100,100,400,50) setlabeltext("User Name") settextvalue("Mahmoud") lcheck = exec() if lCheck win1.setwindowtitle(oInput.textvalue()) ok } The application during the runtime 47.41. Using QInputDialog Class 437
459.
Ring Documentation, Release1.2 47.42 KeyPress and Mouse Move Events In this example we will learn how to use the Events Filter to know about KeyPress and Mouse Move Events Load "guilib.ring" new qApp { win1 = new qWidget() { setWindowTitle("Test using Event Filter!") setGeometry(100,100,400,400) setmousetracking(true) myfilter = new qallevents(win1) myfilter.setKeyPressEvent("pWork()") myfilter.setMouseButtonPressevent("pClick()") myfilter.setmousemoveevent("pMove()") installeventfilter(myfilter) show() } exec() } 47.42. KeyPress and Mouse Move Events 438
460.
Ring Documentation, Release1.2 func pWork win1.setwindowtitle('KeyPress! : ' + myfilter.getkeycode()) func pClick new qmessagebox(win1) { setgeometry(100,100,400,100) setwindowtitle("click event!") settext("x : " + myfilter.getx() + " y : " + myfilter.gety() + " button : " + myfilter.getbutton() ) show() } func pMove win1.setwindowtitle("Mouse Move , X : " + myfilter.getx() + " Y : " + myfilter.gety() ) The application during the runtime 47.43 Moving Objects using the Mouse In the next example we will learn how to program movable objects where the user can move a label Load "guilib.ring" lPress = false 47.43. Moving Objects using the Mouse 439
461.
Ring Documentation, Release1.2 nX = 0 nY = 0 new qApp { win1 = new qWidget() { setWindowTitle("Move this label!") setGeometry(100,100,400,400) setstylesheet("background-color:white;") Label1 = new qLabel(Win1){ setGeometry(100,100,200,50) setText("Welcome") setstylesheet("font-size: 30pt") myfilter = new qallevents(label1) myfilter.setEnterevent("pEnter()") myfilter.setLeaveevent("pLeave()") myfilter.setMouseButtonPressEvent("pPress()") myfilter.setMouseButtonReleaseEvent("pRelease()") installeventfilter(myfilter) } show() } exec() } Func pEnter Label1.setStyleSheet("background-color: purple; color:white;font-size: 30pt;") Func pLeave Label1.setStyleSheet("background-color: white; color:black;font-size: 30pt;") Func pPress lPress = True nX = myfilter.getglobalx() ny = myfilter.getglobaly() Func pRelease lPress = False pEnter() Func pMove nX2 = myfilter.getglobalx() ny2 = myfilter.getglobaly() ndiffx = nX2 - nX ndiffy = nY2 - nY if lPress Label1 { move(x()+ndiffx,y()+ndiffy) setStyleSheet("background-color: Green; color:white;font-size: 30pt;") nX = nX2 ny = nY2 } 47.43. Moving Objects using the Mouse 440
462.
Ring Documentation, Release1.2 ok The application during the runtime 47.43. Moving Objects using the Mouse 441
Ring Documentation, Release1.2 47.44 Inheritance from GUI Classes Example : Load "guilib.ring" New MyWindow() new qApp { exec() } class mywindow from qwidget Func init super.init() setwindowtitle("First Window") setgeometry(100,100,400,400) setstylesheet("background-color: purple;") settooltip("my first window!") show() The application during the runtime 47.44. Inheritance from GUI Classes 443
465.
Ring Documentation, Release1.2 47.45 Using QDesktopWidget Class In the next example we will learn about using the QDesktopWidget class Load "guilib.ring" New qApp { win1 = New qWidget() { resize(400,400) btn1 = new qPushbutton(win1) { setText("Center") move(100,100) resize(100,30) setClickEvent("pCenter()") } Show() } exec() } Func pCenter oDesktop = new qDesktopWidget() 47.45. Using QDesktopWidget Class 444
466.
Ring Documentation, Release1.2 oRect = oDesktop.screenGeometry( oDesktop.primaryScreen() ) win1.move((oRect.width()-win1.width()) /2 , (oRect.Height()-win1.Height())/2 ) win1.show() The application during the runtime 47.46 Rotate Text The next example rotate text using a Timer. Load "guilib.ring" nAngle = 0 New qapp { win1 = new qwidget() { setwindowtitle("Rotate Text") resize(800,600) label1 = new qlabel(win1) { settext("") myfilter = new qallevents(win1) myfilter.setMouseButtonPressevent("pClick()") installeventfilter(myfilter) } new qtimer(win1) { setinterval(50) 47.46. Rotate Text 445
467.
Ring Documentation, Release1.2 settimeoutevent("pTime()") start() } pDraw() L1 = new qVBoxLayout() { AddWidget(Label1) } SetLayout(L1) showMaximized() } exec() } Func pDraw p1 = new qpicture() color = new qcolor() { setrgb(0,0,255,255) } pen = new qpen() { setcolor(color) setwidth(50) } painter = new qpainter() { begin(p1) setpen(pen) myfont = font() myfont.setpointsize(50) setfont(myfont) rotate(nAngle) drawtext(350,0*nAngle,"welcome") drawtext(0,0*nAngle,"welcome") endpaint() } label1 { setpicture(p1) show() } Func pClick win1 { setwindowtitle("Click Event") } Func pTime nAngle++ if nAngle = 90 nAngle = 10 ok pDraw() The application during the runtime 47.46. Rotate Text 446
468.
Ring Documentation, Release1.2 47.47 Change Focus The next example change the focus using the ENTER key. load "guilib.ring" new qApp { win = new qWidget() { resize(600,600) SetWindowTitle("Change Focus") text1 = new qLineEdit(win) text2 = new qLineEdit(win) text3 = new qLineEdit(win) text4 = new qLineEdit(win) layout1 = new qVBoxLayout() { AddWidget(text1) AddWidget(text2) AddWidget(text3) AddWidget(text4) } setLayout(Layout1) 47.47. Change Focus 447
469.
Ring Documentation, Release1.2 aList = [text1,text2,text3,text4] oFilter = new qallevents(win) oFilter.setKeyPressEvent("pWork()") installeventfilter(oFilter) show() } exec() } func pWork nCode = oFilter.getkeycode() if nCode = 16777220 # ENTER Key for x=1 to len(aList) if aList[x].HasFocus() t = x+1 if t > len(aList) t=1 ok aList[t].SetFocus(0) exit ok next ok 47.48 Regular Expressions The next example uses the Regular Expressions classes. load "guilib.ring" new qApp { see "Using Regular Expressions" + nl exp = new qregularexpression() { setPattern("dd w+") see pattern() + nl match = match("33 one",0,0,0) see match.hasmatch() + nl match = match("3 one",0,0,0) see match.hasmatch() + nl match = match("welcome 11 one",0,0,0) see match.hasmatch() + nl matched = match.captured(0) see matched + nl } exp = new qregularexpression() { setPattern("^(dd)/(dd)/(dddd)$") see pattern() + nl match = match("08/12/1985",0,0,0) see match.hasmatch() + nl day = match.captured(1) month = match.captured(2) year = match.captured(3) see day + nl + month + nl + year + nl see "(" + match.capturedStart(1) + "," + match.capturedEnd(1)+ ")" + nl see "(" + match.capturedStart(2) + "," + match.capturedEnd(2)+ ")" + nl see "(" + match.capturedStart(3) + "," + match.capturedEnd(3)+ ")" + nl 47.48. Regular Expressions 448
470.
Ring Documentation, Release1.2 } } Output Using Regular Expressions dd w+ 1 0 1 11 one ^(dd)/(dd)/(dddd)$ 1 08 12 1985 (0,2) (3,5) (6,10) 47.49 Simple Client and Server Example In this section we will learn about creating simple Client and Server Application Load "guilib.ring" new qApp { oClient = new Client { client() } oServer = new Server { server() } exec() } Class Client win1 lineedit1 cOutput="" oTcpSocket func client win1 = new qwidget() new qpushbutton(win1) { setgeometry(50,50,100,30) settext("connect") setclickevent("oClient.Connect()") } lineedit1 = new qtextedit(win1) { setGeometry(150,50,200,300) } win1 { setwindowtitle("client") setgeometry(10,100,400,400) show() 47.49. Simple Client and Server Example 449
471.
Ring Documentation, Release1.2 } func connect cOutput = "Connect to host 127.0.0.1 port 9999" + nl lineedit1.settext(cOutput) oTcpSocket = new qTcpSocket(win1) { setconnectedevent("oClient.pConnected()") setreadyreadevent("oClient.pRead()") connecttohost("127.0.0.1",9999,3,0) waitforconnected(5000) } func pConnected cOutput += "Connected!" + nl lineedit1.settext(cOutput) func pRead cOutput += "Ready Read!" + nl lineedit1.settext(cOutput) cOutput += oTcpSocket.readall().data() + nl lineedit1.settext(cOutput) Class Server win1 lineedit1 oTcpServer oTcpClient cOutput = "" func server win1 = new qwidget() lineedit1 = new qtextedit(win1) { setGeometry(150,50,200,300) } win1 { setwindowtitle("Server") setgeometry(450,100,400,400) show() } oTcpServer = new qTcpServer(win1) { setNewConnectionEvent("oServer.pNewConnection()") oHostAddress = new qHostAddress() oHostAddress.SetAddress("127.0.0.1") listen(oHostAddress,9999) } cOutput = "Server Started" + nl + "listen to port 9999" + nl lineedit1.settext(cOutput) Func pNewConnection oTcpClient = oTcpServer.nextPendingConnection() 47.49. Simple Client and Server Example 450
472.
Ring Documentation, Release1.2 cOutput += "Accept Connection" + nl lineedit1.settext(cOutput) oTcpClient { cStr ="Hello from server to client!"+char(13)+char(10) write(cStr,len(cStr)) flush() waitforbyteswritten(300000) close() } The application during the runtime 47.50 Dynamic Objects We may create objects in the runtime and add them to windows. Example: load "guilib.ring" oFormDesigner = new FormDesigner { start("oFormDesigner") } Class FormDesigner winToolBox winForm aObjects = [] func start cObjectName oApp = new qApp winToolBox = new qWidget() winToolBox.setWindowTitle("ToolBox") 47.50. Dynamic Objects 451
473.
Ring Documentation, Release1.2 winToolBox.move(10,10) winToolBox.resize(300,600) btn = new qPushButton(winToolBox) btn.resize(300,30) btn.setText("Create Button") btn.setClickEvent(cObjectName+".pCreateButton()") btn.show() winToolBox.show() winForm = new qWidget() { move(400,50) setWindowTitle("Form Designer") resize(600,600) show() } oApp.exec() func pCreateButton nCount = len(aObjects) aObjects + new MyButton(winForm) { nIndex = nCount + 1 setText("Button"+ nIndex) Move(30*nIndex,30*nIndex) resize(100,30) show() } Class MyButton from qPushButton nIndex = 0 47.51 Weight History Application The next sample help in recording (Date, Time and Weight). Load "guilib.ring" MyApp = new qApp { $ApplicationObject = "oApp" # To be used when calling events oApp = new App exec() oApp.CloseDatabase() } class App cDir = currentdir() + "/" oCon 47.51. Weight History Application 452
474.
Ring Documentation, Release1.2 aIDs = [] win1 = new qWidget() { setWindowTitle("Weight History") resize(600,600) layoutButtons = new qhboxlayout() { label1 = new qLabel(win1) { setText("Weight") } text1 = new qlineedit(win1) btnAdd = new qpushbutton(win1) { setText("Add") setClickEvent($ApplicationObject+".AddWeight()") } btnDelete = new qpushbutton(win1) { setText("Delete") setClickEvent($ApplicationObject+".Deleteweight()") } addwidget(label1) addwidget(text1) addwidget(btnAdd) addwidget(btnDelete) } layoutData = new qhboxlayout() { Table1 = new qTableWidget(win1) { setrowcount(0) setcolumncount(3) setselectionbehavior(QAbstractItemView_SelectRows) setHorizontalHeaderItem(0, new QTableWidgetItem("Date")) setHorizontalHeaderItem(1, new QTableWidgetItem("Time")) setHorizontalHeaderItem(2, new QTableWidgetItem("Weight")) setitemChangedEvent($ApplicationObject+".ItemChanged()") setAlternatingRowColors(true) horizontalHeader().setStyleSheet("color: blue") verticalHeader().setStyleSheet("color: red") } addWidget(Table1) } layoutClose = new qhboxlayout() { btnclose = new qpushbutton(win1) { setText("Close") setClickEvent("MyApp.Quit()") } addwidget(btnClose) } layoutMain = new qvboxlayout() { addlayout(layoutButtons) addLayout(LayoutData) addLayout(layoutClose) } setlayout(layoutMain) self.OpenDatabase() self.ShowRecords() show() } 47.51. Weight History Application 453
475.
Ring Documentation, Release1.2 Func OpenDatabase lCreate = False if not fexists(cDir + "weighthistory.db") lCreate = True ok new QSqlDatabase() { this.oCon = addDatabase("QSQLITE") { setDatabaseName("weighthistory.db") Open() } } if lCreate new QSqlQuery( ) { exec("create table weighthistory (id integer primary key,"+ " f_date varchar(10),"+ " f_time varchar(8), f_weight varchar(8) );") delete() } ok Func CloseDatabase oCon.Close() Func AddWeight cWeight = text1.text() AddRecord(cWeight) Func DeleteWeight Table1 { nRow = CurrentRow() if nRow >= 0 nID = this.aIDs[nROW+1] new QSqlQuery( ) { exec("delete from weighthistory where id = " + nID ) } Del(this.aIDs,nRow+1) removerow(nRow) selectrow(nRow) ok } Func AddRecord cWeight new QSqlQuery( ) { cStr = "insert into weighthistory (f_date,f_time,f_weight) values"+ " ('%f1','%f2','%f3')" cDate = Date() cTime = Time() cStr = substr(cStr,"%f1",cDate) cStr = substr(cStr,"%f2",cTime) cStr = substr(cStr,"%f3",cWeight) exec(cStr) delete() } ShowRecords() Table1.selectrow(table1.rowcount()-1) 47.51. Weight History Application 454
476.
Ring Documentation, Release1.2 Func ShowRecords table1.setitemChangedEvent("") aIDs = [] query = new QSqlQuery() { exec("select * from weighthistory") nRows = 0 this.Table1.setrowcount(0) while movenext() this.table1 { insertRow(nRows) this.aIDs + query.value(0).tostring() for x = 1 to 3 cStr = query.value(x).tostring() item = new qTableWidgetItem(cStr) setItem(nRows,x-1,item) next } nRows++ end delete() } table1.setitemChangedEvent($ApplicationObject+".ItemChanged()") Func ItemChanged nRow = table1.currentrow() if nRow >= 0 myitem = Table1.item(table1.currentrow(),0) cDate = myitem.text() myitem = Table1.item(table1.currentrow(),1) cTime = myitem.text() myitem = Table1.item(table1.currentrow(),2) cWeight = myitem.text() new QSqlQuery( ) { cStr = "update weighthistory set f_date ='%f1' , f_time = '%f2' , "+ "f_weight ='%f3' where id = " + this.aIDs[nROW+1] cStr = substr(cStr,"%f1",cDate) cStr = substr(cStr,"%f2",cTime) cStr = substr(cStr,"%f3",cWeight) exec(cStr) delete() } ok The next screen shot for the application during the runtime 47.51. Weight History Application 455
477.
Ring Documentation, Release1.2 47.52 Notepad Application In the next example we will see simple Notepad developed using the RingQt Load "guilib.ring" cActiveFileName = "" aTextColor = [0,0,0] aBackColor = [255,255,255] cFont = "MS Shell Dlg 2,14,-1,5,50,0,0,0,0,0" cWebsite = "http://www.google.com" 47.52. Notepad Application 456
478.
Ring Documentation, Release1.2 oSearch = NULL oSearchValue = NULL oSearchCase = NULL oSearchFilter = NULL oReplaceValue = NULL lAskToSave = false MyApp = New qApp { win1 = new qMainWindow() { setwindowtitle("Ring Notepad") setGeometry(100,100,400,400) aBtns = [ new qpushbutton(win1) { setbtnimage(self,"image/new.png") setclickevent("pNew()") settooltip("New File") } , new qpushbutton(win1) { setbtnimage(self,"image/open.png") setclickevent("pOpen()") settooltip("Open File") } , new qpushbutton(win1) { setbtnimage(self,"image/save.png") setclickevent("pSave()") settooltip("Save") } , new qpushbutton(win1) { setbtnimage(self,"image/saveas.png") setclickevent("pSaveAs()") settooltip("Save As") } , new qpushbutton(win1) { setbtnimage(self,"image/cut.png") setclickevent("pCut()") settooltip("Cut") } , new qpushbutton(win1) { setbtnimage(self,"image/copy.png") setclickevent("pCopy()") settooltip("Copy") } , new qpushbutton(win1) { setbtnimage(self,"image/paste.png") setclickevent("pPaste()") settooltip("Paste") } , new qpushbutton(win1) { setbtnimage(self,"image/font.png") setclickevent("pFont()") settooltip("Font") } , new qpushbutton(win1) { setbtnimage(self,"image/colors.jpg") setclickevent("pColor()") settooltip("Text Color") 47.52. Notepad Application 457
479.
Ring Documentation, Release1.2 } , new qpushbutton(win1) { setbtnimage(self,"image/search.png") setclickevent("pFind()") settooltip("Find and Replace") } , new qpushbutton(win1) { setbtnimage(self,"image/print.png") setclickevent("pPrint()") settooltip("Print") } , new qpushbutton(win1) { setbtnimage(self,"image/debug.png") setclickevent("pDebug()") settooltip("Debug (Run then wait!)") } , new qpushbutton(win1) { setbtnimage(self,"image/run.png") setclickevent("pRun()") settooltip("Run the program") } , new qpushbutton(win1) { setbtnimage(self,"image/close.png") setclickevent("pQuit()") settooltip("Quit") } ] tool1 = addtoolbar("files") { for x in aBtns addwidget(x) addseparator() next } menu1 = new qmenubar(win1) { sub1 = addmenu("File") sub2 = addmenu("Edit") sub3 = addmenu("View") sub4 = addmenu("Help") sub1 { oAction = new qAction(win1) { setShortcut(new QKeySequence("Ctrl+n")) setbtnimage(self,"image/new.png") settext("New") setclickevent("pNew()") } addaction(oAction) oAction = new qAction(win1) { setShortcut(new QKeySequence("Ctrl+o")) setbtnimage(self,"image/open.png") settext("Open") setclickevent("pOpen()") } addaction(oAction) addseparator() oAction = new qAction(win1) { setShortcut(new QKeySequence("Ctrl+s")) setbtnimage(self,"image/save.png") settext("Save") setclickevent("pSave()") 47.52. Notepad Application 458
Ring Documentation, Release1.2 aCode = str2list(cCode) fp = fopen(cFileName,"wb") for cLine in aCode fwrite(fp,cLine+char(13)+char(10)) next fclose(fp) Func MsgBox cTitle,cMessage new qMessagebox(win1) { setwindowtitle(cTitle) setText(cMessage) show() } Func pLang MsgBox("Programming Language", "This application developed using the Ring programming language") Func pGUI MsgBox("GUI Library", "This application uses the Qt GUI Library through RingQt") Func pAbout MsgBox("About", "2016, Mahmoud Fayed <msfclipper@yahoo.com>") Func pSaveSettings cSettings = "aTextColor = ["+aTextColor[1]+","+aTextColor[2]+ ","+aTextColor[3]+"]" + nl + "aBackColor = ["+aBackColor[1]+","+aBackColor[2]+ ","+aBackColor[3]+"]" + nl + "cFont = '" + cFont + "'" + nl + "cWebSite = '" + cWebsite + "'" + nl cSettings = substr(cSettings,nl,char(13)+char(10)) write("ringnotepad.ini",cSettings) if lAsktoSave new qmessagebox(win1) { setwindowtitle("Save Changes?") settext("Some changes are not saved!") setInformativeText("Do you want to save your changes?") setstandardbuttons(QMessageBox_Yes | QMessageBox_No | QMessageBox_Cancel) result = exec() win1 { if result = QMessageBox_Yes pSave() but result = QMessageBox_Cancel return false ok } } ok return true Func pSetWebsite oWebView { loadpage(new qurl(cWebSite)) } 47.52. Notepad Application 469
491.
Ring Documentation, Release1.2 oWBText { setText(cWebSite) } Func RestoreSettings eval(read("ringnotepad.ini")) pSetColors() pSetFont() pSetWebsite() Func pQuit if pSaveSettings() myapp.quit() ok The application during the runtime The next screen shot demonstrates the “File” menu The next window for “search and replace” The next screen shot demonstrates the application main window 47.52. Notepad Application 470
492.
Ring Documentation, Release1.2 Note: the functions pDebug(), pRun() and pRunNoConsole() in the previous sample are not portable! They are written in this sample for MS-Windows and we can update them for other operating systems. 47.53 The Cards Game In the next example we will see a simple Cards game developed using RingQt Each player get 5 cards, the cards are unknown to any one. each time one player click on one card to see it. if the card is identical to another card the play get point for each card. if the card value is “5” the player get points for all visible cards. Load "guilib.ring" nScale = 1 app1 = new qApp mypic = new QPixmap("cards.jpg") mypic2 = mypic.copy(0,(124*4)+1,79,124) Player1EatPic = mypic.copy(80,(124*4)+1,79,124) Player2EatPic= mypic.copy(160,(124*4)+1,79,124) aMyCards = [] aMyValues = [] for x1 = 0 to 3 for y1 = 0 to 12 temppic = mypic.copy((79*y1)+1,(124*x1)+1,79,124) aMyCards + temppic aMyValues + (y1+1) next next 47.53. The Cards Game 471
493.
Ring Documentation, Release1.2 nPlayer1Score = 0 nPlayer2Score=0 do Page1 = new Game Page1.Start() again Page1.lnewgame mypic.delete() mypic2.delete() Player1EatPic.delete() Player2EatPic.delete() for t in aMyCards t.delete() next func gui_setbtnpixmap pBtn,pPixmap pBtn { setIcon(new qicon(pPixmap.scaled(width(),height(),0,0))) setIconSize(new QSize(width(),height())) } Class Game nCardsCount = 10 win1 layout1 label1 label2 layout2 layout3 aBtns aBtns2 aCards nRole=1 aStatus = list(nCardsCount) aStatus2 = aStatus aValues aStatusValues = aStatus aStatusValues2 = aStatus Player1EatPic Player2EatPic lnewgame = false nDelayEat = 0.5 nDelayNewGame = 1 func start win1 = new qWidget() { setwindowtitle("Five") setstylesheet("background-color: White") showfullscreen() } layout1 = new qvboxlayout() label1 = new qlabel(win1) { settext("Player (1) - Score : " + nPlayer1Score) setalignment(Qt_AlignHCenter | Qt_AlignVCenter) setstylesheet("color: White; background-color: Purple; font-size:20pt") setfixedheight(200) } closebtn = new qpushbutton(win1) { settext("Close Application") setstylesheet("font-size: 18px ; color : white ; background-color: black ;") setclickevent("Page1.win1.close()") } 47.53. The Cards Game 472
494.
Ring Documentation, Release1.2 aCards = aMyCards aValues = aMyValues layout2 = new qhboxlayout() aBtns = [] for x = 1 to nCardsCount aBtns + new qpushbutton(win1) aBtns[x].setfixedwidth(79*nScale) aBtns[x].setfixedheight(124*nScale) gui_setbtnpixmap(aBtns[x],mypic2) layout2.addwidget(aBtns[x]) aBtns[x].setclickevent("Page1.Player1click("+x+")") next layout1.addwidget(label1) layout1.addlayout(layout2) label2 = new qlabel(win1) { settext("Player (2) - Score : " + nPlayer2Score) setalignment(Qt_AlignHCenter | Qt_AlignVCenter) setstylesheet("color: white; background-color: red; font-size:20pt") setfixedheight(200) } layout3 = new qhboxlayout() aBtns2 = [] for x = 1 to nCardsCount aBtns2 + new qpushbutton(win1) aBtns2[x].setfixedwidth(79*nScale) aBtns2[x].setfixedheight(124*nScale) gui_setbtnpixmap(aBtns2[x],mypic2) layout3.addwidget(aBtns2[x]) aBtns2[x].setclickevent("Page1.Player2click("+x+")") next layout1.addwidget(label2) layout1.addlayout(layout3) layout1.addwidget(closebtn) win1.setlayout(layout1) app1.exec() Func Player1Click x if nRole = 1 and aStatus[x] = 0 nPos = ((random(100)+clock())%(len(aCards)-1)) + 1 gui_setbtnpixmap(aBtns[x],aCards[nPos]) del(aCards,nPos) nRole = 2 aStatus[x] = 1 aStatusValues[x] = aValues[nPos] del(aValues,nPos) Player1Eat(x,aStatusValues[x]) checknewgame() 47.53. The Cards Game 473
495.
Ring Documentation, Release1.2 ok Func Player2Click x if nRole = 2 and aStatus2[x] = 0 nPos = ((random(100)+clock())%(len(aCards)-1)) + 1 gui_setbtnpixmap(aBtns2[x],aCards[nPos]) del(aCards,nPos) nRole = 1 aStatus2[x] = 1 aStatusValues2[x] = aValues[nPos] del(aValues,nPos) Player2Eat(x,aStatusValues2[x]) checknewgame() ok Func Player1Eat nPos,nValue app1.processEvents() delay(nDelayEat) lEat = false for x = 1 to nCardsCount if aStatus2[x] = 1 and (aStatusValues2[x] = nValue or nValue=5) aStatus2[x] = 2 gui_setbtnpixmap(aBtns2[x],Player1EatPic) lEat = True nPlayer1Score++ ok if (x != nPos) and (aStatus[x] = 1) and (aStatusValues[x] = nValue or nValue=5) aStatus[x] = 2 gui_setbtnpixmap(aBtns[x],Player1EatPic) lEat = True nPlayer1Score++ ok next if lEat nPlayer1Score++ gui_setbtnpixmap(aBtns[nPos],Player1EatPic) aStatus[nPos] = 2 label1.settext("Player (1) - Score : " + nPlayer1Score) ok Func Player2Eat nPos,nValue app1.processEvents() delay(nDelayEat) lEat = false for x = 1 to nCardsCount if aStatus[x] = 1 and (aStatusValues[x] = nValue or nValue = 5) aStatus[x] = 2 gui_setbtnpixmap(aBtns[x],Player2EatPic) lEat = True nPlayer2Score++ ok if (x != nPos) and (aStatus2[x] = 1) and 47.53. The Cards Game 474
496.
Ring Documentation, Release1.2 (aStatusValues2[x] = nValue or nValue=5 ) aStatus2[x] = 2 gui_setbtnpixmap(aBtns2[x],Player2EatPic) lEat = True nPlayer2Score++ ok next if lEat nPlayer2Score++ gui_setbtnpixmap(aBtns2[nPos],Player2EatPic) aStatus2[nPos] = 2 label2.settext("Player (2) - Score : " + nPlayer2Score) ok Func checknewgame if isnewgame() lnewgame = true if nPlayer1Score > nPlayer2Score label1.settext("Player (1) Wins!!!") ok if nPlayer2Score > nPlayer1Score label2.settext("Player (2) Wins!!!") ok app1.processEvents() delay(nDelayNewGame) win1.delete() app1.quit() ok Func isnewgame for t in aStatus if t = 0 return false ok next for t in aStatus2 if t = 0 return false ok next return true Func delay x nTime = x * 1000 oTest = new qTest oTest.qsleep(nTime) The application during the runtime 47.53. The Cards Game 475
497.
Ring Documentation, Release1.2 Note: in the previous screen shot the player get the card number ‘5’ but his score is not increased because he opened this card while no other cards are visible! The next screen shot while running the game using a Mobile (Android) 47.53. The Cards Game 476
498.
Ring Documentation, Release1.2 Note: using Qt we can run the same application on other Mobile systems 47.54 Classes and their Methods to use the default events The next table present the class name and the methods that we have to use the default events. Class Name Methods to use the default Events QPushButton SetClickEvent() QAction SetClickEvent() QLineEdit SetTextChangedEvent() SetCursorPositionChangedEvent() SetEditingFinishedEvent() SetReturnPressedEvent() SetSelectionChangedEvent() SetTextEditedEvent() QTextEdit SetCopyAvailableEvent() SetCurrentCharFormatChangedEvent() SetCursorPositionChangedEvent() SetRedoAvailableEvent() Continued on next page 47.54. Classes and their Methods to use the default events 477
499.
Ring Documentation, Release1.2 Table 47.1 – continued from previous page Class Name Methods to use the default Events SetSelectionChangedEvent() SetTextChangedEvent() SetUndoAvailableEvent() QListWidget SetCurrentItemChangedEvent() SetCurrentRowChangedEvent() SetCurrentTextChangedEvent() SetItemActivatedEvent() SetItemChangedEvent() SetItemClickedEvent() SetItemDoubleClickedEvent() SetItemEnteredEvent() SetItemPressedEvent() SetItemSelectionChangedEvent() QTreeView SetCollapseEvent() SetExpandedEvent() SetActivatedEvent() SetClickedEvent() SetDoubleClickedEvent() SetEnteredEvent() SetPressedEvent() SetViewportEnteredEvent() QTreeWidget SetCollapsedEvent() SetExpandedEvent() SetActivatedEvent() SetClickedEvent() SetDoubleClickedEvent() SetEnteredEvent() SetPressedEvent() SetViewportEnteredEvent() SetCurrentItemChangedEvent() SetItemActivatedEvent() SetItemChangedEvent() SetItemClickedEvent() SetItemCollapsedEvent() SetItemDoubleClickedEvent() SetItemEnteredEvent() SetItemExpandedEvent() SetItemPressedEvent() SetItemSelectionChangedEvent() QComboBox SetActivatedEvent() SetCurrentIndexChangedEvent() SetEditTextChangedEvent() SetHighlightedEvent() QTabWidget SetCurrentChangedEvent() SetTabCloseRequestedEvent() QTableWidget SetCellActivatedEvent() SetCellChangedEvent() SetCellClickedEvent() SetCellDoubleClickedEvent() Continued on next page 47.54. Classes and their Methods to use the default events 478
500.
Ring Documentation, Release1.2 Table 47.1 – continued from previous page Class Name Methods to use the default Events SetCellEnteredEvent() SetCellPressedEvent() SetCurrentCellChangedEvent() SetCurrentItemChangedEvent() SetItemActivatedEvent() SetItemChangedEvent() SetItemClickedEvent() SetItemDoubleClickedEvent() SetItemEnteredEvent() SetItemPressedEvent() SetItemSelectionChangedEvent() QProgressBar SetValueChangedEvent() QSpinBox SetValueChangedEvent() QSlider SetActionTriggeredEvent() SetRangeChangedEvent() SetSliderMovedEvent() SetSliderPressedEvent() SetSliderReleasedEvent() SetValueChangedEvent() QDial SetActionTriggeredEvent() SetRangeChangedEvent() SetSliderMovedEvent() SetSliderPressedEvent() SetSliderReleasedEvent() SetValueChangedEvent() QWebView SetLoadFinishedEvent() SetLoadProgressEvent() SetLoadStartedEvent() SetSelectionChangedEvent() SetTitleChangedEvent() SetUrlChangedEvent() QCheckBox SetStateChangedEvent() SetClickedEvent() SetPressedEvent() SetReleasedEvent() SetToggledEvent() QRadioButton SetClickedEvent() SetPressedEvent() SetReleasedEvent() SetToggledEvent() QButtonGroup SetButtonClickedEvent() SetButtonPressedEvent() SetButtonReleasedEvent() QVideoWidget SetBrightnessChangedEvent() SetContrastChangedEvent() SetFullScreenChangedEvent() SetHueChangedEvent() SetSaturationChangedEvent() QTimer SetTimeoutEvent() Continued on next page 47.54. Classes and their Methods to use the default events 479
501.
Ring Documentation, Release1.2 Table 47.1 – continued from previous page Class Name Methods to use the default Events QTcpServer SetAcceptErrorEvent() SetNewConnectionEvent() QIODevice SetAboutToCloseEvent() SetBytesWrittenEvent() SetReadChannelFinishedEvent() SetReadyReadEvent() QAbstractSocket SetConnectedEvent() SetDisconnectedEvent() SetErrorEvent() SetHostFoundEvent() SetProxyAuthenticationRequiredEvent() SetStateChangedEvent() QTcpSocket SetConnectedEvent() SetDisconnectedEvent() SetErrorEvent() SetHostFoundEvent() SetProxyAuthenticationRequiredEvent() SetStateChangedEvent() SetAboutToCloseEvent() SetBytesWrittenEvent() SetReadChannelFinishedEvent() SetReadyReadEvent() QColorDialog SetColorSelectedEvent() SetCurrentColorChangedEvent() QNetworkAccessManager SetFinishedEvent() QThread SetStartedEvent() SetFinishedEvent() 47.55 Methods to use Events with Events Filter RingQt define a new class called QAllEvents that help you in using Events Filter The next table presents the methods that we have Methods to get parameters Class Name getKeyCode() –> Number QAllEvents getx() –> Number gety() –> Number getglobalx() –> Number getglobaly() –> Number getbutton() –> Number getbuttons() –> Number The next table presents the methods that we have to use events. 47.55. Methods to use Events with Events Filter 480
502.
Ring Documentation, Release1.2 Method Name Class Name setKeyPressEvent(cEvent) QAllEvents setMouseButtonPressEvent(cEvent) setMouseButtonReleaseEvent(cEvent) setMouseButtonDblClickEvent(cEvent) setMouseMoveEvent(cEvent) setCloseEvent(cEvent) setContextMenuEvent(cEvent) setDragEnterEvent(cEvent) setDragLeaveEvent(cEvent) setDragMoveEvent(cEvent) setDropEvent(cEvent) setEnterEvent(cEvent) setFocusInEvent(cEvent) setFocusOutEvent(cEvent) setKeyReleaseEvent(cEvent) setLeaveEvent(cEvent) setNonClientAreaMouseButtonDblClickEvent(cEvent) setNonClientAreaMouseButtonPressEvent(cEvent) setNonClientAreaMouseButtonReleaseEvent(cEvent) setNonClientAreaMouseMoveEvent(cEvent) setMoveEvent(cEvent) setResizeEvent(cEvent) setWindowActivateEvent(cEvent) setWindowBlockedEvent(cEvent) setWindowDeactivateEvent(cEvent) setWindowStateChangeEvent(cEvent) setWindowUnblockedEvent(cEvent) 47.56 The Difference between Qt and RingQt 1. RingQt use simple methods to set the code that will be executed for events. Syntax: Set<Event_Name>Event(cEventCode) 2. RingQt change the name of some methods to avoid conflict with Ring Keywords. The next table present these little changes 47.56. The Difference between Qt and RingQt 481
503.
Ring Documentation, Release1.2 Class Name Qt Method Name RingQt Method Name QWebView load loadpage QMediaPlaylist load loadfile QMediaPlaylist next movenext QPainter end endpaint QPicture load loadfile QLineEdit end endtext QDialog done donedialog QTextDocument end enddoc QTextBlock next nextblock QSqlQuery next movenext QImage load loadimage QNetworkAccessManager get getvalue QNetworkAccessManager put putvalue QThread exit exitfromthread QRegularExpressionMatchIterator next nextitem QCamera load loadcamera 47.57 RingQt Classes and their Qt Documentation Qt Documentation : http://doc.qt.io/qt-5/classes.html See the “RingQt Classes and Methods Reference” chapter for supported classes and methods. 47.57. RingQt Classes and their Qt Documentation 482
504.
CHAPTER FORTYEIGHT BUILDING RINGQT APPLICATIONSFOR MOBILE In this chapter we will learn about Building RingQt Applications for Mobile. 48.1 Download Requirements Check the next link : http://doc.qt.io/qt-5/androidgs.html Download • The Android SDK Tools https://developer.android.com/studio/index.html • The Android NDK https://developer.android.com/ndk/index.html • Apache Ant v1.8 or later http://ant.apache.org/bindownload.cgi • Java SE Development Kit (JDK) v6 or later http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260.html 48.2 Update the Android SDK Update the Android SDK to get the API and tools packages required for development 48.3 Install Qt for Android • You can install Qt for Android from the next link https://download.qt.io/archive/qt/5.5/5.5.1/ • Run Qt Creator, Select Tools > Options > Android to add the Android NDK and SDK paths. http://doc.qt.io/qtcreator/creator-developing-android.html • Using Qt Creator Open the project Folder : ring/android/ringqt/project Project file : project.pro 483
505.
Ring Documentation, Release1.2 • You will find the code in resourcestest.ring You can modify the code then build and run for Desktop or Mobile. 48.4 Comments about developing for Android using RingQt 1. The main project file is main.cpp This file load Ring Compiler/Virtual Machine and RingQt Then copy files during the runtime from the resources to temp. folder Then run the test.ring Through main.cpp you can extract more files from the resources to temp. folder once you add them (create projects with many files). 2. The next functions are missing from this Ring edition • Database (ODBC, SQLite & MySQL) • Security and Internet functions (LibCurl & OpenSSL) • RingAllegro (Allegro Library) • RingLibSDL (LibSDL Library) Just use Qt Classes through RingQt. For database access use the QSqlDatabase Class Note: All of the missing libraries ((LibCurl, OpenSSL & Allegro) can be compiled for Android, but they are not included in this Qt project. 3. use if isandroid() when you want to modify the code just for android 48.4. Comments about developing for Android using RingQt 484
506.
Ring Documentation, Release1.2 Example: if isandroid() // Android code else // other platforms ok (4) Sometimes you will find that the button text/image is repeated in drawing ! it’s Qt problem that you can avoid using the next code. if isandroid() setStyleSheet(" border-style: outset; border-width: 2px; border-radius: 4px; border-color: black; padding: 6px;") ok 5. Always use Layouts instead of manual setting of controls position and size. This is the best way to get the expected user interface to avoid problems like (controls with small/extra size) 6. When you deal with Qt Classes you can determine the images from resources (you don’t need to copy them using main.cpp) Example: if isandroid() mypic = new QPixmap(":/resources/cardsimage") else mypic = new QPixmap("cards.jpg") ok In the previous example, cards.jpg is added to the resources then we write the “cardsimage” as alias for “cards.jpg” 48.4. Comments about developing for Android using RingQt 485
507.
CHAPTER FORTYNINE OBJECTS LIBRARY FORRINGQT APPLICATION In this chapter we will learn about the objects library for RingQt applications. Ring 1.2 comes with the Objects library for RingQt applications. Instead of using global variables for windows objects and connecting events to objects using the object name, the Objects Library will manage the GUI objects and will provide a more natural API to quickly create one or many windows from the same class and the library provide a way to quickly set methods to be executed when an event is fired. Also the library provide a natural interface to quickly use the parent or the caller windows from the child or sub windows. The Objects Library is designed to be used with the MVC Design Pattern. The Objects Library is merged in RingQt so you can use it directly when you use RingQt 49.1 Library Usage • Use the Open_Window(cWindowControllerClassName) function to open new Windows • Create at least Two Classes for each window, The Controller Class and the View Class • Create each controller class from the WindowsControllerParent Class • Create each view class from the WindowsViewParent Class • Use the Last_Window() function to get the object of the last window created (The Controller object). • When you call a sub window, use the SetParentObject() method and pass the self object. • In the View Class, To determine the event method use the Method(cMethodName) function. • The Method(cMethodName) function determine the method in the controller class that will be executed. • Each controller class contains by default the CloseAction() method that you can call to close the window. • You don’t need to call the Show() Method for each window, When you use Open_Window() It will be called. • In the view class, Define the GUI window object as an attribute called win. 49.2 Example In the next example we will create two types of windows. • Main Window contains a button. When the user click on the button a sub window will be opened. • The User Can click on the button many times to open many sub windows. • Each Sub Window contains Two buttons. 486
508.
Ring Documentation, Release1.2 • The first button in the sub window change the Main and the Sub Windows Titles. • The second button in the sub window close the Sub Window. load "guilib.ring" new qApp { open_window( :MainWindowController ) exec() } class MainWindowController from WindowsControllerParent oView = new MainWindowView func SubWindowAction Open_window( :SubWindowController ) Last_Window().SetParentObject(self) class MainWindowView from WindowsViewParent win = new qWidget() { SetWindowTitle("Main Window") btnSub = new qPushButton(win) { setText("Sub Window") setClickEvent( Method( :SubWindowAction ) ) } resize(400,400) } class SubWindowController from WindowsControllerParent oView = new SubWindowView func SetMainWindowTitleAction Parent().oView.win.SetWindowTitle("Message from the Sub Window") oView.win.SetWindowTitle("Click Event Done!") class SubWindowView from WindowsViewParent win = new qWidget() { SetWindowTitle("Sub Window") btnMsg = new qPushButton(win) { setText("Set Main Window Title") setClickEvent( Method( :SetMainWindowTitleAction ) ) } btnClose = new qPushButton(win) { Move(200,0) setText("Close") setClickEvent( Method( :CloseAction ) ) } resize(400,400) } The next screen shot after creating three sub windows. 49.2. Example 487
509.
Ring Documentation, Release1.2 The next screen shot after clicking on the button in each sub window. 49.2. Example 488
510.
Ring Documentation, Release1.2 49.3 Objects Library Source Code The library source code is very simple, You can check the source code files • https://github.com/ring-lang/ring/blob/master/extensions/ringqt/objectslib/objects.ring • https://github.com/ring-lang/ring/blob/master/extensions/ringqt/objectslib/subwindows.ring # List of objects (Windows/Forms) $RingQt_ObjectsList = [] # Contains sub lists [object ID , Object] # The Object ID Counter $RingQt_ObjectID = 0 # Variable used for Windows/Forms object name - used for setting events $RingQt_ObjName = "" # The next constants for the Objects List C_RINGQT_OBJECTSLIST_ID = 1 49.3. Objects Library Source Code 489
511.
Ring Documentation, Release1.2 C_RINGQT_OBJECTSLIST_OBJECT = 2 /* The next function create new object, add the object to the $RingQt_ObjectsList Then set $RingQt_ObjName to the object in the $RingQt_ObjectsList Then call the start() method */ func Open_Window cClass $RingQt_ObjectID++ $RingQt_ObjectsList + [$RingQt_ObjectID,""] $RingQt_ObjName = "$RingQt_ObjectsList[Get_Window_Pos("+$RingQt_ObjectID+")]" + "[C_RINGQT_OBJECTSLIST_OBJECT]" cCode = $RingQt_ObjName + " = new " + cClass + nl + $RingQt_ObjName + ".start()" eval(cCode) /* The next function return the last window created */ func Last_Window return $RingQt_ObjectsList[len($RingQt_ObjectsList)][C_RINGQT_OBJECTSLIST_OBJECT] /* The next function for using in GUI controls events */ func Method cMethod cMethod = Trim(cMethod) if right(cMethod,1) != ")" { cMethod += "()" } return $RingQt_objname+"."+cMethod /* The next function get the Window ID Then search in the Objects List to find the Window Item Position */ func Get_Window_Pos nID return find($RingQt_ObjectsList,nID,C_RINGQT_OBJECTSLIST_ID) /* The next class is the parent class for Windows/Forms Classes When you create a new class, just use from WindowsBase When you close the window just use Super.Close() */ class WindowsControllerBase nID = $RingQt_ObjectID func Close nPos = Get_Window_Pos(nID) del($RingQt_ObjectsList,nPos) func ObjectID 49.3. Objects Library Source Code 490
512.
Ring Documentation, Release1.2 return nID func GetObjectByID nID return $RingQt_ObjectsList[nID][C_RINGQT_OBJECTSLIST_OBJECT] class WindowsControllerParent from WindowsControllerBase nParentID # Goal Designer Object ID func Start oView.win.Show() func setParentObject oParent nParentID = oParent.ObjectID() func Parent return GetObjectByID(nParentID) func CloseAction oView.Close() Super.Close() class WindowsViewParent func Close win.close() 49.3. Objects Library Source Code 491
513.
CHAPTER FIFTY SCOPE RULES FORVARIABLES AND ATTRIBUTES In this chapter we will learn about scope rules and how Ring find variables. Also we will learn about conflicts and how to solve/avoid them. The next information are important once you start developing large applications using Ring These application may uses • Global variables (Try to avoid them) • Classes (Object-Oriented) • braces { } to access objects • Declarative Programming • Natural Programming 50.1 Three Scopes In Ring we have three scopes :- 1. Public/Global Scope - Each variable you define in the statements part (before functions and classes) 2. Object Scope - When you are inside an object (Inside class method or using { } to access the object ) 3. Local Scope - Related to functions and methods 50.2 Defining Variables and Variables Access 1. Ring uses lexical scoping, i.e. the scope of the variable is based on where we defined the variable. 2. Inside braces { } when you access an object, You will change the current active object scope to this object scope but you still can access the global scope and the local scope. 3. After the ‘Class’ keyword and the class name, when you write variable names to be defined as attributes, You still can access the global scope. In this region (class region - after the class name and before methods) we have • Global Scope —-> The Global Scope • Object Scope —-> The Object Scope • Local Scope —-> The Object Scope 492
514.
Ring Documentation, Release1.2 Note: Since the local scope in the class region point also to the object scope in this region, we can use nested braces and still have access to the object scope of the class through the local scope. Tip: You can create windows and controls as attibutes by defining them in this region. Tip: In the class region if you created objects and used braces {} to access them then using self.attribute inside braces will use the class (not the object that you access) because you have access to the class through the local scope. 4. Function Parameters are automatically defined in the local scope. 50.3 How Ring find the variable? 1 - Search First in the Local Scope if not found ! 2 - Search in the Object Scope if not found ! 3 - Search in the public scope if not found —-> Runtime Error if found —-> Check if we can do optimization to avoid searching next time (Cache / Pointers for performance). 50.4 Using Object.Attribute When we use object.attribute the search will be in the object attributes only. I.e. no search will be done in the local scope or in the global scope for the object attribute. Note: Using self.attribute will search for the first self before searching for attributes. 50.5 The Self Object The self object is a reference to the current object that we can use from the class methods. When we are inside class method and use Self we mean the object that will be created from this class. Inside the class methods if we used Braces { } this will change the current object scope and self will be changed also inside braces to reference the object that we access using Braces. Inside the Class Region (after the class name and before any method) we have access to the object through the object scope and the local scope also. In this region using Self will always be a reference to the class object. if we used Braces to change the object scope then used Self inside Braces, Also self will be a reference to the class object (not the object that we already access using braces) because in the class region we have :- • Global Scope —> Global Scope • Object Scope —> Object Scope 50.3. How Ring find the variable? 493
515.
Ring Documentation, Release1.2 • Local Scope —> Object Scope And using Braces changes the object scope only (not the local scope) and when Ring search for variables it will search in the Local Scope first so it will find self in the class that we are inside. 50.6 How Ring Define Variables and Attributes Ring will use the variable name in the Assignment operation 1 - Search using the variable name 2 - If not found —> Avoid the runtime error and define the variable in the current scope 3 - If found —> Use the variable and don’t define anything in the current scope • In the global region (before any function or class) the current scope is the global scope. • In the class region (after the class name and before any method) the current scope is the object attributes. • In Functions and methods the current scope is the local scope. 50.7 Conflict between Global Variables and Class Attributes Look at this example: name = "test" o1 = new person see o1 class person name address phone In the previous example we have a global variable called ‘name’ inside the class person. when we use the variable ‘name’, Ring will start the search operation and will try to find it. if found —> Use it if not found —> Define new attribute But the variable name is a global variable, so it will be found and used! We will not have the attribute name! added to the object. Solution (1) - Use the Main Function func main name = "test" o1 = new person see o1 class person name address phone Solution (2) - Use special mark for global variable names like $ 50.6. How Ring Define Variables and Attributes 494
516.
Ring Documentation, Release1.2 $name = "test" o1 = new person see o1 class person name address phone Solution (3) - Use the AddAttribute() Method name = "test" o1 = new person see o1 class person AddAttribute(self,"name") address phone Solution (4) - Use self before the attribute name name = "test" o1 = new person see o1 class person self.name address phone So what is the best solution to this conflict? 1 - Use the $ Mark for global variables 2 - Optional : Try to avoid global variables and use the Main function In practice i do both of them. The other solution • Use self before the attribute name or use AddAttribute() 50.8 Conflict between Class Attributes and Local Variables This conflict may happen when we access the object using braces Example: func main name = "nice" o1 = new person {name="mahmoud" address="Egypt" phone = 000 } see o1 class person name address phone 50.8. Conflict between Class Attributes and Local Variables 495
517.
Ring Documentation, Release1.2 In the previous example we have the local variable name. The value of this variable will be set to “mahmoud” instead of the object attribute. Solution (1) : Just use Self func main name = "nice" o1 = new person {self.name="mahmoud" address="Egypt" phone = 000 } see o1 class person name address phone Solution (2) : Change the Local variable name func main cName = "nice" o1 = new person {name="mahmoud" address="Egypt" phone = 000 } see o1 class person name address phone Solution (3) : Change Braces and use the Dot operator func main name = "nice" o1 = new person o1.name ="mahmoud" o1.address ="Egypt" o1.phone = 000 see o1 class person name address phone 50.9 Using Braces to access objects inside Class Methods Remember that we have Three scopes (Local Scope, Object Scope and Global Scope) and when we are inside a class method, we expect that we have access to the object attributes and methods and this is true until we use braces to access another object attributes and methods because in this case our object scope will be switched to another object. new point { test() } class point x=10 y=20 func test see x + nl + y + nl # works fine myobj = new otherclass { see name + nl see x + nl + y + nl # error ! 50.9. Using Braces to access objects inside Class Methods 496
518.
Ring Documentation, Release1.2 } class otherclass name = "test" Output: 10 20 test Line 8 Error (R24) : Using uninitialized variable : x In method test() in file methodbraceerror.ring called from line 5 in file methodbraceerror.ring Now what we will do to solve the previous problem? Solution (1) : Write the code that access the class attributes outside braces. new point { test() } class point x=10 y=20 func test see x + nl + y + nl # works fine myobj = new otherclass { see name + nl } see x + nl + y + nl # Outside braces - works fine class otherclass name = "test" Output: 10 20 test 10 20 Solution (2) : Don’t Use Braces new point { test() } class point x=10 y=20 func test see x + nl + y + nl myobj = new otherclass see myobj.name see x + nl + y + nl class otherclass name = "test" Solution (3) : Copy the self object We may use this solution if we want to use braces and get access to the class attributes (Just Reading). 50.9. Using Braces to access objects inside Class Methods 497
519.
Ring Documentation, Release1.2 new point { test() } class point x=10 y=20 func test oSelf = self see x + nl + y + nl myobj = new otherclass { see name + nl see oself.x + nl + oself.y + nl } class otherclass name = "test" Output: 10 20 test 10 20 Now look at this line oself = self The problem with the previous line is that we will have a new copy from the object Because in Ring the assignment operator copy lists and objects by value (not by reference). When we access the new object attributes (reading) we don’t have problems But if we modified the object attributes (Then we will modify the copy!). Note: We can use braces again with the copy new point { test() } class point x=10 y=20 func test oSelf = self see x + nl + y + nl myobj = new otherclass { see name + nl oSelf { see x + nl + y + nl } } class otherclass name = "test" In a GUI application, we may create a class contains the window objects as attributes to be able to access the controls from different methods. Remember the previous information when you try to access objects using braces inside methods because in this case you can’t access the object attributes directly and if you copied the self object you will work on a copy and the new controls that you create will be related to the copy and you can’t access them. 50.9. Using Braces to access objects inside Class Methods 498
520.
Ring Documentation, Release1.2 50.10 Accessing the class attributes from braces inside class meth- ods We access the class attributes directly from the class methods, also we have the choice to use the Self reference before the attribute/method name. Using Braces {} inside class method change the active object scope and prevent us from getting direct access to the class attributes. Also using Self will not help because the Self reference will be changed to the object that we access using Braces. In this case if you want to read an attribute you have to copy the Self object before using Braces and if you want to modify an attribute you have to the copy from local variable to the object attribute after using Braces. This case happens when you want to read/modify attribute insead braces. Class MyApp oCon # Attribute # some code here Func OpenDatabase # some code here new QSqlDatabase() { oCon = addDatabase("QSQLITE") { setDatabaseName("weighthistory.db") open() } } self.oCon = oCon # some code here In the previous example we want to create the connection object and save it inside the oCon attribute. The object is an output from the addDatabase() method that we use after accessing the QSQLDatabase() object. Inside braces we can’t use the Self reference to use the object created from the MyApp class, Because the Self reference here will be to the object that we access using Braces. We solved the problem in the previous example by creating a local variable called oCon then after Braces we copied that variable to the oCon attribute. The next code is another solution. Class MyApp oCon # Attribute # some code here Func OpenDatabase # some code here oCon = new QSqlDatabase() oCon = oCon.addDatabase("QSQLITE") { setDatabaseName("weighthistory.db") Open() } # some code here The next code is a better solution. 50.10. Accessing the class attributes from braces inside class methods 499
521.
Ring Documentation, Release1.2 Class MyApp oCon # Attribute # some code here Func OpenDatabase # some code here new QSqlDatabase() { this.oCon = addDatabase("QSQLITE") { setDatabaseName("weighthistory.db") Open() } } # some code here Note: We used this.attribute to access the class attribute (oCon) while we are inside Braces. 50.11 Creating a Class for each Window in GUI applications A good way for creating classes for windows is to define the window directly after the class name In this area you can use nested braces without problems to define the window and the controls, and they will be attributes that you can access from methods. Example: Load "guilib.ring" new qApp { $ObjectName = "oFirstWindow" oFirstWindow = new FirstWindow $ObjectName = "oSecondWindow" oSecondWindow = new SecondWindow exec() } Class FirstWindow win = new qWidget() { setgeometry(0,50,300,200) setWindowTitle("First Window") label1 = new qLabel(win) { setgeometry(10,10,300,30) setText("0") } btn1 = new qPushButton(win) { move(100,100) setText("Increment") setClickEvent($ObjectName+".increment()") } 50.11. Creating a Class for each Window in GUI applications 500
522.
Ring Documentation, Release1.2 show() } Func Increment label1 { setText( "" + ( 0 + text() + 1 ) ) } Class SecondWindow win = new qWidget() { setgeometry(400,50,300,200) setWindowTitle("Second Window") label1 = new qLabel(win) { setgeometry(10,10,300,30) setText("0") } btn1 = new qPushButton(win) { move(100,100) setText("Decrement") setClickEvent($ObjectName+".decrement()") } show() } Func Decrement label1 { setText( "" + ( 0 + text() - 1 ) ) } 50.12 Conflict between self inside braces and self in the class region In the class region (after the class name and before any methods) we define the attributes. In this region we have access to the global scope and the local scope will point to the object scope. Three Scopes • Global Scope —> Gloabl Scope • Object Scope —> Object Scope • Local Scope —> Object Scope Look at this example New Account { see aFriends } Class Account name = "Mahmoud" aFriends = [] aFriends + new Friend { name = "Gal" 50.12. Conflict between self inside braces and self in the class region 501
523.
Ring Documentation, Release1.2 } aFriends + new Friend { name = "Bert" } Class Friend name Output: name: NULL name: NULL The problem in the previous example is that the Class account contains an attribute called “name” and the Friend class contains an attribue called “name” also. If you tried using self.name inside braces you will get the same result! New Account { see aFriends } Class Account name = "Mahmoud" aFriends = [] aFriends + new Friend { self.name = "Gal" } aFriends + new Friend { self.name = "Bert" } Class Friend name So why using self.name inside braces doesn’t solve this conflict? Because after the class region we have • global scope —> global scope • object scope —> object scope (Account Class) • local scope —> local scope (Account Class) When we use braces we change the object scope, so we have • global scope —> global scope • object scope —> object scope (Friend Class) • local scope —> local scope (Account Class) Ring search in the local scope first, so using self.name will use the Account class. There are many solution Solution (1) : Access the object through the list New Account { see aFriends } Class Account 50.12. Conflict between self inside braces and self in the class region 502
524.
Ring Documentation, Release1.2 name = "Mahmoud" aFriends = [] aFriends + new Friend aFriends[len(aFriends)] { aFriends[len(aFriends)].name = "Gal" } aFriends + new Friend aFriends[len(aFriends)] { aFriends[len(aFriends)].name = "Bert" } Class Friend name Solution (2) : Create Method in the friend class to set the name attribute. New Account { see aFriends } Class Account name = "Mahmoud" aFriends = [] aFriends + new Friend { setname("Gal") } aFriends + new Friend { setname("Bert") } Class Friend name func setname cName name = cName Solution (3) : Create a method in the account class to set the attribute New Account { see aFriends } Class Account name = "Mahmoud" aFriends = [] friend("Gal") friend("Bert") func friend cName aFriends + new Friend { name = cName } Class Friend name Solution (4) : Declarative Programming New Account { name = "mahmoud" friend { 50.12. Conflict between self inside braces and self in the class region 503
525.
Ring Documentation, Release1.2 name = "Gal" } friend { name = "Bert" } see aFriends } Class Account name aFriends = [] friend func getfriend aFriends + new Friend return aFriends[len(aFriends)] Class Friend name Output: name: Gal name: Bert 50.13 Using braces to escape from the current object scope Since braces change the current object scope to another object. we can use it to do some work without modifying the class attributes and using the same variable names. new point {x=10 y=20 z=30 start() } class point x y z func start see self # print the x y z values (10,20,30) new Local { x = 100 y = 200 z = 300 } see self # print the x y z values (10,20,30) see x + nl # will print 100 see y + nl # will print 200 see z + nl # will print 300 Self { # NO Advantage - Search is done in local scope first see x + nl # will print 100 see y + nl # will print 200 see z + nl # will print 300 } see self.x + nl # will print 10 see self.y + nl # will print 20 see self.z + nl # will print 30 class Local Output: x: 10.000000 y: 20.000000 50.13. Using braces to escape from the current object scope 504
526.
Ring Documentation, Release1.2 z: 30.000000 x: 10.000000 y: 20.000000 z: 30.000000 100 200 300 100 200 300 10 20 30 50.14 Summary of Scope Rules At first remember that 1 - Each programming language comes with it’s scope rules based on the language goals 2 - Programming in the small is different than Programming in the Large 3 - Some programming language are designed for developing small programs while others are designed for large programs 4 - In programming, If we have access to more than one scope - Then problems may come if we don’t manage things correctly 5 - It’s always more secure to reduce the number of visible scopes 6 - Some programming languages force you to manage the scope in some way, while others not! In Ring 1 - Special and very simple scope rules that are designed for Flexibility first then Security 2 - Ring is designed to support programming in the small and programming in the large. 3 - The language provide the different programming paradigms that you may select from based on the project size. Errors comes only if you selected a bad paradigm for the target project or you are using the paradigm in a way that is not correct or at least not common. 4 - In Ring you have the choice, you can use global variables or avoid them. you can give them a special $ mark or leave them. you can use object-oriented or stay with procedures. you can use the class region (after the class name and before any method) just for attributes or use it for code too. 5 - Just read the next scope rules and think about them then use them in your favorite way. Scope Rules: 1 - At any place in our program code we have only at maximum Three Scopes (Local Scope, Object Scope and Global Scope). 2 - When Ring find a variable it will search in the local scope first then in the object scope then in the global scope. 3 - At any time inside procedures or methods you can use braces { } to access an object and change the current object scope. 4 - In the class region (After the class name and before any method) this is a special region where both of the object scope and the local scope point to the object scope. I.e. No local variables where each variable you define in this region will become an attribute. 50.14. Summary of Scope Rules 505
527.
Ring Documentation, Release1.2 5 - Before defining any variable (in any scope and in the class region too) a search process will be done to use the variable if it’s found. 6 - Functions and Methods parameters are defined automatically as local variables to these functions or methods. 7 - Using Object.Attribute will search in the object attributes only. 8 - Using Self.Attribute will lead to a search for Self first then search in Self Attributes. 9 - The Self reference inside class region (after the class name and before any method) always point to the object scope created from the class. 10- The Self reference inside methods will be changed when we uses Braces to be a reference to the object that we access. 11- Writing variable names directly in the class region (after the class name and before any method) means using them or define then (in order). 12- Using self.attribute in the class region reduce search to the object scope (avoid conflict with global scope). From these rules you can understand all types of conflicts and why you may have them and how to avoid them Simple advices to avoid any conflict and use the scope rules in a better way 1 - Try to avoid global variables 2 - Use the Main Function - This will help you to avoid global variables 3 - If you are going to use many global variables use the $ mark before the variable name 4 - In the class region if you don’t respect the advice number three ($) then use self.attribute when you define your attributes 5 - You can use object.attribute and object.method() instead of object { attribute } and object { method() } if you don’t like changing the object scope. 6 - If you will use nested braces in a class - think about using the class region if possible because in this region you will have access to the object that you access using { } + access to the class attributes 7 - If you are inside a class method and used nested braces you will change the object scope with each brace and you will loss the access to the class attributes directly but you have access to the local scope before and after using brace { } , if you will read/modify the class attribute from braces then use This.Attribute because using ‘This’ means (The object created from this class) while using ‘Self’ means (The object in the current object scope). After understanding all of the previous points, You will master this topic. 50.14. Summary of Scope Rules 506
528.
CHAPTER FIFTYONE SCOPE RULES FORFUNCTIONS AND METHODS In this chapter we will learn about the scope rules for functions and methods. You need to know the next information once you started using Ring for large applications. These applications may contains and use • Many Packages and Classes written in Ring • Many Functions written in Ring • Standard Ring Functions (Written in C language) • Functions and Classes written in C/C++ languages 51.1 How Ring find the Functions and Methods? When you call a method or function, Ring will start a search process to find this function If found –> Call the function and store the function pointer in the cache so Ring can use it again with doing another search. If not found —> Runtime error message (That you can avoid using Try/Catch) How the search process is done? Search for functions/methods follow the next order 1 - Search in methods (if we are inside class method or object using braces {}) 2 - Search in functions written by the programmer using Ring Code 3 - Search in functions written in C/C++ like standard Ring functions This enable us to write clean code inside classes methods and avoid any conflict with functions. If we want to call a function with the same name as a method in the class we will need a wrapper function or we will access a temp. object using { } then call that function there. We can replace C/C++ Functions with Ring Functions. We can replace Ring Functions with Ring Methods. Note: Using self.method() is not necessary in any use case. Tip: We can use this.method() to escape from the current active scope that we access using braces {} and call a method in the class that we are inside. 507
529.
Ring Documentation, Release1.2 51.2 Example about Sharing Names between Functions and Methods Look at the next example func main o1 = new myclass { test() test2() } test2() func f1 see "f1 function" + nl func f2 see "f2 function" + nl func f3 see "f3 function" + nl func test2 myline() see "test2 function" + nl new myclass { f1() f2() f3() self.f3() } myobj = new myclass myobj.f3() myline() func myline see copy("=",40) + nl Class myclass func test myline() see "test method" + nl f1() f2() f3() myline() func f3 see "f3 method" + nl func test2 myline() see "test2 method" + nl self { f1() f2() f3() } myline() Output: 51.2. Example about Sharing Names between Functions and Methods 508
530.
Ring Documentation, Release1.2 ======================================== test method f1 function f2 function f3 method ======================================== ======================================== test2 method f1 function f2 function f3 method ======================================== ======================================== test2 function f1 function f2 function f3 method f3 method f3 method ======================================== 51.3 Calling a function sharing the name with a method in the current class In the previous example we have a function called f3() and we have a method called f3() How we can call the f3() function from the test() method ? Solution (1) : Change the current object scope to another object scope In this solution we will have an empty class called local that we will use to change the current object scope. func main o1 = new myclass { test()} func f1 see "f1 function" + nl func f2 see "f2 function" + nl func f3 see "f3 function" + nl func myline see copy("=",40) + nl Class myclass func test myline() see "test method" + nl f1() f2() f3() # call f3() method new local { f3() } # call f3() function myline() 51.3. Calling a function sharing the name with a method in the current class 509
531.
Ring Documentation, Release1.2 func f3 see "f3 method" + nl class local Output: ======================================== test method f1 function f2 function f3 method f3 function ======================================== 51.3. Calling a function sharing the name with a method in the current class 510
532.
CHAPTER FIFTYTWO SYNTAX FLEXIBILITY In thischapter we will learn about some options that are provided automatically by the Ring compiler for syntax flexibility. 52.1 Change Language Keywords We can change any keyword using the ChangeRingKeyword command. Note: Remember to restore the keyword again if the team will mix between styles in the same project. Tip: The ChangeRingKeyword command is executed in the scanner stage by the compiler (before parsing). Syntax: ChangeRingKeyword <oldkeyword> <newkeyword> Example: ChangeRingKeyword see print print "welcome" + nl ChangeRingKeyword print see see "Welcome" + nl Example: ChangeRingKeyword func function ChangeRingKeyword see print ChangeRingKeyword ok endif ChangeRingKeyword next endfor ChangeRingKeyword end endwhile x = 10 while x > 0 print "x = " + x + nl for t = 1 to 10 if t = 3 print "number three" + nl endif endfor 511
533.
Ring Documentation, Release1.2 x-- endwhile test() function test print "message from test" + nl ChangeRingKeyword function func ChangeRingKeyword print see ChangeRingKeyword endif ok ChangeRingKeyword endfor next ChangeRingKeyword endwhile end 52.2 Change Language Operators We can change any operator using the ChangeRingOperator command. Note: Remember to restore the operator again if the team will mix between styles in the same project. Tip: The ChangeRingOperartor command is executed in the scanner stage by the compiler (before parsing). Syntax: ChangeRingOperator <oldkeyword> <newkeyword> Example: The next program hide the + operator by changing it to _+ changeringoperator + _+ changeringkeyword SEE PRINT try print 5 + 10 catch print nl print "error" print nl done changeringoperator _+ + The next program change the + operator to “plus”. changeringoperator + plus changeringkeyword SEE PRINT Print 5 plus 5 changeringoperator plus + changeringkeyword PRINT SEE 52.2. Change Language Operators 512
534.
Ring Documentation, Release1.2 52.3 Load Syntax Files You may store a group of ChangeRingKeyword and ChangeRingOperator commands in a file to use later in many source files. You can’t use the Load command to call these files because • ChangeRingKeyword and ChangeRingOperator commands are executed in the scanner phase by the compiler (before parsing). • The load command is executed in the parsing phase (after the scanner phase). Solution: Use the LoadSyntax Command which is executed in the scanner phase. Syntax: LoadSyntax "syntaxfile.ring" Example: File : StyleBasicOn.ring ChangeRingKeyword see print ChangeRingKeyword ok endif ChangeRingKeyword next endfor ChangeRingKeyword end endwhile File : StyleBasicOff.ring ChangeRingKeyword print see ChangeRingKeyword endif ok ChangeRingKeyword endfor next ChangeRingKeyword endwhile end File : UseStyleBasic.ring LoadSyntax "stylebasicon.ring" x = 10 while x > 0 print "x = " + x + nl for t = 1 to 10 if t = 3 print "number three" + nl endif endfor x-- endwhile LoadSyntax "stylebasicoff.ring" see "done" + nl Note: files called by the LoadSyntax command must contains ChangeRingKeyword and ChangeRingOperator com- mands only. Tip: files called by the LoadSyntax command doesn’t support functions, packages and classes. just imperative commands only. Note: Using this feature you can create many styles that you can use in the same project and you can support Ring 52.3. Load Syntax Files 513
535.
Ring Documentation, Release1.2 translation to other languages like Arabic, French and so on. 52.4 Using “()” around the function parameters We can use () around the function parameters (optional). Example: hello() sum(3,4) func hello() see "Hello" + nl func sum(x,y) see x+y+nl Output: Hello 7 Example: myfunc = func x,y { see x + y + nl } call myfunc (3,4) myfunc2 = func (x,y) { see x+y+nl } call myfunc(3,4) Output: 7 7 52.5 Using Semi-colon after and between statements In Ring we can use semi-colon after and between statements (optional). Example: # Using semi-colon is optional see "Hello" + nl ; see "How are you?" + nl ; see "Welcome to Ring" + nl ; one() ; two() ; three() ; func one ; see "one" + nl ; func two ; see "two" + nl ; func three ; see "three" + nl ; Output: Hello How are you? Welcome to Ring 52.4. Using “()” around the function parameters 514
536.
Ring Documentation, Release1.2 one two three 52.6 Using $ and @ in the start of the variable name You can use any unicode character in the variable name also we can use $ and @ in the name. This feature may help, for example we can start global variables with $ and the object attributes with @. In other languages like Ruby this is the rule, In the Ring language this is just an option without any force from the Compiler. example: $global_variable = 5 new test { hello() } class test @instance_variable = 10 func hello local_variable = 15 see "Global : " + $global_variable + nl + "Instance : " + @instance_variable + nl + "Local : " + local_variable + nl Output: Global : 5 Instance : 10 Local : 15 52.7 Using the ‘elseif’ keyword as ‘but’ in if statement if you don’t like the ‘but’ keyword in if statement Then you can use the ‘elseif’ keyword. Example: give x if x = 1 see "one" elseif x=2 see "two" elseif x=3 see "three" elseif x=4 see "four" else see "other" ok see nl 52.6. Using $ and @ in the start of the variable name 515
537.
Ring Documentation, Release1.2 52.8 Using the ‘else’ keyword as ‘other’ in switch statement if you don’t like the ‘other’ keyword in switch statement Then you can use the ‘else’ keyword. Also you can replace ‘else’ with ‘other’ in if statement. i.e. ‘other’ keyword is the same as ‘else’ keyword. Example: x = 1 switch x on 10 see "10" + nl else see "not 10" + nl end Output: not 10 52.9 Using the ‘end’ keyword in different control structures We can use the ‘end’ keyword to close different control structures • If statement • For loop • Switch • While • Try-Catch Example: see "if statement.." + nl x = 1 if x = 1 see "one" + nl elseif x=2 see "two" + nl elseif x=3 see "three" + nl end see "for loop.." + nl for t = 1 to 10 see t end see nl see "switch..." + nl x = 1 switch x on 1 see "one" + nl on 2 see "two" + nl end 52.8. Using the ‘else’ keyword as ‘other’ in switch statement 516
538.
Ring Documentation, Release1.2 see "try catch..." + nl try x = 1 / 0 catch see "catching error" + nl end Output: if statement.. one for loop.. 12345678910 switch... one try catch... catching error 52.10 Using braces to start and end different control structures We can use braces { } to start and end different control structures • If statement • For loop • Switch • While • Try-Catch Example: see "if statement.." + nl x = 1 if x = 1 { see "one" + nl elseif x=2 see "two" + nl elseif x=3 see "three" + nl } see "for loop.." + nl for t = 1 to 10 { see t } see nl see "switch..." + nl x = 1 switch x { on 1 see "one" + nl on 2 see "two" + nl } see "try catch..." + nl try { 52.10. Using braces to start and end different control structures 517
539.
Ring Documentation, Release1.2 x = 1 / 0 catch see "catching error" + nl } Output: if statement.. one for loop.. 12345678910 switch... one try catch... catching error 52.11 Using ‘put’ and ‘get’ as ‘see’ and ‘give’ We can replace the ‘see’ keyword with the ‘put’ keyword. Also we can replacew the ‘give’ keyword with the ‘get’ keyword. Example: put "Hello World" + nl put "Enter Your Name ? " Get Name Put "Hello " + Name 52.12 Using ‘case’ as ‘on’ in switch statements We can replace the ‘on’ keyword with ‘case’ keyword in the switch statement. Example (1) : for x=1 to 10 switch x case 1 put "one" + nl case 2 put "two" + nl case 3 put "thre" + nl else put "else" + nl end end Example (2) : for x=1 to 10 { switch x { case 1 put "one" + nl case 2 put "two" + nl case 3 put "thre" + nl else put "else" + nl } } 52.11. Using ‘put’ and ‘get’ as ‘see’ and ‘give’ 518
540.
Ring Documentation, Release1.2 52.13 Using ‘def’ as ‘func’ in functions/methods definition We can use the ‘def’ keyword as the ‘func’ keyword to define functions and methods. Example: one() two() def one put "one" + nl def two put "two" + nl 52.13. Using ‘def’ as ‘func’ in functions/methods definition 519
541.
CHAPTER FIFTYTHREE DISTRIBUTING RING APPLICATIONS Inthis chapter we will learn about distributing Ring applications. 53.1 Distributing Applications for Microsoft Windows Step 1: Copy c:ringbin folder to be for example c:myapp Step 2: Rename c:myappring.exe to c:myappmyapp.exe Step 3: Create a file c:myappring.ring And write Load "myapp.ring" When you run myapp.exe the file ring.ring will be executed automatically So your file myapp.ring will be called and executed Or just rename myapp.ring to ring.ring It’s a fast way to distribute applications. 53.2 Protecting the Source Code Step 1: Execute the next command ring myapp.ring -go This will generate one object file (myapp.ringo) from the project files (*.ring) Step 2: Rename myapp.ringo to ring.ringo When you run the executable file (ring.exe) or (myapp.exe) the file ring.ringo will be executed. 520
542.
Ring Documentation, Release1.2 53.3 Creating Windows Installer There are many tools that you can use to distribute your application. Check : nullsoft scriptable install system URL : http://nsis.sourceforge.net/Main_Page 53.4 Using C/C++ Compiler and Linker Another method to distribute applications is to use a C/C++ compiler. Ring can be embedded in C/C++ projects, We can create executable files using a C/C++ compiler by embedding the Ring language in our project. Check the “Embedding Ring Language in C/C++ Programs” chapter. Using this way we will avoid using ring.ring or ring.ringo files. 53.5 Distributing Applications and Games for Mobile Ring can be embedded in a Qt projects or LibSDL projects to build Mobile applications and Games. You can build the Qt project or the LibSDL project and get the Android package directly (*.apk) Check Ring distributions for Mobile development using Qt or LibSDL. 53.3. Creating Windows Installer 521
543.
CHAPTER FIFTYFOUR COMMAND LINE OPTIONS Thering language takes source code file (.ring) or the object file (.ringo) as input to execute, also the language provide other options like Option Description -tokens Print a list of tokens in the source code file -rules Print grammar rules applied on the tokens -ic Print the intermediate byte code (before execution) -icfinal Print the final byte code (after execution) -cgi Print http response header before error messages -norun Don’t run the program after compiling -ins Print instruction operation code before execution -performance Print clock before and after program execution -go Generate Object File -w Display Warnings 54.1 Printing Tokens Example: Func Main See "Hello World" + nl for x = 1 to 10 see x + nl next test() func test see "welcome" + nl o1 = new point { x=10 y=20 z=30 } see o1 class point x y z Command: ring test.ring -tokens -norun Output: =================================================== Tokens - Generated by the Scanner =================================================== 522
544.
Ring Documentation, Release1.2 Keyword : FUNC Identifier : main EndLine Keyword : SEE Literal : Hello World Operator : + Identifier : nl EndLine Keyword : FOR Identifier : x Operator : = Number : 1 Keyword : TO Number : 10 EndLine Keyword : SEE Identifier : x Operator : + Identifier : nl EndLine Keyword : NEXT EndLine Identifier : test Operator : ( Operator : ) EndLine Keyword : FUNC Identifier : test EndLine Keyword : SEE Literal : welcome Operator : + Identifier : nl EndLine Identifier : o1 Operator : = Keyword : NEW Identifier : point Operator : { Identifier : x Operator : = Number : 10 Identifier : y Operator : = Number : 20 Identifier : z Operator : = Number : 30 Operator : } EndLine Keyword : SEE Identifier : o1 EndLine Keyword : CLASS Identifier : point Identifier : x Identifier : y Identifier : z 54.1. Printing Tokens 523
545.
Ring Documentation, Release1.2 EndLine =================================================== 54.2 Printing Rules Command: ring test.ring -rules -norun Output: =================================================== Grammar Rules Used by The Parser =================================================== Rule : Program --> {Statement} Line 1 Rule : Statement --> 'Func' Identifier [ParaList] Line 2 Rule : Factor --> Literal Rule : Range --> Factor Rule : Term --> Range Rule : Arithmetic --> Term Rule : Factor --> Identifier [ {Mixer} | Assignment | PlusPlus | MinusMinus] Rule : Range --> Factor Rule : Term --> Range Rule : Arithmetic --> Term Rule : Arithmetic --> Arithmetic + Arithmetic Rule : BitShift --> Arithmetic Rule : BitAnd --> BitShift Rule : BitOrXOR --> BitAnd Rule : Compare --> BitOrXOR Rule : EqualOrNot --> Compare Rule : LogicNot -> EqualOrNot Rule : Expr --> LogicNot Rule : Statement --> 'See' Expr Line 3 Rule : Factor --> Number Rule : Range --> Factor Rule : Term --> Range Rule : Arithmetic --> Term Rule : BitShift --> Arithmetic Rule : BitAnd --> BitShift Rule : BitOrXOR --> BitAnd Rule : Compare --> BitOrXOR Rule : EqualOrNot --> Compare Rule : LogicNot -> EqualOrNot Rule : Expr --> LogicNot Rule : Factor --> Number Rule : Range --> Factor Rule : Term --> Range Rule : Arithmetic --> Term Rule : BitShift --> Arithmetic 54.2. Printing Rules 524
Ring Documentation, Release1.2 202 NewLine 5 203 PushP 007D37D8 0 207 204 AssignmentPointer 205 PushN 1.000000 206 BeforeEqual 0 207 Assignment 0 0 208 FreeStack 209 NewLine 6 210 Return =================================================== 54.5 CGI Support Command: ring test.ring -cgi 54.6 No Run Command: ring test.ring -norun 54.7 Printing Instruction Operation Code Command: ring test.ring -ins Output: =================================================== Operation : ReturnNull PC : 1 Line Number : 1 , File test.ring SP (After) : 0 - FuncSP : 0 LineNumber 1 =================================================== ..... ..... ..... Tip: Output removed from the previous example because it’s very large! 54.8 Performance Command: 54.5. CGI Support 535
557.
Ring Documentation, Release1.2 ring test.ring -performance Output: =================================================== Date : 2015/09/15 Time : 15:56:17 Clock : 0 =================================================== Hello World 1 2 3 4 5 6 7 8 9 10 welcome x: 10.000000 y: 20.000000 z: 30.000000 =================================================== Date : 2015/09/15 Time : 15:56:17 Clock : 0 =================================================== 54.9 Generate Object File You can generate object file (.ringo) from your source code file (.ring) using -go option Tip: You will get one object file to use for distributing/running your application which may contains one or many ring source files that you can keep or distribute based on the application (commercial or open source). Command: ring test.ring -go To run the compiled object file ring test.ringo 54.9. Generate Object File 536
558.
CHAPTER FIFTYFIVE LOW LEVEL FUNCTIONS Inthis chapter we will learn about the low level functions provided by Ring • callgc() • varptr() • space() • nullpointer() • object2pointer() • pointer2object() • ptrcmp() • ringvm_cfunctionslist() • ringvm_functionslist() • ringvm_classeslist() • ringvm_packageslist() • ringvm_memorylist() • ringvm_calllist() • ringvm_fileslist() 55.1 callgc() function Use this function to force calling the garbage collector during function execution when you use a loop that create temp. variables that you don’t free using the assignment operation. It’s very rare to need this function but it’s useful when you create something like event-loop for your game engine and start creating lists on the fly when you call functions. Example While True # process events # call functions using temp. lists like myfunc(["temp list"]) # call the garbage collector callgc() End 537
559.
Ring Documentation, Release1.2 Tip: In Ring the garbage collector works automatically in the end of function execution or when you use the assign- ment statement. 55.2 varptr() function Use the varptr() function when you need to pass a pointer to a C/C++ function. Syntax: varptr(cVariableName,cPointerType) —> Low Level Object (C Pointer) example: r = 10 z = 20 see r + nl see varptr("r","int") see varptr("z","int") Output: 10 00E3C740 int 2 00E3BEC0 int 2 Note: the low level object is a list contains three items (The Pointer, The Type, The Status) 55.3 space() function Use the space function to allocate a specific number of bytes in Memory. Syntax: Space(nBytesCount) ---> String Example: mystring = space(200) See "String Size : " + len(mystring) + nl See "String : " + mystring + nl See "String Pointer : " See varptr("mystring","char *") Output: String Size : 200 String : String Pointer : 00FF8FE8 char * 2 55.2. varptr() function 538
560.
Ring Documentation, Release1.2 Note: You may need the space() and VarPtr() functions to pass buffers to C functions. 55.4 nullpointer() function You may need to pass the NULL pointer to a C function that may expect a pointer as parameter and accept NULL pointers for optional parameters. Example: The next example uses the SDL_BlitSurface() function from the LibSDL Library through RingSDL The function accept SDL_Rect pointers in the second and the last parameter. Also the function accept NULL pointers, so we can pass them using the NULLPointer() Function. SDL_BlitSurface(text, nullpointer(), surface, nullpointer()) Note: The previous code doesn’t work alone, you need to learn how to use RingSDL first. Tip: We can pass NULL as parameter instead of using NULLPointer() 55.5 object2pointer() function Use this function to get a C pointer for Ring lists and objects Syntax: object2pointer(List|Object) --> Low Level Object ( C Pointer ) 55.6 pointer2object() function Use this function to get the Ring list and/or object from the low level object (C Pointer) Syntax: pointer2object(Low Level Object) ---> List|Object Example: # Create the list mylist = 1:5 # Create pointer to the list x = object2pointer(mylist) see x see nl # Add items to the list mylist + "welcome" # print the list items 55.4. nullpointer() function 539
561.
Ring Documentation, Release1.2 y = pointer2object(x) see y Output: 0069A5D8 OBJECTPOINTER 0 1 2 3 4 5 welcome Note: In Ring the assignment operator copy lists and objects by value, to copy by reference Just use the ob- ject2pointer() and pointer2object() functions. Tip: The object2pointer() and pointer2object() are used in the stdlib - Tree Class implementation to create a reference for the parent node (object) in the child node (another object). 55.7 ptrcmp() function We can compare between two pointers (C Objects) using the ptrcmp() function. Syntax: ptrcmp(oObject1,oObject2) ---> value = 1 if oObject1 = oObject2 value = 0 if oObject1 != oObject2 Example: fp = fopen("ptrcmp.ring","r") fp2 = fp fp3 = fopen("ptrcmp.ring","r") see ptrcmp(fp,fp2) + nl see ptrcmp(fp,fp3) + nl fclose(fp) fclose(fp3) Output: 1 0 55.8 ringvm_cfunctionslist() function The Function return a list of functions written in C. Syntax: 55.7. ptrcmp() function 540
562.
Ring Documentation, Release1.2 RingVM_CFunctionsList() ---> List Example: See RingVM_CFunctionsList() 55.9 ringvm_functionslist() function The Function return a list of functions written in Ring. Each List Member is a list contains the next items • Function Name • Program Counter (PC) - Function Position in Byte Code. • Source Code File Name • Private Flag (For Private Methods in Classes) Syntax: RingVM_FunctionsList() ---> List Example: test() func test see ringvm_functionslist() Output: test 8 B:/ring/tests/scripts/functionslist.ring 0 55.10 ringvm_classeslist() function The Function return a list of Classes. Each List Member is a list contains the next items • Class Name • Program Counter (PC) - Class Position in Byte Code. • Parent Class Name • Methods List • Flag (Is parent class information collected) • Pointer to the package (or NULL if no package is used) Syntax: RingVM_ClassesList() ---> List 55.9. ringvm_functionslist() function 541
563.
Ring Documentation, Release1.2 Example: see ringvm_classeslist() class class1 func f1 class class2 from class1 class class3 from class1 Output: class1 9 f1 13 B:/ring/tests/scripts/classeslist.ring 0 0 00000000 class2 16 class1 0 00000000 class3 20 class1 0 00000000 55.11 ringvm_packageslist() function The Function return a list of Packages. Each List Member is a list contains the next items • Package Name • Classes List Syntax: RingVM_PackagesList() ---> List Example: see ringvm_packageslist() package package1 class class1 package package2 class class1 package package3 class class1 Output: 55.11. ringvm_packageslist() function 542
564.
Ring Documentation, Release1.2 package1 class1 11 0 00FEF838 package2 class1 17 0 00FEF978 package3 class1 23 0 00FEFF68 55.12 ringvm_memorylist() function The Function return a list of Memory Scopes and Variables. Each List Member is a list contains variables in a different scope. Each Item in the scope list is a list contains the next items • Variable Name • Variable Type • Variable Value • Pointer Type (List/Item) if the value is a list • Private Flag (if the variable is an attribute in a Class) Syntax: RingVM_MemoryList() ---> List Example: x = 10 test() func test y = 20 see ringvm_memorylist() Output: true 2 1 0 0 false 2 0 0 55.12. ringvm_memorylist() function 543
Ring Documentation, Release1.2 sysargv 3 B:ringbin/ring B:/ring/tests/scripts/memorylist.ring 0 0 x 2 10 0 0 y 2 20 0 0 55.13 ringvm_calllist() function The Function return a list of the functions call list. Each List Member is a list contains the next items • Function Type • Function Name • Program Counter (PC) • Stack Pointer (SP) • Temp. Memory List • Method or Function Flag • Caller PC • FuncExec Flag • ListStart Flag • Nested Lists Pointer • State List Syntax: RingVM_CallList() ---> List Example: hello() func hello test() func test mylist = ringvm_calllist() for t in mylist see t[2] + nl next Output: 55.13. ringvm_calllist() function 545
567.
Ring Documentation, Release1.2 function hello() in file B:/ring/tests/scripts/calllist.ring called from line 1 function test() in file B:/ring/tests/scripts/calllist.ring called from line 3 ringvm_calllist 55.14 ringvm_fileslist() function Function return a list of the Ring Files. Syntax: RingVM_FilesList() ---> List Example: load "stdlib.ring" see ringvm_fileslist() Output: B:/ring/tests/scripts/fileslist.ring B:ringbinstdlib.ring eval stdlib.ring stdlib.rh stdclasses.ring stdfunctions.ring stdbase.ring stdstring.ring stdlist.ring stdstack.ring stdqueue.ring stdmath.ring stddatetime.ring stdfile.ring stdsystem.ring stddebug.ring stddatatype.ring stdconversion.ring stdodbc.ring stdmysql.ring stdsecurity.ring stdinternet.ring stdhashtable.ring stdtree.ring 55.14. ringvm_fileslist() function 546
568.
CHAPTER FIFTYSIX EXTENSION USING THEC/C++ LANGUAGES We can extend the Ring Virtual Machine (RingVM) by adding new functions written in the C programming language or C++. The RingVM comes with many functions written in C that we can call like any Ring function. We can extend the language by writing new functions then rebuilding the RingVM again, or we can create shared library (DLL/So) file to extend the RingVM without the need to rebuild it. The Ring language source code comes with two files to add new modules to the RingVM, ring_ext.h and ring_ext.c 56.1 ring_ext.h The file ring_ext.h contains constants that we can change to include/exclude modules during the build process. #ifndef ringext_h #define ringext_h /* Constants */ #define RING_VM_LISTFUNCS 1 #define RING_VM_REFMETA 1 #define RING_VM_MATH 1 #define RING_VM_FILE 1 #define RING_VM_OS 1 #define RING_VM_MYSQL 1 #define RING_VM_ODBC 1 #define RING_VM_OPENSSL 1 #define RING_VM_CURL 1 #define RING_VM_DLL 1 #endif 56.2 ring_ext.c The file ring_ext.c check constants defined in ring_ext.h before calling the start-up function in each module. Each module contains a function that register the module functions in the RingVM. #include "ring.h" void ring_vm_extension ( RingState *pRingState ) { /* Reflection and Meta-programming */ #if RING_VM_REFMETA ring_vm_refmeta_loadfunctions(pRingState); #endif 547
569.
Ring Documentation, Release1.2 /* List Functions */ #if RING_VM_LISTFUNCS ring_vm_listfuncs_loadfunctions(pRingState); #endif /* Math */ #if RING_VM_MATH ring_vm_math_loadfunctions(pRingState); #endif /* File */ #if RING_VM_FILE ring_vm_file_loadfunctions(pRingState); #endif /* OS */ #if RING_VM_OS ring_vm_os_loadfunctions(pRingState); #endif /* MySQL */ #if RING_VM_MYSQL ring_vm_mysql_loadfunctions(pRingState); #endif /* ODBC */ #if RING_VM_ODBC ring_vm_odbc_loadfunctions(pRingState); #endif /* OPENSSL */ #if RING_VM_OPENSSL ring_vm_openssl_loadfunctions(pRingState); #endif /* CURL */ #if RING_VM_CURL ring_vm_curl_loadfunctions(pRingState); #endif /* DLL */ #if RING_VM_DLL ring_vm_dll_loadfunctions(pRingState); #endif } 56.3 Module Organization Each module starts by include the ring header file (ring.h). This files contains the Ring API that we can use to extend the RingVM. Each module comes with a function to register the module functions in the RingVM The registration is done by using ring_vm_funcregister() function. The ring_vm_funcregister() function takes two parameters, the first is the function name that will be used by Ring programs to call the function. The second parameter is the function pointer in the C program. for example, the ring_vmmath.c module contains the next code to register the module functions #include "ring.h" void ring_vm_math_loadfunctions ( RingState *pRingState ) { ring_vm_funcregister("sin",ring_vm_math_sin); ring_vm_funcregister("cos",ring_vm_math_cos); 56.3. Module Organization 548
570.
Ring Documentation, Release1.2 ring_vm_funcregister("tan",ring_vm_math_tan); ring_vm_funcregister("asin",ring_vm_math_asin); ring_vm_funcregister("acos",ring_vm_math_acos); ring_vm_funcregister("atan",ring_vm_math_atan); ring_vm_funcregister("atan2",ring_vm_math_atan2); ring_vm_funcregister("sinh",ring_vm_math_sinh); ring_vm_funcregister("cosh",ring_vm_math_cosh); ring_vm_funcregister("tanh",ring_vm_math_tanh); ring_vm_funcregister("exp",ring_vm_math_exp); ring_vm_funcregister("log",ring_vm_math_log); ring_vm_funcregister("log10",ring_vm_math_log10); ring_vm_funcregister("ceil",ring_vm_math_ceil); ring_vm_funcregister("floor",ring_vm_math_floor); ring_vm_funcregister("fabs",ring_vm_math_fabs); ring_vm_funcregister("pow",ring_vm_math_pow); ring_vm_funcregister("sqrt",ring_vm_math_sqrt); ring_vm_funcregister("unsigned",ring_vm_math_unsigned); ring_vm_funcregister("decimals",ring_vm_math_decimals); ring_vm_funcregister("murmur3hash",ring_vm_math_murmur3hash); } Tip: Remember that the function ring_vm_math_loadfunctions() will be called by the ring_vm_extension() function (in the ring_ext.c file). 56.4 Function Structure Each module function may contains the next steps 1 - Check Parameters Count 2 - Check Parameters Type 3 - Get Parameters Values 4 - Execute Code/Call Functions 5 - Return Value The structure is very similar to any function (Input - Process - Output) But here we will use the Ring API for the steps 1,2,3 and 5. 56.5 Check Parameters Count We can check the parameters count using the RING_API_PARACOUNT macro. We can compare RING_API_PARACOUNT with any numeric value using == or != operators. Example: if ( RING_API_PARACOUNT != 1 ) { /* code */ } Example: 56.4. Function Structure 549
571.
Ring Documentation, Release1.2 if ( RING_API_PARACOUNT == 1 ) { /* code */ } 56.6 Display Error Message We can display error messages using the RING_API_ERROR() function. The function will display the error and end the execution of the program. Note: the behaviour of this function can be changed by the Ring code using Try/Catch/Done statements, so in your C code, use Return after this function. Syntax: RING_API_ERROR(const char *cErrorMsg); The Ring API comes with some of predefined error messages that we can use #define RING_API_MISS1PARA "Bad parameters count, the function expect one parameter" #define RING_API_MISS2PARA "Bad parameters count, the function expect two parameters" #define RING_API_MISS3PARA "Bad parameters count, the function expect three parameters" #define RING_API_MISS4PARA "Bad parameters count, the function expect four parameters" #define RING_API_BADPARATYPE "Bad parameter type!" #define RING_API_BADPARACOUNT "Bad parameters count!" #define RING_API_BADPARARANGE "Bad parameters value, error in range!" #define RING_API_NOTPOINTER "Error in parameter, not pointer!" #define RING_API_NULLPOINTER "Error in parameter, NULL pointer!" #define RING_API_EMPTYLIST "Bad parameter, empty list!" 56.7 Check Parameters Type We can check the parameter type using the next functions int RING_API_ISNUMBER(int nParameterNumber); int RING_API_ISSTRING(int nParameterNumber); int RING_API_ISLIST(int nParameterNumber); int RING_API_ISPOINTER(int nParameterNumber); The output of these functions will be 1 (True) or 0 (False). 56.8 Get Parameters Values We can get paramters values using the next functions double RING_API_GETNUMBER(int nParameterNumber); const char *RING_API_GETSTRING(int nParameterNumber); int RING_API_GETSTRINGSIZE(int nParameterNumber); List *RING_API_GETLIST(int nParameterNumber); void *RING_API_GETCPOINTER(int nParameterNumber, const char *cPoinerType); int RING_API_GETPOINTERTYPE(int nParameterNumber); 56.6. Display Error Message 550
572.
Ring Documentation, Release1.2 56.9 Return Value We can return values from our function using the next functions. RING_API_RETNUMBER(double nValue); RING_API_RETSTRING(const char *cString); RING_API_RETSTRING2(const char *cString,int nStringSize); RING_API_RETLIST(List *pList); RING_API_RETCPOINTER(void *pValue,const char *cPointerType); 56.10 Function Prototype When we define new function to be used for RingVM extension, we use the next prototype void my_function_name( void *pPointer ); or we can use the RING_FUNC() Macro RING_FUNC(my_function_name); 56.11 Sin() Function Implementation The next code represents the sin() function implementation using the Ring API and the sin() C function. void ring_vm_math_sin ( void *pPointer ) { if ( RING_API_PARACOUNT != 1 ) { RING_API_ERROR(RING_API_MISS1PARA); return ; } if ( RING_API_ISNUMBER(1) ) { RING_API_RETNUMBER(sin(RING_API_GETNUMBER(1))); } else { RING_API_ERROR(RING_API_BADPARATYPE); } } 56.12 Fopen() and Fclose() Functions Implementation The next code represents the fopen() function implementation using the Ring API and the fopen() C Function. The function takes two parameters, the first parameter is the file name as string. The second parameter is the mode as string. In the file ring_vmfile.h we have some constants to use as the pointer type like #define RING_VM_POINTER_FILE "file" #define RING_VM_POINTER_FILEPOS "filepos" The function implementation in ring_vmfile.c 56.9. Return Value 551
573.
Ring Documentation, Release1.2 void ring_vm_file_fopen ( void *pPointer ) { FILE *fp ; if ( RING_API_PARACOUNT != 2 ) { RING_API_ERROR(RING_API_MISS2PARA); return ; } if ( RING_API_ISSTRING(1) && RING_API_ISSTRING(2) ) { fp = fopen(RING_API_GETSTRING(1),RING_API_GETSTRING(2)); RING_API_RETCPOINTER(fp,RING_VM_POINTER_FILE); } else { RING_API_ERROR(RING_API_BADPARATYPE); } } The next code represents the fclose() function implementation void ring_vm_file_fclose ( void *pPointer ) { FILE *fp ; if ( RING_API_PARACOUNT != 1 ) { RING_API_ERROR(RING_API_MISS1PARA); return ; } if ( RING_API_ISPOINTER(1) ) { fp = (FILE *) RING_API_GETCPOINTER(1,RING_VM_POINTER_FILE) ; if ( fp != NULL ) { RING_API_RETNUMBER(fclose(fp)); RING_API_SETNULLPOINTER(1); } } else { RING_API_ERROR(RING_API_BADPARATYPE); } } From fopen() and fclose() implementation we learned 1 - how to return C pointer using RING_API_RETCPOINTER() function 2 - how to check if the parameter is a pointer using the RING_API_ISPOINTER() function 3 - how to get C pointer value using the RING_API_GETCPOINTER() function 4 - how to set the C pointer variable (in RingVM) to NULL using the RING_API_SETNULLPOINTER() function 56.13 Ring API - List Functions In this section we will learn about the list functions provided by the Ring API to create new lists and manipulate the list items. List * ring_list_new ( int nSize ) ; void ring_list_newitem ( List *pList ) ; Item * ring_list_getitem ( List *pList,int index ) ; List * ring_list_delete ( List *pList ) ; void ring_list_deleteitem ( List *pList,int index ) ; void ring_list_print ( List *pList ) ; int ring_list_gettype ( List *pList, int index ) ; void ring_list_setint ( List *pList, int index ,int number ) ; 56.13. Ring API - List Functions 552
574.
Ring Documentation, Release1.2 void ring_list_addint ( List *pList,int x ) ; void ring_list_setpointer ( List *pList, int index ,void *pValue ) ; void ring_list_addpointer ( List *pList,void *pValue ) ; void ring_list_setfuncpointer ( List *pList, int index ,void (*pFunc)(void *) ) ; void ring_list_addfuncpointer ( List *pList,void (*pFunc)(void *) ) ; int ring_list_isfuncpointer ( List *pList, int index ) ; void ring_list_setdouble ( List *pList, int index ,double number ) ; void ring_list_adddouble ( List *pList,double x ) ; void ring_list_setstring ( List *pList, int index ,const char *str ) ; void ring_list_setstring2 ( List *pList, int index ,const char *str,int nStrSize ) ; void ring_list_addstring ( List *pList,const char *str ) ; void ring_list_addstring2 ( List *pList,const char *str,int nStrSize ) ; List * ring_list_newlist ( List *pList ) ; List * ring_list_getlist ( List *pList, int index ) ; void ring_list_setlist ( List *pList, int index ) ; void ring_list_setactiveitem ( List *pList, Items *pItems, int index ) ; void ring_list_copy ( List *pNewList, List *pList ) ; int ring_list_isnumber ( List *pList, int index ) ; int ring_list_isstring ( List *pList, int index ) ; int ring_list_islist ( List *pList, int index ) ; int ring_list_ispointer ( List *pList, int index ) ; void ring_list_deleteallitems ( List *pList ) ; void ring_list_insertitem ( List *pList,int x ) ; void ring_list_insertint ( List *pList,int nPos,int x ) ; void ring_list_insertdouble ( List *pList,int nPos,double x ) ; void ring_list_insertpointer ( List *pList,int nPos,void *pValue ) ; void ring_list_insertstring ( List *pList,int nPos,const char *str ) ; void ring_list_insertstring2 ( List *pList,int nPos,const char *str,int nStrSize ) ; void ring_list_insertfuncpointer ( List *pList,int nPos,void (*pFunc)(void *) ) ; List * ring_list_insertlist ( List *pList,int nPos ) ; int ring_list_isiteminsidelist ( List *pList,Item *pItem ) ; int ring_list_findstring ( List *pList,const char *str,int nColumn ) ; int ring_list_finddouble ( List *pList,double nNum1,int nColumn ) ; void ring_list_sortnum ( List *pList,int left,int right,int nColumn ) ; void ring_list_sortstr ( List *pList,int left,int right,int nColumn ) ; int ring_list_binarysearchnum ( List *pList,double nNum1,int nColumn ) ; int ring_list_binarysearchstr ( List *pList,const char *cFind,int nColumn ) ; void ring_list_swap ( List *pList,int x,int y ) ; double ring_list_getdoublecolumn ( List *pList,int nIndex,int nColumn ) ; char * ring_list_getstringcolumn ( List *pList,int nIndex,int nColumn ) ; void ring_list_genarray ( List *pList ) ; void ring_list_deletearray ( List *pList ) ; void ring_list_genhashtable ( List *pList ) ; void ring_list_genhashtable2 ( List *pList ) ; void ring_list_refcopy ( List *pNewList, List *pList ) ; void ring_list_clear ( List *pList ) ; /* Macro */ ring_list_isdouble(pList,index) ring_list_isint(pList,index) ring_list_deletelastitem(x) ring_list_gethashtable(x) ring_list_getint(pList,index) ring_list_getpointer(pList,index) ring_list_getfuncpointer(pList,index) ring_list_callfuncpointer(pList,index,x) ring_list_getdouble(pList,index) ring_list_getstring(pList,index) ring_list_getstringobject(pList,index) 56.13. Ring API - List Functions 553
575.
Ring Documentation, Release1.2 ring_list_getstringsize(pList,index) ring_list_getsize(x) (x->nSize) 56.14 Ring API - String Functions In this section we will learn about the string functions provided by the Ring API to create new string and manipulate the string content. String * ring_string_new ( const char *str ) ; String * ring_string_new2 ( const char *str,int nStrSize ) ; String * ring_string_delete ( String *pString ) ; int ring_string_size ( String *pString ) ; void ring_string_set ( String *pString,const char *str ) ; void ring_string_set2 ( String *pString,const char *str,int nStrSize ) ; void ring_string_add ( String *pString,const char *str ) ; void ring_string_add2 ( String *pString,const char *str,int nStrSize ) ; void ring_string_print ( String *pString ) ; void ring_string_setfromint ( String *pString,int x ) ; char * ring_string_lower ( char *cStr ) ; char * ring_string_upper ( char *cStr ) ; char * ring_string_lower2 ( char *cStr,int nStrSize ) ; char * ring_string_upper2 ( char *cStr,int nStrSize ) ; char * ring_string_find ( char *cStr1,char *cStr2 ) ; char * ring_string_find2 ( char *cStr1,int nStrSize1,char *cStr2,int nStrSize2 ) ; /* Macro */ ring_string_tolower(x) ring_string_toupper(x) ring_string_get(x) 56.15 MySQL_Columns() Function Implementation The next code presents the MySQL_Columns() function implementation. This function returns table columns information. void ring_vm_mysql_columns ( void *pPointer ) { MYSQL *con ; MYSQL_RES *result ; int nColumns,x ; MYSQL_ROW row ; MYSQL_FIELD *field ; List *pList, *pList2 ; if ( RING_API_PARACOUNT != 1 ) { RING_API_ERROR(RING_API_MISS1PARA); return ; } if ( RING_API_ISPOINTER(1) ) { con = (MYSQL *) RING_API_GETCPOINTER(1,RING_VM_POINTER_MYSQL) ; if ( con == NULL ) { return ; } result = mysql_store_result(con); if ( result == NULL ) { 56.14. Ring API - String Functions 554
576.
Ring Documentation, Release1.2 RING_API_RETNUMBER(0); return ; } pList = RING_API_NEWLIST ; nColumns = mysql_num_fields(result); if ( row = mysql_fetch_row(result) ) { while ( field = mysql_fetch_field(result) ) { pList2 = ring_list_newlist(pList); ring_list_addstring(pList2,field->name); ring_list_adddouble(pList2,field->length); ring_list_adddouble(pList2,field->type); ring_list_adddouble(pList2,field->flags); } } mysql_free_result(result); RING_API_RETLIST(pList); } else { RING_API_ERROR(RING_API_BADPARATYPE); } } Lists are of type List, in the previoud function we declared two pointers of type List using List *pList, *pList2; Note: The function uses RING_API_NEWLIST to create new list instead of ring_list_new() to create the list in Temp. Memory related to the function scope. This way we can return the list from the function. Also we don’t delete the list, if it’s stored in a variable by Ring Code it will be saved, if not it will be automatically deleted by RingVM. The list can contains sub lists, we used the function ring_list_newlist() to create a sublist. The function ring_list_addstring() is used to add string items to the list/sublist. The function ring_list_adddouble() is used to add numeric items to the list/sublist. Note: All numeric items in lists returned from RingVM extension functions must be of type double and added to the list using ring_list_adddouble() function. We return the list from the extension function using the RING_API_RETLIST() function. 56.16 Dynamic/Shared Libraries (DLL/So) and LoadLib() function Instead of rebuilding the RingVM after writing new functions using C/C++ and the Ring API, we can create a DLL/So file and dynamically use the functions provided by this file in the runtime using the LoadLib() function. Dynamic library example in C #include "ring.h" RING_DLL __declspec(dllexport) RING_FUNC(ring_ringlib_dlfunc) { printf("Message from dlfunc"); } RING_DLL void ringlib_init(RingState *pRingState) { 56.16. Dynamic/Shared Libraries (DLL/So) and LoadLib() function 555
577.
Ring Documentation, Release1.2 ring_vm_funcregister("dlfunc",ring_ringlib_dlfunc); } the idea is to create the ringlib_init() function, this function will be called by the RingVM when we use the generated DLL file though the LoadLib() function. Inside the ringlib_init() function we can register the module function or call a function that do the registration process for all of the module functions. The next Ring code demonstrates how to use the DLL library during the runtime. See "Dynamic DLL" + NL LoadLib("ringlib.dll") dlfunc() Output: Dynamic DLL Message from dlfunc 56.16. Dynamic/Shared Libraries (DLL/So) and LoadLib() function 556
578.
CHAPTER FIFTYSEVEN EMBEDDING RING LANGUAGEIN C/C++ PROGRAMS We can use the Ring language from C/C++ programs using the next functions RingState *ring_state_init(); ring_state_runcode(RingState *pState,const char *cCode); ring_state_delete(RingState *pState); 57.1 Ring State The idea is to use the ring_state_init() to create new state for the Ring Language then call the ring_state_runcode() function to execut Ring code using the same state. When we are done, we call the ring_state_delete() to free the memory. Example: #include "ring.h" #include "stdlib.h" int main(int argc, char *argv[]) { RingState *pState = ring_state_init(); printf("welcomen"); ring_state_runcode(pState,"see 'hello world from the ring programming language'+nl"); ring_state_delete(pState); } Output: welcome hello world from the ring programming language 57.2 Ring State Functions The Ring API comes with the next functions to create and delete the state. Also we have functions to create new variables and get variables values. RingState * ring_state_init ( void ) ; RingState * ring_state_delete ( RingState *pRingState ) ; void ring_state_runcode ( RingState *pRingState,const char *cStr ) ; List * ring_state_findvar ( RingState *pRingState,const char *cStr ) ; List * ring_state_newvar ( RingState *pRingState,const char *cStr ) ; void ring_state_main ( int argc, char *argv[] ) ; 557
579.
Ring Documentation, Release1.2 void ring_state_runfile ( RingState *pRingState,const char *cFileName ) ; void ring_state_runobjectfile ( RingState *pRingState,const char *cFileName ) ; 57.3 Ring State Variables We can create more than one ring state in the same program and we can create and modify variable values. To get the variable list we can use the ring_state_findvar() function. To create new variable we can use the ring_state_newvar() function. Example: #include "ring.h" #include "stdlib.h" int main(int argc, char *argv[]) { List *pList; RingState *pState = ring_state_init(); RingState *pState2 = ring_state_init(); printf("welcomen"); ring_state_runcode(pState,"see 'hello world from the ring programming language'+nl"); printf("Again from C we will call ring coden"); ring_state_runcode(pState,"for x = 1 to 10 see x + nl next"); ring_state_runcode(pState2,"for x = 1 to 5 see x + nl next"); printf("Now we will display the x variable value from ring coden"); ring_state_runcode(pState,"see 'x value : ' + x + nl "); ring_state_runcode(pState2,"see 'x value : ' + x + nl "); pList = ring_state_findvar(pState,"x"); printf("Printing Ring variable value from C , %.0fn", ring_list_getdouble(pList,RING_VAR_VALUE)); printf("now we will set the ring variable value from Cn"); ring_list_setdouble(pList,RING_VAR_VALUE,20); ring_state_runcode(pState,"see 'x value after update : ' + x + nl "); pList = ring_state_newvar(pState,"v1"); ring_list_setdouble(pList,RING_VAR_VALUE,10); pList = ring_state_newvar(pState,"v2"); ring_list_setdouble(pList,RING_VAR_VALUE,20); ring_state_runcode(pState,"see 'v1 + v2 = ' see v1+v2 see nl"); ring_state_runcode(pState,"see 'end of test' + nl"); ring_state_delete(pState); 57.3. Ring State Variables 558
580.
Ring Documentation, Release1.2 ring_state_delete(pState2); } Output: welcome hello world from the ring programming language Again from C we will call ring code 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 Now we will display the x variable value from ring code x value : 11 x value : 6 Printing Ring variable value from C , 11 now we will set the ring variable value from C x value after update : 20 v1 + v2 = 30 end of test 57.3. Ring State Variables 559
581.
CHAPTER FIFTYEIGHT CODE GENERATOR FORWRAPPING C/C++ LIBRARIES In this chapter we will learn how to use the code generator to wrap C/C++ Libraries to use it in our Ring applications. 58.1 Using the tool The code generator program is parsec.ring that can be executed as any ring code using the ring language. URL : https://github.com/ring-lang/ring/tree/master/extensions/codegen for example to read a configuration file called test.cf to generate the source code file test.c run parsec.ring as in the next command ring parsec.ring test.cf test.c 58.2 Configuration file The configuration file (*.cf) is the input file that we pass to the code generator. This file determine the functions prototypes that we need to use from a C/C++ library. Writing configuration files is simple according to the next rules 58.3 Using the function prototype • To generate code that wraps a C function, we just write the C function prototype Example: ALLEGRO_DISPLAY *al_create_display(int w, int h) void al_destroy_display(ALLEGRO_DISPLAY *display) int al_get_new_display_flags(void) void al_set_new_display_flags(int flags) int al_get_new_display_option(int option, int *importance) The previous example will guide the code generator to generate 5 functions that wraps the al_create_display(), al_destroy_display(), al_get_new_display_flags(), al_set_new_diplay_flas() and al_get_new_display_option() func- tions. The generated code will be as in the next example 560
Ring Documentation, Release1.2 { if ( RING_API_PARACOUNT != 2 ) { RING_API_ERROR(RING_API_MISS2PARA); return ; } if ( ! RING_API_ISNUMBER(1) ) { RING_API_ERROR(RING_API_BADPARATYPE); return ; } if ( ! RING_API_ISSTRING(2) ) { RING_API_ERROR(RING_API_BADPARATYPE); return ; } RING_API_RETNUMBER(al_get_new_display_option( (int ) RING_API_GETNUMBER(1), RING_API_GETINTPOINTER(2))); RING_API_ACCEPTINTVALUE(2) ; } from the previous example we can see how much of time and effort is saved using the Code Generator. 58.4 Adding code to the generated code • To generate code directly type it between <code> and </code> Example : <code> /* some C code will be written here */ </code> We use this feature when we need to do something without the help of the code generator. for example including header files and defining constants using Macro. 58.5 Prefix for Functions Names • To determine a prefix in all of the functions names type it between <funcstart> and </funcstart> for ex- ample when we wrap the Allegro game programming library and we need all of the library functions to start with “al” we type the next code in the configuration file <funcstart> al </funcstart> 58.6 Generate function to wrap structures • To generate functions that wrap structures (create/delete/get structure members) just type the structures names between <struct> and </struct> also after the structure name you can type the structure members between { } separated by comma. Example 58.4. Adding code to the generated code 562
584.
Ring Documentation, Release1.2 <struct> ALLEGRO_COLOR ALLEGRO_EVENT { type , keyboard.keycode , mouse.x , mouse.y } </struct> from the previous example we will generate two function to create/delete the structure ALLEGRO_COLOR Also we will generate two functions to create/delete the structure ALLEGRO_EVENT and four functions to get the structure ALLEGRO_EVENT members (type, keyboard.keycode, mouse.x, mouse.y). 58.7 Determine Structure Members Types You can determine the pointer name before the strucuture member name. Example: SDL_Surface {flags,SDL_PixelFormat *format,w,h,pitch,void *pixels,void *userdata,locked,void *lock_da 58.8 Defining Contants You can define constatants using <constant> and </constant> The generator will generate the required functions to get the constant values And will define the constants to be used with the same name in Ring code using *.rh file that will be generated too. rh = Ring Header Example: <constant> MIX_DEFAULT_FORMAT SDL_QUIT SDL_BUTTON_LEFT SDL_BUTTON_MIDDLE SDL_BUTTON_RIGHT </constant> Note: You will need to pass the *.rh file name to parsec.ring after the generated source file name. Example: ring ..codegenparsec.ring libsdl.cf ring_libsdl.c ring_libsdl.rh 58.9 Register New Functions We can register functions by typing the function prototype between <register> and </register> We need this feature only when we don’t provide the function prototype as input directly where we need to write the code of this function. Example: <register> void al_exit(void) </register> 58.7. Determine Structure Members Types 563
585.
Ring Documentation, Release1.2 <code> RING_FUNC(ring_al_exit) { if ( RING_API_PARACOUNT != 0 ) { RING_API_ERROR(RING_API_BADPARACOUNT); return ; } exit(0); } </code> In the previous example we register the al_exit() function. This function is not part of the Allegro Library, it’s just an extra function that we need to add. Then the code if this function is written inside <code> and </code>. This function call the exit() function from the C language library. 58.10 Writing comments in the configuration file • To type comments just type it between <comment> and </comment> Example: <comment> configuration files </comment> 58.11 Executing code during code generation • To ask from the code generator to execute Ring code during reading the configuration file, just write the code between <runcode> and </runcode> Example: <runcode> aNumberTypes + "al_fixed" </runcode> The previoud line of code add the string “al_fixed” to the list aNumberTypes, This list contains types that can be considered as numbers when the code generator find it in the function prototype. 58.12 Enum and Numbers We have the list aEnumTypes to use for adding each Enumeration we uses in the functions prototype. Example: <runcode> aNumberTypes + "qreal" aNumberTypes + "qint64" aEnumTypes + "Qt::GestureType" aEnumTypes + "Qt::GestureFlag" </runcode> 58.10. Writing comments in the configuration file 564
586.
Ring Documentation, Release1.2 58.13 Filtering using Expressions using <filter> and </filter> we can include/exclude parts of the configuration file based on a condition, for example <filter> iswindows() ... functions related to windows </filter> 58.14 Configuration file for the Allegro Library The next configuration file enable us to use the Allegro library functions. The configuration file size is less than 1000 lines. when the code generator take this file as input the generated source code file in the C language will be 12000 lines of code! We can see this configuration file as a complete example about using the code generator Also we can use it to know the functions that can be used from RingAllegro when you use it to create 2D games! <code> #define ALLEGRO_NO_MAGIC_MAIN #include <allegro5/allegro.h> #include "allegro5/allegro_image.h" #include <allegro5/allegro_font.h> #include <allegro5/allegro_ttf.h> #include <allegro5/allegro_audio.h> #include <allegro5/allegro_acodec.h> #include <allegro5/allegro_opengl.h> #include <allegro5/allegro_direct3d.h> #include <allegro5/allegro_color.h> #include <allegro5/allegro_memfile.h> #include "allegro5/allegro_native_dialog.h" #include <allegro5/allegro_physfs.h> #include <allegro5/allegro_primitives.h> </code> <funcstart> al </funcstart> <struct> ALLEGRO_EVENT { type , keyboard.keycode , mouse.x , mouse.y } ALLEGRO_TIMEOUT ALLEGRO_SAMPLE_ID ALLEGRO_COLOR </struct> <register> void al_exit(void) </register> <code> RING_FUNC(ring_al_exit) { if ( RING_API_PARACOUNT != 0 ) { RING_API_ERROR(RING_API_BADPARACOUNT); return ; 58.13. Filtering using Expressions 565
587.
Ring Documentation, Release1.2 } exit(0); } </code> int al_init(void) <comment> configuration files </comment> <runcode> aNumberTypes + "al_fixed" </runcode> ALLEGRO_CONFIG *al_create_config(void) void al_destroy_config(ALLEGRO_CONFIG *config) ALLEGRO_CONFIG *al_load_config_file(const char *filename) ALLEGRO_CONFIG *al_load_config_file_f(ALLEGRO_FILE *file) bool al_save_config_file(const char *filename, const ALLEGRO_CONFIG *config) bool al_save_config_file_f(ALLEGRO_FILE *file, const ALLEGRO_CONFIG *config) void al_add_config_section(ALLEGRO_CONFIG *config, const char *name) Note: we just provided part of the configuration file, for complete copy check the Ring source code distribution. 58.15 Threads Support Next, another part of the configutaiton file, it’s important because we can learn from it how to add threads to our Ring applications by using a threads library. The idea is using ring_vm_mutexfunctions() and ring_vm_runcodefromthread() to execute Ring code. <comment> Threads </comment> <code> void *al_func_thread(ALLEGRO_THREAD *thread, void *pPointer) { List *pList; VM *pVM; const char *cStr; pList = (List *) pPointer ; pVM = (VM *) ring_list_getpointer(pList,2); cStr = ring_list_getstring(pList,1); ring_vm_runcodefromthread(pVM,cStr); ring_list_delete(pList); return NULL; } RING_FUNC(ring_al_create_thread) { ALLEGRO_THREAD *pThread; List *pList; if ( RING_API_PARACOUNT != 1 ) { 58.15. Threads Support 566
Ring Documentation, Release1.2 58.16 Code Generator Rules for Wrapping C++ Classes • We can define classes between <class> and </class> • Between <class> and <class> we set attributes like “name, nonew, para, parent, codename, passvmpointer and abstract” • we set the attributes using the style attributename:value or attributename only if no values are required • The “name” attribute determine the class name in C++ code and this name will be the default name in the Ring code • The nonew instruction means that we don’t need new/delete methods • The parent attribute determine the parent class name • The codename attribute determine another class name in C++ code • The passvmpoint instruction means passing the Ring VM pointer to the class constructor when we create new objects, this happens when we set the codename attribute to a class the we will define and this class need the Virtual Machine pointer (for example to use it to execute Ring code from C++ code). • The abstract instruction means that no new method is required for this class “no objects will be created”. • Using <nodllstartup> we can avoid #include “ring.h”, We need this to write our startup code. • Using <libinitfunc> we can change the function name that register the library functions • Using <ignorecpointertype> we can ignore pointer type check • Using the aStringTypes list when can defined new types that treated like const char * • Using the aBeforeReturn list when can define code that is inserted after the variable name when we return that variable from a function • Using the aNewMethodName list we can define another method name to be used in Ring code when we call the C++ method. this feature is required because some C++ method may be identical to Ring Keywords like “load”,”next”,”end” and “done”. • in method prototype - when we use @ in the method name, we mean that we have the same method with different parameters (As in C++) 58.17 Using configuration file that wrap C++ Library To run the code generator to generate code for using C++ library in the Ring application, we can do that as we did with using C libraries but here we will generate .cpp file instead of *.c file. Also we will determine another file to be generated (.ring). This file will contains classes in Ring code that wraps C++ functions for using C++ classes and objects. ring parsec.ring qt.cf ring_qt.cpp ring_qt.ring 58.18 Configuration file for the Qt Framework The next configuration file is used to wrap many Qt classes The configuration file is around 3500 lines and generate C++ code around 56000 lines and generate also Ring code around 9000 lines. 58.16. Code Generator Rules for Wrapping C++ Classes 568
Ring Documentation, Release1.2 </class> void setText(const char *) void setClickEvent(const char *) void setIcon(QIcon) void setIconSize(QSize) <class> name: QLineEdit para: QWidget * parent: QWidget codename: GLineEdit passvmpointer </class> int alignment(void) void backspace(void) QCompleter *completer(void) QMenu *createStandardContextMenu(void) void cursorBackward(bool mark, int steps) void cursorForward(bool mark, int steps) int cursorMoveStyle(void) int cursorPosition(void) int cursorPositionAt(QPoint) void cursorWordBackward(bool mark) void cursorWordForward(bool mark) void del(void) void deselect(void) QString displayText(void) bool dragEnabled(void) int echoMode(void) void end(bool mark) void getTextMargins(int *left, int *top, int *right, int *bottom) bool hasAcceptableInput(void) bool hasFrame(void) bool hasSelectedText(void) void home(bool mark) QString inputMask(void) void insert(QString) bool isModified(void) bool isReadOnly(void) bool isRedoAvailable(void) bool isUndoAvailable(void) int maxLength(void) QString placeholderText(void) QString selectedText(void) int selectionStart(void) void setAlignment(int flag) void setCompleter(QCompleter *c) void setCursorMoveStyle(int style) void setCursorPosition(int) void setDragEnabled(bool b) void setEchoMode(int) void setFrame(bool) void setInputMask(QString) void setMaxLength(int) void setModified(bool) void setPlaceholderText(QString) 58.18. Configuration file for the Qt Framework 577
599.
Ring Documentation, Release1.2 void setReadOnly(bool) void setSelection(int start, int length) void setTextMargins(int left, int top, int right, int bottom) void setValidator(QValidator *v) QString text(void) QMargins textMargins(void) QValidator *validator(void) void clear(void) void copy(void) void cut(void) void paste(void) void redo(void) void selectAll(void) void setText(QString) void undo(void) void setTextChangedEvent(const char *) void setcursorPositionChangedEvent(const char *) void seteditingFinishedEvent(const char *) void setreturnPressedEvent(const char *) void setselectionChangedEvent(const char *) void settextEditedEvent(const char *) Note: Most of the content of the previous configuration file is removed from this documentation, for a complete version see the Ring source code distribution. 58.19 Configuration Files Examples You can learn from the next examples • RingAllegro : https://github.com/ring-lang/ring/blob/master/extensions/ringallegro/allegro.cf • RingQt : https://github.com/ring-lang/ring/blob/master/extensions/ringqt/qt.cf • RingLibSDL : https://github.com/ring-lang/ring/blob/master/extensions/ringsdl/libsdl.cf After modifing the configuration file, You will need to generate the code, You can learn from the next examples • RingAllegro : https://github.com/ring-lang/ring/blob/master/extensions/ringallegro/gencode.bat • RingQt : https://github.com/ring-lang/ring/blob/master/extensions/ringqt/gencode.bat • RingLibSDL : https://github.com/ring-lang/ring/blob/master/extensions/ringsdl/gencode.bat After generating the code, You will need to build the library, You can learn from the next examples • RingAllegro : https://github.com/ring-lang/ring/blob/master/extensions/ringallegro/buildvc.bat • RingQt : https://github.com/ring-lang/ring/blob/master/extensions/ringqt/buildmingw32.bat • RingLibSDL : https://github.com/ring-lang/ring/blob/master/extensions/ringsdl/buildvc.bat 58.19. Configuration Files Examples 578
Ring Documentation, Release1.2 • int IMG_isPCX(SDL_RWops *src) • int IMG_isGIF(SDL_RWops *src) • int IMG_isJPG(SDL_RWops *src) • int IMG_isTIF(SDL_RWops *src) • int IMG_isPNG(SDL_RWops *src) • int IMG_isLBM(SDL_RWops *src) • int IMG_isXV(SDL_RWops *src) • int TTF_Init(void) • int TTF_WasInit(void) • void TTF_Quit(void) • TTF_Font *TTF_OpenFont(const char *file, int ptsize) • TTF_Font *TTF_OpenFontRW(SDL_RWops *src, int freesrc, int ptsize) • TTF_Font *TTF_OpenFontIndex(const char *file, int ptsize, long index) • TTF_Font *TTF_OpenFontIndexRW(SDL_RWops *src, int freesrc, int ptsize, long index) • void TTF_CloseFont(TTF_Font *font) • void TTF_ByteSwappedUNICODE(int swapped) • int TTF_GetFontStyle(TTF_Font *font) • void TTF_SetFontStyle(TTF_Font *font, int style) • int TTF_GetFontOutline(TTF_Font *font) • void TTF_SetFontOutline(TTF_Font *font, int outline) • int TTF_GetFontHinting(TTF_Font *font) • void TTF_SetFontHinting(TTF_Font *font, int hinting) • int TTF_GetFontKerning(TTF_Font *font) • void TTF_SetFontKerning(TTF_Font *font, int allowed) • int TTF_FontHeight(const TTF_Font *font) • int TTF_FontAscent(const TTF_Font *font) • int TTF_FontDescent(const TTF_Font *font) • int TTF_FontLineSkip(const TTF_Font *font) • long TTF_FontFaces(const TTF_Font *font) • int TTF_FontFaceIsFixedWidth(const TTF_Font *font) • char *TTF_FontFaceFamilyName(const TTF_Font *font) • char *TTF_FontFaceStyleName(const TTF_Font *font) • int TTF_GlyphIsProvided(const TTF_Font *font, Uint16 ch) • int TTF_GlyphMetrics(TTF_Font *font, Uint16 ch, int *minx, int *maxx, int *miny, int *maxy, int *advance) • int TTF_SizeText(TTF_Font *font, const char *text, int *w, int *h) • int TTF_SizeUTF8(TTF_Font *font, const char *text, int *w, int *h) 612
634.
Ring Documentation, Release1.2 • int TTF_SizeUNICODE(TTF_Font *font, const Uint16 *text, int *w, int *h) • SDL_Surface *TTF_RenderText_Solid(TTF_Font *font, const char *text, SDL_Color fg) • SDL_Surface *TTF_RenderUTF8_Solid(TTF_Font *font, const char *text,SDL_Color fg) • SDL_Surface *TTF_RenderUNICODE_Solid(TTF_Font *font, const Uint16 *text,SDL_Color fg) • SDL_Surface *TTF_RenderGlyph_Solid(TTF_Font *font, Uint16 ch, SDL_Color fg) • SDL_Surface *TTF_RenderText_Shaded(TTF_Font *font, const char *text,SDL_Color fg, SDL_Color bg) • SDL_Surface *TTF_RenderUTF8_Shaded(TTF_Font *font, const char *text,SDL_Color fg, SDL_Color bg) • SDL_Surface *TTF_RenderUNICODE_Shaded(TTF_Font *font, const Uint16 *text,SDL_Color fg, SDL_Color bg) • SDL_Surface *TTF_RenderGlyph_Shaded(TTF_Font *font, Uint16 ch, SDL_Color fg,SDL_Color bg) • SDL_Surface *TTF_RenderText_Blended(TTF_Font *font, const char *text,SDL_Color fg) • SDL_Surface *TTF_RenderUTF8_Blended(TTF_Font *font, const char *text,SDL_Color fg) • SDL_Surface *TTF_RenderUNICODE_Blended(TTF_Font *font, const Uint16 *text,SDL_Color fg) • SDL_Surface *TTF_RenderGlyph_Blended(TTF_Font *font, Uint16 ch, SDL_Color fg) • int Mix_Init(int flags) • void Mix_Quit(void) • int Mix_OpenAudio(int frequency, Uint16 format, int channels, int chunksize) • void Mix_CloseAudio(void) • int Mix_QuerySpec(int *frequency, Uint16 *format, int *channels) • int Mix_GetNumChunkDecoders(void) • const char *Mix_GetChunkDecoder(int index) • Mix_Chunk *Mix_LoadWAV(char *file) • Mix_Chunk *Mix_LoadWAV_RW(SDL_RWops *src, int freesrc) • Mix_Chunk *Mix_QuickLoad_WAV(Uint8 *mem) • void Mix_FreeChunk(Mix_Chunk *chunk) • int Mix_AllocateChannels(int numchans) • int Mix_Volume(int channel, int volume) • int Mix_PlayChannel(int channel, Mix_Chunk *chunk, int loops) • int Mix_PlayChannelTimed(int channel, Mix_Chunk *chunk, int loops, int ticks) • int Mix_FadeInChannel(int channel, Mix_Chunk *chunk, int loops, int ms) • int Mix_FadeInChannelTimed(int channel, Mix_Chunk *chunk,int loops, int ms, int ticks) • void Mix_Pause(int channel) • void Mix_Resume(int channel) • int Mix_HaltChannel(int channel) • int Mix_ExpireChannel(int channel, int ticks) • int Mix_FadeOutChannel(int channel, int ms) 613
635.
Ring Documentation, Release1.2 • int Mix_Paused(int channel) • Mix_Fading Mix_FadingChannel(int which) • Mix_Chunk *Mix_GetChunk(int channel) • int Mix_ReserveChannels(int num) • int Mix_GroupChannel(int which, int tag) • int Mix_GroupChannels(int from, int to, int tag) • int Mix_GroupCount(int tag) • int Mix_GroupAvailable(int tag) • int Mix_GroupOldest(int tag) • int Mix_GroupNewer(int tag) • int Mix_FadeOutGroup(int tag, int ms) • int Mix_HaltGroup(int tag) • int Mix_GetNumMusicDecoders(void) • const char *Mix_GetMusicDecoder(int index) • Mix_Music *Mix_LoadMUS(const char *file) • void Mix_FreeMusic(Mix_Music *music) • int Mix_PlayMusic(Mix_Music *music, int loops) • int Mix_FadeInMusic(Mix_Music *music, int loops, int ms) • int Mix_FadeInMusicPos(Mix_Music *music, int loops, int ms, double position) • int Mix_PlayingMusic(void) • int Mix_PausedMusic(void) • Mix_Fading Mix_FadingMusic(void) • void *Mix_GetMusicHookData(void) • int Mix_RegisterEffect(int chan, Mix_EffectFunc_t f, Mix_EffectDone_t d,void *arg) • int Mix_UnregisterEffect(int channel, Mix_EffectFunc_t f) • int Mix_UnregisterAllEffects(int channel) • int Mix_SetDistance(int channel, Uint8 distance) • int Mix_SetPosition(int channel, Sint16 angle, Uint8 distance) • int Mix_SetReverseStereo(int channel, int flip) • int SDLNet_Init(void) • void SDLNet_Quit(void) • char *SDLNet_GetError(void) • void SDLNet_Write16(Uint16 value, void *area) • void SDLNet_Write32(Uint32 value, void *area) • Uint16 SDLNet_Read16(void *area) • Uint32 SDLNet_Read32(void *area) 614
636.
Ring Documentation, Release1.2 • int SDLNet_ResolveHost(IPaddress *address, const char *host, Uint16 port) • const char *SDLNet_ResolveIP(IPaddress *address) • TCPsocket SDLNet_TCP_Open(IPaddress *ip) • void SDLNet_TCP_Close(TCPsocket sock) • TCPsocket SDLNet_TCP_Accept(TCPsocket server) • IPaddress *SDLNet_TCP_GetPeerAddress(TCPsocket sock) • int SDLNet_TCP_Send(TCPsocket sock, const void *data, int len) • int SDLNet_TCP_Recv(TCPsocket sock, void *data, int maxlen) • UDPsocket SDLNet_UDP_Open(Uint16 port) • void SDLNet_UDP_Close(UDPsocket sock) • int SDLNet_UDP_Bind(UDPsocket sock, int channel, IPaddress *address) • void SDLNet_UDP_Unbind(UDPsocket sock, int channel) • IPaddress *SDLNet_UDP_GetPeerAddress(UDPsocket sock, int channel) • int SDLNet_UDP_Send(UDPsocket sock, int channel, UDPpacket *packet) • int SDLNet_UDP_Recv(UDPsocket sock, UDPpacket *packet) • int SDLNet_UDP_SendV(UDPsocket sock, UDPpacket **packetV, int npackets) • int SDLNet_UDP_RecvV(UDPsocket sock, UDPpacket **packetV) • UDPpacket *SDLNet_AllocPacket(int size) • int SDLNet_ResizePacket(UDPpacket *packet, int size) • void SDLNet_FreePacket(UDPpacket *packet) • UDPpacket **SDLNet_AllocPacketV(int howmany, int size) • void SDLNet_FreePacketV(UDPpacket **packetV) • SDLNet_SocketSet SDLNet_AllocSocketSet(int maxsockets) • void SDLNet_FreeSocketSet(SDLNet_SocketSet set) • int SDLNet_AddSocket(SDLNet_SocketSet set, SDLNet_GenericSocket sock) • int SDLNet_TCP_AddSocket(SDLNet_SocketSet set, TCPsocket sock) • int SDLNet_UDP_AddSocket(SDLNet_SocketSet set, UDPsocket sock) • int SDLNet_DelSocket(SDLNet_SocketSet set, SDLNet_GenericSocket sock) • int SDLNet_TCP_DelSocket(SDLNet_SocketSet set, TCPsocket sock) • int SDLNet_UDP_DelSocket(SDLNet_SocketSet set, UDPsocket sock) • int SDLNet_CheckSockets(SDLNet_SocketSet set, Uint32 timeout) • int SDLNet_SocketReady(TCPsocket sock) • int circleRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 615
Ring Documentation, Release1.2 • void setHistory(QStringList) • void setIconProvider(QFileIconProvider *provider) • void setItemDelegate(QAbstractItemDelegate *delegate) • void setLabelText(QFileDialog::DialogLabel label, QString) • void setMimeTypeFilters(QStringList) • void setNameFilter(QString) • void setNameFilters(QStringList) • void setOption(QFileDialog::Option option, bool) • void setOptions(QFileDialog::Option options) • void setProxyModel(QAbstractProxyModel *proxyModel) • int viewMode(void) • QString getExistingDirectory(QWidget *,QString,QString, QFileDialog::Option) • QUrl getExistingDirectoryUrl(QWidget *,QString,QUrl, QFileDialog::Option,QStringList) • QString getOpenFileName(QWidget *,QString,QString,QString) • QUrl getSaveFileUrl(QWidget *,QString, QUrl,QString, QString *, QFileDialog::Option options,QStringList) 62.57 QPainter Class C++ Reference : http://doc.qt.io/qt-5/QPainter.html Parameters : void • QBrush background(void) • int backgroundMode(void) • bool begin(QPaintDevice *device) • void beginNativePainting(void) • QRect boundingRect(int x, int y, int w, int h, int flags, QString text) • QBrush brush(void) • QPoint brushOrigin(void) • QRectF clipBoundingRect(void) • QPainterPath clipPath(void) • QRegion clipRegion(void) • QTransform combinedTransform(void) • int compositionMode(void) • QPaintDevice *device(void) • QTransform deviceTransform(void) • void drawArc(int x, int y, int width, int height, int startAngle, int spanAngle) • void drawChord(int x, int y, int width, int height, int startAngle, int spanAngle) 62.57. QPainter Class 671
693.
Ring Documentation, Release1.2 • void drawConvexPolygon( QPoint * points, int pointCount) • void drawEllipse(int x, int y, int width, int height) • void drawGlyphRun( QPointF position, QGlyphRun glyphs) • void drawImage(int x, int y, QImage image) • void drawLine(int x1, int y1, int x2, int y2) • void drawLines( QLine * lines, int lineCount) • void drawPath( QPainterPath path) • void drawPicture(int x, int y, QPicture picture) • void drawPie(int x, int y, int width, int height, int startAngle, int spanAngle) • void drawPixmap(int x, int y, QPixmap) • void drawPoints( QPointF * points, int pointCount) • void drawPolygon( QPointF * points, int pointCount, Qt::FillRule fillRule) • void drawPolyline( QPointF * points, int pointCount) • void drawRect(int x, int y, int width, int height) • void drawRects( QRectF * rectangles, int rectCount) • void drawRoundedRect(int x, int y, int w, int h, qreal xRadius, qreal yRadius, Qt::SizeMode mode) • void drawStaticText(int left, int top, QStaticText staticText) • void drawText(int x, int y, QString text) • void drawTiledPixmap(int x, int y, int width, int height, QPixmap pixmap, int sx, int sy) • bool end(void) # In RingQt use : bool endpaint(void) • void endNativePainting(void) • void eraseRect(int x, int y, int width, int height) • void fillPath( QPainterPath path, QBrush brush) • void fillRect(int x, int y, int width, int height, QBrush) • QFont font(void) • QFontInfo fontInfo(void) • bool hasClipping(void) • void initFrom( QWidget *widget) • bool isActive(void) • int layoutDirection(void) • double opacity(void) • QPaintEngine *paintEngine(void) • QPen pen(void) • int renderHints(void) • void resetTransform(void) • void restore(void) 62.57. QPainter Class 672
Ring Documentation, Release1.2 • void swap(QPen) • int width(void) • double widthF(void) 62.60 QColor Class C++ Reference : http://doc.qt.io/qt-5/QColor.html Parameters : void • int alpha(void) • double alphaF(void) • int black(void) • double blackF(void) • int blue(void) • double blueF(void) • QColor convertTo(QColor::Spec colorSpec) • int cyan(void) • double cyanF(void) • QColor darker(int factor) • void getCmyk(int *c, int *m, int *y, int *k, int *a) • void getCmykF(qreal *c, qreal *m, qreal *y, qreal *k, qreal *a) • void getHsl(int *h, int *s, int *l, int *a) • void getHslF(qreal *h, qreal *s, qreal *l, qreal *a) • void getHsv(int *h, int *s, int *v, int *a) • void getHsvF(qreal *h, qreal *s, qreal *v, qreal *a) • void getRgb(int *r, int *g, int *b, int *a) • void getRgbF(qreal *r, qreal *g, qreal *b, qreal *a) • int green(void) • double greenF(void) • int hslHue(void) • double hslHueF(void) • int hslSaturation(void) • double hslSaturationF(void) • int hsvHue(void) • double hsvHueF(void) • int hsvSaturation(void) • double hsvSaturationF(void) 62.60. QColor Class 675
697.
Ring Documentation, Release1.2 • int hue(void) • double hueF(void) • bool isValid(void) • QColor lighter(int factor) • int lightness(void) • double lightnessF(void) • int magenta(void) • double magentaF(void) • QString name(void) • int red(void) • double redF(void) • QRgb rgb(void) • QRgb rgba(void) • int saturation(void) • double saturationF(void) • void setAlpha(int alpha) • void setAlphaF(double alpha) • void setBlue(int blue) • void setBlueF(double blue) • void setCmyk(int c, int m, int y, int k, int a) • void setCmykF(double c, double m, double y, double k, double a) • void setGreen(int green) • void setGreenF(double green) • void setHsl(int h, int s, int l, int a) • void setHslF(double h, double s, double l, double a) • void setHsv(int h, int s, int v, int a) • void setHsvF(double h, double s, double v, double a) • void setNamedColor(QString) • void setRed(int red) • void setRedF(double red) • void setRgb(int r, int g, int b, int a) • void setRgbF(double r, double g, double b, double a) • void setRgba(QRgb rgba) • int spec(void) • QColor toCmyk(void) • QColor toHsl(void) 62.60. QColor Class 676
698.
Ring Documentation, Release1.2 • QColor toHsv(void) • QColor toRgb(void) • int value(void) • double valueF(void) • int yellow(void) • double yellowF(void) • QStringList colorNames(void) • QColor fromCmyk(int c, int m, int y, int k, int a) • QColor fromCmykF(double c, double m, double y, double k, double a) • QColor fromHsl(int h, int s, int l, int a) • QColor fromHslF(double h, double s, double l, double a) • QColor fromHsv(int h, int s, int v, int a) • QColor fromHsvF(double h, double s, double v, double a) • QColor fromRgb(int r, int g, int b, int a) • QColor fromRgbF(double r, double g, double b, double a) • QColor fromRgba(QRgb rgba) • bool isValidColor(QString) 62.61 QPrinter Class C++ Reference : http://doc.qt.io/qt-5/QPrinter.html Parameters : QPrinter::PrinterMode • bool abort(void) • bool collateCopies(void) • int colorMode(void) • int copyCount(void) • QString creator(void) • QString docName(void) • int duplex(void) • bool fontEmbeddingEnabled(void) • int fromPage(void) • bool fullPage(void) • bool isValid(void) • QString outputFileName(void) • int outputFormat(void) • QRectF pageRect(QPrinter::Unit unit) 62.61. QPrinter Class 677
Ring Documentation, Release1.2 62.126 QGridLayout Class C++ Reference : http://doc.qt.io/qt-5/QGridLayout.html Parameters : void • void addItem(QLayoutItem * item, int row, int column, int rowSpan , int columnSpan , Qt::Alignment alignment ) • void addLayout(QLayout * layout, int row, int column, Qt::Alignment alignment ) • void addLayout_2(QLayout * layout, int row, int column, int rowSpan, int columnSpan, Qt::Alignment align- ment ) • void addWidget(QWidget * widget, int row, int column, Qt::Alignment alignment ) • void addWidget_2(QWidget * widget, int fromRow, int fromColumn, int rowSpan, int columnSpan, Qt::Alignment alignment ) • QRect cellRect(int row, int column) • int columnCount(void) • int columnMinimumWidth(int column) • int columnStretch(int column) • void getItemPosition(int index, int * row, int * column, int * rowSpan, int * columnSpan) • int horizontalSpacing(void) • QLayoutItem * itemAtPosition(int row, int column) • Qt::Corner originCorner(void) • int rowCount(void) • int rowMinimumHeight(int row) • int rowStretch(int row) • void setColumnMinimumWidth(int column, int minSize) • void setColumnStretch(int column, int stretch) • void setHorizontalSpacing(int spacing) • void setOriginCorner(Qt::Corner corner) • void setRowMinimumHeight(int row, int minSize) • void setRowStretch(int row, int stretch) • void setSpacing(int spacing) • void setVerticalSpacing(int spacing) • int spacing(void) • int verticalSpacing(void) 62.127 QTextCharFormat Class C++ Reference : http://doc.qt.io/qt-5/QTextCharFormat.html Parameters : void 62.126. QGridLayout Class 730
Ring Documentation, Release1.2 • void setX(qreal x) • void setY(qreal y) • QPoint toPoint(void) • qreal x(void) • qreal y(void) 62.142 QPoint Class C++ Reference : http://doc.qt.io/qt-5/QPoint.html Parameters : void • bool isNull(void) • int manhattanLength(void) • int rx(void) • int ry(void) • void setX(int x) • void setY(int y) • int x(void) • int y(void) 62.142. QPoint Class 741
763.
CHAPTER SIXTYTHREE FREQUENTLY ASKED QUESTIONS(FAQ) 63.1 Why do we need Yet Another Programming Language (YAPL)? The language comes with better support for Natural Language Programming and Declarative Programming. The inno- vation comes in supporting these paradigms with new practical techniques on the top of Object-Oriented Programming and Functional Programming. Ring provide the programmers with the tools required to build a Natural Language like Supernova or Declarative Language like REBOL and QML without the need to know anything about (Compilers and Parsing). You get the language constructs ready for use to create domain-specific languages in a fraction of time. Check the Supernova programming language, In this language you can type (I want window and the window title is hello world.) and it will create a GUI window with “Hello, World!” as the window title. When I created Supernova language in 2010. I discovered that using the Natural Code can be (Like English without limits and we can get the human language power in programming) but to implement that You need a new language that are 1. General Purpose 2. Practical 3. Can create Natural Languages very quickly. So we can get a System that can increase ease of use and productivity to the maximum level. Ring is the best language to do that. So I created Ring to achieve this goal. Supernova was just a test for the idea. To get a near view about what are the Advantages and Disadvantages. After testing the new ideas you provide something practical. So we have Ring after Supernova. A story that maybe similar to having Python after ABC. Python avoid ABC problems but bring ABC advantages. Also Ring learn from Ruby and ROR story. The language power could appears in Frameworks better than direct usage as a general purpose language. Also Ring comes with a clear goal/motivation (Creating a new version of the PWCT Software) something learned from designing the C language to create the Unix Operating System. You have a goal that direct you in each design decision. You will understand the value of our decisions once you start trying to solve the problem that we will use Ring to solve. Could you enable any one in the world without knowledge about computer programming concepts to create very powerful software? In science the answer is (Visual Programming) and (Natural Programming). In practical we still away from switching to these paradigms without introducing other problems. Ring is designed to solve this problem. It’s designed to provide Natural Programming in a practical way. And to create a powerful Visual Programming tool. Ring is designed to be a new world of programming after 10 years of research in Visual Programming and Natural Languages. The Ring Programming Language (Compiler+VM) is developed 100% using Visual Programming without writing a single line of code. I used my tool (Programming Without Coding Technology) to design everything and get the C code generated for me. Advantages ? 1. More Faster 2. No Syntax Errors 742
764.
Ring Documentation, Release1.2 3. Easy to understand and manage the code because the Abstraction level is more higher 4. No Critical Disadvantages because you can control everything as writing your code. From my experience in using Visual Programming for 10 years and Natural Programming for 5 years I designed Ring to move the knowledge to mainstream programmers by providing a practical language that support these ideas. I agree that each programmer/developer has the freedom to form his opinions about any software including program- ming languages. Ring is not an exception but you may miss the idea behind the language. It’s innovative and may help you to think different about how to solve your problems. Maybe this is not clear to many programmers because It’s practical language and includes many features known to programmers and when a programmer look at a language he/she may think that nothing new because it’s familiar. I created Ring to solve problems in a different way. Where I will start programming just by describing the software using new natural interfaces that I will implement later when I move from the design stage to the implementation stage. (I don’t determine the time to switch between stages, You are free to use Agile methods). Since Ring is a new language you have 3 options. 1. Just don’t care. 2. Think in the future of the language and help us if you understand the idea and want to contribute. 3. Wait and come back again in the future to use it. Summary: • Ring is designed based on a need to develop a new version of the PWCT software. Once we finish PWCT 2.0 we will have good and large software developed using Ring. • We will push Declarative and Natural paradigms many steps forward. Also in next versions we have a plan to present a new paradigm for Network Programming and Concurrency. We tested this new paradigm through simple prototypes during the last years and we will integrate it with Ring in Future releases. • It’s a new language, just Ring version 1.1. A serious ecosystem comes along the way. 63.2 Why Ring is weakly typed? Because it’s more Natural, and Faster and this is important for the language goals. What comes first is what you want. When you type “Print : ” + 5 , The String comes first then 5 will be converted to a String. while when you type 5 + “10” The number comes first so “10” will be converted to 10. This help a lot to quickly convert between numbers and strings using the same operator. If you want to prevent conversion (Write code that prevent conversion) In these cases you will notice that what you are writing is less code (And can be removed). Weakly Typed = Automatic Conversion and Automatic is Good Thing and is better than Manual if you know how to use it correctly. 63.3 What are the advantages to using Ring over Lisp or Smalltalk? Smalltalk and Lisp are GREAT languages. I like many of the concepts behind them but I’m sure that selecting the right programming language is based on the problem and comes after the problem definition. I have a problem that I want to solve and these GREAT languages are not ideal for this problem so I designed Ring. When you design a new language, You can learn from the past but you must look forward and live in the Future. What you know about Natural Programming maybe based on the Old Knowledge about the power of these paradigms in the practical world and I agree with you but I see another techniques that can be applied to get this to work in practical. What you miss about Natural Language is that they are Context Sensitive and this means we can use it and think different about how we can express our ideas. 63.2. Why Ring is weakly typed? 743
765.
Ring Documentation, Release1.2 example : I want window contains 3 buttons. In one sentence I created 4 objects (The window and the three buttons) and added the buttons to the window. The idea of Natural Programming is to get many things done like that. 63.4 Why Ring is largely focussed on UI creation? Yes UI creation is one of the important things in the language features because it’s designed to create a visual pro- gramming tool, But the language is a multi-paradigm language where we can select the programming paradigm based on the problem. 63.5 Is Ring some sort of improvement over PHP? Ring is not designed to replace PHP, Lua and/or Smalltalk. And Ring support for Declarative Programming and Natural Language Programming is very innovative and much better than staying with Procedural, Object-Oriented and Functional Languages. Ring see the future in programming without code (Using Natural Languages) and is designed to support that. 63.6 What are the advantages to using Ring over native C or C++? Ring provides a better way to mix between different programming paradigms in solving problems. The different programming paradigms play well together in the same language. 1. It’s easy to switch from one programming paradigm to another one because the language constructs use similar syntax for similar concepts. 2. The paradigms are provided to interact and used together in different layers in the software. for example you can create a game engine using object-oriented programming but write the game code using declara- tive programming or natural programming and behind the scene your declarative or natural code will use the object- oriented classes. 3. Ring is very productive and natural programming language than C/C++ languages. 4. Ring is a dynamic language. We can generate and execute code during the runtime. We have dynamic typing and weakly typed language for flexibility. 5. The Garbage collector is generational (escape analysis) and also use reference counting. it’s very fast and still provide control to the programmer who can delete memory at any time. 6. Ring Compiler and Virtual Machine is just 15,000 lines of ANSI C code that can be compiled and used in any platform. 7. You can use C/C++ libraries and Ring comes with code generator to create wrappers from C functions or C++ classes. so when you need more performance or when you need to use more libraries you can easily do that. 63.7 What is the difference between Ring and Python? And is Ring Open Source? Yes the language is Free Open Source (MIT license) 63.4. Why Ring is largely focussed on UI creation? 744
766.
Ring Documentation, Release1.2 In general I like Python and Ruby but I was looking for a language more suitable for creating the next version of the Programming Without Coding Technology (PWCT) software so I started the Ring design. Some simple changes that matters for my goal are 1. Not case sensitive 2. The list index start from 1 3. You can call functions before definition 4. Don’t use Python syntax like (indentation, using self, :, pass & _) 5. Weakly typed (convert automatically between types based on context) 6. The programs follow simple and constant structure (Statements then functions then packages and classes) 7. Using the ‘=’ operator for assignment and for testing values Critical changes are 1. Small Language : The Ring compiler + Virtual Machine = 15K lines of C code , the other 85K lines are related to libraries and are optional when we go for using the language in C/C++ programs. 2. The Garbage collector : Uses Escape Analysis/Reference counting and give the programmer the ability to determine when to delete memory using the assignment operator 3. Compact Syntax : Ring is not line sensitive, you don’t need to write ; or press ENTER to separate between statements 4. Using { } to access the object then using the object attributes and methods directly 5. Natural Programming : It’s very easy to create natural interfaces using Ring based on OOP 6. Declarative Programming using Nested Structure The Ring programming language is designed based on my experience from using many other languages like C, C++, C#, Lua, PHP, Python, Ruby, Harbour, Basic and Supernova And the language comes with innovative features added to achieve the language goal • Applications programming language. • Productivity and developing high quality solutions that can scale. • Small and fast language that can be embedded in C/C++ projects. • Simple language that can be used in education and introducing Compiler/VM concepts. • General-Purpose language that can be used for creating domain-specific libraries, frameworks and tools. • Practical language designed for creating the next version of the Programming Without Coding Technology software. 63.8 What are the advantages to using Ring over Perl, PHP, Python or Ruby? 1. Ring is New and Innovative. The language will let you think different about programming. 2. Ring is Smaller. (Lessons learned from the Lua language) 3. Ring is Simple. (Lessons learned from the BASIC and Clipper/Harbour languages) 4. Ring is more Natural. (Lessons learned from the Supernova language) 5. Ring is more Declarative. (Lessons learned from REBOL and QML languages) 63.8. What are the advantages to using Ring over Perl, PHP, Python or Ruby? 745
767.
Ring Documentation, Release1.2 6. Ring Implementation is Transparent, Visual and comes with Rich Features. 63.9 What are the advantages to using Ring over Tcl or Lua? 1. Clean Code (More Natural) 2. More Features (A lot of useful programming paradigms) 63.10 What are the advantages to using Ring over C# or Java? 1. Compact Code (Clean and Natural), More Productivity and Flexibility. 2. Better support for Declarative Programming and Natural Programming 63.11 The documentation says functional programming is sup- ported, but then this happens? The question was about this code f = func { a = 42 return func { return a } } innerF = call f() call innerF() Output: Using uninitialized variable : a In function _ring_anonymous_func_16601() The Answer: • It’s Anonymous Functions, i.e. Not Closures. • It’s Just Ring version 1.1 (Many developers asked about supporting Closures) and during language development we may add new features that doesn’t go against the language goals or sprite. • You can use classes and objects when you want to merge between the state and functions to provide a clear solution. • You can use Lists and put the anonymous function inside the List then return the list that contains the state and the function. Pass the list to the function when you use it. • You can use eval() and substr() to add the variable value directly to the anonymous function before return. • We protect you from other scopes when you define the function. In Ring we provided the Three Scopes Rule where at each point you have only at maximum three scopes (Global, Object Scope and Local Scope). • We don’t get everything from everywhere to be like others! We don’t need to do that. If we will think like that then we will create a very complex language or we will save our time and use other languages. • When you think about learning or studying a new language concentrate about (What is new?) and (What is better in this language?) to know when to use it. Don’t compare a new language just released little months ago with languages started many years ago and expect to find everything that you used to have. 63.9. What are the advantages to using Ring over Tcl or Lua? 746
768.
Ring Documentation, Release1.2 • Each programming language miss features in other languages. The idea is not the Features. it’s the sprite and ability behind all of the features together. 63.12 Why the ability to define your own languages Instead of just handing over the syntax so you can parse it using whatever code you like? It’s innovation - You create natural statements without the need to learn about parsing. You just use Classes which is intelligent decision (where later we can mix between classes to support more statements based on the context - We can change and translate the defined statements and many more!). Also the statements are added in Ring World where you can use any Ring statement. 63.13 Why you can specify the number of loops you want to break out of? The language support programming in the small and programming in the large. The selection of what features to use is based on what are you going to do. Any programmer can write bad code in any language if he/she wants to do that. The idea is what must be done from the language design to prevent errors without causing other problems like killing flexibility. Read some source code in the Linux Kernel and Ruby Implementation for example, You will find good usage for GOTO as a practical example that General Rules are not for All Use Cases and great programmers know when to break the rules. I’m not saying go and use GOTO or saying Ring add things like that. But the ability to break more than one loop and/or the ability to break the loop from sub functions is practical for small programs. Anyway these are some of the small new things added by the language (Not the big idea). 63.14 Why Ring uses ‘See’, ‘Give’, ‘But’ and ‘Ok’ Keywords? See and Give are selected not to be “opposite actions” but to reflect what I want to do as a programmer. When I want to see something on the screen I use ‘See’. When I want to give some input to the program I use ‘Give’. My selection of “but” and “ok” is based on selecting keywords that can be written quickly. Also using “but” is easy to remember than elseif/elif/elsif where each language select a different keyword. In Ring 1.1 All of this is just an option. You can use ‘Put’ and ‘Get’ instead of ‘See’ and ‘Give’ You can use ‘elseif’ and ‘end’ insetad of ‘But’ and ‘Ok’ It’s your choice. In Ring we have syntax flexibility where we provide more than one style. Also you can change the language keywords and operators. Also you can define new natural languages too. 63.12. Why the ability to define your own languages Instead of just handing over the syntax so you can parse it using whatever code you like? 747
769.
Ring Documentation, Release1.2 63.15 What is the philosophy behind data types in Ring? The Ring programming language is designed to be SMALL. The language provides the basic constructs that you need to do anything! One of the goals is to keep the basic constructs simple and small as possible. Using Lists in Ring you can • Create Arrays (one data type) • Create Lists (Mix of data types) • Create Tree (Nested arrays) • Use String Index (Looks like Dictionary/Hash Table) The same principle is applied to Numbers • You can use the number for int value • You can use the number for double value • You can use the number for Boolean value (True/False) The sample principle is applied for Strings • You can use the string for storing one character • You can use the string for storing text (one or many lines) • You can use the string for storing binary data • You can use the string for storing date • You can use the string for storing time • You can use the string for storing NULL values (empty strings) And we have Object Oriented Support + Operator Overloading where the programmer can define new data types and use them as default types defined by the language So We have • A small and simple language that someone can pick in little days • A fast language that provide primitive types (String ? Number ? List ? Object) • A flexible language that can be extended using OOP to add new types according to the application domain 63.16 What about the Boolean values in Ring? You can use true for 1 and false for 0 when you test the result of Boolean expressions in your code. Just when you print the value using the see command you will see 1 for (true) and 0 for (false) Why ? Because Ring contains only 4 types of variables 1. Number 2. String 3. List 63.15. What is the philosophy behind data types in Ring? 748
770.
Ring Documentation, Release1.2 4. Object The first type (Number) is used to represent int, double and Boolean values. The second type (String) is used to represent char, array of characters, date and time. The third type (List) is used to represent Arrays of one type, Arrays of more than one type, Hash (Dictionary), Tree, etc. The object can be an object created from a Ring class (Any Class) or just a C Pointer that we get from calling a C/C++ function/method. Why ? The Ring is designed to give the programmer/developer the most simple constructs that can be used to do everything. The programmer/developer can customize the language by creating new classes (and use operator overloading) to get more types that he care about according to the problem domain. Why ? Because simple is better, and easy to learn and remember! And this provide flexibility to convert between high level types that can be represented using the same basic type 63.17 What is the goal of including the “Main” function in Ring? The main function is very important, you need it when you want to write statements that uses local variables instead of the Global scope. Example: x = 10 myfunc() See "X value = " + X # here I expect that x will be (10) # but I will get another value (6) because myfunc() uses x ! Func myfunc for x = 1 to 5 See x + nl next Output: 1 2 3 4 5 X value = 6 Now using the Main function Func Main x = 10 myfunc() See "X value = " + X Func myfunc for x = 1 to 5 See x + nl next 63.17. What is the goal of including the “Main” function in Ring? 749
771.
Ring Documentation, Release1.2 Output 1 2 3 4 5 X value = 10 63.18 Why the list index start from 1 in Ring? It’s about how we count in the real world, when we have three apples in our hand we say 1 2 3 We don’t start from 0 The question must be why the other languages start from 0 ? The answer is, because this is related to the machine and how we deal with values and memory address. Example we have array called myarray[5] In memory : myarray will have an address The first item will be stored in that address The second item will come after that address and so on Now when we need to point to the first item we need the address of myarray So we type myarray[0] because myarray + 0 result will still point to the first item for the second item myarray[1] because myarray + 1 result will point to the second item and so on In Low Level languages or languages near to the machine it’s good to be like this But for high level language designed for applications it’s better to be natural Example mylist = [1,2,3,4,5] for x = 1 to len(mylist) see x + nl next In the previous example we start from 1 to the length of the array if the index starts from 0 we will write for x = 0 to len(mylist)-1 or remember the for loop in other languages for(x=0 ; x<nMax ; x++ ) You will use the < operator ! 63.19 Is there constructor methods in Ring? When you create new object for example 63.18. Why the list index start from 1 in Ring? 750
772.
Ring Documentation, Release1.2 new point 1 - Ring will allocate dynamic memory space to be used for the new object attributes that Ring doesn’t know anything about them. 2 - Ring will change the current local scope and the current object scope to use the object state created in step (1) 3 - Ring will move the execution to the class Region (After the class name and before any methods) 4 - Any Instructions/Code in the class region will be executed as any Ring code 5 - Control is moved from the class region to the location of (new point) once we reach the end of the class region or we uses a Return command. So All attributes that added to the object are dynamic attributes, this mean that you can control what attributes will be added through the runtime. Example: $3D = False see new point $3D = True see new point class point x y if not $3D return ok z Output: x: NULL y: NULL x: NULL y: NULL z: NULL You have an option to call init() method directly when you create a new object This method can do anything with the object attributes as it will be called after creating the object and executing the class region code. p1 = new point3d(100,200,300) see p1 class point3d x y z func init p1,p2,p3 x=p1 y=p2 z=p3 63.20 What happens when we create a new object? 1- When you create an object, the class region code will be executed and you will have the object attributes based on the code in that region 2- Ring don’t care about the object methods until you start calling a method 3- When you call a method, Ring will check the object class and the class parent (if you are using inheritance) and will collect the methods for you to be used now or later from any object that belong to the same class. 63.20. What happens when we create a new object? 751
773.
Ring Documentation, Release1.2 4- Since methods are dynamic and each object get the method from the class, you can after creating objects, add new methods and use it with the object or any object created or will be created from the same class. Example: o1 = new point {x=10 y=20 z=30} o2 = new point {x=100 y=200 z =300} addmethod(o1,"print", func { see x + nl + y + nl + z + nl } ) o1.print() o2.print() class point x y z Output: 10 20 30 100 200 300 63.21 Can we use the attributes by accessing the Getter and Setter methods? Yes we can, The setter/getter methods are called automatically when you start using the attributes from outside the class Also you can call the methods instead of using the attributes. It’s your choice. Example: o1 = new Developer o1.name = "Mahmoud" see o1.name + nl o1 { name = "Gal" see name } o1 { name = "Bert" see name } o1.setname("Marino") see o1.getname() Class Developer name language = "Ring Programming Language" func setname value see "Message from SetName() Function!" + nl name = value + " - " + language func getname see "Message from GetName() Function!" + nl + nl return "Mr. " + name + nl Output Message from SetName() Function! Message from GetName() Function! 63.21. Can we use the attributes by accessing the Getter and Setter methods? 752
774.
Ring Documentation, Release1.2 Mr. Mahmoud - Ring Programming Language Message from SetName() Function! Message from GetName() Function! Mr. Gal - Ring Programming Language Message from SetName() Function! Message from GetName() Function! Mr. Bert - Ring Programming Language Message from SetName() Function! Message from GetName() Function! Mr. Marino - Ring Programming Language 63.22 Why should a search of global names be made while defining the class attributes? The question is why we don’t avoid conflicts with global variable names when we define the class attributes ? At first remember that using the optional $ mark in the global variables names solve the problem. Also using the Main function and avoiding global variables may help. The Answer: Ring is a dynamic language We can in the run-time determine the class attributes (Add/Remove) We can execute (any code) while defining the class attributes Example (1) oPerson = new Person Class Person See "Welcome to the Ring language" Example (2) Customize attributes based on global variable value $debug = true oPerson = new Person see oPerson Class Person if $debug date=date() time=time() ok In the previous example when we have the $debug flag set to true, we will add the Date and Time attributes to the object state. Example (3) Store the object index based on global variable $ObjectsCount = 0 oPerson = new Person see oPerson oPerson2 = new Person see oPerson2 63.22. Why should a search of global names be made while defining the class attributes? 753
775.
Ring Documentation, Release1.2 Class Person $ObjectsCount++ nIndex = $ObjectsCount Output: nindex: 1.000000 nindex: 2.000000 Common Example: • Connect to the database then get table columns (Using global Variable/Object). • Create class attributes based on the column names. • Later when you modify the database - you may don’t need to modify your code. It’s flexibility but remember that power comes with great responsibility. 63.23 Why Ring doesn’t avoid the conflict between Global Variables and Class Attributes Names? In this use case we have 1 - Global Variable defined without a special mark like $ 2 - Class contains Attributes defined using a special syntax (where we type the attribute name directly after the class) 3 - The Attributes are defined in the class region that allows writing code and using global variables If I will accepted your proposal about changing how Ring find variables in the class region I must break one of the previous three features which will lead to more problems that are more important than this problem. I don’t like changing the feature number (1) because I would like to keep Ring code more clean and let the programmer decide when to use $ or not. I don’t like changing the feature number (2) because I like this feature and I don’t like forcing the programmer to type self.attribute I don’t like changing the feature number (3) because it’s very important in many applications to access global variables in the class region. So what was my decision ? I decided to leave this case for the programmer who will decide what to do to avoid this special case 1 - The programmer can avoid using global variables (Better) and can use the Main function (Optional) 2 - The programmer can use $ before the variable name or any mark like global_ or g_ 3 - The programmer can use self.attribute after the class name to define the attributes In general, for small programs you can use global variables and functions. For large programs, use classes and objects and small number of global variables or avoid them at all. 63.24 Where can I write a program and execute it? Run the Ring Notepad where you can write/execute programs. If you want to run programs using the command line 63.23. Why Ring doesn’t avoid the conflict between Global Variables and Class Attributes Names? 754
776.
Ring Documentation, Release1.2 Add Ring/bin folder to the path then 63.25 How to get the file size using ftell() and fseek() functions? The next function can be used to get the file size without reading the file! func getFileSize fp C_FILESTART = 0 C_FILEEND = 2 fseek(fp,0,C_FILEEND) nFileSize = ftell(fp) fseek(fp,0,C_FILESTART) return nFileSize Note: The previous function take the fp (file pointer) as parameter, We can get the fp from opening the file using fopen() function. fp = fopen("filename","r") see "File Size : " + getFileSize(fp) + nl Another solution (Read the file) see len(read("filename")) 63.26 How to get the current source file path? We can use the next function to get the current source file path then we can add the path variable to the file name cPath = CurrentPath() func currentpath cFileName = filename() for x = len(cFileName) to 1 step -1 if cFileName[x] = "/" return left(cFileName,x-1) ok next return cFileName 63.27 What about predefined parameters or optional parameters in functions? if you want to use predefined parameters or optional parameters Just accept a list that works like hash/dictionary Example sum([ :a = 1, :b = 2]) sum([ :a = 1 ]) sum([ :b = 2 ]) func sum pList if plist[:a] = NULL pList[:a] = 4 ok 63.25. How to get the file size using ftell() and fseek() functions? 755
777.
Ring Documentation, Release1.2 if plist[:b] = NULL pList[:b] = 5 ok see pList[:a] + pList[:b] + nl Output 3 6 6 63.28 How to print keys or values only in List/Dictionary? If you want to print keys only or values only just select the index of the item (one or two). Example C_COUNTRY = 1 C_CITY = 2 mylist = [ :KSA = "Riyadh" , :Egypt = "Cairo" ] for x in mylist see x[C_COUNTRY] + nl next for x in mylist see x[C_CITY] + nl next Output ksa egypt Riyadh Cairo 63.29 Why I get a strange result when printing nl with lists? In the next code list = 1:5 # list = [1,2,3,4,5] see list + nl New Line will be added to the list then the list will be printed, the default print of the lists will print a newline at the end, You added new newline and You have now 2 newlines to be printed. See <Expr> The see command just print the final result of the expression, the expression will be evaluated as it nl = char(13) + char(10) # just a variable that you can change to anything ! The + is an operator 63.28. How to print keys or values only in List/Dictionary? 756
778.
Ring Documentation, Release1.2 string + string ---> new string string + number ---> new string number + number ---> new number number + string ---> new number list + item —> nothing new will be created but the item will be added to the same list Exception number + nl ?> New String This exception is added to easily print numbers then new line. No need for this with printing lists because after printing the last item we already get a new line. 63.30 Could you explain the output of the StrCmp() function? At first remember that you can check strings using ‘=’ operator directly. see strcmp("hello","hello") + nl + strcmp("abc","bcd") + nl + strcmp("bcd","abc") + nl if the two strings are the same then it returns 0 abc and bcd aren’t the same. in the second line it returns -1 and in the third line it returns 1 In the second line we compare between “abc” and “bcd” Not equal because the first letter in “abc” = “a” and the first letter in “bcd” = “b” So we have “a” != “b” and “a” < “b” So we get output = -1 In the third line we have “bcd” and “abc” the first letter in “bcd” is “b” and the first letter in “abc” is “a” So we have “b” != “a” and “b” > “a” So we get output = 1 Note: ASCII(“a”) = 97 and ASCII(“b”) = 98 So “a” < “b” because 97 < 98 63.31 How to use many source code files in the project? Example: I have the next folder C:LRing Contains the next files C:LRingt1.ring C:LRingmylib.ring C:LRinglibsmylib2.ring 63.30. Could you explain the output of the StrCmp() function? 757
779.
Ring Documentation, Release1.2 The file t1.ring contains the next code load "mylib.ring" load "libsmylib2.ring" myfunc() test() The file mylib.ring contains the next code func myfunc see "message from myfunc"+nl The file libsmylib2.ring contains the next code func test see "message from test" + nl from the folder C:LRing If Ring is not added to the path you can add it or use the next command set path=%path%;c:ringbin; Where c:ring is the Ring folder Now run Ring t1.ring Output message from myfunc message from test 63.32 Why this example use the GetChar() twice? The GetChar() function accept one character from the keyboard buffer In this example While True See " Main Menu (1) Say Hello (2) Exit " Option = GetChar() GetChar() GetChar() # End of line # the previous two lines can be replaced with the next line # Give Option if Option = 1 see "Enter your name : " give cName see "Hello " + cName else bye ok End 63.32. Why this example use the GetChar() twice? 758
780.
Ring Documentation, Release1.2 We uses GetChar() Three times The first time we get the user option Option = GetChar() But in the second and the third times (We accept the new line characters from the buffer) GetChar() GetChar() # End of line Example : when the user select the option number 1 then press ENTER We have Three Characters • The first character is : Number 1 • The second character is : CHAR(13) • The third character is : CHAR(10) Because Windows uses CHAR(13) and CHAR(10) for each new line ( i.e. CR+LF ) 63.33 How to use NULL and ISNULL() function? when we try to use uninitialized variable in the Ring programming language, we get a clear runtime error message Example See x Output Line 1 Error (R24) : Using uninitialized variable : x in file testsseeuninit.ring The same happens when you try to access uninitialized attributes Example o1 = new point see o1 see o1.x class point x y z Output x: NULL y: NULL z: NULL Line 3 Error (R24) : Using uninitialized variable : x in file testsseeuninit2.ring if you want to check for the error, just use Try/Catch/End Try see x Catch See "Sorry, We can't use x!" + nl Done Output 63.33. How to use NULL and ISNULL() function? 759
781.
Ring Documentation, Release1.2 Sorry, We can't use x! Now we will talk about NULL and ISNULL() Since we get error message when we deal with uninitialized variables We can check these errors using Try/Catch/Done, So we uses NULL and ISNULL() for dealing with Strings. NULL is a variable contains an empty string ISNULL() is a function that returns true (1) if the input is an empty string or just a string contains “NULL” This because we need to test these values (empty strings) and strings contains “NULL” that sometimes come from external resource like DBMS. Example See IsNull(5) + nl + # print 0 IsNull("hello") + nl + # print 0 IsNull([1,3,5]) + nl + # print 0 IsNull("") + nl + # print 1 IsNull("NULL") # print 1 63.34 How to print lists that contains objects? In this example we will see how we can print a list contains objects. aList = [[1,2,3] , new point(1,2,3), new point(1,2,3)] see "print the list" + nl see alist see "print the item (object)" + nl see alist[2] class point x y z func init p1,p2,p3 x=p1 y=p2 z=p3 Output print the list 1 2 3 x: 1.000000 y: 2.000000 z: 3.000000 x: 1.000000 y: 2.000000 z: 3.000000 print the item (object) x: 1.000000 y: 2.000000 z: 3.000000 63.35 How to insert an item to the first position in the list? To insert an item we can use the insert(aList,nIndex,Value) function. 63.34. How to print lists that contains objects? 760
782.
Ring Documentation, Release1.2 aList = 1:5 insert(aList,0,0) See aList # print numbers from 0 to 5 63.36 How to print new lines and other characters? To print new line we can use the nl variable. See "Hello" + nl or we can use multi-line literal as in the next example See "Hello " if we want to print other characters we can use the char(nASCII) function See char(109) + nl + # print m char(77) # print M 63.37 Why we don’t use () after the qApp class name? When we use RingQt to create GUI application, we uses () after the class name when we create new objects for example. new qWidget() { setWindowTitle("Hello World") resize(400,400) show() } but before doing that we create an object from the qApp class and we don’t use () after that Load "guilib.ring" app = new qApp { win=new qWidget() { setwindowtitle(:test) show() } exec() } Using () after the class name means calling the init() method in the class and passing parameters to this method. If we used () while no init() method in the class we get the expected error message. The class qApp don’t have this method while the other classes have it because they need it to create an object using a function that return a pointer to that object and this pointer will be stored in an attribute called pObject, for more information see ring_qt.ring file which contains the classes. 63.38 Why the window title bar is going outside the screen? When we write the next code 63.36. How to print new lines and other characters? 761
783.
Ring Documentation, Release1.2 Load "guilib.ring" app = new qApp { win=new qWidget() { setwindowtitle(:test) setGeometry(0,0,200,200) show() } exec() } I would expect that the window will run at the point (0,0) with (200,200) size but the actual result is that the window title bar is going outside the screen. This is related to the behavior of Qt framework. The next code will avoid the problem load "guilib.ring" new qApp { new qWidget() { move(0,0) resize(200,200) show() } exec() } 63.39 How to create an array of buttons in GUI applications? Check the next example: Load "guilib.ring" App1 = new qApp { win1 = new qWidget() { move(0,0) resize(500,500) new qPushButton(win1) { settext("OK") setclickevent("click()") } btn1 = new qPushButton(win1) { setgeometry(100,100,100,30) settext("Button1") } btn2 = new qPushButton(win1) { setgeometry(200,100,100,30) settext("Button2") } 63.39. How to create an array of buttons in GUI applications? 762
784.
Ring Documentation, Release1.2 button = [btn1, btn2] show() } exec() } func click button[1] { settext ("Button3") } button[2] { settext ("Button4") } 63.40 How to Close a window then displaying another one? This example demonstrates how to close a window and show another one Load "guilib.ring" app=new qApp { frmBefore=new Qwidget() { setWindowTitle("before!") resize(300,320) move(200,200) button=new qPushButton(frmBefore) { setText("Close") setClickEvent("frmBefore.close() frmMain.show()") } show() } frmMain=new Qwidget() { setWindowTitle("After!") resize(300,320) move(200,200) } exec() } 63.41 How to create a Modal Window? This example demonstrates how to create a modal window load "guilib.ring" app=new qApp { 63.40. How to Close a window then displaying another one? 763
785.
Ring Documentation, Release1.2 frmStart=new Qwidget() { setWindowTitle("The First Window") resize(300,320) move(200,200) button=new qPushButton(frmStart) { setText("Show Modal Window") resize(200,30) setClickEvent("frmModal.show()") } new qPushButton(frmStart) { setText("Close Window") move(0,50) resize(200,30) setClickEvent("frmStart.Close()") } show() } frmModal =new Qwidget() { setWindowTitle("Modal Window") resize(300,320) move(200,200) setparent(frmStart) setwindowmodality(true) setwindowflags(Qt_Dialog) } exec() } Related Documents • http://doc.qt.io/qt-5/qtwidgets-widgets-windowflags-example.html • http://doc.qt.io/qt-5/qt.html#WindowType-enum • http://doc.qt.io/qt-5/qwindow.html#setParent • http://doc.qt.io/qt-5/qt.html#WindowModality-enum 63.42 How can I disable maximize button and resize window? Use the method setWindowFlags() Load "guilib.ring" app1 = new qapp { win1 = new qwidget() { setwindowtitle("First") setgeometry(100,100,500,500) 63.42. How can I disable maximize button and resize window? 764
786.
Ring Documentation, Release1.2 new qpushbutton(win1) { setgeometry(100,100,100,30) settext("close") setclickevent("app1.quit()") } new qpushbutton(win1) { setgeometry(250,100,100,30) settext("Second") setclickevent("second()") } showmaximized() } exec() } func second win2 = new qwidget() { setwindowtitle("Second") setgeometry(100,100,500,500) setwindowflags(Qt_dialog) show() } 63.43 How to use SQLite using ODBC? In Ring 1.1 we have native support for SQLite, so you don’t need to use it through ODBC. Also we can access SQLite through RingQt. The answer to your question pODBC = odbc_init() odbc_connect(pODBC,"DRIVER=SQLite3 ODBC Driver;Database=mydb.db;LongNames=0;"+ "Timeout=1000;NoTXN=0;SyncPragma=NORMAL;StepAPI=0;") odbc_execute(pODBC,"create table 'tel' ('ID','NAME','PHONE');") odbc_execute(pODBC,"insert into 'tel' values ('1','Mahmoud','123456');") odbc_execute(pODBC,"insert into 'tel' values ('2','Ahmed','123456');") odbc_execute(pODBC,"insert into 'tel' values ('3','Ibrahim','123456');") odbc_execute(pODBC,"select * from tel") + nl nMax = odbc_colcount(pODBC) See "Columns Count : " + nMax + nl while odbc_fetch(pODBC) See nl for x = 1 to nMax see odbc_getdata(pODBC,x) if x != nMax see " - " ok next end odbc_disconnect(pODBC) odbc_close(pODBC) Output: Columns Count : 3 63.43. How to use SQLite using ODBC? 765
787.
Ring Documentation, Release1.2 1 - Mahmoud - 123456 2 - Ahmed - 123456 3 - Ibrahim - 123456 The program will create the file : mydb.db Note : when I print the odbc drivers I see the long list that includes SQLite3 ODBC Driver - UsageCount=1 SQLite ODBC Driver - UsageCount=1 SQLite ODBC (UTF-8) Driver - UsageCount=1 And I’m using “SQLite3 ODBC Driver”. 63.44 Can I connect to dbase/harbour database? You can connect to any database using ODBC To connect to xbase files (*.DBF) See "Using DBF Files using ODBC" + nl pODBC = odbc_init() See "Connect to database" + nl odbc_connect(pODBC,"Driver={Microsoft dBase Driver (*.dbf)};"+ "datasource=dBase Files;DriverID=277") See "Select data" + nl odbc_execute(pODBC,"select * from tel.dbf") nMax = odbc_colcount(pODBC) See "Columns Count : " + nMax + nl while odbc_fetch(pODBC) See "Row data:" + nl for x = 1 to nMax see odbc_getdata(pODBC,x) + " - " next end See "Close database..." + nl odbc_disconnect(pODBC) odbc_close(pODBC) Output Using DBF Files using ODBC Connect to database Select data Columns Count : 3 Row data: Ahmad - Egypt - 234567 - Row data: Fady - Egypt - 345678 - Row data: Shady - Egypt - 456789 - Row data: Mahmoud - Egypt - 123456 - Close database... Also you can connect to a Visual FoxPro database (requires installing Visual FoxPro driver) See "ODBC test 6" + nl pODBC = odbc_init() See "Connect to database" + nl odbc_connect(pODBC,"Driver={Microsoft Visual FoxPro Driver};"+ "SourceType=DBC;SourceDB=C:PWCT19ssbuildPWCTDATACH1Datamydata.dbc;") 63.44. Can I connect to dbase/harbour database? 766
788.
Ring Documentation, Release1.2 See "Select data" + nl see odbc_execute(pODBC,"select * from t38") + nl nMax = odbc_colcount(pODBC) See "Columns Count : " + nMax + nl while odbc_fetch(pODBC) See "Row data:" + nl for x = 1 to nMax see odbc_getdata(pODBC,x) + " - " next end See "Close database..." + nl odbc_disconnect(pODBC) odbc_close(pODBC) 63.45 Why setClickEvent() doesn’t see the object methods directly? setClickEvent(cCode) take a string contains code. The code will be executed when the event happens. Ring support Many Programming Paradigms like Procedural, OOP, Functional and others. But when you support many paradigms at the language level you can’t know which paradigm will be used so you have two options 1. Provide General Solutions that works with many programming paradigms. 2. Provide Many Specific solutions where each one match a specific paradigm. setClickEvent() and others belong to (General Solutions that works with many programming paradigms). You just pass a string of code that will be executed without any care about classes and objects. This code could be anything like calling a function, calling a method and setting variable value. Some other languages force you to use OOP and call methods for events. Also some other languages uses anonymous functions that may get parameters like the current object. Now we have the general solution (not restricted with any paradigm), In the future we may add specific solutions that match specific paradigms (OOP, Functional, Declarative and Natural). 63.46 Why I get Calling Function without definition Error? Each program follow the next order 1 - Loading Files 2 - Global Variables and Statements 3 - Functions 4 - Packages, Classes and Methods So what does that mean ? 1. **** No Functions comes After Classes **** 2. **** No command is required to end functions/methods/classes/packages **** Look at this example See "Hello" test() func test see "message from the test function!" + nl class test 63.45. Why setClickEvent() doesn’t see the object methods directly? 767
789.
Ring Documentation, Release1.2 In the previous example we have a function called test() so we can call it directly using test() In the next example, test() will become a method See"Hello" test() # runtime error message class test func test # Test() now is a method (not a function) see "message from the test method!" + nl The errors comes when you define a method then try calling it directly as a function. The previous program must be See"Hello" new test { test() } # now will call the method class test func test # Test() now is a method (not a function) see "message from the test method!" + nl 63.47 Can Ring work on Windows XP? Ring can work on Windows XP and load extensions without problems. Just be sure that the extension can work on Windows XP and your compiler version support that (modern compilers requires some flags to support XP) Check this topic https://blogs.msdn.microsoft.com/vcblog/2012/10/08/windows-xp-targeting-with-c-in-visual-studio- 2012/ For example, We added /link /SUBSYSTEM:CONSOLE,"5.01" To the batch file to support Windows XP See : https://github.com/ring-lang/ring/blob/master/src/buildvccomplete.bat 63.48 How to extend RingQt and add more classes? You have many options In general you can extend Ring using C or C++ code Ring from Ring code you can call C Functions or use C++ Classes & Methods This chapter in the documentation explains this part in the language http://ring- lang.sourceforge.net/doc/extension.html For example the next code in .c file can be compiled to a DLL file using the Ring library (.lib) #include "ring.h" RING_FUNC(ring_ringlib_dlfunc) { printf("Message from dlfunc"); } 63.47. Can Ring work on Windows XP? 768
790.
Ring Documentation, Release1.2 RING_API void ringlib_init(RingState *pRingState) { ring_vm_funcregister("dlfunc",ring_ringlib_dlfunc); } Then from Ring you can load the DLL file using LoadLib() function then call the C function that called dlfunc() as any Ring function. See "Dynamic DLL" + NL LoadLib("ringlib.dll") dlfunc() Output Dynamic DLL Message from dlfunc When you read the documentation you will know about how to get parameters like (strings, numbers, lists and objects) And how to return a value (any type) from you function. From experience, when we support a C library or C++ Library We discovered that a lot of functions share a lot of code To save our time, and to quickly generate wrappers for C/C++ Libraries to be used in Ring We have this code generator https://github.com/ring-lang/ring/blob/master/extensions/codegen/parsec.ring The code generator is just a Ring program < 1200 lines of Ring code The generator take as input a configuration file contains the C/C++ library information like Functions Prototype, Classes and Methods, Constants, Enum, Structures and members , etc. Then the generator will generate *.C File for C libraries (to be able to use the library functions) *.CPP File for C++ libraries (to be able to use C++ classes and methods) *.Ring File (to be able to use C++ classes as Ring classes) *.RH file (Constants) To understand how the generator work check this extension for the Allegro game programming library https://github.com/ring-lang/ring/tree/master/extensions/ringallegro At first we have the configuration file https://github.com/ring-lang/ring/blob/master/extensions/ringallegro/allegro.cf To write this file, i just used the Allegro documentation + the Ring code generator rules Then after executing the generator using this batch file https://github.com/ring-lang/ring/blob/master/extensions/ringallegro/gencode.bat or using this script https://github.com/ring-lang/ring/blob/master/extensions/ringallegro/gencode.sh I get the generated source code file https://github.com/ring-lang/ring/blob/master/extensions/ringallegro/ring_allegro.c 63.48. How to extend RingQt and add more classes? 769
791.
Ring Documentation, Release1.2 The generated source code file (ring_allegro.c) is around 12,000 Lines of code (12 KLOC) While the configuration file is less than 1 KLOC To build the library (create the DLL files) https://github.com/ring-lang/ring/blob/master/extensions/ringallegro/buildvc.bat Also you can check this extension for the LibSDL Library https://github.com/ring-lang/ring/tree/master/extensions/ringsdl After this know you should know about 1 - Writing the configuration file 2 - Using the Code Generator 3 - Building your library/extension 4 - Using your library/extension from Ring code Let us move now to you question about Qt We have RingQt which is just an extension to ring (ringqt.dll) You don’t need to modify Ring. 1. You just need to modify RingQt 2. Or extend Ring with another extension based on Qt (but the same Qt version) For the first option see the RingQt extension https://github.com/ring-lang/ring/tree/master/extensions/ringqt Configuration file https://github.com/ring-lang/ring/blob/master/extensions/ringqt/qt.cf To generate the source code https://github.com/ring-lang/ring/blob/master/extensions/ringqt/gencode.bat https://github.com/ring-lang/ring/blob/master/extensions/ringqt/gencode.sh https://github.com/ring-lang/ring/blob/master/extensions/ringqt/gencodeandroid.bat To build the DLL/so/Dylib files https://github.com/ring-lang/ring/blob/master/extensions/ringqt/buildmingw32.bat https://github.com/ring-lang/ring/blob/master/extensions/ringqt/buildgcc.sh https://github.com/ring-lang/ring/blob/master/extensions/ringqt/buildclang.sh Study RingQt Learn about the options that you have 1. wrapping a Qt class directly 2. Creating a new class then wrapping your new class For the second option (in the previous two points or in the two points before that) You will create new classes in C++ code Then you merge these classes to RingQt or provide special DLL for them (your decision) If your work is general (will help others) just put it to RingQt. 63.48. How to extend RingQt and add more classes? 770
792.
Ring Documentation, Release1.2 if your work is special (to specific application) just put it in another extension. 63.49 How to add Combobox and other elements to the cells of a QTableWidget? Check the next code Load "guilib.ring" New qApp { win1 = new qMainWindow() { setGeometry(100,100,1100,370) setwindowtitle("Using QTableWidget") Table1 = new qTableWidget(win1) { setrowcount(10) setcolumncount(10) setGeometry(0,0,800,400) setselectionbehavior(QAbstractItemView_SelectRows) for x = 1 to 10 for y = 1 to 10 item1 = new qtablewidgetitem("R"+X+"C"+Y) setitem(x-1,y-1, item1) next next cmb = new QComboBox(Table1) { alist = ["one","two","three","four","five"] for x in aList additem(x,0) next } setCellWidget(5, 5, cmb) } setcentralwidget(table1) show() } exec() } 63.50 How to perform some manipulations on selected cells in QTableWidget? Check the next sample Load "guilib.ring" New qApp { win1 = new qMainWindow() { setGeometry(100,100,800,600) setwindowtitle("Using QTableWidget") Table1 = new qTableWidget(win1) { setrowcount(10) setcolumncount(10) setGeometry(10,10,400,400) 63.49. How to add Combobox and other elements to the cells of a QTableWidget? 771
793.
Ring Documentation, Release1.2 for x = 1 to 10 for y = 1 to 10 item1 = new qtablewidgetitem("10") setitem(x-1,y-1,item1) next next } btn1 = new qPushButton(win1) { setText("Increase") setGeometry(510,10,100,30) setClickEvent("pClick()") } show() } exec() } func pClick for nRow = 0 to Table1.rowcount() - 1 for nCol = 0 to Table1.columncount() - 1 Table1.item(nRow,nCol) { if isSelected() setText( "" + ( 10 + text()) ) ok } next next 63.50. How to perform some manipulations on selected cells in QTableWidget? 772
794.
CHAPTER SIXTYFOUR LANGUAGE REFERENCE In thischapter we will learn about • Language keywords • Language Functions • Compiler Errors • Runtime Errors • Language Grammar • Virtual Machine (VM) Instructions 64.1 Language Keywords Keywords Count : 46 • again • and • but • bye • call • case • catch • changeringkeyword • changeringoperator • class • def • do • done • else • elseif • end • exit 773
795.
Ring Documentation, Release1.2 • for • from • func • get • give • if • import • in • load • loadsyntax • loop • new • next • not • off • ok • on • or • other • package • private • put • return • see • step • switch • to • try • while 64.2 Language Functions Functions Count : 217 acos() add() addattribute() adddays() addmethod() ascii() asin() assert() atan() atan2() attributes() binarysearch() callgc() ceil() cfunctions() char() chdir() classes() classname() clearerr() clock() clockspersecond() 64.2. Language Functions 774
Ring Documentation, Release1.2 • Error (C7) : Error in list items • Error (C8) : Parentheses ‘)’ is missing • Error (C9) : Brackets ‘]’ is missing • Error (C10) : Error in parent class name • Error (C11) : Error in expression operator • Error (C12) :No class definition • Error (C13) : Error in variable name • Error (C14) : Try/Catch miss the Catch keyword! • Error (C15) : Try/Catch miss the Done keyword! • Error (C16) : Error in Switch statement expression! • Error (C17) : Switch statement without OFF • Error (C18) : Missing closing brace for the block opened! • Error (C19) : Numeric Overflow! • Error (C20) : Error in package name • Error (C21) : Unclosed control strucutre, ‘again’ is missing • Error (C22) : Function redefinition, function is already defined! • Error (C23) : Using ‘(‘ after number! • Error (C24) : The parent class name is identical to the subclass name • Error (C25) : Trying to access the self reference after the object name” 64.4 Runtime Errors • Error (R1) : Cann’t divide by zero ! • Error (R2) : Array Access (Index out of range) ! • Error (R3) : Calling Function without definition ! • Error (R4) : Stack Overflow ! • Error (R5) : Can’t access the list item, Object is not list ! • Error (R6) : Variable is required • Error (R7) : Can’t assign to a string letter more than one character • Error (R8) : Variable is not a string • Error (R9) : Using exit command outside loops • Error (R10) : Using exit command with number outside the range • Error (R11) : error in class name, class not found! • Error (R12) : error in property name, property not found! • Error (R13) : Object is required • Error (R14) : Calling Method without definition ! 64.4. Runtime Errors 776
798.
Ring Documentation, Release1.2 • Error (R15) : error in parent class name, class not found! • Error (R16) : Using braces to access unknown object ! • Error (R17) : error, using ‘Super’ without parent class! • Error (R18) : Numeric Overflow! • Error (R19) : Calling function with less number of parameters! • Error (R20) : Calling function with extra number of parameters! • Error (R21) : Using operator with values of incorrect type • Error (R22) : Using loop command outside loops • Error (R23) : Using loop command with number outside the range • Error (R24) : Using uninitialized variable • Error (R25) : Error in package name, Package not found! • Error (R26) : Calling private method from outside the class • Error (R27) : Using private attribute from outside the class • Error (R28) : Using bad data type as step value • Error (R29) : Using bad data type in for loop • Error (R30) : parent class name is identical to child class name • Error (R31) : Trying to destory the object using the self reference • Error (R32) : The CALL command expect a variable contains string! • Error (R33) : Bad decimals number (correct range >= 0 and <=14) ! • Error (R34) : Variable is required for the assignment operation • Error (R35) : Can’t create/open the file! • Error (R36) : The column number is not correct! It’s greater than the number of columns in the list 64.5 Language Grammar Program —> {statement} Statement —> ‘package’ <Identifier> { ‘.’ <Identifier> } Statement —> ‘class’ <Identifier> [ ‘from’ <Identifier> ] Statement —> ‘func’|’def’ <Identifier> [ParaList] Statement —> ‘import’ <Identifier> { ‘.’ <Identifier> } Statement —> ‘private’ Statement —> ‘load’ <Literal> Statement —> ‘loadsyntax’ <Literal> Statement —> ‘changeringkeyword’ <OldKeyword> <NewKeyword> Statement —> ‘changeringoperator’ <OldOperator> <NewOperator> Statement —> ‘see’|’put’ <Expr> 64.5. Language Grammar 777
Ring Documentation, Release1.2 Factor —> ‘call’ <identifier> { ‘.’ <Identifier> } ‘(‘ <Parameters> ‘)’ List —> ‘[’ [ <Expr> { ‘,’ <Expr> } ] ‘]’ Mixer —> { ‘.’ <Identifier> } Mixer —> ‘[’ <Expr> ‘]’ Mixer —> ‘(‘ [ <Expr> [ { ‘,’ <Expr> }] ] ‘)’ Mixer —> ‘{‘ {Statement} ‘}’ AnonymousFunction —> ‘func’|’def’| [<ParaList>] ‘{‘ {Statement} ‘}’ 64.6 Virtual Machine (VM) Instructions Definitions :- • VM : Virtual Machine • Stack : VM Stack • IR : Instruction Register • PC : Program Counter • VP : Variable Pointer • Stack[nSize] : Last Item in the Stack (Last In - First Out) • VV : Variable Value (We have a Pointer to a variable, And we access this variable value) (Stack and Variables) 64.6. Virtual Machine (VM) Instructions 779
801.
Ring Documentation, Release1.2 Operation Description • ICO_PUSHC Add string from the IR to the stack • ICO_PUSHN Add number from the IR to the stack • ICO_PUSHV Replace VP in the stack[nSize] with the variable value • ICO_LOADADDRESS Read variable name from the IR, push VP to the stack • ICO_ASSIGNMENT Stack[nSize-1] VV = Stack[nSize] VV , POP Stack[nSize] • ICO_INC Increment Number in Stack[nSize] by 1 • ICO_LOADAPUSHV The same as ICO_LOADADDRESS then ICO_PUSHV • ICO_NEWLINE Store new line number (debug info) • ICO_FREESTACK Remove all items from the stack , nSize = 0 • ICO_FILENAME Store the source code file name (debug info) • ICO_FREELOADASCOPE Free the Scope List of the current Expression (Jump) Operation Description • ICO_JUMP Set PC to new value from the IR • ICO_JUMPZERO If Stack[nSize] is a number = 0 then Set PC to new value from the IR • ICO_JUMPFOR End of for loop • ICO_JUMPONE If Stack[nSize] is a number = 1 then Set PC to new value from the IR • ICO_JUMPZERO2 As ICO_JUMPZERO but add 1 to the stack (required for many ‘AND’ conditions) • ICO_JUMPONE2 As ICO_JUMPONE but add 1 to the stack (required for many ‘OR’ conditions) (Compare) 64.6. Virtual Machine (VM) Instructions 780
802.
Ring Documentation, Release1.2 Operation Description • ICO_LESSEQUAL If stack[nSize-1] <= stack[nSize] , POP stack[nSize], set Stack[nSize-1] = 1 else set Stack[nSize-1] = 0 • ICO_EQUAL If stack[nSize-1] = stack[nSize] , POP stack[nSize], set Stack[nSize-1] = 1 else set Stack[nSize-1] = 0 • ICO_LESS If stack[nSize-1] < stack[nSize] , POP stack[nSize], set Stack[nSize-1] = 1 else set Stack[nSize-1] = 0 • ICO_GREATER If stack[nSize-1] > stack[nSize] , POP stack[nSize], set Stack[nSize-1] = 1 else set Stack[nSize-1] = 0 • ICO_GREATEREQUAL If stack[nSize-1] >= stack[nSize] , POP stack[nSize], set Stack[nSize-1] = 1 else set Stack[nSize-1] = 0 • ICO_NOTEQUAL If stack[nSize-1] != stack[nSize] , POP stack[nSize], set Stack[nSize-1] = 1 else set Stack[nSize-1] = 0 (Math) Operation Description • ICO_SUM Stack[nSize-1] = Stack[nSize-1] + Stack[nSize] , POP stack[nSize] • ICO_SUB Stack[nSize-1] = Stack[nSize-1] - Stack[nSize] , POP stack[nSize] • ICO_MUL Stack[nSize-1] = Stack[nSize-1] * Stack[nSize] , POP stack[nSize] • ICO_DIV Stack[nSize-1] = Stack[nSize-1] / Stack[nSize] , POP stack[nSize] • ICO_MOD Stack[nSize-1] = Stack[nSize-1] % Stack[nSize] , POP stack[nSize] • ICO_NEG Stack[nSize] = - Stack[nSize-1] • ICO_PLUSPLUS Stack[nSize] = Stack[nSize] + 1 • ICO_MINUSMINUS Stack[nSize] = Stack[nSize] - 1 (Logic) Operation Description • ICO_AND Stack[nSize-1] = Stack[nSize-1] && Stack[nSize] , POP stack[nSize] • ICO_OR Stack[nSize-1] = Stack[nSize-1] || Stack[nSize] , POP stack[nSize] • ICO_NOT Stack[nSize] = ! Stack[nSize] (Lists) 64.6. Virtual Machine (VM) Instructions 781
803.
Ring Documentation, Release1.2 Operation Description • ICO_LISTSTART Start New List in Temp. Memory • ICO_LISTITEM Add List Item • ICO_LISTEND End List • ICO_LOADINDEXADDRESS Stack[nSize-1] = Stack[nSize-1] VV [ Stack[nSize] ] , POP stack[nSize] (Functions) Operation Description • ICO_LOADFUNC Find function • ICO_CALL Call function • ICO_RETURN Return from function • ICO_RETNULL Return NULl from function • ICO_RETFROMEVAL Return after eval() • ICO_RETITEMREF Return the list item reference - not the value • ICO_NEWFUNC Start new function • ICO_BLOCKFLAG Flag to determine where to jump later (after ICO_RETURN) • ICO_FUNCEXE Start executing function • ICO_ENDFUNCEXE End function execution • ICO_ANONYMOUS Anonymous function (User Interface) Operation Description • ICO_PRINT Print value to the standard output • ICO_GIVE Get input from the keyboard (End Program/Loop) 64.6. Virtual Machine (VM) Instructions 782
804.
Ring Documentation, Release1.2 Operation Description • ICO_BYE End execution of VM • ICO_EXITMARK Place to exit to from a loop • ICO_POPEXITMARK Remove exit mark • ICO_EXIT Break from one loop or more • ICO_LOOP Continue to next loop (For Better Performance) Operation Description • ICO_PUSHP Push pointer to the stack • ICO_INCP Increment variable value using pointer • ICO_PUSHPV Push value of variable using variable pointer • ICO_INCJUMP Increment then jump • ICO_INCPJUMP Increment using pointer then jump • ICO_JUMPVARLENUM Jump if variable value is <= numeric value • ICO_JUMPVARPLENUM Jump if variable value (using pointer) <= numeric value • ICO_LOADFUNCP Push function pointer • ICO_PUSHPLOCAL Push pointer to local variable • ICO_INCLPJUMP Increment value using pointer to local variable then jump • ICO_JUMPVARLPLENUM Jump if the variable value (using pointer) <= numeric value • ICO_INCPJUMPSTEP1 Increment value using variable pointer then jump (for loop step = 1) • ICO_JUMPVARPLENUMSTEP1 Increment value using variable pointer then jump (for loop step = 1) (Try-Catch-Done) 64.6. Virtual Machine (VM) Instructions 783
805.
Ring Documentation, Release1.2 Operation Description • ICO_TRY Start try region • ICO_DONE End try region (Duplicate and Range) Operation Description • ICO_DUPLICATE Duplicate stack value • ICO_RANGE Create list from value to value (OOP) Operation Description • ICO_NEWOBJ Create new object, get class name from the IR, push ob- ject pointer to the stack. • ICO_SETSCOPE Called after creating new object, set the active scope to be the object scope. • ICO_LOADSUBADDRESS Get object attribute, push the pointer to the stack. • ICO_LOADMETHOD Find object method • ICO_AFTERCALLMETHOD Used after calling a method - normal case • ICO_AFTERCALLMETHOD2 Used after calling a method - second case • ICO_NEWCLASS Start new class region • ICO_BRACESTART Open brace • ICO_BRACEEND End brace • ICO_IMPORT Import package • ICO_PRIVATE start private attributes region • ICO_SETPROPERTY set attribute value - check for setter. • ICO_CALLCLASSINIT call call init() method. (Other) 64.6. Virtual Machine (VM) Instructions 784
806.
Ring Documentation, Release1.2 Operation Description • ICO_SETREFERENCE Copy by reference • ICO_KILLREFERENCE Remove reference • ICO_ASSIGNMENTPOINTER Determine the left side variable • ICO_BEFOREEQUAL Determine operators like += , -= , ... etc (Bitwise Operators) Operation Description • ICO_BITAND Stack[nSize-1] = Stack[nSize-1] & Stack[nSize] , POP stack[nSize] • ICO_BITOR Stack[nSize-1] = Stack[nSize-1] | Stack[nSize] , POP stack[nSize] • ICO_BITXOR Stack[nSize-1] = Stack[nSize-1] ^ Stack[nSize] , POP stack[nSize] • ICO_BITNOT Stack[nSize] = ! Stack[nSize] • ICO_BITSHL Stack[nSize-1] = Stack[nSize-1] << Stack[nSize] , POP stack[nSize] • ICO_BITSHR Stack[nSize-1] = Stack[nSize-1] >> Stack[nSize] , POP stack[nSize] (For Step) Operation Description • ICO_STEPNUMBER Determine step number in for loop • ICO_POPSTEP POP step number from steps stack • ICO_LOADAFIRST Load the first address of variable name 64.6. Virtual Machine (VM) Instructions 785
807.
CHAPTER SIXTYFIVE RESOURCES In this sectionyou will find resources about the language 65.1 Ring Language Website For news about the language check the website http://ring-lang.net http://ring-lang.sf.net 65.2 Ring Group For questions use the Ring Group (English) https://groups.google.com/forum/#!forum/ring-lang 65.3 Contact the Authors Name : Eng. Mahmoud Samir Fayed Country : Egypt Email : msfclipper@yahoo.com Facebook : https://facebook.com/mahmoudfayed1986 LinkedIn : https://sa.linkedin.com/in/mahmoudfayed1986 Name : Dr. Atif M. Alamri Country : Saudi Arabia Email : atif@ksu.edu.sa LinkedIn : https://sa.linkedin.com/in/dr-atif-alamri-8b341747 Ring Team : http://ring-lang.sourceforge.net/team.html 786
808.
INDEX Access List Itemsby String Index Lists, 95 Access Objects Using Braces Object Oriented Programming, 169 Access String Letters Strings, 97 Accessing the class attributes from braces inside class methods Scope Rules, 498 Add Items Lists, 89 addattribute() Reflection and Meta-programming, 196 AddDays() Date and Time, 105 Adding code to the generated code Code Generator, 562 Adding Hyperlink to QLabel Desktop and Mobile Development, 413 addmethod() Reflection and Meta-programming, 196 Animate Class Game Engine for 2D Games, 334 Animate Events Game Engine for 2D Games, 345 Animation Game Engine for 2D Games, 339 Animation and Functions Game Engine for 2D Games, 340 Anonymous and Nested Functions Functional Programming, 182 Application Class Web Development (CGI Library), 302 Applications How to contribute?, 43 Applications developed in little hours FetchStockData Application, 2 Fifteen Puzzle Game, 3 Introduction, 1 Quotes about Ring, 1 Samples in this book, 5 Squares Puzzle Game, 4 TicTacToe Game, 3 Werdy Application, 4 apppath() Stdlib Functions, 203 Arithmetic Operators Operators, 64 Ascii() Data Type, 112 Assert() Eval() and Debugging, 136 Assignment Operators Operators, 65 attributes() Reflection and Meta-programming, 193 Better Call Command What is new in Ring 1.2?, 27 Better Code Generator for Extensions What is new in Ring 1.1?, 37 Better Documentation What is new in Ring 1.1?, 37 Better Functions What is new in Ring 1.2?, 24 Better Natural Language Programming Support What is new in Ring 1.1?, 29 Better Quality What is new in Ring 1.2?, 27 Better Ring Notepad What is new in Ring 1.2?, 24 Better RingQt What is new in Ring 1.2?, 24 binarydigits() Stdlib Functions, 211 Bitwise Operators Operators, 64 BraceError() Method Natural Language Programming, 252 BraceExprEval Method Natural Language Programming, 251 BraceStart and BraceEnd Methods Natural Language Programming, 250 Branching Control Structures, 67 787
809.
Ring Documentation, Release1.2 Control Structures - Second Style, 74 Control Structures - Third Style, 77 Building From Source Code Building using CMake, 41 Building using MacOS X, 40 Building using Microsoft Windows, 39 Building using Ubuntu Linux, 40 Introduction, 38 Building Games For Android Building the project, 381 Download Requirements and Update the Android SDK, 380 Introduction, 379 Project Folder, 380 Building RingQt Applications for Mobile Comments about developing for Android using RingQt, 484 Download Requirements, 483 Install Qt for Android, 483 Introduction, 482 Update the Android SDK, 483 Building the project Building Games For Android, 381 Building using CMake Building From Source Code, 41 Building using MacOS X Building From Source Code, 40 Building using Microsoft Windows Building From Source Code, 39 Building using Ubuntu Linux Building From Source Code, 40 Call Functions Functions, 84 callgc() Low Level Functions, 537 Calling a function sharing the name with a method in the current class Scope Rules for Functions and Methods, 509 Can I connect to dbase/harbour database? Frequently Asked Questions, 766 Can Ring work on Windows XP? Frequently Asked Questions, 768 capitalized() Stdlib Functions, 205 cfunctions() Reflection and Meta-programming, 186 CGI Support Command Line Options, 535 Change Focus Desktop and Mobile Development, 447 Change Language Keywords Syntax Flexibility, 511 Change Language Operators Syntax Flexibility, 512 Change the ’=’ operator to ’is’ Natural Language Programming, 248 Change the Ring Keyword ’And’ Natural Language Programming, 246 Change the Ring Operator ’+’ Natural Language Programming, 247 changestring() Stdlib Functions, 213 Char() Data Type, 112 ChDir() Function System Functions, 133 Check Character Data Type, 107 Check Data Type Data Type, 106 Check Parameters Count Extension, 549 Check Parameters Type Extension, 550 Classes and Objects Object Oriented Programming, 167 Classes and their Methods to use the default events Desktop and Mobile Development, 477 classes() Reflection and Meta-programming, 190 classname() Reflection and Meta-programming, 192 Clean Natural Code Natural Language Programming, 253 Clearerr() Files, 124 clock() Date and Time, 103 Close Window Event RingLibSDL, 326 ClosPerSecond() Date and Time, 103 Code Generator Adding code to the generated code, 562 Comments in configuration file, 564 Configuration file, 560 Configuration file for the Allegro library, 565 Configuration Files Examples, 578 Defining Constants, 563 Determine Structure Members Types, 563 Enum and Numbers, 564 Executing code during code generation, 564 Filtering using Expressions, 564 function prototype, 560 Introduction, 559 Prefix for Functions Names, 562 Qt configuration file, 568 Index 788
810.
Ring Documentation, Release1.2 Register New Functions, 563 Threads Support, 566 Using configuration file that wrap C++ library, 568 Using the tool, 560 Wrap structures, 562 Wrapping C++ Classes, 567 Command Line Options CGI Support, 535 Generate Object File, 536 Introduction, 521 No Run, 535 Performance, 535 Printing Final Intermediate Code, 530 Printing Instruction Operation Code, 535 Printing Intermediate Code, 528 Printing Rules, 524 Printing Tokens, 522 Comments about developing for Android using RingQt Building RingQt Applications for Mobile, 484 Comments about evaluation Control Structures - First Style, 72 Comments in configuration file Code Generator, 564 Compact Syntax Language Design, 18 Compiler and Virtual Machine (VM) How to contribute?, 43 Compiler Errors Reference, 775 Composition Object Oriented Programming, 170 Configuration file Code Generator, 560 Configuration file for the Allegro library Code Generator, 565 Configuration Files Examples Code Generator, 578 Configure the Apache web server Web Development (CGI Library), 255 Conflict between Class Attributes and Local Variables Scope Rules, 495 Conflict between Global Variables and Class Attributes Frequently Asked Questions, 754 Scope Rules, 494 Conflict between self inside braces and self in the class region Scope Rules, 501 Constructor methods in Ring Frequently Asked Questions, 750 Contact the Autor Resources, 786 Control Structures Branching, 67 Looping, 78 Control Structures - First Style Comments about evaluation, 72 Do Again Loop, 70 Exit, 70 Exit from two loops, 70 Exit/Loop inside sub functions, 71 For In Loop, 69 for in to modify lists, 69 For Loop, 68 Introduction, 66 Loop Command, 71 Looping, 68 Short-circuit evaluation, 71 Step Option, 69 Switch Statement, 67 While Loop, 68 Control Structures - Second Style Branching, 74 Exceptions, 76 For In Loop, 76 For Loop, 75 If Statement, 74 Introduction, 73 Looping, 75 Switch Statement, 74 Control Structures - Third Style Branching, 77 Exceptions, 80 For In Loop, 80 For Loop, 79 If Statement, 77 Introduction, 76 Switch Statement, 77 While Loop, 78 Conversion Data Type, 111 Conversion Class Stdlib Classes, 233 Convert Letters Case Strings, 97 Cookies Web Development (CGI Library), 267 Copy Lists Lists, 93 Copy() Strings, 99 Could you explain the output of the StrCmp() function? Frequently Asked Questions, 757 Create Database MySQL Functions, 151 Create Lists Lists, 89 Create Table and Insert Data MySQL Functions, 152 Index 789
811.
Ring Documentation, Release1.2 Create Window RingLibSDL, 323 Creating a Class for each Window in GUI applications Scope Rules, 500 Creating Menubar Desktop and Mobile Development, 393 Creating more than one window Desktop and Mobile Development, 431 Creating StatusBar Desktop and Mobile Development, 397 Creating the Game Window Game Engine for 2D Games, 334 Creating Toolbar Desktop and Mobile Development, 396 Creating Windows Installer Distributing Ring Application, 520 CRUD Example using MVC Web Development (CGI Library), 288 CurrentDir() Function System Functions, 132 Data Type Ascii(), 112 Char(), 112 Check Character, 107 Check Data Type, 106 Conversion, 111 Dec(), 112 Hex(), 112 Hex2str(), 113 Introduction, 105 IsAlNum(), 108 IsAlpha(), 108 IsCntrl(), 108 IsDigit(), 109 IsGraph(), 109 IsList(), 107 IsLower(), 109 IsNULL(), 107 IsNumber(), 106 IsPrint(), 109 IsPunct(), 110 IsSpace(), 110 IsString(), 106 IsUpper(), 110 IsXdigit(), 110 Number(), 111 Str2Hex(), 113 String(), 111 Type(), 107 Database, ModelBase & ControllerBase classes Web Development (CGI Library), 296 DataType Class Stdlib Classes, 232 Date and Time AddDays(), 105 clock(), 103 ClosPerSecond(), 103 Date(), 103 DiffDays(), 105 Introduction, 102 Time(), 103 TimeList(), 104 Date() Date and Time, 103 DateTime Class Stdlib Classes, 227 dayofweek() Stdlib Functions, 212 Debug Class Stdlib Classes, 231 Dec() Data Type, 112 Decimals() Mathematical Functions, 117 Declarative Programming Declarative programming on the top of Object- Oriented, 242 executing code after the end of object access, 242 Introduction, 238 More Beatiful Code, 243 Objects inside lists, 239 Return object by reference, 240 Declarative programming on the top of Object-Oriented Declarative Programming, 242 Declare parameters Functions, 85 Decrypt() Security and Internet Functions, 164 Deep Copy Variables, 62 Define Declarative Languages Language Design, 21 Define Functions Functions, 84 Define Natural Statements Language Design, 19 Defining Constants Code Generator, 563 Defining Variables and Variables Access Scope Rules, 492 Delete Item From List Lists, 90 Demo Programs Introduction, 136 Language Shell, 137 Main Menu, 137 The Cards Game, 471 Index 790
812.
Ring Documentation, Release1.2 Designed for a clear goal Language Design, 14 Desktop and Mobile Development Adding Hyperlink to QLabel, 413 Change Focus, 447 Classes and their Methods to use the default events, 477 Creating Menubar, 393 Creating more than one window, 431 Creating StatusBar, 397 Creating Toolbar, 396 Display Image using QLabel, 417 Display Scaled Image using QLabel, 426 Drawing using QPainter, 428 Dynamic Objects, 451 Inheritance from GUI Classes, 443 KeyPress and Mouse Move Events, 438 Menubar and StyleSheet Example, 418 Methods to use Events with Events Filter, 480 Movable Label Example, 434 Moving Objects using the Mouse, 439 Notepad Application, 456 Other Widgets Events, 422 Playing Sound, 432 Printing using QPrinter, 430 QLineEdit Events and QMessageBox, 420 QMessagebox Example, 435 QVideoWidget and QMediaPlayer, 414 Regular Expressions, 448 RingQt Classes and their Qt Documentation, 482 Rotate Text, 445 Simple Client and Server Example, 449 The Cards Game, 471 The Difference between Qt and RingQt, 481 The First GUI Application, 383 Using Layout, 384 Using QCheckBox, 410 Using QComboBox Class, 392 Using QDateEdit, 405 Using QDesktopWidget Class, 444 Using QDial, 406 Using QDockWidget, 398 Using QFrame, 415 Using QInputDialog Class, 436 Using qLCDNumber, 433 Using QProgressBar, 402 Using QProgressBar and Timer, 425 Using QRadioButton and QButtonGroup, 411 Using QSlider, 403 Using QSpinBox, 403 Using QTableWidget, 401 Using QTabWidget, 399 Using QTreeView and QFileSystemModel, 390 Using QTreeWidget and QTreeWidgetItem, 391 Using QWebView, 409 Using the QColorDialog Class, 432 Using the QFileDialog Class, 427 Using the QListWidget Class, 387 Using the QTextEdit Class, 386 Using the QTimer Class, 424 Weight History Application, 452 Determine Structure Members Types Code Generator, 563 DiffDays() Date and Time, 105 Dir() Files, 120 direxists() Stdlib Functions, 214 Display Error Message Extension, 550 Display Image RingLibSDL, 323 Display Image using QLabel Desktop and Mobile Development, 417 Display PNG Images RingLibSDL, 324 Display Scaled Image using QLabel Desktop and Mobile Development, 426 Display Transparent Images RingLibSDL, 325 Display Warnings Option What is new in Ring 1.2?, 27 Distributing Applications and Games for Mobile Distributing Ring Application, 521 Distributing Applications for Microsoft Windows Distributing Ring Application, 520 Distributing Ring Application Creating Windows Installer, 520 Distributing Applications and Games for Mobile, 521 Distributing Applications for Microsoft Windows, 520 Introduction, 519 Protecting the Source Code, 520 Using C/C++ Compiler and Linker, 521 Do Again Loop Control Structures - First Style, 70 Documentation How to contribute?, 42 Download Requirements Building RingQt Applications for Mobile, 483 Download Requirements and Update the Android SDK Building Games For Android, 380 Download() Security and Internet Functions, 166 Draw Rectangle RingLibSDL, 324 Index 791
813.
Ring Documentation, Release1.2 Drawing Text Game Engine for 2D Games, 335 Drawing using QPainter Desktop and Mobile Development, 428 Drawing, Animation and Input Graphics and Game Programming, 310 Dynamic Attributes Object Oriented Programming, 174 Dynamic Objects Desktop and Mobile Development, 451 Dynamic Typing Variables, 62 Editors Support How to contribute?, 43 Embedding Ring Language in C/C++ Programs Introduction, 556 Ring State, 557 Ring State Functions, 557 Ring State Variables, 558 Encourage Organization Language Design, 16 Encrypt() Security and Internet Functions, 164 endswith() Stdlib Functions, 208 Enum and Numbers Code Generator, 564 Equality of functions Functional Programming, 183 Eval() Eval() and Debugging, 134 Eval() and Debugging Assert(), 136 Eval(), 134 Introduction, 133 Raise(), 135 Try/Carch/Done, 134 evenorodd() Stdlib Functions, 209 Example Files, 126 Mathematical Functions, 114 Natural Language Programming, 245 Objects Library for RingQt Application, 486 Security and Internet Functions, 165 System Functions, 130 Example about Sharing Names between Functions and Methods Scope Rules for Functions and Methods, 507 Exceptions Control Structures - Second Style, 76 Control Structures - Third Style, 80 Execute Query and Print Result ODBC Functions, 145 executing code after the end of object access Declarative Programming, 242 Executing code during code generation Code Generator, 564 ExeFileName() Function System Functions, 133 ExeFolder() Function System Functions, 133 Exit Control Structures - First Style, 70 Exit from two loops Control Structures - First Style, 70 Exit/Loop inside sub functions Control Structures - First Style, 71 Extension Check Parameters Count, 549 Check Parameters Type, 550 Display Error Message, 550 Fopen() and Fclose() Implementation, 551 Function Prototype, 551 Function Structure, 549 Get Parameters Values, 550 Introduction, 546 Module Organization, 548 MySQL_Columns() Implementation, 554 Return Value, 550 RING API - list Functions, 552 RING API - String Functions, 554 ring_ext.c, 547 ring_ext.h, 547 Shared Libraries, 555 Sin() Implementation, 551 Extensions in C/C++ How to contribute?, 43 Facebook Login RingLibCurl, 307 factorial() Stdlib Functions, 206 factors() Stdlib Functions, 210 Fclose() Files, 121 Features Introduction, 10 Feof() Files, 124 Ferror() Files, 124 FetchStockData Application Applications developed in little hours, 2 Fexists() Files, 126 Index 792
814.
Ring Documentation, Release1.2 Fflush() Files, 122 Fgetc() Files, 125 Fgetpos() Files, 124 Fgets() Files, 125 fibonacci() Stdlib Functions, 206 Fifteen Puzzle Game Applications developed in little hours, 3 File Class Stdlib Classes, 229 File Hash Security and Internet Functions, 165 file2list() Stdlib Functions, 207 Files Clearerr(), 124 Dir(), 120 Example, 126 Fclose(), 121 Feof(), 124 Ferror(), 124 Fexists(), 126 Fflush(), 122 Fgetc(), 125 Fgetpos(), 124 Fgets(), 125 Fopen(), 121 Fputc(), 125 Fputs(), 125 Fread(), 126 Freopen(), 122 Fseek(), 123 Fsetpos(), 124 Ftell(), 123 Fwrite(), 126 Introduction, 118 Perror(), 124 Read File using Read(), 120 Remove(), 121 Rename(), 121 Rewind(), 123 Tempfile(), 123 Tempname(), 123 Ungetc(), 125 Write file using Write(), 120 filter() Stdlib Functions, 204 Filtering using Expressions Code Generator, 564 Find SubString Strings, 100 Find() and List of Objects Object Oriented Programming, 175 First-Class Functions Functional Programming, 181 First-Class Lists Lists, 94 Flappy Bird 3000 Game Game Engine for 2D Games, 361 Fopen() Files, 121 Fopen() and Fclose() Implementation Extension, 551 For In Loop Control Structures - First Style, 69 Control Structures - Second Style, 76 Control Structures - Third Style, 80 for in to modify lists Control Structures - First Style, 69 For Loop Control Structures - First Style, 68 Control Structures - Second Style, 75 Control Structures - Third Style, 79 Fputc() Files, 125 Fputs() Files, 125 Fread() Files, 126 Freopen() Files, 122 Frequently Asked Questions Can I connect to dbase/harbour database?, 766 Can Ring work on Windows XP?, 768 Conflict between Global Variables and Class At- tributes, 754 Constructor methods in Ring, 750 Could you explain the output of the StrCmp() func- tion?, 757 Getter and Setter Methods, 752 Goal of including the Main function in Ring, 749 How can I disable maximize button and resize win- dow?, 764 How to add Combobox and other elements to the cells of a QTableWidget?, 771 How to Close a window then displaying another one?, 763 How to create a Modal Window?, 763 How to create an array of buttons in GUI applica- tions?, 762 How to extend RingQt and add more classes?, 768 How to get the current source file path?, 755 How to get the file size using ftell() and fseek() func- tions?, 755 Index 793
815.
Ring Documentation, Release1.2 How to insert an item to the first position in the list?, 760 How to perform some manipulations on selected cells in QTableWidget?, 771 How to print keys or values only in List/Dictionary?, 756 How to print lists that contains objects?, 760 How to print new lines and other characters?, 761 How to use many source code files in the project?, 757 How to use NULL and ISNULL() function?, 759 How to use SQLite using ODBC?, 765 Introduction, 741 Is Ring some sort of improvement over PHP?, 744 List index start from 1, 750 Philosophy behind data types in Ring, 747 Search of global names while defining the class at- tributes, 753 The documentation says functional programming is supported, but then this happens?, 746 What about predefined parameters or optional pa- rameters in functions?, 755 What about the Boolean values in Ring?, 748 What are the advantages to using Ring over C# or Java?, 746 What are the advantages to using Ring over Lisp or Smalltalk?, 743 What are the advantages to using Ring over native C or C++?, 744 What are the advantages to using Ring over Python and Ruby?, 745 What are the advantages to using Ring over Tcl and Lua?, 746 What happens when we create a new object?, 751 What is the difference between Ring and Python? And is Ring Open Source?, 744 Where can I write a program and execute it?, 754 Why do we need Yet Another Programming Lan- guage (YAPL)?, 742 Why I get a strange result when printing nl with lists?, 756 Why I get Calling Function without definition Er- ror?, 767 Why Ring is largely focussed on UI creation?, 744 Why Ring is weakly typed?, 743 Why Ring uses ’See’, ’Give’, ’But’ and ’Ok’ Key- words?, 747 Why setClickEvent() doesn’t see the object methods directly?, 767 Why the ability to define your own languages Instead of just handing over the syntax so you can parse it using whatever code you like?, 747 Why the window title bar is going outside the screen?, 761 Why this example use the GetChar() twice?, 758 Why we don’t use () after the qApp class name?, 761 Why you can specify the number of loops you want to break out of?, 747 Fseek() Files, 123 Fsetpos() Files, 124 Ftell() Files, 123 Function Prototype Extension, 551 function prototype Code Generator, 560 Function Structure Extension, 549 Functional Programming Anonymous and Nested Functions, 182 Equality of functions, 183 First-Class Functions, 181 Higher-order Functions, 181 Introduction, 179 Pure Functions, 180 Functions Call Functions, 84 Declare parameters, 85 Define Functions, 84 Introduction, 83 Main Function, 85 Recursion, 87 Return Value, 86 Send Parameters, 85 Variables Scope, 86 functions() Reflection and Meta-programming, 186 Fwrite() Files, 126 Game Class Game Engine for 2D Games, 332 Game Engine Classes Game Engine for 2D Games, 331 Game Engine for 2D Games Animate Class, 334 Animate Events, 345 Animation, 339 Animation and Functions, 340 Creating the Game Window, 334 Drawing Text, 335 Flappy Bird 3000 Game, 361 Game Class, 332 Game Engine Classes, 331 GameObject Class, 332 Games Layer, 331 Index 794
816.
Ring Documentation, Release1.2 Graphics Library Bindings, 330 Interface to graphics library, 330 Introduction, 329 Map, 347 Map Class, 334 Map Events, 348 Moving Text, 336 Object and Drawing, 350 Playing Sound, 338 Project Layers, 330 Sound Class, 334 Sprite Automatic Movement, 341 Sprite Class, 333 Sprite Keypress Event, 342 Sprite Mouse Event, 343 Sprite State Event, 344 Stars Fighter Game, 353 Super Man 2016 Game, 368 Text Class, 333 What is new in Ring 1.1?, 35 GameObject Class Game Engine for 2D Games, 332 Games Layer Game Engine for 2D Games, 331 gcd() Stdlib Functions, 208 Generate Object File Command Line Options, 536 Generate/Execute Ring Object Files (*.ringo) What is new in Ring 1.1?, 30 Generating Pages using Objects Web Development (CGI Library), 279 Get Active Source File Name System Functions, 132 Get Command Line Arguments System Functions, 131 Get List Item Lists, 90 Get List Size Lists, 90 Get Number of Characters from position Strings, 100 Get Parameters Values Extension, 550 Get Request RingLibCurl, 307 Get String Length Strings, 97 Get Substring from position to end Strings, 100 getattribute() Reflection and Meta-programming, 198 GetChar() Getting Input, 82 getnumber() Stdlib Functions, 202 getstring() Stdlib Functions, 202 Getter and Setter Methods Frequently Asked Questions, 752 Getting Input GetChar(), 82 Getting Started - First Style, 45 Getting Started - Second Style, 47 Getting Started - Third Style, 49 Give Command, 82 Input(), 83 Introduction, 81 Getting Started - First Style Getting Input, 45 Hello World, 44 Introduction, 43 Multi-Line literals, 44 No Explicit End For Statements, 45 Not Case-Sensitive, 44 Run the program, 44 Writing Comments, 45 Getting Started - Second Style Getting Input, 47 Hello World, 46 Introduction, 45 Multi-Line literals, 46 No Explicit End For Statements, 47 Not Case-Sensitive, 46 Run the program, 46 Writing Comments, 47 Getting Started - Third Style Getting Input, 49 Hello World, 48 Introduction, 47 Multi-Line literals, 48 No Explicit End For Statements, 49 Not Case-Sensitive, 48 Run the program, 48 Writing Comments, 49 Give Command Getting Input, 82 globals() Reflection and Meta-programming, 185 Goal of including the Main function in Ring Frequently Asked Questions, 749 Gradient Web Development (CGI Library), 278 Graphics and Game Programming Drawing, Animation and Input, 310 Introduction, 309 Playing Sound, 317 Scaling and Rotating Images, 318 Index 795
817.
Ring Documentation, Release1.2 Threads, 320 Transparent Image, 319 TrueType Fonts, 316 Graphics Library Bindings Game Engine for 2D Games, 330 Hash Functions Web Development (CGI Library), 273 HashTable Class Stdlib Classes, 222 Hello World Getting Started - First Style, 44 Getting Started - Second Style, 46 Getting Started - Third Style, 48 Hello World Program using the Web Library Web Development (CGI Library), 256 Hex() Data Type, 112 Hex2str() Data Type, 113 Higher-order Functions Functional Programming, 181 History Introduction, 10 Natural Language Programming, 245 How can I disable maximize button and resize window? Frequently Asked Questions, 764 How Ring find a functions and methods? Scope Rules for Functions and Methods, 507 How Ring find the Variable? Scope Rules, 493 How to add Combobox and other elements to the cells of a QTableWidget? Frequently Asked Questions, 771 How to Close a window then displaying another one? Frequently Asked Questions, 763 How to contribute? Applications, 43 Compiler and Virtual Machine (VM), 43 Documentation, 42 Editors Support, 43 Extensions in C/C++, 43 Ideas and suggestions, 43 Introduction, 41 Libraries in Ring, 43 Samples, 42 Special thanks to contributors, 42 Testing, 42 How to create a Modal Window? Frequently Asked Questions, 763 How to create an array of buttons in GUI applications? Frequently Asked Questions, 762 How to extend RingQt and add more classes? Frequently Asked Questions, 768 How to get the current source file path? Frequently Asked Questions, 755 How to get the file size using ftell() and fseek() functions? Frequently Asked Questions, 755 How to insert an item to the first position in the list? Frequently Asked Questions, 760 How to perform some manipulations on selected cells in QTableWidget? Frequently Asked Questions, 771 How to print keys or values only in List/Dictionary? Frequently Asked Questions, 756 How to print lists that contains objects? Frequently Asked Questions, 760 How to print new lines and other characters? Frequently Asked Questions, 761 How to use many source code files in the project? Frequently Asked Questions, 757 How to use NULL and ISNULL() function? Frequently Asked Questions, 759 How to use SQLite using ODBC? Frequently Asked Questions, 765 HTML Lists Web Development (CGI Library), 276 HTML Special Characters Web Development (CGI Library), 272 HTML Tables Web Development (CGI Library), 277 HTTP Get Example Web Development (CGI Library), 257 HTTP POST Example Web Development (CGI Library), 262 Ideas and suggestions How to contribute?, 43 If Statement Control Structures - Second Style, 74 Control Structures - Third Style, 77 Inheritance Object Oriented Programming, 173 Inheritance from GUI Classes Desktop and Mobile Development, 443 Input() Getting Input, 83 Insert() Lists, 93 Install Qt for Android Building RingQt Applications for Mobile, 483 Interface to graphics library Game Engine for 2D Games, 330 Internet Class Stdlib Classes, 238 Introduction Features, 10 History, 10 Index 796
818.
Ring Documentation, Release1.2 Introduction, 8 Motivation, 9 Is Ring some sort of improvement over PHP? Frequently Asked Questions, 744 IsAlNum() Data Type, 108 IsAlpha() Data Type, 108 IsAndroid() Function System Functions, 130 isattribute() Reflection and Meta-programming, 194 iscfunction() Reflection and Meta-programming, 188 isclass() Reflection and Meta-programming, 190 IsCntrl() Data Type, 108 IsDigit() Data Type, 109 IsFreeBSD() Function System Functions, 130 isfunction() Reflection and Meta-programming, 188 isglobal() Reflection and Meta-programming, 187 IsGraph() Data Type, 109 isleapyear() Stdlib Functions, 210 IsLinux() Function System Functions, 130 IsList() Data Type, 107 islocal() Reflection and Meta-programming, 187 IsLower() Data Type, 109 IsMacOSX() Function System Functions, 129 ismainsourcefile() Stdlib Functions, 214 ismethod() Reflection and Meta-programming, 195 IsMSDOS() Function System Functions, 129 IsNULL() Data Type, 107 IsNumber() Data Type, 106 isobject() Reflection and Meta-programming, 193 ispackage() Reflection and Meta-programming, 189 ispackagesclass() Reflection and Meta-programming, 192 isprime() Stdlib Functions, 206 IsPrint() Data Type, 109 isprivateattribute() Reflection and Meta-programming, 194 isprivatemethod() Reflection and Meta-programming, 195 IsPunct() Data Type, 110 IsSpace() Data Type, 110 isspecial() Stdlib Functions, 205 IsString() Data Type, 106 IsUnix() Function System Functions, 129 IsUpper() Data Type, 110 isvowel() Stdlib Functions, 205 IsWindows() Function System Functions, 129 IsWindows64() Function System Functions, 129 IsXdigit() Data Type, 110 KeyPress and Mouse Move Events Desktop and Mobile Development, 438 Language Design Compact Syntax, 18 Define Declarative Languages, 21 Define Natural Statements, 19 Designed for a clear goal, 14 Encourage Organization, 16 Introduction, 13 Simple, 14 Smart Garbage Collector, 22 Transparent Implementation, 16 Trying to be natural, 15 Visual Implementation, 17 Why Ring?, 14 Language Functions Reference, 774 Language Grammar Reference, 777 Language Keywords Reference, 773 Language Shell Index 797
819.
Ring Documentation, Release1.2 Demo Programs, 137 lcm() Stdlib Functions, 209 Left() Strings, 98 Libraries in Ring How to contribute?, 43 Library Usage Objects Library for RingQt Application, 486 linecount() Stdlib Functions, 206 Lines() Strings, 99 List Class Stdlib Classes, 219 List index start from 1 Frequently Asked Questions, 750 List of changes and new features What is new in Ring 1.1?, 29 What is new in Ring 1.2?, 23 list of functions Mathematical Functions, 114 list2file() Stdlib Functions, 207 Lists Access List Items by String Index, 95 Add Items, 89 Copy Lists, 93 Create Lists, 89 Delete Item From List, 90 First-Class Lists, 94 Get List Item, 90 Get List Size, 90 Insert(), 93 Introduction, 88 Nested Lists, 93 Passing Lists to Functions, 94 Passing Parameters Using List, 95 Reverse(), 92 Search, 91 Set List Item, 90 Sort(), 91 Using Lists during definition, 94 Load Syntax Files Syntax Flexibility, 512 locals() Reflection and Meta-programming, 185 Logical Operators Operators, 64 Loop Command Control Structures - First Style, 71 Looping Control Structures, 78 Control Structures - First Style, 68 Control Structures - Second Style, 75 Low Level Functions callgc(), 537 Introduction, 536 nullpointer(), 539 object2pointer(), 539 pointer2object(), 539 ptrcmp(), 540 RingVM_CallList(), 545 RingVM_CFunctionsList(), 540 RingVM_ClassesList(), 541 RingVM_FilesList(), 546 RingVM_FunctionsList(), 541 RingVM_MemoryList(), 543 RingVM_PackagesList(), 542 space(), 538 varptr(), 538 Main Function Functions, 85 Main Menu Demo Programs, 137 makedir() Stdlib Functions, 214 Map Game Engine for 2D Games, 347 Map Class Game Engine for 2D Games, 334 Map Events Game Engine for 2D Games, 348 map() Stdlib Functions, 203 Math Class Stdlib Classes, 224 Mathematical Functions Decimals(), 117 Example, 114 Introduction, 113 list of functions, 114 Random(), 116 Unsigned(), 117 matrixmulti() Stdlib Functions, 211 matrixtrans() Stdlib Functions, 211 MD5() Security and Internet Functions, 162 Menubar and StyleSheet Example Desktop and Mobile Development, 418 mergemethods() Reflection and Meta-programming, 200 Methods to use Events with Events Filter Desktop and Mobile Development, 480 methods() Index 798
820.
Ring Documentation, Release1.2 Reflection and Meta-programming, 193 Misc Operators Operators, 65 Module Organization Extension, 548 More Beatiful Code Declarative Programming, 243 Motivation Introduction, 9 Mouse Events RingLibSDL, 327 Movable Label Example Desktop and Mobile Development, 434 Moving Objects using the Mouse Desktop and Mobile Development, 439 Moving Text Game Engine for 2D Games, 336 Multi-Line literals Getting Started - First Style, 44 Getting Started - Second Style, 46 Getting Started - Third Style, 48 MySQL Class Stdlib Classes, 235 MySQL Functions Create Database, 151 Create Table and Insert Data, 152 Introduction, 149 MySQL_AutoCommit(), 157 MySQL_Close(), 151 MySQL_Columns(), 154 MySQL_Commit(), 157 MySQL_Connect(), 151 MySQL_Error(), 151 MySQL_Escape_String(), 156 MySQL_Info(), 150 MySQL_Init(), 150 MySQL_Inser_ID(), 153 MySQL_Next_Result(), 154 MySQL_Query(), 151 MySQL_Result(), 153 MySQL_Result2(), 155 MySQL_Rollback(), 157 Print Query Result, 154 Restore Image From The Database, 156 Save Image Inside the Database, 156 Transaction Example, 157 MySQL_AutoCommit() MySQL Functions, 157 MySQL_Close() MySQL Functions, 151 MySQL_Columns() MySQL Functions, 154 MySQL_Columns() Implementation Extension, 554 MySQL_Commit() MySQL Functions, 157 MySQL_Connect() MySQL Functions, 151 MySQL_Error() MySQL Functions, 151 MySQL_Escape_String() MySQL Functions, 156 MySQL_Info() MySQL Functions, 150 MySQL_Init() MySQL Functions, 150 MySQL_Inser_ID() MySQL Functions, 153 MySQL_Next_Result() MySQL Functions, 154 MySQL_Query() MySQL Functions, 151 MySQL_Result() MySQL Functions, 153 MySQL_Result2() MySQL Functions, 155 MySQL_Rollback() MySQL Functions, 157 Natural Language Programming BraceError() Method, 252 BraceExprEval Method, 251 BraceStart and BraceEnd Methods, 250 Change the ’=’ operator to ’is’, 248 Change the Ring Keyword ’And’, 246 Change the Ring Operator ’+’, 247 Clean Natural Code, 253 Example, 245 History, 245 Introduction, 244 Real Natual Code, 251 Using Eval() with our Natural Code, 249 Nested Lists Lists, 93 New Functions What is new in Ring 1.2?, 23 New Functions and Changes What is new in Ring 1.1?, 32 newlist() Stdlib Functions, 204 No Explicit End For Statements Getting Started - First Style, 45 Getting Started - Second Style, 47 Getting Started - Third Style, 49 No Run Command Line Options, 535 Not Case-Sensitive Getting Started - First Style, 44 Index 799
821.
Ring Documentation, Release1.2 Getting Started - Second Style, 46 Getting Started - Third Style, 48 Notepad Application Desktop and Mobile Development, 456 nullpointer() Low Level Functions, 539 Number() Data Type, 111 Object and Drawing Game Engine for 2D Games, 350 Object Library Source Code Objects Library for RingQt Application, 489 Object Oriented Programming Access Objects Using Braces, 169 Classes and Objects, 167 Composition, 170 Dynamic Attributes, 174 Find() and List of Objects, 175 Inheritance, 173 Introduction, 166 Operator Overloading, 172 Packages, 174 Printing Objects, 175 Private Attributes and Methods, 171 Setter and Getter, 171 Sort() and List of Objects, 176 Using Self.Attribute, 178 object2pointer() Low Level Functions, 539 objectid() Reflection and Meta-programming, 192 Objects inside lists Declarative Programming, 239 Objects Library for RingQt What is new in Ring 1.2?, 25 Objects Library for RingQt Application Example, 486 Introduction, 485 Library Usage, 486 Object Library Source Code, 489 ODBC Class Stdlib Classes, 234 ODBC Functions Execute Query and Print Result, 145 Introduction, 140 odbc_autocommit(), 147 odbc_close(), 142 odbc_colcount(), 144 odbc_columns(), 146 odbc_commit(), 147 odbc_connect(), 143 odbc_datasources(), 142 odbc_disconnect(), 144 odbc_drivers(), 141 odbc_execute(), 144 odbc_fetch(), 144 odbc_getdata(), 145 odbc_init(), 141 odbc_rollback(), 147 odbc_tables(), 145 Open and Close Connection, 144 Print List of ODBC Data Sources, 143 Print List of ODBC Drivers, 142 Save and Restore Images, 148 Transactions and Using Commit and Rollback, 147 odbc_autocommit() ODBC Functions, 147 odbc_close() ODBC Functions, 142 odbc_colcount() ODBC Functions, 144 odbc_columns() ODBC Functions, 146 odbc_commit() ODBC Functions, 147 odbc_connect() ODBC Functions, 143 odbc_datasources() ODBC Functions, 142 odbc_disconnect() ODBC Functions, 144 odbc_drivers() ODBC Functions, 141 odbc_execute() ODBC Functions, 144 odbc_fetch() ODBC Functions, 144 odbc_getdata() ODBC Functions, 145 odbc_init() ODBC Functions, 141 odbc_rollback() ODBC Functions, 147 odbc_tables() ODBC Functions, 145 Open and Close Connection ODBC Functions, 144 Operator Overloading Object Oriented Programming, 172 Operators Arithmetic Operators, 64 Assignment Operators, 65 Bitwise Operators, 64 Introduction, 63 Logical Operators, 64 Misc Operators, 65 Operators Precedence, 65 Index 800
822.
Ring Documentation, Release1.2 Relational Operators, 64 Operators Precedence Operators, 65 Other Widgets Events Desktop and Mobile Development, 422 Packages Object Oriented Programming, 174 packages() Reflection and Meta-programming, 189 packagesclasses() Reflection and Meta-programming, 191 Page Class Web Development (CGI Library), 303 palindrome() Stdlib Functions, 210 Passing Lists to Functions Lists, 94 Passing Parameters Using List Lists, 95 Performance Command Line Options, 535 permutation() Stdlib Functions, 212 Perror() Files, 124 Philosophy behind data types in Ring Frequently Asked Questions, 747 Play Sound RingLibSDL, 328 Playing Sound Desktop and Mobile Development, 432 Game Engine for 2D Games, 338 Graphics and Game Programming, 317 pointer2object() Low Level Functions, 539 Post Request RingLibCurl, 307 Prefix for Functions Names Code Generator, 562 PrevFileName() Function System Functions, 132 Print List of ODBC Data Sources ODBC Functions, 143 Print List of ODBC Drivers ODBC Functions, 142 Print Query Result MySQL Functions, 154 print() Stdlib Functions, 202 Printing Final Intermediate Code Command Line Options, 530 Printing Instruction Operation Code Command Line Options, 535 Printing Intermediate Code Command Line Options, 528 Printing Objects Object Oriented Programming, 175 Printing Rules Command Line Options, 524 Printing Tokens Command Line Options, 522 Printing using QPrinter Desktop and Mobile Development, 430 Private Attributes and Methods Object Oriented Programming, 171 prodlist() Stdlib Functions, 209 Program Structure Introduction, 87 Source Code File Sections, 88 Using Many Source Code Files, 88 Project Folder Building Games For Android, 380 Project Layers Game Engine for 2D Games, 330 Protecting the Source Code Distributing Ring Application, 520 ptrcmp() Low Level Functions, 540 Pure Functions Functional Programming, 180 puts() Stdlib Functions, 202 QAbstractButton Class RingQt Classes Reference, 662 QAbstractItemView Class RingQt Classes Reference, 648 QAbstractScrollArea Class RingQt Classes Reference, 648 QAbstractSlider Class RingQt Classes Reference, 655 QAbstractSocket Class RingQt Classes Reference, 683 QAbstractSpinBox Class RingQt Classes Reference, 658 QAction Class RingQt Classes Reference, 666 QAllEvents Class RingQt Classes Reference, 696 QApp Class RingQt Classes Reference, 616 QBitmap Class RingQt Classes Reference, 624 QBoxLayout Class RingQt Classes Reference, 738 QBrush Class Index 801
823.
Ring Documentation, Release1.2 RingQt Classes Reference, 680 QButtonGroup Class RingQt Classes Reference, 664 QByteArray Class RingQt Classes Reference, 681 QCamera Class RingQt Classes Reference, 733 QCameraImageCapture Class RingQt Classes Reference, 733 QCameraViewfinder Class RingQt Classes Reference, 732 QCheckBox Class RingQt Classes Reference, 662 QColor Class RingQt Classes Reference, 675 QColorDialog Class RingQt Classes Reference, 692 QComboBox Class RingQt Classes Reference, 638 QDate Class RingQt Classes Reference, 705 QDateEdit Class RingQt Classes Reference, 657 QDateTimeEdit Class RingQt Classes Reference, 657 QDesktopWidget Class RingQt Classes Reference, 698 QDial Class RingQt Classes Reference, 659 QDialog Class RingQt Classes Reference, 690 QDir Class RingQt Classes Reference, 633 QDirModel Class RingQt Classes Reference, 689 QDockWidget Class RingQt Classes Reference, 644 QEvent Class RingQt Classes Reference, 668 QFileDialog Class RingQt Classes Reference, 670 QFileInfo Class RingQt Classes Reference, 688 QFileSystemModel Class RingQt Classes Reference, 633 QFont Class RingQt Classes Reference, 678 QFontDialog Class RingQt Classes Reference, 690 QFontMetrics Class RingQt Classes Reference, 737 QFrame Class RingQt Classes Reference, 647 QGradient Class RingQt Classes Reference, 740 QGraphicsVideoItem Class RingQt Classes Reference, 732 QGridLayout Class RingQt Classes Reference, 729 QHBoxLayout Class RingQt Classes Reference, 627 QHeaderView Class RingQt Classes Reference, 734 QHostAddress Class RingQt Classes Reference, 687 QHostInfo Class RingQt Classes Reference, 687 QIcon Class RingQt Classes Reference, 624 QImage Class RingQt Classes Reference, 716 QInputDialog Class RingQt Classes Reference, 695 QIODevice Class RingQt Classes Reference, 682 QJsonArray Class RingQt Classes Reference, 724 QJsonDocument Class RingQt Classes Reference, 725 QJsonObject Class RingQt Classes Reference, 726 QJsonParseError Class RingQt Classes Reference, 726 QJsonValue Class RingQt Classes Reference, 726 QKeySequence Class RingQt Classes Reference, 694 QLabel Class RingQt Classes Reference, 622 QLayout Class RingQt Classes Reference, 739 QLCDNumber Class RingQt Classes Reference, 694 QLinearGradient Class RingQt Classes Reference, 740 QLineEdit Class RingQt Classes Reference, 625 QLineEdit Events and QMessageBox Desktop and Mobile Development, 420 QListWidget Class RingQt Classes Reference, 630 QListWidgetItem Class RingQt Classes Reference, 704 QMainWindow Class RingQt Classes Reference, 642 QMediaObject Class RingQt Classes Reference, 734 QMediaPlayer Class Index 802
824.
Ring Documentation, Release1.2 RingQt Classes Reference, 664 QMediaPlaylist Class RingQt Classes Reference, 665 QMenu Class RingQt Classes Reference, 641 QMenuBar Class RingQt Classes Reference, 640 QMessageBox Class RingQt Classes Reference, 668 QMessagebox Example Desktop and Mobile Development, 435 QNetworkAccessManager Class RingQt Classes Reference, 713 QNetworkProxy Class RingQt Classes Reference, 685 QNetworkReply Class RingQt Classes Reference, 714 QNetworkRequest Class RingQt Classes Reference, 713 QObject Class RingQt Classes Reference, 616 QPainter Class RingQt Classes Reference, 671 QPainterPath Class RingQt Classes Reference, 714 QPen Class RingQt Classes Reference, 674 QPicture Class RingQt Classes Reference, 673 QPixmap Class RingQt Classes Reference, 624 QPlainTextEdit Class RingQt Classes Reference, 727 QPoint Class RingQt Classes Reference, 741 QPointF Class RingQt Classes Reference, 740 QPrinter Class RingQt Classes Reference, 677 QProgressBar Class RingQt Classes Reference, 654 QPushButton Class RingQt Classes Reference, 623 QRadioButton Class RingQt Classes Reference, 663 QRect Class RingQt Classes Reference, 699 QRegularExpression Class RingQt Classes Reference, 723 QRegularExpressionMatch Class RingQt Classes Reference, 723 QRegularExpressionMatchIterator Class RingQt Classes Reference, 724 QSize Class RingQt Classes Reference, 624 QSlider Class RingQt Classes Reference, 656 QSpinBox Class RingQt Classes Reference, 654 QSplashScreen Class RingQt Classes Reference, 738 QSqlDatabase Class RingQt Classes Reference, 706 QSqlDriver Class RingQt Classes Reference, 708 QSqlDriverCreatorBase Class RingQt Classes Reference, 711 QSqlError Class RingQt Classes Reference, 709 QSqlField Class RingQt Classes Reference, 710 QSqlIndex Class RingQt Classes Reference, 709 QSqlQuery Class RingQt Classes Reference, 708 QSqlRecord Class RingQt Classes Reference, 710 QStatusBar Class RingQt Classes Reference, 644 QStringList Class RingQt Classes Reference, 693 QSystemTrayIcon Class RingQt Classes Reference, 705 Qt configuration file Code Generator, 568 QTableView Class RingQt Classes Reference, 650 QTableWidget Class RingQt Classes Reference, 651 QTableWidgetItem Class RingQt Classes Reference, 646 QTabWidget Class RingQt Classes Reference, 645 QTcpServer Class RingQt Classes Reference, 686 QTcpSocket Class RingQt Classes Reference, 685 QTest Class RingQt Classes Reference, 616 QTextBlock Class RingQt Classes Reference, 702 QTextCharFormat Class RingQt Classes Reference, 730 QTextCodec Class RingQt Classes Reference, 706 QTextCursor Class RingQt Classes Reference, 691 QTextDocument Class Index 803
825.
Ring Documentation, Release1.2 RingQt Classes Reference, 700 QTextEdit Class RingQt Classes Reference, 627 QThread Class RingQt Classes Reference, 722 QThreadPool Class RingQt Classes Reference, 722 QTime Class RingQt Classes Reference, 703 QTimer Class RingQt Classes Reference, 669 QToolBar Class RingQt Classes Reference, 641 QTreeView Class RingQt Classes Reference, 631 QTreeWidget Class RingQt Classes Reference, 635 QTreeWidgetItem Class RingQt Classes Reference, 637 Queue Class Stdlib Classes, 221 Quotes about Ring Applications developed in little hours, 1 QUrl Class RingQt Classes Reference, 661 QVariant Class RingQt Classes Reference, 711 QVBoxLayout Class RingQt Classes Reference, 627 QVideoWidget and QMediaPlayer Desktop and Mobile Development, 414 QVideoWidget Class RingQt Classes Reference, 665 QVideoWidgetControl Class RingQt Classes Reference, 732 QWebView Class RingQt Classes Reference, 660 QWidget Class RingQt Classes Reference, 617 QXmlStreamAttribute Class RingQt Classes Reference, 721 QXmlStreamAttributes Class RingQt Classes Reference, 721 QXmlStreamEntityDeclaration Class RingQt Classes Reference, 721 QXmlStreamEntityResolver Class RingQt Classes Reference, 720 QXmlStreamNamespaceDeclaration Class RingQt Classes Reference, 720 QXmlStreamNotationDeclaration Class RingQt Classes Reference, 720 QXmlStreamReader Class RingQt Classes Reference, 717 QXmlStreamWriter Class RingQt Classes Reference, 719 Raise() Eval() and Debugging, 135 RandBytes() Security and Internet Functions, 165 Random Image Web Development (CGI Library), 275 Random() Mathematical Functions, 116 Read File using Read() Files, 120 readline() Stdlib Functions, 212 Real Natual Code Natural Language Programming, 251 Recursion Functions, 87 Reference Compiler Errors, 775 Introduction, 772 Language Functions, 774 Language Grammar, 777 Language Keywords, 773 Runtime Errors, 776 Virtual Machine Instructions, 779 Reflection and Meta-programming addattribute(), 196 addmethod(), 196 attributes(), 193 cfunctions(), 186 classes(), 190 classname(), 192 functions(), 186 getattribute(), 198 globals(), 185 Introduction, 184 isattribute(), 194 iscfunction(), 188 isclass(), 190 isfunction(), 188 isglobal(), 187 islocal(), 187 ismethod(), 195 isobject(), 193 ispackage(), 189 ispackagesclass(), 192 isprivateattribute(), 194 isprivatemethod(), 195 locals(), 185 mergemethods(), 200 methods(), 193 objectid(), 192 packages(), 189 Index 804
826.
Ring Documentation, Release1.2 packagesclasses(), 191 setattribute(), 199 Register New Functions Code Generator, 563 Regular Expressions Desktop and Mobile Development, 448 Relational Operators Operators, 64 Remove() Files, 121 Rename() Files, 121 Resources Contact the Autor, 786 Introduction, 785 Ring Group, 786 Ring Language Website, 786 Restore Image From The Database MySQL Functions, 156 Return object by reference Declarative Programming, 240 Return Value Extension, 550 Functions, 86 Reverse() Lists, 92 Rewind() Files, 123 Right() Strings, 98 RING API - list Functions Extension, 552 RING API - String Functions Extension, 554 Ring CGI Hello World Program Web Development (CGI Library), 256 Ring Group Resources, 786 Ring Language Website Resources, 786 Ring Notepad Introduction, 49 Ring Notepad - Creating and running your first con- sole application, 50 Ring Notepad - Creating and running your first game, 55 Ring Notepad - Creating and running your first GUI application, 53 Ring Notepad - Creating and running your first Web application, 54 Ring Notepad - Main Window, 50 Ring Notepad - Creating and running your first console application Ring Notepad, 50 Ring Notepad - Creating and running your first game Ring Notepad, 55 Ring Notepad - Creating and running your first GUI ap- plication Ring Notepad, 53 Ring Notepad - Creating and running your first Web ap- plication Ring Notepad, 54 Ring Notepad - Main Window Ring Notepad, 50 Ring State Embedding Ring Language in C/C++ Programs, 557 Ring State Functions Embedding Ring Language in C/C++ Programs, 557 Ring State Variables Embedding Ring Language in C/C++ Programs, 558 ring_ext.c Extension, 547 ring_ext.h Extension, 547 RingAllegro Functions Reference Introduction, 580 RingCodeHighlighter Class RingQt Classes Reference, 717 RingLibCurl Facebook Login, 307 Get Request, 307 Introduction, 306 Post Request, 307 Save output to string, 308 What is new in Ring 1.2?, 26 RingLibCurl Functions Reference Introduction, 578 RingLibSDL Close Window Event, 326 Create Window, 323 Display Image, 323 Display PNG Images, 324 Display Transparent Images, 325 Draw Rectangle, 324 Introduction, 322 Mouse Events, 327 Play Sound, 328 Switch Between Two Images, 323 Use TTF Fonts, 325 What is new in Ring 1.1?, 35 RingLibSDL Functions Reference Introduction, 599 RingQt Classes and their Qt Documentation Desktop and Mobile Development, 482 RingQt Classes Reference Introduction, 615 QAbstractButton Class, 662 QAbstractItemView Class, 648 Index 805
Ring Documentation, Release1.2 QTcpSocket Class, 685 QTest Class, 616 QTextBlock Class, 702 QTextCharFormat Class, 730 QTextCodec Class, 706 QTextCursor Class, 691 QTextDocument Class, 700 QTextEdit Class, 627 QThread Class, 722 QThreadPool Class, 722 QTime Class, 703 QTimer Class, 669 QToolBar Class, 641 QTreeView Class, 631 QTreeWidget Class, 635 QTreeWidgetItem Class, 637 QUrl Class, 661 QVariant Class, 711 QVBoxLayout Class, 627 QVideoWidget Class, 665 QVideoWidgetControl Class, 732 QWebView Class, 660 QWidget Class, 617 QXmlStreamAttribute Class, 721 QXmlStreamAttributes Class, 721 QXmlStreamEntityDeclaration Class, 721 QXmlStreamEntityResolver Class, 720 QXmlStreamNamespaceDeclaration Class, 720 QXmlStreamNotationDeclaration Class, 720 QXmlStreamReader Class, 717 QXmlStreamWriter Class, 719 RingCodeHighlighter Class, 717 RingSQLite What is new in Ring 1.1?, 36 RingVM_CallList() Low Level Functions, 545 RingVM_CFunctionsList() Low Level Functions, 540 RingVM_ClassesList() Low Level Functions, 541 RingVM_FilesList() Low Level Functions, 546 RingVM_FunctionsList() Low Level Functions, 541 RingVM_MemoryList() Low Level Functions, 543 RingVM_PackagesList() Low Level Functions, 542 Rotate Text Desktop and Mobile Development, 445 Run the program Getting Started - First Style, 44 Getting Started - Second Style, 46 Getting Started - Third Style, 48 Runtime Errors Reference, 776 Samples How to contribute?, 42 Samples in this book Applications developed in little hours, 5 Save and Restore Images ODBC Functions, 148 Save Image Inside the Database MySQL Functions, 156 Save output to string RingLibCurl, 308 Scaling and Rotating Images Graphics and Game Programming, 318 Scope Rules Accessing the class attributes from braces inside class methods, 498 Conflict between Class Attributes and Local Vari- ables, 495 Conflict between Global Variables and Class At- tributes, 494 Conflict between self inside braces and self in the class region, 501 Creating a Class for each Window in GUI applica- tions, 500 Defining Variables and Variables Access, 492 How Ring find the Variable?, 493 Introduction, 491 Summary of Scope Rules, 505 The Self Object, 493 Three Scopes, 492 Using Braces to access objects inside Class Methods, 496 Using braces to escape from the current object scope, 504 Using Object.Attribute, 493 Scope Rules for Functions and Methods Calling a function sharing the name with a method in the current class, 509 Example about Sharing Names between Functions and Methods, 507 How Ring find a functions and methods?, 507 Introduction, 506 ScriptFunctions Class Web Development (CGI Library), 305 Search Lists, 91 Search of global names while defining the class attributes Frequently Asked Questions, 753 Security and Internet Functions Decrypt(), 164 Download(), 166 Encrypt(), 164 Index 807
829.
Ring Documentation, Release1.2 Example, 165 File Hash, 165 Introduction, 161 MD5(), 162 RandBytes(), 165 SendEmail(), 166 SHA1(), 162 SHA224(), 164 SHA256(), 163 SHA384(), 164 SHA512(), 163 Security Class Stdlib Classes, 237 Send Parameters Functions, 85 SendEmail() Security and Internet Functions, 166 Set List Item Lists, 90 setattribute() Reflection and Meta-programming, 199 Setter and Getter Object Oriented Programming, 171 SHA1() Security and Internet Functions, 162 SHA224() Security and Internet Functions, 164 SHA256() Security and Internet Functions, 163 SHA384() Security and Internet Functions, 164 SHA512() Security and Internet Functions, 163 Shared Libraries Extension, 555 Short-circuit evaluation Control Structures - First Style, 71 sign() Stdlib Functions, 207 Simple Language Design, 14 Simple Client and Server Example Desktop and Mobile Development, 449 Sin() Implementation Extension, 551 Single: Desktop and Mobile Development Introduction, 382 sleep() Stdlib Functions, 213 Smart Garbage Collector Language Design, 22 Sort() Lists, 91 Sort() and List of Objects Object Oriented Programming, 176 Sound Class Game Engine for 2D Games, 334 Source Code File Sections Program Structure, 88 space() Low Level Functions, 538 Special thanks to contributors How to contribute?, 42 split() Stdlib Functions, 204 Sprite Automatic Movement Game Engine for 2D Games, 341 Sprite Class Game Engine for 2D Games, 333 Sprite Keypress Event Game Engine for 2D Games, 342 Sprite Mouse Event Game Engine for 2D Games, 343 Sprite State Event Game Engine for 2D Games, 344 SQLite Introduction, 158 sqlite_close(), 159 sqlite_execute(), 159 sqlite_init(), 159 sqlite_open(), 159 SQLite Class Stdlib Classes, 236 sqlite_close() SQLite, 159 sqlite_execute() SQLite, 159 sqlite_init() SQLite, 159 sqlite_open() SQLite, 159 Squares Puzzle Game Applications developed in little hours, 4 Stack Class Stdlib Classes, 221 Stars Fighter Game Game Engine for 2D Games, 353 startswith() Stdlib Functions, 208 StdBase Class Stdlib Classes, 216 Stdlib Classes Conversion Class, 233 DataType Class, 232 DateTime Class, 227 Debug Class, 231 File Class, 229 HashTable Class, 222 Index 808
830.
Ring Documentation, Release1.2 Internet Class, 238 Introduction, 215 List Class, 219 Math Class, 224 MySQL Class, 235 ODBC Class, 234 Queue Class, 221 Security Class, 237 SQLite Class, 236 Stack Class, 221 StdBase Class, 216 String Class, 217 System Class, 230 Tree Class, 223 Stdlib Functions apppath(), 203 binarydigits(), 211 capitalized(), 205 changestring(), 213 dayofweek(), 212 direxists(), 214 endswith(), 208 evenorodd(), 209 factorial(), 206 factors(), 210 fibonacci(), 206 file2list(), 207 filter(), 204 gcd(), 208 getnumber(), 202 getstring(), 202 Introduction, 201 isleapyear(), 210 ismainsourcefile(), 214 isprime(), 206 isspecial(), 205 isvowel(), 205 lcm(), 209 linecount(), 206 list2file(), 207 makedir(), 214 map(), 203 matrixmulti(), 211 matrixtrans(), 211 newlist(), 204 palindrome(), 210 permutation(), 212 print(), 202 prodlist(), 209 puts(), 202 readline(), 212 sign(), 207 sleep(), 213 split(), 204 startswith(), 208 substring(), 213 sumlist(), 209 times(), 203 value(), 203 StdLib functions and classes written in Ring What is new in Ring 1.1?, 33 Step Option Control Structures - First Style, 69 Str2Hex() Data Type, 113 str2list() and list2str() Strings, 101 strcmp() Strings, 101 String Class Stdlib Classes, 217 String Literals Strings, 97 String() Data Type, 111 Strings Access String Letters, 97 Convert Letters Case, 97 Copy(), 99 Find SubString, 100 Get Number of Characters from position, 100 Get String Length, 97 Get Substring from position to end, 100 Introduction, 96 Left(), 98 Lines(), 99 Right(), 98 str2list() and list2str(), 101 strcmp(), 101 String Literals, 97 Substr(), 99 Transform Substring To Another Substring, 100 Trim(), 99 StyleFunctions Class Web Development (CGI Library), 305 Substr() Strings, 99 substring() Stdlib Functions, 213 sumlist() Stdlib Functions, 209 Summary of Scope Rules Scope Rules, 505 Super Man 2016 Game Game Engine for 2D Games, 368 Switch Between Two Images RingLibSDL, 323 Switch Statement Index 809
831.
Ring Documentation, Release1.2 Control Structures - First Style, 67 Control Structures - Second Style, 74 Control Structures - Third Style, 77 Syntax Flexibility Change Language Keywords, 511 Change Language Operators, 512 Introduction, 510 Load Syntax Files, 512 Using ’case’ as ’on’ in switch statements, 518 Using ’def’ as ’func’ in functions/methods defini- tion, 518 Using ’put’ and ’get’ as ’see’ and ’give’, 518 Using () around the function parameters, 512 in the start of the variable name, 515 Using braces to start and end different control struc- tures, 517 Using Semi-colon after and between statements, 514 Using the ’else’ keyword as ’other’ in switch state- ment, 515 Using the ’elseif’ keyword as ’but’ in if statement, 515 Using the ’end’ keyword in different control struc- tures, 516 What is new in Ring 1.1?, 30 SysGet() Function System Functions, 128 System Class Stdlib Classes, 230 System Functions ChDir() Function, 133 CurrentDir() Function, 132 Example, 130 ExeFileName() Function, 133 ExeFolder() Function, 133 Get Active Source File Name, 132 Get Command Line Arguments, 131 Introduction, 127 IsAndroid() Function, 130 IsFreeBSD() Function, 130 IsLinux() Function, 130 IsMacOSX() Function, 129 IsMSDOS() Function, 129 IsUnix() Function, 129 IsWindows() Function, 129 IsWindows64() Function, 129 PrevFileName() Function, 132 SysGet() Function, 128 System() Function, 128 Version() Function, 133 Windowsnl() Function, 130 System() Function System Functions, 128 Tempfile() Files, 123 Templates Web Development (CGI Library), 270 Tempname() Files, 123 Testing How to contribute?, 42 Text Class Game Engine for 2D Games, 333 The Cards Game Demo Programs, 471 Desktop and Mobile Development, 471 The Difference between Qt and RingQt Desktop and Mobile Development, 481 The documentation says functional programming is sup- ported, but then this happens? Frequently Asked Questions, 746 The First GUI Application Desktop and Mobile Development, 383 The Self Object Scope Rules, 493 Threads Graphics and Game Programming, 320 Threads Support Code Generator, 566 Three Scopes Scope Rules, 492 TicTacToe Game Applications developed in little hours, 3 Time() Date and Time, 103 TimeList() Date and Time, 104 times() Stdlib Functions, 203 Transaction Example MySQL Functions, 157 Transactions and Using Commit and Rollback ODBC Functions, 147 Transform Substring To Another Substring Strings, 100 Transparent Image Graphics and Game Programming, 319 Transparent Implementation Language Design, 16 Tree Class Stdlib Classes, 223 Trim() Strings, 99 TrueType Fonts Graphics and Game Programming, 316 Try/Carch/Done Eval() and Debugging, 134 Trying to be natural Index 810
832.
Ring Documentation, Release1.2 Language Design, 15 Type() Data Type, 107 Ungetc() Files, 125 Unsigned() Mathematical Functions, 117 Update the Android SDK Building RingQt Applications for Mobile, 483 Upload Files Web Development (CGI Library), 264 URL Encode Web Development (CGI Library), 269 Use TTF Fonts RingLibSDL, 325 Users registration and Login Web Development (CGI Library), 290 Using ’case’ as ’on’ in switch statements Syntax Flexibility, 518 Using ’def’ as ’func’ in functions/methods definition Syntax Flexibility, 518 Using ’put’ and ’get’ as ’see’ and ’give’ Syntax Flexibility, 518 Using () around the function parameters Syntax Flexibility, 512 in the start of the variable name Syntax Flexibility, 515 Using Atom Using Other Code Editors, 59 Using Bootstrap Library using Functions Web Development (CGI Library), 284 Using Bootstrap Library using Objects Web Development (CGI Library), 285 Using Braces to access objects inside Class Methods Scope Rules, 496 Using braces to escape from the current object scope Scope Rules, 504 Using braces to start and end different control structures Syntax Flexibility, 517 Using C/C++ Compiler and Linker Distributing Ring Application, 521 Using configuration file that wrap C++ library Code Generator, 568 Using Eval() with our Natural Code Natural Language Programming, 249 Using Geany Using Other Code Editors, 58 Using Layout Desktop and Mobile Development, 384 Using Lists during definition Lists, 94 Using Many Source Code Files Program Structure, 88 Using Notepad++ Using Other Code Editors, 57 Using NULL instead of NULLPointer() What is new in Ring 1.2?, 27 Using Object.Attribute Scope Rules, 493 Using Other Code Editors Introduction, 56 Using Atom, 59 Using Geany, 58 Using Notepad++, 57 Using Sublime Text 2, 60 Using Visual Studio IDE, 61 Using QCheckBox Desktop and Mobile Development, 410 Using QComboBox Class Desktop and Mobile Development, 392 Using QDateEdit Desktop and Mobile Development, 405 Using QDesktopWidget Class Desktop and Mobile Development, 444 Using QDial Desktop and Mobile Development, 406 Using QDockWidget Desktop and Mobile Development, 398 Using QFrame Desktop and Mobile Development, 415 Using QInputDialog Class Desktop and Mobile Development, 436 Using qLCDNumber Desktop and Mobile Development, 433 Using QProgressBar Desktop and Mobile Development, 402 Using QProgressBar and Timer Desktop and Mobile Development, 425 Using QRadioButton and QButtonGroup Desktop and Mobile Development, 411 Using QSlider Desktop and Mobile Development, 403 Using QSpinBox Desktop and Mobile Development, 403 Using QTableWidget Desktop and Mobile Development, 401 Using QTabWidget Desktop and Mobile Development, 399 Using QTreeView and QFileSystemModel Desktop and Mobile Development, 390 Using QTreeWidget and QTreeWidgetItem Desktop and Mobile Development, 391 Using QWebView Desktop and Mobile Development, 409 Using Self.Attribute Object Oriented Programming, 178 Index 811
833.
Ring Documentation, Release1.2 Using Self.Attribute in the Class Region to define new at- tributes What is new in Ring 1.1?, 37 Using Semi-colon after and between statements Syntax Flexibility, 514 Using Sublime Text 2 Using Other Code Editors, 60 Using the ’else’ keyword as ’other’ in switch statement Syntax Flexibility, 515 Using the ’elseif’ keyword as ’but’ in if statement Syntax Flexibility, 515 Using the ’end’ keyword in different control structures Syntax Flexibility, 516 Using the QColorDialog Class Desktop and Mobile Development, 432 Using the QFileDialog Class Desktop and Mobile Development, 427 Using the QListWidget Class Desktop and Mobile Development, 387 Using the QTextEdit Class Desktop and Mobile Development, 386 Using the QTimer Class Desktop and Mobile Development, 424 Using the tool Code Generator, 560 Using This.Attribute in nested Braces inside the Class Methods What is new in Ring 1.1?, 37 Using Visual Studio IDE Using Other Code Editors, 61 value() Stdlib Functions, 203 Variables Deep Copy, 62 Dynamic Typing, 62 Introduction, 61 Weakly Typed, 63 Variables Scope Functions, 86 varptr() Low Level Functions, 538 Version() Function System Functions, 133 Virtual Machine Instructions Reference, 779 Visual Implementation Language Design, 17 Weakly Typed Variables, 63 Web Development (CGI Library) Application Class, 302 Configure the Apache web server, 255 Cookies, 267 CRUD Example using MVC, 288 Database, ModelBase & ControllerBase classes, 296 Generating Pages using Objects, 279 Gradient, 278 Hash Functions, 273 Hello World Program using the Web Library, 256 HTML Lists, 276 HTML Special Characters, 272 HTML Tables, 277 HTTP Get Example, 257 HTTP POST Example, 262 Introduction, 254 Page Class, 303 Random Image, 275 Ring CGI Hello World Program, 256 ScriptFunctions Class, 305 StyleFunctions Class, 305 Templates, 270 Upload Files, 264 URL Encode, 269 Users registration and Login, 290 Using Bootstrap Library using Functions, 284 Using Bootstrap Library using Objects, 285 Web Library Features, 257 WebLib API, 301 Web Library Features Web Development (CGI Library), 257 WebLib API Web Development (CGI Library), 301 Weight History Application Desktop and Mobile Development, 452 Werdy Application Applications developed in little hours, 4 What about predefined parameters or optional parameters in functions? Frequently Asked Questions, 755 What about the Boolean values in Ring? Frequently Asked Questions, 748 What are the advantages to using Ring over C# or Java? Frequently Asked Questions, 746 What are the advantages to using Ring over Lisp or Smalltalk? Frequently Asked Questions, 743 What are the advantages to using Ring over native C or C++? Frequently Asked Questions, 744 What are the advantages to using Ring over Python and Ruby? Frequently Asked Questions, 745 What are the advantages to using Ring over Tcl and Lua? Frequently Asked Questions, 746 What happens when we create a new object? Frequently Asked Questions, 751 Index 812
834.
Ring Documentation, Release1.2 What is new in Ring 1.1? Better Code Generator for Extensions, 37 Better Documentation, 37 Better Natural Language Programming Support, 29 Game Engine for 2D Games, 35 Generate/Execute Ring Object Files (*.ringo), 30 Introduction, 28 List of changes and new features, 29 New Functions and Changes, 32 RingLibSDL, 35 RingSQLite, 36 StdLib functions and classes written in Ring, 33 Syntax Flexibility, 30 Using Self.Attribute in the Class Region to define new attributes, 37 Using This.Attribute in nested Braces inside the Class Methods, 37 What is new in Ring 1.2? Better Call Command, 27 Better Functions, 24 Better Quality, 27 Better Ring Notepad, 24 Better RingQt, 24 Display Warnings Option, 27 Introduction, 22 List of changes and new features, 23 New Functions, 23 Objects Library for RingQt, 25 RingLibCurl, 26 Using NULL instead of NULLPointer(), 27 What is the difference between Ring and Python? And is Ring Open Source? Frequently Asked Questions, 744 Where can I write a program and execute it? Frequently Asked Questions, 754 While Loop Control Structures - First Style, 68 Control Structures - Third Style, 78 Why do we need Yet Another Programming Language (YAPL)? Frequently Asked Questions, 742 Why I get a strange result when printing nl with lists? Frequently Asked Questions, 756 Why I get Calling Function without definition Error? Frequently Asked Questions, 767 Why Ring is largely focussed on UI creation? Frequently Asked Questions, 744 Why Ring is weakly typed? Frequently Asked Questions, 743 Why Ring uses ’See’, ’Give’, ’But’ and ’Ok’ Keywords? Frequently Asked Questions, 747 Why Ring? Language Design, 14 Why setClickEvent() doesn’t see the object methods di- rectly? Frequently Asked Questions, 767 Why the ability to define your own languages Instead of just handing over the syntax so you can parse it using whatever code you like? Frequently Asked Questions, 747 Why the window title bar is going outside the screen? Frequently Asked Questions, 761 Why this example use the GetChar() twice? Frequently Asked Questions, 758 Why we don’t use () after the qApp class name? Frequently Asked Questions, 761 Why you can specify the number of loops you want to break out of? Frequently Asked Questions, 747 Windowsnl() Function System Functions, 130 Wrap structures Code Generator, 562 Wrapping C++ Classes Code Generator, 567 Write file using Write() Files, 120 Writing Comments Getting Started - First Style, 45 Getting Started - Second Style, 47 Getting Started - Third Style, 49 Index 813