7
|
1 /* vi:set ts=8 sts=4 sw=4:
|
|
2 *
|
|
3 * VIM - Vi IMproved by Bram Moolenaar
|
|
4 *
|
|
5 * Do ":help uganda" in Vim to read copying and usage conditions.
|
|
6 * Do ":help credits" in Vim to see a list of people who contributed.
|
|
7 * See README.txt for an overview of the Vim source code.
|
|
8 */
|
|
9
|
|
10 #include "vim.h"
|
|
11
|
|
12 /*
|
|
13 * os_riscos.c
|
|
14 *
|
|
15 * Thomas Leonard <tal197@ecs.soton.ac.uk>
|
|
16 */
|
|
17
|
|
18 const char *__dynamic_da_name = "Vim heap"; /* Enable and name our dynamic area */
|
|
19 int ro_line_mode = TRUE; /* For Ex mode we much echo chars to the screen ourselves */
|
|
20 int windowed; /* Flag - are we running inside a text window? */
|
|
21 int WinLeft, WinTop; /* We might be started inside a text window */
|
|
22 int ScrollTop; /* Make cursor movements relative to ScrollTop. */
|
|
23
|
|
24 int old_escape_state = -1;
|
|
25 int old_cursor_state = -1;
|
|
26
|
|
27 #define rgb(r,g,b) ((b<<24) + (g<<16) + (r<<8))
|
|
28 #define NORMAL_FG 0x00000000
|
|
29 #define NORMAL_BG 0xffffffff
|
|
30
|
|
31 /* Convert a DOS colour number to an RGB palette entry.
|
|
32 * Mappings from X11 rgb/txt file.
|
|
33 */
|
|
34 static int
|
|
35 map_colour(dos)
|
|
36 int dos; /* Standard DOS colour number. */
|
|
37 {
|
|
38 switch (dos)
|
|
39 {
|
|
40 case 0: return 0; /* Black */
|
|
41 case 1: return rgb(0,0,139); /* DarkBlue */
|
|
42 case 2: return rgb(0,100,0); /* DarkGreen */
|
|
43 case 3: return rgb(0,139,139); /* DarkCyan */
|
|
44 case 4: return rgb(139,0,0); /* DarkRed */
|
|
45 case 5: return rgb(139,0,139); /* DarkMagenta */
|
|
46 case 6: return rgb(165,42,42); /* Brown, DarkYellow */
|
|
47 case 7: return rgb(211,211,211); /* LightGray, LightGrey, Gray, Grey */
|
|
48 case 8: return rgb(169,169,169); /* DarkGray, DarkGrey */
|
|
49 case 9: return rgb(173,216,230); /* Blue, LightBlue */
|
|
50 case 10: return rgb(144,238,144); /* Green, LightGreen */
|
|
51 case 11: return rgb(224,255,255); /* Cyan, LightCyan */
|
|
52 case 12: return rgb(255,0,0); /* Red, LightRed */
|
|
53 case 13: return rgb(255,0,255); /* Magenta, LightMagenta */
|
|
54 case 14: return rgb(255,255,0); /* Yellow, LightYellow */
|
|
55 case 15: return rgb(255,255,255); /* White */
|
|
56 }
|
|
57 return rgb(100,100,100);
|
|
58 }
|
|
59
|
|
60 static void
|
|
61 text_fg(fg)
|
|
62 int fg; /* Foregound colour in the form &BBGGRR00 */
|
|
63 {
|
|
64 xswi(ColourTrans_SetTextColour, fg, 0, 0, 0);
|
|
65 }
|
|
66
|
|
67 static void
|
|
68 text_bg(bg)
|
|
69 int bg; /* Backgound colour in the form &BBGGRR00 */
|
|
70 {
|
|
71 xswi(ColourTrans_SetTextColour, bg, 0, 0, 1 << 7);
|
|
72 }
|
|
73
|
|
74 #define OUT_NORMAL 0
|
|
75 #define OUT_NUMBER 1 /* Reading in a number */
|
|
76
|
|
77 void
|
|
78 mch_write(s, len)
|
|
79 char_u *s;
|
|
80 int len;
|
|
81 {
|
|
82 static int mode = OUT_NORMAL;
|
|
83 static int x, y; /* For reading numbers in. */
|
|
84
|
|
85 if (!term_console)
|
|
86 {
|
|
87 /* Maybe we are running Vim remotely - don't interpret chars */
|
|
88 while (len--)
|
|
89 {
|
|
90 char_u c = *s++;
|
|
91 swi(OS_WriteC, c);
|
|
92 /* We might need to send a CR too. This shouldn't
|
|
93 * hurt if we don't need it, should it?
|
|
94 */
|
|
95 if (c == 10)
|
|
96 swi(OS_WriteI + 13);
|
|
97 }
|
|
98 return;
|
|
99 }
|
|
100
|
|
101 while (len--)
|
|
102 {
|
|
103 char_u c = *s++;
|
|
104 switch (mode)
|
|
105 {
|
|
106 case OUT_NUMBER:
|
|
107 if (c < '0' || c > '9')
|
|
108 {
|
|
109 mode = OUT_NORMAL;
|
|
110 }
|
|
111 else
|
|
112 {
|
|
113 x = (x * 10) + c - '0';
|
|
114 continue;
|
|
115 }
|
|
116 /* note: no break here! */
|
|
117
|
|
118 case OUT_NORMAL:
|
|
119 switch (c)
|
|
120 {
|
|
121 case 1:
|
|
122 /* Number (in decimal) follows. */
|
|
123 mode = OUT_NUMBER;
|
|
124 y = x;
|
|
125 x = 0;
|
|
126 break;
|
|
127 case 2:
|
|
128 /* Position cursor. */
|
|
129 swi(OS_WriteI + 31);
|
|
130 swi(OS_WriteC, x);
|
|
131 swi(OS_WriteC, y - ScrollTop);
|
|
132 break;
|
|
133 case 3:
|
|
134 /* Set scroll region. */
|
|
135 if (x == Rows -1 && y == 0 && !windowed)
|
|
136 {
|
|
137 /* Whole screen - remove text window.
|
|
138 * This is MUCH faster.
|
|
139 */
|
|
140 swi(OS_WriteI + 26);
|
|
141 }
|
|
142 else
|
|
143 {
|
|
144 /* Create a text window. */
|
|
145 swi(OS_WriteI + 28);
|
|
146 swi(OS_WriteC, WinLeft);
|
|
147 swi(OS_WriteC, WinTop + x);
|
|
148 swi(OS_WriteC, WinLeft + Columns - 1);
|
|
149 swi(OS_WriteC, WinTop + y);
|
|
150 }
|
|
151 ScrollTop = y;
|
|
152 break;
|
|
153 case 4:
|
|
154 /* Normal mode. */
|
|
155 text_fg(NORMAL_FG);
|
|
156 text_bg(NORMAL_BG);
|
|
157 break;
|
|
158 case 5:
|
|
159 /* Reverse mode. */
|
|
160 text_fg(NORMAL_BG);
|
|
161 text_bg(NORMAL_FG);
|
|
162 break;
|
|
163 case 10:
|
|
164 swi(OS_NewLine);
|
|
165 break;
|
|
166 case 14:
|
|
167 /* Cursor invisible. */
|
|
168 swi(OS_WriteN,
|
|
169 "\027\001\000\000\000\000\000\000\000\000",
|
|
170 10);
|
|
171 break;
|
|
172 case 15:
|
|
173 /* Cursor visible. */
|
|
174 swi(OS_WriteN,
|
|
175 "\027\001\002\000\000\000\000\000\000\000",
|
|
176 10);
|
|
177 break;
|
|
178 case 16:
|
|
179 /* Cursor very visible (flash) */
|
|
180 swi(OS_WriteN,
|
|
181 "\027\001\003\000\000\000\000\000\000\000",
|
|
182 10);
|
|
183 case 17:
|
|
184 /* Set foreground colour. */
|
|
185 text_fg(map_colour(x));
|
|
186 break;
|
|
187 case 18:
|
|
188 /* Set background colour. */
|
|
189 text_bg(map_colour(x));
|
|
190 break;
|
|
191 case 19:
|
|
192 /* Scroll text down. */
|
|
193 swi(OS_WriteN,
|
|
194 "\027\007\000\002\000\000\000\000\000\000",
|
|
195 10);
|
|
196 break;
|
|
197 default:
|
|
198 swi(OS_WriteC, c);
|
|
199 }
|
|
200 continue;
|
|
201
|
|
202 default:
|
|
203 printf("[output error]");
|
|
204 mode = OUT_NORMAL;
|
|
205 }
|
|
206 }
|
|
207 }
|
|
208
|
|
209 /*
|
|
210 * mch_inchar(): low level input funcion.
|
|
211 * Get a characters from the keyboard.
|
|
212 * Return the number of characters that are available.
|
|
213 * If wtime == 0 do not wait for characters.
|
|
214 * If wtime == n wait n msecs for characters.
|
|
215 * If wtime == -1 wait forever for characters.
|
|
216 *
|
|
217 * TODO: call convert_input() for 'fileencoding' to 'encoding' conversion.
|
|
218 */
|
|
219 int
|
|
220 mch_inchar(buf, maxlen, wtime, tb_change_cnt)
|
|
221 char_u *buf;
|
|
222 int maxlen;
|
|
223 long wtime;
|
|
224 int tb_change_cnt;
|
|
225 {
|
|
226 int got=0;
|
|
227 unsigned int start_time = clock();
|
|
228
|
|
229 if (ro_line_mode)
|
|
230 {
|
|
231 /* We're probably in Ex mode - get whole lines at a time. */
|
|
232
|
|
233 static char_u line_buffer[256];
|
|
234 static int remaining_chars = 0;
|
|
235 static int buf_pos = 0;
|
|
236
|
|
237 /* Do we need to fetch another line? */
|
|
238 if (remaining_chars == 0)
|
|
239 {
|
|
240 int old_esc_state;
|
|
241 swi(OS_Byte, 200, 1, 0xfe);
|
|
242 old_esc_state = r1;
|
|
243
|
|
244 buf_pos = 0;
|
|
245 if (xswi(OS_ReadLine, line_buffer, 255, 0, 255) & (c_flag | v_flag))
|
|
246 {
|
|
247 got_int = TRUE; /* ESC pressed */
|
|
248 r1 = 0;
|
|
249 }
|
|
250 line_buffer[r1] = 13;
|
|
251 remaining_chars = r1 + 1; /* Count CR as part of input */
|
|
252
|
|
253 swi(OS_Byte, 200, old_esc_state, 0);
|
|
254 }
|
|
255
|
|
256 /* Can we send the rest of the buffer back in one go? */
|
|
257 if (remaining_chars <= maxlen)
|
|
258 {
|
|
259 int got = remaining_chars;
|
|
260
|
|
261 memcpy(buf, line_buffer + buf_pos, got);
|
|
262 remaining_chars = 0;
|
|
263 return got;
|
|
264 }
|
|
265
|
|
266 /* Send as much as we can */
|
|
267 memcpy(buf, line_buffer + buf_pos, maxlen);
|
|
268 buf_pos += maxlen;
|
|
269 remaining_chars -= maxlen;
|
|
270
|
|
271 return maxlen;
|
|
272 }
|
|
273
|
|
274 if (!term_console)
|
|
275 {
|
|
276 /* Use OS_ReadC for all input.
|
|
277 * Avoids problems with remote access getting interference from
|
|
278 * the keyboard.
|
|
279 */
|
|
280 if (wtime == 0)
|
|
281 return 0; /* Ignore quick key checks */
|
|
282
|
|
283 if (xswi(OS_ReadC) & c_flag)
|
|
284 {
|
|
285 got_int = TRUE; /* ESC pressed - can this happen? */
|
|
286 swi(OS_Byte, 124); /* Clear Escape state */
|
|
287 r0 = 0x1b; /* It *might* not have been Escape! */
|
|
288 }
|
|
289 buf[0] = r0;
|
|
290 return 1;
|
|
291 }
|
|
292
|
|
293 /*
|
|
294 * OK, here's the plan:
|
|
295 *
|
|
296 * 1) Wait until wtime expires or we get a key
|
|
297 * 2) Get keys until the keyboard buffer is empty or buf is full
|
|
298 */
|
|
299
|
|
300 while (xswi(OS_Byte,145,0) & c_flag)
|
|
301 {
|
|
302 /* Nothing at all in the keyboard buffer.
|
|
303 * Has our time expired yet?
|
|
304 */
|
|
305 if ( (wtime != -1) && (clock() - start_time) >= wtime )
|
|
306 return 0; /* Nothing read - giving up */
|
|
307 }
|
|
308
|
|
309 /* We've got one char (in r2) - are there any more? */
|
|
310
|
|
311 while (got < maxlen)
|
|
312 {
|
|
313 buf[got++] = r2;
|
|
314
|
|
315 if (xswi(OS_Byte,145,0) & c_flag)
|
|
316 return got; /* Keyboard buffer empty */
|
|
317 }
|
|
318 return got; /* buf is full */
|
|
319 }
|
|
320
|
|
321 /*
|
|
322 * return non-zero if a character is available
|
|
323 */
|
|
324 int
|
|
325 mch_char_avail()
|
|
326 {
|
|
327 if (!term_console)
|
|
328 return 0; /* Can't tell */
|
|
329 if (xswi(OS_Byte, 152, 0) & c_flag)
|
|
330 return 0;
|
|
331 return 1;
|
|
332 }
|
|
333
|
|
334 /* Find out how much free memory we have.
|
|
335 * I don't know how to work this out exactly but, since we can claim
|
|
336 * more memory from the OS, let's just report the free pool size.
|
|
337 * Dynamic area 6 doesn't exist pre 3.6 according to StrongHelp, so
|
|
338 * we'll use Wimp_SlotSize. If that fails (outside the desktop?)
|
|
339 * then just return a big number and hope.
|
|
340 */
|
|
341 long_u
|
|
342 mch_avail_mem(special)
|
|
343 int special;
|
|
344 {
|
|
345 if (xswi(Wimp_SlotSize, -1, -1) & v_flag)
|
|
346 return 0x7fffffff;
|
|
347 return r2;
|
|
348 }
|
|
349
|
|
350 void
|
|
351 mch_delay(msec, ignoreinput)
|
|
352 long msec;
|
|
353 int ignoreinput;
|
|
354 {
|
|
355 int start_time, time_now;
|
|
356 int csec = msec / 10;
|
|
357
|
|
358 swi(OS_ReadMonotonicTime);
|
|
359 start_time = r0;
|
|
360
|
|
361 for (;;)
|
|
362 {
|
|
363 swi(OS_ReadMonotonicTime);
|
|
364 time_now = r0;
|
|
365 if (time_now - start_time > csec)
|
|
366 return;
|
|
367 #ifdef FEAT_GUI
|
|
368 /* In the GUI, allow other programs to run while waiting. */
|
|
369 if (gui.in_use)
|
|
370 gui_mch_wait_for_chars(start_time + csec);
|
|
371 #endif
|
|
372 }
|
|
373 }
|
|
374
|
|
375 /*
|
|
376 * If the machine has job control, use it to suspend the program,
|
|
377 * otherwise fake it by starting a new shell.
|
|
378 */
|
|
379 void
|
|
380 mch_suspend()
|
|
381 {
|
|
382 suspend_shell();
|
|
383 }
|
|
384
|
|
385 void
|
|
386 mch_init()
|
|
387 {
|
|
388 /*
|
|
389 * Read window size first. Calls to mch_get_shellsize() will
|
|
390 * simply return these values in future so that setting the
|
|
391 * text window (used for scrolling) won't give strange results.
|
|
392 */
|
|
393
|
|
394 int buf[7] = {132, 135, 256, 257, 1, 2, -1};
|
|
395
|
|
396 /* Command windows are no longer forced open, since if we are
|
|
397 * in the desktop then we'll use the GUI version.
|
|
398 * Opening a command window here messes up the GUI version startup
|
|
399 */
|
|
400 #ifndef FEAT_GUI
|
|
401 swi(OS_WriteI);
|
|
402 #endif
|
|
403 swi(OS_ReadVduVariables, buf, buf);
|
|
404 WinLeft = buf[0];
|
|
405 WinTop = buf[1];
|
|
406 Columns = buf[2];
|
|
407 Rows = buf[3] + 1; /* Seems to be one off (VduVars wrong?) */
|
|
408 ScrollTop = 0;
|
|
409
|
|
410 /* Are we running in a textwindow? */
|
|
411 if (Rows == buf[5] + 1 && Columns == buf[4] + 1)
|
|
412 windowed = 0;
|
|
413 else
|
|
414 windowed = 1;
|
|
415
|
|
416 /* Choose a nice colour scheme. */
|
|
417 text_fg(NORMAL_FG);
|
|
418 text_bg(NORMAL_BG);
|
|
419 }
|
|
420
|
|
421 /*
|
|
422 * Check_win checks whether we have an interactive stdout.
|
|
423 */
|
|
424 /* ARGSUSED */
|
|
425 int
|
|
426 mch_check_win(argc, argv)
|
|
427 int argc;
|
|
428 char **argv;
|
|
429 {
|
|
430 return OK;
|
|
431 }
|
|
432
|
|
433 /*
|
|
434 * Return TRUE if the input comes from a terminal, FALSE otherwise.
|
|
435 */
|
|
436 int
|
|
437 mch_input_isatty()
|
|
438 {
|
|
439 if (xswi(OS_ChangeRedirection, -1, -1) & v_flag)
|
|
440 return TRUE; /* Error - TRUE is probably correct though */
|
|
441 if (r0 == 0)
|
|
442 return TRUE;
|
|
443 return FALSE;
|
|
444 }
|
|
445
|
|
446 #ifdef FEAT_TITLE
|
|
447 int
|
|
448 mch_can_restore_title()
|
|
449 {
|
|
450 return FALSE;
|
|
451 }
|
|
452
|
|
453 int
|
|
454 mch_can_restore_icon()
|
|
455 {
|
|
456 return FALSE;
|
|
457 }
|
|
458
|
|
459
|
|
460 /*
|
|
461 * Set the window title and icon.
|
|
462 */
|
|
463 void
|
|
464 mch_settitle(title, icon)
|
|
465 char_u *title;
|
|
466 char_u *icon;
|
|
467 {
|
|
468 if (title == NULL)
|
|
469 title = (char_u *) "<untitled>";
|
|
470 #ifdef FEAT_GUI
|
|
471 if (gui.in_use && strcmp(title, gui.window_title))
|
|
472 {
|
|
473 int length;
|
|
474 length = strlen(title);
|
|
475 if (length >= gui.window_title_size)
|
|
476 length = gui.window_title_size - 1;
|
|
477 strncpy(gui.window_title, title, length);
|
|
478 gui.window_title[length] = 0;
|
|
479 ro_redraw_title(gui.window_handle);
|
|
480 }
|
|
481 #endif
|
|
482 return;
|
|
483 }
|
|
484
|
|
485 /*
|
|
486 * Restore the window/icon title.
|
|
487 * "which" is one of:
|
|
488 * 1 only restore title
|
|
489 * 2 only restore icon
|
|
490 * 3 restore title and icon
|
|
491 */
|
|
492 void
|
|
493 mch_restore_title(which)
|
|
494 int which;
|
|
495 {
|
|
496 return;
|
|
497 }
|
|
498 #endif
|
|
499
|
|
500 /*
|
|
501 * Insert user name in s[len].
|
|
502 * Return OK if a name found.
|
|
503 */
|
|
504 int
|
|
505 mch_get_user_name(s, len)
|
|
506 char_u *s;
|
|
507 int len;
|
|
508 {
|
|
509 /* RISC OS doesn't support user names. */
|
|
510 *s = NUL;
|
|
511 return FAIL;
|
|
512 }
|
|
513
|
|
514 /*
|
|
515 * Insert host name in s[len].
|
|
516 */
|
|
517
|
|
518 void
|
|
519 mch_get_host_name(s, len)
|
|
520 char_u *s;
|
|
521 int len;
|
|
522 {
|
|
523 if (xswi(OS_ReadVarVal, "Machine$Name", s, len, 0, 3) & v_flag)
|
|
524 {
|
|
525 /* Variable does not exist (normal operation) */
|
|
526 STRNCPY(s, "(unknown)", len);
|
|
527 }
|
|
528 }
|
|
529
|
|
530 /*
|
|
531 * return process ID
|
|
532 */
|
|
533 long
|
|
534 mch_get_pid()
|
|
535 {
|
|
536 if (xswi(Wimp_ReadSysInfo, 5) & v_flag)
|
|
537 return 0;
|
|
538 return r0;
|
|
539 }
|
|
540
|
|
541 /*
|
|
542 * Get name of current directory into buffer 'buf' of length 'len' bytes.
|
|
543 * Return OK for success, FAIL for failure.
|
|
544 */
|
|
545 int
|
|
546 mch_dirname(buf, len)
|
|
547 char_u *buf;
|
|
548 int len;
|
|
549 {
|
|
550 if (xswi(OS_FSControl, 37, "@", buf, 0, 0, len) & v_flag)
|
|
551 return FAIL;
|
|
552 return OK;
|
|
553 }
|
|
554
|
|
555 /*
|
|
556 * Get absolute file name into buffer 'buf' of length 'len' bytes.
|
|
557 *
|
|
558 * return FAIL for failure, OK for success
|
|
559 */
|
|
560 int
|
|
561 mch_FullName(fname, buf, len, force)
|
|
562 char_u *fname, *buf;
|
|
563 int len;
|
|
564 int force; /* Also expand when already absolute path name.
|
|
565 * Not used under RISC OS.
|
|
566 */
|
|
567 {
|
|
568 if (xswi(OS_FSControl, 37, fname, buf, 0, 0, len) & v_flag)
|
|
569 return FAIL;
|
|
570 return OK;
|
|
571 }
|
|
572
|
|
573 /*
|
|
574 * Return TRUE if "fname" does not depend on the current directory.
|
|
575 */
|
|
576 int
|
|
577 mch_isFullName(fname)
|
|
578 char_u *fname;
|
|
579 {
|
|
580 if (strstr(fname, "::") && strstr(fname,".$."))
|
|
581 return TRUE;
|
|
582 return FALSE;
|
|
583 }
|
|
584
|
|
585 /*
|
|
586 * Get file permissions for 'name'.
|
|
587 * Returns -1 when it doesn't exist.
|
|
588 */
|
|
589 long
|
|
590 mch_getperm(name)
|
|
591 char_u *name;
|
|
592 {
|
|
593 struct stat statb;
|
|
594
|
|
595 if (stat((char *)name, &statb))
|
|
596 return -1;
|
|
597 return statb.st_mode;
|
|
598 }
|
|
599
|
|
600 /*
|
|
601 * set file permission for 'name' to 'perm'
|
|
602 *
|
|
603 * return FAIL for failure, OK otherwise
|
|
604 */
|
|
605 int
|
|
606 mch_setperm(name, perm)
|
|
607 char_u *name;
|
|
608 long perm;
|
|
609 {
|
|
610 return (chmod((char *)name, (mode_t)perm) == 0 ? OK : FAIL);
|
|
611 }
|
|
612
|
|
613 /*
|
|
614 * Set hidden flag for "name".
|
|
615 */
|
|
616 /* ARGSUSED */
|
|
617 void
|
|
618 mch_hide(name)
|
|
619 char_u *name;
|
|
620 {
|
|
621 /* can't hide a file */
|
|
622 }
|
|
623
|
|
624 /*
|
|
625 * return TRUE if "name" is a directory
|
|
626 * return FALSE if "name" is not a directory
|
|
627 * return FALSE for error
|
|
628 */
|
|
629 int
|
|
630 mch_isdir(name)
|
|
631 char_u *name;
|
|
632 {
|
|
633 if (xswi(OS_File, 17, name) & v_flag)
|
|
634 return FALSE;
|
|
635 if (r0 == 2 || r0 == 3)
|
|
636 return TRUE; /* Count image files as directories. */
|
|
637 return FALSE;
|
|
638 }
|
|
639
|
|
640 #if defined(FEAT_EVAL) || defined(PROTO)
|
|
641 /*
|
|
642 * Return 1 if "name" can be executed, 0 if not.
|
|
643 * Return -1 if unknown. Requires which to work.
|
|
644 */
|
|
645 int
|
|
646 mch_can_exe(name)
|
|
647 char_u *name;
|
|
648 {
|
|
649 char_u *buf;
|
|
650 char_u *p;
|
|
651 int retval;
|
|
652
|
|
653 buf = alloc((unsigned)STRLEN(name) + 7);
|
|
654 if (buf == NULL)
|
|
655 return -1;
|
|
656 sprintf((char *)buf, "which %s", name);
|
24
|
657 p = get_cmd_output(buf, NULL, SHELL_SILENT);
|
7
|
658 vim_free(buf);
|
|
659 if (p == NULL)
|
|
660 return -1;
|
|
661 /* result can be: "name: Command not found" */
|
|
662 retval = (*p != NUL && strstr((char *)p, "not found") == NULL);
|
|
663 vim_free(p);
|
|
664 return retval;
|
|
665 }
|
|
666 #endif
|
|
667
|
|
668 /*
|
|
669 * Check what "name" is:
|
|
670 * NODE_NORMAL: file or directory (or doesn't exist)
|
|
671 * NODE_WRITABLE: writable device, socket, fifo, etc.
|
|
672 * NODE_OTHER: non-writable things
|
|
673 */
|
|
674 int
|
|
675 mch_nodetype(name)
|
|
676 char_u *name;
|
|
677 {
|
|
678 /* TODO */
|
|
679 return NODE_NORMAL;
|
|
680 }
|
|
681
|
|
682 void
|
|
683 mch_early_init()
|
|
684 {
|
|
685 /* Turn off all the horrible filename munging in UnixLib. */
|
35
|
686 int __riscosify_control = __RISCOSIFY_NO_PROCESS;
|
7
|
687 }
|
|
688
|
|
689 void
|
|
690 mch_exit(r)
|
|
691 int r;
|
|
692 {
|
|
693 settmode(TMODE_COOK);
|
|
694 exiting = TRUE;
|
|
695 out_flush();
|
|
696 ml_close_all(TRUE); /* remove all memfiles */
|
|
697
|
|
698 #ifdef FEAT_GUI
|
|
699 if (gui.in_use)
|
|
700 gui_exit(r);
|
|
701 #endif
|
|
702 swi(OS_NewLine);
|
|
703 if (old_escape_state != -1)
|
|
704 swi(OS_Byte, 229, old_escape_state, 0);
|
|
705 if (old_cursor_state != -1)
|
|
706 swi(OS_Byte, 4, old_cursor_state);
|
|
707 exit(r);
|
|
708 }
|
|
709
|
|
710 void
|
|
711 mch_settmode(tmode)
|
|
712 int tmode; /* TMODE_RAW or TMODE_COOK */
|
|
713 {
|
|
714 if (tmode == TMODE_COOK)
|
|
715 {
|
|
716 ro_line_mode = TRUE;
|
|
717 return;
|
|
718 }
|
|
719
|
|
720 ro_line_mode = FALSE;
|
|
721
|
|
722 if (term_console)
|
|
723 {
|
|
724 /* Block cursor. */
|
|
725 swi(OS_WriteN,
|
|
726 "\027\000\012\000\000\000\000\000\000\000",
|
|
727 10);
|
|
728
|
|
729 /* Disable the standard cursor key actions. */
|
|
730 swi(OS_Byte, 4, 1);
|
|
731 if (old_cursor_state == -1)
|
|
732 old_cursor_state = r1;
|
|
733 }
|
|
734
|
|
735 /* Stop Escape from quitting Vim! */
|
|
736 swi(OS_Byte, 229, 1, 0);
|
|
737 if (old_escape_state == -1)
|
|
738 old_escape_state = r1;
|
|
739 }
|
|
740
|
|
741 /*
|
|
742 * set mouse clicks on or off (only works for xterms)
|
|
743 */
|
|
744 void
|
|
745 mch_setmouse(on)
|
|
746 int on;
|
|
747 {
|
|
748 }
|
|
749
|
|
750 /*
|
|
751 * set screen mode, always fails.
|
|
752 */
|
|
753 /* ARGSUSED */
|
|
754 int
|
|
755 mch_screenmode(arg)
|
|
756 char_u *arg;
|
|
757 {
|
35
|
758 EMSG(_(e_screenmode));
|
7
|
759 return FAIL;
|
|
760 }
|
|
761
|
|
762 /*
|
|
763 * Try to get the current window size.
|
|
764 * Return OK when size could be determined, FAIL otherwise.
|
|
765 * Simply return results stored by mch_init() if we are the
|
|
766 * machine's console. If not, we don't know how big the screen is.
|
|
767 */
|
|
768 int
|
|
769 mch_get_shellsize()
|
|
770 {
|
|
771 /* if size changed: screenalloc will allocate new screen buffers */
|
|
772 return term_console ? OK : FAIL;
|
|
773 }
|
|
774
|
|
775 /*
|
|
776 * Can't change the size.
|
|
777 * Assume the user knows what he's doing and use the new values.
|
|
778 */
|
|
779 void
|
|
780 mch_set_shellsize()
|
|
781 {
|
|
782 /* Assume the user knows what he's doing and use the new values. */
|
|
783 }
|
|
784
|
|
785 /*
|
|
786 * Rows and/or Columns has changed.
|
|
787 */
|
|
788 void
|
|
789 mch_new_shellsize()
|
|
790 {
|
|
791 /* Nothing to do. */
|
|
792 }
|
|
793
|
|
794 int
|
|
795 mch_call_shell(cmd, options)
|
|
796 char_u *cmd;
|
|
797 int options; /* SHELL_*, see vim.h */
|
|
798 {
|
|
799 int retval;
|
|
800 int tmode = cur_tmode;
|
|
801
|
|
802 if (cmd == NULL)
|
|
803 cmd = (char_u *) "GOS";
|
|
804
|
|
805 #ifdef FEAT_GUI
|
|
806 if (gui.in_use)
|
|
807 return gui_mch_call_shell(cmd, options);
|
|
808 #endif
|
|
809 if (options & SHELL_COOKED)
|
|
810 settmode(TMODE_COOK); /* set to normal mode */
|
|
811 MSG_PUTS("\n");
|
|
812
|
|
813 /* I don't even want to think about what UnixLib must
|
|
814 * be doing to allow this to work...
|
|
815 */
|
|
816 retval = system(cmd);
|
|
817 if (retval && !(options & SHELL_SILENT))
|
|
818 EMSG(strerror(EOPSYS)); /* Doesn't seem to set errno? */
|
|
819
|
|
820 swi(OS_Byte, 229, 1, 0); /* Re-disable escape */
|
|
821 if (tmode == TMODE_RAW)
|
|
822 settmode(TMODE_RAW); /* set to raw mode */
|
|
823 return retval ? FAIL : OK;
|
|
824 }
|
|
825
|
|
826 /*
|
|
827 * Check for Escape being pressed right now.
|
|
828 * [ different if !term_console? ]
|
|
829 */
|
|
830 void
|
|
831 mch_breakcheck()
|
|
832 {
|
|
833 if (xswi(OS_Byte, 121, 0xf0) & v_flag)
|
|
834 return;
|
|
835 if (r1 == 0xff)
|
|
836 {
|
|
837 got_int = TRUE;
|
|
838 swi(OS_Byte, 15, 1); /* Flush input buffer */
|
|
839 }
|
|
840 }
|
|
841
|
|
842 /*
|
|
843 * Recursively expand one path component into all matching files and/or
|
|
844 * directories.
|
|
845 * "path" has backslashes before chars that are not to be expanded.
|
|
846 * Return the number of matches found.
|
|
847 */
|
|
848 int
|
|
849 mch_expandpath(gap, path, flags)
|
|
850 garray_T *gap; /* Grow array for results. */
|
|
851 char_u *path;
|
|
852 int flags; /* EW_* flags */
|
|
853 {
|
|
854 int got; /* Number of matches. */
|
|
855 char_u *pattern;
|
|
856
|
|
857 /* Plan:
|
|
858 *
|
|
859 * 1) Get first part of path - no wildcards
|
|
860 * 2) Get next path element (wildcarded)
|
|
861 * 3) Get rest of path
|
|
862 *
|
|
863 * If (3) is nothing then only the leaf is wildcarded - add to gap
|
|
864 * Otherwise call recursively for each path in (2), passing (3)
|
|
865 *
|
|
866 * This is just the header function.
|
|
867 */
|
|
868
|
|
869 /* We must be able to modifiy path, so make a copy */
|
|
870 pattern = vim_strsave(path);
|
|
871 if (pattern == NULL)
|
|
872 return 0;
|
|
873 got = expand_section(gap, (char_u *)"", pattern, flags);
|
|
874 vim_free(pattern);
|
|
875 return got;
|
|
876 }
|
|
877
|
|
878 /*
|
|
879 * expand_section(gap, "$.Dir1.Dir2", "ABBA*.myleaf##")
|
|
880 *
|
|
881 * calls expand_section(gap, "$.Dir1.Dir2.ABBA_Gold", "myleaf##")
|
|
882 * and expand_section(gap, "$.Dir1.Dir2.ABBA_Live", "myleaf##")
|
|
883 *
|
|
884 * If rest is just a leaf then all matches are added to gap.
|
|
885 *
|
|
886 * Returns number of items added to gap.
|
|
887 */
|
|
888 int
|
|
889 expand_section(gap, root, rest, flags)
|
|
890 garray_T *gap;
|
|
891 char_u *root; /* Non-wildcarded path to search */
|
|
892 char_u *rest; /* Wildcarded remainder of path */
|
|
893 int flags; /* Add dirs/files/missing objects. */
|
|
894 {
|
|
895 static char_u buf[MAXPATHL]; /* Temporary buffer. */
|
|
896 char_u dir[MAXPATHL];
|
|
897 int start_element = -1; /* Start of wildcarded element */
|
|
898 char_u c;
|
|
899 int i;
|
|
900 int got, dir_pos;
|
|
901 int buflen; /* Chars used in buf[] */
|
|
902 int colon = 0; /* Dir ends in ':' */
|
|
903
|
|
904 buflen = strlen(root);
|
|
905 STRNCPY(buf, root, buflen); /* Copy root into buffer. */
|
|
906
|
|
907 /*
|
|
908 * Find end of nonwildcarded section.
|
|
909 * Count ':' as a path sep since Vim:Bug* is a valid pathname.
|
|
910 */
|
|
911
|
|
912 for (i = 0; c = rest[i]; i++)
|
|
913 {
|
|
914 if (c == PATHSEP)
|
|
915 {
|
|
916 start_element = i;
|
|
917 colon = 0;
|
|
918 }
|
|
919 if (c == ':')
|
|
920 {
|
|
921 start_element = i + 1;
|
|
922 colon = 1;
|
|
923 }
|
|
924 if (c == '#' || c == '*')
|
|
925 break;
|
|
926 }
|
|
927 if (c == 0)
|
|
928 start_element = i;
|
|
929
|
|
930 /*
|
|
931 * start_element +> terminator for non-wildcarded section.
|
|
932 * Transfer this bit into buf.
|
|
933 */
|
|
934 if (buflen + start_element + 4 >= MAXPATHL)
|
|
935 return 0; /* Buffer full */
|
|
936 if (start_element >= 0)
|
|
937 {
|
|
938 if (*root && !colon)
|
|
939 buf[buflen++] = PATHSEP;
|
|
940 strncpy(buf + buflen, rest, start_element);
|
|
941 buflen += start_element;
|
|
942 }
|
|
943 buf[buflen] = 0;
|
|
944
|
|
945 /*
|
|
946 * Did we reach the end of the string without hitting any wildcards?
|
|
947 */
|
|
948 if (c == 0)
|
|
949 {
|
|
950 /* Yes - add combined path to grow array and return. */
|
|
951 addfile(gap, buf, flags);
|
|
952 return 1;
|
|
953 }
|
|
954
|
|
955 if (start_element < 0 || !colon)
|
|
956 start_element++;
|
|
957 rest += start_element;
|
|
958
|
|
959 /*
|
|
960 * rest does contain wildcards if we get here.
|
|
961 *
|
|
962 * Now : have we reached the leaf names part yet?
|
|
963 * If so, add all matches (files and dirs) to gap.
|
|
964 * If not, get next path element and scan all matching directories.
|
|
965 */
|
|
966
|
|
967 start_element = -1;
|
|
968 for (i = 0; rest[i]; i++)
|
|
969 {
|
|
970 if (rest[i] == '.')
|
|
971 {
|
|
972 start_element = i;
|
|
973 rest[i] = 0; /* Break string here. */
|
|
974 break;
|
|
975 }
|
|
976 }
|
|
977
|
|
978 /* If start_element is -1 then we are matching leaf names */
|
|
979
|
|
980 r3 = 0; /* Number of objs read. */
|
|
981 dir_pos = 0; /* Position through directory. */
|
|
982 got = 0; /* Files added so far. */
|
|
983 while (dir_pos != -1)
|
|
984 {
|
|
985 buf[buflen] = 0;
|
|
986 if (xswi(OS_GBPB, 9,
|
|
987 buf, /* Directory to scan. */
|
|
988 buf + buflen + (1 - colon), /* Buffer for result. */
|
|
989 1, /* Number of objects to read. */
|
|
990 dir_pos, /* Search position. */
|
|
991 MAXPATHL - 2 - buflen, /* Size of result buffer. */
|
|
992 rest) /* Wildcarded leafname. */
|
|
993 & v_flag)
|
|
994 {
|
|
995 EMSG(r0 + 4);
|
|
996 r4 = -1;
|
|
997 }
|
|
998 dir_pos = r4; /* r4 corrupted by addfile() */
|
|
999 if (r3 > 0)
|
|
1000 {
|
|
1001 char_u *path = buf;
|
|
1002 if (buflen == 0)
|
|
1003 path++; /* Don't do '.File' */
|
|
1004 else if (!colon)
|
|
1005 buf[buflen] = '.'; /* Join path and leaf */
|
|
1006
|
|
1007 /* Path -> full path of object found */
|
|
1008 if (start_element == -1)
|
|
1009 {
|
|
1010 addfile(gap, path, flags);
|
|
1011 got++;
|
|
1012 }
|
|
1013 else
|
|
1014 {
|
|
1015 /* Scan into subdirectories and images; ignore files */
|
|
1016 swi(OS_File, 17, path);
|
|
1017 if (r0 == 2 || r0 == 3)
|
|
1018 got += expand_section(gap,
|
|
1019 path,
|
|
1020 rest + start_element + 1,
|
|
1021 flags);
|
|
1022 }
|
|
1023 }
|
|
1024 }
|
|
1025
|
|
1026 /* Restore the dot if we removed it. */
|
|
1027 if (start_element >= 0)
|
|
1028 rest[start_element] = '.';
|
|
1029 return got;
|
|
1030 }
|
|
1031
|
|
1032 /*
|
|
1033 * mch_expand_wildcards() - this code does wild-card pattern matching using
|
|
1034 * the shell. It isn't used under RISC OS.
|
|
1035 *
|
|
1036 * return OK for success, FAIL for error (you may lose some memory) and put
|
|
1037 * an error message in *file.
|
|
1038 *
|
|
1039 * num_pat is number of input patterns
|
|
1040 * pat is array of pointers to input patterns
|
|
1041 * num_file is pointer to number of matched file names
|
|
1042 * file is pointer to array of pointers to matched file names
|
|
1043 */
|
|
1044 int
|
|
1045 mch_expand_wildcards(num_pat, pat, num_file, file, flags)
|
|
1046 int num_pat;
|
|
1047 char_u **pat;
|
|
1048 int *num_file;
|
|
1049 char_u ***file;
|
|
1050 int flags; /* EW_* flags */
|
|
1051 {
|
|
1052 /* This doesn't get called unless SPECIAL_WILDCHAR is defined. */
|
|
1053 return FAIL;
|
|
1054 }
|
|
1055
|
|
1056 /*
|
|
1057 * Return TRUE if "p" contains wildcards which can be expanded by
|
|
1058 * mch_expandpath().
|
|
1059 */
|
|
1060 int
|
|
1061 mch_has_exp_wildcard(p)
|
|
1062 char_u *p;
|
|
1063 {
|
|
1064 if (vim_strpbrk((char_u *)"*#", p))
|
|
1065 return TRUE;
|
|
1066 return FALSE;
|
|
1067 }
|
|
1068
|
|
1069 /* Return TRUE if "p" contains wildcards. */
|
|
1070 int
|
|
1071 mch_has_wildcard(p)
|
|
1072 char_u *p;
|
|
1073 {
|
|
1074 if (vim_strpbrk((char_u *)"*#`", p))
|
|
1075 return TRUE;
|
|
1076 return FALSE;
|
|
1077 }
|
|
1078
|
|
1079 int /* see Unix unlink(2) */
|
|
1080 mch_remove(file)
|
|
1081 char_u *file; /* Name of file to delete. */
|
|
1082 {
|
|
1083 if (xswi(OS_FSControl, 27, file, 0, 0) & v_flag)
|
|
1084 return EXIT_FAILURE;
|
|
1085 return EXIT_SUCCESS;
|
|
1086 }
|
|
1087
|
|
1088 /* Try to make existing scripts work without modification.
|
|
1089 * Return a pointer to the new string (freed by caller), or NULL
|
|
1090 *
|
|
1091 * Two main cases:
|
|
1092 * - Absolute : $VIM/syntax/help.vim
|
|
1093 * - Relative : Adfs::4.$.!Vim.Resources.Syntax/help.vim
|
|
1094 */
|
|
1095 char_u *
|
|
1096 mch_munge_fname(fname)
|
|
1097 char_u *fname;
|
|
1098 {
|
|
1099 char_u c;
|
|
1100 int len;
|
|
1101 char_u *retval;
|
|
1102
|
|
1103 retval = fname = vim_strsave(fname);
|
|
1104 if (fname == NULL)
|
|
1105 return NULL;
|
|
1106
|
|
1107 if (strncmp(fname, "$VIM/", 5) == 0)
|
|
1108 {
|
|
1109 strncpy(fname, "Vim:", 4);
|
|
1110 for (fname += 5; c = *fname; fname++)
|
|
1111 {
|
|
1112 if (c == '.')
|
|
1113 break;
|
|
1114 if (c == '/')
|
|
1115 fname[-1] = '.';
|
|
1116 else
|
|
1117 fname[-1] = c;
|
|
1118 }
|
|
1119 fname[-1] = '\0';
|
|
1120 }
|
|
1121 else
|
|
1122 {
|
|
1123 /* Check to see if the file exists without modification. */
|
|
1124 if (xswi(OS_File, 17, fname) & v_flag)
|
|
1125 r0 == 0; /* Invalid filename? */
|
|
1126 if (r0)
|
|
1127 return retval;
|
|
1128
|
|
1129 len = strlen(fname);
|
|
1130 if (strcmp(fname + len - 4, ".vim") == 0)
|
|
1131 {
|
|
1132 fname[len - 4] = '\0';
|
|
1133 for (; c = *fname; fname++)
|
|
1134 {
|
|
1135 if (c == '/')
|
|
1136 *fname = '.';
|
|
1137 }
|
|
1138 }
|
|
1139 }
|
|
1140 return retval;
|
|
1141 }
|
|
1142
|
|
1143 /* QuickFix reads munged names from the error file.
|
|
1144 * Correct them.
|
|
1145 */
|
|
1146 int
|
|
1147 ro_buflist_add(old_name)
|
|
1148 char_u *old_name; /* Name of file found by quickfix */
|
|
1149 {
|
|
1150 char_u *fname;
|
|
1151 char_u *leaf; /* Pointer to start of leaf in old_name */
|
|
1152 char_u *ptr;
|
|
1153 char_u c;
|
|
1154 int retval;
|
|
1155
|
|
1156 if (old_name == NULL)
|
|
1157 return buflist_add(NULL, 0);
|
|
1158
|
|
1159 /* Copy the name so we can mess around with it. */
|
|
1160 fname = vim_strsave(old_name);
|
|
1161 if (fname == NULL)
|
|
1162 /* Out of memory - can't modify name */
|
|
1163 return buflist_add(old_name, 0);
|
|
1164
|
|
1165 /* Change `dir/main.c' into `dir.c.main' */
|
|
1166 leaf = fname;
|
|
1167 for (ptr = fname; c = *ptr; ptr++)
|
|
1168 {
|
|
1169 if (c == '/')
|
|
1170 {
|
|
1171 leaf = ptr + 1;
|
|
1172 *ptr = '.';
|
|
1173 }
|
|
1174 else if (c == '.')
|
|
1175 break;
|
|
1176 }
|
|
1177 if (c == '.')
|
|
1178 {
|
|
1179 /* Change `main.c' into `c.main'
|
|
1180 * | |
|
|
1181 * leaf ptr
|
|
1182 */
|
|
1183 ptr += old_name - fname;
|
|
1184 *ptr = '\0';
|
|
1185 sprintf(leaf,
|
|
1186 "%s.%s",
|
|
1187 ptr + 1,
|
|
1188 leaf - fname + old_name);
|
|
1189 }
|
|
1190
|
|
1191 retval = buflist_add(fname, 0);
|
|
1192 free(fname);
|
|
1193 return retval;
|
|
1194 }
|
|
1195
|
|
1196 /* Change the current directory.
|
|
1197 * Strip trailing dots to make it easier to use with filename completion.
|
|
1198 * Return 0 for success, -1 for failure.
|
|
1199 */
|
|
1200 int
|
|
1201 mch_chdir(dir)
|
|
1202 char_u *dir;
|
|
1203 {
|
|
1204 int length;
|
|
1205 int retval;
|
|
1206 char_u *new_dir;
|
|
1207
|
|
1208 length = strlen(dir);
|
|
1209 if (dir[length - 1] != '.')
|
|
1210 return chdir(dir); /* No trailing dots - nothing to do. */
|
|
1211 new_dir = vim_strsave(dir);
|
|
1212 if (new_dir == NULL)
|
|
1213 return chdir(dir); /* Can't allocate memory. */
|
|
1214
|
|
1215 while (new_dir[--length] == '.')
|
|
1216 new_dir[length] = '\0';
|
|
1217
|
|
1218 retval = chdir(new_dir);
|
|
1219 vim_free(new_dir);
|
|
1220 return retval;
|
|
1221 }
|
|
1222
|
|
1223 /* Examine the named file, and set the 'osfiletype' option
|
|
1224 * (in curbuf) to the file's type.
|
|
1225 */
|
|
1226 void
|
|
1227 mch_read_filetype(file)
|
|
1228 char_u *file;
|
|
1229 {
|
|
1230 int type;
|
|
1231 char_u type_string[9];
|
|
1232 int i;
|
|
1233
|
|
1234 if (xswi(OS_File, 23, file) & v_flag)
|
|
1235 type = 0xfff; /* Default to Text */
|
|
1236 else
|
|
1237 type = r6;
|
|
1238
|
|
1239 /* Type is the numerical value - see if we have a textual equivalent */
|
|
1240 swi(OS_FSControl, 18, 0, type);
|
|
1241 ((int *) type_string)[0] = r2;
|
|
1242 ((int *) type_string)[1] = r3;
|
|
1243 type_string[8] = 0;
|
|
1244 for (i = 0; type_string[i] > ' '; i++)
|
|
1245 ;
|
|
1246 type_string[i] = 0;
|
|
1247
|
|
1248 set_string_option_direct("osfiletype", -1, type_string, OPT_FREE);
|
|
1249 return;
|
|
1250 }
|
|
1251
|
|
1252 void
|
|
1253 mch_set_filetype(file, type)
|
|
1254 char_u *file;
|
|
1255 char_u *type;
|
|
1256 {
|
|
1257 if (xswi(OS_FSControl, 31, type) & v_flag)
|
|
1258 {
|
|
1259 EMSG(_("E366: Invalid 'osfiletype' option - using Text"));
|
|
1260 r2 = 0xfff;
|
|
1261 }
|
|
1262
|
|
1263 swi(OS_File, 18, file, r2);
|
|
1264 }
|
|
1265
|
|
1266 /* Return TRUE if the file's type matches 'type'
|
|
1267 * RISC OS types always start with '&'
|
|
1268 */
|
|
1269 int
|
|
1270 mch_check_filetype(fname, type)
|
|
1271 char_u *fname;
|
|
1272 char_u *type;
|
|
1273 {
|
|
1274 int value;
|
|
1275 char *end;
|
|
1276
|
|
1277 if (*type != '&')
|
|
1278 return FALSE;
|
|
1279
|
|
1280 value = strtol(type + 1, &end, 16);
|
|
1281 if (*end)
|
|
1282 return FALSE; /* Invalid type (report error?) */
|
|
1283
|
|
1284 if (xswi(OS_File, 23, fname) & v_flag)
|
|
1285 return FALSE; /* Invalid filename? */
|
|
1286
|
|
1287 return (r0 && r6 == value);
|
|
1288 }
|