void
dmz::InputModuleBasic::release_input_observer (
      const Handle Channel,
      const Mask EventMask,
      InputObserver &obs) {

   if (_inEvent) { _que_event (new ReleaseObserverStruct (Channel, EventMask, obs)); } 
   else {

      _inEvent = True;

      ChannelStruct *cs (_channelTable.lookup (Channel));
      const Handle ObsHandle (obs.get_input_observer_handle ());
      ObsStruct *os (_obsTable.lookup (ObsHandle));

      if (cs && os) {

         Mask *obsMask (os->table.lookup (Channel));

         if (obsMask) {

            Mask updateMask;

            if (EventMask & LocalStateMask) {

               if (cs->stateTable.remove (ObsHandle)) { obsMask->unset (LocalStateMask); }
            }

            if (EventMask & LocalAxisMask) {

               if (cs->axisTable.remove (ObsHandle)) {

                  obsMask->unset (LocalAxisMask);
                  updateMask |= LocalAxisMask;
               }
            }

            if (EventMask & LocalButtonMask) {

               if (cs->buttonTable.remove (ObsHandle)) {

                  obsMask->unset (LocalButtonMask);
                  updateMask |= LocalButtonMask;
               }
            }

            if (EventMask & LocalSwitchMask) {

               if (cs->switchTable.remove (ObsHandle)) {

                  obsMask->unset (LocalSwitchMask);
                  updateMask |= LocalSwitchMask;
               }
            }

            if (EventMask & LocalKeyMask) {

               if (cs->keyTable.remove (ObsHandle)) {

                  obsMask->unset (LocalKeyMask);
                  updateMask |= LocalKeyMask;
               }
            }

            if (EventMask & LocalMouseMask) {

               if (cs->mouseTable.remove (ObsHandle)) {

                  obsMask->unset (LocalMouseMask);
                  updateMask |= LocalMouseMask;
               }
            }

            if (EventMask & LocalDataMask) {

               if (cs->dataTable.remove (ObsHandle)) {

                  obsMask->unset (LocalDataMask);
                  updateMask |= LocalDataMask;
               }
            }

            if (cs->active && updateMask.is_set ()) {

               _decrement_active_count (cs->ChannelHandle, updateMask, *os);
            }

            if (!obsMask->is_set ()) {

               cs->activeTable.remove (os->ObsHandle);

               if (os->table.remove (Channel)) { delete obsMask; obsMask = 0; }

               if (os->table.get_count () == 0) {

                  if (_obsTable.remove (ObsHandle)) { delete os; os = 0; }
               }
            }
         }
      }

      _inEvent = False;

      _do_qued_events ();
   }
}
// Input Module Interface
void
dmz::InputModuleBasic::register_input_observer (
      const Handle Channel,
      const Mask EventMask,
      InputObserver &obs) {

   ChannelStruct *cs (_create_channel (Channel));

   if (cs) {

      const Handle ObsHandle (obs.get_input_observer_handle ());

      ObsStruct *os (_obsTable.lookup (ObsHandle));

      if (!os) {

         os = new ObsStruct (obs);

         if (os) { if (!_obsTable.store (ObsHandle, os)) { delete os; os = 0; } }
      }

      Mask *obsMask (0);

      if (os) {

         obsMask = os->table.lookup (Channel);

         if (!obsMask) {

            obsMask = new Mask;

            if (!os->table.store (Channel, obsMask)) { delete obsMask; obsMask = 0; }
         }

         if (obsMask) {

            Mask updateMask;

            if (EventMask & LocalStateMask) {

               if (cs->stateTable.store (ObsHandle, &obs)) {

                  *obsMask |= LocalStateMask;
               }
            }

            if (EventMask & LocalAxisMask) {

               if (cs->axisTable.store (ObsHandle, os)) {

                  *obsMask |= LocalAxisMask;
                  updateMask |= LocalAxisMask;
               }
            }

            if (EventMask & LocalButtonMask) {

               if (cs->buttonTable.store (ObsHandle, os)) {

                  *obsMask |= LocalButtonMask;
                  updateMask |= LocalButtonMask;
               }
            }

            if (EventMask & LocalSwitchMask) {

               if (cs->switchTable.store (ObsHandle, os)) {

                  *obsMask |= LocalSwitchMask;
                  updateMask |= LocalSwitchMask;
               }
            }

            if (EventMask & LocalKeyMask) {

               if (cs->keyTable.store (ObsHandle, os)) {

                  *obsMask |= LocalKeyMask;
                  updateMask |= LocalKeyMask;
               }
            }

            if (EventMask & LocalMouseMask) {

               if (cs->mouseTable.store (ObsHandle, os)) {

                  *obsMask |= LocalMouseMask;
                  updateMask |= LocalMouseMask;
               }
            }

            if (EventMask & LocalDataMask) {

               if (cs->dataTable.store (ObsHandle, os)) {

                  *obsMask |= LocalDataMask;
                  updateMask |= LocalDataMask;
               }
            }

            if (obsMask->is_set ()) {

               cs->activeTable.store (os->ObsHandle, os);

               if (cs->active && updateMask.is_set ()) {

                  _increment_active_count (cs->ChannelHandle, updateMask, *os);
               }
            }
            else if (os->table.remove (Channel)) {

               delete obsMask; obsMask = 0;
               cs->activeTable.remove (os->ObsHandle);
            }

            // This call need to be last because the observer may be removed in this
            // call.
            if (EventMask & LocalStateMask) {

               if (cs->active) { obs.update_channel_state (Channel, True); }
            }
         }
      }
   }
}