Did you know Emacs does not only support the full range of Windows operating systems, but even works on MS-DOS? One would have assumed the support for this officially unsupported platform would have been snipped out already, but Eli Zaretskii, a high profile core Emacs developer best known for their contributions to the display engine, is still contributing to it.

The build process is slightly weird. You do need GCC to support the full range of GNUisms the code is riddled with, but GCC surely doesn’t support DOS… or does it? Meet DJGPP!

That being said, msdos.c is surprisingly easy to read compared to the rest I’ve dipped my toes into. Must be the low number of C macro abuse incidents, well commented code and the overall simplicity of the system target, much unlike modern platforms. I urge you to take a look as well, here’s my top ten comments:

/* Note the startup time, so we know not to clear the screen if we exit immediately; see IT_reset_terminal_modes. (Yes, I know `clock' returns zero the first time it's called, but I do this anyway, in case some wiseguy changes that at some point.) */ startup_time = clock ();

/* We only look at the keyboard Ctrl/Shift/Alt keys when Emacs is ready to read a key. Therefore, if they press `Alt-x' when Emacs is busy, by the time we get to `dos_get_modifiers', they might have already released the Alt key, and Emacs gets just `x', which is BAD. However, for keys with the `Map' property set, the ASCII code returns zero only if Alt is pressed. So, when we DON'T have to support international_keyboard, we don't have to distinguish between the left and right Alt keys, and we can set the META modifier for any keys with the `Map' property if they return zero ASCII code (c = 0). */

/* Emacs calls cursor-movement functions a lot when it updates the display (probably a legacy of old terminals where you cannot update a screen line without first moving the cursor there). However, cursor movement is expensive on MSDOS (it calls a slow BIOS function and requires 2 mode switches), while actual screen updates access the video memory directly and don't depend on cursor position. To avoid slowing down the redisplay, we cheat: all functions that move the cursor only set internal variables which record the cursor position, whereas the cursor is only moved to its final position whenever screen update is complete. `IT_cmgoto' is called from the keyboard reading loop and when the frame update is complete. This means that we are ready for user input, so we update the cursor position to show where the point is, and also make the mouse pointer visible. Special treatment is required when the cursor is in the echo area, to put the cursor at the end of the text displayed there. */

/* Define a lot of environment variables if not already defined. Don't remove anything unless you know what you're doing -- lots of code will break if one or more of these are missing. */

/* Time zone determined from country code. To make this possible, the country code may not span more than one time zone. In other words, in the USA, you lose. */

/* FIXME: I'm not sure the above will run at all on DOS/V. But let's be defensive anyway. */ if ( screen_virtual_segment ) dosv_refresh_virtual_screen ( 0 , * cols * * rows );

/* Simulation of X's menus. Nothing too fancy here -- just make it work for now. Actually, I don't know the meaning of all the parameters of the functions here -- I only know how they are called by xmenu.c. I could of course grab the nearest Xlib manual (down the hall, second-to-last door on the left), but I don't think it's worth the effort. */

/* In some sense all dos users have root privileges, so... */ setenv ( "USER" , "root" , 0 ); setenv ( "NAME" , getenv ( "USER" ), 0 );

/* Don't restore the screen if we are exiting less than 2 seconds after startup: we might be crashing, and the screen might show some vital clues to what's wrong. */