1 /*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU Library General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
15 */
16 /*----------------------------------------------------------------------*
17 * Originally written:
18 * 2002 Alexis <materm@tele2.fr>
19 *
20 *----------------------------------------------------------------------*/
21
22 /* $Id: notebook2.c,v 1.19 2004/08/15 16:16:39 alexis Exp $
23 */
24
25 #include "rxvt.h"
26
27 #ifdef HAVE_LIBXPM
28
29 #include <X11/xpm.h>
30 #include "close_term.xpm"
31 #include "term.xpm"
32 #include "right.xpm"
33 #include "left.xpm"
34
35 #else
36
37 #include "close_term.xbm"
38 #include "term.xbm"
39 #include "right.xbm"
40 #include "left.xbm"
41
42 #endif /* HAVE_LIBXPM */
43
44 #ifdef DEBUG
45 #define DEBUG_NOT_ALEXIS 1
46 #else
47 #define DEBUG_NOT_ALEXIS 0
48 #endif
49
50 #if DEBUG_NOT_ALEXIS
51 #define DN_ALEXIS(d,x) if(d <= DEBUG_NOT_ALEXIS) fprintf x
52 #else
53 #define DN_ALEXIS(d,x)
54 #endif
55
56 #define THUMB_SPACE 1 /* space between button/thumb */
57 #define THUMB_WIDTH 60
58 #define THUMB_HEIGHT 21
59 #define BUTTON_SIZE 22
60 #define BUTTON_SPACE 5
61 #define THUMB_PAD (TOP_SPACE - THUMB_HEIGHT -2)
62 #define THUMBS_PLACE (width-(4*(BUTTON_SIZE+BUTTON_SPACE)+THUMB_SPACE))
63
64 extern Status XAllocColorNew(Display *dpy, Colormap cmap, XColor *xcolor);
65 static GC whiteGC;
66 static GC light_greyGC; /* for the active vt*/
67 static GC dark_greyGC; /* unactive vt*/
68 static GC dark_grey2GC; /* grey for separation bettween thumbs */
69
70 enum {XPM_TERM,XPM_CLOSE,XPM_LEFT,XPM_RIGHT,NB_XPM};
71
72
73 #ifdef HAVE_LIBXPM
74 static char **xpm_name[] = {
75 mini_term_xpm,close_file_xpm,
76 bookmark_prev_xpm,bookmark_next_xpm
77 };
78 #else
79 static char *xpm_name[] = {
80 term_bits,close_bits,
81 left_bits,right_bits
82 };
83 #endif
84
85 static XImage *img[NB_XPM];
86 static XImage *img_mask[NB_XPM];
87
88 extern void create_vt();
89 extern char **cmd_argv;
90
91 // width of the thumb bar
92 static int width;
93 static int default_tab_title_size;
94
95 // widths of the thumbs
96 static int thumbs_widths[MAX_PAGES];
97
width_beetween(int a,int b)98 int width_beetween(int a,int b) {
99 int i,w=0;
100
101 for(i=a; i <= b; i++) {
102 w += thumbs_widths[i] + THUMB_SPACE;
103 }
104
105 return w;
106 }
107 #ifdef DRAW_THUMBBAR
108
blank_between_right_and_buttons()109 void blank_between_right_and_buttons() {
110 int x=width_beetween(TermWin.left_page,TermWin.right_page);
111 XFillRectangle(Xdisplay,TermWin.thumb_bar,light_greyGC,
112 x,THUMB_PAD,THUMBS_PLACE-x,THUMB_HEIGHT);
113 }
114
compute_size_of_thumbs(void)115 void compute_size_of_thumbs(void) {
116 int i;
117 default_tab_title_size = XTextWidth(
118 TermWin.font,
119 rs_default_tab_title,
120 strlen(rs_default_tab_title)) + 20;
121 for(i=0; i < MAX_PAGES; i++) {
122 thumbs_widths[i] = XTextWidth(TermWin.font,TermWin.vts[i].tab_title,
123 strlen(TermWin.vts[i].tab_title)) + 20;
124 DN_ALEXIS(2,(stderr,"width %d [%s]: %d\n",i,TermWin.vts[i].tab_title,thumbs_widths[i]));
125 }
126 }
127 #endif
128
init_notebook(void)129 void init_notebook(void) {
130 TermWin.last_page = -1;
131 TermWin.active_page = -1;
132 TermWin.left_page = 0;
133 TermWin.right_page = -1;
134 TermWin.last_active_page = 0;
135 }
136
137 #ifdef DRAW_THUMBBAR
set_thumb_num(int page,int active)138 void set_thumb_num(int page,int active) {
139 // x is the index of visible thumbs : start at 0
140 // because TermWin.left_page <= page <= TermWin.right_page <= TermWin.last_page
141 int x=page-TermWin.left_page;
142 int i;
143 char title[TITLE_TAB_MAX+1];
144 GC *gc;
145
146 DN_ALEXIS(1,(stderr,"set_thumb_num(%d,%s)\n",page, active ? "active" : "unactive"));
147 if(active) {
148 gc = &light_greyGC;
149 } else {
150 gc = &dark_greyGC;
151 }
152 x = THUMB_SPACE;
153 for(i=TermWin.left_page; i < page; i++) {
154 x += thumbs_widths[i] + THUMB_SPACE;
155 }
156
157 /* rectangle */
158 XFillRectangle(Xdisplay,TermWin.thumb_bar,*gc,
159 x,
160 THUMB_PAD,thumbs_widths[page],THUMB_HEIGHT);
161
162 /* top horitzontal line */
163 XDrawLine(Xdisplay,TermWin.thumb_bar,whiteGC,
164 x,THUMB_PAD,
165 x+thumbs_widths[page]-1,THUMB_PAD);
166
167 if(active) {
168 /* left vertical line */
169 XDrawLine(Xdisplay,TermWin.thumb_bar,whiteGC,
170 x,THUMB_PAD,
171 x,THUMB_PAD+THUMB_HEIGHT-1);
172
173 /* bottom horitzontal line */
174 XDrawLine(Xdisplay,TermWin.thumb_bar,light_greyGC,
175 x,THUMB_PAD+THUMB_HEIGHT,
176 x+thumbs_widths[page]+THUMB_SPACE,THUMB_PAD+THUMB_HEIGHT);
177 } else {
178 /* bottom horizontal line */
179 XDrawLine(Xdisplay,TermWin.thumb_bar,whiteGC,
180 x,THUMB_PAD+THUMB_HEIGHT,
181 x+thumbs_widths[page]+THUMB_SPACE,THUMB_PAD+THUMB_HEIGHT);
182 }
183
184 /* right vertical line */
185 XDrawLine(Xdisplay,TermWin.thumb_bar,dark_grey2GC,
186 x+thumbs_widths[page],THUMB_PAD,
187 x+thumbs_widths[page],THUMB_PAD+THUMB_HEIGHT-1);
188
189 /* draw the text */
190
191 sprintf(title,"%s",TermWin.vts[page].tab_title);
192 XDrawString(Xdisplay, TermWin.thumb_bar,
193 TermWin.thumbGC,x+10,
194 20,title,strlen(title));
195
196 }
197 #endif
198
199 /* x is the new left_page
200 */
page_left_shift(int x)201 void page_left_shift(int x) {
202
203 DN_ALEXIS(1,(stderr,"page_left_shift(%d)\n",x));
204 if( x >= 0 ) {
205 int i;
206 int space=THUMB_SPACE;
207
208 TermWin.left_page = x;
209 for(i=TermWin.left_page; space + thumbs_widths[i] + THUMB_SPACE < THUMBS_PLACE && i <= TermWin.last_page; i++) {
210 space += thumbs_widths[i] + THUMB_SPACE;
211 }
212
213 if( space + thumbs_widths[i] + THUMB_SPACE >= THUMBS_PLACE ) {
214 TermWin.right_page = max(0,i-1); // to avoid -1
215 } else {
216 TermWin.right_page = TermWin.last_page;
217 }
218 DN_ALEXIS(1,(stderr,"page_left_shift : [%d,%d,%d]\n",
219 TermWin.left_page,TermWin.active_page,TermWin.right_page));
220 #ifdef DRAW_THUMBBAR
221 for(i=TermWin.left_page; i <= TermWin.right_page; i++) {
222 if(i == TermWin.active_page) {
223 set_thumb_num(i,1);
224 } else {
225 set_thumb_num(i,0);
226 }
227 }
228 blank_between_right_and_buttons();
229 #endif
230 }
231 }
232
233 /* x the the new right page
234 */
page_right_shift(int x)235 void page_right_shift(int x) {
236 DN_ALEXIS(1,(stderr,"page_right_shift(%d)\n",x));
237 if( x <= TermWin.last_page) {
238 int i;
239 int space=THUMB_SPACE;
240
241 TermWin.right_page = x;
242 for(i=TermWin.right_page; space + thumbs_widths[i] + THUMB_SPACE < THUMBS_PLACE && i > 0; i--) {
243 space += thumbs_widths[i] + THUMB_SPACE;
244 }
245
246 if( space + thumbs_widths[i] + THUMB_SPACE >= THUMBS_PLACE) {
247 TermWin.left_page = min(i+1,TermWin.last_page);
248 } else {
249 TermWin.left_page = 0;
250 }
251
252 DN_ALEXIS(1,(stderr,"page_right_shift : [%d,%d,%d]\n",
253 TermWin.left_page,TermWin.active_page,TermWin.right_page));
254 #ifdef DRAW_THUMBBAR
255 for(i=TermWin.left_page; i <= TermWin.right_page; i++) {
256 if(i == TermWin.active_page) {
257 set_thumb_num(i,1);
258 } else {
259 set_thumb_num(i,0);
260 }
261 }
262 blank_between_right_and_buttons();
263 #endif
264 }
265 }
266
append_page(int index)267 void append_page(int index) {
268 /* add keyboard input to the main window
269 */
270 static int has_keypressed_mask = 0;
271 if( !has_keypressed_mask ) {
272 XWindowAttributes attr;
273 XGetWindowAttributes(Xdisplay,TermWin.parent,&attr);
274 if( ! (attr.all_event_masks & KeyPressMask) ) {
275 has_keypressed_mask=1;
276 XSelectInput(Xdisplay, TermWin.parent,
277 KeyPressMask | FocusChangeMask |
278 StructureNotifyMask | VisibilityChangeMask);
279 }
280 }
281
282 if( TermWin.last_page < MAX_PAGES-1) {
283 int x; /* the top left corner of the new thumb */
284 int i;
285 int tmp;
286
287 DN_ALEXIS(1,(stderr,"append_page(%d)\n",index));
288
289 // indicate that we add a new thumb
290 TermWin.last_page++;
291
292 #ifdef DRAW_THUMBBAR
293 // width = (2 * TermWin_internalBorder)+TermWin.width;
294 x = THUMB_SPACE;
295 for(i=TermWin.left_page; i < TermWin.last_page; i++) {
296 x += thumbs_widths[i] + THUMB_SPACE;
297 }
298 //x = TermWin.last_page*(THUMB_WIDTH+THUMB_SPACE)+THUMB_SPACE;
299
300 DN_ALEXIS(2,(stderr,"x=%d,TermWin.width=%d\n",x,TermWin.width));
301 if( x+thumbs_widths[TermWin.last_page] > width-(4*(BUTTON_SIZE+BUTTON_SPACE)+THUMB_SPACE) ) {
302 // need to shift left the thumbs
303 // just compute the new value of TermWin.left_page
304
305 DN_ALEXIS(1,(stderr,"shift on left\n"));
306 tmp=0;
307 // how many thumb do we shift on left ?
308 for(i=TermWin.left_page; i < TermWin.last_page ; i++) {
309 tmp += thumbs_widths[i];
310 if( x + thumbs_widths[TermWin.last_page] - tmp <= width-(4*(BUTTON_SIZE+BUTTON_SPACE)+THUMB_SPACE) ) {
311 tmp = width -(4*(BUTTON_SIZE+BUTTON_SPACE)+THUMB_SPACE) - (x + thumbs_widths[TermWin.last_page] - tmp);
312 //printf("NOW, left_page = %d, space beetween thumbs and buttons = %d\n",i,tmp);
313 break;
314 }
315 }
316 // i is the most left page to shift; i+1 is the new TermWin.left_page !
317 TermWin.left_page = i+1;
318 //TermWin.left_page = (TermWin.last_page-1) - (TermWin.right_page - TermWin.left_page) + 1;
319 x = width_beetween(TermWin.left_page,TermWin.last_page);
320 tmp = width - (4*(BUTTON_SIZE+BUTTON_SPACE)+THUMB_SPACE) - x;
321 XFillRectangle(Xdisplay,TermWin.thumb_bar,light_greyGC,
322 x,THUMB_PAD,tmp,THUMB_HEIGHT
323 );
324
325 }
326 #endif
327 TermWin.right_page = TermWin.active_page = TermWin.last_page;
328
329 {
330 /* number the page appropriately */
331 char *tab_title;
332 free(TermWin.vts[TermWin.active_page].tab_title);
333 tab_title=strdup(rs_default_tab_title);
334 tab_title[strlen(tab_title)-1]=0;
335 sprintf(tab_title, "%s%d",tab_title,TermWin.active_page%10);
336 TermWin.vts[TermWin.active_page].tab_title = tab_title;
337 }
338
339 #ifdef DRAW_THUMBBAR
340 /* active the new active page */
341 /* do a left shift (if necessary) and desactivate the thumb */
342 for(i=TermWin.left_page; i < TermWin.right_page; i++) {
343 set_thumb_num(i,(i==TermWin.active_page) ? 1:0);
344 }
345 #endif
346
347 DN_ALEXIS(1,(stderr,"before create_vt (%s)\n",__FILE__));
348 create_vt();
349
350 DN_ALEXIS(1,(stderr,"last page is %d\n",TermWin.last_page));
351 f_launch_command(TermWin.last_page,cmd_argv);
352 scrollbar_show(1);
353 } else {
354 DN_ALEXIS(1,(stderr,"sorry, too many tabs\n"));
355 }
356 }
357
358 /* consider page is in [ TermWin.left_page , TermWin.right_page ]
359 */
remove_thumb(int page_num)360 void remove_thumb(int page_num) {
361
362 if( page_num >= 0 && page_num <= TermWin.last_page) {
363
364 int i;
365 int minus;
366 int x;
367
368 // update thumbs_widths
369 for(i=page_num; i < TermWin.last_page; i++) {
370 thumbs_widths[i] = thumbs_widths[i+1];
371 }
372 for(;i < MAX_PAGES; i++) {
373 thumbs_widths[i] = default_tab_title_size;
374 }
375
376 // compute TermWin.left_page and TermWin.right_page
377 if( TermWin.right_page == TermWin.last_page) {
378 TermWin.last_page--;
379 TermWin.right_page--;
380 x=THUMB_SPACE;
381 for(i=TermWin.last_page; x + thumbs_widths[i] + THUMB_SPACE < THUMBS_PLACE && i >= 0; i--) {
382 x += thumbs_widths[i] + THUMB_SPACE;
383 }
384 TermWin.left_page = max(0,i+1);
385
386 } else {
387 TermWin.last_page--;
388 x = width_beetween(TermWin.left_page,page_num-1);
389 for(i=page_num; i <= TermWin.last_page && x + thumbs_widths[i] + THUMB_SPACE < THUMBS_PLACE; i++) {
390 x += thumbs_widths[i] + THUMB_SPACE;
391 }
392 TermWin.right_page = min(TermWin.last_page,i-1);
393 // may be we can add other thumb
394 if(TermWin.right_page == TermWin.last_page) {
395 for(i=TermWin.left_page-1; i >= 0 && x + thumbs_widths[i] + THUMB_SPACE < THUMBS_PLACE; i--) {
396 x += x + thumbs_widths[i] + THUMB_SPACE;
397 }
398 TermWin.left_page = max(0,i+1);
399 }
400 }
401
402 #ifdef DRAW_THUMBBAR
403 for(i=TermWin.left_page; i <= TermWin.right_page; i++) {
404 set_thumb_num(i,(i == TermWin.active_page)? 1 : 0);
405 }
406 blank_between_right_and_buttons();
407 #endif
408 DN_ALEXIS(1,(stderr,"right_page=%d\n",TermWin.right_page));
409 }
410 }
411
412 // called by the handler of SIGCHLD
remove_page(int page)413 void remove_page(int page) {
414 int the_end=0;
415
416 if( TermWin.last_page == 0) {
417 /* destroying the only vt => kill the app
418 */
419 the_end=1;
420 } else if( page == TermWin.active_page) {
421 if( page == 0) /* special */
422 TermWin.active_page = 1;
423 else
424 TermWin.active_page--;
425
426 TermWin.vts[page].bMapped = 0;
427 TermWin.vts[TermWin.active_page].bMapped = 1;
428 XMapRaised(Xdisplay,TermWin.vts[TermWin.active_page].vt);
429 }
430
431 pat_destroy_command(page);
432 pat_destroy_vt(page);
433
434 if( TermWin.left_page <= page && page <= TermWin.right_page) {
435 /* removing a visible vt */
436 DN_ALEXIS(2,(stderr,"removing a visible vt\n"));
437 remove_thumb(page);
438 } else {
439 TermWin.last_page--;
440 if( page < TermWin.left_page ) {
441 TermWin.left_page--;
442 TermWin.right_page--;
443 }
444 }
445
446 if(the_end) {
447 exit(EXIT_SUCCESS);
448 }
449
450 if( page == 0 ) {
451 TermWin.active_page = 0;
452 }
453
454 #ifdef DRAW_THUMBBAR
455 if( TermWin.left_page <= TermWin.active_page && TermWin.active_page <= TermWin.right_page) {
456 set_thumb_num(TermWin.active_page,1);
457 }
458 #endif
459
460 DN_ALEXIS(2,(stderr,"left: %d, right: %d, last: %d, active: %d\n",
461 TermWin.left_page,TermWin.right_page,TermWin.last_page,TermWin.active_page));
462 }
463
464 // call back appele qd on clique sur effacer un vt
465 // on envoie un EOF au shell, et c'est dans le sighandler
466 // qu'on fait le traitement.
destroy_page(int page,pid_t pid)467 void destroy_page(int page,pid_t pid) {
468 kill(pid,9);
469 }
470
471 #ifdef DRAW_THUMBBAR
472 #define MAX_POPUP_STRING_LENGTH 15
473 #define MAX_MAPPED_STRING_LENGTH 10
retitle_page(int page)474 void retitle_page(int page) {
475 unsigned int width, height, x = 0, y = 0, i;
476 unsigned int border_width = 4;
477 XEvent report;
478 GC gc = TermWin.thumbGC;
479
480 static Window pop_win;
481 char buffer[MAX_MAPPED_STRING_LENGTH];
482 int bufsize=MAX_MAPPED_STRING_LENGTH;
483 int start_x, start_y;
484 KeySym keysym;
485 XComposeStatus compose;
486 int count;
487 unsigned int pop_width, pop_height;
488 char string[MAX_POPUP_STRING_LENGTH], *strptr;
489 int length;
490 int done = 0;
491
492 x = THUMB_SPACE;
493 for(i=TermWin.left_page; i < page; i++) {
494 x += thumbs_widths[i] + THUMB_SPACE;
495 }
496 y = THUMB_PAD;
497 memset(buffer, 0, bufsize);
498 memset(string, 0, MAX_POPUP_STRING_LENGTH);
499 strncpy(string, TermWin.vts[page].tab_title, MAX_POPUP_STRING_LENGTH -1);
500
501 /* Determine pop-up box size from font information */
502 pop_width = thumbs_widths[page];
503 pop_height = THUMB_HEIGHT;
504 pop_win = XCreateSimpleWindow(Xdisplay, TermWin.thumb_bar, x, y,
505 pop_width, pop_height, 1,
506 BlackPixel(Xdisplay, Xscreen),
507 WhitePixel(Xdisplay, Xscreen));
508 /* Calculate starting position of string in window */
509 start_x = 2;
510 start_y = TermWin.font->max_bounds.ascent + 2;
511 XSelectInput(Xdisplay, pop_win, ExposureMask | KeyPressMask);
512 XMapWindow(Xdisplay, pop_win);
513 /* Get events, use first to display text and graphics */
514 while (!done) {
515 int redraw_text = 0;
516 XNextEvent(Xdisplay, &report);
517 switch (report.type) {
518 case Expose:
519 if (report.xexpose.window == pop_win)
520 redraw_text = 1;
521 else /* It's the main window */
522 process_x_event(&report);
523 break;
524 case KeyPress:
525 /* Get characters until you encounter a
526 * carriage return; deal with backspaces, etc. */
527 count = XLookupString(&report, buffer, bufsize,
528 &keysym, &compose);
529 /* Now do the right thing with as many
530 * keysyms as possible */
531 if ((keysym == XK_Return) || (keysym == XK_KP_Enter)
532 || (keysym == XK_Linefeed)) {
533 XUnmapWindow(Xdisplay, pop_win);
534 DN_ALEXIS(1,(stderr,"title is %sd\n",string));
535 done = 1;
536 break;
537 }
538 else if (((keysym >= XK_KP_Space) && (keysym <= XK_KP_9))
539 || ((keysym >= XK_space) && (keysym <= XK_asciitilde))) {
540 if (strlen(string) + strlen (buffer) >= MAX_POPUP_STRING_LENGTH)
541 ; //XBell(Xdisplay, 100);
542 else
543 strcat(string, buffer);
544 }
545 else if (keysym >= XK_F1 && keysym <= XK_F35 && buffer != NULL &&
546 strlen(string) + strlen(buffer) < MAX_POPUP_STRING_LENGTH)
547 strcat(string, buffer);
548 else if ((keysym == XK_BackSpace) || (keysym == XK_Delete)) {
549 if ((length = strlen(string)) > 0) {
550 string[length - 1] = NULL;
551 XClearWindow(Xdisplay, pop_win);
552 }
553 else
554 ; //XBell(Xdisplay, 100);
555 }
556 redraw_text = 1;
557 buffer[1] = NULL;
558 break;
559 case MappingNotify:
560 XRefreshKeyboardMapping(&report);
561 break;
562 default:
563 /* All events selected by StructureNotifyMask
564 * except ConfigureNotify are thrown away here,
565 * since nothing is done with them */
566 break;
567 } /* End switch */
568 if (redraw_text) {
569 strptr = string;
570 if (XTextWidth(TermWin.font,string,strlen(string)) > thumbs_widths[i])
571 {
572 while (strptr-string < strlen(string) -1 &&
573 XTextWidth(TermWin.font,strptr,strlen(strptr)) > thumbs_widths[i])
574 strptr++;
575 XClearWindow(Xdisplay, pop_win);
576 }
577
578 XDrawString(Xdisplay, pop_win, gc, start_x,
579 start_y, strptr, strlen(strptr));
580 }
581 } /* End while */
582 if (strlen(string)) {
583 free(TermWin.vts[page].tab_title);
584 TermWin.vts[page].tab_title=strdup(string);
585 compute_size_of_thumbs();
586 for(i=page; i <= TermWin.right_page; i++) {
587 set_thumb_num(i,(i == page)? 1 : 0);
588 }
589 blank_between_right_and_buttons();
590 }
591 }
592 #endif
593
activate_page_num(int page)594 void activate_page_num(int page) {
595 if(page == TermWin.active_page)
596 {
597 #ifdef DRAW_THUMBBAR
598 retitle_page(page);
599 #endif
600 return;
601 }
602
603 TermWin.last_active_page = TermWin.active_page;
604 TermWin.vts[TermWin.last_active_page].bMapped = 0;
605 TermWin.active_page = page;
606 TermWin.vts[page].bMapped = 1;
607
608 #ifdef DRAW_THUMBBAR
609 if( TermWin.left_page <= page && page <= TermWin.right_page) {
610 set_thumb_num(TermWin.active_page,1);
611 }
612
613 if( TermWin.left_page <= TermWin.last_active_page
614 && TermWin.last_active_page <= TermWin.right_page) {
615
616 set_thumb_num(TermWin.last_active_page,0);
617 }
618 #endif
619
620 XMapRaised(Xdisplay,TermWin.vts[TermWin.active_page].vt);
621 // XUnmapWindow(Xdisplay,TermWin.vts[TermWin.last_active_page].vt);
622 f_scr_refresh(TermWin.active_page,FAST_REFRESH);
623 DN_ALEXIS(1,(stderr,"active page is %d\n",TermWin.active_page));
624
625 #if defined(TRANSPARENT) || defined(BACKGROUND_IMAGE)
626 refresh_transparent_scrollbar();
627 #endif
628
629 }
630
resize_thumb_bar(XEvent * ev)631 void resize_thumb_bar(XEvent * ev) {
632 #ifdef DRAW_THUMBBAR
633 static int old_width = 0;
634 int x;
635 int i;
636
637 if(old_width == (ev->xconfigure).width )
638 return;
639
640 width = (ev->xconfigure).width;
641 //x = (width - (4*(BUTTON_SIZE+BUTTON_SPACE)+THUMB_SPACE)) / (THUMB_WIDTH+THUMB_SPACE);
642 x = width - (4*(BUTTON_SIZE+BUTTON_SPACE)+THUMB_SPACE);
643 for(i=0; x > THUMB_SPACE; i++) {
644 x -= thumbs_widths[i]+THUMB_SPACE;
645 }
646
647 DN_ALEXIS(1,(stderr,"resize_thumb_bar, x:%d\n",x));
648
649 if( (ev->xconfigure).width > old_width ) {
650
651 // bigger -> may be we can add thumbs
652 if(TermWin.last_page >= 0) {
653 TermWin.vts[TermWin.active_page].bMapped = 0;
654 TermWin.left_page = 0;
655 //TermWin.active_page = 0;
656 TermWin.vts[TermWin.active_page].bMapped = 1;
657 TermWin.right_page = min(i-1,TermWin.last_page);
658 }
659
660 XMoveResizeWindow(Xdisplay,TermWin.thumb_bar,0,0,(ev->xconfigure).width,TOP_SPACE);
661
662 } else if ((ev->xconfigure).width < old_width) {
663
664 // smaller -> may be we need to remove thumbs
665 if(TermWin.last_page >= 0) {
666 TermWin.vts[TermWin.active_page].bMapped = 0;
667 TermWin.left_page = 0;
668 //TermWin.active_page = 0;
669 TermWin.vts[TermWin.active_page].bMapped = 1;
670 TermWin.right_page = min(i-1,TermWin.last_page);
671 }
672
673 XMoveResizeWindow(Xdisplay,TermWin.thumb_bar,0,0,(ev->xconfigure).width,TOP_SPACE);
674
675 }
676
677 old_width = width;
678 #endif
679 }
680
681 #ifdef DRAW_THUMBBAR
dispatch_button_press(int x,int y,pid_t pid)682 void dispatch_button_press(int x,int y,pid_t pid) {
683 int z;
684 int but;
685 // int width = (2 * TermWin_internalBorder)+TermWin.width;
686
687 DN_ALEXIS(2,(stderr,"click in (%d,%d)\n",x,y));
688 but = -1;
689 /* let's decode where the user click
690 */
691 z = width-x;
692
693 if( z < 4*(BUTTON_SIZE+BUTTON_SPACE) && (z%(BUTTON_SIZE+BUTTON_SPACE)) > BUTTON_SPACE) {
694 but = z/(BUTTON_SIZE+BUTTON_SPACE);
695 DN_ALEXIS(1,(stderr,"click on button %d\n",but));
696 switch(but) {
697 case 0 : /* right shift */
698 page_right_shift(TermWin.right_page+1);
699 break;
700 case 1 : /* left shift */
701 printf("TermWin.left_page : %d\n",TermWin.left_page);
702 page_left_shift(TermWin.left_page-1);
703 break;
704 case 2 : /* delete the active vt */
705 destroy_page(TermWin.active_page,pid);
706 break;
707 case 3 : /* create a new vt*/
708 append_page(0);
709 break;
710 default :
711 break;
712 }
713
714 } else if ( x < THUMBS_PLACE && TermWin.last_page >= 0) {
715 int w = 0;
716 int i;
717 for(i=TermWin.left_page; w < x && i <= TermWin.right_page; i++) {
718 w += THUMB_SPACE + thumbs_widths[i];
719 }
720 if(w - THUMB_SPACE >= x) {
721
722 but = i-1;
723 DN_ALEXIS(2,(stderr,"click on tab %d\n",but));
724 activate_page_num(but);
725 }
726 }
727 }
728
thumb_bar_expose()729 void thumb_bar_expose() {
730 int i,j,x;
731 char title[TITLE_TAB_MAX+1];
732
733 DN_ALEXIS(1,(stderr,"thumb_bar_expose [%d,%d,%d]\n",TermWin.left_page,TermWin.active_page,TermWin.right_page));
734
735 /* draw the buttons */
736 for(i=NB_XPM; i >= 1; i--) {
737 XPutImage(Xdisplay,TermWin.thumb_bar,TermWin.thumbGC,img[4-i],
738 0,0,
739 width-(i*(BUTTON_SIZE+BUTTON_SPACE)),THUMB_PAD,
740 BUTTON_SIZE,BUTTON_SIZE);
741
742 }
743
744 if( TermWin.last_page >= 0 ) {
745 /* redraw the thumbs and the bevels
746 */
747 for(i=TermWin.left_page,x=THUMB_SPACE; i <= TermWin.right_page; i++,x += thumbs_widths[i-1]+THUMB_SPACE) {
748
749 if( i == TermWin.active_page) {
750
751 XFillRectangle(Xdisplay,TermWin.thumb_bar,light_greyGC,
752 x,THUMB_PAD,thumbs_widths[i],THUMB_HEIGHT);
753
754 /* left vertical line */
755 XDrawLine(Xdisplay,TermWin.thumb_bar,whiteGC,
756 x,THUMB_PAD,x,THUMB_PAD+THUMB_HEIGHT-1);
757
758 } else {
759 XFillRectangle(Xdisplay,TermWin.thumb_bar,dark_greyGC,
760 x,THUMB_PAD,thumbs_widths[i],THUMB_HEIGHT);
761 }
762
763 /* top horizontal line*/
764 XDrawLine(Xdisplay,TermWin.thumb_bar,whiteGC,
765 x,THUMB_PAD,x+thumbs_widths[i]-1,THUMB_PAD);
766
767 /* right vertical line */
768 XDrawLine(Xdisplay,TermWin.thumb_bar,dark_grey2GC,
769 x + thumbs_widths[i],THUMB_PAD,
770 x + thumbs_widths[i],THUMB_PAD+THUMB_HEIGHT-1);
771 }
772
773 x = width_beetween(0,TermWin.active_page-1);
774 /* draw a line under thumbs */
775 XDrawLine(Xdisplay,TermWin.thumb_bar,whiteGC,0,
776 THUMB_PAD+THUMB_HEIGHT/*TOP_SPACE-1*/,
777 x+THUMB_SPACE,
778 THUMB_PAD+THUMB_HEIGHT/*TOP_SPACE-1*/);
779
780 XDrawLine(Xdisplay,TermWin.thumb_bar,light_greyGC,
781 x+THUMB_SPACE,
782 THUMB_PAD+THUMB_HEIGHT,
783 x+thumbs_widths[TermWin.active_page],
784 THUMB_PAD+THUMB_HEIGHT);
785
786 XDrawLine(Xdisplay,TermWin.thumb_bar,whiteGC,
787 x+thumbs_widths[TermWin.active_page]+THUMB_SPACE,
788 THUMB_PAD+THUMB_HEIGHT/*TOP_SPACE-1*/,
789 width,THUMB_PAD+THUMB_HEIGHT/*TOP_SPACE-1*/);
790
791 // part for the text
792 x=THUMB_SPACE;
793 for(i=TermWin.left_page; i <= TermWin.right_page; i++) {
794 sprintf(title,"%s",TermWin.vts[i].tab_title);
795 XDrawString(Xdisplay, TermWin.thumb_bar,
796 TermWin.thumbGC,x+10,
797 20,title,strlen(title));
798 x += THUMB_SPACE + thumbs_widths[i];
799 }
800 }
801
802 XMapWindow(Xdisplay,TermWin.thumb_bar);
803 }
804 #endif
805
create_thumb_bar(XSizeHints * szHint)806 void create_thumb_bar(XSizeHints *szHint) {
807 #ifdef DRAW_THUMBBAR
808 #ifdef HAVE_LIBXPM
809 XpmAttributes xpm_attr;
810 XpmColorSymbol xpm_color_sym = {"background",NULL,None};
811 #endif
812
813 XColor color;
814 XGCValues gcvalue;
815 Pixel darkPixel;
816 int i;
817 int res;
818
819 DN_ALEXIS(1,(stderr,"Building tumb_bar\n"));
820 compute_size_of_thumbs();
821
822 width = szHint->width;
823 /* create the light_greyGC */
824 color.red = 0xd300;
825 color.green = 0xd300;
826 color.blue = 0xdd00;
827 XAllocColorNew(Xdisplay,Xcmap,&color);
828 gcvalue.foreground = darkPixel = color.pixel;
829
830 #ifdef HAVE_LIBXPM
831 // this defined the transparent color of the pixmap
832 xpm_color_sym.pixel = color.pixel;
833 #endif
834 /* create the window of the thumb bar */
835 TermWin.thumb_bar = XCreateSimpleWindow(
836 Xdisplay,TermWin.parent,
837 0,0,szHint->width,TOP_SPACE,0,
838 2,color.pixel
839 );
840 /* to have transparent notebook ...
841 */
842 /*
843 #if defined(TRANSPARENT)
844 if( Options & Opt_transparent ) {
845 XSetWindowBackgroundPixmap(Xdisplay, TermWin.thumb_bar,ParentRelative);
846 }
847 #endif
848 */
849
850 light_greyGC = XCreateGC(Xdisplay, TermWin.thumb_bar,GCForeground , &gcvalue);
851
852
853 /* create the dark_grey2GC */
854 color.red = 0x8300;
855 color.green = 0x8300;
856 color.blue = 0x9300;
857 XAllocColorNew(Xdisplay,Xcmap,&color);
858 gcvalue.foreground = color.pixel;
859
860 dark_grey2GC = XCreateGC(Xdisplay, TermWin.thumb_bar,GCForeground , &gcvalue);
861
862 /* create the dark_greyGC */
863 color.red = 0xc100;
864 color.green = 0xc100;
865 color.blue = 0xcc00;
866 XAllocColorNew(Xdisplay,Xcmap,&color);
867 gcvalue.foreground = color.pixel;
868 dark_greyGC = XCreateGC(Xdisplay, TermWin.thumb_bar,GCForeground , &gcvalue);
869
870 XSelectInput(Xdisplay,TermWin.thumb_bar,
871 ExposureMask|ButtonPressMask|ButtonReleaseMask);
872
873 /* create the GC for the thumb window
874 */
875 gcvalue.foreground = PixColors[Color_Black];
876 gcvalue.background = PixColors[Color_Grey25];
877 gcvalue.line_width = 1;
878 TermWin.thumbGC = XCreateGC(Xdisplay, TermWin.thumb_bar,
879 GCForeground | GCBackground | GCLineWidth, &gcvalue);
880 XSetFont(Xdisplay, TermWin.thumbGC,TermWin.font->fid);
881
882 gcvalue.foreground = WhitePixelOfScreen(DefaultScreenOfDisplay(Xdisplay));
883 whiteGC = XCreateGC(Xdisplay, TermWin.thumb_bar,
884 GCForeground , &gcvalue);
885
886 /* now, create the buttons
887 */
888 #ifdef HAVE_LIBXPM
889 xpm_attr.colorsymbols = &xpm_color_sym; /* to have transparent background */
890 xpm_attr.numsymbols = 1;
891 xpm_attr.visual = Xvisual;
892 xpm_attr.colormap = Xcmap;
893 xpm_attr.depth = Xdepth;
894 xpm_attr.closeness = 30000;
895 xpm_attr.valuemask = XpmVisual | XpmColormap |
896 XpmDepth | XpmCloseness | XpmReturnPixels | XpmColorSymbols;
897 #endif
898
899 for(i=0; i < NB_XPM; i++) {
900 #ifdef HAVE_LIBXPM
901 /* create the icon for the button ... */
902 res = XpmCreateImageFromData(Xdisplay,xpm_name[i],
903 &img[i],&img_mask[i],&xpm_attr);
904 DN_ALEXIS(2,(stderr,"XpmCreateImageFromData returns %d\n",res));
905 #else
906
907 img[i] = XCreateImage(Xdisplay,Xvisual,Xdepth,
908 ZPixmap,0,
909 xpm_name[i],
910 BUTTON_SIZE,BUTTON_SIZE,8,7);
911 if(img[i] == NULL) {
912 fprintf(stderr,"Null XImage\n");
913 }
914
915 #endif
916
917 /* and display it ! */
918 XPutImage(Xdisplay,TermWin.thumb_bar,TermWin.thumbGC,img[i],
919 0,0,
920 width-((4-i)*(BUTTON_SIZE+BUTTON_SPACE)),THUMB_PAD,
921 BUTTON_SIZE,BUTTON_SIZE);
922
923 }
924
925 XMapWindow(Xdisplay,TermWin.thumb_bar);
926 #endif
927 }
928
page_shift(unsigned int direction,int x)929 void page_shift(unsigned int direction,int x) {
930 DN_ALEXIS(2,(stderr,"page_shift(%d,%d)\n",direction,x));
931 switch(direction) {
932 case 0 :
933 page_left_shift(x);
934 break;
935 case 1 :
936 page_right_shift(x);
937 break;
938 default : DN_ALEXIS(1,(stderr,"direction not supported\n"));
939 }
940 }
941