1 /*
2 * map.c -- mapping routines.
3 *
4 * Copyright (C) 1998 by Massimiliano Ghilardi
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 */
12
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <unistd.h>
16 #include <string.h>
17 #include <ctype.h>
18 #include <time.h>
19 #include <sys/types.h>
20 #include <sys/time.h>
21
22 #include "defines.h"
23 #include "main.h"
24 #include "tty.h"
25 #include "edit.h"
26 #include "tcp.h"
27 #include "list.h"
28
29 /*
30 * mapping variables
31 */
32 static char mappath[MAX_MAPLEN]; /* circular path list */
33 static int mapstart = 0; /* index to first map entry */
34 static int mapend = 0; /* index one past last map entry */
35
36 #define MAPINDEX(i) (((i) + MAX_MAPLEN) % MAX_MAPLEN)
37 #define MAPENTRY(i) mappath[MAPINDEX(i)]
38
39 /*
40 * return reverse direction
41 */
__P1(char,dir)42 static char reverse_dir __P1 (char,dir)
43 {
44 static char dirs[] = "nsewud";
45 char *p = strchr(dirs, dir);
46 return p ? dirs[(p - dirs) ^ 1] : 0;
47 }
48
49 /*
50 * retrace steps on map, optionally walk them back
51 */
__P2(int,steps,int,walk_back)52 void map_retrace __P2 (int,steps, int,walk_back)
53 {
54 char cmd[2];
55
56 cmd[1] = '\0';
57
58 if (!steps && !walk_back)
59 mapend = mapstart;
60 else {
61 if (!steps)
62 steps = -1;
63 if (walk_back && opt_echo) {
64 status(1);
65 tty_putc('[');
66 }
67
68 while (mapstart != mapend && steps--) {
69 mapend = MAPINDEX(mapend - 1);
70 if (walk_back) {
71 cmd[0] = reverse_dir(mappath[mapend]);
72 if (opt_echo)
73 tty_putc(cmd[0]);
74 tcp_write(tcp_fd, cmd);
75 }
76 }
77 if (walk_back && opt_echo)
78 tty_puts("]\n");
79 }
80 }
81
82 /*
83 * show automatic map (latest steps) in the form s2ews14n
84 */
__P0(void)85 void map_show __P0 (void)
86 {
87 char lastdir;
88 int count = 0;
89 int i;
90
91 if (mapstart == mapend) {
92 PRINTF("#map empty\n");
93 } else {
94 PRINTF("#map: ");
95
96 lastdir = mappath[mapstart];
97 for (i = mapstart; i != mapend; i = MAPINDEX(i + 1)) {
98 if (mappath[i] != lastdir) {
99 if (count > 1)
100 tty_printf("%d", count);
101 tty_putc(lastdir);
102
103 count = 1;
104 lastdir = mappath[i];
105 } else
106 count++;
107 }
108
109 if (count > 1)
110 tty_printf("%d", count);
111
112 tty_printf("%c\n", lastdir);
113 }
114 }
115
116 /*
117 * print map to string in the form seewsnnnnn
118 */
__P1(char *,buf)119 void map_sprintf __P1 (char *,buf)
120 {
121 int i;
122
123 if (mapstart != mapend)
124 for (i = mapstart; i != mapend; i = MAPINDEX(i + 1))
125 *buf++ = mappath[i];
126 *buf = '\0';
127 }
128
129 /*
130 * add direction to automap
131 */
__P1(char,dir)132 void map_add_dir __P1 (char,dir)
133 {
134 #ifdef NOMAZEMAPPING
135 if (mapend != mapstart && dir == reverse_dir(MAPENTRY(mapend - 1))) {
136 mapend = MAPINDEX(mapend - 1); /* retrace one step */
137 } else
138 #endif
139 {
140 MAPENTRY(mapend) = dir;
141 mapend = MAPINDEX(mapend + 1);
142 if(mapend == mapstart)
143 mapstart = MAPINDEX(mapstart + 1);
144 }
145 }
146
147 /*
148 * execute walk if word is valid [speed]walk sequence -
149 * return 1 if walked, 0 if not
150 */
__P3(char *,word,int,silent,int,maponly)151 int map_walk __P3 (char *,word, int,silent, int,maponly)
152 {
153 char buf[16];
154 int n = strlen(word);
155 int is_main = (tcp_fd == tcp_main_fd);
156
157 if (!is_main && !maponly && !opt_speedwalk)
158 return 0;
159 if (!n || (n > 1 && !opt_speedwalk && !maponly) ||
160 !strchr("neswud", word[n - 1]) ||
161 (int)strspn(word, "neswud0123456789") != n)
162 return 0;
163
164 if (maponly)
165 silent = 1;
166 buf[1] = '\0';
167 while (*word) {
168 if (!silent) { status(1); tty_putc('['); }
169
170 if (isdigit(*word)) {
171 n = strtol(word, &word, 10);
172 if (!silent)
173 tty_printf("%d", n);
174 } else
175 n = 1;
176 if (!silent)
177 tty_putc(*word);
178 while (n--) {
179 *buf = *word;
180 if (!maponly) {
181 if (*lookup_alias(buf))
182 parse_instruction(buf, 1, 0, 0); // we want to execute aliases n,e,s,w,u,d
183 else tcp_write(tcp_fd, buf);
184 }
185 if (is_main || maponly)
186 map_add_dir(*word);
187 }
188 if (!silent)
189 tty_puts("] ");
190 word++;
191 }
192 if (!silent)
193 tty_putc('\n');
194 return !maponly;
195 }
196
197