File: libTw.txt

package info (click to toggle)
twin 0.4.0-4
  • links: PTS
  • area: main
  • in suites: woody
  • size: 3,804 kB
  • ctags: 23,904
  • sloc: ansic: 61,860; cpp: 1,023; makefile: 777; sh: 552; lex: 302; yacc: 231
file content (591 lines) | stat: -rw-r--r-- 21,795 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

				libTw 2.0.0 tutorial


libTw is the library that talks to `twin' server. Since the parallel between
X11 server and twin server comes out so often, we could say libTw is the
equivalent of libX11.

One thing that has been asked many times is porting applications from ncurses
to libTw. Unlickily, things are not so straightforward as the two libraries
have quite different approaches: libTw is a network transparent, multi window,
multi headed, event driven, mouse aware library, while ncurses is full-screen,
single-headed library without mouse support and without events.
If all you want is to have a ncurses program run inside a SINGLE twin window,
you could just let it run unmodified inside twterm, or, if you like hacking
programs, you could substitute printf(), write(), etc. calls to standard output
with TwWriteAsciiWindow() and read() from standard input with TwReadMsg().
Yet, what you will get will still be a program displaying in a single window:
converting an application that uses ncurses windows to use multiple libTw
windows is usually much more difficult as with libTw any open window can
generate events at any time, while with ncurses the "focused" window that
generates events (user input) is decided by the application.


				   the libTw API
				   

1. Types and defines

   To access libTw functions, you need to

   #include <Tw/Tw.h>

   This include file defines various data types used by all libTw functions.
   The types, together with their usual definition, are:

   typedef   signed char	 num;
   typedef unsigned char	byte;
   typedef   signed short	 dat;
   typedef unsigned short	udat;
   typedef   signed int		ldat;
   typedef unsigned int        uldat;

   Anyway, except for `num' and `byte' (which are always 1 byte long)
   you must NEVER assume to know a type's size as it may change between
   releases of libTw. You should instead use either sizeof(<type>)
   or the defines

   MINDAT
   MAXDAT
   MAXUDAT
   MINLDAT
   MAXLDAT
   MAXULDAT

   for the minimum and maximum values of the various types.

   Other defines coming from the include are:

   TW_NOID : a numeric value meaning `no object'. Used to indicate
          an invalid window, screen, msgport, etc. (see below)

   TW_NOFD : a negative number meaning `no file descriptor' (-1)

   FALSE, TRUE : the obvious meaning

   TW_INET_PORT: the base TCP port used by libTw/twin server (7754)

   TW_SMALLBUFF   : the size for a small data buffer
   TW_BIGBUFF     : the size for a bigger data buffer


   To represent colors, there are some dedicated types and defines:

   hwfont;
   hwcol;
   hwattr;

   Don't assume you know the sizes of these types, always use
   sizeof(<type>) if you need it.
   
   hwfont can hold a single character. This means it surely can contain
   an ASCII character, but depending on libTw configuration, it may even
   contain a UNICODE character.
   
   hwcol can hold a single foreground color + background color combination
   This is loosely based on VGA colors, with 8 different colors

   BLACK, BLUE, GREEN, CYAN, RED, MAGENTA, YELLOW, WHITE
   
   and a special HIGH flag. The maximum possible color value is MAXCOL.

   to convert between this representation and ANSI colors, there are two macros:
   
   ANSI2VGA(col) and VGA2ANSI(col)

   To compose and decompose a hwcol from fg/bg pair, you have the macros
   
   FG(fg), BG(bg) and COL(fg,bg) to compose a hwcol
      COL(fg,bg) is simply FG(fg)|BG(bg)
   COLBG(col) and COLFG(col) to decompose it

   To compose and decompose a hwattr from hwcol/hwfont pair, you have the macros

   HWATTR(col,font) to compose and HWCOL(attr), HWFONT(attr) to decompose.
   
   Examples:
   a blue `f' on white background is HWATTR( COL(BLUE,WHITE), 'f')
   a cyan foreground on red background is COL(CYAN,RED)
   and so on...

   WARNING:
      HWFONT(), HWCOL() and HWATTR() are macros that can evaluate their
      arguments more than once. Don't use arguments that have side effects
      (like increments) inside them.
      For example, this causes unpredictable results because of the `h++'
      increment inside the HWATTR() macro:
      
      hwattr a[2];
      hwfont buf[2], *h = buf;
      a[0] = HWATTR(COL(WHITE,BLACK), *h++);
      a[1] = HWATTR(COL(WHITE,BLACK), *h++);
     

   (types for time intervals: TODO)


   Mouse events masks
   HOLD_LEFT, HOLD_MIDDLE, HOLD_RIGHT, HOLD_ANY

   PRESS_LEFT, PRESS_RIGHT, PRESS_MIDDLE, PRESS_ANY

   #define DOWN_LEFT	(HOLD_LEFT|PRESS_LEFT)
   #define DOWN_RIGHT	(HOLD_RIGHT|PRESS_RIGHT)
   #define DOWN_MIDDLE	(HOLD_MIDDLE|PRESS_MIDDLE)
   #define DOWN_ANY	(HOLD_ANY|PRESS_ANY)

   RELEASE_LEFT, RELEASE_RIGHT, RELEASE_MIDDLE, RELEASE_ANY

   DRAG_MOUSE

   MOTION_MOUSE
   
   #define ANY_ACTION_MOUSE	(PRESS_ANY | RELEASE_ANY | DRAG_MOUSE)

   isPRESS(code), isDRAG(code), isRELEASE(code), isMOTION(code)




   Finally, the types for the various libTw objects:
   
   tobj (generic), twidget (generic), tgadget, trow, twindow,
   tmenuitem, tmenu, tscreen, tmsgport

   The following are instead pointers to various structures:

   tevent_common, tevent_keyboard, tevent_keyboard, tevent_mouse,
   tevent_display, tevent_window, tevent_gadget, tevent_menu,
   tevent_selection, tevent_selectionnotify, tevent_selectionrequest,
   tevent_any

   tmsg
   
   /* Msg ->Type : */
   TW_MSG_DISPLAY, TW_MSG_WINDOW_KEY, TW_MSG_WINDOW_MOUSE,
   TW_MSG_WINDOW_CHANGE, TW_MSG_WINDOW_GADGET, TW_MSG_MENU_ROW	
   TW_MSG_SELECTION, TW_MSG_SELECTIONNOTIFY, TW_MSG_SELECTIONREQUEST
   TW_MSG_SELECTIONCLEAR


   tdisplay


   /* Gadget Flags : */
   TW_GADGETFL_DISABLED, TW_GADGETFL_TOGGLE

   /* Row Flags : */
   TW_ROW_INACTIVE, TW_ROW_ACTIVE, TW_ROW_IGNORE

   /* Window Attrib : */
   TW_WINDOW_WANT_KEYS, TW_WINDOW_WANT_MOUSE, TW_WINDOW_WANT_MOUSE_MOTION
   TW_WINDOW_WANT_CHANGES, TW_WINDOW_DRAG, TW_WINDOW_RESIZE, TW_WINDOW_CLOSE
   TW_WINDOW_ROLLED_UP, TW_WINDOW_X_BAR, TW_WINDOW_Y_BAR

   /* Window Flags: */
   TW_WINDOWFL_USEROWS, TW_WINDOWFL_USECONTENTS, TW_WINDOWFL_USEEXPOSE
   TW_WINDOWFL_USEFILL, TW_WINDOWFL_CURSOR_ON, TW_WINDOWFL_MENU,
   TW_WINDOWFL_DISABLED, TW_WINDOWFL_BORDERLESS,
   TW_WINDOWFL_ROWS_INSERT, TW_WINDOWFL_ROWS_DEFCOL, TW_WINDOWFL_ROWS_SELCURRENT

   /* Window CursorType : */
   TW_NOCURSOR, TW_LINECURSOR, TW_SOLIDCURSOR

   /* Buttons on window borders: */
   TW_MAX_BUTTONS



2. Functions

   When no connections are open, you can call

   byte Tw_CheckMagic(byte Magic[]);
   
   to ensure sizeof() of the various types are the same in the client
   and in the library, and you can call
   
   void Tw_ConfigMalloc(void *(*my_malloc)(size_t),
   			void *(*my_realloc)(void *, size_t),
			void  (*my_free)(void *));
		     
   to set the functions
   
   extern void *(*Tw_AllocMem)(size_t);
   extern void *(*Tw_ReAllocMem)(void *, size_t);
   extern void  (*Tw_FreeMem)(void *);
   extern byte *(*Tw_CloneStr)(byte *);
 
   to your custom malloc/free routines.

   To open a connection to a twin server, call (Tw_Display is optional)
   byte TwOpen(byte *Tw_Display);
     or
   tdisplay Tw_Open(byte *Tw_Display);
   
   To close,
   void TwClose(void);
     or
   void Tw_Close(tdisplay TwD);
   
   The file descriptor of a connection is returned by
   int  TwConnectionFd(void);
     or
   int  Tw_ConnectionFd(tdisplay TwD);


   As you may already have noticed, the functions starting with "Tw_"
   are multiheaded, i.e. can handle multiple tdisplay:s
   If all you want is to talk to a _single_ display, you can use the functions
   starting with "Tw" only (they are actually macros) and save a little typing.
   In case you need it, the "Tw" functions use the tdisplay Tw_DefaultD, so for
   example, TwConnectionFd is defined as
   #define TwConnectionFd()	Tw_ConnectionFd(Tw_DefaultD)

   /* the following four functions return FALSE only after libTw has paniced */
   /* flush output buffer.
    * if not all data can be written immediately, block, then write data when
    * output becomes possible again. return only after all data has been written
    */
   byte    TwFlush(void);
   byte    Tw_Flush(tdisplay TwD);
   
   /* flush output buffer and wait for all replies from server */
   byte    TwSync(void);
   byte    Tw_Sync(tdisplay TwD);

   /* did the library panic on that display? */
   byte    TwInPanic(void);
   byte    Tw_InPanic(tdisplay TwD);
   
  /*
   * after a panic (i.e. a fatal error), the only useful thing
   * you can do is to Tw_Close() the display and, if you need,
   * to Tw_Open() again.
   */
   
  /*
   * try to write to the underlying socket.
   * if not all data could be written immediately, write as much as possible,
   * keep the rest queued, then return.
   * 
   * returns FALSE only after libTw has paniced,
   * returns TRUE if all data was written.
   * returns TRUE+TRUE if not all data could be written.
   */
   byte    TwTimidFlush(void);
   byte    Tw_TimidFlush(tdisplay TwD);

  /*
   * This is the function you must call to get a Msg from the server.
   * If Wait is TRUE  and no Msg is available, it flushes output queue
   *    (with Tw_Flush()) then waits until a Msg arrives.
   * If Wait is FALSE and no Msg is available, it flushes output queue
   *    non-blocking (with Tw_TimidFlush()), then it tries non-blocking
   *    to receive more Msgs.
   * 
   * In both cases, if there are already received Msgs they are returned
   * without waiting.
   */
  tmsg TwReadMsg(byte Wait);
  tmsg Tw_ReadMsg(tdisplay TwD, byte Wait);

  /*
   * this is just like Tw_ReadMsg(), but returns a Tw_AllocMem() copy
   * of the message, to avoid concurrency problems with other threads.
   * You must Tw_FreeMem() it when done!
   */
   tmsg TwReadMsg_Clone(byte Wait);
   tmsg Tw_ReadMsg_Clone(tdisplay TwD, byte Wait);
   
  /*
   * This is the function you must call to check if there are pending Msgs.
   * There may be messages to process even if there's nothig to read on
   * (Fd = Tw_ConnectionFd()) as messages can be received also during any
   * blocking function call like Tw_Sync(), Tw_CreateWindow(), etc.
   * Look at the twterm sources for an example.
   * 
   * This returns the first pending Msg, or (tmsg)0 if none is available
   * and none can be received non-blocking.
   */
   tmsg TwPeekMsg(void);
   tmsg Tw_PeekMsg(tdisplay TwD);

  /*
   *   <*>  B I G    W A R N I N G  <*>
   * 
   * Tw_PeekMsg() and Tw_ReadMsg() return a (tmsg) pointer to data
   * in a static buffer. The pointer becomes invalid after a call
   * to any function of libTw.h with non-void return value,
   * so that it sends something to the server and waits for the server
   * to send the return value (i.e. it is blocking),
   * in particular any of the following:
   * (but calling one of these with an argument pointing to data
   * inside a tmsg is allowed)
   * 
   * Tw_Sync();
   * Tw_PeekMsg();
   * Tw_ReadMsg();
   * Tw_CreateGadget();
   * Tw_SearchGadget();
   * Tw_CreateWindow();
   * Tw_Create4MenuWindow();
   * Tw_Create4MenuMenuItem();
   * Tw_CreateMsgPort();
   * Tw_CreateMenu();
   * Tw_FirstScreen();
   * Tw_FirstMsgPort();
   * [...]
   * 
   * If you are using threads, or just have a doubt that your code might
   * reference the message returned Tw_PeekMsg() or Tw_ReadMsg()
   * after a call to one of the above functions, use Tw_ReadMsg_Clone() :
   * it's just like Tw_ReadMsg(), except that it returns a Tw_AllocMem() copy
   * of the message, that you can use as long as you wish. Just remember to
   * Tw_FreeMem() it when done!
   * 
   * 
   * Other important notes:
   * 1. Only ONE MsgPort can exists at max on each connection.
   * 2. Tw_DeleteMsgPort() calls Tw_DeleteMenu() on all menus created by the client
   *    and Tw_DeleteWidget/Gadget/Window() on all gadgets/widgets/windows created by the client.
   * 3. Tw_DeleteMenu() calls Tw_UnMapWindow() on all windows which use that menu.
   * 4. Tw_DeleteWidget[/Gadget/Window]() calls Tw_UnMapWidget() on all sub-gadgets/widgets/windows
   *    of that widget, does NOT call Tw_DeleteWidget[/Gadget/Window]() recursively on them!
   *    If you wish to delete a widget and all sub-widgets inside it,
   *    use Tw_RecursiveDeleteWidget[/Gadget/Window]()
   * 
   * also, if you exit() from your program without calling Tw_Flush(), Tw_Sync() or Tw_Close(),
   * pending data will *NOT* be sent to the server.
   */
   
tmsgport Tw_CreateMsgPort(tdisplay TwD, byte NameLen, byte *ProgramName, time_t PauseSec, frac_t PauseFraction, byte WakeUp);
/* WakeUp: */
#define TW_TIMER_ALWAYS	((byte)1)
#define TW_TIMER_ONCE	((byte)2)
void	Tw_DeleteMsgPort(tdisplay TwD, tmsgport MsgPort);


tgadget Tw_CreateGadget(tdisplay TwD, twidget Parent, dat Left, dat Up,
		       hwcol ColText, hwcol ColTextSelect, hwcol ColTextDisabled, hwcol ColTextSelectDisabled,
		       uldat Attrib, uldat Flags, dat XWidth, dat YWidth);
void	Tw_DeleteGadget(tdisplay TwD, tgadget Gadget);
tgadget Tw_SearchGadget(tdisplay TwD, twindow Window, dat i, dat j);
tgadget Tw_CreateButtonGadget(tdisplay TwD, twindow Window,
twindow Tw_CreateButtonGadget(tdisplay TwD, twidget Parent, dat XWidth, dat YWidth, TW_CONST byte *Title,
			      uldat Flags, udat Code, hwcol BgCol, hwcol Col, hwcol ColDisabled,
			      dat Left, dat Up);

void	Tw_Create4MenuRow(tdisplay TwD, twindow Window, udat Code, byte FlagActive, uldat TextLen, byte *Text);
#define Tw_Row4Menu Tw_Create4MenuRow

twindow Tw_CreateWindow(tdisplay TwD, dat NameLen, TW_CONST byte *Name, TW_CONST hwcol *ColName, tmenu Menu,
		       hwcol ColText, uldat cursorType, uldat Attrib, uldat Flags,
		       dat XWidth, dat YWidth, dat ScrollBackLines);
void	Tw_DeleteWindow(tdisplay TwD, twindow Window);
twindow Tw_Create4MenuWindow(tdisplay TwD, tmenu Menu);
#define Tw_Win4Menu Tw_Create4MenuWindow
void	Tw_MapWindow(tdisplay TwD, twindow Window, tscreen Screen);
void	Tw_UnMapWindow(tdisplay TwD, twindow Window);
void	Tw_WriteAsciiWindow(tdisplay TwD, twindow Window, uldat AsciiLen, TW_CONST byte *AsciiSeq);
void	Tw_WriteTextWindow(tdisplay TwD, twindow Window, ldat AsciiLen, TW_CONST byte *Text);
void	Tw_WriteUnicodeWindow(tdisplay TwD, twindow Window, ldat AsciiLen, TW_CONST udat *UnicodeSeq);
void    Tw_WriteHWAttrWindow(tdisplay TwD, twindow Window, udat x, udat y, uldat Len, TW_CONST hwattr *Attr);
void	Tw_WriteRowWindow(tdisplay TwD, twindow Window, uldat Len, byte *Text);
void	Tw_SetColTextWindow(tdisplay TwD, twindow Window, hwcol ColText);
void	Tw_SetColorsWindow(tdisplay TwD, twindow Window, udat Bitmap, hwcol ColGadgets, hwcol ColArrows, hwcol ColBars, hwcol ColTabs,
			  hwcol ColBorder, hwcol ColText, hwcol ColSelect, hwcol ColDisabled, hwcol ColSelectDisabled);
void	Tw_ConfigureWindow(tdisplay TwD, twindow Window, byte Bitmap, dat Left, udat Up, udat MinXWidth, udat MinYWidth, udat MaxXWidth, udat MaxYWidth);
void	Tw_ResizeWindow(tdisplay TwD, twindow Window, udat XWidth, udat YWidth);
void	Tw_GotoXYWindow(tdisplay TwD, twindow Window, uldat X, uldat Y);
tgadget Tw_SearchGadgetWindow(tdisplay TwD, twindow Window, dat X, dat Y);

tmenuitem Tw_Create4MenuMenuItem(tdisplay TwD, tmenu Menu, twindow Window, byte Flags, udat NameLen, byte *Name);
#define   Tw_Item4Menu Tw_Create4MenuMenuItem
tmenuitem Tw_Create4MenuCommonMenuItem(tdisplay TwD, tmenu Menu);
#define   Tw_Item4MenuCommon Tw_Create4MenuCommonMenuItem
void	Tw_DeleteMenuItem(tdisplay TwD, tmenuitem MenuItem);

tmenu	Tw_CreateMenu(tdisplay TwD, tmsgport MsgPort, hwcol ColItem, hwcol ColSelect, hwcol ColDisabled,
		     hwcol ColSelectDisabled, hwcol ColShtCut, hwcol ColSelShtCut, byte FlagDefColInfo);
#define Tw_Grab	Tw_CreateMutex
void	Tw_SetInfoMenu(tdisplay TwD, tmenu Menu, byte Flags, uldat Len, byte *Text, hwcol *ColText);
#define Tw_Info4Menu Tw_SetInfoMenu
void	Tw_DeleteMenu(tdisplay TwD, tmenu Menu);


void	Tw_BgImageScreen(tdisplay TwD, tscreen Screen, udat BgWidth, udat BgHeight, hwattr *BgImage);

tscreen	Tw_FirstScreen(tdisplay TwD);
twindow	Tw_FirstWindow(tdisplay TwD, tscreen Screen);
tgadget Tw_FirstGadget(tdisplay TwD, twindow Window);
tmsgport Tw_FirstMsgPort(tdisplay TwD);
tmenu    Tw_FirstMenu(tdisplay TwD, tmsgport MsgPort);
tmenuitem Tw_FirstMenuItem(tdisplay TwD, tmenu Menu);

tobj Tw_PrevObj(tdisplay TwD, tobj Obj);
tobj Tw_NextObj(tdisplay TwD, tobj Obj);
tobj Tw_ParentObj(tdisplay TwD, tobj Obj);

udat Tw_GetDisplayWidth(tdisplay TwD);
udat Tw_GetDisplayHeight(tdisplay TwD);

tmsg Tw_CreateMsg(tdisplay TwD, udat Type, udat Len);
void Tw_DeleteMsg(tdisplay TwD, tmsg Msg);
byte Tw_SendMsg(tdisplay TwD, tmsgport MsgPort, tmsg Msg);
void Tw_BlindSendMsg(tdisplay TwD, tmsgport MsgPort, tmsg Msg);


/*
 * Selection handling. This is very similar to X11:
 * 
 * if client <a> wants to know the contents of selection to paste it,
 * it must find who is the Selection owner (say <b>) and ask him:
 * 
 * Tw_RequestSelection(TwD, Tw_GetOwnerSelection(TwD), ReqPrivate);
 * 
 * ReqPrivate is some opaque data that client <a> may specify,
 * and it will be sent back later literally.
 * 
 * after a while, a TW_MSG_SELECTIONNOTIFY will arrive with all the
 * precious Selection data and also with ReqPrivate.
 * 
 * 
 * 
 * Now the other half of the story: What The Selection Owner Must Do.
 * (this is handled automagically by twin server if the client choosed
 * not to receive mouse events)
 * 
 * If the user just hilighted some data in a window of client <b>,
 * client <b> will want to become the Selection owner, so that other
 * clients may receive that data too. For this, client <b> must call
 * 
 * Tw_SetOwnerSelection(TwD, myMsgPort, TW_SEL_CURRENTTIME, TW_SEL_CURRENTTIME);
 * 
 * where myMsgPort is actually client <b> MsgPort. From now on, and until
 * client <b> receives a TW_MSG_SELECTIONCLEAR event, client <b> must
 * send its precious Selection to whoever asks for it: every time client <b>
 * receives a TW_MSG_SELECTIONREQUEST event from libTw, it must call
 * 
 * Tw_NotifySelection(TwD, Requestor, ReqPrivate, Magic, MIME, Len, Data);
 * 
 * where Requestor and ReqPrivate come from the TW_MSG_SELECTIONREQUEST event,
 * and the rest is the Selection data: its Magic type (usually TW_SEL_TEXTMAGIC),
 * its MIME type ("text/plain", or whatever looks appropriate),
 * its Len in bytes and finally, Data: a pointer to the actual data.
 * 
 * 
 * There is a last thing: how can client <a> know that the user
 * wants to paste the selection in one of its windows ?
 * If the client keeps track of mouse movement and buttons, it can figure
 * out by its own. Otherwise, twin automagically solves the problem sending
 * a TW_MSG_SELECTION to the client when it should paste the selection
 * in a window. Client should then call the first function said above,
 * 
 * Tw_RequestSelection(TwD, Tw_GetOwnerSelection(TwD), ReqPrivate);
 * 
 * and start the chain of communications just explained.
 * Once client <a> got the Selection, it must paste it in the window
 * in whatever way is appropriate for that window.
 * 
 * P.S. hint: a possible use for ReqPrivate is to store the window
 *            that client <a> must paste into.
 * 
 * Finally, the function prototypes:
 */
tobj Tw_GetOwnerSelection(tdisplay TwD);

void Tw_RequestSelection(tdisplay TwD, tobj Owner, uldat ReqPrivate);

void Tw_SetOwnerSelection(tdisplay TwD, tobj Owner, time_t Time, frac_t Frac);
#define TW_SEL_CURRENTTIME ((time_t)0)

void Tw_NotifySelection(tdisplay TwD, tobj Requestor, uldat ReqPrivate,
			uldat Magic, byte MIME[TW_MAX_MIMELEN], uldat Len, byte *Data);













   /*
    * a few string/memory related function macros:
    */
   
   #define TwLenStr(S) strlen(S)
   #define TwCmpStr(S1, S2) strcmp((S1), (S2))
   #define TwCopyStr(From,To) strcpy((To),(From))
   
   #define TwCopyMem(From, To, Size)	memcpy((To), (From), (size_t)(Size))
   #define TwMoveMem(From, To, Size)	memmove((To), (From), (size_t)(Size))
   #define TwWriteMem(Mem, Char, Size)	memset((Mem), (int)(Char), (size_t)(Size))
   #define TwCmpMem(m1, m2, Size)	memcmp((m1), (m2), (size_t)(Size))
   
   /*
    * the "Tw_" versions of the above ones exist, and have exactly the same
    * definition (no tdisplay argument here)
    */
   
   
   
   /*
    * Check if the server supports a function given its name
    * (without the Tw/Tw_ prefix)
    */
   uldat TwFindFunction(byte Len, byte *Name);
   uldat Tw_FindFunction(tdisplay TwD, byte Len, byte *Name);
   
   /*
    * Check if the server supports a list of functions given its pointers
    * (you must use the ones with Tw_ prefix as the other are macros)
    * The list must be NULL terminated.
    */
   byte  Tw_FindFunctions(tdisplay TwD, void *Function, ...);

   /*
    * enable gzip compression on the socket
    */
   byte TwEnableGzip(void);
   byte Tw_EnableGzip(tdisplay TwD);

   /*
    * disable gzip compression on the socket
    */
    byte TwDisableGzip(void);
    byte Tw_DisableGzip(tdisplay TwD);

   /*
    * these are reserved for the programs "twattach" and "twdisplay" :
    * manage attaching/detaching of display drivers inside twin core.
    */
    void TwNeedResizeDisplay(void);
    void Tw_NeedResizeDisplay(tdisplay TwD);
    
    void TwAttachHW(uldat len, byte *name, byte redirect);
    void Tw_AttachHW(tdisplay TwD, uldat len, byte *name, byte redirect);
    
    byte *TwAttachGetReply(uldat *len);
    byte *Tw_AttachGetReply(tdisplay TwD, uldat *len);
    
    void TwAttachConfirm(void);
    void Tw_AttachConfirm(tdisplay TwD);
    
    byte TwDetachHW(uldat len, byte *name);
    byte Tw_DetachHW(tdisplay TwD, uldat len, byte *name);


   /*
    * load a customizable translation table. "trans" points to a 128 byte
    * translation table for the ASCII codes 0x80 - 0xff
    */
    void TwSetFontTranslation(byte trans[0x80]);
    void Tw_SetFontTranslation(tdisplay TwD, byte trans[0x80]);