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