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

Wine、Cedega、CrossOver 等配置
回复
头像
xrfang
帖子: 1116
注册时间: 2006-12-08 10:21

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

#1

帖子 xrfang » 2008-11-22 22:42

第四页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
上次由 xrfang 在 2008-12-16 21:26,总共编辑 2 次。
你爱用不用,没人逼你用--这就是Free的定义?
不,请自重,不要玷污Linux文化。
头像
windowssux
帖子: 618
注册时间: 2006-08-06 16:58
来自: 北海

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

#2

帖子 windowssux » 2008-11-23 1:04

好啊,顶上!!
头像
xrfang
帖子: 1116
注册时间: 2006-12-08 10:21

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

#3

帖子 xrfang » 2008-11-23 10:45

我个人的测试是成功的。但有一个程序,和讯股道,即原来的飞狐交易师,死活显示不正常。希望懂windows font原理的大师解惑,以便大家可以群策群力给出较好的中文解决方案。我个人认为没有必要使用“自动字符集判断”。看看下面两个图:
附件
设置WINE_DEFAULT_CODEPAGE=936
设置WINE_DEFAULT_CODEPAGE=936
cp936.png (11.65 KiB) 查看 14349 次
未设置WINE_DEFAULT_CODEPAGE
未设置WINE_DEFAULT_CODEPAGE
cpdef.png (13.4 KiB) 查看 14350 次
你爱用不用,没人逼你用--这就是Free的定义?
不,请自重,不要玷污Linux文化。
dkeehl
帖子: 49
注册时间: 2007-12-02 18:12

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

#4

帖子 dkeehl » 2008-11-23 11:38

纯支持

第一张图中程序似乎选择了一个不含中文字符的字体
头像
yinliang108
帖子: 964
注册时间: 2005-10-01 21:38
来自: 湖南邵东流光岭

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

#5

帖子 yinliang108 » 2008-11-23 12:16

飞狐交易师可以在字体设置里选择已有的字体。
小江恩的博客
http://gann.blog.ifeng.com/
头像
xrfang
帖子: 1116
注册时间: 2006-12-08 10:21

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

#6

帖子 xrfang » 2008-11-23 13:15

yinliang108 写了:飞狐交易师可以在字体设置里选择已有的字体。
果真如此!没想到这么简单就可以解决。谢谢楼上和楼上的楼上。
你爱用不用,没人逼你用--这就是Free的定义?
不,请自重,不要玷污Linux文化。
aaawhale
帖子: 63
注册时间: 2007-09-24 16:51

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

#7

帖子 aaawhale » 2008-11-23 18:31

怎么使用啊,我不懂编程啊
头像
xrfang
帖子: 1116
注册时间: 2006-12-08 10:21

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

#8

帖子 xrfang » 2008-11-24 7:27

aaawhale 写了:怎么使用啊,我不懂编程啊
如不懂编程,直接使用置顶贴的文件就可以了 :em09 这个帖子的期望目的在于使这个补丁被wine官方所接受。我们先探讨一个最佳解决方案。
你爱用不用,没人逼你用--这就是Free的定义?
不,请自重,不要玷污Linux文化。
the_Fm
帖子: 13
注册时间: 2008-11-19 18:27

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

#9

帖子 the_Fm » 2008-11-25 10:55

这样不行,稍微变换下,等我研究下不过要看WINE如何配置。我对WINE的配置不是很了解。
一会用vc测试下1.1.9的EFAULT_CODEPAGE问题。
头像
xrfang
帖子: 1116
注册时间: 2006-12-08 10:21

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

#10

帖子 xrfang » 2008-11-25 11:59

the_Fm 写了:这样不行,稍微变换下,等我研究下不过要看WINE如何配置。我对WINE的配置不是很了解。
一会用vc测试下1.1.9的EFAULT_CODEPAGE问题。
我用GCC测试过getenv()没有问题,另外,我自己在用这个修改过的补丁是可以的。不知LS说的不行是什么东西,期待你测试完了以后详加说明...
你爱用不用,没人逼你用--这就是Free的定义?
不,请自重,不要玷污Linux文化。
the_Fm
帖子: 13
注册时间: 2008-11-19 18:27

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

#11

帖子 the_Fm » 2008-11-25 13:09

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

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

#12

帖子 xrfang » 2008-11-25 18:36

the_Fm 写了:
xrfang 写了:
the_Fm 写了:这样不行,稍微变换下,等我研究下不过要看WINE如何配置。我对WINE的配置不是很了解。
一会用vc测试下1.1.9的EFAULT_CODEPAGE问题。
我用GCC测试过getenv()没有问题,另外,我自己在用这个修改过的补丁是可以的。不知LS说的不行是什么东西,期待你测试完了以后详加说明...
我的理解的dirty不是pageocde在前面设置了的问题。而是对 DEFAULT的修改。所以要读下代码。
这就是我说的第二个问题。我改动的代码解决了这个问题--只有特定条件下才修改default
你爱用不用,没人逼你用--这就是Free的定义?
不,请自重,不要玷污Linux文化。
hzhr
帖子: 16
注册时间: 2006-05-05 2:22

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

#13

帖子 hzhr » 2008-11-26 2:12

什么脏不脏,这个补丁没有找到问题的所在,肯定不会被接受。

需要修正的函数是 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
头像
gcell
帖子: 429
注册时间: 2007-04-30 2:25
来自: 湖南湘潭
联系:

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

#14

帖子 gcell » 2008-11-26 3:13

等楼上的好消息!!!
孰能浊静之以徐清,孰能安动之以馀生!
gcell -- http://gcell.blog.163.com/
头像
xrfang
帖子: 1116
注册时间: 2006-12-08 10:21

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

#15

帖子 xrfang » 2008-11-27 17:04

受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不是从根本上解决问题,但我想总比现在这个好些?
你爱用不用,没人逼你用--这就是Free的定义?
不,请自重,不要玷污Linux文化。
回复