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 10062 - (hide annotations) (download) (as text)
Fri Jul 15 16:31:18 2022 UTC (20 months, 3 weeks ago) by zmatsuo
File MIME type: text/x-csrc
File size: 135438 byte(s)
空行を選択したときスペースが1文字コピーされる

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