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
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<TITLE>XmHTML Programmers Guide</TITLE>
<META HTTP-EQUIV="Keywords" CONTENT="XmHTML, HTML, Motif, Widget, Programming, Linux">
<META HTTP-EQUIV="Reply-to" CONTENT="ripley@xs4all.nl">
<META HTTP-EQUIV="Description" CONTENT="This document contains XmHTML's programmers Guide. XmHTML provides an interactive Motif widget capable of displaying HTML 3.2 text.">
<META NAME="Author" CONTENT="Koen D'Hondt">
<META NAME="Copyright" content="1995-1997 by Ripley Software Development">
<META NAME="Source" content="$Source$">
<META NAME="Revision" content="$Revision$">
<!--
<META NAME="Font" content="helvetica">
<base href="http://www.xs4all.nl/~ripley/eXode/">
-->
<link rev="made" href="mailto:ripley@xs4all.nl">
<link rel="home" href="http://www.xs4all.nl/~ripley">
<link rel="index" href="XmHTML.html">
<link rel="previous" href="legals.html">
<link rel="down" href="parser_prog.html">
<link rel="next" href="convenience.html">
<link rel="copyright" href="copyrights.html">
<link rel="TOC" href="progguide.html">
</HEAD>
<BODY BGCOLOR="#FFFFFF" TEXT="#000000">
<p>
<div align="right">
<b><font face="helvetica, arial" size="7">Chapter 2<br>
XmHTML Widgets</font></b>
</div>
<p> <p>
Have you ever wanted to write an application capable of displaying HTML
documents, went out to find a Widget which offered HTML display capabilities
and finally give up on your wonderfull idea when no such widget seemed to
be available? Maybe you did find a HTML widget but were not satisfied with
its capabilities? With the XmHTML Widget described in this chapter you no
longer have to despair.
<p>
With the XmHTML Widget one can create applications that range from simple
HTML viewers to full-blown WWW browsers. The XmHTML Widget offers a widget
capable of displaying HTML documents and, as one would expect, allows full
interactive use of HTML documents thru various callback resources and
convenience functions. Besides of being able to display HTML documents,
displaying of plain text and images is also supported.
<p>
XmHTML widgets provide the following mechanisms for program control:
<p>
<ul>
<li>Resources that access the widget's content and can alter it's appearance.
<li>Callback resources that allow navigation through and between HTML documents
when hyperlinks are activated.
<li>Callback resources that provide both visual and content information about
the widget's text.
<li>Keyboard management methods that control output (paging style).
<li>Convenience routines allowing quick and easy ways to load images, scroll
through the widget's text and access document information.
</ul>
<p>
XmHTML widgets implement the full HTML 3.2 standard as well as a few
extensions. The chapter on <a href="extensions.html">HTML Extensions</a>
lists the supported extensions. One supported extension that is worthwhile to
mention is the <font face="fixed"><FRAMESET></font> extension.
<p>
The current implementation of the XmHTML widget does have its limitations
though. The most important features lacking in the current release
(1.0.22 Alpha) are support for HTML tables and progressive document
loading. All these features will be added in due time.
<p>
As you will notice in this chapter, the behaviour and name of a number of
XmHTML's resources and convenience functions closely resemble those of Motif's
Text widget. The first reason for this similarity is that both widget's display
text. The second reason is that, if you are already familiar with Motif's Text
widget, the interface to a XmHTML widget will also look familiar and thus
learning how to use a XmHTML widget will be a bit easier.
<h1><a name="basics"><font face="helvetica, arial">
2.1 The Basics of a XmHTML Widget
</font></a></h1>
To understand and appreciate most of the material described in this chapter,
it is important to address some of the basic resources and functions provided
by the XmHTML widget. The widget's text and HTML verification process, document
fonts, dimensions of the widget and hyperlink resources are among the most
important. We begin with how to create a standard XmHTML widget.
<h2><a name="creating"><font face="helvetica, arial">
2.1.1 Creating a XmHTML Widget
</font></a></h2>
Applications that wish to use XmHTML widgets need to include the file
<i><XmHTML.h></i>. You can create a standard XmHTML widget using
the <tt>XtVaCreateManagedWidget()</tt> function:
<pre>
Widget html_w;
html_w = XtVaCreateManagedWidget("name", xmHTMLWidgetClass, parent,
<i>resource-value pairs</i>,
NULL);
</pre>
The <i>resource-value pairs</i> can be any number of resources specific to the
XmHTML widget or its superclasses. Please note that the XmHTML widget is
subclassed from the Manager widget class.
<p>
Another way of creating a standard XmHTML widget is by using the
<tt>XmCreateHTML()</tt> convenience function:
<pre>
Widget html_w;
html_w = XmCreateHTML(parent, "name", <i>args</i>, <i>nargs</i>);
</pre>
The <i>args</i> argument can be any number of resource-value pairs specified
using the <tt>XtSetArg</tt> function. <i>nargs</i> specifies how many
resource-value pairs are contained in the <i>args</i> argument.
<h2><a name="text"><font face="helvetica, arial">
2.1.2 The XmHTML Widget's Text
</font></a></h2>
The first thing to learn about the XmHTML widget is how to access its internal
text storage. The most simple method to do this is by using the
<tt>XmNvalue</tt> resource. Unlike most widgets in the Motif toolkit that use
text, the XmHTML widget does not use compound strings for its value. Instead,
the value is specified as a regular C string as shown in example 2-1.
<p>
<i>Example 2-1. The simple_html.c program</i><br>
<pre>
/* simple_html.c -- Create a minimally configured XmHTML widget */
#include <XmHTML.h>
main(int argc, char **argv)
{
Widget toplevel;
XtAppContext app;
toplevel = XtVaAppInitialize(&app, "Demos", NULL, 0,
&argc, argv, NULL, NULL);
XtVaCreateManagedWidget("html", xmHTMLWidgetClass, toplevel,
XmNvalue, "<html><body>A minimally configured XmHTML widget."
"</body></html>",
NULL);
XtRealizeWidget(toplevel);
XtAppMainLoop(app);
}
</pre>
This short program simply creates a XmHTML widget whose initial value is set
to <b>"A minimally configured XmHTML widget."</b> (See Figure 2-1).
<p>
<img src="../Images/book/simple_html.gif" alt="[A Simple HTML Widget]">
<br>
<i>Figure 2-1. simple_html.c: a minimally configured XmHTML widget</i>
<h3><font face="helvetica, arial">
HTML Verification
</font></h3>
As one can see in the above example, the value of the <tt>XmNvalue</tt> resource
contains five HTML elements: four markup and one text element. This brings us
to one of the most important aspects of the XmHTML widget: it is a widget for
displaying HTML documents. HTML documents are text documents written in the
<i>HyperText Markup Language</i>, which is a language composed of a set of
elements that define a document and guide its display.
<p>
In order for XmHTML to display such a document properly, it is necessary that
the widget verifies the correctness of these markup elements. It does this by
comparing the contents of the document that is to be displayed against the
now official W3C HTML 3.2 recommendation (referred to as the HTML 3.2
standard). This standard defines both appearance and content of each
markup element. During this verification process (which is performed
before anything is displayed), the widget goes thru great lengths as to
ensure that the document adheres to this standard. As such, the widget
is capable of modifying the specified <i>markup</i> elements substantially
(it will never modify text elements). The disadvantage of this document
verification is that a document might not look as expected, but the main
advantage is that even the most horrid HTML document will be displayed.
<p>
A detailed description of this document verification and repair process is
given in the next chapter, so we will only mention that the more a document
adheres to the HTML 3.2 standard, the less the widget will modify the markup
elements.
<h3><font face="helvetica, arial">
Setting a XmHTML Widget's Text
</font></h3>
The initial value of the <tt>XmNvalue</tt> resource may be set either at
initialization time (as in example 2-1) or by using <tt>XtVaSetValues</tt>:
<pre>
XtVaSetValues(html_w, XmNvalue, <i>text</i>, NULL);
</pre>
This resource always represents the entire text of the widget.
<p>
Another method for setting the text in a XmHTML widget is by using the
convenience routine <tt>XmHTMLTextSetString</tt>:
<pre>
void
XmHTMLTextSetString(html_w, value)
Widget html_w;
char *value;
</pre>
Although the two methods produce the same results, the convenience routine may
be more efficient since it accesses the internals of the widget directly
(The <tt>XtVaSetValues()</tt> method involves going through the X Toolkit
Intrinsics). On the other hand, if you are also setting many other resources
at the same time, the <tt>XtVaSetValues</tt> method is better since it saves
the overhead of multiple function calls (All resources can be set in a single
call).
<p>
Whichever function you use, the <i>value</i> (however it is provided) is
copied into the internals of the widget. This is important to known if you have
provided the <i>value</i> via an allocated memory buffer: once the text is set
in the widget, you can safely free this memory buffer.
<p>
A XmHTML widget's may contain large amounts of text provided there is enough
memory available on the computer running the client application. The upper
limit on the number of bytes a XmHTML widget may have is given by the maximum
value of an unsigned int (4 gigabyte on 32 bit systems), so it is more likely
that the user's computer will run out of memory before the XmHTML widget's
maximum capacity is reached.
<h3><font face="helvetica, arial">
Getting a XmHTML Widget's Text
</font></h3>
XmHTML widget's provide several methods for obtaining text. Before learning
how to get the widget's text however, it is important to make a distinction
between the <i>source text</i> and the <i>displayed text</i>. The source text
is the text you have set into a XmHTML widget by using the <tt>XmNvalue</tt>
resource (or by using the <tt>XmHTMLTextSetString()</tt> convenience function),
while the displayed text is the source text after HTML verification
has taken place. This distinction is important since XmHTML widget's will
never modify the source text but instead create a new HTML document while the
HTML verification process is taking place.
<p>
<font face="helvetica, arial" size="3">[Note: A new HTML document is not
actually created: when text is set in a XmHTML widget, the HTML parser
translates the source text to a list of internal objects. The new HTML document
that is mentioned in the above paragraph only exists in theory but can be
created upon request as we will soon see.]</font>
<p>
You might ask yourself why this distinction is important. The answer is that
it depends on the type of application you are using a XmHTML widget for.
Lets assume you are using a XmHTML widget in an application that displays
HTML documents you have retrieved via a network layer (a WWW browser for
example). When the user of your application wishes to save the document he has
been viewing, it is most likely he wishes to save the original document and
not the verified document. On the other hand, when you are using a XmHTML
widget in an application intended for writing and/or verifying HTML documents,
the most obvious thing a user would want to save is his verified document.
<p>
<h4><font face="helvetica, arial">
Getting the Source Text
</font></h4>
So how does one go about getting a XmHTML widget's text? To get the widget's
<i>source</i> text, you can use either <tt>XtVaGetValues()</tt> or the
<tt>XmHTMLTextGetSource()</tt> convenience function. Both methods return the
value of the <tt>XmNvalue</tt> resource. The value returned is a pointer
to the internal text storage, which may never be freed nor
modified. The code fragment below demonstrates how to use the convenience
function:
<pre>
String text_p;
if((text_p = XmHTMLTextGetSource(html_w)) != NULL)
{
/* Save, display the text, but never modify or free it */
}
</pre>
Or, by using the Xt function <tt>XtVaGetValues()</tt>:
<pre>
String text;
XtVaGetValues(html_w, XmNvalue, &text_p, NULL);
</pre>
Similar to using the <tt>XmHTMLTextSetString()</tt> convenience function to
set a XmHTML widget's text, using the <tt>XmHTMLTextGetSource()</tt> to get a
XmHTML
widget's text may be more efficient since it accesses the internals of the
widget directly instead of going through the X Toolkit Intrinsics.
<p>
<font face="helvetica, arial" size="3">[Note: It is also worthwhile to mention
that all of the <tt>XmHTML...</tt> convenience functions access the internals of
the XmHTML widget directly. None of them involves going through the X Toolkit
Intrinsics.]</font>
<p>
If you want to modify the source text, or you just want a copy of the text
that you can modify for other reasons, then you must copy the text
into your own local dataspace:
<pre>
char *text_p, buf[1024];
text_p = XmHTMLTextGetSource(html_w);
(void)strncpy(buf, text_p, 1024);
/* modify "buf" all you want */
</pre>
Here, we don't know how much text <tt>text_p</tt>
points to, but for purposes of this demonstration, we assume it's not more
than 1024 bytes. Just to be sure that we don't cause an overflow of
<tt>buf</tt>, we use <tt>strncpy()</tt>. Let me stress that, unless you are
intimately familiar with the nature of the XmHTML widget your are using, it is
unwise to make general assumptions about the amount of text you are getting.
<h4><font face="helvetica, arial">
Getting the Displayed Text
</font></h4>
The method to get the <i>displayed text</i> is very similar to the Motif
Text <tt>XmTextGetString()</tt> convenience function:
<tt>XmHTMLTextGetString()</tt>.
Both functions allocate enough space (using <tt>XtMalloc()</tt>) to contain
all the text and return a pointer to this newly allocated area. While the
pointer can be modified any way you like, you must free it using
<tt>XtFree()</tt> when you are through using it. The code fragment below
demonstrates how this function may be used:
<pre>
String text_p;
if((text_p = XmHTMLTextGetString(html_w)) != NULL)
{
/*
* Allocated memory returned.
* do anything with "text_p" you want.
*/
XtFree(text_p);
/* we *must* free "text" or there will be a memory leak */
}
</pre>
This convenience function returns a HTML document created from the
XmHTML widget's internal representation of the original source document after
HTML verification has taken place. Depending on the adherance to the HTML 3.2
standard of the original source document, the newly created HTML document may
or may not differ from the original source document. If there is a difference,
it will only be found in the markup elements; XmHTML widget's never modify
text elements.
<p>
Getting the displayed text of a XmHTML widget is potentially an expensive
operation if the widget contains large amounts of text. A XmHTML widget
needs to create a HTML document from the internal representation every time
<tt>XmHTMLTextGetString()</tt> is called.
<h2><a name="dimensions"><font face="helvetica, arial">
2.1.3 XmHTML Widget's Dimensions
</font></a></h2>
Let's return to Example 2-1 and examine more closely what is exposed to the
user. As you can notice from the output of the program (shown in Figure
2-1), a vertical scrollbar is displayed and the text is not entirely visible:
the user has to drag the vertical scrollbar to see all the text contained in
the XmHTML widget. When no size has been specified, the width of a
XmHTML widget defaults to 20 ex (a <i>T<sub>E</sub>X</i> measure for average
character width) and the height of a single line in the default font.
<p>
You specify the size of a XmHTML widget by using the <tt>XmNwidth</tt> and
<tt>XmNheight</tt> resources (which a XmHTML widget inherits from the
<tt>Core</tt> widget), as shown in Example 2-2:
<p>
<i>Example 2-2. The simple_html2.c program</i><br>
<pre>
/* simple_html2.c -- Create another minimally configured XmHTML widget */
#include <XmHTML.h>
main(int argc, char **argv)
{
Widget toplevel;
XtAppContext app;
toplevel = XtVaAppInitialize(&app, "Demos", NULL, 0,
&argc, argv, NULL, NULL);
/* create a XmHTML widget but this time we specify a size */
XtVaCreateManagedWidget("html", xmHTMLWidgetClass, toplevel,
XmNvalue, "<html><body>Another minimally configured XmHTML "
"widget.</body></html>",
XmNwidth, 200,
XmNheight, 75,
NULL);
XtRealizeWidget(toplevel);
XtAppMainLoop(app);
}
</pre>
The output of this program is shown in Figure 2-2.
<p>
<img src="../Images/book/simple_html2.gif" alt="[Another Simple HTML Widget]">
<br>
<i>Figure 2-2. simple_html2.c: another minimally configured XmHTML widget</i>
<p>
The specified width and height are only used at initialization. Once the
application is up and running, the user can resize windows and effectively
change those dimensions.
<p>
<h3><a name="autosize"><font face="helvetica, arial">
2.1.3.1 Autosizing a XmHTML Widget
</font></a></h3>
As you can see in Figure 2-2, the widget's text is now entirely visible
but a vertical scrollbar is still present. We could remove this vertical
scrollbar by obtaining a handle to it and then unmanaging it, but another and
more subtle way to remove the vertical scrollbar is to use the autosizing
feature of a XmHTML widget as shown in Example 2-3.
<p>
<i>Example 2-3. The autosize_html.c program</i><br>
<pre>
/* autosize_html.c -- Demonstrate the autosizing feature of a XmHTML widget */
#include <XmHTML.h>
main(int argc, char **argv)
{
Widget toplevel;
XtAppContext app;
toplevel = XtVaAppInitialize(&app, "Demos", NULL, 0,
&argc, argv, NULL, NULL);
/* make sure we may resize ourselves */
XtVaSetValues(toplevel, XmNallowShellResize, True, NULL);
/* create a XmHTML widget but this time enable autosizing */
XtVaCreateManagedWidget("html", xmHTMLWidgetClass, toplevel,
XmNvalue, "<html><body>An AutoSizing XmHTML widget.</body></html>",
XmNresizeWidth, True,
XmNresizeHeight, True,
NULL);
XtRealizeWidget(toplevel);
XtAppMainLoop(app);
}
</pre>
The output of this program is shown in Figure 2-3.
<p>
<img src="../Images/book/autosize_html.gif" alt="[An Autosizing HTML Widget]">
<br>
<i>Figure 2-3. autosize_html.c: an autosizing XmHTML widget</i>
<p>
When looking at Example 2-3, we notice a few things that are of interest. First
of all, there is the <tt>XmNallowShellResize</tt> resource. The value of this
resource determines whether a <tt>Shell</tt> widget (or any of its subclasses,
in this case a <tt>topLevelShellWidget</tt>) will honor geometry requests from
its children. Since we want the XmHTML widget to compute its own size, we
must set this resource to <tt>True</tt> (it is <tt>False</tt> by default).
<p>
The second and most interesting thing to notice are the
<tt>XmNresizeWidth</tt> and
<tt>XmNresizeHeight</tt> resources. These resources
control the autosizing feature of XmHTML widgets. The first enables autosizing
in horizontal direction and the latter in vertical direction. When the
<tt>XmNresizeWidth</tt> resource is set to <tt>True</tt>,
XmHTML widget's base their initial width on the width of the longest
text element in the source document, with a maximum of 80 characters.
XmHTML widget's with autosizing enabled will never cover the entire screen:
the maximum dimensions a XmHTML widget take will never exceed 80% of
the available screen dimensions.
<p>
In strong contrast with specifying the dimensions of XmHTML widget's using
the <tt>XmNwidth</tt> and <tt>XmNheight</tt> resources, autosizing is
persistent: When the user resizes a window, the dimensions of a XmHTML widget
are not affected. Autosizing remains effective as long as the autosizing
resources are set.
<p>
You should use the autosizing feature of XmHTML widget's sparingly. Dynamic
resizing of widgets is generally considered as poor design. This is especially
true of widgets in a Shell or Dialog with other elements in it.
<p>
An example of acceptable use of dynamic resizing would be when a XmHTML widget
is used in a popup dialog used for displaying small amounts of text (such as
explanation of terminology in a Hypertext Help system).
<h3><a name="dimension_by_resource"><font face="helvetica, arial">
2.1.3.2 XmHTML Widget's Dimensions and Resources
</font></a></h3>
As we will see in section 2.1.5, <a href="#children">XmHTML Children</a>, a
XmHTML widget creates three subwidgets: a DrawingArea and two scrollbars.
<p>
When a XmHTML widget is created, the size of the DrawingArea is set explicitly
by the widget itself, but it uses the Motif default values when it creates
the scrollbars. It is important that you realize this when you set the
dimensions of a XmHTML widget by means of application-wide fallback resources
or when specifying them in a resource file: if you specify the dimensions of a
XmHTML widget using resource wildcarding you can be sure to expect
unwanted behaviour whenever text is set into the widget.
<p>
The correct way to specify the widget dimensions is as follows:
<pre>
static String fallbackResources[] = {
"*XmHTML.width: 575",
"*XmHTML.height: 600",
};
</pre>
This will only set the width of the DrawingArea subwidget to 575 pixels and the
height to 600 pixels, leading to the expected behaviour.
<p>
If on the other hand you incorrectly specify the dimensions as follows:
<pre>
static String fallbackResources[] = {
"*XmHTML*width: 575",
"*XmHTML*height: 600",
};
</pre>
you are not only setting the dimensions of the DrawingArea subwidget but
also the dimensions for every subwidget created by a XmHTML widget. Needless
to say that this kind of behaviour is unwanted. The correct way to specify
the dimensions of both a XmHTML widget and its ScrollBar subwidgets is as
follows:
<pre>
static String fallbackResources[] = {
"*XmHTML.width: 575",
"*XmHTML.height: 600",
"*XmHTML*verticalScrollBar.width: 25",
"*XmHTML*horizontalScrollBar.height: 25",
};
</pre>
<p>
<font face="helvetica, arial" size="3">[Note: although it is possible to
use resource wildcarding to set the dimensions of a XmHTML widget when the
width and height of a ScrollBar are explicitly set, it is advisable that
this is never done. The problem is not limited to the dimensions of the
ScrollBars subwidgets but extends to any subwidgets a XmHTML widget creates
when it encounters a HTML document with a <FORM></FORM>
declaration in it.]
</font>
<h2><a name="scrolling"><font face="helvetica, arial">
2.1.4 Document Scrolling
</font></a></h2>
Adding document scrolling to XmHTML widget's is easy: you don't. If you look
at the output of Example 2-1 (Figure 2-1), you will notice that a vertical
scrollbar is present while we didn't instruct the XmHTML widget to add one.
When the XmHTML widget was created it noticed that it wasn't high enough to
display all of the text and thus it added a vertical scrollbar to allow the
user to view all of the text by dragging the scrollbar. If you resize the
window vertically, the vertical scrollbar will disappear when the widget is
high enough to contain all text (including the horizontal and vertical margins).
<p>
The behaviour you have observed in Example 2-1 is the default behaviour for
the XmHTML widget: when not all of the text can be fitted in the available
dimensions, a horizontal and/or vertical scrollbar is added, and when all text
can be fitted in the available dimensions, the horizontal and/or vertical
scrollbar is removed.
<p>
As there might be cases where you want the presence of a vertical scrollbar
while one is not required, you can force the presence of a vertical scrollbar
by using the <tt>XmNscrollBarDisplayPolicy</tt> resource as shown in the
following example:
<p>
<i>Example 2-4. The forced_html.c program</i><br>
<pre>
/* forced_html.c -- Force the display of the vertical scrollbar */
#include <XmHTML.h>
main(int argc, char **argv)
{
Widget toplevel;
XtAppContext app;
toplevel = XtVaAppInitialize(&app, "Demos", NULL, 0,
&argc, argv, NULL, NULL);
/* create a XmHTML widget but this time we specify a size */
XtVaCreateManagedWidget("html", xmHTMLWidgetClass, toplevel,
XmNvalue, "<html><body>A minimally configured "
"XmHTML widget.</body><html>",
XmNwidth, 200,
XmNheight, 75,
XmNscrollBarDisplayPolicy, XmSTATIC,
XmNscrollBarPlacement, XmTOP_LEFT,
XmNmarginWidth, 5,
XmNmarginHeight, 5,
NULL);
XtRealizeWidget(toplevel);
XtAppMainLoop(app);
}
</pre>
The <tt>XmNmarginWidth</tt> and <tt>XmNmarginHeight</tt> resources determine the
spacing between the outer borders of a XmHTML widget and the displayed text.
For demonstration purposes they have been set to a smaller value than the
default value of 20. If you compile and run this program you will see that a
vertical scrollbar is present and stays present when the widget is resized,
even when the widget is high enough to contain all text.
<p>
Example 2-4 also shows the <tt>XmNscrollBarPlacement</tt> resource. This
resource controls the placement of both horizontal and vertical scrollbar. In
this case the vertical scrollbar is placed on the left side of the window and
the horizontal scrollbar is placed on top of the window (making the window
smaller will show the horizontal scrollbar). Possible values for this resource
are:
<p>
<ul>
<li><tt>XmTOP_LEFT:</tt> vertical ScrollBar on left; horizontal on top;
<li><tt>XmBOTTOM_LEFT:</tt> vertical ScrollBar on left; horizontal on bottom;
<li><tt>XmTOP_RIGHT:</tt> vertical ScrollBar on right; horizontal on top;
<li><tt>XmBOTTOM_RIGHT:</tt> vertical ScrollBar on right; horizontal on bottom;
</ul>
<p>
XmHTML widget's do not provide any way to force the display of a horizontal
scrollbar, you can only control it's placement.
<h4><a name="scrolling"><font face="helvetica, arial">
Keyboard Scrolling
</font></a></h4>
XmHTML widget's implement a full keyboard navigation interface by installing a
number of translations. On most keyboards, the arrows provide the same behaviour
as dragging the scrollbars while the PageUp and PageDown keys scroll through a
document a page at a time. Additional keys are also available, see the XmHTML
Reference Manual for the complete set of translations that XmHTML widget's
install.
<h2><a name="children"><font face="helvetica, arial">
2.1.5 XmHTML Children
</font></a></h2>
A XmHTML widget is made up of a number of subwidgets: a DrawingArea widget in
which the document is displayed, and two ScrollBars. You can get the
handles to these children using the Xt <tt>XtVaGetValues()</tt> method, as
demonstrated in the following code fragment:
<pre>
Widget work_window, hsb, vsb;
XtVaGetValues(html_w,
XmNworkWindow, &work_window,
XmNhorizontalScrollBar, &hsb,
XmNverticalScrollBar, &vsb,
NULL);
</pre>
Getting XmHTML widget children can be usefull when you want to install your
own event handlers or set additional resources on these children.
<p>
Let us now demonstrate a case where it is usefull to get a handle to one of
XmHTML's children: the workWindow. Amongst the many convenience routines offered
by the XmHTML widget's is the <tt>XmHTMLXYToInfo()</tt>
function. This function takes a XmHTML widget and a pointer position as it's
arguments and returns a structure containing information about the contents of
the currently displayed document at the requested pointer position. The
structure returned is of type <tt>XmHTMLInfoStructure</tt>, which is defined as
follows:
<pre>
typedef struct
{
int line_no; /* line number at selected position */
Boolean is_map; /* true when clicked image is an imagemap */
int x,y; /* position relative to image corner */
XmImageInfo *image; /* image data */
XmHTMLAnchorPtr anchor; /* possible anchor data */
}XmHTMLInfoStructure, *XmHTMLInfoPtr;
</pre>
The <tt>XmImageInfo</tt> and <tt>XmHTMLAnchorPtr</tt> members of this structure
will be explained in the following sections, so we will now only say that the
first structure contains information about an image over which the pointer
is located, while the latter contains information about a hyperlink over which
the anchor is currently located.
<p>
A perfect way to display this information to the user would be to display
a popup menu when the user clicks on the currently displayed document. In
order for this to work, we need to attach an event handler to the workWindow
of a XmHTML widget. The following example demonstrates how to attach the event
handler to the workWindow and how to use the <tt>XmHTMLXYToInfo()</tt>
function:
<p>
<i>Example 2-5. The work_window.c program</i><br>
<pre>
/*
* work_window.c: attaching an event handler to the work_window of a XmHTML
* widget.
*/
#include <XmHTML.h>
void
attachInfoHandler(Widget html, Widget popup)
{
Widget work_window;
XtVaGetValues(html, XmNworkWindow, &work_window, NULL);
/*
* Add an event handler which responds to mouse clicks. "popup" is the
* popup menu which is to be displayed, it is stored as client_data
* for the event handler.
*/
XtAddEventHandler(work_window, ButtonPressMark, 0,
(XtEventHandler)infoHandler, popup);
}
void
infoHandler(Widget work_window, Widget popup, XButtonPressedEvent *event)
{
XmHTMLInfoPtr info;
Widget html_w;
WidgetList children;
/* we only take events generated by button 3 */
if(event->button != 3)
return;
/*
* The work_window is a child of a XmHTML widget, so we can get a handle
* to the XmHTML widget itself by using Xt's <b>XtParent</b> routine.
*/
html_w = XtParent(work_window);
/* get the info for the selected position. */
info = XmHTMLXYToInfo(html_w, event->x, event->y);
/*
* Check the returned info structure. There will be nothing to display
* if the pointer wasn't over an image or anchor when the user
* clicked his mouse.
*/
if(info == NULL || (info->image == NULL && info->anchor == NULL))
return;
/*
* For this example we assume that the popup menu has two buttons:
* a hyperlink button and an image button. We retrieve these children
* of the popup menu using the XmNchildren resource of Motif's
* rowColumn widget.
*/
XtVaGetValues(popup, XmNchildren, &children, NULL);
/* check if the info structure has an anchor */
if(info->anchor)
{
XmString label;
label = XmStringCreateLocalized(info->anchor->href);
XtVaSetValues(children[0], XmNlabelString, label, NULL);
XmStringFree(label);
XtManageChild(children[0]);
}
else
XtUnmanageChild(children[0]);
/* check if the info structure has an image */
if(info->image)
{
XmString label;
label = XmStringCreateLocalized(info->image->url);
XtVaSetValues(children[1], XmNlabelString, label, NULL);
XmStringFree(label);
XtManageChild(children[1]);
}
else
XtUnmanageChild(children[1]);
/* the "popup" menu has now been configured, pop it up */
XmMenuPosition(popup, event);
XtManageChild(popup);
}
</pre>
Note that the above example does not use any global variables; we can obtain
all handles to the widgets we need. The handle to the popup menu is
stored as client_data for the event handler, while the handles to the menu
buttons of the popup menu can be easily obtained using one of Motif's
<tt>RowColumn</tt> widget resources. It is also important to notice that it is
very easy to obtain the widget id of the XmHTML widget. The event handler was
attached to the workWindow of a XmHTML widget, and therefore this workWindow is
the same widget as the work_window argument to the infoHandler routine. This
is the reason why the <tt>XtParent(work_window)</tt> call returns the handle
of the XmHTML widget.
<p>
Also notice that we do not have to free any of the members of the returned
<tt>XmHTMLInfoStructure</tt> structure. In fact, we
are not permitted to do this since the <tt>image</tt> and <tt>anchor</tt>
members of this structure contain pointers to data owned by a XmHTML widget.
Unless it is explicitly mentioned, all structures returned by any of XmHTML
widget's resources, callback resources or convenience routines should be
considered as read only.
<p>
Example 2-5 is a simple demonstration which does not use any callbacks on
the popup menu buttons. In a real implementation however, callback resources
could be attached to each of the popup menu buttons which would allow the user
to jump to the selected hyperlink or display information about the selected
image.
<p>
<font face="helvetica, arial" size="3">[Note: if you want to specify
resource values for the subwidgets mentioned in this chapter by means of
application fallback resources or in a resource file, the following names
should be used: workWindow for the DrawingArea child, verticalScrollBar for
the vertical ScrollBar child and horizontalScrollBar for the horizontal
ScrollBar child.]
</font>
<h1><a name="appearance"><font face="helvetica, arial">
2.2 Modifying the Document Appearance
</font></a></h1>
A HTML document typically contains a number of hyperlinks. Hyperlinks (also
referred to as <i>anchors</i>) are often used in HTML documents to allow the
reader to navigate the currently displayed document or between different
documents. In order for the reader to recognize these anchors they should
appear different from the main content of a HTML document. XmHTML widget's
provide a number of resources that control the appearance of these anchors.
<p>
Another set of resources allow you to control the fonts that are used to render
the displayed text.
<h2><a name="anchor"><font face="helvetica, arial">
2.2.1 Changing the Anchor Appearance
</font></a></h2>
XmHTML widget's identify three different types of anchors: a regular anchor,
a visited anchor and an anchor which has the <tt>target</tt> attribute set.
The latter is a special type of anchor and is one of the extensions to the
HTML 3.2 standard that are implemented by XmHTML. Typical use of this
attribute can be found in HTML documents that utilize the HTML
<tt><FRAMESET></tt> extension, where this attribute indicates a
destination to which the contents of the activated anchor
should be sent. This destination can target (amongst others) another XmHTML
widget or a new dialog. Other use of this attribute can be found in Hypertext
help systems where it might be used to indicate that the contents of the
activated anchor should be displayed in a popup window.
<p>
A visited anchor is an anchor that the reader of the document has selected in
the past.
<p>
Each anchor has three states: <i>passive</i>, <i>armed</i> and
<i>activated</i>. An anchor is considered armed when a user has located
the mouse pointer over an anchor. It is active when the user presses the first
or second mouse button on an armed anchor. It is considered passive otherwise.
<p>
XmHTML widget's provide four ways to let an anchor stand out:
<p>
<ul>
<li>by changing the cursor when an anchor is armed;
<li>by actively changing the look of an anchor when it is armed;
<li>by rendering the anchor as a pushbutton;
<li>by underlining the anchor;
</ul>
<p>
The first and second item in this list are always selectable, while the
third and fourth item are mutually exclusive: you choose either to display the
anchors as pushbuttons or to underline them. The latter offers the most
control on anchor appearance, while some users may find pushbutton anchors
aesthetically more pleasing (although it can be slightly more difficult to
identify anchors).
Both types allow you to control the color in which the anchor is displayed in
both it's passive and activated state.
<p>
XmHTML widget's will display anchors as pushbuttons by default: the default
value of the <tt>XmNanchorButtons</tt> resource is <tt>True</tt>. By setting
this resource to False, anchors will be underlined instead of being displayed
as a pushbutton.
<h3><a name="anchor_cursor"><font face="helvetica, arial">
2.2.1.1 Anchor Cursor Resources
</font></a></h3>
To indicate that an anchor can be activated by the user, it is often convenient
to not only render the anchor differently than the remainder of the document
but also to change the cursor when the pointer is moved over an anchor.
<p>
XmHTML widget's will change the cursor to a hand with a pointing finger when
the user moves the pointer over an anchor. The default cursor is a built-in
cursor, but it can be changed to a different cursor by using the
<tt>XmNanchorCursor</tt> resource. Although it will seldomly be needed, the
<tt>XmNanchorDisplayCursor</tt> resource allows you to control whether or not
XmHTML widget's should change the cursor when the pointer is moved over an
anchor (it is <tt>True</tt> by default).
<p>
The following code fragment demonstrates how to create, set and destroy a
cursor:
<pre>
#include <X11/cursorfont.h> /* standard X cursors */
#include <XmHTML.h>
void
setCursor(Widget html_w, Boolean destroy_cursor)
{
static Cursor cursor;
/* create a standard X cursor when it is not yet created */
if(cursor == None)
cursor = XCreateFontCursor(XtDisplay(html_w), XC_hand2);
if(destroy_cursor)
{
/* only free the cursor when we have created one */
if(cursor != None)
XFreeCursor(XtDisplay(html_w), cursor);
cursor = None;
}
else /* set this cursor as the anchor cursor for this XmHTML widget */
XtVaSetValues(html_w,
XmNanchorCursor, cursor,
XmNanchorDisplayCursor, True,
NULL);
}
</pre>
The <tt>cursor</tt> is created using <tt>XCreateFontCursor()</tt>, but this is
not required; you may use other functions like <tt>XCreateGlyphCursor()</tt>
or <tt>XCreatePixmapCursor()</tt>,
if you like. See O'Reilly's X Window System Programming guides Volume One,
<i>Xlib Programmer's Manual</i>, for more information.
<p>
It is also considered nice programming to use X resources sparingly (although
in the case of cursor's it is not really required, they are a virtually
unlimited resource under X). This is why the above fragment declares the
allocated cursor as a static variable: once allocated the cursor id is always
available and we can use it for every XmHTML widget that is provided as an
argument to the above routine. When this routine is called with the
<tt>destroy_cursor</tt> argument set to True the cursor is destroyed and reset.
<h3><a name="anchor_display"><font face="helvetica, arial">
2.2.1.2 Anchor Display Resources
</font></a></h3>
Whether or not you select to display anchors as pushbuttons or to underline
them, you can always specify the foreground color in which an anchor is
rendered. You can specify a different foreground color for the passive state of
each of the anchor types mentioned in the introduction to this section:
<p>
<ul>
<li><tt>XmNanchorForeground</tt>:<br>
specifies the foreground color that is to be used to render a regular
anchor;
<li><tt>XmNanchorVisitedForeground</tt>:<br>
specifies the foreground color that is to be used to render a visited
anchor;
<li><tt>XmNanchorTargetForeground</tt>:<br>
specifies the foreground color that is to be used to render an anchor
that has the <b>target</b> attribute set;
</ul>
<p>
The <tt>XmNanchorActivatedForeground</tt> resource
identifies the foreground color to be used when an anchor is activated.
This resource is the same for all three anchor types.
<p>
When you opt to underline the anchors, you can also use the
<tt>XmNanchorActivatedBackground</tt> resource to
specify the background color to use when an anchor is activated.
<p>
<font face="helvetica, arial" size="3">[Note: When a HTML document contains
a background image and displaying of background images is enabled (which is
true by default), the <b>XmNanchorActivatedBackground</b> resource is also
ignored when anchors are to be underlined, making the anchors appear as being
transparent.]</font>
<p>
You need to specify a <i>Pixel</i> for all three resources. You can specify
a Pixel value by pre-allocating a pixel (by using any of Xlib's
<tt>XAllocColor()</tt> routines) or by using Xt's <tt>XtVaTypedArg</tt> method.
Both methods have their pro's and con's, but in either case you must free
the allocated color values when your application exits.
<p>
When you have set the <tt>XmNanchorButtons</tt> resource to <tt>False</tt>,
you can also specify the type of underlining for each of the three anchor
types. XmHTML widget's support the following types of underlining:
<p>
<ul>
<li><tt>XmNO_LINE:</tt><br>
no lines are drawn;
<li><tt>XmSINGLE_LINE:</tt><br>
a single solid line. This is the default for regular and visited anchors;
<li><tt>XmDOUBLE_LINE:</tt><br>
a double solid line. This is the default for anchors that have the
<tt>target</tt> attribute set;
<li><tt>XmSINGLE_DASHED_LINE:</tt><br>
a single dashed line;
<li><tt>XmDOUBLE_DASHED_LINE:</tt><br>
a double dashed line;
</ul>
<p>
The resource names are as follows:
<p>
<ul>
<li><tt>XmNanchorUnderlineType</tt>:<br>
specifies the type of underlining to use for regular anchors;
<li><tt>XmNanchorVisitedUnderlineType</tt>:<br>
specifies the type of underlining to use for visited anchors;
<li><tt>XmNanchorTargetUnderlineType</tt>:<br>
specifies the type of underlining to use for anchors
that have the <tt>target</tt> attribute set;
</ul>
<p>
Finally, there is the <tt>XmNhighlightOnEnter</tt> resource. When set to
<tt>True</tt> (which is the default), a XmHTML widget will actively modify
the look of an anchor whenever it becomes armed by <i>highlighting</i>
the anchor. The actual color and type of highlighting used heavily depends on
the content of the document that is currently displayed. When a background
image is present, a XmHTML widget will base the highlight color on the value
of the <tt>XmNanchorActivatedForeground</tt> resource and render the
anchor's text in the computed color. When no background image is present, the
highlight color will be based on the current document background and the
anchor's text will be rendered in a rectangle filled with the computed
color. If you decide to enable this resource, it is adviced that you offer
a possibility to the user to toggle the value of this resource: a XmHTML widget
attempts to do it's best when computing the highlight color, but might fail
to find a suitable color. This can happen, for instance, on documents where
the colors used by the background (fixed color or background image), text
and anchors are poorly balanced.
<h2><a name="anchor_visited"><font face="helvetica, arial">
2.2.2 Marking a Visited Anchor
</font></a></h2>
You now know that XmHTML widget's contain the concept of <i>visited anchors</i>,
which are anchors that the reader of the document has selected in the past
(e.g, have already been visited). But when the user of your application is
switching between documents the following question arises: how do you inform a
XmHTML widget that an anchor was previously visited by the user?
<p>
The answer is fairly simple: you use the
<tt>XmNanchorVisitedProc</tt> resource. When a
procedure has been installed for this resource, a XmHTML widget will call this
procedure to test if an anchor has already been visited. There are two
arguments to this procedure: the widget id of a XmHTML widget and the name of
the anchor. It should return <tt>True</tt> when the anchor should be rendered
using the <tt>XmNanchorVisitedForeground</tt> resource and <tt>False</tt> when
it should be rendered as a regular anchor.
<p>
Please note that a XmHTML widget only calls any installed procedure when a
document is set into a XmHTML widget, and that it will be called for every
anchor that is found in this document.
<p>
The following example shows how easy it can be to use this resource:
<pre>
#include <XmHTML.h>
static int num_visited_anchors;
String visited_anchors[100];
static Boolean
visitedTestProc(Widget html_w, String anchor)
{
int i;
for(i = 0; i < num_visited_anchors; i++)
if(!strcasecmp(visited_anchors[i], anchor))
return(True);
return(False);
}
int
main(int argc, char **argv)
{
Widget toplevel;
XtAppContext app;
toplevel = XtVaAppInitialize(&app, "Demos", NULL, 0,
&argc, argv, NULL, NULL);
XtVaCreateManagedWidget("html", xmHTMLWidgetClass, toplevel,
XmNanchorVisitedProc, visitedTestProc,
NULL);
XtRealizeWidget(toplevel);
XtAppMainLoop(app);
}
</pre>
In this example we assume that text can be set in the XmHTML widget,
<tt>visited_anchors</tt> contains a list of already visited anchors and that
<tt>num_visited_anchors</tt> contains the number of items in the visited anchor
list. In section 2.5 we will demonstrate how to maintain this list.
<p>
<h2><a name="fonts"><font face="helvetica, arial">
2.2.3 Specifying the Document Fonts
</font></a></h2>
One of the most important (if not the most important) aspect that will
determine the way a document will look to the user concerns the fonts used to
render the text in a document. Selecting an appropriate default font (and its
size) is a very important decision when using a XmHTML widget, and it is more
difficult than it might seem, especially if you want to internationalize your
application.
<p>
Font specification for a XmHTML widget does not follow the standard Motif font
specification rules (the <tt>XmFontList</tt> type). Due to the nature of the
HTML language this would be rather impossible; it does not only contain font
markup elements that allow the writer of a HTML document to change the style
of a font, but also to change the typeface and size of a font. To make things
even more complicated, all of these font markup elements can be used in
arbitrary sequence.
<p>
In order to cope efficiently with this virtually unlimited number of font
combinations in HTML documents, XmHTML widget's allocate their fonts directly
and employ a smart font caching scheme that will keep the number of required
font allocations to an absolute minimum. The font cache is shared by all
XmHTML widget's on a per display basis (which effectively means that you
can use a XmHTML widget for a multi-display application).
<p>
Another reason why XmHTML widget's do not use the Motif font specification
rules is that the XmHTML font allocation routines go thru great lengths to
ensure that a requested font is matched. When a requested font can not be
exactly matched, the font allocation routines attempt to find a close match
by following a number of different paths instead of giving up immediatly and
using a default font. XmHTML widget's produce much better looking text than
some of the most well known HTML browsers as a result of this.
<p>
Because XmHTML widget's allocate their fonts themselves instead of relying on
Motif, a number of resources are offered that allow you, the programmer, to
select a character set, foundry, typeface, spacing and size of the fonts that
are to be used for displaying a document.
<p>
<font face="helvetica, arial" size="3">[Note: In order to fully appreciate the
font resources of XmHTML widget's you are encouraged to read Appendix A of
O'Reilly's X Window System Programming guides, Volume One,
<i>Xlib Programmer's Manual</i>.]</font>
<p>
Before explaining the various font resources I will mention that a XmHTML
widget uses the contents of the font resources to compose a X Logical Font
Description (XLFD) which is used to query your X server. Knowing this, it
is obvious that you are allowed to use wildcards for all font resources
(except size of course). This can be potentially dangerous: depending on the
configuration of your font path and directories, the font returned by the X
server may or may not be what is intended.
<p>
As a final note in this fairly long introduction, the default values for
each of the various font resources have been choosen in such a way that every
combination represents a font that is present in the default font path of
the standard R5 X distribution.
<h3><a name="fonts_charset"><font face="helvetica, arial">
2.2.3.1 Specifying the Character Set
</font></a></h3>
The character set resource, <tt>XmNcharset</tt>,
is a string representing the ISO character set encoding to be used. The
default character set used by XmHTML widget's, <tt>ISO8859-1</tt>, represents
the ISO Latin-1 character set (which is used by all of the fonts in the
<i>75dpi</i> and <i>100dpi</i> directories of X's default font path). This
character set is a superset of the standard ASCII character set, which includes
various special characters used in European languages other than English.
<p>
The <tt>XmNcharset</tt> resource makes it relatively
easy to select a font for non-European (non-English) languages. For example,
<tt>"XmNcharset: koi8-*"</tt> specifies the koi8
Cyrillic font, while <tt>"XmNcharset: UJIS-*"</tt>
identifies a Japanese font.
<p>
It is also important to notice that this resource is very important, if not
the most important font resource. If a charset is specified which is
unknown to the X server (or the charset is given as a wildcard), a XmHTML
widget has almost no control about the fonts to use: the actual charset that
is used will then only depend on the fontpath configuration of the X server and
the specified font family. Therefore it is considered wise to first verify
if the requested character set is available on the system your application
is running on before changing it. See also section
<a href="#fonts_family">2.2.3.2</a>, Specifying the Font Family.
<p>
The font allocation scheme used by XmHTML will first try to load a font for
a given character set and font family. When that fails it will wildcard the
charset. This causes a XmHTML Widget to honor the following sequence of HTML
tags with the default charset:
<p>
<tt> <FONT FACE="symbol">alpha</FONT></tt>
<p>
which is rendered as:
<p>
<tt> </tt><font face="symbol">alpha</font>
<p>
<font face="helvetica, arial" size="3">[Note: this will render the word alpha
in the symbol font if it is installed on your X server, and in english if you
are viewing this document with almost any other browser or haven't got the
symbol font installed.]</font>
<h3><a name="fonts_family"><font face="helvetica, arial">
2.2.3.2 Specifying the Font Family
</font></a></h3>
XmHTML widget's use two different types of font: a proportional font and a
fixed-width font. Proportional fonts are fonts in which each character in a
character set has a different width (an example of a proportional font is Times
Roman), while fonts in which each character has the same width are called
fixed-width fonts. Proportional fonts are more easy for the human eye to read
than fixed-width fonts and therefore the main portion of the text in a HTML
document is rendered in a proportional font. Fixed-width fonts are used to
display preformatted text in a HTML document.
<p>
You specify the proportional font family by using the
<tt>XmNfontFamily</tt> resource,
and the fixed-width font family by using the
<tt>XmNfontFamilyFixed</tt> resource.
The value for both these resources is a sequence of four dash-seperated
strings that define a font family. These four fields are:
<p>
<ol>
<li>foundry: the type foundry that digitized and supplied the font, i.e.
Adobe;
<li>family: the font family name (also known as typeface), i.e. roman;
<li>set width: a value describing a font's proportionate width according
to the selected foundry, i.e. normal;
<li>spacing: type of character spacing for a font. m (for monospace, i.e.
fixed width) or p (proportional, i.e., variable-width) are two well
known font spacings.
</ol>
<p>
The default value for the <tt>XmNfontFamily</tt>
resource is <tt>adobe-times-normal-*</tt>, and the
default value for the <tt>XmNfontFamilyFixed</tt>
resource is <tt>adobe-courier-normal-*</tt>.
Both font families represent a standard, scalable font, present on each
X server.
<p>
You should always try to specify a scalable font whenever possible: HTML
documents intend to use a lot of differently sized fonts (the header markup
elements for example all require a different font size), and the displayed
text will generally look much better if a scalable font is used instead of a
bitmapped font.
<p>
A note of caution: before changing any of the <tt>fontFamily</tt> resources,
the existence of this font (within the context of the current or new value of
the <tt>XmNcharset</tt> resource) should be verified before actually changing
it. An unsuccesfull attempt to change the default font settings <b>can</b>
cause a XmHTML widget to exit your application: if it can not find a default
font it simply can not display anything.
<h3><a name="fonts_sizes"><font face="helvetica, arial">
2.2.3.3 Specifying the Font Sizes
</font></a></h3>
The last step in specifying the document fonts is to specify the font sizes
for both the proportional and fixed-width font families. Font sizes are
always specified in <i>points</i> and not in pixels: specifying a font
size in pixels would require you to know in advance the x- and y-resolution of
the screen your application is running on. The XmHTML widget determines the
screen resolution and selects an appropriate pixel size automatically.
<p>
You can specify the text font size, the sup- and superscript font size and the
font size for each of the header markup elements for the proportional font
family. For the fixed-width font family you can specify the text font size and
sup- and superscript size.
<p>
The sizes for the proportional font family are given by the
<tt>XmNfontSizeList</tt> resource. The value for this resource is a comma
seperated list of eight strings. The list below describes the fields in this
resource.
<p>
<ol>
<li>normal text size;
<li>sub and superscript font size;
<li>font size for the <H1> markup element;
<li>font size for the <H2> markup element;
<li>font size for the <H3> markup element;
<li>font size for the <H4> markup element;
<li>font size for the <H5> markup element;
<li>font size for the <H6> markup element;
</ol>
<p>
The default value for this resource is
<tt>"14,8,24,18,14,12,10,8"</tt>.
<p>
You do not have to specify all values; when an element in this list has the
value 0 (zero), the appropriate default font size is used.
<p>
The sizes for the fixed-width font family are given by the
<tt>XmNfontSizeFixedList</tt> resource. The value for
this resource is a comma seperated list of two strings, where the first
value describes the normal text size and the second value the size for sup- and
superscript text. The default value for this resource is <tt>"12,8"</tt>.
<h1><a name="images"><font face="helvetica, arial">
2.3 XmHTML and Images
</font></a></h1>
One of the strong and much admired features of the XmHTML Widget is it's
built in image support. A XmHTML widget can support a wide range of different
image types (from simple X11 bitmaps through complex GIF animations to full
32bit RGB PNG images with an alpha channel). For simple applications one
does not need to know anything about this image support as a XmHTML widget
can handle almost everything by itself. In fact, you only need to read
this section if you want to exploit XmHTML's image support to it's fullest.
<h2><a name="images_info"><font face="helvetica, arial">
2.3.1 The XmImageInfo Structure
</font></a></h2>
The basis of XmHTML's image API is formed by the XmImageInfo structure.
XmHTML uses this structure to compose the actual image.
<pre>
typedef struct _XmImageInfo
{
/* regular image fields */
String url; /* original location of image */
unsigned char *data; /* raw image data. ZPixmap format */
unsigned char *clip; /* raw clipmask data. XYBitmap format */
Dimension width; /* used image width, in pixels */
Dimension height; /* used image height, in pixels */
int *reds; /* red image pixels */
int *greens; /* green image pixels */
int *blues; /* blue image pixels */
unsigned int ncolors; /* Number of colors in the image */
int bg; /* transparent pixel index */
unsigned char *rgba; /* image data in rgba format */
float fg_gamma; /* image gamma */
unsigned int options; /* image option bits */
/* Additional animation data */
int x; /* logical screen x-position for a frame */
int y; /* logical screen y-position for a frame */
int loop_count; /* animation loop count */
unsigned char dispose; /* image disposal method */
int timeout; /* frame refreshment in milliseconds */
int nframes; /* no of animation frames remaining */
struct _XmImageInfo *frame; /* ptr to next animation frame */
/* image classification fields and original data */
unsigned char type; /* image type, see below */
int depth; /* bits per pixel for this image */
unsigned char colorspace; /* colorspace for this image */
unsigned char transparency; /* transparency type for this image */
Dimension swidth; /* image width as read from image */
Dimension sheight; /* image height as read from image */
unsigned int scolors; /* Original number of colors in the image */
XtPointer user_data; /* any data to be stored with this image */
}XmImageInfo, *XmImageInfoStruct;
</pre>
The first part of this structure contains the raw image data XmHTML
requires to create an image. The second part is used for creating animations
while the third part provides additional information about the image
represented by this structure.
<p>
As will be shown in the following sections of this chapter, all of the
convenience functions of a XmHTML widget that deal with images work with this
structure, either as an argument or as a return value.
<p>
<h3><a name="image_info_explained"><font face="helvetica, arial">
2.3.1.1 The XmImageInfo Structure Explained
</font></a></h3>
Although this section is mostly intended for those that want to add support
for an image type that is unknown to XmHTML, it also contains important
information for those that want to enable what is known as
<a href="#advanced_images_delayed">delayed image loading</a> or want to exploit
XmHTML's built-in image support to its fullest extent. It explains every field
in the XmImageInfo structure, what each field should contain and the default
values assumed when an image is loaded using the
<a href="#images_proc">XmHTMLImageDefaultProc</a>.
<p>
<dl>
<dt><tt>url</tt>
<dd>This field represents the original location from where the image in
question should be or has been obtained. It is actually the contents of
the <tt>SRC</tt> attribute of the <tt><IMG></tt> tag.
It is important that this field always contains a value,
especially if you want to switch on delayed image loading.
<p>
<dt><tt>data</tt>
<dd>This field represents the actual image data in ZPixmap format. It is a
continuous stream of bytes in which each byte represents an index in the
colormap for this image (as defined by the <i>reds, greens</i> and
<i>blues</i> fields).
<p>
<dt><tt>clip</tt>
<dd>This field represents a <i>bitmap</i> (a pixmap with depth 1) which a
XmHTML widget will use to create a clipmask. It is a continuous stream
of <b>bits</b>, where each bit defines if the underlying pixel should
be rendered (bit set to 1) or should be left as it is (bit set to 0).
It is only valid for transparent images, although it is very well
possible to use this field for defining non-rectangular pixmaps.
The dimensions of this bitmap should equal the actual image dimensions.
<p>
<dt><tt>width</tt> and <tt>height</tt>
<dd>These fields contain the absolute dimensions of the final pixmap as given
by the <tt>data</tt> field. They are specified in pixel units, and their
product <b>must</b> match the size of the <tt>data</tt> field.
<p>
<dt><tt>reds, greens, blues</tt> and <tt>ncolors</tt>
<dd>Each of these fields is an array of color component values which together
form the RGB colormap of the image. Each array must have the same
size, and this size is given by the value of <tt>ncolors</tt>. This number
must be equal the the number of colors used by the image. A XmHTML widget
uses these arrays to allocate the actual image colors and then maps the
image data onto these colors.
<p>
<dt><tt>bg</tt>
<dd>The index of the transparent pixel, or <tt>-1</tt> when the image is
fully opaque.
<p>
<dt><tt>rgba</tt>
<dd>This field is only used for images containing an alpha channel.
An alpha channel is a series of pixel values in an image used to compute
partial pixel transparency. With partial pixel transparency fade in/out or
anti-aliasing effects can be achieved regardless of the current background
setting. The XmHTMLImageDefaultProc supports alpha channelled PNG images.
The format of the data stored in this field is a continuous stream of
bytes where each pixel is represented by its red, green, blue and
alpha channel component.
<p>
<dt><tt>fg_gamma</tt>
<dd>This field contains the gamma value of the display on which the image
was created. It is only used in combination with alpha channelled images.
<p>
<dt><tt>options</tt>
<dd>This field contains a combination of OR'd constants which tell
a XmHTML Widget what it can and can't do with an <tt>XmImageInfo</tt>
structure. A number of these constants define how and when a XmHTML
should free a structure (or members of it), while others determine
what type of operations are allowed and how the actual image should
be processed.
<p>
"Set by default" indicates a bit set when the
XmHTMLImageDefaultProc was used to read an image.
<p>
<dl>
<dt><tt>XmIMAGE_DELAYED</tt>
<dd>When set, XmHTML will ignore all fields except <tt>url</tt> and use
a default image instead. This default image can be updated at a later
stage using either the
<a href="images.html#XmHTMLImageReplace">XmHTMLImageReplace</a> or
<a href="images.html#XmHTMLImageUpdate">XmHTMLImageUpdate</a>
convenience function;
See the section on <a href="#advanced_images_delayed">Delayed Image
Loading</a> for more information.
<p>
<dt><tt>XmIMAGE_DEFERRED_FREE</tt>
<dd>When set, XmHTML will take care of destroying this structure when
a new document is loaded. Set by default;
<p>
<dt><tt>XmIMAGE_IMMEDIATE_FREE</tt>
<dd>When set, this structure will be destroyed as soon as XmHTML no longer
needs it;
<p>
<dt><tt>XmIMAGE_RGB_SINGLE</tt>
<dd>set this bit when the <tt>reds, greens</tt> and <tt>blues</tt> fields
have been allocated with one single malloc instead of three separate.
Set by default;
<p>
<dt><tt>XmIMAGE_ALLOW_SCALE</tt>
<dd>set this bit when scaling an image is allowed. Set by default;
<p>
<dt><tt>XmIMAGE_FRAME_IGNORE</tt>
<dd>use with animations: set this bit when a frame falls outside the
logical screen area. No pixmap is created but the timeout for the
frame is kept.
<p>
<dt><tt>XmIMAGE_CLIPMASK</tt>
<dd>This bit is set when the returned <tt>XmImageInfo</tt> structure
contains clipmask data. XmHTML uses this info to create a clipping
bitmap. Changing this bit from set to unset will lead to a memory leak
while changing it from unset to set without providing a clipmask
yourself will cause an error to happen. You can however set this bit
when you are providing your own clipmask (to provide non-rectangular
images for example), provided you fill the "clip" field
with valid bitmap data.
<p>
<dt><tt>XmIMAGE_SHARED_DATA</tt>
<dd>This bit is set when images share data. XmHTML sets this bit when the
image in question is an internal image, e.i., one for which the image
data may never be freed. Be carefull setting this bit yourself, since
it prevents XmHTML from freeing the image data present in the
XmImageInfo structure. It can easily lead to memory leaks when an
image is not an internal image.
<p>
<dt><tt>XmIMAGE_PROGRESSIVE</tt>
<dd>Setting this bit will enable progressive image loading. A function
must have been installed on the <tt>XmNprogressiveReadProc</tt>
resource prior to setting this bit. Installing a function on the
<tt>XmNprogressiveEndProc</tt> is optional but strongly advised. When
this bit is set all other bits and all members except the <tt>url</tt>
field of the <tt>XmImageInfo</tt> structure will be ignored.
<p>
<dt><tt>XmIMAGE_DELAYED_CREATION</tt>
<dd>This bit is read-only. It is used internally by XmHTML for images with
an alpha channel. Alpha channel processing merges the current
background with the original RGBA data (see above) from the image and
uses the result to compose the actual on-screen image (the merged data
is stored in the "data" field of the <tt>XmImageInfo</tt>
structure). XmHTML needs to store the original data somewhere, and
when this bit is set it is stored in the "rgba" field of the
<tt>XmImageInfo</tt> structure. When this bit is set, the returned
structure may not be freed as long as the current document is alive.
You can discard it as soon as a new document is loaded.
</dl>
<p>
<dt><tt>type</tt>
<dd>This field contains a value which describes the type of image that is
represented by this structure. This field is unused internally and is
provided for your convenience only. You should consider this value
read-only though as it might well be used in the future. Table 2-1 lists
all possible values for this field.
<p>
<center>
<table cols="2" border="1">
<caption>Table 2-1. Supported Image Types</caption>
<tr valign="top" halign="left">
<th>Type
<th>Image description
<tr valign="top" halign="left">
<td>IMAGE_ERROR
<td>error on image loading
<tr valign="top" halign="left">
<td>IMAGE_UNKNOWN
<td>unknown image
<tr valign="top" halign="left">
<td>IMAGE_XPM
<td>X11 pixmap
<tr valign="top" halign="left">
<td>IMAGE_XBM
<td>X11 bitmap
<tr valign="top" halign="left">
<td>IMAGE_GIF
<td>CompuServe(C) Gif87a or Gif89a
<tr valign="top" halign="left">
<td>IMAGE_GIFANIM
<td>animated gif
<tr valign="top" halign="left">
<td>IMAGE_GIFANIMLOOP
<td>animated gif with NETSCAPE2.0 loop extension
<tr valign="top" halign="left">
<td>IMAGE_GZF
<td>compatible Gif87a or Gif89a
<tr valign="top" halign="left">
<td>IMAGE_GZFANIM
<td>compatible animated gif
<tr valign="top" halign="left">
<td>IMAGE_GZFANIMLOOP
<td>compatible animated gif with NETSCAPE2.0 loop extension
<tr valign="top" halign="left">
<td>IMAGE_JPEG
<td>JPEG image
<tr valign="top" halign="left">
<td>IMAGE_PNG
<td>PNG image
<tr>
</table>
</center>
<p>
</dl>
<h2><a name="images_proc"><font face="helvetica, arial">
2.3.2 The XmHTMLDefaultImageProc
</font></a></h2>
<h2><a name="images_anim"><font face="helvetica, arial">
2.3.3 Animations
</font></a></h2>
<h2><a name="images_maps"><font face="helvetica, arial">
2.3.4 XmHTML's Imagemap Support
</font></a></h2>
<h1><a name="callbacks"><font face="helvetica, arial">
2.4 XmHTML Widget Callback Functions
</font></a></h1>
<h2><a name="anchorCB"><font face="helvetica, arial">
2.4.1 Anchor Activation Callback
</font></a></h2>
<h2><a name="trackCB"><font face="helvetica, arial">
2.4.2 Anchor Tracking Callback
</font></a></h2>
<h2><a name="frameCB"><font face="helvetica, arial">
2.4.3 Frame Notification Callback
</font></a></h2>
<h2><a name="formCB"><font face="helvetica, arial">
2.4.4 Form Activation Callback
</font></a></h2>
<h2><a name="imageCB"><font face="helvetica, arial">
2.4.5 Imagemap Activation Callback
</font></a></h2>
<h2><a name="docCB"><font face="helvetica, arial">
2.4.6 Document Verification Callback
</font></a></h2>
<h2><a name="linkCB"><font face="helvetica, arial">
2.4.7 Document Link Callback
</font></a></h2>
<h2><a name="motionCB"><font face="helvetica, arial">
2.4.8 Document Motion Callback
</font></a></h2>
<h2><a name="armCB"><font face="helvetica, arial">
2.4.9 Document Arm Callback
</font></a></h2>
<h2><a name="inputCB"><font face="helvetica, arial">
2.4.10 Document Input Callback
</font></a></h2>
<h1><a name="collective_example"><font face="helvetica, arial">
2.5 Collective Example
</font></a></h1>
<h1><a name="advanced"><font face="helvetica, arial">
2.6 Advanced XmHTML Programming Techniques
</font></a></h1>
<h2><a name="advanced_frame"><font face="helvetica, arial">
2.6.1 Adding Support for HTML Frames
</font></a></h2>
<h2><a name="advanced_images_delayed"><font face="helvetica,arial">
2.6.2 Delayed Image Loading
</font></a></h2>
When a document is loaded into a XmHTML widget, it might not always be possible
to provide an image when the XmHTML widget encounters one in the document: a
net connection might be slow or the image requested can be that large that
loading it can take quite a long time. It can be quite annoying if XmHTML
should block until the image is available. Therefore, XmHTML offers Delayed
Image Loading. Delayed Image Loading fools XmHTML into thinking that it has the
image it wants, so it will happily continue without a noticable slowdown, and
display the document once it has been parsed and formatted.
<p>
Now, how does it work? Basically it is quite simple: when a XmHTML widget
finds a <IMG> tag, it will call the function that has been installed for
the XmNimageProc resource function (say, <a href="#imageProc">imageProc</a>).
<p>
The XmNimageProc function should then initialise a blank
<a href="#images_info">XmImageInfo</a> structure, fill in the <i>url</i> field
and set the <i>XmIMAGE_DELAYED</i> bit (this last step is imperative). It
should then call a function which requests an image from a remote server and
return the new XmImageInfo to XmHTML. The image is retrieved asynchronously.
<p>
At some point in the future, the image has been retrieved by the network layer,
and the application calls a routine (say
<a href="#replaceImage">replaceImage</a>) which will replace the blank image in
the XmImageInfo structure with the newly loaded one.
<p>
XmHTML widget's provide two functions for replacing or updating a delayed
image: XmHTMLImageReplace and XmHTMLImageUpdate. The difference between these
two functions is that the former will actually replace the given XmImageInfo
structure with a new one while the latter will only update the given image.
<p>
The above will probably make more sense in an example, so here is one.
<p>
<i>Example 2-?: Delayed Image Loading</i><br> <a name="imageProc"></a>
<pre>
#include <XmHTML.h>
XmImageInfo *imageProc(Widget w, String url)
{
String filename;
static XmImageInfo *image;
image = NULL;
/* test delayed image loading */
if((filename = resolveFile(url)) != NULL)
{
image = XmHTMLImageDefaultProc(html, filename, NULL, 0);
image_cache[current_image].image = image;
image_cache[current_image++].name = strdup(filename);
}
else
{
image = (XmImageInfo*)malloc(sizeof(XmImageInfo));
memset(image, 0, sizeof(XmImageInfo));
image->options = XmIMAGE_DELAYED; /* Tell XmHTML this image is delayed */
image->url = strdup(url);
/* associate the new XmImageInfo with this url */
image_cache[current_image].image = image;
image_cache[current_image++].name = strdup(url);
fetchFileFromServer(url);
}
return(image);
}
</pre>
In the above example, it is first tested if the requested image is already
available. When it is, XmHTMLImageDefaultProc is called to load the image, and
it's return value is stored in an image cache.
<p>
When the requested image is not available on the other hand, a blank
XmImageInfo structure is initialized and stored, the delayed bit is set
and a function is called which will fetch the image asynchronously from
a server. The blank XmImageInfo structure is then returned and XmHTML
will continue where it left off. When the image has been received, the
application calls the replaceImage function.
<p>
<i>Example 2-?: Updating delayed images</i><br> <a name="replaceImage"></a>
<pre>
#include <XmHTML.h>
void replaceImage(String url, unsigned char *buf, int len)
{
int i;
XmImageInfo *image;
for(i = 0; i < image_cache_size; i++)
{
if(!(strcmp(image_cache[i].name, url)))
{
image = XmHTMLImageDefaultProc(html, url, buf, len);
XmHTMLImageReplace(html, image_cache[i].image, image);
image_cache[i].image = image;
}
}
}
</pre>
As already explained in this section, the replaceImage function is called
when an image has been retrieved from a server. Contents of the image from
location <i>url</i> have been placed in the buffer <i>buf</i> with size
<i>len</i>.
<p>
Remember that we have already associated a XmImageInfo structure with a url
in the imageProc function, so the first thing we do is get the correct
XmImageInfo. When we have found the correct entry, we simply call
XmHTMLImageDefaultProc to actually load the image, replace the image
represented by our old XmImageInfo structure and update the image cache.
<p>
In a real world implementation the previous XmImageInfo structure would also
be freed. It would also call the XmHTMLRedisplay function after all images
have been loaded to force XmHTML to do a recalculation of it's screen layout.
<h2><a name="advanced_images_other"><font face="helvetica, arial">
2.6.3 Adding Support for Other Imagetypes
</font></a></h2>
<h2><a name="advanced_images_misc"><font face="helvetica, arial">
2.6.4 Using XmHTML's Image Support for Other Purposes
</font></a></h2>
One of the many nice features in a XmHTML widget is the built-in image support.
What is even nicer is that this image support is also available for purposes
other than use with a XmHTML widget: the XmHTML widget set contains a number of
routines that allow you to read an image of any of the supported image types.
You can then use the returned <b>XmImage</b> to your own likings. This section
explains the XmImage image datatype and describes how to create, destroy and
use such images.
<h3><a name="advanced_images_xmimage"><font face="helvetica, arial">
2.6.4.1 The XmImage Structure
</font></a></h3>
The basis of the external image support of the XmHTML widget set is formed
by the <b>XmImage</b> structure. This structure is defined as follows:
<pre>
typedef struct{
/* regular image data */
String file; /* originating file */
unsigned char type; /* image type */
Pixmap pixmap; /* actual image */
Pixmap clip; /* for transparant pixmaps */
int width; /* image width */
int height; /* image height */
/* animation data */
XmImageFrame *frames; /* array of animation frames */
int nframes; /* no of frames following */
int current_frame; /* current frame count */
int current_loop; /* current loop count */
int loop_count; /* maximum loop count */
XtIntervalId proc_id; /* timer id for animations */
Widget w; /* image owner */
XtAppContext context; /* Application context for animations */
/* Private data */
unsigned long *pixels;
int npixels;
struct _XColorContext *xcc;
}XmImage;
</pre>
The <i>pixmap</i> field contains the actual image. It is this pixmap that
you should use in a call to <b>XCopyArea</b> to put it directly in a window
or in combination with Motif's <b>XmNlabelPixmap</b> resource to put the
pixmap in a label widget.
<p>
If the value of the <i>clip</i> field is other than <b>None</b>, it means the
original image is a transparent image. You can then use this field as a
clipmask of a GC so your image will also be transparent.
<p>
<font face="helvetica, arial" size="3">[Note: the clipmask is a pixmap of depth
1, so it is actually a X11 bitmap.]</font>
<p>
One important reminder before explaining how to create and use a XmImage:
you should never touch any of the fields in the XmImage structure which are
mentioned as private data. This private data is used when the XmImage is
destroyed, so modifying any of these fields is a potential danger and leads
at least to a memory leak. If you really want to know what these fields
represent, here's a very short explanation of what they represent:
<p>
<ul>
<li><i>pixels</i>: an array of allocated pixels values;
<li><i>npixels</i>: the number of elements in pixels;
<li><i>xcc</i>: a structure containing a lot of information about the current
visual, colormap, maximum number of colors, color shifts and masks, etc...
This structure is used when allocating colors. If you really want to know
more about this structure, you should examine the following source files
of the XmHTML Widget Set source code: <tt>XCC.c, XCC.h</tt> and
<tt>XCCP.h</tt>
</ul>
<p>
<h3><a name="advanced_images_create"><font face="helvetica, arial">
2.6.4.2 Creating a XmImage
</font></a></h3>
You can create an XmImage by using the <b>XmImageCreate</b> convenience
function. This function is defined as follows:
<pre>
XmImage *XmImageCreate(Widget w, String file, Dimension width,
Dimension height);
</pre>
<i>w</i> must contain the id of a <b>Widget</b> (and not a Gadget) which will
be the owner of this image, <i>file</i> is the name of a file representing
the image that is to be loaded. The <i>width</i> and <i>height</i> arguments
allow you to scale the image. If both have the value 0 (zero), the
dimensions of the loaded image will be the dimensions as found in the image.
Otherwise, <b>XmImageCreate</b> will scale to image to fit the given
dimensions. Scaling is only done in the directions for which a value is given:
if you only want to scale the image horizontally, you should only specify
a value for <i>width</i> and set <i>height</i> to zero (or a value for height
and 0 for width to only scale the image vertically).
<p>
Although the external image support is independent of a XmHTML widget, you can
also use the <b>XmImageInfo</b> structure to create a XmImage. An example where
this can be usefull is in conjuction with the
<b><font face="fixed">XmHTMLXYToInfo()</font></b> convenience function.
As you may know by now, the return value of this function can contain a pointer
to a XmImageInfo structure. Supposing this is the case and you would want to
display a dialog box to the user with a thumbnail of the image, it is much
more convenient to create a XmImage directly from the XmImageInfo structure
instead of creating it from a file.
<p>
The syntax of the <b>XmImageCreateFromInfo()</b> convenience function is as
follows:
<pre>
XmImage *XmImageCreateFromInfo(Widget w, XmImageInfo *info, Dimension width,
Dimension height);
</pre>
The only difference with the <b>XmImageCreate()</b> function is that instead
of a filename you now supply a XmImageInfo structure.
<h3><a name="advanced_images_destroy"><font face="helvetica, arial">
2.6.4.3 Destroying a XmImage
</font></a></h3>
When you are done using a XmImage, you should destroy it using the
<b>XmImageDestroy</b> convenience function. The syntax to this function is
as follows:
<pre>
void XmImageDestroy(XmImage *image);
</pre>
This function will take care of destroying all pixmaps, possible animation
data and will free the colors allocated to this image. When this function
returns the given XmImage will no longer be valid.
<p>
One thing that this function will <b>not</b> do is release any
<b>XtIntervalId</b> that might be present in the given XmImage structure. It
is your responsibility to do this.
<h3><a name="advanced_images_using"><font face="helvetica, arial">
2.6.4.4 How to use a XmImage
</font></a></h3>
<h4><font face="helvetica, arial">
Normal Images
</font></h4>
<h4><font face="helvetica, arial">
Running Animations
</font></h4>
For the sake of clarity, we will repeat the <i>animation data</i> of the
<a href="#advanced_images_xmimage">XmImage</a> structure here:
<pre>
/* animation data */
XmImageFrame *frames; /* array of animation frames */
int nframes; /* no of frames following */
int current_frame; /* current frame count */
int current_loop; /* current loop count */
int loop_count; /* maximum loop count */
XtIntervalId proc_id; /* timer id for animations */
Widget w; /* image owner */
XtAppContext context; /* Application context for animations */
</pre>
The <i>*frames</i> field points to an array of structures of the following
type:
<pre>
typedef struct
{
int x; /* x position in logical screen */
int y; /* y position in logical screen */
int w; /* width of this particular frame */
int h; /* height of this particular frame */
int timeout; /* timeout for the next frame */
unsigned char dispose; /* previous frame disposal method */
Pixmap pixmap; /* actual image */
Pixmap clip; /* image clipmask */
Pixmap prev_state; /* previous screen state */
/* private data */
unsigned long *pixels;
int npixels;
}XmImageFrame;
</pre>
The total number of frames is given by the <i>nframes</i> field in the XmImage
structure. Each member of this array of structures represents a single frame in
an animation, so displaying all frames in sequence will result in an animation
being shown to the user.
<p>
Before embarking on how to display animations, it is necessary that you
understand the what the fields of the XmImageFrame structure represent.
<p>
<b>x, y, w and h</b>
<p>
The first frame in an animation determines the screen size of the animation.
This is what is called the <i>logical screen</i>. Every following frame can
have a size equal to or less than the logical screen size. The <i>x</i> and
<i>y</i> fields of the XmImageFrame structure determine the place of a frame
on the logical screen, while the <i>w</i> and <i>h</i> fields determine
the size of a frame.
<p>
<font face="helvetica, arial" size="3">[Note: Frames crossing logical screen
boundaries are automatically clipped by the XmImageCreate routines.]</font>
<p>
<b>timeout</b>
<p>
This field field indicates the number of milliseconds that should expire
before the next frame in an animation is displayed.
<p>
<b>loop_count</b>
<p>
This field indicates how many times an animation should be run. A loop_count
of zero indicates forever. Any self-respecting application should run
animations with a non-zero loop_count only for the specified number of loops.
<p>
<b>dispose</b>
<p>
This indicates how the <b>previous</b> frame should be removed before a new
frame is displayed. This field can have the following values:
<p>
<dl>
<dt>XmIMAGE_DISPOSE_NONE (value = 1)
<dd>do nothing, overlay the previous frame with the current frame;
<dt>XmIMAGE_DISPOSE_BY_BACKGROUND (value = 2)
<dd>Restore to background color. The area used by the previous frame should
be restored to the background color/image;
<p>
<dt>XmIMAGE_DISPOSE_BY_PREVIOUS (value = 3)
<dd>Restore to previous. The area used by the previous frame should be
restored to what was there prior to rendering the previous frame.
</dl>
<p>
Handling disposal methods 2 and 3 are one of the most difficult items to deal
with when running an animation. This is the reason why the <i>prev_state</i>
field is present in the <b>XmImageFrame</b> structure.
<p>
The use of the remaining fields of the <b>XmImageFrame</b> structure will
become clear in the following example which demonstrates how to run an
animation and how to deal with the different disposal methods.
<p>
<i>Example 2-?: Running an animation</i><p>
<pre>
[Put in a copy of the src/paint.c, routine DrawFrame]
</pre>
<p>
<IMG SRC="../Images/wood/bar.gif" width=508 height=15>
<br>
<img ismap usemap=#back src="../Images/wood/back.gif" border=0>
<map name=back>
<area href="progguide.html" shape=rect coords=0,0,83,33>
</map>
<img ismap usemap=#home src="../Images/wood/home.gif" border=0>
<map name=home>
<area href="http://www.xs4all.nl" shape=rect coords=0,0,83,33>
</map>
<img ismap usemap=#email_map src="../Images/wood/email.gif" border=0>
<map name=email_map>
<area href="mailto:ripley@xs4all.nl" shape=rect coords=0,0,83,33>
</map>
<br><IMG SRC="../Images/wood/bar.gif" width=508 height=15><br>
<i><font size="-1">
©Copyright 1996-1997 by Ripley Software Development<br>
Last update: September 19, 1997 by Koen
</font></i>
</BODY>
</HTML>
|