Corrected some bugs in AutoComplete.  Also, Page Up/Down in ACW implemented;
mouse and cursor selection in ACWindow implemented; double Tab inserts current
selection and closes ACW (similar to double-click and Return); scroll wheel now
works in ACW.  Added AutoComplete instructions to IDLE Help.
Backport of r53679
diff --git a/Lib/idlelib/AutoCompleteWindow.py b/Lib/idlelib/AutoCompleteWindow.py
index d02a695..9cdb830 100644
--- a/Lib/idlelib/AutoCompleteWindow.py
+++ b/Lib/idlelib/AutoCompleteWindow.py
@@ -10,13 +10,14 @@
 KEYPRESS_VIRTUAL_EVENT_NAME = "<<autocompletewindow-keypress>>"
 # We need to bind event beyond <Key> so that the function will be called
 # before the default specific IDLE function
-KEYPRESS_SEQUENCES = ("<Key>", "<Key-BackSpace>", "<Key-Return>",
-                      "<Key-Up>", "<Key-Down>", "<Key-Home>", "<Key-End>")
+KEYPRESS_SEQUENCES = ("<Key>", "<Key-BackSpace>", "<Key-Return>", "<Key-Tab>",
+                      "<Key-Up>", "<Key-Down>", "<Key-Home>", "<Key-End>",
+                      "<Key-Prior>", "<Key-Next>")
 KEYRELEASE_VIRTUAL_EVENT_NAME = "<<autocompletewindow-keyrelease>>"
 KEYRELEASE_SEQUENCE = "<KeyRelease>"
-LISTUPDATE_SEQUENCE = "<ButtonRelease>"
+LISTUPDATE_SEQUENCE = "<B1-ButtonRelease>"
 WINCONFIG_SEQUENCE = "<Configure>"
-DOUBLECLICK_SEQUENCE = "<Double-ButtonRelease>"
+DOUBLECLICK_SEQUENCE = "<B1-Double-ButtonRelease>"
 
 class AutoCompleteWindow:
 
@@ -49,6 +50,8 @@
         # event ids
         self.hideid = self.keypressid = self.listupdateid = self.winconfigid \
         = self.keyreleaseid = self.doubleclickid                         = None
+        # Flag set if last keypress was a tab
+        self.lastkey_was_tab = False
 
     def _change_start(self, newstart):
         i = 0
@@ -118,11 +121,6 @@
             i = 0
             while i < len(lts) and i < len(selstart) and lts[i] == selstart[i]:
                 i += 1
-            previous_completion = self.completions[cursel - 1]
-            while cursel > 0 and selstart[:i] <= previous_completion:
-                i += 1
-                if selstart == previous_completion:
-                    break  # maybe we have a duplicate?
             newstart = selstart[:i]
         self._change_start(newstart)
 
@@ -206,7 +204,7 @@
                                              self.keyrelease_event)
         self.widget.event_add(KEYRELEASE_VIRTUAL_EVENT_NAME,KEYRELEASE_SEQUENCE)
         self.listupdateid = listbox.bind(LISTUPDATE_SEQUENCE,
-                                         self.listupdate_event)
+                                         self.listselect_event)
         self.winconfigid = acw.bind(WINCONFIG_SEQUENCE, self.winconfig_event)
         self.doubleclickid = listbox.bind(DOUBLECLICK_SEQUENCE,
                                           self.doubleclick_event)
@@ -228,11 +226,12 @@
             return
         self.hide_window()
 
-    def listupdate_event(self, event):
+    def listselect_event(self, event):
         if not self.is_active():
             return
         self.userwantswindow = True
-        self._selection_changed()
+        cursel = int(self.listbox.curselection()[0])
+        self._change_start(self.completions[cursel])
 
     def doubleclick_event(self, event):
         # Put the selected completion in the text, and close the list
@@ -248,7 +247,8 @@
             state = event.mc_state
         else:
             state = 0
-
+        if keysym != "Tab":
+            self.lastkey_was_tab = False
         if (len(keysym) == 1 or keysym in ("underscore", "BackSpace")
             or (self.mode==AutoComplete.COMPLETE_FILES and keysym in
                 ("period", "minus"))) \
@@ -330,13 +330,21 @@
             self.listbox.select_clear(cursel)
             self.listbox.select_set(newsel)
             self._selection_changed()
+            self._change_start(self.completions[newsel])
             return "break"
 
         elif (keysym == "Tab" and not state):
-            # The user wants a completion, but it is handled by AutoComplete
-            # (not AutoCompleteWindow), so ignore.
-            self.userwantswindow = True
-            return
+            if self.lastkey_was_tab:
+                # two tabs in a row; insert current selection and close acw
+                cursel = int(self.listbox.curselection()[0])
+                self._change_start(self.completions[cursel])
+                self.hide_window()
+                return "break"
+            else:
+                # first tab; let AutoComplete handle the completion
+                self.userwantswindow = True
+                self.lastkey_was_tab = True
+                return
 
         elif reduce(lambda x, y: x or y,
                     [keysym.find(s) != -1 for s in ("Shift", "Control", "Alt",