Develop and Download Open Source Software

Browse Subversion Repository

Annotation of /trunk/teraterm/teraterm/buffer.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 9115 - (hide annotations) (download) (as text)
Mon Dec 28 14:29:48 2020 UTC (3 years, 3 months ago) by zmatsuo
File MIME type: text/x-csrc
File size: 134486 byte(s)
エスケープシーケンスからの印字を修正

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