Enhancements For the Console Capability

Got an idea for enhancing PureBasic? New command(s) you'd like to see?
oldefoxx
Enthusiast
Enthusiast
Posts: 532
Joined: Fri Jul 25, 2003 11:24 pm

Enhancements For the Console Capability

Post by oldefoxx »

I've programmed in many BASICs over the decades, almost always in Console mode.
Why? The reason is simple. It's good enough to get the information across, and
you don't spend a lot of time designing and working with forms and related
objects.

PureBasic requires that you work in ConsoleGraphic(1) mode in order to use certain
features like ConsoleLocate(). That's fine. But there are a number of features that
have not been included.

CURLIN or CURSORY -- the ability to read what line the cursor is currently on
POS() or CURSORX -- the ability to read what column the cursor is currently on
SCREENY -- the ability to read how many lines are available in the Console screen
SCREENX -- the ability to read how many columns are availabel in the Console screen
SCREEN() -- the ability to read the ASCII code of the character at an X,Y coordinate.

It would also be handy to read or modify the attributes of the character at a given
x,y coordinate, or in a given Console rectangle.
has-been wanna-be (You may not agree with what I say, but it will make you think).
User avatar
helpy
Enthusiast
Enthusiast
Posts: 552
Joined: Sat Jun 28, 2003 12:01 am

Re: Enhancements For the Console Capability

Post by helpy »

Some time ago I wrote a few functions, which I used in a little project.

You can find them in the german development lounge:
==> http://www.development-lounge.de/viewto ... 937#p61937

These functions use windows API.

Here are the functions:

Code: Select all

EnableExplicit
; ============================================================
; Makros:
;     ConsoleHandle() ............ handle of the console window
;
; Funktionen:
;     ConsoleLocation()
;         X and Y position of the cursor in the console window
;         Returns a long which contains position in COORD format
;     ConsoleLocationX()
;         X position of the cursor in the console window
;     ConsoleLocationY()
;         Y position of the cursor in the console window
;     ConsoleWidth()
;         width of the console window
;     ConsoleHeight()
;         height of the console window
;     ConsoleBufferLocation()
;         X and Y position of the cursor in the console screen buffer
;         Returns a long which contains position in COORD format
;     ConsoleBufferLocationX()
;         X position of the cursor in the console screen buffer
;     ConsoleBufferLocationY()
;         Y position of the cursor in the console screen buffer
;     ConsoleBufferWidth()
;         width of the console screen buffer
;     ConsoleBufferHeight()
;         height of the console screen buffer
;     ConsoleBufferLocate()
;         similar to ConsoleLocate() but positions the cursor
;         inside the console screen buffer
;     ConsoleMoveUp()
;         moves the cursor up one line
;         sets the cursor to the left postion
;     ConsoleMoveUp( CountLines )
;         moves the cursor up [CountLines] lines
;         sets the cursor to the left postion
;     ConsoleDeletePrevLines()
;         moves the cursor up one line
;         sets the cursor to the left postion
;         deletes the whole Line (overwrite With spaces)
;     ConsoleDeletePrevLines( CountLines )
;         moves the cursor up [CountLines] lines
;         sets the cursor to the left postion
;         deletes the whole Line (overwrite with spaces)
;     GetConsoleTitle()
;         returns a string, which contains the console title
;
; ============================================================

Macro ConsoleHandle()
	GetStdHandle_( #STD_OUTPUT_HANDLE )  ; GetConsoleWindow_() funktioniert nicht
EndMacro

Structure tConsole_COORD
	StructureUnion
		coord.COORD
		long.l
	EndStructureUnion
EndStructure

Procedure.l ConsoleLocation()
	Protected ConsoleBufferInfo.CONSOLE_SCREEN_BUFFER_INFO
	Protected hConsole
	Protected location.tConsole_COORD
	
	hConsole = ConsoleHandle()
	GetConsoleScreenBufferInfo_( hConsole, @ConsoleBufferInfo )
	
	location\coord\x = ConsoleBufferInfo\dwCursorPosition\x - ConsoleBufferInfo\srWindow\left
	location\coord\y = ConsoleBufferInfo\dwCursorPosition\y - ConsoleBufferInfo\srWindow\top
	
	ProcedureReturn location\long
EndProcedure

Procedure   ConsoleLocationX()
	Protected ConsoleBufferInfo.CONSOLE_SCREEN_BUFFER_INFO
	Protected hConsole
	
	hConsole = ConsoleHandle()
	GetConsoleScreenBufferInfo_( hConsole, @ConsoleBufferInfo )
	
	ProcedureReturn ConsoleBufferInfo\dwCursorPosition\x - ConsoleBufferInfo\srWindow\left
EndProcedure

Procedure   ConsoleLocationY()
	Protected ConsoleBufferInfo.CONSOLE_SCREEN_BUFFER_INFO
	Protected hConsole
	
	hConsole = ConsoleHandle()
	GetConsoleScreenBufferInfo_( hConsole, @ConsoleBufferInfo )
	
	ProcedureReturn ConsoleBufferInfo\dwCursorPosition\y - ConsoleBufferInfo\srWindow\top
EndProcedure

Procedure.l ConsoleBufferLocation()
	Protected ConsoleBufferInfo.CONSOLE_SCREEN_BUFFER_INFO
	Protected hConsole
	Protected location.tConsole_COORD
	
	hConsole = ConsoleHandle()
	GetConsoleScreenBufferInfo_( hConsole, @ConsoleBufferInfo )
	
	location\coord\x = ConsoleBufferInfo\dwCursorPosition\x
	location\coord\y = ConsoleBufferInfo\dwCursorPosition\y
	
	ProcedureReturn location\long
EndProcedure

Procedure   ConsoleBufferLocationX()
	Protected ConsoleBufferInfo.CONSOLE_SCREEN_BUFFER_INFO
	Protected hConsole
	
	hConsole = ConsoleHandle()
	GetConsoleScreenBufferInfo_( hConsole, @ConsoleBufferInfo )
	
	ProcedureReturn ConsoleBufferInfo\dwCursorPosition\x
EndProcedure

Procedure   ConsoleBufferLocationY()
	Protected ConsoleBufferInfo.CONSOLE_SCREEN_BUFFER_INFO
	Protected hConsole
	
	hConsole = ConsoleHandle()
	GetConsoleScreenBufferInfo_( hConsole, @ConsoleBufferInfo )
	
	ProcedureReturn ConsoleBufferInfo\dwCursorPosition\y
EndProcedure

Procedure   ConsoleWidth()
	Protected ConsoleBufferInfo.CONSOLE_SCREEN_BUFFER_INFO
	Protected hConsole
	
	hConsole = ConsoleHandle()
	GetConsoleScreenBufferInfo_( hConsole, @ConsoleBufferInfo )
	
	ProcedureReturn ConsoleBufferInfo\srWindow\right - ConsoleBufferInfo\srWindow\left + 1
EndProcedure

Procedure   ConsoleHeight()
	Protected ConsoleBufferInfo.CONSOLE_SCREEN_BUFFER_INFO
	Protected hConsole
	
	hConsole = ConsoleHandle()
	GetConsoleScreenBufferInfo_( hConsole, @ConsoleBufferInfo )
	
	ProcedureReturn ConsoleBufferInfo\srWindow\bottom - ConsoleBufferInfo\srWindow\top + 1
EndProcedure

Procedure   ConsoleBufferWidth()
	Protected ConsoleBufferInfo.CONSOLE_SCREEN_BUFFER_INFO
	Protected hConsole
	
	hConsole = ConsoleHandle()
	GetConsoleScreenBufferInfo_( hConsole, @ConsoleBufferInfo )
	
	ProcedureReturn ConsoleBufferInfo\dwSize\x
EndProcedure

Procedure   ConsoleBufferHeight()
	Protected ConsoleBufferInfo.CONSOLE_SCREEN_BUFFER_INFO
	Protected hConsole
	
	hConsole = ConsoleHandle()
	GetConsoleScreenBufferInfo_( hConsole, @ConsoleBufferInfo )
	
	ProcedureReturn ConsoleBufferInfo\dwSize\y
EndProcedure

Procedure   ConsoleMoveUp( CountLines = 1 )
	Protected ConsoleBufferInfo.CONSOLE_SCREEN_BUFFER_INFO
	Protected hConsole, x, y
	Protected location.tConsole_COORD
	
	If CountLines < 1 : ProcedureReturn #False : EndIf
	
	hConsole = ConsoleHandle()
	GetConsoleScreenBufferInfo_( hConsole, @ConsoleBufferInfo )
	location\coord = ConsoleBufferInfo\dwCursorPosition
	location\coord\x = 0
	location\coord\y - CountLines
	If location\coord\y < 0 : location\coord\y = 0
		ElseIf location\coord\y >= ConsoleBufferInfo\dwSize\y : location\coord\y = ConsoleBufferInfo\dwSize\y - 1 : EndIf
	SetConsoleCursorPosition_( hConsole, location\long )
	
	ProcedureReturn #True
EndProcedure

Procedure   ConsoleDeletePrevLines( CountLines = 1 )
	Protected ConsoleBufferInfo.CONSOLE_SCREEN_BUFFER_INFO
	Protected hConsole, x, y
	Protected location.tConsole_COORD
	
	If CountLines < 1 : ProcedureReturn #False : EndIf
	
	hConsole = ConsoleHandle()
	GetConsoleScreenBufferInfo_( hConsole, @ConsoleBufferInfo )
	location\coord\x = 0
	location\coord\y = ConsoleBufferInfo\dwCursorPosition\y
	While CountLines And location\coord\y
		location\coord\y - 1
		SetConsoleCursorPosition_( hConsole, location\long )
		Print( Space(ConsoleBufferInfo\dwSize\x) )
		If CountLines = 1
			SetConsoleCursorPosition_( hConsole, location\long )
		EndIf
		CountLines - 1
	Wend
	
	ProcedureReturn #True
EndProcedure

Procedure   ConsoleBufferLocate( x, y )
	Protected ConsoleBufferInfo.CONSOLE_SCREEN_BUFFER_INFO
	Protected hConsole
	Protected location.tConsole_COORD
	
	If y < 0 Or y < 0
		; x or y outside the console screen buffer
		ProcedureReturn #False
	EndIf
	
	hConsole = ConsoleHandle()
	GetConsoleScreenBufferInfo_( hConsole, @ConsoleBufferInfo )
	
	If y >= ConsoleBufferInfo\dwSize\y Or x >= ConsoleBufferInfo\dwSize\x
		; x or y outside the console screen buffer
		ProcedureReturn #False
	EndIf
	
	location\coord\x = x
	location\coord\y = y
	SetConsoleCursorPosition_( hConsole, location\long )
	
	ProcedureReturn #True
EndProcedure

Procedure.s GetConsoleTitle()
	Protected title.s = Space(1024)
	GetConsoleTitle_( @title, 1024 )
	ProcedureReturn title
EndProcedure
And here a little test program:

Code: Select all

Macro WaitKey()
	While Inkey() = "" : Delay(100) : Wend
EndMacro

Define i

OpenConsole()

For i = 0 To 100
	PrintN( Str(i) )
Next i


WaitKey()

ConsoleMoveUp( 10 )
For i = 1001 To 1010
	PrintN( "Overwrite last 10 lines (100 - 110) with " + Str(i) )
Next i
WaitKey()

ConsoleDeletePrevLines( 10 )
PrintN( "Deleted last 10 lines" )
WaitKey()

ConsoleMoveUp( 20 )
PrintN( "Move up 20 lines and overwrite line with something else ..." )
WaitKey()

ConsoleBufferLocate( 0, 0 )
Print( " <-- This is position (0,0) in screen buffer" )
ConsoleBufferLocate( 0, 0 )
WaitKey()

ConsoleBufferLocate( 0, ConsoleBufferHeight()-1 )
Print( RSet("This is position (" + Str(ConsoleBufferWidth()-1) + "," + Str(ConsoleBufferHeight()-1) + ") in screen buffer -->", ConsoleBufferWidth()-1, " "))
WaitKey()

CloseConsole()
End
Maybe its of some help for you.
Greetings from bavaria,
guido
Windows 10 / Windows 7
PB Last Final / Last Beta Testing
oldefoxx
Enthusiast
Enthusiast
Posts: 532
Joined: Fri Jul 25, 2003 11:24 pm

Re: Enhancements For the Console Capability

Post by oldefoxx »

Nicely done, and I do appreciate it. The only thing lacking is the necessary keywords
to help external searches come onto your code. Let me help out there. For you
searchers out there, the key words are PureBasic Console Cursor Functions locate.
Let's add PureBasic cursor position just to be sure.

I have sometimes relied on the Windows APIs for doing things, but you sort of need a
guide to learn your way around the APIs, and you need a breakdown of the API calls
themselves. I haven't gotten that far with PureBasic yet, but there is an excellent
breakdown of most of the APIs and constants/types used with them that can be had
off the www.powerbasic.site in the download section. The PowerBasic language has
a different syntax than PureBasic, but it should be possible to make out the changes
needed. You don't know the entirety of the INC files, just the portions that you are
going to use in your own programming efforts.

There is not just one set of Windows APIs either. For more information on this and
the Windows SDK (Software Developer's Kit), you can start at
http://en.wikipedia.org/wiki/Windows_SDK

You not only get a little background, but it will guide you to where you can download
the Microsoft Windows SDK yourself. Microsoft uses rather long names for things, and
that makes it fairly easy to identify functions that fit into a category, such as console.
The types and constants are all defined first, so you have to go down towards the end
of the documentation to find where the functions themselves are declared, and their
listing is alphabetical by function name.

Note if you want the APIs in BASIC format, the PowerBasic site may be best. If you
want it in C++ notation, get it directly from Microsoft. PureBasic is rather like C++,
but somewhat wordier. Also note that when calling external functions, which is what
you do when you call something from a DLL like Kernel2s,dll or User32.dll, it is the case
settings in the ALIAS double quote pair that are truly significant. The internal name
for each functions is not near as significant, unless there is no ALIAS name given.

One function mentioned earlier is the one that would take a rectangular area of the console
and let you change that attributes as a block. You could then change all the foreground or
background colors for the block in one step. You could make a flashing sign, a sign that
changed colors, or make other effects take place. That function is is found here.

Another function mentioned is one that would read a block of characters back off the screen
in one effort. Most Console screens have the ability to let you select any portion of them,
then when you hit the Enter key, the selection is transferred to the clipboard and the select
color selection (usually indicated by reversing foreground and background colors) goes away.
But what we are looking for here is a way of getting that selection into your running program
if you want it there.
has-been wanna-be (You may not agree with what I say, but it will make you think).
User avatar
helpy
Enthusiast
Enthusiast
Posts: 552
Joined: Sat Jun 28, 2003 12:01 am

Re: Enhancements For the Console Capability

Post by helpy »

;-)

I will not do any further work on my code!
The code was sufficient for my purposes.

Take it, change it, do what ever you want with it.

cu,
guido
Windows 10 / Windows 7
PB Last Final / Last Beta Testing
oldefoxx
Enthusiast
Enthusiast
Posts: 532
Joined: Fri Jul 25, 2003 11:24 pm

Re: Enhancements For the Console Capability

Post by oldefoxx »

guido, my comments were not meant specifically for your eyes and ears. What you
submitted is more than I would have expected. I wasn't after you to do anything
more. I could not even challenge anyone to come up with anything on their own
that would match your efforts.

I just let it slip (well, not "slip" exactly, but got it into my response) that there are
a couple of aspects of using the Console that haven't been covered here, and that
it would not hurt to have them brought in if anyone were interested. I may even
take a stab at it myself, but I've a long list of things to get done as well, and I
sort of put these things out there sometimes in case anybody wanted to know what
might help others.

No, what you submitted is fine and much appreciated. The other is in case anyone
else wants to help out a bit. Not me personally, but the Console-leaning community
if there still is one circulating out there.

Must be. I mean when I try to post a query to Google, it often anticipates what I am
requesting a search on, and that comes from somebody else somewhere else having
made a similar request before I put mine in. More than one person I would assume,
which means I see that as an indication that it is among one of the most frequently
questions asked of Google for a number of prior request to spring up in a list like that.
has-been wanna-be (You may not agree with what I say, but it will make you think).
User avatar
blueb
Addict
Addict
Posts: 1111
Joined: Sat Apr 26, 2003 2:15 pm
Location: Cuernavaca, Mexico

Re: Enhancements For the Console Capability

Post by blueb »

oldefoxx wrote:....I have sometimes relied on the Windows APIs for doing things, but you sort of need a
guide to learn your way around the APIs, and you need a breakdown of the API calls
themselves....
Try ApiViewer2004. It displays a PureBasic coding style.

http://www.activevb.de/rubriken/apiview ... ereng.html

Note: You may have to download the latest API database (2008)
- It was too lonely at the top.

System : PB 6.21(x64) and Win 11 Pro (x64)
Hardware: AMD Ryzen 9 5900X w/64 gigs Ram, AMD RX 6950 XT Graphics w/16gigs Mem
oldefoxx
Enthusiast
Enthusiast
Posts: 532
Joined: Fri Jul 25, 2003 11:24 pm

Re: Enhancements For the Console Capability

Post by oldefoxx »

Hmmm. I checked out the link, which is to a site named ActiveVB. Turns out you
also need the VB 6 Runtime as well. And as you say, you have to get the latest
version of the specific SDK, there being three. And of course you have to deal with
getting it set up-.

No real problem with all that, but I was sort of thinking of a package deal, where
you get one extraction file, everything goes into the appropiate place, and you get
an icon on the desktop to call it up. Anybody have something like that to offer?

I have young people (anybody 50 or younger) that sometimes approach me about
what does it take to get into programming on the side. A few are serious, others
not so much. It's gotten harder to come up with answers. There was a time when
only one thing was required: GWBasic. Those days are long gone.

I'm not sure that everybody that has gotten as far as reading postings on these forums
truly realizes how far they themselved have come just to get to this point. You want
to try and encapsulate all those steps to get here and make it easy for someone else
to swallow? Good luck with that. Now if you know of anyone still way ahead of where
you are, you figure you are ever going to get that far? Especially when nobody has laid
out a roadmap for you either.

Some programmers come up through the educational system, where schools lay out a
whole program of what some believe is the best way or the "approved" way to get there.
Someone wants to learn to program, I don't see it necessary to steer them in that
direction. Every few years, I try to teach myself a new language or a new dialect, and I
don't run down to the nearest campus to sign up for a program for the purpose. I did do
that twice, once I took night classes in both Fortran IV and COBOL at the same time, and
years later I tried an online course in web site building where you exchanged emails with
the instructor. It didn't work out so well, as the instructor got roped into a little circle of
people that collectively steered him in a direction they wanted to go. They smartly used
him to help them build a real commercial site, just for student fees.

I can't push people in the directions of a language that only supports the ability to put
together Windows applications. It's just too complicated and involved. I need that Console
aspect in order to get them over the early humps at least. Now some will never move
beyond the Console mode, but that is not a crime. And if everything else they learn works
to their advantage, who is to complain?

As I see it, some people are driven to become programmers. Whether it is coming from a
force within, or they are just caught up in an environment or circumstances where that
turned out to be the way too go. Really sharp programmers bring something of themselves
into the game, and the rest of us can recognize this when we run up against their work.

I'm not here to plead the case for Brainiacs, they can take care of themselves. I am here
to make the case for lesser people, ones that are going to have a tougher road to follow.
Provide, good, decent means for Console activity, then let them decide if they want to
move on up to doing Windows apps when the time comes.
has-been wanna-be (You may not agree with what I say, but it will make you think).
Post Reply