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 8771 - (hide annotations) (download) (as text)
Tue May 12 14:32:44 2020 UTC (3 years, 11 months ago) by zmatsuo
File MIME type: text/x-csrc
File size: 132773 byte(s)
fontプロパティーページ追加

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