home *** CD-ROM | disk | FTP | other *** search
/ The CDPD Public Domain Collection for CDTV 3 / CDPDIII.bin / bbs / ff810.lha / FF810 / Amiga_E / Docs / Tutorial.doc < prev    next >
Text File  |  1993-01-24  |  14KB  |  357 lines

  1.         +-----------------------------------------------+
  2.         |                        |
  3.         |                 Amiga E v2.1                  |
  4.         |          Compiler for The E Language          |
  5.         |           By Wouter van Oortmerssen           |
  6.         |                        |
  7.          |                    Tutorial                   |
  8.         |                        |
  9.         +-----------------------------------------------+
  10.  
  11.  
  12.         +-----------------------------------------------+
  13.         |               LANGUAGE TUTORIAL               |
  14.         +-----------------------------------------------+
  15.  
  16. This chapter will take you on a step by step guided tour to learn
  17. some E. As soon as you covered the basics in this section, you may
  18. enhance your knowledge of E using reference.doc and the examples on
  19. disk. It's best to try the examples with the compiler as you go along.
  20. It is assumed that the reader possesses some kind of knowledge of any
  21. higher programming language (like C/Pascal) to be able to omit the more
  22. obvious explanations. If you feel that you need more explanation about
  23. some feature, see reference.doc.
  24.  
  25. make sure you managed to install Amiga E in your system as descibed
  26. in 'Compiler.doc' and compiled 'Helloworld.e' as first test.
  27.  
  28. Ok, we'll start of easy. Doesn't it strike you as odd that there's
  29. no such command as CLS in the shell? yes? then we'll write our own:
  30.  
  31. PROC main()
  32.   WriteF('\c',12)
  33. ENDPROC
  34.  
  35. save it as 'cls.e' and compile it with 'ec cls'. then see the result.
  36. nothing shocking sofar, but it gets us to two important points.
  37. first of all, you'll notice that even the smallest programs have to
  38. be put in a function, with the name "main". For now it may look
  39. superfluous, but when you start writing bigger programs, you'll notice
  40. why this is. Secondly, we learn something new about WriteF(), and
  41. where the "F" stands for. In compiling HelloWorld.e, you saw that
  42. WriteF() just prints strings to the console. Here we see that such
  43. a string may contain formatting codes introduced by a "\" and a
  44. character that says what type of formatting will take place, like
  45. "c" is for characters, and "d" for decimals. Any arguments to such
  46. a code are simply added as arguments to WriteF(). Here we print
  47. a character with ascii-code 12, which wipes the screen.
  48.  
  49. And now for something completely different.
  50. Every programmer who starts to learn a new language on the amiga wants
  51. to open his own window. Ok, so lets do that in E.
  52.  
  53. First we use the E-systemfunction OpenW() to open a window:
  54.  
  55. w:=OpenW(20,11,400,100,$200,$F,'My first window in E!',NIL,1,NIL)
  56.  
  57. The first few arguments are ofcourse the coordinates, the
  58. string must be the title (you can check the exact parameters in
  59. reference.doc chapter 9D). Those two hexadecimal values are flags:
  60. the values for those are defined in the module file 'intuition/intuition'.
  61. there are two ways to use flags like that, by using the module:
  62.  
  63. MODULE 'intuition/intuition'
  64.  
  65. idcmpflags:=IDCMP_CLOSEWINDOW
  66.  
  67. or the lazy way, by just writing down the values:
  68.  
  69. idcmpflags:=$200
  70.  
  71. both function exactly equal, and it's up to your personal taste which
  72. you use. Ofcourse, an empty window is boring, so we put a line in it:
  73.  
  74. Line(20,20,50,50,2)
  75.  
  76. Line() knows from the last call to OpenW() where to draw it.
  77. We specified $200 (=IDCMP_CLOSEWINDOW) while opening our
  78. window, because we want the user to press the closegadget if he's
  79. ready watching our window. We accomplish this waiting by:
  80.  
  81. WaitIMessage(w)
  82.  
  83. This function waits for exactly one message to arrive at our window's
  84. port. And because we told intuition we only want to know about the
  85. close-gadget, this must be IDCMP_CLOSEWINDOW.
  86. Now we can close our window:
  87.  
  88. CloseW(w)
  89.  
  90. Putting all this together for our first working window-program:
  91.  
  92.  
  93. /* Opening a window in E */
  94.  
  95. DEF w
  96.  
  97. PROC main()
  98.   IF w:=OpenW(20,11,400,100,$200,$F,'My first window in E!',NIL,1,NIL)
  99.     Line(20,20,50,50,2)
  100.     WaitIMessage(w)
  101.     CloseW(w)
  102.   ENDIF
  103. ENDPROC
  104.  
  105.  
  106. Save this as 'mywindow.e' and compile it with 'ec mywindow'
  107. You'll notice that there's a small addition to our program: the
  108. IF statement. We do this to check if our window could be opened.
  109. You must _always_ check if you're allocating resources like screens,
  110. windows, libraries and memory! If the assignment in the IF-statement
  111. looks strange to you, remember that OpenW() will return NIL (=0) if
  112. it fails, an then w:=OpenW() will also evaluate to 0, which is FALSE.
  113.  
  114. Note that if you want to display text in your window, you cannot use
  115. WriteF(), because WriteF() operates on consoles (or files). however,
  116. there's a "F" funtion that works on rastports (an underlying structure
  117. for both windows and screens and the like): TextF().
  118. For example, add after the Line() function:
  119.  
  120. TextF(20,70,'Well well, i'm writing to my window')
  121.  
  122. You can even use the Colour() function to change the front- and
  123. background colours of the text.
  124.  
  125. Now we'll get a bit more complex: we want to have gadgets in our
  126. window to perform actions. Who has used gadgets in other languages
  127. knows that this means filling in tons of structures. Not in E.
  128. We use the function Gadget() to create gadgets for us. This function
  129. needs buffers to store those structures, so we compute the needed
  130. buffersize in a constant:
  131.  
  132. CONST BUFSIZE=GADGETSIZE*3
  133.  
  134. where "3" is ofcourse the number of gadgets we wish to create.
  135. "GADGETSIZE" is a systemconstant that tells us how many bytes
  136. we need to store one gadget.
  137. Then we create the space as a global array:
  138.  
  139. DEF buf[BUFSIZE]:ARRAY, next
  140.  
  141. we need the variable next as a sort of dummy with the Gadget() function.
  142. now we can start creating our gadgets:
  143.  
  144. next:=Gadget(buf,NIL,1,0,20,20,100,'Gadget 1')
  145. next:=Gadget(next,buf,2,0,20,35,100,'Gadget 2')
  146. next:=Gadget(next,buf,3,0,20,50,100,'Gadget 3')
  147.  
  148. and so our complete program will look like:
  149.  
  150.  
  151.  
  152. /* Opening a window with gadgets in E */
  153.  
  154. MODULE 'intuition/intuition'
  155.  
  156. CONST BUFSIZE=GADGETSIZE*3, IFLAGS=IDCMP_CLOSEWINDOW+IDCMP_GADGETUP
  157.  
  158. DEF buf[BUFSIZE]:ARRAY,next,w,gad:PTR TO gadget
  159.  
  160. PROC main()
  161.   next:=Gadget(buf,NIL,1,0,20,20,100,'Gadget 1')
  162.   next:=Gadget(next,buf,2,0,20,35,100,'Gadget 2')
  163.   next:=Gadget(next,buf,3,0,20,50,100,'Gadget 3')
  164.   IF w:=OpenW(20,11,300,100,IFLAGS,$F,'My first window in E!',NIL,1,buf)
  165.     WHILE WaitIMessage(w)<>IDCMP_CLOSEWINDOW
  166.       gad:=MsgIaddr()
  167.       TextF(20,80,'You pressed gadget #\d',gad.userdata)
  168.     ENDWHILE
  169.     CloseW(w)
  170.   ENDIF
  171. ENDPROC
  172.  
  173.  
  174.  
  175. As you will notice, we now go the straight way of using our intuition
  176. constants by including the module. We define the constant IFLAGS for
  177. all the flags we need: this is now one more, as we also want to hear
  178. about the user pressing gadgets. The OpenW() call has also changed a
  179. little, as the last argument for gadgets, which was NIL in our previous
  180. example, is now filled. Because we now have to respond to two types
  181. of events, our WaitIMessage() construction has changed: the function
  182. returns the class of the event which we didn't use before. Now we'll
  183. only do the WHILE loop for pressed gadgets. We can get a pointer to
  184. the object that caused the event (in our case always a gadget), and
  185. we can look in the .userdata field of the gadget to see which one
  186. was pressed. The value that we find here is exactly the same as what
  187. we wrote as third argument to Gadget(), thus 1,2 or 3. then we
  188. write that value to our window with the TextF() function.
  189.  
  190. Note that to be able to read fields of a structure relative to a
  191. pointer like "gad", we need to tell the compiler what kind of object
  192. it will be pointing to. We do this with the declaration:
  193.  
  194. DEF gad:PTR TO gadget
  195.  
  196. "gad" will still be a variable like the ones we declare like "DEF gad",
  197. but the compiler will now enable us to use it as an object just like
  198. one we create ourselves.
  199.  
  200. Ofcourse there are lots of other ways to process events. one way is
  201. to make a loop, and each item get one message:
  202.  
  203. class:=WaitIMessage(w)
  204.  
  205. and then use a "SELECT class" statement to check out all the
  206. different types of classes.
  207.  
  208. Now we got a pretty good picture of how to write intuition-frontends
  209. to our programs. Another way of creating even more proffesional
  210. interfaces that works remarkably well with E is using the 2.0
  211. gadtools library. Using immediate lists and typed list, you can
  212. create all sorts of gadgets (not just boolean gadgets) with little
  213. more machinery than we used before.
  214. See GadToolsDemo.e how to create interfaces like that.
  215.  
  216. To give just a tiny example how we can write a program that uses
  217. those lists in a powerfull fashion we'll write a program that
  218. puts up a requester with a message from the command line args,
  219. and returns 0 or 5 (WARN) to dos, according to the gadget selected:
  220.  
  221.  
  222. PROC main() RETURN EasyRequestArgs(0,[20,0,0,arg,'ok|cancel'],0,NIL)*5
  223.  
  224.  
  225. Yes, indeed, that's the whole program. Note that it only runs on 2.0
  226. or higher. save as 'select.e', and compile 'ec select'. now run:
  227.  
  228. 1> select Select "ok" if you wish to perform this action
  229.  
  230. This would present the requester and return a value suitable for
  231. tests in scripts ("IF WARN ...").
  232.  
  233. The compactness of this example lies in the fact that normally functions
  234. like EasyRequestArgs get pointers to structures as arguments,
  235. which have to build up bit by bit and then given as argument to the
  236. function (see the C-example for this function in the RKRM's to see
  237. what i mean). In E there's the list-feature which is unique for
  238. procedural programming languages which enables you to build complex
  239. datastructures 'on-the-fly' without seperately defining them and
  240. making identifiers for them.
  241.  
  242. in this case we made a structure of type "easystruct", (which is
  243. an object defined in 'intuition/intuition.m') that is
  244. the second argument to the function, like:
  245.  
  246. [20,0,0,arg,'ok|cancel']:easystruct
  247.  
  248. the :<type> specifies the type of the data structure; default is :LONG,
  249. and as all fields of easystruct are again of type LONG we left the ":"
  250. spec. out. Always note that the value of such expressions is a pointer
  251. to the datastructure in memory.
  252.  
  253. As a second example we'll use taglists: we'll open a screen in 2.0
  254. fashion with OpenScreenTaglist():
  255.  
  256. s:=OpenScreenTagList(0,[SA_DEPTH,8,SA_DISPLAYID,$8020,0])
  257.  
  258. as you see, we need not build up a taglist structure seperately,
  259. nor need we link any varargs hacks.
  260.  
  261.  
  262. Next we'll be watching how to use librarycalls other than those
  263. builtin (like EasyRequestArgs() we just saw from intuition):
  264. We'll be using the "asl.library" to pop up a filerequester
  265. (again, this is 2.0 and up only). This example is a short version
  266. of 'AslDemo.e', and is also featured in reference.doc in the
  267. modules chapter. Here we'll explain how it works.
  268.  
  269.  
  270. MODULE 'Asl', 'libraries/Asl'
  271.  
  272. PROC main()
  273.   DEF req:PTR TO filerequestr
  274.   IF aslbase:=OpenLibrary('asl.library',37)
  275.     IF req:=AllocFileRequest()
  276.       IF RequestFile(req) THEN WriteF('File: "\s" in "\s"\n',req.file,req.dir)
  277.       FreeFileRequest(req)
  278.     ENDIF
  279.     CloseLibrary(aslbase)
  280.   ENDIF
  281. ENDPROC
  282.  
  283.  
  284. Until recently, we only used modules to load definitions of constanst
  285. and objects; now we'll use modules to define new functioncalls.
  286.  
  287. as you see from the module statement, the modules that define
  288. librarycalls are in the root of emodules: while all other defintions
  289. are in the specific directories (read all about that in reference.doc).
  290.  
  291. Such a module provides us with a variable for base address of
  292. the library: mostly this is <libname>+"base". in this example,
  293. we have to fill the variable aslbase with a correct value before we
  294. can use it's functions, and at the end we have to close it again.
  295. As you can see, the actual usage of the library is very simple.
  296. the hear about the result, we need to check our requester structure
  297. that we got returned from AllocFileRequest() for the members
  298. req.file and req.dir . RequestFile() returns TRUE or FALSE depending
  299. on the fact if a file was selected in the first place.
  300.  
  301. There are lots of sources in the examples/ dir that show how to
  302. interface with other libraries in a similar fashion, for example
  303. with the great "ReqTools.library"
  304.  
  305.  
  306. In our next example we'll be developing a small utility from
  307. 'sources/utilities' step by step: DirQuick.e.
  308. It is a nice and short nononsence three column directory-lister.
  309.  
  310.  
  311. MODULE 'dos/dos'
  312.  
  313. PROC main()
  314.   DEF info:fileinfoblock,lock,ok,c=0
  315.   IF lock:=Lock(arg,-2)
  316.     IF Examine(lock,info)
  317.       IF info.direntrytype>0
  318.         WriteF('Directory of: \s\n',info.filename)
  319.         WHILE ExNext(lock,info)
  320.           IF info.direntrytype>0
  321.             WriteF('\e[1;32m\l\s[25]\e[0;31m',info.filename)
  322.           ELSE
  323.             WriteF('\l\s[17] \r\d[7]',info.filename,info.size)
  324.           ENDIF
  325.           WriteF(IF c++=2 THEN (c:=0)+'\n' ELSE ' ')
  326.         ENDWHILE
  327.         IF c THEN WriteF('\n')
  328.       ELSE
  329.         WriteF('No Dir!\n')
  330.       ENDIF
  331.     ENDIF
  332.     UnLock(lock)
  333.   ELSE
  334.     WriteF('What ?!?\n')
  335.   ENDIF
  336. ENDPROC
  337.  
  338. We need only one module, 'dos/dos.m' to tell us about the object
  339. "fileinfoblock". Then we encounter something new: our variable
  340. "info" is not a pointer, but has as type an object. Such a declaration
  341. gives us space on the stack for a complete fileinfoblock structure.
  342. To get to the directory, we have to try to lock it's name, and
  343. then examine it. That's were our "info" block comes in: the function
  344. Examine() fills our structure with data it reads from disk. Before
  345. reading all directory entries in this fashion with ExNext(), we'll
  346. have to check if the block is a directory (if direntrytype>0).
  347. With each entry we display colour #2 for directories, and
  348. normal display (with filesize) for the files. Compare those format-
  349. strings with the output, and with the stringformatting descriptions
  350. in 'reference.doc'. With the variable "c" we check howmany columns we
  351. did sofar: after every 3 we write a <lf> ('\n').
  352.  
  353.  
  354. That's it for the tutorial: to learn more, read all the documentation
  355. thoroughly, and study the examples. But most of all: try your own
  356. programs!
  357.