1head	1.1;
2access;
3symbols;
4locks
5	juhana:1.1; strict;
6comment	@ * @;
7
8
91.1
10date	98.10.28.21.50.29;	author juhana;	state Exp;
11branches;
12next	;
13
14
15desc
16@@
17
18
191.1
20log
21@Initial revision
22@
23text
24@/*
25 * xwave - an interactive audio player, recorder, editor
26 * for the XWindow System
27 *
28 * Copyright (C) 1996 Kai Kollmorgen
29 * (kkollmor@@informatik.uni-rostock.de)
30 *
31 *
32 * This program is free software; you can redistribute it and/or modify
33 * it under the terms of the GNU General Public License as published by
34 * the Free Software Foundation; either version 2 of the License, or
35 * (at your option) any later version.
36 *
37 * This program is distributed in the hope that it will be useful,
38 * but WITHOUT ANY WARRANTY; without even the implied warranty of
39 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
40 * GNU General Public License for more details.
41 *
42 * You should have received a copy of the GNU General Public License
43 * along with this program; if not, write to the Free Software
44 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
45 *
46 */
47
48#include <stdio.h>
49#include <stdlib.h>
50#include <unistd.h>
51#include <fcntl.h>
52#include <dirent.h>
53
54#include <X11/Xlib.h>		/* GC and other */
55#include <X11/Intrinsic.h>	/* Intrinsics Definitions */
56#include <X11/StringDefs.h>	/* Standard Name-String definitions */
57#include <X11/Shell.h>
58#include <X11/Xatom.h>
59#include <X11/cursorfont.h>
60
61#include <X11/Xaw/Box.h>	/*Athena Widget Set */
62#include <X11/Xaw/Form.h>
63#include <X11/Xaw/Simple.h>
64#include <X11/Xaw/Label.h>
65#include <X11/Xaw/Scrollbar.h>
66
67#include "types.h"
68#include "xwave.h"
69#include "menu.h"
70#include "button.h"
71#include "status.h"
72#include "audio.h"
73#include "audio_file.h"
74#include "misc.h"
75#include "xwave_widget.h"
76#include "sample_settings.h"
77#include "graphics.h"
78#include "record_dialog.h"
79#include "filebrowse.h"
80#include "fileop.h"
81#include "bitmaps/xwave.xbm"
82#include "bitmaps/canvas.xbm"
83
84static void setwave_action (Widget w,Next_Wave *nw, XEvent *event,
85			    Boolean *flg);
86static void delete_toplevel (Widget w,Main_Data *md, XEvent *event,
87			     Boolean *flg);
88static void reparent_canvas (Widget w,Next_Wave *nw, XReparentEvent *event,
89			     Boolean *flg);
90static void reparent_toplevel (Widget w,Main_Data *md, XReparentEvent *event,
91			       Boolean *flg);
92static void pop_canvas_menu (Widget w,Main_Data *md, XButtonEvent *event,
93			     Boolean *flg);
94static void usage();
95static void XtWarningHandler(String msg);
96
97/* in this struct we have all data about open files */
98
99Main_Data *MD;
100
101AppResources app_resources;
102
103static Cursor previewC[3];
104static Atom delwin=None,protocols=None,focus=None;
105static char **load_files;
106static int no_load_files;
107
108static XtResource resources[] = {
109      {"version","Version",XtRString,sizeof(String),
110	    XtOffsetOf(AppResources,version),XtRImmediate,"0.0"},
111      {"device","Device",XtRString,sizeof(String),
112	    XtOffsetOf(AppResources,device),XtRImmediate,"/dev/dsp"},
113      {"wdir","WDir",XtRString,sizeof(String),
114	    XtOffsetOf(AppResources,wdir),XtRImmediate,"."},
115      {"tdir","TDir",XtRString,sizeof(String),
116	    XtOffsetOf(AppResources,tdir),XtRImmediate,"/tmp"},
117      {"wavemainfgl","WaveMainFgl",XtRString,sizeof(String),
118	    XtOffsetOf(AppResources,wavemainfgl),XtRImmediate,"blue"},
119      {"wavemainfgr","WaveMainFgr",XtRString,sizeof(String),
120	    XtOffsetOf(AppResources,wavemainfgr),XtRImmediate,"red"},
121      {"markcolor","MarkColor",XtRString,sizeof(String),
122	    XtOffsetOf(AppResources,markcolor),XtRImmediate,"green"},
123      {"default_recname","Default_recname",XtRString,sizeof(String),
124	    XtOffsetOf(AppResources,default_recname),XtRImmediate,"record"},
125      {"default_newname","Default_newname",XtRString,sizeof(String),
126	    XtOffsetOf(AppResources,default_newname),XtRImmediate,"unnamed"},
127      {"playlinefg","PlayLineFg",XtRString,sizeof(String),
128	    XtOffsetOf(AppResources,playlinefg),XtRImmediate,"black"},
129      {"err_overwrite","Err_overwrite",XtRString,sizeof(String),
130	    XtOffsetOf(AppResources,err_overwrite),XtRImmediate,"not defined"},
131      {"err_openfile","Err_openfile",XtRString,sizeof(String),
132	    XtOffsetOf(AppResources,err_openfile),XtRImmediate,"not defined"},
133      {"err_fileinuse","Err_fileinuse",XtRString,sizeof(String),
134	    XtOffsetOf(AppResources,err_fileinuse),XtRImmediate,"not defined"},
135      {"err_modified","Err_modified",XtRString,sizeof(String),
136	    XtOffsetOf(AppResources,err_modified),XtRImmediate,"not defined"},
137      {"err_16bit","Err_16bit",XtRString,sizeof(String),
138	    XtOffsetOf(AppResources,err_16bit),XtRImmediate,"not defined"},
139      {"err_stereo","Err_stereo",XtRString,sizeof(String),
140	    XtOffsetOf(AppResources,err_stereo),XtRImmediate,"not defined"},
141      {"err_44khz","Err_44khz",XtRString,sizeof(String),
142	    XtOffsetOf(AppResources,err_44khz),XtRImmediate,"not defined"},
143      {"err_44khzstereo","Err_44khzstereo",XtRString,sizeof(String),
144	    XtOffsetOf(AppResources,err_44khzstereo),
145	    XtRImmediate,"not defined"},
146      {"err_permissions","Err_permissions",XtRString,sizeof(String),
147	    XtOffsetOf(AppResources,err_permissions),
148	    XtRImmediate,"not defined"},
149      {"err_notsupported","Err_notsupported",XtRString,sizeof(String),
150	    XtOffsetOf(AppResources,err_notsupported),XtRImmediate,
151	    "not defined"},
152      {"err_wrongformat","Err_wrongformat",XtRString,sizeof(String),
153	    XtOffsetOf(AppResources,err_wrongformat),XtRImmediate,
154	    "not defined"},
155      {"err_mem","Err_mem",XtRString,sizeof(String),
156	    XtOffsetOf(AppResources,err_mem),XtRImmediate,"not defined"},
157      {"err_input","Err_input",XtRString,sizeof(String),
158	    XtOffsetOf(AppResources,err_input),XtRImmediate,"not defined"},
159      {"err_bg","Err_bg",XtRString,sizeof(String),
160	    XtOffsetOf(AppResources,err_bg),XtRImmediate,"not defined"},
161      {"err_nohome","Err_nohome",XtRString,sizeof(String),
162	    XtOffsetOf(AppResources,err_nohome),XtRImmediate,"not defined"},
163      {"err_notmp","Err_notmp",XtRString,sizeof(String),
164	    XtOffsetOf(AppResources,err_notmp),XtRImmediate,"not defined"},
165      {"err_notimplement","Err_notimplement",XtRString,sizeof(String),
166	    XtOffsetOf(AppResources,err_notimplement),XtRImmediate,
167	    "not defined"},
168      {"default_ext","Default_ext",XtRString,sizeof(String),
169	    XtOffsetOf(AppResources,default_ext),XtRImmediate,"*wav"},
170      {"maxmem","MaxMem",XtRInt,sizeof(int),
171	    XtOffsetOf(AppResources,maxmem),XtRImmediate,(XtPointer)1000},
172      {"cv_maxpoints","CV_Maxpoints",XtRInt,sizeof(int),
173	    XtOffsetOf(AppResources,cv_maxpoints),XtRImmediate,(XtPointer)10},
174      {"default_ftype","Default_ftype",XtRInt,sizeof(int),
175	    XtOffsetOf(AppResources,default_comp),XtRImmediate,(XtPointer)0},
176      {"default_comp","Default_comp",XtRInt,sizeof(int),
177	    XtOffsetOf(AppResources,default_comp),XtRImmediate,(XtPointer)0},
178      {"doubleplay","DoublePlay",XtRBoolean,sizeof(Boolean),
179	    XtOffsetOf(AppResources,doubleplay),XtRImmediate,(XtPointer)True},
180      {"raisecanvas","RaiseCanvas",XtRBoolean,sizeof(Boolean),
181	    XtOffsetOf(AppResources,raisecanvas),XtRImmediate,(XtPointer)True}
182};
183
184static XrmOptionDescRec options[] = {
185      { "-device",".device",XrmoptionSepArg,(XtPointer)"/dev/dsp"},
186      { "-wdir",".wdir",XrmoptionSepArg,(XtPointer)"."},
187      { "-maxmem",".maxmem",XrmoptionSepArg,(XtPointer)1000}
188};
189
190
191static String fallback_resources[]={
192    NULL,
193};
194
195static void usage()
196{
197    printf("XWave Version %s:\n\n",VERSION);
198    printf("-?, -h, -help, display this help.\n");
199    printf("-device, the play/rec device (usually /dev/dsp).\n");
200    printf("-wdir, set working directory.\n");
201    printf("-maxmem, max. amount of memory to load whole sample in memory.\n");
202    printf("If sample is greater than maxmem, we do everything on HDD.\n");
203    exit(1);
204}
205
206void XtWarningHandler(String msg)
207{
208    if (strncmp(msg,"XtRemoveGrab",strlen("XtRemoveGrab"))==0) return;
209    if (MD!=NULL)
210      warn_popup(MD->mw->form,msg);
211    else printf("%s\n",msg);
212}
213
214
215void main (int argc, char *argv[])
216{
217    XtAppContext context;
218    Widget toplevel,form,widget,graph;
219    Pixmap xwIcon;
220    XGCValues xgcv;
221    Dimension width,height;
222    Display *dpy;
223    XSetWindowAttributes wattr;
224
225   /*
226#if defined (_LITTLE_ENDIAN) || BYTE_ORDER == LITTLE_ENDIAN
227    printf("little_endian\n");
228#endif
229#if defined (_BIG_ENDIAN) || BYTE_ORDER == BIG_ENDIAN
230    printf("big_endian\n");
231#endif
232    */
233
234   MD=NULL;
235    toplevel = XtVaAppInitialize (&context,
236				  "XWave",
237				  options, XtNumber(options),
238				  &argc, argv,
239				  fallback_resources,
240				  NULL);
241
242    XtGetApplicationResources(toplevel,(XtPointer)&app_resources,
243			      resources,XtNumber(resources),NULL,0);
244
245    if (argc>1) {
246	int i;
247	if (strcmp(argv[1],"-?")==0) usage();
248	if (strcmp(argv[1],"-h")==0) usage();
249	if (strcmp(argv[1],"-help")==0) usage();
250	if (strcmp(argv[1],"-wdir")==0) usage();
251	if (strcmp(argv[1],"-maxmem")==0) usage();
252	if (strcmp(argv[1],"-device")==0) usage();
253	no_load_files=argc-1;
254	load_files=(char **) XtCalloc(sizeof(char**),argc);
255	for (i=1;i<argc;i++) {
256	    load_files[i-1]=argv[i];
257	}
258    }
259
260    if (strcmp(app_resources.version,"0.0")==0) {
261	initwarn_popup(toplevel,NORESOURCE);
262    }
263
264    if (strcmp(app_resources.version,VERSION)!=0) {
265	initwarn_popup(toplevel,WRONGRESOURCE);
266    }
267
268    XtAppSetWarningHandler(context,(XtErrorHandler) XtWarningHandler);
269    dpy=XtDisplay(toplevel);
270
271    /*
272     XSynchronize(dpy,TRUE);
273    */
274    /* alloc mem for Main_Data (this is global) */
275
276    if ((MD=calloc(sizeof(Main_Data),1))==NULL) {
277	initwarn_popup(toplevel,app_resources.err_mem);
278	exit(-1);
279    }
280    MD->mb=calloc(sizeof(Main_Bool),1);
281    MD->mg=calloc(sizeof(Main_Graphic),1);
282    MD->mw=calloc(sizeof(Main_Widget),1);
283    MD->cd=calloc(sizeof(Clip_Data),1);
284    if ((MD->mb==NULL)||(MD->mg==NULL)||(MD->mw==NULL)||(MD->cd==NULL)) {
285	initwarn_popup(toplevel,app_resources.err_mem);
286	exit(-1);
287    }
288    MD->nw=NULL;
289    MD->wd=NULL;
290    if ((MD->cd->wd=calloc(sizeof(Wave_Data),1))==NULL) {
291	initwarn_popup(toplevel,app_resources.err_mem);
292	exit(-1);
293    }
294    if ((MD->cd->wd->name=
295	 calloc(strlen(app_resources.tdir)+strlen(CLIPFILE)+1,1))==NULL) {
296	initwarn_popup(toplevel,app_resources.err_mem);
297	exit(-1);
298    }
299    sprintf(MD->cd->wd->name,"%s/%s",app_resources.tdir,CLIPFILE);
300
301    MD->mg->pixmap=None;
302    MD->maxmem=app_resources.maxmem * 1024;
303    if ((MD->mg->fbuf=(ushort*) malloc(MAXUSHORT))==NULL)  {
304	initwarn_popup(toplevel,app_resources.err_mem);
305	exit(-1);
306    }
307
308    /* get environment variables */
309
310    if ((MD->home=getenv(HOME_ENV))==NULL) {
311	initwarn_popup(toplevel,app_resources.err_nohome);
312	exit(-1);
313    }
314#ifdef sun
315    if (getenv(AUDIODEV_ENV)!=NULL) app_resources.device=getenv(AUDIODEV_ENV);
316#endif
317    /* set the tmp directory, should really have permissions to write here */
318    if (!can_write(app_resources.tdir)) {
319	if (can_write(TMP)) {
320	    if (strlen(app_resources.tdir)>=strlen(TMP))
321	      strcpy(app_resources.tdir,TMP);
322	    else app_resources.tdir=XtNewString(TMP);
323	} else {
324	    if (can_write(MD->home)) app_resources.tdir=MD->home;
325	    else {
326		initwarn_popup(toplevel,app_resources.err_notmp);
327		exit(-1);
328	    }
329	}
330    }
331    check_audio(MD->mb);
332    if (!MD->mb->canplay) app_resources.device=XtNewString("no device");
333
334    MD->no=0;
335    MD->mb->playing=False;
336    MD->mb->exposing=False;
337    MD->mb->isclip=False;
338
339    form = MW ("main_form",formWidgetClass,toplevel,NULL);
340    MD->mw->form=form;
341
342    widget= MW ("menu_form",formWidgetClass,form,
343		XtNtop,XawChainTop,XtNbottom,XawChainTop,
344		XtNleft,XawChainLeft,XtNright,XawChainRight,
345		NULL);
346
347    create_topmenu(widget);
348
349    widget=MW ("main_line",formWidgetClass,form,
350	       XtNfromVert,widget,XtNborderWidth,2,
351	       XtNtop,XawChainTop,XtNbottom,XawChainTop,
352	       XtNleft,XawChainLeft,XtNright,XawChainRight,
353	       NULL);
354
355    widget=MW ("border_form",formWidgetClass,form,
356	       XtNfromVert,widget,XtNborderWidth,0,
357	       XtNtop,XawChainTop,XtNbottom,XawChainTop,
358	       XtNleft,XawChainLeft,XtNright,XawChainLeft,
359	       NULL);
360
361    create_button(widget);
362
363    graph=MW ("main_graph",simpleWidgetClass,form,
364	      XtNfromVert,widget,XtNheight,PREVIEWHEIGHT,
365	      XtNtop,XawChainBottom,XtNbottom,XawChainBottom,NULL);
366
367    MD->mw->graph=graph;
368    xgcv.foreground=ConvertColor(graph,app_resources.wavemainfgl);
369    MD->mg->gcl=XtGetGC(MD->mw->graph,GCForeground, &xgcv);
370    xgcv.foreground=ConvertColor(graph,app_resources.wavemainfgr);
371    MD->mg->gcr=XtGetGC(MD->mw->graph,GCForeground, &xgcv);
372    xgcv.foreground=ConvertColor(graph,app_resources.markcolor);
373    xgcv.function=GXxor;
374    MD->mg->markgc=XtGetGC(MD->mw->graph,GCForeground|GCFunction,&xgcv);
375    xgcv.foreground=ConvertColor(graph,app_resources.playlinefg);
376    MD->mg->playgc=XtGetGC(MD->mw->graph,GCForeground, &xgcv);
377
378    XtVaGetValues(MD->mw->form,XtNcursor,&previewC[CURSOR_DEFAULT],NULL);
379    previewC[CURSOR_MARK]=XCreateFontCursor(dpy,XC_sb_h_double_arrow);
380    previewC[CURSOR_CLOCK]=XCreateFontCursor(dpy,XC_watch);
381
382    widget=MW ("status_form",formWidgetClass,form,
383	       XtNfromVert,graph,XtNborderWidth,0,
384	       XtNtop,XawChainBottom,XtNbottom,XawChainBottom,
385	       XtNleft,XawChainLeft,XtNright,XawChainRight,
386	       NULL);
387
388    create_status(widget);
389
390    /* create ATOM WM_DELETE_WINDOW and WM_TAKEFOCUS, this is for the DELETE
391     * MenuItem of WINDOWMANAGERS
392     * the Properties are only set, if an REPARENT EVENT occurs
393     * most of the WM use this to set an own window (i hope)
394     */
395
396    delwin=XInternAtom(dpy, "WM_DELETE_WINDOW", TRUE);
397    focus=XInternAtom(dpy, "WM_TAKE_FOCUS", TRUE);
398    protocols = XInternAtom(dpy, "WM_PROTOCOLS", TRUE);
399
400    XtAddEventHandler(toplevel, StructureNotifyMask, FALSE,
401		      (XtEventHandler)reparent_toplevel, (XtPointer) MD);
402
403    create_canvas_menu(toplevel,MD->mw);
404
405    XtRealizeWidget(toplevel);
406
407    /* create the file_dialog datas, now we can popup file_dialog very fast */
408    create_file_dialog(toplevel);
409
410    /* create the sample_dialog data */
411    create_sample_dialog(toplevel);
412
413    /* create the record_dialog data */
414    create_record_dialog(toplevel);
415
416    /* set the icon for main window */
417    xwIcon = XCBFD(dpy,XtWindow(form),(char *)xwave_bits,
418		   xwave_width, xwave_height);
419
420    /* set min,max width and height and icon */
421    XtVaSetValues(toplevel,XtNiconPixmap,xwIcon,NULL);
422    XtVaGetValues(toplevel,XtNheight,&height,XtNwidth,&width,NULL);
423    XtVaSetValues(toplevel,XtNminWidth,width,XtNmaxHeight,height,XtNminHeight,
424		  height,NULL);
425
426    XtAddEventHandler(graph, ExposureMask, FALSE,
427		      (XtEventHandler)expose_action, (XtPointer) MD);
428    XtAddEventHandler(graph, StructureNotifyMask, FALSE,
429		      (XtEventHandler)config_action, (XtPointer) MD);
430    XtAddEventHandler(graph, Button1MotionMask, FALSE,
431		      (XtEventHandler)mark_action, (XtPointer) MD);
432    XtAddEventHandler(graph, ButtonPressMask, FALSE,
433		      (XtEventHandler)buttonp_action, (XtPointer) MD);
434    XtAddEventHandler(graph, ButtonReleaseMask, FALSE,
435		      (XtEventHandler)buttonr_action, (XtPointer) MD);
436
437    /* if server can backing store, we want backing store */
438    wattr.backing_store=DoesBackingStore(DefaultScreenOfDisplay(dpy));
439    XChangeWindowAttributes(dpy,XtWindow(graph),CWBackingStore,&wattr);
440
441    XtAppMainLoop(context);
442}
443
444void new_canvas(Widget w,Next_Wave *nw)
445{
446    Widget popup,form;
447    Pixmap cwIcon;
448    static XtTranslations trans;
449    XGCValues xgcv;
450    Dimension width,height;
451    Display *dpy;
452    XSetWindowAttributes wattr;
453
454    trans= XtParseTranslationTable("<Btn3Down>: XtMenuPopup(cv_menu)");
455    popup=XtVaCreatePopupShell(nw->wd->name,topLevelShellWidgetClass,w,NULL);
456
457    nw->cw->popup=popup;
458    nw->cg->pixmap=None;
459
460    form  = MW ("cv_main_form",formWidgetClass,popup,
461		XtNresizable,TRUE,
462		XtNborderWidth,0,
463		NULL);
464
465
466    nw->cw->graph= MW ("cv_graph",simpleWidgetClass,form,
467		       XtNtranslations, trans,
468		       XtNtop,XawChainTop,XtNbottom,XawChainBottom,
469		       XtNleft,XawChainLeft,XtNright,XawChainRight,
470		       NULL);
471
472    nw->cw->scroll = MW ("cv_pos_scroll", scrollbarWidgetClass,form,
473			 XtNfromVert,nw->cw->graph,
474			 XtNorientation,XtorientHorizontal,
475			 XtNtop,XawChainBottom,XtNbottom,XawChainBottom,
476			 XtNleft,XawChainLeft,XtNright,XawChainRight,
477			 NULL);
478
479    XtVaGetValues(nw->cw->graph,XtNwidth,&width,NULL);
480    XtVaSetValues(nw->cw->scroll,XtNwidth,width,NULL);
481
482    nw->cw->zscroll = MW ("cv_zoom_scroll", scrollbarWidgetClass,form,
483			  XtNfromHoriz,nw->cw->graph,
484			  XtNorientation,XtorientVertical,
485			  XtNtop,XawChainTop,XtNbottom,XawChainBottom,
486			  XtNleft,XawChainRight,XtNright,XawChainRight,NULL);
487
488    XtVaGetValues(nw->cw->graph,XtNheight,&height,NULL);
489    XtVaSetValues(nw->cw->zscroll,XtNheight,height,NULL);
490
491    xgcv.foreground=ConvertColor(nw->cw->graph,app_resources.wavemainfgl);
492    nw->cg->gcl=XtGetGC(nw->cw->graph,GCForeground, &xgcv);
493    xgcv.foreground=ConvertColor(nw->cw->graph,app_resources.wavemainfgr);
494    nw->cg->gcr=XtGetGC(nw->cw->graph,GCForeground, &xgcv);
495    xgcv.foreground=ConvertColor(nw->cw->graph,app_resources.markcolor);
496    xgcv.function=GXxor;
497    nw->cg->markgc=XtGetGC(nw->cw->graph,GCForeground|GCFunction,&xgcv);
498
499    XtAddEventHandler(popup, StructureNotifyMask, False,
500		      (XtEventHandler)reparent_canvas, (XtPointer) nw);
501
502    XtAddEventHandler(nw->cw->graph, ButtonPressMask|Button1MotionMask, False,
503		      (XtEventHandler)mark_canvas, (XtPointer) MD);
504
505    XtPopup(popup,XtGrabNone);
506
507    XtAddEventHandler(nw->cw->graph, ExposureMask, False,
508		      (XtEventHandler)expose_canvas, (XtPointer) MD);
509    XtAddEventHandler(nw->cw->graph, StructureNotifyMask, False,
510		      (XtEventHandler)config_canvas, (XtPointer) MD);
511
512    XtVaGetValues(popup,XtNheight,&height,XtNwidth,&width,NULL);
513    XtVaSetValues(popup,XtNminWidth,width/2,XtNminHeight,height/2,NULL);
514
515    XtAddCallback(nw->cw->scroll, XtNjumpProc, jump_canvas, (XtPointer) MD);
516    XtAddCallback(nw->cw->scroll, XtNscrollProc, scroll_canvas, (XtPointer) MD);
517
518    XtAddCallback(nw->cw->zscroll, XtNjumpProc, zjump_canvas, (XtPointer) MD);
519    XtAddCallback(nw->cw->zscroll, XtNscrollProc, zscroll_canvas,
520		  (XtPointer) MD);
521
522    XtAddEventHandler(nw->cw->graph, ButtonPressMask, False,
523		      (XtEventHandler)pop_canvas_menu, (XtPointer) MD);
524
525    /* if server can backing store, we want backing store */
526    dpy=XtDisplay(nw->cw->graph);
527    wattr.backing_store=DoesBackingStore(DefaultScreenOfDisplay(dpy));
528    XChangeWindowAttributes(dpy,XtWindow(nw->cw->graph),CWBackingStore,&wattr);
529
530    cwIcon = XCBFD(dpy,XtWindow(form),(char *)canvas_bits,
531		   canvas_width, canvas_height);
532    XtVaSetValues(popup,XtNiconPixmap,cwIcon,NULL);
533
534    add_menu_entry(nw);
535}
536
537static void setwave_action (Widget w,Next_Wave *nw, XEvent *event,
538			    Boolean *flg)
539{
540    XClientMessageEvent *cevent=(XClientMessageEvent*)event;
541    if (MD->mb->exposing) return;
542    if (cevent->type!=ClientMessage) return;
543    if (cevent->message_type==protocols && cevent->data.l[0]==focus)
544      set_actual_canvas(nw);
545    if (cevent->message_type==protocols && cevent->data.l[0]==delwin) {
546	if (MD->mb->playing) {
547	    warn_popup(w,"Stop playing to close file !");
548	    return;
549	}
550	close_call(w,MD,NULL);
551    }
552}
553
554void set_actual_canvas(Next_Wave *nw)
555{
556
557    if (MD->wd==nw->wd) return;
558    if (MD->mb->playing) return;
559
560    MD->wd=nw->wd;
561    MD->cw=nw->cw;
562    MD->cb=nw->cb;
563    MD->cg=nw->cg;
564    MD->mg->step=(float)MD->wd->tlength/(float)MD->mg->width;
565
566    if (app_resources.raisecanvas) window_order(nw->cw->popup,Above);
567
568    update_display(MD);
569    return;
570}
571
572static void reparent_canvas (Widget w,Next_Wave *nw, XReparentEvent *event,
573			     Boolean *flg)
574{
575    if (event->type!=ReparentNotify) return;
576
577    XtAddRawEventHandler(w, 0, True,
578			 (XtEventHandler)setwave_action, (XtPointer) nw);
579    if (delwin!=None || protocols!=None) {
580	XChangeProperty(XtDisplay(w), XtWindow(w),
581			protocols,XA_ATOM, 32, PropModeReplace,
582			(unsigned char *) &delwin, 1);
583    }
584    if (focus!=None || protocols!=None) {
585	XChangeProperty(XtDisplay(w), XtWindow(w),
586			protocols,XA_ATOM, 32, PropModeAppend,
587			(unsigned char *) &focus, 1);
588    }
589}
590
591static void reparent_toplevel (Widget w,Main_Data *md, XReparentEvent *event,
592			       Boolean *flg)
593{
594    Display *dpy=XtDisplay(w);
595    if (event->type!=ReparentNotify) return;
596
597    XtAddRawEventHandler(w, 0, TRUE,
598			 (XtEventHandler)delete_toplevel, (XtPointer) md);
599
600    if (delwin!=None || protocols!=None) {
601	XChangeProperty(dpy, XtWindow(w),
602			protocols,XA_ATOM, 32, PropModeReplace,
603			(unsigned char *) &delwin, 1);
604    }
605    md->mg->lpixmap=XCreatePixmap(dpy, XtWindow(md->mw->graph),1/*width*/,
606				  PREVIEWHEIGHT,
607				  DefaultDepth(dpy,DefaultScreen(dpy)));
608
609    if (no_load_files>0) {
610	int i,type;
611	for (i=0;i<no_load_files;i++) {
612	    fprintf(stderr,"Loading %s... ",load_files[i]);
613	    fflush(stderr);
614	    type=load_file(load_files[i],AF_NORAW,AF_COMP_UNDEFINED);
615	    switch (type) {
616	     case AF_ERROR:
617		fprintf(stderr,"error.\n");
618		break;
619	     case AF_RAW:
620		fprintf(stderr,"can't load raw files from cmdline !\n");
621		break;
622	     case AF_NOTSUPPORTED:
623		fprintf(stderr,"filetype not supported !\n");
624		break;
625	     default:
626		fprintf(stderr,"done.\n");
627		break;
628	    }
629	}
630    }
631    XtFree((char*)load_files);
632
633    update_status(md);
634
635    /* set working directory to wdir-Resource */
636    chdir(app_resources.wdir);
637    /*
638     if (XInternAtom(dpy, "_SUN_WM_PROTOCOLS", TRUE)!=None)
639     	warn_popup(w,"SUN WM present (olwm,olvwm), expect problems !");
640     */
641    if (DoesBackingStore(DefaultScreenOfDisplay(dpy))==NotUseful) {
642	warn_popup(w,"Your X-Server doesn't support BackingStore !\nThis will slow down the screen updates !");
643    }
644    if (!MD->mb->canplay) {
645	warn_popup(w,"Couldn't access audio device !\nNo play and record !");
646    }
647}
648
649static void delete_toplevel (Widget w,Main_Data *md, XEvent *event,
650			     Boolean *flg)
651{
652    XClientMessageEvent *cevent=(XClientMessageEvent*)event;
653    if (md->mb->exposing) return;
654    if (cevent->type!=ClientMessage) return;
655    if (cevent->message_type==protocols && cevent->data.l[0]==delwin)
656      if (md->mb->playing) {
657	  warn_popup(w,"Stop playing to quit !");
658	  return;
659      }
660    quit_call(w,md,NULL);
661}
662
663void set_cursor(Widget w,byte which)
664{
665    XtVaSetValues(w,XtNcursor,previewC[which],NULL);
666}
667
668void watch_cursor(bool state)
669{
670    Window win=XtWindow(FindWmShell(MD->mw->form));
671    Display *dpy=XtDisplay(MD->mw->form);
672    Next_Wave *nw=MD->nw;
673
674    if (state) {
675	XDefineCursor(dpy,win,previewC[CURSOR_CLOCK]);
676	while (nw!=NULL) {
677	    win=XtWindow(FindWmShell(nw->cw->popup));
678	    dpy=XtDisplay(nw->cw->popup);
679	    XDefineCursor(dpy,win,previewC[CURSOR_CLOCK]);
680	    nw=nw->nw;
681	}
682    } else {
683	XUndefineCursor(dpy,win);
684	while (nw!=NULL) {
685	    win=XtWindow(FindWmShell(nw->cw->popup));
686	    dpy=XtDisplay(nw->cw->popup);
687	    XUndefineCursor(dpy,win);
688	    nw=nw->nw;
689	}
690    }
691    XFlush(dpy);
692}
693
694static void pop_canvas_menu (Widget w,Main_Data *md, XButtonEvent *event,
695			     Boolean *flg)
696{
697    if (event->button==3) { /* right mbutton (3-chord-mouse) */
698	Screen *scr=XtScreen(w);
699	Position x,y;
700	Dimension width,height;
701
702	x=event->x_root;
703	y=event->y_root;
704	XtVaGetValues(md->mw->cmenu,XtNwidth,&width,XtNheight,&height,NULL);
705	if (y>scr->height-height) y-=y+height-scr->height;
706	else y-=10;
707	if (x<width/2) x=0;
708	else if (x<scr->width-width/2) x-=width/2;
709	else {
710	    width-=scr->width-x;
711	    x-=width;
712	}
713	XtVaSetValues(md->mw->cmenu,XtNx,x,XtNy,y,NULL);
714    }
715    if (!md->mb->playing) {
716	set_cmenu_state(CM_ZOOM,CM_COPY,md->wd->ismark);
717	set_cmenu_state(CM_PASTE_I,CM_PASTE_M,md->mb->isclip);
718    }
719}
720
721@
722