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