1 /* -*- mode: C; mode: fold; -*- */
2 /* Copyright (c) 1992, 1998 John E. Davis
3 * This file is part of JED editor library source.
4 *
5 * You may distribute this file under the terms the GNU General Public
6 * License. See the file COPYING for more information.
7 */
8 #include "config.h"
9 #include "jed-feat.h"
10
11 /*{{{ Include Files */
12
13 #ifdef MSWINDOWS
14 # ifndef __WIN32__
15 # include <toolhelp.h>
16 # else
17 # include <windows.h>
18 # endif
19 #endif
20
21 #include <stdio.h>
22
23 #ifdef HAVE_SYS_WAIT_H
24 # include <sys/types.h>
25 # include <sys/wait.h>
26 #endif
27
28 #ifndef WEXITSTATUS
29 # define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
30 #endif
31 #ifndef WIFEXITED
32 # define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
33 #endif
34
35 #include <slang.h>
36 #include "jdmacros.h"
37
38 #include <string.h>
39
40 #ifdef IBMPC_SYSTEM
41 # include <fcntl.h>
42 #endif
43
44 #include <stdarg.h>
45
46 #include "buffer.h"
47 #include "keymap.h"
48 #include "file.h"
49 #include "ins.h"
50 #include "ledit.h"
51 #include "screen.h"
52 #include "window.h"
53 #include "display.h"
54 #include "search.h"
55 #include "misc.h"
56 #include "replace.h"
57 #include "paste.h"
58 #include "sysdep.h"
59 #include "cmds.h"
60 #include "text.h"
61 #include "hooks.h"
62 #include "undo.h"
63 #include "menu.h"
64 #include "kanji.h"
65 #if JED_HAS_CANNA_SUPPORT
66 #include "canna.h"
67 #endif
68
69 #ifdef __WIN32__
70 # include "win32.h"
71 #endif
72
73 #define JED_PROMPT "S-Lang>"
74
75 #if JED_HAS_SUBPROCESSES
76 # include "jprocess.h"
77 #endif
78
79
80 /*}}}*/
81
82 Buffer *MiniBuffer;
83 Buffer *The_MiniBuffer; /* this never gets deleted since we may need it */
84 Window_Type *The_MiniWindow;
85
86 static Buffer *Last_Buffer;
87
88 extern char *get_cwd(void);
89 int Ignore_Beep = 0;
90 int MiniBuffer_Active = 0;
91
92 char *Jed_Library;
93
94 int (*complete_open)(char *);
95 int (*complete_next)(char *);
96 static int Buf_List_Len;
97 Buffer *Buf_Context;
98
99 static char *Expect_File_Error = "Expecting filename.";
100 static char *Keymap_Error = "Unknown_Keymap";
101
102
next_bufflist(char * buf)103 static int next_bufflist(char *buf) /*{{{*/
104 {
105 Buffer *tthis;
106 while (1)
107 {
108 tthis = Buf_Context;
109 if (tthis == MiniBuffer) return(0);
110 Buf_Context = Buf_Context->next;
111
112 if ((Buf_List_Len == 0)
113 #if JED_FILE_PRESERVE_CASE
114 || (0 == strncmp(buf, tthis->name, Buf_List_Len))
115 #else
116 || (0 == jed_case_strncmp (buf, tthis->name, Buf_List_Len))
117 #endif
118 )
119 {
120 if (*tthis->name == ' ') continue; /* internal buffers */
121 strcpy (buf, tthis->name);
122 return 1;
123 }
124 }
125 }
126
127 /*}}}*/
128
open_bufflist(char * buf)129 static int open_bufflist(char *buf) /*{{{*/
130 {
131 if ((Buf_Context = MiniBuffer) == NULL) return(0);
132 Buf_Context = Buf_Context->next;
133 Buf_List_Len = strlen(buf);
134 return next_bufflist(buf);
135 }
136
137 /*}}}*/
138
what_buffer()139 char *what_buffer() /*{{{*/
140 {
141 return (CBuf->name);
142 }
143
144 /*}}}*/
145
bufferp(char * name)146 int bufferp(char *name) /*{{{*/
147 {
148 if (NULL == find_buffer(name)) return(0); else return(1);
149 }
150
151 /*}}}*/
152
insert_buffer_name(char * name)153 int insert_buffer_name(char *name) /*{{{*/
154 {
155 Buffer *buf;
156
157 if (NULL != (buf = find_buffer(name)))
158 {
159 insert_buffer(buf);
160 return(1);
161 }
162 else msg_error("Unable to find buffer.");
163 return(0);
164 }
165
166 /*}}}*/
167
replace_cmd(char * old,char * neew)168 int replace_cmd(char *old, char *neew) /*{{{*/
169 {
170 int n = 0;
171
172 CHECK_READ_ONLY
173 push_spot ();
174 if (search(old, 1, 0)) while(replace_next(old, neew)) n++;
175 pop_spot();
176 return n;
177 }
178
179 /*}}}*/
180
find_scratch_buffer(void)181 static Buffer *find_scratch_buffer (void) /*{{{*/
182 {
183 char *sname = "*scratch*";
184 Buffer *scratch;
185
186 scratch = find_buffer (sname);
187 if (NULL == scratch)
188 scratch = make_buffer (sname, CBuf->dir, NULL);
189 return scratch;
190 }
191
192 /*}}}*/
193
194
195 /* Try to find any other buffer but kill_buf such that the buffer is not
196 * visible, not scratch and not buried.
197 */
find_non_visible_buffer(Buffer * kill_buf)198 static Buffer *find_non_visible_buffer (Buffer *kill_buf) /*{{{*/
199 {
200 Buffer *buf, *scratch;
201
202 buf = kill_buf->next;
203 scratch = find_scratch_buffer ();
204
205 while ((buf != kill_buf) &&
206 ((*buf->name == ' ') || (buf->flags & BURIED_BUFFER)
207 || (buf == scratch) || (buffer_visible(buf))))
208 {
209 buf = buf->next;
210 }
211 if (buf == kill_buf) buf = scratch;
212 return buf;
213 }
214
215 /*}}}*/
216
217
218
kill_buffer_cmd(char * name)219 int kill_buffer_cmd(char *name) /*{{{*/
220 {
221 Buffer *this_buf, *kill_buf, *scratch, *buf;
222 Window_Type *w;
223 int kill;
224
225 if (NULL == (kill_buf = find_buffer(name)))
226 {
227 msg_error("Buffer does not exist.");
228 return(0);
229 }
230
231 /* Do not allow the minibuffer to be deleted. Otherwise, the whole
232 * minibuffer creation/selection needs to be cleaned up.
233 */
234 if (kill_buf == The_MiniBuffer)
235 return 0;
236
237 this_buf = CBuf;
238 switch_to_buffer(kill_buf);
239
240 #if JED_HAS_SUBPROCESSES
241 if (kill_buf->locked)
242 {
243 erase_buffer ();
244 switch_to_buffer (this_buf);
245 return 0;
246 }
247 #endif
248
249 kill = 1;
250 if ((*name != ' ') && (kill_buf->flags & BUFFER_MODIFIED))
251 {
252 jed_vmessage (1, "Buffer %s modified. (K)ill, (S)ave first, (A)bort:",
253 name);
254
255 /* This does not go through keyboard macro routines
256 * on purpose!
257 */
258 switch (my_getkey())
259 {
260 case 'k': case 'K': kill = 1; break;
261 case 's': case 'S': kill = 2; break;
262 default: msg_error("Aborted."); return(0);
263 }
264 clear_message ();
265 }
266
267 if (kill == 2)
268 {
269 write_buffer();
270 if (SLang_Error)
271 {
272 switch_to_buffer(this_buf);
273 return(0);
274 }
275 }
276
277 /* if it is the scratch buffer, just erase it since we are going to
278 recreate it anyway. */
279
280 scratch = find_scratch_buffer ();
281
282 if (kill_buf == scratch)
283 {
284 erase_buffer();
285 #if JED_HAS_SUBPROCESSES
286 if (kill_buf->subprocess) jed_kill_process (kill_buf->subprocess - 1);
287 #endif
288 switch_to_buffer(this_buf);
289 return 1;
290 }
291
292 buf = find_non_visible_buffer (kill_buf);
293
294 /* search through windows looking for the buffer and replace it */
295 w = JWindow;
296 do
297 {
298 if (kill_buf == JWindow->buffer)
299 {
300 touch_window_hard (JWindow, 0);
301 window_buffer(buf);
302 buf = find_non_visible_buffer (kill_buf);
303 }
304 JWindow = JWindow->next;
305 }
306 while (w != JWindow);
307
308 if (kill_buf == Last_Buffer) Last_Buffer = NULL;
309 if (kill_buf == this_buf) this_buf = buf;
310 switch_to_buffer(this_buf);
311 delete_buffer(kill_buf);
312 return 1;
313 }
314
315 /*}}}*/
316
write_buffer_cmd(char * filestr)317 int write_buffer_cmd(char *filestr) /*{{{*/
318 {
319 #ifdef VMS
320 char *ff;
321 #endif
322 char dir[JED_MAX_PATH_LEN], *f, file[JED_MAX_PATH_LEN];
323 int n;
324
325 #ifdef REAL_UNIX_SYSTEM
326 f = expand_link(filestr);
327 #else
328 f = expand_filename(filestr);
329 #endif
330
331 strncpy (file, f, JED_MAX_PATH_LEN); file[JED_MAX_PATH_LEN - 1] = 0;
332 f = extract_file(file);
333
334 if ((*f == 0) && (*CBuf->file == 0))
335 {
336 msg_error("Filename Required.");
337 return(0);
338 }
339
340 n = (int) (f - file);
341 SLMEMCPY((char *) dir, (char *) file, n);
342 dir[n] = 0;
343
344 if (*f == 0)
345 {
346 safe_strcpy (file, CBuf->file, sizeof (file));
347 f = file;
348 }
349
350 if (file_changed_on_disk (CBuf, dir_file_merge (dir, f)))
351 {
352 if (0 == jed_get_yes_no("File changed on disk. Save anyway?"))
353 return 0;
354 }
355
356 n = write_file_with_backup (dir, f);
357 if (n >= 0)
358 {
359 #ifdef VMS
360 ff = f; while (*ff) if (*ff == ';') *ff = 0; else ff++;
361 #endif
362 if (Batch != 2)
363 {
364 jed_vmessage (0, "Wrote %d lines to %s%s", n, dir, f);
365 }
366 CBuf->flags &= ~BUFFER_MODIFIED;
367 CBuf->flags |= AUTO_SAVE_BUFFER;
368 CBuf->hits = 0;
369 #ifdef UNDO_HAS_REDO
370 update_undo_unchanged ();
371 #endif
372 visit_file(dir, f);
373 return(1);
374 }
375 else
376 {
377 jed_verror ("Error writing file %s%s", dir, f);
378 return 0;
379 }
380 }
381
382 /*}}}*/
383
384 #if defined(__BORLANDC__) && !defined(MSWINDOWS)
show_memory()385 int show_memory() /*{{{*/
386 {
387 struct farheapinfo hi;
388 char *c;
389 unsigned long total = 0, core, used = 0;
390 unsigned long max = 0;
391 int i = 0;
392
393 hi.ptr = NULL;
394 if (farheapcheck() == _HEAPCORRUPT) c = "corrupt"; else c = "ok";
395 while (farheapwalk(&hi) == _HEAPOK)
396 {
397 if (hi.in_use)
398 used += hi.size;
399 else
400 {
401 total += hi.size;
402 if (hi.size > max) max = hi.size;
403 i++;
404 }
405 }
406 core = farcoreleft();
407 jed_vmessage (0, "used:%lu, core:%lu, free:%lu, grand:%lu, max:%lu, frag:%d (%s)",
408 used, core, total, core + total, max, i, c);
409 return 0;
410 }
411
412 /*}}}*/
413
414 #endif
415
416 #ifdef MSWINDOWS
show_memory(void)417 int show_memory (void) /*{{{*/
418 {
419 #ifndef __WIN32__
420 MEMMANINFO mmi;
421 if (MemManInfo(&mmi))
422 {
423 jed_vmessage (0, "tot pages: %lu, free pages: %lu",
424 mmi.dwTotalLinearSpace, mmi.dwFreeLinearSpace);
425 }
426 #else
427 MEMORYSTATUS mst;
428 GlobalMemoryStatus(&mst);
429 jed_vmessage (0, "avail space: %lu, tot phys space: %lu, avail phys space: %lu",
430 mst.dwAvailPhys + mst.dwAvailPageFile, mst.dwTotalPhys, mst.dwAvailPhys);
431 #endif
432
433 return 0;
434 }
435
436 /*}}}*/
437
438 #endif
439
440 #ifdef __WATCOMC__
441 #include <malloc.h>
show_memory()442 int show_memory() /*{{{*/
443 {
444 jed_vmessage (0, "avail mem: %lu, tot phys pgs: ???, free lin space: %lu",
445 _memavl (), _memmax ());
446 return 0;
447 }
448
449 /*}}}*/
450
451 #endif
452
453 #ifdef __GO32__
454 #include <dpmi.h>
455
show_memory()456 int show_memory() /*{{{*/
457 {
458 unsigned long mem;
459 _go32_dpmi_meminfo info;
460
461 _go32_dpmi_get_free_memory_information(&info);
462
463 if ((long)info.available_physical_pages != -1L)
464 mem = info.available_physical_pages * 4096UL;
465 else mem = info.available_memory;
466
467 jed_vmessage (0, "avail mem: %lu, tot phys pgs: %lu, free lin space: %lu",
468 mem, info.total_physical_pages, info.free_linear_space);
469 return 0;
470 }
471
472 /*}}}*/
473
474 #endif
475
set_buffer(char * name)476 int set_buffer(char *name) /*{{{*/
477 {
478 Buffer *buf;
479
480 if ((name == NULL) || (*name == 0))
481 {
482 msg_error("set_buffer: Buffer name is NULL");
483 return (0);
484 }
485
486 /* Last_Buffer = CBuf; */
487
488 if (NULL == (buf = find_buffer(name)))
489 buf = make_buffer (name, CBuf->dir, NULL);
490 switch_to_buffer(buf);
491
492 return 1;
493 }
494
495 /*}}}*/
496
jed_get_mini_response(char * s)497 int jed_get_mini_response (char *s)
498 {
499 int ch;
500 MiniBuf_Get_Response_String = s;
501 update (NULL, 0, 0);
502 ch = jed_getkey ();
503 MiniBuf_Get_Response_String = NULL;
504 return ch;
505 }
506
strcat_malloc(char * a,char * b)507 static char *strcat_malloc (char *a, char *b)
508 {
509 unsigned int len;
510 char *c;
511
512 len = strlen (a);
513
514 if (NULL == (c = SLmalloc (len + strlen (b) + 1)))
515 return NULL;
516
517 strcpy (c, a);
518 strcpy (c + len, b);
519 return c;
520 }
521
522
jed_get_y_n(char * question)523 int jed_get_y_n (char *question)
524 {
525 int ans;
526 char *yn_quest;
527
528 if (NULL == (yn_quest = strcat_malloc (question, "? (y/n)")))
529 return -1;
530
531 ans = jed_get_mini_response (yn_quest);
532 SLfree (yn_quest);
533
534 if ((ans == 'y') || (ans == 'Y'))
535 return 1;
536 if ((ans == 'n') || (ans == 'N'))
537 return 0;
538 if (SLKeyBoard_Quit)
539 return -1;
540 jed_beep ();
541 return jed_get_yes_no (question);
542 }
543
544
jed_vget_y_n(char * fmt,char * arg)545 int jed_vget_y_n (char *fmt, char *arg)
546 {
547 char msg [1024];
548
549 if (arg == NULL)
550 {
551 arg = fmt;
552 fmt = "%s";
553 }
554 /* FIXME: Priority=low: This is a hack to prevent a possible overflow */
555 if (strlen (arg) + strlen (fmt) >= sizeof (msg))
556 arg = "";
557
558 sprintf (msg, fmt, arg);
559
560 return jed_get_y_n (msg);
561 }
562
563
jed_get_yes_no(char * question)564 int jed_get_yes_no (char *question) /*{{{*/
565 {
566 char *yn_quest;
567 char *tmp;
568 int n;
569
570 if (NULL == (yn_quest = strcat_malloc (question, "? (yes or no)")))
571 return -1;
572
573 while (1)
574 {
575 if (NULL == (tmp = read_from_minibuffer(yn_quest, 0, NULL, &n)))
576 {
577 SLfree (yn_quest);
578 return -1;
579 }
580
581 if (!strcmp(tmp, "yes"))
582 {
583 SLfree(tmp);
584 SLfree (yn_quest);
585 return 1;
586 }
587
588 if (!strcmp(tmp, "no"))
589 {
590 SLfree(tmp);
591 SLfree (yn_quest);
592 return 0;
593 }
594 msg_error("Answer `yes' or `no'.");
595 SLfree(tmp);
596 }
597 }
598
599 /*}}}*/
600
find_file_cmd(char * filestr)601 int find_file_cmd (char *filestr) /* filestr is const ! */ /*{{{*/
602 {
603 char *f, *file, filebuf[JED_MAX_PATH_LEN];
604 Buffer *buf;
605 int n;
606
607 #ifdef REAL_UNIX_SYSTEM
608 file = expand_link(filestr);
609 #else
610 file = expand_filename(filestr);
611 #endif
612
613 safe_strcpy(filebuf, file, sizeof (filebuf));
614 file = filebuf;
615 f = extract_file(file);
616 if ((*file == 0) || (*f == 0))
617 {
618 msg_error(Expect_File_Error);
619 return(0);
620 }
621
622 check_buffers ();
623
624 /* search for the file in current buffer list */
625
626 if (NULL != (buf = find_file_buffer(file)))
627 {
628 if (file_changed_on_disk (buf, file))
629 {
630 if (jed_get_yes_no("File changed on disk. Read From Disk"))
631 {
632 if (*Error_Buffer) return(1);
633 n = (int) buf->linenum;
634 buf->flags &= ~BUFFER_MODIFIED;
635 kill_buffer_cmd(buf->name);
636 find_file_cmd(file);
637 goto_line(&n);
638 return(1);
639 }
640 }
641
642 switch_to_buffer (buf);
643 return(1);
644 }
645
646 buf = make_buffer (NULL, file, NULL);
647 switch_to_buffer(buf);
648
649 n = read_file(file);
650 CLine = CBuf->beg;
651 Point = 0;
652 LineNum = 1;
653 if (CLine == NULL) make_line(25);
654 set_file_modes();
655 CBuf->flags |= UNDO_ENABLED;
656
657 switch(n)
658 {
659 case -2: msg_error("File not readable."); break;
660 default:
661 if (Batch == 2) break;
662 if (*Message_Buffer) break; /* autosave warning? */
663 if (n == -1) message("New file.");
664 else
665 {
666 jed_vmessage (0, "%d lines read", n);
667 }
668 }
669
670 SLang_run_hooks("find_file_hook", 1, file);
671 return(1);
672 }
673
674 /*}}}*/
675
find_file_in_window(char * file)676 int find_file_in_window(char *file) /*{{{*/
677 {
678 int ret;
679 Buffer *b = CBuf;
680
681 ret = find_file_cmd (file);
682 if ((b != CBuf) && (*CBuf->name != ' ')) Last_Buffer = CBuf;
683 window_buffer(CBuf);
684 return(ret);
685 }
686
687 /*}}}*/
688
689
690 /* create a minibuffer with window and switch to it. */
create_minibuffer(void)691 static void create_minibuffer(void) /*{{{*/
692 {
693 Window_Type *w;
694 MiniBuffer = The_MiniBuffer;
695
696 /* I want to make Mini_Window->next = Current Window so that scroll other
697 window routines will scroll it. */
698
699 w = JWindow;
700 do other_window(); while (JWindow->next != w);
701 JWindow->next = The_MiniWindow;
702 The_MiniWindow->next = w;
703 The_MiniWindow->column = 1;
704 Mini_Info.action_window = w;
705 other_window(); /* now in minibuffer window */
706 window_buffer(MiniBuffer);
707 switch_to_buffer(MiniBuffer);
708 MiniBuffer_Active = 1;
709 erase_buffer ();
710 /* allow kill region to kill to beginning of minibuffer.
711 * Suggested by stefen@uni-paderborn.de */
712 push_mark ();
713 }
714
715 /*}}}*/
716
717 char *Completion_Buffer = "*Completions*";
718
719 static char *Last_Completion_Buffer;
720 static int Last_Completion_Windows;
721
722 /* evaluate command in minibuffer and leave */
exit_minibuffer()723 int exit_minibuffer() /*{{{*/
724 {
725 if (IS_MINIBUFFER)
726 {
727 if (Last_Completion_Buffer != NULL)
728 {
729 pop_to_buffer (Completion_Buffer);
730 CBuf->flags &= ~BUFFER_MODIFIED;
731 switch_to_buffer_cmd (Last_Completion_Buffer);
732 kill_buffer_cmd (Completion_Buffer);
733 touch_window_hard (JWindow, 0);
734 if (Last_Completion_Windows == 1) one_window ();
735 }
736 select_minibuffer ();
737 Exit_From_MiniBuffer = 1;
738 }
739 Last_Completion_Buffer = NULL;
740 return(0);
741 }
742
743 /*}}}*/
744
745 /* return 1 if minibuffer already exists otherwise returns 0 */
select_minibuffer()746 int select_minibuffer() /*{{{*/
747 {
748 Window_Type *w;
749
750 /* Try to find active minibuffer and go there */
751 w = JWindow;
752 while (MiniBuffer != NULL)
753 {
754 if (JWindow->top == Jed_Num_Screen_Rows) return(1);
755 other_window();
756 if (w == JWindow) exit_error("Internal Error: no window!", 1);
757 }
758
759 /* switchs to minibuffer too */
760 create_minibuffer();
761 return(0);
762 }
763
764 /*}}}*/
765
766 /* if cmd != NULL, insert it into minibuffer and then send the result to
767 the appropriate routine. */
768
ledit(void)769 static int ledit(void) /*{{{*/
770 {
771 int n;
772 char *tmp;
773
774 if (MiniBuffer == NULL) complete_open = NULL;
775 if (NULL == (tmp = read_from_minibuffer(JED_PROMPT, 0, NULL, &n))) return(0);
776 SLang_Error = 0;
777 Suspend_Screen_Update = 1;
778
779 SLang_load_string(tmp);
780 SLfree(tmp);
781
782 if ((SLang_Error == -1) && SLKeyBoard_Quit)
783 {
784 msg_error("Quit!");
785 }
786 SLang_Error = 0;
787
788 return(1);
789 }
790
791 /*}}}*/
792
read_file_from_minibuffer(char * prompt,char * def)793 static char *read_file_from_minibuffer(char *prompt, char *def) /*{{{*/
794 {
795 int n;
796 char buf[JED_MAX_PATH_LEN];
797
798 complete_open = sys_findfirst;
799 complete_next = sys_findnext;
800
801 if (*CBuf->dir == 0)
802 buffer_filename (CBuf, NULL, CBuf->file);
803
804 strcpy (buf, CBuf->dir);
805 return read_from_minibuffer (prompt, def, buf, &n);
806 }
807
808 /*}}}*/
809
810 static char *String_Completion_Str;
811 static char *String_Completion_Str_Next;
812 static int String_Completion_Str_Len;
813
814
next_string_list(char * buf)815 static int next_string_list (char *buf) /*{{{*/
816 {
817 register char *s = String_Completion_Str_Next;
818 int len;
819 while (*s)
820 {
821 while (*s && (*s != ',')) s++;
822 len = (int) (s - String_Completion_Str_Next);
823
824 if (*s == ',') s++;
825
826 if (!len
827 || strncmp (buf, String_Completion_Str_Next, String_Completion_Str_Len))
828 {
829 String_Completion_Str_Next = s;
830 continue;
831 }
832 if (len >= JED_MAX_PATH_LEN) len = JED_MAX_PATH_LEN - 1;
833 strncpy (buf, String_Completion_Str_Next, len);
834 buf[len] = 0;
835 String_Completion_Str_Next = s;
836 return 1;
837 }
838 String_Completion_Str_Next = s;
839 return 0;
840 }
841
842 /*}}}*/
843
open_string_list(char * buf)844 static int open_string_list (char *buf) /*{{{*/
845 {
846 String_Completion_Str_Next = String_Completion_Str;
847 String_Completion_Str_Len = strlen (buf);
848 return next_string_list (buf);
849 }
850
851 /*}}}*/
852
853
read_object_with_completion(char * prompt,char * dflt,char * stuff,int * typep)854 void read_object_with_completion(char *prompt, char *dflt, char *stuff, int *typep) /*{{{*/
855 {
856 int type = *typep, n;
857 char buf[JED_MAX_PATH_LEN], *tmp;
858 char *str = NULL;
859
860 *buf = 0;
861 if (type == 'f') /* file */
862 {
863 complete_open = sys_findfirst;
864 complete_next = sys_findnext;
865 if (*CBuf->dir == 0)
866 buffer_filename (CBuf, NULL, CBuf->file);
867 strcpy (buf, CBuf->dir);
868 }
869 else if (type == 'b') /* buffer */
870 {
871 complete_open = open_bufflist;
872 complete_next = next_bufflist;
873 }
874 else if (type == 'F') /* function */
875 {
876 complete_open = open_function_list;
877 complete_next = next_function_list;
878 }
879 else if (type == 's')
880 {
881 complete_open = open_string_list;
882 complete_next = next_string_list;
883 if (SLpop_string (&str)) return;
884 String_Completion_Str = str;
885 }
886 else
887 {
888 complete_open = NULL;
889 }
890
891 strcat (buf, stuff);
892
893 if (NULL != (tmp = read_from_minibuffer(prompt, dflt, buf, &n)))
894 {
895 if (type == 'f') SLang_push_string(expand_filename(tmp));
896 else SLang_push_string(tmp);
897
898 SLfree(tmp);
899 if (str != NULL) SLfree (str);
900 }
901 }
902
903 /*}}}*/
904
insert_file_cmd()905 int insert_file_cmd() /*{{{*/
906 {
907 char *filebuf, *f, *file;
908
909 CHECK_READ_ONLY
910
911 if (NULL == (filebuf = read_file_from_minibuffer("Insert file:", NULL))) return(0);
912 file = expand_filename(filebuf);
913 SLfree (filebuf);
914 f = extract_file(file);
915 if ((*file == 0) || (*f == 0))
916 {
917 msg_error(Expect_File_Error);
918 return(1);
919 }
920
921 if (insert_file(file) < 0) msg_error("Error inserting file.");
922 return(1);
923 }
924
925 /*}}}*/
926
find_file(void)927 int find_file (void) /*{{{*/
928 {
929 char *tmp, *f;
930 char file [JED_MAX_PATH_LEN];
931
932 if (NULL == (tmp = read_file_from_minibuffer("Find file:", (char *) NULL)))
933 return 0;
934
935 safe_strcpy (file, tmp, sizeof (file));
936 SLfree(tmp);
937
938 f = extract_file (file);
939 if (*f == 0)
940 {
941 /* Use buffer filename as default. */
942 safe_strcpy (f, CBuf->file,
943 sizeof(file) - (unsigned int) (f - file));
944 }
945 find_file_in_window (file);
946
947 return 0;
948 }
949
950 /*}}}*/
951
write_buffer(void)952 int write_buffer (void) /*{{{*/
953 {
954 char *tmp;
955
956 if (NULL == (tmp = read_file_from_minibuffer("Write to file:", (char *) NULL))) return(0);
957 write_buffer_cmd(tmp);
958 SLfree(tmp);
959 return(1);
960 }
961
962 /*}}}*/
963
switch_to_buffer_cmd(char * name)964 void switch_to_buffer_cmd (char *name) /*{{{*/
965 {
966 Buffer *tthis = CBuf;
967
968 set_buffer(name);
969 window_buffer(CBuf);
970 if ((CBuf != tthis) && (*CBuf->name != ' ')) Last_Buffer = tthis;
971 }
972
973 /*}}}*/
974
get_last_buffer(void)975 static void get_last_buffer(void) /*{{{*/
976 {
977 if ((Last_Buffer == CBuf) || (Last_Buffer == NULL)
978 || (*Last_Buffer->name == ' ')
979 || (Last_Buffer->flags & BURIED_BUFFER))
980 {
981 Last_Buffer = find_non_visible_buffer (CBuf);
982 }
983 }
984
985 /*}}}*/
986
get_buffer()987 int get_buffer() /*{{{*/
988 {
989 char *tmp;
990 int n;
991 complete_open = open_bufflist;
992 complete_next = next_bufflist;
993
994 get_last_buffer ();
995
996 if (NULL == (tmp = read_from_minibuffer("Switch to buffer:", Last_Buffer->name, NULL, &n))) return(0);
997 switch_to_buffer_cmd(tmp);
998 SLfree(tmp);
999 return(1);
1000 }
1001
1002 /*}}}*/
1003
kill_buffer(void)1004 int kill_buffer (void) /*{{{*/
1005 {
1006 char *tmp;
1007 int n;
1008
1009 complete_open = open_bufflist;
1010 complete_next = next_bufflist;
1011 tmp = read_from_minibuffer("Kill buffer:", (char *) CBuf->name, NULL, &n);
1012 if (tmp != NULL)
1013 {
1014 #if JED_HAS_SUBPROCESSES
1015 Buffer *b = find_buffer(tmp);
1016 if ((b != NULL) && (b->subprocess))
1017 {
1018 if (0 == jed_get_yes_no("Buffer has a subprocess attached. Delete anyway"))
1019 return 0;
1020 }
1021 #endif
1022 kill_buffer_cmd(tmp);
1023 SLfree(tmp);
1024 return(1);
1025 }
1026 return 0;
1027 }
1028
1029 /*}}}*/
1030
evaluate_cmd()1031 int evaluate_cmd() /*{{{*/
1032 {
1033 return(!ledit());
1034 }
1035
1036 /*}}}*/
1037
insert_string(char * s)1038 void insert_string(char *s) /*{{{*/
1039 {
1040 CHECK_READ_ONLY_VOID
1041 ins_chars((unsigned char *) s, strlen(s));
1042 }
1043
1044 /*}}}*/
1045
1046 /* This is weird, Ultrix cc will not compile if set_key comes before unset_key */
unset_key(char * key)1047 void unset_key(char *key) /*{{{*/
1048 {
1049 if (*key)
1050 SLang_undefine_key(key, Global_Map);
1051 }
1052
1053 /*}}}*/
1054
set_key(char * function,char * key)1055 void set_key(char *function, char *key) /*{{{*/
1056 {
1057 if (*key)
1058 SLang_define_key(key, function, Global_Map);
1059 }
1060
1061 /*}}}*/
1062
unset_key_in_keymap(char * key,char * map)1063 void unset_key_in_keymap(char *key, char *map) /*{{{*/
1064 {
1065 SLKeyMap_List_Type *kmap;
1066
1067 if (NULL == (kmap = SLang_find_keymap(map)))
1068 {
1069 msg_error(Keymap_Error);
1070 return;
1071 }
1072
1073 if (*key) SLang_undefine_key(key, kmap);
1074 }
1075
1076 /*}}}*/
1077
keymap_p(char * name)1078 int keymap_p(char *name) /*{{{*/
1079 {
1080 return ! (NULL == SLang_find_keymap(name));
1081 }
1082
1083 /*}}}*/
1084
set_key_in_keymap(char * f,char * key,char * map)1085 void set_key_in_keymap(char *f, char *key, char *map) /*{{{*/
1086 {
1087 SLKeyMap_List_Type *kmap;
1088
1089 if (NULL == (kmap = SLang_find_keymap(map)))
1090 {
1091 msg_error(Keymap_Error);
1092 return;
1093 }
1094
1095 if (*key) SLang_define_key(key, f, kmap);
1096 }
1097
1098 /*}}}*/
1099
1100 #if 0
1101 void my_set_key_in_keymap(char *f, char *key, char *map) /*{{{*/
1102 {
1103 #ifdef SLKEYMAP_OBSOLETE
1104 VOID_STAR func;
1105 #else
1106 FVOID_STAR func;
1107 #endif
1108 SLKeyMap_List_Type *kmap;
1109
1110 if (NULL == (kmap = SLang_find_keymap(map)))
1111 {
1112 msg_error(Keymap_Error);
1113 return;
1114 }
1115
1116 func = SLang_find_key_function(f, kmap);
1117
1118 if (*key)
1119 {
1120 SLang_undefine_key(key, kmap);
1121 SLkm_define_key(key, func, kmap);
1122 }
1123 }
1124
1125 /*}}}*/
1126 #endif /* 0 */
1127
pop_to_buffer(char * name)1128 char *pop_to_buffer(char *name) /*{{{*/
1129 {
1130 Window_Type *w, *action, *use_this;
1131 char *bname;
1132 Line *line, *oldline;
1133 int p, oldp, lnum, oldlnum;
1134 Buffer *b, *oldb;
1135
1136 if (!strcmp(name, " <mini>"))
1137 {
1138 select_minibuffer ();
1139 return CBuf->name;
1140 }
1141
1142 /* save position so we can pop back to it if buffer already exists in
1143 window */
1144 oldb = CBuf; oldline = CLine; oldp = Point; oldlnum = LineNum;
1145
1146 set_buffer(name);
1147 line = CLine; p = Point; lnum = LineNum;
1148
1149 use_this = NULL;
1150 if (MiniBuffer != NULL)
1151 {
1152 action = Mini_Info.action_window;
1153 }
1154 else action = NULL;
1155
1156 if (Batch) return CBuf->name;
1157
1158 w = JWindow;
1159 /* find a window to use */
1160 do
1161 {
1162 if (w->top != Jed_Num_Screen_Rows)
1163 {
1164 if (action != NULL)
1165 {
1166 if (w != action) use_this = w;
1167 }
1168 else if (w != JWindow) use_this = w;
1169
1170 if (w->buffer == CBuf)
1171 {
1172 use_this = w;
1173 break;
1174 }
1175 }
1176 w = w->next;
1177 }
1178 while (w != JWindow);
1179
1180 b = CBuf;
1181 if (use_this != NULL)
1182 {
1183 while(JWindow != use_this) other_window();
1184 /* This is a good reason for haveing otherwindow avoid switching buffers */
1185 if (CBuf == oldb)
1186 {
1187 CLine = oldline; Point = oldp; LineNum = oldlnum;
1188 }
1189 }
1190 else
1191 {
1192 if (action != NULL) while(JWindow != action) other_window();
1193 split_window();
1194 /*
1195 * doing it this way makes screen update look better
1196 */
1197 w = JWindow;
1198 do
1199 {
1200 other_window();
1201 }
1202 while (JWindow->buffer != w->buffer);
1203 JWindow->column = 1;
1204 }
1205
1206 bname = CBuf->name;
1207 switch_to_buffer(b);
1208 b->line = CLine = line;
1209 b->point = Point = p;
1210 b->linenum = LineNum = lnum;
1211 if (b != JWindow->buffer) window_buffer(b);
1212 return bname;
1213 }
1214
1215 /*}}}*/
1216
1217 /* return number of windows */
num_windows()1218 int num_windows() /*{{{*/
1219 {
1220 Window_Type *w;
1221 int i = 0;
1222
1223 w = JWindow->next;
1224 while (i++, w != JWindow) w = w->next;
1225 return(i);
1226 }
1227
1228 /*}}}*/
1229
1230 /* I need to make this take another parameter which indicates what to do
1231 * with the cursor rather than sticking it at the end. Call the parameter p.
1232 * Then try:
1233 * if (p <= 0) p = strlen(Message_Buffer) + 1;
1234 * tt_goto_rc(Screen_Height, p); */
1235
flush_message(char * m)1236 void flush_message(char *m) /*{{{*/
1237 {
1238 message(m);
1239 if (Batch) return;
1240 do_dialog(Message_Buffer);
1241 SLsmg_gotorc (Jed_Num_Screen_Rows - 1, strlen(Message_Buffer));
1242 *Message_Buffer = 0;
1243 JWindow->trashed = 1;
1244 SLsmg_refresh ();
1245 }
1246
1247 /*}}}*/
1248
1249 #if defined (REAL_UNIX_SYSTEM) || defined(__WIN32__) || (defined (__os2__) && !defined(__WATCOMC__))
1250
1251 # if defined (__WIN32__) /* defined (__BORLANDC__) || defined (_MSC_VER) */
1252 # undef popen
1253 # undef pclose
1254 # define popen w32_popen
1255 # define pclose w32_pclose
1256 # endif
1257
1258 # ifdef __IBMC__
1259 extern FILE *popen(char *, char *);
1260 extern int pclose(FILE *);
1261 # endif
1262
1263 # if !JED_HAS_SUBPROCESSES
1264 # define jed_popen popen
1265 # define jed_pclose pclose
1266 # endif
1267
1268 static char *Process_Error = "Unable to open process.";
shell_command(char * cmd)1269 int shell_command(char *cmd) /*{{{*/
1270 {
1271 FILE *pp;
1272 VFILE *vp;
1273 int status;
1274 #if JED_HAS_SUBPROCESSES
1275 int tmp_filecode;
1276 #endif
1277
1278 if (Jed_Secure_Mode)
1279 {
1280 msg_error ("Access denied.");
1281 return -1;
1282 }
1283
1284 if (NULL == (pp = jed_popen(cmd, "r")))
1285 {
1286 msg_error(Process_Error);
1287 return -1;
1288 }
1289
1290 if (NULL != (vp = vstream(fileno(pp), 0, VFILE_TEXT)))
1291 {
1292 #if JED_HAS_SUBPROCESSES
1293 tmp_filecode = CBuf->kfcode;
1294 CBuf->kfcode = kanji_default_process_code;
1295 #endif
1296 (void) insert_file_pointer(vp);
1297 #if JED_HAS_SUBPROCESSES
1298 CBuf->kfcode = tmp_filecode;
1299 #endif
1300 SLfree(vp->buf);
1301 SLfree ((char *)vp);
1302 }
1303 else msg_error("Malloc Error.");
1304
1305 status = jed_pclose (pp);
1306
1307 #if defined(WIFEXITED) && defined(WEXITSTATUS)
1308 if ((status != -1) && WIFEXITED(status))
1309 {
1310 status = WEXITSTATUS(status);
1311 }
1312 #endif
1313 return status;
1314 }
1315
1316 /*}}}*/
pipe_region(char * cmd)1317 int pipe_region(char *cmd) /*{{{*/
1318 {
1319 FILE *pp;
1320 int n, tmp_filecode;
1321
1322 if (Jed_Secure_Mode)
1323 {
1324 msg_error ("Access denied.");
1325 return -1;
1326 }
1327
1328 if (NULL == (pp = jed_popen (cmd, "w")))
1329 {
1330 msg_error(Process_Error);
1331 return(-1);
1332 }
1333
1334 #if 1
1335 /* pp is file pointer of pipe.
1336 * normally it use KANJI file code of current buffer.
1337 * this code fake it by process code of KANJI.
1338 * But,,, I(Kazuhisa Yoshino) can't use this code,
1339 * because pipe is special "file" on unix.
1340 * If you use "pipe_region" function on S-Lang,
1341 * before you use it, set current buffer's file code
1342 * by s-lang "set_kanji_file_code" function.
1343 * And, after use "pipe_region" function, restore
1344 * buffer's KANJI file code.
1345 */
1346 tmp_filecode = CBuf->kfcode;
1347 #if JED_HAS_SUBPROCESSES
1348 CBuf->kfcode = kanji_default_process_code;
1349 #endif
1350 n = write_region_to_fp(fileno(pp));
1351 CBuf->kfcode = tmp_filecode;
1352 #else
1353 n = write_region_to_fp(fileno(pp));
1354 #endif
1355 if (n == -1)
1356 msg_error ("pipe_region: write failed");
1357
1358 return jed_pclose (pp);
1359 }
1360
1361 /*}}}*/
1362 #endif
1363
1364 /*
1365 * Try to open a .slc then a .sl
1366 */
1367 #ifdef SIXTEEN_BIT_SYSTEM
1368 #define VFILE_BUF_SIZE 1024
1369 #else
1370 #define VFILE_BUF_SIZE 4096
1371 #endif
1372
1373
jed_open_lib_file(char * file)1374 static VFILE *jed_open_lib_file (char *file) /*{{{*/
1375 {
1376 char libfsl[JED_MAX_PATH_LEN], libfslc[JED_MAX_PATH_LEN];
1377 char *lib, *type, *libf;
1378 unsigned int n;
1379 VFILE *vp = NULL;
1380
1381 libf = file;
1382 lib = Jed_Library;
1383
1384 /* If file begins with ./,then read it from the current directory */
1385 if ((*file == '.')
1386 && ((file[1] == '/')
1387 #ifdef IBMPC_SYSTEM
1388 || (file[1] == '\\')
1389 #endif
1390 ))
1391 lib = "";
1392 else if ((lib == NULL) || (*lib == 0))
1393 exit_error("JED_ROOT environment variable needs set.", 0);
1394
1395 if ((NULL != (type = file_type(file)))
1396 && (*type == 0))
1397 type = NULL;
1398
1399 n = 0;
1400 while (0 == SLextract_list_element (lib, n, ',', libfsl, sizeof(libfsl)))
1401 {
1402 n++;
1403
1404 fixup_dir(libfsl);
1405 safe_strcat (libfsl, file, sizeof (libfsl));
1406 strcpy (libfsl, expand_filename(libfsl));
1407
1408 libf = libfsl;
1409
1410 if (NULL != (vp = vopen(libf, VFILE_BUF_SIZE, VFILE_TEXT)))
1411 break;
1412
1413 if (type == NULL)
1414 {
1415 #ifdef VMS
1416 int vmsn;
1417 /* remove trailing '.' */
1418 if (0 != (vmsn = strlen(libfsl)))
1419 {
1420 vmsn--;
1421 if (libfsl[vmsn] == '.') libfsl[vmsn] = 0;
1422 }
1423 #endif
1424
1425 /* Try .sl and .slc */
1426 strcat (libfsl, ".sl");
1427 strcpy (libfslc, libfsl);
1428 strcat (libfslc, "c");
1429
1430 if (file_time_cmp(libfslc, libfsl) >= 0)
1431 libf = libfslc;
1432
1433 if (NULL != (vp = vopen(libf, VFILE_BUF_SIZE, VFILE_TEXT)))
1434 break;
1435 }
1436 }
1437
1438 if (Batch != 2)
1439 jed_vmessage (1, "loading %s", libf);
1440
1441 return (vp);
1442 }
1443
1444 /*}}}*/
1445
jed_read_from_file(SLang_Load_Type * x)1446 static char *jed_read_from_file(SLang_Load_Type *x) /*{{{*/
1447 {
1448 char *s;
1449 unsigned int n;
1450
1451 if ((s = vgets((VFILE *) x->client_data, &n)) != NULL)
1452 {
1453 if (s[n - 1] != '\n') s[n] = 0;
1454 }
1455
1456 return s;
1457 }
1458
1459 /*}}}*/
1460
jed_load_file(char * file)1461 int jed_load_file (char *file)
1462 {
1463 VFILE *vp;
1464 SLang_Load_Type *x;
1465 int ret;
1466
1467 if (NULL == (x = SLallocate_load_type (file)))
1468 return -1;
1469
1470 if (NULL == (vp = jed_open_lib_file (file)))
1471 {
1472 SLang_verror (SL_OBJ_NOPEN, "Unable to load %s", file);
1473 SLdeallocate_load_type (x);
1474 return -1;
1475 }
1476
1477 x->client_data = (VOID_STAR) vp;
1478 x->read = jed_read_from_file;
1479 ret = SLang_load_object (x);
1480 SLdeallocate_load_type (x);
1481 vclose (vp);
1482 return ret;
1483 }
1484
1485
1486 typedef struct
1487 {
1488 Line *l;
1489 char buf[256];
1490 }
1491 Buffer_Client_Type;
1492
jed_read_from_buffer(SLang_Load_Type * x)1493 static char *jed_read_from_buffer (SLang_Load_Type *x) /*{{{*/
1494 {
1495 Buffer_Client_Type *b;
1496 char *buf;
1497 Line *l;
1498 unsigned int len;
1499
1500 b = (Buffer_Client_Type *)x->client_data;
1501
1502 if (NULL == (l = b->l))
1503 return NULL;
1504
1505 len = (unsigned int) l->len;
1506 if (len > 255)
1507 {
1508 SLang_doerror ("Line len too long");
1509 return NULL;
1510 }
1511
1512 buf = b->buf;
1513 SLMEMCPY(buf, (char *) l->data, len);
1514 buf [len] = 0;
1515 b->l = l->next;
1516
1517 return buf;
1518 }
1519 /*}}}*/
1520
load_buffer(void)1521 void load_buffer (void) /*{{{*/
1522 {
1523 SLang_Load_Type *x;
1524 Buffer_Client_Type client_data;
1525 Buffer *cbuf = CBuf;
1526 int flags = CBuf->flags;
1527 Line *l, *lwant;
1528
1529 /* FIXME!!! This should be changed to use the filename if present.
1530 * Otherwise, static objects will not get put in the proper table.
1531 */
1532 if (NULL == (x = SLallocate_load_type (cbuf->name)))
1533 return;
1534
1535 x->read = jed_read_from_buffer;
1536 x->client_data = (VOID_STAR) &client_data;
1537 client_data.l = CBuf->beg;
1538
1539 cbuf->flags |= READ_ONLY;
1540 SLang_load_object(x);
1541 SLdeallocate_load_type (x);
1542
1543 if (buffer_exists (cbuf))
1544 cbuf->flags = flags;
1545 else cbuf = NULL;
1546
1547 if ((SLang_Error == 0)
1548 && (*Error_Buffer == 0))
1549 return;
1550
1551 SLang_doerror(NULL);
1552 if (cbuf == NULL)
1553 return;
1554
1555 pop_to_buffer (cbuf->name);
1556 lwant = client_data.l;
1557
1558 if (lwant != NULL)
1559 {
1560 bob();
1561 while (1)
1562 {
1563 l = CLine->next;
1564 if ((l == NULL) || (l == lwant)) break;
1565 CLine = l; LineNum++;
1566 }
1567 (void) skip_whitespace();
1568 }
1569 }
1570
1571 /*}}}*/
1572
1573
get_key_function()1574 void get_key_function() /*{{{*/
1575 {
1576 char *s;
1577 int kind;
1578
1579 s = find_key(&kind);
1580 if (s != NULL)
1581 {
1582 if (SLKeyBoard_Quit && (SLang_Error == USER_BREAK))
1583 {
1584 SLang_Error = 0;
1585 SLKeyBoard_Quit = 0;
1586 /* s = "kbd_quit"; */
1587 }
1588 SLang_push_integer(kind);
1589 }
1590 else s = "";
1591 SLang_push_string(s);
1592 }
1593
1594 /*}}}*/
1595
1596 static SLang_Name_Type *Expand_File_Hook;
set_expansion_hook(char * s)1597 void set_expansion_hook (char *s) /*{{{*/
1598 {
1599 if (NULL == (Expand_File_Hook = SLang_get_function (s)))
1600 {
1601 msg_error ("The expansion hook has not been defined.");
1602 }
1603 }
1604
1605 /*}}}*/
1606
mini_complete(void)1607 int mini_complete (void) /*{{{*/
1608 {
1609 char *pl, *pb;
1610 char last[JED_MAX_PATH_LEN], buf[JED_MAX_PATH_LEN], *tmp;
1611 static char prev[JED_MAX_PATH_LEN];
1612 int n, last_key_char = SLang_Last_Key_Char;
1613 static int flag = 0; /* when flag goes 0, we call open */
1614
1615 if (complete_open == NULL) return ins_char_cmd();
1616
1617 Point = 0;
1618 push_mark();
1619 eob();
1620 if (NULL == (tmp = make_buffer_substring(&n))) return(1);
1621
1622 safe_strcpy(buf, tmp, sizeof (buf));
1623 SLfree(tmp);
1624
1625 if ((last_key_char == ' ') && ((long) Last_Key_Function == (long) mini_complete))
1626 {
1627 if (flag)
1628 flag = (*complete_next)(buf);
1629 if (flag == 0)
1630 {
1631 safe_strcpy(buf, prev, sizeof (buf));
1632 flag = (*complete_open)(buf);
1633 }
1634 strcpy(last, buf);
1635 n = -1;
1636 }
1637 else
1638 {
1639 n = 0;
1640 strcpy(prev, buf); /* save this search context */
1641 }
1642
1643 if (!n)
1644 {
1645 if ((Repeat_Factor != NULL)
1646 || (complete_open != sys_findfirst) || (Expand_File_Hook == NULL))
1647 flag = (*complete_open)(buf);
1648 else
1649 {
1650 int do_free;
1651 SLang_push_string (buf);
1652 SLexecute_function (Expand_File_Hook);
1653 if (SLang_Error == 0) SLang_pop_integer (&do_free);
1654 if (SLang_Error == 0)
1655 {
1656 if (do_free == 0)
1657 {
1658 flag = (*complete_open) (buf);
1659 goto start_loop;
1660 }
1661 }
1662
1663 if (SLang_Error || SLang_pop_slstring (&tmp))
1664 {
1665 msg_error ("Error encounter during expansion. Disabling expansion hook.");
1666 Expand_File_Hook = NULL;
1667 return 1;
1668 }
1669 safe_strcpy (last, tmp, sizeof (last));
1670 strcpy (prev, last);
1671 SLang_free_slstring (tmp);
1672 flag = 0; /* So we do not call complete_next */
1673 n = -1;
1674 }
1675 }
1676
1677 start_loop:
1678
1679 if (!n && flag)
1680 {
1681 strcpy(last, buf);
1682
1683 /* This do loop tests all values from complete_next and returns the
1684 smallest length match of initial characters of buf */
1685 do
1686 {
1687 if ((n == 0) && (last_key_char == '\t'))
1688 {
1689 set_buffer (Completion_Buffer);
1690 erase_buffer ();
1691 CBuf->flags |= BURIED_BUFFER;
1692 insert_string ("!!! Use Page Up/Down keys to scroll this window. !!!\n");
1693 }
1694
1695 n++;
1696 pl = last;
1697 pb = buf;
1698
1699 #if !JED_FILE_PRESERVE_CASE
1700 if (complete_open == open_bufflist)
1701 while (*pl && (UPPER_CASE(*pl) == UPPER_CASE(*pb)))
1702 {
1703 pl++;
1704 pb++;
1705 }
1706 else /* next statement */
1707 #endif
1708 while (*pl && (*pl == *pb))
1709 {
1710 pl++;
1711 pb++;
1712 }
1713
1714
1715 *pl = 0;
1716
1717 if (last_key_char == '\t')
1718 {
1719 while (*pb) pb++;
1720 quick_insert ((unsigned char *)buf, (int) (pb - buf));
1721 newline ();
1722 }
1723 }
1724 while(0 != (flag = (*complete_next)(buf)));
1725
1726 #if JED_FILE_PRESERVE_CASE
1727 /* OS/2 uses case-insensitive search on buffer-names. Set the
1728 * flag if there is an exact match, so that completion will
1729 * cycle without repeats through all the matches.
1730 */
1731 if (complete_open == open_bufflist)
1732 {
1733 strcpy(buf, last);
1734 (*complete_open)(buf);
1735 do
1736 {
1737 if (!strcmp(buf, last))
1738 {
1739 flag = 1; break;
1740 }
1741 }
1742 while ((*complete_next)(buf));
1743 }
1744 #endif
1745 }
1746
1747 if ((n > 1) && (last_key_char == '\t') && (Last_Completion_Buffer == NULL))
1748 {
1749 Last_Completion_Windows = num_windows () - 1; /* not including mini */
1750 Last_Completion_Buffer = pop_to_buffer (Completion_Buffer);
1751 bob ();
1752 }
1753
1754 while ((CBuf != MiniBuffer) || !IS_MINIBUFFER) other_window ();
1755
1756 if (n)
1757 {
1758 erase_buffer();
1759 /* strcpy(last, buf); */
1760 insert_string(last);
1761 if ((n == 1) && ((long) Last_Key_Function == (long) mini_complete))
1762 message("[Sole Completion.]");
1763 }
1764 else msg_error("No Match!");
1765
1766 return(1);
1767 }
1768
1769 /*}}}*/
1770
what_char()1771 int what_char() /*{{{*/
1772 {
1773 if (eobp()) return(0);
1774 return( (int) *(CLine->data + Point) );
1775 }
1776
1777 /*}}}*/
1778
jwhat_char()1779 unsigned int jwhat_char() /*{{{*/
1780 {
1781 unsigned int ch;
1782
1783 if (eobp()) return(0);
1784 ch = (unsigned int) *(CLine->data + Point);
1785 if(iskanji(ch))
1786 {
1787 ch <<= 8;
1788 ch += (unsigned int) *(CLine->data + Point +1);
1789 }
1790 return(ch);
1791 }
1792
1793 /*}}}*/
1794
update_cmd(int * force)1795 void update_cmd(int *force) /*{{{*/
1796 {
1797 if (Batch) return;
1798 JWindow->trashed = 1;
1799 update((Line *) NULL, *force, 0);
1800 }
1801
1802 /*}}}*/
1803
call_cmd(char * str)1804 void call_cmd(char *str) /*{{{*/
1805 {
1806 SLKeyMap_List_Type *km;
1807 int (*fp)(void);
1808
1809 km = CBuf->keymap;
1810 if (NULL == (fp = (int (*)(void)) (SLang_find_key_function(str, km))))
1811 {
1812 msg_error("Function does not exist!");
1813 }
1814 else (void) (*fp)();
1815 }
1816
1817 /*}}}*/
1818
copy_region_cmd(char * name)1819 void copy_region_cmd(char *name) /*{{{*/
1820 {
1821 Buffer *buf;
1822
1823 if (NULL != (buf = find_buffer(name)))
1824 {
1825 copy_region_to_buffer(buf);
1826 }
1827 else msg_error("Unable to find buffer.");
1828 }
1829
1830 /*}}}*/
1831
1832 #ifndef IBMPC_SYSTEM
1833
screen_w80(void)1834 void screen_w80 (void) /*{{{*/
1835 {
1836 tt_narrow_width ();
1837 jed_resize_display ();
1838 }
1839
1840 /*}}}*/
screen_w132(void)1841 void screen_w132 (void) /*{{{*/
1842 {
1843 tt_wide_width();
1844 jed_resize_display ();
1845 }
1846
1847 /*}}}*/
1848 #endif
1849
make_line_string(char * string,unsigned int buflen)1850 char *make_line_string(char *string, unsigned int buflen) /*{{{*/
1851 {
1852 unsigned char *tmp, *p1, *p2;
1853 unsigned int n;
1854
1855 if (CBuf->marks == NULL)
1856 {
1857 p1 = CLine->data + Point;
1858 p2 = CLine->data + CLine->len;
1859 }
1860 else
1861 {
1862 p1 = CLine->data + CBuf->marks->point;
1863 p2 = CLine->data + Point;
1864 if (p2 < p1)
1865 {
1866 tmp = p1; p1 = p2; p2 = tmp;
1867 }
1868 pop_mark(&Number_Zero);
1869 }
1870 n = (unsigned int) (p2 - p1);
1871 if (n >= buflen) n = buflen - 1;
1872 SLMEMCPY(string, (char *) p1, n);
1873 string[n] = 0;
1874 return(string);
1875 }
1876
1877 /*}}}*/
1878
make_buffer_substring(int * np)1879 char *make_buffer_substring(int *np) /*{{{*/
1880 {
1881 Line *tthis, *beg;
1882 int n = 1, dn, thisp;
1883 unsigned char *buf;
1884
1885 if (!check_region(&n)) return (NULL); /* spot pushed */
1886 /* Point now at end of the region */
1887
1888 beg = tthis = CBuf->marks->line;
1889 thisp = CBuf->marks->point;
1890 n = 0;
1891 pop_mark(&n);
1892
1893 while (tthis != CLine)
1894 {
1895 n += tthis->len;
1896 tthis = tthis->next;
1897 }
1898 n -= thisp;
1899 n += Point;
1900
1901 if (NULL == (buf = (unsigned char *) SLmalloc (n + 1)))
1902 {
1903 pop_spot();
1904 return (NULL);
1905 }
1906
1907 if (CLine == (tthis = beg))
1908 {
1909 SLMEMCPY((char *)buf, (char *) (tthis->data + thisp), n);
1910 }
1911 else
1912 {
1913 n = 0;
1914 while (tthis != CLine)
1915 {
1916 dn = tthis->len - thisp;
1917 SLMEMCPY((char *)(buf + n), (char *) (tthis->data + thisp), dn);
1918 tthis = tthis->next;
1919 thisp = 0;
1920 n += dn;
1921 }
1922 SLMEMCPY((char *)(buf + n), (char *) tthis->data, Point);
1923 n += Point;
1924 }
1925 buf[n] = 0;
1926 *np = n;
1927 pop_spot();
1928 return ((char *) buf);
1929 }
1930
1931 /*}}}*/
1932
buffer_substring()1933 void buffer_substring() /*{{{*/
1934 {
1935 char *buf;
1936 int n;
1937 if (NULL == (buf = make_buffer_substring(&n))) return;
1938 SLang_push_malloced_string((char *)buf);
1939 }
1940
1941 /*}}}*/
1942
markp(void)1943 int markp(void) /*{{{*/
1944 {
1945 return (CBuf->marks != NULL);
1946 }
1947
1948 /*}}}*/
1949
dup_mark(void)1950 int dup_mark(void) /*{{{*/
1951 {
1952 if (CBuf->marks == NULL) return(0);
1953
1954 push_spot();
1955 goto_mark(CBuf->marks);
1956 push_mark();
1957 pop_spot();
1958 return(1);
1959 }
1960
1961 /*}}}*/
1962
mini_read(char * prompt,char * def,char * stuff)1963 void mini_read(char *prompt, char *def, char *stuff) /*{{{*/
1964 {
1965 char *buf;
1966 int n;
1967
1968 complete_open = NULL;
1969 if (NULL == (buf = read_from_minibuffer(prompt, def, stuff, &n)))
1970 SLang_push_string ("");
1971 else SLang_push_malloced_string(buf);
1972 }
1973
1974 /*}}}*/
1975
get_buffer_info(void)1976 void get_buffer_info(void) /*{{{*/
1977 {
1978 SLang_push_string(CBuf->file);
1979 SLang_push_string(CBuf->dir);
1980 SLang_push_string(CBuf->name);
1981 SLang_push_integer(CBuf->flags);
1982 }
1983
1984 /*}}}*/
1985
set_buffer_info(char * file,char * dir,char * name,int * flags)1986 void set_buffer_info(char *file, char *dir, char *name, int *flags) /*{{{*/
1987 {
1988 char dirbuf [JED_MAX_PATH_LEN + 1];
1989
1990 safe_strcpy (dirbuf, dir, sizeof (dirbuf) - 2);
1991 fixup_dir (dirbuf);
1992 dir = SLang_create_slstring (expand_filename (dirbuf));
1993 file = SLang_create_slstring (file);
1994 name = SLang_create_slstring (name);
1995
1996 if (SLang_Error)
1997 {
1998 /* SLang_free_slstring ignores NULL */
1999 SLang_free_slstring (dir);
2000 SLang_free_slstring (file);
2001 SLang_free_slstring (name);
2002 return;
2003 }
2004
2005 CBuf->file = file;
2006 CBuf->name = name;
2007 CBuf->dir = dir;
2008 CBuf->flags = *flags;
2009 }
2010
2011 /*}}}*/
2012
make_buffer_list(void)2013 void make_buffer_list(void) /*{{{*/
2014 {
2015 int n = 0;
2016 Buffer *b;
2017
2018 b = CBuf;
2019
2020 do
2021 {
2022 SLang_push_string(b->name);
2023 b = b->next;
2024 n++;
2025 }
2026 while (b != CBuf);
2027 SLang_push_integer(n);
2028 }
2029
2030 /*}}}*/
2031
window_size_intrinsic(int * what)2032 int window_size_intrinsic(int *what) /*{{{*/
2033 {
2034 register int n = 0;
2035 switch (*what)
2036 {
2037 case 'r': n = JWindow->rows; break;
2038 case 'c': n = JWindow->column; break;
2039 case 't': n = JWindow->top; break;
2040 case 'w': n = JWindow->width; break;
2041 default: SLang_Error = SL_UNKNOWN_ERROR;
2042 }
2043 return (n);
2044 }
2045
2046 /*}}}*/
2047
2048
2049 /* Given a file name with wildcards return expanded list to S-Lang stack
2050 * with number. This does NOT work on unix with wild cards. Instead the
2051 * expansion is file* (completion) */
expand_wildcards(char * file)2052 int expand_wildcards(char *file) /*{{{*/
2053 {
2054 char buf[JED_MAX_PATH_LEN];
2055 int n = 0;
2056
2057 safe_strcpy(buf, file, sizeof (buf));
2058
2059 if (sys_findfirst(buf))
2060 {
2061 do
2062 {
2063 n++;
2064 SLang_push_string(buf);
2065 }
2066 while (sys_findnext(buf));
2067 }
2068 return (n);
2069 }
2070
2071 /*}}}*/
2072
jed_traceback(char * s)2073 static void jed_traceback(char *s) /*{{{*/
2074 {
2075 char *n;
2076 if (!Batch)
2077 {
2078 n = CBuf->name;
2079 set_buffer("*traceback*");
2080 eob();
2081 insert_string(s);
2082 set_buffer(n);
2083 }
2084 else fprintf(stderr, s);
2085 }
2086
2087 /*}}}*/
2088
2089 #if 0
2090 static struct /*{{{*/
2091 {
2092 int depth = 0;
2093 char *name[20];
2094 int marks[20];
2095 }
2096
2097 /*}}}*/
2098 FName_Stack;
2099
2100 void enter_function(char *name) /*{{{*/
2101 {
2102 if (depth > 20)
2103 {
2104 msg_error("Function Stack too deep.");
2105 return;
2106 }
2107 FName_Stack->name[depth] = name;
2108 FName_Stack->marks[depth] = 0;
2109 }
2110
2111 /*}}}*/
2112 void exit_function(char *name) /*{{{*/
2113 {
2114 int n = FName_Stack->marks[depth];
2115
2116 }
2117
2118 /*}}}*/
2119 #endif
2120
2121
2122
count_chars(void)2123 void count_chars(void) /*{{{*/
2124 {
2125 unsigned long n = 0, m = 0;
2126 int ch, ch2 = 0;
2127 char buf[64];
2128 Line *l = CBuf->beg;
2129
2130 while (l != NULL)
2131 {
2132 n += l->len;
2133 l = l->next;
2134 }
2135 l = CBuf->beg;
2136 while (l != CLine)
2137 {
2138 m += l->len;
2139 l = l->next;
2140 }
2141 m += Point + 1;
2142 ch = eobp() ? 0 : (int) *(CLine->data + Point);
2143 if(iskanji(ch)) ch2 = *(CLine->data + Point + 1);
2144 if(ch2 && is_kanji_jedcode())
2145 sprintf(buf, "'@@'=%d,%d/0x%x%x, point %lu of %lu", ch, ch2, ch, ch2, m, n);
2146 else
2147 sprintf(buf, "'@'=%d/0x%x/%#o, point %lu of %lu", ch, ch, ch, m, n);
2148 if (ch != 0) buf[1] = ch;
2149 else buf[0] = '^';
2150 if (ch2) buf[2] = ch2;
2151 SLang_push_string(buf);
2152 }
2153
2154 /*}}}*/
2155
jed_clear_error(void)2156 static void jed_clear_error(void) /*{{{*/
2157 {
2158 *Error_Buffer = 0;
2159 SLKeyBoard_Quit = 0;
2160 }
2161
2162 /*}}}*/
2163
2164 typedef struct _Init_SLang_Hook_Type
2165 {
2166 int (*hook)(void);
2167 struct _Init_SLang_Hook_Type *next;
2168 }
2169 Init_SLang_Hook_Type;
2170
2171 static Init_SLang_Hook_Type *Init_SLang_Hooks;
2172
jed_add_init_slang_hook(int (* hook)(void))2173 int jed_add_init_slang_hook (int (*hook)(void))
2174 {
2175 Init_SLang_Hook_Type *h;
2176
2177 if (hook == NULL)
2178 return 0;
2179
2180 h = (Init_SLang_Hook_Type *)SLmalloc (sizeof (Init_SLang_Hook_Type));
2181 if (h == NULL)
2182 return -1;
2183
2184 h->hook = hook;
2185 h->next = Init_SLang_Hooks;
2186 Init_SLang_Hooks = h;
2187 return 0;
2188 }
2189
run_init_slang_hooks(void)2190 static int run_init_slang_hooks (void)
2191 {
2192 Init_SLang_Hook_Type *h;
2193
2194 h = Init_SLang_Hooks;
2195
2196 while (h != NULL)
2197 {
2198 if (-1 == (*h->hook)())
2199 return -1;
2200 h = h->next;
2201 }
2202
2203 while (Init_SLang_Hooks != NULL)
2204 {
2205 h = Init_SLang_Hooks->next;
2206 SLfree ((char *) Init_SLang_Hooks);
2207 Init_SLang_Hooks = h;
2208 }
2209
2210 return 0;
2211 }
2212
slang_exit_error_handler(char * fmt,va_list ap)2213 static void slang_exit_error_handler (char *fmt, va_list ap)
2214 {
2215 char buf [2048];
2216
2217 vsprintf (buf, fmt, ap);
2218 exit_error (buf, 0);
2219 }
2220
vmsg_hook(char * fmt,va_list ap)2221 static void vmsg_hook (char *fmt, va_list ap)
2222 {
2223 char buf [2048];
2224 vsprintf (buf, fmt, ap);
2225 message (buf);
2226 }
2227
init_minibuffer()2228 void init_minibuffer() /*{{{*/
2229 {
2230 Buffer *tmp;
2231
2232 tmp = CBuf;
2233
2234 The_MiniBuffer = make_buffer (" <mini>", NULL, NULL);
2235 The_MiniBuffer->modes = 0;
2236 /* do some initializing */
2237 switch_to_buffer(The_MiniBuffer);
2238 remake_line(132);
2239 The_MiniWindow = create_window(Jed_Num_Screen_Rows, 1, 1, Jed_Num_Screen_Cols);
2240 The_MiniWindow->buffer = CBuf;
2241 Buffer_Local.tab = 0;
2242 switch_to_buffer(tmp);
2243 SLang_Dump_Routine = jed_traceback;
2244 SLang_Exit_Error_Hook = slang_exit_error_handler;
2245
2246 #ifdef __GO32__
2247 SLang_Interrupt = i386_check_kbd;
2248 #endif
2249
2250 #if 0
2251 SLang_Enter_Function = enter_function;
2252 SLang_Exit_Function = exit_function;
2253 #endif
2254 if ((-1 == SLang_init_slang ())
2255 #ifndef SIXTEEN_BIT_SYSTEM
2256 || (-1 == SLang_init_slmath ())
2257 #endif
2258 || (-1 == SLang_init_posix_process ())
2259 || (-1 == SLang_init_posix_dir ())
2260 || (-1 == SLang_init_slassoc ())
2261 || (-1 == init_jed_intrinsics ())
2262 #if JED_HAS_MENUS
2263 || (-1 == jed_init_menus ())
2264 #endif
2265 || (-1 == register_jed_classes ())
2266 || (-1 == SLang_init_slfile())
2267 || (-1 == kSLinit_kanji())
2268 #if JED_HAS_CANNA_SUPPORT
2269 || (-1 == init_SLCanna())
2270 #endif
2271 || (-1 == run_init_slang_hooks ()))
2272 {
2273 exit_error("Unable to initialize S-Lang!", 0);
2274 }
2275
2276 /* use jed rouotines instead of default slang ones */
2277 SLang_Error_Hook = msg_error;
2278 SLang_VMessage_Hook = vmsg_hook;
2279 SLang_User_Clear_Error = jed_clear_error;
2280 SLang_Load_File_Hook = jed_load_file;
2281 }
2282
2283 /*}}}*/
2284