Develop and Download Open Source Software

Browse Subversion Repository

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

Parent Directory Parent Directory | Revision Log Revision Log


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