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 3615 - (hide annotations) (download) (as text)
Fri Aug 28 16:32:09 2009 UTC (14 years, 7 months ago) by yutakapon
File MIME type: text/x-csrc
File size: 76449 byte(s)
EnableURLColor=on
EnableClickableUrl=off
と設定した場合においても、URLをクリックはできないが、カラー表示できるようにした。

1 maya 3227 /* Tera Term
2     Copyright(C) 1994-1998 T. Teranishi
3     All rights reserved. */
4    
5     /* TERATERM.EXE, scroll buffer routines */
6    
7     #include "teraterm.h"
8     #include "tttypes.h"
9     #include <string.h>
10    
11     #include "ttwinman.h"
12     #include "teraprn.h"
13     #include "vtdisp.h"
14     #include "clipboar.h"
15     #include "telnet.h"
16     #include "ttplug.h" /* TTPLUG */
17    
18     #include "buffer.h"
19    
20     // URLを強調する(石崎氏パッチ 2005/4/2)
21     #define URL_EMPHASIS 1
22    
23     #define BuffXMax TermWidthMax
24     //#define BuffYMax 100000
25     //#define BuffSizeMax 8000000
26     // スクロールバッファの最大長を拡張 (2004.11.28 yutaka)
27     #define BuffYMax 500000
28     #define BuffSizeMax (BuffYMax * 80)
29    
30     // status line
31     int StatusLine; //0: none 1: shown
32     /* top & bottom margin */
33     int CursorTop, CursorBottom;
34     BOOL Selected;
35     BOOL Wrap;
36    
37     static WORD TabStops[256];
38     static int NTabStops;
39    
40     static WORD BuffLock = 0;
41     static HANDLE HCodeBuff = 0;
42     static HANDLE HAttrBuff = 0;
43     static HANDLE HAttrBuff2 = 0;
44     static HANDLE HAttrBuffFG = 0;
45     static HANDLE HAttrBuffBG = 0;
46    
47     static PCHAR CodeBuff; /* Character code buffer */
48     static PCHAR AttrBuff; /* Attribute buffer */
49     static PCHAR AttrBuff2; /* Color attr buffer */
50     static PCHAR AttrBuffFG; /* Foreground color attr buffer */
51     static PCHAR AttrBuffBG; /* Background color attr buffer */
52     static PCHAR CodeLine;
53     static PCHAR AttrLine;
54     static PCHAR AttrLine2;
55     static PCHAR AttrLineFG;
56     static PCHAR AttrLineBG;
57     static LONG LinePtr;
58     static LONG BufferSize;
59     static int NumOfLinesInBuff;
60     static int BuffStartAbs, BuffEndAbs;
61     static POINT SelectStart, SelectEnd, SelectEndOld;
62     static BOOL BoxSelect;
63     static POINT DblClkStart, DblClkEnd;
64    
65     static int StrChangeStart, StrChangeCount;
66    
67     static BOOL SeveralPageSelect; // add (2005.5.15 yutaka)
68    
69     static TCharAttr CurCharAttr;
70    
71     LONG GetLinePtr(int Line)
72     {
73 maya 3393 LONG Ptr;
74 maya 3227
75 maya 3393 Ptr = (LONG)(BuffStartAbs + Line) * (LONG)(NumOfColumns);
76     while (Ptr>=BufferSize) {
77     Ptr = Ptr - BufferSize;
78     }
79     return Ptr;
80 maya 3227 }
81    
82     LONG NextLinePtr(LONG Ptr)
83     {
84 maya 3393 Ptr = Ptr + (LONG)NumOfColumns;
85     if (Ptr >= BufferSize) {
86     Ptr = Ptr - BufferSize;
87     }
88     return Ptr;
89 maya 3227 }
90    
91     LONG PrevLinePtr(LONG Ptr)
92     {
93 maya 3393 Ptr = Ptr - (LONG)NumOfColumns;
94     if (Ptr < 0) {
95     Ptr = Ptr + BufferSize;
96     }
97     return Ptr;
98 maya 3227 }
99    
100     BOOL ChangeBuffer(int Nx, int Ny)
101     {
102 maya 3393 HANDLE HCodeNew, HAttrNew, HAttr2New, HAttrFGNew, HAttrBGNew;
103     LONG NewSize;
104     int NxCopy, NyCopy, i;
105     PCHAR CodeDest, AttrDest, AttrDest2, AttrDestFG, AttrDestBG;
106     PCHAR Ptr;
107     LONG SrcPtr, DestPtr;
108     WORD LockOld;
109 maya 3227
110 maya 3393 if (Nx > BuffXMax) {
111     Nx = BuffXMax;
112     }
113     if (ts.ScrollBuffMax > BuffYMax) {
114     ts.ScrollBuffMax = BuffYMax;
115     }
116     if (Ny > ts.ScrollBuffMax) {
117     Ny = ts.ScrollBuffMax;
118     }
119 maya 3227
120 maya 3393 if ( (LONG)Nx * (LONG)Ny > BuffSizeMax ) {
121     Ny = BuffSizeMax / Nx;
122     }
123 maya 3227
124 maya 3393 NewSize = (LONG)Nx * (LONG)Ny;
125 maya 3227
126 maya 3393 HCodeNew = GlobalAlloc(GMEM_MOVEABLE, NewSize);
127     if ( HCodeNew==0 ) {
128     return FALSE;
129     }
130     Ptr = GlobalLock(HCodeNew);
131     if ( Ptr==NULL ) {
132     GlobalFree(HCodeNew);
133     return FALSE;
134     }
135     CodeDest = Ptr;
136 maya 3227
137 maya 3393 HAttrNew = GlobalAlloc(GMEM_MOVEABLE, NewSize);
138     if ( HAttrNew==0 ) {
139     GlobalFree(HCodeNew);
140     return FALSE;
141     }
142     Ptr = GlobalLock(HAttrNew);
143     if ( Ptr==NULL ) {
144     GlobalFree(HCodeNew);
145     GlobalFree(HAttrNew);
146     return FALSE;
147     }
148     AttrDest = Ptr;
149 maya 3227
150 maya 3393 HAttr2New = GlobalAlloc(GMEM_MOVEABLE, NewSize);
151     if ( HAttr2New==0 ) {
152     GlobalFree(HCodeNew);
153     GlobalFree(HAttrNew);
154     return FALSE;
155     }
156     Ptr = GlobalLock(HAttr2New);
157     if ( Ptr==NULL ) {
158     GlobalFree(HCodeNew);
159     GlobalFree(HAttrNew);
160     GlobalFree(HAttr2New);
161     return FALSE;
162     }
163     AttrDest2 = Ptr;
164 maya 3227
165 maya 3393 HAttrFGNew = GlobalAlloc(GMEM_MOVEABLE, NewSize);
166     if ( HAttrFGNew==0 ) {
167     GlobalFree(HCodeNew);
168     GlobalFree(HAttrNew);
169     GlobalFree(HAttr2New);
170     return FALSE;
171     }
172     Ptr = GlobalLock(HAttrFGNew);
173     if ( Ptr==NULL ) {
174     GlobalFree(HCodeNew);
175     GlobalFree(HAttrNew);
176     GlobalFree(HAttr2New);
177     GlobalFree(HAttrFGNew);
178     return FALSE;
179     }
180     AttrDestFG = Ptr;
181 maya 3227
182 maya 3393 HAttrBGNew = GlobalAlloc(GMEM_MOVEABLE, NewSize);
183     if ( HAttrBGNew==0 ) {
184     GlobalFree(HCodeNew);
185     GlobalFree(HAttrNew);
186     GlobalFree(HAttr2New);
187     GlobalFree(HAttrFGNew);
188     return FALSE;
189     }
190     Ptr = GlobalLock(HAttrBGNew);
191     if ( Ptr==NULL ) {
192     GlobalFree(HCodeNew);
193     GlobalFree(HAttrNew);
194     GlobalFree(HAttr2New);
195     GlobalFree(HAttrFGNew);
196     GlobalFree(HAttrBGNew);
197     return FALSE;
198     }
199     AttrDestBG = Ptr;
200 maya 3227
201 maya 3393 memset(&CodeDest[0], 0x20, NewSize);
202     memset(&AttrDest[0], AttrDefault, NewSize);
203     memset(&AttrDest2[0], AttrDefault, NewSize);
204     memset(&AttrDestFG[0], AttrDefaultFG, NewSize);
205     memset(&AttrDestBG[0], AttrDefaultBG, NewSize);
206     if ( HCodeBuff!=0 ) {
207     if ( NumOfColumns > Nx ) {
208     NxCopy = Nx;
209     }
210     else {
211     NxCopy = NumOfColumns;
212     }
213 maya 3227
214 maya 3393 if ( BuffEnd > Ny ) {
215     NyCopy = Ny;
216     }
217     else {
218     NyCopy = BuffEnd;
219     }
220     LockOld = BuffLock;
221     LockBuffer();
222     SrcPtr = GetLinePtr(BuffEnd-NyCopy);
223     DestPtr = 0;
224     for (i = 1 ; i <= NyCopy ; i++) {
225     memcpy(&CodeDest[DestPtr],&CodeBuff[SrcPtr],NxCopy);
226     memcpy(&AttrDest[DestPtr],&AttrBuff[SrcPtr],NxCopy);
227     memcpy(&AttrDest2[DestPtr],&AttrBuff2[SrcPtr],NxCopy);
228     memcpy(&AttrDestFG[DestPtr],&AttrBuffFG[SrcPtr],NxCopy);
229     memcpy(&AttrDestBG[DestPtr],&AttrBuffBG[SrcPtr],NxCopy);
230     SrcPtr = NextLinePtr(SrcPtr);
231     DestPtr = DestPtr + (LONG)Nx;
232     }
233     FreeBuffer();
234     }
235     else {
236     LockOld = 0;
237     NyCopy = NumOfLines;
238     Selected = FALSE;
239     }
240 maya 3227
241 maya 3393 if (Selected) {
242     SelectStart.y = SelectStart.y - BuffEnd + NyCopy;
243     SelectEnd.y = SelectEnd.y - BuffEnd + NyCopy;
244     if (SelectStart.y < 0) {
245     SelectStart.y = 0;
246     SelectStart.x = 0;
247     }
248     if (SelectEnd.y<0) {
249     SelectEnd.x = 0;
250     SelectEnd.y = 0;
251     }
252 maya 3227
253 maya 3393 Selected = (SelectEnd.y > SelectStart.y) ||
254     ((SelectEnd.y=SelectStart.y) &&
255     (SelectEnd.x > SelectStart.x));
256     }
257 maya 3227
258 maya 3393 HCodeBuff = HCodeNew;
259     HAttrBuff = HAttrNew;
260     HAttrBuff2 = HAttr2New;
261     HAttrBuffFG = HAttrFGNew;
262     HAttrBuffBG = HAttrBGNew;
263     BufferSize = NewSize;
264     NumOfLinesInBuff = Ny;
265     BuffStartAbs = 0;
266     BuffEnd = NyCopy;
267 maya 3227
268 maya 3393 if (BuffEnd==NumOfLinesInBuff) {
269     BuffEndAbs = 0;
270     }
271     else {
272     BuffEndAbs = BuffEnd;
273     }
274 maya 3227
275 maya 3393 PageStart = BuffEnd - NumOfLines;
276    
277     LinePtr = 0;
278     if (LockOld>0) {
279     CodeBuff = (PCHAR)GlobalLock(HCodeBuff);
280     AttrBuff = (PCHAR)GlobalLock(HAttrBuff);
281     AttrBuff2 = (PCHAR)GlobalLock(HAttrBuff2);
282     AttrBuffFG = (PCHAR)GlobalLock(HAttrBuffFG);
283     AttrBuffBG = (PCHAR)GlobalLock(HAttrBuffBG);
284     CodeLine = CodeBuff;
285     AttrLine = AttrBuff;
286     AttrLine2 = AttrBuff2;
287     AttrLineFG = AttrBuffFG;
288     AttrLineBG = AttrBuffBG;
289     }
290     else {
291     GlobalUnlock(HCodeNew);
292     GlobalUnlock(HAttrNew);
293     }
294     BuffLock = LockOld;
295    
296     return TRUE;
297 maya 3227 }
298    
299     void InitBuffer()
300     {
301 maya 3393 int Ny;
302 maya 3227
303 maya 3393 /* setup terminal */
304     NumOfColumns = ts.TerminalWidth;
305     NumOfLines = ts.TerminalHeight;
306 maya 3227
307 maya 3393 /* setup window */
308     if (ts.EnableScrollBuff>0) {
309     if (ts.ScrollBuffSize < NumOfLines) {
310     ts.ScrollBuffSize = NumOfLines;
311     }
312     Ny = ts.ScrollBuffSize;
313     }
314     else {
315     Ny = NumOfLines;
316     }
317 maya 3227
318 maya 3393 if (! ChangeBuffer(NumOfColumns,Ny)) {
319     PostQuitMessage(0);
320     }
321 maya 3227
322 maya 3393 if (ts.EnableScrollBuff>0) {
323     ts.ScrollBuffSize = NumOfLinesInBuff;
324     }
325 maya 3227
326 maya 3393 StatusLine = 0;
327 maya 3227 }
328    
329     void NewLine(int Line)
330     {
331 maya 3393 LinePtr = GetLinePtr(Line);
332     CodeLine = &CodeBuff[LinePtr];
333     AttrLine = &AttrBuff[LinePtr];
334     AttrLine2 = &AttrBuff2[LinePtr];
335     AttrLineFG = &AttrBuffFG[LinePtr];
336     AttrLineBG = &AttrBuffBG[LinePtr];
337 maya 3227 }
338    
339     void LockBuffer()
340     {
341 maya 3393 BuffLock++;
342     if (BuffLock>1) {
343     return;
344     }
345     CodeBuff = (PCHAR)GlobalLock(HCodeBuff);
346     AttrBuff = (PCHAR)GlobalLock(HAttrBuff);
347     AttrBuff2 = (PCHAR)GlobalLock(HAttrBuff2);
348     AttrBuffFG = (PCHAR)GlobalLock(HAttrBuffFG);
349     AttrBuffBG = (PCHAR)GlobalLock(HAttrBuffBG);
350     NewLine(PageStart+CursorY);
351 maya 3227 }
352    
353     void UnlockBuffer()
354     {
355 maya 3393 if (BuffLock==0) {
356     return;
357     }
358     BuffLock--;
359     if (BuffLock>0) {
360     return;
361     }
362     if (HCodeBuff!=NULL) {
363     GlobalUnlock(HCodeBuff);
364     }
365     if (HAttrBuff!=NULL) {
366     GlobalUnlock(HAttrBuff);
367     }
368     if (HAttrBuff2!=NULL) {
369     GlobalUnlock(HAttrBuff2);
370     }
371     if (HAttrBuffFG!=NULL) {
372     GlobalUnlock(HAttrBuffFG);
373     }
374     if (HAttrBuffBG!=NULL) {
375     GlobalUnlock(HAttrBuffBG);
376     }
377 maya 3227 }
378    
379     void FreeBuffer()
380     {
381 maya 3393 BuffLock = 1;
382     UnlockBuffer();
383     if (HCodeBuff!=NULL) {
384     GlobalFree(HCodeBuff);
385     HCodeBuff = NULL;
386     }
387     if (HAttrBuff!=NULL) {
388     GlobalFree(HAttrBuff);
389     HAttrBuff = NULL;
390     }
391     if (HAttrBuff2!=NULL) {
392     GlobalFree(HAttrBuff2);
393     HAttrBuff2 = NULL;
394     }
395     if (HAttrBuffFG!=NULL) {
396     GlobalFree(HAttrBuffFG);
397     HAttrBuffFG = NULL;
398     }
399     if (HAttrBuffBG!=NULL) {
400     GlobalFree(HAttrBuffBG);
401     HAttrBuffBG = NULL;
402     }
403 maya 3227 }
404    
405     void BuffAllSelect()
406     {
407     SelectStart.x = 0;
408     SelectStart.y = 0;
409     SelectEnd.x = 0;
410     SelectEnd.y = BuffEnd;
411     // SelectEnd.x = NumOfColumns;
412     // SelectEnd.y = BuffEnd - 1;
413     }
414    
415     void BuffScreenSelect()
416     {
417     int X, Y;
418     DispConvWinToScreen(0, 0, &X, &Y, NULL);
419     SelectStart.x = X;
420     SelectStart.y = Y + PageStart;
421     SelectEnd.x = 0;
422     SelectEnd.y = SelectStart.y + NumOfLines;
423     // SelectEnd.x = X + NumOfColumns;
424     // SelectEnd.y = Y + PageStart + NumOfLines - 1;
425     }
426    
427     void BuffCancelSelection()
428     {
429     SelectStart.x = 0;
430     SelectStart.y = 0;
431     SelectEnd.x = 0;
432     SelectEnd.y = 0;
433     }
434    
435     void BuffReset()
436     // Reset buffer status. don't update real display
437     // called by ResetTerminal()
438     {
439 maya 3393 int i;
440 maya 3227
441 maya 3393 /* Cursor */
442     NewLine(PageStart);
443     WinOrgX = 0;
444     WinOrgY = 0;
445     NewOrgX = 0;
446     NewOrgY = 0;
447 maya 3227
448 maya 3393 /* Top/bottom margin */
449     CursorTop = 0;
450     CursorBottom = NumOfLines-1;
451 maya 3227
452 maya 3393 /* Tab stops */
453     NTabStops = (NumOfColumns-1) >> 3;
454     for (i=1 ; i<=NTabStops ; i++) {
455     TabStops[i-1] = i*8;
456     }
457 maya 3227
458 maya 3393 /* Initialize text selection region */
459     SelectStart.x = 0;
460     SelectStart.y = 0;
461     SelectEnd = SelectStart;
462     SelectEndOld = SelectStart;
463     Selected = FALSE;
464 maya 3227
465 maya 3393 StrChangeCount = 0;
466     Wrap = FALSE;
467     StatusLine = 0;
468 maya 3227
469 maya 3393 SeveralPageSelect = FALSE; // yutaka
470 maya 3227 }
471    
472     void BuffScroll(int Count, int Bottom)
473     {
474 maya 3393 int i, n;
475     LONG SrcPtr, DestPtr;
476     int BuffEndOld;
477 maya 3227
478 maya 3393 if (Count>NumOfLinesInBuff) {
479     Count = NumOfLinesInBuff;
480     }
481 maya 3227
482 maya 3393 DestPtr = GetLinePtr(PageStart+NumOfLines-1+Count);
483     n = Count;
484     if (Bottom<NumOfLines-1) {
485     SrcPtr = GetLinePtr(PageStart+NumOfLines-1);
486     for (i=NumOfLines-1; i>=Bottom+1; i--) {
487     memcpy(&(CodeBuff[DestPtr]),&(CodeBuff[SrcPtr]),NumOfColumns);
488     memcpy(&(AttrBuff[DestPtr]),&(AttrBuff[SrcPtr]),NumOfColumns);
489     memcpy(&(AttrBuff2[DestPtr]),&(AttrBuff2[SrcPtr]),NumOfColumns);
490     memcpy(&(AttrBuffFG[DestPtr]),&(AttrBuffFG[SrcPtr]),NumOfColumns);
491     memcpy(&(AttrBuffBG[DestPtr]),&(AttrBuffBG[SrcPtr]),NumOfColumns);
492     memset(&(CodeBuff[SrcPtr]),0x20,NumOfColumns);
493     memset(&(AttrBuff[SrcPtr]),AttrDefault,NumOfColumns);
494     memset(&(AttrBuff2[SrcPtr]),CurCharAttr.Attr2,NumOfColumns);
495     memset(&(AttrBuffFG[SrcPtr]),CurCharAttr.Fore,NumOfColumns);
496     memset(&(AttrBuffBG[SrcPtr]),CurCharAttr.Back,NumOfColumns);
497     SrcPtr = PrevLinePtr(SrcPtr);
498     DestPtr = PrevLinePtr(DestPtr);
499     n--;
500     }
501     }
502     for (i = 1 ; i <= n ; i++) {
503     memset(&CodeBuff[DestPtr],0x20,NumOfColumns);
504     memset(&AttrBuff[DestPtr],AttrDefault,NumOfColumns);
505     memset(&AttrBuff2[DestPtr],CurCharAttr.Attr2,NumOfColumns);
506     memset(&AttrBuffFG[DestPtr],CurCharAttr.Fore,NumOfColumns);
507     memset(&AttrBuffBG[DestPtr],CurCharAttr.Back,NumOfColumns);
508     DestPtr = PrevLinePtr(DestPtr);
509     }
510 maya 3227
511 maya 3393 BuffEndAbs = BuffEndAbs + Count;
512     if (BuffEndAbs >= NumOfLinesInBuff) {
513     BuffEndAbs = BuffEndAbs - NumOfLinesInBuff;
514     }
515     BuffEndOld = BuffEnd;
516     BuffEnd = BuffEnd + Count;
517     if (BuffEnd >= NumOfLinesInBuff) {
518     BuffEnd = NumOfLinesInBuff;
519     BuffStartAbs = BuffEndAbs;
520     }
521     PageStart = BuffEnd-NumOfLines;
522 maya 3227
523 maya 3393 if (Selected) {
524     SelectStart.y = SelectStart.y - Count + BuffEnd - BuffEndOld;
525     SelectEnd.y = SelectEnd.y - Count + BuffEnd - BuffEndOld;
526     if ( SelectStart.y<0 ) {
527     SelectStart.x = 0;
528     SelectStart.y = 0;
529     }
530     if ( SelectEnd.y<0 ) {
531     SelectEnd.x = 0;
532     SelectEnd.y = 0;
533     }
534     Selected = (SelectEnd.y > SelectStart.y) ||
535     ((SelectEnd.y==SelectStart.y) &&
536     (SelectEnd.x > SelectStart.x));
537     }
538 maya 3227
539 maya 3393 NewLine(PageStart+CursorY);
540 maya 3227 }
541    
542     void NextLine()
543     {
544 maya 3393 LinePtr = NextLinePtr(LinePtr);
545     CodeLine = &CodeBuff[LinePtr];
546     AttrLine = &AttrBuff[LinePtr];
547     AttrLine2 = &AttrBuff2[LinePtr];
548     AttrLineFG = &AttrBuffFG[LinePtr];
549     AttrLineBG = &AttrBuffBG[LinePtr];
550 maya 3227 }
551    
552     void PrevLine()
553     {
554 maya 3393 LinePtr = PrevLinePtr(LinePtr);
555     CodeLine = &CodeBuff[LinePtr];
556     AttrLine = &AttrBuff[LinePtr];
557     AttrLine2 = &AttrBuff2[LinePtr];
558     AttrLineFG = &AttrBuffFG[LinePtr];
559     AttrLineBG = &AttrBuffBG[LinePtr];
560 maya 3227 }
561    
562     void EraseKanji(int LR)
563     {
564     // If cursor is on left/right half of a Kanji, erase it.
565     // LR: left(0)/right(1) flag
566    
567 maya 3393 if ((CursorX-LR>=0) &&
568     ((AttrLine[CursorX-LR] & AttrKanji) != 0)) {
569     CodeLine[CursorX-LR] = 0x20;
570     AttrLine[CursorX-LR] = CurCharAttr.Attr;
571     AttrLine2[CursorX-LR] = CurCharAttr.Attr2;
572     AttrLineFG[CursorX-LR] = CurCharAttr.Fore;
573     AttrLineBG[CursorX-LR] = CurCharAttr.Back;
574     if (CursorX-LR+1 < NumOfColumns) {
575     CodeLine[CursorX-LR+1] = 0x20;
576     AttrLine[CursorX-LR+1] = CurCharAttr.Attr;
577     AttrLine2[CursorX-LR+1] = CurCharAttr.Attr2;
578     AttrLineFG[CursorX-LR+1] = CurCharAttr.Fore;
579     AttrLineBG[CursorX-LR+1] = CurCharAttr.Back;
580     }
581     }
582 maya 3227 }
583    
584     void BuffInsertSpace(int Count)
585     // Insert space characters at the current position
586     // Count: Number of characters to be inserted
587     {
588 maya 3393 NewLine(PageStart+CursorY);
589 maya 3227
590 doda 3416 if (ts.Language==IdJapanese || ts.Language==IdKorean || ts.Language==IdUtf8) {
591 maya 3393 EraseKanji(1); /* if cursor is on right half of a kanji, erase the kanji */
592     }
593 maya 3227
594 maya 3393 if (Count > NumOfColumns - CursorX) {
595     Count = NumOfColumns - CursorX;
596     }
597 maya 3227
598 maya 3393 memmove(&(CodeLine[CursorX+Count]),&(CodeLine[CursorX]),
599     NumOfColumns-Count-CursorX);
600     memmove(&(AttrLine[CursorX+Count]),&(AttrLine[CursorX]),
601     NumOfColumns-Count-CursorX);
602     memmove(&(AttrLine2[CursorX+Count]),&(AttrLine2[CursorX]),
603     NumOfColumns-Count-CursorX);
604     memmove(&(AttrLineFG[CursorX+Count]),&(AttrLineFG[CursorX]),
605     NumOfColumns-Count-CursorX);
606     memmove(&(AttrLineBG[CursorX+Count]),&(AttrLineBG[CursorX]),
607     NumOfColumns-Count-CursorX);
608     memset(&(CodeLine[CursorX]),0x20,Count);
609     memset(&(AttrLine[CursorX]),AttrDefault,Count);
610     memset(&(AttrLine2[CursorX]),CurCharAttr.Attr2,Count);
611     memset(&(AttrLineFG[CursorX]),CurCharAttr.Fore,Count);
612     memset(&(AttrLineBG[CursorX]),CurCharAttr.Back,Count);
613     /* last char in current line is kanji first? */
614     if ((AttrLine[NumOfColumns-1] & AttrKanji) != 0) {
615     /* then delete it */
616     CodeLine[NumOfColumns-1] = 0x20;
617     AttrLine[NumOfColumns-1] = AttrDefault;
618     AttrLine2[NumOfColumns-1] = CurCharAttr.Attr2;
619     AttrLineFG[NumOfColumns-1] = CurCharAttr.Fore;
620     AttrLineBG[NumOfColumns-1] = CurCharAttr.Back;
621     }
622     BuffUpdateRect(CursorX,CursorY,NumOfColumns-1,CursorY);
623 maya 3227 }
624    
625     void BuffEraseCurToEnd()
626     // Erase characters from cursor to the end of screen
627     {
628 maya 3393 LONG TmpPtr;
629     int offset;
630     int i, YEnd;
631 maya 3227
632 maya 3393 NewLine(PageStart+CursorY);
633 doda 3416 if (ts.Language==IdJapanese || ts.Language==IdKorean || ts.Language==IdUtf8) {
634 maya 3393 EraseKanji(1); /* if cursor is on right half of a kanji, erase the kanji */
635     }
636     offset = CursorX;
637     TmpPtr = GetLinePtr(PageStart+CursorY);
638     YEnd = NumOfLines-1;
639     if ((StatusLine>0) &&
640     (CursorY<NumOfLines-1)) {
641     YEnd--;
642     }
643     for (i = CursorY ; i <= YEnd ; i++) {
644     memset(&(CodeBuff[TmpPtr+offset]),0x20,NumOfColumns-offset);
645     memset(&(AttrBuff[TmpPtr+offset]),AttrDefault,NumOfColumns-offset);
646     memset(&(AttrBuff2[TmpPtr+offset]),CurCharAttr.Attr2,NumOfColumns-offset);
647     memset(&(AttrBuffFG[TmpPtr+offset]),CurCharAttr.Fore,NumOfColumns-offset);
648     memset(&(AttrBuffBG[TmpPtr+offset]),CurCharAttr.Back,NumOfColumns-offset);
649     offset = 0;
650     TmpPtr = NextLinePtr(TmpPtr);
651     }
652     /* update window */
653     DispEraseCurToEnd(YEnd);
654 maya 3227 }
655    
656     void BuffEraseHomeToCur()
657     // Erase characters from home to cursor
658     {
659 maya 3393 LONG TmpPtr;
660     int offset;
661     int i, YHome;
662 maya 3227
663 maya 3393 NewLine(PageStart+CursorY);
664 doda 3416 if (ts.Language==IdJapanese || ts.Language==IdKorean || ts.Language==IdUtf8) {
665 maya 3393 EraseKanji(0); /* if cursor is on left half of a kanji, erase the kanji */
666     }
667     offset = NumOfColumns;
668     if ((StatusLine>0) && (CursorY==NumOfLines-1)) {
669     YHome = CursorY;
670     }
671     else {
672     YHome = 0;
673     }
674     TmpPtr = GetLinePtr(PageStart+YHome);
675     for (i = YHome ; i <= CursorY ; i++) {
676     if (i==CursorY) {
677     offset = CursorX+1;
678     }
679     memset(&(CodeBuff[TmpPtr]),0x20,offset);
680     memset(&(AttrBuff[TmpPtr]),AttrDefault,offset);
681     memset(&(AttrBuff2[TmpPtr]),CurCharAttr.Attr2,offset);
682     memset(&(AttrBuffFG[TmpPtr]),CurCharAttr.Fore,offset);
683     memset(&(AttrBuffBG[TmpPtr]),CurCharAttr.Back,offset);
684     TmpPtr = NextLinePtr(TmpPtr);
685     }
686 maya 3227
687 maya 3393 /* update window */
688     DispEraseHomeToCur(YHome);
689 maya 3227 }
690    
691     void BuffInsertLines(int Count, int YEnd)
692     // Insert lines at current position
693     // Count: number of lines to be inserted
694     // YEnd: bottom line number of scroll region (screen coordinate)
695     {
696 maya 3393 int i;
697     LONG SrcPtr, DestPtr;
698 maya 3227
699 maya 3393 BuffUpdateScroll();
700 maya 3227
701 maya 3393 SrcPtr = GetLinePtr(PageStart+YEnd-Count);
702     DestPtr = GetLinePtr(PageStart+YEnd);
703     for (i= YEnd-Count ; i>=CursorY ; i--) {
704     memcpy(&(CodeBuff[DestPtr]),&(CodeBuff[SrcPtr]),NumOfColumns);
705     memcpy(&(AttrBuff[DestPtr]),&(AttrBuff[SrcPtr]),NumOfColumns);
706     memcpy(&(AttrBuff2[DestPtr]),&(AttrBuff2[SrcPtr]),NumOfColumns);
707     memcpy(&(AttrBuffFG[DestPtr]),&(AttrBuffFG[SrcPtr]),NumOfColumns);
708     memcpy(&(AttrBuffBG[DestPtr]),&(AttrBuffBG[SrcPtr]),NumOfColumns);
709     SrcPtr = PrevLinePtr(SrcPtr);
710     DestPtr = PrevLinePtr(DestPtr);
711     }
712     for (i = 1 ; i <= Count ; i++) {
713     memset(&(CodeBuff[DestPtr]),0x20,NumOfColumns);
714     memset(&(AttrBuff[DestPtr]),AttrDefault,NumOfColumns);
715     memset(&(AttrBuff2[DestPtr]),CurCharAttr.Attr2,NumOfColumns);
716     memset(&(AttrBuffFG[DestPtr]),CurCharAttr.Fore,NumOfColumns);
717     memset(&(AttrBuffBG[DestPtr]),CurCharAttr.Back,NumOfColumns);
718     DestPtr = PrevLinePtr(DestPtr);
719     }
720 maya 3227
721 maya 3393 if (! DispInsertLines(Count,YEnd)) {
722     BuffUpdateRect(WinOrgX,CursorY,WinOrgX+WinWidth-1,YEnd);
723     }
724 maya 3227 }
725    
726     void BuffEraseCharsInLine(int XStart, int Count)
727     // erase characters in the current line
728     // XStart: start position of erasing
729     // Count: number of characters to be erased
730     {
731 doda 3312 #ifndef NO_COPYLINE_FIX
732 maya 3393 BOOL LineContinued=FALSE;
733 doda 3312
734 maya 3393 if (ts.EnableContinuedLineCopy && XStart == 0 && (AttrLine[0] & AttrLineContinued)) {
735     LineContinued = TRUE;
736     }
737 doda 3312 #endif /* NO_COPYLINE_FIX */
738    
739 doda 3416 if (ts.Language==IdJapanese || ts.Language==IdKorean || ts.Language==IdUtf8) {
740 maya 3393 EraseKanji(1); /* if cursor is on right half of a kanji, erase the kanji */
741     }
742 maya 3227
743 maya 3393 NewLine(PageStart+CursorY);
744     memset(&(CodeLine[XStart]),0x20,Count);
745     memset(&(AttrLine[XStart]),AttrDefault,Count);
746     memset(&(AttrLine2[XStart]),CurCharAttr.Attr2,Count);
747     memset(&(AttrLineFG[XStart]),CurCharAttr.Fore,Count);
748     memset(&(AttrLineBG[XStart]),CurCharAttr.Back,Count);
749 maya 3227
750 doda 3312 #ifndef NO_COPYLINE_FIX
751 maya 3393 if (ts.EnableContinuedLineCopy) {
752     if (LineContinued) {
753     BuffLineContinued(TRUE);
754     }
755    
756     if (XStart + Count >= NumOfColumns) {
757     AttrBuff[NextLinePtr(LinePtr)] &= ~AttrLineContinued;
758     }
759     }
760 doda 3312 #endif /* NO_COPYLINE_FIX */
761    
762 maya 3393 DispEraseCharsInLine(XStart, Count);
763 maya 3227 }
764    
765     void BuffDeleteLines(int Count, int YEnd)
766     // Delete lines from current line
767     // Count: number of lines to be deleted
768     // YEnd: bottom line number of scroll region (screen coordinate)
769     {
770 maya 3393 int i;
771     LONG SrcPtr, DestPtr;
772 maya 3227
773 maya 3393 BuffUpdateScroll();
774 maya 3227
775 maya 3393 SrcPtr = GetLinePtr(PageStart+CursorY+Count);
776     DestPtr = GetLinePtr(PageStart+CursorY);
777     for (i=CursorY ; i<= YEnd-Count ; i++) {
778     memcpy(&(CodeBuff[DestPtr]),&(CodeBuff[SrcPtr]),NumOfColumns);
779     memcpy(&(AttrBuff[DestPtr]),&(AttrBuff[SrcPtr]),NumOfColumns);
780     memcpy(&(AttrBuff2[DestPtr]),&(AttrBuff2[SrcPtr]),NumOfColumns);
781     memcpy(&(AttrBuffFG[DestPtr]),&(AttrBuffFG[SrcPtr]),NumOfColumns);
782     memcpy(&(AttrBuffBG[DestPtr]),&(AttrBuffBG[SrcPtr]),NumOfColumns);
783     SrcPtr = NextLinePtr(SrcPtr);
784     DestPtr = NextLinePtr(DestPtr);
785     }
786     for (i = YEnd+1-Count ; i<=YEnd ; i++) {
787     memset(&(CodeBuff[DestPtr]),0x20,NumOfColumns);
788     memset(&(AttrBuff[DestPtr]),AttrDefault,NumOfColumns);
789     memset(&(AttrBuff2[DestPtr]),CurCharAttr.Attr2,NumOfColumns);
790     memset(&(AttrBuffFG[DestPtr]),CurCharAttr.Fore,NumOfColumns);
791     memset(&(AttrBuffBG[DestPtr]),CurCharAttr.Back,NumOfColumns);
792     DestPtr = NextLinePtr(DestPtr);
793     }
794 maya 3227
795 maya 3393 if (! DispDeleteLines(Count,YEnd)) {
796     BuffUpdateRect(WinOrgX,CursorY,WinOrgX+WinWidth-1,YEnd);
797     }
798 maya 3227 }
799    
800     void BuffDeleteChars(int Count)
801     // Delete characters in current line from cursor
802     // Count: number of characters to be deleted
803     {
804 maya 3393 NewLine(PageStart+CursorY);
805 maya 3227
806 doda 3416 if (ts.Language==IdJapanese || ts.Language==IdKorean || ts.Language==IdUtf8) {
807 maya 3393 EraseKanji(0); /* if cursor is on left harf of a kanji, erase the kanji */
808     EraseKanji(1); /* if cursor on right half... */
809     }
810 maya 3227
811 maya 3393 if (Count > NumOfColumns-CursorX) {
812     Count = NumOfColumns-CursorX;
813     }
814     memmove(&(CodeLine[CursorX]),&(CodeLine[CursorX+Count]),
815     NumOfColumns-Count-CursorX);
816     memmove(&(AttrLine[CursorX]),&(AttrLine[CursorX+Count]),
817     NumOfColumns-Count-CursorX);
818     memmove(&(AttrLine2[CursorX]),&(AttrLine2[CursorX+Count]),
819     NumOfColumns-Count-CursorX);
820     memmove(&(AttrLineFG[CursorX]),&(AttrLineFG[CursorX+Count]),
821     NumOfColumns-Count-CursorX);
822     memmove(&(AttrLineBG[CursorX]),&(AttrLineBG[CursorX+Count]),
823     NumOfColumns-Count-CursorX);
824     memset(&(CodeLine[NumOfColumns-Count]),0x20,Count);
825     memset(&(AttrLine[NumOfColumns-Count]),AttrDefault,Count);
826     memset(&(AttrLine2[NumOfColumns-Count]),CurCharAttr.Attr2,Count);
827     memset(&(AttrLineFG[NumOfColumns-Count]),CurCharAttr.Fore,Count);
828     memset(&(AttrLineBG[NumOfColumns-Count]),CurCharAttr.Back,Count);
829 maya 3227
830 maya 3393 BuffUpdateRect(CursorX,CursorY,WinOrgX+WinWidth-1,CursorY);
831 maya 3227 }
832    
833     void BuffEraseChars(int Count)
834     // Erase characters in current line from cursor
835     // Count: number of characters to be deleted
836     {
837 maya 3393 NewLine(PageStart+CursorY);
838 maya 3227
839 doda 3416 if (ts.Language==IdJapanese || ts.Language==IdKorean || ts.Language==IdUtf8) {
840 maya 3393 EraseKanji(0); /* if cursor is on left harf of a kanji, erase the kanji */
841     EraseKanji(1); /* if cursor on right half... */
842     }
843 maya 3227
844 maya 3393 if (Count > NumOfColumns-CursorX) {
845     Count = NumOfColumns-CursorX;
846     }
847     memset(&(CodeLine[CursorX]),0x20,Count);
848     memset(&(AttrLine[CursorX]),AttrDefault,Count);
849     memset(&(AttrLine2[CursorX]),CurCharAttr.Attr2,Count);
850     memset(&(AttrLineFG[CursorX]),CurCharAttr.Fore,Count);
851     memset(&(AttrLineBG[CursorX]),CurCharAttr.Back,Count);
852 maya 3227
853 maya 3393 /* update window */
854     DispEraseCharsInLine(CursorX,Count);
855 maya 3227 }
856    
857     void BuffFillWithE()
858     // Fill screen with 'E' characters
859     {
860 maya 3393 LONG TmpPtr;
861     int i;
862 maya 3227
863 maya 3393 TmpPtr = GetLinePtr(PageStart);
864     for (i = 0 ; i <= NumOfLines-1-StatusLine ; i++) {
865     memset(&(CodeBuff[TmpPtr]),'E',NumOfColumns);
866     memset(&(AttrBuff[TmpPtr]),AttrDefault,NumOfColumns);
867     memset(&(AttrBuff2[TmpPtr]),AttrDefault,NumOfColumns);
868     memset(&(AttrBuffFG[TmpPtr]),AttrDefaultFG,NumOfColumns);
869     memset(&(AttrBuffBG[TmpPtr]),AttrDefaultBG,NumOfColumns);
870     TmpPtr = NextLinePtr(TmpPtr);
871     }
872     BuffUpdateRect(WinOrgX,WinOrgY,WinOrgX+WinWidth-1,WinOrgY+WinHeight-1);
873 maya 3227 }
874    
875     void BuffDrawLine(TCharAttr Attr, int Direction, int C)
876     { // IO-8256 terminal
877 maya 3393 LONG Ptr;
878     int i, X, Y;
879 maya 3227
880 maya 3393 if (C==0) {
881     return;
882     }
883     Attr.Attr |= AttrSpecial;
884 maya 3227
885 maya 3393 switch (Direction) {
886     case 3:
887     case 4:
888     if (Direction==3) {
889     if (CursorY==0) {
890     return;
891     }
892     Y = CursorY-1;
893     }
894     else {
895     if (CursorY==NumOfLines-1-StatusLine) {
896     return;
897     }
898     Y = CursorY+1;
899     }
900     if (CursorX+C > NumOfColumns) {
901     C = NumOfColumns-CursorX;
902     }
903     Ptr = GetLinePtr(PageStart+Y);
904     memset(&(CodeBuff[Ptr+CursorX]),'q',C);
905     memset(&(AttrBuff[Ptr+CursorX]),Attr.Attr,C);
906     memset(&(AttrBuff2[Ptr+CursorX]),Attr.Attr2,C);
907     memset(&(AttrBuffFG[Ptr+CursorX]),Attr.Fore,C);
908     memset(&(AttrBuffBG[Ptr+CursorX]),Attr.Back,C);
909     BuffUpdateRect(CursorX,Y,CursorX+C-1,Y);
910     break;
911     case 5:
912     case 6:
913     if (Direction==5) {
914     if (CursorX==0) {
915     return;
916     }
917     X = CursorX - 1;
918     }
919     else {
920     if (CursorX==NumOfColumns-1) {
921     X = CursorX-1;
922     }
923     else {
924     X = CursorX+1;
925     }
926     }
927     Ptr = GetLinePtr(PageStart+CursorY);
928     if (CursorY+C > NumOfLines-StatusLine) {
929     C = NumOfLines-StatusLine-CursorY;
930     }
931     for (i=1; i<=C; i++) {
932     CodeBuff[Ptr+X] = 'x';
933     AttrBuff[Ptr+X] = Attr.Attr;
934     AttrBuff2[Ptr+X] = Attr.Attr2;
935     AttrBuffFG[Ptr+X] = Attr.Fore;
936     AttrBuffBG[Ptr+X] = Attr.Back;
937     Ptr = NextLinePtr(Ptr);
938     }
939     BuffUpdateRect(X,CursorY,X,CursorY+C-1);
940     break;
941     }
942 maya 3227 }
943    
944     void BuffEraseBox
945     (int XStart, int YStart, int XEnd, int YEnd)
946     // IO-8256 terminal
947     {
948 maya 3393 int C, i;
949     LONG Ptr;
950 maya 3227
951 maya 3393 if (XEnd>NumOfColumns-1) {
952     XEnd = NumOfColumns-1;
953     }
954     if (YEnd>NumOfLines-1-StatusLine) {
955     YEnd = NumOfLines-1-StatusLine;
956     }
957     if (XStart>XEnd) {
958     return;
959     }
960     if (YStart>YEnd) {
961     return;
962     }
963     C = XEnd-XStart+1;
964     Ptr = GetLinePtr(PageStart+YStart);
965     for (i=YStart; i<=YEnd; i++) {
966     if ((XStart>0) &&
967     ((AttrBuff[Ptr+XStart-1] & AttrKanji) != 0)) {
968     CodeBuff[Ptr+XStart-1] = 0x20;
969     AttrBuff[Ptr+XStart-1] = CurCharAttr.Attr;
970     AttrBuff2[Ptr+XStart-1] = CurCharAttr.Attr2;
971     AttrBuffFG[Ptr+XStart-1] = CurCharAttr.Fore;
972     AttrBuffBG[Ptr+XStart-1] = CurCharAttr.Back;
973     }
974     if ((XStart+C<NumOfColumns) &&
975     ((AttrBuff[Ptr+XStart+C-1] & AttrKanji) != 0)) {
976     CodeBuff[Ptr+XStart+C] = 0x20;
977     AttrBuff[Ptr+XStart+C] = CurCharAttr.Attr;
978     AttrBuff2[Ptr+XStart+C] = CurCharAttr.Attr2;
979     AttrBuffFG[Ptr+XStart+C] = CurCharAttr.Fore;
980     AttrBuffBG[Ptr+XStart+C] = CurCharAttr.Back;
981     }
982     memset(&(CodeBuff[Ptr+XStart]),0x20,C);
983     memset(&(AttrBuff[Ptr+XStart]),AttrDefault,C);
984     memset(&(AttrBuff2[Ptr+XStart]),CurCharAttr.Attr2,C);
985     memset(&(AttrBuffFG[Ptr+XStart]),CurCharAttr.Fore,C);
986     memset(&(AttrBuffBG[Ptr+XStart]),CurCharAttr.Back,C);
987     Ptr = NextLinePtr(Ptr);
988     }
989     BuffUpdateRect(XStart,YStart,XEnd,YEnd);
990 maya 3227 }
991    
992     int LeftHalfOfDBCS(LONG Line, int CharPtr)
993     // If CharPtr is on the right half of a DBCS character,
994     // return pointer to the left half
995     // Line: points to a line in CodeBuff
996     // CharPtr: points to a char
997     // return: points to the left half of the DBCS
998     {
999 maya 3393 if ((CharPtr>0) &&
1000     ((AttrBuff[Line+CharPtr-1] & AttrKanji) != 0)) {
1001     CharPtr--;
1002     }
1003     return CharPtr;
1004 maya 3227 }
1005    
1006     int MoveCharPtr(LONG Line, int *x, int dx)
1007     // move character pointer x by dx character unit
1008     // in the line specified by Line
1009     // Line: points to a line in CodeBuff
1010     // x: points to a character in the line
1011     // dx: moving distance in character unit (-: left, +: right)
1012 maya 3393 // One DBCS character is counted as one character.
1013 maya 3227 // The pointer stops at the beginning or the end of line.
1014     // Output
1015     // x: new pointer. x points to a SBCS character or
1016     // the left half of a DBCS character.
1017     // return: actual moving distance in character unit
1018     {
1019 maya 3393 int i;
1020 maya 3227
1021 maya 3393 *x = LeftHalfOfDBCS(Line,*x);
1022     i = 0;
1023     while (dx!=0) {
1024     if (dx>0) { // move right
1025     if ((AttrBuff[Line+*x] & AttrKanji) != 0) {
1026     if (*x<NumOfColumns-2) {
1027     i++;
1028     *x = *x + 2;
1029     }
1030     }
1031     else if (*x<NumOfColumns-1) {
1032     i++;
1033     (*x)++;
1034     }
1035     dx--;
1036     }
1037     else { // move left
1038     if (*x>0) {
1039     i--;
1040     (*x)--;
1041     }
1042     *x = LeftHalfOfDBCS(Line,*x);
1043     dx++;
1044     }
1045 maya 3227 }
1046 maya 3393 return i;
1047 maya 3227 }
1048    
1049     void BuffCBCopy(BOOL Table)
1050     // copy selected text to clipboard
1051     {
1052 maya 3393 LONG MemSize;
1053     PCHAR CBPtr;
1054     LONG TmpPtr;
1055     int i, j, k, IStart, IEnd;
1056     BOOL Sp, FirstChar;
1057     BYTE b;
1058 maya 3227 #ifndef NO_COPYLINE_FIX
1059 maya 3393 BOOL LineContinued, PrevLineContinued;
1060     LineContinued = FALSE;
1061 maya 3227 #endif /* NO_COPYLINE_FIX */
1062    
1063 maya 3393 if (TalkStatus==IdTalkCB) {
1064     return;
1065     }
1066     if (! Selected) {
1067     return;
1068     }
1069 maya 3227
1070     // --- open clipboard and get CB memory
1071 maya 3393 if (BoxSelect) {
1072     MemSize = (SelectEnd.x-SelectStart.x+3)*
1073     (SelectEnd.y-SelectStart.y+1) + 1;
1074     }
1075     else {
1076     MemSize = (SelectEnd.y-SelectStart.y)*
1077     (NumOfColumns+2) +
1078     SelectEnd.x - SelectStart.x + 1;
1079     }
1080     CBPtr = CBOpen(MemSize);
1081     if (CBPtr==NULL) {
1082     return;
1083     }
1084 maya 3227
1085     // --- copy selected text to CB memory
1086 maya 3393 LockBuffer();
1087 maya 3227
1088 maya 3393 CBPtr[0] = 0;
1089     TmpPtr = GetLinePtr(SelectStart.y);
1090     k = 0;
1091     for (j = SelectStart.y ; j<=SelectEnd.y ; j++) {
1092     if (BoxSelect) {
1093     IStart = SelectStart.x;
1094     IEnd = SelectEnd.x-1;
1095     }
1096     else {
1097     IStart = 0;
1098     IEnd = NumOfColumns-1;
1099     if (j==SelectStart.y) {
1100     IStart = SelectStart.x;
1101     }
1102     if (j==SelectEnd.y) {
1103     IEnd = SelectEnd.x-1;
1104     }
1105     }
1106     i = LeftHalfOfDBCS(TmpPtr,IStart);
1107     if (i!=IStart) {
1108     if (j==SelectStart.y) {
1109     IStart = i;
1110     }
1111     else {
1112     IStart = i + 2;
1113     }
1114     }
1115 maya 3227
1116 maya 3393 // exclude right-side space characters
1117     IEnd = LeftHalfOfDBCS(TmpPtr,IEnd);
1118 maya 3227 #ifndef NO_COPYLINE_FIX
1119 maya 3393 PrevLineContinued = LineContinued;
1120     LineContinued = FALSE;
1121     if (ts.EnableContinuedLineCopy && j!=SelectEnd.y && !BoxSelect) {
1122     LONG NextTmpPtr = NextLinePtr(TmpPtr);
1123     if ((AttrBuff[NextTmpPtr] & AttrLineContinued) != 0) {
1124     LineContinued = TRUE;
1125     }
1126     if (IEnd == NumOfColumns-1 &&
1127     (AttrBuff[TmpPtr + IEnd] & AttrLineContinued) != 0) {
1128     MoveCharPtr(TmpPtr,&IEnd,-1);
1129     }
1130     }
1131     if (!LineContinued)
1132 maya 3227 #endif /* NO_COPYLINE_FIX */
1133 maya 3393 while ((IEnd>0) && (CodeBuff[TmpPtr+IEnd]==0x20)) {
1134     MoveCharPtr(TmpPtr,&IEnd,-1);
1135     }
1136     if ((IEnd==0) && (CodeBuff[TmpPtr]==0x20)) {
1137     IEnd = -1;
1138     }
1139     else if ((AttrBuff[TmpPtr+IEnd] & AttrKanji) != 0) { /* DBCS first byte? */
1140     IEnd++;
1141     }
1142 maya 3227
1143 maya 3393 Sp = FALSE;
1144     FirstChar = TRUE;
1145     i = IStart;
1146     while (i <= IEnd) {
1147     b = CodeBuff[TmpPtr+i];
1148     i++;
1149     if (! Sp) {
1150     if ((Table) && (b<=0x20)) {
1151     Sp = TRUE;
1152     b = 0x09;
1153     }
1154 maya 3227 #ifndef NO_COPYLINE_FIX
1155 maya 3393 if ((b!=0x09) || (! FirstChar) || PrevLineContinued) {
1156 maya 3227 #else
1157 maya 3393 if ((b!=0x09) || (! FirstChar)) {
1158 maya 3227 #endif
1159 maya 3393 FirstChar = FALSE;
1160     CBPtr[k] = b;
1161     k++;
1162     }
1163     }
1164     else {
1165     if (b>0x20) {
1166     Sp = FALSE;
1167     FirstChar = FALSE;
1168     CBPtr[k] = b;
1169     k++;
1170     }
1171     }
1172     }
1173 maya 3227
1174     #ifndef NO_COPYLINE_FIX
1175 maya 3393 if (!LineContinued)
1176 maya 3227 #endif /* NO_COPYLINE_FIX */
1177 maya 3393 if (j < SelectEnd.y) {
1178     CBPtr[k] = 0x0d;
1179     k++;
1180     CBPtr[k] = 0x0a;
1181     k++;
1182     }
1183 maya 3227
1184 maya 3393 TmpPtr = NextLinePtr(TmpPtr);
1185     }
1186     CBPtr[k] = 0;
1187 maya 3227 #ifndef NO_COPYLINE_FIX
1188 maya 3393 LineContinued = FALSE;
1189     if (ts.EnableContinuedLineCopy && j!=SelectEnd.y && !BoxSelect && j<BuffEnd-1) {
1190     LONG NextTmpPtr = NextLinePtr(TmpPtr);
1191     if ((AttrBuff[NextTmpPtr] & AttrLineContinued) != 0) {
1192     LineContinued = TRUE;
1193     }
1194     if (IEnd == NumOfColumns-1 &&
1195     (AttrBuff[TmpPtr + IEnd] & AttrLineContinued) != 0) {
1196     MoveCharPtr(TmpPtr,&IEnd,-1);
1197     }
1198     }
1199     if (!LineContinued)
1200 maya 3227 #endif /* NO_COPYLINE_FIX */
1201 maya 3393 UnlockBuffer();
1202 maya 3227
1203     // --- send CB memory to clipboard
1204 maya 3393 CBClose();
1205     return;
1206 maya 3227 }
1207    
1208     void BuffPrint(BOOL ScrollRegion)
1209     // Print screen or selected text
1210     {
1211 maya 3393 int Id;
1212     POINT PrintStart, PrintEnd;
1213     TCharAttr CurAttr, TempAttr;
1214     int i, j, count;
1215     int IStart, IEnd;
1216     LONG TmpPtr;
1217 maya 3227
1218 maya 3393 TempAttr = DefCharAttr;
1219 maya 3227
1220 maya 3393 if (ScrollRegion) {
1221     Id = VTPrintInit(IdPrnScrollRegion);
1222     }
1223     else if (Selected) {
1224     Id = VTPrintInit(IdPrnScreen | IdPrnSelectedText);
1225     }
1226     else {
1227     Id = VTPrintInit(IdPrnScreen);
1228     }
1229     if (Id==IdPrnCancel) {
1230     return;
1231     }
1232 maya 3227
1233 maya 3393 /* set print region */
1234     if (Id==IdPrnSelectedText) {
1235     /* print selected region */
1236     PrintStart = SelectStart;
1237     PrintEnd = SelectEnd;
1238     }
1239     else if (Id==IdPrnScrollRegion) {
1240     /* print scroll region */
1241     PrintStart.x = 0;
1242     PrintStart.y = PageStart + CursorTop;
1243     PrintEnd.x = NumOfColumns;
1244     PrintEnd.y = PageStart + CursorBottom;
1245     }
1246     else {
1247     /* print current screen */
1248     PrintStart.x = 0;
1249     PrintStart.y = PageStart;
1250     PrintEnd.x = NumOfColumns;
1251     PrintEnd.y = PageStart + NumOfLines - 1;
1252     }
1253     if (PrintEnd.y > BuffEnd-1) {
1254     PrintEnd.y = BuffEnd-1;
1255     }
1256 maya 3227
1257 maya 3393 LockBuffer();
1258 maya 3227
1259 maya 3393 TmpPtr = GetLinePtr(PrintStart.y);
1260     for (j = PrintStart.y ; j <= PrintEnd.y ; j++) {
1261     if (j==PrintStart.y) {
1262     IStart = PrintStart.x;
1263     }
1264     else {
1265     IStart = 0;
1266     }
1267     if (j == PrintEnd.y) {
1268     IEnd = PrintEnd.x - 1;
1269     }
1270     else {
1271     IEnd = NumOfColumns - 1;
1272     }
1273 maya 3227
1274 maya 3393 while ((IEnd>=IStart) &&
1275     (CodeBuff[TmpPtr+IEnd]==0x20) &&
1276     (AttrBuff[TmpPtr+IEnd]==AttrDefault) &&
1277     (AttrBuff2[TmpPtr+IEnd]==AttrDefault)) {
1278     IEnd--;
1279     }
1280 maya 3227
1281 maya 3393 i = IStart;
1282     while (i <= IEnd) {
1283     CurAttr.Attr = AttrBuff[TmpPtr+i] & ~ AttrKanji;
1284     CurAttr.Attr2 = AttrBuff2[TmpPtr+i];
1285     CurAttr.Fore = AttrBuffFG[TmpPtr+i];
1286     CurAttr.Back = AttrBuffBG[TmpPtr+i];
1287 maya 3227
1288 maya 3393 count = 1;
1289     while ((i+count <= IEnd) &&
1290     (CurAttr.Attr == (AttrBuff[TmpPtr+i+count] & ~ AttrKanji)) &&
1291     (CurAttr.Attr2 == AttrBuff2[TmpPtr+i+count]) &&
1292     (CurAttr.Fore == AttrBuffFG[TmpPtr+i+count]) &&
1293     (CurAttr.Back == AttrBuffBG[TmpPtr+i+count]) ||
1294     (i+count<NumOfColumns) &&
1295     ((AttrBuff[TmpPtr+i+count-1] & AttrKanji) != 0)) {
1296     count++;
1297     }
1298 maya 3227
1299 maya 3393 if (TCharAttrCmp(CurAttr, TempAttr) != 0) {
1300     PrnSetAttr(CurAttr);
1301     TempAttr = CurAttr;
1302     }
1303     PrnOutText(&(CodeBuff[TmpPtr+i]),count);
1304     i = i+count;
1305     }
1306     PrnNewLine();
1307     TmpPtr = NextLinePtr(TmpPtr);
1308     }
1309 maya 3227
1310 maya 3393 UnlockBuffer();
1311     VTPrintEnd();
1312 maya 3227 }
1313    
1314     void BuffDumpCurrentLine(BYTE TERM)
1315     // Dumps current line to the file (for path through printing)
1316     // HFile: file handle
1317     // TERM: terminator character
1318     // = LF or VT or FF
1319     {
1320 maya 3393 int i, j;
1321 maya 3227
1322 maya 3393 i = NumOfColumns;
1323     while ((i>0) && (CodeLine[i-1]==0x20)) {
1324     i--;
1325     }
1326     for (j=0; j<i; j++) {
1327     WriteToPrnFile(CodeLine[j],FALSE);
1328     }
1329     WriteToPrnFile(0,TRUE);
1330     if ((TERM>=LF) && (TERM<=FF)) {
1331     WriteToPrnFile(0x0d,FALSE);
1332     WriteToPrnFile(TERM,TRUE);
1333     }
1334 maya 3227 }
1335    
1336    
1337     /* begin - ishizaki */
1338     static void markURL(int x)
1339     {
1340     #ifdef URL_EMPHASIS
1341 yutakapon 3414 // RFC3986(Uniform Resource Identifier (URI): Generic Syntax)に準拠する
1342 maya 3227 // by sakura editor 1.5.2.1: etc_uty.cpp
1343     static const char url_char[] = {
1344     /* +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F */
1345     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* +00: */
1346     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* +10: */
1347     0, -1, 0, -1, -1, -1, -1, 0, 0, 0, 0, -1, -1, -1, -1, -1, /* +20: " !"#$%&'()*+,-./" */
1348     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, 0, -1, /* +30: "0123456789:;<=>?" */
1349     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* +40: "@ABCDEFGHIJKLMNO" */
1350     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, 0, 0, -1, /* +50: "PQRSTUVWXYZ[\]^_" */
1351     0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* +60: "`abcdefghijklmno" */
1352 yutakapon 3414 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, -1, 0, /* +70: "pqrstuvwxyz{|}~ " */
1353 maya 3227 /* 0 : not url char
1354     * -1 : url char
1355     * other: url head char --> url_table array number + 1
1356     */
1357     };
1358 yutakapon 3614 static char *prefix[] = {
1359     "https://",
1360     "http://",
1361     "sftp://",
1362     "tftp://",
1363     "news://",
1364     "ftp://",
1365     "mms://",
1366     NULL
1367     };
1368 maya 3227 unsigned char ch = CodeLine[x];
1369    
1370 yutakapon 3615 if (ts.EnableClickableUrl == FALSE &&
1371     (ts.ColorFlag & CF_URLCOLOR) == 0)
1372 maya 3227 return;
1373    
1374     // 直前の行から連結しているか。
1375     // TODO: 1つ前の行の終端文字が URL の一部なら、強制的に現在の行頭文字もURLの一部とみなす。
1376     // (2005.4.3 yutaka)
1377     if (x == 0) {
1378     if (AttrLine > AttrBuff && (AttrLine[x-1] & AttrURL)) {
1379     if (!(ch & 0x80 || url_char[ch]==0)) { // かつURL構成文字なら
1380 yutakapon 3608 AttrLine[x] |= (AttrURL | AttrUnder);
1381 maya 3227 }
1382     }
1383     return;
1384     }
1385    
1386     if ((x-1>=0) && (AttrLine[x-1] & AttrURL) &&
1387     !(ch & 0x80 || url_char[ch]==0)) {
1388     // !((CodeLine[x] <= ' ') && !(AttrLine[x] & AttrKanji))) {
1389 yutakapon 3608 AttrLine[x] |= (AttrURL | AttrUnder);
1390 maya 3227 return;
1391     }
1392    
1393     if ((x-2>=0) && !strncmp(&CodeLine[x-2], "://", 3)) {
1394 maya 3417 int i, len = -1;
1395 yutakapon 3608 RECT rc;
1396     int CaretX, CaretY;
1397 yutakapon 3614 char **p = prefix;
1398 yutakapon 3608
1399 yutakapon 3614 while (*p) {
1400     len = strlen(*p) - 1;
1401     if ((x-len>=0) && !strncmp(&CodeLine[x-len], *p, len)) {
1402     for (i = 0; i <= len; i++) {
1403     AttrLine[x-i] |= (AttrURL | AttrUnder);
1404     }
1405     break;
1406     }
1407     p++;
1408 maya 3227 }
1409 yutakapon 3608
1410     /* ハイパーリンクの色属性変更は、すでに画面へ出力後に、バッファを遡って URL 属性を
1411     * 付け直すというロジックであるため、色が正しく描画されない場合がある。
1412     * 少々強引だが、ハイパーリンクを発見したタイミングで、その行に再描画指示を出すことで、
1413     * リアルタイムな色描画を実現する。
1414     * (2009.8.26 yutaka)
1415     */
1416     CaretX = (0-WinOrgX)*FontWidth;
1417     CaretY = (CursorY-WinOrgY)*FontHeight;
1418     rc.left = CaretX;
1419     rc.top = CaretY;
1420     rc.right = CaretX + NumOfColumns * FontWidth;
1421     rc.bottom = CaretY + FontHeight;
1422     InvalidateRect(HVTWin, &rc, FALSE);
1423 maya 3227 }
1424     #endif
1425     }
1426     /* end - ishizaki */
1427    
1428     void BuffPutChar(BYTE b, TCharAttr Attr, BOOL Insert)
1429     // Put a character in the buffer at the current position
1430     // b: character
1431     // Attr: attributes
1432     // Insert: Insert flag
1433     {
1434 maya 3393 int XStart;
1435 maya 3227
1436 doda 3312 #ifndef NO_COPYLINE_FIX
1437 maya 3393 if (ts.EnableContinuedLineCopy && CursorX == 0 && (AttrLine[0] & AttrLineContinued)) {
1438     Attr.Attr |= AttrLineContinued;
1439     }
1440 doda 3312 #endif /* NO_COPYLINE_FIX */
1441    
1442 doda 3416 if (ts.Language==IdJapanese || ts.Language==IdKorean || ts.Language==IdUtf8) {
1443 maya 3393 EraseKanji(1); /* if cursor is on right half of a kanji, erase the kanji */
1444     if (! Insert) {
1445     EraseKanji(0); /* if cursor on left half... */
1446     }
1447     }
1448 maya 3227
1449 maya 3393 if (Insert) {
1450     memmove(&CodeLine[CursorX+1],&CodeLine[CursorX],NumOfColumns-1-CursorX);
1451     memmove(&AttrLine[CursorX+1],&AttrLine[CursorX],NumOfColumns-1-CursorX);
1452     memmove(&AttrLine2[CursorX+1],&AttrLine2[CursorX],NumOfColumns-1-CursorX);
1453     memmove(&AttrLineFG[CursorX+1],&AttrLineFG[CursorX],NumOfColumns-1-CursorX);
1454     memmove(&AttrLineBG[CursorX+1],&AttrLineBG[CursorX],NumOfColumns-1-CursorX);
1455     CodeLine[CursorX] = b;
1456     AttrLine[CursorX] = Attr.Attr;
1457     AttrLine2[CursorX] = Attr.Attr2;
1458     AttrLineFG[CursorX] = Attr.Fore;
1459     AttrLineBG[CursorX] = Attr.Back;
1460     /* last char in current line is kanji first? */
1461     if ((AttrLine[NumOfColumns-1] & AttrKanji) != 0) {
1462     /* then delete it */
1463     CodeLine[NumOfColumns-1] = 0x20;
1464     AttrLine[NumOfColumns-1] = CurCharAttr.Attr;
1465     AttrLine2[NumOfColumns-1] = CurCharAttr.Attr2;
1466     AttrLineFG[NumOfColumns-1] = CurCharAttr.Fore;
1467     AttrLineBG[NumOfColumns-1] = CurCharAttr.Back;
1468     }
1469     /* begin - ishizaki */
1470     markURL(CursorX+1);
1471     markURL(CursorX);
1472     /* end - ishizaki */
1473 maya 3227
1474 maya 3393 if (StrChangeCount==0) {
1475     XStart = CursorX;
1476     }
1477     else {
1478     XStart = StrChangeStart;
1479     }
1480     StrChangeCount = 0;
1481     BuffUpdateRect(XStart,CursorY,NumOfColumns-1,CursorY);
1482     }
1483     else {
1484     CodeLine[CursorX] = b;
1485     AttrLine[CursorX] = Attr.Attr;
1486     AttrLine2[CursorX] = Attr.Attr2;
1487     AttrLineFG[CursorX] = Attr.Fore;
1488     AttrLineBG[CursorX] = Attr.Back;
1489     /* begin - ishizaki */
1490     markURL(CursorX);
1491     /* end - ishizaki */
1492 maya 3227
1493 maya 3393 if (StrChangeCount==0) {
1494     StrChangeStart = CursorX;
1495     }
1496     StrChangeCount++;
1497     }
1498 maya 3227 }
1499    
1500     void BuffPutKanji(WORD w, TCharAttr Attr, BOOL Insert)
1501     // Put a kanji character in the buffer at the current position
1502     // b: character
1503     // Attr: attributes
1504     // Insert: Insert flag
1505     {
1506 maya 3393 int XStart;
1507 maya 3227
1508 doda 3312 #ifndef NO_COPYLINE_FIX
1509 maya 3393 if (ts.EnableContinuedLineCopy && CursorX == 0 && (AttrLine[0] & AttrLineContinued)) {
1510     Attr.Attr |= AttrLineContinued;
1511     }
1512 doda 3312 #endif /* NO_COPYLINE_FIX */
1513    
1514 maya 3393 EraseKanji(1); /* if cursor is on right half of a kanji, erase the kanji */
1515 maya 3227
1516 maya 3393 if (Insert) {
1517     memmove(&CodeLine[CursorX+2],&CodeLine[CursorX],NumOfColumns-2-CursorX);
1518     memmove(&AttrLine[CursorX+2],&AttrLine[CursorX],NumOfColumns-2-CursorX);
1519     memmove(&AttrLine2[CursorX+2],&AttrLine2[CursorX],NumOfColumns-2-CursorX);
1520     memmove(&AttrLineFG[CursorX+2],&AttrLineFG[CursorX],NumOfColumns-2-CursorX);
1521     memmove(&AttrLineBG[CursorX+2],&AttrLineBG[CursorX],NumOfColumns-2-CursorX);
1522 maya 3227
1523 maya 3393 CodeLine[CursorX] = HIBYTE(w);
1524     AttrLine[CursorX] = Attr.Attr | AttrKanji; /* DBCS first byte */
1525     AttrLine2[CursorX] = Attr.Attr2;
1526     AttrLineFG[CursorX] = Attr.Fore;
1527     AttrLineBG[CursorX] = Attr.Back;
1528     if (CursorX < NumOfColumns-1) {
1529     CodeLine[CursorX+1] = LOBYTE(w);
1530     AttrLine[CursorX+1] = Attr.Attr;
1531     AttrLine2[CursorX+1] = Attr.Attr2;
1532     AttrLineFG[CursorX+1] = Attr.Fore;
1533     AttrLineBG[CursorX+1] = Attr.Back;
1534     }
1535     /* begin - ishizaki */
1536     markURL(CursorX);
1537     markURL(CursorX+1);
1538     /* end - ishizaki */
1539 maya 3227
1540 maya 3393 /* last char in current line is kanji first? */
1541     if ((AttrLine[NumOfColumns-1] & AttrKanji) != 0) {
1542     /* then delete it */
1543     CodeLine[NumOfColumns-1] = 0x20;
1544     AttrLine[NumOfColumns-1] = CurCharAttr.Attr;
1545     AttrLine2[NumOfColumns-1] = CurCharAttr.Attr2;
1546     AttrLineFG[NumOfColumns-1] = CurCharAttr.Fore;
1547     AttrLineBG[NumOfColumns-1] = CurCharAttr.Back;
1548     }
1549 maya 3227
1550 maya 3393 if (StrChangeCount==0) {
1551     XStart = CursorX;
1552     }
1553     else {
1554     XStart = StrChangeStart;
1555     }
1556     StrChangeCount = 0;
1557     BuffUpdateRect(XStart,CursorY,NumOfColumns-1,CursorY);
1558     }
1559     else {
1560     CodeLine[CursorX] = HIBYTE(w);
1561     AttrLine[CursorX] = Attr.Attr | AttrKanji; /* DBCS first byte */
1562     AttrLine2[CursorX] = Attr.Attr2;
1563     AttrLineFG[CursorX] = Attr.Fore;
1564     AttrLineBG[CursorX] = Attr.Back;
1565     if (CursorX < NumOfColumns-1) {
1566     CodeLine[CursorX+1] = LOBYTE(w);
1567     AttrLine[CursorX+1] = Attr.Attr;
1568     AttrLine2[CursorX+1] = Attr.Attr2;
1569     AttrLineFG[CursorX+1] = Attr.Fore;
1570     AttrLineBG[CursorX+1] = Attr.Back;
1571     }
1572     /* begin - ishizaki */
1573     markURL(CursorX);
1574     markURL(CursorX+1);
1575     /* end - ishizaki */
1576 maya 3227
1577 maya 3393 if (StrChangeCount==0) {
1578     StrChangeStart = CursorX;
1579     }
1580     StrChangeCount = StrChangeCount + 2;
1581     }
1582 maya 3227 }
1583    
1584     BOOL CheckSelect(int x, int y)
1585     // subroutine called by BuffUpdateRect
1586     {
1587 maya 3393 LONG L, L1, L2;
1588 maya 3227
1589 maya 3393 if (BoxSelect) {
1590     return (Selected &&
1591     ((SelectStart.x<=x) && (x<SelectEnd.x) ||
1592     (SelectEnd.x<=x) && (x<SelectStart.x)) &&
1593     ((SelectStart.y<=y) && (y<=SelectEnd.y) ||
1594     (SelectEnd.y<=y) && (y<=SelectStart.y)));
1595     }
1596     else {
1597     L = MAKELONG(x,y);
1598     L1 = MAKELONG(SelectStart.x,SelectStart.y);
1599     L2 = MAKELONG(SelectEnd.x,SelectEnd.y);
1600 maya 3227
1601 maya 3393 return (Selected &&
1602     ((L1<=L) && (L<L2) || (L2<=L) && (L<L1)));
1603     }
1604 maya 3227 }
1605    
1606     void BuffUpdateRect
1607     (int XStart, int YStart, int XEnd, int YEnd)
1608     // Display text in a rectangular region in the screen
1609     // XStart: x position of the upper-left corner (screen cordinate)
1610     // YStart: y position
1611     // XEnd: x position of the lower-right corner (last character)
1612     // YEnd: y position
1613     {
1614 maya 3393 int i, j, count;
1615     int IStart, IEnd;
1616     int X, Y;
1617     LONG TmpPtr;
1618     TCharAttr CurAttr, TempAttr;
1619     BOOL CurSel, TempSel, Caret;
1620 maya 3227
1621 maya 3393 if (XStart >= WinOrgX+WinWidth) {
1622     return;
1623     }
1624     if (YStart >= WinOrgY+WinHeight) {
1625     return;
1626     }
1627     if (XEnd < WinOrgX) {
1628     return;
1629     }
1630     if (YEnd < WinOrgY) {
1631     return;
1632     }
1633 maya 3227
1634 maya 3393 if (XStart < WinOrgX) {
1635     XStart = WinOrgX;
1636     }
1637     if (YStart < WinOrgY) {
1638     YStart = WinOrgY;
1639     }
1640     if (XEnd >= WinOrgX+WinWidth) {
1641     XEnd = WinOrgX+WinWidth-1;
1642     }
1643     if (YEnd >= WinOrgY+WinHeight) {
1644     YEnd = WinOrgY+WinHeight-1;
1645     }
1646 maya 3227
1647 maya 3393 TempAttr = DefCharAttr;
1648     TempSel = FALSE;
1649 maya 3227
1650 maya 3393 Caret = IsCaretOn();
1651     if (Caret) {
1652     CaretOff();
1653     }
1654 maya 3227
1655 maya 3393 DispSetupDC(DefCharAttr, TempSel);
1656 maya 3227
1657 maya 3393 Y = (YStart-WinOrgY)*FontHeight;
1658     TmpPtr = GetLinePtr(PageStart+YStart);
1659     for (j = YStart+PageStart ; j <= YEnd+PageStart ; j++) {
1660     IStart = XStart;
1661     IEnd = XEnd;
1662 maya 3227
1663 maya 3393 IStart = LeftHalfOfDBCS(TmpPtr,IStart);
1664 maya 3227
1665 maya 3393 X = (IStart-WinOrgX)*FontWidth;
1666 maya 3227
1667 maya 3393 i = IStart;
1668     do {
1669     CurAttr.Attr = AttrBuff[TmpPtr+i] & ~ AttrKanji;
1670     CurAttr.Attr2 = AttrBuff2[TmpPtr+i];
1671     CurAttr.Fore = AttrBuffFG[TmpPtr+i];
1672     CurAttr.Back = AttrBuffBG[TmpPtr+i];
1673     CurSel = CheckSelect(i,j);
1674     count = 1;
1675     while ( (i+count <= IEnd) &&
1676     (CurAttr.Attr == (AttrBuff[TmpPtr+i+count] & ~ AttrKanji)) &&
1677     (CurAttr.Attr2==AttrBuff2[TmpPtr+i+count]) &&
1678     (CurAttr.Fore==AttrBuffFG[TmpPtr+i+count]) &&
1679     (CurAttr.Back==AttrBuffBG[TmpPtr+i+count]) &&
1680     (CurSel==CheckSelect(i+count,j)) ||
1681     (i+count<NumOfColumns) &&
1682     ((AttrBuff[TmpPtr+i+count-1] & AttrKanji) != 0) ) {
1683     count++;
1684     }
1685 maya 3227
1686 maya 3393 if (TCharAttrCmp(CurAttr, TempAttr) != 0 || (CurSel != TempSel)) {
1687     DispSetupDC(CurAttr, CurSel);
1688     TempAttr = CurAttr;
1689     TempSel = CurSel;
1690     }
1691     DispStr(&CodeBuff[TmpPtr+i],count,Y, &X);
1692     i = i+count;
1693     }
1694     while (i<=IEnd);
1695     Y = Y + FontHeight;
1696     TmpPtr = NextLinePtr(TmpPtr);
1697     }
1698     if (Caret) {
1699     CaretOn();
1700     }
1701 maya 3227 }
1702    
1703     void UpdateStr()
1704     // Display not-yet-displayed string
1705     {
1706 maya 3393 int X, Y;
1707     TCharAttr TempAttr;
1708 maya 3227
1709 maya 3393 if (StrChangeCount==0) {
1710     return;
1711     }
1712     X = StrChangeStart;
1713     Y = CursorY;
1714     if (! IsLineVisible(&X, &Y)) {
1715     StrChangeCount = 0;
1716     return;
1717     }
1718 maya 3227
1719 maya 3393 TempAttr.Attr = AttrLine[StrChangeStart];
1720     TempAttr.Attr2 = AttrLine2[StrChangeStart];
1721     TempAttr.Fore = AttrLineFG[StrChangeStart];
1722     TempAttr.Back = AttrLineBG[StrChangeStart];
1723     DispSetupDC(TempAttr, FALSE);
1724     DispStr(&CodeLine[StrChangeStart],StrChangeCount,Y, &X);
1725     StrChangeCount = 0;
1726 maya 3227 }
1727    
1728     #if 0
1729     void UpdateStrUnicode(void)
1730     // Display not-yet-displayed string
1731     {
1732     int X, Y;
1733     TCharAttr TempAttr;
1734    
1735     if (StrChangeCount==0) return;
1736     X = StrChangeStart;
1737     Y = CursorY;
1738     if (! IsLineVisible(&X, &Y))
1739     {
1740     StrChangeCount = 0;
1741     return;
1742     }
1743    
1744     TempAttr.Attr = AttrLine[StrChangeStart];
1745     TempAttr.Attr2 = AttrLine2[StrChangeStart];
1746     TempAttr.Fore = AttrLineFG[StrChangeStart];
1747     TempAttr.Back = AttrLineBG[StrChangeStart];
1748     DispSetupDC(TempAttr, FALSE);
1749     DispStr(&CodeLine[StrChangeStart],StrChangeCount,Y, &X);
1750     StrChangeCount = 0;
1751     }
1752     #endif
1753    
1754     void MoveCursor(int Xnew, int Ynew)
1755     {
1756 maya 3393 UpdateStr();
1757 maya 3227
1758 maya 3393 if (CursorY!=Ynew) {
1759     NewLine(PageStart+Ynew);
1760     }
1761 maya 3227
1762 maya 3393 CursorX = Xnew;
1763     CursorY = Ynew;
1764     Wrap = FALSE;
1765 maya 3227
1766 maya 3393 /* 最下行でだけ自動スクロールする*/
1767     if (ts.AutoScrollOnlyInBottomLine == 0 || WinOrgY == 0) {
1768     DispScrollToCursor(CursorX, CursorY);
1769     }
1770 maya 3227 }
1771    
1772     void MoveRight()
1773     /* move cursor right, but dont update screen.
1774     this procedure must be called from DispChar&DispKanji only */
1775     {
1776 maya 3393 CursorX++;
1777     /* 最下行でだけ自動スクロールする */
1778     if (ts.AutoScrollOnlyInBottomLine == 0 || WinOrgY == 0) {
1779     DispScrollToCursor(CursorX, CursorY);
1780     }
1781 maya 3227 }
1782    
1783     void BuffSetCaretWidth()
1784     {
1785 maya 3393 BOOL DW;
1786 maya 3227
1787 maya 3393 /* check whether cursor on a DBCS character */
1788     DW = (((BYTE)(AttrLine[CursorX]) & AttrKanji) != 0);
1789     DispSetCaretWidth(DW);
1790 maya 3227 }
1791    
1792     void ScrollUp1Line()
1793     {
1794 maya 3393 int i;
1795     LONG SrcPtr, DestPtr;
1796 maya 3227
1797 maya 3393 if ((CursorTop<=CursorY) && (CursorY<=CursorBottom)) {
1798     UpdateStr();
1799 maya 3227
1800 maya 3393 DestPtr = GetLinePtr(PageStart+CursorBottom);
1801     for (i = CursorBottom-1 ; i >= CursorTop ; i--) {
1802     SrcPtr = PrevLinePtr(DestPtr);
1803     memcpy(&(CodeBuff[DestPtr]),&(CodeBuff[SrcPtr]),NumOfColumns);
1804     memcpy(&(AttrBuff[DestPtr]),&(AttrBuff[SrcPtr]),NumOfColumns);
1805     memcpy(&(AttrBuff2[DestPtr]),&(AttrBuff2[SrcPtr]),NumOfColumns);
1806     memcpy(&(AttrBuffFG[DestPtr]),&(AttrBuffFG[SrcPtr]),NumOfColumns);
1807     memcpy(&(AttrBuffBG[DestPtr]),&(AttrBuffBG[SrcPtr]),NumOfColumns);
1808     DestPtr = SrcPtr;
1809     }
1810     memset(&(CodeBuff[SrcPtr]),0x20,NumOfColumns);
1811     memset(&(AttrBuff[SrcPtr]),AttrDefault,NumOfColumns);
1812     memset(&(AttrBuff2[SrcPtr]),CurCharAttr.Attr2,NumOfColumns);
1813     memset(&(AttrBuffFG[SrcPtr]),CurCharAttr.Fore,NumOfColumns);
1814     memset(&(AttrBuffBG[SrcPtr]),CurCharAttr.Back,NumOfColumns);
1815 maya 3227
1816 maya 3393 DispScrollNLines(CursorTop,CursorBottom,-1);
1817     }
1818 maya 3227 }
1819    
1820     void BuffScrollNLines(int n)
1821     {
1822 maya 3393 int i;
1823     LONG SrcPtr, DestPtr;
1824 maya 3227
1825 maya 3393 if (n<1) {
1826     return;
1827     }
1828     UpdateStr();
1829 maya 3227
1830 maya 3393 if ((CursorTop == 0) && (CursorBottom == NumOfLines-1)) {
1831     WinOrgY = WinOrgY-n;
1832     /* 最下行でだけ自動スクロールする */
1833     if (ts.AutoScrollOnlyInBottomLine != 0 && NewOrgY != 0) {
1834     NewOrgY = WinOrgY;
1835     }
1836     BuffScroll(n,CursorBottom);
1837     DispCountScroll(n);
1838     }
1839     else if ((CursorTop==0) && (CursorY<=CursorBottom)) {
1840     /* 最下行でだけ自動スクロールする */
1841     if (ts.AutoScrollOnlyInBottomLine != 0 && NewOrgY != 0) {
1842     /* スクロールさせない場合の処理 */
1843     WinOrgY = WinOrgY-n;
1844     NewOrgY = WinOrgY;
1845     BuffScroll(n,CursorBottom);
1846     DispCountScroll(n);
1847     } else {
1848     BuffScroll(n,CursorBottom);
1849     DispScrollNLines(WinOrgY,CursorBottom,n);
1850     }
1851     }
1852     else if ((CursorTop<=CursorY) && (CursorY<=CursorBottom)) {
1853     DestPtr = GetLinePtr(PageStart+CursorTop);
1854     if (n<CursorBottom-CursorTop+1) {
1855     SrcPtr = GetLinePtr(PageStart+CursorTop+n);
1856     for (i = CursorTop+n ; i<=CursorBottom ; i++) {
1857     memmove(&(CodeBuff[DestPtr]),&(CodeBuff[SrcPtr]),NumOfColumns);
1858     memmove(&(AttrBuff[DestPtr]),&(AttrBuff[SrcPtr]),NumOfColumns);
1859     memmove(&(AttrBuff2[DestPtr]),&(AttrBuff2[SrcPtr]),NumOfColumns);
1860     memmove(&(AttrBuffFG[DestPtr]),&(AttrBuffFG[SrcPtr]),NumOfColumns);
1861     memmove(&(AttrBuffBG[DestPtr]),&(AttrBuffBG[SrcPtr]),NumOfColumns);
1862     SrcPtr = NextLinePtr(SrcPtr);
1863     DestPtr = NextLinePtr(DestPtr);
1864     }
1865     }
1866     else {
1867     n = CursorBottom-CursorTop+1;
1868     }
1869     for (i = CursorBottom+1-n ; i<=CursorBottom; i++) {
1870     memset(&(CodeBuff[DestPtr]),0x20,NumOfColumns);
1871     memset(&(AttrBuff[DestPtr]),AttrDefault,NumOfColumns);
1872     memset(&(AttrBuff2[DestPtr]),CurCharAttr.Attr2,NumOfColumns);
1873     memset(&(AttrBuffFG[DestPtr]),CurCharAttr.Fore,NumOfColumns);
1874     memset(&(AttrBuffBG[DestPtr]),CurCharAttr.Back,NumOfColumns);
1875     DestPtr = NextLinePtr(DestPtr);
1876     }
1877     DispScrollNLines(CursorTop,CursorBottom,n);
1878     }
1879 maya 3227 }
1880    
1881     void BuffRegionScrollUpNLines(int n) {
1882 maya 3393 int i;
1883     LONG SrcPtr, DestPtr;
1884 maya 3227
1885 maya 3393 if (n<1) {
1886     return;
1887     }
1888     UpdateStr();
1889 maya 3227
1890 maya 3393 if (n > 0) {
1891     if ((CursorTop == 0) && (CursorBottom == NumOfLines-1)) {
1892     WinOrgY = WinOrgY-n;
1893     BuffScroll(n,CursorBottom);
1894     DispCountScroll(n);
1895     }
1896     else if (CursorTop==0) {
1897     BuffScroll(n,CursorBottom);
1898     DispScrollNLines(WinOrgY,CursorBottom,n);
1899     }
1900     else {
1901     DestPtr = GetLinePtr(PageStart+CursorTop);
1902     if (n<CursorBottom-CursorTop+1) {
1903     SrcPtr = GetLinePtr(PageStart+CursorTop+n);
1904     for (i = CursorTop+n ; i<=CursorBottom ; i++) {
1905     memmove(&(CodeBuff[DestPtr]),&(CodeBuff[SrcPtr]),NumOfColumns);
1906     memmove(&(AttrBuff[DestPtr]),&(AttrBuff[SrcPtr]),NumOfColumns);
1907     memmove(&(AttrBuff2[DestPtr]),&(AttrBuff2[SrcPtr]),NumOfColumns);
1908     memmove(&(AttrBuffFG[DestPtr]),&(AttrBuffFG[SrcPtr]),NumOfColumns);
1909     memmove(&(AttrBuffBG[DestPtr]),&(AttrBuffBG[SrcPtr]),NumOfColumns);
1910     SrcPtr = NextLinePtr(SrcPtr);
1911     DestPtr = NextLinePtr(DestPtr);
1912     }
1913     }
1914     else {
1915     n = CursorBottom-CursorTop+1;
1916     }
1917     for (i = CursorBottom+1-n ; i<=CursorBottom; i++) {
1918     memset(&(CodeBuff[DestPtr]),0x20,NumOfColumns);
1919     memset(&(AttrBuff[DestPtr]),AttrDefault,NumOfColumns);
1920     memset(&(AttrBuff2[DestPtr]),CurCharAttr.Attr2,NumOfColumns);
1921     memset(&(AttrBuffFG[DestPtr]),CurCharAttr.Fore,NumOfColumns);
1922     memset(&(AttrBuffBG[DestPtr]),CurCharAttr.Back,NumOfColumns);
1923     DestPtr = NextLinePtr(DestPtr);
1924     }
1925     DispScrollNLines(CursorTop,CursorBottom,n);
1926     }
1927 maya 3227 }
1928     }
1929    
1930     void BuffRegionScrollDownNLines(int n) {
1931 maya 3393 int i;
1932     LONG SrcPtr, DestPtr;
1933 maya 3227
1934 maya 3393 if (n<1) {
1935     return;
1936     }
1937     UpdateStr();
1938 maya 3227
1939 maya 3393 DestPtr = GetLinePtr(PageStart+CursorBottom);
1940     if (n < CursorBottom-CursorTop+1) {
1941     SrcPtr = GetLinePtr(PageStart+CursorBottom-n);
1942     for (i=CursorBottom-n ; i>=CursorTop ; i--) {
1943     memmove(&(CodeBuff[DestPtr]),&(CodeBuff[SrcPtr]),NumOfColumns);
1944     memmove(&(AttrBuff[DestPtr]),&(AttrBuff[SrcPtr]),NumOfColumns);
1945     memmove(&(AttrBuff2[DestPtr]),&(AttrBuff2[SrcPtr]),NumOfColumns);
1946     memmove(&(AttrBuffFG[DestPtr]),&(AttrBuffFG[SrcPtr]),NumOfColumns);
1947     memmove(&(AttrBuffBG[DestPtr]),&(AttrBuffBG[SrcPtr]),NumOfColumns);
1948     SrcPtr = PrevLinePtr(SrcPtr);
1949     DestPtr = PrevLinePtr(DestPtr);
1950     }
1951     }
1952     else {
1953     n = CursorBottom - CursorTop + 1;
1954     }
1955     for (i = CursorTop+n-1; i>=CursorTop; i--) {
1956     memset(&(CodeBuff[DestPtr]),0x20,NumOfColumns);
1957     memset(&(AttrBuff[DestPtr]),AttrDefault,NumOfColumns);
1958     memset(&(AttrBuff2[DestPtr]),CurCharAttr.Attr2,NumOfColumns);
1959     memset(&(AttrBuffFG[DestPtr]),CurCharAttr.Fore,NumOfColumns);
1960     memset(&(AttrBuffBG[DestPtr]),CurCharAttr.Back,NumOfColumns);
1961     DestPtr = PrevLinePtr(DestPtr);
1962     }
1963 maya 3227
1964 maya 3393 DispScrollNLines(CursorTop,CursorBottom,-n);
1965 maya 3227 }
1966    
1967     void BuffClearScreen()
1968     { // clear screen
1969 maya 3393 if ((StatusLine>0) && (CursorY==NumOfLines-1)) {
1970     BuffScrollNLines(1); /* clear status line */
1971     }
1972     else { /* clear main screen */
1973     UpdateStr();
1974     BuffScroll(NumOfLines-StatusLine,NumOfLines-1-StatusLine);
1975     DispScrollNLines(WinOrgY,NumOfLines-1-StatusLine,NumOfLines-StatusLine);
1976     }
1977 maya 3227 }
1978    
1979     void BuffUpdateScroll()
1980     // Updates scrolling
1981     {
1982 maya 3393 UpdateStr();
1983     DispUpdateScroll();
1984 maya 3227 }
1985    
1986     void CursorUpWithScroll()
1987     {
1988 maya 3393 if ((0<CursorY) && (CursorY<CursorTop) ||
1989     (CursorTop<CursorY)) {
1990     MoveCursor(CursorX,CursorY-1);
1991     }
1992     else if (CursorY==CursorTop) {
1993     ScrollUp1Line();
1994     }
1995 maya 3227 }
1996    
1997     // called by BuffDblClk
1998     // check if a character is the word delimiter
1999     BOOL IsDelimiter(LONG Line, int CharPtr)
2000     {
2001 maya 3393 if ((AttrBuff[Line+CharPtr] & AttrKanji) !=0) {
2002     return (ts.DelimDBCS!=0);
2003     }
2004     return (strchr(ts.DelimList,CodeBuff[Line+CharPtr])!=NULL);
2005 maya 3227 }
2006    
2007     void GetMinMax(int i1, int i2, int i3,
2008 maya 3393 int *min, int *max)
2009 maya 3227 {
2010 maya 3393 if (i1<i2) {
2011     *min = i1;
2012     *max = i2;
2013     }
2014     else {
2015     *min = i2;
2016     *max = i1;
2017     }
2018     if (i3<*min) {
2019     *min = i3;
2020     }
2021     if (i3>*max) {
2022     *max = i3;
2023     }
2024 maya 3227 }
2025    
2026     /* start - ishizaki */
2027     static void invokeBrowser(LONG ptr)
2028     {
2029     #ifdef URL_EMPHASIS
2030 maya 3393 LONG i, start, end;
2031     char url[1024];
2032 maya 3227 char *uptr, ch;
2033    
2034 maya 3393 start = ptr;
2035     while (AttrBuff[start] & AttrURL) {
2036     start--;
2037     }
2038     start++;
2039 maya 3227
2040 maya 3393 end = ptr;
2041     while (AttrBuff[end] & AttrURL) {
2042     end++;
2043     }
2044     end--;
2045 maya 3227
2046 yutakapon 3405 if (start + (LONG)sizeof(url) <= end) {
2047     end = start + sizeof(url) - 1;
2048     end--; // '\0'の分は引いておく。
2049 maya 3393 }
2050 maya 3227 uptr = url;
2051 maya 3393 for (i = 0; i < end - start + 1; i++) {
2052 maya 3227 ch = CodeBuff[start + i];
2053     if ((start + i) % NumOfColumns == NumOfColumns - 1
2054     && ch == '\\') {
2055     // Emacs対応。行末に \ が来ている場合は、次の行に続くという意味で emacs が
2056     // 自動で挿入する文字なので、URLには含めないようにする。
2057     // (2007.8.7 yutaka)
2058    
2059     } else {
2060     *uptr++ = ch;
2061     }
2062 maya 3393 }
2063 maya 3227 *uptr = '\0';
2064 maya 3393 ShellExecute(NULL, NULL, url, NULL, NULL,SW_SHOWNORMAL);
2065 maya 3227 #endif
2066     }
2067     /* end - ishizaki */
2068    
2069     void ChangeSelectRegion()
2070     {
2071 maya 3393 POINT TempStart, TempEnd;
2072     int j, IStart, IEnd;
2073     BOOL Caret;
2074 maya 3227
2075 maya 3393 if ((SelectEndOld.x==SelectEnd.x) &&
2076     (SelectEndOld.y==SelectEnd.y)) {
2077     return;
2078     }
2079 maya 3227
2080 maya 3393 if (BoxSelect) {
2081     GetMinMax(SelectStart.x,SelectEndOld.x,SelectEnd.x,
2082     (int *)&TempStart.x,(int *)&TempEnd.x);
2083     GetMinMax(SelectStart.y,SelectEndOld.y,SelectEnd.y,
2084     (int *)&TempStart.y,(int *)&TempEnd.y);
2085     TempEnd.x--;
2086     Caret = IsCaretOn();
2087     if (Caret) {
2088     CaretOff();
2089     }
2090     DispInitDC();
2091     BuffUpdateRect(TempStart.x,TempStart.y-PageStart,
2092     TempEnd.x,TempEnd.y-PageStart);
2093     DispReleaseDC();
2094     if (Caret) {
2095     CaretOn();
2096     }
2097     SelectEndOld = SelectEnd;
2098     return;
2099     }
2100 maya 3227
2101 maya 3393 if ((SelectEndOld.y < SelectEnd.y) ||
2102     (SelectEndOld.y==SelectEnd.y) &&
2103     (SelectEndOld.x<=SelectEnd.x)) {
2104     TempStart = SelectEndOld;
2105     TempEnd.x = SelectEnd.x-1;
2106     TempEnd.y = SelectEnd.y;
2107     }
2108     else {
2109     TempStart = SelectEnd;
2110     TempEnd.x = SelectEndOld.x-1;
2111     TempEnd.y = SelectEndOld.y;
2112     }
2113     if (TempEnd.x < 0) {
2114     TempEnd.x = NumOfColumns - 1;
2115     TempEnd.y--;
2116     }
2117 maya 3227
2118 maya 3393 Caret = IsCaretOn();
2119     if (Caret) {
2120     CaretOff();
2121     }
2122     for (j = TempStart.y ; j <= TempEnd.y ; j++) {
2123     IStart = 0;
2124     IEnd = NumOfColumns-1;
2125     if (j==TempStart.y) {
2126     IStart = TempStart.x;
2127     }
2128     if (j==TempEnd.y) {
2129     IEnd = TempEnd.x;
2130     }
2131 maya 3227
2132 maya 3393 if ((IEnd>=IStart) && (j >= PageStart+WinOrgY) &&
2133     (j < PageStart+WinOrgY+WinHeight)) {
2134     DispInitDC();
2135     BuffUpdateRect(IStart,j-PageStart,IEnd,j-PageStart);
2136     DispReleaseDC();
2137     }
2138     }
2139     if (Caret) {
2140     CaretOn();
2141     }
2142 maya 3227
2143 maya 3393 SelectEndOld = SelectEnd;
2144 maya 3227 }
2145    
2146     BOOL BuffUrlDblClk(int Xw, int Yw)
2147     {
2148 maya 3393 int X, Y;
2149     LONG TmpPtr;
2150     BOOL url_invoked = FALSE;
2151 maya 3227
2152 maya 3393 if (! ts.EnableClickableUrl) {
2153     return FALSE;
2154     }
2155 maya 3227
2156 maya 3393 CaretOff();
2157 maya 3227
2158 maya 3393 DispConvWinToScreen(Xw,Yw,&X,&Y,NULL);
2159     Y = Y + PageStart;
2160     if ((Y<0) || (Y>=BuffEnd)) {
2161     return 0;
2162     }
2163     if (X<0) X = 0;
2164     if (X>=NumOfColumns) {
2165     X = NumOfColumns-1;
2166     }
2167 maya 3227
2168 maya 3393 if ((Y>=0) && (Y<BuffEnd)) {
2169     LockBuffer();
2170     TmpPtr = GetLinePtr(Y);
2171     /* start - ishizaki */
2172     if (AttrBuff[TmpPtr+X] & AttrURL) {
2173     BoxSelect = FALSE;
2174     SelectEnd = SelectStart;
2175     ChangeSelectRegion();
2176 maya 3227
2177 maya 3393 url_invoked = TRUE;
2178     invokeBrowser(TmpPtr+X);
2179 maya 3227
2180 maya 3393 SelectStart.x = 0;
2181     SelectStart.y = 0;
2182     SelectEnd.x = 0;
2183     SelectEnd.y = 0;
2184     SelectEndOld.x = 0;
2185     SelectEndOld.y = 0;
2186     Selected = FALSE;
2187     }
2188     UnlockBuffer();
2189     }
2190     return url_invoked;
2191 maya 3227 }
2192    
2193     void BuffDblClk(int Xw, int Yw)
2194     // Select a word at (Xw, Yw) by mouse double click
2195     // Xw: horizontal position in window coordinate (pixels)
2196     // Yw: vertical
2197     {
2198 maya 3393 int X, Y, YStart, YEnd;
2199     int IStart, IEnd, i;
2200     LONG TmpPtr;
2201     BYTE b;
2202     BOOL DBCS;
2203 maya 3227
2204 maya 3393 CaretOff();
2205 maya 3227
2206 maya 3393 DispConvWinToScreen(Xw,Yw,&X,&Y,NULL);
2207     Y = Y + PageStart;
2208     if ((Y<0) || (Y>=BuffEnd)) {
2209     return;
2210     }
2211     if (X<0) X = 0;
2212     if (X>=NumOfColumns) X = NumOfColumns-1;
2213 maya 3227
2214 maya 3393 BoxSelect = FALSE;
2215     LockBuffer();
2216     SelectEnd = SelectStart;
2217     ChangeSelectRegion();
2218 maya 3227
2219 maya 3393 if ((Y>=0) && (Y<BuffEnd)) {
2220     TmpPtr = GetLinePtr(Y);
2221 maya 3227
2222 maya 3393 IStart = X;
2223     IStart = LeftHalfOfDBCS(TmpPtr,IStart);
2224     IEnd = IStart;
2225     YStart = YEnd = Y;
2226 maya 3227
2227 maya 3393 if (IsDelimiter(TmpPtr,IStart)) {
2228     b = CodeBuff[TmpPtr+IStart];
2229     DBCS = (AttrBuff[TmpPtr+IStart] & AttrKanji) != 0;
2230     while ((b==CodeBuff[TmpPtr+IStart]) ||
2231     DBCS &&
2232     ((AttrBuff[TmpPtr+IStart] & AttrKanji)!=0)) {
2233     MoveCharPtr(TmpPtr,&IStart,-1); // move left
2234     if (ts.EnableContinuedLineCopy) {
2235     if (IStart<=0) {
2236     // 左端の場合
2237     if (YStart>0 && AttrBuff[TmpPtr] & AttrLineContinued) {
2238     // 前の行に移動する
2239     YStart--;
2240     TmpPtr = GetLinePtr(YStart);
2241     IStart = NumOfColumns;
2242     }
2243     else {
2244     break;
2245     }
2246     }
2247     }
2248     else {
2249     if (IStart<=0) {
2250     // 左端の場合は終わり
2251     break;
2252     }
2253     }
2254 maya 3227 }
2255 maya 3393 if ((b!=CodeBuff[TmpPtr+IStart]) &&
2256     ! (DBCS && ((AttrBuff[TmpPtr+IStart] & AttrKanji)!=0))) {
2257     // 最終位置が Delimiter でない場合にはひとつ右にずらす
2258     if (ts.EnableContinuedLineCopy && IStart == NumOfColumns-1) {
2259     // 右端の場合には次の行へ移動する
2260     YStart++;
2261     TmpPtr = GetLinePtr(YStart);
2262     IStart = 0;
2263     }
2264     else {
2265     MoveCharPtr(TmpPtr,&IStart,1);
2266     }
2267 maya 3227 }
2268 maya 3393
2269     // 行が移動しているかもしれないので、クリックした行を取り直す
2270     TmpPtr = GetLinePtr(YEnd);
2271     i = 1;
2272     while (((b==CodeBuff[TmpPtr+IEnd]) ||
2273     DBCS &&
2274     ((AttrBuff[TmpPtr+IEnd] & AttrKanji)!=0))) {
2275     i = MoveCharPtr(TmpPtr,&IEnd,