Update po/mc.pot and po/*.po files.
[midnight-commander.git] / src / viewer / growbuf.c
blob64ccc9f7759b1fe317b633c1e43c07e478ca7211
1 /*
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, 2011
7 The Free Software Foundation, Inc.
9 Written by:
10 Miguel de Icaza, 1994, 1995, 1998
11 Janne Kukonlehto, 1994, 1995
12 Jakub Jelinek, 1995
13 Joseph M. Hinkle, 1996
14 Norbert Warmuth, 1997
15 Pavel Machek, 1998
16 Roland Illig <roland.illig@gmx.de>, 2004, 2005
17 Slava Zanko <slavazanko@google.com>, 2009
18 Andrew Borodin <aborodin@vmail.ru>, 2009
19 Ilia Maslakov <il.smind@gmail.com>, 2009
21 This file is part of the Midnight Commander.
23 The Midnight Commander is free software: you can redistribute it
24 and/or modify it under the terms of the GNU General Public License as
25 published by the Free Software Foundation, either version 3 of the License,
26 or (at your option) any later version.
28 The Midnight Commander is distributed in the hope that it will be useful,
29 but WITHOUT ANY WARRANTY; without even the implied warranty of
30 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31 GNU General Public License for more details.
33 You should have received a copy of the GNU General Public License
34 along with this program. If not, see <http://www.gnu.org/licenses/>.
37 #include <config.h>
38 #include <errno.h>
40 #include "lib/global.h"
41 #include "lib/vfs/vfs.h"
42 #include "lib/util.h"
43 #include "lib/widget.h" /* D_NORMAL */
45 #include "internal.h"
47 /* Block size for reading files in parts */
48 #define VIEW_PAGE_SIZE ((size_t) 8192)
50 /*** global variables ****************************************************************************/
52 /*** file scope macro definitions ****************************************************************/
54 /*** file scope type declarations ****************************************************************/
56 /*** file scope variables ************************************************************************/
58 /*** file scope functions ************************************************************************/
59 /* --------------------------------------------------------------------------------------------- */
61 /* --------------------------------------------------------------------------------------------- */
62 /*** public functions ****************************************************************************/
63 /* --------------------------------------------------------------------------------------------- */
65 void
66 mcview_growbuf_init (mcview_t * view)
68 view->growbuf_in_use = TRUE;
69 view->growbuf_blockptr = g_ptr_array_new ();
70 view->growbuf_lastindex = VIEW_PAGE_SIZE;
71 view->growbuf_finished = FALSE;
74 /* --------------------------------------------------------------------------------------------- */
76 void
77 mcview_growbuf_free (mcview_t * view)
79 #ifdef HAVE_ASSERT_H
80 assert (view->growbuf_in_use);
81 #endif
83 g_ptr_array_foreach (view->growbuf_blockptr, (GFunc) g_free, NULL);
85 (void) g_ptr_array_free (view->growbuf_blockptr, TRUE);
87 view->growbuf_blockptr = NULL;
88 view->growbuf_in_use = FALSE;
91 /* --------------------------------------------------------------------------------------------- */
93 off_t
94 mcview_growbuf_filesize (mcview_t * view)
96 #ifdef HAVE_ASSERT_H
97 assert (view->growbuf_in_use);
98 #endif
100 if (view->growbuf_blockptr->len == 0)
101 return 0;
102 else
103 return ((off_t) view->growbuf_blockptr->len - 1) * VIEW_PAGE_SIZE + view->growbuf_lastindex;
106 /* --------------------------------------------------------------------------------------------- */
107 /** Copies the output from the pipe to the growing buffer, until either
108 * the end-of-pipe is reached or the interval [0..ofs) of the growing
109 * buffer is completely filled.
112 void
113 mcview_growbuf_read_until (mcview_t * view, off_t ofs)
115 ssize_t nread;
116 byte *p;
117 size_t bytesfree;
118 gboolean short_read;
120 #ifdef HAVE_ASSERT_H
121 assert (view->growbuf_in_use);
122 #endif
124 if (view->growbuf_finished)
125 return;
127 short_read = FALSE;
128 while (mcview_growbuf_filesize (view) < ofs || short_read)
130 if (view->growbuf_lastindex == VIEW_PAGE_SIZE)
132 /* Append a new block to the growing buffer */
133 byte *newblock = g_try_malloc (VIEW_PAGE_SIZE);
134 if (newblock == NULL)
135 return;
137 g_ptr_array_add (view->growbuf_blockptr, newblock);
138 view->growbuf_lastindex = 0;
140 p = g_ptr_array_index (view->growbuf_blockptr,
141 view->growbuf_blockptr->len - 1) + view->growbuf_lastindex;
143 bytesfree = VIEW_PAGE_SIZE - view->growbuf_lastindex;
145 if (view->datasource == DS_STDIO_PIPE)
147 nread = fread (p, 1, bytesfree, view->ds_stdio_pipe);
148 if (nread == 0)
150 view->growbuf_finished = TRUE;
151 (void) pclose (view->ds_stdio_pipe);
152 mcview_display (view);
153 close_error_pipe (D_NORMAL, NULL);
154 view->ds_stdio_pipe = NULL;
155 return;
158 else
160 #ifdef HAVE_ASSERT_H
161 assert (view->datasource == DS_VFS_PIPE);
162 #endif
165 nread = mc_read (view->ds_vfs_pipe, p, bytesfree);
167 while (nread == -1 && errno == EINTR);
168 if (nread == -1 || nread == 0)
170 view->growbuf_finished = TRUE;
171 (void) mc_close (view->ds_vfs_pipe);
172 view->ds_vfs_pipe = -1;
173 return;
176 short_read = ((size_t) nread < bytesfree);
177 view->growbuf_lastindex += nread;
181 /* --------------------------------------------------------------------------------------------- */
183 gboolean
184 mcview_get_byte_growing_buffer (mcview_t * view, off_t byte_index, int *retval)
186 off_t pageno;
187 off_t pageindex;
189 if (retval != NULL)
190 *retval = -1;
192 pageno = byte_index / VIEW_PAGE_SIZE;
193 pageindex = byte_index % VIEW_PAGE_SIZE;
195 #ifdef HAVE_ASSERT_H
196 assert (view->growbuf_in_use);
197 #endif
199 if (pageno < 0)
200 return FALSE;
202 mcview_growbuf_read_until (view, byte_index + 1);
203 if (view->growbuf_blockptr->len == 0)
204 return FALSE;
205 if (pageno < (off_t) view->growbuf_blockptr->len - 1)
207 if (retval != NULL)
208 *retval = *((byte *) (g_ptr_array_index (view->growbuf_blockptr, pageno) + pageindex));
209 return TRUE;
211 if (pageno == (off_t) view->growbuf_blockptr->len - 1
212 && pageindex < (off_t) view->growbuf_lastindex)
214 if (retval != NULL)
215 *retval = *((byte *) (g_ptr_array_index (view->growbuf_blockptr, pageno) + pageindex));
216 return TRUE;
218 return FALSE;
221 /* --------------------------------------------------------------------------------------------- */
223 char *
224 mcview_get_ptr_growing_buffer (mcview_t * view, off_t byte_index)
226 off_t pageno = byte_index / VIEW_PAGE_SIZE;
227 off_t pageindex = byte_index % VIEW_PAGE_SIZE;
229 #ifdef HAVE_ASSERT_H
230 assert (view->growbuf_in_use);
231 #endif
233 if (pageno < 0)
234 return NULL;
236 mcview_growbuf_read_until (view, byte_index + 1);
237 if (view->growbuf_blockptr->len == 0)
238 return NULL;
239 if (pageno < (off_t) view->growbuf_blockptr->len - 1)
240 return (char *) (g_ptr_array_index (view->growbuf_blockptr, pageno) + pageindex);
241 if (pageno == (off_t) view->growbuf_blockptr->len - 1
242 && pageindex < (off_t) view->growbuf_lastindex)
243 return (char *) (g_ptr_array_index (view->growbuf_blockptr, pageno) + pageindex);
244 return NULL;
247 /* --------------------------------------------------------------------------------------------- */