What is new in Ring 1.5?

In this chapter we will learn about the changes and new features in Ring 1.5 release.

List of changes and new features

Ring 1.5 comes with many new features!

  • Video-Music-Player Application

  • Windows StartUp Manager Application

  • Calculator Application

  • Better Ring Notepad

  • Better StdLib

  • Better WebLib

  • Better RingQt

  • Better Objects Library

  • RingFreeGLUT Extension

  • RingOpenGL Extension

  • Better Code Generator for Extensions

  • Better Documentation Generator for Extensions

  • Ring VM - Tracing Functions

  • Trace Library and Interactive Debugger

  • More Syntax Flexibility

  • Type Hints Library

  • Better Quality

Video-Music-Player Application

The Video-Music-Player application is added to the Applications folder.

Screen Shot:

Video Music Player

Windows StartUp Manager Application

The Windows StartUp Manager

URL : https://github.com/ring-lang/WinStartupManager

Screen Shot:

Windows Startup Manager

Calculator Application

The Calculator application is added to the Applications folder.

Screen Shot:

Calculator Application

Better Ring Notepad

  1. Ring Notepad is updated to include some new styles and the Main File ToolBar

The idea of the Main File ToolBar is to determine the main file in the project When the project contains many source code files

This way you can run the project ( Main File ) at any time while opening other files in the project without the need to switch to the Main File to run the project.

To quickly use this feature

(Open the project main file)

Press Ctrl+Shift+M to set the current source code file as the main file

Open and modify other source code files in the project

To run the project (Main File) at any time press Ctrl+Shift+F5 (GUI) or Ctrl+Shift+D (Console)

Screen Shots:

Ring Notepad Ring Notepad Ring Notepad
  1. The output window is updated to display the new lines correctly and contains the "Clear" button.

Screen Shot:

Output Window

(3) The Ring Notepad is updated to quickly open and switch between large files while preparing the functions/classes lists in the background.

Screen Shot:

Ring Notepad - Large Files

Better StdLib

New Functions

  • Print2Str()

  • ListAllFiles()

  • SystemCmd()

  1. The Print2Str() is a new function added to the StdLib

Example:

load "stdlib.ring"
world = "World!"
mystring = print2str("Hello, #{world} \nIn Year \n#{2000+17} \n")
see mystring + nl

Output:

Hello, World!
In Year
2017
  1. The ListAllFiles() is a new function added to the StdLib

Using this function we can quickly do a process on a group of files in a folder and it’s sub folders.

Example:

load "stdlib.ring"
aList = ListAllFiles("c:/ring/ringlibs","ring") # *.ring only
aList = sort(aList)
see aList

Example:

load "stdlib.ring"
see listallfiles("b:/ring/ringlibs/weblib","") # All Files
  1. The SystemCmd() is a new function added to the StdLib

The function will execute a system command like the System() function but will return the output in a string.

Example:

cYou = SystemCmd("whoami")
See "SystemCmd: whoami ====="+ nl + cYou +nl

Output:

SystemCmd: whoami =====
desktop-umberto\umberto

Better WebLib

The WebLib is updated to include the HTMLPage class

Using this class we can create HTML documents without printing the output to the standard output

So instead of using the WebLib in Web Applications only

We can use it in Console/GUI/Mobile Applications too

Example:

load "stdlib.ring"
load "weblib.ring"
import System.Web
func main
 mypage = new HtmlPage {
 h1 { text("Customers Report") }
 Table
 {
 style = stylewidth("100%") + stylegradient(4)
 TR
 {
 TD { WIDTH="10%" text("Customers Count : " ) }
 TD { text (100) }
 }
 }
 Table
 {
 style = stylewidth("100%") + stylegradient(26)
 TR
 {
 style = stylewidth("100%") + stylegradient(24)
 TD { text("Name " ) }
 TD { text("Age" ) }
 TD { text("Country" ) }
 TD { text("Job" ) }
 TD { text("Company" ) }
 }
 for x = 1 to 100
 TR
 {
 TD { text("Test" ) }
 TD { text("30" ) }
 TD { text("Egypt" ) }
 TD { text("Sales" ) }
 TD { text("Future" ) }
 }
 next
 }
 }
 write("report.html",mypage.output())

Using this feature we can create reports quickly using WebLib & GUILib together

Example:

load "stdlib.ring"
load "weblib.ring"
load "guilib.ring"
import System.Web
import System.GUI
new qApp {
 open_window(:CustomersReportController)
 exec()
}
class CustomersReportController
 oView = new CustomersReportView
 func Start
 CreateReport()
 func CreateReport
 mypage = new HtmlPage {
 h1 { text("Customers Report") }
 Table
 {
 style = stylewidth("100%") + stylegradient(4)
 TR
 {
 TD { WIDTH="10%"
 text("Customers Count : " ) }
 TD { text (100) }
 }
 }
 Table
 {
 style = stylewidth("100%") + stylegradient(26)
 TR
 {
 style = stylewidth("100%") +
 stylegradient(24)
 TD { text("Name " ) }
 TD { text("Age" ) }
 TD { text("Country" ) }
 TD { text("Job" ) }
 TD { text("Company" ) }
 }
 for x = 1 to 100
 TR
 {
 TD { text("Test" ) }
 TD { text("30" ) }
 TD { text("Egypt" ) }
 TD { text("Sales" ) }
 TD { text("Future" ) }
 }
 next
 }
 }
 write("report.html",mypage.output())
 func PrintEvent
 printer1 = new qPrinter(0) {
 setoutputformat(1)
 setoutputfilename("report.pdf")
 }
 oView {
 web.print(printer1)
 web.show()
 }
 system ("report.pdf")
class CustomersReportView
 win = new window() {
 setwindowtitle("Report Window")
 setgeometry(100,100,500,500)
 web = new webview(win) {
 setgeometry(100,100,1000,500)
 loadpage(new qurl("file:///"+
 currentdir()+"/report.html"))
 }
 new pushbutton(win) {
 setGeometry(100,20,100,30)
 settext("Print")
 setclickevent(Method(:PrintEvent))
 }
 showMaximized()
 }

Screen Shot:

Customers Report

Better RingQt

New classes added to RingQt :

  • QStringRef

  • QMutex

  • QMutexLocker

  • QBuffer

  • QBluetoothAddress

  • QBluetoothDeviceDiscoveryAgent

  • QBluetoothDeviceInfo

  • QBluetoothHostInfo

  • QBluetoothLocalDevice

  • QBluetoothServer

  • QBluetoothServiceDiscoveryAgent

  • QBluetoothServiceInfo

  • QBluetoothSocket

  • QBluetoothTransferManager

  • QBluetoothTransferReply

  • QBluetoothTransferRequest

  • QBluetoothUuid

Example:

### Submits your car VIN - Vehicle Id Number - to the Web Site - vpic.nhtsa.dot.gov -
### Parses XML data returned
### Prints out the car info result
load "libcurl.ring"
load "guilib.ring"
load "stdlib.ring"
curl = curl_easy_init()
# request = "3G1JC5248YS251015?format=xml" ### VIN - Chevrolet
 request = "3GYFK62847G247323?format=xml" ### VIN - Cadillac
call_type = "decodevinvalues/"
url = "https://vpic.nhtsa.dot.gov/api/vehicles/"
url_request = url + call_type + request
 See "URL Request: "+ url_request +nl
curl_easy_setopt(curl, curlopt_url, url_request)
response = curl_easy_perform_silent(curl);
 See nl +"Response Raw: "+ response +nl +nl
curl_easy_cleanup(curl)
xml = new qxmlstreamreader()
xml.adddata_2(response)
x = new qstringref()
while not xml.atend()
 if xml.error()
 see xml.errorstring() see nl
 exit loop
 ok
 x = xml.text()
 if not x.length() = 0
 see "Length: " see x.length() +" --- "
 see "Value: " see x.tostring() see nl
 ok
 xml.readnext()
end
get x
###------------------------------------------
### Results
#
# ==>Value: 115
# ==>Value: Results returned successfully
# ==>Value: VIN(s): 3G1JC5248YS251015
# ==>Value: 3G1JC5248YS251015
# ==>Value: Sedan/Saloon
# ==>Value: 4
# ==>Value: 2200.0
# ==>Value: 134.25223700841
# ==>Value: 2.2
# ==>Value: 4
# ==>Value: LN2
# ==>Value: CHEVROLET
# ==>Value: GENERAL MOTORS LLC
# ==>Value: Cavalier
# ==>Value: 2000
# ==>Value: Ramos Arzipe
# ==>Value: PASSENGER CAR
# ==>Value: 4
# ==>Value: In-Line
# ==>Value: 1st Row (Driver & Passenger)
# ==>Value: Sequential Fuel Injection (SFI)
# ==>Value: Mexico
# ==>Value: NA
# ==>Value: Manual
# ==>Value: Body Type: Sedan, 4-6 Window, Notchback (GM codes: 19, 69)
# ==>Value: Name Plate: Chevrolet, Pontiac
# ==>Value: 0 - VIN decoded clean. Check Digit (9th position) is correct
# ==>Value: LAN
# ==>Value: 984
#
###-----------------------------------------

Better Objects Library

The function Open_WindowInPackages() is added to the Objects library.

The Open_WindowInPackages() function is the same as Open_Window() but takes an extra list that determine the packages to import before opening the window.

Syntax:

Open_WindowInPackages(cClassName,aPackagesList)

Example:

The next example from the Form Designer source code, Open the Window Flags window using the open_windowInPackages() function.

We determine the class name "WindowFlagsController" and the packages name.

The Window Flags window uses the FormDesigner and System.GUI packages.

open_windowInPackages(:WindowFlagsController,[
 "formdesigner",
 "System.GUI"
])

RingFreeGLUT Extension

Ring 1.5 comes with RingFreeGLUT extension to support the FreeGLUT library

Example:

/*
 This sample is based on C Tutorials
 from : http://www.lighthouse3d.com/tutorials/glut-tutorial/
*/
load "freeglut.ring"
load "opengl21lib.ring"
// angle of rotation for the camera direction
angle = 0.0
// actual vector representing the camera's direction
lx=0.0 lz=-1.0
// XZ position of the camera
x=0.0 z=5.0
// the key states. These variables will be zero
//when no key is being presses
deltaAngle = 0.0
deltaMove = 0
xOrigin = -1
// Constant definitions for Menus
C_RED = 1
C_GREEN = 2
C_BLUE = 3
C_ORANGE = 4
C_FILL = 5
C_LINE = 6
// Pop up menu identifiers
fillMenu=NULL
fontMenu=NULL
mainMenu=NULL
colorMenu=NULL
// color for the nose
red = 1.0
blue=0.5
green=0.5
// scale of snowman
scale = 1.0
// menu status
menuFlag = 0
// default font
font = GLUT_BITMAP_TIMES_ROMAN_24
C_INT_GLUT_BITMAP_8_BY_13 = 7
C_INT_GLUT_BITMAP_9_BY_15 = 8
C_INT_GLUT_BITMAP_TIMES_ROMAN_10 = 9
C_INT_GLUT_BITMAP_TIMES_ROMAN_24 = 10
C_INT_GLUT_BITMAP_HELVETICA_10 = 11
C_INT_GLUT_BITMAP_HELVETICA_12 = 12
C_INT_GLUT_BITMAP_HELVETICA_18 = 13
// width and height of the window
h = 0
w = 0
// variables to compute frames per second
frame=0
time=0
timebase=0
s = ""
func changeSize
 w = glutEventWidth()
 h = glutEventHeight()
 // Prevent a divide by zero, when window is too short
 // (you cant make a window of zero width).
 if h = 0
 h = 1
 ok
 ratio = w * 1.0 / h
 // Use the Projection Matrix
 glMatrixMode(GL_PROJECTION)
 // Reset Matrix
 glLoadIdentity()
 // Set the viewport to be the entire window
 glViewport(0, 0, w, h)
 // Set the correct perspective.
 gluPerspective(45.0, ratio, 0.1, 100.0)
 // Get Back to the Modelview
 glMatrixMode(GL_MODELVIEW)
func drawSnowMan
 glScalef(scale, scale, scale)
 glColor3f(1.0, 1.0, 1.0)
// Draw Body
 glTranslatef(0.0 ,0.75, 0.0)
 glutSolidSphere(0.75,20,20)
// Draw Head
 glTranslatef(0.0, 1.0, 0.0)
 glutSolidSphere(0.25,20,20)
// Draw Eyes
 glPushMatrix()
 glColor3f(0.0,0.0,0.0)
 glTranslatef(0.05, 0.10, 0.18)
 glutSolidSphere(0.05,10,10)
 glTranslatef(-0.1, 0.0, 0.0)
 glutSolidSphere(0.05,10,10)
 glPopMatrix()
// Draw Nose
 glColor3f(red, green, blue)
 glRotatef(0.0,1.0, 0.0, 0.0)
 glutSolidCone(0.08,0.5,10,2)
 glColor3f(1.0, 1.0, 1.0)
func renderBitmapString x,y,z,font,string
 glRasterPos3f(x, y,z)
 for c in string
 glutBitmapCharacter(font,ascii(c))
 next
func renderStrokeFontString x,y,z,font,string
 glPushMatrix()
 glTranslatef(x, y,z)
 glScalef(0.002, 0.002, 0.002)
 for c in string
 glutStrokeCharacter(font, Ascii(c));
 next
 glPopMatrix()
func restorePerspectiveProjection
 glMatrixMode(GL_PROJECTION)
 // restore previous projection matrix
 glPopMatrix()
 // get back to modelview mode
 glMatrixMode(GL_MODELVIEW)
func setOrthographicProjection
 // switch to projection mode
 glMatrixMode(GL_PROJECTION)
 // save previous matrix which contains the
 //settings for the perspective projection
 glPushMatrix()
 // reset matrix
 glLoadIdentity()
 // set a 2D orthographic projection
 gluOrtho2D(0, w, h, 0)
 // switch back to modelview mode
 glMatrixMode(GL_MODELVIEW)
func computePos deltaMove
 x += deltaMove * lx * 0.1
 z += deltaMove * lz * 0.1
func renderScene
 if deltaMove
 computePos(deltaMove)
 ok
 // Clear Color and Depth Buffers
 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
 // Reset transformations
 glLoadIdentity()
 // Set the camera
 gluLookAt( x, 1.0, z,
 x+lx, 1.0, z+lz,
 0.0, 1.0, 0.0)
 // Draw ground
 glColor3f(0.9, 0.9, 0.9)
 glBegin(GL_QUADS)
 glVertex3f(-100.0, 0.0, -100.0)
 glVertex3f(-100.0, 0.0, 100.0)
 glVertex3f( 100.0, 0.0, 100.0)
 glVertex3f( 100.0, 0.0, -100.0)
 glEnd()
// Draw 9 SnowMen
 for i = -3 to -1
 for j = -3 to -1
 glPushMatrix()
 glTranslatef(i*10.0, 0.0, j * 10.0)
 drawSnowMan()
 number = (i+3)*3+(j+3)
 renderBitmapString(0.0, 0.5, 0.0,font ,""+number)
 glPopMatrix()
 next
 next
 // Code to compute frames per second
 frame++
 time=glutGet(GLUT_ELAPSED_TIME)
 if time - timebase > 1000
 s = "RingFreeGLUT - FPS: " + (frame*1000.0/(time-timebase))
 timebase = time
 frame = 0
 ok
 // Code to display a string (fps) with bitmap fonts
 setOrthographicProjection()
 glPushMatrix()
 glLoadIdentity()
 renderBitmapString(5,30,0,GLUT_BITMAP_HELVETICA_18,s)
 glPopMatrix()
 restorePerspectiveProjection()
 glutSwapBuffers()
// -----------------------------------
// KEYBOARD
// -----------------------------------
func processNormalKeys
 key = glutEventKey()
 xx = glutEventX()
 yy = glutEventY()
 switch key
 on 27
 glutDestroyMenu(mainMenu)
 glutDestroyMenu(fillMenu)
 glutDestroyMenu(colorMenu)
 glutDestroyMenu(fontMenu)
 Shutdown()
 off
func pressKey
 key = glutEventKey()
 xx = glutEventX()
 yy = glutEventY()
 switch key
 on GLUT_KEY_UP
 deltaMove = 0.5
 on GLUT_KEY_DOWN
 deltaMove = -0.5
 off
func releaseKey
 key = glutEventKey()
 switch key
 on GLUT_KEY_UP
 deltaMove = 0
 on GLUT_KEY_DOWN
 deltaMove = 0
 off
// -----------------------------------
// MOUSE
// -----------------------------------
func mouseMove
 xx = glutEventX()
 yy = glutEventY()
 // this will only be true when the left button is down
 if xOrigin >= 0
 // update deltaAngle
 deltaAngle = (xx - xOrigin) * 0.001
 // update camera's direction
 lx = sin(angle + deltaAngle)
 lz = -cos(angle + deltaAngle)
 ok
func mouseButton
 button = glutEventButton()
 state = glutEventState()
 xx = glutEventX()
 yy = glutEventY()
 // only start motion if the left button is pressed
 if button = GLUT_LEFT_BUTTON
 // when the button is released
 if state = GLUT_UP
 angle += deltaAngle
 xOrigin = -1
 else
 // state = GLUT_DOWN
 xOrigin = xx
 ok
 ok
// -----------------------------------
// MENUS
// -----------------------------------
func processMenuStatus
 status = glutEventStatus()
 if status = GLUT_MENU_IN_USE
 menuFlag = 1
 else
 menuFlag = 0
 ok
func processMainMenu
 // nothing to do in here
 // all actions are for submenus
func processFillMenu
 option = glutEventValue()
 switch option
 on C_FILL
 glPolygonMode(GL_FRONT, GL_FILL)
 on C_LINE
 glPolygonMode(GL_FRONT, GL_LINE)
 off
func processFontMenu
 option = glutEventValue()
 switch (option) {
 on C_INT_GLUT_BITMAP_8_BY_13
 font = GLUT_BITMAP_8_BY_13
 on C_INT_GLUT_BITMAP_9_BY_15
 font = GLUT_BITMAP_9_BY_15
 on C_INT_GLUT_BITMAP_TIMES_ROMAN_10
 font = GLUT_BITMAP_TIMES_ROMAN_10
 on C_INT_GLUT_BITMAP_TIMES_ROMAN_24
 font = GLUT_BITMAP_TIMES_ROMAN_24
 on C_INT_GLUT_BITMAP_HELVETICA_10
 font = GLUT_BITMAP_HELVETICA_10
 on C_INT_GLUT_BITMAP_HELVETICA_12
 font = GLUT_BITMAP_HELVETICA_12
 on C_INT_GLUT_BITMAP_HELVETICA_18
 font = GLUT_BITMAP_HELVETICA_18
 off
func processColorMenu
 option = glutEventValue()
 switch option
 on C_RED
 red = 1.0
 green = 0.0
 blue = 0.0
 on C_GREEN
 red = 0.0
 green = 1.0
 blue = 0.0
 on C_BLUE
 red = 0.0
 green = 0.0
 blue = 1.0
 on C_ORANGE
 red = 1.0
 green = 0.5
 blue = 0.5
 off
func createPopupMenus
 fontMenu = glutCreateMenu(:processFontMenu)
 glutAddMenuEntry("BITMAP_8_BY_13 ",C_INT_GLUT_BITMAP_8_BY_13 )
 glutAddMenuEntry("BITMAP_9_BY_15",C_INT_GLUT_BITMAP_9_BY_15 )
 glutAddMenuEntry("BITMAP_TIMES_ROMAN_10 ",C_INT_GLUT_BITMAP_TIMES_ROMAN_10 )
 glutAddMenuEntry("BITMAP_TIMES_ROMAN_24",C_INT_GLUT_BITMAP_TIMES_ROMAN_24 )
 glutAddMenuEntry("BITMAP_HELVETICA_10 ",C_INT_GLUT_BITMAP_HELVETICA_10 )
 glutAddMenuEntry("BITMAP_HELVETICA_12",C_INT_GLUT_BITMAP_HELVETICA_12 )
 glutAddMenuEntry("BITMAP_HELVETICA_18",C_INT_GLUT_BITMAP_HELVETICA_18 )
 fillMenu = glutCreateMenu(:processFillMenu)
 glutAddMenuEntry("Fill",C_FILL)
 glutAddMenuEntry("Line",C_LINE)
 colorMenu = glutCreateMenu(:processColorMenu)
 glutAddMenuEntry("Red",C_RED);
 glutAddMenuEntry("Blue",C_BLUE);
 glutAddMenuEntry("Green",C_GREEN);
 glutAddMenuEntry("Orange",C_ORANGE);
 mainMenu = glutCreateMenu(:processMainMenu)
 glutAddSubMenu("Polygon Mode", fillMenu)
 glutAddSubMenu("Color", colorMenu)
 glutAddSubMenu("Font",fontMenu)
 // attach the menu to the right button
 glutAttachMenu(GLUT_RIGHT_BUTTON)
 // this will allow us to know if the menu is active
 glutMenuStatusFunc(:processMenuStatus)
// -----------------------------------
// MAIN
// -----------------------------------
func main
 // init GLUT and create window
 glutInit()
 glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA)
 glutInitWindowPosition(100,100)
 glutInitWindowSize(320,320)
 glutCreateWindow("RingFreeGLUT - Test - 9 SnowMan")
 // register callbacks
 glutDisplayFunc(:renderScene)
 glutReshapeFunc(:changeSize)
 glutIdleFunc(:renderScene)
 glutIgnoreKeyRepeat(1)
 glutKeyboardFunc(:processNormalKeys)
 glutSpecialFunc(:pressKey)
 glutSpecialUpFunc(:releaseKey)
 // here are the two new functions
 glutMouseFunc(:mouseButton)
 glutMotionFunc(:mouseMove)
 // OpenGL init
 glEnable(GL_DEPTH_TEST)
 glEnable(GL_CULL_FACE)
 // init Menus
 createPopupMenus()
 // enter GLUT event processing cycle
 glutMainLoop()

Screen Shots:

RingFreeGLUT RingFreeGLUT

RingOpenGL Extension

Ring 1.5 comes with RingOpenGL and support for the next versions

  • OpenGL 1.1

  • OpenGL 1.2

  • OpenGL 1.3

  • OpenGL 1.4

  • OpenGL 1.5

  • OpenGL 2.0

  • OpenGL 2.1

  • OpenGL 3.0

  • OpenGL 3.2

  • OpenGL 3.3

  • OpenGL 4.0

  • OpenGL 4.1

  • OpenGL 4.2

  • OpenGL 4.3

  • OpenGL 4.4

  • OpenGL 4.5

  • OpenGL 4.6

Example:

/*
 This sample is based on C Tutorials
 from :
 http://www.wikihow.com/Make-a-Cube-in-OpenGL
*/
load "freeglut.ring"
load "opengl21lib.ring"
// ----------------------------------------------------------
// Global Variables
// ----------------------------------------------------------
rotate_y=0
rotate_x=0
// ----------------------------------------------------------
// display() Callback function
// ----------------------------------------------------------
func display
 // Clear screen and Z-buffer
 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
 // Reset transformations
 glLoadIdentity()
 // Rotate when user changes rotate_x and rotate_y
 glRotatef( rotate_x, 1.0, 0.0, 0.0 )
 glRotatef( rotate_y, 0.0, 1.0, 0.0 )
 //Multi-colored side - FRONT
 glBegin(GL_POLYGON)
 glColor3f( 1.0, 0.0, 0.0 ) glVertex3f( 0.5, -0.5, -0.5 ) # P1 is red
 glColor3f( 0.0, 1.0, 0.0 ) glVertex3f( 0.5, 0.5, -0.5 ) # P2 is green
 glColor3f( 0.0, 0.0, 1.0 ) glVertex3f( -0.5, 0.5, -0.5 ) # P3 is blue
 glColor3f( 1.0, 0.0, 1.0 ) glVertex3f( -0.5, -0.5, -0.5 ) # P4 is purple
 glEnd()
 // White side - BACK
 glBegin(GL_POLYGON)
 glColor3f( 1.0, 1.0, 1.0 )
 glVertex3f( 0.5, -0.5, 0.5 )
 glVertex3f( 0.5, 0.5, 0.5 )
 glVertex3f( -0.5, 0.5, 0.5 )
 glVertex3f( -0.5, -0.5, 0.5 )
 glEnd()
 // Purple side - RIGHT
 glBegin(GL_POLYGON)
 glColor3f( 1.0, 0.0, 1.0 )
 glVertex3f( 0.5, -0.5, -0.5 )
 glVertex3f( 0.5, 0.5, -0.5 )
 glVertex3f( 0.5, 0.5, 0.5 )
 glVertex3f( 0.5, -0.5, 0.5 )
 glEnd()
 // Green side - LEFT
 glBegin(GL_POLYGON)
 glColor3f( 0.0, 1.0, 0.0 )
 glVertex3f( -0.5, -0.5, 0.5 )
 glVertex3f( -0.5, 0.5, 0.5 )
 glVertex3f( -0.5, 0.5, -0.5 )
 glVertex3f( -0.5, -0.5, -0.5 )
 glEnd()
 // Blue side - TOP
 glBegin(GL_POLYGON)
 glColor3f( 0.0, 0.0, 1.0 )
 glVertex3f( 0.5, 0.5, 0.5 )
 glVertex3f( 0.5, 0.5, -0.5 )
 glVertex3f( -0.5, 0.5, -0.5 )
 glVertex3f( -0.5, 0.5, 0.5 )
 glEnd()
 // Red side - BOTTOM
 glBegin(GL_POLYGON)
 glColor3f( 1.0, 0.0, 0.0 )
 glVertex3f( 0.5, -0.5, -0.5 )
 glVertex3f( 0.5, -0.5, 0.5 )
 glVertex3f( -0.5, -0.5, 0.5 )
 glVertex3f( -0.5, -0.5, -0.5 )
 glEnd()
 glFlush()
 glutSwapBuffers()
// ----------------------------------------------------------
// specialKeys() Callback Function
// ----------------------------------------------------------
func specialKeys
 key = glutEventKey()
 // Right arrow - increase rotation by 5 degree
 switch Key
 on GLUT_KEY_RIGHT
 rotate_y += 5
 // Left arrow - decrease rotation by 5 degree
 on GLUT_KEY_LEFT
 rotate_y -= 5
 on GLUT_KEY_UP
 rotate_x += 5
 on GLUT_KEY_DOWN
 rotate_x -= 5
 off
 // Request display update
 glutPostRedisplay()
// ----------------------------------------------------------
// main() function
// ----------------------------------------------------------
func main
 // Initialize GLUT and process user parameters
 glutInit()
 // Request double buffered true color window with Z-buffer
 glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH)
 // Create window
 glutCreateWindow("Awesome Cube")
 // Enable Z-buffer depth test
 glEnable(GL_DEPTH_TEST)
 // Callback functions
 glutDisplayFunc(:display)
 glutSpecialFunc(:specialKeys)
 // Pass control to GLUT for events
 glutMainLoop()
 // Return to OS

Screen Shot:

RingOpenGL

Better Code Generator for Extensions

The Code Generator is updated to support <constant> type, So we can have constants other than numbers, for example : Strings and Pointers.

When we have pointers we can determine the pointer type. To use this feature, before <constant> and </constant> we can use

$nDefaultConstantType = C_CONSTANT_TYPE_POINTER
$cDefaultConstantPointerType = "void *"

The next example from the RingFreeGLUT extension

<runcode>
 $nDefaultConstantType = C_CONSTANT_TYPE_POINTER
 $cDefaultConstantPointerType = "void"
</runcode>
<constant>
 GLUT_STROKE_ROMAN
 GLUT_STROKE_MONO_ROMAN
 GLUT_BITMAP_9_BY_15
 GLUT_BITMAP_8_BY_13
 GLUT_BITMAP_TIMES_ROMAN_10
 GLUT_BITMAP_TIMES_ROMAN_24
 GLUT_BITMAP_HELVETICA_10
 GLUT_BITMAP_HELVETICA_12
 GLUT_BITMAP_HELVETICA_18
</constant>

Better Documentation Generator for Extensions

The documentation generator for extensions is updated to generate a list of constants in the generated documentation

The previous versions provides the functions prototype only, Now we have the list of constants too.

Ring VM - Tracing Functions

In Ring 1.5 the next functions are added to Ring VM

  • RingVM_SetTrace(cCode)

  • RingVM_TraceData() –> aDataList

  • RingVM_TraceEvent() –> nTraceEvent

  • RingVM_TraceFunc() –> cCode

  • RingVM_ScopesCount() –> nScopes

  • RingVM_EvalInScope(nScope,cCode)

  • RingVM_PassError()

  • RingVM_HideErrorMsg(lStatus)

  • RingVM_CallFunc(cFuncName)

Example:

load "tracelib.ring"
ringvm_settrace("mytrace()")
see "Hello, world!" + nl
see "Welcome" + nl
see "How are you?" +nl
mytest()
new myclass { mymethod() }
func mytest
 see "Message from mytest" + nl
func mytrace
 see "====== The Trace function is Active ======" + nl +
 "Trace Function Name : " + ringvm_TraceFunc() + nl +
 "Trace Event : "
 switch ringvm_TraceEvent()
 on TRACEEVENT_NEWLINE see "New Line"
 on TRACEEVENT_NEWFUNC see "New Function"
 on TRACEEVENT_RETURN see "Return"
 on TRACEEVENT_ERROR see "Error"
 on TRACEEVENT_BEFORECFUNC see "Before C Function"
 on TRACEEVENT_AFTERCFUNC see "After C Function"
 off
 see nl +
 "Line Number : " + ringvm_tracedata()[TRACEDATA_LINENUMBER] + nl +
 "File Name : " + ringvm_tracedata()[TRACEDATA_FILENAME] + nl +
 "Function Name : " + ringvm_tracedata()[TRACEDATA_FUNCNAME] + nl +
 "Method or Function : "
 if ringvm_tracedata()[TRACEDATA_METHODORFUNC] =
 TRACEDATA_METHODORFUNC_METHOD
 see "Method"
 else
 if ringvm_tracedata()[TRACEDATA_FUNCNAME] = NULL
 see "Command"
 else
 see "Function"
 ok
 ok
 see nl + Copy("=",42) + nl
class myclass
 func mymethod
 see "Message from mymethod" + nl

Output:

====== The Trace function is Active ======
Trace Function Name : mytrace()
Trace Event : After C Function
Line Number : 3
File Name : test1.ring
Function Name : ringvm_settrace
Method or Function : Function
==========================================
====== The Trace function is Active ======
Trace Function Name : mytrace()
Trace Event : New Line
Line Number : 5
File Name : test1.ring
Function Name :
Method or Function : Command
==========================================
Hello, world!
====== The Trace function is Active ======
Trace Function Name : mytrace()
Trace Event : New Line
Line Number : 6
File Name : test1.ring
Function Name :
Method or Function : Command
==========================================
Welcome
====== The Trace function is Active ======
Trace Function Name : mytrace()
Trace Event : New Line
Line Number : 7
File Name : test1.ring
Function Name :
Method or Function : Command
==========================================
How are you?
====== The Trace function is Active ======
Trace Function Name : mytrace()
Trace Event : New Line
Line Number : 8
File Name : test1.ring
Function Name :
Method or Function : Command
==========================================
====== The Trace function is Active ======
Trace Function Name : mytrace()
Trace Event : New Function
Line Number : 8
File Name : test1.ring
Function Name : mytest
Method or Function : Function
==========================================
====== The Trace function is Active ======
Trace Function Name : mytrace()
Trace Event : New Line
Line Number : 12
File Name : test1.ring
Function Name : mytest
Method or Function : Function
==========================================
Message from mytest
====== The Trace function is Active ======
Trace Function Name : mytrace()
Trace Event : New Line
Line Number : 14
File Name : test1.ring
Function Name : mytest
Method or Function : Function
==========================================
====== The Trace function is Active ======
Trace Function Name : mytrace()
Trace Event : Return
Line Number : 8
File Name : test1.ring
Function Name :
Method or Function : Command
==========================================
====== The Trace function is Active ======
Trace Function Name : mytrace()
Trace Event : New Line
Line Number : 9
File Name : test1.ring
Function Name :
Method or Function : Command
==========================================
====== The Trace function is Active ======
Trace Function Name : mytrace()
Trace Event : New Line
Line Number : 43
File Name : test1.ring
Function Name :
Method or Function : Command
==========================================
====== The Trace function is Active ======
Trace Function Name : mytrace()
Trace Event : Before C Function
Line Number : 9
File Name : test1.ring
Function Name : ismethod
Method or Function : Function
==========================================
====== The Trace function is Active ======
Trace Function Name : mytrace()
Trace Event : After C Function
Line Number : 9
File Name : test1.ring
Function Name : ismethod
Method or Function : Function
==========================================
====== The Trace function is Active ======
Trace Function Name : mytrace()
Trace Event : New Function
Line Number : 9
File Name : test1.ring
Function Name : mymethod
Method or Function : Method
==========================================
====== The Trace function is Active ======
Trace Function Name : mytrace()
Trace Event : New Line
Line Number : 44
File Name : test1.ring
Function Name : mymethod
Method or Function : Method
==========================================
Message from mymethod
====== The Trace function is Active ======
Trace Function Name : mytrace()
Trace Event : Return
Line Number : 9
File Name : test1.ring
Function Name :
Method or Function : Command
==========================================
====== The Trace function is Active ======
Trace Function Name : mytrace()
Trace Event : Before C Function
Line Number : 9
File Name : test1.ring
Function Name : ismethod
Method or Function : Function
==========================================
====== The Trace function is Active ======
Trace Function Name : mytrace()
Trace Event : After C Function
Line Number : 9
File Name : test1.ring
Function Name : ismethod
Method or Function : Function
==========================================
====== The Trace function is Active ======
Trace Function Name : mytrace()
Trace Event : Before C Function
Line Number : 9
File Name : test1.ring
Function Name : ismethod
Method or Function : Function
==========================================
====== The Trace function is Active ======
Trace Function Name : mytrace()
Trace Event : After C Function
Line Number : 9
File Name : test1.ring
Function Name : ismethod
Method or Function : Function
==========================================
====== The Trace function is Active ======
Trace Function Name : mytrace()
Trace Event : New Line
Line Number : 11
File Name : test1.ring
Function Name :
Method or Function : Command
==========================================

Trace Library and Interactive Debugger

Ring 1.5 comes with the Trace Library and the Interactive Debugger

Using this library we can trace events, execute programs line by line, open the Interactive Debugger when an error happens or at breakpoints.

Example:

The next example uses a Breakpoint to open the Interactive Debugger!

load "tracelib.ring"
test1()
func test1
 x = 10
 see :test1 + nl
 t = 12
 BreakPoint()
 see "After breakpoint!" +nl
 see "t = " + t + nl
 see "End of program!" + nl

Screen Shots:

We have the Interactive Debugger at the Breakpoint!

Interactive Debugger

We can print the variables values

Interactive Debugger

We can change the variables values then continue execution

Interactive Debugger

We can run the Interactive Debugger in the Output Window

Interactive Debugger

More Syntax Flexibility

  • Using braces { } in Packages/Classes/Functions

Example:

load "stdlib.ring"
import mypackage
new myclass {
 myfunc()
}
package mypackage
{
 class myclass
 {
 func myfunc
 {
 print("Hello, World!\n")
 }
 }
}
  • Using ‘end’ keyword after Packages/Classes/Functions

Example:

import mypackage
new myclass {
 myfunc()
}
package mypackage
 class myclass
 def myfunc
 put "Hello, World!"
 end
 end
end
  • Using ‘endpackage’/’endclass’/’endfunc’ keywords after Packages/Classes/Functions

Example:

import mypackage
new myclass { myfunc() }
package mypackage
 class myclass
 func myfunc
 see "welcome" + nl
 endfunc
 endclass
endpackage

Type Hints Library

Ring 1.5 comes with the Type Hints library

Using this library we can add the type information to the source code which will be very useful for tools like

  • Code Editors

  • Static-Analysis

Example:

load "typehints.ring"
see sum(3,4) + nl ;
see sayHello("Mahmoud");
int func sum(int x,int y) {
 return x+y ;
}
string func sayHello(string name) {
 return "Hello " + name ;
}

The library is very powerful and support the User types (Classes) automatically!

Example:

load "typehints.ring"
import mypackage
test() { main([:one,:two,:three]) }
myclass func test() {
 see "Testing User Types!" + nl
 return new myclass
}
package mypackage {
 public class myclass {
 public static void func main(list args) {
 see "welcome" + nl
 see args
 }
 }
}

Also You can use the types inside the code (not only the function prototype)

Example:

load "typehints.ring"
int sum = sum(3,4)
string msg = sayHello("Mahmoud")
see "Sum = " + sum + nl + msg + nl
int func sum(int x,int y) {
 return x+y ;
}
string func sayHello(string name) {
 return "Hello " + name ;
}

Rules:

  • To use the types in the function prototype, You must use ‘(‘ and ‘)’ around parameters

  • To use the types in the function code, You must set the variable value (Assignment).

Note

Ring is a dynamic language, No type checking will be done by the compiler.

Better Quality

Based on Ring usage every day in practical projects

Ring 1.5 is more stable and more productive!

We are adding features based on clear vision and practical needs.

Also the documentation is better.

What is new in Ring 1.5.1?

  • Better Documentation

  • StdLib - Factorial() function update

  • RingVM - Better code for clearing the stack in the Class Region.

  • Sample : 3D Cube (OpenGL) + Texture Image using GameLib (RingAllegro)

Source Code:

load "gamelib.ring"
load "opengl21lib.ring"
func main
 new GraphicsApp {
 start()
 }
class GraphicsApp from GraphicsAppBase
 TITLE = "Ring Cube"
 bitmap texture
 xrot = 0.0
 yrot = 0.0
 zrot = 0.0
 func loadresources
 bitmap = al_load_bitmap("ring.bmp")
 texture = al_get_opengl_texture(bitmap)
 func destroyResources
 al_destroy_bitmap(bitmap)
 func drawScene
 w = 800 h = 600
 ratio = w / h
 glViewport(0, 0, w, h)
 glMatrixMode(GL_PROJECTION)
 glLoadIdentity()
 gluPerspective(45,ratio,1,100)
 glMatrixMode(GL_MODELVIEW)
 glLoadIdentity()
 glEnable(GL_TEXTURE_2D)
 glShadeModel(GL_SMOOTH)
 glClearColor(0.0, 0.0, 0.0, 0.5)
 glClearDepth(1.0)
 glEnable(GL_DEPTH_TEST)
 glEnable(GL_CULL_FACE)
 glDepthFunc(GL_LEQUAL)
 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)
 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
 glLoadIdentity();
 glTranslatef(0.0,0.0,-5.0);
 glRotatef(xrot,1.0,0.0,0.0);
 glRotatef(yrot,0.0,1.0,0.0);
 glRotatef(zrot,0.0,0.0,1.0);
 glBindTexture(GL_TEXTURE_2D, texture)
 glBegin(GL_QUADS)
 // Front Face
 glTexCoord2f(0.0, 0.0) glVertex3f(-1.0, -1.0, 1.0)
 glTexCoord2f(1.0, 0.0) glVertex3f( 1.0, -1.0, 1.0)
 glTexCoord2f(1.0, 1.0) glVertex3f( 1.0, 1.0, 1.0)
 glTexCoord2f(0.0, 1.0) glVertex3f(-1.0, 1.0, 1.0)
 // Back Face
 glTexCoord2f(1.0, 0.0) glVertex3f(-1.0, -1.0, -1.0)
 glTexCoord2f(1.0, 1.0) glVertex3f(-1.0, 1.0, -1.0)
 glTexCoord2f(0.0, 1.0) glVertex3f( 1.0, 1.0, -1.0)
 glTexCoord2f(0.0, 0.0) glVertex3f( 1.0, -1.0, -1.0)
 // Top Face
 glTexCoord2f(0.0, 1.0) glVertex3f(-1.0, 1.0, -1.0)
 glTexCoord2f(0.0, 0.0) glVertex3f(-1.0, 1.0, 1.0)
 glTexCoord2f(1.0, 0.0) glVertex3f( 1.0, 1.0, 1.0)
 glTexCoord2f(1.0, 1.0) glVertex3f( 1.0, 1.0, -1.0)
 // Bottom Face
 glTexCoord2f(1.0, 1.0) glVertex3f(-1.0, -1.0, -1.0)
 glTexCoord2f(0.0, 1.0) glVertex3f( 1.0, -1.0, -1.0)
 glTexCoord2f(0.0, 0.0) glVertex3f( 1.0, -1.0, 1.0)
 glTexCoord2f(1.0, 0.0) glVertex3f(-1.0, -1.0, 1.0)
 // Right face
 glTexCoord2f(1.0, 0.0) glVertex3f( 1.0, -1.0, -1.0)
 glTexCoord2f(1.0, 1.0) glVertex3f( 1.0, 1.0, -1.0)
 glTexCoord2f(0.0, 1.0) glVertex3f( 1.0, 1.0, 1.0)
 glTexCoord2f(0.0, 0.0) glVertex3f( 1.0, -1.0, 1.0)
 // Left Face
 glTexCoord2f(0.0, 0.0) glVertex3f(-1.0, -1.0, -1.0)
 glTexCoord2f(1.0, 0.0) glVertex3f(-1.0, -1.0, 1.0)
 glTexCoord2f(1.0, 1.0) glVertex3f(-1.0, 1.0, 1.0)
 glTexCoord2f(0.0, 1.0) glVertex3f(-1.0, 1.0, -1.0)
 glEnd()
 xrot += 0.3
 yrot += 0.2
 zrot += 0.4
class GraphicsAppBase
 display event_queue ev timeout
 timer redraw = true
 FPS = 60
 SCREEN_W = 800
 SCREEN_H = 600
 KEY_UP = 1
 KEY_DOWN = 2
 KEY_LEFT = 3
 KEY_RIGHT = 4
 Key = [false,false,false,false]
 TITLE = "Graphics Application"
 func start
 SetUp()
 loadResources()
 eventsLoop()
 destroy()
 func setup
 al_init()
 al_init_image_addon()
 al_set_new_display_flags(ALLEGRO_OPENGL)
 display = al_create_display(SCREEN_W,SCREEN_H)
 al_set_Window_title(display,TITLE)
 al_clear_to_color(al_map_rgb(0,0,0))
 event_queue = al_create_event_queue()
 al_register_event_source(event_queue,
 al_get_display_event_source(display))
 ev = al_new_allegro_event()
 timeout = al_new_allegro_timeout()
 al_init_timeout(timeout, 0.06)
 timer = al_create_timer(1.0 / FPS)
 al_register_event_source(event_queue,
 al_get_timer_event_source(timer))
 al_start_timer(timer)
 al_install_mouse()
 al_register_event_source(event_queue,
 al_get_mouse_event_source())
 al_install_keyboard()
 al_register_event_source(event_queue,
 al_get_keyboard_event_source())
 func eventsLoop
 while true
 al_wait_for_event_until(event_queue, ev, timeout)
 switch al_get_allegro_event_type(ev)
 on ALLEGRO_EVENT_DISPLAY_CLOSE
 exit
 on ALLEGRO_EVENT_TIMER
 redraw = true
 on ALLEGRO_EVENT_MOUSE_AXES
 mouse_x = al_get_allegro_event_mouse_x(ev)
 mouse_y = al_get_allegro_event_mouse_y(ev)
 on ALLEGRO_EVENT_MOUSE_ENTER_DISPLAY
 mouse_x = al_get_allegro_event_mouse_x(ev)
 mouse_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
 drawScene()
 al_flip_display()
 ok
 callgc()
 end
 func destroy
 destroyResources()
 al_destroy_timer(timer)
 al_destroy_allegro_event(ev)
 al_destroy_allegro_timeout(timeout)
 al_destroy_event_queue(event_queue)
 al_destroy_display(display)
 func loadresources
 func drawScene
 func destroyResources

Screen Shot:

Ring Cube

What is new in Ring 1.5.2?

  • Documentation - Chapter "Applications developed in little hours" is updated

  • Ring Notepad - Display programs output in the output window on all platforms

  • Form Designer - Help Menu - Open CHM/PDF files without displaying the console window

  • Form Designer - Better response to Resize/Move Events when moving the Mouse quickly

  • Form Designer - New/Open/Save As, will open the Controller class in Ring Notepad

  • Form Designer - Added "Close Form" option to the file menu

  • Ring Notepad - Run, will save the current file (Also the opened Form) automatically

  • GetQuotesHistory Application - Updated to work on MacOS X and Qt 5.2

  • Calculator Application - Updated to include more features!

  • RingVM - Classification for Environment Errors (Check Chapter : Language Reference)

  • RingQt - New methods added to QAllEvents for faster Events execution

  • RingQt - Fusion Black Style - Better colors for disabled controls

  • Scripts - For building Ring on Fedora Linux (Check Chapter : Building From Source Code)

Screen Shot:

Ring on Fedora 1

What is new in Ring 1.5.3?

  • Form Designer : Close Action will notify Ring Notepad to be able to open the Form again

  • Form Designer : Save Action will open the controller class in Ring Notepad

  • Form Designer : Keep current control selected when selecting many controls using CTRL Key

  • Form Designer : Nice form back color when used in Ring Notepad (Style: Modern Black)

  • RingOpenSSL : Updated to support newer versions like OpenSSL 1.1

  • Building Scripts : Updated to work on Fedora 26 (64bit)

  • OpenGL : New Sample - Many Cubes (samples/3D/manycubes)

Screen Shot:

Many Cubes
  • RingQt : Add QDateTime Class

  • RingQt : New methods added to QMenu and QCursor Classes

Example:

load "guilib.ring"
new qApp {
 win = new qwidget() {
 setwindowtitle("Context Menu")
 resize(400,400)
 myfilter = new qAllEvents(win) {
 setContextmenuEvent("mymenu()")
 }
 installeventfilter(myfilter)
 show()
 }
 exec()
}
func mymenu
 new qMenu(win) {
 oAction = new qAction(win) {
 settext("new")
 setClickEvent("See :New")
 }
 addaction(oAction)
 oAction = new qAction(win) {
 settext("open")
 setClickEvent("See :Open")
 }
 addaction(oAction)
 oAction = new qAction(win) {
 settext("save")
 setClickEvent("See :Save")
 }
 addaction(oAction)
 oAction = new qAction(win) {
 settext("close")
 setClickEvent("See :Close")
 }
 addaction(oAction)
 oCursor = new qCursor()
 exec(oCursor.pos())
 }
  • Compiler : Support using _ in numbers

Example:

x = 1_000_000
see type(x)+nl
see x+1+nl

Output:

NUMBER
100000001
  • Compiler : Support using f after numbers

Example:

x = 19.99f
see type(x) + nl

Output:

NUMBER
  • Google API Shortener Application

Screen Shots:

URLShortener - shot 1
  • TicTacToe 3D Game

Screen Shot:

TicTacToe 3D Game

What is new in Ring 1.5.4?

  • CalmoSoft Fifteen Puzzle Game 3D

  • Ring Notepad - New Styles

  • Ring Notepad - Better Toolbar Style

  • Ring Notepad - View Modes

  • Ring Notepad - QPlainTextEdit - don’t set back color for the scroll bars

  • Ring Notepad - Style Fusion (White) - use Silver color for comments

  • Ring Notepad - Tab and Shift-Tab - Indent multiple lines

  • Form Designer - Better Toolbar Style

  • Form Designer - Nice backcolor for Window Flags and Menubar Designer

  • Form Designer - Default back color for controls

  • RingQt - Added grab() and windowHandle() methods to QWidget class

  • RingQt - Added new methods to QPixmap Class

  • RingQt - Added Classes :-
    • QScreen

    • QWindow

    • QGuiApplication

    • QTextBrowser

  • Code Generator for Extensions - Nonew Option - Support Parent Class

  • Ring VM - Internal Implementation - Pass state to Strings and Lists objects

  • Ring VM - Garbage Collector - Memory Pool for Small Objects

  • Ring VM - Better code for Saving/Restoring the State