Emulating a mainframe

General FreeBASIC programming questions.
Gablea
Posts: 1104
Joined: Apr 06, 2010 0:05
Location: Northampton, United Kingdom
Contact:

Emulating a mainframe

Post by Gablea »

Hi everyone

I was wondering if you all can help with a question.

I remember using a old dumb terminal that was connected to a Linux mainframe and allowed me to edit update delete items from a data table.

Does anyone know how they would have done the input screen?

Image

As you may see the “text” boxes are fields that are green and when you type the text is black (invented)

I know they would only Be text mode so how would they do that? (And would the same metholds work in a ascii only program in FreeBASIC)
bcohio2001
Posts: 556
Joined: Mar 10, 2007 15:44
Location: Ohio, USA
Contact:

Re: Emulating a mainframe

Post by bcohio2001 »

Yes, all text mode can be done like what is displayed.

The "grid boxes" are drawn using ascii codes 169 - 218. Using Code Page 437.

Text is printed by:

Code: Select all

Color Green, Black
Print "Current Date: ……"
And the input is:

Code: Select all

Color Black, Green
Input A
caseih
Posts: 2157
Joined: Feb 26, 2007 5:32

Re: Emulating a mainframe

Post by caseih »

Unix programs would use codes, similar to ANSI codes, to instruct the terminal screen to move the cursor, set the color, and draw characters. So boxes were simply drawn on the screen much like you do it now in FB, with "locate"-like commands, printing box drawing characters. Each character set had certain box-drawing characters you could write, like the other reply mentions. Since terminals were remote, there was no way for the unix program to ask the terminal to read back to it the existing contents of the display. So when a box needed to be popped up asking for input, the program would simply draw them on the screen, overwriting the background characters. After the box was done, the program would then redraw the entire screen (sometimes this was quite noticeably slow), erasing the popup box. This is actually the technique I would use on FB. Printing to the text console is fast enough nowadays that it would hardly be noticeable, and your program could be smart about only reprinting the areas that need to be reprinted. And actually this is really how GUI windows work under the hood also--the program just redraws pieces of the screen when windows disappear or move.

Years ago, the common need for drawing "windows" on the terminal and requesting keyboard input, combined with the need to understand special codes for displaying and keyboard input, led to the development of common libraries to automate this. The modern version of these libraries is called ncurses. There's even a port of it to Windows, called pdcurses. ncurses handles things like keyboard input (ctrl, alt combinations, special keys, key codes for letters and function keys), output (move cursor, set color, print text, box drawing), primitive text-based windows, and even mouse events. FB does rely on a part of ncurses called libtinfo to handle differences in the various types of terminal emulators used on Linux, but FB does not actually use ncurses itself for printing. Instead FB implements many things similar to ncurses in the runtime library for commands like LOCATE, PRINT, COLOR, INPUT, etc.

So the short answer to your question is yes, the same methods used by older unix programs can be done in text mode with FB with only the built-in commands, such as locate, print, color, input, etc. Years ago I wrote a simple text input field routine that would use inkey$ to make a simple field editor using whatever colors (inverse background or just underlines to mark the field). Could use arrow keys, had insert, delete, etc. You'd want to implement something similar as the INPUT command is fairly limited in terms of editing (can't throw in an existing value). I'll have to dig up the code and post it here.
Gablea
Posts: 1104
Joined: Apr 06, 2010 0:05
Location: Northampton, United Kingdom
Contact:

Re: Emulating a mainframe

Post by Gablea »

Thanks for the advice guys I am thinking about doing a basic program that I could use on my linux server and tuning it from a dumb terminal this has all given me a idea as how to do that I would have to come up with some simple screen designs as I’m sure they would be limited to what can be displayed and no tab support (like we have in windows etc)

@caseih
If you do not mind I would appreciate seeing your code as I will admit keyboard support has never been my strong point.
caseih
Posts: 2157
Joined: Feb 26, 2007 5:32

Re: Emulating a mainframe

Post by caseih »

Sure I can find it. It's made for qb/fblite, but could be adapted to run in normal FB. Give me a couple of days to put it together with a brief example of how to use it.
Gablea
Posts: 1104
Joined: Apr 06, 2010 0:05
Location: Northampton, United Kingdom
Contact:

Re: Emulating a mainframe

Post by Gablea »

@caseih
meany thanks. I do like my old systems :) I assume if I was to run this via a serial terminal on a Linux machine it would still work (I assume I can have 2 terminal connected to the machine at one time)
MrSwiss
Posts: 3910
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: Emulating a mainframe

Post by MrSwiss »

@Gablea,

if you are that much into 'old style', you may want to look at/read:
ASCII Art at Wikipedia ...
I've used that (simple frames) even in simple batch-jobs ...
batch-menues, to be more precise, however, in the late 1980th.

(And, I wouldn't want to go back there, there is simply no viable
reason, to do so!)
angros47
Posts: 2321
Joined: Jun 21, 2005 19:04

Re: Emulating a mainframe

Post by angros47 »

That kind of interface, drawn using only ASCII character, is called TUI (Text User Interface). Google for it, there are several libraries designed to help for it.
caseih
Posts: 2157
Joined: Feb 26, 2007 5:32

Re: Emulating a mainframe

Post by caseih »

I disagree about never going back. TUIs are alive and well and serve very useful purposes. I use several text mode programs with TUIs (menus, windows of sorts) on a regular basis. Remotely and locally. A GUI app will never replace these specific needs, though many have tried over the years.
Last edited by caseih on Aug 13, 2018 19:19, edited 1 time in total.
Gablea
Posts: 1104
Joined: Apr 06, 2010 0:05
Location: Northampton, United Kingdom
Contact:

Re: Emulating a mainframe

Post by Gablea »

I think a TUI is ideal for a keyboard based till application just need to work out how to do large fonts (like using xfont but would that work in text mode)
jj2007
Posts: 2326
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: Emulating a mainframe

Post by jj2007 »

bcohio2001 wrote:The "grid boxes" are drawn using ascii codes 169 - 218. Using Code Page 437
Thanks for the inspiration: The console isn't completely dead yet ;-)
grindstone
Posts: 862
Joined: May 05, 2015 5:35
Location: Germany

Re: Emulating a mainframe

Post by grindstone »

@Gablea: This is "my" substitution of the INPUT statement (I call it "stringmod.bi"). The options to imitate keystrokes with mouse and joystick and of running a plugin may be a little overhead for you, but you can submit an initial string to modify:

Code: Select all

Type tJoyBack
	up_ As String
	right_ As String
	down_ As String
	left_ As String
End Type
Dim Shared tJoyBackZero As tJoyBack

Declare Operator = (jr1 As tJoyBack, jr2 As tJoyBack) As Integer
Operator = (r1 As tJoyBack, r2 As tJoyBack) As Integer
	If r1.up_ <> r2.up_ Then Return 0
	If r1.right_ <> r2.right_ Then Return 0
	If r1.down_ <> r2.down_ Then Return 0
	If r1.left_ <> r2.left_ Then Return 0
	Return -1
End Operator

Operator <> (r1 As tJoyBack, r2 As tJoyBack) As Integer
	If r1.up_ <> r2.up_ Then Return -1
	If r1.right_ <> r2.right_ Then Return -1
	If r1.down_ <> r2.down_ Then Return -1
	If r1.left_ <> r2.left_ Then Return -1
	Return 0
End Operator

Type tMouseBack
	left_ As String
	middle_ As String
	right_ As String
	forward_ As String
	back_ As string
End Type
Dim Shared tMouseBackZero As tMouseBack	

Operator = (r1 As tMouseBack, r2 As tMouseBack) As Integer
	If r1.left_ <> r2.left_ Then Return 0
	If r1.middle_ <> r2.middle_ Then Return 0
	If r1.right_ <> r2.right_ Then Return 0
	If r1.forward_ <> r2.forward_ Then Return 0
	If r1.back_ <> r2.back_ Then Return 0
	Return -1
End Operator

Operator <> (r1 As tMouseBack, r2 As tMouseBack) As Integer
	If r1.left_ <> r2.left_ Then Return -1
	If r1.middle_ <> r2.middle_ Then Return -1
	If r1.right_ <> r2.right_ Then Return -1
	If r1.forward_ <> r2.forward_ Then Return -1
	If r1.back_ <> r2.back_ Then Return -1
	Return 0
End Operator

Declare Function stringmod(text As String = "", mode As Integer = 0, _
                           mouseback As tMouseBack = tMouseBackZero, _
                           joyback As tJoyBack = tJoyBackZero, _
                           callback As Any Ptr = 0) As String
Declare Function joysubst OverLoad () As Integer
Declare Function joysubst (top_ As String, right_ As String, _
                           left_ As String, bottom_ As String) As String
Declare Function joysubst (joyback As tJoyBack) As String
Declare Function mousesubst OverLoad (left_ As String = "", middle_ As String = "", _
                                     right_ As String = "", forward_ As String = "", _
                                     back_ As String = "" ) As String
Declare Function mousesubst(mouseback As tMouseBack) As String

Function stringmod(text As String = "", mode As Integer = 0, _
                           mouseback As tMouseBack = tMouseBackZero, _
                           joyback As tJoyBack = tJoyBackZero, _
                           callback As Any Ptr = 0) As String
'the submission of 'mode' is optional, default is 0
'mode0 --> normal function
'mode1 --> returns after 'arrow up', 'arrow down', 'screen up' and 'screen down'
'mode2 --> treats joystick movements like arrow keys (up, down, right, left)
'mode4 --> only sets the variable 'lasttext' and returns
'mode8 --> adds a Chr(27) at the beginning of the retrun string if 'esc' key is pressed 

'if  'mouseback' is submitted as a 6-character string (each 2 characters for left/mid/right),
' mouseklicks are treated like keystrokes.

'if a pointer to a callback routine is submitted, the input loop is redirected to this 
' routine, which can optional return a string that is treated like a keyboard input afterwards.
    
  Dim As Integer ze, sp, co, gi, lock_, ms, mz, wheel, buttons, length
  Dim As Single joyx, joyy
  Dim As String g, remember, txt
  Dim plugin As Sub (address As Any Ptr, length As Any Ptr)
    
  Static As String lasttext, g_back
  Static As Integer mousewheel
     
  If (mode And 4) Then
  	lasttext = text + " "
  	Return text
  EndIf
  
  If lasttext = "" Then
  	lasttext = " "
  EndIf
  
  txt = text + " "
  remember = txt
  co = Pos 'cursor offset
  ze = CsrLin
  sp = Len(txt) 'pointer to the character under the cursor
  lock_ = 0
      
  Locate ze, co, 1
  Print txt;
  Locate ze, sp+co-1, 1
  
  
  Do
    'input
    plugin = callback 'set pointer to the plugin
    If (callback <> 0) And (g_back = "") Then 'call plugin
    	g_back = String(200,Chr(0)) 'allocate memory for the return string
    	length = Len(g_back) 'max length of the return string
    	plugin(StrPtr(g_back),@length) 'call plugin
      g_back = Left(g_back,length) 'write return string to buffer
    EndIf
    
    If (mouseback <> tMouseBackZero) Then
  		g_back += mousesubst(mouseback)
    EndIf
		     
  	If (joyback <> tJoyBackZero) Then 'treats joystick like keys
	    g_back += joysubst(joyback)
  	EndIf
           
    If g_back = "" Then
    	g = InKey
    Else 'process return string
    	If Left(g_back,1) = Chr(255) Then 'control character
    		g = Left(g_back,2) 'imitated keystroke
    		g_back = Mid(g_back,3) 'shorten return string
    	Else 'normal character
    		g = Left(g_back,1) 'imitated keystroke
    		g_back = Mid(g_back,2) 'shorten return string
    	EndIf
    EndIf
        
    If Len(g) = 1 Then 'normal character
    	If g[0] > 31 Then 'character
        txt = Left(txt, sp - 1) + g + Mid(txt, sp)
        sp += 1
        Locate ze, co, 0
        Print txt;
        Locate ze, sp+co-1, 1
    	Else 'control character
        Select Case g[0] 
        	Case 8 ' back key
            If sp > 1 Then
              txt = Left(txt, sp - 2) + Mid(txt, sp)
              sp -= 1
              Locate ze, co, 0
              Print txt;
              Locate ze, sp+co-1, 1
            End If
        	Case 27 'esc
            If (mode And 8) Then
            	txt = Chr$(27) + txt
            Else
            	txt = remember 'old string
            EndIf
            g = Chr$(13) 'terminate
        End Select
      End If
    ElseIf Len(g) = 2 Then 'control character
    	gi = g[1] 
      Select Case gi 'control character
      	Case 75 'left arrow -> cursor left
          If sp > 1 Then
            sp -= 1
            Locate ze, sp+co-1, 1
          End If
      	Case 77 'right arrow -> cursor right
          If sp < Len(txt) Then
            sp += 1
            Locate ze, sp+co-1, 1
          ElseIf txt = " " Then 'set old string
          	txt = lasttext
          	sp = Len(txt)
          	Print txt;
          	Locate ze, sp+co-1, 1
          End If
      	Case 14 'back -> delete character left of cursor
          If sp > 1 Then
            txt = Left(txt, sp - 1) + Mid$(txt, sp)
            sp -= 1
            Locate ze, co, 0
            Print txt;
            Locate ze, sp+co-1, 1
          End If
      	Case 83 'del -> delete character right of cursor
          If sp < Len(txt) Then
            txt = Left(txt, sp - 1) + Mid$(txt, sp + 1)
            Locate ze, co, 0
            Print txt;
            Locate ze, sp+co-1, 1
          End If
      	Case 71 'pos1 -> set cursor to the beginning of the string
          sp = 1
          Locate ze, sp+co-1, 1
      	Case 79 'end -> set cursor to the end of the string
          sp = Len(txt)
          Locate ze, sp+co-1, 1
      	Case Else
      		If (mode And 1) Then
            txt = g + Chr$(ze) + Chr$(co) + txt 'return control character and cursor position
            g = Chr$(13)
          EndIf
      End Select
    Else 'no key
    	Sleep 1
    End If
  Loop Until g = Chr$(13) 'return
		
  lasttext = txt
  Return Left(txt, Len(txt) - 1)
  Locate ze, sp+co-1, 0 'cursor off
             
End Function

Function joysubst () As Integer
	
	Dim As Single joyx, joyy
	Dim As Integer buttons, output_
	Static As Integer lock_ = 0
	Static As Double locktime
	
	output_ = 0 'default value no key pressed
		
	If GetJoystick (0, buttons, joyx, joyy) Then
		'no joystick connected
	Else
		If joyx < -.5 Then 'left
		  output_ = 4
		ElseIf joyx > .5 Then 'right
			output_ = 2
		EndIf
		If joyy < -.5 Then 'top
			output_ = 1
		ElseIf joyy > .5 Then 'bottom
			output_ = 3
		EndIf
	EndIf
	
	If output_ = 0 Then 'no key pressed, set delay to 0
		lock_ = 0
	EndIf

	Select Case lock_ 'delay mode
		Case 0 'immediate execution 
			If output_ Then 'key pressed
				lock_ = 1 'delay mode
			  locktime = Timer + 0.3 'delay for 1st keystroke
			EndIf
		Case 1 'key is held down
			If Timer > locktime Then 'check if delay time is over
				lock_ = 2 'repeat mode
				locktime = Timer + 0.07 'delay value for repetition mode
			Else 'delay time not over
				output_ = 0
			EndIf
		Case 2 'delay mode
			If Timer > locktime Then 'check if delay time is over
				locktime = Timer + 0.07 'set time for the next delay loop
			Else 'delay time not over
				output_ = 0
			EndIf
	End Select
	
	Return output_
  
End Function

Function joysubst (up_ As String, right_ As String, _
                   down_ As String, left_ As String) As String
			
	Select Case joysubst()
		Case 0 'no key
			Return ""
		Case 1 'up
			Return up_
		Case 2 'right
			Return right_
		Case 3 'down
			Return down_
		Case 4 'left
			Return left_
	End Select
	
End Function

Function joysubst (joyback As tJoyBack) As String
			
	Select Case joysubst()
		Case 0 'no key
			Return ""
		Case 1 'top
			Return joyback.up_
		Case 2 'right
			Return joyback.right_
		Case 3 'bottom
			Return joyback.down_
		Case 4 'left
			Return joyback.left_
	End Select
	
End Function

Function mousesubst(mouseback As tMouseBack) As String
	Return mousesubst(mouseback.left_, mouseback.middle_, mouseback.right_, _
	                 mouseback.forward_, mouseback.back_)
End Function

Function mousesubst (left_ As String = "", middle_ As String = "", _
                    right_ As String = "", forward_ As String = "", _
                    back_ As String = "") As String
	Dim As Integer ms, mz, wheel, buttons
	Static As Integer mousewheel
	
	GetMouse (ms,mz,wheel,buttons)
	If (buttons And 1) Then 'left mouse button
		Function = left_
	ElseIf (buttons And 4) Then 'mid mouse button
		Function = middle_
	ElseIf (buttons And 2) Then 'right mouse button
		Function = right_
	EndIf
		    	
	If wheel < mousewheel Then
		Function = back_ 'mouse wheel back
		mousewheel = wheel
	ElseIf wheel > mousewheel Then
		Function = forward_ 'mouse wheel forward
		mousewheel = wheel
	EndIf
	
	Do 'wait for mouse button release
		GetMouse (ms,mz,wheel,buttons)
		Sleep 1
	Loop While buttons

End Function
marcov
Posts: 3455
Joined: Jun 16, 2005 9:45
Location: Netherlands
Contact:

Re: Emulating a mainframe

Post by marcov »

search for "vt220 escape sequences" Note that the linux console still uses such escape sequences.
jj2007
Posts: 2326
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: Emulating a mainframe

Post by jj2007 »

grindstone wrote:...you can submit an initial string to modify
Your code compiles but doesn't do anything. Can you show a usage example?
grindstone
Posts: 862
Joined: May 05, 2015 5:35
Location: Germany

Re: Emulating a mainframe

Post by grindstone »

Eagerly. Start the snippet, modify the preset sentence like in a textbox, then press return.

Code: Select all

#Include "stringmod.bi"

Dim As String textout
Dim As tMouseBack mouseBack

'simple stringmod example
Print "Preset string: ";
textout = stringmod("This is a stringmod example")
Locate 5,1
Print "Modified string: ";textout
Print
Print

'simple example how to substitute the mouse buttons and -wheel
Print "Now press your mouse buttons and move the wheel. End with RETURN"
With mouseBack 'preset mouse buttons and wheel with text
	.left_    = "You pressed the left mouse button ** "
	.middle_  = "You pressed the middle mouse button ** "
	.right_   = "You pressed the right mouse button ** "
	.forward_ = "You moved the wheel forward ** "
	.back_    = "You moved the wheel backward ** "
End With

Print
textout = stringmod("",, mouseBack) 
     
Print
Print
Print textout

Sleep
Post Reply