Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

414 lines
12 KiB

  1. /* $Header: /nw/tony/src/stevie/src/RCS/main.c,v 1.12 89/08/02 19:53:27 tony Exp $
  2. *
  3. * The main routine and routines to deal with the input buffer.
  4. */
  5. #include "stevie.h"
  6. int Rows; /* Number of Rows and Columns */
  7. int Columns; /* in the current window. */
  8. char INITFILENAME[] = "ntvi.ini"; /* file that's source'd at startup */
  9. char *Realscreen = NULL; /* What's currently on the screen, a single */
  10. /* array of size Rows*Columns. */
  11. char *Nextscreen = NULL; /* What's to be put on the screen. */
  12. char *Filename = NULL; /* Current file name */
  13. char *Appname = NULL; /* Name of program (vi, for instance) */
  14. LNPTR *Filemem; /* Pointer to the first line of the file */
  15. LNPTR *Filetop; /* Line 'above' the start of the file */
  16. LNPTR *Fileend; /* Pointer to the end of the file in Filemem. */
  17. /* (It points to the byte AFTER the last byte.) */
  18. LNPTR *Topchar; /* Pointer to the byte in Filemem which is */
  19. /* in the upper left corner of the screen. */
  20. LNPTR *Botchar; /* Pointer to the byte in Filemem which is */
  21. /* just off the bottom of the screen. */
  22. LNPTR *Curschar; /* Pointer to byte in Filemem at which the */
  23. /* cursor is currently placed. */
  24. int Cursrow, Curscol; /* Current position of cursor */
  25. int Cursvcol; /* Current virtual column, the column number of */
  26. /* the file's actual line, as opposed to the */
  27. /* column number we're at on the screen. This */
  28. /* makes a difference on lines that span more */
  29. /* than one screen line. */
  30. int Curswant = 0; /* The column we'd like to be at. This is used */
  31. /* try to stay in the same column through up/down */
  32. /* cursor motions. */
  33. bool_t set_want_col; /* If set, then update Curswant the next time */
  34. /* through cursupdate() to the current virtual */
  35. /* column. */
  36. int State = NORMAL; /* This is the current state of the command */
  37. /* interpreter. */
  38. int Prenum = 0; /* The (optional) number before a command. */
  39. int namedbuff = -1; /* the (optional) named buffer before a command */
  40. LNPTR *Insstart; /* This is where the latest insert/append */
  41. /* mode started. */
  42. bool_t Changed = 0; /* Set to 1 if something in the file has been */
  43. /* changed and not written out. */
  44. char *Redobuff; /* Each command should stuff characters into this */
  45. /* buffer that will re-execute itself. */
  46. char *Insbuff; /* Each insertion gets stuffed into this buffer. */
  47. int InsbuffSize;
  48. int Ninsert = 0; /* Number of characters in the current insertion. */
  49. char *Insptr = NULL;
  50. bool_t got_int=FALSE; /* set to TRUE when an interrupt occurs (if possible) */
  51. bool_t interactive = FALSE; /* set TRUE when main() is ready to roll */
  52. char **files; /* list of input files */
  53. int numfiles; /* number of input files */
  54. int curfile; /* number of the current file */
  55. static char *getcbuff;
  56. static char *getcnext = NULL;
  57. static void chk_mline();
  58. static void
  59. usage()
  60. {
  61. fprintf(stderr, "usage: stevie [file ...]\n");
  62. fprintf(stderr, " stevie -t tag\n");
  63. fprintf(stderr, " stevie +[num] file\n");
  64. fprintf(stderr, " stevie +/pat file\n");
  65. exit(1);
  66. }
  67. __cdecl main(argc,argv)
  68. int argc;
  69. char *argv[];
  70. {
  71. char *initstr; /* init string from the environment */
  72. char *tag = NULL; /* tag from command line */
  73. char *pat = NULL; /* pattern from command line */
  74. int line = -1; /* line number from command line */
  75. char *p1, *p2;
  76. p1 = strrchr(argv[0], '\\');
  77. if (!p1)
  78. p1 = strrchr(argv[0], ':');
  79. if (p1)
  80. p1++;
  81. else
  82. p1 = argv[0];
  83. p2 = strrchr(p1, '.');
  84. if (!p2)
  85. Appname = strsave(p1);
  86. else {
  87. Appname = malloc((size_t)(p2-p1+1));
  88. strncpy(Appname, p1, (size_t)(p2-p1));
  89. Appname[p2-p1] = '\0';
  90. }
  91. /*
  92. * Process the command line arguments.
  93. */
  94. if (argc > 1) {
  95. switch (argv[1][0]) {
  96. case '-': /* -t tag */
  97. if (argv[1][1] != 't')
  98. usage();
  99. if (argv[2] == NULL)
  100. usage();
  101. Filename = NULL;
  102. tag = argv[2];
  103. numfiles = 1;
  104. break;
  105. case '+': /* +n or +/pat */
  106. if (argv[1][1] == '/') {
  107. if (argv[2] == NULL)
  108. usage();
  109. Filename = strsave(argv[2]);
  110. pat = &(argv[1][1]);
  111. numfiles = 1;
  112. } else if (isdigit(argv[1][1]) || argv[1][1] == NUL) {
  113. if (argv[2] == NULL)
  114. usage();
  115. Filename = strsave(argv[2]);
  116. numfiles = 1;
  117. line = (isdigit(argv[1][1])) ?
  118. atoi(&(argv[1][1])) : 0;
  119. } else
  120. usage();
  121. break;
  122. default: /* must be a file name */
  123. Filename = strsave(argv[1]);
  124. files = &(argv[1]);
  125. numfiles = argc - 1;
  126. break;
  127. }
  128. } else {
  129. Filename = NULL;
  130. numfiles = 1;
  131. }
  132. curfile = 0;
  133. if (numfiles > 1)
  134. fprintf(stderr, "%d files to edit\n", numfiles);
  135. windinit();
  136. /*
  137. * Allocate LNPTR structures for all the various position pointers
  138. */
  139. if ((Filemem = (LNPTR *) malloc(sizeof(LNPTR))) == NULL ||
  140. (Filetop = (LNPTR *) malloc(sizeof(LNPTR))) == NULL ||
  141. (Fileend = (LNPTR *) malloc(sizeof(LNPTR))) == NULL ||
  142. (Topchar = (LNPTR *) malloc(sizeof(LNPTR))) == NULL ||
  143. (Botchar = (LNPTR *) malloc(sizeof(LNPTR))) == NULL ||
  144. (Curschar = (LNPTR *) malloc(sizeof(LNPTR))) == NULL ||
  145. (Insstart = (LNPTR *) malloc(sizeof(LNPTR))) == NULL ) {
  146. fprintf(stderr, "Can't allocate data structures\n");
  147. windexit(0);
  148. }
  149. screenalloc();
  150. filealloc(); /* Initialize Filemem, Filetop, and Fileend */
  151. inityank();
  152. getcbuff = malloc(1);
  153. if(((getcbuff = malloc(1 )) == NULL)
  154. || ((Redobuff = malloc(REDOBUFFMIN)) == NULL)
  155. || ((Insbuff = malloc(INSERTSLOP )) == NULL))
  156. {
  157. fprintf(stderr,"Can't allocate buffers\n");
  158. windexit(1);
  159. }
  160. *getcbuff = 0;
  161. InsbuffSize = INSERTSLOP;
  162. screenclear();
  163. {
  164. char *srcinitname,*initvar;
  165. bool_t unmalloc;
  166. unsigned x;
  167. if((initvar = getenv("INIT")) == NULL) {
  168. srcinitname = INITFILENAME;
  169. unmalloc = FALSE;
  170. } else {
  171. srcinitname = malloc((x = strlen(initvar))+strlen(INITFILENAME)+2);
  172. if(srcinitname == NULL) {
  173. fprintf(stderr,"Can't allocate initial source buffer\n");
  174. windexit(1);
  175. }
  176. unmalloc = TRUE;
  177. strcpy(srcinitname,initvar);
  178. if(srcinitname[x-1] != '\\') { // not NLS-aware!!
  179. srcinitname[x] = '\\';
  180. srcinitname[x+1] = '\0';
  181. }
  182. strcat(srcinitname,INITFILENAME);
  183. }
  184. dosource(srcinitname,FALSE);
  185. if(unmalloc) {
  186. free(srcinitname);
  187. }
  188. }
  189. if ((initstr = getenv("EXINIT")) != NULL) {
  190. char *lp, buf[128];
  191. if ((lp = getenv("LINES")) != NULL) {
  192. sprintf(buf, "%s lines=%s", initstr, lp);
  193. docmdln(buf);
  194. } else
  195. docmdln(initstr);
  196. }
  197. if (Filename != NULL) {
  198. if (readfile(Filename, Filemem, FALSE))
  199. filemess("[New File]");
  200. } else if (tag == NULL)
  201. msg("Empty Buffer");
  202. setpcmark();
  203. if (tag) {
  204. stuffin(":ta ");
  205. stuffin(tag);
  206. stuffin("\n");
  207. } else if (pat) {
  208. stuffin(pat);
  209. stuffin("\n");
  210. } else if (line >= 0) {
  211. if (line > 0)
  212. stuffnum(line);
  213. stuffin("G");
  214. }
  215. interactive = TRUE;
  216. edit();
  217. windexit(0);
  218. return 1; /* shouldn't be reached */
  219. }
  220. void
  221. stuffin(s)
  222. char *s;
  223. {
  224. char *p;
  225. if (s == NULL) { /* clear the stuff buffer */
  226. getcnext = NULL;
  227. return;
  228. }
  229. if (getcnext == NULL) {
  230. p = ralloc(getcbuff,strlen(s)+1);
  231. if(p) {
  232. getcbuff = p;
  233. strcpy(getcbuff,s);
  234. getcnext = getcbuff;
  235. } else {
  236. getcnext = NULL;
  237. }
  238. } else {
  239. p = ralloc(getcbuff,strlen(getcbuff)+strlen(s)+1);
  240. if(p) {
  241. getcnext += p - getcbuff;
  242. getcbuff = p;
  243. strcat(getcbuff,s);
  244. } else {
  245. getcnext = NULL;
  246. }
  247. }
  248. }
  249. void
  250. stuffnum(n)
  251. int n;
  252. {
  253. char buf[32];
  254. sprintf(buf, "%d", n);
  255. stuffin(buf);
  256. }
  257. int
  258. vgetc()
  259. {
  260. register int c;
  261. /*
  262. * inchar() may map special keys by using stuffin(). If it does
  263. * so, it returns -1 so we know to loop here to get a real char.
  264. */
  265. do {
  266. if ( getcnext != NULL ) {
  267. int nextc = *getcnext++;
  268. if ( *getcnext == NUL ) {
  269. *getcbuff = NUL;
  270. getcnext = NULL;
  271. }
  272. return(nextc);
  273. }
  274. c = inchar();
  275. } while (c == -1);
  276. return c;
  277. }
  278. /*
  279. * anyinput
  280. *
  281. * Return non-zero if input is pending.
  282. */
  283. bool_t
  284. anyinput()
  285. {
  286. return (getcnext != NULL);
  287. }
  288. /*
  289. * do_mlines() - process mode lines for the current file
  290. *
  291. * Returns immediately if the "ml" parameter isn't set.
  292. */
  293. #define NMLINES 5 /* no. of lines at start/end to check for modelines */
  294. void
  295. do_mlines()
  296. {
  297. int i;
  298. register LNPTR *p;
  299. if (!P(P_ML))
  300. return;
  301. p = Filemem;
  302. for (i=0; i < NMLINES ;i++) {
  303. chk_mline(p->linep->s);
  304. if ((p = nextline(p)) == NULL)
  305. break;
  306. }
  307. if ((p = prevline(Fileend)) == NULL)
  308. return;
  309. for (i=0; i < NMLINES ;i++) {
  310. chk_mline(p->linep->s);
  311. if ((p = prevline(p)) == NULL)
  312. break;
  313. }
  314. }
  315. /*
  316. * chk_mline() - check a single line for a mode string
  317. */
  318. static void
  319. chk_mline(s)
  320. register char *s;
  321. {
  322. register char *cs; /* local copy of any modeline found */
  323. register char *e;
  324. for (; *s != NUL ;s++) {
  325. if (strncmp(s, "vi:", 3) == 0 || strncmp(s, "ex:", 3) == 0) {
  326. cs = strsave(s+3);
  327. if ((e = strchr(cs, ':')) != NULL) {
  328. *e = NUL;
  329. stuffin(mkstr(CTRL('o')));
  330. docmdln(cs);
  331. }
  332. free(cs);
  333. }
  334. }
  335. }