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