Develop and Download Open Source Software

Browse Subversion Repository

Contents of /trunk/teraterm/teraterm/vtterm.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 10936 - (show annotations) (download) (as text)
Sat Sep 16 14:32:22 2023 UTC (5 months, 3 weeks ago) by zmatsuo
File MIME type: text/x-csrc
File size: 134821 byte(s)
ウィンドウタイトルをスタックに保存(CSI 22)が行えない場合があったので修正

- リモートタイトルが設定されていない場合
1 /*
2 * Copyright (C) 1994-1998 T. Teranishi
3 * (C) 2004- TeraTerm Project
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 /* TERATERM.EXE, VT terminal emulation */
31 #include "teraterm.h"
32 #include "tttypes.h"
33 #include <stdio.h>
34 #include <string.h>
35 #include <locale.h>
36 #include <ctype.h>
37 #if !defined(_CRTDBG_MAP_ALLOC)
38 #define _CRTDBG_MAP_ALLOC
39 #endif
40 #include <stdlib.h>
41 #include <crtdbg.h>
42 #include <assert.h>
43
44 #include "buffer.h"
45 #include "ttwinman.h"
46 #include "ttcommon.h"
47 #include "commlib.h"
48 #include "vtdisp.h"
49 #include "keyboard.h"
50 #include "ttlib.h"
51 #include "filesys.h"
52 #include "teraprn.h"
53 #include "telnet.h"
54 #include "ttime.h"
55 #include "clipboar.h"
56 #include "codeconv.h"
57 #include "ttdde.h"
58 #include "checkeol.h"
59 #include "asprintf.h"
60 #include "charset.h"
61 #include "ttcstd.h"
62
63 #include "vtterm.h"
64
65 // #define DEBUG_DUMP_INPUTCODE 1
66
67 #define Accept8BitCtrl ((VTlevel >= 2) && (ts.TermFlag & TF_ACCEPT8BITCTRL))
68
69 /* Parsing modes */
70 #define ModeFirst 0
71 #define ModeESC 1
72 #define ModeDCS 2
73 #define ModeDCUserKey 3
74 #define ModeSOS 4
75 #define ModeCSI 5
76 #define ModeXS 6
77 #define ModeDLE 7
78 #define ModeCAN 8
79 #define ModeIgnore 9
80
81 #define NParamMax 16
82 #define NSParamMax 16
83 #define IntCharMax 5
84
85 /* DEC Locator Flag */
86 #define DecLocatorOneShot 1
87 #define DecLocatorPixel 2
88 #define DecLocatorButtonDown 4
89 #define DecLocatorButtonUp 8
90 #define DecLocatorFiltered 16
91
92 static void RingBell(int type);
93 static void VisualBell(void);
94 static BOOL DecLocatorReport(int Event, int Button);
95 static CharSetData *CharSetInitTerm(void);
96
97 /* character attribute */
98 static TCharAttr CharAttr;
99
100 /* various modes of VT emulation */
101 static BOOL RelativeOrgMode;
102 static BOOL InsertMode;
103 static BOOL LFMode;
104 static BOOL ClearThenHome;
105 static BOOL AutoWrapMode;
106 static BOOL FocusReportMode;
107 static BOOL AltScr;
108 static BOOL LRMarginMode;
109 static BOOL RectangleMode;
110 static BOOL BracketedPaste;
111
112 static char BracketStart[] = "\033[200~";
113 static char BracketEnd[] = "\033[201~";
114 static int BracketStartLen = (sizeof(BracketStart)-1);
115 static int BracketEndLen = (sizeof(BracketEnd)-1);
116
117 static int VTlevel;
118
119 static BOOL AcceptWheelToCursor;
120
121 // save/restore cursor
122 typedef struct {
123 int CursorX, CursorY;
124 TCharAttr Attr;
125 CharSetState CharSetState;
126 BOOL AutoWrapMode;
127 BOOL RelativeOrgMode;
128 } TStatusBuff;
129 typedef TStatusBuff *PStatusBuff;
130
131 // currently only used for AUTO CR/LF receive mode
132 static BYTE PrevCharacter;
133 static BOOL PrevCRorLFGeneratedCRLF; // indicates that previous CR or LF really generated a CR+LF
134
135 static char32_t LastPutCharacter;
136
137 // status buffer for main screen & status line
138 static TStatusBuff SBuff1, SBuff2, SBuff3;
139
140 static BOOL ESCFlag, JustAfterESC;
141
142 static int Param[NParamMax+1];
143 static int SubParam[NParamMax+1][NSParamMax+1];
144 static int NParam, NSParam[NParamMax+1];
145 static BOOL FirstPrm;
146 static BYTE IntChar[IntCharMax+1];
147 static int ICount;
148 static BYTE Prv;
149 static int ParseMode;
150 static int ChangeEmu;
151
152 typedef struct tstack {
153 wchar_t *title;
154 struct tstack *next;
155 } TStack;
156 typedef TStack *PTStack;
157 static PTStack TitleStack = NULL;
158
159 /* user defined keys */
160 static BOOL WaitKeyId, WaitHi;
161
162 // variables for status line mode
163 static int StatusX=0;
164 static BOOL StatusWrap=FALSE;
165 static BOOL StatusCursor=TRUE;
166 static int MainX, MainY; //cursor registers
167 static int MainTop, MainBottom; // scroll region registers
168 static BOOL MainWrap;
169 static BOOL MainCursor=TRUE;
170
171 /* status for printer escape sequences */
172 static BOOL PrintEX = TRUE; // printing extent
173 // (TRUE: screen, FALSE: scroll region)
174 static BOOL AutoPrintMode = FALSE;
175 static BOOL PrinterMode = FALSE;
176 static BOOL DirectPrn = FALSE;
177 PrintFile *PrintFile_;
178
179 /* User key */
180 static BYTE NewKeyStr[FuncKeyStrMax];
181 static int NewKeyId, NewKeyLen;
182
183 /* Mouse Report */
184 static int MouseReportMode;
185 static int MouseReportExtMode;
186 static unsigned int DecLocatorFlag;
187 static int LastX, LastY;
188 static int ButtonStat;
189 static int FilterTop, FilterBottom, FilterLeft, FilterRight;
190
191 /* Saved IME status */
192 static BOOL SavedIMEstatus;
193
194 /* Beep over-used */
195 static DWORD BeepStartTime = 0;
196 static DWORD BeepSuppressTime = 0;
197 static DWORD BeepOverUsedCount = 0;
198
199 static _locale_t CLocale = NULL;
200
201 typedef struct {
202 CheckEOLData_t *check_eol;
203 int log_cr_type;
204 } vtterm_work_t;
205
206 static CharSetData *charset_data;
207 static vtterm_work_t vtterm_work;
208
209 static void ClearParams(void)
210 {
211 ICount = 0;
212 NParam = 1;
213 NSParam[1] = 0;
214 Param[1] = 0;
215 Prv = 0;
216 }
217
218 static void SaveCursorBuf(PStatusBuff Buff)
219 {
220 Buff->CursorX = CursorX;
221 Buff->CursorY = CursorY;
222 Buff->Attr = CharAttr;
223
224 CharSetSaveState(charset_data, &Buff->CharSetState);
225 Buff->AutoWrapMode = AutoWrapMode;
226 Buff->RelativeOrgMode = RelativeOrgMode;
227 }
228
229 static void SaveCursor()
230 {
231 PStatusBuff Buff;
232
233 if (isCursorOnStatusLine)
234 Buff = &SBuff2; // for status line
235 else if (AltScr)
236 Buff = &SBuff3; // for alternate screen
237 else
238 Buff = &SBuff1; // for main screen
239
240 SaveCursorBuf(Buff);
241 }
242
243 static void RestoreCursor()
244 {
245 PStatusBuff Buff;
246
247 UpdateStr();
248
249 if (isCursorOnStatusLine)
250 Buff = &SBuff2; // for status line
251 else if (AltScr)
252 Buff = &SBuff3; // for alternate screen
253 else
254 Buff = &SBuff1; // for main screen
255
256 if (Buff->CursorX > NumOfColumns-1)
257 Buff->CursorX = NumOfColumns-1;
258 if (Buff->CursorY > NumOfLines-1-StatusLine)
259 Buff->CursorY = NumOfLines-1-StatusLine;
260 MoveCursor(Buff->CursorX, Buff->CursorY);
261
262 CharAttr = Buff->Attr;
263 BuffSetCurCharAttr(CharAttr);
264 CharSetLoadState(charset_data, &Buff->CharSetState);
265
266 AutoWrapMode = Buff->AutoWrapMode;
267 RelativeOrgMode = Buff->RelativeOrgMode;
268 }
269
270 void ResetTerminal() /*reset variables but don't update screen */
271 {
272 DispReset();
273 BuffReset();
274
275 /* Attribute */
276 CharAttr = DefCharAttr;
277 BuffSetCurCharAttr(CharAttr);
278
279 /* Various modes */
280 InsertMode = FALSE;
281 LFMode = (ts.CRSend == IdCRLF);
282 AutoWrapMode = TRUE;
283 AppliKeyMode = FALSE;
284 AppliCursorMode = FALSE;
285 AppliEscapeMode = FALSE;
286 AcceptWheelToCursor = ts.TranslateWheelToCursor;
287 RelativeOrgMode = FALSE;
288 ts.ColorFlag &= ~CF_REVERSEVIDEO;
289 AutoRepeatMode = TRUE;
290 FocusReportMode = FALSE;
291 MouseReportMode = IdMouseTrackNone;
292 MouseReportExtMode = IdMouseTrackExtNone;
293 DecLocatorFlag = 0;
294 ClearThenHome = FALSE;
295 RectangleMode = FALSE;
296
297 ChangeTerminalID();
298
299 LastX = 0;
300 LastY = 0;
301 ButtonStat = 0;
302
303 if (CLocale == NULL) {
304 CLocale = _create_locale(LC_ALL, "C");
305 }
306
307 /* Character sets */
308 ResetCharSet();
309 // status buffers
310 SaveCursorBuf(&SBuff1);
311 SaveCursorBuf(&SBuff2);
312 SaveCursorBuf(&SBuff3);
313
314 /* ESC flag for device control sequence */
315 ESCFlag = FALSE;
316 /* for TEK sequence */
317 JustAfterESC = FALSE;
318
319 /* Parse mode */
320 ParseMode = ModeFirst;
321
322 /* Clear printer mode */
323 PrinterMode = FALSE;
324
325 // Alternate Screen Buffer
326 AltScr = FALSE;
327
328 // Left/Right Margin Mode
329 LRMarginMode = FALSE;
330
331 // Bracketed Paste Mode
332 BracketedPaste = FALSE;
333
334 // Saved IME Status
335 SavedIMEstatus = FALSE;
336
337 // previous received character
338 PrevCharacter = -1; // none
339 PrevCRorLFGeneratedCRLF = FALSE;
340
341 LastPutCharacter = 0;
342
343 // Beep over-used
344 BeepStartTime = GetTickCount();
345 BeepSuppressTime = BeepStartTime - ts.BeepSuppressTime * 1000;
346 BeepStartTime -= (ts.BeepOverUsedTime * 1000);
347 BeepOverUsedCount = ts.BeepOverUsedCount;
348
349 {
350 vtterm_work_t *vtterm = &vtterm_work;
351 if (vtterm->check_eol == NULL) {
352 vtterm->check_eol = CheckEOLCreate();
353 }
354 else {
355 CheckEOLClear(vtterm->check_eol);
356 }
357 vtterm->log_cr_type = 0;
358 }
359 }
360
361 void ResetCharSet()
362 {
363 if (ts.Language != IdJapanese) {
364 cv.SendCode = IdASCII;
365 cv.EchoCode = IdASCII;
366 }
367
368 cv.Language = ts.Language;
369 cv.CRSend = ts.CRSend;
370 cv.KanjiCodeEcho = ts.KanjiCode;
371 cv.JIS7KatakanaEcho = ts.JIS7Katakana;
372 cv.KanjiCodeSend = ts.KanjiCodeSend;
373 cv.JIS7KatakanaSend = ts.JIS7KatakanaSend;
374 cv.KanjiIn = ts.KanjiIn;
375 cv.KanjiOut = ts.KanjiOut;
376
377 if (charset_data != NULL) {
378 CharSetFinish(charset_data);
379 }
380 charset_data = CharSetInitTerm();
381 }
382
383 void ResetKeypadMode(BOOL DisabledModeOnly)
384 {
385 if (!DisabledModeOnly || ts.DisableAppKeypad)
386 AppliKeyMode = FALSE;
387 if (!DisabledModeOnly || ts.DisableAppCursor)
388 AppliCursorMode = FALSE;
389 }
390
391 static void MoveToMainScreen(void)
392 {
393 StatusX = CursorX;
394 StatusWrap = Wrap;
395 StatusCursor = IsCaretEnabled();
396
397 CursorTop = MainTop;
398 CursorBottom = MainBottom;
399 Wrap = MainWrap;
400 DispEnableCaret(MainCursor);
401 MoveCursor(MainX, MainY); // move to main screen
402 }
403
404 /**
405 * 1�L�����N�^(unsigned int, char32_t)��macro���o��
406 */
407 static void DDEPut1U32(unsigned int u32)
408 {
409 if (DDELog) {
410 // UTF-8 ���o������
411 char u8_buf[4];
412 size_t u8_len = UTF32ToUTF8(u32, u8_buf, _countof(u8_buf));
413 size_t i;
414 for (i = 0; i < u8_len; i++) {
415 BYTE b = u8_buf[i];
416 DDEPut1(b);
417 }
418 }
419 }
420
421 /**
422 * ���O���������������s�R�[�h���o��
423 */
424 static void OutputLogNewLine(vtterm_work_t *vtterm)
425 {
426 switch(vtterm->log_cr_type) {
427 case 0:
428 // CR + LF
429 FLogPutUTF32(CR);
430 FLogPutUTF32(LF);
431 break;
432 case 1:
433 // CR
434 FLogPutUTF32(CR);
435 break;
436 case 2:
437 // LF
438 FLogPutUTF32(LF);
439 break;
440 }
441 }
442
443 /**
444 * 1�L�����N�^(unsigned int, char32_t)�����O(or/and macro���M�o�b�t�@)���o��
445 * �o����
446 * ���O�t�@�C��
447 * macro���M�o�b�t�@(DDEPut1())
448 * �v�����g�p
449 */
450 static void OutputLogUTF32(unsigned int u32)
451 {
452 vtterm_work_t *vtterm;
453 CheckEOLRet r;
454
455 if (!FLogIsOpendText() && !DDELog && !PrinterMode) {
456 return;
457 }
458 vtterm = &vtterm_work;
459 r = CheckEOLCheck(vtterm->check_eol, u32);
460
461 // ���O
462 if (FLogIsOpendText()) {
463 if ((r & CheckEOLOutputEOL) != 0) {
464 // ���s���o��
465 OutputLogNewLine(vtterm);
466 }
467
468 if ((r & CheckEOLOutputChar) != 0) {
469 // u32���o��
470 FLogPutUTF32(u32);
471 }
472 }
473
474 // �}�N���o��
475 if (DDELog) {
476 if ((r & CheckEOLOutputEOL) != 0) {
477 // ���s���o��
478 DDEPut1(CR);
479 DDEPut1(LF);
480 }
481
482 // u32���o��
483 if ((r & CheckEOLOutputChar) != 0) {
484 DDEPut1U32(u32);
485 }
486 }
487
488 // �v�����g
489 if (PrinterMode) {
490 if ((r & CheckEOLOutputEOL) != 0) {
491 // ���s���o��
492 WriteToPrnFile(PrintFile_, CR,TRUE);
493 WriteToPrnFile(PrintFile_, LF,TRUE);
494 }
495
496 // u32���o��
497 if ((r & CheckEOLOutputChar) != 0) {
498 WriteToPrnFileUTF32(PrintFile_, u32, TRUE);
499 }
500 }
501 }
502
503 /**
504 * 1�L�����N�^(BYTE)�����O(or/and macro���M�o�b�t�@)���o��
505 */
506 static void OutputLogByte(BYTE b)
507 {
508 OutputLogUTF32(b);
509 }
510
511 /**
512 * ���O(or/and Macro���M�o�b�t�@)�o�����K�v��������?
513 */
514 static BOOL NeedsOutputBufs(void)
515 {
516 return FLogIsOpendText() || DDELog;
517 }
518
519 void MoveToStatusLine()
520 {
521 MainX = CursorX;
522 MainY = CursorY;
523 MainTop = CursorTop;
524 MainBottom = CursorBottom;
525 MainWrap = Wrap;
526 MainCursor = IsCaretEnabled();
527
528 DispEnableCaret(StatusCursor);
529 MoveCursor(StatusX, NumOfLines-1); // move to status line
530 CursorTop = NumOfLines-1;
531 CursorBottom = CursorTop;
532 Wrap = StatusWrap;
533 }
534
535 void HideStatusLine()
536 {
537 if (isCursorOnStatusLine)
538 MoveToMainScreen();
539 StatusX = 0;
540 StatusWrap = FALSE;
541 StatusCursor = TRUE;
542 ShowStatusLine(0); //hide
543 }
544
545 void ChangeTerminalSize(int Nx, int Ny)
546 {
547 BuffChangeTerminalSize(Nx, Ny);
548 StatusX = 0;
549 MainX = 0;
550 MainY = 0;
551 MainTop = 0;
552 MainBottom = NumOfLines-StatusLine-1;
553 }
554
555 static void SendCSIstr(char *str, int len)
556 {
557 size_t l;
558
559 if (str == NULL || len < 0)
560 return;
561
562 if (len == 0) {
563 l = strlen(str);
564 }
565 else {
566 l = len;
567 }
568
569 if (Send8BitMode)
570 CommBinaryOut(&cv,"\233", 1);
571 else
572 CommBinaryOut(&cv,"\033[", 2);
573
574 CommBinaryOut(&cv, str, l);
575 }
576
577 static void SendOSCstrW(const wchar_t *str, char TermChar)
578 {
579 size_t len;
580
581 if (str == NULL) {
582 return;
583 }
584
585 len = wcslen(str);
586
587 if (TermChar == BEL) {
588 CommBinaryOut(&cv,"\033]", 2);
589 CommTextOutW(&cv, str, len);
590 CommBinaryOut(&cv,"\007", 1);
591 }
592 else if (Send8BitMode) {
593 CommBinaryOut(&cv,"\235", 1);
594 CommTextOutW(&cv, str, len);
595 CommBinaryOut(&cv,"\234", 1);
596 }
597 else {
598 CommBinaryOut(&cv,"\033]", 2);
599 CommTextOutW(&cv, str, len);
600 CommBinaryOut(&cv,"\033\\", 2);
601 }
602
603 }
604
605 static void SendOSCstr(char *str, int len, char TermChar)
606 {
607 size_t l;
608
609 if (str == NULL || len < 0)
610 return;
611
612 if (len == 0) {
613 l = strlen(str);
614 }
615 else {
616 l = len;
617 }
618
619 if (TermChar == BEL) {
620 CommBinaryOut(&cv,"\033]", 2);
621 CommBinaryOut(&cv, str, l);
622 CommBinaryOut(&cv,"\007", 1);
623 }
624 else if (Send8BitMode) {
625 CommBinaryOut(&cv,"\235", 1);
626 CommBinaryOut(&cv, str, l);
627 CommBinaryOut(&cv,"\234", 1);
628 }
629 else {
630 CommBinaryOut(&cv,"\033]", 2);
631 CommBinaryOut(&cv, str, l);
632 CommBinaryOut(&cv,"\033\\", 2);
633 }
634
635 }
636
637 static void SendDCSstr(char *str, int len)
638 {
639 size_t l;
640
641 if (str == NULL || len < 0)
642 return;
643
644 if (len == 0) {
645 l = strlen(str);
646 }
647 else {
648 l = len;
649 }
650
651 if (Send8BitMode) {
652 CommBinaryOut(&cv,"\220", 1);
653 CommBinaryOut(&cv, str, l);
654 CommBinaryOut(&cv,"\234", 1);
655 }
656 else {
657 CommBinaryOut(&cv,"\033P", 2);
658 CommBinaryOut(&cv, str, l);
659 CommBinaryOut(&cv,"\033\\", 2);
660 }
661 }
662
663 static void BackSpace(void)
664 {
665 if (CursorX == CursorLeftM || CursorX == 0) {
666 if (CursorY > 0 && (ts.TermFlag & TF_BACKWRAP)) {
667 MoveCursor(CursorRightM, CursorY-1);
668 if (NeedsOutputBufs() && !ts.LogTypePlainText) OutputLogByte(BS);
669 }
670 }
671 else if (CursorX > 0) {
672 MoveCursor(CursorX-1, CursorY);
673 if (NeedsOutputBufs() && !ts.LogTypePlainText) OutputLogByte(BS);
674 }
675 }
676
677 static void CarriageReturn(BOOL logFlag)
678 {
679 if (!ts.EnableContinuedLineCopy || logFlag)
680 if (NeedsOutputBufs()) OutputLogByte(CR);
681
682 if (RelativeOrgMode || CursorX > CursorLeftM)
683 MoveCursor(CursorLeftM, CursorY);
684 else if (CursorX < CursorLeftM)
685 MoveCursor(0, CursorY);
686
687 CharSetFallbackFinish(charset_data);
688 }
689
690 static void LineFeed(BYTE b, BOOL logFlag)
691 {
692 /* for auto print mode */
693 if ((AutoPrintMode) &&
694 (b>=LF) && (b<=FF))
695 BuffDumpCurrentLine(PrintFile_, b);
696
697 if (!ts.EnableContinuedLineCopy || logFlag)
698 if (NeedsOutputBufs()) OutputLogByte(LF);
699
700 if (CursorY < CursorBottom)
701 MoveCursor(CursorX,CursorY+1);
702 else if (CursorY == CursorBottom) BuffScrollNLines(1);
703 else if (CursorY < NumOfLines-StatusLine-1)
704 MoveCursor(CursorX,CursorY+1);
705
706 ClearLineContinued();
707
708 if (LFMode) CarriageReturn(logFlag);
709
710 CharSetFallbackFinish(charset_data);
711 }
712
713 static void Tab(void)
714 {
715 if (Wrap && !ts.VTCompatTab) {
716 CarriageReturn(FALSE);
717 LineFeed(LF,FALSE);
718 if (ts.EnableContinuedLineCopy) {
719 SetLineContinued();
720 }
721 Wrap = FALSE;
722 }
723 CursorForwardTab(1, AutoWrapMode);
724 if (NeedsOutputBufs()) OutputLogByte(HT);
725 }
726
727 static void BuffPutChar(BYTE b, TCharAttr Attr, BOOL Insert)
728 {
729 BuffPutUnicode(b, Attr, Insert);
730 }
731
732 /**
733 * unicode(char32_t)���o�b�t�@����������
734 * ���O������������������ PutU32() ���g��
735 */
736 static void PutU32NoLog(unsigned int code)
737 {
738 int LineEnd;
739 TCharAttr CharAttrTmp;
740 BOOL dec_special;
741 int r;
742
743 LastPutCharacter = code;
744
745 dec_special = FALSE;
746 if (code <= 0xff) {
747 dec_special = CharSetIsSpecial(charset_data, code);
748 }
749
750 if (ts.Dec2Unicode) {
751 if (dec_special) {
752 // DEC������������Unicode�����}�b�s���O
753 if (ts.Dec2Unicode) {
754 // 0x5f����0x7e �� Unicode �������U��
755 // Unicode�����}�b�s���O��
756 // DEC Special Graphics(Wikipedia en)��Unicode���Q�l������
757 // https://en.wikipedia.org/wiki/DEC_Special_Graphics
758 static const char16_t dec2unicode[] = {
759 0x00a0, // 0x5f
760
761 0x25c6, 0x2592, 0x2409, 0x240c, // 0x60 -
762 0x240d, 0x240a, 0x00b0, 0x00b1,
763 0x2424, 0x240b, 0x2518, 0x2510,
764 0x250c, 0x2514, 0x253c, 0x23ba, // 0x6c - 0x6f
765
766 0x23bb, 0x2500, 0x23bc, 0x23bd, // 0x70 -
767 0x251c, 0x2524, 0x2534, 0x252c,
768 0x2502, 0x2264, 0x2265, 0x03c0,
769 0x2260, 0x00a3, 0x00b7, // 0x7c - 0x7e
770 };
771 code = code & 0x7F;
772 if (0x5f <= code && code <= 0x7e) {
773 code = dec2unicode[code - 0x5f];
774 dec_special = FALSE;
775 }
776 }
777 }
778 }
779 else {
780 // Unicode����DEC�������������}�b�s���O
781 if (dec_special == FALSE && ts.UnicodeDecSpMapping) {
782 unsigned short cset;
783 cset = UTF32ToDecSp(code);
784 if (((cset >> 8) & ts.UnicodeDecSpMapping) != 0) {
785 dec_special = TRUE;
786 code = cset & 0xff;
787 }
788 }
789 }
790
791 CharAttrTmp = CharAttr;
792 if (dec_special) {
793 CharAttrTmp.Attr |= AttrSpecial;
794 }
795 else {
796 CharAttrTmp.Attr |= CharAttr.Attr;
797 }
798
799 if (CursorX > CursorRightM)
800 LineEnd = NumOfColumns - 1;
801 else
802 LineEnd = CursorRightM;
803
804 // Wrap�����A�J�[�\������
805 if (Wrap) {
806 // ���� Wrap ����
807 if (!BuffIsCombiningCharacter(CursorX, CursorY, code)) {
808 // �����R�[�h������������������ = �J�[�\������������
809
810 // �J�[�\�����u���s�p���A�g���r���[�g������
811 TCharAttr t = BuffGetCursorCharAttr(CursorX, CursorY);
812 t.Attr |= AttrLineContinued;
813 t.AttrEx = t.Attr;
814 BuffSetCursorCharAttr(CursorX, CursorY, t);
815
816 // �s�p���A�g���r���[�g��������
817 CharAttrTmp.Attr |= AttrLineContinued;
818 CharAttrTmp.AttrEx = CharAttrTmp.Attr;
819
820 // �����s���s����
821 CarriageReturn(FALSE);
822 LineFeed(LF,FALSE);
823 }
824 }
825
826 // �o�b�t�@��������������
827 // BuffPutUnicode()���������l���������Z�������m��������������
828 // �G���[�����J�[�\�����u����������
829 CharAttrTmp.AttrEx = CharAttrTmp.Attr;
830 retry:
831 r = BuffPutUnicode(code, CharAttrTmp, InsertMode);
832 if (r == -1) {
833 // �����S�p���s���A������������
834
835 if (AutoWrapMode) {
836 // �������s
837 // �Awrap����
838 CharAttrTmp = CharAttr;
839 CharAttrTmp.Attr |= AttrLineContinued;
840 CharAttrTmp.AttrEx = CharAttrTmp.Attr | AttrPadding;
841 // AutoWrapMode
842 // ts.EnableContinuedLineCopy
843 //if (CursorX != LineEnd){
844 //&& BuffIsHalfWidthFromCode(&ts, code)) {
845
846 // full width�o���������o������������������0x20���o��
847 BuffPutUnicode(0x20, CharAttrTmp, FALSE);
848 CharAttrTmp.AttrEx = CharAttrTmp.AttrEx & ~AttrPadding;
849
850 // �����s���s����
851 CarriageReturn(FALSE);
852 LineFeed(LF,FALSE);
853 }
854 else {
855 // �s��������
856 CursorX = 0;
857 }
858
859 //CharAttrTmp.Attr &= ~AttrLineContinued;
860 goto retry;
861 }
862 else if (r == 0) {
863 // �J�[�\������������,��������,��������
864 // Wrap ������������
865 UpdateStr(); // �u���v->�u���v�����A�����������������������`������
866 } else if (r == 1) {
867 // ���p(1�Z��)
868 if (CursorX + 0 == CursorRightM || CursorX >= NumOfColumns - 1) {
869 UpdateStr();
870 Wrap = AutoWrapMode;
871 } else {
872 MoveRight();
873 Wrap = FALSE;
874 }
875 } else if (r == 2) {
876 // �S�p(2�Z��)
877 if (CursorX + 1 == CursorRightM || CursorX + 1 >= NumOfColumns - 1) {
878 MoveRight(); // �S�p���E�����J�[�\������
879 UpdateStr();
880 Wrap = AutoWrapMode;
881 } else {
882 MoveRight();
883 MoveRight();
884 Wrap = FALSE;
885 }
886 }
887 else {
888 assert(FALSE);
889 }
890 }
891
892 /**
893 * unicode(char32_t)���o�b�t�@����������
894 * ���O������������
895 *
896 * PutChar() �� UTF-32��
897 */
898 static void PutU32(unsigned int code)
899 {
900 PutU32NoLog(code);
901
902 // ���O���o��
903 OutputLogUTF32(code);
904 }
905
906 static void RepeatChar(char32_t b, int count)
907 {
908 int i;
909
910 if (b <= US || b == DEL)
911 return;
912
913 for (i = 0; i < count; i++) {
914 PutU32NoLog(b);
915 }
916 }
917
918 static void PutChar(BYTE b)
919 {
920 PutU32(b);
921 }
922
923 static void PrnParseControl(BYTE b) // printer mode
924 {
925 switch (b) {
926 case NUL:
927 return;
928 case SO:
929 if ((ts.ISO2022Flag & ISO2022_SO) && ! DirectPrn) {
930 if ((ts.Language==IdJapanese) &&
931 (ts.KanjiCode==IdJIS) &&
932 (ts.JIS7Katakana==1) &&
933 ((ts.TermFlag & TF_FIXEDJIS)!=0))
934 {
935 CharSet2022Designate(charset_data, 1, IdKatakana);
936 }
937 /* LS1 */
938 CharSet2022Invoke(charset_data, CHARSET_LS1);
939 return;
940 }
941 break;
942 case SI:
943 if ((ts.ISO2022Flag & ISO2022_SI) && ! DirectPrn) {
944 /* LS0 */
945 CharSet2022Invoke(charset_data, CHARSET_LS0);
946 return;
947 }
948 break;
949 case DC1:
950 case DC3:
951 return;
952 case ESC:
953 ICount = 0;
954 JustAfterESC = TRUE;
955 ParseMode = ModeESC;
956 WriteToPrnFile(PrintFile_, 0, TRUE); // flush prn buff
957 return;
958 case CSI:
959 if (! Accept8BitCtrl) {
960 PutChar(b); /* Disp C1 char in VT100 mode */
961 return;
962 }
963 ClearParams();
964 FirstPrm = TRUE;
965 ParseMode = ModeCSI;
966 WriteToPrnFile(PrintFile_, 0, TRUE); // flush prn buff
967 WriteToPrnFile(PrintFile_, b, FALSE);
968 return;
969 }
970 /* send the uninterpreted character to printer */
971 WriteToPrnFile(PrintFile_, b, TRUE);
972 }
973
974 static void ParseControl(BYTE b)
975 {
976 if (PrinterMode) { // printer mode
977 PrnParseControl(b);
978 return;
979 }
980
981 if (b>=0x80) { /* C1 char */
982 if (ts.Language==IdEnglish) { /* English mode */
983 if (!Accept8BitCtrl) {
984 PutChar(b); /* Disp C1 char in VT100 mode */
985 return;
986 }
987 }
988 else { /* Japanese mode */
989 if ((ts.TermFlag & TF_ACCEPT8BITCTRL)==0) {
990 return; /* ignore C1 char */
991 }
992 /* C1 chars are interpreted as C0 chars in VT100 mode */
993 if (VTlevel < 2) {
994 b = b & 0x7F;
995 }
996 }
997 }
998 switch (b) {
999 /* C0 group */
1000 case ENQ:
1001 CommBinaryOut(&cv, &(ts.Answerback[0]), ts.AnswerbackLen);
1002 break;
1003 case BEL:
1004 if (ts.Beep != IdBeepOff)
1005 RingBell(ts.Beep);
1006 break;
1007 case BS:
1008 BackSpace();
1009 break;
1010 case HT:
1011 Tab();
1012 break;
1013 case LF:
1014 if (ts.CRReceive == IdLF) {
1015 // ���M�������s�R�[�h�� LF ���������A�T�[�o���� LF ���������������������������A
1016 // CR+LF���������������������B
1017 // cf. http://www.neocom.ca/forum/viewtopic.php?t=216
1018 // (2007.1.21 yutaka)
1019 CarriageReturn(TRUE);
1020 LineFeed(b, TRUE);
1021 break;
1022 }
1023 else if (ts.CRReceive == IdAUTO) {
1024 // 9th Apr 2012: AUTO CR/LF mode (tentner)
1025 // a CR or LF will generated a CR+LF, if the next character is the opposite, it will be ignored
1026 if(PrevCharacter != CR || !PrevCRorLFGeneratedCRLF) {
1027 CarriageReturn(TRUE);
1028 LineFeed(b, TRUE);
1029 PrevCRorLFGeneratedCRLF = TRUE;
1030 }
1031 else {
1032 PrevCRorLFGeneratedCRLF = FALSE;
1033 }
1034 break;
1035 }
1036
1037 case VT:
1038 LineFeed(b, TRUE);
1039 break;
1040
1041 case FF:
1042 if ((ts.AutoWinSwitch>0) && JustAfterESC) {
1043 CommInsert1Byte(&cv, b);
1044 CommInsert1Byte(&cv, ESC);
1045 ChangeEmu = IdTEK; /* Enter TEK Mode */
1046 }
1047 else
1048 LineFeed(b, TRUE);
1049 break;
1050 case CR:
1051 if (ts.CRReceive == IdAUTO) {
1052 // 9th Apr 2012: AUTO CR/LF mode (tentner)
1053 // a CR or LF will generated a CR+LF, if the next character is the opposite, it will be ignored
1054 if(PrevCharacter != LF || !PrevCRorLFGeneratedCRLF) {
1055 CarriageReturn(TRUE);
1056 LineFeed(b, TRUE);
1057 PrevCRorLFGeneratedCRLF = TRUE;
1058 }
1059 else {
1060 PrevCRorLFGeneratedCRLF = FALSE;
1061 }
1062 }
1063 else {
1064 CarriageReturn(TRUE);
1065 if (ts.CRReceive==IdCRLF) {
1066 CommInsert1Byte(&cv, LF);
1067 }
1068 }
1069 break;
1070 case SO: /* LS1 */
1071 if (ts.ISO2022Flag & ISO2022_SO) {
1072 if ((ts.Language==IdJapanese) &&
1073 (ts.KanjiCode==IdJIS) &&
1074 (ts.JIS7Katakana==1) &&
1075 ((ts.TermFlag & TF_FIXEDJIS)!=0))
1076 {
1077 CharSet2022Designate(charset_data, 1, IdKatakana);
1078 }
1079
1080 CharSet2022Invoke(charset_data, CHARSET_LS1);
1081 }
1082 break;
1083 case SI: /* LS0 */
1084 if (ts.ISO2022Flag & ISO2022_SI) {
1085 CharSet2022Invoke(charset_data, CHARSET_LS0);
1086 }
1087 break;
1088 case DLE:
1089 if ((ts.FTFlag & FT_BPAUTO)!=0)
1090 ParseMode = ModeDLE; /* Auto B-Plus activation */
1091 break;
1092 case CAN:
1093 if ((ts.FTFlag & FT_ZAUTO)!=0)
1094 ParseMode = ModeCAN; /* Auto ZMODEM activation */
1095 // else if (ts.AutoWinSwitch>0)
1096 // ChangeEmu = IdTEK; /* Enter TEK Mode */
1097 else
1098 ParseMode = ModeFirst;
1099 break;
1100 case SUB:
1101 ParseMode = ModeFirst;
1102 break;
1103 case ESC:
1104 ICount = 0;
1105 JustAfterESC = TRUE;
1106 ParseMode = ModeESC;
1107 break;
1108 case FS:
1109 case GS:
1110 case RS:
1111 case US:
1112 if (ts.AutoWinSwitch>0) {
1113 CommInsert1Byte(&cv, b);
1114 ChangeEmu = IdTEK; /* Enter TEK Mode */
1115 }
1116 break;
1117
1118 /* C1 char */
1119 case IND:
1120 LineFeed(0, TRUE);
1121 break;
1122 case NEL:
1123 LineFeed(0, TRUE);
1124 CarriageReturn(TRUE);
1125 break;
1126 case HTS:
1127 if (ts.TabStopFlag & TABF_HTS8)
1128 SetTabStop();
1129 break;
1130 case RI:
1131 CursorUpWithScroll();
1132 break;
1133 case SS2:
1134 if (ts.ISO2022Flag & ISO2022_SS2) {
1135 CharSet2022Invoke(charset_data, CHARSET_SS2);
1136 }
1137 break;
1138 case SS3:
1139 if (ts.ISO2022Flag & ISO2022_SS3) {
1140 CharSet2022Invoke(charset_data, CHARSET_SS3);
1141 }
1142 break;
1143 case DCS:
1144 ClearParams();
1145 ESCFlag = FALSE;
1146 ParseMode = ModeDCS;
1147 break;
1148 case SOS:
1149 ESCFlag = FALSE;
1150 ParseMode = ModeIgnore;
1151 break;
1152 case CSI:
1153 ClearParams();
1154 FirstPrm = TRUE;
1155 ParseMode = ModeCSI;
1156 break;
1157 case OSC:
1158 ClearParams();
1159 ParseMode = ModeXS;
1160 break;
1161 case PM:
1162 case APC:
1163 ESCFlag = FALSE;
1164 ParseMode = ModeIgnore;
1165 break;
1166 }
1167 }
1168
1169 static void csPutU32(char32_t code, void *client_data)
1170 {
1171 (void)client_data;
1172 PutU32(code);
1173 }
1174
1175 static void csParseControl(BYTE b, void *client_data)
1176 {
1177 (void)client_data;
1178 ParseControl(b);
1179 }
1180
1181 static CharSetData *CharSetInitTerm(void)
1182 {
1183 CharSetOp op;
1184 op.PutU32 = csPutU32;
1185 op.ParseControl = csParseControl;
1186 return CharSetInit(&op, NULL);
1187 }
1188
1189 static void AnswerTerminalType(void)
1190 {
1191 char Tmp[50];
1192
1193 if (ts.TerminalID<IdVT320 || !Send8BitMode)
1194 strncpy_s(Tmp, sizeof(Tmp),"\033[?", _TRUNCATE);
1195 else
1196 strncpy_s(Tmp, sizeof(Tmp),"\233?", _TRUNCATE);
1197
1198 switch (ts.TerminalID) {
1199 case IdVT100:
1200 strncat_s(Tmp,sizeof(Tmp),"1;2",_TRUNCATE);
1201 break;
1202 case IdVT100J:
1203 strncat_s(Tmp,sizeof(Tmp),"5;2",_TRUNCATE);
1204 break;
1205 case IdVT101:
1206 strncat_s(Tmp,sizeof(Tmp),"1;0",_TRUNCATE);
1207 break;
1208 case IdVT102:
1209 strncat_s(Tmp,sizeof(Tmp),"6",_TRUNCATE);
1210 break;
1211 case IdVT102J:
1212 strncat_s(Tmp,sizeof(Tmp),"15",_TRUNCATE);
1213 break;
1214 case IdVT220J:
1215 strncat_s(Tmp,sizeof(Tmp),"62;1;2;5;6;7;8",_TRUNCATE);
1216 break;
1217 case IdVT282:
1218 strncat_s(Tmp,sizeof(Tmp),"62;1;2;4;5;6;7;8;10;11",_TRUNCATE);
1219 break;
1220 case IdVT320:
1221 strncat_s(Tmp,sizeof(Tmp),"63;1;2;6;7;8",_TRUNCATE);
1222 break;
1223 case IdVT382:
1224 strncat_s(Tmp,sizeof(Tmp),"63;1;2;4;5;6;7;8;10;15",_TRUNCATE);
1225 break;
1226 case IdVT420:
1227 strncat_s(Tmp,sizeof(Tmp),"64;1;2;7;8;9;15;18;21",_TRUNCATE);
1228 break;
1229 case IdVT520:
1230 strncat_s(Tmp,sizeof(Tmp),"65;1;2;7;8;9;12;18;19;21;23;24;42;44;45;46",_TRUNCATE);
1231 break;
1232 case IdVT525:
1233 strncat_s(Tmp,sizeof(Tmp),"65;1;2;7;9;12;18;19;21;22;23;24;42;44;45;46",_TRUNCATE);
1234 break;
1235 }
1236 strncat_s(Tmp,sizeof(Tmp),"c",_TRUNCATE);
1237
1238 CommBinaryOut(&cv,Tmp,strlen(Tmp)); /* Report terminal ID */
1239 }
1240
1241 static void ESCSpace(BYTE b)
1242 {
1243 switch (b) {
1244 case 'F': // S7C1T
1245 Send8BitMode = FALSE;
1246 break;
1247 case 'G': // S8C1T
1248 if (VTlevel >= 2) {
1249 Send8BitMode = TRUE;
1250 }
1251 break;
1252 }
1253 }
1254
1255 static void ESCSharp(BYTE b)
1256 {
1257 switch (b) {
1258 case '8': /* Fill screen with "E" (DECALN) */
1259 BuffUpdateScroll();
1260 BuffFillWithE();
1261 CursorTop = 0;
1262 CursorBottom = NumOfLines-1-StatusLine;
1263 CursorLeftM = 0;
1264 CursorRightM = NumOfColumns - 1;
1265 MoveCursor(0, 0);
1266 ParseMode = ModeFirst;
1267 break;
1268 }
1269 }
1270
1271 /* select double byte code set */
1272 static void ESCDBCSSelect(BYTE b)
1273 {
1274 int Dist;
1275
1276 if (ts.Language!=IdJapanese) return;
1277
1278 switch (ICount) {
1279 case 1:
1280 // - ESC $ @ (01/11 02/04 04/00) (0x1b 0x24 0x40)
1281 // - G0 <- ��JIS����
1282 // - ��JIS���� = JIS X 0208-1978 (JIS C 6226-1978)
1283 // - ESC $ B (01/11 02/04 04/02) (0x1b 0x24 0x42)
1284 // - G0 <- �VJIS����
1285 // - �VJIS���� = JIS X 0208-1990
1286 if ((b=='@') || (b=='B'))
1287 {
1288 /* Kanji -> G0 */
1289 CharSet2022Designate(charset_data, 0, IdKanji);
1290 if ((ts.TermFlag & TF_AUTOINVOKE)!=0) {
1291 /* G0->GL */
1292 CharSet2022Invoke(charset_data, CHARSET_LS0);
1293 }
1294 }
1295 break;
1296 case 2:
1297 // - ESC $ ( @ (01/11 02/04 02/08 04/00) (0x1b 0x24 0x28 0x40)
1298 // - ESC $ ) @ (01/11 02/04 02/09 04/00) (0x1b 0x24 0x29 0x40)
1299 // - ESC $ * @ (01/11 02/04 02/10 04/00) (0x1b 0x24 0x2a 0x40)
1300 // - ESC $ + @ (01/11 02/04 02/11 04/00) (0x1b 0x24 0x2b 0x40)
1301 // - G0..G3 <- ��JIS����
1302 // - ESC $ ( B (01/11 02/04 02/08 04/02) (0x1b 0x24 0x28 0x42)
1303 // - ESC $ ) B (01/11 02/04 02/09 04/02) (0x1b 0x24 0x29 0x42)
1304 // - ESC $ * B (01/11 02/04 02/10 04/02) (0x1b 0x24 0x2a 0x42)
1305 // - ESC $ + B (01/11 02/04 02/11 04/02) (0x1b 0x24 0x2b 0x42)
1306 // - G0..G3 <- �VJIS����
1307 //
1308 /* Second intermediate char must be
1309 '(' or ')' or '*' or '+'. */
1310 Dist = (IntChar[2]-'(') & 3; /* G0 - G3 */
1311 if ((b=='1') || (b=='3') ||
1312 (b=='@') || (b=='B'))
1313 {
1314 /* Kanji -> G0-3 */
1315 CharSet2022Designate(charset_data, Dist, IdKanji);
1316 if (((ts.TermFlag & TF_AUTOINVOKE)!=0) && (Dist==0)) {
1317 /* G0->GL */
1318 CharSet2022Invoke(charset_data, CHARSET_LS0);
1319 }
1320 }
1321 break;
1322 }
1323 }
1324
1325 static void ESCSelectCode(BYTE b)
1326 {
1327 switch (b) {
1328 case '0':
1329 if (ts.AutoWinSwitch>0)
1330 ChangeEmu = IdTEK; /* enter TEK mode */
1331 break;
1332 }
1333 }
1334
1335 /* select single byte code set */
1336 static void ESCSBCSSelect(BYTE b)
1337 {
1338 int Dist;
1339
1340 /* Intermediate char must be '(' or ')' or '*' or '+'. */
1341 Dist = (IntChar[1]-'(') & 3; /* G0 - G3 */
1342
1343 switch (b) {
1344 case '0':
1345 CharSet2022Designate(charset_data, Dist, IdSpecial);
1346 break;
1347 case '<':
1348 case '>':
1349 case 'A':
1350 case 'B':
1351 case 'H':
1352 CharSet2022Designate(charset_data, Dist, IdASCII);
1353 break;
1354 case 'I':
1355 if (ts.Language==IdJapanese)
1356 CharSet2022Designate(charset_data, Dist, IdKatakana);
1357 break;
1358 case 'J':
1359 CharSet2022Designate(charset_data, Dist, IdASCII);
1360 break;
1361 }
1362
1363 if (((ts.TermFlag & TF_AUTOINVOKE)!=0) && (Dist==0)) {
1364 /* G0->GL */
1365 CharSet2022Invoke(charset_data, CHARSET_LS0);
1366 }
1367 }
1368
1369 static void PrnParseEscape(BYTE b) // printer mode
1370 {
1371 int i;
1372
1373 ParseMode = ModeFirst;
1374 switch (ICount) {
1375 /* no intermediate char */
1376 case 0:
1377 switch (b) {
1378 case '[': /* CSI */
1379 ClearParams();
1380 FirstPrm = TRUE;
1381 WriteToPrnFile(PrintFile_, ESC,FALSE);
1382 WriteToPrnFile(PrintFile_, '[',FALSE);
1383 ParseMode = ModeCSI;
1384 return;
1385 } /* end of case Icount=0 */
1386 break;
1387 /* one intermediate char */
1388 case 1:
1389 switch (IntChar[1]) {
1390 case '$':
1391 if (! DirectPrn) {
1392 ESCDBCSSelect(b);
1393 return;
1394 }
1395 break;
1396 case '(':
1397 case ')':
1398 case '*':
1399 case '+':
1400 if (! DirectPrn) {
1401 ESCSBCSSelect(b);
1402 return;
1403 }
1404 break;
1405 }
1406 break;
1407 /* two intermediate char */
1408 case 2:
1409 if ((! DirectPrn) &&
1410 (IntChar[1]=='$') &&
1411 ('('<=IntChar[2]) &&
1412 (IntChar[2]<='+'))
1413 {
1414 ESCDBCSSelect(b);
1415 return;
1416 }
1417 break;
1418 }
1419 // send the uninterpreted sequence to printer
1420 WriteToPrnFile(PrintFile_, ESC,FALSE);
1421 for (i=1; i<=ICount; i++)
1422 WriteToPrnFile(PrintFile_, IntChar[i],FALSE);
1423 WriteToPrnFile(PrintFile_, b,TRUE);
1424 }
1425
1426 static void ParseEscape(BYTE b) /* b is the final char */
1427 {
1428 if (PrinterMode) { // printer mode
1429 PrnParseEscape(b);
1430 return;
1431 }
1432
1433 switch (ICount) {
1434 case 0: /* no intermediate char */
1435 switch (b) {
1436 case '6': // DECBI
1437 if (CursorY >= CursorTop && CursorY <= CursorBottom &&
1438 CursorX >= CursorLeftM && CursorX <= CursorRightM) {
1439 if (CursorX == CursorLeftM)
1440 BuffScrollRight(1);
1441 else
1442 MoveCursor(CursorX-1, CursorY);
1443 }
1444 break;
1445 case '7': SaveCursor(); break;
1446 case '8': RestoreCursor(); break;
1447 case '9': // DECFI
1448 if (CursorY >= CursorTop && CursorY <= CursorBottom &&
1449 CursorX >= CursorLeftM && CursorX <= CursorRightM) {
1450 if (CursorX == CursorRightM)
1451 BuffScrollLeft(1);
1452 else
1453 MoveCursor(CursorX+1, CursorY);
1454 }
1455 break;
1456 case '=': AppliKeyMode = TRUE; break;
1457 case '>': AppliKeyMode = FALSE; break;
1458 case 'D': /* IND */
1459 LineFeed(0,TRUE);
1460 break;
1461 case 'E': /* NEL */
1462 MoveCursor(0,CursorY);
1463 LineFeed(0,TRUE);
1464 break;
1465 case 'H': /* HTS */
1466 if (ts.TabStopFlag & TABF_HTS7)
1467 SetTabStop();
1468 break;
1469 case 'M': /* RI */
1470 CursorUpWithScroll();
1471 break;
1472 case 'N': /* SS2 */
1473 if (ts.ISO2022Flag & ISO2022_SS2) {
1474 CharSet2022Invoke(charset_data, CHARSET_SS2);
1475 }
1476 break;
1477 case 'O': /* SS3 */
1478 if (ts.ISO2022Flag & ISO2022_SS3) {
1479 CharSet2022Invoke(charset_data, CHARSET_SS3);
1480 }
1481 break;
1482 case 'P': /* DCS */
1483 ClearParams();
1484 ESCFlag = FALSE;
1485 ParseMode = ModeDCS;
1486 return;
1487 case 'X': /* SOS */
1488 case '^': /* APC */
1489 case '_': /* PM */
1490 ESCFlag = FALSE;
1491 ParseMode = ModeIgnore;
1492 return;
1493 case 'Z': /* DECID */
1494 AnswerTerminalType();
1495 break;
1496 case '[': /* CSI */
1497 ClearParams();
1498 FirstPrm = TRUE;
1499 ParseMode = ModeCSI;
1500 return;
1501 case '\\': break; /* ST */
1502 case ']': /* XTERM sequence (OSC) */
1503 ClearParams();
1504 ParseMode = ModeXS;
1505 return;
1506 case 'c': /* Hardware reset */
1507 HideStatusLine();
1508 ResetTerminal();
1509 ClearUserKey();
1510 ClearBuffer();
1511 if (ts.PortType==IdSerial) // reset serial port
1512 CommResetSerial(&ts, &cv, TRUE);
1513 break;
1514 case 'g': /* Visual Bell (screen original?) */
1515 RingBell(IdBeepVisual);
1516 break;
1517 case 'n': /* LS2 */
1518 if (ts.ISO2022Flag & ISO2022_LS2) {
1519 CharSet2022Invoke(charset_data, CHARSET_LS2);
1520 }
1521 break;
1522 case 'o': /* LS3 */
1523 if (ts.ISO2022Flag & ISO2022_LS3) {
1524 CharSet2022Invoke(charset_data, CHARSET_LS3);
1525 }
1526 break;
1527 case '|': /* LS3R */
1528 if (ts.ISO2022Flag & ISO2022_LS3R) {
1529 CharSet2022Invoke(charset_data, CHARSET_LS3R);
1530 }
1531 break;
1532 case '}': /* LS2R */
1533 if (ts.ISO2022Flag & ISO2022_LS2R) {
1534 CharSet2022Invoke(charset_data, CHARSET_LS2R);
1535 }
1536 break;
1537 case '~': /* LS1R */
1538 if (ts.ISO2022Flag & ISO2022_LS1R) {
1539 CharSet2022Invoke(charset_data, CHARSET_LS1R);
1540 }
1541 break;
1542 }
1543 break;
1544 /* end of case Icount=0 */
1545
1546 case 1: /* one intermediate char */
1547 switch (IntChar[1]) {
1548 case ' ': ESCSpace(b); break;
1549 case '#': ESCSharp(b); break;
1550 case '$': ESCDBCSSelect(b); break;
1551 case '%': break;
1552 case '(':
1553 case ')':
1554 case '*':
1555 case '+':
1556 ESCSBCSSelect(b);
1557 break;
1558 }
1559 break;
1560
1561 case 2: /* two intermediate char */
1562 if ((IntChar[1]=='$') && ('('<=IntChar[2]) && (IntChar[2]<='+'))
1563 ESCDBCSSelect(b);
1564 else if ((IntChar[1]=='%') && (IntChar[2]=='!'))
1565 ESCSelectCode(b);
1566 break;
1567 }
1568 ParseMode = ModeFirst;
1569 }
1570
1571 static void EscapeSequence(BYTE b)
1572 {
1573 if (b<=US)
1574 ParseControl(b);
1575 else if ((b>=0x20) && (b<=0x2F)) {
1576 // TODO: ICount �� IntCharMax ���B�������A������ IntChar ���u����������������?
1577 if (ICount<IntCharMax)
1578 ICount++;
1579 IntChar[ICount] = b;
1580 }
1581 else if ((b>=0x30) && (b<=0x7E))
1582 ParseEscape(b);
1583 else if ((b>=0x80) && (b<=0x9F))
1584 ParseControl(b);
1585 else if (b>=0xA0) {
1586 ParseMode=ModeFirst;
1587 ParseFirst(charset_data, b);
1588 }
1589
1590 JustAfterESC = FALSE;
1591 }
1592
1593 #define CheckParamVal(p,m) \
1594 if ((p) == 0) { \
1595 (p) = 1; \
1596 } \
1597 else if ((p) > (m) || p < 0) { \
1598 (p) = (m); \
1599 }
1600
1601 #define CheckParamValMax(p,m) \
1602 if ((p) > (m) || p <= 0) { \
1603 (p) = (m); \
1604 }
1605
1606 #define RequiredParams(n) \
1607 if ((n) > 1) { \
1608 while (NParam < n) { \
1609 NParam++; \
1610 Param[NParam] = 0; \
1611 NSParam[NParam] = 0; \
1612 } \
1613 }
1614
1615 // ICH
1616 static void CSInsertCharacter(void)
1617 {
1618 // Insert space characters at cursor
1619 CheckParamVal(Param[1], NumOfColumns);
1620
1621 BuffUpdateScroll();
1622 BuffInsertSpace(Param[1]);
1623 }
1624
1625 static void CSCursorUp(BOOL AffectMargin) // CUU / VPB
1626 {
1627 int topMargin, NewY;
1628
1629 CheckParamVal(Param[1], CursorY);
1630
1631 if (AffectMargin && CursorY >= CursorTop)
1632 topMargin = CursorTop;
1633 else
1634 topMargin = 0;
1635
1636 NewY = CursorY - Param[1];
1637 if (NewY < topMargin)
1638 NewY = topMargin;
1639
1640 MoveCursor(CursorX, NewY);
1641 }
1642
1643 static void CSCursorUp1() // CPL
1644 {
1645 MoveCursor(CursorLeftM, CursorY);
1646 CSCursorUp(TRUE);
1647 }
1648
1649 static void CSCursorDown(BOOL AffectMargin) // CUD / VPR
1650 {
1651 int bottomMargin, NewY;
1652
1653 if (AffectMargin && CursorY <= CursorBottom)
1654 bottomMargin = CursorBottom;
1655 else
1656 bottomMargin = NumOfLines-StatusLine-1;
1657
1658 CheckParamVal(Param[1], bottomMargin);
1659
1660 NewY = CursorY + Param[1];
1661 if (NewY > bottomMargin)
1662 NewY = bottomMargin;
1663
1664 MoveCursor(CursorX, NewY);
1665 }
1666
1667 static void CSCursorDown1() // CNL
1668 {
1669 MoveCursor(CursorLeftM, CursorY);
1670 CSCursorDown(TRUE);
1671 }
1672
1673 static void CSScreenErase()
1674 {
1675 BuffUpdateScroll();
1676 switch (Param[1]) {
1677 case 0:
1678 // <ESC>[H(Cursor in left upper corner)�������J�[�\�������������w�������������A
1679 // <ESC>[J��<ESC>[2J�����������������A�����������A���s�o�b�t�@���X�N���[���A�E�g
1680 // �����������������B(2005.5.29 yutaka)
1681 // �R���t�B�O���[�V�������������������������������B(2008.5.3 yutaka)
1682 if (ts.ScrollWindowClearScreen &&
1683 (CursorX == 0 && CursorY == 0)) {
1684 // Erase screen (scroll out)
1685 BuffClearScreen();
1686 UpdateWindow(HVTWin);
1687
1688 } else {
1689 // Erase characters from cursor to the end of screen
1690 BuffEraseCurToEnd();
1691 }
1692 break;
1693
1694 case 1:
1695 // Erase characters from home to cursor
1696 BuffEraseHomeToCur();
1697 break;
1698
1699 case 2:
1700 // Erase screen (scroll out)
1701 BuffClearScreen();
1702 UpdateWindow(HVTWin);
1703 if (ClearThenHome && !isCursorOnStatusLine) {
1704 if (RelativeOrgMode) {
1705 MoveCursor(0, 0);
1706 }
1707 else {
1708 MoveCursor(CursorLeftM, CursorTop);
1709 }
1710 }
1711 break;
1712
1713 case 3:
1714 if (ts.TermFlag & TF_REMOTECLEARSBUFF) {
1715 ClearBuffer();
1716 }
1717 break;
1718 }
1719 }
1720
1721 static void CSQSelScreenErase()
1722 {
1723 BuffUpdateScroll();
1724 switch (Param[1]) {
1725 case 0:
1726 // Erase characters from cursor to end
1727 BuffSelectedEraseCurToEnd();
1728 break;
1729
1730 case 1:
1731 // Erase characters from home to cursor
1732 BuffSelectedEraseHomeToCur();
1733 break;
1734
1735 case 2:
1736 // Erase entire screen
1737 BuffSelectedEraseScreen();
1738 break;
1739
1740 case 3:
1741 if (ts.TermFlag & TF_REMOTECLEARSBUFF) {
1742 ClearBuffer();
1743 }
1744 break;
1745 }
1746 }
1747
1748 static void CSInsertLine()
1749 {
1750 // Insert lines at current position
1751 int Count, YEnd;
1752
1753 if (CursorY < CursorTop || CursorY > CursorBottom) {
1754 return;
1755 }
1756
1757 CheckParamVal(Param[1], NumOfLines);
1758
1759 Count = Param[1];
1760
1761 YEnd = CursorBottom;
1762 if (CursorY > YEnd)
1763 YEnd = NumOfLines-1-StatusLine;
1764
1765 if (Count > YEnd+1 - CursorY)
1766 Count = YEnd+1 - CursorY;
1767
1768 BuffInsertLines(Count,YEnd);
1769 }
1770
1771 static void CSLineErase()
1772 {
1773 BuffUpdateScroll();
1774 switch (Param[1]) {
1775 case 0: /* erase char from cursor to end of line */
1776 BuffEraseCharsInLine(CursorX,NumOfColumns-CursorX);
1777 break;
1778
1779 case 1: /* erase char from start of line to cursor */
1780 BuffEraseCharsInLine(0,CursorX+1);
1781 break;
1782
1783 case 2: /* erase entire line */
1784 BuffEraseCharsInLine(0,NumOfColumns);
1785 break;
1786 }
1787 }
1788
1789 static void CSQSelLineErase(void)
1790 {
1791 BuffUpdateScroll();
1792 switch (Param[1]) {
1793 case 0: /* erase char from cursor to end of line */
1794 BuffSelectedEraseCharsInLine(CursorX,NumOfColumns-CursorX);
1795 break;
1796
1797 case 1: /* erase char from start of line to cursor */
1798 BuffSelectedEraseCharsInLine(0,CursorX+1);
1799 break;
1800
1801 case 2: /* erase entire line */
1802 BuffSelectedEraseCharsInLine(0,NumOfColumns);
1803 break;
1804 }
1805 }
1806
1807 static void CSDeleteNLines()
1808 // Delete lines from current line
1809 {
1810 int Count, YEnd;
1811
1812 if (CursorY < CursorTop || CursorY > CursorBottom) {
1813 return;
1814 }
1815
1816 CheckParamVal(Param[1], NumOfLines);
1817 Count = Param[1];
1818
1819 YEnd = CursorBottom;
1820 if (CursorY > YEnd)
1821 YEnd = NumOfLines-1-StatusLine;
1822
1823 if (Count > YEnd+1-CursorY)
1824 Count = YEnd+1-CursorY;
1825
1826 BuffDeleteLines(Count,YEnd);
1827 }
1828
1829 // DCH
1830 static void CSDeleteCharacter(void)
1831 {
1832 // Delete characters in current line from cursor
1833 CheckParamVal(Param[1], NumOfColumns);
1834
1835 BuffUpdateScroll();
1836 BuffDeleteChars(Param[1]);
1837 }
1838
1839 // ECH
1840 static void CSEraseCharacter(void)
1841 {
1842 CheckParamVal(Param[1], NumOfColumns);
1843
1844 BuffUpdateScroll();
1845 BuffEraseChars(Param[1]);
1846 }
1847
1848 static void CSRepeatCharacter()
1849 {
1850 CheckParamVal(Param[1], NumOfColumns * NumOfLines);
1851
1852 BuffUpdateScroll();
1853 RepeatChar(LastPutCharacter, Param[1]);
1854 LastPutCharacter = 0;
1855 }
1856
1857 static void CSScrollUp()
1858 {
1859 // TODO: �X�N���[���������l���[���s�����������������v����
1860 CheckParamVal(Param[1], INT_MAX);
1861
1862 BuffUpdateScroll();
1863 BuffRegionScrollUpNLines(Param[1]);
1864 }
1865
1866 static void CSScrollDown()
1867 {
1868 CheckParamVal(Param[1], NumOfLines);
1869
1870 BuffUpdateScroll();
1871 BuffRegionScrollDownNLines(Param[1]);
1872 }
1873
1874 static void CSForwardTab()
1875 {
1876 CheckParamVal(Param[1], NumOfColumns);
1877 CursorForwardTab(Param[1], AutoWrapMode);
1878 }
1879
1880 static void CSBackwardTab()
1881 {
1882 CheckParamVal(Param[1], NumOfColumns);
1883 CursorBackwardTab(Param[1]);
1884 }
1885
1886 static void CSMoveToColumnN() // CHA / HPA
1887 {
1888 CheckParamVal(Param[1], NumOfColumns);
1889
1890 Param[1]--;
1891
1892 if (RelativeOrgMode) {
1893 if (CursorLeftM + Param[1] > CursorRightM )
1894 MoveCursor(CursorRightM, CursorY);
1895 else
1896 MoveCursor(CursorLeftM + Param[1], CursorY);
1897 }
1898 else {
1899 MoveCursor(Param[1], CursorY);
1900 }
1901 }
1902
1903 static void CSCursorRight(BOOL AffectMargin) // CUF / HPR
1904 {
1905 int NewX, rightMargin;
1906
1907 CheckParamVal(Param[1], NumOfColumns);
1908
1909 if (AffectMargin && CursorX <= CursorRightM) {
1910 rightMargin = CursorRightM;
1911 }
1912 else {
1913 rightMargin = NumOfColumns-1;
1914 }
1915
1916 NewX = CursorX + Param[1];
1917 if (NewX > rightMargin)
1918 NewX = rightMargin;
1919
1920 MoveCursor(NewX, CursorY);
1921 }
1922
1923 static void CSCursorLeft(BOOL AffectMargin) // CUB / HPB
1924 {
1925 int NewX, leftMargin;
1926
1927 CheckParamVal(Param[1], NumOfColumns);
1928
1929 if (AffectMargin && CursorX >= CursorLeftM) {
1930 leftMargin = CursorLeftM;
1931 }
1932 else {
1933 leftMargin = 0;
1934 }
1935
1936 NewX = CursorX - Param[1];
1937 if (NewX < leftMargin) {
1938 NewX = leftMargin;
1939 }
1940
1941 MoveCursor(NewX, CursorY);
1942 }
1943
1944 static void CSMoveToLineN() // VPA
1945 {
1946 CheckParamVal(Param[1], NumOfLines-StatusLine);
1947
1948 if (RelativeOrgMode) {
1949 if (CursorTop+Param[1]-1 > CursorBottom)
1950 MoveCursor(CursorX,CursorBottom);
1951 else
1952 MoveCursor(CursorX,CursorTop+Param[1]-1);
1953 }
1954 else {
1955 if (Param[1] > NumOfLines-StatusLine)
1956 MoveCursor(CursorX,NumOfLines-1-StatusLine);
1957 else
1958 MoveCursor(CursorX,Param[1]-1);
1959 }
1960 CharSetFallbackFinish(charset_data);
1961 }
1962
1963 static void CSMoveToXY() // CUP / HVP
1964 {
1965 int NewX, NewY;
1966
1967 RequiredParams(2);
1968 CheckParamVal(Param[1], NumOfLines-StatusLine);
1969 CheckParamVal(Param[2], NumOfColumns);
1970
1971 NewY = Param[1] - 1;
1972 NewX = Param[2] - 1;
1973
1974 if (isCursorOnStatusLine)
1975 NewY = CursorY;
1976 else if (RelativeOrgMode) {
1977 NewX += CursorLeftM;
1978 if (NewX > CursorRightM)
1979 NewX = CursorRightM;
1980
1981 NewY += CursorTop;
1982 if (NewY > CursorBottom)
1983 NewY = CursorBottom;
1984 }
1985 else {
1986 if (NewY > NumOfLines-1-StatusLine)
1987 NewY = NumOfLines-1-StatusLine;
1988 }
1989
1990 MoveCursor(NewX, NewY);
1991 CharSetFallbackFinish(charset_data);
1992 }
1993
1994 static void CSDeleteTabStop()
1995 {
1996 ClearTabStop(Param[1]);
1997 }
1998
1999 static void CS_h_Mode() // SM
2000 {
2001 switch (Param[1]) {
2002 case 2: // KAM
2003 KeybEnabled = FALSE; break;
2004 case 4: // IRM
2005 InsertMode = TRUE; break;
2006 case 12: // SRM
2007 ts.LocalEcho = 0;
2008 if (cv.Ready && cv.TelFlag && (ts.TelEcho>0))
2009 TelChangeEcho();
2010 break;
2011 case 20: // LF/NL
2012 LFMode = TRUE;
2013 ts.CRSend = IdCRLF;
2014 cv.CRSend = IdCRLF;
2015 break;
2016 case 33: // WYSTCURM
2017 if (ts.WindowFlag & WF_CURSORCHANGE) {
2018 ts.NonblinkingCursor = TRUE;
2019 ChangeCaret();
2020 }
2021 break;
2022 case 34: // WYULCURM
2023 if (ts.WindowFlag & WF_CURSORCHANGE) {
2024 ts.CursorShape = IdHCur;
2025 ChangeCaret();
2026 }
2027 break;
2028 }
2029 }
2030
2031 static void CS_i_Mode() // MC
2032 {
2033 switch (Param[1]) {
2034 /* print screen */
2035 // PrintEX -- TRUE: print screen
2036 // FALSE: scroll region
2037 case 0:
2038 if (ts.TermFlag&TF_PRINTERCTRL) {
2039 BuffPrint(! PrintEX);
2040 }
2041 break;
2042 /* printer controller mode off */
2043 case 4: break; /* See PrnParseCS() */
2044 /* printer controller mode on */
2045 case 5:
2046 if (ts.TermFlag&TF_PRINTERCTRL) {
2047 if (! AutoPrintMode)
2048 PrintFile_ = OpenPrnFile();
2049 DirectPrn = (ts.PrnDev[0]!=0);
2050 PrinterMode = TRUE;
2051 }
2052 break;
2053 }
2054 }
2055
2056 static void CS_l_Mode() // RM
2057 {
2058 switch (Param[1]) {
2059 case 2: // KAM
2060 KeybEnabled = TRUE; break;
2061 case 4: // IRM
2062 InsertMode = FALSE; break;
2063 case 12: // SRM
2064 ts.LocalEcho = 1;
2065 if (cv.Ready && cv.TelFlag && (ts.TelEcho>0))
2066 TelChangeEcho();
2067 break;
2068 case 20: // LF/NL
2069 LFMode = FALSE;
2070 ts.CRSend = IdCR;
2071 cv.CRSend = IdCR;
2072 break;
2073 case 33: // WYSTCURM
2074 if (ts.WindowFlag & WF_CURSORCHANGE) {
2075 ts.NonblinkingCursor = FALSE;
2076 ChangeCaret();
2077 }
2078 break;
2079 case 34: // WYULCURM
2080 if (ts.WindowFlag & WF_CURSORCHANGE) {
2081 ts.CursorShape = IdBlkCur;
2082 ChangeCaret();
2083 }
2084 break;
2085 }
2086 }
2087
2088 static void CS_n_Mode() // DSR
2089 {
2090 char Report[16];
2091 int X, Y, len;
2092
2093 switch (Param[1]) {
2094 case 5:
2095 /* Device Status Report -> Ready */
2096 SendCSIstr("0n", 0);
2097 break;
2098 case 6:
2099 /* Cursor Position Report */
2100 if (isCursorOnStatusLine) {
2101 X = CursorX + 1;
2102 Y = 1;
2103 }
2104 else if (RelativeOrgMode) {
2105 X = CursorX - CursorLeftM + 1;
2106 Y = CursorY - CursorTop + 1;
2107 }
2108 else {
2109 X = CursorX + 1;
2110 Y = CursorY+1;
2111 }
2112 len = _snprintf_s_l(Report, sizeof(Report), _TRUNCATE, "%u;%uR", CLocale, Y, X);
2113 SendCSIstr(Report, len);
2114 break;
2115 }
2116 }
2117
2118 static void ParseSGRParams(PCharAttr attr, PCharAttr mask, int start)
2119 {
2120 int i, j, P, r, g, b, color;
2121 TCharAttr dummy;
2122
2123 if (mask == NULL) {
2124 mask = &dummy;
2125 }
2126
2127 for (i=start ; i<=NParam ; i++) {
2128 P = Param[i];
2129 switch (P) {
2130 case 0: /* Clear all */
2131 attr->Attr = DefCharAttr.Attr;
2132 attr->Attr2 = DefCharAttr.Attr2 | (attr->Attr2&Attr2Protect);
2133 attr->AttrEx = attr->Attr;
2134 attr->Fore = DefCharAttr.Fore;
2135 attr->Back = DefCharAttr.Back;
2136 mask->Attr = AttrSgrMask;
2137 mask->Attr2 = Attr2ColorMask;
2138 break;
2139
2140 case 1: /* Bold */
2141 attr->Attr |= AttrBold;
2142 mask->Attr |= AttrBold;
2143 break;
2144
2145 case 4: /* Under line */
2146 attr->Attr |= AttrUnder;
2147 mask->Attr |= AttrUnder;
2148 break;
2149
2150 case 5: /* Blink */
2151 attr->Attr |= AttrBlink;
2152 mask->Attr |= AttrBlink;
2153 break;
2154
2155 case 7: /* Reverse */
2156 attr->Attr |= AttrReverse;
2157 mask->Attr |= AttrReverse;
2158 break;
2159
2160 case 22: /* Bold off */
2161 attr->Attr &= ~ AttrBold;
2162 mask->Attr |= AttrBold;
2163 break;
2164
2165 case 24: /* Under line off */
2166 attr->Attr &= ~ AttrUnder;
2167 mask->Attr |= AttrUnder;
2168 break;
2169
2170 case 25: /* Blink off */
2171 attr->Attr &= ~ AttrBlink;
2172 mask->Attr |= AttrBlink;
2173 break;
2174
2175 case 27: /* Reverse off */
2176 attr->Attr &= ~ AttrReverse;
2177 mask->Attr |= AttrReverse;
2178 break;
2179
2180 case 30:
2181 case 31:
2182 case 32:
2183 case 33:
2184 case 34:
2185 case 35:
2186 case 36:
2187 case 37: /* text color */
2188 attr->Attr2 |= Attr2Fore;
2189 mask->Attr2 |= Attr2Fore;
2190 attr->Fore = P - 30;
2191 break;
2192
2193 case 38: /* text color (256color mode) */
2194 if (ts.ColorFlag & CF_XTERM256) {
2195 /*
2196 * Change foreground color. accept following formats.
2197 *
2198 * 38 ; 2 ; r ; g ; b
2199 * 38 ; 2 : r : g : b
2200 * 38 : 2 : r : g : b
2201 * 38 ; 5 ; idx
2202 * 38 ; 5 : idx
2203 * 38 : 5 : idx
2204 *
2205 */
2206 color = -1;
2207 j = 0;
2208 if (NSParam[i] > 0) {
2209 P = SubParam[i][1];
2210 j++;
2211 }
2212 else if (i < NParam) {
2213 P = Param[i+1];
2214 if (P == 2 || P == 5) {
2215 i++;
2216 }
2217 }
2218 switch (P) {
2219 case 2:
2220 r = g = b = 0;
2221 if (NSParam[i] > 0) {
2222 if (j < NSParam[i]) {
2223 r = SubParam[i][++j];
2224 if (j < NSParam[i]) {
2225 g = SubParam[i][++j];
2226 }
2227 if (j < NSParam[i]) {
2228 b = SubParam[i][++j];
2229 }
2230 color = DispFindClosestColor(r, g, b);
2231 }
2232 }
2233 else if (i < NParam && NSParam[i+1] > 0) {
2234 r = Param[++i];
2235 g = SubParam[i][1];
2236 if (NSParam[i] > 1) {
2237 b = SubParam[i][2];
2238 }
2239 color = DispFindClosestColor(r, g, b);
2240 }
2241 else if (i+2 < NParam) {
2242 r = Param[++i];
2243 g = Param[++i];
2244 b = Param[++i];
2245 color = DispFindClosestColor(r, g, b);
2246 }
2247 break;
2248 case 5:
2249 if (NSParam[i] > 0) {
2250 if (j < NSParam[i]) {
2251 color = SubParam[i][++j];
2252 }
2253 }
2254 else if (i < NParam) {
2255 color = Param[++i];
2256 }
2257 break;
2258 }
2259 if (color >= 0 && color < 256) {
2260 attr->Attr2 |= Attr2Fore;
2261 mask->Attr2 |= Attr2Fore;
2262 attr->Fore = color;
2263 }
2264 }
2265 break;
2266
2267 case 39: /* Reset text color */
2268 attr->Attr2 &= ~ Attr2Fore;
2269 mask->Attr2 |= Attr2Fore;
2270 attr->Fore = AttrDefaultFG;
2271 break;
2272
2273 case 40:
2274 case 41:
2275 case 42:
2276 case 43:
2277 case 44:
2278 case 45:
2279 case 46:
2280 case 47: /* Back color */
2281 attr->Attr2 |= Attr2Back;
2282 mask->Attr2 |= Attr2Back;
2283 attr->Back = P - 40;
2284 break;
2285
2286 case 48: /* Back color (256color mode) */
2287 if (ts.ColorFlag & CF_XTERM256) {
2288 color = -1;
2289 j = 0;
2290 if (NSParam[i] > 0) {
2291 P = SubParam[i][1];
2292 j++;
2293 }
2294 else if (i < NParam) {
2295 P = Param[i+1];
2296 if (P == 2 || P == 5) {
2297 i++;
2298 }
2299 }
2300 switch (P) {
2301 case 2:
2302 r = g = b = 0;
2303 if (NSParam[i] > 0) {
2304 if (j < NSParam[i]) {
2305 r = SubParam[i][++j];
2306 if (j < NSParam[i]) {
2307 g = SubParam[i][++j];
2308 }
2309 if (j < NSParam[i]) {
2310 b = SubParam[i][++j];
2311 }
2312 color = DispFindClosestColor(r, g, b);
2313 }
2314 }
2315 else if (i < NParam && NSParam[i+1] > 0) {
2316 r = Param[++i];
2317 g = SubParam[i][1];
2318 if (NSParam[i] > 1) {
2319 b = SubParam[i][2];
2320 }
2321 color = DispFindClosestColor(r, g, b);
2322 }
2323 else if (i+2 < NParam) {
2324 r = Param[++i];
2325 g = Param[++i];
2326 b = Param[++i];
2327 color = DispFindClosestColor(r, g, b);
2328 }
2329 break;
2330 case 5:
2331 if (NSParam[i] > 0) {
2332 if (j < NSParam[i]) {
2333 color = SubParam[i][++j];
2334 }
2335 }
2336 else if (i < NParam) {
2337 color = Param[++i];
2338 }
2339 break;
2340 }
2341 if (color >= 0 && color < 256) {
2342 attr->Attr2 |= Attr2Back;
2343 mask->Attr2 |= Attr2Back;
2344 attr->Back = color;
2345 }
2346 }
2347 break;
2348
2349 case 49: /* Reset back color */
2350 attr->Attr2 &= ~ Attr2Back;
2351 mask->Attr2 |= Attr2Back;
2352 attr->Back = AttrDefaultBG;
2353 break;
2354
2355 case 90:
2356 case 91:
2357 case 92:
2358 case 93:
2359 case 94:
2360 case 95:
2361 case 96:
2362 case 97: /* aixterm style text color */
2363 if (ts.ColorFlag & CF_AIXTERM16) {
2364 attr->Attr2 |= Attr2Fore;
2365 mask->Attr2 |= Attr2Fore;
2366 attr->Fore = P - 90 + 8;
2367 }
2368 break;
2369
2370 case 100:
2371 if (! (ts.ColorFlag & CF_AIXTERM16)) {
2372 /* Reset text and back color */
2373 attr->Attr2 &= ~ (Attr2Fore | Attr2Back);
2374 mask->Attr2 |= Attr2ColorMask;
2375 attr->Fore = AttrDefaultFG;
2376 attr->Back = AttrDefaultBG;
2377 break;
2378 }
2379 // fall through
2380 // to aixterm style back color
2381
2382 case 101:
2383 case 102:
2384 case 103:
2385 case 104:
2386 case 105:
2387 case 106:
2388 case 107: /* aixterm style back color */
2389 if (ts.ColorFlag & CF_AIXTERM16) {
2390 attr->Attr2 |= Attr2Back;
2391 mask->Attr2 |= Attr2Back;
2392 attr->Back = P - 100 + 8;
2393 }
2394 break;
2395 }
2396 }
2397 }
2398
2399 static void CSSetAttr(void) // SGR
2400 {
2401 UpdateStr();
2402 ParseSGRParams(&CharAttr, NULL, 1);
2403 BuffSetCurCharAttr(CharAttr);
2404 }
2405
2406 static void CSSetScrollRegion() // DECSTBM
2407 {
2408 if (isCursorOnStatusLine) {
2409 MoveCursor(0,CursorY);
2410 return;
2411 }
2412
2413 RequiredParams(2);
2414 CheckParamVal(Param[1], NumOfLines-StatusLine);
2415 CheckParamValMax(Param[2], NumOfLines-StatusLine);
2416
2417 if (Param[1] >= Param[2])
2418 return;
2419
2420 CursorTop = Param[1] - 1;
2421 CursorBottom = Param[2] - 1;
2422
2423 if (RelativeOrgMode)
2424 // TODO: ���}�[�W���������������B�v���@�m�F�B
2425 MoveCursor(0, CursorTop);
2426 else
2427 MoveCursor(0, 0);
2428 }
2429
2430 static void CSSetLRScrollRegion() // DECSLRM
2431 {
2432 // TODO: �X�e�[�^�X���C�������������m�F�B
2433 // if (isCursorOnStatusLine) {
2434 // MoveCursor(0,CursorY);
2435 // return;
2436 // }
2437
2438 RequiredParams(2);
2439 CheckParamVal(Param[1], NumOfColumns);
2440 CheckParamValMax(Param[2], NumOfColumns);
2441
2442 if (Param[1] >= Param[2])
2443 return;
2444
2445 CursorLeftM = Param[1] - 1;
2446 CursorRightM = Param[2] - 1;
2447
2448 if (RelativeOrgMode)
2449 MoveCursor(CursorLeftM, CursorTop);
2450 else
2451 MoveCursor(0, 0);
2452 }
2453
2454 // CSI sequence
2455 static void CSSunSequence() /* Sun terminal private sequences */
2456 {
2457 int x, y, len;
2458 char Report[TitleBuffSize*2+10];
2459
2460 switch (Param[1]) {
2461 case 1: // De-iconify window
2462 if (ts.WindowFlag & WF_WINDOWCHANGE)
2463 DispShowWindow(WINDOW_RESTORE);
2464 break;
2465
2466 case 2: // Iconify window
2467 if (ts.WindowFlag & WF_WINDOWCHANGE)
2468 DispShowWindow(WINDOW_MINIMIZE);
2469 break;
2470
2471 case 3: // set window position
2472 if (ts.WindowFlag & WF_WINDOWCHANGE) {
2473 RequiredParams(3);
2474 DispMoveWindow(Param[2], Param[3]);
2475 }
2476 break;
2477
2478 case 4: // set window size
2479 if (ts.WindowFlag & WF_WINDOWCHANGE) {
2480 RequiredParams(3);
2481 DispResizeWin(Param[3], Param[2]);
2482 }
2483 break;
2484
2485 case 5: // Raise window
2486 if (ts.WindowFlag & WF_WINDOWCHANGE)
2487 DispShowWindow(WINDOW_RAISE);
2488 break;
2489
2490 case 6: // Lower window
2491 if (ts.WindowFlag & WF_WINDOWCHANGE)
2492 DispShowWindow(WINDOW_LOWER);
2493 break;
2494
2495 case 7: // Refresh window
2496 if (ts.WindowFlag & WF_WINDOWCHANGE)
2497 DispShowWindow(WINDOW_REFRESH);
2498 break;
2499
2500 case 8: /* set terminal size */
2501 if (ts.WindowFlag & WF_WINDOWCHANGE) {
2502 RequiredParams(3);
2503 if (Param[2] <= 1) Param[2] = 24;
2504 if (Param[3] <= 1) Param[3] = 80;
2505 ChangeTerminalSize(Param[3], Param[2]);
2506 }
2507 break;
2508
2509 case 9: // Maximize/Restore window
2510 if (ts.WindowFlag & WF_WINDOWCHANGE) {
2511 RequiredParams(2);
2512 if (Param[2] == 0) {
2513 DispShowWindow(WINDOW_RESTORE);
2514 }
2515 else if (Param[2] == 1) {
2516 DispShowWindow(WINDOW_MAXIMIZE);
2517 }
2518 }
2519 break;
2520
2521 case 10: // Full-screen
2522 /*
2523 * �{�������� PuTTY ���������t���X�N���[�����[�h�������������������A
2524 * �������������������������������p����
2525 */
2526 if (ts.WindowFlag & WF_WINDOWCHANGE) {
2527 RequiredParams(2);
2528 switch (Param[2]) {
2529 case 0:
2530 DispShowWindow(WINDOW_RESTORE);
2531 break;
2532 case 1:
2533 DispShowWindow(WINDOW_MAXIMIZE);
2534 break;
2535 case 2:
2536 DispShowWindow(WINDOW_TOGGLE_MAXIMIZE);
2537 break;
2538 }
2539 }
2540 break;
2541
2542 case 11: // Report window state
2543 if (ts.WindowFlag & WF_WINDOWREPORT) {
2544 len = _snprintf_s_l(Report, sizeof(Report), _TRUNCATE, "%dt", CLocale, DispWindowIconified()?2:1);
2545 SendCSIstr(Report, len);
2546 }
2547 break;
2548
2549 case 13: // Report window position
2550 if (ts.WindowFlag & WF_WINDOWREPORT) {
2551 RequiredParams(2);
2552 switch (Param[2]) {
2553 case 0:
2554 case 1:
2555 DispGetWindowPos(&x, &y, FALSE);
2556 break;
2557 case 2:
2558 DispGetWindowPos(&x, &y, TRUE);
2559 break;
2560 default:
2561 return;
2562 }
2563 len = _snprintf_s_l(Report, sizeof(Report), _TRUNCATE, "3;%u;%ut", CLocale, (unsigned int)x, (unsigned int)y);
2564 SendCSIstr(Report, len);
2565 }
2566 break;
2567
2568 case 14: /* get window size */
2569 if (ts.WindowFlag & WF_WINDOWREPORT) {
2570 RequiredParams(2);
2571 switch (Param[2]) {
2572 case 0:
2573 case 1:
2574 DispGetWindowSize(&x, &y, TRUE);
2575 break;
2576 case 2:
2577 DispGetWindowSize(&x, &y, FALSE);
2578 break;
2579 default:
2580 return;
2581 }
2582
2583 len = _snprintf_s_l(Report, sizeof(Report), _TRUNCATE, "4;%d;%dt", CLocale, y, x);
2584 SendCSIstr(Report, len);
2585 }
2586 break;
2587
2588 case 15: // Report display size (pixel)
2589 if (ts.WindowFlag & WF_WINDOWREPORT) {
2590 DispGetRootWinSize(&x, &y, TRUE);
2591 len = _snprintf_s_l(Report, sizeof(Report), _TRUNCATE, "5;%d;%dt", CLocale, y, x);
2592 SendCSIstr(Report, len);
2593 }
2594 break;
2595
2596 case 16: // Report character cell size (pixel)
2597 if (ts.WindowFlag & WF_WINDOWREPORT) {
2598 len = _snprintf_s_l(Report, sizeof(Report), _TRUNCATE, "6;%d;%dt", CLocale, FontHeight, FontWidth);
2599 SendCSIstr(Report, len);
2600 }
2601 break;
2602
2603 case 18: /* get terminal size */
2604 if (ts.WindowFlag & WF_WINDOWREPORT) {
2605 len = _snprintf_s_l(Report, sizeof(Report), _TRUNCATE, "8;%u;%ut", CLocale,
2606 NumOfLines-StatusLine, NumOfColumns);
2607 SendCSIstr(Report, len);
2608 }
2609 break;
2610
2611 case 19: // Report display size (character)
2612 if (ts.WindowFlag & WF_WINDOWREPORT) {
2613 DispGetRootWinSize(&x, &y, FALSE);
2614 len = _snprintf_s_l(Report, sizeof(Report), _TRUNCATE, "9;%d;%dt", CLocale, y, x);
2615 SendCSIstr(Report, len);
2616 }
2617 break;
2618
2619 case 20: // Report icon label
2620 switch (ts.WindowFlag & WF_TITLEREPORT) {
2621 case IdTitleReportIgnore:
2622 // nothing to do
2623 break;
2624
2625 case IdTitleReportAccept: {
2626 wchar_t *osc_str;
2627 const wchar_t *remote = (cv.TitleRemoteW == NULL) ? L"" : cv.TitleRemoteW;
2628 switch (ts.AcceptTitleChangeRequest) {
2629 case IdTitleChangeRequestOff:
2630 aswprintf(&osc_str, L"L%hs", ts.Title);
2631 break;
2632
2633 case IdTitleChangeRequestAhead:
2634 aswprintf(&osc_str, L"L%s %hs", remote, ts.Title);
2635 break;
2636
2637 case IdTitleChangeRequestLast:
2638 aswprintf(&osc_str, L"L%hs %s", ts.Title, remote);
2639 break;
2640
2641 default:
2642 if (cv.TitleRemoteW == NULL) {
2643 aswprintf(&osc_str, L"L%hs", ts.Title);
2644 }
2645 else {
2646 aswprintf(&osc_str, L"L%s", remote);
2647 }
2648 break;
2649 }
2650 SendOSCstrW(osc_str, ST);
2651 free(osc_str);
2652 break;
2653 }
2654
2655 default: // IdTitleReportEmpty:
2656 SendOSCstr("L", 0, ST);
2657 break;
2658 }
2659 break;
2660
2661 case 21: // Report window title
2662 switch (ts.WindowFlag & WF_TITLEREPORT) {
2663 case IdTitleReportIgnore:
2664 // nothing to do
2665 break;
2666
2667 case IdTitleReportAccept: {
2668 wchar_t *osc_str;
2669 wchar_t *remote = (cv.TitleRemoteW == NULL) ? L"" : cv.TitleRemoteW;
2670 switch (ts.AcceptTitleChangeRequest) {
2671 case IdTitleChangeRequestOff:
2672 aswprintf(&osc_str, L"l%hs", ts.Title);
2673 break;
2674
2675 case IdTitleChangeRequestAhead:
2676 aswprintf(&osc_str, L"l%s %hs", remote, ts.Title);
2677 break;
2678
2679 case IdTitleChangeRequestLast:
2680 aswprintf(&osc_str, L"l%hs %s", ts.Title, remote);
2681 break;
2682
2683 default:
2684 if (cv.TitleRemoteW == NULL) {
2685 aswprintf(&osc_str, L"l%hs", ts.Title);
2686 }
2687 else {
2688 aswprintf(&osc_str, L"l%s", cv.TitleRemoteW);
2689 }
2690 }
2691 SendOSCstrW(osc_str, ST);
2692 free(osc_str);
2693 break;
2694 }
2695
2696 default: // IdTitleReportEmpty:
2697 SendOSCstr("l", 0, ST);
2698 break;
2699 }
2700 break;
2701
2702 case 22: // Push Title
2703 RequiredParams(2);
2704 switch (Param[2]) {
2705 case 0:
2706 case 1:
2707 case 2: {
2708 PTStack t;
2709 if (ts.AcceptTitleChangeRequest && (t=malloc(sizeof(TStack))) != NULL) {
2710 if (cv.TitleRemoteW == NULL) {
2711 t->title = NULL;
2712 t->next = TitleStack;
2713 TitleStack = t;
2714 }
2715 else if ((t->title = _wcsdup(cv.TitleRemoteW)) != NULL) {
2716 t->next = TitleStack;
2717 TitleStack = t;
2718 }
2719 else {
2720 free(t);
2721 }
2722 }
2723 break;
2724 }
2725 }
2726 break;
2727
2728 case 23: // Pop Title
2729 RequiredParams(2);
2730 switch (Param[2]) {
2731 case 0:
2732 case 1:
2733 case 2: {
2734 if (ts.AcceptTitleChangeRequest && TitleStack != NULL) {
2735 PTStack t;
2736 t = TitleStack;
2737 TitleStack = t->next;
2738 free(cv.TitleRemoteW);
2739 cv.TitleRemoteW = t->title;
2740 ChangeTitle();
2741 free(t);
2742 }
2743 break;
2744 }
2745 }
2746 }
2747 }
2748
2749 static void CSLT(BYTE b)
2750 {
2751 switch (b) {
2752 case 'r':
2753 if (CanUseIME()) {
2754 SetIMEOpenStatus(HVTWin, SavedIMEstatus);
2755 }
2756 break;
2757
2758 case 's':
2759 if (CanUseIME()) {
2760 SavedIMEstatus = GetIMEOpenStatus(HVTWin);
2761 }
2762 break;
2763
2764 case 't':
2765 if (CanUseIME()) {
2766 SetIMEOpenStatus(HVTWin, Param[1] == 1);
2767 }
2768 break;
2769 }
2770 }
2771
2772 static void CSEQ(BYTE b)
2773 {
2774 char Report[16];
2775 int len;
2776
2777 switch (b) {
2778 case 'c': /* Tertiary terminal report (Tertiary DA) */
2779 if (Param[1] == 0) {
2780 len = _snprintf_s_l(Report, sizeof(Report), _TRUNCATE, "!|%8s", CLocale, ts.TerminalUID);
2781 SendDCSstr(Report, len);
2782 }
2783 break;
2784 }
2785 }
2786
2787 static void CSGT(BYTE b)
2788 {
2789 switch (b) {
2790 case 'c': /* second terminal report (Secondary DA) */
2791 if (Param[1] == 0) {
2792 SendCSIstr(">32;331;0c", 0); /* VT382(>32) + xterm rev 331 */
2793 }
2794 break;
2795
2796 case 'J': // IO-8256 terminal
2797 if (Param[1]==3) {
2798 RequiredParams(5);
2799 CheckParamVal(Param[2], NumOfLines-StatusLine);
2800 CheckParamVal(Param[3], NumOfColumns);
2801 CheckParamValMax(Param[4], NumOfLines-StatusLine);
2802 CheckParamValMax(Param[5], NumOfColumns);
2803
2804 if (Param[2] > Param[4] || Param[3] > Param[5]) {
2805 return;
2806 }
2807
2808 BuffEraseBox(Param[3]-1, Param[2]-1, Param[5]-1, Param[4]-1);
2809 }
2810 break;
2811
2812 case 'K': // IO-8256 terminal
2813 switch (Param[1]) {
2814 case 3:
2815 RequiredParams(3);
2816 CheckParamVal(Param[2], NumOfColumns);
2817 CheckParamVal(Param[3], NumOfColumns);
2818
2819 if (Param[2] > Param[3]) {
2820 return;
2821 }
2822
2823 BuffEraseCharsInLine(Param[2]-1, Param[3]-Param[2]+1);
2824 break;
2825
2826 case 5:
2827 RequiredParams(3);
2828 switch (Param[2]) {
2829 case 3:
2830 case 4:
2831 case 5:
2832 case 6: // Draw Line
2833 BuffDrawLine(CharAttr, Param[2], Param[3]);
2834 break;
2835
2836 case 12: // Text color
2837 if ((Param[3]>=0) && (Param[3]<=7)) {
2838 switch (Param[3]) {
2839 case 3: CharAttr.Fore = IdBlue; break;
2840 case 4: CharAttr.Fore = IdCyan; break;
2841 case 5: CharAttr.Fore = IdYellow; break;
2842 case 6: CharAttr.Fore = IdMagenta; break;
2843 default: CharAttr.Fore = Param[3]; break;
2844 }
2845 CharAttr.Attr2 |= Attr2Fore;
2846 BuffSetCurCharAttr(CharAttr);
2847 }
2848 break;
2849 }
2850 break;
2851 }
2852 break;
2853 }
2854 }
2855
2856 // DECSCNM / Visual Bell
2857 static void CSQExchangeColor(void)
2858 {
2859 BuffUpdateScroll();
2860
2861 ts.ColorFlag ^= CF_REVERSEVIDEO;
2862
2863 DispChangeBackground();
2864 UpdateWindow(HVTWin);
2865 }
2866
2867 static void CSQChangeColumnMode(int width) // DECCOLM
2868 {
2869 ChangeTerminalSize(width, NumOfLines-StatusLine);
2870 LRMarginMode = FALSE;
2871
2872 // DECCOLM �����������N���A�����������d�l
2873 // ClearOnResize �� off �������������N���A�����B
2874 // ClearOnResize �� on ������ ChangeTerminalSize() ���������N���A�����������A
2875 // �]�v���X�N���[�����������������������N���A�������B
2876 if ((ts.TermFlag & TF_CLEARONRESIZE) == 0) {
2877 MoveCursor(0, 0);
2878 BuffClearScreen();
2879 UpdateWindow(HVTWin);
2880 }
2881 }
2882
2883 static void CSQ_h_Mode() // DECSET
2884 {
2885 int i;
2886
2887 for (i = 1 ; i<=NParam ; i++) {
2888 switch (Param[i]) {
2889 case 1: AppliCursorMode = TRUE; break; // DECCKM
2890 case 3: CSQChangeColumnMode(132); break; // DECCOLM
2891 case 5: /* Reverse Video (DECSCNM) */
2892 if (!(ts.ColorFlag & CF_REVERSEVIDEO))
2893 CSQExchangeColor(); /* Exchange text/back color */
2894 break;
2895 case 6: // DECOM
2896 if (isCursorOnStatusLine)
2897 MoveCursor(0,CursorY);
2898 else {
2899 RelativeOrgMode = TRUE;
2900 MoveCursor(0,CursorTop);
2901 }
2902 break;
2903 case 7: AutoWrapMode = TRUE; break; // DECAWM
2904 case 8: AutoRepeatMode = TRUE; break; // DECARM
2905 case 9: /* X10 Mouse Tracking */
2906 if (ts.MouseEventTracking)
2907 MouseReportMode = IdMouseTrackX10;
2908 break;
2909 case 12: /* att610 cursor blinking */
2910 if (ts.WindowFlag & WF_CURSORCHANGE) {
2911 ts.NonblinkingCursor = FALSE;
2912 ChangeCaret();
2913 }
2914 break;
2915 case 19: PrintEX = TRUE; break; // DECPEX
2916 case 25: DispEnableCaret(TRUE); break; // cursor on (DECTCEM)
2917 case 38: // DECTEK
2918 if (ts.AutoWinSwitch>0)
2919 ChangeEmu = IdTEK; /* Enter TEK Mode */
2920 break;
2921 case 47: // Alternate Screen Buffer
2922 if ((ts.TermFlag & TF_ALTSCR) && !AltScr) {
2923 BuffSaveScreen();
2924 AltScr = TRUE;
2925 }
2926 break;
2927 case 59:
2928 if (ts.Language==IdJapanese) {
2929 /* kanji terminal */
2930 CharSet2022Designate(charset_data, 0, IdASCII);
2931 CharSet2022Designate(charset_data, 1, IdKatakana);
2932 CharSet2022Designate(charset_data, 2, IdKatakana);
2933 CharSet2022Designate(charset_data, 3, IdKanji);
2934 CharSet2022Invoke(charset_data, CHARSET_LS0);
2935 if ((ts.KanjiCode==IdJIS) && (ts.JIS7Katakana==0))
2936 // 8-bit katakana
2937 CharSet2022Invoke(charset_data, CHARSET_LS2R);
2938 else
2939 CharSet2022Invoke(charset_data, CHARSET_LS3R);
2940 }
2941 break;
2942 case 66: AppliKeyMode = TRUE; break; // DECNKM
2943 case 67: ts.BSKey = IdBS; break; // DECBKM
2944 case 69: LRMarginMode = TRUE; break; // DECLRMM (DECVSSM)
2945 case 1000: // Mouse Tracking
2946 if (ts.MouseEventTracking)
2947 MouseReportMode = IdMouseTrackVT200;
2948 break;
2949 case 1001: // Hilite Mouse Tracking
2950 if (ts.MouseEventTracking)
2951 MouseReportMode = IdMouseTrackVT200Hl;
2952 break;
2953 case 1002: // Button-Event Mouse Tracking
2954 if (ts.MouseEventTracking)
2955 MouseReportMode = IdMouseTrackBtnEvent;
2956 break;
2957 case 1003: // Any-Event Mouse Tracking
2958 if (ts.MouseEventTracking)
2959 MouseReportMode = IdMouseTrackAllEvent;
2960 break;
2961 case 1004: // Focus Report
2962 if (ts.MouseEventTracking)
2963 FocusReportMode = TRUE;
2964 break;
2965 case 1005: // Extended Mouse Tracking (UTF-8)
2966 if (ts.MouseEventTracking)
2967 MouseReportExtMode = IdMouseTrackExtUTF8;
2968 break;
2969 case 1006: // Extended Mouse Tracking (SGR)
2970 if (ts.MouseEventTracking)
2971 MouseReportExtMode = IdMouseTrackExtSGR;
2972 break;
2973 case 1015: // Extended Mouse Tracking (rxvt-unicode)
2974 if (ts.MouseEventTracking)
2975 MouseReportExtMode = IdMouseTrackExtURXVT;
2976 break;
2977 case 1047: // Alternate Screen Buffer
2978 if ((ts.TermFlag & TF_ALTSCR) && !AltScr) {
2979 BuffSaveScreen();
2980 AltScr = TRUE;
2981 }
2982 break;
2983 case 1048: // Save Cursor Position (Alternate Screen Buffer)
2984 if (ts.TermFlag & TF_ALTSCR) {
2985 SaveCursor();
2986 }
2987 break;
2988 case 1049: // Alternate Screen Buffer
2989 if ((ts.TermFlag & TF_ALTSCR) && !AltScr) {
2990 SaveCursor();
2991 BuffSaveScreen();
2992 BuffClearScreen();
2993 AltScr = TRUE;
2994 }
2995 break;
2996 case 2004: // Bracketed Paste Mode
2997 BracketedPaste = TRUE;
2998 break;
2999 case 7727: // mintty Application Escape Mode
3000 AppliEscapeMode = 1;
3001 break;
3002 case 7786: // Wheel to Cursor translation
3003 if (ts.TranslateWheelToCursor) {
3004 AcceptWheelToCursor = TRUE;
3005 }
3006 break;
3007 case 8200: // ClearThenHome
3008 ClearThenHome = TRUE;
3009 break;
3010 case 14001: // NetTerm mouse mode
3011 if (ts.MouseEventTracking)
3012 MouseReportMode = IdMouseTrackNetTerm;
3013 break;
3014 case 14002: // test Application Escape Mode 2
3015 case 14003: // test Application Escape Mode 3
3016 case 14004: // test Application Escape Mode 4
3017 AppliEscapeMode = Param[i] - 14000;
3018 break;
3019 }
3020 }
3021 }
3022
3023 static void PrintFileFinish(PrintFile *handle)
3024 {
3025 PrnFinish(handle);
3026 PrintFile_ = NULL;
3027 }
3028
3029 static void CSQ_i_Mode(void) // DECMC
3030 {
3031 switch (Param[1]) {
3032 case 1:
3033 if (ts.TermFlag&TF_PRINTERCTRL) {
3034 PrintFile_ = OpenPrnFile();
3035 BuffDumpCurrentLine(PrintFile_, LF);
3036 if (! AutoPrintMode) {
3037 ClosePrnFile(PrintFile_, PrintFileFinish);
3038 }
3039 }
3040 break;
3041 /* auto print mode off */
3042 case 4:
3043 if (AutoPrintMode) {
3044 ClosePrnFile(PrintFile_, PrintFileFinish);
3045 AutoPrintMode = FALSE;
3046 }
3047 break;
3048 /* auto print mode on */
3049 case 5:
3050 if (ts.TermFlag&TF_PRINTERCTRL) {
3051 if (! AutoPrintMode) {
3052 PrintFile_ = OpenPrnFile();
3053 AutoPrintMode = TRUE;
3054 }
3055 }
3056 break;
3057 }
3058 }
3059
3060 static void CSQ_l_Mode() // DECRST
3061 {
3062 int i;
3063
3064 for (i = 1 ; i <= NParam ; i++) {
3065 switch (Param[i]) {
3066 case 1: AppliCursorMode = FALSE; break; // DECCKM
3067 case 3: CSQChangeColumnMode(80); break; // DECCOLM
3068 case 5: /* Normal Video (DECSCNM) */
3069 if (ts.ColorFlag & CF_REVERSEVIDEO)
3070 CSQExchangeColor(); /* Exchange text/back color */
3071 break;
3072 case 6: // DECOM
3073 if (isCursorOnStatusLine)
3074 MoveCursor(0,CursorY);
3075 else {
3076 RelativeOrgMode = FALSE;
3077 MoveCursor(0,0);
3078 }
3079 break;
3080 case 7: AutoWrapMode = FALSE; break; // DECAWM
3081 case 8: AutoRepeatMode = FALSE; break; // DECARM
3082 case 9: MouseReportMode = IdMouseTrackNone; break; /* X10 Mouse Tracking */
3083 case 12: /* att610 cursor blinking */
3084 if (ts.WindowFlag & WF_CURSORCHANGE) {
3085 ts.NonblinkingCursor = TRUE;
3086 ChangeCaret();
3087 }
3088 break;
3089 case 19: PrintEX = FALSE; break; // DECPEX
3090 case 25: DispEnableCaret(FALSE); break; // cursor off (DECTCEM)
3091 case 47: // Alternate Screen Buffer
3092 if ((ts.TermFlag & TF_ALTSCR) && AltScr) {
3093 BuffRestoreScreen();
3094 AltScr = FALSE;
3095 }
3096 break;
3097 case 59:
3098 if (ts.Language==IdJapanese) {
3099 /* katakana terminal */
3100 CharSet2022Designate(charset_data, 0, IdASCII);
3101 CharSet2022Designate(charset_data, 1, IdKatakana);
3102 CharSet2022Designate(charset_data, 2, IdKatakana);
3103 CharSet2022Designate(charset_data, 3, IdKanji);
3104 CharSet2022Invoke(charset_data, CHARSET_LS0);
3105 if ((ts.KanjiCode==IdJIS) && (ts.JIS7Katakana==0))
3106 // 8-bit katakana
3107 CharSet2022Invoke(charset_data, CHARSET_LS2R);
3108 else
3109 CharSet2022Invoke(charset_data, CHARSET_LS3R);
3110 }
3111 break;
3112 case 66: AppliKeyMode = FALSE; break; // DECNKM
3113 case 67: ts.BSKey = IdDEL; break; // DECBKM
3114 case 69: // DECLRMM (DECVSSM)
3115 LRMarginMode = FALSE;
3116 CursorLeftM = 0;
3117 CursorRightM = NumOfColumns - 1;
3118 break;
3119 case 1000: // Mouse Tracking
3120 case 1001: // Hilite Mouse Tracking
3121 case 1002: // Button-Event Mouse Tracking
3122 case 1003: // Any-Event Mouse Tracking
3123 MouseReportMode = IdMouseTrackNone;
3124 break;
3125 case 1004: // Focus Report
3126 FocusReportMode = FALSE;
3127 break;
3128 case 1005: // Extended Mouse Tracking (UTF-8)
3129 case 1006: // Extended Mouse Tracking (SGR)
3130 case 1015: // Extended Mouse Tracking (rxvt-unicode)
3131 MouseReportExtMode = IdMouseTrackExtNone;
3132 break;
3133 case 1047: // Alternate Screen Buffer
3134 if ((ts.TermFlag & TF_ALTSCR) && AltScr) {
3135 BuffClearScreen();
3136 BuffRestoreScreen();
3137 AltScr = FALSE;
3138 }
3139 break;
3140 case 1048: // Save Cursor Position (Alternate Screen Buffer)
3141 if (ts.TermFlag & TF_ALTSCR) {
3142 RestoreCursor();
3143 }
3144 break;
3145 case 1049: // Alternate Screen Buffer
3146 if ((ts.TermFlag & TF_ALTSCR) && AltScr) {
3147 BuffClearScreen();
3148 BuffRestoreScreen();
3149 AltScr = FALSE;
3150 RestoreCursor();
3151 }
3152 break;
3153 case 2004: // Bracketed Paste Mode
3154 BracketedPaste = FALSE;
3155 break;
3156 case 7727: // mintty Application Escape Mode
3157 AppliEscapeMode = 0;
3158 break;
3159 case 7786: // Wheel to Cursor translation
3160 AcceptWheelToCursor = FALSE;
3161 break;
3162 case 8200: // ClearThenHome
3163 ClearThenHome = FALSE;
3164 break;
3165 case 14001: // NetTerm mouse mode
3166 MouseReportMode = IdMouseTrackNone;
3167 break;
3168 case 14002: // test Application Escape Mode 2
3169 case 14003: // test Application Escape Mode 3
3170 case 14004: // test Application Escape Mode 4
3171 AppliEscapeMode = 0;
3172 break;
3173 }
3174 }
3175 }
3176
3177 static void CSQ_n_Mode() // DECDSR
3178 {
3179 switch (Param[1]) {
3180 case 53:
3181 case 55:
3182 /* Locator Device Status Report -> Ready */
3183 SendCSIstr("?50n", 0);
3184 break;
3185 }
3186 }
3187
3188 static void CSQuest(BYTE b)
3189 {
3190 switch (b) {
3191 case 'J': CSQSelScreenErase(); break; // DECSED
3192 case 'K': CSQSelLineErase(); break; // DECSEL
3193 case 'h': CSQ_h_Mode(); break; // DECSET
3194 case 'i': CSQ_i_Mode(); break; // DECMC
3195 case 'l': CSQ_l_Mode(); break; // DECRST
3196 case 'n': CSQ_n_Mode(); break; // DECDSR
3197 }
3198 }
3199
3200 static void SoftReset()
3201 // called by software-reset escape sequence handler
3202 {
3203 UpdateStr();
3204 AutoRepeatMode = TRUE;
3205 DispEnableCaret(TRUE); // cursor on
3206 InsertMode = FALSE;
3207 RelativeOrgMode = FALSE;
3208 AppliKeyMode = FALSE;
3209 AppliCursorMode = FALSE;
3210 AppliEscapeMode = FALSE;
3211 AcceptWheelToCursor = ts.TranslateWheelToCursor;
3212 if (isCursorOnStatusLine)
3213 MoveToMainScreen();
3214 CursorTop = 0;
3215 CursorBottom = NumOfLines-1-StatusLine;
3216 CursorLeftM = 0;
3217 CursorRightM = NumOfColumns - 1;
3218 ResetCharSet();
3219
3220 /* Attribute */
3221 CharAttr = DefCharAttr;
3222 BuffSetCurCharAttr(CharAttr);
3223
3224 // status buffers
3225 {
3226 PStatusBuff Buff;
3227 int save_x = CursorX;
3228 int save_y = CursorY;
3229
3230 if (AltScr) {
3231 Buff = &SBuff3; // Alternate screen buffer
3232 }
3233 else {
3234 Buff = &SBuff1; // Normal screen buffer
3235 }
3236 CursorX = 0;
3237 CursorY = 0;
3238 SaveCursorBuf(Buff);
3239 CursorX = save_x;
3240 CursorY = save_y;
3241 }
3242
3243 // Saved IME status
3244 IMEstat = FALSE;
3245 }
3246
3247 static void CSExc(BYTE b)
3248 {
3249 switch (b) {
3250 case 'p':
3251 /* Software reset */
3252 SoftReset();
3253 break;
3254 }
3255 }
3256
3257 static void CSDouble(BYTE b)
3258 {
3259 switch (b) {
3260 case 'p': // DECSCL
3261 /* Select terminal mode (software reset) */
3262 RequiredParams(2);
3263
3264 SoftReset();
3265 ChangeTerminalID();
3266 if (Param[1] >= 61 && Param[1] <= 65) {
3267 if (VTlevel > Param[1] - 60) {
3268 VTlevel = Param[1] - 60;
3269 }
3270 }
3271 else {
3272 VTlevel = 1;
3273 }
3274
3275 if (VTlevel < 2 || Param[2] == 1)
3276 Send8BitMode = FALSE;
3277 else
3278 Send8BitMode = TRUE;
3279 break;
3280
3281 case 'q': // DECSCA
3282 switch (Param[1]) {
3283 case 0:
3284 case 2:
3285 CharAttr.Attr2 &= ~Attr2Protect;
3286 BuffSetCurCharAttr(CharAttr);
3287 break;
3288 case 1:
3289 CharAttr.Attr2 |= Attr2Protect;
3290 BuffSetCurCharAttr(CharAttr);
3291 break;
3292 default:
3293 /* nothing to do */
3294 break;
3295 }
3296 break;
3297 }
3298 }
3299
3300 static void CSDolRequestMode(void) // DECRQM
3301 {
3302 char buff[256];
3303 char *pp;
3304 int len, resp = 0;
3305
3306 switch (Prv) {
3307 case 0: /* ANSI Mode */
3308 resp = 4;
3309 pp = "";
3310 switch (Param[1]) {
3311 case 2: // KAM
3312 if (KeybEnabled)
3313 resp = 2;
3314 else
3315 resp = 1;
3316 break;
3317 case 4: // IRM
3318 if (InsertMode)
3319 resp = 1;
3320 else
3321 resp = 2;
3322 break;
3323 case 12: // SRM
3324 if (ts.LocalEcho)
3325 resp = 2;
3326 else
3327 resp = 1;
3328 break;
3329 case 20: // LNM
3330 if (LFMode)
3331 resp = 1;
3332 else
3333 resp = 2;
3334 break;
3335 case 33: // WYSTCURM
3336 if (ts.NonblinkingCursor)
3337 resp = 1;
3338 else
3339 resp = 2;
3340 if ((ts.WindowFlag & WF_CURSORCHANGE) == 0)
3341 resp += 2;
3342 break;
3343 case 34: // WYULCURM
3344 if (ts.CursorShape == IdHCur)
3345 resp = 1;
3346 else
3347 resp = 2;
3348 if ((ts.WindowFlag & WF_CURSORCHANGE) == 0)
3349 resp += 2;
3350 break;
3351 }
3352 break;
3353
3354 case '?': /* DEC Mode */
3355 pp = "?";
3356 switch (Param[1]) {
3357 case 1: // DECCKM
3358 if (AppliCursorMode)
3359 resp = 1;
3360 else
3361 resp = 2;
3362 break;
3363 case 3: // DECCOLM
3364 if (NumOfColumns == 132)
3365 resp = 1;
3366 else
3367 resp = 2;
3368 break;
3369 case 5: // DECSCNM
3370 if (ts.ColorFlag & CF_REVERSEVIDEO)
3371 resp = 1;
3372 else
3373 resp = 2;
3374 break;
3375 case 6: // DECOM
3376 if (RelativeOrgMode)
3377 resp = 1;
3378 else
3379 resp = 2;
3380 break;
3381 case 7: // DECAWM
3382 if (AutoWrapMode)
3383 resp = 1;
3384 else
3385 resp = 2;
3386 break;
3387 case 8: // DECARM
3388 if (AutoRepeatMode)
3389 resp = 1;
3390 else
3391 resp = 2;
3392 break;
3393 case 9: // XT_MSE_X10 -- X10 Mouse Tracking
3394 if (!ts.MouseEventTracking)
3395 resp = 4;
3396 else if (MouseReportMode == IdMouseTrackX10)
3397 resp = 1;
3398 else
3399 resp = 2;
3400 break;
3401 case 12: // XT_CBLINK -- att610 cursor blinking
3402 if (ts.NonblinkingCursor)
3403 resp = 2;
3404 else
3405 resp = 1;
3406 if ((ts.WindowFlag & WF_CURSORCHANGE) == 0)
3407 resp += 2;
3408 break;
3409 case 19: // DECPEX
3410 if (PrintEX)
3411 resp = 1;
3412 else
3413 resp = 2;
3414 break;
3415 case 25: // DECTCEM
3416 if (IsCaretEnabled())
3417 resp = 1;
3418 else
3419 resp = 2;
3420 break;
3421 case 38: // DECTEK
3422 resp = 4;
3423 break;
3424 case 47: // XT_ALTSCRN -- Alternate Screen / (DECGRPM)
3425 if ((ts.TermFlag & TF_ALTSCR) == 0)
3426 resp = 4;
3427 else if (AltScr)
3428 resp = 1;
3429 else
3430 resp = 2;
3431 break;
3432 case 59: // DECKKDM
3433 if (ts.Language!=IdJapanese)
3434 resp = 0;
3435 else if ((ts.KanjiCode == IdJIS) && (!ts.JIS7Katakana))
3436 resp = 4;
3437 else
3438 resp = 3;
3439 break;
3440 case 66: // DECNKM
3441 if (AppliKeyMode)
3442 resp = 1;
3443 else
3444 resp = 2;