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