}
    void advanceMultipleSelection (ListSelectionModel firstModel, int firstMin,                                   int firstMax, ListSelectionModel secondModel,                                    int secondMin, int secondMax, boolean reverse,                                   boolean eventIsTab)  {      // If eventIsTab, all the "firsts" correspond to columns, otherwise, to rows      // "seconds" correspond to the opposite      int firstLead = firstModel.getLeadSelectionIndex();      int secondLead = secondModel.getLeadSelectionIndex();      int numFirsts = eventIsTab ?         table.getModel().getColumnCount() : table.getModel().getRowCount();      int numSeconds = eventIsTab ?         table.getModel().getRowCount() : table.getModel().getColumnCount();      // check if we have to wrap the "firsts" around, going to the other side      if ((firstLead == firstMax && !reverse) ||           (reverse && firstLead == firstMin))    {          firstModel.addSelectionInterval(reverse ? firstMax : firstMin,                                           reverse ? firstMax : firstMin);                    // check if we have to wrap the "seconds"          if ((secondLead == secondMax && !reverse) ||               (reverse && secondLead == secondMin))            secondModel.addSelectionInterval(reverse ? secondMax : secondMin,                                              reverse ? secondMax : secondMin);          // if we're not wrapping the seconds, we have to find out where we          // are within the secondModel and advance to the next cell (or           // go back to the previous cell if reverse == true)          else            {              int[] secondsSelected;              if (eventIsTab && table.getRowSelectionAllowed() ||                   !eventIsTab && table.getColumnSelectionAllowed())                secondsSelected = eventIsTab ?                   table.getSelectedRows() : table.getSelectedColumns();              else                {                  // if row selection is not allowed, then the entire column gets                  // selected when you click on it, so consider ALL rows selected                  secondsSelected = new int[numSeconds];                  for (int i = 0; i < numSeconds; i++)                  secondsSelected[i] = i;        }              // and now find the "next" index within the model              int secondIndex = reverse ? secondsSelected.length - 1 : 0;              if (!reverse)                while (secondsSelected[secondIndex] <= secondLead)                  secondIndex++;              else                while (secondsSelected[secondIndex] >= secondLead)                  secondIndex--;              // and select it - updating the lead selection index              secondModel.addSelectionInterval(secondsSelected[secondIndex],                                                secondsSelected[secondIndex]);    }    }      // We didn't have to wrap the firsts, so just find the "next" first      // and select it, we don't have to change "seconds"      else    {          int[] firstsSelected;          if (eventIsTab && table.getColumnSelectionAllowed() ||               !eventIsTab && table.getRowSelectionAllowed())            firstsSelected = eventIsTab ?               table.getSelectedColumns() : table.getSelectedRows();          else        {                                                     // if selection not allowed, consider ALL firsts to be selected              firstsSelected = new int[numFirsts];              for (int i = 0; i < numFirsts; i++)                firstsSelected[i] = i;        }          int firstIndex = reverse ? firstsSelected.length - 1 : 0;          if (!reverse)            while (firstsSelected[firstIndex] <= firstLead)              firstIndex++;      else            while (firstsSelected[firstIndex] >= firstLead)              firstIndex--;          firstModel.addSelectionInterval(firstsSelected[firstIndex],                                           firstsSelected[firstIndex]);          secondModel.addSelectionInterval(secondLead, secondLead);    }  }