1 
2 #include <stdio.h>
3 #include <string.h>
4 #include <stdlib.h>
5 
6 #include <system_includes.h>
7 
8 #include "util.h"
9 #include "replay.h"
10 #include "gui.h"
11 #include "undo.h"
12 
13 extern struct ahx_tune       *curtune;
14 extern struct textbox         tbx[];
15 extern int32                  pref_maxundobuf;
16 
17 extern struct ahx_instrument *perf_lastinst;
18 extern int16                  insls_lastcuri;
19 extern int16                  inslsb_lastcuri;
20 extern int16                  posed_lastposnr;
21 extern int16                  trked_lastposnr;
22 extern struct rawbm mainbm;
23 
24 struct textbox *show_tbox;
25 uint32 mubsizes[] = { 0, 262144, 524288, 1048576, 2097152, 4194304 };
26 
27 /*****************************************************/
28 
free_undolists(struct ahx_tune * at)29 void free_undolists( struct ahx_tune *at )
30 {
31   struct undonode *tn, *nn;
32 
33   // Clear undo system lists
34   tn = (struct undonode *)IExec->GetHead(at->at_undolist);
35   while( tn )
36   {
37     nn = (struct undonode *)IExec->GetSucc(&tn->un_ln);
38     IExec->Remove( (struct Node *)tn );
39     IExec->FreeSysObject( ASOT_NODE, tn );
40     tn = nn;
41   }
42 
43   tn = (struct undonode *)IExec->GetHead(at->at_redolist);
44   while( tn )
45   {
46     nn = (struct undonode *)IExec->GetSucc(&tn->un_ln);
47     IExec->Remove( (struct Node *)tn );
48     IExec->FreeSysObject( ASOT_NODE, tn );
49     tn = nn;
50   }
51 
52   at->at_undomem = 0;
53 }
54 
clear_redolist(struct ahx_tune * at)55 void clear_redolist( struct ahx_tune *at )
56 {
57   struct undonode *tn, *nn;
58 
59   tn = (struct undonode *)IExec->GetHead(at->at_redolist);
60   while( tn )
61   {
62     nn = (struct undonode *)IExec->GetSucc(&tn->un_ln);
63     at->at_undomem -= tn->un_size;
64     IExec->Remove( (struct Node *)tn );
65     IExec->FreeSysObject( ASOT_NODE, tn );
66     tn = nn;
67   }
68 }
69 
trim_undolist(struct ahx_tune * at)70 void trim_undolist( struct ahx_tune *at )
71 {
72   struct undonode *un;
73 
74   if( mubsizes[pref_maxundobuf] == 0 ) return;
75 
76   while( at->at_undomem > mubsizes[pref_maxundobuf] )
77   {
78     un = (struct undonode *)IExec->RemHead( at->at_undolist );
79     if( !un )
80     {
81       // WTF?
82       clear_redolist( at );
83       at->at_undomem = 0;
84       return;
85     }
86 
87     at->at_undomem -= un->un_size;
88     IExec->FreeSysObject( ASOT_NODE, un );
89   }
90 }
91 
alloc_undonode(struct ahx_tune * at,uint32 size)92 struct undonode *alloc_undonode( struct ahx_tune *at, uint32 size )
93 {
94   struct undonode *un;
95 
96   un = (struct undonode *)allocnode(size);
97   if( !un ) return NULL;
98 
99   un->un_ln.ln_Succ = NULL;
100   un->un_ln.ln_Pred = NULL;
101   un->un_size = size;
102   at->at_undomem += size;
103   trim_undolist( at );
104   return un;
105 }
106 
107 /*****************************************************/
108 
setbefore_posregion(struct ahx_tune * at,int32 left,int32 pos,int32 chans,int32 rows)109 void setbefore_posregion( struct ahx_tune *at, int32 left, int32 pos, int32 chans, int32 rows )
110 {
111   int32 size;
112   int32 x, y, i;
113 
114   size = chans*rows*2;
115 
116   at->at_rem_pbleft  = left;
117   at->at_rem_pbpos   = pos;
118   at->at_rem_pbchans = chans;
119   at->at_rem_pbrows  = rows;
120 
121   i=0;
122   for( y=pos; y<(pos+rows); y++ )
123   {
124     for( x=left; x<(left+chans); x++ )
125     {
126       at->at_rem_posbuf[i++] = at->at_Positions[y].pos_Track[x];
127       at->at_rem_posbuf[i++] = at->at_Positions[y].pos_Transpose[x];
128     }
129   }
130 }
131 
setafter_posregion(struct ahx_tune * at,int32 left,int32 pos,int32 chans,int32 rows)132 void setafter_posregion( struct ahx_tune *at, int32 left, int32 pos, int32 chans, int32 rows )
133 {
134   struct undonode *un;
135   struct udat_pos_region *ud;
136   int32 x,y,i,size;
137 
138   // Ensure we're talking about the same region
139   if( ( left  != at->at_rem_pbleft ) ||
140       ( pos   != at->at_rem_pbpos ) ||
141       ( chans != at->at_rem_pbchans ) ||
142       ( rows  != at->at_rem_pbrows ) )
143     return;
144 
145   size = chans*rows*2;
146 
147   un = alloc_undonode( at, sizeof( struct undonode )+sizeof( struct udat_pos_region )+(size*2) );
148   if( !un ) return;
149 
150   ud         = (struct udat_pos_region *)&un[1];
151   ud->before = (uint8 *)&ud[1];
152   ud->after  = (uint8 *)&ud->before[size];
153 
154   un->un_type       = UNT_POS_REGION;
155   un->un_data       = ud;
156   ud->left          = left;
157   ud->pos           = pos;
158   ud->chans         = chans;
159   ud->rows          = rows;
160   ud->posnr         = at->at_PosNr;
161   ud->posed_curs    = at->at_posed_curs;
162   ud->curlch        = at->at_curlch;
163 
164   i=0;
165   for( y=pos; y<(pos+rows); y++ )
166   {
167     for( x=left; x<(left+chans); x++ )
168     {
169       ud->before[i]  = at->at_rem_posbuf[i];
170       ud->after[i++] = at->at_Positions[y].pos_Track[x];
171       ud->before[i]  = at->at_rem_posbuf[i];
172       ud->after[i++] = at->at_Positions[y].pos_Transpose[x];
173     }
174   }
175 
176   IExec->AddTail( at->at_undolist, (struct Node *)un );
177   clear_redolist( at );
178 }
179 
setbefore_track(struct ahx_tune * at,int32 trk)180 void setbefore_track( struct ahx_tune *at, int32 trk )
181 {
182   int32 i;
183 
184   for( i=0; i<64; i++ )
185     at->at_rem_track[i] = at->at_Tracks[trk][i];
186 }
187 
setafter_track(struct ahx_tune * at,int32 trk)188 void setafter_track( struct ahx_tune *at, int32 trk )
189 {
190   struct undonode *un;
191   struct udat_track *ud;
192   int32 i;
193 
194   un = alloc_undonode( at, sizeof( struct undonode )+sizeof( struct udat_track ) );
195   if( !un ) return;
196 
197   ud = (struct udat_track *)&un[1];
198   un->un_ln.ln_Succ = NULL;
199   un->un_ln.ln_Pred = NULL;
200   un->un_type       = UNT_TRACK;
201   un->un_data       = ud;
202   ud->track         = trk;
203   ud->posnr         = at->at_PosNr;
204   ud->notenr        = at->at_NoteNr;
205   ud->tracked_curs  = at->at_tracked_curs;
206   ud->curlch        = at->at_curlch;
207 
208   for( i=0; i<64; i++ )
209   {
210     ud->before[i] = at->at_rem_track[i];
211     ud->after[i]  = at->at_Tracks[trk][i];
212   }
213 
214   IExec->AddTail( at->at_undolist, (struct Node *)un );
215   clear_redolist( at );
216 }
217 
setbefore_string(struct ahx_tune * at,TEXT * ptr)218 void setbefore_string( struct ahx_tune *at, TEXT *ptr )
219 {
220   if( ptr == NULL ) return;
221   strcpy( at->at_rem_string, ptr );
222 }
223 
setafter_string(int32 which,struct ahx_tune * at,TEXT * ptr)224 void setafter_string( int32 which, struct ahx_tune *at, TEXT *ptr )
225 {
226   struct undonode *un;
227   struct udat_string *ud;
228 
229   if( ptr == NULL ) return;
230 
231   un = alloc_undonode( at, sizeof( struct undonode )+sizeof( struct udat_string )+strlen( ptr )+strlen( at->at_rem_string )+2 );
232   if( !un ) return;
233 
234   ud = (struct udat_string *)&un[1];
235   ud->before = (TEXT *)&ud[1];
236   ud->after  = &ud->before[strlen(at->at_rem_string)+1];
237 
238   un->un_ln.ln_Succ = NULL;
239   un->un_ln.ln_Pred = NULL;
240   un->un_type       = which;
241   un->un_data       = ud;
242   ud->ptr           = ptr;
243 
244   strcpy( ud->before, at->at_rem_string );
245   strcpy( ud->after,  ptr );
246 
247   switch( which )
248   {
249     case UNT_STRING_INSNAME:
250       ud->extra = at->at_curins;
251       break;
252   }
253 
254   IExec->AddTail( at->at_undolist, (struct Node *)un );
255   clear_redolist( at );
256 }
257 
setbefore_plist(struct ahx_tune * at,struct ahx_plsentry * ptr)258 void setbefore_plist( struct ahx_tune *at, struct ahx_plsentry *ptr )
259 {
260   int32 i;
261 
262   for( i=0; i<256; i++ )
263     at->at_rem_pls_Entries[i] = ptr[i];
264 }
265 
setafter_plist(struct ahx_tune * at,struct ahx_plsentry * ptr)266 void setafter_plist( struct ahx_tune *at, struct ahx_plsentry *ptr )
267 {
268   struct undonode *un;
269   struct udat_whole_plist *ud;
270   int32 i;
271 
272   un = alloc_undonode( at, sizeof( struct undonode )+sizeof( struct udat_whole_plist ) );
273   if( !un ) return;
274 
275   ud = (struct udat_whole_plist *)&un[1];
276   un->un_ln.ln_Succ = NULL;
277   un->un_ln.ln_Pred = NULL;
278   un->un_type       = UNT_PLE;
279   un->un_data       = ud;
280   ud->ptr           = ptr;
281   ud->insnum        = at->at_curins;
282 
283   for( i=0; i<256; i++ )
284   {
285     ud->before[i] = at->at_rem_pls_Entries[i];
286     ud->after[i]  = ptr[i];
287   }
288 
289   IExec->AddTail( at->at_undolist, (struct Node *)un );
290   clear_redolist( at );
291 }
292 
293 /*****************************************************/
294 
295 // Simple modifications
modify_env_w(struct ahx_tune * at,struct ahx_envelope * ptr,uint32 field,int16 new)296 void modify_env_w( struct ahx_tune *at, struct ahx_envelope *ptr, uint32 field, int16 new )
297 {
298   struct undonode *un;
299   struct udat_env_w *ud = NULL;
300   BOOL rembef;
301 
302   rembef = FALSE;
303 
304   // Check for strings of the same action
305   un = (struct undonode *)IExec->GetTail( at->at_undolist );
306   if( ( un != NULL ) &&
307       ( un->un_type == field ) &&
308       ( ((struct udat_env_w *)un->un_data)->ptr == ptr ) )
309   {
310     ud = (struct udat_env_w *)un->un_data;
311     ud->after = new;
312   } else {
313     un = alloc_undonode( at, sizeof( struct undonode )+sizeof( struct udat_env_w ) );
314     if( un )
315     {
316       ud = (struct udat_env_w *)&un[1];
317       un->un_ln.ln_Succ = NULL;
318       un->un_ln.ln_Pred = NULL;
319       un->un_type       = field;
320       un->un_data       = ud;
321       ud->ptr           = ptr;
322       ud->insnum        = at->at_curins;
323       ud->after         = new;
324 
325       IExec->AddTail( at->at_undolist, (struct Node *)un );
326       clear_redolist( at );
327       rembef = TRUE;
328     }
329   }
330 
331   switch( field )
332   {
333     case UNT_ENV_AFRAMES:
334       if( rembef ) ud->before = ptr->aFrames;
335       ptr->aFrames = new;
336       break;
337 
338     case UNT_ENV_AVOLUME:
339       if( rembef ) ud->before = ptr->aVolume;
340       ptr->aVolume = new;
341       break;
342 
343     case UNT_ENV_DFRAMES:
344       if( rembef ) ud->before = ptr->dFrames;
345       ptr->dFrames = new;
346       break;
347 
348     case UNT_ENV_DVOLUME:
349       if( rembef ) ud->before = ptr->dVolume;
350       ptr->dVolume = new;
351       break;
352 
353     case UNT_ENV_SFRAMES:
354       if( rembef ) ud->before = ptr->sFrames;
355       ptr->sFrames = new;
356       break;
357 
358     case UNT_ENV_RFRAMES:
359       if( rembef ) ud->before = ptr->rFrames;
360       ptr->rFrames = new;
361       break;
362 
363     case UNT_ENV_RVOLUME:
364       if( rembef ) ud->before = ptr->rVolume;
365       ptr->rVolume = new;
366       break;
367   }
368 }
369 
modify_ins_b(struct ahx_tune * at,struct ahx_instrument * ptr,uint32 field,uint8 new)370 void modify_ins_b( struct ahx_tune *at, struct ahx_instrument *ptr, uint32 field, uint8 new )
371 {
372   struct undonode *un;
373   struct udat_ins_b *ud = NULL;
374   BOOL rembef;
375 
376   rembef = FALSE;
377 
378   // Check for strings of the same action
379   un = (struct undonode *)IExec->GetTail( at->at_undolist );
380   if( ( un != NULL ) &&
381       ( un->un_type == field ) &&
382       ( ((struct udat_ins_b *)un->un_data)->ptr == ptr ) )
383   {
384     ud = (struct udat_ins_b *)un->un_data;
385     ud->after = new;
386   } else {
387     un = alloc_undonode( at, sizeof( struct undonode )+sizeof( struct udat_ins_b ) );
388     if( un )
389     {
390       ud = (struct udat_ins_b *)&un[1];
391       un->un_ln.ln_Succ = NULL;
392       un->un_ln.ln_Pred = NULL;
393       un->un_type       = field;
394       un->un_data       = ud;
395       ud->ptr           = ptr;
396       ud->insnum        = at->at_curins;
397       ud->after         = new;
398 
399       IExec->AddTail( at->at_undolist, (struct Node *)un );
400       clear_redolist( at );
401       rembef = TRUE;
402     }
403   }
404 
405   switch( field )
406   {
407     case UNT_INS_VOLUME:
408       if( rembef ) ud->before = ptr->ins_Volume;
409       ptr->ins_Volume = new;
410       break;
411 
412     case UNT_INS_WAVELENGTH:
413       if( rembef ) ud->before = ptr->ins_WaveLength;
414       ptr->ins_WaveLength = new;
415       break;
416 
417     case UNT_INS_FILTERLOWERLIMIT:
418       if( rembef ) ud->before = ptr->ins_FilterLowerLimit;
419       ptr->ins_FilterLowerLimit = new;
420       break;
421 
422     case UNT_INS_FILTERUPPERLIMIT:
423       if( rembef ) ud->before = ptr->ins_FilterUpperLimit;
424       ptr->ins_FilterUpperLimit = new;
425       break;
426 
427     case UNT_INS_FILTERSPEED:
428       if( rembef ) ud->before = ptr->ins_FilterSpeed;
429       ptr->ins_FilterSpeed = new;
430       break;
431 
432     case UNT_INS_SQUARELOWERLIMIT:
433       if( rembef ) ud->before = ptr->ins_SquareLowerLimit;
434       ptr->ins_SquareLowerLimit = new;
435       break;
436 
437     case UNT_INS_SQUAREUPPERLIMIT:
438       if( rembef ) ud->before = ptr->ins_SquareUpperLimit;
439       ptr->ins_SquareUpperLimit = new;
440       break;
441 
442     case UNT_INS_SQUARESPEED:
443       if( rembef ) ud->before = ptr->ins_SquareSpeed;
444       ptr->ins_SquareSpeed = new;
445       break;
446 
447     case UNT_INS_VIBRATODELAY:
448       if( rembef ) ud->before = ptr->ins_VibratoDelay;
449       ptr->ins_VibratoDelay = new;
450       break;
451 
452     case UNT_INS_VIBRATOSPEED:
453       if( rembef ) ud->before = ptr->ins_VibratoSpeed;
454       ptr->ins_VibratoSpeed = new;
455       break;
456 
457     case UNT_INS_VIBRATODEPTH:
458       if( rembef ) ud->before = ptr->ins_VibratoDepth;
459       ptr->ins_VibratoDepth = new;
460       break;
461 
462     case UNT_INS_HARDCUTRELEASE:
463       if( rembef ) ud->before = ptr->ins_HardCutRelease;
464       ptr->ins_HardCutRelease = new;
465       break;
466 
467     case UNT_INS_HARDCUTRELEASEFRAMES:
468       if( rembef ) ud->before = ptr->ins_HardCutReleaseFrames;
469       ptr->ins_HardCutReleaseFrames = new;
470       break;
471   }
472 }
473 
modify_ple_b(struct ahx_tune * at,struct ahx_instrument * ins,struct ahx_plsentry * ptr,uint32 field,int8 new)474 void modify_ple_b( struct ahx_tune *at, struct ahx_instrument *ins, struct ahx_plsentry *ptr, uint32 field, int8 new )
475 {
476   struct undonode *un;
477   struct udat_ple_b *ud = NULL;
478   BOOL rembef;
479 
480   rembef = FALSE;
481 
482   // Check for strings of the same action
483   un = (struct undonode *)IExec->GetTail( at->at_undolist );
484   if( ( un != NULL ) &&
485       ( un->un_type == field ) &&
486       ( ((struct udat_ple_b *)un->un_data)->ptr == ptr ) )
487   {
488     ud = (struct udat_ple_b *)un->un_data;
489     ud->after = new;
490   } else {
491     un = alloc_undonode( at, sizeof( struct undonode )+sizeof( struct udat_ple_b ) );
492     if( un )
493     {
494       ud = (struct udat_ple_b *)&un[1];
495       un->un_ln.ln_Succ = NULL;
496       un->un_ln.ln_Pred = NULL;
497       un->un_type       = field;
498       un->un_data       = ud;
499       ud->ptr           = ptr;
500       ud->pins          = ins;
501       ud->insnum        = at->at_curins;
502       ud->after         = new;
503       ud->ptop          = ins->ins_ptop;
504       ud->pcurx         = ins->ins_pcurx;
505       ud->pcury         = ins->ins_pcury;
506 
507       IExec->AddTail( at->at_undolist, (struct Node *)un );
508       clear_redolist( at );
509       rembef = TRUE;
510     }
511   }
512 
513   switch( field )
514   {
515     case UNT_PLE_NOTE:
516       if( rembef ) ud->before = ptr->ple_Note;
517       ptr->ple_Note = new;
518       break;
519 
520     case UNT_PLE_WAVEFORM:
521       if( rembef ) ud->before = ptr->ple_Waveform;
522       ptr->ple_Waveform = new;
523       break;
524 
525     case UNT_PLE_FX0:
526       if( rembef ) ud->before = ptr->ple_FX[0];
527       ptr->ple_FX[0] = new;
528       break;
529 
530     case UNT_PLE_FX1:
531       if( rembef ) ud->before = ptr->ple_FX[1];
532       ptr->ple_FX[1] = new;
533       break;
534 
535     case UNT_PLE_FXPARAM0:
536       if( rembef ) ud->before = ptr->ple_FXParam[0];
537       ptr->ple_FXParam[0] = new;
538       break;
539 
540     case UNT_PLE_FXPARAM1:
541       if( rembef ) ud->before = ptr->ple_FXParam[1];
542       ptr->ple_FXParam[1] = new;
543       break;
544   }
545 }
546 
modify_ple_w(struct ahx_tune * at,struct ahx_instrument * ins,struct ahx_plsentry * ptr,uint32 field,int16 new)547 void modify_ple_w( struct ahx_tune *at, struct ahx_instrument *ins, struct ahx_plsentry *ptr, uint32 field, int16 new )
548 {
549   struct undonode *un;
550   struct udat_ple_w *ud = NULL;
551   BOOL rembef;
552 
553   rembef = FALSE;
554 
555   // Check for strings of the same action
556   un = (struct undonode *)IExec->GetTail( at->at_undolist );
557   if( ( un != NULL ) &&
558       ( un->un_type == field ) &&
559       ( ((struct udat_ple_w *)un->un_data)->ptr == ptr ) )
560   {
561     ud = (struct udat_ple_w *)un->un_data;
562     ud->after = new;
563   } else {
564     un = alloc_undonode( at, sizeof( struct undonode )+sizeof( struct udat_ple_w ) );
565     if( un )
566     {
567       ud = (struct udat_ple_w *)&un[1];
568       un->un_ln.ln_Succ = NULL;
569       un->un_ln.ln_Pred = NULL;
570       un->un_type       = field;
571       un->un_data       = ud;
572       ud->ptr           = ptr;
573       ud->pins          = ins;
574       ud->insnum        = at->at_curins;
575       ud->after         = new;
576       ud->ptop          = ins->ins_ptop;
577       ud->pcurx         = ins->ins_pcurx;
578       ud->pcury         = ins->ins_pcury;
579 
580       IExec->AddTail( at->at_undolist, (struct Node *)un );
581       clear_redolist( at );
582       rembef = TRUE;
583     }
584   }
585 
586   switch( field )
587   {
588     case UNT_PLE_FIXED:
589       if( rembef ) ud->before = ptr->ple_Fixed;
590       ptr->ple_Fixed = new;
591       break;
592   }
593 }
594 
modify_pls_w(struct ahx_tune * at,struct ahx_plist * ptr,uint32 field,int16 new)595 void modify_pls_w( struct ahx_tune *at, struct ahx_plist *ptr, uint32 field, int16 new )
596 {
597   struct undonode *un;
598   struct udat_pls_w *ud = NULL;
599   BOOL rembef;
600 
601   rembef = FALSE;
602 
603   // Check for strings of the same action
604   un = (struct undonode *)IExec->GetTail( at->at_undolist );
605 
606   if( ( un != NULL ) &&
607       ( un->un_type == field ) &&
608       ( ((struct udat_pls_w *)un->un_data)->ptr == ptr ) )
609   {
610     ud = (struct udat_pls_w *)un->un_data;
611     ud->after = new;
612   } else {
613     un = alloc_undonode( at, sizeof( struct undonode )+sizeof( struct udat_pls_w ) );
614     if( un )
615     {
616       ud = (struct udat_pls_w *)&un[1];
617       un->un_ln.ln_Succ = NULL;
618       un->un_ln.ln_Pred = NULL;
619       un->un_type       = field;
620       un->un_data       = ud;
621       ud->ptr           = ptr;
622       ud->insnum        = at->at_curins;
623       ud->after         = new;
624 
625       IExec->AddTail( at->at_undolist, (struct Node *)un );
626       clear_redolist( at );
627       rembef = TRUE;
628     }
629   }
630 
631   switch( field )
632   {
633     case UNT_PLS_SPEED:
634       if( rembef ) ud->before = ptr->pls_Speed;
635       ptr->pls_Speed = new;
636       break;
637 
638     case UNT_PLS_LENGTH:
639       if( rembef ) ud->before = ptr->pls_Length;
640       ptr->pls_Length = new;
641       break;
642   }
643 }
644 
modify_stp_b(struct ahx_tune * at,struct ahx_step * ptr,uint32 field,int8 new)645 void modify_stp_b( struct ahx_tune *at, struct ahx_step *ptr, uint32 field, int8 new )
646 {
647   struct undonode *un;
648   struct udat_stp_b *ud = NULL;
649   BOOL rembef;
650 
651   rembef = FALSE;
652 
653   // Check for strings of the same action
654   un = (struct undonode *)IExec->GetTail( at->at_undolist );
655   if( ( un != NULL ) &&
656       ( un->un_type == field ) &&
657       ( ((struct udat_stp_b *)un->un_data)->ptr == ptr ) )
658   {
659     ud = (struct udat_stp_b *)un->un_data;
660     ud->after = new;
661   } else {
662     un = alloc_undonode( at, sizeof( struct undonode )+sizeof( struct udat_stp_b ) );
663     if( un )
664     {
665       ud = (struct udat_stp_b *)&un[1];
666       un->un_ln.ln_Succ = NULL;
667       un->un_ln.ln_Pred = NULL;
668       un->un_type       = field;
669       un->un_data       = ud;
670       ud->ptr           = ptr;
671       ud->after         = new;
672       ud->posnr         = at->at_PosNr;
673       ud->notenr         = at->at_NoteNr;
674       ud->tracked_curs  = at->at_tracked_curs;
675       ud->curlch        = at->at_curlch;
676 
677       IExec->AddTail( at->at_undolist, (struct Node *)un );
678       clear_redolist( at );
679       rembef = TRUE;
680     }
681   }
682 
683   switch( field )
684   {
685     case UNT_STP_NOTE:
686       if( rembef ) ud->before = ptr->stp_Note;
687       ptr->stp_Note = new;
688       break;
689 
690     case UNT_STP_INSTRUMENT:
691       if( rembef ) ud->before = ptr->stp_Instrument;
692       ptr->stp_Instrument = new;
693       break;
694 
695     case UNT_STP_FX:
696       if( rembef ) ud->before = ptr->stp_FX;
697       ptr->stp_FX = new;
698       break;
699 
700     case UNT_STP_FXB:
701       if( rembef ) ud->before = ptr->stp_FXb;
702       ptr->stp_FXb = new;
703       break;
704 
705     case UNT_STP_FXPARAM:
706       if( rembef ) ud->before = ptr->stp_FXParam;
707       ptr->stp_FXParam = new;
708       break;
709 
710     case UNT_STP_FXBPARAM:
711       if( rembef ) ud->before = ptr->stp_FXbParam;
712       ptr->stp_FXbParam = new;
713       break;
714   }
715 }
716 
modify_stp_w(struct ahx_tune * at,struct ahx_step * ptr,uint32 field,int16 new)717 void modify_stp_w( struct ahx_tune *at, struct ahx_step *ptr, uint32 field, int16 new )
718 {
719   struct undonode *un;
720   struct udat_stp_w *ud = NULL;
721   BOOL rembef;
722 
723   rembef = FALSE;
724 
725   // Check for strings of the same action
726   un = (struct undonode *)IExec->GetTail( at->at_undolist );
727   if( ( un != NULL ) &&
728       ( un->un_type == field ) &&
729       ( ((struct udat_stp_w *)un->un_data)->ptr == ptr ) )
730   {
731     ud = (struct udat_stp_w *)un->un_data;
732     ud->after = new;
733   } else {
734     un = alloc_undonode( at, sizeof( struct undonode )+sizeof( struct udat_stp_w ) );
735     if( un )
736     {
737       ud = (struct udat_stp_w *)&un[1];
738       un->un_ln.ln_Succ = NULL;
739       un->un_ln.ln_Pred = NULL;
740       un->un_type       = field;
741       un->un_data       = ud;
742       ud->ptr           = ptr;
743       ud->after         = new;
744       ud->posnr         = at->at_PosNr;
745       ud->notenr         = at->at_NoteNr;
746       ud->tracked_curs  = at->at_tracked_curs;
747       ud->curlch        = at->at_curlch;
748 
749       IExec->AddTail( at->at_undolist, (struct Node *)un );
750       clear_redolist( at );
751       rembef = TRUE;
752     }
753   }
754 
755   switch( field )
756   {
757     case UNT_STP_NOTEANDINS:
758       if( rembef ) ud->before = (ptr->stp_Note<<8)|(ptr->stp_Instrument);
759       ptr->stp_Note = new>>8;
760       ptr->stp_Instrument = new & 0xff;
761       break;
762 
763     case UNT_STP_FXANDPARAM:
764       if( rembef ) ud->before = (ptr->stp_FX<<8)|(ptr->stp_FXParam);
765       ptr->stp_FX = new>>8;
766       ptr->stp_FXParam = new & 0xff;
767       break;
768 
769     case UNT_STP_FXBANDPARAM:
770       if( rembef ) ud->before = (ptr->stp_FXb<<8)|(ptr->stp_FXbParam);
771       ptr->stp_FXb = new>>8;
772       ptr->stp_FXbParam = new & 0xff;
773       break;
774   }
775 }
776 
modify_pos_b(struct ahx_tune * at,struct ahx_position * ptr,int32 chan,uint32 field,int8 new)777 void modify_pos_b( struct ahx_tune *at, struct ahx_position *ptr, int32 chan, uint32 field, int8 new )
778 {
779   struct undonode *un;
780   struct udat_pos_b *ud = NULL;
781   BOOL rembef;
782 
783   rembef = FALSE;
784 
785   // Check for strings of the same action
786   un = (struct undonode *)IExec->GetTail( at->at_undolist );
787   if( ( un != NULL ) &&
788       ( un->un_type == field ) &&
789       ( ((struct udat_pos_b *)un->un_data)->chan == chan ) &&
790       ( ((struct udat_pos_b *)un->un_data)->ptr == ptr ) )
791   {
792     ud = (struct udat_pos_b *)un->un_data;
793     ud->after = new;
794   } else {
795     un = alloc_undonode( at, sizeof( struct undonode )+sizeof( struct udat_pos_b ) );
796     if( un )
797     {
798       ud = (struct udat_pos_b *)&un[1];
799       un->un_ln.ln_Succ = NULL;
800       un->un_ln.ln_Pred = NULL;
801       un->un_type       = field;
802       un->un_data       = ud;
803       ud->ptr           = ptr;
804       ud->chan          = chan;
805       ud->after         = new;
806       ud->posnr         = at->at_PosNr;
807       ud->posed_curs    = at->at_posed_curs;
808       ud->curlch        = at->at_curlch;
809 
810       IExec->AddTail( at->at_undolist, (struct Node *)un );
811       clear_redolist( at );
812       rembef = TRUE;
813     }
814   }
815 
816   switch( field )
817   {
818     case UNT_POS_TRACK:
819       if( rembef ) ud->before = ptr->pos_Track[chan];
820       ptr->pos_Track[chan] = new;
821       break;
822 
823     case UNT_POS_TRANS:
824       if( rembef ) ud->before = ptr->pos_Transpose[chan];
825       ptr->pos_Transpose[chan] = new;
826       break;
827   }
828 }
829 
modify_tune_b(struct ahx_tune * at,uint32 field,int8 new)830 void modify_tune_b( struct ahx_tune *at, uint32 field, int8 new )
831 {
832   struct undonode *un;
833   struct udat_tune_b *ud = NULL;
834   BOOL rembef;
835 
836   rembef = FALSE;
837 
838   // Check for strings of the same action
839   un = (struct undonode *)IExec->GetTail( at->at_undolist );
840   if( ( un != NULL ) &&
841       ( un->un_type == field ) )
842   {
843     ud = (struct udat_tune_b *)un->un_data;
844     ud->after = new;
845   } else {
846     un = alloc_undonode( at, sizeof( struct undonode )+sizeof( struct udat_tune_b ) );
847     if( un )
848     {
849       ud = (struct udat_tune_b *)&un[1];
850       un->un_ln.ln_Succ = NULL;
851       un->un_ln.ln_Pred = NULL;
852       un->un_type       = field;
853       un->un_data       = ud;
854       ud->after         = new;
855 
856       IExec->AddTail( at->at_undolist, (struct Node *)un );
857       clear_redolist( at );
858       rembef = TRUE;
859     }
860   }
861 
862   switch( field )
863   {
864     case UNT_TRACKLEN:
865       if( rembef ) ud->before = at->at_TrackLength;
866       at->at_TrackLength = new;
867       break;
868 
869     case UNT_CHANNELS:
870       if( rembef ) ud->before = at->at_Channels;
871       at->at_Channels = new;
872       break;
873 
874     case UNT_MIXGAIN:
875       if( rembef ) ud->before = at->at_mixgainP;
876       at->at_mixgainP = new;
877       break;
878 
879     case UNT_SPMUL:
880       if( rembef ) ud->before = at->at_SpeedMultiplier;
881       at->at_SpeedMultiplier = new;
882       break;
883   }
884 }
885 
modify_tune_w(struct ahx_tune * at,uint32 field,int16 new)886 void modify_tune_w( struct ahx_tune *at, uint32 field, int16 new )
887 {
888   struct undonode *un;
889   struct udat_tune_w *ud = NULL;
890   BOOL rembef;
891 
892   rembef = FALSE;
893 
894   // Check for strings of the same action
895   un = (struct undonode *)IExec->GetTail( at->at_undolist );
896   if( ( un != NULL ) &&
897       ( un->un_type == field ) )
898   {
899     ud = (struct udat_tune_w *)un->un_data;
900     ud->after = new;
901   } else {
902     un = alloc_undonode( at, sizeof( struct undonode )+sizeof( struct udat_tune_w ) );
903     if( un )
904     {
905       ud = (struct udat_tune_w *)&un[1];
906       un->un_ln.ln_Succ = NULL;
907       un->un_ln.ln_Pred = NULL;
908       un->un_type       = field;
909       un->un_data       = ud;
910       ud->after         = new;
911 
912       IExec->AddTail( at->at_undolist, (struct Node *)un );
913       clear_redolist( at );
914       rembef = TRUE;
915     }
916   }
917 
918   switch( field )
919   {
920     case UNT_POSITIONNR:
921       if( rembef ) ud->before = at->at_PositionNr;
922       at->at_PositionNr = new;
923       break;
924 
925     case UNT_RESTART:
926       if( rembef ) ud->before = at->at_Restart;
927       at->at_Restart = new;
928       break;
929 
930     case UNT_SUBSONGS:
931       if( rembef ) ud->before = at->at_SubsongNr;
932       at->at_SubsongNr = new;
933       break;
934   }
935 }
936 
modify_sspos(struct ahx_tune * at,int16 new)937 void modify_sspos( struct ahx_tune *at, int16 new )
938 {
939   struct undonode *un;
940   struct udat_subsongpos *ud;
941   BOOL rembef;
942 
943   if( at->at_curss == 0 ) return;
944 
945   rembef = FALSE;
946 
947   // Check for strings of the same action
948   un = (struct undonode *)IExec->GetTail( at->at_undolist );
949   if( ( un != NULL ) &&
950       ( un->un_type == UNT_SSPOS ) &&
951       ( ((struct udat_subsongpos *)un->un_data)->subsong == at->at_curss ) )
952   {
953     ud = (struct udat_subsongpos *)un->un_data;
954     ud->after = new;
955   } else {
956     un = alloc_undonode( at, sizeof( struct undonode )+sizeof( struct udat_subsongpos ) );
957     if( un )
958     {
959       ud = (struct udat_subsongpos *)&un[1];
960       un->un_ln.ln_Succ = NULL;
961       un->un_ln.ln_Pred = NULL;
962       un->un_type       = UNT_SSPOS;
963       un->un_data       = ud;
964       ud->after         = new;
965       ud->subsong       = at->at_curss;
966 
967       IExec->AddTail( at->at_undolist, (struct Node *)un );
968       clear_redolist( at );
969       rembef = TRUE;
970     }
971   }
972 
973   if( rembef ) ud->before = at->at_Subsongs[at->at_curss-1];
974   at->at_Subsongs[at->at_curss-1] = new;
975 }
976 
977 /*****************************************************/
978 
show_changed(struct ahx_tune * at,int32 wpanel,BOOL forceall)979 void show_changed( struct ahx_tune *at, int32 wpanel, BOOL forceall )
980 {
981   if( at != curtune ) return;
982 
983   if( wpanel == -1 ) return;
984 
985   if( wpanel != at->at_curpanel )
986   {
987     // Switch panel and render whole thing
988     at->at_curpanel = wpanel;
989     gui_render_tunepanel( TRUE );
990     return;
991   }
992 
993   // Try and be semi-smart about re-rendering parts of the panel
994   switch( wpanel )
995   {
996     case PN_TRACKER:
997       gui_render_tracker( forceall );
998       gui_render_inslist( forceall );
999       break;
1000 
1001     case PN_INSED:
1002       gui_render_perf( at, &at->at_Instruments[at->at_curins], forceall );
1003       gui_render_inslistb( forceall );
1004       break;
1005   }
1006 
1007   if( show_tbox )
1008   {
1009     gui_render_tbox( &mainbm, show_tbox );
1010     gui_render_tabs();
1011   }
1012 
1013   gui_set_various_things( at );
1014 }
1015 
undo(struct ahx_tune * at)1016 void undo( struct ahx_tune *at )
1017 {
1018   struct undonode         *un;
1019   struct udat_env_w       *env_w;
1020   struct udat_whole_plist *whole_plist;
1021   struct udat_ple_b       *ple_b;
1022   struct udat_ple_w       *ple_w;
1023   struct udat_pls_w       *pls_w;
1024   struct udat_ins_b       *ins_b;
1025   struct udat_track       *rtrk;
1026   struct udat_stp_b       *stp_b;
1027   struct udat_stp_w       *stp_w;
1028   struct udat_string      *rstr;
1029   struct udat_pos_b       *pos_b;
1030   struct udat_pos_region  *pos_r;
1031   int32 i, wpanel, x, y;
1032   BOOL forceall = FALSE;
1033 
1034   wpanel = -1;
1035   show_tbox = NULL;
1036 
1037   // Get last thing in the undo list
1038   un = (struct undonode *)IExec->RemTail( at->at_undolist );
1039   if( !un ) return;
1040 
1041   // Undo it!
1042   switch( un->un_type )
1043   {
1044     case UNT_POSITIONNR:
1045       at->at_PositionNr = ((struct udat_tune_w *)un->un_data)->before;
1046       wpanel = PN_TRACKER;
1047       break;
1048 
1049     case UNT_RESTART:
1050       at->at_Restart = ((struct udat_tune_w *)un->un_data)->before;
1051       wpanel = PN_TRACKER;
1052       break;
1053 
1054     case UNT_TRACKLEN:
1055       at->at_TrackLength = ((struct udat_tune_b *)un->un_data)->before;
1056       wpanel = PN_TRACKER;
1057       break;
1058 
1059     case UNT_SUBSONGS:
1060       at->at_SubsongNr = ((struct udat_tune_w *)un->un_data)->before;
1061       wpanel = PN_TRACKER;
1062       break;
1063 
1064     case UNT_SSPOS:
1065       at->at_curss = ((struct udat_subsongpos *)un->un_data)->subsong;
1066       at->at_Subsongs[at->at_curss-1] = ((struct udat_tune_b *)un->un_data)->before;
1067       wpanel = PN_TRACKER;
1068       break;
1069 
1070     case UNT_CHANNELS:
1071       at->at_Channels = ((struct udat_tune_b *)un->un_data)->before;
1072       at->at_curlch = 0;
1073       wpanel = PN_TRACKER;
1074       forceall = TRUE;
1075       break;
1076 
1077     case UNT_MIXGAIN:
1078       at->at_mixgainP = ((struct udat_tune_b *)un->un_data)->before;
1079       at->at_mixgain = (at->at_mixgainP*256)/100;
1080       wpanel = PN_TRACKER;
1081       break;
1082 
1083     case UNT_SPMUL:
1084       at->at_SpeedMultiplier = ((struct udat_tune_b *)un->un_data)->before;
1085       wpanel = PN_TRACKER;
1086       break;
1087 
1088     case UNT_ENV_AFRAMES:
1089       env_w = (struct udat_env_w *)un->un_data;
1090       env_w->ptr->aFrames = env_w->before;
1091       wpanel = PN_INSED;
1092       at->at_curins = env_w->insnum;
1093       break;
1094 
1095     case UNT_ENV_AVOLUME:
1096       env_w = (struct udat_env_w *)un->un_data;
1097       env_w->ptr->aVolume = env_w->before;
1098       wpanel = PN_INSED;
1099       at->at_curins = env_w->insnum;
1100       break;
1101 
1102     case UNT_ENV_DFRAMES:
1103       env_w = (struct udat_env_w *)un->un_data;
1104       env_w->ptr->dFrames = env_w->before;
1105       wpanel = PN_INSED;
1106       at->at_curins = env_w->insnum;
1107       break;
1108 
1109     case UNT_ENV_DVOLUME:
1110       env_w = (struct udat_env_w *)un->un_data;
1111       env_w->ptr->aVolume = env_w->before;
1112       wpanel = PN_INSED;
1113       at->at_curins = env_w->insnum;
1114       break;
1115 
1116     case UNT_ENV_SFRAMES:
1117       env_w = (struct udat_env_w *)un->un_data;
1118       env_w->ptr->sFrames = env_w->before;
1119       wpanel = PN_INSED;
1120       at->at_curins = env_w->insnum;
1121       break;
1122 
1123     case UNT_ENV_RFRAMES:
1124       env_w = (struct udat_env_w *)un->un_data;
1125       env_w->ptr->rFrames = env_w->before;
1126       wpanel = PN_INSED;
1127       at->at_curins = env_w->insnum;
1128       break;
1129 
1130     case UNT_ENV_RVOLUME:
1131       env_w = (struct udat_env_w *)un->un_data;
1132       env_w->ptr->rVolume = env_w->before;
1133       wpanel = PN_INSED;
1134       at->at_curins = env_w->insnum;
1135       break;
1136 
1137     case UNT_PLE:
1138       whole_plist = (struct udat_whole_plist *)un->un_data;
1139       for( i=0; i<256; i++ ) whole_plist->ptr[i] = whole_plist->before[i];
1140       wpanel = PN_INSED;
1141       perf_lastinst = NULL;
1142       at->at_curins = whole_plist->insnum;
1143       break;
1144 
1145     case UNT_PLE_NOTE:
1146       ple_b = (struct udat_ple_b *)un->un_data;
1147       ple_b->ptr->ple_Note = ple_b->before;
1148       ple_b->pins->ins_ptop  = ple_b->ptop;
1149       ple_b->pins->ins_pcurx = ple_b->pcurx;
1150       ple_b->pins->ins_pcury = ple_b->pcury;
1151       wpanel = PN_INSED;
1152       perf_lastinst = NULL;
1153       at->at_curins = ple_b->insnum;
1154       break;
1155 
1156     case UNT_PLE_WAVEFORM:
1157       ple_b = (struct udat_ple_b *)un->un_data;
1158       ple_b->ptr->ple_Waveform = ple_b->before;
1159       ple_b->pins->ins_ptop  = ple_b->ptop;
1160       ple_b->pins->ins_pcurx = ple_b->pcurx;
1161       ple_b->pins->ins_pcury = ple_b->pcury;
1162       wpanel = PN_INSED;
1163       perf_lastinst = NULL;
1164       at->at_curins = ple_b->insnum;
1165       break;
1166 
1167     case UNT_PLE_FIXED:
1168       ple_w = (struct udat_ple_w *)un->un_data;
1169       ple_w->ptr->ple_Fixed = ple_w->before;
1170       ple_w->pins->ins_ptop  = ple_w->ptop;
1171       ple_w->pins->ins_pcurx = ple_w->pcurx;
1172       ple_w->pins->ins_pcury = ple_w->pcury;
1173       wpanel = PN_INSED;
1174       perf_lastinst = NULL;
1175       at->at_curins = ple_w->insnum;
1176       break;
1177 
1178     case UNT_PLE_FX0:
1179       ple_b = (struct udat_ple_b *)un->un_data;
1180       ple_b->ptr->ple_FX[0] = ple_b->before;
1181       ple_b->pins->ins_ptop  = ple_b->ptop;
1182       ple_b->pins->ins_pcurx = ple_b->pcurx;
1183       ple_b->pins->ins_pcury = ple_b->pcury;
1184       wpanel = PN_INSED;
1185       perf_lastinst = NULL;
1186       at->at_curins = ple_b->insnum;
1187       break;
1188 
1189     case UNT_PLE_FX1:
1190       ple_b = (struct udat_ple_b *)un->un_data;
1191       ple_b->ptr->ple_FX[1] = ple_b->before;
1192       ple_b->pins->ins_ptop  = ple_b->ptop;
1193       ple_b->pins->ins_pcurx = ple_b->pcurx;
1194       ple_b->pins->ins_pcury = ple_b->pcury;
1195       wpanel = PN_INSED;
1196       perf_lastinst = NULL;
1197       at->at_curins = ple_b->insnum;
1198       break;
1199 
1200     case UNT_PLE_FXPARAM0:
1201       ple_b = (struct udat_ple_b *)un->un_data;
1202       ple_b->ptr->ple_FXParam[0] = ple_b->before;
1203       ple_b->pins->ins_ptop  = ple_b->ptop;
1204       ple_b->pins->ins_pcurx = ple_b->pcurx;
1205       ple_b->pins->ins_pcury = ple_b->pcury;
1206       wpanel = PN_INSED;
1207       perf_lastinst = NULL;
1208       at->at_curins = ple_b->insnum;
1209       break;
1210 
1211     case UNT_PLE_FXPARAM1:
1212       ple_b = (struct udat_ple_b *)un->un_data;
1213       ple_b->ptr->ple_FXParam[1] = ple_b->before;
1214       ple_b->pins->ins_ptop  = ple_b->ptop;
1215       ple_b->pins->ins_pcurx = ple_b->pcurx;
1216       ple_b->pins->ins_pcury = ple_b->pcury;
1217       wpanel = PN_INSED;
1218       perf_lastinst = NULL;
1219       at->at_curins = ple_b->insnum;
1220       break;
1221 
1222     case UNT_PLS_SPEED:
1223       pls_w = (struct udat_pls_w *)un->un_data;
1224       pls_w->ptr->pls_Speed = pls_w->before;
1225       wpanel = PN_INSED;
1226       at->at_curins = pls_w->insnum;
1227       break;
1228 
1229     case UNT_PLS_LENGTH:
1230       pls_w = (struct udat_pls_w *)un->un_data;
1231       pls_w->ptr->pls_Length = pls_w->before;
1232       wpanel = PN_INSED;
1233       at->at_curins = pls_w->insnum;
1234       break;
1235 
1236     case UNT_INS_VOLUME:
1237       ins_b = (struct udat_ins_b *)un->un_data;
1238       ins_b->ptr->ins_Volume = ins_b->before;
1239       wpanel = PN_INSED;
1240       at->at_curins = ins_b->insnum;
1241       break;
1242 
1243     case UNT_INS_WAVELENGTH:
1244       ins_b = (struct udat_ins_b *)un->un_data;
1245       ins_b->ptr->ins_WaveLength = ins_b->before;
1246       wpanel = PN_INSED;
1247       at->at_curins = ins_b->insnum;
1248       break;
1249 
1250     case UNT_INS_FILTERLOWERLIMIT:
1251       ins_b = (struct udat_ins_b *)un->un_data;
1252       ins_b->ptr->ins_FilterLowerLimit = ins_b->before;
1253       wpanel = PN_INSED;
1254       at->at_curins = ins_b->insnum;
1255       break;
1256 
1257     case UNT_INS_FILTERUPPERLIMIT:
1258       ins_b = (struct udat_ins_b *)un->un_data;
1259       ins_b->ptr->ins_FilterUpperLimit = ins_b->before;
1260       wpanel = PN_INSED;
1261       at->at_curins = ins_b->insnum;
1262       break;
1263 
1264     case UNT_INS_FILTERSPEED:
1265       ins_b = (struct udat_ins_b *)un->un_data;
1266       ins_b->ptr->ins_FilterSpeed = ins_b->before;
1267       wpanel = PN_INSED;
1268       at->at_curins = ins_b->insnum;
1269       break;
1270 
1271     case UNT_INS_SQUARELOWERLIMIT:
1272       ins_b = (struct udat_ins_b *)un->un_data;
1273       ins_b->ptr->ins_SquareLowerLimit = ins_b->before;
1274       wpanel = PN_INSED;
1275       at->at_curins = ins_b->insnum;
1276       break;
1277 
1278     case UNT_INS_SQUAREUPPERLIMIT:
1279       ins_b = (struct udat_ins_b *)un->un_data;
1280       ins_b->ptr->ins_SquareUpperLimit = ins_b->before;
1281       wpanel = PN_INSED;
1282       at->at_curins = ins_b->insnum;
1283       break;
1284 
1285     case UNT_INS_SQUARESPEED:
1286       ins_b = (struct udat_ins_b *)un->un_data;
1287       ins_b->ptr->ins_SquareSpeed = ins_b->before;
1288       wpanel = PN_INSED;
1289       at->at_curins = ins_b->insnum;
1290       break;
1291 
1292     case UNT_INS_VIBRATODELAY:
1293       ins_b = (struct udat_ins_b *)un->un_data;
1294       ins_b->ptr->ins_VibratoDelay = ins_b->before;
1295       wpanel = PN_INSED;
1296       at->at_curins = ins_b->insnum;
1297       break;
1298 
1299     case UNT_INS_VIBRATOSPEED:
1300       ins_b = (struct udat_ins_b *)un->un_data;
1301       ins_b->ptr->ins_VibratoSpeed = ins_b->before;
1302       wpanel = PN_INSED;
1303       at->at_curins = ins_b->insnum;
1304       break;
1305 
1306     case UNT_INS_VIBRATODEPTH:
1307       ins_b = (struct udat_ins_b *)un->un_data;
1308       ins_b->ptr->ins_VibratoDepth = ins_b->before;
1309       wpanel = PN_INSED;
1310       at->at_curins = ins_b->insnum;
1311       break;
1312 
1313     case UNT_INS_HARDCUTRELEASE:
1314       ins_b = (struct udat_ins_b *)un->un_data;
1315       ins_b->ptr->ins_HardCutRelease = ins_b->before;
1316       wpanel = PN_INSED;
1317       at->at_curins = ins_b->insnum;
1318       break;
1319 
1320     case UNT_INS_HARDCUTRELEASEFRAMES:
1321       ins_b = (struct udat_ins_b *)un->un_data;
1322       ins_b->ptr->ins_HardCutReleaseFrames = ins_b->before;
1323       wpanel = PN_INSED;
1324       at->at_curins = ins_b->insnum;
1325       break;
1326 
1327     case UNT_STRING_INSNAME:
1328       rstr = (struct udat_string *)un->un_data;
1329       strcpy( rstr->ptr, rstr->before );
1330       show_tbox = &tbx[TB_INSNAME];
1331       wpanel = PN_INSED;
1332       at->at_curins = rstr->extra;
1333       inslsb_lastcuri = -1;
1334       break;
1335 
1336     case UNT_STRING_INSNAME2:
1337       rstr = (struct udat_string *)un->un_data;
1338       strcpy( rstr->ptr, rstr->before );
1339       wpanel = PN_TRACKER;
1340       insls_lastcuri = -1;
1341       break;
1342 
1343     case UNT_STRING_SONGNAME:
1344       rstr = (struct udat_string *)un->un_data;
1345       strcpy( rstr->ptr, rstr->before );
1346       show_tbox = &tbx[TB_SONGNAME];
1347       wpanel = PN_TRACKER;
1348       break;
1349 
1350     case UNT_TRACK:
1351       rtrk = (struct udat_track *)un->un_data;
1352       for( i=0; i<64; i++ )
1353         at->at_Tracks[rtrk->track][i] = rtrk->before[i];
1354       at->at_PosNr        = rtrk->posnr;
1355       at->at_NoteNr       = rtrk->notenr;
1356       at->at_tracked_curs = rtrk->tracked_curs;
1357       at->at_curlch       = rtrk->curlch;
1358       wpanel = PN_TRACKER;
1359       trked_lastposnr = 1000;
1360       break;
1361 
1362     case UNT_STP_NOTEANDINS:
1363       stp_w = (struct udat_stp_w *)un->un_data;
1364       stp_w->ptr->stp_Note = (stp_w->before>>8);
1365       stp_w->ptr->stp_Instrument = stp_w->before & 0xff;
1366       at->at_PosNr        = stp_w->posnr;
1367       at->at_NoteNr       = stp_w->notenr;
1368       at->at_tracked_curs = stp_w->tracked_curs;
1369       at->at_curlch       = stp_w->curlch;
1370       wpanel = PN_TRACKER;
1371       trked_lastposnr = 1000;
1372       break;
1373 
1374     case UNT_STP_FXANDPARAM:
1375       stp_w = (struct udat_stp_w *)un->un_data;
1376       stp_w->ptr->stp_FX      = (stp_w->before>>8);
1377       stp_w->ptr->stp_FXParam = stp_w->before & 0xff;
1378       at->at_PosNr        = stp_w->posnr;
1379       at->at_NoteNr       = stp_w->notenr;
1380       at->at_tracked_curs = stp_w->tracked_curs;
1381       at->at_curlch       = stp_w->curlch;
1382       wpanel = PN_TRACKER;
1383       trked_lastposnr = 1000;
1384       break;
1385 
1386     case UNT_STP_FXBANDPARAM:
1387       stp_w = (struct udat_stp_w *)un->un_data;
1388       stp_w->ptr->stp_FXb      = (stp_w->before>>8);
1389       stp_w->ptr->stp_FXbParam = stp_w->before & 0xff;
1390       at->at_PosNr        = stp_w->posnr;
1391       at->at_NoteNr       = stp_w->notenr;
1392       at->at_tracked_curs = stp_w->tracked_curs;
1393       at->at_curlch       = stp_w->curlch;
1394       wpanel = PN_TRACKER;
1395       trked_lastposnr = 1000;
1396       break;
1397 
1398     case UNT_STP_NOTE:
1399       stp_b = (struct udat_stp_b *)un->un_data;
1400       stp_b->ptr->stp_Note = stp_b->before;
1401       at->at_PosNr        = stp_b->posnr;
1402       at->at_NoteNr       = stp_b->notenr;
1403       at->at_tracked_curs = stp_b->tracked_curs;
1404       at->at_curlch       = stp_b->curlch;
1405       wpanel = PN_TRACKER;
1406       trked_lastposnr = 1000;
1407       break;
1408 
1409     case UNT_STP_INSTRUMENT:
1410       stp_b = (struct udat_stp_b *)un->un_data;
1411       stp_b->ptr->stp_Instrument = stp_b->before;
1412       at->at_PosNr        = stp_b->posnr;
1413       at->at_NoteNr       = stp_b->notenr;
1414       at->at_tracked_curs = stp_b->tracked_curs;
1415       at->at_curlch       = stp_b->curlch;
1416       wpanel = PN_TRACKER;
1417       trked_lastposnr = 1000;
1418       break;
1419 
1420     case UNT_STP_FX:
1421       stp_b = (struct udat_stp_b *)un->un_data;
1422       stp_b->ptr->stp_FX = stp_b->before;
1423       at->at_PosNr        = stp_b->posnr;
1424       at->at_NoteNr       = stp_b->notenr;
1425       at->at_tracked_curs = stp_b->tracked_curs;
1426       at->at_curlch       = stp_b->curlch;
1427       wpanel = PN_TRACKER;
1428       trked_lastposnr = 1000;
1429       break;
1430 
1431     case UNT_STP_FXPARAM:
1432       stp_b = (struct udat_stp_b *)un->un_data;
1433       stp_b->ptr->stp_FXParam = stp_b->before;
1434       at->at_PosNr        = stp_b->posnr;
1435       at->at_NoteNr       = stp_b->notenr;
1436       at->at_tracked_curs = stp_b->tracked_curs;
1437       at->at_curlch       = stp_b->curlch;
1438       wpanel = PN_TRACKER;
1439       trked_lastposnr = 1000;
1440       break;
1441 
1442     case UNT_STP_FXB:
1443       stp_b = (struct udat_stp_b *)un->un_data;
1444       stp_b->ptr->stp_FXb = stp_b->before;
1445       at->at_PosNr        = stp_b->posnr;
1446       at->at_NoteNr       = stp_b->notenr;
1447       at->at_tracked_curs = stp_b->tracked_curs;
1448       at->at_curlch       = stp_b->curlch;
1449       wpanel = PN_TRACKER;
1450       trked_lastposnr = 1000;
1451       break;
1452 
1453     case UNT_STP_FXBPARAM:
1454       stp_b = (struct udat_stp_b *)un->un_data;
1455       stp_b->ptr->stp_FXbParam = stp_b->before;
1456       at->at_PosNr        = stp_b->posnr;
1457       at->at_NoteNr       = stp_b->notenr;
1458       at->at_tracked_curs = stp_b->tracked_curs;
1459       at->at_curlch       = stp_b->curlch;
1460       wpanel = PN_TRACKER;
1461       trked_lastposnr = 1000;
1462       break;
1463 
1464     case UNT_POS_TRACK:
1465       pos_b = (struct udat_pos_b *)un->un_data;
1466       pos_b->ptr->pos_Track[pos_b->chan] = pos_b->before;
1467       at->at_PosNr        = pos_b->posnr;
1468       at->at_posed_curs   = pos_b->posed_curs;
1469       at->at_curlch       = pos_b->curlch;
1470       wpanel = PN_TRACKER;
1471       posed_lastposnr = 1000;
1472       trked_lastposnr = 1000;
1473       break;
1474 
1475     case UNT_POS_TRANS:
1476       pos_b = (struct udat_pos_b *)un->un_data;
1477       pos_b->ptr->pos_Transpose[pos_b->chan] = pos_b->before;
1478       at->at_PosNr        = pos_b->posnr;
1479       at->at_posed_curs   = pos_b->posed_curs;
1480       at->at_curlch       = pos_b->curlch;
1481       wpanel = PN_TRACKER;
1482       posed_lastposnr = 1000;
1483       trked_lastposnr = 1000;
1484       break;
1485 
1486     case UNT_POS_REGION:
1487       pos_r = (struct udat_pos_region *)un->un_data;
1488 
1489       i=0;
1490       for( y=pos_r->pos; y<(pos_r->pos+pos_r->rows); y++ )
1491       {
1492         for( x=pos_r->left; x<(pos_r->left+pos_r->chans); x++ )
1493         {
1494           at->at_Positions[y].pos_Track[x]     = pos_r->before[i++];
1495           at->at_Positions[y].pos_Transpose[x] = pos_r->before[i++];
1496         }
1497       }
1498       at->at_PosNr        = pos_r->posnr;
1499       at->at_posed_curs   = pos_r->posed_curs;
1500       at->at_curlch       = pos_r->curlch;
1501       wpanel = PN_TRACKER;
1502       posed_lastposnr = 1000;
1503       trked_lastposnr = 1000;
1504       break;
1505   }
1506 
1507   at->at_modified = TRUE;
1508 
1509   // Place it into the redo list
1510   IExec->AddTail( at->at_redolist, (struct Node *)un );
1511 
1512   show_changed( at, wpanel, forceall );
1513 }
1514 
redo(struct ahx_tune * at)1515 void redo( struct ahx_tune *at )
1516 {
1517   struct undonode         *un;
1518   struct udat_env_w       *env_w;
1519   struct udat_whole_plist *whole_plist;
1520   struct udat_ple_b       *ple_b;
1521   struct udat_ple_w       *ple_w;
1522   struct udat_pls_w       *pls_w;
1523   struct udat_ins_b       *ins_b;
1524   struct udat_track       *rtrk;
1525   struct udat_stp_b       *stp_b;
1526   struct udat_stp_w       *stp_w;
1527   struct udat_string      *rstr;
1528   struct udat_pos_b       *pos_b;
1529   struct udat_pos_region  *pos_r;
1530   int32 i, wpanel, x, y;
1531   BOOL forceall = FALSE;
1532 
1533   wpanel = -1;
1534   show_tbox = NULL;
1535 
1536   // Get last thing in the redo list
1537   un = (struct undonode *)IExec->RemTail( at->at_redolist );
1538   if( !un ) return;
1539 
1540   // Redo it!
1541   switch( un->un_type )
1542   {
1543     case UNT_POSITIONNR:
1544       at->at_PositionNr = ((struct udat_tune_w *)un->un_data)->after;
1545       wpanel = PN_TRACKER;
1546       break;
1547 
1548     case UNT_RESTART:
1549       at->at_Restart = ((struct udat_tune_w *)un->un_data)->after;
1550       wpanel = PN_TRACKER;
1551       break;
1552 
1553     case UNT_TRACKLEN:
1554       at->at_TrackLength = ((struct udat_tune_b *)un->un_data)->after;
1555       wpanel = PN_TRACKER;
1556       break;
1557 
1558     case UNT_SUBSONGS:
1559       at->at_SubsongNr = ((struct udat_tune_w *)un->un_data)->after;
1560       wpanel = PN_TRACKER;
1561       break;
1562 
1563     case UNT_SSPOS:
1564       at->at_curss = ((struct udat_subsongpos *)un->un_data)->subsong;
1565       at->at_Subsongs[at->at_curss-1] = ((struct udat_tune_b *)un->un_data)->after;
1566       wpanel = PN_TRACKER;
1567       break;
1568 
1569     case UNT_CHANNELS:
1570       at->at_Channels = ((struct udat_tune_b *)un->un_data)->after;
1571       at->at_curlch = 0;
1572       wpanel = PN_TRACKER;
1573       forceall = TRUE;
1574       break;
1575 
1576     case UNT_MIXGAIN:
1577       at->at_mixgainP = ((struct udat_tune_b *)un->un_data)->after;
1578       at->at_mixgain = (at->at_mixgainP*256)/100;
1579       wpanel = PN_TRACKER;
1580       break;
1581 
1582     case UNT_SPMUL:
1583       at->at_SpeedMultiplier = ((struct udat_tune_b *)un->un_data)->after;
1584       wpanel = PN_TRACKER;
1585       break;
1586 
1587     case UNT_ENV_AFRAMES:
1588       env_w = (struct udat_env_w *)un->un_data;
1589       env_w->ptr->aFrames = env_w->after;
1590       wpanel = PN_INSED;
1591       at->at_curins = env_w->insnum;
1592       break;
1593 
1594     case UNT_ENV_AVOLUME:
1595       env_w = (struct udat_env_w *)un->un_data;
1596       env_w->ptr->aVolume = env_w->after;
1597       wpanel = PN_INSED;
1598       at->at_curins = env_w->insnum;
1599       break;
1600 
1601     case UNT_ENV_DFRAMES:
1602       env_w = (struct udat_env_w *)un->un_data;
1603       env_w->ptr->dFrames = env_w->after;
1604       wpanel = PN_INSED;
1605       at->at_curins = env_w->insnum;
1606       break;
1607 
1608     case UNT_ENV_DVOLUME:
1609       env_w = (struct udat_env_w *)un->un_data;
1610       env_w->ptr->aVolume = env_w->after;
1611       wpanel = PN_INSED;
1612       at->at_curins = env_w->insnum;
1613       break;
1614 
1615     case UNT_ENV_SFRAMES:
1616       env_w = (struct udat_env_w *)un->un_data;
1617       env_w->ptr->sFrames = env_w->after;
1618       wpanel = PN_INSED;
1619       at->at_curins = env_w->insnum;
1620       break;
1621 
1622     case UNT_ENV_RFRAMES:
1623       env_w = (struct udat_env_w *)un->un_data;
1624       env_w->ptr->rFrames = env_w->after;
1625       wpanel = PN_INSED;
1626       at->at_curins = env_w->insnum;
1627       break;
1628 
1629     case UNT_ENV_RVOLUME:
1630       env_w = (struct udat_env_w *)un->un_data;
1631       env_w->ptr->rVolume = env_w->after;
1632       wpanel = PN_INSED;
1633       at->at_curins = env_w->insnum;
1634       break;
1635 
1636     case UNT_PLE:
1637       whole_plist = (struct udat_whole_plist *)un->un_data;
1638       for( i=0; i<256; i++ ) whole_plist->ptr[i] = whole_plist->after[i];
1639       wpanel = PN_INSED;
1640       perf_lastinst = NULL;
1641       at->at_curins = whole_plist->insnum;
1642       break;
1643 
1644     case UNT_PLE_NOTE:
1645       ple_b = (struct udat_ple_b *)un->un_data;
1646       ple_b->ptr->ple_Note = ple_b->after;
1647       ple_b->pins->ins_ptop  = ple_b->ptop;
1648       ple_b->pins->ins_pcurx = ple_b->pcurx;
1649       ple_b->pins->ins_pcury = ple_b->pcury;
1650       wpanel = PN_INSED;
1651       perf_lastinst = NULL;
1652       at->at_curins = ple_b->insnum;
1653       break;
1654 
1655     case UNT_PLE_WAVEFORM:
1656       ple_b = (struct udat_ple_b *)un->un_data;
1657       ple_b->ptr->ple_Waveform = ple_b->after;
1658       ple_b->pins->ins_ptop  = ple_b->ptop;
1659       ple_b->pins->ins_pcurx = ple_b->pcurx;
1660       ple_b->pins->ins_pcury = ple_b->pcury;
1661       wpanel = PN_INSED;
1662       perf_lastinst = NULL;
1663       at->at_curins = ple_b->insnum;
1664       break;
1665 
1666     case UNT_PLE_FIXED:
1667       ple_w = (struct udat_ple_w *)un->un_data;
1668       ple_w->ptr->ple_Fixed = ple_w->after;
1669       ple_w->pins->ins_ptop  = ple_w->ptop;
1670       ple_w->pins->ins_pcurx = ple_w->pcurx;
1671       ple_w->pins->ins_pcury = ple_w->pcury;
1672       wpanel = PN_INSED;
1673       perf_lastinst = NULL;
1674       at->at_curins = ple_w->insnum;
1675       break;
1676 
1677     case UNT_PLE_FX0:
1678       ple_b = (struct udat_ple_b *)un->un_data;
1679       ple_b->ptr->ple_FX[0] = ple_b->after;
1680       ple_b->pins->ins_ptop  = ple_b->ptop;
1681       ple_b->pins->ins_pcurx = ple_b->pcurx;
1682       ple_b->pins->ins_pcury = ple_b->pcury;
1683       wpanel = PN_INSED;
1684       perf_lastinst = NULL;
1685       at->at_curins = ple_b->insnum;
1686       break;
1687 
1688     case UNT_PLE_FX1:
1689       ple_b = (struct udat_ple_b *)un->un_data;
1690       ple_b->ptr->ple_FX[1] = ple_b->after;
1691       ple_b->pins->ins_ptop  = ple_b->ptop;
1692       ple_b->pins->ins_pcurx = ple_b->pcurx;
1693       ple_b->pins->ins_pcury = ple_b->pcury;
1694       wpanel = PN_INSED;
1695       perf_lastinst = NULL;
1696       at->at_curins = ple_b->insnum;
1697       break;
1698 
1699     case UNT_PLE_FXPARAM0:
1700       ple_b = (struct udat_ple_b *)un->un_data;
1701       ple_b->ptr->ple_FXParam[0] = ple_b->after;
1702       ple_b->pins->ins_ptop  = ple_b->ptop;
1703       ple_b->pins->ins_pcurx = ple_b->pcurx;
1704       ple_b->pins->ins_pcury = ple_b->pcury;
1705       wpanel = PN_INSED;
1706       perf_lastinst = NULL;
1707       at->at_curins = ple_b->insnum;
1708       break;
1709 
1710     case UNT_PLE_FXPARAM1:
1711       ple_b = (struct udat_ple_b *)un->un_data;
1712       ple_b->ptr->ple_FXParam[1] = ple_b->after;
1713       ple_b->pins->ins_ptop  = ple_b->ptop;
1714       ple_b->pins->ins_pcurx = ple_b->pcurx;
1715       ple_b->pins->ins_pcury = ple_b->pcury;
1716       wpanel = PN_INSED;
1717       perf_lastinst = NULL;
1718       at->at_curins = ple_b->insnum;
1719       break;
1720 
1721     case UNT_PLS_SPEED:
1722       pls_w = (struct udat_pls_w *)un->un_data;
1723       pls_w->ptr->pls_Speed = pls_w->after;
1724       wpanel = PN_INSED;
1725       at->at_curins = pls_w->insnum;
1726       break;
1727 
1728     case UNT_PLS_LENGTH:
1729       pls_w = (struct udat_pls_w *)un->un_data;
1730       pls_w->ptr->pls_Length = pls_w->after;
1731       wpanel = PN_INSED;
1732       at->at_curins = pls_w->insnum;
1733       break;
1734 
1735     case UNT_INS_VOLUME:
1736       ins_b = (struct udat_ins_b *)un->un_data;
1737       ins_b->ptr->ins_Volume = ins_b->after;
1738       wpanel = PN_INSED;
1739       at->at_curins = ins_b->insnum;
1740       break;
1741 
1742     case UNT_INS_WAVELENGTH:
1743       ins_b = (struct udat_ins_b *)un->un_data;
1744       ins_b->ptr->ins_WaveLength = ins_b->after;
1745       wpanel = PN_INSED;
1746       at->at_curins = ins_b->insnum;
1747       break;
1748 
1749     case UNT_INS_FILTERLOWERLIMIT:
1750       ins_b = (struct udat_ins_b *)un->un_data;
1751       ins_b->ptr->ins_FilterLowerLimit = ins_b->after;
1752       wpanel = PN_INSED;
1753       at->at_curins = ins_b->insnum;
1754       break;
1755 
1756     case UNT_INS_FILTERUPPERLIMIT:
1757       ins_b = (struct udat_ins_b *)un->un_data;
1758       ins_b->ptr->ins_FilterUpperLimit = ins_b->after;
1759       wpanel = PN_INSED;
1760       at->at_curins = ins_b->insnum;
1761       break;
1762 
1763     case UNT_INS_FILTERSPEED:
1764       ins_b = (struct udat_ins_b *)un->un_data;
1765       ins_b->ptr->ins_FilterSpeed = ins_b->after;
1766       wpanel = PN_INSED;
1767       at->at_curins = ins_b->insnum;
1768       break;
1769 
1770     case UNT_INS_SQUARELOWERLIMIT:
1771       ins_b = (struct udat_ins_b *)un->un_data;
1772       ins_b->ptr->ins_SquareLowerLimit = ins_b->after;
1773       wpanel = PN_INSED;
1774       at->at_curins = ins_b->insnum;
1775       break;
1776 
1777     case UNT_INS_SQUAREUPPERLIMIT:
1778       ins_b = (struct udat_ins_b *)un->un_data;
1779       ins_b->ptr->ins_SquareUpperLimit = ins_b->after;
1780       wpanel = PN_INSED;
1781       at->at_curins = ins_b->insnum;
1782       break;
1783 
1784     case UNT_INS_SQUARESPEED:
1785       ins_b = (struct udat_ins_b *)un->un_data;
1786       ins_b->ptr->ins_SquareSpeed = ins_b->after;
1787       wpanel = PN_INSED;
1788       at->at_curins = ins_b->insnum;
1789       break;
1790 
1791     case UNT_INS_VIBRATODELAY:
1792       ins_b = (struct udat_ins_b *)un->un_data;
1793       ins_b->ptr->ins_VibratoDelay = ins_b->after;
1794       wpanel = PN_INSED;
1795       at->at_curins = ins_b->insnum;
1796       break;
1797 
1798     case UNT_INS_VIBRATOSPEED:
1799       ins_b = (struct udat_ins_b *)un->un_data;
1800       ins_b->ptr->ins_VibratoSpeed = ins_b->after;
1801       wpanel = PN_INSED;
1802       at->at_curins = ins_b->insnum;
1803       break;
1804 
1805     case UNT_INS_VIBRATODEPTH:
1806       ins_b = (struct udat_ins_b *)un->un_data;
1807       ins_b->ptr->ins_VibratoDepth = ins_b->after;
1808       wpanel = PN_INSED;
1809       at->at_curins = ins_b->insnum;
1810       break;
1811 
1812     case UNT_INS_HARDCUTRELEASE:
1813       ins_b = (struct udat_ins_b *)un->un_data;
1814       ins_b->ptr->ins_HardCutRelease = ins_b->after;
1815       wpanel = PN_INSED;
1816       at->at_curins = ins_b->insnum;
1817       break;
1818 
1819     case UNT_INS_HARDCUTRELEASEFRAMES:
1820       ins_b = (struct udat_ins_b *)un->un_data;
1821       ins_b->ptr->ins_HardCutReleaseFrames = ins_b->after;
1822       wpanel = PN_INSED;
1823       at->at_curins = ins_b->insnum;
1824       break;
1825 
1826     case UNT_STRING_INSNAME:
1827       rstr = (struct udat_string *)un->un_data;
1828       strcpy( rstr->ptr, rstr->after );
1829       show_tbox = &tbx[TB_INSNAME];
1830       wpanel = PN_INSED;
1831       at->at_curins = rstr->extra;
1832       inslsb_lastcuri = -1;
1833       break;
1834 
1835     case UNT_STRING_INSNAME2:
1836       rstr = (struct udat_string *)un->un_data;
1837       strcpy( rstr->ptr, rstr->after );
1838       wpanel = PN_TRACKER;
1839       insls_lastcuri = -1;
1840       break;
1841 
1842     case UNT_STRING_SONGNAME:
1843       rstr = (struct udat_string *)un->un_data;
1844       strcpy( rstr->ptr, rstr->after );
1845       show_tbox = &tbx[TB_SONGNAME];
1846       wpanel = PN_TRACKER;
1847       break;
1848 
1849     case UNT_TRACK:
1850       rtrk = (struct udat_track *)un->un_data;
1851       for( i=0; i<64; i++ )
1852         at->at_Tracks[rtrk->track][i] = rtrk->after[i];
1853       at->at_PosNr        = rtrk->posnr;
1854       at->at_NoteNr       = rtrk->notenr;
1855       at->at_tracked_curs = rtrk->tracked_curs;
1856       at->at_curlch       = rtrk->curlch;
1857       wpanel = PN_TRACKER;
1858       trked_lastposnr = 1000;
1859       break;
1860 
1861     case UNT_STP_NOTEANDINS:
1862       stp_w = (struct udat_stp_w *)un->un_data;
1863       stp_w->ptr->stp_Note = (stp_w->after>>8);
1864       stp_w->ptr->stp_Instrument = stp_w->after & 0xff;
1865       at->at_PosNr        = stp_w->posnr;
1866       at->at_NoteNr       = stp_w->notenr;
1867       at->at_tracked_curs = stp_w->tracked_curs;
1868       at->at_curlch       = stp_w->curlch;
1869       wpanel = PN_TRACKER;
1870       trked_lastposnr = 1000;
1871       break;
1872 
1873     case UNT_STP_FXANDPARAM:
1874       stp_w = (struct udat_stp_w *)un->un_data;
1875       stp_w->ptr->stp_FX      = (stp_w->after>>8);
1876       stp_w->ptr->stp_FXParam = stp_w->after & 0xff;
1877       at->at_PosNr        = stp_w->posnr;
1878       at->at_NoteNr       = stp_w->notenr;
1879       at->at_tracked_curs = stp_w->tracked_curs;
1880       at->at_curlch       = stp_w->curlch;
1881       wpanel = PN_TRACKER;
1882       trked_lastposnr = 1000;
1883       break;
1884 
1885     case UNT_STP_FXBANDPARAM:
1886       stp_w = (struct udat_stp_w *)un->un_data;
1887       stp_w->ptr->stp_FXb      = (stp_w->after>>8);
1888       stp_w->ptr->stp_FXbParam = stp_w->after & 0xff;
1889       at->at_PosNr        = stp_w->posnr;
1890       at->at_NoteNr       = stp_w->notenr;
1891       at->at_tracked_curs = stp_w->tracked_curs;
1892       at->at_curlch       = stp_w->curlch;
1893       wpanel = PN_TRACKER;
1894       trked_lastposnr = 1000;
1895       break;
1896 
1897     case UNT_STP_NOTE:
1898       stp_b = (struct udat_stp_b *)un->un_data;
1899       stp_b->ptr->stp_Note = stp_b->after;
1900       at->at_PosNr        = stp_b->posnr;
1901       at->at_NoteNr       = stp_b->notenr;
1902       at->at_tracked_curs = stp_b->tracked_curs;
1903       at->at_curlch       = stp_b->curlch;
1904       wpanel = PN_TRACKER;
1905       trked_lastposnr = 1000;
1906       break;
1907 
1908     case UNT_STP_INSTRUMENT:
1909       stp_b = (struct udat_stp_b *)un->un_data;
1910       stp_b->ptr->stp_Instrument = stp_b->after;
1911       at->at_PosNr        = stp_b->posnr;
1912       at->at_NoteNr       = stp_b->notenr;
1913       at->at_tracked_curs = stp_b->tracked_curs;
1914       at->at_curlch       = stp_b->curlch;
1915       wpanel = PN_TRACKER;
1916       trked_lastposnr = 1000;
1917       break;
1918 
1919     case UNT_STP_FX:
1920       stp_b = (struct udat_stp_b *)un->un_data;
1921       stp_b->ptr->stp_FX = stp_b->after;
1922       at->at_PosNr        = stp_b->posnr;
1923       at->at_NoteNr       = stp_b->notenr;
1924       at->at_tracked_curs = stp_b->tracked_curs;
1925       at->at_curlch       = stp_b->curlch;
1926       wpanel = PN_TRACKER;
1927       trked_lastposnr = 1000;
1928       break;
1929 
1930     case UNT_STP_FXPARAM:
1931       stp_b = (struct udat_stp_b *)un->un_data;
1932       stp_b->ptr->stp_FXParam = stp_b->after;
1933       at->at_PosNr        = stp_b->posnr;
1934       at->at_NoteNr       = stp_b->notenr;
1935       at->at_tracked_curs = stp_b->tracked_curs;
1936       at->at_curlch       = stp_b->curlch;
1937       wpanel = PN_TRACKER;
1938       trked_lastposnr = 1000;
1939       break;
1940 
1941     case UNT_STP_FXB:
1942       stp_b = (struct udat_stp_b *)un->un_data;
1943       stp_b->ptr->stp_FXb = stp_b->after;
1944       at->at_PosNr        = stp_b->posnr;
1945       at->at_NoteNr       = stp_b->notenr;
1946       at->at_tracked_curs = stp_b->tracked_curs;
1947       at->at_curlch       = stp_b->curlch;
1948       wpanel = PN_TRACKER;
1949       trked_lastposnr = 1000;
1950       break;
1951 
1952     case UNT_STP_FXBPARAM:
1953       stp_b = (struct udat_stp_b *)un->un_data;
1954       stp_b->ptr->stp_FXbParam = stp_b->after;
1955       at->at_PosNr        = stp_b->posnr;
1956       at->at_NoteNr       = stp_b->notenr;
1957       at->at_tracked_curs = stp_b->tracked_curs;
1958       at->at_curlch       = stp_b->curlch;
1959       wpanel = PN_TRACKER;
1960       trked_lastposnr = 1000;
1961       break;
1962 
1963     case UNT_POS_TRACK:
1964       pos_b = (struct udat_pos_b *)un->un_data;
1965       pos_b->ptr->pos_Track[pos_b->chan] = pos_b->after;
1966       at->at_PosNr        = pos_b->posnr;
1967       at->at_posed_curs   = pos_b->posed_curs;
1968       at->at_curlch       = pos_b->curlch;
1969       wpanel = PN_TRACKER;
1970       posed_lastposnr = 1000;
1971       trked_lastposnr = 1000;
1972       break;
1973 
1974     case UNT_POS_TRANS:
1975       pos_b = (struct udat_pos_b *)un->un_data;
1976       pos_b->ptr->pos_Transpose[pos_b->chan] = pos_b->after;
1977       at->at_PosNr        = pos_b->posnr;
1978       at->at_posed_curs   = pos_b->posed_curs;
1979       at->at_curlch       = pos_b->curlch;
1980       wpanel = PN_TRACKER;
1981       posed_lastposnr = 1000;
1982       trked_lastposnr = 1000;
1983       break;
1984 
1985     case UNT_POS_REGION:
1986       pos_r = (struct udat_pos_region *)un->un_data;
1987 
1988       i=0;
1989       for( y=pos_r->pos; y<(pos_r->pos+pos_r->rows); y++ )
1990       {
1991         for( x=pos_r->left; x<(pos_r->left+pos_r->chans); x++ )
1992         {
1993           at->at_Positions[y].pos_Track[x]     = pos_r->after[i++];
1994           at->at_Positions[y].pos_Transpose[x] = pos_r->after[i++];
1995         }
1996       }
1997       at->at_PosNr        = pos_r->posnr;
1998       at->at_posed_curs   = pos_r->posed_curs;
1999       at->at_curlch       = pos_r->curlch;
2000       wpanel = PN_TRACKER;
2001       posed_lastposnr = 1000;
2002       trked_lastposnr = 1000;
2003       break;
2004   }
2005 
2006   at->at_modified = TRUE;
2007 
2008   // Place it back into the undo list
2009   IExec->AddTail( at->at_undolist, (struct Node *)un );
2010 
2011   show_changed( at, wpanel, forceall );
2012 }
2013