mirror of
https://github.com/MidnightCommander/mc
synced 2024-12-22 20:36:50 +03:00
168 lines
6.0 KiB
Plaintext
168 lines
6.0 KiB
Plaintext
-*-outline-*-
|
|
|
|
This is the developers' hint guide.
|
|
Some parts are based on mail messages.
|
|
|
|
Please feel free to add your name to this list:
|
|
by Miguel de Icaza
|
|
|
|
* Working with the Midnight Commander
|
|
|
|
If you plan on working on the Midnight Commander, here are some
|
|
tips on how to make your development easier and my job of merging
|
|
your code easier, I find them useful.
|
|
|
|
o Run make depend if you modify the source code structure (e.g. you
|
|
add/remove include files). This is very important, it will help you
|
|
to get an accurate compilation.
|
|
|
|
o It's recommended that you use GNU Make (if you want to use the
|
|
depend feature).
|
|
|
|
o I work with the tags feature of GNU emacs. Run the make tags
|
|
command to get an updated TAGS file. The command Alt-. will take
|
|
you to any function or variable definition.
|
|
|
|
o Try to keep the indenting style as it is currently. Normally if you
|
|
just created a new file with a different coding style, run the GNU
|
|
indent program on it (remember to make a backup copy first) like
|
|
this: indent -kr -i4 -psl -pcs filename.c
|
|
|
|
o This code is distributed under the GNU General Public License and
|
|
Keep this in mind when adding code to the program.
|
|
|
|
* Code structure.
|
|
|
|
The program uses extensively the dialog manager written by Radek
|
|
Doulik. To understand how the dialog manager works, please read the
|
|
dialog.c and dialog.h. You will find the basic widgets in the files
|
|
widget.c and widget.h. If you understand these files, you are done.
|
|
The files option.c and boxes.c contain some examples of how the
|
|
dialog manager functions are used. For a more complete example, take
|
|
a look at the main.c file.
|
|
|
|
The file util.c has a lot of utility functions. Get familiar with
|
|
them, they are very simple.
|
|
|
|
The code has almost no hardcoded limits, there are a lot of ways of
|
|
avoiding them. For example, when you want to concatenate strings,
|
|
use the g_strconcat functions, it is used like this:
|
|
|
|
new_text = g_strconcat (username, " ", password, NULL);
|
|
|
|
This mallocs the required area, so it still needs to be freed.
|
|
|
|
* Upcoming changes.
|
|
|
|
* Panels
|
|
|
|
* Input handling
|
|
|
|
The routines for input handling on the Midnight Commander are:
|
|
getch, get_key_code, mi_getch and get_event.
|
|
|
|
getch is an interface to the low level system input mechanism. It
|
|
does not deal with the mouse.
|
|
|
|
In the case of ncurses, this is a function implemented in the
|
|
ncurses library that translates key sequences to key codes (\E[A to
|
|
something like KEY_UP and so on).
|
|
|
|
In the case of S-Lang there is no such conversion, that's why we
|
|
load a set of extra definitions.
|
|
|
|
The get_key_code routine converts the data from getch to the
|
|
constants the Midnight Commander uses.
|
|
|
|
In the case of S-Lang, it will actually do all the jobs that getch
|
|
does for curses. In the case of curses it patches a couple of
|
|
sequences that are not available on some terminal databases. This
|
|
routine is the one you want to use if you want a character without
|
|
the mouse support.
|
|
|
|
get_event is the routine you want to use if you want to handle mouse
|
|
events, it will return 0 on a mouse event, -1 if no input is available
|
|
or a key code if there is some input available. This routine in turn
|
|
uses get_key_code to decode the input stream and convert it to useful
|
|
constants.
|
|
|
|
mi_getch is just a wrapper around get_event that ignores all the mouse
|
|
events. It's used only in a couple of places, this routine may return
|
|
-1 if no input is available (if you have set the nodelay option of
|
|
ncurses or S-Lang with nodelay) or a character code if no such option is
|
|
available.
|
|
|
|
* Mouse support.
|
|
|
|
The mouse support in the Midnight Commander is based on the get_event
|
|
routine. The core of the mouse event dispatching is in the
|
|
dlg.c:run_dlg routine.
|
|
|
|
* ncurses
|
|
|
|
Although S-Lang is now used by default, we still support it ncurses. We
|
|
basically are using a small subset of ncurses because we want to be
|
|
compatible with Slang.
|
|
|
|
|
|
* The Dialog manager and the Widgets
|
|
|
|
The Dialog manager and the Widget structure are implemented in
|
|
src/dialog.c. Everything shown on screen is a dialog. Dialogs contain
|
|
widgets, but not everything on screen is a widget. Dialogs can draw
|
|
themselves.
|
|
|
|
Dialogs are connected into a singly linked list using "parent" field.
|
|
Currently active dialog is saved in current_dlg variable. The toplevel
|
|
dialog has parent NULL. Usually it's midnight_dlg.
|
|
|
|
parent parent
|
|
current_dlg ------->another dialog-- ... -->midnight_dlg
|
|
|
|
When the screen needs to be refreshed, every dialog asks its parent to
|
|
refresh first, and then refreshes itself.
|
|
|
|
A dialog is created by create_dlg(). Then it's populated by widgets
|
|
using add_widget(). Then the dialog is run by calling run_dlg(), which
|
|
returns the id of the button selected by the user. Finally, the dialog
|
|
is destroyed by calling destroy_dlg().
|
|
|
|
Widgets are placed to a doubly linked circular list. Each widget has
|
|
previous and next widget.
|
|
|
|
prev next prev next
|
|
widget1 <---------> widget2 <---------> widget3
|
|
^ ^
|
|
-----------------------------------------
|
|
next prev
|
|
|
|
Pressing Tab moves focus to the "next" widget, pressing Shift-Tab moves
|
|
focus to "prev". The tab order is equal to the add order except some
|
|
old code that use the reverse order by setting DLG_REVERSE flag in
|
|
create_dlg() call. Please don't use reverse order in the new code.
|
|
|
|
The initial widget to get focus can be selected by calling
|
|
dlg_select_widget().
|
|
|
|
When creating a dialog, you may want to use a callback that would
|
|
intercept some dialog events. However, many widgets will do the right
|
|
thing by default, so some dialogs can work just fine without callbacks.
|
|
|
|
There are also widget events, which are sent by the dialog to individual
|
|
widgets. Some widgets also have user callbacks.
|
|
|
|
To create your own widget, use init_widget(). In this case, you must
|
|
provide a callback function. Please note that it's not the same as the
|
|
user callback in some widgets.
|
|
|
|
** Button widget
|
|
|
|
** Check box widget
|
|
|
|
** Radio widget
|
|
|
|
** Input widget
|
|
|
|
** Listbox widget
|
|
|