a blast from the past

Well, i thought it was self explained but anyways. The actual monitor the encoder initial state, store them in a variable (OldPos) and then spin in round until the value change. Most encoder use the gray code.
http://en.wikipedia.org/wiki/Gray_code

now you need to know the direction, this is done by when you compare the NewPos and OldPos.

here's another version with a littlt bit more comments 'round.
Code:
    '
    '    ////////////////////////////////|\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\            
    '
                                    GetEncoder:
    '                               ===========
    '
    '    Procedure to get value change from rotary encoder
    '        1. Read variant of rotary encoder (move, enter pushbutton)
    '        2. Store result in 'MenuChoice' & 'MenuPointer' variables
    '
    '    Resume conditions:
    '    ------------------
    '        1. Encoder Move
    '        2. PBEnter button is pressed
    '        3. User move to previous menu
    '
    '    ////////////////////////////////|\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\            
    '
    OldPos = (PORTB & %11000000)>>6 ' get only PORTB<7:6> bits
    NewPos = OldPos 
        '   
        '    -----------------------------------------------------
        '    see if encoder has move or if ENTER button is pressed
        '    -----------------------------------------------------
    while ((NewPos==0) or (NewPos==3)) and PBEnter
       NewPos = (PORTB & %11000000)>>6 ' get only PORTB<7:6> bits
    wend
    pause 20 ' debounce delay
        '  
        '    --------------------
        '    Get encoder movement
        '    --------------------
        '
        '        Rotary encoder output table (clockWise rotation):
        '        -------------------------------------------------
        '               00
        '               01 between move (half detent)
        '               11
        '               10 between move (half detent)
        '
        '        Using XOR
        '
        '               OldPOS   : 0     0     3     3
        '               NewPos   : 1     2     1     2
        '               movement : CW   CCW   CCW    CW
        '           XOR -------------------------------
        '                          1     2     2     1
        '
        '    So, if NewPos XOR OldPos = 1 => increment
        '           Newpos XOR OldPos = 2 => Decrement    
        '
    Newpos=newpos ^ oldpos 
    select case newpos
        '
           case 1
               menuchoice=menuchoice+1
               Menupointer=menupointer+1
        '
           case 2
               menuchoice=menuchoice-1
               Menupointer=menupointer-1
        '
     end select
        '
        '    ---------------------------
        '    test the actual menu choice
        '    ---------------------------
        '        if higher than the maximum menu item... stay there
        '
    If menuchoice > Item then 
       menuchoice = Item
       menupointer = thisSCREENLINES
    endif
    return
For 5 different encoder, you'll have to read ALL related encoder i/o in oneshot, determine which one has moved, and in which direction. mmm

depending what else your program need to do, make sure you never miss any movements. you have to read and react really fast. Assembler could be handy here. For a background process, as you need 10 interrupts source, it's not going to be really easy.

Sometimes it's handy to have few different dedicated controller for that.