File: part1_defining_forms.texi

package info (click to toggle)
libforms 1.0.93sp1-1
  • links: PTS
  • area: main
  • in suites: squeeze
  • size: 11,548 kB
  • ctags: 9,107
  • sloc: ansic: 97,227; sh: 9,236; makefile: 858
file content (1748 lines) | stat: -rw-r--r-- 60,033 bytes parent folder | download | duplicates (2)
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
@node Part I Defining Forms
@chapter Defining Forms

In this chapter we will describe the basics of defining forms. Not all
possible classes of objects are described here, only the most common
ones. Also, for most classes only a subset of the available types are
described. See Part III for a complete overview of all object classes
currently available.

Normally you will almost never have to write the code to define forms
yourself because the package includes a Form Designer that does this
for you (see Part II). Still it is useful to read through this chapter
because it explains what some of the different object classes are and
how to work with them.

@ifnottex

@menu
* Starting and Ending a Form Definition::
* Boxes::
* Texts::
* Buttons::
* Sliders::
* ValSliders::
* Input Fields::
* Grouping Objects::
* Hiding and Showing::
* Deactivating and Triggering Objects::
* Changing Attributes::
* Adding and Deleting::
* Freeing Objects::
@end menu

@end ifnottex


@node Starting and Ending a Form Definition
@section Starting and Ending a Form Definition

A form consists of a collection of objects. A form definition is started
with the routine 
@findex fl_bgn_form()
@example
FL_FORM *fl_bgn_form(int type, FL_Coord w, FL_Coord h);
@end example
@noindent
@code{w} and @code{h} indicate the width and height of the form (in
pixels by default). Positions in the form will be indicated by
integers between 0 and @code{w-1} or @code{h-1}. The actual size of
the form when displayed on the screen can still be varied. @code{type}
indicates the type of the background drawn in the form. The background
of each form is a box. See the next section for the different types
available. The routine returns a pointer to the form just defined.
This pointer must be used, for example, when drawing the form or doing
interaction with it. The form definition ends with
@findex fl_end_form()
@example
void fl_end_form(void);
@end example
@noindent
Between these two calls objects are added to the form. The following
sections describe some of the more common classes of objects that can
be added to a form.

Many different forms can be defined and displayed when required.
Normally you probably will first define all your forms before starting
the actual work but it's no problem to define new forms also later on.


@node Boxes
@section Boxes

The first type of objects are boxes. Boxes are simply used to give the
forms and objects a nicer appearance. They can be used to visually
group other objects together. The background of each form is a box. To
add a box to a form you use the routine
@findex fl_add_box()
@example
FL_OBJECT *fl_add_box(int type, FL_Coord x, FL_Coord y,
                      FL_Coord w, FL_Coord h, const char *label);
@end example
@noindent
where @code{type} indicates the shape of the box. The Forms
Library at the moment supports the following types of boxes:

@table @code
@tindex FL_NO_BOX
@item FL_NO_BOX
No box at all (it's transparent), just a label
@tindex FL_UP_BOX
@item FL_UP_BOX
A box that comes out of the screen
@tindex FL_DOWN_BOX
@item FL_DOWN_BOX
A box that goes down into the screen
@tindex FL_BORDER_BOX
@item FL_BORDER_BOX
A flat box with a border
@tindex FL_SHADOW_BOX
@item FL_SHADOW_BOX
A flat box with a shadow
@tindex FL_FRAME_BOX
@item FL_FRAME_BOX
A flat box with an engraved frame
@tindex FL_ROUNDED_BOX
@item FL_ROUNDED_BOX
A rounded box
@tindex FL_EMBOSSED_BOX
@item FL_EMBOSSED_BOX
A flat box with an embossed frame
@tindex FL_FLAT_BOX
@item FL_FLAT_BOX
A flat box without a border (normally invisible unless given a
different color than the surroundings)
@tindex FL_RFLAT_BOX
@item FL_RFLAT_BOX
A rounded box without a border (normally invisible unless given a
different color than the surroundings)
@tindex FL_RSHADOW_BOX
@item FL_RSHADOW_BOX
A rounded box with a shadow
@tindex FL_OVAL_BOX
@item FL_OVAL_BOX
A box shaped like an ellipse
@tindex FL_ROUNDED3D_UPBOX
@item FL_ROUNDED3D_UPBOX
A rounded box coming out of the screen
@tindex FL_ROUNDED3D_DOWNBOX
@item FL_ROUNDED3D_DOWNBOX
A rounded box going into the screen
@tindex FL_OVAL3D_UPBOX
@item FL_OVAL3D_UPBOX
An oval box coming out of the screen
@tindex FL_OVAL3D_DOWNBOX
@item FL_OVAL3D_DOWNBOX
An oval box going into the screen
@end table

@ifhtml
@center @image{images/boxtypes}
@end ifhtml
@ifnothtml
@center @image{images/boxtypes,15cm}
@end ifnothtml

@code{x} and @code{y} indicate the upper left corner of the box in the
form. @code{w} and @code{h} are the width and height of the box.
@code{label} is a text that is placed in the center of the box. If you
don't want a label in the box, use an empty string or a @code{NULL}
pointer. The label can be either one line or multiple lines. To obtain
multi-line labels, insert newline characters (@code{\n}) in the label
string. It is also possible to underline the label or one of the
characters in the label. This is accomplished by embedding
@code{<CNTRL> H} (@code{\010}) after the letter that needs to be
underlined. If the very first character of the label is
@code{<Ctrl>H}, the entire label is underlined.

The routine @code{@ref{fl_add_box()}} returns a pointer to the box object.
(All routines that add objects return a pointer to the object.) This
pointer can be used for later references to the object.

It is possible to change the appearance of a box in a form. First of
all, it is possible to change the color of the box and secondly, it is
possible to change color, size and position of the label inside the
box. Details on changing attributes of objects can be found in
@ref{Changing Attributes}. Just a simple example has to suffice here.
Assume we want to create a red box, coming out of the screen with the
large words "I am a Box" in green in the center:
@example
FL_OBJECT *thebox;

thebox = fl_add_box(FL_UP_BOX, 20, 20, 100, 100, "I am a Box");
fl_set_object_color(thebox, FL_RED, 0 );    /* make box red     */
fl_set_object_lcol(thebox, FL_GREEN );      /* make label green */
fl_set_object_lsize(thebox, FL_LARGE_SIZE); /* make label large */
@end example
@noindent
Of course, this has to be placed inside a form definition.


@node Texts
@section Texts

A second type of object is text. Text can be placed at any place on the
form in any color you like. Placing a text object is done with the
routine
@findex fl_add_text()
@example
FL_OBJECT *fl_add_text(int type, FL_Coord x, FL_Coord y,
                       FL_Coord w, FL_Coord h, const char *label);
@end example
@noindent
where @code{type} indicates the shape of the text. The Forms Library at
the moment supports only one type of text: @code{FL_NORMAL_TEXT}.

The text can be placed inside a box using the routine
@code{@ref{fl_set_object_boxtype()}} to be described in @ref{Changing
Attributes}. Again, the text can be multi-lined or underlined by
embedding respectively the newline (@code{\n}) or @code{<Ctrl>H}
(@code{\010}) in the label. The style, size and color of the text can
be controlled and changed in many ways. @xref{Label Attributes and
Fonts}.

Note that there is almost no difference between a box with a label and
a text. The only difference lies in the position where the text is
placed. Text is normally placed inside the box at the left side. This
helps you put different lines of text below each other. Labels inside
boxes are by default centered in the box. You can change the position
of the text inside the box using the routines in @ref{Label Attributes
and Fonts}. Note that, when not using any box around the text there is
no need to specify a width and height of the box; they can both be 0.


@node Buttons
@section Buttons

A very important class of objects are buttons. Buttons are placed on the
form such that the user can push them with the mouse. Different types of
buttons exist: buttons that return to their normal position when the
user releases the mouse, buttons that stay pushed until the user pushes
them again and radio buttons that make other buttons be released. Adding
a button to a form can be done using the following routine
@findex fl_add_button()
@example
FL_OBJECT *fl_add_button(int type, FL_Coord x, FL_Coord y,
                         FL_Coord w, FL_Coord h,
                         const char *label);
@end example
@noindent
@code{label} is the text placed inside (or next to) the button.
@code{type} indicates the type of the button. The Forms Library at the
moment supports a number of types of buttons. The most important ones
are:
@tindex FL_NORMAL_BUTTON
@tindex FL_PUSH_BUTTON
@tindex FL_TOUCH_BUTTON
@tindex FL_RADIO_BUTTON
@example
FL_NORMAL_BUTTON
FL_PUSH_BUTTON
FL_TOUCH_BUTTON
FL_RADIO_BUTTON
@end example
@noindent
They all look the same on the screen but their functions are quite
different. Each of these buttons get pushed down when the user presses
the mouse on top of them. What actually happens when the user does so
depends on the type of button.

A normal button returns to its normal position when the user releases
the mouse button.

A push button remains pushed and is only released when the user pushes
it again.

A touch button is like a normal button except that as long as the user
keeps the mouse pressed it is returned to the application program.
(@xref{Part I Doing Interaction, , Doing Interaction}, on the details
of interaction.)

A radio button is a push button with additional extra property:
Whenever the user pushes a radio button, all other pushed radio
buttons in the form (or at least in the group, see below) they belong
to are released. In this way the user can make a choice among some
mutually exclusive possibilities.

Whenever the user pushes a button and then releases the mouse, the
interaction routine @code{@ref{fl_do_forms()}} is interrupted and
returns a pointer to the button that was pushed and released. If a
callback routine is present for the object being pushed, this routine
will be invoked. In either case, the application program knows that
the button was pushed and can take action accordingly. In the first
case, control will have to be returned to @code{@ref{fl_do_forms()}}
again after the appropriate action is performed; and in the latter,
@code{@ref{fl_do_forms()}} would never return. @xref{Part I Doing
Interaction, , Doing Interaction}, for details on the interaction with
forms.

Different types of buttons are used in all the example programs
provided. The application program can also set a button to be pushed
or not itself without a user action. (This is of course only useful
for push buttons and radio buttons. Setting a radio button does not
mean that the currently set radio button is reset. The application
program has to do this.) To set or reset a button use the routine
@findex fl_set_button()
@example
void fl_set_button(FL_OBJECT *obj, int pushed);
@end example
@noindent
@code{pushed} indicates whether the button should be pushed (1) or
released (0). To figure out whether a button is pushed or not use
@findex fl_get_button()
@example
int fl_get_button(FL_OBJECT *obj);
@end example
@noindent
See the program @file{pushbutton.c} for an example of the
use of push buttons and setting and getting button information.

The color and label of buttons can again be changed using the routines
in @ref{Changing Attributes}.

There are other classes of buttons available that behave the same way as
buttons but only look different.
@table @asis
@item Light buttons
have a small "light" (colored area) in the button. Pushing the button
switches the light on, and releasing the button switches it off. To
add a light button use @code{@ref{fl_add_lightbutton()}} with the same
parameters as for normal buttons. The other routines are exactly the
same as for normal buttons. The color of the light can be controlled
with the routine @code{@ref{fl_set_object_color()}}. @xref{Changing
Attributes}.
@item Round buttons
are buttons that are round. Use @code{@ref{fl_add_roundbutton()}} to
add a round button to a form.
@item Round3d buttons
are buttons that are round and 3D-ish looking. Round and light buttons
are nice as radio and push buttons.
@item Check buttons
are buttons that have a small checkbox the user can push. To add a
check button, use @code{@ref{fl_add_checkbutton()}}. More stylish for
a group of radio buttons.
@item Bitmap buttons
are buttons that have a bitmap on top of the box. Use routine
@code{@ref{fl_add_bitmapbutton()}} to add a bitmap button to a form.
@item Pixmap buttons
are buttons that have a pixmap on top of the box. Use routine
@code{@ref{fl_add_pixmapbutton()}} to add a pixmap button to a form.
@end table

Playing with different boxtypes, colors, etc., you can make many
different types of buttons. See @file{buttonall.c} for some examples.
Fig. 16.1 shows all buttons in their default states.


@node Sliders
@section Sliders

Sliders are useful in letting the user indicate a value between some
fixed bounds. A slider is added to a form using the routine
@findex fl_add_slider()
@example
FL_OBJECT *fl_add_slider(int type, FL_Coord x, FL_Coord y,
                         FL_Coord w, FL_Coord h,
                         const char *label);
@end example

The two most important types of sliders are @code{FL_VERT_SLIDERM} and
@code{FL_HOR_SLIDER}. The former displays a slider that can be moved
vertically and the latter gives a slider that moves horizontally. In
both cases the label is placed below the slider. Default value of the
slider is 0.5 and can vary between 0.0 and 1.0. These values can be
changed using the routines:
@findex fl_set_slider_value()
@findex fl_set_slider_bounds()
@example
void fl_set_slider_value(FL_OBJECT *obj, double val);
void fl_set_slider_bounds(FL_OBJECT *obj, double min, double max);
@end example
@noindent
Whenever the value of the slider is changed by the
user, it results in the slider being returned to the application program
or the callback routine invoked. The program can read the slider value
using the call
@findex fl_get_slider_value()
@example
double fl_get_slider_value(FL_OBJECT *obj);
@end example
@noindent
and take action accordingly. See the example program @file{demo05.c} for
the use of these routines.


@ifhtml
@center @image{images/slider}
@end ifhtml
@ifnothtml
@center @image{images/slider,8cm}
@end ifnothtml

@node ValSliders
@section ValSliders

A valslider is almost identical with a normal slider. The only
difference is the way the slider is drawn. For valsliders, in addition
to the slider itself, its current value is also shown.

To add a valslider, use
@findex fl_add_valslider()
@example
FL_OBJECT *fl_add_valslider(int type, FL_Coord x, FL_Coord y,
                            FL_Coord w, FL_Coord h,
                            const char *label);
@end example

For all other interaction with a valslider the same function as for
normal sliders can be used.


@node Input Fields
@section Input Fields

It is often required to obtain textual input from the user, e.g. a file
name, some fields in a database, etc. To this end input fields exist in
the Forms Library. An input field is a field that can be edited by the
user using the keyboard. To add an input field to a form use
@findex fl_add_input()
@example
FL_OBJECT *fl_add_input(int type, FL_Coord x, FL_Coord y,
                        FL_Coord w, FL_Coord h, const char *label);
@end example
@noindent
The main type of input field available is @code{FL_NORMAL_INPUT}. The
input field normally looks like an @code{FL_DOWN_BOX}. This can be
changed using the routine @code{@ref{fl_set_object_boxtype()}} to be
described in @ref{Changing Attributes}.

Whenever the user presses the mouse inside an input field a cursor will
appear in it (and it will change color). Further input will appear
inside this field. Full emacs(1) style editing is supported. When the
user presses @code{<Return>} or @code{<Tab>} the input field is returned
to the application program and further input is directed to the next
input field. (The @code{<Return>} key only works if there are no default
buttons in the form. See the overview of object classes. The
@code{<Tab>} key always works.)

@ifhtml
@center @image{images/input}
@end ifhtml
@ifnothtml
@center @image{images/input,8cm}
@end ifnothtml

The user can use the mouse to select parts of the input field which will
be removed when the user types the erase character or replaced by any
new input the user types in. Also the location of the cursor can be
moved in the input field using the mouse.

The input field is fully integrated with the X Selection mechanism. Use
the left button to cut from and the middle button to paste into an input
field.

The application program can direct the focus to a particular object
using the call
@findex fl_set_focus_object()
@example
void fl_set_focus_object(FL_FORM *form, FL_OBJECT *obj);
@end example
@noindent
It puts the input focus in the form form onto object @code{obj}. To
obtain the focus object, the following routine is available
@findex fl_get_focus_object()
@example
FL_OBJECT *fl_get_focus_object(FL_FORM *form);
@end example

Note that the label is not the default text in the input field. The
label is (by default) placed in front of the input field. To set the
contents of the input field use the routine
@findex fl_set_input()
@example
void fl_set_input(FL_OBJECT *obj, const char *str);
@end example

To change the color of the input text or the cursor use
@findex fl_set_input_color()
@example
void fl_set_input_color(FL_OBJECT *obj, int tcol, int ccol);
@end example
@noindent
Here @code{tcol} indicates the color of the text
and @code{ccol} is the color of the cursor. To obtain the
string in the field (when the user has changed it) use:
@findex fl_get_input()
@example
[const] char *fl_get_input(FL_OBJECT *obj);
@end example
@noindent
Notice the bracket around the qualifier const. This indicates although
the function is not declared to return a pointer to const string, it
should be used as one. This is done mainly for compilation on machines
whose string library header is buggy. Modifying the string returned by
this function can produce unpredictable results.

See the program @file{demo06.c} for an example of the use of input
fields.


@node Grouping Objects
@section Grouping Objects

Objects inside a form definition can be grouped together. To this end we
place them in between the routines
@findex fl_bgn_group()
@example
FL_OBJECT *fl_bgn_group(void);
@end example
@noindent
and
@findex fl_end_group()
@example
void fl_end_group(void);
@end example
@noindent
The first function returns a pointer to a pseudo-object that
represents the start of the group (its class is
@code{FL_BEGIN_GROUP}). It can be used in a number of functions to
work on the whole group at once. Also the second creates a
pseudo-object (of class @code{FL_END_GROUP}), marking the groups end,
but since this object can't be used its address isn't returned.

Groups can't be nested. Groups are useful for two reasons. First of
all it is possible to hide groups of objects. (@xref{Hiding and
Showing}, below.) This is often very handy. We can, for example,
display part of a form only when the user asks for it (see demo
program @file{group.c}. Some attributes are naturally multi-objects,
e.g., to glue several objects together using the gravity attribute.
Instead of setting the gravity for each object, you can place all
related objects inside a group and set the resize/gravity attribute of
the group.

The second reason is for using radio buttons. As indicated in section
3.4 pushing a radio button makes the currently pushed radio button
released. In fact, this happens only with radio buttons in the
particular group. So to make two pairs (or more) of radio buttons,
simply put each pair in a different group so that they won't interfere
with each other. See, e.g., the example program @file{buttonall.c}. It
is a good idea to always put radio buttons in a group, even if you
have only one set of them.

It is possible to add objects to an existing group
@findex fl_addto_group()
@example
FL_OBJECT *fl_addto_group(FL_OBJECT *group);
@end example
@noindent
where @code{group} is the object returned by
@code{@ref{fl_bgn_group()}}. After this call, you can start adding
objects to the group (e.g., @code{@ref{fl_add_button()}} etc.). The
newly added objects are appended at the end of the group. When through
with adding, use @code{@ref{fl_end_group()}} as before.


@node Hiding and Showing
@section Hiding and Showing

It is possible to temporarily hide certain objects or groups of objects.
To this end, use the routine
@findex fl_hide_object()
@example
void fl_hide_object(FL_OBJECT *obj);
@end example
@noindent
@code{obj} is the object to hide or the group of objects to hide. Hidden
objects don't play any role anymore. All routines on the form act as if
the object does not exist. To make the object or group of objects
visible again use
@findex fl_show_object()
@example
void fl_show_object(FL_OBJECT *obj);
@end example
@noindent
Hiding and showing (groups of) objects are useful to change the
appearance of a form depending on particular information provided by the
user. You can also make overlapping groups in the form and take care
that only one of them is visible.

If you want to know if an object is shown you can use
@findex fl_object_is_visible()
@example
int fl_object_is_visible(FL_OBJECT *obj);
@end example
@noindent
Please note for an object to be visible also the form it belongs to
must be shown, which isn't factored into the return value.


@node Deactivating and Triggering Objects
@section Deactivating and Triggering Objects

Sometimes you might want a particular object to be temporarily inactive,
e.g., you want to make it impossible for the user to press a particular
button or to type input in a particular field. For this you can use the
routine
@findex fl_deactivate_object()
@example
void fl_deactivate_object(FL_OBJECT *obj);
@end example
@noindent
@code{obj} is the object to be deactivated.
When @code{obj} is a group the whole group is deactivated.
To reactivate the group or button use the routine
@findex fl_activate_object()
@example
void fl_activate_object(FL_OBJECT *obj);
@end example

To find out if an object is in active state use the function
@findex fl_object_is_active()
@example
int fl_object_is_active(FL_OBJECT *obj);
@end example

Normally you also want to give the user a visual indication that the
object is not active. This can, for example, be done by changing the
label color to grey (see below). This is not done automatically, so
unless you set e.g.@: a different color the objects appearance won't
change on deactivation (or re-activation).

It is possible to simulate the action of an object being triggered from
within the program by using the following routine
@findex fl_trigger_object()
@example
void fl_trigger_object(FL_OBJECT *obj);
@end example
@noindent
Calling this routine on an object @code{obj} results in the object
returned to the application program or its callback being called if it
exists. Note however, there is no visual feedback, i.e.@:
@code{fl_trigger_object(button)} will not make the button object
named @code{button} appear to be pushed.


@node Changing Attributes
@section Changing Attributes

There are a number of general routines that can be used to alter the
appearance of any object.

@ifnottex

@menu
* Color::
* Bounding Boxes::
* Label Attributes and Fonts::
* Tool Tips::
* Redrawing::
* Changing Many Attributes::
* Symbols::
@end menu

@end ifnottex


@node Color
@subsection Color

To change the color of a particular object use the routine
@findex fl_set_object_color()
@example
void fl_set_object_color(FL_OBJECT *obj,
                         FL_COLOR col1, FL_COLOR col2);
@end example
@noindent
@code{col1} and @code{col2} are indices into a colormap. Which colors
are actually changed depends on the type of the object. For box and
text only @code{col1} is important. It indicates the color of the box
or of the box in which the text is placed. For buttons, @code{col1} is
the color of the button when released and @code{col2} is the color of
the button when pushed. (Note that when changing the color of a button
the nice property that the color of a button changes when the mouse
moves over it disappears.) For light buttons the two colors indicate
the color of the light when off and when on. For bitmap buttons,
@code{col1} is the color of the box and @code{col2} is the color of
the bitmap. For sliders @code{col1} is the color of the background of
the slider and @code{col2} is the color of the slider itself. Finally,
for input objects @code{col1} is the color of the input field when it
is not selected and @code{col2} is the color when it has input focus,
i.e.@: the user can enter text. For all types of objects, the default
colors can be found in the file @file{forms.h}. For example, for input
fields the default colors are @code{FL_INPUT_COL1} and
@code{FL_INPUT_COL2}. Form Designer comes in very handy in
familiarizing you with various attributes since you can change all
attributes of an object and immediately see the difference by
"test"ing the object.

To find out the colors of an object use
@findex fl_get_object_color()
@example
void fl_get_object_color(FL_OBJECT *obj,
                         FL_COLOR *col1, FL_COLOR *col2);
@end example

The following pre-defined color symbols can be used in all color change
requests. If the workstation does not support this many colors,
substitution by the closest color will happen.
@multitable @columnfractions 0.3 0.3 0.3
@headitem Name
@tab RGB triple
@tindex FL_BLACK
@item @code{FL_BLACK}
@tab @code{(  0,   0,   0)}
@ifhtml
@tab @image{images/FL_BLACK}
@end ifhtml
@ifnothtml
@tab @image{images/FL_BLACK,2cm,5mm}
@end ifnothtml
@tindex FL_WHITE
@item @code{FL_WHITE}
@tab @code{(255, 255, 255)},
@ifhtml
@tab @image{images/FL_WHITE}
@end ifhtml
@ifnothtml
@tab @image{images/FL_WHITE,2cm,5mm}
@end ifnothtml
@tindex FL_COL1
@item @code{FL_COL1}
@tab @code{(173, 173, 173)}
@ifhtml
@tab @image{images/FL_COL1}
@end ifhtml
@ifnothtml
@tab @image{images/FL_COL1,2cm,5mm}
@end ifnothtml
@tindex FL_BOTTOM_BCOL
@item @code{FL_BOTTOM_BCOL}
@tab @code{(  89,  89,  89)}
@ifhtml
@tab @image{images/FL_BOTTOM_BCOL}
@end ifhtml
@ifnothtml
@tab @image{images/FL_BOTTOM_BCOL,2cm,5mm}
@end ifnothtml
@tindex FL_RIGHT_BCOL
@item @code{FL_RIGHT_BCOL}
@tab @code{(  41,  41,  41)}
@ifhtml
@tab @image{images/FL_RIGHT_BCOL}
@end ifhtml
@ifnothtml
@tab @image{images/FL_RIGHT_BCOL,2cm,5mm}
@end ifnothtml
@tindex FL_MCOL
@item @code{FL_MCOL}
@tab @code{(191, 191, 191)}
@ifhtml
@tab @image{images/FL_MCOL}
@end ifhtml
@ifnothtml
@tab @image{images/FL_MCOL,2cm,5mm}
@end ifnothtml
@tindex FL_LEFT_BCOL
@item @code{FL_LEFT_BCOL}
@tab @code{(222, 222, 222)}
@ifhtml
@tab @image{images/FL_LEFT_BCOL}
@end ifhtml
@ifnothtml
@tab @image{images/FL_LEFT_BCOL,2cm,5mm}
@end ifnothtml
@tindex FL_LIGHTER_COL1
@item @code{FL_LIGHTER_COL1}
@tab @code{(204, 204, 204)}
@ifhtml
@tab @image{images/FL_LIGHTER_COL1}
@end ifhtml
@ifnothtml
@tab @image{images/FL_LIGHTER_COL1,2cm,5mm}
@end ifnothtml
@tindex FL_DARKER_COL1
@item @code{FL_DARKER_COL1}
@tab @code{(161, 161, 161)}
@ifhtml
@tab @image{images/FL_DARKER_COL1}
@end ifhtml
@ifnothtml
@tab @image{images/FL_DARKER_COL1,2cm,5mm}
@end ifnothtml
@tindex FL_SLATEBLUE
@item @code{FL_SLATEBLUE}
@tab @code{(113, 113, 198)}
@ifhtml
@tab @image{images/FL_SLATEBLUE}
@end ifhtml
@ifnothtml
@tab @image{images/FL_SLATEBLUE,2cm,5mm}
@end ifnothtml
@tindex FL_INDIANRED
@item @code{FL_INDIANRED}
@tab @code{(198, 113, 113)}
@ifhtml
@tab @image{images/FL_INDIANARED}
@end ifhtml
@ifnothtml
@tab @image{images/FL_INDIANARED,2cm,5mm}
@end ifnothtml
@tindex FL_RED
@item @code{FL_RED}
@tab @code{(255,   0,   0)}
@ifhtml
@tab @image{images/FL_RED}
@end ifhtml
@ifnothtml
@tab @image{images/FL_RED,2cm,5mm}
@end ifnothtml
@tindex FL_BLUE
@item @code{FL_BLUE}
@tab @code{(  0,   0, 255)}
@ifhtml
@tab @image{images/FL_BLUE}
@end ifhtml
@ifnothtml
@tab @image{images/FL_BLUE,2cm,5mm}
@end ifnothtml
@tindex FL_GREEN
@item @code{FL_GREEN}
@tab @code{(  0, 255,   0)}
@ifhtml
@tab @image{images/FL_GREEN}
@end ifhtml
@ifnothtml
@tab @image{images/FL_GREEN,2cm,5mm}
@end ifnothtml
@tindex FL_YELLOW
@item @code{FL_YELLOW}
@tab @code{(255, 255,   0)}
@ifhtml
@tab @image{images/FL_YELLOW}
@end ifhtml
@ifnothtml
@tab @image{images/FL_YELLOW,2cm,5mm}
@end ifnothtml
@tindex FL_MAGENTA
@item @code{FL_MAGENTA}
@tab @code{(255,   0, 255)}
@ifhtml
@tab @image{images/FL_MAGENTA}
@end ifhtml
@ifnothtml
@tab @image{images/FL_MAGENTA,2cm,5mm}
@end ifnothtml
@tindex FL_CYAN
@item @code{FL_CYAN}
@tab @code{(  0, 255, 255)}
@ifhtml
@tab @image{images/FL_CYAN}
@end ifhtml
@ifnothtml
@tab @image{images/FL_CYAN,2cm,5mm}
@end ifnothtml
@tindex FL_TOMATO
@item @code{FL_TOMATO}
@tab @code{       255,  99,  71}
@ifhtml
@tab @image{images/FL_TOMATO}
@end ifhtml
@ifnothtml
@tab @image{images/FL_TOMATO,2cm,5mm}
@end ifnothtml
@tindex FL_INACTIVE
@item @code{FL_INACTIVE}
@tab @code{(110, 110, 110)}
@ifhtml
@tab @image{images/FL_INACTIVE}
@end ifhtml
@ifnothtml
@tab @image{images/FL_INACTIVE,2cm,5mm}
@end ifnothtml
@tindex FL_TOP_BCOL
@item @code{FL_TOP_BCOL}
@tab @code{(204, 204, 204)}
@ifhtml
@tab @image{images/FL_TOP_BCOL}
@end ifhtml
@ifnothtml
@tab @image{images/FL_TOP_BCOL,2cm,5mm}
@end ifnothtml
@tindex FL_PALEGREEN
@item @code{FL_PALEGREEN}
@tab @code{(113, 198, 113)}
@ifhtml
@tab @image{images/FL_PALEGREEN}
@end ifhtml
@ifnothtml
@tab @image{images/FL_PALEGREEN,2cm,5mm}
@end ifnothtml
@tindex FL_DARKGOLD
@item @code{FL_DARKGOLD}
@tab @code{(205, 149,  10)}
@ifhtml
@tab @image{images/FL_DARKGOLD}
@end ifhtml
@ifnothtml
@tab @image{images/FL_DARKGOLD,2cm,5mm}
@end ifnothtml
@tindex FL_ORCHID
@item @code{FL_ORCHID}
@tab @code{(205, 105, 201)}
@ifhtml
@tab @image{images/FL_ORCHID}
@end ifhtml
@ifnothtml
@tab @image{images/FL_ORCHID,2cm,5mm}
@end ifnothtml
@tindex FL_DARKCYAN
@item @code{FL_DARKCYAN}
@tab @code{(40, 170, 175)}
@ifhtml
@tab @image{images/FL_DARKCYAN}
@end ifhtml
@ifnothtml
@tab @image{images/FL_DARKCYAN,2cm,5mm}
@end ifnothtml
@tindex FL_DARKTOMATO
@item @code{FL_DARKTOMATO}
@tab @code{(139,  54,  38)}
@ifhtml
@tab @image{images/FL_DARKTOMATO}
@end ifhtml
@ifnothtml
@tab @image{images/FL_DARKTOMATO,2cm,5mm}
@end ifnothtml
@tindex FL_WHEAT
@item @code{FL_WHEAT}
@tab @code{(255, 231, 155)}
@ifhtml
@tab @image{images/FL_WHEAT}
@end ifhtml
@ifnothtml
@tab @image{images/FL_WHEAT,2cm,5mm}
@end ifnothtml
@tindex FL_DARKORANGE
@item @code{FL_DARKORANGE}
@tab @code{(255, 128,   0)}
@ifhtml
@tab @image{images/FL_DARKORANGE}
@end ifhtml
@ifnothtml
@tab @image{images/FL_DARKORANGE,2cm,5mm}
@end ifnothtml
@tindex FL_DEEPPINK
@item @code{FL_DEEPPINK}
@tab @code{(255,   0, 128)}
@ifhtml
@tab @image{images/FL_DARKPINK}
@end ifhtml
@ifnothtml
@tab @image{images/FL_DARKPINK,2cm,5mm}
@end ifnothtml
@tindex FL_CHARTREUSE
@item @code{FL_CHARTREUSE}
@tab @code{(128, 255,   0)}
@ifhtml
@tab @image{images/FL_CHARTEUSE}
@end ifhtml
@ifnothtml
@tab @image{images/FL_CHARTEUSE,2cm,5mm}
@end ifnothtml
@tindex FL_DARKVIOLET
@item @code{FL_DARKVIOLET}
@tab @code{(128,   0, 255)}
@ifhtml
@tab @image{images/FL_DARKVIOLET}
@end ifhtml
@ifnothtml
@tab @image{images/FL_DARKVIOLET,2cm,5mm}
@end ifnothtml
@tindex FL_SPRINGGREEN
@item @code{FL_SPRINGGREEN}
@tab @code{(  0, 255, 128)}
@ifhtml
@tab @image{images/FL_SPRINGGREEN}
@end ifhtml
@ifnothtml
@tab @image{images/FL_SPRINGGREEN,2cm,5mm}
@end ifnothtml
@tindex FL_DODGERBLUE
@item @code{FL_DODGERBLUE}
@tab @code{(  0, 128, 255)}
@ifhtml
@tab @image{images/FL_DODGERBLUE}
@end ifhtml
@ifnothtml
@tab @image{images/FL_DODGERBLUE,2cm,5mm}
@end ifnothtml
@tindex FL_FREE_COL1
@item @code{FL_FREE_COL1}
@tab @code{(  ?,   ?,   ?)}
@end multitable

Of all the colors listed in the table above @code{FL_FREE_COL1} has
the largest numerical value, and all color with indices smaller than
that are used (or can potentially be used) by the Forms Library
although, if you wish, they can also be changed using the following
routine prior to @code{@ref{fl_initialize()}}:
@findex fl_set_icm_color()
@example
void fl_set_icm_color(FL_COLOR index, int r, int g, int b);
@end example

Note that although the color of an object is indicated by a single
index, it is not necessarily true that the Forms Library is operating
in PseudoColor. Forms Library is capable of operating in all visuals
and as a matter of fact the Forms Library will always select TrueColor
or DirectColor if the hardware is capable of it.

The actual color is handled by an internal colormap of
@anchor{FL_MAX_COLORS}
@tindex FL_MAX_COLORS
@code{FL_MAX_COLORS} entries (default is 1024). To change or query the
values of this internal colormap use the call
@findex fl_set_icm_color()
@findex fl_get_icm_color()
@example
void fl_set_icm_color(FL_COLOR index, int r, int g, int b);
void fl_get_icm_color(FL_COLOR index, int *r, int *g, int *b);
@end example

Call @code{@ref{fl_set_icm_color()}} before
@code{@ref{fl_initialize()}} to change XForms's default colormap. Note
that these two routines do not communicate with the X server, they
only populate/return information about the internal colormap, which is
made known to the X server by the initialization routine
@code{@ref{fl_initialize()}}.

To change the colormap and make a color index active so that it can be
used in various drawing routines after @code{@ref{fl_initialize()}}
initialization, use the following function
@example
unsigned long fl_mapcolor(FL_COLOR i,
                          int red, int green, int blue);
@end example
@noindent
This function frees the previous allocated pixel corresponding to color
index @code{i} and re-allocates a pixel with the RGB value specified.
The pixel value is returned by the function. It is recommended that you
use an index larger than @code{FL_FREE_COL1} for your remap request to
avoid accidentally freeing the colors you have not explicitly allocated.
Indices larger than 224 are reserved and should not be used.

Sometimes it may be more convenient to associate an index with a
colorname, e.g., "red" etc., which may have been obtained via resources.
To this end, the following routine exists
@example
long fl_mapcolorname(FL_COLOR i, const char *name);
@end example
@noindent
where @code{name} is the color name@footnote{Standard color names are
listed in a file named @file{rgb.txt} and usually resides in
@file{/usr/lib/X11/}}. The function returns -1 if the colorname name is
not resolved. You can obtain the RGB values of an index by using the
following routine
@example
unsigned long fl_getmcolor(FL_COLOR i,
                           int *red, int *green, int *blue);
@end example
@noindent
The function returns the pixel value as known by the Xserver. If the
requested index, @code{i}, is never mapped or is freed, the RGB values
as well as the pixel value are random. Since this function communicates
with the Xserver to obtain the pixel information, it has a two-way
traffic overhead. If you're only interested in the internal colormap of
XForms, @code{@ref{fl_get_icm_color()}} is more efficient.

Note that the current version only uses the lower byte of the primary
color. Thus all primary colors in the above functions should be
specified in the range of 0-255 inclusive.

To free any colors that you no longer need, the following routine should
be used
@example
void fl_free_colors(FL_COLOR colors[], int ncolors);
@end example

Prior to XForms version 0.76, there is a color "leakage" in the
implementation of the internal colormap that prevents the old index from
being freed in the call @code{@ref{fl_mapcolor()}}, resulting in accelerated
colormap overflow and some other undesirable behavior. Since there may
still be some applications based on older versions of the Forms Library,
a routine is provided to force the library to be compatible with the
(buggy) behavior:
@example
void fl_set_color_leak(int flag);
@end example

Due to the use of an internal colormap and the simplified user
interface, changing the colormap value for the index may not result
in a change of the color for the object. An actual redraw of the
object (see below) whose color is changed may be required to have the
change take effect. Therefore, a typical sequence of changing the color
of a visible object is as follows:
@example
fl_mapcolor(newcol, red, green, blue);  /* obj uses newcol */
fl_redraw_object(obj);
@end example


@node Bounding Boxes
@subsection Bounding Boxes

Each object has a bounding box. This bounding box can have different
shapes. For boxes it is determined by the type. For text it is normally
not visible. For input fields it normally is a @code{FL_DOWN_BOX}, etc.
The shape of the box can be changed using the routine
@example
void fl_set_object_boxtype(FL_OBJECT *obj, int boxtype);
@end example
@noindent
@code{boxtype} should be one of the following: @code{FL_UP_BOX},
@code{FL_DOWN_BOX}, @code{FL_FLAT_BOX}, @code{FL_BORDER_BOX},
@code{FL_SHADOW_BOX}, @code{FL_ROUNDED_BOX}, @code{FL_RFLAT_BOX},
@code{FL_RSHADOW_BOX} and @code{FL_NO_BOX}, with the same meaning as the
type for boxes. Some care has to be taken when changing boxtypes. In
particular, for objects like sliders, input fields, etc. never use the
boxtype @code{FL_NO_BOX}. Don't change the boxtype of objects that are
visible on the screen. It might have undesirable effects. If you must do
so, redraw the entire form after changing the boxtype of an object (see
below). See the program @file{boxtype.c} for the effect of the boxtype
on the different classes of objects.

It is possible to alter the appearance of an object by changing the
border width attribute
@example
void fl_set_object_bw(FL_OBJECT *obj, int bw);
@end example
@noindent
To find out about the current setting for the border width of an
object call
@findex fl_get_object_bw()
@example
int fl_get_object_bw(FL_OBJECT *obj);
@end example

Border width controls the "height" of an object, e.g., a button having
a border width of 3 pixels appears more pronounced than one having a
border width of 2. The Forms Library's default is
@code{FL_BOUND_WIDTH} (1) pixels (before version 1.0.91 the default
was 3). Note that the border width can be negative. Negative border
width does not make a down box, rather, it makes the object having an
upbox appear less pronounced and "softer". See program
@file{borderwidth.c} for the effect of border width on different
objects. All applications developed using XForms accept a command line
option @samp{-bw}, followed by an integer number, the user can use to
select the preferred border width. It is recommended that you document
this flag in your application documentation. If you prefer a certain
border width, use @code{@ref{fl_set_defaults()}} or
@code{@ref{fl_set_border_width()}} before @code{@ref{fl_initialize()}}
to set the border width instead of hard-coding it on a per form or per
object basis so the user has the option to change it at run time via
the @samp{-bw} flag.

@ifhtml
@center @image{images/borderwidth}
@end ifhtml
@ifnothtml
@center @image{images/borderwidth,14cm}
@end ifnothtml

There also exists a call that changes the object border width for the
entire application
@example
void fl_set_border_width(int border_width);
@end example


@node Label Attributes and Fonts
@subsection Label Attributes and Fonts

There are also a number of routines to change the appearance of the
label. The first one is
@example
void fl_set_object_lcol(FL_OBJECT *obj, FL_COLOR lcol);
@end example
@noindent
It sets the color of the label. The default is black
(@code{FL_BLACK}). The font size of the label
can be changed using the routine
@example
void fl_set_object_lsize(FL_OBJECT *obj, int lsize);
@end example
@noindent
where @code{lsize} gives the size in points. Depending on the server and
fonts installed, arbitrary sizes may or may not be possible. Fig 3.5
shows the font sizes that are standard with MIT/XConsortium
distribution. So use of these values is encouraged. In any case, if a
requested size can not be honored, substitution will be made. The
default size for XForms is 10pt.

@multitable  @columnfractions 0.3 0.2 0.5
@anchor{FL_TINY_SIZE}
@tindex FL_TINY_SIZE
@item @code{FL_TINY_SIZE}
@tab 8pt
@anchor{FL_SMALL_SIZE}
@tindex FL_SMALL_SIZE
@item @code{FL_SMALL_SIZE}
@tab 10pt
@anchor{FL_NORMAL_SIZE}
@tindex FL_NORMAL_SIZE
@item @code{FL_NORMAL_SIZE}
@tab 12pt
@anchor{FL_MEDIUM_SIZE}
@tindex FL_MEDIUM_SIZE
@item @code{FL_MEDIUM_SIZE}
@tab 14pt
@anchor{FL_LARGE_SIZE}
@tindex FL_LARGE_SIZE
@item @code{FL_LARGE_SIZE}
@tab 18pt
@anchor{FL_HUGE_SIZE}
@tindex FL_HUGE_SIZE
@item @code{FL_HUGE_SIZE}
@tab 24pt
@end multitable

@ifhtml
@center @image{images/fontsize}
@end ifhtml
@ifnothtml
@center @image{images/fontsize,6cm}
@end ifnothtml


Labels can be drawn in many different font styles. The style of the
label can be controlled with the routine
@example
void fl_set_object_lstyle(FL_OBJECT *obj, int lstyle);
@end example
@noindent
The default font for the Forms Library is Helvetica at 10pt.

Additional styles are available:
@multitable @columnfractions 0.5 0.5
@anchor{FL_NORMAL_STYLE}
@tindex FL_NORMAL_STYLE
@item @code{FL_NORMAL_STYLE}
@tab Normal text
@anchor{FL_BOLD_STYLE}
@tindex FL_BOLD_STYLE
@item @code{FL_BOLD_STYLE}
@tab Boldface text
@anchor{FL_ITALIC_STYLE}
@tindex FL_ITALIC_STYLE
@item @code{FL_ITALIC_STYLE}
@tab Guess what
@anchor{FL_BOLDITALIC_STYLE}
@tindex FL_BOLDITALIC_STYLE
@item @code{FL_BOLDITALIC_STYLE}
@tab BoldItalic
@anchor{FL_FIXED_STYLE}
@tindex FL_FIXED_STYLE
@item @code{FL_FIXED_STYLE}
@tab Fixed width (good for tables)
@anchor{FL_FIXEDBOLD_STYLE}
@tindex FL_FIXEDBOLD_STYLE
@item @code{FL_FIXEDBOLD_STYLE}
@tab 
@anchor{FL_FIXEDITALIC_STYLE}
@tindex FL_FIXEDITALIC_STYLE
@item @code{FL_FIXEDITALIC_STYLE}
@tab 
@anchor{FL_FIXEDBOLDITALIC_STYLE}
@tindex FL_FIXEDBOLDITALIC_STYLE
@item @code{FL_FIXEDBOLDITALIC_STYLE}
@tab 
@anchor{FL_TIMES_STYLE}
@tindex FL_TIMES_STYLE
@item @code{FL_TIMES_STYLE}
@tab Times-Roman like font
@anchor{FL_TIMESBOLD_STYLE FL}
@tindex FL_TIMESBOLD_STYLE FL
@item @code{FL_TIMESBOLD_STYLE FL}
@tab 
@anchor{FL_TIMESITALIC_STYLE}
@tindex FL_TIMESITALIC_STYLE
@item @code{FL_TIMESITALIC_STYLE}
@tab 
@anchor{FL_TIMESBOLDITALIC_STYLE}
@tindex FL_TIMESBOLDITALIC_STYLE
@item @code{FL_TIMESBOLDITALIC_STYLE}
@tab 
@anchor{FL_SHADOW_STYLE}
@tindex FL_SHADOW_STYLE
@item @code{FL_SHADOW_STYLE}
@tab Text casting a shadow
@anchor{FL_ENGRAVED_STYLE}
@tindex FL_ENGRAVED_STYLE
@item @code{FL_ENGRAVED_STYLE}
@tab Text engraved into the form
@anchor{FL_EMBOSSED_STYLE}
@tindex FL_EMBOSSED_STYLE
@item @code{FL_EMBOSSED_STYLE}
@tab Text standing out
@end multitable
The last three styles are special in that they are modifiers, i.e.,
they do not cause font changes themselves, they only modify the
appearance of the font already active. E.g., to get a bold engraved
text, set @code{lstyle} to @code{FL_BOLD_STYLE|FL_ENGRAVED_STYLE}.

Other styles correspond to the first 12 fonts. The package, however, can
handle up to 48 different fonts. The first 16 (numbers 0-15) have been
pre-defined. The following table gives their names:
@example
 0 helvetica-medium-r
 1 helvetica-bold-r
 2 helvetica-medium-o
 3 helvetica-bold-o
 4 courier-medium-r
 5 courier-bold-r
 6 courier-medium-o
 7 courier-bold-o
 8 times-medium-r
 9 times-bold-r
10 times-medium-o
11 times-bold-o
12 charter-medium-r
13 charter-bold-r
14 charter-medium-i
15 Symbol
@end example

The other 32 fonts (numbers 16-47) can be filled in by the application
program. Actually, the application program can also change the first 16
fonts if required (e.g., to force a particular resolution). To change a
font for the the entire application, use the following routine:
@example
int fl_set_font_name(int index, const char *name);
@end example
where @code{index} is the number of the font (between 0 and 47) and
@code{name} should be a valid font name (with the exception of the size
field). If you are defining a completely different font family
starting at index @code{k}, it's a good idea to define
@code{k + FL_BOLD_STYLE} to be the corresponding bold font in the
family , and @code{k + FL_ITALIC_STYLE} the corresponding italic font
in the family (so object like browser can obtain correct style when
switching font styles):
@example
#define Pretty       30
#define PrettyBold   (Pretty + FL_BOLD_STYLE)
#define PrettyItalic (Pretty + FL_ITALIC_STYLE)

fl_set_font_name(Pretty, fontname);
fl_set_font_name(PrettyBold, boldfontname);
fl_set_font_name(PrettyItalic, italicfontname);
...
fl_set_object_lstyle(obj, PrettyBold);
@end example
The function returns a negative value if the requested font is invalid
or otherwise can't be loaded. Note however, if this routine is called
before @code{@ref{fl_initialize()}}, it will return 0, but may fail later if
the font name is not valid. To change the default font
(helvetica-medium), a program should change font @code{FL_NORMAL_STYLE}.

If a font name in XLFD is given, a question mark
(@code{?}) in the point size position informs
the Forms Library that variable size will be requested later. It is
preferable that the complete XLFD name (i.e., with 14 dashes and
possibly wildcards) be given because a complete name has the advantage
that the font may be re-scalable if scalable fonts are available. This
means that although both
@example
"-*-helvetica-medium-r-*-*-*-?-*-*-*-*-*-*"
"-*-helvetica-medium-r-*-*-*-?-*-*"
@end example
@noindent
are valid font names, the first form may be re-scalable while the the
second is not. To obtain the actual built-in font names, use the
following function
@example
int fl_enumerate_fonts(void (*cb)(const char *f), int shortform);
@end example
where @code{cb} is a callback function that gets called once for every
built-in font name. The font name is passed to the callback function as
the string pointer parameter while @code{shortform} selects if a short
form of the name should be used.

XForms only specifies the absolutely needed parts of the font names, and
assumes the font path is set so that the server always chooses the most
optimal fonts for the system. If this is not true, you can use
@code{@ref{fl_set_font_name()}} to select the exact
font you want. In general, this is not recommended if your application
is to be run/displayed on different servers.

See @file{fonts.c} for a demonstration of all the built-in font styles
available.

You can change the alignment of the label with respect to the bounding
box of the object. For this you use the routine
@example
void fl_set_object_lalign(FL_OBJECT *obj, int align);
@end example

The following possibilities exist:
@multitable @columnfractions 0.3 0.7
@anchor{FL_ALIGN_LEFT}
@tindex FL_ALIGN_LEFT
@item @code{FL_ALIGN_LEFT}
@tab To the left of the box.
@anchor{FL_ALIGN_RIGHT}
@tindex FL_ALIGN_RIGHT
@item @code{FL_ALIGN_RIGHT}
@tab To the right of the box.
@anchor{FL_ALIGN_TOP}
@tindex FL_ALIGN_TOP
@item @code{FL_ALIGN_TOP}
@tab To the top of the box.
@anchor{FL_ALIGN_BOTTOM}
@tindex FL_ALIGN_BOTTOM
@item @code{FL_ALIGN_BOTTOM}
@tab To the bottom of the box.
@anchor{FL_ALIGN_CENTER}
@tindex FL_ALIGN_CENTER
@item @code{FL_ALIGN_CENTER}
@tab In the middle of the box.
@anchor{FL_ALIGN_RIGHT_BOTTOM}
@tindex FL_ALIGN_RIGHT_BOTTOM
@item @code{FL_ALIGN_RIGHT_BOTTOM}
@tab To the right and bottom of the box.
@anchor{FL_ALIGN_LEFT_BOTTOM}
@tindex FL_ALIGN_LEFT_BOTTOM
@item @code{FL_ALIGN_LEFT_BOTTOM}
@tab To the left and bottom of the box.
@anchor{FL_ALIGN_RIGHT_TOP}
@tindex FL_ALIGN_RIGHT_TOP
@item @code{FL_ALIGN_RIGHT_TOP}
@tab To the right and top of the box.
@anchor{FL_ALIGN_LEFT_TOP}
@tindex FL_ALIGN_LEFT_TOP
@item @code{FL_ALIGN_LEFT_TOP}
@tab To the left and top of the box.
@end multitable

Normally, all the alignment requests place the text outside the box,
except for
@anchor{FL_ALIGN_INSIDE}
@tindex FL_ALIGN_INSIDE
@code{FL_ALIGN_CENTER}. This can be changed by using a
special mask, @code{FL_ALIGN_INSIDE}, to request alignments that place
the text inside the box. This works for most of the objects in the
library but not for all. For sliders, inputs and some others, placing
the label inside the box simply does not make sense. In these cases,
inside request is ignored. See the demo program @file{lalign.c} for an
example use of @code{FL_ALIGN_INSIDE}.

Finally, the routine
@findex fl_set_object_label()
@example
void fl_set_object_label(FL_OBJECT *obj, const char *label);
@end example
changes the label of a given object. An internal copy of the parameter
@code{label} is made. As mentioned earlier, newline (@code{\n}) can be
embedded in the label to generate multiple lines. By embedding
@code{<Ctrl>H} (@code{\010}) in the label, the entire label or one of
the characters in the label can be underlined. The function
@findex fl_get_object_label()
@example
const char * fl_get_object_label(FL_OBJECT *obj);
@end example
@noindent
returns the label string.


@node Tool Tips
@subsection Tool Tips

As will be seen later, an object can be decorated by icons instead of
labels. For this kind of object, it is helpful to show a text string
that explains the function the object controls under appropriate
conditions. Forms Library elected to show the message after the mouse
enters the object for about 600 milli-seconds. The text is removed when
the mouse leaves the object or when the mouse is pressed.

To set the text, use the following routine
@findex fl_set_object_helper()
@example
void fl_set_object_helper(FL_OBJECT *obj, const char *helpmsg);
@end example
where @code{helpmsg} is a text string (with possible embedded newlines
in it) that will be shown when the mouse enters the object, after about
a 600 milli-second delay. A internal copy of the string is made.

The boxtype, color and font for the message display can be customized
further using the following routines
@example
void fl_set_tooltip_boxtype(int boxtype);
void fl_set_tooltip_color(FL_COLOR textcolor, FL_COLOR background);
void fl_set_tooltip_font(int style, int size);
void fl_set_tooltip_lalign(int align);
@end example
@noindent
where @code{boxtype} is the backface of the form that displays the text.
The default is @code{FL_BORDER_BOX}. @code{textcolor} and
@code{background} specify the colors of the text string and the
backface. The defaults for these are @code{FL_BLACK} and
@code{FL_YELLOW} respectively. The @code{style} and @code{size}
parameters are the font style and size of the text. @code{align} is the
alignment of the text string with respective to the box. The default is
@code{FL_ALIGN_LEFT | FL_ALIGN_INSIDE} .


@node Redrawing
@subsection Redrawing Objects

A word of caution is required. It is possible to change the attributes
of an object at any time. But when the form is already displayed on the
screen some care has to be taken. Whenever attributes change the
system redraws the object. This is fine when drawing the object erases
the old one but this is not always the case. For example, when placing
labels outside the box (not using @code{FL_ALIGN_CENTER}) they are not
correctly erased. It is always possible to force the system to redraw an
object using
@example
void fl_redraw_object(FL_OBJECT *obj);
@end example
When the object is a group it redraws the complete group. To redraw an
entire form, use
@example
void fl_redraw_form(FL_FORM *form);
@end example
Use of these routines is normally not necessary and should be kept to an
absolute minimum.


@node Changing Many Attributes
@subsection Changing Many Attributes

Whenever you change an attribute of an object in a visible form the
object is redrawn immediately to make the change visible. This can be
undesirable when you change a number of attributes of the same object.
You only want the changed object to be drawn after the last change.
Drawing it after each change will give a flickering effect on the
screen. This gets even worse when you e.g. want to hide a few objects.
After each object you hide the entire form is redrawn. In addition to
the flickering, it is also time consuming. Thus it is more efficient to
tell the library to temporarily not redraw the form while changes are
being made. This can be done by "freezing" the form. While a form is
being frozen it is not redrawn, all changes made are instead buffered
internally. Only when you unfreeze the form, all changes made in the
meantime are drawn at once. For freezing and unfreezing two calls exist:
@example
void fl_freeze_form(FL_FORM *form);
@end example
@noindent
and
@example
void fl_unfreeze_form(FL_FORM *form);
@end example
@noindent
It is a good practice to place multiple changes to the contents of a
form always between calls to these two procedures. Further, it is better
to complete modifying the attributes of one object before starting work
on the next.


@node Symbols
@subsection Symbols

Rather than textual labels, it is possible to place symbols like arrows
etc. on objects. This is done in the following way:

When the label starts with the character @code{@@} no label is drawn but
a particular symbol is drawn instead@footnote{If you want a literal
@code{@@} character as the first character, escape it with another
@code{@@} character.}. The rest of the label string indicates the
symbol. A number of pre-defined symbols are available:
@multitable   @columnfractions 0.2 0.8
@item @code{->}
@tab Normal arrow pointing to the right.
@item @code{<-}
@tab Normal arrow pointing to the left.
@item @code{>}
@tab Triangular arrow pointing to the right.
@item @code{<}
@tab Triangular arrow pointing to the left.
@item @code{>>}
@tab Double triangle pointing to the right.
@item @code{<<}
@tab Double triangle pointing to the left.
@item @code{<->}
@tab Arrow pointing left and right.
@item @code{->|}
@tab A normal arrow with a bar at the end.
@item @code{>|}
@tab A triangular arrow with a bar at the end.
@item @code{-->}
@tab A thin arrow pointing to the right.
@item @code{=}
@tab Three embossed lines.
@item @code{arrow}
@tab Same as @code{-->}.
@item @code{returnarrow}
@tab @code{<Return>} key symbol.
@item @code{square}
@tab A square.
@item @code{circle}
@tab A circle.
@item @code{line}
@tab A horizontal line.
@item @code{plus}
@tab A plus sign (can be rotated to get a cross).
@item @code{UpLine}
@tab An embossed line.
@item @code{DnLine}
@tab An engraved line.
@item @code{UpArrow}
@tab An embossed arrow.
@item @code{DnArrow}
@tab An engraved arrow.
@end multitable
@noindent
See Fig. 3.6 for how some of them look. See also @file{symbols.c}.

It is possible to put the symbols in different orientations. When the
symbol name is preceded by a digit 1-9 (not 5) it is rotated like on the
numerical keypad, i.e., 6 indicates no rotation, 9 a rotation of 45
degrees counter-clockwise, 8 a rotation of 90 degrees, etc. Hence the
order is 6, 9, 8, 7, 4, 1, 2, 3. (Just think of the keypad as consisting
of arrow keys.) So to get an arrow that is pointing to the left top use
a label @code{@@7->}. To put the symbol in other orientations, put a 0
after the @code{@@}, followed by three digits that indicate the angle
(counter-clockwise). E.g. to draw an arrow at an angle of 30 degrees use
label @code{@@0030->}.

The symbol will be scaled to fit in the bounding box. When the bounding
box is not square, scaling in the x- and y-directions will be different.
If keeping the aspect ratio is desired, put a sharp (@code{#})
immediately after the @. E.g., @code{@@#9->}.

Two additional prefixes, @code{+} and @code{-}, followed by a single
digit, can be used to make small symbol size adjustment. These prefixes
must be either immediately after @code{@@} or follow @code{#}. The +
indicates increase the symbol size and - indicates decrease the symbol
size. The digit following the prefixes indicates the increment
(decrement) in pixels. For example, to draw a circle that is 3 pixels
smaller in radius than the default size, use @code{@@-3square}.

@ifhtml
@center @image{images/symbols}
@end ifhtml
@ifnothtml
@center @image{images/symbols}
@end ifnothtml

In addition to using symbols as object labels, symbols can also be drawn
directly using
@findex fl_draw_symbol()
@anchor{fl_draw_symbol()}
@example
int fl_draw_symbol(const char *symbolname, FL_Coord x, FL_Coord y,
                   FL_Coord w, FL_Coord h, FL_Color col);
@end example
@noindent
(the function returns @code{1} on success and @code{0} on failure
when the symbol name isn't valid) or indirectly via
@code{@ref{fl_drw_text()}}. The application program can also add
symbols to the system which it can then use to display symbols on
objects that are not provided by the Forms Library. To add
a symbol, use the call
@findex fl_add_symbol()
@anchor{fl_add_symbol()}
@example
int fl_add_symbol(const char *name, void (*drawit)(),int sc);
@end example
@noindent
@code{name} is the name under which the symbol should be known (at most
15 characters), without the leading @code{@@}. @code{drawit()} is the
drawing routine that draws the symbol. @code{sc} is reserved and
currently has no meaning. Simply setting it to zero would do.

The routine @code{drawit()} should have the form
@example
void drawit(FL_Coord x, FL_Coord y, FL_Coord w, FL_Coord h,
            int angle, FL_COLOR col);
@end example
@noindent
@code{col} is the color in which to draw the symbol. This is the label
color that can be provided and changed by the application program. The
routine should draw the symbol centered inside the box by @code{x},
@code{y}, @code{w}, @code{h} and rotated from its natural position by
@code{angle} degrees. The draw function can call all types of drawing
routines, including @code{@ref{fl_draw_symbol()}}.

If the new symbol name is the same as one of the built-ins, the new
definition overrides the built-in. Note the the new symbol does not have
to be vector graphics, you can use pixmap or whatever in the drawing
function.

The symbol handling routines really should be viewed as a means of
associating an arbitrary piece of text (the label) with arbitrary
graphics, application of which can be quite pleasant given the right
tasks.


@node Adding and Deleting
@section Adding and Deleting Objects

In some situations you might want to add an object to an existing form.
This can be done using the call
@example
FL_FORM *fl_addto_form(FL_FORM *form);
@end example
@noindent
After this call you can continue adding objects to the form with the
usual functions for adding objects like @code{@ref{fl_add_button()}}
etc. To stop adding objects to the form again use
@code{@ref{fl_end_form()}}. It is possible to add objects to forms
that are being displayed, but this is not always a good idea because
not everything behaves well (e.g.@: strange things might happen when a
group is started but not yet finished).

To delete an object from a form simply use
@example
void fl_delete_object(FL_OBJECT *obj);
@end example

It deletes the object from the form it currently belongs to and also
from a group it may belong to. The argument can also be the
pseudo-object starting a group (i.e.@: the return value of
@code{@ref{fl_bgn_group()}}) in which case the whole group of objects
will be removed from the form.

The object remains available (except if it's an object that marks the
start or end of a group) and can be added again to the same or another
form later using
@findex fl_add_object()
@anchor{fl_add_object()}
@example
void fl_add_object(FL_FORM *form, FL_OBJECT *obj);
@end example
@noindent
Normally, this function is used in object classes to add a newly
created object to a form. It may not be used for objects representing
the start or end of a group.


@node Freeing Objects
@section Freeing Objects

If the application program does not need an object anymore, it can free
the memory used by the object using the call
@example
void fl_free_object(FL_OBJECT *obj);
@end example
@noindent
After this the object can no longer be used. If you hadn't deleted the
object from the form it did belong to before this will happen
automatically.

To free the memory used by an entire form use the call
@example
void fl_free_form(FL_FORM *form);
@end example
@noindent
This will delete and free all the objects on the form and the form
itself. A freed form may not be referenced anymore.