forked from alb42/MCAmiga
-
Notifications
You must be signed in to change notification settings - Fork 0
/
MCAmiga.pas
444 lines (423 loc) · 13.1 KB
/
MCAmiga.pas
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
program MCAmiga;
{$mode objfpc}{$H+}
uses
ATHreads,
workbench, icon, AppWindowUnit, Intuition,
{$ifdef RELEASE}
Versioncheck,
{$endif}
Types, SysUtils, Video, mouse, keyboard,
{$if defined(Amiga68k) or defined(MorphOS) or defined(AROS)}
xad, xadarchive,
{$endif}
FileListUnit, dialogunit, EventUnit, archiveunit, searchunit;
var
Src: TFileList;
Dest: TFileList;
Left, Right: TFileList;
LeftDefaultPath: string = '';
RightDefaultPath: string = '';
// Swap Destination and Source -> change the Focus
procedure SwapSrcDest;
var
Temp: TFileList;
begin
Temp := Dest;
Dest := Src;
Src := Temp;
Src.IsActive := True;
Dest.IsActive := False;
end;
// Mouse Event, handling all Mouse Events of main application
// connected to EventUnit OnMouseEvent
procedure MouseEvent(Me: TMouseEvent);
var
P: TPoint;
Len: LongInt;
begin
// react on Mouse down, Panel will check for right/left
if me.Action = MouseActionDown then
begin
P := Point(Me.x, Me.y);
// check if left panel is hit by mouse
if Left.PanelRect.Contains(P) then
begin
// click to panel also activate the panel
if Right.IsActive then
SwapSrcDest;
Left.MouseEvent(Me);
Exit;
end;
// check if right panel is hit by mouse
if Right.PanelRect.Contains(P) then
begin
if Left.IsActive then
SwapSrcDest;
Right.MouseEvent(Me);
Exit;
end;
// special handling of the Bottom F Key Menu, if visible
if (Me.y = ScreenHeight - 1) and DefShowMenu then
begin
Len := ScreenWidth div 10;
case Me.x div Len of
0:begin //F1
ShowHelp;
Left.Update(False);
Right.Update(False);
end;
1:begin // F2
ShowTools(Src, Dest);
Left.Update(False);
Right.Update(False);
end;
2:begin //F3
if me.buttons = MouseLeftButton then
Src.ViewFile(ViewerLink);
if me.buttons = MouseRightButton then
Src.ViewFile(AltViewerLink);
end;
3:begin //F4
if me.buttons = MouseLeftButton then
Src.EditFile(EditLink);
if me.buttons = MouseRightButton then
Src.EditFile(AltEditLink);
end;
4:begin //F5
Src.CopyFiles;
end;
5:begin //F6
if me.buttons = MouseLeftButton then
Src.MoveFiles;
if me.buttons = MouseRightButton then
Src.Rename();
end;
6:begin //F7
Src.MakeDir();
end;
7:begin //F8
Src.DeleteSelected();
end;
9: begin // F10
if AskQuestion('Quit Program') then
begin
Terminate;
Exit;
end;
Left.Update(False);
Right.Update(False);
end;
end;
end;
end
else
begin
// all other events just gibve to src panel -> needed
// for click and move to selece
Src.MouseEvent(Me);
end;
end;
// Key Event, handling all key Events of main application
// connected to EventUnit OnKeyEvent
procedure KeyEvent(Ev: TKeyEvent);
var
st: Byte;
begin
st := GetKeyEventShiftState(Ev);
case TranslateKeyEvent(Ev) and $ffff of
$0F09, $0F00: SwapSrcDest; // (Shift) TAB -> change Focus to other window
kbdLeft, $0008, $0034: Src.GoToParent; // Backspace, Left -> Parent
$1C0D, $000D: Src.EnterPressed(st and kbShift <> 0, True); // return -> Enter Dir/Assign/Drive
kbdRight, $0036: Src.EnterPressed(False, False); // return -> Enter Dir/Assign/Drive
kbdUp, $38: begin if (st and kbShift) <> 0 then Src.SelectActiveEntry(False); Src.ActiveElement := Src.ActiveElement - 1; end; // cursor up -> Move around
kbdDown, $32: if (st and kbShift) <> 0 then Src.SelectActiveEntry else Src.ActiveElement := Src.ActiveElement + 1; // cursor down -> Move around
kbdPgUp, $39, $8D00: Src.ActiveElement := Src.ActiveElement - 10; // pg up -> Move around
kbdPgDn, $33, $9100: Src.ActiveElement := Src.ActiveElement + 10; // pg down -> Move around
kbdHome, $37, $7300: Src.ActiveElement := 0; // Home -> Move around
kbdEnd, $31, $7400: Src.ActiveElement := MaxInt; // end -> Move around
$1312, $1300: Src.Update(True); // Ctrl + R Alt + R -> Reload
$180F, $1800: Dest.CurrentPath := Src.CurrentPath; // Ctrl + O Alt + O -> copy path to dest
$2004, $2000: Src.CurrentPath := ''; // Ctrl + D Alt + D -> back to drives/Assign
$1F13: Src.SearchList; // Crtl + S -> jump mode
$2106: begin // Ctrl + F -> toggle visibility of bottom menu
DefShowMenu := not DefShowMenu;
ClearScreen;
Left.Resize(Rect(0, 0, (ScreenWidth div 2) - 1, ScreenHeight - 1));
Right.Resize(Rect((ScreenWidth div 2), 0, ScreenWidth - 1, ScreenHeight - 1));
end;
kbdInsert, $23, $30, $20: begin // Insert, #, 0, Space -> Select file, scan dir size
if ((st and kbShift) <> 0) and (TranslateKeyEvent(Ev) and $ffff = $20) then
begin
Src.ScanSize;
Left.Update(False);
Right.Update(False);
end
else
Src.SelectActiveEntry;
end;
$002B: Src.SelectByPattern(True); // + -> Select files by pattern
$002D: Src.SelectByPattern(False); // - -> Deselect files by pattern
kbdF10, $011B: begin // F10, ESC -> Quit
if AskQuestion('Quit Program') then
begin
Terminate;
Exit;
end;
Left.Update(False);
Right.Update(False);
end;
kbdF3: begin // F3 -> View
if st and kbShift <> 0 then
Src.ViewFile(AltViewerLink)
else
Src.ViewFile(ViewerLink);
end;
kbdF4: begin // F4 -> Edit
if st and kbShift <> 0 then
Src.EditFile(AltEditLink)
else
Src.EditFile(EditLink);
end;
kbdF5: Src.CopyFiles; // F5 -> Copy/CopyAs
kbdF6: begin // F6 -> Move/Rename
if st and kbShift <> 0 then
Src.Rename()
else
Src.MoveFiles;
end;
kbdF7: Src.MakeDir(); // F7 -> MakeDir
kbdF8, kbdDelete: Src.DeleteSelected(); // F8 -> Delete
kbdF2: begin // F2
if ((st and kbAlt) <> 0) or ((st and kbCtrl) <> 0) then
begin
Right.CurrentPath := '';
end
else
begin
ShowTools(Src, Dest);
Left.Update(False);
Right.Update(False);
end;
end;
kbdF1: begin // F1 -> Help
if ((st and kbAlt) <> 0) or ((st and kbCtrl) <> 0) then
begin
Left.CurrentPath := '';
end
else
begin
ShowHelp;
Left.Update(False);
Right.Update(False);
end;
end
{$ifndef RELEASE}
else
if (ev and $FFFF) <> 0 then writeln('Key: $' + HexStr(TranslateKeyEvent(Ev), 4), ' Shiftstate ', st);
{$endif}
end;
end;
var
MySize: TSize; // prevent endless looping of resize
// Resize of Window, is not supported by the original video unit, so we have to fake that
// by changing the video mode
procedure ResizeEvent(NewWidth, NewHeight: Integer);
var
Mode: TVideoMode;
begin
// prevent looping
if (NewWidth > 0) and (NewHeight > 0) and ((NewWidth <> MySize.cx) or (NewHeight <> MySize.cy)) then
begin
Mode.Col := 0;
// get video mode, it still has the old sizes, set the new sizes, and set again!
Video.GetVideoMode(Mode);
Mode.Col := NewWidth;
Mode.Row := NewHeight;
// careful at this point a resize event will occur again
Video.SetVideoMode(Mode);
MySize.cx := NewWidth;
MySize.cy := NewHeight;
// we have a new FAST clearscreen, there for we can do that here
ClearScreen;
// let the panels resize
Left.Resize(Rect(0, 0, (ScreenWidth div 2) - 1, ScreenHeight - 1));
Right.Resize(Rect((ScreenWidth div 2), 0, ScreenWidth - 1, ScreenHeight - 1));
end;
end;
// idle event, sent to src panel -> used to scroll too long filenames
procedure IdleEvent;
begin
Src.IdleEvent;
end;
// Event when a item is dropped on the app window
procedure DropEvent(Path, Name: string; MousePos: TPoint);
begin
// not a path -> nothing to do
if Path = '' then
Exit;
// Which panel is hit
if PtInRect(Left.PanelRect, MousePos) then
begin
Left.CurrentPath := Path;
if Name <> '' then
Left.ActivateFile(Name);
end else
if PtInRect(Right.PanelRect, MousePos) then
begin
Right.CurrentPath := Path;
if Name <> '' then
Right.ActivateFile(Name);
end;
end;
// Get a ToolType as String
// Entry = name of ToolType
// Default = if ToolType Entry not found what to return
// Returns the Value begin the '=' of the toolType if it's only a keyword
// it will return an empty string (then better to have Default <> '')
function GetStrToolType(DObj: PDiskObject; Entry: string; Default: string): string;
var
Res: PChar;
{$ifdef AROS}
TT: PPchar;
s: string;
{$endif}
begin
Result := Default;
// just to be sure
if not assigned(Dobj) then
Exit;
if not Assigned(Dobj^.do_Tooltypes) then
Exit;
// aros does not have this call until now, we have to parse for ourself
{$ifdef AROS}
TT := Dobj^.do_Tooltypes;
while Assigned(TT^) do
begin
s := TT^;
if (Pos('=', s) > 0) and (Trim(Copy(s, 1, Pos('=', s) - 1)) = Entry) then
begin
Result := copy(s, Pos('=', s) + 1, Length(s));
Break;
end;
Inc(TT);
end;
{$else}
// get the ToolType
Res := FindToolType(Dobj^.do_Tooltypes, PChar(Entry));
if Assigned(Res) then
Result := Res;
{$endif}
end;
// Get the settings from the icon
procedure GetSettings;
var
DObj: PDiskObject;
begin
// Load icon propertied
DObj := GetDiskObject(PChar(ParamStr(0)));
if Assigned(DObj) then
begin
// Viewer
ViewerLink := GetStrToolType(DObj, 'VIEWER', ViewerLink);
AltViewerLink := GetStrToolType(DObj, 'VIEWER2', AltViewerLink);
// Editor
EditLink := GetStrToolType(DObj, 'EDITOR', EditLink);
AltEditLink := GetStrToolType(DObj, 'EDITOR2', AltEditLink);
// Defaults but with th
LeftDefaultPath := GetStrToolType(DObj, 'LEFT', LeftDefaultPath);
RightDefaultPath := GetStrToolType(DObj, 'RIGHT', RightDefaultPath);
// WithDevices
WithDevices := GetStrToolType(DObj, 'WITHDEVICES', '0') <> '0';
// ShowMenu
DefShowMenu := GetStrToolType(DObj, 'SHOWMENU', '0') = '';
// Own Screen
FullScreen := GetStrToolType(DObj, 'FULLSCREEN', '0') = '';
// Default Shell settings (CON:....)
DefaultShell := GetStrToolType(DObj, 'DEFAULTSHELL', '');
//
FreeDiskObject(DObj);
end;
end;
// Main procedure of MCAmiga
procedure StartMe;
var
Mode: TVideoMode;
VideoFontHeight, x,y: LongInt;
begin
LockScreenUpdate;
// defaults are available on every amiga style system
LeftDefaultPath := 'sys:';
RightDefaultPath := 'ram:';
// get prefs from tooltypes
GetSettings;
// connect Events
OnKeyPress := @KeyEvent;
OnMouseEvent := @MouseEvent;
OnResize := @ResizeEvent;
OnIdle := @IdleEvent;
OnDropItem := @DropEvent;
// Check Video size, set fullscreen if needed
Mode.Col := 0;
Video.GetVideoMode(Mode);
if FullScreen then
Mode.color := False;
Video.SetVideoMode(Mode);
// create Main Panels, and link them together
Left := TFileList.Create(Rect(0, 0, (ScreenWidth div 2) - 1, ScreenHeight - 1));
Right := TFileList.Create(Rect((ScreenWidth div 2), 0, ScreenWidth - 1, ScreenHeight - 1));
Left.OtherSide := Right;
Right.OtherSide := Left;
// src and dest for easier handling
Src := Left;
Dest := Right;
// set the path for both panels -> both will load these and redraw
Left.CurrentPath := LeftDefaultPath;
Right.CurrentPath := RightDefaultPath;
// nasty hack to make FullScreen work
if FullScreen then
begin
// I don't know how big the char ist
// luckyly there is a video call translating the real to video coords
// so we can claculate back
x := 1;
y := 1;
VideoFontHeight := 16;
TranslateToCharXY(100, 100, x,y);
if y > 0 then
VideoFontHeight := 100 div y;
// start resize to the new calculated screen size
ResizeEvent(VideoWindow^.GZZWidth div 8, VideoWindow^.GZZHeight div VideoFontHeight);
// strangely the opened video screen is not active
ActivateWindow(VideoWindow);
end;
// all done lets draw
UnlockScreenUpdate;
UpdateScreen(True);
Right.ActiveElement := 0;
Left.IsActive := True;
{$ifdef RELEASE}
CreateVersion;
{$endif}
// Activate the App Window
MakeAppWindow;
// run the main event cycle
RunApp;
// Application is closed, remove everything
DestroyAppWindow;
//
Left.Free;
Right.Free;
end;
begin
{$ifdef RELEASE}
DoVersionInformation;
{$endif}
InitVideo;
InitMouse;
InitKeyboard;
Video.SetWindowTitle('MyCommander Amiga ' + NumVERSION, Copy(VERSION, 6, 12));
StartMe;
DoneKeyboard;
DoneMouse;
DoneVideo;
end.