-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcolour.cpp
1414 lines (1255 loc) · 42.9 KB
/
colour.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/**************************************************************************/
// colour.cpp - Dawn colour system, (c)1998-2001 Michael Garratt
/***************************************************************************
* The Dawn of Time v1.69r (c)1997-2004 Michael Garratt *
* >> A number of people have contributed to the Dawn codebase, with the *
* majority of code written by Michael Garratt - www.dawnoftime.org *
* >> To use this source code, you must fully comply with the dawn license *
* in licenses.txt... In particular, you may not remove this copyright *
* notice. *
**************************************************************************/
#include "include.h"
#include "colour.h"
#include "cust_col.h"
#include "help.h"
#include "clan.h"
#include "socials.h"
#include "interp.h"
#define MAX_RANDOM 14
char randomColours[MAX_RANDOM+2] = "SrRgGyYbBmMcCwW";
bool colour_convert_disabled=true;
//prototypes
int number_range( int from, int to );
/**************************************************************************/
// this table as all the entries the colour table is made from
colour_codes makeFullColourTableFrom[] = {
// code,special,dont_repeat,noColour,ansi, irc, ircWhite, html
// (think of dont_repeat as is_colour)
// IRC White uses black for `X, `x, `W and `w. dark gray for `S
// it doesn't use light gray (\00314,00)
//silver
{'s', false, true, "", "\033[1;30m", "\00314,01", "\00314,00", "</FONT><FONT COLOR=\"#7F7F7F\">"},
{'S', false, true, "", "\033[1;30m", "\00314,01", "\00314,00", "</FONT><FONT COLOR=\"#7F7F7F\">"},
//red
{'r', false, true, "", "\033[0;31m", "\00304,01", "\00304,00", "</FONT><FONT COLOR=\"#FF007F\">"},
{'R', false, true, "", "\033[1;31m", "\00305,01", "\00305,00", "</FONT><FONT COLOR=\"#FF0000\">"},
//green
{'g', false, true, "", "\033[0;32m", "\00303,01", "\00303,00", "</FONT><FONT COLOR=\"#007F00\">"},
{'G', false, true, "", "\033[1;32m", "\00309,01", "\00309,00", "</FONT><FONT COLOR=\"#00FF00\">"},
//yellow
{'y', false, true, "", "\033[0;33m", "\00307,01", "\00308,00", "</FONT><FONT COLOR=\"#7F7F00\">"},
{'Y', false, true, "", "\033[1;33m", "\00308,01", "\00307,00", "</FONT><FONT COLOR=\"#FFFF00\">"},
//blue
{'b', false, true, "", "\033[0;34m", "\00302,01", "\00302,00", "</FONT><FONT COLOR=\"#00007F\">"},
{'B', false, true, "", "\033[1;34m", "\00312,01", "\00312,00", "</FONT><FONT COLOR=\"#0000FF\">"},
//magenta
{'m', false, true, "", "\033[0;35m", "\00306,01", "\00306,00", "</FONT><FONT COLOR=\"#7F007F\">"},
{'M', false, true, "", "\033[1;35m", "\00313,01", "\00313,00", "</FONT><FONT COLOR=\"#FF00FF\">"},
//cyan
{'c', false, true, "", "\033[0;36m", "\00310,01", "\00310,00", "</FONT><FONT COLOR=\"#007F7F\">"},
{'C', false, true, "", "\033[1;36m", "\00311,01", "\00311,00", "</FONT><FONT COLOR=\"#00FFFF\">"},
//white
{'w', false, true, "", "\033[0;37m", "\00315,01", "\00301,00", "</FONT><FONT COLOR=\"#BFBFBF\">"},
{'W', false, true, "", "\033[1;37m", "\00300,01", "\00301,00", "</FONT><FONT COLOR=\"#FFFFFF\">"},
//Clear - aliased to white
{'x', false, true, "", "\033[0;37m", "\00315,01", "\00301,00", "</FONT><FONT COLOR=\"#BFBFBF\">"},
{'X', false, true, "", "\033[0;37m", "\00315,01", "\00301,00", "</FONT><FONT COLOR=\"#BFBFBF\">"},
// underlined character - ansi only
{'_', false, true, "", "\033[4m", "", "", ""},
// ~ symbol
{'-', false, false, "~", "~", "~", "~", "~"},
// ` symbol
{COLOURCODE, false, false, CCSTR, CCSTR, CCSTR, CCSTR, CCSTR},
// newline
{'1', true, false, "", "", "", "", "<BR>"}, // allowing `1 for newline
{'}', true, false, "", "", "", "", "<BR>"}, // allowing `} for newline (historical reasons)
{'+', false, false, "", "", "", "", ""}, // ignored by colour parser
// SPECIAL CODES
// flashing
{'F', true, true, "", "\033[5m", "", "", ""},
// -- RANDOM COLOUR
{'?', true, true, "", "", "", "", ""},
// -- SAVE
{'#', true, true, "", "", "", "", ""},
// -- RESTORE - NO REWIND
{'^', true, true, "", "", "", "", ""},
// -- RESTORE - AND REWIND
{'&', true, true, "", "", "", "", ""},
// // clear the screen - ansi only - disabled by default
// {'*', false, true, "", "\033[2J", "", "", ""},
{'=', true, true, "", "", "", "", ""}, // custom colour pointer
// -- mud Name - converted to the name of the mud in the gamesettings.
{'N', true, false, "", "", "", "", ""},
// CUSTOMISE THE OLC COLOURS TO CHANGE THE OLC COLOUR SCHEME
// olc colour 1
{'o', false, true, "", "\033[0;33m", "\00305,01", "\00305,00", "</FONT><FONT COLOR=\"#7F7F00\">"},
// olc colour 2
{'O', false, true, "", "\033[0;36m", "\00310,01", "\00310,00", "</FONT><FONT COLOR=\"#007F7F\">"},
// syntax code
{'.', false, true, "", "\033[1;33m", "\00308,01", "\00308,00", "</FONT><FONT COLOR=\"#FFFF00\">"},
// code,special,dont_repeat,noColour,ansi, mxp, irc , ircWhite, html
// (think of dont_repeat as is_colour)
// end of table marker
{'\0', false, false, "", "", "", ""}
};
/**************************************************************************/
// empty table now - it is configured when initColour is called
colour_codes colourTable[256] = {
{'\0', false, false, "", "", "","", ""}
};
/**************************************************************************/
void init_custom_colours();
/**************************************************************************/
// sets up the colour
void initColour(){
static bool already_initialised=false;
// only initialise the system once
if(already_initialised){
log_string("initColour(): Colour system already initialised");
return;
}
already_initialised=true;
init_custom_colours();
static colour_codes blankColourEntry;
int i;
char buf[20];
// check the colour codes are setup correctly
sprintf(buf,"%c",COLOURCODE);
if (strcmp(CCSTR, buf)){
bugf("initColour: colour codes setup incorrectly!\n");
bugf("in colour.h CCSTR should be a string version of COLOURCODE\n");
exit_error( 1 , "initColour", "colour codes setup incorrectly!");
}
// first initialise the table
for (i=0;i<256; i++){
colourTable[i]= blankColourEntry;
}
i=0;
while(makeFullColourTableFrom[i].code!='\0'){
colourTable[makeFullColourTableFrom[i].code]=makeFullColourTableFrom[i];
i++;
}
}
/**************************************************************************/
// return the colour code letter for a particular custom colour code
unsigned char resolve_custom_colour(unsigned char custom_colour_code, COLOUR_MEMORY_TYPE *cm)
{
// the character after the = is our pointer code
unsigned char pointer_code=custom_colour_code;
// find at what position the particular pointer
// code is stored in the colour pointer table
int custom_position=custom_colour_index[pointer_code];
// get the Custom Colour Code for that position
unsigned char ccc=cm->custom_colour[custom_position];
// if they haven't changed that particular colour use the
// colour from their underlying template for that position
if(ccc=='.'){ // . marks no change from template
ccc=cm->colour_template->template_colour[custom_position];
}
// by this stage we have the Custom Colour Code (ccc)
// that the user has assigned for a particular custom
// colour pointer.
// if Custom Colour Code is a number, it is a default
// template colour, convert into the template value
if(is_digit(ccc)){ // . marks no change from template
int default_template=custom_colour_index[ccc];
ccc=cm->custom_colour[default_template];
if(ccc=='.'){ // . means use template
ccc=cm->colour_template->template_colour[default_template];
}
}
return ccc;
}
/**************************************************************************/
#define sz ((int)sizeof(colour_codes))
char *fread_custom_colours(FILE* fp, bool player);
/**************************************************************************/
char helplink_code='\0'; // out here so show_olc_cmd's can hook into it
/**************************************************************************/
// process_colour returns a pointer to a static buffer... has a big buffer,
// assumes it isnt going to get a buffer overrun...
// easily big enough for anything Dawn uses at time of coding.
char *process_colour(const char *raw_text, connection_data *d)
{
if(IS_NULLSTR(raw_text)){
return "";
}
COLOUR_TYPE cType=CT_HTML;
COLOUR_MEMORY_TYPE *cm=NULL;
char_data *ch=NULL;
bool mxp_client=false;
bool mxp_secure_prefix_each_line=false;
bool flashing_disabled=false;
int gamename_count=0; // can only use gamename a fixed number of times per process colour
if(d){
flashing_disabled=d->flashing_disabled;
cType=d->colour_mode;
cm=&d->colour_memory;
mxp_client=d->mxp_enabled;
if(mxp_client && IS_SET(d->flags, CONNECTFLAG_MXP_SECURE_PREFIX_EACH_LINE)){
mxp_secure_prefix_each_line=true;
}else{
mxp_secure_prefix_each_line=false;
}
ch=CH(d);
}
char *sp=NULL;
// static variables - memory allocated first time things are run
static char *result; // permanantly allocated result buffer
static COLOUR_MEMORY_TYPE *static_cm=NULL;
static char brokenhelplink_code='\0';
if(result==NULL){ // first time run, initialise the statics
// allocate memory the first time things are run
logf("process_colour(): Allocating memory for colour processing.");
result=new char[120120];
// 120120 bytes is used for historical reasons.
// the old memory management system couldn't allocate a block larger
// than this... in an ideal world, the code would be rewritten to not
// use a buffer like this... but the implementation is acceptable
// for the time being.
assertp(result);
// init the static_cm (static colour memory)
static_cm=new COLOUR_MEMORY_TYPE;
memset(static_cm, 0, sizeof(COLOUR_MEMORY_TYPE));
static_cm->current='x';
memset(static_cm->saved, 'x', MAX_SAVED_COLOUR_ARRAY);
static_cm->saved_index=0;
static_cm->custom_colour=fread_custom_colours(NULL, true);
// allocate the helplink_code (the character used to specify helplinks)
int i;
for(i=0; custom_colour_table[i].custom_colour_code!='\0'; i++){
if(custom_colour_table[i].cc_code==CC_HELP_LINK){
helplink_code=custom_colour_table[i].custom_colour_code;
break;
}
}
assert(custom_colour_table[i].custom_colour_code!='\0');
// helplink_code now contains the '_' character unless it has been changed
// allocate the brokenhelplink_code (the character used to specify unfound helplinks)
for(i=0; custom_colour_table[i].custom_colour_code!='\0'; i++){
if(custom_colour_table[i].cc_code==CC_HELP_BROKENLINK){
brokenhelplink_code=custom_colour_table[i].custom_colour_code;
break;
}
}
assert(custom_colour_table[i].custom_colour_code!='\0');
// brokenhelplink_code now contains the '"' character unless it has been changed
}
char *pSrc, *pDest, *pLastNewLine, *baseCol,*col="";
// get setup for colour conversion
if(!cm){
cm=static_cm;
}
// assign the defaults to connections without any
if(cm->colour_template==NULL){
cm->colour_template=default_colour_template;
}
if(IS_NULLSTR(cm->custom_colour)){
cm->custom_colour=fread_custom_colours(NULL, true);
}
switch (cType){
default:
case CT_NOCOLOUR:
baseCol= colourTable[0].noColour; break;
case CT_ANSI:
baseCol= colourTable[0].ansi; break;
case CT_IRC:
baseCol= colourTable[0].irc; break;
case CT_IRCWHITE:
baseCol= colourTable[0].ircWhite; break;
case CT_HTML:
baseCol= colourTable[0].html;
mxp_client=true; // have side effect of converting <'s into < etc
break;
case CT_AUTODETECT:
if(d){
if(IS_IRCCON(d)){
baseCol= colourTable[0].ircWhite;
}else{
baseCol= colourTable[0].ansi;
}
}else{
baseCol= colourTable[0].noColour;
}
break;
}
if(cm->in_help_link){
pSrc="`=_"; // we get a help link, if we are already in a help link,
// switch pSrc over to raw_text when parsing the help link
}else{
pSrc=(char *)&raw_text[0];
}
pDest=result;
pLastNewLine=pDest;
if(mxp_secure_prefix_each_line){
// automatically put secure prefix for old clients
sp=MXP_SECURE_LINE;
while (*sp){
*pDest++=*sp++;
}
}
// convert the colours
while (*pSrc){
if (*pSrc==COLOURCODE){
// check for special codes
if(colourTable[(unsigned char)*(++pSrc)].special){
if (*pSrc=='='){ // colour customisation pointer system
unsigned char ccc;
pSrc++;
// If we are processing a custom helplink `=_
if(*pSrc==helplink_code && mxp_client){
unsigned char helpcol=0;
pSrc++; // skip the helplink_code
// check we dont have a helplink code without any help keyword
// following cause of end of input... if so we prefix the `=_
// to the next infomation sent thru the colour system for this
// colour memory... bit of a hack but efficient fix
if(IS_NULLSTR(pSrc)){
if(cm->in_help_link){
// last time we had a help link code at the end of a string
pSrc=(char *)&raw_text[0];
cm->in_help_link=false;
}else{
cm->in_help_link=true;
continue;
}
}
// copy thru any white space directly after the help colour code
while ( is_space(*pSrc) ){
*pDest++=*pSrc++;
}
// now get the help keyword
char keyword[MIL];
pSrc=help_find_keyword(pSrc, keyword, ch);
if(help_get_by_keyword(keyword, ch, false)){
ccc=resolve_custom_colour(helplink_code, cm);
}else{
ccc=resolve_custom_colour(brokenhelplink_code, cm);
}
// find out what colour our helplink/broken helplink resolved to
if (colourTable[(unsigned char)ccc].special)
{ // it isnt allow to be a special code except random
if(ccc=='?'){ // random
cm->current=randomColours[number_range(0, MAX_RANDOM)];
col=baseCol + ( sz * (int)cm->current );
}else{
col="";
}
helpcol=cm->current; // dont want to trigger a resend
}else{
// dont resend colours we have just sent
if(cm->current==ccc
&& colourTable[(unsigned char)ccc].dont_repeat){
col="";
}else{
col=baseCol + ( sz * (unsigned char)ccc);
// help colours dont affect the current colour since we revert to current after
}
helpcol=(unsigned char)ccc;
}
strcpy(pDest, col);
strcat(pDest, "<help>"); // doesn't need to be mxp_tagify'ed cause in process_colour
strcat(pDest, keyword);
strcat(pDest, "</help>");
if(helpcol!=cm->current){ // if the help colour isnt the current colour, revert back
strcat(pDest, baseCol + ( sz * (unsigned char)cm->current));
}
pDest+=str_len(pDest);
col="";
}else{
ccc=resolve_custom_colour(*pSrc, cm);
// now process the Custom Colour Code (ccc) as if a normal code
if (colourTable[(unsigned char)ccc].special)
{ // it isnt allow to be a special code except random
if(ccc=='?'){ // random
cm->current=randomColours[number_range(0, MAX_RANDOM)];
col=baseCol + ( sz * (int)cm->current );
}else{
pSrc++;
continue;
}
}else{
// dont resend colours we have just sent
if(cm->current==ccc
&& colourTable[(unsigned char)ccc].dont_repeat){
pSrc++;
continue;
}
col=baseCol + ( sz * (unsigned char)ccc);
cm->current=(unsigned char)ccc;
}
}
}else if (*pSrc=='F'){ // flashing, players can turn it off
if(!flashing_disabled){
if( colourTable[(int)*(pSrc)].dont_repeat) // can think of dont_repeat as is_colour
{
if(cm->current==*(pSrc)){
pSrc++;
continue;
}
cm->current=*(pSrc); // record the current colour only if it is a colour
}
col=baseCol + ( sz * (int)*pSrc );
}else{
col="";
}
}else if (*pSrc=='N'){ // game/mud Name
if(++gamename_count<10){
col=game_settings->gamename;
}else{
col="";
}
}else if (*pSrc=='?'){ // random
cm->current=randomColours[number_range(0, MAX_RANDOM)];
col=baseCol + ( sz * (int)cm->current );
}else if (*pSrc=='#'){ // save current colour using a save buffer
++cm->saved_index%=MAX_SAVED_COLOUR_ARRAY;
cm->saved[cm->saved_index]=cm->current;
col="";
}else if (*pSrc=='^'){ // restore colour, no rewind of save buffer
cm->current=cm->saved[cm->saved_index];
col=baseCol + ( sz * ((int)cm->current));
}else if (*pSrc=='&'){ // restore colour and rewind of save buffer
cm->current=cm->saved[cm->saved_index];
col=baseCol + ( sz * ((int)cm->current));
cm->saved_index=(cm->saved_index+(MAX_SAVED_COLOUR_ARRAY-1))%MAX_SAVED_COLOUR_ARRAY;
}else if (*pSrc=='1' || *pSrc==/*{*/'}'){ // newline
if(cType!=CT_HTML){
*pDest++='\r'; // all but html have the \r
}
*pDest++='\n';
// we back up the pointer to the character immediately following the last '\n'
pLastNewLine=pDest;
if(mxp_secure_prefix_each_line){
// automatically put secure prefix for old clients
sp=MXP_SECURE_LINE;
while (*sp){
*pDest++=*sp++;
}
}
if(cType==CT_IRC || cType==CT_IRCWHITE){// irc has to have the previous
col=baseCol + ( sz * ( (int)cm->current)); // lines colour resent
}else{
col="";
}
}
}else{ // not a special code - (colourTable[(int)*(++pSrc)].special)=false
// normal code
// dont resend colours we have already changed to
if( colourTable[(int)*(pSrc)].dont_repeat) // can think of dont_repeat as is_colour
{
if(cm->current==*(pSrc)){
pSrc++;
continue;
}
cm->current=*(pSrc); // record the current colour only if it is a colour
}
col=baseCol + ( sz * (int)*pSrc );
}
// by this stage, the colour code has been processed, and
// 'char *col' is pointing at the result of the code
// copy 'col' into the destination
while (*col){
*pDest++=*col++;
}
if(*pSrc){ // move onto the next source character
pSrc++;// (if we arent at the end of the string)
}
}else if (mxp_client){ // we didn't have a colour code, but checks for HTML coding
switch (*pSrc){
default: *pDest++=*pSrc++; break;
case '\r': // strip off \r in HTML
if(cType==CT_HTML){
pSrc++;
}else{
*pDest++=*pSrc++;
}
break;
case '\n': // record where the end of the line is so we can insert stuff after it
*pDest++=*pSrc++;
pLastNewLine=pDest;
if(mxp_secure_prefix_each_line){
// automatically put secure prefix for old clients
sp=MXP_SECURE_LINE;
while (*sp){
*pDest++=*sp++;
}
}
break;
case '&': // convert '&' symbol into correct html code
*pDest++='&';
*pDest++='a';
*pDest++='m';
*pDest++='p';
*pDest++=';';
pSrc++;
break;
case '<': // convert '<' symbol into correct html code
*pDest++='&';
*pDest++='l';
*pDest++='t';
*pDest++=';';
pSrc++;
break;
case '>': // convert '>' symbol into correct html code
*pDest++='&';
*pDest++='g';
*pDest++='t';
*pDest++=';';
pSrc++;
break;
case MXP_AMPERSAND: // convert mxp_ampersand into symbol '&'
*pDest++='&';
pSrc++;
break;
case MXP_BEGIN_TAG: // convert mxp_begin_tag into symbol '<'
*pDest++='<';
pSrc++;
break;
case MXP_END_TAG: // convert mxp_end_tag into symbol '>'
*pDest++='>';
pSrc++;
break;
#ifdef VALIDATE_HTML
case ' ': // convert ' ' into a space in HTML
*pDest++='&';
*pDest++='#';
*pDest++='1';
*pDest++='6';
*pDest++='0';
*pDest++=';';
pSrc++;
break;
#endif
}
}else if(*pSrc=='\n'){ // do special things at the end of the line?
*pDest++=*pSrc++; // copy the '\n' character
pLastNewLine=pDest;
if(mxp_secure_prefix_each_line){
// automatically put secure prefix for old clients
sp=MXP_SECURE_LINE;
while (*sp){
*pDest++=*sp++;
}
}
if (cType==CT_IRC || cType==CT_IRCWHITE){
// resend colour on new lines
col=baseCol + ( sz * ( (int)cm->current));
while (*col){
*pDest++=*col++;
}
}
}else{
*pDest++=*pSrc++; // copy plain characters to the destination
}
}
// terminate the string
*pDest='\0';
// return the length
return (result);
}
/**************************************************************************/
// convertColour
// returns the length of dest - the colour coded string
// - This function is old, and was the original basis for the webserver
// colour parsing system... Only the webhelp and
// write_to_descriptor_colour() still use it... since I dont have time
// to remove it from the source before the Dawn 1.7 release it remains...
// - Kalahn, September 2000.
int convertColour(const char *src, char *dest, COLOUR_TYPE cType, bool parital_html){
char *pSrc, *pDest, *baseCol,*col="";
char savedCol='x';
char currentCol='\0';
bool flashing_disabled=false;
switch (cType){
default:
case CT_NOCOLOUR:
baseCol= colourTable[0].noColour; break;
case CT_ANSI:
baseCol= colourTable[0].ansi; break;
case CT_IRC:
baseCol= colourTable[0].irc; break;
case CT_IRCWHITE:
baseCol= colourTable[0].ircWhite; break;
case CT_HTML:
baseCol= colourTable[0].html; break;
}
// convert the colours
pSrc=(char *)&src[0];
pDest=dest;
while (*pSrc){
if (*pSrc==COLOURCODE){
// check for special codes
if (colourTable[(int)*(++pSrc)].special){
if (*pSrc=='='){ // colour customisation pointer system
// the character after the = is our pointer code
unsigned char pointer_code=*(++pSrc);
// find at what position the particular pointer
// code is stored in the colour pointer table
int custom_position=custom_colour_index[pointer_code];
// get the Custom Colour Code from the default template
unsigned char ccc=default_colour_template->template_colour[custom_position];
// by this stage we have the default Custom Colour Code (ccc)
// if Custom Colour Code is a number, it is a default
// template colour, convert into the template value
if(is_digit(ccc)){ // . marks no change from template
int default_template=custom_colour_index[ccc];
ccc=default_colour_template->template_colour[default_template];
}
// now process the Custom Colour Code (ccc) as if a normal code
if (colourTable[(unsigned char)ccc].special)
{ // it isnt allow to be a special code except random
if(ccc=='?'){ // random
currentCol=randomColours[number_range(0, MAX_RANDOM)];
col=baseCol + ( sz * (int)currentCol);
}else{
pSrc++;
continue;
}
}else{
// dont resend colours we have just sent
if(currentCol==ccc
&& colourTable[(unsigned char)ccc].dont_repeat){
pSrc++;
continue;
}
col=baseCol + ( sz * (unsigned char)ccc);
currentCol=(unsigned char)ccc;
}
}else if (*pSrc=='F'){ // flashing, players can turn it off
if(!flashing_disabled){
if( colourTable[(int)*(pSrc)].dont_repeat) // can think of dont_repeat as is_colour
{
currentCol=*(pSrc);
col=baseCol + ( sz * (int)currentCol );
}
col=baseCol + ( sz * (int)*pSrc );
}else{
col="";
}
}else if (*pSrc=='?'){ // random
currentCol=randomColours[number_range(0, MAX_RANDOM)];
col=baseCol + ( sz * (int)currentCol );
}else
// save
if (*pSrc=='#'){
savedCol=currentCol;
col="";
}else
//restore
if (*pSrc=='^'){
col=baseCol + ( sz * ( (int)savedCol ));
currentCol=savedCol;
}else if //{
(*pSrc=='1' || *pSrc=='}'){ // newline
if(cType!=CT_HTML){
*pDest++='\r'; // all but html have the \r
}
*pDest++='\n';
// we back up the pointer to the character immediately following the last '\n'
// pLastNewLine=pDest;
if(cType==CT_IRC || cType==CT_IRCWHITE){// irc has to have the previous
col=baseCol + ( sz * ( (int)savedCol)); // lines colour resent
}else{
col="";
}
}
}else{
// normal code
// dont repeat displayed codes
if(colourTable[(int)*(pSrc)].dont_repeat
&& currentCol==*(pSrc)){
pSrc++;
continue;
}
currentCol=*(pSrc);
col=baseCol + ( sz * (int)currentCol );
}
while (*col){
*pDest++=*col++;
}
if(*pSrc){
pSrc++;
}
}else if (cType==CT_HTML){
switch (*pSrc){
default:
*pDest++=*pSrc++;
break;
case '\r': // strip off \r in HTML
pSrc++;
break;
/* case '\n': // convert \n into <BR> in HTML
*pDest++='<';
*pDest++='B';
*pDest++='R';
*pDest++='>';
#ifdef VALIDATE_HTML
*pDest++='\n';
#endif
pSrc++;
break;
*/
case '&': // convert '&' symbol into correct html code if not parital html
if(parital_html){
*pDest++=*pSrc++;
}else{
*pDest++='&';
*pDest++='a';
*pDest++='m';
*pDest++='p';
*pDest++=';';
pSrc++;
}
break;
case '>': // convert '>' symbol into correct html code if not parital html
if(parital_html){
*pDest++=*pSrc++;
}else{
*pDest++='&';
*pDest++='#';
*pDest++='6';
*pDest++='2';
*pDest++=';';
pSrc++;
}
break;
case '<': // convert '<' symbol into correct html code if not parital html
if(parital_html){
*pDest++=*pSrc++;
}else{
*pDest++='&';
*pDest++='#';
*pDest++='6';
*pDest++='0';
*pDest++=';';
pSrc++;
}
break;
#ifdef VALIDATE_HTML
case ' ': // convert ' ' into a space in HTML
*pDest++='&';
*pDest++='#';
*pDest++='1';
*pDest++='6';
*pDest++='0';
*pDest++=';';
pSrc++;
break;
#endif
}
}else if (cType==CT_IRC || cType==CT_IRCWHITE){
switch (*pSrc){
default:
*pDest++=*pSrc++;
break;
case '\n': // resend colour on new lines
*pDest++=*pSrc++;
col=baseCol + ( sz * ( (int)currentCol ));
while (*col){
*pDest++=*col++;
}
break;
}
}else{
*pDest++=*pSrc++;
}
}
// terminate the string
*pDest='\0';
// return the length
return (int)(pDest-dest);
}
/**************************************************************************/
// Function: strip_colour() - Kal October 2000
// Notes: Uses convertColour to parse all colour codes out, pretty simple
char *strip_colour(const char *coloured_text)
{
static int mri; // multi result index
static char *multi_result[3]; // circular managed result buffer
// nothing to do with empty strings
if( IS_NULLSTR(coloured_text)){
return "";
}
// rotate buffers
++mri%=3;
manage_dynamic_buffer(&multi_result[mri], str_len(coloured_text)+MSL); // maintain result so always has enough space
char *result=multi_result[mri]; // managed result buffer
convertColour(coloured_text, result, CT_NOCOLOUR, false);
return result;
}
/***************************************************************************/
const struct colour_table_type colour_table[]=
{
{"`x"}, // 0
{"`r"}, // 1
{"`g"}, // 2
{"`y"}, // 3
{"`b"}, // 4
{"`m"}, // 5
{"`c"}, // 6
{"`w"}, // 7
{"`s"}, // 8
{"`R"}, // 9
{"`G"}, // 10
{"`Y"}, // 11
{"`B"}, // 12
{"`M"}, // 13
{"`C"}, // 14
{"`W"}, // 15
};
/**************************************************************************/
// converts the use of { colour codes to ` in a string
// writes into a result buffer which is returned
char *colour_convert_code_format(char *text)
{
static char *result; // managed result buffer
// nothing to do with empty strings
if( IS_NULLSTR(text)){
return "";
}
manage_dynamic_buffer(&result, str_len(text)*2+1); // maintain result so always has enough space
// convert ` -> ``
// convert {{ -> {
// convert {` -> `?
// convert {} -> `1
// convert {=x to `=x (where x represents any character but nul)
// convert { -> `
char *d=result;
for(char *p=text; *p; p++){
if(*p=='`'){ // convert ` into ``
*d++='`';
*d++='`';
continue;
}else if(*p!='{'){ // we haven't found an oldstyle colour code
*d++=*p;
continue;
}
// { oldstyle colour code discovered, work on conversion code
p++; // skip to the character after the { code
if(!*p){ // check that we aren't looking at a NULL
break; // if we have terminate the loop
}
// convert {{ -> {
if(*p=='{'){
*d++='{';
continue;
}
// convert {` -> `?
if(*p=='`'){
*d++='`';
*d++='?';
continue;
}
// convert {} -> `1
if(*p=='}'){ // newline, new encouraged format
*d++='`';
*d++='1';
continue;
}
// convert {=x -> `=x (where x is anything but null)
if(*p=='='){
p++; // skip to the character after the = custom colour code character
if(!*p){ // check that we aren't looking at a NULL
break; // if we have terminate the loop
}
*d++='`';
*d++='=';
*d++=*p;
continue;
}
// not a special code, copy it over
*d++='`';
*d++=*p;
}
*d='\0'; // terminate the result
return result;
}
/**************************************************************************/
#define str_replace_colour_code(str) \
do{ char *t; \
if((str)!=NULL && (str)[0]!='\0'){ \
t=colour_convert_code_format(str); \
replace_string(str, t); \
} \
}while(0)
/**************************************************************************/
void colour_convert_helps( helpfile_data *pHelpfile )
{
if(colour_convert_disabled)return;
if(pHelpfile->colourcode==COLOURCODE){
// no need to convert the colour codes for this help
// since they have already been done
return;
}
logf(" >>>colour_convert_helps(%s)", pHelpfile->file_name);
// *** convert helps
for ( help_data *pHelp = help_first; pHelp; pHelp = pHelp->next )
{
if(pHelp->helpfile!=pHelpfile){
continue;
}
// help text
str_replace_colour_code(pHelp->text);
// help title
str_replace_colour_code(pHelp->title);
// help keywords
str_replace_colour_code(pHelp->keyword);