IMD 1.17: 20/08/2009 22:41:11 Simple Editor source code 0941 ULDSDDST  1hcromix c2#O&%$#"!      E  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQ` c46z   !"#$%&'()*+,-./01234 56789:;<=>?@ABCDEFGc2!c2$c45HSW &W  c4/I W 0W %c4#xyz{|}~JW +9W .c4"vwK W  W  4c4 lmnopqrstuLPW  ;W  "c4 !"#$%&'()*+,;MW  W -c4     ):NW 5W 5-c4 O W 52W 6c4aMP2W  W c4\%Q0W #W c34{|}~RSTUVWXYZ[\]^_`abcdefghijklmnop qrstuvwxyz{|}~        !"#$ %&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_` abcdefghijklmnopqrstuvwxyz{|}~  sescr.cQsecmd.cPseext.cOseext.hNseutil.cMseiocrx.cLseiocrx.dKse.makJsedefcrx.hIse.binH941files.txtG/* */ /* ECS Screen Editor, */ /* J. A. Pickering, Department of Electronics and Computer Science, */ /* (C) Copyright 1987 Southampton University, UK. */ /* */ /* C version : last updated 05-Oct-87 */ /*  */ /* Permission to use and amend the code herein is given on condition: */ /* */ /* (1) That the Department of Electronics and Computer Science, */ /* Southampton University, UK, and the Copyright notice remain in the */ /* code source headers and within the executable code, */ /* */ /* (2) That the editor signon message remains "ECS Screen Editor", */ /* */ /* (3) That copies of the source code OR the executable code so derived */ /* are not sold for gain or profit by any other party except the */ /* Southampton University, UK, or its authorised agents, */ /* */ /* (4) That this copy is used solely by the purchaser on one machine for */ /* generating executable binaries for one type of target machine */ /* operating system. Further copies should be obtained otherwise. */ /* (The amended source may already be available.) */ /* */ /* */ /* This part comprises the screen editing command loop,  */ /* closely associated utilities and the MAIN program. */ /* */ #ifndef MONOLITH #include "sedef.h" #include "seext.h" #endif /*--------------------------------------------------------------------*/ /* */ /* ECS Screen Editor MAIN routine. Initialises key text buffer, */ /* terminal IO, global variables, analyses command arguments and */ /* sets up the files and text buffer. The screen editing loop then */ /* starts. */ /* */ /*--------------------------------------------------------------------*/ main(argc, argv) int argc; char *argv[]; { mem_init(); trm_init(); /* (writes banner) */ findstr1 = gvec(width-PROMPTPOS-STATUSWIDTH+1); *findstr1 = 0; findstr2 = gvec(width-PROMPTPOS-STATUSWIDTH+1); *findstr2 = 0; last_infile = gvec(width-PROMPTPOS-STATUSWIDTH+1); *last_infile = 0; temp_buff = gvec(sizeof(lnode)); hold_list = NULL; first_line = NULL; last_line = NULL; next_line = 1; line_ptr = 1; mark_line = 0; mark_char = 0; height = depth-screen_start+1; memorise = FALSE; replay = FALSE; status = 0; new_status = status; status_msg = NULL; errorlevel = 0; attn = FALSE; com_line(argc, argv); set_files();  insert_mode = !browsing; next_kbuf = 0; next_key = 0; key_mode = insert_mode; off_left = 0; margin = wrapon ? width-13 : maxint; set_window(strin(iline, LINES), strin(icol, ABSOLUTE)); set_current(); bottom_line = top_line+height-1; modified = FALSE; flush_input(); se_screen(INTERACTIVE, k_verify); se_exit(TRUE, FALSE); /* safety net */ } /* */ /* Check if at the beginning of a word. */ /* */ static boolean at_word() { if ( (cur_line[char_ptr] != ' ') && ((char_ptr == 1) || (cur_line[char_ptr-1] == ' ')) ) return(TRUE); return FALSE; } /* */ /* Fill a line with spaces to a target character position. */ /* */ static void fillout(line, to_position) unsigned char *line; int to_position; { int i; for (i = *line+1 ; i <= to_position ; i++) line[i] = ' '; *line = max(to_position, *line); } /* */ /* Scroll screen upwards one line, filling in the new bottom line. */ /* */ static boolean scr_upline() { line_ptr++; top_line++; scroll_up(screen_start); bottom_line++; /* keep this uptodate for wright */ display_line(bottom_line, 1); return TRUE; /* never fails */ } /* */ /* Scroll screen downwards one line, filling in the new top line. */ /* */ static boolean scr_downline() { if (top_line == 1) return FALSE; line_ptr--; top_line--; scroll_down(screen_start); display_line(top_line, 1); return TRUE; } /* */ /* Move cursor down one line, scrolling displan if necessary. */ /* */ static void cur_down() { if (line_ptr < bottom_line) line_ptr++; else scr_upline(); } /* */ /* Move cursor up one line, scrolling display if necessary. */ /*   */ static void cur_up() { if (line_ptr > top_line) line_ptr--; else scr_downline(); } /* */ /* Update status line with the changes in SE status. */ /* */ static void disp_status(changes) int changes; { if ((changes & st_all) == 0) return; /* no changes so don't waste time */ if (((changes & (st_err | st_change)) != 0)) { move(1, 1); clear_line(); if (errorlevel != 0) printf("[ %s ]", status_msg); changes = st_all; /* now force a full display */ } if ((changes & st_keybuf) == st_keybuf) { move(1, width-43); if (memorise) fputs("[ memorising ]", stdout); if (replay) fputs("[ replaying ]", stdout); if (!(replay || memorise)) blank(14); } if ((changes & st_lheld) == st_lheld) { move(1, width-28); if (hold_list != NULL) fputs("[ holding ]", stdout); else { if (filling) fputs("[ Filling ]", stdout); else blank(11); } } if ((changes & st_ins) == st_ins) { move(1, width-1); emphasise(FALSE); move(1, width-15); if (insert_mode) { emphasise(TRUE); fputs("INSERTING", stdout); move(1, width-6); emphasise(FALSE); } else { emphasise(FALSE); if (browsing) fputs(" Browsing", stdout); else blank(9); } } } /* */ /* Insert a new line in front of the current cursor position, */ /* adjusting the new position according to whether auto indent mode */ /* is in force. Also fixup the display to match the insert. */ /* */ static void insert_line() { int align_at = autoind ? ( (cur_length > 0) ? next_printable(cur_line, 1) : char_ptr ) : 1; if (!( (line_ptr >= next_line) || ((line_ptr == (next_line-1)) && (char_ptr > cur_length)) )) { copy(cur_line, temp_buff); *temp_buff = min(*temp_buff, char_ptr-1); if (insert(temp_buff, line_ptr) == NULL) return; *temp_buff = 0; if (char_ptr <= cur_length)  /* split line */ { int align = autoind ? next_printable(cur_line, char_ptr) : char_ptr; slice_out(cur_line, 1, align); if (autoind) fillout(temp_buff, align_at-1); if (!(slice_in(cur_line, temp_buff, align_at-1))) return; display_line(line_ptr, 1); } if (insert(temp_buff, line_ptr+1) == NULL) return; delete(line_ptr+2); } char_ptr = align_at; if (line_ptr == bottom_line) scr_upline();  /* whole screen */ else /* or */ { scroll_down(screen_line(++line_ptr)); /* part screen fixup */ display_line(line_ptr, 1); } } /* */ /* Join two lines at the current cursor position taking account of */ /* auto indent mode. The display is fixed up accordingly. */ /* */  static void join_lines() { int first_printable, i; if (line_ptr >= next_line-1) return; copy(cur_line, temp_buff); fillout(temp_buff, char_ptr-1); cur_line = (line(line_ptr+1))->line; first_printable = next_printable(cur_line, 1); if (autoind) slice_out(cur_line, 1, first_printable); /* takeout excess space */ if (!(slice_in(cur_line, temp_buff, *temp_buff))) return; move(screen_line(line_ptr), char_ptr); for (i = 1; i <= *cur_line; i++) sc_wrch(cur_line[i], screen_line(line_ptr), char_ptr+i-1); if (insert(temp_buff, line_ptr) == NULL) return; delete(line_ptr+1); delete(line_ptr+1); if (line_ptr <= bottom_line) /* screen fixup */ { scroll_up(screen_line(line_ptr+1)); display_line(bottom_line, 1); } } /* */ /* Screen editing mode command loop. */ /* */ void se_screen(times, command) int times, command; { int ch = command; int times_round = 0; boolean prev_insert_mode = insert_mode; while (TRUE) { if (!replay) cursor(FALSE); *char_str = 1; /* string form used by default: */ char_str[1] = ch; switch (ch) { case k_wleft: while (TRUE) { boolean bof = !(char_back()); int new_line_ptr = line_ptr; if (line_ptr < top_line) { line_ptr = top_line; while (line_ptr != new_line_ptr) scr_downline(); } if ((at_word() && (char_ptr > off_left) && (char_ptr <= (width+off_left))) || bof) break; } break; case k_wright: while (TRUE) { boolean eof = !(char_fwd()); int new_line_ptr = line_ptr;  if (new_line_ptr > bottom_line) { line_ptr = bottom_line; while (line_ptr != new_line_ptr) scr_upline(); } if ((at_word() && (char_ptr > off_left) && (char_ptr <= (width+off_left))) || eof) break; } break; case k_up: flush_input(); cur_up(); break; case k_newline: if (insert_mode) { insert_line(); break; } char_ptr = 1; /* and do a k_down ... */ case k_down: if (ch == k_down) flush_input(); cur_down(); break; case k_scroldown: flush_input(); scr_upline(); break; case k_scrolup: flush_input();  scr_downline(); break; case k_uppage: flush_input(); if (top_line == 1) break; top_line = max(1, top_line-height); /* set TEXT position */ line_ptr = max(1, line_ptr-height); /* wrt cursor */ disp_page(); break; case k_downpage: flush_input(); if (bottom_line >= next_line) break; top_line = min( top_line+height , max(1,next_line-1-(height>>1)) ); line_ptr = min( line_ptr+height, max(1,next_line) ); char_ptr = (line_ptr == next_line) ? 1 : char_ptr; disp_page(); break; case k_dline: flush_input(); if (!browsing) { if (filling) cur_up(); if (line_ptr >= next_line) break;  pushline(line_ptr); scroll_up(screen_line(line_ptr)); move(depth, 1); display_line(bottom_line, 1); } break; case k_rstone: case k_restore: /* behaviour is filling mode dependent ... */ { lnode *top_held_list = hold_list; boolean more = ((hold_list != NULL) || filling); if (line_ptr >= next_line) if (create_lines(line_ptr-1) == NULL) break; while (more) { if (hold_list != NULL) { if (insert((popline())->line, line_ptr) == NULL) break; } else { if (filling) { if ( (readline(temp_buff) == ERR) || (insert(temp_buff, line_ptr) == NULL) ) break; }  } scroll_down(screen_line(line_ptr)); display_line(line_ptr, 1); if (filling) cur_down(); new_status = (hold_list == NULL) ? 0 : st_lheld; disp_status(new_status ^ status); status = new_status; more = ( ((hold_list != NULL) || filling) && !kready() && (ch != k_rstone) ); } if (!filling) { if ((ch == k_rstone) && (top_held_list != NULL)) fvec(top_held_list); else hold_list = top_held_list; /* for next restore */ } flush_input(); /* absorb panic characters */ break; } case k_backsp: if (browsing) break; /* otherwise do the delete ... */ case k_left:  { boolean was_first_char = (char_ptr == 1); if (!was_first_char) { char_ptr--; if (char_ptr <= off_left) break; /* abandon, cant place cursor properly */ } else { line_ptr--; /* back up to previous */ if (line_ptr < top_line) /* eol if possible */ { line_ptr = top_line; if (!(scr_downline())) break; } set_current(); char_ptr = cur_length+1; if (char_ptr > (off_left+width)) /* abandon, */ break; /* cant position properly */ } if ((ch == k_backsp) && !insert_mode && (char_ptr <= cur_length)) { int this_line = screen_line(line_ptr); cur_line[char_ptr] = ' '; /* wipe character */ move(this_line, char_ptr); sc_wrch(' ', this_line, char_ptr); strip_spaces(cur_line); modified = TRUE; break; } if (!( (ch == k_backsp) && insert_mode && ((char_ptr <= cur_length) || was_first_char) )) break; } /* otherwise do a delete ... */ case k_dchar: if (!browsing) { int i; flush_input(); if (line_ptr >= next_line) break; if (char_ptr > cur_length) { join_lines(); break; } if (!((1 <= char_ptr) && (char_ptr <= cur_length))) break; for (i = char_ptr+1 ; i <= cur_length ; i++) cur_line[i-1] = cur_line[i]; cur_line[cur_length] = ' ';  display_line(line_ptr, char_ptr); strip_spaces(cur_line); modified = TRUE; } break; case k_insert: insert_mode = (browsing) ? FALSE : !insert_mode; ++times_round; if (times_round == 2) freehold(); break; case k_verify: clear_screen(); disp_page(); status |= st_change; break; case k_again: if (memorise || browsing) { memorise = FALSE; break; } next_key = 1; prev_insert_mode = insert_mode; insert_mode = key_mode; replay = TRUE; break; case k_null: break; case k_tab: case k_right: { int old_char_ptr = char_ptr; do char_ptr++; while ( (ch == k_tab) && ((char_ptr % tabint ) != 1) ); if (!(insert_mode && (ch == k_tab))) break; /* otherwise insert the necessary spaces ... */ *char_str = 0; fillout(char_str, char_ptr-old_char_ptr); char_ptr = old_char_ptr; } default: { int ch = char_str[1]; if (ch < ' ') { se_command(); status |= st_change; break; } if (browsing) break; /* otherwise perform character processing ... */ if (ch != ' ') { if ((char_ptr == (width+off_left)) && insert_mode) { errmsg(cgt, warning); break; } if (line_ptr >= next_line) if (create_lines(line_ptr) == NULL) break; } if (!insert_mode && (char_ptr <= cur_length)) { /* in overtype mode in a line ... */ cur_line[char_ptr] = ch; sc_wrch(ch, screen_line(line_ptr), char_ptr); /* over */ strip_spaces(cur_line); modified = TRUE; } else { /* we're inserting or extending ... */ if ((ch == ' ') && (char_ptr > margin) && insert_mode) { insert_line(); break; } if ( (ch > ' ') || /* a printable or space within line */ ((ch == ' ') && (char_ptr <= cur_length)) ) { copy(cur_line, temp_buff); fillout(temp_buff, char_ptr-1); if (!(slice_in(char_str, temp_buff, char_ptr-1))) break; if (insert(temp_ buff, line_ptr) == NULL) break; delete(line_ptr+1); display_line(line_ptr, char_ptr); } } char_ptr += *char_str; break; } } if (ch != k_insert) times_round = 0; if (memorise) { if (next_kbuf == KEYMAX) errmsg("Keypress buffer full", warning); else keybuf[next_kbuf++] = ch; } if (replay) { if ((next_key >= next_kbuf) || (errorlevel >= warning)) { replay = FALSE; insert_mode = prev_insert_mode; if (times != INTERACTIVE) { if (times != UPTOTAG) times--; if (kready() || (times == 0) || (errorlevel >= warning) || (next_kbuf <= 1) || ((times == UPTOTAG) && (line_ptr >= mark_line)) ) { flush_input(); return; } else { next_key = 1; /* round we go again ... */ insert_mode = key_mode; replay = TRUE; } } } } if (replay) ch = keybuf[next_key++]; set_current(); bottom_line = top_line+height-1; if (cur_length > (width+off_left)) errmsg("Long line", interest);  if ((char_ptr <= off_left) || (char_ptr > (width+off_left))) errmsg(cgt, information); if (errorlevel == panic) { insert_mode = FALSE; browsing = TRUE; } new_status = (hold_list == NULL) ? 0 : st_lheld; new_status = (insert_mode) ? new_status | st_ins : new_status & ~st_ins; new_status = (memorise || replay) ? new_status | st_keybuf : new_status & ~st_keybuf; new_status = (errorlevel << 4) | (new_status & ~st_err); disp_status(new_status ^ status); /* only the changes */ status = new_status; if (attn) { bell(); attn = FALSE; } errorlevel = (errorlevel < danger) ? 0 : errorlevel; char_ptr = min(max(char_ptr,off_left+1),width+off_left); move(screen_line(line_ptr), char_ptr); if (!replay) { cursor(TRUE); update_screen(); ch = rch(); } else  update_screen(); } } /* */ /* ECS Screen Editor, */ /* J. A. Pickering, Department of Electronics and Computer Science, */ /* Copyright (C) 1987 Southampton University, UK. */ /* */ /* C version: Last updated 05-Oct-87 */ /*  */ /* Permission to use and amend the code herein is given on condition: */ /* */ /* (1) That the Department of Electronics and Computer Science, */ /* Southampton University, UK, and the Copyright notice remain in the */ /* code source headers and within the executable code, */ /* */ /* (2) That the editor signon message remains "ECS Screen Editor", */ /* */ /* (3) That copies of the source code OR the executable code so derived */ /* are not sold for gain or profit by any other party except the */ /* Southampton University, UK, or its authorised agents, */ /* */ /* (4) That this copy is used solely by the purchaser on one machine for */ /* generating executable binaries for one type of target machine */ /* operating system. Further copies should be obtained otherwise. */ /* (The amended source may already be available.) */ /* */ /* */ /* This part contains the command mode parser and associated primitives. */ /* */ #ifndef MONOLITH #include "sedef.h" #include "seext.h" #endif #define BARLINE 0 /* cursor report type (explicit enumeration) */ #define NUMBERS 1 #define REPTYPES 5 /* number of different types of command line reports */ /* */ /* Report current cursor position on the status line. */ /*  */ static void report_position(type, rewrite) int type; boolean rewrite; { cursor(FALSE); if (rewrite) { move(1, width-STATUSWIDTH); blank(STATUSWIDTH); } move(1, width-STATUSWIDTH); switch (type) { case NUMBERS: printf("[ at l %d c %d ]", line_ptr, char_ptr); break; case BARLINE: { long span = next_line*(STATUSWIDTH+1); long at_cursor = line_ptr*STATUSWIDTH; long at_marker = mark_line*STATUSWIDTH; long top = (top_line-1)*STATUSWIDTH; long bottom = bottom_line*STATUSWIDTH; boolean past_cursor = FALSE; boolean past_marker = (at_marker == 0); long i = next_line; while (i < span) { char barbit = BARLINECH; if (i > top) barbit = BARWINDCH; if (i > bottom) barbit = BARLINECH; if ((i > at_marker) && !past_marker) { barbit = BARMARKCH; past_marker = TRUE; } if ((i > at_cursor) && !past_cursor) { barbit = (barbit != BARMARKCH) ? BARCURSCH : BARBOTHCH; past_cursor = TRUE; } fputc(barbit, stdout); i += next_line; } break; } } if (rewrite) { update_screen(); move(1, PROMPTPOS+*temp_buff); /* back to end of command */ } cursor(TRUE); } /* */ /* Report other status information on the status line. Long status messages */ /* may flow over into the text window. In most cases the display will be */ /* refreshed as a result of the command, so this problem is not worth */ /* sweating over. */ /*   */ static void report(form, item) char *form, *item; { cursor(FALSE); move(1, width-STATUSWIDTH); if (*form == '\0') blank(STATUSWIDTH); else printf(form, item); cursor(TRUE); } /* */ /* Find a string in the text buffer from the current cursor position. */ /* */ static boolean findstring(fwd_direction, left_sym, right_sym) boolean fwd_direction; unsigned char *left_sym, *right_sym; { int (*next_position)() = (fwd_direction) ? char_fwd : char_back; int l_sym_len = *left_sym; int r_sym_len = *right_sym; int l_sym_nonsp, r_sym_nonsp, i, match_len, ch; int passed = 0; int search_level = 1; if (r_sym_len == 0) return TRUE; /* null string always works */ strip_spaces(left_sym); l_sym_nonsp = *left_sym; *left_sym = l_sym_len; strip_spaces(right_sym);  r_sym_nonsp = *right_sym; *right_sym = r_sym_len; while ((*next_position)()) { int chars_left = cur_length+1-char_ptr; if (passed++ == SEARCHSPAN) { passed = 0; report_position(BARLINE, TRUE); if (kready()) { flush_input(); /* throw away panic chars */ return FALSE; } } if (chars_left >= l_sym_nonsp) /* check for left symbol */ { match_len = min(l_sym_len, chars_left); if (match_len > 0) for (i = 1; i <= match_len; i++) { if (cur_line[(i-1)+char_ptr] != left_sym[i]) break; if (i == match_len) { search_level++; break; } } } if (chars_left >= r_sym_nonsp) /* check for right symbol */ { match_len = min(r_sym_len, chars_left); for (i = 1; i <= match_len; i++) { if (cur_line[(i-1)+char_ptr] != right_sym[i]) break; if (i == match_len) if (--search_level == 0) return TRUE; /* found the target */ } } } return FALSE; } /* */ /* Calculate and set new left margin, returning change state. */ /* */ static boolean set_left() { int newleft = off_left;  boolean result = FALSE; if ((char_ptr > width+off_left) || (char_ptr <= off_left)) newleft = min(max(0,char_ptr-(width>>1)), MAXLEN-width); result = (newleft != off_left); off_left = newleft; return (result); } /* */ /* Strip leading spaces from a string. */ /* */ static unsigned char *lead_strip(str) unsigned char *str; { slice_out(str, 1, next_printable(str, 1)); return(str); } /* */ /* Command mode command loop. */ /* */ void se_command() { static char rub[] = " \b\b \b"; /* wipes under the cursor as well */ int refresh_needed = FALSE; /* whole page */ int line_refresh = FALSE; /* just current line */ boolean done = FALSE; int prev_top_line = top_line; int relative_to = line_ptr; int offset = 0; int ch; int times_round = 0; boolean get_next_ch; memorise = FALSE; replay = FALSE; cursor(TRUE); while (!done) { move(1, 1); clear_line(); switch (times_round) /* mod REPTYPES */ { case 0: report_position(BARLINE, FALSE); break; case 1: report_position(NUMBERS, FALSE); break; case 2: report("[ from %s ]", infilename); break; case 3: report("[ to %s ]", outfilename); break; case 4: report("[ %s ]", start_message); break; } move(1, 1); printf("Command: "); *temp_buff = 0; *findstr1 = 0; get_next_ch = TRUE; while (get_next_ch) {  update_screen(); ch = rch(); switch (ch) { case k_backsp: if (*temp_buff == 0) continue; (*temp_buff)--; fputs(rub, stdout); continue; case k_newline: if (*lead_strip(temp_buff) == 0) { done = TRUE; break; } { char initial = toupper(temp_buff[1]);  boolean single = (*temp_buff == 1); fputs(" \b", stdout); if (initial > '9') /* not numeric class */ { switch (initial) { case 'E': case 'Q': case 'C': if (single) done = se_exit( ((initial == 'E') || (initial == 'C')), (initial == 'C') ); case 'V': if (single) { done = TRUE; refresh_needed = TRUE; } break; case 'S': if (single) { done = shell_out(); refresh_needed = TRUE; } else { if (toupper(temp_buff[2]) == 'E') { done = ( (*temp_buff > 3) && (temp_buff[3] == ' ') ) ? shell_se(temp_buff, 4) : shell_se(cur_line, char_ptr); refresh_needed = TRUE; } } break; case 'H': initial = '?'; case '?': draw_help(); refresh_needed = TRUE; break;   case 'M': if (single) { next_kbuf = 0; next_key = 1; /* avoid this command */ key_mode = insert_mode; memorise = TRUE; done = TRUE; } break; case '>': case '<': if (single) { int shift = (initial == '>') ? width>>1 : -(width>>1); set_window(line_ptr, char_ptr+shift); off_left = min(max(0, off_left+shift), MAXLEN-width);  done = TRUE; refresh_needed = TRUE; } break; case '=': if (single) { off_left = min(max(0,char_ptr-(width>>1)), MAXLEN-width); set_window(line_ptr, char_ptr); done = TRUE; refresh_needed = TRUE; } break; case 'R': case 'T': if (single) { int old_line_mark = mark_line; int old_char_mark = mark_char;  mark_line = line_ptr; mark_char = char_ptr; if ( (initial == 'R') && (old_line_mark != 0) && (old_char_mark != 0) ) { set_window(old_line_mark, old_char_mark); refresh_needed = set_left() || (top_line != prev_top_line) || refresh_needed; } done = TRUE; } break; } if (done || (initial == '?')) break; else  { fputs("?\b", stdout); bell(); continue; } } /* else command is numeric ... */ relative_to = (isdigit(initial) || (initial == '.')) ? 0 : line_ptr; char_ptr = 1; /* and like k_down ... */ } case k_scroldown: ch = k_down; case k_scrolup: /* scroll same but target line still in centre */ /* to be consistent with command behaviour ... */ case k_up: case k_down: { if (*lead_strip(temp_buff) == 0) line_ptr = (ch == k_up) ? top_line : min(top_line+height-1, next_line); else { offset = strin(temp_buff, LINES); offset = (ch == k_down) ? offset : -offset; set_window(max(offset,relative_to+offset), char_ptr); refresh_needed = set_left() || (top_line != prev_top_line) || refresh_needed; } done = TRUE; break; } case k_tab:  if ((*lead_strip(temp_buff) == 0) && (char_ptr != 1)) do char_ptr--; while ((char_ptr % tabint) != 1); else { char_ptr = (strin(temp_buff, TABS)-1)*tabint+1; char_ptr = max(1, char_ptr); } refresh_needed = set_left() || refresh_needed; done = TRUE; break; case k_left: case k_right: if (*temp_buff == 0) { char_ptr = (ch == k_left) ? 1 : cur_length+1; refresh_needed = set_left() || refresh_needed; done = TRUE; break; } /* else treat as word left/right */ case k_wleft: case k_wright: { int old_line_ptr = line_ptr; int old_char_ptr = char_ptr; if (*temp_buff > 0) { strcopy(temp_buff, findstr2); fputs(" \b", stdout); } else { strcopy(findstr2, temp_buff); fputs(tocstr(temp_buff), stdout); } update_screen(); done = findstring((ch == k_right) || (ch == k_wright), findstr1, findstr2 ); if (done) { set_window(line_ptr, char_ptr); refresh_needed = set_left() || (top_line != prev_top_line) || refresh_needed; break; } line_ptr = old_line_ptr; char_ptr = old_char_ptr; set_current(); report_position(BARLINE, TRUE); fputs("?\b", stdout); bell(); continue; } case k_rstone: { int i; for (i = 1; i <= *temp_buff; i++) fputs(rub, stdout); *temp_buff = 0; *findstr1 = findpair(cur_line, char_ptr); if (*findstr1 == 0) strcopy(findstr2, temp_buff); else  for (i = 1; i <= *findstr1; i++) findstr1[i] = cur_line[char_ptr+i-1]; fputs(tocstr(temp_buff), stdout); continue; } case k_dline: if (!browsing) { int n = strin(lead_strip(temp_buff), LINES); if (filling) /* reverse order delete */ { if (n > 0) { n = min(n, next_line-line_p tr); line_ptr = line_ptr+n; } else n = (n <= -next_line) ? line_ptr-1 : -n; while (n-- > 0) { if (--line_ptr < next_line) pushline(line_ptr); } } else /* delete normally */ { if (n < 0)  { n = min(-n, line_ptr-1); line_ptr = max(1, line_ptr-n); } while (n-- > 0) { if (line_ptr >= next_line) break; pushline(line_ptr); } } } set_window(line_ptr, char_ptr); refresh_needed = TRUE; done = TRUE;  break; case k_dchar: if (!browsing) { int n = strin(lead_strip(temp_buff), CHARS); int lpos, rpos; char_ptr = min(char_ptr, cur_length+1); lpos = (n < 0) ? max(char_ptr+n,1) : char_ptr; rpos = (n < 0) ? char_ptr : char_ptr+n; slice_out(cur_line, lpos, rpos); modified = TRUE;  char_ptr = lpos; refresh_needed = set_left() || refresh_needed; line_refresh = TRUE; } done = TRUE; break; case k_uppage: case k_downpage: { int page_offset = strin(lead_strip(temp_buff), PAGES); offset = (ch == k_downpage) ? page_offset*height : -page_offset*height;  set_window(relative_to+offset, char_ptr); refresh_needed = (top_line != prev_top_line) || refresh_needed; done = TRUE; break; } case k_restore: { int i; if (*temp_buff == 0) { copy(last_infile, temp_buff); fputs(tocstr(temp_buff), stdout); continue; } for (i = 1; i <= *temp_buff; i++) fputs(rub, stdout); if (*lead_strip(temp_buff) == 0) continue; copy(temp_buff, last_infile); switch (read_infile(tocstr(temp_buff), line_ptr)) { case ERR: copy(last_infile, temp_buff); fputs(tocstr(temp_buff), stdout);  fputs("?\b", stdout); bell(); continue; case 0: errmsg("File empty", information); } set_window(line_ptr, char_ptr); refresh_needed = TRUE; done = TRUE; break; } case k_again: if (!browsing) { int n = strin(lead_strip(temp_buff), ABSOLUTE); boolean totag = ((*temp_buff >=1) && (temp_buff[1] == '*')); if (n > 0) { replay = TRUE; report(""); /* wipe status information */ cursor(FALSE); se_screen((totag) ? UPTOTAG : n, k_again); cursor(TRUE); } }  set_window(line_ptr, char_ptr); refresh_needed = TRUE; done = TRUE; break; case k_insert: if ((errorlevel < panic) && (*outfilename != '\0')) { browsing = !browsing; insert_mode = !browsing; } status |= st_change; done = TRUE; break; default:  if ((ch >= ' ') && (ch < 0x7F)) { if (*temp_buff < width-PROMPTPOS-STATUSWIDTH-1) { *char_str = 1; char_str[1] = ch; slice_in(char_str, temp_buff, *temp_buff); putc(ch, stdout); } else bell(); continue; } else { times_round = (++times_round)%REPTYPES; break; } } get_next_ch = FALSE; /* only done on 'break' in case */ } } cursor(FALSE); if (refresh_needed) disp_page(); else if (line_refresh) display_line(line_ptr, 1); } /* */ /* ECS Screen Editor, */ /* J. A. Pickering, Department of Electronics and Computer Science, */ /* (C) Copyright 1987 Southampton University, UK. */ /* */ /* C version : last updated 26-Sep-87 */ /*  */ /* Permission to use and amend the code herein is given on condition: */ /* */ /* (1) That the Department of Electronics and Computer Science, */ /* Southampton University, UK, and the Copyright notice remain in the */ /* code source headers and within the executable code, */ /* */ /* (2) That the editor signon message remains "ECS Screen Editor", */ /* */ /* (3) That copies of the source code OR the executable code so derived */ /* are not sold for gain or profit by any other party except the */ /* Southampton University, UK, or its authorised agents, */ /* */ /* (4) That this copy is used solely by the purchaser on one machine for */ /* generating executable binaries for one type of target machine */ /* operating system. Further copies should be obtained otherwise. */ /* (The amended source may already be available.) */ /* */ /* */ /* Global data declarations herein.   */ /* */ #ifndef MONOLITH #include "sedef.h" #endif int width, /* VDU cols */ depth, /* VDU lines */ line_ptr, /* cursor text line number (1.. ) */ char_ptr, /* cursor character position (1.. ) */ top_line, /* text line number at top of display */ bottom_line, /* text line number at bottom of display */ next_line,  /* next text line number (1 + no_ lines in text) */ mark_line, /* marked text line number */ mark_char, /* marked character position */ tabint, /* tabbing interval */ margin, /* margin for wrap */ off_left, /* columns off to the left of window */ cur_length, /* length of string part of current line */ height, /* height of text display on screen */ status,  /* status line setting */ new_status, /* last status line setting */ errorlevel, /* level of status message */ keybuf[KEYMAX], /* keypress buffer */ next_kbuf, /* next position in keypress buffer */ next_key; /* next key value from buffer */ boolean wrapon, /* wrap flag */ browsing, /* browse mode flag */ insert_mode, /* insert if true, else overwrite chars */ memorise,  /* keypress recording on */ replay, /* replay from key buffer in progress */ key_mode, /* insert mode applicable to keypress buffer */ autoind, /* auto indent on */ filling, /* filling mode */ attn, /* bell the user */ modified; /* file updated flag */ lnode *hold_list, /* held line list entry pointer */ *first_line, /* text line list entry pointer */ *last_line; /* last line list entry pointer */ unsigned char *cur_line, /* string part of current line */ *temp_buff, /* general purpose string work area */ *findstr1, /* left find string */ *findstr2, /* right find string */ *last_infile, /* name of last file read */ *iline, /* initial line number */ *icol, /* initial col number */ char_str[MAXTABINC+1]; /* string version of char(s) */ char *status_msg, /* error message string pointer */ *start_message, /* initial message */ *cgt = "Cursor cannot go there", /* commonly used error message */ *infilename, /* input file name */ *outfilename; /* output file name */ #if HEAPFFRONT unsigned char *buff_hiwater; /* text buffer space space warning threshold */ #endif /* */ /* Header file for ECS Screen Editor, */ /* J. A. Pickering, Department of Electronics and Computer Science, */ /* Copyright (C) 1987 Southampton University, UK. */ /* */ /* C Version : last updated 26-Sep-87 */ /*  */ /* Permission to use and amend the code herein is given on condition: */ /* */ /* (1) That the Department of Electronics and Computer Science, */ /* Southampton University, UK, and the Copyright notice remain in the */ /* code source headers and within the executable code, */ /* */ /* (2) That the editor signon message remains "ECS Screen Editor", */ /* */ /* (3) That copies of the source code OR the executable code so derived */ /* are not sold for gain or profit by any other party except the */ /* Southampton University, UK, or its authorised agents, */ /* */ /* (4) That this copy is used solely by the purchaser on one machine for */ /* generating executable binaries for one type of target machine */ /* operating system. Further copies should be obtained otherwise. */ /* (The amended source may already be available.) */ /* */ /* */ /* External declarations herein.  */ /* */ extern int width, /* terminal cols */ depth, /* terminal lines */ line_ptr, /* cursor text line number (1.. ) */ char_ptr, /* cursor character position (1.. ) */ top_line, /* text line number at top of display */ bottom_line, /* text line number at bottom of display */ next_line, /* next text line number (1 + no_ lines in text) */ mark_line, /* marked text line number */ mark_char, /* marked character position */ tabint, /* tabbing interval */ margin, /* margin for wrap */ off_left, /* columns to the left of window */ cur_length, /* length of string part of current line */ height, /* height of text display on screen */ status, /* status line setting */ new_status, /* last status line setting */ errorlevel, /* level of status message */ keybuf[], /* keypress buffer */ next_kbuf, /* next position in keypress buffer */ next_key; /* next key value from buffer */ extern boolean wrapon, /* wrap flag */ browsing, /* browse mode flag */ insert_mode, /* insert if true, else overwrite chars */ memorise, /* keypress memorise on */  replay, /* keypress buffer replay active */ key_mode, /* insert mode applicable to keypress buffer */ autoind, /* auto indent on */ filling, /* filling mode */ attn, /* bell the user */ modified; /* printable character directed at text buffer */ extern lnode *hold_list, /* held line list entry pointer */ *first_line, /* text line list entry pointer */ *last_line; /* last line list entry pointer */ extern unsigned char *cur_line, /* string part of current line */ *temp_buff, /* general purpose string work area */ *findstr1, /* left find string */ *findstr2, /* right find string */ *last_infile, /* last file name read in */ *iline, *icol, /* initial line and column */ char_str[]; /* short char string */ extern char *status_msg, /* error message string pointer */ *cgt,   /* cursor error message */ *start_message, /* starting message */ *infilename, /* input file name */ *outfilename; /* output file name */ #if HEAPFFRONT extern unsigned char *buff_hiwater; /* warning level in text buffer */ #endif /* SE procedure definitions ... */ #if ANSI /* use prototype declarations */ extern void com_line(int, char * *), set_files(void), draw_help(void), giveup(char *, char *), flush_input(void), clear_line(void), clear_screen(void), scroll_up(int), scroll_down(int), bell(void), move(int, int), emphasise(boolean), cursor(boolean), update_screen(void), strip_spaces(unsigned char *), blank(int), se_screen(int, int), se_command(void), set_current(void), strcopy(unsigned char *, unsigned char *), copy(unsigned char *, unsigned char *), freehold(void),  disp_page(void), display_line(int, int), pushline(int), sc_wrch(unsigned char, int, int), set_window(int, int), errmsg(char *, int), slice_out(unsigned char *, int, int), trm_init(void), mem_init(void), delete(int), fvec(void *), tosestr(char *); extern int stringnumber(char *), rch(void), readline(unsigned char *), read_infile(char *, int), findpair(unsigned char *, int), next_printable(unsigned char *, int), strin(unsigned char *, int), screen_line(int), size(unsigned char *); extern long atol(char *); extern boolean kready(void), shell_out(void), shell_se(unsigned char *, int), char_fwd(void), char_back(void), slice_in(unsigned char *, unsigned char *, int), se_exit(boolean, boolean); extern unsigned char *gvec(int); extern lnode *line(int), *create_lines(int), *insert(unsigned char *, int), *popline(void); extern char *tocstr(unsigned char *); #else /* the compiler will have to cope without parameter information */ extern void com_line(), /* command line parser */ draw_help(), /* get helpfile and display it */ set_files(), /* set up input, output and scratch files */ giveup(), /* error exit */ flush_input(), /* clear input buffer */ clear_line(), /* terminal clear line to space/null */ clear_screen(), /* terminal clear screen to space/null and home */ scroll_up(), /* terminal scroll up one line */ scroll_down(), /* terminal scroll down one line */ bell(), /* terminal sound bell */ move(), /* terminal move cursor to position */ emphasise(), /* terminal switch emphasis on/off */ cursor(), /* terminal switch cursor on/off */ update_screen(), /* force update of terminal screen */  strip_spaces(), /* strip trailing spaces from string */ blank(), /* output a number of spaces */ se_screen(), /* screen editing loop */ se_command(), /* get and do an se command */ set_current(), /* set the current line pointer and length */ strcopy(), /* SE format string copy */ copy(), /* copy string and strip trailing space */ freehold(), /* free held lines */ disp_page(),  /* refresh the text display portion of screen */ display_line(), /* display a line from given character position */ pushline(), /* add a line to the held stack */ sc_wrch(), /* screen writing primitive */ set_window(), /* set current position and set display window */ errmsg(), /* causes message to appear on status line */ slice_out(), /* take out section of string */ trm_init(), /* initialise all to do with terminal */ mem_init(), /* set up text buffer structures */ delete(), /* remove line from buffer */ fvec(), /* return free chunk to text buffer space */ tosestr(); /* convert C string into temp buff in SE format */ extern int stringnumber(), /* similar to atoi for SE format strings */ rch(), /* screen read */ readline(), /* read line into buffer */ read_infile(), /* read input file into text buffer */ findpair(), /* find 'matching bracket' string */ next_printable(), /* scan for next printable in string */ strin(), /* convert string to integer */ screen_line(), /* convert text line number to screen row number */ size(); /* calculates space needed for strg in text buf */ extern long atol(); /* like atoi but returns long */ extern boolean kready(), /* keyboard input available */ shell_out(), /* suspend edit */ shell_se(), /* run another invocation of SE */ char_fwd(), /* move forward one character in text buffer */ char_back(), /* move backward one character in text buffer */ slice_in(), /* slice one string into another */ se_exit(); /* exit file processing */ extern unsigned char *gvec(); /* get a chunk from text buffer space */ extern lnode *line(), /* generates line rec ptr from text line number */ *create_lines(), /* create new lines upto and incl. given line */ *insert(), /* insert string in frnt of given line in buffer */ *popline(); /* used to restore deleted line */ extern char *tocstr(); /* return ptr to a C format string nondestructive*/ #endif /* */ /* ECS Screen Editor, */ /* J. A. Pickering, Department of Electronics and Computer Science, */ /* Copyright (C) 1987 Southampton University, UK. */ /* */ /* C version: Last updated 05-Oct-87 */ /*  */ /* Permission to use and amend the code herein is given on condition: */ /* */ /* (1) That the Department of Electronics and Computer Science, */ /* Southampton University, UK, and the Copyright notice remain in the */ /* code source headers and within the executable code, */ /*  */ /* (2) That the editor signon message remains "ECS Screen Editor", */ /* */ /* (3) That copies of the source code OR the executable code so derived */ /* are not sold for gain or profit by any other party except the */ /* Southampton University, UK, or its authorised agents, */ /* */ /* (4) That this copy is used solely by the purchaser on one machine for */ /* generating executable binaries for one type of target machine */ /* operating system. Further copies should be obtained otherwise. */ /* (The amended source may already be available.) */ /* */ /* */ /* This part contains the low level string and text buffer data structure */ /* handling primitives. */ /* */ #ifndef MONOLITH #include "sedef.h" #include "seext.h" #endif /* */ /* Find the next printable character in the string. */ /* */ int next_printable(str, from) unsigned char *str; int from; { int n = *str; int i = from; if (i > n) return(n+1); while ((i <= n) && (str[i] == ' ')) i++; return i; } /* */ /* Set the current line pointer and the current line length count. */ /* */ void set_current() { lnode *lp = line(line_ptr); cur_line = (lp == NULL) ? NULL : &(lp->line[0]); /* current line string */ cur_length = (lp == NULL) ? 0 : *cur_line; /* and its length */ } /* */ /* Slice out a substring and remove it from a string. */ /* */ void slice_out(str, start, upto) unsigned char *str; int start, upto; { int i, span; upto = min(upto, *str+1); span = upto-start; if (span <= 0) return; for (i = upto ; i <= *str; i++) str[i-span] = str[i]; *str = *str-span; } /* */ /* Set the display window and cursor to be around the given line and column. */ /* */ void set_window(line, col) int line, col; { line_ptr = min(next_line, max(1,line)); top_line = max(1, (line_ptr-(height>>1))); char_ptr = (line_ptr == next_line) ? 1 : max(1, min(col, MAXLEN)); } /* */ /* Create lines between the end of the text and the current line. */ /* */ lnode *create_lines(upto) int upto; { static unsigned char null_str[] = { 0 }; int i; lnode *p; for (i = next_line ; i <= upto; i++) if ((p = insert(null_str, next_line)) == NULL) return NULL; set_current(); return p; } /* */ /* Slice a substring into a string after the given position. */ /* */ boolean slice_in(string, into_string, after) unsigned char *string, *into_string; int after; { int into_len = *into_string; int str_len = *string; int final_len = into_len+str_len; int i; if (final_len > MAXLEN) /* assume max length is possible */ { errmsg("Line would be too long", warning); return FALSE; } if (after > into_len) return TRUE; /* cos its silly */ for (i = into_len; i >= after+1; i--) into_string[str_len+i] = into_string[i]; /* split to make room */ for (i = 1; i <= str_len; i++) into_string[after+i] = string[i]; /* fill in the new space */ *into_string = final_len; return TRUE; } /* */ /* Move current cursor position one character forward. */ /* */ boolean char_fwd() { char_ptr++; while (char_ptr > cur_length) { char_ptr = 1; line_ptr = min(next_line, line_ptr+1); set_current(); if (line_ptr == next_line) return FALSE; /* eof */ } return TRUE; } /* */ /* Move current cursor position one character back. */ /* */ boolean char_back() { char_ptr = min(char_ptr-1, cur_length); while (char_ptr < 1) { line_ptr--; if (line_ptr < 1) { line_ptr = 1; char_ptr = 1; return FALSE; /* sof */ } set_current(); char_ptr = cur_length; } return TRUE; } /*  */ /* Strip trailing spaces from string. */ /* */ void strip_spaces(str) unsigned char *str; { int i = *str; while ((str[i] == ' ') && (i > 0)) i--; *str = i; } /* */ /* Straight string copy; all characters regardless of type. */ /*  */ void strcopy(a, b) unsigned char *a, *b; { unsigned char *lastch = *a+a; while(a <= lastch) *b++ = *a++; } /* */ /* Copy string without trailing space. */ /* */ void copy(a, b) unsigned char *a, *b; { strip_spaces(a); strcopy(a, b); } /*  */ /* Insert string before given line into text buffer. */ /* */ lnode *insert(v, l) unsigned char *v; int l; { lnode *a, *n, *p; a = (lnode *) gvec(size(v)); n = line(l); p = (n == NULL) ? line(l-1) : n->previous; if (a == NULL) { errmsg("Text buffer is full", panic); return NULL; } if (p != NULL) p->next   = a; if (n != NULL) n->previous = a; a->next = n; a->previous = p; copy(v, a->line); if (p == NULL) first_line = a; if (n == NULL) last_line = a; next_line++; if (mark_line >= l) mark_line++; #if HEAPFFRONT if (a > buff_hiwater) errmsg("Text buffer is nearly full", danger); #endif modified = TRUE; return a; } /* */ /* Pop a line from the holding buffer. */ /* */ lnode *popline() { lnode *a; a = hold_list; if (a == NULL) return NULL; hold_list = a->next; return a; } /* */ /* Free off held lines. */ /* */ void freehold() { lnode *a; a = popline(); while (a != NULL) { fvec(a); a = popline(); } } /* */ /* Remove given line from the text buffer. */ /* */ static lnode *takeout(l) int l; { lnode *a, *p, *n; a = line(l); p = (a == NULL) ? NULL : a->previous; n = (a == NULL) ? NULL : a->next; if (p != NULL) p->next = n; else first_line = n; if (n != NULL) n->previous = p; else last_line = p; next_line--; if (mark_line >= l) mark_line--; modified = TRUE; return a; } /* */ /* Delete given line and free off its allocated space. */ /* */ void delete(l) int l; { fvec(takeout(l)); } /* */ /* Push line from text buffer into holding buffer. */ /* */ void pushline(l) int l; { lnode *a; a = takeout(l); a->next = hold_list; hold_list = a; } /* */ /* Find the line node pointer text buffer line number. (SE 'hot spot') */ /* */ lnode *line(n) int n; { lnode *b; int i; if ((n < 1) || (n >= next_line)) return NULL; if (n < (next_line>>1)) /* search from front */ { b = first_line; for (i = 2; i <= n; i++) b = b->next; } else /* search from back */ { b = last_line; for (i = next_line-2; i >= n; i--) b = b->previous; } return b; } /*  */ /* Find the screen line number of the given text buffer line number. */ /* */ int screen_line(n) int n; { return(n-top_line+screen_start); /* allow for command line */ } /* */ /* Set the error message and error level. */ /*  */ void errmsg(message, level) char *message; int level; { if (level >= errorlevel) { status_msg = message; errorlevel = level; attn = (level >= warning); /* bell the user if appl. */ } } /* */ /* Convert SE string to integer. */ /*  */ int stringnumber(str) unsigned char *str; { return (int) atol(tocstr(str)); } /* */ /* Convert SE string to integer incorporating special number symbols. */ /* */ int strin(str, context) unsigned char *str; int context; { char ch1 = (*str > 0) ? str[1] : '0'; int i, range, minima; int sign = 1; switch (context) {  case CHARS: range = cur_length+1; minima = -char_ptr; break; case TABS: range = MAXLEN/tabint+1; minima = 0; break; case LINES: range = next_line; minima = -line_ptr; break; case PAGES: range = next_line/height+1; minima = -line_ptr/height; break; default: /* ABSOLUTE etc. */ range = maxint; minima = -maxint; break; } if ( (*str == 1) && ((ch1 == '-') || (ch1 == '.') || (ch1 == '+')) ) return( (ch1 == '-') ? minima : range ); if (ch1 == '*') { i = mark_line-line_ptr; switch (context) { case CHARS: return( (mark_line == line_ptr) ? mark_char-char_ptr : 0 ); case ABSOLUTE: return( max(0, i) ); case LINES: return( (mark_line == 0) ? 0 : i ); default: return 0; } } if (ch1 == '-') { sign = -1; if ((*str > 2) && (str[2] == '.')) slice_out(str, 1, 2); ch1 = str[1]; } if ( (*str > 1) && (ch1 == '.') ) { int p = 10; strip_spaces(str); slice_out(str, 1, 2); for (i = 1; i < *str; i++) p *= 10; return ( sign*(int)(((long)range*(long)stringnumber(str))/(long)p) ); } i = stringnumber(str); if ((context == ABSOLUTE) && (i < 0)) i = -i; return (min(max(i,minima),range)); } /* */ /* Convert SE string to ASCIIZ (C) format. */ /* */ char *tocstr(str) unsigned char *str; { str[*str+1] = '\0'; return (char *) &str[1]; } /* */ /* Convert ASCIIZ (C) string to SE format (uses temporary buffer for result) */ /* */ void tosestr(cstr) /* using temp buffer for result */ char *cstr; { int i; for (i = 0; cstr[i] != '\0'; i++) temp_buff[i+1] = cstr[i]; *temp_buff = i; } /* */ /* ECS Screen Editor, */ /* J. A. Pickering, Department of Electronics and Computer Science, */ /* (C) Copyright 1987 Southampton University, UK. */ /* */ /* C version : Last updated 28-Sep-87. */ /*    */ /* Permission to use and amend the code herein is given on condition: */ /* */ /* (1) That the Department of Electronics and Computer Science, */ /* Southampton University, UK, and the Copyright notice remain in the */ /* code source headers and within the executable code, */ /* */ /* (2) That the editor signon message remains "ECS Screen Editor", */ /* */ /* (3) That copies of the source code OR the executable code so derived */ /* are not sold for gain or profit by any other party except the */ /* Southampton University, UK, or its authorised agents, */ /* */ /* (4) That this copy is used solely by the purchaser on one machine for */ /* generating executable binaries for one type of target machine */ /* operating system. Further copies should be obtained otherwise. */ /* (The amended source may already be available.) */ /* */ /* */ /* This part contains the machine environment dependent bits -  */ /* file IO, screen handling, dynamic memory management and shelling out. */ /* */ /* Version for Cromemco CROMIX-Plus using termcap entries for terminals. */ /* */ #ifndef MONOLITH #segment SEIO #include "sedef.h" #include "seext.h" #endif #define FREECHECK TRUE /* check for NULL disposes in fvec() */ #include /* CROMIX system call define files */ #include #include "seiocrx.d" /* CROMIX dependent data structures */ static FILE *infile = NULL, /* general purpose file descriptors */ *ofile = NULL; static char *cow = "Cannot open workfile %s\r\n", *termid = "null", /* must be 4 or more chars */ helpfilename[PATHLEN] = "", *holdfile = HOLDFILE, *workfilename, *tobak, *bakfilename, *reserve; /* reserved space on heap to ensure safe exit */ static char clrl[TCLEN], /* filled by entries from termcaps */ dlin[TCLEN] = "", /* (non-initialised capabilities are essential) */ insl[TCLEN] = "", clrs[TCLEN], curo[TCLEN] = "", curf[TCLEN] = "", emon[TCLEN] = "", emof[TCLEN] = "", curr[TCLEN] = "", curs[LTCLEN], tset[LTCLEN] = "", kset[LTCLEN] = "", kres[LTCLEN] = ""; static boolean trmwrap, hardwrap; /* whether terminal automatically wraps */ static int attrib_chars = 0; /* char positions used up by attributes */ static int omode1, omode2, omode3; /* prior terminal modes */ static boolean saved = FALSE; /* whether a continue save has taken place */ /* */ /* ASCIIZ to long integer conversion (for those that don't have one). */ /* */ long atol(s) char *s; { int i, n, sign; for (i = 0; isspace(s[i]); i++) ; sign = 1; if (s[i] == '+' || s[i] == '-') sign = (s[i++] == '+') ? 1 : -1; for (n = 0; isdigit(s[i]); i++) n = 10*n+(s[i]-'0'); return (sign*n); } /* */ /* Library routine Strlen (absent in SVS C !!) */ /* */ static int strlen(str) char *str; { int n; for (n = 0; *str != '\0'; str++) n++; return n; } /* */ /* String match C strings. Returns 0 : s1 = s2 */ /* 1 : s1 is a prefix of s2 */ /* -1 : s2 is a prefix of s1 */ /* */ static int strmatch(s1, s2) char *s1, *s2; { while (*s1 == *s2) { if (*s1 == '\0') return 0; s1++; s2++; } return ((*s1 == '\0') ? 1 : -1); } /* */ /* Find the matching pair for 'bracket matching' searches. Returns the */ /* pair in the temporary buffer with the value of the number of characters */ /* from the input line that were matched to find it. Uses minimum number */ /* of characters and delivers the first found in the pair table. Nil string */ /* and a zero result are returned if nothing is found. */ /* */ int findpair(line, at) unsigned char *line; int at; { int chars_left = *line-at; int i; *temp_buff = 0; *char_str = 1; while (chars_left >= 0) { boolean isprefix = FALSE; char_str[1] = line[at++]; slice_in(char_str, temp_buff, *temp_buff); for (i = 0; (pairs[i] != NULL); i++) { int matchlen = *temp_buff; switch (strmatch(tocstr(temp_buff), pairs[i])) { case 0: tosestr(pairs[i^1]); /* found it */ return(matchlen); case -1: continue; /* look for more */ case 1: isprefix = TRUE; } break; } if (!isprefix) { *temp_buff = 0; /* no prefixes so abort */ return(0); } chars_left--; } return(0); } /*---------------------------------------------------------------------------*/ /* */ /* Free space (heap) management routines. Use the system free space */ /* or implement your own. If a 'first fit' algorithm is used then it is */ /* possible to issue a meaningful 'Text buffer nearly full' message (see */ /* limits in header).  */ /* */ void mem_init() { reserve = (char *) malloc(BUFSIZ); /* to ensure that file IO works */ #if HEAPFFRONT /* when heap full */ buffer_size = maxmem; buffer_base = (unsigned char *) malloc(1); buff_hiwater = buffer_base+buffer_size-headroom; #endif } int size(v) unsigned char *v; { return( *v+1+sizeof(lnode *)+sizeof(lnode *) ); } unsigned char *gvec(n) int n; { return( (unsigned char *) malloc(n) ); } void fvec(v) unsigned char *v; { #if FREECHECK if (v == NULL) errmsg("SE: free error", warning); else #endif free(v); } static void free_mem() { /* resetmem(); is not necessary in Cromix */ } /*---------------------------------------------------------------------------*/ /* */ /* Set terminal driver mode(s). Runs terminal as 'raw  -./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijk' as possible. If */ /* required to it also saves the previous mode settings for subsequent */ /* restore on shelling or leaving editor. Also switches off SE's response */ /* to signals. */ /* */ static void set_modes(saveold) boolean saveold; { int mode3val = (strmatch(termid, "3102") == 0) ? FNKEYS : BINARY; if (saveold)  /* cant switch 3102 to binary */ { omode1 = getmode(STDIN, MD_MODE1); /* because of function keys */ omode2 = getmode(STDIN, MD_MODE2); omode3 = setmode(STDIN, MD_MODE3); signal(sigabort, 1L); signal(siguser, 1L); } setmode(STDIN, MD_MODE1, RAW, RAW|ECHO|LCASE|CRDEVICE|XTAB ); setmode(STDIN, MD_MODE2, 0, ABENABLE|SGENABLE|XFF|SIGALLC ); setmode(STDIN, MD_MODE3, mode3val,  FNKEYS|BINARY ); } /* */ /* Reset terminal driver mode(s). Restores settings as saved by the mode */ /* setting routine. */ /* */ static void res_modes() { setmode(STDIN, MD_MODE1, omode1, RAW|ECHO|LCASE|CRDEVICE|XTAB ); setmode(STDIN, MD_MODE2, omode2, ABENABLE|SGENABLE|XFF|SIGALLC ); setmode(STDIN, MD_MODE3, omode3, FNKEYS|BINARY ); } /*---------------------------------------------------------------------------*/ /* */ /* Leaving the editor. */ /* */ static void leave_se(result) int result; { free_mem(); trm_reset(); res_modes(); exit(result); } void giveup(str1, str2) char *str1, *str2; { fprintf(stderr, str1, str2); leave_se(ERR); } /*---------------------------------------------------------------------------*/ /* */ /* File IO routines ... */ /* */ /* */ /* Test that a file exists and is ordinary. */ /* */ static boolean a_file(fn) char *fn; { return ( (fstat(fn, st_ftype) == is_ordin) ? TRUE : FALSE ); } /* */ /* Test that a file path exists. */ /* */ static boolean exists(fn) char *fn; { return ( (fstat(fn, st_ftype) != ERR) ? TRUE : FALSE ); } /* */ /* Test whether a file is a device file. */ /* */ static boolean a_device(fn) char *fn; { return ( (fstat(fn, st_ftype) == is_char) ? TRUE : FALSE ); } /* */ /* Save holding buffer. Writes the holding buffer lines to a file for the */ /* next level of SE to pick up. If filling mode is in force then the file */ /* position of the input file is appended also. */ /* */ static void save_hold() { FILE *se_hld; fvec(reserve); se_hld = fopen(holdfile, "w"); if (se_hld != NULL) { lnode *top_held_list = hold_list; while (hold_list != NULL) { unsigned char *p = &(popline()->line[0]); unsigned char *pmax = p+*p; p++; while (p <= pmax) fputc(*p++, se_hld); fputc('\n', se_hld); } hold_list = top_held_list; if (filling) fprintf(se_hld, "%ld", ftell(infile)); fclose(se_hld); } else errmsg(cow, warning); reserve = (char *) gvec(BUFSIZ); } /*  */ /* Get the holding buffer from the SE communication file. Uses the standard */ /* buffer filling routine and switches the buffer pointers. If filling mode */ /* is in force then the input file pointer is repositioned. */ /* */ static void get_hold() { lnode *old_first_line = first_line; lnode *old_last_line = last_line; int old_next_line = next_line; int old_line_ptr = line_ptr; int old_mark_line = mark_line; if (exists(holdfile)) { first_line = NULL; next_line = 1; line_ptr = 1; mark_line = 0; freehold(); read_infile(holdfile, 1); hold_list = first_line; mark_line = old_mark_line; line_ptr = old_line_ptr; next_line = old_next_line; last_line = old_last_line; first_line = old_first_line; if (filling) fseek(infile, atol(tocstr(temp_buff)), 0); } } /*  */ /* Set up the back file and work file names and check that the workfile */ /* can be created. Read the file into the text buffer. */ /* */ void set_files() { int out; char *inputfile = NULL; tobak = NULL; if (a_file(infilename)) { if (!browsing) /* set up the rest of the file names */ { inputfile = infilename;  if (outfilename == NULL) { tobak = infilename; outfilename = infilename; } else { if (a_file(outfilename)) tobak = outfilename; } if (tobak == NULL) bakfilename = NULL; else { int i; bakfilename = (char *) gvec(strlen(tobak)+*b_extn+2); tosestr(tobak); *bakfilename = 0; /* (string processing in SE format) */ slice_in(temp_buff, bakfilename, 0); for (i = *bakfilename; (i > 0) && (bakfilename[i] != '/'); i--) ; /* find filename element */ slice_in(b_extn, bakfilename, min(*bakfilename, i+MAXFL-2)); *bakfilename = min(*bakfilename, i+MAXFL); bakfilename = tocstr(bakfilename); } } else /* browse mode */ { inputfile = infilename; outfilename = ""; /* second f  ilename is ignored */ } } else /* infile does not exist or not ordinary */ { if (exists(infilename) || (outfilename != NULL) || browsing) giveup("File %s cannot be accessed.\r\n", infilename); outfilename = infilename; tobak = NULL; } if (!browsing) { if (a_device(outfilename)) workfilename = outfilename; else { int i; workfilename = (char *) gvec(strlen(outfilename)+*w_extn+2); *workfilename = 0; tosestr(outfilename); slice_in(temp_buff, workfilename, 0); for (i = *workfilename; (i > 0) && (workfilename[i] != '/'); i--) ; /* find filename element */ slice_in(w_extn, workfilename, min(*workfilename, i+MAXFL-2)); *workfilename = min(*workfilename, i+MAXFL); workfilename = tocstr(workfilename); if (exists(workfilename) || ((out = creat(workfilename, 0)) == ERR)) giveup(cow, workfilename); close(out); } } if (inputfile == NULL) errmsg("New file", information); else { if (filling) infile = fopen(inputfile, "r"); else { switch (read_infile(inputfile, 1)) { case ERR: giveup("File %s cannot be read.\r\n", inputfile); case 0: errmsg("File empty", information); default: tosestr(inputfile); copy(temp_buff, last_infile); } } } get_hold(); } /* */ /* Places the next line of data from the input file into a buffer */ /* */ int readline(v) /* reads into (buffer address) */ unsigned char *v; { int p = 0; int get_next_ch = TRUE; while (get_next_ch && (p < 255)) { int ch = fgetc(infile); ch = (ch == EOF) ? ch : ch & 0x7F; /* strip b7.. */ switch (ch) { case '\n': break; case '\t': v[++p] = ' '; /* expand tabs */ while (((p % tabint) != 0) && (p < 255)) v[++p] = ' '; continue; case EOF: *v = p; /* define length so far but ... */ return ERR; /* because incomplete lines are not allowed */ default: if (ch < ' ')  continue; /* throw away control chars */ v[++p] = ch; continue; } get_next_ch = FALSE; } if (p == 255) errmsg("Long lines wrapped", warning); *v = p; return p; } /* */ /* Read a file into the text buffer starting at a given line position. */ /* If the file name is specified then the whole file is read, otherwise */ /* just the next line of the file infile is read. */ /* */ int read_infile(fn, position) char *fn; int position; { int new_position = position; int result = 0; int n = 0; FILE *last_infile = infile; if (fn != NULL) { infile = fopen(fn, "r"); if (infile != NULL) { printf("Reading %s ", fn); update_screen(); create_lines(line_ptr-1); while (TRUE)  { int chars_read = readline(temp_buff); if (chars_read == ERR) break; if ((n += chars_read) > FILESPAN) { n -= FILESPAN; fputc('.', stdout); update_screen(); } if (insert(temp_buff, new_position) == NULL) break; new_position++; } result = new_position-position; fclose(infile); } else result = ERR; } infile = last_infile; return (result); } /* */ /* Perform the exit operations, writing the text buffer to the workfile */ /* and performing the renaming and deleting operations as appropriate. */ /* If a quit is requested then no writing occurs. The routine terminates */ /* the editing session unless go back is requested. */ /*  */ boolean se_exit(with_writing, goback) boolean with_writing, goback; { int i, len; int n = 0; boolean with_ret = (boolean) options[CRET].arg; unsigned char *p, *pmax; clear_screen(); move(1, 1); if ((boolean) options[BROWSE].arg) { if (goback) return FALSE; else { printf("Finished browsing file %s\r\n", infilename); leave_se(0); } } if (with_writing) { fvec(reserve); ofile = fopen(workfilename, "w"); if (ofile != NULL) { lnode *this_line = first_line; printf("Writing file "); update_screen(); while (this_line != NULL) { p = &(this_line->line[0]); pmax = *p+p; len = *p; p++; while (p <= pmax) fputc(*p++, ofile); if (with_ret) { fputc('\r', ofile); len++; }  fputc('\n', ofile); if ((n += ++len) > FILESPAN) { n -= FILESPAN; fputc('.', stdout); update_screen(); } this_line = this_line->next; } clear_line(); printf("Written file "); fclose(ofile); saved = TRUE; } else { printf(cow, workfilename); return FALSE; /* user might have some bright ideas what to do! */ } reserve = (char *) gvec(BUFSIZ); if (goback) { save_hold(); update(); /* as continuing tends to indicate a flaky system */ return TRUE; } else { int result = 0; if (options[STMESSG].arg == NULL) unlink(holdfile); else save_hold(); if (tobak != NULL) { unlink(bakfilename); result = flink(tobak, bakfilename);  if (!result) unlink(tobak); } if (workfilename != outfilename) { result |= flink(workfilename, outfilename); if (result) printf("but cannot rename files.\r\n"); else { unlink(workfilename); printf("%s\r\n", outfilename); } } else printf("%s\r\n", outfilename); } } else { int ch; if (modified) { printf("File %s has been modified, sure? [Y/N] ", outfilename); update_screen(); ch = rch(); if (toupper(ch) != 'Y') return FALSE; clear_line(); } if (options[STMESSG].arg == NULL) unlink(holdfile); if (workfilename != outfilename) /* not a device file */ { if (saved) { printf("The last save is in file %s, keep it? [Y/N] ",    workfilename); update_screen(); ch = rch(); if (toupper(ch) == 'N') { clear_line(); unlink(workfilename); } else printf("%c\r\nN.B. Delete it or rename it NOW.\r\n", ch); } else unlink(workfilename); } printf("Aborted, file %s not written.\r\n", outfilename); }  leave_se(0); } /* */ /* Draw a screenful of help information. Reads the helpfile given for the */ /* particular terminal in use. If this does not exist or cannot be found */ /* 'bare' help is given. */ /* */ void draw_help() { char *hfile = (helpfilename[0] == '\0') ? DEFHELPFILE : helpfilename; FILE *f = fopen(hfile, "r"); clear_screen(); move(screen_start, 1); if (f != NULL) { while (fgets(temp_buff, 255, f) != NULL) { fputs(temp_buff, stdout); fputc('\r',stdout); } fclose(f); } else { move(3, PROMPTPOS); fputs("E to exit", stdout); move(4, PROMPTPOS); fputs("Q to quit", stdout); move(5, PROMPTPOS); fputs(" to continue editing", stdout); move(7, 1);  printf("[ Helpfile %s is not available ]", hfile); } } /*---------------------------------------------------------------------------*/ /* */ /* Parse the invocation command line. Matches the arguments and options */ /* supplied and modifies and adds to the options data structure. */ /* */ static int parse_opt(opt, nopt, argv, argc) oprec *opt; int nopt; char **argv; int argc; { int i = 1; int j; char c, *p; boolean single; while (i <= argc-1) { while ((p = argv[i]) && (*p++ == '-') && *p) { i++; single = (p[1] == '\0'); while (c = *p++) { c = tolower(c); for (j = 0; opt[j].id != c; j++) if (opt[j].id == '\0') return ERR; if (opt[j].swtch) opt[j].arg = (char *)!((boolean)opt[j].arg); /* Ugh! */ else { if (!single || (argv[i] == NULL)) return ERR; opt[j].arg = argv[i++]; } } } for (j = 0; ((opt[j].id != '\0') || (opt[j].arg != NULL)) && (j < nopt) ; j++); if (j < nopt) opt[j].arg = argv[i]; i++; } return 0; } /* */ /* Invocation command line analyser. Checks the number of arguments are */ /* sensible, parses them and sets editor values accordingly. */ /* */ void com_line(argc, argv) int argc; char **argv; { if ((argc == 1) || (parse_opt(options, NARGS, argv, argc) == ERR)) giveup(usg1, usg2); autoind = (boolean) options[AUTO].arg; wrapon = (boolean) options[WRAP].arg; tabint = min(atol(options[TABINC].arg), MAXTABINC); filling = (boolean) options[FILL].arg; browsing = (boolean) options[BROWSE].arg; tosestr(options[STLINE].arg); iline = gvec(*temp_buff+1); *iline = 0; slice_in(temp_buff, iline, 0); tosestr(options[STCOL].arg); icol = gvec(*temp_buff+1); *icol = 0; slice_in(temp_buff, icol, 0); if (options[STMESSG].arg != NULL) { errmsg(options[STMESSG].arg, information); start_message = options[STMESSG].arg; } else start_message = ""; if ((infilename = options[INFILE].arg) == NULL) giveup(usg1, usg2); outfilename = options[OUTFILE].arg; return; } /*---------------------------------------------------------------------------*/ /* */ /* Shell creation. Entered when the shell command given in command mode */ /* and returns once shell exited. Returns TRUE if shell was successful */ /* and screen needs redrawing. If shell is not implemented should return */ /* FALSE. */ /* */ boolean shell_out() { static char *arg[] = { "shell", "-z", NULL }; int states[2]; int procid = fshell(arg, SIGTERM|SIGUSER|SIGABORT, SIGUSER|SIGABORT); if (procid > 0) { clear_screen(); printf("Exit to resume edit.\r\n"); update_screen(); res_modes(); wait(0, procid, states); set_modes(FALSE); trm_set(); } return (procid > 0); } /* */ /* Check for a legal character in a filename. */ /* */ static boolean legal(ch) char ch; { char *p = "_.$/^"; if (isalpha(ch) || isdigit(ch)) return TRUE; while (*p) if (*p++ == ch) return TRUE;  return FALSE; } /* */ /* Shell another invocation of SE. Similar to shell_out except that another */ /* copy of SE is run from the current one. The filename used is cleaned up */ /* for use as an argument for the next invocation. The new SE inherits the */ /* same format settings as the current one. */ /* */ boolean shell_se(line, at) unsigned char *line; int at; { static char *args[] = { "sh", "-p", "se", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; int procid = 0; int states[2]; oprec *op; int i = 3; char *p1 = (char *) gvec(120); char *p = p1; if (p == NULL) return(FALSE); for (op = options; op->id != 0; op++) { if (!(op->swtch & !op->arg)) { args[i++] = p; *p++ = '-'; *p++ = op->id; *p++ = '\0'; } if (!op->swtch) { switch (op->id) { case 'm': /* generate message */ { char *q = "Within "; args[i++] = p; for ( ; *q != '\0'; *p++ = *q++) ; for (q = infilename; *q != '\0'; *p++ = *q++) ; *p++ = '\0'; break; } case 'l': /* these aren't inherited, */ case 'c': i--; break; default: /* the rest are ... */ args[i++] = op->arg; } } } if (filling && !browsing) args[i++] = infilename; args[i++] = p; while ((at <= *line) && (line[at] != ' ')) /* up to end of word */ { char c = (char) line[at++]; if (legal(c)) *p++ = c; } *p++ = '\0'; args[i] = NULL; save_hol  d(); procid = fshell(args, SIGTERM|SIGUSER|SIGABORT, SIGUSER|SIGABORT); if (procid >= 0) { clear_screen(); res_modes(); wait(0, procid, states); set_modes(FALSE); trm_set(); if (states[0] == ERR) errmsg("Could not start new SE", warning); get_hold(); } fvec(p1); return (procid > 0); } /*---------------------------------------------------------------------------*/ /*  */ /* Terminal intialisation. Top level routine responsible for initialising */ /* the terminal driver and the terminal itself. Collects the terminal id */ /* for the sign-on message and all the terminal control strings for input */ /* (key 'bindings') and output (display and cursor control). */ /* */ void trm_init() { int i, tchan; char *term_entry = (char *) gvec(TCSIZE); matchentry *mtp; union { int _int; char _str[4]; } uterm; uterm._int = ustat(0, usr_term); for (i = 0; i <= 3; i++) termid[i] = uterm._str[i]; set_modes(TRUE); printf(logon_form, header.logon, termid, copyrite); update_screen(); tchan = open(TCAPFILE, 0); if ((tchan == ERR) || (tgread(tchan, term_entry, TCSIZE) != 0)) giveup("\r\nCannot get termcap entry for %s.\r\n", termid); close(tchan); width = tgnum(term_entry, "co"); depth = tgnum(term_entry, "li"); hardwrap = tgbool(term_entry, "am"); if ( (tgstr(term_entry, "ce", clrl, TCLEN) | tgstr(term_entry, "cl", clrs, TCLEN) | tgstr(term_entry, "cm", curs, LTCLEN)) == ERR ) giveup("\r\nTerminal %s has insufficient capabilities.\r\n",termid); if ( ((tgstr(term_entry, "al", insl, TCLEN) | tgstr(term_entry, "dl", dlin, TCLEN)) == ERR ) && hardwrap) { width--; /* cannot use full width without insl/dlin */ trmwrap = FALSE;  } else trmwrap = hardwrap; for (mtp = matchtab; mtp->tc[0] == 'k'; mtp++) tgstr(term_entry, mtp->tc, mtp->termstr, TCLEN); tchan = open(SETCAPFILE, 0); if ((tchan != ERR) && (tgread(tchan, term_entry, TCSIZE) == 0)) { close(tchan); if (*term_entry != '\0') { tgstr(term_entry, "hf", helpfilename, PATHLEN); tgstr(term_entry, "ks", kset, LTCLEN); tgstr(term_entry, "ke", kres, LTCLEN); tgstr(term_entry, "is", tset, LTCLEN); tgstr(term_entry, "oc", curo, TCLEN); tgstr(term_entry, "fc", curf, TCLEN); tgstr(term_entry, "so", emon, TCLEN); tgstr(term_entry, "se", emof, TCLEN); if ((attrib_chars = tgnum(term_entry, "sg")) != 0) tgstr(term_entry, "nd", curr, TCLEN); for ( ; mtp->secode != 0; mtp++) /* after the k.. ones onwards */ tgstr(term_entry, mtp->tc, mtp->termstr, TCLEN); } } trm_set(); fvec(term_entry); } /*---------------------------------------------------------------------------*/ /* */ /* Read next input from terminal. Returns internal SE code corresponding */ /* to the character sequence received. */ /* */ int rch() { char instr[TCLEN]; char *ip = instr; matchentry *mtp; int len = 0; while (len < TCLEN) { boolean isprefix = FALSE; *ip++ = rdbyte(STDIN) & 0x7F; *ip = '\0'; len++; for (mtp = matchtab; mtp->secode != 0; mtp++) { switch (strmatch(instr, mtp->termstr)) { case 0: return mtp->secode; case -1: continue; /* matching */ case 1: isprefix = TRUE; } break; /* matching */ } if (!isprefix)  { if (len > 1) return k_error; /* bad prefix */ else return instr[0]; } } return k_error; } /* */ /* Keyboard input available. Returns true if a key has been pressed and is */ /* waiting in the system's buffer to be read. (Used by screen loop when */ /* repeat replaying and enables user to abort loop by pressing any key.) */ /*  */ boolean kready() { return( (getmode(STDIN, MD_STATUS) == INOTEMPTY) ? TRUE : FALSE ); } /* */ /* Flush input buffer of waiting characters. */ /* */ void flush_input() { int ch; while (kready()) ch = rch(); } /*---------------------------------------------------------------------------*/ /* */ /* Screen control primitives. All display output in screen editing mode */ /* is performed using combinations of the following routines finishing with */ /* update_screen before stopping for further user input. */ /* */ void blank(n) /* only used in contexts where no danger of hardwrap */ int n; { int i; for (i = 1; i <= n; i++) fputc(' ', stdout); } void clear_line() /* simulation using blank is definitely not recommended! */ { printf("\r%s", clrl); /* note ensures cursor at column 1 afterwards */ } void scroll_up(at_line) int at_line; { if (*dlin == '\0') /* do a soft scroll */ { int i, first_row, last_row; if ( hardwrap && (at_line < (depth>>1)) ) { move(screen_start, 1); clear_line(); move(depth, width); blank(2); /* induce scrolling of whole page */ first_row = top_line; /* rewrite TOP lines */ last_row = top_line+at_line-screen_start-1; status |= st_change; } else { first_row = top_line+at_line-screen_start; last_row = top_line+height-2; } for ( i = first_row; i <= last_row; i++) display_line(i, 1); } else /* hardware scroll */ { move(at_line, 1); fputs(dlin, stdout); } } void scroll_down(at_line) int at_line; { move(at_line, 1); if (*insl == '\0') /* do a soft scroll */ { int i = top_line+at_line-screen_start; /* write top line early */ clear_line(); for ( ; i <= top_line+height-1; i++) display_line(i, 1); } else /* hardware scroll */ fputs(insl, stdout); } void bell() { fputc('\007', stdout); } void move(line, col) /* it is assumed that writing occurs */ /* implicitly to the left of the cursor */ int line, col; { static char curstr[LTCLEN]; int v_l = line-1; int v_c = (line >= screen_start) ? col-off_left-1 : col-1; tprint(curstr, curs, v_l, max(0,v_c)); /* note conversion from SE 'natural' */ fputs(curstr, stdout); /* numbering for columns and lines */ } void clear_screen() { fputs(clrs, stdout); } void trm_set() { fputs(tset, stdout); fputs(kset, stdout); } void trm_reset() { fput  s(kres, stdout); } void emphasise(on) boolean on; { int i; if (!on) for (i = 1; i <= attrib_chars; i++) fputs( curr, stdout); fputs( (on ? emon : emof), stdout); } void cursor(on) boolean on; { fputs( (on ? curo : curf), stdout); } void update_screen() { fflush(stdout); } void disp_page() { int i; for (i = top_line; i <= top_line+height-1; i++) display_line(i, 1); } void display_line(n, from) int n, from; { lnode *p; int i, s; int rmargin = width+off_left; int leftstart = max(from, off_left+1); p = line(n); s = screen_line(n); move(s, from); if (from == 1) clear_line(); if (p != NULL) /* for (i = from ; i <= p->line[0]; i++) */ /* sc_wrch(p->line[i], s, i); */ /* The following alternative simulates the above lines but does it in */ /* mostly one system call. This SIGNIFICANTLY enhaces the response of the */ /* editor. */ { int nchars = min(p->line[0], rmargin)-leftstart+1; fflush(stdout); /* make sure buffered IO clear */ if (nchars > 0) wrseq(STDOUT, &(p->line[leftstart]), nchars); } if ((p->line[0] >= rmargin) && (s == depth) && trmwrap) { wrbyte(STDOUT, p->line[rmargin]); wrbyte(STDOUT, ' '); scroll_down(1); status |= st_change; } } void sc_wrch(ch, atline, atcol) unsigned char ch; int atline, atcol; { int rmargin = width+off_left; if ( ((atcol > off_left) && (atcol < rmargin)) || ((atcol == rmargin) && (atline != depth)) ) { fputc(ch, stdout); return; } if ((atcol > rmargin) || !trmwrap) return; fputc(ch, stdout); fputc(' ', stdout); /* force even a vt100 to really wrap */ scroll_down(1); /* then do screen fixup assuming wrap */ status |= st_change; } /* * CROMIX dependent data structures for SE ... * * Last updated: (see header message below) * */ #define TCAPFILE "/etc/termcaps" /* basic termcap file */ #define SETCAPFILE "/etc/setermcaps" /* SE termcap file */ #define HOLDFILE "se.hld" /* intermediate hold file */ #define DEFHELPFILE "/etc/se.hlp" /* default help file */ #define PATHLEN 32 /* helpfile filename max */ #define TCSIZE 1024 /* max termcap entry size */ #define TCLEN 8 /* short termcap string */ #define LTCLEN 16 /* long termcap string */ #define MAXFL 24 /* max file string length */ #define AUTO 0 /* argument order in */ #define WRAP 1 /* option structure */ #define TABINC 2 #define STLINE 3 #define STCOL 4 #define STMESSG 5 #define CRET 6 #define FILL 7 #define BROWSE 8 #define INFILE 9 #define OUTFILE 10 #define NARGS 11 /* number of arguments */ typedef struct _header { char magicnos[8]; char version; char release; char logon[50]; }; static struct _header header = { 0xfd, 0xed, 0xfd, 0xed, 0, 0, 0, 0, 1, 1, "ECS Screen Editor, 05-Oct-87. " }; static char *copyrite = "Copyright (C) 1987, Southampton University, UK."; static char *logon_form = "%s(%s)\r\n"; /* logon, termid, copyrite */ typedef struct { char id; /* option letter id */ boolean swtch; /* switch (T) or value must follow (F) */ char *arg /* actual or default value */ } oprec; static oprec options[] = { /* # desc. */ { 'a', TRUE, FALSE}, /* 0 auto indent */ { 'w', TRUE, FALSE}, /* 1 wrap */ { 't', FALSE, "8" }, /* 2 tab interval */ { 'l', FALSE, "1" }, /* 3 start at line */ { 'c', FALSE, "1" }, /* 4 start at column */ { 'm', FALSE, NULL}, /* 5 start up message */ { 'r', TRUE, FALSE}, /* 6 add returns on output */ { 'f', TRUE, FALSE}, /* 7 fill */ { 'b', TRUE, FALSE}, /* 8 browse mode */ { 0, 0, NULL}, /* 9 infile */ { 0, 0, NULL}, /* 10 outfile */ { 0, 0, 0,} }; static char *usg1 = "SE usage:\r\n %s\r\n", *usg2 = "se [-abfrw] [-t #] [-l #] [-c #] [-m msg] infile [outfile]"; typedef struct { int secode; /* SE opcode */ char tc[3]; /* termcap/se mnemonic */ char termstr[TCLEN]; /* actual code emitted by terminal */ } matchentry; static matchentry matchtab[] = { { k_help, "kh", ""}, /* termcap k.. flavoured codes */ { k_up, "ku", ""}, { k_down, "kd", ""}, { k_right, "kr", ""}, { k_left, "kl", ""}, { k_help, "ch", ""}, /* SE termcap codes. */ { k_backsp, "bd", ""}, /* Note that these are from a separate */ { k_insert, "in", ""}, /* vocabulary of mnemonics from termcap. */ { k_restore, "ra", ""}, { k_scroldown,"sd", ""}, { k_down, "cd", ""}, { k_downpage, "pd", ""}, { k_left, "cl", ""}, { k_dchar, "dc", ""}, { k_right, "cr", ""}, { k_scrolup, "su", ""}, { k_up, "cu", ""}, { k_uppage, "pu", ""}, { k_dline, "dl", ""}, { k_wleft, "wl", ""}, { k_wright, "wr", ""}, { k_rstone, "ro", ""}, { k_again, "ag", ""}, { k_verify, "ve", ""}, { 0, NULL, NULL } }; static unsigned char w_extn[] = { 4, '.','$','$','$' }, /* workfile extension */ b_extn[] = { 4, '.','b','a','k' }; /* back file extension */ /* (internal SE format) */ static char *pairs[] = { /* each element MUST be distinct */ /* and be compatible with strmatch() */ "(", ")", /* brackets */ "[", "]", "{", "}", "/*", "*/", /* C, Pascal */ "$(", "$)", /* BCPL */ "begin", "end", /* Pascal */ "DO", "END", /* PL/M */ "#if", "#endif", /* C prepro. */ NULL, NULL /* end of list */ }; sedef.h : sedefcrx.h maklink -f sedefcrx.h sedef.h seext.obj : seext.c sedef.h c seext jcode seext.i sescr.obj : sescr.c sedef.h seext.h c sescr jcode sescr.i secmd.obj : secmd.c sedef.h seext.h c secmd jcode secmd.i seutil.obj : seutil.c sedef.h seext.h c seutil jcode seutil.i seiocrx.obj : seiocrx.c sedef.h seext.h seiocrx.d c seiocrx jcode seiocrx.i se.bin : seext.obj sescr.obj secmd.obj seutil.obj seiocrx.obj jlinker -ose seext sescr secmd seutil seiocrx syslib clib paslib version -c se.bin   config se.bin 150k /* */ /* Header file for ECS Screen Editor, */ /* J. A. Pickering, Department of Electronics and Computer Science, */ /* Copyright (C) 1987 Southampton University, UK. */ /* */ /* C Version : last updated 05-Oct-87 */ /*  */ /* Permission to use and amend the code herein is given on condition: */ /* */ /* (1) That the Department of Electronics and Computer Science, */ /* Southampton University, UK, and the Copyright notice remain in the */ /* code source headers and within the executable code, */ /* */ /* (2) That the editor signon message remains "ECS Screen Editor", */ /* */ /* (3) That copies of the source code OR the executable code so derived */ /* are not sold for gain or profit by any other party except the */ /* Southampton University, UK, or its authorised agents, */ /* */ /* (4) That this copy is used solely by the purchaser on one machine for */ /* generating executable binaries for one type of target machine */ /* operating system. Further copies should be obtained otherwise. */ /* (The amended source may already be available.) */ /* */ /* */ /* Header file for SVS C Compiler.  */ /* */ /* compiler dependents ... */ #include #ifndef min #define min(x,y) ( ((x)<(y)) ? (x) : (y) ) #endif #ifndef max #define max(x,y) ( ((x)<(y)) ? (y) : (x) ) #endif #define maxint ( ( (unsigned int) ~0) >> 1 ) #ifndef ERR #define ERR (-1) #endif #ifndef NULL #define NULL 0 #endif #define TRUE (-1) #define FALSE 0 #define boolean int #define ANSI FALSE #define void int /* as compiler does not understand 'void' */ #define HEAPFFRONT FALSE /* TRUE for a malloc that scans from heap start */ #undef MONOLITH /* defined by se.c for single unit compilation */ /* SE fixtures ... */ #if HEAPFFRONT #define maxmem 0x00000L /* maximum possible size of text buffer */ #define headroom 300 /* space left on heap at warning (bytes) */ #endif #define KEYMAX 200 /* maximum keypresses in keypress buffer */ #define PROMPTPOS 10 /* column position of Command: prompt */ #define STATUSWIDTH 22 /* width allowed for Command: reports */ #define SEARCHSPAN 3000 /* characters passed in search between reports */ #define FILESPAN 5000 /* characters between file IO progress 'dots' */ #define MAXTABINC 20 /* maximum tab increment */ #define screen_start 2 /* real VDU line number of top of text window */ #define st_ins (1 << 0) /* status bits */ #define st_lheld (1 << 1) #define st_keybuf (1 << 2) #define st_change (1 << 3) #define st_err 0xF0 /* errorlevel field */ #define st_all 0xFF #define panic 5 /* error code levels (explicit enumeration) */ #define danger 4 #define warning 3 /* (3 or above gives bell as well as message) */ #define information 2 #define interest 1 #define ABSOLUTE 0 /* context for 'special number' arguments */ #define CHARS 1 /* (explicit enumeration) */ #define TABS 2 #define LINES 3 #define PAGES 4 /* screen editing mode loop modes: */ #define INTERACTIVE 0 /* and +ve numbers -> no. of times to execute */ #define UPTOTAG -1 /* run continuously upto tagged line */ #define BARLINECH '-' /* characters used for bar line status report */ #define BARWINDCH '=' #define BARMARKCH ':' #define BARCURSCH '|' #define BARBOTHCH '!' #define k_null 0 #define k_tab ('I'-0x40) /* Default control key codes */ #define k_newline ('M'-0x40) #define k_help ('Z'-0x40) #define k_error k_help #define k_backsp 0x7F #define k_insert ('O'-0x40) #define k_restore ('W'-0x40) #define k_scroldown ('_'-0x40) #define k_down ('J'-0x40) #define k_downpage ('F'-0x40) #define k_left ('H'-0x40) #define k_dchar ('G'-0x40) #define k_right ('L'-0x40) #define k_scrolup ('\\'-0x40) #define k_up ('K'-0x40) #define k_uppage ('R'-0x40) #define k_dline ('E'-0x40) #define k_wleft ('B'-0x40) #define k_wright ('N'-0x40) #define k_rstone ('U'-0x40) #define k_again ('A'-0x40) #define k_verify ('V'-0x40) /* SE data declarations ... */ #define MAXLEN 255 /* maximum line length using this struct */ typedef struct aline { struct aline *next; struct aline *previous; unsigned char line[256]; /* line[0] is length, line[1].. is string */ } lnode; `]t NVHN~`(nB`R 4 xg 4 xg 4 xg 4 xgz 4+xg 4-xf R 4+fp`p*B` Hx /N~4xHH0П,R 49xn 40xl//N~ LN^NuNV/N~`B`RR nJf .N^NuNV/ N~`(n n fJfp`RR `Jfp`p(_N^NuNVHN~`I np , TBp4JmB n . R 5 Tp//Hy4NIz B`Z Tp( A/0/NP.NPORg&SgSf"gpA/0NPXO `,`z`R AJfJf TBp`S`LpLN^NuNVN~`HxN{XO#4N^NuNVN~` npRXXN^NuNVN~`/.N{XON^NuNVN~`JfHxHyNMPO` /.N|XON^NuNVN~`N^NuNV/N~`Hy/9NPOJfp`p .Jg\HxBNQPO#`HxBNQPO#dHxBNQ:PO#hHxHxNSPOHxHxNSPOHx>Hx HxBNQ:HxBHxBNQ:Hx"/HxBNQ:.N^NuNVN~`Hx>/9`HxBNQ:Hx/9dHxBNQ:Hx"/9hHxBNQ:N^NuNVN~`N~NJNd/.NmXON^NuNVN~`/. /.HyNd HxNXON^NuNVN~`Hx/.NQPOJfp`pN^NuNVN~`Hx/.NQPOrg`p" N^NuNVN~`Hx/.NQPOrfp`pN^NuNVH8N~`/94NJXOHy/9@NaPO(@ g$y J gBNL< @Gp" Ҁ.Rm/ KRp/NbPO`/ Hx NbPO`# J g /9NbR.Hy/ Nd / N`XXO`Hx/9NMPOHxN0XO#4LN^NuNVHN~`(y&y*9.9,9/9@NFXOJgB  p##BNLdHx/9@N PO# #####J g(B/9NP.N./9Na LN^NuNVH8N~`E0G(B,/9NXOJgTJPf6(yJf#,#`/9NXOJg #,J,fB`/9,NXOr9ЁT/N0XO$/9,NPXO RBB//9NIz RHH,`SJo R 0/hf RHH"ҼUo RHH` мU//HyNIz R-H RHH"Ҽo RHH` м n/NPXO$`(yA#`F/9NFXOJfJfJPg/9HyNPO#B,JPfHyp. /NbPOHyHx NbPOHxNXOLN^Nu @" $A   H@@ @D $D$$I$I$D!"H)BH HI"HAB@  H$$ H H"$$" D $HH@BA"B$H!"I "H A D $"B@$ D @$ "@$I@B@ !$@"DB@$"  @ $ HI$H$""DHH $"E  HHHH@ @$!I $  "H H@$ @I $$@ $A A$@$@@ @H"@A oNVN^NuNVNrN~`NNP 9 R/N0XO# yB 9 R/N0XO# yB 9 R/N0XO# yBHxN0XO#B BBr##BB$9(UR#BBB#BB$B\/. /.NPON\JPWDHH#BB#B 9|g"9 ` <"#B/9NNHPO/Hx/9NNHPO/NHpPONG 9йS#TBNHxBN(POBHxN PON^NuNVN~` y, 9Lr0t g(rLg y, 9LSt0p fp`pN^NuNVHN~`(n,. pR.`p xRlpd `pLN^NuNVN~`RRHxNXORTHx/9TN`POpN^NuNVN~`pfr `,SSHxNXOHx/9N`POpN^NuNVN~` 9̰TlR`N"N^NuNVN~` 9̰oS`N"N^NuNVH8N~`..IGc(E~ f` g4HxHxNPONJ$g/9HyNdPO.< rfh 9+/HxNPOJgHlHyNPOJgHlHyNPOJVDf JVDJf HxNXO rfR 9/HxNPOJ gHlHyNPO`$J gHlHyNPO` Hx NXO rf 9S//NPOBNlXO 9/HxNPOJg8HxNlXOHlHyNPO 9]/HxNPOBNlXO`.BNlXOJPgHlHyNPO` Hx NXOLN^NuNVH8N~`ILGE 9Xg J0oHx/9,NGzPO` `p. \Df 9SWDg 0^DJf//9,NKLPO R-H Rp"Sc Rp` S n//NKtPOJf` RB 0nx 9Xg//9,NGzPO` ,/Hx/9,NH JXg S//N"dPO S///9,NIz Jf`hHx/N`PO R//NKtPOJf`D T/NMXO( TfN"`"R/NM.NXOHx/N`POLN^NuNVHN~`G,I 9Sn`D/9/NKLPO 9LS//9N"dPO R/NMdXO @P&Hx/NGzPO,JXg/Hx/NH yp//9/NIz Jf`/9L/NM.N~PO~`, йLS//NM. Sp0x/Nn R Spd//9NKtPOJf`N R/NMXO R/NMXO Tn( R/NM.NXOHx/9TN`POLN^NuNVH8N~`(.ILEG.. B-Rpg Jf BNXOp45"mfgkv nlI2;NBbbB 0bbxbbHHbbbbhbbXpgfNJvJWDHH-@-S"l& gN"`N"Jg o 9йlJg```2pghNJJWDHH-@-S".첹To&T gN"`N"Jg o 9йlJg```NN#^`Jg N%`p(p fNN#4`NN"`zNN"`jNpf`V 9ro` 9"# ro` "&N$`N 9Tm` 9й-@ 9S"9⁐ro` 9S"9⁐" .貀o 9й`0 9S"9⁐ro` 9S"9⁐" # 9Г-@po` 9".䰁o 9Г`po` 9& fp` (N$`NJPfZJ gN#^ m`/NM8.NM.NXOHx/9(N~POHx/9TN`PO`-y J VDf J VDHH-@"m"S/NI.XOJf`TJgJ g /NL< @HhNKtPOJf``4J g,/9N XOrg//9NKtPOJf`/NM.NXOHx/N`POJ gN#4J fp`p#"9/N#XO#J VDf J VDg N`JWDg pVDHH-@`J f"pfJg/.NJXO`# N`"JPg`pWDHH-AJfS"n``DS l&N"Jf`NG 90R( 9йl`pffJfb"0nX/NMXO-@ y,"t //.N~PO//.Hx Nn /9,NJXOp#`>pWDgJVDg 0_DfJVDJf` JPfN m` 0o N'2`p_Dg "0_DJf` R*` y, S"y,XR0o y, 90r //N`PO/9,NJXOp#`\ 9Pgr` JWDHH"$RpfNLd`0NN$`JfJPg B`p#-R$r#``-TRp f//9NrfJVDg p WDJf`B94 /Hy4N"dPO(p95,p oN9*`\JPg`Pp gF"9ҹfJgHx/9$NMPO` m/NI.XOJf`JfH 0n> y, //NM./Nn /9,NJXOp#`p f"oJg N%`p mf"0nx/9/9,NKLPO S//9N"dPO S//9Hy4NIz Jf`8//9NKtPOJf`" R/NM./N`POp94єpgBJg8 fHxHyNMPO` 9RA!Jg 9l r$nhB$JgZpgSN`Jf(Jg$p$orltf m N`p#$r#Jg 9RA.0NG 9йS#T"9ҹ0lHxHyNMPO o 9йlHx/9$NMPOp$f Br#PJ fp`p# g p`p#JVDf JVDJg p`p#"9$$<Ĺ# 9/N#XO#J\g N^B\p$or` 9$"#$ 9Rl ` 9R"9ҹo 9Rl ` 9R` 9й(//NM.N~POJfHxNXONN.`N`LN^NuNVN^NuNVHN~`BNXOJ g& 9/HxN~POHxNXO 9/HxN~PO .g&Sf/9L/9HyLNd `Hx/9N~-_Hx/9N~-_Hx/9N~* 9SHx/N~-_Hx/9TN~-_BJWDHH&.9lX|-o|=o|-lJf|:voJf :gp|`p!xHy HH/NbPO 9ހ`J g$N ypм /HxN~POHxNXOLN^NuNVN~`BNXO 9/HxN~PO nJfHxNXO`/. /.NdPOHxNXON^NuNVH8N~`(n &n .g AJ"` AJv "$Ap&p(Bp-@Jfr `/ NJXOp-@/ NJXOp-@NJg 90RL* .R f(BHxBN4PON`Jg Np`m>o ` ,o0~`( y, SйL04xg`fR`RlԺmDo ` ,~`0 y, SйL03xg`fSJfp` Rl` pLN^NuNVHN~`ILG.9B 9Гm nH "lp` " "<o "lp` " ` <.VDHH,# LN^NuNV/ N~`(nHx/ NGzPO/Hx/ NH (_N^NuNVH8N~`GLEIBBB-y-RBBBBHxNXOJf HxHxN~PON .kz nrH0;N *@VBBN4PO`PBHxN4PO`@/9HydN6PO`*/9HypN6PO`/9HyzN6POHxHxN~POHyNdXO TB yBp-@Jg NN( mf g\~k n H0;N   n0ZZh n  Z X Tpf`t TSHyHy^Nc(PO`X/N8XO @pf|` * Tp(rzTDg Tp(taSDJg Tp( ` Tp( TprWDHH-@HyHyNc(PO 9o: H@m*k @ nH0;N@J||@k @ nH0;N>>Jg0 CWDHH/ EWDf CWDHH/N PO,Jg|~`bJgNv,~` Tp(rzTDg Tp(taSDJg Tp( ` Tp(rEfH TprUDg Tp(t WDJgHx/NLPO`//9,NLPO,~`v?Nf~`Jg"Bp##r#|`Jg >f 9` 9D-@Г//NHpPO .йlp` .й"<o .йlp` .й` <#|~`Jgt 9"lp` 9"  "<o" 9"lp` 9" ` <#//NHpPO|~`rJgl-y-y## RfHJgBJg 9‰o(y~`(TRl`(y 9U.`(lSo LN^NuNVN~` .TN^NuNV/N~`.. $m ##$p_DHH#\.N^NuNVN~`/.NP.NXON^NuNVHN~`(npcp,`p0v . SgSg Sg6SfvgB 90R* 9LD,`jHx/9N$ R*B`P*9 9D,`>/9/9N$ R* 9D//9N$,` *<,<prf" -g .g +f -f ` `Z *fj 9. . g0SgUfHg4 9f"9ĒL`p" `Jlp` `Jfp` `p` -f.vprdp,t.f/Hx/ NH ,prdr .flp -@/ NJXOHxHx/ NH ~`A/Hx N~ Rpb/ NN&./N~/.N$/N~ `8/ NN&XO.J f Jl D.l ` o l ` ` LN^NuNV/ N~`(npRB4A (_N^NuNV/N~`B` y R"nxR nJ0xf y.N^NuNVN^NuNVN^NuNVN~`-n-n HnHxNSPOJgp` .N^NuNV/ N~`I)n)n )n )n/ HxNSPOJgp` , (_N^NuNVN~`-n-n -nHnHxNSPOJgp` .N^NuNVN~`-nHnHxNSPOJgp` .N^NuNV/ N~`I)n)n )n/ Hx NSPOJgp`R . SkH n@H0;N&&&&&&&&&,8888,,&& , ` , ሀ`p(_N^NuNVN~`-n-n HnHx$NSPON^NuNVN~`-n-n HnHx(NSPOJgp` .N^NuNV/ N~`I)n)n / HxENSPOJgp` n  n!l , (_N^NuNVN~`-n-n -nHnHxHNSPOJgp` .N^NuNVN~`HnHxRNSPON^NuNVN^NuNVH $n L .N@QHd Nqp`BLN^NuNV". . N@d Nqp`BN^NuNV/ $.CC($Q n "C`C( g IN@@d Nqp` g $_N^NuBH /:A"/A pNXL?DXNuaaaaaaaaNVH8N~`(n Hx BNRPO-@GB+B$LBB/.Np .S// /.NZ ,lp`Jf`plHx/ HlN[ JgpmB l,B` 4:xfR`Rn/ Ї// N]6 *` S 4:f`SJnJoS.` S 4:f`SJn rfLHxHy\HtxN[ Jg0GHx VHt/ N]6 B+Їև`ֆ(J,B` rn 4:xf V 4@f X*`n rnb 4:XfZHx RHt RHtN[ Jg8 R(` 4:Hf`Rn  /HtHHtXN]6 `RnY / XHtHtxN]6 Rn>B4hpLN^NuNV/ N~`(n/ N[XO(@Jg>Hx/. / N[ Jg$ ,#fHnHlN\POJg .```p(_N^NuNV/ N~`(n/ N[XO(@Jg*Hx/. / N[ Jg ,:fp`p``p(_N^NuNVHN~`(n&nB/ N[XO(@JgHx/. / N[ Jg ,=fVB 0m 9n LRHH0( :gvlnJfp` ^f.RJg :fp`| R LRHH¼`, \fRH@m^@mgY@gQ@gXY@gdU@fgx@mfg@k @ nH0;N|||||||| @0fp` Rr R` Rr R`~ RrR`p Rr R`b Rr R`T RrR`FzB`  LRHH0,SJg 0m 7o R` R LR` R LR` Єm`" SJg Rr`B3x ```pLN^NuNVH8N~`&n E(nBBBB KRgD %f2 KR H@mg0[@g@f g@9gW@gY@gS@g @fg JX *0Jox`Bo .ڀJgR +f KRHHڀ|. .f LR`tB`"/Hx N x/Hx N$*Rpnpl$"SJ6f dg"HH0lS` SJg LR6xHHм0``, KRHH-@ KRHH-A`x` v` LR` LR`B LN^NuNVHN~`(n *.B`p // /.Npp .f`4Jg& SJ4g S 4 g S 4 fS`Jg #gJg S 4\fS`܇` Ї܇no `pLN^NuNVN~`` n"n gp`R R SJfpN^NuNV/ N~`(n` Jfp` R :f R(_N^NuNVHN~`(nBBBB  g  g  g  fR` +fR` -fp-@RB A\Dg Z_DJgHHм `HH.p0nr9m0`panrfm Wv`` Hx /N~ П, Ї(RR`Jfp`\ A\Dg Z_DJgHHм `HHrhf,R`Jgp` n -H .g"D`" n LN^NuNVHN~`(n Ю&@` nRR nLN^NuNVN^Nu.Nn G0H//N PBNmNoT&/N@FNVHN~`(nR, HHfp`, HHgFHxHn, HH/NqL .pf.HH `, Jl, p`|Jf(, HxN{XO)@JfHyNmXOHx(/,, HH/NqL .n, Jl, p`S)G R @pLN^NuNVHN~`(n *.R, HHfp`, HHgBEHxHn, HH/Nq| .pf"¼ `, p`JfD, HxN{XO)@(JfHy8NmXO)| R @ `N ,//,, HH/Nq| .g , p`()| R @ LN^NuNVHN~`(n, HHfp`^, HHgp`JJfp`@ ,//,, HH/Nq| .g , p`()|pLN^NuNVHN~`(n, gV/ N_XO., HHg/,N|XOBB, pHH)@, HH/NoXOJgp` LN^NuNVH8N~`&n(n$n / N`XXO rfB/ NpPO.p@ `b wfHx/ NoPO.p@ `D af@mgBY@gU@g8W@fg0@ k @nH0;Nrrr@cfxgr .X @,-FIB. df\ f Sp8,<334J]"DAg D,S/Hx Np0П/Hx N$,f.gSr-` uf.S/.Hx Np0ПA/Hx N Jf`V ofSpм0A  f`2 xf(Spм0 9o'A  f`SA ".&JfJ.g" .0f"LRHH// /Nd SJo.HH// /Nd `A o"LRHH// /Nd ` SJo.HH// /Nd `` .X @(P-LB`R .R @fJgl, .&Jf" SJo.HH// /Nd ` SJg LRHH// /Nd ` SJo.HH// /Nd ``0-nP nC""Jg gfx ef&HnHnHn R/A/ / Nnb`bHnHnHnHxA/ / Nnb ff"Hn0.H"ҀR/HnNeB `Hn R/HnNeB Rn eg gf0.Hrm Htm gfJo 60HfS`p"@=AH.HH҂\ .&Jf" SJo.HH// /Nd `.gHx-/ /Nd .HH// /Nd Hx./ /Nd |`4po6hHH// /Nd `Hx0/ /Nd RSnJnfSnHxe/ /Nd 0.Hl Hx-/ /Nd 0.HD=@`Hx+/ /Nd 0.H/HxdN$r0ҟ// /Nd A0HdH@00.H/Hx N$r0ҟ// /Nd 0.H/Hx Nr0ҟ// /Nd `b gfJo0.H"ҀS 60fS`.HH"ҀR$.&2.HoH`SJf" SJo.HH// /Nd `.gHx-/ /Nd 0.HnHx0/ /Nd B`4po6hHH// /Nd `Hx0/ /Nd R0.SnHnHx./ /Nd 0.RnHroJgSHx0/ /Nd ` SJg6po6hHH// /Nd `Hx0/ /Nd R` SJo.HH// /Nd ``` HH// /Nd ` HH// /Nd `2Jg R @BLN^NuNV/ N~`(ngLS J m" 9R @"LRHH`Hy LRHH/N^PO`(_N^NuNVHN~`IB`0, HHg, HHf / N_XORpn/.N]XOLN^NuNVN^NuNV/. /.?./././.Nx8N^NuNV/.?.?./.NvN^NuNV/.?.?./.NuN^Nu,gE0*H// Ns0 _ .@Hzf/NV-F0*H// Hn HzJHnNsN^ _"_/ /Nu @/h/h /h (?@/hNuBNu&N@FHz/<NqNrNO HEAP ADDRESS NV".N@ dNp`BN^NuH o $<v N@d( @ f$<v N@e LNuNpLNu/ /g:NBt&xN@# /N."t&xN@# /N"t&xN@#" LNupVVVTONuH o$/ &/N@d NDpLNu LNuH"/ o &/SN@d NBLNuJ00g 0 0f 0 0f 0SB00R LNuH"/$/&/ jJgDDN@d NpLNuN@ LNuNVH n$. &.BCN@ dNp` LN^NuH"/ o N@d NhpLNu LNuH"/&/ o N@d @gN8p`p` LNuH"/&/ o N@dNp` LNuH/Nr NuH$o@L"/DN@LdpNuBNu oN@dNBNu /NuNVH/./. /<Np L?N^ _PONNu @ h0/HNNVHHzP/<a$.v2A A o^AA0AHn/<aQHz$/<atL?N^.Nuat location 0x ?. (n p@@B,rABAl(B,B,,JnVDB GfB,l@)@A`0JGfB,lp@)@@`JGl BB B` H)@LN^ _PNNVA@ N^NuNVN^NuNVH6. B nl8.`x=D|`&Hx /N~ n0`HHП*0RFino/N. R@=n<`2//`JGfA/ / BBN`gP/ / B/JGfn noz`:.A/ / B/<@?NHN0NA / / B/<@$N`mRFP/ / B/<@$N0 p@xA/ / B/<@@N "VAH>`A/ / N =@ Go(P/ / H/NNB/<@ÈN v D@m(0.H H@=@"Ct0nJngB.0.H =@SCJClXDSG Gln R@=n>` p0pRGino.gBFB n 0`fA/ / NJgp?=@` A/ / NJgp-=@`p+=@=n~` pRGino n BP n-WDLN^ _NNVN^NuNVA N^NuNVN^NuNVH8..po~` ^.&y g(k$L`* f$j f&k l є l)h Дg̾n< rn#(A,`^'l f#A,`@&L(l f~#N{"Ҽl(y߹(A `p` LN^NuNVH8 .Y$@(y g6&l`(K&l n l`(K&k n)J%K#` #%JLN^NuNVN^Nu/0/ o m.on( /W\Nu/ / mn /W NuHz/< Nq//Nr2Nr?/@on 0/WXNuHz/<Nq//Nr2Nr?0/@ @g0Nu /g Hz/<` Hz/<Nq//Nr2Nr?0/@ @g0Nu /f / fAp` Hzj/<Nq//Nr2NrN{ XmNuHzf/<NqNr2NrRange error String range error Floating point NAN Floating point infinity Stack overflow //0/2/ AH@B@2/Ё/@" .Nua/o.Nua.NuHx /g`lDD"/ lDDD l4BAHA62HA02HA`4$& l //N^lSЂ`B"<JlDJDlD/A /@LNuN.NuN /o.NuH /"/ BBx㓶mRQ/C/B LNuoHL UUðcACBBDfJgvJffҀ`j`f<< gf<D FmQFf쨴fҀd$RE|m`ZkgP[SEngBEd RE Eg0/A$L.NuJffg"<`B`"<`oHL$UUŰcBCEHNLJGf(gJFf `0 FgvFDGQGmfJf` ^GkQJkցՀd RF|m`PdFED@N|NMH ,L..NuN`(fFfJj$<B`$<B`////////N/_/_B B////////abd  m4L /WNu////////a.d o /o /oL /WNuHL(ȀkBCf (g< g&ki?|"`>?|"`6i?|"`,?| "`$ki?|"`?|"`i?| "`?|"㊰dB c?|"`f?|"L/_ NwH / "/BCBD@ARSDoJRRSCoXR蘘C6HA4B@䀁HHHBЂDN/@ L?.Nuf SDbRD`g*Jg`$gJfB`Jg SCdRC`Jg <`eJg@`p`HL$*グcBCNL:,G|gJGgHL:/B:/ օӇ:/ օӇ:օӇ:/ ԅч: ԅчH@: ҅GH@6HCBAHAւчЁ$FNH ,L..Nu*Gg <<N`.gSFjRF`F$<`BB`//oH"/N2a2HLNuHLaND`HLaNj/AL.NuH~LapNND L~..NuLH>aLN`LH>a8N aL|..Nu o"_$.H0YO/La NL Nu$<&HCĀ(f<Jg,<`&HBJ|f4<`<Jg<`SB<B2NuLH0HNBFCa@ar, AKNux ,<.̂(ȃ⊄(΀ȁ∀NuJf F m F BJgk [ZNu<Jf Jj4XO`Gfl<$HBNFHB b $<JjTB`BBXO`|BփՂ\ ǖ[j ցՀ JD]Nu////////aL/_ NuHL$*xa8SGGo <SFaF N|NH ,L..Nu"/ _ .H0YO/aaL Nu oHB4H _PN&HCBBf<Jg*<`$<f4<`B<Jg<`<SB<BBNu oL6HB o NuLH0Haa _PL N8 m `$Jg PDf gkSDjDa "KNu /..NuJkSDJDn Dm"DRBDdRD Dl UNuBNu <NuH"/a*Nj/ALNuH"/Na/ALNuBBvJjDBNu la(BJf JkJCjDNu"<NuN The last save is in file %s, keep it? [Y/N] %c N.B. Delete it or rename it NOW. Aborted, file %s not written. /etc/se.hlprE to exitQ to quit to continue editing[ Helpfile %s is not available ]PVExit to resume edit. _.$/^Z^bWithin Could not start new SE/etc/termcaps Cannot get termcap entry for %s. coliamceclcm Terminal %s has insufficient capabilities. aldl/etc/setermcapshfkskeisocfcsosesgnd %sLine would be too longText buffer is full[ at l %d c %d ]  [ from %s ][ to %s ][ %s ]Command: ? ??File empty[ %s ][ memorising ][ replaying ][ holding ][ Filling ]INSERTING BrowsingKeypress buffer fullLong line(Cursor cannot go there(( @  0 1 rewa re-- re-- system Aug-05 05:50 941files.txt 41,984 1 rewa rewa re-- bin Oct-04 1987 se.bin 533 1 rewa rewa re-- bin Sep-19 1987 se.mak 24,909 1 rewa rewa re-- bin Oct-04 1987 secmd.c 5,556 1 rewa rewa re-- bin Oct-04 1987 sedefcrx.h 4,994 1 rewa rewa re-- bin Sep-28 1987 seext.c 10,554 1 rewa rewa re-- bin Sep-28 1987 seext.h 40,429 1 rewa rewa re-- bin Sep-28 1987 seiocrx.c 4,853 1 rewa rewa re-- bin Oct-04 1987 seiocrx.d 23,589 1 rewa rewa re-- bin Oct-04 1987 sescr.c 15,122 1 rewa rewa re-- bin Oct-04 1987 seutil.c      Pvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('      P~}|{zyxw     P          Pfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!       P~}|{zyxwvutsrqponmlkjihg     P    ! ! " PVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!      " # # $ $ % P~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXW% & & ' ' P( ( ) ) * PFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!      * + + , , - P~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHG- . . / / P0 0 1 1 2 P6543210/.-,+*)('&%$#"!      2 3 3 4 4 5 P~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9875 6 6 7 7 P8 8 9 9 : P&%$#"!      : ; ; < < = Pvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('= > > ? ? P~}|{zyxw@ @ A A B P     B C C D D E Pfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"! E F F G G P~}|{zyxwvutsrqponmlkjihgH H I I J P      J K K L L