Mercurial > emacs
annotate src/cm.c @ 15145:86a1f426871e
Include config.h after CRT headers. Include fcntl.h.
(child_process, MAX_CHILDREN, CHILD_ACTIVE): Moved to nt.h.
(DebugPrint): New macro.
(new_child): Create input event structures for child processes.
(delete_child): New function.
(reader_thread): Return nonzero upon failure. Use _sys_read_ahead.
(create_child): Add child_process and parent PID arguments.
Don't create input event or thread structures here.
Fixup Win95 negative process IDs.
(register_child): Don't set consumed event; instead, set thread
status so that select will release it.
(remove_child): Renamed to reap_process. Only free resources
of synchronous children.
(win32_wait): Renamed to sys_wait. Sanity check to make sure
handle to subprocess exists. Don't reclaim thread resources here.
(win32_spawnve): Renamed to sys_spawnve.
Check for proper wait mode first thing.
Convert command name to DOS format.
Quote whitespace and quotes in arguments to subprocess.
Use alloca instead of malloc.
If max subprocesses, return EAGAIN in hopes of another completing.
(sys_select): Add support for socket input. Remove dead code.
Check input from children fairly.
(sys_select) [HAVE_TIMEVAL]: Remove conditional check and code.
(win32_kill_process): Renamed to sys_kill. Use OpenProcess
to terminate process.
(prepate_standard_handles, reset_standard_handles): Moved here
from nt.c.
author | Geoff Voelker <voelker@cs.washington.edu> |
---|---|
date | Fri, 03 May 1996 18:35:50 +0000 |
parents | ee40177f6c68 |
children | fa9ff387d260 |
rev | line source |
---|---|
484 | 1 /* Cursor motion subroutines for GNU Emacs. |
11235 | 2 Copyright (C) 1985, 1995 Free Software Foundation, Inc. |
484 | 3 based primarily on public domain code written by Chris Torek |
4 | |
5 This file is part of GNU Emacs. | |
6 | |
7 GNU Emacs is free software; you can redistribute it and/or modify | |
8 it under the terms of the GNU General Public License as published by | |
7107 | 9 the Free Software Foundation; either version 2, or (at your option) |
484 | 10 any later version. |
11 | |
12 GNU Emacs is distributed in the hope that it will be useful, | |
13 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 GNU General Public License for more details. | |
16 | |
17 You should have received a copy of the GNU General Public License | |
18 along with GNU Emacs; see the file COPYING. If not, write to | |
14186
ee40177f6c68
Update FSF's address in the preamble.
Erik Naggum <erik@naggum.no>
parents:
11235
diff
changeset
|
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
ee40177f6c68
Update FSF's address in the preamble.
Erik Naggum <erik@naggum.no>
parents:
11235
diff
changeset
|
20 Boston, MA 02111-1307, USA. */ |
484 | 21 |
22 | |
4696
1fc792473491
Include <config.h> instead of "config.h".
Roland McGrath <roland@gnu.org>
parents:
484
diff
changeset
|
23 #include <config.h> |
484 | 24 #include <stdio.h> |
25 #include "cm.h" | |
26 #include "termhooks.h" | |
27 | |
28 #define BIG 9999 /* 9999 good on VAXen. For 16 bit machines | |
29 use about 2000.... */ | |
30 | |
31 char *tgoto (); | |
32 | |
33 extern char *BC, *UP; | |
34 | |
35 int cost; /* sums up costs */ | |
36 | |
37 /* ARGSUSED */ | |
38 evalcost (c) | |
39 char c; | |
40 { | |
41 cost++; | |
8985
2825665b8352
(evalcost, cmputc): They now return their arguments.
Richard M. Stallman <rms@gnu.org>
parents:
7107
diff
changeset
|
42 return c; |
484 | 43 } |
44 | |
45 cmputc (c) | |
46 char c; | |
47 { | |
48 if (termscript) | |
49 fputc (c & 0177, termscript); | |
50 putchar (c & 0177); | |
8985
2825665b8352
(evalcost, cmputc): They now return their arguments.
Richard M. Stallman <rms@gnu.org>
parents:
7107
diff
changeset
|
51 return c; |
484 | 52 } |
53 | |
54 /* NEXT TWO ARE DONE WITH MACROS */ | |
55 #if 0 | |
56 /* | |
57 * Assume the cursor is at row row, column col. Normally used only after | |
58 * clearing the screen, when the cursor is at (0, 0), but what the heck, | |
59 * let's let the guy put it anywhere. | |
60 */ | |
61 | |
62 static | |
63 at (row, col) { | |
64 curY = row; | |
65 curX = col; | |
66 } | |
67 | |
68 /* | |
69 * Add n columns to the current cursor position. | |
70 */ | |
71 | |
72 static | |
73 addcol (n) { | |
74 curX += n; | |
75 | |
76 /* | |
77 * If cursor hit edge of screen, what happened? | |
78 * N.B.: DO NOT!! write past edge of screen. If you do, you | |
79 * deserve what you get. Furthermore, on terminals with | |
80 * autowrap (but not magicwrap), don't write in the last column | |
81 * of the last line. | |
82 */ | |
83 | |
84 if (curX == Wcm.cm_cols) { | |
85 /* | |
86 * Well, if magicwrap, still there, past the edge of the | |
87 * screen (!). If autowrap, on the col 0 of the next line. | |
88 * Otherwise on last column. | |
89 */ | |
90 | |
91 if (Wcm.cm_magicwrap) | |
92 ; /* "limbo" */ | |
93 else if (Wcm.cm_autowrap) { | |
94 curX = 0; | |
95 curY++; /* Beware end of screen! */ | |
96 } | |
97 else | |
98 curX--; | |
99 } | |
100 } | |
101 #endif | |
102 | |
103 /* | |
10437 | 104 * Terminals with magicwrap (xn) don't all behave identically. |
105 * The VT100 leaves the cursor in the last column but will wrap before | |
106 * printing the next character. I hear that the Concept terminal does | |
107 * the wrap immediately but ignores the next newline it sees. And some | |
108 * terminals just have buggy firmware, and think that the cursor is still | |
109 * in limbo if we use direct cursor addressing from the phantom column. | |
110 * The only guaranteed safe thing to do is to emit a CRLF immediately | |
111 * after we reach the last column; this takes us to a known state. | |
112 */ | |
113 void | |
114 cmcheckmagic () | |
115 { | |
116 if (curX == FrameCols) | |
117 { | |
118 if (!MagicWrap || curY >= FrameRows - 1) | |
119 abort (); | |
120 if (termscript) | |
121 putc ('\r', termscript); | |
122 putchar ('\r'); | |
123 if (termscript) | |
124 putc ('\n', termscript); | |
125 putchar ('\n'); | |
126 curX = 0; | |
127 curY++; | |
128 } | |
129 } | |
130 | |
131 | |
132 /* | |
484 | 133 * (Re)Initialize the cost factors, given the output speed of the terminal |
134 * in the variable ospeed. (Note: this holds B300, B9600, etc -- ie stuff | |
135 * out of <sgtty.h>.) | |
136 */ | |
137 | |
138 cmcostinit () | |
139 { | |
140 char *p; | |
141 | |
142 #define COST(x,e) (x ? (cost = 0, tputs (x, 1, e), cost) : BIG) | |
143 #define CMCOST(x,e) ((x == 0) ? BIG : (p = tgoto(x, 0, 0), COST(p ,e))) | |
144 | |
145 Wcm.cc_up = COST (Wcm.cm_up, evalcost); | |
146 Wcm.cc_down = COST (Wcm.cm_down, evalcost); | |
147 Wcm.cc_left = COST (Wcm.cm_left, evalcost); | |
148 Wcm.cc_right = COST (Wcm.cm_right, evalcost); | |
149 Wcm.cc_home = COST (Wcm.cm_home, evalcost); | |
150 Wcm.cc_cr = COST (Wcm.cm_cr, evalcost); | |
151 Wcm.cc_ll = COST (Wcm.cm_ll, evalcost); | |
152 Wcm.cc_tab = Wcm.cm_tabwidth ? COST (Wcm.cm_tab, evalcost) : BIG; | |
153 | |
154 /* | |
155 * These last three are actually minimum costs. When (if) they are | |
156 * candidates for the least-cost motion, the real cost is computed. | |
157 * (Note that "0" is the assumed to generate the minimum cost. | |
158 * While this is not necessarily true, I have yet to see a terminal | |
159 * for which is not; all the terminals that have variable-cost | |
160 * cursor motion seem to take straight numeric values. --ACT) | |
161 */ | |
162 | |
163 Wcm.cc_abs = CMCOST (Wcm.cm_abs, evalcost); | |
164 Wcm.cc_habs = CMCOST (Wcm.cm_habs, evalcost); | |
165 Wcm.cc_vabs = CMCOST (Wcm.cm_vabs, evalcost); | |
166 | |
167 #undef CMCOST | |
168 #undef COST | |
169 } | |
170 | |
171 /* | |
172 * Calculate the cost to move from (srcy, srcx) to (dsty, dstx) using | |
173 * up and down, and left and right, motions, and tabs. If doit is set | |
174 * actually perform the motion. | |
175 */ | |
176 | |
177 static | |
178 calccost (srcy, srcx, dsty, dstx, doit) | |
179 { | |
180 register int deltay, | |
181 deltax, | |
182 c, | |
183 totalcost; | |
184 int ntabs, | |
185 n2tabs, | |
186 tabx, | |
187 tab2x, | |
188 tabcost; | |
189 register char *p; | |
190 | |
191 /* If have just wrapped on a terminal with xn, | |
192 don't believe the cursor position: give up here | |
193 and force use of absolute positioning. */ | |
194 | |
195 if (curX == Wcm.cm_cols) | |
196 goto fail; | |
197 | |
198 totalcost = 0; | |
199 if ((deltay = dsty - srcy) == 0) | |
200 goto x; | |
201 if (deltay < 0) | |
202 p = Wcm.cm_up, c = Wcm.cc_up, deltay = -deltay; | |
203 else | |
204 p = Wcm.cm_down, c = Wcm.cc_down; | |
205 if (c == BIG) { /* caint get thar from here */ | |
206 if (doit) | |
207 printf ("OOPS"); | |
208 return c; | |
209 } | |
210 totalcost = c * deltay; | |
211 if (doit) | |
212 while (--deltay >= 0) | |
213 tputs (p, 1, cmputc); | |
214 x: | |
215 if ((deltax = dstx - srcx) == 0) | |
216 goto done; | |
217 if (deltax < 0) { | |
218 p = Wcm.cm_left, c = Wcm.cc_left, deltax = -deltax; | |
219 goto dodelta; /* skip all the tab junk */ | |
220 } | |
221 /* Tabs (the toughie) */ | |
222 if (Wcm.cc_tab >= BIG || !Wcm.cm_usetabs) | |
223 goto olddelta; /* forget it! */ | |
224 | |
225 /* | |
226 * ntabs is # tabs towards but not past dstx; n2tabs is one more | |
227 * (ie past dstx), but this is only valid if that is not past the | |
228 * right edge of the screen. We can check that at the same time | |
229 * as we figure out where we would be if we use the tabs (which | |
230 * we will put into tabx (for ntabs) and tab2x (for n2tabs)). | |
231 */ | |
232 | |
233 ntabs = (deltax + srcx % Wcm.cm_tabwidth) / Wcm.cm_tabwidth; | |
234 n2tabs = ntabs + 1; | |
235 tabx = (srcx / Wcm.cm_tabwidth + ntabs) * Wcm.cm_tabwidth; | |
236 tab2x = tabx + Wcm.cm_tabwidth; | |
237 | |
238 if (tab2x >= Wcm.cm_cols) /* too far (past edge) */ | |
239 n2tabs = 0; | |
240 | |
241 /* | |
242 * Now set tabcost to the cost for using ntabs, and c to the cost | |
243 * for using n2tabs, then pick the minimum. | |
244 */ | |
245 | |
246 /* cost for ntabs + cost for right motion */ | |
247 tabcost = ntabs ? ntabs * Wcm.cc_tab + (dstx - tabx) * Wcm.cc_right | |
248 : BIG; | |
249 | |
250 /* cost for n2tabs + cost for left motion */ | |
251 c = n2tabs ? n2tabs * Wcm.cc_tab + (tab2x - dstx) * Wcm.cc_left | |
252 : BIG; | |
253 | |
254 if (c < tabcost) /* then cheaper to overshoot & back up */ | |
255 ntabs = n2tabs, tabcost = c, tabx = tab2x; | |
256 | |
257 if (tabcost >= BIG) /* caint use tabs */ | |
258 goto newdelta; | |
259 | |
260 /* | |
261 * See if tabcost is less than just moving right | |
262 */ | |
263 | |
264 if (tabcost < (deltax * Wcm.cc_right)) { | |
265 totalcost += tabcost; /* use the tabs */ | |
266 if (doit) | |
267 while (--ntabs >= 0) | |
268 tputs (Wcm.cm_tab, 1, cmputc); | |
269 srcx = tabx; | |
270 } | |
271 | |
272 /* | |
273 * Now might as well just recompute the delta. | |
274 */ | |
275 | |
276 newdelta: | |
277 if ((deltax = dstx - srcx) == 0) | |
278 goto done; | |
279 olddelta: | |
280 if (deltax > 0) | |
281 p = Wcm.cm_right, c = Wcm.cc_right; | |
282 else | |
283 p = Wcm.cm_left, c = Wcm.cc_left, deltax = -deltax; | |
284 | |
285 dodelta: | |
286 if (c == BIG) { /* caint get thar from here */ | |
287 fail: | |
288 if (doit) | |
289 printf ("OOPS"); | |
290 return BIG; | |
291 } | |
292 totalcost += c * deltax; | |
293 if (doit) | |
294 while (--deltax >= 0) | |
295 tputs (p, 1, cmputc); | |
296 done: | |
297 return totalcost; | |
298 } | |
299 | |
300 #if 0 | |
301 losecursor () | |
302 { | |
303 curY = -1; | |
304 } | |
305 #endif | |
306 | |
307 #define USEREL 0 | |
308 #define USEHOME 1 | |
309 #define USELL 2 | |
310 #define USECR 3 | |
311 | |
312 cmgoto (row, col) | |
313 { | |
314 int homecost, | |
315 crcost, | |
316 llcost, | |
317 relcost, | |
318 directcost; | |
319 int use; | |
320 char *p, | |
321 *dcm; | |
322 | |
323 /* First the degenerate case */ | |
324 if (row == curY && col == curX) /* already there */ | |
325 return; | |
326 | |
327 if (curY >= 0 && curX >= 0) | |
328 { | |
329 /* We may have quick ways to go to the upper-left, bottom-left, | |
330 * start-of-line, or start-of-next-line. Or it might be best to | |
331 * start where we are. Examine the options, and pick the cheapest. | |
332 */ | |
333 | |
334 relcost = calccost (curY, curX, row, col, 0); | |
335 use = USEREL; | |
336 if ((homecost = Wcm.cc_home) < BIG) | |
337 homecost += calccost (0, 0, row, col, 0); | |
338 if (homecost < relcost) | |
339 relcost = homecost, use = USEHOME; | |
340 if ((llcost = Wcm.cc_ll) < BIG) | |
341 llcost += calccost (Wcm.cm_rows - 1, 0, row, col, 0); | |
342 if (llcost < relcost) | |
343 relcost = llcost, use = USELL; | |
344 if ((crcost = Wcm.cc_cr) < BIG) { | |
345 if (Wcm.cm_autolf) | |
346 if (curY + 1 >= Wcm.cm_rows) | |
347 crcost = BIG; | |
348 else | |
349 crcost += calccost (curY + 1, 0, row, col, 0); | |
350 else | |
351 crcost += calccost (curY, 0, row, col, 0); | |
352 } | |
353 if (crcost < relcost) | |
354 relcost = crcost, use = USECR; | |
355 directcost = Wcm.cc_abs, dcm = Wcm.cm_abs; | |
356 if (row == curY && Wcm.cc_habs < BIG) | |
357 directcost = Wcm.cc_habs, dcm = Wcm.cm_habs; | |
358 else if (col == curX && Wcm.cc_vabs < BIG) | |
359 directcost = Wcm.cc_vabs, dcm = Wcm.cm_vabs; | |
360 } | |
361 else | |
362 { | |
363 directcost = 0, relcost = 100000; | |
364 dcm = Wcm.cm_abs; | |
365 } | |
366 | |
367 /* | |
368 * In the following comparison, the = in <= is because when the costs | |
369 * are the same, it looks nicer (I think) to move directly there. | |
370 */ | |
371 if (directcost <= relcost) | |
372 { | |
373 /* compute REAL direct cost */ | |
374 cost = 0; | |
375 p = dcm == Wcm.cm_habs ? tgoto (dcm, row, col) : | |
376 tgoto (dcm, col, row); | |
377 tputs (p, 1, evalcost); | |
378 if (cost <= relcost) | |
379 { /* really is cheaper */ | |
380 tputs (p, 1, cmputc); | |
381 curY = row, curX = col; | |
382 return; | |
383 } | |
384 } | |
385 | |
386 switch (use) | |
387 { | |
388 case USEHOME: | |
389 tputs (Wcm.cm_home, 1, cmputc); | |
390 curY = 0, curX = 0; | |
391 break; | |
392 | |
393 case USELL: | |
394 tputs (Wcm.cm_ll, 1, cmputc); | |
395 curY = Wcm.cm_rows - 1, curX = 0; | |
396 break; | |
397 | |
398 case USECR: | |
399 tputs (Wcm.cm_cr, 1, cmputc); | |
400 if (Wcm.cm_autolf) | |
401 curY++; | |
402 curX = 0; | |
403 break; | |
404 } | |
405 | |
406 (void) calccost (curY, curX, row, col, 1); | |
407 curY = row, curX = col; | |
408 } | |
409 | |
410 /* Clear out all terminal info. | |
411 Used before copying into it the info on the actual terminal. | |
412 */ | |
413 | |
414 Wcm_clear () | |
415 { | |
416 bzero (&Wcm, sizeof Wcm); | |
417 UP = 0; | |
418 BC = 0; | |
419 } | |
420 | |
421 /* | |
422 * Initialized stuff | |
423 * Return 0 if can do CM. | |
424 * Return -1 if cannot. | |
425 * Return -2 if size not specified. | |
426 */ | |
427 | |
428 Wcm_init () | |
429 { | |
430 #if 0 | |
431 if (Wcm.cm_abs && !Wcm.cm_ds) | |
432 return 0; | |
433 #endif | |
434 if (Wcm.cm_abs) | |
435 return 0; | |
436 /* Require up and left, and, if no absolute, down and right */ | |
437 if (!Wcm.cm_up || !Wcm.cm_left) | |
438 return - 1; | |
439 if (!Wcm.cm_abs && (!Wcm.cm_down || !Wcm.cm_right)) | |
440 return - 1; | |
441 /* Check that we know the size of the screen.... */ | |
442 if (Wcm.cm_rows <= 0 || Wcm.cm_cols <= 0) | |
443 return - 2; | |
444 return 0; | |
445 } |