The above screen shot shows some of the things this flavor of PDCurses can do, such as display of bold, italic, underlined, overlined, 'strikeout', blinking text, and full colors. (The actual window does have blinking text and blinking cursors as indicated; I didn't try to replicate that in the screen shot!)
Last updated 2013 November 22
PDCurses currently comes in several flavors: DOS, Win32 console, XCurses, OS/2, and SDL. These each have merits and demerits, but none actually implements all PDCurses capabilities. For example, only XCurses and SDL allow for underlined and left/right lined text. Most versions don't implement italic or blinking text, and "bold" text usually just means "brighter color" text. The machines may support lots of colors, but PDCurses usually supports 16 or 8. Mouse wheel events and double-clicks aren't always handled. I wanted a full-capability, no-compromises version of PDCurses.
One possibility would have been to modify the SDL version. That would have made some sense; I'd have had to add bold and italic fonts, blinking text, and revised it to support 256 colors (now full RGB). This is still a tempting idea, especially since I'd have a cross-platform solution (though since Win32a works perfectly with Wine, it really is cross-platform). However, I thought it wouldn't take too long to make a for-real Windows version. Silly me! (Despite the fact that one can run Win32a apps using Wine, I'm still mildly tempted to modify the X11 flavor of PDCurses to support all the things this flavor supports. But I probably won't do that unless somebody pays me for it, which seems unlikely.)
In any case, to bring SDL up to par with Win32a, I'd now have to revise SDL to support Unicode, triple mouse clicks, a more advanced concept of cursor display, cutting and pasting to clipboard, hotkeys to change the font size, resizable windows, and more.
Anyway... it does look as if this flavor of PDCurses now supports absolutely everything known to Curses, even nearly useless features such as triple mouse clicks. All display attributes work, and all mouse and keyboard events are detected. The window can be resized, programmatically or by the user (*), and fonts and font sizes can be chosen. The user can click and drag a rectangle or paragraph and have it copied to the clipboard, and/or paste from the clipboard to the input stream.
I have made some extensions to PDCurses, but backward compatibility has been key. None of the original features of PDCurses has been broken. You should be able to compile your legacy PDCurses apps with this new library, and all should work Just Fine.
This flavor is currently known as Win32a, just to distinguish it from the "real", console-based Win32 version.
Like the rest of PDCurses, Win32a is in the public domain. I hope to get it merged as a flavor of PDCurses. I've e-mailed the maintainers of PDCurses, and am awaiting a reply. But the "mainstream" PDCurses project appears to be mostly inactive; I have doubts this will ever join "mainstream" PDCurses.
"Public domain" does mean that you can do whatever you want with the code; you don't need to release your changes, for example. However, I do appreciate any bug reports, fixes, suggestions for improvements, etc. You can contact me.
Click here to download the source code (about 197 KBytes). Make a folder such as c:\pdcurses and and unZIP the source into it. You should then be able to change to the c:\pdcurses\win32a folder and compile it, using the various make files for MinGW, Visual C/C++, or OpenWATCOM (or possibly the others; those are the three compilers I've used.)
I have maintained the basic form of the standard PDCurses distribution. The file/directory layout is almost identical, except with the Win32a folder and no X11, OS2, DOS, etc. folders. The Win32a folder is new, of course. The other files are either exact copies of those supplied with standard PDCurses, or incorporate small changes required to get things working with Win32a (but which do not "break" the other flavors of PDCurses.) The pdcurses folder has a file, diff.txt, which explains what got changed in existing files and why.
I was providing a DLL for a while, and one could swap it in for an existing PDCurses DLL so that current PDCurses apps (if linked to a DLL) would suddenly become Win32a ones. Unfortunately, when I extended Win32a to support five-button mice, it made it impossible to do this sort of swapping. The addition of tilt-wheel mouse support further breaks binary compatibility.
This is being provided as part of Win32a, but can be applied to any flavor of PDCurses. In fact, you could download standard PDCurses and simply replace the slk.c file provided in that distribution with the one provided in this distribution, and you'd have the new SLK features described below.
Soft Label Keys (SLKs) are shown at the bottom of the screen shot at the top of this page: they provide a simple way to make sure that there are a few buttons, which can be user-labelled, at the bottom of the window. A line or two has to be sacrificed to accommodate them. Click on the buttons, and it's as if you hit a function key.
As provided in current PDCurses, you can have only certain configurations of buttons: "3-2-3" format (three buttons on the left and right sides and two in the middle), "4-4" format (four on each side), "4-4-4", "5-5", and "4-4-4 with index", in which above each button is a label giving the corresponding function key. You can't get any other format, nor can you change formats in mid-program.
The revised slk.c in Win32a fixes both limitations. As is described in the code itself, you can get essentially any label layout you want. (This actually resulted in somewhat simpler code. The original version treated each layout as a special case, without recognizing that they could be handled in a common manner.) I also found that by adding a couple of lines of code, I was able to allow changes in format in mid-program; see newtest.cpp (part of the Win32a source code) for an example. You do still have to set up soft label keys before the window is initialized. Turning SLKs on (or off) after the window was created would mean adding (or removing) lines from the main window, and I've not seen a good way to do that.
Fixes (2013 Nov 22):
• Amanieu d'Antras pointed out that in Vista and later forks of Windows, a Win32a window could "collapse" because of the code I used to determine the difference between the client rectangle and the full application window rectangle. He supplied a patch that uses the Win32 API AdjustWindowRect function, which both removes the bug and makes the code a lot easier to follow and less kludgey, all at the same time. Definitely a welcome contribution.
• I realized that the code to determine whether a mouse click was single, double, or triple was flawed: I was getting double and triple clicks in situations where I had waited several seconds since clicking the mouse. This turned out to be due to my use of the clock( ) function, which apparently measures the process time, not the "wall clock" time (the time you'd see elapse if you looked at a clock on a wall). So you might think several seconds had elapsed between two clicks, but your application would only have been busy for a few milliseconds between the clicks and would decide you'd double-clicked. The fix, again, was to use a suitable Win32 API function that gets "wall clock" time; for details, check the milliseconds_since_1970( ) function in pdcscrn.c.
• When using 64-bit chtypes, one can now set the A_DIM attribute type, and the text will actually be dimmed. (With 16 or 32-bit chtypes, and on all other flavors of PDCurses, A_DIM is defined to be equal to A_NORMAL.) The use of this attribute is demonstrated in newtest.c.
Fixes (2013 Oct 17):
• A bug and its fix, applying to all flavors of PDCurses, was posted on the PDCurses mailing list. Essentially, you could conceivably get crashes if a window was shrunk and the cursor ended up outside the new window. The new version incorporates the fix.
• I originally set up 64-bit chtypes so that they could contain Unicode values up to twenty bits. This seemed absurd overkill. However, the upper range of Unicode is 0x10ffff, so that 21 bits really should be allowed. Fortunately, I was able to do that with only a couple of lines revised. Unfortunately, it does mean that the attribute bits are shifted up by one; you'll have to recompile everything to use the current version. (Note that this applies only to the 64-bit flavor of Win32a. That's the default, though, and I'd bet few people are using 32-bit or 16-bit chtypes these days.)
There's some question as to whether such values can be displayed. I tried revising testcurs.c to display the character U+1D11E, which should correspond to the musical symbol G clef... which may or may not show up correctly in your browser: 𝄞 I'm not getting it to display with Win32a, though, in WinXP or in Wine under Linux.
• In investigating the above problem, I realized that Windows uses UTF-16, in which wchar_t is sixteen bits and Unicode characters beyond U+FFFF are displayed using "surrogate characters". Some revision to pdcdisp.c enabled this feature. However, as described above, it's unclear whether Windows can actually handle characters beyond the 64K limit. Apparently, according to Microsoft, 64K characters should be enough for anybody.
Furthermore, there are at least two other ways in which Win32a handles Unicode imperfectly. First, Xavier Wang pointed out that certain Chinese characters should be drawn with twice the width of other characters. Secondly, 'composited' characters aren't handled. For example, the Unicode character U+20D7 indicates that the preceding character should have an arrow over it, like these: a⃗ b⃗ c⃗ D⃗ (note that not all browsers handle these). I've no plans to support these Unicode features.
Fixes (2013 July 5):
• Win32a stored information about font choice and window sizing/placement in the registry under HKEY_LOCAL_MACHINE. Mark Hessling pointed out that, while this works under WinXP and previous forks of Windows, it fails on Windows 7 (or any Windows with UAC). In that situation, you need administrative rights to change that part of the registry.
The fix was to instead store the font and window sizing/placement information under HKEY_CURRENT_USER. Two lines of code were suitably changed.
Fixes (2013 Jun 26):
• Mark Hessling spotted some errors in wide-character support in Win32a and in the handling of SLKs (soft-label keys) and supplied bug fixes. He also noticed that if you use 64-bit chtypes with the Win32 console or DOS flavors of PDCurses, things broke rather badly. It turned out that I had to slightly modify three source files for the Win32 console flavor and one for the DOS flavor; these are now included in the download.
To test out the SLK changes, I had to modify newtest to allow for a feature to toggle display of SLKs. (When you turn them off, the SLK area goes blank and stays blank; you don't suddenly get one or two more lines to play with.)
Fixes (2013 Jan 26):
• The 'enlarge font' and 'shrink font' options are now missing from the menu, and a new 'Font' option has been added. Click on this, and you can choose the font used in the window (size and type). You can also hit Ctrl-Comma to access this dialog.
Note that while you can now select any font you want, not all fonts will work equally well. The display is fixed-pitch; non-proportional fonts will usually look pretty weird. Not all fonts support the box-and-lines type alternative characters. I originally chose Courier New because it supports absolutely everything, including non-Latin alphabets. Still, for a lot of purposes, you'll find that other fonts work Just Fine.
• Jason Foley pointed out that Win32a didn't register most Ctrl-Shift key combinations as events, and didn't recognize Ctrl-Alt anything. I was able to fix the former easily enough. The latter is a stickier wicket, now described in comments in pdcscrn.c. Basically, some keyboards consider Ctrl-Alt to be a modifier to get characters not otherwise available. For example, on a Swedish keyboard, Shift-2 gets a " (double quote) mark, and Ctrl-Alt-2 gets a @. We really should, when using a Swedish layout, return a key for Ctrl-Alt-1, but not for Ctrl-Alt-2; Windows will "convert" that into an at-sign, and we'd feed two characters to the user.
At least for the nonce, therefore, Win32a still doesn't return Ctrl-Alt combinations, unless one sets the new external variable PDC_show_ctrl_alts to a non-zero value.
Fixes (2012 Nov 10):
• Roald Ribe pointed out that the most recent version failed when run in Windows 7. I borrowed a Win7 machine and replicated the failure. It turned out that the window style used for non-resizable windows was wrong. This is now fixed. I also rearranged the newtest demo program's screen (as shown in the image at the top of this page) so that it would be useable in the default 25-line/80-column mode.
Fixes (2012 Oct 31 and 2012 Oct 18):
• Xavier Wang found and fixed bugs occurring when apps didn't handle user resizing messages. This is quite common, because only the X11, Win32a, and SDL platforms support user resizing at all. When apps written for the DOS, OS/2 or Windows versions are linked to Win32a and the user changes the window size, you could get garbage on the screen, or crashes. Xavier fixed this.
Thinking about this caused me to change the behavior of Win32a. There is no way for Win32a to know in advance if an application has been written to handle user resizing correctly. So Win32a now defaults to non-user-resizable windows, with two ways to get resizable windows.
You can, before calling initscr( ) or Xinitscr( ), signal to Win32a that the window can be resized from 20 to 55 lines, and 70 to 100 columns, by calling
PDC_set_resize_limits( 20, 55, 70, 100);
The above has only one slight flaw: the PDC_set_resize_limits( ) function exists, at present, only in Win32a. If you try to use it with other flavors of PDCurses, you'll get unresolved external function errors. Eventually, the function may exist in other flavors; in X11 and SDL, it could actually be "functional" (other flavors of PDCurses don't support resizing, so this would be a do-nothing function for them.)
Alternatively, you can (again, before calling initscr( ) or Xinitscr( )) set the following:
ttytype = 20; /* Window must have at least 20 lines in Win32a */
ttytype = 55; /* Window can have a max of 55 lines in Win32a */
ttytype = 70; /* Window must have at least 70 columns in Win32a */
ttytype = (unsigned char)200; /* Window can have a max of 200 columns in Win32a */
...which won't cause trouble with other flavors (they'll just ignore it), but which is inelegant and limits you to 255x255 windows. Though arguably, 255x255 windows should be big enough for anyone.
My thanks to Anatoly Techtonik for pointing out some problems in my original version of this feature.
• Xavier also pointed out that the window didn't capture mouse events. You could get strange behavior if you clicked within the Win32a window, dragged the mouse, and released the button somewhere outside the window. A few calls to SetCapture( ) and ReleaseCapture( ) fixed this.
• Xavier also pointed out that certain Chinese characters really should be drawn "wide", occupying twice the space of other characters. I don't have an answer for that problem yet; the code assumes a fixed-width font, and things would get very strange indeed if we changed that assumption.
Fixes (2012 Jun 11):
• Roald Ribe provided a patch that made the WndProc( ) function in pdcdisp.c considerably cleaner. That function had become too large to be easily managed; the new arrangement is a little easier to follow.
• As is shown in the screen shot at the top of this page, one can get text to appear with any desired foreground and background colors; you aren't limited to the 256-color palette. You can just specify a foreground RGB and a background RGB for each character. For an example of how this is done, see newtest.cpp. Note that this works only when using 64-bit chtypes.
• I found that if you maximized a Win32a window, exited, and restarted the program, it would hang. Also, attempting to check for a key press wouldn't necessarily work, now that we aren't multi-threading: PDC_check_key( ) must explicitly check for new messages sent to the PDCurses window, in order to make sure that all keyboard events have been processed. Both bugs are now fixed.
Fixes (2012 Jun 2) :
• Previously, the window had been handled in a separate thread. This made the code somewhat more complicated than it had to be. More seriously, there were issues caused by the lack of re-entrancy in PDCurses. It was at least theoretically possible to have the window thread and the "main" outside-the-window-thread accessing variables simultaneously. A mutex helped to avoid this problem, sort of, but it wasn't a perfect fix. However, Roald Ribe figured out a nice way to avoid the need to multi-thread. The code is much saner and safer as a result.
• Roald also pointed out that a lot of code uses Xinitscr( ) when compiled for XCurses and initscr( ) otherwise. There is no good need for this. On non-XCurses platforms, initscr( ) simply calls Xinitscr( 0, NULL), and the argc and argv parameters are then ignored. So Xinitscr( ) is now enabled for all platforms. Use of it is actually a Good Thing; it makes it slightly more likely that the correct command line arguments will get to the library, which can then use them for setting the window title and getting the previous window state from the Registry.
• Roald also pointed
out that it would be nice to be able to select in
"paragraph style" instead of the default "block style". So you could
mark things like
<- From here, keep marking text until it wrap
s around, then keep on marking some more lines to b
e copied to clipboard until you've had enough, right
...i.e., the way things usually get marked in most word processors. This is now enabled. Drag with the left mouse button pressed, and a paragraph will be highlighted and copied to the Windows clipboard when you let go of the button. (Hold down Shift when you press that mouse button, and you can get the previous block-marking and copying behavior.)
• Roald also provided some fixes to OpenWATCOM compilation to get proper symbols in the debugger and smooth out a few problems with that compiler.
• I made some changes in curses.h so that, when using 64-bit chtypes, one can specify Unicode characters up to 20 bits. Almost all "normal" Unicode characters fit within 16 bits -- hence the widespread use of UTF-16 -- but if you look at the Unicode code charts, you'll see that, for example, (Cretan) Linear B, Old Italic, Phaistos Disc, Shavian, Phoenician, and so on require a seventeenth bit. It does appear as if Unicode can require 21 bits, if one makes use of the "Private Use Area". But 20 bits appears to be overkill for all practical purposes. I also extended the color field within chtype to consume 31 bits. See newtest.c for an example of the use of this (or look at the screen shot at the top of this page). Basically, five bits each specify the foreground and background R, G, and B, plus one more "signal" bit to indicate that the color is to be treated in this manner, instead of as an index within a palette... that brings us up to 31 bits.
This color specification system could also apply to the SDL and XCurses flavors of PDCurses.
Fixes (2012 May 14) :
Fixes (2011 November 1) :
Fixes (2011 September 14) :
Fixes (2011 June 12) :
Fixes (2011 January 20) :
Fixes (2010 December 26) :
Fixes (2010 November 29) :
Fixes (2010 November 12) :
Fixes (2010 September 26) :
Fixes (2010 August 5) :
Fixes (2010 May 24) :
Fixes (2010 May 9) :
Fixes (2010 May 4) :
Fixes (2010 May 3) :
Fixes (2010 Apr 30) :
Fixes (2010 Apr 29) :
Fixes (2010 Apr 26) :
Fixes (2010 Apr 23) :
Fixes (2010 Apr 19) :
Fixes (2010 Apr 15) :
Fixes (2010 Apr 14) :
Fixes (2010 Apr 13) :
Fixes (2010 Apr 12) :
Fixes (2010 Apr 11) :
Fixes (2010 Apr 7) :
Fixes (2010 Apr 6) :
Fixes (2010 Apr 5) :
Fixes (2010 Apr 4) :
Fixes (2010 Apr 3) :
Fixes (2010 Apr 1) :
Fixes (2010 Mar 30) :
• In the input test part of 'testcurs', mouse move events are reported if a button is pressed. Looking at the definition of ALL_MOUSE_EVENTS in curses.h, this makes sense; all bits are set, except for the REPORT_MOUSE_POSITION button. I turned that one on, too, thinking it would cause 'testcurs' to report all mouse movement, whether buttons were pressed or not. That doesn't happen, with either the SDL or "standard" Win32 libraries. This is probably a matter of my not understanding how PDCurses is supposed to work.
• At certain font sizes, junk can be left behind on the screen. Probably the way around this will involve just not using those sizes. (I think this happens because sometimes, a "fixed-width" TrueType font has a non-integral width/height. It may also have to do with TrueType fonts not necessarily staying within the character block size. The way around this may be to force bitmapped fonts.)
• Wide-character support fails (compiles cleanly, but testcurs locks when run). Also, if you aim for a DLL version, certain functions aren't exported (not declared in pdcurses.def.)
• The default Courier New font always works. You can choose other fonts, but they may have shortcomings. You can use Lucida, Verdana, Courier, and other fixed-size fonts if you wish; you'll just find that italic and/or bold text may not work. Which, for most existing applications, won't matter; other flavors of PDCurses didn't support those things anyway. Also, if you try to display characters not included in the font, you'll get blanks or boxes or question marks. (Again, not an issue for the many apps that use only Latin-1 anyway.) For that matter, you can even use Times or other proportional fonts, though you may find that the result looks a little weird.
• Also at certain font sizes, Windoze decides that normal = bold. That is to say, its font mapper can't be persuaded to provide two different fonts for certain sizes. The only way around this (at present) is to hit choose a different or larger font.
• Menu options to print the current screen, and/or save it as an HTML file, could be useful. Neither would be difficult to do. PostScript output would be nearly trivial (mostly because I already know a lot about PS). The functions for PS and HTML export would even be platform-independent. PDF would be a little tougher. One could just use ps2pdf, but I'd rather avoid the dependency.
• Functions should be provided to specify maximum and minimum dimensions. In many cases, these might be the same (a legacy app that expects 80 columns and 25 rows, for example, and which has no provisions for resizing events). In such cases, the dialog style might change from "resizable window" to "fixed window".
• A fix for SDL: in the course of testing PDC_set_line_color, I noticed that it only 'sort of' works in SDL: it'll change the line color for subsequently drawn lines. If you run newtest with the SDL library, for example, when you click to change the line color, nothing happens. But resize the window (triggering a redraw), and hey presto, the lines are redrawn in the correct color.
• A conversation with Mark Hessling caused me to realize that being able to configure the menu programmatically could be helpful, and might not even be all that tough to do.
• Mark also pointed out that some sort of drag-and-drop functionality could be useful. He's currently doing this when in the Win32 console flavor of PDCurses, but in Win32a, you don't have the same direct access to the window. Doing this would require some relatively simple extensions to PDCurses, which would realistically speaking probably only occur in Win32a; the other flavors are not under much active development.
• There are currently 32 ACS_ alternate character set #defines in curses.h. As best I can tell, there's nothing preventing us from having up to 128 such. It would be nice, in my humble opinion, if the double-line variants of the box characters ACS_RTEE and such were supported; perhaps also ACS_CHECKMARK, perhaps some of the block/half-block characters... If one did this, would there be backward-compatibility issues? (I see none.) As best I can tell, only the behaviour of those 32 ACS items is specified; we're still free to play around with anything else. (I've added some possible #defines to pdcwin.h to illustrate. Note that these should be available on other systems, too.)
• At present, all flavors of PDCurses support one display window, called stdscr. At least in theory, it would be possible for Win32a to support multiple display windows. That'd be really nifty (and useful), but probably more effort than I'll go to unless I can get somebody to pay me to do it. (It would involve a new 'switch stdscr' function, which would have to store all the many static/external variables associated with the current stdscr, then create a new one; or, restore all the static/external variables. Plus some other annoying bits and pieces.)
• A full-screen option might be useful. This would basically enlarge the window so that the borders and menu and such were just outside the actual screen (something I've done with the astronomy software that is my "day job", so I'm familiar with the process.)
• If you drag open an area with the left mouse button pressed, it marks that area and then copies it to the clipboard when you release the mouse button. To me, this makes a certain amount of intuitive sense. Almost all the time, if you drag open an area on-screen in a PDCurses window, you're doing it to copy it to the clipboard. It may be useful to provide a menu option to disable mark/copy, for those probably very few apps wherein one might drag the mouse for another reason.
• There are two menu options at present: select the font, and paste from the clipboard. (With this last, if you've text in the clipboard, it's fed through getch( ) to your program.) These probably should be icons rather than text. Both functions are available via Ctrl-Comma and Ctrl-V respectively.
• Mice are almost totally supported (five buttons, and up to triple clicks.) For the wheel, we really ought to be keeping track of total wheel motion, which isn't necessarily an integral number of wheel clicks. Vista, in particular, added support for continuously varying wheels:
The issues described therein, of the need to accumulate mouse motion, are handled properly in the code now; 'wheel up' and 'wheel down' messages are generated as needed, after the mouse has moved far enough. But there's no way to signal "mouse wheel moved just a little bit".
• This version supports COLORS=256 and COLOR_PAIRS=256. Compile with the testcurs that's part of the win32a.zip file, and go to Color Test, and you'll see this demonstrated. Or you can see it in the Newtest demo at the top of this page. This also shows how, when using 64-bit chtypes, one can get full RGB coloring.
• Italic, reverse, and under/left/right-lined text has been added, as has blinking, using timer events to trigger a reversal in color. (Compile and link the testcurs included with the win32a.zip file, and look at the 'color test' portion, and you should see all attribute combinations.) Those are all the attributes we can probably get with a 32-bit chtype. With a 64-bit chtype, one can also get strike-out text and full RGB coloring. All of this is backward compatible (always a key consideration with PDCurses).
With the 64-bit chtype flavor, we could set A_INVIS to some different value. I assume its purpose would be that if you set that attribute, the text disappears (i.e., that character cell is just filled with the background color).
• Currently, key_modifiers includes Alt, Shift, Control, and Numlock. Why not Capslock and Scroll lock?
• I don't really like the way key modifiers are handled (using GetAsyncKey). The code I wrote does work, but if, for some reason, there's a significant delay between the key being hit and the WM_KEYDOWN message getting to WndProc, the user may no longer be pressing the Ctrl or Shift key, and those modifiers will have been lost. I've not actually seen that happen, and it seems unlikely. But it seems as if in theory, it ought to be possible. Proper fixing of this, though, would require having a queue of mouse events, and I think might break existing Curses programs that assume no queue. Or maybe it's assumed that the program checks for input on a frequent basis.
• I've tested this (to varying degrees) with Visual C, OpenWATCOM, Digital Mars, and MinGW. On the latter, I'm getting problems with finding libgdi32.a and libuser32.a unless I specify their locations explicitly, but that may just reflect my (lack of) knowledge. (This is at least partly fixed now.)
I can be reached at plüto@prôjéctplutö.cöm (obviously, removing diacritical marks inserted in hopes of confusing spammers!)
Should you send me code for a "problem" case, it would be nice (but not essential) if it compiles to use the DLL flavor of PDCurses. The advantage of this is that I can swap the Win32 console flavor DLL for the SDL flavor DLL, or the Win32a flavor DLL, without needing to recompile anything. Also, that way, I can just recompile Win32a and immediately test it with your app.