3 * AUTHOR: John L. Miller, johnmil@cs.cmu.edu / johnmil@jprc.com
6 * Copyright (c) 1996 John L. Miller
8 * Full permission is granted to use, modify and distribute
10 * 1) This comment field is included in its entirity
11 * 2) No money is charged for any work including or based on
12 * portions of this code.
14 * If you're a nice person and find this useful, I'd appreciate a
15 * note letting me know about it. e-mail is usually what spurs me
16 * on to improve and support software I've written.
18 * This file contains functions intended to provide the back
19 * end to a console window for my semi-vt100 emulator.
22 /* Note - one HUGE difference between console windows and terminal
23 * windows. Console windows displays start at (0,0). Terminal displays
24 * start at (1,1). YUCK!
30 int topScrollRow
=TOP_EDGE
;
31 int bottomScrollRow
=BOTTOM_EDGE
;
33 /* This variable will contain terminal configuration flags, such as
34 * reverse/standard video, whether wrapping is enabled, and so on.
38 /* Variable to hold the cursor position for save/restore cursor calls */
39 COORD cursorPosSave
={1,1};
41 /* Handles to the current console for input and output */
42 HANDLE hConIn
, hConOut
;
44 /* Array of all the tabs which are currently set. Ironically, I think the
45 * primary emulator can CLEAR tags, but not set them.
51 /* This section contains console-specific color information. NT consoles can
52 * have Red, blue, green, and intensity flags set. Hence, 4 con_colors.
54 #define NUM_CON_COLORS 4
56 /* Foreground and background colors are separated out */
57 int conForeColors
, conBackColors
;
59 /* mapping between foreground and background console colors: needed
60 * when reverse video is being used
62 int conColorMapping
[NUM_CON_COLORS
][2] =
64 {FOREGROUND_RED
, BACKGROUND_RED
},
65 {FOREGROUND_BLUE
, BACKGROUND_BLUE
},
66 {FOREGROUND_GREEN
, BACKGROUND_GREEN
},
67 {FOREGROUND_INTENSITY
, BACKGROUND_INTENSITY
}
71 /* Device-independant foreground and background flags stored here.
72 * probably a bad division of labor, but hey, since we don't use
73 * all of their flags in our console stuff (and hence can't retrieve
74 * them), the information has to live SOMEWHERE.
77 int scForeFlags
, scBackFlags
;
79 /* Defines for array indexing for translation of flags */
81 #define CONSOLE_FLAG 1
83 /* Color mapping between SC (the vt-100 emulator device independant
84 * flags) and NT console character specific flags. Flags which have no analog
85 * are set to 0. Note that all global character attributes (character set
86 * underline, bold, reverse) are all stored in foreground only
88 const int scForeMapping
[NUM_SC_ATTRIBUTES
][2] =
90 {SC_RED
,FOREGROUND_RED
},
91 {SC_GREEN
,FOREGROUND_GREEN
},
92 {SC_BLUE
,FOREGROUND_BLUE
},
93 {SC_BOLD
,FOREGROUND_INTENSITY
},
103 /* Background color mapping between SC and console */
104 const int scBackMapping
[NUM_SC_ATTRIBUTES
][2] =
106 {SC_RED
,BACKGROUND_RED
},
107 {SC_GREEN
,BACKGROUND_GREEN
},
108 {SC_BLUE
,BACKGROUND_BLUE
},
109 {SC_BOLD
,BACKGROUND_INTENSITY
},
119 /* These arrays map character vals 0-255 to new values.
120 * Since the G0 and G1 character sets don't have a direct analog in
121 * NT, I'm settling for replacing the ones I know what to set them
127 /* These four sets of variables are just precomputed combinations of
128 * all the possible flags to save time for masking.
130 int allFore
[2], allBack
[2];
131 int bothFore
[2], bothBack
[2];
134 /* FORWARD DECLARATIONS */
146 /* END FORWARD DECLARATIONS */
150 /* beInitVT100Terminal() -
152 * This function is called by the VT100 emulator as soon as the
153 * front-end terminal is initialized. It's responsible for setting
154 * initial state of the terminal, and initing our many wacky variables.
158 beInitVT100Terminal()
161 CONSOLE_SCREEN_BUFFER_INFO csbi
;
163 /* Set tabs to every 8 spaces initially */
165 for (numTabs
=0; numTabs
< 132/8; numTabs
++)
166 tabSet
[numTabs
] = (numTabs
+1)*8;
168 /* Init the cursor save position to HOME */
172 /* Disable scrolling window limits */
173 topScrollRow
=TOP_EDGE
;
174 bottomScrollRow
=BOTTOM_EDGE
;
176 conTermMode
= ANSI_MODE
|WRAP_MODE
|REPEAT_MODE
;
178 hConIn
= GetStdHandle(STD_INPUT_HANDLE
);
179 hConOut
= GetStdHandle(STD_OUTPUT_HANDLE
);
181 /* Init our time-saving mask variables */
182 allFore
[SC_FLAG
] = allBack
[SC_FLAG
] = 0;
183 allFore
[CONSOLE_FLAG
] = allBack
[CONSOLE_FLAG
] = 0;
184 bothFore
[SC_FLAG
] = bothBack
[SC_FLAG
] = 0;
185 bothFore
[CONSOLE_FLAG
] = bothBack
[CONSOLE_FLAG
] = 0;
187 for (i
=0; i
<NUM_SC_ATTRIBUTES
; i
++)
189 allFore
[SC_FLAG
] |= scForeMapping
[i
][SC_FLAG
];
190 allFore
[CONSOLE_FLAG
] |= scForeMapping
[i
][CONSOLE_FLAG
];
191 allBack
[SC_FLAG
] |= scBackMapping
[i
][SC_FLAG
];
192 allBack
[CONSOLE_FLAG
] |= scBackMapping
[i
][CONSOLE_FLAG
];
194 if (scForeMapping
[i
][SC_FLAG
] && scForeMapping
[i
][CONSOLE_FLAG
])
196 bothFore
[SC_FLAG
] |= scForeMapping
[i
][SC_FLAG
];
197 bothFore
[CONSOLE_FLAG
] |= scForeMapping
[i
][CONSOLE_FLAG
];
200 if (scBackMapping
[i
][SC_FLAG
] && scBackMapping
[i
][CONSOLE_FLAG
])
202 bothBack
[SC_FLAG
] |= scBackMapping
[i
][SC_FLAG
];
203 bothBack
[CONSOLE_FLAG
] |= scBackMapping
[i
][CONSOLE_FLAG
];
207 conForeColors
= conBackColors
= 0;
209 for (i
=0; i
<NUM_CON_COLORS
; i
++)
211 conForeColors
|= conColorMapping
[i
][0];
212 conBackColors
|= conColorMapping
[i
][1];
216 /* Do initial settings for device-independant flags */
217 scForeFlags
= SC_ASCII
;
220 GetConsoleScreenBufferInfo(hConOut
, &csbi
);
222 for (i
=0; i
<NUM_SC_ATTRIBUTES
; i
++)
224 if (csbi
.wAttributes
& scForeMapping
[i
][CONSOLE_FLAG
])
225 scForeFlags
|= scForeMapping
[i
][SC_FLAG
];
227 if (csbi
.wAttributes
& scBackMapping
[i
][CONSOLE_FLAG
])
228 scBackFlags
|= scBackMapping
[i
][SC_FLAG
];
232 /* Since the G0/G1 character sets don't really map to
233 * USASCII, So come as close as we can. By default, it'll
234 * just print the ascii character. For the graphics characters
235 * I was able to identify, change that mapping.
238 for (i
=0; i
<256; i
++)
244 G1Chars
['a']=(char)177;
245 G1Chars
['f']=(char)248;
246 G1Chars
['g']=(char)241;
247 G1Chars
['j']=(char)217;
248 G1Chars
['k']=(char)191;
249 G1Chars
['l']=(char)218;
250 G1Chars
['m']=(char)192;
251 G1Chars
['n']=(char)197;
252 G1Chars
['o']=(char)196;
253 G1Chars
['p']=(char)196;
254 G1Chars
['q']=(char)196;
255 G1Chars
['r']=(char)196;
256 G1Chars
['s']=(char)196;
257 G1Chars
['t']=(char)195;
258 G1Chars
['u']=(char)180;
259 G1Chars
['v']=(char)193;
260 G1Chars
['w']=(char)194;
261 G1Chars
['x']=(char)179;
262 G1Chars
['y']=(char)243;
263 G1Chars
['z']=(char)242;
270 /* beAbsoluteCursor -
272 * Given an input row and column, move the cursor to the
273 * absolute screen coordinates requested. Note that if the
274 * display window has scrollbars, the column is adjusted
275 * to take that into account, but the row is not. This allows
276 * for large scrollback in terminal windows.
278 * ROW must be able to accept CUR_ROW, TOP_EDGE, BOTTOM_EDGE,
281 * COLUMN must be able to accept CUR_COL, LEFT_EDGE, RIGHT_EDGE,
282 * or a column number.
291 CONSOLE_SCREEN_BUFFER_INFO csbi
;
294 GetConsoleScreenBufferInfo(hConOut
, &csbi
);
297 row
= csbi
.dwCursorPosition
.Y
;
298 else if (row
== TOP_EDGE
)
299 row
= csbi
.srWindow
.Top
;
300 else if (row
== BOTTOM_EDGE
)
301 row
= csbi
.srWindow
.Bottom
;
303 row
+= csbi
.srWindow
.Top
- 1;
306 col
= csbi
.dwCursorPosition
.X
;
307 else if (col
== LEFT_EDGE
)
309 else if (col
== RIGHT_EDGE
)
310 col
= csbi
.dwSize
.X
-1;
317 SetConsoleCursorPosition(hConOut
, cursorPos
);
325 * Given an input row and column offset, move the cursor by that
326 * many positions. For instance, row=0 and column=-1 would move
327 * the cursor left a single column.
329 * If the cursor can't move the requested amount, results are
339 CONSOLE_SCREEN_BUFFER_INFO csbi
;
342 GetConsoleScreenBufferInfo(hConOut
, &csbi
);
344 cursorPos
= csbi
.dwCursorPosition
;
345 cursorPos
.X
+= column
;
351 if (cursorPos
.X
>= csbi
.dwSize
.X
)
353 cursorPos
.X
-= csbi
.dwSize
.X
;
360 SetConsoleCursorPosition(hConOut
, cursorPos
);
368 * Saved cursor position should be stored in a static
369 * variable in the back end. This function restores the
370 * cursor to the position stored in that variable.
374 beRestoreCursor(void)
376 CONSOLE_SCREEN_BUFFER_INFO csbi
;
379 GetConsoleScreenBufferInfo(hConOut
, &csbi
);
381 cursorPos
= csbi
.dwCursorPosition
;
383 cursorPos
.Y
+= cursorPosSave
.Y
;
385 SetConsoleCursorPosition(hConOut
, cursorPos
);
392 * The back-end should maintain a static variable with the
393 * last STORED cursor position in it. This function replaces
394 * the contents of that variable with the current cursor position.
395 * The cursor may be restored to this position by using the
396 * beRestoreCursor function.
402 CONSOLE_SCREEN_BUFFER_INFO csbi
;
404 GetConsoleScreenBufferInfo(hConOut
, &csbi
);
405 cursorPosSave
= csbi
.dwCursorPosition
;
407 cursorPosSave
.Y
-= csbi
.srWindow
.Top
;
413 /* beGetTextAttributes -
415 * given a pointer to 'fore'ground and 'back'ground ints,
416 * fill them with a device-independant description of the
417 * current foreground and background colors, as well as any
418 * font information in the foreground variable.
427 CONSOLE_SCREEN_BUFFER_INFO csbi
;
430 /* Since it's entirely possible that the text attributes were
431 * changed without our terminal being notified, we might as well
432 * make sure they're accurate.
435 /* First, strip out everything in the screen buffer variables
439 scForeFlags
&= ~bothFore
[SC_FLAG
];
440 scBackFlags
&= ~bothBack
[SC_FLAG
];
442 /* Now, find out what the real settings are, and set the
443 * flag values accordingly.
446 GetConsoleScreenBufferInfo(hConOut
, &csbi
);
449 /* If reverse video is set, we need to reverse our color mappings
450 * before any calculations get made.
453 if (scForeFlags
& SC_RV
)
455 int tmpFore
, tmpBack
;
457 tmpFore
= csbi
.wAttributes
& conForeColors
;
458 tmpBack
= csbi
.wAttributes
& conBackColors
;
460 csbi
.wAttributes
&= ~(conForeColors
| conBackColors
);
462 for (i
=0; i
<NUM_CON_COLORS
; i
++)
464 if (tmpFore
& conColorMapping
[i
][0])
465 csbi
.wAttributes
|= conColorMapping
[i
][1];
467 if (tmpBack
& conColorMapping
[i
][1])
468 csbi
.wAttributes
|= conColorMapping
[i
][0];
472 /* Now, do the actual translation between our detectable
473 * console text attributes and the corresponding device-independant
477 for (i
=0; i
<NUM_SC_ATTRIBUTES
; i
++)
479 if (csbi
.wAttributes
& scForeMapping
[i
][CONSOLE_FLAG
])
480 scForeFlags
|= scForeMapping
[i
][SC_FLAG
];
482 if (csbi
.wAttributes
& scBackMapping
[i
][CONSOLE_FLAG
])
483 scBackFlags
|= scBackMapping
[i
][SC_FLAG
];
486 /* Finally, copy our updated sc flags into the variables
500 /* beSetTextAttributes -
502 * Given a foreground and a background device independant (SC) color and font
503 * specification, apply these to the display, and save the state in the
504 * static screen variables.
506 * Note that many font-specific constants (bold/underline/reverse, G0/G1/ASCII)
507 * are stored ONLY in the foreground specification.
516 CONSOLE_SCREEN_BUFFER_INFO csbi
;
520 /* First off, let's assign these settings into our
521 * device-independant holder.
527 /* Next, determine the console's actual current settings */
529 GetConsoleScreenBufferInfo(hConOut
, &csbi
);
531 /* Mask out any of the attributes which can be set via
532 * our device-independant options. Since the console settings
533 * have additional options, we need to retain those so we don't
534 * do something unpleasant to our I/O abilities, for instance.
537 wAttributes
= csbi
.wAttributes
;
539 wAttributes
&= ~(bothFore
[CONSOLE_FLAG
] | bothBack
[CONSOLE_FLAG
]);
541 /* Now, loop through the device-independant possibilities for
542 * flags, and modify our console flags as appropriate.
545 for (i
=0; i
<NUM_SC_ATTRIBUTES
; i
++)
547 if (scForeFlags
& scForeMapping
[i
][SC_FLAG
])
548 wAttributes
|= scForeMapping
[i
][CONSOLE_FLAG
];
550 if (scBackFlags
& scBackMapping
[i
][SC_FLAG
])
551 wAttributes
|= scBackMapping
[i
][CONSOLE_FLAG
];
554 /* One last unpleasantry: if reverse video is set, then we should
555 * reverse the foreground and background colors
558 if (scForeFlags
& SC_RV
)
560 int tmpFore
, tmpBack
;
562 tmpFore
= wAttributes
& conForeColors
;
563 tmpBack
= wAttributes
& conBackColors
;
565 wAttributes
&= ~(conForeColors
| conBackColors
);
567 for (i
=0; i
<NUM_CON_COLORS
; i
++)
569 if (tmpFore
& conColorMapping
[i
][0])
570 wAttributes
|= conColorMapping
[i
][1];
572 if (tmpBack
& conColorMapping
[i
][1])
573 wAttributes
|= conColorMapping
[i
][0];
577 /* The appropriate colors, etc. should be set in
578 * the wAttributes variable now. Apply them to the
582 SetConsoleTextAttribute(hConOut
, wAttributes
);
590 * The name of this function is misleading. Given a pointer to
591 * ascii text and a count of bytes to print, print them to the
592 * display device. If wrapping is enabled, wrap text. If there is a
593 * scrolling region set and the cursor is in it,
594 * scroll only within that region. 'beRawTextOut' means that it's guaranteed
595 * not to have control sequences within the text.
606 /* If there's no work to do, return immediately. */
607 if ((text
== NULL
)||(len
== 0))
612 /* Otherwise, loop through the text until all of it has been output */
615 /* This inner loop serves to divide the raw text to output into
616 * explicit lines. While the 'RawPrintLine' may still have to
617 * break lines to do text wrapping, explicit line breaks are
618 * handled right here.
621 while ((text
[j
] != '\n')&&(j
<len
))
626 RawPrintLine(text
+i
, j
-i
, (text
[j
] == '\n'));
637 * This routine is a helper for beRawTextOut. It is given a
638 * line of text which is guaranteed not to have any newlines
639 * or control characters (which need to be interpreted) in it.
640 * It prints out the text, wrapping if necessary, and handles
641 * scrolling or truncation.
643 * If scrollAtEnd is true, an extra carriage return (scroll) is
644 * performed after the text has been printed out.
655 CONSOLE_SCREEN_BUFFER_INFO csbi
;
658 if ((scrollAtEnd
== FALSE
) && ((text
== NULL
)||(len
== 0)))
661 GetConsoleScreenBufferInfo(hConOut
, &csbi
);
663 /* find out how far to the first tab or end of text */
667 for (end
=0; end
<len
; end
++)
669 if (text
[end
] == '\t')
673 if (end
> (csbi
.dwSize
.X
- csbi
.dwCursorPosition
.X
))
674 end
= (csbi
.dwSize
.X
- csbi
.dwCursorPosition
.X
);
676 /* If we're in non-ascii mode, we need to do a little
677 * magic to get the right characters out.
680 if (scForeFlags
& SC_G1
)
682 for (i
=0; i
<end
; i
++)
684 text
[i
] = G1Chars
[text
[i
]];
688 /* actually print out the text. */
690 WriteConsole(hConOut
,text
,(DWORD
)end
,&dwWritten
,NULL
);
692 if (end
== (csbi
.dwSize
.X
- csbi
.dwCursorPosition
.X
))
695 if ( (!(conTermMode
& WRAP_MODE
))
696 && (end
== (csbi
.dwSize
.X
- csbi
.dwCursorPosition
.X
))
702 if (text
[end
] == '\t')
705 RawPrintLine(text
+end
+1,len
- (end
+1), FALSE
);
709 RawPrintLine(text
+end
, len
-end
, FALSE
);
710 beAbsoluteCursor(CUR_ROW
,1);
716 /* Now that we've printed this line, scroll if we need to.
717 * Note that a scroll implies a newline.
723 beAbsoluteCursor(CUR_ROW
,1);
733 * Given a row specification, calculate a scroll executed in that
734 * row. It could be within a scroll range, or outside of it.
736 * For some ungodly reason, I made this routine handle the TOP_EDGE,
737 * BOTTOM_EDGE, and CUR_ROW specifiers as well as a real row.
745 CONSOLE_SCREEN_BUFFER_INFO csbi
;
746 SMALL_RECT scrollRect
;
750 GetConsoleScreenBufferInfo(hConOut
, &csbi
);
753 row
= csbi
.srWindow
.Top
;
754 else if (row
== BOTTOM_EDGE
)
755 row
= csbi
.srWindow
.Bottom
;
756 else if (row
== CUR_ROW
)
757 row
= csbi
.dwCursorPosition
.Y
;
759 row
+= csbi
.srWindow
.Top
;
761 /* Escape out if we don't really need to scroll */
763 if ( (row
< (csbi
.dwSize
.Y
-1))
764 && ((row
-csbi
.srWindow
.Top
+ 1) < bottomScrollRow
)
768 /* NT console requires a fill character for scrolling. */
770 fillChar
.Char
.AsciiChar
=' ';
771 fillChar
.Attributes
= csbi
.wAttributes
;
773 /* Determine the rectangle of text to scroll. Under NT this
774 * is actually an overlap-safe block-copy.
778 scrollRect
.Right
= csbi
.dwSize
.X
;
779 scrollRect
.Bottom
= row
;
781 if (topScrollRow
!= TOP_EDGE
)
783 scrollRect
.Top
= csbi
.srWindow
.Top
+ topScrollRow
+ 1;
786 if ( (bottomScrollRow
!= BOTTOM_EDGE
)
787 && ((csbi
.srWindow
.Top
+bottomScrollRow
) < scrollRect
.Bottom
)
790 scrollRect
.Bottom
= csbi
.srWindow
.Top
+ bottomScrollRow
;
794 dest
.Y
= scrollRect
.Top
- 1;
796 ScrollConsoleScreenBuffer(hConOut
,&scrollRect
,NULL
,
805 * Given a 'from' and a 'to' position in display coordinates,
806 * this function will fill in all characters between the two
807 * (inclusive) with spaces. Note that the coordinates do NOT
808 * specify a rectangle. erasing from (1,1) to (2,2) erases
809 * all of the first row, and the first two characters of the
812 * Note that this routine must be able to handle TOP_EDGE,
813 * BOTTOM_EDGE, LEFT_EDGE, RIGHT_EDGE, CUR_ROW, and CUR_COL
814 * in the appropriate parameters.
825 CONSOLE_SCREEN_BUFFER_INFO csbi
;
826 COORD dest
, saveCursor
;
827 DWORD nLength
, dwWritten
;
829 GetConsoleScreenBufferInfo(hConOut
, &csbi
);
831 saveCursor
= csbi
.dwCursorPosition
;
833 /* Convert the row and column specifications into
836 if (rowFrom
== CUR_ROW
)
837 rowFrom
= csbi
.dwCursorPosition
.Y
;
838 else if (rowFrom
== TOP_EDGE
)
839 rowFrom
= csbi
.srWindow
.Top
;
841 rowFrom
+= csbi
.srWindow
.Top
-1;
843 if (colFrom
== CUR_COL
)
844 colFrom
= csbi
.dwCursorPosition
.X
;
845 else if (colFrom
== LEFT_EDGE
)
850 if (rowTo
== CUR_ROW
)
851 rowTo
= csbi
.dwCursorPosition
.Y
;
852 else if (rowTo
== BOTTOM_EDGE
)
853 rowTo
= csbi
.srWindow
.Bottom
;
855 rowTo
+= csbi
.srWindow
.Top
-1;
857 if (colTo
== CUR_COL
)
858 colTo
= csbi
.dwCursorPosition
.X
;
859 else if (colTo
== RIGHT_EDGE
)
860 colTo
= csbi
.dwSize
.X
;
864 /* We're going to erase by filling a continuous range of
865 * character cells with spaces. Note that this has displeasing
866 * asthetics under NT, as highlighting appears to be immune.
868 nLength
= (rowTo
- rowFrom
)*csbi
.dwSize
.X
;
869 nLength
+= colTo
- colFrom
;
874 FillConsoleOutputCharacter(hConOut
, ' ', nLength
, dest
, &dwWritten
);
875 FillConsoleOutputAttribute(hConOut
, csbi
.wAttributes
, nLength
, dest
, &dwWritten
);
877 SetConsoleCursorPosition(hConOut
, saveCursor
);
885 * Given a screen cursor 'from' and 'to' position, this function
886 * will delete all text between the two. Text will be scrolled
887 * up as appropriate to fill the deleted space. Note that, as in
888 * beEraseText, the two coordinates don't specify a rectangle, but
889 * rather a starting position and ending position. In other words,
890 * deleting from (1,1) to (2,2) should move the text from (2,3) to the
891 * end of the second row to (1,1), move line 3 up to line 2, and so on.
893 * This function must be able to process TOP_EDGE, BOTTOM_EDGE, LEFT_EDGE,
894 * RIGHT_EDGE, CUR_ROW, and CUR_COL specifications in the appropriate
895 * variables as well as regular row and column specifications.
906 CONSOLE_SCREEN_BUFFER_INFO csbi
;
907 COORD dest
, saveCursor
;
910 GetConsoleScreenBufferInfo(hConOut
, &csbi
);
912 saveCursor
= csbi
.dwCursorPosition
;
914 if (rowFrom
== CUR_ROW
)
915 rowFrom
= csbi
.dwCursorPosition
.Y
;
916 else if (rowFrom
== TOP_EDGE
)
917 rowFrom
= csbi
.srWindow
.Top
;
919 rowFrom
+= csbi
.srWindow
.Top
-1;
921 if (colFrom
== CUR_COL
)
922 colFrom
= csbi
.dwCursorPosition
.X
;
923 else if (colFrom
== LEFT_EDGE
)
928 if (rowTo
== CUR_ROW
)
929 rowTo
= csbi
.dwCursorPosition
.Y
;
930 else if (rowTo
== BOTTOM_EDGE
)
931 rowTo
= csbi
.srWindow
.Bottom
;
933 rowTo
+= csbi
.srWindow
.Top
-1;
935 if (colTo
== CUR_COL
)
936 colTo
= csbi
.dwCursorPosition
.X
;
937 else if (colTo
== RIGHT_EDGE
)
938 colTo
= csbi
.dwSize
.X
;
942 fillChar
.Char
.AsciiChar
=' ';
943 fillChar
.Attributes
= csbi
.wAttributes
;
945 /* Now that we've got the from and to positions
946 * set correctly, we need to delete appropriate
953 /* BUGBUG - need to implement this. What can I say, I'm lazy :) */
961 * Given a row number or CUR_ROW, TOP_EDGE or BOTTOM_EDGE as an input,
962 * this function will scroll all text from the current row down down by one,
963 * and create a blank row under the cursor.
971 CONSOLE_SCREEN_BUFFER_INFO csbi
;
974 SMALL_RECT scrollRect
;
976 GetConsoleScreenBufferInfo(hConOut
, &csbi
);
978 fillChar
.Char
.AsciiChar
=' ';
979 fillChar
.Attributes
= csbi
.wAttributes
;
982 row
= csbi
.dwCursorPosition
.Y
;
983 else if (row
== TOP_EDGE
)
984 row
= csbi
.srWindow
.Top
;
985 else if (row
== BOTTOM_EDGE
)
986 row
= csbi
.srWindow
.Bottom
;
988 row
+= csbi
.srWindow
.Top
-1;
993 scrollRect
.Top
= row
;
995 scrollRect
.Right
= csbi
.dwSize
.X
;
996 scrollRect
.Bottom
= csbi
.srWindow
.Bottom
;
998 ScrollConsoleScreenBuffer(hConOut
, &scrollRect
, NULL
, dest
, &fillChar
);
1006 * Given a pointer to text and byte count, this routine should transmit data
1007 * to whatever host made the request it's responding to. Typically this routin
1008 * should transmit data as though the user had typed it in.
1017 if ((text
== NULL
) || (len
< 1))
1020 /* BUGBUG - need to implement this. */
1028 * This routine will destructively advance the cursor to the
1029 * next set tab, or to the end of the line if there are no
1030 * more tabs to the right of the cursor.
1034 beAdvanceToTab(void)
1036 CONSOLE_SCREEN_BUFFER_INFO csbi
;
1041 GetConsoleScreenBufferInfo(hConOut
,&csbi
);
1043 col
= csbi
.dwCursorPosition
.X
+1;
1045 dest
= csbi
.dwCursorPosition
;
1047 for(i
=0; i
<numTabs
; i
++)
1049 if (col
< tabSet
[i
])
1058 tocol
= csbi
.dwSize
.X
;
1061 FillConsoleOutputCharacter(hConOut
, ' ', tocol
-col
,
1064 beOffsetCursor(0,tocol
-col
);
1072 * This function accepts a constant, and will try to clear tabs
1073 * appropriately. Its argument is either
1074 * ALL_TABS, meaning all tabs should be removed
1075 * CUR_COL, meaning the tab in the current column should be wiped, or
1076 * a column value, meaning if there's a tab there it should be wiped.
1086 CONSOLE_SCREEN_BUFFER_INFO csbi
;
1088 if (col
== ALL_TABS
)
1097 GetConsoleScreenBufferInfo(hConOut
,&csbi
);
1098 col
= csbi
.dwCursorPosition
.X
+1;
1101 for (i
=0; i
<numTabs
; i
++)
1103 if (tabSet
[i
] == col
)
1107 for (j
=i
; j
<numTabs
; j
++)
1108 tabSet
[j
]=tabSet
[j
+1];
1117 /* beSetScrollingRows -
1119 * Given a pair of row numbers, this routine will set the scrolling
1120 * rows to those values. Note that this routine will accept
1121 * TOP_ROW and BOTTOM_ROW as values, meaning that scrolling should
1122 * be enabled for the entire display, regardless of resizing.
1131 if (fromRow
> toRow
)
1134 topScrollRow
= fromRow
;
1135 bottomScrollRow
= toRow
;
1143 * Ring the system bell once.
1149 MessageBeep((UINT
)-1);
1156 * Return the value of conTermMode, which is the terminal settings which
1157 * can be queried/set by <esc>[?#h/l.
1163 return(conTermMode
);
1169 * Set the terminal as requested, assuming we can. Right now we only handle a
1170 * couple of the possible flags, but we store many of the others.
1178 CONSOLE_SCREEN_BUFFER_INFO csbi
;
1180 SMALL_RECT newWindowRect
;
1183 changes
= conTermMode
^ newMode
;
1185 /* For each bit set in 'changes', determine the
1186 * appropriate course of action.
1189 for (i
=0; i
< NUM_TERM_ATTR_MODES
; i
++)
1191 if (termAttrMode
[i
] & changes
)
1193 switch(termAttrMode
[i
])
1196 GetConsoleScreenBufferInfo(hConOut
, &csbi
);
1197 newSize
.Y
= csbi
.dwSize
.Y
;
1198 newSize
.X
= (newMode
& COL132_MODE
) ? 132 : 80;
1199 if (newSize
.X
!= csbi
.dwSize
.X
)
1201 newWindowRect
.Top
= csbi
.srWindow
.Top
;
1202 newWindowRect
.Bottom
= csbi
.srWindow
.Bottom
;
1203 newWindowRect
.Left
= 0;
1204 newWindowRect
.Right
= csbi
.dwSize
.X
- 1;
1205 SetConsoleScreenBufferSize(hConOut
, newSize
);
1206 SetConsoleWindowInfo(hConOut
, TRUE
, &newWindowRect
);
1211 GetConsoleMode(hConOut
,&dwConMode
);
1212 if ( (newMode
& WRAP_MODE
)
1213 && (! (dwConMode
& ENABLE_WRAP_AT_EOL_OUTPUT
))
1216 dwConMode
|= ENABLE_WRAP_AT_EOL_OUTPUT
;
1217 SetConsoleMode(hConOut
, dwConMode
);
1219 if ( (!(newMode
& WRAP_MODE
))
1220 && (dwConMode
& ENABLE_WRAP_AT_EOL_OUTPUT
)
1223 dwConMode
&= ~ENABLE_WRAP_AT_EOL_OUTPUT
;
1224 SetConsoleMode(hConOut
, dwConMode
);
1228 case CURSORAPPL_MODE
:
1230 case SMOOTHSCROLL_MODE
:
1231 case REVSCREEN_MODE
:
1232 case ORIGINREL_MODE
:
1234 /* bugbug - we don't handle any of these. */
1240 conTermMode
= newMode
;