Develop and Download Open Source Software

Browse Subversion Repository

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

Parent Directory Parent Directory | Revision Log Revision Log


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