1 {: Pascal (Delphi/ Kylix) Interface unit for the smapi. Documentation comments
2 are taken from sqdev.prn, which is part of Scott Dudley's SQDEV200.zip archive. }
3
4 {: NOTE: Unfortunately it turned out that the structures that are passed
5 between smapi and any calling programs are in no way align controlled,
6 that is, how they are aligned is left to the compiler.
7 That means that if you are not using the same compiler for your
8 program that was used to compile the libraries, chances are that
9 you will have an alignment problem resulting in fields of the
10 structures being out of sync, e.g. you are reading something totally
11 different from what the library put there.
12 Because of this and because I don't want to chase a moving target
13 like this, I will stop maintaining smapi.pas and fidoconf.pas.
14 That probably means that husky has now become a project that can
15 only be used by C programmers, unless somebody else wants
16 to go through the trouble.
17 One possible solution I can think of, would be having an interface
18 layer that converts the randomly aligned structures to other
19 structures that are fixed. I might do it, maybe, if I don't find
20 anything else to waste my time on. But this is rather unlikely,
21 because it has to be done in C and that is definitely not my
22 favourite programming language.
23 Please leave this comment in here, so nobody else will waste time
24 trying to figure out why the data his programs reads is wrong.
25 2001-07-22 twm }
26
27 unit smapi;
28
29 interface
30
31 type
32 // this assumes that a word is 2 bytes and a longword is 4 bytes, true
33 // for Delphi 5 and Kylix.
34 sword = word;
35 dword = longword;
36 PPChar = ^PChar;
37 PLongint = ^Longint;
38
39 const
40 MSGAREA_NORMAL = $00; // read/write
41 MSGAREA_CREATE = $01; // create
42 MSGAREA_CRIFNEC = $02; // create if necessary
43
44 MSGTYPE_SDM = $01; // *.MSG
45 MSGTYPE_SQUISH = $02; // squish
46 MSGTYPE_JAM = $08; // jam
47 MSGTYPE_ECHO = $80;
48 MSGTYPE_NOTH = $0100; // ??
49
50 MSGNUM_CUR: longint = -1;
51 MSGNUM_PREV: longint = -2;
52 MSGNUM_NEXT: longint = -3;
53 MSGNUM_current: longint = -1;
54 MSGNUM_previous: longint = -2;
55
56 MOPEN_CREATE = 0;
57 MOPEN_READ = 1;
58 MOPEN_WRITE = 2;
59 MOPEN_RW = 3;
60
61 MSGAPI_VERSION = 1;
62 SMAPI_VERSION = '1.5.65.65.65.65.6';
63
64 MSGPRIVATE = $00001;
65 MSGCRASH = $00002;
66 MSGREAD = $00004;
67 MSGSENT = $00008;
68 MSGFILE = $00010;
69 MSGFWD = $00020; // also called intransit flag
70 MSGORPHAN = $00040;
71 MSGKILL = $00080;
72 MSGLOCAL = $00100;
73 MSGHOLD = $00200;
74 MSGXX2 = $00400;
75 MSGFRQ = $00800;
76 MSGRRQ = $01000;
77 MSGCPT = $02000;
78 MSGARQ = $04000;
79 MSGURQ = $08000;
80 MSGSCANNED = $10000;
81 MSGLOCKED: dword = $40000000; // seems to be a feature of GoldEd
82
83 XMSG_NAME_SIZE = 36;
84 XMSG_FROM_SIZE = XMSG_NAME_SIZE;
85 XMSG_TO_SIZE = XMSG_NAME_SIZE;
86 XMSG_SUBJ_SIZE = 72;
87 MAX_REPLY = 9;
88 FTS0001_DATE_SIZE = 20;
89
90 XMSG_SIZE = ((94 + XMSG_FROM_SIZE) + XMSG_TO_SIZE) + XMSG_SUBJ_SIZE;
91 MSGAPI_ID: dword = $0201414D;
92
93 MSGH_ID = $0302484D;
94
95 UID_EXACT = $00;
96 UID_NEXT = $01;
97 UID_PREV = $02;
98
99 // error constants
100
101 MERR_NONE = 0; // No error
102 MERR_BADH = 1; // Invalid handle passed to function
MERR_BADFnull103 MERR_BADF = 2; // Invalid or corrupted file
104 MERR_NOMEM = 3; // Not enough memory for specified operation
105 MERR_NODS = 4; // Maybe not enough disk space for operation
106 MERR_NOENT = 5; // File/message does not exist
107 MERR_BADA = 6; // Bad argument passed to msgapi function
MERR_EOPENnull108 MERR_EOPEN = 7; // Couldn't close - messages still open
109
110 {: used nowhere
111 BROWSE_ACUR = $0001;
112 BROWSE_ATAG = $0002;
113 BROWSE_AALL = $0004;
114 BROWSE_ALL = $0008;
115 BROWSE_NEW = $0010;
116 BROWSE_SEARCH = $0020;
117 BROWSE_FROM = $0040;
118 BROWSE_READ = $0100;
119 BROWSE_LIST = $0200;
120 BROWSE_QWK = $0400;
121 BROWSE_GETTXT = $0800;
122 BROWSE_EXACT = $1000;
123 BROWSE_HASH = $2000;
124 BROWSE_AREA = (BROWSE_ACUR or BROWSE_ATAG) or BROWSE_AALL;
125 BROWSE_TYPE = ((BROWSE_ALL or BROWSE_NEW) or BROWSE_SEARCH) or BROWSE_FROM;
126 BROWSE_DISPLAY = (BROWSE_READ or BROWSE_LIST) or BROWSE_QWK;
127 }
128 SF_HAS_ATTR = $01;
129 SF_NOT_ATTR = $02;
130 SF_OR = $04;
131 SF_AND = $08;
132 WHERE_TO = $01;
133 WHERE_FROM = $02;
134 WHERE_SUBJ = $04;
135 WHERE_BODY = $08;
136 WHERE_ALL = ((WHERE_TO or WHERE_FROM) or WHERE_SUBJ) or WHERE_BODY;
137 SCAN_BLOCK_SDM = 48;
138 SCAN_BLOCK_SQUISH = 512;
139
140 type
141 PAreaHandle = ^TAreaHandle;
142 PMsgHandle = ^TMsgHandle;
143 PXMSG = ^TXMSG;
144 PNETADDR = ^TNETADDR;
145 PSEARCH = ^TSEARCH;
146 {: used nowhere
147 PBROWSE = ^TBROWSE;
148 }
149 TUMsgId = dword;
150
151 { Timestamp }
152 TStamp = packed record
153 // This was true for the original Squish MsgAPI, but smapi is double word aligned
154 // case Boolean of
155 // True: (Date, Time: sword);
156 // False: (Value: dword);
157 Date, Filler1, Time, Filler2: sword;
158 // Date, Time: dword;
159 end;
160
161 PMINF = ^TMINF;
162 TMINF = packed record
163 req_version: sword;
164 def_zone: sword;
165 haveshare: sword;
166
167 // necessary for Versions >= 1 always set to NIL
168 palloc: pointer;
169 pfree: pointer;
170 repalloc: pointer;
171 farpalloc: pointer;
172 farpfree: pointer;
173 farrepalloc: pointer;
174 end;
175
176 TNetAddr = packed record
177 zone: sword;
178 net: sword;
179 node: sword;
180 point: sword;
181 end;
182
183 TMsgName = packed array[0..XMSG_NAME_SIZE - 1] of char;
184 TMsgSubj = packed array[0..XMSG_SUBJ_SIZE - 1] of Char;
185 // TMsgSubjStr = string[XMSG_SUBJ_SIZE];
186
187 TXMSG = packed record
188 attr: dword;
189 from: TMsgName;
190 _to: TMsgName;
191 subj: TMsgSubj;
192 orig: TNetAddr;
193 dest: TNetAddr;
194 date_written: TStamp;
195 date_arrived: TStamp;
196 utc_ofs: sword;
197 filler1: sword; // dword align
198 replyto: TUMsgId;
199 Replies: array[0..MAX_REPLY - 1] of TUMsgId;
200 filler2: sword; // dword align
201 FtscData: array[0..FTS0001_DATE_SIZE - 1] of Char;
202 end;
203
204 TApiFuncs = packed record
205 CloseArea: function(mh: PAreaHandle): sword; cdecl;
206 OpenMsg: function(mh: PAreaHandle; mode: sword; n: dword): PMsgHandle; cdecl;
207 CloseMsg: function(msgh: PMsgHandle): sword; cdecl;
208 ReadMsg: function(msgh: PMsgHandle; msg: PXMSG; ofs: dword; bytes: dword; text: PChar; cbyt: dword; ctxt: PChar): dword; cdecl;
209 WriteMsg: function(msgh: PMsgHandle; append: sword; msg: PXMSG; text: PChar; textlen: dword; totlen: dword; clen: dword; ctxt: PChar): sword; cdecl;
210 KillMsg: function(mh: PAreaHandle; msgnum: dword): sword; cdecl;
211 Lock: function(mh: PAreaHandle): sword; cdecl;
212 UnLock: function(mh: PAreaHandle): sword; cdecl;
213 SetCurPos: function(msgh: PMsgHandle; pos: dword): sword; cdecl;
214 GetCurPos: function(msgh: PMsgHandle): dword; cdecl;
215 MsgnToUid: function(mh: PAreaHandle; msgnum: dword): TUMsgId; cdecl;
216 UidToMsgn: function(mh: PAreaHandle; UMsgId: TUMsgId; _type: sword): dword; cdecl;
217 GetHighWater: function(mh: PAreaHandle): dword; cdecl;
218 SetHighWater: function(mh: PAreaHandle; hwm: dword): sword; cdecl;
219 GetTextLen: function(msgh: PMsgHandle): dword; cdecl;
220 GetCtrlLen: function(msgh: PMsgHandle): dword; cdecl;
221 end;
222 PApiFuncs = ^TApiFuncs;
223
224 TMSGAPI = packed record
225 id: dword;
226 len: sword;
227 _type: sword;
228 num_msg: dword;
229 cur_msg: dword;
230 high_msg: dword;
231 high_water: dword;
232 sz_xmsg: sword;
233 locked: byte;
234 isecho: byte;
235 api: PApiFuncs;
236 apidata: pointer; // Pointer to application-specific data.
237 // API_SQ.C and API_SDM.C use this for
238 // different things, so again, no applications
239 // should muck with anything in here.
240 end;
241
242 TAreaHandle = TMSGAPI;
243
244 TMsgHandle = packed record
245 sq: PAreaHandle;
246 id: dword;
247 bytes_written: dword;
248 cur_pos: dword;
249 end;
250
251 TSEARCH = packed record
252 next: PSEARCH;
253 attr: longint;
254 flag: longint;
255 txt: Pchar;
256 where: char;
257 end;
258
259 {: used nowhere
260 TBROWSE = packed record
261 path: Pchar;
262 _type: sword;
263 bflag: sword;
264 bdata: dword;
265 first: PSEARCH;
266 nonstop: Pchar;
267 msgn: dword;
268 sq: PAreaHandle;
269 m: PMsgHandle;
270 msg: TXMSG;
271 matched: sword;
272 Begin_Ptr: function(b: pBROWSE): longint; cdecl;
273 Status_Ptr: function(b: pBROWSE; aname: pchar; colour: longint): longint;
274 Idle_Ptr: function(b: pBROWSE): longint;
275 Display_Ptr: function(b: pBROWSE): longint;
276 After_Ptr: function(b: pBROWSE): longint;
277 End_Ptr: function(b: pBROWSE): longint;
278 Match_Ptr: function(b: pBROWSE): longint;
279 end;
280 }
281 //Var
282 // msgapierr: sword; cvar; external;
283 // mi: minf; cvar; external;
284
285 {: Helper function. Since Delphi/Kylix does not support external variables,
286 this function has been introduced. It reads the smapi error variable
287 msgapierr and returns its value }
288 function MsgGetMsgApiErr: sword; cdecl;
289
290 {: Closes a message area.
291 This function performs all clean-up actions necessary, such as closing files,
292 changing directories, and so on. The MsgCloseArea function should be
293 called for each area opened by MsgOpenArea.
294 @param AreaHandle is an HAREA handle returnded by MsgOpenArea.
295 @returns 0 if the area was successfully closed, otherwise it returns -1
296 and msgapierr is set to one of the following:
297 MERR_BADH An invalid handle was passed to the function.
298 MERR_EOPEN Messages are still open in this area, so the area
299 could not be closed. }
300 function MsgCloseArea(_AreaHandle: PAreaHandle): sword; cdecl;
301
302 {: Opens a message for access, and it must be used to read from or write to
303 a given message.
304 @param AreaHandle is a message area handle, as returned by the MsgOpenArea
305 function.
306 @param Mode is an access flag, containing one of the following manifest
307 constants:
308 MOPEN_CREATE Create a new message. This mode should only
309 be used for creating new messages.
310 MOPEN_READ Open an existing message for reading ONLY.
311 MOPEN_WRITE Open an existing message for writing ONLY.
312 MOPEN_RW Open an existing message for reading AND writing.
313 @param MsgNum is the specified message number to open. If mode is either
314 MOPEN_READ, MOPEN_WRITE or MOPEN_RW, the message number must
315 currently exist in the specified area. If mode is set to
316 MOPEN_CREATE, a value of 0 for 'msgn' indicates that a new
317 message should be created, and assigned a number one higher
318 than the current highest message. If MsgN is non-zero, but
319 MOPEN_CREATE is set to the number of a currently-existing
320 message, the specified message will be truncated and the
321 new message will take its place.
322 For MOPEN_READ or MOPEN_RW, the following constants can also
323 be passed in place of 'msgn':
324 MSGNUM_CUR Open the last message which was accessed by MsgOpenMsg.
325 MSGNUM_PREV Open the message prior to the last message accessed
326 by MsgOpenMsg.
327 MSGNUM_NEXT Open the message after the last message accessed by
328 MsgOpenMsg.
329 The MsgAPI maintains the number of the last message opened by
330 MsgOpenMsg, which is used when processing these constants.
331 (See also MsgGetCurMsg.)
332 @returns a HMSG handle ff the message was successfully opened. Otherwise,
333 a value of NULL is returned, and msgapierr will be set to one of
334 the following:
335 MERR_NOENT
336 MERR_NOMEM
337 MERR_BADF
338 MERR_BADA
339 MERR_BADH }
340 function MsgOpenMsg(_AreaHandle: PAreaHandle; _Mode: sword; _MsgNum: dword): PMsgHandle; cdecl;
341
342 {: Closes a message which has been previously opened by MsgOpenMsg.
343 All messages should be closed after use, or else data loss may result.
344 @params MsgHandle is the message handle that was returned by MsgOpenMsg.
345 @returns 0, if the message was successfully closed, otherwise, -1 is
346 returned, and msgapierr is set to:
347 MERR_BADH }
348 function MsgCloseMsg(_MsgHandle: PMsgHandle): sword; cdecl;
349
350 {: Reads a message from disk.
351 This function can be used to read all parts of a message, including the
352 message header, message body, and control information.
353
354 @param MsgHandle is a message handle, as returned by the MsgOpenMsg function.
355 The message in question must have been opened with a mode of either
356 MOPEN_READ or MOPEN_RW.
357
358 @param XMsg is a pointer to an TXMSG (extended message) structure.
359 The format of this structure is detailed in the Squish File Format
360 Specification section, but it contains all of the message information
361 that is found in the message header, including the to/from/subject
362 fields, origination and arrival dates, 4D origination and destination
363 addresses, and so forth. (See the appendices for specific information
364 on the XMSG structure itself.)
365 If the application wishes to read the header of a given message, this
366 argument should point to an XMSG structure. Otherwise, this argument
367 should be NULL, which informs the API that the message header does
368 not need to be read.
369
370 @param Offset is used for reading message text in a multiple-pass environment.
371 This defines the offset in the message body from which the API should
372 start reading. To start reading from the beginning of the message,
373 a value of 0L should be given. Otherwise, the offset into the message
374 (in bytes) should be given for this argument. If the application does
375 not wish to read the message body, this argument should be set to 0L.
376
377 @param BodyLen represents the maximum number of bytes to read from the message.
378 Fewer bytes may be read, but the API will read no more than BodyLen
379 during this call. (See BodyLen, and also this function's return value.)
380 If the application does not wish to read the message body, this
381 argument should be set to 0L.
382
383 @param Body is a pointer to a block of memory, into which the API will place
384 the message body. The message body will be read from the position
385 specified by Offset, up to a maximum of BodyLen bytes. If the
386 application does not wish to read the message body, this argument
387 should be set to NULL.
388
389 @param ControlLen represents the maximum number of bytes of control
390 information to read from the message.
391
392 @param Control is a pointer to a block of memory, into which the API will
393 place the message control information. No more than ControlLne bytes
394 of control information will be placed into the buffer.
395 NOTE: unlike the message text functions, control information can only
396 be read in one pass.
397
isnull398 The text read by this function is free-form. The message body may or may not
399 contain control characters, NULs, or any other sequence of characters.
400 Messages are simply treated as a block of bytes, with no interpretation
401 whatsoever.
402
403 In FidoNet areas, the message body consists of one or more paragraphs of
404 text. Each paragraph is delimited by a hard carriage return, '\r', or
405 ASCII 13. Each paragraph can be of any length, so the text should be
406 wordwrapped onto logical lines before being displayed. If created by older
407 applications, paragraphs may also contain linefeeds ('\n') and soft returns
408 ('\x8d') at the end of each line, but these are optional and should always be
409 ignored.
410
411 As an example, assume that the following stream of text was returned by
412 MsgReadMsg():
413
414 "Hi!\r\rHow's it going? I got the new MsgAPI kit today!\r\rAnyhow, gotta run!"
415
416 The "\r" marks are carriage returns, so they indicate the end of a paragraph.
417 Notice that the second paragraph is fairly long, so it might have to be
418 wordwrapped, depending on the screen width. Your application might wordwrap
419 the text to make it look like this, if using a window 40 characters wide:
420
421 -----------------------------------------
422 | Hi! |
423 | |
424 | How's it going? I got the new MsgAPI |
425 | kit today! |
426 | |
427 | Anyhow, gotta run! |
428 -----------------------------------------
429
430 Paragraphs should always be wordwrapped by the application, regardless
431 of the screen/window size. When parsing the message text, linefeeds and
432 soft carriage returns should be simply skipped.
433
434 The 'message control information' has a somewhat more restricted format.
435 The control information is passed to the application in the form of an
436 ASCIIZ string. The control information is a variable-length string of text
437 which contains information not found in the (fixed-size) message header.
438
439 The format of control information is given by the following regular
440 expression:
441
442 (group)+<NUL>
443
444 A 'group' consists of a <SOH> and a control item.
445
446 <SOH> is the Start Of Header character, or ASCII 01. All control information
447 strings must begin with an SOH, whether or not control items are present.
448
449 Following the <SOH> is a control item. A control item consists of a string
450 which describes the type of control item, or it may consist of nothing.
451
452 At least one group must be present in each message. If a message has no extra
453 control information, this field should consists of a <SOH> followed by a
454 single <NUL>.
455
456 Although the control items are free-form, the following format is
457 suggested:
458
459 <SOH>tag: value
460
461 where 'tag' is a descriptive identifier, describing the type of field that
462 the item represents. 'value' is simply free-form text, which continues up
463 until the next SOH or <NUL>.
464
465 The character set for the tag and value consists of those characters in the
466 range 2-255, inclusive.
467
468 As an example, a message might have the following control information:
469
470 <SOH>CHARSET: LATIN1<SOH>REALNAME: Mark Twain<NUL>
471
472 The trailing <NUL> byte must be included in the read count given by 'cbyt'.
473
474 @returns the number of bytes read from the message body. If no characters
475 were requested, this function returns 0.
476 On error, the function returns -1 and sets msgapierr to one
477 of the following:
478 MERR_BADH
479 MERR_BADF
480 MERR_NOMEM }
481 function MsgReadMsg(_MsgHandle: PMsgHandle; _XMsg: PXMSG; _Offset: dword;
482 _BodyLen: dword; _Body: PChar; _ControlLen: dword; _Control: PChar): integer; cdecl;
483
484 {: Writes the message header, body, and control information to a message.
485 @param MsgHandle is a message handle, as returned by the MsgOpenMsg
486 function. The message must have been opened with a mode of
487 MOPEN_CREATE, MOPEN_WRITE or MOPEN_RW.
488
489 @param Append is a boolean flag, indicating the state of the message body.
490 If Append is zero, then the API will write the message body starting
491 at offset zero. Otherwise, if Append is non-zero, the API will
492 continue writing from the offset used by the last MsgWriteMsg call.
493 This flag applies to the message body only; if no text is to be
494 written to the body, this argument should be set to 0.
495
496 @param XMsg is a pointer to an XMSG structure. If this pointer is non-NULL,
497 then MsgWriteMsg will place the XMSG structure information into the
498 message's physical header. To leave the header unmodified, NULL should
499 be passed for XMsg.
500 THIS PARAMETER MUST BE PASSED THE **FIRST** TIME THAT MSGWRITEMSG()
501 IS USED WITH A JUST-OPENED MESSAGE HANDLE!
502
503 @param Body points to an array of bytes to be written to the message body.
504 If no text is to be written, this argument should be NULL.
505
506 @param Bodylen indicates the number of bytes to be written to the message
507 body in this pass of the MsgWriteMsg function. The text is free-format,
508 and it can consist of any characters, including NULs and control
509 characters. If the application does not wish to update the message
510 body, a value of 0L should be passed for this argument.
511
512 @param Total indicates the total length of the message to be written. This
513 differs from Bodylen in that the message may be written a piece at a
514 time (using small Bodylen values), but the total length of the message
515 will not exceed Total. This parameter can be somewhat restrictive for
516 the application; however, this value is required for optimal use of
517 some message base types. The Total value does not have to be the exact
518 length of the message to write; however, space may be wasted if this
519 value is not reasonably close to the actual length of the message.
520 The rationale behind this argument is that it gives the API writer
521 the most flexibility, in terms of supporting future message base
522 formats. If the application can provide this information to the API,
523 then almost any message base format can be supported by simply dropping
524 in a new API module or DLL.
525 To write text by making multiple passes, the FIRST pass should call
526 MsgWriteMsg with Append set to 0, with the total length of the message
527 in Total, and the length of Body in Bodylen. Second and subsequent
528 passes should set Append to 1, with the length of Body in Bodylen.
529 If the application does not wish to update the message body of an
530 existing message, a value of 0L should be passed for this argument.
531 This argument MUST be specified during the first call to the
532 MsgWriteMsg when using a mode of MOPEN_CREATE, even if the first
533 call is not requesting any text to be written.
534 However, this value will be stored internally, and ignored on the
535 second and later calls.
536 When operating on a preexisting message (opened with MOPEN_WRITE or
537 MOPEN_RW), it is an error to specify a length in 'totlen' which is
538 greater than the original length of the message.
539
540 @param ControlLen specifies the total length of the control information,
541 including the trailing NUL byte. To write no control information,
542 a value of 0L should be passed for this argument.
543
544 @param Control is a pointer to the control information string. To write no
545 control information, a value of 0L should be passed for this argument.
546 N.B. Several restrictions apply to writing control information:
547 First and foremost, control information can only be written once.
548 If the control information is to be changed, the message must be read
549 and copied to another message.
550 Secondly, control information MUST be written during or before
551 MsgWriteMsg is called with information about the message body.
552
553 @returns a value of 0 on success, or -1 on error. If an error occurred,
554 msgapierr will be set to one of the following values:
555 MERR_BADH
556 MERR_BADF
557 MERR_NOMEM
558 MERR_NODS }
MsgWriteMsgnull559 function MsgWriteMsg(_MsgHandle: PMsgHandle; _Append: sword; _XMsg: PXMSG;
560 _Body: PChar; _Bodylen: dword; _Total: dword; _ControlLen: dword;
561 _Control: PChar): sword; cdecl;
562
563
564 {: Deletes a message from the specified message area.
565
566 @param AreaHandle is a message area handle, as returned by MsgOpenArea.
567
568 @param MsgNum specifies the message number to kill.
569
570 It is an error to kill a message which is currently open.
571
572 @returns a value of 0 if the message was successfully killed, or it
573 returns -1 on error and sets msgapierr to one of the following:
574 MERR_BADH
575 MERR_NOENT
576 MERR_BADF
577 MERR_NOMEM }
MsgKillMsgnull578 function MsgKillMsg(_AreaHandle: PAreaHandle; _MsgNum: dword): sword; cdecl;
579
MsgLocknull580 function MsgLock(mh: PAreaHandle): sword; cdecl;
MsgUnLocknull581 function MsgUnLock(mh: PAreaHandle): sword; cdecl;
582
583 {: Sets the 'current position' in a message handle. This position is used by
584 MsgReadMsg to read text from the message body.
585
586 @param MsgHandle is a message handle, as returned by MsgOpenMsg.
587
588 @param Pos is the number of bytes into the message from which MsgReadMsg
589 should start reading.
590
591 @returns 0 on success, or -1 on error and sets msgapierr to:
592 MERR_BADH }
593
MsgSetCurPosnull594 function MsgSetCurPos(_MsgHandle: PMsgHandle; _Pos: dword): sword; cdecl;
595
596 {: Retrieves the 'current position' of a message handle. This position is
597 where the MsgReadMsg would read text from the message body next.
598
599 @param MsgHandle is a message handle, as returned by MsgOpenMsg.
600
601 MsgGetCurPos returns the offset into the message on success, or (dword)-1 on
602 error and sets msgapierr to:
603 MERR_BADH }
MsgGetCurPosnull604 function MsgGetCurPos(_MsgHandle: PMsgHandle): dword; cdecl;
605
606 {: Converts a message number to a 'unique message ID', or UMSGID. This function
607 can be used to maintain pointers to an 'absolute' message number, regardless
608 of whether or not the area is renumbered or packed. The MsgMsgnToUid
609 function converts a message number to a UMSGID, and the MsgUidToMsgn
610 function converts that UMSGID back to a message number.
611
612 @param AreaHandle is the message area handle, as returned by MsgOpenArea.
613
614 @param MsgNum is the message number to convert.
615
616 @returns a UMSGID on success; otherwise, it returns 0 and sets msgapierr to:
617 MERR_BADH
618 MERR_BADF
619 MERR_NOENT }
MsgMsgnToUidnull620 function MsgMsgnToUid(_AreaHandle: PAreaHandle; _MsgNum: dword): TUMsgId; cdecl;
621
622 {: Converts a UMSGID to a message number.
623
624 @param AreaHandle is the message area handle, as returned by MsgOpenArea.
625
626 @param UMsgId is the UMSGID, as returned by a prior call to MsgMsgnToUid.
627
628 @param Type is the type of conversion to perform. Type can be any of the
629 following values:
630 UID_EXACT Return the message number represented by the UMSGID,
631 or 0 if the message no longer exists.
632 UID_PREV Return the message number represented by the UMSGID.
633 If the message no longer exists, the number of the
634 preceding message will be returned.
635
636 UID_NEXT Return the message number represented by the UMSGID.
637 If the message no longer exists, the number of the
638 following message will be returned.
639
640 @returns the requested UMSGID. If no valid message could be found,
641 MsgUidToMsgn returns 0 and sets msgapierr to one of the
642 following:
643 MERR_BADH
644 MERR_NOENT }
MsgUidToMsgnnull645 function MsgUidToMsgn(_AreaHandle: PAreaHandle; _UMsgId: TUMsgId; _Type: sword): dword; cdecl;
646
647 {: Returns the 'high water marker' for an area.
648 This number represents the highest message number that was processed by a
649 message export or import utility. The high water marker is automatically
650 adjusted when messages are killed.
651 @param AreaHandle is a message area handle, as returned by MsgOpenArea.
652 @returns the high water mark on success, or 0 on error and
653 sets msgapierr to: MERR_BADH }
MsgGetHighWaternull654 function MsgGetHighWater(_AreaHandle: PAreaHandle): dword; cdecl;
655
656 {: Sets the 'high water marker' for the current area.
657
658 @param AreaHandle is a message area handle, as returned by MsgOpenArea.
659
660 @param HighWater is the new high water marker to use for the specified area.
661
662 @returns 0 on success, or -1 on error and sets msgapierr to:
663 MERR_BADH }
MsgSetHighWaternull664 function MsgSetHighWater(_AreaHandle: PAreaHandle; _HighWater: dword): sword; cdecl;
665
666 {: Retrieves the length of the message body for the specified message.
667
668 @param MsgHandle is a message handle, as returned by MsgOpenMsg.
669
670 @returns the length of the body on success. On error, it returns (dword)-1
671 and sets msgapierr to:
672 MERR_BADHT }
MsgGetTextLennull673 function MsgGetTextLen(_MsgHandle: PMsgHandle): dword; cdecl;
674
675 {: Retrieves the length of the control information for the specified message.
676
677 @param MsgHandle is a message handle, as returned by MsgOpenMsg.
678
679 @returns the length of the control information on success. On error, it
680 returns (dword)-1 and sets msgapierr to:
681 MERR_BADH }
MsgGetCtrlLennull682 function MsgGetCtrlLen(_MsgHandle: PMsgHandle): dword; cdecl;
683
684 {: Initializes the MsgAPI.
685 This function must be called before any of the other API functions are
686 called, or else the results are undefined.
687 This function serves to initialize any needed structures, and to prepare
688 the message bases for use.
689 @param MInf is a structure contining the following fields:
690
691 record TMInf
692 // The following fields are required for all
693 // MsgAPI clients:
694
695 word req_version;
696 word def_zone;
697 word haveshare;
698
699 // The following fields are required when
700 // req_version >= 1:
701 void OS2FAR * (MAPIENTRY *palloc)(size_t size);
702 void (MAPIENTRY *pfree)(void OS2FAR *ptr);
703 void OS2FAR * (MAPIENTRY *repalloc)(void OS2FAR *ptr,
704 size_t size);
705
706 void far * (MAPIENTRY *farpalloc)(size_t size);
707 void (MAPIENTRY *farpfree)(void far *ptr);
708 void far * (MAPIENTRY *farrepalloc)(void far *ptr,
709 size_t size);
710 end;
711
712 'req_version' indicates the MsgAPI revision level that the application is
713 requesting. The compile-time revision level can always be
714 accessed using the constant 'MSGAPI_VERSION'.
715
716 'def_zone' should contain a default FidoNet zone number.
717 Certain message systems, such as the FTSC-0001 *.MSG format,
718 do not store zone information with each message. When the
719 API encounters such a message and no zone is present, the
720 specified zone will be used instead. A 'def_zone' of 0
721 indicates that nothing is to be inferred about the zone
722 number of a message, and in that case, the API functions
723 will return 0 as the zone number for any message with an
724 unknown zone.
725
726 'haveshare' is automatically filled in by the internal API routines, and
727 this flag indicates whether or not the DOS "SHARE.EXE" program
728 is currently loaded.
729 Note that SHARE must always be loaded to access Squish-format
730 bases in a multitasking or network environment. This field is
731 not used in the OS/2 version of the MsgAPI.
732
733 If 'req_version' is more than or equal to 1, the final six fields in the
734 _minf structure must be provided. These fields are memory allocation hooks
735 that MsgAPI will call whenever it needs to allocate memory.
736 (If req_version is 0, or if one of the function pointers in this structure
737 is NULL, then MsgAPI will use its own memory allocation routines.)
738
739 'palloc' is called to allocate a block of near memory. This function
740 should behave in the same manner as the ANSI malloc()
741 function. If this field is NULL, the MsgAPI will use its own
742 malloc() function.
743
744 'pfree' is called to free a block of near memory. This function should
745 behave in the same manner as the ANSI free() function. If this
746 field is NULL, the MsgAPI will use its own free() function.
747
748 'repalloc' is called to reallocate a block of near memory. This function
749 should behave in the same manner as the ANSI realloc()
750 function. If this field is NULL, the MsgAPI will use its own
751 realloc() function.
752
753 'farpalloc' is called to allocate a block of far memory. This function
754 should behave in the same manner as the ANSI malloc()
755 function, except that a far pointer should be returned.
756 If this field is NULL, MsgAPI will use its own malloc()
757 function.
758
759 'farpfree' is called to free a block of far memory. This function should
760 behave in the same manner as the ANSI free() function, except
761 that a far pointer should be accepted. If this field is NULL,
762 MsgAPI will use its own free() function.
763
764 'farrepalloc' is called to reallocate a block of far memory. This function
765 should behave in the same manner as the ANSI realloc()
766 function, except that a far pointer should be accepted and
767 returned. If this field is NULL, MsgAPI will use its own
768 realloc() function.
769
770 @returns a value of 0 if the initialization was performed successfully,
771 and -1 if a problem was encountered. }
MsgOpenApinull772 function MsgOpenApi(_MInf: PMINF): sword; cdecl;
773
774 {: Deinitialize theMsgAPI. This function performs any clean-up actions which
775 may be necessary, including the closing of files and releasing allocated
776 memory. This function should be called before the application terminates.
777
778 @returns a value of 0 if the API was successfully deinitialized,
779 and -1 otherwise. }
MsgCloseApinull780 function MsgCloseApi: sword; cdecl;
781
782 {: Opens or creates a message area.
783 @param Name is the name of the message area to open. The contents of this
784 string are implementation-defined. (See Type for more information.)
785
786 @param Mode is the mode with which the area should be opened. Values for
787 Mmode are as follows:
788
789 MSGAREA_NORMAL Open the message area in a normal access mode. If
790 the area does not exist, this function fails.
791
792 MSGAREA_CRIFNEC Open the message area in a normal access mode.
793 If the area does not exist, the MsgAPI attempts
794 to create the area. If the area cannot be created,
795 this function fails.
796
797 MSGAREA_CREATE Create the message area. If the area already exists,
798 it is truncated or started anew with no messages.
799 If the area cannot be created, this function fails.
800
801 @param Type specifies the type of message area to open. Type can have any of
802 the following values:
803
804 MSGTYPE_SDM Star Dot MSG (SDM). This specifies a FTSC-0001
805 compatible access mode, and it instructs the MsgAPI
806 to create and read Fido-compatible messages for
807 this area. If MSGTYPE_SDM is specified, Name should
808 contain the path to the *.MSG directory.
809
810 MSGTYPE_SQUISH Squish (*.SQ?) format. This specifies that the
811 proprietary Squish message format is to be used
812 for this area. Name should give the path and root
813 name (eight characters in DOS) for the message area.
814
815 In addition, if the mask 'MSGTYPE_ECHO' is bitwise 'OR'ed with the '
816 'MSGTYPE_SDM' value, the area in question will be treated as a
817 FidoNet-style echomail area. This instructs the MsgAPI to keep
818 high-water mark information in the 1.MSG file, and to stop the normal
819 MsgAPI functions from writing to the first message in each area.
820 Other message formats have a cleaner way of storing the high-water
821 mark, so this mask is only required for *.MSG areas.
822
823 Other values for Type' are currently reserved.
824
825 @returns a HAREA handle on success. This handle does not contain any
826 information which can be used directly by the caller; all
827 interaction should be performed through the MsgAPI functions only.
828
829 If this function fails, NULL is returned, and the global MsgApiErr
830 variable is set to one of the following values:
831 MERR_NOMEM Not enough memory for requested task
832 MERR_NOENT The area did not exist or could not be created.
833 MERR_BADF The message area is structurally damaged. }
MsgOpenAreanull834 function MsgOpenArea(_Name: PChar; _Mode: sword; _Type: sword): PAreaHandle; cdecl;
835
836
837 {: The MsgValidate function validates a particular message area, determining
838 whether or not the area exists and if it is valid.
839 @param Type is the type of the message area, using the same constants as
840 specified for MsgOpenArea.
841 @param Name is the name of the message area, using the same format as
842 specified for MsgOpenArea.
843 @returns the value 1 if the area exists and is valid. 0 otherwise. }
844 function MsgValidate(_Type: sword; _Name: PChar): sword; cdecl;
845
846 function MsgCurMsg(_AreaHandle: PAreaHandle): integer;
847 function MsgNumMsg(_AreaHandle: PAreaHandle): integer;
848 function MsgHighMsg(_AreaHandle: PAreaHandle): integer;
849 function MsgGetCurMsg(_AreaHandle: PAreaHandle): integer;
850 function MsgGetNumMsg(_AreaHandle: PAreaHandle): integer;
851 function MsgGetHighMsg(_AreaHandle: PAreaHandle): integer;
852
853 function InvalidMsgh(msgh: PMsgHandle): sword; cdecl;
854 function InvalidMh(mh: PAreaHandle): sword; cdecl;
855
856 procedure SquishSetMaxMsg(sq: PAreaHandle; max_msgs: dword; skip_msgs: dword; age: dword); cdecl;
857 function SquishHash(f: PChar): dword; cdecl;
858
859 function SdmOpenArea(name: PChar; mode: sword; _type: sword): PAreaHandle; cdecl;
860 function SdmValidate(name: PChar): sword; cdecl;
861
862 function SquishOpenArea(name: PChar; mode: sword; _type: sword): PAreaHandle; cdecl;
863 function SquishValidate(name: PChar): sword; cdecl;
864
865 function JamOpenArea(name: PChar; mode: sword; _type: sword): PAreaHandle; cdecl;
866 function JamValidate(name: PChar): sword; cdecl;
867
868 function CvtCtrlToKludge(ctrl: PChar): PChar; cdecl;
869 function GetCtrlToken(where: PChar; what: PChar): PChar; cdecl;
870 function CopyToControlBuf(txt: PChar; newtext: PPChar; length: PLongInt): PChar; cdecl;
871 procedure ConvertControlInfo(ctrl: PChar; orig: PNETADDR; dest: PNETADDR); cdecl;
872 function NumKludges(txt: PChar): sword; cdecl;
873 procedure RemoveFromCtrl(ctrl: PChar; what: PChar); cdecl;
874
875 function Address(a: PNETADDR): PChar; cdecl;
876 function StripNasties(str: PChar): PChar; cdecl;
877
878 implementation
879
880 const LIBSMAPI_NAME = 'libsmapi.so';
881
882 function MsgCloseArea(_AreaHandle: PAreaHandle): sword; cdecl;
883 begin
884 MsgCloseArea := _AreaHandle^.api^.CloseArea(_AreaHandle);
885 end;
886
887 function MsgOpenMsg(_AreaHandle: PAreaHandle; _Mode: sword; _MsgNum: dword): PMsgHandle; cdecl;
888 begin
889 MsgOpenMsg := _AreaHandle^.api^.OpenMsg(_AreaHandle, _Mode, _MsgNum);
890 end;
891
892 function MsgCloseMsg(_MsgHandle: PMsgHandle): sword; cdecl;
893 begin
894 MsgCloseMsg := _MsgHandle^.sq^.api^.CloseMsg(_MsgHandle);
895 end;
896
897 function MsgReadMsg(_MsgHandle: PMsgHandle; _XMsg: PXMSG; _Offset: dword;
898 _BodyLen: dword; _Body: PChar; _ControlLen: dword; _Control: PChar): integer; cdecl;
899 begin
900 MsgReadMsg := _MsgHandle^.sq^.api^.ReadMsg(_MsgHandle, _XMsg, _Offset,
901 _BodyLen, _Body, _ControlLen, _Control);
902 end;
903
904 function MsgWriteMsg(_MsgHandle: PMsgHandle; _Append: sword; _Xmsg: PXMSG;
905 _Body: PChar; _Bodylen: dword; _Total: dword; _ControlLen: dword; _Control: PChar): sword; cdecl;
906 begin
907 MsgWriteMsg := _MsgHandle^.sq^.api^.WriteMsg(_MsgHandle, _Append, _Xmsg,
908 _Body, _Bodylen, _Total, _ControlLen, _Control);
909 end;
910
911 function MsgKillMsg(_AreaHandle: PAreaHandle; _MsgNum: dword): sword; cdecl;
912 begin
913 MsgKillMsg := _AreaHandle^.api^.KillMsg(_AreaHandle, _MsgNum);
914 end;
915
916 function MsgLock(mh: PAreaHandle): sword; cdecl;
917 begin
918 MsgLock := mh^.api^.Lock(mh);
919 end;
920
921 function MsgUnLock(mh: PAreaHandle): sword; cdecl;
922 begin
923 MsgUnLock := mh^.api^.UnLock(mh);
924 end;
925
926 function MsgSetCurPos(_MsgHandle: PMsgHandle; _Pos: dword): sword; cdecl;
927 begin
928 MsgSetCurPos := _MsgHandle^.sq^.api^.SetCurPos(_MsgHandle, _Pos);
929 end;
930
931 function MsgGetCurPos(_MsgHandle: PMsgHandle): dword; cdecl;
932 begin
933 MsgGetCurPos := _MsgHandle^.sq^.api^.GetCurPos(_MsgHandle);
934 end;
935
936 function MsgMsgnToUid(_AreaHandle: PAreaHandle; _MsgNum: dword): TUMsgId; cdecl;
937 begin
938 MsgMsgnToUid := _AreaHandle^.api^.MsgnToUid(_AreaHandle, _MsgNum);
939 end;
940
941 function MsgUidToMsgn(_AreaHandle: PAreaHandle; _UMsgId: TUMsgId;
942 _Type: sword): dword; cdecl;
943 begin
944 MsgUidToMsgn := _AreaHandle^.api^.UidToMsgn(_AreaHandle, _UMsgId, _Type);
945 end;
946
947 function MsgGetHighWater(_AreaHandle: PAreaHandle): dword; cdecl;
948 begin
949 MsgGetHighWater := _AreaHandle^.api^.GetHighWater(_AreaHandle);
950 end;
951
952 function MsgSetHighWater(_AreaHandle: PAreaHandle; _HighWater: dword): sword; cdecl;
953 begin
954 MsgSetHighWater := _AreaHandle^.api^.SetHighWater(_AreaHandle, _HighWater);
955 end;
956
957 function MsgGetTextLen(_MsgHandle: PMsgHandle): dword; cdecl;
958 begin
959 MsgGetTextLen := _MsgHandle^.sq^.api^.GetTextLen(_MsgHandle);
960 end;
961
962 function MsgGetCtrlLen(_MsgHandle: PMsgHandle): dword; cdecl;
963 begin
964 MsgGetCtrlLen := _MsgHandle^.sq^.api^.GetCtrlLen(_MsgHandle);
965 end;
966
967 // Thes functions aren't actually functions, they are just wrappers to
968 // access some fields in the AreaHandle in a controlled way.
969 // in C they are macros.
970
971 function MsgCurMsg(_AreaHandle: PAreaHandle): integer;
972 begin
973 Result := _AreaHandle^.cur_msg;
974 end;
975
976 function MsgGetCurMsg(_AreaHandle: PAreaHandle): integer;
977 begin
978 Result := _AreaHandle^.cur_msg;
979 end;
980
981 function MsgNumMsg(_AreaHandle: PAreaHandle): integer;
982 begin
983 Result := _AreaHandle^.num_msg;
984 end;
985
986 function MsgGetNumMsg(_AreaHandle: PAreaHandle): integer;
987 begin
988 Result := _AreaHandle^.num_msg;
989 end;
990
991 function MsgHighMsg(_AreaHandle: PAreaHandle): integer;
992 begin
993 Result := _AreaHandle^.high_msg;
994 end;
995
996 function MsgGetHighMsg(_AreaHandle: PAreaHandle): integer;
997 begin
998 Result := _AreaHandle^.high_msg;
999 end;
1000
1001 function MsgGetMsgApiErr: sword; cdecl; external LIBSMAPI_NAME name 'MsgGetMsgApiErr';
1002
1003 function MsgOpenApi(_MInf: PMINF): sword; cdecl; external LIBSMAPI_NAME name 'MsgOpenApi';
1004
1005 function MsgCloseApi: sword; cdecl; external LIBSMAPI_NAME name 'MsgCloseApi';
1006
1007 function MsgOpenArea(_Name: PChar; _Mode: sword; _Type: sword): PAreaHandle; cdecl; external LIBSMAPI_NAME name 'MsgOpenArea';
1008
1009 function MsgValidate(_Type: sword; _Name: PChar): sword; cdecl; external LIBSMAPI_NAME name 'MsgValidate';
1010
1011 function InvalidMsgh(msgh: PMsgHandle): sword; cdecl; external LIBSMAPI_NAME name 'InvalidMsgh';
1012
1013 function InvalidMh(mh: PAreaHandle): sword; cdecl; external LIBSMAPI_NAME name 'InvalidMh';
1014
1015 procedure SquishSetMaxMsg(sq: PAreaHandle; max_msgs: dword; skip_msgs: dword; age: dword); cdecl; external LIBSMAPI_NAME name 'SquishSetMaxMsg';
1016
1017 function SquishHash(f: PChar): dword; cdecl; external LIBSMAPI_NAME name 'SquishHash';
1018
1019 function SdmOpenArea(name: PChar; mode: sword; _type: sword): PAreaHandle; cdecl; external LIBSMAPI_NAME name 'SdmOpenArea';
1020
1021 function SdmValidate(name: PChar): sword; cdecl; external LIBSMAPI_NAME name 'SdmValidate';
1022
1023 function SquishOpenArea(name: PChar; mode: sword; _type: sword): PAreaHandle; cdecl; external LIBSMAPI_NAME name 'SquishOpenArea';
1024
1025 function SquishValidate(name: PChar): sword; cdecl; external LIBSMAPI_NAME name 'SquishValidate';
1026
1027 function JamOpenArea(name: PChar; mode: sword; _type: sword): PAreaHandle; cdecl; external LIBSMAPI_NAME name 'JamOpenArea';
1028
1029 function JamValidate(name: PChar): sword; cdecl; external LIBSMAPI_NAME name 'JamValidate';
1030
1031 function CvtCtrlToKludge(ctrl: PChar): PChar; cdecl; external LIBSMAPI_NAME name 'CvtCtrlToKludge';
1032
1033 function GetCtrlToken(where: PChar; what: PChar): PChar; cdecl; external LIBSMAPI_NAME name 'GetCtrlToken';
1034
1035 function CopyToControlBuf(txt: PChar; newtext: PPChar; length: PLongInt): PChar; cdecl; external LIBSMAPI_NAME name 'CopyToControlBuf';
1036
1037 procedure ConvertControlInfo(ctrl: PChar; orig: PNETADDR; dest: PNETADDR); cdecl; external LIBSMAPI_NAME name 'ConvertControlInfo';
1038
1039 function NumKludges(txt: PChar): sword; cdecl; external LIBSMAPI_NAME name 'NumKludges';
1040
1041 procedure RemoveFromCtrl(ctrl: PChar; what: PChar); cdecl; external LIBSMAPI_NAME name 'RemoveFromCtrl';
1042
1043 function Address(a: PNETADDR): PChar; cdecl; external LIBSMAPI_NAME name 'Address';
1044
1045 function StripNasties(str: PChar): PChar; cdecl; external LIBSMAPI_NAME name 'StripNasties';
1046
1047 end.
1048