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