HACKING 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401
  1. This document
  2. =============
  3. This document is a guide how to develop GNU Midnight Commander. It's
  4. quite incomplete, but may be worth reading anyway.
  5. The document was written by Miguel de Icaza and reworked by Pavel
  6. Roskin. Some parts were taken from the messages posted in the mailing
  7. lists.
  8. Compiling from CVS
  9. ==================
  10. To compile GNU Midnight commander from CVS, the following software is
  11. required:
  12. Autoconf 2.52 and above (latest is recommended)
  13. Automake 1.5 and above (latest is recommended)
  14. Gettext 0.11.5 and above
  15. Glib 1.2.6 and above (2.x is recommended)
  16. It is recommended that all those tools are installed with the same
  17. prefix. Make sure that the tools with the right version are first in
  18. PATH.
  19. Once you have the right tools, run `autogen.sh' - it will generate
  20. everything necessary for the build and run `configure'. Arguments given
  21. to `autogen.sh' are passed to `configure'. Then run `make' as usually.
  22. The distribution tarball is created by the command `make distcheck'.
  23. This command can take a while.
  24. Currently snapshots are made on Debian unstable and use the versions of
  25. the tools from the unstable repository. Yes, the rpm packages are made
  26. on Debian too.
  27. Note that the version of gettext doesn't affect the snapshot because the
  28. distributed files are installed by gettext from archives for the version
  29. used in the AM_GNU_GETTEXT_VERSION macro, which is 0.11.5.
  30. Working with GNU Midnight Commander
  31. ===================================
  32. Please use the CVS version. It may be quite different from the released
  33. versions. A lot of cleanup is going on. The CVS version may be easier
  34. to understand, in addition to the obvious fact that the merging is
  35. easier with the CVS version.
  36. There are some tools in the maint directory on CVS. They are not
  37. included with releases or snapshots. You may be interested to look at
  38. them if you are going to work on the project for an extended period of
  39. time. In particular, the release procedure is described there.
  40. In order to compile GNU Midnight Commander from a clean CVS checkout you
  41. should use autogen.sh instead of configure. Arguments passed to
  42. autogen.sh are passed to configure after it's generated.
  43. GNU Midnight Commander uses Autoconf and Automake, with make it fairly
  44. portable. However, GNU Make is strongly recommended for development
  45. because other versions of make may not track dependencies properly.
  46. This is very important for correct compilation, especially if you change
  47. any header files.
  48. If you add or remove any files, please change Makefile.am in the same
  49. directory accordingly. When doing significant changes in the tree
  50. structure, "make distcheck" is strongly recommended.
  51. If you have etags installed, you can run "make tags" and use tags in
  52. emacs to find functions or variables. But you can also use the internal
  53. editor and the "Find File" command to find any text in the source tree.
  54. GNU Autoconf allows you to test several different configurations are
  55. once. To do so, use the so called out-of-tree (or VPATH) compilation.
  56. Create separate empty directories and run configure with full path from
  57. those directories, like this:
  58. cd /usr/local/src
  59. mkdir mc-slang
  60. mkdir mc-ncurses
  61. cd mc-slang
  62. /usr/local/src/mc/configure && make all
  63. cd ../mc-ncurses
  64. /usr/local/src/mc/configure --with-screen=ncurses && make all
  65. Please use the same indentation as other developers. To indent a block,
  66. select in the internal editor and use Shift-F9 to call the external
  67. indent. For historic reasons, GNU Midnight Commander used formatting
  68. that is not default for GNU Indent. Please put following text to your
  69. ~/.indent.pro file to make GNU Indent follow the style used in GNU
  70. Midnight Commander:
  71. -kr -i4 -pcs -psl --ignore-newlines
  72. It's OK to indent the whole function if you edit it. However, please
  73. refrain from it if you are posting your patch for review. In this case
  74. you would save time of other developers if you only include significant
  75. changes. The developer applying your patch can format the code for you.
  76. Please keep in mind that the VFS subsystem is licensed under LGPL, while
  77. the rest of the code uses GPL.
  78. Code structure - outline
  79. ========================
  80. The code is located in following directories.
  81. vfs - Virtual File System.
  82. This library provides filesystem-like access to various data, such are
  83. archives and remote filesystems. To use VFS, you should use wrappers
  84. around POSIX calls. The wrappers have names composed from "mc_" and the
  85. standard name of the function. For example, to open a file on VFS, use
  86. mc_open() instead.
  87. edit - the internal editor.
  88. This code has been contributed by Paul Sheer, the author of Cooledit.
  89. The internal editor shares some code with Cooledit, but now it's
  90. developed as part of GNU Midnight Commander.
  91. src - the main part of the code.
  92. This code includes the dialog manager written by Radek Doulik and source
  93. code of the main application.
  94. slang - stripped down S-Lang library.
  95. It's provided to allow compilation that don't have the S-Lang library
  96. with complete headers or the library is broken. Please avoid changing
  97. this code. If you do change it, please consider contributing your
  98. changes to the maintainers of S-Lang.
  99. Code structure - details
  100. ========================
  101. GNU Midnight Commander uses extensively the dialog manager written by
  102. Radek Doulik. To understand how the dialog manager works, please read
  103. the dialog.c. You will find the basic widgets in the files widget.c.
  104. Some more high-level functions, e.g. to display a message box, are
  105. located in wtools.c. This file also contains the Quick Dialog code,
  106. which makes it easier to create complex dialogs.
  107. Files findme.c, popt.c, poptconfig.c, popthelp.c and poptparse.c come
  108. from the popt library used to parse the command line. They should not
  109. be modified unless absolutely necessary.
  110. The files util.c and utilunix.c have a lot of utility functions. Get
  111. familiar with them, they are very simple.
  112. glib is used for memory allocation and for some utility functions, such
  113. as manipulation with lists and trees. gmodule (part of the glib
  114. distribution) is used to load some libraries dynamically at the run
  115. time.
  116. Thanks to glib, the code has almost no hardcoded limits, since there are
  117. many ways to avoid them. For example, when you want to concatenate
  118. strings, use the g_strconcat() function:
  119. new_text = g_strconcat (username, " ", password, (char *)0);
  120. This allocates new memory for the string, so you should use g_free() on
  121. the result.
  122. The parent of all dialogs is called midnight_dlg. Both panels are
  123. widgets in that dialog. Other widgets include the menu, the command
  124. line and the button bar.
  125. Input handling
  126. ==============
  127. The routines for input handling on the Midnight Commander are:
  128. getch, get_key_code, mi_getch and get_event.
  129. getch is an interface to the low level system input mechanism. It
  130. does not deal with the mouse.
  131. In the case of ncurses, this is a function implemented in the
  132. ncurses library that translates key sequences to key codes (\E[A to
  133. something like KEY_UP and so on).
  134. In the case of S-Lang there is no such conversion, that's why we
  135. load a set of extra definitions.
  136. The get_key_code routine converts the data from getch to the
  137. constants the Midnight Commander uses.
  138. In the case of S-Lang, it will actually do all the jobs that getch
  139. does for curses. In the case of curses it patches a couple of
  140. sequences that are not available on some terminal databases. This
  141. routine is the one you want to use if you want a character without
  142. the mouse support.
  143. get_event is the routine you want to use if you want to handle mouse
  144. events, it will return 0 on a mouse event, -1 if no input is available
  145. or a key code if there is some input available. This routine in turn
  146. uses get_key_code to decode the input stream and convert it to useful
  147. constants.
  148. mi_getch is just a wrapper around get_event that ignores all the mouse
  149. events. It's used only in a couple of places, this routine may return
  150. -1 if no input is available (if you have set the nodelay option of
  151. ncurses or S-Lang with nodelay) or a character code if no such option is
  152. available.
  153. Mouse support
  154. =============
  155. The mouse support in the Midnight Commander is based on the get_event
  156. routine. The core of the mouse event dispatching is in the
  157. dlg.c:run_dlg routine.
  158. ncurses
  159. =======
  160. Although S-Lang is now used by default, we still support ncurses. We
  161. basically are using a small subset of ncurses because we want to be
  162. compatible with Slang.
  163. The Dialog manager and the Widgets
  164. ==================================
  165. The Dialog manager and the Widget structure are implemented in
  166. src/dialog.c. Everything shown on screen is a dialog. Dialogs contain
  167. widgets, but not everything on screen is a widget. Dialogs can draw
  168. themselves.
  169. Dialogs are connected into a singly linked list using "parent" field.
  170. Currently active dialog is saved in current_dlg variable. The toplevel
  171. dialog has parent NULL. Usually it's midnight_dlg.
  172. parent parent
  173. current_dlg ------->another dialog-- ... -->midnight_dlg
  174. When the screen needs to be refreshed, every dialog asks its parent to
  175. refresh first, and then refreshes itself.
  176. A dialog is created by create_dlg(). Then it's populated by widgets
  177. using add_widget(). Then the dialog is run by calling run_dlg(), which
  178. returns the id of the button selected by the user. Finally, the dialog
  179. is destroyed by calling destroy_dlg().
  180. Widgets are placed to a doubly linked circular list. Each widget has
  181. previous and next widget.
  182. prev next prev next
  183. widget1 <---------> widget2 <---------> widget3
  184. ^ ^
  185. -----------------------------------------
  186. next prev
  187. Pressing Tab moves focus to the "next" widget, pressing Shift-Tab moves
  188. focus to "prev". The tab order is equal to the add order except some
  189. old code that use the reverse order by setting DLG_REVERSE flag in
  190. create_dlg() call. Please don't use reverse order in the new code.
  191. The initial widget to get focus can be selected by calling
  192. dlg_select_widget().
  193. When creating a dialog, you may want to use a callback that would
  194. intercept some dialog events. However, many widgets will do the right
  195. thing by default, so some dialogs can work just fine without callbacks.
  196. There are also widget events, which are sent by the dialog to individual
  197. widgets. Some widgets also have user callbacks.
  198. To create your own widget, use init_widget(). In this case, you must
  199. provide a callback function. Please note that it's not the same as the
  200. user callback in some widgets.
  201. Where to Find Bug Reports and Patches
  202. =====================================
  203. The official place for bug reports is:
  204. http://www.midnight-commander.org/
  205. There are various unofficial sources where bug reports and patches can
  206. be found (NOT maintained by the MC team).
  207. http://bugs.debian.org/mc
  208. The bug tracking system for Debian, a package collection mainly
  209. for GNU/Linux and the Hurd.
  210. http://bugzilla.redhat.com/bugzilla/buglist.cgi?component=mc
  211. Bugs reported in Redhat Linux.
  212. http://www.openbsd.org/cgi-bin/cvsweb/ports/misc/mc/patches/
  213. The patches that are applied for the OpenBSD version of MC.
  214. http://www.freebsd.org/cgi/cvsweb.cgi/ports/misc/mc/files/
  215. The patches that are applied for the FreeBSD version of MC.
  216. http://cvsweb.netbsd.org/bsdweb.cgi/pkgsrc/sysutils/mc/patches/
  217. The patches that are applied for the NetBSD version of MC.
  218. http://www.gentoo.org/cgi-bin/viewcvs.cgi/app-misc/mc/files/?hideattic=1
  219. The patches that are applied for the Gentoo Linux version of MC.
  220. Programming Tips
  221. ================
  222. (This list should be sorted alphabetically.)
  223. ?: This operator has a precedence that is easy to use the wrong way. You
  224. might think that
  225. int right = 25 + have_frame() ? 1 : 0; /* WRONG */
  226. results in either 25 or 26. This is not the case. The C compiler
  227. sees this as:
  228. int right = (25 + have_frame()) ? 1 : 0; /* WRONG */
  229. To avoid this, put the ?: in parentheses, like this
  230. int right = 25 + (have_frame() ? 1 : 0); /* RIGHT */
  231. If the condition is more complicated, put it in additional
  232. parentheses:
  233. int right = 25 + ((have_frame()) ? 1 : 0); /* RIGHT */
  234. const: For every function taking a string argument, decide whether you
  235. (as a user of the function) would expect that the string is modi-
  236. fied by the function. If not, declare the string argument as
  237. "const char *". If your implementation needs to modify the string,
  238. use g_strdup to create a local copy.
  239. const_cast: Has been replaced by str_unconst.
  240. g_free: g_free handles NULL argument too, no need for the comparison.
  241. Bad way:
  242. if (old_dir) g_free (old_dir);
  243. Right way:
  244. g_free (old_dir);
  245. g_strdup: When you use g_strdup to create a local copy of a string, use
  246. the following pattern to keep the reference.
  247. char * const pathref = g_strdup(argument);
  248. /* ... */
  249. g_free (pathref);
  250. The "const" will make the pointer unmodifiable (pathref++
  251. is not possible), but you can still modify the string contents.
  252. g_strlcpy: Whenever you use this function, be sure to add "glibcompat.h"
  253. to the included headers. This is because in glib-1.2 there is
  254. no such function.
  255. NULL: When you pass NULL as an argument of a varargs function, cast the
  256. 0 to the appropriate data type. If a system #defines NULL to
  257. be 0 (at least NetBSD and OpenBSD do), and the sizes of int and
  258. a pointer are different, the argument will be passed as int 0,
  259. not as a pointer.
  260. This tip applies at least to catstrs (edit/edit.h), execl(3),
  261. execle(3), execlp(3), g_strconcat (glib), parent_call
  262. (src/background.h), parent_call_string (src/background.h),
  263. rpc_get (vfs/mcfsutil.h), rpc_send (vfs/mcfsutil.h).
  264. example:
  265. char *path = g_strconcat("dir", "/", "file", (char *)0);
  266. size_t: This data type is suitable for expressing sizes of memory or the
  267. length of strings. This type is unsigned, so you need not check
  268. if the value is >= 0.
  269. strncpy: Don't use this function in newly created code. It is slow, insecure
  270. and hard to use. A much better alternative is g_strlcpy (see there).
  271. str_unconst: We use many libraries that do not know about "const char *"
  272. and thus declare their functions to require "char *". If you
  273. know for sure that an external function does not modify the
  274. string, you can "unconst" a string using the function
  275. str_unconst(). If you are not sure whether the function modifies
  276. the string, you should use g_strdup() to pass a copy of a string
  277. to the function. Don't forget to call g_free() after work is done.
  278. unused: Unused arguments of a function can be marked like this:
  279. void do_nothing(int data)
  280. {
  281. (void) &data;
  282. }
  283. This tells the GNU C Compiler not to emit a warning, and has no
  284. side effects for other compilers.