00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407 #include "mined.h"
00408 #include <signal.h>
00409 #include <termios.h>
00410 #include <limits.h>
00411 #include <errno.h>
00412 #include <sys/wait.h>
00413 #include <sys/ioctl.h>
00414 #if __STDC__
00415 #include <stdarg.h>
00416 #else
00417 #include <varargs.h>
00418 #endif
00419
00420 extern int errno;
00421 int ymax = YMAX;
00422 int screenmax = SCREENMAX;
00423
00424
00425
00426
00427
00428 void FS()
00429 {
00430 fstatus(file_name[0] ? "" : "[buffer]", -1L);
00431 }
00432
00433
00434
00435
00436
00437 void VI()
00438 {
00439 char new_file[LINE_LEN];
00440
00441 if (modified == TRUE && ask_save() == ERRORS)
00442 return;
00443
00444
00445 if (get_file("Visit file:", new_file) == ERRORS)
00446 return;
00447
00448
00449 initialize();
00450 #ifdef UNIX
00451 tputs(CL, 0, _putchar);
00452 #else
00453 string_print (enter_string);
00454 #endif
00455 load_file(new_file[0] == '\0' ? NIL_PTR : new_file);
00456 }
00457
00458
00459
00460
00461 int WT()
00462 {
00463 register LINE *line;
00464 register long count = 0L;
00465 char file[LINE_LEN];
00466 int fd;
00467
00468 if (modified == FALSE) {
00469 error ("Write not necessary.", NIL_PTR);
00470 return FINE;
00471 }
00472
00473
00474 if (file_name[0] == '\0' || writable == FALSE) {
00475 if (get_file("Enter file name:", file) != FINE)
00476 return ERRORS;
00477 copy_string(file_name, file);
00478 }
00479 if ((fd = creat(file_name, 0644)) < 0) {
00480 error("Cannot create ", file_name);
00481 writable = FALSE;
00482 return ERRORS;
00483 }
00484 else
00485 writable = TRUE;
00486
00487 clear_buffer();
00488
00489 status_line("Writing ", file_name);
00490 for (line = header->next; line != tail; line = line->next) {
00491 if (line->shift_count & DUMMY) {
00492 if (line->next == tail && line->text[0] == '\n')
00493 continue;
00494 }
00495 if (writeline(fd, line->text) == ERRORS) {
00496 count = -1L;
00497 break;
00498 }
00499 count += (long) length_of(line->text);
00500 }
00501
00502 if (count > 0L && flush_buffer(fd) == ERRORS)
00503 count = -1L;
00504
00505 (void) close(fd);
00506
00507 if (count == -1L)
00508 return ERRORS;
00509
00510 modified = FALSE;
00511 rpipe = FALSE;
00512
00513
00514 fstatus("Wrote", count);
00515 return FINE;
00516 }
00517
00518
00519 void XWT()
00520 {
00521 (void) WT();
00522 }
00523
00524
00525
00526
00527
00528
00529 void SH()
00530 {
00531 register int w;
00532 int pid, status;
00533 char *shell;
00534
00535 if ((shell = getenv("SHELL")) == NIL_PTR) shell = "/bin/sh";
00536
00537 switch (pid = fork()) {
00538 case -1:
00539 error("Cannot fork.", NIL_PTR);
00540 return;
00541 case 0:
00542 set_cursor(0, ymax);
00543 putchar('\n');
00544 flush();
00545 raw_mode(OFF);
00546 if (rpipe) {
00547 close (0);
00548 if (open("/dev/tty", 0) < 0)
00549 exit (126);
00550 }
00551 execl(shell, shell, (char *) 0);
00552 exit(127);
00553 default :
00554 signal(SIGINT, SIG_IGN);
00555 signal(SIGQUIT, SIG_IGN);
00556 do {
00557 w = wait(&status);
00558 } while (w != -1 && w != pid);
00559 }
00560
00561 raw_mode(ON);
00562 RD();
00563
00564 if ((status >> 8) == 127)
00565 error("Cannot exec ", shell);
00566 else if ((status >> 8) == 126)
00567 error("Cannot open /dev/tty as fd #0", NIL_PTR);
00568 }
00569
00570
00571
00572
00573
00574
00575 LINE *proceed(line, count)
00576 register LINE *line;
00577 register int count;
00578 {
00579 if (count < 0)
00580 while (count++ < 0 && line != header)
00581 line = line->prev;
00582 else
00583 while (count-- > 0 && line != tail)
00584 line = line->next;
00585 return line;
00586 }
00587
00588
00589
00590
00591
00592
00593 int bottom_line(revfl, s1, s2, inbuf, statfl)
00594 FLAG revfl;
00595 char *s1, *s2;
00596 char *inbuf;
00597 FLAG statfl;
00598 {
00599 int ret = FINE;
00600 char buf[LINE_LEN];
00601 register char *p = buf;
00602
00603 *p++ = ' ';
00604 if (s1 != NIL_PTR)
00605 while (*p = *s1++)
00606 p++;
00607 if (s2 != NIL_PTR)
00608 while (*p = *s2++)
00609 p++;
00610 *p++ = ' ';
00611 *p++ = 0;
00612
00613 if (revfl == ON && stat_visible == TRUE)
00614 clear_status ();
00615 set_cursor(0, ymax);
00616 if (revfl == ON) {
00617 #ifdef UNIX
00618 tputs(SO, 0, _putchar);
00619 #else
00620 string_print(rev_video);
00621 #endif
00622 stat_visible = TRUE;
00623 }
00624 else
00625 stat_visible = FALSE;
00626
00627 string_print(buf);
00628
00629 if (inbuf != NIL_PTR)
00630 ret = input(inbuf, statfl);
00631
00632
00633 #ifdef UNIX
00634 tputs(SE, 0, _putchar);
00635 tputs(CE, 0, _putchar);
00636 #else
00637 string_print(normal_video);
00638 string_print(blank_line);
00639 #endif
00640 if (inbuf != NIL_PTR)
00641 set_cursor(0, ymax);
00642 else
00643 set_cursor(x, y);
00644 flush();
00645 if (ret != FINE)
00646 clear_status();
00647 return ret;
00648 }
00649
00650
00651
00652
00653
00654 int count_chars(line)
00655 LINE *line;
00656 {
00657 register int cnt = get_shift(line->shift_count) * -SHIFT_SIZE;
00658 register char *textp = line->text;
00659
00660
00661 while (cnt < 0) {
00662 if (is_tab(*textp++))
00663 cnt = tab(cnt);
00664 else
00665 cnt++;
00666 }
00667
00668
00669 cnt = 0;
00670 while (*textp != '\n') {
00671 if (is_tab(*textp++))
00672 cnt = tab(cnt);
00673 else
00674 cnt++;
00675 }
00676 return cnt;
00677 }
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689 void move(new_x, new_address, new_y)
00690 register int new_x;
00691 int new_y;
00692 char *new_address;
00693 {
00694 register LINE *line = cur_line;
00695 int shift = 0;
00696 static int rel_x = 0;
00697 int tx = x;
00698
00699
00700 if (new_y < 0 || new_y > last_y)
00701 return;
00702
00703
00704 if (new_y < y)
00705 while (y != new_y) {
00706 y--;
00707 line = line->prev;
00708 }
00709 else
00710 while (y != new_y) {
00711 y++;
00712 line = line->next;
00713 }
00714
00715
00716 if (new_address == NIL_PTR) {
00717 new_address = find_address(line, (new_x == x) ? rel_x : new_x , &tx);
00718 if (new_x != x)
00719 rel_x = tx;
00720 new_x = tx;
00721 }
00722 else
00723 rel_x = new_x = find_x(line, new_address);
00724
00725
00726 if (new_x < 0 || new_x >= XBREAK) {
00727 if (new_x > XBREAK || (new_x == XBREAK && *new_address != '\n'))
00728 shift = (new_x - XBREAK) / SHIFT_SIZE + 1;
00729 else {
00730 shift = new_x / SHIFT_SIZE;
00731 if (new_x % SHIFT_SIZE)
00732 shift--;
00733 }
00734
00735 if (shift != 0) {
00736 line->shift_count += shift;
00737 new_x = find_x(line, new_address);
00738 set_cursor(0, y);
00739 line_print(line);
00740 rel_x = new_x;
00741 }
00742 }
00743
00744
00745 x = new_x;
00746 cur_text = new_address;
00747 cur_line = line;
00748 set_cursor(x, y);
00749 }
00750
00751
00752
00753
00754
00755 int find_x(line, address)
00756 LINE *line;
00757 char *address;
00758 {
00759 register char *textp = line->text;
00760 register int nx = get_shift(line->shift_count) * -SHIFT_SIZE;
00761
00762 while (textp != address && *textp != '\0') {
00763 if (is_tab(*textp++))
00764 nx = tab(nx);
00765 else
00766 nx++;
00767 }
00768 return nx;
00769 }
00770
00771
00772
00773
00774
00775 char *find_address(line, x_coord, old_x)
00776 LINE *line;
00777 int x_coord;
00778 int *old_x;
00779 {
00780 register char *textp = line->text;
00781 register int tx = get_shift(line->shift_count) * -SHIFT_SIZE;
00782
00783 while (tx < x_coord && *textp != '\n') {
00784 if (is_tab(*textp)) {
00785 if (*old_x - x_coord == 1 && tab(tx) > x_coord)
00786 break;
00787 else
00788 tx = tab(tx);
00789 }
00790 else
00791 tx++;
00792 textp++;
00793 }
00794
00795 *old_x = tx;
00796 return textp;
00797 }
00798
00799
00800
00801
00802
00803 int length_of(string)
00804 register char *string;
00805 {
00806 register int count = 0;
00807
00808 if (string != NIL_PTR) {
00809 while (*string++ != '\0')
00810 count++;
00811 }
00812 return count;
00813 }
00814
00815
00816
00817
00818
00819 void copy_string(to, from)
00820 register char *to;
00821 register char *from;
00822 {
00823 while (*to++ = *from++)
00824 ;
00825 }
00826
00827
00828
00829
00830
00831
00832 void reset(head_line, screen_y)
00833 LINE *head_line;
00834 int screen_y;
00835 {
00836 register LINE *line;
00837
00838 top_line = line = head_line;
00839
00840
00841 for (last_y = 0; last_y < nlines - 1 && last_y < screenmax
00842 && line->next != tail; last_y++)
00843 line = line->next;
00844
00845 bot_line = line;
00846 y = (screen_y > last_y) ? last_y : screen_y;
00847
00848
00849 cur_line = proceed(top_line, y);
00850 }
00851
00852
00853
00854
00855 void set_cursor(nx, ny)
00856 int nx, ny;
00857 {
00858 #ifdef UNIX
00859 extern char *tgoto();
00860
00861 tputs(tgoto(CM, nx, ny), 0, _putchar);
00862 #else
00863 char text_buffer[10];
00864
00865 build_string(text_buffer, pos_string, ny+1, nx+1);
00866 string_print(text_buffer);
00867 #endif
00868 }
00869
00870
00871
00872
00873 void open_device()
00874 {
00875 if ((input_fd = open("/dev/tty", 0)) < 0)
00876 panic("Cannot open /dev/tty for read");
00877 }
00878
00879
00880
00881
00882
00883 int getchar()
00884 {
00885 #ifdef UNIX
00886 return (_getchar() & 0377);
00887 #else
00888 char c;
00889
00890 if (read(input_fd, &c, 1) != 1 && quit == FALSE)
00891 panic("Can't read one char from fd #0");
00892
00893 return c & 0377;
00894 #endif
00895 }
00896
00897
00898
00899
00900
00901
00902
00903 void display(x_coord, y_coord, line, count)
00904 int x_coord, y_coord;
00905 register LINE *line;
00906 register int count;
00907 {
00908 set_cursor(x_coord, y_coord);
00909
00910
00911 if (count < 0) {
00912 line = proceed(line, count);
00913 count = -count;
00914 }
00915
00916
00917 while (line != tail && count-- >= 0) {
00918 line_print(line);
00919 line = line->next;
00920 }
00921
00922
00923 if (loading == FALSE) {
00924 while (count-- >= 0) {
00925 #ifdef UNIX
00926 tputs(CE, 0, _putchar);
00927 #else
00928 string_print(blank_line);
00929 #endif
00930 putchar('\n');
00931 }
00932 }
00933 }
00934
00935
00936
00937
00938 int write_char(fd, c)
00939 int fd;
00940 char c;
00941 {
00942 screen [out_count++] = c;
00943 if (out_count == SCREEN_SIZE)
00944 return flush_buffer(fd);
00945 return FINE;
00946 }
00947
00948
00949
00950
00951 int writeline(fd, text)
00952 register int fd;
00953 register char *text;
00954 {
00955 while(*text)
00956 if (write_char(fd, *text++) == ERRORS)
00957 return ERRORS;
00958 return FINE;
00959 }
00960
00961
00962
00963
00964
00965
00966
00967 void put_line(line, offset, clear_line)
00968 LINE *line;
00969 int offset;
00970 FLAG clear_line;
00971 {
00972 register char *textp = line->text;
00973 register int count = get_shift(line->shift_count) * -SHIFT_SIZE;
00974 int tab_count;
00975
00976
00977 while (count < offset) {
00978 if (is_tab(*textp++))
00979 count = tab(count);
00980 else
00981 count++;
00982 }
00983
00984 while (*textp != '\n' && count < XBREAK) {
00985 if (is_tab(*textp)) {
00986 tab_count = tab(count);
00987 while (count < XBREAK && count < tab_count) {
00988 count++;
00989 putchar(' ');
00990 }
00991 textp++;
00992 }
00993 else {
00994 if (*textp >= '\01' && *textp <= '\037') {
00995 #ifdef UNIX
00996 tputs(SO, 0, _putchar);
00997 #else
00998 string_print (rev_video);
00999 #endif
01000 putchar(*textp++ + '\100');
01001 #ifdef UNIX
01002 tputs(SE, 0, _putchar);
01003 #else
01004 string_print (normal_video);
01005 #endif
01006 }
01007 else
01008 putchar(*textp++);
01009 count++;
01010 }
01011 }
01012
01013
01014 if (count == XBREAK && *textp != '\n')
01015 putchar(textp[1]=='\n' ? *textp : SHIFT_MARK);
01016
01017
01018 if (clear_line == TRUE) {
01019 #ifdef UNIX
01020 tputs(CE, 0, _putchar);
01021 #else
01022 string_print(blank_line);
01023 #endif
01024 putchar('\n');
01025 }
01026 }
01027
01028
01029
01030
01031 int flush_buffer(fd)
01032 int fd;
01033 {
01034 if (out_count <= 0)
01035 return FINE;
01036 #ifdef UNIX
01037 if (fd == STD_OUT) {
01038 printf("%.*s", out_count, screen);
01039 _flush();
01040 }
01041 else
01042 #endif
01043 if (write(fd, screen, out_count) != out_count) {
01044 bad_write(fd);
01045 return ERRORS;
01046 }
01047 clear_buffer();
01048 return FINE;
01049 }
01050
01051
01052
01053
01054 void bad_write(fd)
01055 int fd;
01056 {
01057 if (fd == STD_OUT)
01058 exit(1);
01059
01060 clear_buffer();
01061 build_string(text_buffer, "Command aborted: %s (File incomplete)",
01062 (errno == ENOSPC || errno == -ENOSPC) ?
01063 "No space on device" : "Write error");
01064 error(text_buffer, NIL_PTR);
01065 }
01066
01067
01068
01069
01070 void catch(sig)
01071 int sig;
01072 {
01073
01074 signal(SIGQUIT, catch);
01075 quit = TRUE;
01076 }
01077
01078
01079
01080
01081 void abort_mined()
01082 {
01083 quit = FALSE;
01084
01085
01086 status_line("Really abort? ", NIL_PTR);
01087 if (getchar() != 'y') {
01088 clear_status();
01089 return;
01090 }
01091
01092
01093 raw_mode(OFF);
01094 set_cursor(0, ymax);
01095 putchar('\n');
01096 flush();
01097 #ifdef UNIX
01098 abort();
01099 #else
01100 exit(1);
01101 #endif
01102 }
01103
01104 #define UNDEF _POSIX_VDISABLE
01105
01106
01107
01108
01109
01110 void raw_mode(state)
01111 FLAG state;
01112 {
01113 static struct termios old_tty;
01114 static struct termios new_tty;
01115
01116 if (state == OFF) {
01117 tcsetattr(input_fd, TCSANOW, &old_tty);
01118 return;
01119 }
01120
01121
01122 tcgetattr(input_fd, &old_tty);
01123
01124
01125 tcgetattr(input_fd, &new_tty);
01126 new_tty.c_lflag &= ~(ICANON|ECHO|ECHONL);
01127 new_tty.c_iflag &= ~(IXON|IXOFF);
01128
01129
01130 new_tty.c_cc[VINTR] = new_tty.c_cc[VSUSP] = UNDEF;
01131 new_tty.c_cc[VQUIT] = '\\' & 037;
01132 signal(SIGQUIT, catch);
01133
01134 tcsetattr(input_fd, TCSANOW, &new_tty);
01135 }
01136
01137
01138
01139
01140
01141
01142
01143 void panic(message)
01144 register char *message;
01145 {
01146 extern char yank_file[];
01147
01148 #ifdef UNIX
01149 tputs(CL, 0, _putchar);
01150 build_string(text_buffer, "%s\nError code %d\n", message, errno);
01151 #else
01152 build_string(text_buffer, "%s%s\nError code %d\n", enter_string, message, errno);
01153 #endif
01154 (void) write(STD_OUT, text_buffer, length_of(text_buffer));
01155
01156 if (loading == FALSE)
01157 XT();
01158 else
01159 (void) unlink(yank_file);
01160 raw_mode(OFF);
01161
01162 #ifdef UNIX
01163 abort();
01164 #else
01165 exit(1);
01166 #endif
01167 }
01168
01169 char *alloc(bytes)
01170 int bytes;
01171 {
01172 char *p;
01173
01174 p = malloc((unsigned) bytes);
01175 if (p == NIL_PTR) {
01176 if (loading == TRUE)
01177 panic("File too big.");
01178 panic("Out of memory.");
01179 }
01180 return(p);
01181 }
01182
01183 void free_space(p)
01184 char *p;
01185 {
01186 free(p);
01187 }
01188
01189
01190
01191
01192
01193
01194
01195 void (*key_map[256])() = {
01196 MA, BL, MP, YA, SD, RD, MN, IF, DPC, S, S, DT, LR, S, DNW,LIB,
01197 DPW, WB, GR, SH, DLN, SU, VI, XWT, XT, PT, EL, ESC, I, GOTO,
01198 HIGH, LOW,
01199 S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, S,
01200 S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, S,
01201 S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, S,
01202 S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, S,
01203 S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, S,
01204 S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, DCC,
01205 S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, S,
01206 S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, S,
01207 S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, S,
01208 S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, S,
01209 S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, S,
01210 S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, S,
01211 S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, S,
01212 S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, S,
01213 };
01214
01215 int nlines;
01216 LINE *header;
01217 LINE *tail;
01218 LINE *cur_line;
01219 LINE *top_line;
01220 LINE *bot_line;
01221 char *cur_text;
01222 int last_y;
01223 char screen[SCREEN_SIZE];
01224
01225 int x, y;
01226 FLAG modified = FALSE;
01227 FLAG stat_visible;
01228 FLAG writable;
01229 FLAG loading;
01230 FLAG quit = FALSE;
01231 FLAG rpipe = FALSE;
01232 int input_fd = 0;
01233 int out_count;
01234 char file_name[LINE_LEN];
01235 char text_buffer[MAX_CHARS];
01236
01237
01238 #ifdef UNIX
01239 char *CE, *VS, *SO, *SE, *CL, *AL, *CM;
01240 #else
01241 char *enter_string = "\033[H\033[J";
01242 char *pos_string = "\033[%d;%dH";
01243 char *rev_scroll = "\033M";
01244 char *rev_video = "\033[7m";
01245 char *normal_video = "\033[m";
01246 char *blank_line = "\033[K";
01247 #endif
01248
01249
01250
01251
01252 FLAG yank_status = NOT_VALID;
01253 char yank_file[] = "/tmp/mined.XXXXXX";
01254 long chars_saved;
01255
01256
01257
01258
01259
01260 void initialize()
01261 {
01262 register LINE *line, *next_line;
01263
01264
01265 for (line = header->next; line != tail; line = next_line) {
01266 next_line = line->next;
01267 free_space(line->text);
01268 free_space((char*)line);
01269 }
01270
01271
01272 line->next = line->prev = line;
01273 x = y = 0;
01274 rpipe = modified = FALSE;
01275 }
01276
01277
01278
01279
01280 char *basename(path)
01281 char *path;
01282 {
01283 register char *ptr = path;
01284 register char *last = NIL_PTR;
01285
01286 while (*ptr != '\0') {
01287 if (*ptr == '/')
01288 last = ptr;
01289 ptr++;
01290 }
01291 if (last == NIL_PTR)
01292 return path;
01293 if (*(last + 1) == '\0') {
01294 *last = '\0';
01295 return basename(path);
01296 }
01297 return last + 1;
01298 }
01299
01300
01301
01302
01303
01304
01305 void load_file(file)
01306 char *file;
01307 {
01308 register LINE *line = header;
01309 register int len;
01310 long nr_of_chars = 0L;
01311 int fd = -1;
01312
01313 nlines = 0;
01314
01315
01316 writable = TRUE;
01317 if (file == NIL_PTR) {
01318 if (rpipe == FALSE)
01319 status_line("No file.", NIL_PTR);
01320 else {
01321 fd = 0;
01322 file = "standard input";
01323 }
01324 file_name[0] = '\0';
01325 }
01326 else {
01327 copy_string(file_name, file);
01328 if (access(file, 0) < 0)
01329 status_line("New file ", file);
01330 else if ((fd = open(file, 0)) < 0)
01331 status_line("Cannot open ", file);
01332 else if (access(file, 2) != 0)
01333 writable = FALSE;
01334 }
01335
01336
01337 loading = TRUE;
01338
01339 if (fd >= 0) {
01340 status_line("Reading ", file);
01341 while ((len = get_line(fd, text_buffer)) != ERRORS) {
01342 line = line_insert(line, text_buffer, len);
01343 nr_of_chars += (long) len;
01344 }
01345 if (nlines == 0)
01346 line = line_insert(line, "\n", 1);
01347 clear_buffer();
01348 cur_line = header->next;
01349 fstatus("Read", nr_of_chars);
01350 (void) close(fd);
01351 }
01352 else
01353 (void) line_insert(line, "\n", 1);
01354
01355 reset(header->next, 0);
01356
01357
01358 display (0, 0, header->next, last_y);
01359 move_to (0, 0);
01360 flush();
01361 loading = FALSE;
01362 }
01363
01364
01365
01366
01367
01368
01369 int get_line(fd, buffer)
01370 int fd;
01371 register char *buffer;
01372 {
01373 static char *last = NIL_PTR;
01374 static char *current = NIL_PTR;
01375 static int read_chars;
01376 register char *cur_pos = current;
01377 char *begin = buffer;
01378
01379 do {
01380 if (cur_pos == last) {
01381 if ((read_chars = read(fd, screen, SCREEN_SIZE)) <= 0)
01382 break;
01383 last = &screen[read_chars];
01384 cur_pos = screen;
01385 }
01386 if (*cur_pos == '\0')
01387 *cur_pos = ' ';
01388 } while ((*buffer++ = *cur_pos++) != '\n');
01389
01390 current = cur_pos;
01391 if (read_chars <= 0) {
01392 if (buffer == begin)
01393 return ERRORS;
01394 if (*(buffer - 1) != '\n')
01395 if (loading == TRUE)
01396 *buffer++ = '\n';
01397 else {
01398 *buffer = '\0';
01399 return NO_LINE;
01400 }
01401 }
01402
01403 *buffer = '\0';
01404 return buffer - begin;
01405 }
01406
01407
01408
01409
01410
01411 LINE *install_line(buffer, length)
01412 char *buffer;
01413 int length;
01414 {
01415 register LINE *new_line = (LINE *) alloc(sizeof(LINE));
01416
01417 new_line->text = alloc(length + 1);
01418 new_line->shift_count = 0;
01419 copy_string(new_line->text, buffer);
01420
01421 return new_line;
01422 }
01423
01424 void main(argc, argv)
01425 int argc;
01426 char *argv[];
01427 {
01428
01429
01430 register int index;
01431 struct winsize winsize;
01432
01433 #ifdef UNIX
01434 get_term();
01435 tputs(VS, 0, _putchar);
01436 tputs(CL, 0, _putchar);
01437 #else
01438 string_print(enter_string);
01439 #endif
01440 if (ioctl(STD_OUT, TIOCGWINSZ, &winsize) == 0 && winsize.ws_row != 0) {
01441 ymax = winsize.ws_row - 1;
01442 screenmax = ymax - 1;
01443 }
01444
01445 if (!isatty(0)) {
01446 if (argc != 1) {
01447 write(2, "Cannot find terminal.\n", 22);
01448 exit (1);
01449 }
01450 rpipe = TRUE;
01451 modified = TRUE;
01452 open_device();
01453 }
01454
01455 raw_mode(ON);
01456
01457 header = tail = (LINE *) alloc(sizeof(LINE));
01458 header->text = NIL_PTR;
01459 header->next = tail->prev = header;
01460
01461
01462 if (argc < 2)
01463 load_file(NIL_PTR);
01464 else {
01465 (void) get_file(NIL_PTR, argv[1]);
01466 load_file(argv[1]);
01467 }
01468
01469
01470 for (;;) {
01471 index = getchar();
01472 if (stat_visible == TRUE)
01473 clear_status();
01474 if (quit == TRUE)
01475 abort_mined();
01476 else {
01477 (*key_map[index])(index);
01478 flush();
01479 if (quit == TRUE)
01480 quit = FALSE;
01481 }
01482 }
01483
01484 }
01485
01486
01487
01488
01489
01490
01491
01492
01493 void RD()
01494 {
01495
01496 #ifdef UNIX
01497 tputs(VS, 0, _putchar);
01498 tputs(CL, 0, _putchar);
01499 #else
01500 string_print(enter_string);
01501 #endif
01502
01503
01504 display(0, 0, top_line, last_y);
01505
01506
01507 set_cursor(0, ymax);
01508 #ifdef UNIX
01509 tputs(CE, 0, _putchar);
01510 #else
01511 string_print(blank_line);
01512 #endif
01513 move_to(x, y);
01514 }
01515
01516
01517
01518
01519 void I()
01520 {
01521 }
01522
01523
01524
01525
01526 void XT()
01527 {
01528 if (modified == TRUE && ask_save() == ERRORS)
01529 return;
01530
01531 raw_mode(OFF);
01532 set_cursor(0, ymax);
01533 putchar('\n');
01534 flush();
01535 (void) unlink(yank_file);
01536 exit(0);
01537 }
01538
01539 void (*escfunc(c))()
01540 int c;
01541 {
01542 #if (CHIP == M68000)
01543 #ifndef COMPAT
01544 int ch;
01545 #endif
01546 #endif
01547 if (c == '[') {
01548
01549 c = getchar();
01550 #if (CHIP == M68000)
01551 #ifndef COMPAT
01552 if ((c >= '0') && (c <= '9')) ch = getchar();
01553
01554 #endif
01555 #endif
01556 switch (c) {
01557 case 'H': return(HO);
01558 case 'A': return(UP);
01559 case 'B': return(DN);
01560 case 'C': return(RT);
01561 case 'D': return(LF);
01562 #if (CHIP == M68000)
01563 #ifndef COMPAT
01564
01565
01566
01567
01568
01569
01570
01571
01572 case '1':
01573 switch (ch) {
01574 case '~': return(SF);
01575 case '7': (void) getchar(); return(MA);
01576 case '8': (void) getchar(); return(CTL);
01577 }
01578 case '2': return(SR);
01579 case '3': return(PD);
01580 case '4': return(PU);
01581 case '5': return(FS);
01582 case '6': return(EF);
01583 #endif
01584 #endif
01585 #if (CHIP == INTEL)
01586 case 'G': return(FS);
01587 case 'S': return(SR);
01588 case 'T': return(SF);
01589 case 'U': return(PD);
01590 case 'V': return(PU);
01591 case 'Y': return(EF);
01592 #endif
01593 }
01594 return(I);
01595 }
01596 #if (CHIP == M68000)
01597 #ifdef COMPAT
01598 if (c == 'O') {
01599
01600 switch (getchar()) {
01601 case 'P': return(SF);
01602 case 'Q': return(SR);
01603 case 'R': return(PD);
01604 case 'S': return(PU);
01605 case 'T': return(FS);
01606 case 'U': return(EF);
01607 case 'V': return(MA);
01608 case 'W': return(CTL);
01609 }
01610 }
01611 #endif
01612 #endif
01613 return(I);
01614 }
01615
01616
01617
01618
01619
01620
01621 void ESC()
01622 {
01623 register int count = 0;
01624 register void (*func)();
01625 int index;
01626
01627 index = getchar();
01628 while (index >= '0' && index <= '9' && quit == FALSE) {
01629 count *= 10;
01630 count += index - '0';
01631 index = getchar();
01632 }
01633 if (count == 0) {
01634 count = 1;
01635 func = escfunc(index);
01636 } else {
01637 func = key_map[index];
01638 if (func == ESC)
01639 func = escfunc(getchar());
01640 }
01641
01642 if (func == I) {
01643 clear_status();
01644 return;
01645 }
01646
01647 while (count-- > 0 && quit == FALSE) {
01648 if (stat_visible == TRUE)
01649 clear_status();
01650 (*func)(index);
01651 flush();
01652 }
01653
01654 if (quit == TRUE)
01655 error("Aborted", NIL_PTR);
01656 }
01657
01658
01659
01660
01661 int ask_save()
01662 {
01663 register int c;
01664
01665 status_line(file_name[0] ? basename(file_name) : "[buffer]" ,
01666 " has been modified. Save? (y/n)");
01667
01668 while((c = getchar()) != 'y' && c != 'n' && quit == FALSE) {
01669 ring_bell();
01670 flush();
01671 }
01672
01673 clear_status();
01674
01675 if (c == 'y')
01676 return WT();
01677
01678 if (c == 'n')
01679 return FINE;
01680
01681 quit = FALSE;
01682 return ERRORS;
01683 }
01684
01685
01686
01687
01688 int line_number()
01689 {
01690 register LINE *line = header->next;
01691 register int count = 1;
01692
01693 while (line != cur_line) {
01694 count++;
01695 line = line->next;
01696 }
01697
01698 return count;
01699 }
01700
01701
01702
01703
01704
01705 void file_status(message, count, file, lines, writefl, changed)
01706 char *message;
01707 register long count;
01708 char *file;
01709 int lines;
01710 FLAG writefl, changed;
01711 {
01712 register LINE *line;
01713 char msg[LINE_LEN + 40];
01714 char yank_msg[LINE_LEN];
01715
01716 if (count < 0)
01717 for (line = header->next; line != tail; line = line->next)
01718 count += length_of(line->text);
01719
01720 if (yank_status != NOT_VALID)
01721 build_string(yank_msg, " Buffer: %D char%s.", chars_saved,
01722 (chars_saved == 1L) ? "" : "s");
01723 else
01724 yank_msg[0] = '\0';
01725
01726 build_string(msg, "%s %s%s%s %d line%s %D char%s.%s Line %d", message,
01727 (rpipe == TRUE && *message != '[') ? "standard input" : basename(file),
01728 (changed == TRUE) ? "*" : "",
01729 (writefl == FALSE) ? " (Readonly)" : "",
01730 lines, (lines == 1) ? "" : "s",
01731 count, (count == 1L) ? "" : "s",
01732 yank_msg, line_number());
01733
01734 if (length_of(msg) + 1 > LINE_LEN - 4) {
01735 msg[LINE_LEN - 4] = SHIFT_MARK;
01736 msg[LINE_LEN - 3] = '\0';
01737 }
01738 status_line(msg, NIL_PTR);
01739 }
01740
01741
01742
01743
01744
01745 #if __STDC__
01746 void build_string(char *buf, char *fmt, ...)
01747 {
01748 #else
01749 void build_string(buf, fmt, va_alist)
01750 char *buf, *fmt;
01751 va_dcl
01752 {
01753 #endif
01754 va_list argptr;
01755 char *scanp;
01756
01757 #if __STDC__
01758 va_start(argptr, fmt);
01759 #else
01760 va_start(argptr);
01761 #endif
01762
01763 while (*fmt) {
01764 if (*fmt == '%') {
01765 fmt++;
01766 switch (*fmt++) {
01767 case 's' :
01768 scanp = va_arg(argptr, char *);
01769 break;
01770 case 'd' :
01771 scanp = num_out((long) va_arg(argptr, int));
01772 break;
01773 case 'D' :
01774 scanp = num_out((long) va_arg(argptr, long));
01775 break;
01776 default :
01777 scanp = "";
01778 }
01779 while (*buf++ = *scanp++)
01780 ;
01781 buf--;
01782 }
01783 else
01784 *buf++ = *fmt++;
01785 }
01786 va_end(argptr);
01787 *buf = '\0';
01788 }
01789
01790
01791
01792
01793
01794 char *num_out(number)
01795 long number;
01796 {
01797 static char num_buf[11];
01798 register long digit;
01799 register long pow = 1000000000L;
01800 FLAG digit_seen = FALSE;
01801 int i;
01802
01803 for (i = 0; i < 10; i++) {
01804 digit = number / pow;
01805 if (digit == 0L && digit_seen == FALSE && i != 9)
01806 num_buf[i] = ' ';
01807 else {
01808 num_buf[i] = '0' + (char) digit;
01809 number -= digit * pow;
01810 digit_seen = TRUE;
01811 }
01812 pow /= 10L;
01813 }
01814 for (i = 0; num_buf[i] == ' '; i++)
01815 ;
01816 return (&num_buf[i]);
01817 }
01818
01819
01820
01821
01822
01823
01824 int get_number(message, result)
01825 char *message;
01826 int *result;
01827 {
01828 register int index;
01829 register int count = 0;
01830
01831 status_line(message, NIL_PTR);
01832
01833 index = getchar();
01834 if (quit == FALSE && (index < '0' || index > '9')) {
01835 error("Bad count", NIL_PTR);
01836 return ERRORS;
01837 }
01838
01839
01840 while (index >= '0' && index <= '9' && quit == FALSE) {
01841 count *= 10;
01842 count += index - '0';
01843 index = getchar();
01844 }
01845
01846 if (quit == TRUE) {
01847 clear_status();
01848 return ERRORS;
01849 }
01850
01851 *result = count;
01852 return index;
01853 }
01854
01855
01856
01857
01858
01859 int input(inbuf, clearfl)
01860 char *inbuf;
01861 FLAG clearfl;
01862 {
01863 register char *ptr;
01864 register char c;
01865
01866 ptr = inbuf;
01867
01868 *ptr = '\0';
01869 while (quit == FALSE) {
01870 flush();
01871 switch (c = getchar()) {
01872 case '\b' :
01873 if (ptr > inbuf) {
01874 ptr--;
01875 #ifdef UNIX
01876 tputs(SE, 0, _putchar);
01877 #else
01878 string_print(normal_video);
01879 #endif
01880 if (is_tab(*ptr))
01881 string_print(" \b\b\b \b\b");
01882 else
01883 string_print(" \b\b \b");
01884 #ifdef UNIX
01885 tputs(SO, 0, _putchar);
01886 #else
01887 string_print(rev_video);
01888 #endif
01889 string_print(" \b");
01890 *ptr = '\0';
01891 }
01892 else
01893 ring_bell();
01894 break;
01895 case '\n' :
01896
01897 return (ptr == inbuf && clearfl == TRUE) ? NO_INPUT :FINE;
01898 default :
01899 if ((c >= ' ' && c <= '~') || c == '\t') {
01900 *ptr++ = c;
01901 *ptr = '\0';
01902 if (c == '\t')
01903 string_print("^I");
01904 else
01905 putchar(c);
01906 string_print(" \b");
01907 }
01908 else
01909 ring_bell();
01910 }
01911 }
01912 quit = FALSE;
01913 return ERRORS;
01914 }
01915
01916
01917
01918
01919
01920 int get_file(message, file)
01921 char *message, *file;
01922 {
01923 char *ptr;
01924 int ret;
01925
01926 if (message == NIL_PTR || (ret = get_string(message, file, TRUE)) == FINE) {
01927 if (length_of((ptr = basename(file))) > NAME_MAX)
01928 ptr[NAME_MAX] = '\0';
01929 }
01930 return ret;
01931 }
01932
01933
01934
01935
01936
01937 #ifdef UNIX
01938 #undef putchar
01939
01940 int _getchar()
01941 {
01942 char c;
01943
01944 if (read(input_fd, &c, 1) != 1 && quit == FALSE)
01945 panic ("Cannot read 1 byte from input");
01946 return c & 0377;
01947 }
01948
01949 void _flush()
01950 {
01951 (void) fflush(stdout);
01952 }
01953
01954 void _putchar(c)
01955 char c;
01956 {
01957 (void) write_char(STD_OUT, c);
01958 }
01959
01960 void get_term()
01961 {
01962 static char termbuf[50];
01963 extern char *tgetstr(), *getenv();
01964 char *loc = termbuf;
01965 char entry[1024];
01966
01967 if (tgetent(entry, getenv("TERM")) <= 0) {
01968 printf("Unknown terminal.\n");
01969 exit(1);
01970 }
01971
01972 AL = tgetstr("al", &loc);
01973 CE = tgetstr("ce", &loc);
01974 VS = tgetstr("vs", &loc);
01975 CL = tgetstr("cl", &loc);
01976 SO = tgetstr("so", &loc);
01977 SE = tgetstr("se", &loc);
01978 CM = tgetstr("cm", &loc);
01979 ymax = tgetnum("li") - 1;
01980 screenmax = ymax - 1;
01981
01982 if (!CE || !SO || !SE || !CL || !AL || !CM) {
01983 printf("Sorry, no mined on this type of terminal\n");
01984 exit(1);
01985 }
01986 }
01987 #endif