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 2476 - (hide annotations) (download) (as text)
Mon Apr 14 17:35:50 2008 UTC (16 years ago) by maya
Original Path: teraterm/trunk/teraterm/buffer.c
File MIME type: text/x-csrc
File size: 72192 byte(s)
ファイル移動に伴う修正

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