~ubuntu-branches/ubuntu/quantal/hexer/quantal

« back to all changes in this revision

Viewing changes to hexer.c

  • Committer: Bazaar Package Importer
  • Author(s): Peter Mathiasson
  • Date: 2003-06-19 09:48:34 UTC
  • Revision ID: james.westby@ubuntu.com-20030619094834-t127jo9kd93shx02
Tags: upstream-0.1.4c
ImportĀ upstreamĀ versionĀ 0.1.4c

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* hexer.c      8/19/1995
 
2
 */
 
3
 
 
4
/* Copyright (c) 1995,1996 Sascha Demetrio
 
5
 * All rights reserved.
 
6
 *
 
7
 * Redistribution and use in source and binary forms, with or without
 
8
 * modification, are permitted provided that the following conditions
 
9
 * are met:
 
10
 * 1. Redistributions of source code must retain the above copyright
 
11
 *    notice, this list of conditions and the following disclaimer.
 
12
 *    If you modify any part of HEXER and resitribute it, you must add
 
13
 *    a notice to the `README' file and the modified source files containing
 
14
 *    information about the  changes you made.  I do not want to take
 
15
 *    credit or be blamed for your modifications.
 
16
 * 2. Redistributions in binary form must reproduce the above copyright
 
17
 *    notice, this list of conditions and the following disclaimer in the
 
18
 *    documentation and/or other materials provided with the distribution.
 
19
 *    If you modify any part of HEXER and resitribute it in binary form,
 
20
 *    you must supply a `README' file containing information about the
 
21
 *    changes you made.
 
22
 * 3. The name of the developer may not be used to endorse or promote
 
23
 *    products derived from this software without specific prior written
 
24
 *    permission.
 
25
 *
 
26
 * HEXER WAS DEVELOPED BY SASCHA DEMETRIO.
 
27
 * THIS SOFTWARE SHOULD NOT BE CONSIDERED TO BE A COMMERCIAL PRODUCT.
 
28
 * THE DEVELOPER URGES THAT USERS WHO REQUIRE A COMMERCIAL PRODUCT
 
29
 * NOT MAKE USE OF THIS WORK.
 
30
 *
 
31
 * DISCLAIMER:
 
32
 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPER ``AS IS'' AND
 
33
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
34
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 
35
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE DEVELOPER BE LIABLE
 
36
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 
37
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 
38
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 
39
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 
40
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 
41
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 
42
 * SUCH DAMAGE.
 
43
 */
 
44
 
 
45
#include "config.h"
 
46
 
 
47
#include <stdio.h>
 
48
#include <stdlib.h>
 
49
#include <string.h>
 
50
#include <unistd.h>
 
51
#include <errno.h>
 
52
#include <assert.h>
 
53
#if USE_STDARG
 
54
#include <stdarg.h>
 
55
#else
 
56
#include <varargs.h>
 
57
#endif
 
58
 
 
59
#include <sys/types.h>
 
60
#include <sys/param.h>
 
61
 
 
62
#ifndef PATH_MAX
 
63
#define PATH_MAX 63
 
64
#endif
 
65
 
 
66
#include "hexer.h"
 
67
 
 
68
extern int errno;
 
69
 
 
70
#ifndef BSD
 
71
extern char *sys_errlist[];
 
72
#endif
 
73
extern int sys_nerr;
 
74
extern mkstemp();
 
75
 
 
76
const struct buffer_s NO_BUFFER = { 0, 0, 0, 0, 0, 0 };
 
77
 
 
78
const char *hexer_ext = ".hexer";
 
79
 
 
80
struct buffer_s *current_buffer;
 
81
struct buffer_s *buffer_list = 0;
 
82
struct he_message_s *he_messages;
 
83
char *alternate_buffer;
 
84
char *he_pagerprg;
 
85
 
 
86
#if USE_STDARG
 
87
  void
 
88
he_message(int beep, char *fmt, ...)
 
89
#else
 
90
  void
 
91
he_message(beep, fmt, va_alist)
 
92
  int beep;
 
93
  char *fmt;
 
94
  va_dcl
 
95
#endif
 
96
{
 
97
  va_list ap;
 
98
  struct he_message_s *m;
 
99
  /* int length; */
 
100
 
 
101
#if USE_STDARG
 
102
  va_start(ap, fmt);
 
103
#else
 
104
  va_start(ap);
 
105
#endif
 
106
  /* length = tio_nprintf(fmt, ap); */
 
107
  m = (struct he_message_s *)malloc(sizeof(struct he_message_s));
 
108
  m->next = he_messages;
 
109
  m->beep = beep;
 
110
  /* m->message = (char *)malloc(length + 1); */
 
111
  m->message = (char *)malloc(512); /* FIXME */
 
112
  vsprintf(m->message, fmt, ap);
 
113
  he_messages = m;
 
114
  va_end(ap);
 
115
}
 
116
/* he_message */
 
117
 
 
118
 
 
119
/* hexer options
 
120
 */
 
121
 
 
122
  static void
 
123
action_ascii(current_value)
 
124
  int current_value;
 
125
{
 
126
  he_refresh_all(current_buffer->hedit);
 
127
  if (current_value)
 
128
    s_set_option("iso", "false", 1);
 
129
  else
 
130
    s_set_option("iso", "true", 1);
 
131
}
 
132
/* action_ascii */
 
133
 
 
134
  static void
 
135
action_iso(current_value)
 
136
  int current_value;
 
137
{
 
138
  he_refresh_all(current_buffer->hedit);
 
139
  if (current_value)
 
140
    s_set_option("ascii", "false", 1);
 
141
  else
 
142
    s_set_option("ascii", "true", 1);
 
143
}
 
144
/* action_iso */
 
145
 
 
146
  static void
 
147
action_maxmatch(current_value)
 
148
  long current_value;
 
149
{
 
150
  extern long rx_maxmatch;
 
151
 
 
152
  rx_maxmatch = current_value;
 
153
}
 
154
/* action_maxmatch */
 
155
 
 
156
  static void
 
157
action_TERM()
 
158
{
 
159
  tio_init(0);
 
160
  he_refresh_all(current_buffer->hedit);
 
161
}
 
162
/* action_TERM */
 
163
 
 
164
  static void
 
165
action_specialnl(current_value)
 
166
  int current_value;
 
167
{
 
168
  extern rx_special_nl;
 
169
 
 
170
  rx_special_nl = current_value;
 
171
}
 
172
/* action_specialnl */
 
173
 
 
174
  static void
 
175
action_mapmagic(current_value)
 
176
  int current_value;
 
177
{
 
178
  extern he_map_special;
 
179
 
 
180
  he_map_special = current_value;
 
181
}
 
182
/* action_mapmagic */
 
183
 
 
184
static const struct hexer_options_s {
 
185
  char *option;
 
186
  enum s_option_e type;
 
187
  char *default_value;
 
188
  set_fn action;
 
189
} hexer_options[] = {
 
190
  { "ascii", S_BOOL, "true", (set_fn)action_ascii },
 
191
  { "iso", S_BOOL, "false", (set_fn)action_iso },
 
192
  { "maxmatch", S_INTEGER, "1024", (set_fn)action_maxmatch },
 
193
  { "TERM", S_STRING, "", (set_fn)action_TERM }, /* set in `hexer_init()' */
 
194
  { "specialnl", S_BOOL, "false", (set_fn)action_specialnl },
 
195
  { "mapmagic", S_BOOL, "false", (set_fn)action_mapmagic },
 
196
  { "fg", S_INTEGER, "7", (set_fn)0 },
 
197
  { "bg", S_INTEGER, "4", (set_fn)0 },
 
198
  { 0, (enum s_option_e)0, 0, 0 }
 
199
};
 
200
 
 
201
 
 
202
/* hexer buffers
 
203
 */
 
204
 
 
205
  int
 
206
he_open_buffer(name, path)
 
207
  char *name;
 
208
  char *path;
 
209
{
 
210
  struct buffer_s *buffer;
 
211
  int no_file_f = 0, read_only = 0;
 
212
  struct buffer_s *i;
 
213
  FILE *fp;
 
214
  char cwd[PATH_MAX + 1];
 
215
 
 
216
  if (path) {
 
217
    /* check out the read/write permissions */
 
218
    if (access(path, R_OK))
 
219
      switch (errno) {
 
220
      case ENOENT: /* file doesn't exist */
 
221
        no_file_f = 1;
 
222
        break;
 
223
      default:
 
224
        if (errno >= sys_nerr) /* unknown error */
 
225
          he_message(1, "`%s': @Abunknown error@~", path);
 
226
        else
 
227
          he_message(1, "`%s': @Ab%s@~", path, sys_errlist[errno]);
 
228
        return -1;
 
229
      }
 
230
    if (!no_file_f ? access(path, W_OK) : 0)
 
231
      switch (errno) {
 
232
      case EACCES: /* write permission denied */
 
233
        read_only = 1;
 
234
        break;
 
235
      default:
 
236
        if (errno >= sys_nerr) /* unknown error */
 
237
          he_message(1, "`%s': @Abunknown error@~", path);
 
238
        else
 
239
          he_message(1, "`%s': @Ab%s@~", path, sys_errlist[errno]);
 
240
        return -1;
 
241
      }
 
242
  }
 
243
  *(buffer = (struct buffer_s *)malloc(sizeof(struct buffer_s))) = NO_BUFFER;
 
244
  buffer->hedit = (struct he_s *)malloc(sizeof(struct he_s));
 
245
  memset(buffer->hedit, 0, sizeof (struct he_s));
 
246
  buffer->hedit->begin_selection = -1;
 
247
  buffer->hedit->end_selection = -1;
 
248
  buffer->hedit->insert_position = -1;
 
249
  buffer->hedit->buffer_name = strdup(name);
 
250
  if (path && !no_file_f) {
 
251
    if (!(fp = fopen(path, "r"))) {
 
252
      if (errno >= sys_nerr) /* unknown error */
 
253
        he_message(1, "`%s': @Abunknown error@~", path);
 
254
      else
 
255
        he_message(1, "`%s': @Ab%s@~", path, sys_errlist[errno]);
 
256
      free((char *)buffer->hedit->buffer_name);
 
257
      free((char *)buffer->hedit);
 
258
      free((char *)buffer);
 
259
      return -1;
 
260
    } else
 
261
      fclose(fp);
 
262
  } else {
 
263
    buffer->hedit->buffer = new_buffer(0);
 
264
    buffer->loaded_f = 1;
 
265
    buffer->visited_f = 1;
 
266
  }
 
267
  if (path) {
 
268
    buffer->path = strdup(path);
 
269
    if (!getcwd(cwd, PATH_MAX)) {
 
270
      if (errno >= sys_nerr)
 
271
        he_message(0, "@Abcan't get cwd: unknown error");
 
272
      else
 
273
        he_message(0, "@Abcan't get cwd: %s@~", sys_errlist[errno]);
 
274
      buffer->fullpath = strdup(path);
 
275
    } else {
 
276
      buffer->fullpath =
 
277
        (char *)malloc(strlen(path) + strlen(cwd) + 2);
 
278
      sprintf(buffer->fullpath, "%s/%s", cwd, path);
 
279
    }
 
280
  }
 
281
  buffer->hedit->read_only = read_only;
 
282
  if (!buffer_list)
 
283
    current_buffer = buffer_list = buffer;
 
284
  else {
 
285
    for (i = buffer_list; i->next; i = i->next);
 
286
    i->next = buffer;
 
287
  }
 
288
  return 0;
 
289
}
 
290
/* he_open_buffer */
 
291
 
 
292
  int
 
293
he_select_buffer_(buffer)
 
294
  struct buffer_s *buffer;
 
295
  /* Set `current_buffer' to `buffer'.  The file for `buffer' is loaded if
 
296
   * nessecarry.
 
297
   */
 
298
{
 
299
  struct buffer_s *i;
 
300
  char swap_template[8];
 
301
  
 
302
  strcpy(swap_template, ".XXXXXX");
 
303
  for (i = buffer_list; i != buffer && i; i = i->next);
 
304
  if (!i) return -1;
 
305
  current_buffer = i;
 
306
  if (!i->loaded_f) {
 
307
    i->hedit->buffer = new_buffer(0);
 
308
    /* read the file */
 
309
    if (b_read_buffer_from_file(i->hedit->buffer, i->path) < 0) {
 
310
      delete_buffer(i->hedit->buffer);
 
311
      i->hedit->buffer = 0;
 
312
      he_close_buffer(0);
 
313
      return -1;
 
314
    }
 
315
    /* check out if we can open a swapfile */
 
316
    i->hedit->swapfile =
 
317
      (char *)malloc(strlen(hexer_ext) + strlen(i->path) + 1);
 
318
    strcpy(i->hedit->swapfile, i->path);
 
319
    strcat(i->hedit->swapfile, hexer_ext);
 
320
    if (access(i->hedit->swapfile, R_OK)) {
 
321
      if (errno == ENOENT) /* swapfile doesn't exist -- fine */
 
322
        if (access(i->hedit->swapfile, W_OK))
 
323
          if (errno == ENOENT) {
 
324
            if ((i->hedit->undo.swapfile = fopen(i->hedit->swapfile, "w+")))
 
325
              i->hedit->swapping = 1;
 
326
          } else
 
327
            he_message(0, "@Abno swapfile@~");
 
328
    } else {
 
329
      /* a swapfile does exist */
 
330
      int swapfd;
 
331
      he_message(1, "@Abwarning: swapfile@~ `%s' @Abexists@~",
 
332
                 i->hedit->swapfile);
 
333
      i->hedit->swapfile =
 
334
        (char *)realloc(i->hedit->swapfile,
 
335
                      strlen(i->hedit->swapfile) + strlen(swap_template) + 1);
 
336
        strcat(i->hedit->swapfile, swap_template);
 
337
      if ((swapfd = mkstemp(i->hedit->swapfile)) < 0)
 
338
        he_message(0, "@Abno swapfile@~");
 
339
      else {
 
340
        i->hedit->undo.swapfile = fdopen(swapfd, "r+");
 
341
        i->hedit->swapping = 1;
 
342
        he_message(0, "@Abswapping to@~ `%s'", i->hedit->swapfile);
 
343
      }
 
344
    }
 
345
    if (i->hedit->swapping) {
 
346
      /* write the swap-header to the swapfile */
 
347
      fputs("hexer ", i->hedit->undo.swapfile);
 
348
      fputs(HEXER_VERSION, i->hedit->undo.swapfile);
 
349
      fputc('\n', i->hedit->undo.swapfile);
 
350
      fputs(i->fullpath, i->hedit->undo.swapfile);
 
351
      fputc('\n', i->hedit->undo.swapfile);
 
352
      fwrite("\0\0\0\0", 4, 1, i->hedit->undo.swapfile);
 
353
      fflush(i->hedit->undo.swapfile);
 
354
    }
 
355
    i->hedit->buffer->modified = 0;
 
356
    i->loaded_f = 1;
 
357
    i->visited_f = 1;
 
358
  }
 
359
  return 0;
 
360
}
 
361
/* he_select_buffer_ */
 
362
 
 
363
  int
 
364
he_select_buffer(name)
 
365
  char *name;
 
366
{
 
367
  struct buffer_s *i;
 
368
 
 
369
  for (i = buffer_list; i; i = i->next)
 
370
    if (!strcmp(name, i->hedit->buffer_name)) break;
 
371
  if (!i) return -1;
 
372
  return he_select_buffer_(i);
 
373
}
 
374
/* he_select_buffer */
 
375
 
 
376
  int
 
377
he_alternate_buffer()
 
378
{
 
379
  char *ab = alternate_buffer;
 
380
 
 
381
  alternate_buffer = current_buffer->hedit->buffer_name;
 
382
  if (ab ? he_select_buffer(ab) < 0 : 0) {
 
383
    alternate_buffer = 0;
 
384
    return -1;
 
385
  }
 
386
  return 0;
 
387
}
 
388
/* he_alternate_buffer */
 
389
 
 
390
  int
 
391
he_set_buffer_readonly(name)
 
392
  char *name;
 
393
  /* Return values:
 
394
   * -1: no buffer named `name'
 
395
   * 0:  ok
 
396
   */
 
397
{
 
398
  struct buffer_s *i;
 
399
 
 
400
  for (i = buffer_list; i; i = i->next)
 
401
    if (!strcmp(name, i->hedit->buffer_name)) break;
 
402
  if (!i) return -1;
 
403
  i->hedit->read_only = 1;
 
404
  return 0;
 
405
}
 
406
/* he_set_buffer_readonly */
 
407
 
 
408
  int
 
409
he_buffer_readonly(name)
 
410
  char *name;
 
411
  /* Return values:
 
412
   * -1: no buffer named `name'
 
413
   * 0:  buffer is readwrite
 
414
   * 1:  buffer is readonly
 
415
   */
 
416
{
 
417
  struct buffer_s *i;
 
418
 
 
419
  for (i = buffer_list; i; i = i->next)
 
420
    if (!strcmp(name, i->hedit->buffer_name)) break;
 
421
  if (!i) return -1;
 
422
  return !!i->hedit->read_only;
 
423
}
 
424
/* he_buffer_readonly */
 
425
 
 
426
  int
 
427
he_buffer_modified(name)
 
428
  char *name;
 
429
  /* Return values:
 
430
   * -1: no buffer named `name'
 
431
   * 0:  buffer saved
 
432
   * 1:  buffer modified
 
433
   */
 
434
{
 
435
  struct buffer_s *i;
 
436
 
 
437
  for (i = buffer_list; i; i = i->next)
 
438
    if (!strcmp(name, i->hedit->buffer_name)) break;
 
439
  if (!i) return -1;
 
440
  return !!i->hedit->buffer->modified;
 
441
}
 
442
/* he_buffer_modified */
 
443
 
 
444
  int
 
445
he_close_buffer(name)
 
446
  char *name;
 
447
  /* Close the buffer named `name'. If `name == 0', the current buffer
 
448
   * is closed.  The return value is 0 if all goes well, 1 if the named
 
449
   * buffer doesn't exist and -1 if the `buffer_list' is empty.
 
450
   */
 
451
{
 
452
  struct buffer_s *i, *j;
 
453
  int empty = 0;
 
454
  int buffer_switched = 0;
 
455
 
 
456
  if (!buffer_list) return -1;
 
457
  if (!name)
 
458
    i = current_buffer;
 
459
  else {
 
460
    for (i = buffer_list; i; i = i->next)
 
461
      if (!strcmp(i->hedit->buffer_name, name)) break;
 
462
    if (!i) return -1;
 
463
  }
 
464
  if (i != buffer_list) {
 
465
    for (j = buffer_list; j->next != i; j = j->next);
 
466
    if (alternate_buffer
 
467
        ? !strcmp(alternate_buffer, i->hedit->buffer_name) : 0)
 
468
      alternate_buffer = 0;
 
469
    j->next = i->next;
 
470
    if (i == current_buffer) {
 
471
      if (i->next)
 
472
        he_select_buffer_(i->next);
 
473
      else
 
474
        he_select_buffer_(j);
 
475
      buffer_switched = 1;
 
476
    }
 
477
  } else
 
478
    if (!(buffer_list = current_buffer = i->next))
 
479
      empty = 1;
 
480
    else {
 
481
      he_select_buffer_(buffer_list);
 
482
      buffer_switched = 1;
 
483
    }
 
484
  if (i->hedit->buffer_name) free((char *)i->hedit->buffer_name);
 
485
  if (i->hedit->buffer) delete_buffer(i->hedit->buffer);
 
486
  if (i->hedit->swapping) {
 
487
    fclose(i->hedit->undo.swapfile);
 
488
    unlink(i->hedit->swapfile);
 
489
  } else
 
490
    if (i->hedit->undo.list) he_free_command(i->hedit->undo.list);
 
491
  free((char *)i->hedit);
 
492
  if (i->path) free((char *)i->path);
 
493
  free((char *)i);
 
494
  if (empty) buffer_list = 0, current_buffer = 0;
 
495
  if (buffer_switched) {
 
496
    alternate_buffer = 0;
 
497
    he_refresh_all(current_buffer->hedit);
 
498
  }
 
499
  return empty ? -1 : 0;
 
500
}
 
501
/* he_close_buffer */
 
502
 
 
503
 
 
504
/* misc
 
505
 */
 
506
 
 
507
  void
 
508
he_status_message(verbose)
 
509
  int verbose;
 
510
  /* display name and size of the current buffer.  if `verbose' is set,
 
511
   * the current position is also displayed.
 
512
   */
 
513
{
 
514
  struct he_s *hedit = current_buffer->hedit;
 
515
 
 
516
  if (hedit->buffer->size)
 
517
    if (verbose)
 
518
      he_message(0, "\"%s\" %s%sat 0x%lx (%li) of 0x%lx (%li) bytes  (%li %%)",
 
519
                 hedit->buffer_name,
 
520
                 hedit->buffer->modified ? "[modified] " : "",
 
521
                 hedit->read_only ? "[readonly] " : "",
 
522
                 hedit->position, hedit->position,
 
523
                 hedit->buffer->size, hedit->buffer->size,
 
524
                 (hedit->position * 100) / hedit->buffer->size);
 
525
    else
 
526
    if (hedit->buffer->size)
 
527
      he_message(0, "\"%s\" %s%s0x%lx (%li) bytes",
 
528
                 hedit->buffer_name,
 
529
                 hedit->buffer->modified ? "[modified] " : "",
 
530
                 hedit->read_only ? "[readonly] " : "",
 
531
                 hedit->buffer->size, hedit->buffer->size);
 
532
  else
 
533
    he_message(0, "\"%s\" %s%s(empty)", hedit->buffer_name,
 
534
               hedit->buffer->modified ? "[modified] " : "",
 
535
               hedit->read_only ? "[readonly] " : "");
 
536
}
 
537
/* he_status_message */
 
538
 
 
539
  char *
 
540
he_query_command(prompt, dfl, context)
 
541
  char *prompt;
 
542
  char *dfl;
 
543
  int context;
 
544
  /* Convention:
 
545
   * `context == 0': exh-command;
 
546
   * `context == 1': shell-command;
 
547
   * `context == 2': search-command.
 
548
   * `context == 3': calculator.
 
549
   */
 
550
{
 
551
  extern int lines;
 
552
 
 
553
  tio_goto_line(lines - 1);
 
554
  tio_return();
 
555
  return readline(prompt, dfl, context);
 
556
}
 
557
/* he_query_command */
 
558
 
 
559
#if USE_STDARG
 
560
  int
 
561
he_query_yn(int dfl, char *fmt, ...)
 
562
#else
 
563
  int
 
564
he_query_yn(dfl, fmt, va_alist)
 
565
  int dfl;
 
566
  char *fmt;
 
567
  va_dcl
 
568
#endif
 
569
{
 
570
  va_list ap;
 
571
  extern int lines;
 
572
  int key;
 
573
  int choice;
 
574
  extern window_changed;
 
575
 
 
576
#if USE_STDARG
 
577
  va_start(ap, fmt);
 
578
#else
 
579
  va_start(ap);
 
580
#endif
 
581
  tio_keypad(0);
 
582
restart:
 
583
  tio_goto_line(lines - 1);
 
584
  tio_return();
 
585
  tio_clear_to_eol();
 
586
  if (dfl < 0) { /* no default answer */
 
587
    tio_vprintf(fmt, ap);
 
588
    tio_printf("? ");
 
589
  } else {
 
590
    dfl = !!dfl;
 
591
    tio_vprintf(fmt, ap);
 
592
    tio_printf("? [%c] ", dfl ? 'y' : 'n');
 
593
  }
 
594
  for (;;) {
 
595
    key = tio_getch();
 
596
    switch (key) {
 
597
    case KEY_NONE:
 
598
      if (window_changed) he_refresh_screen(current_buffer->hedit);
 
599
      goto restart;
 
600
    case 'q': case 'Q':
 
601
      tio_printf("quit");
 
602
      choice = -1;
 
603
      goto exit_he_query_yn;
 
604
    case KEY_ESCAPE:
 
605
      tio_printf("escape");
 
606
      choice = -1;
 
607
      goto exit_he_query_yn;
 
608
    case KEY_RETURN:
 
609
      if (dfl < 0) break;
 
610
      choice = dfl;
 
611
      switch (choice) {
 
612
      case -1: tio_printf("quit"); break;
 
613
      case 0: tio_printf("no"); break;
 
614
      case 1: tio_printf("yes"); break;
 
615
      case 2: tio_printf("always"); break;
 
616
      }
 
617
      goto exit_he_query_yn;
 
618
    case 'y': case 'Y':
 
619
      tio_printf("yes");
 
620
      choice = 1;
 
621
      goto exit_he_query_yn;
 
622
    case 'n': case 'N':
 
623
      tio_printf("no");
 
624
      choice = 0;
 
625
      goto exit_he_query_yn;
 
626
    case 'a': case 'A':
 
627
      tio_printf("always");
 
628
      choice = 2;
 
629
      goto exit_he_query_yn;
 
630
    default:
 
631
      break;
 
632
    }
 
633
  }
 
634
 
 
635
exit_he_query_yn:
 
636
  tio_return();
 
637
  tio_keypad(1);
 
638
  tio_flush();
 
639
  va_end(ap);
 
640
  return choice;
 
641
}
 
642
/* he_query_yn */
 
643
 
 
644
 
 
645
/* I/O wrap-functions for `regex_match()':
 
646
 */
 
647
 
 
648
static Buffer *rxwrap_current_buffer;
 
649
static long rxwrap_position;
 
650
 
 
651
  static long
 
652
rxwrap_read(buf, count)
 
653
  char *buf;
 
654
  long count;
 
655
{
 
656
  long rval = b_read(rxwrap_current_buffer, buf, rxwrap_position, count);
 
657
  rxwrap_position += rval;
 
658
  return rval;
 
659
}
 
660
/* rxwrap_read */
 
661
 
 
662
  static long
 
663
rxwrap_seek(position)
 
664
  long position;
 
665
{
 
666
  return rxwrap_position = position;
 
667
}
 
668
/* rxwrap_seek */
 
669
 
 
670
  static long
 
671
rxwrap_tell()
 
672
{
 
673
  return rxwrap_position;
 
674
}
 
675
/* rxwrap_tell */
 
676
 
 
677
  long
 
678
he_search(hedit, exp, replace, direction, wrap, increment, end,
 
679
          replace_str, replace_len, match_len)
 
680
  struct he_s *hedit;
 
681
  char *exp;
 
682
    /* regular expression.
 
683
     */
 
684
  char *replace;
 
685
    /* replace template.  the replace template may contain back references to
 
686
     * the regular expression (`\0', ... `\9').
 
687
     */
 
688
  int direction;
 
689
    /* `direction >= 0': forward search.
 
690
     * `direction < 0': reverse search.
 
691
     */
 
692
  int wrap;
 
693
    /* if `wrap' is set, the search continues at the top of the buffer/file
 
694
     * if the bottom has been (or vice versa, depending on `direction').
 
695
     */
 
696
  int increment;
 
697
    /* if `increment' is set, the search starts at `hedit->position + 1'
 
698
     * rather than at `hedit->position'.  if the direction is set to reverse
 
699
     * search, the `increment'-flag has no effect.
 
700
     */
 
701
  long end;
 
702
    /* if `wrap' is not set and `end' is not negative, the search ends at
 
703
     * position `end'.
 
704
     */
 
705
  char **replace_str;
 
706
    /* if `replace_str' is non-zero and a match was found, the replace
 
707
     * string generated from `replace' will be copied to `*replace_str'.
 
708
     * the memory for that replace string will be allocated via `malloc()'.
 
709
     * NOTE: the replace string wont be terminated with a null-character
 
710
     *   since it may contain null characters.
 
711
     */
 
712
  long *replace_len;
 
713
    /* the length of the replace sting is written to `*replace_len'.
 
714
     */
 
715
  long *match_len;
 
716
    /* the length of the match is written to `*replace_len'.
 
717
     */
 
718
  /* RETURN VALUE:  if a match was found, the position of the match is
 
719
   *   returned;  -1: search failed;  -2: illegal expression (check out
 
720
   *   `rx_error'/`rx_error_msg').
 
721
   * NOTE:  if the returned value is positive, `*replace_str' has to be 
 
722
   *   `free()'d by the caller.
 
723
   */
 
724
{
 
725
  static long *regex;
 
726
  long position;
 
727
 
 
728
  /* setup the regex I/O */
 
729
  regex_init(rxwrap_read, rxwrap_seek, rxwrap_tell);
 
730
  rxwrap_current_buffer = hedit->buffer;
 
731
  regex_reset();
 
732
 
 
733
  if (wrap || end < 0) end = hedit->buffer->size;
 
734
 
 
735
  if (exp) if (!(regex = regex_compile(exp, replace))) return -2;
 
736
  if (direction < 0) direction = -1; else direction = 1;
 
737
  if (direction > 0) {
 
738
    position = regex_search(regex, 0, end, hedit->position + !!increment,
 
739
                            1, replace_str, replace_len, match_len);
 
740
    if (wrap && position < 0) {
 
741
      position = regex_search(regex, 0, end, 0, 1,
 
742
                              replace_str, replace_len, match_len);
 
743
      if (position >= 0) he_message(0, "@Abwrapped@~");
 
744
    }
 
745
  } else {
 
746
    position = regex_search(regex, 0, end, hedit->position - !!hedit->position,
 
747
                            -1, replace_str, replace_len, match_len);
 
748
    if (wrap && position < 0) {
 
749
      position = regex_search(regex, 0, end, hedit->buffer->size - 1,
 
750
                              -1, replace_str, replace_len, match_len);
 
751
      if (position >= 0) he_message(0, "@Abwrapped@~");
 
752
    }
 
753
  }
 
754
  return position;
 
755
}
 
756
/* he_search */
 
757
 
 
758
  void
 
759
he_search_command(hedit, exp, dir)
 
760
  struct he_s *hedit;
 
761
  char *exp;
 
762
  int dir;
 
763
{
 
764
  long position;
 
765
  char *rs;
 
766
  long rl, ml;
 
767
  static char last_exp[4096] = "";
 
768
 
 
769
  if (!*exp)
 
770
    if (!*last_exp) {
 
771
      he_message(0, "@Abno previous expression@~");
 
772
      goto exit;
 
773
    } else
 
774
      exp = last_exp;
 
775
  switch ((position = he_search(hedit, exp, "", dir, 1, 1, -1,
 
776
                                &rs, &rl, &ml))) {
 
777
  case -2:  /* invalid expression */
 
778
    he_message(0, "@Abinvalid expression:@~ %s", rx_error_msg[rx_error]);
 
779
    goto exit;
 
780
  case -1:  /* no match */
 
781
    if (!rx_error)
 
782
      he_message(0, "no match");
 
783
    else
 
784
      he_message(0, "@Abregexp error:@~ %s", rx_error_msg[rx_error]);
 
785
    break;
 
786
  default:  /* match */
 
787
    hedit->position = position;
 
788
    free((char *)rs);
 
789
    break;
 
790
  }
 
791
  if (exp != last_exp) strcpy(last_exp, exp);
 
792
 
 
793
exit:
 
794
  return;
 
795
}
 
796
/* he_search_command */
 
797
 
 
798
  extern int
 
799
exh_command( /* struct he_s *hedit, char *cmd */ );
 
800
 
 
801
  static void
 
802
he_refresh()
 
803
{
 
804
  he_refresh_all(current_buffer->hedit);
 
805
  he_update_screen(current_buffer->hedit);
 
806
}
 
807
/* he_refresh */
 
808
 
 
809
  void
 
810
hexer_version()
 
811
{
 
812
  he_message(0, "@AbHexer@~ version @U%s@u", HEXER_VERSION);
 
813
}
 
814
/* hexer_version */
 
815
 
 
816
  void
 
817
hexer_init()
 
818
  /* this function is called by `process_args()' (main.c) before executing
 
819
   * the commands given at the command line.
 
820
   */
 
821
{
 
822
  int i;
 
823
  extern he_map_special;
 
824
  extern char *terminal_name;
 
825
  char *hexerinit, *home;
 
826
  char path[1024];
 
827
  char line[1024];
 
828
  extern char *exh_initialize[];
 
829
  FILE *fp;
 
830
 
 
831
  he_pagerprg = getenv("PAGER");
 
832
  if (!he_pagerprg) he_pagerprg = HE_DEFAULT_PAGER;
 
833
  for (i = 0; hexer_options[i].option; ++i) {
 
834
    s_set_type(hexer_options[i].option, hexer_options[i].type);
 
835
    s_set_option(hexer_options[i].option, hexer_options[i].default_value, 1);
 
836
    s_set_action(hexer_options[i].option, hexer_options[i].action);
 
837
  }
 
838
  s_set_option("TERM", terminal_name, 1);
 
839
 
 
840
  he_map_special = 1;
 
841
  for (i = 0; exh_initialize[i]; ++i)
 
842
    exh_command(current_buffer->hedit, exh_initialize[i]);
 
843
 
 
844
  if (!(home = getenv("HOME"))) home = ".";
 
845
  if (!(hexerinit = getenv("HEXERRC"))) hexerinit = HEXERINIT_FILE;
 
846
  strcpy(path, home);
 
847
  strcat(path, "/");
 
848
  strcat(path, hexerinit);
 
849
  if ((fp = fopen(path, "r"))) {
 
850
    while (!feof(fp)) {
 
851
      fgets(line, 1024, fp);
 
852
      if (!*line) break;
 
853
      line[strlen(line) - 1] = 0; /* discard the trailing newline */
 
854
      if (*line && *line != '"')
 
855
        exh_command(current_buffer->hedit, line, 0);
 
856
      /* the command might have quit the editor, so we gotta check */
 
857
      if (!current_buffer) {
 
858
        fprintf(stderr,
 
859
                "warning: a command in your `%s' causes the editor to quit.\n",
 
860
                hexerinit);
 
861
        break;
 
862
      }
 
863
    }
 
864
  }
 
865
}
 
866
/* hexer_init */
 
867
 
 
868
  int
 
869
hexer()
 
870
{
 
871
  int key;
 
872
  char *cmd;
 
873
  char dfl[256], buf[256];
 
874
  long begin, end;
 
875
  int anchor, anchor_f = 0;
 
876
  extern int rl_redisplay;
 
877
  extern void (*rl_winch)( /* void */ );
 
878
  extern void (*tio_winch)( /* void */ );
 
879
  int redisplay;
 
880
 
 
881
  tio_winch = rl_winch = he_refresh;
 
882
  he_refresh_part(current_buffer->hedit, 0, -1);
 
883
  for (; buffer_list;) {
 
884
    key = he_mainloop(current_buffer->hedit);
 
885
    redisplay = 0;
 
886
    switch (key) {
 
887
    case '!':  /* shell-command. */
 
888
      he_cancel_selection(current_buffer->hedit);
 
889
      he_update_screen(current_buffer->hedit);
 
890
      cmd = he_query_command("!", "", 1);
 
891
      redisplay = rl_redisplay;
 
892
      if (cmd) {
 
893
        strcpy(buf + 1, cmd);
 
894
        *buf = '!';
 
895
        exh_command(current_buffer->hedit, buf);
 
896
      }
 
897
      break;
 
898
    case ':':  /* exh command. */
 
899
      begin = current_buffer->hedit->begin_selection;
 
900
      end = current_buffer->hedit->end_selection;
 
901
      anchor = current_buffer->hedit->anchor_selection;
 
902
      if (begin >= 0 && end >= begin) {
 
903
        anchor_f = 1;
 
904
        sprintf(dfl, "0x%lx,0x%lx ", begin, end);
 
905
      } else {
 
906
        *dfl = 0;
 
907
        anchor_f = 0;
 
908
      }
 
909
      he_cancel_selection(current_buffer->hedit);
 
910
      cmd = he_query_command(":", dfl, 0);
 
911
      redisplay = rl_redisplay;
 
912
      if (cmd ? *cmd : 0)
 
913
        exh_command(current_buffer->hedit, cmd);
 
914
      if (current_buffer && anchor_f)
 
915
        if (current_buffer->hedit->begin_selection >= 0)
 
916
          current_buffer->hedit->anchor_selection = anchor;
 
917
      break;
 
918
    case '^' & 0x1f: /* C-^ - switch to alternate buffer */
 
919
      he_cancel_selection(current_buffer->hedit);
 
920
      if (he_alternate_buffer() < 0) 
 
921
        he_message(0, "no alternate buffer");
 
922
      else {
 
923
        he_refresh_part(current_buffer->hedit, 0, -1);
 
924
        tio_ungetch('g' & 0x1f);  /* FIXME */
 
925
      }
 
926
      break;
 
927
    default:
 
928
      he_cancel_selection(current_buffer->hedit);
 
929
      he_update_screen(current_buffer->hedit);
 
930
    }
 
931
    if (current_buffer) {
 
932
      if (redisplay) he_refresh_all(current_buffer->hedit);
 
933
      he_update_screen(current_buffer->hedit);
 
934
    }
 
935
  }
 
936
  return 0;
 
937
}
 
938
/* hexer */
 
939
 
 
940
/* end of hexer.c */
 
941
 
 
942
 
 
943
/* VIM configuration: (do not delete this line)
 
944
 *
 
945
 * vim:aw:bk:bdir=./bak:ch=2:nodg:ef=make.log:efm=%f\:%l\:%m:et:hid:icon:
 
946
 * vim:sw=2:sc:sm:si:textwidth=79:to:ul=1024:wh=12:wrap:wb:
 
947
 */