2 Internal file viewer for the Midnight Commander
3 Function for work with growing bufers
5 Copyright (C) 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2003,
6 2004, 2005, 2006, 2007, 2009 Free Software Foundation, Inc.
8 Written by: 1994, 1995, 1998 Miguel de Icaza
9 1994, 1995 Janne Kukonlehto
14 2004 Roland Illig <roland.illig@gmx.de>
15 2005 Roland Illig <roland.illig@gmx.de>
16 2009 Slava Zanko <slavazanko@google.com>
17 2009 Andrew Borodin <aborodin@vmail.ru>
18 2009 Ilia Maslakov <il.smind@gmail.com>
20 This file is part of the Midnight Commander.
22 The Midnight Commander is free software; you can redistribute it
23 and/or modify it under the terms of the GNU General Public License as
24 published by the Free Software Foundation; either version 2 of the
25 License, or (at your option) any later version.
27 The Midnight Commander is distributed in the hope that it will be
28 useful, but WITHOUT ANY WARRANTY; without even the implied warranty
29 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
30 General Public License for more details.
32 You should have received a copy of the GNU General Public License
33 along with this program; if not, write to the Free Software
34 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
41 #include "lib/global.h"
42 #include "lib/vfs/vfs.h"
44 #include "lib/widget.h" /* D_NORMAL */
48 /* Block size for reading files in parts */
49 #define VIEW_PAGE_SIZE ((size_t) 8192)
51 /*** global variables ****************************************************************************/
53 /*** file scope macro definitions ****************************************************************/
55 /*** file scope type declarations ****************************************************************/
57 /*** file scope variables ************************************************************************/
59 /*** file scope functions ************************************************************************/
60 /* --------------------------------------------------------------------------------------------- */
62 /* --------------------------------------------------------------------------------------------- */
63 /*** public functions ****************************************************************************/
64 /* --------------------------------------------------------------------------------------------- */
67 mcview_growbuf_init (mcview_t
* view
)
69 view
->growbuf_in_use
= TRUE
;
70 view
->growbuf_blockptr
= g_ptr_array_new ();
71 view
->growbuf_lastindex
= VIEW_PAGE_SIZE
;
72 view
->growbuf_finished
= FALSE
;
75 /* --------------------------------------------------------------------------------------------- */
78 mcview_growbuf_free (mcview_t
* view
)
80 assert (view
->growbuf_in_use
);
82 g_ptr_array_foreach (view
->growbuf_blockptr
, (GFunc
) g_free
, NULL
);
84 (void) g_ptr_array_free (view
->growbuf_blockptr
, TRUE
);
86 view
->growbuf_blockptr
= NULL
;
87 view
->growbuf_in_use
= FALSE
;
90 /* --------------------------------------------------------------------------------------------- */
93 mcview_growbuf_filesize (mcview_t
* view
)
95 assert (view
->growbuf_in_use
);
97 if (view
->growbuf_blockptr
->len
== 0)
100 return ((off_t
) view
->growbuf_blockptr
->len
- 1) * VIEW_PAGE_SIZE
+ view
->growbuf_lastindex
;
103 /* --------------------------------------------------------------------------------------------- */
104 /** Copies the output from the pipe to the growing buffer, until either
105 * the end-of-pipe is reached or the interval [0..ofs) of the growing
106 * buffer is completely filled.
110 mcview_growbuf_read_until (mcview_t
* view
, off_t ofs
)
117 assert (view
->growbuf_in_use
);
119 if (view
->growbuf_finished
)
123 while (mcview_growbuf_filesize (view
) < ofs
|| short_read
)
125 if (view
->growbuf_lastindex
== VIEW_PAGE_SIZE
)
127 /* Append a new block to the growing buffer */
128 byte
*newblock
= g_try_malloc (VIEW_PAGE_SIZE
);
129 if (newblock
== NULL
)
132 g_ptr_array_add (view
->growbuf_blockptr
, newblock
);
133 view
->growbuf_lastindex
= 0;
135 p
= g_ptr_array_index (view
->growbuf_blockptr
,
136 view
->growbuf_blockptr
->len
- 1) + view
->growbuf_lastindex
;
138 bytesfree
= VIEW_PAGE_SIZE
- view
->growbuf_lastindex
;
140 if (view
->datasource
== DS_STDIO_PIPE
)
142 nread
= fread (p
, 1, bytesfree
, view
->ds_stdio_pipe
);
145 view
->growbuf_finished
= TRUE
;
146 (void) pclose (view
->ds_stdio_pipe
);
147 mcview_display (view
);
148 close_error_pipe (D_NORMAL
, NULL
);
149 view
->ds_stdio_pipe
= NULL
;
155 assert (view
->datasource
== DS_VFS_PIPE
);
158 nread
= mc_read (view
->ds_vfs_pipe
, p
, bytesfree
);
160 while (nread
== -1 && errno
== EINTR
);
161 if (nread
== -1 || nread
== 0)
163 view
->growbuf_finished
= TRUE
;
164 (void) mc_close (view
->ds_vfs_pipe
);
165 view
->ds_vfs_pipe
= -1;
169 short_read
= ((size_t) nread
< bytesfree
);
170 view
->growbuf_lastindex
+= nread
;
174 /* --------------------------------------------------------------------------------------------- */
177 mcview_get_byte_growing_buffer (mcview_t
* view
, off_t byte_index
, int *retval
)
185 pageno
= byte_index
/ VIEW_PAGE_SIZE
;
186 pageindex
= byte_index
% VIEW_PAGE_SIZE
;
188 assert (view
->growbuf_in_use
);
193 mcview_growbuf_read_until (view
, byte_index
+ 1);
194 if (view
->growbuf_blockptr
->len
== 0)
196 if (pageno
< (off_t
) view
->growbuf_blockptr
->len
- 1)
199 *retval
= *((byte
*) (g_ptr_array_index (view
->growbuf_blockptr
, pageno
) + pageindex
));
202 if (pageno
== (off_t
) view
->growbuf_blockptr
->len
- 1
203 && pageindex
< (off_t
) view
->growbuf_lastindex
)
206 *retval
= *((byte
*) (g_ptr_array_index (view
->growbuf_blockptr
, pageno
) + pageindex
));
212 /* --------------------------------------------------------------------------------------------- */
215 mcview_get_ptr_growing_buffer (mcview_t
* view
, off_t byte_index
)
217 off_t pageno
= byte_index
/ VIEW_PAGE_SIZE
;
218 off_t pageindex
= byte_index
% VIEW_PAGE_SIZE
;
220 assert (view
->growbuf_in_use
);
225 mcview_growbuf_read_until (view
, byte_index
+ 1);
226 if (view
->growbuf_blockptr
->len
== 0)
228 if (pageno
< (off_t
) view
->growbuf_blockptr
->len
- 1)
229 return (char *) (g_ptr_array_index (view
->growbuf_blockptr
, pageno
) + pageindex
);
230 if (pageno
== (off_t
) view
->growbuf_blockptr
->len
- 1
231 && pageindex
< (off_t
) view
->growbuf_lastindex
)
232 return (char *) (g_ptr_array_index (view
->growbuf_blockptr
, pageno
) + pageindex
);
236 /* --------------------------------------------------------------------------------------------- */