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 2551 - (hide annotations) (download) (as text)
Thu Jul 3 20:14:09 2008 UTC (15 years, 9 months ago) by doda
Original Path: teraterm/trunk/teraterm/buffer.c
File MIME type: text/x-csrc
File size: 73123 byte(s)
CBT制御シーケンスに対応。

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