PageRenderTime 99ms CodeModel.GetById 37ms RepoModel.GetById 1ms app.codeStats 0ms

/src/Face.c

https://github.com/vidarh/FrexxEd
C | 784 lines | 609 code | 64 blank | 111 comment | 134 complexity | a0042ccdaba547256069864ba6f0fa09 MD5 | raw file
  1. /*
  2. * FrexxEd - Copyright (C) 1998, Daniel Stenberg and Kjell Ericson
  3. *
  4. * This file is open-source software. Please refer to the file LEGAL
  5. * for the licensing conditions and responsibilities.
  6. */
  7. /*
  8. * Faces
  9. */
  10. #include <stdio.h>
  11. #include <string.h>
  12. #include <proto/utility.h>
  13. #include "Buf.h"
  14. #include "Alloc.h"
  15. #include "Face.h"
  16. #include "UpdtScreenC.h"
  17. #include "FACT.h"
  18. #define BG(x) ((x)<<8)
  19. #define FG(x) (x)
  20. #define READ_BG(x) ((x)>>8)
  21. #define READ_FG(x) ((x)&255)
  22. extern DefaultStruct Default;
  23. static struct FaceControl *fc; /* current one */
  24. static struct FaceType facetype[MAX_STYLES]= {
  25. { cb_NORMAL, FG(1) | BG(0), FT_STATIC, "Normal" },
  26. { cb_REVERSE, FG(1) | BG(0), FT_STATIC, "Reverse" },
  27. { cb_BOLD, FG(1) | BG(0), FT_STATIC, "Bold" },
  28. { cb_ITALIC, FG(1) | BG(0), FT_STATIC, "Italic" },
  29. { cb_UNDERLINE, FG(1) | BG(0), FT_STATIC, "Underline" },
  30. { cb_NORMAL, FG(2) | BG(0), FT_STATIC, "Highlight" },
  31. { cb_NORMAL, FG(3) | BG(0), FT_STATIC, "Shadow" },
  32. { cb_ITALIC, FG(2) | BG(0), FT_STATIC, "Highitalic"}
  33. };
  34. static int NumOfFaceStyles=8; /* NUMBER of entries above */
  35. static struct Face *screenface[2];
  36. static int mode[2]; /* scan mode */
  37. static char lastchar[2]; /* final character of the end string */
  38. static int facenum; /* current face */
  39. static char *screentext; /* current text line */
  40. static struct screen_buffer *screenstore;
  41. static BufStruct *Storage;
  42. static char spacestat;
  43. static int firstnspace;
  44. static int start_offset;
  45. #define ISWORD(x) (Storage->using_fact->xflags[x]&factx_CLASS_WORD?1:0)
  46. #define ISNWORD(x) (!(Storage->using_fact->xflags[x]&factx_CLASS_WORD))
  47. #define ISSYMBOL(x) (Storage->using_fact->xflags[x]&factx_CLASS_SYMBOL?1:0)
  48. #define ISSPACE(x) (Storage->using_fact->xflags[x]&factx_CLASS_SPACE?1:0)
  49. #define ISUPPERCASE(x) (Storage->using_fact->xflags[x]&factx_UPPERCASE?1:0)
  50. #define ISLOWERCASE(x) (Storage->using_fact->xflags[x]&factx_LOWERCASE?1:0)
  51. #define ISOPEN(x) (Storage->using_fact->xflags[x]&factx_CLASS_OPEN?1:0)
  52. #define ISCLOSE(x) (Storage->using_fact->xflags[x]&factx_CLASS_CLOSE?1:0)
  53. #define ISNEWLINE(x) (Storage->using_fact->flags[x]&fact_NEWLINE)
  54. #define ISTAB(x) (Storage->using_fact->flags[x]&fact_TAB?1:0)
  55. static long __inline FaceStyleString(char *flags);
  56. static long __inline Faceaddflags(char *flagstr, char *usepipe);
  57. /**********************************************************************
  58. *
  59. * int Gethash();
  60. *
  61. * Return the hash number for the name received as argument.
  62. *
  63. *****/
  64. static __inline unsigned long Gethash(char *name, long len)
  65. {
  66. unsigned long hash=0;
  67. while(len--)
  68. hash=(hash<<1)+(*name++ +1)+(hash&(1<<31)?-2000000000:0);
  69. return hash;
  70. }
  71. #if 1
  72. #define SetColour(strlen, facenum, store, index) \
  73. do { \
  74. /* \
  75. * This is a found substring! \
  76. */ \
  77. int count=store-start_offset; \
  78. short pen = facetype[facenum].pen; \
  79. short style = facetype[facenum].style; \
  80. while (--count>=0 && \
  81. index-strlen<screenstore->linebuffer[count]) { \
  82. screenstore->control[count+start_offset]=style; \
  83. screenstore->colors[count+start_offset]=pen; \
  84. } \
  85. } while(0)
  86. #else
  87. void SetColour(strlen, facenum, store, index)
  88. {
  89. /*
  90. * This is a found substring!
  91. */
  92. int count=store-start_offset;
  93. short pen = facetype[facenum].pen;
  94. short style = facetype[facenum].style;
  95. while (--count>=0 &&
  96. index-strlen<screenstore->linebuffer[count]) {
  97. screenstore->control[count+start_offset]=style;
  98. screenstore->colors[count+start_offset]=pen;
  99. }
  100. }
  101. #endif
  102. struct FaceControl * __regargs InitFace(char *name)
  103. {
  104. struct FaceControl *facecontrol;
  105. facecontrol = Malloc(sizeof(struct FaceControl)+strlen(name));
  106. if(facecontrol) {
  107. memset(facecontrol, 0, sizeof(struct FaceControl));
  108. facecontrol->shortest=9999;
  109. facecontrol->conts=Malloc(sizeof(struct Face *));
  110. if(!facecontrol->conts) {
  111. Dealloc(facecontrol);
  112. return NULL;
  113. }
  114. facecontrol->conts[0]=NULL; /* this first is never really used */
  115. strcpy(facecontrol->name, name);
  116. {
  117. SharedStruct *shared=Default.SharedDefault.Next;
  118. while (shared) {
  119. if (!Stricmp(name, shared->face_name)) {
  120. shared->face=facecontrol;
  121. shared->face_updated_line=0;
  122. {
  123. BufStruct *count=shared->Entry;
  124. while (count) {
  125. count->face_top_updated_line=0;
  126. count->face_bottom_updated_line=0;
  127. count=count->NextSplitBuf;
  128. }
  129. }
  130. face_update=TRUE;
  131. }
  132. shared=shared->Next;
  133. }
  134. }
  135. #if 0
  136. AddFaceString(facecontrol, 0, "while", 5, NULL, 0, ADD_WORDONLY);
  137. AddFaceString(facecontrol, 0, "if", 2, NULL, 0, ADD_WORDONLY);
  138. AddFaceString(facecontrol, 0, "int", 3, NULL, 0, ADD_WORDONLY);
  139. AddFaceString(facecontrol, 0, "for", 3, NULL, 0, ADD_WORDONLY);
  140. AddFaceString(facecontrol, 0, "do", 2, NULL, 0, ADD_WORDONLY);
  141. AddFaceString(facecontrol, 0, "else", 4, NULL, 0, ADD_WORDONLY);
  142. AddFaceString(facecontrol, 1, "/*", 2, "*/", 2, ADD_IMPORTANT);
  143. AddFaceString(facecontrol, 1, "\"", 1, "\"", 1, ADD_BACKSLASH);
  144. AddFaceString(facecontrol, 0, "#", 1, "\n", 1, ADD_BACKSLASH|
  145. ADD_1STNONSPC|
  146. ADD_OBEYIMPO);
  147. #endif
  148. }
  149. return facecontrol;
  150. }
  151. /*
  152. * Add a string to a facecontrol.
  153. */
  154. long __regargs AddFaceString(struct FaceControl *facecontrol,
  155. char facetype,
  156. char *string,
  157. long strlen,
  158. char *string2,
  159. long strlen2,
  160. long flags)
  161. {
  162. struct Face *face;
  163. face = Malloc( sizeof(struct Face) + strlen + strlen2);
  164. if(face) {
  165. char lastchar = string[strlen-1];
  166. memcpy(face->string, string, strlen);
  167. face->string[strlen]=0; /* zero terminate for easier access */
  168. face->strlen = strlen;
  169. facecontrol->numofstrings++; /* increase number of things added */
  170. if(string2 && strlen2) {
  171. void *tmp;
  172. if(facecontrol->numofconts==MAX_CONTINUATIONS) {
  173. /* we can only take a certain amount of these kind since it will
  174. be using data space in the struct stored for each line in a
  175. single buffer */
  176. Dealloc(face);
  177. return SYNTAX_ERROR;
  178. }
  179. ++facecontrol->numofconts; /* increase number of continuation faces */
  180. memcpy(face->string2+strlen, string2, strlen2);
  181. tmp = Realloc((char *)facecontrol->conts, sizeof(struct Face *) *
  182. (facecontrol->numofconts + 1) /* plus the default */ );
  183. if(!tmp) {
  184. Dealloc(face);
  185. return OUT_OF_MEM;
  186. }
  187. facecontrol->conts = (struct Face **)tmp;
  188. facecontrol->conts[facecontrol->numofconts] = face;
  189. face->num = facecontrol->numofconts; /* set face num in face struct */
  190. }
  191. face->string2[strlen2+strlen]=0; /* zero terminate for easier access */
  192. face->strlen2 = strlen2;
  193. face->hash = Gethash(string, strlen);
  194. face->flags = (flags&ADD_1STNONSPC?FACE_1STNONSPC:0)|
  195. (flags&ADD_BACKSLASH?FACE_BACKSLASH:0)|
  196. (flags&ADD_OBEYIMPO?FACE_OBEYIMPOR:0)|
  197. (flags&ADD_WORDONLY?FACE_WORDONLY:FACE_ANYWHERE)|
  198. (flags&ADD_IMPORTANT?FACE_IMPORTANT:0);
  199. face->facetype = facetype;
  200. /* fix that shortest string stuff */
  201. if(facecontrol->shortest>strlen)
  202. facecontrol->shortest = strlen;
  203. /* if there already is a string ending with the same character as we
  204. do... */
  205. if(facecontrol->exist[ lastchar ])
  206. facecontrol->exist[ lastchar ] |= FC_SEVERAL; /* we're not alone */
  207. /* set the ->exist flag depending on the flags set for the string */
  208. facecontrol->exist[ lastchar ] |=
  209. (flags&ADD_WORDONLY?FACE_WORDONLY:FACE_ANYWHERE)|
  210. (flags&ADD_IMPORTANT?FC_IMPORTANT:0);
  211. /* link ourself to the chain of face-strings */
  212. face->next = facecontrol->strings[lastchar%FACETABLE_SIZE];
  213. facecontrol->strings[lastchar%FACETABLE_SIZE] = face;
  214. }
  215. else {
  216. return OUT_OF_MEM;
  217. }
  218. return OK;
  219. }
  220. struct Face * MatchWord(struct Face *face,
  221. long col,
  222. long flags)
  223. {
  224. if(!ISWORD(screentext[ col + 1 ])) {
  225. /*
  226. * We're at the end of a word, get the entire word and its
  227. * checksum
  228. */
  229. long n=col;
  230. while(--col >= 0 && ISWORD(screentext[ col ]) );
  231. n -= col++; /* we have the length */
  232. /* word is 'n' bytes long starting at 'col' */
  233. if(n<=FACESTRING_LENGTH) {
  234. /*
  235. * This isn't longer than maxlength, cause if it is, we won't
  236. * have to bother to check the word.
  237. */
  238. unsigned long hash = Gethash(&screentext[col], n);
  239. do {
  240. if(((face->flags&(FACE_WORDONLY|flags)) == (FACE_WORDONLY|flags)) &&
  241. face->hash == hash &&
  242. !memcmp(face->string, &screentext[col], n)) {
  243. if (face->flags&FACE_1STNONSPC &&
  244. col != firstnspace)
  245. continue;
  246. return face;
  247. }
  248. } while(face=face->next);
  249. }
  250. }
  251. return NULL;
  252. }
  253. struct Face * __inline
  254. MatchAnyWhere(struct Face *face,
  255. long col,
  256. long flags)
  257. {
  258. do {
  259. if(((face->flags&(FACE_ANYWHERE|flags)) == (FACE_ANYWHERE|flags)) &&
  260. col + 1 >= face->strlen &&
  261. !memcmp(face->string,
  262. &screentext[ col - face->strlen + 1],
  263. face->strlen)) {
  264. if (face->flags&FACE_1STNONSPC &&
  265. col != firstnspace)
  266. continue;
  267. return face; /* found it! */
  268. }
  269. } while(face=face->next);
  270. return NULL; /* none found */
  271. }
  272. void StringMatchInit(BufStruct *storage,
  273. char *text, /* buffer line */
  274. struct screen_buffer *dest, /* destination storage */
  275. int offset, /* start offset */
  276. int line) /* line */
  277. {
  278. screentext = text;
  279. screenstore = dest;
  280. Storage = storage;
  281. spacestat = FALSE;
  282. firstnspace = 0;
  283. start_offset = offset;
  284. fc = Storage->shared->face;
  285. if(storage->shared->text[line-1].old_style) {
  286. facenum=1;
  287. screenface[0]=fc->conts[storage->shared->text[line-1].old_style];
  288. mode[0] = screenface[0]->flags|FACE_CONTINUE;
  289. lastchar[0] = screenface[0]->string2[screenface[0]->strlen+screenface[0]->strlen2-1];
  290. }
  291. else
  292. facenum = 0;
  293. if(storage->shared->text[line-1].current_style) {
  294. screenface[facenum]=fc->conts[storage->shared->text[line-1].current_style];
  295. mode[facenum] = screenface[facenum]->flags|FACE_CONTINUE;
  296. lastchar[facenum] = screenface[facenum]->string2[screenface[facenum]->strlen+screenface[facenum]->strlen2-1];
  297. }
  298. else {
  299. mode[facenum]=0;
  300. }
  301. }
  302. int __regargs StringMatchEnd(BufStruct *Storage,
  303. int line)
  304. {
  305. char old_old = BUF(shared->text[line].old_style);
  306. char old_curr = BUF(shared->text[line].current_style);
  307. BUF(shared->text[line].current_style)=mode[facenum]&FACE_CONTINUE?screenface[facenum]->num:0;
  308. BUF(shared->text[line].old_style)=facenum?screenface[0]->num:0;
  309. if (old_old!=BUF(shared->text[line].old_style) ||
  310. old_curr!=BUF(shared->text[line].current_style))
  311. return FALSE;
  312. return TRUE;
  313. }
  314. void __regargs
  315. StringMatch(char byte, /* character in text */
  316. int index, /* byte position in line */
  317. int store) /* store position index */
  318. {
  319. long flags = 0;
  320. if(!spacestat && !ISSPACE(byte)) {
  321. spacestat = TRUE;
  322. firstnspace = index;
  323. }
  324. if( mode[facenum] & FACE_CONTINUE ) {
  325. if(mode[facenum] & FACE_BACKSLASH &&
  326. ('\\' == byte ||
  327. mode[facenum] & FACE_SKIPNEXT)) {
  328. /*
  329. * If backslash-aware is 'ON', then do the following if we're on
  330. * a backslash or the letter following it.
  331. */
  332. if(mode[facenum] & FACE_SKIPNEXT)
  333. /* we're on the byte after a backslash */
  334. mode[facenum] &= ~FACE_SKIPNEXT;
  335. else
  336. /* we're supposed to skip next letter */
  337. mode[facenum] |= FACE_SKIPNEXT;
  338. /* still the same mode here */
  339. if(-1 != store)
  340. SetColour(1, screenface[facenum]->facetype, store, index);
  341. return;
  342. }
  343. else if(mode[facenum] & FACE_OBEYIMPOR &&
  344. fc->exist[ byte ] & FC_IMPORTANT) {
  345. flags = FACE_IMPORTANT; /* it better be important! ;) */
  346. }
  347. else if(byte == lastchar[facenum] &&
  348. index >= screenface[facenum]->strlen2-1 &&
  349. !memcmp(&screenface[facenum]->string2[screenface[facenum]->strlen],
  350. &screentext[index - screenface[facenum]->strlen2 + 1],
  351. screenface[facenum]->strlen2)) {
  352. mode[facenum]=0;
  353. if(-1 != store)
  354. SetColour(screenface[facenum]->strlen2,
  355. screenface[facenum]->facetype,
  356. store,
  357. index);
  358. if(facenum)
  359. --facenum;
  360. return;
  361. }
  362. else {
  363. /* still the same mode here */
  364. if(-1 != store)
  365. SetColour(1, screenface[facenum]->facetype, store, index);
  366. return;
  367. }
  368. }
  369. if( fc->exist[byte] ) {
  370. char code = fc->exist[byte];
  371. struct Face *face = fc->strings [ byte % FACETABLE_SIZE ];
  372. if(code & FACE_WORDONLY &&
  373. (face = MatchWord(face, index, flags)))
  374. ;
  375. else if(code & FACE_ANYWHERE &&
  376. /*
  377. * We may have matched some word right *now*.
  378. * Check all FACE_ANYWHERE strings on the text in the buffer.
  379. */
  380. (face = MatchAnyWhere(face, index, flags)) )
  381. ;
  382. else {
  383. if(mode[facenum] & FACE_CONTINUE) {
  384. /* still the same mode here */
  385. if(-1 != store)
  386. SetColour(1, screenface[facenum]->facetype, store, index);
  387. }
  388. return;
  389. }
  390. if(-1 != store)
  391. SetColour(face->strlen, face->facetype, store, index);
  392. if(face->strlen2) {
  393. if(FACE_IMPORTANT == flags)
  394. ++facenum;
  395. /*
  396. * If this turns out to be a "starting" string!
  397. */
  398. mode[facenum] |= FACE_CONTINUE|face->flags;
  399. lastchar[facenum] = face->string2[face->strlen+face->strlen2-1];
  400. screenface[facenum] = face;
  401. }
  402. }
  403. }
  404. /*
  405. FPL USAGE:
  406. int face = FaceGet("c-mode", 1); // create one if missing
  407. */
  408. struct FaceControl *Allfaces; /* main linked list pointer */
  409. struct FaceControl *FaceGet(char *facename, long mode)
  410. {
  411. struct FaceControl *fc = Allfaces;
  412. struct FaceControl *old=NULL;
  413. struct FaceControl *new;
  414. if(fc) {
  415. do {
  416. if(!Stricmp(facename, fc->name)) {
  417. return fc;
  418. }
  419. old = fc;
  420. } while(fc = fc->next);
  421. }
  422. if(FACEGET_CHECK == mode)
  423. return NULL;
  424. new = InitFace(facename);
  425. if(new) {
  426. if(old)
  427. old->next = new;
  428. else
  429. Allfaces = new;
  430. }
  431. return new;
  432. }
  433. char **FaceListFaces(int *faces)
  434. {
  435. struct FaceControl *fc = Allfaces;
  436. long num=0;
  437. char **list;
  438. while(fc) {
  439. fc = fc->next;
  440. num++;
  441. }
  442. if(num) {
  443. list = Malloc(sizeof(char *) * num);
  444. if(list) {
  445. num=0;
  446. fc = Allfaces;
  447. while(fc) {
  448. list[num++]=fc->name;
  449. fc = fc->next;
  450. }
  451. }
  452. else
  453. num=0;
  454. }
  455. *faces = num;
  456. return list;
  457. }
  458. /* static struct FaceType facetype[MAX_STYLES]= { */
  459. char **FaceListStyles(int *faces)
  460. {
  461. char **list;
  462. list = Malloc(sizeof(char *) * NumOfFaceStyles);
  463. if(list) {
  464. register int i;
  465. for(i=0; i< NumOfFaceStyles; i++)
  466. list[i] = facetype[i].name;
  467. *faces = NumOfFaceStyles;
  468. }
  469. else {
  470. *faces = 0;
  471. list = NULL;
  472. }
  473. return list;
  474. }
  475. char *GetFaceStyle(char *style, int *fg, int *bg)
  476. {
  477. static char buffer[80];
  478. int i=0;
  479. do {
  480. if(!Stricmp(style, facetype[i].name)) {
  481. char *pnt=buffer;
  482. int num=0;
  483. strcpy(buffer, "normal"); /* default non-styled style */
  484. if(facetype[i].style&cb_REVERSE) {
  485. strcpy(pnt, "reverse");
  486. num++;
  487. pnt += strlen(pnt);
  488. }
  489. if(facetype[i].style&cb_BOLD) {
  490. if(num++)
  491. *pnt++='|';
  492. strcpy(pnt, "bold");
  493. pnt += strlen(pnt);
  494. }
  495. if(facetype[i].style&cb_ITALIC) {
  496. if(num++)
  497. *pnt++='|';
  498. strcpy(pnt, "italic");
  499. pnt += strlen(pnt);
  500. }
  501. if(facetype[i].style&cb_UNDERLINE) {
  502. if(num++)
  503. *pnt++='|';
  504. strcpy(pnt, "underline");
  505. pnt += strlen(pnt);
  506. }
  507. *fg = READ_FG(facetype[i].pen);
  508. *bg = READ_BG(facetype[i].pen);
  509. return buffer;
  510. }
  511. } while(++i<MAX_STYLES && facetype[i].name);
  512. return NULL;
  513. }
  514. /*
  515. FPL USAGE:
  516. Get the style named "c-keywords" OR create one that is bold with
  517. foreground pen 3 and background pen 0. If none matched and none
  518. could be created, it will return the style of the best match and
  519. no style will be named like this.
  520. style = FaceStyle("c-keywords", "bold", 3, 0);
  521. */
  522. #define FACE_REWRITE 1
  523. int __regargs FaceStyle(char *name, char *flags, int fg, int bg, int opts)
  524. {
  525. int i=0;
  526. long style;
  527. short pens;
  528. char found=FALSE;
  529. do {
  530. if(!Stricmp(name, facetype[i].name)) {
  531. if(opts & FACE_REWRITE) {
  532. found = TRUE;
  533. break;
  534. }
  535. return i;
  536. }
  537. } while(++i<MAX_STYLES && facetype[i].name);
  538. style = FaceStyleString(flags);
  539. pens = FG(fg) | BG(bg);
  540. if(!found) {
  541. if(MAX_STYLES == i) {
  542. /* all types are in use, and we couldn't find the one we wanted,
  543. try scanning for one that has the pens and style all right
  544. if not this routine should try getting one that fits almost!
  545. (left TODO) */
  546. i=0;
  547. do {
  548. if((pens == facetype[i].pen) &&
  549. (style == facetype[i].style))
  550. return i;
  551. } while(++i<MAX_STYLES);
  552. return 0; /* the built-in, normal type */
  553. }
  554. facetype[i].name = Strdup(name);
  555. ++NumOfFaceStyles;
  556. }
  557. facetype[i].pen = pens;
  558. facetype[i].style = style;
  559. return i;
  560. }
  561. static long __inline FaceStyleString(char *flags)
  562. {
  563. long result=0;
  564. char *pnt=flags;
  565. do {
  566. if(!Strnicmp("Bold", pnt, 4)) {
  567. result |= cb_BOLD;
  568. pnt+=4;
  569. } else if(!Strnicmp("Normal", pnt, 6)) {
  570. result |= cb_NORMAL;
  571. pnt+=6;
  572. } else if(!Strnicmp("Italic", pnt, 6)) {
  573. result |= cb_ITALIC;
  574. pnt+=6;
  575. } else if(!Strnicmp("Underline", pnt, 9)) {
  576. result |= cb_UNDERLINE;
  577. pnt+=9;
  578. } else if(!Strnicmp("Reverse", pnt, 7)) {
  579. result |= cb_REVERSE;
  580. pnt+=7;
  581. } else
  582. ++pnt;
  583. } while('|' == *pnt++);
  584. return result;
  585. }
  586. /*
  587. FPL USAGE:
  588. FaceAdd(face, // add word(s) to this face
  589. style, // use the c-keywords style
  590. // Specify all words we want to add to this face with this
  591. // particular style, we can of course add more words at a
  592. // later time
  593. "for|do|while|else|if|int|long|short|char|extern",
  594. "word" // these are word-only matches, that must be surrounded
  595. // with non-word letters to get recognized
  596. );
  597. */
  598. int __regargs FaceAdd(struct FaceControl *fc,
  599. int style,
  600. char *addstring,
  601. long addlen,
  602. char *flagstr,
  603. char *endstring,
  604. long endlen)
  605. {
  606. struct FaceControl *fco=Allfaces;
  607. long flags;
  608. char usepipe=FALSE;
  609. char *end;
  610. char *start;
  611. int ret;
  612. while(fco) {
  613. if(fc == fco)
  614. break;
  615. fco = fco->next;
  616. }
  617. if(!fco)
  618. /* illegal face specified! */
  619. return 0;
  620. flags = Faceaddflags(flagstr, &usepipe);
  621. if(endstring || usepipe) {
  622. /* one single string */
  623. /*
  624. Example use:
  625. AddFaceString(facecontrol, 0, "while", 5, NULL, 0, ADD_WORDONLY);
  626. */
  627. ret = AddFaceString(fc, style, addstring, addlen,
  628. endstring, endlen, flags);
  629. }
  630. else {
  631. /* possibly multiple strings */
  632. start = addstring;
  633. do {
  634. end = strchr(start, '|');
  635. if(!end)
  636. end = strchr(start, '\0');
  637. if(end-start)
  638. ret = AddFaceString(fc, style, start, end-start, NULL, 0, flags);
  639. start = end+1;
  640. } while (!ret && ('|' == *end));
  641. }
  642. return ret;
  643. }
  644. /*
  645. FLAGS for FaceAdd():
  646. ====================
  647. usepipe - the pipe ('|') letter is a part of the actual string
  648. word - the string(s) must match as a word-only
  649. anywhere - matches wherever it appears in the text (default)
  650. strong - a strong string. Will conquer weak ones.
  651. weak - a weak string. Will be conquered by strong ones.
  652. 1nonspace - must be the first non-whitespace on a line to match
  653. backslash - a letter following a backslash will be ignored
  654. */
  655. static __inline long Faceaddflags(char *flagstr, char *usepipe)
  656. {
  657. long result=0;
  658. char *pnt=flagstr;
  659. do {
  660. if(!Strnicmp("usepipe", pnt, 7)) {
  661. *usepipe=TRUE;
  662. pnt+=7;
  663. } else if(!Strnicmp("word", pnt, 4)) {
  664. result |= ADD_WORDONLY;
  665. pnt+=4;
  666. } else if(!Strnicmp("anywhere", pnt, 8)) {
  667. result &= ~ADD_WORDONLY;
  668. pnt+=8;
  669. } else if(!Strnicmp("strong", pnt, 6)) {
  670. result |= ADD_IMPORTANT;
  671. pnt+=6;
  672. } else if(!Strnicmp("weak", pnt, 4)) {
  673. result |= ADD_OBEYIMPO;
  674. pnt+=4;
  675. } else if(!Strnicmp("1nonspace", pnt, 9)) {
  676. result |= ADD_1STNONSPC;
  677. pnt+=9;
  678. } else if(!Strnicmp("backslash", pnt, 9)) {
  679. result |= ADD_BACKSLASH;
  680. pnt+=9;
  681. } else
  682. ++pnt;
  683. } while('|' == *pnt++);
  684. return result;
  685. }
  686. void __regargs CleanupAllFaces()
  687. {
  688. struct FaceControl *fc = Allfaces;
  689. struct FaceControl *next=NULL;
  690. int i;
  691. if(fc) {
  692. do {
  693. next = fc->next;
  694. for(i=0; i<FACETABLE_SIZE; ++i) {
  695. struct Face *facestr = fc->strings[i];
  696. struct Face *facenxt;
  697. facestr = fc->strings[i];
  698. while(facestr) {
  699. facenxt = facestr->next;
  700. Dealloc(facestr);
  701. facestr = facenxt;
  702. }
  703. }
  704. Dealloc(fc->conts); /* remove conts pointer allocation */
  705. Dealloc(fc); /* remove the full face */
  706. } while(fc = next);
  707. }
  708. for(i=0; i<MAX_STYLES; ++i) {
  709. if(facetype[i].name && !(facetype[i].flags&FT_STATIC)) {
  710. Dealloc(facetype[i].name);
  711. }
  712. }
  713. }