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 8770 - (hide annotations) (download) (as text)
Tue May 12 14:32:31 2020 UTC (3 years, 11 months ago) by zmatsuo
Original Path: trunk/teraterm/teraterm/buffer.c
File MIME type: text/x-csrc
File size: 132633 byte(s)
フォント選択時にANSI表示用文字コードに使用するコードページを自動で選ぶようにした

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