~ubuntu-branches/ubuntu/maverick/ncbi-tools6/maverick

« back to all changes in this revision

Viewing changes to vibrant/vibmouse.c

  • Committer: Bazaar Package Importer
  • Author(s): Aaron M. Ucko
  • Date: 2002-04-04 22:13:09 UTC
  • Revision ID: james.westby@ubuntu.com-20020404221309-vfze028rfnlrldct
Tags: upstream-6.1.20011220a
ImportĀ upstreamĀ versionĀ 6.1.20011220a

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*  $Id: vibmouse.c,v 6.4 2001/03/28 01:40:48 juran Exp $
 
2
* ===========================================================================
 
3
*
 
4
*                            PUBLIC DOMAIN NOTICE
 
5
*            National Center for Biotechnology Information (NCBI)
 
6
*
 
7
*  This software/database is a "United States Government Work" under the
 
8
*  terms of the United States Copyright Act.  It was written as part of
 
9
*  the author's official duties as a United States Government employee and
 
10
*  thus cannot be copyrighted.  This software/database is freely available
 
11
*  to the public for use. The National Library of Medicine and the U.S.
 
12
*  Government do not place any restriction on its use or reproduction.
 
13
*  We would, however, appreciate having the NCBI and the author cited in
 
14
*  any work or product based on this material
 
15
*
 
16
*  Although all reasonable efforts have been taken to ensure the accuracy
 
17
*  and reliability of the software and data, the NLM and the U.S.
 
18
*  Government do not and cannot warrant the performance or results that
 
19
*  may be obtained by using this software or data. The NLM and the U.S.
 
20
*  Government disclaim all warranties, express or implied, including
 
21
*  warranties of performance, merchantability or fitness for any particular
 
22
*  purpose.
 
23
*
 
24
* ===========================================================================
 
25
*
 
26
* Author:  Denis Vakatov
 
27
*
 
28
* File Description: 
 
29
*   user interface to manage mouse-event callbacks
 
30
*   program interface to describe groups of mouse-event callbacks
 
31
*
 
32
* ===========================================================================
 
33
* $Log: vibmouse.c,v $
 
34
* Revision 6.4  2001/03/28 01:40:48  juran
 
35
* "for (...) { continue; }", squelch warning
 
36
*
 
37
* Revision 6.3  1999/04/06 14:23:25  lewisg
 
38
* add opengl replacement for viewer3d
 
39
*
 
40
* Revision 6.2  1998/07/02 18:24:34  vakatov
 
41
* Cleaned the code & made it pass through the C++ compilation
 
42
*
 
43
* Revision 6.1  1997/11/26 21:30:31  vakatov
 
44
* Fixed errors and warnings issued by C and C++ (GNU and Sun) compilers
 
45
*
 
46
* Revision 6.0  1997/08/25 18:57:21  madden
 
47
* Revision changed to 6.0
 
48
*
 
49
* Revision 1.3  1997/05/06 16:27:07  vakatov
 
50
* Ignore the MA_Drag and MA_Release events not preceded by MA_Press
 
51
*
 
52
 * Revision 1.2  1997/03/21  16:15:12  vakatov
 
53
 * Removed #<ni_list.h> -- as the list stuff has been moved to "ncbimisk.[ch]"
 
54
 *
 
55
 * Revision 1.1  1997/03/20  16:23:26  vakatov
 
56
 * Initial revision
 
57
 *
 
58
*
 
59
* ==========================================================================
 
60
*/
 
61
 
 
62
#ifdef VAR_ARGS
 
63
#include <varargs.h>
 
64
#else
 
65
#include <stdarg.h>
 
66
#endif
 
67
#include <vibrant.h>  /* move out of header.  lyg */
 
68
#include <vibmouse.h>
 
69
 
 
70
 
 
71
#define BAD ASSERT(FALSE)
 
72
 
 
73
 
 
74
/*****************************************************************************
 
75
 *  Internal Data and Type Definitions
 
76
*****************************************************************************/
 
77
 
 
78
static const Char *MA_name[MK_Default][MA_Init] =
 
79
{
 
80
  {
 
81
    "Click",
 
82
    "Press",
 
83
    "DoubleClick",
 
84
    "Hold",
 
85
    "Drag",
 
86
    "Release",
 
87
    "Cancel"
 
88
  },
 
89
 
 
90
  {
 
91
    "Shift-Click",
 
92
    "Shift-Press",
 
93
    "Shift-DoubleClick",
 
94
    "Shift-Hold",
 
95
    "Shift-Drag",
 
96
    "Shift-Release",
 
97
    "Shift-Cancel"
 
98
  },
 
99
 
 
100
  {
 
101
    "Ctrl-Click",
 
102
    "Ctrl-Press",
 
103
    "Ctrl-DoubleClick",
 
104
    "Ctrl-Hold",
 
105
    "Ctrl-Drag",
 
106
    "Ctrl-Release",
 
107
    "Ctrl-Cancel"
 
108
  }
 
109
};
 
110
 
 
111
 
 
112
typedef struct _MAction
 
113
{
 
114
  enumMKey     mod_key;
 
115
  enumMAction  type;
 
116
  MA_Func      func;
 
117
  VoidPtr      data;
 
118
  CharPtr      name;
 
119
  IteM         item;
 
120
  MAPtr        ma;
 
121
}
 
122
MAction;
 
123
 
 
124
typedef struct _MA_Group
 
125
{
 
126
  CharPtr    name;  /* the group name as it appears in the group menu */
 
127
  MActionPtr init;
 
128
  MActionPtr done;
 
129
  MActionPtr action[MK_Default][MA_Init];
 
130
  Boolean    only  [MK_Default][MA_Init]; /* TRUE if cannot be replaced by a
 
131
                         "foreign" callback while the group is active */
 
132
  IteM       item;
 
133
  MAPtr      ma;
 
134
}
 
135
MA_Group;
 
136
 
 
137
 
 
138
 
 
139
typedef struct _MA
 
140
{
 
141
  /* interface */
 
142
  MenU        group_menu;
 
143
  MenU        action_menu;
 
144
  MenU        menu[MK_Default][MA_Init];
 
145
 
 
146
  /* all registered actions and groups */
 
147
  NodePtr     actions;
 
148
  NodePtr     groups;
 
149
 
 
150
  /* presently active groups and actions */
 
151
  NodePtr     active_groups;
 
152
  MActionPtr  action[MK_Default][MA_Init];
 
153
  Boolean     only  [MK_Default][MA_Init];
 
154
 
 
155
  /* presently active(snapshot during the last "Press" action) modifier */ 
 
156
  enumMKey    mod_key;
 
157
 
 
158
  /* type and position of the most recent mouse action(but MA_Hold) */
 
159
  enumMAction last_type;
 
160
  PoinT       last_pos;
 
161
 
 
162
  /* auxiliary temporary store area shared between the action callbacks */
 
163
  MA_Trace    trace;
 
164
 
 
165
  /* presently linked panel(slate) */
 
166
  PaneL       panel;
 
167
 
 
168
  /* user-specified pointer to an extra data */
 
169
  VoidPtr     extra;
 
170
}
 
171
MA;
 
172
 
 
173
 
 
174
 
 
175
/*****************************************************************************
 
176
 *  Internal (Static)  Functions
 
177
*****************************************************************************/
 
178
 
 
179
/* In the "action->ma", find the active group containing 
 
180
 * the "only" action of type "action->mod_key/type"
 
181
 */ 
 
182
static MA_GroupPtr GroupOfOnlyAction(MActionPtr action)
 
183
{
 
184
  MAPtr   ma   = action->ma;
 
185
  NodePtr node = ma->active_groups;
 
186
 
 
187
  ASSERT ( ma->only[action->mod_key][action->type] );
 
188
 
 
189
  while ( node )
 
190
    {
 
191
      MA_GroupPtr mag = (MA_GroupPtr)node->elem;
 
192
      if ( mag->only[action->mod_key][action->type] )
 
193
        return mag;
 
194
 
 
195
      node = ListGetNext( node );
 
196
    }
 
197
 
 
198
  BAD;
 
199
  return NULL;
 
200
}
 
201
 
 
202
 
 
203
/* Set current action according to the submenu item click
 
204
 */
 
205
static void MA_ActionItemCB(IteM item)
 
206
{
 
207
  MActionPtr action = (MActionPtr)GetObjectExtra( item );
 
208
 
 
209
  VERIFY ( MA_SetAction(action, TRUE) );
 
210
}
 
211
 
 
212
 
 
213
/* Add the action item to the relevant submenu
 
214
 */
 
215
static Boolean MA_ShowAction(MActionPtr action)
 
216
{
 
217
  MAPtr ma;
 
218
  if (action == NULL  ||  action->name == NULL  ||
 
219
      (ma = action->ma) == NULL  ||  ma->action_menu == NULL  ||
 
220
      !ma->action_menu  ||  !ma->menu[action->mod_key][action->type])
 
221
    return FALSE;
 
222
 
 
223
  if (action->item != NULL)
 
224
    return TRUE;
 
225
 
 
226
  action->item = CommandItem(ma->menu[action->mod_key][action->type],
 
227
                             action->name, MA_ActionItemCB);
 
228
  if ( !action->item )
 
229
    return FALSE;
 
230
 
 
231
  SetObjectExtra(action->item, action, NULL);
 
232
  return TRUE;
 
233
}
 
234
 
 
235
 
 
236
/*  Activate/deactivate the mouse callback group "group"
 
237
 */
 
238
static void MA_GroupItemCB(IteM item)
 
239
{
 
240
  MA_GroupPtr group = (MA_GroupPtr)GetObjectExtra( item );
 
241
 
 
242
  if ( GetStatus( item ) )
 
243
    VERIFY ( MA_SetGroup( group ) );
 
244
  else
 
245
    VERIFY ( MA_UnsetGroup( group ) );
 
246
}
 
247
 
 
248
 
 
249
/*  Add the "group"'s name to the list of mouse callback groups
 
250
 */
 
251
static Boolean MA_ShowGroup(MA_GroupPtr group)
 
252
{
 
253
  if (group                 != NULL  &&
 
254
      group->name           != NULL  &&
 
255
      group->ma             != NULL  &&
 
256
      group->ma->group_menu != NULL  &&
 
257
      (group->item = StatusItem(group->ma->group_menu, group->name,
 
258
                                MA_GroupItemCB)) != NULL)
 
259
    {
 
260
      SetObjectExtra(group->item, group, NULL);
 
261
      return TRUE;
 
262
    }
 
263
 
 
264
  return FALSE;
 
265
}
 
266
 
 
267
 
 
268
/* Measure distance between the two points
 
269
 */
 
270
static double PointDist(PoinT p1, PoinT p2)
 
271
{
 
272
  return sqrt( (double)((p2.x - p1.x) * (p2.x - p1.x) +
 
273
                        (p2.y - p1.y) * (p2.y - p1.y)));
 
274
}
 
275
 
 
276
/* The Panel-to-MA callback dispatcher
 
277
 */
 
278
static void MA_Execute(MAPtr ma, PoinT pt, enumMAction type)
 
279
{
 
280
  ASSERT ( 0 <= type  &&  type < MA_Init );
 
281
 
 
282
  /* set the key status of the action in progress */
 
283
  if (type == MA_Press  ||  type == MA_DClick  ||  ma->mod_key == MK_Default)
 
284
    ma->mod_key = Nlm_shftKey ? MK_Shift :
 
285
                  Nlm_ctrlKey ? MK_Ctrl  :
 
286
                  MK_Normal;
 
287
 
 
288
  /* Refuse MA_Drag and MA_Release not preceded by MA_Press */
 
289
  if ((type == MA_Drag  ||  type == MA_Release)  &&
 
290
      ma->last_type != MA_Press  &&  ma->last_type != MA_Drag)
 
291
    return;
 
292
 
 
293
  /* MA_Click vs. MA_Drag|MA_Release */
 
294
  if (ma->last_type == MA_Press)
 
295
    {
 
296
      double CLICK_RADIUS = (double)8;
 
297
      switch ( type )
 
298
        {
 
299
        case MA_Drag:
 
300
          if (PointDist(pt, ma->last_pos) <= CLICK_RADIUS)
 
301
            return;
 
302
          break;
 
303
 
 
304
        case MA_Release:
 
305
          if (PointDist(pt, ma->last_pos) <= CLICK_RADIUS)
 
306
            type = MA_Click;
 
307
          break;
 
308
 
 
309
        default:
 
310
          break;
 
311
        }
 
312
    }
 
313
 
 
314
  {{ /* call the relevant user-specified action callback, if any */
 
315
    MActionPtr action = ma->action[ma->mod_key][type];
 
316
    if ( action )
 
317
      {
 
318
        ASSERT ( action->ma   == ma   );
 
319
        ASSERT ( action->type == type );
 
320
        (*action->func)(ma, &ma->trace, pt, action->data);
 
321
      }
 
322
  }}
 
323
 
 
324
  if (type == MA_Release  ||  type == MA_Cancel  ||  type == MA_DClick)
 
325
    ma->mod_key = MK_Default;  /* no action in progress */
 
326
 
 
327
  if (type != MA_Hold)
 
328
    {  
 
329
      ma->last_type = type;
 
330
      ma->last_pos  = pt;
 
331
    }
 
332
}
 
333
 
 
334
static void MA_ExecuteP(PaneL panel, PoinT pt, enumMAction type)
 
335
{
 
336
  MAPtr ma = NULL;
 
337
  GetPanelExtra(panel, &ma);
 
338
  MA_Execute(ma, pt, type);
 
339
}
 
340
 
 
341
 
 
342
/* MA wrappers of the panel callbacks
 
343
 */
 
344
static void MA_ClickCB(PaneL panel, PoinT pt)
 
345
{
 
346
  if ( Nlm_dblClick )
 
347
    MA_ExecuteP(panel, pt, MA_DClick);
 
348
  else
 
349
    MA_ExecuteP(panel, pt, MA_Press);
 
350
}
 
351
 
 
352
 
 
353
static void MA_HoldCB(PaneL panel, PoinT pt)
 
354
{
 
355
  MA_ExecuteP(panel, pt, MA_Hold);
 
356
}
 
357
 
 
358
 
 
359
static void MA_DragCB(PaneL panel, PoinT pt)
 
360
{
 
361
  MA_ExecuteP(panel, pt, MA_Drag);
 
362
}
 
363
 
 
364
 
 
365
static void MA_ReleaseCB(PaneL panel, PoinT pt)
 
366
{
 
367
  MA_ExecuteP(panel, pt, MA_Release);
 
368
}
 
369
 
 
370
 
 
371
 
 
372
/*****************************************************************************
 
373
 *  External Functions
 
374
*****************************************************************************/
 
375
 
 
376
/* Creation functions
 
377
 */
 
378
extern MAPtr MA_Create(MenU group_menu, MenU action_menu)
 
379
{
 
380
  MAPtr ma = (MAPtr)MemNew( sizeof(MA) );
 
381
  if ( !ma ) {
 
382
    BAD;
 
383
    return NULL;
 
384
  }
 
385
 
 
386
  ma->group_menu  = group_menu;
 
387
  ma->action_menu = action_menu;
 
388
 
 
389
  MA_Reset( ma );
 
390
  return ma;
 
391
}
 
392
 
 
393
 
 
394
/* DUMMY MA callback function
 
395
 */
 
396
extern void DoNothingMA(MAPtr ma, MA_TracePtr trace, PoinT point,
 
397
                        VoidPtr extra)
 
398
{
 
399
  /* do nothing */
 
400
}
 
401
 
 
402
 
 
403
extern MActionPtr MA_AddAction(MAPtr            ma,
 
404
                               enumMKey         mod_key,
 
405
                               enumMAction      type,
 
406
                               MA_Func          func,
 
407
                               VoidPtr          data,
 
408
                               const Char PNTR  name)
 
409
{
 
410
  MActionPtr new_action;
 
411
  NodePtr    new_node;
 
412
 
 
413
  if (ma == NULL  ||  mod_key == MK_Default  ||  type == MA_Default  ||
 
414
      func == NULL)
 
415
    {
 
416
      BAD;
 
417
      return NULL;
 
418
    }
 
419
  ASSERT ( name == NULL  ||  *name != '\0' );
 
420
 
 
421
  new_action = (MActionPtr) MemNew( sizeof(MAction) );
 
422
  new_node = ListInsertPrev(new_action, ma->actions);
 
423
  if (new_node == NULL)
 
424
    {
 
425
      BAD;
 
426
      MemFree( new_action );
 
427
      return NULL;
 
428
    }
 
429
  if (ma->actions == NULL)
 
430
    ma->actions = new_node;
 
431
 
 
432
  new_action->mod_key = mod_key;
 
433
  new_action->type    = type;
 
434
  new_action->func    = func;
 
435
  new_action->data    = data;
 
436
  new_action->name    = StringSave( name );
 
437
  new_action->ma      = ma;
 
438
  MA_ShowAction( new_action );
 
439
 
 
440
  return new_action;
 
441
}
 
442
 
 
443
 
 
444
extern Boolean MA_SetAction(MActionPtr action, Boolean can_unset_group)
 
445
{
 
446
  MAPtr       ma        = action->ma;
 
447
  MActionPtr *ma_action = &ma->action[action->mod_key][action->type];
 
448
 
 
449
  if ( ma->only[action->mod_key][action->type] )
 
450
    {
 
451
      if ( can_unset_group )
 
452
        {
 
453
          VERIFY ( MA_UnsetGroup( GroupOfOnlyAction(action) ) );
 
454
          ASSERT ( !ma->only[action->mod_key][action->type] );
 
455
        }
 
456
      else
 
457
        return FALSE;
 
458
    }
 
459
 
 
460
  if (*ma_action  &&  (*ma_action)->item)
 
461
    Enable( (*ma_action)->item );
 
462
  if (action  &&  action->item)
 
463
    Disable( action->item );
 
464
 
 
465
  *ma_action = action;
 
466
  return TRUE;
 
467
}
 
468
 
 
469
 
 
470
extern Boolean MA_UnsetAll(MAPtr ma)
 
471
{
 
472
  while ( ma->active_groups )
 
473
    if ( !MA_UnsetGroup( (MA_GroupPtr)ma->active_groups->elem ) )
 
474
      {
 
475
        BAD;
 
476
        return FALSE;
 
477
      }
 
478
 
 
479
  {{
 
480
    int i,j;
 
481
    for (i = 0;  i < MK_Default;  i++)
 
482
    for (j = 0;  j < MA_Init;     j++)
 
483
      {
 
484
        ASSERT ( !ma->only[i][j] );
 
485
        if ( ma->action[i][j] )
 
486
          {
 
487
            if ( ma->action[i][j]->item )
 
488
              Enable( ma->action[i][j]->item );
 
489
            ma->action[i][j] = NULL;
 
490
          }
 
491
      }
 
492
  }}
 
493
 
 
494
  return TRUE;
 
495
}
 
496
 
 
497
 
 
498
#ifdef VAR_ARGS
 
499
extern MA_GroupPtr MA_AddGroup(ma, name, action, only, va_alist)
 
500
MAPtr            ma;
 
501
const Char PNTR  name;
 
502
MActionPtr       action;
 
503
long             only;
 
504
va_dcl
 
505
#else
 
506
extern MA_GroupPtr MA_AddGroup(MAPtr ma,  const Char PNTR name,
 
507
                               MActionPtr action,  long only,
 
508
                               /* and more pairs: <action>, <only>; */
 
509
                               /* then, the last arg. must be NULL! */
 
510
                               ...)
 
511
#endif
 
512
{
 
513
  MA_GroupPtr new_group;
 
514
 
 
515
  if (ma == NULL  ||  name == NULL  ||  action == NULL)
 
516
    {
 
517
      BAD;
 
518
      return NULL;
 
519
    }
 
520
 
 
521
  new_group = (MA_GroupPtr)MemNew( sizeof(MA_Group) );
 
522
  
 
523
  {{ /* Extract the group actions from the list of arguments */
 
524
    va_list args;
 
525
#ifdef VAR_ARGS
 
526
    va_start(args);
 
527
#else
 
528
    va_start(args, only);
 
529
#endif
 
530
    for ( ; action != NULL;
 
531
         action = va_arg(args, MActionPtr),
 
532
         only   = va_arg(args, long))
 
533
      {
 
534
        MActionPtr *dest_action = NULL;
 
535
 
 
536
        switch ( action->type )
 
537
          {
 
538
          case MA_Init:
 
539
            dest_action = &new_group->init;
 
540
            break;
 
541
 
 
542
          case MA_Done:
 
543
            dest_action = &new_group->done;
 
544
            break;
 
545
 
 
546
          default:
 
547
            dest_action = &new_group->action[action->mod_key][action->type];
 
548
            new_group->only[action->mod_key][action->type] =
 
549
              (Boolean)(only == MA_ONLY);
 
550
            break;
 
551
          }
 
552
        
 
553
        if (*dest_action != NULL)
 
554
          {
 
555
            BAD;
 
556
            MemFree( new_group );
 
557
            return NULL;
 
558
          }
 
559
 
 
560
        *dest_action = action;
 
561
      }
 
562
    va_end(args);
 
563
  }}
 
564
 
 
565
  {{ /* Insert the new group to the end of the list of groups */
 
566
    NodePtr new_node = ListInsertPrev(new_group, ma->groups);
 
567
    if (new_node == NULL)
 
568
      {
 
569
        BAD;
 
570
        MemFree( new_group );
 
571
        return NULL;
 
572
      }
 
573
    if (ma->groups == NULL)
 
574
      ma->groups = new_node;
 
575
  }}
 
576
 
 
577
  new_group->name = StringSave( name );
 
578
  new_group->ma   = ma;
 
579
  MA_ShowGroup( new_group );
 
580
 
 
581
  return new_group;
 
582
}
 
583
 
 
584
 
 
585
extern Boolean MA_UnsetGroup(MA_GroupPtr group)
 
586
{
 
587
  MAPtr ma = group->ma;
 
588
 
 
589
  {{ /* find and exclude the "group" from the list of active groups */
 
590
    NodePtr node;
 
591
    for (node = ma->active_groups;
 
592
         node  &&  node->elem != group;
 
593
         node = ListGetNext( node ))
 
594
    {
 
595
      continue;
 
596
    }
 
597
 
 
598
    if ( !node )
 
599
      return FALSE;
 
600
 
 
601
    if (node == ma->active_groups)
 
602
      ma->active_groups = ListDelete( node );
 
603
    else
 
604
      ListDelete( node );
 
605
  }}
 
606
 
 
607
  {{ /* unset the "group"'s "only" actions */
 
608
    int i, j;
 
609
    for (i = 0;  i < MK_Default;  i++)
 
610
    for (j = 0;  j < MA_Init;     j++)
 
611
      if ( group->only[i][j] )
 
612
          {
 
613
            ASSERT ( ma->action[i][j] == group->action[i][j] );
 
614
            ASSERT ( ma->only  [i][j] );
 
615
            if ( ma->menu[i][j] )
 
616
              Enable( ma->menu[i][j] );
 
617
            ma->action[i][j] = NULL;
 
618
            ma->only  [i][j] = FALSE;
 
619
          }
 
620
  }}
 
621
 
 
622
  /* call the group's "done" method(i.e. the user-defined group destructor);
 
623
     always call the "cancel" method before -- if there is a mouse
 
624
     action "in progress" */
 
625
  if (ma->mod_key != MK_Default)
 
626
    MA_Execute(ma, ma->trace.end, MA_Cancel);
 
627
 
 
628
  if (group->item != NULL)
 
629
    SetStatus(group->item, FALSE);
 
630
 
 
631
  if ( group->done )
 
632
    (*group->done->func)(ma, &ma->trace, ma->trace.end, group->done->data);
 
633
 
 
634
  return TRUE;
 
635
}
 
636
 
 
637
 
 
638
extern Boolean MA_SetGroup(MA_GroupPtr group)
 
639
{
 
640
  int   i, j;
 
641
  MAPtr ma = group->ma;
 
642
 
 
643
  {{ /* check for the "only"-actions double-crossing; in that case
 
644
      * unset all "only" actions of the old group(i.e. unset the group) */
 
645
    for (i = 0;  i < MK_Default;  i++)
 
646
    for (j = 0;  j < MA_Init;     j++)
 
647
      if (ma->only[i][j]  &&  group->only[i][j]  &&
 
648
          !MA_UnsetGroup( GroupOfOnlyAction(group->action[i][j]) ))
 
649
        {
 
650
          BAD;
 
651
          return FALSE;
 
652
        }
 
653
  }}
 
654
 
 
655
  /* replace all old non-"only" actions with these from the "group" */
 
656
  for (i = 0;  i < MK_Default;  i++)
 
657
  for (j = 0;  j < MA_Init;     j++)
 
658
    {
 
659
      if (group->action[i][j] != NULL)
 
660
        {
 
661
          ASSERT ( !group->only[i][j]  ||  !ma->only[i][j]);
 
662
          if ( ma->only[i][j] )
 
663
            {
 
664
              ASSERT ( !group->only[i][j] );
 
665
            }
 
666
          else
 
667
            {
 
668
              if (ma->action[i][j]  &&  ma->action[i][j]->item)
 
669
                Enable( ma->action[i][j]->item );
 
670
              ma->action[i][j] = group->action[i][j];
 
671
              ma->only  [i][j] = group->only  [i][j];
 
672
            }
 
673
        }
 
674
 
 
675
      if ( ma->only[i][j] )
 
676
        Disable( ma->menu[i][j] );
 
677
    }
 
678
 
 
679
  ListConnectRing( ma->active_groups );
 
680
  ma->active_groups = ListInsertPrev(group, ma->active_groups);
 
681
  ListBreakRing( ma->active_groups );
 
682
 
 
683
  if (group->item != NULL)
 
684
    SetStatus(group->item, TRUE);
 
685
 
 
686
  /* call the group "init" method (user-defined group constructor) */
 
687
  ma->trace.end.x = ma->trace.end.y = 0;
 
688
  ma->trace.start = ma->trace.end;
 
689
  if ( group->init )
 
690
    (*group->init->func)(ma, &ma->trace, ma->trace.end, group->init->data);
 
691
 
 
692
  return TRUE;
 
693
}
 
694
 
 
695
 
 
696
extern Boolean MA_LinkPanel(MAPtr ma, PaneL panel)
 
697
{
 
698
  if (ma == NULL  ||  panel == NULL)
 
699
    return FALSE;
 
700
 
 
701
  SetPanelClick(panel, MA_ClickCB, MA_DragCB, MA_HoldCB, MA_ReleaseCB);
 
702
  SetPanelExtra(panel, &ma); 
 
703
  ma->panel = panel;
 
704
  return TRUE;
 
705
}
 
706
 
 
707
 
 
708
extern PaneL MA_GetPanel(MAPtr ma)
 
709
{
 
710
  return (PaneL) (ma ? ma->panel : NULL);
 
711
}
 
712
 
 
713
 
 
714
extern void MA_UnlinkPanel(MAPtr ma)
 
715
{
 
716
  MAPtr ma_NULL = NULL;
 
717
 
 
718
  if (ma == NULL  ||  ma->panel == NULL)
 
719
    return;
 
720
 
 
721
  SetPanelClick(ma->panel, NULL, NULL, NULL, NULL);
 
722
  SetPanelExtra(ma->panel, &ma_NULL);
 
723
  ma->panel = NULL;
 
724
}
 
725
 
 
726
 
 
727
extern Boolean MA_SetVisible(MAPtr ma, Boolean visibility)
 
728
{
 
729
  if (!ma  ||  (!ma->group_menu  &&  !ma->action_menu))
 
730
    return FALSE;
 
731
 
 
732
  if ( visibility )
 
733
    {
 
734
      Show( ma->group_menu  );
 
735
      Show( ma->action_menu );
 
736
    }
 
737
  else
 
738
    {
 
739
      Hide( ma->group_menu  );
 
740
      Hide( ma->action_menu );
 
741
    }
 
742
 
 
743
  return TRUE;
 
744
}
 
745
 
 
746
 
 
747
extern Boolean MA_GetVisible(MAPtr ma)
 
748
{
 
749
  return (Boolean)
 
750
    (ma  &&
 
751
     ((ma->group_menu   &&  Visible(ma->group_menu )) ||
 
752
      (ma->action_menu  &&  Visible(ma->action_menu))));
 
753
}
 
754
 
 
755
 
 
756
extern void MA_SetExtra(MAPtr ma, VoidPtr extra)
 
757
{
 
758
  ma->extra = extra;
 
759
}
 
760
 
 
761
 
 
762
extern VoidPtr MA_GetExtra(MAPtr ma)
 
763
{
 
764
  return (ma ? ma->extra : NULL);
 
765
}
 
766
 
 
767
 
 
768
extern void MA_Reset(MAPtr ma)
 
769
{
 
770
  int i, j;
 
771
 
 
772
  /* unset all presently active groups */
 
773
  while ( ma->active_groups )
 
774
    VERIFY ( MA_UnsetGroup( (MA_GroupPtr)ma->active_groups->elem ) );
 
775
 
 
776
  /* Unlink panel */
 
777
  MA_UnlinkPanel( ma );
 
778
 
 
779
  /* Reset menu-based interface */
 
780
  if ( ma->action_menu )
 
781
    {
 
782
      Reset( ma->action_menu );
 
783
 
 
784
      for (i = 0;  i < MK_Default;  i++)
 
785
      for (j = 0;  j < MA_Init;     j++)
 
786
        ma->menu[i][j] = SubMenu(ma->action_menu, (CharPtr)MA_name[i][j]);
 
787
    }
 
788
 
 
789
  if ( ma->group_menu )
 
790
    {
 
791
      if (ma->group_menu == ma->action_menu)
 
792
        SeparatorItem( ma->action_menu );
 
793
      else
 
794
        Reset( ma->group_menu );
 
795
    }
 
796
 
 
797
  /* Reset internal data */
 
798
  MA_SetExtra(ma, NULL);
 
799
 
 
800
  while (ma->groups != NULL)
 
801
    {
 
802
      MemFree( ((MA_GroupPtr)ma->groups->elem)->name );
 
803
      MemFree( ma->groups->elem );
 
804
      ma->groups = ListDelete( ma->groups );
 
805
    }
 
806
 
 
807
  for (i = 0;  i < MK_Default;  i++)
 
808
  for (j = 0;  j < MA_Init;     j++)
 
809
    {
 
810
      ma->action[i][j] = NULL;
 
811
      ma->only  [i][j] = FALSE;
 
812
    }
 
813
 
 
814
  while ( ma->actions )
 
815
    {
 
816
      MemFree( ((MActionPtr)ma->actions->elem)->name );
 
817
      MemFree( ma->actions->elem );
 
818
      ma->actions = ListDelete( ma->actions );
 
819
    }
 
820
 
 
821
  ma->mod_key   = MK_Default;
 
822
  ma->last_type = MA_Default;
 
823
}
 
824
 
 
825
 
 
826
extern void MA_Destroy(MAPtr ma)
 
827
{
 
828
  MA_Reset( ma );
 
829
  MemFree( ma );
 
830
}
 
831
 
 
832
 
 
833
/* EOF ($RCSfile: vibmouse.c,v $) */
 
834