1 /*
2  * xwave - an interactive audio player, recorder, editor
3  * for the XWindow System
4  *
5  * Copyright (C) 1996 Kai Kollmorgen
6  * (kkollmor@informatik.uni-rostock.de)
7  *
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22  *
23  */
24 
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <dirent.h>
28 #include <sys/types.h>
29 #include <X11/Intrinsic.h>	/* Intrinsics Definitions */
30 #include <X11/StringDefs.h>	/* Standard Name-String definitions */
31 #include <X11/Shell.h>     	/* Shell Definitions */
32 
33 #include <X11/Xaw/MenuButton.h>	/* Athena Command Widget */
34 #include <X11/Xaw/SimpleMenu.h>
35 #include <X11/Xaw/SmeBSB.h>
36 #include <X11/Xaw/SmeLine.h>
37 #include <X11/Xaw/Command.h>
38 #include <X11/Xaw/Box.h>
39 #include <X11/Xaw/Label.h>
40 #include <X11/Xaw/List.h>
41 #include <X11/Xaw/Form.h>
42 #include <X11/Xaw/Viewport.h>
43 
44 #include "types.h"
45 #include "xwave.h"
46 #include "xwave_widget.h"
47 #include "fileop.h"
48 #include "edit.h"
49 #include "misc.h"
50 #include "menu.h"
51 #include "effects.h"
52 #include "button.h"
53 #include "help.h"
54 #include "graphics.h"
55 
56 #include "bitmaps/pullright.xbm"
57 
58 extern Main_Data *MD;
59 
60 static void destroy(Widget w, XtPointer data, XtPointer junk);
61 static void new_menu_bar(Widget w,TopMenuBar menu_bar, Bar_Widget *bw);
62 static void create_item(Widget parent, TopMenuItem item, Top_Widget *tw);
63 static void right_action(Widget w, XEvent *event, String *params,
64 			 Cardinal *nparams);
65 static void canvas_menu_activated(Widget w,XtPointer client_data,
66 				  XtPointer call_data);
67 static void setactual_cb(Widget w,XtPointer client_data,XtPointer call_data);
68 static void list_cb(Widget w,XtPointer client_data,XtPointer call_data);
69 static void separator(Widget w,bool add);
70 static void create_window_lister(Widget w);
71 static void open_list_cb(Widget w,XtPointer client_data,XtPointer call_data);
72 static void ca_cb(Widget w,XtPointer client_data,XtPointer call_data);
73 static Widget find_mentry(char *name);
74 
75 static Bar_Widget *BarWidget;
76 static Pixmap pullBitmap = None;
77 static Widget listpopup,wlist;
78 static int lcounter=0;
79 static Widget cm_widgets[CM_ALL];
80 static Next_Wave **lnw=NULL;
81 
82 static RightMenuItem items_paste[]={
83     MI_PULL("p_merge",TRUE,paste_merge_call),
84       MI_PULL("p_insert",TRUE,paste_insert_call),
85       MI_PULL("p_new",TRUE,paste_new_call)
86 };
87 
88 static RightMenuItem items_volume[]={
89     MI_PULL("v_abs",TRUE,abs_vol_call),
90       MI_PULL("v_env",TRUE,env_vol_call)
91 };
92 
93 static TopMenuItem items_file[]={
94     MI_SIMPLE("new",TRUE,new_call),
95       MI_SIMPLE("load",TRUE,load_call),
96       MI_SIMPLE("close",FALSE,close_call),
97       MI_SIMPLE("save",FALSE,save_call),
98       MI_SIMPLE("saveas",FALSE,saveas_call),
99       MI_LINE(),
100       MI_SIMPLE("quit",TRUE,quit_call)
101 };
102 
103 static TopMenuItem items_edit[]={
104     MI_SIMPLE("undo",FALSE,undo_call),
105       MI_LINE(),
106       MI_SIMPLE("cut",FALSE,cut_call),
107       MI_SIMPLE("copy",FALSE,copy_call),
108       MI_LINE(),
109       MI_RIGHT("paste",FALSE,NULL,XtNumber(items_paste),items_paste)
110 };
111 
112 static TopMenuItem items_effects[]=
113 {
114     MI_SIMPLE("echo",FALSE,echo_call),
115       MI_RIGHT("volume",FALSE,NULL,XtNumber(items_volume),items_volume),
116       MI_SIMPLE("reverse",FALSE,reverse_call),
117       MI_SIMPLE("swap",FALSE,swap_call),
118       MI_SIMPLE("props",FALSE,props_call)
119 };
120 
121 static TopMenuItem items_help[]={
122     MI_SIMPLE("about",TRUE,about_call),
123       MI_LINE(),
124       MI_SIMPLE("help",FALSE,help_call),
125 };
126 
127 static TopMenuBar menu_bar[]={
128       {"file",XtNumber(items_file),items_file},
129       {"edit",XtNumber(items_edit),items_edit},
130       {"effects",XtNumber(items_effects),items_effects},
131       {"windows",0,NULL},
132       {"help",XtNumber(items_help),items_help}
133 };
134 
canvas_menu_activated(Widget w,XtPointer client_data,XtPointer call_data)135 static void canvas_menu_activated(Widget w,XtPointer client_data,
136 				  XtPointer call_data)
137 {
138     int entry=(int) client_data;
139     switch (entry) {
140      case CM_PLAY:
141 	play_it(w,(XtPointer) MD,(XtPointer) NULL);
142 	break;
143      case CM_STOP:
144 	stop_it(w,(XtPointer) MD,(XtPointer) NULL);
145 	break;
146      case CM_ZOOM:
147 	zoom_canvas(MD);
148 	break;
149      case CM_CUT:
150 	cut_call(w,(XtPointer) MD,(XtPointer) NULL);
151 	break;
152      case CM_COPY:
153 	copy_call(w,(XtPointer) MD,(XtPointer) NULL);
154 	break;
155      case CM_PASTE_I:
156 	paste_insert_call(w,(XtPointer) MD,(XtPointer) NULL);
157 	break;
158      case CM_PASTE_M:
159 	paste_merge_call(w,(XtPointer) MD,(XtPointer) NULL);
160 	break;
161      case CM_CLOSE:
162 	close_call(w,(XtPointer) MD,(XtPointer) NULL);
163 	break;
164     }
165 }
166 
set_cmenu_state(int from,int to,bool state)167 void set_cmenu_state(int from, int to, bool state)
168 {
169     int i;
170     if (to>CM_ALL) to=CM_ALL;
171     if (from>CM_ALL) from=CM_ALL;
172 
173     for (i=from;i<=to;i++) {
174 	XtVaSetValues(cm_widgets[i],XtNsensitive,state,NULL);
175     }
176 }
177 
create_canvas_menu(Widget w,Main_Widget * mw)178 void create_canvas_menu(Widget w,Main_Widget *mw)
179 {
180     Widget mbox,mlabel;
181     static XtTranslations trans1,trans2;
182     char buf[15];
183     int i;
184 
185     trans1= XtParseTranslationTable("<BtnUp>: XtMenuPopdown(cv_menu)");
186     trans2= XtParseTranslationTable("<EnterWindow>: set()\n\
187 <LeaveWindow>: unset()\n\
188 <BtnUp>: set() XtMenuPopdown(cv_menu) notify() unset()");
189 
190     mw->cmenu=XtVaCreatePopupShell("cv_menu",overrideShellWidgetClass,
191                                    w,XtNtranslations, trans1,NULL);
192 
193     mbox=MW("cv_menu_box",boxWidgetClass,mw->cmenu,NULL);
194 
195     mlabel=MW("cv_menu_label",labelWidgetClass,mbox,NULL);
196 
197     for (i=0;i<=CM_ALL;i++) {
198 	sprintf(buf,"cv_menu_%d",i);
199 	cm_widgets[i]=MW(buf,commandWidgetClass,mbox,XtNtranslations,
200 			 trans2,NULL);
201 	XtAddCallback(cm_widgets[i],XtNcallback,canvas_menu_activated,
202 		      (XtPointer) i);
203     }
204 }
205 
206 
destroy(Widget w,XtPointer data,XtPointer junk)207 static void destroy(Widget w, XtPointer data, XtPointer junk)
208 {
209     XtFree((XtPointer)data);
210 }
211 
right_action(Widget w,XEvent * event,String * params,Cardinal * nparams)212 static void right_action(Widget w, XEvent *event, String *params,
213 			 Cardinal *nparams)
214 {
215     Dimension width,height;
216     int x,y;
217     Widget RightShell=NULL;
218     Bar_Widget *bw;
219     Top_Widget *tw;
220     Widget cw=XawSimpleMenuGetActiveEntry(w);
221 
222     if (cw == None || event->type != MotionNotify) return;
223 
224     x = event->xmotion.x;
225     y = event->xmotion.y;
226 
227     XtVaGetValues(w, XtNwidth, &width, XtNheight, &height, NULL);
228     if (x < 0 || x >= width || y < 0 || y >= height) return;
229 
230     /*
231      * Only the second half of the menu is sensitve to pulls
232      */
233     if (x < ((width / 2)+(width / 3))) return;
234 
235     bw=BarWidget;
236     while ((bw!=NULL)&&(RightShell==NULL)) {
237 	tw=bw->tops;
238 	while ((RightShell==NULL)&&(tw!=NULL)) {
239 	    if (tw->widget==cw) {
240 		RightShell=tw->shell;
241 		break;
242 	    }
243 	    if (tw->widget==cw) break;
244 	    tw=tw->next;
245 	}
246 	bw=bw->next;
247     }
248     if (RightShell==NULL) return;
249 
250     x = event->xmotion.x_root - 20;
251     y = event->xmotion.y_root - 20;
252 
253 
254     XtVaSetValues(RightShell, XtNx, x, XtNy, y, NULL);
255 
256     XtPopup(RightShell, XtGrabExclusive);
257 }
258 
new_menu_bar(Widget w,TopMenuBar menu_bar,Bar_Widget * bw)259 static void new_menu_bar(Widget w,TopMenuBar menu_bar, Bar_Widget *bw)
260 {
261     int i;
262     char name[20],menuname[20],*nm;
263     static Widget last_widget=None;
264     Top_Widget *tw=NULL;
265 
266     strcpy(name,menu_bar.name);
267     strcat(name,"_menu");
268     strcpy(menuname,name);
269 
270     nm = XtNewString(menuname);
271 
272     strcat(name,"_btn");
273 
274     bw->button = MW (name,menuButtonWidgetClass,w,
275 		     XtNfromHoriz,last_widget,
276 		     XtNmenuName, nm,
277 		     NULL);
278 
279     last_widget=bw->button;
280 
281     XtAddCallback(bw->button, XtNdestroyCallback, destroy, (XtPointer)nm);
282 
283     bw->widget = XtCreatePopupShell (menuname,
284 				     simpleMenuWidgetClass,
285 				     bw->button,
286 				     NULL,0);
287 
288     bw->tops=NULL;
289     if (menu_bar.nitems>0) {
290 	bw->tops=calloc(sizeof(Top_Widget),1);
291 	tw=bw->tops;
292 	create_item(bw->widget,menu_bar.items[0],tw);
293     }
294 
295     for (i=1;i<menu_bar.nitems;i++) {
296 	tw->next=calloc(sizeof(Top_Widget),1);
297 	tw=tw->next;
298 	create_item(bw->widget,menu_bar.items[i],tw);
299 	tw->next=NULL;
300     }
301 }
302 
create_item(Widget parent,TopMenuItem item,Top_Widget * tw)303 static void create_item(Widget parent, TopMenuItem item, Top_Widget *tw)
304 {
305     char name[20];
306     static XtTranslations trans1,trans2;
307     int i;
308     String nm=NULL;
309 
310     if (strlen(item.name)==0) {
311 	tw->widget= MW ("seperator",smeLineObjectClass,
312 			parent,
313 			NULL);
314     }
315     else {
316 	strcpy(name,item.name);
317 	strcat(name,"_item");
318 	if (item.nitems>0) {
319 	    Right_Widget *rw=NULL,*nrw=NULL;
320 
321 	    tw->widget = MW (name,smeBSBObjectClass,
322 			     parent,
323 			     XtNsensitive,item.sensitive,
324 			     XtNrightMargin, pullright_width,
325 			     XtNrightBitmap, pullBitmap,
326 			     NULL);
327 	    trans1 = XtParseTranslationTable("<BtnMotion>: highlight()\
328 popup_right_menu()");
329 	    trans2 = XtParseTranslationTable
330 	      ("<LeaveWindow>: unhighlight() MenuPopdown()\n\
331 <BtnUp>: notify() unhighlight() MenuPopdown()\n\
332 <BtnMotion>: highlight()");
333 
334 	    strcpy(name,item.name);
335 	    strcat(name,"_right");
336 	    tw->shell = XtVaCreatePopupShell(nm,
337 					     simpleMenuWidgetClass, parent,
338 					     XtNtranslations, trans2,
339 					     NULL);
340 	    XtAddCallback(tw->shell, XtNdestroyCallback, destroy,
341 			  (XtPointer)nm);
342 	    XtOverrideTranslations(parent, trans1);
343 
344 	    for (i = 0; i < item.nitems; i++) {
345 		strcpy(name,item.items[i].name);
346 		strcat(name,"_item");
347 		rw=calloc(sizeof(Right_Widget),1);
348 		rw->widget = MW (name,smeBSBObjectClass, tw->shell,
349 					NULL);
350 		XtAddCallback (rw->widget,XtNcallback,
351 			       item.items[i].callback,(XtPointer) MD);
352 		if (i==0) {
353 		    tw->right=rw;
354 		    nrw=rw;
355 		} else  {
356 		    nrw->next=rw;
357 		    nrw=rw;
358 		}
359 		rw->next=NULL;
360 	    }
361 	} else {
362 	    tw->widget = MW (name,smeBSBObjectClass,
363 			     parent,
364 			     XtNsensitive,item.sensitive,
365 			     NULL);
366 	    XtAddCallback (tw->widget,XtNcallback, item.callback,(XtPointer)MD);
367 	    tw->shell=NULL;
368 	}
369     }
370 }
371 
372 
create_topmenu(Widget w)373 void create_topmenu(Widget w)
374 {
375 
376     static XtActionsRec act={"popup_right_menu", (XtActionProc)right_action};
377     int i;
378     Bar_Widget *bw;
379 
380     pullBitmap = XCreateBitmapFromData(XtDisplay(w),
381 				       DefaultRootWindow(XtDisplay(w)),
382 				       (char *)pullright_bits,
383 				       pullright_width, pullright_height);
384 
385 
386     XtAppAddActions(XtWidgetToApplicationContext(w), &act, 1);
387 
388     /* alloc mem for top of all widgets in the list */
389 
390     if (XtNumber(menu_bar)>0) {
391 	bw=calloc(sizeof(Bar_Widget),1);
392 	BarWidget=bw;
393 	new_menu_bar(w,menu_bar[0],bw);
394     }
395     for (i=1;i<XtNumber(menu_bar);i++) {
396 	bw->next=calloc(sizeof(Bar_Widget),1);
397 	bw=bw->next;
398 	new_menu_bar(w,menu_bar[i],bw);
399 	bw->next=NULL;
400     }
401 
402     create_window_lister(w);
403 }
404 
menu_state(bool state)405 void menu_state(bool state)
406 {
407     int i;
408     Bar_Widget *bw;
409 
410     bw=BarWidget;
411     for (i=0;i<XtNumber(menu_bar);i++) {
412 	XtVaSetValues(bw->button,XtNsensitive,state,NULL);
413 	bw=bw->next;
414     }
415 }
416 
add_menu_entry(Next_Wave * nw)417 void add_menu_entry(Next_Wave *nw)
418 {
419     int i;
420     char name[]="window  ";
421     char *wname;
422     Bar_Widget *bw;
423     Top_Widget *tw;
424 
425     wname=nw->wd->name;
426     i=strlen(wname);
427     wname+=i;
428     while (*wname!='/') wname--;
429     wname++;
430 
431     bw=BarWidget;
432     for (i=0;i<XtNumber(menu_bar)-2;i++) bw=bw->next;
433 
434     tw=bw->tops;
435     i=0;
436     if (bw->tops==NULL) {
437 	bw->tops=calloc(sizeof(Top_Widget),1);
438 	XtVaSetValues(bw->button,XtNsensitive,True,NULL);
439 	separator(bw->widget,False);
440 	tw=bw->tops;
441     } else {
442 	i++;
443 	while (tw->next!=NULL) {
444 	    tw=tw->next;
445 	    i++;
446 	}
447 	if (i<=MAXWINDOWENTRIES) {
448 	    tw->next=calloc(sizeof(Top_Widget),1);
449 	    tw=tw->next;
450 	    tw->widget=NULL;
451 	}
452     }
453     tw->next=NULL;
454     tw->shell=NULL;
455 
456     strcat(name,itoa(i));
457 
458     if (i>=MAXWINDOWENTRIES) {
459 	String *list=NULL;
460 	lcounter++;
461 	if (tw->widget!=NULL) {
462 	    String *newlist;
463 	    Next_Wave **newlnw;
464 
465 	    XtVaGetValues(wlist,XtNlist,&list,NULL);
466 	    newlist=(String*)calloc(sizeof(String *), lcounter);
467 	    newlnw=(Next_Wave **)calloc(sizeof(Next_Wave*), lcounter);
468 	    for (i=0;i<lcounter-1;i++) {
469 		newlnw[i]=lnw[i];
470 		newlist[i]=XtNewString(newlnw[i]->wd->name);
471 	    }
472 	    newlist[lcounter-1]=XtNewString(nw->wd->name);
473 	    XawListChange(wlist,newlist,lcounter,0,True);
474 	    XtFree((char *)list);
475 	    XtFree((char *)lnw);
476 	    lnw=newlnw;
477 	    lnw[lcounter-1]=nw;
478 	    nw->cw->mentry=NULL;
479 	    return;
480 	}
481 	list=(String*)calloc(sizeof(String *), 1);
482 	list[0]=XtNewString(nw->wd->name);
483 	separator(bw->widget,True);
484 	XawListChange(wlist,list,1,0,True);
485 	tw->widget = MW ("morewin_item",smeBSBObjectClass,bw->widget,NULL);
486 	XtAddCallback (tw->widget,XtNcallback, open_list_cb,(XtPointer) nw);
487 	lnw=(Next_Wave **)XtCalloc(sizeof(Next_Wave*), lcounter);
488 	lnw[lcounter-1]=nw;
489 	nw->cw->mentry=NULL;
490 	return;
491     }
492 
493     tw->widget = MW (name,smeBSBObjectClass,
494 		     bw->widget,
495 		     XtNlabel,wname,
496 		     NULL);
497     XtAddCallback (tw->widget,XtNcallback, setactual_cb,(XtPointer) nw);
498     nw->cw->mentry=tw->widget;
499 }
500 
setactual_cb(Widget w,XtPointer client_data,XtPointer call_data)501 void setactual_cb(Widget w,XtPointer client_data,XtPointer call_data)
502 {
503     set_actual_canvas((Next_Wave *)client_data);
504 }
505 
open_list_cb(Widget w,XtPointer client_data,XtPointer call_data)506 void open_list_cb(Widget w,XtPointer client_data,XtPointer call_data)
507 {
508     popup_centered(listpopup);
509 }
510 
511 
remove_menu_entry(Next_Wave * nw)512 void remove_menu_entry(Next_Wave *nw)
513 {
514     int i;
515     Bar_Widget *bw;
516     Top_Widget *tw;
517     Top_Widget *lw;
518 
519     bw=BarWidget;
520     for (i=0;i<XtNumber(menu_bar)-2;i++) bw=bw->next;
521 
522     tw=lw=bw->tops;
523 
524     i=0;
525     while ((tw->next!=NULL)&&(tw->widget!=nw->cw->mentry)) {
526 	tw=tw->next;
527 	i++;
528     }
529 
530     if (tw->widget==nw->cw->mentry) {
531 	if (lcounter==0) {
532 	    if (i==0) {
533 		if (tw->next==NULL) {
534 		    separator(bw->widget,True);
535 		    XtVaSetValues(bw->button,XtNsensitive,False,NULL);
536 		    XtDestroyWidget(tw->widget);
537 		    XtFree((char*)tw);
538 		    bw->tops=NULL;
539 		    return;
540 		} else {
541 		    bw->tops=tw->next;
542 		    XtDestroyWidget(tw->widget);
543 		    XtFree((char*)tw);
544 		    return;
545 		}
546 	    } else {
547 		if (tw->next==NULL) {
548 		    XtDestroyWidget(tw->widget);
549 		    while (i-->1) lw=lw->next;
550 		    lw->next=NULL;
551 		    XtFree((char*)tw);
552 		    return;
553 		} else {
554 		    XtDestroyWidget(tw->widget);
555 		    while (i-->1) lw=lw->next;
556 		    lw->next=tw->next;
557 		    XtFree((char*)tw);
558 		    return;
559 		}
560 	    }
561 	} else {
562 	    String *newlist;
563 	    String *list=NULL;
564 	    char *wname;
565 	    Next_Wave *nnw,**newlnw;
566 
567 	    XtVaGetValues(wlist,XtNlist,&list,NULL);
568 	    lcounter--;
569 	    /* get last string in list */
570 	    wname=list[lcounter];
571 	    i=strlen(wname);
572 	    wname+=i;
573 	    while (*wname!='/') wname--;
574 	    wname++;
575 	    /* set menu label to gotten string */
576 	    XtVaSetValues(nw->cw->mentry,XtNlabel,wname,NULL);
577 	    /* get last Next_Wave from lnw (**Next_Wave) list */
578 	    nnw=lnw[lcounter];
579 	    nnw->cw->mentry=nw->cw->mentry;
580 	    XtRemoveCallback(nw->cw->mentry,XtNcallback,setactual_cb,(XtPointer) nw);
581 	    XtAddCallback (nnw->cw->mentry,XtNcallback, setactual_cb,(XtPointer) nnw);
582 	    if (lcounter==0) {
583 		XawListChange(wlist,NULL,0,0,True);
584 		XtFree((char *)list);
585 		tw=lw=bw->tops;
586 		while (tw->next!=NULL) {
587 		    lw=tw;
588 		    tw=tw->next;
589 		}
590 		XtDestroyWidget(tw->widget);
591 		XtFree((char*) tw);
592 		lw->next=NULL;
593 		separator(bw->widget,FALSE);
594 		XtFree((char *)lnw);
595 		return;
596 	    }
597 	    newlist=(String*)calloc(sizeof(String *), lcounter);
598 	    newlnw=(Next_Wave **)calloc(sizeof(Next_Wave*), lcounter);
599 	    for (i=0;i<lcounter;i++) {
600 		newlnw[i]=lnw[i];
601 		newlist[i]=XtNewString(newlnw[i]->wd->name);
602 	    }
603 	    XawListChange(wlist,newlist,lcounter,0,True);
604 	    XtFree((char *)list);
605 	    XtFree((char *)lnw);
606 	    lnw=newlnw;
607 	}
608 	return;
609     }
610 
611     if (lcounter>0) {
612 	String *newlist;
613 	String *list=NULL;
614 	Next_Wave **newlnw;
615 	int j;
616 
617 	XtVaGetValues(wlist,XtNlist,&list,NULL);
618 	lcounter--;
619 	if (lcounter==0) {
620 	    XawListChange(wlist,NULL,0,0,True);
621 	    XtFree((char *)list);
622 	    tw=lw=bw->tops;
623 	    while (tw->next!=NULL) {
624 		lw=tw;
625 		tw=tw->next;
626 	    }
627 	    XtDestroyWidget(tw->widget);
628 	    XtFree((char*) tw);
629 	    lw->next=NULL;
630 	    separator(bw->widget,FALSE);
631 	    XtFree((char *)lnw);
632 	    return;
633 	}
634 	newlist=(String*)calloc(sizeof(String *), lcounter);
635 	newlnw=(Next_Wave **)calloc(sizeof(Next_Wave*), lcounter);
636 	for (i=0,j=0;i<lcounter;i++,j++) {
637 	    if (lnw[j]==nw) j++;
638 	    newlnw[i]=lnw[j];
639 	    newlist[i]=XtNewString(newlnw[i]->wd->name);
640 	}
641 	XawListChange(wlist,newlist,lcounter,0,True);
642 	XtFree((char *)list);
643 	XtFree((char *)lnw);
644 	lnw=newlnw;
645 	return;
646     }
647 }
648 
separator(Widget w,bool add)649 void separator(Widget w,bool add)
650 {
651     static Widget sep=NULL;
652     if (add)  {
653 	sep = MW ("seperator",smeLineObjectClass,w,NULL);
654     } else {
655 	if (sep!=NULL) XtDestroyWidget(sep);
656     }
657 }
658 
create_window_lister(Widget w)659 void create_window_lister(Widget w)
660 {
661     Widget form,viewport,button;
662     static XtTranslations trans;
663 
664     listpopup=XtVaCreatePopupShell("Select Window",
665 				   transientShellWidgetClass,w,NULL);
666 
667     form  = MW ("wl_main_form",formWidgetClass,listpopup,
668 		XtNresizable,TRUE,
669 		XtNborderWidth,0,
670 		NULL);
671 
672     viewport = MW ("wl_main_vp",viewportWidgetClass,form,
673 		   XtNallowVert,TRUE,XtNallowHoriz,TRUE,XtNforceBars,False,
674 		   XtNtop,XawRubber,XtNbottom,XawRubber,
675 		   XtNleft,XawRubber,XtNright,XawRubber,NULL);
676 
677     trans=XtParseTranslationTable("#override\n\
678 <Btn1Up>(2) : Set() Notify()\n");
679 
680     wlist = MW ("wl_main_list",listWidgetClass,viewport,
681 		XtNdefaultColumns,1,
682 		XtNtranslations, trans,
683 		NULL);
684 
685     XtAddCallback (wlist, XtNcallback, list_cb, (XtPointer) wlist);
686 
687     button = MW ("wl_ok_btn",commandWidgetClass,form,
688 		 XtNfromVert,viewport,
689 		 XtNtop,XawChainBottom,XtNbottom,XawChainBottom,
690 		 XtNleft,XawChainLeft,XtNright,XawChainLeft,NULL);
691 
692     XtAddCallback (button, XtNcallback, list_cb,(XtPointer) wlist);
693 
694     button = MW ("wl_ca_btn",commandWidgetClass,form,
695 		 XtNfromVert,viewport,XtNfromHoriz,button,
696 		 XtNtop,XawChainBottom,XtNbottom,XawChainBottom,
697 		 XtNleft,XawChainLeft,XtNright,XawChainLeft,NULL);
698 
699     XtAddCallback (button, XtNcallback, ca_cb,(XtPointer) wlist);
700 
701     XtRealizeWidget(listpopup);
702 
703 }
704 
list_cb(Widget w,XtPointer client_data,XtPointer call_data)705 void list_cb(Widget w,XtPointer client_data,XtPointer call_data)
706 {
707     Widget shell;
708     XawListReturnStruct *item=XawListShowCurrent((Widget) client_data);
709     if (item->list_index==-1) return;
710     XawListUnhighlight((Widget) client_data);
711     shell=XtParent(w);
712     while (!XtIsShell(shell)) shell=XtParent(shell);
713     XtPopdown(shell);
714     set_actual_canvas(lnw[item->list_index]);
715 }
716 
ca_cb(Widget w,XtPointer client_data,XtPointer call_data)717 void ca_cb(Widget w,XtPointer client_data,XtPointer call_data)
718 {
719     Widget shell;
720     XawListUnhighlight((Widget) client_data);
721     shell=XtParent(w);
722     while (!XtIsShell(shell)) shell=XtParent(shell);
723     XtPopdown(shell);
724 }
725 
find_mentry(char * name)726 static Widget find_mentry(char *name)
727 {
728     int i,j,k;
729     Bar_Widget *bw;
730     Top_Widget *tw;
731     Right_Widget *rw;
732     TopMenuItem *tmit;
733     RightMenuItem *rmit;
734 
735     bw=BarWidget;
736     for (i=0;i<XtNumber(menu_bar);i++) {
737 	tmit=menu_bar[i].items;
738 	tw=bw->tops;
739 	for (j=0;tw!=NULL;j++) {
740 	    if (strcmp(tmit[j].name,name)==0) return(tw->widget);
741 	    if (tmit[j].nitems>0) {
742 		rw=tw->right;
743 		rmit=tmit[j].items;
744 		for (k=0;k<tmit[j].nitems;k++) {
745 		    if (strcmp(rmit[k].name,name)==0) return(rw->widget);
746 		    rw=rw->next;
747 		}
748 	    }
749 	    tw=tw->next;
750 	}
751 	bw=bw->next;
752     }
753     return(None);
754 }
755 
set_menu_state(int from,int to,bool state)756 void set_menu_state(int from, int to, bool state)
757 {
758     int i;Widget w;
759 
760     for (i=from;i<=to;i++) {
761 	switch (i) {
762 	 case M_SAVE:
763 	    if ((w=find_mentry("save"))!=None)
764 	      XtVaSetValues(w,XtNsensitive,state,NULL);
765 	    break;
766 	 case M_SAVEAS:
767 	    if ((w=find_mentry("saveas"))!=None)
768 	      XtVaSetValues(w,XtNsensitive,state,NULL);
769 	    break;
770 	 case M_CLOSE:
771 	    if ((w=find_mentry("close"))!=None)
772 	      XtVaSetValues(w,XtNsensitive,state,NULL);
773 	    break;
774 	 case M_CUT:
775 	    if ((w=find_mentry("cut"))!=None)
776 	      XtVaSetValues(w,XtNsensitive,state,NULL);
777 	    break;
778 	 case M_COPY:
779 	    if ((w=find_mentry("copy"))!=None)
780 	      XtVaSetValues(w,XtNsensitive,state,NULL);
781 	    break;
782 	 case M_PASTE:
783 	    if ((w=find_mentry("paste"))!=None)
784 	      XtVaSetValues(w,XtNsensitive,state,NULL);
785 	    break;
786 	 case M_ECHO:
787 	    if ((w=find_mentry("echo"))!=None)
788 	      XtVaSetValues(w,XtNsensitive,state,NULL);
789 	    break;
790 	 case M_VOLUME:
791 	    if ((w=find_mentry("volume"))!=None)
792 	      XtVaSetValues(w,XtNsensitive,state,NULL);
793 	    break;
794 	 case M_REVERSE:
795 	    if ((w=find_mentry("reverse"))!=None)
796 	      XtVaSetValues(w,XtNsensitive,state,NULL);
797 	    break;
798 	 case M_SWAP:
799 	    if ((w=find_mentry("swap"))!=None)
800 	      XtVaSetValues(w,XtNsensitive,state,NULL);
801 	    break;
802 	 case M_PROPS:
803 	    if ((w=find_mentry("props"))!=None)
804 	      XtVaSetValues(w,XtNsensitive,state,NULL);
805 	    break;
806 	 default:
807 	    return;
808 	}
809     }
810 }
811 
actual_menu_wname(Main_Data * md,char * name)812 void actual_menu_wname(Main_Data *md,char *name)
813 {
814     int i;
815     char *wname;
816 
817     if (lcounter==0) {
818 	wname=md->wd->name;
819 	i=strlen(wname);
820 	wname+=i;
821 	while (*wname!='/') wname--;
822 	wname++;
823 	XtVaSetValues(md->cw->mentry,XtNlabel,wname,NULL);
824     } else {
825 	String *list=NULL;
826 
827 	XtVaGetValues(wlist,XtNlist,&list,NULL);
828 	i=0;
829 	while (i<=lcounter) {
830 	    wname=list[i];
831 	    if (strcmp(wname,name)==0) break;
832 	    i++;
833 	}
834 	XtFree(list[i]);
835 	list[i]=XtNewString(md->wd->name);
836 	XtVaSetValues(wlist,XtNlist,list,NULL);
837     }
838 }
839