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 8825 - (hide annotations) (download) (as text)
Fri Jul 3 14:43:19 2020 UTC (3 years, 9 months ago) by zmatsuo
File MIME type: text/x-csrc
File size: 132889 byte(s)
ttcstd.hを追加

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