分页: 1 / 8

洗干净Wine补丁的尝试,请爱好者和Linux编程高手进

发表于 : 2008-11-22 22:42
xrfang
第四页49楼更新,提供了打过提交官方备选的2#补丁的gdi32.dll.so。请大家试用反馈,争取这个补丁被早日融合到wine中!

我每2个星期就要给wine打一次补丁,有点不胜其烦。看了置顶帖的召集很感兴趣,就对目前使用的补丁做了一点分析。我不懂Linux编程,权当抛砖引玉。希望我们的努力能够为Wine官方接受。

首先,我们来看一下那个补丁的详情,依我看来,它并不太脏,只是有一点点脏。

代码: 全选

1    if(lf.lfCharSet == DEFAULT_CHARSET || lf.lfCharSet == ANSI_CHARSET) {
2     int codepage = 936; /* I'm Chinese. Let me do something selfish. */
3      char *env_wdc = getenv("WINE_DEFAULT_CODEPAGE");
4      if(env_wdc != NULL) {
5        codepage = atoi(env_wdc);
6      }
7      FIXME("Dirty hack. Default and ansi charset is translated to getenv(\"WINE_DEFAULT_CODEPAGE\")\n");
8      if(!TranslateCharsetInfo((DWORD*)(INT_PTR)codepage, &csi, TCI_SRCCODEPAGE)) {
9        FIXME("OMG. Even this dirty hack doesn't work.  Let's PRAY.\n");
10       csi.fs.fsCsb[0] = 0; 
11     }
12     lf.lfCharSet = csi.ciCharset;
13  } else if(!TranslateCharsetInfo((DWORD*)(INT_PTR)lf.lfCharSet, &csi, TCI_SRCCHARSET)) {
14      switch(lf.lfCharSet) {
15	    case DEFAULT_CHARSET:
16	      csi.fs.fsCsb[0] = 0;
17	      break;
18      default:
19	        FIXME("Untranslated charset %d\n", lf.lfCharSet);
20	        csi.fs.fsCsb[0] = 0;
21	        break;
22	    }
23  }
我们所谈论的补丁是第1行到第13行的else为止的部分。“脏”的地方有2个:

1)默认codepage=936,这个可能对其他非中文用户产生影响。
2)虽然后面定义了WINE_DEFAULT_CODEPAGE,但为时已晚,因为这个分支对所有的lfCharset == DEFAULT_CHARSET和lfCharset == ANSI_CHARSET都做了处理,而不进入WINE原版程序的TranslateCharsetInfo((DWORD*)(INT_PTR)lf.lfCharSet...)函数。

我的设想是,我们利用WINE_DEFAULT_CODEPAGE这个参数,如果这个参数没有设置,我们依照Wine原始的逻辑处理,如果设置了,我们就依照这个codepage处理。代码如下:

代码: 全选

    int codepage = 0;
    char *env_wdc = getenv("WINE_DEFAULT_CODEPAGE");
    if(env_wdc != NULL) 
      codepage = atoi(env_wdc);
    if((codepage != 0) && (lf.lfCharSet == DEFAULT_CHARSET || lf.lfCharSet == ANSI_CHARSET)) {
      FIXME("WINE_DEFAULT_CODEPAGE=%d, overriding lfCharSet\n", codepage);
      if(!TranslateCharsetInfo((DWORD*)(INT_PTR)codepage, &csi, TCI_SRCCODEPAGE)) {
        FIXME("OMG. Even this hack doesn't work.  Let's PRAY.\n");
        csi.fs.fsCsb[0] = 0; 
      }
      lf.lfCharSet = csi.ciCharset;
    } else if(!TranslateCharsetInfo((DWORD*)(INT_PTR)lf.lfCharSet, &csi, TCI_SRCCHARSET)) {
        switch(lf.lfCharSet) {
	      case DEFAULT_CHARSET:
	        csi.fs.fsCsb[0] = 0;
	        break;
	      default:
	        FIXME("Untranslated charset %d\n", lf.lfCharSet);
	        csi.fs.fsCsb[0] = 0;
	        break;
	    }
    }
这个简单的改动使得只有WINE_DEFAULT_CODEPAGE被设置的情况下,才按照他来TranslateCharsetInfo,这样我觉得就做到了和原来代码的兼容。对于我们中文用户,只要在系统某个文件比如/etc/profile中export WINE_DEFAULT_CODEPAGE=936就可以实现中文兼容了。

不知我这个方案可行否?请Linux编程高手指导。我对Linux程序的理解仅限于当年大学一年级用HPUX学C语言,以及对man page的阅读。至于为什么要lf.lfCharSet = csi.ciCharset;诸如此类的问题,我就比较迷糊了。 :em04

Re: 洗干净Wine补丁的尝试,请爱好者和Linux编程高手进

发表于 : 2008-11-23 1:04
windowssux
好啊,顶上!!

Re: 洗干净Wine补丁的尝试,请爱好者和Linux编程高手进

发表于 : 2008-11-23 10:45
xrfang
我个人的测试是成功的。但有一个程序,和讯股道,即原来的飞狐交易师,死活显示不正常。希望懂windows font原理的大师解惑,以便大家可以群策群力给出较好的中文解决方案。我个人认为没有必要使用“自动字符集判断”。看看下面两个图:

Re: 洗干净Wine补丁的尝试,请爱好者和Linux编程高手进

发表于 : 2008-11-23 11:38
dkeehl
纯支持

第一张图中程序似乎选择了一个不含中文字符的字体

Re: 洗干净Wine补丁的尝试,请爱好者和Linux编程高手进

发表于 : 2008-11-23 12:16
yinliang108
飞狐交易师可以在字体设置里选择已有的字体。

Re: 洗干净Wine补丁的尝试,请爱好者和Linux编程高手进

发表于 : 2008-11-23 13:15
xrfang
yinliang108 写了:飞狐交易师可以在字体设置里选择已有的字体。
果真如此!没想到这么简单就可以解决。谢谢楼上和楼上的楼上。

Re: 洗干净Wine补丁的尝试,请爱好者和Linux编程高手进

发表于 : 2008-11-23 18:31
aaawhale
怎么使用啊,我不懂编程啊

Re: 洗干净Wine补丁的尝试,请爱好者和Linux编程高手进

发表于 : 2008-11-24 7:27
xrfang
aaawhale 写了:怎么使用啊,我不懂编程啊
如不懂编程,直接使用置顶贴的文件就可以了 :em09 这个帖子的期望目的在于使这个补丁被wine官方所接受。我们先探讨一个最佳解决方案。

Re: 洗干净Wine补丁的尝试,请爱好者和Linux编程高手进

发表于 : 2008-11-25 10:55
the_Fm
这样不行,稍微变换下,等我研究下不过要看WINE如何配置。我对WINE的配置不是很了解。
一会用vc测试下1.1.9的EFAULT_CODEPAGE问题。

Re: 洗干净Wine补丁的尝试,请爱好者和Linux编程高手进

发表于 : 2008-11-25 11:59
xrfang
the_Fm 写了:这样不行,稍微变换下,等我研究下不过要看WINE如何配置。我对WINE的配置不是很了解。
一会用vc测试下1.1.9的EFAULT_CODEPAGE问题。
我用GCC测试过getenv()没有问题,另外,我自己在用这个修改过的补丁是可以的。不知LS说的不行是什么东西,期待你测试完了以后详加说明...

Re: 洗干净Wine补丁的尝试,请爱好者和Linux编程高手进

发表于 : 2008-11-25 13:09
the_Fm
xrfang 写了:
the_Fm 写了:这样不行,稍微变换下,等我研究下不过要看WINE如何配置。我对WINE的配置不是很了解。
一会用vc测试下1.1.9的EFAULT_CODEPAGE问题。
我用GCC测试过getenv()没有问题,另外,我自己在用这个修改过的补丁是可以的。不知LS说的不行是什么东西,期待你测试完了以后详加说明...
我的理解的dirty不是pageocde在前面设置了的问题。而是对 DEFAULT的修改。所以要读下代码。

Re: 洗干净Wine补丁的尝试,请爱好者和Linux编程高手进

发表于 : 2008-11-25 18:36
xrfang
the_Fm 写了:
xrfang 写了:
the_Fm 写了:这样不行,稍微变换下,等我研究下不过要看WINE如何配置。我对WINE的配置不是很了解。
一会用vc测试下1.1.9的EFAULT_CODEPAGE问题。
我用GCC测试过getenv()没有问题,另外,我自己在用这个修改过的补丁是可以的。不知LS说的不行是什么东西,期待你测试完了以后详加说明...
我的理解的dirty不是pageocde在前面设置了的问题。而是对 DEFAULT的修改。所以要读下代码。
这就是我说的第二个问题。我改动的代码解决了这个问题--只有特定条件下才修改default

Re: 洗干净Wine补丁的尝试,请爱好者和Linux编程高手进

发表于 : 2008-11-26 2:12
hzhr
什么脏不脏,这个补丁没有找到问题的所在,肯定不会被接受。

需要修正的函数是 GdiGetCodePage,当用DEFAULT_CHARSET或ANSI_CHARSET创建字体、GDI选择这个字体后,GdiGetCodePage应该返回的codepage是936,而现在的返回codepage是有问题的。

等有时间了我来提交一个补丁吧。

xrfang 写了:我每2个星期就要给wine打一次补丁,有点不胜其烦。看了置顶帖的召集很感兴趣,就对目前使用的补丁做了一点分析。我不懂Linux编程,权当抛砖引玉。希望我们的努力能够为Wine官方接受。

首先,我们来看一下那个补丁的详情,依我看来,它并不太脏,只是有一点点脏。

代码: 全选

1    if(lf.lfCharSet == DEFAULT_CHARSET || lf.lfCharSet == ANSI_CHARSET) {
2     int codepage = 936; /* I'm Chinese. Let me do something selfish. */
3      char *env_wdc = getenv("WINE_DEFAULT_CODEPAGE");
4      if(env_wdc != NULL) {
5        codepage = atoi(env_wdc);
6      }
7      FIXME("Dirty hack. Default and ansi charset is translated to getenv(\"WINE_DEFAULT_CODEPAGE\")\n");
8      if(!TranslateCharsetInfo((DWORD*)(INT_PTR)codepage, &csi, TCI_SRCCODEPAGE)) {
9        FIXME("OMG. Even this dirty hack doesn't work.  Let's PRAY.\n");
10       csi.fs.fsCsb[0] = 0; 
11     }
12     lf.lfCharSet = csi.ciCharset;
13  } else if(!TranslateCharsetInfo((DWORD*)(INT_PTR)lf.lfCharSet, &csi, TCI_SRCCHARSET)) {
14      switch(lf.lfCharSet) {
15	    case DEFAULT_CHARSET:
16	      csi.fs.fsCsb[0] = 0;
17	      break;
18      default:
19	        FIXME("Untranslated charset %d\n", lf.lfCharSet);
20	        csi.fs.fsCsb[0] = 0;
21	        break;
22	    }
23  }
我们所谈论的补丁是第1行到第13行的else为止的部分。“脏”的地方有2个:

1)默认codepage=936,这个可能对其他非中文用户产生影响。
2)虽然后面定义了WINE_DEFAULT_CODEPAGE,但为时已晚,因为这个分支对所有的lfCharset == DEFAULT_CHARSET和lfCharset == ANSI_CHARSET都做了处理,而不进入WINE原版程序的TranslateCharsetInfo((DWORD*)(INT_PTR)lf.lfCharSet...)函数。

我的设想是,我们利用WINE_DEFAULT_CODEPAGE这个参数,如果这个参数没有设置,我们依照Wine原始的逻辑处理,如果设置了,我们就依照这个codepage处理。代码如下:

代码: 全选

    int codepage = 0;
    char *env_wdc = getenv("WINE_DEFAULT_CODEPAGE");
    if(env_wdc != NULL) 
      codepage = atoi(env_wdc);
    if((codepage != 0) && (lf.lfCharSet == DEFAULT_CHARSET || lf.lfCharSet == ANSI_CHARSET)) {
      FIXME("WINE_DEFAULT_CODEPAGE=%d, overriding lfCharSet\n", codepage);
      if(!TranslateCharsetInfo((DWORD*)(INT_PTR)codepage, &csi, TCI_SRCCODEPAGE)) {
        FIXME("OMG. Even this hack doesn't work.  Let's PRAY.\n");
        csi.fs.fsCsb[0] = 0; 
      }
      lf.lfCharSet = csi.ciCharset;
    } else if(!TranslateCharsetInfo((DWORD*)(INT_PTR)lf.lfCharSet, &csi, TCI_SRCCHARSET)) {
        switch(lf.lfCharSet) {
	      case DEFAULT_CHARSET:
	        csi.fs.fsCsb[0] = 0;
	        break;
	      default:
	        FIXME("Untranslated charset %d\n", lf.lfCharSet);
	        csi.fs.fsCsb[0] = 0;
	        break;
	    }
    }
这个简单的改动使得只有WINE_DEFAULT_CODEPAGE被设置的情况下,才按照他来TranslateCharsetInfo,这样我觉得就做到了和原来代码的兼容。对于我们中文用户,只要在系统某个文件比如/etc/profile中export WINE_DEFAULT_CODEPAGE=936就可以实现中文兼容了。

不知我这个方案可行否?请Linux编程高手指导。我对Linux程序的理解仅限于当年大学一年级用HPUX学C语言,以及对man page的阅读。至于为什么要lf.lfCharSet = csi.ciCharset;诸如此类的问题,我就比较迷糊了。 :em04

Re: 洗干净Wine补丁的尝试,请爱好者和Linux编程高手进

发表于 : 2008-11-26 3:13
gcell
等楼上的好消息!!!

Re: 洗干净Wine补丁的尝试,请爱好者和Linux编程高手进

发表于 : 2008-11-27 17:04
xrfang
受13楼hzhr大师的启发,我发现只有CharSet==ANSI_CHARSET的时候才有问题,而DEFAULT_CHARSET是没有问题的。于是有了另一个版本的patch,我本人测试通过:

代码: 全选

    if (lf.lfCharSet == ANSI_CHARSET) {
	  UINT codepage;
	  codepage = GetACP();
      FIXME("lf.lfCharSet == ANSI_CHARSET, using GetACP (%d)\n", codepage);
      if(!TranslateCharsetInfo((DWORD*)(INT_PTR)codepage, &csi, TCI_SRCCODEPAGE)) {
        FIXME("OMG. Even this hack doesn't work.  Let's PRAY.\n");
        csi.fs.fsCsb[0] = 0; 
      }
      lf.lfCharSet = csi.ciCharset;
    } else if(!TranslateCharsetInfo((DWORD*)(INT_PTR)lf.lfCharSet, &csi, TCI_SRCCHARSET)) {
        switch(lf.lfCharSet) {
	      case DEFAULT_CHARSET:
	        csi.fs.fsCsb[0] = 0;
	        break;
	      default:
	        FIXME("Untranslated charset %d\n", lf.lfCharSet);
	        csi.fs.fsCsb[0] = 0;
	        break;
	    }
    }
这个版本不需要WINE_DEFAULT_CODEPAGE来支持。我想由于用了GetACP(),应该是兼容非中文系统的?

我看了一下GdiGetCodePage函数,这个函数虽然简单,但我没有完全理解,不敢动它,另外,作者或者维护者在里面写了个注释:

/* Hmm, nicely designed api this one! */

既然大师对这个函数如此青睐,我更加未敢造次了!

虽然这个patch不是从根本上解决问题,但我想总比现在这个好些?