Develop and Download Open Source Software

Browse Subversion Repository

Annotation of /trunk/teraterm/teraterm/buffer.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3686 - (hide annotations) (download) (as text)
Mon Nov 16 17:48:29 2009 UTC (14 years, 4 months ago) by doda
File MIME type: text/x-csrc
File size: 77065 byte(s)
Alternate Screen Bufferのサポートに向けたコード整理。

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