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 10345 - (hide annotations) (download) (as text)
Wed Nov 2 13:43:19 2022 UTC (17 months, 1 week ago) by zmatsuo
File MIME type: text/x-csrc
File size: 138130 byte(s)
TERATERM.INI の UnknownUnicodeCharacterAsWide を削除

- 不明な文字幅がなくなったため不要となった
- tttypes.UnknownUnicodeCharaAsWide を削除
- 関連ドキュメントを修正
- 表示できない文字の場合は '?' が文字のセル幅表示
  - ANSI API(Additional setting - Font)で描画時
- エスケープシーケンスによる印字はANSIで行う
  - "\x1b[5i" から
  - "\x1b[4i" まで
1 doda 6806 /*
2     * Copyright (C) 1994-1998 T. Teranishi
3 nmaya 9048 * (C) 2004- TeraTerm Project
4 doda 6806 * All rights reserved.
5     *
6 doda 6841 * Redistribution and use in source and binary forms, with or without
7     * modification, are permitted provided that the following conditions
8     * are met:
9 doda 6806 *
10 doda 6841 * 1. Redistributions of source code must retain the above copyright
11     * notice, this list of conditions and the following disclaimer.
12     * 2. Redistributions in binary form must reproduce the above copyright
13     * notice, this list of conditions and the following disclaimer in the
14     * documentation and/or other materials provided with the distribution.
15     * 3. The name of the author may not be used to endorse or promote products
16     * derived from this software without specific prior written permission.
17 doda 6806 *
18 doda 6841 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
19     * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20     * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21     * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22     * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23     * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24     * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25     * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26     * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27     * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 doda 6806 */
29 maya 3227
30     /* TERATERM.EXE, scroll buffer routines */
31    
32     #include "teraterm.h"
33     #include <string.h>
34 yutakapon 4707 #include <stdio.h>
35 doda 8445 #include <windows.h>
36     #define _CRTDBG_MAP_ALLOC
37     #include <crtdbg.h>
38     #include <assert.h>
39 maya 3227
40 doda 8445 #include "tttypes.h"
41 maya 3227 #include "ttwinman.h"
42     #include "teraprn.h"
43     #include "vtdisp.h"
44     #include "telnet.h"
45     #include "ttplug.h" /* TTPLUG */
46 doda 8445 #include "codeconv.h"
47     #include "unicode.h"
48 maya 3227 #include "buffer.h"
49 zmatsuo 8584 #include "asprintf.h"
50 zmatsuo 8825 #include "ttcstd.h"
51 maya 3227
52 doda 8445 // �o�b�t�@�������p1������������
53     typedef struct {
54     char32_t u32;
55     char32_t u32_last;
56 zmatsuo 8766 char WidthProperty; // 'W' or 'F' or 'H' or 'A' or 'n'(Narrow) or 'N'(Neutual) (����������)
57 zmatsuo 10308 char cell; // ������cell�� 1/2/3+=���p,�S�p,3����
58     // 2�����������A����������������padding��cell-1������
59 doda 8445 char Padding; // TRUE = �S�p�������l���� or �s�����l����
60     char Emoji; // TRUE = �G����
61 zmatsuo 8585 unsigned char CombinationCharCount16; // charactor count
62     unsigned char CombinationCharSize16; // buffer size
63     unsigned char CombinationCharCount32;
64     unsigned char CombinationCharSize32;
65 doda 8445 wchar_t *pCombinationChars16;
66     char32_t *pCombinationChars32;
67     wchar_t wc2[2];
68 zmatsuo 8741 unsigned char fg;
69     unsigned char bg;
70 zmatsuo 8742 unsigned char attr;
71     unsigned char attr2;
72 zmatsuo 8744 unsigned short ansi_char;
73 doda 8445 } buff_char_t;
74    
75 maya 3227 #define BuffXMax TermWidthMax
76     //#define BuffYMax 100000
77     //#define BuffSizeMax 8000000
78     // �X�N���[���o�b�t�@�����������g�� (2004.11.28 yutaka)
79     #define BuffYMax 500000
80     #define BuffSizeMax (BuffYMax * 80)
81    
82 zmatsuo 9404 // 1���������������������T�C�Y
83     #define MAX_CHAR_SIZE 100
84    
85 maya 3227 // status line
86 doda 6435 int StatusLine; //0: none 1: shown
87 doda 5324 /* top, bottom, left & right margin */
88     int CursorTop, CursorBottom, CursorLeftM, CursorRightM;
89 doda 8400 BOOL Selected, Selecting;
90 maya 3227 BOOL Wrap;
91    
92     static WORD TabStops[256];
93     static int NTabStops;
94    
95     static WORD BuffLock = 0;
96    
97 zmatsuo 8739 static buff_char_t *CodeBuffW;
98 maya 3227 static LONG LinePtr;
99     static LONG BufferSize;
100     static int NumOfLinesInBuff;
101     static int BuffStartAbs, BuffEndAbs;
102 doda 8400 static POINT SelectStart, SelectStartTmp, SelectEnd, SelectEndOld;
103     static DWORD SelectStartTime;
104 maya 3227 static BOOL BoxSelect;
105     static POINT DblClkStart, DblClkEnd;
106    
107 doda 8445 // �`��
108     static int StrChangeStart; // �`���J�n X (Y=CursorY)
109     static int StrChangeCount; // �`���L�����N�^��(���p�P��),0�������`����������������
110 zmatsuo 8748 static BOOL UseUnicodeApi;
111 maya 3227
112     static BOOL SeveralPageSelect; // add (2005.5.15 yutaka)
113    
114     static TCharAttr CurCharAttr;
115    
116 doda 8445 static char *SaveBuff = NULL;
117     static int SaveBuffX;
118     static int SaveBuffY;
119 doda 3743
120 zmatsuo 8770 // ANSI�\���p����������������CodePage
121     static int CodePage = 932;
122    
123 doda 8445 static void BuffDrawLineI(int DrawX, int DrawY, int SY, int IStart, int IEnd);
124 zmatsuo 9040 static void BuffDrawLineIPrn(int SY, int IStart, int IEnd);
125 doda 8445
126     static void BuffSetChar2(buff_char_t *buff, char32_t u32, char property, BOOL half_width, char emoji)
127 maya 3227 {
128 doda 8445 size_t wstr_len;
129     buff_char_t *p = buff;
130     if (p->pCombinationChars16 != NULL) {
131     free(p->pCombinationChars16);
132     p->pCombinationChars16 = NULL;
133     }
134     p->CombinationCharCount16 = 0;
135     p->CombinationCharSize16 = 0;
136     if (p->pCombinationChars32 != NULL) {
137     free(p->pCombinationChars32);
138     p->pCombinationChars32 = NULL;
139     }
140     p->CombinationCharCount32 = 0;
141     p->CombinationCharSize32 = 0;
142     p->WidthProperty = property;
143 zmatsuo 10308 p->cell = half_width ? 1 : 2;
144 doda 8445 p->u32 = u32;
145     p->u32_last = u32;
146     p->Padding = FALSE;
147     p->Emoji = emoji;
148 zmatsuo 8741 p->fg = AttrDefaultFG;
149     p->bg = AttrDefaultBG;
150 doda 8445
151     //
152     wstr_len = UTF32ToUTF16(u32, &p->wc2[0], 2);
153     switch (wstr_len) {
154     case 0:
155     default:
156     p->wc2[0] = 0;
157     p->wc2[1] = 0;
158     break;
159     case 1:
160     p->wc2[1] = 0;
161     break;
162     case 2:
163     break;
164     }
165 zmatsuo 8745
166     if (u32 < 0x80) {
167     p->ansi_char = (unsigned short)u32;
168     }
169     else {
170 zmatsuo 8770 if (u32 == 0x203e && CodePage == 932) {
171     // U+203e OVERLINE ��������
172     // U+203e��0x7e'~'������
173     //p->ansi_char = 0x7e7e;
174     p->ansi_char = 0x7e;
175     }
176     else {
177     char strA[4];
178     size_t lenA = UTF32ToMBCP(u32, CodePage, strA, sizeof(strA));
179     switch (lenA) {
180 zmatsuo 8745 case 0:
181     default:
182 zmatsuo 10345 p->ansi_char = '?';
183 zmatsuo 8745 break;
184     case 1:
185     p->ansi_char = (unsigned char)strA[0];
186     break;
187     case 2:
188     p->ansi_char = (unsigned char)strA[1] | ((unsigned char)strA[0] << 8);
189     break;
190 zmatsuo 8770 }
191 zmatsuo 8745 }
192     }
193 doda 8445 }
194    
195 zmatsuo 8742 static void BuffSetChar4(buff_char_t *buff, char32_t u32, unsigned char fg, unsigned char bg, unsigned char attr, unsigned char attr2, char property)
196     {
197     buff_char_t *p = buff;
198     BuffSetChar2(p, u32, property, TRUE, FALSE);
199     p->fg = fg;
200     p->bg = bg;
201     p->attr = attr;
202     p->attr2 = attr2;
203     }
204    
205 doda 8445 static void BuffSetChar(buff_char_t *buff, char32_t u32, char property)
206     {
207     BuffSetChar2(buff, u32, property, TRUE, FALSE);
208     }
209    
210     /**
211     * �����������A�R���r�l�[�V����
212     */
213     static void BuffAddChar(buff_char_t *buff, char32_t u32)
214     {
215     buff_char_t *p = buff;
216     assert(p->u32 != 0);
217     // �������������������g������
218     if (p->CombinationCharSize16 < p->CombinationCharCount16 + 2) {
219     size_t new_size = p->CombinationCharSize16;
220     new_size = new_size == 0 ? 5 : new_size * 2;
221 zmatsuo 9404 if (new_size > MAX_CHAR_SIZE) {
222     new_size = MAX_CHAR_SIZE;
223     }
224     if (p->CombinationCharSize16 != new_size) {
225     p->pCombinationChars16 = realloc(p->pCombinationChars16, sizeof(wchar_t) * new_size);
226     p->CombinationCharSize16 = (char)new_size;
227     }
228 doda 8445 }
229     if (p->CombinationCharSize32 < p->CombinationCharCount32 + 2) {
230     size_t new_size = p->CombinationCharSize32;
231     new_size = new_size == 0 ? 5 : new_size * 2;
232 zmatsuo 9404 if (new_size > MAX_CHAR_SIZE) {
233     new_size = MAX_CHAR_SIZE;
234     }
235     if (p->CombinationCharSize32 != new_size) {
236     p->pCombinationChars32 = realloc(p->pCombinationChars32, sizeof(char32_t) * new_size);
237     p->CombinationCharSize32 = (char)new_size;
238     }
239 doda 8445 }
240    
241     // UTF-32
242 zmatsuo 9404 if (p->CombinationCharCount32 < p->CombinationCharSize32) {
243     p->u32_last = u32;
244     p->pCombinationChars32[(size_t)p->CombinationCharCount32] = u32;
245     p->CombinationCharCount32++;
246     }
247 doda 8445
248     // UTF-16
249 zmatsuo 9404 if (p->CombinationCharCount16 < p->CombinationCharSize16) {
250     wchar_t u16_str[2];
251     size_t wlen = UTF32ToUTF16(u32, &u16_str[0], 2);
252     if (p->CombinationCharCount16 + wlen <= p->CombinationCharSize16) {
253     size_t i = (size_t)p->CombinationCharCount16;
254     p->pCombinationChars16[i] = u16_str[0];
255     if (wlen == 2) {
256     i++;
257     p->pCombinationChars16[i] = u16_str[1];
258     }
259 zmatsuo 9839 p->CombinationCharCount16 += (unsigned char)wlen;
260 zmatsuo 9404 }
261 doda 8445 }
262     }
263    
264 zmatsuo 8742 // TODO: ���[�N����
265 doda 8445 static void memcpyW(buff_char_t *dest, const buff_char_t *src, size_t count)
266     {
267     size_t i;
268     memcpy(dest, src, count * sizeof(buff_char_t));
269     for (i=0; i<count; i++) {
270     buff_char_t *p = &dest[i];
271     size_t size = p->CombinationCharSize16;
272     if (size > 0) {
273     wchar_t *new_buf = malloc(sizeof(wchar_t) * size);
274     memcpy(new_buf, p->pCombinationChars16, sizeof(wchar_t) * size);
275     p->pCombinationChars16 = new_buf;
276     }
277     size = p->CombinationCharSize32;
278     if (size > 0) {
279     char32_t *new_buf = malloc(sizeof(char32_t) * size);
280     memcpy(new_buf, p->pCombinationChars32, sizeof(char32_t) * size);
281     p->pCombinationChars32 = new_buf;
282     }
283     }
284     }
285    
286 zmatsuo 8742 static void memsetW(buff_char_t *dest, wchar_t ch, unsigned char fg, unsigned char bg, unsigned char attr, unsigned char attr2, size_t count)
287 doda 8445 {
288     size_t i;
289     for (i=0; i<count; i++) {
290     BuffSetChar(dest, ch, 'H');
291 zmatsuo 8741 dest->fg = fg;
292     dest->bg = bg;
293 zmatsuo 8742 dest->attr = attr;
294     dest->attr2 = attr2;
295 doda 8445 dest++;
296     }
297     }
298    
299     static void memmoveW(buff_char_t *dest, const buff_char_t *src, size_t count)
300     {
301     memmove(dest, src, count * sizeof(buff_char_t));
302     }
303    
304     static BOOL IsBuffPadding(const buff_char_t *b)
305     {
306     if (b->Padding == TRUE)
307     return TRUE;
308     if (b->u32 == 0)
309     return TRUE;
310     return FALSE;
311     }
312    
313     static BOOL IsBuffFullWidth(const buff_char_t *b)
314     {
315 zmatsuo 10308 if (b->cell != 1)
316 doda 8445 return TRUE;
317     return FALSE;
318     }
319    
320     static LONG GetLinePtr(int Line)
321     {
322 maya 3393 LONG Ptr;
323 maya 3227
324 maya 3393 Ptr = (LONG)(BuffStartAbs + Line) * (LONG)(NumOfColumns);
325     while (Ptr>=BufferSize) {
326     Ptr = Ptr - BufferSize;
327     }
328     return Ptr;
329 maya 3227 }
330    
331 doda 8445 static LONG NextLinePtr(LONG Ptr)
332 maya 3227 {
333 maya 3393 Ptr = Ptr + (LONG)NumOfColumns;
334     if (Ptr >= BufferSize) {
335     Ptr = Ptr - BufferSize;
336     }
337     return Ptr;
338 maya 3227 }
339    
340 doda 8445 static LONG PrevLinePtr(LONG Ptr)
341 maya 3227 {
342 maya 3393 Ptr = Ptr - (LONG)NumOfColumns;
343     if (Ptr < 0) {
344     Ptr = Ptr + BufferSize;
345     }
346     return Ptr;
347 maya 3227 }
348    
349 zmatsuo 8744 /**
350     * �|�C���^�����u���� x,y ��������
351     */
352     static void GetPosFromPtr(const buff_char_t *b, int *bx, int *by)
353     {
354     size_t index = b - CodeBuffW;
355     int x = (int)(index % NumOfColumns);
356     int y = (int)(index / NumOfColumns);
357     if (y >= BuffStartAbs) {
358     y -= BuffStartAbs;
359     }
360     else {
361 zmatsuo 9840 y = y - BuffStartAbs + NumOfLinesInBuff;
362 zmatsuo 8744 }
363     *bx = x;
364     *by = y;
365     }
366    
367 doda 8445 static BOOL ChangeBuffer(int Nx, int Ny)
368 maya 3227 {
369 maya 3393 LONG NewSize;
370     int NxCopy, NyCopy, i;
371     LONG SrcPtr, DestPtr;
372     WORD LockOld;
373 doda 8445 buff_char_t *CodeDestW;
374 maya 3227
375 maya 3393 if (Nx > BuffXMax) {
376     Nx = BuffXMax;
377     }
378     if (ts.ScrollBuffMax > BuffYMax) {
379     ts.ScrollBuffMax = BuffYMax;
380     }
381     if (Ny > ts.ScrollBuffMax) {
382     Ny = ts.ScrollBuffMax;
383     }
384 maya 3227
385 maya 3393 if ( (LONG)Nx * (LONG)Ny > BuffSizeMax ) {
386     Ny = BuffSizeMax / Nx;
387     }
388 maya 3227
389 maya 3393 NewSize = (LONG)Nx * (LONG)Ny;
390 maya 3227
391 doda 8445 CodeDestW = NULL;
392     CodeDestW = malloc(NewSize * sizeof(buff_char_t));
393     if (CodeDestW == NULL) {
394     goto allocate_error;
395     }
396 maya 3227
397 doda 8445 memset(&CodeDestW[0], 0, NewSize * sizeof(buff_char_t));
398 zmatsuo 8742 memsetW(&CodeDestW[0], 0x20, AttrDefaultFG, AttrDefaultBG, AttrDefault, AttrDefault, NewSize);
399 zmatsuo 8744 if ( CodeBuffW != NULL ) {
400 maya 3393 if ( NumOfColumns > Nx ) {
401     NxCopy = Nx;
402     }
403     else {
404     NxCopy = NumOfColumns;
405     }
406 maya 3227
407 maya 3393 if ( BuffEnd > Ny ) {
408     NyCopy = Ny;
409     }
410     else {
411     NyCopy = BuffEnd;
412     }
413     LockOld = BuffLock;
414     LockBuffer();
415     SrcPtr = GetLinePtr(BuffEnd-NyCopy);
416     DestPtr = 0;
417     for (i = 1 ; i <= NyCopy ; i++) {
418 doda 8445 memcpyW(&CodeDestW[DestPtr],&CodeBuffW[SrcPtr],NxCopy);
419 zmatsuo 8742 if (CodeDestW[DestPtr+NxCopy-1].attr & AttrKanji) {
420 zmatsuo 8744 BuffSetChar(&CodeDestW[DestPtr + NxCopy - 1], ' ', 'H');
421 zmatsuo 8742 CodeDestW[DestPtr+NxCopy-1].attr ^= AttrKanji;
422     }
423 maya 3393 SrcPtr = NextLinePtr(SrcPtr);
424     DestPtr = DestPtr + (LONG)Nx;
425     }
426     FreeBuffer();
427     }
428     else {
429     LockOld = 0;
430     NyCopy = NumOfLines;
431     Selected = FALSE;
432     }
433 maya 3227
434 maya 3393 if (Selected) {
435     SelectStart.y = SelectStart.y - BuffEnd + NyCopy;
436     SelectEnd.y = SelectEnd.y - BuffEnd + NyCopy;
437     if (SelectStart.y < 0) {
438     SelectStart.y = 0;
439     SelectStart.x = 0;
440     }
441     if (SelectEnd.y<0) {
442     SelectEnd.x = 0;
443     SelectEnd.y = 0;
444     }
445 maya 3227
446 maya 3393 Selected = (SelectEnd.y > SelectStart.y) ||
447 zmatsuo 8411 ((SelectEnd.y == SelectStart.y) &&
448 maya 3393 (SelectEnd.x > SelectStart.x));
449     }
450 maya 3227
451 doda 8445 CodeBuffW = CodeDestW;
452 maya 3393 BufferSize = NewSize;
453     NumOfLinesInBuff = Ny;
454     BuffStartAbs = 0;
455     BuffEnd = NyCopy;
456 maya 3227
457 maya 3393 if (BuffEnd==NumOfLinesInBuff) {
458     BuffEndAbs = 0;
459     }
460     else {
461     BuffEndAbs = BuffEnd;
462     }
463 maya 3227
464 maya 3393 PageStart = BuffEnd - NumOfLines;
465    
466     LinePtr = 0;
467     if (LockOld>0) {
468     }
469     else {
470 doda 8445 ;
471 maya 3393 }
472     BuffLock = LockOld;
473    
474     return TRUE;
475 doda 3686
476     allocate_error:
477 doda 8445 if (CodeDestW) free(CodeDestW);
478 doda 3686 return FALSE;
479 maya 3227 }
480    
481 zmatsuo 8748 void InitBuffer(BOOL use_unicode_api)
482 maya 3227 {
483 maya 3393 int Ny;
484 maya 3227
485 zmatsuo 8748 UseUnicodeApi = use_unicode_api;
486    
487 maya 3393 /* setup terminal */
488     NumOfColumns = ts.TerminalWidth;
489     NumOfLines = ts.TerminalHeight;
490 maya 3227
491 doda 6785 if (NumOfColumns <= 0)
492     NumOfColumns = 80;
493     else if (NumOfColumns > TermWidthMax)
494     NumOfColumns = TermWidthMax;
495    
496     if (NumOfLines <= 0)
497     NumOfLines = 24;
498     else if (NumOfLines > TermHeightMax)
499     NumOfLines = TermHeightMax;
500    
501 maya 3393 /* setup window */
502     if (ts.EnableScrollBuff>0) {
503     if (ts.ScrollBuffSize < NumOfLines) {
504     ts.ScrollBuffSize = NumOfLines;
505     }
506     Ny = ts.ScrollBuffSize;
507     }
508     else {
509     Ny = NumOfLines;
510     }
511 maya 3227
512 maya 3393 if (! ChangeBuffer(NumOfColumns,Ny)) {
513     PostQuitMessage(0);
514     }
515 maya 3227
516 maya 3393 if (ts.EnableScrollBuff>0) {
517     ts.ScrollBuffSize = NumOfLinesInBuff;
518     }
519 maya 3227
520 maya 3393 StatusLine = 0;
521 maya 3227 }
522    
523 doda 8445 static void NewLine(int Line)
524 maya 3227 {
525 maya 3393 LinePtr = GetLinePtr(Line);
526 maya 3227 }
527    
528 zmatsuo 10100 void LockBuffer(void)
529 maya 3227 {
530 maya 3393 BuffLock++;
531     if (BuffLock>1) {
532     return;
533     }
534     NewLine(PageStart+CursorY);
535 maya 3227 }
536    
537 zmatsuo 10100 void UnlockBuffer(void)
538 maya 3227 {
539 maya 3393 if (BuffLock==0) {
540     return;
541     }
542     BuffLock--;
543     if (BuffLock>0) {
544     return;
545     }
546 maya 3227 }
547    
548 zmatsuo 10104 static void FreeCombinationBuffer(void)
549     {
550     int i;
551     for (i = 0; i < NumOfColumns * NumOfLinesInBuff; i++) {
552     buff_char_t *b = &CodeBuffW[i];
553     if (b->pCombinationChars16 != NULL) {
554     free(b->pCombinationChars16);
555     b->pCombinationChars16 = NULL;
556     }
557     if (b->pCombinationChars32 != NULL) {
558     free(b->pCombinationChars32);
559     b->pCombinationChars32 = NULL;
560     }
561     }
562     }
563    
564 zmatsuo 10100 void FreeBuffer(void)
565 maya 3227 {
566 zmatsuo 10104 FreeCombinationBuffer();
567 maya 3393 BuffLock = 1;
568     UnlockBuffer();
569 doda 8445 if (CodeBuffW != NULL) {
570     free(CodeBuffW);
571     CodeBuffW = NULL;
572 maya 3393 }
573 maya 3227 }
574    
575 zmatsuo 10100 void BuffAllSelect(void)
576 maya 3227 {
577     SelectStart.x = 0;
578     SelectStart.y = 0;
579     SelectEnd.x = 0;
580     SelectEnd.y = BuffEnd;
581     // SelectEnd.x = NumOfColumns;
582     // SelectEnd.y = BuffEnd - 1;
583 doda 8400 Selecting = TRUE;
584 maya 3227 }
585    
586 zmatsuo 10100 void BuffScreenSelect(void)
587 maya 3227 {
588     int X, Y;
589     DispConvWinToScreen(0, 0, &X, &Y, NULL);
590     SelectStart.x = X;
591     SelectStart.y = Y + PageStart;
592     SelectEnd.x = 0;
593     SelectEnd.y = SelectStart.y + NumOfLines;
594     // SelectEnd.x = X + NumOfColumns;
595     // SelectEnd.y = Y + PageStart + NumOfLines - 1;
596 doda 8400 Selecting = TRUE;
597 maya 3227 }
598    
599 zmatsuo 10100 void BuffCancelSelection(void)
600 maya 3227 {
601     SelectStart.x = 0;
602     SelectStart.y = 0;
603     SelectEnd.x = 0;
604     SelectEnd.y = 0;
605 doda 8400 Selecting = FALSE;
606 maya 3227 }
607    
608 zmatsuo 10100 void BuffReset(void)
609 maya 3227 // Reset buffer status. don't update real display
610     // called by ResetTerminal()
611     {
612 maya 3393 int i;
613 maya 3227
614 maya 3393 /* Cursor */
615     NewLine(PageStart);
616     WinOrgX = 0;
617     WinOrgY = 0;
618     NewOrgX = 0;
619     NewOrgY = 0;
620 maya 3227
621 maya 3393 /* Top/bottom margin */
622     CursorTop = 0;
623     CursorBottom = NumOfLines-1;
624 doda 5324 CursorLeftM = 0;
625     CursorRightM = NumOfColumns-1;
626 maya 3227
627 maya 3393 /* Tab stops */
628     NTabStops = (NumOfColumns-1) >> 3;
629     for (i=1 ; i<=NTabStops ; i++) {
630 doda 8445 TabStops[i-1] = (WORD)(i*8);
631 maya 3393 }
632 maya 3227
633 maya 3393 /* Initialize text selection region */
634     SelectStart.x = 0;
635     SelectStart.y = 0;
636     SelectEnd = SelectStart;
637     SelectEndOld = SelectStart;
638     Selected = FALSE;
639 maya 3227
640 maya 3393 StrChangeCount = 0;
641     Wrap = FALSE;
642     StatusLine = 0;
643 maya 3227
644 maya 3393 SeveralPageSelect = FALSE; // yutaka
645 doda 3745
646     /* Alternate Screen Buffer */
647     BuffDiscardSavedScreen();
648 maya 3227 }
649    
650 zmatsuo 9839 static void BuffScroll(int Count, int Bottom)
651 maya 3227 {
652 maya 3393 int i, n;
653     LONG SrcPtr, DestPtr;
654     int BuffEndOld;
655 maya 3227
656 maya 3393 if (Count>NumOfLinesInBuff) {
657     Count = NumOfLinesInBuff;
658     }
659 maya 3227
660 maya 3393 DestPtr = GetLinePtr(PageStart+NumOfLines-1+Count);
661     n = Count;
662     if (Bottom<NumOfLines-1) {
663     SrcPtr = GetLinePtr(PageStart+NumOfLines-1);
664     for (i=NumOfLines-1; i>=Bottom+1; i--) {
665 doda 8445 memcpyW(&(CodeBuffW[DestPtr]),&(CodeBuffW[SrcPtr]),NumOfColumns);
666 zmatsuo 8742 memsetW(&(CodeBuffW[SrcPtr]),0x20,CurCharAttr.Fore, CurCharAttr.Back, AttrDefault, CurCharAttr.Attr2 & Attr2ColorMask, NumOfColumns);
667 maya 3393 SrcPtr = PrevLinePtr(SrcPtr);
668     DestPtr = PrevLinePtr(DestPtr);
669     n--;
670     }
671     }
672     for (i = 1 ; i <= n ; i++) {
673 zmatsuo 8741 buff_char_t *b = &CodeBuffW[DestPtr];
674 zmatsuo 8742 memsetW(b ,0x20, CurCharAttr.Fore, CurCharAttr.Back, AttrDefault, CurCharAttr.Attr2 & Attr2ColorMask, NumOfColumns);
675 maya 3393 DestPtr = PrevLinePtr(DestPtr);
676     }
677 maya 3227
678 maya 3393 BuffEndAbs = BuffEndAbs + Count;
679     if (BuffEndAbs >= NumOfLinesInBuff) {
680     BuffEndAbs = BuffEndAbs - NumOfLinesInBuff;
681     }
682     BuffEndOld = BuffEnd;
683     BuffEnd = BuffEnd + Count;
684     if (BuffEnd >= NumOfLinesInBuff) {
685     BuffEnd = NumOfLinesInBuff;
686     BuffStartAbs = BuffEndAbs;
687     }
688     PageStart = BuffEnd-NumOfLines;
689 maya 3227
690 maya 3393 if (Selected) {
691     SelectStart.y = SelectStart.y - Count + BuffEnd - BuffEndOld;
692     SelectEnd.y = SelectEnd.y - Count + BuffEnd - BuffEndOld;
693     if ( SelectStart.y<0 ) {
694     SelectStart.x = 0;
695     SelectStart.y = 0;
696     }
697     if ( SelectEnd.y<0 ) {
698     SelectEnd.x = 0;
699     SelectEnd.y = 0;
700     }
701     Selected = (SelectEnd.y > SelectStart.y) ||
702     ((SelectEnd.y==SelectStart.y) &&
703     (SelectEnd.x > SelectStart.x));
704     }
705 maya 3227
706 maya 3393 NewLine(PageStart+CursorY);
707 maya 3227 }
708    
709     // If cursor is on left/right half of a Kanji, erase it.
710     // LR: left(0)/right(1) flag
711 doda 8445 // LR 0 �J�[�\��������������
712     // 1 �J�[�\�����������E��
713     static void EraseKanji(int LR)
714     {
715 zmatsuo 8739 buff_char_t * CodeLineW = &CodeBuffW[LinePtr];
716    
717 doda 8445 buff_char_t *p;
718     int bx;
719     if (CursorX < LR) {
720     // �S�p������������
721     return;
722     }
723     bx = CursorX-LR;
724     p = &CodeLineW[bx];
725     if (IsBuffFullWidth(p)) {
726     // �S�p��������
727     BuffSetChar(p, ' ', 'H');
728 zmatsuo 8742 p->attr = CurCharAttr.Attr;
729     p->attr2 = CurCharAttr.Attr2;
730 zmatsuo 8741 p->fg = CurCharAttr.Fore;
731     p->bg = CurCharAttr.Back;
732 doda 8445 if (bx+1 < NumOfColumns) {
733     BuffSetChar(p + 1, ' ', 'H');
734 zmatsuo 8742 (p+1)->attr = CurCharAttr.Attr;
735     (p+1)->attr2 = CurCharAttr.Attr2;
736 zmatsuo 8741 (p+1)->fg = CurCharAttr.Fore;
737     (p+1)->bg = CurCharAttr.Back;
738 doda 8445 }
739     }
740 maya 3227 }
741    
742 zmatsuo 8785 static void EraseKanjiOnLRMargin(LONG ptr, int count)
743 doda 5371 {
744     int i;
745     LONG pos;
746    
747     if (count < 1)
748     return;
749    
750     for (i=0; i<count; i++) {
751     pos = ptr + CursorLeftM-1;
752 zmatsuo 8742 if (CursorLeftM>0 && (CodeBuffW[pos].attr & AttrKanji)) {
753 doda 8445 BuffSetChar(&CodeBuffW[pos], 0x20, 'H');
754 zmatsuo 8742 CodeBuffW[pos].attr &= ~AttrKanji;
755 doda 5371 pos++;
756 doda 8445 BuffSetChar(&CodeBuffW[pos], 0x20, 'H');
757 zmatsuo 8742 CodeBuffW[pos].attr &= ~AttrKanji;
758 doda 5371 }
759     pos = ptr + CursorRightM;
760 zmatsuo 8742 if (CursorRightM < NumOfColumns-1 && (CodeBuffW[pos].attr & AttrKanji)) {
761 doda 8445 BuffSetChar(&CodeBuffW[pos], 0x20, 'H');
762 zmatsuo 8742 CodeBuffW[pos].attr &= ~AttrKanji;
763 doda 5371 pos++;
764 doda 8445 BuffSetChar(&CodeBuffW[pos], 0x20, 'H');
765 zmatsuo 8742 CodeBuffW[pos].attr &= ~AttrKanji;
766 doda 5371 }
767     ptr = NextLinePtr(ptr);
768     }
769     }
770    
771 doda 8445 // Insert space characters at the current position
772     // Count: Number of characters to be inserted
773 maya 3227 void BuffInsertSpace(int Count)
774 doda 8445 {
775 zmatsuo 8739 buff_char_t * CodeLineW = &CodeBuffW[LinePtr];
776 doda 8445 int MoveLen;
777     int extr = 0;
778     int sx;
779     buff_char_t *b;
780    
781     if (CursorX < CursorLeftM || CursorX > CursorRightM)
782     return;
783    
784     NewLine(PageStart + CursorY);
785    
786     sx = CursorX;
787     b = &CodeLineW[CursorX];
788     if (IsBuffPadding(b)) {
789     /* if cursor is on right half of a kanji, erase the kanji */
790     BuffSetChar(b - 1, ' ', 'H');
791     BuffSetChar(b, ' ', 'H');
792 zmatsuo 8742 b->attr &= ~AttrKanji;
793 doda 8445 sx--;
794     extr++;
795     }
796    
797 zmatsuo 8742 if (CursorRightM < NumOfColumns - 1 && (CodeLineW[CursorRightM].attr & AttrKanji)) {
798 doda 8445 BuffSetChar(&CodeLineW[CursorRightM + 1], 0x20, 'H');
799 zmatsuo 8742 CodeLineW[CursorRightM + 1].attr &= ~AttrKanji;
800 doda 8445 extr++;
801     }
802    
803     if (Count > CursorRightM + 1 - CursorX)
804     Count = CursorRightM + 1 - CursorX;
805    
806     MoveLen = CursorRightM + 1 - CursorX - Count;
807    
808     if (MoveLen > 0) {
809     memmoveW(&(CodeLineW[CursorX + Count]), &(CodeLineW[CursorX]), MoveLen);
810     }
811 zmatsuo 8742 memsetW(&(CodeLineW[CursorX]), 0x20, CurCharAttr.Fore, CurCharAttr.Back, AttrDefault, CurCharAttr.Attr2, Count);
812 doda 8445 /* last char in current line is kanji first? */
813 zmatsuo 8742 if ((CodeLineW[CursorRightM].attr & AttrKanji) != 0) {
814 doda 8445 /* then delete it */
815     BuffSetChar(&CodeLineW[CursorRightM], 0x20, 'H');
816 zmatsuo 8742 CodeLineW[CursorRightM].attr &= ~AttrKanji;
817 doda 8445 }
818     BuffUpdateRect(sx, CursorY, CursorRightM + extr, CursorY);
819     }
820 doda 5324
821 zmatsuo 10100 void BuffEraseCurToEnd(void)
822 maya 3227 // Erase characters from cursor to the end of screen
823     {
824 maya 3393 LONG TmpPtr;
825     int offset;
826     int i, YEnd;
827 maya 3227
828 maya 3393 NewLine(PageStart+CursorY);
829 doda 3416 if (ts.Language==IdJapanese || ts.Language==IdKorean || ts.Language==IdUtf8) {
830 maya 3393 EraseKanji(1); /* if cursor is on right half of a kanji, erase the kanji */
831     }
832     offset = CursorX;
833     TmpPtr = GetLinePtr(PageStart+CursorY);
834     YEnd = NumOfLines-1;
835 doda 5324 if (StatusLine && !isCursorOnStatusLine) {
836 maya 3393 YEnd--;
837     }
838     for (i = CursorY ; i <= YEnd ; i++) {
839 zmatsuo 8742 memsetW(&(CodeBuffW[TmpPtr+offset]),0x20,CurCharAttr.Fore, CurCharAttr.Back, AttrDefault, CurCharAttr.Attr2 & Attr2ColorMask, NumOfColumns-offset);
840 maya 3393 offset = 0;
841     TmpPtr = NextLinePtr(TmpPtr);
842     }
843     /* update window */
844 zmatsuo 10338 DispEraseCurToEnd(YEnd, &CurCharAttr);
845 maya 3227 }
846    
847 zmatsuo 10100 void BuffEraseHomeToCur(void)
848 maya 3227 // Erase characters from home to cursor
849     {
850 maya 3393 LONG TmpPtr;
851     int offset;
852     int i, YHome;
853 maya 3227
854 maya 3393 NewLine(PageStart+CursorY);
855 doda 3416 if (ts.Language==IdJapanese || ts.Language==IdKorean || ts.Language==IdUtf8) {
856 maya 3393 EraseKanji(0); /* if cursor is on left half of a kanji, erase the kanji */
857     }
858     offset = NumOfColumns;
859 doda 5324 if (isCursorOnStatusLine) {
860 maya 3393 YHome = CursorY;
861     }
862     else {
863     YHome = 0;
864     }
865     TmpPtr = GetLinePtr(PageStart+YHome);
866     for (i = YHome ; i <= CursorY ; i++) {
867     if (i==CursorY) {
868     offset = CursorX+1;
869     }
870 zmatsuo 8742 memsetW(&(CodeBuffW[TmpPtr]),0x20, CurCharAttr.Fore, CurCharAttr.Back, AttrDefault, CurCharAttr.Attr2 & Attr2ColorMask, offset);
871 maya 3393 TmpPtr = NextLinePtr(TmpPtr);
872     }
873 maya 3227
874 maya 3393 /* update window */
875 zmatsuo 10338 DispEraseHomeToCur(YHome, &CurCharAttr);
876 maya 3227 }
877    
878     void BuffInsertLines(int Count, int YEnd)
879     // Insert lines at current position
880     // Count: number of lines to be inserted
881     // YEnd: bottom line number of scroll region (screen coordinate)
882     {
883 doda 5324 int i, linelen;
884 doda 5371 int extl=0, extr=0;
885 maya 3393 LONG SrcPtr, DestPtr;
886 maya 3227
887 maya 3393 BuffUpdateScroll();
888 maya 3227
889 doda 5371 if (CursorLeftM > 0)
890     extl = 1;
891     if (CursorRightM < NumOfColumns-1)
892     extr = 1;
893     if (extl || extr)
894     EraseKanjiOnLRMargin(GetLinePtr(PageStart+CursorY), YEnd-CursorY+1);
895    
896 doda 5324 SrcPtr = GetLinePtr(PageStart+YEnd-Count) + CursorLeftM;
897     DestPtr = GetLinePtr(PageStart+YEnd) + CursorLeftM;
898     linelen = CursorRightM - CursorLeftM + 1;
899 maya 3393 for (i= YEnd-Count ; i>=CursorY ; i--) {
900 doda 8445 memcpyW(&(CodeBuffW[DestPtr]), &(CodeBuffW[SrcPtr]), linelen);
901 maya 3393 SrcPtr = PrevLinePtr(SrcPtr);
902     DestPtr = PrevLinePtr(DestPtr);
903     }
904     for (i = 1 ; i <= Count ; i++) {
905 zmatsuo 8742 memsetW(&(CodeBuffW[DestPtr]), 0x20, CurCharAttr.Fore, CurCharAttr.Back, AttrDefault, CurCharAttr.Attr2 & Attr2ColorMask, linelen);
906 maya 3393 DestPtr = PrevLinePtr(DestPtr);
907     }
908 maya 3227
909 doda 5324 if (CursorLeftM > 0 || CursorRightM < NumOfColumns-1 || !DispInsertLines(Count, YEnd)) {
910 doda 5371 BuffUpdateRect(CursorLeftM-extl, CursorY, CursorRightM+extr, YEnd);
911 maya 3393 }
912 maya 3227 }
913    
914     void BuffEraseCharsInLine(int XStart, int Count)
915     // erase characters in the current line
916     // XStart: start position of erasing
917     // Count: number of characters to be erased
918     {
919 zmatsuo 8739 buff_char_t * CodeLineW = &CodeBuffW[LinePtr];
920 maya 3393 BOOL LineContinued=FALSE;
921 doda 3312
922 zmatsuo 8742 if (ts.EnableContinuedLineCopy && XStart == 0 && (CodeLineW[0].attr & AttrLineContinued)) {
923 maya 3393 LineContinued = TRUE;
924     }
925 doda 3312
926 doda 3416 if (ts.Language==IdJapanese || ts.Language==IdKorean || ts.Language==IdUtf8) {
927 maya 3393 EraseKanji(1); /* if cursor is on right half of a kanji, erase the kanji */
928     }
929 maya 3227
930 maya 3393 NewLine(PageStart+CursorY);
931 zmatsuo 8742 memsetW(&(CodeLineW[XStart]),0x20, CurCharAttr.Fore, CurCharAttr.Back, AttrDefault, CurCharAttr.Attr2 & Attr2ColorMask, Count);
932 maya 3227
933 maya 3393 if (ts.EnableContinuedLineCopy) {
934     if (LineContinued) {
935     BuffLineContinued(TRUE);
936     }
937    
938     if (XStart + Count >= NumOfColumns) {
939 zmatsuo 8742 CodeBuffW[NextLinePtr(LinePtr)].attr &= ~AttrLineContinued;
940 maya 3393 }
941     }
942 doda 3312
943 zmatsuo 10338 DispEraseCharsInLine(XStart, Count, &CurCharAttr);
944 maya 3227 }
945    
946     void BuffDeleteLines(int Count, int YEnd)
947     // Delete lines from current line
948     // Count: number of lines to be deleted
949     // YEnd: bottom line number of scroll region (screen coordinate)
950     {
951 doda 5324 int i, linelen;
952 doda 5371 int extl=0, extr=0;
953 maya 3393 LONG SrcPtr, DestPtr;
954 maya 3227
955 maya 3393 BuffUpdateScroll();
956 maya 3227
957 doda 5371 if (CursorLeftM > 0)
958     extl = 1;
959     if (CursorRightM < NumOfColumns-1)
960     extr = 1;
961     if (extl || extr)
962     EraseKanjiOnLRMargin(GetLinePtr(PageStart+CursorY), YEnd-CursorY+1);
963    
964 doda 5324 SrcPtr = GetLinePtr(PageStart+CursorY+Count) + (LONG)CursorLeftM;
965     DestPtr = GetLinePtr(PageStart+CursorY) + (LONG)CursorLeftM;
966     linelen = CursorRightM - CursorLeftM + 1;
967 maya 3393 for (i=CursorY ; i<= YEnd-Count ; i++) {
968 doda 8445 memcpyW(&(CodeBuffW[DestPtr]), &(CodeBuffW[SrcPtr]), linelen);
969 maya 3393 SrcPtr = NextLinePtr(SrcPtr);
970     DestPtr = NextLinePtr(DestPtr);
971     }
972     for (i = YEnd+1-Count ; i<=YEnd ; i++) {
973 zmatsuo 8742 memsetW(&(CodeBuffW[DestPtr]), 0x20, CurCharAttr.Fore, CurCharAttr.Back, AttrDefault, CurCharAttr.Attr2 & Attr2ColorMask, linelen);
974 maya 3393 DestPtr = NextLinePtr(DestPtr);
975     }
976 maya 3227
977 doda 5324 if (CursorLeftM > 0 || CursorRightM < NumOfColumns-1 || ! DispDeleteLines(Count,YEnd)) {
978 doda 5371 BuffUpdateRect(CursorLeftM-extl, CursorY, CursorRightM+extr, YEnd);
979 maya 3393 }
980 maya 3227 }
981    
982     // Delete characters in current line from cursor
983     // Count: number of characters to be deleted
984 doda 8445 void BuffDeleteChars(int Count)
985 maya 3227 {
986 zmatsuo 8739 buff_char_t * CodeLineW = &CodeBuffW[LinePtr];
987 doda 5325 int MoveLen;
988 doda 8445 int extr = 0;
989     buff_char_t *b;
990    
991     if (Count > CursorRightM + 1 - CursorX)
992     Count = CursorRightM + 1 - CursorX;
993    
994     if (CursorX < CursorLeftM || CursorX > CursorRightM)
995     return;
996    
997     NewLine(PageStart + CursorY);
998    
999     b = &CodeLineW[CursorX];
1000    
1001     if (IsBuffPadding(b)) {
1002     // �S�p���E���A�S�p���X�y�[�X���u��������
1003     BuffSetChar(b - 1, ' ', 'H');
1004     BuffSetChar(b, ' ', 'H');
1005     }
1006     if (IsBuffFullWidth(b)) {
1007     // �S�p�������A�S�p���X�y�[�X���u��������
1008     BuffSetChar(b, ' ', 'H');
1009     BuffSetChar(b + 1, ' ', 'H');
1010     }
1011     if (Count > 1) {
1012     // �I�[���`�F�b�N
1013     if (IsBuffPadding(b + Count)) {
1014     // �S�p���E���A�S�p���X�y�[�X���u��������
1015     BuffSetChar(b + Count - 1, ' ', 'H');
1016     BuffSetChar(b + Count, ' ', 'H');
1017     }
1018     }
1019    
1020 zmatsuo 8742 if (CursorRightM < NumOfColumns - 1 && (CodeLineW[CursorRightM].attr & AttrKanji)) {
1021 doda 8445 BuffSetChar(&CodeLineW[CursorRightM], 0x20, 'H');
1022 zmatsuo 8742 CodeLineW[CursorRightM].attr &= ~AttrKanji;
1023 doda 8445 BuffSetChar(&CodeLineW[CursorRightM + 1], 0x20, 'H');
1024 zmatsuo 8742 CodeLineW[CursorRightM + 1].attr &= ~AttrKanji;
1025 doda 8445 extr = 1;
1026     }
1027    
1028     MoveLen = CursorRightM + 1 - CursorX - Count;
1029    
1030     if (MoveLen > 0) {
1031     memmoveW(&(CodeLineW[CursorX]), &(CodeLineW[CursorX + Count]), MoveLen);
1032     }
1033 zmatsuo 8742 memsetW(&(CodeLineW[CursorX + MoveLen]), ' ', CurCharAttr.Fore, CurCharAttr.Back, AttrDefault, CurCharAttr.Attr2 & Attr2ColorMask, Count);
1034 doda 8445
1035     BuffUpdateRect(CursorX, CursorY, CursorRightM + extr, CursorY);
1036     }
1037 doda 5325
1038 maya 3227 // Erase characters in current line from cursor
1039     // Count: number of characters to be deleted
1040 doda 8445 void BuffEraseChars(int Count)
1041 maya 3227 {
1042 zmatsuo 8739 buff_char_t * CodeLineW = &CodeBuffW[LinePtr];
1043 doda 8445 int extr = 0;
1044     int sx = CursorX;
1045     buff_char_t *b;
1046     NewLine(PageStart + CursorY);
1047    
1048     if (Count > NumOfColumns - CursorX) {
1049     Count = NumOfColumns - CursorX;
1050     }
1051    
1052     b = &CodeLineW[CursorX];
1053     if (IsBuffPadding(b)) {
1054     // �S�p���E���A�S�p���X�y�[�X���u��������
1055     BuffSetChar(b - 1, ' ', 'H');
1056     BuffSetChar(b, ' ', 'H');
1057     sx--;
1058     extr++;
1059     }
1060     if (IsBuffFullWidth(b)) {
1061     // �S�p�������A�S�p���X�y�[�X���u��������
1062     BuffSetChar(b, ' ', 'H');
1063     BuffSetChar(b + 1, ' ', 'H');
1064     if (Count == 1) {
1065     extr++;
1066     }
1067     }
1068     if (Count > 1) {
1069     // �I�[���`�F�b�N
1070     if (IsBuffPadding(b + Count)) {
1071     // �S�p���E���A�S�p���X�y�[�X���u��������
1072     BuffSetChar(b + Count - 1, ' ', 'H');
1073     BuffSetChar(b + Count, ' ', 'H');
1074     extr++;
1075     }
1076     }
1077    
1078 zmatsuo 8742 memsetW(&(CodeLineW[CursorX]), 0x20, CurCharAttr.Fore, CurCharAttr.Back, AttrDefault, CurCharAttr.Attr2 & Attr2ColorMask, Count);
1079 doda 8445
1080     /* update window */
1081 zmatsuo 10338 DispEraseCharsInLine(sx, Count + extr, &CurCharAttr);
1082 doda 8445 }
1083 maya 3227
1084 zmatsuo 10100 void BuffFillWithE(void)
1085 maya 3227 // Fill screen with 'E' characters
1086     {
1087 maya 3393 LONG TmpPtr;
1088     int i;
1089 maya 3227
1090 maya 3393 TmpPtr = GetLinePtr(PageStart);
1091     for (i = 0 ; i <= NumOfLines-1-StatusLine ; i++) {
1092 zmatsuo 8742 memsetW(&(CodeBuffW[TmpPtr]),'E', AttrDefaultFG, AttrDefaultBG, AttrDefault, AttrDefault, NumOfColumns);
1093 maya 3393 TmpPtr = NextLinePtr(TmpPtr);
1094     }
1095     BuffUpdateRect(WinOrgX,WinOrgY,WinOrgX+WinWidth-1,WinOrgY+WinHeight-1);
1096 maya 3227 }
1097    
1098     void BuffDrawLine(TCharAttr Attr, int Direction, int C)
1099     { // IO-8256 terminal
1100 maya 3393 LONG Ptr;
1101     int i, X, Y;
1102 maya 3227
1103 maya 3393 if (C==0) {
1104     return;
1105     }
1106     Attr.Attr |= AttrSpecial;
1107 maya 3227
1108 maya 3393 switch (Direction) {
1109     case 3:
1110     case 4:
1111     if (Direction==3) {
1112     if (CursorY==0) {
1113     return;
1114     }
1115     Y = CursorY-1;
1116     }
1117     else {
1118     if (CursorY==NumOfLines-1-StatusLine) {
1119     return;
1120     }
1121     Y = CursorY+1;
1122     }
1123     if (CursorX+C > NumOfColumns) {
1124     C = NumOfColumns-CursorX;
1125     }
1126     Ptr = GetLinePtr(PageStart+Y);
1127 zmatsuo 8742 memsetW(&(CodeBuffW[Ptr+CursorX]),'q', Attr.Fore, Attr.Back, Attr.Attr, Attr.Attr2, C);
1128 maya 3393 BuffUpdateRect(CursorX,Y,CursorX+C-1,Y);
1129     break;
1130     case 5:
1131     case 6:
1132     if (Direction==5) {
1133     if (CursorX==0) {
1134     return;
1135     }
1136     X = CursorX - 1;
1137     }
1138     else {
1139     if (CursorX==NumOfColumns-1) {
1140     X = CursorX-1;
1141     }
1142     else {
1143     X = CursorX+1;
1144     }
1145     }
1146     Ptr = GetLinePtr(PageStart+CursorY);
1147     if (CursorY+C > NumOfLines-StatusLine) {
1148     C = NumOfLines-StatusLine-CursorY;
1149     }
1150     for (i=1; i<=C; i++) {
1151 zmatsuo 8744 BuffSetChar4(&CodeBuffW[Ptr+X], 'x', Attr.Fore, Attr.Back, Attr.Attr, Attr.Attr2, 'H');
1152 maya 3393 Ptr = NextLinePtr(Ptr);
1153     }
1154     BuffUpdateRect(X,CursorY,X,CursorY+C-1);
1155     break;
1156     }
1157 maya 3227 }
1158    
1159 zmatsuo 8742 void BuffEraseBox(int XStart, int YStart, int XEnd, int YEnd)
1160 maya 3227 {
1161 maya 3393 int C, i;
1162     LONG Ptr;
1163 maya 3227
1164 maya 3393 if (XEnd>NumOfColumns-1) {
1165     XEnd = NumOfColumns-1;
1166     }
1167     if (YEnd>NumOfLines-1-StatusLine) {
1168     YEnd = NumOfLines-1-StatusLine;
1169     }
1170     if (XStart>XEnd) {
1171     return;
1172     }
1173     if (YStart>YEnd) {
1174     return;
1175     }
1176     C = XEnd-XStart+1;
1177     Ptr = GetLinePtr(PageStart+YStart);
1178     for (i=YStart; i<=YEnd; i++) {
1179     if ((XStart>0) &&
1180 zmatsuo 8742 ((CodeBuffW[Ptr+XStart-1].attr & AttrKanji) != 0)) {
1181     BuffSetChar4(&CodeBuffW[Ptr+XStart-1], 0x20, CurCharAttr.Fore, CurCharAttr.Back, CurCharAttr.Attr, CurCharAttr.Attr2, 'H');
1182 maya 3393 }
1183     if ((XStart+C<NumOfColumns) &&
1184 zmatsuo 8742 ((CodeBuffW[Ptr+XStart+C-1].attr & AttrKanji) != 0)) {
1185     BuffSetChar4(&CodeBuffW[Ptr+XStart+C], 0x20, CurCharAttr.Fore, CurCharAttr.Back, CurCharAttr.Attr, CurCharAttr.Attr2, 'H');
1186 maya 3393 }
1187 zmatsuo 8742 memsetW(&(CodeBuffW[Ptr+XStart]),0x20, CurCharAttr.Fore, CurCharAttr.Back, AttrDefault, CurCharAttr.Attr2 & Attr2ColorMask, C);
1188 maya 3393 Ptr = NextLinePtr(Ptr);
1189     }
1190     BuffUpdateRect(XStart,YStart,XEnd,YEnd);
1191 maya 3227 }
1192    
1193 doda 5090 void BuffFillBox(char ch, int XStart, int YStart, int XEnd, int YEnd)
1194     {
1195     int Cols, i;
1196     LONG Ptr;
1197    
1198     if (XEnd>NumOfColumns-1) {
1199     XEnd = NumOfColumns-1;
1200     }
1201     if (YEnd>NumOfLines-1-StatusLine) {
1202     YEnd = NumOfLines-1-StatusLine;
1203     }
1204     if (XStart>XEnd) {
1205     return;
1206     }
1207     if (YStart>YEnd) {
1208     return;
1209     }
1210     Cols = XEnd-XStart+1;
1211     Ptr = GetLinePtr(PageStart+YStart);
1212     for (i=YStart; i<=YEnd; i++) {
1213     if ((XStart>0) &&
1214 zmatsuo 8742 ((CodeBuffW[Ptr+XStart-1].attr & AttrKanji) != 0)) {
1215 doda 8446 BuffSetChar(&CodeBuffW[Ptr + XStart - 1], 0x20, 'H');
1216 zmatsuo 8742 CodeBuffW[Ptr+XStart-1].attr ^= AttrKanji;
1217 doda 5090 }
1218     if ((XStart+Cols<NumOfColumns) &&
1219 zmatsuo 8742 ((CodeBuffW[Ptr+XStart+Cols-1].attr & AttrKanji) != 0)) {
1220 doda 8446 BuffSetChar(&CodeBuffW[Ptr + XStart + Cols], 0x20, 'H');
1221 doda 5090 }
1222 zmatsuo 8742 memsetW(&(CodeBuffW[Ptr+XStart]), ch, CurCharAttr.Fore, CurCharAttr.Back, CurCharAttr.Attr, CurCharAttr.Attr2, Cols);
1223 doda 5090 Ptr = NextLinePtr(Ptr);
1224     }
1225     BuffUpdateRect(XStart, YStart, XEnd, YEnd);
1226     }
1227    
1228 doda 6174 //
1229     // TODO: 1 origin �������������� 0 origin ������
1230     //
1231 doda 5089 void BuffCopyBox(
1232     int SrcXStart, int SrcYStart, int SrcXEnd, int SrcYEnd, int SrcPage,
1233     int DstX, int DstY, int DstPage)
1234     {
1235     int i, C, L;
1236     LONG SPtr, DPtr;
1237    
1238     SrcXStart--;
1239     SrcYStart--;
1240     SrcXEnd--;
1241     SrcYEnd--;
1242     SrcPage--;
1243     DstX--;
1244     DstY--;
1245     DstPage--;
1246    
1247     if (SrcXEnd > NumOfColumns - 1) {
1248     SrcXEnd = NumOfColumns-1;
1249     }
1250     if (SrcYEnd > NumOfLines-1-StatusLine) {
1251     SrcYEnd = NumOfColumns-1;
1252     }
1253     if (SrcXStart > SrcXEnd ||
1254     SrcYStart > SrcYEnd ||
1255     DstX > NumOfColumns-1 ||
1256     DstY > NumOfLines-1-StatusLine) {
1257     return;
1258     }
1259    
1260     C = SrcXEnd - SrcXStart + 1;
1261     if (DstX + C > NumOfColumns) {
1262     C = NumOfColumns - DstX;
1263     }
1264     L = SrcYEnd - SrcYStart + 1;
1265     if (DstY + C > NumOfColumns) {
1266     C = NumOfColumns - DstX;
1267     }
1268    
1269     if (SrcXStart > DstX) {
1270     SPtr = GetLinePtr(PageStart+SrcYStart);
1271     DPtr = GetLinePtr(PageStart+DstY);
1272     for (i=0; i<L; i++) {
1273 doda 8445 memcpyW(&(CodeBuffW[DPtr+DstX]), &(CodeBuffW[SPtr+SrcXStart]), C);
1274 doda 5089 SPtr = NextLinePtr(SPtr);
1275     DPtr = NextLinePtr(DPtr);
1276     }
1277     }
1278     else if (SrcXStart < DstX) {
1279     SPtr = GetLinePtr(PageStart+SrcYEnd);
1280     DPtr = GetLinePtr(PageStart+DstY+L-1);
1281     for (i=L; i>0; i--) {
1282 doda 8445 memcpyW(&(CodeBuffW[DPtr+DstX]), &(CodeBuffW[SPtr+SrcXStart]), C);
1283 doda 5089 SPtr = PrevLinePtr(SPtr);
1284     DPtr = PrevLinePtr(DPtr);
1285     }
1286     }
1287     else if (SrcYStart != DstY) {
1288     SPtr = GetLinePtr(PageStart+SrcYStart);
1289     DPtr = GetLinePtr(PageStart+DstY);
1290     for (i=0; i<L; i++) {
1291 doda 8445 memmoveW(&(CodeBuffW[DPtr+DstX]), &(CodeBuffW[SPtr+SrcXStart]), C);
1292 doda 5089 SPtr = NextLinePtr(SPtr);
1293     DPtr = NextLinePtr(DPtr);
1294     }
1295     }
1296     BuffUpdateRect(DstX,DstY,DstX+C-1,DstY+L-1);
1297     }
1298    
1299 doda 5095 void BuffChangeAttrBox(int XStart, int YStart, int XEnd, int YEnd, PCharAttr attr, PCharAttr mask)
1300     {
1301     int C, i, j;
1302     LONG Ptr;
1303    
1304     if (XEnd>NumOfColumns-1) {
1305     XEnd = NumOfColumns-1;
1306     }
1307     if (YEnd>NumOfLines-1-StatusLine) {
1308     YEnd = NumOfLines-1-StatusLine;
1309     }
1310     if (XStart>XEnd || YStart>YEnd) {
1311     return;
1312     }
1313     C = XEnd-XStart+1;
1314     Ptr = GetLinePtr(PageStart+YStart);
1315    
1316     if (mask) { // DECCARA
1317     for (i=YStart; i<=YEnd; i++) {
1318     j = Ptr+XStart-1;
1319 zmatsuo 8742 if (XStart>0 && (CodeBuffW[j].attr & AttrKanji)) {
1320     CodeBuffW[j].attr = (CodeBuffW[j].attr & ~mask->Attr) | attr->Attr;
1321     CodeBuffW[j].attr2 = (CodeBuffW[j].attr2 & ~mask->Attr2) | attr->Attr2;
1322 zmatsuo 8741 if (mask->Attr2 & Attr2Fore) { CodeBuffW[j].fg = attr->Fore; }
1323     if (mask->Attr2 & Attr2Back) { CodeBuffW[j].bg = attr->Back; }
1324 doda 5095 }
1325 doda 7083 while (++j < Ptr+XStart+C) {
1326 zmatsuo 8742 CodeBuffW[j].attr = (CodeBuffW[j].attr & ~mask->Attr) | attr->Attr;
1327     CodeBuffW[j].attr2 = (CodeBuffW[j].attr2 & ~mask->Attr2) | attr->Attr2;
1328 zmatsuo 8741 if (mask->Attr2 & Attr2Fore) { CodeBuffW[j].fg = attr->Fore; }
1329     if (mask->Attr2 & Attr2Back) { CodeBuffW[j].bg = attr->Back; }
1330 doda 5095 }
1331 zmatsuo 8742 if (XStart+C<NumOfColumns && (CodeBuffW[j-1].attr & AttrKanji)) {
1332     CodeBuffW[j].attr = (CodeBuffW[j].attr & ~mask->Attr) | attr->Attr;
1333     CodeBuffW[j].attr2 = (CodeBuffW[j].attr2 & ~mask->Attr2) | attr->Attr2;
1334 zmatsuo 8741 if (mask->Attr2 & Attr2Fore) { CodeBuffW[j].fg = attr->Fore; }
1335     if (mask->Attr2 & Attr2Back) { CodeBuffW[j].bg = attr->Back; }
1336 doda 5095 }
1337     Ptr = NextLinePtr(Ptr);
1338     }
1339     }
1340     else { // DECRARA
1341     for (i=YStart; i<=YEnd; i++) {
1342     j = Ptr+XStart-1;
1343 zmatsuo 8742 if (XStart>0 && (CodeBuffW[j].attr & AttrKanji)) {
1344     CodeBuffW[j].attr ^= attr->Attr;
1345 doda 5095 }
1346 doda 7083 while (++j < Ptr+XStart+C) {
1347 zmatsuo 8742 CodeBuffW[j].attr ^= attr->Attr;
1348 doda 5095 }
1349 zmatsuo 8742 if (XStart+C<NumOfColumns && (CodeBuffW[j-1].attr & AttrKanji)) {
1350     CodeBuffW[j].attr ^= attr->Attr;
1351 doda 5095 }
1352     Ptr = NextLinePtr(Ptr);
1353     }
1354     }
1355     BuffUpdateRect(XStart, YStart, XEnd, YEnd);
1356     }
1357    
1358 doda 7086 void BuffChangeAttrStream(int XStart, int YStart, int XEnd, int YEnd, PCharAttr attr, PCharAttr mask)
1359     {
1360     int i, j, endp;
1361     LONG Ptr;
1362    
1363     if (XEnd>NumOfColumns-1) {
1364     XEnd = NumOfColumns-1;
1365     }
1366     if (YEnd>NumOfLines-1-StatusLine) {
1367     YEnd = NumOfLines-1-StatusLine;
1368     }
1369     if (XStart>XEnd || YStart>YEnd) {
1370     return;
1371     }
1372    
1373     Ptr = GetLinePtr(PageStart+YStart);
1374    
1375     if (mask) { // DECCARA
1376     if (YStart == YEnd) {
1377     i = Ptr + XStart - 1;
1378     endp = Ptr + XEnd + 1;
1379    
1380 zmatsuo 8742 if (XStart > 0 && (CodeBuffW[i].attr & AttrKanji)) {
1381 zmatsuo 10101 CodeBuffW[i].attr = (CodeBuffW[i].attr & ~mask->Attr) | attr->Attr;
1382     CodeBuffW[i].attr2 = (CodeBuffW[i].attr2 & ~mask->Attr2) | attr->Attr2;
1383 zmatsuo 8741 if (mask->Attr2 & Attr2Fore) { CodeBuffW[i].fg = attr->Fore; }
1384     if (mask->Attr2 & Attr2Back) { CodeBuffW[i].bg = attr->Back; }
1385 doda 7086 }
1386     while (++i < endp) {
1387 zmatsuo 10101 CodeBuffW[i].attr = (CodeBuffW[i].attr & ~mask->Attr) | attr->Attr;
1388     CodeBuffW[i].attr2 = (CodeBuffW[i].attr2 & ~mask->Attr2) | attr->Attr2;
1389 zmatsuo 8741 if (mask->Attr2 & Attr2Fore) { CodeBuffW[i].fg = attr->Fore; }
1390     if (mask->Attr2 & Attr2Back) { CodeBuffW[i].bg = attr->Back; }
1391 doda 7086 }
1392 zmatsuo 8742 if (XEnd < NumOfColumns-1 && (CodeBuffW[i-1].attr & AttrKanji)) {
1393 zmatsuo 10101 CodeBuffW[i].attr = (CodeBuffW[i].attr & ~mask->Attr) | attr->Attr;
1394     CodeBuffW[i].attr2 = (CodeBuffW[i].attr2 & ~mask->Attr2) | attr->Attr2;
1395 zmatsuo 8741 if (mask->Attr2 & Attr2Fore) { CodeBuffW[i].fg = attr->Fore; }
1396     if (mask->Attr2 & Attr2Back) { CodeBuffW[i].bg = attr->Back; }
1397 doda 7086 }
1398     }
1399     else {
1400     i = Ptr + XStart - 1;
1401     endp = Ptr + NumOfColumns;
1402    
1403 zmatsuo 8742 if (XStart > 0 && (CodeBuffW[i].attr & AttrKanji)) {
1404 zmatsuo 10101 CodeBuffW[i].attr = (CodeBuffW[i].attr & ~mask->Attr) | attr->Attr;
1405     CodeBuffW[i].attr2 = (CodeBuffW[i].attr2 & ~mask->Attr2) | attr->Attr2;
1406 zmatsuo 8741 if (mask->Attr2 & Attr2Fore) { CodeBuffW[i].fg = attr->Fore; }
1407     if (mask->Attr2 & Attr2Back) { CodeBuffW[i].bg = attr->Back; }
1408 doda 7086 }
1409     while (++i < endp) {
1410 zmatsuo 10101 CodeBuffW[i].attr = (CodeBuffW[i].attr & ~mask->Attr) | attr->Attr;
1411     CodeBuffW[i].attr2 = (CodeBuffW[i].attr2 & ~mask->Attr2) | attr->Attr2;
1412 zmatsuo 8741 if (mask->Attr2 & Attr2Fore) { CodeBuffW[i].fg = attr->Fore; }
1413     if (mask->Attr2 & Attr2Back) { CodeBuffW[i].bg = attr->Back; }
1414 doda 7086 }
1415    
1416     for (j=0; j < YEnd-YStart-1; j++) {
1417     Ptr = NextLinePtr(Ptr);
1418     i = Ptr;
1419     endp = Ptr + NumOfColumns;
1420    
1421     while (i < endp) {
1422 zmatsuo 10101 CodeBuffW[i].attr = (CodeBuffW[i].attr & ~mask->Attr) | attr->Attr;
1423     CodeBuffW[i].attr2 = (CodeBuffW[i].attr2 & ~mask->Attr2) | attr->Attr2;
1424 zmatsuo 8741 if (mask->Attr2 & Attr2Fore) { CodeBuffW[i].fg = attr->Fore; }
1425     if (mask->Attr2 & Attr2Back) { CodeBuffW[i].bg = attr->Back; }
1426 doda 7086 i++;
1427     }
1428     }
1429    
1430     Ptr = NextLinePtr(Ptr);
1431     i = Ptr;
1432     endp = Ptr + XEnd + 1;
1433    
1434     while (i < endp) {
1435 zmatsuo 10101 CodeBuffW[i].attr = (CodeBuffW[i].attr & ~mask->Attr) | attr->Attr;
1436     CodeBuffW[i].attr2 = (CodeBuffW[i].attr2 & ~mask->Attr2) | attr->Attr2;
1437 zmatsuo 8741 if (mask->Attr2 & Attr2Fore) { CodeBuffW[i].fg = attr->Fore; }
1438     if (mask->Attr2 & Attr2Back) { CodeBuffW[i].bg = attr->Back; }
1439 doda 7086 i++;
1440     }
1441 zmatsuo 8742 if (XEnd < NumOfColumns-1 && (CodeBuffW[i-1].attr & AttrKanji)) {
1442 zmatsuo 10101 CodeBuffW[i].attr = (CodeBuffW[i].attr & ~mask->Attr) | attr->Attr;
1443     CodeBuffW[i].attr2 = (CodeBuffW[i].attr2 & ~mask->Attr2) | attr->Attr2;
1444 zmatsuo 8741 if (mask->Attr2 & Attr2Fore) { CodeBuffW[i].fg = attr->Fore; }
1445     if (mask->Attr2 & Attr2Back) { CodeBuffW[i].bg = attr->Back; }
1446 doda 7086 }
1447     }
1448     }
1449     else { // DECRARA
1450     if (YStart == YEnd) {
1451     i = Ptr + XStart - 1;
1452     endp = Ptr + XEnd + 1;
1453    
1454 zmatsuo 8742 if (XStart > 0 && (CodeBuffW[i].attr & AttrKanji)) {
1455     CodeBuffW[i].attr ^= attr->Attr;
1456 doda 7086 }
1457     while (++i < endp) {
1458 zmatsuo 8742 CodeBuffW[i].attr ^= attr->Attr;
1459 doda 7086 }
1460 zmatsuo 8742 if (XEnd < NumOfColumns-1 && (CodeBuffW[i-1].attr & AttrKanji)) {
1461     CodeBuffW[i].attr ^= attr->Attr;
1462 doda 7086 }
1463     }
1464     else {
1465     i = Ptr + XStart - 1;
1466     endp = Ptr + NumOfColumns;
1467    
1468 zmatsuo 8742 if (XStart > 0 && (CodeBuffW[i].attr & AttrKanji)) {
1469     CodeBuffW[i].attr ^= attr->Attr;
1470 doda 7086 }
1471     while (++i < endp) {
1472 zmatsuo 8742 CodeBuffW[i].attr ^= attr->Attr;
1473 doda 7086 }
1474    
1475     for (j=0; j < YEnd-YStart-1; j++) {
1476     Ptr = NextLinePtr(Ptr);
1477     i = Ptr;
1478     endp = Ptr + NumOfColumns;
1479    
1480     while (i < endp) {
1481 zmatsuo 8742 CodeBuffW[i].attr ^= attr->Attr;
1482 doda 7086 i++;
1483     }
1484     }
1485    
1486     Ptr = NextLinePtr(Ptr);
1487     i = Ptr;
1488     endp = Ptr + XEnd + 1;
1489    
1490     while (i < endp) {
1491 zmatsuo 8742 CodeBuffW[i].attr ^= attr->Attr;
1492 doda 7086 i++;
1493     }
1494 zmatsuo 8742 if (XEnd < NumOfColumns-1 && (CodeBuffW[i-1].attr & AttrKanji)) {
1495     CodeBuffW[i].attr ^= attr->Attr;
1496 doda 7086 }
1497     Ptr = NextLinePtr(Ptr);
1498     }
1499     }
1500     BuffUpdateRect(0, YStart, NumOfColumns-1, YEnd);
1501     }
1502    
1503 zmatsuo 10308 /**
1504     * (Line,CharPtr)���u���S�p���E��(��������N cell��1cell����������)����
1505     * ���������������u������
1506     *
1507     * If CharPtr is on the right half of a DBCS character
1508     * return pointer to the left half
1509     *
1510     * @param Line points to a line in CodeBuff
1511     * @param CharPtr points to a char
1512     * @return points to the left half of the DBCS
1513     */
1514 doda 8445 static int LeftHalfOfDBCS(LONG Line, int CharPtr)
1515 maya 3227 {
1516 zmatsuo 10308 int x = CharPtr;
1517     while(x > 0) {
1518     if ((CodeBuffW[Line+x].Padding) == FALSE) {
1519     // padding��������
1520     break;
1521     }
1522     assert(x > 0); // �s���� padding?
1523     x--;
1524 maya 3393 }
1525 zmatsuo 10308 return x;
1526 maya 3227 }
1527    
1528 doda 8445 static int MoveCharPtr(LONG Line, int *x, int dx)
1529 maya 3227 // move character pointer x by dx character unit
1530     // in the line specified by Line
1531     // Line: points to a line in CodeBuff
1532     // x: points to a character in the line
1533     // dx: moving distance in character unit (-: left, +: right)
1534 maya 3393 // One DBCS character is counted as one character.
1535 maya 3227 // The pointer stops at the beginning or the end of line.
1536     // Output
1537     // x: new pointer. x points to a SBCS character or
1538     // the left half of a DBCS character.
1539     // return: actual moving distance in character unit
1540     {
1541 maya 3393 int i;
1542 maya 3227
1543 maya 3393 *x = LeftHalfOfDBCS(Line,*x);
1544     i = 0;
1545     while (dx!=0) {
1546     if (dx>0) { // move right
1547 zmatsuo 8742 if ((CodeBuffW[Line+*x].attr & AttrKanji) != 0) {
1548 maya 3393 if (*x<NumOfColumns-2) {
1549     i++;
1550     *x = *x + 2;
1551     }
1552     }
1553     else if (*x<NumOfColumns-1) {
1554     i++;
1555     (*x)++;
1556     }
1557     dx--;
1558     }
1559     else { // move left
1560     if (*x>0) {
1561     i--;
1562     (*x)--;
1563     }
1564     *x = LeftHalfOfDBCS(Line,*x);
1565     dx++;
1566     }
1567 maya 3227 }
1568 maya 3393 return i;
1569 maya 3227 }
1570    
1571 doda 8445 /**
1572     * (�N���b�v�{�[�h�p��)������������
1573     * @param[in] sx,sy,ex,ey �I������
1574     * @param[in] box_select TRUE=���^(���`)�I��
1575     * FALSE=�s�I��
1576     * @param[out] _str_len ��������(�����[L'\0'������)
1577     * NULL����������������
1578     * @return ������
1579     * �g�p���� free() ��������
1580     */
1581     static wchar_t *BuffGetStringForCB(int sx, int sy, int ex, int ey, BOOL box_select, size_t *_str_len)
1582     {
1583     wchar_t *str_w;
1584     size_t str_size; // �m�������T�C�Y
1585     size_t k;
1586     LONG TmpPtr;
1587     int x, y;
1588    
1589 zmatsuo 10061 str_size = (NumOfColumns + 2) * (ey - sy + 1);
1590 doda 8445 str_w = malloc(sizeof(wchar_t) * str_size);
1591    
1592     LockBuffer();
1593    
1594     str_w[0] = 0;
1595     TmpPtr = GetLinePtr(sy);
1596     k = 0;
1597     for (y = sy; y<=ey ; y++) {
1598 zmatsuo 10030 int IStart; // �J�n
1599     int IEnd; // �I��
1600     BOOL LineContinued;
1601    
1602 doda 8445 if (box_select) {
1603 zmatsuo 10030 IStart = sx;
1604     IEnd = ex - 1;
1605     LineContinued = FALSE;
1606 doda 8445 }
1607     else {
1608 zmatsuo 10030 // �s�I��
1609     IStart = (y == sy) ? sx : 0;
1610 zmatsuo 10061 LineContinued = FALSE;
1611     if (y == ey) {
1612     // 1�s�I�����A����
1613     // �����s�I�������������s
1614     IEnd = ex - 1;
1615     }
1616     else {
1617     // �����s�I�������r�����s
1618     // �s�������I������������
1619     IEnd = NumOfColumns - 1;
1620 doda 8445
1621 zmatsuo 10061 // �p���s�R�s�[����
1622     if (ts.EnableContinuedLineCopy) {
1623     LONG NextTmpPtr = NextLinePtr(TmpPtr);
1624     if ((CodeBuffW[NextTmpPtr].attr & AttrLineContinued) != 0) {
1625     // �����s���p����������
1626     LineContinued = TRUE;
1627     }
1628 doda 8445 }
1629     }
1630     }
1631    
1632 zmatsuo 10062 // IEnd=�R�s�[���K�v�����������u
1633     if (LineContinued) {
1634     // �s���������������R�s�[����
1635     IEnd++;
1636     }
1637     else {
1638 zmatsuo 10061 // �����s���p�����������������A�X�y�[�X����������
1639 zmatsuo 10030 while (IEnd >= IStart) {
1640     // �R�s�[�s�v��" "(0x20)������
1641 doda 8445 const buff_char_t *b = &CodeBuffW[TmpPtr + IEnd];
1642 zmatsuo 10030 if (b->u32 != 0x20) {
1643     // �X�y�[�X���O������
1644 zmatsuo 10062 IEnd++;
1645 zmatsuo 10030 break;
1646 doda 8445 }
1647 zmatsuo 10030 if (IEnd == 0) {
1648 doda 8445 break;
1649     }
1650 zmatsuo 10030 // �����l����
1651     MoveCharPtr(TmpPtr,&IEnd,-1);
1652 doda 8445 }
1653     }
1654    
1655 zmatsuo 10030 // 1���C�����������R�s�[����
1656 zmatsuo 10062 // IEnd=�R�s�[���K�v�����������u+1
1657 doda 8445 x = IStart;
1658 zmatsuo 10062 while (x < IEnd) {
1659 doda 8445 const buff_char_t *b = &CodeBuffW[TmpPtr + x];
1660     if (b->u32 != 0) {
1661     str_w[k++] = b->wc2[0];
1662     if (b->wc2[1] != 0) {
1663     str_w[k++] = b->wc2[1];
1664     }
1665     if (k + 2 >= str_size) {
1666     str_size *= 2;
1667     str_w = realloc(str_w, sizeof(wchar_t) * str_size);
1668     }
1669     {
1670     int i;
1671     // �R���r�l�[�V����
1672     if (k + b->CombinationCharCount16 >= str_size) {
1673     str_size += + b->CombinationCharCount16;
1674     str_w = realloc(str_w, sizeof(wchar_t) * str_size);
1675     }
1676     for (i = 0 ; i < (int)b->CombinationCharCount16; i++) {
1677     str_w[k++] = b->pCombinationChars16[i];
1678     }
1679     }
1680     }
1681     x++;
1682     }
1683    
1684     if (y < ey) {
1685     // ���s��������(�������s���O������)
1686     if (!LineContinued) {
1687     str_w[k++] = 0x0d;
1688     str_w[k++] = 0x0a;
1689     }
1690     }
1691    
1692     TmpPtr = NextLinePtr(TmpPtr);
1693     }
1694     str_w[k++] = 0;
1695    
1696     UnlockBuffer();
1697    
1698     if (_str_len != NULL) {
1699     *_str_len = k;
1700     }
1701     return str_w;
1702     }
1703    
1704     /**
1705 zmatsuo 8678 * 1�Z������wchar_t���������W�J����
1706     * @param[in] b 1�Z�������������������|�C���^
1707     * @param[in,out] buf �������W�J�� NULL���������W�J��������
1708 zmatsuo 8744 * @param[in] buf_size buf��������(buff == NULL���������Q����������)
1709     * @param[out] too_small NULL ��������������������
1710     * TRUE �o�b�t�@�T�C�Y�s��
1711     * �����l���K�v��������������
1712     * FALSE �������W�J������
1713     * @retrun ������ �o��������
1714     * 0�������A�����o������
1715 zmatsuo 8745 *
1716     * TODO
1717     * GetWCS() ������?
1718 zmatsuo 8678 */
1719     static size_t expand_wchar(const buff_char_t *b, wchar_t *buf, size_t buf_size, BOOL *too_samll)
1720     {
1721     size_t len;
1722    
1723     if (IsBuffPadding(b)) {
1724     if (too_samll != NULL) {
1725     *too_samll = FALSE;
1726     }
1727     return 0;
1728     }
1729    
1730     // ����������
1731     len = 0;
1732     if (b->wc2[1] == 0) {
1733     // �T���Q�[�g�y�A��������
1734     len++;
1735     } else {
1736     // �T���Q�[�g�y�A
1737     len += 2;
1738     }
1739     // �R���r�l�[�V����
1740     len += b->CombinationCharCount16;
1741    
1742     if (buf == NULL) {
1743     // ��������������
1744     return len;
1745     }
1746    
1747     // �o�b�t�@��������?
1748     if (len > buf_size) {
1749     // �o�b�t�@������������
1750     if (too_samll != NULL) {
1751     *too_samll = TRUE;
1752     }
1753 zmatsuo 8908 return len;
1754 zmatsuo 8678 }
1755     if (too_samll != NULL) {
1756     *too_samll = FALSE;
1757     }
1758    
1759     // �W�J��������
1760     *buf++ = b->wc2[0];
1761     if (b->wc2[1] != 0) {
1762     *buf++ = b->wc2[1];
1763     }
1764     if (b->CombinationCharCount16 != 0) {
1765     memcpy(buf, b->pCombinationChars16, b->CombinationCharCount16 * sizeof(wchar_t));
1766     }
1767    
1768     return len;
1769     }
1770    
1771     /**
1772 doda 8445 * (x,y) ��1������ str��������������
1773     * *�� 1������������wchar_t�����\������������
1774     *
1775 zmatsuo 8744 * @param b
1776     * @param str ���r������(wchar_t)
1777     * @param len ���r��������
1778     * @retval �}�b�`������������
1779     * 0=�}�b�`����������
1780 doda 8445 */
1781 zmatsuo 8744 static size_t MatchOneStringPtr(const buff_char_t *b, const wchar_t *str, size_t len)
1782 doda 8445 {
1783 zmatsuo 8747 int match_pos = 0;
1784 zmatsuo 8744 if (len == 0) {
1785     return 0;
1786     }
1787 doda 8445 if (b->wc2[1] == 0) {
1788     // �T���Q�[�g�y�A��������
1789     if (str[match_pos] != b->wc2[0]) {
1790     return 0;
1791     }
1792     match_pos++;
1793     len--;
1794     } else {
1795     // �T���Q�[�g�y�A
1796     if (len < 2) {
1797     return 0;
1798     }
1799     if (str[match_pos+0] != b->wc2[0] ||
1800     str[match_pos+1] != b->wc2[1]) {
1801     return 0;
1802     }
1803     match_pos+=2;
1804     len-=2;
1805     }
1806     if (b->CombinationCharCount16 > 0) {
1807     // �R���r�l�[�V����
1808     int i;
1809     if (len < b->CombinationCharCount16) {
1810     return 0;
1811     }
1812     for (i = 0 ; i < (int)b->CombinationCharCount16; i++) {
1813     if (str[match_pos++] != b->pCombinationChars16[i]) {
1814     return 0;
1815     }
1816     }
1817     len -= b->CombinationCharCount16;
1818     }
1819     return match_pos;
1820     }
1821    
1822     /**
1823 zmatsuo 8744 * (x,y) ��1������ str��������������
1824     * *�� 1������������wchar_t�����\������������
1825     *
1826     * @param y PageStart + CursorY
1827     * @param str 1����(wchar_t��)
1828     * @param len ��������
1829     * @retval 0=�}�b�`����������
1830     * �}�b�`������������
1831     */
1832     static size_t MatchOneString(int x, int y, const wchar_t *str, size_t len)
1833     {
1834     int TmpPtr = GetLinePtr(y);
1835     const buff_char_t *b = &CodeBuffW[TmpPtr + x];
1836     return MatchOneStringPtr(b, str, len);
1837     }
1838    
1839     /**
1840     * b ���� str��������������
1841     *
1842     * @param b �o�b�t�@�����|�C���^�A����������������
1843     * @param LineCntinued TRUE=�s���p�����l������
1844     * @retval TRUE �}�b�`����
1845     * @retval FALSE �}�b�`����������
1846     */
1847 zmatsuo 10311 #if 0
1848 zmatsuo 8744 static BOOL MatchStringPtr(const buff_char_t *b, const wchar_t *str, BOOL LineContinued)
1849     {
1850     int x;
1851     int y;
1852     BOOL result;
1853     size_t len = wcslen(str);
1854     if (len == 0) {
1855     return FALSE;
1856     }
1857     GetPosFromPtr(b, &x, &y);
1858     for(;;) {
1859 zmatsuo 8747 size_t match_len;
1860 zmatsuo 8744 if (IsBuffPadding(b)) {
1861     b++;
1862     continue;
1863     }
1864     // 1����������������
1865 zmatsuo 8747 match_len = MatchOneString(x, y, str, len);
1866 zmatsuo 8744 if (match_len == 0) {
1867     result = FALSE;
1868     break;
1869     }
1870     len -= match_len;
1871     if (len == 0) {
1872     // �S���������I������
1873     result = TRUE;
1874     break;
1875     }
1876     str += match_len;
1877    
1878     // ��������
1879     x++;
1880     if (x == NumOfColumns) {
1881     if (LineContinued && ((b->attr & AttrLineContinued) != 0)) {
1882     // �����s��
1883     y++;
1884     if (y == NumOfLines) {
1885     // �o�b�t�@���I�[
1886     return 0;
1887     }
1888     x = 0;
1889     b = &CodeBuffW[GetLinePtr(y)];
1890     } else {
1891     // �s��
1892     result = FALSE;
1893     break;
1894     }
1895     }
1896     }
1897    
1898     return result;
1899     }
1900 zmatsuo 10311 #endif
1901 zmatsuo 8744
1902     /**
1903 doda 8445 * (x,y)���� str��������������
1904     *
1905     * @param x �}�C�i�X�����A�����s������������
1906     * @param y PageStart + CursorY
1907     * @param LineCntinued TRUE=�s���p�����l������
1908     * @retval TRUE �}�b�`����
1909     * @retval FALSE �}�b�`����������
1910     */
1911     static BOOL MatchString(int x, int y, const wchar_t *str, BOOL LineContinued)
1912     {
1913     BOOL result;
1914     int TmpPtr = GetLinePtr(y);
1915     size_t len = wcslen(str);
1916     if (len == 0) {
1917     return FALSE;
1918     }
1919     while(x < 0) {
1920 zmatsuo 8742 if (LineContinued && (CodeBuffW[TmpPtr+0].attr & AttrLineContinued) == 0) {
1921 doda 8445 // �s���p�������������l�� & �p������������
1922     x = 0; // �s������������
1923     break;
1924     }
1925     TmpPtr = PrevLinePtr(TmpPtr);
1926     x += NumOfColumns;
1927     y--;
1928     }
1929     while(x > NumOfColumns) {
1930 zmatsuo 8742 if (LineContinued && (CodeBuffW[TmpPtr+NumOfColumns-1].attr & AttrLineContinued) == 0) {
1931 doda 8445 // �s���p�������������l�� & �p������������
1932     x = 0; // �s������������
1933     break;
1934     }
1935     TmpPtr = NextLinePtr(TmpPtr);
1936     x -= NumOfColumns;
1937     }
1938    
1939     for(;;) {
1940     // 1����������������
1941     size_t match_len = MatchOneString(x, y, str, len);
1942     if (match_len == 0) {
1943     result = FALSE;
1944     break;
1945     }
1946     len -= match_len;
1947     if (len == 0) {
1948     // �S���������I������
1949     result = TRUE;
1950     break;
1951     }
1952     str += match_len;
1953    
1954     // ��������
1955     x++;
1956     if (x == NumOfColumns) {
1957 zmatsuo 8742 if (LineContinued && (CodeBuffW[TmpPtr+NumOfColumns-1].attr & AttrLineContinued) != 0) {
1958 doda 8445 // �����s��
1959     x = 0;
1960     TmpPtr = NextLinePtr(TmpPtr);
1961     y++;
1962     } else {
1963     // �s��
1964     result = FALSE;
1965     break;
1966     }
1967     }
1968     }
1969    
1970     return result;
1971     }
1972    
1973     /**
1974     * (sx,sy)����(ex,ey)������ str ���}�b�`�����������T����
1975     * ���u������
1976     *
1977     * @param sy,ex PageStart + CursorY
1978     * @param[out] x �}�b�`�������u
1979     * @param[out] y �}�b�`�������u
1980     * @retval TRUE �}�b�`����
1981     */
1982     static BOOL BuffGetMatchPosFromString(
1983     int sx, int sy, int ex, int ey, const wchar_t *str,
1984     int *match_x, int *match_y)
1985     {
1986     int IStart, IEnd;
1987     int x, y;
1988    
1989     for (y = sy; y<=ey ; y++) {
1990     IStart = 0;
1991     IEnd = NumOfColumns-1;
1992     if (y== sy) {
1993     IStart = sx;
1994     }
1995     if (y== ey) {
1996     IEnd = ex;
1997     }
1998    
1999     x = IStart;
2000     while (x <= IEnd) {
2001     if (MatchString(x, y, str, TRUE)) {
2002     // �}�b�`����
2003     if (match_x != NULL) {
2004     *match_x = x;
2005     }
2006     if (match_y != NULL) {
2007     *match_y = y;
2008     }
2009     return TRUE;
2010     }
2011     x++;
2012     }
2013     }
2014     return FALSE;
2015     }
2016    
2017    
2018     /**
2019     * �A�������X�y�[�X���^�u1�����u������
2020     * @param[out] _str_len ��������(L'\0'������)
2021     * @return ������
2022     * �g�p���� free() ��������
2023     */
2024     static wchar_t *ConvertTable(const wchar_t *src, size_t src_len, size_t *str_len)
2025     {
2026     wchar_t *dest_top = malloc(sizeof(wchar_t) * src_len);
2027     wchar_t *dest = dest_top;
2028     BOOL WhiteSpace = FALSE;
2029     while (*src != '\0') {
2030     wchar_t c = *src++;
2031     if (c == 0x0d || c == 0x0a) {
2032     *dest++ = c;
2033     WhiteSpace = FALSE;
2034     } else if (c <= L' ') {
2035     if (!WhiteSpace) {
2036     // insert tab
2037     *dest++ = 0x09;
2038     WhiteSpace = TRUE;
2039     }
2040     } else {
2041     *dest++ = c;
2042     WhiteSpace = FALSE;
2043     }
2044     }
2045     *dest = L'\0';
2046     *str_len = dest - dest_top + 1;
2047     return dest_top;
2048     }
2049    
2050    
2051 zmatsuo 8676 /**
2052     * �N���b�v�{�[�h�p����������
2053     * @return ������
2054     * �g�p���� free() ��������
2055     */
2056     wchar_t *BuffCBCopyUnicode(BOOL Table)
2057 doda 8445 {
2058     wchar_t *str_ptr;
2059     size_t str_len;
2060     str_ptr = BuffGetStringForCB(
2061     SelectStart.x, SelectStart.y,
2062     SelectEnd.x, SelectEnd.y, BoxSelect,
2063     &str_len);
2064    
2065     // �e�[�u���`��������
2066     if (Table) {
2067     size_t table_len;
2068     wchar_t *table_ptr = ConvertTable(str_ptr, str_len, &table_len);
2069     free(str_ptr);
2070     str_ptr = table_ptr;
2071     str_len = table_len;
2072     }
2073 zmatsuo 8676 return str_ptr;
2074 doda 8445 }
2075    
2076 maya 3227 void BuffPrint(BOOL ScrollRegion)
2077     // Print screen or selected text
2078     {
2079 maya 3393 int Id;
2080     POINT PrintStart, PrintEnd;
2081 zmatsuo 9040 int j;
2082 maya 3393 int IStart, IEnd;
2083     LONG TmpPtr;
2084 maya 3227
2085 maya 3393 if (ScrollRegion) {
2086     Id = VTPrintInit(IdPrnScrollRegion);
2087     }
2088     else if (Selected) {
2089     Id = VTPrintInit(IdPrnScreen | IdPrnSelectedText);
2090     }
2091     else {
2092     Id = VTPrintInit(IdPrnScreen);
2093     }
2094     if (Id==IdPrnCancel) {
2095     return;
2096     }
2097 maya 3227
2098 maya 3393 /* set print region */
2099     if (Id==IdPrnSelectedText) {
2100     /* print selected region */
2101     PrintStart = SelectStart;
2102     PrintEnd = SelectEnd;
2103     }
2104     else if (Id==IdPrnScrollRegion) {
2105     /* print scroll region */
2106     PrintStart.x = 0;
2107     PrintStart.y = PageStart + CursorTop;
2108     PrintEnd.x = NumOfColumns;
2109     PrintEnd.y = PageStart + CursorBottom;
2110     }
2111     else {
2112     /* print current screen */
2113     PrintStart.x = 0;
2114     PrintStart.y = PageStart;
2115     PrintEnd.x = NumOfColumns;
2116     PrintEnd.y = PageStart + NumOfLines - 1;
2117     }
2118     if (PrintEnd.y > BuffEnd-1) {
2119     PrintEnd.y = BuffEnd-1;
2120     }
2121 maya 3227
2122 maya 3393 LockBuffer();
2123 maya 3227
2124 maya 3393 TmpPtr = GetLinePtr(PrintStart.y);
2125     for (j = PrintStart.y ; j <= PrintEnd.y ; j++) {
2126     if (j==PrintStart.y) {
2127     IStart = PrintStart.x;
2128     }
2129     else {
2130     IStart = 0;
2131     }
2132     if (j == PrintEnd.y) {
2133     IEnd = PrintEnd.x - 1;
2134     }
2135     else {
2136     IEnd = NumOfColumns - 1;
2137     }
2138 maya 3227
2139 zmatsuo 9040 BuffDrawLineIPrn(j, IStart, IEnd);
2140 maya 3393 PrnNewLine();
2141     TmpPtr = NextLinePtr(TmpPtr);
2142     }
2143 maya 3227
2144 maya 3393 UnlockBuffer();
2145     VTPrintEnd();
2146 maya 3227 }
2147    
2148 zmatsuo 8744 // TODO ���������� ANSI ������
2149 maya 3227 // Dumps current line to the file (for path through printing)
2150     // HFile: file handle
2151     // TERM: terminator character
2152     // = LF or VT or FF
2153 zmatsuo 9115 void BuffDumpCurrentLine(PrintFile *handle, BYTE TERM)
2154 maya 3227 {
2155 maya 3393 int i, j;
2156 zmatsuo 8744 buff_char_t *b = &CodeBuffW[LinePtr];
2157     char bufA[TermWidthMax+1];
2158     char *p = bufA;
2159 maya 3227
2160 maya 3393 i = NumOfColumns;
2161 zmatsuo 8744 while ((i>0) && (b[i-1].ansi_char == 0x20)) {
2162 maya 3393 i--;
2163     }
2164 zmatsuo 8744 p = bufA;
2165 maya 3393 for (j=0; j<i; j++) {
2166 zmatsuo 8744 unsigned short c = b[j].ansi_char;
2167     *p++ = (c & 0xff);
2168     if (c > 0x100) {
2169     *p++ = (c & 0xff);
2170     }
2171 maya 3393 }
2172 zmatsuo 8744 p = bufA;
2173     for (j=0; j<i; j++) {
2174 zmatsuo 9115 WriteToPrnFile(handle, bufA[j],FALSE);
2175 zmatsuo 8744 }
2176 zmatsuo 9115 WriteToPrnFile(handle, 0,TRUE);
2177 maya 3393 if ((TERM>=LF) && (TERM<=FF)) {
2178 zmatsuo 9115 WriteToPrnFile(handle, 0x0d,FALSE);
2179     WriteToPrnFile(handle, TERM,TRUE);
2180 maya 3393 }
2181 maya 3227 }
2182    
2183 doda 8445 static BOOL isURLchar(unsigned int u32)
2184     {
2185     // RFC3986(Uniform Resource Identifier (URI): Generic Syntax)����������
2186     // by sakura editor 1.5.2.1: etc_uty.cpp
2187     static const char url_char[] = {
2188     /* +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F */
2189     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* +00: */
2190     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* +10: */
2191     0, -1, 0, -1, -1, -1, -1, 0, 0, 0, 0, -1, -1, -1, -1, -1, /* +20: " !"#$%&'()*+,-./" */
2192     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, 0, -1, /* +30: "0123456789:;<=>?" */
2193     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* +40: "@ABCDEFGHIJKLMNO" */
2194     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, 0, 0, -1, /* +50: "PQRSTUVWXYZ[\]^_" */
2195     0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* +60: "`abcdefghijklmno" */
2196     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, -1, 0, /* +70: "pqrstuvwxyz{|}~ " */
2197     /* 0 : not url char
2198     * -1 : url char
2199     * other: url head char --> url_table array number + 1
2200     */
2201     };
2202 maya 3227
2203 doda 8445 if (u32 >= 0x80) {
2204     return FALSE;
2205     }
2206     return url_char[u32] == 0 ? FALSE : TRUE;
2207     }
2208    
2209 zmatsuo 8798 static BOOL BuffIsHalfWidthFromPropery(const TTTSet *ts_, char width_property)
2210 doda 8445 {
2211     switch (width_property) {
2212     case 'H': // Halfwidth
2213     case 'n': // Narrow
2214     case 'N': // Neutral
2215     default:
2216     return TRUE;
2217     case 'A': // Ambiguous �B��
2218 zmatsuo 8798 if (ts_->UnicodeAmbiguousWidth == 2) {
2219 doda 8445 // �S�p����������
2220     return FALSE;
2221     }
2222     return TRUE;
2223     case 'W':
2224     case 'F':
2225     return FALSE; // �S�p
2226     }
2227     }
2228    
2229 zmatsuo 8766 static BOOL BuffIsHalfWidthFromCode(const TTTSet *ts_, unsigned int u32, char *width_property, char *emoji)
2230 doda 8445 {
2231     *width_property = UnicodeGetWidthProperty(u32);
2232     *emoji = (char)UnicodeIsEmoji(u32);
2233 zmatsuo 8798 if (ts_->UnicodeEmojiOverride) {
2234     if (*emoji) {
2235     // �G��������������
2236 zmatsuo 9462 if (u32 < 0x1f000) {
2237     if (ts_->UnicodeEmojiWidth == 2) {
2238     // �S�p
2239 zmatsuo 8798 return FALSE;
2240     }
2241 zmatsuo 9462 else {
2242     // ���p
2243     return TRUE;
2244     }
2245 doda 8445 }
2246 zmatsuo 9462 else {
2247     // �����S�p
2248     return FALSE;
2249     }
2250 doda 8445 }
2251     }
2252 zmatsuo 8798 return BuffIsHalfWidthFromPropery(ts_, *width_property);
2253 doda 8445 }
2254    
2255     /**
2256     * �J�[�\�����u����URL�A�g���r���[�g�����������������v�Z����
2257     */
2258 zmatsuo 8740 static int get_url_len(int cur_x, int cur_y)
2259 doda 8445 {
2260     int sp = cur_x + cur_y * NumOfColumns;
2261     int cp;
2262     int dp;
2263     {
2264     int p = sp;