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 3316 - (hide annotations) (download) (as text)
Wed Apr 15 12:49:32 2009 UTC (14 years, 11 months ago) by doda
File MIME type: text/x-csrc
File size: 76634 byte(s)
ELで行末までを消した時に、次の行への継続もクリアするようにした。

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