# File raggle, line 3961
      def NcursesInterface::save_bookmark

        # grab bookmark settings
        bm = $config['bookmark']
        return unless bm && bm.kind_of?(Array)
        
        # was the bookmark saved?
        was_saved = true

        # get feed categories
        item = $config['feeds'].get($a_feed)
        feed_cats = ' ' << (item['category'] || '')

        # get actual item
        desc_win = $wins[NcursesInterface::get_win_id('desc')]
        item = desc_win.items[desc_win.active_item]

        # get item information
        return unless item && item['title'] && (item['url'] || item['site'])
        title = item['title']
        time = Time.now.xmlschema
        url = item['site'] || item['url']

        NcursesInterface::set_status($config['msg_bm_saving'] % [title])

        # check to see if we need to get extended information
        get_ext = bm.any? { |bmb| !bmb[:no_desc] }
        get_tag = bm.any? { |bmb| !bmb[:no_tags] }

        ext, user_tags = '', ''        
        ext = NcursesInterface::get_input('bm_desc') if get_ext
        user_tags = NcursesInterface::get_input('bm_tag') if get_tag

        # iterate over bookmark backends and save bookmark to each one
        bm.each do |bmb|
          # get tags, add feed categories (unless disabled)
          tags = user_tags
          unless bmb.key?(:inherit_tags) && bmb[:inherit_tags] == false
            tags += feed_cats 
          end

          case bmb[:type]
          when :csv_file
            # expand bookmark file path
            path = Engine::expand_str(bmb[:path])
            
            # save title and bookmark to file
            begin
              # create CSV line from title, time, and URL
              csv_line = [title, url, time, ext, tags].map { |str| 
                '"' << str.gsub(/"/, '""') << '"' 
              }.join(',')
              
              # if the CSV doesn't exist, then prepend the columns
              unless File::exists?(path)
                csv_line = "title,url,time,description,tags\n" << csv_line
              end

              # append to CSV file
              File::open(path, 'a') { |file| file.puts(csv_line) }
            rescue Exception => err
              # couldn't write to bookmark file, set status
              was_saved = false
              status = $config['msg_bm_file_err'] % [path, err.to_s]
              NcursesInterface::set_status(status)
            end
          when :exec
            fork {
              system(bmb[:path], title, url, tags, ext)
            }
          when :db
            # build query
            cols, args = [], []
            { :title  => title,
              :url    => url,
              :tags   => tags,
              :desc   => ext,
            }.each_pair do |col_key, val|
              if bmb[:fields][col_key]
                cols << bmb[:fields][col_key]
                args << val
              end
            end

            begin 
              db, quote_meth = nil, nil

              # database-specific connection stuff
              case bmb[:dbtype]
              when :mysql
                unless $HAVE_LIB['mysql']
                  raise $config['msg_bm_db_missing'] % 'Mysql'
                end

                # connect to database, set quote method
                db = Mysql::connect(bmb[:host], bmb[:user], bmb[:pass])
                db.select_db(bmb[:dbname])
                quote_meth = Mysql::method(:escape_string)
              when :sqlite
                unless $HAVE_LIB['sqlite']
                  raise $config['msg_bm_db_missing'] % 'SQLite'
                end

                # connect to database, set quote method
                path = Engine::expand_str(bmb[:path])
                db = SQLite::Database.new(path)
                quote_meth = SQLite::Database.method(:quote)
              else
                # unknown database type
                raise $config['msg_bm_bad_db_type']
              end

              # build query
              query = "INSERT INTO #{bmb[:table]}(#{cols.join(',')}) 
                       VALUES " << '(' << args.map { |arg| 
                "'" << quote_meth.call(arg) << "'"
              }.join(',') << ')'

              # execute query
              db.query(query)
            rescue Exception => err
              was_saved = false
              status = $config['msg_bm_db_err'] % [err.to_s]
              NcursesInterface::set_status(status)
            end
          else
            # bad bookmark type
            was_saved = false
            status = $config['msg_bm_bad_type'] % [bmb[:type].to_s]
            NcursesInterface::set_status(status)
          end

          # set status indicating success
          status = $config['msg_bm_saved'] % [title]
          NcursesInterface::set_status(status) if was_saved
        end
      end