# File raggle, line 5298
    def Engine::grab_feed(feed)
      meth = 'Engine.grab_feed'
      t = Time.now
      
      # set the name and priority of the current thread
      Thread::current['feed'] = feed
      Thread::current.priority = $config['thread_priority_feed']
      
      msg = _("Checking feed")
      $new_status = " #{msg} \"#{feed['title']}\"..."
      $log.info(meth) { "#{msg} \"#{feed['title']}\"" }
      return unless feed['refresh'] > 0 && 
        feed['updated'] + (feed['refresh'] * 60) < t.to_i
      
      # update statusbar and grab log
      msg, src_msg = _("Updating feed"), _('from')
      $new_status = " #{msg} \"#{feed['title']}\"..."
      $log.info(meth) { "#{msg} \"#{feed['title']}\" #{src_msg} \"#{feed['url']}\"" }
      
      # get channel
      begin
        chan = Raggle::Feed::Channel.new(feed['url'], feed['last_modified'])
        feed.delete 'error'
      rescue
        err_msg = _('Error updating')
        err = feed['error'] = "#$!"

        if $config['mode'] == 'view'
          Raggle::Interfaces::NcursesInterface::set_status "#{err_msg} \"#{feed['title']}\"."
        end
        $log.error(meth) { "#{err_msg}: #{err}" }

        # mark this feed as updated so it doesn't get constantly polled
        feed['updated'] = t.to_i 
        return
      end
      
      # update feed attributes
      if !chan.last_modified ||
         chan.last_modified != feed['last_modified']
        Thread::critical = $config['use_critical_regions']
        feed['title'] = chan.title unless $config['lock_feed_title'] ||
                                          feed['lock_title?'] == true
        feed['desc'] = chan.desc
        feed['site'] = chan.link
        feed['image'] = chan.image
        feed['updated'] = t.to_i
    
        # Note: last_modified is slightly different than modified,
        # because we're using it as a token, not as a timestamp
        # -- paul
        feed['last_modified'] = chan.last_modified
        
        # hash the urls, save the read and visibility status
        status = {}
        feed['items'].each { |item| status[item['url']] = { :read => item['read?'], :visible => item['visible'] } }
    
        # clear the list if we're not saving feed items
        Thread::critical = $config['use_critical_regions']
        feed['items'].clear unless $config['save_feed_items'] ||
                                   feed['save_items?']
        Thread::critical = false
        
        # insert new items
        new_items = []
        chan.items.each { |item|
          unless (($config['save_feed_items'] ||
                   feed['save_items?']) &&
                  status.has_key?(item.link))
            if status.has_key?(item.link)
              was_read = status[item.link][:read]
              is_visible = status[item.link][:visible]
            else  # new item
              was_read = false; is_visible = true
            end
            new_items << {
              'title'   => item.title,
              'date'    => item.date,
              'url'     => item.link,
              'desc'    => item.desc,
              'read?'   => was_read,
              'visible' => is_visible,
              'added'   => Time.now.to_i,
            }
          end
        }
        
        # if we're saving old items, then prepend the new items
        # otherwise, replace the old list
        Thread::critical = $config['use_critical_regions']
        if $config['save_feed_items'] || feed['save_items?']
          feed['items'] = new_items + feed['items']
    
          max = $config['max_feed_items'] || feed['max_items']
          if max && max > 0
            old = (feed['items'].slice!(max .. -1) || []).size
            rm_msg = _('Removing %d old items.')
            $log.info(meth) { rm_msg % [old] }
          end
        else
          feed['items'] = new_items
        end

        if $config['do_beep']
          print "\a"
        end
        
        Thread::critical = false
      else
        feed['updated'] = t.to_i
        same_msg = _("Feed \"%s\" hasn't changed.")
        $log.info(meth) { same_msg % [feed['title']] }
      end
      
      # if this is the currently selected feed, then re-select it
      # so it's contents are updated
      # TODO: make this select the currently selected item again
      # (assuming it still exists)
      if $config['mode'] == 'view' && 
        !$config['run_http_server'] && !$config['run_drb_server'] &&
         $config['feeds'].get($a_feed)['url'] == feed['url']
         feed_win_id = Raggle::Interfaces::NcursesInterface::get_win_id('feed')
        $wins[feed_win_id].select_win_item
      end
    
      # redraw feed / item windows
      $update_wins = true
    end