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