Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/doc/xaosdev.info
blob: 57b5d826bfe21de72008b8227983462769a3fc05 (plain)
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
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
This is Info file xaosdev.info, produced by Makeinfo version 1.68 from
the input file xaosdev.texinfo.

INFO-DIR-SECTION Graphics
START-INFO-DIR-ENTRY
* XaoS: (xaosdev).               The fast real-time interactive fractal zoomer
                                  (developers documentation
END-INFO-DIR-ENTRY

   (C) 1997 Jan Hubicka

   Permission is granted to make and distribute verbatim copies of this
manual provided the copyright notice and this permission notice are
preserved on all copies.


File: xaosdev.info,  Node: Top,  Prev: (dir),  Up: (dir)

XaoS 3.1
********

                                An real-time interactive fractal zoomer
                                                         Hacker's guide
                                                           May 14, 1998

   This manual contains documentation for those who are interested in
studying and improving XaoS sources or using them in other programs.
It includes description of algorithm and documentation of those parts
of XaoS I think they should be useful for someone.

* Menu:

* design::		Overview of the XaoS design
* driver::		Driver API description
* gui-driver::		Writing user interface driver
* eui::			Writing an external user interface
* ui-helper::		UI helper library
* xthreads::		XaoS thread library
* filters::		Filters
* algorithm::		Algorithm description
* timerlib::		The timer library
* registry::		XaoS function registry
* index::		Function command and variable index


File: xaosdev.info,  Node: design,  Next: driver,  Prev: Top,  Up: Top

Overview of the XaoS design
***************************

   Whole sources of XaoS are designed into several "libraries" (some of
them are not really libraries, but added into other's, but should be
separated easily).

   Understanding to the main philosophy should help you to navigate in
the sources.  I also expect that many of the lower level stuff should
be useful in the other projects, since it is designed to be fairly
generic.

   So here is an overview from the lowest level stuff to the highest.

Palette and image library
=========================

   Sources are in directory `src/filter'. The aim of palette library is
to provide relatively abstract interface to the various visuals and
hide differences in the hardware and driver implementation. Fixedcolor,
pseudocolor, grayscale and truecolor visuals should be handled in the
almost same way.

   It provides the structure `palette', which contains actual palette.
You might allocate new colors here (you give RGB value and
corresponding pixel is returned), interpolate colors where possible,
cycle colors and so on.  Every palette also consist from the two
parts--the preallocated color cells and the actual palette. This lets
for example to GUI possibility to allocate statically colors for its
texts and dialogs, while rest of palette is under control of different
parts of XaoS.

   This library also contain set of functions to allocate different
palettes used by other parts. I expected that different parts of XaoS
should use same palette. Nothing similar happened yet, but functions
are kept here.

   The image library is built at the top of palette library. It extends
functionality for handling actual image data. Each image is represented
by one or two frame-buffers (it is useful for double-buffering). One
frame-buffer is called current and other old. They should be flipped by
special function.  Program can draw into both of them.

   Frame-buffers are hold as the set of pointers to the scan-lines.
This brings better flexibility, because tricks like sub-windows, or
flipped bitmaps are possible. Also speeds up, since you should avoid
one multiplication.

   The last significant information image structure hold is of course
bpp depth.  It is counted in bytes, and should be 0-4. Where 0 is used
for 1bit bitmaps.

Filter library
==============

   Source are available in `src/filter'. This library controls the
process of creation of the image. It handles an queue of the filters,
where each filter should modify the image. There are two special filter
at the beginning and end of queue. The first filter is usually the
actual fractal engine which creates image, while the terminal filter is
usually user interface helper library.

Xthread library
===============

   This library provides interface to various multi-threading libraries
(currently the BeOS, plan9 and POSIX implementations are available). It
allows to run various function paraelly and some synchronization
primitives (semaphores). It is simple, but has all the functionality
required for the XaoS engine.

Fractal library
===============

   Source are available in `src/engine/', headers in `fractal.h'.  This
library contains the actual fractal calculation routines. It operates
with fractal context, which contains informations like current formula,
seed for julia, palette etc.

   Functions for calculating the various fractal types and various
coloring modes are available here.

Zooming engine and other filters.
=================================

   Source are available in `src/engine/'.  This is the actual zooming
engine filter. It is done in fairly independent way at fractal library,
so it should be possibly used for zooming other stuff.  (it was already
used for zooming large scale images containing maps of Hungary).

   All other filter has their special file, where is implementation and
structure containing all functions exported from the filter to user
interface. They are registered in the file `ui_helper'.  One other
terminal filter is implemented--Julia morpher. Other filters adds
special effects (such as motion blur), or does conversions (such as
rotation, dithering etc.)

Timer library
=============

   This library provides many of very useful timing primitives. Such as
timers, etc. Currently it is used by some other programs too.

xio library
===========

   This library aims to provide united interface to file-system. Some
strange systems (such as MacOS) has file-system API done in much
different way than in UNIX. They don't have names in string, and uses
special structures etc.

xshl library
============

   Xshl stands for XaoS simple hypertext library. It contains fairly
universal engine parsing an xshl language. It is similar to HTML with
some additions and many restrictions. It should render this texts for
the proportional/non-proportional fonts and various sizes.

help library
============

   it is built at the top of xshl and xio libraries. It should read
help files, wick contains an chapters. Parse chapter with given keyword
etc.

xmenu library
=============

   This is the XaoS function registry. All functions from UI-Helper
library are registered in the registry. From this registry the menus,
dialogs, command line options and scripting language are built.

Catalog library
===============

   This is library for handling an message catalogs. It should read
catalog and convert the keyword into actual message.

PNG library
===========

   This library provides the function for saving an image from Image
library to the file (in PNG format). Other formats should be added as
well if required.

UI-helper library
=================

   This library controls all the low-level stuff and provides an high
level interface to it. It has functions for playing animations,
zooming/UN-zooming and such. It heavily uses all the described
libraries. It don't implement functions for handling menus and such,
but makes great help for such implementations, because of the function
registry database.

Ugly interface
==============

   This is currently the only real user interface for XaoS (there is
also an second, wich is used for rendering animations, but it is not
user interface, how users expect it). It is built at the top of
UI-helper library and provides functions for drawing menus, dialogs and
such.  It has drivers for many platforms, and it should be easily
ported to the others.

   In the future, it should be quite easily to extended to let drivers
specify their own menu/dialog handling code, so it should be possible
to give it an "native" look of given platform.

   It has also an function, where an GUI drawing routines are disabled.
Function registry database is transfered trough pipe to external
program, wick should build the menus and act as external user
interface. It then back sends an commands in the scripting language
representing things, that user done.  So it is an another way, how to
give native look to ugly interface.

   Ugly interface has also one serious limitation--for the historical
reasons it is coded to handle just one window (rest of XaoS probably
can do multiple windows--untested). So in windowed environments it is
impossible to open multiple menus with fractals. At the other hand,
this limitation is not so important, once external GUI enter the role.
They should just start multiple XaoS engines. This will bring extra
robustness, multitasking and some other advantages, so it is the
proffered way. Thats why I don't plan to remove this limitation yet.


File: xaosdev.info,  Node: driver,  Next: gui-driver,  Prev: design,  Up: Top

Driver API description
**********************

   To port successfully XaoS to some platform you need:

   * ANSI C compatible optimizing compiler. Note that optimizing
     compiler is really required, since XaoS is coded to be good target
     for optimizations and don't have any routines coded in assembly,
     so if you will use some bad compiler, you should receive more than
     ten times slower result. Also note that some compilers has serious
     problems with compiling XaoS--like most of DOS compilers (Watcom
     C, Borland C, Microsoft C etc...), has serious problems.  They
     generate incorrect code or crash during compilation. I highly
     recommend to use GNU C compiler. Even some versions of GNU C has
     problems. Please read `compilers.txt' for more information.

   * Fast way to avoid division by zero/overflow and other floating
     point exception. XaoS is carefully coded to not to crash in this
     case, but don't have any tests to avoid such situation and expect
     random result in such case.  Many platforms provide way to switch
     coprocessor into mode, where 1/0 is evaluated into Inf etc. If
     there is no such way, try to use some kind of signal handler that
     will ignore such exceptions.

     The "normal" solution--add ifs to avoid division by zero is almost
     impossible. The division is quite easy to check. But other
     cases--overflows are much worse. So I don't think it is possible
     to avoid all crashes just by adding ifs.

     XaoS don't depend at IEEE arithmetic. Result in such cases should
     me mostly undefined. XaoS usually works well with compiler's
     switches for inexact math enabled (such as `-ffast-math' in GNU).
     But no guarantees. For example at Alphas this is not true--since
     they usually generates exceptions then.  Also `-mno-ieee-fp' at
     Intel don't work. This is due to gcc bug. Gcc in some cases reverse
     the condition when this switch is enabled. I've made patch to fix this
     problem and hope that it will get to egcs or gcc soon.

   * Text or graphics output device. If you have only text output
     device, you may use AA driver, which renders fractals into high
     quality ASCII art. In this case you might skip this chapter,
     download AA-lib (http://www.ta.jcu.cz/aa) and read porting chapter
     of AAlib manual. Graphics device must one of:

        * 8bits per pixel with user definable palette `C256', static
          palette `FIXEDCOLOR', or static grayscale `GRAYSCALE'

        * 16bits per pixel with arbitrary bits per each color
          `TRUECOLOR'

        * 24bits per pixel with 8 bits per each color, arbitrary order
          `TRUECOLOR24'

        * 32bits per pixel with arbitrary order of colors, where each
          colors fit to exactly one byte `TRUECOLOR'

        * 1bits per pixel bitmap with both orders (Least or Most
          significant bit first)

     Please contact me if you have different kind of device. Some modes
     (like miss-ordered truecolor modes) should be added really easily
     if required.  Note that mono/4/16 colors devices will be probably
     never supported internally by XaoS, since I expect they will be
     slower than 8bpp, so XaoS will internally work in 8bpp and then
     image should be converted. Contact me if you want to write such
     converter. (For bitmap there already exists--see `dither.c'.

   * Some way to save images. By default XaoS uses `pnglib', which is
     ported to many platforms, but there is still many others. If your
     system has some standard image format, which is easier to handle
     than `.png', contact me and I will show you, how to add such
     support to XaoS (see `png.c').

   * Stdio compatible library (this is problem at Mac or BeOS). XaoS
     has the abstract layer at the top of stdio, so it should use other
     input/output libraries too. You might write just another
     implementation if it's library called `xio'. See `xio.h'.

   Ugly interface is designed to make writing of new drivers as easy as
possible.  You need to write just few functions to fill following table:
(use file `ui_template' for starting of writing new driver from scrath)
     struct ui_driver {
       char *name;
       int (*init)(void);            /*initializing function. returns 0 if fail*/
       void (*getsize)(int *,int *);	/*get current size..in full-screen versions
                                       i.e svga and dos asks user for it*/
       void (*processevents)(int,int *,int *,int *,int *);
                                     /*processevents..calls ui_resize,ui_key
                                       also returns positions of mouse..
                                       waits for event if first parameter is
                                       1*/
       void (*getmouse)(int *,int *,int *);
                                     /*returns current mouse positions*/
       void (*uninit)();             /*called before exit*/
       int (*set_color)(int,int,int,int);
                                     /*alloc palette color and returns number*/
       int (*set_range)(ui_palette *palette,int start,int end)
                                     /*Set palette range*/
       void (*print)(int,int,char *);/*prints text*/
       void (*display)();            /*displays bitmap*/
       int (*alloc_buffers)(char **buffer1,char **buffer2);/*makes buffers*/
       void (*free_buffers)(char *buffer1,char *buffer2);/*frees buffers*/
       void (*flip_buffers)(void);   /*prints text*/
       void (*mousetype) (int type); /*Change mouse cursor*/
       void (*flush) (void);         /*Flush current state to screen*/
       int textwidth;                /*width of text*/
       int textheight;		/*height of text*/
       struct params *params;        /*command line parameters*/
       int flags;
       float width,height;
       int maxwidth,maxheight;
       int imagetype;
       int palettestart,paletteend,maxentries;
       int rmask, gmask, bmask;
       struct gui_driver gui_driver;
     };

Functions
=========

   Ui uses following functions to communicate with driver:

 - Function: init
     function that initializes driver and returns 1 if success and 0 if
     fail

 - Function: getsize (INT *WIDTH, INT *HEIGHT)
     returns size of screen(window) x and y

 - Function: processevents (INT WAIT, INT *X,INT *Y, INT *BUTTONMASK,
          INT &KEYS)
     gets new keyboard/mouse events. parameters:
    WAIT
          if 1 function can wait for next event otherwise just lookup if
                    something came. This is useful on multi-tasked os
          where xaos 	   does not eats unnecesaru CPU.

    *X,*Y
          here returns current positions of mouse

    *B
          returns mask of `BUTTON1',`BUTTON2',`BUTTON3' for mouse
          buttons

    *K
          returns mask for cursor keys
         `1'
               left

         `2'
               right

         `4'
               up

         `8'
               down             function also calls `ui_key' (ASCII
     character) and ui_resize if required.      For special keys use
     `UIKEY_UP', `UIKEY_DOWN', etc. See     `ui.h' for complete lists
     of this constants.

     note in case of problems freeing/allocating inside processevents
     you may     call `ui_call_resize' that calls resize later outside
     this function

 - Function: uninit
     Unitialises driver--called before exit.

 - Function: set_range (UI_PALETTE *PALETTE, INT START, INT END)
     This is an preffered way to set palette (second way is `set_color')
     when `imagetype' is `UI_C256' (256 color with palette) one of this
     two functions is required. In truecolor modes they are unused. In
     case direct access to palette is possible at your platform, define
     this one. Function is expected to set all color cells between
     START to END to colors defined in PALETTE. `Ui_palette' is array
     of UI_RGB. `Palette[0]' is color for entry number START. `Ui_rgb'
     is an array of `char'.  `Palette[0][0]' is red field of entry
     number START, `Palette[0][1]' is green and `Palette[0][2]' is
     blue. `0' means black and `255' means full intensity. Use `NULL'
     if your driver don't support this call.

 - Function: set_color (INT R, INT G, INT B, INT INIT)
     This is an secondary way, that should be used at platforms w/o
     direct   palette access (like X11 or static color schemes). It
     receives RGB value   of color, and returns index of color cell
     with this color or -1 if no more   color cells available. An INIT
     parameter is set to 1, when first entry   of palette is allocated,
     `set_color' is expected to free all color   entries previously
     allocated. Use `NULL' if your driver don't support   this call

 - Function: print (INT `x',INT `y', CHAR *`text')
     prints text to screen at position x/y. This function is a bit
     archaistic   (XaoS now uses in the most cases its own functions
     drawing directly to the   buffer), but in some
     cases--initialization messages or calculation,   functions are
     unusable, so we still need this primitive. In the `C256'   mode
     you might rely, that first allocated color is always black and
     second   is white.

 - Function: display (VOID)
     displays current buffer to screen

 - Function: alloc_buffers (CHAR **BUFFER1,CHAR **BUFFER2)
     allocs two buffers that can hold screen size bitmap.    Also sets
     current buffer to BUFFER1. Since version 2.1 returns scan-line
     size in bytes(usually width) and 0 if fail. This is useful on
     systems, that   allocated bitmap bigger than
     window/screen(dividable by 4 or so)

 - Function: free_buffers (CHAR *BUFFER1, CHAR *BUFFER2)
     frees allocated buffers

 - Function: flip_buffer (VOID)
     flips buffers--set current buffer to other one

 - Function: flush (VOID)
     This function should be used by drivers with buffered output to
     flush   output buffers. Other driver should set it to NULL.

 - Function: mousetype (INT TYPE)
     This function is used to change mouse cursor. It receives
     following values:
    `NORMALMOUSE'
          This mouse is usually displayed at screen, when UI waits for
          user      commands

    `WAITMOUSE'
          This mouse is displayed when UI is busy(should be famous wait
          clocks)      or you may use mouse defined in
          ui_dos--mandelbrot set

    `REPLAYMOUSE'
          This mouse is displayed during replay. Should be none at
          fullscreen      drivers, since blinking mouse cursor during
          replay looks ugly. At      windowed system disabling mouse
          looks ugly, so it should be some funny      cursor.
     You should use NULL if your driver don't support this.

Other information
=================

   Also some additional variables are used to inform ui about driver.
All this values can be changed by init functions in case they are
unknown before.

TEXTHEIGHT, TEXTWIDTH
     width and height of your font

PALETTESTART, PALETTEEND
     First and last palette entry, that should be changed. This you
     should use   to avoid changing of entries reserved for window
     system, text, mouse etc.

RMASK, GMASK, BMASK
     This fields are used in truecolor modes to specify, where each
     color is   defined

MAXENTRIES;
     Number of allocatable entries. Normally should be
     PALETTESTART-PALETTEEND

IMAGETYPE
     defines type of image. Should be one of following values:
    `UI_C256'
          classical 256 color with palette scheme used by most older
          graphics     adapters. You should use it also for
          static-color schemes but they are     not supported well in
          current version.

    `UI_TRUECOLOR'
          32bpp truecolor mode

    `UI_TRUECOLOR24'
          24bpp truecolor mode.

    `UI_TRUECOLOR16'
          16bpp truecolor mode

   FOLLOWING PART IS NOT REQUIRED TO MAKE FIRST VERSION OF DRIVER
WORKING.  so you may skip to REGISTERING DRIVER for first read and
return here later.

PARAMS
     Using this you may define command line options for you driver.

     They are defined using params structure like:
            static struct params params[]={
              {"-mode",P_NUMBER,&defmode,
                "Select graphics mode(same number as in interactive menu)"},
              {NULL,0,NULL,NULL}  /*this is MUST be last option field*/
            };

     every line is one parameters. List ends with `{NULL,0,NULL,NULL}'.
      First filed is option name.    Second field is type of parameter:
    `P_SWITCH'
          no parameter--variable is just set to 1 if option

    `P_NUMBER'
          integer number

    `P_STRING'
          string

    `P_FLOAT'
          floating point number (variable is float)     Third is
     pointer to variable that is changed if option is set.    It is for
     example `int*' for `P_NUMBER' or `P_SWITCH' and so on..    Last
     one is help text. Displayed by `ui -h'

WIDTH,HEIGHT
     see FLAGS. May be set to `0.0, 0.0' for the beginning

MAXWIDTH,MAXHEIGHT
     see FLAGS. May be set to 0,0 for the beginning

FLAGS
     This variable says more about your driver. You may start with
     value 0.    But for final version it is recommended to read
     following chapter carefully.

     Flags are uppercase constants and should be set by following way:

     `ASYNC_PALETTE | RANDOM_PALETTE_SIZE'

     following switches are supported:

    `RANDOM_PALETTE_SIZE'
          random size of palette. This is used in X where palette is
          shared between     programs. By default xaos allocates all
          available colors up to 256. This     is not very nice to
          other applications in X. So randomsize causes that     just
          some random number of colors(between 8-256) are allocated.

          Also when this variable is off XaoS expects that allays same
          number of     colors is available.

    `UPDATE_AFTER_RESIZE'
          recalculate and redraw screen even if its size is not changed.
             In case that resize procedure destroys data in buffers

    `RESIZE_COMMAND'
          Some drivers (mainly the fullscreen ones) may in the function
          `get_size'     ask user for the size and color depth. It
          should be nice to let user change this parameter     at
          runtime. I.E force XaoS to reinitialize his images. This is
          done by     `ui_resize' call. This call in windowed drivers
          is called by the     external event. But in fullscreen
          drivers you need key/menu item for this.      You might add
          this function directly into XaoS's function registry (see
          for example the GGI driver)--it is usefull mainly when you
          want to make     some size selection dialog in the standard
          way, or let XaoS add his default     one. And this is done by
          this flag. See for example SVGAlib or DOG driver.
     Screen/window size informations:

     Xaos needs to know exact size of displayed images. This is required
        for random dot stereo-grams and also for keeping fractals in
     their shape     (do not make them wide on 640x200 resolution etc.)
        So minimally one of the following values should be defined.
      (they are sorted in order I prefer them)
    `SCREENSIZE'
          values width/height specifies exact size of screen/window in
          centimeters

    `PIXELSIZE'
          values width/height specifies exact size of one pixel in
          centimeters      This is better for windowed environments
          where window size is often changed

    `FULLSCREEN'
          driver runs fullscreen. XaoS automatically uses default
          screen size      (29.0cm x 21.5cm)

    `RESOLUTION'
          driver does not know exact screen size. But knows resolution
          used.       (it is in variables width/height) XaoS
          automatically calculates      pixel width
          using:29.0cm/maxwidth      and height: 21.5/maxheight
     Of course default width and height can be changed by command line
     options.     You may also use combinations like:

    `SCREENSIZE | FULLSCREEN'
          the best for fullscreen drivers

    `PIXELSIZE | RESOLUTION'
          the best for windowed drivers

    `FULLSCREEN'
          for fullscreen drivers than have no idea about screen size...
                do not forget to set WIDTH, HEIGHT, MAXWIDTH,
     MAXHEIGHT fields if required.

GUI_DRIVER
     See next section for description.

Registering driver
==================

   Than just register driver to `driver.c' and you may compile :) You
may use `ui_template.c' as driver template..

   You may also look at xthreads library description if you are porting
XaoS to some SMP platform.

   Please let me know if you want to start code some driver.


File: xaosdev.info,  Node: gui-driver,  Next: eui,  Prev: driver,  Up: Top

Writting GUI driver
*******************

   XaoS have builtin GUI. Many operating systems have native gui
toolkits and XaoS default GUI might look strange there. To avoid this
problem, you might write external gui program (see eui section) or
write mappings of XaoS GUI functions. The advantage of external gui
process in multitasking.  XaoS is not thread safe and GUI must be
synchronous with calculation.  Also ugly interface code currently don't
support multiple windows (this should be solved in future).  This
solution is suitable mainly for those systems, where cooperation of two
programs sharing one window should be problem (like on Windows).

   To write gui driver you need to fill following structure:
     struct gui_driver
     {
        void (*setrootmenu)(struct uih_context *c, char *name);
        void (*enabledisable)(struct uih_context *c, char *name);
        void (*menu)(struct uih_context *c, char *name);
        void (*dialog)(struct uih_context *c, char *name);
        void (*help)(struct uih_context *c, char *name);
     };

   All function have `uih_context' parameter. You don't need to worry
about it's contents. Just pass it to the called functions that require
it. This parameter is for multiple window support, that is not
implemented yet.

   The `setrootmenu' function expected to draw root menu according to
the menu called `name'. To get menu fields you might use following
piece of code:
     #include <ui.h>
     #include <xmenu.h>
     
     ....
     
     int i;
     menuitem *item;
     for (i = 0; (item = menu_item (name, i)) != NULL; i++)
        {
           if (item->type == MENU_SUBMENU) {
     	      /* This field is submenu. You might call here
     	         function to construct submenu. item->shortname contains
     		 name for submenu */
           }
           /* add menu field here.
     
              You might check flags here:
              item->flags&MENUFLAG_CHECKBOX
     	   field have beckbox
              item->flags&MENUFLAG_RADIO
     	   field is part of radio button group. In current implementation
     	   there is one radio button group per menu.
     
     	 in both cases you might call: menu_enabled(uih, item) to see
     	 if item is checked or not.
     
              item->name contains field's text
     
     	 item->key contains hotkey (one letter string in current
     	 implementation)
        }
   Once field is selected, call function `ui_menuactivate(item, NULL)'
where `item' is pointer to `menuitem' record of selected field.

   Function `enabledisable' is called when checkbox or radiobutton
state is changed. The `name' parameter match to `item->shortname' of
changed field.  So you need to browse all created menus, compare
`item->shortname' and in case it match, call `menu_enabled' to obtain
new state. For radiobuttons only enable events are noticed. Your code
is expected to automatically disable all other radiobuttons in the same
submenu.

   function `menu' works in similar way to `setrootmenu' but displays
popup menu.

   Function `dialog' is called for dialogs. The function should look
like:
     menuitem *item = menu_findcommand(name);
     menudialog *dialog = menu_getdialog(uih, item);
     int i;
     for(i=0; dialog[i].question; i++)
     {
        /* Construct dialog, where left side contains labels with
         dialog[i].question. Right side contains input entities based on the
         dialog[i].type. Dialog[i].type is one of the following:
     
         DIALOG_INT: integer value input. The default value is: dialog[i].defint
         DIALOG_FLOAT: floating point input value (long double, where availble
         exact). Default value is dialog: dialog[i].deffloat
         DIALOG_COORD: complex value floating point input (two floats), default
         values are dialog[i].deffloat and dialog[i].deffloat2
         DIALOG_STRING: string input. default value is dialog[i].defstr
         DIALOG_IFILE: input file
         DIALOG_OFILE: output file
              default mask is dialog[i].defstr
         DIALOG_CHOICE: choice between various strings.
              retype dialog[i].defstr to char ** to get pointer to NULL terminated
     	 array of the choices.
     }
   Once dialog is filled by user, gui_driver is expected to allocate
array of union `dialogparam' `dialogparam':
     dialogparam *p = calloc (sizeof (*p), nitems);
   fill selected values. `p[i].dint' is used to pass integer value, or
number of DIALOG_CHOICE selection, `p[i].number' is used for floating
point number, `p[i].dstring' for strings and filenames,
`p[i].dcoord[0]' and `p[i].dcoord[1]' for complex values.

   The string values are expected to be in separate malloced chunks.
Once array is filled, call `ui_menuactivate(item, p)'.

   The function `help' is used to display help about given topic.  To
implement it you might eighter convert XaoS help file to some native
format, or use xshl library to render help page for you. To render xshl
page use:
     #include <xshl.h>
     xshl_line *lines;
     int getwidth (void *data, int flags, char *text)
     {
     	return width of text with given flags
     	flags is mask of the following:
              XSHL_BIG - large text
              XSHL_EMPH - emphatized text
              XSHL_MONOSPACE - monospaced text (typewriter)
              XSHL_LINK - line (should be underlined or so)
              XSHL_WHITE
              XSHL_RED
              XSHL_BLACK - color of text (not very meaningfull here)
              XSHL_RIGHTALIGN
              XSHL_CENTERALIGN - alignment of the text
     
     }
     lines = help_make (name, getwidth, textheight, largetextheight);
     if (lines == NULL)
       lines = help_make ("main", getwidth, textheight, largetextheight);
   Now you might use `lines' to draw the help. It is pointer to the
arraw of structures:
     struct xshl_line {
       int y;
       struct xshl_item *first;
     };
   `y' is possition of the line from beggining of text and first is
pointer to the blocks of texts on the line. Last line contains NULL
pointer in the first section.

   `first' is linked list of the structures:
     struct xshl_item {
       struct xshl_context c;
       char *text;
       int x;
       int width;
       struct xshl_item *next;
     };

   you might draw text `text' on the possition `x' (and `y' from the
line record) using style described by `xshl_context':
     struct xshl_context {
     	  int flags;
     	  char *linktext;
     };
   `flags' have same meaning as in `getwidth' section. `linktext' is
name of the next help page in case field have XSHL_LINK atribute.

   As an example of `gui_driver' see win32 driver code.


File: xaosdev.info,  Node: eui,  Next: ui-helper,  Prev: gui-driver,  Up: Top

Writting an external user interface
***********************************

   This part describes, how to make an external user interface--it is
the separate program, which makes an window with all menus and dialogs.
It uses XaoS engine for calculating the fractal as separate process.
This design brings many advantages--the external GUI implementation
should have an "native look" for given platform and should contain many
extensions, such as multiple windows etc. Also all calculation are done
in the multitasking and user interface is usable even when engine is
busy.

   The X window provides a way, when program draws into other's
window--"master" program creates window and sub-window, where he wants
to have fractal, then calls engine with `-windowid' NUMBER_OF_WINDOW
parameters. It instead of creating new window uses specified window.
Most famous example of such cooperation is probably
ghostscript/ghostview.

   Other windowed environments probably provides similar way for
cooperation. At others it should be implemented using shared memory, so
it should work at most platforms, I expect.

   Of course, you might also design UI as separate button box in
another window, like most of animation players, or Imagemagick have. In
fact external GUI should be very similar to Imagemagick style.

basic concept
=============

   The UI implementation has function to disable it's GUI functions.
Because of the function registry, all it's menus and dialogs are
described in the fairly simple database. This database is mapped also
to the scripting language similar to scheme. So the external UI
implementation just translate the actions into this scripting language
and sends it trough pipe.

   This commands should be created automatically from the database, as
well as menus and dialogs, so UI don't need to have special code for
various XaoS features. At the beginning it should use XaoS' command
`(print_menus)' to force him to send information about database, then
build menus using this information.

   For this you need just some equivalent to UNIX pipes, so again I
expect it is doable at most platforms.

starting XaoS as slave process
==============================

   One of the first thinks, engine needs to do is to initialize XaoS in
right mode to work as slave process. For this you need to do several
thinks:

   * Open the pipe

   * Disable builtin GUI

   * Read menu hierarchy (this is optional--GUI can also have all menus
     coded into it. But it is not recommended, since it will make
     problems with future adding new features)

   Opening pipe is done via `-pipe' option. It takes one parameter,
which is name of FIFO you want use. If you specify "`-'", XaoS will
read input from stdin.

   To disable XaoS GUI use option `-nogui'. This will disable all menus,
dialogs and help text.

   To read menu hiearchy just add `-print_menus' parameter and then
parse XaoS's output. This will print the whole hierarchy. In case you
are building menus at the time, they are selected, you might prefer
usage of the command `print_menu'. It prints just one menu without it's
sub-menus, so it's output should be directly used for building it. It
takes one string parameter, which is name of menu you want to print. To
print root menu use `"root"'.  Option should look like this:
`-print_menu root'.

   Under X Window you need also specify the `-windowid'. Also the
`-shared' is quite recommended. Otherwise in pseudocolor visuals XaoS
will create it's own colormap, wich will most probably collide with
UI's colormap and XaoS or UI will have false colors. If you have any
idea, how to avoid this, let me know.

   You might also let user to specify some extra parameters from the
command line. You should simple add the to the end of command line. The
`-nogui' and `-print_menus' commands must be first for the simple
reason: XaoS parses it's command line in the early initialization
stages. Some commands (like `-print_menus') should be processed at this
time, while others (like `-loadpos' needs to have working engine. This
commands are queued and processed later, once engine is  initialized.
In case some such command is before `-print_menus' XaoS will decide to
keep same order of commands, so it will queue `-print_menus' too. This
will case, that menus will be printed much later and startup will be
slower.

   So the proper calling sequence for the user interface under X should
look like:

     xaos -nogui -print_menus -windowid <id> -share -pipe - [OTHER OPTIONS]

Parsing the menu structure
==========================

   The structure is printed menu by menu. Each menu contains an header,
some entries and `endmenu'. Whole listing from `print_menus' is
terminated by `endmenus'.

   The header starts with `menu' and then contains an identifier of menu
and full name. Such as:

     menu "fractal" "Fractal"

   Then each entry has its own line. It starts by type, which should be
`submenu' or `menuentry'.

   `submenu' has similar format to header--fullname of menu and
identifier.

   `menuentry' adds next few fields. It has an type of entry, which
should be `normal', `radio' or `checkbox'. `radio' and `checkbox' are
followed by `on' or `off' specifying whether it is enabled or disabled.
The radio-buttons don't have explicit information about groups they
belongs to. For now I just expect, that each menu contains just one
such group, so it is clear.

   Then set of flags should follow. Currently two flags are defined.
`dialog', wich specifies, that function has dialog, and
`dialogatdisable'. By default, dialog for check-boxed functions are
displayed just in case they are enabled. The second flag reverses this
behaviour. It is now used for `mandlebrot' function, which behaves in
this style. When you disable it, user is prompted for the Julia seed.

   So specification should look like this:

     menu fractal "Fractal"
     submenu "formulae" "mformula"
     submenu "Incoloring mode" "mincoloring"
     submenu "Outcoloring mode" "moutcoloring"
     submenu "Plane" "mplane"
     submenu "Palette" "palette"
     menuentry "Mandelbrot mode" "uimandelbrot" checkbox off dialogatdisable dialog
     menuentry "Perturbation" "uiperturbation" checkbox off dialog
     menuentry "View" "uiview" normal dialog
     menuentry "Reset to defaults" "initstate" normal
     endmenu

Activating functions and dialogs
================================

   Once the menu structure is built and user selects some item, it
should be activated. It is done by simple command: `(NAME)'. Once "`)'"
is sent, command is executed by XaoS.

   Check-boxed functions has one extra parameter--`#t' to enable them
and `#f' to disable. So if you want enable item `autopilot' send:
`autopilot #t'

   Radio-buttons don't have any such special parameter--because
disabling radio-button is nonsense.

   In case, item has flag dialog enabled, engine expects that UI will
make dialog first, ask user of values and then call function with
parameters.  UI needs first to know, what parameters function expect.
It is done by sending command `(print_dialog "NAME")'.  XaoS replies
with dialog specification very similar to menu specification.

   It has header `dialog' followed by the name of function. Then one
dialog entry per line is sent. it is started by `dialogentry' followed
by question UI should display. The is type, which should be one of the
following:
`integer'
     Integer number such as `123'

`float'
     Floating point number such as `123.123'

`string'
     String such as `"ahoj"'

`keyword'
     String such as `'ahoj'. The keywords are mostly similar to string,
     except they can not contain space. They are used for example for
     specifying formula type. Strings are used for printing texts etc.

`inputfile'

`outputfile'
     Here UI should display file selection dialogs. With `outputfile'
     it is also good idea to check, whether file exist and in this case
     make some overwriting dialog too.

`onoff'
     Boolean value (`#f', or `#t')

`complex'
     Complex value--two floating point numbers such as `123.123 123.123'

`choice'
     Choice between some keywords. Those keywords are send after
     `choice' in enclosed the `{' `}'.  Last information at the line is
the default value in the same format as examples above. For files, the
default value is in format `"[PREFIX]*[EXTENSION]"'.

   Some examples:

     customdialog "uiview"
     dialogentry "center:" complex 0.000000 0.000000
     dialogentry "Radius:" float 0.000000
     dialogentry "Angle:" float 0.000000
     enddialog
     
     dialog "load"
     dialogentry "Filename:" inputfile "fract*.xpf"
     enddialog
     
     customdialog "color"
     dialogentry "Color" choice {white black red }white
     enddialog

   To activate function, send command which contain function name,
possible `#t'/`#f' in check-boxes and parameters in the same order as
in dialog, same format as in examples, separated by the space. Such as:

     (uiview 0 0 0.5 0)
     (load "text.xpf")
     (color 'white)

Synchronization
===============

   In some cases, XaoS can change radio-box and check-box values. (like
when user pressed a key, or loaded some file). So all changes are sent
to GUI, wich should inform about this. They are sent to standard output
in following format:

     checkbox "name" on/off
     radio "name" on/off

   So your GUI should parse this and change it's menus when necessary.

   Also XaoS's menus can contain more distinct trees. In some cases
(like when animation replay is active) root of menu structure should
change. The XaoS sends command:

     root "name"

   Also user can press keys, which normally displayed menus, dialogs or
help. Then XaoS sends commands:

     menu "name"
     dialog "name"
     help "topic"

   All this commands should be taken into account by GUI, or should be
ignored.

help
====

   XaoS's help is in the simple hypertext language. In order to
simplify it's parsing I've made an xshl and help libraries. So making
of help window should be quite easy. Just call help function:

 - Function: struct xshl_line *help_make (char *COMMAND, int GETWIDTH
          (void *, int FLAGS, char *TEXT), int WIDTH, int SMALLHEIGHT,
          int BIGHEIGHT);
   and you will receive of listings of text with positions, where to
print into window.

   `command' parameter is topic of help. `getwidth' function is
function, wich returns width of given text. `width' is width of window,
`smallheight' is height of small font and `bigheight' is height of big
font.

   Please ask me for more details if necessary.

   And thats all. Good luck with coding.


File: xaosdev.info,  Node: ui-helper,  Next: xthreads,  Prev: eui,  Up: Top

UI-helper library
*****************

   UI helper library takes care to all XaoS' engine functions and
features and gives the higher level API, which is quite easy to
understand. If you want to write completely new user interface
(replacement for the ugly interface--not just new bindings for native
menus or external user interfaces) or you want to use XaoS engine in
your program as an library, you will probably want to use this library.

   It's API has many calls and features. This section gives just brief
overview of it's calls. Please ask me about details.

initialization
==============

   To initialize ui helper library, you need to prepare an palette and
image.  Palette is created using palette library calls `createpalette'.
Creating truecolor palette should look like this:

       struct palette *pal = createpalette (0, 0, TRUECOLOR, 0, 0, NULL,
                                            NULL, NULL, NULL);

   For details about creating palettes see `ui.c' or ask me.

   To create image call:

       struct *image img = create_image_mem (width, height, 2, pal,
                                             pixelwidth, pixelheight);

   This creates image in the memory. If you want to create it in your
own buffers, you might use `create_image_cont' or `create_image' calls.
Again see `ui.c'.

   Then it is time to fire up main library:

       struct uih_context *uih = uih_mkcontext (0, img, passfunc,
                                                NULL, NULL);

   The `passfunc' is called when engine is calculating. It might process
events and display process information. It should look like this:

     static int
     ui_passfunc (struct uih_context *c, int display, char *text, float percent)
     {
       /*process events */
       if (uih->display)
         {
           uih_drawwindows (uih);
           /*display */
         }
       if (display)
         {
           if (percent)
     	sprintf (str, "%s %3.2f%%        ", text, (double) percent);
           else
     	sprintf (str, "%s          ", text);
           /*display it */
         }
     }
   It might set `uih->interrupt', if it wants to interrupt current
calculation.

   You also might load the catalog file in order to make tutorials
working:

       uih_loadcatalog (uih, "english");

   Since this ui_helper library is fully functional and you might enter
the main loop.

main loop
=========

   UI helper library does an timing primitives. So it expect an
standard form of the main loop. It asks the program to display changed
image when necessary.  Library also use timerlib for it's timing. So
read section about this library, since you might use it for your
purposes too.

   Main loop should look like this:

     while (1)
       {
         if (uih->display)
           {
     	uih_prepare_image (uih);
     	uih_drawwindows(uih);
     	/*display current image buffer*/
           }
         uih_update (uih, mousex, mousey, buttons);
         if ((time = tl_process_group (syncgroup, NULL)) != -1 &&
     	    !uih->inanimation) {
     	    /*relax given time in usec - wait of events etc..*/
         }
         /*and repeat*/
       }

calling functions
=================

   UI helper library has many functions declared in `ui_helper.h' for
various actions. There is too much of them to describe, but their names
are quite informative, so I hope you will not have problems.

   You might also use XaoS function registry, which does all this stuff
for you.  You will just draw menus and dialogs based at this registry
and automatically all features will be available. So if you are writing
an ordinary user interface, this is the preffered way.

   Note that `ui_helper' library is not reentrant, so you can't call
most of this function from the `passfunc'. If you are using registry,
activating function handles this automatically and queues functions
when necessary.  To process them you need to flush queue in the main
loop as follows:

     static void
     processbuffer (void)
     {
       menuitem *item;
       dialogparam *d;
       if (uih->incalculation)
         return;
       while ((item = menu_delqueue (&d)) != NULL)
         {
           menu_menuactivate (item, d);
         }
     }

closing library
===============

   This is done using:

       uih_freecontext (uih);

   One implementation of user interface at the top is ugly interface.
See dirrectory `src/ui'. Another, much simpler is `render.c', which does
animation rendering.


File: xaosdev.info,  Node: xthreads,  Next: filters,  Prev: ui-helper,  Up: Top

XaoS thread library
*******************

   This description should be useful for those, who want to port XaoS
into multiprocessor platforms and those, who want to implement some
filter or other relatively computational expensive code. Note that
thread library should be mapped into nothread calls, in case host does
not allows multi-threading or it is not SMP architecture (since this
library is used only to distribute calculation into other CPUs)

   XaoS thread library is simple map of few functions required by XaoS
to system library for threads.

   It has following variables:

 - Variable: ethreads
     This is set to 1 in case that threads are enabled

 - Variable: nthreads
     Number of threads

   It and following calls:

 - Function: void xth_init (int THREADS)
     This function initializes threading library (starts threads, sets
     ETHREAD to 1 and NTHREADS to n. THREADS parameter should be set to
     0--auto-detection or number of threads users wants. In case threads
     is set to 1, threading library is disabled and following functions
     are mapped into those nothread_ equivalents defined in `xthread.h'.

     Note that threads are not identical--there is main thread (one
     that called xth_init) that communicates with drivers, controls
     calculation etc. and other tasks that are waiting to orders from
     main task. They also can't use functions from xthread library.

 - Function: void xth_uninit (void)
     This function UN-initialize thread library--kills child threads,
     sets ETHREAD to 0 and NTHREADS to 1.

 - Function: void xth_function (xfunction *FUNCTION, void *data, int
          RANGE)
     This function is used in case, engine wants to perform some
     operation at image in parael. It is expected to wait until all
     threads are ready and start FUNCTION at all threads including
     control one with following parameters: DATA--this parameter is
     same as DATA passed to xth_function, TASKINFO--pointer to structure
     taskinfo, that is platform depended (defined in `xthread.h') but
     must have at least field `n', that holds number of thread (control
     thread has 0 and other numbers in range 1 - NTHREADS). Next two
     parameters is range of image, function is expected to do action.
     Xth_function is expected to divided RANGE into NTHREADS equal
     pieces and pass always start of piece and start of next piece
     (RANGE in case of last one). Function does not wait for other
     threads at the end and returns immediately to main thread after
     FUNCTION returns.

     This function is called approx. 5-10 times per frame

 - Function: void xth_sync (void)
     This functions waits until all threads are ready for next order
     from main task.

     This function is called approx 5-10 times per frame

 - Function: void xth_bgjob (xfunction *FUNCTION, void *DATA)
     This function is expected to behave as follows: look if there is
     any thread waiting for orders, if so, ask him to call FUNCTION
     with similar conventions as in xth_function except that range
     parameters are set to 0.  Otherwise it starts function in normally
     (at foreground).

     This function is called once per frame.

 - Function: void xth_nthread (struct taskinfo *S)
     This function should be used to determine number of current
     thread. Do not use `taskinfo->n' instead since in case threads are
     disabled, it should be defined to 0 and that allows optimizer to
     perform better optimizations.  This function should be called by
     all threads.

 - Function: void xth_lock (int N)

 - Function: void xth_unlock (int N)
     Lock/unlock lock number N. At least `MAXSEMAPHORS' locks must be
     available.

     Note that locks are used always for very short fragments of code
     so they needs to be fast. So spin-locks are maybe better than
     Dijskra semaphores.  Untested. They are called once per calculated
     line/row during zoom and once per approx 10 pixels during
     calculation of new image.

 - Function: void xth_sleep (int N, int L)
     It is expected to atomically unlock lock L and sleep in queue N.
     At least `MAXCONDS' queues must be available.  After it is waked
     up, lock L again. This mechanism is used by calculation of new
     image algorithm, but it is designed to minimize its calls, so I
     expect they should be called once or twice.

 - Function: void xth_wakeup (int N)
     Wake up some thread from queue N. Lock used by sleep calls is
     locked in this cases. Function should also wake up all threads if
     such operation is not supported by host API. With luck, this
     function should not be called at all. It should be called by new
     image calculation routines in case queue is empty. This happens in
     case of 50 threads but happens rarely at two or eight threads
     according to my tests.

 - Function: void xth_wakeall (int N)
     Similar to wakeup but wake up all threads.


File: xaosdev.info,  Node: filters,  Next: algorithm,  Prev: xthreads,  Up: Top

Filters
*******

   This is a brief description of filter system used internally by XaoS.
Filters in XaoS provides an object oriented interface to every part of
XaoS engine. Main filters are: User interface implemented in ui_helper.c
and zooming engine implemented in zoom.c. Filters are connected into an
queue--at the beginning there is just two filters here(zoom and ui) but
later additional filters should be inserted into the middle of queue
like an stereo-gram generation etc. The queue supports operations like
remove filter, add filter and initialize.

   In the calculation every filter should use data calculated by filter
lower in the queue. Data are stored into image. So for example
stereo-gram filter should use fractal generated by zooming engine and
create an stereo-gram.

   This makes XaoS's code more flexible and makes easy future
enhancements like different zooming engine, image rotation, other
special effects, plug-ins and some other funny stuff since interface of
each such part is well defined and each filter has quite good control
over his child.  So stereo-gram filter should change palette, force
zooming engine to change depth, width and height of calculated image to
fit his needs and so on.

   This document describes mainly creating of filter like stereo-gram
generator i.e. filter placed into middle of queue since I don't expect
there will be many people creating "terminal" filters (zooming
engines/user interface layer) note that different user interface is
possible since user interface layer is not the real user interface just
set of high level functions that should be called by main application
like set_view. So in case you want to use XaoS as an calculation engine
in your program this document is probably not for you.

   Each filter is defined by filter_action structures as follows:
     struct filteraction {
       char *name;
       char *shortname;
       int flags;
       struct filter *(*getinstance)(struct filteraction *a);
       void (*destroyinstance)(struct filter *f);
       int (*doit)(struct filter *f,int flags,int time);
       int (*requirement)(struct filter *f,struct requirements *r);
       int (*initialize)(struct filter *f,struct initdata *i);
       void (*convertup)(struct filter *f,int *x,int *y);
       void (*convertdown)(struct filter *f,int *x,int *y);
       void (*removefilter)(struct filter *f);
     };
   This structure describes static filter's parameters (like its name)
and basic set of methods required for communication with resto of XaoS.
The name field describes filter's name like "An random dot stereo-gram
generator". Name is displayed by ugly interface in filter's menu. So it
is expected to be descriptive and shorter than 30 characters. The short
name is one word long name for filter like "stereogram". This name is
used by save files, possibly by command line parameters. Simply
everywhere where user should need to write it and writing long
descriptive name should be just wasting of time and disk space.

   Flags field is kept for future enhancements and is expected to be 0
for now.

Creating / destroying of instance
=================================

   Functions getinstance and destroyinstance are equivalents to
constructor and destructor in OOP. Getinstance is expected to create
and fill following structure:

     struct filter {
       struct filter *next,*previous;
       struct queue *queue;
       struct filteraction *action;
       struct image *image,*childimage;
       struct requirements req;
       struct fractal_context *fractalc;
       void *data;
       char *name;
       int flags;
       void (*wait_function) (struct filter *f);
       /*stuff for wait_function*/
       int pos,max,incalculation,readyforinterrupt,interrupt;
       char *pass;
     };
   Altrought this structure seems to be long and complex, most of
fields are unused at this time and rest of them are filled
automatically by function:

 - Function: struct filter * createfilter (struct filteraction *FA);
     That should be used to create instance. Only possibly interesting
     field is data. It's pointer reserved for filter's internal use. So
     it should be pointer to filter's internal variables if required.
     Following is example implementation of get-instance with
     allocating of such additional structure. In case nothing similar
     is required you should use directly createfilter at getinstance's
     place.

     static struct filter *getinstance(struct filteraction *a)
     {
           struct filter *f = createfilter(a);    /*create filter structure*/
           struct stereogramdata *i=calloc(sizeof(*i),1);
                                                  /*allocate internal variables*/
           /*initialize your variables here*/
           f->data=i;                             /*add pointer to internal data*/
           return (f);
     }

   The destroyinstance is expected to free memory used by filter
structure and all internal data of filter. To free filter structure use
normal free(filter); So implementation of such function should look
like:
     static void destroyinstance(struct filter *f)
     {
          destroyinheredimage(f);
          free(f->data);
          free(f);
     }
   The meaning of destroyinheredimage will be described later.

Initialization
==============

   During initialization phaste each filter says to his parent what kind
of images it supports (this should depend on images supported by his
child), parent chooses best supported image format for his purposes and
gives it to the child. Initialization is done in two pases.

   First pass start by lowest filter in the queue and each filter
passes to his parents requirement structure.

   Second pass starts by the highest filter and each filter passes to
child an image and some other stuff. Then calculation should begin.

   Queue needs to be reinitialized after creating, resizing,
adding/removing of filter and similar operations.

   First pass is implemented using require function. This function is
expected to take care at child's requirements it received as parameter,
fill requirements structure and call require function of his parent
filter.
     struct requirements {
       int nimages;
       int supportedmask;
       int flags;
     };
   The nimages field should be set to 1 or 2. In case it is 2, parent
filter must pass image with two buffers. Note that in case it is 1,
parent should pass image with two buffers too.

   Supported mask is mask of supported image types by filter. Image
types are following:
`C256'
     An normal 8bpp image with palette

`TRUECOLOR24'
     An 24bpp truecolor image with 8bits for each color.

`TRUECOLOR16'
     An 16bpp truecolor image

`TRUECOLOR'
     An 32bpp truecolor image with 8bits for each color.

`LARGEITER'
     An 16bpp image but w/o colors. It is expected to hold number of
     iterations   it should be also tought as 16bpp grayscale image

`SMALLITER'
     Similar to `LARGEITER' but 8bpp

   In case you don't worry about palettes, allocations of colors and
you do just some operation with bitmap, so you worry just about depth
of image you should use mask of following: `MASK1BPP' for 8 bit images,
`MASK2BPP' for 16bit and so on.

   The latest field of requirements structure is flags. It mask from
following constants:

`IMAGEDATA'
     in case your filter requires data from previous frame untouched.
     In case   this is not set, filters should reuse your image and
     change it. But some   filters like and motion blur or zooming
     engine requires data from previous   frame to construct new, so
     this flag should be set there is no more flags supported at the
moment. Function require should also save child's require structure
into filter->req for later use by initialize pass. So you should look
like:
     static int requirement(struct filter *f,struct requirements *r)
     {
       f->req=*r;    /*Save an child's requirements*/
       r->nimages=1; /*Just one image is required*/
       r->flags&=~IMAGEDATA;/*unset the imagedata field*/
       r->supportedmask=C256|TRUECOLOR|HICOLOR|REALCOLOR;
                     /*mask of all supported image types*/
       return (f->next->action->requirement(f->next, r));
                     /*call parent*/
     }
   Next pass is main initialization. It goes in opposite order(from
parent to child) and child's infers some stuff from parent like images
etc...  The initialize structure receives an initdata structure:
     struct initdata {
       void (*wait_function) (struct filter *f);
       struct image *image;
       struct fractal_context *fractalc;
       int flags;
     };
   an wait_function is function called by filter during calculation that
lets the parent filters(usually user interface layer) to inform user
how calculation continues. Image is an image expected to be filled by
image in calculation phaste. Fractalc is pointer to structure that will
contain information about fractal during calculation(like formula type
etc...) Flags is mask of following constants:
`DATALOST'
     this is set in case, that data in image was lost(image was cleared
     or  resized or freshly allocated). Filters that uses data from
     previous frames  should take care to this flag. Zooming engine for
     example recalculates  whole image since pixels from previous frame
     was lost.   Note that data should be lost also in case, filter
     receives different  image that in previous initialization since
     some filter behind was  removed.  An inhering process is done
using function:

 - Function: void inhermisc (struct filter *F,struct initdata *I);
     This function sets fields in filter structure like as fractalc or
     wait_func.  Inhering of image is quite complex, since new image
     needs to be prepared for child. In order to save memory it is
     highly recommended to use same image or at least same memory for
     data when passing to child. But this is not allays possible.
     Following function implements heuristic to do this:

 - Function: int inherimage (struct filter *F,struct initdata *DATA,
          int FLAGS, int WIDTH, int HEIGHT, struct palette *PALETTE,
          float PIXELWIDTH, float PIXELHEIGHT)
     You should call this function in your initialize pass. It fills
     image and childimage in filter structure, prepares initdata for
     child and creates image for child. Note that it should fail in
     some cases and return 0. In this case filter is expected to
     interrupt initialization and return 0 too.

     An FLAGS parameter is mask of following constants:
    `IMAGEDATA'
          in case your filter requires data from previous frame

    `TOUCHDATA'
          In case your filter touches data in output image. This is
          very usual but   there is some filters (like interlace or
          subwindow that don't)

    `NEWIMAGE'
          Set in case your filter can not deal with shared images
          (images that have   input data in same memory are as output)
     WIDTH and HEIGHT should be set to 0 in case you want same
     width/height as in parent image or width and height of image you
     want to pass to child.  PALETTE is palette of image you want to
     pass. Set to `NULL' if palette should be inhered from parent's
     image (usual).  PIXELWIDTH and PIXELHEIGHT specifies physical size
     of pixel in centimeters.  If set to 0 they are inhered from
     parent's image.

   In case you use inherimage mechanism you also must call
destroyinheredimage in destroyinstance function and updateinheredimage
at the beginning of calculate function.

   Example implementation:
     static int initialize(struct filter *f,struct initdata *i)
     {struct stereogramdata *s=f->data;
       inhermisc(f,i);
       if(!inherimage(f,i,TOUCHIMAGE,0,0,NULL,0,0) return 0;
       /*initialize here*/
       return(f->previous->action->initialize(f->previous,i));
     }
   Also note that fractal context hold pointer to fractal palette. In
case You don't change image palette everything is OK. But in case
child's image differs from parents image, there should be two
behaviors--fractal's palette is child one (this should be common for
example in conversion filters ( 8bpp to truecolor etc)) or fractal's
palette is parent's one (like in edge detection filter). By default
fractal's palette is kept to parent's one.  This should be changed by
setfractalpalette call. It has two parameters--filter structure and
palette. When you pass as palette child's palette, fractal's palette
will be changed to child. In case you pass NULL. Changing of palette
will be disabled (like in motion blur filter in 8bpp mode).  Note that
this is changed just in case you still have access to fractal palette.
Some parent should redirect palette before. Than this function does
nothing.

Caluclation
===========

   Main calculation is done using doit function. It is expected to call
child's calculation function when required and apply filter at output.
It receives flags. Only flag in `INTERRUPTIBLE' for now. It is mainly
for zooming engine so I do not describe it here. But filter is expected
to pass this flag to child. Next parameter is time in milliseconds that
expired since last doit call. It should be used to calculate speed of
animation.

   Calculation loops returns flags. Flags is mask from following
constants:
`ANIMATION'
     in case filter performs some animation and expect that calculation
     will be  called again soon

`CHANGED'
     in case something changed in output image (usual)

`INEXACT'
     This is enabled by zooming engine in `INTERRUPTIBLE' mode in case
     that time  exceeded.

   An doit function changes image. Image structure contains following
fields significant for you:
`bytesperpixel'
     number of bytes per pixel (image depth)

`palette'
     palette of image.

`currlines'
     array of pointers to beginnings of every scanline of image

`oldlines'
     array of pointers like currlines but for previous image in case
     doublebuffering is enabled

`nimages'
     set to 2 in case doublebuffering is active

`flipimage'
     pointer to function that flips oldlines and currlines.

   palette structure contains following significant fields:

`type'
     type of palette/image (`C256', `TRUECOLOR' etc...)

`size'
     number of allocated entries

`pixels'
     array of allocated entries. Conversion table from number of
     iteration  to pixel value.

`rgb'
     Rgb values for pixels (`NULL' for `TRUECOLOR', `HICOLOR' and
     similiar types)

   To make easier writing calculation loops for different depths
`pixel8_t', `pixel16_t' and `pixel32_t' are predefined. You also can
use include system as in edge detection filter, that lets you write
calculation loops just once and use cpixel_t and it will be compiled
for every bitmap depth.  See edge detection filter (engine/edge.c and
engine/edged.c) for implementation details.

Conversion
==========

   Convertup and convertdown functions are used for converting screen
coordinates to position in fractal and back. Convertup is function that
receives coordinates in child's image and is expected to convert them
into coordinates in parents image and call parent's convertup function.

   Convertdown is reversed(from parent to child).

   In case coordinates respond 1:1 you should use convertupgeneric and
convertdowngeneric. In other case implementation should look like:

     static void convertup(struct filter *f,int *x,int *y)
     {
         *y*=2;
         *x*=2;
         if(f->next!=NULL) f->next->action->convertup(f->next,x,y);
     }
     static void convertdown(struct filter *f,int *x,int *y)
     {
         *y/=2;
         *x/=2;
         if(f->previous!=NULL) f->previous->action->convertdown(f->previous,x,y);
     }

Removing of filter
==================

   Before filter is removed from queue, removefilter function is called.
It is expected to clean up thinks filter changed. Should be NULL in
most cases.

Registering of filter
=====================

   Once filteraction structure is filled, filter is done and you should
try to enable it. To enable it in user interface you need to edit
ui/ui_helper.c, add filter into uih_filters structure and increase
uih_nfilters.  Note that order of filters in uih_filter is significant,
since same order is kept in filter queue, so you should specify if you
want to be called before/after filter xy.

   Then it is high time to start experimenting.

   Good luck!


File: xaosdev.info,  Node: algorithm,  Next: timerlib,  Prev: filters,  Up: Top

Algorithm description
*********************

   The main idea behind XaoS is that it is not required to calculate the
whole image every frame. Most pixels are already calculated in the
previous frames. You usually don't have exactly the pixels you want,
but all within a range lower than a step between pixels are acceptable.
That is why the image flicker a bit and why points do not blink
randomly as in recalculated animations.

   This document describes some of the most important algorithms in XaoS
   * Saving Previous Pixels

   * Approximation Algorithm

   * Moving Pixels to New Positions

   * Calculating New Pixels

   * Symmetry

   * Calculation of Mandelbrot Set

   * Dynamic Resolution

   * Autopilot

Saving Previous Pixels
======================

   Ideally, all recalculated points should be saved and used for
building successive frames. I could not figure out a practical way to
implement this. To save all frames for half an hour would require 24 Mb
of memory, and searching the saved frames would be more computationally
expensive than recalculating an entirely new frame.

   One way was later used by program Frang. It remembers all pixels as
x,y and value fields and when it builds new image, it draws all pixels
to it and then browses image and fills it by new pixels. Possibly some
rle cache should be used for calculated pixels. Frang actually uses
algorithm, that takes away pixels out of screen, so it behaves exactly
in same way as algorihm described here. At the other hand, this method
seems to require much more memory than XaoS algorithm and drawing
pixels/browsing image cost quite a lot, so algorithm described here
seems to be faster. Since it never requires examining of whole image
and new image is constructed using block move operations.

   For this reason only the last generated frame is used as reference.
This way the memory requirements are proportional to xsize * ysize. It
can be shown that this method is only about 2-5% slower during zooming.
Of course unzooming back to once browsed areas is much slower.

   Because only the previous frame is used, another optimization can be
performed: Imaginary and real parts of the calculated image are not
precise since they are the result of successive iterations of same
algorithm. In order to prevent errors from being distributed to the
following frames their exact coordinates need to be known.
Fortunately, it isn't necessary to save their values since it is known
that all real components in a row and all imaginary components in a
column are equal. Thus, the only things that must be saved are the real
components for every row and the imaginary components for every column.

   This allows for a substantial speed-up in approximation because the
calculation requires less data. Of course, some rows and columns fall
out of the threshold and new ones need to be calculate to fill in the
gaps in the frame.

   Obviously, much less work is done. There are only xsize + ysize
calculations instead of xsize * ysize. So the main loop in XaoS looks
like this:
   * Make approximations for rows

   * Make approximations for columns

   * Move old pixels to their new positions

   * Calculate pixels for which there is no good approximation for
      their row

   * Calculate pixels for which there is not good approximation for
       their column but there is one for their row

Approximation Algorithm
=======================

Introduction to problem
-----------------------

   You can see that the approximation algorithm is central to the
implementation of XaoS. If the guess is incorrect the image will look
strange, boundaries will not be smooth and the zoom will flicker. On
the other hand, if it adds more new rows or columns than required,
zooming will become much slower. Also, in the instance of doubling
(i.e., using an old row or column more than once) the resolution will
lower. It is important to keep the increasing imaginary and real
components in the correct order. If a row and column of complex
coordinates follows one with higher coordinate values an improved
approximation can be attained by swapping their values.

   The algorithm needs to be relatively fast. It is only used for xsize
+ ysize values but if its speed is proportional to O(n^2), it can be
slower than a whole recalculation of the image. Speeds of O(n) or O(n *
log(n)) are acceptable.

Some simple algorithms to solve it
----------------------------------

   Initially, a very simple algorithm was used:

   Find the old row/column nearest the row/column that needs to be
regenerated. If the difference between them is less than one step
(step = (end - beginning) / resolution) then use it. Otherwise,
recalculate a new one.

   Finding the nearest row/column pair is very simple since it is always
greater or equal to the pair needing to be generated.

   Surprisingly, this simple algorithm has almost all the problems
described above. Doubling was fixed by lowering the limit to step / 2.
This cause a considerable slowdown so the limit was returned to step.
Instead, the algorithm was changed to search for only row/column pairs
that are greater than the previous frame's row/column pairs. This is
the algorithm that was used in version 1.0

   This algorithm still added to many new rows and columns and did not
generate smooth boundaries. For version 1.1 a heuristic was added that
preferred approximating rows/columns with lower values. This way it did
not occupy possible rows/columns for the next approximation. The result
was a speedup by a magnitude of four. In versions 1.1 to 2.0 many
improvements were made to the heuristic to give it added performance.
The following example tries to explain how complicated the problem is
(O is the old coordinates and X is the values to be approximated):
             X1        X2        X3        X4        X5        X6        X7
     O1 O2                    O3 O4 O5                   O6 O7 O8

   The normal algorithm will aproximate X1 by O2, X3 by O4 but nothing
more. For the algorithm with threshold step instead of step / 2:

       O2 to X1
       O3 to X2
       O4 to X3
       O5 to X4
       O6 to X5
       O8 to X6

   But this will fail with X7. The second algorithm which relies on
lower values will do the following:

       O1 to X1
       O3 to X2
       O4 to X3
       O5 to X4
       O6 to X5
       O7 to X6
       O8 to X7

   O1 to X1 is wrong. And there is many and many other situations that
may occur. But you may see that the normal algorithm will calculate 4
new rows/columns but the heuristic saves all of these calculations.

Current algorithms used
-----------------------

   In version 2.1 work on this heuristic was disabled after I discovered
a surprisingly simple algorithm that solves all these problems. First I
decided to define exactly what is best approximation. This should be
done by defining a price for every approximation and choose the
approximation with the lowest price. Prices are defined as such:

   Approximating row/column x by y costs dist(x, y) ^ 2.

   This prefers two smaller approximation errors before a single larger
error and describes my goal quite well.

   The cost for adding a new row/column specifies when it is better to
do a bad approximation and when to add a new row/column. I use (4 *
step) * (4 * step). This means that the approximation is acceptable when
dist(x, y) < 4 * step. Otherwise, adding a new row/column costs less.
Now the best approximation is known. All that is required is a fast
algorithm to do this. Surprisingly, this is possible in linear time
using a relatively simple dynamic algorithm. It uses approximations of
length < n to make a guess at the length of n. It can start by
approximating one row/column and then again for two, three up to
xsize/ysize rows/columns.

   The algorithm starts by calculating prices for all possible new
positions for old row/column 1. Because of the pricing there are
maximally 8 new positions. (Other ones must cost more than adding new
row/column). Of course it is possible that there are no new positions.

   For calculating the price of approximations for row/column 2 I may
use previous one: Try new position n. Calculate the price and add the
best approximation for the previous (row/column 1) one that uses a new
position lower than n(prohibits doubling or swapping). This should be
one of 8 positions or eventually adding of new one and not using
row/column 1 at all.

   The same method can be used for the rest of the rows/columns. At the
end the best price may be found for the last row/column and return by
the way it was calculated. (For this I need the saved "calculated
using" values.) At this step the best approximation has been determined.

   To fill the table, 9 * n steps are required and n steps to backtrack
best approximation. The only problem is that this algorithm is still a
little slow (chiefly because of slow memory access on Intel
architectures). -But with some optimizing it works well.

   This algorithm is almost perfect except that it occasionally adds new
rows/columns to the wrong locations. It does not prefer to add new
rows/columns into holes. But it does not seem that this is the real
problem. The last optimization made was based upon the face that added
rows/columns do not have the exact real and imaginary components
calculated by (beginning + x * step) but lies at the average of left
and right neighbors. This makes the boundaries smooth and distributes
coordinates better. It also has the added benefit of making the input
better for future approximations.

   Another danger during implementation if this algorithm is that
adding new rows/columns into their ideal positions should cause
miss-ordered results, since some rows/columns should be off more that
is distance between them.  To avoid this, I use algorithm that always
examine start and end of block of new rows/columns and linearly
interpolates value between them. Special care needs to be at the blocks
that start at the beginning or overs at the end.

   Implementation should be much faster using custom fixedpoint
routines--first recalculate values that 0 means start of image and
65536 means end.  Than calculation is much cleaner. Values <0 and
>65536 are of screen, calculation is independent at scale and many
thinks should be recalculated--like tables for calculating price from
distance.  Also dividing main loops into many specialized parts and
avoiding filing unnecessary parts of table helps. So current algorithm
in XaoS is about 5 or 6 times faster than first naive implementation.

Moving Pixels to New Positions
==============================

   Since XaoS is using the approximation algorithm the following table
is filled for every row/column:
   * calculate

   * oldpoint

   * position     calculate is 1 if the current row/column is new and
needs to be calculated or 0 if no old pixels need to be moved. oldpoint
is a pointer to the old row/column that corresponds to the new one. This
pixel needs to be copied to the new location. position is the real and
imaginary components of the coordinates used for future approximations.
Because almost all points will be moved, the solution seems to be
simple: for every new point look at the row and column table; copy it
if required.

   There is the problem that this minimally needs three memory reads for
every pixel (read calculate, oldpoint and index of old point). This is
too slow, so a small optimization is performed. Instead rewriting the
piece of code in assembly, normal memcpy is used to move blocks of
pixels to their new locations. This minimizes the internal loop and
access can be done more quickly since memcpy is usually optimized for
each architecture.

   Using the row table, a list of blocks to move for every row is
created. With this new table all the pixels can be moved quickly. This
increased the speed of XaoS about four times and made this function so
fast that it is no longer a problem. (In fact, it takes much less
processing than all other parts of XaoS.)

Calculating New Pixels
======================

   The above optimizations make XaoS very fast, but another 30% increase
in speed is acquired by using a clever method for calculating the new
pixels. Many methods are known for saving calculations during the
generation of fractal images. The most powerful is boundary detection.
It relies on the fact that the Mandelbrot Set is connected with lakes.
You need only one pixel at the boundary, then traverse the whole set
and then fill the solid area inside. This method saves many
calculations but is too complex for adding just one line. Many claim
that it does not introduce any errors, but this is not true. It is
possible for a connected part of the lake to be so small that it is not
visible in smaller resolutions. In this case, boundary detection misses
the whole area. This algorithm is actually used just for calculating of
new images (i.e. at the startup).

   XaoS uses modification of method known as solid guessing. The pixels
at the boundaries of a rectangle are calculated. If they are all the
same you may assume that this rectangle does not does not contain
anything and fill it.

   This algorithm is further modified to operate on added lines. For
this it is at least as good as boundary detection and produces more
tangible errors. When adding a single line, the upper and lower line
may be examined for the nearest three pixels. If they are all the same
then it is assumed that 9x9 pixels are the same. This disables all
calculations inside solid areas and calculates as many points as
boundary detection. The only possibility of creating a larger error
with this method as opposed to boundary detection is in the instance
that the shape of the set is so sharp that it does not set any of the
tested points but comes from the right (i.e., uncalculated) location.
This situation is not very common.

   Later, rules were added for new rows and columns that crossed each
other. In this instance you can test only four pixels. This situation
is very rare. It is hoped that it does not introduce many errors.

   If multiple blocks of new lines need to be calculated there are not
reference pixels to use for solid guessing. Interlacing does the trick.
By calculating the odd lines without any guessing, the guessing
algorithm is now possible for the remaining uncalculated lines. This
simple trick saves about 30% of the calculation of the main Mandelbrot
image.

   A similar approximation can also be done for the X coordinate. This
makes it possible to improve solid guessing at even pixels because all
surrounding pixels are available, further reducing errors.

Symmetry
========

   Many fractals are horizontally or vertically symmetrical. This is
implemented in the approximation code. When there is no good
approximation available, try to mirror the opposite side if the line is
available.

   This method primarily speeds up the initial image.

Calculation of the Mandelbrot Set
=================================

   Internal Mandelbrot calculation loop is unrolled--it calculates
first 8 iterations using normal method and then it expects that number
of iterations will be probably large so it switches into mode, where it
calculates iterations in block of 8 with one bailout test at the end.
When bailout is received, saved values from previous iterations is
restored and last 8 iterations are recalculated slowly to get exact
values. This helps a lot especially at Pentium, where conditionals in
floating point code is slow.

   Another stuff is periodicity checking. XaoS has both version of
loops--with an without periodicity checks. In most cases it uses
nonperiodicity checking version. Periodicity check version is used just
in case, some inside set pixel has been found during solid guessing
paste around. This is done mainly because periodicity checking version
of loop is significantly slower.

Dynamic Resolution
==================

   The above optimizations often do not help enough and image
calculation is still too slow. One option was to reduce the framerate,
but a framerate lower than 5 frames per second is unbearable. Another
option is simply to calculate only the details that can be determined
within a time interval.

   Rows/columns not calculated are simple approximated by referencing
the nearest other row/column. The result is an image with larger pixels.
One problem is the fact that the order of calculating the rows/columns
is significant. Previous versions of XaoS simply calculated all rows
from top to bottom and then columns from left to right. Using the
dynamic resolution code with this algorithm would result in distorted
images. This was solved by adding priority to every row/column and
calculating the high priority row/column first. The algorithm for
adding these priorities is as follows:
   * Find middle row/column of uncalculated block. Priority is the size
        of the block (in floating point coordinates)

   * Start function for left block and right block

   This function produces quite good results. It tends to make same size
rectangles on the whole image and does not depend on resolution.

   Another interesting optimization is that during the zoom it is more
advantageous to calculate rows/columns in the center of the zoom
instead of the borders since these will be in the viewport longer and
the user is usually focusing on center of the zoom anyhow.

   This is done by simply adding to the calculated priority
normal_priority / (abs(newposition - oldposition) / step + 1). This
prefers rows/columns that do not move a great deal. Of course,
unzooming uses the formula reversed.

   The last variable to consider is the time interval for one frame.
Setting it too low makes the calculation slow. Setting it too high
makes the framerate too low. So the amount of time spent in other parts
of the program is calculated and multiplied by 5 to determine the
interval. If time is then lower than 15FPS, 15FPS is used instead,
since slower animations are unacceptable. At the other hand if it is
higher than 35FPS, it is set to 35FPS, since higher framerate is just
wasting of computer resources. When image is not animating, this values
is changed, so framerate is choose between 5FPS and 15FPS. This caused
that images are calculated quickly after zooms stops.

Autopilot
=========

   Another interesting algorithm controls the autopilot. It is actually
quite simple. Interesting parts are found at the boundaries of the set.
It randomly looks around and zooms to the first area containing both
outside and inside set points. Some fractals (such as the Newton) do
not have points inside the set at all. In this case it selects a point
where many (more than 2) different colors are around. (i.e., It zooms
into noisy areas.)

   In the instance that there are no such areas, the autopilot will
unzoom. Also detects oscillating.

   Current implementation also does detection of out of range numbers
and randomly choosed points are choosed near the old one, to avoid too
often changes of direction.

SMP support
===========

   Since version 3.0 XaoS supports SMP. This is done using threads.
Most of XaoS routines should be threaded easily--for example
moveoldpoints just divides image into n equal part and each part is
proceeded by one processor.  Only unthreaded part is realloc table
calculation routines. I don't see any way to paraelize it except it
calculates both--x and y approximation at one time (using two
processors).  Another interesting algorithm to paraelize is boundary
trace. See comments `btrace.c' for discussion about current
implementation.  Only problem of current implementation I see is
possibility, that calculation is divided into too many parts (realloc
tables, move points, calculate, symmetries, dynamic resolution) and
tasks needs to synchronize between each part. So this should be too
slow at real SMP box.


File: xaosdev.info,  Node: timerlib,  Next: registry,  Prev: algorithm,  Up: Top

The timer library
*****************

   Timer library is library I did for timing in XaoS. But I found it
useful in many other programs (like demonstrations, games, animation
players and all other stuff that needs to be timed). So you should read
this description and possibly use it in your application and save some
coding time.

   There is many ways how to design of such timed application (game)

  1. read user input, move badies, display and again this way has one
     disadvantage. Speed of game depends on speed of computer.  This
     was acceptable in old times where only processor was Z80 :) but now
     with wide variety of various hardwares such internal loop is
     unacceptable

  2. read user input, measure time since last loop and calculate step
     for badies, move badies for set step, display and again.  This way
     fixes problem with speed. But moving badies just for calculated
     step, that should differ a much is quite complex, usually
     introduces complex calculation, floating/fixedpoint math and other
     unnecesarry stuff that makes program long and introduces many bugs.

  3. Set the fixed framerate that is high enough to make game smooth
     but low enough to do whole internal loop in time. So internal loop
     should look like: read user input, move badies, display, measure
     time spent in loop an sleep rest of time until next frame.  This
     is quite popular scheme but has another disadvantage--game can not
     be designed to use whole CPU power since on slower computers
     internal loop should take longer time that is reserved for one
     frame. Game will run slowly again.

  4. To take away disadvantage of previous method, many games times just
     moving of badies and user input. Other stuff like displaying
     should be done in rest of time. In DOS games moving and user input
     is often at asynchronous interrupt and drawing runs as main loop.
     This solves problem in case that drawing of game takes
     significantly longer time than moving of badies. This is quite
     usual so this scheme works well.

  5. previous scheme still has one problem--since timer interrupt works
     asynchronously, there should happend many race condition, in case
     moving takes longer time than time reserved from frame, computer
     can crash. So this scheme should be enhanced into synchronous one
     with exactly same result but avoiding problem with race condition:

     read user input, measure time spent by loop and calculate how many
     simulated frame interrupts activated since last activation, if
     zero sleep until simulated interrupt, move badies as many times as
     required, display

     this is an combination of 4 and 3 and seems to be most comfortable
     way for writing games but since main loop is now quite complex
     many games don't do that.

  6. there is still one small problem. Method 5 expect that moving takes
     significantly lower time that displaying. This may not be truth.
     Simple work around is to write moving routine, that should move
     for x moves by faster way that calling move x times. This is often
     possible and makes easy extension to scheme 5. This scheme allows
     you to use very large maximal framerate (say 100FPS) and to have
     same results as method 2 (that is maximally exact method)

   As you can see, designing of main loop isn't so easy. This is just
very simple example. More advanced application for example should want
to move one set of badies at one framerate and other at different
framerate. This requires two such timings. Another complication is that
there is many different ways to measure time exactly at different
platforms. Under Linux you can measure using gettimeofday but under DOS
this is exact just to 1/18 of second and thats too low for smooth
animation and so on.

   Thats why I decided to design portable easy to use timer library,
that makes easy to implement all described method, combining of them
and much more.  During design I taken care at the following thinks:
quality of timing, how easy to use it is, speed, portability and to
minimalize inexpected situations (like race conditions in asynchronous
interrupts and so on)

The name of game
================

   Timer library operates with "timers". They should be created, you
should measure time since last reset, pause them or set "handler" and
"interval".  But handler is not activated at given interval yet. Since
timer library is not asynchronous, you must activate them.

   For activating is used "groups". You should process group at some
place in your program. Then all timers in group are checked and their
handlers activated if required. When time spent since last activation
is higher than interval, handler is activated more times. Also interval
to next invocation is calculated to keep frequency.  Simple scheduling
is performed at handler--handler is activated just once and then all
other timers are checked before it is activated again. You should also
define an multihandler--handler that is activated just once and
receives argument how many intervals has left.

   There is two special groups--`asyncgroup'. Timers in this group are
activated asynchronously like from interrupt. It is not recommended to
use it, since it brings many problems and usually isn't required. Also
it does not work at many platforms. `Syncgroup' is the default group.
Program is expected to process is quite often. In case you don't need
to use more groups, you should use this one.

   Time in timerlib is bit strange, since it does not flow continuously
but jumps. It is updated every time you call `tl_updatetime'. I used
this way in order to minimize context switches but later I found this
scheme very useful, since you should lookup timer, do something and
then reset it and don't wory about time spend between lookup and reset
since it is 0 in case you did not called tl_updatetime. This helps to
keep frequency of timers exact w/o any errors caused by such
situations. At the other hand you need to call tl_updatetime at least
once in your main loop.

   Maybe you don't know why to create more groups, but I found it quite
useful.  For example an autopilot in XaoS has such special group--I
need to call it approx. every 1/20 of second but just at one place in
program. Invoking of autopilot when calculation is active should
produce incorrect results, so I have special group for autopilot and
process just at one place where I am sure it is safe.

   Timers should be also emulated. You should stop them and then
control flow of time for given timer. This should be quite useful for
example when you want precalculate animation at given framerate.

   To control group of timers, you might create "emulators". It is just
another time controlled by you. It is useful in cases you want to
emulate fixed framerate (for animation rendering) or such.

Time functions
==============

 - Function: void tl_update_time (void)
     Update time used by timerlib. This must be called at least once in
     main loop otherwise time will not flow. See above.

 - Function: void tl_sleep (int TIME)
     Sleep given time. Similar to usleep at POSIX.

Group functions
===============

 - Function: tl_group* tl_create_group (void)
     Allocate and initialize group header. Returns NULL when malloc
     fails.

 - Function: void tl_free_group (tl_group *GROUP)
     Free memory storage used by group structure

 - Function: int tl_process_group (tl_group *GROUP, int *ACTIVATED)
     Process timers in group and activates their handlers. Returns time
     until next invocation. Main loop should sleep returned time then.
     An ACTIVATED parameter sould be `NULL'. If it is non `NULL',
     variable is set to number of activated handlers.

Timer functions
===============

 - Function: tl_timer* tl_create_timer (void)
     Create timer structure.

 - Function: void tl_free_timer (tl_timer *TIMER)
     Free memory storage used by timer structure

 - Function: void tl_reset_timer (tl_timer *TIMER);
     Reset timer to current time. (time of last actication of
     `tl_update_time')

 - Function: int tl_lookup_timer (tl_timer *TIMER);
     Return time since last call of tl_reset_timer or last activation
     of handler.

 - Function: void tl_set_interval (tl_timer *TIMER, int INTERVAL);

 - Function: void tl_set_handler (tl_timer *TIMER, void (*HANDLER)
          (void *),void *userdata);

 - Function: void tl_set_multihandler (tl_timer *TIMER, void (*HANDLER)
          (void *,int),void *userdata);
     Handler, multihandler and interval control functions

 - Function: void tl_add_timer (tl_group *GROUP, tl_timer *TIMER)
     Add timer to given group. Timer should be added into just one
     group.

 - Function: void tl_stop_timer (tl_timer *TIMER)

 - Function: void tl_resume_timer (tl_timer *TIMER)
     Stop and resume timer.

 - Function: void tl_slowdown_timer (tl_timer *TIMER,int TIME)
     Time in timer is moved back for given time.

Emulator functions
==================

 - Function: struct timeemulator *tl_create_emulator (void);
     This function creates new emulator--you need to create one first
     before emulating.

 - Function: void tl_free_emulator (struct timeemulator *T);
     Destroy emulator's data

 - Function: void tl_elpased (struct timeemulator *T, int ELPASED);
     Move emulated time.

 - Function: void tl_emulate_timer (struct timer *T, struct
          timeemulator *E);
     Set timer to the emulated mode. Since now all time is controled by
     emulator E. All other behavior of timer keeps unchanged.

 - Function: void tl_unemulate_timer (struct timer *T);
     Disable emulated mode for the timer.

Example main loop
=================

     while(1)
     {
       time=tl_process_group(syncgroup,activated); /*Call game control functions*/
       update_keys();
       if(activated) /*something changed*/
         display();
       else tl_sleep(time);
     }


File: xaosdev.info,  Node: registry,  Next: index,  Prev: timerlib,  Up: Top

XaoS function registry
**********************

   XaoS has an ui helper library, which provides functionality provided
by user interface. All it's useful functions are registered into
central registry.  This registry is used to generate menus and dialogs
as well as command line options or scripting language. So it is very
significant think in XaoS design.

   Not only those who want hack XaoS ui-helper layer needs to know
this, but also authors of drivers should use this to add new driver
depended functions into XaoS's menu. Also external user interface is
based at this.  Main idea behind external user interfaces (currently
one for TCL/Tk and Gtk is under development) is following: XaoS
transfers it's registry to interface (using simple description
language). User interface starts XaoS in it's window and builds menus
and dialogs based at this registry. Then once user select some
function, it creates an command for scripting language and sends it back
to XaoS' engine.

   So knowledge of this part is essential for many developers. Please
take care for this part.

   The implementation of registry is in file `xmenu.c', header is
`xmenu.h'. Mainly for historical reasons it speaks about menus and
dialogs. (It was designed for the GUI at the beginning) I am keeping
this terminology, since it is quite clean and easy to understand
instead of talking in some cryptic abstract term.

Function description
====================

   To add function into database, you need write it's description into
menuitem structure. It has following prototype:

     typedef struct menuitem
       {
         char *menuname;
         char *key;
         char *name;
         char *shortname;
         int type;
         int flags;
         void (*function) ();
         int iparam;
         void *pparam;
         int (*control) (struct uih_context *);
         menudialog *(*dialog) (struct uih_context *);
       }
     menuitem;

 - Variable: menuname
     Name of menu (or category) function belongs in. The root of all
     categories is called `"root"'. XaoS alternativly uses an
     `"animroot"' when animation replay is active. If you are adding an
     function, it is better to add it into some subcategory like as
     `"ui"' (it will be placed into UI menu then) or create an new
     category for your functions if needed. It will appear as submenu
     in main menu in the UI.

 - Variable: key
     Ascii code of hotkey to activate this function. Use `NULL' if none.

 - Variable: name
     Longer name of functions used in the menu entry, or `xaos --help'
     listing

 - Variable: shortname
     One-word name of function used in command language and references
     to function.

 - Variable: type
     type of function--this is not return type. Type should be one of
     following constants:
    `MENU_SUBMENU'
          An submenu. This is not real function, but name for submenu.
          You might fill    the KEY, NAME, SHORTNAME functions. An name
          of this new    submenu is placed in the field PPARAM.

    `MENU_NOPARAM'
          An normal function without any parameters. When actived,
          function    FUNCTION with just an pointer to `uih_context'
          will be called.

    `MENU_INT'
          This should be used to simplify entering of more similar
          functions (handled    by just one universal function in the c
          code). This function is handled in    same way as
          `MENU_NOPARAM', but also in one integer parameters taken
          from `iparam' is passed.

    `MENU_STRING'
          Similar to `MENU_INT' but uses string instead of integer.

    `MENU_DIALOG'
          If you function needs some paramters, use dialog structure to
          describe    them. In scripting language your function will
          have parameters then, in    user interface dialog will be
          displayed. PPARAM must then point to    array of dialog
          entries. Witting them will be described later.     If your
          function has just one parameter described in dialog
          structure, it    will be called in normal c way--if you want
          string parameter, one    pointer pointing to string (in
          addition to `uih_context') will be    passed to the functions.

          In case of multiple parameters are requested, it is
          impossible to call    function in c way without special
          wrapper for each such case. So it will    receive pointer to
          array of `dialogparam' unions, wich contains    one entry for
          each parameter. `dialogparam' is declared as follows:
               typedef union
                 {
                   char *dstring;
                   int dint;
                   number_t number;
                   number_t dcoord[2];
                   xio_path dpath;
                   void *dummy;
                 }
               dialogparam;

    `MENU_CDIALOG'
          In some cases, it is useful to add some context specific
          default values    to the dialog structure. In this case you
          might use this type instead. In    this case function DIALOG
          is called first, and it is expected to    return pointer to
          correct dialog structure. Dialog structure must lie in
          static storage (since it is not freed) and always must have
          the same    fields, just differ in the default values.
          Also this function must work correctly even in the case
          pointer to    `uih_context' is `NULL', since it is often
          called in the    initialization stages (parameter parsing
          etc.)

 - Variable: flags
     Flags are used to set additional information about function:
    `MENUFLAG_CHECKBOX'
          Some features act like check-box--i.e. by one calling of
          function they are enabled, second call disables this. In menu
          it is useful to add an check-box for this function indicating
          whether feature is on or off.

          And thats exactly what this flag does :). You need also
          define the function CONTROL wich return's `1' when enabled
          and `0' when disabled.  In order to let external GUI's work
          correctly you need also call `uih_updatemenus("name")' every
          time state of this function changes.

          In the scripting language this adds an first parameter, wich
          if `#t' or `#f'.  Engine then calls function just when it is
          necessary. For `#t' dialog is requested, with `#f' function
          is called just as `NOPARAM'. I.e.  dialog is displayed just
          when enabling feature.

    `MENUFLAG_DIALOGATDISABLE'
          In checkbox display dialog when this feature is disabled
          instead when enabled.

    `MENUFLAG_RADIO'
          Other features act like radio-button. Control function in
          this case receives same parameter as defined for `MENU_INT'
          or `MENU_STRING' types and is expected to return `1' when
          enabled. You also need to call `uih_updatemenus' when
          changed. No special parameter is added in the scripting
          language.

    `MENUFLAG_INTERRUPT'
          Interrupt current calculation when this function called (it
          is used by functions with causes recalculation of screen)

    `MENUFLAG_INCALC'
          By default XaoS queues functions and calls later when they
          are activated in caluclation. This flag disables this feature.

    `MENUFLAG_ATSTARTUP'
          By default XaoS queues functions and calls later when they
          are activated as command line parameters (in time engine is
          not fully initialized yet).  This flag disables this feature.

    `MENUFLAG_NOMENU'
          Function will not be visible in the menu

    `MENUFLAG_NOPLAY'
          Function will not be available as command in scripts

    `MENUFLAG_NOOPTION'
          Function will not be available as command line option

Initializing menuitem structure as static variable
==================================================

   In most case menuitems should be wrote as static variables. Because
contents of this structure should change in future, please use one of
macros defined in `xmenu.h'. They provides cleaner and easier to extend
way to define this entries.

   For example to define `MENU_NOPARAM' function use following macro:

 - Function: MENUNOP (MENUNAME, KEY, NAME, SHORTNAME, FLAGS, FUNCTION)
   Similar macros exist for the other types too. They ends for `CB' or
`RB' for check-boxed or radio-boxes functions. See `menu.c' for large
example of definitions. They should look like this:

     static menuitem menuitems[] =   /*XaoS menu specifications */
     {
       SUBMENU ("", NULL, "Root menu", "root"),
       SUBMENU ("", NULL, "Replay only commands", "plc"),
       MENUNOP ("comm", NULL, "print menus specifications of all menus",
                "print_menus", MENUFLAG_NOMENU|MENUFLAG_NOPLAY|MENUFLAG_ATSTARTUP,
                uih_printallmenus),
                ...

Dialog description
==================

   Dialog description is similar to menuitem. It is array of following
structures:
     typedef struct dialog
       {
         char *question;
         int type;
         int defint;
         char *defstr;
         number_t deffloat;
         number_t deffloat2;
       }
     menudialog;
   It is terminated by QUESTION pointer set to `NULL'.

   The QUESTION contains string ui should display when is asking for
this field.

   TYPE should be one of following values: `DIALOG_INT',
`DIALOG_FLOAT', `DIALOG_STRING', `DIALOG_KEYSTRING' (the difference
between string and keystring is, that in scripting language string is
passed as `"hello"', but keystring is passed as scheme keyword as
`'hello'), `DIALOG_IFILE' (input file), `DIALOG_OFILE', `DIALOG_CHOICE'
(choice between different keystrings), `DIALOG_ONOFF' (boolean
parameter), `DIALOG_COORD' (two floats--complex number)

   Set to corresponding DEF* field for default value. In case of files
use string in the format `"[PREFIX]*[EXTENSION]"'. For type
`DIALOG_CHOICE' set DEFSTR to pointer to array of strings terminated by
`NULL' entry.

   To write dialog structures again use macros defined in `xmenu.h'
like:
     DIALOGSTR(question,default)
   The definition should look like:

     static menudialog uih_viewdialog[] =
     {
       DIALOGCOORD ("center:", 0, 0),
       DIALOGFLOAT ("Radius:", 1),
       DIALOGFLOAT ("Angle:", 0),
       {NULL}
     };

Modifying registry
==================

 - Function: void menu_add (menuitem *ITEM, int N);
     Add array of N items to the database.

 - Function: void menu_delete (menuitem *ITEMS, int N);
     Remove array of N items from database.

Querying registry
=================

 - Function: menuitem* menu_findkey (char *KEY, char *ROOT);
     Find item for given key. ROOT is menu where to start (submenus are
     searched recursively)

 - Function: menuitem* menu_findcommand (char *NAME);
     Find item for given short name

 - Function: char* menu_fullname (char *MENU);
     Long name for the short name of menu

 - Function: menuitem* menu_item (char *MENU, int N);
     Nth entry of the MENU. Return `NULL' if no more entries available.

 - Function: int menu_enabled (menuitem *ITEM, struct uih_context *C);
     Check whether given item is activated (for check-boxed and
     radio-boxed functions)

 - Function: int menu_havedialog (menuitem *ITEM, struct uih_context
          *C);
     Does this function have dialog?

 - Function: menu_getdialog (CONTEXT, M)
     Macro returns pointer to dialog structure. (function must have it,
     otherwise garbage is returned).

 - Function: int menu_available (menuitem *ITEM, char *ROOT);
     Check whether item is available as one of entries of ROOT (or it's
     submenus)


File: xaosdev.info,  Node: index,  Prev: registry,  Up: Top

Index of functions, variables, types and constants
**************************************************

* Menu:

* alloc_buffers:                         driver.
* ANIMATION:                             filters.
* C256 <1>:                              filters.
* C256:                                  driver.
* CHANGED:                               filters.
* createfilter:                          filters.
* display:                               driver.
* ethreads:                              xthreads.
* filter:                                filters.
* filteraction:                          filters.
* FIXEDCOLOR <1>:                        filters.
* FIXEDCOLOR:                            driver.
* flip_buffer:                           driver.
* flush:                                 driver.
* free_buffers:                          driver.
* FULLSCREEN:                            driver.
* getinstance:                           filters.
* getsize:                               driver.
* GRAYSCALE <1>:                         filters.
* GRAYSCALE:                             driver.
* image <1>:                             filters.
* image:                                 design.
* INEXACT:                               filters.
* inherimage:                            filters.
* inhermisc:                             filters.
* init:                                  driver.
* initdata:                              filters.
* MASK1BPP:                              filters.
* MAXCONDS:                              xthreads.
* MAXSEMAPHORS:                          xthreads.
* menu_add:                              registry.
* menu_available:                        registry.
* MENU_CDIALOG:                          registry.
* menu_delete:                           registry.
* MENU_DIALOG:                           registry.
* menu_enabled:                          registry.
* menu_findcommand:                      registry.
* menu_findkey:                          registry.
* menu_fullname:                         registry.
* menu_getdialog:                        registry.
* menu_havedialog:                       registry.
* MENU_INT:                              registry.
* menu_item:                             registry.
* MENU_NOPARAM:                          registry.
* MENU_STRING:                           registry.
* MENU_SUBMENU:                          registry.
* menudialog:                            registry.
* MENUFLAG_ATSTARTUP:                    registry.
* MENUFLAG_CHECKBOX:                     registry.
* MENUFLAG_DIALOGATDISABLE:              registry.
* MENUFLAG_INCALC:                       registry.
* MENUFLAG_INTERRUPT:                    registry.
* MENUFLAG_NOMENU:                       registry.
* MENUFLAG_NOOPTION:                     registry.
* MENUFLAG_NOPLAY:                       registry.
* MENUFLAG_RADIO:                        registry.
* menuitem:                              registry.
* MENUNOP:                               registry.
* mousetype:                             driver.
* nthreads:                              xthreads.
* P_FLOAT:                               driver.
* P_NUMBER:                              driver.
* P_STRING:                              driver.
* P_SWITCH:                              driver.
* palette:                               design.
* params:                                driver.
* PIXELSIZE:                             driver.
* print:                                 driver.
* processevents:                         driver.
* RANDOM_PALETTE_SIZE:                   driver.
* requirements:                          filters.
* RESIZE_COMMAND:                        driver.
* RESOLUTION:                            driver.
* SCREENSIZE:                            driver.
* set_color:                             driver.
* set_range:                             driver.
* timeemulator:                          timerlib.
* tl_add_timer:                          timerlib.
* tl_create_group:                       timerlib.
* tl_create_timer:                       timerlib.
* tl_elpased:                            timerlib.
* tl_emulate_timer:                      timerlib.
* tl_free_emulator:                      timerlib.
* tl_free_group:                         timerlib.
* tl_free_timer:                         timerlib.
* tl_lookup_timer:                       timerlib.
* tl_process_group:                      timerlib.
* tl_reset_timer:                        timerlib.
* tl_resume_timer:                       timerlib.
* tl_set_handler:                        timerlib.
* tl_set_interval:                       timerlib.
* tl_set_multihandler:                   timerlib.
* tl_sleep:                              timerlib.
* tl_slowdown_timer:                     timerlib.
* tl_stop_timer:                         timerlib.
* tl_unemulate_timer:                    timerlib.
* tl_update_time:                        timerlib.
* TRUECOLOR <1>:                         filters.
* TRUECOLOR:                             driver.
* TRUECOLOR24 <1>:                       filters.
* TRUECOLOR24:                           driver.
* TRUECOLOR32 <1>:                       filters.
* TRUECOLOR32:                           driver.
* UI_C256:                               driver.
* ui_driver:                             driver.
* UI_FIXEDCOLOR:                         driver.
* UI_GRAYSCALE:                          driver.
* UI_TRUECOLOR:                          driver.
* UI_TRUECOLOR24:                        driver.
* UI_TRUECOLOR32:                        driver.
* uninit:                                driver.
* UPDATE_AFTER_RESIZE:                   driver.
* xshl_line:                             eui.
* xth_bgjob:                             xthreads.
* xth_function:                          xthreads.
* xth_init:                              xthreads.
* xth_lock:                              xthreads.
* xth_nthread:                           xthreads.
* xth_sleep:                             xthreads.
* xth_sync:                              xthreads.
* xth_uninit:                            xthreads.
* xth_unlock:                            xthreads.
* xth_wakeall:                           xthreads.
* xth_wakeup:                            xthreads.



Tag Table:
Node: Top501
Node: design1475
Node: driver9067
Node: gui-driver25868
Node: eui32613
Node: ui-helper43320
Node: xthreads47876
Node: filters52923
Node: algorithm69506
Node: timerlib89511
Node: registry99566
Node: index111446

End Tag Table