<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title><![CDATA[i'm Chao]]></title>
  <link href="http://imchao.net/atom.xml" rel="self"/>
  <link href="http://imchao.net/"/>
  <updated>2012-01-08T16:32:26+08:00</updated>
  <id>http://imchao.net/</id>
  <author>
    <name><![CDATA[吼吼]]></name>
    
  </author>
  <generator uri="http://octopress.org/">Octopress</generator>

  
  <entry>
    <title type="html"><![CDATA[让UIColor支持Hex值]]></title>
    <link href="http://imchao.net/2012/01/08/using-hex-value-with-uicolor/"/>
    <updated>2012-01-08T16:00:00+08:00</updated>
    <id>http://imchao.net/2012/01/08/using-hex-value-with-uicolor</id>
    <content type="html"><![CDATA[<p>在使用Cocoa的地方，有个很奇怪问题。为什么每次实例化一个UIColor的时候非要分别指定RGBA四个值，而且每个值都需要除以255.0f。作为前端出生的我太不适应了。公司产品的界面自定义太多了，需要用到特殊颜色的地方也很多。一个颜色值从Photoshop吸取出来后，需要复制四个值。n个颜色也就需要复制4n次。每次都要我这么搞，这也太坑爹了吧。</p>

<p>那有没有办法让UIColor和网页中的CSS那样使用Hex（十六进制值）来指定呢？我写了个UIColor的Category解决了这个问题。</p>

<!-- more -->




<div><script src='https://gist.github.com/1542973.js?file='></script>
<noscript><pre><code>//
//  UIColor+Hex.h
// 
//
//  Created by 超 沈 on 11-12-31.
//  Copyright (c) 2011年 __MyCompanyName__. All rights reserved.
//

#import &lt;UIKit/UIKit.h&gt;

@interface UIColor (Hex)
+ (UIColor*)colorWithHex:(NSInteger)hexValue alpha:(CGFloat)alphaValue;
+ (UIColor*)colorWithHex:(NSInteger)hexValue;
+ (UIColor*)whiteColorWithAlpha:(CGFloat)alphaValue;
+ (UIColor*)blackColorWithAlpha:(CGFloat)alphaValue;
@end
</code></pre></noscript></div>


<p>使用起来可以直接这样：</p>

<figure class='code'><figcaption><span>Using UIColor With Hex  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='c'><span class='line'><span class="p">[</span><span class="n">UIColor</span> <span class="n">colorWithHex</span><span class="o">:</span><span class="mh">0x3d5d6d</span> <span class="n">alpha</span><span class="o">:</span><span class="mf">0.6</span><span class="p">];</span>
</span><span class='line'><span class="p">[</span><span class="n">UIColor</span> <span class="n">colorWithHex</span><span class="o">:</span><span class="mh">0x3d5d6d</span><span class="p">];</span>
</span><span class='line'><span class="p">[</span><span class="n">UIColor</span> <span class="n">whiteColorWithAlpha</span><span class="o">:</span><span class="mf">0.6</span><span class="p">];</span>
</span><span class='line'><span class="p">[</span><span class="n">UIColor</span> <span class="n">blackColorWithAlpha</span><span class="o">:</span><span class="mf">0.9</span><span class="p">];</span>
</span></code></pre></td></tr></table></div></figure>


<p>如果不想使用Category，可以直接使用下面的代码：</p>

<figure class='code'><figcaption><span>UIColorFromRGB  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='c'><span class='line'><span class="cp">#define UIColorFromRGB(rgbValue) [UIColor \</span>
</span><span class='line'><span class="cp">    colorWithRed:((float)((rgbValue &amp; 0xFF0000) &gt;&gt; 16))/255.0 \</span>
</span><span class='line'><span class="cp">    green:((float)((rgbValue &amp; 0xFF00) &gt;&gt; 8))/255.0 \</span>
</span><span class='line'><span class="cp">    blue:((float)(rgbValue &amp; 0xFF))/255.0 alpha:1.0]</span>
</span></code></pre></td></tr></table></div></figure>



]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[写在2011最后一天]]></title>
    <link href="http://imchao.net/2011/12/31/write-in-late-2011/"/>
    <updated>2011-12-31T23:59:00+08:00</updated>
    <id>http://imchao.net/2011/12/31/write-in-late-2011</id>
    <content type="html"><![CDATA[<p>半年没动blog了，28号的时候冷不丁的写了一篇《<a href="http://imchao.net/2011/12/28/draw-rounded-corner-image-with-shadow-by-quartz/">使用Quartz绘制带阴影的圆角图</a>》，实际上我一直想写类似的技术博文，而且也积压了好多主题，苦于工作所迫一直没写。总之先写了这篇总结再说吧。</p>

<h2>工作篇</h2>

<p>去年的9月我再次来到阿里学院，与之前不同，这次是作为正式员工加入阿里巴巴。这也是我的第一份正式工作。这段日子有艰辛又有收获。出于个人梦想，在今年9月，也就是工作刚满一年之时，我辞去了这份工作来到了一家初创公司，任职前端开发。两个月后又因为公司需要我转向了iOS开发，直至今天。</p>

<p>一直想学Cocoa编程，现今刚好有机会可以在公司边学边做，每天都很充实。从我开始学习到先在应该有一个半月了，目前写了7000多行代码，我第一个移动应用预计会在春节前发布，大家拭目以待吧。</p>

<h2>7Peers篇</h2>

<p>加入阿里巴巴后，认识了很多业内的朋友。我们因拥有相同的梦想走在一起，也因梦想陆续离开，各奔前程。在大家相继离开前，我们创立了7Peers，目的是让大家在工作之余，可以一起做些感兴趣的产品。<a href="http://imchao.net/2011/06/03/stash-coming-my-first-chrome-extensions">Stash</a>就是我们第一个对外发布的产品。此外还有许多未发布、开发中的产品。比如：</p>

<ul>
<li>nooon.in</li>
<li>Lento</li>
<li>DewDewTree</li>
</ul>


<p><a href="http://imchao.net/2011/06/03/stash-coming-my-first-chrome-extensions">Stash</a>本该在今年7月重构一个新版本，但由于那时公司开始了一个大型项目，而之后我又开始换工作，所以直到今天毫无进展。明年，我的事情应该会少很多，我将继续<a href="http://imchao.net/2011/06/03/stash-coming-my-first-chrome-extensions">Stash</a>的开发。</p>

<p>就在今年7月，随着<a href="http://imchao.net/2011/06/03/stash-coming-my-first-chrome-extensions">Stash</a>0.2.3版的发布，我们一起推出了<a href="http://www.7peers.com">7Peers.com</a>。我们的天才设计师<a href="http://johnsonliu.me/">强生生</a>同学的给力设计让我们的官网一下子受到了业内的关注。没过多久，某澳大利亚公司就给我们发邮件，想出钱让我们团队为他们设计开发产品。虽然最后我们还是婉拒了邀请，不过这封邮件让我们振奋不已。</p>

<p>如今7Peers成员均已离开阿里巴巴，我是最后一个走的。大家分散在全国各地，7Peers的项目并没有终止。而且明年还有一个全新的项目，目前唯一能透露的就是这是一个Mac应用。</p>

<!-- more -->


<h2>技术宅篇</h2>

<p>正如前面所述，我开始转型了，我从一个前端开发工程师，转到了iOS开发工程师，以后应该也是Cocoa工程师。</p>

<p>这一年我所学不少，javascript、python、objective-c。我是语言杂食动物。另外在去年入的MacbookAir已成为主力。现在windows、linux几乎不碰了，Mac OS用的相当顺手。</p>

<p>大家可能发现我的博客又变了。是的，先开始我迷恋上了github，之后又是markdown，现在索性把臃肿wordpress换成了octopress，所有文章都以markdown格式在本地存储。这样不仅好管理，查阅也方便。连博客对服务器性能的要求也小了。</p>

<h2>蜗居篇</h2>

<p>上个月ING公寓杭州总部搬迁至城西了，我们告别了住了一年半的温馨人家。离开那一天，我和Frankyue还在说在这里的日子历历在目，那道不削皮的炒丝瓜，那个谁都做不好的宫保鸡丁。就是在这里，我们三个技术宅学做菜的，聊技术，而如今已是物是人非。</p>

<p>搬了新家，房子少了50个平方，不过挺温馨的，家里很干净，装修是全新的。最终要的是这里有我的老婆和爱犬——美酱。</p>

<h2>家庭篇</h2>

<p>是的，我结婚了，就在今年9月29，我们结婚了。虽然我还没有求婚，我还没有买戒指。如今我已是已婚人士，身上的责任更大了。现在我还不够成熟，生活难免会有擦擦碰碰的，但我坚信我以后一定可以做好丈夫这个角色的。老婆很体贴，会做饭，偶尔发发小脾气。每天下班回家都有饭吃，这日子真舒服。</p>

<p>话说我们家的狗狗——美酱已经来到家里已经半个月了。我说的美酱实际上是美酱二代。实际上还有个美酱一代，不过它来到我们家第三天就病了，随后它就去了。那是真是伤心，还在忧郁要不要继续养狗的时候，宠物店把美酱二代带来了。第一眼看到它的时候觉得它非常可人，所以我就把它带回家了。</p>

<h2>展望篇</h2>

<p>新年一年要做些什么呢？大概想了想：</p>

<ul>
<li>写好Cocoa，发布公司产品</li>
<li>看完《浪潮之巅》《乔布斯转》《失控》《百年孤独》</li>
<li>重构Stash</li>
<li>某秘密Mac项目</li>
<li>带老婆旅游</li>
<li>训练狗狗</li>
<li>life goes on&#8230;</li>
</ul>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[使用Quartz绘制带阴影的圆角图]]></title>
    <link href="http://imchao.net/2011/12/28/draw-rounded-corner-image-with-shadow-by-quartz/"/>
    <updated>2011-12-28T20:08:00+08:00</updated>
    <id>http://imchao.net/2011/12/28/draw-rounded-corner-image-with-shadow-by-quartz</id>
    <content type="html"><![CDATA[<p>最近在做iOS开发的时候，遇到这样的需求：需要开发一个高度自适应的控件，背景使用图案平铺，控件下方两个角为圆角，控件的下边有5像素宽的阴影。具体如图所示：</p>

<p><img src="http://imchao.net/uploads/2011/12/28/rounded-corner-image-requirement.png" title="需求效果图" alt="需求效果图" /></p>

<h2>方案A</h2>

<p>在做这个需求时首先想到是用<code>colorWithPatternImage</code>来平铺图片，然后使用CALayer添加阴影。</p>

<!-- more -->




<div><script src='https://gist.github.com/1531487.js?file=RoundedCornerImageA.m'></script>
<noscript><pre><code>//
//  RoundedCornerImageA.m
//  tutugogo
//
//  Created by ohsc on 11-12-28.
//  Copyright (c) 2011年 __MyCompanyName__. All rights reserved.
//

#import &quot;RoundedCornerImageA.h&quot;

#define kHeight 64
#define kRoundSize 10
@implementation RoundedCornerImageA

- (id)initWithFrame:(CGRect)frame
{
    CGRect aFrame = CGRectMake(frame.origin.x, frame.origin.y, frame.size.width, kHeight);
    self = [super initWithFrame:aFrame];
    if (self) {
        // Initialization code
        self.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@&quot;pattern.png&quot;]];
        self.layer.cornerRadius = kRoundSize;
        self.layer.masksToBounds = YES;
        
        [self.layer setShadowColor:[UIColor colorWithRed:0 green:0 blue:0 alpha:0.3].CGColor];
        [self.layer setShadowOffset:CGSizeMake(0, 0)];
        [self.layer setShadowOpacity:1.0];
        [self.layer setShadowRadius:kRoundSize];

    }
    return self;
}
@end</code></pre></noscript></div>


<p>不过这样做的严重缺陷是阴影被裁切掉了。</p>

<h2>方案B</h2>

<p>所以考虑使用Quartz的<code>CGContextDrawTiledImage</code>来平铺背景，使用layer制造阴影。</p>

<div><script src='https://gist.github.com/1531487.js?file=RoundedCornerImageB.m'></script>
<noscript><pre><code>//
//  RoundedCornerImageB.m
//  tutugogo
//
//  Created by ohsc on 11-12-28.
//  Copyright (c) 2011年 __MyCompanyName__. All rights reserved.
//

#import &quot;RoundedCornerImageB.h&quot;

#define kHeight 64
#define kRoundSize 10
@implementation RoundedCornerImageB

- (id)initWithFrame:(CGRect)frame
{
    CGRect aFrame = CGRectMake(frame.origin.x, frame.origin.y, frame.size.width, kHeight);
    self = [super initWithFrame:aFrame];
    if (self) {
        // Initialization code
        
        CALayer *bgLayer = [CALayer layer];
        bgLayer.frame = CGRectMake(0, 0, self.layer.frame.size.width, self.layer.frame.size.height);
        bgLayer.delegate = [[RoundedCornerImageBBgLayerHelper alloc] init];
        [bgLayer setNeedsDisplay];
        [self.layer addSublayer:bgLayer];
    }
    return self;
}
@end

@implementation RoundedCornerImageBBgLayerHelper

- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx
{
    CGFloat minx = CGRectGetMinX(layer.frame) , midx = CGRectGetMidX(layer.frame), maxx = CGRectGetMaxX(layer.frame) ;
    CGFloat miny = CGRectGetMinY(layer.frame) , maxy = CGRectGetMaxY(layer.frame)-5 ;
    
    CGMutablePathRef path = CGPathCreateMutable();
    CGPathMoveToPoint(path, NULL, minx, miny);
    CGPathAddArcToPoint(path, NULL, minx, maxy, midx, maxy, kRoundSize);
    CGPathAddArcToPoint(path, NULL, maxx, maxy, maxx, miny, kRoundSize);
    CGPathAddLineToPoint(path, NULL, maxx, miny);
    CGPathAddLineToPoint(path, NULL, minx, miny);
    CGPathCloseSubpath(path);
    
    CGContextAddPath(ctx, path);
    CGContextClip(ctx);
    
    UIImage *image = [UIImage imageNamed:@&quot;pattern.png&quot;];
    CGContextDrawTiledImage(ctx, CGRectMake(0, 0, image.size.width, image.size.height), image.CGImage);
    
    CGPathRelease(path);
    
    [layer setShadowColor:[UIColor colorWithRed:0 green:0 blue:0 alpha:0.3].CGColor];
    [layer setShadowOffset:CGSizeMake(0, 0)];
    [layer setShadowOpacity:1.0];
    [layer setShadowRadius:kRoundSize];
}


@end</code></pre></noscript></div>


<p>这样做虽然可以大概的实现需求，不过阴影的宽度不可控制。</p>

<h2>方案C</h2>

<p>于是我尝试使用Quartz的<code>CGContextSetShadowWithColor</code>来绘制阴影，但是怎么绘制阴影呢？使用<code>CGContextDrawTiledImage</code>平铺背景时会占满指定的区域，这样也有没有了绘制阴影的空间。</p>

<p>在stackoverflow搜索了一圈，有人建议先使用固定色填充圆角区域，再在这个区域平铺图片。</p>

<div><script src='https://gist.github.com/1531487.js?file=RoundedCornerImageC.m'></script>
<noscript><pre><code>//
//  RoundedCornerImageC.m
//  tutugogo
//
//  Created by ohsc on 11-12-28.
//  Copyright (c) 2011年 __MyCompanyName__. All rights reserved.
//

#import &quot;RoundedCornerImageC.h&quot;

#define kHeight 64
#define kRoundSize 10
@implementation RoundedCornerImageC

- (id)initWithFrame:(CGRect)frame
{
    CGRect aFrame = CGRectMake(frame.origin.x, frame.origin.y, frame.size.width, kHeight);
    self = [super initWithFrame:aFrame];
    if (self) {
        // Initialization code
        
        CALayer *bgLayer = [CALayer layer];
        bgLayer.frame = CGRectMake(0, 0, self.layer.frame.size.width, self.layer.frame.size.height);
        bgLayer.delegate = [[RoundedCornerImageCBgLayerHelper alloc] init];
        [bgLayer setNeedsDisplay];
        [self.layer addSublayer:bgLayer];
    }
    return self;
}
@end

@implementation RoundedCornerImageCBgLayerHelper

- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx
{
    CGFloat minx = CGRectGetMinX(layer.frame) , midx = CGRectGetMidX(layer.frame), maxx = CGRectGetMaxX(layer.frame) ;
    CGFloat miny = CGRectGetMinY(layer.frame) , maxy = CGRectGetMaxY(layer.frame)-5 ;
    
    CGMutablePathRef path = CGPathCreateMutable();
    CGPathMoveToPoint(path, NULL, minx, miny);
    CGPathAddArcToPoint(path, NULL, minx, maxy, midx, maxy, kRoundSize);
    CGPathAddArcToPoint(path, NULL, maxx, maxy, maxx, miny, kRoundSize);
    CGPathAddLineToPoint(path, NULL, maxx, miny);
    CGPathAddLineToPoint(path, NULL, minx, miny);
    CGPathCloseSubpath(path);
    
    CGContextSetShadowWithColor(ctx, CGSizeMake(0, 0), 5, [UIColor colorWithRed:0/255.0 green:0/255.0 blue:0/255.0 alpha:0.4].CGColor);
    CGContextAddPath(ctx, path);
    CGContextFillPath(ctx);
    
    CGContextAddPath(ctx, path);
    CGContextClip(ctx);

    UIImage *image = [UIImage imageNamed:@&quot;pattern.png&quot;];
    CGContextDrawTiledImage(ctx, CGRectMake(0, 0, image.size.width, image.size.height), image.CGImage);
    
    CGPathRelease(path);        
}


@end</code></pre></noscript></div>


<p>这个方案比上个方案好了很多，不过细心的人可能会发现圆角的阴影有深色的锯齿，不够协调。原因是阴影是根据固定色生成的，在处理边界过度时是从固定色过度来的。</p>

<h2>方案D</h2>

<p>那有没有办法让阴影根据图片来生成呢？我想到了<code>CGContextDrawImage</code>方法。先在一个特殊的<code>context</code>生成平铺图，然后在当前的<code>context</code>使用<code>CGContextDrawImage</code>来绘制图片，这样绘制图片的同时会产生相应的阴影。</p>

<div><script src='https://gist.github.com/1531487.js?file=RoundedCornerImageD.m'></script>
<noscript><pre><code>//
//  RoundedCornerImageD.m
//  tutugogo
//
//  Created by ohsc on 11-12-28.
//  Copyright (c) 2011年 __MyCompanyName__. All rights reserved.
//

#import &quot;RoundedCornerImageD.h&quot;

#define kHeight 64
#define kRoundSize 10
@implementation RoundedCornerImageD

- (id)initWithFrame:(CGRect)frame
{
    CGRect aFrame = CGRectMake(frame.origin.x, frame.origin.y, frame.size.width, kHeight);
    self = [super initWithFrame:aFrame];
    if (self) {
        // Initialization code
        
        CALayer *bgLayer = [CALayer layer];
        bgLayer.frame = CGRectMake(0, 0, self.layer.frame.size.width, self.layer.frame.size.height);
        bgLayer.delegate = [[RoundedCornerImageDBgLayerHelper alloc] init];
        [bgLayer setNeedsDisplay];
        [self.layer addSublayer:bgLayer];
    }
    return self;
}
@end

@implementation RoundedCornerImageDBgLayerHelper

- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx
{
    CGFloat minx = CGRectGetMinX(layer.frame) , midx = CGRectGetMidX(layer.frame), maxx = CGRectGetMaxX(layer.frame) ;
    CGFloat miny = CGRectGetMinY(layer.frame) , maxy = CGRectGetMaxY(layer.frame)-5 ;
    
    CGMutablePathRef path = CGPathCreateMutable();
    CGPathMoveToPoint(path, NULL, minx, miny);
    CGPathAddArcToPoint(path, NULL, minx, maxy, midx, maxy, kRoundSize);
    CGPathAddArcToPoint(path, NULL, maxx, maxy, maxx, miny, kRoundSize);
    CGPathAddLineToPoint(path, NULL, maxx, miny);
    CGPathAddLineToPoint(path, NULL, minx, miny);
    CGPathCloseSubpath(path);
    
    CGContextRef imgCtx = CGBitmapContextCreate(NULL, layer.frame.size.width, layer.frame.size.height, 8, 0, CGColorSpaceCreateDeviceRGB(), kCGImageAlphaPremultipliedLast);

    CGContextAddPath(imgCtx, path);
    CGContextClip(imgCtx);

    UIImage *image = [UIImage imageNamed:@&quot;pattern.png&quot;];
    CGContextDrawTiledImage(imgCtx, CGRectMake(0, 0, image.size.width, image.size.height), image.CGImage);
    
    CGImageRef img = CGBitmapContextCreateImage(imgCtx);
    
    CGContextSetShadowWithColor(ctx, CGSizeMake(0, 0), 5, [UIColor colorWithRed:0/255.0 green:0/255.0 blue:0/255.0 alpha:0.4].CGColor);        

    CGContextDrawImage(ctx, layer.frame, img);
    
    CGPathRelease(path);
    CGContextRelease(imgCtx);
    CGImageRelease(img);
}


@end</code></pre></noscript></div>


<h2>结语</h2>

<p>作为初学者，对Quartz也只是一知半解。尝试过程中发现绘制的时候一定要注意顺序，否则会出现各种奇怪的问题。Quartz是个强大东西，要好好利用还需跟多的尝试。</p>

<p>另附上本文的源代码：<a href="https://github.com/ohsc/CodeBox-of-Cocoa/tree/master/RoundedCornerImageWithShadow">https://github.com/ohsc/CodeBox-of-Cocoa/tree/master/RoundedCornerImageWithShadow</a></p>

<p>四个方案运行效果图：</p>

<p><img src="http://imchao.net/uploads/2011/12/28/rounded-corner-image-implementation.png" title="运行结果图" alt="运行结果图" /></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[7Peers即将到来 & Stash的下一版本]]></title>
    <link href="http://imchao.net/2011/06/13/7peers-is-coming-soon-and-next-version-of-stash/"/>
    <updated>2011-06-13T00:00:00+08:00</updated>
    <id>http://imchao.net/2011/06/13/7peers-is-coming-soon-and-next-version-of-stash</id>
    <content type="html"><![CDATA[<p>7Peers即将到来！什么是7Peers呢？7Peers其实就是指我们团队。团队创立之初，大家抱着共同的梦想聚在一起，那时候我们有七人。而如今我们又要各奔东西分散各地，但是我们的梦想不变。我们相约，继续通过网络交流，继续一起创作互联网产品。Peer预示着节点、同伴、同等，而7Peers彼此联系，构成网络，预示着我们共同的织网梦想。这就是我们——Seven Team。</p>

<p>我们注册了<a href="http://7peers.com/">7peers.com</a>的域名，<a href="http://7peers.com/">coming soon</a>页面已经上线，网站本身很快也会发布。此外我们还开通了twitter、facebook、新浪微博。请关注我们：</p>

<ul>
<li><a href="http://7peers.com/">http://7peers.com</a></li>
<li><a href="http://weibo.com/n/7Peers">http://weibo.com/n/7Peers</a></li>
<li><a href="http://twitter.com/7peers">http://twitter.com/7peers</a></li>
<li><a href="http://www.facebook.com/pages/7Peers/211442722228539">http://www.facebook.com/pages/7Peers/211442722228539</a></li>
</ul>


<p>另外，Stash的下一版本已经进入紧张的开发阶段。新版本会带来两大特性，一个是列表锁定，另一个特性是快捷键。</p>

<p><img src="http://www.imchao.net/uploads/2011/06/stash-v0.3.png" alt="stash 3.0预览" /></p>

<!-- more -->


<p>Stash发布后，不少用户反映为什么恢复页签后会自动删除记录？开发Stash之初，我担心用户在使用stash的同时会变得懒惰。他在体验到stash便利的同时，可能会把自己暂时不愿看的文章存起来。这就会出现这样的情况：他一推再推，始终不愿意把东西处理掉，删掉又觉得可惜，最后这些东西就变成stash列表中的僵尸条目。</p>

<p>我希望引入自动删除机制可以帮助用户改掉这个坏习惯。不过在发布后，我们发现很多用户不喜欢这样。甚至有些用户期望stash能帮助他们把经常要打开的网站存起来。好吧，新版的stash给你们带来了锁定功能。你可以在配置页面设置自动锁定记录，或者手动锁定记录。锁定记录后，当你点击恢复标签页时，记录不会再自动删除。</p>

<p>很多用户跟我们说stash很好用，解决了他们的难题。是的，正如我上篇文章所说，stash的产生就是来自我自身的需求。不过我觉得stash还不够好用。为什么不提供快捷键呢？每次存储需要先点图标，再点“暂存”，两次点击，还不够快。所以我在新版本中开发了快捷键功能。启用后，你可以直接用快捷键保存单个或多个标签页。</p>

<p>嘿嘿，不好小心说漏嘴了。其实新版本中还有很多小特性。比如支持单标签暂存，比如增加了自定义设置，比如记录名称修改。</p>

<p>Stash目前的版本是0.2.2，我们会在0.3版推出以上所有功能。也许你会很兴奋，不过我必须要说明，Stash不会马上进化到0.3版。可能会先有0.2.3、0.2.4、0.2.5版等等。我会通过小版本迅速迭代的方式，把这些功能都加进来。放心吧，0.3版不会很远。</p>

<p>最后必须要说，你的声音是对我们最大的支持，请把你的想法告诉我们，通过微博、twitter、email都可以，谢谢！</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Stash来啦！我开发的第一个Chrome扩展]]></title>
    <link href="http://imchao.net/2011/06/03/stash-coming-my-first-chrome-extensions/"/>
    <updated>2011-06-03T00:00:00+08:00</updated>
    <id>http://imchao.net/2011/06/03/stash-coming-my-first-chrome-extensions</id>
    <content type="html"><![CDATA[<p><a href="http://www.imchao.net/uploads/2011/06/Coming.jpg"><img src="http://www.imchao.net/uploads/2011/06/Coming-300x204.jpg" alt="stash availble" /></a></p>

<p><a href="http://www.imchao.net/uploads/2011/06/Coming-1.jpg"><img src="http://www.imchao.net/uploads/2011/06/Coming-1-212x300.jpg" alt="stash preview" /></a></p>

<p>很久很久很久很久没写博客啦，难得写一次博客，居然是来发布产品的。言归正传，我和一个朋友(<a href="http://johnsonliu.me/" title="强生生的博客">强生</a>)打磨的Chrome扩展——Stash来啦！绝对是你需要的工具，请耐心看完下面的内容。</p>

<p>什么是Stash？Stash是一个以全新的方式储存和管理标签页的chrome扩展程序。这个小东西由强生和我合力完成。从构思到开发我们花了不到一个月的时间，而且都是在业余时间进行的。我们希望以这个项目作为起点和尝试，能做出更多有意思的产品。</p>

<p>那么究竟Stash有什么用呢？我们来看一下当初我们构思的故事吧。</p>

<!-- more -->


<p>在某个下午，Dick在一台普通的台式机前忙碌。他正在进行BOSS交给他的A任务。他在网上找了很多资料，这时候他的浏览器状态是这样的。</p>

<p><a href="http://www.imchao.net/uploads/2011/06/tab%E7%9A%84%E6%82%B2%E5%89%A7.png"><img src="http://www.imchao.net/uploads/2011/06/tab%E7%9A%84%E6%82%B2%E5%89%A7-300x34.png" alt="tab的悲剧" /></a></p>

<p>怎么样，标签多得可怕？更可怕的是，这时候BOSS突然要他优先完成B任务。Dick开始清理桌面，准备进行新的工作。那么这些已经找到的资料怎么办呢？</p>

<p>别管他新开个窗口？一个一个保存到收藏夹？可以批量保存到收藏夹？</p>

<p>NO！NO！NO！Dick打开了Stash，点击“暂存”。这时候所有的标签页都不见了！不过Dick很淡定，因为他知道，只要点击Stash列表中的项目，就可以奇迹般的恢复原来的标签页！</p>

<p>故事还没结束。</p>

<p>这时候BOSS突然安排他去见一位客户，他将在路上花费2小时。Dick觉得路上不能浪费时间。他掏出笔记本，打开浏览器，点击Stash列表中的项目。奇迹发生了，明明在台式机上保存的标签页，居然在笔记本上原封不动的恢复了！</p>

<p>这就是Stash！</p>

<blockquote><p>Stash下载地址：<a href="https://chrome.google.com/webstore/detail/bnhjedgfogckebfhnlicnkbdjlmpibck" title="Stash下载地址">Chrome web store</a> （可能需要用具有中国特色的手段才能访问）</p></blockquote>

<p>Stash的产品模型来自我的迫切的需求。当初构思这个产品就是想单纯的满足我自己的需求。我当然最了解自己的需求，所以在发布后，Stash完全按照我预想的方向发展，没有偏离轨道。</p>

<p>快速开发，多次迭代是Stash项目顺利进行的关键。Stash经常被修改，现在已经到0.2.2版了。记得当初开发出0.1版本的时候非常不稳定。我通过多次迭代使得它进化到0.2版。目前Stash已趋于稳定，之后我们还会继续迭代。</p>

<p>要把简单留给用户。Stash的诞生的使命就是解决问题。我们不想把麻烦带给用户。所以我们把stash做的足够的简约，以至于它只有三个行动点。但实际上stash有很多功能。它可以同步存储的书签。当初我们还想搞个云同步。可是搞云同步还需要让用户注册一个额外的账号，这样太麻烦了。不如直接利用Chrome原生的书签同步功能。我们把tab存储为书签，这样Chrome就会自动同步。这就好像是个Gift，当用户使用了Chrome的同步后，突然发现Stash居然也是同步的。我们觉得这样做不但可以简化流程，还可以给用户带来惊喜。</p>

<p>What’s next? 支持快捷键？支持自定义？支持***？别担心，我们会继续围绕着stash的功能进行讨论，目的是找到Stash的核心价值，让Stash更好用。</p>

<p>Furthermore，你的声音是对我们最大的支持，请把你的想法告诉我们，谢谢！</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[构建大型jQuery应用]]></title>
    <link href="http://imchao.net/2011/01/04/building-large-scale-jquery-applications/"/>
    <updated>2011-01-04T00:00:00+08:00</updated>
    <id>http://imchao.net/2011/01/04/building-large-scale-jquery-applications</id>
    <content type="html"><![CDATA[<p>原文：<a href="http://addyosmani.com/blog/large-scale-jquery/">http://addyosmani.com/blog/large-scale-jquery/</a></p>

<h2>1.依赖管理</h2>

<p>目前常用的script loader主要有两个，RequireJS (by James Burke) 与LabJS (by Kyle Simpson)。有些人会认为这其中一个会比另一个要好，但事实上他们各自有各自的特点。以我的经验来讲，RequireJS的特性之一是提供结构化模块的支持，而LabJS更适合不需要额外特性或者需要轻量级库的时候。</p>

<p>如果你想知道更多关于如何选择 RequireJS、LabJS，请看这里：<a href="http://msdn.microsoft.com/en-us/scriptjunkie/ff943568">http://msdn.microsoft.com/en-us/scriptjunkie/ff943568</a>。如果这两个还不能满足你的需求，你还可以看看下面的内容。</p>

<h3>解决方案：</h3>

<p><strong>RequireJS</strong> – 如果你期望你的代码更加模块化，我强烈推荐它。它会试图限制模块对全局命名空间的影响，并使得依赖更加明确。同时它还提供一个优化工具，帮助你合并压缩脚本 - <a href="http://requirejs.org/docs/jquery.html">http://requirejs.org/docs/jquery.html</a></p>

<p><strong>LabJS</strong> – 如果你需要按照一定的顺序高效的加载脚本，或者你正在寻找比RequireJS更轻量级的框架，或者你对模块化依赖管理根本不感兴趣，那么你不妨试试LabJS。 – <a href="http://www.labjs.com">http://www.labjs.com</a> (Alex Sexton 还在LabJS的基础上开发了条件化的loader，YepNope JS - <a href="http://www.yepnopejs.com">http://www.yepnopejs.com</a>)</p>

<p><strong>StealJS</strong> – 又一个非常棒的依赖管理工具。Steal是 JavaScriptMVC框架的一部分，不过你可以单独使用它。它也提供了合并、压缩、清理等功能。 – <a href="http://jupiterjs.com/news/stealjs-script-manager">http://jupiterjs.com/news/stealjs-script-manager</a></p>

<p><strong>JSL Script Loader</strong> – 提供了加载、防重复加载、缓存等功能。但是它的用户也许没有LabJS、RequireJS那么多 –  <a href="http://www.andresvidal.com/jsl">http://www.andresvidal.com/jsl</a></p>

<p><strong>Bootstrap</strong> – 它的功能很少，但足以完成任务。如在你在寻找一个最小的没有任何多余功能的解决方案，那么也许它是最合适的。 – <a href="https://bitbucket.org/scott_koon/bootstrap">https://bitbucket.org/scott_koon/bootstrap</a></p>

<h2>2.MVC&amp;管理大型jQuery应用</h2>

<p>软件工程中的设计模式、架构模式可以让你创建可重用的，结构化的，更具组织性的代码。我认为在开发中使用设计模式是必要的，尤其当你需要确保团队编写的代码的风格和结构是一致的时候。</p>

<!--more-->


<p>MVC设计模式通常可以满足web应用的开发的需要，当然你可能觉得MVC并不适合你，或者你需要的是别的设计模式。</p>

<p>在我开始向你介绍一些MVC方案前，如果你需要对设计模式做更多的了解，请去阅读<a href="http://addyosmani.com/blog/essentialjsdesignpatterns">http://addyosmani.com/blog/essentialjsdesignpatterns</a>（免费）。</p>

<p>『吼吼：在开始之前请自行去了解什么是MVC。 这部分内容我就不翻译了。</p>

<h3>为什么我推荐 JavaScriptMVC</h3>

<p>JavaScriptMVC已经收到不少积极的评论，同时它还被认为这是在大型项目开发中最好理解的框架。 如果你习惯使用传统方式构建web应用（比如重父端，轻客户端），那么你在使用JavascriptMVC的时候，会发现你的思想只需要做细微的变化。这是我和其他开发过js大型项目的同事们共同的想法。</p>

<p>举例来说，当你的应用很大一部分是基于js的，而你还需要一堆工具来保证代码的模块化、可管理、可测试、干净的。那么其中有一件事情就是使用JMVC。大多数开发者可能会认为这是服务端该干的事情，但是现在已经到了考虑客户端代码的时候了。</p>

<p>Justin Meyer谈论JMVC项目的时候提到，新人对JMVC最大的迷惑是误解了项目真正提供了什么。在这段之后我会来澄清这块内容。</p>

<p>JMVC可以被当作一个整合的开发工具、一个可重用的MVC架构。JMVC的好处是，它提供了一个清晰的思路来添加功能，并帮你简化里很多的事情。</p>

<p>首先，JavaScriptMVC的MVC部分的含义：</p>

<ul>
<li>Model – 一种封装、组织Ajax请求和web服务数据的方式</li>
<li>Controller – 一个jQuery widget生成器</li>
<li>View – 客户端的模板引擎</li>
</ul>


<p>第二，在为项目提供的集成开发工具方面，你可以得到一下功能。</p>

<ul>
<li>依赖管理、产品构建</li>
<li>自动化的单元测试、功能测试</li>
<li>文档支持</li>
</ul>


<h3>解决方案：</h3>

<p>待翻译，等不及的朋友请看原文。</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[清理浮动的整理]]></title>
    <link href="http://imchao.net/2010/10/14/clean-up-floating/"/>
    <updated>2010-10-14T00:00:00+08:00</updated>
    <id>http://imchao.net/2010/10/14/clean-up-floating</id>
    <content type="html"><![CDATA[<p>清理浮动是前端工程师每天都会用到的技术，目前清理浮动的技术形形色色，另很多新手眼花缭乱。所以我就结合了几篇文章，做了一些整理。</p>

<h2>一、为什么要清理浮动？</h2>

<p>这里我不做细讲，请新手参考《<a href="http://book.douban.com/subject/4736167/" target="_blank">CSS Mastery</a>》中有关浮动的章节。</p>

<p>简单的讲，当我们把一个框向左浮动起来时，它就会脱离文档流，并且向左移动，直到它左边缘碰到其父框的左边缘。当我们把框浮动起来后，会出现各种问题，比如下一个非浮动元素环绕着浮动框。这时候为了正确排版，我们需要把浮动清理。</p>

<h2>二、如何清理浮动？</h2>

<h3>1、采用div标签clear的方式</h3>

<figure class='code'><figcaption><span>html  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'> <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;clear&quot;</span><span class="nt">&gt;&lt;/div&gt;</span>
</span><span class='line'>  
</span></code></pre></td></tr></table></div></figure>




<figure class='code'><figcaption><span>css  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
</pre></td><td class='code'><pre><code class='css'><span class='line'>  <span class="nt">div</span><span class="nc">.clear</span> <span class="p">{</span>
</span><span class='line'>      <span class="k">clear</span><span class="o">:</span><span class="k">both</span><span class="p">;</span>
</span><span class='line'>      <span class="k">height</span><span class="o">:</span><span class="m">0</span><span class="p">;</span>
</span><span class='line'>      <span class="k">line-height</span><span class="o">:</span><span class="m">0</span><span class="p">;</span>
</span><span class='line'>      <span class="k">margin</span><span class="o">:</span><span class="m">0</span><span class="p">;</span>
</span><span class='line'>      <span class="k">padding</span><span class="o">:</span><span class="m">0</span><span class="p">;</span>
</span><span class='line'>      <span class="k">border</span><span class="o">:</span><span class="m">0</span><span class="p">;</span>
</span><span class='line'>      <span class="k">overflow</span><span class="o">:</span><span class="k">hidden</span><span class="p">;</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'>  
</span></code></pre></td></tr></table></div></figure>


<p>优点：代码量极少，复用性极高。</p>

<p>缺点：完全不能完美的适应语义化，不利于改版以及需求变更。</p>

<p>建议：初学者使用，可以让你快速的解决浮动问题。</p>

<h3>2、采用br标签clear的方式<!-- more --></h3>

<figure class='code'><figcaption><span>html  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'>    <span class="nt">&lt;br</span> <span class="na">class=</span><span class="s">&quot;clear&quot;</span> <span class="nt">/&gt;</span>
</span><span class='line'>
</span></code></pre></td></tr></table></div></figure>




<figure class='code'><figcaption><span>css  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
</pre></td><td class='code'><pre><code class='css'><span class='line'>    <span class="nt">br</span><span class="nc">.clear</span><span class="p">{</span>
</span><span class='line'>        <span class="k">clear</span><span class="o">:</span><span class="k">both</span><span class="p">;</span>
</span><span class='line'>        <span class="k">height</span><span class="o">:</span><span class="m">0</span><span class="p">;</span>
</span><span class='line'>        <span class="k">line-height</span><span class="o">:</span><span class="m">0</span><span class="p">;</span>
</span><span class='line'>        <span class="k">margin</span><span class="o">:</span><span class="m">0</span><span class="p">;</span>
</span><span class='line'>        <span class="k">padding</span><span class="o">:</span><span class="m">0</span><span class="p">;</span>
</span><span class='line'>        <span class="k">border</span><span class="o">:</span><span class="m">0</span><span class="p">;</span>
</span><span class='line'>        <span class="k">overflow</span><span class="o">:</span><span class="k">hidden</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span></code></pre></td></tr></table></div></figure>


<p>优点：语义化程度比第5种情况要更优；代码量极少，复用性极高。</p>

<p>缺点：语义化依旧不完美，不利于改版以及需求变更。</p>

<p>建议：初学者使用，可以让你快速的解决浮动问题。</p>

<h3>3、采用br标签以及其自身HTML的clear属性的方式</h3>

<figure class='code'><figcaption><span>html  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'>    <span class="nt">&lt;br</span> <span class="na">clear=</span><span class="s">&quot;all&quot;</span> <span class="nt">/&gt;</span>
</span><span class='line'>
</span></code></pre></td></tr></table></div></figure>


<p>优点：语义化程度比第1、2种情况要更优；代码量最少，复用性极高。</p>

<p>缺点：语义化依旧不完美，不利于改版以及需求变更。</p>

<p>建议：引导初学者思维升级时使用，让其明白与其用classname来控制一种表现，倒不如回归到WEB1.0的时代的网页直接用html属性来控制表现，毕竟后者的代码量更少。</p>

<h3>4、采用伪类:after进行后续空制的高度位零的伪类层清除</h3>

<figure class='code'><figcaption><span>css  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
</pre></td><td class='code'><pre><code class='css'><span class='line'>    <span class="c">/*after伪类+content方式*/</span>
</span><span class='line'>    <span class="nc">.clearfix</span><span class="nd">:after</span> <span class="p">{</span>
</span><span class='line'>        <span class="k">content</span><span class="o">:</span> <span class="s2">&quot;.&quot;</span><span class="p">;</span>
</span><span class='line'>        <span class="k">display</span><span class="o">:</span> <span class="k">block</span><span class="p">;</span>
</span><span class='line'>        <span class="k">height</span><span class="o">:</span> <span class="m">0</span><span class="p">;</span>
</span><span class='line'>        <span class="k">clear</span><span class="o">:</span> <span class="k">both</span><span class="p">;</span>
</span><span class='line'>        <span class="k">visibility</span><span class="o">:</span> <span class="k">hidden</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span></code></pre></td></tr></table></div></figure>


<p>优点：结构语义化完全正确，不会产生其余的怪异问题。</p>

<p>缺点：IE6不支持after伪类。复用方式不当容易造成代码量急剧增大。</p>

<p>建议：要结合与zoom:1;舍得兼容IE6。最外层轻浮动时使用，或清晰模块化复用方式的人使用。</p>

<h3>5、采用CSS overflow:auto的方式撑高</h3>

<figure class='code'><figcaption><span>css  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='css'><span class='line'>    <span class="c">/* 通过overflow auto的方式 */</span>
</span><span class='line'>    <span class="nc">.overflow-auto-clear</span><span class="p">{</span>
</span><span class='line'>        <span class="k">overflow</span><span class="o">:</span><span class="k">auto</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span></code></pre></td></tr></table></div></figure>


<p>优点：结构语义化完全正确，代码量极少。</p>

<p>缺点：多个嵌套后，点击最外层的轻浮动框会遭成最外层至最内层内容全选（FF）；或者在mouseover造成宽度改变时会出现最外层模块有滚动条（IE）。</p>

<p>建议：内个模块使用，请勿嵌套。</p>

<h3>6、采用CSS overflow:hidden的方式产生怪异适应</h3>

<figure class='code'><figcaption><span>css  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='css'><span class='line'>    <span class="c">/* 通过overflow hidden的方式 */</span>
</span><span class='line'>    <span class="nc">.overflow-hidden-clear</span><span class="p">{</span>
</span><span class='line'>        <span class="k">overflow</span><span class="o">:</span><span class="k">hidden</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span></code></pre></td></tr></table></div></figure>


<p>优点：结构语义化完全正确，代码量极少。</p>

<p>缺点：内容增多时候极易不会自动换行而内容被隐藏掉。</p>

<p>建议：宽度固定时使用，请勿嵌套。</p>

<h3>7、采用display:table将对象变成table形式</h3>

<figure class='code'><figcaption><span>css  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='css'><span class='line'>    <span class="c">/* display 的方式*/</span>
</span><span class='line'>    <span class="nc">.display-clear</span><span class="p">{</span>
</span><span class='line'>        <span class="k">display</span><span class="o">:</span><span class="n">table</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span></code></pre></td></tr></table></div></figure>


<p>优点：结构语义化完全正确，代码量极少。</p>

<p>缺点：盒模型属性已经改变，可想而知奇异事件自然多得你数都数不到。</p>

<p>建议：如果你不想改Bug改死你的话，最好不要使用。</p>

<h3>8、采用形式</h3>

<figure class='code'><figcaption><span>css  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='css'><span class='line'>    <span class="c">/* display 的方式*/</span>
</span><span class='line'>    <span class="nc">.display-inline-block-clear</span><span class="p">{</span>
</span><span class='line'>        <span class="k">display</span><span class="o">:</span><span class="k">inline</span><span class="o">-</span><span class="k">block</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span></code></pre></td></tr></table></div></figure>


<p>优点：结构语义化完全正确，代码量极少。</p>

<p>缺点：IE6\7只把它识别为inline，并触发了haslayout，看似效果与inline-block差不多，但还是有区别。而在能正确解析的浏览器中，父容器将变为行内元素。</p>

<p>建议：如果你不想改Bug改死你的话，最好不要使用。</p>

<h3>9、浮动方式</h3>

<figure class='code'><figcaption><span>css  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='css'><span class='line'>    <span class="c">/* float的方式*/</span>
</span><span class='line'>    <span class="nc">.float-clear</span><span class="p">{</span>
</span><span class='line'>        <span class="k">float</span><span class="o">:</span><span class="k">left</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span></code></pre></td></tr></table></div></figure>


<p>优点：结构语义化完全正确，代码量极少。</p>

<p>缺点：下一个元素会受到影响，为此必须全文浮动。</p>

<p>建议：浮动会变得复杂，不建议使用。</p>

<h3>10、zoom方式</h3>

<figure class='code'><figcaption><span>css  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='css'><span class='line'>    <span class="c">/* zoom的方式*/</span>
</span><span class='line'>    <span class="nc">.zoom-clear</span><span class="p">{</span>
</span><span class='line'>        <span class="n">zoom</span><span class="o">:</span><span class="m">1</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span></code></pre></td></tr></table></div></figure>


<p>优点：结构语义化完全正确，代码量极少。</p>

<p>缺点：兼容性太差。</p>

<p>建议：结合其他浮动清除方式使用（见下一节）。</p>

<h3>11、height:1%方式</h3>

<figure class='code'><figcaption><span>css  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='css'><span class='line'>    <span class="c">/* height:1%方式 Hides from IE-mac \*/</span>
</span><span class='line'>    <span class="nc">.clearfix</span> <span class="p">{</span>
</span><span class='line'>        <span class="k">height</span><span class="o">:</span> <span class="m">1</span><span class="o">%</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>    <span class="c">/* End hide from IE-mac */</span>
</span><span class='line'>
</span></code></pre></td></tr></table></div></figure>


<p>优点：结构语义化完全正确，代码量极少。</p>

<p>缺点：兼容性太差。</p>

<p>建议：结合其他浮动清除方式使用（见下一节）。</p>

<h2>三、清理浮动进阶，处理兼容性</h2>

<p>在这里我整理以上11种浮动清理方法在各种浏览器的效果，并作了对比。具体如下图（点击放大）：</p>

<p><a href="http://www.imchao.net/uploads/2010/10/floatcompare.png" title="清理浮动效果比较"><img src="http://www.imchao.net/uploads/2010/10/floatcompare-300x161.png" title="清理浮动效果比较" alt="清理浮动效果比较" /></a></p>

<p>首先我必须把第1、2、3方案淘汰掉，因为其语义化不佳，所以我也不建议使用。至于第7方案，因为其改变了合适模型，会有很多bug，不推荐使用。而第8方案，因为父容器变成了行内元素，可能会对布局带来麻烦，不建议使用。然后是第9方案，它把父元素浮动起来，从而清理了浮动。不幸的是，父元素却又会影响到下一个元素，为此我们不得不把全文浮动起来，这样对布局很不利，所以我再把第9方案淘汰。</p>

<p>然后我们再看第10、11方案，实际上这两个方案是通过触发IE的haslayout，从而达到清除浮动的效果。而haslayout是IE特有的，故其他浏览器不支持。由此可以想到，把第10、11方案与其他第4、5、6方案结合使用。</p>

<p>接下来我们还需要具体讨论第4、5、6方案的使用。</p>

<h3>4、采用伪类:after进行后续空制的高度位零的伪类层清除</h3>

<p>采用这种方法清理浮动，怪异现象最少，是我最推荐的。但是由于其代码复杂，如果不考虑复用方式，将使得整个css文件冗余难懂。解决办法是，在公共css文件中专门定义一个clearfix，需要清理浮动时，直接在父容器引用即可。</p>

<h3>5、CSS overflow:auto &amp; 6、CSS overflow:hidden的方式</h3>

<p>这两种方式正如其原本功能那样，在使用时需要注意其表现。一旦子元素大小超过父容器，其表现就会出现问题（隐藏或出现滚动条）。所以在使用此方式清理浮动到时候一定要在多个浏览器测试。</p>

<h2>四、总结</h2>


<p>看到这里，相信大家已经对清理浮动的技术有数了。清理浮动没有完美的解决方案，在日常工作中，我通常会用到第4、5方案。其中以第4方案为主，我会把它写入项目的base.css中，而第5方案，则在某些不希望在html中到处添加<code>class="clearfix"</code>的时候使用。然后附上第4方案完整版：</p>

<figure class='code'><figcaption><span>css  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
</pre></td><td class='code'><pre><code class='css'><span class='line'>    <span class="nc">.clearfix</span><span class="nd">:after</span> <span class="p">{</span>
</span><span class='line'>        <span class="k">content</span><span class="o">:</span> <span class="s2">&quot;.&quot;</span><span class="p">;</span>
</span><span class='line'>        <span class="k">display</span><span class="o">:</span> <span class="k">block</span><span class="p">;</span>
</span><span class='line'>        <span class="k">height</span><span class="o">:</span> <span class="m">0</span><span class="p">;</span>
</span><span class='line'>        <span class="k">clear</span><span class="o">:</span> <span class="k">both</span><span class="p">;</span>
</span><span class='line'>        <span class="k">visibility</span><span class="o">:</span> <span class="k">hidden</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>    <span class="nc">.clearfix</span> <span class="p">{</span>
</span><span class='line'>        <span class="n">zoom</span><span class="o">:</span> <span class="m">1</span><span class="p">;</span>
</span><span class='line'>        <span class="k">display</span><span class="o">:</span> <span class="k">inline</span><span class="o">-</span><span class="k">block</span><span class="p">;</span>
</span><span class='line'>        <span class="err">_</span><span class="k">height</span><span class="o">:</span> <span class="m">1px</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>    <span class="o">*</span><span class="nt">html</span> <span class="nc">.clearfix</span> <span class="p">{</span>
</span><span class='line'>        <span class="k">height</span><span class="o">:</span> <span class="m">1</span><span class="o">%</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>    <span class="o">*+</span><span class="nt">html</span> <span class="nc">.clearfix</span> <span class="p">{</span>
</span><span class='line'>        <span class="k">height</span><span class="o">:</span> <span class="m">1</span><span class="o">%</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>    <span class="nc">.clearfix</span> <span class="p">{</span>
</span><span class='line'>        <span class="k">display</span><span class="o">:</span> <span class="k">block</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span></code></pre></td></tr></table></div></figure>


<p>好了，以上就是我对清理浮动的整理与分析，希望能给新手带来帮助。如果文中有问题，请大家直接指出，谢谢！下面附上参考文章，如涉及到版权问题，请及时联系我。</p>

<h3>五、参考文章</h3>

<p><a href="http://isd.tencent.com/?p=1122">http://isd.tencent.com/?p=1122</a></p>

<p><a href="http://guitarbean.com/topic/clearfloat/#first-start%22">http://guitarbean.com/topic/clearfloat/#first-start%22</a></p>

<p><a href="http://www.cnblogs.com/hongru/archive/2010/10/06/1844855.html%22">http://www.cnblogs.com/hongru/archive/2010/10/06/1844855.html%22</a></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Yubikey不再记忆密码]]></title>
    <link href="http://imchao.net/2010/03/10/yubikey-nerver-remember-the-password/"/>
    <updated>2010-03-10T00:00:00+08:00</updated>
    <id>http://imchao.net/2010/03/10/yubikey-nerver-remember-the-password</id>
    <content type="html"><![CDATA[<h2>我的密码管理历史</h2>

<p>相信的大家一定有很多帐号。上网这么多年下来，东注册一个帐号，西注册一个帐号。时间长了，觉得老用一套帐号不安全。于是换了一套又一套，久而久之密码堆积了一堆，连自己也搞不清哪个对应哪个了。</p>

<p>就在两年前，我找到了keepass这个软件。它很好的帮我把所有密码管理起来，而且还是跨平台的，我只要记住主密码(master key)就可以取得所有帐号密码。不过我经常要在不同的系统、电脑使用同一个密码库，keepass没有我想要的同步功能。</p>

<p>后来找到了Dropbox这个强大的同步工具，帮keepass弥补了这个缺点。尽管同步问题解决了，可是keepass还是有个致命的弱点&#8211;操作效率太低。每登录一个网站，先要找到这个帐号记录，再复制粘贴帐号，然后还要复制粘贴密码。来来回回折腾太麻烦了，如果keepass能和浏览器结合，自动帮我填入帐号密码就好了。就像浏览器在带的密码管理器一样，不过浏览器自带的不安全，也不方便，不能同步，而且重装系统帐号就丢失了。</p>

<p>后来我发现了Lastpass这个强大的工具，它是浏览器的扩展，支持ie、firefox、chrome，而且跨平台，甚至在iPhone、黑莓、Android上都有客户端。Lastpass是把我的帐号密码存在云端的。每当我在一个网站登录的时候，它会检测这个站点的帐号是否记录过，如果没有，它会提示我记录。当我确定记录帐号后，下次再访问这个站点的时候，lastpass会自动帮我填入帐号密码，我只要按登录即可。</p>

<!--more-->


<p>有了lastpass，我再也不需要同步密码库了，这些信息本生就存储在lastpass公司的服务器上。也许有人会担心。密码存在云端安不安全？lastpass是否可信任？lastpass被黑客攻击了怎么办？对于这些质疑，我只能说没有绝对安全的东西，我们只能相信它。即便存在自己的电脑上，也会遭受病毒、黑客的威胁。一个公司的技术实力总比一个人强吧。</p>

<p>lastpass解决了大部分问题，大大地提高了用户体验。剩下还有一个问题，如何让master key足够的安全呢？</p>

<h2>yubikey，廉价的OTP方案</h2>

<p>对于这个产品相信大家从没听过。这是一款强大又廉价的产品，要把它所有功能都讲清楚是不容易的。所以我就先简单介绍两个功能，以后再扩展。</p>

<h3>一、OTP(One-Time-Password)</h3>

<p>yubikey是个可以根据一定算法随机产生密码的输入设备。yubikey产生的OTP密码分为两部分，左边部分是设备识别码，右边部分是随机码。每个设备的识别码是全球唯一的。</p>

<p>接下来解释一下过程。A网站支持使用yubikey登录，于是我把自己的yubikey和A网站绑定。当访问A网站时，A网站提示输入yubikey密码。我轻触一下yubikey，OTP密码就马上输入好了。这时候A网站会去访问yubikey开发公司的服务器yubico，并提交收到的OTP密码请求认证。yubico得到密码后，把它拆分，根据自己的私有算法进行校验。如果这个密码确实是绑定A网站的密码的那个yubikey设备产生的，yubico就会告诉A网站验证成功。</p>

<p>每个yubikey都根据自己的识别码，以不同方式产生不同的随机密码。每个时刻产生的密码都不同。所以yubikey之间不可以相互冒充。而这种随机验证方式，对于黑客来说更难破解。</p>

<h3>二、Static Password静态密码</h3>

<p>这是yubikey的附加功能。可以记忆一个复杂的、较长的、个人难以记忆的密码。比如：</p>

<p>某B，把sdadasdefkjgbhoijt34tdfKJSW%<sup>$%<sup>&amp;hasdqal942nlsdnfalsz这段作为自己lastpass的master</sup></sup> key。某B不需要记忆这么恐怖的密码。某B只要把它设置到yubikey上。轻触一下yubikey，就可以把密码输入。</p>

<p>很好理解吧，这个功能就是为master key设计的。从此不再需要记忆任何密码。yubikey在密码就在。yubikey丢了，那也就惨了。所以最好在电脑以外的地方备份一下这段密码。</p>

<h2>其他</h2>

<p>yubikey2.1版本支持OTP和StaticPassword同时存在。可以通过轻触时间的长短来区分。用户可以使用官方的工具的来自己定义yubikey的功能，包括密码长短，复杂程度等等。</p>

<p>另外于yubikey的开源项目非常多，比如wordpress上的yubikey验证插件，drapal上的验证插件。大家可以找到很多其他相关的项目。在开发方面，公司开放了很多资料：<a href="http://www.yubico.com/developers/intro/">http://www.yubico.com/developers/intro/</a></p>

<p>最后再提一下，尽管yubikey在诸多OTP方案中，是比较廉价的，25美元一个，不过对于大多数中国草根来说还是挺贵的，而且国内没的卖。幸好yubikey有个竞争对手叫umikey，它们的思路差不多的。umikey在中国有生产，也有卖，100RMB以内，不是很贵。可惜umikey的应用还不是很广泛，我们只能祝福它快速发展。lastpass有个竞争对手叫mashedlife，mashedlife是umikey的最佳搭档。当然据说也可以和yubikey结合（我没试过）。另外听小道消息，unikey正在和lastpass接触。</p>

<p>听我讲了这么多，还是自己去看看吧，相关网址：</p>

<ul>
<li><p><a href="https://lastpass.com/">https://lastpass.com/</a></p></li>
<li><p><a href="http://www.yubico.com/">http://www.yubico.com/</a></p></li>
<li><p><a href="http://www.umikey.com/">http://www.umikey.com/</a></p></li>
<li><p><a href="http://www.umikey.cn/">http://www.umikey.cn/</a></p></li>
<li><p><a href="https://mashedlife.com/">https://mashedlife.com/</a></p></li>
</ul>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[入手yubikey]]></title>
    <link href="http://imchao.net/2010/03/10/start-yubikey/"/>
    <updated>2010-03-10T00:00:00+08:00</updated>
    <id>http://imchao.net/2010/03/10/start-yubikey</id>
    <content type="html"><![CDATA[<p>yubikey是我在春节前买了，大约1周就到了。25$一个，买了两个，一个是帮同学带的，运费20$。因为一直在复习GRE，没时间写文章。接下来让我们来看看yubikey真面目吧。（不知道yubikey？参见<a href="http://imchao.net/2010/03/10/yubikey-nerver-remember-the-password/" title="Yubikey不再记忆密码">Yubikey不再记忆密码</a>）</p>

<p>首先是拿到手的国际邮件：</p>

<p><a href="http://imchao.net/uploads/2010/03/2010-09-03-16.08.26.jpg" title="yubico发来的EMS"><img src="http://imchao.net/uploads/2010/03/2010-09-03-16.08.26-300x225.jpg" title="yubico发来的EMS" alt="yubico发来的EMS" /></a></p>

<!--more-->


<p>拆封后还有一个小信封：</p>

<p><a href="http://imchao.net/uploads/2010/03/4421768071_41d619200d_b.jpg" title="EMS拆开后的小信封"><img src="http://imchao.net/uploads/2010/03/4421768071_41d619200d_b-300x225.jpg" title="EMS拆开后的小信封" alt="EMS拆开后的小信封" /></a></p>

<p>揭开庐山真面目：</p>

<p><a href="http://imchao.net/uploads/2010/03/4421768417_8ea393a414_b.jpg" title="yubikey的真面目"><img src="http://imchao.net/uploads/2010/03/4421768417_8ea393a414_b-300x225.jpg" title="yubikey的真面目" alt="yubikey的真面目" /></a></p>

<p>接入电脑后，会发出绿光，光环中心区域是静电感应区域，轻触就有反应：</p>

<p><a href="http://imchao.net/uploads/2010/03/4421797595_04cccb5486_b.jpg" title="开始yubikey"><img src="http://imchao.net/uploads/2010/03/4421797595_04cccb5486_b-300x225.jpg" title="开始yubikey" alt="开始yubikey" /></a></p>

<p>接下来我演示一下如何使用yubikey：</p>

<p>1.打开浏览器，lastpass处于未登录状态，点击图标：</p>

<p><a href="http://imchao.net/uploads/2010/03/4421844237_502fcacf7e_m.jpg" title="点击lastpass"><img src="http://imchao.net/uploads/2010/03/4421844237_502fcacf7e_m.jpg" title="点击lastpass" alt="点击lastpass" /></a></p>

<p>2.输入邮件地址（可保存），短触yubikey，自动输入密码（可保存）：</p>

<p><a href="http://imchao.net/uploads/2010/03/4422609546_81c009bdd3.jpg" title="登陆lastpass"><img src="http://imchao.net/uploads/2010/03/4422609546_81c009bdd3-300x222.jpg" title="登陆lastpass" alt="登陆lastpass" /></a></p>

<p>3.提示二次验证（此步骤可选），长触yubikey，自动填入OTP密码：</p>

<p><a href="http://imchao.net/uploads/2010/03/4421844351_5d0a8c1c57.jpg" title="lastpass使用yubikey二次认证"><img src="http://imchao.net/uploads/2010/03/4421844351_5d0a8c1c57-300x117.jpg" title="lastpass使用yubikey二次认证" alt="lastpass使用yubikey二次认证" /></a></p>

<p>4.最后登录成功，上网畅通无阻：</p>

<p><a href="http://imchao.net/uploads/2010/03/4422609696_fc31b10387_m.jpg" title="lastpass登陆成功"><img src="http://imchao.net/uploads/2010/03/4422609696_fc31b10387_m.jpg" title="lastpass登陆成功" alt="lastpass登陆成功" /></a></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[用笨办法实现电驴和迅雷直接的互导]]></title>
    <link href="http://imchao.net/2010/03/05/the-realization-of-edonkey-and-thunder-direct-transconductance/"/>
    <updated>2010-03-05T00:00:00+08:00</updated>
    <id>http://imchao.net/2010/03/05/the-realization-of-edonkey-and-thunder-direct-transconductance</id>
    <content type="html"><![CDATA[<p>之前在用电驴下一部比较老的片子，结果挂到95%最后发现已经没人共享了，这很是让人郁闷。然后我拿迅雷离线下载下同样的文件，结果发现迅雷居然下好了，我估计这文件一直存在迅雷的服务器上。如果这时候我用迅雷下载，当然可以下完，但我又不想让那个95%的电驴白下，怎么办呢？</p>

<p>曾经我有一个同学号称下载杀手(什么download breaker，完全盗版imagine breaker嘛)。flashget、迅雷、bitcomet、emule之类的文件他都可以实现互导，不能直接导的，还可以通过修改文件来导入。不过我没这么厉害，我只会把店里的文件后缀改成迅雷的后缀，然后让迅雷导入。这方法以前可行，可是现在好像不行了，不知道为什么。</p>

<p>后来我突发奇想。虽然他们两的文件格式一样，可是他们都遵循ed2k协议。于是我想到了通过ed2k互导。我抱着试一试的心态，把电驴和迅雷都连上同一台ed2k服务器，结果迅雷发现了我的电驴，然后以2m/s的速度下好了95%。最后我用迅雷离线下载把文件下好了，稍微等了一会，电驴也下好了。出于对别人分享的尊敬，我继续把电驴开着给他人分享。</p>

<p>这种方法果然可行，不过有一定成功率。有一次，我的迅雷怎么也连不上自己的电驴。可能是因为下载的人还是比较多的，有干扰。为了解决这个问题，我找到了利器，edonkey server。对，就是在本地搭建私人的电驴服务器，导完后，再关掉。可惜的是edonkey的网站已经关掉了，找不到正宗的官方下载地址。没办法，只能从国内某些下载站下载了。下下来后，发现这个软件很小，而且不需要安装，直接运行即可，非常方便。</p>

<p>用法也很简单。首先启动ed2k服务器，然后在迅雷和电驴里面加入本地地址，我用的是localhost。然后让迅雷电驴都连上去，接着就开始飞快导入咯。很简单吧？</p>

<p>附上ed2k服务器软件（共享一个月）：</p>

<p>Linux版：<a href="https://dl.dropbox.com/u/1284503/ed2k/ed2kserver.gz">https://dl.dropbox.com/u/1284503/ed2k/ed2kserver.gz</a></p>

<p>Windows版：<a href="https://dl.dropbox.com/u/1284503/ed2k/ed2kserver.zip">https://dl.dropbox.com/u/1284503/ed2k/ed2kserver.zip</a></p>

<p>最后提醒大家：</p>

<p>下完后一定要分享！！</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[说说Python包管理]]></title>
    <link href="http://imchao.net/2010/02/05/talk-about-python-package-management/"/>
    <updated>2010-02-05T00:00:00+08:00</updated>
    <id>http://imchao.net/2010/02/05/talk-about-python-package-management</id>
    <content type="html"><![CDATA[<p>虽然我的Python学习才起步，不过有时候也需要装一些额外的软件包。一般Python教程上都推荐使用easy_install。这个工具很酷，有了它，我不需要去找软件包。我可以直接easy_install 包名，它会帮我去pypi查找下载最新的软件包，然后自动安装。这个和Linux上的apt、yum之类的包管理器很类似。但是问题来，作为Linux用户，我不希望我在系统上有两套包管理器。有一天我在安装Mako(一个很快的模板引擎)，我就在想我是使用apt来安装呢，还是使用easy_install来安装。于是我用<code>apt-cache showpkg python-mako</code>检查一下，apt源中的mako是2.4版本的。然后我又用easy_install检查了一下，是2.5版本的。当然，听说easy_install所使用的pypi库的包往往都是最新的。像我这样的更新狂肯定想装2.5版本的，那我应该使用easy_install安装吗？</p>

<p>经我研究发现，easy_install有以下问题：</p>

<ol>
<li><p>卸载能力低下，<code>easy_install -m 包名</code>，可以卸载软件包，但是卸载后还要手动删除遗留文件。</p></li>
<li><p>可能会和apt冲突。比如某天我用easy_install安装了软件包A，后来我在用apt安装软件包B的时候依赖软件包A，而apt并不知道A的存在。</p></li>
</ol>


<!--more-->


<p>这样的工具我还敢用吗？所以我在想有没有什么东西，可以用pypi下载最新的软件包，然后自动打成deb包，再使用dpkg来安装，纳入apt的管理。在寻觅中我找到了<a href="http://pypi.python.org/pypi/stdeb/0.5.1">stdeb</a>这个工具很强大，提供pypi_install的指令，我只需要执行<code>pypi_install Mako</code>，它就会去pypi找最新的mako，然后打成deb包，再安装。很强大吧？让我们看看它还有哪些功能。</p>

<h2>stdeb</h2>

<figure class='code'><figcaption><span>bash  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>    pypi-install mypackage
</span><span class='line'>  
</span></code></pre></td></tr></table></div></figure>


<p>从pypi下载最新软件包，构建deb包，再安装</p>

<figure class='code'><figcaption><span>bash  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>    py2dsc mypackage-0.1.tar.gz
</span><span class='line'>  
</span></code></pre></td></tr></table></div></figure>


<p>使用源码包构建deb src包</p>

<figure class='code'><figcaption><span>bash  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>    python setup.py --command-packages<span class="o">=</span>stdeb.command sdist_dsc
</span><span class='line'>  
</span></code></pre></td></tr></table></div></figure>


<p>在使用setuptools的python源码包中，构建deb src包</p>

<figure class='code'><figcaption><span>bash  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>    python setup.py --command-packages<span class="o">=</span>stdeb.command bdist_deb
</span><span class='line'>  
</span></code></pre></td></tr></table></div></figure>


<p>在使用setuptools的python源码包中，构建deb包</p>

<p>stdeb很强大，不过也有一些问题，比如有时候生成的deb包名与apt源中的不一样。比如我安装web.py的时候，生成的deb包是python-web-py，而apt源中的是python-webpy。这方面stdeb还有待改进那。</p>

<h2>获得stdeb</h2>

<p>如何获得stdeb呢，似乎ubuntu9.10的源中并没有stdeb。不过你可以在这里找到它<a href="http://packages.ubuntu.com/zh-cn/lucid/python-stdeb">http://packages.ubuntu.com/zh-cn/lucid/python-stdeb</a>。</p>

<p>这个版本是给10.04使用的，不过9.10也能用，先用着吧。</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[DIY了家用NAS]]></title>
    <link href="http://imchao.net/2010/01/27/diy-for-home-nas/"/>
    <updated>2010-01-27T00:00:00+08:00</updated>
    <id>http://imchao.net/2010/01/27/diy-for-home-nas</id>
    <content type="html"><![CDATA[<p>随着我收藏的电影、动画不断增多，小小的移动硬盘已经不能满足我对容量的需求。而且家里有两台笔记本、一台上网本、一台高清播放机，等我毕业后，还要从学校搬回一台台式机，就算买了移动硬盘，也不能解决所有设备的存储问题。假期，表弟表妹们经常会来我家玩，看看电影是必然的，这也就面临着数据共享的问题。于是我打算搞一台nas。目前市面上有一些现成的家用nas，比如qnap、buffalo。虽然他们都是基于Linux的，可以自己定制，但是价格比较昂贵，而且性能一般。最终我还是决定自己组一台低功耗计算机当nas使用。</p>

<p>配置如下：</p>

<p>主板：Intel D945GCLF(板载N230、显卡、两个sata接口)</p>

<p>内存：金士顿 1G DDR2</p>

<p>机箱：技展 高清3号机箱（两个3.5寸的仓位）</p>

<p>电源：航嘉冷静王标准版电源 最大300W</p>

<p>（本来想搞DC-ATX这类五风扇电源的，又静音又省电，但是好像都只有一个sata电源接口）</p>

<p>硬盘：西数 WD10EARS 1TB 64M缓存</p>

<p>总价：1500</p>

<p>所有配件都在淘宝上搞定，1天后全部到货。</p>

<!--more-->


<p>这是Atom主板：</p>

<p><a href="http://imchao.net/uploads/2010/01/4307943125_5b1483d2e5_b.jpg" title="装好后的nas主板"><img src="http://imchao.net/uploads/2010/01/4307943125_5b1483d2e5_b-300x225.jpg" alt="装好后的nas主板" /></a></p>

<p>装好后的裸机：</p>

<p><a href="http://imchao.net/uploads/2010/01/4307943127_8cdd05f895_b.jpg" title="nas的组件全部拼接好了"><img src="http://imchao.net/uploads/2010/01/4307943127_8cdd05f895_b-300x225.jpg" alt="nas的组件全部拼接好了" /></a></p>

<p>装好后的样子：</p>

<p><a href="http://imchao.net/uploads/2010/01/4307943137_65bff76b1c_z.jpg" title="装好后的样子"><img src="http://imchao.net/uploads/2010/01/4307943137_65bff76b1c_z-300x225.jpg" alt="装好后的样子" /></a></p>

<p>机箱大小与上网本对比：</p>

<p><a href="http://imchao.net/uploads/2010/01/4307943139_c023400cf6_z.jpg" title="nas机箱与上网本对比"><img src="http://imchao.net/uploads/2010/01/4307943139_c023400cf6_z-300x225.jpg" alt="nas机箱与上网本对比" /></a></p>

<p>花了一下午算是装好了，系统本来是想选用freenas、openfiler，不过我还想有更多的定制性，于是装了ubuntu server，没有装xserver，不需要图形界面。</p>

<p><a href="http://imchao.net/uploads/2010/01/4307943143_5cf4aeabf2_z.jpg" title="nas安装ubuntu server"><img src="http://imchao.net/uploads/2010/01/4307943143_5cf4aeabf2_z-300x225.jpg" alt="nas安装ubuntu server" /></a></p>

<p>然后装了以下服务：</p>

<p>Samba：Windows 文件共享</p>

<p>Apache：http服务器</p>

<p>Mysql：数据库服务器</p>

<p>SSH：远程管理</p>

<p>uShare：多媒体upnp服务器、DLNA</p>

<p>transmission：bt下载</p>

<p>webmin：web端管理</p>

<p>acpid：有了这个直接按电源钮就能关机了。</p>

<p>目前nas正式投入使用了，可以拖动多台电脑同时看电影，当然，1080p的还不行，毕竟家里没有千兆网卡和千兆路由。半夜还能bt下载。</p>

<p>最后给transmission web端来了张照片，很mac啊。</p>

<p><a href="http://imchao.net/uploads/2010/01/4307968795_ae339894f3.jpg" title="nas上的transmission web"><img src="http://imchao.net/uploads/2010/01/4307968795_ae339894f3.jpg" alt="nas上的transmission web" /></a></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Netbook OS分享会]]></title>
    <link href="http://imchao.net/2009/12/27/netbook-os-sharing/"/>
    <updated>2009-12-27T00:00:00+08:00</updated>
    <id>http://imchao.net/2009/12/27/netbook-os-sharing</id>
    <content type="html"><![CDATA[<p>酝酿了很久的分享会，作为杭州<a href="http://groups.google.com/group/hangzhou-gtug">GTUG</a>成立后的首次活动，《Netbook OS大比拼》圆满结束咯。这得要感谢与会的每一位朋友，虽然外面下着大雪，但是还是有很多朋友来了，而且还有三位上海朋友；另外还要特别感谢杭州图书馆，他们为我们提供了一个非常棒的会场，书香气为我们的技术交流更是增添了别样的气氛。</p>

<p>以下是流水帐。这次分享会是由<a href="http://imtx.cn" target="_blank">Tualatrix</a>（以下简称TX）和我共同主持的。会议主题是《Netbook OS大比拼》。<!--more--></p>

<p>分享会开始，TX同学首先给大家带来了Chromium OS的介绍。正如TX同学所介绍的，在WebGL、WebSocket、HTML5这类新技术陆续推出后，Chromium OS可以算是互联网发展的必然产物。确实如此，没有这些技术的支撑，Chromium OS是很难把桌面应用搬到浏览器上的（如:3D网游）；没有V8引擎的强劲保障，工程师也不敢把桌面应用迁移到浏览器上。</p>

<p>秀完很酷的Chromium OS，接下来是我给大家带来的可爱的Moblin。虽然Moblin的很多特效都很酷，但是我还是觉得可爱这个此更适合它。我这次给大家演示的是Intel最新的Moblin V2.1。给大家炫完Moblin的界面后，我又简单的介绍了一下Clutter技术，并且还演示了几个用Python写的Clutter Demo。我接触Moblin近两个月，其实了解的还不是很深，所以不能给大家深入讲解Clutter开发，不过我以后肯定会研究Clutter开发。最后我简单展示了一下我近期的研究成果，一个是完成度70%的gstreamer-plugins的rpm包，一个是ndiswrapper的rpm包，还有就是openvpn的rpm包。Intel的Moblin自带软件包比较少，很多还不能和fedora通用，所以我只能自己动手了。目前我的Moblin已经解决了ath9k的驱动问题，能播放Mp3、Rmvb（无声）了。算是已经基本满足我对OS的需求了。近段时间，我还会在这方面花时间，为了打造我完美可爱的Moblin！</p>

<p>在我们专题展示结束后，我们又给大家展示了一下Gnome3中的组件，gnome-shell，同样采用了clutter技术。最后我还发现这些采用Clutter技术的软件有很多共同点，包括交互的理念，对3d技术的态度。</p>

<p>分享会顺利结束了，我想这是一个好的开始。TX和我只是抛砖引玉，希望以后GTUG每个月的分享会，朋友们都能有所分享，有所收获，我们的分享会越开越精彩。</p>

<p>最后是我们会上的幻灯片，还有python demo包。</p>

<p><a href="http://code-of-tualatrix.googlecode.com/files/chrome-os.pdf">Chromium OS大探秘</a></p>

<p><a href="http://imchao.googlecode.com/files/moblin.pdf" target="_blank">可爱的Moblin</a></p>

<p><a href="http://imchao.googlecode.com/files/pyclutter-demo.tar.gz" target="_blank">pyclutter-demo</a></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[解决1005ha/1008ha在ubuntu 9.10下糟糕的表现]]></title>
    <link href="http://imchao.net/2009/12/06/solve-1005ha1008ha-the-poor-performance-under-ubuntu-9-10/"/>
    <updated>2009-12-06T00:00:00+08:00</updated>
    <id>http://imchao.net/2009/12/06/solve-1005ha1008ha-the-poor-performance-under-ubuntu-9-10</id>
    <content type="html"><![CDATA[<p>自从我的Eee pc 1005ha-h升级到ubuntu 9.10后，无线网络开始不断抽风。</p>

<p>先是信号非常弱，频繁掉线。我在launchpad.net查到1005ha的无线网卡是atheros的ar9285，对应的驱动是ath9k。而ath9k在2.6.31下有兼容性问题，ubuntu的backport驱动解决了这些问题。于是我给2.6.31.14内核安装了backport驱动。</p>

<p>[bash]sudo apt-get install linux-backports-modules-2.6.31-14-generic[/bash]</p>

<p>重启后，信号变强了，线也不掉了，但是网络僵尸了。主要表现在chrome打开一个站点往往需要15-30秒时间，其中至少有10秒时间在解析dns。开始我以为是ipv6导致解析缓慢的，所以我就把ipv6禁用了。</p>

<p>打开配置文件：</p>

<p>[bash]gksu gedit /etc/sysctl.conf [/bash]</p>

<p>在文件最后加入：</p>

<p>[bash]net.ipv6.conf.wlan0.disable_ipv6 = 1[/bash]</p>

<p>重启后发现速度确实快了，但是解析还是需要很长时间。<!--more--></p>

<p>后来在lauchpad.net上看到<a href="https://bugs.launchpad.net/ubuntu/+source/linux-backports-modules-2.6.31/+bug/414560" target="_blank">类似的bug</a>，只要安装backport-wireless的驱动就可以了。</p>

<p>[bash]sudo apt-get install linux-backports-modules-wireless-karmic-generic[/bash]</p>

<p>这个软件包会自动安装2.6.31-15以上的内核，装完后发现，速度更慢了，而且所有加密的无线网络都连不上了。我看了一下日志。</p>

<p>[bash]tail /var/log/syslog[/bash]</p>

<p>发现下面的错误几乎总是日志的最后一行。</p>

<p>[bash]wpa_supplicant[922]: CTRL-EVENT-SCAN-RESULTS[/bash]</p>

<p>接着我又在launchpad.net找到了<a href="https://bugs.launchpad.net/ubuntu/+source/linux/+bug/460886" target="_blank">对应的bug</a>，但是至今还没有解决。此时我已经1周不能正常上网了，每天下班回来就开始折腾ath9k驱动，弄得快崩溃了。甚至后来还考虑给1005ha换个无线模块或者买个usb的无线网卡。我装了个windows 7，打算逛逛淘宝。在装驱动的时候突然想到，好像有个什么软件可以让linux使用windows的驱动。这就是ndiswrapper。于是我赶忙去asus官网下了个<a href="http://dlsvr04.asus.com/pub/ASUS/EeePC/1005HAB/WLAN_NE785.zip " target="_blank">xp版的驱动</a>。下好后解压，里面有个ndis5x文件夹，这是我要用的，先放一边，装个ndiswrapper再说：</p>

<p>[bash]sudo apt-get install ndiswrapper-utils-1.9[/bash]</p>

<p>装好后我进入ndis5x目录，安装驱动，这会需要一小会时间。</p>

<p>[bash]sudo ndiswrapper -i netathw.inf[/bash]</p>

<p>装好后，我们为modprobe生成一个配置文件。</p>

<p>[bash]sudo ndiswrapper -m[/bash]</p>

<p>再打开module的配置文件</p>

<p>[bash]gksu gedit /etc/modules [/bash]</p>

<p>在尾行加入以下内容</p>

<p>[bash]ndiswrapper[/bash]</p>

<p>检查一下驱动是否正确安装。</p>

<p>[bash]ndiswrapper -l[/bash]</p>

<p>如果有下面内容就表示已经正确安装了。</p>

<p>[bash]netathw : driver installed<br />
	device (168C:002B) present (alternate driver: ath9k)[/bash]</p>

<p>好了，我们把ath9k卸了再加载ndiswrapper看看</p>

<p>[bash]sudo rmmod ath9k<br />
sudo modprobe ndiswrapper[/bash]</p>

<p>此时无线应该已经可用，速度飞快。最后收个尾，把ath9k禁用。</p>

<p>打开modprobe的blacklist</p>

<p>[bash]gksu gedit /etc/modprobe.d/blacklist.conf[/bash]</p>

<p>在尾行加入</p>

<p>[bash]ath9k[/bash]</p>

<p>弄好ndiswrapper后，我的网络非常稳定，至今还没有异常断过。</p>

<p>如果你的在用linux 2.6.31的内核，如果你的网卡也是悲剧的atheros生产的，如果你也正在饱受ath9k的折磨，那么不妨尝试一下我的方案吧。</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[在Moblin2.1-preview上编译安装ibus]]></title>
    <link href="http://imchao.net/2009/11/08/compiled-in-the-moblin2-1-preview-install-ibus/"/>
    <updated>2009-11-08T00:00:00+08:00</updated>
    <id>http://imchao.net/2009/11/08/compiled-in-the-moblin2-1-preview-install-ibus</id>
    <content type="html"><![CDATA[<p>前段时间安装了Moblin2.1-preview版，一直没玩。今天突然有兴致跑进去玩玩。先是改了一下源，升级了一把，大概250MB。然后发现浏览器变成firefox3.5了，支持书签和插件，clutter下的ff就是漂亮，上网一定很爽！可是为什么不给我装好输入法呢？找了半天也没有找到安装的入口，所以我进shell安装了scim。</p>

<p>[bash]<br />
yum install scim scim-pinyin scim-bridge scim-bridge-gtk scim-bridge-clutter<br />
[/bash]</p>

<p>装好后发现很多地方用不了scim。我只好抛弃了scim，转投ibus。</p>

<p>ibus没有现成的包，必须手动编译。于是我开始手动编译，接下来的过程消耗了我一个晚上，弄得我头昏脑胀，可算是凄惨啊。
<h2>编译ibus</h2>
参考地址：http://code.google.com/p/ibus/wiki/Install</p>

<p>先把依赖包装好:</p>

<p>[bash]<br />
yum install git gnome-common autoconf automake libtool glib2-devel intltool gtk-doc GConf-dbus-devel make gcc clutter-devel dbus-python-devel iso-codes-devel<br />
[/bash]</p>

<p>然后把源代码下下来：</p>

<p>[bash]<br />
git clone git://github.com/phuang/ibus.git ibus<br />
cd ibus<br />
[/bash]</p>

<p>开始编译</p>

<p>[bash]<br />
./autogen.sh &#8211;prefix=&#8217;/usr&#8217; &#8211;sysconfdir=&#8217;/etc&#8217; &#8211;libdir=&#8217;/usr/lib&#8217; &#8211;enable-gtk-doc<br />
make<br />
sudo make install<br />
[/bash]</p>

<p>我在运行autogen.sh的时候出现了以下错误：</p>

<p>Makefile.am: required file `./ChangeLog&#8217; not found</p>

<p>直接输入下面指令后，重新运行autogen.sh</p>

<p>[bash]<br />
touch ChangeLog<br />
[/bash]
<h2>编译ibus-pinyin</h2>
先安装依赖包：</p>

<p>[bash]<br />
yum install sqlite-devel gcc-c++ libuuid-devel<br />
[/bash]</p>

<p>下载源代码：</p>

<p>[bash]<br />
git clone git://github.com/phuang/ibus-pinyin.git ibus-pinyin<br />
cd ibus-pinyin<br />
[/bash]</p>

<p>开始编译：</p>

<p>[bash]<br />
./autogen.sh &#8211;prefix=/usr<br />
make<br />
sudo make install<br />
[/bash]
<!--more-->
<h2>编译ibus-client-clutter</h2>
参考地址：http://moblin.org/documentation/input-method-framework/guide-ibus-moblin2</p>

<p>先解决依赖问题：</p>

<p>[bash]<br />
yum install clutter-imcontext-devel<br />
[/bash]</p>

<p>下载源代码</p>

<p>[bash]<br />
git clone git://git.moblin.org/ibus-client-clutter<br />
cd ibus-client-clutter<br />
[/bash]</p>

<p>开始编译：</p>

<p>[bash]<br />
./autogen.sh &#8211;prefix=/usr &#8211;sysconfdir=/etc<br />
[/bash]<br />
这时候会出错，它要求clutter的版本一定要是0.9的。我们修改一下配置文件：</p>

<p>[bash]<br />
vi configure.ac<br />
[/bash]</p>

<p>找到clutter-0.9 &gt;= 0.9.7</p>

<p>改成clutter-1.0 &gt;= 0.9.7</p>

<p>重新运行autogen.sh，问题解决</p>

<p>[bash]<br />
make<br />
sudo make install<br />
[/bash]</p>

<p>刷新Clutter IMContext Framework的配置文件</p>

<p>[bash]<br />
clutter-scan-immodules &gt; /tmp/clutter.immodules<br />
sudo cp /tmp/clutter.immodules /etc/clutter-imcontext/clutter.immodules<br />
clutter-scan-immodules &gt; /tmp/clutter.immodules<br />
sudo cp /tmp/clutter.immodules /etc/clutter-imcontext/clutter.immodules<br />
[/bash]</p>

<p>最后在环境变量中加入：</p>

<p>[bash]<br />
export CLUTTER_IM_MODULE=ibus<br />
export GTK_IM_MODULE=ibus<br />
[/bash]</p>

<p>大功告成，重启一下，就可以使用ibus了。</p>

<p>什么？重启后ibus还没有启动？</p>

<p>原因是缺少pydxg。我们去http://www.freedesktop.org/wiki/Software/pyxdg下载最新源码</p>

<p>下载好后先安装需要的安装环境：</p>

<p>[bash]<br />
yum install python-devel<br />
[/bash]</p>

<p>然后安装</p>

<p>[bash]<br />
tar zxvf pyxdg-0.18.tar.gz<br />
cd pyxdg-0.18<br />
python setup.py install<br />
[/bash]</p>

<p>OK了，这下就可以使用ibus了。</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[在Eee PC 1005ha上为Ubuntu打开多点触控]]></title>
    <link href="http://imchao.net/2009/11/06/setting-up-multi-touch-scrolling-for-ubuntu-9-10-karmic-koala-linux-on-asus-eee-1005ha-netbook/"/>
    <updated>2009-11-06T00:00:00+08:00</updated>
    <id>http://imchao.net/2009/11/06/setting-up-multi-touch-scrolling-for-ubuntu-9-10-karmic-koala-linux-on-asus-eee-1005ha-netbook</id>
    <content type="html"><![CDATA[<p>原文：<a href="http://blog.twinapex.fi/2009/10/11/setting-up-multi-touch-scrolling-for-ubuntu-9-10-karmic-koala-linux-on-asus-eee-1005ha-netbook/">Setting up multi-touch scrolling for Ubuntu 9.10 Karmic Koala Linux on Asus Eee 1005HA netbook</a></p>

<p>虽然本文是基于Asus EeePC 1005ha的，但是本文阐述的方法也适用于其他采用Synaptics的笔记本。</p>

<p>多点触控允许用户使用双指手势在触摸板上进行UI操作。苹果率先在Macbook引入了此技术，大大提高了在上网本上浏览网页的用户体验。最重要的手势是双指滚动文本。</p>

<p>苹果还有很多相关的手势专利，所以他们不会被默认启用。</p>

<p>真正的多点触控需要多点感知(电容)的触摸板支持。但是大多数笔记本都没有配备这种触摸板。不过很幸运，我们可以在压力敏感的触摸板上通过计算和技巧模拟出一些类似双指滚动的简单手势。</p>

<p>注意：<a href="https://bugs.launchpad.net/ubuntu/+source/xserver-xorg-input-synaptics/+bug/355071" target="_blank">Ubuntu HAL对Synaptics的支持有问题</a>。只有最后那段shell脚本是有用的。在FDI文件中的HAL设定被忽略了。
<h2>设定Synaptics驱动</h2>
在终端中输入：<br />
[bash]<br />
gksudo gedit /etc/hal/fdi/policy/11-x11-synaptics.fdi<br />
[/bash]<br />
把下面内容粘贴进去：<!--more--></p>

<p>[xml]<br />
&lt;?xml version=”1.0″ encoding=”ISO-8859-1″?&gt;<br />
&lt;deviceinfo version=”0.2″&gt;<br />
    &lt;device&gt;<br />
        &lt;match key=”info.capabilities” contains=”input.touchpad”&gt;<br />
            &lt;merge key=”input.x11_driver” type=”string”&gt;synaptics&lt;/merge&gt;<br />
            &lt;merge key=”input.x11_options.SHMConfig” type=”string”&gt;On&lt;/merge&gt;<br />
            &lt;merge key=”input.x11_options.EmulateTwoFingerMinZ” type=”string”&gt;40&lt;/merge&gt;<br />
            &lt;merge key=”input.x11_options.VertTwoFingerScroll” type=”string”&gt;1&lt;/merge&gt;<br />
            &lt;merge key=”input.x11_options.HorizTwoFingerScroll” type=”string”&gt;1&lt;/merge&gt;<br />
            &lt;merge key=”input.x11_options.TapButton1″ type=”string”&gt;1&lt;/merge&gt;<br />
            &lt;merge key=”input.x11_options.TapButton2″ type=”string”&gt;3&lt;/merge&gt;<br />
            &lt;!–two finger tap -&gt; middle clieck(3) –&gt;<br />
            &lt;merge key=”input.x11_options.TapButton3″ type=”string”&gt;2&lt;/merge&gt;<br />
            &lt;!–three finger tap -&gt; right click(2). almost impossible to click –&gt;<br />
        &lt;/match&gt;<br />
    &lt;/device&gt;<br />
&lt;/deviceinfo&gt;<br />
[/xml]</p>

<p>这个设定将允许我们使用synclient在终端观察触摸板的实时数据。</p>

<p>现在重启X：<br />
[bash]<br />
sudo /etc/init.d/gdm restart<br />
[/bash]<br />
然后在终端中输入：<br />
[bash]<br />
synclient -m 100<br />
[/bash]<br />
接着你将在终端看到这样的数据：<br />
[bash]<br />
129.355  2912 3469  59 1  4  0 0 0 0 0  00000000   0  0  0   0   0<br />
129.455  2952 3529  59 1  4  1 0 0 0 0  00000000   0  0  0   0   0<br />
time     x    y   z f  w  l r u d m     multi  gl gm gr gdx gdy<br />
129.555  3283 3516  60 1  4  1 0 0 0 0  00000000   0  0  0   0   0<br />
129.656  3928 3517  60 1  4  1 0 0 0 0  00000000   0  0  0   0   0<br />
129.756  4364 3637  60 1  4  1 0 0 0 0  00000000   0  0  0   0   0<br />
129.856  4020 3329  49 1  4  0 0 0 0 0  00000000   0  0  0   0   0<br />
129.956  3634 3122  58 1  4  0 0 0 0 0  00000000   0  0  0   0   0<br />
130.057  3320 2957  60 1  4  0 0 0 0 0  00000000   0  0  0   0   0<br />
130.157  2779 3312  61 1  4  0 0 0 0 0  00000000   0  0  0   0   0<br />
130.257  2557 3739  61 1  4  0 0 0 0 0  00000000   0  0  0   0   0<br />
130.358  2636 3485  39 1  4  0 0 0 0 0  00000000   0  0  0   0   0<br />
130.458  2659 3104  60 1  4  0 0 0 0 0  00000000   0  0  0   0   0<br />
130.558  2671 2988  60 1  4  0 0 0 0 0  00000000   0  0  0   0   0<br />
[/bash]</p>

<p>f表示触摸板上的手指数，w表示触摸区域的宽度，z表示触摸的压力。</p>

<p>如果你用两只手指按在触摸板上，f值等于2，这代表你的触摸板支持多点感应。不过很不幸运，看样子华硕EeePC 1005ha支持1个点。
<h2>模拟方法</h2>
Synaptics的驱动可以在以下环境模拟双指触摸：
<ul>
	<li>触摸区域的宽度超过一定阈值（最小宽度）</li>
	<li>触摸压力超过一定阈值</li>
</ul>
当出现以上情况，驱动会认为也许用户正在使用两个手指。注意，每种触摸板都有特定的值，不能互用。</p>

<p><a href="http://manpages.ubuntu.com/manpages/karmic/man4/synaptics.4.html" target="_blank">Synaptics驱动设定的介绍在这里</a>。我们可以在允许时使用xinput指令来修改Synaptics的驱动设置。开一个窗口，用synclient -m 100监控。再在另一个窗口修改阈值，直到你找到笔记本触摸板的模拟参数。下面是我的xinput测试,在firefox中滚动任意长的网页。</p>

<p>[bash]<br />
moo@huiskuttaja:~$ xinput set-int-prop &quot;SynPS/2 Synaptics TouchPad&quot; &quot;Synaptics Two-Finger Width&quot; 32 7<br />
moo@huiskuttaja:~$ xinput set-int-prop &quot;SynPS/2 Synaptics TouchPad&quot; &quot;Synaptics Two-Finger Pressure&quot; 32 280<br />
moo@huiskuttaja:~$ xinput set-int-prop &quot;SynPS/2 Synaptics TouchPad&quot; &quot;Synaptics Two-Finger Width&quot; 32 11<br />
moo@huiskuttaja:~$ xinput set-int-prop &quot;SynPS/2 Synaptics TouchPad&quot; &quot;Synaptics Two-Finger Pressure&quot; 32 50<br />
moo@huiskuttaja:~$<br />
[/bash]</p>

<p>以下参数比较适合华硕EeePC 1005ha:<br />
[bash]<br />
width(W):8<br />
pressure(Z):10<br />
[/bash]<br />
你可以用synclient -l来dump现在的设置。</p>

<p>以下是最终在登录时运行的脚本（参见<a href="https://bugs.launchpad.net/ubuntu/+source/xserver-xorg-input-synaptics/+bug/355071" target="_blank">Ubuntu HAL对Synaptics的支持有问题</a>）：<br />
[bash]<br />
#!/bin/sh<br />
#
# Use xinput &#8211;list-props &quot;SynPS/2 Synaptics TouchPad&quot; to extract data<br />
#
# Set multi-touch emulation parameters<br />
xinput set-int-prop &quot;SynPS/2 Synaptics TouchPad&quot; &quot;Synaptics Two-Finger Pressure&quot; 32 10<br />
xinput set-int-prop &quot;SynPS/2 Synaptics TouchPad&quot; &quot;Synaptics Two-Finger Width&quot; 32 8<br />
xinput set-int-prop &quot;SynPS/2 Synaptics TouchPad&quot; &quot;Two-Finger Scrolling&quot; 8 1<br />
xinput set-int-prop &quot;SynPS/2 Synaptics TouchPad&quot; &quot;Synaptics Two-Finger Scrolling&quot; 8 1 1<br />
# Disable edge scrolling<br />
xinput set-int-prop &quot;SynPS/2 Synaptics TouchPad&quot; &quot;Synaptics Edge Scrolling&quot; 8 0 0 0<br />
# This will make cursor not to jump if you have two fingers on the touchpad and you list one<br />
# (which you usually do after two-finger scrolling)<br />
xinput set-int-prop &quot;SynPS/2 Synaptics TouchPad&quot; &quot;Synaptics Jumpy Cursor Threshold&quot; 32 110<br />
[/bash]</p>

<p>当你在双指滚动时，如果一只手指提前提出来，鼠标箭头会跳动。Synaptics的驱动好像没有相关设置可以用来过滤这样的问题事件。如果有朋友有解决方案，请务必留言。谢谢！
<h2>其他资源</h2>
<ul>
	<li><span style="background-color: #ffffff;"><a href="http://randomtruth.110mb.com/blog/index.php/2009/03/30/v10-of-linux-multi-touch-released/" target="_blank">Linux 多点触控</a>项目是一个收集Perl脚本的工程。这些脚本与多点事件有关。如果你想定制你的多点触控经验并且你有一些开发经验，这个地方可以帮助入门。</span></li>
	<li><span style="background-color: #ffffff;"><a href="https://bugs.launchpad.net/ubuntu/+source/xserver-xorg-input-synaptics/+bug/422224" target="_blank">关于模拟多点触控的注意事项</a>（看最后的留言）</span></li>
	<li><span style="background-color: #ffffff;"><a href="http://ubuntu-snippets.blogspot.com/2009/03/multi-touch-for-anyall-synaptics.html" target="_blank">诊断多点支持和HAL文件编辑</a></span></li>
	<li><span style="background-color: #ffffff;"><a href="http://brainstorm.ubuntu.com/idea/3077/" target="_blank">在Ubuntu 头脑风暴上的有关idea</a> </span></li>
	<li><span style="background-color: #ffffff;"><a href="http://cgit.freedesktop.org/xorg/driver/xf86-input-synaptics/" target="_blank">Synaptics X11 驱动源代码</a>. <a href="http://web.telia.com/~u89404340/touchpad/index.html" target="_blank">Synaptics 驱动项目主页</a>. 看起来它背后没有一个核心人物，除了维护和来自分销商的大量补丁。</span></li>
</ul></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[imchao在feedsky上的feed出问题了]]></title>
    <link href="http://imchao.net/2009/08/27/imchao-in-the-feed-on-the-problem-of-feedsky/"/>
    <updated>2009-08-27T00:00:00+08:00</updated>
    <id>http://imchao.net/2009/08/27/imchao-in-the-feed-on-the-problem-of-feedsky</id>
    <content type="html"><![CDATA[<p>在<a href="https://twitter.com/bangchuinan" target="_blank">@棒槌男</a>同学的提醒下，吼吼发现本站托管在feedsky的feed很久没有更新了。不知何故，吼吼强制提交更新了几次，可是还是没有解决问题。</p>

<p>于是吼吼决定放弃feedsky了。feedsky上的feed30天后删除。请想继续关注本站的朋友们，把订阅器中的feed更新为http://www.imchao.net/feed</p>

<p>感谢大家的支持，再次感谢一下<a href="https://twitter.com/bangchuinan" target="_blank">@棒槌男</a>同学。</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[EeePC 1005ha(1008ha)安装Ubuntu的完美方案]]></title>
    <link href="http://imchao.net/2009/08/21/perfect-ubuntu-on-the-asus-eeepc-1005ha-and-1008ha/"/>
    <updated>2009-08-21T00:00:00+08:00</updated>
    <id>http://imchao.net/2009/08/21/perfect-ubuntu-on-the-asus-eeepc-1005ha-and-1008ha</id>
    <content type="html"><![CDATA[<p>原文：<a href="http://www.jfwhome.com/2009/08/06/perfect-ubuntu-jaunty-on-the-asus-eeepc-1005ha-and-1008ha/" target="_blank">《Perfect Ubuntu Jaunty on the Asus eeePC 1005HA (and 1008HA)》</a></p>

<p>本文并没有按照原文100%翻译，吼吼去掉了一些无关紧要的内容，同时还做了一些完善性的修改。</p>

<p><strong>准备工作</strong>
<p style="padding-left: 30px;">在这里我们使用的是Ubuntu netbook remix版。这是为上网本设计的，内核也是特殊定制的。即使你不喜欢上网本版的界面，你也可以在装好后，通过设置很容易地恢复到默认的界面。</p>
<p style="padding-left: 30px;">下载<a href="http://www.ubuntu.org.cn/getubuntu/download-netbook/" target="_blank">Ubuntu netbook remix</a></p>
<p style="padding-left: 30px;">请准备好u盘，然后<a href="https://help.ubuntu.com/community/Installation/FromImgFiles" target="_blank">参照这里</a>制作安装盘。</p>
<p style="padding-left: 30px;">在开始前请确定您已经阅读完本文。如果您只有一台电脑，请在开始前把需要下载的驱动文件都下载好。准备就绪后，我们开始安装。</p>
<p style="padding-left: 30px;">先关掉Boot Booster，以便我们使用U盘进行引导：</p>
<p style="padding-left: 30px;">开机按F2进入BIOS设置。在Boot settings里找到Boot Booster，把他设为disable，按F10保存退出重启。</p>
<p style="padding-left: 30px;">当机器开始重启时，按Ese进入启动选择菜单，选择U盘启动。</p>
<p style="padding-left: 30px;">进入Ubuntu启动菜单后，直接进入安装。<!--more--></p></p>

<p><strong>分区</strong>
<p style="padding-left: 30px;">请根据自己的需要进行分区。但是有以下几点需要注意：</p>
<p style="padding-left: 30px;">1.如果您要使用boot booster功能，请不要破坏EFI分区。</p>
<p style="padding-left: 30px;">2.如果您已经破坏了EFI分区，请先分配一个16M的主分区，我们会在最后讲述如何修复EFI。</p>
<p style="padding-left: 30px;">3.如果您需要休眠功能，请给swap分区分配2倍于内存大小的空间。</p>
<p style="padding-left: 30px;">关于boot booster与EFI：</p>
<p style="padding-left: 30px;">华硕所谓的boot booster功能，其实就是使用一个至少8M的EFI分区来缓存BIOS的信息，以节省开机自检的几秒时间。EFI分区一定要是主分区，文件系统类型是EFI。</p></p>

<p><strong>有线网卡</strong>
<p style="padding-left: 30px;">当系统安装好后，我们进入配置阶段。我们首先安装有线网卡的驱动。</p>
<p style="padding-left: 30px;">访问<a href="http://partner.atheros.com/Drivers.aspx" target="_blank">http://partner.atheros.com/Drivers.aspx</a> 下载“AR81Family Linux Driver”</p>
<p style="padding-left: 30px;">解压驱动：</p>
<p style="padding-left: 60px;"><em><strong>tar zxvf AR81Family-linux-v1.0.0.10.tar.gz</strong></em></p>
<p style="padding-left: 30px;">进入源码目录：</p>
<p style="padding-left: 60px;"><em><strong>cd src</strong></em></p>
<p style="padding-left: 30px;">进行编译安装：</p>
<p style="padding-left: 60px;"><strong><em>make</em></strong></p>
<p style="padding-left: 60px;"><strong><em>sudo make install</em></strong></p>
<p style="padding-left: 60px;"><strong><em>sudo insmod atl1e.ko</em></strong></p>
<p style="padding-left: 30px;">PS:以后更新内核后，请按使用<em><strong> sudo rmmod atl1e.ko</strong></em> 卸载驱动后，按照上面步骤重新安装。</p>
<p style="padding-left: 30px;">现在开始，您的有线网络已经可以用了，请先接入互联网。</p></p>

<p><strong>无线网卡</strong>
<p style="padding-left: 30px;">进入Administration（系统管理）&gt;Software Sources（软件源&gt;Updates（更新）</p>
<p style="padding-left: 30px;">启用Unsupported Updates (jaunty-backports) 中文是不支持的更新(jaunty-backports)</p>
<p style="padding-left: 30px;">安装驱动：</p>
<p style="padding-left: 60px;"><strong><em>sudo apt-get install linux-backports-modules-jaunty</em></strong></p></p>

<p><strong>切换界面</strong>
<p style="padding-left: 30px;">进入Preferences(首选项)&gt;Switch Desktop Mode(切换桌面模式)，选择经典桌面。</p>
<p style="padding-left: 30px;">GNOME的面板在屏幕上占用太多空间。您可以设置它们自动隐藏。右键单击面板，并选择属性，点击自动隐藏。</p></p>

<p><strong>安装Super Hybrid Engine、eeePC托盘工具、快捷键</strong>
<p style="padding-left: 30px;">超级混合引擎（Super Hybrid Engine）是华硕的一项节能技术，可以让使用者依不同需求来选择以高效模式或节能模式运作。</p>
<p style="padding-left: 30px;">托盘工具与快捷键都可以让你用很简单的方法来开关系统集成的外设。</p>
<p style="padding-left: 30px;">在这里我们推荐“eeepc-tray”这个软件，这个软件集成了Super Hybrid Engine、eeePC托盘工具、快捷键三大功能。</p>
<p style="padding-left: 30px;">接下来我们开始安装。</p>
<p style="padding-left: 30px;">先下载key文件<a href="http://www.statux.org/ubuntu/key/statux.pub" target="_blank">http://www.statux.org/ubuntu/key/statux.pub</a></p>
<p style="padding-left: 30px;">然后参照这里把源设置好<a href="http://www.statux.org/content?page=repo">http://www.statux.org/content?page=repo</a></p>
<p style="padding-left: 30px;">然后我安装软件：</p>
<p style="padding-left: 60px;"><em><strong>sudo apt-get install eeepc-tray eeepc-laptop-dkms</strong></em></p>
<p style="padding-left: 30px;">装好后重启。现在除了Fn+Space、Fn+F3、触摸板开关以外，其他的快捷键都可以用了。</p></p>

<p><strong>完善快捷键</strong>
<p style="padding-left: 30px;">首先我们要使触摸板能被其他程序访问。</p>
<p style="padding-left: 30px;">编辑配置文件：</p>
<p style="padding-left: 60px;"><strong><em>sudo gedit /etc/hal/fdi/policy/shmconfig.fdi</em></strong></p>
<p style="padding-left: 30px;">把下面内容放粘贴进去：</p>
<p style="padding-left: 60px;"><strong><em>&lt;?xml version=&#8221;1.0&#8221; encoding=&#8221;UTF-8&#8221;?&gt;</em></strong></p>
<p style="padding-left: 60px;"><strong><em>&lt;deviceinfo version=&#8221;0.2&#8221;&gt;</em></strong></p>
<p style="padding-left: 60px;"><strong><em>&lt;device&gt;</em></strong></p>
<p style="padding-left: 60px;"><strong><em>&lt;match key=&#8221;info.product&#8221; string=&#8221;SynPS/2 Synaptics TouchPad&#8221;&gt;</em></strong></p>
<p style="padding-left: 60px;"><strong><em>&lt;merge key=&#8221;input.x11_options.SHMConfig&#8221; type=&#8221;string&#8221;&gt;True&lt;/merge&gt;</em></strong></p>
<p style="padding-left: 60px;"><strong><em>&lt;merge key=&#8221;input.x11_driver&#8221; type=&#8221;string&#8221;&gt;synaptics&lt;/merge&gt;</em></strong></p>
<p style="padding-left: 60px;"><strong><em>&lt;/match&gt;</em></strong></p>
<p style="padding-left: 60px;"><strong><em>&lt;/device&gt;</em></strong></p>
<p style="padding-left: 60px;"><strong><em>&lt;device&gt;</em></strong></p>
<p style="padding-left: 60px;"><strong><em>&lt;match key=&#8221;info.linux.driver&#8221; string=&#8221;psmouse&#8221;&gt;</em></strong></p>
<p style="padding-left: 60px;"><strong><em>&lt;merge key=&#8221;input.x11_options.SHMConfig&#8221; type=&#8221;string&#8221;&gt;True&lt;/merge&gt;</em></strong></p>
<p style="padding-left: 60px;"><strong><em>&lt;/match&gt;</em></strong></p>
<p style="padding-left: 60px;"><strong><em>&lt;/device&gt;</em></strong></p>
<p style="padding-left: 60px;"><strong><em>&lt;/deviceinfo&gt;</em></strong></p>
<p style="padding-left: 30px;">保存后重启。</p>
<p style="padding-left: 30px;">进入系统后右键eeepc-tray的图标，点击Edit Configuration，然后把下面内容粘贴进去：</p>
<p style="padding-left: 60px;"><em><strong>#Touchpad control</strong></em></p>
<p style="padding-left: 60px;"><em><strong>KEY_TOUCHPAD=&#8221;00000037&#8221;</strong></em></p>
<p style="padding-left: 60px;"><em><strong># Fn + space</strong></em></p>
<p style="padding-left: 60px;"><em><strong>KEY_FSB=&#8221;00000039&#8221;</strong></em></p>
<p style="padding-left: 30px;">现在所有快捷键都可以使用了。</p></p>

<p><strong>麦克风</strong>
<p style="padding-left: 30px;">打开Volume Control，点击Preferences，启用所有Mic和Input Source选项。</p>
<p style="padding-left: 30px;">然后把input source设为Int Mic。</p>
<p style="padding-left: 30px;">在skype中把声音输入设备设置为HDA Intel (hw:Intel, 0)。声音输出设备设为pulse。</p></p>

<p><strong>设定EFI分区，启用boot booster</strong>
<p style="padding-left: 30px;">查看分区列表：</p>
<p style="padding-left: 60px;">sudo fdisk -l</p>
<p style="padding-left: 30px;">找到你的之前给EFI分好的分区，如/dev/sda1</p>
<p style="padding-left: 30px;">设定为EFI分区：</p>
<p style="padding-left: 60px;"><em><strong>sudo sfdisk &#8211;change-id /dev/sda 1 ef</strong></em></p>
<p style="padding-left: 60px;"><strong>注意</strong><strong>，请把这里的1改为你的EFI分区的分区号</strong><strong>，比如你的EFI分区是/dev/sda2,那么分区号是2</strong></p>
<p style="padding-left: 30px;">最后重启，按F2进入BIOS，重新把boot booster打开。</p></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[给1005ha-h装了三系统]]></title>
    <link href="http://imchao.net/2009/08/13/1005ha-h-fitted-to-the-three-systems/"/>
    <updated>2009-08-13T00:00:00+08:00</updated>
    <id>http://imchao.net/2009/08/13/1005ha-h-fitted-to-the-three-systems</id>
    <content type="html"><![CDATA[<p>贝壳机买回来后，就开始不断的折腾。现在我已经给它装了三个系统了：ubuntu、windows7、moblin</p>

<p>开机后使用的是ubuntu的grub引导的。有三个系统可选。</p>

<p><a href="http://www.imchao.net/wp-content/uploads/2009/08/3817231013_de2534329a_b.jpg"><img class="aligncenter size-medium wp-image-324" title="eeepc上的三系统" src="http://www.imchao.net/wp-content/uploads/2009/08/3817231013_de2534329a_b-300x200.jpg" alt="" width="300" height="200" /></a></p>

<p>这是漂亮的moblin，我升级了一下，但是源里没有最新的clutter包，所以导致了部分程序不能使用。今天尝试编译了一下clutter，结果提示No glib-gettextize,怎么办那。</p>

<p><!--more--></p>

<p><a href="http://www.imchao.net/wp-content/uploads/2009/08/3818041170_9073f0e87b.jpg"><img class="aligncenter size-medium wp-image-325" title="eeepc上的moblin" src="http://www.imchao.net/wp-content/uploads/2009/08/3818041170_9073f0e87b-300x175.jpg" alt="" width="300" height="175" /></a></p>

<p>接下来是windows7，看这图形性能。。。</p>

<p><a href="http://www.imchao.net/wp-content/uploads/2009/08/3817231725_0b3421a33b.jpg"><img class="aligncenter size-medium wp-image-326" title="eeepc上的win7评分" src="http://www.imchao.net/wp-content/uploads/2009/08/3817231725_0b3421a33b-300x175.jpg" alt="" width="300" height="175" /></a></p>

<p>最后是ubuntu netbook remix。</p>

<p><a href="http://www.imchao.net/wp-content/uploads/2009/08/3817231927_c5f2c931e1.jpg"><img class="aligncenter size-medium wp-image-327" title="eeepc上的ubuntu netbook remix" src="http://www.imchao.net/wp-content/uploads/2009/08/3817231927_c5f2c931e1-300x175.jpg" alt="" width="300" height="175" /></a></p>

<p>三个系统安装都很顺利，但是对epc驱动支持不完全。moblin里面没有有线网卡的驱动，ubuntu中有线网卡和无线网卡都没有驱动。win7问题不大，通过update把驱动都补全了。</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[入手了EeePC1005ha-h]]></title>
    <link href="http://imchao.net/2009/08/11/start-a-eeepc1005ha-h/"/>
    <updated>2009-08-11T00:00:00+08:00</updated>
    <id>http://imchao.net/2009/08/11/start-a-eeepc1005ha-h</id>
    <content type="html"><![CDATA[<p>那啥，我先承认错误，以及提前承认错误。本人计划毕业后出国留学，目前正在准备GRE考试。所以上网的时间不多了，写blog的时间也不多了，也许会有很长时间不写blog了。但是我还是尽量写一点吧。</p>

<p>8月初，我入手了1005ha-h，华硕的贝壳机哟，非常漂亮。1005ha-h在所有上网本中有着不俗的性能，和长达10.5小时的超长续航时间。以后吼吼就可以带着上网本出去稍微游荡一会了，上个网，喝点茶什么的。呵呵，在这里我顺便再教唆一下TualatriX，赶快去买上网本吧。</p>

<p>接下来show一下照片。</p>

<p><a href="http://www.imchao.net/wp-content/uploads/2009/08/2009-08-04-14.20.19.jpg"><img class="aligncenter size-medium wp-image-344" title="1008ha" src="http://www.imchao.net/wp-content/uploads/2009/08/2009-08-04-14.20.19-300x225.jpg" alt="" width="300" height="225" /></a></p>

<p><!--more--></p>

<p>这是在百脑汇看到的1008ha，比我的1005还漂亮，还要轻。全封闭式的，电池不可拆卸，从侧面可以看到，非常薄。不错，1008ha是epc中最轻薄的一款。</p>

<p><a href="http://www.imchao.net/wp-content/uploads/2009/08/2009-08-04-14.20.37.jpg"><img class="aligncenter size-medium wp-image-345" title="1005ha" src="http://www.imchao.net/wp-content/uploads/2009/08/2009-08-04-14.20.37-300x225.jpg" alt="" width="300" height="225" /></a></p>

<p>这是1005ha系列的侧面，相比1008ha确实厚了很多，电池是可拆卸的，所以有3芯电和6芯电之选。</p>

<p>本人在颐高、百脑汇内的所有华硕专卖店做过调查后，发现只有百脑汇里面的一家有1005ha-h卖，其他店铺连1005ha-h是啥都不知道。我看价格合适，一激动就买下来了。</p>

<p><a href="http://www.imchao.net/wp-content/uploads/2009/08/2009-08-04-16.18.19.jpg"><img class="aligncenter size-medium wp-image-346" title="1005ha-h包装盒" src="http://www.imchao.net/wp-content/uploads/2009/08/2009-08-04-16.18.19-300x225.jpg" alt="" width="300" height="225" /></a></p>

<p>这是包装盒。准备拆封拉。。</p>

<p>哈哈，这就是我买的上网本。</p>

<p><a href="http://www.imchao.net/wp-content/uploads/2009/08/2009-08-04-16.20.41.jpg"><img class="aligncenter size-medium wp-image-348" title="1005ha-h" src="http://www.imchao.net/wp-content/uploads/2009/08/2009-08-04-16.20.41-300x225.jpg" alt="" width="300" height="225" /></a></p>

<p>这是拆封后的全家福。主机、电池、电源、说明书、保修卡、光盘。还有万恶的绿坝安装说明。</p>

<p><img class="aligncenter size-medium wp-image-347" title="1005ha-h" src="http://www.imchao.net/wp-content/uploads/2009/08/2009-08-04-16.22.03-300x225.jpg" alt="" width="300" height="225" /></p>
]]></content>
  </entry>
  
</feed>

