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.

517 lines
14 KiB

  1. #include "zext.h"
  2. /*
  3. * Modifications
  4. * 12-Sep-1988 mz Made WhenLoaded match declaration
  5. *
  6. */
  7. #define fLeftSide(ch) ((ch) == '[' || (ch) == '{' || (ch) == '(' || (ch) == '<' )
  8. #define EOF (int)0xFFFFFFFF
  9. #define BOF (int)0xFFFFFFFE
  10. #define EOL (int)0xFFFFFFFD
  11. #ifndef TRUE
  12. #define FALSE 0
  13. #define TRUE (!FALSE)
  14. #endif
  15. #ifndef NULL
  16. #define NULL ((void *) 0)
  17. #endif
  18. #define SQ '\''
  19. #define DQ '\"'
  20. #define ANYCHAR '\0'
  21. #define BACKSLASH '\\'
  22. /****************************************************************************
  23. * *
  24. * Handle apostrophes ( which look like single quotes, but don't come in *
  25. * pairs ) by defining a maximum number of chars that can come between *
  26. * single quotes. 4 will handle '\000' and '\x00' *
  27. * *
  28. ****************************************************************************/
  29. #define SQTHRESH 4
  30. flagType pascal EXTERNAL PMatch (unsigned, ARG far *, flagType);
  31. char MatChar (char);
  32. void openZFile (void);
  33. void lopen (PFILE, int, int) ;
  34. int rgetc (void);
  35. int ngetc (void);
  36. int lgetc (void);
  37. void pos (COL far *, LINE far *);
  38. flagType ParenMatch (int, flagType);
  39. /****************************************************************************
  40. * *
  41. * PMatch(argData, pArg, fMeta) *
  42. * *
  43. * argData - ignored *
  44. * pArg - ignored *
  45. * fMeta - TRUE means search for first matchable character *
  46. * *
  47. * RETURNS: *
  48. * *
  49. * TRUE if matching character was found. *
  50. * FALSE if not. *
  51. * *
  52. * SIDE EFFECTS: *
  53. * *
  54. * Changes location of cursor. *
  55. * *
  56. * DESCRIPTION: *
  57. * *
  58. * <pmatch>: If the cursor is on a "match" character, find the *
  59. * match and move the cursor there. If not, do *
  60. * nothing. *
  61. * *
  62. * <arg><pmatch>: Same as <pmatch>, but search forward for a "match" *
  63. * character if we're not on one. *
  64. * *
  65. * Always ignore characters between quotes. *
  66. * *
  67. * Match characters currently supported are: *
  68. * *
  69. * '{' and '}' *
  70. * '[' and ']' *
  71. * '(' and ')' *
  72. * '<' and '>' *
  73. * *
  74. * NOTES: *
  75. * *
  76. * This is defined as a CURSORFUNC, and therefore can be used to *
  77. * select text as part of an argument. For example, to grab the body *
  78. * of a function, go to the opening brace of the body and do *
  79. * <arg><pmatch><pick>. *
  80. * *
  81. ****************************************************************************/
  82. flagType pascal EXTERNAL PMatch (
  83. unsigned int argData,
  84. ARG far * pArg,
  85. flagType fMeta
  86. )
  87. {
  88. COL x;
  89. LINE y;
  90. char ch;
  91. //
  92. // Unreferenced parameters
  93. //
  94. (void)argData;
  95. (void)pArg;
  96. /* Set up file functions */
  97. openZFile ();
  98. /* If current character has no match ... */
  99. if (!MatChar (ch = (char)ngetc()))
  100. {
  101. if (fMeta)
  102. { /* Move forward looking for first matchable character */
  103. if (!ParenMatch (ANYCHAR, TRUE)) return FALSE;
  104. pos ((COL far *)&x, (LINE far *)&y);
  105. MoveCur (x, y);
  106. return TRUE;
  107. }
  108. else return FALSE;
  109. }
  110. if (ParenMatch ((int)ch, (flagType)fLeftSide(ch)))
  111. { /* We got one */
  112. pos ((COL far *)&x, (LINE far *)&y);
  113. MoveCur (x, y);
  114. return TRUE;
  115. }
  116. return FALSE; /* No match found */
  117. }
  118. /****************************************************************************
  119. * *
  120. * ParenMatch (chOrig, fForward) *
  121. * *
  122. * chOrig - character we are trying to match. *
  123. * fForward - TRUE means search forward, FALSE search backwards *
  124. * Returns TRUE if match found, false otherwise *
  125. * *
  126. * RETURNS: * *
  127. * *
  128. * TRUE if matching character found, FALSE if not. *
  129. * *
  130. * SIDE EFFECTS: *
  131. * *
  132. * Changes internal cursor location *
  133. * *
  134. * DESCRIPTION: *
  135. * *
  136. * Search for the next character that "pairs" with 'ch'. Account for * *
  137. * nesting. Ignore all characters between double quotes and single *
  138. * quotes. Recognize escaped quotes. Account for apostrophes. *
  139. * *
  140. ****************************************************************************/
  141. flagType ParenMatch (
  142. int chOrig,
  143. flagType fForward
  144. )
  145. {
  146. int lvl = 0, state = 0, sqcnt = 0;
  147. int (*nextch)(void) = (int (*)(void))(fForward ? rgetc : lgetc);
  148. int (*_ungetch)(void) = (int (*)(void))(fForward ? lgetc : rgetc);
  149. int ch, chMatch;
  150. if (chOrig) chMatch = (int)MatChar ((char)chOrig);
  151. while ((ch = (*nextch)()) >= 0)
  152. switch (state)
  153. {
  154. case 0: /* Regular text */
  155. if (ch == SQ)
  156. if (fForward) state = 1;
  157. else state = 5;
  158. else if (ch == DQ)
  159. if (fForward) state = 3;
  160. else state = 7;
  161. else
  162. if (chOrig != ANYCHAR)
  163. if (ch == chOrig) lvl++; /* Nest in one */
  164. else
  165. {
  166. if (ch == chMatch) /* Nest out or ...*/
  167. if (!lvl--) goto found;/* Found it! */
  168. }
  169. else
  170. if ((flagType)MatChar ((char)ch)) goto found; /* Found one! */
  171. break;
  172. case 1: /* Single quote moving forwards */
  173. sqcnt++;
  174. if (ch == BACKSLASH) state = 2;
  175. else if (ch == SQ || /* We matched the ', or ... */
  176. sqcnt > SQTHRESH ) /* ... we gave up trying */
  177. {
  178. sqcnt = 0;
  179. state = 0;
  180. }
  181. break;
  182. case 2: /* Escaped character inside single quotes */
  183. sqcnt++;
  184. state = 1;
  185. break;
  186. case 3: /* Double quote moving forwards */
  187. if (ch == BACKSLASH) state = 4;
  188. else if (ch == DQ) state = 0;
  189. break;
  190. case 4: /* Escaped character inside double quotes */
  191. state = 3;
  192. break;
  193. case 5: /* Single quote moving backwards */
  194. sqcnt++;
  195. if (ch == SQ) state = 6;
  196. else if (sqcnt > SQTHRESH)
  197. {
  198. sqcnt = 0;
  199. state = 0;
  200. }
  201. break;
  202. case 6: /* Check for escaped single quote moving backwards */
  203. sqcnt++;
  204. if (ch == BACKSLASH) state = 5;
  205. else
  206. {
  207. sqcnt = 0;
  208. (*_ungetch)();
  209. state = 0;
  210. }
  211. break;
  212. case 7: /* Double quote moving backwards */
  213. if (ch == DQ) state = 8;
  214. break;
  215. case 8: /* Check for escaped double quote moving backwards */
  216. if (ch == BACKSLASH) state = 7;
  217. else
  218. {
  219. (*_ungetch)();
  220. state = 0;
  221. }
  222. break;
  223. }
  224. return FALSE;
  225. found: return TRUE;
  226. }
  227. /****************************************************************************
  228. * *
  229. * MatChar(ch) *
  230. * *
  231. * ch - Character to match *
  232. * *
  233. * RETURNS: *
  234. * *
  235. * Character that matches the argument *
  236. * *
  237. * SIDE EFFECTS: *
  238. * *
  239. * None. *
  240. * *
  241. * DESCRIPTION *
  242. * *
  243. * Given one character out of one of the pairs {}, [], (), <>, return *
  244. * the other one. *
  245. * *
  246. ****************************************************************************/
  247. char MatChar (
  248. char ch
  249. )
  250. {
  251. switch (ch)
  252. {
  253. case '{': return '}';
  254. case '}': return '{';
  255. case '[': return ']';
  256. case ']': return '[';
  257. case '(': return ')';
  258. case ')': return '(';
  259. case '<': return '>';
  260. case '>': return '<';
  261. default : return '\0';
  262. }
  263. }
  264. /****************************************************************************
  265. * *
  266. * Extension specific file reading state. *
  267. * *
  268. * The static globals record the current state of file reading. The *
  269. * pmatch extension reads through the file either forwards or backwards. *
  270. * The state is kept as the current column and row, the contents of the *
  271. * current line, the length of the current line and the file, and some *
  272. * flags. *
  273. * *
  274. ****************************************************************************/
  275. static char LineBuf[BUFLEN]; /* Text of current line in file */
  276. static COL col ; /* Current column in file (0-based) */
  277. static LINE line ; /* Current line in file (0-based) */
  278. static int numCols ; /* Columns of text on curent line */
  279. static LINE numLines; /* Number of lines in the file */
  280. static PFILE pFile ; /* File to be reading from */
  281. static flagType fEof ; /* TRUE ==> end-of-file reached last time */
  282. static flagType fBof ; /* TRUE ==> begin-of-file reached last time */
  283. char CurFile[] = "" ; /* Current file to Z */
  284. /****************************************************************************
  285. * *
  286. * openZFile() *
  287. * *
  288. * SIDE EFFECTS: *
  289. * *
  290. * Changes globals pFile, fEof, fBof, col, line, numCols, numLines *
  291. * and LineBuf *
  292. * *
  293. * DESCRIPTION: *
  294. * *
  295. * Opens the current file. This must be called before trying to read *
  296. * the file. This is not a true "open" because it need not be closed *
  297. * *
  298. ****************************************************************************/
  299. void openZFile ()
  300. {
  301. COL x;
  302. LINE y;
  303. GetTextCursor ((COL far *)&x, (LINE far *)&y);
  304. /* Get Z handle for current file */
  305. pFile = FileNameToHandle (CurFile, CurFile);
  306. fEof = FALSE; /* We haven't read the end of file */
  307. fBof = FALSE; /* We haven't read the beginning of file */
  308. col = x; /* We start where Z is now in the file */
  309. line = y; /* We start where Z is now in the file */
  310. /* We pre-read the current line */
  311. numCols = GetLine (line, (char far *)LineBuf, pFile);
  312. /* We find the length of file (in lines) */
  313. numLines = FileLength (pFile);
  314. }
  315. /****************************************************************************
  316. * *
  317. * rgetc () *
  318. * *
  319. * RETURNS: *
  320. * *
  321. * Next character in file, not including line terminators. EOF if *
  322. * there are no more. *
  323. * *
  324. * SIDE EFFECTS: *
  325. * *
  326. * Changes globals col, numCols, numLines, LineBuf, fEof, fBof and *
  327. * line. *
  328. * *
  329. * DESCRIPTION: *
  330. * *
  331. * Advances current file position to the right, then returns the *
  332. * character found there. Reads through blank lines if necessary *
  333. * *
  334. ****************************************************************************/
  335. int
  336. rgetc ()
  337. {
  338. if (fEof) return (int)EOF; /* We already hit EOF last time */
  339. if (++col >= numCols) /* If next character is on the next line ... */
  340. {
  341. /* ... get next non-blank line (or EOF) */
  342. while ( ++line < numLines &&
  343. !(numCols = GetLine (line, (char far *)LineBuf, pFile)));
  344. if (line >= numLines)
  345. { /* Oh, no more lines */
  346. fEof = TRUE;
  347. return (int)EOF;
  348. }
  349. col = 0; /* We got a line, so start in column 0 */
  350. }
  351. fBof = FALSE; /* We got something, so we can't be at BOF */
  352. return LineBuf[col];
  353. }
  354. /****************************************************************************
  355. * *
  356. * ngetc() *
  357. * *
  358. * RETURNS: *
  359. * *
  360. * Character at current position. EOF or BOF if we are at end or top *
  361. * of file. *
  362. * *
  363. ****************************************************************************/
  364. int
  365. ngetc()
  366. {
  367. if (fEof) return (int)EOF;
  368. if (fBof) return (int)BOF;
  369. return LineBuf[col];
  370. }
  371. /****************************************************************************
  372. * *
  373. * lgetc () *
  374. * *
  375. * RETURNS: *
  376. * *
  377. * Previous character in file, not including line terminators. EOF *
  378. * if there are no more. *
  379. * *
  380. * SIDE EFFECTS: *
  381. * *
  382. * Changes globals col, numCols, numLines, LineBuf, fEof, fBof and *
  383. * line. *
  384. * *
  385. * DESCRIPTION: *
  386. * *
  387. * Decrements current file position to the right, then returns the *
  388. * character found there. Reads through blank lines if necessary *
  389. * *
  390. ****************************************************************************/
  391. int
  392. lgetc ()
  393. {
  394. if (fBof) return (int)BOF; /* We already it BOF last time */
  395. if (--col < 0)
  396. { /* If prev character is on prev line ... */
  397. /* ... get prev non-blank line (or BOF) */
  398. while ( --line >= 0 &&
  399. !(numCols = GetLine (line, (char far *)LineBuf, pFile)));
  400. if (line < 0)
  401. { /* We're at the top of the file */
  402. fBof = TRUE;
  403. return (int)BOF;
  404. }
  405. col = numCols - 1; /* We got a line, so start at last character */
  406. }
  407. fEof = (int)FALSE;
  408. return LineBuf[col];
  409. }
  410. /****************************************************************************
  411. * *
  412. * pos (&x, &y) *
  413. * *
  414. * SIDE EFFECTS: *
  415. * *
  416. * Fills memory at *x and *y with current file position. *
  417. * *
  418. * DESCRIPTION: *
  419. * *
  420. * Gets the current file position. Far pointers are needed because *
  421. * SS != DS. *
  422. * *
  423. ****************************************************************************/
  424. void pos (fpx, fpy)
  425. COL far *fpx;
  426. LINE far *fpy;
  427. {
  428. *fpx = col;
  429. *fpy = line;
  430. }
  431. /****************************************************************************
  432. * *
  433. * WhenLoaded () *
  434. * *
  435. * DESCRIPTION: *
  436. * *
  437. * Attach to ALT+P and issue sign-on message. *
  438. * *
  439. ****************************************************************************/
  440. void PMatchWhenLoaded ()
  441. {
  442. return;
  443. }