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 3743 - (hide annotations) (download) (as text)
Wed Jan 27 22:20:42 2010 UTC (14 years, 2 months ago) by doda
File MIME type: text/x-csrc
File size: 80501 byte(s)
Alternate Screen Bufferに対応。

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