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 3338 - (hide annotations) (download) (as text)
Wed Apr 22 10:27:54 2009 UTC (14 years, 11 months ago) by doda
Original Path: trunk/teraterm/teraterm/buffer.c
File MIME type: text/x-csrc
File size: 76932 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 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 doda 3338 if (ts.EnableContinuedLineCopy && CursorX == 0 && (AttrLine[0] & AttrLineContinued)) {
1451 doda 3312 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 salarm 3321 if (ts.AutoScrollOnlyInBottomLine != 0 && NewOrgY != 0) {
1754     NewOrgY = WinOrgY;
1755     }
1756 maya 3227 BuffScroll(n,CursorBottom);
1757     DispCountScroll(n);
1758     }
1759     else if ((CursorTop==0) && (CursorY<=CursorBottom))
1760     {
1761 salarm 3321 /* 最下行でだけ自動スクロールする */
1762     if (ts.AutoScrollOnlyInBottomLine != 0 && NewOrgY != 0) {
1763     /* スクロールさせない場合の処理 */
1764     WinOrgY = WinOrgY-n;
1765     NewOrgY = WinOrgY;
1766     BuffScroll(n,CursorBottom);
1767     DispCountScroll(n);
1768     } else {
1769     BuffScroll(n,CursorBottom);
1770     DispScrollNLines(WinOrgY,CursorBottom,n);
1771     }
1772 maya 3227 }
1773     else if ((CursorTop<=CursorY) && (CursorY<=CursorBottom))
1774     {
1775     DestPtr = GetLinePtr(PageStart+CursorTop);
1776     if (n<CursorBottom-CursorTop+1)
1777     {
1778     SrcPtr = GetLinePtr(PageStart+CursorTop+n);
1779     for (i = CursorTop+n ; i<=CursorBottom ; i++)
1780     {
1781     memmove(&(CodeBuff[DestPtr]),&(CodeBuff[SrcPtr]),NumOfColumns);
1782     memmove(&(AttrBuff[DestPtr]),&(AttrBuff[SrcPtr]),NumOfColumns);
1783     memmove(&(AttrBuff2[DestPtr]),&(AttrBuff2[SrcPtr]),NumOfColumns);
1784     memmove(&(AttrBuffFG[DestPtr]),&(AttrBuffFG[SrcPtr]),NumOfColumns);
1785     memmove(&(AttrBuffBG[DestPtr]),&(AttrBuffBG[SrcPtr]),NumOfColumns);
1786     SrcPtr = NextLinePtr(SrcPtr);
1787     DestPtr = NextLinePtr(DestPtr);
1788     }
1789     }
1790     else
1791     n = CursorBottom-CursorTop+1;
1792     for (i = CursorBottom+1-n ; i<=CursorBottom; i++)
1793     {
1794     memset(&(CodeBuff[DestPtr]),0x20,NumOfColumns);
1795     memset(&(AttrBuff[DestPtr]),AttrDefault,NumOfColumns);
1796     memset(&(AttrBuff2[DestPtr]),CurCharAttr.Attr2,NumOfColumns);
1797     memset(&(AttrBuffFG[DestPtr]),CurCharAttr.Fore,NumOfColumns);
1798     memset(&(AttrBuffBG[DestPtr]),CurCharAttr.Back,NumOfColumns);
1799     DestPtr = NextLinePtr(DestPtr);
1800     }
1801     DispScrollNLines(CursorTop,CursorBottom,n);
1802     }
1803     }
1804    
1805     void BuffRegionScrollUpNLines(int n) {
1806     int i;
1807     LONG SrcPtr, DestPtr;
1808    
1809     if (n<1) return;
1810     UpdateStr();
1811    
1812     if (n > 0) {
1813     if ((CursorTop == 0) && (CursorBottom == NumOfLines-1)) {
1814     WinOrgY = WinOrgY-n;
1815     BuffScroll(n,CursorBottom);
1816     DispCountScroll(n);
1817     }
1818     else if (CursorTop==0) {
1819     BuffScroll(n,CursorBottom);
1820     DispScrollNLines(WinOrgY,CursorBottom,n);
1821     }
1822     else {
1823     DestPtr = GetLinePtr(PageStart+CursorTop);
1824     if (n<CursorBottom-CursorTop+1) {
1825     SrcPtr = GetLinePtr(PageStart+CursorTop+n);
1826     for (i = CursorTop+n ; i<=CursorBottom ; i++) {
1827     memmove(&(CodeBuff[DestPtr]),&(CodeBuff[SrcPtr]),NumOfColumns);
1828     memmove(&(AttrBuff[DestPtr]),&(AttrBuff[SrcPtr]),NumOfColumns);
1829     memmove(&(AttrBuff2[DestPtr]),&(AttrBuff2[SrcPtr]),NumOfColumns);
1830     memmove(&(AttrBuffFG[DestPtr]),&(AttrBuffFG[SrcPtr]),NumOfColumns);
1831     memmove(&(AttrBuffBG[DestPtr]),&(AttrBuffBG[SrcPtr]),NumOfColumns);
1832     SrcPtr = NextLinePtr(SrcPtr);
1833     DestPtr = NextLinePtr(DestPtr);
1834     }
1835     }
1836     else
1837     n = CursorBottom-CursorTop+1;
1838     for (i = CursorBottom+1-n ; i<=CursorBottom; i++) {
1839     memset(&(CodeBuff[DestPtr]),0x20,NumOfColumns);
1840     memset(&(AttrBuff[DestPtr]),AttrDefault,NumOfColumns);
1841     memset(&(AttrBuff2[DestPtr]),CurCharAttr.Attr2,NumOfColumns);
1842     memset(&(AttrBuffFG[DestPtr]),CurCharAttr.Fore,NumOfColumns);
1843     memset(&(AttrBuffBG[DestPtr]),CurCharAttr.Back,NumOfColumns);
1844     DestPtr = NextLinePtr(DestPtr);
1845     }
1846     DispScrollNLines(CursorTop,CursorBottom,n);
1847     }
1848     }
1849     }
1850    
1851     void BuffRegionScrollDownNLines(int n) {
1852     int i;
1853     LONG SrcPtr, DestPtr;
1854    
1855     if (n<1) {
1856     return;
1857     }
1858     UpdateStr();
1859    
1860     DestPtr = GetLinePtr(PageStart+CursorBottom);
1861     if (n < CursorBottom-CursorTop+1) {
1862     SrcPtr = GetLinePtr(PageStart+CursorBottom-n);
1863     for (i=CursorBottom-n ; i>=CursorTop ; i--) {
1864     memmove(&(CodeBuff[DestPtr]),&(CodeBuff[SrcPtr]),NumOfColumns);
1865     memmove(&(AttrBuff[DestPtr]),&(AttrBuff[SrcPtr]),NumOfColumns);
1866     memmove(&(AttrBuff2[DestPtr]),&(AttrBuff2[SrcPtr]),NumOfColumns);
1867     memmove(&(AttrBuffFG[DestPtr]),&(AttrBuffFG[SrcPtr]),NumOfColumns);
1868     memmove(&(AttrBuffBG[DestPtr]),&(AttrBuffBG[SrcPtr]),NumOfColumns);
1869     SrcPtr = PrevLinePtr(SrcPtr);
1870     DestPtr = PrevLinePtr(DestPtr);
1871     }
1872     }
1873     else {
1874     n = CursorBottom - CursorTop + 1;
1875     }
1876     for (i = CursorTop+n-1; i>=CursorTop; i--) {
1877     memset(&(CodeBuff[DestPtr]),0x20,NumOfColumns);
1878     memset(&(AttrBuff[DestPtr]),AttrDefault,NumOfColumns);
1879     memset(&(AttrBuff2[DestPtr]),CurCharAttr.Attr2,NumOfColumns);
1880     memset(&(AttrBuffFG[DestPtr]),CurCharAttr.Fore,NumOfColumns);
1881     memset(&(AttrBuffBG[DestPtr]),CurCharAttr.Back,NumOfColumns);
1882     DestPtr = PrevLinePtr(DestPtr);
1883     }
1884    
1885     DispScrollNLines(CursorTop,CursorBottom,-n);
1886     }
1887    
1888     void BuffClearScreen()
1889     { // clear screen
1890     if ((StatusLine>0) && (CursorY==NumOfLines-1))
1891     BuffScrollNLines(1); /* clear status line */
1892     else { /* clear main screen */
1893     UpdateStr();
1894     BuffScroll(NumOfLines-StatusLine,NumOfLines-1-StatusLine);
1895     DispScrollNLines(WinOrgY,NumOfLines-1-StatusLine,NumOfLines-StatusLine);
1896     }
1897     }
1898    
1899     void BuffUpdateScroll()
1900     // Updates scrolling
1901     {
1902     UpdateStr();
1903     DispUpdateScroll();
1904     }
1905    
1906     void CursorUpWithScroll()
1907     {
1908     if ((0<CursorY) && (CursorY<CursorTop) ||
1909     (CursorTop<CursorY))
1910     MoveCursor(CursorX,CursorY-1);
1911     else if (CursorY==CursorTop)
1912     ScrollUp1Line();
1913     }
1914    
1915     // called by BuffDblClk
1916     // check if a character is the word delimiter
1917     BOOL IsDelimiter(LONG Line, int CharPtr)
1918     {
1919     if ((AttrBuff[Line+CharPtr] & AttrKanji) !=0)
1920     return (ts.DelimDBCS!=0);
1921     return
1922     (strchr(ts.DelimList,CodeBuff[Line+CharPtr])!=NULL);
1923     }
1924    
1925     void GetMinMax(int i1, int i2, int i3,
1926     int *min, int *max)
1927     {
1928     if (i1<i2)
1929     {
1930     *min = i1;
1931     *max = i2;
1932     }
1933     else {
1934     *min = i2;
1935     *max = i1;
1936     }
1937     if (i3<*min)
1938     *min = i3;
1939     if (i3>*max)
1940     *max = i3;
1941     }
1942    
1943     /* start - ishizaki */
1944     static void invokeBrowser(LONG ptr)
1945     {
1946     #ifdef URL_EMPHASIS
1947     LONG i, start, end;
1948     char url[1024];
1949     char *uptr, ch;
1950    
1951     start = ptr;
1952     while (AttrBuff[start] & AttrURL) start--;
1953     start++;
1954    
1955     end = ptr;
1956     while (AttrBuff[end] & AttrURL) end++;
1957     end--;
1958    
1959     if (start + 1024 <= end) end = start + 1023;
1960     uptr = url;
1961     for (i = 0; i < end - start + 1; i++) {
1962     ch = CodeBuff[start + i];
1963     if ((start + i) % NumOfColumns == NumOfColumns - 1
1964     && ch == '\\') {
1965     // Emacs対応。行末に \ が来ている場合は、次の行に続くという意味で emacs が
1966     // 自動で挿入する文字なので、URLには含めないようにする。
1967     // (2007.8.7 yutaka)
1968    
1969     } else {
1970     *uptr++ = ch;
1971     }
1972     }
1973     *uptr = '\0';
1974     ShellExecute(NULL, NULL, url, NULL, NULL,SW_SHOWNORMAL);
1975     #endif
1976     }
1977     /* end - ishizaki */
1978    
1979     void ChangeSelectRegion()
1980     {
1981     POINT TempStart, TempEnd;
1982     int j, IStart, IEnd;
1983     BOOL Caret;
1984    
1985     if ((SelectEndOld.x==SelectEnd.x) &&
1986     (SelectEndOld.y==SelectEnd.y)) return;
1987    
1988     if (BoxSelect)
1989     {
1990     GetMinMax(SelectStart.x,SelectEndOld.x,SelectEnd.x,
1991     (int *)&TempStart.x,(int *)&TempEnd.x);
1992     GetMinMax(SelectStart.y,SelectEndOld.y,SelectEnd.y,
1993     (int *)&TempStart.y,(int *)&TempEnd.y);
1994     TempEnd.x--;
1995     Caret = IsCaretOn();
1996     if (Caret) CaretOff();
1997     DispInitDC();
1998     BuffUpdateRect(TempStart.x,TempStart.y-PageStart,
1999     TempEnd.x,TempEnd.y-PageStart);
2000     DispReleaseDC();
2001     if (Caret) CaretOn();
2002     SelectEndOld = SelectEnd;
2003     return;
2004     }
2005    
2006     if ((SelectEndOld.y < SelectEnd.y) ||
2007     (SelectEndOld.y==SelectEnd.y) &&
2008     (SelectEndOld.x<=SelectEnd.x))
2009     {
2010     TempStart = SelectEndOld;
2011     TempEnd.x = SelectEnd.x-1;
2012     TempEnd.y = SelectEnd.y;
2013     }
2014     else {
2015     TempStart = SelectEnd;
2016     TempEnd.x = SelectEndOld.x-1;
2017     TempEnd.y = SelectEndOld.y;
2018     }
2019     if (TempEnd.x < 0)
2020     {
2021     TempEnd.x = NumOfColumns - 1;
2022     TempEnd.y--;
2023     }
2024    
2025     Caret = IsCaretOn();
2026     if (Caret) CaretOff();
2027     for (j = TempStart.y ; j <= TempEnd.y ; j++)
2028     {
2029     IStart = 0;
2030     IEnd = NumOfColumns-1;
2031     if (j==TempStart.y) IStart = TempStart.x;
2032     if (j==TempEnd.y) IEnd = TempEnd.x;
2033    
2034     if ((IEnd>=IStart) && (j >= PageStart+WinOrgY) &&
2035     (j < PageStart+WinOrgY+WinHeight))
2036     {
2037     DispInitDC();
2038     BuffUpdateRect(IStart,j-PageStart,IEnd,j-PageStart);
2039     DispReleaseDC();
2040     }
2041     }
2042     if (Caret) CaretOn();
2043    
2044     SelectEndOld = SelectEnd;
2045     }
2046    
2047     BOOL BuffUrlDblClk(int Xw, int Yw)
2048     {
2049     int X, Y;
2050     LONG TmpPtr;
2051     BOOL url_invoked = FALSE;
2052    
2053     if (! ts.EnableClickableUrl) {
2054     return FALSE;
2055     }
2056    
2057     CaretOff();
2058    
2059     DispConvWinToScreen(Xw,Yw,&X,&Y,NULL);
2060     Y = Y + PageStart;
2061     if ((Y<0) || (Y>=BuffEnd)) return 0;
2062     if (X<0) X = 0;
2063     if (X>=NumOfColumns) X = NumOfColumns-1;
2064    
2065     if ((Y>=0) && (Y<BuffEnd)) {
2066     LockBuffer();
2067     TmpPtr = GetLinePtr(Y);
2068     /* start - ishizaki */
2069     if (AttrBuff[TmpPtr+X] & AttrURL) {
2070     BoxSelect = FALSE;
2071     SelectEnd = SelectStart;
2072     ChangeSelectRegion();
2073    
2074     url_invoked = TRUE;
2075     invokeBrowser(TmpPtr+X);
2076    
2077     SelectStart.x = 0;
2078     SelectStart.y = 0;
2079     SelectEnd.x = 0;
2080     SelectEnd.y = 0;
2081     SelectEndOld.x = 0;
2082     SelectEndOld.y = 0;
2083     Selected = FALSE;
2084     }
2085     UnlockBuffer();
2086     }
2087     return url_invoked;
2088     }
2089    
2090     void BuffDblClk(int Xw, int Yw)
2091     // Select a word at (Xw, Yw) by mouse double click
2092     // Xw: horizontal position in window coordinate (pixels)
2093     // Yw: vertical
2094     {
2095     int X, Y, YStart, YEnd;
2096     int IStart, IEnd, i;
2097     LONG TmpPtr;
2098     BYTE b;
2099     BOOL DBCS;
2100    
2101     CaretOff();
2102    
2103     DispConvWinToScreen(Xw,Yw,&X,&Y,NULL);
2104     Y = Y + PageStart;
2105     if ((Y<0) || (Y>=BuffEnd)) return;
2106     if (X<0) X = 0;
2107     if (X>=NumOfColumns) X = NumOfColumns-1;
2108    
2109     BoxSelect = FALSE;
2110     LockBuffer();
2111     SelectEnd = SelectStart;
2112     ChangeSelectRegion();
2113    
2114     if ((Y>=0) && (Y<BuffEnd))
2115     {
2116     TmpPtr = GetLinePtr(Y);
2117    
2118     IStart = X;
2119     IStart = LeftHalfOfDBCS(TmpPtr,IStart);
2120     IEnd = IStart;
2121     YStart = YEnd = Y;
2122    
2123     if (IsDelimiter(TmpPtr,IStart))
2124     {
2125     b = CodeBuff[TmpPtr+IStart];
2126     DBCS = (AttrBuff[TmpPtr+IStart] & AttrKanji) != 0;
2127     while ((b==CodeBuff[TmpPtr+IStart]) ||
2128     DBCS &&
2129     ((AttrBuff[TmpPtr+IStart] & AttrKanji)!=0)) {
2130     MoveCharPtr(TmpPtr,&IStart,-1); // move left
2131     if (ts.EnableContinuedLineCopy) {
2132     if (IStart<=0) {
2133     // 左端の場合
2134     if (YStart>0 && AttrBuff[TmpPtr] & AttrLineContinued) {
2135     // 前の行に移動する
2136     YStart--;
2137     TmpPtr = GetLinePtr(YStart);
2138     IStart = NumOfColumns;
2139     }
2140     else {
2141     break;
2142     }
2143     }
2144     }
2145     else {
2146     if (IStart<=0) {
2147     // 左端の場合は終わり
2148     break;
2149     }
2150     }
2151     }
2152     if ((b!=CodeBuff[TmpPtr+IStart]) &&
2153     ! (DBCS &&
2154     ((AttrBuff[TmpPtr+IStart] & AttrKanji)!=0))) {
2155     // 最終位置が Delimiter でない場合にはひとつ右にずらす
2156     if (ts.EnableContinuedLineCopy && IStart == NumOfColumns-1) {
2157     // 右端の場合には次の行へ移動する
2158     YStart++;
2159     TmpPtr = GetLinePtr(YStart);
2160     IStart = 0;
2161     }
2162     else {
2163     MoveCharPtr(TmpPtr,&IStart,1);
2164     }
2165     }
2166    
2167     // 行が移動しているかもしれないので、クリックした行を取り直す
2168     TmpPtr = GetLinePtr(YEnd);
2169     i = 1;
2170     while (((b==CodeBuff[TmpPtr+IEnd]) ||
2171     DBCS &&
2172     ((AttrBuff[TmpPtr+IEnd] & AttrKanji)!=0))) {
2173     i = MoveCharPtr(TmpPtr,&IEnd,1); // move right
2174     if (ts.EnableContinuedLineCopy) {
2175     if (i==0) {
2176     // 右端の場合
2177     if (YEnd<BuffEnd &&
2178     AttrBuff[TmpPtr+IEnd+1+DBCS] & AttrLineContinued) {
2179     // 次の行に移動する
2180     YEnd++;
2181     TmpPtr = GetLinePtr(YEnd);
2182     IEnd = 0;
2183     }
2184     else {
2185     break;
2186     }
2187     }
2188     }
2189     else {
2190     if (i==0) {
2191     // 右端の場合は終わり
2192     break;
2193     }
2194     }
2195     }
2196     }
2197     else {
2198     while (! IsDelimiter(TmpPtr,IStart)) {
2199     MoveCharPtr(TmpPtr,&IStart,-1); // move left
2200     if (ts.EnableContinuedLineCopy) {
2201     if (IStart<=0) {
2202     // 左端の場合
2203     if (YStart>0 && AttrBuff[TmpPtr] & AttrLineContinued) {
2204     // 前の行に移動する
2205     YStart--;
2206     TmpPtr = GetLinePtr(YStart);
2207     IStart = NumOfColumns;
2208     }
2209     else {
2210     break;
2211     }
2212     }
2213     }
2214     else {
2215     if (IStart<=0) {
2216     // 左端の場合は終わり
2217     break;
2218     }
2219     }
2220     }
2221     if (IsDelimiter(TmpPtr,IStart)) {
2222     // 最終位置が Delimiter の場合にはひとつ右にずらす
2223     if (ts.EnableContinuedLineCopy && IStart == NumOfColumns-1) {
2224     // 右端の場合には次の行へ移動する
2225     YStart++;
2226     TmpPtr = GetLinePtr(YStart);
2227     IStart = 0;
2228     }
2229     else {
2230     MoveCharPtr(TmpPtr,&IStart,1);
2231     }
2232     }
2233    
2234     // 行が移動しているかもしれないので、クリックした行を取り直す
2235     TmpPtr = GetLinePtr(YEnd);
2236     i = 1;
2237     while (! IsDelimiter(TmpPtr,IEnd)) {
2238     i = MoveCharPtr(TmpPtr,&IEnd,1); // move right
2239     if (ts.EnableContinuedLineCopy) {
2240     if (i==0) {
2241     // 右端の場合
2242     if (YEnd<BuffEnd && AttrBuff[TmpPtr+IEnd+1] & AttrLineContinued) {
2243     // 次の行に移動する
2244     YEnd++;
2245     TmpPtr = GetLinePtr(YEnd);
2246     IEnd = 0;
2247     }
2248     else {
2249     break;
2250     }
2251     }
2252     }
2253     else {
2254     if (i==0) {
2255     // 右端の場合は終わり
2256     break;
2257     }
2258     }
2259     }
2260     }
2261     if (ts.EnableContinuedLineCopy) {
2262     if (IEnd == 0) {
2263     // 左端の場合には前の行へ移動する
2264     YEnd--;
2265     IEnd = NumOfColumns;
2266     }
2267     else if (i==0) {
2268     IEnd = NumOfColumns;
2269     }
2270     }
2271     else {
2272     if (i==0)
2273     IEnd = NumOfColumns;
2274     }
2275    
2276     SelectStart.x = IStart;
2277     SelectStart.y = YStart;
2278     SelectEnd.x = IEnd;
2279     SelectEnd.y = YEnd;
2280     SelectEndOld = SelectStart;
2281     DblClkStart = SelectStart;
2282     DblClkEnd = SelectEnd;
2283     Selected = TRUE;
2284     ChangeSelectRegion();
2285     }
2286     UnlockBuffer();
2287     return;
2288     }
2289    
2290     void BuffTplClk(int Yw)
2291     // Select a line at Yw by mouse tripple click
2292     // Yw: vertical clicked position
2293     // in window coordinate (pixels)
2294     {
2295     int Y;
2296    
2297     CaretOff();
2298    
2299     DispConvWinToScreen(0,Yw,NULL,&Y,NULL);
2300     Y = Y + PageStart;
2301     if ((Y<0) || (Y>=BuffEnd)) return;
2302    
2303     LockBuffer();
2304     SelectEnd = SelectStart;
2305     ChangeSelectRegion();
2306     SelectStart.x = 0;
2307     SelectStart.y = Y;
2308     SelectEnd.x = NumOfColumns;
2309     SelectEnd.y = Y;
2310     SelectEndOld = SelectStart;
2311     DblClkStart = SelectStart;
2312     DblClkEnd = SelectEnd;
2313     Selected = TRUE;
2314     ChangeSelectRegion();
2315     UnlockBuffer();
2316     }
2317    
2318    
2319     // The block of the text between old and new cursor positions is being selected.
2320     // This function enables to select several pages of output from Tera Term window.
2321     // add (2005.5.15 yutaka)
2322     void BuffSeveralPagesSelect(int Xw, int Yw)
2323     // Start text selection by mouse button down
2324     // Xw: horizontal position in window coordinate (pixels)
2325     // Yw: vertical
2326     {
2327     int X, Y;
2328     BOOL Right;
2329    
2330     DispConvWinToScreen(Xw,Yw, &X,&Y,&Right);
2331     Y = Y + PageStart;
2332     if ((Y<0) || (Y>=BuffEnd)) return;
2333     if (X<0) X = 0;
2334     if (X>=NumOfColumns) X = NumOfColumns-1;
2335    
2336     SelectEnd.x = X;
2337     SelectEnd.y = Y;
2338     //BoxSelect = FALSE; // box selecting disabled
2339     SeveralPageSelect = TRUE;
2340     }
2341    
2342     void BuffStartSelect(int Xw, int Yw, BOOL Box)
2343     // Start text selection by mouse button down
2344     // Xw: horizontal position in window coordinate (pixels)
2345     // Yw: vertical
2346     // Box: Box selection if TRUE
2347     {
2348     int X, Y;
2349     BOOL Right;
2350     LONG TmpPtr;
2351    
2352     DispConvWinToScreen(Xw,Yw, &X,&Y,&Right);
2353     Y = Y + PageStart;
2354     if ((Y<0) || (Y>=BuffEnd)) return;
2355     if (X<0) X = 0;
2356     if (X>=NumOfColumns) X = NumOfColumns-1;
2357    
2358     SelectEndOld = SelectEnd;
2359     SelectEnd = SelectStart;
2360    
2361     LockBuffer();
2362     ChangeSelectRegion();
2363     UnlockBuffer();
2364    
2365     SelectStart.x = X;
2366     SelectStart.y = Y;
2367     if (SelectStart.x<0) SelectStart.x = 0;
2368     if (SelectStart.x > NumOfColumns)
2369     SelectStart.x = NumOfColumns;
2370     if (SelectStart.y < 0) SelectStart.y = 0;
2371     if (SelectStart.y >= BuffEnd)
2372     SelectStart.y = BuffEnd - 1;
2373    
2374     TmpPtr = GetLinePtr(SelectStart.y);
2375     // check if the cursor is on the right half of a character
2376     if ((SelectStart.x>0) &&
2377     ((AttrBuff[TmpPtr+SelectStart.x-1] & AttrKanji) != 0) ||
2378     ((AttrBuff[TmpPtr+SelectStart.x] & AttrKanji) == 0) &&
2379     Right) SelectStart.x++;
2380    
2381     SelectEnd = SelectStart;
2382     SelectEndOld = SelectEnd;
2383     CaretOff();
2384     Selected = TRUE;
2385     BoxSelect = Box;
2386     }
2387    
2388     void BuffChangeSelect(int Xw, int Yw, int NClick)
2389     // Change selection region by mouse move
2390     // Xw: horizontal position of the mouse cursor
2391     // in window coordinate
2392     // Yw: vertical
2393     {
2394     int X, Y;
2395     BOOL Right;
2396     LONG TmpPtr;
2397     int i;
2398     BYTE b;
2399     BOOL DBCS;
2400    
2401     DispConvWinToScreen(Xw,Yw,&X,&Y,&Right);
2402     Y = Y + PageStart;
2403    
2404     if (X<0) X = 0;
2405     if (X > NumOfColumns)
2406     X = NumOfColumns;
2407     if (Y < 0) Y = 0;
2408     if (Y >= BuffEnd)
2409     Y = BuffEnd - 1;
2410    
2411     TmpPtr = GetLinePtr(Y);
2412     LockBuffer();
2413     // check if the cursor is on the right half of a character
2414     if ((X>0) &&
2415     ((AttrBuff[TmpPtr+X-1] & AttrKanji) != 0) ||
2416     (X<NumOfColumns) &&
2417     ((AttrBuff[TmpPtr+X] & AttrKanji) == 0) &&
2418     Right) X++;
2419    
2420     if (X > NumOfColumns)
2421     X = NumOfColumns;
2422    
2423     // check URL string on mouse over(2005/4/3 yutaka)
2424     if (NClick == 0) {
2425     extern void SetMouseCursor(char *cursor);
2426    
2427     if ((AttrBuff[TmpPtr+X] & AttrURL)) {
2428     SetMouseCursor("HAND");
2429    
2430     } else {
2431     SetMouseCursor(ts.MouseCursorName);
2432     //SetCursor(LoadCursor(NULL, IDC_IBEAM));
2433    
2434     }
2435    
2436     UnlockBuffer();
2437     return;
2438     }
2439    
2440     #if 0
2441     /* start - ishizaki */
2442     if (ts.EnableClickableUrl && (NClick == 2) && (AttrBuff[TmpPtr+X] & AttrURL)) {
2443     invokeBrowser(TmpPtr+X);
2444    
2445     SelectStart.x = 0;
2446     SelectStart.y = 0;