clienti18n.cc #1

  • //
  • guest/
  • perforce_software/
  • p4/
  • client/
  • clienti18n.cc
  • View
  • Commits
  • Open Download .zip Download (10 KB)
/*
 * Copyright 1995, 1996 Perforce Software.  All rights reserved.
 *
 * This file is part of Perforce - the FAST SCM System.
 */

# include <stdhdrs.h>

# include <debug.h>
# include <strbuf.h>
# include <strdict.h>
# include <strtable.h>
# include <error.h>
# include <i18napi.h>
# include <charset.h>
# include <charcvt.h>
# include <transdict.h>
# include <options.h>
# include <handler.h>
# include <rpc.h>
# include <ident.h>
# include <enviro.h>

# include <filesys.h>

# include <msgclient.h>
# include <p4tags.h>

# include "clientuser.h"
# include "clientservice.h"
# include "clientmerge.h"
# include "client.h"
# include "regexp.h"

void
Client::SetTrans( int output,
		  int content,
		  int fnames,
		  int dialog )
{
	CharSetCvt *converter = NULL;

	if (dialog == -2)
	    dialog = output;
	if (content == -2)
	    content = output;
	if (fnames == -2)
	    fnames = content;

	// if we were already in unicode mode, take that down
	if( is_unicode )
	    CleanupTrans();

	// if all args are 0, disable translation
	if( !( output | content | fnames | dialog ) )
	{
	    content_charset = 0;
	    GlobalCharSet::Set( 0 );
	    return;
	}

	// we are in unicode mode now...
	is_unicode = 1;

	enviro->SetCharSet(output);
	content_charset = content;
	output_charset = output;
	GlobalCharSet::Set(fnames);
	// our concept of current directory could change at this point
	cwd = "";
	enviro->Config( GetCwd() );

	if (output != 0)
	{
	    converter = CharSetCvt::FindCvt( CharSetCvt::UTF_8,
				     (CharSetCvt::CharSet)output );
	    if (converter)
	    {
                    // TransDict will delete the converter
		translated = new TransDict( this, converter );
                if (fnames == output)
                    transfname = translated;
	    }
	}
	if ( fnames != 0 && fnames != output)
	{
	    converter = CharSetCvt::FindCvt( CharSetCvt::UTF_8,
				     (CharSetCvt::CharSet)fnames );
	    if (converter)
	    {
                    // TransDict will delete the converter
		transfname = new TransDict( this, converter );
 	    }
	}
	if ( dialog != 0 )
	{
	    fromTransDialog = CharSetCvt::FindCvt( CharSetCvt::UTF_8,
					 (CharSetCvt::CharSet)dialog );
	    if (fromTransDialog)
		toTransDialog = fromTransDialog->ReverseCvt();
	}
}

void
Client::CleanupTrans()
{
	if (transfname != this && transfname != translated)
	    delete transfname;
	if (translated != this)
	    delete translated;

	translated = this;
	transfname = this;

        delete fromTransDialog;
	delete toTransDialog;
	fromTransDialog = toTransDialog = NULL;

	is_unicode = 0;
	content_charset = 0;
	output_charset = 0;
 	enviro->SetCharSet( 0 );
}

int Client::ContentCharset()
{
	// Content charset is overridden by server-provided charset if present

	StrPtr *charset = GetVar( P4Tag::v_charset );

	return charset ? charset->Atoi() : content_charset;
}

#if defined ( OS_MACOSX )

int
Client::GuessCharset()
{
        return CharSetApi::UTF_8;
}

#elif defined ( OS_NT )

#include <windows.h>


// these next two routines attempt to determine if the app is a console app
bool
ReadBytes(HANDLE hFile,
          LPVOID buffer,
          DWORD  size)
{
    DWORD bytes;

    if (!ReadFile(hFile,
                  buffer,
                  size,
                  &bytes,
                  NULL))
    {
        return false;
    }
    else if (size != bytes)
    {
        return false;
    }
    return true;
}

// http://www.devx.com/tips/Tip/33584
static bool
UseOEMCodePage()
{
        DWORD nameLength;
        char  nameBuf[256];
        HANDLE hImage;

        DWORD  bytes;
        DWORD  iSection;
        DWORD  SectionOffset;
        DWORD  CoffHeaderOffset;
        DWORD  MoreDosHeader[16];

        ULONG  ntSignature;

        IMAGE_DOS_HEADER      image_dos_header;
        IMAGE_FILE_HEADER     image_file_header;
        IMAGE_OPTIONAL_HEADER image_optional_header;
        IMAGE_SECTION_HEADER  image_section_header;

        nameLength = GetModuleFileName(NULL, nameBuf, 256);
        if (! nameLength || nameLength >= 256)
            return true;
        /*
         *  Open the reference file.
         */ 
         hImage = CreateFile(nameBuf,
                        GENERIC_READ,
                        FILE_SHARE_READ,
                        NULL,
                        OPEN_EXISTING,
                        FILE_ATTRIBUTE_NORMAL,
                        NULL);

        if (INVALID_HANDLE_VALUE == hImage)
            return true;
        /*
         *  Read the MS-DOS image header.
         */ 
        if (! ReadBytes(hImage,
                &image_dos_header,
                sizeof(IMAGE_DOS_HEADER)))
            return true;

        if (IMAGE_DOS_SIGNATURE != image_dos_header.e_magic)
            return true;

        /*
        *  Read more MS-DOS header.       */ 
        if (! ReadBytes(hImage,
                MoreDosHeader,
                sizeof(MoreDosHeader)))
            return true;

        /*
         *  Get actual COFF header.
         */ 
        CoffHeaderOffset = SetFilePointer(hImage, image_dos_header.e_lfanew,
                                          NULL,
                                          FILE_BEGIN);
        if (CoffHeaderOffset == 0xFFFFFFFF)
            return true;

        CoffHeaderOffset += sizeof(ULONG);

        if (! ReadBytes (hImage, &ntSignature, sizeof(ULONG)))
            return true;

        if (IMAGE_NT_SIGNATURE != ntSignature)
            return true;

        SectionOffset = CoffHeaderOffset + IMAGE_SIZEOF_FILE_HEADER +
                    sizeof(image_optional_header);

        if (! ReadBytes(hImage,
              &image_file_header,
              IMAGE_SIZEOF_FILE_HEADER))
            return true;

        /*
         *  Read optional header.
         */ 
        if (!ReadBytes(hImage,
              &image_optional_header,
              sizeof(image_optional_header)))
            return true;

        if (image_optional_header.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI)
            return false;
        return true;
}

int
Client::GuessCharset()
{
        UINT codePage;
        if (UseOEMCodePage()) // for console apps
            codePage = GetOEMCP();
        else
            codePage = GetACP();
        
        switch (codePage)
        {
            case 437:   return CharSetApi::WIN_US_OEM;
//            case 737:   return CharSetApi::CP737;	// problems
            case 850:   return CharSetApi::CP850;
            case 858:   return CharSetApi::CP858;
            case 932:   return CharSetApi::SHIFTJIS;
            case 936:   return CharSetApi::CP936;
            case 949:   return CharSetApi::CP949;
            case 950:   return CharSetApi::CP950;
            case 1200:  return CharSetApi::UTF_16_LE_BOM;
            case 1201:  return CharSetApi::UTF_16_BE_BOM;
            case 1251:  return CharSetApi::WIN_CP_1251;
            case 1252:  return CharSetApi::WIN_US_ANSI;
            case 1253:  return CharSetApi::CP1253;
            case 10000: return CharSetApi::MACOS_ROMAN;
            case 12000: return CharSetApi::UTF_32_LE_BOM;
            case 12001: return CharSetApi::UTF_32_BE_BOM;
            case 20866: return CharSetApi::KOI8_R;
            case 20932: return CharSetApi::EUCJP;
            case 28591: return CharSetApi::ISO8859_1;
            case 28595: return CharSetApi::ISO8859_5;
            case 28605: return CharSetApi::ISO8859_15;
            case 65001: return CharSetApi::UTF_8;
            default:    return 0;
        }
}


#elif ( defined ( OS_LINUX )   || \
        defined ( OS_FREEBSD ) || \
        defined ( OS_SOLARIS ) || \
        defined ( OS_NETBSD )  )


int
Client::GuessCharset()
{
        const char *setInEnv = enviro->Get( "LANG" );

        if( !setInEnv )
            return 0;

        int begin = 0;
	int len = strlen( setInEnv );

        // if it is just set to C, use UTF_8
        if (len == 1 && setInEnv[0] == 'C')
            return CharSetApi::UTF_8;

        // Now we search for this pattern
        // [language[_territory][.codeset][@modifier]]
        // See http://osr507doc.sco.com/en/man/html.M/locale.M.html
        // We are interested in the codeset so look for '.'
        for (begin=0; begin<len; begin++)
        {
            if (setInEnv[begin] == '.')
                break;
        }

        // modifier is optional
        if (begin < len)
        {
            int end;
            begin++;

            for(end=begin; end<len; end++)
            {
                if (setInEnv[end] == '@')
                    break;
            }
            
            StrBuf charset;
            charset.Set(&(setInEnv[begin]), end-begin);

            if (!StrPtr::CCompare(charset.Text(), "ISO8859-1"))
                return CharSetApi::ISO8859_1;
            if (!StrPtr::CCompare(charset.Text(), "ISO8859-5"))
                return CharSetApi::ISO8859_5;
            if (!StrPtr::CCompare(charset.Text(), "ISO8859-7"))
                return CharSetApi::ISO8859_7;
            if (!StrPtr::CCompare(charset.Text(), "ISO8859-15"))
                return CharSetApi::ISO8859_15;
            if (!StrPtr::CCompare(charset.Text(), "JISX0201.1976-0"))
                return CharSetApi::SHIFTJIS;
            if (!StrPtr::CCompare(charset.Text(), "JISX0208.1983-0"))
                return CharSetApi::SHIFTJIS;
            if (!StrPtr::CCompare(charset.Text(), "EUC-JP"))
                return CharSetApi::EUCJP;
            if (!StrPtr::CCompare(charset.Text(), "UTF-8"))
                return CharSetApi::UTF_8;
            if (!StrPtr::CCompare(charset.Text(), "GB2312.1980-0"))
                return CharSetApi::CP936;
            if (!StrPtr::CCompare(charset.Text(), "GB18030"))
                return CharSetApi::CP936;
            if (!StrPtr::CCompare(charset.Text(), "KSC5601.1987-0"))
                return CharSetApi::CP949;
        }

        return 0;
}

#else

int
Client::GuessCharset()
{
	return CharSetApi::UTF_8;
}
#endif
# Change User Description Committed
#2 12188 Matt Attaway Move 'main' p4 into a release specific directory in prep for new releases
#1 9129 Matt Attaway Initial commit of the 2014.1 p4/p4api source code