+#define DEFAULT_CURSOR_START (-1)
+#define DEFAULT_CURSOR_WIDTH (-1)
+#define BOX_CURSOR_WIDTH (-32)
+
+/* Set cursor to begin at scan line START_LINE in the character cell
+ and extend for WIDTH scan lines. Scan lines are counted from top
+ of the character cell, starting from zero. */
+static void
+msdos_set_cursor_shape (struct frame *f, int start_line, int width)
+{
+#if __DJGPP__ > 1
+ unsigned desired_cursor;
+ __dpmi_regs regs;
+ int max_line, top_line, bot_line;
+
+ /* Avoid the costly BIOS call if F isn't the currently selected
+ frame. Allow for NULL as unconditionally meaning the selected
+ frame. */
+ if (f && f != SELECTED_FRAME())
+ return;
+
+ /* The character cell size in scan lines is stored at 40:85 in the
+ BIOS data area. */
+ max_line = _farpeekw (_dos_ds, 0x485) - 1;
+ switch (max_line)
+ {
+ default: /* this relies on CGA cursor emulation being ON! */
+ case 7:
+ bot_line = 7;
+ break;
+ case 9:
+ bot_line = 9;
+ break;
+ case 13:
+ bot_line = 12;
+ break;
+ case 15:
+ bot_line = 14;
+ break;
+ }
+
+ if (width < 0)
+ {
+ if (width == BOX_CURSOR_WIDTH)
+ {
+ top_line = 0;
+ bot_line = max_line;
+ }
+ else if (start_line != DEFAULT_CURSOR_START)
+ {
+ top_line = start_line;
+ bot_line = top_line - width - 1;
+ }
+ else if (width != DEFAULT_CURSOR_WIDTH)
+ {
+ top_line = 0;
+ bot_line = -1 - width;
+ }
+ else
+ top_line = bot_line + 1;
+ }
+ else if (width == 0)
+ {
+ /* [31, 0] seems to DTRT for all screen sizes. */
+ top_line = 31;
+ bot_line = 0;
+ }
+ else /* WIDTH is positive */
+ {
+ if (start_line != DEFAULT_CURSOR_START)
+ bot_line = start_line;
+ top_line = bot_line - (width - 1);
+ }
+
+ /* If the current cursor shape is already what they want, we are
+ history here. */
+ desired_cursor = ((top_line & 0x1f) << 8) | (bot_line & 0x1f);
+ if (desired_cursor == _farpeekw (_dos_ds, 0x460))
+ return;
+
+ regs.h.ah = 1;
+ regs.x.cx = desired_cursor;
+ __dpmi_int (0x10, ®s);
+#endif /* __DJGPP__ > 1 */
+}
+
+static void
+IT_set_cursor_type (struct frame *f, Lisp_Object cursor_type)
+{
+ if (EQ (cursor_type, Qbar))
+ {
+ /* Just BAR means the normal EGA/VGA cursor. */
+ msdos_set_cursor_shape (f, DEFAULT_CURSOR_START, DEFAULT_CURSOR_WIDTH);
+ }
+ else if (CONSP (cursor_type) && EQ (XCAR (cursor_type), Qbar))
+ {
+ Lisp_Object bar_parms = XCDR (cursor_type);
+ int width;
+
+ if (INTEGERP (bar_parms))
+ {
+ /* Feature: negative WIDTH means cursor at the top
+ of the character cell, zero means invisible cursor. */
+ width = XINT (bar_parms);
+ msdos_set_cursor_shape (f, width >= 0 ? DEFAULT_CURSOR_START : 0,
+ width);
+ }
+ else if (CONSP (bar_parms)
+ && INTEGERP (XCAR (bar_parms))
+ && INTEGERP (XCDR (bar_parms)))
+ {
+ int start_line = XINT (XCDR (bar_parms));
+
+ width = XINT (XCAR (bar_parms));
+ msdos_set_cursor_shape (f, start_line, width);
+ }
+ }
+ else
+ /* Treat anything unknown as "box cursor". This includes nil, so
+ that a frame which doesn't specify a cursor type gets a box,
+ which is the default in Emacs. */
+ msdos_set_cursor_shape (f, 0, BOX_CURSOR_WIDTH);
+}
+