blob: cc52d85a69332f195d0d2570c494fcc395951935 [file] [log] [blame]
Bram Moolenaar071d4272004-06-13 20:20:40 +00001/* 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
18const char *__dynamic_da_name = "Vim heap"; /* Enable and name our dynamic area */
19int ro_line_mode = TRUE; /* For Ex mode we much echo chars to the screen ourselves */
20int windowed; /* Flag - are we running inside a text window? */
21int WinLeft, WinTop; /* We might be started inside a text window */
22int ScrollTop; /* Make cursor movements relative to ScrollTop. */
23
24int old_escape_state = -1;
25int 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
35map_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
61text_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
68text_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
78mch_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
220mch_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
325mch_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
342mch_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
351mch_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
380mch_suspend()
381{
382 suspend_shell();
383}
384
385 void
386mch_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
426mch_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
437mch_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
448mch_can_restore_title()
449{
450 return FALSE;
451}
452
453 int
454mch_can_restore_icon()
455{
456 return FALSE;
457}
458
459
460/*
461 * Set the window title and icon.
462 */
463 void
464mch_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
493mch_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
505mch_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
519mch_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) */
Bram Moolenaarb6356332005-07-18 21:40:44 +0000526 vim_strncpy(s, "(unknown)", len - 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000527 }
528}
529
530/*
531 * return process ID
532 */
533 long
534mch_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
546mch_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
561mch_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
577mch_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
590mch_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
606mch_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
618mch_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
630mch_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
646mch_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);
Bram Moolenaarc0197e22004-09-13 20:26:32 +0000657 p = get_cmd_output(buf, NULL, SHELL_SILENT);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000658 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
675mch_nodetype(name)
676 char_u *name;
677{
678 /* TODO */
679 return NODE_NORMAL;
680}
681
682 void
683mch_early_init()
684{
685 /* Turn off all the horrible filename munging in UnixLib. */
Bram Moolenaar741b07e2004-12-09 21:09:42 +0000686 int __riscosify_control = __RISCOSIFY_NO_PROCESS;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000687}
688
689 void
690mch_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
711mch_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
745mch_setmouse(on)
746 int on;
747{
748}
749
750/*
751 * set screen mode, always fails.
752 */
753/* ARGSUSED */
754 int
755mch_screenmode(arg)
756 char_u *arg;
757{
Bram Moolenaar741b07e2004-12-09 21:09:42 +0000758 EMSG(_(e_screenmode));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000759 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
769mch_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
780mch_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
789mch_new_shellsize()
790{
791 /* Nothing to do. */
792}
793
794 int
795mch_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
831mch_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
849mch_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
889expand_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
1045mch_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
1061mch_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
1071mch_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) */
1080mch_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 *
1096mch_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
1147ro_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
1201mch_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
1227mch_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
Bram Moolenaar5e3cb7e2006-02-27 23:58:35 +00001248 set_string_option_direct("osfiletype", -1, type_string, OPT_FREE, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001249 return;
1250}
1251
1252 void
1253mch_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
1270mch_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}