Develop and Download Open Source Software

Browse Subversion Repository

Annotation of /branches/ttcomtester/teraterm/teraterm/buffer.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3312 - (hide annotations) (download) (as text)
Wed Apr 15 10:22:42 2009 UTC (14 years, 11 months ago) by doda
Original Path: trunk/teraterm/teraterm/buffer.c
File MIME type: text/x-csrc
File size: 76490 byte(s)
継続行コピーがうまく働かない場合があるのを修正。

1 maya 3227 /* Tera Term
2     Copyright(C) 1994-1998 T. Teranishi
3     All rights reserved. */
4    
5     /* TERATERM.EXE, scroll buffer routines */
6    
7     #include "teraterm.h"
8     #include "tttypes.h"
9     #include <string.h>
10    
11     #include "ttwinman.h"
12     #include "teraprn.h"
13     #include "vtdisp.h"
14     #include "clipboar.h"
15     #include "telnet.h"
16     #include "ttplug.h" /* TTPLUG */
17    
18     #include "buffer.h"
19    
20     // URLを強調する(石崎氏パッチ 2005/4/2)
21     #define URL_EMPHASIS 1
22    
23     #define BuffXMax TermWidthMax
24     //#define BuffYMax 100000
25     //#define BuffSizeMax 8000000
26     // スクロールバッファの最大長を拡張 (2004.11.28 yutaka)
27     #define BuffYMax 500000
28     #define BuffSizeMax (BuffYMax * 80)
29    
30     // status line
31     int StatusLine; //0: none 1: shown
32     /* top & bottom margin */
33     int CursorTop, CursorBottom;
34     BOOL Selected;
35     BOOL Wrap;
36    
37     static WORD TabStops[256];
38     static int NTabStops;
39    
40     static WORD BuffLock = 0;
41     static HANDLE HCodeBuff = 0;
42     static HANDLE HAttrBuff = 0;
43     static HANDLE HAttrBuff2 = 0;
44     static HANDLE HAttrBuffFG = 0;
45     static HANDLE HAttrBuffBG = 0;
46    
47     static PCHAR CodeBuff; /* Character code buffer */
48     static PCHAR AttrBuff; /* Attribute buffer */
49     static PCHAR AttrBuff2; /* Color attr buffer */
50     static PCHAR AttrBuffFG; /* Foreground color attr buffer */
51     static PCHAR AttrBuffBG; /* Background color attr buffer */
52     static PCHAR CodeLine;
53     static PCHAR AttrLine;
54     static PCHAR AttrLine2;
55     static PCHAR AttrLineFG;
56     static PCHAR AttrLineBG;
57     static LONG LinePtr;
58     static LONG BufferSize;
59     static int NumOfLinesInBuff;
60     static int BuffStartAbs, BuffEndAbs;
61     static POINT SelectStart, SelectEnd, SelectEndOld;
62     static BOOL BoxSelect;
63     static POINT DblClkStart, DblClkEnd;
64    
65     static int StrChangeStart, StrChangeCount;
66    
67     static BOOL SeveralPageSelect; // add (2005.5.15 yutaka)
68    
69     static TCharAttr CurCharAttr;
70    
71     LONG GetLinePtr(int Line)
72     {
73     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]),AttrDefault,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],AttrDefault,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]),AttrDefault,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] = AttrDefault;
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]),AttrDefault,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]),AttrDefault,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]),AttrDefault,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 doda 3312 #ifndef NO_COPYLINE_FIX
722     BOOL LineContinued=FALSE;
723    
724     if (ts.EnableContinuedLineCopy && XStart == 0 && (AttrLine[0] & AttrLineContinued))
725     LineContinued = TRUE;
726     #endif /* NO_COPYLINE_FIX */
727    
728 maya 3227 if (ts.Language==IdJapanese)
729     EraseKanji(1); /* if cursor is on right half of a kanji, erase the kanji */
730    
731     NewLine(PageStart+CursorY);
732     memset(&(CodeLine[XStart]),0x20,Count);
733     memset(&(AttrLine[XStart]),AttrDefault,Count);
734     memset(&(AttrLine2[XStart]),CurCharAttr.Attr2,Count);
735     memset(&(AttrLineFG[XStart]),CurCharAttr.Fore,Count);
736     memset(&(AttrLineBG[XStart]),CurCharAttr.Back,Count);
737    
738 doda 3312 #ifndef NO_COPYLINE_FIX
739     if (LineContinued)
740     BuffLineContinued(TRUE);
741     #endif /* NO_COPYLINE_FIX */
742    
743 maya 3227 DispEraseCharsInLine(XStart, Count);
744     }
745    
746     void BuffDeleteLines(int Count, int YEnd)
747     // Delete lines from current line
748     // Count: number of lines to be deleted
749     // YEnd: bottom line number of scroll region (screen coordinate)
750     {
751     int i;
752     LONG SrcPtr, DestPtr;
753    
754     BuffUpdateScroll();
755    
756     SrcPtr = GetLinePtr(PageStart+CursorY+Count);
757     DestPtr = GetLinePtr(PageStart+CursorY);
758     for (i=CursorY ; i<= YEnd-Count ; i++)
759     {
760     memcpy(&(CodeBuff[DestPtr]),&(CodeBuff[SrcPtr]),NumOfColumns);
761     memcpy(&(AttrBuff[DestPtr]),&(AttrBuff[SrcPtr]),NumOfColumns);
762     memcpy(&(AttrBuff2[DestPtr]),&(AttrBuff2[SrcPtr]),NumOfColumns);
763     memcpy(&(AttrBuffFG[DestPtr]),&(AttrBuffFG[SrcPtr]),NumOfColumns);
764     memcpy(&(AttrBuffBG[DestPtr]),&(AttrBuffBG[SrcPtr]),NumOfColumns);
765     SrcPtr = NextLinePtr(SrcPtr);
766     DestPtr = NextLinePtr(DestPtr);
767     }
768     for (i = YEnd+1-Count ; i<=YEnd ; i++)
769     {
770     memset(&(CodeBuff[DestPtr]),0x20,NumOfColumns);
771     memset(&(AttrBuff[DestPtr]),AttrDefault,NumOfColumns);
772     memset(&(AttrBuff2[DestPtr]),CurCharAttr.Attr2,NumOfColumns);
773     memset(&(AttrBuffFG[DestPtr]),CurCharAttr.Fore,NumOfColumns);
774     memset(&(AttrBuffBG[DestPtr]),CurCharAttr.Back,NumOfColumns);
775     DestPtr = NextLinePtr(DestPtr);
776     }
777    
778     if (! DispDeleteLines(Count,YEnd))
779     BuffUpdateRect(WinOrgX,CursorY,WinOrgX+WinWidth-1,YEnd);
780     }
781    
782     void BuffDeleteChars(int Count)
783     // Delete characters in current line from cursor
784     // Count: number of characters to be deleted
785     {
786     NewLine(PageStart+CursorY);
787    
788     if (ts.Language==IdJapanese)
789     {
790     EraseKanji(0); /* if cursor is on left harf of a kanji, erase the kanji */
791     EraseKanji(1); /* if cursor on right half... */
792     }
793    
794     if (Count > NumOfColumns-CursorX) Count = NumOfColumns-CursorX;
795     memmove(&(CodeLine[CursorX]),&(CodeLine[CursorX+Count]),
796     NumOfColumns-Count-CursorX);
797     memmove(&(AttrLine[CursorX]),&(AttrLine[CursorX+Count]),
798     NumOfColumns-Count-CursorX);
799     memmove(&(AttrLine2[CursorX]),&(AttrLine2[CursorX+Count]),
800     NumOfColumns-Count-CursorX);
801     memmove(&(AttrLineFG[CursorX]),&(AttrLineFG[CursorX+Count]),
802     NumOfColumns-Count-CursorX);
803     memmove(&(AttrLineBG[CursorX]),&(AttrLineBG[CursorX+Count]),
804     NumOfColumns-Count-CursorX);
805     memset(&(CodeLine[NumOfColumns-Count]),0x20,Count);
806     memset(&(AttrLine[NumOfColumns-Count]),AttrDefault,Count);
807     memset(&(AttrLine2[NumOfColumns-Count]),CurCharAttr.Attr2,Count);
808     memset(&(AttrLineFG[NumOfColumns-Count]),CurCharAttr.Fore,Count);
809     memset(&(AttrLineBG[NumOfColumns-Count]),CurCharAttr.Back,Count);
810    
811     BuffUpdateRect(CursorX,CursorY,WinOrgX+WinWidth-1,CursorY);
812     }
813    
814     void BuffEraseChars(int Count)
815     // Erase characters in current line from cursor
816     // Count: number of characters to be deleted
817     {
818     NewLine(PageStart+CursorY);
819    
820     if (ts.Language==IdJapanese)
821     {
822     EraseKanji(0); /* if cursor is on left harf of a kanji, erase the kanji */
823     EraseKanji(1); /* if cursor on right half... */
824     }
825    
826     if (Count > NumOfColumns-CursorX) Count = NumOfColumns-CursorX;
827     memset(&(CodeLine[CursorX]),0x20,Count);
828     memset(&(AttrLine[CursorX]),AttrDefault,Count);
829     memset(&(AttrLine2[CursorX]),CurCharAttr.Attr2,Count);
830     memset(&(AttrLineFG[CursorX]),CurCharAttr.Fore,Count);
831     memset(&(AttrLineBG[CursorX]),CurCharAttr.Back,Count);
832    
833     /* update window */
834     DispEraseCharsInLine(CursorX,Count);
835     }
836    
837     void BuffFillWithE()
838     // Fill screen with 'E' characters
839     {
840     LONG TmpPtr;
841     int i;
842    
843     TmpPtr = GetLinePtr(PageStart);
844     for (i = 0 ; i <= NumOfLines-1-StatusLine ; i++)
845     {
846     memset(&(CodeBuff[TmpPtr]),'E',NumOfColumns);
847     memset(&(AttrBuff[TmpPtr]),AttrDefault,NumOfColumns);
848     memset(&(AttrBuff2[TmpPtr]),AttrDefault,NumOfColumns);
849     memset(&(AttrBuffFG[TmpPtr]),AttrDefaultFG,NumOfColumns);
850     memset(&(AttrBuffBG[TmpPtr]),AttrDefaultBG,NumOfColumns);
851     TmpPtr = NextLinePtr(TmpPtr);
852     }
853     BuffUpdateRect(WinOrgX,WinOrgY,WinOrgX+WinWidth-1,WinOrgY+WinHeight-1);
854     }
855    
856     void BuffDrawLine(TCharAttr Attr, int Direction, int C)
857     { // IO-8256 terminal
858     LONG Ptr;
859     int i, X, Y;
860    
861     if (C==0) return;
862     Attr.Attr |= AttrSpecial;
863    
864     switch (Direction) {
865     case 3:
866     case 4:
867     if (Direction==3)
868     {
869     if (CursorY==0) return;
870     Y = CursorY-1;
871     }
872     else {
873     if (CursorY==NumOfLines-1-StatusLine) return;
874     Y = CursorY+1;
875     }
876     if (CursorX+C > NumOfColumns)
877     C = NumOfColumns-CursorX;
878     Ptr = GetLinePtr(PageStart+Y);
879     memset(&(CodeBuff[Ptr+CursorX]),'q',C);
880     memset(&(AttrBuff[Ptr+CursorX]),Attr.Attr,C);
881     memset(&(AttrBuff2[Ptr+CursorX]),Attr.Attr2,C);
882     memset(&(AttrBuffFG[Ptr+CursorX]),Attr.Fore,C);
883     memset(&(AttrBuffBG[Ptr+CursorX]),Attr.Back,C);
884     BuffUpdateRect(CursorX,Y,CursorX+C-1,Y);
885     break;
886     case 5:
887     case 6:
888     if (Direction==5)
889     {
890     if (CursorX==0) return;
891     X = CursorX - 1;
892     }
893     else {
894     if (CursorX==NumOfColumns-1)
895     X = CursorX-1;
896     else
897     X = CursorX+1;
898     }
899     Ptr = GetLinePtr(PageStart+CursorY);
900     if (CursorY+C > NumOfLines-StatusLine)
901     C = NumOfLines-StatusLine-CursorY;
902     for (i=1; i<=C; i++)
903     {
904     CodeBuff[Ptr+X] = 'x';
905     AttrBuff[Ptr+X] = Attr.Attr;
906     AttrBuff2[Ptr+X] = Attr.Attr2;
907     AttrBuffFG[Ptr+X] = Attr.Fore;
908     AttrBuffBG[Ptr+X] = Attr.Back;
909     Ptr = NextLinePtr(Ptr);
910     }
911     BuffUpdateRect(X,CursorY,X,CursorY+C-1);
912     break;
913     }
914     }
915    
916     void BuffEraseBox
917     (int XStart, int YStart, int XEnd, int YEnd)
918     // IO-8256 terminal
919     {
920     int C, i;
921     LONG Ptr;
922    
923     if (XEnd>NumOfColumns-1)
924     XEnd = NumOfColumns-1;
925     if (YEnd>NumOfLines-1-StatusLine)
926     YEnd = NumOfLines-1-StatusLine;
927     if (XStart>XEnd) return;
928     if (YStart>YEnd) return;
929     C = XEnd-XStart+1;
930     Ptr = GetLinePtr(PageStart+YStart);
931     for (i=YStart; i<=YEnd; i++)
932     {
933     if ((XStart>0) &&
934     ((AttrBuff[Ptr+XStart-1] & AttrKanji) != 0))
935     {
936     CodeBuff[Ptr+XStart-1] = 0x20;
937     AttrBuff[Ptr+XStart-1] = CurCharAttr.Attr;
938     AttrBuff2[Ptr+XStart-1] = CurCharAttr.Attr2;
939     AttrBuffFG[Ptr+XStart-1] = CurCharAttr.Fore;
940     AttrBuffBG[Ptr+XStart-1] = CurCharAttr.Back;
941     }
942     if ((XStart+C<NumOfColumns) &&
943     ((AttrBuff[Ptr+XStart+C-1] & AttrKanji) != 0))
944     {
945     CodeBuff[Ptr+XStart+C] = 0x20;
946     AttrBuff[Ptr+XStart+C] = CurCharAttr.Attr;
947     AttrBuff2[Ptr+XStart+C] = CurCharAttr.Attr2;
948     AttrBuffFG[Ptr+XStart+C] = CurCharAttr.Fore;
949     AttrBuffBG[Ptr+XStart+C] = CurCharAttr.Back;
950     }
951     memset(&(CodeBuff[Ptr+XStart]),0x20,C);
952     memset(&(AttrBuff[Ptr+XStart]),AttrDefault,C);
953     memset(&(AttrBuff2[Ptr+XStart]),CurCharAttr.Attr2,C);
954     memset(&(AttrBuffFG[Ptr+XStart]),CurCharAttr.Fore,C);
955     memset(&(AttrBuffBG[Ptr+XStart]),CurCharAttr.Back,C);
956     Ptr = NextLinePtr(Ptr);
957     }
958     BuffUpdateRect(XStart,YStart,XEnd,YEnd);
959     }
960    
961     int LeftHalfOfDBCS(LONG Line, int CharPtr)
962     // If CharPtr is on the right half of a DBCS character,
963     // return pointer to the left half
964     // Line: points to a line in CodeBuff
965     // CharPtr: points to a char
966     // return: points to the left half of the DBCS
967     {
968     if ((CharPtr>0) &&
969     ((AttrBuff[Line+CharPtr-1] & AttrKanji) != 0))
970     CharPtr--;
971     return CharPtr;
972     }
973    
974     int MoveCharPtr(LONG Line, int *x, int dx)
975     // move character pointer x by dx character unit
976     // in the line specified by Line
977     // Line: points to a line in CodeBuff
978     // x: points to a character in the line
979     // dx: moving distance in character unit (-: left, +: right)
980     // One DBCS character is counted as one character.
981     // The pointer stops at the beginning or the end of line.
982     // Output
983     // x: new pointer. x points to a SBCS character or
984     // the left half of a DBCS character.
985     // return: actual moving distance in character unit
986     {
987     int i;
988    
989     *x = LeftHalfOfDBCS(Line,*x);
990     i = 0;
991     while (dx!=0)
992     {
993     if (dx>0) // move right
994     {
995     if ((AttrBuff[Line+*x] & AttrKanji) != 0)
996     {
997     if (*x<NumOfColumns-2)
998     {
999     i++;
1000     *x = *x + 2;
1001     }
1002     }
1003     else if (*x<NumOfColumns-1)
1004     {
1005     i++;
1006     (*x)++;
1007     }
1008     dx--;
1009     }
1010     else { // move left
1011     if (*x>0)
1012     {
1013     i--;
1014     (*x)--;
1015     }
1016     *x = LeftHalfOfDBCS(Line,*x);
1017     dx++;
1018     }
1019     }
1020     return i;
1021     }
1022    
1023     void BuffCBCopy(BOOL Table)
1024     // copy selected text to clipboard
1025     {
1026     LONG MemSize;
1027     PCHAR CBPtr;
1028     LONG TmpPtr;
1029     int i, j, k, IStart, IEnd;
1030     BOOL Sp, FirstChar;
1031     BYTE b;
1032     #ifndef NO_COPYLINE_FIX
1033     BOOL LineContinued, PrevLineContinued;
1034     LineContinued = FALSE;
1035     #endif /* NO_COPYLINE_FIX */
1036    
1037     if (TalkStatus==IdTalkCB) return;
1038     if (! Selected) return;
1039    
1040     // --- open clipboard and get CB memory
1041     if (BoxSelect)
1042     MemSize = (SelectEnd.x-SelectStart.x+3)*
1043     (SelectEnd.y-SelectStart.y+1) + 1;
1044     else
1045     MemSize = (SelectEnd.y-SelectStart.y)*
1046     (NumOfColumns+2) +
1047     SelectEnd.x - SelectStart.x + 1;
1048     CBPtr = CBOpen(MemSize);
1049     if (CBPtr==NULL) return;
1050    
1051     // --- copy selected text to CB memory
1052     LockBuffer();
1053    
1054     CBPtr[0] = 0;
1055     TmpPtr = GetLinePtr(SelectStart.y);
1056     k = 0;
1057     for (j = SelectStart.y ; j<=SelectEnd.y ; j++)
1058     {
1059     if (BoxSelect)
1060     {
1061     IStart = SelectStart.x;
1062     IEnd = SelectEnd.x-1;
1063     }
1064     else {
1065     IStart = 0;
1066     IEnd = NumOfColumns-1;
1067     if (j==SelectStart.y) IStart = SelectStart.x;
1068     if (j==SelectEnd.y) IEnd = SelectEnd.x-1;
1069     }
1070     i = LeftHalfOfDBCS(TmpPtr,IStart);
1071     if (i!=IStart)
1072     {
1073     if (j==SelectStart.y)
1074     IStart = i;
1075     else
1076     IStart = i + 2;
1077     }
1078    
1079     // exclude right-side space characters
1080     IEnd = LeftHalfOfDBCS(TmpPtr,IEnd);
1081     #ifndef NO_COPYLINE_FIX
1082     PrevLineContinued = LineContinued;
1083     LineContinued = FALSE;
1084     if (ts.EnableContinuedLineCopy && j!=SelectEnd.y && !BoxSelect)
1085     {
1086     LONG NextTmpPtr = NextLinePtr(TmpPtr);
1087     if ((AttrBuff[NextTmpPtr] & AttrLineContinued) != 0)
1088     LineContinued = TRUE;
1089     if (IEnd == NumOfColumns-1 &&
1090     (AttrBuff[TmpPtr + IEnd] & AttrLineContinued) != 0)
1091     MoveCharPtr(TmpPtr,&IEnd,-1);
1092     }
1093     if (!LineContinued)
1094     #endif /* NO_COPYLINE_FIX */
1095     while ((IEnd>0) && (CodeBuff[TmpPtr+IEnd]==0x20))
1096     MoveCharPtr(TmpPtr,&IEnd,-1);
1097     if ((IEnd==0) && (CodeBuff[TmpPtr]==0x20))
1098     IEnd = -1;
1099     else if ((AttrBuff[TmpPtr+IEnd] & AttrKanji) != 0) /* DBCS first byte? */
1100     IEnd++;
1101    
1102     Sp = FALSE;
1103     FirstChar = TRUE;
1104     i = IStart;
1105     while (i <= IEnd)
1106     {
1107     b = CodeBuff[TmpPtr+i];
1108     i++;
1109     if (! Sp)
1110     {
1111     if ((Table) && (b<=0x20))
1112     {
1113     Sp = TRUE;
1114     b = 0x09;
1115     }
1116     #ifndef NO_COPYLINE_FIX
1117     if ((b!=0x09) || (! FirstChar) || PrevLineContinued)
1118     #else
1119     if ((b!=0x09) || (! FirstChar))
1120     #endif
1121     {
1122     FirstChar = FALSE;
1123     CBPtr[k] = b;
1124     k++;
1125     }
1126     }
1127     else {
1128     if (b>0x20)
1129     {
1130     Sp = FALSE;
1131     FirstChar = FALSE;
1132     CBPtr[k] = b;
1133     k++;
1134     }
1135     }
1136     }
1137    
1138     #ifndef NO_COPYLINE_FIX
1139     if (!LineContinued)
1140     #endif /* NO_COPYLINE_FIX */
1141     if (j < SelectEnd.y)
1142     {
1143     CBPtr[k] = 0x0d;
1144     k++;
1145     CBPtr[k] = 0x0a;
1146     k++;
1147     }
1148    
1149     TmpPtr = NextLinePtr(TmpPtr);
1150     }
1151     CBPtr[k] = 0;
1152     #ifndef NO_COPYLINE_FIX
1153     LineContinued = FALSE;
1154     if (ts.EnableContinuedLineCopy && j!=SelectEnd.y && !BoxSelect && j<BuffEnd-1)
1155     {
1156     LONG NextTmpPtr = NextLinePtr(TmpPtr);
1157     if ((AttrBuff[NextTmpPtr] & AttrLineContinued) != 0)
1158     LineContinued = TRUE;
1159     if (IEnd == NumOfColumns-1 &&
1160     (AttrBuff[TmpPtr + IEnd] & AttrLineContinued) != 0)
1161     MoveCharPtr(TmpPtr,&IEnd,-1);
1162     }
1163     if (!LineContinued)
1164     #endif /* NO_COPYLINE_FIX */
1165     UnlockBuffer();
1166    
1167     // --- send CB memory to clipboard
1168     CBClose();
1169     return;
1170     }
1171    
1172     void BuffPrint(BOOL ScrollRegion)
1173     // Print screen or selected text
1174     {
1175     int Id;
1176     POINT PrintStart, PrintEnd;
1177     TCharAttr CurAttr, TempAttr;
1178     int i, j, count;
1179     int IStart, IEnd;
1180     LONG TmpPtr;
1181    
1182     TempAttr = DefCharAttr;
1183    
1184     if (ScrollRegion)
1185     Id = VTPrintInit(IdPrnScrollRegion);
1186     else if (Selected)
1187     Id = VTPrintInit(IdPrnScreen | IdPrnSelectedText);
1188     else
1189     Id = VTPrintInit(IdPrnScreen);
1190     if (Id==IdPrnCancel) return;
1191    
1192     /* set print region */
1193     if (Id==IdPrnSelectedText)
1194     {
1195     /* print selected region */
1196     PrintStart = SelectStart;
1197     PrintEnd = SelectEnd;
1198     }
1199     else if (Id==IdPrnScrollRegion)
1200     {
1201     /* print scroll region */
1202     PrintStart.x = 0;
1203     PrintStart.y = PageStart + CursorTop;
1204     PrintEnd.x = NumOfColumns;
1205     PrintEnd.y = PageStart + CursorBottom;
1206     }
1207     else {
1208     /* print current screen */
1209     PrintStart.x = 0;
1210     PrintStart.y = PageStart;
1211     PrintEnd.x = NumOfColumns;
1212     PrintEnd.y = PageStart + NumOfLines - 1;
1213     }
1214     if (PrintEnd.y > BuffEnd-1)
1215     PrintEnd.y = BuffEnd-1;
1216    
1217     LockBuffer();
1218    
1219     TmpPtr = GetLinePtr(PrintStart.y);
1220     for (j = PrintStart.y ; j <= PrintEnd.y ; j++)
1221     {
1222     if (j==PrintStart.y)
1223     IStart = PrintStart.x;
1224     else IStart = 0;
1225     if (j == PrintEnd.y)
1226     IEnd = PrintEnd.x - 1;
1227     else
1228     IEnd = NumOfColumns - 1;
1229    
1230     while ((IEnd>=IStart) &&
1231     (CodeBuff[TmpPtr+IEnd]==0x20) &&
1232     (AttrBuff[TmpPtr+IEnd]==AttrDefault) &&
1233     (AttrBuff2[TmpPtr+IEnd]==AttrDefault))
1234     IEnd--;
1235    
1236     i = IStart;
1237     while (i <= IEnd) {
1238     CurAttr.Attr = AttrBuff[TmpPtr+i] & ~ AttrKanji;
1239     CurAttr.Attr2 = AttrBuff2[TmpPtr+i];
1240     CurAttr.Fore = AttrBuffFG[TmpPtr+i];
1241     CurAttr.Back = AttrBuffBG[TmpPtr+i];
1242    
1243     count = 1;
1244     while ((i+count <= IEnd) &&
1245     (CurAttr.Attr == (AttrBuff[TmpPtr+i+count] & ~ AttrKanji)) &&
1246     (CurAttr.Attr2 == AttrBuff2[TmpPtr+i+count]) &&
1247     (CurAttr.Fore == AttrBuffFG[TmpPtr+i+count]) &&
1248     (CurAttr.Back == AttrBuffBG[TmpPtr+i+count]) ||
1249     (i+count<NumOfColumns) &&
1250     ((AttrBuff[TmpPtr+i+count-1] & AttrKanji) != 0))
1251     count++;
1252    
1253     if (TCharAttrCmp(CurAttr, TempAttr) != 0) {
1254     PrnSetAttr(CurAttr);
1255     TempAttr = CurAttr;
1256     }
1257     PrnOutText(&(CodeBuff[TmpPtr+i]),count);
1258     i = i+count;
1259     }
1260     PrnNewLine();
1261     TmpPtr = NextLinePtr(TmpPtr);
1262     }
1263    
1264     UnlockBuffer();
1265     VTPrintEnd();
1266     }
1267    
1268     void BuffDumpCurrentLine(BYTE TERM)
1269     // Dumps current line to the file (for path through printing)
1270     // HFile: file handle
1271     // TERM: terminator character
1272     // = LF or VT or FF
1273     {
1274     int i, j;
1275    
1276     i = NumOfColumns;
1277     while ((i>0) && (CodeLine[i-1]==0x20))
1278     i--;
1279     for (j=0; j<i; j++)
1280     WriteToPrnFile(CodeLine[j],FALSE);
1281     WriteToPrnFile(0,TRUE);
1282     if ((TERM>=LF) && (TERM<=FF))
1283     {
1284     WriteToPrnFile(0x0d,FALSE);
1285     WriteToPrnFile(TERM,TRUE);
1286     }
1287     }
1288    
1289    
1290     /* begin - ishizaki */
1291     static void markURL(int x)
1292     {
1293     #ifdef URL_EMPHASIS
1294     // by sakura editor 1.5.2.1: etc_uty.cpp
1295     static const char url_char[] = {
1296     /* +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F */
1297     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* +00: */
1298     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* +10: */
1299     0, -1, 0, -1, -1, -1, -1, 0, 0, 0, 0, -1, -1, -1, -1, -1, /* +20: " !"#$%&'()*+,-./" */
1300     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, 0, -1, /* +30: "0123456789:;<=>?" */
1301     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* +40: "@ABCDEFGHIJKLMNO" */
1302     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, 0, 0, -1, /* +50: "PQRSTUVWXYZ[\]^_" */
1303     0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* +60: "`abcdefghijklmno" */
1304     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, -1, 0, /* +70: "pqrstuvwxyz{|}~ " */
1305     /* 0 : not url char
1306     * -1 : url char
1307     * other: url head char --> url_table array number + 1
1308     */
1309     };
1310     unsigned char ch = CodeLine[x];
1311    
1312     if (ts.EnableClickableUrl == FALSE)
1313     return;
1314    
1315     // 直前の行から連結しているか。
1316     // TODO: 1つ前の行の終端文字が URL の一部なら、強制的に現在の行頭文字もURLの一部とみなす。
1317     // (2005.4.3 yutaka)
1318     if (x == 0) {
1319     if (AttrLine > AttrBuff && (AttrLine[x-1] & AttrURL)) {
1320     if (!(ch & 0x80 || url_char[ch]==0)) { // かつURL構成文字なら
1321     AttrLine[x] |= AttrURL;
1322     }
1323     }
1324     return;
1325     }
1326    
1327     if ((x-1>=0) && (AttrLine[x-1] & AttrURL) &&
1328     !(ch & 0x80 || url_char[ch]==0)) {
1329     // !((CodeLine[x] <= ' ') && !(AttrLine[x] & AttrKanji))) {
1330     AttrLine[x] |= AttrURL;
1331     // AttrLine[x] |= (AttrURL | AttrUnder);
1332     return;
1333     }
1334    
1335     if ((x-2>=0) && !strncmp(&CodeLine[x-2], "://", 3)) {
1336     int i, len = 0;
1337     if ((x-6>=0) && !strncmp(&CodeLine[x-6], "http", 4)) {
1338     len = 6;
1339     }
1340     if ((x-7>=0) && !strncmp(&CodeLine[x-7], "https", 5)) {
1341     len = 7;
1342     }
1343     if ((x-6>=0) && !strncmp(&CodeLine[x-6], "news", 4)) {
1344     len = 6;
1345     }
1346     if ((x-5>=0) && !strncmp(&CodeLine[x-5], "ftp", 3)) {
1347     len = 5;
1348     }
1349     if ((x-5>=0) && !strncmp(&CodeLine[x-5], "mms", 3)) {
1350     len = 5;
1351     }
1352     #if 0
1353     if ((x-5>=0) && !strncmp(&CodeLine[x-5], "ttp", 3)) {
1354     len = 5;
1355     }
1356     #endif
1357     for (i = 0; i <= len; i++) {
1358     AttrLine[x-i] |= AttrURL;
1359     // AttrLine[x-i] |= (AttrURL | AttrUnder);
1360     }
1361     }
1362     #endif
1363     }
1364     /* end - ishizaki */
1365    
1366     void BuffPutChar(BYTE b, TCharAttr Attr, BOOL Insert)
1367     // Put a character in the buffer at the current position
1368     // b: character
1369     // Attr: attributes
1370     // Insert: Insert flag
1371     {
1372     int XStart;
1373    
1374 doda 3312 #ifndef NO_COPYLINE_FIX
1375     if (ts.EnableContinuedLineCopy && CursorX == 0 && (AttrLine[0] & AttrLineContinued)) {
1376     Attr.Attr |= AttrLineContinued;
1377     }
1378     #endif /* NO_COPYLINE_FIX */
1379    
1380 maya 3227 if (ts.Language==IdJapanese)
1381     {
1382     EraseKanji(1); /* if cursor is on right half of a kanji, erase the kanji */
1383     if (! Insert) EraseKanji(0); /* if cursor on left half... */
1384     }
1385    
1386     if (Insert)
1387     {
1388     memmove(&CodeLine[CursorX+1],&CodeLine[CursorX],NumOfColumns-1-CursorX);
1389     memmove(&AttrLine[CursorX+1],&AttrLine[CursorX],NumOfColumns-1-CursorX);
1390     memmove(&AttrLine2[CursorX+1],&AttrLine2[CursorX],NumOfColumns-1-CursorX);
1391     memmove(&AttrLineFG[CursorX+1],&AttrLineFG[CursorX],NumOfColumns-1-CursorX);
1392     memmove(&AttrLineBG[CursorX+1],&AttrLineBG[CursorX],NumOfColumns-1-CursorX);
1393     CodeLine[CursorX] = b;
1394     AttrLine[CursorX] = Attr.Attr;
1395     AttrLine2[CursorX] = Attr.Attr2;
1396     AttrLineFG[CursorX] = Attr.Fore;
1397     AttrLineBG[CursorX] = Attr.Back;
1398     /* last char in current line is kanji first? */
1399     if ((AttrLine[NumOfColumns-1] & AttrKanji) != 0)
1400     {
1401     /* then delete it */
1402     CodeLine[NumOfColumns-1] = 0x20;
1403     AttrLine[NumOfColumns-1] = CurCharAttr.Attr;
1404     AttrLine2[NumOfColumns-1] = CurCharAttr.Attr2;
1405     AttrLineFG[NumOfColumns-1] = CurCharAttr.Fore;
1406     AttrLineBG[NumOfColumns-1] = CurCharAttr.Back;
1407     }
1408     /* begin - ishizaki */
1409     markURL(CursorX+1);
1410     markURL(CursorX);
1411     /* end - ishizaki */
1412    
1413     if (StrChangeCount==0) XStart = CursorX;
1414     else XStart = StrChangeStart;
1415     StrChangeCount = 0;
1416     BuffUpdateRect(XStart,CursorY,NumOfColumns-1,CursorY);
1417     }
1418     else {
1419     CodeLine[CursorX] = b;
1420     AttrLine[CursorX] = Attr.Attr;
1421     AttrLine2[CursorX] = Attr.Attr2;
1422     AttrLineFG[CursorX] = Attr.Fore;
1423     AttrLineBG[CursorX] = Attr.Back;
1424     /* begin - ishizaki */
1425     markURL(CursorX);
1426     /* end - ishizaki */
1427    
1428     if (StrChangeCount==0)
1429     StrChangeStart = CursorX;
1430     StrChangeCount++;
1431     }
1432     }
1433    
1434     void BuffPutKanji(WORD w, TCharAttr Attr, BOOL Insert)
1435     // Put a kanji character in the buffer at the current position
1436     // b: character
1437     // Attr: attributes
1438     // Insert: Insert flag
1439     {
1440     int XStart;
1441    
1442 doda 3312 #ifndef NO_COPYLINE_FIX
1443     if (ts.EnableContinuedLineCopy && CursorX == 0 && (AttrLine[0] | AttrLineContinued)) {
1444     Attr.Attr |= AttrLineContinued;
1445     }
1446     #endif /* NO_COPYLINE_FIX */
1447    
1448 maya 3227 EraseKanji(1); /* if cursor is on right half of a kanji, erase the kanji */
1449    
1450     if (Insert)
1451     {
1452     memmove(&CodeLine[CursorX+2],&CodeLine[CursorX],NumOfColumns-2-CursorX);
1453     memmove(&AttrLine[CursorX+2],&AttrLine[CursorX],NumOfColumns-2-CursorX);
1454     memmove(&AttrLine2[CursorX+2],&AttrLine2[CursorX],NumOfColumns-2-CursorX);
1455     memmove(&AttrLineFG[CursorX+2],&AttrLineFG[CursorX],NumOfColumns-2-CursorX);
1456     memmove(&AttrLineBG[CursorX+2],&AttrLineBG[CursorX],NumOfColumns-2-CursorX);
1457    
1458     CodeLine[CursorX] = HIBYTE(w);
1459     AttrLine[CursorX] = Attr.Attr | AttrKanji; /* DBCS first byte */
1460     AttrLine2[CursorX] = Attr.Attr2;
1461     AttrLineFG[CursorX] = Attr.Fore;
1462     AttrLineBG[CursorX] = Attr.Back;
1463     if (CursorX < NumOfColumns-1)
1464     {
1465     CodeLine[CursorX+1] = LOBYTE(w);
1466     AttrLine[CursorX+1] = Attr.Attr;
1467     AttrLine2[CursorX+1] = Attr.Attr2;
1468     AttrLineFG[CursorX+1] = Attr.Fore;
1469     AttrLineBG[CursorX+1] = Attr.Back;
1470     }
1471     /* begin - ishizaki */
1472     markURL(CursorX);
1473     markURL(CursorX+1);
1474     /* end - ishizaki */
1475    
1476     /* last char in current line is kanji first? */
1477     if ((AttrLine[NumOfColumns-1] & AttrKanji) != 0)
1478     {
1479     /* then delete it */
1480     CodeLine[NumOfColumns-1] = 0x20;
1481     AttrLine[NumOfColumns-1] = CurCharAttr.Attr;
1482     AttrLine2[NumOfColumns-1] = CurCharAttr.Attr2;
1483     AttrLineFG[NumOfColumns-1] = CurCharAttr.Fore;
1484     AttrLineBG[NumOfColumns-1] = CurCharAttr.Back;
1485     }
1486    
1487     if (StrChangeCount==0) XStart = CursorX;
1488     else XStart = StrChangeStart;
1489     StrChangeCount = 0;
1490     BuffUpdateRect(XStart,CursorY,NumOfColumns-1,CursorY);
1491     }
1492     else {
1493     CodeLine[CursorX] = HIBYTE(w);
1494     AttrLine[CursorX] = Attr.Attr | AttrKanji; /* DBCS first byte */
1495     AttrLine2[CursorX] = Attr.Attr2;
1496     AttrLineFG[CursorX] = Attr.Fore;
1497     AttrLineBG[CursorX] = Attr.Back;
1498     if (CursorX < NumOfColumns-1)
1499     {
1500     CodeLine[CursorX+1] = LOBYTE(w);
1501     AttrLine[CursorX+1] = Attr.Attr;
1502     AttrLine2[CursorX+1] = Attr.Attr2;
1503     AttrLineFG[CursorX+1] = Attr.Fore;
1504     AttrLineBG[CursorX+1] = Attr.Back;
1505     }
1506     /* begin - ishizaki */
1507     markURL(CursorX);
1508     markURL(CursorX+1);
1509     /* end - ishizaki */
1510    
1511     if (StrChangeCount==0)
1512     StrChangeStart = CursorX;
1513     StrChangeCount = StrChangeCount + 2;
1514     }
1515     }
1516    
1517     BOOL CheckSelect(int x, int y)
1518     // subroutine called by BuffUpdateRect
1519     {
1520     LONG L, L1, L2;
1521    
1522     if (BoxSelect)
1523     {
1524     return (Selected &&
1525     ((SelectStart.x<=x) && (x<SelectEnd.x) ||
1526     (SelectEnd.x<=x) && (x<SelectStart.x)) &&
1527     ((SelectStart.y<=y) && (y<=SelectEnd.y) ||
1528     (SelectEnd.y<=y) && (y<=SelectStart.y)));
1529     }
1530     else {
1531     L = MAKELONG(x,y);
1532     L1 = MAKELONG(SelectStart.x,SelectStart.y);
1533     L2 = MAKELONG(SelectEnd.x,SelectEnd.y);
1534    
1535     return (Selected &&
1536     ((L1<=L) && (L<L2) || (L2<=L) && (L<L1)));
1537     }
1538     }
1539    
1540     void BuffUpdateRect
1541     (int XStart, int YStart, int XEnd, int YEnd)
1542     // Display text in a rectangular region in the screen
1543     // XStart: x position of the upper-left corner (screen cordinate)
1544     // YStart: y position
1545     // XEnd: x position of the lower-right corner (last character)
1546     // YEnd: y position
1547     {
1548     int i, j, count;
1549     int IStart, IEnd;
1550     int X, Y;
1551     LONG TmpPtr;
1552     TCharAttr CurAttr, TempAttr;
1553     BOOL CurSel, TempSel, Caret;
1554    
1555     if (XStart >= WinOrgX+WinWidth) return;
1556     if (YStart >= WinOrgY+WinHeight) return;
1557     if (XEnd < WinOrgX) return;
1558     if (YEnd < WinOrgY) return;
1559    
1560     if (XStart < WinOrgX) XStart = WinOrgX;
1561     if (YStart < WinOrgY) YStart = WinOrgY;
1562     if (XEnd >= WinOrgX+WinWidth) XEnd = WinOrgX+WinWidth-1;
1563     if (YEnd >= WinOrgY+WinHeight) YEnd = WinOrgY+WinHeight-1;
1564    
1565     TempAttr = DefCharAttr;
1566     TempSel = FALSE;
1567    
1568     Caret = IsCaretOn();
1569     if (Caret) CaretOff();
1570    
1571     DispSetupDC(DefCharAttr, TempSel);
1572    
1573     Y = (YStart-WinOrgY)*FontHeight;
1574     TmpPtr = GetLinePtr(PageStart+YStart);
1575     for (j = YStart+PageStart ; j <= YEnd+PageStart ; j++)
1576     {
1577     IStart = XStart;
1578     IEnd = XEnd;
1579    
1580     IStart = LeftHalfOfDBCS(TmpPtr,IStart);
1581    
1582     X = (IStart-WinOrgX)*FontWidth;
1583    
1584     i = IStart;
1585     do {
1586     CurAttr.Attr = AttrBuff[TmpPtr+i] & ~ AttrKanji;
1587     CurAttr.Attr2 = AttrBuff2[TmpPtr+i];
1588     CurAttr.Fore = AttrBuffFG[TmpPtr+i];
1589     CurAttr.Back = AttrBuffBG[TmpPtr+i];
1590     CurSel = CheckSelect(i,j);
1591     count = 1;
1592     while
1593     ( (i+count <= IEnd) &&
1594     (CurAttr.Attr == (AttrBuff[TmpPtr+i+count] & ~ AttrKanji)) &&
1595     (CurAttr.Attr2==AttrBuff2[TmpPtr+i+count]) &&
1596     (CurAttr.Fore==AttrBuffFG[TmpPtr+i+count]) &&
1597     (CurAttr.Back==AttrBuffBG[TmpPtr+i+count]) &&
1598     (CurSel==CheckSelect(i+count,j)) ||
1599     (i+count<NumOfColumns) &&
1600     ((AttrBuff[TmpPtr+i+count-1] & AttrKanji) != 0) )
1601     count++;
1602    
1603     if (TCharAttrCmp(CurAttr, TempAttr) != 0 || (CurSel != TempSel)) {
1604     DispSetupDC(CurAttr, CurSel);
1605     TempAttr = CurAttr;
1606     TempSel = CurSel;
1607     }
1608     DispStr(&CodeBuff[TmpPtr+i],count,Y, &X);
1609     i = i+count;
1610     }
1611     while (i<=IEnd);
1612     Y = Y + FontHeight;
1613     TmpPtr = NextLinePtr(TmpPtr);
1614     }
1615     if (Caret) CaretOn();
1616     }
1617    
1618     void UpdateStr()
1619     // Display not-yet-displayed string
1620     {
1621     int X, Y;
1622     TCharAttr TempAttr;
1623    
1624     if (StrChangeCount==0) return;
1625     X = StrChangeStart;
1626     Y = CursorY;
1627     if (! IsLineVisible(&X, &Y))
1628     {
1629     StrChangeCount = 0;
1630     return;
1631     }
1632    
1633     TempAttr.Attr = AttrLine[StrChangeStart];
1634     TempAttr.Attr2 = AttrLine2[StrChangeStart];
1635     TempAttr.Fore = AttrLineFG[StrChangeStart];
1636     TempAttr.Back = AttrLineBG[StrChangeStart];
1637     DispSetupDC(TempAttr, FALSE);
1638     DispStr(&CodeLine[StrChangeStart],StrChangeCount,Y, &X);
1639     StrChangeCount = 0;
1640     }
1641    
1642     #if 0
1643     void UpdateStrUnicode(void)
1644     // Display not-yet-displayed string
1645     {
1646     int X, Y;
1647     TCharAttr TempAttr;
1648    
1649     if (StrChangeCount==0) return;
1650     X = StrChangeStart;
1651     Y = CursorY;
1652     if (! IsLineVisible(&X, &Y))
1653     {
1654     StrChangeCount = 0;
1655     return;
1656     }
1657    
1658     TempAttr.Attr = AttrLine[StrChangeStart];
1659     TempAttr.Attr2 = AttrLine2[StrChangeStart];
1660     TempAttr.Fore = AttrLineFG[StrChangeStart];
1661     TempAttr.Back = AttrLineBG[StrChangeStart];
1662     DispSetupDC(TempAttr, FALSE);
1663     DispStr(&CodeLine[StrChangeStart],StrChangeCount,Y, &X);
1664     StrChangeCount = 0;
1665     }
1666     #endif
1667    
1668     void MoveCursor(int Xnew, int Ynew)
1669     {
1670     UpdateStr();
1671    
1672     if (CursorY!=Ynew) NewLine(PageStart+Ynew);
1673    
1674     CursorX = Xnew;
1675     CursorY = Ynew;
1676     Wrap = FALSE;
1677    
1678     /* 最下行でだけ自動スクロールする*/
1679     if (ts.AutoScrollOnlyInBottomLine == 0 || WinOrgY == 0) {
1680     DispScrollToCursor(CursorX, CursorY);
1681     }
1682     }
1683    
1684     void MoveRight()
1685     /* move cursor right, but dont update screen.
1686     this procedure must be called from DispChar&DispKanji only */
1687     {
1688     CursorX++;
1689     /* 最下行でだけ自動スクロールする */
1690     if (ts.AutoScrollOnlyInBottomLine == 0 || WinOrgY == 0) {
1691     DispScrollToCursor(CursorX, CursorY);
1692     }
1693     }
1694    
1695     void BuffSetCaretWidth()
1696     {
1697     BOOL DW;
1698    
1699     /* check whether cursor on a DBCS character */
1700     DW = (((BYTE)(AttrLine[CursorX]) & AttrKanji) != 0);
1701     DispSetCaretWidth(DW);
1702     }
1703    
1704     void ScrollUp1Line()
1705     {
1706     int i;
1707     LONG SrcPtr, DestPtr;
1708    
1709     if ((CursorTop<=CursorY) && (CursorY<=CursorBottom))
1710     {
1711     UpdateStr();
1712    
1713     DestPtr = GetLinePtr(PageStart+CursorBottom);
1714     for (i = CursorBottom-1 ; i >= CursorTop ; i--)
1715     {
1716     SrcPtr = PrevLinePtr(DestPtr);
1717     memcpy(&(CodeBuff[DestPtr]),&(CodeBuff[SrcPtr]),NumOfColumns);
1718     memcpy(&(AttrBuff[DestPtr]),&(AttrBuff[SrcPtr]),NumOfColumns);
1719     memcpy(&(AttrBuff2[DestPtr]),&(AttrBuff2[SrcPtr]),NumOfColumns);
1720     memcpy(&(AttrBuffFG[DestPtr]),&(AttrBuffFG[SrcPtr]),NumOfColumns);
1721     memcpy(&(AttrBuffBG[DestPtr]),&(AttrBuffBG[SrcPtr]),NumOfColumns);
1722     DestPtr = SrcPtr;
1723     }
1724     memset(&(CodeBuff[SrcPtr]),0x20,NumOfColumns);
1725     memset(&(AttrBuff[SrcPtr]),AttrDefault,NumOfColumns);
1726     memset(&(AttrBuff2[SrcPtr]),CurCharAttr.Attr2,NumOfColumns);
1727     memset(&(AttrBuffFG[SrcPtr]),CurCharAttr.Fore,NumOfColumns);
1728     memset(&(AttrBuffBG[SrcPtr]),CurCharAttr.Back,NumOfColumns);
1729    
1730     DispScrollNLines(CursorTop,CursorBottom,-1);
1731     }
1732     }
1733    
1734     void BuffScrollNLines(int n)
1735     {
1736     int i;
1737     LONG SrcPtr, DestPtr;
1738    
1739     if (n<1) return;
1740     UpdateStr();
1741    
1742     if ((CursorTop == 0) && (CursorBottom == NumOfLines-1))
1743     {
1744     WinOrgY = WinOrgY-n;
1745     /* 最下行でだけ自動スクロールする */
1746     if (ts.AutoScrollOnlyInBottomLine != 0 && NewOrgY != 0) {
1747     NewOrgY = WinOrgY;
1748     }
1749     BuffScroll(n,CursorBottom);
1750     DispCountScroll(n);
1751     }
1752     else if ((CursorTop==0) && (CursorY<=CursorBottom))
1753     {
1754     BuffScroll(n,CursorBottom);
1755     DispScrollNLines(WinOrgY,CursorBottom,n);
1756     }
1757     else if ((CursorTop<=CursorY) && (CursorY<=CursorBottom))
1758     {
1759     DestPtr = GetLinePtr(PageStart+CursorTop);
1760     if (n<CursorBottom-CursorTop+1)
1761     {
1762     SrcPtr = GetLinePtr(PageStart+CursorTop+n);
1763     for (i = CursorTop+n ; i<=CursorBottom ; i++)
1764     {
1765     memmove(&(CodeBuff[DestPtr]),&(CodeBuff[SrcPtr]),NumOfColumns);
1766     memmove(&(AttrBuff[DestPtr]),&(AttrBuff[SrcPtr]),NumOfColumns);
1767     memmove(&(AttrBuff2[DestPtr]),&(AttrBuff2[SrcPtr]),NumOfColumns);
1768     memmove(&(AttrBuffFG[DestPtr]),&(AttrBuffFG[SrcPtr]),NumOfColumns);
1769     memmove(&(AttrBuffBG[DestPtr]),&(AttrBuffBG[SrcPtr]),NumOfColumns);
1770     SrcPtr = NextLinePtr(SrcPtr);
1771     DestPtr = NextLinePtr(DestPtr);
1772     }
1773     }
1774     else
1775     n = CursorBottom-CursorTop+1;
1776     for (i = CursorBottom+1-n ; i<=CursorBottom; i++)
1777     {
1778     memset(&(CodeBuff[DestPtr]),0x20,NumOfColumns);
1779     memset(&(AttrBuff[DestPtr]),AttrDefault,NumOfColumns);
1780     memset(&(AttrBuff2[DestPtr]),CurCharAttr.Attr2,NumOfColumns);
1781     memset(&(AttrBuffFG[DestPtr]),CurCharAttr.Fore,NumOfColumns);
1782     memset(&(AttrBuffBG[DestPtr]),CurCharAttr.Back,NumOfColumns);
1783     DestPtr = NextLinePtr(DestPtr);
1784     }
1785     DispScrollNLines(CursorTop,CursorBottom,n);
1786     }
1787     }
1788    
1789     void BuffRegionScrollUpNLines(int n) {
1790     int i;
1791     LONG SrcPtr, DestPtr;
1792    
1793     if (n<1) return;
1794     UpdateStr();
1795    
1796     if (n > 0) {
1797     if ((CursorTop == 0) && (CursorBottom == NumOfLines-1)) {
1798     WinOrgY = WinOrgY-n;
1799     BuffScroll(n,CursorBottom);
1800     DispCountScroll(n);
1801     }
1802     else if (CursorTop==0) {
1803     BuffScroll(n,CursorBottom);
1804     DispScrollNLines(WinOrgY,CursorBottom,n);
1805     }
1806     else {
1807     DestPtr = GetLinePtr(PageStart+CursorTop);
1808     if (n<CursorBottom-CursorTop+1) {
1809     SrcPtr = GetLinePtr(PageStart+CursorTop+n);
1810     for (i = CursorTop+n ; i<=CursorBottom ; i++) {
1811     memmove(&(CodeBuff[DestPtr]),&(CodeBuff[SrcPtr]),NumOfColumns);
1812     memmove(&(AttrBuff[DestPtr]),&(AttrBuff[SrcPtr]),NumOfColumns);
1813     memmove(&(AttrBuff2[DestPtr]),&(AttrBuff2[SrcPtr]),NumOfColumns);
1814     memmove(&(AttrBuffFG[DestPtr]),&(AttrBuffFG[SrcPtr]),NumOfColumns);
1815     memmove(&(AttrBuffBG[DestPtr]),&(AttrBuffBG[SrcPtr]),NumOfColumns);
1816     SrcPtr = NextLinePtr(SrcPtr);
1817     DestPtr = NextLinePtr(DestPtr);
1818     }
1819     }
1820     else
1821     n = CursorBottom-CursorTop+1;
1822     for (i = CursorBottom+1-n ; i<=CursorBottom; i++) {
1823     memset(&(CodeBuff[DestPtr]),0x20,NumOfColumns);
1824     memset(&(AttrBuff[DestPtr]),AttrDefault,NumOfColumns);
1825     memset(&(AttrBuff2[DestPtr]),CurCharAttr.Attr2,NumOfColumns);
1826     memset(&(AttrBuffFG[DestPtr]),CurCharAttr.Fore,NumOfColumns);
1827     memset(&(AttrBuffBG[DestPtr]),CurCharAttr.Back,NumOfColumns);
1828     DestPtr = NextLinePtr(DestPtr);
1829     }
1830     DispScrollNLines(CursorTop,CursorBottom,n);
1831     }
1832     }
1833     }
1834    
1835     void BuffRegionScrollDownNLines(int n) {
1836     int i;
1837     LONG SrcPtr, DestPtr;
1838    
1839     if (n<1) {
1840     return;
1841     }
1842     UpdateStr();
1843    
1844     DestPtr = GetLinePtr(PageStart+CursorBottom);
1845     if (n < CursorBottom-CursorTop+1) {
1846     SrcPtr = GetLinePtr(PageStart+CursorBottom-n);
1847     for (i=CursorBottom-n ; i>=CursorTop ; i--) {
1848     memmove(&(CodeBuff[DestPtr]),&(CodeBuff[SrcPtr]),NumOfColumns);
1849     memmove(&(AttrBuff[DestPtr]),&(AttrBuff[SrcPtr]),NumOfColumns);
1850     memmove(&(AttrBuff2[DestPtr]),&(AttrBuff2[SrcPtr]),NumOfColumns);
1851     memmove(&(AttrBuffFG[DestPtr]),&(AttrBuffFG[SrcPtr]),NumOfColumns);
1852     memmove(&(AttrBuffBG[DestPtr]),&(AttrBuffBG[SrcPtr]),NumOfColumns);
1853     SrcPtr = PrevLinePtr(SrcPtr);
1854     DestPtr = PrevLinePtr(DestPtr);
1855     }
1856     }
1857     else {
1858     n = CursorBottom - CursorTop + 1;
1859     }
1860     for (i = CursorTop+n-1; i>=CursorTop; i--) {
1861     memset(&(CodeBuff[DestPtr]),0x20,NumOfColumns);
1862     memset(&(AttrBuff[DestPtr]),AttrDefault,NumOfColumns);
1863     memset(&(AttrBuff2[DestPtr]),CurCharAttr.Attr2,NumOfColumns);
1864     memset(&(AttrBuffFG[DestPtr]),CurCharAttr.Fore,NumOfColumns);
1865     memset(&(AttrBuffBG[DestPtr]),CurCharAttr.Back,NumOfColumns);
1866     DestPtr = PrevLinePtr(DestPtr);
1867     }
1868    
1869     DispScrollNLines(CursorTop,CursorBottom,-n);
1870     }
1871    
1872     void BuffClearScreen()
1873     { // clear screen
1874     if ((StatusLine>0) && (CursorY==NumOfLines-1))
1875     BuffScrollNLines(1); /* clear status line */
1876     else { /* clear main screen */
1877     UpdateStr();
1878     BuffScroll(NumOfLines-StatusLine,NumOfLines-1-StatusLine);
1879     DispScrollNLines(WinOrgY,NumOfLines-1-StatusLine,NumOfLines-StatusLine);
1880     }
1881     }
1882    
1883     void BuffUpdateScroll()
1884     // Updates scrolling
1885     {
1886     UpdateStr();
1887     DispUpdateScroll();
1888     }
1889    
1890     void CursorUpWithScroll()
1891     {
1892     if ((0<CursorY) && (CursorY<CursorTop) ||
1893     (CursorTop<CursorY))
1894     MoveCursor(CursorX,CursorY-1);
1895     else if (CursorY==CursorTop)
1896     ScrollUp1Line();
1897     }
1898    
1899     // called by BuffDblClk
1900     // check if a character is the word delimiter
1901     BOOL IsDelimiter(LONG Line, int CharPtr)
1902     {
1903     if ((AttrBuff[Line+CharPtr] & AttrKanji) !=0)
1904     return (ts.DelimDBCS!=0);
1905     return
1906     (strchr(ts.DelimList,CodeBuff[Line+CharPtr])!=NULL);
1907     }
1908    
1909     void GetMinMax(int i1, int i2, int i3,
1910     int *min, int *max)
1911     {
1912     if (i1<i2)
1913     {
1914     *min = i1;
1915     *max = i2;
1916     }
1917     else {
1918     *min = i2;
1919     *max = i1;
1920     }
1921     if (i3<*min)
1922     *min = i3;
1923     if (i3>*max)
1924     *max = i3;
1925     }
1926    
1927     /* start - ishizaki */
1928     static void invokeBrowser(LONG ptr)
1929     {
1930     #ifdef URL_EMPHASIS
1931     LONG i, start, end;
1932     char url[1024];
1933     char *uptr, ch;
1934    
1935     start = ptr;
1936     while (AttrBuff[start] & AttrURL) start--;
1937     start++;
1938    
1939     end = ptr;
1940     while (AttrBuff[end] & AttrURL) end++;
1941     end--;
1942    
1943     if (start + 1024 <= end) end = start + 1023;
1944     uptr = url;
1945     for (i = 0; i < end - start + 1; i++) {
1946     ch = CodeBuff[start + i];
1947     if ((start + i) % NumOfColumns == NumOfColumns - 1
1948     && ch == '\\') {
1949     // Emacs対応。行末に \ が来ている場合は、次の行に続くという意味で emacs が
1950     // 自動で挿入する文字なので、URLには含めないようにする。
1951     // (2007.8.7 yutaka)
1952    
1953     } else {
1954     *uptr++ = ch;
1955     }
1956     }
1957     *uptr = '\0';
1958     ShellExecute(NULL, NULL, url, NULL, NULL,SW_SHOWNORMAL);
1959     #endif
1960     }
1961     /* end - ishizaki */
1962    
1963     void ChangeSelectRegion()
1964     {
1965     POINT TempStart, TempEnd;
1966     int j, IStart, IEnd;
1967     BOOL Caret;
1968    
1969     if ((SelectEndOld.x==SelectEnd.x) &&
1970     (SelectEndOld.y==SelectEnd.y)) return;
1971    
1972     if (BoxSelect)
1973     {
1974     GetMinMax(SelectStart.x,SelectEndOld.x,SelectEnd.x,
1975     (int *)&TempStart.x,(int *)&TempEnd.x);
1976     GetMinMax(SelectStart.y,SelectEndOld.y,SelectEnd.y,
1977     (int *)&TempStart.y,(int *)&TempEnd.y);
1978     TempEnd.x--;
1979     Caret = IsCaretOn();
1980     if (Caret) CaretOff();
1981     DispInitDC();
1982     BuffUpdateRect(TempStart.x,TempStart.y-PageStart,
1983     TempEnd.x,TempEnd.y-PageStart);
1984     DispReleaseDC();
1985     if (Caret) CaretOn();
1986     SelectEndOld = SelectEnd;
1987     return;
1988     }
1989    
1990     if ((SelectEndOld.y < SelectEnd.y) ||
1991     (SelectEndOld.y==SelectEnd.y) &&
1992     (SelectEndOld.x<=SelectEnd.x))
1993     {
1994     TempStart = SelectEndOld;
1995     TempEnd.x = SelectEnd.x-1;
1996     TempEnd.y = SelectEnd.y;
1997     }
1998     else {
1999     TempStart = SelectEnd;
2000     TempEnd.x = SelectEndOld.x-1;
2001     TempEnd.y = SelectEndOld.y;
2002     }
2003     if (TempEnd.x < 0)
2004     {
2005     TempEnd.x = NumOfColumns - 1;
2006     TempEnd.y--;
2007     }
2008    
2009     Caret = IsCaretOn();
2010     if (Caret) CaretOff();
2011     for (j = TempStart.y ; j <= TempEnd.y ; j++)
2012     {
2013     IStart = 0;
2014     IEnd = NumOfColumns-1;
2015     if (j==TempStart.y) IStart = TempStart.x;
2016     if (j==TempEnd.y) IEnd = TempEnd.x;
2017    
2018     if ((IEnd>=IStart) && (j >= PageStart+WinOrgY) &&
2019     (j < PageStart+WinOrgY+WinHeight))
2020     {
2021     DispInitDC();
2022     BuffUpdateRect(IStart,j-PageStart,IEnd,j-PageStart);
2023     DispReleaseDC();
2024     }
2025     }
2026     if (Caret) CaretOn();
2027    
2028     SelectEndOld = SelectEnd;
2029     }
2030    
2031     BOOL BuffUrlDblClk(int Xw, int Yw)
2032     {
2033     int X, Y;
2034     LONG TmpPtr;
2035     BOOL url_invoked = FALSE;
2036    
2037     if (! ts.EnableClickableUrl) {
2038     return FALSE;
2039     }
2040    
2041     CaretOff();
2042    
2043     DispConvWinToScreen(Xw,Yw,&X,&Y,NULL);
2044     Y = Y + PageStart;
2045     if ((Y<0) || (Y>=BuffEnd)) return 0;
2046     if (X<0) X = 0;
2047     if (X>=NumOfColumns) X = NumOfColumns-1;
2048    
2049     if ((Y>=0) && (Y<BuffEnd)) {
2050     LockBuffer();
2051     TmpPtr = GetLinePtr(Y);
2052     /* start - ishizaki */
2053     if (AttrBuff[TmpPtr+X] & AttrURL) {
2054     BoxSelect = FALSE;
2055     SelectEnd = SelectStart;
2056     ChangeSelectRegion();
2057    
2058     url_invoked = TRUE;
2059     invokeBrowser(TmpPtr+X);
2060    
2061     SelectStart.x = 0;
2062     SelectStart.y = 0;
2063     SelectEnd.x = 0;
2064     SelectEnd.y = 0;
2065     SelectEndOld.x = 0;
2066     SelectEndOld.y = 0;
2067     Selected = FALSE;
2068     }
2069     UnlockBuffer();
2070     }
2071     return url_invoked;
2072     }
2073    
2074     void BuffDblClk(int Xw, int Yw)
2075     // Select a word at (Xw, Yw) by mouse double click
2076     // Xw: horizontal position in window coordinate (pixels)
2077     // Yw: vertical
2078     {
2079     int X, Y, YStart, YEnd;
2080     int IStart, IEnd, i;
2081     LONG TmpPtr;
2082     BYTE b;
2083     BOOL DBCS;
2084    
2085     CaretOff();
2086    
2087     DispConvWinToScreen(Xw,Yw,&X,&Y,NULL);
2088     Y = Y + PageStart;
2089     if ((Y<0) || (Y>=BuffEnd)) return;
2090     if (X<0) X = 0;
2091     if (X>=NumOfColumns) X = NumOfColumns-1;
2092    
2093     BoxSelect = FALSE;
2094     LockBuffer();
2095     SelectEnd = SelectStart;
2096     ChangeSelectRegion();
2097    
2098     if ((Y>=0) && (Y<BuffEnd))
2099     {
2100     TmpPtr = GetLinePtr(Y);
2101    
2102     IStart = X;
2103     IStart = LeftHalfOfDBCS(TmpPtr,IStart);
2104     IEnd = IStart;
2105     YStart = YEnd = Y;
2106    
2107     if (IsDelimiter(TmpPtr,IStart))
2108     {
2109     b = CodeBuff[TmpPtr+IStart];
2110     DBCS = (AttrBuff[TmpPtr+IStart] & AttrKanji) != 0;
2111     while ((b==CodeBuff[TmpPtr+IStart]) ||
2112     DBCS &&
2113     ((AttrBuff[TmpPtr+IStart] & AttrKanji)!=0)) {
2114     MoveCharPtr(TmpPtr,&IStart,-1); // move left
2115     if (ts.EnableContinuedLineCopy) {
2116     if (IStart<=0) {
2117     // 左端の場合
2118     if (YStart>0 && AttrBuff[TmpPtr] & AttrLineContinued) {
2119     // 前の行に移動する
2120     YStart--;
2121     TmpPtr = GetLinePtr(YStart);
2122     IStart = NumOfColumns;
2123     }
2124     else {
2125     break;
2126     }
2127     }
2128     }
2129     else {
2130     if (IStart<=0) {
2131     // 左端の場合は終わり
2132     break;
2133     }
2134     }
2135     }
2136     if ((b!=CodeBuff[TmpPtr+IStart]) &&
2137     ! (DBCS &&
2138     ((AttrBuff[TmpPtr+IStart] & AttrKanji)!=0))) {
2139     // 最終位置が Delimiter でない場合にはひとつ右にずらす
2140     if (ts.EnableContinuedLineCopy && IStart == NumOfColumns-1) {
2141     // 右端の場合には次の行へ移動する
2142     YStart++;
2143     TmpPtr = GetLinePtr(YStart);
2144     IStart = 0;
2145     }
2146     else {
2147     MoveCharPtr(TmpPtr,&IStart,1);
2148     }
2149     }
2150    
2151     // 行が移動しているかもしれないので、クリックした行を取り直す
2152     TmpPtr = GetLinePtr(YEnd);
2153     i = 1;
2154     while (((b==CodeBuff[TmpPtr+IEnd]) ||
2155     DBCS &&
2156     ((AttrBuff[TmpPtr+IEnd] & AttrKanji)!=0))) {
2157     i = MoveCharPtr(TmpPtr,&IEnd,1); // move right
2158     if (ts.EnableContinuedLineCopy) {
2159     if (i==0) {
2160     // 右端の場合
2161     if (YEnd<BuffEnd &&
2162     AttrBuff[TmpPtr+IEnd+1+DBCS] & AttrLineContinued) {
2163     // 次の行に移動する
2164     YEnd++;
2165     TmpPtr = GetLinePtr(YEnd);
2166     IEnd = 0;
2167     }
2168     else {
2169     break;
2170     }
2171     }
2172     }
2173     else {
2174     if (i==0) {
2175     // 右端の場合は終わり
2176     break;
2177     }
2178     }
2179     }
2180     }
2181     else {
2182     while (! IsDelimiter(TmpPtr,IStart)) {
2183     MoveCharPtr(TmpPtr,&IStart,-1); // move left
2184     if (ts.EnableContinuedLineCopy) {
2185     if (IStart<=0) {
2186     // 左端の場合
2187     if (YStart>0 && AttrBuff[TmpPtr] & AttrLineContinued) {
2188     // 前の行に移動する
2189     YStart--;
2190     TmpPtr = GetLinePtr(YStart);
2191     IStart = NumOfColumns;
2192     }
2193     else {
2194     break;
2195     }
2196     }
2197     }
2198     else {
2199     if (IStart<=0) {
2200     // 左端の場合は終わり
2201     break;
2202     }
2203     }
2204     }
2205     if (IsDelimiter(TmpPtr,IStart)) {
2206     // 最終位置が Delimiter の場合にはひとつ右にずらす
2207     if (ts.EnableContinuedLineCopy && IStart == NumOfColumns-1) {
2208     // 右端の場合には次の行へ移動する
2209     YStart++;
2210     TmpPtr = GetLinePtr(YStart);
2211     IStart = 0;
2212     }
2213     else {
2214     MoveCharPtr(TmpPtr,&IStart,1);
2215     }
2216     }
2217    
2218     // 行が移動しているかもしれないので、クリックした行を取り直す
2219     TmpPtr = GetLinePtr(YEnd);
2220     i = 1;
2221     while (! IsDelimiter(TmpPtr,IEnd)) {
2222     i = MoveCharPtr(TmpPtr,&IEnd,1); // move right
2223     if (ts.EnableContinuedLineCopy) {
2224     if (i==0) {
2225     // 右端の場合
2226     if (YEnd<BuffEnd && AttrBuff[TmpPtr+IEnd+1] & AttrLineContinued) {
2227     // 次の行に移動する
2228     YEnd++;
2229     TmpPtr = GetLinePtr(YEnd);
2230     IEnd = 0;
2231     }
2232     else {
2233     break;
2234     }
2235     }
2236     }
2237     else {
2238     if (i==0) {
2239     // 右端の場合は終わり
2240     break;
2241     }
2242     }
2243     }
2244     }
2245     if (ts.EnableContinuedLineCopy) {
2246     if (IEnd == 0) {
2247     // 左端の場合には前の行へ移動する
2248     YEnd--;
2249     IEnd = NumOfColumns;
2250     }
2251     else if (i==0) {
2252     IEnd = NumOfColumns;
2253     }
2254     }
2255     else {
2256     if (i==0)
2257     IEnd = NumOfColumns;
2258     }
2259    
2260     SelectStart.x = IStart;
2261     SelectStart.y = YStart;
2262     SelectEnd.x = IEnd;
2263     SelectEnd.y = YEnd;
2264     SelectEndOld = SelectStart;
2265     DblClkStart = SelectStart;
2266     DblClkEnd = SelectEnd;
2267     Selected = TRUE;
2268     ChangeSelectRegion();
2269     }
2270     UnlockBuffer();
2271     return;
2272     }
2273    
2274     void BuffTplClk(int Yw)
2275     // Select a line at Yw by mouse tripple click
2276     // Yw: vertical clicked position
2277     // in window coordinate (pixels)
2278     {
2279     int Y;
2280    
2281     CaretOff();
2282    
2283     DispConvWinToScreen(0,Yw,NULL,&Y,NULL);
2284     Y = Y + PageStart;
2285     if ((Y<0) || (Y>=BuffEnd)) return;
2286    
2287     LockBuffer();
2288     SelectEnd = SelectStart;
2289     ChangeSelectRegion();
2290     SelectStart.x = 0;
2291     SelectStart.y = Y;
2292     SelectEnd.x = NumOfColumns;
2293     SelectEnd.y = Y;
2294     SelectEndOld = SelectStart;
2295     DblClkStart = SelectStart;
2296     DblClkEnd = SelectEnd;
2297     Selected = TRUE;
2298     ChangeSelectRegion();
2299     UnlockBuffer();
2300     }
2301    
2302    
2303     // The block of the text between old and new cursor positions is being selected.
2304     // This function enables to select several pages of output from Tera Term window.
2305     // add (2005.5.15 yutaka)
2306     void BuffSeveralPagesSelect(int Xw, int Yw)
2307     // Start text selection by mouse button down
2308     // Xw: horizontal position in window coordinate (pixels)
2309     // Yw: vertical
2310     {
2311     int X, Y;
2312     BOOL Right;
2313    
2314     DispConvWinToScreen(Xw,Yw, &X,&Y,&Right);
2315     Y = Y + PageStart;
2316     if ((Y<0) || (Y>=BuffEnd)) return;
2317     if (X<0) X = 0;
2318     if (X>=NumOfColumns) X = NumOfColumns-1;
2319    
2320     SelectEnd.x = X;
2321     SelectEnd.y = Y;
2322     //BoxSelect = FALSE; // box selecting disabled
2323     SeveralPageSelect = TRUE;
2324     }
2325    
2326     void BuffStartSelect(int Xw, int Yw, BOOL Box)
2327     // Start text selection by mouse button down
2328     // Xw: horizontal position in window coordinate (pixels)
2329     // Yw: vertical
2330     // Box: Box selection if TRUE
2331     {
2332     int X, Y;
2333     BOOL Right;
2334     LONG TmpPtr;
2335    
2336     DispConvWinToScreen(Xw,Yw, &X,&Y,&Right);
2337     Y = Y + PageStart;
2338     if ((Y<0) || (Y>=BuffEnd)) return;
2339     if (X<0) X = 0;
2340     if (X>=NumOfColumns) X = NumOfColumns-1;
2341    
2342     SelectEndOld = SelectEnd;
2343     SelectEnd = SelectStart;
2344    
2345     LockBuffer();
2346     ChangeSelectRegion();
2347     UnlockBuffer();
2348    
2349     SelectStart.x = X;
2350     SelectStart.y = Y;
2351     if (SelectStart.x<0) SelectStart.x = 0;
2352     if (SelectStart.x > NumOfColumns)
2353     SelectStart.x = NumOfColumns;
2354     if (SelectStart.y < 0) SelectStart.y = 0;
2355     if (SelectStart.y >= BuffEnd)
2356     SelectStart.y = BuffEnd - 1;
2357    
2358     TmpPtr = GetLinePtr(SelectStart.y);
2359     // check if the cursor is on the right half of a character
2360     if ((SelectStart.x>0) &&
2361     ((AttrBuff[TmpPtr+SelectStart.x-1] & AttrKanji) != 0) ||
2362     ((AttrBuff[TmpPtr+SelectStart.x] & AttrKanji) == 0) &&
2363     Right) SelectStart.x++;
2364    
2365     SelectEnd = SelectStart;
2366     SelectEndOld = SelectEnd;
2367     CaretOff();
2368     Selected = TRUE;
2369     BoxSelect = Box;
2370     }
2371    
2372     void BuffChangeSelect(int Xw, int Yw, int NClick)
2373     // Change selection region by mouse move
2374     // Xw: horizontal position of the mouse cursor
2375     // in window coordinate
2376     // Yw: vertical
2377     {
2378     int X, Y;
2379     BOOL Right;
2380     LONG TmpPtr;
2381     int i;
2382     BYTE b;
2383     BOOL DBCS;
2384    
2385     DispConvWinToScreen(Xw,Yw,&X,&Y,&Right);
2386     Y = Y + PageStart;
2387    
2388     if (X<0) X = 0;
2389     if (X > NumOfColumns)
2390     X = NumOfColumns;
2391     if (Y < 0) Y = 0;
2392     if (Y >= BuffEnd)
2393     Y = BuffEnd - 1;
2394    
2395     TmpPtr = GetLinePtr(Y);
2396     LockBuffer();
2397     // check if the cursor is on the right half of a character
2398     if ((X>0) &&
2399     ((AttrBuff[TmpPtr+X-1] & AttrKanji) != 0) ||
2400     (X<NumOfColumns) &&
2401     ((AttrBuff[TmpPtr+X] & AttrKanji) == 0) &&
2402     Right) X++;
2403    
2404     if (X > NumOfColumns)
2405     X = NumOfColumns;
2406    
2407     // check URL string on mouse over(2005/4/3 yutaka)
2408     if (NClick == 0) {
2409     extern void SetMouseCursor(char *cursor);
2410    
2411     if ((AttrBuff[TmpPtr+X] & AttrURL)) {
2412     SetMouseCursor("HAND");
2413    
2414     } else {
2415     SetMouseCursor(ts.MouseCursorName);
2416     //SetCursor(LoadCursor(NULL, IDC_IBEAM));
2417    
2418     }
2419    
2420     UnlockBuffer();
2421     return;
2422     }
2423    
2424     #if 0
2425     /* start - ishizaki */
2426     if (ts.EnableClickableUrl && (NClick == 2) && (AttrBuff[TmpPtr+X] & AttrURL)) {
2427     invokeBrowser(TmpPtr+X);
2428    
2429     SelectStart.x = 0;
2430     SelectStart.y = 0;
2431     SelectEnd.x = 0;
2432     SelectEnd.y = 0;
2433     SelectEndOld.x = 0;
2434     SelectEndOld.y = 0;
2435     Selected = FALSE;
2436     goto end;
2437     }
2438     /* end - ishizaki */
2439     #endif
2440    
2441     SelectEnd.x = X;
2442     SelectEnd.y = Y;
2443    
2444     if (NClick==2) // drag after double click
2445     {
2446     if ((SelectEnd.y>SelectStart.y) ||
2447     (SelectEnd.y<