about summary refs log tree commit diff stats
path: root/wiki/lib/images/fileicons/html.png
blob: f45847f7e7d556c43cd602164e685fa5719fa178 (plain)
ofshex dumpascii
0000 89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 00 00 00 10 00 00 00 10 08 03 00 00 00 28 2d 0f .PNG........IHDR.............(-.
0020 53 00 00 00 84 50 4c 54 45 00 00 00 ff ff ff 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 S....PLTE.......................
0040 00 33 66 99 94 94 94 95 95 95 99 99 99 2a 54 7e 33 66 99 2f 5f 8f f8 f8 f8 f9 f9 f9 f9 f9 f9 fb .3f..........*T~3f./_...........
0060 fb fb fc fc fc 33 66 99 64 8a b1 65 8b b1 e6 e6 e6 e7 e7 e7 e9 e9 e9 ea ea ea eb eb eb ec ec ec .....3f.d..e....................
0080 ed ed ed ef ef ef f0 f0 f0 f1 f1 f1 f2 f2 f2 f3 f3 f3 f4 f4 f4 f5 f5 f5 f6 f6 f6 f7 f7 f7 f8 f8 ................................
00a0 f8 f9 f9 f9 fb fb fb fc fc fc ff ff ff b5 78 98 09 00 00 00 14 74 52 4e 53 00 00 02 1c 20 32 34 ..............x......tRNS.....24
00c0 36 7e 91 91 91 9b bf cd f1 f3 f5 fd fd bf 58 da f0 00 00 00 8e 49 44 41 54 18 19 05 c1 31 52 c3 6~............X......IDAT....1R.
00e0 30 10 00 c0 bd 93 15 7b 02 0d 43 21 aa f0 ff 6f d1 a9 65 26 80 01 49 d9 8d 58 25 13 30 e6 b2 91 0......{..C!...o..e&..I..X%.0...
0100 d7 f2 06 c6 c7 df 5c 25 d4 fd 65 8e 71 9e f7 eb fa 9f 0a db 4d 11 6b cd 63 7b fe 99 09 29 95 0c ......\%..e.q.......M.k.c{...)..
0120 75 7f 2f 1b 44 88 59 ea e7 1c af 36 08 22 89 51 88 a3 ee 00 c8 af ac 37 4d 6b 4d 6b 9a 99 b9 43 u./.D.Y....6.".Q.......7MkMk...C
0140 d7 e9 ad 37 97 a4 01 80 a4 03 80 3c 01 80 df 38 ea 0e 80 f8 8e 58 97 a7 6c 80 3e ee 11 ab 94 00 ...7.......<...8.....X..l.>.....
0160 30 e7 03 1a b9 2e 4f e8 04 34 ba 00 00 00 00 49 45 4e 44 ae 42 60 82 0.....O..4.....IEND.B`.
08' href='#n108'>108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224
# This file is part of ranger, the console file manager.
# License: GNU GPL version 3, see the file "AUTHORS" for details.

"""The pager displays text and allows you to scroll inside it."""

from . import Widget
from ranger.core.loader import CommandLoader
from ranger.gui import ansi
from ranger.ext.direction import Direction
from ranger.ext.img_display import ImgDisplayUnsupportedException

# TODO: Scrolling in embedded pager
class Pager(Widget):
    source = None
    source_is_stream = False

    old_source = None
    old_scroll_begin = 0
    old_startx = 0
    need_clear_image = False
    need_redraw_image = False
    max_width = None
    def __init__(self, win, embedded=False):
        Widget.__init__(self, win)
        self.embedded = embedded
        self.scroll_begin = 0
        self.startx = 0
        self.markup = None
        self.lines = []
        self.image = None
        self.image_drawn = False

    def open(self):
        self.scroll_begin = 0
        self.markup = None
        self.max_width = 0
        self.startx = 0
        self.need_redraw = True

    def clear_image(self, force=False):
        if (force or self.need_clear_image) and self.image_drawn:
            self.fm.image_displayer.clear(self.x, self.y, self.wid, self.hei)
            self.need_clear_image = False
            self.image_drawn = False

    def close(self):
        if self.image:
            self.need_clear_image = True
            self.clear_image()
        if self.source and self.source_is_stream:
            self.source.close()

    def destroy(self):
        self.clear_image(force=True)

    def finalize(self):
        self.fm.ui.win.move(self.y, self.x)

    def draw(self):
        if self.need_clear_image:
            self.need_redraw = True

        if self.old_source != self.source:
            self.old_source = self.source
            self.need_redraw = True

        if self.old_scroll_begin != self.scroll_begin or \
                self.old_startx != self.startx:
            self.old_startx = self.startx
            self.old_scroll_begin = self.scroll_begin
            self.need_redraw = True

        if self.need_redraw:
            self.win.erase()
            self.need_redraw_image = True
            self.clear_image()

            if not self.image:
                line_gen = self._generate_lines(
                        starty=self.scroll_begin, startx=self.startx)

                for line, i in zip(line_gen, range(self.hei)):
                    self._draw_line(i, line)

            self.need_redraw = False

    def draw_image(self):
        if self.image and self.need_redraw_image:
            self.source = None
            self.need_redraw_image = False
            try:
                self.fm.image_displayer.draw(self.image, self.x, self.y,
                        self.wid, self.hei)
            except ImgDisplayUnsupportedException:
                self.fm.settings.preview_images = False
            except Exception as e:
                self.fm.notify(e, bad=True)
            else:
                self.image_drawn = True

    def _draw_line(self, i, line):
        if self.markup is None:
            self.addstr(i, 0, line)
        elif self.markup == 'ansi':
            try:
                self.win.move(i, 0)
            except:
                pass
            else:
                for chunk in ansi.text_with_fg_bg_attr(line):
                    if isinstance(chunk, tuple):
                        self.set_fg_bg_attr(*chunk)
                    else:
                        self.addstr(chunk)

    def move(self, narg=None, **kw):
        direction = Direction(kw)
        if direction.horizontal():
            self.startx = direction.move(
                    direction=direction.right(),
                    override=narg,
                    maximum=self.max_width,
                    current=self.startx,
                    pagesize=self.wid,
                    offset=-self.wid + 1)
        if direction.vertical():
            if self.source_is_stream:
                self._get_line(self.scroll_begin + self.hei * 2)
            self.scroll_begin = direction.move(
                    direction=direction.down(),
                    override=narg,
                    maximum=len(self.lines),
                    current=self.scroll_begin,
                    pagesize=self.hei,
                    offset=-self.hei + 1)

    def press(self, key):
        self.fm.ui.keymaps.use_keymap('pager')
        self.fm.ui.press(key)

    def set_image(self, image):
        if self.image:
            self.need_clear_image = True
        self.image = image

        if self.source and self.source_is_stream:
            self.source.close()
        self.source = None
        self.source_is_stream = False

    def set_source(self, source, strip=False):
        if self.image:
            self.image = None
            self.need_clear_image = True

        if self.source and self.source_is_stream:
            self.source.close()

        self.max_width = 0
        if isinstance(source, str):
            self.source_is_stream = False
            self.lines = source.splitlines()
            if self.lines:
                self.max_width = max(len(line) for line in self.lines)
        elif hasattr(source, '__getitem__'):
            self.source_is_stream = False
            self.lines = source
            if self.lines:
                self.max_width = max(len(line) for line in source)
        elif hasattr(source, 'readline'):
            self.source_is_stream = True
            self.lines = []
        else:
            self.source = None
            self.source_is_stream = False
            return False
        self.markup = 'ansi'

        if not self.source_is_stream and strip:
            self.lines = map(lambda x: x.strip(), self.lines)

        self.source = source
        return True

    def click(self, event):
        n = event.ctrl() and 1 or 3
        direction = event.mouse_wheel_direction()
        if direction:
            self.move(down=direction * n)
        return True

    def _get_line(self, n, attempt_to_read=True):
        assert isinstance(n, int), n
        try:
            return self.lines[n]
        except (KeyError, IndexError):
            if attempt_to_read and self.source_is_stream:
                try:
                    for l in self.source:
                        if len(l) > self.max_width:
                            self.max_width = len(l)
                        self.lines.append(l)
                        if len(self.lines) > n:
                            break
                except (UnicodeError, IOError):
                    pass
                return self._get_line(n, attempt_to_read=False)
            return ""

    def _generate_lines(self, starty, startx):
        i = starty
        if not self.source:
            raise StopIteration
        while True:
            try:
                line = self._get_line(i).expandtabs(4)
                if self.markup is 'ansi':
                    line = ansi.char_slice(line, startx, self.wid) + ansi.reset
                else:
                    line = line[startx:self.wid + startx]
                yield line.rstrip()
            except IndexError:
                raise StopIteration
            i += 1