Import Upstream version 0.0.8
Boyuan Yang
4 years ago
0 | gman: | |
1 | Xinkai Wang <aakwxk@hotmail.com> | |
2 | ||
3 | special thanks to Josip Rodin<jrodin@jagor.srce.hr>, | |
4 | who provide a patch to improve gman from 0.0.7 to 0.0.8 | |
5 |
0 | ChangeLog for G-man by Xinkai Wang | |
1 | ||
2 | v0.0.8 (10/17/99) | |
3 | - pure GTK+ implement, independent from gnome | |
4 | - gramatical and spelling errors corrected in README | |
5 | - fix in Makefile | |
6 | - gman.1x included | |
7 | - "show_warning" option | |
8 | ||
9 | v0.0.7 (10/12/99) | |
10 | - Second release | |
11 | - Should be bug free | |
12 | - keyword search capability | |
13 | - bug-fix for the "task" libary (which is a user-level thread libary) | |
14 | ||
15 | v0.0.2 (8/9/99) | |
16 | - First public release | |
17 | - Should be bug free | |
18 | - multi-thread implement | |
19 | - index search | |
20 | - Read the file README for usage and features |
0 | # Gman Makefile | |
1 | # You can adjust the following variables. | |
2 | CXX = g++ | |
3 | CXXFLAGS = -DVERSION=\"0.0.8\" `gtk-config --cflags` -O2 #-Wall | |
4 | CC = $(CXX) $(CXXFLAGS) | |
5 | ||
6 | GNOMELIB = #`gnome-config --libs gnomeui` | |
7 | prefix = /usr/local | |
8 | ||
9 | # There shouldn't be any need to edit anything below this point. | |
10 | all: gman | |
11 | ||
12 | gman: menu.o mandata.o util.o gman.o list.o context.o task.o taskfunc.o window2.o | |
13 | $(CC) -lgtk -lgdk -lpthread $(GNOMELIB) menu.o mandata.o util.o gman.o list.o context.o task.o taskfunc.o window2.o -o gman | |
14 | ||
15 | gman.o: gman.c menu.h | |
16 | $(CC) -c gman.c | |
17 | ||
18 | menu.o: menu.c mandata.h util.h | |
19 | $(CC) -c menu.c -o menu.o | |
20 | ||
21 | mandata.o: mandata.c mandata.h util.h mandatadef.h | |
22 | $(CC) -c mandata.c -o mandata.o | |
23 | ||
24 | util.o: util.c util.h | |
25 | $(CC) -c util.c -o util.o | |
26 | ||
27 | list.o: list.c list.h | |
28 | $(CC) -c list.c | |
29 | ||
30 | context.o: context.c context.h | |
31 | $(CC) -c context.c | |
32 | ||
33 | task.o: task.c task.h | |
34 | $(CC) -c task.c | |
35 | ||
36 | taskfunc.o: taskfunc.c taskfunc.h | |
37 | $(CC) -c taskfunc.c | |
38 | ||
39 | window2.o: window2.c window2.h | |
40 | $(CC) -c window2.c | |
41 | ||
42 | clean: | |
43 | rm -f *.o gman | |
44 | ||
45 | install: | |
46 | test -d $(prefix)/bin || mkdir -p $(prefix)/bin | |
47 | test -d $(prefix)/man/man1 || mkdir -p $(prefix)/man/man1 | |
48 | install -s -m 755 gman $(prefix)/bin | |
49 | install -m 644 gman.1x $(prefix)/man/man1 |
0 | ||
1 | General Information | |
2 | =================== | |
3 | ||
4 | This is Gman, a GTK+ front end for man. | |
5 | ||
6 | Gman's home page will be in http://homex.s-one.net.sg/user/xkwang/gman | |
7 | (still under construction) | |
8 | ||
9 | This a little piece of software is mostly developed for the new users of | |
10 | Unix/Linux. When I was a newbie of Linux, I felt I always could not find | |
11 | the man pages that I need. I believed the man pages must be somewhere in the | |
12 | system, but I just could not find the name of it. | |
13 | ||
14 | So I thought, maybe we need new graphical man page system. I don't like | |
15 | xman because it looks ugly and it is difficult to use (I felt). I think | |
16 | gnome-help-browser is too slow and it eats too much memory (about 12M on my | |
17 | system). It does not have index search function, and it can not be operated | |
18 | with keyboard shortcuts. | |
19 | ||
20 | I think an ideal help system must have the index search function (just like | |
21 | the help system on windoze). This will help a newbie to find the | |
22 | information that s/he needs, and sometimes help him/her go around to see | |
23 | what other man pages are there in the system, in his leisure time. | |
24 | ||
25 | Gman is nothing else but a simple front-end for the usual man page system. | |
26 | The most basic job of gman is to build a database for all the man pages | |
27 | and display them (or part of them) on the screen. When user decides to read | |
28 | a man page, gman will launch a xterm window and call the normal man system | |
29 | to display the man page in the window. Gman can launch more than one xterm | |
30 | window at same time. And user can use the index search function to look for | |
31 | the man pages that s/he needs. | |
32 | ||
33 | Installation | |
34 | ============ | |
35 | ||
36 | (possibly editing of Makefile) | |
37 | $ make | |
38 | (change to super user if needed) | |
39 | # make install | |
40 | ||
41 | This will put gman binary in /usr/local/bin, and its manual page | |
42 | in /usr/local/man/man1. | |
43 | ||
44 | Features of this version | |
45 | ======================== | |
46 | ||
47 | It's easy to write a simple software that can work, but the problem is | |
48 | in making it work better. It took me a lot of time to improve it's UI | |
49 | and some other little things, such as: | |
50 | ||
51 | 1. Multi-threading. | |
52 | When you have many manual pages on your system, some of the work (such | |
53 | as update window) will take a lot of time. So I used multi-thread | |
54 | programming, which means that the user can input new commands at any | |
55 | time, without waiting for the previous operation to end. | |
56 | ||
57 | 2. ~/.gman file. | |
58 | Every time gman starts up, it will read some configuration information | |
59 | from $HOME/.gman file. And every time gman exits, it will also write the | |
60 | current configuration information to that same file. ~/.gman file is a | |
61 | simple text file and can be edited using any text editor. | |
62 | ||
63 | To do | |
64 | ===== | |
65 | ||
66 | * autoconf support, especially if GNOME support is included. | |
67 | * use of gettext for easier translation to other languages. | |
68 | * improvment for the parser when reading the ~/.gman file (context.c). | |
69 | * internal method of displaying manual pages, not with xterm. | |
70 | ||
71 | Your comments and suggestions will be the most important for gman | |
72 | development. Patches (bug fixes or code additions) are welcome. | |
73 | ||
74 | Final note | |
75 | ========== | |
76 | ||
77 | I wonder if it is worthy for me to spend more time on it. Maybe, if you are | |
78 | already an expert, you will feel I'm wasting my time doing such useless | |
79 | work. I believe a user-friendly graphical interface is extremely important | |
80 | for a software system. Sometimes (often) people find it even more important | |
81 | than the contents of the software! (windoze is a good example) | |
82 | ||
83 | I hope you will benefit from my work. | |
84 | ||
85 | /* gman | |
86 | * Copyright (C) 1999 Xinkai Wang | |
87 | * | |
88 | * This program is free software; you can redistribute it and/or modify | |
89 | * it under the terms of the GNU General Public License as published by | |
90 | * the Free Software Foundation; either version 2 of the License, or | |
91 | * (at your option) any later version. | |
92 | * | |
93 | * This program is distributed in the hope that it will be useful, | |
94 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
95 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
96 | * GNU General Public License for more details. | |
97 | * | |
98 | * You should have received a copy of the GNU General Public License | |
99 | * along with this program; if not, write to the Free Software | |
100 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
101 | */ |
0 | /* config.h. Generated automatically by configure. */ | |
1 | /* config.h.in. Generated automatically from configure.in by autoheader. */ | |
2 | ||
3 | /* Define if you have the ANSI C header files. */ | |
4 | #define STDC_HEADERS 1 | |
5 | ||
6 | /* Name of package */ | |
7 | #define PACKAGE "project1" | |
8 | ||
9 | /* Version number of package */ | |
10 | #define VERSION "0.1" | |
11 |
0 | /****************** context.c ******************/ | |
1 | /****************** 1999.6.17 ******************/ | |
2 | #include <stdio.h> | |
3 | #include <string.h> | |
4 | #include "context.h" | |
5 | #include "util.h" | |
6 | ||
7 | AppContext::AppContext() | |
8 | { | |
9 | names = new List(); | |
10 | types = new List(); | |
11 | values = new List(); | |
12 | name_default = new List(); | |
13 | type_default = new List(); | |
14 | value_default = new List(); | |
15 | ||
16 | set_default_value("h_size","int",(void *)300); | |
17 | set_default_value("v_size","int",(void *)200); | |
18 | } | |
19 | ||
20 | AppContext::~AppContext() | |
21 | { | |
22 | delete names; | |
23 | delete types; | |
24 | delete values; | |
25 | delete name_default; | |
26 | delete type_default; | |
27 | delete value_default; | |
28 | } | |
29 | ||
30 | int AppContext::search_name(List * list,char * name) | |
31 | { | |
32 | int i,j; | |
33 | j = list->get_size(); | |
34 | for (i = 0;i < j;i++) | |
35 | if (!strcmp((char*)(list->get_item(i)),name)) break; | |
36 | return (i<j)? i:-1; | |
37 | } | |
38 | ||
39 | int AppContext::set_value(char * _name, char * type, void * data) | |
40 | { | |
41 | int i; | |
42 | if((i = search_name(name_default,_name)) != -1) { | |
43 | if( !strcmp((char*)type_default->get_item(i),type)) { | |
44 | if((i = search_name(names,_name)) != -1) | |
45 | values->reset_item(i,data); | |
46 | else{ | |
47 | values->add_item(data); | |
48 | types->add_item(type); | |
49 | names->add_item(_name); | |
50 | } | |
51 | } | |
52 | else { | |
53 | fprintf(stderr,"Warning: class AppContext: data type mismatch, " | |
54 | " variable \"%s\" is a \"%s\" instead of \"%s\"\n", | |
55 | name_default->get_item(i),type_default->get_item(i),type); | |
56 | return 1; | |
57 | } | |
58 | } | |
59 | else { | |
60 | if((i = search_name(names,_name)) != -1) | |
61 | values->reset_item(i,data); | |
62 | else{ | |
63 | values->add_item(data); | |
64 | types->add_item(type); | |
65 | names->add_item(_name); | |
66 | } | |
67 | } | |
68 | return 0; | |
69 | } | |
70 | ||
71 | void * AppContext::get_value(char * _name) | |
72 | { | |
73 | int i; | |
74 | if((i = search_name(names,_name)) != -1) | |
75 | return values->get_item(i); | |
76 | else if ((i = search_name(name_default,_name)) != -1) | |
77 | return value_default->get_item(i); | |
78 | return 0; | |
79 | } | |
80 | ||
81 | char * AppContext::get_value_type(char * _name) | |
82 | { | |
83 | int i; | |
84 | if((i = search_name(names,_name)) != -1) | |
85 | return (char*)types->get_item(i); | |
86 | else if ((i = search_name(name_default,_name)) != -1) | |
87 | return (char*)type_default->get_item(i); | |
88 | return NULL; | |
89 | } | |
90 | ||
91 | void AppContext::set_default_value(char * _name, char * type, void * data) | |
92 | { | |
93 | int i; | |
94 | if((i = search_name(name_default,_name)) != -1) { | |
95 | value_default->reset_item(i,data); | |
96 | type_default->reset_item(i,type); | |
97 | } | |
98 | else{ | |
99 | name_default->add_item(_name); | |
100 | type_default->add_item(type); | |
101 | value_default->add_item(data); | |
102 | } | |
103 | } | |
104 | ||
105 | void AppContext::restore_default(char * _name) | |
106 | { | |
107 | int i; | |
108 | if((i = search_name(names,_name)) != -1) { | |
109 | values->delete_item(i); | |
110 | types->delete_item(i); | |
111 | names->delete_item(i); | |
112 | } | |
113 | } | |
114 | ||
115 | void AppContext::restore_all() | |
116 | { | |
117 | names->delete_all(); | |
118 | types->delete_all(); | |
119 | values->delete_all(); | |
120 | } | |
121 | ||
122 | void AppContext::display_values() | |
123 | { | |
124 | int i,j,k; | |
125 | printf("values:\n"); | |
126 | j = names->get_size(); | |
127 | for(i = 0; i<j;i++) | |
128 | if(!strcmp((char*)types->get_item(i),"char*")) | |
129 | printf("\"%s\" = \"%s\"\n",names->get_item(i),values->get_item(i)); | |
130 | else if(!strcmp((char*)types->get_item(i),"int")) | |
131 | printf("\"%s\" = %d\n",names->get_item(i),values->get_item(i)); | |
132 | else | |
133 | printf("\"%s\" = 0x%x\n",names->get_item(i),values->get_item(i)); | |
134 | printf("default values:\n"); | |
135 | j = name_default->get_size(); | |
136 | for(i = 0; i<j;i++) | |
137 | if(!strcmp((char*)type_default->get_item(i),"char*")) | |
138 | printf("\"%s\" = \"%s\"\n",name_default->get_item(i),value_default->get_item(i)); | |
139 | else if(!strcmp((char*)type_default->get_item(i),"int")) | |
140 | printf("\"%s\" = %d\n",name_default->get_item(i),value_default->get_item(i)); | |
141 | else | |
142 | printf("\"%s\" = 0x%x\n",name_default->get_item(i),value_default->get_item(i)); | |
143 | } | |
144 | ||
145 | #define BUFFER_LENGTH 200 | |
146 | #define BEGIN 1 | |
147 | #define NAME 2 | |
148 | #define NAME_ESCAPE 4 | |
149 | #define VALUE 3 | |
150 | ||
151 | static int is_blank(char c) { return c==' ' || c==9;} | |
152 | static int is_end(char c) { return c=='\n' || c == 0;} | |
153 | static int is_number(char c) {return c<='9' && c>='0';} | |
154 | ||
155 | static void * my_parser(char *a, char ** type) | |
156 | { | |
157 | char * b; | |
158 | int n; | |
159 | for(b = a; is_number(*b) && !is_blank(*b) && !is_end(*b);b++); | |
160 | if(!(is_blank(*b)||is_end(*b))) { | |
161 | for(;!is_blank(*b) && !is_end(*b);b++); | |
162 | *b = '\0'; | |
163 | *type = "char*"; | |
164 | return (void*)my_strdup(a); | |
165 | } | |
166 | else { | |
167 | *type = "int"; | |
168 | sscanf(a,"%d",&n); | |
169 | return (void*) n; | |
170 | } | |
171 | } | |
172 | ||
173 | void AppContext::load(FILE * fd) | |
174 | { | |
175 | int i,j,k,state; | |
176 | long pos; | |
177 | char *a,*b,*c,*name,*type; | |
178 | void * value; | |
179 | char buffer[BUFFER_LENGTH]; | |
180 | ||
181 | a = buffer; | |
182 | pos = 0L; | |
183 | for(k = 1;k;){ | |
184 | fseek(fd,pos,SEEK_SET); | |
185 | i = fread(buffer,1,BUFFER_LENGTH-1,fd); | |
186 | if (i == 0) break; | |
187 | buffer[i] = '\0'; | |
188 | //printf(buffer); | |
189 | b = strchr(buffer,(int)'\n'); | |
190 | if (b) { | |
191 | pos += b - buffer +1; | |
192 | *b = '\0'; | |
193 | } | |
194 | else k = 0; | |
195 | ||
196 | for(a = buffer;is_blank(*a) && !is_end(*a);a++); | |
197 | if (*a == '#' || is_end(*a)) continue; | |
198 | for(b = a;!is_blank(*b) && !is_end(*b) && *b != '=';b++); | |
199 | if(is_end(*b)) continue; | |
200 | c = strchr(b,(int)'='); | |
201 | if(!c) continue; | |
202 | c++; | |
203 | for(;is_blank(*c) && !is_end(*c);c++); | |
204 | if(is_end(*c)) continue; | |
205 | *b = 0; | |
206 | // printf("name = %s, value = %s",a,c); | |
207 | name = my_strdup(a); | |
208 | value = my_parser(c,&type); | |
209 | set_value(name,type,value); | |
210 | } | |
211 | } | |
212 | ||
213 | void AppContext::save(FILE * fp, char * header) | |
214 | { | |
215 | int i,j,k; | |
216 | char * type; | |
217 | if(header != NULL) | |
218 | fprintf(fp,"#%s\n\n",header); | |
219 | ||
220 | j = names->get_size(); | |
221 | for (i = 0;i<j;i++) { | |
222 | type = (char*)types->get_item(i); | |
223 | if (!strcmp(type,"char*")) | |
224 | fprintf(fp,"%s = %s\n",names->get_item(i),values->get_item(i)); | |
225 | else if (!strcmp(type,"int")) | |
226 | fprintf(fp,"%s = %d\n",names->get_item(i),values->get_item(i)); | |
227 | else fprintf(stderr,"class AppContext: save: type \"%s\" does not be supported yet.\n",type); | |
228 | } | |
229 | } | |
230 | ||
231 | #undef BUFFER_LENGTH | |
232 | ||
233 |
0 | /******************** context.h ********************/ | |
1 | ||
2 | #ifndef _CONTEXT_H | |
3 | #define _CONTEXT_H | |
4 | ||
5 | #include <stdio.h> | |
6 | #include "list.h" | |
7 | ||
8 | class AppContext | |
9 | { | |
10 | public: | |
11 | AppContext(); | |
12 | ~AppContext(); | |
13 | void * get_value(char * name); | |
14 | char * get_value_type(char * name); | |
15 | int set_value(char * name, char * type, void * buffer); | |
16 | void set_default_value(char *name, char * type, void * buffer); | |
17 | /* AppContext::set_value() and set_default_value() only implement simpliest | |
18 | data management function. If the name or type is in a temp buffer, | |
19 | it is caller's duty to do strdup() before call the set_value() or | |
20 | set_default_value() */ | |
21 | void restore_default(char * name); | |
22 | void restore_all(); | |
23 | void load(FILE *); | |
24 | void save(FILE *, char *); | |
25 | void display_values(); | |
26 | private: | |
27 | int search_name(List*, char *); | |
28 | List * names; | |
29 | List * types; | |
30 | List * values; | |
31 | List * name_default; | |
32 | List * type_default; | |
33 | List * value_default; | |
34 | }; | |
35 | ||
36 | #endif |
0 | .TH GMAN 1x "October 1999" "Gman" | |
1 | .SH NAME | |
2 | gman \- small X/GTK+ based man front-end | |
3 | .SH SYNOPSIS | |
4 | .B gman | |
5 | .SH DESCRIPTION | |
6 | .B Gman | |
7 | is nothing else but only a simple front-end for the original | |
8 | .I man | |
9 | page system. The most basic job of gman is to build a database for all | |
10 | the man pages and display them (or part of them) on the screen. When | |
11 | user decides to read a man page, | |
12 | .B gman | |
13 | will launch a | |
14 | .I xterm | |
15 | window and call the normal man system to display the man page in the | |
16 | window. | |
17 | .sp | |
18 | .B Gman | |
19 | can launch more than one xterm window at same time. And user can use | |
20 | the index search function to look for the man pages that he needs. | |
21 | .sp | |
22 | It is simple, but it is useful. | |
23 | .SH OPTIONS | |
24 | There are no command line options for gman, for now. | |
25 | .SH FILES | |
26 | .PD 0 | |
27 | .TP 20 | |
28 | .I ~/.gman | |
29 | .PD | |
30 | .SH SEE ALSO | |
31 | .BR man (1), | |
32 | .BR man (7), | |
33 | .BR xterm (1). | |
34 | .SH AUTHOR | |
35 | .B Gman | |
36 | was written by Xinkai Wang <aakwxk@hotmail.com>. Home page of gman is at: | |
37 | .br | |
38 | .I http://homex.s-one.net.sg/user/xkwang/gman |
0 | /********************* gman.c ********************************/ | |
1 | /* gman | |
2 | * Copyright (C) 1999 Xinkai Wang | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License as published by | |
6 | * the Free Software Foundation; either version 2 of the License, or | |
7 | * (at your option) any later version. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | * GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License | |
15 | * along with this program; if not, write to the Free Software | |
16 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
17 | */ | |
18 | ||
19 | #include <stdio.h> | |
20 | #include <stdlib.h> | |
21 | ||
22 | #include <gtk/gtk.h> | |
23 | #include "menu.h" | |
24 | #include "context.h" | |
25 | #include "gman.h" | |
26 | #include "task.h" | |
27 | #include "taskfunc.h" | |
28 | #include "mandata.h" | |
29 | #include <unistd.h> | |
30 | ||
31 | void init_context(); | |
32 | pthread_mutex_t gtk_lock; | |
33 | pthread_mutex_t context_lock; | |
34 | pthread_mutex_t loading_man_path_lock; | |
35 | AppContext * context; | |
36 | int debuging; | |
37 | ||
38 | /********************** main **********************/ | |
39 | TaskGroup * task_group; | |
40 | ||
41 | void main(int argc, char *argv[]) | |
42 | { | |
43 | GtkWidget *window; | |
44 | pthread_t th_init_data; | |
45 | ||
46 | pthread_mutex_init(>k_lock,NULL); | |
47 | pthread_mutex_init(&context_lock,NULL); | |
48 | pthread_mutex_init(&loading_man_path_lock,NULL); | |
49 | init_context(); | |
50 | debuging = (int)context->get_value("debuging"); | |
51 | pthread_mutex_lock(>k_lock); | |
52 | gtk_init (&argc, &argv); | |
53 | window = gtk_window_new(GTK_WINDOW_TOPLEVEL); | |
54 | ||
55 | task_group = task_group_new(); | |
56 | init_thread(task_group); | |
57 | ||
58 | init_main_window(window); | |
59 | gtk_widget_show(window); | |
60 | pthread_mutex_unlock(>k_lock); | |
61 | //pthread_create(&th_init_data, NULL, (void * (*)(void*))init_man_data, 0); | |
62 | ||
63 | //gtk_main(); | |
64 | ||
65 | while(1){ | |
66 | pthread_mutex_lock(>k_lock); | |
67 | while(gtk_events_pending()) { | |
68 | gtk_main_iteration(); | |
69 | } | |
70 | pthread_mutex_unlock(>k_lock); | |
71 | usleep(10000); | |
72 | } | |
73 | ||
74 | return(0); | |
75 | } | |
76 | ||
77 | /******************* init_context() *****************/ | |
78 | void init_context() | |
79 | { | |
80 | FILE * fd; | |
81 | char buffer[256]; | |
82 | context = new AppContext(); | |
83 | // context->set_default_value("v_size",(void*)400); | |
84 | context->set_default_value("debuging","int",(void*)0); | |
85 | context->set_default_value("man_paths","char*",(void*)"/usr/man:/usr/local/man:/usr/X11R6/man"); | |
86 | context->set_default_value("display_section_policy","int",(void*)0); | |
87 | context->set_default_value("display_section","int",(void*)3); | |
88 | context->set_default_value("xterm_command","char*",(void*)"xterm"); | |
89 | context->set_default_value("searching_mode","int",(void*)0); | |
90 | context->set_default_value("show_status_bar","int",(void*)0); | |
91 | context->set_default_value("show_warning","int",(void*)1); | |
92 | ||
93 | attach(buffer,getenv("HOME"),".gman"); | |
94 | if((fd = fopen(buffer,"r"))) { | |
95 | context->load(fd); | |
96 | fclose(fd); | |
97 | } | |
98 | if(context->get_value("debuging")) context->display_values(); | |
99 | //context->save(stdout,"this is just a test"); | |
100 | } | |
101 | ||
102 | ||
103 |
0 | /******************** context.h ********************/ | |
1 | ||
2 | #ifndef _GMAN_H | |
3 | #define _GMAN_H | |
4 | ||
5 | #include "context.h" | |
6 | #include <pthread.h> | |
7 | ||
8 | extern pthread_mutex_t gtk_lock; | |
9 | extern pthread_mutex_t context_lock; | |
10 | extern pthread_mutex_t loading_man_path_lock; | |
11 | extern AppContext * context; | |
12 | extern int debuging; | |
13 | #endif |
0 | #define CANNOT_FORK 1 | |
1 | #define WAIT_FAILED 2 | |
2 | #define GOT_WRONG_PID 3 | |
3 | #define CHILD_TERMINATED_ABNORMALLY 4 | |
4 | #define NO_EXEC 5 | |
5 | #define SYSTEM_FAILED 6 | |
6 | #define OUT_OF_MEMORY 7 |
0 | /********************* list.c **********************/ | |
1 | /********************* 1999.6.13 *******************/ | |
2 | ||
3 | #include "list.h" | |
4 | #include <stdlib.h> | |
5 | #include <unistd.h> | |
6 | #include <stdio.h> | |
7 | #include <string.h> | |
8 | #include <glib.h> | |
9 | ||
10 | #define LIST_INIT_SIZE 15 | |
11 | List::List() | |
12 | { | |
13 | items = NULL; | |
14 | buffer_length = 0; | |
15 | count = 0; | |
16 | }; | |
17 | ||
18 | List::~List() | |
19 | { | |
20 | if(items) free(items); | |
21 | }; | |
22 | ||
23 | void List::add_item(void * item) | |
24 | { | |
25 | if(!items) { | |
26 | items = (void **)malloc((size_t)sizeof(void*)*LIST_INIT_SIZE); | |
27 | if(!items) { | |
28 | perror("class List: can not malloc mem when init:"); | |
29 | exit(1); | |
30 | } | |
31 | buffer_length = LIST_INIT_SIZE; | |
32 | } | |
33 | else if(buffer_length == count){ | |
34 | items = (void **)realloc((void*)items,sizeof(void *)*(buffer_length+=buffer_length)); | |
35 | if(!items){ | |
36 | perror("class List: mem not enought when realloc:"); | |
37 | exit(1); | |
38 | } | |
39 | } | |
40 | items[count++] = item; | |
41 | } | |
42 | ||
43 | void * List::get_item(int handle) | |
44 | { | |
45 | if(handle >= count || handle < 0) return NULL; | |
46 | return items[handle]; | |
47 | } | |
48 | ||
49 | int List::reset_item(int handle, void * data) | |
50 | { | |
51 | if(handle >= count || handle < 0) return 1; | |
52 | items[handle] = data; | |
53 | return 0; | |
54 | } | |
55 | ||
56 | int List::search_item(void * item) | |
57 | { | |
58 | int i; | |
59 | for (i = 0;i < count && items[i] != item;i++); | |
60 | return (i == count)? -1:i; | |
61 | } | |
62 | ||
63 | int List::delete_item(int handle) | |
64 | { | |
65 | g_return_val_if_fail(handle < count && handle >= 0, 1); | |
66 | if(handle != count-1) memmove(items+handle, | |
67 | items+(handle+1), | |
68 | (count-handle-1)*sizeof(void*)); | |
69 | count--; | |
70 | return 0; | |
71 | } | |
72 | ||
73 | void List::insert_item(int handle, void * item) | |
74 | { | |
75 | int i; | |
76 | if(!items) { | |
77 | items = (void **)malloc(sizeof(void*)*LIST_INIT_SIZE); | |
78 | if(!items) { | |
79 | perror("class List: can not malloc mem when init:"); | |
80 | exit(1); | |
81 | } | |
82 | buffer_length = LIST_INIT_SIZE; | |
83 | } | |
84 | else if(buffer_length == count){ | |
85 | items = (void **)realloc((void*)items,sizeof(void *)*(buffer_length+=buffer_length)); | |
86 | if(!items){ | |
87 | perror("class List: mem not enought when realloc:"); | |
88 | exit(1); | |
89 | } | |
90 | } | |
91 | if(handle >= count) | |
92 | items[count++] = item; | |
93 | else { | |
94 | handle = handle <0? 0:handle; | |
95 | for(i = count++;i>handle;i--) | |
96 | items[i] = items[i-1]; | |
97 | items[handle] = item; | |
98 | } | |
99 | } | |
100 | ||
101 | void List::delete_all() | |
102 | { | |
103 | count = 0; | |
104 | } | |
105 | ||
106 | int List::get_items(void * buffer) | |
107 | { | |
108 | memcpy((void *)buffer,(void *)items,count*sizeof(void*)); | |
109 | return count; | |
110 | } | |
111 | ||
112 | int List::get_size() | |
113 | { | |
114 | return count; | |
115 | } | |
116 | ||
117 | int List::meet_end(int handle) | |
118 | { | |
119 | return (handle >= count)? 1:0; | |
120 | } | |
121 | ||
122 | /********************* class Dictionary ***************/ | |
123 | ||
124 | Dictionary::Dictionary() | |
125 | { | |
126 | names = new List; | |
127 | values = new List; | |
128 | } | |
129 | ||
130 | Dictionary::~Dictionary() | |
131 | { | |
132 | delete(names); | |
133 | delete(values); | |
134 | } | |
135 | ||
136 | void Dictionary::add_item(char * name,void * value) | |
137 | { | |
138 | int i; | |
139 | if((i = search_item(name)) != -1) { | |
140 | values->reset_item(i,value); | |
141 | } | |
142 | else { | |
143 | names->add_item(name); | |
144 | values->add_item(value); | |
145 | } | |
146 | } | |
147 | ||
148 | int Dictionary::search_item(char * name) | |
149 | { | |
150 | int i,j; | |
151 | j = names->get_size(); | |
152 | for(i = 0;i<j && strcmp(name,(char*)names->get_item(i));i++); | |
153 | return (i==j)? -1:i; | |
154 | } | |
155 | ||
156 | int Dictionary::have_item(char * name) | |
157 | { | |
158 | return search_item(name) != -1; | |
159 | } | |
160 | ||
161 | void * Dictionary::get_value(char * name) | |
162 | { | |
163 | int i; | |
164 | i = names->search_item(name); | |
165 | return (i==-1)? NULL:values->get_item(i); | |
166 | } | |
167 | ||
168 | int Dictionary::get_size() | |
169 | { | |
170 | return names->get_size(); | |
171 | } | |
172 | ||
173 | void * Dictionary::get_value(int i) | |
174 | { | |
175 | return values->get_item(i); | |
176 | } | |
177 | ||
178 | char * Dictionary::get_name(int i) | |
179 | { | |
180 | return (char*)names->get_item(i); | |
181 | } | |
182 | ||
183 | void Dictionary::set_value(int i, void * value) | |
184 | { | |
185 | values->reset_item(i,value); | |
186 | } | |
187 | ||
188 | void Dictionary::delete_item(int i) | |
189 | { | |
190 | names->delete_item(i); | |
191 | values->delete_item(i); | |
192 | } | |
193 | ||
194 | void Dictionary::display_items() | |
195 | { | |
196 | int i,j; | |
197 | j = names->get_size(); | |
198 | for(i = 0;i<j;i++) | |
199 | printf("%s\n",names->get_item(i)); | |
200 | } | |
201 | ||
202 | ||
203 |
0 | /******************** list.h *****************/ | |
1 | /******************** 1999.6.13 *************/ | |
2 | ||
3 | #ifndef _LIST_H | |
4 | #define _LIST_H | |
5 | ||
6 | class List | |
7 | { | |
8 | private: | |
9 | void ** items; | |
10 | int buffer_length; | |
11 | int count; | |
12 | public: | |
13 | List(); | |
14 | ~List(); | |
15 | void add_item(void * item); | |
16 | void * get_item(int handle); | |
17 | int reset_item(int handle,void * item); | |
18 | int search_item(void * item); | |
19 | int delete_item(int handle); | |
20 | void insert_item(int handle, void * item); | |
21 | void delete_all(); | |
22 | int get_size(); | |
23 | int get_items(void * buffer); | |
24 | int meet_end(int handle); | |
25 | }; | |
26 | ||
27 | class Dictionary | |
28 | { | |
29 | private: | |
30 | List * names; | |
31 | List * values; | |
32 | public: | |
33 | Dictionary(); | |
34 | ~Dictionary(); | |
35 | void add_item(char * name,void * value); | |
36 | int have_item(char * name); | |
37 | int search_item(char * name); | |
38 | void * get_value(char* name); | |
39 | int get_size(); | |
40 | void * get_value(int i); | |
41 | char * get_name(int i); | |
42 | void set_value(int i,void * value); | |
43 | void delete_item(int i); | |
44 | void display_items(); | |
45 | }; | |
46 | ||
47 | #endif | |
48 | ||
49 | ||
50 | ||
51 | ||
52 | ||
53 | ||
54 | ||
55 | ||
56 | ||
57 |
0 | /********************** modified from t2.c *******************/ | |
1 | /********************* kman.c ********************************/ | |
2 | ||
3 | #include <stdio.h> | |
4 | #include <string.h> | |
5 | #include <sys/types.h> | |
6 | #ifdef SYS_DIR | |
7 | #include <sys_dir.h> | |
8 | #else | |
9 | #ifdef NDIR | |
10 | ||
11 | #include <ndir.h> | |
12 | #else | |
13 | #include <dirent.h> | |
14 | #endif | |
15 | #endif | |
16 | ||
17 | #include <sys/stat.h> | |
18 | #include <unistd.h> | |
19 | #include <errno.h> | |
20 | ||
21 | #include "mandata.h" | |
22 | #include "mandatadef.h" | |
23 | #include "util.h" | |
24 | #include "context.h" | |
25 | #include "gman.h" | |
26 | ||
27 | #include <stdlib.h> | |
28 | ||
29 | void attach (char *dest, const char *dirname, const char *name); | |
30 | static int section_translate_c_to_n(const char* c); | |
31 | static int ManItemComp(ManItem ** a,ManItem ** b); | |
32 | static int is_zip_suffix(char* c); | |
33 | ||
34 | char buffer1[BUFFER_SIZE]; | |
35 | char buffer2[BUFFER_SIZE]; | |
36 | ||
37 | /************************* ManPath ************************/ | |
38 | ManPath::ManPath(char* _path_name) | |
39 | { | |
40 | int i; | |
41 | int len; | |
42 | active = 1; | |
43 | path_name = my_strdup(_path_name); | |
44 | for (i=0;i<MAX_MAN_SECTION;i++) section[i] = new List(); | |
45 | LoadManPath(path_name); | |
46 | } | |
47 | ||
48 | ManPath::~ManPath() | |
49 | { | |
50 | int i,j,k; | |
51 | for (i = 0;i<MAX_MAN_SECTION;i++) { | |
52 | k = section[i]->get_size(); | |
53 | for(j = 0;j<k;j++) delete ((ManItem*)(section[i]->get_item(j))); | |
54 | delete(section[i]); | |
55 | } | |
56 | if(path_name) free(path_name); | |
57 | } | |
58 | ||
59 | ManPath::GetSize(int section_ID) | |
60 | { | |
61 | int count; | |
62 | int i; | |
63 | for (count = i = 0;i<MAX_MAN_SECTION;i++) | |
64 | if (1<<i & section_ID) count += section[i]->get_size(); | |
65 | return count; | |
66 | } | |
67 | ||
68 | ManPath::GetItems(int section_ID, ManItem * buffer[]) | |
69 | { | |
70 | int count; | |
71 | int i; | |
72 | for (count = i = 0;i<MAX_MAN_SECTION;i++) | |
73 | if (1<<i & section_ID) count += section[i]->get_items((void*)(buffer + count)); | |
74 | return count; | |
75 | } | |
76 | ||
77 | const char * ManPath::GetPath() {return (const char*) path_name;} | |
78 | ||
79 | struct stat state; | |
80 | ||
81 | ManPath::LoadManPath(char * path_name) | |
82 | { | |
83 | DIR *dirp; | |
84 | #if defined(SYS_DIR)||defined(NDIR) | |
85 | struct direct *item; | |
86 | #else | |
87 | struct dirent *item; | |
88 | #endif | |
89 | ||
90 | ManItem * man_item; | |
91 | int val,i; | |
92 | ||
93 | // printf("LoadManPath: %s\n",path_name); | |
94 | ||
95 | dirp = opendir(path_name); | |
96 | if (!dirp) | |
97 | { | |
98 | fprintf(stderr,"Can not open man path %s\n",path_name); | |
99 | return 1; | |
100 | } | |
101 | for (item = readdir(dirp);item != NULL;item = readdir(dirp)) | |
102 | { | |
103 | if(item->d_name[0] == '.' && (item->d_name[1] == 0 ||(item->d_name[1] == '.'&&item->d_name[2]==0))) | |
104 | continue; | |
105 | attach(buffer1,path_name,item->d_name); | |
106 | //printf("LoadManPath: %s\n",name); | |
107 | val = stat (buffer1, &state); | |
108 | if (val < 0) fprintf(stderr,"error number %d, in get state %s",errno,buffer1); | |
109 | else if (S_ISDIR(state.st_mode) && !strncmp(item->d_name,"man",3)) LoadManSubPath(item->d_name); | |
110 | else | |
111 | { | |
112 | man_item = new ManItem(this,item -> d_name); | |
113 | val = man_item->get_section_ID(); | |
114 | if(!val) delete(man_item); | |
115 | else{ | |
116 | for(i = 0;!(1<<i & val);i++); | |
117 | section[i]->add_item(man_item); | |
118 | } | |
119 | //printf("%d\n",n); | |
120 | } | |
121 | } | |
122 | closedir(dirp); | |
123 | return 0; | |
124 | } | |
125 | ||
126 | ManPath::LoadManSubPath(char * sub_name) | |
127 | { | |
128 | DIR *dirp; | |
129 | #if defined(SYS_DIR)||defined(NDIR) | |
130 | struct direct *item; | |
131 | #else | |
132 | struct dirent *item; | |
133 | #endif | |
134 | ||
135 | int val,i; | |
136 | ManItem * man_item; | |
137 | ||
138 | attach(buffer2,path_name,sub_name); | |
139 | //printf("LoadManSubPath: %s\n",buffer2); | |
140 | dirp = opendir(buffer2); | |
141 | if (!dirp) | |
142 | { | |
143 | fprintf(stderr,"Can not open man path %s\n",buffer2); | |
144 | } | |
145 | for (item = readdir(dirp);item != NULL;item = readdir(dirp)) | |
146 | { | |
147 | if(item->d_name[0] == '.' && (item->d_name[1] == 0 ||(item->d_name[1] == '.'&&item->d_name[2]==0))) | |
148 | continue; | |
149 | attach(buffer1,buffer2,item->d_name); | |
150 | //printf("LoadManSubPath: %s\n",full_name); | |
151 | val = stat (buffer1, &state); | |
152 | if (val < 0) fprintf(stderr,"error number %d, in get state %s\n",errno,buffer1); | |
153 | else if (S_ISDIR(state.st_mode)) continue; | |
154 | else | |
155 | { | |
156 | attach(buffer1,sub_name,item->d_name); | |
157 | man_item = new ManItem(this,buffer1); | |
158 | val = man_item->get_section_ID(); | |
159 | if(!val) delete(man_item); | |
160 | else{ | |
161 | for(i = 0;!(1<<i & val);i++); | |
162 | section[i]->add_item(man_item); | |
163 | } | |
164 | } | |
165 | } | |
166 | closedir(dirp); | |
167 | } | |
168 | ||
169 | ManItem * ManPath::search_man_item(char * name, char * sect) | |
170 | { | |
171 | int i,j,k; | |
172 | int len; | |
173 | ManItem * a; | |
174 | char buffer[100]; | |
175 | ||
176 | len = strlen(name); | |
177 | if(section) { | |
178 | j = section_translate_c_to_n(sect); | |
179 | //printf("point0.1\n"); | |
180 | if(!j) return NULL; | |
181 | for(i = 0;!(1<<i & j);i++); | |
182 | //printf("point0.2, section = %x,%d: section[i] = %x\n", j,i,section[i]); | |
183 | k = section[i]->get_size(); | |
184 | //printf("point0.25, k = %d\n",k); | |
185 | for(j = 0;j<k;j++) { | |
186 | a=(ManItem*)(section[i]->get_item(j)); | |
187 | if(!strcmp(name,a->get_display_name(buffer))) return a; | |
188 | } | |
189 | a = NULL; | |
190 | } | |
191 | return NULL; | |
192 | } | |
193 | ||
194 | /************************* ManItem ************************/ | |
195 | inline ManItem::ManItem(ManPath* _man_path, char* _file_name) | |
196 | { | |
197 | file_name = my_strdup(_file_name); | |
198 | man_path = _man_path; | |
199 | display_name = strrchr(file_name,'/'); | |
200 | display_name = display_name? display_name + sizeof('/'):file_name; | |
201 | section_name = strrchr(display_name,'.'); | |
202 | if (!section_name) { section_ID = 0; return;} | |
203 | for (;is_zip_suffix(section_name) && section_name != display_name;) | |
204 | for(section_name--;section_name != display_name && *section_name != '.';section_name --); | |
205 | if (section_name == display_name) {section_ID = 0; return;} | |
206 | section_ID = section_translate_c_to_n(++section_name); | |
207 | //if(!section_ID) printf("%s\n",display_name); | |
208 | } | |
209 | ||
210 | inline ManItem::~ManItem() | |
211 | { | |
212 | if(file_name) free(file_name); | |
213 | } | |
214 | ||
215 | char * ManItem::get_display_name(char * buffer) | |
216 | { | |
217 | char * p2 = buffer; | |
218 | for(char * p = display_name;p+1 != section_name && *p != '\0';) *buffer++ = *p++; | |
219 | *buffer = '\0'; | |
220 | return p2; | |
221 | } | |
222 | ||
223 | char * ManItem::get_section_name(char * buffer) | |
224 | { | |
225 | char * p2 = buffer; | |
226 | for(char * p = section_name;*p != '.' && *p != '\0';) *buffer++ = *p++; | |
227 | *buffer = '\0'; | |
228 | return p2; | |
229 | } | |
230 | ||
231 | int ManItem::get_section_ID() {return section_ID;} | |
232 | ||
233 | void * ManItem::get_man_path() {return (void *)man_path;} | |
234 | ||
235 | void ManItem::active_man_page(void) | |
236 | { | |
237 | int i; | |
238 | int len; | |
239 | char buffer[BUFFER_SIZE]; | |
240 | sprintf(buffer,"%s -T '%s' -n GMan -e man ", | |
241 | (char*)context->get_value("xterm_command"), | |
242 | get_display_name(buffer1)); | |
243 | len = strlen(buffer); | |
244 | attach(buffer+len,man_path->GetPath(),file_name); | |
245 | //printf(buffer); | |
246 | ||
247 | if(!fork()) | |
248 | { | |
249 | //printf(buffer); | |
250 | system(buffer); | |
251 | _exit(0); | |
252 | } | |
253 | ||
254 | return; | |
255 | } | |
256 | ||
257 | /************************* init global data ************************/ | |
258 | ||
259 | /* Put DIRNAME/NAME into DEST, handling `.' and `/' properly. */ | |
260 | ||
261 | void attach (char *dest, const char *dirname, const char *name) | |
262 | { | |
263 | const char *dirnamep = dirname; | |
264 | ||
265 | /* Copy dirname if it is not ".". */ | |
266 | if (dirname[0] != '.' || dirname[1] != 0) | |
267 | { | |
268 | while (*dirnamep) *dest++ = *dirnamep++; | |
269 | /* Add '/' if `dirname' doesn't already end with it. */ | |
270 | if (dirnamep > dirname && dirnamep[-1] != '/') *dest++ = '/'; | |
271 | } | |
272 | while (*name) *dest++ = *name++; | |
273 | *dest = 0; | |
274 | } | |
275 | ||
276 | int section_translate_c_to_n(const char *c) | |
277 | { | |
278 | int i; | |
279 | for(i=0;sections[i].name && strncmp(sections[i].name,c,sections[i].n);i++); | |
280 | if(sections[i].name == NULL) return 0; // no match | |
281 | return 1<<i; | |
282 | } | |
283 | ||
284 | int is_zip_suffix(char * s) | |
285 | { | |
286 | int i; | |
287 | for (i=0;suffix[i].name && strncmp(suffix[i].name,s,suffix[i].n);i++); | |
288 | return suffix[i].n; | |
289 | } | |
290 | ||
291 | int man_item_compare(ManItem ** a,ManItem ** b) | |
292 | { | |
293 | return (strcmp((*a)->get_display_name(buffer1),(*b)->get_display_name(buffer2))); | |
294 | } | |
295 | ||
296 | /* | |
297 | int ItemMatch(char * name) | |
298 | { | |
299 | int i; | |
300 | for (i=0;i<item_list_count && strcmp(name,item_list[i]->display_name)>0 ;i++); | |
301 | return (i >= item_list_count)? i-1:i; | |
302 | } | |
303 | */ | |
304 | ||
305 |
0 | /********************** modified from t2.c *******************/ | |
1 | /********************* kman.h ********************************/ | |
2 | #include "list.h" | |
3 | ||
4 | #ifndef _KMAN_H | |
5 | #define _KMAN_H | |
6 | ||
7 | #define MAX_MAN_SECTION 15 | |
8 | #define BUFFER_SIZE 200 | |
9 | ||
10 | class ManPath; | |
11 | class ManItem; | |
12 | ||
13 | class ManPath | |
14 | { | |
15 | private: | |
16 | char * path_name; | |
17 | List * section[MAX_MAN_SECTION]; //1:2:3:4:5:6:7:8:9:tcl:n:l:p:o | |
18 | private: | |
19 | LoadManSubPath(char *); | |
20 | public: | |
21 | int active; | |
22 | ManPath(char * path_name); | |
23 | ~ManPath(); | |
24 | LoadManPath(char *); | |
25 | const char * GetPath(); | |
26 | int GetSize(int section_ID); | |
27 | int GetItems(int section_ID, ManItem **buffer); | |
28 | ManItem * search_man_item(char * name, char * section); | |
29 | }; | |
30 | ||
31 | class ManItem | |
32 | { | |
33 | public: | |
34 | ManItem(ManPath *, char * file_name); | |
35 | ~ManItem(); | |
36 | char * get_display_name(char * buffer); | |
37 | char * get_section_name(char * buffer); | |
38 | int get_section_ID(); | |
39 | void * get_man_path(); | |
40 | void active_man_page(); | |
41 | private: | |
42 | ManPath * man_path; | |
43 | char * file_name; | |
44 | char * display_name; | |
45 | char * section_name; | |
46 | int section_ID; | |
47 | }; | |
48 | ||
49 | //int ItemMatch(char * name); | |
50 | int man_item_compare(ManItem **,ManItem **); | |
51 | void attach (char *dest, const char *dirname, const char *name); | |
52 | ||
53 | #endif /* _KMAN_H */ | |
54 | ||
55 |
0 | struct data_pair | |
1 | { | |
2 | char * name; | |
3 | int n; | |
4 | }; | |
5 | ||
6 | #define MAX_MAN_SECTION 15 | |
7 | ||
8 | data_pair sections[]= | |
9 | { | |
10 | {"1",1}, | |
11 | {"2",1}, | |
12 | {"3",1}, | |
13 | {"4",1}, | |
14 | {"5",1}, | |
15 | {"6",1}, | |
16 | {"7",1}, | |
17 | {"8",1}, | |
18 | {"l",1}, | |
19 | {"n",1}, | |
20 | {"9",1}, | |
21 | {"tcl",3}, | |
22 | {"p",1}, | |
23 | {"o",1}, | |
24 | {NULL,0} | |
25 | }; | |
26 | ||
27 | data_pair suffix[]= | |
28 | { | |
29 | {".gz",3}, | |
30 | {".bz2",4}, | |
31 | {".z",2}, | |
32 | {".Z",2}, | |
33 | {".F",2}, | |
34 | {".Y",2}, | |
35 | {NULL,0} | |
36 | }; | |
37 |
0 | /********************** modified from t2.c *******************/ | |
1 | /********************* menu.c ********************************/ | |
2 | ||
3 | #include <stdio.h> | |
4 | #include <string.h> | |
5 | #include <strings.h> | |
6 | #include <sys/types.h> | |
7 | #ifdef SYS_DIR | |
8 | #include <sys_dir.h> | |
9 | #else | |
10 | #ifdef NDIR | |
11 | #include <ndir.h> | |
12 | #else | |
13 | #include <dirent.h> | |
14 | #endif | |
15 | #endif | |
16 | ||
17 | #include <sys/stat.h> | |
18 | #include <unistd.h> | |
19 | #include <errno.h> | |
20 | ||
21 | #include <stdlib.h> | |
22 | ||
23 | #include <gtk/gtk.h> | |
24 | ||
25 | #include <libintl.h> | |
26 | ||
27 | #include "mandata.h" | |
28 | #include "util.h" | |
29 | #include "gman.h" | |
30 | #include "list.h" | |
31 | #include "task.h" | |
32 | #include "window2.h" | |
33 | #include "taskfunc.h" | |
34 | ||
35 | static int print_hello(GtkWidget *w, gpointer data); | |
36 | static int test_callback(GtkWidget *w, gpointer data); | |
37 | static int window_resize_callback(GtkWidget *w, GtkAllocation *size, gpointer data); | |
38 | static int section_policy_callback(GtkWidget *w, gpointer data); | |
39 | static int section_select_callback(GtkWidget *w, gpointer data); | |
40 | static int status_bar_callback (GtkWidget *widget, gpointer data); | |
41 | static int search_mode_callback (GtkWidget *widget, gpointer data); | |
42 | static void app_quit(GtkWidget *w, gpointer data); | |
43 | static void select_row_callback(GtkWidget *, gint, gint, GdkEventButton *, gpointer); | |
44 | static void select_row_callback3(GtkWidget *, gint, gint, GdkEventButton *, gpointer); | |
45 | static void entry_activate_callback(GtkWidget *,gpointer); | |
46 | static void entry_changed_callback(GtkWidget *,gpointer); | |
47 | static void window_help_about_callback (GtkWidget *widget, gpointer data); | |
48 | static void entry4_activate_callback(GtkWidget *,gpointer); | |
49 | static void entry4_changed_callback(GtkWidget *,gpointer); | |
50 | static int button_clicked_callback(GtkWidget *,gpointer); | |
51 | ||
52 | #define MAX_PATHS 10 | |
53 | ||
54 | #define MENU_DISPLAY_POSITION 201 | |
55 | #define MENU_NEXT_POSITION 202 | |
56 | ||
57 | #define _(string) gettext(string) | |
58 | ||
59 | static GtkItemFactoryEntry menu_items[] = { | |
60 | {"/_File", NULL, NULL, 0, "<Branch>"}, | |
61 | {"/File/_Quit", "<control>Q", (void (*)(...))app_quit, 0, NULL}, | |
62 | {"/_Sections", NULL, NULL, 0, "<Branch>"}, | |
63 | {"/Sections/tearoff1", NULL, NULL, 0, "<Tearoff>" }, | |
64 | {"/Sections/_All", NULL, (void (*)(...))section_policy_callback, 0, "<RadioItem>"}, | |
65 | {"/Sections/all _But", NULL, (void (*)(...))section_policy_callback, 1, "/Sections/All"}, | |
66 | {"/Sections/_Only", NULL, (void (*)(...))section_policy_callback, 2, "/Sections/All"}, | |
67 | {"/Sections/sep1", NULL, NULL, 0, "<Separator>"}, | |
68 | {"/Sections/_1: User Commands", NULL, (void (*)(...))section_select_callback, 1<<0, "<CheckItem>"}, | |
69 | {"/Sections/_2: System Calls", NULL, (void (*)(...))section_select_callback, 1<<1, "<CheckItem>"}, | |
70 | {"/Sections/_3: Subroutines", NULL, (void (*)(...))section_select_callback, 1<<2, "<CheckItem>"}, | |
71 | {"/Sections/_4: Devices", NULL, (void (*)(...))section_select_callback, 1<<3, "<CheckItem>"}, | |
72 | {"/Sections/_5: File Formats", NULL, (void (*)(...))section_select_callback, 1<<4, "<CheckItem>"}, | |
73 | {"/Sections/_6: Games", NULL, (void (*)(...))section_select_callback, 1<<5, "<CheckItem>"}, | |
74 | {"/Sections/_7: Miscellaneous", NULL, (void (*)(...))section_select_callback, 1<<6, "<CheckItem>"}, | |
75 | {"/Sections/_8: Sys.Administration",NULL, (void (*)(...))section_select_callback, 1<<7, "<CheckItem>"}, | |
76 | {"/Sections/_l: Local", NULL, (void (*)(...))section_select_callback, 1<<8, "<CheckItem>"}, | |
77 | {"/Sections/_n: New", NULL, (void (*)(...))section_select_callback, 1<<9, "<CheckItem>"}, | |
78 | {"/_Options", NULL, NULL, 0, "<Branch>"}, | |
79 | {"/Options/Status bar", NULL, (void (*)(...))status_bar_callback, 0, "<CheckItem>"}, | |
80 | {"/Options/sep1", NULL, NULL, 0, "<Separator>"}, | |
81 | {"/Options/_Index search", NULL, (void (*)(...))search_mode_callback, 0, "<RadioItem>"}, | |
82 | {"/Options/_Key word search", NULL, (void (*)(...))search_mode_callback, 1, "/Options/Index search"}, | |
83 | {"/Options/sep2", NULL, NULL, 0, "<Separator>"}, | |
84 | {"/Options/Man _Paths...", "<control>P", (void (*)(...))edit_paths_callback, 0, NULL}, | |
85 | // {"/Options/Test", NULL, (void (*)(...))test_callback, 0, NULL}, | |
86 | {"/_Help", NULL, NULL, 0, "<LastBranch>"}, | |
87 | {"/_Help/About", NULL, GTK_SIGNAL_FUNC(window_help_about_callback),0,NULL} | |
88 | }; | |
89 | ||
90 | /********************* init_main_window *************************/ | |
91 | ||
92 | GtkWidget * clist; | |
93 | GtkWidget * entry; | |
94 | GtkWidget * clist3; | |
95 | GtkWidget * window; //main window | |
96 | GtkTooltips * tooltips; | |
97 | ||
98 | GtkWidget * section_buttons[MAX_MAN_SECTION]; | |
99 | GtkWidget * section_select[3]; | |
100 | GtkWidget * searching_mode_buttons[2]; | |
101 | GtkWidget * status_bar_button; | |
102 | ||
103 | int signal_select_row; //used by select_row_callback() to decide whether to active man pages | |
104 | int signal_entry_change; //used by entry_changed_callback() to decide whether to refresh list | |
105 | int signal_menu_change; //used by menu_item callback to decide whether to take action or not | |
106 | Dictionary * man_paths; | |
107 | char * *man_items_buffer; | |
108 | int man_items_count; | |
109 | int clist_selected_row; | |
110 | List * man_paths_to_be_load; | |
111 | char * keyword; | |
112 | ||
113 | void updata_menu_buttons(int); | |
114 | ||
115 | void get_main_menu(GtkWidget *window, GtkWidget ** menubar) { | |
116 | int nmenu_items = sizeof(menu_items) / sizeof(menu_items[0]); | |
117 | GtkItemFactory *item_factory; | |
118 | GtkAccelGroup *accel_group; | |
119 | ||
120 | accel_group = gtk_accel_group_new(); | |
121 | ||
122 | /* This function initializes the item factory. | |
123 | Param 1: The type of menu - can be GTK_TYPE_MENU_BAR, GTK_TYPE_MENU, | |
124 | or GTK_TYPE_OPTION_MENU. | |
125 | Param 2: The path of the menu. | |
126 | Param 3: A pointer to a gtk_accel_group. The item factory sets up | |
127 | the accelerator table while generating menus. | |
128 | */ | |
129 | ||
130 | item_factory = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<main>", | |
131 | accel_group); | |
132 | ||
133 | /* This function generates the menu items. Pass the item factory, | |
134 | the number of items in the array, the array itself, and any | |
135 | callback data for the the menu items. */ | |
136 | gtk_item_factory_create_items(item_factory, nmenu_items, menu_items, NULL); | |
137 | ||
138 | /* Attach the new accelerator group to the window. */ | |
139 | gtk_accel_group_attach (accel_group, GTK_OBJECT (window)); | |
140 | ||
141 | if (menubar) | |
142 | /* Finally, return the actual menu bar created by the item factory. */ | |
143 | *menubar = gtk_item_factory_get_widget(item_factory, "<main>"); | |
144 | section_select[0] = gtk_item_factory_get_widget(item_factory, "/Sections/All"); | |
145 | section_select[1] = gtk_item_factory_get_widget(item_factory, "/Sections/all But"); | |
146 | section_select[2] = gtk_item_factory_get_widget(item_factory, "/Sections/Only"); | |
147 | section_buttons[0] = gtk_item_factory_get_widget(item_factory, "/Sections/1: User Commands"); | |
148 | section_buttons[1] = gtk_item_factory_get_widget(item_factory, "/Sections/2: System Calls"); | |
149 | section_buttons[2] = gtk_item_factory_get_widget(item_factory, "/Sections/3: Subroutines"); | |
150 | section_buttons[3] = gtk_item_factory_get_widget(item_factory, "/Sections/4: Devices"); | |
151 | section_buttons[4] = gtk_item_factory_get_widget(item_factory, "/Sections/5: File Formats"); | |
152 | section_buttons[5] = gtk_item_factory_get_widget(item_factory, "/Sections/6: Games"); | |
153 | section_buttons[6] = gtk_item_factory_get_widget(item_factory, "/Sections/7: Miscellaneous"); | |
154 | section_buttons[7] = gtk_item_factory_get_widget(item_factory, "/Sections/8: Sys.Administration"); | |
155 | section_buttons[8] = gtk_item_factory_get_widget(item_factory, "/Sections/l: Local"); | |
156 | section_buttons[9] = gtk_item_factory_get_widget(item_factory, "/Sections/n: New"); | |
157 | searching_mode_buttons[0] = gtk_item_factory_get_widget(item_factory, "/Options/Index search"); | |
158 | searching_mode_buttons[1] = gtk_item_factory_get_widget(item_factory, "/Options/Key word search"); | |
159 | status_bar_button = gtk_item_factory_get_widget(item_factory, "/Options/Status bar"); | |
160 | // gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(section_buttons[4]),1); | |
161 | updata_menu_buttons(0); | |
162 | } | |
163 | ||
164 | /*flag = 0 means not to invoke call backs when changing the states of buttons.*/ | |
165 | void updata_menu_buttons(int flag) | |
166 | { | |
167 | int i,j,k,k2; | |
168 | k = (int)context->get_value("display_section_policy"); | |
169 | if(k>0 && k<=2) | |
170 | if(!((GtkCheckMenuItem*)(section_select[k]))->active){ | |
171 | if(!flag) signal_menu_change++; | |
172 | gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(section_select[k]),1); | |
173 | } | |
174 | k = (int)context->get_value("display_section"); | |
175 | for (i = 0;i<10;i++) | |
176 | if(!(k&(1<<i)) != !(((GtkCheckMenuItem*)(section_buttons[i]))->active)) { | |
177 | if(!flag) signal_menu_change++; | |
178 | gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(section_buttons[i]),k&(1<<i)); | |
179 | } | |
180 | k = (int)context->get_value("searching_mode"); | |
181 | if(k>0 && k<=1) | |
182 | if(!(((GtkCheckMenuItem*)(searching_mode_buttons[k]))->active)) { | |
183 | if(!flag) signal_menu_change++; | |
184 | gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(searching_mode_buttons[k]),1); | |
185 | } | |
186 | k2 = (int)context->get_value("show_status_bar"); | |
187 | i = k2&(1<<k); | |
188 | j = (((GtkCheckMenuItem*)(status_bar_button))->active); | |
189 | if((i&&!j) || (!i&&j)) { | |
190 | if(!flag) signal_menu_change++; | |
191 | gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(status_bar_button),i); | |
192 | } | |
193 | gtk_widget_hide(status_bar_button); | |
194 | } | |
195 | ||
196 | static GtkWidget *index_search_vbox; | |
197 | static GtkWidget *keyword_search_vbox; | |
198 | static GtkWidget *hbox4; | |
199 | static GtkWidget *hbox_status; | |
200 | static GtkWidget *entry4; | |
201 | GtkWidget *search_button; | |
202 | GtkWidget *stop_button; | |
203 | static GtkWidget *statusbar1; | |
204 | static GtkWidget *statusbar2; | |
205 | ||
206 | static void updata_widget_show(int flag) | |
207 | { | |
208 | int k,k2; | |
209 | ||
210 | k = (int)context->get_value("searching_mode"); | |
211 | k2 = (int)context->get_value("show_status_bar"); | |
212 | ||
213 | if(k2&(1<<k)) | |
214 | gtk_widget_show(hbox_status); | |
215 | else | |
216 | gtk_widget_hide(hbox_status); | |
217 | gtk_widget_hide(!k?keyword_search_vbox:index_search_vbox); | |
218 | gtk_widget_show(k?keyword_search_vbox:index_search_vbox); | |
219 | if(k2 & (1<<k)) gtk_widget_show (hbox_status); | |
220 | } | |
221 | ||
222 | ||
223 | void init_main_window(GtkWidget * window) | |
224 | { | |
225 | GtkWidget * main_vbox; | |
226 | GtkWidget * menubar; | |
227 | GtkWidget * swindow; | |
228 | GtkWidget * swindow2; | |
229 | GtkWidget * focus; | |
230 | ||
231 | int k,k2; | |
232 | ||
233 | ::window = window; | |
234 | gchar *titles[2] = { "Name", "Section" }; | |
235 | gchar *titles2[3] = { "Name", "Section", "Description"}; | |
236 | signal_select_row = 0; | |
237 | signal_entry_change = 0; | |
238 | ||
239 | tooltips = gtk_tooltips_new(); | |
240 | ||
241 | gtk_signal_connect(GTK_OBJECT(window), "destroy", | |
242 | GTK_SIGNAL_FUNC(app_quit), | |
243 | 0); | |
244 | ||
245 | gtk_window_set_title(GTK_WINDOW(window), "G-man"); | |
246 | gtk_window_set_policy( GTK_WINDOW( window ), FALSE, TRUE, FALSE ); | |
247 | gtk_window_set_default_size(GTK_WINDOW(window), | |
248 | (int)context->get_value("h_size"), | |
249 | (int)context->get_value("v_size")); | |
250 | ||
251 | gtk_widget_set_usize(GTK_WIDGET(window),200,150); | |
252 | main_vbox = gtk_vbox_new(FALSE, 1); | |
253 | gtk_container_border_width(GTK_CONTAINER(main_vbox), 1); | |
254 | gtk_container_add(GTK_CONTAINER(window), main_vbox); | |
255 | gtk_widget_show(main_vbox); | |
256 | ||
257 | get_main_menu(window, &menubar); | |
258 | gtk_box_pack_start(GTK_BOX(main_vbox), menubar, FALSE, TRUE, 0); | |
259 | gtk_widget_show(menubar); | |
260 | ||
261 | gtk_signal_connect(GTK_OBJECT(window),"size_allocate",GTK_SIGNAL_FUNC(window_resize_callback),NULL); | |
262 | ||
263 | //keyword_search_vbox | |
264 | keyword_search_vbox = gtk_vbox_new(FALSE,1); | |
265 | gtk_box_pack_start(GTK_BOX(main_vbox), keyword_search_vbox, TRUE, TRUE, 0); | |
266 | ||
267 | hbox4 = gtk_hbox_new (FALSE, 1); | |
268 | gtk_object_set_data (GTK_OBJECT (window), "hbox4", hbox4); | |
269 | gtk_box_pack_start (GTK_BOX (keyword_search_vbox), hbox4, FALSE, TRUE, 0); | |
270 | gtk_widget_show (hbox4); | |
271 | ||
272 | stop_button = gtk_button_new_with_label ("Stop"); | |
273 | gtk_object_set_data (GTK_OBJECT (window), "stop_button", stop_button); | |
274 | gtk_widget_set_sensitive(stop_button,0); | |
275 | gtk_signal_connect (GTK_OBJECT(stop_button),"clicked",(GtkSignalFunc)button_clicked_callback,(void*)1); | |
276 | gtk_widget_show (stop_button); | |
277 | gtk_box_pack_start (GTK_BOX (hbox4), stop_button, FALSE, TRUE, 0); | |
278 | gtk_widget_set_usize (stop_button, 40, -2); | |
279 | ||
280 | entry4 = gtk_entry_new (); | |
281 | gtk_object_set_data (GTK_OBJECT (window), "entry4", entry4); | |
282 | gtk_widget_show (entry4); | |
283 | gtk_tooltips_set_tip (tooltips, entry4, "Key word search", NULL); | |
284 | gtk_box_pack_start (GTK_BOX (hbox4), entry4, TRUE, TRUE, 0); | |
285 | gtk_signal_connect(GTK_OBJECT(entry4), "activate", | |
286 | GTK_SIGNAL_FUNC(entry4_activate_callback),NULL); | |
287 | gtk_signal_connect(GTK_OBJECT(entry4), "changed", | |
288 | GTK_SIGNAL_FUNC(entry4_changed_callback),NULL); | |
289 | ||
290 | search_button = gtk_button_new_with_label ("Search"); | |
291 | gtk_object_set_data (GTK_OBJECT (window), "search_button", search_button); | |
292 | gtk_widget_set_sensitive(search_button,0); | |
293 | gtk_signal_connect (GTK_OBJECT(stop_button),"clicked",(GtkSignalFunc)button_clicked_callback,(void*)2); | |
294 | gtk_widget_show (search_button); | |
295 | gtk_box_pack_start (GTK_BOX (hbox4), search_button, FALSE, TRUE, 0); | |
296 | gtk_widget_set_usize (search_button, 60, -2); | |
297 | ||
298 | ||
299 | clist3 = gtk_clist_new_with_titles( 3, titles2); | |
300 | swindow2 = gtk_scrolled_window_new (NULL, NULL); | |
301 | gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swindow2), | |
302 | GTK_POLICY_AUTOMATIC, | |
303 | GTK_POLICY_AUTOMATIC); | |
304 | ||
305 | ||
306 | gtk_clist_set_column_width(GTK_CLIST(clist3),0,100); | |
307 | gtk_clist_set_selection_mode(GTK_CLIST(clist3),GTK_SELECTION_SINGLE); | |
308 | gtk_clist_column_titles_passive(GTK_CLIST(clist3)); | |
309 | gtk_clist_set_column_auto_resize (GTK_CLIST(clist3),2,1); | |
310 | ||
311 | gtk_container_add (GTK_CONTAINER (swindow2), clist3); | |
312 | gtk_box_pack_start (GTK_BOX (keyword_search_vbox), swindow2, TRUE, TRUE, 0); | |
313 | gtk_widget_show_all(GTK_WIDGET(swindow2)); | |
314 | ||
315 | gtk_signal_connect(GTK_OBJECT(clist3),"select_row", | |
316 | GTK_SIGNAL_FUNC(select_row_callback3),NULL); | |
317 | ||
318 | //index_search_vbox | |
319 | index_search_vbox = gtk_vbox_new(FALSE,1); | |
320 | gtk_box_pack_start(GTK_BOX(main_vbox), index_search_vbox, TRUE, TRUE, 0); | |
321 | entry = gtk_entry_new_with_max_length (50); | |
322 | clist = gtk_clist_new_with_titles( 2, titles); | |
323 | gtk_signal_connect(GTK_OBJECT(entry), "activate", | |
324 | GTK_SIGNAL_FUNC(entry_activate_callback), | |
325 | (gpointer)clist); | |
326 | gtk_signal_connect(GTK_OBJECT(entry), "changed", | |
327 | GTK_SIGNAL_FUNC(entry_changed_callback), | |
328 | (gpointer)clist); | |
329 | gtk_box_pack_start (GTK_BOX (index_search_vbox), entry, FALSE, TRUE, 0); | |
330 | gtk_tooltips_set_tip (tooltips, entry, "index search", NULL); | |
331 | gtk_widget_show(entry); | |
332 | ||
333 | swindow = gtk_scrolled_window_new (NULL, NULL); | |
334 | gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swindow), | |
335 | GTK_POLICY_AUTOMATIC, | |
336 | GTK_POLICY_AUTOMATIC); | |
337 | ||
338 | ||
339 | gtk_clist_set_column_width(GTK_CLIST(clist),0,200); | |
340 | gtk_clist_set_selection_mode(GTK_CLIST(clist),GTK_SELECTION_SINGLE); | |
341 | gtk_clist_column_titles_passive(GTK_CLIST(clist)); | |
342 | gtk_container_add (GTK_CONTAINER (swindow), clist); | |
343 | gtk_box_pack_start (GTK_BOX (index_search_vbox), swindow, TRUE, TRUE, 0); | |
344 | ||
345 | gtk_signal_connect(GTK_OBJECT(clist),"select_row", | |
346 | GTK_SIGNAL_FUNC(select_row_callback),NULL); | |
347 | ||
348 | focus = entry; | |
349 | gtk_widget_grab_focus (focus); | |
350 | gtk_widget_show_all (swindow); | |
351 | ||
352 | hbox_status = gtk_hbox_new (FALSE, 0); | |
353 | gtk_object_set_data (GTK_OBJECT (window), "hbox_status", hbox_status); | |
354 | gtk_box_pack_start (GTK_BOX (main_vbox), hbox_status, FALSE, TRUE, 0); | |
355 | ||
356 | updata_widget_show(0); | |
357 | ||
358 | statusbar1 = gtk_statusbar_new (); | |
359 | gtk_object_set_data (GTK_OBJECT (window), "statusbar1", statusbar1); | |
360 | gtk_widget_show (statusbar1); | |
361 | gtk_box_pack_start (GTK_BOX (hbox_status), statusbar1, TRUE, TRUE, 0); | |
362 | ||
363 | statusbar2 = gtk_statusbar_new (); | |
364 | gtk_object_set_data (GTK_OBJECT (window), "statusbar2", statusbar2); | |
365 | gtk_widget_show (statusbar2); | |
366 | gtk_box_pack_start (GTK_BOX (hbox_status), statusbar2, FALSE, TRUE, 0); | |
367 | } | |
368 | ||
369 | ||
370 | /******************* tools functions ******************/ | |
371 | int search_array_for_text(char ** array, int count, char * text) | |
372 | { | |
373 | int i; | |
374 | for (i=0;i<count && strcmp(text,array[i])>0 ;i++); | |
375 | return (i >= count)? i-1:i; | |
376 | } | |
377 | ||
378 | /******************* call backs ***********************/ | |
379 | void select_row_callback(GtkWidget *widget, | |
380 | gint row, | |
381 | gint column, | |
382 | GdkEventButton *event, | |
383 | gpointer data) | |
384 | { | |
385 | ManItem * item; | |
386 | if(signal_select_row>0) {signal_select_row--;return;} | |
387 | item = (ManItem*) gtk_clist_get_row_data(GTK_CLIST(widget),row); | |
388 | item->active_man_page(); | |
389 | signal_entry_change++; | |
390 | gtk_entry_set_text(GTK_ENTRY(entry),man_items_buffer[row]); | |
391 | } | |
392 | void select_row_callback3(GtkWidget *widget, | |
393 | gint row, | |
394 | gint column, | |
395 | GdkEventButton *event, | |
396 | gpointer data) | |
397 | { | |
398 | ManItem * item; | |
399 | if(signal_select_row>0) {signal_select_row--;return;} | |
400 | item = (ManItem*) gtk_clist_get_row_data(GTK_CLIST(widget),row); | |
401 | if(item) item->active_man_page(); | |
402 | } | |
403 | void entry_activate_callback(GtkWidget * w,gpointer data) | |
404 | { | |
405 | int i; | |
406 | GtkWidget * clist = (GtkWidget *)data; | |
407 | i = search_array_for_text(man_items_buffer, | |
408 | man_items_count, | |
409 | gtk_entry_get_text(GTK_ENTRY(w))); | |
410 | if (i == -1) return; | |
411 | gtk_clist_moveto(GTK_CLIST(clist),i,0,0.1,0.0); | |
412 | GTK_CLIST(clist)->focus_row = i; | |
413 | gtk_clist_select_row(GTK_CLIST(clist),i,0); | |
414 | } | |
415 | ||
416 | void entry_changed_callback(GtkWidget * w,gpointer data) | |
417 | { | |
418 | int i; | |
419 | GtkWidget * clist = (GtkWidget *)data; | |
420 | if(signal_entry_change>0) {signal_entry_change--;return;} | |
421 | i = search_array_for_text(man_items_buffer, | |
422 | man_items_count, | |
423 | gtk_entry_get_text(GTK_ENTRY(w))); | |
424 | if (i == -1) return; | |
425 | signal_select_row++; | |
426 | gtk_clist_moveto(GTK_CLIST(clist),i,0,0.1,0.0); | |
427 | GTK_CLIST(clist)->focus_row = i; | |
428 | gtk_clist_select_row(GTK_CLIST(clist),i,0); | |
429 | } | |
430 | ||
431 | static int print_hello(GtkWidget *w, gpointer data) { | |
432 | if(signal_menu_change>0) {signal_menu_change--;return 1;} | |
433 | g_message("Hello, World! %x\n",data); | |
434 | return 0; | |
435 | } | |
436 | ||
437 | static int test_callback(GtkWidget *w, gpointer data) { | |
438 | int i,j; | |
439 | if(signal_menu_change>0) {signal_menu_change--;return 1;} | |
440 | j = man_paths->get_size(); | |
441 | for(i = 0;i<j;i++) | |
442 | delete ((ManPath*)(man_paths->get_value(i))); | |
443 | delete (man_paths); | |
444 | init_man_data(); | |
445 | return 0; | |
446 | } | |
447 | ||
448 | static int section_policy_callback(GtkWidget *w, gpointer data) { | |
449 | // static int signal; | |
450 | int k,k2; | |
451 | k2 = (int) data; | |
452 | if(!((GtkCheckMenuItem*)(section_select[k2]))->active) return 1; | |
453 | // g_message("Hello, World! %x\n signal = %d",data,signal_menu_change); | |
454 | if(signal_menu_change>0) {signal_menu_change--;return 1;} | |
455 | //if(!signal) {signal++;return 1;} | |
456 | //signal--; | |
457 | k = (int) context->get_value("display_section_policy"); | |
458 | if(k == k2) return 1; | |
459 | pthread_mutex_lock(&context_lock); | |
460 | context->set_value("display_section_policy","int",(void*)k2); | |
461 | pthread_mutex_unlock(&context_lock); | |
462 | task_set_active(task_extract_man_data); | |
463 | task_set_active(task_add_data_to_clist); | |
464 | } | |
465 | ||
466 | static int section_select_callback(GtkWidget *w, gpointer data) { | |
467 | int var; | |
468 | if(signal_menu_change>0) {signal_menu_change--;return 1;} | |
469 | ||
470 | pthread_mutex_lock(&context_lock); | |
471 | var = (int)context->get_value("display_section"); | |
472 | var ^= (int)data; | |
473 | context->set_value("display_section","int",(void*)var); | |
474 | if (context->get_value("display_section_policy")) { | |
475 | task_set_active(task_extract_man_data); | |
476 | task_set_active(task_add_data_to_clist); | |
477 | } | |
478 | pthread_mutex_unlock(&context_lock); | |
479 | // g_message("Hello, World! %x\n",data); | |
480 | } | |
481 | ||
482 | static void app_quit(GtkWidget *w, gpointer data) { | |
483 | // g_message("Bye, World! %x\n",data); | |
484 | char buffer[1024],*p; | |
485 | FILE * fd; | |
486 | int i,j; | |
487 | p = buffer; | |
488 | j = man_paths->get_size(); | |
489 | for (i = 0;i<j;i++) { | |
490 | sprintf(p,i?":%s":"%s",man_paths->get_name(i)); | |
491 | for(;*p;p++); | |
492 | } | |
493 | context->set_value("man_paths","char*",my_strdup(buffer)); | |
494 | attach(buffer,getenv("HOME"),".gman"); | |
495 | if((fd = fopen(buffer,"w"))) { | |
496 | context->save(fd,"automatically made by G-man"); | |
497 | fclose(fd); | |
498 | } | |
499 | // context->save(stdout,"automatically made by G-man"); | |
500 | ||
501 | gtk_exit((int)data); | |
502 | } | |
503 | ||
504 | static int window_resize_callback(GtkWidget *w, GtkAllocation * size, gpointer data) | |
505 | { | |
506 | /* | |
507 | g_message("x = %d, y = %d, width = %d, height = %d, data = %x\n", | |
508 | size->x,size->y,size->width,size->height,data); */ | |
509 | context->set_value("h_size","int",(void*)size->width); | |
510 | context->set_value("v_size","int",(void*)size->height); | |
511 | return 0; | |
512 | } | |
513 | ||
514 | static void window_help_about_callback (GtkWidget *widget, gpointer data) | |
515 | { | |
516 | const gchar *authors[] = {"Xinkai Wang <aakwxk@hotmail.com>", NULL }; | |
517 | static GtkWidget *about_window = NULL; | |
518 | ||
519 | if (!about_window) | |
520 | { | |
521 | ||
522 | GtkWidget *button; | |
523 | GdkFont *font; | |
524 | ||
525 | about_window = gtk_dialog_new (); | |
526 | gtk_window_set_position (GTK_WINDOW (about_window), GTK_WIN_POS_MOUSE); | |
527 | gtk_window_set_title (GTK_WINDOW (about_window), _("About gman")); | |
528 | ||
529 | gtk_signal_connect (GTK_OBJECT (about_window), "delete_event", | |
530 | GTK_SIGNAL_FUNC (gtk_false), NULL); | |
531 | gtk_signal_connect (GTK_OBJECT (about_window), "destroy", | |
532 | (GtkSignalFunc) gtk_widget_destroyed, | |
533 | &about_window); | |
534 | ||
535 | button = gtk_button_new_with_label (_("Close")); | |
536 | gtk_widget_show (button); | |
537 | gtk_box_pack_start (GTK_BOX (GTK_DIALOG (about_window)->action_area), | |
538 | button, TRUE, TRUE, 0); | |
539 | gtk_signal_connect_object (GTK_OBJECT (button), "clicked", | |
540 | (GtkSignalFunc) gtk_widget_destroy, | |
541 | GTK_OBJECT (about_window)); | |
542 | ||
543 | gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (about_window)->vbox), 5); | |
544 | ||
545 | /* TODO: we need a logo ;) */ | |
546 | ||
547 | gtk_box_pack_start (GTK_BOX (GTK_DIALOG (about_window)->vbox), | |
548 | gtk_label_new ("Gman - version " VERSION), | |
549 | FALSE, FALSE, 5); | |
550 | ||
551 | gtk_box_pack_start (GTK_BOX (GTK_DIALOG (about_window)->vbox), | |
552 | gtk_label_new ("Copyright (C) 1999 Xinkai Wang"), | |
553 | FALSE, FALSE, 5); | |
554 | ||
555 | gtk_box_pack_start (GTK_BOX (GTK_DIALOG (about_window)->vbox), | |
556 | gtk_label_new ("Comments and suggestions are extremely welcome!"), | |
557 | FALSE, FALSE, 5); | |
558 | ||
559 | gtk_box_pack_start (GTK_BOX (GTK_DIALOG (about_window)->vbox), | |
560 | gtk_label_new ("Web: http://homex.s-one.net.sg/user/xkwang/gman"), | |
561 | FALSE, FALSE, 5); | |
562 | ||
563 | if (!GTK_WIDGET_VISIBLE (about_window)) | |
564 | gtk_widget_show_all (about_window); | |
565 | else | |
566 | gtk_widget_hide (about_window); | |
567 | ||
568 | } | |
569 | } | |
570 | ||
571 | static status_bar_callback (GtkWidget *widget, gpointer data) | |
572 | { | |
573 | int k,k2; | |
574 | if(signal_menu_change>0) {signal_menu_change--;return 1;} | |
575 | k2 = (int) context->get_value("show_status_bar"); | |
576 | k = (int) context->get_value("searching_mode"); | |
577 | if(((GtkCheckMenuItem*)(status_bar_button))->active) k2 = k2 | (1<<k); | |
578 | else k2 = k2 & ~(1<<k); | |
579 | pthread_mutex_lock(&context_lock); | |
580 | context->set_value("show_status_bar","int",(void*)k2); | |
581 | pthread_mutex_unlock(&context_lock); | |
582 | updata_widget_show(0); | |
583 | return 0; | |
584 | } | |
585 | ||
586 | static int search_mode_callback (GtkWidget *widget, gpointer data) | |
587 | { | |
588 | int k,k2; | |
589 | k2 = (int) data; | |
590 | if(!((GtkCheckMenuItem*)(searching_mode_buttons[k2]))->active) return 1; | |
591 | if(signal_menu_change>0) {signal_menu_change--;return 1;} | |
592 | //if(!signal) {signal++;return 1;} | |
593 | //signal--; | |
594 | k = (int) context->get_value("searching_mode"); | |
595 | if(k == k2) return 1; | |
596 | pthread_mutex_lock(&context_lock); | |
597 | context->set_value("searching_mode","int",(void*)k2); | |
598 | pthread_mutex_unlock(&context_lock); | |
599 | updata_widget_show(0); | |
600 | updata_menu_buttons(0); | |
601 | return 0; | |
602 | } | |
603 | ||
604 | static void entry4_activate_callback(GtkWidget *w,gpointer data) | |
605 | { | |
606 | keyword = gtk_entry_get_text(GTK_ENTRY(entry4)); | |
607 | task_set_active(task_key_word_search); | |
608 | } | |
609 | ||
610 | static void entry4_changed_callback(GtkWidget *w,gpointer data) | |
611 | { | |
612 | char * tmp; | |
613 | tmp = gtk_entry_get_text(GTK_ENTRY(entry4)); | |
614 | gtk_widget_set_sensitive(search_button,strlen(tmp) >= 3); | |
615 | ||
616 | } | |
617 | ||
618 | static int button_clicked_callback(GtkWidget * w,gpointer data) | |
619 | { | |
620 | int i = (int) data; | |
621 | switch (i) { | |
622 | case 1: task_set_stop(task_key_word_search);break; | |
623 | case 2: task_set_active(task_key_word_search);break; | |
624 | } | |
625 | } |
0 | /********************* menu.h *********************/ | |
1 | ||
2 | #ifndef _MENU_H | |
3 | #define _MENU_H | |
4 | #include "task.h" | |
5 | #include <gtk/gtk.h> | |
6 | ||
7 | void init_main_window(GtkWidget *); | |
8 | ||
9 | extern GtkWidget * clist; | |
10 | extern GtkWidget * clist3; | |
11 | ||
12 | extern List * man_paths_to_be_load; | |
13 | extern GtkTooltips * tooltips; | |
14 | extern Dictionary * man_paths; | |
15 | extern char * *man_items_buffer; | |
16 | extern int man_items_count; | |
17 | extern char *keyword; | |
18 | ||
19 | extern GtkWidget *search_button; | |
20 | extern GtkWidget *stop_button; | |
21 | ||
22 | #endif | |
23 |
0 | /* An alternative to qsort, with an identical interface. | |
1 | This file is part of the GNU C Library. | |
2 | Copyright (C) 1992, 1995, 1996, 1997 Free Software Foundation, Inc. | |
3 | Written by Mike Haertel, September 1988. | |
4 | ||
5 | The GNU C Library is free software; you can redistribute it and/or | |
6 | modify it under the terms of the GNU Library General Public License as | |
7 | published by the Free Software Foundation; either version 2 of the | |
8 | License, or (at your option) any later version. | |
9 | ||
10 | The GNU C Library is distributed in the hope that it will be useful, | |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | Library General Public License for more details. | |
14 | ||
15 | You should have received a copy of the GNU Library General Public | |
16 | License along with the GNU C Library; see the file COPYING.LIB. If not, | |
17 | write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
18 | Boston, MA 02111-1307, USA. */ | |
19 | ||
20 | #include <stdlib.h> | |
21 | #include <string.h> | |
22 | #include <memcopy.h> | |
23 | #include <errno.h> | |
24 | ||
25 | static void msort_with_tmp __P ((void *b, size_t n, size_t s, | |
26 | __compar_fn_t cmp, char *t)); | |
27 | ||
28 | static void | |
29 | msort_with_tmp (b, n, s, cmp, t) | |
30 | void *b; | |
31 | size_t n; | |
32 | size_t s; | |
33 | __compar_fn_t cmp; | |
34 | char *t; | |
35 | { | |
36 | char *tmp; | |
37 | char *b1, *b2; | |
38 | size_t n1, n2; | |
39 | ||
40 | if (n <= 1) | |
41 | return; | |
42 | ||
43 | n1 = n / 2; | |
44 | n2 = n - n1; | |
45 | b1 = b; | |
46 | b2 = (char *) b + (n1 * s); | |
47 | ||
48 | msort_with_tmp (b1, n1, s, cmp, t); | |
49 | msort_with_tmp (b2, n2, s, cmp, t); | |
50 | ||
51 | tmp = t; | |
52 | ||
53 | if (s == OPSIZ && (b1 - (char *) 0) % OPSIZ == 0) | |
54 | /* We are operating on aligned words. Use direct word stores. */ | |
55 | while (n1 > 0 && n2 > 0) | |
56 | { | |
57 | if ((*cmp) (b1, b2) <= 0) | |
58 | { | |
59 | --n1; | |
60 | *((op_t *) tmp)++ = *((op_t *) b1)++; | |
61 | } | |
62 | else | |
63 | { | |
64 | --n2; | |
65 | *((op_t *) tmp)++ = *((op_t *) b2)++; | |
66 | } | |
67 | } | |
68 | else | |
69 | while (n1 > 0 && n2 > 0) | |
70 | { | |
71 | if ((*cmp) (b1, b2) <= 0) | |
72 | { | |
73 | tmp = (char *) __mempcpy (tmp, b1, s); | |
74 | b1 += s; | |
75 | --n1; | |
76 | } | |
77 | else | |
78 | { | |
79 | tmp = (char *) __mempcpy (tmp, b2, s); | |
80 | b2 += s; | |
81 | --n2; | |
82 | } | |
83 | } | |
84 | if (n1 > 0) | |
85 | memcpy (tmp, b1, n1 * s); | |
86 | memcpy (b, t, (n - n2) * s); | |
87 | } | |
88 | ||
89 | void | |
90 | qsort (b, n, s, cmp) | |
91 | void *b; | |
92 | size_t n; | |
93 | size_t s; | |
94 | __compar_fn_t cmp; | |
95 | { | |
96 | const size_t size = n * s; | |
97 | ||
98 | if (size < 1024) | |
99 | /* The temporary array is small, so put it on the stack. */ | |
100 | msort_with_tmp (b, n, s, cmp, __alloca (size)); | |
101 | else | |
102 | { | |
103 | /* It's somewhat large, so malloc it. */ | |
104 | int save = errno; | |
105 | char *tmp = malloc (size); | |
106 | if (tmp == NULL) | |
107 | { | |
108 | /* Couldn't get space, so use the slower algorithm | |
109 | that doesn't need a temporary array. */ | |
110 | extern void _quicksort __P ((void *const __base, | |
111 | size_t __nmemb, size_t __size, | |
112 | __compar_fn_t __compar)); | |
113 | _quicksort (b, n, s, cmp); | |
114 | } | |
115 | else | |
116 | { | |
117 | msort_with_tmp (b, n, s, cmp, tmp); | |
118 | free (tmp); | |
119 | } | |
120 | __set_errno (save); | |
121 | } | |
122 | } |
0 | /********************** modified from myfont.c *******************/ | |
1 | /********************* to test the use of XmScrolledList *********/ | |
2 | ||
3 | #include <stdio.h> | |
4 | #include <string.h> | |
5 | #include <sys/types.h> | |
6 | #ifdef SYS_DIR | |
7 | #include <sys_dir.h> | |
8 | #else | |
9 | #ifdef NDIR | |
10 | #include <ndir.h> | |
11 | #else | |
12 | #include <dirent.h> | |
13 | #endif | |
14 | #endif | |
15 | ||
16 | #include <sys/stat.h> | |
17 | #include <unistd.h> | |
18 | #include <errno.h> | |
19 | ||
20 | #include <stdlib.h> | |
21 | ||
22 | #include <X11/Intrinsic.h> | |
23 | #include <X11/IntrinsicP.h> | |
24 | #include <X11/CoreP.h> | |
25 | #include <X11/Shell.h> | |
26 | #include <Xm/XmAll.h> | |
27 | ||
28 | void main(); | |
29 | Widget MyCreateMain(Widget ); | |
30 | Widget SelectedFontSample(Widget ); | |
31 | Widget MyHelpDialog(Widget,int ); | |
32 | ||
33 | Widget slist; | |
34 | Widget command_window; | |
35 | //Widget swindow; | |
36 | static int call_back_signal = 0; | |
37 | ||
38 | void FontSelectedCB(Widget,caddr_t,caddr_t); | |
39 | void CloseCB(Widget,caddr_t,caddr_t); | |
40 | void HelpCB(Widget,int,caddr_t); | |
41 | void QuitCB(Widget,caddr_t,caddr_t); | |
42 | void ListSelectCB(Widget,caddr_t,XmListCallbackStruct *); | |
43 | void ListActionCB(Widget,caddr_t,caddr_t); | |
44 | void CommandWindowInputCB(Widget,caddr_t,caddr_t); | |
45 | void MenuCommandCB(Widget,caddr_t,caddr_t); | |
46 | void ActiveCB(Widget,caddr_t,caddr_t); | |
47 | ||
48 | #define MAX_ARGS 20 | |
49 | ||
50 | #define MENU_DISPLAY_POSITION 201 | |
51 | #define MENU_NEXT_POSITION 202 | |
52 | ||
53 | typedef struct | |
54 | { | |
55 | char *fontpath; | |
56 | }ApplicationData,*ApplicationDataPtr; | |
57 | ||
58 | class ManPath; | |
59 | class SubDir; | |
60 | class ManItem; | |
61 | ||
62 | class ManPath | |
63 | { | |
64 | public: | |
65 | ManPath* next; | |
66 | char * alias; | |
67 | char * man_path; | |
68 | SubDir* sub_dir[11]; | |
69 | public: | |
70 | ManPath(char * path_name); | |
71 | ~ManPath(); | |
72 | LoadManPath(char *); | |
73 | int GetSize(char c); | |
74 | int GetItems(char c, ManItem *buffer[]); | |
75 | }; | |
76 | ||
77 | class SubDir | |
78 | { | |
79 | public: | |
80 | ManPath *man_path; | |
81 | int buffer_length; | |
82 | int count; | |
83 | ManItem **item_list; | |
84 | public: | |
85 | SubDir(ManPath *); | |
86 | ~SubDir(); | |
87 | void AddItem(char* name); | |
88 | int GetSize(); | |
89 | int GetItems(ManItem *buffer[]); | |
90 | }; | |
91 | ||
92 | class ManItem | |
93 | { | |
94 | public: | |
95 | SubDir *sub_dir; | |
96 | char *name; | |
97 | public: | |
98 | ManItem(SubDir *, char* name); | |
99 | ~ManItem(); | |
100 | }; | |
101 | ||
102 | void InitData(); | |
103 | static void attach (char *dest, const char *dirname, const char *name); | |
104 | static int subdir_translate_c_to_n(char c); | |
105 | static int ManItemComp(ManItem ** a,ManItem ** b); | |
106 | static int ItemMatch(char *); | |
107 | static void active_man_page(ManItem *); | |
108 | ||
109 | ManPath * man_paths; | |
110 | ManItem ** item_list; | |
111 | int item_list_length; | |
112 | int item_list_count; | |
113 | ||
114 | ApplicationData AppData; | |
115 | ||
116 | #define XtNfontPath "fontPath" | |
117 | #define XtCFontPath "FontPath" | |
118 | static XtResource resources[] = | |
119 | { | |
120 | { | |
121 | XtNfontPath,XtCFontPath,XmRString,sizeof(String), | |
122 | XtOffset(ApplicationDataPtr,fontpath), | |
123 | //XmRString,"/usr/lib/X11/fonts/misc" | |
124 | XmRString,"/home/wxk/fonts" | |
125 | } | |
126 | }; | |
127 | ||
128 | static XmStringCharSet charset = (XmStringCharSet)XmSTRING_DEFAULT_CHARSET; | |
129 | ||
130 | /********************** main **********************/ | |
131 | void main(int argc,char ** argv) | |
132 | { | |
133 | Widget toplevel; | |
134 | Widget main_window; | |
135 | XtAppContext app_context; | |
136 | ||
137 | toplevel = XtVaAppInitialize(&app_context,"XMdemos",NULL,0, | |
138 | &argc,argv,NULL,XmNallowShellResize,True,NULL); | |
139 | main_window = MyCreateMain(toplevel); | |
140 | XtRealizeWidget(toplevel); | |
141 | ||
142 | XtAppMainLoop(app_context); | |
143 | } | |
144 | ||
145 | /********************* MyCreateMain *************************/ | |
146 | Widget MyCreateMain(Widget parent) | |
147 | { | |
148 | Widget main_window; | |
149 | Widget menu_bar; | |
150 | Widget menu_pane; | |
151 | Widget cascade; | |
152 | Widget frame; | |
153 | Widget form; | |
154 | Widget button; | |
155 | Widget hsb,vsb; | |
156 | ||
157 | Arg args[MAX_ARGS]; | |
158 | register int n; | |
159 | DIR *dirp; | |
160 | #if defined(SYS_DIR)||defined(NDIR) | |
161 | struct direct *item; | |
162 | #else | |
163 | struct dirent *item; | |
164 | #endif | |
165 | ||
166 | char filename[80]; | |
167 | int len; | |
168 | int i,j,k; | |
169 | XmString label_string; | |
170 | XmString stringx[2]; | |
171 | ||
172 | /***************** Init Data *************/ | |
173 | InitData(); | |
174 | ||
175 | printf("piont3.0\n"); | |
176 | /***************** Create MainWindow *************/ | |
177 | n = 0; | |
178 | main_window = XmCreateMainWindow(parent,"main1",args,n); | |
179 | XtManageChild(main_window); | |
180 | ||
181 | /***************** Create MenuBar ***************/ | |
182 | n = 0; | |
183 | menu_bar = XmCreateMenuBar(main_window,"menu_bar",args,n); | |
184 | XtManageChild(menu_bar); | |
185 | XmAddTabGroup(menu_bar); | |
186 | ||
187 | /***************** Create "exit" menu ************/ | |
188 | n = 0; | |
189 | menu_pane = XmCreatePulldownMenu(menu_bar,"menu_pane",args,n); | |
190 | ||
191 | n = 0; | |
192 | button = XmCreatePushButton(menu_pane,"Quit",args,n); | |
193 | XtManageChild(button); | |
194 | XtAddCallback(button,XmNactivateCallback,(void (*)(Widget,void *, void *))QuitCB,(XtPointer)NULL); | |
195 | ||
196 | n = 0; | |
197 | button = XmCreatePushButton(menu_pane,"Display",args,n); | |
198 | XtManageChild(button); | |
199 | XtAddCallback(button,XmNactivateCallback,(void (*)(Widget,void *, void *))MenuCommandCB,(XtPointer)MENU_DISPLAY_POSITION); | |
200 | ||
201 | n = 0; | |
202 | button = XmCreatePushButton(menu_pane,"Next",args,n); | |
203 | XtManageChild(button); | |
204 | XtAddCallback(button,XmNactivateCallback,(void (*)(Widget,void *, void *))MenuCommandCB,(XtPointer)MENU_NEXT_POSITION); | |
205 | ||
206 | printf("piont3.2\n"); | |
207 | n = 0; | |
208 | XtSetArg(args[n],XmNsubMenuId,menu_pane);n++; | |
209 | cascade = XmCreateCascadeButton(menu_bar,"Exit",args,n); | |
210 | XtManageChild(cascade); | |
211 | ||
212 | /***************** Create "help" menu ************/ | |
213 | n = 0; | |
214 | //cascade = XmCreateCascadeButton(menu_bar,"help",args,n); | |
215 | cascade = XmCreateCascadeButtonGadget(menu_bar,"help",args,n); | |
216 | XtManageChild(cascade); | |
217 | XtAddCallback(cascade,XmNactivateCallback,(void (*)(Widget,void *, void *))HelpCB,(XtPointer)1); | |
218 | ||
219 | n = 0; | |
220 | XtSetArg(args[n],XmNmenuHelpWidget,cascade);n++; | |
221 | XtSetValues(menu_bar,args,n); | |
222 | ||
223 | /***************** Create Frame window ********/ | |
224 | n = 0; | |
225 | XtSetArg(args[n],XmNmarginWidth,2);n++; | |
226 | XtSetArg(args[n],XmNmarginHeight,2);n++; | |
227 | XtSetArg(args[n],XmNshadowThickness,1);n++; | |
228 | XtSetArg(args[n],XmNshadowType,XmSHADOW_OUT);n++; | |
229 | frame = XmCreateFrame(main_window,"frame",args,n); | |
230 | XtManageChild(frame); | |
231 | ||
232 | /***************** Create command window ********/ | |
233 | n = 0; | |
234 | form = XmCreateForm(frame,"form",args,n); | |
235 | XtManageChild(form); | |
236 | n = 0; | |
237 | XtSetArg(args[n],XmNtopAttachment,XmATTACH_FORM);n++; | |
238 | XtSetArg(args[n],XmNleftAttachment,XmATTACH_FORM);n++; | |
239 | XtSetArg(args[n],XmNrightAttachment,XmATTACH_FORM);n++; | |
240 | command_window = XmCreateTextField(form,"textfield",args,n); | |
241 | XtManageChild(command_window); | |
242 | ||
243 | /***************** Create Scrolled list ***************/ | |
244 | n = 0; | |
245 | XtSetArg(args[n],XmNtopAttachment,XmATTACH_WIDGET);n++; | |
246 | XtSetArg(args[n],XmNtopWidget,command_window);n++; | |
247 | XtSetArg(args[n],XmNleftAttachment,XmATTACH_FORM);n++; | |
248 | XtSetArg(args[n],XmNrightAttachment,XmATTACH_FORM);n++; | |
249 | XtSetArg(args[n],XmNbottomAttachment,XmATTACH_FORM);n++; | |
250 | XtSetArg(args[n],XmNscrollBarDisplayPolicy,XmAS_NEEDED);n++; | |
251 | XtSetArg(args[n],XmNscrollingPolicy,XmAUTOMATIC);n++; | |
252 | XtSetArg(args[n],XmNvisibleItemCount,30);n++; | |
253 | XtSetArg(args[n],XmNlistMarginWidth,5);n++; | |
254 | XtSetArg(args[n],XmNwidth,400);n++; | |
255 | XtSetArg(args[n],XmNlistSizePolicy,XmCONSTANT);n++; | |
256 | slist = XmCreateScrolledList(form,"slist",args,n); | |
257 | XtManageChild(slist); | |
258 | ||
259 | /**************** Set MainWindow areas and add tab groups ******* | |
260 | XmMainWindowSetAreas(main_window,menu_bar,NULL,NULL,NULL,frame); | |
261 | n = 0; | |
262 | XtSetArg(args[n],XmNhorizontalScrollBar,&hsb);n++; | |
263 | XtSetArg(args[n],XmNverticalScrollBar,&vsb);n++; | |
264 | XtGetValues(swindow,args,n); | |
265 | XmAddTabGroup(slist); | |
266 | printf("hsb = %x, vsb = %x",hsb,vsb); | |
267 | if(hsb) XmAddTabGroup(hsb); | |
268 | if(vsb) XmAddTabGroup(vsb); | |
269 | */ | |
270 | XmAddTabGroup(slist); | |
271 | XmAddTabGroup(command_window); | |
272 | ||
273 | //system("ls /home/wxk/x "); | |
274 | /**************** Create items in the slist **********/ | |
275 | for (i=0;i<item_list_count;i++) | |
276 | { | |
277 | label_string = XmStringCreateLtoR(item_list[i]->name,charset); | |
278 | XmListAddItem(slist,label_string,0); | |
279 | //if (!strcmp(filename,"core")) stringx[0] = label_string; | |
280 | XmStringFree(label_string); | |
281 | } | |
282 | n = 0; | |
283 | //XtSetArg(args[n],XmNselectedItemCount,1);n++; | |
284 | //XtSetArg(args[n],XmNselectedItems,stringx);n++; | |
285 | //XtSetArg(args[n],XmNtopItemPosition,14);n++; | |
286 | XtSetValues(slist,args,n); | |
287 | XtAddCallback(slist,XmNbrowseSelectionCallback,(void (*)(Widget,void *, void *))ListSelectCB,(XtPointer)NULL); | |
288 | XtAddCallback(slist,XmNdefaultActionCallback,(void (*)(Widget,void *, void *))ActiveCB,(XtPointer)NULL); | |
289 | XtAddCallback(command_window,XmNvalueChangedCallback,(void (*)(Widget,void *, void *))CommandWindowInputCB,(XtPointer)NULL); | |
290 | XtAddCallback(command_window,XmNactivateCallback,(void (*)(Widget,void *, void *))ActiveCB,(XtPointer)NULL); | |
291 | printf("piont3.10\n"); | |
292 | return(main_window); | |
293 | } | |
294 | ||
295 | /********************* SelectFontCB ***********************/ | |
296 | Widget SelectedFontSample(Widget widget) | |
297 | { | |
298 | Widget message_box; | |
299 | Widget button; | |
300 | Arg args[MAX_ARGS]; | |
301 | register int n; | |
302 | int i; | |
303 | XtPointer * buffer; | |
304 | char *name = NULL; | |
305 | XFontStruct * font = NULL; | |
306 | XmFontList fontlist = NULL; | |
307 | static char message[BUFSIZ]; | |
308 | XmString name_string = NULL; | |
309 | XmString message_string = NULL; | |
310 | XmString button_string = NULL; | |
311 | ||
312 | /******************* get font name *********************/ | |
313 | printf("piont SelectedFontSample\n"); | |
314 | XtVaGetValues(widget,XmNlabelString,&name_string,NULL); | |
315 | XmStringGetLtoR(name_string,charset,&name); | |
316 | /* | |
317 | for(i=0;i<10;i++) | |
318 | { | |
319 | if(name) font = XLoadQueryFont(XtDisplay(XtParent(widget)),name); | |
320 | if(font == NULL) sprintf(message,"Unable to load font:%s.",name); | |
321 | else | |
322 | { | |
323 | fontlist = XmFontListCreate(font,charset); | |
324 | sprintf(message,"\n This is font %s.\n The quick brown fox jumps over the lazy dog.",name); | |
325 | } | |
326 | printf("font=%x, fontlist=%x\n",font,fontlist); | |
327 | XmFontListFree(fontlist); | |
328 | if(font) XFreeFont(XtDisplay(XtParent(widget)),font); | |
329 | } | |
330 | */ | |
331 | if(name) font = XLoadQueryFont(XtDisplay(XtParent(widget)),name); | |
332 | if(font == NULL) sprintf(message,"Unable to load font:%s.",name); | |
333 | else | |
334 | { | |
335 | fontlist = XmFontListCreate(font,charset); | |
336 | sprintf(message,"\n This is font %s.\n The quick brown fox jumps over the lazy dog.",name); | |
337 | } | |
338 | printf("font=%x, fontlist=%x\n",font,fontlist); | |
339 | buffer = (XtPointer*)XtMalloc(sizeof(XtPointer)*2); | |
340 | printf("buffer=%x, size=%d\n",buffer,sizeof(XtPointer)*2); | |
341 | buffer[0] = (XtPointer)fontlist; | |
342 | buffer[1] = (XtPointer)font; | |
343 | ||
344 | printf("piont SelectedFontSample, name=%x, name_string=%x, font=%x\n",name,name_string,font); | |
345 | message_string = XmStringCreateLtoR(message,charset); | |
346 | for(i=0;i<0;i++) | |
347 | { | |
348 | button_string = XmStringCreateLtoR("Close",charset); | |
349 | printf("button_string=%x\n",button_string); | |
350 | XmStringFree(button_string); | |
351 | } | |
352 | button_string = XmStringCreateLtoR("Close",charset); | |
353 | ||
354 | n = 0; | |
355 | if (fontlist) | |
356 | { | |
357 | XtSetArg(args[n],XmNlabelFontList,fontlist);n++; | |
358 | } | |
359 | XtSetArg(args[n],XmNdialogTitle,name_string);n++; | |
360 | XtSetArg(args[n],XmNokLabelString,button_string);n++; | |
361 | XtSetArg(args[n],XmNmessageString,message_string);n++; | |
362 | for(i=0;i<0;i++) | |
363 | { | |
364 | message_box = XmCreateMessageDialog(XtParent(XtParent(widget)),"fontbox",args,n); | |
365 | XtDestroyWidget(message_box); | |
366 | } | |
367 | message_box = XmCreateMessageDialog(XtParent(XtParent(widget)),"fontbox",args,n); | |
368 | XtAddCallback(message_box,XmNokCallback,(void (*)(Widget,void *, void *))CloseCB,(XtPointer)buffer); | |
369 | XtAddCallback(message_box,XmNhelpCallback,(void (*)(Widget,void *, void *))HelpCB,(XtPointer)2); | |
370 | ||
371 | button = XmMessageBoxGetChild(message_box,XmDIALOG_CANCEL_BUTTON); | |
372 | //if(name_string) XmStringFree(name_string); | |
373 | //XtVaGetValues(button,XmNlabelString,&name_string,NULL); | |
374 | //if(name_string) XmStringFree(name_string); | |
375 | XtUnmanageChild(button); | |
376 | //XtDestroyWidget(button); | |
377 | ||
378 | //if(fontlist) XmFontListFree(fontlist); | |
379 | if(name) XtFree((char*)name); | |
380 | //if(name_string) XtFree((char*)name_string); | |
381 | //if(message_string) XtFree((char*)message_string); | |
382 | //if(button_string) XtFree((char*)button_string); | |
383 | if(button_string) XmStringFree(button_string); | |
384 | if(message_string) XmStringFree(message_string); | |
385 | printf("button_string=%x, message_string=%x, name_string=%x\n",button_string,message_string,name_string); | |
386 | return (message_box); | |
387 | } | |
388 | ||
389 | Widget MyHelpDialog(Widget parent,int flag) | |
390 | { | |
391 | static int first_time = 1; | |
392 | static Widget message_box; | |
393 | Arg args[MAX_ARGS]; | |
394 | register int n; | |
395 | ||
396 | static char message[BUFSIZ]; | |
397 | XmString title_string = NULL; | |
398 | static XmString message_string1 = NULL; | |
399 | static XmString message_string2 = NULL; | |
400 | XmString button_string = NULL; | |
401 | ||
402 | if (first_time) | |
403 | { | |
404 | Widget wtmp; | |
405 | n = 0; | |
406 | message_box = XmCreateMessageDialog(XtParent(XtParent(parent)),"helpbox",args,n); | |
407 | button_string = XmStringCreateLtoR("Close",charset); | |
408 | title_string = XmStringCreateLtoR("myfonts help",charset); | |
409 | message_string1 = XmStringCreateLtoR("\nPush one button to get the sample " | |
410 | "\ntext display in the font.\n(Some font may not be opened.)",charset); | |
411 | message_string2 = XmStringCreateLtoR("\n The help text for this specific font.\n",charset); | |
412 | ||
413 | XtVaSetValues(message_box,XmNdialogTitle,title_string,XmNokLabelString,button_string,NULL); | |
414 | wtmp = XmMessageBoxGetChild(message_box,XmDIALOG_CANCEL_BUTTON); | |
415 | XtUnmanageChild(wtmp); | |
416 | wtmp = XmMessageBoxGetChild(message_box,XmDIALOG_HELP_BUTTON); | |
417 | XtUnmanageChild(wtmp); | |
418 | first_time = 0; | |
419 | } | |
420 | ||
421 | if (flag == 1) | |
422 | XtVaSetValues(message_box,XmNmessageString,message_string1,NULL); | |
423 | else | |
424 | XtVaSetValues(message_box,XmNmessageString,message_string2,NULL); | |
425 | ||
426 | return (message_box); | |
427 | } | |
428 | ||
429 | void FontSelectedCB(Widget w,caddr_t client_data,caddr_t call_data) | |
430 | { | |
431 | Widget message_box; | |
432 | //putchar(007);fflush(stdout); | |
433 | message_box = SelectedFontSample(w); | |
434 | XtManageChild(message_box); | |
435 | } | |
436 | ||
437 | void CloseCB(Widget w,caddr_t client_data,caddr_t call_data) | |
438 | { | |
439 | XmString message_string = NULL; | |
440 | XmString button_string = NULL; | |
441 | XmString name_string = NULL; | |
442 | Widget button; | |
443 | XtPointer * buffer; | |
444 | ||
445 | Widget message_box = XtParent(w); | |
446 | buffer = (XtPointer*)client_data; | |
447 | printf("buffer=%x, call_data=%x\n",buffer,call_data); | |
448 | //putchar(007);fflush(stdout); | |
449 | //XtVaGetValues(w,XmNokLabelString,&button_string,XmNmessageString,&message_string,XmNdialogTitle,&name_string,NULL); | |
450 | //printf("freeing button_string=%x, message_string=%x\n",button_string,message_string); | |
451 | XtUnmanageChild(message_box); | |
452 | XtDestroyWidget(message_box); | |
453 | ||
454 | if(buffer[0]) XmFontListFree((XmFontList)buffer[0]); | |
455 | //printf("font=%x, fontlist=%x\n",buffer[1],buffer[0]); | |
456 | if(buffer[1]) XFreeFont(XtDisplay(XtParent(w)),(XFontStruct *)buffer[1]); | |
457 | XtFree((char*)buffer); | |
458 | /* | |
459 | if(button_string) XmStringFree(button_string); | |
460 | if(button_string) XmStringFree(button_string); | |
461 | if(message_string) XmStringFree(message_string); | |
462 | if(message_string) XmStringFree(message_string); | |
463 | */ | |
464 | } | |
465 | ||
466 | void HelpCB(Widget w,int tag,caddr_t call_data) | |
467 | { | |
468 | Widget message_box; | |
469 | int i = tag; | |
470 | printf("tag=%d\n",tag); | |
471 | //putchar(007);fflush(stdout); | |
472 | message_box = MyHelpDialog(w,i); | |
473 | XtManageChild(message_box); | |
474 | } | |
475 | ||
476 | void QuitCB(Widget w,caddr_t client_data,caddr_t call_data) | |
477 | { | |
478 | //putchar(007);fflush(stdout); | |
479 | exit(0); | |
480 | } | |
481 | ||
482 | void MenuCommandCB(Widget w,caddr_t client_data,caddr_t call_data) | |
483 | { | |
484 | Arg args[MAX_ARGS]; | |
485 | int command; | |
486 | int n; | |
487 | int *position; | |
488 | int buffer[4]; | |
489 | ||
490 | command = (int)client_data; | |
491 | switch(command) | |
492 | { | |
493 | case MENU_DISPLAY_POSITION: | |
494 | n = 0; | |
495 | XtSetArg(args[n],XmNselectedPositions,&position);n++; | |
496 | XtGetValues(slist,args,n); | |
497 | if(position) printf("MenuCommandCB: position[0] = %d\n",*position); | |
498 | else printf("MenuCommandCB: position = NULL\n"); | |
499 | break; | |
500 | case MENU_NEXT_POSITION: | |
501 | n = 0; | |
502 | XtSetArg(args[n],XmNselectedPositions,&position);n++; | |
503 | XtGetValues(slist,args,n); | |
504 | if(position) | |
505 | { | |
506 | buffer[0] = *position + 1; | |
507 | XmListDeselectAllItems(slist); | |
508 | n = 0; | |
509 | XtSetArg(args[n],XmNselectedPositions,buffer);n++; | |
510 | XtSetArg(args[n],XmNselectedPositionCount,1);n++; | |
511 | XtSetValues(slist,args,n); | |
512 | } | |
513 | else | |
514 | { | |
515 | buffer[0] = 10; | |
516 | n = 0; | |
517 | XtSetArg(args[n],XmNselectedPositions,buffer);n++; | |
518 | XtSetArg(args[n],XmNselectedPositionCount,1);n++; | |
519 | XtSetValues(slist,args,n); | |
520 | } | |
521 | break; | |
522 | default: | |
523 | printf("undefined command\n"); | |
524 | } | |
525 | } | |
526 | ||
527 | void ListSelectCB(Widget w,caddr_t client_data,XmListCallbackStruct * callback_data) | |
528 | { | |
529 | Arg args[MAX_ARGS]; | |
530 | int n; | |
531 | int *position; | |
532 | ||
533 | n = 0; | |
534 | XtSetArg(args[n],XmNselectedPositions,&position);n++; | |
535 | XtGetValues(slist,args,n); | |
536 | //printf("ListSelectCB: position = %d\n",*position); | |
537 | //n = 0; | |
538 | //XtSetArg(args[n],XmNtopItemPosition,(*position-1)?(*position-1):1);n++; | |
539 | //XtSetValues(slist,args,n); | |
540 | call_back_signal = 1; | |
541 | XmTextSetString(command_window,item_list[*position-1]->name); | |
542 | } | |
543 | ||
544 | void ActiveCB(Widget w,caddr_t client_data,caddr_t call_data) | |
545 | { | |
546 | Arg args[MAX_ARGS]; | |
547 | int n; | |
548 | int *position; | |
549 | ||
550 | n = 0; | |
551 | XtSetArg(args[n],XmNselectedPositions,&position);n++; | |
552 | XtGetValues(slist,args,n); | |
553 | if(!position) return; | |
554 | //printf("active = %d, name = %s\n",position[0]-1,item_list[position[0]-1]->name); | |
555 | active_man_page(item_list[position[0]-1]); | |
556 | } | |
557 | ||
558 | void CommandWindowInputCB(Widget w,caddr_t client_data,caddr_t call_data) | |
559 | { | |
560 | Arg args[MAX_ARGS]; | |
561 | int n; | |
562 | int count; | |
563 | char * name; | |
564 | int position; | |
565 | int *positions; | |
566 | ||
567 | if (call_back_signal) | |
568 | { | |
569 | call_back_signal = 0; | |
570 | return; | |
571 | } | |
572 | ||
573 | name = XmTextGetString(command_window); | |
574 | ||
575 | position = ItemMatch(name); | |
576 | position ++; | |
577 | //printf("match position = %d\n",position); | |
578 | XtFree(name); | |
579 | ||
580 | XmListDeselectAllItems(slist); | |
581 | n = 0; | |
582 | XtSetArg(args[n],XmNselectedPositionCount,1);n++; | |
583 | XtSetArg(args[n],XmNselectedPositions,&position);n++; | |
584 | XtSetArg(args[n],XmNtopItemPosition,(position-1)?(position-1):1);n++; | |
585 | XtSetValues(slist,args,n); | |
586 | } | |
587 | ||
588 | /************************* ManPath ************************/ | |
589 | ManPath::ManPath(char* path_name) | |
590 | { | |
591 | int i; | |
592 | int len; | |
593 | next = NULL; | |
594 | alias = NULL; | |
595 | len = strlen(path_name); | |
596 | man_path = (char*)malloc(len+1); | |
597 | strncpy(man_path,path_name,len); | |
598 | man_path[len] = '\0'; | |
599 | for (i=0;i<11;i++) sub_dir[i] = new SubDir(this); | |
600 | LoadManPath(path_name); | |
601 | } | |
602 | ||
603 | ManPath::~ManPath() | |
604 | { | |
605 | int i; | |
606 | for (i = 0;i<11;i++) delete(sub_dir[i]); | |
607 | free(man_path); | |
608 | } | |
609 | ||
610 | ManPath::GetSize(char c) | |
611 | { | |
612 | int count; | |
613 | int i; | |
614 | int type = subdir_translate_c_to_n(c)+1; | |
615 | if (type <= 11 && type >= 1) return sub_dir[type-1]->GetSize(); | |
616 | for (i = count = 0;i<11;i++) count += sub_dir[i]->GetSize(); | |
617 | return count; | |
618 | } | |
619 | ||
620 | ManPath::GetItems(char c, ManItem * buffer[]) | |
621 | { | |
622 | int count; | |
623 | int i; | |
624 | int type = subdir_translate_c_to_n(c)+1; | |
625 | if (type <= 11 && type >= 1) return sub_dir[type-1]->GetItems(buffer); | |
626 | for (i = count = 0;i<11;i++) count += sub_dir[i]->GetItems(buffer+count); | |
627 | return count; | |
628 | } | |
629 | ||
630 | struct stat state; | |
631 | ||
632 | ManPath::LoadManPath(char * path_name) | |
633 | { | |
634 | DIR *dirp; | |
635 | #if defined(SYS_DIR)||defined(NDIR) | |
636 | struct direct *item; | |
637 | #else | |
638 | struct dirent *item; | |
639 | #endif | |
640 | ||
641 | int len; | |
642 | int val; | |
643 | char name[180]; | |
644 | ||
645 | man_path = (char*)realloc(man_path,strlen(path_name)+1); | |
646 | strcpy(man_path,path_name); | |
647 | ||
648 | dirp = opendir(path_name); | |
649 | if (!dirp) | |
650 | { | |
651 | fprintf(stderr,"Can not open man path %s\n",path_name); | |
652 | } | |
653 | for (item = readdir(dirp);item != NULL;item = readdir(dirp)) | |
654 | { | |
655 | if(item->d_name[0] == '.' && (item->d_name[1] == 0 ||(item->d_name[1] == '.'&&item->d_name[2]==0))) | |
656 | continue; | |
657 | attach(name,path_name,item->d_name); | |
658 | val = stat (name, &state); | |
659 | if (val < 0) fprintf(stderr,"error number %d, in get state %s",errno,name); | |
660 | else if (S_ISDIR(state.st_mode)) LoadManPath(name); | |
661 | else | |
662 | { | |
663 | len = (strlen(item -> d_name)); | |
664 | if(item -> d_name[len-2] == '.') | |
665 | { | |
666 | val = subdir_translate_c_to_n(item->d_name[len-1]); | |
667 | strncpy(name,item->d_name,len-2); | |
668 | name[len-2] = '('; | |
669 | name[len-1] = item->d_name[len-1]; | |
670 | name[len] = ')'; | |
671 | name[len+1] = '\0'; | |
672 | sub_dir[val]->AddItem(name); | |
673 | } | |
674 | else if(item -> d_name[len-3] == '.') | |
675 | { | |
676 | val = subdir_translate_c_to_n(item->d_name[len-2]); | |
677 | strncpy(name,item->d_name,len-3); | |
678 | name[len-3] = '('; | |
679 | name[len-2] = item->d_name[len-2]; | |
680 | name[len-1] = item->d_name[len-1]; | |
681 | name[len] = ')'; | |
682 | name[len+1] = '\0'; | |
683 | sub_dir[val]->AddItem(name); | |
684 | } | |
685 | } | |
686 | } | |
687 | } | |
688 | ||
689 | /************************* SubDir ************************/ | |
690 | SubDir::SubDir(ManPath* path) | |
691 | { | |
692 | man_path = path; | |
693 | buffer_length = 64; | |
694 | count = 0; | |
695 | item_list = (ManItem**)malloc(buffer_length*sizeof(ManItem*)); | |
696 | } | |
697 | ||
698 | SubDir::~SubDir() | |
699 | { | |
700 | int i; | |
701 | for (i=0;i<count;i++) delete(item_list[i]); | |
702 | free(item_list); | |
703 | } | |
704 | ||
705 | void SubDir::AddItem(char * file_name) | |
706 | { | |
707 | if(count >= buffer_length) item_list = (ManItem**)realloc(item_list,(buffer_length*=2)*sizeof(*item_list)); | |
708 | item_list[count++] = new ManItem(this,file_name); | |
709 | } | |
710 | ||
711 | inline SubDir::GetSize() | |
712 | { | |
713 | return count; | |
714 | } | |
715 | ||
716 | SubDir::GetItems(ManItem *buffer[]) | |
717 | { | |
718 | memcpy(buffer,item_list,count*sizeof(ManItem*)); | |
719 | return count; | |
720 | } | |
721 | ||
722 | /************************* ManItem ************************/ | |
723 | inline ManItem::ManItem(SubDir * sub,char *name) | |
724 | { | |
725 | int len; | |
726 | len = strlen(name); | |
727 | this->name = (char*)malloc(len+1); | |
728 | strncpy(this->name,name,len); | |
729 | this->name[len] = '\0'; | |
730 | } | |
731 | ||
732 | inline ManItem::~ManItem() | |
733 | { | |
734 | free(name); | |
735 | } | |
736 | ||
737 | /************************* init global data ************************/ | |
738 | void InitData() | |
739 | { | |
740 | int i; | |
741 | man_paths = NULL; | |
742 | item_list = NULL; | |
743 | item_list_length = 0; | |
744 | item_list_count = 0; | |
745 | ||
746 | man_paths = new ManPath("/usr/X11/man/"); | |
747 | printf("GetSize = %d\n",man_paths->GetSize('a')); | |
748 | ||
749 | item_list_length = item_list_count = man_paths->GetSize('a'); | |
750 | printf("GetSize = %d\n",item_list_count); | |
751 | item_list = (ManItem**)malloc(item_list_count*sizeof(ManItem*)); | |
752 | man_paths->GetItems('a',item_list); | |
753 | qsort(item_list,item_list_count,sizeof(ManItem*),&ManItemComp); | |
754 | //for(i=0;i<item_list_count;i++) printf("%s\n",item_list[i]->name); | |
755 | } | |
756 | ||
757 | /* Put DIRNAME/NAME into DEST, handling `.' and `/' properly. */ | |
758 | ||
759 | static void attach (char *dest, const char *dirname, const char *name) | |
760 | { | |
761 | const char *dirnamep = dirname; | |
762 | ||
763 | /* Copy dirname if it is not ".". */ | |
764 | if (dirname[0] != '.' || dirname[1] != 0) | |
765 | { | |
766 | while (*dirnamep) *dest++ = *dirnamep++; | |
767 | /* Add '/' if `dirname' doesn't already end with it. */ | |
768 | if (dirnamep > dirname && dirnamep[-1] != '/') *dest++ = '/'; | |
769 | } | |
770 | while (*name) *dest++ = *name++; | |
771 | *dest = 0; | |
772 | } | |
773 | ||
774 | int subdir_translate_c_to_n(char c) | |
775 | { | |
776 | if(c<='8' && c>='1') return (c-'1'); | |
777 | else if(c == 'n') return 8; | |
778 | else if(c == 'l') return 9; | |
779 | else if(c == 'a') return -1; | |
780 | else return 10; | |
781 | } | |
782 | ||
783 | int ManItemComp(ManItem ** a,ManItem ** b) | |
784 | { | |
785 | return (strcmp((*a)->name,(*b)->name)); | |
786 | } | |
787 | ||
788 | int ItemMatch(char * name) | |
789 | { | |
790 | int i; | |
791 | for (i=0;i<item_list_count && strcmp(name,item_list[i]->name)>0 ;i++); | |
792 | return (i >= item_list_count)? i-1:i; | |
793 | } | |
794 | ||
795 | static void active_man_page(ManItem * item) | |
796 | { | |
797 | int i; | |
798 | int len,len2; | |
799 | char buffer[180]; | |
800 | len = strlen(item->name); | |
801 | if (item->name[len-3] == '(') len -= 3; | |
802 | else len -= 4; | |
803 | ||
804 | strcpy(buffer,"nxterm -T '"); | |
805 | strcat(buffer,item->name); | |
806 | strcat(buffer,"' -n KMan -e man "); | |
807 | len2 = strlen(buffer); | |
808 | strncat(buffer,item->name,len); buffer[len+len2] = '\0'; | |
809 | if(!fork()) | |
810 | { | |
811 | //printf(buffer); | |
812 | system(buffer); | |
813 | exit(0); | |
814 | } | |
815 | return; | |
816 | } | |
817 |
0 | /************************ task.c ***************************/ | |
1 | /*********************** 1999.6.21 *************************/ | |
2 | ||
3 | #include "task.h" | |
4 | #include <stdio.h> | |
5 | #include <unistd.h> | |
6 | #include <pthread.h> | |
7 | ||
8 | struct _task_group { | |
9 | pthread_t thread; | |
10 | pthread_attr_t attr; | |
11 | pthread_mutex_t lock; | |
12 | int state; | |
13 | List * tasks; | |
14 | }; | |
15 | ||
16 | struct _task { | |
17 | TaskGroup * task_group; | |
18 | pthread_mutex_t lock; | |
19 | int state; | |
20 | float priority; | |
21 | TaskRunFunc task_run_func; | |
22 | gpointer user_data; | |
23 | List * signals[2]; | |
24 | //signal quenes, 1 for synchronous signals, 0 for unsynchronous signals | |
25 | }; | |
26 | ||
27 | static void * task_group_running(TaskGroup *); | |
28 | static void task_group_set_active(TaskGroup *); | |
29 | ||
30 | TaskGroup * task_group_new() | |
31 | { | |
32 | int retcode; | |
33 | TaskGroup * task_group = (TaskGroup*)g_malloc(sizeof(TaskGroup)); | |
34 | task_group->tasks = new List; | |
35 | task_group->state = 0; | |
36 | pthread_attr_init(&(task_group->attr)); | |
37 | pthread_attr_setdetachstate(&(task_group->attr), 1); | |
38 | pthread_mutex_init(&task_group->lock,NULL); | |
39 | //retcode = pthread_create(&task_group->thread, NULL, (void*(*)(void*))my_thread_running, (void *) task_group); | |
40 | //if (retcode != 0) g_error("my_thread_new:thread creation failed %d\n", retcode); | |
41 | return task_group; | |
42 | } | |
43 | ||
44 | Task * task_new(TaskGroup * task_group, float priority, TaskRunFunc task_func, gpointer data) | |
45 | { | |
46 | int i,j,k; | |
47 | Task * task; | |
48 | g_return_val_if_fail((priority>0.0 && priority <1.0)&&(task_group != NULL)&&(task_func != NULL),NULL); | |
49 | ||
50 | task = (Task *)g_malloc(sizeof(Task)); | |
51 | pthread_mutex_init(&task->lock,NULL); | |
52 | task->priority = priority; | |
53 | task->state = 0; | |
54 | task->task_group = task_group; | |
55 | task->task_run_func = task_func; | |
56 | task->user_data = data; | |
57 | task->signals[0] = new List; | |
58 | task->signals[1] = new List; | |
59 | ||
60 | pthread_mutex_lock(&task_group->lock); | |
61 | j = task_group->tasks->get_size(); | |
62 | for(i = 0;i<j && priority>((Task*)task_group->tasks->get_item(i))->priority;i++); | |
63 | task_group->tasks->insert_item(i,(void*)task); | |
64 | pthread_mutex_unlock(&task_group->lock); | |
65 | ||
66 | return task; | |
67 | } | |
68 | ||
69 | void task_signal_send(Task * task, int signal) | |
70 | { | |
71 | g_return_if_fail(task != NULL); | |
72 | pthread_mutex_lock(&task->lock); | |
73 | task->signals[signal&1]->add_item((void*)signal); | |
74 | pthread_mutex_unlock(&task->lock); | |
75 | task_group_set_active(task->task_group); | |
76 | } | |
77 | ||
78 | void task_set_active(Task * task) | |
79 | { | |
80 | task_signal_send(task,TASK_START); | |
81 | } | |
82 | ||
83 | void task_set_stop(Task * task) | |
84 | { | |
85 | task_signal_send(task,TASK_STOP); | |
86 | } | |
87 | ||
88 | //let the task itself to decide wether to stop or not | |
89 | //of the task don't want to be wake up any more, it will return 0, | |
90 | //otherwise 1. | |
91 | ||
92 | static void task_group_set_active(TaskGroup * task_group) | |
93 | { | |
94 | int retcode; | |
95 | pthread_mutex_lock(&task_group->lock); | |
96 | if(!task_group->state) { | |
97 | task_group->state |= 1; | |
98 | retcode = pthread_create(&task_group->thread, &task_group->attr, (void*(*)(void*))task_group_running, (void *) task_group); | |
99 | if (retcode != 0) g_error("thread creation failed %d\n", retcode); | |
100 | } | |
101 | pthread_mutex_unlock(&task_group->lock); | |
102 | } | |
103 | ||
104 | static void * task_group_running(TaskGroup * task_group) | |
105 | { | |
106 | int i,j; | |
107 | int have_task; | |
108 | int state,k; | |
109 | Task * task; | |
110 | ||
111 | do { | |
112 | have_task = 0; | |
113 | task = NULL; | |
114 | int flag; | |
115 | pthread_mutex_lock(&task_group->lock); | |
116 | j = task_group->tasks->get_size(); | |
117 | for(i = 0; i<j && !have_task ;i++) { | |
118 | if((task = (Task*)task_group->tasks->get_item(i))->signals[0]->get_size()) { | |
119 | flag = ((int)task->signals[0]->get_item(0) & ~1) | (task->state & 1); | |
120 | task->signals[0]->delete_item(0); | |
121 | have_task++; | |
122 | } | |
123 | else if (task->state & TASK_RUNNING) { | |
124 | flag = task->state & TASK_RUNNING; | |
125 | have_task++; | |
126 | } | |
127 | else if (task->signals[1]->get_size()) { | |
128 | flag = ((int)task->signals[1]->get_item(1) & ~1); | |
129 | task->signals[1]->delete_item(0); | |
130 | have_task++; | |
131 | } | |
132 | } | |
133 | pthread_mutex_unlock(&task_group->lock); | |
134 | if(have_task) { | |
135 | // printf("init state = %x\n",task->state); | |
136 | state = (*task->task_run_func)(flag,task->user_data); | |
137 | if(state) | |
138 | task->state |= TASK_RUNNING; | |
139 | else | |
140 | task->state &= ~TASK_RUNNING; | |
141 | // printf("return state = %x\n",task->state); | |
142 | } | |
143 | } while (have_task); | |
144 | pthread_mutex_lock(&task_group->lock); | |
145 | task_group->state &= ~TASK_RUNNING; | |
146 | pthread_mutex_unlock(&task_group->lock); | |
147 | return 0; | |
148 | } | |
149 |
0 | /************************ task.h ***************************/ | |
1 | /************************ 1999.6.21 ************************/ | |
2 | ||
3 | #ifndef _TASK_H | |
4 | #define _TASK_H | |
5 | ||
6 | #include <glib.h> | |
7 | #include "list.h" | |
8 | ||
9 | typedef enum | |
10 | { | |
11 | TASK_RUNNING = 1 << 0, | |
12 | TASK_START = 1 << 1, | |
13 | TASK_STOP = 1 << 2, | |
14 | } MyTaskRunningFlags; | |
15 | ||
16 | typedef struct _task_group TaskGroup; | |
17 | typedef struct _task Task; | |
18 | typedef int (* TaskRunFunc) (int flag, gpointer data); | |
19 | ||
20 | TaskGroup * task_group_new(); | |
21 | Task * task_new(TaskGroup * thread, float priority, TaskRunFunc task_func, gpointer data); | |
22 | void task_signal_send(Task * task, int signal); | |
23 | void task_set_active(Task * task); | |
24 | void task_set_stop(Task * task); | |
25 | ||
26 | #endif | |
27 |
0 | #include <stdlib.h> | |
1 | #include "taskfunc.h" | |
2 | #include "menu.h" | |
3 | #include "mandata.h" | |
4 | #include "context.h" | |
5 | #include "util.h" | |
6 | #include "gman.h" | |
7 | #include <string.h> | |
8 | #include "window2.h" | |
9 | #include <unistd.h> | |
10 | #include <sys/types.h> | |
11 | #include <signal.h> | |
12 | #include <errno.h> | |
13 | #include <stdio.h> | |
14 | ||
15 | //#include <gtk/gtk.h> | |
16 | ||
17 | /********************* init_man_data *************************/ | |
18 | int init_man_data() | |
19 | { | |
20 | ManPath * path; | |
21 | char * path_name,*p1,*p2; | |
22 | int end = 0; | |
23 | man_paths = new Dictionary; | |
24 | path_name = my_strdup((char*)context->get_value("man_paths")); | |
25 | p1 = path_name; | |
26 | while(!end) { | |
27 | p2 = strchr(p1,(int)':'); | |
28 | if(p2 == NULL) end++; | |
29 | else *p2 = '\0'; | |
30 | man_paths->add_item(my_strdup(p1),(void*)( new ManPath(p1))); | |
31 | p1 = p2+1; | |
32 | } | |
33 | if(path_name) free (path_name); | |
34 | return 0; | |
35 | } | |
36 | ||
37 | int extract_man_data() | |
38 | { | |
39 | ManItem ** buffer; | |
40 | int i,j,count; | |
41 | int display_section_ID; | |
42 | ||
43 | pthread_mutex_lock(&context_lock); | |
44 | switch ((int)context->get_value("display_section_policy")) { | |
45 | case 0: display_section_ID = ~0;break; | |
46 | case 1: display_section_ID = ~(int)(context->get_value("display_section"));break; | |
47 | case 2: display_section_ID = (int)context->get_value("display_section"); break; | |
48 | default: fprintf(stderr,"warning: init_man_data: \"display_section_policy\" " | |
49 | "have invalid value %d",context->get_value("display_section_policy")); | |
50 | display_section_ID = ~0; | |
51 | } | |
52 | pthread_mutex_unlock(&context_lock); | |
53 | ||
54 | if(man_items_count) free(man_items_buffer); | |
55 | j = man_paths->get_size(); | |
56 | for(i = man_items_count = 0;i<j;i++) | |
57 | man_items_count += ((ManPath*)(man_paths->get_value(i)))->GetSize(display_section_ID); | |
58 | buffer = (ManItem**)malloc(sizeof(ManItem*)*man_items_count); | |
59 | man_items_buffer = (char**) buffer; | |
60 | for(i = count = 0;i<j;i++) | |
61 | count += ((ManPath*)(man_paths->get_value(i)))->GetItems(display_section_ID,buffer+count); | |
62 | if( count != man_items_count) exit(1); | |
63 | ||
64 | if(context->get_value("debuging")) printf("count = %d\n",count); | |
65 | qsort((void *)buffer,count,sizeof(ManItem*),(int(*)(const void*,const void*))&man_item_compare); | |
66 | if(context->get_value("debuging")) printf("count = %d, qsort end.\n",count); | |
67 | ||
68 | return 0; | |
69 | } | |
70 | ||
71 | int add_data_to_clist(int flag) | |
72 | { | |
73 | gchar *text[2]; | |
74 | static int i; | |
75 | int j,k; | |
76 | ManItem ** buffer; | |
77 | static char ** pointer; | |
78 | char a[100],b[20]; | |
79 | int display_section_ID; | |
80 | ||
81 | text[0] = a; text[1] = b; | |
82 | buffer = (ManItem**) man_items_buffer; | |
83 | ||
84 | pthread_mutex_lock(>k_lock); | |
85 | ||
86 | if(flag & TASK_START) { | |
87 | i = 0; | |
88 | pointer = man_items_buffer; | |
89 | gtk_clist_clear(GTK_CLIST(clist)); | |
90 | } | |
91 | ||
92 | gtk_clist_freeze(GTK_CLIST(clist)); | |
93 | for (j = 0;j<100 & i< man_items_count;i++,j++) { | |
94 | buffer[i]->get_display_name(a); | |
95 | buffer[i]->get_section_name(b); | |
96 | gtk_clist_append(GTK_CLIST(clist),text); | |
97 | gtk_clist_set_row_data(GTK_CLIST(clist),i,(gpointer)buffer[i]); | |
98 | gtk_clist_get_text(GTK_CLIST(clist),i,0,pointer++); | |
99 | } | |
100 | gtk_clist_thaw(GTK_CLIST(clist)); | |
101 | pthread_mutex_unlock(>k_lock); | |
102 | ||
103 | //pointer = man_items_display_name; | |
104 | //for(int i = 0;i<man_items_count;i++) printf(*(pointer++)); | |
105 | return (i < man_items_count); | |
106 | } | |
107 | ||
108 | int loading_man_data() | |
109 | { | |
110 | ManPath * p; | |
111 | char * c; | |
112 | int i; | |
113 | char buffer[100]; | |
114 | if(!man_paths_to_be_load->get_size()) return 0; | |
115 | pthread_mutex_lock(&loading_man_path_lock); | |
116 | c = (char*)man_paths_to_be_load->get_item(0); | |
117 | man_paths_to_be_load->delete_item(0); | |
118 | pthread_mutex_unlock(&loading_man_path_lock); | |
119 | p = new ManPath(c); | |
120 | i = man_paths->search_item(c); | |
121 | if (i == -1) { | |
122 | delete (p); | |
123 | g_warning("man path %s does not exist\n",c); | |
124 | return man_paths_to_be_load->get_size(); | |
125 | } | |
126 | // printf("loading... %d end\n",i); | |
127 | man_paths->set_value(i,(void*)p); | |
128 | if(clist2) { | |
129 | sprintf(buffer,"%d",p->GetSize(-1)); | |
130 | pthread_mutex_lock(>k_lock); | |
131 | gtk_clist_set_text(GTK_CLIST(clist2),i,2,buffer); | |
132 | pthread_mutex_unlock(>k_lock); | |
133 | } | |
134 | return man_paths_to_be_load->get_size(); | |
135 | } | |
136 | ||
137 | int is_blank(char c) {return (c==0x20||c==0x09)?1:0;} | |
138 | ||
139 | typedef enum | |
140 | { | |
141 | S_START, | |
142 | S_NAME, | |
143 | S_NAME_END1, | |
144 | S_NAME_END2, | |
145 | S_SECTION, | |
146 | S_SECTION_END1, | |
147 | S_SECTION_END2, | |
148 | S_MINUS, | |
149 | S_COMMENT_START, | |
150 | S_COMMENT | |
151 | } STATES; | |
152 | ||
153 | #define BUF_SIZE 400 | |
154 | ||
155 | static List * names; //the names returned are strdup() , need to free out side | |
156 | static char * comment; | |
157 | static char section[BUF_SIZE/4]; | |
158 | ||
159 | static int parser_whatis(int fd) | |
160 | { | |
161 | static int init = 0; | |
162 | int i,j,k,end; | |
163 | static char buffer[BUF_SIZE]; | |
164 | char a,b,c; | |
165 | ||
166 | if(!init) { | |
167 | names = new List; | |
168 | init ++; | |
169 | } | |
170 | ||
171 | names->delete_all(); | |
172 | i = 0; | |
173 | end = 0; | |
174 | STATES s = S_START; | |
175 | while(!end) { | |
176 | k = read(fd,&c,1); | |
177 | //g_print("%c",c,k); | |
178 | if(k == -1) g_error("key word task:reading from pipe:%s",g_strerror(errno)); | |
179 | if (k == 0 || c == 0x0a) { | |
180 | if (s == S_COMMENT) { | |
181 | buffer[i] = 0; | |
182 | // add items to clist | |
183 | //for(j = 0;j<names->get_size();j++) g_print("%s , ",(char*)names->get_item(j)); | |
184 | //g_print("section = %s, \tcomment = %s\n",section,buffer); | |
185 | comment = buffer; | |
186 | } | |
187 | else if( s != S_START) { | |
188 | if(context->get_value("show_warning")) | |
189 | g_warning("parser error: unexpected end of %s",k?"line":"file"); | |
190 | comment = NULL; | |
191 | } | |
192 | end++; | |
193 | continue; | |
194 | } | |
195 | switch (s) { | |
196 | case S_START: | |
197 | if(!is_blank(c)) { | |
198 | s = S_NAME; | |
199 | i = 0; | |
200 | buffer[i++] = c; | |
201 | } | |
202 | break; | |
203 | case S_NAME: | |
204 | if( c == ',') { | |
205 | s = S_NAME_END1; | |
206 | buffer[i] = 0; | |
207 | names->add_item(my_strdup(buffer)); | |
208 | } else if(is_blank(c)) { | |
209 | s = S_NAME_END2; | |
210 | }else { | |
211 | buffer[i++] = c; | |
212 | } | |
213 | break; | |
214 | case S_NAME_END1: | |
215 | if(is_blank(c)) break; | |
216 | else if(c == '(') { | |
217 | s = S_SECTION; | |
218 | i = 0; | |
219 | } | |
220 | else { | |
221 | s = S_NAME; | |
222 | i = 0; | |
223 | buffer[i++] = c; | |
224 | } | |
225 | break; | |
226 | case S_NAME_END2: | |
227 | if(is_blank(c)) break; | |
228 | else if(c == '(') { | |
229 | buffer[i] = 0; | |
230 | names->add_item(my_strdup(buffer)); | |
231 | s = S_SECTION; | |
232 | i = 0; | |
233 | } else if(c == ',') { | |
234 | s = S_NAME_END1; | |
235 | buffer[i] = 0; | |
236 | names->add_item(my_strdup(buffer)); | |
237 | } | |
238 | else { | |
239 | s = S_NAME; | |
240 | buffer[i++] = c; | |
241 | } | |
242 | break; | |
243 | case S_SECTION: | |
244 | if(is_blank(c)) break; | |
245 | else if(c == ')') { | |
246 | s = S_SECTION_END1; | |
247 | if(i == 0) { | |
248 | g_warning("parser error: unknown format"); | |
249 | } | |
250 | else { | |
251 | buffer[i] = 0; | |
252 | strcpy(section,buffer); | |
253 | } | |
254 | } | |
255 | else buffer[i++] = c; | |
256 | break; | |
257 | case S_SECTION_END1: | |
258 | if(is_blank(c)) break; | |
259 | else if(c == '-') s = S_SECTION_END2; | |
260 | break; | |
261 | case S_SECTION_END2: | |
262 | if(is_blank(c)) s = S_COMMENT_START; | |
263 | else g_warning("parser error: unknwn format"); | |
264 | break; | |
265 | case S_COMMENT_START: | |
266 | if(!is_blank(c)) { | |
267 | s = S_COMMENT; | |
268 | i = 0; | |
269 | buffer[i++] = c; | |
270 | } | |
271 | break; | |
272 | case S_COMMENT: | |
273 | buffer[i++] = c; | |
274 | break; | |
275 | default: g_warning("parser error: unknow state"); | |
276 | } | |
277 | } | |
278 | //g_print("k = %d\n",k); | |
279 | return k; | |
280 | } | |
281 | ||
282 | List * keyword_search_list; | |
283 | ||
284 | static int key_word_search_taskfunc(int flag) | |
285 | { | |
286 | static int init = 0; | |
287 | static char * parameter; | |
288 | static int process_ID; | |
289 | static int pipes[2]; | |
290 | static List * paths; | |
291 | static char * path; | |
292 | static int pipe_active; // pipe is in active | |
293 | static int running; // pipe is in active | |
294 | static int counter; | |
295 | ||
296 | ManPath * man_path; | |
297 | ManItem * man_item; | |
298 | int i,j,k; | |
299 | char file_name[BUF_SIZE], buffer[BUF_SIZE]; | |
300 | char * text[3]; | |
301 | char * s; | |
302 | ||
303 | if(!init) { | |
304 | pipe_active = 0; | |
305 | running = 0; | |
306 | paths = new List(); | |
307 | keyword_search_list = new List(); | |
308 | init ++; | |
309 | } | |
310 | ||
311 | //g_print("task key-word search ...\n"); | |
312 | if((flag & (TASK_START|TASK_STOP)) && pipe_active) { | |
313 | //g_print("reset ...\n"); | |
314 | kill(process_ID,3); | |
315 | close(pipes[0]); | |
316 | pipe_active = 0; | |
317 | running = 0; | |
318 | gtk_widget_set_sensitive(stop_button,0); | |
319 | //paths->delete_all(); | |
320 | } | |
321 | if(flag & TASK_START) { | |
322 | //g_print("starting ... key = %s\n",keyword); | |
323 | running = 1; | |
324 | gtk_widget_set_sensitive(stop_button,1); | |
325 | paths->delete_all(); | |
326 | gtk_clist_clear(GTK_CLIST(clist3)); | |
327 | counter = 0; | |
328 | j = man_paths->get_size(); | |
329 | for(i = 0;i<j;i++) paths->add_item(man_paths->get_name(i)); | |
330 | } else if( !pipe_active ) { | |
331 | if(paths->get_size() == 0) { | |
332 | running = 0; | |
333 | gtk_widget_set_sensitive(stop_button,0); | |
334 | } else { | |
335 | path = (char*) paths->get_item(0); | |
336 | paths->delete_item(0); | |
337 | strcpy(buffer,"grep "); | |
338 | strcat(buffer,keyword); | |
339 | strcat(buffer," "); | |
340 | attach(file_name,path,"whatis"); | |
341 | strcat(buffer,file_name); | |
342 | strcat(buffer," "); | |
343 | ||
344 | g_return_val_if_fail(!pipe(pipes),0); | |
345 | process_ID = fork(); | |
346 | if(process_ID == -1) {g_warning("can not fork a new process");return 0;} | |
347 | if(process_ID == 0) { | |
348 | g_return_val_if_fail(close(pipes[0]) != -1,0);; | |
349 | close(1); | |
350 | g_return_val_if_fail(dup(pipes[1]) == 1,0); | |
351 | g_return_val_if_fail(close(pipes[1]) != -1,0); | |
352 | //write(1,"1234567890safdsfd%srfwfwefw",10); | |
353 | //fprintf(stderr,"%s\n",buffer); | |
354 | if(do_system_command(buffer,0));// g_warning("my_system returned a non-zero value!"); | |
355 | _exit(0); | |
356 | } | |
357 | close(pipes[1]); | |
358 | pipe_active ++; | |
359 | } | |
360 | } else { //running, pipe in active | |
361 | k = parser_whatis(pipes[0]); | |
362 | if((j = names->get_size())) { | |
363 | /* | |
364 | for(i = 0;i<j;i++) | |
365 | g_print(i?", %s":"%s",names->get_item(i)); | |
366 | g_print("(%s)",section); | |
367 | g_print(" - %s\n",comment); | |
368 | */ | |
369 | man_path = (ManPath*)man_paths->get_value(man_paths->search_item(path)); | |
370 | text[1] = section; | |
371 | text[2] = ""; | |
372 | for(i = 0;i<j;i++) { | |
373 | //g_print("point 0, man_item = %x\n",man_path); | |
374 | s = (char*)names->get_item(i); | |
375 | if(s[0] == '/') s = strrchr(s, '/') + 1; | |
376 | man_item = (ManItem*)man_path->search_man_item(s,section); | |
377 | //g_print("point 1\n"); | |
378 | if(context->get_value("show_warning")) | |
379 | if (!man_item) g_warning("man item: %s (%s) could not found",names->get_item(i),section); | |
380 | text[0] = (char*)names->get_item(i); | |
381 | //g_print("point 2\n"); | |
382 | if(i == j-1) text[2] = comment; | |
383 | pthread_mutex_lock(>k_lock); | |
384 | gtk_clist_append(GTK_CLIST(clist3),text); | |
385 | gtk_clist_set_row_data(GTK_CLIST(clist3),counter++,(gpointer)man_item); | |
386 | pthread_mutex_unlock(>k_lock); | |
387 | } | |
388 | } | |
389 | if(k == 0) { | |
390 | close(pipes[0]); | |
391 | pipe_active = 0; | |
392 | //g_print("pipe closeing \n"); | |
393 | } | |
394 | } | |
395 | return running; | |
396 | } | |
397 | ||
398 | /******************* init thread **********************/ | |
399 | Task *task_init_man_data; | |
400 | Task *task_extract_man_data; | |
401 | Task *task_add_data_to_clist; | |
402 | Task *task_loading_man_data; | |
403 | Task *task_key_word_search; | |
404 | void init_thread(TaskGroup * thread) | |
405 | { | |
406 | task_init_man_data = task_new(thread,0.3,(TaskRunFunc)init_man_data,NULL); | |
407 | task_set_active(task_init_man_data); | |
408 | task_extract_man_data = task_new(thread,0.5,(TaskRunFunc)extract_man_data,NULL); | |
409 | task_set_active(task_extract_man_data); | |
410 | task_add_data_to_clist = task_new(thread,0.7,(TaskRunFunc)add_data_to_clist,NULL); | |
411 | task_set_active(task_add_data_to_clist); | |
412 | task_loading_man_data = task_new(thread,0.31,(TaskRunFunc)loading_man_data,NULL); | |
413 | task_key_word_search = task_new(thread,0.5,(TaskRunFunc)key_word_search_taskfunc,NULL); | |
414 | } |
0 | #ifndef _TASKFUNC_H_ | |
1 | #define _TASKFUNC_H_ | |
2 | #include "task.h" | |
3 | ||
4 | extern Task *task_init_man_data; | |
5 | extern Task *task_extract_man_data; | |
6 | extern Task *task_add_data_to_clist; | |
7 | extern Task *task_loading_man_data; | |
8 | extern Task *task_key_word_search; | |
9 | ||
10 | void init_thread(TaskGroup * thread); | |
11 | int init_man_data(); | |
12 | ||
13 | #endif |
0 | #include "kman.h" | |
1 | #include <stdio.h> | |
2 | ||
3 | void main() | |
4 | { | |
5 | ManPath a("/usr/man"); | |
6 | printf("size = %d",a.GetSize(1)); | |
7 | } | |
8 |
0 | #include <stdio.h> | |
1 | #include "context.h" | |
2 | ||
3 | main() | |
4 | { | |
5 | int i; | |
6 | AppContext context(NULL); | |
7 | context.set_value("test",(void*)1234); | |
8 | context.set_value("v_size",(void*)1024); | |
9 | context.restore_default("test"); | |
10 | context.display_values(); | |
11 | i = (int)context.get_value("v_size"); | |
12 | printf("v_size = %d, h_size = %d, test = %d",i,context.get_value("h_size"),context.get_value("test")); | |
13 | } | |
14 |
0 | /*************** testdict.c ******************/ | |
1 | ||
2 | #include "list.h" | |
3 | #include <stdio.h> | |
4 | ||
5 | void main() | |
6 | { | |
7 | Dictionary * dict; | |
8 | dict = new Dictionary; | |
9 | dict->add_item("/usr/man",(void *)100); | |
10 | dict->add_item("/usr/local/man",(void * )200); | |
11 | printf("size = %d, /usr/man = %d\n",dict->get_size(),dict->get_value("/usr/local/man")); | |
12 | } |
0 | #include "list.h" | |
1 | #include <stdio.h> | |
2 | ||
3 | void main() | |
4 | { | |
5 | List * a; | |
6 | int i,j,k; | |
7 | a = new List; | |
8 | for (i = 0;i<100;i++) | |
9 | { | |
10 | a->add_item((void *)i); | |
11 | } | |
12 | a->delete_item(15); | |
13 | j = 0; | |
14 | while(!a->meet_end(j)) | |
15 | { | |
16 | k = (int)a->get_item(j++); | |
17 | printf("%d ,j = %d\n",k,j); | |
18 | } | |
19 | } | |
20 |
0 | #include <stdlib.h> | |
1 | #include <stdio.h> | |
2 | ||
3 | void main() | |
4 | { | |
5 | int i; | |
6 | void *a,*b; | |
7 | for (i = 1;i<100;i++) | |
8 | { | |
9 | a = malloc(i); | |
10 | b = malloc(1); | |
11 | printf("i = %d, space = %d\n",i,b-a); | |
12 | free(b); | |
13 | free(a); | |
14 | } | |
15 | } | |
16 |
0 | #include "task.h" | |
1 | #include <stdio.h> | |
2 | #include <unistd.h> | |
3 | ||
4 | int task_runb(int state, void * data); | |
5 | int task_runa(int state, void * data); | |
6 | ||
7 | Task *a,*b; | |
8 | void main() | |
9 | { | |
10 | TaskGroup * task_group; | |
11 | task_group = task_group_new(); | |
12 | b = task_new(task_group,0.5,task_runb,"b"); | |
13 | a = task_new(task_group,0.4,task_runa,"a"); | |
14 | task_set_active(b);usleep(15000); | |
15 | //task_set_active(a); | |
16 | //task_set_active(b); | |
17 | sleep(4); | |
18 | } | |
19 | ||
20 | int task_runa(int state, void* data) | |
21 | { | |
22 | static int i; | |
23 | int j,k; | |
24 | if(state&TASK_START) | |
25 | { | |
26 | printf("task a begain... state = %d",state); | |
27 | write(1,"task a begin to run...\n",24); | |
28 | i = 0; | |
29 | //task_set_active(b); | |
30 | } | |
31 | for(j = 0;j < 100 && i< 2000;j++,i++) { | |
32 | write(1,data,1); | |
33 | } | |
34 | usleep(1); | |
35 | return (i<2000); | |
36 | } | |
37 | ||
38 | int task_runb(int state, void* data) | |
39 | { | |
40 | static int i; | |
41 | int j,k; | |
42 | if(state&TASK_START) i = 0; | |
43 | for(j = 0;j < 100 && i< 1000;j++,i++) | |
44 | write(1,data,1); | |
45 | if(i==500) task_set_active(a); | |
46 | write(1,"\n",1); | |
47 | return (i<1000); | |
48 | } | |
49 |
0 | /* | |
1 | * util.c | |
2 | * | |
3 | * Copyright (c) 1990, 1991, John W. Eaton. | |
4 | * | |
5 | * You may distribute under the terms of the GNU General Public | |
6 | * License as specified in the file COPYING that comes with the man | |
7 | * distribution. | |
8 | * | |
9 | * John W. Eaton | |
10 | * jwe@che.utexas.edu | |
11 | * Department of Chemical Engineering | |
12 | * The University of Texas at Austin | |
13 | * Austin, Texas 78712 | |
14 | */ | |
15 | ||
16 | #include <stdio.h> | |
17 | #include <string.h> | |
18 | #include <stdlib.h> | |
19 | #include <stdarg.h> | |
20 | #include <ctype.h> | |
21 | #include <signal.h> | |
22 | #include <sys/types.h> | |
23 | #include <sys/stat.h> | |
24 | #include <sys/wait.h> | |
25 | #include <unistd.h> | |
26 | #include <jerror.h> | |
27 | ||
28 | #include "util.h" | |
29 | #include "gripedefs.h" | |
30 | ||
31 | int debug = 0; | |
32 | char * progname = 0; | |
33 | ||
34 | /* | |
35 | * Extract last element of a name like /foo/bar/baz. | |
36 | */ | |
37 | char * | |
38 | mkprogname (char *s) { | |
39 | char *t; | |
40 | ||
41 | t = strrchr (s, '/'); | |
42 | if (t == (char *)NULL) | |
43 | t = s; | |
44 | else | |
45 | t++; | |
46 | ||
47 | return my_strdup (t); | |
48 | } | |
49 | ||
50 | /* | |
51 | * Is file a nonempty and newer than file b? | |
52 | * | |
53 | * case: | |
54 | * | |
55 | * a newer than b returns 1 | |
56 | * a older than b returns 0 | |
57 | * stat on a fails or a empty returns -1 | |
58 | * stat on b fails or b empty returns -2 | |
59 | * both fail or empty returns -3 | |
60 | */ | |
61 | int | |
62 | is_newer (char *fa, char *fb) { | |
63 | struct stat fa_sb; | |
64 | struct stat fb_sb; | |
65 | register int fa_stat; | |
66 | register int fb_stat; | |
67 | register int status = 0; | |
68 | ||
69 | fa_stat = stat (fa, &fa_sb); | |
70 | if (fa_stat != 0 || fa_sb.st_size == 0) | |
71 | status = 1; | |
72 | ||
73 | fb_stat = stat (fb, &fb_sb); | |
74 | if (fb_stat != 0 || fb_sb.st_size == 0) | |
75 | status |= 2; | |
76 | ||
77 | if (status != 0) | |
78 | return -status; | |
79 | ||
80 | return (fa_sb.st_mtime > fb_sb.st_mtime); | |
81 | } | |
82 | ||
83 | int ruid, rgid, euid, egid, suid; | |
84 | ||
85 | void | |
86 | get_permissions (void) { | |
87 | ruid = getuid(); | |
88 | euid = geteuid(); | |
89 | rgid = getgid(); | |
90 | egid = getegid(); | |
91 | suid = (ruid != euid || rgid != egid); | |
92 | } | |
93 | ||
94 | void | |
95 | no_privileges (void) { | |
96 | if (suid) { | |
97 | #ifndef __CYGWIN32__ | |
98 | setreuid(ruid, ruid); | |
99 | setregid(rgid, rgid); | |
100 | #endif | |
101 | suid = 0; | |
102 | } | |
103 | } | |
104 | ||
105 | /* | |
106 | * Unfortunately, Linux libc system() ignores SIGINT and SIGQUIT | |
107 | * The consequence is that "man -K" cannot be interrupted. | |
108 | * Here a private copy that doesn't fiddle with signals. | |
109 | * (But see below.) | |
110 | */ | |
111 | static int | |
112 | system0 (char *command) { | |
113 | int pid, pid2, status; | |
114 | ||
115 | pid = fork(); | |
116 | if (pid == -1) { | |
117 | perror(progname); | |
118 | fatal (CANNOT_FORK, command); | |
119 | } | |
120 | if (pid == 0) { | |
121 | char *argv[4]; | |
122 | argv[0] = "sh"; | |
123 | argv[1] = "-c"; | |
124 | argv[2] = command; | |
125 | argv[3] = 0; | |
126 | execv("/bin/sh", argv); /* was: execve(*,*,environ); */ | |
127 | exit(127); | |
128 | } | |
129 | do { | |
130 | pid2 = wait(&status); | |
131 | if (pid2 == -1) | |
132 | return -1; | |
133 | } while(pid2 != pid); | |
134 | return status; | |
135 | } | |
136 | ||
137 | /* | |
138 | * What to do upon an interrupt? Experience shows that | |
139 | * if we exit immediately, sh notices that its child has | |
140 | * died and will try to fiddle with the tty. | |
141 | * Simultaneously, also less will fiddle with the tty, | |
142 | * resetting the mode before exiting. | |
143 | * This leads to undesirable races. So, we catch SIGINT here | |
144 | * and exit after the child has exited. | |
145 | */ | |
146 | static int interrupted = 0; | |
147 | static void catch_int(int a) { | |
148 | interrupted = 1; | |
149 | } | |
150 | ||
151 | static int | |
152 | system1 (char *command) { | |
153 | void (*prev_handler)(int) = signal (SIGINT,catch_int); | |
154 | int ret = system0(command); | |
155 | if (interrupted) | |
156 | exit(1); | |
157 | signal(SIGINT,prev_handler); | |
158 | return ret; | |
159 | } | |
160 | ||
161 | static int | |
162 | my_system (char *command) { | |
163 | int pid, pid2, status, stat; | |
164 | ||
165 | if (!suid) | |
166 | return system1 (command); | |
167 | ||
168 | #ifdef _POSIX_SAVED_IDS | |
169 | ||
170 | /* we need not fork */ | |
171 | setuid(ruid); | |
172 | setgid(rgid); | |
173 | status = system1(command); | |
174 | setuid(euid); | |
175 | setgid(egid); | |
176 | return (WIFEXITED(status) ? WEXITSTATUS(status) : 127); | |
177 | #endif | |
178 | ||
179 | fflush(stdout); fflush(stderr); | |
180 | pid = fork(); | |
181 | if (pid == -1) { | |
182 | perror(progname); | |
183 | fatal (CANNOT_FORK, command); | |
184 | } | |
185 | if (pid == 0) { | |
186 | setuid(ruid); | |
187 | setgid(rgid); | |
188 | status = system1 (command); | |
189 | exit(WIFEXITED(status) ? WEXITSTATUS(status) : 127); | |
190 | } | |
191 | pid2 = wait (&stat); | |
192 | if (pid2 == -1) { | |
193 | perror(progname); | |
194 | fatal (WAIT_FAILED, command); /* interrupted? */ | |
195 | } | |
196 | if (pid2 != pid) | |
197 | fatal (GOT_WRONG_PID); | |
198 | if (WIFEXITED(stat) && WEXITSTATUS(stat) != 127) | |
199 | return WEXITSTATUS(stat); | |
200 | fatal (CHILD_TERMINATED_ABNORMALLY, command); | |
201 | return -1; /* not reached */ | |
202 | } | |
203 | ||
204 | FILE * | |
205 | my_popen(const char *command, const char *type) { | |
206 | FILE *r; | |
207 | ||
208 | if (!suid) | |
209 | return popen(command, type); | |
210 | ||
211 | #ifdef _POSIX_SAVED_IDS | |
212 | setuid(ruid); | |
213 | setgid(rgid); | |
214 | r = popen(command, type); | |
215 | setuid(euid); | |
216 | setgid(egid); | |
217 | return r; | |
218 | #endif | |
219 | ||
220 | no_privileges(); | |
221 | return popen(command, type); | |
222 | } | |
223 | ||
224 | /* | |
225 | * Attempt a system () call. | |
226 | */ | |
227 | int | |
228 | do_system_command (char *command, int silent) { | |
229 | int status = 0; | |
230 | ||
231 | /* | |
232 | * If we're debugging, don't really execute the command -- you never | |
233 | * know what might be in that mangled string :-O. | |
234 | */ | |
235 | if (debug == 1) | |
236 | gripe (NO_EXEC, command); | |
237 | else | |
238 | status = my_system (command); | |
239 | ||
240 | if (status && !silent) | |
241 | gripe (SYSTEM_FAILED, command, status); | |
242 | ||
243 | return status; | |
244 | } | |
245 | ||
246 | char * | |
247 | my_malloc (int n) { | |
248 | char *s = (char*) malloc(n); | |
249 | if (!s) | |
250 | fatal (OUT_OF_MEMORY, n); | |
251 | return s; | |
252 | } | |
253 | ||
254 | char * | |
255 | my_strdup (char *s) { | |
256 | char *t = my_malloc(strlen(s) + 1); | |
257 | strcpy(t, s); | |
258 | return t; | |
259 | } | |
260 | ||
261 | /******************* modifyed by Wang XinKai ,1999.3.19 *********/ | |
262 | char *getmsg(int n) | |
263 | { | |
264 | static char buffer[100]; | |
265 | buffer[0] = 0; | |
266 | //sprintf(buffer,"error, errorcode = %d\n",n); | |
267 | return buffer; | |
268 | } | |
269 | ||
270 | void | |
271 | gripe (int n, ...) { | |
272 | va_list p; | |
273 | ||
274 | va_start(p, n); | |
275 | vfprintf (stderr, getmsg(n), p); | |
276 | va_end(p); | |
277 | fflush (stderr); | |
278 | } | |
279 | ||
280 | void | |
281 | fatal (int n, ...) { | |
282 | va_list p; | |
283 | fprintf (stderr, "%s: ", progname); | |
284 | va_start(p, n); | |
285 | vfprintf (stderr, getmsg(n), p); | |
286 | va_end(p); | |
287 | exit (1); | |
288 | } | |
289 | /************************** modify end ************************/ |
0 | /* functions and variables exported from util.c */ | |
1 | ||
2 | void get_permissions (void); | |
3 | void no_privileges (void); | |
4 | char *my_malloc (int n); | |
5 | char *my_strdup (char *s); | |
6 | char *mkprogname (char *s); | |
7 | int is_newer (char *fa, char *fb); | |
8 | int do_system_command (char *cmd, int silent); | |
9 | FILE *my_popen(const char *cmd, const char *type); | |
10 | void gripe (int n, ...); | |
11 | void fatal (int n, ...); | |
12 | ||
13 | extern int ruid, rgid, euid, egid, suid; | |
14 | extern char * progname; | |
15 | extern int debug; |
0 | /******************** departed from menu.c ***************/ | |
1 | /******************** window2.c **************************/ | |
2 | ||
3 | #include <stdio.h> | |
4 | #include <gtk/gtk.h> | |
5 | #include "menu.h" | |
6 | #include "list.h" | |
7 | #include "util.h" | |
8 | #include "mandata.h" | |
9 | #include "taskfunc.h" | |
10 | ||
11 | static int window2_button_callback(GtkWidget *w, gpointer data); | |
12 | static int window2_delete_event_callback(GtkWidget *w, GdkEvent *event,gpointer data); | |
13 | static int clist2_select_callback(GtkWidget *w,int row, int column, GdkEvent *event,gpointer data); | |
14 | static void entry2_activate_callback(GtkWidget *,gpointer); | |
15 | static void entry2_changed_callback(GtkWidget *,gpointer); | |
16 | ||
17 | int signal_window2_change; //used by window2_button_callback() to decide whether to take action or not | |
18 | GtkWidget * window2 = NULL; //edit paths window | |
19 | ||
20 | GtkWidget * clist2 = NULL; | |
21 | int clist2_selected_row; | |
22 | ||
23 | GtkWidget* | |
24 | create_window2 () | |
25 | { | |
26 | GtkWidget *window2; | |
27 | GtkWidget *hbox3; | |
28 | GtkWidget *vbox1; | |
29 | GtkWidget *clist2; | |
30 | GtkWidget *swindow; | |
31 | GtkWidget *hbox4; | |
32 | GtkWidget *button1; | |
33 | GtkWidget *button2; | |
34 | GtkWidget *vbox2; | |
35 | GtkWidget *vbox3; | |
36 | GtkWidget *button3; | |
37 | GtkWidget *button4; | |
38 | GtkWidget *button5; | |
39 | GtkWidget *entry2; | |
40 | ||
41 | gchar *titles[3] = { "a", "Path", "Items" }; | |
42 | ||
43 | window2 = gtk_window_new (GTK_WINDOW_TOPLEVEL); | |
44 | // GTK_WIDGET_UNSET_FLAGS (window2, GTK_CAN_FOCUS); | |
45 | gtk_object_set_data (GTK_OBJECT (window2), "window2", window2); | |
46 | gtk_window_set_title (GTK_WINDOW (window2), "edit man paths"); | |
47 | gtk_window_set_policy (GTK_WINDOW (window2), FALSE, TRUE, FALSE); | |
48 | gtk_widget_set_usize(window2,300,220); | |
49 | ||
50 | gtk_signal_connect(GTK_OBJECT(window2), "delete_event", | |
51 | GTK_SIGNAL_FUNC(window2_delete_event_callback), | |
52 | (void*)1); | |
53 | ||
54 | hbox3 = gtk_hbox_new (FALSE, 10); | |
55 | gtk_object_set_data (GTK_OBJECT (window2), "hbox3", hbox3); | |
56 | gtk_widget_show (hbox3); | |
57 | gtk_container_add (GTK_CONTAINER (window2), hbox3); | |
58 | gtk_container_border_width (GTK_CONTAINER (hbox3), 10); | |
59 | ||
60 | vbox1 = gtk_vbox_new (FALSE, 10); | |
61 | gtk_object_set_data (GTK_OBJECT (window2), "vbox1", vbox1); | |
62 | gtk_widget_show (vbox1); | |
63 | gtk_box_pack_start (GTK_BOX (hbox3), vbox1, TRUE, TRUE, 0); | |
64 | ||
65 | vbox3 = gtk_vbox_new (FALSE, 0); | |
66 | gtk_object_set_data (GTK_OBJECT (window2), "vbox3", vbox1); | |
67 | gtk_widget_show (vbox3); | |
68 | gtk_box_pack_start (GTK_BOX (vbox1), vbox3, TRUE, TRUE, 0); | |
69 | ||
70 | clist2 = gtk_clist_new_with_titles( 3, titles); | |
71 | ::clist2 = clist2; | |
72 | swindow = gtk_scrolled_window_new (NULL, NULL); | |
73 | gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swindow), | |
74 | GTK_POLICY_AUTOMATIC, | |
75 | GTK_POLICY_AUTOMATIC); | |
76 | ||
77 | //GTK_WIDGET_UNSET_FLAGS (swindow, GTK_CAN_FOCUS); | |
78 | ||
79 | gtk_clist_set_column_width(GTK_CLIST(clist2),0,10); | |
80 | gtk_clist_set_column_width(GTK_CLIST(clist2),1,130); | |
81 | gtk_clist_set_column_justification(GTK_CLIST(clist2),0,GTK_JUSTIFY_CENTER); | |
82 | gtk_clist_set_column_justification(GTK_CLIST(clist2),2,GTK_JUSTIFY_RIGHT); | |
83 | gtk_clist_set_selection_mode(GTK_CLIST(clist2),GTK_SELECTION_SINGLE); | |
84 | gtk_clist_column_titles_passive(GTK_CLIST(clist2)); | |
85 | gtk_container_add (GTK_CONTAINER (swindow), clist2); | |
86 | gtk_signal_connect(GTK_OBJECT(clist2),"select_row",GTK_SIGNAL_FUNC(clist2_select_callback),(void*)1); | |
87 | gtk_signal_connect(GTK_OBJECT(clist2),"unselect_row",GTK_SIGNAL_FUNC(clist2_select_callback),(void*)0); | |
88 | ||
89 | gtk_object_set_data (GTK_OBJECT (window2), "clist2", clist2); | |
90 | gtk_widget_show (clist2); | |
91 | gtk_widget_show (swindow); | |
92 | gtk_box_pack_start (GTK_BOX (vbox3), swindow, TRUE, TRUE, 0); | |
93 | ||
94 | entry2 = gtk_entry_new_with_max_length (200); | |
95 | gtk_object_set_data (GTK_OBJECT (window2), "entry2", entry2); | |
96 | gtk_widget_show (entry2); | |
97 | gtk_box_pack_start (GTK_BOX (vbox3), entry2, FALSE, FALSE, 0); | |
98 | gtk_signal_connect(GTK_OBJECT(entry2),"activate",GTK_SIGNAL_FUNC(entry2_activate_callback),NULL); | |
99 | gtk_signal_connect(GTK_OBJECT(entry2),"changed",GTK_SIGNAL_FUNC(entry2_changed_callback),NULL); | |
100 | gtk_tooltips_set_tip (tooltips, entry2, "Input new path here", NULL); | |
101 | ||
102 | ||
103 | hbox4 = gtk_hbox_new (TRUE, 15); | |
104 | gtk_object_set_data (GTK_OBJECT (window2), "hbox4", hbox4); | |
105 | gtk_widget_show (hbox4); | |
106 | gtk_box_pack_end (GTK_BOX (vbox1), hbox4, FALSE, TRUE, 0); | |
107 | ||
108 | button1 = gtk_button_new_with_label ("OK"); | |
109 | gtk_object_set_data (GTK_OBJECT (window2), "button1", button1); | |
110 | gtk_widget_show (button1); | |
111 | gtk_box_pack_start (GTK_BOX (hbox4), button1, TRUE, FALSE, 0); | |
112 | gtk_signal_connect (GTK_OBJECT(button1),"clicked",(GtkSignalFunc)window2_button_callback,(void*)1); | |
113 | GTK_WIDGET_SET_FLAGS (button1, GTK_CAN_DEFAULT); | |
114 | gtk_widget_grab_default (button1); | |
115 | ||
116 | button2 = gtk_button_new_with_label ("apply"); | |
117 | gtk_object_set_data (GTK_OBJECT (window2), "button2", button2); | |
118 | gtk_widget_show (button2); | |
119 | gtk_box_pack_start (GTK_BOX (hbox4), button2, TRUE, FALSE, 0); | |
120 | gtk_signal_connect (GTK_OBJECT(button2),"clicked",(GtkSignalFunc)window2_button_callback,(void*)2); | |
121 | ||
122 | vbox2 = gtk_vbox_new (FALSE, 0); | |
123 | gtk_object_set_data (GTK_OBJECT (window2), "vbox2", vbox2); | |
124 | gtk_widget_show (vbox2); | |
125 | gtk_box_pack_start (GTK_BOX (hbox3), vbox2, FALSE, TRUE, 0); | |
126 | ||
127 | button3 = gtk_button_new_with_label ("Add new"); | |
128 | gtk_object_set_data (GTK_OBJECT (window2), "button3", button3); | |
129 | gtk_widget_show (button3); | |
130 | gtk_box_pack_start (GTK_BOX (vbox2), button3, FALSE, FALSE, 15); | |
131 | gtk_signal_connect (GTK_OBJECT(button3),"clicked",(GtkSignalFunc)window2_button_callback,(void*)3); | |
132 | gtk_widget_set_sensitive(button3,0); | |
133 | ||
134 | button4 = gtk_button_new_with_label ("Delete"); | |
135 | gtk_object_set_data (GTK_OBJECT (window2), "button4", button4); | |
136 | gtk_widget_show (button4); | |
137 | gtk_box_pack_start (GTK_BOX (vbox2), button4, FALSE, FALSE, 0); | |
138 | gtk_signal_connect (GTK_OBJECT(button4),"clicked",(GtkSignalFunc)window2_button_callback,(void*)4); | |
139 | gtk_widget_set_sensitive(button4,0); | |
140 | ||
141 | button5 = gtk_button_new_with_label ("Default"); | |
142 | gtk_object_set_data (GTK_OBJECT (window2), "button5", button5); | |
143 | gtk_widget_show (button5); | |
144 | gtk_box_pack_start (GTK_BOX (vbox2), button5, FALSE, FALSE, 15); | |
145 | gtk_signal_connect (GTK_OBJECT(button5),"clicked",(GtkSignalFunc)window2_button_callback,(void*)5); | |
146 | ||
147 | button5 = gtk_button_new_with_label ("Reload"); | |
148 | gtk_object_set_data (GTK_OBJECT (window2), "button6", button5); | |
149 | gtk_widget_show (button5); | |
150 | gtk_box_pack_start (GTK_BOX (vbox2), button5, FALSE, FALSE, 0); | |
151 | gtk_signal_connect (GTK_OBJECT(button5),"clicked",(GtkSignalFunc)window2_button_callback,(void*)6); | |
152 | ||
153 | button5 = gtk_button_new_with_label ("Reload all"); | |
154 | gtk_object_set_data (GTK_OBJECT (window2), "button7", button5); | |
155 | gtk_widget_show (button5); | |
156 | gtk_box_pack_start (GTK_BOX (vbox2), button5, FALSE, FALSE, 15); | |
157 | gtk_signal_connect (GTK_OBJECT(button5),"clicked",(GtkSignalFunc)window2_button_callback,(void*)7); | |
158 | ||
159 | return window2; | |
160 | } | |
161 | ||
162 | /******************* tool functions ***********************/ | |
163 | void load_clist2() | |
164 | { | |
165 | int i,j; | |
166 | ManPath * p; | |
167 | gchar * clist_item[3]; | |
168 | gchar buffer[100]; | |
169 | j = man_paths->get_size(); | |
170 | gtk_clist_clear(GTK_CLIST(clist2)); | |
171 | for (i = 0;i<j;i++) { | |
172 | p = (ManPath*) man_paths->get_value(i); | |
173 | if (p) { | |
174 | clist_item[0] = p->active?"o":""; | |
175 | clist_item[1] = man_paths->get_name(i); | |
176 | sprintf(buffer,"%d",p->GetSize(-1)); | |
177 | clist_item[2] = buffer; | |
178 | } | |
179 | else { | |
180 | clist_item[0] = "o"; | |
181 | clist_item[1] = man_paths->get_name(i); | |
182 | clist_item[2] = "???"; | |
183 | } | |
184 | gtk_clist_append(GTK_CLIST(clist2),clist_item); | |
185 | } | |
186 | } | |
187 | ||
188 | /******************* interfaces to outside***********************/ | |
189 | int edit_paths_callback(GtkWidget *w, gpointer data) | |
190 | { | |
191 | GtkWidget * apply_button,*delete_button,*focus; | |
192 | if (!window2) { | |
193 | window2 = create_window2(); | |
194 | man_paths_to_be_load = new List; | |
195 | clist2_selected_row = -1; | |
196 | } | |
197 | apply_button = (GtkWidget*) gtk_object_get_data(GTK_OBJECT(window2),"button2"); | |
198 | gtk_widget_set_sensitive(apply_button,0); | |
199 | delete_button = (GtkWidget*) gtk_object_get_data(GTK_OBJECT(window2),"button4"); | |
200 | gtk_widget_set_sensitive(delete_button,0); | |
201 | signal_window2_change = 0; | |
202 | load_clist2(); | |
203 | gtk_widget_show(window2); | |
204 | focus = (GtkWidget*) gtk_object_get_data(GTK_OBJECT(window2),"button1"); | |
205 | gtk_widget_grab_focus (focus); | |
206 | } | |
207 | ||
208 | /******************* call backs ***********************/ | |
209 | static int window2_delete_event_callback(GtkWidget *w, GdkEvent * event, gpointer data) | |
210 | { | |
211 | GtkWidget * ok_button; | |
212 | ok_button = (GtkWidget*)gtk_object_get_data(GTK_OBJECT(w),"button1"); | |
213 | gtk_signal_emit_by_name(GTK_OBJECT(ok_button),"clicked"); | |
214 | return 1; | |
215 | } | |
216 | ||
217 | static int window2_button_callback(GtkWidget *w, gpointer data) | |
218 | { | |
219 | GtkWidget * x, *apply_button,*add_new_button; | |
220 | gchar * c, *c2; | |
221 | int i; | |
222 | int select = (int)data; | |
223 | gchar * clist_item[3]; | |
224 | // printf("point2 data = %d\n",select); | |
225 | apply_button = (GtkWidget*)gtk_object_get_data(GTK_OBJECT(window2),"button2"); | |
226 | add_new_button = (GtkWidget*)gtk_object_get_data(GTK_OBJECT(window2),"button3"); | |
227 | switch(select) { | |
228 | case 1: gtk_widget_hide(window2); //OK | |
229 | case 2: //Apply | |
230 | if(signal_window2_change) { | |
231 | task_set_active(task_extract_man_data); | |
232 | task_set_active(task_add_data_to_clist); | |
233 | } | |
234 | signal_window2_change = 0; | |
235 | gtk_widget_set_sensitive(apply_button,0); | |
236 | break; | |
237 | case 3: //Add New | |
238 | x = (GtkWidget*)gtk_object_get_data(GTK_OBJECT(window2),"entry2"); | |
239 | c = gtk_entry_get_text(GTK_ENTRY(x)); | |
240 | if(!strcmp(c,"")) { | |
241 | g_print("g-man: path name can not be empty\n"); | |
242 | break; | |
243 | } | |
244 | if (man_paths->have_item(c)) break; | |
245 | c2 = my_strdup(c); | |
246 | clist_item[0] = "o"; | |
247 | clist_item[1] = c2; | |
248 | clist_item[2] = "???"; | |
249 | gtk_clist_append(GTK_CLIST(clist2),clist_item); | |
250 | man_paths->add_item(c2,(void*)0); | |
251 | man_paths_to_be_load->add_item(c2); | |
252 | task_set_active(task_loading_man_data); | |
253 | signal_window2_change ++; | |
254 | gtk_widget_set_sensitive(apply_button,1); | |
255 | gtk_editable_select_region (GTK_EDITABLE (x), 0, strlen(c)); | |
256 | break; | |
257 | case 4: //Delete | |
258 | if (clist2_selected_row == -1) break; | |
259 | // printf("remove %d\n",clist2_selected_row); | |
260 | i = clist2_selected_row; | |
261 | delete ((ManPath*)(man_paths->get_value(i))); | |
262 | man_paths->delete_item(i); | |
263 | gtk_clist_remove(GTK_CLIST(clist2),i); | |
264 | signal_window2_change ++; | |
265 | gtk_widget_set_sensitive(apply_button,1); | |
266 | break; | |
267 | default: | |
268 | g_print("g-man: sorry... this function not implementd yet, please wait for the future version\n"); | |
269 | }; | |
270 | return 1; | |
271 | } | |
272 | ||
273 | static int clist2_select_callback(GtkWidget *w,int row, int column, GdkEvent *event,gpointer data) | |
274 | { | |
275 | GtkWidget * delete_button; | |
276 | delete_button = (GtkWidget*)gtk_object_get_data(GTK_OBJECT(window2),"button4"); | |
277 | if(data) { | |
278 | clist2_selected_row = row; | |
279 | } | |
280 | else { | |
281 | if (clist2_selected_row == row) clist2_selected_row = -1; | |
282 | } | |
283 | gtk_widget_set_sensitive(delete_button,clist2_selected_row != -1); | |
284 | return 0; | |
285 | } | |
286 | ||
287 | static void entry2_activate_callback(GtkWidget *w,gpointer data) | |
288 | { | |
289 | GtkWidget * add_new_button; | |
290 | add_new_button = (GtkWidget*)gtk_object_get_data(GTK_OBJECT(window2),"button3"); | |
291 | // printf("button3 = %x\n",add_new_button); | |
292 | gtk_signal_emit_by_name(GTK_OBJECT(add_new_button),"clicked"); | |
293 | } | |
294 | ||
295 | static void entry2_changed_callback(GtkWidget *w,gpointer data) | |
296 | { | |
297 | GtkWidget * add_new_button; | |
298 | add_new_button = (GtkWidget*)gtk_object_get_data(GTK_OBJECT(window2),"button3"); | |
299 | // printf("button3 = %x\n",add_new_button); | |
300 | gtk_widget_set_sensitive(add_new_button,strcmp("",gtk_entry_get_text(GTK_ENTRY(w)))); | |
301 | } |