Develop and Download Open Source Software

Browse Subversion Repository

Annotation of /branches/ttcomtester/teraterm/teraterm/buffer.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 8598 - (hide annotations) (download) (as text)
Sun Mar 15 15:24:18 2020 UTC (4 years ago) by zmatsuo
Original Path: trunk/teraterm/teraterm/buffer.c
File MIME type: text/x-csrc
File size: 160023 byte(s)
結合文字等を遅れて受信した際正しく表示されるよう修正

- "ほ" U+307B の後に U+309A が送られてきたときなど
- 例
  - U+307B U+309A = "ぽ" (U+307D)
  - U+0061 U+0302 = "â" (U+00E2)
  - U+0041 U+0302 U+0300
- Ticket #15826
1 doda 6806 /*
2     * Copyright (C) 1994-1998 T. Teranishi
3 doda 8480 * (C) 2004-2020 TeraTerm Project
4 doda 6806 * All rights reserved.
5     *
6 doda 6841 * Redistribution and use in source and binary forms, with or without
7     * modification, are permitted provided that the following conditions
8     * are met:
9 doda 6806 *
10 doda 6841 * 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 doda 6806 *
18 doda 6841 * 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 doda 6806 */
29 maya 3227
30     /* TERATERM.EXE, scroll buffer routines */
31    
32     #include "teraterm.h"
33     #include <string.h>
34 yutakapon 4707 #include <stdio.h>
35 doda 8445 #include <windows.h>
36     #define _CRTDBG_MAP_ALLOC
37     #include <crtdbg.h>
38     #include <mbstring.h>
39     #include <assert.h>
40     #include <errno.h>
41 maya 3227
42 doda 8445 #include "tttypes.h"
43 maya 3227 #include "ttwinman.h"
44     #include "teraprn.h"
45     #include "vtdisp.h"
46     #include "clipboar.h"
47     #include "telnet.h"
48     #include "ttplug.h" /* TTPLUG */
49 doda 8445 #include "codeconv.h"
50     #include "unicode.h"
51 maya 3227 #include "buffer.h"
52 doda 8445 #include "unicode_test.h"
53 zmatsuo 8584 #include "asprintf.h"
54 maya 3227
55 doda 8445 #if UNICODE_INTERNAL_BUFF
56 maya 3227
57 doda 8445 typedef unsigned long char32_t; // C++11
58    
59     // �o�b�t�@�������p1������������
60     typedef struct {
61     char32_t u32;
62     char32_t u32_last;
63     char WidthProperty; // 'W' or 'F' or 'H' or 'A' (����������)
64     char HalfWidth; // TRUE/FALSE = ���p/�S�p (�\������������������)
65     char Padding; // TRUE = �S�p�������l���� or �s�����l����
66     char Emoji; // TRUE = �G����
67 zmatsuo 8585 unsigned char CombinationCharCount16; // charactor count
68     unsigned char CombinationCharSize16; // buffer size
69     unsigned char CombinationCharCount32;
70     unsigned char CombinationCharSize32;
71 doda 8445 wchar_t *pCombinationChars16;
72     char32_t *pCombinationChars32;
73     wchar_t wc2[2];
74     } buff_char_t;
75     #endif
76    
77 maya 3227 #define BuffXMax TermWidthMax
78     //#define BuffYMax 100000
79     //#define BuffSizeMax 8000000
80     // �X�N���[���o�b�t�@�����������g�� (2004.11.28 yutaka)
81     #define BuffYMax 500000
82     #define BuffSizeMax (BuffYMax * 80)
83    
84     // status line
85 doda 6435 int StatusLine; //0: none 1: shown
86 doda 5324 /* top, bottom, left & right margin */
87     int CursorTop, CursorBottom, CursorLeftM, CursorRightM;
88 doda 8400 BOOL Selected, Selecting;
89 maya 3227 BOOL Wrap;
90    
91     static WORD TabStops[256];
92     static int NTabStops;
93    
94     static WORD BuffLock = 0;
95    
96     static PCHAR CodeBuff; /* Character code buffer */
97     static PCHAR AttrBuff; /* Attribute buffer */
98     static PCHAR AttrBuff2; /* Color attr buffer */
99     static PCHAR AttrBuffFG; /* Foreground color attr buffer */
100     static PCHAR AttrBuffBG; /* Background color attr buffer */
101     static PCHAR CodeLine;
102     static PCHAR AttrLine;
103     static PCHAR AttrLine2;
104     static PCHAR AttrLineFG;
105     static PCHAR AttrLineBG;
106 doda 8445 #if UNICODE_INTERNAL_BUFF
107     static buff_char_t *CodeBuffW;
108     static buff_char_t *CodeLineW;
109     #endif
110 maya 3227 static LONG LinePtr;
111     static LONG BufferSize;
112     static int NumOfLinesInBuff;
113     static int BuffStartAbs, BuffEndAbs;
114 doda 8400 static POINT SelectStart, SelectStartTmp, SelectEnd, SelectEndOld;
115     static DWORD SelectStartTime;
116 maya 3227 static BOOL BoxSelect;
117     static POINT DblClkStart, DblClkEnd;
118    
119 doda 8445 // �`��
120     static int StrChangeStart; // �`���J�n X (Y=CursorY)
121     static int StrChangeCount; // �`���L�����N�^��(���p�P��),0�������`����������������
122 maya 3227
123     static BOOL SeveralPageSelect; // add (2005.5.15 yutaka)
124    
125     static TCharAttr CurCharAttr;
126    
127 doda 8445 static char *SaveBuff = NULL;
128     static int SaveBuffX;
129     static int SaveBuffY;
130 doda 3743
131 doda 8445 #if UNICODE_INTERNAL_BUFF
132     static void BuffDrawLineI(int DrawX, int DrawY, int SY, int IStart, int IEnd);
133     #endif
134    
135     #if UNICODE_INTERNAL_BUFF
136     static void BuffSetChar2(buff_char_t *buff, char32_t u32, char property, BOOL half_width, char emoji)
137 maya 3227 {
138 doda 8445 size_t wstr_len;
139     buff_char_t *p = buff;
140     if (p->pCombinationChars16 != NULL) {
141     free(p->pCombinationChars16);
142     p->pCombinationChars16 = NULL;
143     }
144     p->CombinationCharCount16 = 0;
145     p->CombinationCharSize16 = 0;
146     if (p->pCombinationChars32 != NULL) {
147     free(p->pCombinationChars32);
148     p->pCombinationChars32 = NULL;
149     }
150     p->CombinationCharCount32 = 0;
151     p->CombinationCharSize32 = 0;
152     p->WidthProperty = property;
153     p->HalfWidth = (char)half_width;
154     p->u32 = u32;
155     p->u32_last = u32;
156     p->Padding = FALSE;
157     p->Emoji = emoji;
158    
159     //
160     wstr_len = UTF32ToUTF16(u32, &p->wc2[0], 2);
161     switch (wstr_len) {
162     case 0:
163     default:
164     p->wc2[0] = 0;
165     p->wc2[1] = 0;
166     break;
167     case 1:
168     p->wc2[1] = 0;
169     break;
170     case 2:
171     break;
172     }
173     }
174    
175     static void BuffSetChar(buff_char_t *buff, char32_t u32, char property)
176     {
177     BuffSetChar2(buff, u32, property, TRUE, FALSE);
178     }
179    
180     /**
181     * �����������A�R���r�l�[�V����
182     */
183     static void BuffAddChar(buff_char_t *buff, char32_t u32)
184     {
185     buff_char_t *p = buff;
186     assert(p->u32 != 0);
187     // �������������������g������
188     if (p->CombinationCharSize16 < p->CombinationCharCount16 + 2) {
189     size_t new_size = p->CombinationCharSize16;
190     new_size = new_size == 0 ? 5 : new_size * 2;
191     p->pCombinationChars16 = realloc(p->pCombinationChars16, sizeof(wchar_t) * new_size);
192     p->CombinationCharSize16 = (char)new_size;
193     }
194     if (p->CombinationCharSize32 < p->CombinationCharCount32 + 2) {
195     size_t new_size = p->CombinationCharSize32;
196     new_size = new_size == 0 ? 5 : new_size * 2;
197     p->pCombinationChars32 = realloc(p->pCombinationChars32, sizeof(char32_t) * new_size);
198     p->CombinationCharSize32 = (char)new_size;
199     }
200    
201     // UTF-32
202     p->u32_last = u32;
203     p->pCombinationChars32[(size_t)p->CombinationCharCount32] = u32;
204     p->CombinationCharCount32++;
205    
206     // UTF-16
207     {
208     wchar_t *u16 = &p->pCombinationChars16[(size_t)p->CombinationCharCount16];
209     size_t wlen = UTF32ToUTF16(u32, u16, 2);
210     p->CombinationCharCount16 += (char)wlen;
211     }
212     }
213    
214     static void memcpyW(buff_char_t *dest, const buff_char_t *src, size_t count)
215     {
216     size_t i;
217     memcpy(dest, src, count * sizeof(buff_char_t));
218     for (i=0; i<count; i++) {
219     buff_char_t *p = &dest[i];
220     size_t size = p->CombinationCharSize16;
221     if (size > 0) {
222     wchar_t *new_buf = malloc(sizeof(wchar_t) * size);
223     memcpy(new_buf, p->pCombinationChars16, sizeof(wchar_t) * size);
224     p->pCombinationChars16 = new_buf;
225     }
226     size = p->CombinationCharSize32;
227     if (size > 0) {
228     char32_t *new_buf = malloc(sizeof(char32_t) * size);
229     memcpy(new_buf, p->pCombinationChars32, sizeof(char32_t) * size);
230     p->pCombinationChars32 = new_buf;
231     }
232     }
233     }
234    
235     static void memsetW(buff_char_t *dest, wchar_t ch, size_t count)
236     {
237     size_t i;
238     for (i=0; i<count; i++) {
239     BuffSetChar(dest, ch, 'H');
240     dest++;
241     }
242     }
243    
244     static void memmoveW(buff_char_t *dest, const buff_char_t *src, size_t count)
245     {
246     memmove(dest, src, count * sizeof(buff_char_t));
247     }
248    
249     static BOOL IsBuffPadding(const buff_char_t *b)
250     {
251     if (b->Padding == TRUE)
252     return TRUE;
253     if (b->u32 == 0)
254     return TRUE;
255     return FALSE;
256     }
257    
258     static BOOL IsBuffFullWidth(const buff_char_t *b)
259     {
260     if (b->HalfWidth == FALSE)
261     return TRUE;
262     return FALSE;
263     }
264    
265     #endif
266    
267     static LONG GetLinePtr(int Line)
268     {
269 maya 3393 LONG Ptr;
270 maya 3227
271 maya 3393 Ptr = (LONG)(BuffStartAbs + Line) * (LONG)(NumOfColumns);
272     while (Ptr>=BufferSize) {
273     Ptr = Ptr - BufferSize;
274     }
275     return Ptr;
276 maya 3227 }
277    
278 doda 8445 static LONG NextLinePtr(LONG Ptr)
279 maya 3227 {
280 maya 3393 Ptr = Ptr + (LONG)NumOfColumns;
281     if (Ptr >= BufferSize) {
282     Ptr = Ptr - BufferSize;
283     }
284     return Ptr;
285 maya 3227 }
286    
287 doda 8445 static LONG PrevLinePtr(LONG Ptr)
288 maya 3227 {
289 maya 3393 Ptr = Ptr - (LONG)NumOfColumns;
290     if (Ptr < 0) {
291     Ptr = Ptr + BufferSize;
292     }
293     return Ptr;
294 maya 3227 }
295    
296 doda 8445 static BOOL ChangeBuffer(int Nx, int Ny)
297 maya 3227 {
298 maya 3393 LONG NewSize;
299     int NxCopy, NyCopy, i;
300     PCHAR CodeDest, AttrDest, AttrDest2, AttrDestFG, AttrDestBG;
301     LONG SrcPtr, DestPtr;
302     WORD LockOld;
303 doda 8445 #if UNICODE_INTERNAL_BUFF
304     buff_char_t *CodeDestW;
305     #endif
306 maya 3227
307 maya 3393 if (Nx > BuffXMax) {
308     Nx = BuffXMax;
309     }
310     if (ts.ScrollBuffMax > BuffYMax) {
311     ts.ScrollBuffMax = BuffYMax;
312     }
313     if (Ny > ts.ScrollBuffMax) {
314     Ny = ts.ScrollBuffMax;
315     }
316 maya 3227
317 maya 3393 if ( (LONG)Nx * (LONG)Ny > BuffSizeMax ) {
318     Ny = BuffSizeMax / Nx;
319     }
320 maya 3227
321 maya 3393 NewSize = (LONG)Nx * (LONG)Ny;
322 maya 3227
323 doda 8445 CodeDest = NULL;
324     AttrDest = NULL;
325     AttrDest2 = NULL;
326     AttrDestFG = NULL;
327     AttrDestBG = NULL;
328     #if UNICODE_INTERNAL_BUFF
329     CodeDestW = NULL;
330     #endif
331 maya 3227
332 doda 8445 CodeDest = malloc(NewSize);
333     if (CodeDest == NULL) {
334 doda 3686 goto allocate_error;
335 maya 3393 }
336 doda 8445 AttrDest = malloc(NewSize);
337     if (AttrDest == NULL) {
338 doda 3686 goto allocate_error;
339 maya 3393 }
340 doda 8445 AttrDest2 = malloc(NewSize);
341     if (AttrDest2 == NULL) {
342 doda 3686 goto allocate_error;
343 maya 3393 }
344 doda 8445 AttrDestFG = malloc(NewSize);
345     if (AttrDestFG == NULL) {
346 doda 3686 goto allocate_error;
347 maya 3393 }
348 doda 8445 AttrDestBG = malloc(NewSize);
349     if (AttrDestBG == NULL) {
350 doda 3686 goto allocate_error;
351 maya 3393 }
352 doda 8445 #if UNICODE_INTERNAL_BUFF
353     CodeDestW = malloc(NewSize * sizeof(buff_char_t));
354     if (CodeDestW == NULL) {
355     goto allocate_error;
356     }
357     #endif
358 maya 3227
359 maya 3393 memset(&CodeDest[0], 0x20, NewSize);
360 doda 8445 #if UNICODE_INTERNAL_BUFF
361     memset(&CodeDestW[0], 0, NewSize * sizeof(buff_char_t));
362     memsetW(&CodeDestW[0], 0x20, NewSize);
363     #endif
364 maya 3393 memset(&AttrDest[0], AttrDefault, NewSize);
365     memset(&AttrDest2[0], AttrDefault, NewSize);
366     memset(&AttrDestFG[0], AttrDefaultFG, NewSize);
367     memset(&AttrDestBG[0], AttrDefaultBG, NewSize);
368 doda 8445 if ( CodeBuff != NULL ) {
369 maya 3393 if ( NumOfColumns > Nx ) {
370     NxCopy = Nx;
371     }
372     else {
373     NxCopy = NumOfColumns;
374     }
375 maya 3227
376 maya 3393 if ( BuffEnd > Ny ) {
377     NyCopy = Ny;
378     }
379     else {
380     NyCopy = BuffEnd;
381     }
382     LockOld = BuffLock;
383     LockBuffer();
384     SrcPtr = GetLinePtr(BuffEnd-NyCopy);
385     DestPtr = 0;
386     for (i = 1 ; i <= NyCopy ; i++) {
387     memcpy(&CodeDest[DestPtr],&CodeBuff[SrcPtr],NxCopy);
388 doda 8445 #if UNICODE_INTERNAL_BUFF
389     memcpyW(&CodeDestW[DestPtr],&CodeBuffW[SrcPtr],NxCopy);
390     #endif
391 maya 3393 memcpy(&AttrDest[DestPtr],&AttrBuff[SrcPtr],NxCopy);
392     memcpy(&AttrDest2[DestPtr],&AttrBuff2[SrcPtr],NxCopy);
393     memcpy(&AttrDestFG[DestPtr],&AttrBuffFG[SrcPtr],NxCopy);
394     memcpy(&AttrDestBG[DestPtr],&AttrBuffBG[SrcPtr],NxCopy);
395 doda 3766 if (AttrDest[DestPtr+NxCopy-1] & AttrKanji) {
396     CodeDest[DestPtr+NxCopy-1] = ' ';
397     AttrDest[DestPtr+NxCopy-1] ^= AttrKanji;
398     }
399 maya 3393 SrcPtr = NextLinePtr(SrcPtr);
400     DestPtr = DestPtr + (LONG)Nx;
401     }
402     FreeBuffer();
403     }
404     else {
405     LockOld = 0;
406     NyCopy = NumOfLines;
407     Selected = FALSE;
408     }
409 maya 3227
410 maya 3393 if (Selected) {
411     SelectStart.y = SelectStart.y - BuffEnd + NyCopy;
412     SelectEnd.y = SelectEnd.y - BuffEnd + NyCopy;
413     if (SelectStart.y < 0) {
414     SelectStart.y = 0;
415     SelectStart.x = 0;
416     }
417     if (SelectEnd.y<0) {
418     SelectEnd.x = 0;
419     SelectEnd.y = 0;
420     }
421 maya 3227
422 maya 3393 Selected = (SelectEnd.y > SelectStart.y) ||
423 zmatsuo 8411 ((SelectEnd.y == SelectStart.y) &&
424 maya 3393 (SelectEnd.x > SelectStart.x));
425     }
426 maya 3227
427 doda 8445 CodeBuff = CodeDest;
428     AttrBuff = AttrDest;
429     AttrBuff2 = AttrDest2;
430     AttrBuffFG = AttrDestFG;
431     AttrBuffBG = AttrDestBG;
432     #if UNICODE_INTERNAL_BUFF
433     CodeBuffW = CodeDestW;
434     #endif
435 maya 3393 BufferSize = NewSize;
436     NumOfLinesInBuff = Ny;
437     BuffStartAbs = 0;
438     BuffEnd = NyCopy;
439 maya 3227
440 maya 3393 if (BuffEnd==NumOfLinesInBuff) {
441     BuffEndAbs = 0;
442     }
443     else {
444     BuffEndAbs = BuffEnd;
445     }
446 maya 3227
447 maya 3393 PageStart = BuffEnd - NumOfLines;
448    
449     LinePtr = 0;
450     if (LockOld>0) {
451     CodeLine = CodeBuff;
452 doda 8445 #if UNICODE_INTERNAL_BUFF
453     CodeLineW = CodeBuffW;
454     #endif
455 maya 3393 AttrLine = AttrBuff;
456     AttrLine2 = AttrBuff2;
457     AttrLineFG = AttrBuffFG;
458     AttrLineBG = AttrBuffBG;
459     }
460     else {
461 doda 8445 ;
462 maya 3393 }
463     BuffLock = LockOld;
464    
465     return TRUE;
466 doda 3686
467     allocate_error:
468 doda 8445 if (CodeDest) free(CodeDest);
469     if (AttrDest) free(AttrDest);
470     if (AttrDest2) free(AttrDest2);
471     if (AttrDestFG) free(AttrDestFG);
472     if (AttrDestBG) free(AttrDestBG);
473     #if UNICODE_INTERNAL_BUFF
474     if (CodeDestW) free(CodeDestW);
475     #endif
476 doda 3686 return FALSE;
477 maya 3227 }
478    
479     void InitBuffer()
480     {
481 maya 3393 int Ny;
482 maya 3227
483 maya 3393 /* setup terminal */
484     NumOfColumns = ts.TerminalWidth;
485     NumOfLines = ts.TerminalHeight;
486 maya 3227
487 doda 6785 if (NumOfColumns <= 0)
488     NumOfColumns = 80;
489     else if (NumOfColumns > TermWidthMax)
490     NumOfColumns = TermWidthMax;
491    
492     if (NumOfLines <= 0)
493     NumOfLines = 24;
494     else if (NumOfLines > TermHeightMax)
495     NumOfLines = TermHeightMax;
496    
497 maya 3393 /* setup window */
498     if (ts.EnableScrollBuff>0) {
499     if (ts.ScrollBuffSize < NumOfLines) {
500     ts.ScrollBuffSize = NumOfLines;
501     }
502     Ny = ts.ScrollBuffSize;
503     }
504     else {
505     Ny = NumOfLines;
506     }
507 maya 3227
508 maya 3393 if (! ChangeBuffer(NumOfColumns,Ny)) {
509     PostQuitMessage(0);
510     }
511 maya 3227
512 maya 3393 if (ts.EnableScrollBuff>0) {
513     ts.ScrollBuffSize = NumOfLinesInBuff;
514     }
515 maya 3227
516 maya 3393 StatusLine = 0;
517 maya 3227 }
518    
519 doda 8445 static void NewLine(int Line)
520 maya 3227 {
521 maya 3393 LinePtr = GetLinePtr(Line);
522     CodeLine = &CodeBuff[LinePtr];
523     AttrLine = &AttrBuff[LinePtr];
524     AttrLine2 = &AttrBuff2[LinePtr];
525     AttrLineFG = &AttrBuffFG[LinePtr];
526     AttrLineBG = &AttrBuffBG[LinePtr];
527 doda 8445 #if UNICODE_INTERNAL_BUFF
528     CodeLineW = &CodeBuffW[LinePtr];
529     #endif
530 maya 3227 }
531    
532     void LockBuffer()
533     {
534 maya 3393 BuffLock++;
535     if (BuffLock>1) {
536     return;
537     }
538     NewLine(PageStart+CursorY);
539 maya 3227 }
540    
541     void UnlockBuffer()
542     {
543 maya 3393 if (BuffLock==0) {
544     return;
545     }
546     BuffLock--;
547     if (BuffLock>0) {
548     return;
549     }
550 maya 3227 }
551    
552     void FreeBuffer()
553     {
554 maya 3393 BuffLock = 1;
555     UnlockBuffer();
556 doda 8445 if (CodeBuff!=NULL) {
557     free(CodeBuff);
558     CodeBuff = NULL;
559 maya 3393 }
560 doda 8445 #if UNICODE_INTERNAL_BUFF
561     if (CodeBuffW != NULL) {
562     free(CodeBuffW);
563     CodeBuffW = NULL;
564 maya 3393 }
565 doda 8445 #endif
566     if (AttrBuff!=NULL) {
567     free(AttrBuff);
568     AttrBuff = NULL;
569 maya 3393 }
570 doda 8445 if (AttrBuff2!=NULL) {
571     free(AttrBuff2);
572     AttrBuff2 = NULL;
573 maya 3393 }
574 doda 8445 if (AttrBuffFG!=NULL) {
575     free(AttrBuffFG);
576     AttrBuffFG = NULL;
577 maya 3393 }
578 doda 8445 if (AttrBuffBG!=NULL) {
579     free(AttrBuffBG);
580     AttrBuffBG = NULL;
581     }
582 maya 3227 }
583    
584     void BuffAllSelect()
585     {
586     SelectStart.x = 0;
587     SelectStart.y = 0;
588     SelectEnd.x = 0;
589     SelectEnd.y = BuffEnd;
590     // SelectEnd.x = NumOfColumns;
591     // SelectEnd.y = BuffEnd - 1;
592 doda 8400 Selecting = TRUE;
593 maya 3227 }
594    
595     void BuffScreenSelect()
596     {
597     int X, Y;
598     DispConvWinToScreen(0, 0, &X, &Y, NULL);
599     SelectStart.x = X;
600     SelectStart.y = Y + PageStart;
601     SelectEnd.x = 0;
602     SelectEnd.y = SelectStart.y + NumOfLines;
603     // SelectEnd.x = X + NumOfColumns;
604     // SelectEnd.y = Y + PageStart + NumOfLines - 1;
605 doda 8400 Selecting = TRUE;
606 maya 3227 }
607    
608     void BuffCancelSelection()
609     {
610     SelectStart.x = 0;
611     SelectStart.y = 0;
612     SelectEnd.x = 0;
613     SelectEnd.y = 0;
614 doda 8400 Selecting = FALSE;
615 maya 3227 }
616    
617     void BuffReset()
618     // Reset buffer status. don't update real display
619     // called by ResetTerminal()
620     {
621 maya 3393 int i;
622 maya 3227
623 maya 3393 /* Cursor */
624     NewLine(PageStart);
625     WinOrgX = 0;
626     WinOrgY = 0;
627     NewOrgX = 0;
628     NewOrgY = 0;
629 maya 3227
630 maya 3393 /* Top/bottom margin */
631     CursorTop = 0;
632     CursorBottom = NumOfLines-1;
633 doda 5324 CursorLeftM = 0;
634     CursorRightM = NumOfColumns-1;
635 maya 3227
636 maya 3393 /* Tab stops */
637     NTabStops = (NumOfColumns-1) >> 3;
638     for (i=1 ; i<=NTabStops ; i++) {
639 doda 8445 TabStops[i-1] = (WORD)(i*8);
640 maya 3393 }
641 maya 3227
642 maya 3393 /* Initialize text selection region */
643     SelectStart.x = 0;
644     SelectStart.y = 0;
645     SelectEnd = SelectStart;
646     SelectEndOld = SelectStart;
647     Selected = FALSE;
648 maya 3227
649 maya 3393 StrChangeCount = 0;
650     Wrap = FALSE;
651     StatusLine = 0;
652 maya 3227
653 maya 3393 SeveralPageSelect = FALSE; // yutaka
654 doda 3745
655     /* Alternate Screen Buffer */
656     BuffDiscardSavedScreen();
657 maya 3227 }
658    
659     void BuffScroll(int Count, int Bottom)
660     {
661 maya 3393 int i, n;
662     LONG SrcPtr, DestPtr;
663     int BuffEndOld;
664 maya 3227
665 maya 3393 if (Count>NumOfLinesInBuff) {
666     Count = NumOfLinesInBuff;
667     }
668 maya 3227
669 maya 3393 DestPtr = GetLinePtr(PageStart+NumOfLines-1+Count);
670     n = Count;
671     if (Bottom<NumOfLines-1) {
672     SrcPtr = GetLinePtr(PageStart+NumOfLines-1);
673     for (i=NumOfLines-1; i>=Bottom+1; i--) {
674     memcpy(&(CodeBuff[DestPtr]),&(CodeBuff[SrcPtr]),NumOfColumns);
675 doda 8445 #if UNICODE_INTERNAL_BUFF
676     memcpyW(&(CodeBuffW[DestPtr]),&(CodeBuffW[SrcPtr]),NumOfColumns);
677     #endif
678 maya 3393 memcpy(&(AttrBuff[DestPtr]),&(AttrBuff[SrcPtr]),NumOfColumns);
679     memcpy(&(AttrBuff2[DestPtr]),&(AttrBuff2[SrcPtr]),NumOfColumns);
680     memcpy(&(AttrBuffFG[DestPtr]),&(AttrBuffFG[SrcPtr]),NumOfColumns);
681     memcpy(&(AttrBuffBG[DestPtr]),&(AttrBuffBG[SrcPtr]),NumOfColumns);
682     memset(&(CodeBuff[SrcPtr]),0x20,NumOfColumns);
683 doda 8445 #if UNICODE_INTERNAL_BUFF
684     memsetW(&(CodeBuffW[SrcPtr]),0x20,NumOfColumns);
685     #endif
686 maya 3393 memset(&(AttrBuff[SrcPtr]),AttrDefault,NumOfColumns);
687 doda 4070 memset(&(AttrBuff2[SrcPtr]),CurCharAttr.Attr2 & Attr2ColorMask, NumOfColumns);
688 maya 3393 memset(&(AttrBuffFG[SrcPtr]),CurCharAttr.Fore,NumOfColumns);
689     memset(&(AttrBuffBG[SrcPtr]),CurCharAttr.Back,NumOfColumns);
690     SrcPtr = PrevLinePtr(SrcPtr);
691     DestPtr = PrevLinePtr(DestPtr);
692     n--;
693     }
694     }
695     for (i = 1 ; i <= n ; i++) {
696     memset(&CodeBuff[DestPtr],0x20,NumOfColumns);
697 doda 8445 #if UNICODE_INTERNAL_BUFF
698     memsetW(&CodeBuffW[DestPtr],0x20,NumOfColumns);
699     #endif
700 maya 3393 memset(&AttrBuff[DestPtr],AttrDefault,NumOfColumns);
701 doda 4070 memset(&AttrBuff2[DestPtr],CurCharAttr.Attr2 & Attr2ColorMask, NumOfColumns);
702 maya 3393 memset(&AttrBuffFG[DestPtr],CurCharAttr.Fore,NumOfColumns);
703     memset(&AttrBuffBG[DestPtr],CurCharAttr.Back,NumOfColumns);
704     DestPtr = PrevLinePtr(DestPtr);
705     }
706 maya 3227
707 maya 3393 BuffEndAbs = BuffEndAbs + Count;
708     if (BuffEndAbs >= NumOfLinesInBuff) {
709     BuffEndAbs = BuffEndAbs - NumOfLinesInBuff;
710     }
711     BuffEndOld = BuffEnd;
712     BuffEnd = BuffEnd + Count;
713     if (BuffEnd >= NumOfLinesInBuff) {
714     BuffEnd = NumOfLinesInBuff;
715     BuffStartAbs = BuffEndAbs;
716     }
717     PageStart = BuffEnd-NumOfLines;
718 maya 3227
719 maya 3393 if (Selected) {
720     SelectStart.y = SelectStart.y - Count + BuffEnd - BuffEndOld;
721     SelectEnd.y = SelectEnd.y - Count + BuffEnd - BuffEndOld;
722     if ( SelectStart.y<0 ) {
723     SelectStart.x = 0;
724     SelectStart.y = 0;
725     }
726     if ( SelectEnd.y<0 ) {
727     SelectEnd.x = 0;
728     SelectEnd.y = 0;
729     }
730     Selected = (SelectEnd.y > SelectStart.y) ||
731     ((SelectEnd.y==SelectStart.y) &&
732     (SelectEnd.x > SelectStart.x));
733     }
734 maya 3227
735 maya 3393 NewLine(PageStart+CursorY);
736 maya 3227 }
737    
738     void NextLine()
739     {
740 maya 3393 LinePtr = NextLinePtr(LinePtr);
741     CodeLine = &CodeBuff[LinePtr];
742     AttrLine = &AttrBuff[LinePtr];
743     AttrLine2 = &AttrBuff2[LinePtr];
744     AttrLineFG = &AttrBuffFG[LinePtr];
745     AttrLineBG = &AttrBuffBG[LinePtr];
746 doda 8445 #if UNICODE_INTERNAL_BUFF
747     CodeLineW = &CodeBuffW[LinePtr];
748     #endif
749 maya 3227 }
750    
751     void PrevLine()
752     {
753 maya 3393 LinePtr = PrevLinePtr(LinePtr);
754     CodeLine = &CodeBuff[LinePtr];
755     AttrLine = &AttrBuff[LinePtr];
756     AttrLine2 = &AttrBuff2[LinePtr];
757     AttrLineFG = &AttrBuffFG[LinePtr];
758     AttrLineBG = &AttrBuffBG[LinePtr];
759 doda 8445 #if UNICODE_INTERNAL_BUFF
760     CodeLineW = &CodeBuffW[LinePtr];
761     #endif
762 maya 3227 }
763    
764     // If cursor is on left/right half of a Kanji, erase it.
765     // LR: left(0)/right(1) flag
766 doda 8445 // LR 0 �J�[�\��������������
767     // 1 �J�[�\�����������E��
768     static void EraseKanji(int LR)
769     {
770     #if UNICODE_INTERNAL_BUFF
771     buff_char_t *p;
772     int bx;
773     if (CursorX < LR) {
774     // �S�p������������
775     return;
776     }
777     bx = CursorX-LR;
778     p = &CodeLineW[bx];
779     if (IsBuffFullWidth(p)) {
780     // �S�p��������
781     BuffSetChar(p, ' ', 'H');
782     CodeLine[bx] = 0x20;
783     AttrLine[bx] = CurCharAttr.Attr;
784     AttrLine2[bx] = CurCharAttr.Attr2;
785     AttrLineFG[bx] = CurCharAttr.Fore;
786     AttrLineBG[bx] = CurCharAttr.Back;
787     if (bx+1 < NumOfColumns) {
788     BuffSetChar(p + 1, ' ', 'H');
789     CodeLine[bx+1] = 0x20;
790     AttrLine[bx+1] = CurCharAttr.Attr;
791     AttrLine2[bx+1] = CurCharAttr.Attr2;
792     AttrLineFG[bx+1] = CurCharAttr.Fore;
793     AttrLineBG[bx+1] = CurCharAttr.Back;
794     }
795     }
796     #else
797 maya 3393 if ((CursorX-LR>=0) &&
798     ((AttrLine[CursorX-LR] & AttrKanji) != 0)) {
799     CodeLine[CursorX-LR] = 0x20;
800     AttrLine[CursorX-LR] = CurCharAttr.Attr;
801     AttrLine2[CursorX-LR] = CurCharAttr.Attr2;
802     AttrLineFG[CursorX-LR] = CurCharAttr.Fore;
803     AttrLineBG[CursorX-LR] = CurCharAttr.Back;
804     if (CursorX-LR+1 < NumOfColumns) {
805     CodeLine[CursorX-LR+1] = 0x20;
806     AttrLine[CursorX-LR+1] = CurCharAttr.Attr;
807     AttrLine2[CursorX-LR+1] = CurCharAttr.Attr2;
808     AttrLineFG[CursorX-LR+1] = CurCharAttr.Fore;
809     AttrLineBG[CursorX-LR+1] = CurCharAttr.Back;
810     }
811     }
812 doda 8445 #endif
813 maya 3227 }
814    
815 doda 5371 void EraseKanjiOnLRMargin(LONG ptr, int count)
816     {
817     int i;
818     LONG pos;
819    
820     if (count < 1)
821     return;
822    
823     for (i=0; i<count; i++) {
824     pos = ptr + CursorLeftM-1;
825     if (CursorLeftM>0 && (AttrBuff[pos] & AttrKanji)) {
826     CodeBuff[pos] = 0x20;
827 doda 8445 #if UNICODE_INTERNAL_BUFF
828     BuffSetChar(&CodeBuffW[pos], 0x20, 'H');
829     #endif
830 doda 5371 AttrBuff[pos] &= ~AttrKanji;
831     pos++;
832     CodeBuff[pos] = 0x20;
833 doda 8445 #if UNICODE_INTERNAL_BUFF
834     BuffSetChar(&CodeBuffW[pos], 0x20, 'H');
835     #endif
836 doda 5371 AttrBuff[pos] &= ~AttrKanji;
837     }
838     pos = ptr + CursorRightM;
839     if (CursorRightM < NumOfColumns-1 && (AttrBuff[pos] & AttrKanji)) {
840     CodeBuff[pos] = 0x20;
841 doda 8445 #if UNICODE_INTERNAL_BUFF
842     BuffSetChar(&CodeBuffW[pos], 0x20, 'H');
843     #endif
844 doda 5371 AttrBuff[pos] &= ~AttrKanji;
845     pos++;
846     CodeBuff[pos] = 0x20;
847 doda 8445 #if UNICODE_INTERNAL_BUFF
848     BuffSetChar(&CodeBuffW[pos], 0x20, 'H');
849     #endif
850 doda 5371 AttrBuff[pos] &= ~AttrKanji;
851     }
852     ptr = NextLinePtr(ptr);
853     }
854     }
855    
856 doda 8445 // Insert space characters at the current position
857     // Count: Number of characters to be inserted
858     #if UNICODE_INTERNAL_BUFF
859 maya 3227 void BuffInsertSpace(int Count)
860 doda 8445 {
861     int MoveLen;
862     int extr = 0;
863     int sx;
864     buff_char_t *b;
865    
866     if (CursorX < CursorLeftM || CursorX > CursorRightM)
867     return;
868    
869     NewLine(PageStart + CursorY);
870    
871     sx = CursorX;
872     b = &CodeLineW[CursorX];
873     if (IsBuffPadding(b)) {
874     /* if cursor is on right half of a kanji, erase the kanji */
875     BuffSetChar(b - 1, ' ', 'H');
876     BuffSetChar(b, ' ', 'H');
877     AttrLine[CursorX] &= ~AttrKanji;
878     sx--;
879     extr++;
880     }
881    
882     if (CursorRightM < NumOfColumns - 1 && (AttrLine[CursorRightM] & AttrKanji)) {
883     CodeLine[CursorRightM + 1] = 0x20;
884     BuffSetChar(&CodeLineW[CursorRightM + 1], 0x20, 'H');
885     AttrLine[CursorRightM + 1] &= ~AttrKanji;
886     extr++;
887     }
888    
889     if (Count > CursorRightM + 1 - CursorX)
890     Count = CursorRightM + 1 - CursorX;
891    
892     MoveLen = CursorRightM + 1 - CursorX - Count;
893    
894     if (MoveLen > 0) {
895     memmove(&(CodeLine[CursorX + Count]), &(CodeLine[CursorX]), MoveLen);
896     memmoveW(&(CodeLineW[CursorX + Count]), &(CodeLineW[CursorX]), MoveLen);
897     memmove(&(AttrLine[CursorX + Count]), &(AttrLine[CursorX]), MoveLen);
898     memmove(&(AttrLine2[CursorX + Count]), &(AttrLine2[CursorX]), MoveLen);
899     memmove(&(AttrLineFG[CursorX + Count]), &(AttrLineFG[CursorX]), MoveLen);
900     memmove(&(AttrLineBG[CursorX + Count]), &(AttrLineBG[CursorX]), MoveLen);
901     }
902     memset(&(CodeLine[CursorX]), 0x20, Count);
903     memsetW(&(CodeLineW[CursorX]), 0x20, Count);
904     memset(&(AttrLine[CursorX]), AttrDefault, Count);
905     memset(&(AttrLine2[CursorX]), CurCharAttr.Attr2 & Attr2ColorMask, Count);
906     memset(&(AttrLineFG[CursorX]), CurCharAttr.Fore, Count);
907     memset(&(AttrLineBG[CursorX]), CurCharAttr.Back, Count);
908     /* last char in current line is kanji first? */
909     if ((AttrLine[CursorRightM] & AttrKanji) != 0) {
910     /* then delete it */
911     CodeLine[CursorRightM] = 0x20;
912     BuffSetChar(&CodeLineW[CursorRightM], 0x20, 'H');
913     AttrLine[CursorRightM] &= ~AttrKanji;
914     }
915     BuffUpdateRect(sx, CursorY, CursorRightM + extr, CursorY);
916     }
917     #else
918     void BuffInsertSpace(int Count)
919 maya 3227 // Insert space characters at the current position
920     // Count: Number of characters to be inserted
921     {
922 doda 5326 int MoveLen;
923 doda 5371 int extr=0;
924 doda 5324
925 doda 5326 if (CursorX < CursorLeftM || CursorX > CursorRightM)
926     return;
927    
928 maya 3393 NewLine(PageStart+CursorY);
929 maya 3227
930 doda 5324 if (ts.Language==IdJapanese || ts.Language==IdKorean || ts.Language==IdUtf8)
931 maya 3393 EraseKanji(1); /* if cursor is on right half of a kanji, erase the kanji */
932 maya 3227
933 doda 5371 if (CursorRightM < NumOfColumns-1 && (AttrLine[CursorRightM] & AttrKanji)) {
934     CodeLine[CursorRightM+1] = 0x20;
935 doda 8445 #if UNICODE_INTERNAL_BUFF
936     BuffSetChar(&CodeLineW[CursorRightM + 1], 0x20, 'H');
937     #endif
938 doda 5371 AttrLine[CursorRightM+1] &= ~AttrKanji;
939     extr = 1;
940     }
941    
942 doda 5326 if (Count > CursorRightM + 1 - CursorX)
943     Count = CursorRightM + 1 - CursorX;
944 doda 5324
945 doda 5326 MoveLen = CursorRightM + 1 - CursorX - Count;
946 doda 5324
947     if (MoveLen > 0) {
948     memmove(&(CodeLine[CursorX+Count]), &(CodeLine[CursorX]), MoveLen);
949 doda 8445 #if UNICODE_INTERNAL_BUFF
950     memmoveW(&(CodeLineW[CursorX+Count]), &(CodeLineW[CursorX]), MoveLen);
951     #endif
952 doda 5324 memmove(&(AttrLine[CursorX+Count]), &(AttrLine[CursorX]), MoveLen);
953     memmove(&(AttrLine2[CursorX+Count]), &(AttrLine2[CursorX]), MoveLen);
954     memmove(&(AttrLineFG[CursorX+Count]), &(AttrLineFG[CursorX]), MoveLen);
955     memmove(&(AttrLineBG[CursorX+Count]), &(AttrLineBG[CursorX]), MoveLen);
956 maya 3393 }
957 doda 5324 memset(&(CodeLine[CursorX]), 0x20, Count);
958 doda 8445 #if UNICODE_INTERNAL_BUFF
959     memsetW(&(CodeLineW[CursorX]), 0x20, Count);
960     #endif
961 doda 5324 memset(&(AttrLine[CursorX]), AttrDefault, Count);
962     memset(&(AttrLine2[CursorX]), CurCharAttr.Attr2 & Attr2ColorMask, Count);
963     memset(&(AttrLineFG[CursorX]), CurCharAttr.Fore, Count);
964     memset(&(AttrLineBG[CursorX]), CurCharAttr.Back, Count);
965 maya 3393 /* last char in current line is kanji first? */
966 doda 5326 if ((AttrLine[CursorRightM] & AttrKanji) != 0) {
967 maya 3393 /* then delete it */
968 doda 5326 CodeLine[CursorRightM] = 0x20;
969 doda 8445 #if UNICODE_INTERNAL_BUFF
970     BuffSetChar(&CodeLineW[CursorRightM], 0x20, 'H');
971     #endif
972 doda 5371 AttrLine[CursorRightM] &= ~AttrKanji;
973 maya 3393 }
974 doda 5371 BuffUpdateRect(CursorX, CursorY, CursorRightM+extr, CursorY);
975 maya 3227 }
976 doda 8445 #endif
977 maya 3227
978     void BuffEraseCurToEnd()
979     // Erase characters from cursor to the end of screen
980     {
981 maya 3393 LONG TmpPtr;
982     int offset;
983     int i, YEnd;
984 maya 3227
985 maya 3393 NewLine(PageStart+CursorY);
986 doda 3416 if (ts.Language==IdJapanese || ts.Language==IdKorean || ts.Language==IdUtf8) {
987 maya 3393 EraseKanji(1); /* if cursor is on right half of a kanji, erase the kanji */
988     }
989     offset = CursorX;
990     TmpPtr = GetLinePtr(PageStart+CursorY);
991     YEnd = NumOfLines-1;
992 doda 5324 if (StatusLine && !isCursorOnStatusLine) {
993 maya 3393 YEnd--;
994     }
995     for (i = CursorY ; i <= YEnd ; i++) {
996     memset(&(CodeBuff[TmpPtr+offset]),0x20,NumOfColumns-offset);
997 doda 8445 #if UNICODE_INTERNAL_BUFF
998     memsetW(&(CodeBuffW[TmpPtr+offset]),0x20,NumOfColumns-offset);
999     #endif
1000 maya 3393 memset(&(AttrBuff[TmpPtr+offset]),AttrDefault,NumOfColumns-offset);
1001 doda 4070 memset(&(AttrBuff2[TmpPtr+offset]),CurCharAttr.Attr2 & Attr2ColorMask, NumOfColumns-offset);
1002 maya 3393 memset(&(AttrBuffFG[TmpPtr+offset]),CurCharAttr.Fore,NumOfColumns-offset);
1003     memset(&(AttrBuffBG[TmpPtr+offset]),CurCharAttr.Back,NumOfColumns-offset);
1004     offset = 0;
1005     TmpPtr = NextLinePtr(TmpPtr);
1006     }
1007     /* update window */
1008     DispEraseCurToEnd(YEnd);
1009 maya 3227 }
1010    
1011     void BuffEraseHomeToCur()
1012     // Erase characters from home to cursor
1013     {
1014 maya 3393 LONG TmpPtr;
1015     int offset;
1016     int i, YHome;
1017 maya 3227
1018 maya 3393 NewLine(PageStart+CursorY);
1019 doda 3416 if (ts.Language==IdJapanese || ts.Language==IdKorean || ts.Language==IdUtf8) {
1020 maya 3393 EraseKanji(0); /* if cursor is on left half of a kanji, erase the kanji */
1021     }
1022     offset = NumOfColumns;
1023 doda 5324 if (isCursorOnStatusLine) {
1024 maya 3393 YHome = CursorY;
1025     }
1026     else {
1027     YHome = 0;
1028     }
1029     TmpPtr = GetLinePtr(PageStart+YHome);
1030     for (i = YHome ; i <= CursorY ; i++) {
1031     if (i==CursorY) {
1032     offset = CursorX+1;
1033     }
1034     memset(&(CodeBuff[TmpPtr]),0x20,offset);
1035 doda 8445 #if UNICODE_INTERNAL_BUFF
1036     memsetW(&(CodeBuffW[TmpPtr]),0x20,offset);
1037     #endif
1038 maya 3393 memset(&(AttrBuff[TmpPtr]),AttrDefault,offset);
1039 doda 4070 memset(&(AttrBuff2[TmpPtr]),CurCharAttr.Attr2 & Attr2ColorMask, offset);
1040 maya 3393 memset(&(AttrBuffFG[TmpPtr]),CurCharAttr.Fore,offset);
1041     memset(&(AttrBuffBG[TmpPtr]),CurCharAttr.Back,offset);
1042     TmpPtr = NextLinePtr(TmpPtr);
1043     }
1044 maya 3227
1045 maya 3393 /* update window */
1046     DispEraseHomeToCur(YHome);
1047 maya 3227 }
1048    
1049     void BuffInsertLines(int Count, int YEnd)
1050     // Insert lines at current position
1051     // Count: number of lines to be inserted
1052     // YEnd: bottom line number of scroll region (screen coordinate)
1053     {
1054 doda 5324 int i, linelen;
1055 doda 5371 int extl=0, extr=0;
1056 maya 3393 LONG SrcPtr, DestPtr;
1057 maya 3227
1058 maya 3393 BuffUpdateScroll();
1059 maya 3227
1060 doda 5371 if (CursorLeftM > 0)
1061     extl = 1;
1062     if (CursorRightM < NumOfColumns-1)
1063     extr = 1;
1064     if (extl || extr)
1065     EraseKanjiOnLRMargin(GetLinePtr(PageStart+CursorY), YEnd-CursorY+1);
1066    
1067 doda 5324 SrcPtr = GetLinePtr(PageStart+YEnd-Count) + CursorLeftM;
1068     DestPtr = GetLinePtr(PageStart+YEnd) + CursorLeftM;
1069     linelen = CursorRightM - CursorLeftM + 1;
1070 maya 3393 for (i= YEnd-Count ; i>=CursorY ; i--) {
1071 doda 5324 memcpy(&(CodeBuff[DestPtr]), &(CodeBuff[SrcPtr]), linelen);
1072 doda 8445 #if UNICODE_INTERNAL_BUFF
1073     memcpyW(&(CodeBuffW[DestPtr]), &(CodeBuffW[SrcPtr]), linelen);
1074     #endif
1075 doda 5324 memcpy(&(AttrBuff[DestPtr]), &(AttrBuff[SrcPtr]), linelen);
1076     memcpy(&(AttrBuff2[DestPtr]), &(AttrBuff2[SrcPtr]), linelen);
1077     memcpy(&(AttrBuffFG[DestPtr]), &(AttrBuffFG[SrcPtr]), linelen);
1078     memcpy(&(AttrBuffBG[DestPtr]), &(AttrBuffBG[SrcPtr]), linelen);
1079 maya 3393 SrcPtr = PrevLinePtr(SrcPtr);
1080     DestPtr = PrevLinePtr(DestPtr);
1081     }
1082     for (i = 1 ; i <= Count ; i++) {
1083 doda 5324 memset(&(CodeBuff[DestPtr]), 0x20, linelen);
1084 doda 8445 #if UNICODE_INTERNAL_BUFF
1085     memsetW(&(CodeBuffW[DestPtr]), 0x20, linelen);
1086     #endif
1087 doda 5324 memset(&(AttrBuff[DestPtr]), AttrDefault, linelen);
1088     memset(&(AttrBuff2[DestPtr]), CurCharAttr.Attr2 & Attr2ColorMask, linelen);
1089     memset(&(AttrBuffFG[DestPtr]), CurCharAttr.Fore, linelen);
1090     memset(&(AttrBuffBG[DestPtr]), CurCharAttr.Back, linelen);
1091 maya 3393 DestPtr = PrevLinePtr(DestPtr);
1092     }
1093 maya 3227
1094 doda 5324 if (CursorLeftM > 0 || CursorRightM < NumOfColumns-1 || !DispInsertLines(Count, YEnd)) {
1095 doda 5371 BuffUpdateRect(CursorLeftM-extl, CursorY, CursorRightM+extr, YEnd);
1096 maya 3393 }
1097 maya 3227 }
1098    
1099     void BuffEraseCharsInLine(int XStart, int Count)
1100     // erase characters in the current line
1101     // XStart: start position of erasing
1102     // Count: number of characters to be erased
1103     {
1104 maya 3393 BOOL LineContinued=FALSE;
1105 doda 3312
1106 maya 3393 if (ts.EnableContinuedLineCopy && XStart == 0 && (AttrLine[0] & AttrLineContinued)) {
1107     LineContinued = TRUE;
1108     }
1109 doda 3312
1110 doda 3416 if (ts.Language==IdJapanese || ts.Language==IdKorean || ts.Language==IdUtf8) {
1111 maya 3393 EraseKanji(1); /* if cursor is on right half of a kanji, erase the kanji */
1112     }
1113 maya 3227
1114 maya 3393 NewLine(PageStart+CursorY);
1115     memset(&(CodeLine[XStart]),0x20,Count);
1116 doda 8445 #if UNICODE_INTERNAL_BUFF
1117     memsetW(&(CodeLineW[XStart]),0x20,Count);
1118     #endif
1119 maya 3393 memset(&(AttrLine[XStart]),AttrDefault,Count);
1120 doda 4070 memset(&(AttrLine2[XStart]),CurCharAttr.Attr2 & Attr2ColorMask, Count);
1121 maya 3393 memset(&(AttrLineFG[XStart]),CurCharAttr.Fore,Count);
1122     memset(&(AttrLineBG[XStart]),CurCharAttr.Back,Count);
1123 maya 3227
1124 maya 3393 if (ts.EnableContinuedLineCopy) {
1125     if (LineContinued) {
1126     BuffLineContinued(TRUE);
1127     }
1128    
1129     if (XStart + Count >= NumOfColumns) {
1130     AttrBuff[NextLinePtr(LinePtr)] &= ~AttrLineContinued;
1131     }
1132     }
1133 doda 3312
1134 maya 3393 DispEraseCharsInLine(XStart, Count);
1135 maya 3227 }
1136    
1137     void BuffDeleteLines(int Count, int YEnd)
1138     // Delete lines from current line
1139     // Count: number of lines to be deleted
1140     // YEnd: bottom line number of scroll region (screen coordinate)
1141     {
1142 doda 5324 int i, linelen;
1143 doda 5371 int extl=0, extr=0;
1144 maya 3393 LONG SrcPtr, DestPtr;
1145 maya 3227
1146 maya 3393 BuffUpdateScroll();
1147 maya 3227
1148 doda 5371 if (CursorLeftM > 0)
1149     extl = 1;
1150     if (CursorRightM < NumOfColumns-1)
1151     extr = 1;
1152     if (extl || extr)
1153     EraseKanjiOnLRMargin(GetLinePtr(PageStart+CursorY), YEnd-CursorY+1);
1154    
1155 doda 5324 SrcPtr = GetLinePtr(PageStart+CursorY+Count) + (LONG)CursorLeftM;
1156     DestPtr = GetLinePtr(PageStart+CursorY) + (LONG)CursorLeftM;
1157     linelen = CursorRightM - CursorLeftM + 1;
1158 maya 3393 for (i=CursorY ; i<= YEnd-Count ; i++) {
1159 doda 5324 memcpy(&(CodeBuff[DestPtr]), &(CodeBuff[SrcPtr]), linelen);
1160 doda 8445 #if UNICODE_INTERNAL_BUFF
1161     memcpyW(&(CodeBuffW[DestPtr]), &(CodeBuffW[SrcPtr]), linelen);
1162     #endif
1163 doda 5324 memcpy(&(AttrBuff[DestPtr]), &(AttrBuff[SrcPtr]), linelen);
1164     memcpy(&(AttrBuff2[DestPtr]), &(AttrBuff2[SrcPtr]), linelen);
1165     memcpy(&(AttrBuffFG[DestPtr]), &(AttrBuffFG[SrcPtr]), linelen);
1166     memcpy(&(AttrBuffBG[DestPtr]), &(AttrBuffBG[SrcPtr]), linelen);
1167 maya 3393 SrcPtr = NextLinePtr(SrcPtr);
1168     DestPtr = NextLinePtr(DestPtr);
1169     }
1170     for (i = YEnd+1-Count ; i<=YEnd ; i++) {
1171 doda 5324 memset(&(CodeBuff[DestPtr]), 0x20, linelen);
1172 doda 8445 #if UNICODE_INTERNAL_BUFF
1173     memsetW(&(CodeBuffW[DestPtr]), 0x20, linelen);
1174     #endif
1175 doda 5324 memset(&(AttrBuff[DestPtr]), AttrDefault, linelen);
1176     memset(&(AttrBuff2[DestPtr]), CurCharAttr.Attr2 & Attr2ColorMask, linelen);
1177     memset(&(AttrBuffFG[DestPtr]), CurCharAttr.Fore, linelen);
1178     memset(&(AttrBuffBG[DestPtr]), CurCharAttr.Back, linelen);
1179 maya 3393 DestPtr = NextLinePtr(DestPtr);
1180     }
1181 maya 3227
1182 doda 5324 if (CursorLeftM > 0 || CursorRightM < NumOfColumns-1 || ! DispDeleteLines(Count,YEnd)) {
1183 doda 5371 BuffUpdateRect(CursorLeftM-extl, CursorY, CursorRightM+extr, YEnd);
1184 maya 3393 }
1185 maya 3227 }
1186    
1187     // Delete characters in current line from cursor
1188     // Count: number of characters to be deleted
1189 doda 8445 #if UNICODE_INTERNAL_BUFF
1190     void BuffDeleteChars(int Count)
1191 maya 3227 {
1192 doda 5325 int MoveLen;
1193 doda 8445 int extr = 0;
1194     buff_char_t *b;
1195    
1196     if (Count > CursorRightM + 1 - CursorX)
1197     Count = CursorRightM + 1 - CursorX;
1198    
1199     if (CursorX < CursorLeftM || CursorX > CursorRightM)
1200     return;
1201    
1202     NewLine(PageStart + CursorY);
1203    
1204     b = &CodeLineW[CursorX];
1205    
1206     if (IsBuffPadding(b)) {
1207     // �S�p���E���A�S�p���X�y�[�X���u��������
1208     BuffSetChar(b - 1, ' ', 'H');
1209     BuffSetChar(b, ' ', 'H');
1210     }
1211     if (IsBuffFullWidth(b)) {
1212     // �S�p�������A�S�p���X�y�[�X���u��������
1213     BuffSetChar(b, ' ', 'H');
1214     BuffSetChar(b + 1, ' ', 'H');
1215     }
1216     if (Count > 1) {
1217     // �I�[���`�F�b�N
1218     if (IsBuffPadding(b + Count)) {
1219     // �S�p���E���A�S�p���X�y�[�X���u��������
1220     BuffSetChar(b + Count - 1, ' ', 'H');
1221     BuffSetChar(b + Count, ' ', 'H');
1222     }
1223     }
1224    
1225     if (CursorRightM < NumOfColumns - 1 && (AttrLine[CursorRightM] & AttrKanji)) {
1226     CodeLine[CursorRightM] = 0x20;
1227     BuffSetChar(&CodeLineW[CursorRightM], 0x20, 'H');
1228     AttrLine[CursorRightM] &= ~AttrKanji;
1229     CodeLine[CursorRightM + 1] = 0x20;
1230     BuffSetChar(&CodeLineW[CursorRightM + 1], 0x20, 'H');
1231     AttrLine[CursorRightM + 1] &= ~AttrKanji;
1232     extr = 1;
1233     }
1234    
1235     MoveLen = CursorRightM + 1 - CursorX - Count;
1236    
1237     if (MoveLen > 0) {
1238     memmove(&(CodeLine[CursorX]), &(CodeLine[CursorX + Count]), MoveLen);
1239     memmoveW(&(CodeLineW[CursorX]), &(CodeLineW[CursorX + Count]), MoveLen);
1240     memmove(&(AttrLine[CursorX]), &(AttrLine[CursorX + Count]), MoveLen);
1241     memmove(&(AttrLine2[CursorX]), &(AttrLine2[CursorX + Count]), MoveLen);
1242     memmove(&(AttrLineFG[CursorX]), &(AttrLineFG[CursorX + Count]), MoveLen);
1243     memmove(&(AttrLineBG[CursorX]), &(AttrLineBG[CursorX + Count]), MoveLen);
1244     }
1245     memset(&(CodeLine[CursorX + MoveLen]), 0x20, Count);
1246     memsetW(&(CodeLineW[CursorX + MoveLen]), ' ', Count);
1247     memset(&(AttrLine[CursorX + MoveLen]), AttrDefault, Count);
1248     memset(&(AttrLine2[CursorX + MoveLen]), CurCharAttr.Attr2 & Attr2ColorMask, Count);
1249     memset(&(AttrLineFG[CursorX + MoveLen]), CurCharAttr.Fore, Count);
1250     memset(&(AttrLineBG[CursorX + MoveLen]), CurCharAttr.Back, Count);
1251    
1252     BuffUpdateRect(CursorX, CursorY, CursorRightM + extr, CursorY);
1253     }
1254     #else
1255     void BuffDeleteChars(int Count)
1256     {
1257     int MoveLen;
1258 doda 5371 int extr=0;
1259 doda 5325
1260     if (CursorX < CursorLeftM || CursorX > CursorRightM)
1261     return;
1262    
1263 maya 3393 NewLine(PageStart+CursorY);
1264 maya 3227
1265 doda 3416 if (ts.Language==IdJapanese || ts.Language==IdKorean || ts.Language==IdUtf8) {
1266 maya 3393 EraseKanji(0); /* if cursor is on left harf of a kanji, erase the kanji */
1267     EraseKanji(1); /* if cursor on right half... */
1268     }
1269 maya 3227
1270 doda 5371 if (CursorRightM < NumOfColumns-1 && (AttrLine[CursorRightM] & AttrKanji)) {
1271     CodeLine[CursorRightM] = 0x20;
1272     AttrLine[CursorRightM] &= ~AttrKanji;
1273     CodeLine[CursorRightM+1] = 0x20;
1274     AttrLine[CursorRightM+1] &= ~AttrKanji;
1275     extr = 1;
1276     }
1277    
1278 doda 5325 if (Count > CursorRightM + 1 - CursorX)
1279     Count = CursorRightM + 1 - CursorX;
1280    
1281     MoveLen = CursorRightM + 1 - CursorX - Count;
1282    
1283     if (MoveLen > 0) {
1284     memmove(&(CodeLine[CursorX]), &(CodeLine[CursorX+Count]), MoveLen);
1285     memmove(&(AttrLine[CursorX]), &(AttrLine[CursorX+Count]), MoveLen);
1286     memmove(&(AttrLine2[CursorX]), &(AttrLine2[CursorX+Count]), MoveLen);
1287     memmove(&(AttrLineFG[CursorX]), &(AttrLineFG[CursorX+Count]), MoveLen);
1288     memmove(&(AttrLineBG[CursorX]), &(AttrLineBG[CursorX+Count]), MoveLen);
1289 maya 3393 }
1290 doda 5325 memset(&(CodeLine[CursorX + MoveLen]), 0x20, Count);
1291     memset(&(AttrLine[CursorX + MoveLen]), AttrDefault, Count);
1292     memset(&(AttrLine2[CursorX + MoveLen]), CurCharAttr.Attr2 & Attr2ColorMask, Count);
1293     memset(&(AttrLineFG[CursorX + MoveLen]), CurCharAttr.Fore, Count);
1294     memset(&(AttrLineBG[CursorX + MoveLen]), CurCharAttr.Back, Count);
1295 maya 3227
1296 doda 5371 BuffUpdateRect(CursorX, CursorY, CursorRightM+extr, CursorY);
1297 maya 3227 }
1298 doda 8445 #endif
1299 maya 3227
1300     // Erase characters in current line from cursor
1301     // Count: number of characters to be deleted
1302 doda 8445 #if UNICODE_INTERNAL_BUFF
1303     void BuffEraseChars(int Count)
1304 maya 3227 {
1305 doda 8445 int extr = 0;
1306     int sx = CursorX;
1307     buff_char_t *b;
1308     NewLine(PageStart + CursorY);
1309    
1310     if (Count > NumOfColumns - CursorX) {
1311     Count = NumOfColumns - CursorX;
1312     }
1313    
1314     b = &CodeLineW[CursorX];
1315     if (IsBuffPadding(b)) {
1316     // �S�p���E���A�S�p���X�y�[�X���u��������
1317     BuffSetChar(b - 1, ' ', 'H');
1318     BuffSetChar(b, ' ', 'H');
1319     sx--;
1320     extr++;
1321     }
1322     if (IsBuffFullWidth(b)) {
1323     // �S�p�������A�S�p���X�y�[�X���u��������
1324     BuffSetChar(b, ' ', 'H');
1325     BuffSetChar(b + 1, ' ', 'H');
1326     if (Count == 1) {
1327     extr++;
1328     }
1329     }
1330     if (Count > 1) {
1331     // �I�[���`�F�b�N
1332     if (IsBuffPadding(b + Count)) {
1333     // �S�p���E���A�S�p���X�y�[�X���u��������
1334     BuffSetChar(b + Count - 1, ' ', 'H');
1335     BuffSetChar(b + Count, ' ', 'H');
1336     extr++;
1337     }
1338     }
1339    
1340     memset(&(CodeLine[CursorX]), 0x20, Count);
1341     #if UNICODE_INTERNAL_BUFF
1342     memsetW(&(CodeLineW[CursorX]), 0x20, Count);
1343     #endif
1344     memset(&(AttrLine[CursorX]), AttrDefault, Count);
1345     memset(&(AttrLine2[CursorX]), CurCharAttr.Attr2 & Attr2ColorMask, Count);
1346     memset(&(AttrLineFG[CursorX]), CurCharAttr.Fore, Count);
1347     memset(&(AttrLineBG[CursorX]), CurCharAttr.Back, Count);
1348    
1349     /* update window */
1350     DispEraseCharsInLine(sx, Count + extr);
1351     }
1352     #else
1353     void BuffEraseChars(int Count)
1354     {
1355 maya 3393 NewLine(PageStart+CursorY);
1356 maya 3227
1357 doda 3416 if (ts.Language==IdJapanese || ts.Language==IdKorean || ts.Language==IdUtf8) {
1358 maya 3393 EraseKanji(0); /* if cursor is on left harf of a kanji, erase the kanji */
1359     EraseKanji(1); /* if cursor on right half... */
1360     }
1361 maya 3227
1362 maya 3393 if (Count > NumOfColumns-CursorX) {
1363     Count = NumOfColumns-CursorX;
1364     }
1365     memset(&(CodeLine[CursorX]),0x20,Count);
1366 doda 8445 #if UNICODE_INTERNAL_BUFF
1367     memsetW(&(CodeLineW[CursorX]),0x20,Count);
1368     #endif
1369 maya 3393 memset(&(AttrLine[CursorX]),AttrDefault,Count);
1370 doda 4070 memset(&(AttrLine2[CursorX]),CurCharAttr.Attr2 & Attr2ColorMask, Count);
1371 maya 3393 memset(&(AttrLineFG[CursorX]),CurCharAttr.Fore,Count);
1372     memset(&(AttrLineBG[CursorX]),CurCharAttr.Back,Count);
1373 maya 3227
1374 maya 3393 /* update window */
1375     DispEraseCharsInLine(CursorX,Count);
1376 maya 3227 }
1377 doda 8445 #endif
1378 maya 3227
1379     void BuffFillWithE()
1380     // Fill screen with 'E' characters
1381     {
1382 maya 3393 LONG TmpPtr;
1383     int i;
1384 maya 3227
1385 maya 3393 TmpPtr = GetLinePtr(PageStart);
1386     for (i = 0 ; i <= NumOfLines-1-StatusLine ; i++) {
1387     memset(&(CodeBuff[TmpPtr]),'E',NumOfColumns);
1388 doda 8445 #if UNICODE_INTERNAL_BUFF
1389     memsetW(&(CodeBuffW[TmpPtr]),'E',NumOfColumns);
1390     #endif
1391 maya 3393 memset(&(AttrBuff[TmpPtr]),AttrDefault,NumOfColumns);
1392     memset(&(AttrBuff2[TmpPtr]),AttrDefault,NumOfColumns);
1393     memset(&(AttrBuffFG[TmpPtr]),AttrDefaultFG,NumOfColumns);
1394     memset(&(AttrBuffBG[TmpPtr]),AttrDefaultBG,NumOfColumns);
1395     TmpPtr = NextLinePtr(TmpPtr);
1396     }
1397     BuffUpdateRect(WinOrgX,WinOrgY,WinOrgX+WinWidth-1,WinOrgY+WinHeight-1);
1398 maya 3227 }
1399    
1400     void BuffDrawLine(TCharAttr Attr, int Direction, int C)
1401     { // IO-8256 terminal
1402 maya 3393 LONG Ptr;
1403     int i, X, Y;
1404 maya 3227
1405 maya 3393 if (C==0) {
1406     return;
1407     }
1408     Attr.Attr |= AttrSpecial;
1409 maya 3227
1410 maya 3393 switch (Direction) {
1411     case 3:
1412     case 4:
1413     if (Direction==3) {
1414     if (CursorY==0) {
1415     return;
1416     }
1417     Y = CursorY-1;
1418     }
1419     else {
1420     if (CursorY==NumOfLines-1-StatusLine) {
1421     return;
1422     }
1423     Y = CursorY+1;
1424     }
1425     if (CursorX+C > NumOfColumns) {
1426     C = NumOfColumns-CursorX;
1427     }
1428     Ptr = GetLinePtr(PageStart+Y);
1429     memset(&(CodeBuff[Ptr+CursorX]),'q',C);
1430 doda 8445 #if UNICODE_INTERNAL_BUFF
1431     memsetW(&(CodeBuffW[Ptr+CursorX]),'q',C);
1432     #endif
1433 maya 3393 memset(&(AttrBuff[Ptr+CursorX]),Attr.Attr,C);
1434     memset(&(AttrBuff2[Ptr+CursorX]),Attr.Attr2,C);
1435     memset(&(AttrBuffFG[Ptr+CursorX]),Attr.Fore,C);
1436     memset(&(AttrBuffBG[Ptr+CursorX]),Attr.Back,C);
1437     BuffUpdateRect(CursorX,Y,CursorX+C-1,Y);
1438     break;
1439     case 5:
1440     case 6:
1441     if (Direction==5) {
1442     if (CursorX==0) {
1443     return;
1444     }
1445     X = CursorX - 1;
1446     }
1447     else {
1448     if (CursorX==NumOfColumns-1) {
1449     X = CursorX-1;
1450     }
1451     else {
1452     X = CursorX+1;
1453     }
1454     }
1455     Ptr = GetLinePtr(PageStart+CursorY);
1456     if (CursorY+C > NumOfLines-StatusLine) {
1457     C = NumOfLines-StatusLine-CursorY;
1458     }
1459     for (i=1; i<=C; i++) {
1460     CodeBuff[Ptr+X] = 'x';
1461 doda 8445 #if UNICODE_INTERNAL_BUFF
1462     BuffSetChar(&CodeBuffW[Ptr+X], 0x20, 'H');
1463     #endif
1464 maya 3393 AttrBuff[Ptr+X] = Attr.Attr;
1465     AttrBuff2[Ptr+X] = Attr.Attr2;
1466     AttrBuffFG[Ptr+X] = Attr.Fore;
1467     AttrBuffBG[Ptr+X] = Attr.Back;
1468     Ptr = NextLinePtr(Ptr);
1469     }
1470     BuffUpdateRect(X,CursorY,X,CursorY+C-1);
1471     break;
1472     }
1473 maya 3227 }
1474    
1475     void BuffEraseBox
1476     (int XStart, int YStart, int XEnd, int YEnd)
1477     {
1478 maya 3393 int C, i;
1479     LONG Ptr;
1480 maya 3227
1481 maya 3393 if (XEnd>NumOfColumns-1) {
1482     XEnd = NumOfColumns-1;
1483     }
1484     if (YEnd>NumOfLines-1-StatusLine) {
1485     YEnd = NumOfLines-1-StatusLine;
1486     }
1487     if (XStart>XEnd) {
1488     return;
1489     }
1490     if (YStart>YEnd) {
1491     return;
1492     }
1493     C = XEnd-XStart+1;
1494     Ptr = GetLinePtr(PageStart+YStart);
1495     for (i=YStart; i<=YEnd; i++) {
1496     if ((XStart>0) &&
1497     ((AttrBuff[Ptr+XStart-1] & AttrKanji) != 0)) {
1498     CodeBuff[Ptr+XStart-1] = 0x20;
1499 doda 8445 #if UNICODE_INTERNAL_BUFF
1500     BuffSetChar(&CodeBuffW[Ptr+XStart-1], 0x20, 'H');
1501     #endif
1502 maya 3393 AttrBuff[Ptr+XStart-1] = CurCharAttr.Attr;
1503     AttrBuff2[Ptr+XStart-1] = CurCharAttr.Attr2;
1504     AttrBuffFG[Ptr+XStart-1] = CurCharAttr.Fore;
1505     AttrBuffBG[Ptr+XStart-1] = CurCharAttr.Back;
1506     }
1507     if ((XStart+C<NumOfColumns) &&
1508     ((AttrBuff[Ptr+XStart+C-1] & AttrKanji) != 0)) {
1509     CodeBuff[Ptr+XStart+C] = 0x20;
1510 doda 8445 #if UNICODE_INTERNAL_BUFF
1511     BuffSetChar(&CodeBuffW[Ptr+XStart+C], 0x20, 'H');
1512     #endif
1513 maya 3393 AttrBuff[Ptr+XStart+C] = CurCharAttr.Attr;
1514     AttrBuff2[Ptr+XStart+C] = CurCharAttr.Attr2;
1515     AttrBuffFG[Ptr+XStart+C] = CurCharAttr.Fore;
1516     AttrBuffBG[Ptr+XStart+C] = CurCharAttr.Back;
1517     }
1518     memset(&(CodeBuff[Ptr+XStart]),0x20,C);
1519 doda 8445 #if UNICODE_INTERNAL_BUFF
1520     memsetW(&(CodeBuffW[Ptr+XStart]),0x20,C);
1521     #endif
1522 maya 3393 memset(&(AttrBuff[Ptr+XStart]),AttrDefault,C);
1523 doda 4070 memset(&(AttrBuff2[Ptr+XStart]),CurCharAttr.Attr2 & Attr2ColorMask, C);
1524 maya 3393 memset(&(AttrBuffFG[Ptr+XStart]),CurCharAttr.Fore,C);
1525     memset(&(AttrBuffBG[Ptr+XStart]),CurCharAttr.Back,C);
1526     Ptr = NextLinePtr(Ptr);
1527     }
1528     BuffUpdateRect(XStart,YStart,XEnd,YEnd);
1529 maya 3227 }
1530    
1531 doda 5090 void BuffFillBox(char ch, int XStart, int YStart, int XEnd, int YEnd)
1532     {
1533     int Cols, i;
1534     LONG Ptr;
1535    
1536     if (XEnd>NumOfColumns-1) {
1537     XEnd = NumOfColumns-1;
1538     }
1539     if (YEnd>NumOfLines-1-StatusLine) {
1540     YEnd = NumOfLines-1-StatusLine;
1541     }
1542     if (XStart>XEnd) {
1543     return;
1544     }
1545     if (YStart>YEnd) {
1546     return;
1547     }
1548     Cols = XEnd-XStart+1;
1549     Ptr = GetLinePtr(PageStart+YStart);
1550     for (i=YStart; i<=YEnd; i++) {
1551     if ((XStart>0) &&
1552     ((AttrBuff[Ptr+XStart-1] & AttrKanji) != 0)) {
1553     CodeBuff[Ptr+XStart-1] = 0x20;
1554 doda 8445 #if UNICODE_INTERNAL_BUFF
1555 doda 8446 BuffSetChar(&CodeBuffW[Ptr + XStart - 1], 0x20, 'H');
1556 doda 8445 #endif
1557 doda 5090 AttrBuff[Ptr+XStart-1] ^= AttrKanji;
1558     }
1559     if ((XStart+Cols<NumOfColumns) &&
1560     ((AttrBuff[Ptr+XStart+Cols-1] & AttrKanji) != 0)) {
1561     CodeBuff[Ptr+XStart+Cols] = 0x20;
1562 doda 8445 #if UNICODE_INTERNAL_BUFF
1563 doda 8446 BuffSetChar(&CodeBuffW[Ptr + XStart + Cols], 0x20, 'H');
1564 doda 8445 #endif
1565 doda 5090 }
1566     memset(&(CodeBuff[Ptr+XStart]), ch, Cols);
1567 doda 8445 #if UNICODE_INTERNAL_BUFF
1568 doda 8446 memsetW(&(CodeBuffW[Ptr+XStart]), ch, Cols);
1569 doda 8445 #endif
1570 doda 5090 memset(&(AttrBuff[Ptr+XStart]), CurCharAttr.Attr, Cols);
1571 doda 5092 memset(&(AttrBuff2[Ptr+XStart]), CurCharAttr.Attr2, Cols);
1572 doda 5090 memset(&(AttrBuffFG[Ptr+XStart]), CurCharAttr.Fore, Cols);
1573     memset(&(AttrBuffBG[Ptr+XStart]), CurCharAttr.Back, Cols);
1574     Ptr = NextLinePtr(Ptr);
1575     }
1576     BuffUpdateRect(XStart, YStart, XEnd, YEnd);
1577     }
1578    
1579 doda 6174 //
1580     // TODO: 1 origin �������������� 0 origin ������
1581     //
1582 doda 5089 void BuffCopyBox(
1583     int SrcXStart, int SrcYStart, int SrcXEnd, int SrcYEnd, int SrcPage,
1584     int DstX, int DstY, int DstPage)
1585     {
1586     int i, C, L;
1587     LONG SPtr, DPtr;
1588    
1589     SrcXStart--;
1590     SrcYStart--;
1591     SrcXEnd--;
1592     SrcYEnd--;
1593     SrcPage--;
1594     DstX--;
1595     DstY--;
1596     DstPage--;
1597    
1598     if (SrcXEnd > NumOfColumns - 1) {
1599     SrcXEnd = NumOfColumns-1;
1600     }
1601     if (SrcYEnd > NumOfLines-1-StatusLine) {
1602     SrcYEnd = NumOfColumns-1;
1603     }
1604     if (SrcXStart > SrcXEnd ||
1605     SrcYStart > SrcYEnd ||
1606     DstX > NumOfColumns-1 ||
1607     DstY > NumOfLines-1-StatusLine) {
1608     return;
1609     }
1610    
1611     C = SrcXEnd - SrcXStart + 1;
1612     if (DstX + C > NumOfColumns) {
1613     C = NumOfColumns - DstX;
1614     }
1615     L = SrcYEnd - SrcYStart + 1;
1616     if (DstY + C > NumOfColumns) {
1617     C = NumOfColumns - DstX;
1618     }
1619    
1620     if (SrcXStart > DstX) {
1621     SPtr = GetLinePtr(PageStart+SrcYStart);
1622     DPtr = GetLinePtr(PageStart+DstY);
1623     for (i=0; i<L; i++) {
1624     memcpy(&(CodeBuff[DPtr+DstX]), &(CodeBuff[SPtr+SrcXStart]), C);
1625 doda 8445 #if UNICODE_INTERNAL_BUFF
1626     memcpyW(&(CodeBuffW[DPtr+DstX]), &(CodeBuffW[SPtr+SrcXStart]), C);
1627     #endif
1628 doda 5089 memcpy(&(AttrBuff[DPtr+DstX]), &(AttrBuff[SPtr+SrcXStart]), C);
1629     memcpy(&(AttrBuff2[DPtr+DstX]), &(AttrBuff2[SPtr+SrcXStart]), C);
1630     memcpy(&(AttrBuffFG[DPtr+DstX]), &(AttrBuffFG[SPtr+SrcXStart]), C);
1631     memcpy(&(AttrBuffBG[DPtr+DstX]), &(AttrBuffBG[SPtr+SrcXStart]), C);
1632     SPtr = NextLinePtr(SPtr);
1633     DPtr = NextLinePtr(DPtr);
1634     }
1635     }
1636     else if (SrcXStart < DstX) {
1637     SPtr = GetLinePtr(PageStart+SrcYEnd);
1638     DPtr = GetLinePtr(PageStart+DstY+L-1);
1639     for (i=L; i>0; i--) {
1640     memcpy(&(CodeBuff[DPtr+DstX]), &(CodeBuff[SPtr+SrcXStart]), C);
1641 doda 8445 #if UNICODE_INTERNAL_BUFF
1642     memcpyW(&(CodeBuffW[DPtr+DstX]), &(CodeBuffW[SPtr+SrcXStart]), C);
1643     #endif
1644 doda 5089 memcpy(&(AttrBuff[DPtr+DstX]), &(AttrBuff[SPtr+SrcXStart]), C);
1645     memcpy(&(AttrBuff2[DPtr+DstX]), &(AttrBuff2[SPtr+SrcXStart]), C);
1646     memcpy(&(AttrBuffFG[DPtr+DstX]), &(AttrBuffFG[SPtr+SrcXStart]), C);
1647     memcpy(&(AttrBuffBG[DPtr+DstX]), &(AttrBuffBG[SPtr+SrcXStart]), C);
1648     SPtr = PrevLinePtr(SPtr);
1649     DPtr = PrevLinePtr(DPtr);
1650     }
1651     }
1652     else if (SrcYStart != DstY) {
1653     SPtr = GetLinePtr(PageStart+SrcYStart);
1654     DPtr = GetLinePtr(PageStart+DstY);
1655     for (i=0; i<L; i++) {
1656     memmove(&(CodeBuff[DPtr+DstX]), &(CodeBuff[SPtr+SrcXStart]), C);
1657 doda 8445 #if UNICODE_INTERNAL_BUFF
1658     memmoveW(&(CodeBuffW[DPtr+DstX]), &(CodeBuffW[SPtr+SrcXStart]), C);
1659     #endif
1660 doda 5089 memmove(&(AttrBuff[DPtr+DstX]), &(AttrBuff[SPtr+SrcXStart]), C);
1661     memmove(&(AttrBuff2[DPtr+DstX]), &(AttrBuff2[SPtr+SrcXStart]), C);
1662     memmove(&(AttrBuffFG[DPtr+DstX]), &(AttrBuffFG[SPtr+SrcXStart]), C);
1663     memmove(&(AttrBuffBG[DPtr+DstX]), &(AttrBuffBG[SPtr+SrcXStart]), C);
1664     SPtr = NextLinePtr(SPtr);
1665     DPtr = NextLinePtr(DPtr);
1666     }
1667     }
1668     BuffUpdateRect(DstX,DstY,DstX+C-1,DstY+L-1);
1669     }
1670    
1671 doda 5095 void BuffChangeAttrBox(int XStart, int YStart, int XEnd, int YEnd, PCharAttr attr, PCharAttr mask)
1672     {
1673     int C, i, j;
1674     LONG Ptr;
1675    
1676     if (XEnd>NumOfColumns-1) {
1677     XEnd = NumOfColumns-1;
1678     }
1679     if (YEnd>NumOfLines-1-StatusLine) {
1680     YEnd = NumOfLines-1-StatusLine;
1681     }
1682     if (XStart>XEnd || YStart>YEnd) {
1683     return;
1684     }
1685     C = XEnd-XStart+1;
1686     Ptr = GetLinePtr(PageStart+YStart);
1687    
1688     if (mask) { // DECCARA
1689     for (i=YStart; i<=YEnd; i++) {
1690     j = Ptr+XStart-1;
1691     if (XStart>0 && (AttrBuff[j] & AttrKanji)) {
1692     AttrBuff[j] = AttrBuff[j] & ~mask->Attr | attr->Attr;
1693 doda 7085 AttrBuff2[j] = AttrBuff2[j] & ~mask->Attr2 | attr->Attr2;
1694 doda 7087 if (mask->Attr2 & Attr2Fore) { AttrBuffFG[j] = attr->Fore; }
1695     if (mask->Attr2 & Attr2Back) { AttrBuffBG[j] = attr->Back; }
1696 doda 5095 }
1697 doda 7083 while (++j < Ptr+XStart+C) {
1698 doda 5095 AttrBuff[j] = AttrBuff[j] & ~mask->Attr | attr->Attr;
1699     AttrBuff2[j] = AttrBuff2[j] & ~mask->Attr2 | attr->Attr2;
1700 doda 7087 if (mask->Attr2 & Attr2Fore) { AttrBuffFG[j] = attr->Fore; }
1701     if (mask->Attr2 & Attr2Back) { AttrBuffBG[j] = attr->Back; }
1702 doda 5095 }
1703     if (XStart+C<NumOfColumns && (AttrBuff[j-1] & AttrKanji)) {
1704     AttrBuff[j] = AttrBuff[j] & ~mask->Attr | attr->Attr;
1705     AttrBuff2[j] = AttrBuff2[j] & ~mask->Attr2 | attr->Attr2;
1706 doda 7087 if (mask->Attr2 & Attr2Fore) { AttrBuffFG[j] = attr->Fore; }
1707     if (mask->Attr2 & Attr2Back) { AttrBuffBG[j] = attr->Back; }
1708 doda 5095 }
1709     Ptr = NextLinePtr(Ptr);
1710     }
1711     }
1712     else { // DECRARA
1713     for (i=YStart; i<=YEnd; i++) {
1714     j = Ptr+XStart-1;
1715     if (XStart>0 && (AttrBuff[j] & AttrKanji)) {
1716 doda 7083 AttrBuff[j] ^= attr->Attr;
1717 doda 5095 }
1718 doda 7083 while (++j < Ptr+XStart+C) {
1719     AttrBuff[j] ^= attr->Attr;
1720 doda 5095 }
1721     if (XStart+C<NumOfColumns && (AttrBuff[j-1] & AttrKanji)) {
1722     AttrBuff[j] ^= attr->Attr;
1723     }
1724     Ptr = NextLinePtr(Ptr);
1725     }
1726     }
1727     BuffUpdateRect(XStart, YStart, XEnd, YEnd);
1728     }
1729    
1730 doda 7086 void BuffChangeAttrStream(int XStart, int YStart, int XEnd, int YEnd, PCharAttr attr, PCharAttr mask)
1731     {
1732     int i, j, endp;
1733     LONG Ptr;
1734    
1735     if (XEnd>NumOfColumns-1) {
1736     XEnd = NumOfColumns-1;
1737     }
1738     if (YEnd>NumOfLines-1-StatusLine) {
1739     YEnd = NumOfLines-1-StatusLine;
1740     }
1741     if (XStart>XEnd || YStart>YEnd) {
1742     return;
1743     }
1744    
1745     Ptr = GetLinePtr(PageStart+YStart);
1746    
1747     if (mask) { // DECCARA
1748     if (YStart == YEnd) {
1749     i = Ptr + XStart - 1;
1750     endp = Ptr + XEnd + 1;
1751    
1752     if (XStart > 0 && (AttrBuff[i] & AttrKanji)) {
1753     AttrBuff[i] = AttrBuff[i] & ~mask->Attr | attr->Attr;
1754     AttrBuff2[i] = AttrBuff2[i] & ~mask->Attr2 | attr->Attr2;
1755 doda 7087 if (mask->Attr2 & Attr2Fore) { AttrBuffFG[i] = attr->Fore; }
1756     if (mask->Attr2 & Attr2Back) { AttrBuffBG[i] = attr->Back; }
1757 doda 7086 }
1758     while (++i < endp) {
1759     AttrBuff[i] = AttrBuff[i] & ~mask->Attr | attr->Attr;
1760     AttrBuff2[i] = AttrBuff2[i] & ~mask->Attr2 | attr->Attr2;
1761 doda 7087 if (mask->Attr2 & Attr2Fore) { AttrBuffFG[i] = attr->Fore; }
1762     if (mask->Attr2 & Attr2Back) { AttrBuffBG[i] = attr->Back; }
1763 doda 7086 }
1764     if (XEnd < NumOfColumns-1 && (AttrBuff[i-1] & AttrKanji)) {
1765     AttrBuff[i] = AttrBuff[i] & ~mask->Attr | attr->Attr;
1766     AttrBuff2[i] = AttrBuff2[i] & ~mask->Attr2 | attr->Attr2;
1767 doda 7087 if (mask->Attr2 & Attr2Fore) { AttrBuffFG[i] = attr->Fore; }
1768     if (mask->Attr2 & Attr2Back) { AttrBuffBG[i] = attr->Back; }
1769 doda 7086 }
1770     }
1771     else {
1772     i = Ptr + XStart - 1;
1773     endp = Ptr + NumOfColumns;
1774    
1775     if (XStart > 0 && (AttrBuff[i] & AttrKanji)) {
1776     AttrBuff[i] = AttrBuff[i] & ~mask->Attr | attr->Attr;
1777     AttrBuff2[i] = AttrBuff2[i] & ~mask->Attr2 | attr->Attr2;
1778 doda 7087 if (mask->Attr2 & Attr2Fore) { AttrBuffFG[i] = attr->Fore; }
1779     if (mask->Attr2 & Attr2Back) { AttrBuffBG[i] = attr->Back; }
1780 doda 7086 }
1781     while (++i < endp) {
1782     AttrBuff[i] = AttrBuff[i] & ~mask->Attr | attr->Attr;
1783     AttrBuff2[i] = AttrBuff2[i] & ~mask->Attr2 | attr->Attr2;
1784 doda 7087 if (mask->Attr2 & Attr2Fore) { AttrBuffFG[i] = attr->Fore; }
1785     if (mask->Attr2 & Attr2Back) { AttrBuffBG[i] = attr->Back; }
1786 doda 7086 }
1787    
1788     for (j=0; j < YEnd-YStart-1; j++) {
1789     Ptr = NextLinePtr(Ptr);
1790     i = Ptr;
1791     endp = Ptr + NumOfColumns;
1792    
1793     while (i < endp) {
1794     AttrBuff[i] = AttrBuff[i] & ~mask->Attr | attr->Attr;
1795     AttrBuff2[i] = AttrBuff2[i] & ~mask->Attr2 | attr->Attr2;
1796 doda 7087 if (mask->Attr2 & Attr2Fore) { AttrBuffFG[i] = attr->Fore; }
1797     if (mask->Attr2 & Attr2Back) { AttrBuffBG[i] = attr->Back; }
1798 doda 7086 i++;
1799     }
1800     }
1801    
1802     Ptr = NextLinePtr(Ptr);
1803     i = Ptr;
1804     endp = Ptr + XEnd + 1;
1805    
1806     while (i < endp) {
1807     AttrBuff[i] = AttrBuff[i] & ~mask->Attr | attr->Attr;
1808     AttrBuff2[i] = AttrBuff2[i] & ~mask->Attr2 | attr->Attr2;
1809 doda 7087 if (mask->Attr2 & Attr2Fore) { AttrBuffFG[i] = attr->Fore; }
1810     if (mask->Attr2 & Attr2Back) { AttrBuffBG[i] = attr->Back; }
1811 doda 7086 i++;
1812     }
1813     if (XEnd < NumOfColumns-1 && (AttrBuff[i-1] & AttrKanji)) {
1814     AttrBuff[i] = AttrBuff[i] & ~mask->Attr | attr->Attr;
1815     AttrBuff2[i] = AttrBuff2[i] & ~mask->Attr2 | attr->Attr2;
1816 doda 7087 if (mask->Attr2 & Attr2Fore) { AttrBuffFG[i] = attr->Fore; }
1817     if (mask->Attr2 & Attr2Back) { AttrBuffBG[i] = attr->Back; }
1818 doda 7086 }
1819     }
1820     }
1821     else { // DECRARA
1822     if (YStart == YEnd) {
1823     i = Ptr + XStart - 1;
1824     endp = Ptr + XEnd + 1;
1825    
1826     if (XStart > 0 && (AttrBuff[i] & AttrKanji)) {
1827     AttrBuff[i] ^= attr->Attr;
1828     }
1829     while (++i < endp) {
1830     AttrBuff[i] ^= attr->Attr;
1831     }
1832     if (XEnd < NumOfColumns-1 && (AttrBuff[i-1] & AttrKanji)) {
1833     AttrBuff[i] ^= attr->Attr;
1834     }
1835     }
1836     else {
1837     i = Ptr + XStart - 1;
1838     endp = Ptr + NumOfColumns;
1839    
1840     if (XStart > 0 && (AttrBuff[i] & AttrKanji)) {
1841     AttrBuff[i] ^= attr->Attr;
1842     }
1843     while (++i < endp) {
1844     AttrBuff[i] ^= attr->Attr;
1845     }
1846    
1847     for (j=0; j < YEnd-YStart-1; j++) {
1848     Ptr = NextLinePtr(Ptr);
1849     i = Ptr;
1850     endp = Ptr + NumOfColumns;
1851    
1852     while (i < endp) {
1853     AttrBuff[i] ^= attr->Attr;
1854     i++;
1855     }
1856     }
1857    
1858     Ptr = NextLinePtr(Ptr);
1859     i = Ptr;
1860     endp = Ptr + XEnd + 1;
1861    
1862     while (i < endp) {
1863     AttrBuff[i] ^= attr->Attr;
1864     i++;
1865     }
1866     if (XEnd < NumOfColumns-1 && (AttrBuff[i-1] & AttrKanji)) {
1867     AttrBuff[i] ^= attr->Attr;
1868     }
1869     Ptr = NextLinePtr(Ptr);
1870     }
1871     }
1872     BuffUpdateRect(0, YStart, NumOfColumns-1, YEnd);
1873     }
1874    
1875 doda 8445 static int LeftHalfOfDBCS(LONG Line, int CharPtr)
1876 maya 3227 // If CharPtr is on the right half of a DBCS character,
1877     // return pointer to the left half
1878     // Line: points to a line in CodeBuff
1879     // CharPtr: points to a char
1880     // return: points to the left half of the DBCS
1881     {
1882 maya 3393 if ((CharPtr>0) &&
1883     ((AttrBuff[Line+CharPtr-1] & AttrKanji) != 0)) {
1884     CharPtr--;
1885     }
1886     return CharPtr;
1887 maya 3227 }
1888    
1889 doda 8445 static int MoveCharPtr(LONG Line, int *x, int dx)
1890 maya 3227 // move character pointer x by dx character unit
1891     // in the line specified by Line
1892     // Line: points to a line in CodeBuff
1893     // x: points to a character in the line
1894     // dx: moving distance in character unit (-: left, +: right)
1895 maya 3393 // One DBCS character is counted as one character.
1896 maya 3227 // The pointer stops at the beginning or the end of line.
1897     // Output
1898     // x: new pointer. x points to a SBCS character or
1899     // the left half of a DBCS character.
1900     // return: actual moving distance in character unit
1901     {
1902 maya 3393 int i;
1903 maya 3227
1904 maya 3393 *x = LeftHalfOfDBCS(Line,*x);
1905     i = 0;
1906     while (dx!=0) {
1907     if (dx>0) { // move right
1908     if ((AttrBuff[Line+*x] & AttrKanji) != 0) {
1909     if (*x<NumOfColumns-2) {
1910     i++;
1911     *x = *x + 2;
1912     }
1913     }
1914     else if (*x<NumOfColumns-1) {
1915     i++;
1916     (*x)++;
1917     }
1918     dx--;
1919     }
1920     else { // move left
1921     if (*x>0) {
1922     i--;
1923     (*x)--;
1924     }
1925     *x = LeftHalfOfDBCS(Line,*x);
1926     dx++;
1927     }
1928 maya 3227 }
1929 maya 3393 return i;
1930 maya 3227 }
1931    
1932 doda 8445 /**
1933     * (�N���b�v�{�[�h�p��)������������
1934     * @param[in] sx,sy,ex,ey �I������
1935     * @param[in] box_select TRUE=���^(���`)�I��
1936     * FALSE=�s�I��
1937     * @param[out] _str_len ��������(�����[L'\0'������)
1938     * NULL����������������
1939     * @return ������
1940     * �g�p���� free() ��������
1941     */
1942     #if UNICODE_INTERNAL_BUFF
1943     static wchar_t *BuffGetStringForCB(int sx, int sy, int ex, int ey, BOOL box_select, size_t *_str_len)
1944     {
1945     wchar_t *str_w;
1946     size_t str_size; // �m�������T�C�Y
1947     size_t k;
1948     LONG TmpPtr;
1949     int IStart, IEnd;
1950     int x, y;
1951     BOOL LineContinued;
1952    
1953     str_size = NumOfColumns * (ey - sy + 1);
1954     str_w = malloc(sizeof(wchar_t) * str_size);
1955    
1956     LockBuffer();
1957    
1958     str_w[0] = 0;
1959     TmpPtr = GetLinePtr(sy);
1960     k = 0;
1961     for (y = sy; y<=ey ; y++) {
1962     if (box_select) {
1963     IStart = SelectStart.x;
1964     IEnd = SelectEnd.x-1;
1965     }
1966     else {
1967     IStart = 0;
1968     IEnd = NumOfColumns-1;
1969     if (y== sy) {
1970     IStart = sx;
1971     }
1972     if (y== ey) {
1973     IEnd = ex -1;
1974     }
1975     }
1976    
1977     // �����s����������?
1978     LineContinued = FALSE;
1979     if (!box_select) {
1980     // �s�I������������
1981     if (ts.EnableContinuedLineCopy && y!= ey ) {
1982     LONG NextTmpPtr = NextLinePtr(TmpPtr);
1983     if ((AttrBuff[NextTmpPtr] & AttrLineContinued) != 0) {
1984     LineContinued = TRUE;
1985     }
1986     }
1987     }
1988    
1989     if (!LineContinued) {
1990     while ((IEnd>0)) {
1991     // �R�s�[�s�v��������
1992     const buff_char_t *b = &CodeBuffW[TmpPtr + IEnd];
1993     if (b->u32 == 0x20) {
1994     MoveCharPtr(TmpPtr,&IEnd,-1); // �����l����
1995     }
1996     else {
1997     break;
1998     }
1999     }
2000     }
2001    
2002     x = IStart;
2003     while (x <= IEnd) {
2004     const buff_char_t *b = &CodeBuffW[TmpPtr + x];
2005     if (b->u32 != 0) {
2006     str_w[k++] = b->wc2[0];
2007     if (b->wc2[1] != 0) {
2008     str_w[k++] = b->wc2[1];
2009     }
2010     if (k + 2 >= str_size) {
2011     str_size *= 2;
2012     str_w = realloc(str_w, sizeof(wchar_t) * str_size);
2013     }
2014     {
2015     int i;
2016     // �R���r�l�[�V����
2017     if (k + b->CombinationCharCount16 >= str_size) {
2018     str_size += + b->CombinationCharCount16;
2019     str_w = realloc(str_w, sizeof(wchar_t) * str_size);
2020     }
2021     for (i = 0 ; i < (int)b->CombinationCharCount16; i++) {
2022     str_w[k++] = b->pCombinationChars16[i];
2023     }
2024     }
2025     }
2026     x++;
2027     }
2028    
2029     if (y < ey) {
2030     // ���s��������(�������s���O������)
2031     if (!LineContinued) {
2032     str_w[k++] = 0x0d;
2033     str_w[k++] = 0x0a;
2034     }
2035     }
2036    
2037     TmpPtr = NextLinePtr(TmpPtr);
2038     }
2039     str_w[k++] = 0;
2040    
2041     UnlockBuffer();
2042    
2043     if (_str_len != NULL) {
2044     *_str_len = k;
2045     }
2046     return str_w;
2047     }
2048     #endif
2049    
2050     /**
2051     * (x,y) ��1������ str��������������
2052     * *�� 1������������wchar_t�����\������������
2053     *
2054     * @param y PageStart + CursorY
2055     * @param str 1����(wchar_t��)
2056     * @param len ��������
2057     * @retval 0=�}�b�`����������
2058     * �}�b�`������������
2059     */
2060     #if UNICODE_INTERNAL_BUFF
2061     static size_t MatchOneString(int x, int y, const wchar_t *str, size_t len)
2062     {
2063     int match_pos = 0;
2064     int TmpPtr = GetLinePtr(y);
2065     const buff_char_t *b = &CodeBuffW[TmpPtr + x];
2066     if (b->wc2[1] == 0) {
2067     // �T���Q�[�g�y�A��������
2068     if (str[match_pos] != b->wc2[0]) {
2069     return 0;
2070     }
2071     match_pos++;
2072     len--;
2073     } else {
2074     // �T���Q�[�g�y�A
2075     if (len < 2) {
2076     return 0;
2077     }
2078     if (str[match_pos+0] != b->wc2[0] ||
2079     str[match_pos+1] != b->wc2[1]) {
2080     return 0;
2081     }
2082     match_pos+=2;
2083     len-=2;
2084     }
2085     if (b->CombinationCharCount16 > 0) {
2086     // �R���r�l�[�V����
2087     int i;
2088     if (len < b->CombinationCharCount16) {
2089     return 0;
2090     }
2091     for (i = 0 ; i < (int)b->CombinationCharCount16; i++) {
2092     if (str[match_pos++] != b->pCombinationChars16[i]) {
2093     return 0;
2094     }
2095     }
2096     len -= b->CombinationCharCount16;
2097     }
2098     return match_pos;
2099     }
2100     #endif
2101    
2102     /**
2103     * (x,y)���� str��������������
2104     *
2105     * @param x �}�C�i�X�����A�����s������������
2106     * @param y PageStart + CursorY
2107     * @param LineCntinued TRUE=�s���p�����l������
2108     * @retval TRUE �}�b�`����
2109     * @retval FALSE �}�b�`����������
2110     */
2111     #if UNICODE_INTERNAL_BUFF
2112     static BOOL MatchString(int x, int y, const wchar_t *str, BOOL LineContinued)
2113     {
2114     BOOL result;
2115     int TmpPtr = GetLinePtr(y);
2116     size_t len = wcslen(str);
2117     if (len == 0) {
2118     return FALSE;
2119     }
2120     while(x < 0) {
2121     if (LineContinued && (AttrBuff[TmpPtr+0] & AttrLineContinued) == 0) {
2122     // �s���p�������������l�� & �p������������
2123     x = 0; // �s������������
2124     break;
2125     }
2126     TmpPtr = PrevLinePtr(TmpPtr);
2127     x += NumOfColumns;
2128     y--;
2129     }
2130     while(x > NumOfColumns) {
2131     if (LineContinued && (AttrBuff[TmpPtr+NumOfColumns-1] & AttrLineContinued) == 0) {
2132     // �s���p�������������l�� & �p������������
2133     x = 0; // �s������������
2134     break;
2135     }
2136     TmpPtr = NextLinePtr(TmpPtr);
2137     x -= NumOfColumns;
2138     }
2139    
2140     for(;;) {
2141     // 1����������������
2142     size_t match_len = MatchOneString(x, y, str, len);
2143     if (match_len == 0) {
2144     result = FALSE;
2145     break;
2146     }
2147     len -= match_len;
2148     if (len == 0) {
2149     // �S���������I������
2150     result = TRUE;
2151     break;
2152     }
2153     str += match_len;
2154    
2155     // ��������
2156     x++;
2157     if (x == NumOfColumns) {
2158     if (LineContinued && (AttrBuff[TmpPtr+NumOfColumns-1] & AttrLineContinued) != 0) {
2159     // �����s��
2160     x = 0;
2161     TmpPtr = NextLinePtr(TmpPtr);
2162     y++;
2163     } else {
2164     // �s��
2165     result = FALSE;
2166     break;
2167     }
2168     }
2169     }
2170    
2171     return result;
2172     }
2173     #endif
2174    
2175     /**
2176     * (sx,sy)����(ex,ey)������ str ���}�b�`�����������T����
2177     * ���u������
2178     *
2179     * @param sy,ex PageStart + CursorY
2180     * @param[out] x �}�b�`�������u
2181     * @param[out] y �}�b�`�������u
2182     * @retval TRUE �}�b�`����
2183     */
2184     #if UNICODE_INTERNAL_BUFF
2185     static BOOL BuffGetMatchPosFromString(
2186     int sx, int sy, int ex, int ey, const wchar_t *str,
2187     int *match_x, int *match_y)
2188     {
2189