• Please review our updated Terms and Rules here

Alt+Letter key problm in win32 console

alank2

Veteran Member
Joined
Aug 3, 2016
Messages
2,264
Location
USA
If there is a better forum for this message I understand if it gets moved.

I'm writing a small program that I plan to compile for DOS and also for WIN32 console. I used getch() to fetch the keys and some are extended keys where you will get a 0 first and then a second key value. Left arrow is a 0 followed by a 75. What I always have done is check for a 0 and if so, fetch another character from getch() and then add 256 to it. In this case 256+75=331, so if I see a 331, I know it is the left arrow.

My first question is, is there a list of these extended keys somewhere?

The second problem I am having is some sort of Windows 10 console problem. It will not pass ALT+A as the proper key (0 followed by 30, or 286 by my add 256 method), but rather it passes it as if the ALT key was not being pressed. Interestingly, the win10 console will process ALT+F1 properly, but not ALT+A properly. I've tried using the legacy console/not legacy console and turning on/off all the options such as quick edit, insert mode, etc., but I can't get it to produce a real ALT+A no matter what I try.
 
Windows has a special set of messages for alt keypresses (WM_SYSKEYDOWN and WM_SYSKEYUP). How you detect alt keys in a Windows console application depends on the language being used. If it's a .NET program the easiest way is probably to use Console.ReadKey() to get a ConsoleKeyInfo struct that will indicate whether Shift, Ctrl and/or Alt were held or not. For a native program this link might point you in the right direction:

https://stackoverflow.com/questions/41212646/get-key-press-in-windows-console
 
As I understand it, the OP wants to use the C library function getch(). I don't know if there's a do-it-all standard C library function for this.
 
I'm using an older Borland compiler (C++ Builder 6) and its conio.h library. I'm going to test it in older win32 OS's to see if it works there; I'll bet it does.

I'm writing an editor; I've always wanted to, but never got around to it. I know there are plenty of editors, but I've always wanted to go through the challenge of making one myself. Also, I want to give it some macro capabilities. Even today I still use superkey with DOS editors sometimes which mostly works, but sometimes there is a disconnect between it and the editor where keys are lost. I hope to eliminate that by integrating the macro feature in the editor itself, and making both a WIN32 and DOS16 will let me do macro modification of files in the win32 environment.

One question - my approach is to allocate a memory structure for each line so that I can insert/delete/modify lines without having to shift up or down large chunks of memory. Is there a better way? Memory isn't such a concern for WIN32, but DOS is a different world for sure. I've tried a simple pointer approach where I support 16383 lines (4 byte pointers * 16383 = around 64K) and then each one points to a line. I was also going to try a ptr to ptr to line approach so I could do more lines in DOS than the 16K, but it seemed like a lot of trouble to go through code wise.
 
Testing shows that the OS makes no difference, I even went back to NT4 and it still doesn't work! So much for me blaming it on win10. It then occurred to me that I had other programs in win32 console that did respond to Alt+letters so going back to review some stuff from 2 decades ago shows that I wrote some code that uses ReadConsoleInput and converts the results to be what getch() would return! I'm not sure I want to bring all that code into my simple editor just to have Alt+ key support when I also have WordStar type support too. Maybe.
 
Have you looked at the code in joe's own editor? It's a Wordstar clone and versions exist for DOS, Win16, Win32 and various flavors of Linux (even ARM-based).
 
Regarding memory management, whether there's a better way or not depends on the style of editor you're writing. For a line editor, structuring your memory allocations per line makes sense. For a screen editor, you might find a line-based structure overly constraining. I feel like you would be well served to focus first on how you will manage character insertion/deletion within a line, how you will handle potentially very long lines, and how you might avoid wasting too much memory for very short lines (or blank lines). I suspect that once those issues are sorted out, whatever scheme you come up with will extend naturally to handling lines as well.

If I were going to write my own editor, one of the first questions I'd ask myself is whether I want to be able to edit files too large to fit in memory. If the answer is yes, that dramatically changes how memory management will need to be done.
 
My current plan is to allocate each line independently, so if it is a line with 5 bytes on it, I'm going to allocate 7 bytes for it, the first 2 are the line length and the remaining 5 hold the characters. I know for DOS this would consume 16 bytes because DOS allocates in 16 byte chunks with the first 4 bytes being used for a pointer to manage the allocation. So ask for 7 or 12, it will consume 16. Each line will be a memory allocation form the heap which seems crazy if you have thousands of lines, but a necessary evil unless I can come up with a better idea. Line editing is easy. I'm going with a 4094 byte maximum line length unless to push it to 8K. When editing a line, that line is copied into a local 4K buffer and edited. When we are done, I will allocate a new line to hold the modified line, delete the old line, and update the pointer for that line to point to the new one. Deleting or inserting a line I just do a movmem on the pointers to the lines moving them all up or down. It will refuse to work with a file that has lines longer than it supports.
 
It has been a long time since I last wrote a line editor but that seems likely to be very slow when inserting text into a line or splitting a line into two.
 
Inserting into a line would pay the penalty when leaving that line, but not during line editing. Splitting a line in two does involve moving pointers in memory in that 64K block, but I'm not sure there is a better way unless I moved to a linked list type of thing and that would use yet more memory...
 
I found that the overall best compromises come with a flat memory model: a file in memory as a single continuous string of characters including carriage return characters.

I used to always have a single separate line for editing which would be inserted into the flat file upon the cursor leaving the line. But my latest editor works much better. I have an invisible character which I call a "deleted character". The flat file is edited directly, and when a character is inserted, 19 more "deleted characters" are inserted. So further typing just replaces those deleted characters until they are depleted, and then 20 more are inserted. This causes a delay at the beginning of and occasionally during typing, as the file is spread to insert the deleted characters. I find this very tolerable, whereas I do not find tolerable the delay when leaving a line. This is because when I'm typing, I'm always going ahead (and the keyboard buffer is filling) whilst the delay happens. This doesn't interrupt my train of thought like the delay after typing does, partly because cursor movement is always delay-free.

It works very well with a 40k file in a stock C64; it should work very, very well on a modern "PC".

The one caveat is that I found it not feasible to track line numbers. I can seek for a line number but never know what line the cursor is on after that. Of course, this will be very feasible on a GHz machine. Cursor column tracking works very well.

Line length is infinitely variable and always efficient: a line can be one character or 40k characters (my self-imposed memory limit). No memory is ever wasted on this. Memory can get very fragmented if lots of characters are deleted. But I have a way to detect high fragmentation and then defragment the file (by removing all the deleted characters).
 
I appreciate the good memory allocation ideas KC9UDX - I'm just about done creating a WIN32 getch equivalent that uses ReadConsoleInput instead and will be able to try some of your ideas!
 
Back
Top