protected function renderRow(array $row, $spanLeft, $spanMiddle, $spanRight)
    {
        $size = $this->_columnWidths;

        $buffer = '';
        $arrayPointer = [];
        $finalChunk = [];
        for ($i = 0, ($max = $this->calculateRowHeight($row)) ?: $max = 1; $i < $max; $i++) {
            $buffer .= $spanLeft . ' ';
            foreach ($size as $index => $cellSize) {
                $cell = $row[$index] ?? null;
                $prefix = '';
                if ($index !== 0) {
                    $buffer .= $spanMiddle . ' ';
                }
                if (is_array($cell)) {
                    if (empty($finalChunk[$index])) {
                        $finalChunk[$index] = '';
                        $start = 0;
                        $prefix = $this->_listPrefix;
                        if (!isset($arrayPointer[$index])) {
                            $arrayPointer[$index] = 0;
                        }
                    } else {
                        $start = mb_strwidth($finalChunk[$index], $this->app->encoding);
                    }
                    $chunk = mb_substr($cell[$arrayPointer[$index]], $start, $cellSize - 4, $this->app->encoding);
                    $finalChunk[$index] .= $chunk;
                    if (isset($cell[$arrayPointer[$index] + 1]) && $finalChunk[$index] === $cell[$arrayPointer[$index]]) {
                        $arrayPointer[$index]++;
                        $finalChunk[$index] = '';
                    }
                } else {
                    $chunk = mb_substr($cell, ($cellSize * $i) - ($i * 2), $cellSize - 2, $this->app->encoding);
                }
                $chunk = $prefix . $chunk;
                $repeat = $cellSize - mb_strwidth($chunk, $this->app->encoding) - 1;
                $buffer .= $chunk;
                if ($repeat >= 0) {
                    $buffer .= str_repeat(' ', $repeat);
                }
            }
            $buffer .= "$spanRight\n";
        }

        return $buffer;
    }