参加2013年九三学社上海市委信息骨干培训

时间:2013.5.31

地点:天等路社会主义学院

有幸参加了2013年九三学社上海市委信息骨干培训,由九三学社中央参政议政部副巡视员张瑛做专题辅导报告。通过这次学习,使我深刻了解反映社情民意信息是供领导科学决策的一种参政议政方式,也是党派参政议政,旅行参政党职能的一个重要内容。今后需要更加认真的学习和思考,不断增强政治意识、群众意识、责任意识和质量意识,提高政治把握能力和参政议政能力,适应新形势、新任务的要求,更好的旅行参政党党员的职能。

 

徐汇区纪念中共中央发布“五一口号”65周年座谈会

时间:2013.4.28 上午9:00

地点:乌鲁木齐南路218号7楼

徐汇区纪念中共中央发布“五一口号”65周年座谈会。会议由钱燕主持,各民主党派和无党派人士参加。其中民盟邹德礼、民建李忠铮、致公陈汝作、民革、民进、九三朱国建、农工奚云斐、台盟代表发言交流了对五一口号精神的认识。

 

 

参加2013CAIF民用飞机航电国际论坛(Civil avionics international forum)

2013CAIF在上海长宁龙之梦万利酒店举行,本人有幸参加了此次论坛。此次论坛云集了众多航电设备设计制造的大牌厂商,是国内航电领域的盛会。

(8:00会场签到的场面)

(会场情况)

(8:30中国航空学会理事长刘高倬开幕致辞)

(615所所长王国庆作报告)

(我也露个脸)

制作ramdisk

mkdir /mnt/tmp
dd if=/dev/zero of=initrd.img bs=1k count=4096(注意4096*1k=4M,于是这里制作的ramdisk是4M大小的,如有需要调节count的大小就可以制作不同大小的ramdisk)
mkfs.ext2 -F MyRam.img
mount -o loop MyRam.img /mnt/tmp
把需要弄到ramdisk里的文件全部拷贝到/mnt/tmpd里面
umount /mnt/tmp
gzip --best -c MyRam.img > MyRam.img.gz
MyRam.img.gz就是制作好的ramdisk了

 

网站迁移到bluehost上了

以前用的justhost的web hosting,由于当时只买了一年的服务,现在到期了,续约竟然要一个月8$的价格,太贵,于是迁移到bluehost上了,一次性买了3年服务共计142$,很便宜。

转载:Xlib库使用基础

Basic Graphics Programming With The Xlib Library
http://users.actcom.co.il/~choo/lupg/tutorials/xlib-programming/xlib-programming.html
1.  Preface
2. The Client And Server Model Of The X Window System
3. GUI programming - the Asynchronous Programming Model
4. Basic Xlib Notions
1. The X Display
2. The GC - Graphics Context
3. Object Handles
4. Memory Allocation For Xlib Structures
5. Events
5. Compiling Xlib-Based Programs
6. Opening And Closing The Connection To An X Server
7. Checking Basic Information About A Display
8. Creating A Basic Window - Our "hello world" Program
9. Drawing In A Window
1. Allocating A Graphics Context (GC)
2. Drawing Primitives - Point, Line, Box, Circle...
10. X Events
1. Registering For Event Types Using Event Masks
2. Receiving Events - Writing The Events Loop
3. Expose Events
4. Getting User Input
1. Mouse Button Click And Release Events
2. Mouse Movement Events
3. Mouse Pointer Enter And Leave Events
4. The Keyboard Focus
5. Keyboard Press And Release Events
5. X Events - A Complete Example
11. Handling Text And Fonts
1. The Font Structure
2. Loading A Font
3. Assigning A Font To A Graphics Context
4. Drawing Text In A Window
12. Windows Hierarchy
1. Root, Parent And Child Windows
2. Events Propagation
13. Interacting With The Window Manager
1. Window Properties
2. Setting The Window Name And Icon Name
3. Setting Preferred Window Size(s)
4. Setting Miscellaneous Window Manager Hints
5. Setting An Application's Icon
14. Simple Window Operations
1. Mapping And UN-Mapping A Window
2. Moving A Window Around The Screen
3. Resizing A Window
4. Changing Windows Stacking Order - Raise And Lower
5. Iconifying And De-Iconifying A Window
6. Getting Info About A Window
15. Using Colors To Paint The Rainbow
1. Color Maps
2. Allocating And Freeing Color Maps
3. Allocating And Freeing A Color Entry
4. Drawing With A Color
16. X Bitmaps And Pixmaps
1. What Is An X Bitmap? An X Pixmap?
2. Loading A Bitmap From A File
3. Drawing A Bitmap In A Window
4. Creating A Pixmap
5. Drawing A Pixmap In A Window
6. Freeing A Pixmap
17. Messing With The Mouse Cursor
1. Creating And Destroying A Mouse Cursor
2. Setting A Window's Mouse Cursor
--------------------------------------------------------------------------------
Preface
This tutorial is the first in a series of "would-be" tutorials about graphical programming in the X window environment. By itself, it is useless. A real X programmer usually uses a much higher level of abstraction, such as using Motif (or its free version, lesstiff), GTK, QT and similar libraries. However, we need to start somewhere. More than this, knowing how things work down below is never a bad idea.
After reading this tutorial, one would be able to write very simple graphical programs, but not programs with a descent user interface. For such programs, one of the previously mentioned libraries would be used.
--------------------------------------------------------------------------------
X窗口系统的客户/服务器模式
当初开发X窗口系统的主要目的只有一个,那就是灵活性。这个灵活性的意思就是说一件东西虽然看起来是在这工作,但却实际上是工作在很远的地方。因此,较低 等级的实现部分就必须提供绘制窗口,处理用户输入,画画,使用颜色等工作的工具。在这个要求下,决定了系统被分成了两部分,客户端和服务器端。客户端决定 做什么,服务器端执行真正的绘图和接受用户的输入并把它发给客户端。
这种模式与我们一般习惯的客户端和服务器端的概念是正好相反的。在我们的情况下,用户就坐在服务器端控制的机器前,而客户端这时却是运行在远程主机上。服 务器端控制着显示屏,鼠标和键盘。一个客户端也许正连接着服务器端,要求给它画一个窗口(或者是一堆),并要求服务器端把用户对它的窗口的输入传给它。结 果,好几个客户端可能连接到了一个服务器端上-有的在运行一个电子邮件软件,有的在运行一个网页浏览器等。当用户输入了指令给窗口,服务器端就会把指令打 包成事件传给控制那个窗口的客户端,客户端根据接受到的事件决定干什么然后发送请求让服务器端去画什么。
以上介绍的会话都是通过X消息协议传输的。该协议是实现在TCP/IP协议上的,它允许在一个网络里的客户端访问这个网络里的任何服务器端。最后,X服务 器端可以和客户端运行在同一台机器上以获得性能优化(注意,一个X协议事件可能会达到上百KB),例如使用共享内存,或者使用Unix域socket(在 一个Unix系统的两个进程间创建一个本地通道进行通信的方法)。
--------------------------------------------------------------------------------
图形用户接口(GUI)编程-异步编程模式
不像我们通常的令人愉快的程序,一个GUI程序通常使用异步编程模式,也就是下面要介绍的"事件驱动编程"。这个"事件驱动编程"的意思是说程序通常都处 于空闲状态,等待从X服务器发来的事件,等收到了事件,才根据事件做相应的事情。一个事件可能是"用户在屏幕某处x,y点击了鼠标左键",或者是"你控制 的窗口需要被重画"。因为程序要回应用户的请求,同时还需要刷新自己的请求队列,因此需要程序尽可能使用较短的事件来处理一个事件(例如,作为一条公认的 准则,不能超过200毫秒)。
这也暗示着当然存在需要程序处理很长时间才能完成的事件(例如一个到远程服务器的网络连接,或者是连接一个数据库,或者是不幸的要处理一个超大文件的复制 工作)。这都要求程序使用异步方式来处理而不是通常的同步方式。这时候就应该采用各种各样的异步编程方法来进行这些耗时的工作了,或者干脆把它们交给一个 线程或进程来进行。
根据以上的说明,一个GUI程序就应该像以下的方式来工作:
进行初始化工作
连接X服务器
进行与X相关的初始化工作
进行循环
从X服务器那里接受下一个事件
根据收到的事件发送各种绘图指令给X服务器
如果事件是个退出事件,结束循环
关闭与X服务器的连接
进行资源释放工作
--------------------------------------------------------------------------------
Xlib的基本思想
X协议是非常复杂的,为了大家不用再辛辛苦苦把时间浪费在实现它上面,就有了一个叫"Xlib"的库。这个库提供了访问任何X服务器的非常底层的手段。因 为X协议已经被标准化了,理论上客户程序使用任何Xlib的实现都可以访问任何X服务器。在今天,这看起来可能很琐碎,但如果回到那个使用字符终端和专有 绘图方法的时代,这应该是一个很大的突破吧。实际上,你很快发现围绕瘦客户机,窗口终端服务器等领域会有许多多么令人兴奋的事情。
--------------------------------------------------------------------------------
X显示
使用XLib的基本思想就是X显示。它代表了一个打开的到X服务器的连接的结构。它隐藏了一个保存有从X服务器来的事件的队列,和一个保存客户程序准备发往服务器的请求队列。在Xlib里,这个结构被命名为显示"Display"。
当我们打开了一个到X服务器的连接,库就会返回一个指向这个结构的指针。然后,我们就可以使用这个指针来使用Xlib里各种各样的函数。
--------------------------------------------------------------------------------
GC - 图形上下文
当我们进行各种绘图操作(图形,文本等)的时候,我们也许会使用许多参数来指定如何绘制,前景,背景,使用什么颜色,使用什么字体等等,等等。为了避免为 每个绘图函数设置数量惊人的参数,我们使用一个叫"GC"的图形上下文结构。我们在这个结构里设置各种绘图参数,然后传给绘图函数就行了。这应当是一个非 常方便的方法吧,尤其当我们在进行一连串操作中使用相同的参数时。
--------------------------------------------------------------------------------
对象句柄
当X服务器为我们创建了各种各样的对象的时候 - 例如窗口,绘图区和光标 - 相应的函数就会返回一个句柄。这是一个存在在X服务器空间中的对象的一个标识-而不是在我们的应用程序的空间里。在后面我们就可以使用Xlib的函数通过 句柄来操纵这些对象。X服务器维护了一个实际对象到句柄的映射表。Xlib提供了各种类型来定义这些对象。虽然这些类型实际上只是简单的整数,但我们应该 继续使用这些类型的名字 - 理由是为了可移植。
--------------------------------------------------------------------------------
Xlib结构的内存分配
Xlib的接口使用了各种类型的结构。有些可以由用户直接来分配内存,有些则只能使用专门的Xlib库函数来分配。在使用库来分配的情况,库会生成有适当 初始参数的结构。这对大家来说是非常方便的,指定初始值对于不太熟练的程序员来说是非常头疼的。记住-Xlib想要提供非常灵活的功能,这也就意味着它也 会变得非常复杂。提供初始值设置的功能将会帮助那些刚开始使用X的程序员们,同时不会干扰那些高高手们。
在释放内存时,我们使用与申请的同样方法来释放(例如,使用free()来释放malloc()申请的内存)。所以,我们必须使用XFree()来释放内存。
事件
一个叫"XEvent"的结构来保存从X服务器那里接受到的事件。Xlib提供了非常大量的事件类型。XEvent包括事件的类型,以及与事件相关的数据 (例如在屏幕什么地方生成的事件,鼠标键的事件等等),因此,要根据事件类型来读取相应的事件里的数据。这时,XEvent结构使用c语言里的联合来保存 可能的数据(如果你搞不清楚c的联合是怎么回事,那你就得花点时间再读读你的教科书了)。结果,我们就可能受到XExpose事件,一个XButton事 件,一个XMotion事件等等。
--------------------------------------------------------------------------------
编译基于Xlib的程序
编译基于Xlib的程序需要与Xlib库连接。可以使用下面的命令行:
cc prog.c -o prog -lX11
如果编译器报告找不到X11库,可以试着加上"-L"标志,像这样:
cc prog.c -o prog -L/usr/X11/lib -lX11
或者这样(针对使用X11的版本6)
cc prog.c -o prog -L/usr/X11R6/lib -lX11
在SunOs 4 系统上,X的库被放到了 /usr/openwin/lib
cc prog.c -o prog -L/usr/openwin/lib -lX11
等等,具体情况具体分析
--------------------------------------------------------------------------------
打开,关闭到一个X服务器的连接
一个X程序首先要打开到X服务器的连接。我们需要指定运行X服务器的主机的地址,以及显示器编号。X窗口允许一台机器开多个显示。然而,通常只有一个编号 为"0"的显示。如果我们想要连接本地的显示(例如进行显示的机器同时又是客户程序运行的机器),我们可以直接使用":0"来连接。现在我们举例,连接一 台地址是"simey"的机器的显示,我们可以使用地址"simey:0",下面演示如何进行连接
#include  /* defines common Xlib functions and structs. */
.
.
/* this variable will contain the pointer to the Display structure */
/* returned when opening a connection. */
Display* display;
/* open the connection to the display "simey:0". */
display = XOpenDisplay("simey:0");
if (display == NULL) {
fprintf(stderr, "Cannot connect to X server %s\n", "simey:0");
exit (-1);
}
注意,通常要为X程序检查是否定义了环境变量"DISPLAY",如果定义了,可以直接使用它来作为XOpenDisplay()函数的连接参数。
当程序完成了它的工作且需要关闭到X服务器的连接,它可以这样做:
XCloseDisplay(display);
这会使X服务器关闭所有为我们创建的窗口以及任何在X服务器上申请的资源被释放。当然,这并不意味着我们的客户程序的结束。
--------------------------------------------------------------------------------
检查一个显示的相关基本信息
一旦我们打开了一个到X服务器的连接,我们应该检查与它相关的一些基本信息:它有什么样的屏幕,屏幕的尺寸(长和宽),它支持多少颜色(黑色和白色?灰度 级?256色?或更多),等等。我们将演示一些有关的操作。我们假设变量"display"指向一个通过调用XOpenDisplay()获得的显示结 构。
/* this variable will be used to store the "default" screen of the */
/* X server. usually an X server has only one screen, so we're only */
/* interested in that screen. */
int screen_num;
/* these variables will store the size of the screen, in pixels. */
int screen_width;
int screen_height;
/* this variable will be used to store the ID of the root window of our */
/* screen. Each screen always has a root window that covers the whole */
/* screen, and always exists. */
Window root_window;
/* these variables will be used to store the IDs of the black and white */
/* colors of the given screen. More on this will be explained later. */
unsigned long white_pixel;
unsigned long black_pixel;
/* check the number of the default screen for our X server. */
screen_num = DefaultScreen(display);
/* find the width of the default screen of our X server, in pixels. */
screen_width = DisplayWidth(display, screen_num);
/* find the height of the default screen of our X server, in pixels. */
screen_height = DisplayHeight(display, screen_num);
/* find the ID of the root window of the screen. */
root_window = RootWindow(display, screen_num);
/* find the value of a white pixel on this screen. */
white_pixel = WhitePixel(display, screen_num);
/* find the value of a black pixel on this screen. */
black_pixel = BlackPixel(display, screen_num);
还有很多其它的宏来帮助我们获取显示的信息,你可以在Xlib里的参考里找到。另外还有很多相当的函数可以完成相同的工作。
--------------------------------------------------------------------------------
创建一个基本的窗口 - 我们的"Hello world"程序
在我们获得一些窗口的基本信息之后,我们就可以开始创建我们的第一个窗口了。Xlib支持好几个函数来创建窗口,它们其中的一个是XCreateSimpleWindow()。这个函数使用很少的几个参数来指定窗口的尺寸,位置等。以下是它完整的参数列表:
Display* display
指向显示结构的指针
Window parent
新窗口的父窗口的ID。
int x
窗口的左上X坐标(单位为屏幕像素)
int y
窗口的左上Y坐标(单位为屏幕像素)
unsigned int width
窗口的宽度(单位为屏幕像素)
unsigned int height
窗口的高度(单位为屏幕像素)
unsigned int border_width
窗口的边框宽度(单位为屏幕像素)
unsigned long border
用来绘制窗口边框的颜色
unsigned long background
用来绘制窗口背景的颜色
让我们创建一个简单的窗口,它的宽度是屏幕宽的1/3,高度是屏幕高的1/3,背景色是白色,边框是黑色,边框的宽度是2个像素。该窗口将会被放置到屏幕的左上角。
/* this variable will store the ID of the newly created window. */
Window win;
/* these variables will store the window's width and height. */
int win_width;
int win_height;
/* these variables will store the window's location. */
int win_x;
int win_y;
/* calculate the window's width and height. */
win_width = DisplayWidth(display, screen_num) / 3;
win_height = DisplayHeight(display, screen_num) / 3;
/* position of the window is top-left corner - 0,0. */
win_x = win_y = 0;
/* create the window, as specified earlier. */
win = XCreateSimpleWindow(display,
RootWindow(display, screen_num),
win_x, win_y,
win_width, win_height,
win_border_width, BlackPixel(display, screen_num),
WhitePixel(display, screen_num));
事实上我们创建窗口并不意味着它将会被立刻显示在屏幕上,在缺省情况下,新建的窗口将不会被映射到屏幕上,它们是不可见的。为了能让我们创建的窗口能被显示到屏幕上,我们使用函数XMapWindow():
XMapWindow(win);
如果想察看目前为止我们所举的例子的代码,请参看源程序simple-window.c。你将会发现两个新的函数 -
XFlush() 和XSync()。函数XFlush()刷新所有处于等待状态的请求到X服务器 - 非常像函数fflush()刷新所有的内容到标准输出。XSync()也刷新所有处于等待状态的请求,接着等待X服务器处理完所有的请求再继续。在一个一 般的程序里这不是必须的(据此你可以发现我们什么时候只是写一个一般的程序),但我们现在把它们提出来,尝试在有或没有这些函数的情况下程序不同的行为。
--------------------------------------------------------------------------------
在窗口里绘制
在窗口里绘图可以使用各种绘图函数 - 画点,线,圈,矩形,等等。为了能在一个窗口里绘图,我们首先需要定义各种参数 - 如线的宽度,使用什么颜色,等等。这都需要使用一个图形上下文(GC)。
--------------------------------------------------------------------------------
申请一个图形上下文(GC)
如我们已经提到的,一个图形上下文定义一些参数来使用绘图函数。因此,为了绘制不同的风格,我们可以在一个窗口里使用多个图形上下文。使用函数 XCreateGC()可以申请到一个新的图形上下文,如以下例(在这段代码里,我们假设"display"指向一个显示结构,"win"是当前创建的一 个窗口的ID):
/* this variable will contain the handle to the returned graphics context. */
GC gc;
/* these variables are used to specify various attributes for the GC. */
/* initial values for the GC. */
XGCValues values = CapButt | JoinBevel;
/* which values in 'values' to check when creating the GC. */
unsigned long valuemask = GCCapStyle | GCJoinStyle;
/* create a new graphical context. */
gc = XCreateGC(display, win, valuemask, &values);
if (gc  0)
break;
/* ok, now draw the line... */
XDrawLine(display, win, gc, 0, 100, 400, 100);
break;
--------------------------------------------------------------------------------
获取用户输入
就目前来说,用户的输入主要从两个地方过来 - 鼠标和键盘。有各种各样的事件帮助我们来获取用户的输入 - 一个键盘上的键被按下了,一个键盘上的键被松开了,鼠标光标离开了我们的窗口,鼠标光标进入了我们的窗口等等。
--------------------------------------------------------------------------------
鼠标按键事件和松开事件
我们为我们的窗口处理的第一个事件是鼠标按钮时间。为了注册一个这样的事件类型,我们将追加以下的面具
ButtonPressMask
通知我们窗口中的任何一个鼠标键按下动作
ButtonReleaseMask
通知我们窗口中的任何一个鼠标键松开动作
在我们的事件循环中通过switch来检查以下的事件类型
ButtonPress
在我们的窗口上一个鼠标键被按下了
ButtonRelease
在我们的窗口上一个鼠标键被松开了
在事件结构里,通过"an_event.xbutton"来获得事件的类型,另外它还包括下面这些有趣的内容:
Window window
事件发送的目标窗口的ID(如果我们为多个窗口注册了事件)
int x, y
从窗口的左上坐标算起,鼠标键按下时光标在窗口中的坐标
int button
鼠标上那个标号的按钮被按下了,值可能是Button1,Button2,Button3
Time time
事件被放进队列的时间。可以被用来实现双击的处理下面的例子,将演示我们如何在鼠标的位置画点,无论我们何时收到编号为1的按钮的"鼠标按下"的事件时我 们画一个黑点,收到编号为2的按钮的"鼠标按下"的事件时我们擦掉那个黑点(例如画一个白点)。我们假设现在有两个GC,gc_draw使用下面的代码
case ButtonPress:
/* store the mouse button coordinates in 'int' variables. */
/* also store the ID of the window on which the mouse was */
/* pressed. */
x = an_event.xbutton.x;
y = an_event.xbutton.y;
the_win = an_event.xbutton.window;
/* check which mouse button was pressed, and act accordingly. */
switch (an_event.xbutton.button) {
case Button1:
/* draw a pixel at the mouse position. */
XDrawPoint(display, the_win, gc_draw, x, y);
break;
case Button2:
/* erase a pixel at the mouse position. */
XDrawPoint(display, the_win, gc_erase, x, y);
break;
default: /* probably 3rd button - just ignore this event. */
break;
}
break;
--------------------------------------------------------------------------------
鼠标光标的进入和离开事件
另一个程序通常会感兴趣的事件是,有关鼠标光标进入一个窗口的领域以及离开那个窗口的领域的事件。有些程序利用该事件来告诉用户程序现在在焦点里面。为了注册这种事件,我们将会在函数XSelectInput()里注册几个面具。
EnterWindowMask
通知我们鼠标光标进入了我们的窗口中的任意一个
LeaveWindowMask
通知我们鼠标光标离开了我们的窗口中的任意一个
我们的事件循环中的分支检查将检查以下的事件类型
EnterNotify
鼠标光标进入了我们的窗口
LeaveNotify
鼠标光标离开了我们的窗口
这些事件类型的数据结构通过例如"an_event.xcrossing"来访问,它还包含以下有趣的成员变量:
Window window
事件发送的目标窗口的ID(如果我们为多个窗口注册了事件)
Window subwindow
在一个进入事件中,它的意思是从那个子窗口进入我们的窗口,在一个离开事件中,它的意思是进入了那个子窗口,如果是"none",它的意思是从外面进入了我们的窗口。
int x, y
从窗口的左上坐标算起,事件产生时鼠标光标在窗口中的坐标
int mode
鼠标上那个标号的按钮被按下了,值可能是Button1,Button2,Button3
Time time
事件被放进队列的时间。可以被用来实现双击的处理
unsigned int state
这个事件发生时鼠标按钮(或是键盘键)被按下的情况 - 如果有的话。这个成员使用按位或的方式来表示
Button1Mask
Button2Mask
Button3Mask
Button4Mask
ShiftMask
LockMask
ControlMask
Mod1Mask
Mod2Mask
Mod3Mask
Mod4Mask
它们的名字是可以扩展的,当第五个鼠标钮被按下时,剩下的属性就指明其它特殊键(例如Mod1一般是"ALT"或者是"META"键)
Bool focus
当值是True的时候说明窗口获得了键盘焦点,False反之
--------------------------------------------------------------------------------
键盘焦点
在屏幕上同时会有很多窗口,但同一时间只能有一个窗口获得键盘的使用。X服务器是如何知道哪一个窗口可以发送键盘事件呢?这个是通过使用键盘焦点来实现 的。在同一时间只能有一个窗口获得键盘焦点。Xlib函数里存在函数允许程序让指定窗口获得键盘焦点。用户通常使用窗口管理器来为窗口设置焦点(通常是点 击窗口的标题栏)。
一旦我们的窗口获得了键盘焦点,每个键的按下和松开都将引起服务器发送事件给我们的程序(如果已经注册了这些事件的类型)。
--------------------------------------------------------------------------------
键盘键按下和松开事件
如果我们程序控制的窗口获得了键盘焦点,它就可以接受按键的按下和松开事件。为了注册这些事件的类型,我们就需要通过函数XSelectInput()来注册下面的面具。
KeyPressMask
通知我们的程序什么时候按键被按下了
KeyPressMask
通知我们的程序什么时候按键被松开了
我们的事件循环中的分支检查将检查以下的事件类型
Window window
事件发送的目标窗口的ID(如果我们为多个窗口注册了事件)
unsigned int keycode
被按下(或松开)的键的编码。这是一些X内部编码,应该被翻译成一个键盘键符号才能方便使用,将会在下面介绍。
int x, y
从窗口的左上坐标算起,事件产生时鼠标光标在窗口中的坐标
Time time
事件被放进队列的时间。可以被用来实现双击的处理
unsigned int state
这个事件发生时鼠标按钮(或是键盘键)被按下的情况 - 如果有的话。这个成员使用按位或的方式来表示
Button1Mask
Button2Mask
Button3Mask
Button4Mask
ShiftMask
LockMask
ControlMask
Mod1Mask
Mod2Mask
Mod3Mask
Mod4Mask
它们的名字是可以扩展的,当第五个鼠标钮被按下时,剩下的属性就指明其它特殊键(例如Mod1一般是"ALT"或者是"META"键)
如我们前面所提到的,按键编码对我们来说是没有什么意义的,它是由连接着X服务器的键盘产生的硬件级编码并且是与某个型号的键盘相关的。为了能解释到底是 哪个按键产生的事件,我们把它翻译成已经被标准化了的按键符号。我们可以使用函数XKeycodeToKeysym()来完成这个翻译工作。该函数使用3 个参数:一个显示的指针,要被翻译的键盘编码,和一个索引(我们在这里使用"0")。标准的Xlib键编码可以参考文 件"X11/keysymdef.h"。在下面的例子里我们使用函数XkeycodeToKeysym来处理按键操作,我们讲演示如何以以下顺序处理按键 事件:按"1"键将会在鼠标的当前位置下画一个点。按下"DEL"键将擦除那个点。按任何字母键(a至z,大写或小写)将在标准输出里打印。其它的按键将 会被无视。假设下面的"case"段代码是在一个消息循环中。
case KeyPress:
/* store the mouse button coordinates in 'int' variables. */
/* also store the ID of the window on which the mouse was */
/* pressed. */
x = an_event.xkey.x;
y = an_event.xkey.y;
the_win = an_event.xkey.window;
{
/* translate the key code to a key symbol. */
KeySym key_symbol = XKeycodeToKeysym(display, an_event.xkey.keycode, 0);
switch (key_symbol) {
case XK_1:
case XK_KP_1: /* '1' key was pressed, either the normal '1', or */
/* the '1' on the keypad. draw the current pixel. */
XDrawPoint(display, the_win, gc_draw, x, y);
break;
case XK_Delete: /* DEL key was pressed, erase the current pixel. */
XDrawPoint(display, the_win, gc_erase, x, y);
break;
default: /* anything else - check if it is a letter key */
if (key_symbol >= XK_A && key_symbol = XK_a && key_symbol fid);
"fid"领域是一个XFontStruct结构用来为各种请求识别各种装载的字体。
--------------------------------------------------------------------------------
在一个窗口中绘制文本
我们一旦为我们的GC装载了字体,我们就可以使用例如函数XDrawString(),在我们的窗口里绘制文本。该函数可以在窗口里的一个给定位置里绘制文本。给定的位置将是从被绘制的文本的左下算起,下面是它的例子:
/* assume that win_width contains the width of our window, win_height */
/* contains the height of our window, and 'win' is the handle of our window. */
/* some temporary variables used for the drawing. */
int x, y;
/* draw a "hello world" string on the top-left side of our window. */
x = 0;
y = 0;
XDrawString(display, win, gc, x, y, "hello world", strlen("hello world"));
/* draw a "middle of the road" string in the middle of our window. */
char* text_string = "middle of the road";
/* find the width, in pixels, of the text that will be drawn using */
/* the given font. */
int string_width = XTextWidth(font_info, text_string, strlen(text_string));
/* find the height of the characters drawn using this font. */
int fond_height = font_info->ascent + font_info->descent;
x = (win_width - string_width) / 2;
y = (win_width - font_height) / 2;
XDrawString(display, win, gc, x, y, "hello world", strlen("hello world"));
以下的说明应该可以使程序更清楚:
函数XTextWidth()被用来预测字符串的长度,当它使用指定字体进行绘制时。它被用来检查那里是开始那里是结束使它看起来占据着窗口的中央
一个字体的两个名字为"ascent"和"descent"的属性用来指定字体的高。基本上,一个字体的字符是画在一条假象的横线上的。一些字符被画在横 线上面,一些画在下面。最高的字符是被画在"font_info->ascent"线上的,最低的部分则 在"font_info->descent"线下面。因此,这两个值得和指明了字体的高度。
上面的源程序可以参考文件simple-text.c
X窗口的组织体系
当窗口被显示在X服务器上时,它们通常按照一定组织体系来排序 - 每个窗口可以有子窗口,每个子窗口又可以有自己的子窗口。让我们来查看这个组织体系的一些特性,看看它们是如何来影响例如绘画和事件等处理。
根窗口,父窗口和子窗口
每一个屏幕上都有一个根窗口。根窗口总是占据整个屏幕尺寸。这个窗口无法被销毁,改变尺寸或者图标化。当一个应用程序创建了一些窗口,它先创建至少一个顶 层窗口。在被映射到屏幕上后,这个窗口成为一个根窗口的直接子窗口。这个窗口在被映射到屏幕上之前,窗口管理器被告知什么发生了,然后,窗口管理器获得特 权成为新顶层窗口的"父亲"。这通常被用来增加一个会包含新窗口的窗口和绘制框架,标题栏,系统菜单等。
一旦一个顶层窗口(当然它实际上不是一个顶层窗口,因为窗口管理器已经成为它的父窗口了)被创建了,应用程序可以在它里面创建它的子窗口。一个子窗口只能 在它的父窗口里显示 - 如果试图把它移动到外面,出去的部分将被父窗口的边框给切掉。任何窗口都可以包含一个以上的子窗口,在这种情况下,这些子窗口将被放置在应用的内部栈上。 当一个顶层窗口被打开 - 它的所有子窗口也将随着它被打开。
以下例子演示如何在一个给定的叫"win"的窗口里打开一个子窗口。
Lets see how to create a child window inside a given window ''win''.
/* this variable will store the handle of the newly created child window. */
Window child_win;
/* these variables will store the window''s width and height. */
int child_win_width = 50;
int child_win_height = 30;
/* these variables will store the window''s location. */
/* position of the child window is top-left corner of the */
/* parent window. - 0,0.  */
int child_win_x = 0;
int child_win_y = 0;
/* create the window, as specified earlier. */
child_win = XCreateSimpleWindow(display, win, child_win_x, child_win_y,                                          child_win_width, child_win_height,  child_win_border_width,                                          BlackPixel(display, screen_num),
WhitePixel(display, screen_num));
事件传递
先前我们已经讨论了事件传递 - 如果一个窗口收到了一个它不处理的事件 - 它就把该事件发到它的父窗口去。如果那个父窗口也不处理该事件 - 那个父窗口就把该事件发到它的父窗口上去,接下来依此类推。这种行为对一个简单的Xlib程序是没什么用的,但对于抽象级更高的绘图库是有用的。这些抽象 级更高的绘图库通常把某个特定窗口的事件联系到一个函数上去。在这种情况下,发送事件到特定的窗口并用适当的函数来处理就非常有用。
与窗口管理器进行交互
在我们察看了如何创建和绘制窗口之后,我们回过头来看一下我们的窗口是如何与它们的环境 - 整个屏幕和其它窗口进行交互的。首先,我们的程序需要与窗口管理器进行交互。窗口管理器有责任装饰被绘制的窗口(例如增加框架,一个图标化的按钮,一个系 统菜单,一个标题栏),同时在窗口被图标化时绘制图标。它还管理屏幕里的窗口排列顺序以及其它可管理的任务。我们需要给它各种提示以让它以我们需要的方式 来对待我们的窗口。
窗口属性
许多与窗口管理器交流的参数都通过叫"properties"的数据来传递。X服务器把这些属性贴到各种窗口上,同时把它们存储成一种可以被各种架构的系 统所能读取的格式(记住,一个X客户程序可能运行在一台远程主机上)。属性可以是各种类型 - 数字,字符串,等等。大部分的窗口管理器提示函数使用文本属性。一个叫XStringListToTextProperty()的函数可以把C语言的字符 串转换成X文本属性,转换后的结果就可以传给各色Xlib函数。以下是一个例子:
/* This variable will store the newly created property. */
XTextProperty window_title_property;
/* This is the string to be translated into a property. */
char* window_title = "hello, world";
/* translate the given string into an X property. */
int rc = XStringListToTextProperty(&window_title, 1, &window_title_property);
/* check the success of the translation. */
if (rc == 0) { fprintf(stderr, "XStringListToTextProperty - out of memory\n");
exit(1);}
函数XStringListToTextProperty()接收一个C字符串矩阵(在我们的例子里只有一个)和一个指向XTextProperty型变 量的指针为参数,合并C字符串里的属性把值传到XTextProperty型变量里。成功时它返回一个非0值,失败时返回0(例如,没有足够的内存来完成 操作)。
设置窗口名字和图标名字
我们需要做的第一件事就是给我们的窗口设置名字。使用函数XSetWMName()。窗口管理器也许会把这个名字显示在窗口标题栏或是在任务栏上。该函数 接受3个参数:一个指向显示的指针,一个窗口句柄,和一个包含有我们设置的名字的XTextProperty变量。下面是我们如何做的:
/* assume that window_title_property is our XTextProperty, and is */
/* defined to contain the desired window title.                   */
XSetWMName(display, win, &window_title_property);
为了设置我们的窗口的图标化名字,我们将用相同的方式使用函数XSetWMIconName()。
/* this time we assume that icon_name_property is an initialized */
/* XTextProperty variable containing the desired icon name.      */
XSetWMIconName(display, win, &icon_name_property);
设置满意的窗口尺寸
在各种情况下,我们希望让窗口管理器知道我们指定的窗口尺寸以及只允许用户在我们的限定下改变窗口尺寸。例如,一个终端窗口(像xterm),我们总是要 求我们的窗口可以包含全部的行和列,因此我们就不能从中间截断我们的显示。在其它情况下,我们不希望我们的窗口可以被改变尺寸(像绝大部分的对话框窗 口),等等。我们可以依赖窗口管理器的这个尺寸信息,虽然它可能被简单的忽视掉。我们首先需要创建一个数据结构来包含该信息,填充必要的数据,然后使用函 数 XSetWMNormalHints()。下面是如何操作:
/* pointer to the size hints structure. */
XSizeHints* win_size_hints = XAllocSizeHints();
if (!win_size_hints) { fprintf(stderr, "XAllocSizeHints - out of memory\n");
exit(1);}
/* initialize the structure appropriately. */
/* first, specify which size hints we want to fill in. */
/* in our case - setting the minimal size as well as the initial size. */
win_size_hints->flags = PSize | PMinSize;
/* next, specify the desired limits.                             */
/* in our case - make the window''s size at least 300x200 pixels.*/
/* and make its initial size 400x250.                            */
win_size_hints->min_width = 300;win_size_hints->min_height = 200;
win_size_hints->base_width = 400;win_size_hints->base_height = 250;
/* pass the size hints to the window manager. */
XSetWMNormalHints(display, win, win_size_hints);
/* finally, we can free the size hints structure. */
XFree(win_size_hints);
请查看你的手册来获取尺寸提示的完整信息。
设置各种窗口管理器提示
使用函数XSetWMHints()还可以设置许多其它的窗口管理器提示。该函数使用一个XWMHints结构来传递参数给窗口管理器。下面是例子:
/* pointer to the WM hints structure. */
XWMHints* win_hints = XAllocWMHints();
if (!win_hints) {    fprintf(stderr, "XAllocWMHints - out of memory\n");
exit(1);}
/* initialize the structure appropriately. */
/* first, specify which hints we want to fill in. */
/* in our case - setting the state hint as well as the icon position hint. */
win_hints->flags = StateHint | IconPositionHint;
/* next, specify the desired hints data.                         */
/* in our case - make the window''s initial state be iconized,   */
/* and set the icon position to the top-left part of the screen. */
win_hints->initial_state = IconicState;win_hints->icon_x = 0;
win_hints->icon_y = 0;
/* pass the hints to the window manager. */
XSetWMHints(display, win, win_hints);
/* finally, we can free the WM hints structure. */
XFree(win_hints);
请查阅手册以获取全部选项的详细信息。
设置一个程序的图标
在用户图标化了我们的程序的时候,为了让窗口管理器能为我们的程序设置一个图标,我们使用上面提到的函数XSetWMHints。但是,首先我们需要创建 一个包含有图标数据的像素图。X服务器使用像素图来操作图片,将在后面介绍它的详细使用。在这里,我们只是向你展示如何为你的程序设置图标。我们假设你已 经得到了一个X bitmap格式的图标文件。教程为了方便提供了一个图标文件"icon.bmp" ,下面是代码:
/* include the definition of the bitmap in our program. */
#include "icon.bmp";
/* pointer to the WM hints structure. */
XWMHints* win_hints;
/* load the given bitmap data and create an X pixmap containing it. */
Pixmap icon_pixmap = XCreateBitmapFromData(display, win, icon_bitmap_bits,                                           icon_bitmap_width, icon_bitmap_height);
if (!icon_pixmap) {
fprintf(stderr, "XCreateBitmapFromData - error creating pixmap\n");
exit(1);}
/* allocate a WM hints structure. */
win_hints = XAllocWMHints();
if (!win_hints) {
fprintf(stderr, "XAllocWMHints - out of memory\n");
exit(1);}
/* initialize the structure appropriately. */
/* first, specify which size hints we want to fill in. */
/* in our case - setting the icon''s pixmap. */
win_hints->flags = IconPixmapHint;
/* next, specify the desired hints data.           */
/* in our case - supply the icon''s desired pixmap.*/
win_hints->icon_pixmap = icon_pixmap;
/* pass the hints to the window manager. */
XSetWMHints(display, win, win_hints);
/* finally, we can free the WM hints structure. */
XFree(win_hints);
你可以使用程序例如"xpaint"来创建使用X bitmap格式的文件。
我们提供文件simple-wm-hints.c来总结这一节,这段程序包括创建一个窗口,设置窗口管理器提示为在上面显示,以及一个简单的事件循环。它允许用户调整参数以察看提示是如何影响程序的行为的。这可以帮助你了解X程序的可移植性。
简单窗口操作
对我们的窗口,我们可以做更多的一些事情。例如,改变它们的尺寸,打开或关闭它们,图标化它们等。Xlib提供了一系列函数来完成上面提到的功能。
映射和解除一个窗口的映射
首先我们对窗口作的一对操作是映射它到屏幕上去和解除它的映射。映射一个窗口的操作将会使一个窗口显示在屏幕上,如我们在简单窗口程序例子里所看到的。解 除映射操作将会把窗口从屏幕里移除出去(虽然作为一个逻辑结点它仍然在X服务器里)。这个可以提供产生窗口被隐藏(映射解除)和再显示(映射)的效果。例 如,我们的程序里有一个对话框,我们不需要每次在需要它显示的时候都重新创建一个窗口,我们只是以映射解除的状态创建一次,在用户需要的时候简单的把它映 射到屏幕上去就行了。这比每一次都创建它和销毁它要快多了,当然,这需要在客户端和服务器端同时使用更多的内存。
你应该还记得映射操作是使用函数XMapWindow()。映射解除操作是使用函数XUnmapWindow(),下面是如何使用它们:
/* make the window actually appear on the screen. */
XMapWindow(display, win);
/* make the window hidden. */
XUnmapWindow(display, win);
除非整个窗口被其它窗口给覆盖了,一个暴露事件将在映射操作后发给应用程序。
在屏幕上移动一个窗口
我们想做的另一个操作是在屏幕里移动窗口。使用函数XMoveWindow()可以完成这个操作。它接受窗口的新坐标,使用的方法和函数XCreateSimpleWindow()是一样的。一下是调用的例子:
/* move the window to coordinates x=400 and y=100. */
XMoveWindow(display, win, 400, 100);
注意当窗口移动的时候,窗口的部分可能后被遮住或被重新暴露,这样我们就可能会收到暴露事件。
改变窗口尺寸
接下来我们要做的是改变一个窗口的尺寸。使用函数XResizeWindow()可以完成这个操作:
/* resize the window to width=200 and height=300 pixels. */
XResizeWindow(display, win, 200, 300);
我们可以合并移动和改变尺寸操作为一个操作,使用函数XMoveResizeWindow():
/* move the window to location x=20 y=30, and change its size */
/* to width=100 and height=150 pixels.                        */
XMoveResizeWindow(display, win, 20, 30, 100, 150);
改变窗口们的栈顺序 - 提升和降低
到目前为止我们已经改变了一个单独窗口的许多属性。接下来我们将看看窗口之间的属性。其中一个就是它们的栈属性。也就是说,窗口是如何在屏幕上排列的。最前面的窗口我们说它是在栈顶,最后面的窗口我们说它是在栈底。下面演示我们如何改变窗口的栈顺序:
/* move the given window to the top of the stack. */
XRaiseWindow(display, win1);
/* move the given window to the bottom of the stack. */
XLowerWindow(display, win1);
图标化和恢复一个窗口
在这里我们将要讲解的最后一个操作就是如何把一个窗口变换成图标状态和恢复它。使用函数XIconifyWindow()来把一个窗口变换成图标状态,使 用函数XMapWindow()来恢复它。为了帮助理解为什么图标化函数没有一个对应的反函数,我们必须理解当一个窗口被图标化时,实际发生的事情是那个 窗口被解除映射了,而它的图表被映射了。结果,如果想使哪个窗口在出现,我们只需要简单的映射它一下就行了。图标实际上是另一个窗口,只不过它与我们的窗 口有非常强的联系关系。下面演示如何图标化一个窗口并恢复它:
/* iconify our window. Make its icon window appear on the same */
/* screen as our window (assuming we created our window on the */
/* default screen).                                            */
XIconifyWindow(display, win, DefaultScreen(display));
/* de-iconify our window. the icon window will be automatically */
/* unmapped by this operation.                                  */
XMapWindow(display, win);
获得一个窗口的信息
与可以为窗口设置许多属性相同,我们也可以要求X服务器提供这些属性的值。例如,我们可以检查窗口现在在屏幕里什么位置,当前尺寸,是否被映射了等等。函数XGetWindowAttributes()可以帮助我们获取那些信息:
/* this variable will contain the attributes of the window. */
XWindowAttributes win_attr;
/* query the window''s attributes. */
Status rc = XGetWindowAttributes(display, win, &win_attr);
结构体XWindowAttributes包含了很多数据域,下面是它的一部分:
int x, y;
窗口的位置,相对于它的父窗口。
int width, height;
窗口的宽和高(单位,像素)。
int border_width
窗口的边框宽度
Window root;
根窗口,也就是我们的窗口在那个窗口里被显示了。
这个函数有些问题,就是它返回的是相对于父窗口的位置。这对一些窗口的操作(例如XMoveWindow)是没有什么意义的。为了解决这个问题,我们需要 使用两步的操作。首先,我们找出窗口的父窗口的ID。然后我们在使用它来确定窗口相对于屏幕的坐标。我们使用两个前面没有介绍的函数来完成这个计 算,XQueryTree()和XTranslateCoordinates()。这两个函数的功能超出了我们的需要,所以我们只关注我们需要的:
/* these variables will eventually hold the translated coordinates. */
int screen_x, screen_y;
/* creen_y contain the location of our original */
/* window, using screen coordinates. */
你可以看到Xlib有时候会让我们处理问题时变得很麻烦。
以上的内容可以参考例子window-operations.c 程序。
使用颜色来绘制彩虹
到目前为止,我们的绘制操作都只使用了黑白两色。现在我们就看看如何使用丰富的颜色来绘制。
颜色映射
首先,是没有完全足够的颜色的。屏幕控制器同时只能支持有限的颜色。因此,一个应用程序不能只是要求使用颜色“轻紫红”就盼望这个颜色能被支持。每个应用分配它自己所需要的颜色,如果全部的16或256色入口都已经在使用了,下一个颜色的分配就会失败。
结果,就介绍使用“一个颜色映射”。一个颜色映射是一个与屏幕控制器同时可以支持的颜色数相同的表。每个表中的节点都为每种颜色包含一个RGB(红,绿和 蓝)。当一个应用想在屏幕上绘制时,它并不指定使用什么颜色,而是指定使用映射表里那一个节点,因此,改变表里某个节点的值将会改变程序绘制的颜色。
为了能让程序员使用他想要的颜色来绘制,提供了颜色映射分配函数。你可以要求分配一个颜色映射节点来对应一个RGB值,然后一个节点的索引值返回给你。如 果表满了,这个操作将会失败。你可以接下来要求一个相近的颜色来满足你的需要。这意味着一个相近的颜色将会被绘制到屏幕上去。
在当今的X 服务器使用的现代显示器上,一般都可以支持上百万的颜色,上面那个限制也许看起来挺傻的,但是记住还有很多古旧的显示卡和显示器在被使用。使用颜色映射, 你可以不必考虑服务器的屏幕硬件细节就可以使用它们。在一个支持上百万的显示器上,任何颜色的分配请求都应该会成功。在一个职能支持有限颜色的显示器上可 能会使用一个相近颜色来代替你的要求,这可能不好看,但你的程序仍然能工作。
分配和释放颜色映射
当你使用Xlib绘制的时候,你可以选择屏幕的标准颜色映射,或者为你的窗口分配一个新的颜色映射。在后一种情况下,每次鼠标移动到你的窗口上时,你窗口 的颜色映射都将替换缺省的屏幕映射,然后你就会看到屏幕花一下其它的窗口颜色也改变了。实际上,这和你在使用“-install”选项运行X应用时效果一 样。
系统定义了宏DefaultColormap来获取屏幕的标准颜色映射:
Colormap screen_colormap = DefaultColormap(display, DefaultScreen(display));
上面的调用将会返回第一个屏幕的缺省颜色映射的句柄(再多余的提醒一下,一个X服务器可以同时支持数个不同的屏幕,每个屏幕都可以有自己的资源)。
另一个选项,分配一个颜色映射,像下面这样工作:
/* first, find the default visual for our screen. */
Visual* default_visual = DefaultVisual(display, DefaultScreen(display));
/* this creates a new color map. the number of color entries in this map */
/* is determined by the number of colors supported on the given screen.  */
Colormap my_colormap = XCreateColormap(display, win, default_visual, AllocNone);
注意,window参数是用来只允许X服务器为指定屏幕分配颜色映射。我们接下来可以使用分配来的颜色映射给同一个屏幕里的任意一个窗口使用。
分配和释放颜色节点
一旦我们获得了颜色映射的访问,我们就可以开始分配颜色。使用函数XAllocNameColor()和XAllocClor()来完成这个工作。首先函 数 XAllocNameColor()获得颜色的名字(例如"红","蓝","棕"等等)然后获得能使用的实际相近颜色。函数XAllocColor()访 问RGB颜色。两个函数都使用XColor结构,它有以下的一些数据域:
unsigned long pixel
颜色映射节点的索引。
unsigned short red
RGB颜色值的红色部分。
unsigned short green
RGB颜色值的绿色部分。
unsigned short blue
RGB颜色值的蓝色部分。
下面是使用的例子:
/* this structure will store the color data actually allocated for us. */
XColor system_color_1, system_color_2;
/* this structure will store the exact RGB values of the named color.  */
/* it might be different from what was actually allocated.             */
XColor exact_color;
/* allocate a "red" color map entry. */
Status rc = XAllocNamedColor(display, screen_colormap, "red", &system_color_1,                             &exact_color);
/* make sure the allocation succeeded. */
if (rc == 0) {
fprintf(stderr, "XAllocNamedColor - allocation of ''red'' color failed.\n");}
else {
printf("Color entry for ''red'' - allocated as (%d,%d,%d) in RGB values.\n",                   system_color_1.red, system_color_1.green, system_color_1.blue);}
/* allocate a color with values (30000, 10000, 0) in RGB. */
system_color_2.red = 30000;
system_color_2.green = 10000;
system_color_2.blue = 0;
Status rc = XAllocColor(display, screen_colormap, &system_color_2);
/* make sure the allocation succeeded. */
if (rc == 0) {
fprintf(stderr, "XAllocColor - allocation of (30000,10000,0) color failed.\n");}
else {
/* do something with the allocated color... */    .    .}
使用一个颜色绘制
我们在分配了希望的颜色之后,我们可以使用它们绘制文本或图形。为了达到目的,我们需要把获得的颜色设置给一些GC(图形上下文)作为前景色和背景色,然 后使用设置好的GC来进行绘制。使用函数XSetForeground()和XSetBackground()来进行,如下:
/* use the previously defined colors as the foreground and background */
/* colors for drawing using the given GC. assume my_gc is a handle to */
/* a previously allocated GC.                                         */
XSetForeground(display, my_gc, screen_color_1.pixel);
XSetForeground(display, my_gc, screen_color_2.pixel);
如你所见,这个是个使用的例子。实际的绘制工作使用我们以前介绍的绘图函数。注意,为了使用各种颜色完成绘制工作,我们可以使用两种方法。我们可以在调用 绘图函数前改变GC的值,也可以使用代表不同颜色的GC。由你自己根据情况使用哪种方法。注意,使用多个GC降消耗X服务器额外的资源,但这样可以使你的 代码显的更紧凑。
作为使用颜色绘制的例子,请察看例子程序color-drawing.c 。这是程序simple-drawing.c 的一个拷贝,我们只是添加了颜色的部分在里面。
X Bitmaps和Pixmaps
一个被称为多媒体的程序所有作的一件事情就是显示图片。在X的世界里,使用bitmaps和pixmaps来实现这个功能。在为我们的程序设置图标的介绍里我们已经使用了它们。现在让我们进一步对它们进行研究,看看在一个窗口里是如何绘制它们的。
在进入之前有一点需要注意,Xlib不能处理许多现在流行的图片格式,例如gif,jpeg或tiff。这些被留给了应用程序(或者是一些图形处理库)来转换成X服务器可以接受的x bitmaps和x pixmaps。
什么是一个X Bitmap?和X Pixmap?
一个Xbitmap是一个有X窗口系统定义的双色图形格式。在保存在一个文件里的时候,bitmap数据看起来就像一段C源程序。它包括定义图片宽高的变量,一个包含比特值得矩阵(矩阵的尺寸=宽*高),和一个可选的热点位置(将会在后面的鼠标光标的部分进行解释)。
一个X pixmap是一个X窗口系统在内存里保存图像的格式。该格式可以储存黑色和白色的图片(例如X bitmaps)也可以保存带颜色的图片。这实际上是X协议唯一能支持的图片格式,任何图片如果想被显示在屏幕上前都要先被转换成这种格式。
实际上,一个X pixmap应该被认为是一个没有被绘制到屏幕上的窗口。许多在窗口上的图形操作也可以工作于X pixmap,只不过使用X pixmap ID来代替窗口ID。事实上,如果你查看手册,你会发现所有的这些函数都是接受一个叫"可画"参数而不是一个窗口参数。因为这两种类型都是可画的,它们都 可以被用在例如函数XDrawArc(),XDrawText()等等。
从一个文件里读取一个Bitmap
在图标的程序里,我们已经看过如何从一个文件里把一个Bitmap装载到内存里。前面我们使用的方法是使用C预编译器"#include"来进行,下面我们看看如何直接从文件里读取。
/* this variable will contain the ID of the newly created pixmap.    */
Pixmap bitmap;
/* these variables will contain the dimensions of the loaded bitmap. */
unsigned int bitmap_width, bitmap_height;
/* these variables will contain the location of the hot-spot of the  */
/* loaded bitmap.                                                    */
int hotspot_x, hotspot_y;
/* this variable will contain the ID of the root window of the screen */
/* for which we want the pixmap to be created.                        */
Window root_win = DefaultRootWindow(display);
/* load the bitmap found in the file "icon.bmp", create a pixmap      */
/* containing its data in the server, and put its ID in the ''bitmap'' */
/* variable.                                                          */
int rc = XReadBitmapFile(display, root_win, "icon.bmp", &bitmap_width,
&bitmap_height, &bitmap, &hotspot_x, &hotspot_y);
/* check for failure or success. */
switch (rc) {
case BitmapOpenFailed:
fprintf(stderr, "XReadBitmapFile - could not open file ''icon.bmp''.\n");
break;
case BitmapFileInvalid:
fprintf(stderr,
"XReadBitmapFile - file ''%s'' doesn''t contain a valid bitmap.\n",                                  "icon.bmp");
break;
case BitmapNoMemory:
fprintf(stderr, "XReadBitmapFile - not enough memory.\n");
break;
case BitmapSuccess:
/* bitmap loaded successfully - do something with it... */
break;
}
注意对于给定的bitmap参数"root_win"什么作用也不起 - 读取的bitmap并不与这个窗口相联系。这个窗口句柄只是被用来指明bitmap所使用的屏幕。这是非常重要的,bitmap必须支持与屏幕相同数量的颜色,这样它才能发挥作用。
在一个窗口里绘制图形
一旦我们获得了从bitmap里生成的pixmap的句柄,我们就可以使用函数XCopyPlane()把它绘制到窗口里。这个函数可以帮助我们指定什么(一个窗口,甚至另一个pixmap)可以画到这个pixmap上去。
/* draw the previously loaded bitmap on the given window, at location   */
/* ''x=100, y=50'' in that window. we want to copy the whole bitmap, so */
/* we specify location ''x=0, y=0'' of the bitmap to start the copy from, */
/* and the full size of the bitmap, to specify how much of it to copy.  */
XCopyPlane(display, bitmap, win, gc, 0, 0, bitmap_width, bitmap_height,
100, 50, 1);
如你所见,我们可以只拷贝制定的矩形区而不是整个pixmap。另外还需要注意的是函数XCopyPlane的最后一个参数(那个结尾的"1")。该参数 指定了那个平面被从源里拷贝出来。对于bitmaps,我们通常只拷贝平面1。到了下面我们讨论颜色深度的时候你就能确切的明白为什么这么做。
创建一个Pixmap
有时我们需要创建一个没有初始化的pixmap,这样我们可以接下来在它上面绘制。这对图像绘制程序是非常有用的。另外,这对读取各种格式的图像数据也是非常有用的。
/* this variable will store the handle of the newly created pixmap. */
Pixmap pixmap;
/* this variable will contain the ID of the root window of the screen */
/* for which we want the pixmap to be created.                        */
Window root_win = DefaultRootWindow(display);
/* this variable will contain the color depth of the pixmap to create. */
/* this ''depth'' specifies the number of bits used to represent a color */
/* index in the color map. the number of colors is 2 to the power of */
/* this depth.                                                       */
int depth = DefaultDepth(display, DefaultScreen(display));
/* create a new pixmap, with a width of 30 pixels, and height of 40 pixels. */
pixmap = XCreatePixmap(display, root_win, 30, 40, depth);
/* just for fun, draw a pixel in the middle of this pixmap. */
XDrawPoint(display, pixmap, gc, 15, 20);
在一个窗口里绘制一个Pixmap
我们在获得了一个pixmap的句柄后,我们就可以使用它在窗口里绘制,使用函数XCopyArea()。
/* draw the previously loaded bitmap on the given window, at location   */
/* ''x=100, y=50'' in that window. we want to copy the whole bitmap, so */
/* we specify location ''x=0, y=0'' of the bitmap to start the copy from, */
/* and the full size of the bitmap, to specify how much of it to copy. */
XCopyPlane(display, bitmap, win, gc, 0, 0, bitmap_width, bitmap_height,                     100, 50, 1);
如你所见,我们可以拷贝指定的矩形区域而不是整个pixmap。
另外一个需要被强调注意的是 - 可以在同一个屏幕上创建不同深度的pixmap。当我们进行拷贝作业时(往一个窗口上拷贝pixmap等等),我们应该保证源和目标是用相同的深度。如果 两个的深度不一样,操作将会失败。除非我们使用前面介绍的函数XCopyPlane()可以完成这个操作。在那样一种情况下,我们拷贝指定的平面到窗口上 去,实际上指定了每一个被拷贝的颜色位。这个操作可以制作许多特殊的效果,但这超出了本文的范围。
释放一个Pixmap
最后,当我们完成了对一个pixmap的操作,我们应该释放它所占的资源。使用函数XFreePixmap()。
/* free the pixmap with the given ID. */
XFreePixmap(display, pixmap);
在释放一个pixmap之后 - 我们绝对不能再访问它。
作为总结这一章,看一下程序draw-pixmap.c 。
改变鼠标光标
我们经常看到改变鼠标光标的程序(经常被称为X光标)。例如,一个正在埋头工作的程序经常会把光标变成沙漏,提示用户需要等待才能处理新的请求。如果没有这么个提示方法,用户会认为程序已经卡住了。下面让我们看看如何为我们的窗口改变鼠标光标。
创建和销毁鼠标光标
系统提供了两个方法来创建光标。其中一个是使用系统预定义的形状,由Xlib支持。另一个是有程序提供一个bitmap来显示。
使用前一种方法时,我们使用一个特殊的字体名字"cursor"和相应的函数XCreateFontCursor()。该函数接受一个形状指示然后返回一个代表生成的光标的句柄。文件
列出了系统支持的光标类型,下面的是其中的三个:
XC_arrow
X服务器显示的普通光标。
XC_pencil
一个笔状的光标。
XC_watch
一个表状沙漏
使用这些符号来创建光标是非常简单的:
#include
/* defines XC_watch, etc. */
/* this variable will hold the handle of the newly created cursor. */
Cursor watch_cursor;
/* create a sand watch cursor. */
watch_cursor = XCreateFontCursor(display, XC_watch);
另一种创建鼠标光标的方法时使用一对pixmaps。一个pixmap定义了光标的形状,另一个是个面具,来指定前一个的什么内容被显示。其它的内容将变 成透明的。创建一个那样的光标使用函数XCreatePixmapCursor()。下面的例子里,我们将使用"icon.bmp"来创建光标。我们将假 设它已经被装载到内存里去了,并已经被转换成pixmap,返回的句柄被保存到"bitmap"变量里。我们希望它是完全透明的。也就是说,只有黑色颜色 的部分会被确实画在屏幕上。为了实现这个效果,我们将会既用它来做光标pixmap且做面具pixmap。希望你能明白为什么这样...
/* this variable will hold the handle of the newly created cursor. *
/Cursor icon_cursor;
/* first, we need to define foreground and background colors for the cursor. */
XColor cursor_fg, cursor_bg;
/* access the default color map of our screen. */
Colormap screen_colormap = DefaultColormap(display, DefaultScreen(display));
/* allocate black and while colors. */
Status rc = XAllocNamedColor(display, screen_colormap, "black", &cursor_fg,                                          &cursor_fg);
if (rc == 0) {
fprintf(stderr,            "XAllocNamedColor - cannot allocate ''black'' ??!!??\n");
exit(1);}
Status rc = XAllocNamedColor(display, screen_colormap, "white",                             &cursor_bg, &cursor_bg);
if (rc == 0) {
fprintf(stderr, "XAllocNamedColor - cannot allocate ''white'' ??!!??\n");
exit(1);}
/* finally, generate the cursor. make the ''hot spot'' be close to the */
/* top-left corner of the cursor - location (x=5, y=4). */
icon_cursor = XCreatePixmapCursor(display, bitmap, bitmap,                  &cursor_fg, &cursor_bg, 5, 4);
上面需要说明的是参数"hot spot"。当我们定义了一个光标,我们需要指明光标里的哪一个像素用来生成各种鼠标事件。通常,我们根据习惯来指定一个看起来像"hot spot"的点。例如一个箭头形状的光标,我们就会选择箭头尖为"hot spot"。
最后,我们不需要再使用光标时,我们可以使用函数XFreeCursor()来释放它的资源:
XFreeCursor(display, icon_cursor);
设置一个窗口的鼠标光标
我们在创建了光标后,就可以告诉X服务器把它贴到我们的任何窗口上去。使用函数XDefineCursor(),X服务器就会在每一次光标移进指定的窗口 时改变光标的形状。稍后我们可以使用函数XUndefinCursor()来撤销刚才的指定。这样,鼠标再移进指定的窗口时就会使用缺省的光标。
/* attach the icon cursor to our window. */
XDefineCursor(display, win, icon_cursor);
/* detach the icon cursor from our window. */
XUndefineCursor(display, win);
作为例子,请查看程序cursor.c, and see
how mouse cursors are set, changed and removed. Run the program, place the
mouse pointer over the created window, and watch.

版本控制-git简易教程

概述

在说明什么是git之前,我们需要对版本控制(Version Control)做一个基本的概述, 一般情况下,我们的源代码都是在时间和空间两个维度上进行管理并维护的,代码本身 以及组织代码的项目文件(如makefile或者vs的项目文件)都是以文件和目录的形式存 储在磁盘空间上的,这种文件管理的形式已经被大家所熟悉了,然而,我们在不同时间 段里做出的各种修改怎么管理呢?版本控制系统 (Version Control System,以下简 称VCS)就是一种记录代码修改演化的系统,他的功能就是方便你今后找回某个特定时 期(或版本)的文件、查看版本之间发生了哪些变化、对变化进行比较或者是修正致命错 误。 版本控制系统主要经历了本地版本控制,集中式版本控制到分布式版本控制的发展: 本地版本控制(Local Version Control System)顾名思义就是本地化的版本控制系 统,没有网络协作等较为先进的版本控制的概念。 集中式版本控制(Centralized Version Control System)为有一台版本控制服务器 运行在那边存放并提供一个项目中所有版本文件的服务,在很长一段时间内占据主 流,其中CVS与SVN为其代表。 分布式版本控制(Distributed Version Control System)克服了集中式版本控制可 能因为单点失败造成的巨大损失的缺点,让每一台客户端在每一次checkout操作后 都完全镜像整个版本控制中的项目。在分布式版本控制系统中,任何一台机器都可 以视为版本控制服务器。即使有一台服务器失去服务能力,其它机器与系统可以继 续协作维持版本控制系统的正常运转。git就是分布式版本控制系统。 git与其它主流的VCS最大的区别就是,在项目版本更新的过程中,git记录的并非是基 于初始文件的变化数据,而是通过一系列快照(Snapshot,就像是个小型的文件系统)来 保存记录每个文件。如果有些文件在版本更新后没有发生任何变化,那么在新的版本中 它会是一个指向最近一次更新的文件版本的链接。 此外,几乎所有git的操作都是在本 地进行的,所以,没有了”延迟”,几乎所有的操作都是瞬间完成的。例如,当你想要 查看项目历史时,不需要特地去服务器上抓取历史记录,直接在本地浏览即可。这意味 着,你可以在本地对比两个不同版本的文件的差别,可以在本地查看过去有哪些人对指 定文件作出了修改与更新,可以……几乎完全本地化的操作也让这样一种场景成为了可 能: 当有人由于没有网络连接条件但是又必须抓紧时间对自己的项目进行修改与开发 ,同时又需要有版本管理系统来记录每次他commit的历史,这时,git提供了他所有需 要的便利。 git使用SHA-1 Hash算法加密生成的40位字符串(而不是文件名)来记录代表git中的每样 东西。格式就像这样: ??6bafcdc09f3d6d416f6572f82082987a486d3098 git中的文件主要会处于三种状态,它们分别是: Committed: 文件或数据已经安全的存放在了git本地数据库中 Modified: 文件或数据已经修改但是尚未commit到数据库 Staged:文件或数据已被标记要放入到下一次commit中 这样的机制致使git的镜像会由三个部分组成(假设有一个git目录叫git-repo): Git directory: 存放项目中所有元数据以及对象的地方(git-repo/.git/) Working directory: 在这里是从git项目数据库中checkout出的一个单独的(默认 情况下是最新的)项目版本,用于对指定项目版本中的文件进行修改和编辑(git-r epo/) Staging area: 一般是存放在Git directory中的一个简单的文件,里面存放着下 一次需要commit的文件的信息(在git-repo/.git/中) 安装与配置 Git可以安装在各种操作系统下,下面以windows为例,linux系统和mac os系统的用户 可以查找github.com上的help内容。 在windows下安装git非常简单,只要依次完成下面操作即可: 第一步:下载 msysgit(http://code.google.com/p/msysgit/),安装时一般只需要 保留默认选项, 只是要注意,不要使用putty作为客户端,GitHub只支持openssh. 安 装完成后需要生成SSH Key。 第二步:配置ssh的key,在用户目录下(windows下通常是C:\Documents and Setting s\,其他系统通常都是/home/)如果已经存在ssh的 配置会存有一个.ssh目录(是隐藏目录),目录下会存有两个文件(id_rsa, id_rsa. pub),将其备份一下,然后生成新的,这里cygwin的命令序列如下 $ ssh-keygen -t rsa -C “your_mail_addr@yourmail.com” Enter file in which to save the key (/c/Users//.ssh/id_r sa): Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /c/Users//.ssh/id_ rsa. Your public key has been saved in /c/Users//.ssh/id_rsa. pub. The key fingerprint is: e8:ae:60:8f:38:c2:98:1d:6d:84:60:8c:9e:dd:47:81 your_mail_addr@yourmail .com 第三步:将Public Key 添加到你所需要提交的服务器上(这里以GitHub为例,其他服 务器的方式联系相关的管理员),打开你的GitHub->SSH Public Key->点击”Add ano ther public key”, 将你的public key(id_rsa.pub)的内容拷贝到GitHub中。 第四步:测试配置是否成功,同样的,在cygwin里如此输入: $ ssh git@github.com ERROR: Hi You’ve successfully authenticated, but GitHu b does not provide shell access Connection to github.com closed. 看到以上信息表示操作成功,接下来,我们可以学习一些基本使用。 本地基本操作 首先我们要初始化一个Repository,如果完全是新建一个项目,我们可以: mkdir test cd test git init 这个时候,test目录下就会多出一个叫做.git的目录,该目录下会有个config文件,他 的内容如下: [core] repositoryformatversion = 0 filemode = true bare = false logallrefupdates = true 我们需要加入自己的用户信息(注意,该信息必须与你配置ssh的时候的信息保持一致 ): [user] name = your_username email = your_mail_addr@yourmail.com 当然,用户信息我们完全可以用命令行来配置,在git init命令之前输入如下命令: git config –global user.name “your_username” git config –global user.email “your_mail_addr@yourmail.com” 如果项目目录已经存在,我们可以直接: cd existing_git_repo git init 接下来就是一些基本的操作了…… 首先要用的是:git status,该命令用于查看目前git镜像的状态,在使用git的过程中 ,我们将会反复的使用到这个工具: $ git status # On branch master # # Initial commit # nothing to commit (create/copy files and use “git add” to track) 可以看出,git status给出了相当详细的信息,第一行中首先给出的是git的分支(bra nch)状态信息,接着,git会告诉你现在还没有东西提交到镜像中,建议先使用命令gi t add来对文件进行追踪。所以,接下来我们介绍git add命令, 假设在的工作目录中 使用python语言写一个helloworld的小程序,将代码保存完成后,我们得到一个hello .py文件,然后,我们希望将这个文件被git镜像追踪(track)到,那么只需要: $ git add hello.py 这样,我们就将hello.py加入到了git镜像中去进行版本控制,再次使用git status来 查看目前的镜像状态: $ git status # On branch master # # Initial commit # # Changes to be committed: # (use “git rm –cached …” to unstage) # # new file: hello.py # 注意这里它提到了changes to be committed,意思是该文件已经处于staged状态,接 下去你可以根据自己的需要将其提交(commit),或者如果你觉得这是一个误操作,该文 件不应当被提交,你可以通过git rm –cached命令来取消它的staged状态(你会发现s tatus信息中给出了精确的提示)。 现在,我们通过命令git commit将hello.py提交: $ git commit 这时,会出现一个带有status信息的文本给你编辑(使用什么编辑器取决于你对git的配 置),在以”#”开头的注释行下输入一些文本,用于注释此次提交,方便于其他代码协 作者的维护与理解! 你也可以通过命令参数-m来直接输入注释内容,加快提交速度: $ git commit -m “comment here” 至此,你的文件hello.py已经处于tracked状态!。 现在,我们有一个hello.py在镜像中了,接下来,假设发现了一个小错误,额,比如一 个循环的条件写错了,于是我们需要针对文件完成修改,之后,当我们再次git statu s的时候: # On branch master # Changed but not updated: # (use “git add …” to update what will be committed)# (use “git che # ckout — …” to discard changes in working directory) # # modified: hello.py # no changes added to commit (use “git add” and/or #“git commit -a”) git status显示,hello.py被修改过了,如果你想要提交,需要再次git add该文件, 或者,可以直接使用git commit -a跳过add的步骤,直接提交(尚未track的文件必须先 git add才能进行提交)。 在提示中,还有提到说,如果你想撤销对hello.py的修改,就可以使用git checkout命 令来实现,这里的情况会是: $ git checkout – hello.py 如果你这么做了,你就会发现,你的hello.py又回到了之前没有被修改过的时候的状态 。 在Unix/Unix-like系统中,几乎都会有一个小巧的对比文件不同的工具叫做diff,在g it中也有这么一个工具,来详细比较你修改后准备提交的文件与修改前的状态的不同之 处,恩,也许你猜到了,这个命令就是git diff。 现在我们尝试着再次修改一下hello.py,然后运行git diff: $ git diff diff –git a/ hello.py b/ hello.py index befc634..a86316b 100644 — a/hello.py +++ b/hello.py @@ -1,3 +1,4 @@ +/* new comment line */ if __name__ == “__main__”: print “hello, world!” 通过git的diff工具,很容易了解到我们更改了哪些地方。这个时候,如果我们想撤销 之前的更改,可以使用git reset命令: $ git reset HEAD hello.py $ git status # On branch master # Untracked files: # (use “git add …” to include in what will be committed) # # hello.py nothing added to commit but untracked files present (use “git add” to track) 再次git status,hello.py又回到了untracked状态! 接下来,如果需要修改README.txt(通常是项目的自述文件)的文件名(千万要记得我 们的文件在git的镜像中进行版本控制管理,不要鲁莽的直接使用unix命令mv或者rm来 对git镜像中的文件进行普通的文件操作),我们该使用git mv命令: $ git mv README.txt tutorial.txt $ git status # On branch master # Changes to be committed: # (use “git reset HEAD …” to unstage) # # renamed: README.txt -> tutorial.txt # $ git commit -a -m “renamed a file” [master 55ce30d] renamed a file 1 files changed, 0 insertions(+), 0 deletions(-) rename README.txt => tutorial.txt (100%) 可以看到,在提交变更后,README.txt在文件系统以及git镜像中都被成功地重命名为 了tutorial.txt。同样的,你可以unstage来撤销对该文件的重命名,the choice is yours! 如果我们不再需要tutorial.txt这个文件,我们可以将其从git镜像中删除,git中删除 文件的命令是git rm: $ git rm tutorial.txt rm ‘tutorial.txt’ $ git status # On branch master # Changes to be committed: # (use “git reset HEAD …” to unstage) # # deleted: tutorial.txt # $ git commit -a -m ” deleted a file” [master 7d81981] deleted a file 1 files changed, 0 insertions(+), 1 deletions(-) delete mode 100644 tutorial.txt 正如之前所提到的,这些操作都是可以恢复的,因为git是版本控制系统,所以自然而 然的就会有一套版本历史管理机制。 我们可以用工具git log提供了查看git镜像的commit历史: $ git log commit 7d819818530ce89322019ba5000723c973eb0420 Author: ghosTM55 Date: Sun Mar 14 15:26:22 2010 +0800 deleted a file commit 55ce30d88fb5c81d20bdf86e2034053613fed632 Author: ghosTM55 Date: Sun Mar 14 15:11:39 2010 +0800 renamed a file commit 2ed9f1f9bd1a7561cd7e57dcdbd7f2cda54668fb Author: ghosTM55 Date: Sun Mar 14 14:58:11 2010 +0800 a little change 基本上可以清楚地看到,git详细记录了每次commit的信息(checksum值、提交者信息、 提交时间)。 下面简单的说一下分支管理的操作,git的分支管理是异常的简单和方便,可以用git branch命令进行非常直观的操作: 首先可以在工作目录下查看当前的项目存在多少分支: $ git branch * master test 可以清楚地看到,目前该项目存在两个分支master和test,带*的是当前分支(我们可 以用命令git checkout test切换到test反之)。接下来我们为项目添加一个分支: $ git branch new $ git branch * master new test 我们看到新分支new已经添加进git的镜像里了,如果要删除该分支,我们可以如此: $ git branch -d new Deleted branch new (was 63c0da1). $ git branch * master test 这时候我们就看到new已不在镜像中,当我们需要将指定分支中的代码合并到默认分支 的时候,可以使用命令: 远程基本操作 (这部分引用一个网络blog:http://archive.cnblogs.com/a/2050324/) 要参与任何一个 Git 项目的协作,必须要了解该如何管理远程仓库。远程仓库是指托 管在网络上的项目仓库,可能会有好多个,其中有些你只能读,另外有些可以写。同他 人协作开发某 个项目时,需要管理这些远程仓库,以便推送或拉取数据,分享各自的 工作进展。管理远程仓库的工作,包括添加远程库,移除废弃的远程库,管理各式远程 库分 支,定义是否跟踪这些分支,等等。本节我们将详细讨论远程库的管理和使用。 查看当前的远程库 要查看当前配置有哪些远程仓库,可以用 git remote 命令,它会列出每个远程库的简 短名字。在克隆完某个项目后,至少可以看到一个名为 origin 的远程库,Git 默认使 用这个名字来标识你所克隆的原始仓库: $ git clone git://github.com/schacon/ticgit.git Initialized empty Git repository in /private/tmp/ticgit/.git/ remote: Counting objects: 595, done. remote: Compressing objects: 100% (269/269), done. remote: Total 595 (delta 255), reused 589 (delta 253) Receiving objects: 100% (595/595), 73.31 KiB | 1 KiB/s, done. Resolving deltas: 100% (255/255), done. $ cd ticgit $ git remote origin 也可以加上 -v 选项(译注:此为 –verbose 的简写,取首字母),显示对应的克隆 地址: $ git remote -v origin git://github.com/schacon/ticgit.git 如果有多个远程仓库,此命令将全部列出。比如在我的 Grit 项目中,可以看到: $ cd grit $ git remote -v bakkdoor git://github.com/bakkdoor/grit.git cho45 git://github.com/cho45/grit.git defunkt git://github.com/defunkt/grit.git koke git://github.com/koke/grit.git origin git@github.com:mojombo/grit.git 这样一来,我就可以非常轻松地从这些用户的仓库中,拉取他们的提交到本地。请注意 ,上面列出的地址只有 origin 用的是 SSH URL 链接,所以也只有这个仓库我能推送 数据上去(我们会在第四章解释原因)。 添加远程仓库 要添加一个新的远程仓库,可以指定一个简单的名字,以便将来引用,运行 git remo te add [shortname] [url]: $ git remote origin $ git remote add pb git://github.com/paulboone/ticgit.git $ git remote -v origin git://github.com/schacon/ticgit.git pb git://github.com/paulboone/ticgit.git 现在可以用字串 pb 指代对应的仓库地址了。比如说,要抓取所有 Paul 有的,但本地 仓库没有的信息,可以运行 git fetch pb: $ git fetch pb remote: Counting objects: 58, done. remote: Compressing objects: 100% (41/41), done. remote: Total 44 (delta 24), reused 1 (delta 0) Unpacking objects: 100% (44/44), done. From git://github.com/paulboone/ticgit * [new branch] master -> pb/master * [new branch] ticgit -> pb/ticgit 现在,Paul 的主干分支(master)已经完全可以在本地访问了,对应的名字是 pb/ma ster,你可以将它合并到自己的某个分支,或者切换到这个分支,看看有些什么有趣的 更新。 从远程仓库抓取数据 正如之前所看到的,可以用下面的命令从远程仓库抓取数据到本地: $ git fetch [remote-name] 此命令会到远程仓库中拉取所有你本地仓库中还没有的数据。运行完成后,你就可以在 本地访问该远程仓库中的所有分支,将其中某个分支合并到本地,或者只是取出某个分 支,一探究竟。(我们会在第三章详细讨论关于分支的概念和操作。) 如果是克隆了一个仓库,此命令会自动将远程仓库归于 origin 名下。所以,git fet ch origin 会抓取从你上次克隆以来别人上传到此远程仓库中的所有更新(或是上次 fetch 以来别人提交的更新)。有一点很重要,需要记住,fetch 命令只是将远端的数 据拉到本地仓库,并不自动合并到当前工作分支,只有当你确实准备好了,才能手工合 并。(说 明:事先需要创建好远程的仓库,然后执行:git remote add [仓库名] [仓 库url],git fetch [远程仓库名],即可抓取到远程仓库数据到本地,再用git merge remotes/[仓库名]/master就可以将远程仓库merge到本地当前branch。这种分支方式 比较适合独立-整合开发,即各自开发测试好后 再整合在一起。比如,Android的Fram ework和AP开发。 可以使用–bare 选项运行git init 来设定一个空仓库,这会初始化一个不包含工作目 录的仓库。 $ cd /opt/git $ mkdir project.git $ cd project.git $ git –bare init 这时,Join,Josie 或者Jessica 就可以把它加为远程仓库,推送一个分支,从而把第 一个版本的工程上传到仓库里了。) 如果设置了某个分支用于跟踪某个远端仓库的分支(参见下节及第三章的内容),可以 使用 git pull 命令自动抓取数据下来,然后将远端分支自动合并到本地仓库中当前分 支。在日常工作中我们经常这么用,既快且好。实际上,默认情况下 git clone 命令 本质上就是自动创建了本地的 master 分支用于跟踪远程仓库中的 master 分支(假设 远程仓库确实有 master 分支)。所以一般我们运行 git pull,目的都是要从原始克 隆的远端仓库中抓取数据后,合并到工作目录中当前分支。 推送数据到远程仓库 项目进行到一个阶段,要同别人分享目前的成果,可以将本地仓库中的数据推送到远程 仓库。实现这个任务的命令很简单: git push [remote-name] [branch-name]。如果 要把本地的 master 分支推送到 origin 服务器上(再次说明下,克隆操作会自动使用 默认的 master 和 origin 名字),可以运行下面的命令: $ git push origin master 只有在所克隆的服务器上有写权限,或者同一时刻没有其他人在推数据,这条命令才会 如期完成任务。如果在你推数据前,已经有其他人推送了若干更新,那 你的推送操作 就会被驳回。你必须先把他们的更新抓取到本地,并到自己的项目中,然后才可以再次 推送。有关推送数据到远程仓库的详细内容见第三章。 查看远程仓库信息 我们可以通过命令 git remote show [remote-name] 查看某个远程仓库的详细信息, 比如要看所克隆的origin 仓库,可以运行: $ git remote show origin * remote origin URL: git://github.com/schacon/ticgit.git Remote branch merged with ‘git pull’ while on branch master master Tracked remote branches master ticgit 除了对应的克隆地址外,它还给出了许多额外的信息。它友善地告诉你如果是在 mast er 分支,就可以用git pull 命令抓取数据合并到本地。另外还列出了所有处于跟踪状 态中的远端分支。 实际使用过程中,git remote show 给出的信息可能会像这样: $ git remote show origin * remote origin URL: git@github.com:defunkt/github.git Remote branch merged with ‘git pull’ while on branch issues issues Remote branch merged with ‘git pull’ while on branch master master New remote branches (next fetch will store in remotes/origin) caching Stale tracking branches (use ‘git remote prune’) libwalker walker2 Tracked remote branches acl apiv2 dashboard2 issues master postgres Local branch pushed with ‘git push’ master:master 它告诉我们,运行 git push 时缺省推送的分支是什么(译注:最后两行)。它还显示 了有哪些远端分支还没有同步 到本地(译注:第六行的 caching 分支),哪些已同步 到本地的远端分支在远端服务器上已被删除(译注:Stale tracking branches 下面的 两个分支),以及运行 git pull 时将自动合并哪些分支(译注:前四行中列出的 is sues 和 master 分支)。(此命令也可以查看到本地分支和远程仓库分支的对应关系。 ) 远程仓库的删除和重命名 在新版 Git 中可以用 git remote rename 命令修改某个远程仓库的简短名称,比如想 把 pb 改成 paul,可以这么运行: $ git remote rename pb paul $ git remote origin paul 注意,对远程仓库的重命名,也会使对应的分支名称发生变化,原来的 pb/master 分 支现在成了paul/master。 碰到远端仓库服务器迁移,或者原来的克隆镜像不再使用,又或者某个参与者不再贡献 代码,那么需要移除对应的远端仓库,可以运行 git remote rm 命令: $ git remote rm paul $ git remote origin 推荐书籍 版本控制之道——使用Git 副标题: —使用Git 作者: Travis Swicegood 译者: 董越 / 付昭伟 / 等译 出版社: 电子工业出版社 出版年: 2010年5月 Git权威指南 作者: 蒋鑫 出版社: 机械工业出版社华章公司 出版年: 2011-6

archlinux 下安装kde4

一直用fvwm,心血来潮安装kde,画面华丽,但启动速度的确很慢,跟猪一样,2012.12月最新的arch下要安装的kde4,发现两个问题,

1. fcitx启动了但打不出字

2. 网络管理不知道用什么软件

研究了下,配置了.xprofile .profile .xinitrc加入

LOCALE=en_US.UTF-8

export LANG=zh_CN.UTF-8

export LC_ALL="zh_CN.UTF-8"

export XMODIFIERS=@im=fcitx

export GTK_IM_MODULE=fcitx

export QT_IM_MODULE=fcitx

然后安装gdm,用gdm启动,就可以使用fcitx了

至于网络么,就用:

pacman -S networkmanager kdeplasma-applets-networkmanagement

systemctl enable NetworkManager.service

然后kde的”系统管理“-》”网路管理”里面的所有选项就能用了

参加政协徐汇区委学习会

时间:2012年6月20号,上午9点

地点:政协徐汇区委1号楼2楼

主讲人:陈勇鸣,上海市市委党校教授

题目:创新驱动,转型发展的瓶颈与突破

 

区委的学习会我一向准时参加,这次陈勇鸣教授的报告相当精彩,我摘录了部分的ppt以供日后继续学习。

导航:大圆航线和等角航线

(\phi_1,\lambda_1),(\phi_2,\lambda_2)分别为起点和终点的地理坐标,其中\phi为维度,\lambda为 经度,计算北纬取正值,南纬取负值,东经取正值,西经取负值。起点和终点间的航路距离D的值以弧度为单位,需要乘以6372换算为公里。

1.大圆航线(Greate Circle)

通过两航路点间的地球大圆圈线为大圆航线。大圆航线上各点的真航线角不相等,但航线距离最短。

航线角的计算公式:cotTC=cos\phi_1 tan\phi_2 csc(\lambda_2 -\lambda_1 )sin\phi_1 cot(\lambda_2 -\lambda_1)

航线距离:cosD=sin\phi_1 sin\phi_2 +cos\phi_1 cos\phi_2 cos(\lambda_2 -\lambda_1)

2.等角航线(Rhumb Line)

两航路点间的等角线的航线为等角航线。等角航线是一条盘向两极的螺旋形曲线,等角航线上各点的航向角相等,但他的距离一般比大圆航线长。

航线角:tanTC=(\lambda_2 -\lambda_1)/[ln \ tan(45^0 +\phi_2 /2)-ln \ tan(45^0+\phi_1 /2)]

航线距离:D=(\phi_2 -\phi_1 )secTCD=(\lambda_2 -\lambda_1 )cos\bar\phi secTC

其中\bar\phi为起点和终点的平均纬度,仅在维度相差不大时使用后者。

第 4 页,共 22 页« 最新...23456...1020...最旧 »