debuggeroutbuf<char>::int_type debuggeroutbuf<char>::overflow(int_type ch) { if(ch == traits_type::eof()) return traits_type::eof(); *epptr() = ch; // SJIS? if(-1 == _ismbstrail((const unsigned char *)pbase(), (const unsigned char *)epptr())) { char *lbp; for(lbp = epptr()-1; lbp > pbase(); lbp--) { if(-1 == _ismbslead((const unsigned char *)pbase(), (const unsigned char *)lbp)) { break; } } int _ch = *lbp; *lbp = '\0'; sync(); sputc(_ch); for(lbp++; lbp <= epptr(); lbp++) { sputc(*lbp); } *epptr() = '\0'; } else { *epptr() = '\0'; sync(); sputc(ch); } return traits_type::not_eof(ch); }
int FdoCommonOSUtil::ismbstrail(const unsigned char *string, const unsigned char *current) { #ifdef _WIN32 return _ismbstrail(string, current); #else // _WIN32 return FdoCommonOSUtil::ismbslead(string, current)==-1 ? 0 : -1; #endif }
char sjis_getlastchar(char *s) { if (!s || !*s) { return 0; } if (!_ismbstrail((const unsigned char *)s, s + strlen(s) - 1)) { return s[strlen(s) - 1]; } return 0; }
char* basename(const char* str) { char*p = ((char*)str)+strlen(str)-1; #ifdef SJIS while(p>str && (*p!='\\' || !_ismbstrail((unsigned char *)str, (unsigned char *)p))) #else while(p>str && *p!='\\') #endif p--; if(p>str) return (p+1); else return p; }
// // 末尾に \ を追加 // kjm::_tstring kjm::path::addBackslash(const kjm::_tstring& path) { // MAX_PATH を超えると PathAddBackslash が使えなくなるので、自作 kjm::_tstring result = path; #if defined(_MBCS) if (_ismbstrail((unsigned char *)&result[0], (unsigned char *)&result[result.length() - 1])) { result.push_back(_T('\\')); } else if (*result.rbegin() != _T('\\')) { result.push_back(_T('\\')); } #else if (*result.rbegin() != _T('\\')) { result.push_back(_T('\\')); } #endif return result; }
void CEditView::DrawLine( int nLine, HDC hDC, int x, int y, int xDividerStart ) const { int nLineLen = m_pBuffer->GetLineLength( nLine ); BOOL bUseColor = ( m_pCtrl->UseColorSyntax() && ( nLineLen <= MAXCOL ) ); int nViewCol = m_nLeftIndex; int nBuffColStart = m_pBuffer->ConvertViewColToBufferCol( nLine, nViewCol, FALSE ); int xLeft = x; // highlight this line if appropriate BOOL bHighlight = m_pBuffer->IsHighlighted( nLine ); if ( bHighlight ) { // fill out the rest of the line with the highlight RECT rc = m_rcView; rc.left = x; rc.top = y; rc.bottom = y + m_cyLine; SetBkColor( hDC, m_pCtrl->GetHighlightedLineColor() ); ExtTextOut( hDC, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL ); } BOOL bMBCS = DBCS_ACTIVE; #ifdef _UNICODE int nRightIndex = m_nRightIndex; #else int nRightIndex = m_nRightIndex + bMBCS * 2; // always paint two more TCHARs so multibyte chars aren't truncated #endif if ( nBuffColStart < nLineLen ) // else nothing to draw { // wait for nLine to become available (in case of background syntax parsing) m_pBuffer->WaitForLine( nLine ); LPCTSTR pszLineStart = m_pBuffer->GetLineText( nLine ); register LPCTSTR psz = pszLineStart + nBuffColStart; LPCTSTR pszStart = psz; ////////////////////////////////////////////////////////////////////////// // Step 1: Expand tabs // BOOL bViewWhitespace = m_pCtrl->DisplayWhitespace(); TCHAR szLine[ 1000 ]; CharFill( szLine, _T(' '), ARRAY_SIZE( szLine ) ); int cbTab = m_pBuffer->GetTabSize(); LPTSTR pszBuff = szLine; TCHAR chTab, chSpace; if ( bMBCS ) { chTab = _T('^'); chSpace = _T('`'); } else { chTab = _T('»'); chSpace = _T('·'); } while ( *psz && ( nViewCol <= nRightIndex ) ) { if ( *psz == _T('\t') ) { int nSpaces = ( ( nViewCol / cbTab ) * cbTab ) + cbTab - nViewCol; if ( nSpaces ) { if ( bViewWhitespace ) { if ( psz != pszStart || m_nLeftIndex == m_pBuffer->ConvertBufferColToViewCol( nLine, nBuffColStart ) ) { *pszBuff = chTab; } } pszBuff += nSpaces; nViewCol += nSpaces; } } else { if ( bViewWhitespace && *psz == _T(' ') ) { *pszBuff++ = chSpace; } else { *pszBuff++ = *psz; } nViewCol++; } psz++; } ////////////////////////////////////////////////////////////////////////// // Step 2: Parse the line and assign colors to everything // DWORD clrLine[ 100 ]; // hiword = token, loword = token offset in szLine int nColors = 0; if ( bUseColor ) { psz = pszLineStart; int nParseLen = m_pBuffer->ConvertViewColToBufferCol( nLine, nRightIndex ) + 20; // +20 is a reasonable max token length nParseLen = min( nParseLen, nLineLen ); nViewCol = 0; int nBuffCol = 0; int nFirstColorViewCol = m_nLeftIndex; BOOL bColorIsVisible = nViewCol >= nFirstColorViewCol; CLineParser Parser( m_pBuffer, nLine, nParseLen ); // pick up where the last line left off -- in a multi-line comment block (or not) clrLine[ nColors++ ] = MAKELPARAM( 0, ( WORD ) ( Parser.m_bInComment ? CBuffer::eMultiLineCommentStart : ( Parser.m_bInString ? CBuffer::eStringDelim : ( Parser.m_bInTag ? CBuffer::eTagText : CBuffer::eText ) ) ) ); while ( Parser.MoreComing() ) { Parser.AcceptToken(); int nTokenStartCol = nViewCol; nBuffCol += Parser.m_nTokenLen; if ( Parser.m_bHasTab ) { ASSERT( Parser.m_eToken == CBuffer::eText || Parser.m_eToken == CBuffer::eTagText || Parser.m_eToken == CBuffer::eStringDelim || Parser.m_eToken == CBuffer::eSingleLineComment ); nViewCol = m_pBuffer->ConvertBufferColToViewCol( nLine, nBuffCol ); } else { nViewCol += Parser.m_nTokenLen; } if ( !bColorIsVisible ) { // Assume this token (unless in a comment) will be the first token to cross the left edge clrLine[ 0 ] = MAKELPARAM( 0, ( WORD )( Parser.m_bInComment ? CBuffer::eMultiLineCommentStart : ( Parser.m_bInString ? CBuffer::eStringDelim : Parser.m_eToken ) ) ); if ( nViewCol > nFirstColorViewCol ) { ////////////////////////// // token is now in view // bColorIsVisible = TRUE; nTokenStartCol = nFirstColorViewCol; } } // record the token position if ( nTokenStartCol > nRightIndex ) { break; } if ( bColorIsVisible && !Parser.m_bWasInComment && !Parser.m_bIsCommentEndToken && !Parser.m_bWasInString && !Parser.m_bIsStringEndToken ) { clrLine[ nColors++ ] = MAKELPARAM( nTokenStartCol - m_nLeftIndex, ( WORD ) Parser.m_eToken ); } clrLine[ nColors ] = MAKELPARAM( ( nViewCol > m_nLeftIndex ? nViewCol : nRightIndex ) - m_nLeftIndex, ( WORD ) Parser.m_eToken ); // don't blow past the local array and corrupt the stack! if ( nColors >= ARRAY_SIZE( clrLine ) - 1 ) { nColors = 0; goto no_color; } } } else { no_color: clrLine[ nColors++ ] = MAKELPARAM( 0, ( WORD ) CBuffer::eText ); // draw text only as far as is necessary. We don't want to paint extra characters that aren't // in the buffer. If underline font used on plain text, the underline will extend to the edge of the window. // we don't want that. int nViewColEnd = m_pBuffer->ConvertBufferColToViewCol( nLine, nLineLen ); nViewColEnd = min( nRightIndex, nViewColEnd ); nViewColEnd = max( m_nLeftIndex, nViewColEnd ); clrLine[ nColors ] = MAKELPARAM( nViewColEnd - m_nLeftIndex, ( WORD ) CBuffer::eText ); } ////////////////////////////////////////////////////////////////////////// // Step 3: Output the line // ASSERT( nColors ); BOOL bFirstToken = TRUE; for ( int i = 0; i < nColors; i++ ) { DWORD dwColorInfo = clrLine[ i ]; CBuffer::LangToken eToken = ( CBuffer::LangToken ) HIWORD( dwColorInfo ); SetTextColor( hDC, m_pCtrl->GetTokenColor( eToken, TRUE ) ); COLORREF crBk = bHighlight ? m_pCtrl->GetHighlightedLineColor() : m_pCtrl->GetTokenColor( eToken, FALSE ); if ( crBk != CLR_INVALID ) { SetBkColor( hDC, crBk ); SetBkMode( hDC, OPAQUE ); } else { SetBkMode( hDC, TRANSPARENT ); } long cxExtraSpacing, cyDescentShift; SelectObject( hDC, m_pCtrl->GetTokenFont( eToken, cxExtraSpacing, cyDescentShift, m_pCtrl->m_font ) ); SetTextCharacterExtra( hDC, cxExtraSpacing ); int nTokenStart = LOWORD( dwColorInfo ); int nTokenNext = LOWORD( clrLine[ i + 1 ] ); int cbToken = nTokenNext - nTokenStart; if ( cbToken ) { #ifndef _UNICODE // The first visible token on the left of the line might be cutoff right // in the middle of a multi-byte char. We need to account for this by not // rendering the character (just leave whitespace). if ( bFirstToken && _ismbstrail( ( const unsigned char * ) pszLineStart, ( const unsigned char * ) pszStart ) ) { // scan backwards to the lead byte LPCTSTR pszLead = pszStart; while ( _ismbstrail( ( const unsigned char * ) pszLineStart, ( const unsigned char * ) --pszLead ) ) ; int cbChar = pszStart - pszLead; nTokenStart += cbChar; cbToken -= cbChar; x += ( cbChar * m_cxChar ); } #endif bFirstToken = FALSE; ExtTextOut( hDC, x, y - cyDescentShift, 0, NULL, szLine + nTokenStart, cbToken, NULL ); x += ( cbToken * m_cxChar ); } // don't worry about deselecting the font -- it will be cleaned up by any // calling method (as an optimization) } } ////////////////////////////////////////////////////////////////////////// // Step 4: give the parent window a crack at painting, too. // DWORD dwStyle = m_pBuffer->GetLineStyle( nLine ); if ( HAS_FLAG( dwStyle, CML_OWNERDRAW ) ) { CM_DRAWLINEDATA dld; dld.hDC = hDC; dld.rcLine.left = xLeft; dld.rcLine.top = y; dld.rcLine.right = m_rcView.right; dld.rcLine.bottom = y + m_cyLine; dld.nLine = nLine; dld.nLeftCol = m_nLeftIndex; dld.nRightCol = m_nRightIndex; dld.lParam = m_pBuffer->GetItemData( nLine ); dld.dwStyle = dwStyle; m_pCtrl->NotifyParent( CMN_DRAWLINE, ( NMHDR * ) &dld ); } // Draw divider line underneath the line if appropriate if ( m_pBuffer->HasDivider( nLine ) ) { COLORREF crDividerLine = m_pCtrl->GetHDividerLineColor(); COLORREF crWindow = m_pCtrl->GetWindowColor( TRUE ); // if line will blend in with the background, make it visible (opposite of window color). if ( crDividerLine == CLR_INVALID || crDividerLine == crWindow ) crDividerLine = ( ~crWindow & 0x00ffffff ); HPEN hPen = CreatePen( PS_SOLID, CY_DIVIDERLINE, crDividerLine ); HPEN hPenOld = ( HPEN ) SelectObject( hDC, hPen ); int yLine = y + m_cyLine - 1; MoveToEx( hDC, xDividerStart, yLine, NULL ); LineTo( hDC, m_rcView.right, yLine ); SelectObject( hDC, hPenOld ); DeleteObject( hPen ); } }
static void test_mbcp(void) { int mb_orig_max = *p__mb_cur_max; int curr_mbcp = _getmbcp(); unsigned char *mbstring = (unsigned char *)"\xb0\xb1\xb2 \xb3\xb4 \xb5"; /* incorrect string */ unsigned char *mbstring2 = (unsigned char *)"\xb0\xb1\xb2\xb3Q\xb4\xb5"; /* correct string */ unsigned char *mbsonlylead = (unsigned char *)"\xb0\0\xb1\xb2 \xb3"; unsigned char buf[16]; int step; /* _mbtype tests */ /* An SBCS codepage test. The ctype of characters on e.g. CP1252 or CP1250 differs slightly * between versions of Windows. Also Windows 9x seems to ignore the codepage and always uses * CP1252 (or the ACP?) so we test only a few ASCII characters */ _setmbcp(1252); expect_eq(p_mbctype[10], 0, char, "%x"); expect_eq(p_mbctype[50], 0, char, "%x"); expect_eq(p_mbctype[66], _SBUP, char, "%x"); expect_eq(p_mbctype[100], _SBLOW, char, "%x"); expect_eq(p_mbctype[128], 0, char, "%x"); _setmbcp(1250); expect_eq(p_mbctype[10], 0, char, "%x"); expect_eq(p_mbctype[50], 0, char, "%x"); expect_eq(p_mbctype[66], _SBUP, char, "%x"); expect_eq(p_mbctype[100], _SBLOW, char, "%x"); expect_eq(p_mbctype[128], 0, char, "%x"); /* double byte code pages */ test_codepage(932); test_codepage(936); test_codepage(949); test_codepage(950); _setmbcp(936); ok(*p__mb_cur_max == mb_orig_max, "__mb_cur_max shouldn't be updated (is %d != %d)\n", *p__mb_cur_max, mb_orig_max); ok(_ismbblead('\354'), "\354 should be a lead byte\n"); ok(_ismbblead(' ') == FALSE, "' ' should not be a lead byte\n"); ok(_ismbblead(0x1234b0), "0x1234b0 should not be a lead byte\n"); ok(_ismbblead(0x123420) == FALSE, "0x123420 should not be a lead byte\n"); ok(_ismbbtrail('\xb0'), "\xa0 should be a trail byte\n"); ok(_ismbbtrail(' ') == FALSE, "' ' should not be a trail byte\n"); /* _ismbslead */ expect_eq(_ismbslead(mbstring, &mbstring[0]), -1, int, "%d"); expect_eq(_ismbslead(mbstring, &mbstring[1]), FALSE, int, "%d"); expect_eq(_ismbslead(mbstring, &mbstring[2]), -1, int, "%d"); expect_eq(_ismbslead(mbstring, &mbstring[3]), FALSE, int, "%d"); expect_eq(_ismbslead(mbstring, &mbstring[4]), -1, int, "%d"); expect_eq(_ismbslead(mbstring, &mbstring[5]), FALSE, int, "%d"); expect_eq(_ismbslead(mbstring, &mbstring[6]), FALSE, int, "%d"); expect_eq(_ismbslead(mbstring, &mbstring[7]), -1, int, "%d"); expect_eq(_ismbslead(mbstring, &mbstring[8]), FALSE, int, "%d"); expect_eq(_ismbslead(mbsonlylead, &mbsonlylead[0]), -1, int, "%d"); expect_eq(_ismbslead(mbsonlylead, &mbsonlylead[1]), FALSE, int, "%d"); expect_eq(_ismbslead(mbsonlylead, &mbsonlylead[2]), FALSE, int, "%d"); expect_eq(_ismbslead(mbsonlylead, &mbsonlylead[5]), FALSE, int, "%d"); /* _ismbstrail */ expect_eq(_ismbstrail(mbstring, &mbstring[0]), FALSE, int, "%d"); expect_eq(_ismbstrail(mbstring, &mbstring[1]), -1, int, "%d"); expect_eq(_ismbstrail(mbstring, &mbstring[2]), FALSE, int, "%d"); expect_eq(_ismbstrail(mbstring, &mbstring[3]), -1, int, "%d"); expect_eq(_ismbstrail(mbstring, &mbstring[4]), FALSE, int, "%d"); expect_eq(_ismbstrail(mbstring, &mbstring[5]), -1, int, "%d"); expect_eq(_ismbstrail(mbstring, &mbstring[6]), FALSE, int, "%d"); expect_eq(_ismbstrail(mbstring, &mbstring[7]), FALSE, int, "%d"); expect_eq(_ismbstrail(mbstring, &mbstring[8]), -1, int, "%d"); expect_eq(_ismbstrail(mbsonlylead, &mbsonlylead[0]), FALSE, int, "%d"); expect_eq(_ismbstrail(mbsonlylead, &mbsonlylead[1]), -1, int, "%d"); expect_eq(_ismbstrail(mbsonlylead, &mbsonlylead[2]), FALSE, int, "%d"); expect_eq(_ismbstrail(mbsonlylead, &mbsonlylead[3]), FALSE, int, "%d"); expect_eq(_ismbstrail(mbsonlylead, &mbsonlylead[4]), FALSE, int, "%d"); expect_eq(_ismbstrail(mbsonlylead, &mbsonlylead[5]), FALSE, int, "%d"); /* _mbsbtype */ expect_eq(_mbsbtype(mbstring, 0), _MBC_LEAD, int, "%d"); expect_eq(_mbsbtype(mbstring, 1), _MBC_TRAIL, int, "%d"); expect_eq(_mbsbtype(mbstring, 2), _MBC_LEAD, int, "%d"); expect_eq(_mbsbtype(mbstring, 3), _MBC_ILLEGAL, int, "%d"); expect_eq(_mbsbtype(mbstring, 4), _MBC_LEAD, int, "%d"); expect_eq(_mbsbtype(mbstring, 5), _MBC_TRAIL, int, "%d"); expect_eq(_mbsbtype(mbstring, 6), _MBC_SINGLE, int, "%d"); expect_eq(_mbsbtype(mbstring, 7), _MBC_LEAD, int, "%d"); expect_eq(_mbsbtype(mbstring, 8), _MBC_ILLEGAL, int, "%d"); expect_eq(_mbsbtype(mbsonlylead, 0), _MBC_LEAD, int, "%d"); expect_eq(_mbsbtype(mbsonlylead, 1), _MBC_ILLEGAL, int, "%d"); expect_eq(_mbsbtype(mbsonlylead, 2), _MBC_ILLEGAL, int, "%d"); expect_eq(_mbsbtype(mbsonlylead, 3), _MBC_ILLEGAL, int, "%d"); expect_eq(_mbsbtype(mbsonlylead, 4), _MBC_ILLEGAL, int, "%d"); expect_eq(_mbsbtype(mbsonlylead, 5), _MBC_ILLEGAL, int, "%d"); /* _mbsnextc */ expect_eq(_mbsnextc(mbstring), 0xb0b1, int, "%x"); expect_eq(_mbsnextc(&mbstring[2]), 0xb220, int, "%x"); /* lead + invalid tail */ expect_eq(_mbsnextc(&mbstring[3]), 0x20, int, "%x"); /* single char */ /* _mbclen/_mbslen */ expect_eq(_mbclen(mbstring), 2, int, "%d"); expect_eq(_mbclen(&mbstring[2]), 2, int, "%d"); expect_eq(_mbclen(&mbstring[3]), 1, int, "%d"); expect_eq(_mbslen(mbstring2), 4, int, "%d"); expect_eq(_mbslen(mbsonlylead), 0, int, "%d"); /* lead + NUL not counted as character */ expect_eq(_mbslen(mbstring), 4, int, "%d"); /* lead + invalid trail counted */ /* _mbccpy/_mbsncpy */ memset(buf, 0xff, sizeof(buf)); _mbccpy(buf, mbstring); expect_bin(buf, "\xb0\xb1\xff", 3); memset(buf, 0xff, sizeof(buf)); _mbsncpy(buf, mbstring, 1); expect_bin(buf, "\xb0\xb1\xff", 3); memset(buf, 0xff, sizeof(buf)); _mbsncpy(buf, mbstring, 2); expect_bin(buf, "\xb0\xb1\xb2 \xff", 5); memset(buf, 0xff, sizeof(buf)); _mbsncpy(buf, mbstring, 3); expect_bin(buf, "\xb0\xb1\xb2 \xb3\xb4\xff", 7); memset(buf, 0xff, sizeof(buf)); _mbsncpy(buf, mbstring, 4); expect_bin(buf, "\xb0\xb1\xb2 \xb3\xb4 \xff", 8); memset(buf, 0xff, sizeof(buf)); _mbsncpy(buf, mbstring, 5); expect_bin(buf, "\xb0\xb1\xb2 \xb3\xb4 \0\0\xff", 10); memset(buf, 0xff, sizeof(buf)); _mbsncpy(buf, mbsonlylead, 6); expect_bin(buf, "\0\0\0\0\0\0\0\xff", 8); memset(buf, 0xff, sizeof(buf)); _mbsnbcpy(buf, mbstring2, 2); expect_bin(buf, "\xb0\xb1\xff", 3); _mbsnbcpy(buf, mbstring2, 3); expect_bin(buf, "\xb0\xb1\0\xff", 4); _mbsnbcpy(buf, mbstring2, 4); expect_bin(buf, "\xb0\xb1\xb2\xb3\xff", 5); memset(buf, 0xff, sizeof(buf)); _mbsnbcpy(buf, mbsonlylead, 5); expect_bin(buf, "\0\0\0\0\0\xff", 6); /* _mbsinc/mbsdec */ step = _mbsinc(mbstring) - mbstring; ok(step == 2, "_mbsinc adds %d (exp. 2)\n", step); step = _mbsinc(&mbstring[2]) - &mbstring[2]; /* lead + invalid tail */ ok(step == 2, "_mbsinc adds %d (exp. 2)\n", step); step = _mbsninc(mbsonlylead, 1) - mbsonlylead; ok(step == 0, "_mbsninc adds %d (exp. 0)\n", step); step = _mbsninc(mbsonlylead, 2) - mbsonlylead; /* lead + NUL byte + lead + char */ ok(step == 0, "_mbsninc adds %d (exp. 0)\n", step); step = _mbsninc(mbstring2, 0) - mbstring2; ok(step == 0, "_mbsninc adds %d (exp. 2)\n", step); step = _mbsninc(mbstring2, 1) - mbstring2; ok(step == 2, "_mbsninc adds %d (exp. 2)\n", step); step = _mbsninc(mbstring2, 2) - mbstring2; ok(step == 4, "_mbsninc adds %d (exp. 4)\n", step); step = _mbsninc(mbstring2, 3) - mbstring2; ok(step == 5, "_mbsninc adds %d (exp. 5)\n", step); step = _mbsninc(mbstring2, 4) - mbstring2; ok(step == 7, "_mbsninc adds %d (exp. 7)\n", step); step = _mbsninc(mbstring2, 5) - mbstring2; ok(step == 7, "_mbsninc adds %d (exp. 7)\n", step); step = _mbsninc(mbstring2, 17) - mbstring2; ok(step == 7, "_mbsninc adds %d (exp. 7)\n", step); /* functions that depend on locale codepage, not mbcp. * we hope the current locale to be SBCS because setlocale(LC_ALL, ".1252") seems not to work yet * (as of Wine 0.9.43) */ if (*p__mb_cur_max == 1) { expect_eq(mblen((char *)mbstring, 3), 1, int, "%x"); expect_eq(_mbstrlen((char *)mbstring2), 7, int, "%d"); }