Here's the concepts:
1. You'll need to combine components from /includes/modules/product_listing.php
Code:
$listing_split = new splitPageResults($listing_sql, MAX_DISPLAY_PRODUCTS_LISTING, 'p.products_id', 'page');
(substituting $categories_query for $listing_sql, since $listing_sql is the SQL query that determines the data to be pulled from the database
MAX_DISPLAY_PRODUCTS_LISTING is the number of records per page, as defined in the admin .... you will probably just end up hard-coding the number of desired records per page, rather than creating a new admin switch)
... combining that kind of selection code into /includes/modules/category_row.php
... keeping in mind that there is logic in that file for combining several subcats on a given row. Thus, you may have to accommodate the number of items per-row when calculating number of rows per page.
2. You'll need to take template-related display components from something like this in tpl_modules_product_listing.php:
Code:
<?php if ( ($listing_split->number_of_rows > 0) && ( (PREV_NEXT_BAR_LOCATION == '1') || (PREV_NEXT_BAR_LOCATION == '3') ) ) {
?>
<div id="productsListingTopNumber" class="navSplitPagesResult back"><?php echo $listing_split->display_count(TEXT_DISPLAY_NUMBER_OF_PRODUCTS); ?></div>
<div id="productsListingListingTopLinks" class="navSplitPagesLinks forward"><?php echo TEXT_RESULT_PAGE . ' ' . $listing_split->display_links(MAX_DISPLAY_PAGE_LINKS, zen_get_all_get_params(array('page', 'info', 'x', 'y', 'main_page'))); ?></div>
<br class="clearBoth" />
<?php
}
?>
and add it around something like this in the tpl_index_categories.php file
Code:
require($template->get_template_dir('tpl_modules_category_row.php',DIR_WS_TEMPLATE, $current_page_base,'templates'). '/tpl_modules_category_row.php');
You'll find the split_page_results logic used in various places on the storefront, and quite extensively in the admin, in case you need more examples of it in action.