1 /* hexer.h	8/19/1995
2  */
3 
4 /* Copyright (c) 1995,1996 Sascha Demetrio
5  * Copyright (c) 2009, 2015, 2016 Peter Pentchev
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  *    If you modify any part of HEXER and redistribute it, you must add
14  *    a notice to the `README' file and the modified source files containing
15  *    information about the  changes you made.  I do not want to take
16  *    credit or be blamed for your modifications.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  *    If you modify any part of HEXER and redistribute it in binary form,
21  *    you must supply a `README' file containing information about the
22  *    changes you made.
23  * 3. The name of the developer may not be used to endorse or promote
24  *    products derived from this software without specific prior written
25  *    permission.
26  *
27  * HEXER WAS DEVELOPED BY SASCHA DEMETRIO.
28  * THIS SOFTWARE SHOULD NOT BE CONSIDERED TO BE A COMMERCIAL PRODUCT.
29  * THE DEVELOPER URGES THAT USERS WHO REQUIRE A COMMERCIAL PRODUCT
30  * NOT MAKE USE OF THIS WORK.
31  *
32  * DISCLAIMER:
33  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPER ``AS IS'' AND
34  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
35  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
36  * ARE DISCLAIMED.  IN NO EVENT SHALL THE DEVELOPER BE LIABLE
37  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
38  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
39  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
40  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
41  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
42  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
43  * SUCH DAMAGE.
44  */
45 
46 #ifndef _HEXER_H_
47 #define _HEXER_H_
48 
49 #include "config.h"
50 #include "defs.h"
51 
52 #include <stdio.h>
53 #include <stdarg.h>
54 
55 #if HAVE_ALLOCA_H
56 #include <alloca.h>
57 #else
58 /**
59  * Sigh, some platforms insist on hiding alloca(3) with _POSIX_C_SOURCE or
60  * _XOPEN_SOURCE, so we'll just have to declare it ourselves.
61  */
62 #if defined(__GNUC__) && __GNUC__ >= 2 || defined(__INTEL_COMPILER)
63 #undef  alloca
64 #define alloca(sz) __builtin_alloca(sz)
65 #else
66 void *alloca(size_t size);
67 #endif
68 #endif
69 
70 #define TIO_MAP 1
71 
72 #define HE_REFRESH_MAX_PARTS 64
73 
74 enum map_e { MAP_COMMAND = 1, MAP_VISUAL, MAP_INSERT, MAP_EXH };
75 
76 struct he_refresh_s {
77   int flag;
78   int first[HE_REFRESH_MAX_PARTS];
79   int last[HE_REFRESH_MAX_PARTS];
80   int parts;
81   int message_f;
82   char message[HE_REFRESH_MAX_PARTS][256];
83   int messages;
84   int beep;
85 };
86 
87 struct he_s {
88   Buffer *buffer;
89   char *buffer_name;
90   long position;
91   long screen_offset;
92   long begin_selection;
93   long end_selection;
94   int anchor_selection;
95     /* `anchor_selection == 0': the position is equal to `end_selection'
96      * `anchor_selection == 1': the position is equal to `begin_selection'
97      */
98   long insert_position;
99   int text_mode;
100   int swapping;
101     /* `swapping == 0': no swapfile, all changes are stored in memory.
102      * `swapping == 1': use the filestream `swapfile' for swapping.
103      */
104   char *swapfile;
105     /* name of the swapfile */
106   union he_undo_u {
107     FILE *swapfile;
108       /* Filestream of the swapfile.
109        */
110     struct he_command_s *list;
111       /* The first command in the undo list.
112        */
113   } undo;
114   struct he_command_s *command;
115     /* Current command in the undo-list.  Used if swapping is turned off.
116      */
117   struct he_refresh_s refresh;
118   int read_only;
119 };
120 
121 extern const struct he_refresh_s NO_REFRESH;
122 
123 struct he_message_s {
124   struct he_message_s *next;
125   char *message;
126   int beep;
127 };
128 
129 extern struct he_message_s *he_messages;
130 
131 void
132 he_message( int beep, const char *fmt, ... ) __printflike(2, 3);
133 
134 void
135 he_refresh_part(struct he_s *hedit, long pos1, long pos2);
136 
137 void
138 he_refresh_lines(struct he_s *hedit, int first, int last);
139 
140 int
141 he_refresh_check(struct he_s *hedit);
142 
143 #define he_refresh_all(hedit) ((void)he_refresh_part((hedit), 0, -1))
144 
145 void
146 he_refresh_screen(const struct he_s *hedit);
147 
148 int
149 he_update_screen(struct he_s *hedit);
150 
151 
152 struct he_command_s {
153   struct he_command_s *next_subcommand;
154     /* Multiple commands may be treated as a single command, i.e. a replace
155      * command is made up by an insert command and a delete command.  Such
156      * a compound command is stored as a list of commands.
157      */
158   struct he_command_s *next_command;
159     /* The next command in the undo list.  This pointer is set only for
160      * the first command of a compound command.  A null value in the first
161      * command of a compound command indicates the end of the list.
162      * NOTE: For all subcommands that are not the first command in a compound
163      *   command, `next_command' has to be set to zero.
164      */
165   struct he_command_s *prev_command;
166     /* The previous command in the undo list.  A null value in the first
167      * command of a compound command indicates the beginning of the list.
168      * For all subcommands that are not the first command in a compound
169      * command, the value of `prev_command' is ignored.
170      */
171   int type;
172     /* `type == 0': delete command; `type == 1': insert command.
173      */
174   int again;
175     /* `again == 1': This command can be performed again at a different
176      *   position in the file.  When the command is repeated with the
177      *   `he_again()' function, the position of every subcommand will be
178      *   changed to the new position, thus the `again' flag should be set
179      *   only if all subcommands perform on the same position in the file.
180      * `again == 0': This command can't be performed again at a different
181      *   position in the file.
182      */
183   unsigned long position;
184     /* The position of the byte of the inserted or deleted data.
185      */
186   unsigned long count;
187     /* The length of the buffer containing the inserted/deleted data.
188      */
189   char *data;
190     /* A pointer to the inserted/deleted data.
191      */
192 };
193 
194 /* The format of the swap file is defined as:
195  *  - The string "hexer <version>\n" (without the quotes), where
196  *    <version> is the version number of `hedit'.
197  *  - The full path and name of the file being edited, followed by a newline.
198  *  - 4 zero bytes.
199  *  - A list of commands, terminated by 4 zero bytes.
200  * Each command is stored as:
201  *  - The number of subcommands stored as big-endian long (4 bytes).
202  *  - One byte indicating if the command may be performed again at a
203  *    different position.
204  *    0: `again' flag cleared.
205  *    1: `again' flag set.
206  *  - A list of subcommands.
207  *  - The position of the first byte of the current entry.  This allows
208  *    reading backwards through the file.
209  * Each subcommand is stored as:
210  *  - One byte indicating the type of the command:
211  *    0: delete command.
212  *    1: insert command.
213  *  - The position in the file (big-endian long).
214  *  - The number of bytes inserted/deleted (big-endian long).
215  *  - The inserted/deleted data.
216  */
217 
218   void
219 he_free_command(struct he_command_s *command);
220   /* Free the memory allocated by command and all the following commands
221    * in the list.
222    */
223 
224   void
225 he_compound_command(struct he_s *hedit, struct he_command_s *command);
226 
227   void
228 he_subcommand(struct he_s *hedit,
229                   int type, unsigned long position, unsigned long count, char *data);
230   /* Update the undo-list of `hedit' by inserting the given subcommand.
231    * The command is *not* performed by calling `he_subcommand()'.
232    * A sequence of subcommands must be terminated by calling
233    * `he_subcommand(hedit, -1, 0, 0, 0)'.
234    * NOTE:  Iff the position for all subcommands is the same, the `again'
235    *   flag will be set to 1.
236    */
237 
238   long
239 he_do_command(struct he_s *hedit, struct he_command_s *command);
240   /* Perform the compound command `command'.  The return value is the
241    * position of the last change made.
242    */
243 
244 
245 /* buffers
246  */
247 
248 struct buffer_s {
249   struct buffer_s *next;
250   struct he_s *hedit;
251   char *path;
252   char *fullpath;
253   int loaded_f;
254   int visited_f;
255 };
256 
257 extern const struct buffer_s     NO_BUFFER;
258 extern char             *alternate_buffer;
259 extern struct buffer_s  *current_buffer;
260 extern const char       *he_pagerprg;
261 
262 
263 /* exh commands
264  */
265 
266 typedef const char *(*exh_fn)(struct he_s *, const char *, long, long);
267 
268 struct exh_cmd_s {
269   const char *cmd_name;
270   char cmd_char;
271   exh_fn cmd;
272   int whole_f;
273     /* `whole_f == 1': if no range is specified, the whole file is use. */
274   int expect;
275     /* `expect == 0': no completer available
276      * `expect == 1': expects a filename
277      * `expect == 2`: expects a buffername
278      * `expect == 3': expects a filename or a buffername
279      * `expect == 4': expects an option name
280      */
281 };
282 
283 
284 #define HE_LINE(x) ((long)(x) >> 4)
285 
286 int
287 he_open_buffer(const char *name, const char *path);
288 
289 int
290 he_select_buffer(const char *name);
291 
292 int
293 he_alternate_buffer(void);
294 
295 int
296 he_set_buffer_readonly(const char *name);
297   /* Return values:
298    * -1: no buffer named `name'
299    * 0:  ok
300    */
301 
302 int
303 he_buffer_readonly(char *name);
304   /* Return values:
305    * -1: no buffer named `name'
306    * 0:  buffer is read/write
307    * 1:  buffer is read-only
308    */
309 
310 int
311 he_buffer_modified(char *name);
312   /* Return values:
313    * -1: no buffer named `name'
314    * 0:  buffer saved
315    * 1:  buffer modified
316    */
317 
318 int
319 he_close_buffer(const char *name);
320   /* Close the buffer named `name'. If `name == 0', the current buffer
321    * is closed.  The return value is 0 if all goes well, 1 if the named
322    * buffer doesn't exist and -1 if the `buffer_list' is empty.
323    */
324 
325 void
326 he_status_message(int verbose);
327   /* display name and size of the current buffer.  if `verbose' is set,
328    * the current position is also displayed.
329    */
330 
331 void
332 he_select(struct he_s *hedit, unsigned long begin, unsigned long end);
333 
334 int
335 he_select_buffer_(const struct buffer_s *);
336 
337 void
338 he_cancel_selection(struct he_s *hedit);
339 
340 long
341 he_search(struct he_s *, const char *, const char *, int, int, int, long,
342               char **, long *, long *);
343 
344 void
345 he_search_command(struct he_s *, char *, int);
346 
347 char *
348 he_query_command(const char *, const char *, int);
349 
350 int
351 he_query_yn( int dfl, const char *fmt, ... ) __printflike(2, 3);
352 
353 int
354 he_mainloop(struct he_s *hedit);
355 
356 int
357 hexer(void);
358 
359 void             hexer_init(void);
360 void             hexer_version(void);
361 
362 #endif
363 
364 /* end of hexer.h */
365 
366 
367 /* VIM configuration: (do not delete this line)
368  *
369  * vim:bk:nodg:efm=%f\:%l\:%m:hid:icon:
370  * vim:sw=2:sm:textwidth=79:ul=1024:wrap:
371  */
372