diff --git a/.DS_Store b/.DS_Store index fe73a055..fdc86689 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/Grafx2.xcodeproj/project.pbxproj b/Grafx2.xcodeproj/project.pbxproj index 44ef9528..fa145b90 100644 --- a/Grafx2.xcodeproj/project.pbxproj +++ b/Grafx2.xcodeproj/project.pbxproj @@ -12,6 +12,12 @@ 002F3A2E09D0888800EBEB88 /* SDLMain.m in Sources */ = {isa = PBXBuildFile; fileRef = 002F3A2C09D0888800EBEB88 /* SDLMain.m */; }; 002F3A3F09D088BA00EBEB88 /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = 002F3A3E09D088BA00EBEB88 /* main.c */; }; 8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; }; + F5142653101F6CC5006CF3C4 /* font_Classic.png in Copy skins */ = {isa = PBXBuildFile; fileRef = F514264D101F6CB8006CF3C4 /* font_Classic.png */; }; + F5142654101F6CC5006CF3C4 /* font_Fairlight.png in Copy skins */ = {isa = PBXBuildFile; fileRef = F514264E101F6CB8006CF3C4 /* font_Fairlight.png */; }; + F5142655101F6CC5006CF3C4 /* font_Fun.png in Copy skins */ = {isa = PBXBuildFile; fileRef = F514264F101F6CB9006CF3C4 /* font_Fun.png */; }; + F5142656101F6CC5006CF3C4 /* font_Melon.png in Copy skins */ = {isa = PBXBuildFile; fileRef = F5142650101F6CB9006CF3C4 /* font_Melon.png */; }; + F5142657101F6CC5006CF3C4 /* skin_classic.png in Copy skins */ = {isa = PBXBuildFile; fileRef = F5142651101F6CB9006CF3C4 /* skin_classic.png */; }; + F5142658101F6CC5006CF3C4 /* skin_modern.png in Copy skins */ = {isa = PBXBuildFile; fileRef = F5142652101F6CB9006CF3C4 /* skin_modern.png */; }; F51CBD2E0EC8A3E1005C06AC /* 5pxtinyfont.png in Copy fonts */ = {isa = PBXBuildFile; fileRef = F51CBD2B0EC8A3E1005C06AC /* 5pxtinyfont.png */; }; F51CBD2F0EC8A3E1005C06AC /* colorfont.pcx in Copy fonts */ = {isa = PBXBuildFile; fileRef = F51CBD2C0EC8A3E1005C06AC /* colorfont.pcx */; }; F51CBD300EC8A3E1005C06AC /* Tuffy.ttf in Copy fonts */ = {isa = PBXBuildFile; fileRef = F51CBD2D0EC8A3E1005C06AC /* Tuffy.ttf */; }; @@ -52,8 +58,6 @@ F5B19BA30EA4BE3E003F4BA4 /* shade.c in Sources */ = {isa = PBXBuildFile; fileRef = F5B19B8B0EA4BE3E003F4BA4 /* shade.c */; }; F5B19BA40EA4BE3E003F4BA4 /* special.c in Sources */ = {isa = PBXBuildFile; fileRef = F5B19B8C0EA4BE3E003F4BA4 /* special.c */; }; F5B19BE10EA4C65A003F4BA4 /* gfx2.cfg in Resources */ = {isa = PBXBuildFile; fileRef = F5B19BDF0EA4C65A003F4BA4 /* gfx2.cfg */; }; - F5B19BE10EA4C65A003F4BA5 /* base.gif in Copy skins */ = {isa = PBXBuildFile; fileRef = F5B19BDF0EA4C65A003F4BA5 /* base.gif */; }; - F5B19BE10EA4C65A003F4BA6 /* ilkke.png in Copy skins */ = {isa = PBXBuildFile; fileRef = F5B19BDF0EA4C65A003F4BA6 /* ilkke.png */; }; F5B19C1D0EA4D71C003F4BA4 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F5B19C1C0EA4D71C003F4BA4 /* CoreFoundation.framework */; }; F5B19C3D0EA4DC91003F4BA4 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = F5B19C3B0EA4DC91003F4BA4 /* InfoPlist.strings */; }; F5B1EE850EAD0F4E00B087B5 /* gfx2def.ini in Resources */ = {isa = PBXBuildFile; fileRef = F5B1EE840EAD0F4E00B087B5 /* gfx2def.ini */; }; @@ -104,6 +108,22 @@ name = "Copy Frameworks into .app bundle"; runOnlyForDeploymentPostprocessing = 0; }; + F514264B101F6C5B006CF3C4 /* Copy skins */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = skins; + dstSubfolderSpec = 7; + files = ( + F5142653101F6CC5006CF3C4 /* font_Classic.png in Copy skins */, + F5142654101F6CC5006CF3C4 /* font_Fairlight.png in Copy skins */, + F5142655101F6CC5006CF3C4 /* font_Fun.png in Copy skins */, + F5142656101F6CC5006CF3C4 /* font_Melon.png in Copy skins */, + F5142657101F6CC5006CF3C4 /* skin_classic.png in Copy skins */, + F5142658101F6CC5006CF3C4 /* skin_modern.png in Copy skins */, + ); + name = "Copy skins"; + runOnlyForDeploymentPostprocessing = 0; + }; F5A33F1D0EC8A26C00F8052D /* Copy fonts */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; @@ -119,18 +139,6 @@ name = "Copy fonts"; runOnlyForDeploymentPostprocessing = 0; }; - F5A33F1D0EC8A26C00F8052E /* Copy skins */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = skins; - dstSubfolderSpec = 7; - files = ( - F5B19BE10EA4C65A003F4BA5 /* base.gif in Copy skins */, - F5B19BE10EA4C65A003F4BA6 /* ilkke.png in Copy skins */, - ); - name = "Copy skins"; - runOnlyForDeploymentPostprocessing = 0; - }; /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ @@ -145,6 +153,12 @@ 32CA4F630368D1EE00C91783 /* Grafx2_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Grafx2_Prefix.pch; sourceTree = ""; }; 8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; 8D1107320486CEB800E47090 /* Grafx2.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Grafx2.app; sourceTree = BUILT_PRODUCTS_DIR; }; + F514264D101F6CB8006CF3C4 /* font_Classic.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = font_Classic.png; path = skins/font_Classic.png; sourceTree = ""; }; + F514264E101F6CB8006CF3C4 /* font_Fairlight.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = font_Fairlight.png; path = skins/font_Fairlight.png; sourceTree = ""; }; + F514264F101F6CB9006CF3C4 /* font_Fun.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = font_Fun.png; path = skins/font_Fun.png; sourceTree = ""; }; + F5142650101F6CB9006CF3C4 /* font_Melon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = font_Melon.png; path = skins/font_Melon.png; sourceTree = ""; }; + F5142651101F6CB9006CF3C4 /* skin_classic.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = skin_classic.png; path = skins/skin_classic.png; sourceTree = ""; }; + F5142652101F6CB9006CF3C4 /* skin_modern.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = skin_modern.png; path = skins/skin_modern.png; sourceTree = ""; }; F51CBD2B0EC8A3E1005C06AC /* 5pxtinyfont.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = 5pxtinyfont.png; path = fonts/5pxtinyfont.png; sourceTree = ""; }; F51CBD2C0EC8A3E1005C06AC /* colorfont.pcx */ = {isa = PBXFileReference; lastKnownFileType = file; name = colorfont.pcx; path = fonts/colorfont.pcx; sourceTree = ""; }; F51CBD2D0EC8A3E1005C06AC /* Tuffy.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = Tuffy.ttf; path = fonts/Tuffy.ttf; sourceTree = ""; }; @@ -186,8 +200,6 @@ F5B19B8B0EA4BE3E003F4BA4 /* shade.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = shade.c; sourceTree = ""; }; F5B19B8C0EA4BE3E003F4BA4 /* special.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = special.c; sourceTree = ""; }; F5B19BDF0EA4C65A003F4BA4 /* gfx2.cfg */ = {isa = PBXFileReference; lastKnownFileType = file; path = gfx2.cfg; sourceTree = ""; }; - F5B19BDF0EA4C65A003F4BA5 /* base.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; name = base.gif; path = skins/base.gif; sourceTree = ""; }; - F5B19BDF0EA4C65A003F4BA6 /* ilkke.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = ilkke.png; path = skins/ilkke.png; sourceTree = ""; }; F5B19C1C0EA4D71C003F4BA4 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = SDKs/MacOSX10.4u.sdk/System/Library/Frameworks/CoreFoundation.framework; sourceTree = SYSTEM_DEVELOPER_DIR; }; F5B19C3C0EA4DC91003F4BA4 /* English */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = ""; }; F5B1EE840EAD0F4E00B087B5 /* gfx2def.ini */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = gfx2def.ini; sourceTree = ""; }; @@ -260,6 +272,12 @@ 29B97314FDCFA39411CA2CEA /* Grafx2 */ = { isa = PBXGroup; children = ( + F514264D101F6CB8006CF3C4 /* font_Classic.png */, + F514264E101F6CB8006CF3C4 /* font_Fairlight.png */, + F514264F101F6CB9006CF3C4 /* font_Fun.png */, + F5142650101F6CB9006CF3C4 /* font_Melon.png */, + F5142651101F6CB9006CF3C4 /* skin_classic.png */, + F5142652101F6CB9006CF3C4 /* skin_modern.png */, F539315D0FE171C3003CB103 /* pversion.c */, F5CDCE310F6EA6D600B31F63 /* pxdouble.c */, F5AC28B90F4873C700455509 /* hotkeys.c */, @@ -294,8 +312,6 @@ F5B19C3B0EA4DC91003F4BA4 /* InfoPlist.strings */, F5B19C1C0EA4D71C003F4BA4 /* CoreFoundation.framework */, F5B19BDF0EA4C65A003F4BA4 /* gfx2.cfg */, - F5B19BDF0EA4C65A003F4BA5 /* base.gif */, - F5B19BDF0EA4C65A003F4BA6 /* ilkke.png */, F5B19B7B0EA4BE3E003F4BA4 /* graph.c */, F5B19B7C0EA4BE3E003F4BA4 /* init.c */, F5B19B7D0EA4BE3E003F4BA4 /* io.c */, @@ -366,7 +382,7 @@ 002F39FD09D0883400EBEB89 /* Copy Frameworks into .app bundle */, 002F39FD09D0883400EBEB8A /* Copy Frameworks into .app bundle */, F5A33F1D0EC8A26C00F8052D /* Copy fonts */, - F5A33F1D0EC8A26C00F8052E /* Copy skins */, + F514264B101F6C5B006CF3C4 /* Copy skins */, ); buildRules = ( ); diff --git a/Grafx2.xcodeproj/xx.pbxuser b/Grafx2.xcodeproj/xx.pbxuser index 28c221dc..a3b5507f 100644 --- a/Grafx2.xcodeproj/xx.pbxuser +++ b/Grafx2.xcodeproj/xx.pbxuser @@ -18,9 +18,9 @@ }; 002F3A3E09D088BA00EBEB88 /* main.c */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1060, 11476}}"; - sepNavSelRange = "{0, 0}"; - sepNavVisRect = "{{0, 0}, {867, 536}}"; + sepNavIntBoundsRect = "{{0, 0}, {1044, 15086}}"; + sepNavSelRange = "{19535, 0}"; + sepNavVisRect = "{{0, 10961}, {867, 536}}"; sepNavWindowFrame = "{{14, 76}, {906, 665}}"; }; }; @@ -29,7 +29,6 @@ activeExecutable = F5B19B5D0EA4BD57003F4BA4 /* Grafx2 */; activeTarget = 8D1107260486CEB800E47090 /* Grafx2 */; addToTargets = ( - 8D1107260486CEB800E47090 /* Grafx2 */, ); breakpointsGroup = F5B19B700EA4BDA9003F4BA4 /* XCBreakpointsBucket */; codeSenseManager = F5B19B6A0EA4BD79003F4BA4 /* Code sense */; @@ -70,14 +69,15 @@ PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Built_ColumnID; PBXFileTableDataSourceColumnWidthsKey = ( 20, - 229, + 99, 20, 48, 43, 43, 20, - 79, - 88, + 264, + 10, + 20, ); PBXFileTableDataSourceColumnsKey = ( PBXFileDataSource_FiletypeID, @@ -89,6 +89,7 @@ PBXFileDataSource_Target_ColumnID, PBXFileDataSource_Path_ColumnID, PBXFileDataSource_Comments_ColumnID, + PBXFileDataSource_SCM_ColumnID, ); }; PBXConfiguration.PBXFileTableDataSource3.PBXFindDataSource = { @@ -165,8 +166,8 @@ PBXFileDataSource_Warnings_ColumnID, ); }; - PBXPerProjectTemplateStateSaveDate = 266433807; - PBXWorkspaceStateSaveDate = 266433807; + PBXPerProjectTemplateStateSaveDate = 270495112; + PBXWorkspaceStateSaveDate = 270495112; }; sourceControlManager = F5B19B690EA4BD79003F4BA4 /* Source Control */; userBuildSettings = { @@ -187,6 +188,11 @@ F5B19B5D0EA4BD57003F4BA4 /* Grafx2 */, ); }; + F51CBD2B0EC8A3E1005C06AC /* 5pxtinyfont.png */ = { + uiCtxt = { + sepNavWindowFrame = "{{15, 25}, {971, 716}}"; + }; + }; F5A33E690EC893F800F8052D /* 8pxfont.png */ = { uiCtxt = { sepNavWindowFrame = "{{15, 76}, {906, 665}}"; @@ -256,10 +262,10 @@ }; F5B19B7B0EA4BE3E003F4BA4 /* graph.c */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1620, 118579}}"; - sepNavSelRange = "{16112, 36}"; - sepNavVisRect = "{{0, 9964}, {867, 536}}"; - sepNavWindowFrame = "{{15, 76}, {906, 665}}"; + sepNavIntBoundsRect = "{{0, 0}, {1140, 52782}}"; + sepNavSelRange = "{6769, 0}"; + sepNavVisRect = "{{0, 0}, {867, 536}}"; + sepNavWindowFrame = "{{14, 76}, {906, 665}}"; }; }; F5B19B7C0EA4BE3E003F4BA4 /* init.c */ = { @@ -296,10 +302,10 @@ }; F5B19B890EA4BE3E003F4BA4 /* sdlscreen.c */ = { uiCtxt = { - sepNavIntBoundsRect = "{{0, 0}, {1580, 11571}}"; - sepNavSelRange = "{0, 0}"; - sepNavVisRect = "{{0, 0}, {867, 536}}"; - sepNavWindowFrame = "{{61, 34}, {906, 665}}"; + sepNavIntBoundsRect = "{{0, 0}, {1396, 4351}}"; + sepNavSelRange = "{2375, 0}"; + sepNavVisRect = "{{0, 1072}, {867, 536}}"; + sepNavWindowFrame = "{{35, 15}, {906, 665}}"; }; }; F5B19C3C0EA4DC91003F4BA4 /* English */ = { diff --git a/Grafx2.xcodeproj/xx.perspective b/Grafx2.xcodeproj/xx.perspective index 30368fc1..f9c5d992 100644 --- a/Grafx2.xcodeproj/xx.perspective +++ b/Grafx2.xcodeproj/xx.perspective @@ -188,9 +188,9 @@ PerspectiveWidths - 970 - 970 - 970 + 971 + 971 + 971 Perspectives @@ -247,7 +247,7 @@ PBXSmartGroupTreeModuleColumnWidthsKey - 305 + 345 PBXSmartGroupTreeModuleColumnsKey_v4 @@ -259,7 +259,10 @@ PBXSmartGroupTreeModuleOutlineStateExpansionKey 29B97314FDCFA39411CA2CEA + 29B97317FDCFA39411CA2CEA 1C37FBAC04509CD000000102 + F56B73F7101F6D9500B6D9A4 + F56B7443101FA1C600B6D9A4 PBXSmartGroupTreeModuleOutlineStateSelectionKey @@ -268,7 +271,7 @@ PBXSmartGroupTreeModuleOutlineStateVisibleRectKey - {{0, 124}, {305, 575}} + {{0, 0}, {345, 600}} PBXTopSmartGroupGIDs @@ -278,17 +281,17 @@ GeometryConfiguration Frame - {{0, 0}, {322, 593}} + {{0, 0}, {362, 618}} GroupTreeTableConfiguration MainColumn - 305 + 345 Module PBXSmartGroupTreeModule Proportion - 322pt + 362pt Dock @@ -299,7 +302,7 @@ PBXProjectModuleGUID F5A33EBD0EC89C3000F8052D PBXProjectModuleLabel - asm pthread_mutex_lock 0x90001a38 + PBXSplitModuleInNavigatorKey Split0 @@ -307,7 +310,7 @@ PBXProjectModuleGUID F5A33EBE0EC89C3000F8052D PBXProjectModuleLabel - asm pthread_mutex_lock 0x90001a38 + SplitCount 1 @@ -320,7 +323,7 @@ GeometryConfiguration Frame - {{0, 0}, {643, 0}} + {{0, 0}, {604, 0}} Module PBXNavigatorGroup @@ -329,7 +332,7 @@ Proportion - 588pt + 613pt Tabs @@ -343,7 +346,7 @@ GeometryConfiguration Frame - {{10, 27}, {643, 561}} + {{10, 27}, {604, 586}} Module XCDetailModule @@ -359,7 +362,7 @@ GeometryConfiguration Frame - {{10, 27}, {650, 590}} + {{10, 27}, {644, 586}} Module PBXProjectFindModule @@ -375,7 +378,7 @@ GeometryConfiguration Frame - {{10, 31}, {603, 297}} + {{10, 27}, {644, 586}} Module PBXCVSModule @@ -384,7 +387,7 @@ Proportion - 643pt + 604pt Name @@ -402,11 +405,11 @@ TableOfContents - F5D646000F487ECB007E515F + F56B7444101FA1C600B6D9A4 1CA23ED40692098700951B8B - F5D646010F487ECB007E515F + F56B7445101FA1C600B6D9A4 F5A33EBD0EC89C3000F8052D - F5D646020F487ECB007E515F + F56B7446101FA1C600B6D9A4 1CA23EDF0692099D00951B8B 1CA23EE00692099D00951B8B 1CA23EE10692099D00951B8B @@ -468,18 +471,24 @@ PBXSmartGroupTreeModuleOutlineStateExpansionKey 29B97314FDCFA39411CA2CEA + F5B19C3B0EA4DC91003F4BA4 080E96DDFE201D6D7F000001 29B97315FDCFA39411CA2CEA 29B97317FDCFA39411CA2CEA + 29B97323FDCFA39411CA2CEA + 1058C7A0FEA54F0111CA2CBB + 1058C7A2FEA54F0111CA2CBB + 19C28FACFE9D520D11CA2CBB PBXSmartGroupTreeModuleOutlineStateSelectionKey + 42 0 PBXSmartGroupTreeModuleOutlineStateVisibleRectKey - {{0, 0}, {275, 583}} + {{0, 475}, {275, 600}} PBXTopSmartGroupGIDs @@ -489,14 +498,14 @@ GeometryConfiguration Frame - {{0, 0}, {292, 601}} + {{0, 0}, {292, 618}} GroupTreeTableConfiguration MainColumn 275 RubberWindowFrame - 65 75 944 642 0 0 1024 746 + 151 75 971 659 0 0 1024 746 Module PBXSmartGroupTreeModule @@ -533,9 +542,9 @@ GeometryConfiguration Frame - {{0, 0}, {647, 0}} + {{0, 0}, {674, 0}} RubberWindowFrame - 65 75 944 642 0 0 1024 746 + 151 75 971 659 0 0 1024 746 Module PBXNavigatorGroup @@ -544,14 +553,14 @@ Proportion - 596pt + 613pt Tabs ContentConfiguration PBXBuildLogShowsTranscriptDefaultKey - {{0, 5}, {647, 564}} + {{0, 5}, {674, 581}} PBXProjectModuleGUID XCMainBuildResultsModuleGUID PBXProjectModuleLabel @@ -564,9 +573,9 @@ GeometryConfiguration Frame - {{10, 27}, {647, 569}} + {{10, 27}, {674, 586}} RubberWindowFrame - 65 75 944 642 0 0 1024 746 + 151 75 971 659 0 0 1024 746 Module PBXBuildResultsModule @@ -628,7 +637,7 @@ Proportion - 647pt + 674pt Name @@ -646,14 +655,14 @@ TableOfContents - F53931560FE170BC003CB103 + F56B7447101FA1C600B6D9A4 1CA23EE50692099D00951B8B - F53931570FE170BC003CB103 + F56B7448101FA1C600B6D9A4 F5A33EC20EC89C3000F8052D - F53931580FE170BC003CB103 + F56B7449101FA1C600B6D9A4 XCMainBuildResultsModuleGUID 1CA23EE80692099D00951B8B - F53931590FE170BC003CB103 + F56B744A101FA1C600B6D9A4 ToolbarConfiguration xcode.toolbar.config.buildAndRun @@ -697,7 +706,7 @@ GeometryConfiguration Frame - {{0, 0}, {1323, 0}} + {{0, 0}, {971, 0}} Module PBXDebugCLIModule @@ -721,8 +730,8 @@ yes sizes - {{0, 0}, {641, 197}} - {{641, 0}, {682, 197}} + {{0, 0}, {470, 295}} + {{470, 0}, {501, 295}} VerticalSplitView @@ -737,8 +746,8 @@ yes sizes - {{0, 0}, {1323, 197}} - {{0, 197}, {1323, 211}} + {{0, 0}, {971, 295}} + {{0, 295}, {971, 318}} @@ -760,12 +769,12 @@ DebugSTDIOWindowFrame {{200, 200}, {500, 300}} Frame - {{0, 5}, {1323, 408}} + {{0, 5}, {971, 613}} Module PBXDebugSessionModule Proportion - 408pt + 613pt Name @@ -784,15 +793,15 @@ TableOfContents - F5AED0700F1999130090A93F + F56B744B101FA1C600B6D9A4 1CCC7628064C1048000F2A68 1CCC7629064C1048000F2A68 - F5AED0710F1999130090A93F - F5AED0720F1999130090A93F - F5AED0730F1999130090A93F - F5AED0740F1999130090A93F - F5AED0410F1989EC0090A93F - F5AED0750F1999130090A93F + F56B744C101FA1C600B6D9A4 + F56B744D101FA1C600B6D9A4 + F56B744E101FA1C600B6D9A4 + F56B744F101FA1C600B6D9A4 + F56B7409101F6DEB00B6D9A4 + F56B7450101FA1C600B6D9A4 ToolbarConfiguration xcode.toolbar.config.debug @@ -801,7 +810,7 @@ PerspectivesBarVisible PinnedNavigatorIdentifier - F539315B0FE170D5003CB103 + F56B743E101F7E4F00B6D9A4 ShelfIsVisible SourceDescription @@ -824,10 +833,11 @@ 5 WindowOrderList + F56B7450101FA1C600B6D9A4 /Users/xx/Grafx2/Grafx2.xcodeproj WindowString - 65 75 944 642 0 0 1024 746 + 151 75 971 659 0 0 1024 746 WindowTools diff --git a/Info.plist b/Info.plist index e2b73ab1..b5d2a5aa 100644 --- a/Info.plist +++ b/Info.plist @@ -1,19 +1,19 @@ - + CFBundleDevelopmentRegion English CFBundleExecutable - ${EXECUTABLE_NAME} + Grafx2 CFBundleIconFile CFBundleIdentifier - http://grafx2.googlecode.com/ + com.googlecode.grafx2 CFBundleInfoDictionaryVersion 6.0 CFBundleName - ${PRODUCT_NAME} + Grafx2 CFBundlePackageType APPL CFBundleSignature diff --git a/Makefile b/Makefile index 93e734a2..21af96b7 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,6 @@ # Grafx2 - The Ultimate 256-color bitmap paint program # +# Copyright 2009 Per Olofsson # Copyright 2008 Peter Gordon # Copyright 2008 Yves Rizoud # Copyright 2007 Adrien Destugues @@ -31,6 +32,8 @@ ### PLATFORM DETECTION AND CONFIGURATION ### +PLATFORMOBJ = + # There is no uname under windows, but we can guess we are there with the COMSPEC env.var # Windows specific ifdef COMSPEC @@ -45,8 +48,7 @@ ifdef COMSPEC OBJDIR = obj/win32 # Resources (icon) WINDRES = windres.exe - OBJRES = $(OBJDIR)/winres.o - CFGOBJRES = $(OBJDIR)/wincfgres.o + PLATFORMOBJ = $(OBJDIR)/winres.o PLATFORM = win32 PLATFORMFILES = SDL.dll SDL_image.dll libpng13.dll zlib1.dll gfx2.ico $(TTFLIBS) #some misc files we have to add to the release archive under windows. ZIP = zip @@ -62,13 +64,36 @@ else RMDIR = rmdir CP = cp BIN = grafx2 - COPT = -Wall -c -gstabs -mcrt=newlib `sdl-config --cflags` -D__USE_INLINE__ $(TTFCOPT) + COPT = -Wall -c -gstabs -mcrt=newlib `sdl-config --cflags` -I/SDK/Local/common/include/SDL -D__USE_INLINE__ $(TTFCOPT) LOPT = `sdl-config --libs` -lSDL_image -lpng -ljpeg -lz $(TTFLOPT) -lft2 CC = gcc OBJDIR = obj/amiga ZIP = lha ZIPOPT = a + else ifeq ($(PLATFORM),Darwin) + #Mac OS X specific + DELCOMMAND = rm -rf + MKDIR = mkdir -p + RMDIR = rmdir + CP = cp + ZIP = zip + PLATFORMFILES = gfx2.png + BIN = grafx2 + # Where the SDL frameworks are located + FWDIR = /Library/Frameworks + SDLCOPT = -arch i386 -I$(FWDIR)/SDL.framework/Headers -I$(FWDIR)/SDL_image.framework/Headers -I$(FWDIR)/SDL_ttf.framework/Headers -D_THREAD_SAFE + SDLLOPT = -arch i386 -L/usr/lib -framework SDL -framework SDL_image -framework SDL_ttf -framework Cocoa -framework Carbon -framework OpenGL + COPT = -D__macosx__ -D__linux__ -W -Wall -Wdeclaration-after-statement -O$(OPTIM) -std=c99 -c -g $(SDLCOPT) $(TTFCOPT) -I/usr/X11/include + LOPT = $(SDLLOPT) -L/usr/X11/lib -R/usr/X11/lib -lpng + # Use gcc for compiling. Use ncc to build a callgraph and analyze the code. + CC = gcc + #CC = nccgen -ncgcc -ncld -ncfabs + OBJDIR = obj/macosx + PLATFORMOBJ = $(OBJDIR)/SDLMain.o + X11LOPT = + MACAPPEXE = Grafx2.app/Contents/MacOS/Grafx2 + else ifeq ($(PLATFORM),AROS) #AROS specific DELCOMMAND = rm -rf @@ -185,7 +210,7 @@ else # Compiles a regular linux exectutable for the native platform BIN = grafx2 - COPT = -W -Wall -Wdeclaration-after-statement -pedantic -std=c99 -c -g `sdl-config --cflags` $(TTFCOPT) + COPT = -W -Wall -Wdeclaration-after-statement -std=c99 -c -g `sdl-config --cflags` $(TTFCOPT) LOPT = `sdl-config --libs` -lSDL_image $(TTFLOPT) -lpng # Use gcc for compiling. Use ncc to build a callgraph and analyze the code. CC = gcc @@ -225,9 +250,30 @@ endif .PHONY : all debug release clean depend zip version force install uninstall # This is the list of the objects we want to build. Dependancies are built by "make depend" automatically. -OBJ = $(OBJDIR)/main.o $(OBJDIR)/init.o $(OBJDIR)/graph.o $(OBJDIR)/sdlscreen.o $(OBJDIR)/misc.o $(OBJDIR)/special.o $(OBJDIR)/buttons.o $(OBJDIR)/palette.o $(OBJDIR)/help.o $(OBJDIR)/operatio.o $(OBJDIR)/pages.o $(OBJDIR)/loadsave.o $(OBJDIR)/readline.o $(OBJDIR)/engine.o $(OBJDIR)/filesel.o $(OBJDIR)/op_c.o $(OBJDIR)/readini.o $(OBJDIR)/saveini.o $(OBJDIR)/shade.o $(OBJDIR)/keyboard.o $(OBJDIR)/io.o $(OBJDIR)/version.o $(OBJDIR)/text.o $(OBJDIR)/SFont.o $(OBJDIR)/setup.o $(OBJDIR)/pxsimple.o $(OBJDIR)/pxtall.o $(OBJDIR)/pxwide.o $(OBJDIR)/pxdouble.o $(OBJDIR)/pxtriple.o $(OBJDIR)/pxtall2.o $(OBJDIR)/pxwide2.o $(OBJDIR)/pxquad.o $(OBJDIR)/windows.o $(OBJDIR)/brush.o $(OBJDIR)/realpath.o $(OBJDIR)/mountlist.o $(OBJDIR)/input.o $(OBJDIR)/hotkeys.o $(OBJDIR)/transform.o $(OBJDIR)/pversion.o +OBJ = $(OBJDIR)/main.o $(OBJDIR)/init.o $(OBJDIR)/graph.o $(OBJDIR)/sdlscreen.o $(OBJDIR)/misc.o $(OBJDIR)/special.o $(OBJDIR)/buttons.o $(OBJDIR)/palette.o $(OBJDIR)/help.o $(OBJDIR)/operatio.o $(OBJDIR)/pages.o $(OBJDIR)/loadsave.o $(OBJDIR)/readline.o $(OBJDIR)/engine.o $(OBJDIR)/filesel.o $(OBJDIR)/op_c.o $(OBJDIR)/readini.o $(OBJDIR)/saveini.o $(OBJDIR)/shade.o $(OBJDIR)/keyboard.o $(OBJDIR)/io.o $(OBJDIR)/version.o $(OBJDIR)/text.o $(OBJDIR)/SFont.o $(OBJDIR)/setup.o $(OBJDIR)/pxsimple.o $(OBJDIR)/pxtall.o $(OBJDIR)/pxwide.o $(OBJDIR)/pxdouble.o $(OBJDIR)/pxtriple.o $(OBJDIR)/pxtall2.o $(OBJDIR)/pxwide2.o $(OBJDIR)/pxquad.o $(OBJDIR)/windows.o $(OBJDIR)/brush.o $(OBJDIR)/realpath.o $(OBJDIR)/mountlist.o $(OBJDIR)/input.o $(OBJDIR)/hotkeys.o $(OBJDIR)/transform.o $(OBJDIR)/pversion.o $(PLATFORMOBJ) +SKIN_FILES = skins/skin_classic.png skins/skin_modern.png skins/font_Classic.png skins/font_Fun.png + +ifeq ($(PLATFORM),Darwin) +all : $(MACAPPEXE) +$(MACAPPEXE) : $(BIN) + rm -rf Grafx2.app + mkdir -p Grafx2.app Grafx2.app/Contents Grafx2.app/Contents/Frameworks Grafx2.app/Contents/MacOS Grafx2.app/Contents/Resources + echo 'APPL????' > Grafx2.app/Contents/PkgInfo + cp Info.plist Grafx2.app/Contents + cp -r English.lproj Grafx2.app/Contents/Resources + cp -r fonts Grafx2.app/Contents/Resources + cp -r skins Grafx2.app/Contents/Resources + cp -r gfx2.cfg Grafx2.app/Contents/Resources + cp -r gfx2def.ini Grafx2.app/Contents/Resources + cp -Rp $(FWDIR)/SDL.framework Grafx2.app/Contents/Frameworks + cp -Rp $(FWDIR)/SDL_image.framework Grafx2.app/Contents/Frameworks + cp -Rp $(FWDIR)/SDL_ttf.framework Grafx2.app/Contents/Frameworks + cp $(BIN) $(MACAPPEXE) +else all : $(BIN) +endif + debug : $(BIN) @@ -237,17 +283,22 @@ release : version $(BIN) # Create a zip archive ready for upload to the website, including binaries and sourcecode ziprelease: version $(BIN) release - tar cvzf src-svn`svnversion | sed 's/:/-/'`.tgz --transform 's,^,src/,g' *.c *.h Makefile Makefile.dep gfx2.ico - $(ZIP) $(ZIPOPT) grafx2-svn`svnversion | sed 's/:/-/'`$(TTFLABEL)-$(PLATFORM).$(ZIP) $(BIN) gfx2def.ini skins/base.gif gfx2.gif doc/README.txt doc/COMPILING.txt doc/gpl-2.0.txt fonts/8pxfont.png doc/README-zlib1.txt doc/README-SDL.txt doc/README-SDL_image.txt doc/README-SDL_ttf.txt fonts/Tuffy.ttf src-svn`svnversion | sed 's/:/-/'`.tgz $(PLATFORMFILES) - $(DELCOMMAND) src-svn`svnversion | sed 's/:/-/'`.tgz - tar cvzf grafx2-svn`svnversion | sed 's/:/-/'`$(TTFLABEL)-src.tgz --transform 's,^,grafx2/,g' *.c *.h Makefile Makefile.dep gfx2def.ini skins/base.gif gfx2.ico gfx2.gif doc/README.txt doc/COMPILING.txt doc/gpl-2.0.txt misc/grafx2.1 misc/grafx2.xpm misc/grafx2.desktop fonts/8pxfont.png fonts/Tuffy.ttf + echo `sed "s/.*=\"\(.*\)\";/\1/" pversion.c`.`svnversion` | tr " :" "_-" | sed -e s/\\(wip\\)\\\\./\\1/I > $(OBJDIR)/versiontag -$(BIN) : $(OBJ) $(OBJRES) - $(CC) $(OBJ) $(OBJRES) -o $(BIN) $(LOPT) + tar cvzf "src-`cat $(OBJDIR)/versiontag`.tgz" --transform 's,^,src/,g' *.c *.h Makefile Makefile.dep gfx2.ico + $(ZIP) $(ZIPOPT) "grafx2-`cat $(OBJDIR)/versiontag`$(TTFLABEL)-$(PLATFORM).$(ZIP)" $(BIN) gfx2def.ini $(SKIN_FILES) gfx2.gif doc/README.txt doc/COMPILING.txt doc/gpl-2.0.txt fonts/8pxfont.png doc/README-zlib1.txt doc/README-SDL.txt doc/README-SDL_image.txt doc/README-SDL_ttf.txt fonts/Tuffy.ttf src-`cat $(OBJDIR)/versiontag`.tgz $(PLATFORMFILES) + $(DELCOMMAND) "src-`cat $(OBJDIR)/versiontag`.tgz" + tar cvzf "grafx2-`cat $(OBJDIR)/versiontag`$(TTFLABEL)-src.tgz" --transform 's,^,grafx2/,g' *.c *.h Makefile Makefile.dep gfx2def.ini $(SKIN_FILES) gfx2.ico gfx2.gif doc/README.txt doc/COMPILING.txt doc/gpl-2.0.txt misc/grafx2.1 misc/grafx2.xpm misc/grafx2.desktop fonts/8pxfont.png fonts/Tuffy.ttf + $(DELCOMMAND) "$(OBJDIR)/versiontag" + +testsed : + +$(BIN) : $(OBJ) + $(CC) $(OBJ) -o $(BIN) $(LOPT) # SVN revision number version.c : - echo "char SVN_revision[]=\"`svnversion`\";" > version.c + echo "char SVN_revision[]=\"`svnversion .`\";" > version.c ifeq ($(LABEL),) else echo "char Program_version[]=\"$(LABEL)\";" > pversion.c @@ -265,10 +316,14 @@ else $(DELCOMMAND) pversion.c endif -$(OBJDIR)/%.o : +$(OBJDIR)/%.o : %.c $(if $(wildcard $(OBJDIR)),,$(MKDIR) $(OBJDIR)) $(CC) $(COPT) -c $*.c -o $(OBJDIR)/$*.o +$(OBJDIR)/%.o : %.m + $(if $(wildcard $(OBJDIR)),,$(MKDIR) $(OBJDIR)) + $(CC) $(COPT) -c $*.m -o $(OBJDIR)/$*.o + depend : $(CC) -MM *.c | sed 's:^[^ ]:$$(OBJDIR)/&:' > Makefile.dep @@ -277,7 +332,7 @@ $(OBJDIR)/winres.o : gfx2.ico echo "1 ICON \"gfx2.ico\"" | $(WINDRES) -o $(OBJDIR)/winres.o clean : - $(DELCOMMAND) $(OBJ) $(OBJDIR)/version.o $(OBJRES) + $(DELCOMMAND) $(OBJ) $(DELCOMMAND) $(BIN) # Linux installation of the program @@ -298,7 +353,7 @@ install : $(BIN) $(CP) gfx2def.ini $(DESTDIR)$(datadir)/grafx2/ $(CP) gfx2.gif $(DESTDIR)$(datadir)/grafx2/ $(CP) fonts/* $(DESTDIR)$(datadir)/grafx2/fonts/ - $(CP) skins/base.gif $(DESTDIR)$(datadir)/grafx2/skins/ + $(CP) $(SKIN_FILES) $(DESTDIR)$(datadir)/grafx2/skins/ # Icon and desktop file for debian $(CP) misc/grafx2.desktop $(DESTDIR)$(datadir)/applications/ $(CP) misc/grafx2.xpm $(DESTDIR)$(datadir)/icons/ @@ -312,7 +367,9 @@ uninstall : $(DELCOMMAND) $(DESTDIR)$(datadir)/grafx2/gfx2.gif $(DELCOMMAND) $(DESTDIR)$(datadir)/grafx2/fonts/* $(if $(wildcard $(DESTDIR)$(datadir)/grafx2/fonts),,$(RMDIR) $(DESTDIR)$(datadir)/grafx2/fonts) - $(DELCOMMAND) $(DESTDIR)$(datadir)/grafx2/skins/base.gif + cd $(DESTDIR)$(datadir)/grafx2 + $(DELCOMMAND) $(SKIN_FILES) + cd .. $(if $(wildcard $(DESTDIR)$(datadir)/grafx2/skins),,$(RMDIR) $(DESTDIR)$(datadir)/grafx2/skins) # Icon and desktop file for debian $(DELCOMMAND) $(DESTDIR)$(datadir)/applications/grafx2.desktop diff --git a/brush.c b/brush.c index a9d7ce16..c6fe95ca 100644 --- a/brush.c +++ b/brush.c @@ -123,7 +123,8 @@ void Display_paintbrush(short x,short y,byte color,byte is_preview) int position; byte * temp; - if (!(is_preview && Mouse_K)) // Si bouton enfoncé & preview > pas de dessin + if (is_preview==0 || Mouse_K==0) // pas de curseur si on est en preview et + // en train de cliquer switch (Paintbrush_shape) { case PAINTBRUSH_SHAPE_POINT : // !!! TOUJOURS EN PREVIEW !!! @@ -151,7 +152,7 @@ void Display_paintbrush(short x,short y,byte color,byte is_preview) end_counter_x=start_x_counter+width; end_counter_y=start_y_counter+height; - if (is_preview) + if (is_preview != 0) { if ( (width>0) && (height>0) ) Display_brush_color( @@ -165,7 +166,7 @@ void Display_paintbrush(short x,short y,byte color,byte is_preview) Brush_width ); - if (Main_magnifier_mode) + if (Main_magnifier_mode != 0) { Compute_clipped_dimensions_zoom(&start_x,&start_y,&width, &height @@ -196,9 +197,9 @@ void Display_paintbrush(short x,short y,byte color,byte is_preview) } else { - if ((Smear_mode) && (Shade_table==Shade_table_left)) + if ((Smear_mode != 0) && (Shade_table==Shade_table_left)) { - if (Smear_start) + if (Smear_start != 0) { if ((width>0) && (height>0)) { @@ -275,7 +276,7 @@ void Display_paintbrush(short x,short y,byte color,byte is_preview) start_y_counter=start_y-(y-Brush_offset_Y); end_counter_x=start_x_counter+width; end_counter_y=start_y_counter+height; - if (is_preview) + if (is_preview != 0) { if ( (width>0) && (height>0) ) Display_brush_mono(start_x-Main_offset_X, @@ -285,7 +286,7 @@ void Display_paintbrush(short x,short y,byte color,byte is_preview) Back_color,Fore_color, Brush_width); - if (Main_magnifier_mode) + if (Main_magnifier_mode != 0) { Compute_clipped_dimensions_zoom(&start_x,&start_y,&width,&height); start_x_counter=start_x-(x-Brush_offset_X); @@ -314,9 +315,9 @@ void Display_paintbrush(short x,short y,byte color,byte is_preview) } else { - if ((Smear_mode) && (Shade_table==Shade_table_left)) + if ((Smear_mode != 0) && (Shade_table==Shade_table_left)) { - if (Smear_start) + if (Smear_start != 0) { if ((width>0) && (height>0)) { @@ -377,7 +378,7 @@ void Display_paintbrush(short x,short y,byte color,byte is_preview) start_y_counter=start_y-(y-Paintbrush_offset_Y); end_counter_x=start_x_counter+width; end_counter_y=start_y_counter+height; - if (is_preview) + if (is_preview != 0) { temp=Brush; Brush=Paintbrush_sprite; @@ -390,7 +391,7 @@ void Display_paintbrush(short x,short y,byte color,byte is_preview) 0,Fore_color, MAX_PAINTBRUSH_SIZE); - if (Main_magnifier_mode) + if (Main_magnifier_mode != 0) { Compute_clipped_dimensions_zoom(&start_x,&start_y,&width,&height); start_x_counter=start_x-(x-Paintbrush_offset_X); @@ -419,9 +420,9 @@ void Display_paintbrush(short x,short y,byte color,byte is_preview) } else { - if ((Smear_mode) && (Shade_table==Shade_table_left)) + if ((Smear_mode != 0) && (Shade_table==Shade_table_left)) { - if (Smear_start) + if (Smear_start != 0) { if ((width>0) && (height>0)) { @@ -444,10 +445,13 @@ void Display_paintbrush(short x,short y,byte color,byte is_preview) { temp_color=Read_pixel_from_current_screen(x_pos,y_pos); position=(counter_y*Smear_brush_width)+counter_x; - if ( (Paintbrush_sprite[(MAX_PAINTBRUSH_SIZE*counter_y)+counter_x]) // Le pinceau sert de masque pour dire quels pixels on doit traiter dans le rectangle - && (counter_y=Smear_min_Y) && (counter_x>=Smear_min_X) ) - Display_pixel(x_pos,y_pos,Smear_brush[position]); + if ( (Paintbrush_sprite[(MAX_PAINTBRUSH_SIZE*counter_y)+counter_x] != 0) + // Le pinceau sert de masque pour dire quels pixels on doit traiter dans le rectangle + && (counter_y=Smear_min_Y) && (counter_x>=Smear_min_X) + // On clippe l'effet smear entre Smear_Min et Smear_Max + ) + Display_pixel(x_pos,y_pos,Smear_brush[position]); Smear_brush[position]=temp_color; } Update_part_of_screen(start_x, start_y, width, height); @@ -464,7 +468,7 @@ void Display_paintbrush(short x,short y,byte color,byte is_preview) for (y_pos=start_y,counter_y=start_y_counter;counter_yMAX_PAINTBRUSH_SIZE)?Brush_width:MAX_PAINTBRUSH_SIZE; + Smear_brush_height=(Brush_height>MAX_PAINTBRUSH_SIZE)?Brush_height:MAX_PAINTBRUSH_SIZE; + Smear_brush=(byte *)malloc(((long)Smear_brush_height)*Smear_brush_width); + + if (Smear_brush == NULL) // Failed to allocate the smear brush + { + Error(0); + return_code=1; + + free(Brush); + Brush=(byte *)malloc(1*1); + if(Brush == NULL) + { + Error(ERROR_MEMORY); + exit(ERROR_MEMORY); + } + Brush_height=1; + Brush_width=1; + + Smear_brush=(byte *)malloc(MAX_PAINTBRUSH_SIZE*MAX_PAINTBRUSH_SIZE); + if(Smear_brush == NULL) + { + Error(ERROR_MEMORY); + exit(ERROR_MEMORY); + } + Smear_brush_height=MAX_PAINTBRUSH_SIZE; + Smear_brush_width=MAX_PAINTBRUSH_SIZE; + } + return return_code; +} + + // -- Effacer le pinceau -- // // void Hide_paintbrush(short x,short y) @@ -495,11 +562,11 @@ void Hide_paintbrush(short x,short y) //short counter_x; // Position X (dans la brosse/pinceau) en cours //d'affichage //short counter_y; // Position Y (dans la brosse/pinceau) en cours d'affichage - short end_counter_x; // Position X ou s'arrête l'affichade de la brosse/pinceau - short end_counter_y; // Position Y ou s'arrête l'affichade de la brosse/pinceau + short end_counter_x; // Position X ou s'arrête l'affichage de la brosse/pinceau + short end_counter_y; // Position Y ou s'arrête l'affichage de la brosse/pinceau byte * temp; - if (!Mouse_K) + if (Mouse_K == 0) switch (Paintbrush_shape) { case PAINTBRUSH_SHAPE_POINT : @@ -531,7 +598,7 @@ void Hide_paintbrush(short x,short y) width,height,Back_color, Main_image_width); - if (Main_magnifier_mode) + if (Main_magnifier_mode != 0) { Compute_clipped_dimensions_zoom(&start_x,&start_y,&width,&height); start_x_counter=start_x; @@ -577,7 +644,7 @@ void Hide_paintbrush(short x,short y) Main_image_width); } - if (Main_magnifier_mode) + if (Main_magnifier_mode != 0) { Compute_clipped_dimensions_zoom(&start_x,&start_y,&width,&height); start_x_counter=start_x; @@ -651,46 +718,12 @@ void Capture_brush(short start_x,short start_y,short end_x,short end_y,short cle if (start_y+new_brush_height>Main_image_height) new_brush_height=Main_image_height-start_y; - if ( (((long)Brush_height)*Brush_width) != - (((long)new_brush_height)*new_brush_width) ) - { - free(Brush); - Brush=(byte *)malloc(((long)new_brush_height)*new_brush_width); - if (!Brush) - { - Error(0); - - Brush=(byte *)malloc(1*1); - new_brush_height=new_brush_width=1; - *Brush=Fore_color; - } - } - Brush_width=new_brush_width; - Brush_height=new_brush_height; - - free(Smear_brush); - Smear_brush_width=(Brush_width>MAX_PAINTBRUSH_SIZE)?Brush_width:MAX_PAINTBRUSH_SIZE; - Smear_brush_height=(Brush_height>MAX_PAINTBRUSH_SIZE)?Brush_height:MAX_PAINTBRUSH_SIZE; - Smear_brush=(byte *)malloc(((long)Smear_brush_height)*Smear_brush_width); - - if (!Smear_brush) // On ne peut même pas allouer la brosse du smear! - { - Error(0); - - free(Brush); - Brush=(byte *)malloc(1*1); - Brush_height=1; - Brush_width=1; - - Smear_brush=(byte *)malloc(MAX_PAINTBRUSH_SIZE*MAX_PAINTBRUSH_SIZE); - Smear_brush_height=MAX_PAINTBRUSH_SIZE; - Smear_brush_width=MAX_PAINTBRUSH_SIZE; - } + Realloc_brush(new_brush_width, new_brush_height); Copy_image_to_brush(start_x,start_y,Brush_width,Brush_height,Main_image_width); // On regarde s'il faut effacer quelque chose: - if (clear) + if (clear != 0) { for (y_pos=start_y;y_pos0) Pixel_in_brush(x_pos-1,y_pos,Back_color); @@ -955,7 +978,7 @@ void Nibble_brush(void) } else { - if (!state) + if (state == 0) { Pixel_in_brush(x_pos,y_pos,Back_color); state=1; @@ -984,7 +1007,7 @@ void Nibble_brush(void) } else { - if (!state) + if (state == 0) { Pixel_in_brush(x_pos,y_pos,Back_color); state=1; @@ -1021,7 +1044,7 @@ void Capture_brush_with_lasso(int vertices, short * points,short clear) short start_y=Limit_bottom+1; short end_x=Limit_left-1; short end_y=Limit_top-1; - short temp; + unsigned short temp; short x_pos; short y_pos; word new_brush_width; @@ -1029,10 +1052,10 @@ void Capture_brush_with_lasso(int vertices, short * points,short clear) // On recherche les bornes de la brosse: - for (temp=0; tempend_x) @@ -1079,6 +1102,7 @@ void Capture_brush_with_lasso(int vertices, short * points,short clear) Error(0); Brush=(byte *)malloc(1*1); + if(Brush==NULL) Error(ERROR_MEMORY); new_brush_height=new_brush_width=1; *Brush=Fore_color; } @@ -1097,6 +1121,7 @@ void Capture_brush_with_lasso(int vertices, short * points,short clear) free(Brush); Brush=(byte *)malloc(1*1); + if(Brush==NULL) Error(ERROR_MEMORY); Brush_height=1; Brush_width=1; diff --git a/brush.h b/brush.h index 02206059..437c43cc 100644 --- a/brush.h +++ b/brush.h @@ -105,4 +105,12 @@ void Nibble_brush(void); */ void Capture_brush_with_lasso(int vertices, short * points,short clear); + +/// +/// Changes the Brush size, discarding its previous content. +/// @return 0 OK, 1 Failed +byte Realloc_brush(word new_brush_width, word new_brush_height); + + + #endif diff --git a/buttons.c b/buttons.c index 1b58324a..96d2348f 100644 --- a/buttons.c +++ b/buttons.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include "const.h" @@ -50,6 +51,20 @@ #include "windows.h" #include "brush.h" #include "input.h" +#include "special.h" + +#if defined(__amigaos4__) || defined(__AROS__) || defined(__MORPHOS__) || defined(__amigaos__) + #include + #include + #define isHidden(x) (0) +#elif defined(__WIN32__) + #include + #include + #define isHidden(x) (GetFileAttributesA((x)->d_name)&FILE_ATTRIBUTE_HIDDEN) +#else + #include + #define isHidden(x) ((x)->d_name[0]=='.') +#endif extern char Program_version[]; // generated in pversion.c @@ -112,10 +127,11 @@ void Message_out_of_memory(void) void Button_Message_initial(void) { - char str[21]; + char str[30]; int x_pos,offs_y,x,y; - sprintf(str,"GrafX2 version %s",Program_version); + strcpy(str,"GrafX2 version "); + strcat(str,Program_version); Open_window(260,172,str); Window_display_frame_in(10,20,239,62); @@ -124,11 +140,11 @@ void Button_Message_initial(void) Menu_factor_X*237,Menu_factor_Y*60,MC_Black); for (y=23,offs_y=0; y<79; offs_y+=231,y++) for (x=14,x_pos=0; x_pos<231; x_pos++,x++) - Pixel_in_window(x,y,GFX_logo_grafx2[offs_y+x_pos]); + Pixel_in_window(x,y,Gfx->Logo_grafx2[offs_y+x_pos]); - Print_in_window(130-4*21,88,"Copyright (c) 2007 by",MC_Dark,MC_Light); + Print_in_window(130-4*26,88,"Copyright (c) 2007-2009 by",MC_Dark,MC_Light); Print_in_window(130-4*23,96,"the Grafx2 project team",MC_Black,MC_Light); - Print_in_window(130-4*26,112,"Copyright (c) 1996-1999 by",MC_Dark,MC_Light); + Print_in_window(130-4*26,112,"Copyright (c) 1996-2001 by",MC_Dark,MC_Light); Print_in_window(130-4*13,120,"Sunset Design",MC_Black,MC_Light); //Print_in_window( 120-4*13,128,"(placeholder)",MC_Dark,MC_Light); Print_in_window(130-4*28,136,"http://grafx2.googlecode.com",MC_Dark,MC_Light); @@ -287,7 +303,7 @@ void Button_Select_forecolor(void) if (color == Fore_color) { // Check if it's a double-click - if (time_click - time_previous < 500) + if (time_click - time_previous < Config.Double_click_speed) { // Open palette window Button_Palette(); @@ -413,6 +429,8 @@ byte Button_Quit_local_function(void) clicked_button=Window_clicked_button(); if (Is_shortcut(Key,0x100+BUTTON_HELP)) Window_help(BUTTON_QUIT, NULL); + else if (Is_shortcut(Key,0x100+BUTTON_QUIT)) + clicked_button=1; } while (clicked_button<=0); @@ -490,6 +508,7 @@ void Button_Clear(void) else Hide_current_image(0); Display_all_screen(); + End_of_modification(); Unselect_button(BUTTON_CLEAR); Display_cursor(); } @@ -503,12 +522,13 @@ void Button_Clear_with_backcolor(void) else Hide_current_image(Back_color); Display_all_screen(); + End_of_modification(); Unselect_button(BUTTON_CLEAR); Display_cursor(); } //---------- Menu dans lequel on tagge des couleurs (genre Stencil) ---------- -void Menu_tag_colors(char * window_title, byte * table, byte * mode, byte can_cancel, const char *help_section) +void Menu_tag_colors(char * window_title, byte * table, byte * mode, byte can_cancel, const char *help_section, word close_shortcut) { short clicked_button; byte backup_table[256]; @@ -608,6 +628,10 @@ void Menu_tag_colors(char * window_title, byte * table, byte * mode, byte can_ca Key=0; break; } + else if (Is_shortcut(Key,close_shortcut)) + { + clicked_button=4; + } } } while (clicked_button<4); @@ -646,7 +670,7 @@ void Stencil_update_color(byte color) void Button_Stencil_menu(void) { - Menu_tag_colors("Stencil",Stencil,&Stencil_mode,1, "STENCIL"); + Menu_tag_colors("Stencil",Stencil,&Stencil_mode,1, "STENCIL", SPECIAL_STENCIL_MENU); } @@ -659,7 +683,7 @@ void Button_Mask_mode(void) void Button_Mask_menu(void) { - Menu_tag_colors("Mask",Mask_table,&Mask_mode,1, "MASK"); + Menu_tag_colors("Mask",Mask_table,&Mask_mode,1, "MASK", SPECIAL_MASK_MENU); } @@ -697,13 +721,16 @@ void Settings_display_config(T_Config * conf) Print_in_window( 91, 99,(conf->Clear_palette)?YES:NO,MC_Black,MC_Light); Print_in_window( 91,114,(conf->Maximize_preview)?YES:NO,MC_Black,MC_Light); Print_in_window( 91,129,(conf->Backup)?YES:NO,MC_Black,MC_Light); + /* switch (conf->Cursor) { case 0 : Print_in_window(67,144," Solid",MC_Black,MC_Light); break; case 1 : Print_in_window(67,144,"Transp",MC_Black,MC_Light); break; default: Print_in_window(67,144," Thin",MC_Black,MC_Light); } + */ + /* if (conf->Font) { // Fun Print_in_window( 8,31," ",MC_Black,MC_Light); @@ -718,6 +745,7 @@ void Settings_display_config(T_Config * conf) Print_in_window( 8,31,"\020",MC_Black,MC_Light); Print_in_window( 78,31,"\021",MC_Black,MC_Light); } + */ Print_in_window(155,166,(conf->Auto_save)?YES:NO,MC_Black,MC_Light); @@ -757,7 +785,6 @@ void Button_Settings(void) Open_window(307,182,"Settings"); // On commence par dessiner tous les Cadres - Window_display_frame( 5, 16,157,30); // Font Window_display_frame( 5, 47,157,17); // Nb UNDO Window_display_frame(163, 16,139,48); // Show in filelist Window_display_frame(253, 77, 49,82); // Mouse sens. @@ -772,7 +799,6 @@ void Button_Settings(void) Pixel_in_window(160,77,MC_Dark); */ // On affiche maintenant tout le blabla - Print_in_window( 69, 19,"Font" ,MC_Dark,MC_Light); Print_in_window(169, 19,"Show in filelist",MC_Dark,MC_Light); Print_in_window( 9, 52,"Nb of UNDO pages",MC_Dark,MC_Light); Print_in_window( 80, 70,"Miscellaneous" ,MC_Dark,MC_Light); @@ -781,52 +807,47 @@ void Button_Settings(void) Print_in_window(256,123,"X" ,MC_Dark,MC_Light); Print_in_window(292,123,"Y" ,MC_Dark,MC_Light); - // Boutons de fontes - Window_set_normal_button(17,28,59,14,"Classic",0,1,SDLK_LAST); // 1 - Window_set_normal_button(91,28,59,14,"Fun" ,0,1,SDLK_LAST); // 2 // Button Show/Hide dans le fileselect - Window_set_normal_button(167, 28,131,14,"Hidden files: ",0,1,SDLK_LAST); // 3 - Window_set_normal_button(167, 43,131,14,"Hidden dir. : ",0,1,SDLK_LAST); // 4 -// Window_set_normal_button(167, 58,131,14,"System dir. : ",0,1,SDLK_LAST); // 5 + Window_set_normal_button(167, 28,131,14,"Hidden files: ",0,1,SDLK_LAST); // 1 + Window_set_normal_button(167, 43,131,14,"Hidden dir. : ",0,1,SDLK_LAST); // 2 +// Window_set_normal_button(167, 58,131,14,"System dir. : ",0,1,SDLK_LAST); // Button Show/Hide Picture limits - Window_set_normal_button( 9, 81,107,14,"Limits : ",0,1,SDLK_LAST); // 6 + Window_set_normal_button( 9, 81,107,14,"Limits : ",0,1,SDLK_LAST); // 3 // Button Show/Hide Picture limits - Window_set_normal_button( 9, 96,107,14,"Clear pal: ",0,1,SDLK_LAST); // 7 + Window_set_normal_button( 9, 96,107,14,"Clear pal: ",0,1,SDLK_LAST); // 4 // Button Show/Hide Picture limits - Window_set_normal_button( 9,111,107,14,"Max prev.: ",0,1,SDLK_LAST); // 8 + Window_set_normal_button( 9,111,107,14,"Max prev.: ",0,1,SDLK_LAST); // 5 // Button Effectuer des backups à chaque sauvegarde - Window_set_normal_button( 9,126,107,14,"Backup : ",0,1,SDLK_LAST); // 9 - // Button item du curseur - Window_set_normal_button( 9,141,107,14,"Cursor: ",0,1,SDLK_LAST); // 10 + Window_set_normal_button( 9,126,107,14,"Backup : ",0,1,SDLK_LAST); // 6 // Button Safety colors - Window_set_normal_button(117, 81,131,14,"Safe. colors: ",0,1,SDLK_LAST); // 11 + Window_set_normal_button(117, 81,131,14,"Safe. colors: ",0,1,SDLK_LAST); // 7 // Button Adjust Brush Pick - Window_set_normal_button(117, 96,131,14,"AdjBrushPick: ",0,1,SDLK_LAST); // 12 + Window_set_normal_button(117, 96,131,14,"AdjBrushPick: ",0,1,SDLK_LAST); // 8 // Button Separate colors - Window_set_normal_button(117,111,131,14,"Separate col: ",0,1,SDLK_LAST); // 13 + Window_set_normal_button(117,111,131,14,"Separate col: ",0,1,SDLK_LAST); // 9 // Button Passer dans la résolution appropriée après un chargement - Window_set_normal_button(117,126,131,14,"Auto-set res: ",0,1,SDLK_LAST); // 14 + Window_set_normal_button(117,126,131,14,"Auto-set res: ",0,1,SDLK_LAST); // 10 // Button Adapter la palette après un chargement (<=> Shift+BkSpc) - Window_set_normal_button(117,141,131,14,"Coords: ",0,1,SDLK_LAST); // 15 + Window_set_normal_button(117,141,131,14,"Coords: ",0,1,SDLK_LAST); // 11 // Button Reload - Window_set_normal_button( 6,163, 51,14,"Reload" ,0,1,SDLK_LAST); // 16 + Window_set_normal_button( 6,163, 51,14,"Reload" ,0,1,SDLK_LAST); // 12 // Button Auto-save - Window_set_normal_button( 73,163,107,14,"Auto-save: ",0,1,SDLK_LAST); // 17 + Window_set_normal_button( 73,163,107,14,"Auto-save: ",0,1,SDLK_LAST); // 13 // Button Save - Window_set_normal_button(183,163, 51,14,"Save" ,0,1,SDLK_LAST); // 18 + Window_set_normal_button(183,163, 51,14,"Save" ,0,1,SDLK_LAST); // 14 // Button Close - Window_set_normal_button(250,163, 51,14,"Close" ,0,1,KEY_ESC); // 19 + Window_set_normal_button(250,163, 51,14,"Close" ,0,1,KEY_ESC); // 15 // Jauges de sensibilité de la souris (X puis Y) - Window_set_scroller_button(265,99,56,4,1,0); // 20 - Window_set_scroller_button(279,99,56,4,1,0); // 21 + Window_set_scroller_button(265,99,56,4,1,0); // 16 + Window_set_scroller_button(279,99,56,4,1,0); // 17 // Zone de saisie du nb de pages de Undo - Window_set_input_button(140,50,2); // 22 + Window_set_input_button(140,50,2); // 18 Update_window_area(0,0,Window_width, Window_height); @@ -841,69 +862,60 @@ void Button_Settings(void) switch(clicked_button) { - case 1 : // Classic - Config_choisie.Font=0; - break; - case 2 : // Fun - Config_choisie.Font=1; - break; - case 3 : // Hidden files + case 1 : // Hidden files Config_choisie.Show_hidden_files=(Config_choisie.Show_hidden_files)?0:-1; break; - case 4 : // Hidden dir. + case 2 : // Hidden dir. Config_choisie.Show_hidden_directories=(Config_choisie.Show_hidden_directories)?0:-1; break; // case 5 : // System dir. // Config_choisie.Show_system_directories=(Config_choisie.Show_system_directories)?0:-1; // break; - case 5 : // Draw limits + case 3 : // Draw limits Config_choisie.Display_image_limits=!Config_choisie.Display_image_limits; break; - case 6 : // Clear palette + case 4 : // Clear palette Config_choisie.Clear_palette=!Config_choisie.Clear_palette; break; - case 7 : // Maximize preview + case 5 : // Maximize preview Config_choisie.Maximize_preview=!Config_choisie.Maximize_preview; break; - case 8 : // Backup + case 6 : // Backup Config_choisie.Backup=!Config_choisie.Backup; break; - case 9 : // Cursor - Config_choisie.Cursor=(Config_choisie.Cursor+1)%3; - break; - case 10 : // Safety colors + case 7 : // Safety colors Config_choisie.Safety_colors=!Config_choisie.Safety_colors; break; - case 11 : // Adjust brush pick + case 8 : // Adjust brush pick Config_choisie.Adjust_brush_pick=!Config_choisie.Adjust_brush_pick; break; - case 12 : // Separate colors + case 9 : // Separate colors Config_choisie.Separate_colors=!Config_choisie.Separate_colors; break; - case 13 : // Auto-set resolution + case 10 : // Auto-set resolution Config_choisie.Auto_set_res=!Config_choisie.Auto_set_res; break; - case 14 : // Coordonnées + case 11 : // Coordonnées Config_choisie.Coords_rel=!Config_choisie.Coords_rel; break; - case 15 : // Reload + case 12 : // Reload Settings_load_config(&Config_choisie); config_is_reloaded=1; break; - case 16 : // Auto-save + case 13 : // Auto-save Config_choisie.Auto_save=!Config_choisie.Auto_save; break; - case 17 : // Save + case 14 : // Save Settings_save_config(&Config_choisie); break; - // 18 : OK - case 19 : // X Sensib. + // 15 : OK + case 16 : // X Sensib. Config_choisie.Mouse_sensitivity_index_x=Window_attribute2+1; break; - case 20 : // Y Sensib. + case 17 : // Y Sensib. Config_choisie.Mouse_sensitivity_index_y=Window_attribute2+1; break; - case 21 : // Nb pages Undo + case 18 : // Nb pages Undo Num2str(Config_choisie.Max_undo_pages,str,2); Readline(142,52,str,2,1); Config_choisie.Max_undo_pages=atoi(str); @@ -933,28 +945,25 @@ void Button_Settings(void) Spare_fileselector_offset=0; } - if ((clicked_button>=1) && (clicked_button<=18)) + if ((clicked_button>=1) && (clicked_button<15)) Settings_display_config(&Config_choisie); if (Is_shortcut(Key,0x100+BUTTON_HELP)) Window_help(BUTTON_SETTINGS, NULL); + else if (Is_shortcut(Key,0x100+BUTTON_SETTINGS)) + clicked_button=15; } - while ( (clicked_button!=18) && (Key!=SDLK_RETURN) ); + while ( (clicked_button!=15) && (Key!=SDLK_RETURN) ); Config=Config_choisie; - // Font selection - if (Config.Font) - Menu_font=GFX_fun_font; - else - Menu_font=GFX_system_font; - if (config_is_reloaded) Compute_optimal_menu_colors(Main_palette); Close_window(); Unselect_button(BUTTON_SETTINGS); - // Raffichage du menu pour que les inscriptions qui y figurent soient retracées avec la nouvelle fonte + // Raffichage du menu pour que les inscriptions qui y figurent soient + // retracées avec la nouvelle fonte Display_menu(); Display_cursor(); @@ -962,101 +971,397 @@ void Button_Settings(void) Set_number_of_backups(Config.Max_undo_pages); } +// Data for skin selector +T_Fileselector Skin_files_list; + + +// Data for font selector +T_Fileselector Font_files_list; + +// +char * Format_font_filename(const char * fname) +{ + static char result[12]; + int c; + int length; + + fname+=5; // Assume "font_" prefix + length=strlen(fname) - 4; // assume .png extension + + for (c=0;c<11 && c11) + result[10] = ELLIPSIS_CHARACTER; + + return result; +} + +// Add a skin to the list +void Add_font_or_skin(const char *name) +{ + const char * fname; + int namelength; + + // Cut the long name to keep only filename (no directory) + fname = Find_last_slash(name); + if (fname) + fname++; + else + fname=name; + namelength = strlen(fname); + if (namelength>=10 && fname[0]!='_' && !strncmp(fname, "skin_", 5) + && (!strcasecmp(fname+namelength-4,".png") + || !strcasecmp(fname+namelength-4,".gif"))) + { + Add_element_to_list(&Skin_files_list, name, 0); + + if (fname[0]=='\0') + return; + + // Remove directory from full name + strcpy(Skin_files_list.First->Full_name, fname); + // Reformat the short name differently + strcpy(Skin_files_list.First->Short_name, + Format_filename(Skin_files_list.First->Full_name, 0) + ); + } + else if (namelength>=10 && !strncmp(fname, "font_", 5) && (!strcasecmp(fname+namelength-4,".png"))) + { + Add_element_to_list(&Font_files_list, name, 0); + + if (fname[0]=='\0') + return; + + // Remove directory from full name + strcpy(Font_files_list.First->Full_name, fname); + // Reformat the short name differently + strcpy(Font_files_list.First->Short_name,Format_font_filename(Font_files_list.First->Full_name)); + } + +} + +// Callback to display a skin name in the list +void Draw_one_skin_name(word x, word y, word index, byte highlighted) +{ + T_Fileselector_item * current_item; + + if (Skin_files_list.Nb_elements) + { + current_item = Get_item_by_index(&Skin_files_list, index); + Print_in_window(x,y,current_item->Short_name, MC_Black, (highlighted)?MC_Dark:MC_Light); + } +} + +/// Skin selector window +void Button_Skins(void) +{ + short clicked_button; + short temp; + char skinsdir[MAX_PATH_CHARACTERS]; + T_Dropdown_button * font_dropdown; + T_Dropdown_button * cursor_dropdown; + T_List_button * skin_list; + T_Scroller_button * file_scroller; + int selected_font=0; + int selected_cursor=Config.Cursor; + + char * cursors[] = { "Solid", "Transparent", "Thin" }; + + #define FILESEL_Y 52 + + // --- Read the contents of skins/ directory ------------------ + + // Here we use the same data container as the fileselectors. + // Reinitialize the list + Free_fileselector_list(&Skin_files_list); + Free_fileselector_list(&Font_files_list); + // Browse the "skins" directory + strcpy(skinsdir,Data_directory); + strcat(skinsdir,"skins"); + // Add each found file to the list + For_each_file(skinsdir, Add_font_or_skin); + // Sort it + Sort_list_of_files(&Skin_files_list); + Sort_list_of_files(&Font_files_list); + + selected_font = Find_file_in_fileselector(&Font_files_list, Config.Font_file); + + // -------------------------------------------------------------- + + Open_window(178,155,"Skins"); + + // Frames + Window_display_frame_in(6,FILESEL_Y-2,148,84); // File selector + + // Texts + Print_in_window( 6, 21,"Font" ,MC_Black,MC_Light); + Print_in_window( 6, 36,"Cursor" ,MC_Black,MC_Light); + + // Ok button + Window_set_normal_button(6,136, 51,14,"OK" ,0,1,SDLK_RETURN); // 1 + + // List of skins + skin_list = Window_set_list_button( + // Fileselector + Window_set_special_button(8,FILESEL_Y+1,144,80), // 2 + // Scroller for the fileselector + (file_scroller = Window_set_scroller_button(160,FILESEL_Y+1,82, + Skin_files_list.Nb_elements,10,0)), // 3 + Draw_one_skin_name); // 4 + + skin_list->Cursor_position = Find_file_in_fileselector(&Skin_files_list, Config.Skin_file); + + // Buttons to choose a font + font_dropdown = Window_set_dropdown_button(60,19,104,11,0, Get_item_by_index(&Font_files_list,selected_font)->Short_name,1,0,1,RIGHT_SIDE|LEFT_SIDE); // 5 + for (temp=0; tempShort_name); + + // Cancel + Window_set_normal_button(62,136, 51,14,"Cancel",0,1,SDLK_ESCAPE); // 6 + + // Dropdown list to choose cursor type + cursor_dropdown = Window_set_dropdown_button(60,34,104,11,0,cursors[selected_cursor],1,0,1,RIGHT_SIDE|LEFT_SIDE); // 7 + for (temp=0; temp<3; temp++) + Window_dropdown_add_item(cursor_dropdown,temp,cursors[temp]); + + Window_redraw_list(skin_list); + + Update_window_area(0,0,Window_width, Window_height); + + Display_cursor(); + + do + { + clicked_button=Window_clicked_button(); + + switch(clicked_button) + { + case 1 : // OK + break; + case 2 : // doesn't happen + break; + case 3 : // doesn't happen + break; + case 4 : // a file is selected + break; + case 5 : // Font dropdown + selected_font=Window_attribute2; // Get the index of the chosen font. + break; + // 5: Cancel + case 7 : // Cursor + selected_cursor = Window_attribute2; + break; + } + + switch (Key) + { + case SDLK_UNKNOWN : break; + /* + case SDLK_DOWN : // Bas + *quicksearch_filename=0; + Hide_cursor(); + Selector_scroll_down(&Main_fileselector_position,&Main_fileselector_offset); + if (file_scroller->Position!=Main_fileselector_position) + { + // Si c'est le cas, il faut mettre à jour la jauge + file_scroller->Position=Main_fileselector_position; + Window_draw_slider(file_scroller); + } + Key=0; + break; + case SDLK_UP : // Haut + *quicksearch_filename=0; + Hide_cursor(); + Selector_scroll_up(&Main_fileselector_position,&Main_fileselector_offset); + if (file_scroller->Position!=Main_fileselector_position) + { + // Si c'est le cas, il faut mettre à jour la jauge + file_scroller->Position=Main_fileselector_position; + Window_draw_slider(file_scroller); + } + Key=0; + break; + case SDLK_PAGEDOWN : // PageDown + case KEY_MOUSEWHEELDOWN : + *quicksearch_filename=0; + Hide_cursor(); + Selector_page_down(&Main_fileselector_position,&Main_fileselector_offset,9); + if (file_scroller->Position!=Main_fileselector_position) + { + // Si c'est le cas, il faut mettre à jour la jauge + file_scroller->Position=Main_fileselector_position; + Window_draw_slider(file_scroller); + } + Key=0; + break; + case SDLK_PAGEUP : // PageUp + case KEY_MOUSEWHEELUP : + *quicksearch_filename=0; + Hide_cursor(); + Selector_page_up(&Main_fileselector_position,&Main_fileselector_offset,9); + if (file_scroller->Position!=Main_fileselector_position) + { + // Si c'est le cas, il faut mettre à jour la jauge + file_scroller->Position=Main_fileselector_position; + Window_draw_slider(file_scroller); + } + Key=0; + break; + case SDLK_END : // End + *quicksearch_filename=0; + Hide_cursor(); + Selector_end(&Main_fileselector_position,&Main_fileselector_offset); + if (file_scroller->Position!=Main_fileselector_position) + { + // Si c'est le cas, il faut mettre à jour la jauge + file_scroller->Position=Main_fileselector_position; + Window_draw_slider(file_scroller); + } + Key=0; + break; + case SDLK_HOME : // Home + *quicksearch_filename=0; + Hide_cursor(); + Selector_home(&Main_fileselector_position,&Main_fileselector_offset); + if (file_scroller->Position!=Main_fileselector_position) + { + // Si c'est le cas, il faut mettre à jour la jauge + file_scroller->Position=Main_fileselector_position; + Window_draw_slider(file_scroller); + } + Key=0; + break; + default: // Autre => On se place sur le nom de fichier qui correspond + if (clicked_button<=0) + { + if (Is_shortcut(Key,0x100+BUTTON_HELP)) + { + Window_help(BUTTON_SETTINGS, NULL); + break; + } + temp=strlen(quicksearch_filename); + if (Key_ANSI>= ' ' && Key_ANSI < 255 && temp<50) + { + quicksearch_filename[temp]=Key_ANSI; + quicksearch_filename[temp+1]='\0'; + most_matching_filename=Find_filename_match(Skin_files_list, quicksearch_filename); + if ( (most_matching_filename) ) + { + temp=Main_fileselector_position+Main_fileselector_offset; + Hide_cursor(); + Highlight_file(most_matching_filename); + Prepare_and_display_filelist(Main_fileselector_position,Main_fileselector_offset,file_scroller); + Display_cursor(); + if (temp!=Main_fileselector_position+Main_fileselector_offset) + New_preview_is_needed=1; + } + else + *quicksearch_filename=0; + Key=0; + } + } + else + *quicksearch_filename=0; + */ + } + } + while ( (clicked_button!=1) && (clicked_button !=6) && (Key != SDLK_ESCAPE)); + + if(clicked_button == 1) + { + T_Gui_skin * gfx; + byte * new_font; + + // (Re-)load GUI graphics from selected skins + strcpy(skinsdir, Get_item_by_index(&Skin_files_list, skin_list->List_start+skin_list->Cursor_position)->Full_name); + gfx=Load_graphics(skinsdir); + if (gfx == NULL) // Error + { + Verbose_error_message(Gui_loading_error_message); + } + else + { + free(Gfx); + Gfx = gfx; + + free(Config.Skin_file); + Config.Skin_file = strdup(skinsdir); + } + // (Re-)load the selected font + new_font = Load_font(Get_item_by_index(&Font_files_list,selected_font)->Full_name); + if (new_font) + { + const char * fname; + + free(Menu_font); + Menu_font = new_font; + fname = Get_item_by_index(&Font_files_list,selected_font)->Full_name; + free(Config.Font_file); + Config.Font_file = strdup(fname); + } + // Confirm the change of cursor shape + Config.Cursor = selected_cursor; + } + + Close_window(); + Unselect_button(BUTTON_SETTINGS); + // Raffichage du menu pour que les inscriptions qui y figurent soient retracées avec la nouvelle fonte + Display_menu(); + Display_cursor(); +} + //---------------------------- Changement de page ---------------------------- void Button_Page(void) { - byte temp_byte; - word temp_word; - short temp_short; - float temp_float; + byte factor_index; char Temp_buffer[256]; + #define SWAP_BYTES(a,b) { byte c=a; a=b; b=c;} + #define SWAP_WORDS(a,b) { word c=a; a=b; b=c;} + #define SWAP_SHORTS(a,b) { short c=a; a=b; b=c;} + #define SWAP_FLOATS(a,b) { float c=a; a=b; b=c;} + Hide_cursor(); // On dégrossit le travail avec les infos des listes de pages Exchange_main_and_spare(); // On fait le reste du travail "à la main": - temp_short=Spare_offset_X; - Spare_offset_X=Main_offset_X; - Main_offset_X=temp_short; - - temp_short=Spare_offset_Y; - Spare_offset_Y=Main_offset_Y; - Main_offset_Y=temp_short; - - temp_short=Old_spare_offset_X; - Old_spare_offset_X=Old_main_offset_X; - Old_main_offset_X=temp_short; - - temp_short=Old_spare_offset_Y; - Old_spare_offset_Y=Old_main_offset_Y; - Old_main_offset_Y=temp_short; - - temp_short=Spare_separator_position; - Spare_separator_position=Main_separator_position; - Main_separator_position=temp_short; - - temp_short=Spare_X_zoom; - Spare_X_zoom=Main_X_zoom; - Main_X_zoom=temp_short; - - temp_float=Spare_separator_proportion; - Spare_separator_proportion=Main_separator_proportion; - Main_separator_proportion=temp_float; - - temp_byte=Spare_magnifier_mode; - Spare_magnifier_mode=Main_magnifier_mode; - Main_magnifier_mode=temp_byte; + SWAP_SHORTS(Main_offset_X,Spare_offset_X) + SWAP_SHORTS(Main_offset_Y,Spare_offset_Y) + SWAP_SHORTS(Old_main_offset_X,Old_spare_offset_X) + SWAP_SHORTS(Old_main_offset_Y,Old_spare_offset_Y) + SWAP_SHORTS(Main_separator_position,Spare_separator_position) + SWAP_SHORTS(Main_X_zoom,Spare_X_zoom) + SWAP_FLOATS(Main_separator_proportion,Spare_separator_proportion) + SWAP_BYTES (Main_magnifier_mode,Spare_magnifier_mode) Pixel_preview=(Main_magnifier_mode)?Pixel_preview_magnifier:Pixel_preview_normal; - temp_word=Spare_magnifier_factor; - Spare_magnifier_factor=Main_magnifier_factor; - Main_magnifier_factor=temp_word; - - temp_word=Spare_magnifier_height; - Spare_magnifier_height=Main_magnifier_height; - Main_magnifier_height=temp_word; - - temp_word=Spare_magnifier_width; - Spare_magnifier_width=Main_magnifier_width; - Main_magnifier_width=temp_word; - - temp_short=Spare_magnifier_offset_X; - Spare_magnifier_offset_X=Main_magnifier_offset_X; - Main_magnifier_offset_X=temp_short; - - temp_short=Spare_magnifier_offset_Y; - Spare_magnifier_offset_Y=Main_magnifier_offset_Y; - Main_magnifier_offset_Y=temp_short; - + SWAP_WORDS (Main_magnifier_factor,Spare_magnifier_factor) + SWAP_WORDS (Main_magnifier_height,Spare_magnifier_height) + SWAP_WORDS (Main_magnifier_width,Spare_magnifier_width) + SWAP_SHORTS(Main_magnifier_offset_X,Spare_magnifier_offset_X) + SWAP_SHORTS(Main_magnifier_offset_Y,Spare_magnifier_offset_Y) // Swap du booléen "Image modifiée" - temp_byte =Spare_image_is_modified; - Spare_image_is_modified=Main_image_is_modified; - Main_image_is_modified=temp_byte; + SWAP_BYTES (Main_image_is_modified,Spare_image_is_modified) // Swap des infos sur les fileselects strcpy(Temp_buffer ,Spare_current_directory); strcpy(Spare_current_directory,Main_current_directory); strcpy(Main_current_directory,Temp_buffer ); - temp_byte=Spare_format; - Spare_format=Main_format; - Main_format=temp_byte; - - temp_word =Spare_fileselector_position; - Spare_fileselector_position=Main_fileselector_position; - Main_fileselector_position=temp_word; - - temp_word =Spare_fileselector_offset; - Spare_fileselector_offset=Main_fileselector_offset; - Main_fileselector_offset=temp_word; - + SWAP_BYTES (Main_format,Spare_format) + SWAP_WORDS (Main_fileselector_position,Spare_fileselector_position) + SWAP_WORDS (Main_fileselector_offset,Spare_fileselector_offset) + // A la fin, on affiche l'écran - for (temp_byte=0; ZOOM_FACTOR[temp_byte]!=Main_magnifier_factor; temp_byte++); - Change_magnifier_factor(temp_byte); + for (factor_index=0; ZOOM_FACTOR[factor_index]!=Main_magnifier_factor; factor_index++); + Change_magnifier_factor(factor_index); Set_palette(Main_palette); Compute_optimal_menu_colors(Main_palette); @@ -1121,7 +1426,7 @@ void Copy_some_colors(void) static byte mask_color_to_copy[256]; // static to use less stack memset(mask_color_to_copy,1,256); - Menu_tag_colors("Tag colors to copy",mask_color_to_copy,&confirmation,0, NULL); + Menu_tag_colors("Tag colors to copy",mask_color_to_copy,&confirmation,0, NULL, 0xFFFF); if (confirmation && (!Spare_image_is_modified || Confirmation_box("Spare page was modified. Proceed?"))) @@ -1158,6 +1463,8 @@ void Button_Copy_page(void) clicked_button=Window_clicked_button(); if (Is_shortcut(Key,0x100+BUTTON_HELP)) Window_help(BUTTON_PAGE, NULL); + else if (Is_shortcut(Key,0x200+BUTTON_PAGE)) + clicked_button=6; } while (clicked_button<=0); @@ -2073,16 +2380,21 @@ void Button_Gradients(void) default: if (Is_shortcut(Key,0x100+BUTTON_HELP)) { - Window_help(BUTTON_GRADMENU, NULL); + Window_help(BUTTON_GRADRECT, NULL); Key=0; break; } + if (Is_shortcut(Key,0x200+BUTTON_GRADRECT)) + clicked_button=6; } } while (clicked_button<6); Close_window(); - Unselect_button(BUTTON_GRADMENU); + // The Grad rect operation uses the same button as Grad menu. + if (Current_operation != OPERATION_GRAD_RECTANGLE) + Unselect_button(BUTTON_GRADRECT); + Display_cursor(); Gradient_pixel=Display_pixel; @@ -2182,19 +2494,27 @@ void Button_Paintbrush_menu(void) short x_pos,y_pos; byte index; - Open_window(310,155,"Paintbrush menu"); + Open_window(310,180,"Paintbrush menu"); - Window_display_frame(8,21,294,107); + Window_display_frame(8,21,294,132); - Window_set_normal_button(122,133,67,14,"Cancel",0,1,KEY_ESC); // 1 + Window_set_normal_button(122,158,67,14,"Cancel",0,1,KEY_ESC); // 1 for (index=0; index(NB_PAINTBRUSH_SPRITES+1)) + { + index = clicked_button-NB_PAINTBRUSH_SPRITES-2; + + if (Window_attribute1==RIGHT_SIDE) + { + // Store + + x_pos=13+((index+NB_PAINTBRUSH_SPRITES)%12)*24; + y_pos=27+((index+NB_PAINTBRUSH_SPRITES)/12)*25; + + Store_brush(index); + Hide_cursor(); + Display_stored_brush_in_window(x_pos+2, y_pos+2, index); + Display_cursor(); + } + else + { + // Restore and exit + + if (Restore_brush(index)) + { + Close_window(); + break; + } + } + + } + else if (clicked_button>1 && Window_attribute1==LEFT_SIDE) + // Standard paintbrushes + { + Close_window(); + index=clicked_button-2; + Paintbrush_shape=Gfx->Paintbrush_type[index]; + Paintbrush_width=Gfx->Preset_paintbrush_width[index]; + Paintbrush_height=Gfx->Preset_paintbrush_height[index]; + Paintbrush_offset_X=Gfx->Preset_paintbrush_offset_X[index]; + Paintbrush_offset_Y=Gfx->Preset_paintbrush_offset_Y[index]; + for (y_pos=0; y_posPaintbrush_sprite[index][y_pos][x_pos]; + Change_paintbrush_shape(Gfx->Paintbrush_type[index]); + + break; + } + else if (clicked_button==1 || Is_shortcut(Key,0x100+BUTTON_PAINTBRUSHES)) + { + Close_window(); + break; + } } - while (clicked_button<=0); - - Close_window(); - - if (clicked_button!=1) // pas Cancel - { - index=clicked_button-2; - Paintbrush_shape=Paintbrush_type[index]; - Paintbrush_width=Preset_paintbrush_width[index]; - Paintbrush_height=Preset_paintbrush_height[index]; - Paintbrush_offset_X=Preset_paintbrush_offset_X[index]; - Paintbrush_offset_Y=Preset_paintbrush_offset_Y[index]; - for (y_pos=0; y_pos>(15-(i&0xF)))&1)?MC_White:MC_Black); + ((Gfx->Sieve_pattern[index][j&0xF]>>(15-(i&0xF)))&1)?MC_White:MC_Black); Update_rect(ToWinX(10),ToWinY(22),ToWinL(12*23+16),ToWinH(16)); } @@ -4258,7 +4723,7 @@ void Copy_preset_sieve(byte index) for (j=0; j<16; j++) for (i=0; i<16; i++) - Sieve[i][j]=(GFX_sieve_pattern[index][j]>>(15-i))&1; + Sieve[i][j]=(Gfx->Sieve_pattern[index][j]>>(15-i))&1; Sieve_width=16; Sieve_height=16; } @@ -4456,10 +4921,9 @@ void Button_Sieve_menu(void) break; case 7 : // Transfer to brush - if (Brush) - free(Brush); Brush_width=Sieve_width; Brush_height=Sieve_height; + free(Brush); Brush=(byte *)malloc(((long)Brush_height)*Brush_width); for (y_pos=0; y_posEffect_sprite[sprite_number][y][x]); Update_rect(ToWinX(start_x),ToWinY(start_y),MENU_SPRITE_WIDTH*Menu_factor_X,MENU_SPRITE_HEIGHT*Menu_factor_Y); } @@ -4767,14 +5231,13 @@ void Button_Effects(void) { clicked_button=Window_clicked_button(); - if (Key==KEY_ESC) + if (Key==KEY_ESC || Is_shortcut(Key,0x100+BUTTON_EFFECTS)) { clicked_button=11; Key=0; } else if (Is_shortcut(Key,0x100+BUTTON_HELP)) { - Key=0; // Aide contextuelle switch(Window_get_clicked_button()) { @@ -4811,7 +5274,9 @@ void Button_Effects(void) default: Window_help(BUTTON_EFFECTS, NULL); } - continue; + // Hack because we have used Window_get_clicked_button() + Input_sticky_control=0; + // } switch (clicked_button) @@ -4970,17 +5435,7 @@ void Button_Effects(void) exit_by_close_button=1; break; case 12 : // All off - Effect_function=No_effect; - Shade_mode=0; - Quick_shade_mode=0; - Colorize_mode=0; - Smooth_mode=0; - Tiling_mode=0; - Smear_mode=0; - Stencil_mode=0; - Mask_mode=0; - Sieve_mode=0; - Snap_mode=0; + Effects_off(); Hide_cursor(); Display_effect_states(); Display_cursor(); @@ -5009,14 +5464,10 @@ void Button_Effects(void) Display_cursor(); } -// Affiche tout le selecteur de fontes -void Draw_font_selector(short x, short y, short list_start, short cursor_position, short nb_visibles) +// Callback to display a font name in the list +void Draw_one_font_name(word x, word y, word index, byte highlighted) { - int index; - for (index=0; index < nb_visibles; index++) - { - Print_in_window(x,y+index*8,Font_label(index+list_start), MC_Black, (cursor_position==index)?MC_Dark:MC_Light); - } + Print_in_window(x,y,Font_label(index), MC_Black, (highlighted)?MC_Dark:MC_Light); } void Button_Text() @@ -5026,6 +5477,7 @@ void Button_Text() static int antialias=1; static short list_start=0; // index de le premiere fonte dans le selector static short cursor_position=0; // index de la ligne active dans le selector + static short selected_font_index=0; static short is_bold=0; static short is_italic=0; @@ -5038,10 +5490,12 @@ void Button_Text() T_Special_button * input_size_button; T_Special_button * input_text_button; T_Special_button * preview_button; + T_Special_button * font_list_button; T_Scroller_button * font_scroller; + T_List_button * font_list; + byte redraw_is_needed=1; byte preview_is_needed=1; - short temp; Open_window(288,180,"Text"); @@ -5065,7 +5519,7 @@ void Button_Text() // Scroller des fontes font_scroller = Window_set_scroller_button(165,35,NB_FONTS*8,Nb_fonts,NB_FONTS,list_start); // 5 // Liste des fontes disponibles - Window_set_special_button(8,35,152,NB_FONTS*8); // 6 + font_list_button = Window_set_special_button(8,35,152,NB_FONTS*8); // 6 Window_display_frame_in(7, 33, 154, NB_FONTS*8+4); // Taille texte @@ -5079,6 +5533,15 @@ void Button_Text() Window_set_normal_button(8,160,40,14,"OK",0,1,SDLK_RETURN); // 11 Window_set_normal_button(54,160,60,14,"Cancel",0,1,KEY_ESC); // 12 + + // List of fonts + font_list = Window_set_list_button(font_list_button, font_scroller, Draw_one_font_name); // 13 + // Restore its settings from last passage in screen + font_list->List_start = list_start; + font_list->Cursor_position = cursor_position; + + Window_redraw_list(font_list); + Update_window_area(0,0,Window_width, Window_height); // str texte @@ -5094,20 +5557,15 @@ void Button_Text() // Taille Num2str(font_size,size_buffer,3); Window_input_content(input_size_button,size_buffer); - // Selecteur de fonte - Draw_font_selector(8, 35, list_start, cursor_position, NB_FONTS); } if (preview_is_needed) { const char * preview_string = "AaBbCcDdEeFf012345"; if (str[0]) preview_string=str; - if (new_brush) - { - free(new_brush); - } Window_rectangle(8, 106, 273, 50,Back_color); - new_brush = Render_text(preview_string, cursor_position+list_start, font_size, antialias, is_bold, is_italic, &new_width, &new_height); + free(new_brush); + new_brush = Render_text(preview_string, selected_font_index, font_size, antialias, is_bold, is_italic, &new_width, &new_height); if (new_brush) { Display_brush( @@ -5137,147 +5595,10 @@ void Button_Text() clicked_button=Window_clicked_button(); if (clicked_button==0) { - if (Key==SDLK_UP && (cursor_position+list_start)>0) - { - Key=0; - Hide_cursor(); - cursor_position--; - if (cursor_position<0) - { - list_start=list_start+cursor_position; - cursor_position=0; - // Mise à jour du scroller - font_scroller->Position=list_start; - Window_draw_slider(font_scroller); - } - redraw_is_needed=1; - preview_is_needed=1; - } - if (Key==SDLK_DOWN && (cursor_position+list_start)<(Nb_fonts-1)) - { - Key=0; - Hide_cursor(); - cursor_position++; - if (cursor_position>(NB_FONTS-1)) - { - list_start=list_start+cursor_position-(NB_FONTS-1); - cursor_position=(NB_FONTS-1); - // Mise à jour du scroller - font_scroller->Position=list_start; - Window_draw_slider(font_scroller); - } - redraw_is_needed=1; - preview_is_needed=1; - } - if (Key==SDLK_HOME && (cursor_position!=0 || list_start!=0)) - { - Key=0; - Hide_cursor(); - cursor_position=0; - list_start=0; - // Mise à jour du scroller - font_scroller->Position=list_start; - Window_draw_slider(font_scroller); - redraw_is_needed=1; - preview_is_needed=1; - } - if (Key==SDLK_END && (cursor_position+list_start)<(Nb_fonts-1)) - { - Key=0; - Hide_cursor(); - cursor_position=(Nb_fonts-1)-list_start; - if (cursor_position>(NB_FONTS-1)) - { - list_start=list_start+cursor_position-(NB_FONTS-1); - cursor_position=(NB_FONTS-1); - // Mise à jour du scroller - font_scroller->Position=list_start; - Window_draw_slider(font_scroller); - } - redraw_is_needed=1; - preview_is_needed=1; - } - if (Key==SDLK_PAGEDOWN && (cursor_position+list_start)<(Nb_fonts-1)) - { - Key=0; - Hide_cursor(); - if (Nb_fontsNb_fonts) - { - list_start=Nb_fonts-NB_FONTS; - } - // Mise à jour du scroller - font_scroller->Position=list_start; - Window_draw_slider(font_scroller); - } - redraw_is_needed=1; - preview_is_needed=1; - } - if (Key==SDLK_PAGEUP && (cursor_position+list_start)>0) - { - Key=0; - Hide_cursor(); - if(cursor_position!=0) - { - cursor_position=0; - } - else - { - list_start-=NB_FONTS; - if (list_start<0) - { - list_start=0; - } - // Mise à jour du scroller - font_scroller->Position=list_start; - Window_draw_slider(font_scroller); - } - redraw_is_needed=1; - preview_is_needed=1; - } - if (Key == KEY_MOUSEWHEELUP && list_start>0) - { - cursor_position+=list_start; - if (list_start>=3) - list_start-=3; - else - list_start=0; - cursor_position-=list_start; - // On affiche à nouveau la liste - Hide_cursor(); - redraw_is_needed=1; - // Mise à jour du scroller - font_scroller->Position=list_start; - Window_draw_slider(font_scroller); - } - if (Key==KEY_MOUSEWHEELDOWN && list_startNb_fonts) - { - list_start=Nb_fonts-NB_FONTS; - } - cursor_position-=list_start; - // On affiche à nouveau la liste - Hide_cursor(); - redraw_is_needed=1; - // Mise à jour du scroller - font_scroller->Position=list_start; - Window_draw_slider(font_scroller); - } if (Is_shortcut(Key,0x100+BUTTON_HELP)) Window_help(BUTTON_TEXT, NULL); + else if (Is_shortcut(Key,0x100+BUTTON_TEXT)) + clicked_button=12; } switch(clicked_button) { @@ -5308,29 +5629,19 @@ void Button_Text() break; case 5: // Scroller des fontes - if (list_start!=Window_attribute2) - { - cursor_position+=list_start; - list_start=Window_attribute2; - cursor_position-=list_start; - // On affiche à nouveau la liste - Hide_cursor(); - redraw_is_needed=1; - } + /* Cannot happen, event is catched by the list control */ break; case 6: // Selecteur de fonte - temp=(((Mouse_Y-Window_pos_Y)/Menu_factor_Y)-35)>>3; - if (temp!=cursor_position && temp < Nb_fonts) - { - cursor_position=temp; - // On affiche à nouveau la liste - Hide_cursor(); - redraw_is_needed=1; - preview_is_needed=1; - } + /* Cannot happen, event is catched by the list control */ break; - + + case 13: // Font selection + selected_font_index = Window_attribute2; + Hide_cursor(); + preview_is_needed=1; + break; + case 7: // Taille du texte (nombre) Readline(222,45,size_buffer,3,1); font_size=atoi(size_buffer); @@ -5369,6 +5680,10 @@ void Button_Text() case 11: // OK + // Save the selector settings + list_start = font_list->List_start; + cursor_position = font_list->Cursor_position; + if (!new_brush) { // Si echec de rendu @@ -5378,7 +5693,7 @@ void Button_Text() Error(0); return; } - if (Brush) free(Brush); + free(Brush); Brush=new_brush; Brush_width=new_width; @@ -5392,7 +5707,7 @@ void Button_Text() // On passe en brosse: Display_cursor(); - if (antialias || !TrueType_font(cursor_position+list_start)) + if (antialias || !TrueType_font(selected_font_index)) Change_paintbrush_shape(PAINTBRUSH_SHAPE_COLOR_BRUSH); else Change_paintbrush_shape(PAINTBRUSH_SHAPE_MONO_BRUSH); @@ -5408,8 +5723,12 @@ void Button_Text() return; case 12: // Cancel - if (new_brush) - free(new_brush); + // Save the selector settings + list_start = font_list->List_start; + cursor_position = font_list->Cursor_position; + + free(new_brush); + new_brush = NULL; Close_window(); Unselect_button(BUTTON_TEXT); Display_cursor(); @@ -5418,12 +5737,232 @@ void Button_Text() } } +void Display_stored_brush_in_window(word x_pos,word y_pos,int index) +{ + if (Brush_container[index].Paintbrush_shape < PAINTBRUSH_SHAPE_MAX) + { + int x,y; + int offset_x=0, offset_y=0; + //int brush_offset_x=0, brush_offset_y=0; + + // Determine draw offset (small brushes are stacked on corner of their preview) + if (Brush_container[index].WidthBRUSH_CONTAINER_PREVIEW_WIDTH) + brush_offset_x = (Paintbrush_width-BRUSH_CONTAINER_PREVIEW_WIDTH)/2; + if (Paintbrush_height>BRUSH_CONTAINER_PREVIEW_HEIGHT) + brush_offset_y = (Paintbrush_height-BRUSH_CONTAINER_PREVIEW_HEIGHT)/2; + + for (y=0; yBRUSH_CONTAINER_PREVIEW_WIDTH || + Brush_height>BRUSH_CONTAINER_PREVIEW_HEIGHT) + { + // Scale + Rescale(Brush, Brush_width, Brush_height, (byte *)(Brush_container[index].Thumbnail), BRUSH_CONTAINER_PREVIEW_WIDTH, BRUSH_CONTAINER_PREVIEW_HEIGHT, 0, 0); + } + else + { + // Direct copy + Copy_part_of_image_to_another(Brush, 0,0,Brush_width, Brush_height,Brush_width,(byte *)(Brush_container[index].Thumbnail),0,0,BRUSH_CONTAINER_PREVIEW_WIDTH); + } + } + else + { + Error(0); + } + } +} + +byte Restore_brush(int index) +{ + byte shape; + word x_pos; + word y_pos; + + shape = Brush_container[index].Paintbrush_shape; + + if (shape == PAINTBRUSH_SHAPE_MAX) + return 0; + // Mono brushes + if (shape <= PAINTBRUSH_SHAPE_MISC) + { + Paintbrush_shape=shape; + Paintbrush_width=Brush_container[index].Width; + Paintbrush_height=Brush_container[index].Height; + if (shape == PAINTBRUSH_SHAPE_HORIZONTAL_BAR) + Paintbrush_height=1; + else if (shape == PAINTBRUSH_SHAPE_VERTICAL_BAR) + Paintbrush_width=1; + + if (Paintbrush_width <= BRUSH_CONTAINER_PREVIEW_WIDTH && + Paintbrush_height <= BRUSH_CONTAINER_PREVIEW_HEIGHT) + { + // Manually copy the "pixels" + for (y_pos=0; y_pos>1; + Paintbrush_offset_Y=Paintbrush_height>>1; + } + else + { + // Recreate the brush pixels from its shape and dimensions + Set_paintbrush_size(Paintbrush_width,Paintbrush_height); + } + } + // Color brushes + if (shape == PAINTBRUSH_SHAPE_COLOR_BRUSH || + shape == PAINTBRUSH_SHAPE_MONO_BRUSH) + { + Paintbrush_shape=shape; + Realloc_brush(Brush_container[index].Width,Brush_container[index].Height); + // Realloc sets Brush_width and Brush_height to new size. + memcpy(Brush, Brush_container[index].Brush, Brush_height*Brush_width); + + Brush_offset_X=Brush_width>>1; + Brush_offset_Y=Brush_height>>1; + + } + Change_paintbrush_shape(shape); + + return 1; +} + +void Button_Brush_container(void) +{ + short clicked_button; + short x_pos,y_pos; + byte index; + + Open_window(BRUSH_CONTAINER_COLUMNS*(BRUSH_CONTAINER_PREVIEW_WIDTH+8)+8, + BRUSH_CONTAINER_ROWS*(BRUSH_CONTAINER_PREVIEW_HEIGHT+8)+40, + "Brushes"); + + Window_set_normal_button( + (BRUSH_CONTAINER_COLUMNS*(BRUSH_CONTAINER_PREVIEW_WIDTH+8)-59)/2, + (BRUSH_CONTAINER_ROWS)*(BRUSH_CONTAINER_PREVIEW_HEIGHT+8)+18, + 67,14,"Cancel",0,1,KEY_ESC); // 1 + + index=0; + for (index=0; index < BRUSH_CONTAINER_ROWS*BRUSH_CONTAINER_COLUMNS; index++) + { + x_pos = (index % BRUSH_CONTAINER_COLUMNS)*(BRUSH_CONTAINER_PREVIEW_WIDTH+8)+7; + y_pos = (index / BRUSH_CONTAINER_COLUMNS)*(BRUSH_CONTAINER_PREVIEW_HEIGHT+8)+18; + Window_set_normal_button( + x_pos, + y_pos, + BRUSH_CONTAINER_PREVIEW_WIDTH+2, + BRUSH_CONTAINER_PREVIEW_HEIGHT+2, + "",0,1,SDLK_LAST); + Display_stored_brush_in_window(x_pos+1, y_pos+1, index); + } + Update_window_area(0,0,Window_width, Window_height); + + Display_cursor(); + + do + { + clicked_button=Window_clicked_button(); + //if (Is_shortcut(Key,0x100+BUTTON_HELP)) + // Window_help(BUTTON_PAINTBRUSHES, NULL); + + if (clicked_button == 1) + break; + + if (clicked_button>1) + { + index = clicked_button-2; + + if (Window_attribute1==RIGHT_SIDE) + { + // Store + + x_pos = (index % BRUSH_CONTAINER_COLUMNS)*(BRUSH_CONTAINER_PREVIEW_WIDTH+8)+7; + y_pos = (index / BRUSH_CONTAINER_COLUMNS)*(BRUSH_CONTAINER_PREVIEW_HEIGHT+8)+18; + + Store_brush(index); + Hide_cursor(); + Display_stored_brush_in_window(x_pos+1, y_pos+1, index); + Display_cursor(); + } + else + { + // Restore and exit + + if (Restore_brush(index)) + break; + } + } + } + while (1); + Close_window(); + + //Unselect_button(BUTTON_PAINTBRUSHES); + Display_cursor(); +} \ No newline at end of file diff --git a/buttons.h b/buttons.h index 68542809..65db64a1 100644 --- a/buttons.h +++ b/buttons.h @@ -353,6 +353,11 @@ void Button_Snap_mode(void); */ void Button_Grid_menu(void); +/*! + Callback to toggle the grid visible in the magnified view. +*/ +void Button_Show_grid(void); + // Mode trame (Sieve) /*! @@ -425,6 +430,17 @@ void Button_Tiling_mode(void); Displays the tiling setup menu. */ void Button_Tiling_menu(void); + +/*! + Callback for the command that turns off all drawaing effects. +*/ +void Effects_off(void); + +/*! + Command that sets the transparency level. +*/ +void Transparency_set(byte amount); + // Menu des effets /*! @@ -568,6 +584,11 @@ void Button_Autosave(void); */ void Button_Settings(void); +/*! + Display the skin selector window. +*/ +void Button_Skins(void); + // Annulation de la dernière modification /*! @@ -621,7 +642,7 @@ void Save_picture(byte image); /*! Generic color tagging menu, for various effects. */ -void Menu_tag_colors(char * window_title, byte * table, byte * mode, byte can_cancel, const char *help_section); +void Menu_tag_colors(char * window_title, byte * table, byte * mode, byte can_cancel, const char *help_section, word close_shortcut ); /*! @@ -635,5 +656,7 @@ void Button_Smooth_menu(void); */ void Button_Smear_mode(void); +void Button_Brush_container(void); + #endif diff --git a/const.h b/const.h index b3716712..20892d2f 100644 --- a/const.h +++ b/const.h @@ -33,7 +33,7 @@ #define BETA1 98 ///< Version number for gfx2.cfg (3/4) #define BETA2 0 ///< Version number for gfx2.cfg (4/4) #define MAX_VIDEO_MODES 100 ///< Maximum number of video modes Grafx2 can propose. -#define NB_SHORTCUTS 134 ///< Number of actions that can have a key combination associated to it. +#define NB_SHORTCUTS 159 ///< Number of actions that can have a key combination associated to it. #define NB_ZOOM_FACTORS 12 ///< Number of zoom levels available in the magnifier. #define MENU_WIDTH 254 ///< Width of the menu (not counting the palette) #define MENU_HEIGHT 44 ///< Height of the menu. @@ -58,13 +58,18 @@ #define DEFAULT_ZOOM_FACTOR 4 ///< Initial zoom factor for the magnifier. #define MAX_PATH_CHARACTERS 260 ///< Number of characters for a file+complete path. Adapt to your OS... #define NB_BOOKMARKS 4 ///< Number of bookmark buttons in Save/Load screen. -// Character to show a right arrow, used when editing long strings. It's present in ::GFX_system_font +// Character to show a right arrow, used when editing long strings. It's present in ::Gfx->System_font #define RIGHT_TRIANGLE_CHARACTER 16 -// Character to show a left arrow, used when editing long strings. It's present in ::GFX_system_font +// Character to show a left arrow, used when editing long strings. It's present in ::Gfx->System_font #define LEFT_TRIANGLE_CHARACTER 17 /// Character to display in menus for an ellipsis. #define ELLIPSIS_CHARACTER '…' +#define BRUSH_CONTAINER_PREVIEW_WIDTH 16 ///< Size for preview of a brush in Brush container +#define BRUSH_CONTAINER_PREVIEW_HEIGHT 16 ///< Size for preview of a brush in Brush container +#define BRUSH_CONTAINER_COLUMNS 4 ///< Number of columns in the Brush container +#define BRUSH_CONTAINER_ROWS 3 ///< Number of rows in the Brush container + /// /// We force the dynamic backup page allocation to leave a minimum of /// 256Kb of free memory, to allow the rest of the program to work safely. @@ -90,14 +95,14 @@ // -- File formats #ifndef __no_pnglib__ -#define NB_KNOWN_FORMATS 13 ///< Total number of known file formats. -#define NB_FORMATS_LOAD 13 ///< Number of file formats that grafx2 can load. -#define NB_FORMATS_SAVE 13 ///< Number of file formats that grafx2 can save. +#define NB_KNOWN_FORMATS 15 ///< Total number of known file formats. +#define NB_FORMATS_LOAD 15 ///< Number of file formats that grafx2 can load. +#define NB_FORMATS_SAVE 15 ///< Number of file formats that grafx2 can save. #else // Without pnglib -#define NB_KNOWN_FORMATS 12 ///< Total number of known file formats. -#define NB_FORMATS_LOAD 12 ///< Number of file formats that grafx2 can load. -#define NB_FORMATS_SAVE 12 ///< Number of file formats that grafx2 can save. +#define NB_KNOWN_FORMATS 14 ///< Total number of known file formats. +#define NB_FORMATS_LOAD 14 ///< Number of file formats that grafx2 can load. +#define NB_FORMATS_SAVE 14 ///< Number of file formats that grafx2 can save. #endif /// List of file formats recognized by grafx2 @@ -114,8 +119,10 @@ enum FILE_FORMATS FORMAT_PI1, FORMAT_PC1, FORMAT_CEL, + FORMAT_NEO, FORMAT_KCF, FORMAT_PAL, + FORMAT_C64, FORMAT_PNG }; @@ -209,7 +216,8 @@ enum PAINTBRUSH_SHAPES PAINTBRUSH_SHAPE_MISC, ///< A raw monochrome bitmap, can't be resized. This must be the last of the preset paintbrush types. PAINTBRUSH_SHAPE_POINT, ///< Used to reduce the paintbrush to a single pixel, during operations like colorpicker. PAINTBRUSH_SHAPE_COLOR_BRUSH, ///< User's brush, in color mode - PAINTBRUSH_SHAPE_MONO_BRUSH ///< User's brush, in mono mode + PAINTBRUSH_SHAPE_MONO_BRUSH, ///< User's brush, in mono mode + PAINTBRUSH_SHAPE_MAX ///< Upper limit. }; /// Normal resting state for a menu button. @@ -241,7 +249,7 @@ enum CHUNKS_CFG CHUNK_MAX }; -/// Identifiers for the 8x8 icons of ::GFX_icon_sprite (these are unused now) +/// Identifiers for the 8x8 icons of ::Gfx->Icon_sprite (most are unused now) enum ICON_TYPES { ICON_FLOPPY_3_5=0, ///< 3½" Floppy disk @@ -271,7 +279,6 @@ enum BUTTON_NUMBERS BUTTON_CIRCLES, BUTTON_FILLCIRC, BUTTON_GRADRECT, - BUTTON_GRADMENU, BUTTON_SPHERES, BUTTON_BRUSH, BUTTON_POLYBRUSH, @@ -374,8 +381,33 @@ enum SPECIAL_ACTIONS SPECIAL_SMOOTH_MODE, SPECIAL_SMOOTH_MENU, SPECIAL_SMEAR_MODE, + SPECIAL_EFFECTS_OFF, SPECIAL_TILING_MODE, + SPECIAL_TRANSPARENCY_1, + SPECIAL_TRANSPARENCY_2, + SPECIAL_TRANSPARENCY_3, + SPECIAL_TRANSPARENCY_4, + SPECIAL_TRANSPARENCY_5, + SPECIAL_TRANSPARENCY_6, + SPECIAL_TRANSPARENCY_7, + SPECIAL_TRANSPARENCY_8, + SPECIAL_TRANSPARENCY_9, + SPECIAL_TRANSPARENCY_0, SPECIAL_TILING_MENU, ///< This must be the last of the "effects" family + SPECIAL_ZOOM_1, + SPECIAL_ZOOM_2, + SPECIAL_ZOOM_3, + SPECIAL_ZOOM_4, + SPECIAL_ZOOM_5, + SPECIAL_ZOOM_6, + SPECIAL_ZOOM_8, + SPECIAL_ZOOM_10, + SPECIAL_ZOOM_12, + SPECIAL_ZOOM_14, + SPECIAL_ZOOM_16, + SPECIAL_ZOOM_18, + SPECIAL_ZOOM_20, + SPECIAL_SHOW_GRID, NB_SPECIAL_SHORTCUTS ///< Number of special shortcuts }; diff --git a/doc/README.txt b/doc/README.txt index 3f71681f..20e49006 100644 --- a/doc/README.txt +++ b/doc/README.txt @@ -52,7 +52,7 @@ executable; You can normally find it in a packed archive whose name begins by the Subversion repository: http://grafx2.googlecode.com/svn/trunk/ or you can find the latest versions as packed archives: -http://code.google.com/p/grafx2/downloads/list +http://code.google.com/p/grafx2/wiki/Downloads === COMPILING === @@ -76,17 +76,18 @@ Sends greetings and glops to pouet.net : http://pouet.net/prod.php?which=51865 === HISTORY === Short revision history : - * 06/2009 2.0 Completed the features planned by Sunset Design. - * 04/2009 2.0b99.0% Many new features and critical fixes. - * 01/2009 2.0b98.0% Now running Linux, Windows, Mac OS X, BeOS, Haiku, - AmigaOS 3.x and 4, MorphOS, SkyOS and gp2x. - * 10/2008 2.0b97.0% Our first public beta release. - * 07/2008 Our first public alpha release, Windows and Linux only - * 04/2007 Start of this project and port to SDL. - * 2001 Sunset Design releases the source under the GNU GPL. - * 12/1999 2.0b96.5% Last release from Sunset Design. - * 11/1996 2.0b90% First public release, at the Wired'96. - * 09/1995 Project starts. + * 09/2009 2.1 GUI improvements and some new features. + * 06/2009 2.0 Completed the features planned by Sunset Design. + * 04/2009 2.0b99.0% Many new features and critical fixes. + * 01/2009 2.0b98.0% Now running Linux, Windows, Mac OS X, BeOS, Haiku, + AmigaOS 3.x and 4, MorphOS, SkyOS and gp2x. + * 10/2008 2.0b97.0% Our first public beta release. + * 07/2008 Our first public alpha release, Windows and Linux only + * 04/2007 Start of this project and port to SDL. + * 2001 Sunset Design releases the source under the GNU GPL. + * 12/1999 2.0b96.5% Last release from Sunset Design. + * 11/1996 2.0b90% First public release, at the Wired'96. + * 09/1995 Project starts. Check http://code.google.com/p/grafx2/source/list for (very) detailed changelog. Check http://code.google.com/p/grafx2/wiki/History for an overview of the new diff --git a/engine.c b/engine.c index 7d371f10..20223d15 100644 --- a/engine.c +++ b/engine.c @@ -75,8 +75,7 @@ char * Menu_tooltip[NB_BUTTONS]= "Filled rectangles ", "Empty circles / ellipses", "Filled circles / ellips.", - "Grad. rectangles ", - "Gradation menu ", + "Grad. rect / Grad. menu ", "Grad. spheres / ellipses", "Brush grab. / Restore ", "Lasso / Restore brush ", @@ -89,13 +88,13 @@ char * Menu_tooltip[NB_BUTTONS]= "Go / Copy to other page ", "Save as / Save ", "Load / Re-load ", - "Settings ", + "Settings / Skins ", "Clear / with backcolor ", "Help / Statistics ", "Undo / Redo ", "Kill current page ", "Quit ", - "Palette editor ", + "Palette editor / setup ", "Scroll pal. bkwd / Fast ", "Scroll pal. fwd / Fast ", "Color #" , @@ -108,6 +107,7 @@ void Save_background(byte **buffer, int x_pos, int y_pos, int width, int height) int index; if(*buffer != NULL) DEBUG("WARNING : buffer already allocated !!!",0); *buffer=(byte *) malloc(width*Menu_factor_X*height*Menu_factor_Y*Pixel_width); + if(*buffer==NULL) Error(0); for (index=0; index<(height*Menu_factor_Y); index++) Read_line(x_pos,y_pos+index,width*Menu_factor_X,(*buffer)+((int)index*width*Menu_factor_X*Pixel_width)); } @@ -119,6 +119,7 @@ void Restore_background(byte *buffer, int x_pos, int y_pos, int width, int heigh for (index=0; indexMenu_block[start_y][end_x]=color_diagonal; // On colorie le point bas gauche Pixel_in_menu(start_x,end_y,color_diagonal); - GFX_menu_block[end_y][start_x]=color_diagonal; + Gfx->Menu_block[end_y][start_x]=color_diagonal; // On colorie la partie haute for (x_pos=start_x;x_pos<=end_x-1;x_pos++) { Pixel_in_menu(x_pos,start_y,color_top_left); - GFX_menu_block[start_y][x_pos]=color_top_left; + Gfx->Menu_block[start_y][x_pos]=color_top_left; } for (y_pos=start_y+1;y_pos<=end_y-1;y_pos++) { // On colorie la partie gauche Pixel_in_menu(start_x,y_pos,color_top_left); - GFX_menu_block[y_pos][start_x]=color_top_left; + Gfx->Menu_block[y_pos][start_x]=color_top_left; // On colorie la partie droite Pixel_in_menu(end_x,y_pos,color_bottom_right); - GFX_menu_block[y_pos][end_x]=color_bottom_right; + Gfx->Menu_block[y_pos][end_x]=color_bottom_right; } // On colorie la partie basse for (x_pos=start_x+1;x_pos<=end_x;x_pos++) { Pixel_in_menu(x_pos,end_y,color_bottom_right); - GFX_menu_block[end_y][x_pos]=color_bottom_right; + Gfx->Menu_block[end_y][x_pos]=color_bottom_right; } break; case BUTTON_SHAPE_TRIANGLE_TOP_LEFT: // On colorie le point haut droit Pixel_in_menu(end_x,start_y,color_diagonal); - GFX_menu_block[start_y][end_x]=color_diagonal; + Gfx->Menu_block[start_y][end_x]=color_diagonal; // On colorie le point bas gauche Pixel_in_menu(start_x,end_y,color_diagonal); - GFX_menu_block[end_y][start_x]=color_diagonal; + Gfx->Menu_block[end_y][start_x]=color_diagonal; // On colorie le coin haut gauche for (x_pos=0;x_posMenu_block[start_y][start_x+x_pos]=color_top_left; Pixel_in_menu(start_x,start_y+x_pos,color_top_left); - GFX_menu_block[start_y+x_pos][start_x]=color_top_left; + Gfx->Menu_block[start_y+x_pos][start_x]=color_top_left; } // On colorie la diagonale for (x_pos=1;x_posMenu_block[end_y-x_pos][start_x+x_pos]=color_bottom_right; } break; case BUTTON_SHAPE_TRIANGLE_BOTTOM_RIGHT: // On colorie le point haut droit Pixel_in_menu(end_x,start_y,color_diagonal); - GFX_menu_block[start_y][end_x]=color_diagonal; + Gfx->Menu_block[start_y][end_x]=color_diagonal; // On colorie le point bas gauche Pixel_in_menu(start_x,end_y,color_diagonal); - GFX_menu_block[end_y][start_x]=color_diagonal; + Gfx->Menu_block[end_y][start_x]=color_diagonal; // On colorie la diagonale for (x_pos=1;x_posMenu_block[end_y-x_pos][start_x+x_pos]=color_top_left; } // On colorie le coin bas droite for (x_pos=0;x_posMenu_block[end_y][end_x-x_pos]=color_bottom_right; Pixel_in_menu(end_x,end_y-x_pos,color_bottom_right); - GFX_menu_block[end_y-x_pos][end_x]=color_bottom_right; + Gfx->Menu_block[end_y-x_pos][end_x]=color_bottom_right; } } if (Menu_is_visible) @@ -372,6 +373,9 @@ void Select_button(int btn_number,byte click) // the unselection of all "Tool" buttons. if (btn_number==BUTTON_ADJUST && click==RIGHT_SIDE) break; + // Same case with the Grad. Rectangle button. + if (btn_number==BUTTON_GRADRECT && click==RIGHT_SIDE) + break; // Pour chaque bouton: for (b=0; bNext; + free(Window_list_button_list); + Window_list_button_list=temp6; + } if (Windows_open != 1) { @@ -1613,6 +1724,42 @@ void Window_dropdown_clear_items(T_Dropdown_button * dropdown) } } +//----------------------- Create a List control ----------------------- +// These controls are special. They work over two controls previously created: +// - entry_button is the textual area where the list values will be printed. +// - scroller is a scroller button attached to it + +T_List_button * Window_set_list_button(T_Special_button * entry_button, T_Scroller_button * scroller, Func_draw_list_item draw_list_item) +{ + T_List_button *temp; + + temp=(T_List_button *)malloc(sizeof(T_List_button)); + temp->Number =++Window_nb_buttons; + temp->List_start = 0; + temp->Cursor_position = 0; + temp->Entry_button = entry_button; + temp->Scroller = scroller; + temp->Draw_list_item = draw_list_item; + + temp->Next=Window_list_button_list; + Window_list_button_list=temp; + return temp; +} + +void Window_redraw_list(T_List_button * list) +{ + int i; + + for (i=Min(list->Scroller->Nb_visibles-1, list->Scroller->Nb_elements-1); i>=0; i--) + { + list->Draw_list_item( + list->Entry_button->Pos_X, + list->Entry_button->Pos_Y + i * 8, + list->List_start + i, + i == list->Cursor_position); + } +} + //----------------------- Ouverture d'un pop-up ----------------------- void Open_popup(word x_pos, word y_pos, word width,word height) @@ -1676,7 +1823,8 @@ void Close_popup(void) T_Palette_button * temp2; T_Scroller_button * temp3; T_Special_button * temp4; - T_Dropdown_button * temp5; + T_Dropdown_button * temp5; + T_List_button * temp6; Hide_cursor(); @@ -1711,7 +1859,13 @@ void Close_popup(void) free(Window_dropdown_button_list); Window_dropdown_button_list=temp5; } - + while (Window_list_button_list) + { + temp6=Window_list_button_list->Next; + free(Window_list_button_list); + Window_list_button_list=temp6; + } + if (Windows_open != 1) { // Restore de ce que la fenêtre cachait @@ -1843,6 +1997,7 @@ void Get_color_behind_window(byte * color, byte * click) char str[25]; byte cursor_was_hidden; + Hide_cursor(); cursor_was_hidden=Cursor_hidden; @@ -1933,15 +2088,15 @@ void Move_window(short dx, short dy) { short new_x=Mouse_X-dx; short new_y=Mouse_Y-dy; - short old_x; - short old_y; - short width=Window_width*Menu_factor_X; - short height=Window_height*Menu_factor_Y; - short a; - byte b; - byte *buffer=NULL; + short old_x; + short old_y; + short width=Window_width*Menu_factor_X; + short height=Window_height*Menu_factor_Y; + short a; + byte b; + byte *buffer=NULL; - Hide_cursor(); + Hide_cursor(); Horizontal_XOR_line(new_x,new_y,width); Vertical_XOR_line(new_x,new_y+1,height-2); @@ -2179,8 +2334,11 @@ short Window_dropdown_on_click(T_Dropdown_button *Button) Window_attribute2=item->Number; if (Button->Display_choice) { - // Mettre à jour automatiquement le libellé de la dropdown - Print_in_window(Button->Pos_X+2,Button->Pos_Y+(Button->Height-7)/2,item->Label,MC_Black,MC_Light); + // Automatically update the label of the dropdown list. + int text_length = (Button->Width-4-(Button->Display_arrow?8:0))/8; + // Clear original label area + Window_rectangle(Button->Pos_X+2,Button->Pos_Y+(Button->Height-7)/2,text_length*8,8,MC_Light); + Print_in_window_limited(Button->Pos_X+2,Button->Pos_Y+(Button->Height-7)/2,item->Label,text_length ,MC_Black,MC_Light); } return Button->Number; } @@ -2221,7 +2379,7 @@ short Window_normal_button_onclick(word x_pos, word y_pos, word width, word heig } } -// --- Renvoie le numéro du bouton clicke (-1:hors de la fenêtre, 0:aucun) --- +// --- Returns the number of the clicked button (-1:out of the window, 0:none) --- short Window_get_clicked_button(void) { T_Normal_button * temp1; @@ -2234,11 +2392,13 @@ short Window_get_clicked_button(void) Window_attribute1=Mouse_K; - // Test du click sur les boutons normaux + // Test click on normal buttons for (temp1=Window_normal_button_list; temp1; temp1=temp1->Next) { - if (Window_click_in_rectangle(temp1->Pos_X,temp1->Pos_Y,temp1->Pos_X+temp1->Width-1,temp1->Pos_Y+temp1->Height-1)) + if ((Input_sticky_control == 0 || Input_sticky_control == temp1->Number) + && Window_click_in_rectangle(temp1->Pos_X,temp1->Pos_Y,temp1->Pos_X+temp1->Width-1,temp1->Pos_Y+temp1->Height-1)) { + Input_sticky_control = temp1->Number; if (temp1->Repeatable) { Hide_cursor(); @@ -2254,135 +2414,145 @@ short Window_get_clicked_button(void) } } - // Test du click sur les zones "palette" + // Test click on "Palette" buttons for (temp2=Window_palette_button_list; temp2; temp2=temp2->Next) { - if (Window_click_in_rectangle(temp2->Pos_X+5,temp2->Pos_Y+3,temp2->Pos_X+160,temp2->Pos_Y+82)) + if ((Input_sticky_control == 0 || Input_sticky_control == temp2->Number) + && Window_click_in_rectangle(temp2->Pos_X+5,temp2->Pos_Y+3,temp2->Pos_X+160,temp2->Pos_Y+82)) { - // On stocke dans Attribut2 le numero de couleur cliqué + Input_sticky_control = temp2->Number; + // We store the clicked color in Attribute2 Window_attribute2 = (((Mouse_X-Window_pos_X)/Menu_factor_X)-(temp2->Pos_X+2)) / 10 * 16 + (((Mouse_Y-Window_pos_Y)/Menu_factor_Y)-(temp2->Pos_Y+3)) / 5; return temp2->Number; } } - // Test du click sur les barres de défilement + // Test click oin slider/scroller bars for (temp3=Window_scroller_button_list; temp3; temp3=temp3->Next) { - if (Window_click_in_rectangle(temp3->Pos_X,temp3->Pos_Y,temp3->Pos_X+10,temp3->Pos_Y+temp3->Height-1)) + // Button Up arrow + if ((Input_sticky_control == 0 || Input_sticky_control == (temp3->Number|1024)) + && Window_click_in_rectangle(temp3->Pos_X,temp3->Pos_Y,temp3->Pos_X+10,temp3->Pos_Y+10)) { - // Button flèche Haut - if (Window_click_in_rectangle(temp3->Pos_X,temp3->Pos_Y,temp3->Pos_X+10,temp3->Pos_Y+10)) + Input_sticky_control = temp3->Number | 1024; + Hide_cursor(); + Window_select_normal_button(temp3->Pos_X,temp3->Pos_Y,11,11); + + if (temp3->Position) { - Hide_cursor(); - Window_select_normal_button(temp3->Pos_X,temp3->Pos_Y,11,11); - - if (temp3->Position) - { - temp3->Position--; - Window_attribute1=1; - Window_attribute2=temp3->Position; - Window_draw_slider(temp3); - } - else - Window_attribute1=0; - - Display_cursor(); - - Slider_timer((Mouse_K==1)? Config.Delay_left_click_on_slider : Config.Delay_right_click_on_slider); - - Hide_cursor(); - Window_unselect_normal_button(temp3->Pos_X,temp3->Pos_Y,11,11); - Display_cursor(); + temp3->Position--; + Window_attribute1=1; + Window_attribute2=temp3->Position; + Window_draw_slider(temp3); } else - // Button flèche Bas - if (Window_click_in_rectangle(temp3->Pos_X,temp3->Pos_Y+temp3->Height-11,temp3->Pos_X+10,temp3->Pos_Y+temp3->Height-1)) + Window_attribute1=0; + + Display_cursor(); + + Slider_timer((Mouse_K==1)? Config.Delay_left_click_on_slider : Config.Delay_right_click_on_slider); + + Hide_cursor(); + Window_unselect_normal_button(temp3->Pos_X,temp3->Pos_Y,11,11); + Display_cursor(); + + return (Window_attribute1)? temp3->Number : 0; + } + + // Button Down arrow + if ((Input_sticky_control == 0 || Input_sticky_control == (temp3->Number|2048)) + && Window_click_in_rectangle(temp3->Pos_X,temp3->Pos_Y+temp3->Height-11,temp3->Pos_X+10,temp3->Pos_Y+temp3->Height-1)) + { + Input_sticky_control = temp3->Number | 2048; + Hide_cursor(); + Window_select_normal_button(temp3->Pos_X,temp3->Pos_Y+temp3->Height-11,11,11); + + if (temp3->Position+temp3->Nb_visiblesNb_elements) { - Hide_cursor(); - Window_select_normal_button(temp3->Pos_X,temp3->Pos_Y+temp3->Height-11,11,11); - - if (temp3->Position+temp3->Nb_visiblesNb_elements) - { - temp3->Position++; - Window_attribute1=2; - Window_attribute2=temp3->Position; - Window_draw_slider(temp3); - } - else - Window_attribute1=0; - - Display_cursor(); - - Slider_timer((Mouse_K==1)? Config.Delay_left_click_on_slider : Config.Delay_right_click_on_slider); - - Hide_cursor(); - Window_unselect_normal_button(temp3->Pos_X,temp3->Pos_Y+temp3->Height-11,11,11); - Display_cursor(); + temp3->Position++; + Window_attribute1=2; + Window_attribute2=temp3->Position; + Window_draw_slider(temp3); } else - // Jauge - if (Window_click_in_rectangle(temp3->Pos_X,temp3->Pos_Y+12,temp3->Pos_X+10,temp3->Pos_Y+temp3->Height-13)) - { - if (temp3->Nb_elements>temp3->Nb_visibles) - { - // S'il y a la place de faire scroller le curseur: - - max_slider_height=(temp3->Height-24); - - // Window_attribute2 reçoit la position dans la jauge correspondant au click - Window_attribute2 =(Mouse_Y-Window_pos_Y) / Menu_factor_Y; - Window_attribute2-=(temp3->Pos_Y+12+((temp3->Cursor_height-1)>>1)); - Window_attribute2*=(temp3->Nb_elements-temp3->Nb_visibles); - - if (Window_attribute2<0) - Window_attribute2=0; - else - { - Window_attribute2 =Round_div(Window_attribute2,max_slider_height-temp3->Cursor_height); - if (Window_attribute2+temp3->Nb_visibles>temp3->Nb_elements) - Window_attribute2=temp3->Nb_elements-temp3->Nb_visibles; - } - - // Si le curseur de la jauge bouge: - - if (temp3->Position!=Window_attribute2) - { - temp3->Position=Window_attribute2; - Window_attribute1=3; - Hide_cursor(); - Window_draw_slider(temp3); - Display_cursor(); - } - else - // Si le curseur de la jauge ne bouge pas: - Window_attribute1=0; - } - else - // S'il n'y a pas la place de bouger le curseur de la jauge: - Window_attribute1=0; - } - else - // Le click se situe dans la zone de la jauge mais n'est sur aucune - // des 3 parties importantes de la jauge Window_attribute1=0; + Display_cursor(); + + Slider_timer((Mouse_K==1)? Config.Delay_left_click_on_slider : Config.Delay_right_click_on_slider); + + Hide_cursor(); + Window_unselect_normal_button(temp3->Pos_X,temp3->Pos_Y+temp3->Height-11,11,11); + Display_cursor(); + return (Window_attribute1)? temp3->Number : 0; } + // Middle slider + if ((Input_sticky_control == temp3->Number) || (Input_sticky_control==0 && + Window_click_in_rectangle(temp3->Pos_X,temp3->Pos_Y+12,temp3->Pos_X+10,temp3->Pos_Y+temp3->Height-13))) + { + Input_sticky_control = temp3->Number; + if (temp3->Nb_elements>temp3->Nb_visibles) + { + // If there is enough room to make the cursor move: + + max_slider_height=(temp3->Height-24); + + // Window_attribute2 receives the position of the cursor. + Window_attribute2 =(Mouse_Y-Window_pos_Y) / Menu_factor_Y; + Window_attribute2-=(temp3->Pos_Y+12+((temp3->Cursor_height-1)>>1)); + Window_attribute2*=(temp3->Nb_elements-temp3->Nb_visibles); + + if (Window_attribute2<0) + Window_attribute2=0; + else + { + Window_attribute2 =Round_div(Window_attribute2,max_slider_height-temp3->Cursor_height); + if (Window_attribute2+temp3->Nb_visibles>temp3->Nb_elements) + Window_attribute2=temp3->Nb_elements-temp3->Nb_visibles; + } + + // If the cursor moved + + if (temp3->Position!=Window_attribute2) + { + temp3->Position=Window_attribute2; + Window_attribute1=3; + Hide_cursor(); + Window_draw_slider(temp3); + Display_cursor(); + } + else + // If the cursor moved + Window_attribute1=0; + } + else + // If there's not enough room to make the cursor move: + Window_attribute1=0; + + return (Window_attribute1)? temp3->Number : 0; + } } - // Test du click sur une zone spéciale + // Test click on a special button for (temp4=Window_special_button_list; temp4; temp4=temp4->Next) { - if (Window_click_in_rectangle(temp4->Pos_X,temp4->Pos_Y,temp4->Pos_X+temp4->Width-1,temp4->Pos_Y+temp4->Height-1)) - return temp4->Number; + if ((Input_sticky_control == 0 || Input_sticky_control == temp4->Number) + && Window_click_in_rectangle(temp4->Pos_X,temp4->Pos_Y,temp4->Pos_X+temp4->Width-1,temp4->Pos_Y+temp4->Height-1)) + { + Input_sticky_control = temp4->Number; + return temp4->Number; + } } - // Test du click sur une dropdown + // Test click on a dropdown box for (temp5=Window_dropdown_button_list; temp5; temp5=temp5->Next) { - if (Window_click_in_rectangle(temp5->Pos_X,temp5->Pos_Y,temp5->Pos_X+temp5->Width-1,temp5->Pos_Y+temp5->Height-1)) + if ((Input_sticky_control == 0 || Input_sticky_control == temp5->Number) + && Window_click_in_rectangle(temp5->Pos_X,temp5->Pos_Y,temp5->Pos_X+temp5->Width-1,temp5->Pos_Y+temp5->Height-1)) { + Input_sticky_control = temp5->Number; if (Mouse_K & temp5->Active_button) return Window_dropdown_on_click(temp5); else @@ -2440,7 +2610,25 @@ short Window_get_button_shortcut(void) temp=temp->Next; } } - + + // Handle arrow keys, end/home, and mouse wheel that have + // a certain behavior if a list control is present. + if (Window_list_button_list) + { + T_List_button *list = Window_list_button_list; + // If there's more than one of such control, only capture + // events if the mouse cursor is over it. + if (list->Next) + { + // to do + } + + + + + + + } return 0; } @@ -2450,31 +2638,275 @@ short Window_clicked_button(void) if(!Get_input())SDL_Delay(20); - // Gestion des clicks + // Handle clicks if (Mouse_K) { if ((Mouse_X=Window_pos_X+(Window_width*Menu_factor_X)) || (Mouse_Y>=Window_pos_Y+(Window_height*Menu_factor_Y))) - return -1; + { + if (Input_sticky_control == 0 || Input_sticky_control == -1) + { + Input_sticky_control = -1; + return -1; + } + else + { + return 0; + } + } + + if (!Input_sticky_control && Mouse_Y < Window_pos_Y+(12*Menu_factor_Y)) + { + Move_window(Mouse_X-Window_pos_X,Mouse_Y-Window_pos_Y); + } else { - if (Mouse_Y < Window_pos_Y+(12*Menu_factor_Y)) - Move_window(Mouse_X-Window_pos_X,Mouse_Y-Window_pos_Y); - else - return Window_get_clicked_button(); + short clicked_button; + T_List_button * list; + + // Check which controls was clicked (by rectangular area) + clicked_button = Window_get_clicked_button(); + + // Check if it's part of a list control + for (list=Window_list_button_list; list!=NULL; list=list->Next) + { + if (list->Entry_button->Number == clicked_button) + { + // Click in the textual part of a list. + short clicked_line; + clicked_line = (((Mouse_Y-Window_pos_Y)/Menu_factor_Y)-list->Entry_button->Pos_Y)>>3; + if (clicked_line == list->Cursor_position || // Same as before + clicked_line >= list->Scroller->Nb_elements) // Below last line + return 0; + + Hide_cursor(); + // Redraw one item as disabled + if (list->Cursor_position>=0 && list->Cursor_positionScroller->Nb_visibles) + list->Draw_list_item( + list->Entry_button->Pos_X, + list->Entry_button->Pos_Y + list->Cursor_position * 8, + list->List_start + list->Cursor_position, + 0); + list->Cursor_position = clicked_line; + // Redraw one item as enabled + if (list->Cursor_position>=0 && list->Cursor_positionScroller->Nb_visibles) + list->Draw_list_item( + list->Entry_button->Pos_X, + list->Entry_button->Pos_Y + list->Cursor_position * 8, + list->List_start + list->Cursor_position, + 1); + Display_cursor(); + + // Store the selected value as attribute2 + Window_attribute2=list->List_start + list->Cursor_position; + // Return the control ID of the list. + return list->Number; + } + else if (list->Scroller->Number == clicked_button) + { + // Click in the scroller part of a list + if (list->List_start == list->Scroller->Position) + return 0; // Didn't actually move + // Update scroller indices + list->Cursor_position += list->List_start; + list->List_start = list->Scroller->Position; + list->Cursor_position -= list->List_start; + // Need to redraw all + Hide_cursor(); + Window_redraw_list(list); + Display_cursor(); + } + } + return clicked_button; } } - // Gestion des touches + // Intercept keys if (Key) { + T_List_button * list; + Button=Window_get_button_shortcut(); if (Button) { Key=0; return Button; } + // Check if there's a list control and the keys can control it + for (list=Window_list_button_list; list!=NULL; list=list->Next) + { + // FIXME: Make only one list have the keyboard focus. + if (1) + { + if (Key==SDLK_UP && (list->Cursor_position+list->List_start)>0) + { + Key=0; + Hide_cursor(); + list->Cursor_position--; + if (list->Cursor_position<0) + { + list->List_start=list->List_start+list->Cursor_position; + list->Cursor_position=0; + // Mise à jour du scroller + list->Scroller->Position=list->List_start; + Window_draw_slider(list->Scroller); + } + Window_redraw_list(list); + Display_cursor(); + // Store the selected value as attribute2 + Window_attribute2=list->List_start + list->Cursor_position; + // Return the control ID of the list. + return list->Number; + } + if (Key==SDLK_DOWN && (list->Cursor_position+list->List_start)<(list->Scroller->Nb_elements-1)) + { + Key=0; + Hide_cursor(); + list->Cursor_position++; + if (list->Cursor_position>(list->Scroller->Nb_visibles-1)) + { + list->List_start=list->List_start+list->Cursor_position-(list->Scroller->Nb_visibles-1); + list->Cursor_position=(list->Scroller->Nb_visibles-1); + // Mise à jour du scroller + list->Scroller->Position=list->List_start; + Window_draw_slider(list->Scroller); + } + Window_redraw_list(list); + Display_cursor(); + // Store the selected value as attribute2 + Window_attribute2=list->List_start + list->Cursor_position; + // Return the control ID of the list. + return list->Number; + } + if (Key==SDLK_HOME && (list->Cursor_position!=0 || list->List_start!=0)) + { + Key=0; + Hide_cursor(); + list->Cursor_position=0; + list->List_start=0; + // Mise à jour du scroller + list->Scroller->Position=list->List_start; + Window_draw_slider(list->Scroller); + Window_redraw_list(list); + Display_cursor(); + // Store the selected value as attribute2 + Window_attribute2=list->List_start + list->Cursor_position; + // Return the control ID of the list. + return list->Number; + } + if (Key==SDLK_END && (list->Cursor_position+list->List_start)<(list->Scroller->Nb_elements-1)) + { + Key=0; + Hide_cursor(); + list->Cursor_position=(list->Scroller->Nb_elements-1)-list->List_start; + if (list->Cursor_position>(list->Scroller->Nb_visibles-1)) + { + list->List_start=list->List_start+list->Cursor_position-(list->Scroller->Nb_visibles-1); + list->Cursor_position=(list->Scroller->Nb_visibles-1); + // Mise à jour du scroller + list->Scroller->Position=list->List_start; + Window_draw_slider(list->Scroller); + } + Window_redraw_list(list); + Display_cursor(); + // Store the selected value as attribute2 + Window_attribute2=list->List_start + list->Cursor_position; + // Return the control ID of the list. + return list->Number; + } + if (Key==SDLK_PAGEDOWN && (list->Cursor_position+list->List_start)<(list->Scroller->Nb_elements-1)) + { + Key=0; + Hide_cursor(); + if (list->Scroller->Nb_elementsScroller->Nb_visibles) + { + list->Cursor_position=list->Scroller->Nb_elements-1; + } + else if(list->Cursor_position!=list->Scroller->Nb_visibles-1) + { + list->Cursor_position=list->Scroller->Nb_visibles-1; + } + else + { + list->List_start+=list->Scroller->Nb_visibles; + if (list->List_start+list->Scroller->Nb_visibles>list->Scroller->Nb_elements) + { + list->List_start=list->Scroller->Nb_elements-list->Scroller->Nb_visibles; + } + // Mise à jour du scroller + list->Scroller->Position=list->List_start; + Window_draw_slider(list->Scroller); + } + Window_redraw_list(list); + Display_cursor(); + // Store the selected value as attribute2 + Window_attribute2=list->List_start + list->Cursor_position; + // Return the control ID of the list. + return list->Number; + } + if (Key==SDLK_PAGEUP && (list->Cursor_position+list->List_start)>0) + { + Key=0; + Hide_cursor(); + if(list->Cursor_position!=0) + { + list->Cursor_position=0; + } + else + { + list->List_start-=list->Scroller->Nb_visibles; + if (list->List_start<0) + { + list->List_start=0; + } + // Mise à jour du scroller + list->Scroller->Position=list->List_start; + Window_draw_slider(list->Scroller); + } + Window_redraw_list(list); + Display_cursor(); + // Store the selected value as attribute2 + Window_attribute2=list->List_start + list->Cursor_position; + // Return the control ID of the list. + return list->Number; + } + if (Key == KEY_MOUSEWHEELUP && list->List_start>0) + { + list->Cursor_position+=list->List_start; + if (list->List_start>=3) + list->List_start-=3; + else + list->List_start=0; + list->Cursor_position-=list->List_start; + // On affiche à nouveau la liste + Hide_cursor(); + Window_redraw_list(list); + // Mise à jour du scroller + list->Scroller->Position=list->List_start; + Window_draw_slider(list->Scroller); + Display_cursor(); + } + if (Key==KEY_MOUSEWHEELDOWN && list->List_startScroller->Nb_elements-list->Scroller->Nb_visibles) + { + list->Cursor_position+=list->List_start; + list->List_start+=3; + if (list->List_start+list->Scroller->Nb_visibles>list->Scroller->Nb_elements) + { + list->List_start=list->Scroller->Nb_elements-list->Scroller->Nb_visibles; + } + list->Cursor_position-=list->List_start; + // On affiche à nouveau la liste + Hide_cursor(); + Window_redraw_list(list); + // Mise à jour du scroller + list->Scroller->Position=list->List_start; + Window_draw_slider(list->Scroller); + Display_cursor(); + } + + } + } } return 0; diff --git a/engine.h b/engine.h index 855c361a..e3de8d0f 100644 --- a/engine.h +++ b/engine.h @@ -1,80 +1,94 @@ -/* Grafx2 - The Ultimate 256-color bitmap paint program - - Copyright 2007 Adrien Destugues - Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) - - Grafx2 is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; version 2 - of the License. - - Grafx2 is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Grafx2; if not, see -*/ - -////////////////////////////////////////////////////////////////////////////// -///@file engine.h -/// Utility functions for the menu and all windows. -////////////////////////////////////////////////////////////////////////////// - -void Main_handler (void); -void Draw_menu_button_frame(byte btn_number,byte pressed); -void Unselect_button (int btn_number); -void Select_button (int btn_number,byte click); -void Open_window (word width,word height, char * title); -void Close_window (void); - -void Open_popup (word x_pos, word y_pos, word width, word height); -void Close_popup (void); - -void Window_draw_normal_bouton(word x_pos,word y_pos,word width,word height, - char * title,byte undersc_letter,byte clickable); -void Window_select_normal_button(word x_pos,word y_pos,word width,word height); -void Window_unselect_normal_button(word x_pos,word y_pos,word width,word height); -void Window_draw_palette_bouton(word x_pos,word y_pos); - -void Compute_slider_cursor_height(T_Scroller_button * button); -void Window_draw_slider(T_Scroller_button * button); -void Window_draw_scroller_bouton(T_Scroller_button * button); - -void Window_input_content(T_Special_button * button, char * content); -void Window_clear_input_button(T_Special_button * button); -void Window_draw_input_bouton(word x_pos,word y_pos,word width_in_characters); - -T_Normal_button * Window_set_normal_button(word x_pos, word y_pos, - word width, word height, - char * title,byte undersc_letter, - byte clickable, word shortcut); -T_Normal_button * Window_set_repeatable_button(word x_pos, word y_pos, - word width, word height, - char * title,byte undersc_letter, - byte clickable, word shortcut); - -T_Palette_button * Window_set_palette_button(word x_pos, word y_pos); -void Window_clear_tags(void); -void Tag_color_range(byte start,byte end); - -T_Scroller_button * Window_set_scroller_button(word x_pos, word y_pos, - word height, - word nb_elements, - word nb_elements_visible, - word initial_position); -T_Special_button * Window_set_special_button(word x_pos,word y_pos,word width,word height); -T_Special_button * Window_set_input_button(word x_pos,word y_pos,word width_in_characters); -T_Dropdown_button * Window_set_dropdown_button(word x_pos,word y_pos,word width,word height,word dropdown_width,const char *label,byte display_choice,byte display_centered,byte display_arrow,byte active_button); -void Window_dropdown_add_item(T_Dropdown_button * dropdown, word btn_number, const char *label); -void Window_dropdown_clear_items(T_Dropdown_button * dropdown); -byte Window_click_in_rectangle(short start_x,short start_y,short end_x,short end_y); -short Wait_click_in_palette(T_Palette_button * button); -void Get_color_behind_window(byte * color, byte * click); - -short Window_clicked_button(void); -int Button_under_mouse(void); -short Window_get_clicked_button(void); -void Remap_window_backgrounds(byte * conversion_table, int Min_Y, int Max_Y); -void Pixel_background(int x_pos, int y_pos, byte color); +/* Grafx2 - The Ultimate 256-color bitmap paint program + + Copyright 2007 Adrien Destugues + Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) + + Grafx2 is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 + of the License. + + Grafx2 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grafx2; if not, see +*/ + +////////////////////////////////////////////////////////////////////////////// +///@file engine.h +/// Utility functions for the menu and all windows. +////////////////////////////////////////////////////////////////////////////// + +#ifndef __ENGINE_H__ +#define __ENGINE_H__ + +#include "struct.h" + +void Main_handler (void); +void Draw_menu_button_frame(byte btn_number,byte pressed); +void Unselect_button (int btn_number); +void Select_button (int btn_number,byte click); +void Open_window (word width,word height, char * title); +void Close_window (void); + +void Open_popup (word x_pos, word y_pos, word width, word height); +void Close_popup (void); + +void Window_draw_normal_bouton(word x_pos,word y_pos,word width,word height, + char * title,byte undersc_letter,byte clickable); +void Window_select_normal_button(word x_pos,word y_pos,word width,word height); +void Window_unselect_normal_button(word x_pos,word y_pos,word width,word height); +void Window_draw_palette_bouton(word x_pos,word y_pos); + +void Compute_slider_cursor_height(T_Scroller_button * button); +void Window_draw_slider(T_Scroller_button * button); +void Window_draw_scroller_bouton(T_Scroller_button * button); + +void Window_input_content(T_Special_button * button, char * content); +void Window_clear_input_button(T_Special_button * button); +void Window_draw_input_bouton(word x_pos,word y_pos,word width_in_characters); + +T_Normal_button * Window_set_normal_button(word x_pos, word y_pos, + word width, word height, + char * title,byte undersc_letter, + byte clickable, word shortcut); +T_Normal_button * Window_set_repeatable_button(word x_pos, word y_pos, + word width, word height, + char * title,byte undersc_letter, + byte clickable, word shortcut); + +T_Palette_button * Window_set_palette_button(word x_pos, word y_pos); +void Window_clear_tags(void); +void Tag_color_range(byte start,byte end); + +T_Scroller_button * Window_set_scroller_button(word x_pos, word y_pos, + word height, word nb_elements, word nb_elements_visible, + word initial_position); +T_Special_button * Window_set_special_button(word x_pos,word y_pos,word width, + word height); +T_Special_button * Window_set_input_button(word x_pos,word y_pos, + word width_in_characters); +T_Dropdown_button * Window_set_dropdown_button(word x_pos,word y_pos,word width, + word height,word dropdown_width,const char *label,byte display_choice, + byte display_centered,byte display_arrow,byte active_button); +void Window_dropdown_add_item(T_Dropdown_button * dropdown, word btn_number, + const char *label); +void Window_dropdown_clear_items(T_Dropdown_button * dropdown); +T_List_button * Window_set_list_button(T_Special_button * entry_button, + T_Scroller_button * scroller, Func_draw_list_item draw_list_item); +void Window_redraw_list(T_List_button * list); +byte Window_click_in_rectangle(short start_x,short start_y,short end_x, + short end_y); +short Wait_click_in_palette(T_Palette_button * button); +void Get_color_behind_window(byte * color, byte * click); + +short Window_clicked_button(void); +int Button_under_mouse(void); +short Window_get_clicked_button(void); +void Remap_window_backgrounds(byte * conversion_table, int Min_Y, int Max_Y); +void Pixel_background(int x_pos, int y_pos, byte color); + +#endif diff --git a/filesel.c b/filesel.c index aaafba87..4f2ed269 100644 --- a/filesel.c +++ b/filesel.c @@ -64,14 +64,58 @@ #define SELECTED_DIRECTORY_COLOR MC_Light // color du texte pour une ligne de repértoire sélectionnée #define SELECTED_BACKGROUND_COLOR MC_Dark // color du fond pour une ligne sélectionnée +// -- Fileselector data + +T_Fileselector Filelist; + // Conventions: // // * Le fileselect modifie le répertoire courant. Ceci permet de n'avoir // qu'un findfirst dans le répertoire courant à faire: +void Recount_files(T_Fileselector *list) +{ + T_Fileselector_item *item; + + list->Nb_files=0; + list->Nb_directories=0; + list->Nb_elements=0; + + for (item = list->First; item != NULL; item = item->Next) + { + if (item->Type == 0) + list->Nb_files ++; + else + list->Nb_directories ++; + list->Nb_elements ++; + } + + if (list->Index) + { + free(list->Index); + list->Index = NULL; + } + + if (list->Nb_elements>0) + { + int i; + + list->Index = (T_Fileselector_item **) malloc(list->Nb_elements * sizeof(T_Fileselector_item **)); + if (list->Index) + { + // Fill the index + for (item = list->First, i=0; item != NULL; item = item->Next, i++) + { + list->Index[i] = item; + } + } + // If the malloc failed, we're probably in trouble, but I don't know + // how to recover from that..I'll just make the index bulletproof. + } +} -// -- Déstruction de la liste chaînée --------------------------------------- -void Free_fileselector_list(void) +// -- Destruction de la liste chaînée --------------------------------------- +void Free_fileselector_list(T_Fileselector *list) // Cette procédure détruit la chaine des fichiers. Elle doit être appelée // avant de rappeler la fonction Read_list_of_files, ainsi qu'en fin de // programme. @@ -79,23 +123,19 @@ void Free_fileselector_list(void) // Pointeur temporaire de destruction T_Fileselector_item * temp_item; - while (Filelist!=NULL) + while (list->First!=NULL) { // On mémorise l'adresse du premier élément de la liste - temp_item =Filelist; + temp_item =list->First; // On fait avancer la tête de la liste - Filelist=Filelist->Next; + list->First=list->First->Next; // Et on efface l'ancien premier élément de la liste free(temp_item); } + Recount_files(list); } - -/// -/// Formats a display name for a file, directory, or similar name (drive, volume). -/// The returned value is a pointer to a single static buffer of 19 characters -/// including the '\0'. -char * Format_filename(char * fname, int type) +char * Format_filename(const char * fname, int type) { static char result[19]; int c; @@ -148,7 +188,7 @@ char * Format_filename(char * fname, int type) // -- Rajouter a la liste des elements de la liste un element --------------- -void Add_element_to_list(char * fname, int type) +void Add_element_to_list(T_Fileselector *list, const char * fname, int type) // Cette procedure ajoute a la liste chainee un fichier passé en argument. { // Pointeur temporaire d'insertion @@ -162,12 +202,12 @@ void Add_element_to_list(char * fname, int type) strcpy(temp_item->Full_name,fname); temp_item->Type = type; - temp_item->Next =Filelist; + temp_item->Next =list->First; temp_item->Previous=NULL; - if (Filelist!=NULL) - Filelist->Previous=temp_item; - Filelist=temp_item; + if (list->First!=NULL) + list->First->Previous=temp_item; + list->First=temp_item; } // -- Vérification si un fichier a l'extension demandée. @@ -203,11 +243,11 @@ int Check_extension(const char *filename, char * filter) // -- Lecture d'une liste de fichiers --------------------------------------- -void Read_list_of_files(byte selected_format) +void Read_list_of_files(T_Fileselector *list, byte selected_format) // Cette procédure charge dans la liste chainée les fichiers dont l'extension // correspond au format demandé. { - DIR* Repertoire_Courant; //Répertoire courant + DIR* current_directory; //Répertoire courant struct dirent* entry; // Structure de lecture des éléments char * filter = "*"; // Extension demandée struct stat Infos_enreg; @@ -218,15 +258,13 @@ void Read_list_of_files(byte selected_format) filter = File_formats[selected_format-1].Extension; // Ensuite, on vide la liste actuelle: - Free_fileselector_list(); + Free_fileselector_list(list); // Après effacement, il ne reste ni fichier ni répertoire dans la liste - Filelist_nb_files=0; - Filelist_nb_directories=0; // On lit tous les répertoires: current_path=getcwd(NULL,0); - Repertoire_Courant=opendir(current_path); - while ((entry=readdir(Repertoire_Courant))) + current_directory=opendir(current_path); + while ((entry=readdir(current_directory))) { // On ignore le répertoire courant if ( !strcmp(entry->d_name, ".")) @@ -243,8 +281,8 @@ void Read_list_of_files(byte selected_format) !isHidden(entry))) { // On rajoute le répertoire à la liste - Add_element_to_list(entry->d_name, 1); - Filelist_nb_directories++; + Add_element_to_list(list, entry->d_name, 1); + list->Nb_directories++; } else if (S_ISREG(Infos_enreg.st_mode) && //Il s'agit d'un fichier (Config.Show_hidden_files || //Il n'est pas caché @@ -253,21 +291,21 @@ void Read_list_of_files(byte selected_format) if (Check_extension(entry->d_name, filter)) { // On rajoute le fichier à la liste - Add_element_to_list(entry->d_name, 0); - Filelist_nb_files++; + Add_element_to_list(list, entry->d_name, 0); + list->Nb_files++; } } } #if defined(__MORPHOS__) || defined(__AROS__) || defined (__amigaos4__) || defined(__amigaos__) - Add_element_to_list("/",1); // on amiga systems, / means parent. And there is no .. - Filelist_nb_directories ++; + Add_element_to_list(list, "/",1); // on amiga systems, / means parent. And there is no .. + list->Nb_directories ++; #endif - closedir(Repertoire_Courant); + closedir(current_directory); free(current_path); - Filelist_nb_elements=Filelist_nb_directories+Filelist_nb_files; + Recount_files(list); } #if defined(__amigaos4__) || defined(__AROS__) || defined(__MORPHOS__) || defined(__amigaos__) @@ -290,14 +328,14 @@ void bstrtostr( BSTR in, STRPTR out, TEXT max ) #endif // -- Lecture d'une liste de lecteurs / volumes ----------------------------- -void Read_list_of_drives(void) +void Read_list_of_drives(T_Fileselector *list) { // Empty the current content of fileselector: - Free_fileselector_list(); + Free_fileselector_list(list); // Reset number of items - Filelist_nb_files=0; - Filelist_nb_directories=0; + list->Nb_files=0; + list->Nb_directories=0; #if defined(__amigaos4__) || defined(__AROS__) || defined(__MORPHOS__) || defined(__amigaos__) { @@ -311,8 +349,8 @@ void Read_list_of_drives(void) { bstrtostr( dl->dol_Name, tmp, 254 ); strcat( tmp, ":" ); - Add_element_to_list( tmp, 2 ); - Filelist_nb_directories++; + Add_element_to_list(list, tmp, 2 ); + list->Nb_directories++; } UnLockDosList( LDF_VOLUMES | LDF_READ ); } @@ -354,8 +392,8 @@ void Read_list_of_drives(void) break; } drive_name[0]='A'+bit_index; - Add_element_to_list(drive_name,2); - Filelist_nb_directories++; + Add_element_to_list(list, drive_name,2); + list->Nb_directories++; drive_index++; } } @@ -368,7 +406,7 @@ void Read_list_of_drives(void) // Ensuite on utilise read_file_system_list pour compléter - struct mount_entry* Liste_points_montage; + struct mount_entry* mount_points_list; struct mount_entry* next; #if defined(__BEOS__) || defined(__HAIKU__) @@ -376,42 +414,42 @@ void Read_list_of_drives(void) #else char * home_dir = getenv("HOME"); #endif - Add_element_to_list("/", 2); - Filelist_nb_directories++; + Add_element_to_list(list, "/", 2); + list->Nb_directories++; if(home_dir) { - Add_element_to_list(home_dir, 2); - Filelist_nb_directories++; + Add_element_to_list(list, home_dir, 2); + list->Nb_directories++; } - Liste_points_montage = read_file_system_list(0); + mount_points_list = read_file_system_list(0); - while(Liste_points_montage != NULL) + while(mount_points_list != NULL) { - if(Liste_points_montage->me_dummy == 0 && strcmp(Liste_points_montage->me_mountdir,"/") && strcmp(Liste_points_montage->me_mountdir,"/home")) + if(mount_points_list->me_dummy == 0 && strcmp(mount_points_list->me_mountdir,"/") && strcmp(mount_points_list->me_mountdir,"/home")) { - Add_element_to_list(Liste_points_montage->me_mountdir,2); - Filelist_nb_directories++; + Add_element_to_list(list, mount_points_list->me_mountdir,2); + list->Nb_directories++; } - next = Liste_points_montage -> me_next; + next = mount_points_list -> me_next; #if !(defined(__macosx__) || defined(__FreeBSD__)) - free(Liste_points_montage -> me_type); + free(mount_points_list -> me_type); #endif - free(Liste_points_montage -> me_devname); - free(Liste_points_montage -> me_mountdir); - free(Liste_points_montage); - Liste_points_montage = next; + free(mount_points_list -> me_devname); + free(mount_points_list -> me_mountdir); + free(mount_points_list); + mount_points_list = next; } } #endif - Filelist_nb_elements=Filelist_nb_directories+Filelist_nb_files; + Recount_files(list); } // -- Tri de la liste des fichiers et répertoires --------------------------- -void Sort_list_of_files(void) +void Sort_list_of_files(T_Fileselector *list) // Tri la liste chainée existante dans l'ordre suivant: // // * Les répertoires d'abord, dans l'ordre alphabétique de leur nom @@ -424,16 +462,15 @@ void Sort_list_of_files(void) T_Fileselector_item * next_item; T_Fileselector_item * next_to_next_item; - // Avant de trier quoi que ce soit, on vérifie qu'il y ait suffisamment - // d'éléments pour qu'il soit possibles qu'ils soient en désordre: - if (Filelist_nb_elements>1) + // Check there are at least two elements before sorting + if (list->First && list->First->Next) { do { // Par défaut, on considère que la liste est triée list_is_sorted=1; - current_item=Filelist; + current_item=list->First; next_item=current_item->Next; while ( (current_item!=NULL) && (next_item!=NULL) ) @@ -478,8 +515,8 @@ void Sort_list_of_files(void) next_to_next_item->Previous=current_item; // On fait bien attention à modifier la tête de liste en cas de besoin - if (current_item==Filelist) - Filelist=next_item; + if (current_item==list->First) + list->First=next_item; // Ensuite, on se prépare à étudier les éléments précédents: current_item=prev_item; @@ -499,11 +536,38 @@ void Sort_list_of_files(void) } while (!list_is_sorted); } + // Force a recount / re-index + Recount_files(list); +} + +T_Fileselector_item * Get_item_by_index(T_Fileselector *list, short index) +{ + // Safety + if (index >= list->Nb_elements) + index=list->Nb_elements-1; + + if (list->Index) + { + return list->Index[index]; + } + else + { + // Index not available. + // Can only happen in case of malloc error. + // Fall back anyway on iterative search + + T_Fileselector_item * item = list->First; + for (;index>0;index--) + item = item->Next; + + return item; + } + } // -- Affichage des éléments de la liste de fichier / répertoire ------------ -void Display_file_list(short offset_first,short selector_offset) +void Display_file_list(T_Fileselector *list, short offset_first,short selector_offset) // // offset_first = Décalage entre le premier fichier visible dans le // sélecteur et le premier fichier de la liste @@ -519,12 +583,10 @@ void Display_file_list(short offset_first,short selector_offset) // On vérifie s'il y a au moins 1 fichier dans la liste: - if (Filelist_nb_elements>0) + if (list->Nb_elements>0) { // On commence par chercher à pointer sur le premier fichier visible: - current_item=Filelist; - for (;offset_first>0;offset_first--) - current_item=current_item->Next; + current_item = Get_item_by_index(list, offset_first); // Pour chacun des 10 éléments inscriptibles à l'écran for (index=0;index<10;index++) @@ -566,7 +628,7 @@ void Display_file_list(short offset_first,short selector_offset) // -- Récupérer le libellé d'un élément de la liste ------------------------- -void Get_selected_item(short offset_first,short selector_offset,char * label,int *type) +void Get_selected_item(T_Fileselector *list, short offset_first,short selector_offset,char * label,int *type) // // offset_first = Décalage entre le premier fichier visible dans le // sélecteur et le premier fichier de la liste @@ -582,13 +644,11 @@ void Get_selected_item(short offset_first,short selector_offset,char * label,int T_Fileselector_item * current_item; // On vérifie s'il y a au moins 1 fichier dans la liste: - if (Filelist_nb_elements>0) + if (list->Nb_elements>0) { - int i; - - current_item=Filelist; - for (i=0; iNext; + // On commence par chercher à pointer sur le premier fichier visible: + // Ensuite, on saute autant d'éléments que le décalage demandé: + current_item = Get_item_by_index(list, offset_first + selector_offset); // On recopie la chaîne strcpy(label, current_item->Full_name); @@ -605,12 +665,12 @@ void Selector_scroll_down(short * offset_first,short * selector_offset) // Fait scroller vers le bas le sélecteur de fichier... (si possible) { if ( ((*selector_offset)<9) - && ( (*selector_offset)+1 < Filelist_nb_elements ) ) + && ( (*selector_offset)+1 < Filelist.Nb_elements ) ) // Si la sélection peut descendre - Display_file_list(*offset_first,++(*selector_offset)); + Display_file_list(&Filelist, *offset_first,++(*selector_offset)); else // Sinon, descendre la fenêtre (si possible) - if ((*offset_first)+100) // Si la sélection peut monter - Display_file_list(*offset_first,--(*selector_offset)); + Display_file_list(&Filelist, *offset_first,--(*selector_offset)); else // Sinon, monter la fenêtre (si possible) if ((*offset_first)>0) - Display_file_list(--(*offset_first),*selector_offset); + Display_file_list(&Filelist, --(*offset_first),*selector_offset); } void Selector_page_down(short * offset_first,short * selector_offset, short lines) { - if (Filelist_nb_elements-1>*offset_first+*selector_offset) + if (Filelist.Nb_elements-1>*offset_first+*selector_offset) { if (*selector_offset<9) { - if (Filelist_nb_elements<10) + if (Filelist.Nb_elements<10) { *offset_first=0; - *selector_offset=Filelist_nb_elements-1; + *selector_offset=Filelist.Nb_elements-1; } else *selector_offset=9; } else { - if (Filelist_nb_elements>*offset_first+18) + if (Filelist.Nb_elements>*offset_first+18) *offset_first+=lines; else { - *offset_first=Filelist_nb_elements-10; + *offset_first=Filelist.Nb_elements-10; *selector_offset=9; } } } - Display_file_list(*offset_first,*selector_offset); + Display_file_list(&Filelist, *offset_first,*selector_offset); } @@ -668,29 +728,29 @@ void Selector_page_up(short * offset_first,short * selector_offset, short lines) *offset_first=0; } } - Display_file_list(*offset_first,*selector_offset); + Display_file_list(&Filelist, *offset_first,*selector_offset); } void Selector_end(short * offset_first,short * selector_offset) { - if (Filelist_nb_elements<10) + if (Filelist.Nb_elements<10) { *offset_first=0; - *selector_offset=Filelist_nb_elements-1; + *selector_offset=Filelist.Nb_elements-1; } else { - *offset_first=Filelist_nb_elements-10; + *offset_first=Filelist.Nb_elements-10; *selector_offset=9; } - Display_file_list(*offset_first,*selector_offset); + Display_file_list(&Filelist, *offset_first,*selector_offset); } void Selector_home(short * offset_first,short * selector_offset) { - Display_file_list((*offset_first)=0,(*selector_offset)=0); + Display_file_list(&Filelist, (*offset_first)=0,(*selector_offset)=0); } @@ -705,8 +765,8 @@ short Compute_click_offset_in_fileselector(void) short computed_offset; computed_offset=(((Mouse_Y-Window_pos_Y)/Menu_factor_Y)-95)>>3; - if (computed_offset>=Filelist_nb_elements) - computed_offset=Filelist_nb_elements-1; + if (computed_offset>=Filelist.Nb_elements) + computed_offset=Filelist.Nb_elements-1; return computed_offset; } @@ -800,22 +860,21 @@ void Print_filename_in_fileselector(void) int Selected_type; // Utilisé pour mémoriser le type d'entrée choisi // dans le selecteur de fichier. -void Prepare_and_display_filelist(short Position, short offset, - T_Scroller_button * button) +void Prepare_and_display_filelist(short Position, short offset, T_Scroller_button * button) { - button->Nb_elements=Filelist_nb_elements; + button->Nb_elements=Filelist.Nb_elements; button->Position=Position; Compute_slider_cursor_height(button); Window_draw_slider(button); // On efface les anciens noms de fichier: Window_rectangle(8-1,95-1,144+2,80+2,MC_Black); // On affiche les nouveaux: - Display_file_list(Position,offset); + Display_file_list(&Filelist, Position,offset); Update_window_area(8-1,95-1,144+2,80+2); // On récupère le nom du schmilblick à "accéder" - Get_selected_item(Position,offset,Main_filename,&Selected_type); + Get_selected_item(&Filelist, Position,offset,Main_filename,&Selected_type); // On affiche le nouveau nom de fichier Print_filename_in_fileselector(); // On affiche le nom du répertoire courant @@ -825,8 +884,8 @@ void Prepare_and_display_filelist(short Position, short offset, void Reload_list_of_files(byte filter, T_Scroller_button * button) { - Read_list_of_files(filter); - Sort_list_of_files(); + Read_list_of_files(&Filelist, filter); + Sort_list_of_files(&Filelist); // // Check and fix the fileselector positions, because // the directory content may have changed. @@ -834,20 +893,20 @@ void Reload_list_of_files(byte filter, T_Scroller_button * button) // Make the offset absolute Main_fileselector_offset += Main_fileselector_position; // Ensure it's within limits - if (Main_fileselector_offset >= Filelist_nb_elements) + if (Main_fileselector_offset >= Filelist.Nb_elements) { - Main_fileselector_offset = Filelist_nb_elements-1; + Main_fileselector_offset = Filelist.Nb_elements-1; } // Ensure the position doesn't show "too many files" - if (Main_fileselector_position!=0 && Main_fileselector_position>(Filelist_nb_elements-10)) + if (Main_fileselector_position!=0 && Main_fileselector_position>(Filelist.Nb_elements-10)) { - if (Filelist_nb_elements<10) + if (Filelist.Nb_elements<10) { Main_fileselector_position=0; } else { - Main_fileselector_position=Filelist_nb_elements-10; + Main_fileselector_position=Filelist.Nb_elements-10; } } // Restore the offset as relative to the position. @@ -870,7 +929,7 @@ void Scroll_fileselector(T_Scroller_button * file_scroller) Window_draw_slider(file_scroller); } // On récupére le nom du schmilblick à "accéder" - Get_selected_item(Main_fileselector_position,Main_fileselector_offset,Main_filename,&Selected_type); + Get_selected_item(&Filelist, Main_fileselector_position,Main_fileselector_offset,Main_filename,&Selected_type); if (strcmp(old_filename,Main_filename)) New_preview_is_needed=1; @@ -880,12 +939,12 @@ void Scroll_fileselector(T_Scroller_button * file_scroller) } -short Find_file_in_fileselector(char * fname) +short Find_file_in_fileselector(T_Fileselector *list, char * fname) { T_Fileselector_item * current_item; short index; - for (index=0, current_item=Filelist; + for (index=0, current_item=list->First; ((current_item!=NULL) && (strcmp(current_item->Full_name,fname))); index++,current_item=current_item->Next); @@ -897,18 +956,18 @@ void Highlight_file(char * fname) { short index; - index=Find_file_in_fileselector(fname); + index=Find_file_in_fileselector(&Filelist, fname); - if ((Filelist_nb_elements<=10) || (index<5)) + if ((Filelist.Nb_elements<=10) || (index<5)) { Main_fileselector_position=0; Main_fileselector_offset=index; } else { - if (index>=Filelist_nb_elements-5) + if (index>=Filelist.Nb_elements-5) { - Main_fileselector_position=Filelist_nb_elements-10; + Main_fileselector_position=Filelist.Nb_elements-10; Main_fileselector_offset=index-Main_fileselector_position; } else @@ -920,18 +979,16 @@ void Highlight_file(char * fname) } -char FFF_best_name[MAX_PATH_CHARACTERS]; -char * Find_filename_match(char * fname) +char * Find_filename_match(T_Fileselector *list, char * fname) { char * best_name_ptr; T_Fileselector_item * current_item; byte matching_letters=0; byte counter; - strcpy(FFF_best_name,Main_filename); best_name_ptr=NULL; - for (current_item=Filelist; current_item!=NULL; current_item=current_item->Next) + for (current_item=list->First; current_item!=NULL; current_item=current_item->Next) { if ( (!Config.Find_file_fast) || (Config.Find_file_fast==(current_item->Type+1)) ) @@ -941,7 +998,6 @@ char * Find_filename_match(char * fname) if (counter>matching_letters) { matching_letters=counter; - strcpy(FFF_best_name,current_item->Full_name); best_name_ptr=current_item->Full_name; } } @@ -974,6 +1030,12 @@ byte Button_Load_or_Save(byte load, byte image) char quicksearch_filename[MAX_PATH_CHARACTERS]=""; char save_filename[MAX_PATH_CHARACTERS]; char * most_matching_filename; + short window_shortcut; + + if (image) + window_shortcut = load?(0x100+BUTTON_LOAD):(0x100+BUTTON_SAVE); + else + window_shortcut = load?SPECIAL_LOAD_BRUSH:SPECIAL_SAVE_BRUSH; initial_palette=(T_Components *)malloc(sizeof(T_Palette)); memcpy(initial_palette,Main_palette,sizeof(T_Palette)); @@ -1140,12 +1202,12 @@ byte Button_Load_or_Save(byte load, byte image) break; case 3 : // Delete - if (Filelist_nb_elements && (*Main_filename!='.') && Selected_type!=2) + if (Filelist.Nb_elements && (*Main_filename!='.') && Selected_type!=2) { char * message; Hide_cursor(); // On affiche une demande de confirmation - if (Main_fileselector_position+Main_fileselector_offset>=Filelist_nb_directories) + if (Main_fileselector_position+Main_fileselector_offset>=Filelist.Nb_directories) { message="Delete file ?"; } @@ -1156,7 +1218,7 @@ byte Button_Load_or_Save(byte load, byte image) if (Confirmation_box(message)) { // Si c'est un fichier - if (Main_fileselector_position+Main_fileselector_offset>=Filelist_nb_directories) + if (Main_fileselector_position+Main_fileselector_offset>=Filelist.Nb_directories) // On efface le fichier (si on peut) temp=(!remove(Main_filename)); else // Si c'est un repertoire @@ -1166,7 +1228,7 @@ byte Button_Load_or_Save(byte load, byte image) if (temp) // temp indique si l'effacement s'est bien passé { // On remonte si c'était le dernier élément de la liste - if (Main_fileselector_position+Main_fileselector_offset==Filelist_nb_elements-1) + if (Main_fileselector_position+Main_fileselector_offset==Filelist.Nb_elements-1) { if (Main_fileselector_position) Main_fileselector_position--; @@ -1177,7 +1239,7 @@ byte Button_Load_or_Save(byte load, byte image) else // Si ce n'était pas le dernier, il faut faire gaffe à ce { // que ses copains d'en dessous ne remontent pas trop. if ( (Main_fileselector_position) - && (Main_fileselector_position+10==Filelist_nb_elements) ) + && (Main_fileselector_position+10==Filelist.Nb_elements) ) { Main_fileselector_position--; Main_fileselector_offset++; @@ -1214,11 +1276,11 @@ byte Button_Load_or_Save(byte load, byte image) Main_fileselector_offset=temp; // On récupére le nom du schmilblick à "accéder" - Get_selected_item(Main_fileselector_position,Main_fileselector_offset,Main_filename,&Selected_type); + Get_selected_item(&Filelist, Main_fileselector_position,Main_fileselector_offset,Main_filename,&Selected_type); // On affiche le nouveau nom de fichier Print_filename_in_fileselector(); // On affiche à nouveau la liste - Display_file_list(Main_fileselector_position,Main_fileselector_offset); + Display_file_list(&Filelist, Main_fileselector_position,Main_fileselector_offset); // On vient de changer de nom de fichier, donc on doit s'appreter // a rafficher une preview @@ -1231,8 +1293,8 @@ byte Button_Load_or_Save(byte load, byte image) // faut mettre le nom de fichier au nom du répertoire. Sinon, dans // certains cas, on risque de sauvegarder avec le nom du fichier // actuel au lieu de changer de répertoire. - if (Main_fileselector_position+Main_fileselector_offsetFull_name,PARENT_DIR)) + if (!strcmp(Filelist.First->Full_name,PARENT_DIR)) { // On va dans le répertoire parent. strcpy(Main_filename,PARENT_DIR); @@ -1494,7 +1556,7 @@ byte Button_Load_or_Save(byte load, byte image) } Key=0; break; - default: // Autre => On se place sur le nom de fichier qui correspond + default: if (clicked_button<=0) { if (Is_shortcut(Key,0x100+BUTTON_HELP)) @@ -1502,12 +1564,18 @@ byte Button_Load_or_Save(byte load, byte image) Window_help(load?BUTTON_LOAD:BUTTON_SAVE, NULL); break; } + if (Is_shortcut(Key,window_shortcut)) + { + clicked_button=2; + break; + } + // Autre => On se place sur le nom de fichier qui correspond temp=strlen(quicksearch_filename); if (Key_ANSI>= ' ' && Key_ANSI < 255 && temp<50) { quicksearch_filename[temp]=Key_ANSI; quicksearch_filename[temp+1]='\0'; - most_matching_filename=Find_filename_match(quicksearch_filename); + most_matching_filename=Find_filename_match(&Filelist, quicksearch_filename); if ( (most_matching_filename) ) { temp=Main_fileselector_position+Main_fileselector_offset; @@ -1552,8 +1620,8 @@ byte Button_Load_or_Save(byte load, byte image) getcwd(Main_current_directory,256); // On lit le nouveau répertoire - Read_list_of_files(Main_format); - Sort_list_of_files(); + Read_list_of_files(&Filelist, Main_format); + Sort_list_of_files(&Filelist); // On place la barre de sélection sur le répertoire d'où l'on vient Highlight_file(previous_directory); } @@ -1614,7 +1682,7 @@ byte Button_Load_or_Save(byte load, byte image) if (Timer_state==1) // Il faut afficher la preview { - if ( (Main_fileselector_position+Main_fileselector_offset>=Filelist_nb_directories) && (Filelist_nb_elements) ) + if ( (Main_fileselector_position+Main_fileselector_offset>=Filelist.Nb_directories) && (Filelist.Nb_elements) ) { strcpy(Main_file_directory,Main_current_directory); @@ -1661,7 +1729,7 @@ byte Button_Load_or_Save(byte load, byte image) Unselect_button((load)?BUTTON_LOAD:BUTTON_SAVE); Display_cursor(); - Free_fileselector_list(); + Free_fileselector_list(&Filelist); Pixel_load_function=Pixel_load_in_current_screen; diff --git a/filesel.h b/filesel.h index 783554f9..0ad4520a 100644 --- a/filesel.h +++ b/filesel.h @@ -1,25 +1,48 @@ -/* Grafx2 - The Ultimate 256-color bitmap paint program - - Copyright 2007 Adrien Destugues - Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) - - Grafx2 is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; version 2 - of the License. - - Grafx2 is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Grafx2; if not, see -*/ - -////////////////////////////////////////////////////////////////////////////// -///@file filesel.h -/// Fileselector window, used for loading and saving images and brushes. -////////////////////////////////////////////////////////////////////////////// - -byte Button_Load_or_Save(byte load, byte image); +/* Grafx2 - The Ultimate 256-color bitmap paint program + + Copyright 2007 Adrien Destugues + Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) + + Grafx2 is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 + of the License. + + Grafx2 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grafx2; if not, see +*/ + +////////////////////////////////////////////////////////////////////////////// +///@file filesel.h +/// Fileselector window, used for loading and saving images and brushes. +////////////////////////////////////////////////////////////////////////////// +#ifndef __FILESEL_H__ +#define __FILESEL_H__ + +#include "struct.h" + +byte Button_Load_or_Save(byte load, byte image); + +void Add_element_to_list(T_Fileselector *list, const char * fname, int type); +/// +/// Formats a display name for a file, directory, or similar name (drive, volume). +/// The returned value is a pointer to a single static buffer of 19 characters +/// including the '\0'. +char * Format_filename(const char * fname, int type); + +void Free_fileselector_list(T_Fileselector *list); + +void Sort_list_of_files(T_Fileselector *list); + +void Recount_files(T_Fileselector *list); + +T_Fileselector_item * Get_item_by_index(T_Fileselector *list, short index); + +short Find_file_in_fileselector(T_Fileselector *list, char * fname); + +#endif diff --git a/gfx2.cfg b/gfx2.cfg index 43f249a8..eacf653b 100644 Binary files a/gfx2.cfg and b/gfx2.cfg differ diff --git a/gfx2def.ini b/gfx2def.ini index 757c4c38..7fdc4d94 100644 --- a/gfx2def.ini +++ b/gfx2def.ini @@ -76,13 +76,6 @@ ; the menus and tool-bar | des menus et de la barre d'outils Menu_ratio = 1 ; (default 1) - ; Font: | Police de caractères (fonte): - ; 1: Classic | 1: Classique - ; 2: Fun | 2: Fun - Font = 1 ; (default 1) - - - [FILE_SELECTOR] # [SELECTEUR_DE_FICHIERS] ; Show hidden files and | Afficher les fichiers et répertoires @@ -269,12 +262,15 @@ Default_window_size = 640,480 ; (default '640,480') ; This setting allows you merge successive mouse movements into a single - ; mouse movement. Ideally you should leave it at zero, but if you have an - ; extremely fast mouse and you see the mouse cursor lagging WHEN YOU'RE NOT - ; DRAWING, you may want to set it to 1, 2 or more, so that GrafX2 skips small - ; steps. A very high value (100) guarantees that Grafx2 merges all the mouse - ; steps into a single one. - Merge_movement = 100 ; (default 100) + ; mouse movement. You should only use it if you are using a mouse which + ; reports at 200Hz or more, and you experience lag when using discontinuous + ; hand-drawing with large brushes (this tool tries to paste the brush and + ; update the screen on each new mouse position) In this case, set this to 2 + ; or more, to ignore some intermediate mouse reports when a more recent one + ; is present. + ; Note that with a value superior to 1, you lose precision with continuous + ; hand-drawing, as intermediate mouse positions are skipped. + Merge_movement = 0 ; (default 0) ; Number of columns in the palette of the menu bar. Can be any number from ; 1 to 256. If there is not enough room, the program will display less @@ -312,4 +308,36 @@ ; OS isn't able to do it by itself. (ie: Windows) Window_position = 9999,9999; (Default 9999,9999 which means: NA) + ; This is the time (in milliseconds) between two clicks for Grafx2 to + ; recognize a double-click. Double-click is used mostly in the palette + ; area of the menu: double-click a color to open the palette. + Double_click_speed = 500; (Default 500) + + ; When you press two digit keys in rapid succession (ex: 3 8), Grafx2 + ; sets transparency to 38% (instead of 30% then 80%). This setting + ; allows you to set the maximum delay between two keypresses for + ; GrafX2 to recognize them as a combo. + Double_key_speed = 500; (Default 500) + + ; Name of the skinfile you want to | Nom du fichier skin que vous voulez + ; use. | utiliser. + ; Default : (empty to let the program choose) + Skin_file = + + ; Name of the font file (8x8) you | Nom du fichier police de caractère + ; want to use. | 8x8 utilisée dans les menus. + ; Default : (empty to let the program choose) + Font_file = + + ; This determines the color value for the grid. Each pixel of + ; the grid will be displayed by XOR-ing the original color with + ; the value of this setting. + ; For example, if you always paint 16-color images, you can set it + ; to 16 so the color of the grid are 16 for 0, 17 for 1, etc. + ; Then you can set colors 16-31 as lighter/darker variants + ; of your original palette, resulting in a pretty grid ! + ; + ; Valid values are 1 to 255. + Grid_XOR_color = 255; (Default 255) + ; end of configuration diff --git a/global.h b/global.h index 89b3eb00..371f198e 100644 --- a/global.h +++ b/global.h @@ -63,9 +63,6 @@ GFX2_GLOBAL T_Video_mode Video_mode[MAX_VIDEO_MODES]; /// Actual number of video modes in ::Video_mode. GFX2_GLOBAL int Nb_video_modes; -/// A default 256-color palette. -GFX2_GLOBAL T_Palette Default_palette; - // -- Menu colors GFX2_GLOBAL byte MC_Black; ///< Index of color to use as "black" in the GUI menus. @@ -81,6 +78,7 @@ GFX2_GLOBAL T_Components Fav_menu_colors[4]; GFX2_GLOBAL word Mouse_X; ///< Current mouse cursor position. GFX2_GLOBAL word Mouse_Y; ///< Current mouse cursor position. GFX2_GLOBAL byte Mouse_K; ///< Current mouse buttons state. Bitfield: 1 for RMB, 2 for LMB. +GFX2_GLOBAL byte Keyboard_click_allowed; ///< Set to 0 when you edit a textfield so you can use space without exiting it /// Helper macro to take only one button when both are pressed (LMB has priority) #define Mouse_K_unique (Mouse_K==0?0:(Mouse_K&1?1:(Mouse_K&2?2:0))) @@ -139,14 +137,8 @@ GFX2_GLOBAL byte Cursor_hidden; GFX2_GLOBAL byte Cursor_in_menu; /// Boolean, means the cursor was hovering over a menu GUI element. GFX2_GLOBAL byte Cursor_in_menu_previous; -/// X coordinate of the mouse cursor's "hot spot". It is < ::CURSOR_SPRITE_WIDTH -GFX2_GLOBAL word Cursor_offset_X[NB_CURSOR_SPRITES]; -/// Y coordinate of the mouse cursor's "hot spot". It is < ::CURSOR_SPRITE_HEIGHT -GFX2_GLOBAL word Cursor_offset_Y[NB_CURSOR_SPRITES]; -/// Graphic resources for the mouse cursor. -GFX2_GLOBAL byte GFX_cursor_sprite[NB_CURSOR_SPRITES][CURSOR_SPRITE_HEIGHT][CURSOR_SPRITE_WIDTH]; /// Storage for the graphics under the mouse cursor. Used by ::Hide_cursor and ::Display_cursor -GFX2_GLOBAL byte CURSOR_BACKGROUND[CURSOR_SPRITE_HEIGHT][CURSOR_SPRITE_WIDTH]; +GFX2_GLOBAL byte Cursor_background[CURSOR_SPRITE_HEIGHT][CURSOR_SPRITE_WIDTH]; // -- Paintbrush data @@ -164,18 +156,6 @@ GFX2_GLOBAL byte Paintbrush_hidden; GFX2_GLOBAL short Paintbrush_X; /// Cordinate of the preview paintbrush in image space. GFX2_GLOBAL short Paintbrush_Y; -/// Graphic resources for the preset paintbrushes. -GFX2_GLOBAL byte GFX_paintbrush_sprite [NB_PAINTBRUSH_SPRITES][PAINTBRUSH_HEIGHT][PAINTBRUSH_WIDTH]; -/// Width of the preset paintbrushes. -GFX2_GLOBAL word Preset_paintbrush_width[NB_PAINTBRUSH_SPRITES]; -/// Height of the preset paintbrushes. -GFX2_GLOBAL word Preset_paintbrush_height[NB_PAINTBRUSH_SPRITES]; -/// Type of the preset paintbrush: index in enum PAINTBRUSH_SHAPES -GFX2_GLOBAL byte Paintbrush_type[NB_PAINTBRUSH_SPRITES]; -/// Brush handle for the preset brushes. Generally ::Preset_paintbrush_width[]/2 -GFX2_GLOBAL word Preset_paintbrush_offset_X[NB_PAINTBRUSH_SPRITES]; -/// Brush handle for the preset brushes. Generally ::Preset_paintbrush_height[]/2 -GFX2_GLOBAL word Preset_paintbrush_offset_Y[NB_PAINTBRUSH_SPRITES]; /// Pixel data of the current brush GFX2_GLOBAL byte * Paintbrush_sprite; /// Current paintbrush's width @@ -548,6 +528,11 @@ GFX2_GLOBAL T_Dropdown_button * Window_stack_dropdown_button_list[8]; /// List of dropdown buttons in the topmost window. #define Window_dropdown_button_list Window_stack_dropdown_button_list[Windows_open-1] +GFX2_GLOBAL T_List_button * Window_stack_list_button_list[8]; +/// List of list buttons in the topmost window. +#define Window_list_button_list Window_stack_list_button_list[Windows_open-1] + + GFX2_GLOBAL int Window_stack_attribute1[8]; /// @@ -660,6 +645,8 @@ GFX2_GLOBAL byte Stencil[256]; /// Boolean, true when the Grid mode is active. GFX2_GLOBAL byte Snap_mode; +/// Boolean, true when the Grid is displayed in zoomed view. +GFX2_GLOBAL byte Show_grid; /// Width of the grid in Grid mode. GFX2_GLOBAL word Snap_width; /// Height of the grid in Grid mode. @@ -675,8 +662,6 @@ GFX2_GLOBAL word Snap_offset_Y; GFX2_GLOBAL byte Sieve_mode; /// Sprite of the sieve pattern. It's actually an array of booleans. GFX2_GLOBAL byte Sieve[16][16]; -/// Preset sieve patterns, stored as binary (one word per line) -GFX2_GLOBAL word GFX_sieve_pattern[12][16]; /// Width of the sieve pattern, in Sieve mode. GFX2_GLOBAL short Sieve_width; /// Height of the sieve pattern, in Sieve mode. @@ -810,40 +795,14 @@ GFX2_GLOBAL byte File_in_command_line; /// Boolean, true if Grafx2 was run with a command-line argument to set a resolution on startup (overrides config) GFX2_GLOBAL byte Resolution_in_command_line; -// - Graphic skin data +// - Graphic -/// Bitmap data for the menu, a single rectangle. -GFX2_GLOBAL byte GFX_menu_block[MENU_HEIGHT][MENU_WIDTH]; -/// Bitmap data for the icons that are displayed over the menu. -GFX2_GLOBAL byte GFX_menu_sprite[NB_MENU_SPRITES][MENU_SPRITE_HEIGHT][MENU_SPRITE_WIDTH]; -/// Bitmap data for the different "effects" icons. -GFX2_GLOBAL byte GFX_effect_sprite[NB_EFFECTS_SPRITES][MENU_SPRITE_HEIGHT][MENU_SPRITE_WIDTH]; -/// Bitmap data for the Grafx2 logo that appears on splash screen. All 256 colors allowed. -GFX2_GLOBAL byte * GFX_logo_grafx2; -/// Bitmap data for the classic 8x8 font used in menus etc. -GFX2_GLOBAL byte GFX_system_font[256*8*8]; -/// Bitmap data for the "fun" 8x8 font used in menus etc. -GFX2_GLOBAL byte GFX_fun_font [256*8*8]; -/// Bitmap data for the 6x8 font used in help screens. -GFX2_GLOBAL byte GFX_help_font_norm [256][6][8]; -/// Bitmap data for the 6x8 font used in help screens ("bold" verstion). -GFX2_GLOBAL byte GFX_bold_font [256][6][8]; -// 12 -// 34 -/// Bitmap data for the title font used in help screens. Top-left quarter. -GFX2_GLOBAL byte GFX_help_font_t1 [64][6][8]; -/// Bitmap data for the title font used in help screens. Top-right quarter. -GFX2_GLOBAL byte GFX_help_font_t2 [64][6][8]; -/// Bitmap data for the title font used in help screens. Bottom-left quarter. -GFX2_GLOBAL byte GFX_help_font_t3 [64][6][8]; -/// Bitmap data for the title font used in help screens. Bottom-right quarter. -GFX2_GLOBAL byte GFX_help_font_t4 [64][6][8]; -/// Bitmap data for the small 8x8 icons. -GFX2_GLOBAL byte GFX_icon_sprite[NB_ICON_SPRITES][ICON_SPRITE_HEIGHT][ICON_SPRITE_WIDTH]; - -/// Pointer to the font selected for menus. It's either ::GFX_system_font or ::GFX_fun_font +/// Pointer to the font selected for menus. GFX2_GLOBAL byte * Menu_font; +/// Pointer to the current active skin. +GFX2_GLOBAL T_Gui_skin * Gfx; + // -- Help data /// Index of the ::Help_section shown by the Help screen. @@ -873,6 +832,8 @@ GFX2_GLOBAL short Colorpicker_X; /// Position of the colorpicker tool, in image coordinates. GFX2_GLOBAL short Colorpicker_Y; +/// Brush container +GFX2_GLOBAL T_Brush_template Brush_container[BRUSH_CONTAINER_COLUMNS*BRUSH_CONTAINER_ROWS]; #ifdef GLOBAL_VARIABLES byte CURSOR_FOR_OPERATION[NB_OPERATIONS]= @@ -921,21 +882,11 @@ GFX2_GLOBAL short Colorpicker_Y; /// each operation, and for each mouse state (no button,left button,right button) GFX2_GLOBAL struct { - byte Hide_cursor; ///< Boolean: Need to hide/unhide cursor during this step Func_action Action; ///< Function to call + byte Hide_cursor; ///< Boolean: Need to hide/unhide cursor during this step + byte Fast_mouse; ///< Operation should take shortcuts with mouse movements } Operation[NB_OPERATIONS][3][OPERATION_STACK_SIZE]; -// -- Fileselector data - -/// Number of elements in the current fileselector's ::Filelist -GFX2_GLOBAL short Filelist_nb_elements; -/// Number of files in the current fileselector's ::Filelist -GFX2_GLOBAL short Filelist_nb_files; -/// Number of directories in the current fileselector's ::Filelist -GFX2_GLOBAL short Filelist_nb_directories; -/// Head of the linked list for the fileselector. -GFX2_GLOBAL T_Fileselector_item * Filelist; - // -- misc /// diff --git a/graph.c b/graph.c index 9a9d8fac..d6947b8c 100644 --- a/graph.c +++ b/graph.c @@ -107,6 +107,7 @@ void Update_part_of_screen(short x, short y, short width, short height) if(effective_Y + effective_h > Menu_Y) effective_h = Menu_Y - effective_Y; + /* SDL_Rect r; r.x=effective_X; @@ -136,7 +137,7 @@ void Update_part_of_screen(short x, short y, short width, short height) } else effective_X += Main_separator_position + SEPARATOR_WIDTH*Menu_factor_X; - diff = effective_X+effective_w-Screen_width; + diff = effective_X+effective_w-Min(Screen_width, Main_X_zoom+(Main_image_width-Main_magnifier_offset_X)*Main_magnifier_factor); if (diff>0) { effective_w -=diff; @@ -153,7 +154,7 @@ void Update_part_of_screen(short x, short y, short width, short height) return; effective_Y = 0; } - diff = effective_Y+effective_h-Menu_Y; + diff = effective_Y+effective_h-Min(Menu_Y, (Main_image_height-Main_magnifier_offset_Y)*Main_magnifier_factor); if (diff>0) { effective_h -=diff; @@ -161,6 +162,7 @@ void Update_part_of_screen(short x, short y, short width, short height) return; } + // Très utile pour le debug :) /*SDL_Rect r; r.x=effective_X; @@ -169,6 +171,7 @@ void Update_part_of_screen(short x, short y, short width, short height) r.w=effective_w; SDL_FillRect(Screen_SDL,&r,3);*/ + Redraw_grid(effective_X,effective_Y,effective_w,effective_h); Update_rect(effective_X,effective_Y,effective_w,effective_h); } } @@ -468,7 +471,7 @@ int Init_mode_video(int width, int height, int fullscreen, int pix_ratio) Clear_border(MC_Black); // Requires up-to-date Screen_* and Pixel_* - // Taille des menus + // Set menu size (software zoom) if (Screen_width/320 > Screen_height/200) factor=Screen_height/200; else @@ -476,28 +479,32 @@ int Init_mode_video(int width, int height, int fullscreen, int pix_ratio) switch (Config.Ratio) { - case 1: // adapter tout + case 1: // Always the biggest possible Menu_factor_X=factor; Menu_factor_Y=factor; break; - case 2: // adapter légèrement + case 2: // Only keep the aspect ratio Menu_factor_X=factor-1; if (Menu_factor_X<1) Menu_factor_X=1; Menu_factor_Y=factor-1; if (Menu_factor_Y<1) Menu_factor_Y=1; break; - default: // ne pas adapter + case 0: // Always smallest possible Menu_factor_X=1; Menu_factor_Y=1; + break; + default: // Stay below some reasonable size + Menu_factor_X=Min(factor,abs(Config.Ratio)); + Menu_factor_Y=Min(factor,abs(Config.Ratio)); } if (Pixel_height>Pixel_width && Screen_width>=Menu_factor_X*2*320) Menu_factor_X*=2; else if (Pixel_width>Pixel_height && Screen_height>=Menu_factor_Y*2*200) Menu_factor_Y*=2; - if (Horizontal_line_buffer) - free(Horizontal_line_buffer); - Horizontal_line_buffer=(byte *)malloc(Pixel_width*((Screen_width>Main_image_width)?Screen_width:Main_image_width)); + free(Horizontal_line_buffer); + Horizontal_line_buffer=(byte *)malloc(Pixel_width * + ((Screen_width>Main_image_width)?Screen_width:Main_image_width)); Set_palette(Main_palette); @@ -677,6 +684,7 @@ void Get_colors_from_brush(void) Display_all_screen(); Display_menu(); Display_cursor(); + End_of_modification(); Main_image_is_modified=1; } @@ -994,7 +1002,18 @@ void Fill_general(byte fill_color) // par l'utilisation de "Display_pixel()", et que les autres... eh bein // on n'y a jamais touché à l'écran les autres: ils sont donc corrects. + if(Main_magnifier_mode) + { + short w,h; + + w=Min(Screen_width-Main_X_zoom, (Main_image_width-Main_magnifier_offset_X)*Main_magnifier_factor); + h=Min(Menu_Y, (Main_image_height-Main_magnifier_offset_Y)*Main_magnifier_factor); + + Redraw_grid(Main_X_zoom,0,w,h); + } + Update_rect(0,0,0,0); + End_of_modification(); } } @@ -1005,11 +1024,32 @@ void Fill_general(byte fill_color) ////////////////////////// avec gestion de previews ////////////////////////// ////////////////////////////////////////////////////////////////////////////// + // Data used by ::Init_permanent_draw() and ::Pixel_figure_permanent() + static Uint32 Permanent_draw_next_refresh=0; + static int Permanent_draw_count=0; + + void Init_permanent_draw(void) + { + Permanent_draw_count = 0; + Permanent_draw_next_refresh = SDL_GetTicks() + 100; + } // Affichage d'un point de façon définitive (utilisation du pinceau) void Pixel_figure_permanent(word x_pos,word y_pos,byte color) { Display_paintbrush(x_pos,y_pos,color,0); + Permanent_draw_count ++; + + // Check every 8 pixels + if (! (Permanent_draw_count&7)) + { + Uint32 now = SDL_GetTicks(); + if (now>= Permanent_draw_next_refresh) + { + Permanent_draw_next_refresh = now+100; + Flush_update(); + } + } } // Affichage d'un point de façon définitive @@ -1151,6 +1191,7 @@ void Draw_empty_circle_general(short center_x,short center_y,short radius,byte c void Draw_empty_circle_permanent(short center_x,short center_y,short radius,byte color) { Pixel_figure=Pixel_figure_permanent; + Init_permanent_draw(); Draw_empty_circle_general(center_x,center_y,radius,color); Update_part_of_screen(center_x - radius, center_y - radius, 2* radius+1, 2*radius+1); } @@ -1293,6 +1334,7 @@ void Draw_empty_ellipse_general(short center_x,short center_y,short horizontal_r void Draw_empty_ellipse_permanent(short center_x,short center_y,short horizontal_radius,short vertical_radius,byte color) { Pixel_figure=Pixel_figure_permanent; + Init_permanent_draw(); Draw_empty_ellipse_general(center_x,center_y,horizontal_radius,vertical_radius,color); Update_part_of_screen(center_x - horizontal_radius, center_y - vertical_radius, 2* horizontal_radius+1, 2*vertical_radius+1); } @@ -1356,46 +1398,132 @@ void Draw_filled_ellipse(short center_x,short center_y,short horizontal_radius,s * TRACÉ DE LIGNES * ******************/ -void Clamp_coordinates_45_degrees(short ax, short ay, short* bx, short* by) -// Modifie bx et by pour que la ligne AXAY - BXBY soit -// - une droite horizontale -// - une droite verticale -// - une droite avec une pente de 45 degrés +/// Alters bx and by so the (AX,AY)-(BX,BY) segment becomes either horizontal, +/// vertical, 45degrees, or isometrical for pixelart (ie 2:1 ratio) +void Clamp_coordinates_regular_angle(short ax, short ay, short* bx, short* by) { - int dx, dy; - float tan; + int dx, dy; + float angle; - dx = (*bx)-ax; - dy = ay- *by; // On prend l'opposée car à l'écran les Y sont positifs en bas, et en maths, positifs en haut + dx = *bx-ax; + dy = *by-ay; - if (dx==0) return; // On est en lockx et de toutes façons le X n'a pas bougé, on sort tout de suite pour éviter une méchante division par 0 + // No mouse move: no need to clamp anything + if (dx==0 || dy == 0) return; - tan = (float)dy/(float)dx; + // Determine angle (heading) + angle = atan2(dx, dy); + + // Get absolute values, useful from now on: + //dx=abs(dx); + //dy=abs(dy); + + // Negative Y + if (angle < M_PI*(-15.0/16.0) || angle > M_PI*(15.0/16.0)) + { + *bx=ax; + *by=ay + dy; + } + // Iso close to negative Y + else if (angle < M_PI*(-13.0/16.0)) + { + dy=dy | 1; // Round up to next odd number + *bx=ax + dy/2; + *by=ay + dy; + } + // 45deg + else if (angle < M_PI*(-11.0/16.0)) + { + *by = (*by + ay + dx)/2; + *bx = ax - ay + *by; + } + // Iso close to negative X + else if (angle < M_PI*(-9.0/16.0)) + { + dx=dx | 1; // Round up to next odd number + *bx=ax + dx; + *by=ay + dx/2; + } + // Negative X + else if (angle < M_PI*(-7.0/16.0)) + { + *bx=ax + dx; + *by=ay; + } + // Iso close to negative X + else if (angle < M_PI*(-5.0/16.0)) + { + dx=dx | 1; // Round up to next odd number + *bx=ax + dx; + *by=ay - dx/2; + } + // 45 degrees + else if (angle < M_PI*(-3.0/16.0)) + { + *by = (*by + ay - dx)/2; + *bx = ax + ay - *by; + } + // Iso close to positive Y + else if (angle < M_PI*(-1.0/16.0)) + { + dy=dy | 1; // Round up to next odd number + *bx=ax - dy/2; + *by=ay + dy; + } + // Positive Y + else if (angle < M_PI*(1.0/16.0)) + { + *bx=ax; + *by=ay + dy; + } + // Iso close to positive Y + else if (angle < M_PI*(3.0/16.0)) + { + dy=dy | 1; // Round up to next odd number + *bx=ax + dy/2; + *by=ay + dy; + } + // 45 degrees + else if (angle < M_PI*(5.0/16.0)) + { + *by = (*by + ay + dx)/2; + *bx = ax - ay + *by; + } + // Iso close to positive X + else if (angle < M_PI*(7.0/16.0)) + { + dx=dx | 1; // Round up to next odd number + *bx=ax + dx; + *by=ay + dx/2; + } + // Positive X + else if (angle < M_PI*(9.0/16.0)) + { + *bx=ax + dx; + *by=ay; + } + // Iso close to positive X + else if (angle < M_PI*(11.0/16.0)) + { + dx=dx | 1; // Round up to next odd number + *bx=ax + dx; + *by=ay - dx/2; + } + // 45 degrees + else if (angle < M_PI*(13.0/16.0)) + { + *by = (*by + ay - dx)/2; + *bx = ax + ay - *by; + } + // Iso close to negative Y + else //if (angle < M_PI*(15.0/16.0)) + { + dy=dy | 1; // Round up to next odd number + *bx=ax - dy/2; + *by=ay + dy; + } - if (tan <= 0.4142 && tan >= -0.4142) - { - // Cas 1 : Lock Y - *by = ay; - } - else if ( tan > 0.4142 && tan < 2.4142) - { - // Cas 2 : dy=dx - *by = (*by + ay - dx)/2; - *bx = ax + ay - *by; - } - else if (tan < -0.4142 && tan >= -2.4142) - { - // Cas 8 : dy = -dx - *by = (*by + ay + dx)/2; - *bx = ax - ay + *by; - } - else - { - // Cas 3 : Lock X - *bx = ax; - } - - return; + return; } // -- Tracer général d'une ligne ------------------------------------------ @@ -1406,8 +1534,7 @@ void Draw_line_general(short start_x,short start_y,short end_x,short end_y, byte short incr_x,incr_y; short i,cumul; short delta_x,delta_y; - - + x_pos=start_x; y_pos=start_y; @@ -1471,11 +1598,12 @@ void Draw_line_general(short start_x,short start_y,short end_x,short end_y, byte // -- Tracer définitif d'une ligne -- -void Draw_line_permanet(short start_x,short start_y,short end_x,short end_y, byte color) +void Draw_line_permanent(short start_x,short start_y,short end_x,short end_y, byte color) { int w = end_x-start_x, h = end_y - start_y; Pixel_figure=Pixel_figure_permanent; + Init_permanent_draw(); Draw_line_general(start_x,start_y,end_x,end_y,color); Update_part_of_screen((start_x=134) + if (order_index>=NB_SHORTCUTS) { Error(0); return; @@ -130,7 +130,7 @@ void Window_set_shortcut(int action_id) while (ConfigKey[config_index].Number!=order_index) { config_index++; - if (config_index>=134) + if (config_index>=NB_SHORTCUTS) { Error(0); return; @@ -278,7 +278,21 @@ void Display_help(void) else if (line_type == 'K') { const char *hyperlink; + const char * escaped_percent_pos; + // Determine link position: link_position = strstr(line,"%s") - line; + // Adjust for any escaped %% that would precede it. + escaped_percent_pos = line; + do + { + escaped_percent_pos = strstr(escaped_percent_pos,"%%"); + if (escaped_percent_pos && escaped_percent_pos - line < link_position) + { + link_position--; + escaped_percent_pos+=2; + } + } while (escaped_percent_pos); + // hyperlink=Keyboard_shortcut_value(Help_section[Current_help_section].Help_table[start_line + line_index].Line_parameter); link_size=strlen(hyperlink); snprintf(buffer, 44, line, hyperlink); @@ -309,27 +323,27 @@ void Display_help(void) if (line_type=='T') { if (line[char_index/2]>'_' || line[char_index/2]<' ') - char_pixel=&(GFX_help_font_norm['!'][0][0]); // Caractère pas géré + char_pixel=&(Gfx->Help_font_norm['!'][0][0]); // Caractère pas géré else if (char_index & 1) - char_pixel=&(GFX_help_font_t2[(unsigned char)(line[char_index/2])-' '][0][0]); + char_pixel=&(Gfx->Help_font_t2[(unsigned char)(line[char_index/2])-' '][0][0]); else - char_pixel=&(GFX_help_font_t1[(unsigned char)(line[char_index/2])-' '][0][0]); + char_pixel=&(Gfx->Help_font_t1[(unsigned char)(line[char_index/2])-' '][0][0]); } else if (line_type=='-') { if (line[char_index/2]>'_' || line[char_index/2]<' ') - char_pixel=&(GFX_help_font_norm['!'][0][0]); // Caractère pas géré + char_pixel=&(Gfx->Help_font_norm['!'][0][0]); // Caractère pas géré else if (char_index & 1) - char_pixel=&(GFX_help_font_t4[(unsigned char)(line[char_index/2])-' '][0][0]); + char_pixel=&(Gfx->Help_font_t4[(unsigned char)(line[char_index/2])-' '][0][0]); else - char_pixel=&(GFX_help_font_t3[(unsigned char)(line[char_index/2])-' '][0][0]); + char_pixel=&(Gfx->Help_font_t3[(unsigned char)(line[char_index/2])-' '][0][0]); } else if (line_type=='S') - char_pixel=&(GFX_bold_font[(unsigned char)(line[char_index])][0][0]); + char_pixel=&(Gfx->Bold_font[(unsigned char)(line[char_index])][0][0]); else if (line_type=='N' || line_type=='K') - char_pixel=&(GFX_help_font_norm[(unsigned char)(line[char_index])][0][0]); + char_pixel=&(Gfx->Help_font_norm[(unsigned char)(line[char_index])][0][0]); else - char_pixel=&(GFX_help_font_norm['!'][0][0]); // Un garde-fou en cas de probleme + char_pixel=&(Gfx->Help_font_norm['!'][0][0]); // Un garde-fou en cas de probleme for (x=0;x<6;x++) for (repeat_menu_x_factor=0;repeat_menu_x_factor -*/ - -////////////////////////////////////////////////////////////////////////////// -///@file help.h -/// Functions related to the help browser. The help data is in helpfile.h -////////////////////////////////////////////////////////////////////////////// - -#ifndef __HELP_H_ -#define __HELP_H_ - -/*! - Called to open the help window with the keyboard shortcut. - If the mouse is over a button, its contextual help will be displayed. - Else, the default helpscreen will be shown. -*/ -void Button_Help(void); - -/*! - Displays and runs the "Statistics" window -*/ -void Button_Stats(void); - -/*! - Displays and runs the "Help / About..." window - @param section Number of the help section page to display (equals the button number the mouse was hovering for the contextual help), -1 for the main help page. - @param sub_section Help sub-section title (the page will be scrolled so this title is at the top). -*/ -void Window_help(int section, const char * sub_section); - -#endif - +/* Grafx2 - The Ultimate 256-color bitmap paint program + + Copyright 2007 Adrien Destugues + Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) + + Grafx2 is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 + of the License. + + Grafx2 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grafx2; if not, see +*/ + +////////////////////////////////////////////////////////////////////////////// +///@file help.h +/// Functions related to the help browser. The help data is in helpfile.h +////////////////////////////////////////////////////////////////////////////// + +#ifndef __HELP_H_ +#define __HELP_H_ + +/*! + Called to open the help window with the keyboard shortcut. + If the mouse is over a button, its contextual help will be displayed. + Else, the default helpscreen will be shown. +*/ +void Button_Help(void); + +/*! + Displays and runs the "Statistics" window +*/ +void Button_Stats(void); + +/*! + Displays and runs the "Help / About..." window + @param section Number of the help section page to display (equals the button number the mouse was hovering for the contextual help), -1 for the main help page. + @param sub_section Help sub-section title (the page will be scrolled so this title is at the top). +*/ +void Window_help(int section, const char * sub_section); + +#endif + diff --git a/helpfile.h b/helpfile.h index 4b7c4539..e328b02d 100644 --- a/helpfile.h +++ b/helpfile.h @@ -1,2389 +1,2496 @@ -/* Grafx2 - The Ultimate 256-color bitmap paint program - - Copyright 2008 Yves Rizoud - Copyright 2009 Franck Charlet - Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) - - Grafx2 is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; version 2 - of the License. - - Grafx2 is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Grafx2; if not, see -*/ - -////////////////////////////////////////////////////////////////////////////// -///@file helpfile.h -/// This is all the text that appears in contextual help and credits. -/// -/// Note: The source code is kept on a public website, so keep this in mind -/// if you're thinking of putting an e-mail address in there. At least, use -/// "\100" instead of @, to help against the most basic email address harversters. -////////////////////////////////////////////////////////////////////////////// - -#include "const.h" // Uses enumerations BUTTON_NUMBERS and SPECIAL_ACTIONS - -// Some magic formulas: - -#define HELP_TEXT(x) {'N', x, 0}, -// Generates a 'N' line (Normal) - -#define HELP_LINK(x,y) {'K', x, y}, -// Generates a 'K' line (Key) - -#define HELP_BOLD(x) {'S', x, 0}, -// Generates a 'S' line (BOLD) - -#define HELP_TITLE(x) {'T', x, 0}, {'-', x, 0}, -// Generates a 'T' line (Title, upper half) -// and a second '-' line (Title, lower half), with the same text. - -static const T_Help_table helptable_about[] = -/* - Do not exceed 44 characters for normal lines: - HELP_TEXT ("--------------------------------------------") - Do not exceed 22 characters for title lines: - HELP_TITLE("======================") -*/ -{ - HELP_TEXT ("") // Leave enough room for a hard-coded logo, eventually. - HELP_TEXT ("") - HELP_TEXT ("") - HELP_TEXT ("") - HELP_TITLE(" GRAFX 2 ") - HELP_BOLD (" \"Summer Sunset\" Edition") - HELP_BOLD (" THE ULTIMATE MULTI-RESOLUTION GFX EDITOR") - HELP_TEXT (" http://grafx2.googlecode.com") - HELP_TEXT ("") - HELP_TEXT (" Copyright 2007 by the Grafx2 project team") - HELP_TEXT (" Copyright 1996-2001 by SUNSET DESIGN") -}; -static const T_Help_table helptable_licence[] = -{ - HELP_TITLE(" LICENSE") - HELP_TEXT ("") - HELP_TEXT ("Grafx2 is FREE SOFTWARE, you can") - HELP_TEXT ("redistribute it and/or modify it under the") - HELP_TEXT ("terms of the GNU General Public License as") - HELP_TEXT ("published by the Free Software Foundation;") - HELP_TEXT ("version 2 of the License.") - HELP_TEXT ("") - HELP_TEXT ("Grafx2 is distributed in the hope that it") - HELP_TEXT ("will be useful, but WITHOUT ANY WARRANTY;") - HELP_TEXT ("without even the implied warranty of") - HELP_TEXT ("MERCHANTABILITY or FITNESS FOR A PARTICULAR") - HELP_TEXT ("PURPOSE. See the GNU General Public License") - HELP_TEXT ("for more details.") - HELP_TEXT ("") - HELP_TEXT ("You should have received a copy of the GNU") - HELP_TEXT ("General Public License along with Grafx2;") - HELP_TEXT ("if not, see http://www.gnu.org/licenses/ or") - HELP_TEXT ("write to the Free Software Foundation, Inc.") - HELP_TEXT (" 59 Temple Place - Suite 330, Boston,") - HELP_TEXT (" MA 02111-1307, USA.") - -}; -static const T_Help_table helptable_help[] = -{ - HELP_TITLE(" HELP") - HELP_TEXT ("") - HELP_TEXT (" Contextual help is available by pressing") - HELP_LINK (" the %s key",0x100+BUTTON_HELP) - HELP_TEXT (" You can do it while hovering a menu icon,") - HELP_TEXT (" or while a window is open.") - HELP_TEXT (" When a keyboard shortcut is displayed it's") - HELP_TEXT (" your current configuration and you can") - HELP_TEXT (" change it by clicking it.") - HELP_TEXT ("") - HELP_TITLE(" KEYBOARD SHORTCUTS") - HELP_TEXT ("") - HELP_TEXT ("Scroll visible area") - HELP_LINK (" up: %s", SPECIAL_SCROLL_UP) - HELP_LINK (" down: %s", SPECIAL_SCROLL_DOWN) - HELP_LINK (" left: %s", SPECIAL_SCROLL_LEFT) - HELP_LINK (" right: %s", SPECIAL_SCROLL_RIGHT) - HELP_LINK (" up faster: %s", SPECIAL_SCROLL_UP_FAST) - HELP_LINK (" down faster: %s", SPECIAL_SCROLL_DOWN_FAST) - HELP_LINK (" left faster: %s", SPECIAL_SCROLL_LEFT_FAST) - HELP_LINK (" right faster: %s", SPECIAL_SCROLL_RIGHT_FAST) - HELP_LINK (" up slower: %s", SPECIAL_SCROLL_UP_SLOW) - HELP_LINK (" down slower: %s", SPECIAL_SCROLL_DOWN_SLOW) - HELP_LINK (" left slower: %s", SPECIAL_SCROLL_LEFT_SLOW) - HELP_LINK (" right slower: %s", SPECIAL_SCROLL_RIGHT_SLOW) - HELP_TEXT ("Emulate mouse") - HELP_LINK (" Up: %s", SPECIAL_MOUSE_UP) - HELP_LINK (" Down: %s", SPECIAL_MOUSE_DOWN) - HELP_LINK (" Left: %s", SPECIAL_MOUSE_LEFT) - HELP_LINK (" Right: %s", SPECIAL_MOUSE_RIGHT) - HELP_LINK (" Left click: %s", SPECIAL_CLICK_LEFT) - HELP_LINK (" Right click: %s", SPECIAL_CLICK_RIGHT) - HELP_LINK ("Show / Hide menu: %s", 0x100+BUTTON_HIDE) - HELP_LINK ("Show / Hide cursor: %s", SPECIAL_SHOW_HIDE_CURSOR) - HELP_LINK ("Paintbrush = \".\": %s", SPECIAL_DOT_PAINTBRUSH) - HELP_LINK ("Paintbrush choice: %s", 0x100+BUTTON_PAINTBRUSHES) - HELP_LINK ("Monochrome brush: %s", 0x200+BUTTON_PAINTBRUSHES) - HELP_LINK ("Freehand drawing: %s", 0x100+BUTTON_DRAW) - HELP_TEXT ("Switch freehand") - HELP_LINK (" drawing mode: %s", 0x200+BUTTON_DRAW) - HELP_TEXT ("Continuous freehand") - HELP_LINK (" drawing: %s", SPECIAL_CONTINUOUS_DRAW) - HELP_LINK ("Line: %s", 0x100+BUTTON_LINES) - HELP_LINK ("Knotted lines: %s", 0x200+BUTTON_LINES) - HELP_LINK ("Spray: %s", 0x100+BUTTON_AIRBRUSH) - HELP_LINK ("Spray menu: %s", 0x200+BUTTON_AIRBRUSH) - HELP_LINK ("Floodfill: %s", 0x100+BUTTON_FLOODFILL) - HELP_LINK ("Replace color: %s", 0x200+BUTTON_FLOODFILL) - HELP_LINK ("Bezier's curves: %s", 0x100+BUTTON_CURVES) - HELP_TEXT ("Bezier's curve with") - HELP_LINK (" 3 or 4 points %s", 0x200+BUTTON_CURVES) - HELP_LINK ("Empty rectangle: %s", 0x100+BUTTON_RECTANGLES) - HELP_LINK ("Filled rectangle: %s", 0x100+BUTTON_FILLRECT) - HELP_LINK ("Empty circle: %s", 0x100+BUTTON_CIRCLES) - HELP_LINK ("Empty ellipse: %s", 0x200+BUTTON_CIRCLES) - HELP_LINK ("Filled circle: %s", 0x100+BUTTON_FILLCIRC) - HELP_LINK ("Filled ellipse: %s", 0x200+BUTTON_FILLCIRC) - HELP_LINK ("Empty polygon: %s", 0x100+BUTTON_POLYGONS) - HELP_LINK ("Empty polyform: %s", 0x200+BUTTON_POLYGONS) - HELP_LINK ("Polyfill: %s", 0x100+BUTTON_POLYFILL) - HELP_LINK ("Filled polyform: %s", 0x200+BUTTON_POLYFILL) - HELP_LINK ("Gradient rectangle: %s", 0x100+BUTTON_GRADRECT) - HELP_LINK ("Gradation menu: %s", 0x100+BUTTON_GRADMENU) - HELP_LINK ("Spheres: %s", 0x100+BUTTON_SPHERES) - HELP_LINK ("Gradient ellipses: %s", 0x200+BUTTON_SPHERES) - HELP_LINK ("Adjust picture: %s", 0x100+BUTTON_ADJUST) - HELP_LINK ("Flip picture menu: %s", 0x200+BUTTON_ADJUST) - HELP_LINK ("Effects menu: %s", 0x100+BUTTON_EFFECTS) - HELP_LINK ("Shade mode: %s", SPECIAL_SHADE_MODE) - HELP_LINK ("Shade menu: %s", SPECIAL_SHADE_MENU) - HELP_LINK ("Quick-shade mode: %s", SPECIAL_QUICK_SHADE_MODE) - HELP_LINK ("Quick-shade menu: %s", SPECIAL_QUICK_SHADE_MENU) - HELP_LINK ("Stencil mode: %s", SPECIAL_STENCIL_MODE) - HELP_LINK ("Stencil menu: %s", SPECIAL_STENCIL_MENU) - HELP_LINK ("Mask mode: %s", SPECIAL_MASK_MODE) - HELP_LINK ("Mask menu: %s", SPECIAL_MASK_MENU) - HELP_LINK ("Grid mode: %s", SPECIAL_GRID_MODE) - HELP_LINK ("Grid menu: %s", SPECIAL_GRID_MENU) - HELP_LINK ("Sieve mode: %s", SPECIAL_SIEVE_MODE) - HELP_LINK ("Sieve menu: %s", SPECIAL_SIEVE_MENU) - HELP_LINK ("Invert Sieve: %s", SPECIAL_INVERT_SIEVE) - HELP_LINK ("Colorize mode: %s", SPECIAL_COLORIZE_MODE) - HELP_LINK ("Colorize menu: %s", SPECIAL_COLORIZE_MENU) - HELP_LINK ("Smooth mode: %s", SPECIAL_SMOOTH_MODE) - HELP_LINK ("Smooth menu: %s", SPECIAL_SMOOTH_MENU) - HELP_LINK ("Smear mode: %s", SPECIAL_SMEAR_MODE) - HELP_LINK ("Tiling mode: %s", SPECIAL_TILING_MODE) - HELP_LINK ("Tiling menu: %s", SPECIAL_TILING_MENU) - HELP_LINK ("Pick brush: %s", 0x100+BUTTON_BRUSH) - HELP_LINK ("Pick polyform brush: %s", 0x100+BUTTON_POLYBRUSH) - HELP_LINK ("Restore brush: %s", 0x200+BUTTON_BRUSH) - HELP_LINK ("Flip brush X: %s", SPECIAL_FLIP_X) - HELP_LINK ("Flip brush Y: %s", SPECIAL_FLIP_Y) - HELP_LINK ("90° brush rotation: %s", SPECIAL_ROTATE_90) - HELP_LINK ("180° brush rotation: %s", SPECIAL_ROTATE_180) - HELP_LINK ("Stretch brush: %s", SPECIAL_STRETCH) - HELP_LINK ("Distort brush: %s", SPECIAL_DISTORT) - HELP_LINK ("Outline brush: %s", SPECIAL_OUTLINE) - HELP_LINK ("Nibble brush: %s", SPECIAL_NIBBLE) - HELP_LINK ("Get brush colors: %s", SPECIAL_GET_BRUSH_COLORS) - HELP_LINK ("Recolorize brush: %s", SPECIAL_RECOLORIZE_BRUSH) - HELP_LINK ("Rotate brush: %s", SPECIAL_ROTATE_ANY_ANGLE) - HELP_LINK ("Pipette: %s", 0x100+BUTTON_COLORPICKER) - HELP_LINK ("Swap fore/back color:%s", 0x200+BUTTON_COLORPICKER) - HELP_LINK ("Magnifier mode: %s", 0x100+BUTTON_MAGNIFIER) - HELP_LINK ("Zoom factor menu: %s", 0x200+BUTTON_MAGNIFIER) - HELP_LINK ("Zoom in: %s", SPECIAL_ZOOM_IN) - HELP_LINK ("Zoom out: %s", SPECIAL_ZOOM_OUT) - HELP_LINK ("Brush effects menu: %s", 0x100+BUTTON_BRUSH_EFFECTS) - HELP_LINK ("Text: %s", 0x100+BUTTON_TEXT) - HELP_LINK ("Resolution menu: %s", 0x100+BUTTON_RESOL) - HELP_LINK ("Safety resolution: %s", 0x200+BUTTON_RESOL) - HELP_LINK ("Help: %s", 0x100+BUTTON_HELP) - HELP_LINK ("Statistics: %s", 0x200+BUTTON_HELP) - HELP_LINK ("Go to spare page: %s", 0x100+BUTTON_PAGE) - HELP_LINK ("Copy to spare page: %s", 0x200+BUTTON_PAGE) - HELP_LINK ("Save as: %s", 0x100+BUTTON_SAVE) - HELP_LINK ("Save: %s", 0x200+BUTTON_SAVE) - HELP_LINK ("Load: %s", 0x100+BUTTON_LOAD) - HELP_LINK ("Re-load: %s", 0x200+BUTTON_LOAD) - HELP_LINK ("Save brush: %s", SPECIAL_SAVE_BRUSH) - HELP_LINK ("Load brush: %s", SPECIAL_LOAD_BRUSH) - HELP_LINK ("Larger brush size: %s", SPECIAL_BIGGER_PAINTBRUSH) - HELP_LINK ("Smaller brush size: %s", SPECIAL_SMALLER_PAINTBRUSH) - HELP_LINK ("Settings: %s", 0x100+BUTTON_SETTINGS) - HELP_LINK ("Undo: %s", 0x100+BUTTON_UNDO) - HELP_LINK ("Redo: %s", 0x200+BUTTON_UNDO) - HELP_LINK ("Kill page: %s", 0x100+BUTTON_KILL) - HELP_LINK ("Clear: %s", 0x100+BUTTON_CLEAR) - HELP_LINK ("Clear with BG color: %s", 0x200+BUTTON_CLEAR) - HELP_LINK ("Quit: %s", 0x100+BUTTON_QUIT) - HELP_LINK ("Palette menu: %s", 0x100+BUTTON_PALETTE) - HELP_LINK ("2nd Palette menu: %s", 0x200+BUTTON_PALETTE) - HELP_LINK ("Exclude colors menu: %s", SPECIAL_EXCLUDE_COLORS_MENU) - HELP_TEXT ("") - HELP_TEXT ("Scroll palette") - HELP_LINK (" Back: %s", 0x100+BUTTON_PAL_LEFT) - HELP_LINK (" Forward: %s", 0x100+BUTTON_PAL_RIGHT) - HELP_LINK (" Back faster: %s", 0x200+BUTTON_PAL_LEFT) - HELP_LINK (" Forward faster: %s", 0x200+BUTTON_PAL_RIGHT) - HELP_TEXT ("") - HELP_TEXT ("Change brush attachement") - HELP_LINK (" Center : %s", SPECIAL_CENTER_ATTACHMENT) - HELP_LINK (" Top-left : %s", SPECIAL_TOP_LEFT_ATTACHMENT) - HELP_LINK (" Top-right : %s", SPECIAL_TOP_RIGHT_ATTACHMENT) - HELP_LINK (" Bottom-left : %s", SPECIAL_BOTTOM_LEFT_ATTACHMENT) - HELP_LINK (" Bottom-right: %s", SPECIAL_BOTTOM_RIGHT_ATTACHMENT) - HELP_TEXT ("") - HELP_TEXT ("Select foreground color") - HELP_TEXT ("") - HELP_LINK (" Next : %s", SPECIAL_NEXT_FORECOLOR) - HELP_LINK (" Previous: %s", SPECIAL_PREVIOUS_FORECOLOR) - HELP_TEXT ("") - HELP_TEXT ("Select background color") - HELP_LINK (" Next : %s", SPECIAL_NEXT_BACKCOLOR) - HELP_LINK (" Previous: %s", SPECIAL_PREVIOUS_BACKCOLOR) - HELP_TEXT ("") - HELP_TEXT ("Select user-defined foreground color") - HELP_TEXT ("") - HELP_LINK (" Next : %s", SPECIAL_NEXT_USER_FORECOLOR) - HELP_LINK (" Previous: %s", SPECIAL_PREVIOUS_USER_FORECOLOR) - HELP_TEXT ("") - HELP_TEXT ("Select user-defined background color") - HELP_LINK (" Next : %s", SPECIAL_NEXT_USER_BACKCOLOR) - HELP_LINK (" Previous: %s", SPECIAL_PREVIOUS_USER_BACKCOLOR) - HELP_TEXT ("") -}; -static const T_Help_table helptable_credits[] = -{ -//HELP_TEXT ("0----5----0----5----0----5----0----5----0--X") - HELP_TITLE(" GRAFX2 IS CREATED BY") - HELP_TEXT ("") - HELP_BOLD (" SUNSET DESIGN") - HELP_BOLD (" AUTHORS OF GRAFX2.0 BETA 96.5%") - HELP_TEXT ("") - HELP_TEXT (" Guillaume Dorme alias \"Robinson\" (code)") - HELP_TEXT (" Karl Maritaud alias \"X-Man\" (code&gfx)") -//HELP_TEXT ("0----5----0----5----0----5----0----5----0--X") - HELP_TEXT (" (k.maritaud\100laposte.net)") // there is an \100 so the line is shorter than it looks - HELP_TEXT ("") - HELP_TEXT (" Re-licensed GrafX2 under the GPL in 2001") - HELP_TEXT ("") - HELP_BOLD (" THE GRAFX2 PROJECT TEAM") - HELP_TEXT ("") - HELP_TEXT (" Adrien Destugues (pulkomandy\100gmail.com)") - HELP_TEXT (" Yves Rizoud (yrizoud\100gmail.com)") - HELP_TEXT ("") - HELP_TEXT (" Got the source back to life in 2006") - HELP_TEXT ("") - HELP_BOLD (" ART") - HELP_TEXT ("") - HELP_TEXT (" GrafX2 logo by Made (www.m4de.com)") - HELP_TEXT (" Icons and fonts by X-Man ") - HELP_TEXT (" Additional graphics by iLKke") - HELP_TEXT ("") - HELP_TEXT (" Pixelled all the graphics") - HELP_TEXT ("") - HELP_TEXT ("") - HELP_TITLE(" OTHER MACHINES PORTS") - HELP_TEXT ("") - HELP_BOLD (" AMIGA OS 3 PORT") - HELP_TEXT ("") - HELP_TEXT (" Artur Jarosik (arturjarosik\100gmail.com)") - HELP_TEXT ("") - HELP_BOLD (" AMIGA OS 4 PORT") - HELP_TEXT ("") - HELP_TEXT (" Peter Gordon (pete\100petergordon.org.uk)") - HELP_TEXT ("") - HELP_BOLD (" AROS PORT") - HELP_TEXT ("") - HELP_TEXT (" Fernando Mastandrea (masta.uy\100gmail.com)") - HELP_TEXT (" Markus Weiss (mweiss\100id-architekten.de)") - HELP_TEXT ("") - HELP_BOLD (" FREEBSD PORT") - HELP_TEXT ("") - HELP_TEXT (" Jean-Baptiste Berlioz") - HELP_TEXT (" (tobe\100freemind-tobe.com)") - HELP_TEXT ("") - HELP_BOLD (" HAIKU OS AND BEOS PORT") - HELP_TEXT ("") - HELP_TEXT (" Luc Schrijvers (begasus\100skynet.be)") - HELP_TEXT ("") - HELP_BOLD (" MAC OS X PORT") - HELP_TEXT ("") - HELP_TEXT (" Franck Charlet (hitchhikr\100australia.edu)") - HELP_TEXT ("") - HELP_BOLD (" MORPHOS PORT") - HELP_TEXT ("") - HELP_TEXT (" Rusback (rusback\100wanadoo.fr)") - HELP_TEXT ("") - HELP_BOLD (" SKYOS PORT") - HELP_TEXT ("") - HELP_TEXT (" Luc Schrijvers (begasus\100skynet.be)") - HELP_TEXT ("") - HELP_TEXT (" Made it work on your favourite toaster") - HELP_TEXT ("") - HELP_TEXT ("") - HELP_TITLE(" BUGFINDERS") - HELP_TEXT ("") -//HELP_TEXT ("0----5----0----5----0----5----0----5----0--X") - HELP_TEXT (" BDCIron Ced El Topo ") - HELP_TEXT (" fallenblood Frost Grimmy ") - HELP_TEXT (" Gürkan Sengün HoraK-FDF iLKke ") - HELP_TEXT (" keito kusma Lord Graga ") - HELP_TEXT (" MagerValp mind MooZ ") - HELP_TEXT (" richienyhus TeeEmCee tempest ") - HELP_TEXT (" Timo Kurrpa titus^Rab Tobé ") - HELP_TEXT (" 00ai99 00.rgb.studios") - HELP_TEXT ("") - HELP_TEXT (" Posted the annoying bug reports.") - HELP_TEXT ("") - HELP_TEXT ("") - HELP_TITLE(" FILE FORMATS CREDITS") - HELP_TEXT ("") - HELP_TEXT (" BMP : Microsoft") - HELP_TEXT (" CEL,KCF : K.O.S. (KISekae Set system)") - HELP_TEXT (" GIF : Compuserve") - HELP_TEXT (" IMG : Bivas (W. Wiedmann?)") - HELP_TEXT (" LBM : Electronic Arts") - HELP_TEXT (" PAL : ermmh... nobody (?)") - HELP_TEXT (" PCX : Z-Soft") - HELP_TEXT (" PI1,PC1 : Degas Elite") - HELP_TEXT (" PKM : Sunset Design") - HELP_TEXT (" PNG : W3C") - HELP_TEXT (" SCx : Colorix (?)") - HELP_TEXT ("") - HELP_TEXT ("") - HELP_TITLE (" OUR HOMEPAGE") - HELP_TEXT ("") - HELP_BOLD (" http://grafx2.codegoogle.com") - HELP_TEXT ("") - HELP_TEXT (" Please report any bug you may find there") - HELP_TEXT ("") - HELP_TEXT ("") - HELP_TITLE (" GREETINGS") - HELP_TEXT ("") - HELP_TEXT (" To the Pouet.net BBS posters, the #CPC") - HELP_TEXT (" trolls and the bitfellas") - HELP_TEXT (" To every people who makes the scene alive!") - HELP_TEXT (" To all guys making nice pixelled pictures") - HELP_TEXT (" (with or without GrafX2)") - HELP_TEXT ("") - HELP_BOLD (" We send our best regards to...") - HELP_TEXT ("") - HELP_TEXT (" Access Filter Pink") - HELP_TEXT (" Ace Fiver Pixel") - HELP_TEXT (" AcidJam Flan Profil") - HELP_TEXT (" Acryl Fred Prowler") - HELP_TEXT (" Alexel FreddyV Puznik") - HELP_TEXT (" Alias Frost Quick") - HELP_TEXT (" Amiral Gaël(GDC) Ra") - HELP_TEXT (" Arrakis GainX Raster") - HELP_TEXT (" Avocado Gandalf Ravian") - HELP_TEXT (" Baloo Goblin RedBug") - HELP_TEXT (" Barti Greenpix7 Rem") - HELP_TEXT (" Bat Grid Rez") - HELP_TEXT (" Biro GrosQuick Roudoudou") - HELP_TEXT (" Bisounours HackerCroll Sacrilege") - HELP_TEXT (" BlackAxe Haplo Sam") - HELP_TEXT (" Bonnie Hof SandMan") - HELP_TEXT (" Boo Hornet Scape") - HELP_TEXT (" Boz Hulud Sébastien") - HELP_TEXT (" Carine Java Shodan") - HELP_TEXT (" Chandra JBT Skal") - HELP_TEXT (" Cheetah Jérôme Skyfire") - HELP_TEXT (" Chill Julien(JCA) Sphair") - HELP_TEXT (" Cougar KalMinDo Sprocket") - HELP_TEXT (" Cremax KaneWood Stef") - HELP_TEXT (" Cyclone Karma Stony") - HELP_TEXT (" Dake Keith303 Sumaleth") - HELP_TEXT (" Danny Lazur Sunday") - HELP_TEXT (" Danube LightShow Suny") - HELP_TEXT (" Darjul Lluvia Sybaris") - HELP_TEXT (" Darwin Louie TBF") - HELP_TEXT (" DarkAngel Luk Tempest") - HELP_TEXT (" Das Made Thor") - HELP_TEXT (" Decker Mamos TMK") - HELP_TEXT (" DerPiipo Mandrixx TwoFace") - HELP_TEXT (" Destop Mangue Underking") - HELP_TEXT (" Diabolo Mars Unreal") - HELP_TEXT (" DineS Mephisto VaeVictis") - HELP_TEXT (" Drac Mercure Vastator") - HELP_TEXT (" DrYes Mirec Vatin") - HELP_TEXT (" Edyx Moa Veckman") - HELP_TEXT (" Eller Moxica Wain") - HELP_TEXT (" Ellyn MRK Wally") - HELP_TEXT (" EOF Nitch WillBe") - HELP_TEXT (" Fall Noal Xoomie") - HELP_TEXT (" Fame Nytrik Xtrm") - HELP_TEXT (" Fantom Optic YannSulu") - HELP_TEXT (" Fear Orome Z") - HELP_TEXT (" Feather Pahladin Zeb") - HELP_TEXT (" Fennec Phar Zebig") - HELP_TEXT ("") - HELP_TEXT (" and all #pixel, #demofr and #coders.") - HELP_TEXT ("") - HELP_TEXT ("") - HELP_TITLE (" SNAIL MAIL") - HELP_TEXT ("") - HELP_TEXT (" (From 2001, current status: unknown)") - HELP_TEXT ("") - HELP_TEXT (" GUILLAUME DORME (Robinson)") - HELP_TEXT (" 15, rue de l'observatoire") - HELP_TEXT (" 87000 LIMOGES (FRANCE)") - HELP_TEXT ("") - HELP_TEXT (" KARL MARITAUD (X-Man)") - HELP_TEXT (" 10, rue de la Brasserie") - HELP_TEXT (" 87000 LIMOGES (FRANCE)") - HELP_TEXT ("") - HELP_TEXT ("") - HELP_TITLE(" THANKS") - HELP_TEXT ("") - HELP_TEXT (" Some information taken from several docs") - HELP_TEXT (" (PCGPE, Intervue, PC Interdit...)") - HELP_TEXT (" gave us an invaluable help.") - HELP_TEXT ("") - HELP_TEXT (" Thanks to Shawn Hargreaves for his filled") - HELP_TEXT (" polygon routine from Allegro v2.2.") - HELP_TEXT ("") - HELP_TEXT (" Thanks to Carlos \"Made\" Pardo for his") - HELP_TEXT (" great GrafX2 logo.") - HELP_TEXT ("") - HELP_TEXT (" This is our very first program compiled") - HELP_TEXT (" with the Gnu C Compiler.") - HELP_TEXT (" A thousand thanks to the authors of") - HELP_TEXT (" this compiler.") - HELP_TEXT ("") - HELP_TEXT (" We also would like to thank all the") - HELP_TEXT (" people who gave us ideas to improve") - HELP_TEXT (" GrafX2.") - HELP_TITLE("") -}; -static const T_Help_table helptable_paintbrush[] = -{ - HELP_TITLE("PAINTBRUSHES") - HELP_TEXT ("") - HELP_BOLD (" LEFT CLICK") - HELP_LINK ("(Key:%s)",0x100+BUTTON_PAINTBRUSHES) - HELP_TEXT ("") - HELP_TEXT ("Displays a menu where you can choose the") - HELP_TEXT ("shape of your paintbrush.") - HELP_TEXT ("") - HELP_TEXT ("Paintbrushes are sorted by family. You can") - HELP_TEXT ("see some paintbrushes of the same family but") - HELP_TEXT ("with different sizes. There is at least one") - HELP_TEXT ("paint-brush from each family displayed in") - HELP_TEXT ("this menu.") - HELP_TEXT ("Here is the list of all the different") - HELP_TEXT ("paintbrush families:") - HELP_TEXT ("") - HELP_TEXT ("******* *** * * * * * * ") - HELP_TEXT ("******* ***** * * * * * * ") - HELP_TEXT ("******* ******* * * * * * * * * ") - HELP_TEXT ("******* ******* * * * * * * ") - HELP_TEXT ("******* ******* * * * * * * * * ") - HELP_TEXT ("******* ***** * * * * * * ") - HELP_TEXT ("******* *** * * * * * * ") - HELP_TEXT ("") - HELP_TEXT ("Square Disc Sieve Sieve ") - HELP_TEXT (" square disc ") - HELP_TEXT (" ") - HELP_TEXT (" * * * ") - HELP_TEXT (" *** * * * ") - HELP_TEXT (" ***** * * ") - HELP_TEXT ("******* ******* * ") - HELP_TEXT (" ***** * * * * ") - HELP_TEXT (" *** * ") - HELP_TEXT (" * * * * ") - HELP_TEXT (" ") - HELP_TEXT ("Diamond Random Horiz. Vertical") - HELP_TEXT (" bar bar ") - HELP_TEXT ("") - HELP_TEXT ("") - HELP_TEXT (" * * * * *") - HELP_TEXT (" * * * * *") - HELP_TEXT (" * * * * *") - HELP_TEXT (" * * * *******") - HELP_TEXT (" * * * * *") - HELP_TEXT (" * * * * *") - HELP_TEXT ("* * * * *") - HELP_TEXT ("") - HELP_TEXT (" Slash Back- Cross X Cross +") - HELP_TEXT (" slash") - HELP_TEXT ("") - HELP_TEXT ("When using one of these, you can change the") - HELP_TEXT ("brush size by using the keys:") - HELP_LINK ("Reduce : %s", SPECIAL_SMALLER_PAINTBRUSH) - HELP_LINK ("Increase : %s", SPECIAL_BIGGER_PAINTBRUSH) - HELP_TEXT ("The last 3 paintbrushes in the menu belong") - HELP_TEXT ("to the \"miscellaneous\" family and their size") - HELP_TEXT ("cannot be modified.") - HELP_TEXT ("") - HELP_BOLD (" RIGHT CLICK ") - HELP_LINK ("(Key:%s)",0x200+BUTTON_PAINTBRUSHES) - HELP_TEXT ("") - HELP_TEXT ("Transforms your current user-defined brush") - HELP_TEXT ("into a paintbrush. This is actually a") - HELP_TEXT ("\"monochromisation\" of your user-defined") - HELP_TEXT ("brush. This means that every color of the") - HELP_TEXT ("brush that aren't the Back-color will be") - HELP_TEXT ("set to the Fore-color. But this option") - HELP_TEXT ("doesn't alter the brush: you'll just have") - HELP_TEXT ("to right-click on the \"Get brush\" buttons") - HELP_TEXT ("to get your brush back.") - HELP_TEXT ("") - HELP_TEXT ("Note: When you press (not in the menu) the") - HELP_LINK ("key %s, the current",SPECIAL_DOT_PAINTBRUSH) - HELP_TEXT ("paintbrush becomes the smallest member of") - HELP_TEXT ("the \"Disc\" family: i.e one pixel.") - -}; -static const T_Help_table helptable_adjust[] = -{ - HELP_TITLE("ADJUST OR TRANSFORM") - HELP_TITLE(" PICTURE") - HELP_TEXT ("") - HELP_BOLD (" LEFT CLICK") - HELP_LINK ("(Key:%s)",0x100+BUTTON_ADJUST) - HELP_TEXT ("") - HELP_TEXT ("Allows you to scroll the picture to") - HELP_TEXT ("re-center your graph for example.") - HELP_TEXT ("") - HELP_TEXT ("Any part of the picture that goes out of") - HELP_TEXT ("the image by a side comes back by the") - HELP_TEXT ("opposite one.") - HELP_TEXT ("") - HELP_TEXT ("It is assimilated to the drawing tools") - HELP_TEXT ("family.") - HELP_TEXT ("") - HELP_TEXT ("") - HELP_BOLD (" RIGHT CLICK") - HELP_LINK ("(Key:%s)",0x200+BUTTON_ADJUST) - HELP_TEXT ("") - HELP_TEXT ("Opens the Picture Transform menu.") - HELP_TEXT ("") - HELP_TEXT ("") - HELP_TITLE("PICTURE TRANSFORM") - HELP_TEXT ("") - HELP_BOLD ("RESCALE") - HELP_TEXT ("") - HELP_TEXT ("Allows you to change the image's size,") - HELP_TEXT ("rescaling it accordingly. Enter new size") - HELP_TEXT ("and press RESIZE to confirm.") - HELP_TEXT ("") - HELP_TEXT ("") - HELP_TEXT ("When 'Lock proportions' is checked and you") - HELP_TEXT ("change one dimension, the other one is") - HELP_TEXT ("automatically adjusted to preserve the") - HELP_TEXT ("proportions of the original image.") - HELP_TEXT ("") - HELP_TEXT ("You can use the dropdown button to choose") - HELP_TEXT ("between three ways to enter the dimensions:") - HELP_TEXT ("") - HELP_TEXT ("In 'Pixels' mode, the column 'old' shows") - HELP_TEXT ("the original dimensions, and you can set") - HELP_TEXT ("the new size in pixels.") - HELP_TEXT ("") - HELP_TEXT ("In 'Percent' mode, you set a percentage") - HELP_TEXT ("compared to the original image.") - HELP_TEXT ("") - HELP_TEXT ("In 'Ratio' mode, you can set 2 numbers for") - HELP_TEXT ("each dimension, and the resizing factor will") - HELP_TEXT ("be of 'new'÷'old'. For example you can use") - HELP_TEXT ("1:3 to divide the image by three, 2:1 to") - HELP_TEXT ("double it, and any fraction like 15:16.") - HELP_TEXT ("") - HELP_TEXT ("Be careful that moving from one mode to the") - HELP_TEXT ("next can lose precision, if the selected") - HELP_TEXT ("dimensions cannot be represented exactly in") - HELP_TEXT ("the new mode.") - HELP_TEXT ("") - HELP_BOLD ("MIRROR") - HELP_TEXT ("") - HELP_TEXT ("- X: Flip the picture horizontally.") - HELP_TEXT ("") - HELP_TEXT ("- Y: Flip the picture vertically.") - HELP_TEXT ("") - HELP_BOLD ("ROTATE") - HELP_TEXT ("") - HELP_TEXT ("-90°: Rotates the image by 90°") - HELP_TEXT (" clockwise.") - HELP_TEXT ("") - HELP_TEXT ("+90°: Rotates the image by 90°") - HELP_TEXT (" counter-clockwise.") - HELP_TEXT ("180°: Rotates the image by 180°") - HELP_TEXT ("") - HELP_TEXT ("") -}; -static const T_Help_table helptable_draw[] = -{ - HELP_TITLE("HAND-DRAWING") - HELP_TEXT ("") - HELP_BOLD (" LEFT CLICK") - HELP_LINK ("(Key:%s)",0x100+BUTTON_DRAW) - HELP_TEXT ("") - HELP_TEXT ("Selects the current hand-drawing mode as the") - HELP_TEXT ("active drawing tool. There are 4") - HELP_TEXT ("hand-drawing modes:") - HELP_TEXT ("") - HELP_TEXT ("Continuous hand-drawing: as you move the") - HELP_TEXT ("mouse, the paintbrush is regularily pasted") - HELP_TEXT ("on the picture. This drawing tool allows to") - HELP_TEXT ("change the fore and back colors when being") - HELP_TEXT ("in use.") - HELP_TEXT ("") - HELP_TEXT ("Discontinuous hand-drawing: as you move the") - HELP_TEXT ("mouse, the paintbrush is pasted on the") - HELP_TEXT ("picture every time a delay is passed") - HELP_TEXT ("(actually, the delay is 1 VBL") - HELP_TEXT ("(vertical blanking)). This drawing tool") - HELP_TEXT ("allows to change the fore and back colors") - HELP_TEXT ("when being in use.") - HELP_TEXT ("") - HELP_TEXT ("Dot by dot hand-drawing: the paintbrush is") - HELP_TEXT ("only pasted at the position where you first") - HELP_TEXT ("clicked.") - HELP_TEXT ("") - HELP_TEXT ("Contour fill: Draws pixels like continuous") - HELP_TEXT ("mode, but when you release the button Grafx2") - HELP_TEXT ("draws a line back to your starting position,") - HELP_TEXT ("and fills the area. This tool doesn't use the") - HELP_TEXT ("current brush, but single pixels.") - HELP_TEXT ("") - HELP_BOLD (" RIGHT CLICK") - HELP_LINK ("(Key:%s)",0x200+BUTTON_DRAW) - HELP_TEXT ("") - HELP_TEXT ("Toggles the different hand-drawing modes") - HELP_TEXT ("and activates, at the same time, the") - HELP_TEXT ("hand-drawing tool.") -}; -static const T_Help_table helptable_curves[] = -{ - HELP_TITLE("SPLINES") - HELP_TEXT ("") - HELP_BOLD ("LEFT CLICK") - HELP_LINK ("(Key:%s)",0x100+BUTTON_CURVES) - HELP_TEXT ("") - HELP_TEXT ("Selects the current curve-drawing mode as") - HELP_TEXT ("the active drawing tool. There are 2") - HELP_TEXT ("different curve-drawing modes:") - HELP_TEXT ("") - HELP_TEXT ("* 4 control points curves: define the basic") - HELP_TEXT ("line like a classical line, then move, with") - HELP_TEXT ("the left mouse button, the inner control") - HELP_TEXT ("points to choose the shape of your curve.") - HELP_TEXT ("When the curve has the shape you want, click") - HELP_TEXT ("with the right mouse button to draw it") - HELP_TEXT ("definitively.") - HELP_TEXT ("") - HELP_TEXT ("* 3 control points curves: the same as") - HELP_TEXT ("above, but you'll have only one inner") - HELP_TEXT ("control point to place. Moreover, the spline") - HELP_TEXT ("will be traced just after placing this") - HELP_TEXT ("point.") - HELP_TEXT ("") - HELP_BOLD ("RIGHT CLICK") - HELP_LINK ("(Key:%s)",0x200+BUTTON_CURVES) - HELP_TEXT ("") - HELP_TEXT ("Toggles the different curve-drawing modes") - HELP_TEXT ("and activates, at the same time, the") - HELP_TEXT ("curve-drawing tool.") -}; -static const T_Help_table helptable_lines[] = -{ - HELP_TITLE("LINES") - HELP_TEXT ("") - HELP_BOLD ("LEFT CLICK") - HELP_LINK ("(Key:%s)",0x100+BUTTON_LINES) - HELP_TEXT ("") - HELP_TEXT ("Selects the current line-drawing mode as the") - HELP_TEXT ("active drawing tool. There are 3") - HELP_TEXT ("line-drawing modes:") - HELP_TEXT ("") - HELP_TEXT ("* Classical lines: when first clicking on") - HELP_TEXT ("the picture, you'll define the start of the") - HELP_TEXT ("line. Maintain your click to choose the end") - HELP_TEXT ("of the line and release the mouse button to") - HELP_TEXT ("set it.") - HELP_TEXT ("If you hold SHIFT when drawing, the line") - HELP_TEXT ("will be constrained to horizonal, vertical") - HELP_TEXT ("or diagonal.") - HELP_TEXT ("") - HELP_TEXT ("* Knotted lines: works like classical lines,") - HELP_TEXT ("but the end of your line will automatically") - HELP_TEXT ("become the start of the next one. When you") - HELP_TEXT ("want to stop chaining lines, use the") - HELP_TEXT ("opposite mouse button. \"The opposite button\"") - HELP_TEXT ("means that if you started to draw lignes") - HELP_TEXT ("with the left button (Fore-color), you'll") - HELP_TEXT ("have to stop the procedure with the right") - HELP_TEXT ("button; and conversely.") - HELP_TEXT ("") - HELP_TEXT ("* Concentric lines: when first clicking on") - HELP_TEXT ("the picture, you'll define center of the") - HELP_TEXT ("lines. In fact, the center is defined by the") - HELP_TEXT ("the position of the mouse when you release") - HELP_TEXT ("the mouse button. Then you can draw lines") - HELP_TEXT ("from the center to the current mouse") - HELP_TEXT ("position by clicking. To stop drawing") - HELP_TEXT ("concentric lines, use the opposite mouse") - HELP_TEXT ("button. This drawing tool allows to change") - HELP_TEXT ("the fore and back colors when being in use.") - HELP_TEXT ("") - HELP_BOLD ("RIGHT CLICK") - HELP_LINK ("(Key:%s)",0x200+BUTTON_LINES) - HELP_TEXT ("") - HELP_TEXT ("Toggles the different line-drawing modes and") - HELP_TEXT ("activates, at the same time, the") - HELP_TEXT ("line-drawing tool.") - -}; -static const T_Help_table helptable_airbrush[] = -{ - HELP_TITLE("SPRAY") - HELP_TEXT ("") - HELP_BOLD ("LEFT CLICK") - HELP_LINK ("(Key:%s)",0x100+BUTTON_AIRBRUSH) - HELP_TEXT ("") - HELP_TEXT ("Selects the spray as the active drawing") - HELP_TEXT ("tool. This drawing tool allows to change the") - HELP_TEXT ("fore and back colors when being in use.") - HELP_TEXT ("") - HELP_BOLD ("RIGHT CLICK") - HELP_LINK ("(Key:%s)",0x200+BUTTON_AIRBRUSH) - HELP_TEXT ("") - HELP_TEXT ("Displays a menu where you can configure the") - HELP_TEXT ("spray:") - HELP_TEXT ("") - HELP_TEXT ("- Size: Defines the diameter of the circle") - HELP_TEXT ("in which will effectively fit the spray.") - HELP_TEXT ("") - HELP_TEXT ("- Delay: Defines the number of VBLs that") - HELP_TEXT ("will be waited for between two flows of") - HELP_TEXT ("spray.") - HELP_TEXT ("") - HELP_TEXT ("- Mode: Defines whether you want to use a") - HELP_TEXT ("monochrome spray or a multi- colored one.") - HELP_TEXT ("") - HELP_TEXT ("- Mono-flow: Defines the number of") - HELP_TEXT ("paintbrushes that will be pasted in the") - HELP_TEXT ("circle of the spray at each cycle.") - HELP_TEXT ("") - HELP_TEXT ("- Palette: Left-click on a color of the") - HELP_TEXT ("palette to see how much it will be used in") - HELP_TEXT ("the multicolored flow, and modify it by") - HELP_TEXT ("using the gauge on the right. If the flow of") - HELP_TEXT ("this color was equal to 0, then the \"Init\"") - HELP_TEXT ("value will be applied. Or set the flow of a") - HELP_TEXT ("color to 0 by clicking on it with the right") - HELP_TEXT ("mouse button.") - HELP_TEXT ("") - HELP_TEXT ("- Clear: Removes all the colors from the") - HELP_TEXT ("multicolored flow. Actually, this puts a 0") - HELP_TEXT ("value in the use of each color.") - HELP_TEXT ("") - HELP_TEXT ("- Init: Allows you to define a value that") - HELP_TEXT ("will be set to the color you click on in the") - HELP_TEXT ("palette if its value is equal to 0. This") - HELP_TEXT ("permits to tag a set of colors more quickly.") - HELP_TEXT ("") - HELP_TEXT ("- +1,-1,x2,/2: Modify the values of all the") - HELP_TEXT ("tagged colors (and only them).") - HELP_TEXT ("") - HELP_TEXT ("") - HELP_TEXT ("Tip: If you often use the Shade mode, and") - HELP_TEXT ("are bored to click many times on a color to") - HELP_TEXT ("reach the color you want, you can define a") - HELP_TEXT ("spray with \"Size\"=1, \"Mono-flow\"=1, and") - HELP_TEXT ("\"Delay\"=2 (or more, according to your") - HELP_TEXT ("reflexes). And then, you'll just have to") - HELP_TEXT ("click a few hundredths of second to modify a") - HELP_TEXT ("color.") -}; -static const T_Help_table helptable_floodfill[] = -{ - HELP_TITLE("FLOODFILL") - HELP_TEXT ("") - HELP_BOLD ("LEFT CLICK") - HELP_LINK ("(Key:%s)",0x100+BUTTON_FLOODFILL) - HELP_TEXT ("") - HELP_TEXT ("Selects the filler as the active drawing") - HELP_TEXT ("tool. The filler, as any drawing tool, will") - HELP_TEXT ("be affected by all the effects!") - HELP_TEXT ("") - HELP_TEXT ("Note that only the visible part of the") - HELP_TEXT ("picture will be filled (as every other") - HELP_TEXT ("drawing tools, the floodfill only alters the") - HELP_TEXT ("visible part of the picture; this avoids") - HELP_TEXT ("unwanted effects that wouldn't be controlled") - HELP_TEXT ("by the user).") - HELP_TEXT ("") - HELP_BOLD ("RIGHT CLICK") - HELP_LINK ("(Key:%s)",0x200+BUTTON_FLOODFILL) - HELP_TEXT ("") - HELP_TEXT ("Selects the color replacement as the active") - HELP_TEXT ("drawing tool.") - HELP_TEXT ("") - HELP_TEXT ("Any rule has its exceptions and this one") - HELP_TEXT ("doesn't depart from that. Indeed, this tool") - HELP_TEXT ("is the only one to be affected by no effect") - HELP_TEXT ("(except Stencil) and to be able to modify") - HELP_TEXT ("non visible parts of the picture.") - HELP_TEXT ("The function of this tool being replacing") - HELP_TEXT ("all the occurences of a color in the picture") - HELP_TEXT ("by another, if would have been a shame to") - HELP_TEXT ("limit modifications only to the visible part") - HELP_TEXT ("of the picture.") -}; -static const T_Help_table helptable_polygons[] = -{ - HELP_TITLE("POLYGONS") - HELP_TITLE("POLYFORMS") - HELP_BOLD ("LEFT CLICK") - HELP_LINK ("(Key:%s)",0x100+BUTTON_POLYGONS) - HELP_TEXT ("") - HELP_TEXT ("Selects the polygons as the active drawing") - HELP_TEXT ("tool.") - HELP_TEXT ("") - HELP_TEXT ("This works just like knotted-lines but loops") - HELP_TEXT ("the extremities when you're finished.") - HELP_TEXT ("") - HELP_BOLD ("RIGHT CLICK") - HELP_LINK ("(Key:%s)",0x200+BUTTON_POLYGONS) - HELP_TEXT ("") - HELP_TEXT ("Selects the polyforms as the active drawing") - HELP_TEXT ("tool.") - HELP_TEXT ("") - HELP_TEXT ("This works like a combination of free-hand") - HELP_TEXT ("drawing and knotted-lines. If you keep the") - HELP_TEXT ("mouse button pressed, you'll draw as if you") - HELP_TEXT ("were in free-hand drawing mode. And, if you") - HELP_TEXT ("release the mouse button, it will work like") - HELP_TEXT ("knotted lines.") - HELP_TEXT ("") - HELP_TEXT ("Click on the opposite mouse button (i.e.:") - HELP_TEXT ("click right if you started to draw with the") - HELP_TEXT ("left mouse button, and vice versa) to") - HELP_TEXT ("terminate the operation. The two extremities") - HELP_TEXT ("will be linked automatically.") -}; -static const T_Help_table helptable_polyfill[] = -{ - HELP_TITLE("FILLED POLY") - HELP_LINK ("(Key:%s)",0x100+BUTTON_POLYFILL) - HELP_LINK ("(Key:%s)",0x200+BUTTON_POLYFILL) - HELP_TEXT (" Work exactly the same way as the polygons") - HELP_TEXT ("et polyforms above, but fill in the interior") - HELP_TEXT ("of the drawn shapes.") -}; -static const T_Help_table helptable_rectangles[] = -{ - HELP_TITLE("RECTANGLES") - HELP_LINK ("(Key:%s)",0x100+BUTTON_RECTANGLES) - HELP_TEXT ("") - HELP_TEXT ("Selects the empty rectangles as the active") - HELP_TEXT ("drawing tool.") - HELP_TEXT ("") - HELP_TEXT ("Set a corner of a rectangle. Maintain the") - HELP_TEXT ("click to move the opposite corner and") - HELP_TEXT ("release the mouse button to set it") - HELP_TEXT ("definitively.") -}; -static const T_Help_table helptable_filled_rectangles[] = -{ - HELP_TITLE("FILLED RECT") - HELP_LINK ("(Key:%s)",0x100+BUTTON_FILLRECT) - HELP_TEXT ("") - HELP_TEXT ("Selects the filled rectangles as the active") - HELP_TEXT ("drawing tool.") - HELP_TEXT ("") - HELP_TEXT ("Works like an empty rectangle.") -}; -static const T_Help_table helptable_circles[] = -{ - HELP_TITLE("CIRCLES") - HELP_TITLE("ELLIPSES") - HELP_TEXT ("") - HELP_BOLD ("LEFT CLICK") - HELP_LINK ("(Key:%s)",0x100+BUTTON_CIRCLES) - HELP_TEXT ("") - HELP_TEXT ("Selects the empty circles as the active") - HELP_TEXT ("drawing tool.") - HELP_TEXT ("") - HELP_TEXT ("Position the center of the cercle and") - HELP_TEXT ("maintain the mouse button to select its") - HELP_TEXT ("radius.") - HELP_TEXT ("") - HELP_BOLD ("RIGHT CLICK") - HELP_LINK ("(Key:%s)",0x200+BUTTON_CIRCLES) - HELP_TEXT ("") - HELP_TEXT ("Selects the empty ellipses as the active") - HELP_TEXT ("drawing tool.") - HELP_TEXT ("") - HELP_TEXT ("Position the center of the cercle and") - HELP_TEXT ("maintain the mouse button to select its") - HELP_TEXT ("dimensions.") -}; -static const T_Help_table helptable_filled_circles[] = -{ - HELP_TITLE("FILLED CIRCLES") - HELP_TITLE(" AND ELLIPSES") - HELP_TEXT ("") - HELP_BOLD ("FILLED CIRCLES") - HELP_LINK ("(Key:%s)",0x100+BUTTON_CIRCLES) - HELP_TEXT ("") - HELP_TEXT ("Works like empty circles.") - HELP_TEXT ("") - HELP_BOLD ("FILLED ELLIPSES") - HELP_LINK ("(Key:%s)",0x200+BUTTON_CIRCLES) - HELP_TEXT ("") - HELP_TEXT ("Works like empty ellipses.") -}; -static const T_Help_table helptable_grad_rect[] = -{ - HELP_TITLE("GRAD RECTANGLE") - HELP_TEXT ("") - HELP_LINK ("(Key:%s)",0x100+BUTTON_GRADRECT) - HELP_TEXT ("") - HELP_TEXT ("Selects the rectangle with gradations as") - HELP_TEXT ("the active drawing tool.") - HELP_TEXT ("") - HELP_TEXT ("Set a corner of a rectangle. Maintain the") - HELP_TEXT ("click to move the opposite corner and") - HELP_TEXT ("release the mouse button to set it") - HELP_TEXT ("definitively.") - HELP_TEXT ("") - HELP_TEXT ("If you don't like what you have done and") - HELP_TEXT ("want to restart, you can use the right") - HELP_TEXT ("click to cancel everything at this point.") - HELP_TEXT (" If you think it's nice, then click and hold") - HELP_TEXT ("the mouse in a point you want to have the") - HELP_TEXT ("starting color, drag to a point where you") - HELP_TEXT ("want the ending color, and release the") - HELP_TEXT ("button. You can press SHIFT to enforce your") - HELP_TEXT ("line to be vertical, horizontal, or") - HELP_TEXT ("diagonal.") -}; -static const T_Help_table helptable_grad_menu[] = -{ - HELP_TITLE("GRAD MENU") - HELP_TEXT ("") - HELP_LINK ("(Key:%s)",0x100+BUTTON_GRADMENU) - HELP_TEXT ("") - HELP_TEXT ("Opens a window where you can define the way") - HELP_TEXT ("gradations are processed. The different") - HELP_TEXT ("sections of this menu are:") - HELP_TEXT ("") - HELP_TEXT ("- Direction (arrow): Switches the direction") - HELP_TEXT ("of the gradation.") - HELP_TEXT ("") - HELP_TEXT ("- Dithering method: Toggles the 3 following") - HELP_TEXT ("methods:") - HELP_TEXT (" - No dithering") - HELP_TEXT (" - Basical dithering") - HELP_TEXT (" - Enhanced dithering") - HELP_TEXT ("") - HELP_TEXT ("- Mix: Mixes the gradation with a more or") - HELP_TEXT ("less random factor.") - HELP_TEXT ("") - HELP_TEXT ("- Palette: Select a color range to build a") - HELP_TEXT ("gradation.") - HELP_TEXT ("") - HELP_TEXT ("- Index scroller: Defines the current") - HELP_TEXT ("gradation among a set of 16 that will be") - HELP_TEXT ("memorised.") -}; -static const T_Help_table helptable_spheres[] = -{ - HELP_TITLE("GRAD SPHERE") - HELP_BOLD ("LEFT CLICK") - HELP_LINK ("(Key:%s)",0x100+BUTTON_SPHERES) - HELP_TEXT ("") - HELP_TEXT ("Selects the spheres as the active drawing") - HELP_TEXT ("tool.") - HELP_TEXT ("") - HELP_TEXT ("Position the center of the sphere and") - HELP_TEXT ("maintain the mouse button to select its") - HELP_TEXT ("radius. Then place the spot-light.") - HELP_TEXT ("") - HELP_BOLD ("RIGHT CLICK") - HELP_LINK ("(Key:%s)",0x200+BUTTON_SPHERES) - HELP_TEXT ("") - HELP_TEXT ("Selects the ellipses with gradation as the") - HELP_TEXT ("active drawing tool.") - HELP_TEXT ("") - HELP_TEXT ("Draw the shape like a normal ellipse, and") - HELP_TEXT ("then position the spot-light and click the") - HELP_TEXT ("left mouse button to finish the shape.") - HELP_TEXT ("") - HELP_TEXT ("") - HELP_TEXT ("If you trace a sphere or an ellipse with") - HELP_TEXT ("gradation with the right mouse button, the") - HELP_TEXT ("result will be the same figure filled with") - HELP_TEXT ("the Back-color.") -}; -static const T_Help_table helptable_brush[] = -{ - HELP_TITLE("GRAB BRUSH") - HELP_BOLD (" OR RESTORE BRUSH") - HELP_TEXT ("") - HELP_BOLD ("LEFT CLICK") - HELP_LINK ("(Key:%s)",0x100+BUTTON_BRUSH) - HELP_TEXT ("") - HELP_TEXT ("Engages a brush grabbing.") - HELP_TEXT ("") - HELP_TEXT ("Click on a corner of the rectangle") - HELP_TEXT ("containing the brush then maintain the click") - HELP_TEXT ("to define the opposite corner of the") - HELP_TEXT ("rectangle. Release the mouse button to grab") - HELP_TEXT ("the brush. Performing this operation with") - HELP_TEXT ("the right mouse button will erase the area") - HELP_TEXT ("where the brush was grabbed with the") - HELP_TEXT ("Back-color.") - HELP_TEXT ("") - HELP_BOLD ("RIGHT CLICK") - HELP_LINK ("(Key:%s)",0x200+BUTTON_BRUSH) - HELP_TEXT ("") - HELP_TEXT ("Restores the old brush.") -}; -static const T_Help_table helptable_polybrush[] = -{ - HELP_TITLE("POLY GRAB") - HELP_TEXT ("") - HELP_BOLD ("LEFT CLICK") - HELP_LINK ("(Key:%s)",0x100+BUTTON_POLYBRUSH) - HELP_TEXT ("") - HELP_TEXT ("Grabs a brush of any shape by defining a") - HELP_TEXT ("polyform (please refer to section 8 for more") - HELP_TEXT ("explanations).") - HELP_TEXT ("") - HELP_BOLD ("RIGHT CLICK") - HELP_LINK ("(Key:%s)",0x200+BUTTON_BRUSH) - HELP_TEXT ("") - HELP_TEXT ("Restores the old brush (same as above).") -}; -static const T_Help_table helptable_brush_fx[] = -{ - HELP_TITLE("BRUSH FX") - HELP_TEXT ("") - HELP_LINK ("(Key:%s)",0x100+BUTTON_BRUSH_EFFECTS) - HELP_TEXT ("") - HELP_TEXT ("Displays a menu where the following options") - HELP_TEXT ("are available:") - HELP_TEXT ("") - HELP_LINK ("- X: (Key:%s)",SPECIAL_FLIP_X) - HELP_TEXT ("Flip horizontally.") - HELP_TEXT ("") - HELP_LINK ("- Y: (Key:%s)",SPECIAL_FLIP_Y) - HELP_TEXT ("Flip vertically.") - HELP_TEXT ("") - HELP_LINK ("- Rotate by 90°: (Key:%s)",SPECIAL_ROTATE_90) - HELP_TEXT ("Rotates the brush by an angle of 90 degrees.") - HELP_TEXT ("") - HELP_LINK ("- Rotate by 180°: (Key:%s)",SPECIAL_ROTATE_180) - HELP_TEXT ("Rotates the brush by an angle of 180") - HELP_TEXT ("degrees.") - HELP_TEXT ("") - HELP_TEXT ("- Rotate by any angle:") - HELP_LINK ("(Key:%s)",SPECIAL_ROTATE_ANY_ANGLE) - HELP_TEXT ("Triggers an interactive operation that") - HELP_TEXT ("allows you to rotate the brush. For this,") - HELP_TEXT ("start by placing the center or rotation with") - HELP_TEXT ("the left mouse button (if, at this moment,") - HELP_TEXT ("you press the right button, the operation") - HELP_TEXT ("with be cancelled). After that, you can") - HELP_TEXT ("define the angle of rotation as many times") - HELP_TEXT ("as you want by moving the mouse and") - HELP_TEXT ("left-clicking. Then validate with the right") - HELP_TEXT ("button when you are satisfied. Meanwhile,") - HELP_TEXT ("you can press on the 8 outer digits of the") - HELP_TEXT ("numeric pad for defining angles multiple of") - HELP_TEXT ("45 degrees:") - HELP_TEXT ("") - HELP_TEXT (" 135 90 45") - HELP_TEXT (" \\ | /") - HELP_TEXT (" '7' '8' '9'") - HELP_TEXT (" 180 -'4' '6'- 0") - HELP_TEXT (" '1' '2' '3'") - HELP_TEXT (" / | \\") - HELP_TEXT (" 225 270 315") - HELP_TEXT ("") - HELP_LINK ("- Stretch: (Key:%s)",SPECIAL_STRETCH) - HELP_TEXT ("Triggers an interactive operation") - HELP_TEXT ("that enables you to stretch the brush. For") - HELP_TEXT ("this, start by placing the upper-left") - HELP_TEXT ("cornerof the brush with the left mouse") - HELP_TEXT ("button (if, at this moment, you press the") - HELP_TEXT ("right button, the operation will be") - HELP_TEXT ("cancelled). after that, you can place the") - HELP_TEXT ("opposite corner as many times as you need,") - HELP_TEXT ("then validate with the right mouse button") - HELP_TEXT ("when you are satisfied. If you place this") - HELP_TEXT ("point at coordinates inferior to the ones of") - HELP_TEXT ("the first point, the brush will be inverted.") - HELP_TEXT ("Meanwhile, you can press the following keys") - HELP_TEXT ("whose effects are: 'D' : double the") - HELP_TEXT ("brush in X and Y 'H' : reduce the") - HELP_TEXT ("brush by half in X and Y 'X' : double") - HELP_TEXT ("the brush in X 'Shift+X': reduce the brush") - HELP_TEXT ("by half in X 'Y' : double the brush") - HELP_TEXT ("in Y 'Shift+Y': reduce the brush by half") - HELP_TEXT ("in Y 'N' : restore the normal size of") - HELP_TEXT ("the brush (can be useful") - HELP_TEXT ("because it's the only way for cancelling)") - HELP_TEXT ("") - HELP_LINK ("- Distort: (Key:%s)",SPECIAL_DISTORT) - HELP_TEXT ("Triggers an interactive operation") - HELP_TEXT ("that allows you to distort your brush.") - HELP_TEXT ("Start by placing the brush somewhere on the") - HELP_TEXT ("screen and left-click. The brush will") - HELP_TEXT ("appear, with a little peg at each corner.") - HELP_TEXT ("Use the left mouse button to displace the") - HELP_TEXT ("corners, which will deform the brush.") - HELP_TEXT ("When you're done, click the right mouse") - HELP_TEXT ("button.") - HELP_TEXT ("") - HELP_LINK ("- Outline: (Key:%s)",SPECIAL_OUTLINE) - HELP_TEXT ("This option permits to draw the") - HELP_TEXT ("outlines of the brush with the Fore- color.") - HELP_TEXT ("") - HELP_LINK ("- Nibble: (Key:%s)",SPECIAL_NIBBLE) - HELP_TEXT ("This option \"nibbles\" the outlines") - HELP_TEXT ("of the brush. It's in some way the opposite") - HELP_TEXT ("effect of the Outline option.") - HELP_TEXT ("") - HELP_LINK ("- Recolorize: (Key:%s)",SPECIAL_RECOLORIZE_BRUSH) - HELP_TEXT ("Remaps the brush so that it") - HELP_TEXT ("looks like it would in the spare page, using") - HELP_TEXT ("the current palette.") - HELP_TEXT ("") - HELP_LINK ("- Get brush colors: (Key:%s)",SPECIAL_GET_BRUSH_COLORS) - HELP_TEXT ("Transfers the spare") - HELP_TEXT ("page's colors used by the brush to the") - HELP_TEXT ("current palette.") - HELP_TEXT ("") - HELP_TEXT ("- Brush handle:") - HELP_TEXT ("Allows you to choose where to place the") - HELP_TEXT ("handle of the brush. Shortcuts are :") - HELP_LINK (" Center : %s", SPECIAL_CENTER_ATTACHMENT) - HELP_LINK (" Top-left : %s", SPECIAL_TOP_LEFT_ATTACHMENT) - HELP_LINK (" Top-right : %s", SPECIAL_TOP_RIGHT_ATTACHMENT) - HELP_LINK (" Bottom-left : %s", SPECIAL_BOTTOM_LEFT_ATTACHMENT) - HELP_LINK (" Bottom-right: %s", SPECIAL_BOTTOM_RIGHT_ATTACHMENT) - HELP_TEXT ("") - HELP_LINK ("- Load : (Key:%s)",SPECIAL_LOAD_BRUSH) - HELP_TEXT ("Load a brush from disk.") - HELP_TEXT ("") - HELP_LINK ("- Save : (Key:%s)",SPECIAL_SAVE_BRUSH) - HELP_TEXT ("Save a brush to disk.") -}; -static const T_Help_table helptable_effects[] = -{ - HELP_TITLE("DRAW MODES") - HELP_LINK ("(Key:%s)",0x100+BUTTON_EFFECTS) - HELP_TEXT ("") - HELP_TEXT (" This button opens a menu where you can") - HELP_TEXT ("switch on or off the different drawing") - HELP_TEXT ("modes.") - HELP_TEXT (" In this menu, the \"All off\" button switches") - HELP_TEXT ("all the drawing modes off. The [Del] key") - HELP_TEXT ("is the keyboard shortcut for this button.") - HELP_TEXT (" The \"Feedback\" button is only used in") - HELP_TEXT ("\"Shade\", \"Quick-shade, \"Transparency\"") - HELP_TEXT ("and \"Smooth\" modes. When it is set, it means") - HELP_TEXT ("that the _current_ state of the picture") - HELP_TEXT ("has to be taken into account for the effect") - HELP_TEXT ("instead of the state in which the image") - HELP_TEXT ("was when you started to click for drawing.") - HELP_TEXT ("The best, as often, is that you try by") - HELP_TEXT ("yourself with and without Feedback to see") - HELP_TEXT ("the difference.") - HELP_TEXT (" The other buttons are the following:") - HELP_TEXT ("") - HELP_TITLE("SHADE") - HELP_TEXT (" It consists in increasing or decreasing the") - HELP_TEXT ("color number within a user-defined range.") - HELP_TEXT ("This shows its real dimension when used with") - HELP_TEXT ("a range of colors that shade off. Then,") - HELP_TEXT ("you can work on a part of your picture where") - HELP_TEXT ("colors belong to the same range without") - HELP_TEXT ("having to change your brush color all the") - HELP_TEXT ("time. You can choose the incrementation or") - HELP_TEXT ("decrementation of the color by pressing") - HELP_TEXT ("the left or right mouse button while") - HELP_TEXT ("drawing. If you click on a color that does") - HELP_TEXT ("not belong to the range, it will remain") - HELP_TEXT ("unchanged.") - HELP_BOLD ("LEFT CLICK") - HELP_LINK ("(Key : %s)", SPECIAL_SHADE_MODE) - HELP_TEXT ("") - HELP_TEXT ("Switches the Shade mode.") - HELP_TEXT ("") - HELP_BOLD ("RIGHT CLICK") - HELP_LINK ("(Key: %s)", SPECIAL_SHADE_MENU) - HELP_TEXT ("") - HELP_TEXT ("Opens a menu where you can define one table") - HELP_TEXT ("of shades within a range of 8 memorised by") - HELP_TEXT ("the program. The different sections of this") - HELP_TEXT ("menu are:") - HELP_TEXT ("") - HELP_TEXT ("- Palette: You can define in it the color") - HELP_TEXT ("blocks that will be inserted") - HELP_TEXT ("into the table of shades.") - HELP_TEXT ("") - HELP_TEXT ("- Scroller: Used to change flick through the") - HELP_TEXT ("tables of shades.") - HELP_TEXT ("") - HELP_TEXT ("- Table of shades definition area: The 512") - HELP_TEXT ("squares should be widely") - HELP_TEXT ("sufficient to define the different shades") - HELP_TEXT ("since every 256 colors of") - HELP_TEXT ("the palette cannot be present more than once") - HELP_TEXT ("in each table.") - HELP_TEXT ("") - HELP_TEXT ("- A window (on the top-right side) permits") - HELP_TEXT ("to visualize the different") - HELP_TEXT ("shades defined in he current table.") - HELP_TEXT ("") - HELP_TEXT ("- Copy: Copy the contents of the table in a") - HELP_TEXT ("buffer.") - HELP_TEXT ("(Each time you open this menu, the current") - HELP_TEXT ("table is automatically") - HELP_TEXT ("transfered into this buffer).") - HELP_TEXT ("") - HELP_TEXT ("- Paste: Copy the contents of the buffer") - HELP_TEXT ("above in the current table.") - HELP_TEXT ("") - HELP_TEXT ("- Clear: Reset the \"shades\" table.") - HELP_TEXT ("") - HELP_TEXT ("- Insert: Used to insert the block selected") - HELP_TEXT ("in the palette at the") - HELP_TEXT ("cursor's position in the table of shades.") - HELP_TEXT ("IF you click with the left mouse button on") - HELP_TEXT ("this button THEN IF a block of more than one") - HELP_TEXT ("color is selected in the table THEN It is") - HELP_TEXT ("deleted and the block defined in the palette") - HELP_TEXT ("is inserted. ELSE The block defined in the") - HELP_TEXT ("palette is inserted at the postion just") - HELP_TEXT ("before the selected square. END IF") - HELP_TEXT ("ELSE The block defined in the palette is") - HELP_TEXT ("inserted by erasing the colors following the") - HELP_TEXT ("beginning of the bloc selected in the table.") - HELP_TEXT ("END IF") - HELP_TEXT ("") - HELP_TEXT ("- Delete: Delete the block selected in the") - HELP_TEXT ("table.") - HELP_TEXT ("") - HELP_TEXT ("- Blank: Follows this algorithm:") - HELP_TEXT ("IF you click with the left mouse button on") - HELP_TEXT ("this button THEN Replace the block selected") - HELP_TEXT ("in the table by blank squares.") - HELP_TEXT ("ELSE IF a block of more than one color is") - HELP_TEXT ("selected in the table THEN Insert blank") - HELP_TEXT ("squares to the left and to the right of the") - HELP_TEXT ("block. (this is useful for isolating a") - HELP_TEXT ("shade quickly) ELSE Insert blank squares") - HELP_TEXT ("to the left of the selected square. END IF") - HELP_TEXT ("END IF") - HELP_TEXT ("") - HELP_TEXT ("- Invert: Invert the order of the block") - HELP_TEXT ("selected in the table.") - HELP_TEXT ("") - HELP_TEXT ("- Swap: Allows you you move a block (this") - HELP_TEXT ("exchanges it with what is") - HELP_TEXT ("where you want to move it).") - HELP_TEXT ("") - HELP_TEXT ("- Undo: Cancel the last modification of the") - HELP_TEXT ("table.") - HELP_TEXT ("") - HELP_TEXT ("- The 2 numbers displayed on the right of") - HELP_TEXT ("these buttons are: (above) - the number of") - HELP_TEXT ("the color selected in the palette if only") - HELP_TEXT ("one color is selected. (below) - the number") - HELP_TEXT ("of the color contained in a square in the") - HELP_TEXT ("shades table if this square is the only one") - HELP_TEXT ("selected.") - HELP_TEXT ("") - HELP_TEXT ("- The \"mode\" button displays 3 different") - HELP_TEXT ("modes:") - HELP_TEXT ("\"Normal\": Shades in the range and saturates") - HELP_TEXT ("to its boundaries.") - HELP_TEXT ("\"Loop\": Shades in the range and loops if") - HELP_TEXT ("boundaries are passed.") - HELP_TEXT ("\"No saturation\": Shades in the range and") - HELP_TEXT ("doesn't saturate if boundaries are passed.") - HELP_TEXT ("If the Step (see below) is set to 1, this") - HELP_TEXT ("option does exactly the same as the Normal") - HELP_TEXT ("mode.") - HELP_TEXT ("") - HELP_TEXT ("- Set/Disable: If you want to define several") - HELP_TEXT ("shades in the same table") - HELP_TEXT ("but you'd like these shades not to be") - HELP_TEXT ("effective at the same time, you") - HELP_TEXT ("can mask (disable) some parts of the table") - HELP_TEXT ("so that they will be") - HELP_TEXT ("interpreted a blank squares.") - HELP_TEXT ("To do that, select a block in the table of") - HELP_TEXT ("shades and click on \"Set\".") - HELP_TEXT ("The block will be underlined with a white") - HELP_TEXT ("line; this means that it is") - HELP_TEXT ("disabled.") - HELP_TEXT ("") - HELP_TEXT ("- Clear/Enable: This does exactly the") - HELP_TEXT ("opposite as the button above.") - HELP_TEXT ("") - HELP_TEXT ("- Step: Defines the step of incrementation") - HELP_TEXT ("of the shade. The bigger,") - HELP_TEXT ("the faster you run through the colors of the") - HELP_TEXT ("shade.") - HELP_TEXT ("For example: if the step is 2 and that you") - HELP_TEXT ("have defined a shade with") - HELP_TEXT ("the colors 0,1,4,5,9 and that you click on a") - HELP_TEXT ("pixel of color 1, it will") - HELP_TEXT ("take the value 5 which is 2 positions next") - HELP_TEXT ("in the la table.") - HELP_TEXT ("") - HELP_TEXT ("(We are sorry for these technical") - HELP_TEXT ("considerations quite far from a purely") - HELP_TEXT ("artistic point of view; but know that this") - HELP_TEXT ("effect is really very useful and it is") - HELP_TEXT ("preferable that you understand its whole") - HELP_TEXT ("functionment if you want to fully take") - HELP_TEXT ("advantage of it).") - HELP_TEXT ("") - HELP_TEXT ("") - HELP_TITLE("QUICK SHADE") - HELP_TEXT (" This drawing mode has about the same effect") - HELP_TEXT ("as Shade mode's except that it is faster") - HELP_TEXT ("to configurate but a little bit less") - HELP_TEXT ("powerful. When you draw on a color of the") - HELP_TEXT ("image which is between the fore- and the") - HELP_TEXT ("back-color in the palette, the color tends") - HELP_TEXT ("towards the fore-color (according to the") - HELP_TEXT ("step defined) if you draw with the left") - HELP_TEXT ("mouse button, or it tends towards the") - HELP_TEXT ("back-color if you are using the right mouse") - HELP_TEXT ("button.") - HELP_BOLD ("LEFT CLICK") - HELP_LINK ("(Key: %s)", SPECIAL_QUICK_SHADE_MODE) - HELP_TEXT ("") - HELP_TEXT ("Switches the Quick-shade mode.") - HELP_TEXT ("") - HELP_BOLD ("RIGHT CLICK") - HELP_LINK ("(Key: %s)", SPECIAL_QUICK_SHADE_MENU) - HELP_TEXT ("") - HELP_TEXT ("Opens a menu with a few parameters that mean") - HELP_TEXT ("exactly the same as in the menu of Shade") - HELP_TEXT ("mode. These parameters are the step and the") - HELP_TEXT ("loop/satu- ration mode (normal, loop, no") - HELP_TEXT ("saturation).") - HELP_TEXT ("") - HELP_TEXT ("") - HELP_TITLE("STENCIL") - HELP_TEXT (" It is used to prevent some colors from") - HELP_TEXT ("being modified if you draw on them. The") - HELP_TEXT ("main application of the stencil is when you") - HELP_TEXT ("want to change one color or more into") - HELP_TEXT ("another.") - HELP_BOLD ("LEFT CLICK") - HELP_LINK ("(Key: %s)", SPECIAL_STENCIL_MODE) - HELP_TEXT ("") - HELP_TEXT ("Switches the Stencil mode.") - HELP_TEXT ("") - HELP_BOLD ("RIGHT CLICK") - HELP_LINK ("(Key: %s)", SPECIAL_STENCIL_MENU) - HELP_TEXT ("") - HELP_TEXT ("Opens a menu where you can define a stencil.") - HELP_TEXT ("The different sections of this menu are:") - HELP_TEXT ("") - HELP_TEXT ("- Clear: No color is protected.") - HELP_TEXT ("") - HELP_TEXT ("- Invert: Colors that were protected are") - HELP_TEXT ("unprotected and vice versa.") - HELP_TEXT ("") - HELP_TEXT ("- Palette: Select colors that should be") - HELP_TEXT ("protected with the left mouse button or") - HELP_TEXT ("unprotect colors with the right mouse") - HELP_TEXT ("button.") - HELP_TEXT ("") - HELP_TEXT ("") - HELP_TITLE("MASK") - HELP_TEXT (" This effect could have been called \"True") - HELP_TEXT ("stencil\" because it protects some parts of") - HELP_TEXT ("the picture instead of some colors. The") - HELP_TEXT ("colors you tag represent the pixels in the") - HELP_TEXT ("spare page, corresponding to the pixels in") - HELP_TEXT ("the current page, that you don't want to") - HELP_TEXT ("alter. For example, draw a simple white") - HELP_TEXT ("figure on a black background in the spare") - HELP_TEXT ("page. Then, tag the black color in the menu") - HELP_TEXT ("of the Mask mode. When you'll draw in the") - HELP_TEXT ("current page, only the pixels corresponding") - HELP_TEXT ("to the white (non-black) ones in the spare") - HELP_TEXT ("page will be modified.") - HELP_BOLD ("LEFT CLICK") - HELP_LINK ("(Key: %s)", SPECIAL_MASK_MODE) - HELP_TEXT ("") - HELP_TEXT ("Switches the Mask mode.") - HELP_TEXT ("") - HELP_BOLD ("RIGHT CLICK") - HELP_LINK ("(Key: %s)", SPECIAL_MASK_MENU) - HELP_TEXT ("") - HELP_TEXT ("Opens a menu where you can set the colors of") - HELP_TEXT ("the Mask.") - HELP_TEXT ("This menu works the same way as the one of") - HELP_TEXT ("the Stencil, so please refer to the Stencil") - HELP_TEXT ("paragraph to know how to use it.") - HELP_TEXT ("") - HELP_TEXT ("") - HELP_TITLE("GRID") - HELP_TEXT (" This is useful to snap the cursor to the") - HELP_TEXT ("cross-points of a grid. It's generally") - HELP_TEXT ("used to draw a grid before drawing sprites") - HELP_TEXT ("of the same size such as a font or tiles,") - HELP_TEXT ("or for drawing figures or grabbing brushes") - HELP_TEXT ("with their dimensions multiple of the step") - HELP_TEXT ("of the grid.');") - HELP_BOLD ("LEFT CLICK") - HELP_LINK ("(Key: %s)", SPECIAL_GRID_MODE) - HELP_TEXT ("") - HELP_TEXT ("Switches the Grid mode.") - HELP_TEXT ("") - HELP_BOLD ("RIGHT CLICK") - HELP_LINK ("(Key: %s)", SPECIAL_GRID_MENU) - HELP_TEXT ("") - HELP_TEXT ("Opens a menu where you can define the grid") - HELP_TEXT ("parameters. These parameters are:") - HELP_TEXT ("") - HELP_TEXT ("- X,Y: Steps of the grid.") - HELP_TEXT ("") - HELP_TEXT ("- dX,dY: Offsets of the grid.") - HELP_TEXT ("") - HELP_TEXT ("") - HELP_TITLE("SIEVE") - HELP_TEXT (" This effect allows you, by defining a") - HELP_TEXT ("pattern, to draw only on particular points") - HELP_TEXT ("of the picture. If you are a Manga drawer,") - HELP_TEXT ("you might find this useful to make patterned") - HELP_TEXT ("shades or color transitions.") - HELP_BOLD ("LEFT CLICK") - HELP_LINK ("(Key: %s)", SPECIAL_SIEVE_MODE) - HELP_TEXT ("") - HELP_TEXT ("Switches the Sieve mode.") - HELP_TEXT ("") - HELP_BOLD ("RIGHT CLICK") - HELP_LINK ("(Key: %s)", SPECIAL_SIEVE_MENU) - HELP_TEXT ("") - HELP_TEXT ("Opens a menu where you can define the Sieve") - HELP_TEXT ("parameters. This menu consists in:") - HELP_TEXT ("") - HELP_TEXT ("- 16x16 drawing area: You can define a") - HELP_TEXT ("pattern in it (left click => white pixel /") - HELP_TEXT ("right click => black pixel). All the white") - HELP_TEXT ("pixels indicate that, when you'll draw,") - HELP_TEXT ("pixels will be applied on the picture at the") - HELP_TEXT ("corresponding positions whereas black pixels") - HELP_TEXT ("won't modify the picture: whites pixels are") - HELP_TEXT ("the \"holes of the sieve\".") - HELP_TEXT ("") - HELP_TEXT ("- 12 default patterns: They can be copied to") - HELP_TEXT ("the drawing area.") - HELP_TEXT ("") - HELP_TEXT ("- \"Transfer to brush\": Copies the pattern to") - HELP_TEXT ("the brush (white pixels => Fore-color /") - HELP_TEXT ("black pixels => Back-color).") - HELP_TEXT ("") - HELP_TEXT ("- \"Get from brush\": Puts the brush into the") - HELP_TEXT ("drawing area (back-color => black pixels /") - HELP_TEXT ("others => white pixels).") - HELP_TEXT ("") - HELP_TEXT ("- Scrolling 4-arrows pad: Scrolls the") - HELP_TEXT ("pattern in the drawing area.") - HELP_TEXT ("") - HELP_TEXT ("- Resizing 4-arrows pad: Defines the") - HELP_TEXT ("dimensions of the pattern.") - HELP_TEXT ("") - HELP_TEXT ("- Default-value (black or white square):") - HELP_TEXT ("Indicates which value must be inserted when") - HELP_TEXT ("you increase the dimensions of the pattern.") - HELP_TEXT ("") - HELP_TEXT ("- \"Clear\": Sets the whole pattern with the") - HELP_TEXT ("default value (see above).") - HELP_TEXT ("") - HELP_TEXT ("- \"Invert\": It... inverts :) ... black and") - HELP_TEXT ("white pixels.") - HELP_LINK ("(Key: %s)", SPECIAL_INVERT_SIEVE) - HELP_TEXT ("") - HELP_TEXT ("") - HELP_TITLE("TRANSPARENCY") - HELP_TEXT (" This allows to mix the color(s) of the") - HELP_TEXT ("paintbrush with the colors of the picture.") - HELP_TEXT ("It's used to make transparency effects like") - HELP_TEXT ("with watercolors.") - HELP_BOLD ("LEFT CLICK") - HELP_LINK ("(Key: %s)", SPECIAL_COLORIZE_MODE) - HELP_TEXT ("") - HELP_TEXT ("Switches the Transparency mode.") - HELP_TEXT ("") - HELP_BOLD ("RIGHT CLICK") - HELP_LINK ("(Key: %s)", SPECIAL_COLORIZE_MENU) - HELP_TEXT ("") - HELP_TEXT ("Opens a menu where you can define the") - HELP_TEXT ("Transparency parameters. These parameters") - HELP_TEXT ("are:") - HELP_TEXT ("") - HELP_TEXT ("- Interpolation rate: Indicates the") - HELP_TEXT ("percentage of the applied color that will be") - HELP_TEXT ("considered upon the replaced color.") - HELP_TEXT ("") - HELP_TEXT ("- Interpolation method: Uses an") - HELP_TEXT ("interpolation algorithm to compute the") - HELP_TEXT ("color, according to the interpolation rate.") - HELP_TEXT ("") - HELP_TEXT ("- Additive method: Uses the lightest colors") - HELP_TEXT ("to choose the color to apply. For example:") - HELP_TEXT ("if you want to apply a color RGB:30,20,40 on") - HELP_TEXT ("a color RGB:10,50,20, the color applied will") - HELP_TEXT ("be the one, in the palette, that is the") - HELP_TEXT ("closest to the theoretic color RGB:30,50,40.") - HELP_TEXT ("") - HELP_TEXT ("- Subtractive method: uses the darkest") - HELP_TEXT ("colors to choose the color to apply. For") - HELP_TEXT ("example: if you want to apply a color") - HELP_TEXT ("RGB:30,20,40 on a color RGB:10,50,20, the") - HELP_TEXT ("color applied will be the one, in the") - HELP_TEXT ("palette, that is the closest to the") - HELP_TEXT ("theoretic color RGB:10,20,20.") - HELP_TEXT ("") - HELP_TEXT ("") - HELP_TITLE("SMOOTH") - HELP_TEXT (" It provides an easy but not as efficient") - HELP_TEXT ("anti-aliasing as any artist's touch.") - HELP_TEXT ("Anyway this effect finds a better use in") - HELP_TEXT ("making a blurry aspect.") - HELP_BOLD ("LEFT CLICK") - HELP_LINK ("(Key: %s)", SPECIAL_SMOOTH_MODE) - HELP_TEXT ("") - HELP_TEXT ("Switches the Smooth mode.") - HELP_TEXT ("") - HELP_BOLD ("RIGHT CLICK") - HELP_LINK ("(Key: %s)", SPECIAL_SMOOTH_MENU) - HELP_TEXT ("") - HELP_TEXT ("Opens a menu where you can define the Smooth") - HELP_TEXT ("matrix or choose one among the 4 ones") - HELP_TEXT ("predefined.") - HELP_TEXT ("The middle square represents the pixel on") - HELP_TEXT ("which you draw and the 8 others represent") - HELP_TEXT ("the neighbour pixels. Then, the point on") - HELP_TEXT ("which one draw will be replaced by the") - HELP_TEXT ("weighted average (according to values of") - HELP_TEXT ("each squares) of the 9 defined points.") - HELP_TEXT ("") - HELP_TEXT ("") - HELP_TITLE("SMEAR") - HELP_TEXT (" It smears pixels in the direction you are") - HELP_TEXT ("moving your paintbrush, just as if you") - HELP_TEXT ("wanted to spread fresh paint with your") - HELP_TEXT ("fingers. You can combine this effect with") - HELP_TEXT ("the transparency effect.") - HELP_TEXT ("") - HELP_LINK ("(Key: %s)", SPECIAL_SMEAR_MODE) - HELP_TEXT ("Switches the Smear mode.") - HELP_TEXT ("") - HELP_TEXT ("") - HELP_TITLE("TILING") - HELP_TEXT (" It consists in displaying parts of the") - HELP_TEXT ("brush that are adjusted on a tiling when") - HELP_TEXT ("you are drawing. It's mainly used for") - HELP_TEXT ("quickly drawing a background with a") - HELP_TEXT ("pattern, but there is a great number of") - HELP_TEXT ("other possibilities.") - HELP_BOLD ("LEFT CLICK") - HELP_LINK ("(Key: %s)", SPECIAL_TILING_MODE) - HELP_TEXT ("") - HELP_TEXT ("Switches the Tiling mode.") - HELP_TEXT ("") - HELP_BOLD ("RIGHT CLICK") - HELP_LINK ("(Key: %s)", SPECIAL_TILING_MENU) - HELP_TEXT ("") - HELP_TEXT ("Opens a menu where you can define the Tiling") - HELP_TEXT ("parameters. These parameters are the offsets") - HELP_TEXT ("of the tiling.") -}; -static const T_Help_table helptable_text[] = -{ - HELP_TITLE("TEXT") - HELP_TEXT ("") - HELP_LINK ("(Key:%s)",0x100+BUTTON_TEXT) - HELP_TEXT ("") - HELP_TEXT ("The text menu allows you to enter some text") - HELP_TEXT ("and render it as a brush.") - HELP_TEXT ("The current background and foreground colors") - HELP_TEXT ("are very important, they determine the text") - HELP_TEXT ("color, the transparent color, and also the") - HELP_TEXT ("color range to use for antialiasing.") - HELP_TEXT ("GrafX2 can use 'bitmap' fonts as long as") - HELP_TEXT ("they are in the special layout supported ") - HELP_TEXT ("by SFont.") - HELP_TEXT ("TrueType fonts can also be used if this") - HELP_TEXT ("version of GrafX2 was compiled with") - HELP_TEXT ("TrueType support.") - HELP_TEXT ("") - HELP_TEXT ("- Txt: Click and enter your text here, a") - HELP_TEXT ("line of up to 250 characters.") - HELP_TEXT ("") - HELP_TEXT ("- Clear txt: Empties the current text.") - HELP_TEXT ("When the text is empty, a standard string") - HELP_TEXT ("is shown instead in the preview area.") - HELP_TEXT ("") - HELP_TEXT ("- Antialias: Click to enable or disable") - HELP_TEXT ("Antialiasing. Only affects TrueType fonts.") - HELP_TEXT ("") - HELP_TEXT ("- Size: Determine the font height. Only") - HELP_TEXT ("affects TrueType fonts.") - HELP_TEXT ("") - HELP_TEXT ("- Font selector: Choose a font. You can") - HELP_TEXT ("use the arrow keys (up and down) to quickly") - HELP_TEXT ("browse your fonts.") - HELP_TEXT ("TrueType fonts are indicated by 'TT'.") - HELP_TEXT ("") - HELP_TEXT ("- Preview area: Shows what the brush will") - HELP_TEXT ("look like.") -}; -static const T_Help_table helptable_magnifier[] = -{ - HELP_TITLE("MAGNIFIER") - HELP_TEXT ("") - HELP_BOLD ("LEFT CLICK") - HELP_LINK ("(Key:%s)",0x100+BUTTON_MAGNIFIER) - HELP_TEXT ("") - HELP_TEXT ("Engages/Disengages the choice of the zoomed") - HELP_TEXT ("window. If you're already in magnifier mode,") - HELP_TEXT ("you'll return to normal mode.") - HELP_LINK ("Zoom in : %s",SPECIAL_ZOOM_IN) - HELP_LINK ("Zoom out: %s",SPECIAL_ZOOM_OUT) - HELP_TEXT ("") - HELP_BOLD ("RIGHT CLICK") - HELP_LINK ("(Key:%s)",0x200+BUTTON_MAGNIFIER) - HELP_TEXT ("") - HELP_TEXT ("Displays a menu where you can choose the") - HELP_TEXT ("magnifying factor.") - HELP_TEXT ("") - HELP_TEXT (" Note: When you are in Zoom mode, you can") - HELP_TEXT ("move the \"split\" bar by clicking on it and") - HELP_TEXT ("moving your mouse left or right while") - HELP_TEXT ("holding the mouse button down.") -}; -static const T_Help_table helptable_colorpicker[] = -{ - HELP_TITLE("PIPETTE") - HELP_TEXT ("") - HELP_BOLD ("LEFT CLICK") - HELP_LINK ("(Key:%s)",0x100+BUTTON_COLORPICKER) - HELP_TEXT ("") - HELP_TEXT ("Engages a color grabbing.") - HELP_TEXT ("") - HELP_TEXT ("Click on the picture to get the color of the") - HELP_TEXT ("pixel you're on. You can either get a new") - HELP_TEXT ("Fore-color or Back-color with respectively") - HELP_TEXT ("left or right mouse button.") - HELP_TEXT ("") - HELP_BOLD ("RIGHT CLICK") - HELP_LINK ("(Key:%s)",0x200+BUTTON_COLORPICKER) - HELP_TEXT ("") - HELP_TEXT ("Swap Fore-color and Back-color.") - HELP_TEXT ("") - HELP_TEXT (" The color currently pointed will be") - HELP_TEXT ("displayed in the tool-bar right after the") - HELP_TEXT ("coordinates. If you click outside the") - HELP_TEXT ("picture, the color 0 will be returned.") -}; -static const T_Help_table helptable_resolution[] = -{ - HELP_TITLE("RESOLUTION AND") - HELP_TITLE(" IMAGE SIZE") - HELP_TEXT ("") - HELP_BOLD ("LEFT CLICK") - HELP_LINK ("(Key:%s)",0x100+BUTTON_RESOL) - HELP_TEXT ("") - HELP_TEXT ("Displays a menu where you can define the") - HELP_TEXT ("size of your picture and choose the") - HELP_TEXT ("screen resolution.") - HELP_TEXT ("") - HELP_TEXT ("- Image size") - HELP_TEXT ("Click in the boxes named \"Width\" and") - HELP_TEXT ("\"Height\" to change the size of the image") - HELP_TEXT ("you're editing, up to 9999x9999.") - HELP_TEXT ("You can also right-click a video mode to") - HELP_TEXT ("copy its dimensions to the image's.") - HELP_TEXT ("") - HELP_TEXT ("- Pixel size") - HELP_TEXT ("If you choose any Pixel size other than") - HELP_TEXT ("Normal, Grafx2 will emulate a lower") - HELP_TEXT ("resolution by scaling up everything it") - HELP_TEXT ("displays, including the menus and mouse") - HELP_TEXT ("cursor. In Double, Triple and Quadruple") - HELP_TEXT ("mode, the image will appear zoomed x2, x3 or") - HELP_TEXT ("x4, keeping the original proportions. The") - HELP_TEXT ("scaling is done in software, with no linear") - HELP_TEXT ("interpolation, so it can't cause blur. This") - HELP_TEXT ("setting is especially useful if your") - HELP_TEXT ("hardware or drivers don't support the low") - HELP_TEXT ("resolutions you need, but it also allows you") - HELP_TEXT ("to draw in low-resolution while staying in") - HELP_TEXT ("window mode.") - HELP_TEXT ("If you choose one of the scalers called") - HELP_TEXT ("Wide, Tall, Wide2 and Tall2, this will") - HELP_TEXT ("emulate a video mode which has rectangular") - HELP_TEXT ("pixels (longer horizontally or vertically),") - HELP_TEXT ("like some video modes of the C64, Amstrad") - HELP_TEXT ("CPC, and Commodore Amiga.") - HELP_TEXT ("") - HELP_TEXT ("- Video mode") - HELP_TEXT ("Click on a video mode to select it.") - HELP_TEXT ("Grafx2 only lists modes that are detected") - HELP_TEXT ("as available on your computer. Depending on") - HELP_TEXT ("your video card and drivers, there can be") - HELP_TEXT ("a huge difference in the number of modes") - HELP_TEXT ("it can propose.") - HELP_TEXT ("The small buttons on the left-hand side of") - HELP_TEXT ("the lines in the list of modes have been") - HELP_TEXT ("designed to allow you to disable some modes") - HELP_TEXT ("that are not supported by your card. So, the") - HELP_TEXT ("modes that you will disable won't be used") - HELP_TEXT ("when loading pictures with \"Auto-set") - HELP_TEXT ("resolution\" ON.") - HELP_TEXT ("") - HELP_TEXT ("When you click on one of these buttons, its") - HELP_TEXT ("color changes to one of the 4 following. The") - HELP_TEXT ("signification for each color of these") - HELP_TEXT ("buttons is:") - HELP_TEXT ("") - HELP_TEXT ("- Light gray: The video mode is OK. It can") - HELP_TEXT ("be used by the auto-set resolution option") - HELP_TEXT ("when you load picture, and you can select it") - HELP_TEXT ("in the menu of resolutions.") - HELP_TEXT ("") - HELP_TEXT ("- White: It works exactly the same as above.") - HELP_TEXT ("Moreover, it allows you to tag your") - HELP_TEXT ("favourite modes. Indeed, the huge number of") - HELP_TEXT ("video modes makes it more difficult to find") - HELP_TEXT ("the mode your want in the list; so you can") - HELP_TEXT ("tag your favoutite ones in white, so that it") - HELP_TEXT ("will be easier to locate them. (Note: you") - HELP_TEXT ("cannot disable the standard windowed mode)") - HELP_TEXT ("") - HELP_TEXT ("- Dark gray: It allows you to indicate which") - HELP_TEXT ("modes are not really perfect (flickering,") - HELP_TEXT ("not centered, etc...) but which can be used") - HELP_TEXT ("even so. The difference with the light grey") - HELP_TEXT ("button is that these modes won't be used by") - HELP_TEXT ("the auto-set resolution option.") - HELP_TEXT ("") - HELP_TEXT ("- Black: Use it for totally unsupported") - HELP_TEXT ("modes. Thus, these modes won't be selected") - HELP_TEXT ("the \"auto-set res.\" and the program will") - HELP_TEXT ("not let you select them from the list of") - HELP_TEXT ("resolutions.") - HELP_TEXT ("") - HELP_BOLD ("RIGHT CLICK") - HELP_LINK ("(Key:%s)",0x200+BUTTON_RESOL) - HELP_TEXT ("") - HELP_TEXT (" Automaticaly switches to the 640x400 window") - HELP_TEXT ("mode.") -}; -static const T_Help_table helptable_page[] = -{ - HELP_TITLE("SPARE") - HELP_TEXT ("") - HELP_BOLD ("LEFT CLICK") - HELP_LINK ("(Key:%s)",0x100+BUTTON_PAGE) - HELP_TEXT ("") - HELP_TEXT ("Jumps to spare page. The current page is") - HELP_TEXT ("then considered as the new spare page, and") - HELP_TEXT ("the spare page considered as the new current") - HELP_TEXT ("page.") - HELP_TEXT ("") - HELP_BOLD ("RIGHT CLICK") - HELP_LINK ("(Key:%s)",0x200+BUTTON_PAGE) - HELP_TEXT ("") - HELP_TEXT ("Opens a menu where you can choose whether") - HELP_TEXT ("you want to copy the whole picture (keyboard") - HELP_TEXT ("short-cut in this menu is [Return]), only") - HELP_TEXT ("the pixels, only the palette, or only some") - HELP_TEXT ("colors.") - HELP_TEXT ("In this last case, a second menu") - HELP_TEXT ("(stencil-like) will propose you to tag the") - HELP_TEXT ("colors you want to copy (they are all") - HELP_TEXT ("selected by default).") - HELP_TEXT ("Please refer to section \"Stencil\" to know") - HELP_TEXT ("how to use this last menu.") - HELP_TEXT ("The last option the menu (\"Copy palette and") - HELP_TEXT ("remap\"), remaps the spare page with the") - HELP_TEXT ("current palette and replicates this palette") - HELP_TEXT ("to the spare page. This option is useful to") - HELP_TEXT ("quickly remap a picture with the palette of") - HELP_TEXT ("another.") -}; -static const T_Help_table helptable_save[] = -{ - HELP_TITLE("SAVE") - HELP_TEXT ("") - HELP_BOLD ("LEFT CLICK") - HELP_LINK ("(Key:%s)",0x100+BUTTON_SAVE) - HELP_TEXT ("") - HELP_TEXT ("Displays a fileselector where the following") - HELP_TEXT ("options are available:") - HELP_TEXT ("") - HELP_TEXT ("- Select drive: Allow you to change the") - HELP_TEXT ("current drive.or volume (depending on your") - HELP_TEXT ("operating system") - HELP_TEXT ("") - HELP_TEXT ("- Format: Allows you to choose the file") - HELP_TEXT ("format you want. (PAL and KCF file formats") - HELP_TEXT ("are \"palette\" files).") - HELP_TEXT ("") - HELP_TEXT ("- Filename: Allows you to give a new name to") - HELP_TEXT ("the picture. If no extension is given, the") - HELP_TEXT ("default (according to the format) will be") - HELP_TEXT ("used.") - HELP_TEXT ("") - HELP_TEXT ("- Bookmarks: The four dropdown buttons allow") - HELP_TEXT ("you to bookmark frequently used directories.") - HELP_TEXT ("Use right-click to open a contextual menu") - HELP_TEXT ("to Set it (memorize current directory),") - HELP_TEXT ("Rename it to change its label, and Clear it") - HELP_TEXT ("if you no longer need it. Use left-click to") - HELP_TEXT ("change to the memorized directory.") - HELP_TEXT ("") - HELP_TEXT ("- File-list: Allows you to flick through the") - HELP_TEXT ("disk tree or to overwrite an existing file.") - HELP_TEXT ("") - HELP_TEXT ("- Delete: Allows you to delete the item") - HELP_TEXT ("under the selection bar. If the item is a") - HELP_TEXT ("directory, it must be empty to be removed.") - HELP_TEXT ("") - HELP_TEXT ("- Save: Saves the picture with the current") - HELP_TEXT ("filename, with the chosen format. If the ") - HELP_TEXT ("current filename represents a directory,") - HELP_TEXT ("you'll enter it.") - HELP_TEXT ("") - HELP_TEXT ("- Comment (Txt): If you're using the PKM") - HELP_TEXT ("or PNG format, you can type in a comment on") - HELP_TEXT ("your picture. It will be memorized in the") - HELP_TEXT ("image.") - HELP_TEXT ("") - HELP_TEXT ("Note: The Backspace key brings you directly") - HELP_TEXT ("to the parent directory. You can also type") - HELP_TEXT ("the first letters of a filename you are") - HELP_TEXT ("looking for, to access it faster.") - HELP_TEXT ("") - HELP_BOLD ("RIGHT CLICK") - HELP_LINK ("(Key:%s)",0x200+BUTTON_SAVE) - HELP_TEXT ("") - HELP_TEXT ("Save the current picture with its current") - HELP_TEXT ("filename, format and comment.") - HELP_TEXT ("") - HELP_TEXT ("If the file already exists, a confirmation") - HELP_TEXT ("box will appear.") -}; -static const T_Help_table helptable_load[] = -{ - - HELP_TITLE("LOAD") - HELP_TEXT ("") - HELP_BOLD ("LEFT CLICK") - HELP_LINK ("(Key:%s)",0x100+BUTTON_LOAD) - HELP_TEXT ("") - HELP_TEXT ("This works the same way as Save.") - HELP_TEXT ("") - HELP_TEXT ("You'll have access in the format selector to") - HELP_TEXT ("a \"*.*\" filter. And of course, you won't be") - HELP_TEXT ("able to type in any comment.") - HELP_TEXT ("") - HELP_BOLD ("RIGHT CLICK") - HELP_LINK ("(Key:%s)",0x200+BUTTON_LOAD) - HELP_TEXT ("") - HELP_TEXT ("Reloads the picture.") - HELP_TEXT ("") - HELP_TEXT ("If you want to load a picture and that you") - HELP_TEXT ("haven't saved the last modifications of the") - HELP_TEXT ("current picture, a confirmation box will") - HELP_TEXT ("appear.") -}; -static const T_Help_table helptable_settings[] = -{ - HELP_TITLE("SETTINGS") - HELP_TEXT ("") - HELP_LINK ("(Key:%s)",0x100+BUTTON_SETTINGS) - HELP_TEXT ("") - HELP_TEXT ("Displays a menu where you can configure some") - HELP_TEXT ("miscellaneous elements of the program:") - HELP_TEXT ("") - HELP_TEXT ("- Number of UNDO pages: indicates the total") - HELP_TEXT ("number of pages that GrafX2 will memorize.") - HELP_TEXT ("Each time you modify the picture, its") - HELP_TEXT ("current state is memorized in one of these") - HELP_TEXT ("pages. To flick through these pages, use the") - HELP_TEXT ("\"Oops\" button (Undo/Redo).") - HELP_TEXT ("") - HELP_TEXT ("- Font: determines whether you want to use") - HELP_TEXT ("GrafX2 with a classical font, or another one") - HELP_TEXT ("a bit funnier.") - HELP_TEXT ("") - HELP_TEXT ("- Mouse sensibility: Modifies the speed of") - HELP_TEXT ("the mouse when you're in fullscreen. With") - HELP_TEXT ("the normal setting (slider on top), you may") - HELP_TEXT ("find the mouse too fast, especially in ") - HELP_TEXT ("video modes which are much smaller than your") - HELP_TEXT ("desktop. You can lower the slider to divide") - HELP_TEXT ("the speed by 2, 3 or 4.") - HELP_TEXT ("When using videomodes with native skewed") - HELP_TEXT ("pixels like 640x240 or 320x512, you'll") - HELP_TEXT ("probably want to use a stronger reduction") - HELP_TEXT ("on the axis which has less pixels.") - HELP_TEXT ("") - HELP_TEXT ("- Show/Hide in file list: Defines whether") - HELP_TEXT ("some particular files or directories must be") - HELP_TEXT ("displayed by the fileselectors or not.") - HELP_TEXT ("") - HELP_TEXT ("- Show/Hide picture limits: Indicates if the") - HELP_TEXT ("picture boundaries must be displayed when") - HELP_TEXT ("you are in a resolution bigger than the") - HELP_TEXT ("picture.") - HELP_TEXT ("") - HELP_TEXT ("- Clear palette: Indicates if loading a file") - HELP_TEXT ("with a palette of less than 256 colors must") - HELP_TEXT ("erase the rest of the current palette") - HELP_TEXT ("(replace by the black color).") - HELP_TEXT ("") - HELP_TEXT ("- Maximize preview: maximizes the preview of") - HELP_TEXT ("the pictures so that it is as big as") - HELP_TEXT ("possible. If you're not in the same") - HELP_TEXT ("resolution as the picture's one, it can try") - HELP_TEXT ("to correct the aspect ratio, but if the") - HELP_TEXT ("picture does not fill the whole screen, it") - HELP_TEXT ("can be worse.") - HELP_TEXT ("") - HELP_TEXT ("- Backup: when you'll save a picture over an") - HELP_TEXT ("existing file, the program will rename this") - HELP_TEXT ("file to \"*.BAK\" where * is the name of the") - HELP_TEXT ("picture without its extension. If the backup") - HELP_TEXT ("file already exists in the directory, it") - HELP_TEXT ("will be replaced. If you save a picture with") - HELP_TEXT ("the name of the backup file, no backup file") - HELP_TEXT ("will be created (of course!) ;).") - HELP_TEXT ("") - HELP_TEXT ("- Cursor: allows you to choose whether you") - HELP_TEXT ("prefer a solid cursor or a transparent") - HELP_TEXT ("cursor.") - HELP_TEXT ("") - HELP_TEXT ("- Safety colors: Brings back the 4 default") - HELP_TEXT ("colors of the menus if you run an operation") - HELP_TEXT ("that passes the image in less than four") - HELP_TEXT ("colors in the palette editor.") - HELP_TEXT ("") - HELP_TEXT ("- Adjust brush pick: This option is used") - HELP_TEXT ("when you grab a brush in Grid (Snap) mode.") - HELP_TEXT ("Then, the right-most and down-most pixels") - HELP_TEXT ("won't be picked up with the rest of the") - HELP_TEXT ("brush. This option has been made because, if") - HELP_TEXT ("people grab brushes in Grid mode, that's") - HELP_TEXT ("mostly when they want to grab sprites. For") - HELP_TEXT ("example: if you have 16x16 sprites on your") - HELP_TEXT ("page, you'll set the grid mode to 16x16. But") - HELP_TEXT ("the cursor will snap at points like (0,0),") - HELP_TEXT ("(16,0), (16,16) and so on... And the problem") - HELP_TEXT ("is that, from (0,0) to (16,16), there are 17") - HELP_TEXT ("pixels! But if you keep the") - HELP_TEXT ("adjust-brush-pick option on, the unwanted") - HELP_TEXT ("pixels will be ignored. Moreover, this") - HELP_TEXT ("option adjusts the brush handle so that the") - HELP_TEXT ("brush still fits in the grid, instead of") - HELP_TEXT ("placing the handle in the center of the") - HELP_TEXT ("brush.") - HELP_TEXT ("") - HELP_TEXT ("- Separate colors: Draws a squaring around") - HELP_TEXT ("the colors of the tool-bar.") - HELP_TEXT ("") - HELP_TEXT ("- Auto-set resolution: sets the best") - HELP_TEXT ("resolution for the loaded image.") - HELP_TEXT ("") - HELP_TEXT ("- Coordinates: Choose if you want to display") - HELP_TEXT ("relative or absolute coordinates when using") - HELP_TEXT ("tools such as circles, rectangles, etc...") - HELP_TEXT ("for example, if you draw a circle: if coords") - HELP_TEXT ("are relative, the radius of the circle will") - HELP_TEXT ("be displayed, while in absolute coords, the") - HELP_TEXT ("coordinates of the cursor will be displayed.") - HELP_TEXT ("") - HELP_TEXT ("- Reload: loads the previously saved") - HELP_TEXT ("configuration.") - HELP_TEXT ("") - HELP_TEXT ("- Auto-save: means that the configuration") - HELP_TEXT ("will be automatically saved when you'll quit") - HELP_TEXT ("the program.") - HELP_TEXT ("") - HELP_TEXT ("- Save: saves the configuration at once.") - HELP_TEXT (" All modifications will be effective just") - HELP_TEXT ("after closing the menu.") -}; -static const T_Help_table helptable_clear[] = -{ - - HELP_TITLE("CLEAR") - HELP_TEXT ("") - HELP_BOLD ("LEFT CLICK") - HELP_LINK ("(Key:%s)",0x100+BUTTON_CLEAR) - HELP_TEXT ("") - HELP_TEXT ("Clears the picture with the color number 0.") - HELP_TEXT ("") - HELP_BOLD ("RIGHT CLICK") - HELP_LINK ("(Key:%s)",0x200+BUTTON_CLEAR) - HELP_TEXT ("") - HELP_TEXT ("Clears the picture with the Back-color.") -}; -static const T_Help_table helptable_general[] = -{ - - HELP_TITLE("HELP STATS") - HELP_TEXT ("") - HELP_BOLD ("LEFT CLICK") - HELP_LINK ("(Key:%s)",0x100+BUTTON_HELP) - HELP_TEXT ("") - HELP_TEXT ("Displays an info window where you'll find") - HELP_TEXT ("some credits, help about the credits,") - HELP_TEXT ("different effects, greetings, registering...") - HELP_TEXT ("") - HELP_BOLD ("RIGHT CLICK") - HELP_LINK ("(Key:%s)",0x200+BUTTON_HELP) - HELP_TEXT ("") - HELP_TEXT ("Displays a window where you'll find") - HELP_TEXT ("miscellaneous informations about the system.") - HELP_TEXT (" Note: you should take care to keep more") - HELP_TEXT ("than 128 Kb in order to let the program") - HELP_TEXT ("run in a proper way.") -}; -static const T_Help_table helptable_undo[] = -{ - - HELP_TITLE("OOPS") - HELP_TEXT ("(UNDO/REDO)") - HELP_TEXT ("LEFT CLICK Allows you to undo the last") - HELP_TEXT ("modification on the picture.") - HELP_LINK ("(Key:%s)",0x100+BUTTON_UNDO) - HELP_TEXT ("") - HELP_TEXT ("RIGHT CLICK Allows you to redo the last") - HELP_TEXT ("modification undone on the picture.") - HELP_TEXT ("The maximum number of UNDO that you can") - HELP_TEXT ("perform can be defined in the settings") - HELP_TEXT ("menu.") - HELP_TEXT ("Undo/Redo aren't effective after page") - HELP_TEXT ("switching, picture loading and picture") - HELP_TEXT ("size modifications.") - HELP_LINK ("(Key:%s)",0x200+BUTTON_UNDO) -}; -static const T_Help_table helptable_kill[] = -{ - - HELP_TITLE("KILL") - HELP_TEXT ("KILL CURRENT PAGE") - HELP_TEXT ("") - HELP_LINK ("(Key:%s)",0x100+BUTTON_KILL) - HELP_TEXT ("") - HELP_TEXT ("Removes the current page from the list of") - HELP_TEXT ("\"Undo\" pages. This allows you to free some") - HELP_TEXT ("memory if you need it. For instance, this") - HELP_TEXT ("will allow you to delete the start-up page") - HELP_TEXT ("after having loaded an image. A message will") - HELP_TEXT ("appear if you've already erased all the") - HELP_TEXT ("pages except the last one.") - HELP_TEXT (" Note: Another way to free some memory is to") - HELP_TEXT ("decrease the number of \"Undo\" pages. Or") - HELP_TEXT ("else, if you have recentlt grabbed a very") - HELP_TEXT ("big brush that you don't use any more, you") - HELP_TEXT ("can grab a new smaller one. The memory") - HELP_TEXT ("allocated by the big brush will be thus") - HELP_TEXT ("freed.") -}; -static const T_Help_table helptable_quit[] = -{ - - HELP_TITLE("QUIT") - HELP_TEXT ("") - HELP_LINK ("(Key:%s)",0x100+BUTTON_QUIT) - HELP_TEXT ("") - HELP_TEXT ("Allows you to leave GrafX2. If there are") - HELP_TEXT ("unsaved modifications in the current or") - HELP_TEXT ("spare page, a confirmation box will ask you") - HELP_TEXT ("if you really want to quit GrafX2, if you") - HELP_TEXT ("want to save (Auto-save, no fileselector) or") - HELP_TEXT ("if you want to stay in GrafX2.") -}; -static const T_Help_table helptable_palette[] = -{ - - HELP_TITLE("PAL MENU") - HELP_TEXT ("") - HELP_BOLD ("LEFT CLICK") - HELP_LINK ("(Key:%s)",0x100+BUTTON_PALETTE) - HELP_TEXT ("") - HELP_TEXT ("Displays a menu where the following options") - HELP_TEXT ("are available:") - HELP_TEXT ("") - HELP_TEXT ("- Palette: Allows you to choose a") - HELP_TEXT ("color-block to edit. If you click with the") - HELP_TEXT ("right mouse button, you'll choose a new") - HELP_TEXT ("Back-color.") - HELP_TEXT ("") - HELP_TEXT ("- Gauges: Allow you to modify the") - HELP_TEXT ("current selection.") - HELP_TEXT ("") - HELP_TEXT ("- \"+\" and \"-\": Allow you to lighten or") - HELP_TEXT ("darken the current selection.") - HELP_TEXT ("") - HELP_TEXT ("- Default: Restores the predifined GrafX2") - HELP_TEXT ("palette.") - HELP_TEXT ("") - HELP_TEXT ("- Gray: Transforms the current selection") - HELP_TEXT ("into its gray-scaled equivalent.") - HELP_TEXT ("") - HELP_TEXT ("- Negative: Transforms the current selection") - HELP_TEXT ("into its reverse video equivalent.") - HELP_TEXT ("") - HELP_TEXT ("- Invert: Swaps the colors of the current") - HELP_TEXT ("selection so that the first colors become") - HELP_TEXT ("the last ones.") - HELP_TEXT ("") - HELP_TEXT ("- X-Invert: Works as above but modifies the") - HELP_TEXT ("picture so that it looks the same.") - HELP_TEXT ("") - HELP_TEXT ("- Swap: Swaps the current selection with") - HELP_TEXT ("another color-block. Click on the beginning") - HELP_TEXT ("of the new color-block.") - HELP_TEXT ("") - HELP_TEXT ("- X-Swap: Works as above but modifies the") - HELP_TEXT ("picture so that it looks the same. This may") - HELP_TEXT ("be useful if you want to sort your palette.") - HELP_TEXT ("") - HELP_TEXT ("- Copy: Copies the current selection to") - HELP_TEXT ("another color-block. Click on the beginning") - HELP_TEXT ("of the new color-block.") - HELP_TEXT ("") - HELP_TEXT ("- Spread: Computes a gradation between two") - HELP_TEXT ("colors. If your selection is only made up of") - HELP_TEXT ("one color, select the second color in the") - HELP_TEXT ("palette. Otherwise, the two colors used will") - HELP_TEXT ("be its extremities.") - HELP_TEXT ("") - HELP_TEXT ("- Sort: sorts the palette by color ranges.") - HELP_TEXT ("If you click with the left mouse button, it") - HELP_TEXT ("will sort by H S L; and if you click with") - HELP_TEXT ("the right mouse button, it will sort by L") - HELP_TEXT ("only. Note that you can choose a range of") - HELP_TEXT ("colors before sorting, and instead of the") - HELP_TEXT ("whole palette it will sort this range.") - HELP_TEXT ("") - HELP_TEXT ("- Used: Indicates the number of colors used") - HELP_TEXT ("in the picture.") - HELP_TEXT ("") - HELP_TEXT ("- Zap unused: Erases the unused colors with") - HELP_TEXT ("copies of the current selection. (The") - HELP_TEXT ("keyboard shortcut for this button is ).") - HELP_TEXT ("") - HELP_TEXT ("- HSL: Switches between RGB and HSL color") - HELP_TEXT ("spaces. In HSL mode, the three sliders") - HELP_TEXT ("allow you to set the Hue (tint), Saturation") - HELP_TEXT ("(from grayscale to pure color) and") - HELP_TEXT ("Lightness (from black to white).") - HELP_TEXT ("") - HELP_TEXT ("- Reduce: Allows you to reduce the palette") - HELP_TEXT ("to the number of colors you want (and") - HELP_TEXT ("modifies the picture).") - HELP_TEXT ("") - HELP_TEXT ("- Undo: Allows you to recover the last") - HELP_TEXT ("modifications made on the palette. If the") - HELP_TEXT ("last operation modified the picture, it") - HELP_TEXT ("won't recover them: you'll have to click on") - HELP_TEXT ("Cancel to do so.") - HELP_TEXT ("") - HELP_TEXT ("") - HELP_TEXT ("If you press , the program will") - HELP_TEXT ("replace, as well as possible, some unused") - HELP_TEXT ("colors by the four default colors of the") - HELP_TEXT ("menu. The image won't look altered because") - HELP_TEXT ("the modified colors (in the case they were") - HELP_TEXT ("used on a few points) will be replaced by") - HELP_TEXT ("the closest colors in the rest of the") - HELP_TEXT ("palette. This option is really useful when") - HELP_TEXT ("you modify the palette so that there are no") - HELP_TEXT ("colors that fit for the menu (eg: \"Zap") - HELP_TEXT ("unused\" while very little colors are used in") - HELP_TEXT ("the picture; or \"Reduce\" with a very small") - HELP_TEXT ("number of colors).") - HELP_TEXT ("") - HELP_TEXT ("If you press the key below or <,>") - HELP_TEXT ("(QWERTY), the menu will disappear and you") - HELP_TEXT ("will be able to pick up a color from the") - HELP_TEXT ("picture easily. Press to cancel.") - HELP_TEXT ("") - HELP_TEXT ("If only one color is selected (not a block),") - HELP_TEXT ("the <[> and <]> keys can be used to select") - HELP_TEXT ("the previous or next Forecolor (Backcolor if") - HELP_TEXT ("you press at the same time).") - HELP_TEXT ("") - HELP_TEXT ("Warning! If you press Undo after an action") - HELP_TEXT ("that modifies the picture (X-Swap, X-Invert") - HELP_TEXT ("and Reduce colors), the picture won't be") - HELP_TEXT ("remapped as it was just before this action.") - HELP_TEXT ("Only Cancel will.") - HELP_TEXT ("") - HELP_TITLE("PALETTE OPTIONS") - HELP_TEXT ("") - HELP_BOLD ("RIGHT CLICK") - HELP_LINK ("(Key:%s)",0x200+BUTTON_PALETTE) - HELP_TEXT ("") - HELP_TEXT ("Opens a menu from where you have the") - HELP_TEXT ("following options:") - HELP_TEXT ("") - HELP_TEXT ("- Colors for best match:") - HELP_TEXT ("A menu in which you can select the colors") - HELP_TEXT ("that have not to be used for smoothing, for") - HELP_TEXT ("the transparency mode, and for remapping.") - HELP_TEXT ("") - HELP_TEXT ("- User's color series:") - HELP_TEXT ("A menu in which you can define color series") - HELP_TEXT ("for next/previous user color shortcuts.") - HELP_TEXT ("It's the same settings than the shade mode.") - HELP_TEXT ("After you have some color ranges defined in") - HELP_TEXT ("this screen, you can use those shortcuts to") - HELP_TEXT ("move to the next or previous color according") - HELP_TEXT ("to your ranges:") - HELP_TEXT ("") - HELP_TEXT ("Foreground color") - HELP_TEXT ("") - HELP_LINK (" Next : %s", SPECIAL_NEXT_USER_FORECOLOR) - HELP_LINK (" Previous: %s", SPECIAL_PREVIOUS_USER_FORECOLOR) - HELP_TEXT ("") - HELP_TEXT ("Background color") - HELP_LINK (" Next : %s", SPECIAL_NEXT_USER_BACKCOLOR) - HELP_LINK (" Previous: %s", SPECIAL_PREVIOUS_USER_BACKCOLOR) - HELP_TEXT ("") - HELP_TEXT ("") - HELP_TEXT ("- Palette layout:") - HELP_TEXT ("Lets you customize the palette that appears") - HELP_TEXT ("on the right of the menu. You can choose the") - HELP_TEXT ("number of lines and columns.") - HELP_TEXT ("If you want the colors to run top to bottom,") - HELP_TEXT ("check the 'Vertical' button, otherwise the") - HELP_TEXT ("colors runs left to right.") - HELP_TEXT ("") - HELP_TEXT ("- RGB Scale:") - HELP_TEXT ("Lets you set the scale of the R G B sliders") - HELP_TEXT ("in the palette screen. You should normally") - HELP_TEXT ("leave it at 256 to get the full 0-255 range,") - HELP_TEXT ("but if you want to constrain the palette") - HELP_TEXT ("to the capabilities of some specific") - HELP_TEXT ("computers and consoles, you can choose eg:") - HELP_TEXT (" 64 : VGA") - HELP_TEXT (" 16 : Amiga") - HELP_TEXT (" 4 : MSX2") - HELP_TEXT (" 2 : Amstrad CPC") - }; -static const T_Help_table helptable_pal_scroll[] = -{ - - HELP_TITLE("SCROLL PAL") - HELP_TEXT ("") - HELP_BOLD ("LEFT CLICK") - HELP_TEXT ("") - HELP_TEXT ("Scrolls the palette window in the right of") - HELP_TEXT ("the menu.") - HELP_LINK ("Key for back: %s", 0x100+BUTTON_PAL_LEFT) - HELP_LINK ("Key for forward: %s", 0x100+BUTTON_PAL_RIGHT) - HELP_TEXT ("") - HELP_BOLD ("RIGHT CLICK") - HELP_TEXT ("") - HELP_TEXT ("Same as above, but faster.") - HELP_LINK ("Key for back: %s", 0x200+BUTTON_PAL_LEFT) - HELP_LINK ("Key for forward: %s", 0x200+BUTTON_PAL_RIGHT) - HELP_TEXT ("") -}; -static const T_Help_table helptable_color_select[] = -{ - - HELP_TITLE("PALETTE") - HELP_TEXT ("") - HELP_BOLD ("LEFT CLICK") - HELP_TEXT ("") - HELP_TEXT ("Defines the Fore-color.") - HELP_TEXT ("") - HELP_BOLD ("RIGHT CLICK") - HELP_TEXT ("") - HELP_TEXT ("Defines the Back-color.") -}; -static const T_Help_table helptable_hide[] = -{ - - HELP_TITLE("HIDE MENU") - HELP_TEXT ("") - HELP_TEXT ("Allows you to hide the menu. If you do this,") - HELP_TEXT ("take care to watch before the key to press") - HELP_TEXT ("to show the menu back (the key is") - HELP_LINK ("%s).",0x100+BUTTON_HIDE) - -}; - -#define HELP_TABLE_DECLARATION(x) {x, sizeof(x)/sizeof(const T_Help_table)}, - -T_Help_section Help_section[] = -{ - HELP_TABLE_DECLARATION(helptable_about) - HELP_TABLE_DECLARATION(helptable_licence) - HELP_TABLE_DECLARATION(helptable_help) - HELP_TABLE_DECLARATION(helptable_credits) - - // Attention, keep the same order as BUTTON_NUMBERS: - HELP_TABLE_DECLARATION(helptable_paintbrush) - HELP_TABLE_DECLARATION(helptable_adjust) - HELP_TABLE_DECLARATION(helptable_draw) - HELP_TABLE_DECLARATION(helptable_curves) - HELP_TABLE_DECLARATION(helptable_lines) - HELP_TABLE_DECLARATION(helptable_airbrush) - HELP_TABLE_DECLARATION(helptable_floodfill) - HELP_TABLE_DECLARATION(helptable_polygons) - HELP_TABLE_DECLARATION(helptable_polyfill) - HELP_TABLE_DECLARATION(helptable_rectangles) - HELP_TABLE_DECLARATION(helptable_filled_rectangles) - HELP_TABLE_DECLARATION(helptable_circles) - HELP_TABLE_DECLARATION(helptable_filled_circles) - HELP_TABLE_DECLARATION(helptable_grad_rect) - HELP_TABLE_DECLARATION(helptable_grad_menu) - HELP_TABLE_DECLARATION(helptable_spheres) - HELP_TABLE_DECLARATION(helptable_brush) - HELP_TABLE_DECLARATION(helptable_polybrush) - HELP_TABLE_DECLARATION(helptable_brush_fx) - HELP_TABLE_DECLARATION(helptable_effects) - HELP_TABLE_DECLARATION(helptable_text) - HELP_TABLE_DECLARATION(helptable_magnifier) - HELP_TABLE_DECLARATION(helptable_colorpicker) - HELP_TABLE_DECLARATION(helptable_resolution) - HELP_TABLE_DECLARATION(helptable_page) - HELP_TABLE_DECLARATION(helptable_save) - HELP_TABLE_DECLARATION(helptable_load) - HELP_TABLE_DECLARATION(helptable_settings) - HELP_TABLE_DECLARATION(helptable_clear) - HELP_TABLE_DECLARATION(helptable_general) - HELP_TABLE_DECLARATION(helptable_undo) - HELP_TABLE_DECLARATION(helptable_kill) - HELP_TABLE_DECLARATION(helptable_quit) - HELP_TABLE_DECLARATION(helptable_palette) - HELP_TABLE_DECLARATION(helptable_pal_scroll) - HELP_TABLE_DECLARATION(helptable_pal_scroll) - HELP_TABLE_DECLARATION(helptable_color_select) - HELP_TABLE_DECLARATION(helptable_hide) -}; +/* Grafx2 - The Ultimate 256-color bitmap paint program + + Copyright 2008 Yves Rizoud + Copyright 2009 Franck Charlet + Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) + + Grafx2 is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 + of the License. + + Grafx2 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grafx2; if not, see +*/ + +////////////////////////////////////////////////////////////////////////////// +///@file helpfile.h +/// This is all the text that appears in contextual help and credits. +/// +/// Note: The source code is kept on a public website, so keep this in mind +/// if you're thinking of putting an e-mail address in there. At least, use +/// "\100" instead of @, to help against the most basic email address harvesters. +////////////////////////////////////////////////////////////////////////////// + +#include "const.h" // Uses enumerations BUTTON_NUMBERS and SPECIAL_ACTIONS + +// Some magic formulas: + +#define HELP_TEXT(x) {'N', x, 0}, +// Generates a 'N' line (Normal) + +#define HELP_LINK(x,y) {'K', x, y}, +// Generates a 'K' line (Key) + +#define HELP_BOLD(x) {'S', x, 0}, +// Generates a 'S' line (BOLD) + +#define HELP_TITLE(x) {'T', x, 0}, {'-', x, 0}, +// Generates a 'T' line (Title, upper half) +// and a second '-' line (Title, lower half), with the same text. + +static const T_Help_table helptable_about[] = +/* + Do not exceed 44 characters for normal lines: + HELP_TEXT ("--------------------------------------------") + Do not exceed 22 characters for title lines: + HELP_TITLE("======================") +*/ +{ + HELP_TEXT ("") // Leave enough room for a hard-coded logo, eventually. + HELP_TEXT ("") + HELP_TEXT ("") + HELP_TEXT ("") + HELP_TITLE(" GRAFX 2 ") + HELP_BOLD (" \"Summer Sunset\" Edition") + HELP_BOLD (" THE ULTIMATE MULTI-RESOLUTION GFX EDITOR") + HELP_TEXT (" http://grafx2.googlecode.com") + HELP_TEXT ("") + HELP_TEXT (" Copyright 2007 by the Grafx2 project team") + HELP_TEXT (" Copyright 1996-2001 by SUNSET DESIGN") +}; +static const T_Help_table helptable_licence[] = +{ + HELP_TITLE(" LICENSE") + HELP_TEXT ("") + HELP_TEXT ("Grafx2 is FREE SOFTWARE, you can") + HELP_TEXT ("redistribute it and/or modify it under the") + HELP_TEXT ("terms of the GNU General Public License as") + HELP_TEXT ("published by the Free Software Foundation;") + HELP_TEXT ("version 2 of the License.") + HELP_TEXT ("") + HELP_TEXT ("Grafx2 is distributed in the hope that it") + HELP_TEXT ("will be useful, but WITHOUT ANY WARRANTY;") + HELP_TEXT ("without even the implied warranty of") + HELP_TEXT ("MERCHANTABILITY or FITNESS FOR A PARTICULAR") + HELP_TEXT ("PURPOSE. See the GNU General Public License") + HELP_TEXT ("for more details.") + HELP_TEXT ("") + HELP_TEXT ("You should have received a copy of the GNU") + HELP_TEXT ("General Public License along with Grafx2;") + HELP_TEXT ("if not, see http://www.gnu.org/licenses/ or") + HELP_TEXT ("write to the Free Software Foundation, Inc.") + HELP_TEXT (" 59 Temple Place - Suite 330, Boston,") + HELP_TEXT (" MA 02111-1307, USA.") + +}; +static const T_Help_table helptable_help[] = +{ + HELP_TITLE(" HELP") + HELP_TEXT ("") + HELP_TEXT (" Contextual help is available by pressing") + HELP_LINK (" the %s key",0x100+BUTTON_HELP) + HELP_TEXT (" You can do it while hovering a menu icon,") + HELP_TEXT (" or while a window is open.") + HELP_TEXT (" When a keyboard shortcut is displayed it's") + HELP_TEXT (" your current configuration and you can") + HELP_TEXT (" change it by clicking it.") + HELP_TEXT ("") + HELP_TITLE(" KEYBOARD SHORTCUTS") + HELP_TEXT ("") + HELP_TEXT ("Scroll visible area") + HELP_LINK (" up: %s", SPECIAL_SCROLL_UP) + HELP_LINK (" down: %s", SPECIAL_SCROLL_DOWN) + HELP_LINK (" left: %s", SPECIAL_SCROLL_LEFT) + HELP_LINK (" right: %s", SPECIAL_SCROLL_RIGHT) + HELP_LINK (" up faster: %s", SPECIAL_SCROLL_UP_FAST) + HELP_LINK (" down faster: %s", SPECIAL_SCROLL_DOWN_FAST) + HELP_LINK (" left faster: %s", SPECIAL_SCROLL_LEFT_FAST) + HELP_LINK (" right faster: %s", SPECIAL_SCROLL_RIGHT_FAST) + HELP_LINK (" up slower: %s", SPECIAL_SCROLL_UP_SLOW) + HELP_LINK (" down slower: %s", SPECIAL_SCROLL_DOWN_SLOW) + HELP_LINK (" left slower: %s", SPECIAL_SCROLL_LEFT_SLOW) + HELP_LINK (" right slower: %s", SPECIAL_SCROLL_RIGHT_SLOW) + HELP_TEXT ("Emulate mouse") + HELP_LINK (" Up: %s", SPECIAL_MOUSE_UP) + HELP_LINK (" Down: %s", SPECIAL_MOUSE_DOWN) + HELP_LINK (" Left: %s", SPECIAL_MOUSE_LEFT) + HELP_LINK (" Right: %s", SPECIAL_MOUSE_RIGHT) + HELP_LINK (" Left click: %s", SPECIAL_CLICK_LEFT) + HELP_LINK (" Right click: %s", SPECIAL_CLICK_RIGHT) + HELP_LINK ("Show / Hide menu: %s", 0x100+BUTTON_HIDE) + HELP_LINK ("Show / Hide cursor: %s", SPECIAL_SHOW_HIDE_CURSOR) + HELP_LINK ("Paintbrush = \".\": %s", SPECIAL_DOT_PAINTBRUSH) + HELP_LINK ("Paintbrush choice: %s", 0x100+BUTTON_PAINTBRUSHES) + HELP_LINK ("Monochrome brush: %s", 0x200+BUTTON_PAINTBRUSHES) + HELP_LINK ("Freehand drawing: %s", 0x100+BUTTON_DRAW) + HELP_TEXT ("Switch freehand") + HELP_LINK (" drawing mode: %s", 0x200+BUTTON_DRAW) + HELP_TEXT ("Continuous freehand") + HELP_LINK (" drawing: %s", SPECIAL_CONTINUOUS_DRAW) + HELP_LINK ("Line: %s", 0x100+BUTTON_LINES) + HELP_LINK ("Knotted lines: %s", 0x200+BUTTON_LINES) + HELP_LINK ("Spray: %s", 0x100+BUTTON_AIRBRUSH) + HELP_LINK ("Spray menu: %s", 0x200+BUTTON_AIRBRUSH) + HELP_LINK ("Floodfill: %s", 0x100+BUTTON_FLOODFILL) + HELP_LINK ("Replace color: %s", 0x200+BUTTON_FLOODFILL) + HELP_LINK ("Bezier's curves: %s", 0x100+BUTTON_CURVES) + HELP_TEXT ("Bezier's curve with") + HELP_LINK (" 3 or 4 points %s", 0x200+BUTTON_CURVES) + HELP_LINK ("Empty rectangle: %s", 0x100+BUTTON_RECTANGLES) + HELP_LINK ("Filled rectangle: %s", 0x100+BUTTON_FILLRECT) + HELP_LINK ("Empty circle: %s", 0x100+BUTTON_CIRCLES) + HELP_LINK ("Empty ellipse: %s", 0x200+BUTTON_CIRCLES) + HELP_LINK ("Filled circle: %s", 0x100+BUTTON_FILLCIRC) + HELP_LINK ("Filled ellipse: %s", 0x200+BUTTON_FILLCIRC) + HELP_LINK ("Empty polygon: %s", 0x100+BUTTON_POLYGONS) + HELP_LINK ("Empty polyform: %s", 0x200+BUTTON_POLYGONS) + HELP_LINK ("Polyfill: %s", 0x100+BUTTON_POLYFILL) + HELP_LINK ("Filled polyform: %s", 0x200+BUTTON_POLYFILL) + HELP_LINK ("Gradient rectangle: %s", 0x100+BUTTON_GRADRECT) + HELP_LINK ("Gradation menu: %s", 0x200+BUTTON_GRADRECT) + HELP_LINK ("Spheres: %s", 0x100+BUTTON_SPHERES) + HELP_LINK ("Gradient ellipses: %s", 0x200+BUTTON_SPHERES) + HELP_LINK ("Adjust picture: %s", 0x100+BUTTON_ADJUST) + HELP_LINK ("Flip picture menu: %s", 0x200+BUTTON_ADJUST) + HELP_LINK ("Effects menu: %s", 0x100+BUTTON_EFFECTS) + HELP_LINK ("Effects all off %s", SPECIAL_EFFECTS_OFF) + HELP_LINK ("Shade mode: %s", SPECIAL_SHADE_MODE) + HELP_LINK ("Shade menu: %s", SPECIAL_SHADE_MENU) + HELP_LINK ("Quick-shade mode: %s", SPECIAL_QUICK_SHADE_MODE) + HELP_LINK ("Quick-shade menu: %s", SPECIAL_QUICK_SHADE_MENU) + HELP_LINK ("Stencil mode: %s", SPECIAL_STENCIL_MODE) + HELP_LINK ("Stencil menu: %s", SPECIAL_STENCIL_MENU) + HELP_LINK ("Mask mode: %s", SPECIAL_MASK_MODE) + HELP_LINK ("Mask menu: %s", SPECIAL_MASK_MENU) + HELP_LINK ("Grid mode: %s", SPECIAL_GRID_MODE) + HELP_LINK ("Grid menu: %s", SPECIAL_GRID_MENU) + HELP_LINK ("Grid view: %s", SPECIAL_SHOW_GRID) + HELP_LINK ("Sieve mode: %s", SPECIAL_SIEVE_MODE) + HELP_LINK ("Sieve menu: %s", SPECIAL_SIEVE_MENU) + HELP_LINK ("Invert Sieve: %s", SPECIAL_INVERT_SIEVE) + HELP_LINK ("Colorize mode: %s", SPECIAL_COLORIZE_MODE) + HELP_LINK (" At opacity 10%%: %s", SPECIAL_TRANSPARENCY_1) + HELP_LINK (" At opacity 20%%: %s", SPECIAL_TRANSPARENCY_2) + HELP_LINK (" At opacity 30%%: %s", SPECIAL_TRANSPARENCY_3) + HELP_LINK (" At opacity 40%%: %s", SPECIAL_TRANSPARENCY_4) + HELP_LINK (" At opacity 50%%: %s", SPECIAL_TRANSPARENCY_5) + HELP_LINK (" At opacity 60%%: %s", SPECIAL_TRANSPARENCY_6) + HELP_LINK (" At opacity 70%%: %s", SPECIAL_TRANSPARENCY_7) + HELP_LINK (" At opacity 80%%: %s", SPECIAL_TRANSPARENCY_8) + HELP_LINK (" At opacity 90%%: %s", SPECIAL_TRANSPARENCY_9) + HELP_LINK (" At opacity 100%%: %s", SPECIAL_TRANSPARENCY_0) + HELP_LINK ("Colorize menu: %s", SPECIAL_COLORIZE_MENU) + HELP_LINK ("Smooth mode: %s", SPECIAL_SMOOTH_MODE) + HELP_LINK ("Smooth menu: %s", SPECIAL_SMOOTH_MENU) + HELP_LINK ("Smear mode: %s", SPECIAL_SMEAR_MODE) + HELP_LINK ("Tiling mode: %s", SPECIAL_TILING_MODE) + HELP_LINK ("Tiling menu: %s", SPECIAL_TILING_MENU) + HELP_LINK ("Pick brush: %s", 0x100+BUTTON_BRUSH) + HELP_LINK ("Pick polyform brush: %s", 0x100+BUTTON_POLYBRUSH) + HELP_LINK ("Restore brush: %s", 0x200+BUTTON_BRUSH) + HELP_LINK ("Flip brush X: %s", SPECIAL_FLIP_X) + HELP_LINK ("Flip brush Y: %s", SPECIAL_FLIP_Y) + HELP_LINK ("90° brush rotation: %s", SPECIAL_ROTATE_90) + HELP_LINK ("180° brush rotation: %s", SPECIAL_ROTATE_180) + HELP_LINK ("Stretch brush: %s", SPECIAL_STRETCH) + HELP_LINK ("Distort brush: %s", SPECIAL_DISTORT) + HELP_LINK ("Outline brush: %s", SPECIAL_OUTLINE) + HELP_LINK ("Nibble brush: %s", SPECIAL_NIBBLE) + HELP_LINK ("Get brush colors: %s", SPECIAL_GET_BRUSH_COLORS) + HELP_LINK ("Recolorize brush: %s", SPECIAL_RECOLORIZE_BRUSH) + HELP_LINK ("Rotate brush: %s", SPECIAL_ROTATE_ANY_ANGLE) + HELP_LINK ("Pipette: %s", 0x100+BUTTON_COLORPICKER) + HELP_LINK ("Swap fore/back color:%s", 0x200+BUTTON_COLORPICKER) + HELP_TEXT ("Magnifier mode") + HELP_LINK (" Toggle: %s", 0x100+BUTTON_MAGNIFIER) + HELP_LINK (" Zoom factor menu: %s", 0x200+BUTTON_MAGNIFIER) + HELP_LINK (" Zoom in: %s", SPECIAL_ZOOM_IN) + HELP_LINK (" Zoom out: %s", SPECIAL_ZOOM_OUT) + HELP_LINK (" 1:1 (off) %s", SPECIAL_ZOOM_1) + HELP_LINK (" 2:1 %s", SPECIAL_ZOOM_2) + HELP_LINK (" 3:1 %s", SPECIAL_ZOOM_3) + HELP_LINK (" 4:1 %s", SPECIAL_ZOOM_4) + HELP_LINK (" 5:1 %s", SPECIAL_ZOOM_5) + HELP_LINK (" 6:1 %s", SPECIAL_ZOOM_6) + HELP_LINK (" 8:1 %s", SPECIAL_ZOOM_8) + HELP_LINK (" 10:1 %s", SPECIAL_ZOOM_10) + HELP_LINK (" 12:1 %s", SPECIAL_ZOOM_12) + HELP_LINK (" 14:1 %s", SPECIAL_ZOOM_14) + HELP_LINK (" 16:1 %s", SPECIAL_ZOOM_16) + HELP_LINK (" 18:1 %s", SPECIAL_ZOOM_18) + HELP_LINK (" 20:1 %s", SPECIAL_ZOOM_20) + HELP_LINK ("Brush effects menu: %s", 0x100+BUTTON_BRUSH_EFFECTS) + HELP_LINK ("Text: %s", 0x100+BUTTON_TEXT) + HELP_LINK ("Resolution menu: %s", 0x100+BUTTON_RESOL) + HELP_LINK ("Safety resolution: %s", 0x200+BUTTON_RESOL) + HELP_LINK ("Help: %s", 0x100+BUTTON_HELP) + HELP_LINK ("Statistics: %s", 0x200+BUTTON_HELP) + HELP_LINK ("Go to spare page: %s", 0x100+BUTTON_PAGE) + HELP_LINK ("Copy to spare page: %s", 0x200+BUTTON_PAGE) + HELP_LINK ("Save as: %s", 0x100+BUTTON_SAVE) + HELP_LINK ("Save: %s", 0x200+BUTTON_SAVE) + HELP_LINK ("Load: %s", 0x100+BUTTON_LOAD) + HELP_LINK ("Re-load: %s", 0x200+BUTTON_LOAD) + HELP_LINK ("Save brush: %s", SPECIAL_SAVE_BRUSH) + HELP_LINK ("Load brush: %s", SPECIAL_LOAD_BRUSH) + HELP_LINK ("Larger brush size: %s", SPECIAL_BIGGER_PAINTBRUSH) + HELP_LINK ("Smaller brush size: %s", SPECIAL_SMALLER_PAINTBRUSH) + HELP_LINK ("Settings: %s", 0x100+BUTTON_SETTINGS) + HELP_LINK ("Undo: %s", 0x100+BUTTON_UNDO) + HELP_LINK ("Redo: %s", 0x200+BUTTON_UNDO) + HELP_LINK ("Kill page: %s", 0x100+BUTTON_KILL) + HELP_LINK ("Clear: %s", 0x100+BUTTON_CLEAR) + HELP_LINK ("Clear with BG color: %s", 0x200+BUTTON_CLEAR) + HELP_LINK ("Quit: %s", 0x100+BUTTON_QUIT) + HELP_LINK ("Palette menu: %s", 0x100+BUTTON_PALETTE) + HELP_LINK ("2nd Palette menu: %s", 0x200+BUTTON_PALETTE) + HELP_LINK ("Exclude colors menu: %s", SPECIAL_EXCLUDE_COLORS_MENU) + HELP_TEXT ("") + HELP_TEXT ("Scroll palette") + HELP_LINK (" Back: %s", 0x100+BUTTON_PAL_LEFT) + HELP_LINK (" Forward: %s", 0x100+BUTTON_PAL_RIGHT) + HELP_LINK (" Back faster: %s", 0x200+BUTTON_PAL_LEFT) + HELP_LINK (" Forward faster: %s", 0x200+BUTTON_PAL_RIGHT) + HELP_TEXT ("") + HELP_TEXT ("Change brush attachement") + HELP_LINK (" Center : %s", SPECIAL_CENTER_ATTACHMENT) + HELP_LINK (" Top-left : %s", SPECIAL_TOP_LEFT_ATTACHMENT) + HELP_LINK (" Top-right : %s", SPECIAL_TOP_RIGHT_ATTACHMENT) + HELP_LINK (" Bottom-left : %s", SPECIAL_BOTTOM_LEFT_ATTACHMENT) + HELP_LINK (" Bottom-right: %s", SPECIAL_BOTTOM_RIGHT_ATTACHMENT) + HELP_TEXT ("") + HELP_TEXT ("Select foreground color") + HELP_TEXT ("") + HELP_LINK (" Next : %s", SPECIAL_NEXT_FORECOLOR) + HELP_LINK (" Previous: %s", SPECIAL_PREVIOUS_FORECOLOR) + HELP_TEXT ("") + HELP_TEXT ("Select background color") + HELP_LINK (" Next : %s", SPECIAL_NEXT_BACKCOLOR) + HELP_LINK (" Previous: %s", SPECIAL_PREVIOUS_BACKCOLOR) + HELP_TEXT ("") + HELP_TEXT ("Select user-defined foreground color") + HELP_TEXT ("") + HELP_LINK (" Next : %s", SPECIAL_NEXT_USER_FORECOLOR) + HELP_LINK (" Previous: %s", SPECIAL_PREVIOUS_USER_FORECOLOR) + HELP_TEXT ("") + HELP_TEXT ("Select user-defined background color") + HELP_LINK (" Next : %s", SPECIAL_NEXT_USER_BACKCOLOR) + HELP_LINK (" Previous: %s", SPECIAL_PREVIOUS_USER_BACKCOLOR) + HELP_TEXT ("") +}; +static const T_Help_table helptable_credits[] = +{ +//HELP_TEXT ("0----5----0----5----0----5----0----5----0--X") + HELP_TITLE(" GRAFX2 IS CREATED BY") + HELP_TEXT ("") + HELP_BOLD (" THE GRAFX2 PROJECT TEAM") + HELP_TEXT ("") + HELP_TEXT (" Adrien Destugues (pulkomandy)") + HELP_TEXT (" Yves Rizoud (yrizoud)") + HELP_TEXT ("") + HELP_TEXT (" Got the source back to life in 2006") + HELP_TEXT ("") + HELP_BOLD (" SUNSET DESIGN") + HELP_BOLD (" AUTHORS OF GRAFX2.0 BETA 96.5%") + HELP_TEXT ("") + HELP_TEXT (" Guillaume Dorme alias \"Robinson\" (code)") + HELP_TEXT (" Karl Maritaud alias \"X-Man\" (code&gfx)") +//HELP_TEXT ("0----5----0----5----0----5----0----5----0--X") + HELP_TEXT ("") + HELP_TEXT (" Re-licensed GrafX2 under the GPL in 2001") + HELP_TEXT (" Huge thanks to them for their work !") + HELP_TEXT ("") + HELP_BOLD (" OTHER CODE CONTRIBUTORS") + HELP_TEXT ("") + HELP_TEXT (" Karl Bartel") + HELP_TEXT (" SFont: bitmap fonts rendering") + HELP_TEXT ("") + HELP_TEXT (" Petter Lindquist") + HELP_TEXT (" C64 file and image formats") + HELP_TEXT ("") + HELP_TEXT ("") + HELP_TITLE(" ART") + HELP_TEXT ("") + HELP_TEXT (" Made (www.m4de.com)") + HELP_TEXT (" Logo (classic)") + HELP_TEXT ("") + HELP_TEXT (" X-Man") + HELP_TEXT (" Buttons and fonts (classic)") + HELP_TEXT ("") + HELP_TEXT (" iLKke (ilkke.blogspot.com)") + HELP_TEXT (" Buttons and logo (modern), extra fonts") + HELP_TEXT ("") + HELP_TEXT ("") + HELP_TEXT (" ...Pixelled all the graphics") + HELP_TEXT ("") + HELP_TITLE(" OTHER MACHINES PORTS") + HELP_TEXT ("") + HELP_BOLD (" AMIGA OS 3 PORT") + HELP_TEXT ("") + HELP_TEXT (" Artur Jarosik") + HELP_TEXT ("") + HELP_BOLD (" AMIGA OS 4 PORT") + HELP_TEXT ("") + HELP_TEXT (" Peter Gordon (www.petergordon.org.uk)") + HELP_TEXT ("") + HELP_BOLD (" AROS PORT") + HELP_TEXT ("") + HELP_TEXT (" Fernando Mastandrea (masta.uy)") + HELP_TEXT (" Markus Weiss") + HELP_TEXT ("") + HELP_BOLD (" FREEBSD PORT") + HELP_TEXT ("") + HELP_TEXT (" Jean-Baptiste Berlioz (Tobe)") + HELP_TEXT ("") + HELP_BOLD (" HAIKU OS AND BEOS PORT") + HELP_TEXT ("") + HELP_TEXT (" Luc Schrijvers (Begasus)") + HELP_TEXT ("") + HELP_BOLD (" LINUX BINARIES") + HELP_TEXT ("") + HELP_TEXT (" Gentoo : Matteo 'Peach' Pescarin") + HELP_TEXT (" Debian : Gürkan Sengün") + HELP_TEXT ("") + HELP_BOLD (" MAC OS X PORT") + HELP_TEXT ("") + HELP_TEXT (" Franck Charlet (hitchhikr)") + HELP_TEXT (" Per Olofsson (MagerValp)") + HELP_TEXT ("") + HELP_BOLD (" MORPHOS PORT") + HELP_TEXT ("") + HELP_TEXT (" Rusback") + HELP_TEXT ("") + HELP_BOLD (" SKYOS PORT") + HELP_TEXT ("") + HELP_TEXT (" Luc Schrijvers (Begasus)") + HELP_TEXT ("") + HELP_TEXT ("") + HELP_TEXT (" ... made it work on your favourite toaster") + HELP_TEXT ("") + HELP_TITLE(" BUGFINDERS") + HELP_TEXT ("") +//HELP_TEXT ("0----5----0----5----0----5----0----5----0--X") + HELP_TEXT (" blumunkee BDCIron Ced ") + HELP_TEXT (" El Topo fallenblood Frost ") + HELP_TEXT (" Grimmy Gürkan Sengün Hatch ") + HELP_TEXT (" HoraK-FDF iLKke Jamon ") + HELP_TEXT (" keito kusma Lord Graga ") + HELP_TEXT (" MagerValp mind MooZ ") + HELP_TEXT (" the Peach petter richienyhus ") + HELP_TEXT (" tape.wyrm TeeEmCee tempest ") + HELP_TEXT (" Timo Kurrpa titus^Rab Tobé ") + HELP_TEXT (" 00ai99") + HELP_TEXT ("") + HELP_TEXT ("") + HELP_TEXT (" ... posted the annoying bug reports.") + HELP_TEXT ("") + HELP_TITLE(" FILE FORMATS CREDITS") + HELP_TEXT ("") + HELP_TEXT (" BMP : Microsoft") + HELP_TEXT (" CEL,KCF : K.O.S. (KISekae Set system)") + HELP_TEXT (" GIF : Compuserve") + HELP_TEXT (" IMG : Bivas (W. Wiedmann?)") + HELP_TEXT (" LBM : Electronic Arts") + HELP_TEXT (" PAL : ermmh... nobody (?)") + HELP_TEXT (" PCX : Z-Soft") + HELP_TEXT (" PI1,PC1 : Degas Elite") + HELP_TEXT (" PKM : Sunset Design") + HELP_TEXT (" PNG : W3C") + HELP_TEXT (" SCx : Colorix (?)") + HELP_TEXT ("") + HELP_TEXT ("") + HELP_TITLE(" OUR HOMEPAGE") + HELP_TEXT ("") + HELP_BOLD (" http://grafx2.codegoogle.com") + HELP_TEXT ("") + HELP_TEXT (" Please report any bug you may find there") + HELP_TEXT ("") + HELP_TEXT ("") + HELP_TITLE(" GREETINGS") + HELP_TEXT ("") + HELP_BOLD ("Pulkomandy:") + HELP_TEXT ("") + HELP_TEXT (" To the Pouet.net BBS posters, the #CPC") + HELP_TEXT (" trolls and the bitfellas") + HELP_TEXT (" To every people who makes the scene alive!") + HELP_TEXT (" To all guys making nice pixelled pictures") + HELP_TEXT (" (with or without GrafX2)") + HELP_TEXT ("") + HELP_BOLD ("Sunset Designs:") + HELP_TEXT ("") + HELP_TEXT (" We send our best regards to...") + HELP_TEXT ("") + HELP_TEXT (" Access Filter Pink") + HELP_TEXT (" Ace Fiver Pixel") + HELP_TEXT (" AcidJam Flan Profil") + HELP_TEXT (" Acryl Fred Prowler") + HELP_TEXT (" Alexel FreddyV Puznik") + HELP_TEXT (" Alias Frost Quick") + HELP_TEXT (" Amiral Gaël(GDC) Ra") + HELP_TEXT (" Arrakis GainX Raster") + HELP_TEXT (" Avocado Gandalf Ravian") + HELP_TEXT (" Baloo Goblin RedBug") + HELP_TEXT (" Barti Greenpix7 Rem") + HELP_TEXT (" Bat Grid Rez") + HELP_TEXT (" Biro GrosQuick Roudoudou") + HELP_TEXT (" Bisounours HackerCroll Sacrilege") + HELP_TEXT (" BlackAxe Haplo Sam") + HELP_TEXT (" Bonnie Hof SandMan") + HELP_TEXT (" Boo Hornet Scape") + HELP_TEXT (" Boz Hulud Sébastien") + HELP_TEXT (" Carine Java Shodan") + HELP_TEXT (" Chandra JBT Skal") + HELP_TEXT (" Cheetah Jérôme Skyfire") + HELP_TEXT (" Chill Julien(JCA) Sphair") + HELP_TEXT (" Cougar KalMinDo Sprocket") + HELP_TEXT (" Cremax KaneWood Stef") + HELP_TEXT (" Cyclone Karma Stony") + HELP_TEXT (" Dake Keith303 Sumaleth") + HELP_TEXT (" Danny Lazur Sunday") + HELP_TEXT (" Danube LightShow Suny") + HELP_TEXT (" Darjul Lluvia Sybaris") + HELP_TEXT (" Darwin Louie TBF") + HELP_TEXT (" DarkAngel Luk Tempest") + HELP_TEXT (" Das Made Thor") + HELP_TEXT (" Decker Mamos TMK") + HELP_TEXT (" DerPiipo Mandrixx TwoFace") + HELP_TEXT (" Destop Mangue Underking") + HELP_TEXT (" Diabolo Mars Unreal") + HELP_TEXT (" DineS Mephisto VaeVictis") + HELP_TEXT (" Drac Mercure Vastator") + HELP_TEXT (" DrYes Mirec Vatin") + HELP_TEXT (" Edyx Moa Veckman") + HELP_TEXT (" Eller Moxica Wain") + HELP_TEXT (" Ellyn MRK Wally") + HELP_TEXT (" EOF Nitch WillBe") + HELP_TEXT (" Fall Noal Xoomie") + HELP_TEXT (" Fame Nytrik Xtrm") + HELP_TEXT (" Fantom Optic YannSulu") + HELP_TEXT (" Fear Orome Z") + HELP_TEXT (" Feather Pahladin Zeb") + HELP_TEXT (" Fennec Phar Zebig") + HELP_TEXT ("") + HELP_TEXT (" and all #pixel, #demofr and #coders.") + HELP_TEXT ("") + HELP_TEXT ("") + HELP_TEXT (" Some information taken from several docs") + HELP_TEXT (" (PCGPE, Intervue, PC Interdit...)") + HELP_TEXT (" gave us an invaluable help.") + HELP_TEXT ("") + HELP_TEXT (" Thanks to Shawn Hargreaves for his filled") + HELP_TEXT (" polygon routine from Allegro v2.2.") + HELP_TEXT ("") + HELP_TEXT (" Thanks to Carlos \"Made\" Pardo for his") + HELP_TEXT (" great GrafX2 logo.") + HELP_TEXT ("") + HELP_TEXT (" This is our very first program compiled") + HELP_TEXT (" with the Gnu C Compiler.") + HELP_TEXT (" A thousand thanks to the authors of") + HELP_TEXT (" this compiler.") + HELP_TEXT ("") + HELP_TEXT (" We also would like to thank all the") + HELP_TEXT (" people who gave us ideas to improve") + HELP_TEXT (" GrafX2.") + HELP_TEXT ("") + HELP_TITLE (" SNAIL MAIL") + HELP_TEXT ("") +//HELP_TEXT ("0----5----0----5----0----5----0----5----0--X") + HELP_TEXT (" ADRIEN DESTUGUES (PulkoMandy)") + HELP_TEXT (" 3, rue Lapouble") + HELP_TEXT (" 64000 PAU") + HELP_TEXT (" (Send emails! Welcome in 21th century!)") + HELP_TEXT ("") + HELP_TEXT (" GUILLAUME DORME (Robinson)") + HELP_TEXT (" 15, rue de l'observatoire") + HELP_TEXT (" 87000 LIMOGES (FRANCE)") + HELP_TEXT (" (May take some years to get an answer)") + HELP_TEXT ("") + HELP_TEXT ("") + HELP_TEXT (" KARL MARITAUD (X-Man)") + HELP_TEXT (" 10, rue de la Brasserie") + HELP_TEXT (" 87000 LIMOGES (FRANCE)") + HELP_TEXT (" (From 2001, current status: unknown)") + HELP_TEXT ("") + HELP_TEXT ("") +}; +static const T_Help_table helptable_paintbrush[] = +{ + HELP_TITLE("PAINTBRUSHES") + HELP_TEXT ("") + HELP_BOLD (" LEFT CLICK") + HELP_LINK ("(Key:%s)",0x100+BUTTON_PAINTBRUSHES) + HELP_TEXT ("") + HELP_TEXT ("Displays a menu where you can choose the") + HELP_TEXT ("shape of your paintbrush.") + HELP_TEXT ("") + HELP_TEXT ("Paintbrushes are sorted by family. You can") + HELP_TEXT ("see some paintbrushes of the same family but") + HELP_TEXT ("with different sizes. There is at least one") + HELP_TEXT ("paint-brush from each family displayed in") + HELP_TEXT ("this menu.") + HELP_TEXT ("Here is the list of all the different") + HELP_TEXT ("paintbrush families:") + HELP_TEXT ("") + HELP_TEXT ("******* *** * * * * * * ") + HELP_TEXT ("******* ***** * * * * * * ") + HELP_TEXT ("******* ******* * * * * * * * * ") + HELP_TEXT ("******* ******* * * * * * * ") + HELP_TEXT ("******* ******* * * * * * * * * ") + HELP_TEXT ("******* ***** * * * * * * ") + HELP_TEXT ("******* *** * * * * * * ") + HELP_TEXT ("") + HELP_TEXT ("Square Disc Sieve Sieve ") + HELP_TEXT (" square disc ") + HELP_TEXT (" ") + HELP_TEXT (" * * * ") + HELP_TEXT (" *** * * * ") + HELP_TEXT (" ***** * * ") + HELP_TEXT ("******* ******* * ") + HELP_TEXT (" ***** * * * * ") + HELP_TEXT (" *** * ") + HELP_TEXT (" * * * * ") + HELP_TEXT (" ") + HELP_TEXT ("Diamond Random Horiz. Vertical") + HELP_TEXT (" bar bar ") + HELP_TEXT ("") + HELP_TEXT ("") + HELP_TEXT (" * * * * *") + HELP_TEXT (" * * * * *") + HELP_TEXT (" * * * * *") + HELP_TEXT (" * * * *******") + HELP_TEXT (" * * * * *") + HELP_TEXT (" * * * * *") + HELP_TEXT ("* * * * *") + HELP_TEXT ("") + HELP_TEXT (" Slash Back- Cross X Cross +") + HELP_TEXT (" slash") + HELP_TEXT ("") + HELP_TEXT ("When using one of these, you can change the") + HELP_TEXT ("brush size by using the keys:") + HELP_LINK ("Reduce : %s", SPECIAL_SMALLER_PAINTBRUSH) + HELP_LINK ("Increase : %s", SPECIAL_BIGGER_PAINTBRUSH) + HELP_TEXT ("The last 3 paintbrushes in the menu belong") + HELP_TEXT ("to the \"miscellaneous\" family and their size") + HELP_TEXT ("cannot be modified.") + HELP_TEXT ("") + HELP_BOLD ("BRUSH CONTAINER") + HELP_TEXT ("") + HELP_TEXT ("The bottom row, initially showing empty") + HELP_TEXT ("buttons, is the brush container. You can") + HELP_TEXT ("right-click a button to store the current") + HELP_TEXT ("brush in it, and then whenever you need the") + HELP_TEXT ("brush back, open this menu again and") + HELP_TEXT ("left-click the button.") + HELP_TEXT ("The container can memorize resizable brushes") + HELP_TEXT ("as well as brushes grabbed from the image.") + HELP_TEXT ("Brushes are lost when you exit the program.") + HELP_TEXT ("") + HELP_BOLD (" RIGHT CLICK ") + HELP_LINK ("(Key:%s)",0x200+BUTTON_PAINTBRUSHES) + HELP_TEXT ("") + HELP_TEXT ("Transforms your current user-defined brush") + HELP_TEXT ("into a paintbrush. This is actually a") + HELP_TEXT ("\"monochromisation\" of your user-defined") + HELP_TEXT ("brush. This means that every color of the") + HELP_TEXT ("brush that aren't the Back-color will be") + HELP_TEXT ("set to the Fore-color. But this option") + HELP_TEXT ("doesn't alter the brush: you'll just have") + HELP_TEXT ("to right-click on the \"Get brush\" buttons") + HELP_TEXT ("to get your brush back.") + HELP_TEXT ("") + HELP_TEXT ("Note: When you press (not in the menu) the") + HELP_LINK ("key %s, the current",SPECIAL_DOT_PAINTBRUSH) + HELP_TEXT ("paintbrush becomes the smallest member of") + HELP_TEXT ("the \"Disc\" family: i.e one pixel.") + +}; +static const T_Help_table helptable_adjust[] = +{ + HELP_TITLE("ADJUST OR TRANSFORM") + HELP_TITLE(" PICTURE") + HELP_TEXT ("") + HELP_BOLD (" LEFT CLICK") + HELP_LINK ("(Key:%s)",0x100+BUTTON_ADJUST) + HELP_TEXT ("") + HELP_TEXT ("Allows you to scroll the picture to") + HELP_TEXT ("re-center your graph for example.") + HELP_TEXT ("") + HELP_TEXT ("Any part of the picture that goes out of") + HELP_TEXT ("the image by a side comes back by the") + HELP_TEXT ("opposite one.") + HELP_TEXT ("") + HELP_TEXT ("It is assimilated to the drawing tools") + HELP_TEXT ("family.") + HELP_TEXT ("") + HELP_TEXT ("") + HELP_BOLD (" RIGHT CLICK") + HELP_LINK ("(Key:%s)",0x200+BUTTON_ADJUST) + HELP_TEXT ("") + HELP_TEXT ("Opens the Picture Transform menu.") + HELP_TEXT ("") + HELP_TEXT ("") + HELP_TITLE("PICTURE TRANSFORM") + HELP_TEXT ("") + HELP_BOLD ("RESCALE") + HELP_TEXT ("") + HELP_TEXT ("Allows you to change the image's size,") + HELP_TEXT ("rescaling it accordingly. Enter new size") + HELP_TEXT ("and press RESIZE to confirm.") + HELP_TEXT ("") + HELP_TEXT ("") + HELP_TEXT ("When 'Lock proportions' is checked and you") + HELP_TEXT ("change one dimension, the other one is") + HELP_TEXT ("automatically adjusted to preserve the") + HELP_TEXT ("proportions of the original image.") + HELP_TEXT ("") + HELP_TEXT ("You can use the dropdown button to choose") + HELP_TEXT ("between three ways to enter the dimensions:") + HELP_TEXT ("") + HELP_TEXT ("In 'Pixels' mode, the column 'old' shows") + HELP_TEXT ("the original dimensions, and you can set") + HELP_TEXT ("the new size in pixels.") + HELP_TEXT ("") + HELP_TEXT ("In 'Percent' mode, you set a percentage") + HELP_TEXT ("compared to the original image.") + HELP_TEXT ("") + HELP_TEXT ("In 'Ratio' mode, you can set 2 numbers for") + HELP_TEXT ("each dimension, and the resizing factor will") + HELP_TEXT ("be of 'new'÷'old'. For example you can use") + HELP_TEXT ("1:3 to divide the image by three, 2:1 to") + HELP_TEXT ("double it, and any fraction like 15:16.") + HELP_TEXT ("") + HELP_TEXT ("Be careful that moving from one mode to the") + HELP_TEXT ("next can lose precision, if the selected") + HELP_TEXT ("dimensions cannot be represented exactly in") + HELP_TEXT ("the new mode.") + HELP_TEXT ("") + HELP_BOLD ("MIRROR") + HELP_TEXT ("") + HELP_TEXT ("- X: Flip the picture horizontally.") + HELP_TEXT ("") + HELP_TEXT ("- Y: Flip the picture vertically.") + HELP_TEXT ("") + HELP_BOLD ("ROTATE") + HELP_TEXT ("") + HELP_TEXT ("-90°: Rotates the image by 90°") + HELP_TEXT (" clockwise.") + HELP_TEXT ("") + HELP_TEXT ("+90°: Rotates the image by 90°") + HELP_TEXT (" counter-clockwise.") + HELP_TEXT ("180°: Rotates the image by 180°") + HELP_TEXT ("") + HELP_TEXT ("") +}; +static const T_Help_table helptable_draw[] = +{ + HELP_TITLE("HAND-DRAWING") + HELP_TEXT ("") + HELP_BOLD (" LEFT CLICK") + HELP_LINK ("(Key:%s)",0x100+BUTTON_DRAW) + HELP_TEXT ("") + HELP_TEXT ("Selects the current hand-drawing mode as the") + HELP_TEXT ("active drawing tool. There are 4") + HELP_TEXT ("hand-drawing modes:") + HELP_TEXT ("") + HELP_TEXT ("Continuous hand-drawing: as you move the") + HELP_TEXT ("mouse, the paintbrush is regularily pasted") + HELP_TEXT ("on the picture. This drawing tool allows to") + HELP_TEXT ("change the fore and back colors when being") + HELP_TEXT ("in use.") + HELP_TEXT ("") + HELP_TEXT ("Discontinuous hand-drawing: as you move the") + HELP_TEXT ("mouse, the paintbrush is pasted on the") + HELP_TEXT ("picture every time a delay is passed") + HELP_TEXT ("(actually, the delay is 1 VBL") + HELP_TEXT ("(vertical blanking)). This drawing tool") + HELP_TEXT ("allows to change the fore and back colors") + HELP_TEXT ("when being in use.") + HELP_TEXT ("") + HELP_TEXT ("Dot by dot hand-drawing: the paintbrush is") + HELP_TEXT ("only pasted at the position where you first") + HELP_TEXT ("clicked.") + HELP_TEXT ("") + HELP_TEXT ("Contour fill: Draws pixels like continuous") + HELP_TEXT ("mode, but when you release the button Grafx2") + HELP_TEXT ("draws a line back to your starting position,") + HELP_TEXT ("and fills the area. This tool doesn't use the") + HELP_TEXT ("current brush, but single pixels.") + HELP_TEXT ("") + HELP_BOLD (" RIGHT CLICK") + HELP_LINK ("(Key:%s)",0x200+BUTTON_DRAW) + HELP_TEXT ("") + HELP_TEXT ("Toggles the different hand-drawing modes") + HELP_TEXT ("and activates, at the same time, the") + HELP_TEXT ("hand-drawing tool.") +}; +static const T_Help_table helptable_curves[] = +{ + HELP_TITLE("SPLINES") + HELP_TEXT ("") + HELP_BOLD ("LEFT CLICK") + HELP_LINK ("(Key:%s)",0x100+BUTTON_CURVES) + HELP_TEXT ("") + HELP_TEXT ("Selects the current curve-drawing mode as") + HELP_TEXT ("the active drawing tool. There are 2") + HELP_TEXT ("different curve-drawing modes:") + HELP_TEXT ("") + HELP_TEXT ("* 4 control points curves: define the basic") + HELP_TEXT ("line like a classical line, then move, with") + HELP_TEXT ("the left mouse button, the inner control") + HELP_TEXT ("points to choose the shape of your curve.") + HELP_TEXT ("When the curve has the shape you want, click") + HELP_TEXT ("with the right mouse button to draw it") + HELP_TEXT ("definitively.") + HELP_TEXT ("") + HELP_TEXT ("* 3 control points curves: the same as") + HELP_TEXT ("above, but you'll have only one inner") + HELP_TEXT ("control point to place. Moreover, the spline") + HELP_TEXT ("will be traced just after placing this") + HELP_TEXT ("point.") + HELP_TEXT ("") + HELP_BOLD ("RIGHT CLICK") + HELP_LINK ("(Key:%s)",0x200+BUTTON_CURVES) + HELP_TEXT ("") + HELP_TEXT ("Toggles the different curve-drawing modes") + HELP_TEXT ("and activates, at the same time, the") + HELP_TEXT ("curve-drawing tool.") +}; +static const T_Help_table helptable_lines[] = +{ + HELP_TITLE("LINES") + HELP_TEXT ("") + HELP_BOLD ("LEFT CLICK") + HELP_LINK ("(Key:%s)",0x100+BUTTON_LINES) + HELP_TEXT ("") + HELP_TEXT ("Selects the current line-drawing mode as the") + HELP_TEXT ("active drawing tool. There are 3") + HELP_TEXT ("line-drawing modes:") + HELP_TEXT ("") + HELP_TEXT ("* Classical lines: when first clicking on") + HELP_TEXT ("the picture, you'll define the start of the") + HELP_TEXT ("line. Maintain your click to choose the end") + HELP_TEXT ("of the line and release the mouse button to") + HELP_TEXT ("set it.") + HELP_TEXT ("If you hold SHIFT when drawing, the line") + HELP_TEXT ("will be constrained to horizonal, vertical") + HELP_TEXT ("or diagonal.") + HELP_TEXT ("") + HELP_TEXT ("* Knotted lines: works like classical lines,") + HELP_TEXT ("but the end of your line will automatically") + HELP_TEXT ("become the start of the next one. When you") + HELP_TEXT ("want to stop chaining lines, use the") + HELP_TEXT ("opposite mouse button. \"The opposite button\"") + HELP_TEXT ("means that if you started to draw lignes") + HELP_TEXT ("with the left button (Fore-color), you'll") + HELP_TEXT ("have to stop the procedure with the right") + HELP_TEXT ("button; and conversely.") + HELP_TEXT ("") + HELP_TEXT ("* Concentric lines: when first clicking on") + HELP_TEXT ("the picture, you'll define center of the") + HELP_TEXT ("lines. In fact, the center is defined by the") + HELP_TEXT ("the position of the mouse when you release") + HELP_TEXT ("the mouse button. Then you can draw lines") + HELP_TEXT ("from the center to the current mouse") + HELP_TEXT ("position by clicking. To stop drawing") + HELP_TEXT ("concentric lines, use the opposite mouse") + HELP_TEXT ("button. This drawing tool allows to change") + HELP_TEXT ("the fore and back colors when being in use.") + HELP_TEXT ("") + HELP_BOLD ("RIGHT CLICK") + HELP_LINK ("(Key:%s)",0x200+BUTTON_LINES) + HELP_TEXT ("") + HELP_TEXT ("Toggles the different line-drawing modes and") + HELP_TEXT ("activates, at the same time, the") + HELP_TEXT ("line-drawing tool.") + +}; +static const T_Help_table helptable_airbrush[] = +{ + HELP_TITLE("SPRAY") + HELP_TEXT ("") + HELP_BOLD ("LEFT CLICK") + HELP_LINK ("(Key:%s)",0x100+BUTTON_AIRBRUSH) + HELP_TEXT ("") + HELP_TEXT ("Selects the spray as the active drawing") + HELP_TEXT ("tool. This drawing tool allows to change the") + HELP_TEXT ("fore and back colors when being in use.") + HELP_TEXT ("") + HELP_BOLD ("RIGHT CLICK") + HELP_LINK ("(Key:%s)",0x200+BUTTON_AIRBRUSH) + HELP_TEXT ("") + HELP_TEXT ("Displays a menu where you can configure the") + HELP_TEXT ("spray:") + HELP_TEXT ("") + HELP_TEXT ("- Size: Defines the diameter of the circle") + HELP_TEXT ("in which will effectively fit the spray.") + HELP_TEXT ("") + HELP_TEXT ("- Delay: Defines the number of VBLs that") + HELP_TEXT ("will be waited for between two flows of") + HELP_TEXT ("spray.") + HELP_TEXT ("") + HELP_TEXT ("- Mode: Defines whether you want to use a") + HELP_TEXT ("monochrome spray or a multi- colored one.") + HELP_TEXT ("") + HELP_TEXT ("- Mono-flow: Defines the number of") + HELP_TEXT ("paintbrushes that will be pasted in the") + HELP_TEXT ("circle of the spray at each cycle.") + HELP_TEXT ("") + HELP_TEXT ("- Palette: Left-click on a color of the") + HELP_TEXT ("palette to see how much it will be used in") + HELP_TEXT ("the multicolored flow, and modify it by") + HELP_TEXT ("using the gauge on the right. If the flow of") + HELP_TEXT ("this color was equal to 0, then the \"Init\"") + HELP_TEXT ("value will be applied. Or set the flow of a") + HELP_TEXT ("color to 0 by clicking on it with the right") + HELP_TEXT ("mouse button.") + HELP_TEXT ("") + HELP_TEXT ("- Clear: Removes all the colors from the") + HELP_TEXT ("multicolored flow. Actually, this puts a 0") + HELP_TEXT ("value in the use of each color.") + HELP_TEXT ("") + HELP_TEXT ("- Init: Allows you to define a value that") + HELP_TEXT ("will be set to the color you click on in the") + HELP_TEXT ("palette if its value is equal to 0. This") + HELP_TEXT ("permits to tag a set of colors more quickly.") + HELP_TEXT ("") + HELP_TEXT ("- +1,-1,x2,/2: Modify the values of all the") + HELP_TEXT ("tagged colors (and only them).") + HELP_TEXT ("") + HELP_TEXT ("") + HELP_TEXT ("Tip: If you often use the Shade mode, and") + HELP_TEXT ("are bored to click many times on a color to") + HELP_TEXT ("reach the color you want, you can define a") + HELP_TEXT ("spray with \"Size\"=1, \"Mono-flow\"=1, and") + HELP_TEXT ("\"Delay\"=2 (or more, according to your") + HELP_TEXT ("reflexes). And then, you'll just have to") + HELP_TEXT ("click a few hundredths of second to modify a") + HELP_TEXT ("color.") +}; +static const T_Help_table helptable_floodfill[] = +{ + HELP_TITLE("FLOODFILL") + HELP_TEXT ("") + HELP_BOLD ("LEFT CLICK") + HELP_LINK ("(Key:%s)",0x100+BUTTON_FLOODFILL) + HELP_TEXT ("") + HELP_TEXT ("Selects the filler as the active drawing") + HELP_TEXT ("tool. The filler, as any drawing tool, will") + HELP_TEXT ("be affected by all the effects!") + HELP_TEXT ("") + HELP_TEXT ("Note that only the visible part of the") + HELP_TEXT ("picture will be filled (as every other") + HELP_TEXT ("drawing tools, the floodfill only alters the") + HELP_TEXT ("visible part of the picture; this avoids") + HELP_TEXT ("unwanted effects that wouldn't be controlled") + HELP_TEXT ("by the user).") + HELP_TEXT ("") + HELP_BOLD ("RIGHT CLICK") + HELP_LINK ("(Key:%s)",0x200+BUTTON_FLOODFILL) + HELP_TEXT ("") + HELP_TEXT ("Selects the color replacement as the active") + HELP_TEXT ("drawing tool.") + HELP_TEXT ("") + HELP_TEXT ("Any rule has its exceptions and this one") + HELP_TEXT ("doesn't depart from that. Indeed, this tool") + HELP_TEXT ("is the only one to be affected by no effect") + HELP_TEXT ("(except Stencil) and to be able to modify") + HELP_TEXT ("non visible parts of the picture.") + HELP_TEXT ("The function of this tool being replacing") + HELP_TEXT ("all the occurences of a color in the picture") + HELP_TEXT ("by another, if would have been a shame to") + HELP_TEXT ("limit modifications only to the visible part") + HELP_TEXT ("of the picture.") +}; +static const T_Help_table helptable_polygons[] = +{ + HELP_TITLE("POLYGONS") + HELP_TITLE("POLYFORMS") + HELP_BOLD ("LEFT CLICK") + HELP_LINK ("(Key:%s)",0x100+BUTTON_POLYGONS) + HELP_TEXT ("") + HELP_TEXT ("Selects the polygons as the active drawing") + HELP_TEXT ("tool.") + HELP_TEXT ("") + HELP_TEXT ("This works just like knotted-lines but loops") + HELP_TEXT ("the extremities when you're finished.") + HELP_TEXT ("") + HELP_BOLD ("RIGHT CLICK") + HELP_LINK ("(Key:%s)",0x200+BUTTON_POLYGONS) + HELP_TEXT ("") + HELP_TEXT ("Selects the polyforms as the active drawing") + HELP_TEXT ("tool.") + HELP_TEXT ("") + HELP_TEXT ("This works like a combination of free-hand") + HELP_TEXT ("drawing and knotted-lines. If you keep the") + HELP_TEXT ("mouse button pressed, you'll draw as if you") + HELP_TEXT ("were in free-hand drawing mode. And, if you") + HELP_TEXT ("release the mouse button, it will work like") + HELP_TEXT ("knotted lines.") + HELP_TEXT ("") + HELP_TEXT ("Click on the opposite mouse button (i.e.:") + HELP_TEXT ("click right if you started to draw with the") + HELP_TEXT ("left mouse button, and vice versa) to") + HELP_TEXT ("terminate the operation. The two extremities") + HELP_TEXT ("will be linked automatically.") +}; +static const T_Help_table helptable_polyfill[] = +{ + HELP_TITLE("FILLED POLY") + HELP_LINK ("(Key:%s)",0x100+BUTTON_POLYFILL) + HELP_LINK ("(Key:%s)",0x200+BUTTON_POLYFILL) + HELP_TEXT (" Work exactly the same way as the polygons") + HELP_TEXT ("et polyforms above, but fill in the interior") + HELP_TEXT ("of the drawn shapes.") +}; +static const T_Help_table helptable_rectangles[] = +{ + HELP_TITLE("RECTANGLES") + HELP_LINK ("(Key:%s)",0x100+BUTTON_RECTANGLES) + HELP_TEXT ("") + HELP_TEXT ("Selects the empty rectangles as the active") + HELP_TEXT ("drawing tool.") + HELP_TEXT ("") + HELP_TEXT ("Set a corner of a rectangle. Maintain the") + HELP_TEXT ("click to move the opposite corner and") + HELP_TEXT ("release the mouse button to set it") + HELP_TEXT ("definitively.") +}; +static const T_Help_table helptable_filled_rectangles[] = +{ + HELP_TITLE("FILLED RECT") + HELP_LINK ("(Key:%s)",0x100+BUTTON_FILLRECT) + HELP_TEXT ("") + HELP_TEXT ("Selects the filled rectangles as the active") + HELP_TEXT ("drawing tool.") + HELP_TEXT ("") + HELP_TEXT ("Works like an empty rectangle.") +}; +static const T_Help_table helptable_circles[] = +{ + HELP_TITLE("CIRCLES") + HELP_TITLE("ELLIPSES") + HELP_TEXT ("") + HELP_BOLD ("LEFT CLICK") + HELP_LINK ("(Key:%s)",0x100+BUTTON_CIRCLES) + HELP_TEXT ("") + HELP_TEXT ("Selects the empty circles as the active") + HELP_TEXT ("drawing tool.") + HELP_TEXT ("") + HELP_TEXT ("Position the center of the cercle and") + HELP_TEXT ("maintain the mouse button to select its") + HELP_TEXT ("radius.") + HELP_TEXT ("") + HELP_BOLD ("RIGHT CLICK") + HELP_LINK ("(Key:%s)",0x200+BUTTON_CIRCLES) + HELP_TEXT ("") + HELP_TEXT ("Selects the empty ellipses as the active") + HELP_TEXT ("drawing tool.") + HELP_TEXT ("") + HELP_TEXT ("Position the center of the cercle and") + HELP_TEXT ("maintain the mouse button to select its") + HELP_TEXT ("dimensions.") +}; +static const T_Help_table helptable_filled_circles[] = +{ + HELP_TITLE("FILLED CIRCLES") + HELP_TITLE(" AND ELLIPSES") + HELP_TEXT ("") + HELP_BOLD ("FILLED CIRCLES") + HELP_LINK ("(Key:%s)",0x100+BUTTON_CIRCLES) + HELP_TEXT ("") + HELP_TEXT ("Works like empty circles.") + HELP_TEXT ("") + HELP_BOLD ("FILLED ELLIPSES") + HELP_LINK ("(Key:%s)",0x200+BUTTON_CIRCLES) + HELP_TEXT ("") + HELP_TEXT ("Works like empty ellipses.") +}; +static const T_Help_table helptable_grad_rect[] = +{ + HELP_TITLE("GRAD RECTANGLE") + HELP_TEXT ("") + HELP_BOLD ("LEFT CLICK") + HELP_LINK ("(Key:%s)",0x100+BUTTON_GRADRECT) + HELP_TEXT ("") + HELP_TEXT ("Selects the rectangle with gradations as") + HELP_TEXT ("the active drawing tool.") + HELP_TEXT ("") + HELP_TEXT ("Set a corner of a rectangle. Maintain the") + HELP_TEXT ("click to move the opposite corner and") + HELP_TEXT ("release the mouse button to set it") + HELP_TEXT ("definitively.") + HELP_TEXT ("") + HELP_TEXT ("If you don't like what you have done and") + HELP_TEXT ("want to restart, you can use the right") + HELP_TEXT ("click to cancel everything at this point.") + HELP_TEXT (" If you think it's nice, then click and hold") + HELP_TEXT ("the mouse in a point you want to have the") + HELP_TEXT ("starting color, drag to a point where you") + HELP_TEXT ("want the ending color, and release the") + HELP_TEXT ("button. You can press SHIFT to enforce your") + HELP_TEXT ("line to be vertical, horizontal, or") + HELP_TEXT ("diagonal.") + HELP_TEXT ("") + HELP_TEXT ("") + HELP_BOLD ("RIGHT CLICK") + HELP_LINK ("(Key:%s)",0x200+BUTTON_GRADRECT) + HELP_TEXT ("") + HELP_TEXT ("Opens a window where you can define the way") + HELP_TEXT ("gradations are processed. The different") + HELP_TEXT ("sections of this menu are:") + HELP_TEXT ("") + HELP_TEXT ("- Direction (arrow): Switches the direction") + HELP_TEXT ("of the gradation.") + HELP_TEXT ("") + HELP_TEXT ("- Dithering method: Toggles the 3 following") + HELP_TEXT ("methods:") + HELP_TEXT (" - No dithering") + HELP_TEXT (" - Basical dithering") + HELP_TEXT (" - Enhanced dithering") + HELP_TEXT ("") + HELP_TEXT ("- Mix: Mixes the gradation with a more or") + HELP_TEXT ("less random factor.") + HELP_TEXT ("") + HELP_TEXT ("- Palette: Select a color range to build a") + HELP_TEXT ("gradation.") + HELP_TEXT ("") + HELP_TEXT ("- Index scroller: Defines the current") + HELP_TEXT ("gradation among a set of 16 that will be") + HELP_TEXT ("memorised.") +}; +static const T_Help_table helptable_spheres[] = +{ + HELP_TITLE("GRAD SPHERE") + HELP_BOLD ("LEFT CLICK") + HELP_LINK ("(Key:%s)",0x100+BUTTON_SPHERES) + HELP_TEXT ("") + HELP_TEXT ("Selects the spheres as the active drawing") + HELP_TEXT ("tool.") + HELP_TEXT ("") + HELP_TEXT ("Position the center of the sphere and") + HELP_TEXT ("maintain the mouse button to select its") + HELP_TEXT ("radius. Then place the spot-light.") + HELP_TEXT ("") + HELP_BOLD ("RIGHT CLICK") + HELP_LINK ("(Key:%s)",0x200+BUTTON_SPHERES) + HELP_TEXT ("") + HELP_TEXT ("Selects the ellipses with gradation as the") + HELP_TEXT ("active drawing tool.") + HELP_TEXT ("") + HELP_TEXT ("Draw the shape like a normal ellipse, and") + HELP_TEXT ("then position the spot-light and click the") + HELP_TEXT ("left mouse button to finish the shape.") + HELP_TEXT ("") + HELP_TEXT ("") + HELP_TEXT ("If you trace a sphere or an ellipse with") + HELP_TEXT ("gradation with the right mouse button, the") + HELP_TEXT ("result will be the same figure filled with") + HELP_TEXT ("the Back-color.") +}; +static const T_Help_table helptable_brush[] = +{ + HELP_TITLE("GRAB BRUSH") + HELP_BOLD (" OR RESTORE BRUSH") + HELP_TEXT ("") + HELP_BOLD ("LEFT CLICK") + HELP_LINK ("(Key:%s)",0x100+BUTTON_BRUSH) + HELP_TEXT ("") + HELP_TEXT ("Engages a brush grabbing.") + HELP_TEXT ("") + HELP_TEXT ("Click on a corner of the rectangle") + HELP_TEXT ("containing the brush then maintain the click") + HELP_TEXT ("to define the opposite corner of the") + HELP_TEXT ("rectangle. Release the mouse button to grab") + HELP_TEXT ("the brush. Performing this operation with") + HELP_TEXT ("the right mouse button will erase the area") + HELP_TEXT ("where the brush was grabbed with the") + HELP_TEXT ("Back-color.") + HELP_TEXT ("") + HELP_BOLD ("RIGHT CLICK") + HELP_LINK ("(Key:%s)",0x200+BUTTON_BRUSH) + HELP_TEXT ("") + HELP_TEXT ("Restores the old brush.") +}; +static const T_Help_table helptable_polybrush[] = +{ + HELP_TITLE("POLY GRAB") + HELP_TEXT ("") + HELP_BOLD ("LEFT CLICK") + HELP_LINK ("(Key:%s)",0x100+BUTTON_POLYBRUSH) + HELP_TEXT ("") + HELP_TEXT ("Grabs a brush of any shape by defining a") + HELP_TEXT ("polyform (please refer to section 8 for more") + HELP_TEXT ("explanations).") + HELP_TEXT ("") + HELP_BOLD ("RIGHT CLICK") + HELP_LINK ("(Key:%s)",0x200+BUTTON_BRUSH) + HELP_TEXT ("") + HELP_TEXT ("Restores the old brush (same as above).") +}; +static const T_Help_table helptable_brush_fx[] = +{ + HELP_TITLE("BRUSH FX") + HELP_TEXT ("") + HELP_LINK ("(Key:%s)",0x100+BUTTON_BRUSH_EFFECTS) + HELP_TEXT ("") + HELP_TEXT ("Displays a menu where the following options") + HELP_TEXT ("are available:") + HELP_TEXT ("") + HELP_LINK ("- X: (Key:%s)",SPECIAL_FLIP_X) + HELP_TEXT ("Flip horizontally.") + HELP_TEXT ("") + HELP_LINK ("- Y: (Key:%s)",SPECIAL_FLIP_Y) + HELP_TEXT ("Flip vertically.") + HELP_TEXT ("") + HELP_LINK ("- Rotate by 90°: (Key:%s)",SPECIAL_ROTATE_90) + HELP_TEXT ("Rotates the brush by an angle of 90 degrees.") + HELP_TEXT ("") + HELP_LINK ("- Rotate by 180°: (Key:%s)",SPECIAL_ROTATE_180) + HELP_TEXT ("Rotates the brush by an angle of 180") + HELP_TEXT ("degrees.") + HELP_TEXT ("") + HELP_TEXT ("- Rotate by any angle:") + HELP_LINK ("(Key:%s)",SPECIAL_ROTATE_ANY_ANGLE) + HELP_TEXT ("Triggers an interactive operation that") + HELP_TEXT ("allows you to rotate the brush. For this,") + HELP_TEXT ("start by placing the center or rotation with") + HELP_TEXT ("the left mouse button (if, at this moment,") + HELP_TEXT ("you press the right button, the operation") + HELP_TEXT ("with be cancelled). After that, you can") + HELP_TEXT ("define the angle of rotation as many times") + HELP_TEXT ("as you want by moving the mouse and") + HELP_TEXT ("left-clicking. Then validate with the right") + HELP_TEXT ("button when you are satisfied. Meanwhile,") + HELP_TEXT ("you can press on the 8 outer digits of the") + HELP_TEXT ("numeric pad for defining angles multiple of") + HELP_TEXT ("45 degrees:") + HELP_TEXT ("") + HELP_TEXT (" 135 90 45") + HELP_TEXT (" \\ | /") + HELP_TEXT (" '7' '8' '9'") + HELP_TEXT (" 180 -'4' '6'- 0") + HELP_TEXT (" '1' '2' '3'") + HELP_TEXT (" / | \\") + HELP_TEXT (" 225 270 315") + HELP_TEXT ("") + HELP_LINK ("- Stretch: (Key:%s)",SPECIAL_STRETCH) + HELP_TEXT ("Triggers an interactive operation") + HELP_TEXT ("that enables you to stretch the brush. For") + HELP_TEXT ("this, start by placing the upper-left") + HELP_TEXT ("cornerof the brush with the left mouse") + HELP_TEXT ("button (if, at this moment, you press the") + HELP_TEXT ("right button, the operation will be") + HELP_TEXT ("cancelled). after that, you can place the") + HELP_TEXT ("opposite corner as many times as you need,") + HELP_TEXT ("then validate with the right mouse button") + HELP_TEXT ("when you are satisfied. If you place this") + HELP_TEXT ("point at coordinates inferior to the ones of") + HELP_TEXT ("the first point, the brush will be inverted.") + HELP_TEXT ("Meanwhile, you can press the following keys") + HELP_TEXT ("whose effects are: 'D' : double the") + HELP_TEXT ("brush in X and Y 'H' : reduce the") + HELP_TEXT ("brush by half in X and Y 'X' : double") + HELP_TEXT ("the brush in X 'Shift+X': reduce the brush") + HELP_TEXT ("by half in X 'Y' : double the brush") + HELP_TEXT ("in Y 'Shift+Y': reduce the brush by half") + HELP_TEXT ("in Y 'N' : restore the normal size of") + HELP_TEXT ("the brush (can be useful") + HELP_TEXT ("because it's the only way for cancelling)") + HELP_TEXT ("") + HELP_LINK ("- Distort: (Key:%s)",SPECIAL_DISTORT) + HELP_TEXT ("Triggers an interactive operation") + HELP_TEXT ("that allows you to distort your brush.") + HELP_TEXT ("Start by placing the brush somewhere on the") + HELP_TEXT ("screen and left-click. The brush will") + HELP_TEXT ("appear, with a little peg at each corner.") + HELP_TEXT ("Use the left mouse button to displace the") + HELP_TEXT ("corners, which will deform the brush.") + HELP_TEXT ("When you're done, click the right mouse") + HELP_TEXT ("button.") + HELP_TEXT ("") + HELP_LINK ("- Outline: (Key:%s)",SPECIAL_OUTLINE) + HELP_TEXT ("This option permits to draw the") + HELP_TEXT ("outlines of the brush with the Fore- color.") + HELP_TEXT ("") + HELP_LINK ("- Nibble: (Key:%s)",SPECIAL_NIBBLE) + HELP_TEXT ("This option \"nibbles\" the outlines") + HELP_TEXT ("of the brush. It's in some way the opposite") + HELP_TEXT ("effect of the Outline option.") + HELP_TEXT ("") + HELP_LINK ("- Recolorize: (Key:%s)",SPECIAL_RECOLORIZE_BRUSH) + HELP_TEXT ("Remaps the brush so that it") + HELP_TEXT ("looks like it would in the spare page, using") + HELP_TEXT ("the current palette.") + HELP_TEXT ("") + HELP_LINK ("- Get brush colors: (Key:%s)",SPECIAL_GET_BRUSH_COLORS) + HELP_TEXT ("Transfers the spare") + HELP_TEXT ("page's colors used by the brush to the") + HELP_TEXT ("current palette.") + HELP_TEXT ("") + HELP_TEXT ("- Brush handle:") + HELP_TEXT ("Allows you to choose where to place the") + HELP_TEXT ("handle of the brush. Shortcuts are :") + HELP_LINK (" Center : %s", SPECIAL_CENTER_ATTACHMENT) + HELP_LINK (" Top-left : %s", SPECIAL_TOP_LEFT_ATTACHMENT) + HELP_LINK (" Top-right : %s", SPECIAL_TOP_RIGHT_ATTACHMENT) + HELP_LINK (" Bottom-left : %s", SPECIAL_BOTTOM_LEFT_ATTACHMENT) + HELP_LINK (" Bottom-right: %s", SPECIAL_BOTTOM_RIGHT_ATTACHMENT) + HELP_TEXT ("") + HELP_LINK ("- Load : (Key:%s)",SPECIAL_LOAD_BRUSH) + HELP_TEXT ("Load a brush from disk.") + HELP_TEXT ("") + HELP_LINK ("- Save : (Key:%s)",SPECIAL_SAVE_BRUSH) + HELP_TEXT ("Save a brush to disk.") +}; +static const T_Help_table helptable_effects[] = +{ + HELP_TITLE("DRAW MODES") + HELP_LINK ("(Key:%s)",0x100+BUTTON_EFFECTS) + HELP_TEXT ("") + HELP_TEXT (" This button opens a menu where you can") + HELP_TEXT ("switch on or off the different drawing") + HELP_TEXT ("modes.") + HELP_TEXT (" In this menu, the \"All off\" button switches") + HELP_TEXT ("all the drawing modes off. The [Del] key") + HELP_TEXT ("is the keyboard shortcut for this button.") + HELP_TEXT (" The \"Feedback\" button is only used in") + HELP_TEXT ("\"Shade\", \"Quick-shade, \"Transparency\"") + HELP_TEXT ("and \"Smooth\" modes. When it is set, it means") + HELP_TEXT ("that the _current_ state of the picture") + HELP_TEXT ("has to be taken into account for the effect") + HELP_TEXT ("instead of the state in which the image") + HELP_TEXT ("was when you started to click for drawing.") + HELP_TEXT ("The best, as often, is that you try by") + HELP_TEXT ("yourself with and without Feedback to see") + HELP_TEXT ("the difference.") + HELP_TEXT (" The other buttons are the following:") + HELP_TEXT ("") + HELP_TITLE("SHADE") + HELP_TEXT (" It consists in increasing or decreasing the") + HELP_TEXT ("color number within a user-defined range.") + HELP_TEXT ("This shows its real dimension when used with") + HELP_TEXT ("a range of colors that shade off. Then,") + HELP_TEXT ("you can work on a part of your picture where") + HELP_TEXT ("colors belong to the same range without") + HELP_TEXT ("having to change your brush color all the") + HELP_TEXT ("time. You can choose the incrementation or") + HELP_TEXT ("decrementation of the color by pressing") + HELP_TEXT ("the left or right mouse button while") + HELP_TEXT ("drawing. If you click on a color that does") + HELP_TEXT ("not belong to the range, it will remain") + HELP_TEXT ("unchanged.") + HELP_BOLD ("LEFT CLICK") + HELP_LINK ("(Key : %s)", SPECIAL_SHADE_MODE) + HELP_TEXT ("") + HELP_TEXT ("Switches the Shade mode.") + HELP_TEXT ("") + HELP_BOLD ("RIGHT CLICK") + HELP_LINK ("(Key: %s)", SPECIAL_SHADE_MENU) + HELP_TEXT ("") + HELP_TEXT ("Opens a menu where you can define one table") + HELP_TEXT ("of shades within a range of 8 memorised by") + HELP_TEXT ("the program. The different sections of this") + HELP_TEXT ("menu are:") + HELP_TEXT ("") + HELP_TEXT ("- Palette: You can define in it the color") + HELP_TEXT ("blocks that will be inserted") + HELP_TEXT ("into the table of shades.") + HELP_TEXT ("") + HELP_TEXT ("- Scroller: Used to change flick through the") + HELP_TEXT ("tables of shades.") + HELP_TEXT ("") + HELP_TEXT ("- Table of shades definition area: The 512") + HELP_TEXT ("squares should be widely") + HELP_TEXT ("sufficient to define the different shades") + HELP_TEXT ("since every 256 colors of") + HELP_TEXT ("the palette cannot be present more than once") + HELP_TEXT ("in each table.") + HELP_TEXT ("") + HELP_TEXT ("- A window (on the top-right side) permits") + HELP_TEXT ("to visualize the different") + HELP_TEXT ("shades defined in he current table.") + HELP_TEXT ("") + HELP_TEXT ("- Copy: Copy the contents of the table in a") + HELP_TEXT ("buffer.") + HELP_TEXT ("(Each time you open this menu, the current") + HELP_TEXT ("table is automatically") + HELP_TEXT ("transfered into this buffer).") + HELP_TEXT ("") + HELP_TEXT ("- Paste: Copy the contents of the buffer") + HELP_TEXT ("above in the current table.") + HELP_TEXT ("") + HELP_TEXT ("- Clear: Reset the \"shades\" table.") + HELP_TEXT ("") + HELP_TEXT ("- Insert: Used to insert the block selected") + HELP_TEXT ("in the palette at the") + HELP_TEXT ("cursor's position in the table of shades.") + HELP_TEXT ("IF you click with the left mouse button on") + HELP_TEXT ("this button THEN IF a block of more than one") + HELP_TEXT ("color is selected in the table THEN It is") + HELP_TEXT ("deleted and the block defined in the palette") + HELP_TEXT ("is inserted. ELSE The block defined in the") + HELP_TEXT ("palette is inserted at the postion just") + HELP_TEXT ("before the selected square. END IF") + HELP_TEXT ("ELSE The block defined in the palette is") + HELP_TEXT ("inserted by erasing the colors following the") + HELP_TEXT ("beginning of the bloc selected in the table.") + HELP_TEXT ("END IF") + HELP_TEXT ("") + HELP_TEXT ("- Delete: Delete the block selected in the") + HELP_TEXT ("table.") + HELP_TEXT ("") + HELP_TEXT ("- Blank: Follows this algorithm:") + HELP_TEXT ("IF you click with the left mouse button on") + HELP_TEXT ("this button THEN Replace the block selected") + HELP_TEXT ("in the table by blank squares.") + HELP_TEXT ("ELSE IF a block of more than one color is") + HELP_TEXT ("selected in the table THEN Insert blank") + HELP_TEXT ("squares to the left and to the right of the") + HELP_TEXT ("block. (this is useful for isolating a") + HELP_TEXT ("shade quickly) ELSE Insert blank squares") + HELP_TEXT ("to the left of the selected square. END IF") + HELP_TEXT ("END IF") + HELP_TEXT ("") + HELP_TEXT ("- Invert: Invert the order of the block") + HELP_TEXT ("selected in the table.") + HELP_TEXT ("") + HELP_TEXT ("- Swap: Allows you you move a block (this") + HELP_TEXT ("exchanges it with what is") + HELP_TEXT ("where you want to move it).") + HELP_TEXT ("") + HELP_TEXT ("- Undo: Cancel the last modification of the") + HELP_TEXT ("table.") + HELP_TEXT ("") + HELP_TEXT ("- The 2 numbers displayed on the right of") + HELP_TEXT ("these buttons are: (above) - the number of") + HELP_TEXT ("the color selected in the palette if only") + HELP_TEXT ("one color is selected. (below) - the number") + HELP_TEXT ("of the color contained in a square in the") + HELP_TEXT ("shades table if this square is the only one") + HELP_TEXT ("selected.") + HELP_TEXT ("") + HELP_TEXT ("- The \"mode\" button displays 3 different") + HELP_TEXT ("modes:") + HELP_TEXT ("\"Normal\": Shades in the range and saturates") + HELP_TEXT ("to its boundaries.") + HELP_TEXT ("\"Loop\": Shades in the range and loops if") + HELP_TEXT ("boundaries are passed.") + HELP_TEXT ("\"No saturation\": Shades in the range and") + HELP_TEXT ("doesn't saturate if boundaries are passed.") + HELP_TEXT ("If the Step (see below) is set to 1, this") + HELP_TEXT ("option does exactly the same as the Normal") + HELP_TEXT ("mode.") + HELP_TEXT ("") + HELP_TEXT ("- Set/Disable: If you want to define several") + HELP_TEXT ("shades in the same table") + HELP_TEXT ("but you'd like these shades not to be") + HELP_TEXT ("effective at the same time, you") + HELP_TEXT ("can mask (disable) some parts of the table") + HELP_TEXT ("so that they will be") + HELP_TEXT ("interpreted a blank squares.") + HELP_TEXT ("To do that, select a block in the table of") + HELP_TEXT ("shades and click on \"Set\".") + HELP_TEXT ("The block will be underlined with a white") + HELP_TEXT ("line; this means that it is") + HELP_TEXT ("disabled.") + HELP_TEXT ("") + HELP_TEXT ("- Clear/Enable: This does exactly the") + HELP_TEXT ("opposite as the button above.") + HELP_TEXT ("") + HELP_TEXT ("- Step: Defines the step of incrementation") + HELP_TEXT ("of the shade. The bigger,") + HELP_TEXT ("the faster you run through the colors of the") + HELP_TEXT ("shade.") + HELP_TEXT ("For example: if the step is 2 and that you") + HELP_TEXT ("have defined a shade with") + HELP_TEXT ("the colors 0,1,4,5,9 and that you click on a") + HELP_TEXT ("pixel of color 1, it will") + HELP_TEXT ("take the value 5 which is 2 positions next") + HELP_TEXT ("in the la table.") + HELP_TEXT ("") + HELP_TEXT ("(We are sorry for these technical") + HELP_TEXT ("considerations quite far from a purely") + HELP_TEXT ("artistic point of view; but know that this") + HELP_TEXT ("effect is really very useful and it is") + HELP_TEXT ("preferable that you understand its whole") + HELP_TEXT ("functionment if you want to fully take") + HELP_TEXT ("advantage of it).") + HELP_TEXT ("") + HELP_TEXT ("") + HELP_TITLE("QUICK SHADE") + HELP_TEXT (" This drawing mode has about the same effect") + HELP_TEXT ("as Shade mode's except that it is faster") + HELP_TEXT ("to configurate but a little bit less") + HELP_TEXT ("powerful. When you draw on a color of the") + HELP_TEXT ("image which is between the fore- and the") + HELP_TEXT ("back-color in the palette, the color tends") + HELP_TEXT ("towards the fore-color (according to the") + HELP_TEXT ("step defined) if you draw with the left") + HELP_TEXT ("mouse button, or it tends towards the") + HELP_TEXT ("back-color if you are using the right mouse") + HELP_TEXT ("button.") + HELP_BOLD ("LEFT CLICK") + HELP_LINK ("(Key: %s)", SPECIAL_QUICK_SHADE_MODE) + HELP_TEXT ("") + HELP_TEXT ("Switches the Quick-shade mode.") + HELP_TEXT ("") + HELP_BOLD ("RIGHT CLICK") + HELP_LINK ("(Key: %s)", SPECIAL_QUICK_SHADE_MENU) + HELP_TEXT ("") + HELP_TEXT ("Opens a menu with a few parameters that mean") + HELP_TEXT ("exactly the same as in the menu of Shade") + HELP_TEXT ("mode. These parameters are the step and the") + HELP_TEXT ("loop/satu- ration mode (normal, loop, no") + HELP_TEXT ("saturation).") + HELP_TEXT ("") + HELP_TEXT ("") + HELP_TITLE("STENCIL") + HELP_TEXT (" It is used to prevent some colors from") + HELP_TEXT ("being modified if you draw on them. The") + HELP_TEXT ("main application of the stencil is when you") + HELP_TEXT ("want to change one color or more into") + HELP_TEXT ("another.") + HELP_BOLD ("LEFT CLICK") + HELP_LINK ("(Key: %s)", SPECIAL_STENCIL_MODE) + HELP_TEXT ("") + HELP_TEXT ("Switches the Stencil mode.") + HELP_TEXT ("") + HELP_BOLD ("RIGHT CLICK") + HELP_LINK ("(Key: %s)", SPECIAL_STENCIL_MENU) + HELP_TEXT ("") + HELP_TEXT ("Opens a menu where you can define a stencil.") + HELP_TEXT ("The different sections of this menu are:") + HELP_TEXT ("") + HELP_TEXT ("- Clear: No color is protected.") + HELP_TEXT ("") + HELP_TEXT ("- Invert: Colors that were protected are") + HELP_TEXT ("unprotected and vice versa.") + HELP_TEXT ("") + HELP_TEXT ("- Palette: Select colors that should be") + HELP_TEXT ("protected with the left mouse button or") + HELP_TEXT ("unprotect colors with the right mouse") + HELP_TEXT ("button.") + HELP_TEXT ("") + HELP_TEXT ("") + HELP_TITLE("MASK") + HELP_TEXT (" This effect could have been called \"True") + HELP_TEXT ("stencil\" because it protects some parts of") + HELP_TEXT ("the picture instead of some colors. The") + HELP_TEXT ("colors you tag represent the pixels in the") + HELP_TEXT ("spare page, corresponding to the pixels in") + HELP_TEXT ("the current page, that you don't want to") + HELP_TEXT ("alter. For example, draw a simple white") + HELP_TEXT ("figure on a black background in the spare") + HELP_TEXT ("page. Then, tag the black color in the menu") + HELP_TEXT ("of the Mask mode. When you'll draw in the") + HELP_TEXT ("current page, only the pixels corresponding") + HELP_TEXT ("to the white (non-black) ones in the spare") + HELP_TEXT ("page will be modified.") + HELP_BOLD ("LEFT CLICK") + HELP_LINK ("(Key: %s)", SPECIAL_MASK_MODE) + HELP_TEXT ("") + HELP_TEXT ("Switches the Mask mode.") + HELP_TEXT ("") + HELP_BOLD ("RIGHT CLICK") + HELP_LINK ("(Key: %s)", SPECIAL_MASK_MENU) + HELP_TEXT ("") + HELP_TEXT ("Opens a menu where you can set the colors of") + HELP_TEXT ("the Mask.") + HELP_TEXT ("This menu works the same way as the one of") + HELP_TEXT ("the Stencil, so please refer to the Stencil") + HELP_TEXT ("paragraph to know how to use it.") + HELP_TEXT ("") + HELP_TEXT ("") + HELP_TITLE("GRID") + HELP_TEXT (" This is useful to snap the cursor to the") + HELP_TEXT ("cross-points of a grid. It's generally") + HELP_TEXT ("used to draw a grid before drawing sprites") + HELP_TEXT ("of the same size such as a font or tiles,") + HELP_TEXT ("or for drawing figures or grabbing brushes") + HELP_TEXT ("with their dimensions multiple of the step") + HELP_TEXT ("of the grid.") + HELP_BOLD ("LEFT CLICK") + HELP_LINK ("(Key: %s)", SPECIAL_GRID_MODE) + HELP_TEXT ("") + HELP_TEXT ("Switches the Snap-to-grid mode.") + HELP_TEXT ("") + HELP_BOLD ("RIGHT CLICK") + HELP_LINK ("(Key: %s)", SPECIAL_GRID_MENU) + HELP_TEXT ("") + HELP_TEXT ("Opens a menu where you can define the grid") + HELP_TEXT ("parameters. These parameters are:") + HELP_TEXT ("") + HELP_TEXT ("- X,Y: Steps of the grid.") + HELP_TEXT ("") + HELP_TEXT ("- dX,dY: Offsets of the grid.") + HELP_TEXT ("") + HELP_TEXT ("") + HELP_TEXT ("The following shortcut hides or shows the") + HELP_TEXT ("grid in the magnified view:") + HELP_LINK ("%s", SPECIAL_SHOW_GRID) + HELP_TEXT ("The grid size will be according to your") + HELP_TEXT ("snap-to-grid settings.") + HELP_TEXT ("") + HELP_TEXT ("") + HELP_TITLE("SIEVE") + HELP_TEXT (" This effect allows you, by defining a") + HELP_TEXT ("pattern, to draw only on particular points") + HELP_TEXT ("of the picture. If you are a Manga drawer,") + HELP_TEXT ("you might find this useful to make patterned") + HELP_TEXT ("shades or color transitions.") + HELP_BOLD ("LEFT CLICK") + HELP_LINK ("(Key: %s)", SPECIAL_SIEVE_MODE) + HELP_TEXT ("") + HELP_TEXT ("Switches the Sieve mode.") + HELP_TEXT ("") + HELP_BOLD ("RIGHT CLICK") + HELP_LINK ("(Key: %s)", SPECIAL_SIEVE_MENU) + HELP_TEXT ("") + HELP_TEXT ("Opens a menu where you can define the Sieve") + HELP_TEXT ("parameters. This menu consists in:") + HELP_TEXT ("") + HELP_TEXT ("- 16x16 drawing area: You can define a") + HELP_TEXT ("pattern in it (left click => white pixel /") + HELP_TEXT ("right click => black pixel). All the white") + HELP_TEXT ("pixels indicate that, when you'll draw,") + HELP_TEXT ("pixels will be applied on the picture at the") + HELP_TEXT ("corresponding positions whereas black pixels") + HELP_TEXT ("won't modify the picture: whites pixels are") + HELP_TEXT ("the \"holes of the sieve\".") + HELP_TEXT ("") + HELP_TEXT ("- 12 default patterns: They can be copied to") + HELP_TEXT ("the drawing area.") + HELP_TEXT ("") + HELP_TEXT ("- \"Transfer to brush\": Copies the pattern to") + HELP_TEXT ("the brush (white pixels => Fore-color /") + HELP_TEXT ("black pixels => Back-color).") + HELP_TEXT ("") + HELP_TEXT ("- \"Get from brush\": Puts the brush into the") + HELP_TEXT ("drawing area (back-color => black pixels /") + HELP_TEXT ("others => white pixels).") + HELP_TEXT ("") + HELP_TEXT ("- Scrolling 4-arrows pad: Scrolls the") + HELP_TEXT ("pattern in the drawing area.") + HELP_TEXT ("") + HELP_TEXT ("- Resizing 4-arrows pad: Defines the") + HELP_TEXT ("dimensions of the pattern.") + HELP_TEXT ("") + HELP_TEXT ("- Default-value (black or white square):") + HELP_TEXT ("Indicates which value must be inserted when") + HELP_TEXT ("you increase the dimensions of the pattern.") + HELP_TEXT ("") + HELP_TEXT ("- \"Clear\": Sets the whole pattern with the") + HELP_TEXT ("default value (see above).") + HELP_TEXT ("") + HELP_TEXT ("- \"Invert\": It... inverts :) ... black and") + HELP_TEXT ("white pixels.") + HELP_LINK ("(Key: %s)", SPECIAL_INVERT_SIEVE) + HELP_TEXT ("") + HELP_TEXT ("") + HELP_TITLE("TRANSPARENCY") + HELP_TEXT (" This allows to mix the color(s) of the") + HELP_TEXT ("paintbrush with the colors of the picture.") + HELP_TEXT ("It's used to make transparency effects like") + HELP_TEXT ("with watercolors.") + HELP_TEXT ("") + HELP_TEXT ("You can also use the following shortcuts to") + HELP_TEXT ("activate transparency mode and assign an") + HELP_TEXT ("amount of opacity:") + HELP_LINK (" 10%% : %s", SPECIAL_TRANSPARENCY_1) + HELP_LINK (" 20%% : %s", SPECIAL_TRANSPARENCY_2) + HELP_LINK (" 30%% : %s", SPECIAL_TRANSPARENCY_3) + HELP_LINK (" 40%% : %s", SPECIAL_TRANSPARENCY_4) + HELP_LINK (" 50%% : %s", SPECIAL_TRANSPARENCY_5) + HELP_LINK (" 60%% : %s", SPECIAL_TRANSPARENCY_6) + HELP_LINK (" 70%% : %s", SPECIAL_TRANSPARENCY_7) + HELP_LINK (" 80%% : %s", SPECIAL_TRANSPARENCY_8) + HELP_LINK (" 90%% : %s", SPECIAL_TRANSPARENCY_9) + HELP_LINK (" 100%% : %s", SPECIAL_TRANSPARENCY_0) + HELP_TEXT ("If you use two of these shortcuts quickly,") + HELP_TEXT ("the second will set the units for finer") + HELP_TEXT ("control. Ie: 4 5 makes 45%, 0 9 makes 9%.") + HELP_TEXT ("") + HELP_BOLD ("LEFT CLICK") + HELP_LINK ("(Key: %s)", SPECIAL_COLORIZE_MODE) + HELP_TEXT ("") + HELP_TEXT ("Switches the Transparency mode.") + HELP_TEXT ("") + HELP_BOLD ("RIGHT CLICK") + HELP_LINK ("(Key: %s)", SPECIAL_COLORIZE_MENU) + HELP_TEXT ("") + HELP_TEXT ("Opens a menu where you can define the") + HELP_TEXT ("Transparency parameters. These parameters") + HELP_TEXT ("are:") + HELP_TEXT ("") + HELP_TEXT ("- Interpolation rate: Indicates the") + HELP_TEXT ("percentage of the applied color that will be") + HELP_TEXT ("considered upon the replaced color.") + HELP_TEXT ("") + HELP_TEXT ("- Interpolation method: Uses an") + HELP_TEXT ("interpolation algorithm to compute the") + HELP_TEXT ("color, according to the interpolation rate.") + HELP_TEXT ("") + HELP_TEXT ("- Additive method: Uses the lightest colors") + HELP_TEXT ("to choose the color to apply. For example:") + HELP_TEXT ("if you want to apply a color RGB:30,20,40 on") + HELP_TEXT ("a color RGB:10,50,20, the color applied will") + HELP_TEXT ("be the one, in the palette, that is the") + HELP_TEXT ("closest to the theoretic color RGB:30,50,40.") + HELP_TEXT ("") + HELP_TEXT ("- Subtractive method: uses the darkest") + HELP_TEXT ("colors to choose the color to apply. For") + HELP_TEXT ("example: if you want to apply a color") + HELP_TEXT ("RGB:30,20,40 on a color RGB:10,50,20, the") + HELP_TEXT ("color applied will be the one, in the") + HELP_TEXT ("palette, that is the closest to the") + HELP_TEXT ("theoretic color RGB:10,20,20.") + HELP_TEXT ("") + HELP_TEXT ("") + HELP_TITLE("SMOOTH") + HELP_TEXT (" It provides an easy but not as efficient") + HELP_TEXT ("anti-aliasing as any artist's touch.") + HELP_TEXT ("Anyway this effect finds a better use in") + HELP_TEXT ("making a blurry aspect.") + HELP_BOLD ("LEFT CLICK") + HELP_LINK ("(Key: %s)", SPECIAL_SMOOTH_MODE) + HELP_TEXT ("") + HELP_TEXT ("Switches the Smooth mode.") + HELP_TEXT ("") + HELP_BOLD ("RIGHT CLICK") + HELP_LINK ("(Key: %s)", SPECIAL_SMOOTH_MENU) + HELP_TEXT ("") + HELP_TEXT ("Opens a menu where you can define the Smooth") + HELP_TEXT ("matrix or choose one among the 4 ones") + HELP_TEXT ("predefined.") + HELP_TEXT ("The middle square represents the pixel on") + HELP_TEXT ("which you draw and the 8 others represent") + HELP_TEXT ("the neighbour pixels. Then, the point on") + HELP_TEXT ("which one draw will be replaced by the") + HELP_TEXT ("weighted average (according to values of") + HELP_TEXT ("each squares) of the 9 defined points.") + HELP_TEXT ("") + HELP_TEXT ("") + HELP_TITLE("SMEAR") + HELP_TEXT (" It smears pixels in the direction you are") + HELP_TEXT ("moving your paintbrush, just as if you") + HELP_TEXT ("wanted to spread fresh paint with your") + HELP_TEXT ("fingers. You can combine this effect with") + HELP_TEXT ("the transparency effect.") + HELP_TEXT ("") + HELP_LINK ("(Key: %s)", SPECIAL_SMEAR_MODE) + HELP_TEXT ("Switches the Smear mode.") + HELP_TEXT ("") + HELP_TEXT ("") + HELP_TITLE("TILING") + HELP_TEXT (" It consists in displaying parts of the") + HELP_TEXT ("brush that are adjusted on a tiling when") + HELP_TEXT ("you are drawing. It's mainly used for") + HELP_TEXT ("quickly drawing a background with a") + HELP_TEXT ("pattern, but there is a great number of") + HELP_TEXT ("other possibilities.") + HELP_BOLD ("LEFT CLICK") + HELP_LINK ("(Key: %s)", SPECIAL_TILING_MODE) + HELP_TEXT ("") + HELP_TEXT ("Switches the Tiling mode.") + HELP_TEXT ("") + HELP_BOLD ("RIGHT CLICK") + HELP_LINK ("(Key: %s)", SPECIAL_TILING_MENU) + HELP_TEXT ("") + HELP_TEXT ("Opens a menu where you can define the Tiling") + HELP_TEXT ("parameters. These parameters are the offsets") + HELP_TEXT ("of the tiling.") +}; +static const T_Help_table helptable_text[] = +{ + HELP_TITLE("TEXT") + HELP_TEXT ("") + HELP_LINK ("(Key:%s)",0x100+BUTTON_TEXT) + HELP_TEXT ("") + HELP_TEXT ("The text menu allows you to enter some text") + HELP_TEXT ("and render it as a brush.") + HELP_TEXT ("The current background and foreground colors") + HELP_TEXT ("are very important, they determine the text") + HELP_TEXT ("color, the transparent color, and also the") + HELP_TEXT ("color range to use for antialiasing.") + HELP_TEXT ("GrafX2 can use 'bitmap' fonts as long as") + HELP_TEXT ("they are in the special layout supported ") + HELP_TEXT ("by SFont.") + HELP_TEXT ("TrueType fonts can also be used if this") + HELP_TEXT ("version of GrafX2 was compiled with") + HELP_TEXT ("TrueType support.") + HELP_TEXT ("") + HELP_TEXT ("- Txt: Click and enter your text here, a") + HELP_TEXT ("line of up to 250 characters.") + HELP_TEXT ("") + HELP_TEXT ("- Clear txt: Empties the current text.") + HELP_TEXT ("When the text is empty, a standard string") + HELP_TEXT ("is shown instead in the preview area.") + HELP_TEXT ("") + HELP_TEXT ("- Antialias: Click to enable or disable") + HELP_TEXT ("Antialiasing. Only affects TrueType fonts.") + HELP_TEXT ("") + HELP_TEXT ("- Size: Determine the font height. Only") + HELP_TEXT ("affects TrueType fonts.") + HELP_TEXT ("") + HELP_TEXT ("- Font selector: Choose a font. You can") + HELP_TEXT ("use the arrow keys (up and down) to quickly") + HELP_TEXT ("browse your fonts.") + HELP_TEXT ("TrueType fonts are indicated by 'TT'.") + HELP_TEXT ("") + HELP_TEXT ("- Preview area: Shows what the brush will") + HELP_TEXT ("look like.") +}; +static const T_Help_table helptable_magnifier[] = +{ + HELP_TITLE("MAGNIFIER") + HELP_TEXT ("") + HELP_BOLD ("LEFT CLICK") + HELP_LINK ("(Key:%s)",0x100+BUTTON_MAGNIFIER) + HELP_TEXT ("") + HELP_TEXT ("Engages/Disengages the choice of the zoomed") + HELP_TEXT ("window. If you're already in magnifier mode,") + HELP_TEXT ("you'll return to normal mode.") + HELP_LINK ("Zoom in : %s",SPECIAL_ZOOM_IN) + HELP_LINK ("Zoom out: %s",SPECIAL_ZOOM_OUT) + HELP_TEXT ("") + HELP_BOLD ("RIGHT CLICK") + HELP_LINK ("(Key:%s)",0x200+BUTTON_MAGNIFIER) + HELP_TEXT ("") + HELP_TEXT ("Displays a menu where you can choose the") + HELP_TEXT ("magnifying factor.") + HELP_TEXT ("") + HELP_TEXT (" Note: When you are in Zoom mode, you can") + HELP_TEXT ("move the \"split\" bar by clicking on it and") + HELP_TEXT ("moving your mouse left or right while") + HELP_TEXT ("holding the mouse button down.") +}; +static const T_Help_table helptable_colorpicker[] = +{ + HELP_TITLE("PIPETTE") + HELP_TEXT ("") + HELP_BOLD ("LEFT CLICK") + HELP_LINK ("(Key:%s)",0x100+BUTTON_COLORPICKER) + HELP_TEXT ("") + HELP_TEXT ("Engages a color grabbing.") + HELP_TEXT ("") + HELP_TEXT ("Click on the picture to get the color of the") + HELP_TEXT ("pixel you're on. You can either get a new") + HELP_TEXT ("Fore-color or Back-color with respectively") + HELP_TEXT ("left or right mouse button.") + HELP_TEXT ("") + HELP_BOLD ("RIGHT CLICK") + HELP_LINK ("(Key:%s)",0x200+BUTTON_COLORPICKER) + HELP_TEXT ("") + HELP_TEXT ("Swap Fore-color and Back-color.") + HELP_TEXT ("") + HELP_TEXT (" The color currently pointed will be") + HELP_TEXT ("displayed in the tool-bar right after the") + HELP_TEXT ("coordinates. If you click outside the") + HELP_TEXT ("picture, the color 0 will be returned.") +}; +static const T_Help_table helptable_resolution[] = +{ + HELP_TITLE("RESOLUTION AND") + HELP_TITLE(" IMAGE SIZE") + HELP_TEXT ("") + HELP_BOLD ("LEFT CLICK") + HELP_LINK ("(Key:%s)",0x100+BUTTON_RESOL) + HELP_TEXT ("") + HELP_TEXT ("Displays a menu where you can define the") + HELP_TEXT ("size of your picture and choose the") + HELP_TEXT ("screen resolution.") + HELP_TEXT ("") + HELP_TEXT ("- Image size") + HELP_TEXT ("Click in the boxes named \"Width\" and") + HELP_TEXT ("\"Height\" to change the size of the image") + HELP_TEXT ("you're editing, up to 9999x9999.") + HELP_TEXT ("You can also right-click a video mode to") + HELP_TEXT ("copy its dimensions to the image's.") + HELP_TEXT ("") + HELP_TEXT ("- Pixel size") + HELP_TEXT ("If you choose any Pixel size other than") + HELP_TEXT ("Normal, Grafx2 will emulate a lower") + HELP_TEXT ("resolution by scaling up everything it") + HELP_TEXT ("displays, including the menus and mouse") + HELP_TEXT ("cursor. In Double, Triple and Quadruple") + HELP_TEXT ("mode, the image will appear zoomed x2, x3 or") + HELP_TEXT ("x4, keeping the original proportions. The") + HELP_TEXT ("scaling is done in software, with no linear") + HELP_TEXT ("interpolation, so it can't cause blur. This") + HELP_TEXT ("setting is especially useful if your") + HELP_TEXT ("hardware or drivers don't support the low") + HELP_TEXT ("resolutions you need, but it also allows you") + HELP_TEXT ("to draw in low-resolution while staying in") + HELP_TEXT ("window mode.") + HELP_TEXT ("If you choose one of the scalers called") + HELP_TEXT ("Wide, Tall, Wide2 and Tall2, this will") + HELP_TEXT ("emulate a video mode which has rectangular") + HELP_TEXT ("pixels (longer horizontally or vertically),") + HELP_TEXT ("like some video modes of the C64, Amstrad") + HELP_TEXT ("CPC, and Commodore Amiga.") + HELP_TEXT ("") + HELP_TEXT ("- Video mode") + HELP_TEXT ("Click on a video mode to select it.") + HELP_TEXT ("Grafx2 only lists modes that are detected") + HELP_TEXT ("as available on your computer. Depending on") + HELP_TEXT ("your video card and drivers, there can be") + HELP_TEXT ("a huge difference in the number of modes") + HELP_TEXT ("it can propose.") + HELP_TEXT ("The small buttons on the left-hand side of") + HELP_TEXT ("the lines in the list of modes have been") + HELP_TEXT ("designed to allow you to disable some modes") + HELP_TEXT ("that are not supported by your card. So, the") + HELP_TEXT ("modes that you will disable won't be used") + HELP_TEXT ("when loading pictures with \"Auto-set") + HELP_TEXT ("resolution\" ON.") + HELP_TEXT ("") + HELP_TEXT ("When you click on one of these buttons, its") + HELP_TEXT ("color changes to one of the 4 following. The") + HELP_TEXT ("signification for each color of these") + HELP_TEXT ("buttons is:") + HELP_TEXT ("") + HELP_TEXT ("- Light gray: The video mode is OK. It can") + HELP_TEXT ("be used by the auto-set resolution option") + HELP_TEXT ("when you load picture, and you can select it") + HELP_TEXT ("in the menu of resolutions.") + HELP_TEXT ("") + HELP_TEXT ("- White: It works exactly the same as above.") + HELP_TEXT ("Moreover, it allows you to tag your") + HELP_TEXT ("favourite modes. Indeed, the huge number of") + HELP_TEXT ("video modes makes it more difficult to find") + HELP_TEXT ("the mode your want in the list; so you can") + HELP_TEXT ("tag your favoutite ones in white, so that it") + HELP_TEXT ("will be easier to locate them. (Note: you") + HELP_TEXT ("cannot disable the standard windowed mode)") + HELP_TEXT ("") + HELP_TEXT ("- Dark gray: It allows you to indicate which") + HELP_TEXT ("modes are not really perfect (flickering,") + HELP_TEXT ("not centered, etc...) but which can be used") + HELP_TEXT ("even so. The difference with the light grey") + HELP_TEXT ("button is that these modes won't be used by") + HELP_TEXT ("the auto-set resolution option.") + HELP_TEXT ("") + HELP_TEXT ("- Black: Use it for totally unsupported") + HELP_TEXT ("modes. Thus, these modes won't be selected") + HELP_TEXT ("the \"auto-set res.\" and the program will") + HELP_TEXT ("not let you select them from the list of") + HELP_TEXT ("resolutions.") + HELP_TEXT ("") + HELP_BOLD ("RIGHT CLICK") + HELP_LINK ("(Key:%s)",0x200+BUTTON_RESOL) + HELP_TEXT ("") + HELP_TEXT (" Automaticaly switches to the 640x400 window") + HELP_TEXT ("mode.") +}; +static const T_Help_table helptable_page[] = +{ + HELP_TITLE("SPARE") + HELP_TEXT ("") + HELP_BOLD ("LEFT CLICK") + HELP_LINK ("(Key:%s)",0x100+BUTTON_PAGE) + HELP_TEXT ("") + HELP_TEXT ("Jumps to spare page. The current page is") + HELP_TEXT ("then considered as the new spare page, and") + HELP_TEXT ("the spare page considered as the new current") + HELP_TEXT ("page.") + HELP_TEXT ("") + HELP_BOLD ("RIGHT CLICK") + HELP_LINK ("(Key:%s)",0x200+BUTTON_PAGE) + HELP_TEXT ("") + HELP_TEXT ("Opens a menu where you can choose whether") + HELP_TEXT ("you want to copy the whole picture (keyboard") + HELP_TEXT ("short-cut in this menu is [Return]), only") + HELP_TEXT ("the pixels, only the palette, or only some") + HELP_TEXT ("colors.") + HELP_TEXT ("In this last case, a second menu") + HELP_TEXT ("(stencil-like) will propose you to tag the") + HELP_TEXT ("colors you want to copy (they are all") + HELP_TEXT ("selected by default).") + HELP_TEXT ("Please refer to section \"Stencil\" to know") + HELP_TEXT ("how to use this last menu.") + HELP_TEXT ("The last option the menu (\"Copy palette and") + HELP_TEXT ("remap\"), remaps the spare page with the") + HELP_TEXT ("current palette and replicates this palette") + HELP_TEXT ("to the spare page. This option is useful to") + HELP_TEXT ("quickly remap a picture with the palette of") + HELP_TEXT ("another.") +}; +static const T_Help_table helptable_save[] = +{ + HELP_TITLE("SAVE") + HELP_TEXT ("") + HELP_BOLD ("LEFT CLICK") + HELP_LINK ("(Key:%s)",0x100+BUTTON_SAVE) + HELP_TEXT ("") + HELP_TEXT ("Displays a fileselector where the following") + HELP_TEXT ("options are available:") + HELP_TEXT ("") + HELP_TEXT ("- Select drive: Allow you to change the") + HELP_TEXT ("current drive.or volume (depending on your") + HELP_TEXT ("operating system") + HELP_TEXT ("") + HELP_TEXT ("- Format: Allows you to choose the file") + HELP_TEXT ("format you want. (PAL and KCF file formats") + HELP_TEXT ("are \"palette\" files).") + HELP_TEXT ("") + HELP_TEXT ("- Filename: Allows you to give a new name to") + HELP_TEXT ("the picture. If no extension is given, the") + HELP_TEXT ("default (according to the format) will be") + HELP_TEXT ("used.") + HELP_TEXT ("") + HELP_TEXT ("- Bookmarks: The four dropdown buttons allow") + HELP_TEXT ("you to bookmark frequently used directories.") + HELP_TEXT ("Use right-click to open a contextual menu") + HELP_TEXT ("to Set it (memorize current directory),") + HELP_TEXT ("Rename it to change its label, and Clear it") + HELP_TEXT ("if you no longer need it. Use left-click to") + HELP_TEXT ("change to the memorized directory.") + HELP_TEXT ("") + HELP_TEXT ("- File-list: Allows you to flick through the") + HELP_TEXT ("disk tree or to overwrite an existing file.") + HELP_TEXT ("") + HELP_TEXT ("- Delete: Allows you to delete the item") + HELP_TEXT ("under the selection bar. If the item is a") + HELP_TEXT ("directory, it must be empty to be removed.") + HELP_TEXT ("") + HELP_TEXT ("- Save: Saves the picture with the current") + HELP_TEXT ("filename, with the chosen format. If the ") + HELP_TEXT ("current filename represents a directory,") + HELP_TEXT ("you'll enter it.") + HELP_TEXT ("") + HELP_TEXT ("- Comment (Txt): If you're using the PKM") + HELP_TEXT ("or PNG format, you can type in a comment on") + HELP_TEXT ("your picture. It will be memorized in the") + HELP_TEXT ("image.") + HELP_TEXT ("") + HELP_TEXT ("Note: The Backspace key brings you directly") + HELP_TEXT ("to the parent directory. You can also type") + HELP_TEXT ("the first letters of a filename you are") + HELP_TEXT ("looking for, to access it faster.") + HELP_TEXT ("") + HELP_BOLD ("RIGHT CLICK") + HELP_LINK ("(Key:%s)",0x200+BUTTON_SAVE) + HELP_TEXT ("") + HELP_TEXT ("Save the current picture with its current") + HELP_TEXT ("filename, format and comment.") + HELP_TEXT ("") + HELP_TEXT ("If the file already exists, a confirmation") + HELP_TEXT ("box will appear.") +}; +static const T_Help_table helptable_load[] = +{ + + HELP_TITLE("LOAD") + HELP_TEXT ("") + HELP_BOLD ("LEFT CLICK") + HELP_LINK ("(Key:%s)",0x100+BUTTON_LOAD) + HELP_TEXT ("") + HELP_TEXT ("This works the same way as Save.") + HELP_TEXT ("") + HELP_TEXT ("You'll have access in the format selector to") + HELP_TEXT ("a \"*.*\" filter. And of course, you won't be") + HELP_TEXT ("able to type in any comment.") + HELP_TEXT ("") + HELP_BOLD ("RIGHT CLICK") + HELP_LINK ("(Key:%s)",0x200+BUTTON_LOAD) + HELP_TEXT ("") + HELP_TEXT ("Reloads the picture.") + HELP_TEXT ("") + HELP_TEXT ("If you want to load a picture and that you") + HELP_TEXT ("haven't saved the last modifications of the") + HELP_TEXT ("current picture, a confirmation box will") + HELP_TEXT ("appear.") +}; +static const T_Help_table helptable_settings[] = +{ + HELP_TITLE("SETTINGS") + HELP_TEXT ("") + HELP_LINK ("(Key:%s)",0x100+BUTTON_SETTINGS) + HELP_TEXT ("") + HELP_TEXT ("Displays a menu where you can configure some") + HELP_TEXT ("miscellaneous elements of the program:") + HELP_TEXT ("") + HELP_TEXT ("- Number of UNDO pages: indicates the total") + HELP_TEXT ("number of pages that GrafX2 will memorize.") + HELP_TEXT ("Each time you modify the picture, its") + HELP_TEXT ("current state is memorized in one of these") + HELP_TEXT ("pages. To flick through these pages, use the") + HELP_TEXT ("\"Oops\" button (Undo/Redo).") + HELP_TEXT ("") + HELP_TEXT ("- Mouse sensibility: Modifies the speed of") + HELP_TEXT ("the mouse when you're in fullscreen. With") + HELP_TEXT ("the normal setting (slider on top), you may") + HELP_TEXT ("find the mouse too fast, especially in ") + HELP_TEXT ("video modes which are much smaller than your") + HELP_TEXT ("desktop. You can lower the slider to divide") + HELP_TEXT ("the speed by 2, 3 or 4.") + HELP_TEXT ("When using videomodes with native skewed") + HELP_TEXT ("pixels like 640x240 or 320x512, you'll") + HELP_TEXT ("probably want to use a stronger reduction") + HELP_TEXT ("on the axis which has less pixels.") + HELP_TEXT ("") + HELP_TEXT ("- Show/Hide in file list: Defines whether") + HELP_TEXT ("some particular files or directories must be") + HELP_TEXT ("displayed by the fileselectors or not.") + HELP_TEXT ("") + HELP_TEXT ("- Show/Hide picture limits: Indicates if the") + HELP_TEXT ("picture boundaries must be displayed when") + HELP_TEXT ("you are in a resolution bigger than the") + HELP_TEXT ("picture.") + HELP_TEXT ("") + HELP_TEXT ("- Clear palette: Indicates if loading a file") + HELP_TEXT ("with a palette of less than 256 colors must") + HELP_TEXT ("erase the rest of the current palette") + HELP_TEXT ("(replace by the black color).") + HELP_TEXT ("") + HELP_TEXT ("- Maximize preview: maximizes the preview of") + HELP_TEXT ("the pictures so that it is as big as") + HELP_TEXT ("possible. If you're not in the same") + HELP_TEXT ("resolution as the picture's one, it can try") + HELP_TEXT ("to correct the aspect ratio, but if the") + HELP_TEXT ("picture does not fill the whole screen, it") + HELP_TEXT ("can be worse.") + HELP_TEXT ("") + HELP_TEXT ("- Backup: when you'll save a picture over an") + HELP_TEXT ("existing file, the program will rename this") + HELP_TEXT ("file to \"*.BAK\" where * is the name of the") + HELP_TEXT ("picture without its extension. If the backup") + HELP_TEXT ("file already exists in the directory, it") + HELP_TEXT ("will be replaced. If you save a picture with") + HELP_TEXT ("the name of the backup file, no backup file") + HELP_TEXT ("will be created (of course!) ;).") + HELP_TEXT ("") + HELP_TEXT ("- Safety colors: Brings back the 4 default") + HELP_TEXT ("colors of the menus if you run an operation") + HELP_TEXT ("that passes the image in less than four") + HELP_TEXT ("colors in the palette editor.") + HELP_TEXT ("") + HELP_TEXT ("- Adjust brush pick: This option is used") + HELP_TEXT ("when you grab a brush in Grid (Snap) mode.") + HELP_TEXT ("Then, the right-most and down-most pixels") + HELP_TEXT ("won't be picked up with the rest of the") + HELP_TEXT ("brush. This option has been made because, if") + HELP_TEXT ("people grab brushes in Grid mode, that's") + HELP_TEXT ("mostly when they want to grab sprites. For") + HELP_TEXT ("example: if you have 16x16 sprites on your") + HELP_TEXT ("page, you'll set the grid mode to 16x16. But") + HELP_TEXT ("the cursor will snap at points like (0,0),") + HELP_TEXT ("(16,0), (16,16) and so on... And the problem") + HELP_TEXT ("is that, from (0,0) to (16,16), there are 17") + HELP_TEXT ("pixels! But if you keep the") + HELP_TEXT ("adjust-brush-pick option on, the unwanted") + HELP_TEXT ("pixels will be ignored. Moreover, this") + HELP_TEXT ("option adjusts the brush handle so that the") + HELP_TEXT ("brush still fits in the grid, instead of") + HELP_TEXT ("placing the handle in the center of the") + HELP_TEXT ("brush.") + HELP_TEXT ("") + HELP_TEXT ("- Separate colors: Draws a squaring around") + HELP_TEXT ("the colors of the tool-bar.") + HELP_TEXT ("") + HELP_TEXT ("- Auto-set resolution: sets the best") + HELP_TEXT ("resolution for the loaded image.") + HELP_TEXT ("") + HELP_TEXT ("- Coordinates: Choose if you want to display") + HELP_TEXT ("relative or absolute coordinates when using") + HELP_TEXT ("tools such as circles, rectangles, etc...") + HELP_TEXT ("for example, if you draw a circle: if coords") + HELP_TEXT ("are relative, the radius of the circle will") + HELP_TEXT ("be displayed, while in absolute coords, the") + HELP_TEXT ("coordinates of the cursor will be displayed.") + HELP_TEXT ("") + HELP_TEXT ("- Reload: loads the previously saved") + HELP_TEXT ("configuration.") + HELP_TEXT ("") + HELP_TEXT ("- Auto-save: means that the configuration") + HELP_TEXT ("will be automatically saved when you'll quit") + HELP_TEXT ("the program.") + HELP_TEXT ("") + HELP_TEXT ("- Save: saves the configuration at once.") + HELP_TEXT (" All modifications will be effective just") + HELP_TEXT ("after closing the menu.") + HELP_TEXT ("") + HELP_TITLE("SKINS") + HELP_TEXT ("") + HELP_TEXT ("This window allow you to change the look and") + HELP_TEXT ("feel of the program.") + HELP_TEXT ("") + HELP_TEXT ("- Font: determines whether you want to use") + HELP_TEXT ("GrafX2 with a classical font, or another one") + HELP_TEXT ("a bit funnier.") + HELP_TEXT ("") + HELP_TEXT ("- Cursor: allows you to choose whether you") + HELP_TEXT ("prefer a solid cursor or a transparent") + HELP_TEXT ("cursor.") + HELP_TEXT ("") + HELP_TEXT ("- Graphic file: you can change the whole") + HELP_TEXT ("interface by selecting where the sprites for") + HELP_TEXT ("all buttons are. Look at the files in the") + HELP_TEXT ("\"skin\" directory if you want to create your") + HELP_TEXT ("own. There are two skins available, the") + HELP_TEXT ("default for 2.1 is called modern. Classic is") + HELP_TEXT ("for nostalgics who wish to remember the old") + HELP_TEXT ("days of Sunset Design. If you create a good") + HELP_TEXT ("skin, feel free to share it with us! We may") + HELP_TEXT ("include it in a future release...") +}; +static const T_Help_table helptable_clear[] = +{ + + HELP_TITLE("CLEAR") + HELP_TEXT ("") + HELP_BOLD ("LEFT CLICK") + HELP_LINK ("(Key:%s)",0x100+BUTTON_CLEAR) + HELP_TEXT ("") + HELP_TEXT ("Clears the picture with the color number 0.") + HELP_TEXT ("") + HELP_BOLD ("RIGHT CLICK") + HELP_LINK ("(Key:%s)",0x200+BUTTON_CLEAR) + HELP_TEXT ("") + HELP_TEXT ("Clears the picture with the Back-color.") +}; +static const T_Help_table helptable_general[] = +{ + + HELP_TITLE("HELP STATS") + HELP_TEXT ("") + HELP_BOLD ("LEFT CLICK") + HELP_LINK ("(Key:%s)",0x100+BUTTON_HELP) + HELP_TEXT ("") + HELP_TEXT ("Displays an info window where you'll find") + HELP_TEXT ("some credits, help about the credits,") + HELP_TEXT ("different effects, greetings, registering...") + HELP_TEXT ("") + HELP_BOLD ("RIGHT CLICK") + HELP_LINK ("(Key:%s)",0x200+BUTTON_HELP) + HELP_TEXT ("") + HELP_TEXT ("Displays a window where you'll find") + HELP_TEXT ("miscellaneous informations about the system.") + HELP_TEXT (" Note: you should take care to keep more") + HELP_TEXT ("than 128 Kb in order to let the program") + HELP_TEXT ("run in a proper way.") +}; +static const T_Help_table helptable_undo[] = +{ + + HELP_TITLE("OOPS") + HELP_TEXT ("(UNDO/REDO)") + HELP_TEXT ("LEFT CLICK Allows you to undo the last") + HELP_TEXT ("modification on the picture.") + HELP_LINK ("(Key:%s)",0x100+BUTTON_UNDO) + HELP_TEXT ("") + HELP_TEXT ("RIGHT CLICK Allows you to redo the last") + HELP_TEXT ("modification undone on the picture.") + HELP_TEXT ("The maximum number of UNDO that you can") + HELP_TEXT ("perform can be defined in the settings") + HELP_TEXT ("menu.") + HELP_TEXT ("Undo/Redo aren't effective after page") + HELP_TEXT ("switching, picture loading and picture") + HELP_TEXT ("size modifications.") + HELP_LINK ("(Key:%s)",0x200+BUTTON_UNDO) +}; +static const T_Help_table helptable_kill[] = +{ + + HELP_TITLE("KILL") + HELP_TEXT ("KILL CURRENT PAGE") + HELP_TEXT ("") + HELP_LINK ("(Key:%s)",0x100+BUTTON_KILL) + HELP_TEXT ("") + HELP_TEXT ("Removes the current page from the list of") + HELP_TEXT ("\"Undo\" pages. This allows you to free some") + HELP_TEXT ("memory if you need it. For instance, this") + HELP_TEXT ("will allow you to delete the start-up page") + HELP_TEXT ("after having loaded an image. A message will") + HELP_TEXT ("appear if you've already erased all the") + HELP_TEXT ("pages except the last one.") + HELP_TEXT (" Note: Another way to free some memory is to") + HELP_TEXT ("decrease the number of \"Undo\" pages. Or") + HELP_TEXT ("else, if you have recentlt grabbed a very") + HELP_TEXT ("big brush that you don't use any more, you") + HELP_TEXT ("can grab a new smaller one. The memory") + HELP_TEXT ("allocated by the big brush will be thus") + HELP_TEXT ("freed.") +}; +static const T_Help_table helptable_quit[] = +{ + + HELP_TITLE("QUIT") + HELP_TEXT ("") + HELP_LINK ("(Key:%s)",0x100+BUTTON_QUIT) + HELP_TEXT ("") + HELP_TEXT ("Allows you to leave GrafX2. If there are") + HELP_TEXT ("unsaved modifications in the current or") + HELP_TEXT ("spare page, a confirmation box will ask you") + HELP_TEXT ("if you really want to quit GrafX2, if you") + HELP_TEXT ("want to save (Auto-save, no fileselector) or") + HELP_TEXT ("if you want to stay in GrafX2.") +}; +static const T_Help_table helptable_palette[] = +{ + + HELP_TITLE("PAL MENU") + HELP_TEXT ("") + HELP_BOLD ("LEFT CLICK") + HELP_LINK ("(Key:%s)",0x100+BUTTON_PALETTE) + HELP_TEXT ("") + HELP_TEXT ("Displays a menu where the following options") + HELP_TEXT ("are available:") + HELP_TEXT ("") + HELP_TEXT ("- Palette: Allows you to choose a") + HELP_TEXT ("color-block to edit. If you click with the") + HELP_TEXT ("right mouse button, you'll choose a new") + HELP_TEXT ("Back-color.") + HELP_TEXT ("") + HELP_TEXT ("- Gauges: Allow you to modify the") + HELP_TEXT ("current selection.") + HELP_TEXT ("") + HELP_TEXT ("- \"+\" and \"-\": Allow you to lighten or") + HELP_TEXT ("darken the current selection.") + HELP_TEXT ("") + HELP_TEXT ("- Default: Restores the predifined GrafX2") + HELP_TEXT ("palette.") + HELP_TEXT ("") + HELP_TEXT ("- Gray: Transforms the current selection") + HELP_TEXT ("into its gray-scaled equivalent.") + HELP_TEXT ("") + HELP_TEXT ("- Negative: Transforms the current selection") + HELP_TEXT ("into its reverse video equivalent.") + HELP_TEXT ("") + HELP_TEXT ("- Invert: Swaps the colors of the current") + HELP_TEXT ("selection so that the first colors become") + HELP_TEXT ("the last ones.") + HELP_TEXT ("") + HELP_TEXT ("- X-Invert: Works as above but modifies the") + HELP_TEXT ("picture so that it looks the same.") + HELP_TEXT ("") + HELP_TEXT ("- Swap: Swaps the current selection with") + HELP_TEXT ("another color-block. Click on the beginning") + HELP_TEXT ("of the new color-block.") + HELP_TEXT ("") + HELP_TEXT ("- X-Swap: Works as above but modifies the") + HELP_TEXT ("picture so that it looks the same. This may") + HELP_TEXT ("be useful if you want to sort your palette.") + HELP_TEXT ("") + HELP_TEXT ("- Copy: Copies the current selection to") + HELP_TEXT ("another color-block. Click on the beginning") + HELP_TEXT ("of the new color-block.") + HELP_TEXT ("") + HELP_TEXT ("- Spread: Computes a gradation between two") + HELP_TEXT ("colors. If your selection is only made up of") + HELP_TEXT ("one color, select the second color in the") + HELP_TEXT ("palette. Otherwise, the two colors used will") + HELP_TEXT ("be its extremities.") + HELP_TEXT ("") + HELP_TEXT ("- Sort: sorts the palette by color ranges.") + HELP_TEXT ("If you click with the left mouse button, it") + HELP_TEXT ("will sort by H S L; and if you click with") + HELP_TEXT ("the right mouse button, it will sort by L") + HELP_TEXT ("only. Note that you can choose a range of") + HELP_TEXT ("colors before sorting, and instead of the") + HELP_TEXT ("whole palette it will sort this range.") + HELP_TEXT ("") + HELP_TEXT ("- Used: Indicates the number of colors used") + HELP_TEXT ("in the picture.") + HELP_TEXT ("") + HELP_TEXT ("- Zap unused: Erases the unused colors with") + HELP_TEXT ("copies of the current selection. (The") + HELP_TEXT ("keyboard shortcut for this button is ).") + HELP_TEXT ("") + HELP_TEXT ("- HSL: Switches between RGB and HSL color") + HELP_TEXT ("spaces. In HSL mode, the three sliders") + HELP_TEXT ("allow you to set the Hue (tint), Saturation") + HELP_TEXT ("(from grayscale to pure color) and") + HELP_TEXT ("Lightness (from black to white).") + HELP_TEXT ("") + HELP_TEXT ("- Reduce: Allows you to reduce the palette") + HELP_TEXT ("to the number of colors you want (and") + HELP_TEXT ("modifies the picture).") + HELP_TEXT ("") + HELP_TEXT ("- Undo: Allows you to recover the last") + HELP_TEXT ("modifications made on the palette. If the") + HELP_TEXT ("last operation modified the picture, it") + HELP_TEXT ("won't recover them: you'll have to click on") + HELP_TEXT ("Cancel to do so.") + HELP_TEXT ("") + HELP_TEXT ("") + HELP_TEXT ("If you press , the program will") + HELP_TEXT ("replace, as well as possible, some unused") + HELP_TEXT ("colors by the four default colors of the") + HELP_TEXT ("menu. The image won't look altered because") + HELP_TEXT ("the modified colors (in the case they were") + HELP_TEXT ("used on a few points) will be replaced by") + HELP_TEXT ("the closest colors in the rest of the") + HELP_TEXT ("palette. This option is really useful when") + HELP_TEXT ("you modify the palette so that there are no") + HELP_TEXT ("colors that fit for the menu (eg: \"Zap") + HELP_TEXT ("unused\" while very little colors are used in") + HELP_TEXT ("the picture; or \"Reduce\" with a very small") + HELP_TEXT ("number of colors).") + HELP_TEXT ("") + HELP_TEXT ("If you press the key below or <,>") + HELP_TEXT ("(QWERTY), the menu will disappear and you") + HELP_TEXT ("will be able to pick up a color from the") + HELP_TEXT ("picture easily. Press to cancel.") + HELP_TEXT ("") + HELP_TEXT ("If only one color is selected (not a block),") + HELP_TEXT ("the <[> and <]> keys can be used to select") + HELP_TEXT ("the previous or next Forecolor (Backcolor if") + HELP_TEXT ("you press at the same time).") + HELP_TEXT ("") + HELP_TEXT ("Warning! If you press Undo after an action") + HELP_TEXT ("that modifies the picture (X-Swap, X-Invert") + HELP_TEXT ("and Reduce colors), the picture won't be") + HELP_TEXT ("remapped as it was just before this action.") + HELP_TEXT ("Only Cancel will.") + HELP_TEXT ("") + HELP_TITLE("PALETTE OPTIONS") + HELP_TEXT ("") + HELP_BOLD ("RIGHT CLICK") + HELP_LINK ("(Key:%s)",0x200+BUTTON_PALETTE) + HELP_TEXT ("") + HELP_TEXT ("Opens a menu from where you have the") + HELP_TEXT ("following options:") + HELP_TEXT ("") + HELP_TEXT ("- Colors for best match:") + HELP_TEXT ("A menu in which you can select the colors") + HELP_TEXT ("that have not to be used for smoothing, for") + HELP_TEXT ("the transparency mode, and for remapping.") + HELP_TEXT ("") + HELP_TEXT ("- User's color series:") + HELP_TEXT ("A menu in which you can define color series") + HELP_TEXT ("for next/previous user color shortcuts.") + HELP_TEXT ("It's the same settings than the shade mode.") + HELP_TEXT ("After you have some color ranges defined in") + HELP_TEXT ("this screen, you can use those shortcuts to") + HELP_TEXT ("move to the next or previous color according") + HELP_TEXT ("to your ranges:") + HELP_TEXT ("") + HELP_TEXT ("Foreground color") + HELP_TEXT ("") + HELP_LINK (" Next : %s", SPECIAL_NEXT_USER_FORECOLOR) + HELP_LINK (" Previous: %s", SPECIAL_PREVIOUS_USER_FORECOLOR) + HELP_TEXT ("") + HELP_TEXT ("Background color") + HELP_LINK (" Next : %s", SPECIAL_NEXT_USER_BACKCOLOR) + HELP_LINK (" Previous: %s", SPECIAL_PREVIOUS_USER_BACKCOLOR) + HELP_TEXT ("") + HELP_TEXT ("") + HELP_TEXT ("- Palette layout:") + HELP_TEXT ("Lets you customize the palette that appears") + HELP_TEXT ("on the right of the menu. You can choose the") + HELP_TEXT ("number of lines and columns.") + HELP_TEXT ("If you want the colors to run top to bottom,") + HELP_TEXT ("check the 'Vertical' button, otherwise the") + HELP_TEXT ("colors runs left to right.") + HELP_TEXT ("") + HELP_TEXT ("- RGB Scale:") + HELP_TEXT ("Lets you set the scale of the R G B sliders") + HELP_TEXT ("in the palette screen. You should normally") + HELP_TEXT ("leave it at 256 to get the full 0-255 range,") + HELP_TEXT ("but if you want to constrain the palette") + HELP_TEXT ("to the capabilities of some specific") + HELP_TEXT ("computers and consoles, you can choose eg:") + HELP_TEXT (" 64 : VGA") + HELP_TEXT (" 16 : Amiga") + HELP_TEXT (" 4 : MSX2") + HELP_TEXT (" 2 : Amstrad CPC") + }; +static const T_Help_table helptable_pal_scroll[] = +{ + + HELP_TITLE("SCROLL PAL") + HELP_TEXT ("") + HELP_BOLD ("LEFT CLICK") + HELP_TEXT ("") + HELP_TEXT ("Scrolls the palette window in the right of") + HELP_TEXT ("the menu.") + HELP_LINK ("Key for back: %s", 0x100+BUTTON_PAL_LEFT) + HELP_LINK ("Key for forward: %s", 0x100+BUTTON_PAL_RIGHT) + HELP_TEXT ("") + HELP_BOLD ("RIGHT CLICK") + HELP_TEXT ("") + HELP_TEXT ("Same as above, but faster.") + HELP_LINK ("Key for back: %s", 0x200+BUTTON_PAL_LEFT) + HELP_LINK ("Key for forward: %s", 0x200+BUTTON_PAL_RIGHT) + HELP_TEXT ("") +}; +static const T_Help_table helptable_color_select[] = +{ + + HELP_TITLE("PALETTE") + HELP_TEXT ("") + HELP_BOLD ("LEFT CLICK") + HELP_TEXT ("") + HELP_TEXT ("Defines the Fore-color.") + HELP_TEXT ("") + HELP_BOLD ("RIGHT CLICK") + HELP_TEXT ("") + HELP_TEXT ("Defines the Back-color.") +}; +static const T_Help_table helptable_hide[] = +{ + + HELP_TITLE("HIDE MENU") + HELP_TEXT ("") + HELP_TEXT ("Allows you to hide the menu. If you do this,") + HELP_TEXT ("take care to watch before the key to press") + HELP_TEXT ("to show the menu back (the key is") + HELP_LINK ("%s).",0x100+BUTTON_HIDE) + +}; + +#define HELP_TABLE_DECLARATION(x) {x, sizeof(x)/sizeof(const T_Help_table)}, + +T_Help_section Help_section[] = +{ + HELP_TABLE_DECLARATION(helptable_about) + HELP_TABLE_DECLARATION(helptable_licence) + HELP_TABLE_DECLARATION(helptable_help) + HELP_TABLE_DECLARATION(helptable_credits) + + // Attention, keep the same order as BUTTON_NUMBERS: + HELP_TABLE_DECLARATION(helptable_paintbrush) + HELP_TABLE_DECLARATION(helptable_adjust) + HELP_TABLE_DECLARATION(helptable_draw) + HELP_TABLE_DECLARATION(helptable_curves) + HELP_TABLE_DECLARATION(helptable_lines) + HELP_TABLE_DECLARATION(helptable_airbrush) + HELP_TABLE_DECLARATION(helptable_floodfill) + HELP_TABLE_DECLARATION(helptable_polygons) + HELP_TABLE_DECLARATION(helptable_polyfill) + HELP_TABLE_DECLARATION(helptable_rectangles) + HELP_TABLE_DECLARATION(helptable_filled_rectangles) + HELP_TABLE_DECLARATION(helptable_circles) + HELP_TABLE_DECLARATION(helptable_filled_circles) + HELP_TABLE_DECLARATION(helptable_grad_rect) + HELP_TABLE_DECLARATION(helptable_spheres) + HELP_TABLE_DECLARATION(helptable_brush) + HELP_TABLE_DECLARATION(helptable_polybrush) + HELP_TABLE_DECLARATION(helptable_brush_fx) + HELP_TABLE_DECLARATION(helptable_effects) + HELP_TABLE_DECLARATION(helptable_text) + HELP_TABLE_DECLARATION(helptable_magnifier) + HELP_TABLE_DECLARATION(helptable_colorpicker) + HELP_TABLE_DECLARATION(helptable_resolution) + HELP_TABLE_DECLARATION(helptable_page) + HELP_TABLE_DECLARATION(helptable_save) + HELP_TABLE_DECLARATION(helptable_load) + HELP_TABLE_DECLARATION(helptable_settings) + HELP_TABLE_DECLARATION(helptable_clear) + HELP_TABLE_DECLARATION(helptable_general) + HELP_TABLE_DECLARATION(helptable_undo) + HELP_TABLE_DECLARATION(helptable_kill) + HELP_TABLE_DECLARATION(helptable_quit) + HELP_TABLE_DECLARATION(helptable_palette) + HELP_TABLE_DECLARATION(helptable_pal_scroll) + HELP_TABLE_DECLARATION(helptable_pal_scroll) + HELP_TABLE_DECLARATION(helptable_color_select) + HELP_TABLE_DECLARATION(helptable_hide) +}; diff --git a/hotkeys.c b/hotkeys.c index 8d29852c..fba26f53 100644 --- a/hotkeys.c +++ b/hotkeys.c @@ -1,1235 +1,1460 @@ -/* Grafx2 - The Ultimate 256-color bitmap paint program - - Copyright 2008 Yves Rizoud - Copyright 2008 Adrien Destugues - Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) - - Grafx2 is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; version 2 - of the License. - - Grafx2 is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Grafx2; if not, see -*/ -#include "struct.h" -#include "global.h" -#include "hotkeys.h" - -T_Key_config ConfigKey[NB_SHORTCUTS] = { - {0, - "Scroll up", - "Scrolls the picture up, both in", - "magnify and normal mode.", - "", - false, - SDLK_UP, // HAUT - 0}, - {1, - "Scroll down", - "Scrolls the picture down, both in", - "magnify and normal mode.", - "", - false, - SDLK_DOWN, // BAS - 0}, - {2, - "Scroll left", - "Scrolls the picture to the left,", - "both in magnify and normal mode.", - "", - false, - SDLK_LEFT, // GAUCHE - 0}, - {3, - "Scroll right", - "Scrolls the picture to the right,", - "both in magnify and normal mode.", - "", - false, - SDLK_RIGHT, // DROITE - 0}, - {4, - "Faster scroll up", - "Used to scroll upwards in the", - "picture fast, either in magnify and", - "normal mode.", - true, - SDLK_UP|MOD_SHIFT, // Shift + Haut - 0}, - {5, - "Faster scroll down", - "Used to scroll downwards in the", - "picture fast, either in magnify and", - "normal mode.", - true, - SDLK_DOWN|MOD_SHIFT, // Shift + Bas - 0}, - {6, - "Faster scroll left", - "Used to scroll to the left in the", - "picture fast, either in magnify and", - "normal mode.", - true, - SDLK_LEFT|MOD_SHIFT, // Shift + Gauche - 0}, - {7, - "Faster scroll right", - "Used to scroll to the right in the", - "picture fast, either in magnify and", - "normal mode.", - true, - SDLK_RIGHT|MOD_SHIFT, // Shift + Droite - 0}, - {8, - "Slower scroll up", - "Used to scroll upwards in the", - "picture pixel by pixel, either in", - "magnify and normal mode.", - true, - SDLK_UP|MOD_ALT, // Alt + Haut - 0}, - {9, - "Slower scroll down", - "Used to scroll downwards in the", - "picture pixel by pixel, either in", - "magnify and normal mode.", - true, - SDLK_DOWN|MOD_ALT, // Alt + Bas - 0}, - {10, - "Slower scroll left", - "Used to scroll to the left in the", - "picture pixel by pixel, either in", - "magnify and normal mode.", - true, - SDLK_LEFT|MOD_ALT, // Alt + Gauche - 0}, - {11, - "Slower scroll right", - "Used to scroll to the right in the", - "picture pixel by pixel, either in", - "magnify and normal mode.", - true, - SDLK_RIGHT|MOD_ALT, // Alt + Droite - 0}, - {12, - "Move mouse cursor 1 pixel up", - "Used to simulate a very small mouse", - "deplacement up.It""s very useful", - "when you want ultra-high precision.", - true, - SDLK_UP|MOD_CTRL, // Ctrl + Haut - 0}, - {13, - "Move mouse cursor 1 pixel down", - "Used to simulate a very small mouse", - "deplacement down.It""s very useful", - "when you want ultra-high precision.", - true, - SDLK_DOWN|MOD_CTRL, // Ctrl + Bas - 0}, - {14, - "Move mouse cursor 1 pixel left", - "Used to simulate a very small mouse", - "deplacement left.It""s very useful", - "when you want ultra-high precision.", - true, - SDLK_LEFT|MOD_CTRL, // Ctrl + Gauche - 0}, - {15, - "Move mouse cursor 1 pixel right", - "Used to simulate a very small mouse", - "deplacement right.It""s very useful", - "when you want ultra-high precision.", - true, - SDLK_RIGHT|MOD_CTRL, // Ctrl + Droite - 0}, - {16, - "Simulate left mouse click", - "Used to simulate a click with the", - "left mouse button. It""s useful", - "when you want ultra-high precision.", - true, - SDLK_SPACE, // Space - 0}, - {17, - "Simulate right mouse click", - "Used to simulate a click with the", - "right mouse button.. It""s useful", - "when you want ultra-high precision.", - true, - SDLK_SPACE|MOD_SHIFT, // Shift + Space - 0}, - {18, - "Show/hide option menu", - "Switch the tool bar display on/off.", - "This hot-key cannot be removed.", - "", - false, - SDLK_F10, // F10 - 0}, - {19, - "Show/hide cursor", - "Switch the cursor display on/off.", - "This only works on the \"small cross\"", - "and \"hand\" cursors.", - true, - SDLK_F9, // F9 - 0}, - {20, - "Set paintbrush to 1 pixel", - "Useful when you want to use a", - "\"single-pixel-brush\".", - "", - true, - SDLK_DELETE, // Del - 0}, - {21, - "Paintbrush choice", - "Opens a menu where you can choose a", - "paintbrush out of 24 predefined", - "ones.", - true, - SDLK_F4, // F4 - 0}, - {22, - "Monochrome brush", - "Turn your current user-defined brush", - "into a single colored one. All non-", - "transparent colors are set to FG.", - true, - SDLK_F4|MOD_SHIFT, // Shift + F4 - 0}, - {23, - "Freehand drawing", - "Set the drawing mode to the", - "classical freehand one.", - "", - true, - SDLK_d, // D - 0}, - {24, - "Switch freehand drawing mode", - "Alternates between: continuous,", - "discontinuous, point by point,", - "and contour fill", - true, - SDLK_d|MOD_SHIFT, // Shift + D - 0}, - {25, - "Continuous freehand drawing", - "Switch directly to continuous", - "freehand drawing mode.", - "", - true, - SDLK_d|MOD_CTRL, // Ctrl + D - 0}, - {26, - "Line", - "Allows you to draw lines.", - "", - "", - true, - SDLK_l, // L - 0}, - {27, - "Knotted lines", - "Allows you to draw linked lines.", - "This mode can also be called", - "\"Polyline\".", - true, - SDLK_l|MOD_SHIFT, // Shift + L - 0}, - {28, - "Spray", - "Allows you to spray brushes", - "randomly in the picture.", - "", - true, - SDLK_a, // A (Q en AZERTY) - 0}, - {29, - "Spray menu", - "Opens a menu in which you can", - "configure the spray flow and size.", - "", - true, - SDLK_a|MOD_SHIFT, // Shift + A - 0}, - {30, - "Flood-fill", - "Allows you to fill an area of the", - "picture made of pixels of the same", - "color.", - true, - SDLK_f, // F - 0}, - {124, - "Replace color", - "This tool replaces all the pixels of", - "the clicked color to the fore-color", - "or the back-color.", - true, - SDLK_f|MOD_SHIFT, // Shift + F - 0}, - {31, - "Bezier""s curves", - "Allows you to draw Bezier""s curves.", - "", - "", - true, - SDLK_i, // I - 0}, - {32, - "Bezier""s curve with 3 or 4 points", - "Allows you to choose whether you", - "want to draw Bezier""s curves with", - "3 or 4 points.", - true, - SDLK_i|MOD_SHIFT, // Shift + I - 0}, - {33, - "Empty rectangle", - "Allows you to draw a rectangle using", - "the brush.", - "", - true, - SDLK_r, // R - 0}, - {34, - "Filled rectangle", - "Allows you to draw a filled", - "rectangle.", - "", - true, - SDLK_r|MOD_SHIFT, // Shift + R - 0}, - {35, - "Empty circle", - "Allows you to draw a circle using", - "the brush.", - "", - true, - SDLK_c, // C - 0}, - {36, - "Empty ellipse", - "Allows you to draw an ellipse using", - "the brush.", - "", - true, - SDLK_c|MOD_CTRL, // Ctrl + C - 0}, - {37, - "Filled circle", - "Allows you to draw a filled circle.", - "", - "", - true, - SDLK_c|MOD_SHIFT, // Shift + C - 0}, - {38, - "Filled ellipse", - "Allows you to draw a filled ellipse.", - "", - "", - true, - SDLK_c|MOD_SHIFT|MOD_CTRL, // Shift + Ctrl + C - 0}, - {39, - "Empty polygon", - "Allows you to draw a polygon using", - "the brush.", - "", - true, - SDLK_n, // N - 0}, - {40, - "Empty \"polyform\"", - "Allows you to draw a freehand", - "polygon using the brush.", - "", - true, - SDLK_n|MOD_CTRL, // Ctrl + N - 0}, - {41, - "Filled polygon", - "Allows you to draw a filled polygon.", - "", - "", - true, - SDLK_n|MOD_SHIFT, // Shift + N - 0}, - {42, - "Filled \"polyform\"", - "Allows you to draw a filled freehand", - "polygon.", - "", - true, - SDLK_n|MOD_SHIFT|MOD_CTRL, // Shift + Ctrl + N - 0}, - {43, - "Rectangle with gradation", - "Allows you to draw a rectangle with", - "a color gradation.", - "", - true, - SDLK_r|MOD_ALT, // Alt + R - 0}, - {44, - "Gradation menu", - "Allows you to configure the way", - "color gradations are calculated.", - "", - true, - SDLK_g|MOD_ALT, // Alt + G - 0}, - {45, - "Sphere with gradation", - "Allows you to draw a rectangle with", - "a color gradation.", - "", - true, - SDLK_c|MOD_ALT, // Alt + C - 0}, - {46, - "Ellipse with gradation", - "Allows you to draw an ellipse filled", - "with a color gradation.", - "", - true, - SDLK_c|MOD_SHIFT|MOD_ALT, // Shift + Alt + C - 0}, - {47, - "Adjust picture", - "Allows you to move the whole picture", - "Around. What gets out from a side", - "reappears on the other.", - true, - SDLK_KP5, // Kpad5 - 0}, - {48, - "Picture effects", - "Opens the 'Picture effects' window.", - "", - "", - true, - SDLK_KP5|MOD_SHIFT, // Shift + Kpad5 - 0}, - {49, - "Drawing effects", - "Opens a menu where you can enable/", - "disable and configure the drawing", - "effects.", - true, - SDLK_e, // E - 0}, - {50, - "Shade mode", - "Enables or disables Shade mode", - "", - "", - true, - SDLK_F5, // F5 - 0}, - {51, - "Shade menu", - "Opens a the menu for Shade settings.", - "", - "", - true, - SDLK_F5|MOD_SHIFT, // Shift + F5 - 0}, - {131, - "Quick-shade mode", - "Enables or disables Quick-shade", - "mode.", - "", - true, - SDLK_F5|MOD_CTRL, // Ctrl + F5 - 0}, - {132, - "Quick-shade menu", - "Opens a the menu for Quick-shade", - "settings.", - "", - true, - SDLK_F5|MOD_SHIFT|MOD_CTRL, // Shift + Ctrl + F5 - 0}, - {52, - "Stencil mode", - "Enables or disables Stencil mode.", - "", - "", - true, - SDLK_F6, // F6 - 0}, - {53, - "Stencil menu", - "Opens a the menu for Stencil", - "settings.", - "", - true, - SDLK_F6|MOD_SHIFT, // Shift + F6 - 0}, - {54, - "Mask mode", - "Enables or disables Mask mode.", - "", - "", - true, - SDLK_F6|MOD_ALT, // Alt + F6 - 0}, - {55, - "Mask menu", - "Opens a the menu for Mask settings.", - "", - "", - true, - SDLK_F6|MOD_SHIFT|MOD_ALT, // Shift + Alt + F6 - 0}, - {56, - "Grid mode", - "Enables or disables the Grid mode.", - "", - "", - true, - SDLK_g, // G - 0}, - {57, - "Grid menu", - "Open a menu where you can configure", - "the grid used by Grid mode.", - "", - true, - SDLK_g|MOD_SHIFT, // Shift + G - 0}, - {58, - "Sieve mode", - "Enables or disables the Sieve mode.", - "", - "", - true, - SDLK_g|MOD_CTRL, // Ctrl + G - 0}, - {59, - "Sieve menu", - "Opens a menu where you can configure", - "the sieve.", - "", - true, - SDLK_g|MOD_SHIFT|MOD_CTRL, // Shift + Ctrl + G - 0}, - {60, - "Invert sieve", - "Inverts the pattern defined in the", - "Sieve menu.", - "", - true, - SDLK_g|MOD_CTRL|MOD_ALT, // Ctrl + Alt + G - 0}, - {61, - "Colorize mode", - "Enables or disables the Colorize", - "mode.", - "", - true, - SDLK_F7, // F7 - 0}, - {62, - "Colorize menu", - "Opens a menu where you can give the", - "opacity percentage for Colorize", - "mode.", - true, - SDLK_F7|MOD_SHIFT, // Shift + F7 - 0}, - {63, - "Smooth mode", - "Enables or disables the Smooth", - "mode.", - "", - true, - SDLK_F8, // F8 - 0}, - {123, - "Smooth menu", - "Opens a menu where you can define", - "the Smooth matrix.", - "", - true, - SDLK_F8|MOD_SHIFT, // Shift + F8 - 0}, - {64, - "Smear mode", - "Enables or disables the Smear mode.", - "", - "", - true, - SDLK_F8|MOD_ALT, // Alt + F8 - 0}, - {65, - "Tiling mode", - "Enables or disables the Tiling", - "mode.", - "", - true, - SDLK_b|MOD_ALT, // Alt + B - 0}, - {66, - "Tiling menu", - "Opens a menu where you can configure", - "the origin of the tiling.", - "", - true, - SDLK_b|MOD_SHIFT|MOD_ALT, // Shift + Alt + B - 0}, - {67, - "Classical brush grabbing", - "Allows you to pick a brush defined", - "within a rectangle.", - "", - true, - SDLK_b, // B - 0}, - {68, - "\"Lasso\" brush grabbing", - "Allows you to pick a brush defined", - "within a freehand polygon.", - "", - true, - SDLK_b|MOD_CTRL, // Ctrl + B - 0}, - {69, - "Get previous brush back", - "Restore the last user-defined brush.", - "", - "", - true, - SDLK_b|MOD_SHIFT, // Shift + B - 0}, - {70, - "Horizontal brush flipping", - "Reverse brush horizontally.", - "", - "", - true, - SDLK_x, // X - 0}, - {71, - "Vertical brush flipping", - "Reverse brush vertically.", - "", - "", - true, - SDLK_y, // Y - 0}, - {72, - "90° brush rotation", - "Rotate the user-defined brush by 90°", - "(counter-clockwise).", - "", - true, - SDLK_z, // Z (W en AZERTY) - 0}, - {73, - "180° brush rotation", - "Rotate the user-defined brush by", - "180°.", - "", - true, - SDLK_z|MOD_SHIFT, // Shift + Z - 0}, - {74, - "Strech brush", - "Allows you to resize the", - "user-defined brush.", - "", - true, - SDLK_s, // S - 0}, - {75, - "Distort brush", - "Allows you to distort the", - "user-defined brush.", - "", - true, - SDLK_s|MOD_SHIFT, // Shift + S - 0}, - {76, - "Outline brush", - "Outlines the user-defined brush", - "with the fore color.", - "", - true, - SDLK_o, // O - 0}, - {77, - "Nibble brush", - "Deletes the borders of the", - "user-defined brush.This does the", - "opposite of the Outline option.", - true, - SDLK_o|MOD_SHIFT, // Shift + O - 0}, - {78, - "Get colors from brush", - "Copy colors of the spare page that", - "are used in the brush.", - "", - true, - SDLK_F11, // F11 - 0}, - {79, - "Recolorize brush", - "Recolorize the user-defined brush in", - "order to get a brush which looks as", - "if it was grabbed in the spare page.", - true, - SDLK_F12, // F12 - 0}, - {80, - "Rotate by any angle", - "Rotate the brush by an angle that", - "you can define.", - "", - true, - SDLK_w, // W (Z en AZERTY) - 0}, - {81, - "Pipette", - "Allows you to copy the color of a", - "pixel in the picture into the", - "foreground or background color.", - true, - SDLK_BACKQUOTE, // `~ (Key sous le Esc - ² en AZERTY) - 0}, - {82, - "Swap foreground/background colors", - "Invert foreground and background", - "colors.", - "", - true, - SDLK_BACKQUOTE|MOD_SHIFT, // Shift + `~ - 0}, - {83, - "Magnifier mode", - "Allows you to zoom into the picture.", - "", - "", - true, - SDLK_m, // M (, ? sur AZERTY) - KEY_MOUSEMIDDLE}, - {84, - "Zoom factor menu", - "Opens a menu where you can choose a", - "magnifying factor.", - "", - true, - SDLK_m|MOD_SHIFT, // Shift + M - 0}, - {85, - "Zoom in", - "Increase magnifying factor.", - "", - "", - true, - SDLK_KP_PLUS, // Grey + - KEY_MOUSEWHEELUP}, - {86, - "Zoom out", - "Decrease magnifying factor.", - "", - "", - true, - SDLK_KP_MINUS, // Grey - - KEY_MOUSEWHEELDOWN}, - {87, - "Brush effects menu", - "Opens a menu which proposes", - "different effects on the", - "user-defined brush.", - true, - SDLK_b|MOD_CTRL|MOD_ALT, // Ctrl + Alt + B - 0}, - {88, - "Text", - "Opens a menu which permits you to", - "type in a character string and", - "render it as a brush.", - true, - SDLK_t, // T - 0}, - {89, - "Screen resolution menu", - "Opens a menu where you can choose", - "the screen resolution and image", - "dimensions.", - true, - SDLK_RETURN, // Enter - 0}, - {90, - "\"Safety\" resolution", - "Resets the resolution to a 'safe'", - "mode that should work everywhere:", - "usually a 640x400 window.", - false, - SDLK_RETURN|MOD_SHIFT, // Shift + Enter - 0}, - {91, - "Help and credits", - "Opens a window where you can get", - "information about the program,", - "or contextual help.", - true, - SDLK_F1, // F1 - 0}, - {92, - "Statistics", - "Displays miscellaneous more or less", - "useful information.", - "", - true, - SDLK_F1|MOD_SHIFT, // Shift + F1 - 0}, - {93, - "Jump to spare page", - "Swap current page and spare page.", - "", - "", - true, - SDLK_TAB, // Tab - 0}, - {94, - "Copy current page to spare page", - "Copy current page to spare page.", - "", - "", - true, - SDLK_TAB|MOD_SHIFT, // Shift + Tab - 0}, - {95, - "Save picture as...", - "Opens a file-selector that allows", - "you to save your picture with a new", - "path-name.", - true, - SDLK_F2, // F2 - 0}, - {96, - "Save picture", - "Saves your picture with the last", - "name you gave it.", - "", - true, - SDLK_F2|MOD_SHIFT, // Shift + F2 - 0}, - {97, - "Load picture", - "Opens a file-selector that allows", - "you to load a new picture.", - "", - true, - SDLK_F3, // F3 - 0}, - {98, - "Re-load picture", - "Re-load the current picture. This", - "allows you to cancel modifications", - "made since last saving.", - true, - SDLK_F3|MOD_SHIFT, // Shift + F3 - 0}, - {99, - "Save brush", - "Opens a file-selector that allows", - "you to save your current", - "user-defined brush.", - true, - SDLK_F2|MOD_CTRL, // Ctrl + F2 - 0}, - {100, - "Load brush", - "Opens a file-selector that allows", - "you to load a brush.", - "", - true, - SDLK_F3|MOD_CTRL, // Ctrl + F3 - 0}, - {101, - "Settings", - "Opens a menu which permits you to", - "modify some parameters of the", - "program.", - true, - SDLK_F10|MOD_SHIFT, // Shift + F10 - 0}, - {102, - "Undo (Oops!)", - "Cancel the last action which", - "modified the picture.", - "", - true, - SDLK_u, // U - 0}, - {103, - "Redo", - "Redo the last undone action.", - "", - "", - true, - SDLK_u|MOD_SHIFT, // Shift + U - 0}, - {133, - "Kill", - "Kills the current page. It actually", - "removes the current page from the", - "list of \"Undo\" pages.", - true, - SDLK_DELETE|MOD_SHIFT, // Shift + Suppr - 0}, - {104, - "Clear page", - "Clears the picture with the first", - "color of the palette (usually black)", - "", - true, - SDLK_BACKSPACE, // BackSpace - 0}, - {105, - "Clear page with backcolor", - "Clears the picture with the", - "current backcolor.", - "", - true, - SDLK_BACKSPACE|MOD_SHIFT, // Shift + BackSpace - 0}, - {106, - "Quit program", - "Allows you to leave the program.", - "If modifications were not saved,", - "confirmation is asked.", - false, - SDLK_q, // Q (A en AZERTY) - 0}, - {107, - "Palette menu", - "Opens a menu which allows you to", - "modify the current palette.", - "", - true, - SDLK_p, // P - 0}, - {125, - "Secondary palette menu", - "Opens a menu which allows you to", - "define color series and some tagged", - "colors.", - true, - SDLK_p|MOD_SHIFT, // Shift + P - 0}, - {130, - "Exclude colors menu", - "Opens a menu which allows you to", - "define the colors you don""t want to", - "use in Smooth and Transparency", - true, - SDLK_p|MOD_CTRL, // Ctrl + P - 0}, - {108, - "Scroll palette to the left", - "Scroll palette in the tool bar to", - "the left, column by column.", - "", - true, - SDLK_PAGEUP, // PgUp - 0}, - {109, - "Scroll palette to the right", - "Scroll palette in the tool bar to", - "the right, column by column.", - "", - true, - SDLK_PAGEDOWN, // PgDn - 0}, - {110, - "Scroll palette to the left faster", - "Scroll palette in the tool bar to", - "the left, 8 columns by 8 columns.", - "", - true, - SDLK_PAGEUP|MOD_SHIFT, // Shift + PgUp - 0}, - {111, - "Scroll palette to the right faster", - "Scroll palette in the tool bar to", - "the right, 8 columns by 8 columns.", - "", - true, - SDLK_PAGEDOWN|MOD_SHIFT, // Shift + PgDn - 0}, - {112, - "Center brush attachment point", - "Set the attachement of the", - "user-defined brush to its center.", - "", - true, - SDLK_KP5|MOD_CTRL, // Ctrl + 5 (pavé numérique) - 0}, - {113, - "Top-left brush attachment point", - "Set the attachement of the", - "user-defined brush to its top-left", - "corner.", - true, - SDLK_HOME|MOD_CTRL, // Ctrl + 7 - 0}, - {114, - "Top-right brush attachment point", - "Set the attachement of the", - "user-defined brush to its top-right", - "corner.", - true, - SDLK_PAGEUP|MOD_CTRL, // Ctrl + 9 - 0}, - {115, - "Bottom-left brush attachment point", - "Set the attachement of the", - "user-defined brush to its", - "bottom-left corner.", - true, - SDLK_END|MOD_CTRL, // Ctrl + 1 - 0}, - {116, - "Bottom-right brush attachment point", - "Set the attachement of the", - "user-defined brush to its", - "bottom-right corner.", - true, - SDLK_PAGEDOWN|MOD_CTRL, // Ctrl + 3 - 0}, - {117, - "Next foreground color", - "Set the foreground color to the next", - "in the palette.", - "", - true, - SDLK_RIGHTBRACKET, // ] (0x en AZERTY) - 0}, - {118, - "Previous foreground color", - "Set the foreground color to the", - "previous in the palette.", - "", - true, - SDLK_LEFTBRACKET, // [ (^ en AZERTY) - 0}, - {119, - "Next background color", - "Set the background color to the next", - "in the palette.", - "", - true, - SDLK_RIGHTBRACKET|MOD_SHIFT, // Shift + ] - 0}, - {120, - "Previous background color", - "Set the background color to the", - "previous in the palette.", - "", - true, - SDLK_LEFTBRACKET|MOD_SHIFT, // Shift + [ - 0}, - {126, - "Next user-defined forecolor", - "Set the foreground color to the next", - "in the user-defined color series.", - "", - true, - SDLK_EQUALS, // "=+" - 0}, - {127, - "Previous user-defined forecolor", - "Set the foreground color to the", - "previous in the user-defined color", - "series.", - true, - SDLK_MINUS, // "-_" (")°" en AZERTY - 0}, - {128, - "Next user-defined backcolor", - "Set the background color to the next", - "in the user-defined color series.", - "", - true, - SDLK_EQUALS|MOD_SHIFT, // Shift + "=+" - 0}, - {129, - "Previous user-defined backcolor", - "Set the background color to the", - "previous in the user-defined color", - "series.", - true, - SDLK_MINUS|MOD_SHIFT, // Shift + "-_" (")°" en AZERTY - 0}, - {121, - "Shrink paintbrush", - "Decrease the width of the paintbrush", - "if it is special circle or square.", - "", - true, - SDLK_COMMA, // , < (;. en AZERTY) - 0}, - {122, - "Enlarge paintbrush", - "Increase the width of the paintbrush", - "if it is special circle or square.", - "", - true, - SDLK_PERIOD, // .> (:/ en AZERTY) - 0}, -}; - -word Ordering[NB_SHORTCUTS]= -{ - SPECIAL_SCROLL_UP, // Scroll up - SPECIAL_SCROLL_DOWN, // Scroll down - SPECIAL_SCROLL_LEFT, // Scroll left - SPECIAL_SCROLL_RIGHT, // Scroll right - SPECIAL_SCROLL_UP_FAST, // Scroll up faster - SPECIAL_SCROLL_DOWN_FAST, // Scroll down faster - SPECIAL_SCROLL_LEFT_FAST, // Scroll left faster - SPECIAL_SCROLL_RIGHT_FAST, // Scroll right faster - SPECIAL_SCROLL_UP_SLOW, // Scroll up slower - SPECIAL_SCROLL_DOWN_SLOW, // Scroll down slower - SPECIAL_SCROLL_LEFT_SLOW, // Scroll left slower - SPECIAL_SCROLL_RIGHT_SLOW, // Scroll right slower - SPECIAL_MOUSE_UP, // Emulate mouse up - SPECIAL_MOUSE_DOWN, // Emulate mouse down - SPECIAL_MOUSE_LEFT, // Emulate mouse left - SPECIAL_MOUSE_RIGHT, // Emulate mouse right - SPECIAL_CLICK_LEFT, // Emulate mouse click left - SPECIAL_CLICK_RIGHT, // Emulate mouse click right - 0x100+BUTTON_HIDE, // Show / Hide menu - SPECIAL_SHOW_HIDE_CURSOR, // Show / Hide cursor - SPECIAL_DOT_PAINTBRUSH, // Paintbrush = "." - 0x100+BUTTON_PAINTBRUSHES, // Paintbrush choice - 0x200+BUTTON_PAINTBRUSHES, // Monochrome brush - 0x100+BUTTON_DRAW, // Freehand drawing - 0x200+BUTTON_DRAW, // Switch freehand drawing mode - SPECIAL_CONTINUOUS_DRAW, // Continuous freehand drawing - 0x100+BUTTON_LINES, // Line - 0x200+BUTTON_LINES, // Knotted lines - 0x100+BUTTON_AIRBRUSH, // Spray - 0x200+BUTTON_AIRBRUSH, // Spray menu - 0x100+BUTTON_FLOODFILL, // Floodfill - 0x200+BUTTON_FLOODFILL, // Replace color - 0x100+BUTTON_CURVES, // Bézier's curves - 0x200+BUTTON_CURVES, // Bézier's curve with 3 or 4 points - 0x100+BUTTON_RECTANGLES, // Empty rectangle - 0x100+BUTTON_FILLRECT, // Filled rectangle - 0x100+BUTTON_CIRCLES, // Empty circle - 0x200+BUTTON_CIRCLES, // Empty ellipse - 0x100+BUTTON_FILLCIRC, // Filled circle - 0x200+BUTTON_FILLCIRC, // Filled ellipse - 0x100+BUTTON_POLYGONS, // Empty polygon - 0x200+BUTTON_POLYGONS, // Empty polyform - 0x100+BUTTON_POLYFILL, // Polyfill - 0x200+BUTTON_POLYFILL, // Filled polyform - 0x100+BUTTON_GRADRECT, // Gradient rectangle - 0x100+BUTTON_GRADMENU, // Gradation menu - 0x100+BUTTON_SPHERES, // Spheres - 0x200+BUTTON_SPHERES, // Gradient ellipses - 0x100+BUTTON_ADJUST, // Adjust picture - 0x200+BUTTON_ADJUST, // Flip picture menu - 0x100+BUTTON_EFFECTS, // Menu des effets - SPECIAL_SHADE_MODE, // Shade mode - SPECIAL_SHADE_MENU, // Shade menu - SPECIAL_QUICK_SHADE_MODE, // Quick-shade mode - SPECIAL_QUICK_SHADE_MENU, // Quick-shade menu - SPECIAL_STENCIL_MODE, // Stencil mode - SPECIAL_STENCIL_MENU, // Stencil menu - SPECIAL_MASK_MODE, // Mask mode - SPECIAL_MASK_MENU, // Mask menu - SPECIAL_GRID_MODE, // Grid mode - SPECIAL_GRID_MENU, // Grid menu - SPECIAL_SIEVE_MODE, // Sieve mode - SPECIAL_SIEVE_MENU, // Sieve menu - SPECIAL_INVERT_SIEVE, // Inverser la trame du mode Sieve - SPECIAL_COLORIZE_MODE, // Colorize mode - SPECIAL_COLORIZE_MENU, // Colorize menu - SPECIAL_SMOOTH_MODE, // Smooth mode - SPECIAL_SMOOTH_MENU, // Smooth menu - SPECIAL_SMEAR_MODE, // Smear mode - SPECIAL_TILING_MODE, // Tiling mode - SPECIAL_TILING_MENU, // Tiling menu - 0x100+BUTTON_BRUSH, // Pick brush - 0x100+BUTTON_POLYBRUSH, // Pick polyform brush - 0x200+BUTTON_BRUSH, // Restore brush - SPECIAL_FLIP_X, // Flip X - SPECIAL_FLIP_Y, // Flip Y - SPECIAL_ROTATE_90, // 90° brush rotation - SPECIAL_ROTATE_180, // 180° brush rotation - SPECIAL_STRETCH, // Stretch brush - SPECIAL_DISTORT, // Distort brush - SPECIAL_OUTLINE, // Outline brush - SPECIAL_NIBBLE, // Nibble brush - SPECIAL_GET_BRUSH_COLORS, // Get colors from brush - SPECIAL_RECOLORIZE_BRUSH, // Recolorize brush - SPECIAL_ROTATE_ANY_ANGLE, // Rotate brush by any angle - 0x100+BUTTON_COLORPICKER, // Pipette - 0x200+BUTTON_COLORPICKER, // Swap fore/back color - 0x100+BUTTON_MAGNIFIER, // Magnifier mode - 0x200+BUTTON_MAGNIFIER, // Zoom factor menu - SPECIAL_ZOOM_IN, // Zoom in - SPECIAL_ZOOM_OUT, // Zoom out - 0x100+BUTTON_BRUSH_EFFECTS, // Brush effects menu - 0x100+BUTTON_TEXT, // Text - 0x100+BUTTON_RESOL, // Resolution menu - 0x200+BUTTON_RESOL, // Safety resolution - 0x100+BUTTON_HELP, // Help & credits - 0x200+BUTTON_HELP, // Statistics - 0x100+BUTTON_PAGE, // Go to spare page - 0x200+BUTTON_PAGE, // Copy to spare page - 0x100+BUTTON_SAVE, // Save as - 0x200+BUTTON_SAVE, // Save - 0x100+BUTTON_LOAD, // Load - 0x200+BUTTON_LOAD, // Re-load - SPECIAL_SAVE_BRUSH, // Save brush - SPECIAL_LOAD_BRUSH, // Load brush - 0x100+BUTTON_SETTINGS, // Settings - 0x100+BUTTON_UNDO, // Undo - 0x200+BUTTON_UNDO, // Redo - 0x100+BUTTON_KILL, // Kill - 0x100+BUTTON_CLEAR, // Clear - 0x200+BUTTON_CLEAR, // Clear with backcolor - 0x100+BUTTON_QUIT, // Quit - 0x100+BUTTON_PALETTE, // Palette menu - 0x200+BUTTON_PALETTE, // Palette menu secondaire - SPECIAL_EXCLUDE_COLORS_MENU, // Exclude colors menu - 0x100+BUTTON_PAL_LEFT, // Scroll palette left - 0x100+BUTTON_PAL_RIGHT, // Scroll palette right - 0x200+BUTTON_PAL_LEFT, // Scroll palette left faster - 0x200+BUTTON_PAL_RIGHT, // Scroll palette right faster - SPECIAL_CENTER_ATTACHMENT, // Center brush attachement - SPECIAL_TOP_LEFT_ATTACHMENT, // Top-left brush attachement - SPECIAL_TOP_RIGHT_ATTACHMENT, // Top-right brush attachement - SPECIAL_BOTTOM_LEFT_ATTACHMENT, // Bottom-left brush attachement - SPECIAL_BOTTOM_RIGHT_ATTACHMENT, // Bottom right brush attachement - SPECIAL_NEXT_FORECOLOR, // Next foreground color - SPECIAL_PREVIOUS_FORECOLOR, // Previous foreground color - SPECIAL_NEXT_BACKCOLOR, // Next background color - SPECIAL_PREVIOUS_BACKCOLOR, // Previous background color - SPECIAL_NEXT_USER_FORECOLOR, // Next user-defined foreground color - SPECIAL_PREVIOUS_USER_FORECOLOR, // Previous user-defined foreground color - SPECIAL_NEXT_USER_BACKCOLOR, // Next user-defined background color - SPECIAL_PREVIOUS_USER_BACKCOLOR, // Previous user-defined background color - SPECIAL_SMALLER_PAINTBRUSH, // Rétrécir le pinceau - SPECIAL_BIGGER_PAINTBRUSH // Grossir le pinceau -}; +/* Grafx2 - The Ultimate 256-color bitmap paint program + + Copyright 2008 Yves Rizoud + Copyright 2008 Adrien Destugues + Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) + + Grafx2 is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 + of the License. + + Grafx2 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grafx2; if not, see +*/ +#include "struct.h" +#include "global.h" +#include "hotkeys.h" + +T_Key_config ConfigKey[NB_SHORTCUTS] = { + {0, + "Scroll up", + "Scrolls the picture up, both in", + "magnify and normal mode.", + "", + false, + SDLK_UP, // HAUT + 0}, + {1, + "Scroll down", + "Scrolls the picture down, both in", + "magnify and normal mode.", + "", + false, + SDLK_DOWN, // BAS + 0}, + {2, + "Scroll left", + "Scrolls the picture to the left,", + "both in magnify and normal mode.", + "", + false, + SDLK_LEFT, // GAUCHE + 0}, + {3, + "Scroll right", + "Scrolls the picture to the right,", + "both in magnify and normal mode.", + "", + false, + SDLK_RIGHT, // DROITE + 0}, + {4, + "Faster scroll up", + "Used to scroll upwards in the", + "picture fast, either in magnify and", + "normal mode.", + true, + SDLK_UP|MOD_SHIFT, // Shift + Haut + 0}, + {5, + "Faster scroll down", + "Used to scroll downwards in the", + "picture fast, either in magnify and", + "normal mode.", + true, + SDLK_DOWN|MOD_SHIFT, // Shift + Bas + 0}, + {6, + "Faster scroll left", + "Used to scroll to the left in the", + "picture fast, either in magnify and", + "normal mode.", + true, + SDLK_LEFT|MOD_SHIFT, // Shift + Gauche + 0}, + {7, + "Faster scroll right", + "Used to scroll to the right in the", + "picture fast, either in magnify and", + "normal mode.", + true, + SDLK_RIGHT|MOD_SHIFT, // Shift + Droite + 0}, + {8, + "Slower scroll up", + "Used to scroll upwards in the", + "picture pixel by pixel, either in", + "magnify and normal mode.", + true, + SDLK_UP|MOD_ALT, // Alt + Haut + 0}, + {9, + "Slower scroll down", + "Used to scroll downwards in the", + "picture pixel by pixel, either in", + "magnify and normal mode.", + true, + SDLK_DOWN|MOD_ALT, // Alt + Bas + 0}, + {10, + "Slower scroll left", + "Used to scroll to the left in the", + "picture pixel by pixel, either in", + "magnify and normal mode.", + true, + SDLK_LEFT|MOD_ALT, // Alt + Gauche + 0}, + {11, + "Slower scroll right", + "Used to scroll to the right in the", + "picture pixel by pixel, either in", + "magnify and normal mode.", + true, + SDLK_RIGHT|MOD_ALT, // Alt + Droite + 0}, + {12, + "Move mouse cursor 1 pixel up", + "Used to simulate a very small mouse", + "deplacement up.It""s very useful", + "when you want ultra-high precision.", + true, + SDLK_UP|MOD_CTRL, // Ctrl + Haut + 0}, + {13, + "Move mouse cursor 1 pixel down", + "Used to simulate a very small mouse", + "deplacement down.It""s very useful", + "when you want ultra-high precision.", + true, + SDLK_DOWN|MOD_CTRL, // Ctrl + Bas + 0}, + {14, + "Move mouse cursor 1 pixel left", + "Used to simulate a very small mouse", + "deplacement left.It""s very useful", + "when you want ultra-high precision.", + true, + SDLK_LEFT|MOD_CTRL, // Ctrl + Gauche + 0}, + {15, + "Move mouse cursor 1 pixel right", + "Used to simulate a very small mouse", + "deplacement right.It""s very useful", + "when you want ultra-high precision.", + true, + SDLK_RIGHT|MOD_CTRL, // Ctrl + Droite + 0}, + {16, + "Simulate left mouse click", + "Used to simulate a click with the", + "left mouse button. It""s useful", + "when you want ultra-high precision.", + true, + SDLK_SPACE, // Space + 0}, + {17, + "Simulate right mouse click", + "Used to simulate a click with the", + "right mouse button.. It""s useful", + "when you want ultra-high precision.", + true, + SDLK_SPACE|MOD_SHIFT, // Shift + Space + 0}, + {18, + "Show/hide option menu", + "Switch the tool bar display on/off.", + "This hot-key cannot be removed.", + "", + false, + SDLK_F10, // F10 + 0}, + {19, + "Show/hide cursor", + "Switch the cursor display on/off.", + "This only works on the \"small cross\"", + "and \"hand\" cursors.", + true, + SDLK_F9, // F9 + 0}, + {20, + "Set paintbrush to 1 pixel", + "Useful when you want to use a", + "\"single-pixel-brush\".", + "", + true, + SDLK_DELETE, // Del + 0}, + {21, + "Paintbrush choice", + "Opens a menu where you can choose a", + "paintbrush out of 24 predefined", + "ones.", + true, + SDLK_F4, // F4 + 0}, + {22, + "Monochrome brush", + "Turn your current user-defined brush", + "into a single colored one. All non-", + "transparent colors are set to FG.", + true, + SDLK_F4|MOD_SHIFT, // Shift + F4 + 0}, + {23, + "Freehand drawing", + "Set the drawing mode to the", + "classical freehand one.", + "", + true, + SDLK_d, // D + 0}, + {24, + "Switch freehand drawing mode", + "Alternates between: continuous,", + "discontinuous, point by point,", + "and contour fill", + true, + SDLK_d|MOD_SHIFT, // Shift + D + 0}, + {25, + "Continuous freehand drawing", + "Switch directly to continuous", + "freehand drawing mode.", + "", + true, + SDLK_d|MOD_CTRL, // Ctrl + D + 0}, + {26, + "Line", + "Allows you to draw lines.", + "", + "", + true, + SDLK_l, // L + 0}, + {27, + "Knotted lines", + "Allows you to draw linked lines.", + "This mode can also be called", + "\"Polyline\".", + true, + SDLK_l|MOD_SHIFT, // Shift + L + 0}, + {28, + "Spray", + "Allows you to spray brushes", + "randomly in the picture.", + "", + true, + SDLK_a, // A (Q en AZERTY) + 0}, + {29, + "Spray menu", + "Opens a menu in which you can", + "configure the spray flow and size.", + "", + true, + SDLK_a|MOD_SHIFT, // Shift + A + 0}, + {30, + "Flood-fill", + "Allows you to fill an area of the", + "picture made of pixels of the same", + "color.", + true, + SDLK_f, // F + 0}, + {124, + "Replace color", + "This tool replaces all the pixels of", + "the clicked color to the fore-color", + "or the back-color.", + true, + SDLK_f|MOD_SHIFT, // Shift + F + 0}, + {31, + "Bezier""s curves", + "Allows you to draw Bezier""s curves.", + "", + "", + true, + SDLK_i, // I + 0}, + {32, + "Bezier""s curve with 3 or 4 points", + "Allows you to choose whether you", + "want to draw Bezier""s curves with", + "3 or 4 points.", + true, + SDLK_i|MOD_SHIFT, // Shift + I + 0}, + {33, + "Empty rectangle", + "Allows you to draw a rectangle using", + "the brush.", + "", + true, + SDLK_r, // R + 0}, + {34, + "Filled rectangle", + "Allows you to draw a filled", + "rectangle.", + "", + true, + SDLK_r|MOD_SHIFT, // Shift + R + 0}, + {35, + "Empty circle", + "Allows you to draw a circle using", + "the brush.", + "", + true, + SDLK_c, // C + 0}, + {36, + "Empty ellipse", + "Allows you to draw an ellipse using", + "the brush.", + "", + true, + SDLK_c|MOD_CTRL, // Ctrl + C + 0}, + {37, + "Filled circle", + "Allows you to draw a filled circle.", + "", + "", + true, + SDLK_c|MOD_SHIFT, // Shift + C + 0}, + {38, + "Filled ellipse", + "Allows you to draw a filled ellipse.", + "", + "", + true, + SDLK_c|MOD_SHIFT|MOD_CTRL, // Shift + Ctrl + C + 0}, + {39, + "Empty polygon", + "Allows you to draw a polygon using", + "the brush.", + "", + true, + SDLK_n, // N + 0}, + {40, + "Empty \"polyform\"", + "Allows you to draw a freehand", + "polygon using the brush.", + "", + true, + SDLK_n|MOD_CTRL, // Ctrl + N + 0}, + {41, + "Filled polygon", + "Allows you to draw a filled polygon.", + "", + "", + true, + SDLK_n|MOD_SHIFT, // Shift + N + 0}, + {42, + "Filled \"polyform\"", + "Allows you to draw a filled freehand", + "polygon.", + "", + true, + SDLK_n|MOD_SHIFT|MOD_CTRL, // Shift + Ctrl + N + 0}, + {43, + "Rectangle with gradation", + "Allows you to draw a rectangle with", + "a color gradation.", + "", + true, + SDLK_r|MOD_ALT, // Alt + R + 0}, + {44, + "Gradation menu", + "Allows you to configure the way", + "color gradations are calculated.", + "", + true, + SDLK_g|MOD_ALT, // Alt + G + 0}, + {45, + "Sphere with gradation", + "Allows you to draw a rectangle with", + "a color gradation.", + "", + true, + SDLK_c|MOD_ALT, // Alt + C + 0}, + {46, + "Ellipse with gradation", + "Allows you to draw an ellipse filled", + "with a color gradation.", + "", + true, + SDLK_c|MOD_SHIFT|MOD_ALT, // Shift + Alt + C + 0}, + {47, + "Adjust picture", + "Allows you to move the whole picture", + "Around. What gets out from a side", + "reappears on the other.", + true, + SDLK_KP5, // Kpad5 + 0}, + {48, + "Picture effects", + "Opens the 'Picture effects' window.", + "", + "", + true, + SDLK_KP5|MOD_SHIFT, // Shift + Kpad5 + 0}, + {49, + "Drawing effects", + "Opens a menu where you can enable/", + "disable and configure the drawing", + "effects.", + true, + SDLK_e, // E + 0}, + {50, + "Shade mode", + "Enables or disables Shade mode", + "", + "", + true, + SDLK_F5, // F5 + 0}, + {51, + "Shade menu", + "Opens a the menu for Shade settings.", + "", + "", + true, + SDLK_F5|MOD_SHIFT, // Shift + F5 + 0}, + {131, + "Quick-shade mode", + "Enables or disables Quick-shade", + "mode.", + "", + true, + SDLK_F5|MOD_CTRL, // Ctrl + F5 + 0}, + {132, + "Quick-shade menu", + "Opens a the menu for Quick-shade", + "settings.", + "", + true, + SDLK_F5|MOD_SHIFT|MOD_CTRL, // Shift + Ctrl + F5 + 0}, + {52, + "Stencil mode", + "Enables or disables Stencil mode.", + "", + "", + true, + SDLK_F6, // F6 + 0}, + {53, + "Stencil menu", + "Opens a the menu for Stencil", + "settings.", + "", + true, + SDLK_F6|MOD_SHIFT, // Shift + F6 + 0}, + {54, + "Mask mode", + "Enables or disables Mask mode.", + "", + "", + true, + SDLK_F6|MOD_ALT, // Alt + F6 + 0}, + {55, + "Mask menu", + "Opens a the menu for Mask settings.", + "", + "", + true, + SDLK_F6|MOD_SHIFT|MOD_ALT, // Shift + Alt + F6 + 0}, + {56, + "Grid mode", + "Enables or disables the Grid mode.", + "", + "", + true, + SDLK_g, // G + 0}, + {57, + "Grid menu", + "Open a menu where you can configure", + "the grid used by Grid mode.", + "", + true, + SDLK_g|MOD_SHIFT, // Shift + G + 0}, + {58, + "Sieve mode", + "Enables or disables the Sieve mode.", + "", + "", + true, + SDLK_g|MOD_CTRL, // Ctrl + G + 0}, + {59, + "Sieve menu", + "Opens a menu where you can configure", + "the sieve.", + "", + true, + SDLK_g|MOD_SHIFT|MOD_CTRL, // Shift + Ctrl + G + 0}, + {60, + "Invert sieve", + "Inverts the pattern defined in the", + "Sieve menu.", + "", + true, + SDLK_g|MOD_CTRL|MOD_ALT, // Ctrl + Alt + G + 0}, + {61, + "Colorize mode", + "Enables or disables the Colorize", + "mode.", + "", + true, + SDLK_F7, // F7 + 0}, + {62, + "Colorize menu", + "Opens a menu where you can give the", + "opacity percentage for Colorize", + "mode.", + true, + SDLK_F7|MOD_SHIFT, // Shift + F7 + 0}, + {63, + "Smooth mode", + "Enables or disables the Smooth", + "mode.", + "", + true, + SDLK_F8, // F8 + 0}, + {123, + "Smooth menu", + "Opens a menu where you can define", + "the Smooth matrix.", + "", + true, + SDLK_F8|MOD_SHIFT, // Shift + F8 + 0}, + {64, + "Smear mode", + "Enables or disables the Smear mode.", + "", + "", + true, + SDLK_F8|MOD_ALT, // Alt + F8 + 0}, + {65, + "Tiling mode", + "Enables or disables the Tiling", + "mode.", + "", + true, + SDLK_b|MOD_ALT, // Alt + B + 0}, + {66, + "Tiling menu", + "Opens a menu where you can configure", + "the origin of the tiling.", + "", + true, + SDLK_b|MOD_SHIFT|MOD_ALT, // Shift + Alt + B + 0}, + {67, + "Classical brush grabbing", + "Allows you to pick a brush defined", + "within a rectangle.", + "", + true, + SDLK_b, // B + 0}, + {68, + "\"Lasso\" brush grabbing", + "Allows you to pick a brush defined", + "within a freehand polygon.", + "", + true, + SDLK_b|MOD_CTRL, // Ctrl + B + 0}, + {69, + "Get previous brush back", + "Restore the last user-defined brush.", + "", + "", + true, + SDLK_b|MOD_SHIFT, // Shift + B + 0}, + {70, + "Horizontal brush flipping", + "Reverse brush horizontally.", + "", + "", + true, + SDLK_x, // X + 0}, + {71, + "Vertical brush flipping", + "Reverse brush vertically.", + "", + "", + true, + SDLK_y, // Y + 0}, + {72, + "90° brush rotation", + "Rotate the user-defined brush by 90°", + "(counter-clockwise).", + "", + true, + SDLK_z, // Z (W en AZERTY) + 0}, + {73, + "180° brush rotation", + "Rotate the user-defined brush by", + "180°.", + "", + true, + SDLK_z|MOD_SHIFT, // Shift + Z + 0}, + {74, + "Strech brush", + "Allows you to resize the", + "user-defined brush.", + "", + true, + SDLK_s, // S + 0}, + {75, + "Distort brush", + "Allows you to distort the", + "user-defined brush.", + "", + true, + SDLK_s|MOD_SHIFT, // Shift + S + 0}, + {76, + "Outline brush", + "Outlines the user-defined brush", + "with the fore color.", + "", + true, + SDLK_o, // O + 0}, + {77, + "Nibble brush", + "Deletes the borders of the", + "user-defined brush.This does the", + "opposite of the Outline option.", + true, + SDLK_o|MOD_SHIFT, // Shift + O + 0}, + {78, + "Get colors from brush", + "Copy colors of the spare page that", + "are used in the brush.", + "", + true, + SDLK_F11, // F11 + 0}, + {79, + "Recolorize brush", + "Recolorize the user-defined brush in", + "order to get a brush which looks as", + "if it was grabbed in the spare page.", + true, + SDLK_F12, // F12 + 0}, + {80, + "Rotate by any angle", + "Rotate the brush by an angle that", + "you can define.", + "", + true, + SDLK_w, // W (Z en AZERTY) + 0}, + {81, + "Pipette", + "Allows you to copy the color of a", + "pixel in the picture into the", + "foreground or background color.", + true, + SDLK_BACKQUOTE, // `~ (Key sous le Esc - ² en AZERTY) + 0}, + {82, + "Swap foreground/background colors", + "Invert foreground and background", + "colors.", + "", + true, + SDLK_BACKQUOTE|MOD_SHIFT, // Shift + `~ + 0}, + {83, + "Magnifier mode", + "Allows you to zoom into the picture.", + "", + "", + true, + SDLK_m, // M (, ? sur AZERTY) + KEY_MOUSEMIDDLE}, + {84, + "Zoom factor menu", + "Opens a menu where you can choose a", + "magnifying factor.", + "", + true, + SDLK_m|MOD_SHIFT, // Shift + M + 0}, + {85, + "Zoom in", + "Increase magnifying factor.", + "", + "", + true, + SDLK_KP_PLUS, // Grey + + KEY_MOUSEWHEELUP}, + {86, + "Zoom out", + "Decrease magnifying factor.", + "", + "", + true, + SDLK_KP_MINUS, // Grey - + KEY_MOUSEWHEELDOWN}, + {87, + "Brush effects menu", + "Opens a menu which proposes", + "different effects on the", + "user-defined brush.", + true, + SDLK_b|MOD_CTRL|MOD_ALT, // Ctrl + Alt + B + 0}, + {88, + "Text", + "Opens a menu which permits you to", + "type in a character string and", + "render it as a brush.", + true, + SDLK_t, // T + 0}, + {89, + "Screen resolution menu", + "Opens a menu where you can choose", + "the screen resolution and image", + "dimensions.", + true, + SDLK_RETURN, // Enter + 0}, + {90, + "\"Safety\" resolution", + "Resets the resolution to a 'safe'", + "mode that should work everywhere:", + "usually a 640x400 window.", + false, + SDLK_RETURN|MOD_SHIFT, // Shift + Enter + 0}, + {91, + "Help and credits", + "Opens a window where you can get", + "information about the program,", + "or contextual help.", + true, + SDLK_F1, // F1 + 0}, + {92, + "Statistics", + "Displays miscellaneous more or less", + "useful information.", + "", + true, + SDLK_F1|MOD_SHIFT, // Shift + F1 + 0}, + {93, + "Jump to spare page", + "Swap current page and spare page.", + "", + "", + true, + SDLK_TAB, // Tab + 0}, + {94, + "Copy current page to spare page", + "Copy current page to spare page.", + "", + "", + true, + SDLK_TAB|MOD_SHIFT, // Shift + Tab + 0}, + {95, + "Save picture as...", + "Opens a file-selector that allows", + "you to save your picture with a new", + "path-name.", + true, + SDLK_F2, // F2 + 0}, + {96, + "Save picture", + "Saves your picture with the last", + "name you gave it.", + "", + true, + SDLK_F2|MOD_SHIFT, // Shift + F2 + 0}, + {97, + "Load picture", + "Opens a file-selector that allows", + "you to load a new picture.", + "", + true, + SDLK_F3, // F3 + 0}, + {98, + "Re-load picture", + "Re-load the current picture. This", + "allows you to cancel modifications", + "made since last saving.", + true, + SDLK_F3|MOD_SHIFT, // Shift + F3 + 0}, + {99, + "Save brush", + "Opens a file-selector that allows", + "you to save your current", + "user-defined brush.", + true, + SDLK_F2|MOD_CTRL, // Ctrl + F2 + 0}, + {100, + "Load brush", + "Opens a file-selector that allows", + "you to load a brush.", + "", + true, + SDLK_F3|MOD_CTRL, // Ctrl + F3 + 0}, + {101, + "Settings", + "Opens a menu which permits you to", + "modify some parameters of the", + "program.", + true, + SDLK_F10|MOD_SHIFT, // Shift + F10 + 0}, + {102, + "Undo (Oops!)", + "Cancel the last action which", + "modified the picture.", + "", + true, + SDLK_u, // U + 0}, + {103, + "Redo", + "Redo the last undone action.", + "", + "", + true, + SDLK_u|MOD_SHIFT, // Shift + U + 0}, + {133, + "Kill", + "Kills the current page. It actually", + "removes the current page from the", + "list of \"Undo\" pages.", + true, + SDLK_DELETE|MOD_SHIFT, // Shift + Suppr + 0}, + {104, + "Clear page", + "Clears the picture with the first", + "color of the palette (usually black)", + "", + true, + SDLK_BACKSPACE, // BackSpace + 0}, + {105, + "Clear page with backcolor", + "Clears the picture with the", + "current backcolor.", + "", + true, + SDLK_BACKSPACE|MOD_SHIFT, // Shift + BackSpace + 0}, + {106, + "Quit program", + "Allows you to leave the program.", + "If modifications were not saved,", + "confirmation is asked.", + false, + SDLK_q, // Q (A en AZERTY) + 0}, + {107, + "Palette menu", + "Opens a menu which allows you to", + "modify the current palette.", + "", + true, + SDLK_p, // P + 0}, + {125, + "Secondary palette menu", + "Opens a menu which allows you to", + "define color series and some tagged", + "colors.", + true, + SDLK_p|MOD_SHIFT, // Shift + P + 0}, + {130, + "Exclude colors menu", + "Opens a menu which allows you to", + "define the colors you don""t want to", + "use in Smooth and Transparency", + true, + SDLK_p|MOD_CTRL, // Ctrl + P + 0}, + {108, + "Scroll palette to the left", + "Scroll palette in the tool bar to", + "the left, column by column.", + "", + true, + SDLK_PAGEUP, // PgUp + 0}, + {109, + "Scroll palette to the right", + "Scroll palette in the tool bar to", + "the right, column by column.", + "", + true, + SDLK_PAGEDOWN, // PgDn + 0}, + {110, + "Scroll palette to the left faster", + "Scroll palette in the tool bar to", + "the left, 8 columns by 8 columns.", + "", + true, + SDLK_PAGEUP|MOD_SHIFT, // Shift + PgUp + 0}, + {111, + "Scroll palette to the right faster", + "Scroll palette in the tool bar to", + "the right, 8 columns by 8 columns.", + "", + true, + SDLK_PAGEDOWN|MOD_SHIFT, // Shift + PgDn + 0}, + {112, + "Center brush attachment point", + "Set the attachement of the", + "user-defined brush to its center.", + "", + true, + SDLK_KP5|MOD_CTRL, // Ctrl + 5 (pavé numérique) + 0}, + {113, + "Top-left brush attachment point", + "Set the attachement of the", + "user-defined brush to its top-left", + "corner.", + true, + SDLK_HOME|MOD_CTRL, // Ctrl + 7 + 0}, + {114, + "Top-right brush attachment point", + "Set the attachement of the", + "user-defined brush to its top-right", + "corner.", + true, + SDLK_PAGEUP|MOD_CTRL, // Ctrl + 9 + 0}, + {115, + "Bottom-left brush attachment point", + "Set the attachement of the", + "user-defined brush to its", + "bottom-left corner.", + true, + SDLK_END|MOD_CTRL, // Ctrl + 1 + 0}, + {116, + "Bottom-right brush attachment point", + "Set the attachement of the", + "user-defined brush to its", + "bottom-right corner.", + true, + SDLK_PAGEDOWN|MOD_CTRL, // Ctrl + 3 + 0}, + {117, + "Next foreground color", + "Set the foreground color to the next", + "in the palette.", + "", + true, + SDLK_RIGHTBRACKET, // ] (0x en AZERTY) + 0}, + {118, + "Previous foreground color", + "Set the foreground color to the", + "previous in the palette.", + "", + true, + SDLK_LEFTBRACKET, // [ (^ en AZERTY) + 0}, + {119, + "Next background color", + "Set the background color to the next", + "in the palette.", + "", + true, + SDLK_RIGHTBRACKET|MOD_SHIFT, // Shift + ] + 0}, + {120, + "Previous background color", + "Set the background color to the", + "previous in the palette.", + "", + true, + SDLK_LEFTBRACKET|MOD_SHIFT, // Shift + [ + 0}, + {126, + "Next user-defined forecolor", + "Set the foreground color to the next", + "in the user-defined color series.", + "", + true, + SDLK_EQUALS, // "=+" + 0}, + {127, + "Previous user-defined forecolor", + "Set the foreground color to the", + "previous in the user-defined color", + "series.", + true, + SDLK_MINUS, // "-_" (")°" en AZERTY + 0}, + {128, + "Next user-defined backcolor", + "Set the background color to the next", + "in the user-defined color series.", + "", + true, + SDLK_EQUALS|MOD_SHIFT, // Shift + "=+" + 0}, + {129, + "Previous user-defined backcolor", + "Set the background color to the", + "previous in the user-defined color", + "series.", + true, + SDLK_MINUS|MOD_SHIFT, // Shift + "-_" (")°" en AZERTY + 0}, + {121, + "Shrink paintbrush", + "Decrease the width of the paintbrush", + "if it is special circle or square.", + "", + true, + SDLK_COMMA, // , < (;. en AZERTY) + 0}, + {122, + "Enlarge paintbrush", + "Increase the width of the paintbrush", + "if it is special circle or square.", + "", + true, + SDLK_PERIOD, // .> (:/ en AZERTY) + 0}, + {134, + "Effects off", + "Turns off all drawing effects. This", + "is the same as the 'All off' button", + "in the Effects screen", + true, + SDLK_e|MOD_SHIFT, // Shift-E + 0}, + {135, + "Transparency 10%", + "Turns transparency on and sets its", + "opacity at 10%.", + "", + true, + SDLK_1, // 1 + 0}, + {136, + "Transparency 20%", + "Turns transparency on and sets its", + "opacity at 20%.", + "", + true, + SDLK_2, // 2 + 0}, + {137, + "Transparency 30%", + "Turns transparency on and sets its", + "opacity at 30%.", + "", + true, + SDLK_3, // 3 + 0}, + {138, + "Transparency 40%", + "Turns transparency on and sets its", + "opacity at 40%.", + "", + true, + SDLK_4, // 4 + 0}, + {139, + "Transparency 50%", + "Turns transparency on and sets its", + "opacity at 50%.", + "", + true, + SDLK_5, // 5 + 0}, + {140, + "Transparency 60%", + "Turns transparency on and sets its", + "opacity at 60%.", + "", + true, + SDLK_6, // 6 + 0}, + {141, + "Transparency 70%", + "Turns transparency on and sets its", + "opacity at 70%.", + "", + true, + SDLK_7, // 7 + 0}, + {142, + "Transparency 80%", + "Turns transparency on and sets its", + "opacity at 80%.", + "", + true, + SDLK_8, // 8 + 0}, + {143, + "Transparency 90%", + "Turns transparency on and sets its", + "opacity at 90%.", + "", + true, + SDLK_9, // 9 + 0}, + {144, + "Transparency 0%", + "Turns transparency on and sets its", + "opacity at 0%.", + "", + true, + SDLK_0, // 0 + 0}, + {145, + "Zoom 1:1", + "Turns magnifier mode off.", + "", + "", + true, + SDLK_1|MOD_CTRL, /* Ctrl + 1 */ + 0}, + {146, + "Zoom 2:1", + "Turns magnifier mode on and set its", + "factor to 2:1", + "", + true, + SDLK_2|MOD_CTRL, /* Ctrl + 2 */ + 0}, + {147, + "Zoom 3:1", + "Turns magnifier mode on and set its", + "factor to 3:1", + "", + true, + SDLK_3|MOD_CTRL, /* Ctrl + 3 */ + 0}, + {148, + "Zoom 4:1", + "Turns magnifier mode on and set its", + "factor to 4:1", + "", + true, + SDLK_4|MOD_CTRL, /* Ctrl + 4 */ + 0}, + {149, + "Zoom 5:1", + "Turns magnifier mode on and set its", + "factor to 5:1", + "", + true, + SDLK_5|MOD_CTRL, /* Ctrl + 5 */ + 0}, + {150, + "Zoom 6:1", + "Turns magnifier mode on and set its", + "factor to 6:1", + "", + true, + SDLK_6|MOD_CTRL, /* Ctrl + 6 */ + 0}, + {151, + "Zoom 8:1", + "Turns magnifier mode on and set its", + "factor to 8:1", + "", + true, + SDLK_7|MOD_CTRL, /* Ctrl + 7 */ + 0}, + {152, + "Zoom 10:1", + "Turns magnifier mode on and set its", + "factor to 10:1", + "", + true, + SDLK_8|MOD_CTRL, /* Ctrl + 8 */ + 0}, + {153, + "Zoom 12:1", + "Turns magnifier mode on and set its", + "factor to 12:1", + "", + true, + 0, + 0}, + {154, + "Zoom 14:1", + "Turns magnifier mode on and set its", + "factor to 14:1", + "", + true, + 0, + 0}, + {155, + "Zoom 16:1", + "Turns magnifier mode on and set its", + "factor to 16:1", + "", + true, + 0, + 0}, + {156, + "Zoom 18:1", + "Turns magnifier mode on and set its", + "factor to 18:1", + "", + true, + 0, + 0}, + {157, + "Zoom 20:1", + "Turns magnifier mode on and set its", + "factor to 20:1", + "", + true, + 0, + 0}, + {158, + "Show/Hide Grid", + "Turns on or off the visible grid in ", + "the magnified view. Grid cells match", + "the size ", + true, + SDLK_g|MOD_SHIFT|MOD_ALT, // Shift + Alt + G, + 0}, +}; + +word Ordering[NB_SHORTCUTS]= +{ + SPECIAL_SCROLL_UP, // Scroll up + SPECIAL_SCROLL_DOWN, // Scroll down + SPECIAL_SCROLL_LEFT, // Scroll left + SPECIAL_SCROLL_RIGHT, // Scroll right + SPECIAL_SCROLL_UP_FAST, // Scroll up faster + SPECIAL_SCROLL_DOWN_FAST, // Scroll down faster + SPECIAL_SCROLL_LEFT_FAST, // Scroll left faster + SPECIAL_SCROLL_RIGHT_FAST, // Scroll right faster + SPECIAL_SCROLL_UP_SLOW, // Scroll up slower + SPECIAL_SCROLL_DOWN_SLOW, // Scroll down slower + SPECIAL_SCROLL_LEFT_SLOW, // Scroll left slower + SPECIAL_SCROLL_RIGHT_SLOW, // Scroll right slower + SPECIAL_MOUSE_UP, // Emulate mouse up + SPECIAL_MOUSE_DOWN, // Emulate mouse down + SPECIAL_MOUSE_LEFT, // Emulate mouse left + SPECIAL_MOUSE_RIGHT, // Emulate mouse right + SPECIAL_CLICK_LEFT, // Emulate mouse click left + SPECIAL_CLICK_RIGHT, // Emulate mouse click right + 0x100+BUTTON_HIDE, // Show / Hide menu + SPECIAL_SHOW_HIDE_CURSOR, // Show / Hide cursor + SPECIAL_DOT_PAINTBRUSH, // Paintbrush = "." + 0x100+BUTTON_PAINTBRUSHES, // Paintbrush choice + 0x200+BUTTON_PAINTBRUSHES, // Monochrome brush + 0x100+BUTTON_DRAW, // Freehand drawing + 0x200+BUTTON_DRAW, // Switch freehand drawing mode + SPECIAL_CONTINUOUS_DRAW, // Continuous freehand drawing + 0x100+BUTTON_LINES, // Line + 0x200+BUTTON_LINES, // Knotted lines + 0x100+BUTTON_AIRBRUSH, // Spray + 0x200+BUTTON_AIRBRUSH, // Spray menu + 0x100+BUTTON_FLOODFILL, // Floodfill + 0x200+BUTTON_FLOODFILL, // Replace color + 0x100+BUTTON_CURVES, // Bézier's curves + 0x200+BUTTON_CURVES, // Bézier's curve with 3 or 4 points + 0x100+BUTTON_RECTANGLES, // Empty rectangle + 0x100+BUTTON_FILLRECT, // Filled rectangle + 0x100+BUTTON_CIRCLES, // Empty circle + 0x200+BUTTON_CIRCLES, // Empty ellipse + 0x100+BUTTON_FILLCIRC, // Filled circle + 0x200+BUTTON_FILLCIRC, // Filled ellipse + 0x100+BUTTON_POLYGONS, // Empty polygon + 0x200+BUTTON_POLYGONS, // Empty polyform + 0x100+BUTTON_POLYFILL, // Polyfill + 0x200+BUTTON_POLYFILL, // Filled polyform + 0x100+BUTTON_GRADRECT, // Gradient rectangle + 0x200+BUTTON_GRADRECT, // Gradation menu + 0x100+BUTTON_SPHERES, // Spheres + 0x200+BUTTON_SPHERES, // Gradient ellipses + 0x100+BUTTON_ADJUST, // Adjust picture + 0x200+BUTTON_ADJUST, // Flip picture menu + 0x100+BUTTON_EFFECTS, // Menu des effets + SPECIAL_SHADE_MODE, // Shade mode + SPECIAL_SHADE_MENU, // Shade menu + SPECIAL_QUICK_SHADE_MODE, // Quick-shade mode + SPECIAL_QUICK_SHADE_MENU, // Quick-shade menu + SPECIAL_STENCIL_MODE, // Stencil mode + SPECIAL_STENCIL_MENU, // Stencil menu + SPECIAL_MASK_MODE, // Mask mode + SPECIAL_MASK_MENU, // Mask menu + SPECIAL_GRID_MODE, // Grid mode + SPECIAL_GRID_MENU, // Grid menu + SPECIAL_SIEVE_MODE, // Sieve mode + SPECIAL_SIEVE_MENU, // Sieve menu + SPECIAL_INVERT_SIEVE, // Inverser la trame du mode Sieve + SPECIAL_COLORIZE_MODE, // Colorize mode + SPECIAL_COLORIZE_MENU, // Colorize menu + SPECIAL_SMOOTH_MODE, // Smooth mode + SPECIAL_SMOOTH_MENU, // Smooth menu + SPECIAL_SMEAR_MODE, // Smear mode + SPECIAL_TILING_MODE, // Tiling mode + SPECIAL_TILING_MENU, // Tiling menu + 0x100+BUTTON_BRUSH, // Pick brush + 0x100+BUTTON_POLYBRUSH, // Pick polyform brush + 0x200+BUTTON_BRUSH, // Restore brush + SPECIAL_FLIP_X, // Flip X + SPECIAL_FLIP_Y, // Flip Y + SPECIAL_ROTATE_90, // 90° brush rotation + SPECIAL_ROTATE_180, // 180° brush rotation + SPECIAL_STRETCH, // Stretch brush + SPECIAL_DISTORT, // Distort brush + SPECIAL_OUTLINE, // Outline brush + SPECIAL_NIBBLE, // Nibble brush + SPECIAL_GET_BRUSH_COLORS, // Get colors from brush + SPECIAL_RECOLORIZE_BRUSH, // Recolorize brush + SPECIAL_ROTATE_ANY_ANGLE, // Rotate brush by any angle + 0x100+BUTTON_COLORPICKER, // Pipette + 0x200+BUTTON_COLORPICKER, // Swap fore/back color + 0x100+BUTTON_MAGNIFIER, // Magnifier mode + 0x200+BUTTON_MAGNIFIER, // Zoom factor menu + SPECIAL_ZOOM_IN, // Zoom in + SPECIAL_ZOOM_OUT, // Zoom out + 0x100+BUTTON_BRUSH_EFFECTS, // Brush effects menu + 0x100+BUTTON_TEXT, // Text + 0x100+BUTTON_RESOL, // Resolution menu + 0x200+BUTTON_RESOL, // Safety resolution + 0x100+BUTTON_HELP, // Help & credits + 0x200+BUTTON_HELP, // Statistics + 0x100+BUTTON_PAGE, // Go to spare page + 0x200+BUTTON_PAGE, // Copy to spare page + 0x100+BUTTON_SAVE, // Save as + 0x200+BUTTON_SAVE, // Save + 0x100+BUTTON_LOAD, // Load + 0x200+BUTTON_LOAD, // Re-load + SPECIAL_SAVE_BRUSH, // Save brush + SPECIAL_LOAD_BRUSH, // Load brush + 0x100+BUTTON_SETTINGS, // Settings + 0x100+BUTTON_UNDO, // Undo + 0x200+BUTTON_UNDO, // Redo + 0x100+BUTTON_KILL, // Kill + 0x100+BUTTON_CLEAR, // Clear + 0x200+BUTTON_CLEAR, // Clear with backcolor + 0x100+BUTTON_QUIT, // Quit + 0x100+BUTTON_PALETTE, // Palette menu + 0x200+BUTTON_PALETTE, // Palette menu secondaire + SPECIAL_EXCLUDE_COLORS_MENU, // Exclude colors menu + 0x100+BUTTON_PAL_LEFT, // Scroll palette left + 0x100+BUTTON_PAL_RIGHT, // Scroll palette right + 0x200+BUTTON_PAL_LEFT, // Scroll palette left faster + 0x200+BUTTON_PAL_RIGHT, // Scroll palette right faster + SPECIAL_CENTER_ATTACHMENT, // Center brush attachement + SPECIAL_TOP_LEFT_ATTACHMENT, // Top-left brush attachement + SPECIAL_TOP_RIGHT_ATTACHMENT, // Top-right brush attachement + SPECIAL_BOTTOM_LEFT_ATTACHMENT, // Bottom-left brush attachement + SPECIAL_BOTTOM_RIGHT_ATTACHMENT, // Bottom right brush attachement + SPECIAL_NEXT_FORECOLOR, // Next foreground color + SPECIAL_PREVIOUS_FORECOLOR, // Previous foreground color + SPECIAL_NEXT_BACKCOLOR, // Next background color + SPECIAL_PREVIOUS_BACKCOLOR, // Previous background color + SPECIAL_NEXT_USER_FORECOLOR, // Next user-defined foreground color + SPECIAL_PREVIOUS_USER_FORECOLOR, // Previous user-defined foreground color + SPECIAL_NEXT_USER_BACKCOLOR, // Next user-defined background color + SPECIAL_PREVIOUS_USER_BACKCOLOR, // Previous user-defined background color + SPECIAL_SMALLER_PAINTBRUSH, // Sets paintbrush size: smaller + SPECIAL_BIGGER_PAINTBRUSH, // Sets paintbrush size: bigger + SPECIAL_EFFECTS_OFF, // Turns off all effects + SPECIAL_TRANSPARENCY_1, // Sets transparency level 10% + SPECIAL_TRANSPARENCY_2, // Sets transparency level 20% + SPECIAL_TRANSPARENCY_3, // Sets transparency level 30% + SPECIAL_TRANSPARENCY_4, // Sets transparency level 40% + SPECIAL_TRANSPARENCY_5, // Sets transparency level 50% + SPECIAL_TRANSPARENCY_6, // Sets transparency level 60% + SPECIAL_TRANSPARENCY_7, // Sets transparency level 70% + SPECIAL_TRANSPARENCY_8, // Sets transparency level 80% + SPECIAL_TRANSPARENCY_9, // Sets transparency level 90% + SPECIAL_TRANSPARENCY_0, // Sets transparency level 00% + SPECIAL_ZOOM_1, /**< Sets zoom factor to 1:1 (no magnification) */ + SPECIAL_ZOOM_2, /**< Sets zoom factor to 2:1 */ + SPECIAL_ZOOM_3, /**< Sets zoom factor to 3:1 */ + SPECIAL_ZOOM_4, /**< Sets zoom factor to 4:1 */ + SPECIAL_ZOOM_5, /**< Sets zoom factor to 5:1 */ + SPECIAL_ZOOM_6, /**< Sets zoom factor to 6:1 */ + SPECIAL_ZOOM_8, /**< Sets zoom factor to 8:1 */ + SPECIAL_ZOOM_10, /**< Sets zoom factor to 10:1 */ + SPECIAL_ZOOM_12, /**< Sets zoom factor to 12:1 */ + SPECIAL_ZOOM_14, /**< Sets zoom factor to 14:1 */ + SPECIAL_ZOOM_16, /**< Sets zoom factor to 16:1 */ + SPECIAL_ZOOM_18, /**< Sets zoom factor to 18:1 */ + SPECIAL_ZOOM_20, /**< Sets zoom factor to 20:1 */ + SPECIAL_SHOW_GRID, +}; diff --git a/init.c b/init.c index 82da41c7..2cc6761a 100644 --- a/init.c +++ b/init.c @@ -66,6 +66,7 @@ #include "init.h" #include "transform.h" +char Gui_loading_error_message[512]; // Rechercher la liste et le type des lecteurs de la machine @@ -74,7 +75,7 @@ void bstrtostr( BSTR in, STRPTR out, TEXT max ); #endif // Fonctions de lecture dans la skin de l'interface graphique -void GUI_seek_down(SDL_Surface *gui, int *start_x, int *start_y, byte neutral_color,char * section) +byte GUI_seek_down(SDL_Surface *gui, int *start_x, int *start_y, byte neutral_color,char * section) { byte color; int y; @@ -86,17 +87,17 @@ void GUI_seek_down(SDL_Surface *gui, int *start_x, int *start_y, byte neutral_co if (color!=neutral_color) { *start_y=y; - return; + return 0; } y++; } while (yh); - printf("Error in skin file: Was looking down from %d,%d for a '%s', and reached the end of the image\n", + sprintf(Gui_loading_error_message, "Error in skin file: Was looking down from %d,%d for a '%s', and reached the end of the image\n", *start_x, *start_y, section); - Error(ERROR_GUI_CORRUPTED); + return 1; } -void GUI_seek_right(SDL_Surface *gui, int *start_x, int start_y, byte neutral_color, char * section) +byte GUI_seek_right(SDL_Surface *gui, int *start_x, int start_y, byte neutral_color, char * section) { byte color; int x; @@ -108,17 +109,17 @@ void GUI_seek_right(SDL_Surface *gui, int *start_x, int start_y, byte neutral_co if (color!=neutral_color) { *start_x=x; - return; + return 0; } x++; } while (xw); - printf("Error in skin file: Was looking right from %d,%d for a '%s', and reached the edege of the image\n", + sprintf(Gui_loading_error_message, "Error in skin file: Was looking right from %d,%d for a '%s', and reached the edege of the image\n", *start_x, start_y, section); - Error(ERROR_GUI_CORRUPTED); + return 1; } -void Read_GUI_block(SDL_Surface *gui, int start_x, int start_y, void *dest, int width, int height, char * section, int type) +byte Read_GUI_block(SDL_Surface *gui, int start_x, int start_y, void *dest, int width, int height, char * section, int type) { // type: 0 = normal GUI element, only 4 colors allowed // type: 1 = mouse cursor, 4 colors allowed + transparent @@ -132,9 +133,9 @@ void Read_GUI_block(SDL_Surface *gui, int start_x, int start_y, void *dest, int // Verification taille if (start_y+height>=gui->h || start_x+width>=gui->w) { - printf("Error in skin file: Was looking at %d,%d for a %d*%d object (%s) but it doesn't fit the image.\n", + sprintf(Gui_loading_error_message, "Error in skin file: Was looking at %d,%d for a %d*%d object (%s) but it doesn't fit the image.\n", start_x, start_y, height, width, section); - Error(ERROR_GUI_CORRUPTED); + return 1; } for (y=start_y; yCursor_offset_X[cursor_number]=14-start_x; + gfx->Cursor_offset_Y[cursor_number]=14-start_y; for (y=0;yCursor_sprite[cursor_number][y][x]=cursor_buffer[(start_y+y)*29+start_x+x]; } -void Load_graphics(const char * skin_file) +byte Parse_skin(SDL_Surface * gui, T_Gui_skin *gfx) { int index; - char filename[MAX_PATH_CHARACTERS]; - SDL_Surface * gui; - SDL_Palette * SDLPal; int i; int cursor_x=0,cursor_y=0; byte color; @@ -251,43 +249,36 @@ void Load_graphics(const char * skin_file) int char_3=0; // l'une des fontes dans l'ordre : 1 2 int char_4=0; // 3 4 byte mouse_cursor_area[29][29]; + SDL_Palette * SDLPal; - // Lecture du fichier "skin" - strcpy(filename,Data_directory); - strcat(filename,skin_file); - - gui=IMG_Load(filename); - if (!gui) - { - Error(ERROR_GUI_MISSING); - } + // Default palette if (!gui->format || gui->format->BitsPerPixel != 8) { - printf("Not a 8-bit image"); - Error(ERROR_GUI_CORRUPTED); + sprintf(Gui_loading_error_message, "Not a 8-bit image"); + return 1; } SDLPal=gui->format->palette; if (!SDLPal || SDLPal->ncolors!=256) { - printf("Not a 256-color palette"); - Error(ERROR_GUI_CORRUPTED); + sprintf(Gui_loading_error_message, "Not a 256-color palette"); + return 1; } - // Lecture de la palette par défaut + // Read the default palette for (i=0; i<256; i++) { - Default_palette[i].R=SDLPal->colors[i].r; - Default_palette[i].G=SDLPal->colors[i].g; - Default_palette[i].B=SDLPal->colors[i].b; + gfx->Default_palette[i].R=SDLPal->colors[i].r; + gfx->Default_palette[i].G=SDLPal->colors[i].g; + gfx->Default_palette[i].B=SDLPal->colors[i].b; } - + // Carré "noir" MC_Black = Get_SDL_pixel_8(gui,cursor_x,cursor_y); do { if (++cursor_x>=gui->w) { - printf("Error in GUI skin file: should start with 5 consecutive squares for black, dark, light, white, transparent, then a neutral color\n"); - Error(ERROR_GUI_CORRUPTED); + sprintf(Gui_loading_error_message, "Error in GUI skin file: should start with 5 consecutive squares for black, dark, light, white, transparent, then a neutral color\n"); + return 1; } color=Get_SDL_pixel_8(gui,cursor_x,cursor_y); } while(color==MC_Black); @@ -297,8 +288,8 @@ void Load_graphics(const char * skin_file) { if (++cursor_x>=gui->w) { - printf("Error in GUI skin file: should start with 5 consecutive squares for black, dark, light, white, transparent, then a neutral color\n"); - Error(ERROR_GUI_CORRUPTED); + sprintf(Gui_loading_error_message, "Error in GUI skin file: should start with 5 consecutive squares for black, dark, light, white, transparent, then a neutral color\n"); + return 1; } color=Get_SDL_pixel_8(gui,cursor_x,cursor_y); } while(color==MC_Dark); @@ -308,8 +299,8 @@ void Load_graphics(const char * skin_file) { if (++cursor_x>gui->w) { - printf("Error in GUI skin file: should start with 5 consecutive squares for black, dark, light, white, transparent, then a neutral color\n"); - Error(ERROR_GUI_CORRUPTED); + sprintf(Gui_loading_error_message, "Error in GUI skin file: should start with 5 consecutive squares for black, dark, light, white, transparent, then a neutral color\n"); + return 1; } color=Get_SDL_pixel_8(gui,cursor_x,cursor_y); } while(color==MC_Light); @@ -319,8 +310,8 @@ void Load_graphics(const char * skin_file) { if (++cursor_x>=gui->w) { - printf("Error in GUI skin file: should start with 5 consecutive squares for black, dark, light, white, transparent, then a neutral color\n"); - Error(ERROR_GUI_CORRUPTED); + sprintf(Gui_loading_error_message, "Error in GUI skin file: should start with 5 consecutive squares for black, dark, light, white, transparent, then a neutral color\n"); + return 1; } color=Get_SDL_pixel_8(gui,cursor_x,cursor_y); } while(color==MC_White); @@ -330,8 +321,8 @@ void Load_graphics(const char * skin_file) { if (++cursor_x>=gui->w) { - printf("Error in GUI skin file: should start with 5 consecutive squares for black, dark, light, white, transparent, then a neutral color\n"); - Error(ERROR_GUI_CORRUPTED); + sprintf(Gui_loading_error_message, "Error in GUI skin file: should start with 5 consecutive squares for black, dark, light, white, transparent, then a neutral color\n"); + return 1; } color=Get_SDL_pixel_8(gui,cursor_x,cursor_y); } while(color==MC_Trans); @@ -346,24 +337,33 @@ void Load_graphics(const char * skin_file) cursor_y++; if (cursor_y>=gui->h) { - printf("Error in GUI skin file: should start with 5 consecutive squares for black, dark, light, white, transparent, then a neutral color\n"); - Error(ERROR_GUI_CORRUPTED); + sprintf(Gui_loading_error_message, "Error in GUI skin file: should start with 5 consecutive squares for black, dark, light, white, transparent, then a neutral color\n"); + return 1; } } // Menu - GUI_seek_down(gui, &cursor_x, &cursor_y, neutral_color, "menu"); - Read_GUI_block(gui, cursor_x, cursor_y, GFX_menu_block, MENU_WIDTH, MENU_HEIGHT,"menu",0); + if (GUI_seek_down(gui, &cursor_x, &cursor_y, neutral_color, "menu")) + return 1; + if (Read_GUI_block(gui, cursor_x, cursor_y, gfx->Menu_block, MENU_WIDTH, MENU_HEIGHT,"menu",0)) + return 1; cursor_y+=MENU_HEIGHT; // Effets for (i=0; iEffect_sprite[i], MENU_SPRITE_WIDTH, MENU_SPRITE_HEIGHT, "effect sprite",0)) + return 1; cursor_x+=MENU_SPRITE_WIDTH; } cursor_y+=MENU_SPRITE_HEIGHT; @@ -372,11 +372,18 @@ void Load_graphics(const char * skin_file) for (i=0; iMenu_sprite[i], MENU_SPRITE_WIDTH, MENU_SPRITE_HEIGHT, "menu sprite",1)) + return 1; cursor_x+=MENU_SPRITE_WIDTH; } cursor_y+=MENU_SPRITE_HEIGHT; @@ -401,13 +415,16 @@ void Load_graphics(const char * skin_file) { if (i!=0) cursor_y+=PAINTBRUSH_HEIGHT; - GUI_seek_down(gui, &cursor_x, &cursor_y, neutral_color, "brush icon"); + if (GUI_seek_down(gui, &cursor_x, &cursor_y, neutral_color, "brush icon")) + return 1; } else { - GUI_seek_right(gui, &cursor_x, cursor_y, neutral_color, "brush icon"); + if (GUI_seek_right(gui, &cursor_x, cursor_y, neutral_color, "brush icon")) + return 1; } - Read_GUI_block(gui, cursor_x, cursor_y, GFX_paintbrush_sprite[i], PAINTBRUSH_WIDTH, PAINTBRUSH_HEIGHT, "brush icon",2); + if (Read_GUI_block(gui, cursor_x, cursor_y, gfx->Paintbrush_sprite[i], PAINTBRUSH_WIDTH, PAINTBRUSH_HEIGHT, "brush icon",2)) + return 1; cursor_x+=PAINTBRUSH_WIDTH; } cursor_y+=PAINTBRUSH_HEIGHT; @@ -416,72 +433,47 @@ void Load_graphics(const char * skin_file) for (i=0; iIcon_sprite[i], ICON_SPRITE_WIDTH, ICON_SPRITE_HEIGHT, "sprite drive",1)) + return 1; cursor_x+=ICON_SPRITE_WIDTH; } cursor_y+=ICON_SPRITE_HEIGHT; // Logo splash screen - if (!(GFX_logo_grafx2=(byte *)malloc(231*56))) - Error(ERROR_MEMORY); - GUI_seek_down(gui, &cursor_x, &cursor_y, neutral_color, "logo menu"); - Read_GUI_block(gui, cursor_x, cursor_y, GFX_logo_grafx2, 231, 56, "logo menu",3); + if (GUI_seek_down(gui, &cursor_x, &cursor_y, neutral_color, "logo menu")) + return 1; + if (Read_GUI_block(gui, cursor_x, cursor_y, gfx->Logo_grafx2, 231, 56, "logo menu",3)) + return 1; cursor_y+=56; // Trames for (i=0; iSieve_pattern[i],"sieve pattern")) + return 1; cursor_x+=16; } cursor_y+=16; - - // Font Système - for (i=0; i<256; i++) - { - // Rangés par ligne de 32 - if ((i%32)==0) - { - if (i!=0) - cursor_y+=8; - GUI_seek_down(gui, &cursor_x, &cursor_y, neutral_color, "system font"); - } - else - { - GUI_seek_right(gui, &cursor_x, cursor_y, neutral_color, "system font"); - } - Read_GUI_block(gui, cursor_x, cursor_y, &GFX_system_font[i*64], 8, 8, "system font",2); - cursor_x+=8; - } - cursor_y+=8; - Menu_font=GFX_system_font; - - // Font Fun - for (i=0; i<256; i++) - { - // Rangés par ligne de 32 - if ((i%32)==0) - { - if (i!=0) - cursor_y+=8; - GUI_seek_down(gui, &cursor_x, &cursor_y, neutral_color, "fun font"); - } - else - { - GUI_seek_right(gui, &cursor_x, cursor_y, neutral_color, "fun font"); - } - Read_GUI_block(gui, cursor_x, cursor_y, &GFX_fun_font[i*64], 8, 8, "fun font",2); - cursor_x+=8; - } - cursor_y+=8; // Font help normale for (i=0; i<256; i++) @@ -491,13 +483,16 @@ void Load_graphics(const char * skin_file) { if (i!=0) cursor_y+=8; - GUI_seek_down(gui, &cursor_x, &cursor_y, neutral_color, "help font (norm)"); + if (GUI_seek_down(gui, &cursor_x, &cursor_y, neutral_color, "help font (norm)")) + return 1; } else { - GUI_seek_right(gui, &cursor_x, cursor_y, neutral_color, "help font (norm)"); + if (GUI_seek_right(gui, &cursor_x, cursor_y, neutral_color, "help font (norm)")) + return 1; } - Read_GUI_block(gui, cursor_x, cursor_y, &(GFX_help_font_norm[i][0][0]), 6, 8, "help font (norm)",0); + if (Read_GUI_block(gui, cursor_x, cursor_y, &(gfx->Help_font_norm[i][0][0]), 6, 8, "help font (norm)",0)) + return 1; cursor_x+=6; } cursor_y+=8; @@ -510,13 +505,16 @@ void Load_graphics(const char * skin_file) { if (i!=0) cursor_y+=8; - GUI_seek_down(gui, &cursor_x, &cursor_y, neutral_color, "help font (bold)"); + if (GUI_seek_down(gui, &cursor_x, &cursor_y, neutral_color, "help font (bold)")) + return 1; } else { - GUI_seek_right(gui, &cursor_x, cursor_y, neutral_color, "help font (bold)"); + if (GUI_seek_right(gui, &cursor_x, cursor_y, neutral_color, "help font (bold)")) + return 1; } - Read_GUI_block(gui, cursor_x, cursor_y, &(GFX_bold_font[i][0][0]), 6, 8, "help font (bold)",0); + if (Read_GUI_block(gui, cursor_x, cursor_y, &(gfx->Bold_font[i][0][0]), 6, 8, "help font (bold)",0)) + return 1; cursor_x+=6; } cursor_y+=8; @@ -530,233 +528,344 @@ void Load_graphics(const char * skin_file) { if (i!=0) cursor_y+=8; - GUI_seek_down(gui, &cursor_x, &cursor_y, neutral_color, "help font (title)"); + if (GUI_seek_down(gui, &cursor_x, &cursor_y, neutral_color, "help font (title)")) + return 1; } else { - GUI_seek_right(gui, &cursor_x, cursor_y, neutral_color, "help font (title)"); + if (GUI_seek_right(gui, &cursor_x, cursor_y, neutral_color, "help font (title)")) + return 1; } if (i&1) if (i&64) - dest=&(GFX_help_font_t4[char_4++][0][0]); + dest=&(gfx->Help_font_t4[char_4++][0][0]); else - dest=&(GFX_help_font_t2[char_2++][0][0]); + dest=&(gfx->Help_font_t2[char_2++][0][0]); else if (i&64) - dest=&(GFX_help_font_t3[char_3++][0][0]); + dest=&(gfx->Help_font_t3[char_3++][0][0]); else - dest=&(GFX_help_font_t1[char_1++][0][0]); + dest=&(gfx->Help_font_t1[char_1++][0][0]); - Read_GUI_block(gui, cursor_x, cursor_y, dest, 6, 8, "help font (title)",0); + if (Read_GUI_block(gui, cursor_x, cursor_y, dest, 6, 8, "help font (title)",0)) + return 1; cursor_x+=6; } cursor_y+=8; - // Terminé: libération de l'image skin - SDL_FreeSurface(gui); - Current_help_section=0; Help_position=0; - Preset_paintbrush_width[ 0]= 1; - Preset_paintbrush_height[ 0]= 1; - Paintbrush_type [ 0]=PAINTBRUSH_SHAPE_SQUARE; + gfx->Preset_paintbrush_width [ 0]= 1; + gfx->Preset_paintbrush_height[ 0]= 1; + gfx->Paintbrush_type [ 0]=PAINTBRUSH_SHAPE_SQUARE; - Preset_paintbrush_width[ 1]= 2; - Preset_paintbrush_height[ 1]= 2; - Paintbrush_type [ 1]=PAINTBRUSH_SHAPE_SQUARE; + gfx->Preset_paintbrush_width [ 1]= 2; + gfx->Preset_paintbrush_height[ 1]= 2; + gfx->Paintbrush_type [ 1]=PAINTBRUSH_SHAPE_SQUARE; - Preset_paintbrush_width[ 2]= 3; - Preset_paintbrush_height[ 2]= 3; - Paintbrush_type [ 2]=PAINTBRUSH_SHAPE_SQUARE; + gfx->Preset_paintbrush_width [ 2]= 3; + gfx->Preset_paintbrush_height[ 2]= 3; + gfx->Paintbrush_type [ 2]=PAINTBRUSH_SHAPE_SQUARE; - Preset_paintbrush_width[ 3]= 4; - Preset_paintbrush_height[ 3]= 4; - Paintbrush_type [ 3]=PAINTBRUSH_SHAPE_SQUARE; + gfx->Preset_paintbrush_width [ 3]= 4; + gfx->Preset_paintbrush_height[ 3]= 4; + gfx->Paintbrush_type [ 3]=PAINTBRUSH_SHAPE_SQUARE; - Preset_paintbrush_width[ 4]= 5; - Preset_paintbrush_height[ 4]= 5; - Paintbrush_type [ 4]=PAINTBRUSH_SHAPE_SQUARE; + gfx->Preset_paintbrush_width [ 4]= 5; + gfx->Preset_paintbrush_height[ 4]= 5; + gfx->Paintbrush_type [ 4]=PAINTBRUSH_SHAPE_SQUARE; - Preset_paintbrush_width[ 5]= 7; - Preset_paintbrush_height[ 5]= 7; - Paintbrush_type [ 5]=PAINTBRUSH_SHAPE_SQUARE; + gfx->Preset_paintbrush_width [ 5]= 7; + gfx->Preset_paintbrush_height[ 5]= 7; + gfx->Paintbrush_type [ 5]=PAINTBRUSH_SHAPE_SQUARE; - Preset_paintbrush_width[ 6]= 8; - Preset_paintbrush_height[ 6]= 8; - Paintbrush_type [ 6]=PAINTBRUSH_SHAPE_SQUARE; + gfx->Preset_paintbrush_width [ 6]= 8; + gfx->Preset_paintbrush_height[ 6]= 8; + gfx->Paintbrush_type [ 6]=PAINTBRUSH_SHAPE_SQUARE; - Preset_paintbrush_width[ 7]=12; - Preset_paintbrush_height[ 7]=12; - Paintbrush_type [ 7]=PAINTBRUSH_SHAPE_SQUARE; + gfx->Preset_paintbrush_width [ 7]=12; + gfx->Preset_paintbrush_height[ 7]=12; + gfx->Paintbrush_type [ 7]=PAINTBRUSH_SHAPE_SQUARE; - Preset_paintbrush_width[ 8]=16; - Preset_paintbrush_height[ 8]=16; - Paintbrush_type [ 8]=PAINTBRUSH_SHAPE_SQUARE; + gfx->Preset_paintbrush_width [ 8]=16; + gfx->Preset_paintbrush_height[ 8]=16; + gfx->Paintbrush_type [ 8]=PAINTBRUSH_SHAPE_SQUARE; - Preset_paintbrush_width[ 9]=16; - Preset_paintbrush_height[ 9]=16; - Paintbrush_type [ 9]=PAINTBRUSH_SHAPE_SIEVE_SQUARE; + gfx->Preset_paintbrush_width [ 9]=16; + gfx->Preset_paintbrush_height[ 9]=16; + gfx->Paintbrush_type [ 9]=PAINTBRUSH_SHAPE_SIEVE_SQUARE; - Preset_paintbrush_width[10]=15; - Preset_paintbrush_height[10]=15; - Paintbrush_type [10]=PAINTBRUSH_SHAPE_DIAMOND; + gfx->Preset_paintbrush_width [10]=15; + gfx->Preset_paintbrush_height[10]=15; + gfx->Paintbrush_type [10]=PAINTBRUSH_SHAPE_DIAMOND; - Preset_paintbrush_width[11]= 5; - Preset_paintbrush_height[11]= 5; - Paintbrush_type [11]=PAINTBRUSH_SHAPE_DIAMOND; + gfx->Preset_paintbrush_width [11]= 5; + gfx->Preset_paintbrush_height[11]= 5; + gfx->Paintbrush_type [11]=PAINTBRUSH_SHAPE_DIAMOND; - Preset_paintbrush_width[12]= 3; - Preset_paintbrush_height[12]= 3; - Paintbrush_type [12]=PAINTBRUSH_SHAPE_ROUND; + gfx->Preset_paintbrush_width [12]= 3; + gfx->Preset_paintbrush_height[12]= 3; + gfx->Paintbrush_type [12]=PAINTBRUSH_SHAPE_ROUND; - Preset_paintbrush_width[13]= 4; - Preset_paintbrush_height[13]= 4; - Paintbrush_type [13]=PAINTBRUSH_SHAPE_ROUND; + gfx->Preset_paintbrush_width [13]= 4; + gfx->Preset_paintbrush_height[13]= 4; + gfx->Paintbrush_type [13]=PAINTBRUSH_SHAPE_ROUND; - Preset_paintbrush_width[14]= 5; - Preset_paintbrush_height[14]= 5; - Paintbrush_type [14]=PAINTBRUSH_SHAPE_ROUND; + gfx->Preset_paintbrush_width [14]= 5; + gfx->Preset_paintbrush_height[14]= 5; + gfx->Paintbrush_type [14]=PAINTBRUSH_SHAPE_ROUND; - Preset_paintbrush_width[15]= 6; - Preset_paintbrush_height[15]= 6; - Paintbrush_type [15]=PAINTBRUSH_SHAPE_ROUND; + gfx->Preset_paintbrush_width [15]= 6; + gfx->Preset_paintbrush_height[15]= 6; + gfx->Paintbrush_type [15]=PAINTBRUSH_SHAPE_ROUND; - Preset_paintbrush_width[16]= 8; - Preset_paintbrush_height[16]= 8; - Paintbrush_type [16]=PAINTBRUSH_SHAPE_ROUND; + gfx->Preset_paintbrush_width [16]= 8; + gfx->Preset_paintbrush_height[16]= 8; + gfx->Paintbrush_type [16]=PAINTBRUSH_SHAPE_ROUND; - Preset_paintbrush_width[17]=10; - Preset_paintbrush_height[17]=10; - Paintbrush_type [17]=PAINTBRUSH_SHAPE_ROUND; + gfx->Preset_paintbrush_width [17]=10; + gfx->Preset_paintbrush_height[17]=10; + gfx->Paintbrush_type [17]=PAINTBRUSH_SHAPE_ROUND; - Preset_paintbrush_width[18]=12; - Preset_paintbrush_height[18]=12; - Paintbrush_type [18]=PAINTBRUSH_SHAPE_ROUND; + gfx->Preset_paintbrush_width [18]=12; + gfx->Preset_paintbrush_height[18]=12; + gfx->Paintbrush_type [18]=PAINTBRUSH_SHAPE_ROUND; - Preset_paintbrush_width[19]=14; - Preset_paintbrush_height[19]=14; - Paintbrush_type [19]=PAINTBRUSH_SHAPE_ROUND; + gfx->Preset_paintbrush_width [19]=14; + gfx->Preset_paintbrush_height[19]=14; + gfx->Paintbrush_type [19]=PAINTBRUSH_SHAPE_ROUND; - Preset_paintbrush_width[20]=16; - Preset_paintbrush_height[20]=16; - Paintbrush_type [20]=PAINTBRUSH_SHAPE_ROUND; + gfx->Preset_paintbrush_width [20]=16; + gfx->Preset_paintbrush_height[20]=16; + gfx->Paintbrush_type [20]=PAINTBRUSH_SHAPE_ROUND; - Preset_paintbrush_width[21]=15; - Preset_paintbrush_height[21]=15; - Paintbrush_type [21]=PAINTBRUSH_SHAPE_SIEVE_ROUND; + gfx->Preset_paintbrush_width [21]=15; + gfx->Preset_paintbrush_height[21]=15; + gfx->Paintbrush_type [21]=PAINTBRUSH_SHAPE_SIEVE_ROUND; - Preset_paintbrush_width[22]=11; - Preset_paintbrush_height[22]=11; - Paintbrush_type [22]=PAINTBRUSH_SHAPE_SIEVE_ROUND; + gfx->Preset_paintbrush_width [22]=11; + gfx->Preset_paintbrush_height[22]=11; + gfx->Paintbrush_type [22]=PAINTBRUSH_SHAPE_SIEVE_ROUND; - Preset_paintbrush_width[23]= 5; - Preset_paintbrush_height[23]= 5; - Paintbrush_type [23]=PAINTBRUSH_SHAPE_SIEVE_ROUND; + gfx->Preset_paintbrush_width [23]= 5; + gfx->Preset_paintbrush_height[23]= 5; + gfx->Paintbrush_type [23]=PAINTBRUSH_SHAPE_SIEVE_ROUND; - Preset_paintbrush_width[24]= 2; - Preset_paintbrush_height[24]= 1; - Paintbrush_type [24]=PAINTBRUSH_SHAPE_HORIZONTAL_BAR; + gfx->Preset_paintbrush_width [24]= 2; + gfx->Preset_paintbrush_height[24]= 1; + gfx->Paintbrush_type [24]=PAINTBRUSH_SHAPE_HORIZONTAL_BAR; - Preset_paintbrush_width[25]= 3; - Preset_paintbrush_height[25]= 1; - Paintbrush_type [25]=PAINTBRUSH_SHAPE_HORIZONTAL_BAR; + gfx->Preset_paintbrush_width [25]= 3; + gfx->Preset_paintbrush_height[25]= 1; + gfx->Paintbrush_type [25]=PAINTBRUSH_SHAPE_HORIZONTAL_BAR; - Preset_paintbrush_width[26]= 4; - Preset_paintbrush_height[26]= 1; - Paintbrush_type [26]=PAINTBRUSH_SHAPE_HORIZONTAL_BAR; + gfx->Preset_paintbrush_width [26]= 4; + gfx->Preset_paintbrush_height[26]= 1; + gfx->Paintbrush_type [26]=PAINTBRUSH_SHAPE_HORIZONTAL_BAR; - Preset_paintbrush_width[27]= 8; - Preset_paintbrush_height[27]= 1; - Paintbrush_type [27]=PAINTBRUSH_SHAPE_HORIZONTAL_BAR; + gfx->Preset_paintbrush_width [27]= 8; + gfx->Preset_paintbrush_height[27]= 1; + gfx->Paintbrush_type [27]=PAINTBRUSH_SHAPE_HORIZONTAL_BAR; - Preset_paintbrush_width[28]= 1; - Preset_paintbrush_height[28]= 2; - Paintbrush_type [28]=PAINTBRUSH_SHAPE_VERTICAL_BAR; + gfx->Preset_paintbrush_width [28]= 1; + gfx->Preset_paintbrush_height[28]= 2; + gfx->Paintbrush_type [28]=PAINTBRUSH_SHAPE_VERTICAL_BAR; - Preset_paintbrush_width[29]= 1; - Preset_paintbrush_height[29]= 3; - Paintbrush_type [29]=PAINTBRUSH_SHAPE_VERTICAL_BAR; + gfx->Preset_paintbrush_width [29]= 1; + gfx->Preset_paintbrush_height[29]= 3; + gfx->Paintbrush_type [29]=PAINTBRUSH_SHAPE_VERTICAL_BAR; - Preset_paintbrush_width[30]= 1; - Preset_paintbrush_height[30]= 4; - Paintbrush_type [30]=PAINTBRUSH_SHAPE_VERTICAL_BAR; + gfx->Preset_paintbrush_width [30]= 1; + gfx->Preset_paintbrush_height[30]= 4; + gfx->Paintbrush_type [30]=PAINTBRUSH_SHAPE_VERTICAL_BAR; - Preset_paintbrush_width[31]= 1; - Preset_paintbrush_height[31]= 8; - Paintbrush_type [31]=PAINTBRUSH_SHAPE_VERTICAL_BAR; + gfx->Preset_paintbrush_width [31]= 1; + gfx->Preset_paintbrush_height[31]= 8; + gfx->Paintbrush_type [31]=PAINTBRUSH_SHAPE_VERTICAL_BAR; - Preset_paintbrush_width[32]= 3; - Preset_paintbrush_height[32]= 3; - Paintbrush_type [32]=PAINTBRUSH_SHAPE_CROSS; + gfx->Preset_paintbrush_width [32]= 3; + gfx->Preset_paintbrush_height[32]= 3; + gfx->Paintbrush_type [32]=PAINTBRUSH_SHAPE_CROSS; - Preset_paintbrush_width[33]= 5; - Preset_paintbrush_height[33]= 5; - Paintbrush_type [33]=PAINTBRUSH_SHAPE_CROSS; + gfx->Preset_paintbrush_width [33]= 5; + gfx->Preset_paintbrush_height[33]= 5; + gfx->Paintbrush_type [33]=PAINTBRUSH_SHAPE_CROSS; - Preset_paintbrush_width[34]= 5; - Preset_paintbrush_height[34]= 5; - Paintbrush_type [34]=PAINTBRUSH_SHAPE_PLUS; + gfx->Preset_paintbrush_width [34]= 5; + gfx->Preset_paintbrush_height[34]= 5; + gfx->Paintbrush_type [34]=PAINTBRUSH_SHAPE_PLUS; - Preset_paintbrush_width[35]=15; - Preset_paintbrush_height[35]=15; - Paintbrush_type [35]=PAINTBRUSH_SHAPE_PLUS; + gfx->Preset_paintbrush_width [35]=15; + gfx->Preset_paintbrush_height[35]=15; + gfx->Paintbrush_type [35]=PAINTBRUSH_SHAPE_PLUS; - Preset_paintbrush_width[36]= 2; - Preset_paintbrush_height[36]= 2; - Paintbrush_type [36]=PAINTBRUSH_SHAPE_SLASH; + gfx->Preset_paintbrush_width [36]= 2; + gfx->Preset_paintbrush_height[36]= 2; + gfx->Paintbrush_type [36]=PAINTBRUSH_SHAPE_SLASH; - Preset_paintbrush_width[37]= 4; - Preset_paintbrush_height[37]= 4; - Paintbrush_type [37]=PAINTBRUSH_SHAPE_SLASH; + gfx->Preset_paintbrush_width [37]= 4; + gfx->Preset_paintbrush_height[37]= 4; + gfx->Paintbrush_type [37]=PAINTBRUSH_SHAPE_SLASH; - Preset_paintbrush_width[38]= 8; - Preset_paintbrush_height[38]= 8; - Paintbrush_type [38]=PAINTBRUSH_SHAPE_SLASH; + gfx->Preset_paintbrush_width [38]= 8; + gfx->Preset_paintbrush_height[38]= 8; + gfx->Paintbrush_type [38]=PAINTBRUSH_SHAPE_SLASH; - Preset_paintbrush_width[39]= 2; - Preset_paintbrush_height[39]= 2; - Paintbrush_type [39]=PAINTBRUSH_SHAPE_ANTISLASH; + gfx->Preset_paintbrush_width [39]= 2; + gfx->Preset_paintbrush_height[39]= 2; + gfx->Paintbrush_type [39]=PAINTBRUSH_SHAPE_ANTISLASH; - Preset_paintbrush_width[40]= 4; - Preset_paintbrush_height[40]= 4; - Paintbrush_type [40]=PAINTBRUSH_SHAPE_ANTISLASH; + gfx->Preset_paintbrush_width [40]= 4; + gfx->Preset_paintbrush_height[40]= 4; + gfx->Paintbrush_type [40]=PAINTBRUSH_SHAPE_ANTISLASH; - Preset_paintbrush_width[41]= 8; - Preset_paintbrush_height[41]= 8; - Paintbrush_type [41]=PAINTBRUSH_SHAPE_ANTISLASH; + gfx->Preset_paintbrush_width [41]= 8; + gfx->Preset_paintbrush_height[41]= 8; + gfx->Paintbrush_type [41]=PAINTBRUSH_SHAPE_ANTISLASH; - Preset_paintbrush_width[42]= 4; - Preset_paintbrush_height[42]= 4; - Paintbrush_type [42]=PAINTBRUSH_SHAPE_RANDOM; + gfx->Preset_paintbrush_width [42]= 4; + gfx->Preset_paintbrush_height[42]= 4; + gfx->Paintbrush_type [42]=PAINTBRUSH_SHAPE_RANDOM; - Preset_paintbrush_width[43]= 8; - Preset_paintbrush_height[43]= 8; - Paintbrush_type [43]=PAINTBRUSH_SHAPE_RANDOM; + gfx->Preset_paintbrush_width [43]= 8; + gfx->Preset_paintbrush_height[43]= 8; + gfx->Paintbrush_type [43]=PAINTBRUSH_SHAPE_RANDOM; - Preset_paintbrush_width[44]=13; - Preset_paintbrush_height[44]=13; - Paintbrush_type [44]=PAINTBRUSH_SHAPE_RANDOM; + gfx->Preset_paintbrush_width [44]=13; + gfx->Preset_paintbrush_height[44]=13; + gfx->Paintbrush_type [44]=PAINTBRUSH_SHAPE_RANDOM; - Preset_paintbrush_width[45]= 3; - Preset_paintbrush_height[45]= 3; - Paintbrush_type [45]=PAINTBRUSH_SHAPE_MISC; + gfx->Preset_paintbrush_width [45]= 3; + gfx->Preset_paintbrush_height[45]= 3; + gfx->Paintbrush_type [45]=PAINTBRUSH_SHAPE_MISC; - Preset_paintbrush_width[46]= 3; - Preset_paintbrush_height[46]= 3; - Paintbrush_type [46]=PAINTBRUSH_SHAPE_MISC; + gfx->Preset_paintbrush_width [46]= 3; + gfx->Preset_paintbrush_height[46]= 3; + gfx->Paintbrush_type [46]=PAINTBRUSH_SHAPE_MISC; - Preset_paintbrush_width[47]= 7; - Preset_paintbrush_height[47]= 7; - Paintbrush_type [47]=PAINTBRUSH_SHAPE_MISC; + gfx->Preset_paintbrush_width [47]= 7; + gfx->Preset_paintbrush_height[47]= 7; + gfx->Paintbrush_type [47]=PAINTBRUSH_SHAPE_MISC; for (index=0;index>1); - Preset_paintbrush_offset_Y[index]=(Preset_paintbrush_height[index]>>1); + gfx->Preset_paintbrush_offset_X[index]=(gfx->Preset_paintbrush_width [index]>>1); + gfx->Preset_paintbrush_offset_Y[index]=(gfx->Preset_paintbrush_height[index]>>1); } + return 0; +} +T_Gui_skin * Load_graphics(const char * skin_file) +{ + T_Gui_skin * gfx; + char filename[MAX_PATH_CHARACTERS]; + SDL_Surface * gui; + + gfx = (T_Gui_skin *)malloc(sizeof(T_Gui_skin)); + if (gfx == NULL) + { + sprintf(Gui_loading_error_message, "Not enough memory to read skin file\n"); + return NULL; + } + + // Read the "skin" file + strcpy(filename,Data_directory); + strcat(filename,"skins" PATH_SEPARATOR); + strcat(filename,skin_file); + + gui=IMG_Load(filename); + if (!gui) + { + sprintf(Gui_loading_error_message, "Unable to load the skin image (missing? not an image file?)\n"); + free(gfx); + return NULL; + } + if (Parse_skin(gui, gfx)) + { + SDL_FreeSurface(gui); + free(gfx); + return NULL; + } + SDL_FreeSurface(gui); + return gfx; +} + +// ---- font loading ----- + +byte Parse_font(SDL_Surface * image, byte * font) +{ + int character; + byte color; + int x, y; + int chars_per_line; + + // Check image size + if (image->w % 8) + { + sprintf(Gui_loading_error_message, "Error in font file: Image width is not a multiple of 8.\n"); + return 1; + } + if (image->w * image->h < 8*8*256) + { + sprintf(Gui_loading_error_message, "Error in font file: Image is too small to be a 256-character 8x8 font.\n"); + return 1; + } + chars_per_line = image->w/8; + + for (character=0; character < 256; character++) + { + for (y=0; y<8; y++) + { + for (x=0;x<8; x++) + { + // Pick pixel + color = Get_SDL_pixel_8(image, (character % chars_per_line)*8+x, (character / chars_per_line)*8+y); + if (color > 1) + { + sprintf(Gui_loading_error_message, "Error in font file: Only colors 0 and 1 can be used for the font.\n"); + return 1; + } + // Put it in font. 0 = BG, 1 = FG. + font[character*64 + y*8 + x]=color; + } + } + } + return 0; +} + +byte * Load_font(const char * font_name) +{ + byte * font; + char filename[MAX_PATH_CHARACTERS]; + SDL_Surface * image; + + font = (byte *)malloc(8*8*256); + if (font == NULL) + { + sprintf(Gui_loading_error_message, "Not enough memory to read font file\n"); + return NULL; + } + + // Read the file containing the image + sprintf(filename,"%sskins%s%s", Data_directory, PATH_SEPARATOR, font_name); + + image=IMG_Load(filename); + if (!image) + { + sprintf(Gui_loading_error_message, "Unable to load the skin image (missing? not an image file?)\n"); + free(font); + return NULL; + } + if (Parse_font(image, font)) + { + SDL_FreeSurface(image); + free(font); + return NULL; + } + SDL_FreeSurface(image); + return font; } @@ -920,20 +1029,12 @@ void Init_buttons(void) Init_button(BUTTON_GRADRECT, 85,1, - 15,15, - BUTTON_SHAPE_TRIANGLE_TOP_LEFT, - Button_Grad_rectangle,Button_Grad_rectangle, + 16,16, + BUTTON_SHAPE_RECTANGLE, + Button_Grad_rectangle,Button_Gradients, Do_nothing, FAMILY_TOOL); - Init_button(BUTTON_GRADMENU, - 86,2, - 15,15, - BUTTON_SHAPE_TRIANGLE_BOTTOM_RIGHT, - Button_Gradients,Button_Gradients, - Do_nothing, - FAMILY_INSTANT); - Init_button(BUTTON_SPHERES, 85,18, 16,16, @@ -1034,7 +1135,7 @@ void Init_buttons(void) 178,18, 16,16, BUTTON_SHAPE_RECTANGLE, - Button_Settings,Button_Settings, + Button_Settings,Button_Skins, Do_nothing, FAMILY_INSTANT); @@ -1128,13 +1229,16 @@ void Init_buttons(void) void Init_operation(byte operation_number, byte mouse_button, byte stack_index, - Func_action Action, - byte Hide_cursor) + Func_action action, + byte hide_cursor, + byte fast_mouse) { Operation[operation_number][mouse_button] - [stack_index].Action=Action; + [stack_index].Action=action; Operation[operation_number][mouse_button] - [stack_index].Hide_cursor=Hide_cursor; + [stack_index].Hide_cursor=hide_cursor; + Operation[operation_number][mouse_button] + [stack_index].Fast_mouse=fast_mouse; } @@ -1145,391 +1249,393 @@ void Init_operations(void) byte number; // Numéro de l'option en cours d'auto-initialisation byte Button; // Button souris en cours d'auto-initialisation byte stack_index; // Taille de la pile en cours d'auto-initialisation + #define HIDE_CURSOR 1 + #define FAST_MOUSE 1 // Auto-initialisation des opérations (vers des actions inoffensives) for (number=0;number -*/ - -////////////////////////////////////////////////////////////////////////////// -///@file init.h -/// Initialization (and some de-initialization) functions. -////////////////////////////////////////////////////////////////////////////// - -void Load_graphics(const char * skin_file); -void Init_buttons(void); -void Init_operations(void); -int Load_CFG(int reload_all); -int Save_CFG(void); -void Set_all_video_modes(void); -void Set_config_defaults(void); -void Init_sighandler(void); +/* Grafx2 - The Ultimate 256-color bitmap paint program + + Copyright 2007 Adrien Destugues + Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) + + Grafx2 is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 + of the License. + + Grafx2 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grafx2; if not, see +*/ + +////////////////////////////////////////////////////////////////////////////// +///@file init.h +/// Initialization (and some de-initialization) functions. +////////////////////////////////////////////////////////////////////////////// + +T_Gui_skin *Load_graphics(const char * skin_file); +void Init_buttons(void); +void Init_operations(void); +void Init_brush_container(void); +int Load_CFG(int reload_all); +int Save_CFG(void); +void Set_all_video_modes(void); +void Set_config_defaults(void); +void Init_sighandler(void); + +extern char Gui_loading_error_message[512]; + +/// +/// Loads a 8x8 monochrome font, the kind used in all menus and screens. +/// This function allocates the memory, and returns a pointer to it when +/// successful. +/// If an error is encountered, it frees what needs it, prints an error message +/// in ::Gui_loading_error_message, and returns NULL. +byte * Load_font(const char * font_name); diff --git a/input.c b/input.c index 77a1bc3d..f5cb582d 100644 --- a/input.c +++ b/input.c @@ -31,6 +31,15 @@ void Handle_window_resize(SDL_ResizeEvent event); void Handle_window_exit(SDL_QuitEvent event); +// public Globals (available as extern) + +int Input_sticky_control = 0; +int Snap_axis = 0; +int Snap_axis_origin_X; +int Snap_axis_origin_Y; + +// -- + byte Directional_up; byte Directional_up_right; byte Directional_right; @@ -39,10 +48,12 @@ byte Directional_down; byte Directional_down_left; byte Directional_left; byte Directional_up_left; +byte Directional_click; + long Directional_delay; long Directional_last_move; long Directional_step; -short Mouse_count; // Number of mouse movements received in the current Get_input() +int Mouse_moved; ///< Boolean, Set to true if any cursor movement occurs. word Input_new_mouse_X; word Input_new_mouse_Y; @@ -71,7 +82,7 @@ short Joybutton_right_click=0; // Button number that serves as right-click int Is_shortcut(word Key, word function) { - if (Key == 0) + if (Key == 0 || function == 0xFFFF) return 0; if (function & 0x100) @@ -101,19 +112,20 @@ int Is_shortcut(word Key, word function) int Move_cursor_with_constraints() { int feedback=0; - byte bl=0;//BL va indiquer si on doit corriger la position du curseur + int mouse_blocked=0; ///< Boolean, Set to true if mouse movement was clipped. + // Clip mouse to the editing area. There can be a border when using big // pixels, if the SDL screen dimensions are not factors of the pixel size. if (Input_new_mouse_Y>=Screen_height) { Input_new_mouse_Y=Screen_height-1; - bl=1; + mouse_blocked=1; } if (Input_new_mouse_X>=Screen_width) { Input_new_mouse_X=Screen_width-1; - bl=1; + mouse_blocked=1; } //Gestion "avancée" du curseur: interdire la descente du curseur dans le //menu lorsqu'on est en train de travailler dans l'image @@ -125,7 +137,7 @@ int Move_cursor_with_constraints() if(Menu_Y<=Input_new_mouse_Y) { //On bloque le curseur en fin d'image - bl++; + mouse_blocked=1; Input_new_mouse_Y=Menu_Y-1; //La ligne !!au-dessus!! du menu } @@ -135,7 +147,7 @@ int Move_cursor_with_constraints() { if(Input_new_mouse_X>=Main_separator_position) { - bl++; + mouse_blocked=1; Input_new_mouse_X=Main_separator_position-1; } } @@ -143,7 +155,7 @@ int Move_cursor_with_constraints() { if(Input_new_mouse_XConfig.Mouse_merge_movement) - feedback=1; + if (Mouse_moved > Config.Mouse_merge_movement) + if (! Operation[Current_operation][Mouse_K_unique] + [Operation_stack_size].Fast_mouse) + feedback=1; } - + if (mouse_blocked) + Set_mouse_position(); return feedback; } @@ -296,6 +319,7 @@ int Handle_mouse_release(SDL_MouseButtonEvent event) Input_new_mouse_K &= ~2; break; } + return Move_cursor_with_constraints(); } @@ -327,14 +351,16 @@ int Handle_key_press(SDL_KeyboardEvent event) Directional_right=1; return 0; } - else if(Is_shortcut(Key,SPECIAL_CLICK_LEFT)) + else if(Is_shortcut(Key,SPECIAL_CLICK_LEFT) && Keyboard_click_allowed > 0) { Input_new_mouse_K=1; + Directional_click=1; return Move_cursor_with_constraints(); } - else if(Is_shortcut(Key,SPECIAL_CLICK_RIGHT)) + else if(Is_shortcut(Key,SPECIAL_CLICK_RIGHT) && Keyboard_click_allowed > 0) { Input_new_mouse_K=2; + Directional_click=2; return Move_cursor_with_constraints(); } @@ -344,44 +370,60 @@ int Handle_key_press(SDL_KeyboardEvent event) int Release_control(int key_code, int modifier) { + int need_feedback = 0; - if(key_code == (Config_Key[SPECIAL_MOUSE_UP][0]&0x0FFF) || (Config_Key[SPECIAL_MOUSE_UP][0]&modifier) || - key_code == (Config_Key[SPECIAL_MOUSE_UP][1]&0x0FFF) || (Config_Key[SPECIAL_MOUSE_UP][1]&modifier)) + if (modifier == MOD_SHIFT) + { + // Disable "snap axis" mode + Snap_axis = 0; + need_feedback = 1; + } + + if((key_code && key_code == (Config_Key[SPECIAL_MOUSE_UP][0]&0x0FFF)) || (Config_Key[SPECIAL_MOUSE_UP][0]&modifier) || + (key_code && key_code == (Config_Key[SPECIAL_MOUSE_UP][1]&0x0FFF)) || (Config_Key[SPECIAL_MOUSE_UP][1]&modifier)) { Directional_up=0; } - if(key_code == (Config_Key[SPECIAL_MOUSE_DOWN][0]&0x0FFF) || (Config_Key[SPECIAL_MOUSE_DOWN][0]&modifier) || - key_code == (Config_Key[SPECIAL_MOUSE_DOWN][1]&0x0FFF) || (Config_Key[SPECIAL_MOUSE_DOWN][1]&modifier)) + if((key_code && key_code == (Config_Key[SPECIAL_MOUSE_DOWN][0]&0x0FFF)) || (Config_Key[SPECIAL_MOUSE_DOWN][0]&modifier) || + (key_code && key_code == (Config_Key[SPECIAL_MOUSE_DOWN][1]&0x0FFF)) || (Config_Key[SPECIAL_MOUSE_DOWN][1]&modifier)) { Directional_down=0; } - if(key_code == (Config_Key[SPECIAL_MOUSE_LEFT][0]&0x0FFF) || (Config_Key[SPECIAL_MOUSE_LEFT][0]&modifier) || - key_code == (Config_Key[SPECIAL_MOUSE_LEFT][1]&0x0FFF) || (Config_Key[SPECIAL_MOUSE_LEFT][1]&modifier)) + if((key_code && key_code == (Config_Key[SPECIAL_MOUSE_LEFT][0]&0x0FFF)) || (Config_Key[SPECIAL_MOUSE_LEFT][0]&modifier) || + (key_code && key_code == (Config_Key[SPECIAL_MOUSE_LEFT][1]&0x0FFF)) || (Config_Key[SPECIAL_MOUSE_LEFT][1]&modifier)) { Directional_left=0; } - if(key_code == (Config_Key[SPECIAL_MOUSE_RIGHT][0]&0x0FFF) || (Config_Key[SPECIAL_MOUSE_RIGHT][0]&modifier) || - key_code == (Config_Key[SPECIAL_MOUSE_RIGHT][1]&0x0FFF) || (Config_Key[SPECIAL_MOUSE_RIGHT][1]&modifier)) + if((key_code && key_code == (Config_Key[SPECIAL_MOUSE_RIGHT][0]&0x0FFF)) || (Config_Key[SPECIAL_MOUSE_RIGHT][0]&modifier) || + (key_code && key_code == (Config_Key[SPECIAL_MOUSE_RIGHT][1]&0x0FFF)) || (Config_Key[SPECIAL_MOUSE_RIGHT][1]&modifier)) { Directional_right=0; } - if(key_code == (Config_Key[SPECIAL_CLICK_LEFT][0]&0x0FFF) || (Config_Key[SPECIAL_CLICK_LEFT][0]&modifier) || - key_code == (Config_Key[SPECIAL_CLICK_LEFT][1]&0x0FFF) || (Config_Key[SPECIAL_CLICK_LEFT][1]&modifier)) + if((key_code && key_code == (Config_Key[SPECIAL_CLICK_LEFT][0]&0x0FFF)) || (Config_Key[SPECIAL_CLICK_LEFT][0]&modifier) || + (key_code && key_code == (Config_Key[SPECIAL_CLICK_LEFT][1]&0x0FFF)) || (Config_Key[SPECIAL_CLICK_LEFT][1]&modifier)) { - Input_new_mouse_K &= ~1; - return Move_cursor_with_constraints(); + if (Directional_click & 1) + { + Directional_click &= ~1; + Input_new_mouse_K &= ~1; + return Move_cursor_with_constraints() || need_feedback; + } } - if(key_code == (Config_Key[SPECIAL_CLICK_RIGHT][0]&0x0FFF) || (Config_Key[SPECIAL_CLICK_RIGHT][0]&modifier) || - key_code == (Config_Key[SPECIAL_CLICK_RIGHT][1]&0x0FFF) || (Config_Key[SPECIAL_CLICK_RIGHT][1]&modifier)) + if((key_code && key_code == (Config_Key[SPECIAL_CLICK_RIGHT][0]&0x0FFF)) || (Config_Key[SPECIAL_CLICK_RIGHT][0]&modifier) || + (key_code && key_code == (Config_Key[SPECIAL_CLICK_RIGHT][1]&0x0FFF)) || (Config_Key[SPECIAL_CLICK_RIGHT][1]&modifier)) { - Input_new_mouse_K &= ~2; - return Move_cursor_with_constraints(); + if (Directional_click & 2) + { + Directional_click &= ~2; + Input_new_mouse_K &= ~2; + return Move_cursor_with_constraints() || need_feedback; + } } // Other keys don't need to be released : they are handled as "events" and procesed only once. // These clicks are apart because they need to be continuous (ie move while key pressed) // We are relying on "hardware" keyrepeat to achieve that. - return 0; + return need_feedback; } @@ -614,10 +656,12 @@ int Get_input(void) { SDL_Event event; int user_feedback_required = 0; // Flag qui indique si on doit arrêter de traiter les évènements ou si on peut enchainer - + Key_ANSI = 0; Key = 0; - Mouse_count=0; + Mouse_moved=0; + Input_new_mouse_X = Mouse_X; + Input_new_mouse_Y = Mouse_Y; // Process as much events as possible without redrawing the screen. // This mostly allows us to merge mouse events for people with an high @@ -734,11 +778,20 @@ int Get_input(void) } } } - // Vidage de toute mise à jour de l'affichage à l'écran qui serait encore en attente. - // (c'est fait ici car on est sur que cette function est apellée partout ou on a besoin d'interragir avec l'utilisateur) + // If the cursor was moved since last update, + // it was erased, so we need to redraw it (with the preview brush) + if (Mouse_moved) + { + Compute_paintbrush_coordinates(); + Display_cursor(); + } + // Commit any pending screen update. + // This is done in this function because it's called after reading + // some user input. Flush_update(); - return user_feedback_required; + + return (Mouse_moved!=0) || user_feedback_required; } void Adjust_mouse_sensitivity(word fullscreen) diff --git a/input.h b/input.h index 7a878c95..c6f68f23 100644 --- a/input.h +++ b/input.h @@ -40,3 +40,17 @@ int Is_shortcut(word Key, word function); void Adjust_mouse_sensitivity(word fullscreen); void Set_mouse_position(void); + +/// +/// This holds the ID of the GUI control that the mouse +/// is manipulating. The input system will reset it to zero +/// when mouse button is released, but it's the engine +/// that will record and retrieve a real control ID. +extern int Input_sticky_control; + +/// Allows locking movement to X or Y axis: 0=normal, 1=lock on next move, 2=locked horizontally, 3=locked vertically. +extern int Snap_axis; +/// For the :Snap_axis mode, sets the origin's point (in image coordinates) +extern int Snap_axis_origin_X; +/// For the :Snap_axis mode, sets the origin's point (in image coordinates) +extern int Snap_axis_origin_Y; diff --git a/install/WinInstaller.nsi b/install/WinInstaller.nsi index de83d47a..95552b64 100644 --- a/install/WinInstaller.nsi +++ b/install/WinInstaller.nsi @@ -11,7 +11,7 @@ ;Name and file Name "Grafx2" - OutFile "grafx2-2.0-svn853-win32.exe" + OutFile "grafx2-2.1.1026.win32.exe" ;Default installation folder InstallDir "$PROGRAMFILES\Grafx2" @@ -60,7 +60,7 @@ Section "Grafx2" SecProgram SetOutPath "$INSTDIR" ;ADD YOUR OWN FILES HERE... File ..\grafx2.exe - File ..\src-svn853.tgz + File ..\src-2.1.1026.tgz File ..\gfx2.gif File ..\gfx2def.ini File ..\SDL_image.dll @@ -70,7 +70,10 @@ Section "Grafx2" SecProgram File ..\zlib1.dll File ..\libpng13.dll SetOutPath "$INSTDIR\skins" - File ..\skins\base.gif + File ..\skins\font_Classic.png + File ..\skins\font_Fun.png + File ..\skins\skin_classic.png + File ..\skins\skin_modern.png SetOutPath "$INSTDIR\doc" File ..\doc\README.txt File ..\doc\COMPILING.txt @@ -97,7 +100,7 @@ Section "Grafx2" SecProgram WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Grafx2-SDL" \ "URLInfoAbout" "http://grafx2.googlecode.com" WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Grafx2-SDL" \ - "DisplayVersion" "2.0 final" + "DisplayVersion" "2.1.1026" WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Grafx2-SDL" \ "NoModify" 1 WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Grafx2-SDL" \ @@ -139,7 +142,7 @@ Section "un.SecProgram" ;ADD YOUR OWN FILES HERE... Delete "$INSTDIR\grafx2.exe" - Delete "$INSTDIR\src-svn853.tgz" + Delete "$INSTDIR\src-2.1.1026.tgz" Delete "$INSTDIR\gfx2.gif" Delete "$INSTDIR\gfx2def.ini" Delete "$INSTDIR\SDL_image.dll" @@ -159,7 +162,10 @@ Section "un.SecProgram" Delete "$INSTDIR\fonts\8pxfont.png" Delete "$INSTDIR\fonts\Tuffy.ttf" RMDir "$INSTDIR\fonts" - Delete "$INSTDIR\skins\base.gif" + Delete "$INSTDIR\skins\font_Classic.png" + Delete "$INSTDIR\skins\font_Fun.png" + Delete "$INSTDIR\skins\skin_classic.png" + Delete "$INSTDIR\skins\skin_modern.png" RMDir "$INSTDIR\skins" Delete "$INSTDIR\Uninstall.exe" diff --git a/io.c b/io.c index fe210fb6..507700be 100644 --- a/io.c +++ b/io.c @@ -243,16 +243,16 @@ int File_length_file(FILE * file) void For_each_file(const char * directory_name, void Callback(const char *)) { // Pour scan de répertoire - DIR* Repertoire_Courant; //Répertoire courant + DIR* current_directory; //Répertoire courant struct dirent* entry; // Structure de lecture des éléments char full_filename[MAX_PATH_CHARACTERS]; int filename_position; strcpy(full_filename, directory_name); - Repertoire_Courant=opendir(directory_name); - if(Repertoire_Courant == NULL) return; // Répertoire invalide ... + current_directory=opendir(directory_name); + if(current_directory == NULL) return; // Répertoire invalide ... strcat(full_filename, PATH_SEPARATOR); filename_position = strlen(full_filename); - while ((entry=readdir(Repertoire_Courant))) + while ((entry=readdir(current_directory))) { struct stat Infos_enreg; strcpy(&full_filename[filename_position], entry->d_name); @@ -262,6 +262,6 @@ void For_each_file(const char * directory_name, void Callback(const char *)) Callback(full_filename); } } - closedir(Repertoire_Courant); + closedir(current_directory); } diff --git a/keyboard.c b/keyboard.c index a9de06a3..5582d931 100644 --- a/keyboard.c +++ b/keyboard.c @@ -1,650 +1,650 @@ -/* Grafx2 - The Ultimate 256-color bitmap paint program - - Copyright 2009 Franck Charlet - Copyright 2008 Yves Rizoud - Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) - - Grafx2 is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; version 2 - of the License. - - Grafx2 is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Grafx2; if not, see -*/ -#include -#include -#include "global.h" -#include "keyboard.h" - -// Table de correspondance des scancode de clavier IBM PC AT vers -// les symboles de touches SDL (sym). -// La correspondance est bonne si le clavier est QWERTY US, ou si -// l'utilisateur est sous Windows. -// Dans l'ordre des colonnes: Normal, +Shift, +Control, +Alt -const word Scancode_to_sym[256][4] = -{ -/* 00 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* 01 Esc */ { SDLK_ESCAPE ,SDLK_ESCAPE ,SDLK_ESCAPE ,SDLK_ESCAPE }, -/* 02 1 ! */ { SDLK_1 ,SDLK_1 ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* 03 2 @ */ { SDLK_2 ,SDLK_2 ,SDLK_2 ,SDLK_UNKNOWN }, -/* 04 3 # */ { SDLK_3 ,SDLK_3 ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* 05 4 $ */ { SDLK_4 ,SDLK_4 ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* 06 5 % */ { SDLK_5 ,SDLK_5 ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* 07 6 ^ */ { SDLK_6 ,SDLK_6 ,SDLK_6 ,SDLK_UNKNOWN }, -/* 08 7 & */ { SDLK_7 ,SDLK_7 ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* 09 8 * */ { SDLK_8 ,SDLK_8 ,SDLK_8 ,SDLK_UNKNOWN }, -/* 0A 9 ( */ { SDLK_9 ,SDLK_9 ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* 0B 0 ) */ { SDLK_0 ,SDLK_0 ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* 0C - _ */ { SDLK_MINUS ,SDLK_MINUS ,SDLK_MINUS ,SDLK_UNKNOWN }, -/* 0D = + */ { SDLK_EQUALS ,SDLK_EQUALS ,SDLK_EQUALS ,SDLK_UNKNOWN }, -/* 0E BkSpc */ { SDLK_BACKSPACE ,SDLK_BACKSPACE ,SDLK_BACKSPACE ,SDLK_BACKSPACE }, -/* 0F Tab */ { SDLK_TAB ,SDLK_TAB ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* 10 Q */ { SDLK_q ,SDLK_q ,SDLK_q ,SDLK_q }, -/* 11 W */ { SDLK_w ,SDLK_w ,SDLK_w ,SDLK_w }, -/* 12 E */ { SDLK_e ,SDLK_e ,SDLK_e ,SDLK_e }, -/* 13 R */ { SDLK_r ,SDLK_r ,SDLK_r ,SDLK_r }, -/* 14 T */ { SDLK_t ,SDLK_t ,SDLK_t ,SDLK_t }, -/* 15 Y */ { SDLK_y ,SDLK_y ,SDLK_y ,SDLK_y }, -/* 16 U */ { SDLK_u ,SDLK_u ,SDLK_u ,SDLK_u }, -/* 17 I */ { SDLK_i ,SDLK_i ,SDLK_i ,SDLK_i }, -/* 18 O */ { SDLK_o ,SDLK_o ,SDLK_o ,SDLK_o }, -/* 19 P */ { SDLK_p ,SDLK_p ,SDLK_p ,SDLK_p }, -/* 1A [ */ { SDLK_LEFTBRACKET ,SDLK_LEFTBRACKET ,SDLK_LEFTBRACKET ,SDLK_LEFTBRACKET }, -/* 1B ] */ { SDLK_RIGHTBRACKET,SDLK_RIGHTBRACKET,SDLK_RIGHTBRACKET,SDLK_RIGHTBRACKET}, -/* 1C Retrn */ { SDLK_RETURN ,SDLK_RETURN ,SDLK_RETURN ,SDLK_RETURN }, -/* 1D ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* 1E A */ { SDLK_a ,SDLK_a ,SDLK_a ,SDLK_a }, -/* 1F S */ { SDLK_s ,SDLK_s ,SDLK_s ,SDLK_s }, -/* 20 D */ { SDLK_d ,SDLK_d ,SDLK_d ,SDLK_d }, -/* 21 F */ { SDLK_f ,SDLK_f ,SDLK_f ,SDLK_f }, -/* 22 G */ { SDLK_g ,SDLK_g ,SDLK_g ,SDLK_g }, -/* 23 H */ { SDLK_h ,SDLK_h ,SDLK_h ,SDLK_h }, -/* 24 J */ { SDLK_j ,SDLK_j ,SDLK_j ,SDLK_j }, -/* 25 K */ { SDLK_k ,SDLK_k ,SDLK_k ,SDLK_k }, -/* 26 L */ { SDLK_l ,SDLK_l ,SDLK_l ,SDLK_l }, -/* 27 ; : */ { SDLK_SEMICOLON ,SDLK_SEMICOLON ,SDLK_SEMICOLON ,SDLK_SEMICOLON }, -/* 28 ' */ { SDLK_QUOTE ,SDLK_QUOTE ,SDLK_UNKNOWN ,SDLK_QUOTE }, -/* 29 ` ~ */ { SDLK_BACKQUOTE ,SDLK_BACKQUOTE ,SDLK_UNKNOWN ,SDLK_BACKQUOTE }, -/* 2A ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* 2B \\ */ { SDLK_BACKSLASH ,SDLK_BACKSLASH ,SDLK_BACKSLASH ,SDLK_BACKSLASH }, -/* 2C Z */ { SDLK_z ,SDLK_z ,SDLK_z ,SDLK_z }, -/* 2D X */ { SDLK_x ,SDLK_x ,SDLK_x ,SDLK_x }, -/* 2E C */ { SDLK_c ,SDLK_c ,SDLK_c ,SDLK_c }, -/* 2F V */ { SDLK_v ,SDLK_v ,SDLK_v ,SDLK_v }, -/* 30 B */ { SDLK_b ,SDLK_b ,SDLK_b ,SDLK_b }, -/* 31 N */ { SDLK_n ,SDLK_n ,SDLK_n ,SDLK_n }, -/* 32 M */ { SDLK_m ,SDLK_m ,SDLK_m ,SDLK_m }, -/* 33 , < */ { SDLK_COMMA ,SDLK_COMMA ,SDLK_UNKNOWN ,SDLK_COMMA }, -/* 34 . > */ { SDLK_PERIOD ,SDLK_PERIOD ,SDLK_UNKNOWN ,SDLK_PERIOD }, -/* 35 / ? */ { SDLK_SLASH ,SDLK_SLASH ,SDLK_UNKNOWN ,SDLK_SLASH }, -/* 36 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* 37 Grey* */ { SDLK_KP_MULTIPLY ,SDLK_KP_MULTIPLY ,SDLK_UNKNOWN ,SDLK_KP_MULTIPLY }, -/* 38 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* 39 Space */ { SDLK_SPACE ,SDLK_SPACE ,SDLK_SPACE ,SDLK_SPACE }, -/* 3A ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* 3B F1 */ { SDLK_F1 ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* 3C F2 */ { SDLK_F2 ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* 3D F3 */ { SDLK_F3 ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* 3E F4 */ { SDLK_F4 ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* 3F F5 */ { SDLK_F5 ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* 40 F6 */ { SDLK_F6 ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* 41 F7 */ { SDLK_F7 ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* 42 F8 */ { SDLK_F8 ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* 43 F9 */ { SDLK_F9 ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* 44 F10 */ { SDLK_F10 ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* 45 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* 46 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* 47 Home */ { SDLK_HOME ,SDLK_HOME ,SDLK_UNKNOWN ,SDLK_HOME }, -/* 48 Up */ { SDLK_UP ,SDLK_UP ,SDLK_UNKNOWN ,SDLK_UP }, -/* 49 PgUp */ { SDLK_PAGEUP ,SDLK_PAGEUP ,SDLK_UNKNOWN ,SDLK_PAGEUP }, -/* 4A Grey- */ { SDLK_KP_MINUS ,SDLK_KP_MINUS ,SDLK_UNKNOWN ,SDLK_KP_MINUS }, -/* 4B Left */ { SDLK_LEFT ,SDLK_LEFT ,SDLK_UNKNOWN ,SDLK_LEFT }, -/* 4C Kpad5 */ { SDLK_KP5 ,SDLK_KP5 ,SDLK_UNKNOWN ,SDLK_KP5 }, -/* 4D Right */ { SDLK_RIGHT ,SDLK_RIGHT ,SDLK_UNKNOWN ,SDLK_RIGHT }, -/* 4E Grey+ */ { SDLK_KP_PLUS ,SDLK_KP_PLUS ,SDLK_UNKNOWN ,SDLK_KP_PLUS }, -/* 4F End */ { SDLK_END ,SDLK_END ,SDLK_UNKNOWN ,SDLK_END }, -/* 50 Down */ { SDLK_DOWN ,SDLK_DOWN ,SDLK_UNKNOWN ,SDLK_DOWN }, -/* 51 PgDn */ { SDLK_PAGEDOWN ,SDLK_PAGEDOWN ,SDLK_UNKNOWN ,SDLK_PAGEDOWN }, -/* 52 Ins */ { SDLK_INSERT ,SDLK_INSERT ,SDLK_UNKNOWN ,SDLK_INSERT }, -/* 53 Del */ { SDLK_DELETE ,SDLK_DELETE ,SDLK_UNKNOWN ,SDLK_DELETE }, -/* 54 ??? */ { SDLK_UNKNOWN ,SDLK_F1 ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* 55 ??? */ { SDLK_UNKNOWN ,SDLK_F2 ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* 56 Lft| */ { SDLK_UNKNOWN ,SDLK_F3 ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* 57 ??? */ { SDLK_UNKNOWN ,SDLK_F4 ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* 58 ??? */ { SDLK_UNKNOWN ,SDLK_F5 ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* 59 ??? */ { SDLK_UNKNOWN ,SDLK_F6 ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* 5A ??? */ { SDLK_UNKNOWN ,SDLK_F7 ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* 5B ??? */ { SDLK_UNKNOWN ,SDLK_F8 ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* 5C ??? */ { SDLK_UNKNOWN ,SDLK_F9 ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* 5D ??? */ { SDLK_UNKNOWN ,SDLK_F10 ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* 5E ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F1 ,SDLK_UNKNOWN }, -/* 5F ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F2 ,SDLK_UNKNOWN }, -/* 60 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F3 ,SDLK_UNKNOWN }, -/* 61 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F4 ,SDLK_UNKNOWN }, -/* 62 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F5 ,SDLK_UNKNOWN }, -/* 63 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F6 ,SDLK_UNKNOWN }, -/* 64 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F7 ,SDLK_UNKNOWN }, -/* 65 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F8 ,SDLK_UNKNOWN }, -/* 66 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F9 ,SDLK_UNKNOWN }, -/* 67 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F10 ,SDLK_UNKNOWN }, -/* 68 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F1 }, -/* 69 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F2 }, -/* 6A ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F3 }, -/* 6B ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F4 }, -/* 6C ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F5 }, -/* 6D ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F6 }, -/* 6E ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F7 }, -/* 6F ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F8 }, -/* 70 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F9 }, -/* 71 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F10 }, -/* 72 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* 73 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_LEFT ,SDLK_UNKNOWN }, -/* 74 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_RIGHT ,SDLK_UNKNOWN }, -/* 75 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_END ,SDLK_UNKNOWN }, -/* 76 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_PAGEDOWN ,SDLK_UNKNOWN }, -/* 77 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_HOME ,SDLK_UNKNOWN }, -/* 78 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_1 }, -/* 79 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_2 }, -/* 7A ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_3 }, -/* 7B ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_4 }, -/* 7C ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_5 }, -/* 7D ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_6 }, -/* 7E ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_7 }, -/* 7F ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_8 }, -/* 80 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_9 }, -/* 81 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_0 }, -/* 82 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_MINUS }, -/* 83 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_EQUALS }, -/* 84 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_PAGEUP ,SDLK_UNKNOWN }, -/* 85 F11 */ { SDLK_F11 ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* 86 F12 */ { SDLK_F12 ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* 87 ??? */ { SDLK_UNKNOWN ,SDLK_F11 ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* 88 ??? */ { SDLK_UNKNOWN ,SDLK_F12 ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* 89 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F11 ,SDLK_UNKNOWN }, -/* 8A ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F12 ,SDLK_UNKNOWN }, -/* 8B ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F11 }, -/* 8C ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F12 }, -/* 8D ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UP ,SDLK_UNKNOWN }, -/* 8E ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_KP_MINUS ,SDLK_UNKNOWN }, -/* 8F ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_KP5 ,SDLK_UNKNOWN }, -/* 90 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_KP_PLUS ,SDLK_UNKNOWN }, -/* 91 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_DOWN ,SDLK_UNKNOWN }, -/* 92 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_INSERT ,SDLK_UNKNOWN }, -/* 93 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_DELETE ,SDLK_UNKNOWN }, -/* 94 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_TAB ,SDLK_UNKNOWN }, -/* 95 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_KP_DIVIDE ,SDLK_UNKNOWN }, -/* 96 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_KP_MULTIPLY ,SDLK_UNKNOWN }, -/* 97 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_HOME }, -/* 98 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UP }, -/* 99 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_PAGEUP }, -/* 9A ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* 9B ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_LEFT }, -/* 9C ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* 9D ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_RIGHT }, -/* 9E ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* 9F ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_END }, -/* A0 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_DOWN }, -/* A1 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_PAGEUP }, -/* A2 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_INSERT }, -/* A3 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_DELETE }, -/* A4 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_KP_DIVIDE }, -/* A5 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_TAB }, -/* A6 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_KP_ENTER }, -/* A7 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* A8 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* A9 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* AA ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* AB ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* AC ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* AD ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* AE ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* AF ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* B0 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* B1 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* B2 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* B3 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* B4 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* B5 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* B6 Win L */ { SDLK_LSUPER ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* B7 Win R */ { SDLK_RSUPER ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* B8 Win M */ { SDLK_MENU ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* B9 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* BA ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* BB ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* BC ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* BD ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* BE ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* BF ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* C0 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* C1 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* C2 ??? */ { SDLK_UNKNOWN ,SDLK_LSUPER ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* C3 ??? */ { SDLK_UNKNOWN ,SDLK_RSUPER ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* C4 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* C5 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* C6 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* C7 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* C8 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* C9 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* CA ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* CB ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* CC ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* CD ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* CE ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_LSUPER ,SDLK_UNKNOWN }, -/* CF ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_RSUPER ,SDLK_UNKNOWN }, -/* D0 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_MENU ,SDLK_UNKNOWN }, -/* D1 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* D2 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* D3 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* D4 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* D5 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* D6 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* D7 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* D8 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* D9 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* DA ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_LSUPER }, -/* DB ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_RSUPER }, -/* DC ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_MENU }, -/* DD ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* DE ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* DF ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* E0 Enter */ { SDLK_KP_ENTER ,SDLK_KP_ENTER ,SDLK_KP_ENTER ,SDLK_UNKNOWN }, -/* E1 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* E2 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* E3 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* E4 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* E5 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* E6 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* E7 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* E8 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* E9 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* EA ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* EB ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* EC ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* ED ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* EE ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* EF ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* F0 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* F1 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* F2 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* F3 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* F4 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* F5 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* F6 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* F7 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* F8 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* F9 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* FA ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* FB ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* FC ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* FD ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* FE ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -/* FF ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, -}; - -// Conversion de l'ancien codage des touches: -// 0x00FF le scancode (maintenant code sym sur 0x0FFF) -// 0x0100 shift (maintenant 0x1000) -// 0x0200 control (maintenant 0x2000) -// 0x0400 alt (maintenant 0x4000) -word Key_for_scancode(word scancode) -{ - if (scancode & 0x0400) - return Scancode_to_sym[scancode & 0xFF][3] | - (scancode & 0x0700) << 4; - else if (scancode & 0x0200) - return Scancode_to_sym[scancode & 0xFF][2] | - (scancode & 0x0700) << 4; - else if (scancode & 0x0100) - return Scancode_to_sym[scancode & 0xFF][1] | - (scancode & 0x0700) << 4; - else - return Scancode_to_sym[scancode & 0xFF][0]; -} - -// Convertit des modificateurs de touches SDL en modificateurs GrafX2 -word Key_modifiers(SDLMod mod) -{ - word modifiers=0; - - if (mod & KMOD_CTRL ) - modifiers|=MOD_CTRL; - if (mod & KMOD_SHIFT ) - modifiers|=MOD_SHIFT; - if (mod & (KMOD_ALT|KMOD_MODE)) - modifiers|=MOD_ALT; - if (mod & (KMOD_META)) - modifiers|=MOD_META; - - return modifiers; -} - -word Keysym_to_keycode(SDL_keysym keysym) -{ - word key_code = 0; - word mod; - - // On ignore shift, alt et control isolés. - if (keysym.sym == SDLK_RSHIFT || keysym.sym == SDLK_LSHIFT || - keysym.sym == SDLK_RCTRL || keysym.sym == SDLK_LCTRL || - keysym.sym == SDLK_RALT || keysym.sym == SDLK_LALT || - keysym.sym == SDLK_RMETA || keysym.sym == SDLK_LMETA || - keysym.sym == SDLK_MODE) // AltGr - return 0; - - // Les touches qui n'ont qu'une valeur unicode (très rares) - // seront codées sur 11 bits, le 12e bit est mis à 1 (0x0800) - if (keysym.sym != 0) - key_code = keysym.sym; - else if (keysym.scancode != 0) - { - key_code = (keysym.scancode & 0x07FF) | 0x0800; - } - - // Normally I should test keysym.mod here, but on windows the implementation - // is buggy: if you release a modifier key, the following keys (when they repeat) - // still name the original modifiers. - mod=Key_modifiers(SDL_GetModState()); - - // SDL_GetModState() seems to get the right up-to-date info. - key_code |= mod; - return key_code; -} - -const char * Key_name(word Key) -{ - typedef struct - { - word keysym; - char *Key_name; - } T_key_label; - T_key_label key_labels[] = - { - { SDLK_BACKSPACE , "Backspace" }, - { SDLK_TAB , "Tab" }, - { SDLK_CLEAR , "Clear" }, - { SDLK_RETURN , "Return" }, - { SDLK_PAUSE , "Pause" }, - { SDLK_ESCAPE , "Esc" }, - { SDLK_DELETE , "Del" }, - { SDLK_KP0 , "KP 0" }, - { SDLK_KP1 , "KP 1" }, - { SDLK_KP2 , "KP 2" }, - { SDLK_KP3 , "KP 3" }, - { SDLK_KP4 , "KP 4" }, - { SDLK_KP5 , "KP 5" }, - { SDLK_KP6 , "KP 6" }, - { SDLK_KP7 , "KP 7" }, - { SDLK_KP8 , "KP 8" }, - { SDLK_KP9 , "KP 9" }, - { SDLK_KP_PERIOD , "KP ." }, - { SDLK_KP_DIVIDE , "KP /" }, - { SDLK_KP_MULTIPLY, "KP *" }, - { SDLK_KP_MINUS , "KP -" }, - { SDLK_KP_PLUS , "KP +" }, - { SDLK_KP_ENTER , "KP Enter" }, - { SDLK_KP_EQUALS , "KP =" }, - { SDLK_UP , "Up" }, - { SDLK_DOWN , "Down" }, - { SDLK_RIGHT , "Right" }, - { SDLK_LEFT , "Left" }, - { SDLK_INSERT , "Ins" }, - { SDLK_HOME , "Home" }, - { SDLK_END , "End" }, - { SDLK_PAGEUP , "PgUp" }, - { SDLK_PAGEDOWN , "PgDn" }, - { SDLK_F1 , "F1" }, - { SDLK_F2 , "F2" }, - { SDLK_F3 , "F3" }, - { SDLK_F4 , "F4" }, - { SDLK_F5 , "F5" }, - { SDLK_F6 , "F6" }, - { SDLK_F7 , "F7" }, - { SDLK_F8 , "F8" }, - { SDLK_F9 , "F9" }, - { SDLK_F10 , "F10" }, - { SDLK_F11 , "F11" }, - { SDLK_F12 , "F12" }, - { SDLK_F13 , "F13" }, - { SDLK_F14 , "F14" }, - { SDLK_F15 , "F15" }, - { SDLK_NUMLOCK , "NumLock" }, - { SDLK_CAPSLOCK , "CapsLck" }, - { SDLK_SCROLLOCK , "ScrlLock" }, - { SDLK_RSHIFT , "RShift" }, - { SDLK_LSHIFT , "LShift" }, - { SDLK_RCTRL , "RCtrl" }, - { SDLK_LCTRL , "LCtrl" }, - { SDLK_RALT , "RAlt" }, - { SDLK_LALT , "LAlt" }, - { SDLK_RMETA , "RMeta" }, - { SDLK_LMETA , "LMeta" }, - { SDLK_LSUPER , "LWin" }, - { SDLK_RSUPER , "RWin" }, - { SDLK_MODE , "AltGr" }, - { SDLK_COMPOSE , "Comp" }, - { SDLK_HELP , "Help" }, - { SDLK_PRINT , "Print" }, - { SDLK_SYSREQ , "SysReq" }, - { SDLK_BREAK , "Break" }, - { SDLK_MENU , "Menu" }, - { SDLK_POWER , "Power" }, - { SDLK_EURO , "Euro" }, - { SDLK_UNDO , "Undo" }, - { KEY_MOUSEMIDDLE, "Mouse3" }, - { KEY_MOUSEWHEELUP, "WheelUp" }, - { KEY_MOUSEWHEELDOWN, "WheelDown" } - }; - - int index; - static char buffer[41]; - buffer[0] = '\0'; - - if (Key == SDLK_UNKNOWN) - return "None"; - - if (Key & MOD_CTRL) - strcat(buffer, "Ctrl+"); - if (Key & MOD_ALT) - strcat(buffer, "Alt+"); - if (Key & MOD_SHIFT) - strcat(buffer, "Shift+"); - if (Key & MOD_META) - strcat(buffer, "\201"); - // Note: Apple's "command" character is not present in the ANSI table, so we - // recycled an ANSI value that doesn't have any displayable character - // associated. - - - Key=Key & ~(MOD_CTRL|MOD_ALT|MOD_SHIFT); - - if (Key>=KEY_JOYBUTTON && Key<=KEY_JOYBUTTON+18) - { -#ifdef __GP2X__ - - char *button_name; - switch(Key-KEY_JOYBUTTON) - { - case GP2X_BUTTON_UP: button_name="[UP]"; break; - case GP2X_BUTTON_DOWN: button_name="[DOWN]"; break; - case GP2X_BUTTON_LEFT: button_name="[LEFT]"; break; - case GP2X_BUTTON_RIGHT: button_name="[RIGHT]"; break; - case GP2X_BUTTON_UPLEFT: button_name="[UP-LEFT]"; break; - case GP2X_BUTTON_UPRIGHT: button_name="[UP-RIGHT]"; break; - case GP2X_BUTTON_DOWNLEFT: button_name="[DOWN-LEFT]"; break; - case GP2X_BUTTON_DOWNRIGHT: button_name="[DOWN-RIGHT]"; break; - case GP2X_BUTTON_CLICK: button_name="[CLICK]"; break; - case GP2X_BUTTON_A: button_name="[A]"; break; - case GP2X_BUTTON_B: button_name="[B]"; break; - case GP2X_BUTTON_X: button_name="[X]"; break; - case GP2X_BUTTON_Y: button_name="[Y]"; break; - case GP2X_BUTTON_L: button_name="[L]"; break; - case GP2X_BUTTON_R: button_name="[R]"; break; - case GP2X_BUTTON_START: button_name="[START]"; break; - case GP2X_BUTTON_SELECT: button_name="[SELECT]"; break; - case GP2X_BUTTON_VOLUP: button_name="[VOL UP]"; break; - case GP2X_BUTTON_VOLDOWN: button_name="[VOL DOWN]"; break; - default: sprintf(buffer+strlen(buffer), "[B%d]", Key);return buffer; - } - strcat(buffer,button_name); -#else - sprintf(buffer+strlen(buffer), "[B%d]", Key-KEY_JOYBUTTON); -#endif - return buffer; - } - - if (Key & 0x800) - { - sprintf(buffer+strlen(buffer), "[%d]", Key & 0x7FF); - return buffer; - } - Key = Key & 0x7FF; - // Touches ASCII - if (Key>=' ' && Key < 127) - { - sprintf(buffer+strlen(buffer), "'%c'", toupper(Key)); - return buffer; - } - // Touches 'World' - if (Key>=SDLK_WORLD_0 && Key <= SDLK_WORLD_95) - { - sprintf(buffer+strlen(buffer), "w%d", Key - SDLK_WORLD_0); - return buffer; - } - - // Touches au libellé connu - for (index=0; index < (long)sizeof(key_labels)/(long)sizeof(T_key_label);index++) - { - if (Key == key_labels[index].keysym) - { - sprintf(buffer+strlen(buffer), "%s", key_labels[index].Key_name); - return buffer; - } - } - // Autres touches inconnues - sprintf(buffer+strlen(buffer), "0x%X", Key & 0x7FF); - return buffer; - -} - -// Obtient le caractère ANSI tapé, à partir d'un keysym. -// (Valeur 32 à 255) -// Renvoie 0 s'il n'y a pas de caractère associé (shift, backspace, etc) -word Keysym_to_ANSI(SDL_keysym keysym) -{ - // This part was removed from the MacOSX port, but I put it back for others - // as on Linux and Windows, it's what allows editing a text line with the keys - // SDLK_LEFT, SDLK_RIGHT, SDLK_HOME, SDLK_END etc. - #if !(defined(__macosx__) || defined(__FreeBSD__)) - if ( keysym.unicode == 0) - { - switch(keysym.sym) - { - case SDLK_DELETE: - case SDLK_LEFT: - case SDLK_RIGHT: - case SDLK_HOME: - case SDLK_END: - case SDLK_BACKSPACE: - case KEY_ESC: - case SDLK_RETURN: - return keysym.sym; - default: - return 0; - } - } - #endif - // - if ( keysym.unicode > 32 && keysym.unicode < 127) - { - return keysym.unicode; // Pas de souci, on est en ASCII standard - } - - // Quelques conversions Unicode-ANSI - switch(keysym.unicode) - { - case 0x8100: - return 'ü'; // ü - case 0x1A20: - return 'é'; // é - case 0x201A: - return 'è'; // è - case 0x9201: - return 'â'; // â - case 0x1E20: - return 'ä'; // ä - case 0x2620: - return 'à'; // à - case 0x2020: - return 'å'; // å - case 0x2120: - return 'ç'; // ç - case 0xC602: - return 'ê'; // ê - case 0x3020: - return 'ë'; // ë - case 0x6001: - return 'è'; // è - case 0x3920: - return 'ï'; // ï - case 0x5201: - return 'î'; // î - case 0x8D00: - return 'ì'; // ì - case 0x1C20: - return 'ô'; // ô - case 0x1D20: - return 'ö'; // ö - case 0x2220: - return 'ò'; // ò - case 0x1320: - return 'û'; // û - case 0x1420: - return 'ù'; // ù - case 0xDC02: - return 'ÿ'; // ÿ - case 0x5301: - return '£'; // £ - case 0xA000: - return 'á'; // á - case 0xA100: - return 'í'; // í - case 0xA200: - return 'ó'; // ó - case 0xA300: - return 'ú'; // ú - case 0xA400: - return 'ñ'; // ñ - case 0xA700: - return 'º'; // º - case 0xC600: - return 'ã'; // ã - } - - // Key entre 127 et 255 - if (keysym.unicode<256) - { -#if defined(__macosx__) || defined(__FreeBSD__) - // fc: Looks like there's a mismatch with delete & backspace - // i don't why SDLK_DELETE was returned instead of SDLK_BACKSPACE - if(keysym.unicode == 127) - { - return(SDLK_BACKSPACE); - } - // We don't make any difference between return & enter in the app context. - if(keysym.unicode == 3) - { - return(SDLK_RETURN); - } -#endif - return keysym.unicode; - } - - // Sinon c'est une touche spéciale, on retourne son scancode - return keysym.sym; -} +/* Grafx2 - The Ultimate 256-color bitmap paint program + + Copyright 2009 Franck Charlet + Copyright 2008 Yves Rizoud + Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) + + Grafx2 is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 + of the License. + + Grafx2 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grafx2; if not, see +*/ +#include +#include +#include "global.h" +#include "keyboard.h" + +// Table de correspondance des scancode de clavier IBM PC AT vers +// les symboles de touches SDL (sym). +// La correspondance est bonne si le clavier est QWERTY US, ou si +// l'utilisateur est sous Windows. +// Dans l'ordre des colonnes: Normal, +Shift, +Control, +Alt +const word Scancode_to_sym[256][4] = +{ +/* 00 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* 01 Esc */ { SDLK_ESCAPE ,SDLK_ESCAPE ,SDLK_ESCAPE ,SDLK_ESCAPE }, +/* 02 1 ! */ { SDLK_1 ,SDLK_1 ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* 03 2 @ */ { SDLK_2 ,SDLK_2 ,SDLK_2 ,SDLK_UNKNOWN }, +/* 04 3 # */ { SDLK_3 ,SDLK_3 ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* 05 4 $ */ { SDLK_4 ,SDLK_4 ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* 06 5 % */ { SDLK_5 ,SDLK_5 ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* 07 6 ^ */ { SDLK_6 ,SDLK_6 ,SDLK_6 ,SDLK_UNKNOWN }, +/* 08 7 & */ { SDLK_7 ,SDLK_7 ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* 09 8 * */ { SDLK_8 ,SDLK_8 ,SDLK_8 ,SDLK_UNKNOWN }, +/* 0A 9 ( */ { SDLK_9 ,SDLK_9 ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* 0B 0 ) */ { SDLK_0 ,SDLK_0 ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* 0C - _ */ { SDLK_MINUS ,SDLK_MINUS ,SDLK_MINUS ,SDLK_UNKNOWN }, +/* 0D = + */ { SDLK_EQUALS ,SDLK_EQUALS ,SDLK_EQUALS ,SDLK_UNKNOWN }, +/* 0E BkSpc */ { SDLK_BACKSPACE ,SDLK_BACKSPACE ,SDLK_BACKSPACE ,SDLK_BACKSPACE }, +/* 0F Tab */ { SDLK_TAB ,SDLK_TAB ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* 10 Q */ { SDLK_q ,SDLK_q ,SDLK_q ,SDLK_q }, +/* 11 W */ { SDLK_w ,SDLK_w ,SDLK_w ,SDLK_w }, +/* 12 E */ { SDLK_e ,SDLK_e ,SDLK_e ,SDLK_e }, +/* 13 R */ { SDLK_r ,SDLK_r ,SDLK_r ,SDLK_r }, +/* 14 T */ { SDLK_t ,SDLK_t ,SDLK_t ,SDLK_t }, +/* 15 Y */ { SDLK_y ,SDLK_y ,SDLK_y ,SDLK_y }, +/* 16 U */ { SDLK_u ,SDLK_u ,SDLK_u ,SDLK_u }, +/* 17 I */ { SDLK_i ,SDLK_i ,SDLK_i ,SDLK_i }, +/* 18 O */ { SDLK_o ,SDLK_o ,SDLK_o ,SDLK_o }, +/* 19 P */ { SDLK_p ,SDLK_p ,SDLK_p ,SDLK_p }, +/* 1A [ */ { SDLK_LEFTBRACKET ,SDLK_LEFTBRACKET ,SDLK_LEFTBRACKET ,SDLK_LEFTBRACKET }, +/* 1B ] */ { SDLK_RIGHTBRACKET,SDLK_RIGHTBRACKET,SDLK_RIGHTBRACKET,SDLK_RIGHTBRACKET}, +/* 1C Retrn */ { SDLK_RETURN ,SDLK_RETURN ,SDLK_RETURN ,SDLK_RETURN }, +/* 1D ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* 1E A */ { SDLK_a ,SDLK_a ,SDLK_a ,SDLK_a }, +/* 1F S */ { SDLK_s ,SDLK_s ,SDLK_s ,SDLK_s }, +/* 20 D */ { SDLK_d ,SDLK_d ,SDLK_d ,SDLK_d }, +/* 21 F */ { SDLK_f ,SDLK_f ,SDLK_f ,SDLK_f }, +/* 22 G */ { SDLK_g ,SDLK_g ,SDLK_g ,SDLK_g }, +/* 23 H */ { SDLK_h ,SDLK_h ,SDLK_h ,SDLK_h }, +/* 24 J */ { SDLK_j ,SDLK_j ,SDLK_j ,SDLK_j }, +/* 25 K */ { SDLK_k ,SDLK_k ,SDLK_k ,SDLK_k }, +/* 26 L */ { SDLK_l ,SDLK_l ,SDLK_l ,SDLK_l }, +/* 27 ; : */ { SDLK_SEMICOLON ,SDLK_SEMICOLON ,SDLK_SEMICOLON ,SDLK_SEMICOLON }, +/* 28 ' */ { SDLK_QUOTE ,SDLK_QUOTE ,SDLK_UNKNOWN ,SDLK_QUOTE }, +/* 29 ` ~ */ { SDLK_BACKQUOTE ,SDLK_BACKQUOTE ,SDLK_UNKNOWN ,SDLK_BACKQUOTE }, +/* 2A ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* 2B \\ */ { SDLK_BACKSLASH ,SDLK_BACKSLASH ,SDLK_BACKSLASH ,SDLK_BACKSLASH }, +/* 2C Z */ { SDLK_z ,SDLK_z ,SDLK_z ,SDLK_z }, +/* 2D X */ { SDLK_x ,SDLK_x ,SDLK_x ,SDLK_x }, +/* 2E C */ { SDLK_c ,SDLK_c ,SDLK_c ,SDLK_c }, +/* 2F V */ { SDLK_v ,SDLK_v ,SDLK_v ,SDLK_v }, +/* 30 B */ { SDLK_b ,SDLK_b ,SDLK_b ,SDLK_b }, +/* 31 N */ { SDLK_n ,SDLK_n ,SDLK_n ,SDLK_n }, +/* 32 M */ { SDLK_m ,SDLK_m ,SDLK_m ,SDLK_m }, +/* 33 , < */ { SDLK_COMMA ,SDLK_COMMA ,SDLK_UNKNOWN ,SDLK_COMMA }, +/* 34 . > */ { SDLK_PERIOD ,SDLK_PERIOD ,SDLK_UNKNOWN ,SDLK_PERIOD }, +/* 35 / ? */ { SDLK_SLASH ,SDLK_SLASH ,SDLK_UNKNOWN ,SDLK_SLASH }, +/* 36 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* 37 Grey* */ { SDLK_KP_MULTIPLY ,SDLK_KP_MULTIPLY ,SDLK_UNKNOWN ,SDLK_KP_MULTIPLY }, +/* 38 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* 39 Space */ { SDLK_SPACE ,SDLK_SPACE ,SDLK_SPACE ,SDLK_SPACE }, +/* 3A ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* 3B F1 */ { SDLK_F1 ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* 3C F2 */ { SDLK_F2 ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* 3D F3 */ { SDLK_F3 ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* 3E F4 */ { SDLK_F4 ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* 3F F5 */ { SDLK_F5 ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* 40 F6 */ { SDLK_F6 ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* 41 F7 */ { SDLK_F7 ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* 42 F8 */ { SDLK_F8 ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* 43 F9 */ { SDLK_F9 ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* 44 F10 */ { SDLK_F10 ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* 45 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* 46 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* 47 Home */ { SDLK_HOME ,SDLK_HOME ,SDLK_UNKNOWN ,SDLK_HOME }, +/* 48 Up */ { SDLK_UP ,SDLK_UP ,SDLK_UNKNOWN ,SDLK_UP }, +/* 49 PgUp */ { SDLK_PAGEUP ,SDLK_PAGEUP ,SDLK_UNKNOWN ,SDLK_PAGEUP }, +/* 4A Grey- */ { SDLK_KP_MINUS ,SDLK_KP_MINUS ,SDLK_UNKNOWN ,SDLK_KP_MINUS }, +/* 4B Left */ { SDLK_LEFT ,SDLK_LEFT ,SDLK_UNKNOWN ,SDLK_LEFT }, +/* 4C Kpad5 */ { SDLK_KP5 ,SDLK_KP5 ,SDLK_UNKNOWN ,SDLK_KP5 }, +/* 4D Right */ { SDLK_RIGHT ,SDLK_RIGHT ,SDLK_UNKNOWN ,SDLK_RIGHT }, +/* 4E Grey+ */ { SDLK_KP_PLUS ,SDLK_KP_PLUS ,SDLK_UNKNOWN ,SDLK_KP_PLUS }, +/* 4F End */ { SDLK_END ,SDLK_END ,SDLK_UNKNOWN ,SDLK_END }, +/* 50 Down */ { SDLK_DOWN ,SDLK_DOWN ,SDLK_UNKNOWN ,SDLK_DOWN }, +/* 51 PgDn */ { SDLK_PAGEDOWN ,SDLK_PAGEDOWN ,SDLK_UNKNOWN ,SDLK_PAGEDOWN }, +/* 52 Ins */ { SDLK_INSERT ,SDLK_INSERT ,SDLK_UNKNOWN ,SDLK_INSERT }, +/* 53 Del */ { SDLK_DELETE ,SDLK_DELETE ,SDLK_UNKNOWN ,SDLK_DELETE }, +/* 54 ??? */ { SDLK_UNKNOWN ,SDLK_F1 ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* 55 ??? */ { SDLK_UNKNOWN ,SDLK_F2 ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* 56 Lft| */ { SDLK_UNKNOWN ,SDLK_F3 ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* 57 ??? */ { SDLK_UNKNOWN ,SDLK_F4 ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* 58 ??? */ { SDLK_UNKNOWN ,SDLK_F5 ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* 59 ??? */ { SDLK_UNKNOWN ,SDLK_F6 ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* 5A ??? */ { SDLK_UNKNOWN ,SDLK_F7 ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* 5B ??? */ { SDLK_UNKNOWN ,SDLK_F8 ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* 5C ??? */ { SDLK_UNKNOWN ,SDLK_F9 ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* 5D ??? */ { SDLK_UNKNOWN ,SDLK_F10 ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* 5E ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F1 ,SDLK_UNKNOWN }, +/* 5F ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F2 ,SDLK_UNKNOWN }, +/* 60 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F3 ,SDLK_UNKNOWN }, +/* 61 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F4 ,SDLK_UNKNOWN }, +/* 62 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F5 ,SDLK_UNKNOWN }, +/* 63 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F6 ,SDLK_UNKNOWN }, +/* 64 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F7 ,SDLK_UNKNOWN }, +/* 65 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F8 ,SDLK_UNKNOWN }, +/* 66 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F9 ,SDLK_UNKNOWN }, +/* 67 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F10 ,SDLK_UNKNOWN }, +/* 68 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F1 }, +/* 69 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F2 }, +/* 6A ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F3 }, +/* 6B ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F4 }, +/* 6C ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F5 }, +/* 6D ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F6 }, +/* 6E ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F7 }, +/* 6F ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F8 }, +/* 70 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F9 }, +/* 71 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F10 }, +/* 72 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* 73 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_LEFT ,SDLK_UNKNOWN }, +/* 74 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_RIGHT ,SDLK_UNKNOWN }, +/* 75 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_END ,SDLK_UNKNOWN }, +/* 76 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_PAGEDOWN ,SDLK_UNKNOWN }, +/* 77 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_HOME ,SDLK_UNKNOWN }, +/* 78 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_1 }, +/* 79 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_2 }, +/* 7A ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_3 }, +/* 7B ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_4 }, +/* 7C ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_5 }, +/* 7D ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_6 }, +/* 7E ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_7 }, +/* 7F ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_8 }, +/* 80 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_9 }, +/* 81 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_0 }, +/* 82 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_MINUS }, +/* 83 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_EQUALS }, +/* 84 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_PAGEUP ,SDLK_UNKNOWN }, +/* 85 F11 */ { SDLK_F11 ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* 86 F12 */ { SDLK_F12 ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* 87 ??? */ { SDLK_UNKNOWN ,SDLK_F11 ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* 88 ??? */ { SDLK_UNKNOWN ,SDLK_F12 ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* 89 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F11 ,SDLK_UNKNOWN }, +/* 8A ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F12 ,SDLK_UNKNOWN }, +/* 8B ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F11 }, +/* 8C ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_F12 }, +/* 8D ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UP ,SDLK_UNKNOWN }, +/* 8E ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_KP_MINUS ,SDLK_UNKNOWN }, +/* 8F ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_KP5 ,SDLK_UNKNOWN }, +/* 90 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_KP_PLUS ,SDLK_UNKNOWN }, +/* 91 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_DOWN ,SDLK_UNKNOWN }, +/* 92 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_INSERT ,SDLK_UNKNOWN }, +/* 93 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_DELETE ,SDLK_UNKNOWN }, +/* 94 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_TAB ,SDLK_UNKNOWN }, +/* 95 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_KP_DIVIDE ,SDLK_UNKNOWN }, +/* 96 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_KP_MULTIPLY ,SDLK_UNKNOWN }, +/* 97 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_HOME }, +/* 98 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UP }, +/* 99 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_PAGEUP }, +/* 9A ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* 9B ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_LEFT }, +/* 9C ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* 9D ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_RIGHT }, +/* 9E ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* 9F ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_END }, +/* A0 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_DOWN }, +/* A1 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_PAGEUP }, +/* A2 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_INSERT }, +/* A3 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_DELETE }, +/* A4 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_KP_DIVIDE }, +/* A5 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_TAB }, +/* A6 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_KP_ENTER }, +/* A7 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* A8 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* A9 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* AA ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* AB ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* AC ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* AD ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* AE ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* AF ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* B0 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* B1 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* B2 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* B3 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* B4 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* B5 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* B6 Win L */ { SDLK_LSUPER ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* B7 Win R */ { SDLK_RSUPER ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* B8 Win M */ { SDLK_MENU ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* B9 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* BA ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* BB ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* BC ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* BD ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* BE ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* BF ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* C0 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* C1 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* C2 ??? */ { SDLK_UNKNOWN ,SDLK_LSUPER ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* C3 ??? */ { SDLK_UNKNOWN ,SDLK_RSUPER ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* C4 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* C5 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* C6 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* C7 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* C8 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* C9 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* CA ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* CB ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* CC ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* CD ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* CE ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_LSUPER ,SDLK_UNKNOWN }, +/* CF ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_RSUPER ,SDLK_UNKNOWN }, +/* D0 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_MENU ,SDLK_UNKNOWN }, +/* D1 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* D2 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* D3 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* D4 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* D5 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* D6 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* D7 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* D8 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* D9 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* DA ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_LSUPER }, +/* DB ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_RSUPER }, +/* DC ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_MENU }, +/* DD ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* DE ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* DF ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* E0 Enter */ { SDLK_KP_ENTER ,SDLK_KP_ENTER ,SDLK_KP_ENTER ,SDLK_UNKNOWN }, +/* E1 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* E2 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* E3 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* E4 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* E5 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* E6 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* E7 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* E8 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* E9 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* EA ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* EB ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* EC ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* ED ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* EE ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* EF ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* F0 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* F1 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* F2 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* F3 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* F4 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* F5 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* F6 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* F7 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* F8 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* F9 ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* FA ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* FB ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* FC ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* FD ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* FE ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +/* FF ??? */ { SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN ,SDLK_UNKNOWN }, +}; + +// Conversion de l'ancien codage des touches: +// 0x00FF le scancode (maintenant code sym sur 0x0FFF) +// 0x0100 shift (maintenant 0x1000) +// 0x0200 control (maintenant 0x2000) +// 0x0400 alt (maintenant 0x4000) +word Key_for_scancode(word scancode) +{ + if (scancode & 0x0400) + return Scancode_to_sym[scancode & 0xFF][3] | + (scancode & 0x0700) << 4; + else if (scancode & 0x0200) + return Scancode_to_sym[scancode & 0xFF][2] | + (scancode & 0x0700) << 4; + else if (scancode & 0x0100) + return Scancode_to_sym[scancode & 0xFF][1] | + (scancode & 0x0700) << 4; + else + return Scancode_to_sym[scancode & 0xFF][0]; +} + +// Convertit des modificateurs de touches SDL en modificateurs GrafX2 +word Key_modifiers(SDLMod mod) +{ + word modifiers=0; + + if (mod & KMOD_CTRL ) + modifiers|=MOD_CTRL; + if (mod & KMOD_SHIFT ) + modifiers|=MOD_SHIFT; + if (mod & (KMOD_ALT|KMOD_MODE)) + modifiers|=MOD_ALT; + if (mod & (KMOD_META)) + modifiers|=MOD_META; + + return modifiers; +} + +word Keysym_to_keycode(SDL_keysym keysym) +{ + word key_code = 0; + word mod; + + // On ignore shift, alt et control isolés. + if (keysym.sym == SDLK_RSHIFT || keysym.sym == SDLK_LSHIFT || + keysym.sym == SDLK_RCTRL || keysym.sym == SDLK_LCTRL || + keysym.sym == SDLK_RALT || keysym.sym == SDLK_LALT || + keysym.sym == SDLK_RMETA || keysym.sym == SDLK_LMETA || + keysym.sym == SDLK_MODE) // AltGr + return 0; + + // Les touches qui n'ont qu'une valeur unicode (très rares) + // seront codées sur 11 bits, le 12e bit est mis à 1 (0x0800) + if (keysym.sym != 0) + key_code = keysym.sym; + else if (keysym.scancode != 0) + { + key_code = (keysym.scancode & 0x07FF) | 0x0800; + } + + // Normally I should test keysym.mod here, but on windows the implementation + // is buggy: if you release a modifier key, the following keys (when they repeat) + // still name the original modifiers. + mod=Key_modifiers(SDL_GetModState()); + + // SDL_GetModState() seems to get the right up-to-date info. + key_code |= mod; + return key_code; +} + +const char * Key_name(word Key) +{ + typedef struct + { + word keysym; + char *Key_name; + } T_key_label; + T_key_label key_labels[] = + { + { SDLK_BACKSPACE , "Backspace" }, + { SDLK_TAB , "Tab" }, + { SDLK_CLEAR , "Clear" }, + { SDLK_RETURN , "Return" }, + { SDLK_PAUSE , "Pause" }, + { SDLK_ESCAPE , "Esc" }, + { SDLK_DELETE , "Del" }, + { SDLK_KP0 , "KP 0" }, + { SDLK_KP1 , "KP 1" }, + { SDLK_KP2 , "KP 2" }, + { SDLK_KP3 , "KP 3" }, + { SDLK_KP4 , "KP 4" }, + { SDLK_KP5 , "KP 5" }, + { SDLK_KP6 , "KP 6" }, + { SDLK_KP7 , "KP 7" }, + { SDLK_KP8 , "KP 8" }, + { SDLK_KP9 , "KP 9" }, + { SDLK_KP_PERIOD , "KP ." }, + { SDLK_KP_DIVIDE , "KP /" }, + { SDLK_KP_MULTIPLY, "KP *" }, + { SDLK_KP_MINUS , "KP -" }, + { SDLK_KP_PLUS , "KP +" }, + { SDLK_KP_ENTER , "KP Enter" }, + { SDLK_KP_EQUALS , "KP =" }, + { SDLK_UP , "Up" }, + { SDLK_DOWN , "Down" }, + { SDLK_RIGHT , "Right" }, + { SDLK_LEFT , "Left" }, + { SDLK_INSERT , "Ins" }, + { SDLK_HOME , "Home" }, + { SDLK_END , "End" }, + { SDLK_PAGEUP , "PgUp" }, + { SDLK_PAGEDOWN , "PgDn" }, + { SDLK_F1 , "F1" }, + { SDLK_F2 , "F2" }, + { SDLK_F3 , "F3" }, + { SDLK_F4 , "F4" }, + { SDLK_F5 , "F5" }, + { SDLK_F6 , "F6" }, + { SDLK_F7 , "F7" }, + { SDLK_F8 , "F8" }, + { SDLK_F9 , "F9" }, + { SDLK_F10 , "F10" }, + { SDLK_F11 , "F11" }, + { SDLK_F12 , "F12" }, + { SDLK_F13 , "F13" }, + { SDLK_F14 , "F14" }, + { SDLK_F15 , "F15" }, + { SDLK_NUMLOCK , "NumLock" }, + { SDLK_CAPSLOCK , "CapsLck" }, + { SDLK_SCROLLOCK , "ScrlLock" }, + { SDLK_RSHIFT , "RShift" }, + { SDLK_LSHIFT , "LShift" }, + { SDLK_RCTRL , "RCtrl" }, + { SDLK_LCTRL , "LCtrl" }, + { SDLK_RALT , "RAlt" }, + { SDLK_LALT , "LAlt" }, + { SDLK_RMETA , "RMeta" }, + { SDLK_LMETA , "LMeta" }, + { SDLK_LSUPER , "LWin" }, + { SDLK_RSUPER , "RWin" }, + { SDLK_MODE , "AltGr" }, + { SDLK_COMPOSE , "Comp" }, + { SDLK_HELP , "Help" }, + { SDLK_PRINT , "Print" }, + { SDLK_SYSREQ , "SysReq" }, + { SDLK_BREAK , "Break" }, + { SDLK_MENU , "Menu" }, + { SDLK_POWER , "Power" }, + { SDLK_EURO , "Euro" }, + { SDLK_UNDO , "Undo" }, + { KEY_MOUSEMIDDLE, "Mouse3" }, + { KEY_MOUSEWHEELUP, "WheelUp" }, + { KEY_MOUSEWHEELDOWN, "WheelDown" } + }; + + int index; + static char buffer[41]; + buffer[0] = '\0'; + + if (Key == SDLK_UNKNOWN) + return "None"; + + if (Key & MOD_CTRL) + strcat(buffer, "Ctrl+"); + if (Key & MOD_ALT) + strcat(buffer, "Alt+"); + if (Key & MOD_SHIFT) + strcat(buffer, "Shift+"); + if (Key & MOD_META) + strcat(buffer, "\201"); + // Note: Apple's "command" character is not present in the ANSI table, so we + // recycled an ANSI value that doesn't have any displayable character + // associated. + + + Key=Key & ~(MOD_CTRL|MOD_ALT|MOD_SHIFT); + + if (Key>=KEY_JOYBUTTON && Key<=KEY_JOYBUTTON+18) + { +#ifdef __GP2X__ + + char *button_name; + switch(Key-KEY_JOYBUTTON) + { + case GP2X_BUTTON_UP: button_name="[UP]"; break; + case GP2X_BUTTON_DOWN: button_name="[DOWN]"; break; + case GP2X_BUTTON_LEFT: button_name="[LEFT]"; break; + case GP2X_BUTTON_RIGHT: button_name="[RIGHT]"; break; + case GP2X_BUTTON_UPLEFT: button_name="[UP-LEFT]"; break; + case GP2X_BUTTON_UPRIGHT: button_name="[UP-RIGHT]"; break; + case GP2X_BUTTON_DOWNLEFT: button_name="[DOWN-LEFT]"; break; + case GP2X_BUTTON_DOWNRIGHT: button_name="[DOWN-RIGHT]"; break; + case GP2X_BUTTON_CLICK: button_name="[CLICK]"; break; + case GP2X_BUTTON_A: button_name="[A]"; break; + case GP2X_BUTTON_B: button_name="[B]"; break; + case GP2X_BUTTON_X: button_name="[X]"; break; + case GP2X_BUTTON_Y: button_name="[Y]"; break; + case GP2X_BUTTON_L: button_name="[L]"; break; + case GP2X_BUTTON_R: button_name="[R]"; break; + case GP2X_BUTTON_START: button_name="[START]"; break; + case GP2X_BUTTON_SELECT: button_name="[SELECT]"; break; + case GP2X_BUTTON_VOLUP: button_name="[VOL UP]"; break; + case GP2X_BUTTON_VOLDOWN: button_name="[VOL DOWN]"; break; + default: sprintf(buffer+strlen(buffer), "[B%d]", Key);return buffer; + } + strcat(buffer,button_name); +#else + sprintf(buffer+strlen(buffer), "[B%d]", Key-KEY_JOYBUTTON); +#endif + return buffer; + } + + if (Key & 0x800) + { + sprintf(buffer+strlen(buffer), "[%d]", Key & 0x7FF); + return buffer; + } + Key = Key & 0x7FF; + // Touches ASCII + if (Key>=' ' && Key < 127) + { + sprintf(buffer+strlen(buffer), "'%c'", toupper(Key)); + return buffer; + } + // Touches 'World' + if (Key>=SDLK_WORLD_0 && Key <= SDLK_WORLD_95) + { + sprintf(buffer+strlen(buffer), "w%d", Key - SDLK_WORLD_0); + return buffer; + } + + // Touches au libellé connu + for (index=0; index < (long)sizeof(key_labels)/(long)sizeof(T_key_label);index++) + { + if (Key == key_labels[index].keysym) + { + sprintf(buffer+strlen(buffer), "%s", key_labels[index].Key_name); + return buffer; + } + } + // Autres touches inconnues + sprintf(buffer+strlen(buffer), "0x%X", Key & 0x7FF); + return buffer; + +} + +// Obtient le caractère ANSI tapé, à partir d'un keysym. +// (Valeur 32 à 255) +// Renvoie 0 s'il n'y a pas de caractère associé (shift, backspace, etc) +word Keysym_to_ANSI(SDL_keysym keysym) +{ + // This part was removed from the MacOSX port, but I put it back for others + // as on Linux and Windows, it's what allows editing a text line with the keys + // SDLK_LEFT, SDLK_RIGHT, SDLK_HOME, SDLK_END etc. + #if !(defined(__macosx__) || defined(__FreeBSD__)) + if ( keysym.unicode == 0) + { + switch(keysym.sym) + { + case SDLK_DELETE: + case SDLK_LEFT: + case SDLK_RIGHT: + case SDLK_HOME: + case SDLK_END: + case SDLK_BACKSPACE: + case KEY_ESC: + case SDLK_RETURN: + return keysym.sym; + default: + return 0; + } + } + #endif + // + if ( keysym.unicode > 32 && keysym.unicode < 127) + { + return keysym.unicode; // Pas de souci, on est en ASCII standard + } + + // Quelques conversions Unicode-ANSI + switch(keysym.unicode) + { + case 0x8100: + return 'ü'; // ü + case 0x1A20: + return 'é'; // é + case 0x201A: + return 'è'; // è + case 0x9201: + return 'â'; // â + case 0x1E20: + return 'ä'; // ä + case 0x2620: + return 'à'; // à + case 0x2020: + return 'å'; // å + case 0x2120: + return 'ç'; // ç + case 0xC602: + return 'ê'; // ê + case 0x3020: + return 'ë'; // ë + case 0x6001: + return 'è'; // è + case 0x3920: + return 'ï'; // ï + case 0x5201: + return 'î'; // î + case 0x8D00: + return 'ì'; // ì + case 0x1C20: + return 'ô'; // ô + case 0x1D20: + return 'ö'; // ö + case 0x2220: + return 'ò'; // ò + case 0x1320: + return 'û'; // û + case 0x1420: + return 'ù'; // ù + case 0xDC02: + return 'ÿ'; // ÿ + case 0x5301: + return '£'; // £ + case 0xA000: + return 'á'; // á + case 0xA100: + return 'í'; // í + case 0xA200: + return 'ó'; // ó + case 0xA300: + return 'ú'; // ú + case 0xA400: + return 'ñ'; // ñ + case 0xA700: + return 'º'; // º + case 0xC600: + return 'ã'; // ã + } + + // Key entre 127 et 255 + if (keysym.unicode<256) + { +#if defined(__macosx__) || defined(__FreeBSD__) + // fc: Looks like there's a mismatch with delete & backspace + // i don't why SDLK_DELETE was returned instead of SDLK_BACKSPACE + if(keysym.unicode == 127) + { + return(SDLK_BACKSPACE); + } + // We don't make any difference between return & enter in the app context. + if(keysym.unicode == 3) + { + return(SDLK_RETURN); + } +#endif + return keysym.unicode; + } + + // Sinon c'est une touche spéciale, on retourne son scancode + return keysym.sym; +} diff --git a/keyboard.h b/keyboard.h index d3776d8b..eca0352e 100644 --- a/keyboard.h +++ b/keyboard.h @@ -1,75 +1,75 @@ -/* Grafx2 - The Ultimate 256-color bitmap paint program - - Copyright 2008 Yves Rizoud - Copyright 2007 Adrien Destugues - Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) - - Grafx2 is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; version 2 - of the License. - - Grafx2 is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Grafx2; if not, see -*/ - -////////////////////////////////////////////////////////////////////////////// -///@file keyboard.h -/// Functions to convert bewteen the SDL key formats and the keycode we use -/// in grafx2. -/// The keycode we're using is generalized to handle mouse and joystick shortcuts -/// as well. The format can be broken down as: -/// - 0x0000 + a number between 0 and SDLK_LAST (about 324) : the SDL "sym" key number. -/// - 0x0000 + SDLK_LAST+1: Mouse middle button. -/// - 0x0000 + SDLK_LAST+2: Mouse wheel up. -/// - 0x0000 + SDLK_LAST+3: Mouse wheel down. -/// - 0x0000 + SDLK_LAST+4+B : Joystick button number "B", starting at B=0. -/// - 0x0800 + a number between 0 and 0x7FF: The scancode key number, for keys which have no "sym", such as keys from multimedia keyboards, and "fn" and "Thinkpad" key for a laptop. -/// Add 0x1000 for the Shift modifier MOD_SHIFT -/// Add 0x2000 for the Control modifier ::MOD_CONTROL -/// Add 0x4000 for the Alt modifier ::MOD_ALT -/// Add 0x8000 for the "Meta" modifier ::MOD_META (On MacOS X it's the CMD key) -////////////////////////////////////////////////////////////////////////////// - -/*! - Convert an SDL keysym to an ANSI/ASCII character. - This is used to type text and numeric values in input boxes. - @param keysym SDL symbol to convert -*/ -word Keysym_to_ANSI(SDL_keysym keysym); - -/*! - Convert an SDL keysym to an internal keycode number. - This is needed because SDL tends to split the information across the unicode sym, the regular sym, and the raw keycode. - We also need to differenciate 1 (keypad) and 1 (regular keyboard), and some other things. - See the notice at the beginning of keyboard.h for the format of a keycode. - @param keysym SDL symbol to convert -*/ -word Keysym_to_keycode(SDL_keysym keysym); - -/*! - Helper function to convert between SDL system and the old coding for PC keycodes. - This is only used to convert configuration files from the DOS version of - Grafx2, where keyboard codes are in in the IBM PC AT form. - @param scancode Scancode to convert -*/ -word Key_for_scancode(word scancode); - -/*! - Returns key name in a string. Used to display them in the helpscreens and in the keymapper window. - @param Key keycode of the key to translate, including modifiers -*/ -const char * Key_name(word Key); - -/*! - Gets the modifiers in our format from the SDL_Mod information. - Returns a combination of ::MOD_SHIFT, ::MOD_ALT, ::MOD_CONTROL - @param mod SDL modifiers state -*/ -word Key_modifiers(SDLMod mod); - +/* Grafx2 - The Ultimate 256-color bitmap paint program + + Copyright 2008 Yves Rizoud + Copyright 2007 Adrien Destugues + Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) + + Grafx2 is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 + of the License. + + Grafx2 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grafx2; if not, see +*/ + +////////////////////////////////////////////////////////////////////////////// +///@file keyboard.h +/// Functions to convert bewteen the SDL key formats and the keycode we use +/// in grafx2. +/// The keycode we're using is generalized to handle mouse and joystick shortcuts +/// as well. The format can be broken down as: +/// - 0x0000 + a number between 0 and SDLK_LAST (about 324) : the SDL "sym" key number. +/// - 0x0000 + SDLK_LAST+1: Mouse middle button. +/// - 0x0000 + SDLK_LAST+2: Mouse wheel up. +/// - 0x0000 + SDLK_LAST+3: Mouse wheel down. +/// - 0x0000 + SDLK_LAST+4+B : Joystick button number "B", starting at B=0. +/// - 0x0800 + a number between 0 and 0x7FF: The scancode key number, for keys which have no "sym", such as keys from multimedia keyboards, and "fn" and "Thinkpad" key for a laptop. +/// Add 0x1000 for the Shift modifier MOD_SHIFT +/// Add 0x2000 for the Control modifier ::MOD_CONTROL +/// Add 0x4000 for the Alt modifier ::MOD_ALT +/// Add 0x8000 for the "Meta" modifier ::MOD_META (On MacOS X it's the CMD key) +////////////////////////////////////////////////////////////////////////////// + +/*! + Convert an SDL keysym to an ANSI/ASCII character. + This is used to type text and numeric values in input boxes. + @param keysym SDL symbol to convert +*/ +word Keysym_to_ANSI(SDL_keysym keysym); + +/*! + Convert an SDL keysym to an internal keycode number. + This is needed because SDL tends to split the information across the unicode sym, the regular sym, and the raw keycode. + We also need to differenciate 1 (keypad) and 1 (regular keyboard), and some other things. + See the notice at the beginning of keyboard.h for the format of a keycode. + @param keysym SDL symbol to convert +*/ +word Keysym_to_keycode(SDL_keysym keysym); + +/*! + Helper function to convert between SDL system and the old coding for PC keycodes. + This is only used to convert configuration files from the DOS version of + Grafx2, where keyboard codes are in in the IBM PC AT form. + @param scancode Scancode to convert +*/ +word Key_for_scancode(word scancode); + +/*! + Returns key name in a string. Used to display them in the helpscreens and in the keymapper window. + @param Key keycode of the key to translate, including modifiers +*/ +const char * Key_name(word Key); + +/*! + Gets the modifiers in our format from the SDL_Mod information. + Returns a combination of ::MOD_SHIFT, ::MOD_ALT, ::MOD_CONTROL + @param mod SDL modifiers state +*/ +word Key_modifiers(SDLMod mod); + diff --git a/loadsave.c b/loadsave.c index b475ca6f..de983439 100644 --- a/loadsave.c +++ b/loadsave.c @@ -1,5 +1,6 @@ /* Grafx2 - The Ultimate 256-color bitmap paint program + Copyright 2009 Petter Lindquist Copyright 2008 Yves Rizoud Copyright 2008 Franck Charlet Copyright 2007 Adrien Destugues @@ -43,6 +44,7 @@ #include "sdlscreen.h" #include "struct.h" #include "windows.h" +#include "engine.h" // -- PKM ------------------------------------------------------------------- void Test_PKM(void); @@ -104,6 +106,16 @@ void Test_PC1(void); void Load_PC1(void); void Save_PC1(void); +// -- NEO ------------------------------------------------------------------- +void Test_NEO(void); +void Load_NEO(void); +void Save_NEO(void); + +// -- C64 ------------------------------------------------------------------- +void Test_C64(void); +void Load_C64(void); +void Save_C64(void); + // -- PNG ------------------------------------------------------------------- #ifndef __no_pnglib__ void Test_PNG(void); @@ -111,6 +123,8 @@ void Load_PNG(void); void Save_PNG(void); #endif +void Init_preview(short width,short height,long size,int format,enum PIXEL_RATIO ratio); + T_Format File_formats[NB_KNOWN_FORMATS] = { {"pkm", Test_PKM, Load_PKM, Save_PKM, 1, 1}, {"lbm", Test_LBM, Load_LBM, Save_LBM, 1, 0}, @@ -122,8 +136,10 @@ T_Format File_formats[NB_KNOWN_FORMATS] = { {"pi1", Test_PI1, Load_PI1, Save_PI1, 1, 0}, {"pc1", Test_PC1, Load_PC1, Save_PC1, 1, 0}, {"cel", Test_CEL, Load_CEL, Save_CEL, 1, 0}, + {"neo", Test_NEO, Load_NEO, Save_NEO, 1, 0}, {"kcf", Test_KCF, Load_KCF, Save_KCF, 0, 0}, {"pal", Test_PAL, Load_PAL, Save_PAL, 0, 0}, + {"c64", Test_C64, Load_C64, Save_C64, 1, 1}, #ifndef __no_pnglib__ {"png", Test_PNG, Load_PNG, Save_PNG, 1, 1} #endif @@ -163,10 +179,35 @@ byte HBPm1; // header.BitPlanes-1 void Pixel_load_in_preview(word x_pos,word y_pos,byte color) { if (((x_pos % Preview_factor_X)==0) && ((y_pos % Preview_factor_Y)==0)) - if ((x_pos 127 alors il faut répéter 256-'temp_byte' fois la couleur de l'octet suivant // Si temp_byte <= 127 alors il faut afficher directement les 'temp_byte' octets suivants if (temp_byte>127) { - if(Read_byte(LBM_file, &color)!=1) - { - File_error=2; - break; - } + if(Read_byte(LBM_file, &color)!=1) + { + File_error=2; + break; + } b256=(short)(256-temp_byte); for (counter=0; counter<=b256; counter++) if (x_pos=line_size || Read_byte(LBM_file, &(LBM_buffer[x_pos++]))!=1) - File_error=2; + File_error=2; } if (!File_error) Draw_ILBM_line(y_pos,real_line_size); @@ -1952,17 +2003,17 @@ void Load_LBM(void) for (x_pos=0; ((x_pos127) { if(Read_byte(LBM_file, &color)!=1) - { - File_error=2; - break; - } + { + File_error=2; + break; + } b256=256-temp_byte; for (counter=0; counter<=b256; counter++) Pixel_load_function(x_pos++,y_pos,color); @@ -1972,10 +2023,10 @@ void Load_LBM(void) { byte byte_read=0; if(Read_byte(LBM_file, &byte_read)!=1) - { - File_error=2; - break; - } + { + File_error=2; + break; + } Pixel_load_function(x_pos++,y_pos,byte_read); } } @@ -2392,7 +2443,7 @@ void Load_BMP(void) if (!File_error) { - Init_preview(header.Width,header.Height,file_size,FORMAT_BMP); + Init_preview(header.Width,header.Height,file_size,FORMAT_BMP,PIXEL_SIMPLE); if (File_error==0) { if (Read_bytes(file,local_palette,nb_colors<<2)) @@ -2455,7 +2506,7 @@ void Load_BMP(void) /*Init_lecture();*/ if(Read_byte(file, &a)!=1 || Read_byte(file, &b)!=1) - File_error=2; + File_error=2; while (!File_error) { if (a) // Encoded mode @@ -2471,8 +2522,8 @@ void Load_BMP(void) case 1 : // End of bitmap break; case 2 : // Delta - if(Read_byte(file, &a)!=1 || Read_byte(file, &b)!=1) - File_error=2; + if(Read_byte(file, &a)!=1 || Read_byte(file, &b)!=1) + File_error=2; x_pos+=a; y_pos-=b; break; @@ -2480,7 +2531,7 @@ void Load_BMP(void) while (b) { if(Read_byte(file, &a)!=1) - File_error=2; + File_error=2; //Read_one_byte(file, &c); Pixel_load_function(x_pos++,y_pos,a); //if (--c) @@ -2495,9 +2546,9 @@ void Load_BMP(void) if (a==0 && b==1) break; if(Read_byte(file, &a) !=1 || Read_byte(file, &b)!=1) - { - File_error=2; - } + { + File_error=2; + } } /*Close_lecture();*/ break; @@ -2508,7 +2559,7 @@ void Load_BMP(void) /*Init_lecture();*/ if(Read_byte(file, &a)!=1 || Read_byte(file, &b) != 1) - File_error =2; + File_error =2; while ( (!File_error) && ((a)||(b!=1)) ) { if (a) // Encoded mode (A fois les 1/2 pixels de B) @@ -2531,7 +2582,7 @@ void Load_BMP(void) break; case 2 : // Delta if(Read_byte(file, &a)!=1 || Read_byte(file, &b)!=1) - File_error=2; + File_error=2; x_pos+=a; y_pos-=b; break; @@ -2589,7 +2640,7 @@ void Load_BMP(void) Main_image_width=header.Width; Main_image_height=header.Height; - Init_preview(header.Width,header.Height,file_size,FORMAT_BMP | FORMAT_24B); + Init_preview_24b(header.Width,header.Height,file_size,FORMAT_BMP); if (File_error==0) { switch (header.Compression) @@ -2877,10 +2928,10 @@ void Test_GIF(void) if (GIF_remainder_byte==0) // Lire l'octet nous donnant la taille du bloc de Raster Data suivant if(Read_byte(GIF_file, &GIF_remainder_byte)!=1) - File_error=2; + File_error=2; - if(Read_byte(GIF_file,&GIF_last_byte)!=1) - File_error = 2; + if(Read_byte(GIF_file,&GIF_last_byte)!=1) + File_error = 2; GIF_remainder_byte--; GIF_remainder_bits=8; } @@ -3116,7 +3167,7 @@ void Load_GIF(void) Main_image_width=IDB.Image_width; Main_image_height=IDB.Image_height; - Init_preview(IDB.Image_width,IDB.Image_height,file_size,FORMAT_GIF); + Init_preview(IDB.Image_width,IDB.Image_height,file_size,FORMAT_GIF,PIXEL_SIMPLE); // Palette locale dispo = (IDB.Indicator and $80) // Image entrelacée = (IDB.Indicator and $40) @@ -3788,7 +3839,7 @@ void Load_PCX(void) if (PCX_header.Plane!=3) { - Init_preview(Main_image_width,Main_image_height,file_size,FORMAT_PCX); + Init_preview(Main_image_width,Main_image_height,file_size,FORMAT_PCX,PIXEL_SIMPLE); if (File_error==0) { // On prépare la palette à accueillir les valeurs du fichier PCX @@ -3968,7 +4019,7 @@ void Load_PCX(void) { // Image 24 bits!!! - Init_preview(Main_image_width,Main_image_height,file_size,FORMAT_PCX | FORMAT_24B); + Init_preview_24b(Main_image_width,Main_image_height,file_size,FORMAT_PCX); if (File_error==0) { @@ -4285,7 +4336,7 @@ void Load_CEL(void) Main_image_height=header1.Height; Original_screen_X=Main_image_width; Original_screen_Y=Main_image_height; - Init_preview(Main_image_width,Main_image_height,file_size,FORMAT_CEL); + Init_preview(Main_image_width,Main_image_height,file_size,FORMAT_CEL,PIXEL_SIMPLE); if (File_error==0) { // Chargement de l'image @@ -4315,7 +4366,7 @@ void Load_CEL(void) Main_image_height=header2.Height+header2.Y_offset; Original_screen_X=Main_image_width; Original_screen_Y=Main_image_height; - Init_preview(Main_image_width,Main_image_height,file_size,FORMAT_CEL); + Init_preview(Main_image_width,Main_image_height,file_size,FORMAT_CEL,PIXEL_SIMPLE); if (File_error==0) { // Chargement de l'image @@ -4808,7 +4859,7 @@ void Load_SCx(void) if ((Read_bytes(file,&SCx_header,sizeof(T_SCx_Header)))) { - Init_preview(SCx_header.Width,SCx_header.Height,file_size,FORMAT_SCx); + Init_preview(SCx_header.Width,SCx_header.Height,file_size,FORMAT_SCx,PIXEL_SIMPLE); if (File_error==0) { if (!SCx_header.Planes) @@ -5106,7 +5157,7 @@ void Load_PI1(void) if (Read_bytes(file,buffer,32034)) { // Initialisation de la preview - Init_preview(320,200,File_length_file(file),FORMAT_PI1); + Init_preview(320,200,File_length_file(file),FORMAT_PI1,PIXEL_SIMPLE); if (File_error==0) { // Initialisation de la palette @@ -5440,7 +5491,7 @@ void Load_PC1(void) if (Read_bytes(file,buffercomp,size)) { // Initialisation de la preview - Init_preview(320,200,File_length_file(file),FORMAT_PC1); + Init_preview(320,200,File_length_file(file),FORMAT_PC1,PIXEL_SIMPLE); if (File_error==0) { // Initialisation de la palette @@ -5477,8 +5528,8 @@ void Load_PC1(void) else { File_error=1; - if (bufferdecomp) free(bufferdecomp); - if (buffercomp) free(buffercomp); + free(bufferdecomp); + free(buffercomp); } fclose(file); } @@ -5650,6 +5701,723 @@ void Load_TGA(char * fname,T_Bitmap24B * dest,int * width,int * height) fclose(fichier); } +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +//////////////////////////////////// NEO //////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// + +void Test_NEO(void) +{ + FILE *file; // Fichier du fichier + char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier + int size; // Taille du fichier + word resolution; // Résolution de l'image + + + Get_full_filename(filename,0); + + File_error=1; + + // Ouverture du fichier + if ((file=fopen(filename, "rb"))) + { + // Vérification de la taille + size=File_length_file(file); + if ((size==32128)) + { + // Flag word : toujours 0 + if (Read_word_le(file,&resolution)) + { + if (resolution == 0) + File_error = 0; + } + + // Lecture et vérification de la résolution + if (Read_word_le(file,&resolution)) + { + if (resolution==0 || resolution==1 || resolution==2) + File_error |= 0; + } + } + // Fermeture du fichier + fclose(file); + } + +} + +void Load_NEO(void) +{ + char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier + FILE *file; + word x_pos,y_pos; + byte * buffer; + byte * ptr; + byte pixels[320]; + + Get_full_filename(filename,0); + + File_error=0; + if ((file=fopen(filename, "rb"))) + { + // allocation d'un buffer mémoire + buffer=(byte *)malloc(32128); + if (buffer!=NULL) + { + // Lecture du fichier dans le buffer + if (Read_bytes(file,buffer,32128)) + { + // Initialisation de la preview + Init_preview(320,200,File_length_file(file),FORMAT_NEO,PIXEL_SIMPLE); + if (File_error==0) + { + // Initialisation de la palette + if (Config.Clear_palette) + memset(Main_palette,0,sizeof(T_Palette)); + // on saute la résolution et le flag, chacun 2 bits + PI1_decode_palette(buffer+4,(byte *)Main_palette); + Set_palette(Main_palette); + Remap_fileselector(); + + Main_image_width=320; + Main_image_height=200; + + // Chargement/décompression de l'image + ptr=buffer+128; + for (y_pos=0;y_pos<200;y_pos++) + { + for (x_pos=0;x_pos<(320>>4);x_pos++) + { + PI1_8b_to_16p(ptr,pixels+(x_pos<<4)); + ptr+=8; + } + for (x_pos=0;x_pos<320;x_pos++) + Pixel_load_function(x_pos,y_pos,pixels[x_pos]); + } + } + } + else + File_error=1; + free(buffer); + } + else + File_error=1; + fclose(file); + } + else + File_error=1; +} + +void Save_NEO(void) +{ + char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier + FILE *file; + short x_pos,y_pos; + byte * buffer; + byte * ptr; + byte pixels[320]; + + Get_full_filename(filename,0); + + File_error=0; + // Ouverture du fichier + if ((file=fopen(filename,"wb"))) + { + // allocation d'un buffer mémoire + buffer=(byte *)malloc(32128); + // Codage de la résolution + buffer[0]=0x00; + buffer[1]=0x00; + buffer[2]=0x00; + buffer[3]=0x00; + // Codage de la palette + PI1_code_palette((byte *)Main_palette,buffer+4); + // Codage de l'image + ptr=buffer+128; + for (y_pos=0;y_pos<200;y_pos++) + { + // Codage de la ligne + memset(pixels,0,320); + if (y_pos>4);x_pos++) + { + PI1_16p_to_8b(pixels+(x_pos<<4),ptr); + ptr+=8; + } + } + + if (Write_bytes(file,buffer,32128)) + { + fclose(file); + } + else // Error d'écriture (disque plein ou protégé) + { + fclose(file); + remove(filename); + File_error=1; + } + // Libération du buffer mémoire + free(buffer); + } + else + { + fclose(file); + remove(filename); + File_error=1; + } +} + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +//////////////////////////////////// C64 //////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +void Test_C64(void) +{ + FILE* file; + char filename[MAX_PATH_CHARACTERS]; + long file_size; + + Get_full_filename(filename,0); + + file = fopen(filename,"rb"); + + if (file) + { + file_size = File_length_file(file); + switch (file_size) + { + case 1000: // screen or color + case 1002: // (screen or color) + loadaddr + case 8000: // raw bitmap + case 8002: // raw bitmap with loadaddr + case 9000: // bitmap + screen + case 9002: // bitmap + screen + loadaddr + case 10001: // multicolor + case 10003: // multicolor + loadaddr + File_error = 0; + break; + default: // then we don't know for now. + File_error = 1; + } + fclose (file); + } + else + { + File_error = 1; + } +} + +void Load_C64_hires(byte *bitmap, byte *colors) +{ + int cx,cy,x,y,c[4],pixel,color; + + for(cy=0; cy<25; cy++) + { + for(cx=0; cx<40; cx++) + { + c[1]=colors[cy*40+cx]&15; + c[0]=colors[cy*40+cx]>>4; + for(y=0; y<8; y++) + { + pixel=bitmap[cy*320+cx*8+y]; + for(x=0; x<8; x++) + { + color=c[pixel&(1<<(7-x))?1:0]; + Pixel_load_function(cx*8+x,cy*8+y,color); + } + } + } + } +} + +void Load_C64_multi(byte *bitmap, byte *colors, byte *nybble, byte background) +{ + int cx,cy,x,y,c[4],pixel,color; + c[0]=background; + for(cy=0; cy<25; cy++) + { + for(cx=0; cx<40; cx++) + { + c[1]=colors[cy*40+cx]>>4; + c[2]=colors[cy*40+cx]&15; + c[3]=nybble[cy*40+cx]; + + for(y=0; y<8; y++) + { + pixel=bitmap[cy*320+cx*8+y]; + for(x=0; x<4; x++) + { + color=c[(pixel&3)]; + pixel>>=2; + Pixel_load_function(cx*4+(3-x),cy*8+y,color); + } + } + } + } +} + +void Load_C64(void) +{ + FILE* file; + char filename[MAX_PATH_CHARACTERS]; + long file_size; + int i; + byte background,hasLoadAddr=0; + int loadFormat=0; + enum c64_format {F_hires,F_multi,F_bitmap,F_screen,F_color}; + const char *c64_format_names[]={"hires","multicolor","bitmap","screen","color"}; + + // Palette from http://www.pepto.de/projects/colorvic/ + byte pal[48]={ + 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, + 0x68, 0x37, 0x2B, + 0x70, 0xA4, 0xB2, + 0x6F, 0x3D, 0x86, + 0x58, 0x8D, 0x43, + 0x35, 0x28, 0x79, + 0xB8, 0xC7, 0x6F, + 0x6F, 0x4F, 0x25, + 0x43, 0x39, 0x00, + 0x9A, 0x67, 0x59, + 0x44, 0x44, 0x44, + 0x6C, 0x6C, 0x6C, + 0x9A, 0xD2, 0x84, + 0x6C, 0x5E, 0xB5, + 0x95, 0x95, 0x95}; + + byte bitmap[8000],colors[1000],nybble[1000]; + word width=320, height=200; + + Get_full_filename(filename,0); + file = fopen(filename,"rb"); + + if (file) + { + File_error=0; + file_size = File_length_file(file); + + switch (file_size) + { + case 1000: // screen or color + hasLoadAddr=0; + loadFormat=F_screen; + break; + + case 1002: // (screen or color) + loadaddr + hasLoadAddr=1; + loadFormat=F_screen; + break; + + case 8000: // raw bitmap + hasLoadAddr=0; + loadFormat=F_bitmap; + + case 8002: // raw bitmap with loadaddr + hasLoadAddr=1; + loadFormat=F_bitmap; + break; + + case 9000: // bitmap + screen + hasLoadAddr=0; + loadFormat=F_hires; + break; + + case 9002: // bitmap + screen + loadaddr + hasLoadAddr=1; + loadFormat=F_hires; + break; + + case 10001: // multicolor + hasLoadAddr=0; + loadFormat=F_multi; + break; + + case 10003: // multicolor + loadaddr + hasLoadAddr=1; + loadFormat=F_multi; + break; + + default: // then we don't know what it is. + File_error = 1; + + } + + memcpy(Main_palette,pal,48); // this set the software palette for grafx2 + Set_palette(Main_palette); // this set the hardware palette for SDL + Remap_fileselector(); // Always call it if you change the palette + + if (file_size>9002) + width=160; + + if (hasLoadAddr) + { + // get load address + Read_byte(file,&background); + Read_byte(file,&background); + sprintf(filename,"load at $%02x00",background); + } + else + { + sprintf(filename,"no addr"); + } + + if(file_size>9002) + { + Ratio_of_loaded_image = PIXEL_WIDE; + } + sprintf(Main_comment,"C64 %s, %s", + c64_format_names[loadFormat],filename); + Init_preview(width, height, file_size, FORMAT_C64, Ratio_of_loaded_image); // Do this as soon as you can + + Main_image_width = width ; + Main_image_height = height; + + Read_bytes(file,bitmap,8000); + + if (file_size>8002) + Read_bytes(file,colors,1000); + else + { + for(i=0;i<1000;i++) + { + colors[i]=1; + } + } + + if(width==160) + { + Read_bytes(file,nybble,1000); + Read_byte(file,&background); + Load_C64_multi(bitmap,colors,nybble,background); + } + else + { + Load_C64_hires(bitmap,colors); + } + + File_error = 0; + fclose(file); + } + else + File_error = 1; +} + +int Save_C64_window(byte *saveWhat, byte *loadAddr) +{ + int button; + unsigned int i; + T_Dropdown_button *what, *addr; + char * what_label[] = { + "All", + "Bitmap", + "Screen", + "Color" + }; + char * address_label[] = { + "None", + "$2000", + "$4000", + "$6000", + "$8000", + "$A000", + "$C000", + "$E000" + }; + + Open_window(200,120,"c64 settings"); + Window_set_normal_button(110,100,80,15,"Save",1,1,SDLK_RETURN); + Window_set_normal_button(10,100,80,15,"Cancel",1,1,SDLK_ESCAPE); + + Print_in_window(13,18,"Data:",MC_Dark,MC_Light); + what=Window_set_dropdown_button(10,28,90,15,70,what_label[*saveWhat],1, 0, 1, LEFT_SIDE); + Window_dropdown_clear_items(what); + for (i=0; i2) + { + Warning_message("More than 2 colors in 8x8 pixels"); + // TODO here we should hilite the offending block + printf("\nerror at %dx%d (%d colors)\n",cx*8,cy*8,numcolors); + return 1; + } + for(i=0;i<16;i++) + { + if(cusage[i]) + { + c2=i; + break; + } + } + c1=c2; + for(i=c2+1;i<16;i++) + { + if(cusage[i]) + { + c1=i; + } + } + colors[cx+cy*40]=(c2<<4)|c1; + + for(y=0; y<8; y++) + { + bits=0; + for(x=0; x<8; x++) + { + pixel=Read_pixel_function(x+cx*8,y+cy*8); + if(pixel>15) + { + Warning_message("Color above 15 used"); + // TODO hilite offending block here too? + // or make it smarter with color allocation? + // However, the palette is fixed to the 16 first colors + return 1; + } + bits=bits<<1; + if (pixel==c1) bits|=1; + } + bitmap[pos++]=bits; + //Write_byte(file,bits&255); + } + } + } + + file = fopen(filename,"wb"); + + if(!file) + { + Warning_message("File open failed"); + File_error = 1; + return 1; + } + + if (loadAddr) + { + Write_byte(file,0); + Write_byte(file,loadAddr); + } + if (saveWhat==0 || saveWhat==1) + Write_bytes(file,bitmap,8000); + if (saveWhat==0 || saveWhat==2) + Write_bytes(file,colors,1000); + + fclose(file); + return 0; +} + +int Save_C64_multi(char *filename, byte saveWhat, byte loadAddr) +{ + /* + BITS COLOR INFORMATION COMES FROM + 00 Background color #0 (screen color) + 01 Upper 4 bits of screen memory + 10 Lower 4 bits of screen memory + 11 Color nybble (nybble = 1/2 byte = 4 bits) + */ + + int cx,cy,x,y,c[4]={0,0,0,0},color,lut[16],bits,pixel,pos=0; + byte bitmap[8000],screen[1000],nybble[1000]; + word numcolors,count; + dword cusage[256]; + byte i,background=0; + FILE *file; + + numcolors=Count_used_colors(cusage); + + count=0; + for(x=0;x<16;x++) + { + //printf("color %d, pixels %d\n",x,cusage[x]); + if(cusage[x]>count) + { + count=cusage[x]; + background=x; + } + } + + for(cy=0; cy<25; cy++) + { + //printf("\ny:%2d ",cy); + for(cx=0; cx<40; cx++) + { + numcolors=Count_used_colors_area(cusage,cx*4,cy*8,4,8); + if(numcolors>4) + { + Warning_message("More than 4 colors in 4x8"); + // TODO hilite offending block + return 1; + } + color=1; + c[0]=background; + for(i=0; i<16; i++) + { + lut[i]=0; + if(cusage[i]) + { + if(i!=background) + { + lut[i]=color; + c[color]=i; + color++; + } + else + { + lut[i]=0; + } + } + } + // add to screen and nybble + screen[cx+cy*40]=c[1]<<4|c[2]; + nybble[cx+cy*40]=c[3]; + //printf("%x%x%x ",c[1],c[2],c[3]); + for(y=0;y<8;y++) + { + bits=0; + for(x=0;x<4;x++) + { + pixel=Read_pixel_function(cx*4+x,cy*8+y); + if(pixel>15) + { + Warning_message("Color above 15 used"); + // TODO hilite as in hires, you should stay to + // the fixed 16 color palette + return 1; + } + bits=bits<<2; + bits|=lut[pixel]; + + } + //Write_byte(file,bits&255); + bitmap[pos++]=bits; + } + } + } + + file = fopen(filename,"wb"); + + if(!file) + { + Warning_message("File open failed"); + File_error = 1; + return 1; + } + + if (loadAddr) + { + Write_byte(file,0); + Write_byte(file,loadAddr); + } + + if (saveWhat==0 || saveWhat==1) + Write_bytes(file,bitmap,8000); + + if (saveWhat==0 || saveWhat==2) + Write_bytes(file,screen,1000); + + if (saveWhat==0 || saveWhat==3) + Write_bytes(file,nybble,1000); + + if (saveWhat==0) + Write_byte(file,background); + + fclose(file); + //printf("\nbg:%d\n",background); + return 0; +} + +void Save_C64(void) +{ + char filename[MAX_PATH_CHARACTERS]; + static byte saveWhat=0, loadAddr=0; + dword numcolors,cusage[256]; + numcolors=Count_used_colors(cusage); + + Get_full_filename(filename,0); + + if (numcolors>16) + { + Warning_message("Error: Max 16 colors"); + File_error = 1; + return; + } + if (((Main_image_width!=320) && (Main_image_width!=160)) || Main_image_height!=200) + { + Warning_message("must be 320x200 or 160x200"); + File_error = 1; + return; + } + + if(!Save_C64_window(&saveWhat,&loadAddr)) + { + File_error = 1; + return; + } + //printf("saveWhat=%d, loadAddr=%d\n",saveWhat,loadAddr); + + if (Main_image_width==320) + File_error = Save_C64_hires(filename,saveWhat,loadAddr); + else + File_error = Save_C64_multi(filename,saveWhat,loadAddr); +} + ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// //////////////////////////////////// PNG //////////////////////////////////// @@ -5689,7 +6457,7 @@ void Load_PNG(void) FILE *file; // Fichier du fichier char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier byte png_header[8]; - dword image_size; + byte row_pointers_allocated; png_structp png_ptr; png_infop info_ptr; @@ -5700,29 +6468,45 @@ void Load_PNG(void) if ((file=fopen(filename, "rb"))) { + // Load header (8 first bytes) if (Read_bytes(file,png_header,8)) { + // Do we recognize a png file signature ? if ( !png_sig_cmp(png_header, 0, 8)) { + // Prepare internal PNG loader png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr) { + // Prepare internal PNG loader info_ptr = png_create_info_struct(png_ptr); if (info_ptr) { png_byte color_type; png_byte bit_depth; + // Setup a return point. If a pnglib loading error occurs + // in this if(), the else will be executed. if (!setjmp(png_jmpbuf(png_ptr))) { png_init_io(png_ptr, file); + // Inform pnglib we already loaded the header. png_set_sig_bytes(png_ptr, 8); + // Load file information png_read_info(png_ptr, info_ptr); color_type = info_ptr->color_type; bit_depth = info_ptr->bit_depth; - if (bit_depth <= 8 && (color_type == PNG_COLOR_TYPE_PALETTE || PNG_COLOR_TYPE_GRAY)) + // If it's any supported file + // (Note: As of writing this, this test covers every possible + // image format of libpng) + if (color_type == PNG_COLOR_TYPE_PALETTE + || color_type == PNG_COLOR_TYPE_GRAY + || color_type == PNG_COLOR_TYPE_GRAY_ALPHA + || color_type == PNG_COLOR_TYPE_RGB + || color_type == PNG_COLOR_TYPE_RGB_ALPHA + ) { int num_text; png_text *text_ptr; @@ -5731,8 +6515,8 @@ void Load_PNG(void) png_uint_32 res_x; png_uint_32 res_y; - // Commentaire (tEXt) - Main_comment[0]='\0'; // On efface le commentaire + // Comment (tEXt) + Main_comment[0]='\0'; // Clear the previous comment if ((num_text=png_get_text(png_ptr, info_ptr, &text_ptr, NULL))) { while (num_text--) @@ -5743,7 +6527,7 @@ void Load_PNG(void) size = Min(text_ptr[num_text].text_length, COMMENT_SIZE); strncpy(Main_comment, text_ptr[num_text].text, size); Main_comment[size]='\0'; - break; // Pas besoin de vérifier les suivants + break; // Skip all others tEXt chunks } } } @@ -5764,35 +6548,62 @@ void Load_PNG(void) } } } - Init_preview(info_ptr->width,info_ptr->height,File_length_file(file),FORMAT_PNG); + if (color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_RGB_ALPHA) + Init_preview_24b(info_ptr->width,info_ptr->height,File_length_file(file),FORMAT_PNG); + else + Init_preview(info_ptr->width,info_ptr->height,File_length_file(file),FORMAT_PNG,Ratio_of_loaded_image); if (File_error==0) { int x,y; png_colorp palette; int num_palette; - - if (color_type == PNG_COLOR_TYPE_GRAY) + + // 16-bit images + if (bit_depth == 16) { + // Reduce to 8-bit + png_set_strip_16(png_ptr); + } + else if (bit_depth < 8) + { + // Inform libpng we want one byte per pixel, + // even though the file was less than 8bpp + png_set_packing(png_ptr); + } + + // Images with alpha channel + if (color_type & PNG_COLOR_MASK_ALPHA) + { + // Tell libpng to ignore it + png_set_strip_alpha(png_ptr); + } + + // Greyscale images : + if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + // Map low bpp greyscales to full 8bit (0-255 range) if (bit_depth < 8) png_set_gray_1_2_4_to_8(png_ptr); - // palette de niveaux de gris - for (x=0;xwidth; Main_image_height=info_ptr->height; - image_size=(dword)(Main_image_width*Main_image_height); - + png_set_interlace_handling(png_ptr); png_read_update_info(png_ptr, info_ptr); + + // Allocate row pointers + Row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * Main_image_height); + row_pointers_allocated = 0; + /* read file */ if (!setjmp(png_jmpbuf(png_ptr))) { - Row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * Main_image_height); - for (y=0; yrowbytes); - png_read_image(png_ptr, Row_pointers); - - for (y=0; yrowbytes); + row_pointers_allocated = 1; + + png_read_image(png_ptr, Row_pointers); + + for (y=0; yrowbytes); + row_pointers_allocated = 1; + + png_read_image(png_ptr, Row_pointers); + + for (y=0; y -*/ -////////////////////////////////////////////////////////////////////////////// -///@file loadsave.h -/// Saving and loading different picture formats. -/// Also handles showing the preview in fileselectors. -////////////////////////////////////////////////////////////////////////////// - -void Pixel_load_in_current_screen(word x_pos,word y_pos,byte color); -void Pixel_load_in_preview (word x_pos,word y_pos,byte color); -void Pixel_load_in_brush (word x_pos,word y_pos,byte color); - -void Get_full_filename(char * filename, byte is_colorix_format); - -/// -/// High-level picture loading function. -/// Handles loading an image or a brush, or previewing only. -/// @param image true if the fileselector is the one for loading images (not brush) -void Load_image(byte image); -/// -/// High-level picture saving function. -/// @param image true if the image should be saved (instead of the brush) -void Save_image(byte image); - -/// Data for an image file format. -typedef struct { - char *Extension; ///< Three-letter file extension - Func_action Test; ///< Function which tests if the file is of this format - Func_action Load; ///< Function which loads an image of this format - Func_action Save; ///< Function which saves an image of this format - byte Backup_done; ///< Boolean, true if this format saves all the image, and considers it backed up. Set false for formats which only save the palette. - byte Comment; ///< This file format allows a text comment -} T_Format; - -/// Array of the known file formats -extern T_Format File_formats[NB_KNOWN_FORMATS]; - -/// -/// Function which attempts to save backups of the images (main and spare), -/// called in case of SIGSEGV. -void Image_emergency_backup(void); +/* Grafx2 - The Ultimate 256-color bitmap paint program + + Copyright 2007 Adrien Destugues + Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) + + Grafx2 is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 + of the License. + + Grafx2 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grafx2; if not, see +*/ +////////////////////////////////////////////////////////////////////////////// +///@file loadsave.h +/// Saving and loading different picture formats. +/// Also handles showing the preview in fileselectors. +////////////////////////////////////////////////////////////////////////////// + +void Pixel_load_in_current_screen(word x_pos,word y_pos,byte color); +void Pixel_load_in_preview (word x_pos,word y_pos,byte color); +void Pixel_load_in_brush (word x_pos,word y_pos,byte color); + +void Get_full_filename(char * filename, byte is_colorix_format); + +/// +/// High-level picture loading function. +/// Handles loading an image or a brush, or previewing only. +/// @param image true if the fileselector is the one for loading images (not brush) +void Load_image(byte image); +/// +/// High-level picture saving function. +/// @param image true if the image should be saved (instead of the brush) +void Save_image(byte image); + +/// Data for an image file format. +typedef struct { + char *Extension; ///< Three-letter file extension + Func_action Test; ///< Function which tests if the file is of this format + Func_action Load; ///< Function which loads an image of this format + Func_action Save; ///< Function which saves an image of this format + byte Backup_done; ///< Boolean, true if this format saves all the image, and considers it backed up. Set false for formats which only save the palette. + byte Comment; ///< This file format allows a text comment +} T_Format; + +/// Array of the known file formats +extern T_Format File_formats[NB_KNOWN_FORMATS]; + +/// +/// Function which attempts to save backups of the images (main and spare), +/// called in case of SIGSEGV. +void Image_emergency_backup(void); + +/// Pixel ratio of last loaded image: one of :PIXEL_SIMPLE, :PIXEL_WIDE or :PIXEL_TALL +extern enum PIXEL_RATIO Ratio_of_loaded_image; diff --git a/main.c b/main.c index f3512d29..7d7ef312 100644 --- a/main.c +++ b/main.c @@ -76,7 +76,7 @@ #endif // filename for the current GUI skin file. -static char Gui_skin_file[MAX_PATH_CHARACTERS]= "skins" PATH_SEPARATOR "base.gif"; +static char Gui_skin_file[MAX_PATH_CHARACTERS]; //--- Affichage de la syntaxe, et de la liste des modes vidéos disponibles --- void Display_syntax(void) @@ -344,6 +344,7 @@ int Init_program(int argc,char * argv[]) strcpy(Main_file_directory,Main_current_directory); strcpy(Main_filename,"NO_NAME.GIF"); Main_fileformat=DEFAULT_FILEFORMAT; + // On initialise les données sur le nom de fichier de l'image de brouillon: strcpy(Spare_current_directory,Main_current_directory); strcpy(Spare_file_directory,Main_file_directory); @@ -355,7 +356,7 @@ int Init_program(int argc,char * argv[]) Brush_fileformat =Main_fileformat; // On initialise ce qu'il faut pour que les fileselects ne plantent pas: - Filelist=NULL; // Au début, il n'y a pas de fichiers dans la liste + Main_fileselector_position=0; // Au début, le fileselect est en haut de la liste des fichiers Main_fileselector_offset=0; // Au début, le fileselect est en haut de la liste des fichiers Main_format=0; @@ -398,6 +399,7 @@ int Init_program(int argc,char * argv[]) Spare_magnifier_width=0; Spare_magnifier_offset_X=0; Spare_magnifier_offset_Y=0; + Keyboard_click_allowed = 0; // SDL if(SDL_Init(SDL_INIT_TIMER|SDL_INIT_VIDEO|SDL_INIT_JOYSTICK) < 0) @@ -406,6 +408,7 @@ int Init_program(int argc,char * argv[]) printf("Couldn't initialize SDL.\n"); return(0); } + Joystick = SDL_JoystickOpen(0); SDL_EnableKeyRepeat(250, 32); SDL_EnableUNICODE(SDL_ENABLE); @@ -439,18 +442,18 @@ int Init_program(int argc,char * argv[]) Set_all_video_modes(); Pixel_ratio=PIXEL_SIMPLE; // On initialise les données sur l'état du programme: - // Donnée sur la sortie du programme: + // Donnée sur la sortie du programme: Quit_is_required=0; Quitting=0; - // Données sur l'état du menu: + // Données sur l'état du menu: Pixel_in_menu=Pixel_in_toolbar; Menu_is_visible=1; - // Données sur les couleurs et la palette: + // Données sur les couleurs et la palette: First_color_in_palette=0; - // Données sur le curseur: + // Données sur le curseur: Cursor_shape=CURSOR_SHAPE_TARGET; Cursor_hidden=0; - // Données sur le pinceau: + // Données sur le pinceau: Paintbrush_X=0; Paintbrush_Y=0; Paintbrush_shape=PAINTBRUSH_SHAPE_ROUND; @@ -510,10 +513,14 @@ int Init_program(int argc,char * argv[]) // Initialisation des opérations Init_operations(); + // Initialize the brush container + Init_brush_container(); + Windows_open=0; // Charger la configuration des touches Set_config_defaults(); + switch(Load_CFG(1)) { case ERROR_CFG_MISSING: @@ -533,30 +540,41 @@ int Init_program(int argc,char * argv[]) Analyze_command_line(argc,argv); - // Charger les sprites et la palette - Load_graphics(Gui_skin_file); - + // Load sprites, palette etc. + strcpy(Gui_skin_file,Config.Skin_file); + Gfx = Load_graphics(Gui_skin_file); + if (Gfx == NULL) + { + Gfx = Load_graphics("skin_modern.png"); + if (Gfx == NULL) + { + printf("%s", Gui_loading_error_message); + Error(ERROR_GUI_MISSING); + } + } // Infos sur les trames (Sieve) Sieve_mode=0; Copy_preset_sieve(0); // Transfert des valeurs du .INI qui ne changent pas dans des variables // plus accessibles: - Default_palette[MC_Black]=Fav_menu_colors[0]=Config.Fav_menu_colors[0]; - Default_palette[MC_Dark] =Fav_menu_colors[1]=Config.Fav_menu_colors[1]; - Default_palette[MC_Light]=Fav_menu_colors[2]=Config.Fav_menu_colors[2]; - Default_palette[MC_White]=Fav_menu_colors[3]=Config.Fav_menu_colors[3]; - Compute_optimal_menu_colors(Default_palette); + Gfx->Default_palette[MC_Black]=Fav_menu_colors[0]=Config.Fav_menu_colors[0]; + Gfx->Default_palette[MC_Dark] =Fav_menu_colors[1]=Config.Fav_menu_colors[1]; + Gfx->Default_palette[MC_Light]=Fav_menu_colors[2]=Config.Fav_menu_colors[2]; + Gfx->Default_palette[MC_White]=Fav_menu_colors[3]=Config.Fav_menu_colors[3]; + Compute_optimal_menu_colors(Gfx->Default_palette); Fore_color=MC_White; Back_color=MC_Black; - // Prise en compte de la fonte - if (Config.Font) - Menu_font=GFX_fun_font; - else - Menu_font=GFX_system_font; + // Font + if (!(Menu_font=Load_font(Config.Font_file))) + if (!(Menu_font=Load_font("font_Classic.png"))) + { + printf("Unable to open the default font file: %s\n", "font_Classic.png"); + Error(ERROR_GUI_MISSING); + } - memcpy(Main_palette,Default_palette,sizeof(T_Palette)); + memcpy(Main_palette, Gfx->Default_palette, sizeof(T_Palette)); // Allocation de mémoire pour la brosse if (!(Brush =(byte *)malloc( 1* 1))) Error(ERROR_MEMORY); @@ -571,7 +589,7 @@ int Init_program(int argc,char * argv[]) starting_videomode=Current_resolution; Horizontal_line_buffer=NULL; Screen_width=Screen_height=Current_resolution=0; - + Init_mode_video( Video_mode[starting_videomode].Width, Video_mode[starting_videomode].Height, @@ -672,17 +690,24 @@ void Program_shutdown(void) #endif // On libère le buffer de gestion de lignes - free(Horizontal_line_buffer); + if(Horizontal_line_buffer) free(Horizontal_line_buffer); // On libère le pinceau spécial - free(Paintbrush_sprite); + if (Paintbrush_sprite) free(Paintbrush_sprite); // On libère les différents écrans virtuels et brosse: - free(Brush); + if(Brush) free(Brush); Set_number_of_backups(0); - free(Spare_screen); - free(Main_screen); + if(Spare_screen) free(Spare_screen); + if(Main_screen) free(Main_screen); + // Free the skin (Gui graphics) data + if (Gfx) + { + free(Gfx); + Gfx=NULL; + } + // On prend bien soin de passer dans le répertoire initial: if (chdir(Initial_directory)!=-1) { @@ -711,9 +736,9 @@ int main(int argc,char * argv[]) int phoenix2_found=0; char phoenix_filename1[MAX_PATH_CHARACTERS]; char phoenix_filename2[MAX_PATH_CHARACTERS]; - if(!Init_program(argc,argv)) { + Program_shutdown(); return 0; } @@ -733,6 +758,7 @@ int main(int argc,char * argv[]) strcpy(Main_file_directory,Config_directory); strcpy(Main_filename,"phoenix2.img"); chdir(Main_file_directory); + Button_Reload(); Main_image_is_modified=1; Warning_message("Spare page recovered"); @@ -756,7 +782,6 @@ int main(int argc,char * argv[]) { if (Config.Opening_message && (!File_in_command_line)) Button_Message_initial(); - free(GFX_logo_grafx2); // Pas encore utilisé dans le About if (File_in_command_line) { diff --git a/misc.c b/misc.c index 17d77754..fc6d00f9 100644 --- a/misc.c +++ b/misc.c @@ -35,693 +35,737 @@ #include "palette.h" #include "input.h" +///Count used palette indexes in the whole picture +///Return the total number of different colors +///Fill in "usage" with the count for each color word Count_used_colors(dword* usage) { - int nb_pixels=0; - Uint8* current_pixel=Main_screen; - Uint8 color; - word nb_colors=0; - int i; + int nb_pixels = 0; + Uint8* current_pixel = Main_screen; + Uint8 color; + word nb_colors = 0; + int i; - for (i=0;i<256;i++) usage[i]=0; + for (i = 0; i < 256; i++) usage[i]=0; - //Calcul du nombre de pixels dans l'image - nb_pixels=Main_image_height*Main_image_width; + // Compute total number of pixels in the picture + nb_pixels = Main_image_height * Main_image_width; - // On parcourt l'écran courant pour compter les utilisations des couleurs - for(i=0;i0;dx--) - { - // Pour chaque pixel - for(cx=width;cx>0;cx--) - { - *buffer = conversion_table[*buffer]; - buffer++; - } - buffer += buffer_width-width; - } + // Pour chaque ligne + for(dx=height;dx>0;dx--) + { + // Pour chaque pixel + for(cx=width;cx>0;cx--) + { + *buffer = conversion_table[*buffer]; + buffer++; + } + buffer += buffer_width-width; + } } void Copy_image_to_brush(short start_x,short start_y,short Brush_width,short Brush_height,word image_width) { - byte* src=start_y*image_width+start_x+Main_screen; //Adr départ image (ESI) - byte* dest=Brush; //Adr dest brosse (EDI) - int dx; + byte* src=start_y*image_width+start_x+Main_screen; //Adr départ image (ESI) + byte* dest=Brush; //Adr dest brosse (EDI) + int dx; - for (dx=Brush_height;dx!=0;dx--) - //Pour chaque ligne - { + for (dx=Brush_height;dx!=0;dx--) + //Pour chaque ligne + { - // On fait une copie de la ligne - memcpy(dest,src,Brush_width); + // On fait une copie de la ligne + memcpy(dest,src,Brush_width); - // On passe à la ligne suivante - src+=image_width; - dest+=Brush_width; - } + // On passe à la ligne suivante + src+=image_width; + dest+=Brush_width; + } } byte Read_pixel_from_feedback_screen (word x,word y) { - return *(FX_feedback_screen+y*Main_image_width+x); + return *(FX_feedback_screen+y*Main_image_width+x); } dword Round_div(dword numerator,dword divisor) { - return numerator/divisor; + return numerator/divisor; } byte Effect_sieve(word x,word y) { - return Sieve[x % Sieve_width][y % Sieve_height]; + return Sieve[x % Sieve_width][y % Sieve_height]; } void Replace_colors_within_limits(byte * replace_table) { - int line; - int counter; - byte* Adresse; + int line; + int counter; + byte* Adresse; - byte old; + byte old; - // Pour chaque ligne : - for(line = Limit_top;line <= Limit_bottom; line++) - { - // Pour chaque pixel sur la ligne : - for (counter = Limit_left;counter <= Limit_right;counter ++) - { - Adresse = Main_screen+line*Main_image_width+counter; - old=*Adresse; - *Adresse = replace_table[old]; - } - } + // Pour chaque ligne : + for(line = Limit_top;line <= Limit_bottom; line++) + { + // Pour chaque pixel sur la ligne : + for (counter = Limit_left;counter <= Limit_right;counter ++) + { + Adresse = Main_screen+line*Main_image_width+counter; + old=*Adresse; + *Adresse = replace_table[old]; + } + } } byte Read_pixel_from_backup_screen (word x,word y) { - return *(Screen_backup + x + Main_image_width * y); + return *(Screen_backup + x + Main_image_width * y); } void Palette_256_to_64(T_Palette palette) { - int i; - for(i=0;i<256;i++) - { - palette[i].R = palette[i].R >> 2; - palette[i].G = palette[i].G >> 2; - palette[i].B = palette[i].B >> 2; - } + int i; + for(i=0;i<256;i++) + { + palette[i].R = palette[i].R >> 2; + palette[i].G = palette[i].G >> 2; + palette[i].B = palette[i].B >> 2; + } } void Palette_64_to_256(T_Palette palette) { - int i; - for(i=0;i<256;i++) - { - palette[i].R = (palette[i].R << 2)|(palette[i].R >> 4); - palette[i].G = (palette[i].G << 2)|(palette[i].G >> 4); - palette[i].B = (palette[i].B << 2)|(palette[i].B >> 4); - } + int i; + for(i=0;i<256;i++) + { + palette[i].R = (palette[i].R << 2)|(palette[i].R >> 4); + palette[i].G = (palette[i].G << 2)|(palette[i].G >> 4); + palette[i].B = (palette[i].B << 2)|(palette[i].B >> 4); + } } byte Effect_interpolated_colorize (word x,word y,byte color) { - // factor_a = 256*(100-Colorize_opacity)/100 - // factor_b = 256*( Colorize_opacity)/100 - // - // (Couleur_dessous*factor_a+color*facteur_B)/256 - // + // factor_a = 256*(100-Colorize_opacity)/100 + // factor_b = 256*( Colorize_opacity)/100 + // + // (Couleur_dessous*factor_a+color*facteur_B)/256 + // - // On place dans ESI 3*Couleur_dessous ( = position de cette couleur dans la - // palette des teintes) et dans EDI, 3*color. - byte blue_under=Main_palette[*(FX_feedback_screen + y * Main_image_width + x)].B; - byte blue=Main_palette[color].B; - byte green_under=Main_palette[*(FX_feedback_screen + y * Main_image_width + x)].G; - byte green=Main_palette[color].G; - byte red_under=Main_palette[*(FX_feedback_screen + y * Main_image_width + x)].R; - byte red=Main_palette[color].R; + // On place dans ESI 3*Couleur_dessous ( = position de cette couleur dans la + // palette des teintes) et dans EDI, 3*color. + byte color_under = Read_pixel_from_feedback_screen(x,y); + byte blue_under=Main_palette[color_under].B; + byte blue=Main_palette[color].B; + byte green_under=Main_palette[color_under].G; + byte green=Main_palette[color].G; + byte red_under=Main_palette[color_under].R; + byte red=Main_palette[color].R; - // On récupère les 3 composantes RVB + // On récupère les 3 composantes RVB - // blue - blue = (Factors_inv_table[blue] - + Factors_table[blue_under]) / 256; - green = (Factors_inv_table[green] - + Factors_table[green_under]) / 256; - red = (Factors_inv_table[red] - + Factors_table[red_under]) / 256; - return Best_color(red,green,blue); + // blue + blue = (Factors_inv_table[blue] + + Factors_table[blue_under]) / 256; + green = (Factors_inv_table[green] + + Factors_table[green_under]) / 256; + red = (Factors_inv_table[red] + + Factors_table[red_under]) / 256; + return Best_color(red,green,blue); } byte Effect_additive_colorize (word x,word y,byte color) { - byte blue_under=Main_palette[*(FX_feedback_screen + y * Main_image_width + x)].B; - byte green_under=Main_palette[*(FX_feedback_screen + y * Main_image_width + x)].G; - byte red_under=Main_palette[*(FX_feedback_screen + y * Main_image_width + x)].R; - byte blue=Main_palette[color].B; - byte green=Main_palette[color].G; - byte red=Main_palette[color].R; + byte color_under = Read_pixel_from_feedback_screen(x,y); + byte blue_under=Main_palette[color_under].B; + byte green_under=Main_palette[color_under].G; + byte red_under=Main_palette[color_under].R; + byte blue=Main_palette[color].B; + byte green=Main_palette[color].G; + byte red=Main_palette[color].R; - return Best_color( - red>red_under?red:red_under, - green>green_under?green:green_under, - blue>blue_under?blue:blue_under); + return Best_color( + red>red_under?red:red_under, + green>green_under?green:green_under, + blue>blue_under?blue:blue_under); } byte Effect_substractive_colorize(word x,word y,byte color) { - byte blue_under=Main_palette[*(FX_feedback_screen + y * Main_image_width + x)].B; - byte green_under=Main_palette[*(FX_feedback_screen + y * Main_image_width + x)].G; - byte red_under=Main_palette[*(FX_feedback_screen + y * Main_image_width + x)].R; - byte blue=Main_palette[color].B; - byte green=Main_palette[color].G; - byte red=Main_palette[color].R; + byte color_under = Read_pixel_from_feedback_screen(x,y); + byte blue_under=Main_palette[color_under].B; + byte green_under=Main_palette[color_under].G; + byte red_under=Main_palette[color_under].R; + byte blue=Main_palette[color].B; + byte green=Main_palette[color].G; + byte red=Main_palette[color].R; - return Best_color( - redTimer_start) Timer_state=1; + if((SDL_GetTicks()/55)-Timer_delay>Timer_start) Timer_state=1; } void Flip_Y_lowlevel(byte *src, short width, short height) { - // ESI pointe sur la partie haute de la brosse - // EDI sur la partie basse - byte* ESI = src ; - byte* EDI = src + (height - 1) *width; - byte tmp; - word cx; + // ESI pointe sur la partie haute de la brosse + // EDI sur la partie basse + byte* ESI = src ; + byte* EDI = src + (height - 1) *width; + byte tmp; + word cx; - while(ESI < EDI) - { - // Il faut inverser les lignes pointées par ESI et - // EDI ("Brush_width" octets en tout) + while(ESI < EDI) + { + // Il faut inverser les lignes pointées par ESI et + // EDI ("Brush_width" octets en tout) - for(cx = width;cx>0;cx--) - { - tmp = *ESI; - *ESI = *EDI; - *EDI = tmp; - ESI++; - EDI++; - } + for(cx = width;cx>0;cx--) + { + tmp = *ESI; + *ESI = *EDI; + *EDI = tmp; + ESI++; + EDI++; + } - // On change de ligne : - // ESI pointe déjà sur le début de la ligne suivante - // EDI pointe sur la fin de la ligne en cours, il - // doit pointer sur le début de la précédente... - EDI -= 2 * width; // On recule de 2 lignes - } + // On change de ligne : + // ESI pointe déjà sur le début de la ligne suivante + // EDI pointe sur la fin de la ligne en cours, il + // doit pointer sur le début de la précédente... + EDI -= 2 * width; // On recule de 2 lignes + } } void Flip_X_lowlevel(byte *src, short width, short height) { - // ESI pointe sur la partie gauche et EDI sur la partie - // droite - byte* ESI = src; - byte* EDI = src + width - 1; + // ESI pointe sur la partie gauche et EDI sur la partie + // droite + byte* ESI = src; + byte* EDI = src + width - 1; - byte* line_start; - byte* line_end; - byte tmp; - word cx; + byte* line_start; + byte* line_end; + byte tmp; + word cx; - while(ESI0;cx--) - { - tmp=*ESI; - *ESI=*EDI; - *EDI=tmp; - EDI+=width; - ESI+=width; - } + // On échange par colonnes + for(cx=height;cx>0;cx--) + { + tmp=*ESI; + *ESI=*EDI; + *EDI=tmp; + EDI+=width; + ESI+=width; + } - // On change de colonne - // ESI > colonne suivante - // EDI > colonne précédente - ESI = line_start + 1; - EDI = line_end - 1; - } + // On change de colonne + // ESI > colonne suivante + // EDI > colonne précédente + ESI = line_start + 1; + EDI = line_end - 1; + } } // Rotate a pixel buffer 180º on itself. void Rotate_180_deg_lowlevel(byte *src, short width, short height) { - // ESI pointe sur la partie supérieure de la brosse - // EDI pointe sur la partie basse - byte* ESI = src; - byte* EDI = src + height*width - 1; - // EDI pointe sur le dernier pixel de la derniere ligne - byte tmp; - word cx; + // ESI pointe sur la partie supérieure de la brosse + // EDI pointe sur la partie basse + byte* ESI = src; + byte* EDI = src + height*width - 1; + // EDI pointe sur le dernier pixel de la derniere ligne + byte tmp; + word cx; - // In case of odd height, the algorithm in this function would - // miss the middle line, so we do it this way: - if (height & 1) - { - Flip_X_lowlevel(src, width, height); - Flip_Y_lowlevel(src, width, height); - return; - } + // In case of odd height, the algorithm in this function would + // miss the middle line, so we do it this way: + if (height & 1) + { + Flip_X_lowlevel(src, width, height); + Flip_Y_lowlevel(src, width, height); + return; + } - while(ESI < EDI) - { - // On échange les deux lignes pointées par EDI et - // ESI (Brush_width octets) - // En même temps, on échange les pixels, donc EDI - // pointe sur la FIN de sa ligne + while(ESI < EDI) + { + // On échange les deux lignes pointées par EDI et + // ESI (Brush_width octets) + // En même temps, on échange les pixels, donc EDI + // pointe sur la FIN de sa ligne - for(cx=width;cx>0;cx--) - { - tmp = *ESI; - *ESI = *EDI; - *EDI = tmp; + for(cx=width;cx>0;cx--) + { + tmp = *ESI; + *ESI = *EDI; + *EDI = tmp; - EDI--; // Attention ici on recule ! - ESI++; - } - } + EDI--; // Attention ici on recule ! + ESI++; + } + } } void Rescale(byte *src_buffer, short src_width, short src_height, byte *dst_buffer, short dst_width, short dst_height, short x_flipped, short y_flipped) { - int offset,line,column; + int offset,line,column; - int x_pos_in_brush; // Position courante dans l'ancienne brosse - int y_pos_in_brush; - int delta_x_in_brush; // "Vecteur incrémental" du point précédent - int delta_y_in_brush; - int initial_x_pos; // Position X de début de parcours de ligne - - // Calcul du "vecteur incrémental": - delta_x_in_brush=(src_width<<16) * (x_flipped?-1:1) / (dst_width); - delta_y_in_brush=(src_height<<16) * (y_flipped?-1:1) / (dst_height); + int x_pos_in_brush; // Position courante dans l'ancienne brosse + int y_pos_in_brush; + int delta_x_in_brush; // "Vecteur incrémental" du point précédent + int delta_y_in_brush; + int initial_x_pos; // Position X de début de parcours de ligne - offset=0; + // Calcul du "vecteur incrémental": + delta_x_in_brush=(src_width<<16) * (x_flipped?-1:1) / (dst_width); + delta_y_in_brush=(src_height<<16) * (y_flipped?-1:1) / (dst_height); - // Calcul de la valeur initiale de y_pos: - if (y_flipped) - y_pos_in_brush=(src_height<<16)-1; // Inversion en Y de la brosse - else - y_pos_in_brush=0; // Pas d'inversion en Y de la brosse + offset=0; - // Calcul de la valeur initiale de x_pos pour chaque ligne: - if (x_flipped) - initial_x_pos = (src_width<<16)-1; // Inversion en X de la brosse - else - initial_x_pos = 0; // Pas d'inversion en X de la brosse - - // Pour chaque ligne - for (line=0;line>16) + (y_pos_in_brush>>16)*src_width); - // On passe à la colonne de brosse suivante: - x_pos_in_brush+=delta_x_in_brush; - // On passe au pixel suivant de la nouvelle brosse: - offset++; - } - // On passe à la ligne de brosse suivante: - y_pos_in_brush+=delta_y_in_brush; - } + // Calcul de la valeur initiale de x_pos pour chaque ligne: + if (x_flipped) + initial_x_pos = (src_width<<16)-1; // Inversion en X de la brosse + else + initial_x_pos = 0; // Pas d'inversion en X de la brosse + + // Pour chaque ligne + for (line=0;line>16) + (y_pos_in_brush>>16)*src_width); + // On passe à la colonne de brosse suivante: + x_pos_in_brush+=delta_x_in_brush; + // On passe au pixel suivant de la nouvelle brosse: + offset++; + } + // On passe à la ligne de brosse suivante: + y_pos_in_brush+=delta_y_in_brush; + } } void Slider_timer(byte speed) -//Boucle d'attente pour faire bouger les scrollbars à une vitesse correcte + //Boucle d'attente pour faire bouger les scrollbars à une vitesse correcte { - Uint32 end; - byte original_mouse_k = Mouse_K; - end = SDL_GetTicks() + speed*10; - do - { - if (!Get_input()) SDL_Delay(20); - } while (Mouse_K == original_mouse_k && SDL_GetTicks()0;dx--) - { - // Pour chaque ligne - memcpy(edi,esi,ax); - memcpy(edi - x_offset,esi+ax,x_offset); + byte* esi = Screen_backup; //source de la copie + byte* edi = Main_screen + y_offset * Main_image_width + x_offset; + const word ax = Main_image_width - x_offset; // Nombre de pixels à copier à droite + word dx; + for(dx = Main_image_height - y_offset;dx>0;dx--) + { + // Pour chaque ligne + memcpy(edi,esi,ax); + memcpy(edi - x_offset,esi+ax,x_offset); - // On passe à la ligne suivante - edi += Main_image_width; - esi += Main_image_width; - } + // On passe à la ligne suivante + edi += Main_image_width; + esi += Main_image_width; + } - // On vient de faire le traitement pour otutes les lignes au-dessous de y_offset - // Maintenant on traite celles au dessus - edi = x_offset + Main_screen; - for(dx = y_offset;dx>0;dx--) - { - memcpy(edi,esi,ax); - memcpy(edi - x_offset,esi+ax,x_offset); + // On vient de faire le traitement pour otutes les lignes au-dessous de y_offset + // Maintenant on traite celles au dessus + edi = x_offset + Main_screen; + for(dx = y_offset;dx>0;dx--) + { + memcpy(edi,esi,ax); + memcpy(edi - x_offset,esi+ax,x_offset); - edi += Main_image_width; - esi += Main_image_width; - } + edi += Main_image_width; + esi += Main_image_width; + } - Update_rect(0,0,0,0); + Update_rect(0,0,0,0); } void Zoom_a_line(byte* original_line, byte* zoomed_line, - word factor, word width -) + word factor, word width + ) { - byte color; - word x; + byte color; + word x; - // Pour chaque pixel - for(x=0;x +#define _WIN32_WINNT 0x0500 +#include #elif defined(__macosx__) || defined(__FreeBSD__) - #include +#include #elif defined(__BEOS__) || defined(__HAIKU__) - // sysinfo not implemented +// sysinfo not implemented #elif defined(__AROS__) || defined(__amigaos4__) || defined(__MORPHOS__) || defined(__amigaos__) - #include +#include #elif defined(__SKYOS__) - #include +#include #else - #include // sysinfo() for free RAM +#include // sysinfo() for free RAM #endif // Indique quelle est la mémoire disponible unsigned long Memory_free(void) { - // Memory is no longer relevant. If there is ANY problem or doubt here, - // you can simply return 10*1024*1024 (10Mb), to make the "Pages"something - // memory allocation functions happy. + // Memory is no longer relevant. If there is ANY problem or doubt here, + // you can simply return 10*1024*1024 (10Mb), to make the "Pages"something + // memory allocation functions happy. - // However, it is still a good idea to make a proper function if you can... - // If Grafx2 thinks the memory is full, weird things may happen. And if memory - // ever becomes full and you're still saying there are 10MB free here, the - // program will crash without saving any picture backup ! You've been warned... - #if defined(__WIN32__) - MEMORYSTATUS mstt; - mstt.dwLength = sizeof(MEMORYSTATUS); - GlobalMemoryStatus(&mstt); - return mstt.dwAvailPhys; - #elif defined(__macosx__) || defined(__FreeBSD__) - int mib[2]; - int maxmem; - size_t len; + // However, it is still a good idea to make a proper function if you can... + // If Grafx2 thinks the memory is full, weird things may happen. And if memory + // ever becomes full and you're still saying there are 10MB free here, the + // program will crash without saving any picture backup ! You've been warned... +#if defined(__WIN32__) + MEMORYSTATUS mstt; + mstt.dwLength = sizeof(MEMORYSTATUS); + GlobalMemoryStatus(&mstt); + return mstt.dwAvailPhys; +#elif defined(__macosx__) || defined(__FreeBSD__) + int mib[2]; + int maxmem; + size_t len; - mib[0] = CTL_HW; - mib[1] = HW_USERMEM; - len = sizeof(maxmem); - sysctl(mib,2,&maxmem,&len,NULL,0); - return maxmem; - #elif defined(__BEOS__) || defined(__HAIKU__) || defined(__SKYOS__) || defined(__amigaos4__) || defined(__amigaos__) - // No on BeOS or Haiku - // AvailMem is misleading on os4 (os4 caches stuff in memory that you can still allocate) - #warning "There is missing code there for your platform ! please check and correct :)" - return 10*1024*1024; - #elif defined(__AROS__) || defined(__MORPHOS__) - return AvailMem(MEMF_ANY); - #else - struct sysinfo info; - sysinfo(&info); - return info.freeram*info.mem_unit; - #endif + mib[0] = CTL_HW; + mib[1] = HW_USERMEM; + len = sizeof(maxmem); + sysctl(mib,2,&maxmem,&len,NULL,0); + return maxmem; +#elif defined(__BEOS__) || defined(__HAIKU__) || defined(__SKYOS__) || defined(__amigaos4__) || defined(__amigaos__) + // No on BeOS or Haiku + // AvailMem is misleading on os4 (os4 caches stuff in memory that you can still allocate) +#warning "There is missing code there for your platform ! please check and correct :)" + return 10*1024*1024; +#elif defined(__AROS__) || defined(__MORPHOS__) + return AvailMem(MEMF_ANY); +#else + struct sysinfo info; + sysinfo(&info); + return info.freeram*info.mem_unit; +#endif } @@ -729,51 +773,51 @@ unsigned long Memory_free(void) // Transformer un nombre (entier naturel) en chaîne void Num2str(dword number,char * str,byte nb_char) { - int index; + int index; - for (index=nb_char-1;index>=0;index--) - { - str[index]=(number%10)+'0'; - number/=10; - if (number==0) - for (index--;index>=0;index--) - str[index]=' '; - } - str[nb_char]='\0'; + for (index=nb_char-1;index>=0;index--) + { + str[index]=(number%10)+'0'; + number/=10; + if (number==0) + for (index--;index>=0;index--) + str[index]=' '; + } + str[nb_char]='\0'; } // Arrondir un nombre réel à la valeur entière la plus proche short Round(float value) { - short temp=value; + short temp=value; - if (value>=0) - { if ((value-temp)>= 0.5) temp++; } - else - { if ((value-temp)<=-0.5) temp--; } + if (value>=0) + { if ((value-temp)>= 0.5) temp++; } + else + { if ((value-temp)<=-0.5) temp--; } - return temp; + return temp; } // Arrondir le résultat d'une division à la valeur entière supérieure short Round_div_max(short numerator,short divisor) { - if (!(numerator % divisor)) - return (numerator/divisor); - else - return (numerator/divisor)+1; + if (!(numerator % divisor)) + return (numerator/divisor); + else + return (numerator/divisor)+1; } // Retourne le minimum entre deux nombres int Min(int a,int b) { - return (ab)?a:b; + return (a>b)?a:b; } @@ -781,12 +825,12 @@ int Max(int a,int b) // Fonction retournant le libellé d'une mode (ex: " 320x200") char * Mode_label(int mode) { - static char str[24]; - if (! Video_mode[mode].Fullscreen) - return "window"; - sprintf(str, "%dx%d", Video_mode[mode].Width, Video_mode[mode].Height); + static char str[24]; + if (! Video_mode[mode].Fullscreen) + return "window"; + sprintf(str, "%dx%d", Video_mode[mode].Width, Video_mode[mode].Height); - return str; + return str; } // Trouve un mode video à partir d'une chaine: soit "window", @@ -794,12 +838,12 @@ char * Mode_label(int mode) // Renvoie -1 si la chaine n'est pas convertible int Convert_videomode_arg(const char *argument) { - // Je suis paresseux alors je vais juste tester les libellés - int mode_index; - for (mode_index=0; mode_index -*/ -////////////////////////////////////////////////////////////////////////////// -///@file misc.h -/// Miscellanous unsorted functions. -////////////////////////////////////////////////////////////////////////////// - -void Copy_image_to_brush(short start_x,short start_y,short Brush_width,short Brush_height,word image_width); -void Remap_general_lowlevel(byte * conversion_table,byte * buffer,short width,short height,short buffer_width); -void Scroll_picture(short x_offset,short y_offset); -void Wait_end_of_click(void); -void Set_color(byte color, byte red, byte green, byte blue); -void Set_palette(T_Palette palette); -void Palette_256_to_64(T_Palette palette); -void Palette_64_to_256(T_Palette palette); -void Hide_current_image(byte color); -void Hide_current_image_with_stencil(byte color, byte * stencil); -void Slider_timer(byte speed); -dword Round_div(dword numerator,dword divisor); -word Count_used_colors(dword * usage); -word Count_used_colors_area(dword* usage, word start_x, word start_y, word width, word height); -void Pixel_in_current_screen (word x,word y,byte color); -void Pixel_in_brush (word x,word y,byte color); -byte Read_pixel_from_current_screen (word x,word y); -byte Read_pixel_from_spare_screen(word x,word y); -byte Read_pixel_from_backup_screen (word x,word y); -byte Read_pixel_from_feedback_screen (word x,word y); -byte Read_pixel_from_brush (word x,word y); - -void Ellipse_compute_limites(short horizontal_radius,short vertical_radius); -// Calcule les valeurs suivantes en fonction des deux paramètres: -// -// Ellipse_vertical_radius_squared -// Ellipse_horizontal_radius_squared -// Ellipse_Limit_High -// Ellipse_Limit_Low - - -byte Pixel_in_ellipse(void); -// Indique si le pixel se trouvant à Ellipse_cursor_X pixels -// (Ellipse_cursor_X>0 = à droite, Ellipse_cursor_X<0 = à gauche) et à -// Ellipse_cursor_Y pixels (Ellipse_cursor_Y>0 = en bas, -// Ellipse_cursor_Y<0 = en haut) du centre se trouve dans l'ellipse en -// cours. - -byte Pixel_in_circle(void); -// Indique si le pixel se trouvant à Circle_cursor_X pixels -// (Circle_cursor_X>0 = à droite, Circle_cursor_X<0 = à gauche) et à -// Circle_cursor_Y pixels (Circle_cursor_Y>0 = en bas, -// Circle_cursor_Y<0 = en haut) du centre se trouve dans le cercle en -// cours. - -// Gestion du chrono dans les fileselects -void Init_chrono(dword delay); -void Check_timer(void); - -void Replace_a_color(byte old_color, byte New_color); -void Replace_colors_within_limits(byte * replace_table); - -byte Effect_interpolated_colorize (word x,word y,byte color); -byte Effect_additive_colorize (word x,word y,byte color); -byte Effect_substractive_colorize(word x,word y,byte color); -byte Effect_sieve(word x,word y); - -/// -/// Inverts a pixel buffer, according to a horizontal axis. -/// @param src Pointer to the pixel buffer to process. -/// @param width Width of the buffer. -/// @param height Height of the buffer. -void Flip_Y_lowlevel(byte *src, short width, short height); - -/// -/// Inverts a pixel buffer, according to a vertical axis. -/// @param src Pointer to the pixel buffer to process. -/// @param width Width of the buffer. -/// @param height Height of the buffer. -void Flip_X_lowlevel(byte *src, short width, short height); -/// -/// Rotate a pixel buffer by 90 degrees, clockwise. -/// @param source Source pixel buffer. -/// @param dest Destination pixel buffer. -/// @param width Width of the original buffer (height of the destination one). -/// @param height Height of the original buffer (width of the destination one). -void Rotate_90_deg_lowlevel(byte * source, byte * dest, short width, short height); -/// -/// Rotate a pixel buffer by 90 degrees, counter-clockwise. -/// @param source Source pixel buffer. -/// @param dest Destination pixel buffer. -/// @param width Width of the original buffer (height of the destination one). -/// @param height Height of the original buffer (width of the destination one). -void Rotate_270_deg_lowlevel(byte * source, byte * dest, short width, short height); -/// -/// Rotate a pixel buffer by 180 degrees. -/// @param src The pixel buffer (source and destination). -/// @param width Width of the buffer. -/// @param height Height of the buffer. -void Rotate_180_deg_lowlevel(byte *src, short width, short height); - -/// -/// Copies an image to another, rescaling it and optionally flipping it. -/// @param src_buffer Original image (address of first byte) -/// @param src_width Original image's width in pixels -/// @param src_height Original image's height in pixels -/// @param dst_buffer Destination image (address of first byte) -/// @param dst_width Destination image's width in pixels -/// @param dst_height Destination image's height in pixels -/// @param x_flipped Boolean, true to flip the image horizontally -/// @param y_flipped Boolean, true to flip the image vertically -void Rescale(byte *src_buffer, short src_width, short src_height, byte *dst_buffer, short dst_width, short dst_height, short x_flipped, short y_flipped); - -void Zoom_a_line(byte * original_line,byte * zoomed_line,word factor,word width); -void Copy_part_of_image_to_another(byte * source,word source_x,word source_y,word width,word height,word source_width,byte * dest,word dest_x,word dest_y,word destination_width); - -// -- Gestion du chrono -- -byte Timer_state; // State du chrono: 0=Attente d'un Xème de seconde - // 1=Il faut afficher la preview - // 2=Plus de chrono à gerer pour l'instant -dword Timer_delay; // Nombre de 18.2ème de secondes demandés -dword Timer_start; // Heure de départ du chrono -byte New_preview_is_needed; // Booléen "Il faut relancer le chrono de preview" - - -unsigned long Memory_free(void); - -void Num2str(dword number,char * str,byte nb_char); - -short Round(float value); -short Round_div_max(short numerator,short divisor); - -int Min(int a,int b); -int Max(int a,int b); - -char* Mode_label(int mode); -int Convert_videomode_arg(const char *argument); +/* Grafx2 - The Ultimate 256-color bitmap paint program + + Copyright 2007 Adrien Destugues + Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) + + Grafx2 is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 + of the License. + + Grafx2 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grafx2; if not, see +*/ +////////////////////////////////////////////////////////////////////////////// +///@file misc.h +/// Miscellanous unsorted functions. +////////////////////////////////////////////////////////////////////////////// + +void Copy_image_to_brush(short start_x,short start_y,short Brush_width,short Brush_height,word image_width); +void Remap_general_lowlevel(byte * conversion_table,byte * buffer,short width,short height,short buffer_width); +void Scroll_picture(short x_offset,short y_offset); +void Wait_end_of_click(void); +void Set_color(byte color, byte red, byte green, byte blue); +void Set_palette(T_Palette palette); +void Palette_256_to_64(T_Palette palette); +void Palette_64_to_256(T_Palette palette); +void Hide_current_image(byte color); +void Hide_current_image_with_stencil(byte color, byte * stencil); +void Slider_timer(byte speed); +dword Round_div(dword numerator,dword divisor); +word Count_used_colors(dword * usage); +word Count_used_colors_area(dword* usage, word start_x, word start_y, word width, word height); +word Count_used_colors_screen_area(dword* usage, word start_x, word start_y, word width, word height); +void Pixel_in_current_screen (word x,word y,byte color); +void Pixel_in_brush (word x,word y,byte color); +byte Read_pixel_from_current_screen (word x,word y); +byte Read_pixel_from_spare_screen(word x,word y); +byte Read_pixel_from_backup_screen (word x,word y); +byte Read_pixel_from_feedback_screen (word x,word y); +byte Read_pixel_from_brush (word x,word y); + +void Ellipse_compute_limites(short horizontal_radius,short vertical_radius); +// Calcule les valeurs suivantes en fonction des deux paramètres: +// +// Ellipse_vertical_radius_squared +// Ellipse_horizontal_radius_squared +// Ellipse_Limit_High +// Ellipse_Limit_Low + + +byte Pixel_in_ellipse(void); +// Indique si le pixel se trouvant à Ellipse_cursor_X pixels +// (Ellipse_cursor_X>0 = à droite, Ellipse_cursor_X<0 = à gauche) et à +// Ellipse_cursor_Y pixels (Ellipse_cursor_Y>0 = en bas, +// Ellipse_cursor_Y<0 = en haut) du centre se trouve dans l'ellipse en +// cours. + +byte Pixel_in_circle(void); +// Indique si le pixel se trouvant à Circle_cursor_X pixels +// (Circle_cursor_X>0 = à droite, Circle_cursor_X<0 = à gauche) et à +// Circle_cursor_Y pixels (Circle_cursor_Y>0 = en bas, +// Circle_cursor_Y<0 = en haut) du centre se trouve dans le cercle en +// cours. + +// Gestion du chrono dans les fileselects +void Init_chrono(dword delay); +void Check_timer(void); + +void Replace_a_color(byte old_color, byte New_color); +void Replace_colors_within_limits(byte * replace_table); + +byte Effect_interpolated_colorize (word x,word y,byte color); +byte Effect_additive_colorize (word x,word y,byte color); +byte Effect_substractive_colorize(word x,word y,byte color); +byte Effect_sieve(word x,word y); + +/// +/// Inverts a pixel buffer, according to a horizontal axis. +/// @param src Pointer to the pixel buffer to process. +/// @param width Width of the buffer. +/// @param height Height of the buffer. +void Flip_Y_lowlevel(byte *src, short width, short height); + +/// +/// Inverts a pixel buffer, according to a vertical axis. +/// @param src Pointer to the pixel buffer to process. +/// @param width Width of the buffer. +/// @param height Height of the buffer. +void Flip_X_lowlevel(byte *src, short width, short height); +/// +/// Rotate a pixel buffer by 90 degrees, clockwise. +/// @param source Source pixel buffer. +/// @param dest Destination pixel buffer. +/// @param width Width of the original buffer (height of the destination one). +/// @param height Height of the original buffer (width of the destination one). +void Rotate_90_deg_lowlevel(byte * source, byte * dest, short width, short height); +/// +/// Rotate a pixel buffer by 90 degrees, counter-clockwise. +/// @param source Source pixel buffer. +/// @param dest Destination pixel buffer. +/// @param width Width of the original buffer (height of the destination one). +/// @param height Height of the original buffer (width of the destination one). +void Rotate_270_deg_lowlevel(byte * source, byte * dest, short width, short height); +/// +/// Rotate a pixel buffer by 180 degrees. +/// @param src The pixel buffer (source and destination). +/// @param width Width of the buffer. +/// @param height Height of the buffer. +void Rotate_180_deg_lowlevel(byte *src, short width, short height); + +/// +/// Copies an image to another, rescaling it and optionally flipping it. +/// @param src_buffer Original image (address of first byte) +/// @param src_width Original image's width in pixels +/// @param src_height Original image's height in pixels +/// @param dst_buffer Destination image (address of first byte) +/// @param dst_width Destination image's width in pixels +/// @param dst_height Destination image's height in pixels +/// @param x_flipped Boolean, true to flip the image horizontally +/// @param y_flipped Boolean, true to flip the image vertically +void Rescale(byte *src_buffer, short src_width, short src_height, byte *dst_buffer, short dst_width, short dst_height, short x_flipped, short y_flipped); + +void Zoom_a_line(byte * original_line,byte * zoomed_line,word factor,word width); +void Copy_part_of_image_to_another(byte * source,word source_x,word source_y,word width,word height,word source_width,byte * dest,word dest_x,word dest_y,word destination_width); + +// -- Gestion du chrono -- +byte Timer_state; // State du chrono: 0=Attente d'un Xème de seconde + // 1=Il faut afficher la preview + // 2=Plus de chrono à gerer pour l'instant +dword Timer_delay; // Nombre de 18.2ème de secondes demandés +dword Timer_start; // Heure de départ du chrono +byte New_preview_is_needed; // Booléen "Il faut relancer le chrono de preview" + + +unsigned long Memory_free(void); + +void Num2str(dword number,char * str,byte nb_char); + +short Round(float value); +short Round_div_max(short numerator,short divisor); + +int Min(int a,int b); +int Max(int a,int b); + +char* Mode_label(int mode); +int Convert_videomode_arg(const char *argument); diff --git a/mountlist.c b/mountlist.c index 43067554..74674df2 100644 --- a/mountlist.c +++ b/mountlist.c @@ -1,914 +1,914 @@ -/* mountlist.c -- return a list of mounted file systems - - Copyright (C) 1991, 1992, 1997, 1998, 1999, 2000, 2001, 2002, 2003, - 2004, 2005, 2006, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, see . -*/ - -// This file is not used on some platforms, so don't do anything for them -#if(!defined(__WIN32__))&&(!defined(__amigaos4__))&&(!defined(__AROS__))&&(!defined(__MORPHOS__))&&(!defined(__amigaos__)) - -// We don't use autoconf and all that in grafx2, so let's do the config here ... -#if defined(__macosx__) || defined(__FreeBSD__) // MacOS X is POSIX compliant - #define MOUNTED_GETMNTINFO -#elif defined(__BEOS__) || defined(__HAIKU__) - #define MOUNTED_FS_STAT_DEV -#elif defined(__SKYOS__) - #warning "Your platform is missing some specific code here ! please check and fix :)" -#else - #define MOUNTED_GETMNTENT1 -#endif -// --- END GRAFX2 CUSTOM CONFIG --- - -#include "mountlist.h" - -#include -#include -#include -#include - -#include - -#include - -#include - -#if HAVE_SYS_PARAM_H -# include -#endif - -#if defined MOUNTED_GETFSSTAT /* OSF_1 and Darwin1.3.x */ -# if HAVE_SYS_UCRED_H -# include /* needed on OSF V4.0 for definition of NGROUPS, - NGROUPS is used as an array dimension in ucred.h */ -# include /* needed by powerpc-apple-darwin1.3.7 */ -# endif -# if HAVE_SYS_MOUNT_H -# include -# endif -# if HAVE_SYS_FS_TYPES_H -# include /* needed by powerpc-apple-darwin1.3.7 */ -# endif -# if HAVE_STRUCT_FSSTAT_F_FSTYPENAME -# define FS_TYPE(Ent) ((Ent).f_fstypename) -# else -# define FS_TYPE(Ent) mnt_names[(Ent).f_type] -# endif -#endif /* MOUNTED_GETFSSTAT */ - -#ifdef MOUNTED_GETMNTENT1 /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */ -# include -# if !defined MOUNTED -# if defined _PATH_MOUNTED /* GNU libc */ -# define MOUNTED _PATH_MOUNTED -# endif -# if defined MNT_MNTTAB /* HP-UX. */ -# define MOUNTED MNT_MNTTAB -# endif -# if defined MNTTABNAME /* Dynix. */ -# define MOUNTED MNTTABNAME -# endif -# endif -#endif - -#ifdef MOUNTED_GETMNTINFO /* 4.4BSD. */ -# include -#endif - -#ifdef MOUNTED_GETMNTINFO2 /* NetBSD 3.0. */ -# include -#endif - -#ifdef MOUNTED_GETMNT /* Ultrix. */ -# include -# include -#endif - -#ifdef MOUNTED_FS_STAT_DEV /* BeOS. */ -# include -# include -#endif - -#ifdef MOUNTED_FREAD /* SVR2. */ -# include -#endif - -#ifdef MOUNTED_FREAD_FSTYP /* SVR3. */ -# include -# include -# include -#endif - -#ifdef MOUNTED_LISTMNTENT -# include -#endif - -#ifdef MOUNTED_GETMNTENT2 /* SVR4. */ -# include -#endif - -#ifdef MOUNTED_VMOUNT /* AIX. */ -# include -# include -#endif - -#ifdef DOLPHIN -/* So special that it's not worth putting this in autoconf. */ -# undef MOUNTED_FREAD_FSTYP -# define MOUNTED_GETMNTTBL -#endif - -#if HAVE_SYS_MNTENT_H -/* This is to get MNTOPT_IGNORE on e.g. SVR4. */ -# include -#endif - -#undef MNT_IGNORE -#if defined MNTOPT_IGNORE && defined HAVE_HASMNTOPT -# define MNT_IGNORE(M) hasmntopt ((M), MNTOPT_IGNORE) -#else -# define MNT_IGNORE(M) 0 -#endif - -#if USE_UNLOCKED_IO -# include "unlocked-io.h" -#endif - -#ifndef SIZE_MAX -# define SIZE_MAX ((size_t) -1) -#endif - -/* The results of open() in this file are not used with fchdir, - therefore save some unnecessary work in fchdir.c. */ -#undef open -#undef close - -/* The results of opendir() in this file are not used with dirfd and fchdir, - therefore save some unnecessary work in fchdir.c. */ -#undef opendir -#undef closedir - -// gcc2 under haiku and beos don't like these macros for some reason. -// As they are not used there anyways, we remove them and everyone is happy. -#if !defined(__HAIKU__) && !defined(__BEOS__) -#ifndef ME_DUMMY -# define ME_DUMMY(Fs_name, Fs_type) \ - (strcmp (Fs_type, "autofs") == 0 \ - || strcmp (Fs_type, "none") == 0 \ - || strcmp (Fs_type, "proc") == 0 \ - || strcmp (Fs_type, "subfs") == 0 \ - || strcmp (Fs_type, "sysfs") == 0 \ - || strcmp (Fs_type, "usbfs") == 0 \ - || strcmp (Fs_type, "devpts") == 0 \ - || strcmp (Fs_type, "tmpfs") == 0 \ - /* for NetBSD 3.0 */ \ - || strcmp (Fs_type, "kernfs") == 0 \ - /* for Irix 6.5 */ \ - || strcmp (Fs_type, "ignore") == 0 \ - /* for MacOSX */ \ - || strcmp (Fs_type, "devfs") == 0 \ - || strcmp (Fs_type, "fdesc") == 0 \ - || strcmp (Fs_type, "nfs") == 0 \ - || strcmp (Fs_type, "volfs") == 0) -#endif - -#ifndef ME_REMOTE -/* A file system is `remote' if its Fs_name contains a `:' - or if (it is of type (smbfs or cifs) and its Fs_name starts with `//'). */ -# define ME_REMOTE(Fs_name, Fs_type) \ - (strchr (Fs_name, ':') != NULL \ - || ((Fs_name)[0] == '/' \ - && (Fs_name)[1] == '/' \ - && (strcmp (Fs_type, "smbfs") == 0 \ - || strcmp (Fs_type, "cifs") == 0))) -#endif -#endif // HAIKU / BEOS - -#ifdef MOUNTED_GETMNTINFO - -# if ! HAVE_STRUCT_STATFS_F_FSTYPENAME -static char * -fstype_to_string (short int t) -{ - switch (t) - { -# ifdef MOUNT_PC - case MOUNT_PC: - return "pc"; -# endif -# ifdef MOUNT_MFS - case MOUNT_MFS: - return "mfs"; -# endif -# ifdef MOUNT_LO - case MOUNT_LO: - return "lo"; -# endif -# ifdef MOUNT_TFS - case MOUNT_TFS: - return "tfs"; -# endif -# ifdef MOUNT_TMP - case MOUNT_TMP: - return "tmp"; -# endif -# ifdef MOUNT_UFS - case MOUNT_UFS: - return "ufs" ; -# endif -# ifdef MOUNT_NFS - case MOUNT_NFS: - return "nfs" ; -# endif -# ifdef MOUNT_MSDOS - case MOUNT_MSDOS: - return "msdos" ; -# endif -# ifdef MOUNT_LFS - case MOUNT_LFS: - return "lfs" ; -# endif -# ifdef MOUNT_LOFS - case MOUNT_LOFS: - return "lofs" ; -# endif -# ifdef MOUNT_FDESC - case MOUNT_FDESC: - return "fdesc" ; -# endif -# ifdef MOUNT_PORTAL - case MOUNT_PORTAL: - return "portal" ; -# endif -# ifdef MOUNT_NULL - case MOUNT_NULL: - return "null" ; -# endif -# ifdef MOUNT_UMAP - case MOUNT_UMAP: - return "umap" ; -# endif -# ifdef MOUNT_KERNFS - case MOUNT_KERNFS: - return "kernfs" ; -# endif -# ifdef MOUNT_PROCFS - case MOUNT_PROCFS: - return "procfs" ; -# endif -# ifdef MOUNT_AFS - case MOUNT_AFS: - return "afs" ; -# endif -# ifdef MOUNT_CD9660 - case MOUNT_CD9660: - return "cd9660" ; -# endif -# ifdef MOUNT_UNION - case MOUNT_UNION: - return "union" ; -# endif -# ifdef MOUNT_DEVFS - case MOUNT_DEVFS: - return "devfs" ; -# endif -# ifdef MOUNT_EXT2FS - case MOUNT_EXT2FS: - return "ext2fs" ; -# endif - default: - return "?"; - } -} -# endif - -static char * -fsp_to_string (const struct statfs *fsp) -{ -# if HAVE_STRUCT_STATFS_F_FSTYPENAME - return (char *) (fsp->f_fstypename); -# else - return fstype_to_string (fsp->f_type); -# endif -} - -#endif /* MOUNTED_GETMNTINFO */ - -#ifdef MOUNTED_VMOUNT /* AIX. */ -static char * -fstype_to_string (int t) -{ - struct vfs_ent *e; - - e = getvfsbytype (t); - if (!e || !e->vfsent_name) - return "none"; - else - return e->vfsent_name; -} -#endif /* MOUNTED_VMOUNT */ - - -#if defined MOUNTED_GETMNTENT1 || defined MOUNTED_GETMNTENT2 - -/* Return the device number from MOUNT_OPTIONS, if possible. - Otherwise return (dev_t) -1. */ - -static dev_t -dev_from_mount_options (char const *mount_options) -{ - /* GNU/Linux allows file system implementations to define their own - meaning for "dev=" mount options, so don't trust the meaning - here. */ -# ifndef __linux__ - - static char const dev_pattern[] = ",dev="; - char const *devopt = strstr (mount_options, dev_pattern); - - if (devopt) - { - char const *optval = devopt + sizeof dev_pattern - 1; - char *optvalend; - unsigned long int dev; - errno = 0; - dev = strtoul (optval, &optvalend, 16); - if (optval != optvalend - && (*optvalend == '\0' || *optvalend == ',') - && ! (dev == ULONG_MAX && errno == ERANGE) - && dev == (dev_t) dev) - return dev; - } - -# endif - - return -1; -} - -#endif - -/* Return a list of the currently mounted file systems, or NULL on error. - Add each entry to the tail of the list so that they stay in order. - If NEED_FS_TYPE is true, ensure that the file system type fields in - the returned list are valid. Otherwise, they might not be. */ - -struct mount_entry * -read_file_system_list (bool need_fs_type) -{ - struct mount_entry *mount_list; - struct mount_entry *me; - struct mount_entry **mtail = &mount_list; - -#ifdef MOUNTED_LISTMNTENT - { - struct tabmntent *mntlist, *p; - struct mntent *mnt; - struct mount_entry *me; - - /* the third and fourth arguments could be used to filter mounts, - but Crays doesn't seem to have any mounts that we want to - remove. Specifically, automount create normal NFS mounts. - */ - - if (listmntent (&mntlist, KMTAB, NULL, NULL) < 0) - return NULL; - for (p = mntlist; p; p = p->next) { - mnt = p->ment; - me = xmalloc (sizeof *me); - me->me_devname = xstrdup (mnt->mnt_fsname); - me->me_mountdir = xstrdup (mnt->mnt_dir); - me->me_type = xstrdup (mnt->mnt_type); - me->me_type_malloced = 1; - me->me_dummy = ME_DUMMY (me->me_devname, me->me_type); - me->me_remote = ME_REMOTE (me->me_devname, me->me_type); - me->me_dev = -1; - *mtail = me; - mtail = &me->me_next; - } - freemntlist (mntlist); - } -#endif - -#ifdef MOUNTED_GETMNTENT1 /* GNU/Linux, 4.3BSD, SunOS, HP-UX, Dynix, Irix. */ - { - struct mntent *mnt; - char *table = MOUNTED; - FILE *fp; - - fp = setmntent (table, "r"); - if (fp == NULL) - return NULL; - - while ((mnt = getmntent (fp))) - { - me = malloc (sizeof *me); - me->me_devname = strdup (mnt->mnt_fsname); - me->me_mountdir = strdup (mnt->mnt_dir); - me->me_type = strdup (mnt->mnt_type); - me->me_type_malloced = 1; - me->me_dummy = ME_DUMMY (me->me_devname, me->me_type); - me->me_remote = ME_REMOTE (me->me_devname, me->me_type); - me->me_dev = dev_from_mount_options (mnt->mnt_opts); - - /* Add to the linked list. */ - *mtail = me; - mtail = &me->me_next; - } - - if (endmntent (fp) == 0) - goto free_then_fail; - } -#endif /* MOUNTED_GETMNTENT1. */ - -#ifdef MOUNTED_GETMNTINFO /* 4.4BSD. */ - { - struct statfs *fsp; - int entries; - - entries = getmntinfo (&fsp, MNT_NOWAIT); - if (entries < 0) - return NULL; - for (; entries-- > 0; fsp++) - { - me = malloc (sizeof *me); - me->me_devname = strdup (fsp->f_mntfromname); - me->me_mountdir = strdup (fsp->f_mntonname); -#if defined(__macosx__) - me->me_type = fsp->f_fstypename; -#else - me->me_type = fsp->fs_typename; -#endif - me->me_type_malloced = 0; - me->me_dummy = ME_DUMMY (me->me_devname, me->me_type); - me->me_remote = ME_REMOTE (me->me_devname, me->me_type); - me->me_dev = (dev_t) -1; /* Magic; means not known yet. */ - - /* Add to the linked list. */ - *mtail = me; - mtail = &me->me_next; - } - } -#endif /* MOUNTED_GETMNTINFO */ - -#ifdef MOUNTED_GETMNTINFO2 /* NetBSD 3.0. */ - { - struct statvfs *fsp; - int entries; - - entries = getmntinfo (&fsp, MNT_NOWAIT); - if (entries < 0) - return NULL; - for (; entries-- > 0; fsp++) - { - me = xmalloc (sizeof *me); - me->me_devname = xstrdup (fsp->f_mntfromname); - me->me_mountdir = xstrdup (fsp->f_mntonname); - me->me_type = xstrdup (fsp->f_fstypename); - me->me_type_malloced = 1; - me->me_dummy = ME_DUMMY (me->me_devname, me->me_type); - me->me_remote = ME_REMOTE (me->me_devname, me->me_type); - me->me_dev = (dev_t) -1; /* Magic; means not known yet. */ - - /* Add to the linked list. */ - *mtail = me; - mtail = &me->me_next; - } - } -#endif /* MOUNTED_GETMNTINFO2 */ - -#ifdef MOUNTED_GETMNT /* Ultrix. */ - { - int offset = 0; - int val; - struct fs_data fsd; - - while (errno = 0, - 0 < (val = getmnt (&offset, &fsd, sizeof (fsd), NOSTAT_MANY, - (char *) 0))) - { - me = xmalloc (sizeof *me); - me->me_devname = xstrdup (fsd.fd_req.devname); - me->me_mountdir = xstrdup (fsd.fd_req.path); - me->me_type = gt_names[fsd.fd_req.fstype]; - me->me_type_malloced = 0; - me->me_dummy = ME_DUMMY (me->me_devname, me->me_type); - me->me_remote = ME_REMOTE (me->me_devname, me->me_type); - me->me_dev = fsd.fd_req.dev; - - /* Add to the linked list. */ - *mtail = me; - mtail = &me->me_next; - } - if (val < 0) - goto free_then_fail; - } -#endif /* MOUNTED_GETMNT. */ - -#if defined MOUNTED_FS_STAT_DEV /* BeOS */ - { - /* The next_dev() and fs_stat_dev() system calls give the list of - all file systems, including the information returned by statvfs() - (fs type, total blocks, free blocks etc.), but without the mount - point. But on BeOS all file systems except / are mounted in the - rootfs, directly under /. - The directory name of the mount point is often, but not always, - identical to the volume name of the device. - We therefore get the list of subdirectories of /, and the list - of all file systems, and match the two lists. */ - - DIR *dirp; - struct rootdir_entry - { - char *name; - dev_t dev; - ino_t ino; - struct rootdir_entry *next; - }; - struct rootdir_entry *rootdir_list; - struct rootdir_entry **rootdir_tail; - int32 pos; - dev_t dev; - fs_info fi; - - /* All volumes are mounted in the rootfs, directly under /. */ - rootdir_list = NULL; - rootdir_tail = &rootdir_list; - dirp = opendir ("/"); - if (dirp) - { - struct dirent *d; - - while ((d = readdir (dirp)) != NULL) - { - char *name; - struct stat statbuf; - - if (strcmp (d->d_name, "..") == 0) - continue; - - if (strcmp (d->d_name, ".") == 0) - name = strdup ("/"); - else - { - name = malloc (1 + strlen (d->d_name) + 1); - name[0] = '/'; - strcpy (name + 1, d->d_name); - } - - if (lstat (name, &statbuf) >= 0 && S_ISDIR (statbuf.st_mode)) - { - struct rootdir_entry *re = malloc (sizeof *re); - re->name = name; - re->dev = statbuf.st_dev; - re->ino = statbuf.st_ino; - - /* Add to the linked list. */ - *rootdir_tail = re; - rootdir_tail = &re->next; - } - else - free (name); - } - closedir (dirp); - } - *rootdir_tail = NULL; - - for (pos = 0; (dev = next_dev (&pos)) >= 0; ) - if (fs_stat_dev (dev, &fi) >= 0) - { - /* Note: fi.dev == dev. */ - struct rootdir_entry *re; - - for (re = rootdir_list; re; re = re->next) - if (re->dev == fi.dev && re->ino == fi.root) - break; - - me = malloc (sizeof *me); - me->me_devname = strdup (fi.device_name[0] != '\0' ? fi.device_name : fi.fsh_name); - me->me_mountdir = strdup (re != NULL ? re->name : fi.fsh_name); - me->me_type = strdup (fi.fsh_name); - me->me_type_malloced = 1; - me->me_dev = fi.dev; - me->me_dummy = 0; - me->me_remote = (fi.flags & B_FS_IS_SHARED) != 0; - - /* Add to the linked list. */ - *mtail = me; - mtail = &me->me_next; - } - *mtail = NULL; - - while (rootdir_list != NULL) - { - struct rootdir_entry *re = rootdir_list; - rootdir_list = re->next; - free (re->name); - free (re); - } - } -#endif /* MOUNTED_FS_STAT_DEV */ - -#if defined MOUNTED_GETFSSTAT /* __alpha running OSF_1 */ - { - int numsys, counter; - size_t bufsize; - struct statfs *stats; - - numsys = getfsstat ((struct statfs *)0, 0L, MNT_NOWAIT); - if (numsys < 0) - return (NULL); - if (SIZE_MAX / sizeof *stats <= numsys) - xalloc_die (); - - bufsize = (1 + numsys) * sizeof *stats; - stats = xmalloc (bufsize); - numsys = getfsstat (stats, bufsize, MNT_NOWAIT); - - if (numsys < 0) - { - free (stats); - return (NULL); - } - - for (counter = 0; counter < numsys; counter++) - { - me = xmalloc (sizeof *me); - me->me_devname = xstrdup (stats[counter].f_mntfromname); - me->me_mountdir = xstrdup (stats[counter].f_mntonname); - me->me_type = xstrdup (FS_TYPE (stats[counter])); - me->me_type_malloced = 1; - me->me_dummy = ME_DUMMY (me->me_devname, me->me_type); - me->me_remote = ME_REMOTE (me->me_devname, me->me_type); - me->me_dev = (dev_t) -1; /* Magic; means not known yet. */ - - /* Add to the linked list. */ - *mtail = me; - mtail = &me->me_next; - } - - free (stats); - } -#endif /* MOUNTED_GETFSSTAT */ - -#if defined MOUNTED_FREAD || defined MOUNTED_FREAD_FSTYP /* SVR[23]. */ - { - struct mnttab mnt; - char *table = "/etc/mnttab"; - FILE *fp; - - fp = fopen (table, "r"); - if (fp == NULL) - return NULL; - - while (fread (&mnt, sizeof mnt, 1, fp) > 0) - { - me = xmalloc (sizeof *me); -# ifdef GETFSTYP /* SVR3. */ - me->me_devname = xstrdup (mnt.mt_dev); -# else - me->me_devname = xmalloc (strlen (mnt.mt_dev) + 6); - strcpy (me->me_devname, "/dev/"); - strcpy (me->me_devname + 5, mnt.mt_dev); -# endif - me->me_mountdir = xstrdup (mnt.mt_filsys); - me->me_dev = (dev_t) -1; /* Magic; means not known yet. */ - me->me_type = ""; - me->me_type_malloced = 0; -# ifdef GETFSTYP /* SVR3. */ - if (need_fs_type) - { - struct statfs fsd; - char typebuf[FSTYPSZ]; - - if (statfs (me->me_mountdir, &fsd, sizeof fsd, 0) != -1 - && sysfs (GETFSTYP, fsd.f_fstyp, typebuf) != -1) - { - me->me_type = xstrdup (typebuf); - me->me_type_malloced = 1; - } - } -# endif - me->me_dummy = ME_DUMMY (me->me_devname, me->me_type); - me->me_remote = ME_REMOTE (me->me_devname, me->me_type); - - /* Add to the linked list. */ - *mtail = me; - mtail = &me->me_next; - } - - if (ferror (fp)) - { - /* The last fread() call must have failed. */ - int saved_errno = errno; - fclose (fp); - errno = saved_errno; - goto free_then_fail; - } - - if (fclose (fp) == EOF) - goto free_then_fail; - } -#endif /* MOUNTED_FREAD || MOUNTED_FREAD_FSTYP. */ - -#ifdef MOUNTED_GETMNTTBL /* DolphinOS goes its own way. */ - { - struct mntent **mnttbl = getmnttbl (), **ent; - for (ent=mnttbl;*ent;ent++) - { - me = xmalloc (sizeof *me); - me->me_devname = xstrdup ( (*ent)->mt_resource); - me->me_mountdir = xstrdup ( (*ent)->mt_directory); - me->me_type = xstrdup ((*ent)->mt_fstype); - me->me_type_malloced = 1; - me->me_dummy = ME_DUMMY (me->me_devname, me->me_type); - me->me_remote = ME_REMOTE (me->me_devname, me->me_type); - me->me_dev = (dev_t) -1; /* Magic; means not known yet. */ - - /* Add to the linked list. */ - *mtail = me; - mtail = &me->me_next; - } - endmnttbl (); - } -#endif - -#ifdef MOUNTED_GETMNTENT2 /* SVR4. */ - { - struct mnttab mnt; - char *table = MNTTAB; - FILE *fp; - int ret; - int lockfd = -1; - -# if defined F_RDLCK && defined F_SETLKW - /* MNTTAB_LOCK is a macro name of our own invention; it's not present in - e.g. Solaris 2.6. If the SVR4 folks ever define a macro - for this file name, we should use their macro name instead. - (Why not just lock MNTTAB directly? We don't know.) */ -# ifndef MNTTAB_LOCK -# define MNTTAB_LOCK "/etc/.mnttab.lock" -# endif - lockfd = open (MNTTAB_LOCK, O_RDONLY); - if (0 <= lockfd) - { - struct flock flock; - flock.l_type = F_RDLCK; - flock.l_whence = SEEK_SET; - flock.l_start = 0; - flock.l_len = 0; - while (fcntl (lockfd, F_SETLKW, &flock) == -1) - if (errno != EINTR) - { - int saved_errno = errno; - close (lockfd); - errno = saved_errno; - return NULL; - } - } - else if (errno != ENOENT) - return NULL; -# endif - - errno = 0; - fp = fopen (table, "r"); - if (fp == NULL) - ret = errno; - else - { - while ((ret = getmntent (fp, &mnt)) == 0) - { - me = xmalloc (sizeof *me); - me->me_devname = xstrdup (mnt.mnt_special); - me->me_mountdir = xstrdup (mnt.mnt_mountp); - me->me_type = xstrdup (mnt.mnt_fstype); - me->me_type_malloced = 1; - me->me_dummy = MNT_IGNORE (&mnt) != 0; - me->me_remote = ME_REMOTE (me->me_devname, me->me_type); - me->me_dev = dev_from_mount_options (mnt.mnt_mntopts); - - /* Add to the linked list. */ - *mtail = me; - mtail = &me->me_next; - } - - ret = fclose (fp) == EOF ? errno : 0 < ret ? 0 : -1; - } - - if (0 <= lockfd && close (lockfd) != 0) - ret = errno; - - if (0 <= ret) - { - errno = ret; - goto free_then_fail; - } - } -#endif /* MOUNTED_GETMNTENT2. */ - -#ifdef MOUNTED_VMOUNT /* AIX. */ - { - int bufsize; - char *entries, *thisent; - struct vmount *vmp; - int n_entries; - int i; - - /* Ask how many bytes to allocate for the mounted file system info. */ - if (mntctl (MCTL_QUERY, sizeof bufsize, (struct vmount *) &bufsize) != 0) - return NULL; - entries = xmalloc (bufsize); - - /* Get the list of mounted file systems. */ - n_entries = mntctl (MCTL_QUERY, bufsize, (struct vmount *) entries); - if (n_entries < 0) - { - int saved_errno = errno; - free (entries); - errno = saved_errno; - return NULL; - } - - for (i = 0, thisent = entries; - i < n_entries; - i++, thisent += vmp->vmt_length) - { - char *options, *ignore; - - vmp = (struct vmount *) thisent; - me = xmalloc (sizeof *me); - if (vmp->vmt_flags & MNT_REMOTE) - { - char *host, *dir; - - me->me_remote = 1; - /* Prepend the remote dirname. */ - host = thisent + vmp->vmt_data[VMT_HOSTNAME].vmt_off; - dir = thisent + vmp->vmt_data[VMT_OBJECT].vmt_off; - me->me_devname = xmalloc (strlen (host) + strlen (dir) + 2); - strcpy (me->me_devname, host); - strcat (me->me_devname, ":"); - strcat (me->me_devname, dir); - } - else - { - me->me_remote = 0; - me->me_devname = xstrdup (thisent + - vmp->vmt_data[VMT_OBJECT].vmt_off); - } - me->me_mountdir = xstrdup (thisent + vmp->vmt_data[VMT_STUB].vmt_off); - me->me_type = xstrdup (fstype_to_string (vmp->vmt_gfstype)); - me->me_type_malloced = 1; - options = thisent + vmp->vmt_data[VMT_ARGS].vmt_off; - ignore = strstr (options, "ignore"); - me->me_dummy = (ignore - && (ignore == options || ignore[-1] == ',') - && (ignore[sizeof "ignore" - 1] == ',' - || ignore[sizeof "ignore" - 1] == '\0')); - me->me_dev = (dev_t) -1; /* vmt_fsid might be the info we want. */ - - /* Add to the linked list. */ - *mtail = me; - mtail = &me->me_next; - } - free (entries); - } -#endif /* MOUNTED_VMOUNT. */ - - *mtail = NULL; - return mount_list; - - - free_then_fail: - { - int saved_errno = errno; - *mtail = NULL; - - while (mount_list) - { - me = mount_list->me_next; - free (mount_list->me_devname); - free (mount_list->me_mountdir); - if (mount_list->me_type_malloced) - free (mount_list->me_type); - free (mount_list); - mount_list = me; - } - - errno = saved_errno; - return NULL; - } -} - -#endif - +/* mountlist.c -- return a list of mounted file systems + + Copyright (C) 1991, 1992, 1997, 1998, 1999, 2000, 2001, 2002, 2003, + 2004, 2005, 2006, 2007 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . +*/ + +// This file is not used on some platforms, so don't do anything for them +#if(!defined(__WIN32__))&&(!defined(__amigaos4__))&&(!defined(__AROS__))&&(!defined(__MORPHOS__))&&(!defined(__amigaos__)) + +// We don't use autoconf and all that in grafx2, so let's do the config here ... +#if defined(__macosx__) || defined(__FreeBSD__) // MacOS X is POSIX compliant + #define MOUNTED_GETMNTINFO +#elif defined(__BEOS__) || defined(__HAIKU__) + #define MOUNTED_FS_STAT_DEV +#elif defined(__SKYOS__) + #warning "Your platform is missing some specific code here ! please check and fix :)" +#else + #define MOUNTED_GETMNTENT1 +#endif +// --- END GRAFX2 CUSTOM CONFIG --- + +#include "mountlist.h" + +#include +#include +#include +#include + +#include + +#include + +#include + +#if HAVE_SYS_PARAM_H +# include +#endif + +#if defined MOUNTED_GETFSSTAT /* OSF_1 and Darwin1.3.x */ +# if HAVE_SYS_UCRED_H +# include /* needed on OSF V4.0 for definition of NGROUPS, + NGROUPS is used as an array dimension in ucred.h */ +# include /* needed by powerpc-apple-darwin1.3.7 */ +# endif +# if HAVE_SYS_MOUNT_H +# include +# endif +# if HAVE_SYS_FS_TYPES_H +# include /* needed by powerpc-apple-darwin1.3.7 */ +# endif +# if HAVE_STRUCT_FSSTAT_F_FSTYPENAME +# define FS_TYPE(Ent) ((Ent).f_fstypename) +# else +# define FS_TYPE(Ent) mnt_names[(Ent).f_type] +# endif +#endif /* MOUNTED_GETFSSTAT */ + +#ifdef MOUNTED_GETMNTENT1 /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */ +# include +# if !defined MOUNTED +# if defined _PATH_MOUNTED /* GNU libc */ +# define MOUNTED _PATH_MOUNTED +# endif +# if defined MNT_MNTTAB /* HP-UX. */ +# define MOUNTED MNT_MNTTAB +# endif +# if defined MNTTABNAME /* Dynix. */ +# define MOUNTED MNTTABNAME +# endif +# endif +#endif + +#ifdef MOUNTED_GETMNTINFO /* 4.4BSD. */ +# include +#endif + +#ifdef MOUNTED_GETMNTINFO2 /* NetBSD 3.0. */ +# include +#endif + +#ifdef MOUNTED_GETMNT /* Ultrix. */ +# include +# include +#endif + +#ifdef MOUNTED_FS_STAT_DEV /* BeOS. */ +# include +# include +#endif + +#ifdef MOUNTED_FREAD /* SVR2. */ +# include +#endif + +#ifdef MOUNTED_FREAD_FSTYP /* SVR3. */ +# include +# include +# include +#endif + +#ifdef MOUNTED_LISTMNTENT +# include +#endif + +#ifdef MOUNTED_GETMNTENT2 /* SVR4. */ +# include +#endif + +#ifdef MOUNTED_VMOUNT /* AIX. */ +# include +# include +#endif + +#ifdef DOLPHIN +/* So special that it's not worth putting this in autoconf. */ +# undef MOUNTED_FREAD_FSTYP +# define MOUNTED_GETMNTTBL +#endif + +#if HAVE_SYS_MNTENT_H +/* This is to get MNTOPT_IGNORE on e.g. SVR4. */ +# include +#endif + +#undef MNT_IGNORE +#if defined MNTOPT_IGNORE && defined HAVE_HASMNTOPT +# define MNT_IGNORE(M) hasmntopt ((M), MNTOPT_IGNORE) +#else +# define MNT_IGNORE(M) 0 +#endif + +#if USE_UNLOCKED_IO +# include "unlocked-io.h" +#endif + +#ifndef SIZE_MAX +# define SIZE_MAX ((size_t) -1) +#endif + +/* The results of open() in this file are not used with fchdir, + therefore save some unnecessary work in fchdir.c. */ +#undef open +#undef close + +/* The results of opendir() in this file are not used with dirfd and fchdir, + therefore save some unnecessary work in fchdir.c. */ +#undef opendir +#undef closedir + +// gcc2 under haiku and beos don't like these macros for some reason. +// As they are not used there anyways, we remove them and everyone is happy. +#if !defined(__HAIKU__) && !defined(__BEOS__) +#ifndef ME_DUMMY +# define ME_DUMMY(Fs_name, Fs_type) \ + (strcmp (Fs_type, "autofs") == 0 \ + || strcmp (Fs_type, "none") == 0 \ + || strcmp (Fs_type, "proc") == 0 \ + || strcmp (Fs_type, "subfs") == 0 \ + || strcmp (Fs_type, "sysfs") == 0 \ + || strcmp (Fs_type, "usbfs") == 0 \ + || strcmp (Fs_type, "devpts") == 0 \ + || strcmp (Fs_type, "tmpfs") == 0 \ + /* for NetBSD 3.0 */ \ + || strcmp (Fs_type, "kernfs") == 0 \ + /* for Irix 6.5 */ \ + || strcmp (Fs_type, "ignore") == 0 \ + /* for MacOSX */ \ + || strcmp (Fs_type, "devfs") == 0 \ + || strcmp (Fs_type, "fdesc") == 0 \ + || strcmp (Fs_type, "nfs") == 0 \ + || strcmp (Fs_type, "volfs") == 0) +#endif + +#ifndef ME_REMOTE +/* A file system is `remote' if its Fs_name contains a `:' + or if (it is of type (smbfs or cifs) and its Fs_name starts with `//'). */ +# define ME_REMOTE(Fs_name, Fs_type) \ + (strchr (Fs_name, ':') != NULL \ + || ((Fs_name)[0] == '/' \ + && (Fs_name)[1] == '/' \ + && (strcmp (Fs_type, "smbfs") == 0 \ + || strcmp (Fs_type, "cifs") == 0))) +#endif +#endif // HAIKU / BEOS + +#ifdef MOUNTED_GETMNTINFO + +# if ! HAVE_STRUCT_STATFS_F_FSTYPENAME +static char * +fstype_to_string (short int t) +{ + switch (t) + { +# ifdef MOUNT_PC + case MOUNT_PC: + return "pc"; +# endif +# ifdef MOUNT_MFS + case MOUNT_MFS: + return "mfs"; +# endif +# ifdef MOUNT_LO + case MOUNT_LO: + return "lo"; +# endif +# ifdef MOUNT_TFS + case MOUNT_TFS: + return "tfs"; +# endif +# ifdef MOUNT_TMP + case MOUNT_TMP: + return "tmp"; +# endif +# ifdef MOUNT_UFS + case MOUNT_UFS: + return "ufs" ; +# endif +# ifdef MOUNT_NFS + case MOUNT_NFS: + return "nfs" ; +# endif +# ifdef MOUNT_MSDOS + case MOUNT_MSDOS: + return "msdos" ; +# endif +# ifdef MOUNT_LFS + case MOUNT_LFS: + return "lfs" ; +# endif +# ifdef MOUNT_LOFS + case MOUNT_LOFS: + return "lofs" ; +# endif +# ifdef MOUNT_FDESC + case MOUNT_FDESC: + return "fdesc" ; +# endif +# ifdef MOUNT_PORTAL + case MOUNT_PORTAL: + return "portal" ; +# endif +# ifdef MOUNT_NULL + case MOUNT_NULL: + return "null" ; +# endif +# ifdef MOUNT_UMAP + case MOUNT_UMAP: + return "umap" ; +# endif +# ifdef MOUNT_KERNFS + case MOUNT_KERNFS: + return "kernfs" ; +# endif +# ifdef MOUNT_PROCFS + case MOUNT_PROCFS: + return "procfs" ; +# endif +# ifdef MOUNT_AFS + case MOUNT_AFS: + return "afs" ; +# endif +# ifdef MOUNT_CD9660 + case MOUNT_CD9660: + return "cd9660" ; +# endif +# ifdef MOUNT_UNION + case MOUNT_UNION: + return "union" ; +# endif +# ifdef MOUNT_DEVFS + case MOUNT_DEVFS: + return "devfs" ; +# endif +# ifdef MOUNT_EXT2FS + case MOUNT_EXT2FS: + return "ext2fs" ; +# endif + default: + return "?"; + } +} +# endif + +static char * +fsp_to_string (const struct statfs *fsp) +{ +# if HAVE_STRUCT_STATFS_F_FSTYPENAME + return (char *) (fsp->f_fstypename); +# else + return fstype_to_string (fsp->f_type); +# endif +} + +#endif /* MOUNTED_GETMNTINFO */ + +#ifdef MOUNTED_VMOUNT /* AIX. */ +static char * +fstype_to_string (int t) +{ + struct vfs_ent *e; + + e = getvfsbytype (t); + if (!e || !e->vfsent_name) + return "none"; + else + return e->vfsent_name; +} +#endif /* MOUNTED_VMOUNT */ + + +#if defined MOUNTED_GETMNTENT1 || defined MOUNTED_GETMNTENT2 + +/* Return the device number from MOUNT_OPTIONS, if possible. + Otherwise return (dev_t) -1. */ + +static dev_t +dev_from_mount_options (char const *mount_options) +{ + /* GNU/Linux allows file system implementations to define their own + meaning for "dev=" mount options, so don't trust the meaning + here. */ +# ifndef __linux__ + + static char const dev_pattern[] = ",dev="; + char const *devopt = strstr (mount_options, dev_pattern); + + if (devopt) + { + char const *optval = devopt + sizeof dev_pattern - 1; + char *optvalend; + unsigned long int dev; + errno = 0; + dev = strtoul (optval, &optvalend, 16); + if (optval != optvalend + && (*optvalend == '\0' || *optvalend == ',') + && ! (dev == ULONG_MAX && errno == ERANGE) + && dev == (dev_t) dev) + return dev; + } + +# endif + + return -1; +} + +#endif + +/* Return a list of the currently mounted file systems, or NULL on error. + Add each entry to the tail of the list so that they stay in order. + If NEED_FS_TYPE is true, ensure that the file system type fields in + the returned list are valid. Otherwise, they might not be. */ + +struct mount_entry * +read_file_system_list (bool need_fs_type) +{ + struct mount_entry *mount_list; + struct mount_entry *me; + struct mount_entry **mtail = &mount_list; + +#ifdef MOUNTED_LISTMNTENT + { + struct tabmntent *mntlist, *p; + struct mntent *mnt; + struct mount_entry *me; + + /* the third and fourth arguments could be used to filter mounts, + but Crays doesn't seem to have any mounts that we want to + remove. Specifically, automount create normal NFS mounts. + */ + + if (listmntent (&mntlist, KMTAB, NULL, NULL) < 0) + return NULL; + for (p = mntlist; p; p = p->next) { + mnt = p->ment; + me = xmalloc (sizeof *me); + me->me_devname = xstrdup (mnt->mnt_fsname); + me->me_mountdir = xstrdup (mnt->mnt_dir); + me->me_type = xstrdup (mnt->mnt_type); + me->me_type_malloced = 1; + me->me_dummy = ME_DUMMY (me->me_devname, me->me_type); + me->me_remote = ME_REMOTE (me->me_devname, me->me_type); + me->me_dev = -1; + *mtail = me; + mtail = &me->me_next; + } + freemntlist (mntlist); + } +#endif + +#ifdef MOUNTED_GETMNTENT1 /* GNU/Linux, 4.3BSD, SunOS, HP-UX, Dynix, Irix. */ + { + struct mntent *mnt; + char *table = MOUNTED; + FILE *fp; + + fp = setmntent (table, "r"); + if (fp == NULL) + return NULL; + + while ((mnt = getmntent (fp))) + { + me = malloc (sizeof *me); + me->me_devname = strdup (mnt->mnt_fsname); + me->me_mountdir = strdup (mnt->mnt_dir); + me->me_type = strdup (mnt->mnt_type); + me->me_type_malloced = 1; + me->me_dummy = ME_DUMMY (me->me_devname, me->me_type); + me->me_remote = ME_REMOTE (me->me_devname, me->me_type); + me->me_dev = dev_from_mount_options (mnt->mnt_opts); + + /* Add to the linked list. */ + *mtail = me; + mtail = &me->me_next; + } + + if (endmntent (fp) == 0) + goto free_then_fail; + } +#endif /* MOUNTED_GETMNTENT1. */ + +#ifdef MOUNTED_GETMNTINFO /* 4.4BSD. */ + { + struct statfs *fsp; + int entries; + + entries = getmntinfo (&fsp, MNT_NOWAIT); + if (entries < 0) + return NULL; + for (; entries-- > 0; fsp++) + { + me = malloc (sizeof *me); + me->me_devname = strdup (fsp->f_mntfromname); + me->me_mountdir = strdup (fsp->f_mntonname); +#if defined(__macosx__) + me->me_type = fsp->f_fstypename; +#else + me->me_type = fsp->fs_typename; +#endif + me->me_type_malloced = 0; + me->me_dummy = ME_DUMMY (me->me_devname, me->me_type); + me->me_remote = ME_REMOTE (me->me_devname, me->me_type); + me->me_dev = (dev_t) -1; /* Magic; means not known yet. */ + + /* Add to the linked list. */ + *mtail = me; + mtail = &me->me_next; + } + } +#endif /* MOUNTED_GETMNTINFO */ + +#ifdef MOUNTED_GETMNTINFO2 /* NetBSD 3.0. */ + { + struct statvfs *fsp; + int entries; + + entries = getmntinfo (&fsp, MNT_NOWAIT); + if (entries < 0) + return NULL; + for (; entries-- > 0; fsp++) + { + me = xmalloc (sizeof *me); + me->me_devname = xstrdup (fsp->f_mntfromname); + me->me_mountdir = xstrdup (fsp->f_mntonname); + me->me_type = xstrdup (fsp->f_fstypename); + me->me_type_malloced = 1; + me->me_dummy = ME_DUMMY (me->me_devname, me->me_type); + me->me_remote = ME_REMOTE (me->me_devname, me->me_type); + me->me_dev = (dev_t) -1; /* Magic; means not known yet. */ + + /* Add to the linked list. */ + *mtail = me; + mtail = &me->me_next; + } + } +#endif /* MOUNTED_GETMNTINFO2 */ + +#ifdef MOUNTED_GETMNT /* Ultrix. */ + { + int offset = 0; + int val; + struct fs_data fsd; + + while (errno = 0, + 0 < (val = getmnt (&offset, &fsd, sizeof (fsd), NOSTAT_MANY, + (char *) 0))) + { + me = xmalloc (sizeof *me); + me->me_devname = xstrdup (fsd.fd_req.devname); + me->me_mountdir = xstrdup (fsd.fd_req.path); + me->me_type = gt_names[fsd.fd_req.fstype]; + me->me_type_malloced = 0; + me->me_dummy = ME_DUMMY (me->me_devname, me->me_type); + me->me_remote = ME_REMOTE (me->me_devname, me->me_type); + me->me_dev = fsd.fd_req.dev; + + /* Add to the linked list. */ + *mtail = me; + mtail = &me->me_next; + } + if (val < 0) + goto free_then_fail; + } +#endif /* MOUNTED_GETMNT. */ + +#if defined MOUNTED_FS_STAT_DEV /* BeOS */ + { + /* The next_dev() and fs_stat_dev() system calls give the list of + all file systems, including the information returned by statvfs() + (fs type, total blocks, free blocks etc.), but without the mount + point. But on BeOS all file systems except / are mounted in the + rootfs, directly under /. + The directory name of the mount point is often, but not always, + identical to the volume name of the device. + We therefore get the list of subdirectories of /, and the list + of all file systems, and match the two lists. */ + + DIR *dirp; + struct rootdir_entry + { + char *name; + dev_t dev; + ino_t ino; + struct rootdir_entry *next; + }; + struct rootdir_entry *rootdir_list; + struct rootdir_entry **rootdir_tail; + int32 pos; + dev_t dev; + fs_info fi; + + /* All volumes are mounted in the rootfs, directly under /. */ + rootdir_list = NULL; + rootdir_tail = &rootdir_list; + dirp = opendir ("/"); + if (dirp) + { + struct dirent *d; + + while ((d = readdir (dirp)) != NULL) + { + char *name; + struct stat statbuf; + + if (strcmp (d->d_name, "..") == 0) + continue; + + if (strcmp (d->d_name, ".") == 0) + name = strdup ("/"); + else + { + name = malloc (1 + strlen (d->d_name) + 1); + name[0] = '/'; + strcpy (name + 1, d->d_name); + } + + if (lstat (name, &statbuf) >= 0 && S_ISDIR (statbuf.st_mode)) + { + struct rootdir_entry *re = malloc (sizeof *re); + re->name = name; + re->dev = statbuf.st_dev; + re->ino = statbuf.st_ino; + + /* Add to the linked list. */ + *rootdir_tail = re; + rootdir_tail = &re->next; + } + else + free (name); + } + closedir (dirp); + } + *rootdir_tail = NULL; + + for (pos = 0; (dev = next_dev (&pos)) >= 0; ) + if (fs_stat_dev (dev, &fi) >= 0) + { + /* Note: fi.dev == dev. */ + struct rootdir_entry *re; + + for (re = rootdir_list; re; re = re->next) + if (re->dev == fi.dev && re->ino == fi.root) + break; + + me = malloc (sizeof *me); + me->me_devname = strdup (fi.device_name[0] != '\0' ? fi.device_name : fi.fsh_name); + me->me_mountdir = strdup (re != NULL ? re->name : fi.fsh_name); + me->me_type = strdup (fi.fsh_name); + me->me_type_malloced = 1; + me->me_dev = fi.dev; + me->me_dummy = 0; + me->me_remote = (fi.flags & B_FS_IS_SHARED) != 0; + + /* Add to the linked list. */ + *mtail = me; + mtail = &me->me_next; + } + *mtail = NULL; + + while (rootdir_list != NULL) + { + struct rootdir_entry *re = rootdir_list; + rootdir_list = re->next; + free (re->name); + free (re); + } + } +#endif /* MOUNTED_FS_STAT_DEV */ + +#if defined MOUNTED_GETFSSTAT /* __alpha running OSF_1 */ + { + int numsys, counter; + size_t bufsize; + struct statfs *stats; + + numsys = getfsstat ((struct statfs *)0, 0L, MNT_NOWAIT); + if (numsys < 0) + return (NULL); + if (SIZE_MAX / sizeof *stats <= numsys) + xalloc_die (); + + bufsize = (1 + numsys) * sizeof *stats; + stats = xmalloc (bufsize); + numsys = getfsstat (stats, bufsize, MNT_NOWAIT); + + if (numsys < 0) + { + free (stats); + return (NULL); + } + + for (counter = 0; counter < numsys; counter++) + { + me = xmalloc (sizeof *me); + me->me_devname = xstrdup (stats[counter].f_mntfromname); + me->me_mountdir = xstrdup (stats[counter].f_mntonname); + me->me_type = xstrdup (FS_TYPE (stats[counter])); + me->me_type_malloced = 1; + me->me_dummy = ME_DUMMY (me->me_devname, me->me_type); + me->me_remote = ME_REMOTE (me->me_devname, me->me_type); + me->me_dev = (dev_t) -1; /* Magic; means not known yet. */ + + /* Add to the linked list. */ + *mtail = me; + mtail = &me->me_next; + } + + free (stats); + } +#endif /* MOUNTED_GETFSSTAT */ + +#if defined MOUNTED_FREAD || defined MOUNTED_FREAD_FSTYP /* SVR[23]. */ + { + struct mnttab mnt; + char *table = "/etc/mnttab"; + FILE *fp; + + fp = fopen (table, "r"); + if (fp == NULL) + return NULL; + + while (fread (&mnt, sizeof mnt, 1, fp) > 0) + { + me = xmalloc (sizeof *me); +# ifdef GETFSTYP /* SVR3. */ + me->me_devname = xstrdup (mnt.mt_dev); +# else + me->me_devname = xmalloc (strlen (mnt.mt_dev) + 6); + strcpy (me->me_devname, "/dev/"); + strcpy (me->me_devname + 5, mnt.mt_dev); +# endif + me->me_mountdir = xstrdup (mnt.mt_filsys); + me->me_dev = (dev_t) -1; /* Magic; means not known yet. */ + me->me_type = ""; + me->me_type_malloced = 0; +# ifdef GETFSTYP /* SVR3. */ + if (need_fs_type) + { + struct statfs fsd; + char typebuf[FSTYPSZ]; + + if (statfs (me->me_mountdir, &fsd, sizeof fsd, 0) != -1 + && sysfs (GETFSTYP, fsd.f_fstyp, typebuf) != -1) + { + me->me_type = xstrdup (typebuf); + me->me_type_malloced = 1; + } + } +# endif + me->me_dummy = ME_DUMMY (me->me_devname, me->me_type); + me->me_remote = ME_REMOTE (me->me_devname, me->me_type); + + /* Add to the linked list. */ + *mtail = me; + mtail = &me->me_next; + } + + if (ferror (fp)) + { + /* The last fread() call must have failed. */ + int saved_errno = errno; + fclose (fp); + errno = saved_errno; + goto free_then_fail; + } + + if (fclose (fp) == EOF) + goto free_then_fail; + } +#endif /* MOUNTED_FREAD || MOUNTED_FREAD_FSTYP. */ + +#ifdef MOUNTED_GETMNTTBL /* DolphinOS goes its own way. */ + { + struct mntent **mnttbl = getmnttbl (), **ent; + for (ent=mnttbl;*ent;ent++) + { + me = xmalloc (sizeof *me); + me->me_devname = xstrdup ( (*ent)->mt_resource); + me->me_mountdir = xstrdup ( (*ent)->mt_directory); + me->me_type = xstrdup ((*ent)->mt_fstype); + me->me_type_malloced = 1; + me->me_dummy = ME_DUMMY (me->me_devname, me->me_type); + me->me_remote = ME_REMOTE (me->me_devname, me->me_type); + me->me_dev = (dev_t) -1; /* Magic; means not known yet. */ + + /* Add to the linked list. */ + *mtail = me; + mtail = &me->me_next; + } + endmnttbl (); + } +#endif + +#ifdef MOUNTED_GETMNTENT2 /* SVR4. */ + { + struct mnttab mnt; + char *table = MNTTAB; + FILE *fp; + int ret; + int lockfd = -1; + +# if defined F_RDLCK && defined F_SETLKW + /* MNTTAB_LOCK is a macro name of our own invention; it's not present in + e.g. Solaris 2.6. If the SVR4 folks ever define a macro + for this file name, we should use their macro name instead. + (Why not just lock MNTTAB directly? We don't know.) */ +# ifndef MNTTAB_LOCK +# define MNTTAB_LOCK "/etc/.mnttab.lock" +# endif + lockfd = open (MNTTAB_LOCK, O_RDONLY); + if (0 <= lockfd) + { + struct flock flock; + flock.l_type = F_RDLCK; + flock.l_whence = SEEK_SET; + flock.l_start = 0; + flock.l_len = 0; + while (fcntl (lockfd, F_SETLKW, &flock) == -1) + if (errno != EINTR) + { + int saved_errno = errno; + close (lockfd); + errno = saved_errno; + return NULL; + } + } + else if (errno != ENOENT) + return NULL; +# endif + + errno = 0; + fp = fopen (table, "r"); + if (fp == NULL) + ret = errno; + else + { + while ((ret = getmntent (fp, &mnt)) == 0) + { + me = xmalloc (sizeof *me); + me->me_devname = xstrdup (mnt.mnt_special); + me->me_mountdir = xstrdup (mnt.mnt_mountp); + me->me_type = xstrdup (mnt.mnt_fstype); + me->me_type_malloced = 1; + me->me_dummy = MNT_IGNORE (&mnt) != 0; + me->me_remote = ME_REMOTE (me->me_devname, me->me_type); + me->me_dev = dev_from_mount_options (mnt.mnt_mntopts); + + /* Add to the linked list. */ + *mtail = me; + mtail = &me->me_next; + } + + ret = fclose (fp) == EOF ? errno : 0 < ret ? 0 : -1; + } + + if (0 <= lockfd && close (lockfd) != 0) + ret = errno; + + if (0 <= ret) + { + errno = ret; + goto free_then_fail; + } + } +#endif /* MOUNTED_GETMNTENT2. */ + +#ifdef MOUNTED_VMOUNT /* AIX. */ + { + int bufsize; + char *entries, *thisent; + struct vmount *vmp; + int n_entries; + int i; + + /* Ask how many bytes to allocate for the mounted file system info. */ + if (mntctl (MCTL_QUERY, sizeof bufsize, (struct vmount *) &bufsize) != 0) + return NULL; + entries = xmalloc (bufsize); + + /* Get the list of mounted file systems. */ + n_entries = mntctl (MCTL_QUERY, bufsize, (struct vmount *) entries); + if (n_entries < 0) + { + int saved_errno = errno; + free (entries); + errno = saved_errno; + return NULL; + } + + for (i = 0, thisent = entries; + i < n_entries; + i++, thisent += vmp->vmt_length) + { + char *options, *ignore; + + vmp = (struct vmount *) thisent; + me = xmalloc (sizeof *me); + if (vmp->vmt_flags & MNT_REMOTE) + { + char *host, *dir; + + me->me_remote = 1; + /* Prepend the remote dirname. */ + host = thisent + vmp->vmt_data[VMT_HOSTNAME].vmt_off; + dir = thisent + vmp->vmt_data[VMT_OBJECT].vmt_off; + me->me_devname = xmalloc (strlen (host) + strlen (dir) + 2); + strcpy (me->me_devname, host); + strcat (me->me_devname, ":"); + strcat (me->me_devname, dir); + } + else + { + me->me_remote = 0; + me->me_devname = xstrdup (thisent + + vmp->vmt_data[VMT_OBJECT].vmt_off); + } + me->me_mountdir = xstrdup (thisent + vmp->vmt_data[VMT_STUB].vmt_off); + me->me_type = xstrdup (fstype_to_string (vmp->vmt_gfstype)); + me->me_type_malloced = 1; + options = thisent + vmp->vmt_data[VMT_ARGS].vmt_off; + ignore = strstr (options, "ignore"); + me->me_dummy = (ignore + && (ignore == options || ignore[-1] == ',') + && (ignore[sizeof "ignore" - 1] == ',' + || ignore[sizeof "ignore" - 1] == '\0')); + me->me_dev = (dev_t) -1; /* vmt_fsid might be the info we want. */ + + /* Add to the linked list. */ + *mtail = me; + mtail = &me->me_next; + } + free (entries); + } +#endif /* MOUNTED_VMOUNT. */ + + *mtail = NULL; + return mount_list; + + + free_then_fail: + { + int saved_errno = errno; + *mtail = NULL; + + while (mount_list) + { + me = mount_list->me_next; + free (mount_list->me_devname); + free (mount_list->me_mountdir); + if (mount_list->me_type_malloced) + free (mount_list->me_type); + free (mount_list); + mount_list = me; + } + + errno = saved_errno; + return NULL; + } +} + +#endif + diff --git a/mountlist.h b/mountlist.h index 04ac3535..43a15b21 100644 --- a/mountlist.h +++ b/mountlist.h @@ -1,47 +1,47 @@ -/* mountlist.h -- declarations for list of mounted file systems - - Copyright (C) 1991, 1992, 1998, 2000, 2001, 2002, 2003, 2004, 2005 - Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, see . -*/ - -////////////////////////////////////////////////////////////////////////////// -///@file mountlist.h -/// A function to enumerate the mounting points in the filesystem. -/// Used to display them in fileselectors. -////////////////////////////////////////////////////////////////////////////// - -#ifndef MOUNTLIST_H_ -# define MOUNTLIST_H_ - -# include -# include - -/* A mount table entry. */ -struct mount_entry -{ - char *me_devname; /* Device node name, including "/dev/". */ - char *me_mountdir; /* Mount point directory name. */ - char *me_type; /* "nfs", "4.2", etc. */ - dev_t me_dev; /* Device number of me_mountdir. */ - unsigned int me_dummy : 1; /* Nonzero for dummy file systems. */ - unsigned int me_remote : 1; /* Nonzero for remote fileystems. */ - unsigned int me_type_malloced : 1; /* Nonzero if me_type was malloced. */ - struct mount_entry *me_next; -}; - -struct mount_entry *read_file_system_list (bool need_fs_type); - -#endif +/* mountlist.h -- declarations for list of mounted file systems + + Copyright (C) 1991, 1992, 1998, 2000, 2001, 2002, 2003, 2004, 2005 + Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . +*/ + +////////////////////////////////////////////////////////////////////////////// +///@file mountlist.h +/// A function to enumerate the mounting points in the filesystem. +/// Used to display them in fileselectors. +////////////////////////////////////////////////////////////////////////////// + +#ifndef MOUNTLIST_H_ +# define MOUNTLIST_H_ + +# include +# include + +/* A mount table entry. */ +struct mount_entry +{ + char *me_devname; /* Device node name, including "/dev/". */ + char *me_mountdir; /* Mount point directory name. */ + char *me_type; /* "nfs", "4.2", etc. */ + dev_t me_dev; /* Device number of me_mountdir. */ + unsigned int me_dummy : 1; /* Nonzero for dummy file systems. */ + unsigned int me_remote : 1; /* Nonzero for remote fileystems. */ + unsigned int me_type_malloced : 1; /* Nonzero if me_type was malloced. */ + struct mount_entry *me_next; +}; + +struct mount_entry *read_file_system_list (bool need_fs_type); + +#endif diff --git a/op_c.c b/op_c.c index 687dc260..f2bdee9a 100644 --- a/op_c.c +++ b/op_c.c @@ -1,1219 +1,1291 @@ -/* Grafx2 - The Ultimate 256-color bitmap paint program - - Copyright 2007 Adrien Destugues - Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) - - Grafx2 is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; version 2 - of the License. - - Grafx2 is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Grafx2; if not, see -*/ -#include -#include -#include -#include -#include -#include -#include - -#include "op_c.h" -#include "errors.h" - -void RGB_to_HSL(int r,int g,int b,byte * hr,byte * sr,byte* lr) -{ - double rd,gd,bd,h,s,l,max,min; - - // convert RGB to HSV - rd = r / 255.0; // rd,gd,bd range 0-1 instead of 0-255 - gd = g / 255.0; - bd = b / 255.0; - - // compute L -// l=(rd*0.30)+(gd*0.59)+(bd*0.11); - - // compute maximum of rd,gd,bd - if (rd>=gd) - { - if (rd>=bd) - max = rd; - else - max = bd; - } - else - { - if (gd>=bd) - max = gd; - else - max = bd; - } - - // compute minimum of rd,gd,bd - if (rd<=gd) - { - if (rd<=bd) - min = rd; - else - min = bd; - } - else - { - if (gd<=bd) - min = gd; - else - min = bd; - } - - l = (max + min) / 2.0; - - if(max==min) - s = h = 0; - else - { - if (l<=0.5) - s = (max - min) / (max + min); - else - s = (max - min) / (2 - (max + min)); - - if (max == rd) - h = 42.5 * (gd-bd)/(max-min); - else if (max == gd) - h = 42.5 * (bd-rd)/(max-min)+85; - else - h = 42.5 * (rd-gd)/(max-min)+170; - if (h<0) h+=255; - } - - *hr = h; - *lr = (l*255.0); - *sr = (s*255.0); -} - -void HSL_to_RGB(byte h,byte s,byte l, byte* r, byte* g, byte* b) -{ - float rf =0 ,gf = 0,bf = 0; - float hf,lf,sf; - float p,q; - - if(s==0) - { - *r=*g=*b=l; - return; - } - - hf = h / 255.0; - lf = l / 255.0; - sf = s / 255.0; - - if (lf<=0.5) - q = lf*(1+sf); - else - q = lf+sf-lf*sf; - p = 2*lf-q; - - rf = hf + (1 / 3.0); - gf = hf; - bf = hf - (1 / 3.0); - - if (rf < 0) rf+=1; - if (rf > 1) rf-=1; - if (gf < 0) gf+=1; - if (gf > 1) gf-=1; - if (bf < 0) bf+=1; - if (bf > 1) bf-=1; - - if (rf < 1/6.0) - rf = p + ((q-p)*6*rf); - else if(rf < 0.5) - rf = q; - else if(rf < 2/3.0) - rf = p + ((q-p)*6*(2/3.0-rf)); - else - rf = p; - - if (gf < 1/6.0) - gf = p + ((q-p)*6*gf); - else if(gf < 0.5) - gf = q; - else if(gf < 2/3.0) - gf = p + ((q-p)*6*(2/3.0-gf)); - else - gf = p; - - if (bf < 1/6.0) - bf = p + ((q-p)*6*bf); - else if(bf < 0.5) - bf = q; - else if(bf < 2/3.0) - bf = p + ((q-p)*6*(2/3.0-bf)); - else - bf = p; - - *r = rf * (255); - *g = gf * (255); - *b = bf * (255); -} - -///////////////////////////////////////////////////////////////////////////// -///////////////////////////// Méthodes de gestion des tables de conversion // -///////////////////////////////////////////////////////////////////////////// - -T_Conversion_table * CT_new(int nbb_r,int nbb_g,int nbb_b) -{ - T_Conversion_table * n; - int size; - - n=(T_Conversion_table *)malloc(sizeof(T_Conversion_table)); - if (n!=NULL) - { - // On recopie les paramŠtres demand‚s - n->nbb_r=nbb_r; - n->nbb_g=nbb_g; - n->nbb_b=nbb_b; - - // On calcule les autres - n->rng_r=(1<rng_g=(1<rng_b=(1<dec_r=nbb_g+nbb_b; - n->dec_g=nbb_b; - n->dec_b=0; - n->red_r=8-nbb_r; - n->red_g=8-nbb_g; - n->red_b=8-nbb_b; - - // On tente d'allouer la table - size=(n->rng_r)*(n->rng_g)*(n->rng_b); - n->table=(byte *)malloc(size); - if (n->table!=NULL) - // C'est bon! - memset(n->table,0,size); // Inutile, mais plus propre - else - { - // Table impossible … allouer - free(n); - n=NULL; - } - } - - return n; -} - -void CT_delete(T_Conversion_table * t) -{ - free(t->table); - free(t); -} - -byte CT_get(T_Conversion_table * t,int r,int g,int b) -{ - int index; - - // On réduit le nombre de bits par couleur - r=(r>>t->red_r); - g=(g>>t->red_g); - b=(b>>t->red_b); - - // On recherche la couleur la plus proche dans la table de conversion - index=(r<dec_r) | (g<dec_g) | (b<dec_b); - - return t->table[index]; -} - -void CT_set(T_Conversion_table * t,int r,int g,int b,byte i) -{ - int index; - - index=(r<dec_r) | (g<dec_g) | (b<dec_b); - t->table[index]=i; -} - - - -///////////////////////////////////////////////////////////////////////////// -/////////////////////////////// M‚thodes de gestion des tables d'occurence // -///////////////////////////////////////////////////////////////////////////// - -void OT_init(T_Occurrence_table * t) -{ - int size; - - size=(t->rng_r)*(t->rng_g)*(t->rng_b)*sizeof(int); - memset(t->table,0,size); // On initialise … 0 -} - -T_Occurrence_table * OT_new(int nbb_r,int nbb_g,int nbb_b) -{ - T_Occurrence_table * n; - int size; - - n=(T_Occurrence_table *)malloc(sizeof(T_Occurrence_table)); - if (n!=0) - { - // On recopie les paramŠtres demand‚s - n->nbb_r=nbb_r; - n->nbb_g=nbb_g; - n->nbb_b=nbb_b; - - // On calcule les autres - n->rng_r=(1<rng_g=(1<rng_b=(1<dec_r=nbb_g+nbb_b; - n->dec_g=nbb_b; - n->dec_b=0; - n->red_r=8-nbb_r; - n->red_g=8-nbb_g; - n->red_b=8-nbb_b; - - // On tente d'allouer la table - size=(n->rng_r)*(n->rng_g)*(n->rng_b)*sizeof(int); - n->table=(int *)malloc(size); - if (n->table!=0) - // C'est bon! On initialise … 0 - OT_init(n); - else - { - // Table impossible … allouer - free(n); - n=0; - } - } - - return n; -} - -void OT_delete(T_Occurrence_table * t) -{ - free(t->table); - free(t); -} - -int OT_get(T_Occurrence_table * t,int r,int g,int b) -{ - int index; - - index=(r<dec_r) | (g<dec_g) | (b<dec_b); - return t->table[index]; -} - -void OT_inc(T_Occurrence_table * t,int r,int g,int b) -{ - int index; - - r=(r>>t->red_r); - g=(g>>t->red_g); - b=(b>>t->red_b); - index=(r<dec_r) | (g<dec_g) | (b<dec_b); - t->table[index]++; -} - -void OT_count_occurrences(T_Occurrence_table * t,T_Bitmap24B image,int size) -{ - T_Bitmap24B ptr; - int index; - - for (index=size,ptr=image;index>0;index--,ptr++) - OT_inc(t,ptr->R,ptr->G,ptr->B); -} - -int OT_count_colors(T_Occurrence_table * t) -{ - int val; // Valeur de retour - int nb; // Nombre de couleurs … tester - int i; // Compteur de couleurs test‚es - - val=0; - nb=(t->rng_r)*(t->rng_g)*(t->rng_b); - for (i=0;itable[i]>0) - val++; - - return val; -} - - - -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////// M‚thodes de gestion des clusters // -///////////////////////////////////////////////////////////////////////////// - -void Cluster_analyser(T_Cluster * c,T_Occurrence_table * to) -{ - int rmin,rmax,vmin,vmax,bmin,bmax; - int r,g,b; - - // On cherche les mins et les maxs de chaque composante sur la couverture - - // int nbocc; - - // On prédécale tout pour éviter de faire trop de bazar en se forçant à utiliser OT_get, plus rapide - rmin=c->rmax <<16; rmax=c->rmin << 16; - vmin=c->vmax << 8; vmax=c->vmin << 8; - bmin=c->bmax; bmax=c->bmin; - c->occurences=0; - /* - for (r=c->rmin<<16;r<=c->rmax<<16;r+=1<<16) - for (g=c->vmin<<8;g<=c->vmax<<8;g+=1<<8) - for (b=c->bmin;b<=c->bmax;b++) - { - nbocc=to->table[r + g + b]; // OT_get - if (nbocc) - { - if (rrmax) rmax=r; - if (gvmax) vmax=g; - if (bbmax) bmax=b; - c->occurences+=nbocc; - } - } - */ - - // On recherche le minimum et le maximum en parcourant le cluster selon chaque composante, - // ça évite des accès mémoires inutiles, de plus chaque boucle est plus petite que la - // précédente puisqu'on connait une borne supplémentaire - - for(r=c->rmin<<16;r<=c->rmax<<16;r+=1<<16) - for(g=c->vmin<<8;g<=c->vmax<<8;g+=1<<8) - for(b=c->bmin;b<=c->bmax;b++) - { - if(to->table[r + g + b]) // OT_get - { - rmin=r; - goto RMAX; - } - } -RMAX: - for(r=c->rmax<<16;r>=rmin;r-=1<<16) - for(g=c->vmin<<8;g<=c->vmax<<8;g+=1<<8) - for(b=c->bmin;b<=c->bmax;b++) - { - if(to->table[r + g + b]) // OT_get - { - rmax=r; - goto VMIN; - } - } -VMIN: - for(g=c->vmin<<8;g<=c->vmax<<8;g+=1<<8) - for(r=rmin;r<=rmax;r+=1<<16) - for(b=c->bmin;b<=c->bmax;b++) - { - if(to->table[r + g + b]) // OT_get - { - vmin=g; - goto VMAX; - } - } -VMAX: - for(g=c->vmax<<8;g>=vmin;g-=1<<8) - for(r=rmin;r<=rmax;r+=1<<16) - for(b=c->bmin;b<=c->bmax;b++) - { - if(to->table[r + g + b]) // OT_get - { - vmax=g; - goto BMIN; - } - } -BMIN: - for(b=c->bmin;b<=c->bmax;b++) - for(r=rmin;r<=rmax;r+=1<<16) - for(g=vmin;g<=vmax;g+=1<<8) - { - if(to->table[r + g + b]) // OT_get - { - bmin=b; - goto BMAX; - } - } -BMAX: - for(b=c->bmax;b>=bmin;b--) - for(r=rmin;r<=rmax;r+=1<<16) - for(g=vmin;g<=vmax;g+=1<<8) - { - if(to->table[r + g + b]) // OT_get - { - bmax=b; - goto ENDCRUSH; - } - } -ENDCRUSH: - // Il faut quand même parcourir la partie utile du cluster, pour savoir combien il y a d'occurences - for(r=rmin;r<=rmax;r+=1<<16) - for(g=vmin;g<=vmax;g+=1<<8) - for(b=bmin;b<=bmax;b++) - { - c->occurences+=to->table[r + g + b]; // OT_get - } - - c->rmin=rmin>>16; c->rmax=rmax>>16; - c->vmin=vmin>>8; c->vmax=vmax>>8; - c->bmin=bmin; c->bmax=bmax; - - // On regarde la composante qui a la variation la plus grande - r=(c->rmax-c->rmin)*299; - g=(c->vmax-c->vmin)*587; - b=(c->bmax-c->bmin)*114; - - if (g>=r) - { - // G>=R - if (g>=b) - { - // G>=R et G>=B - c->plus_large=1; - } - else - { - // G>=R et Gplus_large=2; - } - } - else - { - // R>G - if (r>=b) - { - // R>G et R>=B - c->plus_large=0; - } - else - { - // R>G et Rplus_large=2; - } - } -} - -void Cluster_split(T_Cluster * c,T_Cluster * c1,T_Cluster * c2,int hue,T_Occurrence_table * to) -{ - int limit; - int cumul; - int r,g,b; - - limit=(c->occurences)/2; - cumul=0; - if (hue==0) - { - for (r=c->rmin<<16;r<=c->rmax<<16;r+=1<<16) - { - for (g=c->vmin<<8;g<=c->vmax<<8;g+=1<<8) - { - for (b=c->bmin;b<=c->bmax;b++) - { - cumul+=to->table[r + g + b]; - if (cumul>=limit) - break; - } - if (cumul>=limit) - break; - } - if (cumul>=limit) - break; - } - - r>>=16; - g>>=8; - - if (r==c->rmin) - r++; - // R est la valeur de d‚but du 2nd cluster - - c1->Rmin=c->Rmin; c1->Rmax=r-1; - c1->rmin=c->rmin; c1->rmax=r-1; - c1->Gmin=c->Gmin; c1->Vmax=c->Vmax; - c1->vmin=c->vmin; c1->vmax=c->vmax; - c1->Bmin=c->Bmin; c1->Bmax=c->Bmax; - c1->bmin=c->bmin; c1->bmax=c->bmax; - c2->Rmin=r; c2->Rmax=c->Rmax; - c2->rmin=r; c2->rmax=c->rmax; - c2->Gmin=c->Gmin; c2->Vmax=c->Vmax; - c2->vmin=c->vmin; c2->vmax=c->vmax; - c2->Bmin=c->Bmin; c2->Bmax=c->Bmax; - c2->bmin=c->bmin; c2->bmax=c->bmax; - } - else - if (hue==1) - { - - for (g=c->vmin<<8;g<=c->vmax<<8;g+=1<<8) - { - for (r=c->rmin<<16;r<=c->rmax<<16;r+=1<<16) - { - for (b=c->bmin;b<=c->bmax;b++) - { - cumul+=to->table[r + g + b]; - if (cumul>=limit) - break; - } - if (cumul>=limit) - break; - } - if (cumul>=limit) - break; - } - - r>>=16; g>>=8; - - if (g==c->vmin) - g++; - // G est la valeur de d‚but du 2nd cluster - - c1->Rmin=c->Rmin; c1->Rmax=c->Rmax; - c1->rmin=c->rmin; c1->rmax=c->rmax; - c1->Gmin=c->Gmin; c1->Vmax=g-1; - c1->vmin=c->vmin; c1->vmax=g-1; - c1->Bmin=c->Bmin; c1->Bmax=c->Bmax; - c1->bmin=c->bmin; c1->bmax=c->bmax; - c2->Rmin=c->Rmin; c2->Rmax=c->Rmax; - c2->rmin=c->rmin; c2->rmax=c->rmax; - c2->Gmin=g; c2->Vmax=c->Vmax; - c2->vmin=g; c2->vmax=c->vmax; - c2->Bmin=c->Bmin; c2->Bmax=c->Bmax; - c2->bmin=c->bmin; c2->bmax=c->bmax; - } - else - { - - for (b=c->bmin;b<=c->bmax;b++) - { - for (g=c->vmin<<8;g<=c->vmax<<8;g+=1<<8) - { - for (r=c->rmin<<16;r<=c->rmax<<16;r+=1<<16) - { - cumul+=to->table[r + g + b]; - if (cumul>=limit) - break; - } - if (cumul>=limit) - break; - } - if (cumul>=limit) - break; - } - - r>>=16; g>>=8; - - if (b==c->bmin) - b++; - // B est la valeur de d‚but du 2nd cluster - - c1->Rmin=c->Rmin; c1->Rmax=c->Rmax; - c1->rmin=c->rmin; c1->rmax=c->rmax; - c1->Gmin=c->Gmin; c1->Vmax=c->Vmax; - c1->vmin=c->vmin; c1->vmax=c->vmax; - c1->Bmin=c->Bmin; c1->Bmax=b-1; - c1->bmin=c->bmin; c1->bmax=b-1; - c2->Rmin=c->Rmin; c2->Rmax=c->Rmax; - c2->rmin=c->rmin; c2->rmax=c->rmax; - c2->Gmin=c->Gmin; c2->Vmax=c->Vmax; - c2->vmin=c->vmin; c2->vmax=c->vmax; - c2->Bmin=b; c2->Bmax=c->Bmax; - c2->bmin=b; c2->bmax=c->bmax; - } -} - -void Cluster_compute_hue(T_Cluster * c,T_Occurrence_table * to) -{ - int cumul_r,cumul_g,cumul_b; - int r,g,b; - int nbocc; - - byte s=0; - - cumul_r=cumul_g=cumul_b=0; - for (r=c->rmin;r<=c->rmax;r++) - for (g=c->vmin;g<=c->vmax;g++) - for (b=c->bmin;b<=c->bmax;b++) - { - nbocc=OT_get(to,r,g,b); - if (nbocc) - { - cumul_r+=r*nbocc; - cumul_g+=g*nbocc; - cumul_b+=b*nbocc; - } - } - - c->r=(cumul_r<red_r)/c->occurences; - c->g=(cumul_g<red_g)/c->occurences; - c->b=(cumul_b<red_b)/c->occurences; - RGB_to_HSL(c->r,c->g,c->b,&c->h,&s,&c->l); -} - - - -///////////////////////////////////////////////////////////////////////////// -//////////////////////////// M‚thodes de gestion des ensembles de clusters // -///////////////////////////////////////////////////////////////////////////// - -void CS_Init(T_Cluster_set * cs,T_Occurrence_table * to) -{ - cs->clusters[0].Rmin=cs->clusters[0].rmin=0; - cs->clusters[0].Gmin=cs->clusters[0].vmin=0; - cs->clusters[0].Bmin=cs->clusters[0].bmin=0; - cs->clusters[0].Rmax=cs->clusters[0].rmax=to->rng_r-1; - cs->clusters[0].Vmax=cs->clusters[0].vmax=to->rng_g-1; - cs->clusters[0].Bmax=cs->clusters[0].bmax=to->rng_b-1; - Cluster_analyser(cs->clusters+0,to); - // Et hop : le 1er ensemble de couleurs est initialis‚ - cs->nb=1; -} - -T_Cluster_set * CS_New(int nbmax,T_Occurrence_table * to) -{ - T_Cluster_set * n; - - n=(T_Cluster_set *)malloc(sizeof(T_Cluster_set)); - if (n!=0) - { - // On recopie les paramŠtres demand‚s - n->nb_max=OT_count_colors(to); - - // On vient de compter le nombre de couleurs existantes, s'il est plus grand que 256 on limit à 256 (nombre de couleurs voulu au final) - if (n->nb_max>nbmax) - { - n->nb_max=nbmax; - } - - // On tente d'allouer la table - n->clusters=(T_Cluster *)malloc(nbmax*sizeof(T_Cluster)); - if (n->clusters!=NULL) - // C'est bon! On initialise - CS_Init(n,to); - else - { - // Table impossible … allouer - free(n); - n=0; - } - } - - return n; -} - -void CS_Delete(T_Cluster_set * cs) -{ - free(cs->clusters); - free(cs); -} - -void CS_Get(T_Cluster_set * cs,T_Cluster * c) -{ - int index; - - // On cherche un cluster que l'on peut couper en deux, donc avec au moins deux valeurs - // différentes sur l'une des composantes - for (index=0;indexnb;index++) - if ( (cs->clusters[index].rminclusters[index].rmax) || - (cs->clusters[index].vminclusters[index].vmax) || - (cs->clusters[index].bminclusters[index].bmax) ) - break; - - // On le recopie dans c - *c=cs->clusters[index]; - - // On décrémente le nombre et on décale tous les clusters suivants - // Sachant qu'on va réinsérer juste après, il me semble que ça serait une bonne idée de gérer les clusters - // comme une liste chainée... on n'a aucun accès direct dedans, que des parcours ... - cs->nb--; - memcpy((cs->clusters+index),(cs->clusters+index+1),(cs->nb-index)*sizeof(T_Cluster)); -} - -void CS_Set(T_Cluster_set * cs,T_Cluster * c) -{ - int index; - // int decalage; - - // Le tableau des clusters est trié par nombre d'occurences. Donc on cherche la position du premier cluster - // qui est plus grand que le notre - for (index=0;indexnb;index++) - if (cs->clusters[index].occurencesoccurences) -/* - if (((OPTPAL_Cluster[index].rmax-OPTPAL_Cluster[index].rmin+1)* - (OPTPAL_Cluster[index].gmax-OPTPAL_Cluster[index].gmin+1)* - (OPTPAL_Cluster[index].bmax-OPTPAL_Cluster[index].bmin+1)) - < - ((Set->rmax-Set->rmin+1)* - (Set->gmax-Set->gmin+1)* - (Set->bmax-Set->bmin+1)) - ) -*/ - break; - - if (indexnb) - { - // On distingue ici une insertion plutot qu'un placement en fin de liste. - // On doit donc décaler les ensembles suivants vers la fin pour se faire - // une place dans la liste. - - //for (decalage=cs->nb;decalage>index;decalage--) - // memcpy((cs->clusters+decalage),(cs->clusters+decalage-1),sizeof(T_Cluster)); - memmove(cs->clusters+index+1,cs->clusters+index,(cs->nb-index)*sizeof(T_Cluster)); - } - - cs->clusters[index]=*c; - cs->nb++; -} - -// Détermination de la meilleure palette en utilisant l'algo Median Cut : -// 1) On considère l'espace (R,G,B) comme 1 boîte -// 2) On cherche les extrêmes de la boîte en (R,G,B) -// 3) On trie les pixels de l'image selon l'axe le plus long parmi (R,G,B) -// 4) On coupe la boîte en deux au milieu, et on compacte pour que chaque bord corresponde bien à un pixel extreme -// 5) On recommence à couper selon le plus grand axe toutes boîtes confondues -// 6) On s'arrête quand on a le nombre de couleurs voulu -void CS_Generate(T_Cluster_set * cs,T_Occurrence_table * to) -{ - T_Cluster current; - T_Cluster Nouveau1; - T_Cluster Nouveau2; - - // Tant qu'on a moins de 256 clusters - while (cs->nbnb_max) - { - // On récupère le plus grand cluster - CS_Get(cs,¤t); - - // On le coupe en deux - Cluster_split(¤t,&Nouveau1,&Nouveau2,current.plus_large,to); - - // On compacte ces deux nouveaux (il peut y avoir un espace entre l'endroit de la coupure et les premiers pixels du cluster) - Cluster_analyser(&Nouveau1,to); - Cluster_analyser(&Nouveau2,to); - - // On met ces deux nouveaux clusters dans le clusterSet... sauf s'ils sont vides - if(Nouveau1.occurences>0) - CS_Set(cs,&Nouveau1); - if(Nouveau2.occurences>0) - CS_Set(cs,&Nouveau2); - } -} - -void CS_Compute_colors(T_Cluster_set * cs,T_Occurrence_table * to) -{ - int index; - T_Cluster * c; - - for (index=0,c=cs->clusters;indexnb;index++,c++) - Cluster_compute_hue(c,to); -} - -void CS_Sort_by_chrominance(T_Cluster_set * cs) -{ - int byte_used[256]; - int decalages[256]; - int index; - T_Cluster * nc; - - nc=(T_Cluster *)malloc(cs->nb_max*sizeof(T_Cluster)); - - // Initialisation de la table d'occurence de chaque octet - for (index=0;index<256;index++) - byte_used[index]=0; - - // Comptage du nombre d'occurences de chaque octet - for (index=0;indexnb;index++) - byte_used[cs->clusters[index].h]++; - - // Calcul de la table des d‚calages - decalages[0]=0; - for (index=1;index<256;index++) - decalages[index]=decalages[index-1]+byte_used[index-1]; - - // Copie r‚ordonn‚e dans la nouvelle liste - for (index=0;indexnb;index++) - { - nc[decalages[cs->clusters[index].h]]=cs->clusters[index]; - decalages[cs->clusters[index].h]++; - } - - // Remplacement de la liste d‚sordonn‚e par celle tri‚e - free(cs->clusters); - cs->clusters=nc; -} - -void CS_Sort_by_luminance(T_Cluster_set * cs) -{ - int byte_used[256]; - int decalages[256]; - int index; - T_Cluster * nc; - - nc=(T_Cluster *)malloc(cs->nb_max*sizeof(T_Cluster)); - - // Initialisation de la table d'occurence de chaque octet - for (index=0;index<256;index++) - byte_used[index]=0; - - // Comptage du nombre d'occurences de chaque octet - for (index=0;indexnb;index++) - byte_used[cs->clusters[index].l]++; - - // Calcul de la table des d‚calages - decalages[0]=0; - for (index=1;index<256;index++) - decalages[index]=decalages[index-1]+byte_used[index-1]; - - // Copie r‚ordonn‚e dans la nouvelle liste - for (index=0;indexnb;index++) - { - nc[decalages[cs->clusters[index].l]]=cs->clusters[index]; - decalages[cs->clusters[index].l]++; - } - - // Remplacement de la liste d‚sordonn‚e par celle tri‚e - free(cs->clusters); - cs->clusters=nc; -} - -void CS_Generate_color_table_and_palette(T_Cluster_set * cs,T_Conversion_table * tc,T_Components * palette) -{ - int index; - int r,g,b; - - for (index=0;indexnb;index++) - { - palette[index].R=cs->clusters[index].r; - palette[index].G=cs->clusters[index].g; - palette[index].B=cs->clusters[index].b; - - for (r=cs->clusters[index].Rmin;r<=cs->clusters[index].Rmax;r++) - for (g=cs->clusters[index].Gmin;g<=cs->clusters[index].Vmax;g++) - for (b=cs->clusters[index].Bmin;b<=cs->clusters[index].Bmax;b++) - CT_set(tc,r,g,b,index); - } -} - -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////// Méthodes de gestion des dégradés // -///////////////////////////////////////////////////////////////////////////// - -void GS_Init(T_Gradient_set * ds,T_Cluster_set * cs) -{ - ds->gradients[0].nb_colors=1; - ds->gradients[0].min=cs->clusters[0].h; - ds->gradients[0].max=cs->clusters[0].h; - ds->gradients[0].hue=cs->clusters[0].h; - // Et hop : le 1er ensemble de d‚grad‚s est initialis‚ - ds->nb=1; -} - -T_Gradient_set * GS_New(T_Cluster_set * cs) -{ - T_Gradient_set * n; - - n=(T_Gradient_set *)malloc(sizeof(T_Gradient_set)); - if (n!=NULL) - { - // On recopie les paramŠtres demand‚s - n->nb_max=cs->nb_max; - - // On tente d'allouer la table - n->gradients=(T_Gradient *)malloc((n->nb_max)*sizeof(T_Gradient)); - if (n->gradients!=0) - // C'est bon! On initialise - GS_Init(n,cs); - else - { - // Table impossible … allouer - free(n); - n=0; - } - } - - return n; -} - -void GS_Delete(T_Gradient_set * ds) -{ - free(ds->gradients); - free(ds); -} - -void GS_Generate(T_Gradient_set * ds,T_Cluster_set * cs) -{ - int ic,id; // Les indexs de parcours des ensembles - int best_gradient; // Meilleur d‚grad‚ - int best_diff; // Meilleure diff‚rence de chrominance - int diff; // difference de chrominance courante - - // Pour chacun des clusters … traiter - for (ic=0;icnb;ic++) - { - // On recherche le d‚grad‚ le plus proche de la chrominance du cluster - best_gradient=-1; - best_diff=99999999; - for (id=0;idnb;id++) - { - diff=abs(cs->clusters[ic].h - ds->gradients[id].hue); - if ((best_diff>diff) && (diff<16)) - { - best_gradient=id; - best_diff=diff; - } - } - - // Si on a trouv‚ un d‚grad‚ dans lequel inclure le cluster - if (best_gradient!=-1) - { - // On met … jour le d‚grad‚ - if (cs->clusters[ic].h < ds->gradients[best_gradient].min) - ds->gradients[best_gradient].min=cs->clusters[ic].h; - if (cs->clusters[ic].h > ds->gradients[best_gradient].max) - ds->gradients[best_gradient].max=cs->clusters[ic].h; - ds->gradients[best_gradient].hue=((ds->gradients[best_gradient].hue* - ds->gradients[best_gradient].nb_colors) - +cs->clusters[ic].h) - /(ds->gradients[best_gradient].nb_colors+1); - ds->gradients[best_gradient].nb_colors++; - } - else - { - // On cr‚e un nouveau d‚grad‚ - best_gradient=ds->nb; - ds->gradients[best_gradient].nb_colors=1; - ds->gradients[best_gradient].min=cs->clusters[ic].h; - ds->gradients[best_gradient].max=cs->clusters[ic].h; - ds->gradients[best_gradient].hue=cs->clusters[ic].h; - ds->nb++; - } - cs->clusters[ic].h=best_gradient; - } - - // On redistribue les valeurs dans les clusters - for (ic=0;icnb;ic++) - cs->clusters[ic].h=ds->gradients[cs->clusters[ic].h].hue; -} - - - - -T_Conversion_table * Optimize_palette(T_Bitmap24B image,int size,T_Components * palette,int r,int g,int b) -{ - T_Occurrence_table * to; - T_Conversion_table * tc; - T_Cluster_set * cs; - T_Gradient_set * ds; - - // Création des éléments nécessaires au calcul de palette optimisée: - to=0; tc=0; cs=0; ds=0; - - to=OT_new(r,g,b); - if (to!=0) - { - tc=CT_new(r,g,b); - if (tc!=0) - { - - // Première étape : on compte les pixels de chaque couleur pour pouvoir trier là dessus - OT_count_occurrences(to,image,size); - - cs=CS_New(256,to); - if (cs!=0) - { - // C'est bon, on a pu tout allouer - - // On génère les clusters (avec l'algo du median cut) - CS_Generate(cs,to); - - // On calcule la teinte de chaque pixel (Luminance et chrominance) - CS_Compute_colors(cs,to); - - ds=GS_New(cs); - if (ds!=0) - { - GS_Generate(ds,cs); - GS_Delete(ds); - } - - // Enfin on trie les clusters (donc les couleurs de la palette) dans un ordre sympa : par couleur, et par luminosité pour chaque couleur - CS_Sort_by_luminance(cs); - CS_Sort_by_chrominance(cs); - - // Enfin on génère la palette et la table de correspondance entre chaque couleur 24b et sa couleur palette associée. - CS_Generate_color_table_and_palette(cs,tc,palette); - - CS_Delete(cs); - OT_delete(to); - return tc; - } - CT_delete(tc); - } - OT_delete(to); - } - // Si on arrive ici c'est que l'allocation n'a pas réussi, - // l'appelant devra recommencer avec une précision plus faible (3 derniers paramètres) - return 0; -} - -int Modified_value(int value,int modif) -{ - value+=modif; - if (value<0) - { - value=0; - } - else if (value>255) - { - value=255; - } - return value; -} - -void Convert_24b_bitmap_to_256_Floyd_Steinberg(T_Bitmap256 dest,T_Bitmap24B source,int width,int height,T_Components * palette,T_Conversion_table * tc) -// Cette fonction dégrade au fur et à mesure le bitmap source, donc soit on ne -// s'en ressert pas, soit on passe à la fonction une copie de travail du -// bitmap original. -{ - T_Bitmap24B current; - T_Bitmap24B c_plus1; - T_Bitmap24B u_minus1; - T_Bitmap24B next; - T_Bitmap24B u_plus1; - T_Bitmap256 d; - int x_pos,y_pos; - int red,green,blue; - float e_red,e_green,e_blue; - - // On initialise les variables de parcours: - current =source; // Le pixel dont on s'occupe - next =current+width; // Le pixel en dessous - c_plus1 =current+1; // Le pixel à droite - u_minus1=next-1; // Le pixel en bas à gauche - u_plus1 =next+1; // Le pixel en bas à droite - d =dest; - - // On parcours chaque pixel: - for (y_pos=0;y_posR; - green =current->G; - blue =current->B; - // Cherche la couleur correspondant dans la palette et la range dans l'image de destination - *d=CT_get(tc,red,green,blue); - - // Puis on calcule pour chaque composante l'erreur dûe à l'approximation - red-=palette[*d].R; - green -=palette[*d].G; - blue -=palette[*d].B; - - // Et dans chaque pixel voisin on propage l'erreur - // A droite: - e_red=(red*7)/16.0; - e_green =(green *7)/16.0; - e_blue =(blue *7)/16.0; - if (x_pos+1R=Modified_value(c_plus1->R,e_red); - c_plus1->G=Modified_value(c_plus1->G,e_green ); - c_plus1->B=Modified_value(c_plus1->B,e_blue ); - } - // En bas à gauche: - if (y_pos+10) - { - u_minus1->R=Modified_value(u_minus1->R,e_red); - u_minus1->G=Modified_value(u_minus1->G,e_green ); - u_minus1->B=Modified_value(u_minus1->B,e_blue ); - } - // En bas: - e_red=(red*5/16.0); - e_green =(green*5 /16.0); - e_blue =(blue*5 /16.0); - next->R=Modified_value(next->R,e_red); - next->G=Modified_value(next->G,e_green ); - next->B=Modified_value(next->B,e_blue ); - // En bas à droite: - if (x_pos+1R=Modified_value(u_plus1->R,e_red); - u_plus1->G=Modified_value(u_plus1->G,e_green ); - u_plus1->B=Modified_value(u_plus1->B,e_blue ); - } - } - - // On passe au pixel suivant : - current++; - c_plus1++; - u_minus1++; - next++; - u_plus1++; - d++; - } - } - -} - - - -static const byte precision_24b[]= -{ - 8,8,8, - 6,6,6, - 6,6,5, - 5,6,5, - 5,5,5, - 5,5,4, - 4,5,4, - 4,4,4, - 4,4,3, - 3,4,3, - 3,3,3, - 3,3,2}; - - -// Convertie avec le plus de précision possible une image 24b en 256c -// Renvoie s'il y a eu une erreur ou pas.. - -// Cette fonction utilise l'algorithme "median cut" (Optimize_palette) pour trouver la palette, et diffuse les erreurs avec floyd-steinberg. - -int Convert_24b_bitmap_to_256(T_Bitmap256 dest,T_Bitmap24B source,int width,int height,T_Components * palette) -{ - T_Conversion_table * table; // table de conversion - int ip; // index de précision pour la conversion - - // On essaye d'obtenir une table de conversion qui loge en mémoire, avec la - // meilleure précision possible - for (ip=0;ip<(10*3);ip+=3) - { - table=Optimize_palette(source,width*height,palette,precision_24b[ip+0], - precision_24b[ip+1],precision_24b[ip+2]); - if (table!=0) - break; - } - - if (table!=0) - { - Convert_24b_bitmap_to_256_Floyd_Steinberg(dest,source,width,height,palette,table); - CT_delete(table); - return 0; - } - else - return 1; -} - - - +/* Grafx2 - The Ultimate 256-color bitmap paint program + + Copyright 2007 Adrien Destugues + Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) + + Grafx2 is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 + of the License. + + Grafx2 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grafx2; if not, see +*/ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "op_c.h" +#include "errors.h" + +void RGB_to_HSL(int r,int g,int b,byte * hr,byte * sr,byte* lr) +{ + double rd,gd,bd,h,s,l,max,min; + + // convert RGB to HSV + rd = r / 255.0; // rd,gd,bd range 0-1 instead of 0-255 + gd = g / 255.0; + bd = b / 255.0; + + // compute L +// l=(rd*0.30)+(gd*0.59)+(bd*0.11); + + // compute maximum of rd,gd,bd + if (rd>=gd) + { + if (rd>=bd) + max = rd; + else + max = bd; + } + else + { + if (gd>=bd) + max = gd; + else + max = bd; + } + + // compute minimum of rd,gd,bd + if (rd<=gd) + { + if (rd<=bd) + min = rd; + else + min = bd; + } + else + { + if (gd<=bd) + min = gd; + else + min = bd; + } + + l = (max + min) / 2.0; + + if(max==min) + s = h = 0; + else + { + if (l<=0.5) + s = (max - min) / (max + min); + else + s = (max - min) / (2 - (max + min)); + + if (max == rd) + h = 42.5 * (gd-bd)/(max-min); + else if (max == gd) + h = 42.5 * (bd-rd)/(max-min)+85; + else + h = 42.5 * (rd-gd)/(max-min)+170; + if (h<0) h+=255; + } + + *hr = h; + *lr = (l*255.0); + *sr = (s*255.0); +} + +void HSL_to_RGB(byte h,byte s,byte l, byte* r, byte* g, byte* b) +{ + float rf =0 ,gf = 0,bf = 0; + float hf,lf,sf; + float p,q; + + if(s==0) + { + *r=*g=*b=l; + return; + } + + hf = h / 255.0; + lf = l / 255.0; + sf = s / 255.0; + + if (lf<=0.5) + q = lf*(1+sf); + else + q = lf+sf-lf*sf; + p = 2*lf-q; + + rf = hf + (1 / 3.0); + gf = hf; + bf = hf - (1 / 3.0); + + if (rf < 0) rf+=1; + if (rf > 1) rf-=1; + if (gf < 0) gf+=1; + if (gf > 1) gf-=1; + if (bf < 0) bf+=1; + if (bf > 1) bf-=1; + + if (rf < 1/6.0) + rf = p + ((q-p)*6*rf); + else if(rf < 0.5) + rf = q; + else if(rf < 2/3.0) + rf = p + ((q-p)*6*(2/3.0-rf)); + else + rf = p; + + if (gf < 1/6.0) + gf = p + ((q-p)*6*gf); + else if(gf < 0.5) + gf = q; + else if(gf < 2/3.0) + gf = p + ((q-p)*6*(2/3.0-gf)); + else + gf = p; + + if (bf < 1/6.0) + bf = p + ((q-p)*6*bf); + else if(bf < 0.5) + bf = q; + else if(bf < 2/3.0) + bf = p + ((q-p)*6*(2/3.0-bf)); + else + bf = p; + + *r = rf * (255); + *g = gf * (255); + *b = bf * (255); +} + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////// Méthodes de gestion des tables de conversion // +///////////////////////////////////////////////////////////////////////////// + +T_Conversion_table * CT_new(int nbb_r,int nbb_g,int nbb_b) +{ + T_Conversion_table * n; + int size; + + n=(T_Conversion_table *)malloc(sizeof(T_Conversion_table)); + if (n!=NULL) + { + // On recopie les paramŠtres demand‚s + n->nbb_r=nbb_r; + n->nbb_g=nbb_g; + n->nbb_b=nbb_b; + + // On calcule les autres + n->rng_r=(1<rng_g=(1<rng_b=(1<dec_r=nbb_g+nbb_b; + n->dec_g=nbb_b; + n->dec_b=0; + n->red_r=8-nbb_r; + n->red_g=8-nbb_g; + n->red_b=8-nbb_b; + + // On tente d'allouer la table + size=(n->rng_r)*(n->rng_g)*(n->rng_b); + n->table=(byte *)malloc(size); + if (n->table!=NULL) + // C'est bon! + memset(n->table,0,size); // Inutile, mais plus propre + else + { + // Table impossible … allouer + free(n); + n=NULL; + } + } + + return n; +} + +void CT_delete(T_Conversion_table * t) +{ + free(t->table); + free(t); +} + +byte CT_get(T_Conversion_table * t,int r,int g,int b) +{ + int index; + + // On réduit le nombre de bits par couleur + r=(r>>t->red_r); + g=(g>>t->red_g); + b=(b>>t->red_b); + + // On recherche la couleur la plus proche dans la table de conversion + index=(r<dec_r) | (g<dec_g) | (b<dec_b); + + return t->table[index]; +} + +void CT_set(T_Conversion_table * t,int r,int g,int b,byte i) +{ + int index; + + index=(r<dec_r) | (g<dec_g) | (b<dec_b); + t->table[index]=i; +} + + + +///////////////////////////////////////////////////////////////////////////// +/////////////////////////////// M‚thodes de gestion des tables d'occurence // +///////////////////////////////////////////////////////////////////////////// + +void OT_init(T_Occurrence_table * t) +{ + int size; + + size=(t->rng_r)*(t->rng_g)*(t->rng_b)*sizeof(int); + memset(t->table,0,size); // On initialise … 0 +} + +T_Occurrence_table * OT_new(int nbb_r,int nbb_g,int nbb_b) +{ + T_Occurrence_table * n; + int size; + + n=(T_Occurrence_table *)malloc(sizeof(T_Occurrence_table)); + if (n!=0) + { + // On recopie les paramŠtres demand‚s + n->nbb_r=nbb_r; + n->nbb_g=nbb_g; + n->nbb_b=nbb_b; + + // On calcule les autres + n->rng_r=(1<rng_g=(1<rng_b=(1<dec_r=nbb_g+nbb_b; + n->dec_g=nbb_b; + n->dec_b=0; + n->red_r=8-nbb_r; + n->red_g=8-nbb_g; + n->red_b=8-nbb_b; + + // On tente d'allouer la table + size=(n->rng_r)*(n->rng_g)*(n->rng_b)*sizeof(int); + n->table=(int *)malloc(size); + if (n->table!=0) + // C'est bon! On initialise … 0 + OT_init(n); + else + { + // Table impossible … allouer + free(n); + n=0; + } + } + + return n; +} + +void OT_delete(T_Occurrence_table * t) +{ + free(t->table); + free(t); +} + +int OT_get(T_Occurrence_table * t,int r,int g,int b) +{ + int index; + + index=(r<dec_r) | (g<dec_g) | (b<dec_b); + return t->table[index]; +} + +void OT_inc(T_Occurrence_table * t,int r,int g,int b) +{ + int index; + + r=(r>>t->red_r); + g=(g>>t->red_g); + b=(b>>t->red_b); + index=(r<dec_r) | (g<dec_g) | (b<dec_b); + t->table[index]++; +} + +void OT_count_occurrences(T_Occurrence_table* t, T_Bitmap24B image, int size) +{ + T_Bitmap24B ptr; + int index; + + for (index = size, ptr = image; index > 0; index--, ptr++) + OT_inc(t, ptr->R, ptr->G, ptr->B); +} + +int OT_count_colors(T_Occurrence_table * t) +{ + int val; // Valeur de retour + int nb; // Nombre de couleurs … tester + int i; // Compteur de couleurs test‚es + + val = 0; + nb=(t->rng_r)*(t->rng_g)*(t->rng_b); + for (i = 0; i < nb; i++) + if (t->table[i]>0) + val++; + + return val; +} + + + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////// M‚thodes de gestion des clusters // +///////////////////////////////////////////////////////////////////////////// + +void Cluster_pack(T_Cluster * c,T_Occurrence_table * to) +{ + int rmin,rmax,vmin,vmax,bmin,bmax; + int r,g,b; + + // On cherche les mins et les maxs de chaque composante sur la couverture + + // int nbocc; + + // On prédécale tout pour éviter de faire trop de bazar en se forçant à utiliser OT_get, plus rapide + rmin=c->rmax <<16; rmax=c->rmin << 16; + vmin=c->vmax << 8; vmax=c->vmin << 8; + bmin=c->bmax; bmax=c->bmin; + c->occurences=0; + /* + for (r=c->rmin<<16;r<=c->rmax<<16;r+=1<<16) + for (g=c->vmin<<8;g<=c->vmax<<8;g+=1<<8) + for (b=c->bmin;b<=c->bmax;b++) + { + nbocc=to->table[r + g + b]; // OT_get + if (nbocc) + { + if (rrmax) rmax=r; + if (gvmax) vmax=g; + if (bbmax) bmax=b; + c->occurences+=nbocc; + } + } + */ + + // On recherche le minimum et le maximum en parcourant le cluster selon chaque composante, + // ça évite des accès mémoires inutiles, de plus chaque boucle est plus petite que la + // précédente puisqu'on connait une borne supplémentaire + + for(r=c->rmin<<16;r<=c->rmax<<16;r+=1<<16) + for(g=c->vmin<<8;g<=c->vmax<<8;g+=1<<8) + for(b=c->bmin;b<=c->bmax;b++) + { + if(to->table[r + g + b]) // OT_get + { + rmin=r; + goto RMAX; + } + } +RMAX: + for(r=c->rmax<<16;r>=rmin;r-=1<<16) + for(g=c->vmin<<8;g<=c->vmax<<8;g+=1<<8) + for(b=c->bmin;b<=c->bmax;b++) + { + if(to->table[r + g + b]) // OT_get + { + rmax=r; + goto VMIN; + } + } +VMIN: + for(g=c->vmin<<8;g<=c->vmax<<8;g+=1<<8) + for(r=rmin;r<=rmax;r+=1<<16) + for(b=c->bmin;b<=c->bmax;b++) + { + if(to->table[r + g + b]) // OT_get + { + vmin=g; + goto VMAX; + } + } +VMAX: + for(g=c->vmax<<8;g>=vmin;g-=1<<8) + for(r=rmin;r<=rmax;r+=1<<16) + for(b=c->bmin;b<=c->bmax;b++) + { + if(to->table[r + g + b]) // OT_get + { + vmax=g; + goto BMIN; + } + } +BMIN: + for(b=c->bmin;b<=c->bmax;b++) + for(r=rmin;r<=rmax;r+=1<<16) + for(g=vmin;g<=vmax;g+=1<<8) + { + if(to->table[r + g + b]) // OT_get + { + bmin=b; + goto BMAX; + } + } +BMAX: + for(b=c->bmax;b>=bmin;b--) + for(r=rmin;r<=rmax;r+=1<<16) + for(g=vmin;g<=vmax;g+=1<<8) + { + if(to->table[r + g + b]) // OT_get + { + bmax=b; + goto ENDCRUSH; + } + } +ENDCRUSH: + // Il faut quand même parcourir la partie utile du cluster, pour savoir combien il y a d'occurences + for(r=rmin;r<=rmax;r+=1<<16) + for(g=vmin;g<=vmax;g+=1<<8) + for(b=bmin;b<=bmax;b++) + { + c->occurences+=to->table[r + g + b]; // OT_get + } + + c->rmin=rmin>>16; c->rmax=rmax>>16; + c->vmin=vmin>>8; c->vmax=vmax>>8; + c->bmin=bmin; c->bmax=bmax; + + // On regarde la composante qui a la variation la plus grande + r=(c->rmax-c->rmin)*299; + g=(c->vmax-c->vmin)*587; + b=(c->bmax-c->bmin)*114; + + if (g>=r) + { + // G>=R + if (g>=b) + { + // G>=R et G>=B + c->plus_large=1; + } + else + { + // G>=R et Gplus_large=2; + } + } + else + { + // R>G + if (r>=b) + { + // R>G et R>=B + c->plus_large=0; + } + else + { + // R>G et Rplus_large=2; + } + } +} + +void Cluster_split(T_Cluster * c, T_Cluster * c1, T_Cluster * c2, int hue, + T_Occurrence_table * to) +{ + int limit; + int cumul; + int r, g, b; + + limit = c->occurences / 2; + cumul = 0; + if (hue == 0) + { + for (r = c->rmin<<16; r<=c->rmax<<16; r+=1<<16) + { + for (g = c->vmin<<8; g<=c->vmax<<8; g+=1<<8) + { + for (b = c->bmin; b<=c->bmax; b++) + { + cumul+=to->table[r + g + b]; + if (cumul>=limit) + break; + } + if (cumul>=limit) + break; + } + if (cumul>=limit) + break; + } + + r>>=16; + g>>=8; + + if (r==c->rmin) + r++; + // R est la valeur de d‚but du 2nd cluster + + c1->Rmin=c->Rmin; c1->Rmax=r-1; + c1->rmin=c->rmin; c1->rmax=r-1; + c1->Gmin=c->Gmin; c1->Vmax=c->Vmax; + c1->vmin=c->vmin; c1->vmax=c->vmax; + c1->Bmin=c->Bmin; c1->Bmax=c->Bmax; + c1->bmin=c->bmin; c1->bmax=c->bmax; + + c2->Rmin=r; c2->Rmax=c->Rmax; + c2->rmin=r; c2->rmax=c->rmax; + c2->Gmin=c->Gmin; c2->Vmax=c->Vmax; + c2->vmin=c->vmin; c2->vmax=c->vmax; + c2->Bmin=c->Bmin; c2->Bmax=c->Bmax; + c2->bmin=c->bmin; c2->bmax=c->bmax; + } + else + if (hue==1) + { + + for (g=c->vmin<<8;g<=c->vmax<<8;g+=1<<8) + { + for (r=c->rmin<<16;r<=c->rmax<<16;r+=1<<16) + { + for (b=c->bmin;b<=c->bmax;b++) + { + cumul+=to->table[r + g + b]; + if (cumul>=limit) + break; + } + if (cumul>=limit) + break; + } + if (cumul>=limit) + break; + } + + r>>=16; g>>=8; + + if (g==c->vmin) + g++; + // G est la valeur de d‚but du 2nd cluster + + c1->Rmin=c->Rmin; c1->Rmax=c->Rmax; + c1->rmin=c->rmin; c1->rmax=c->rmax; + c1->Gmin=c->Gmin; c1->Vmax=g-1; + c1->vmin=c->vmin; c1->vmax=g-1; + c1->Bmin=c->Bmin; c1->Bmax=c->Bmax; + c1->bmin=c->bmin; c1->bmax=c->bmax; + + c2->Rmin=c->Rmin; c2->Rmax=c->Rmax; + c2->rmin=c->rmin; c2->rmax=c->rmax; + c2->Gmin=g; c2->Vmax=c->Vmax; + c2->vmin=g; c2->vmax=c->vmax; + c2->Bmin=c->Bmin; c2->Bmax=c->Bmax; + c2->bmin=c->bmin; c2->bmax=c->bmax; + } + else + { + + for (b=c->bmin;b<=c->bmax;b++) + { + for (g=c->vmin<<8;g<=c->vmax<<8;g+=1<<8) + { + for (r=c->rmin<<16;r<=c->rmax<<16;r+=1<<16) + { + cumul+=to->table[r + g + b]; + if (cumul>=limit) + break; + } + if (cumul>=limit) + break; + } + if (cumul>=limit) + break; + } + + r>>=16; g>>=8; + + if (b==c->bmin) + b++; + // B est la valeur de d‚but du 2nd cluster + + c1->Rmin=c->Rmin; c1->Rmax=c->Rmax; + c1->rmin=c->rmin; c1->rmax=c->rmax; + c1->Gmin=c->Gmin; c1->Vmax=c->Vmax; + c1->vmin=c->vmin; c1->vmax=c->vmax; + c1->Bmin=c->Bmin; c1->Bmax=b-1; + c1->bmin=c->bmin; c1->bmax=b-1; + + c2->Rmin=c->Rmin; c2->Rmax=c->Rmax; + c2->rmin=c->rmin; c2->rmax=c->rmax; + c2->Gmin=c->Gmin; c2->Vmax=c->Vmax; + c2->vmin=c->vmin; c2->vmax=c->vmax; + c2->Bmin=b; c2->Bmax=c->Bmax; + c2->bmin=b; c2->bmax=c->bmax; + } +} + +void Cluster_compute_hue(T_Cluster * c,T_Occurrence_table * to) +{ + int cumul_r,cumul_g,cumul_b; + int r,g,b; + int nbocc; + + byte s=0; + + cumul_r=cumul_g=cumul_b=0; + for (r=c->rmin;r<=c->rmax;r++) + for (g=c->vmin;g<=c->vmax;g++) + for (b=c->bmin;b<=c->bmax;b++) + { + nbocc=OT_get(to,r,g,b); + if (nbocc) + { + cumul_r+=r*nbocc; + cumul_g+=g*nbocc; + cumul_b+=b*nbocc; + } + } + + c->r=(cumul_r<red_r)/c->occurences; + c->g=(cumul_g<red_g)/c->occurences; + c->b=(cumul_b<red_b)/c->occurences; + RGB_to_HSL(c->r, c->g, c->b, &c->h, &s, &c->l); +} + + + +///////////////////////////////////////////////////////////////////////////// +//////////////////////////// M‚thodes de gestion des ensembles de clusters // +///////////////////////////////////////////////////////////////////////////// + +// Debug helper : check if a cluster set has the right count value +/* +void CS_Check(T_Cluster_set* cs) +{ + int i; + T_Cluster* c = cs->clusters; + for (i = cs->nb; i > 0; i--) + { + assert( c != NULL); + c = c->next; + } + + assert(c == NULL); +} +*/ + +/// Setup the first cluster before we start the operations +void CS_Init(T_Cluster_set * cs, T_Occurrence_table * to) +{ + cs->clusters->Rmin = cs->clusters->rmin = 0; + cs->clusters->Gmin = cs->clusters->vmin = 0; + cs->clusters->Bmin = cs->clusters->bmin = 0; + cs->clusters->Rmax = cs->clusters->rmax = to->rng_r - 1; + cs->clusters->Vmax = cs->clusters->vmax = to->rng_g - 1; + cs->clusters->Bmax = cs->clusters->bmax = to->rng_b - 1; + cs->clusters->next = NULL; + Cluster_pack(cs->clusters, to); + cs->nb = 1; +} + +/// Allocate a new cluster set +T_Cluster_set * CS_New(int nbmax, T_Occurrence_table * to) +{ + T_Cluster_set * n; + + n=(T_Cluster_set *)malloc(sizeof(T_Cluster_set)); + if (n != NULL) + { + // On recopie les paramŠtres demand‚s + n->nb_max = OT_count_colors(to); + + // On vient de compter le nombre de couleurs existantes, s'il est plus grand + // que 256 on limite à 256 + // (nombre de couleurs voulu au final) + if (n->nb_max > nbmax) + { + n->nb_max = nbmax; + } + + // On tente d'allouer le premier cluster + n->clusters=(T_Cluster *)malloc(sizeof(T_Cluster)); + if (n->clusters != NULL) + // C'est bon! On initialise + CS_Init(n, to); + else + { + // Table impossible … allouer + free(n); + n = NULL; + } + } + + return n; +} + +/// Free a cluster set +void CS_Delete(T_Cluster_set * cs) +{ + T_Cluster* nxt; + while (cs->clusters != NULL) + { + nxt = cs->clusters->next; + free(cs->clusters); + cs->clusters = nxt; + } + free(cs); +} + +void CS_Get(T_Cluster_set * cs, T_Cluster * c) +{ + T_Cluster* current = cs->clusters; + T_Cluster* prev = NULL; + + // Search a cluster with at least 2 distinct colors so we can split it + do + { + if ( (current->rmin < current->rmax) || + (current->vmin < current->vmax) || + (current->bmin < current->bmax) ) + break; + + prev = current; + + } while((current = current -> next)); + + // copy it to c + *c = *current; + + // remove it from the list + cs->nb--; + + if(prev) + prev->next = current->next; + else + cs->clusters = current->next; + free(current); + current = NULL; +} + +void CS_Set(T_Cluster_set * cs,T_Cluster * c) +{ + T_Cluster* current = cs->clusters; + T_Cluster* prev = NULL; + + // Search the first cluster that is smaller than ours + while (current && current->occurences > c->occurences) + { + prev = current; + current = current->next; + } + + // Now insert our cluster just before the one we found + c -> next = current; + + current = malloc(sizeof(T_Cluster)); + *current = *c ; + + if (prev) prev->next = current; + else cs->clusters = current; + + cs->nb++; +} + +// Détermination de la meilleure palette en utilisant l'algo Median Cut : +// 1) On considère l'espace (R,G,B) comme 1 boîte +// 2) On cherche les extrêmes de la boîte en (R,G,B) +// 3) On trie les pixels de l'image selon l'axe le plus long parmi (R,G,B) +// 4) On coupe la boîte en deux au milieu, et on compacte pour que chaque bord +// corresponde bien à un pixel extreme +// 5) On recommence à couper selon le plus grand axe toutes boîtes confondues +// 6) On s'arrête quand on a le nombre de couleurs voulu +void CS_Generate(T_Cluster_set * cs, T_Occurrence_table * to) +{ + T_Cluster current; + T_Cluster Nouveau1; + T_Cluster Nouveau2; + + // Tant qu'on a moins de 256 clusters + while (cs->nbnb_max) + { + // On récupère le plus grand cluster + CS_Get(cs,¤t); + + // On le coupe en deux + Cluster_split(¤t, &Nouveau1, &Nouveau2, current.plus_large, to); + + // On compacte ces deux nouveaux (il peut y avoir un espace entre l'endroit + // de la coupure et les premiers pixels du cluster) + Cluster_pack(&Nouveau1, to); + Cluster_pack(&Nouveau2, to); + + // On les remet dans le set + CS_Set(cs,&Nouveau1); + CS_Set(cs,&Nouveau2); + } +} + +void CS_Compute_colors(T_Cluster_set * cs, T_Occurrence_table * to) +{ + T_Cluster * c; + + for (c=cs->clusters;c!=NULL;c=c->next) + Cluster_compute_hue(c,to); +} + +void CS_Sort_by_chrominance(T_Cluster_set * cs) +{ + T_Cluster* nc; + T_Cluster* prev = NULL; + T_Cluster* place; + T_Cluster* newlist = NULL; + + while (cs->clusters) + { + // Remove the first cluster from the original list + nc = cs->clusters; + cs->clusters = cs->clusters->next; + + // Find his position in the new list + for (place = newlist; place != NULL; place = place->next) + { + if (place->h > nc->h) break; + prev = place; + } + + // Chain it there + nc->next = place; + if (prev) prev->next = nc; + else newlist = nc; + + prev = NULL; + } + + // Put the new list bavk in place + cs->clusters = newlist; +} + +void CS_Sort_by_luminance(T_Cluster_set * cs) +{ + T_Cluster* nc; + T_Cluster* prev = NULL; + T_Cluster* place; + T_Cluster* newlist = NULL; + + while (cs->clusters) + { + // Remove the first cluster from the original list + nc = cs->clusters; + cs->clusters = cs->clusters->next; + + // Find its position in the new list + for (place = newlist; place != NULL; place = place->next) + { + if (place->l > nc->l) break; + prev = place; + } + + // Chain it there + nc->next = place; + if (prev) prev->next = nc; + else newlist = nc; + + // reset prev pointer + prev = NULL; + } + + // Put the new list back in place + cs->clusters = newlist; +} + +void CS_Generate_color_table_and_palette(T_Cluster_set * cs,T_Conversion_table * tc,T_Components * palette) +{ + int index; + int r,g,b; + T_Cluster* current = cs->clusters; + + for (index=0;indexnb;index++) + { + palette[index].R=current->r; + palette[index].G=current->g; + palette[index].B=current->b; + + for (r=current->Rmin; r<=current->Rmax; r++) + for (g=current->Gmin;g<=current->Vmax;g++) + for (b=current->Bmin;b<=current->Bmax;b++) + CT_set(tc,r,g,b,index); + current = current->next; + } +} + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////// Méthodes de gestion des dégradés // +///////////////////////////////////////////////////////////////////////////// + +void GS_Init(T_Gradient_set * ds,T_Cluster_set * cs) +{ + ds->gradients[0].nb_colors=1; + ds->gradients[0].min=cs->clusters->h; + ds->gradients[0].max=cs->clusters->h; + ds->gradients[0].hue=cs->clusters->h; + // Et hop : le 1er ensemble de d‚grad‚s est initialis‚ + ds->nb=1; +} + +T_Gradient_set * GS_New(T_Cluster_set * cs) +{ + T_Gradient_set * n; + + n=(T_Gradient_set *)malloc(sizeof(T_Gradient_set)); + if (n!=NULL) + { + // On recopie les paramŠtres demand‚s + n->nb_max=cs->nb_max; + + // On tente d'allouer la table + n->gradients=(T_Gradient *)malloc((n->nb_max)*sizeof(T_Gradient)); + if (n->gradients!=0) + // C'est bon! On initialise + GS_Init(n,cs); + else + { + // Table impossible … allouer + free(n); + n=0; + } + } + + return n; +} + +void GS_Delete(T_Gradient_set * ds) +{ + free(ds->gradients); + free(ds); +} + +void GS_Generate(T_Gradient_set * ds,T_Cluster_set * cs) +{ + int id; // Les indexs de parcours des ensembles + int best_gradient; // Meilleur d‚grad‚ + int best_diff; // Meilleure diff‚rence de chrominance + int diff; // difference de chrominance courante + T_Cluster * current = cs->clusters; + + // Pour chacun des clusters … traiter + do + { + // On recherche le d‚grad‚ le plus proche de la chrominance du cluster + best_gradient=-1; + best_diff=99999999; + for (id=0;idnb;id++) + { + diff=abs(current->h - ds->gradients[id].hue); + if ((best_diff>diff) && (diff<16)) + { + best_gradient=id; + best_diff=diff; + } + } + + // Si on a trouv‚ un d‚grad‚ dans lequel inclure le cluster + if (best_gradient!=-1) + { + // On met … jour le d‚grad‚ + if (current->h < ds->gradients[best_gradient].min) + ds->gradients[best_gradient].min=current->h; + if (current->h > ds->gradients[best_gradient].max) + ds->gradients[best_gradient].max=current->h; + ds->gradients[best_gradient].hue=((ds->gradients[best_gradient].hue* + ds->gradients[best_gradient].nb_colors) + +current->h) + /(ds->gradients[best_gradient].nb_colors+1); + ds->gradients[best_gradient].nb_colors++; + } + else + { + // On cr‚e un nouveau d‚grad‚ + best_gradient=ds->nb; + ds->gradients[best_gradient].nb_colors=1; + ds->gradients[best_gradient].min=current->h; + ds->gradients[best_gradient].max=current->h; + ds->gradients[best_gradient].hue=current->h; + ds->nb++; + } + current->h=best_gradient; + } while((current = current->next)); + + // On redistribue les valeurs dans les clusters + current = cs -> clusters; + do + current->h=ds->gradients[current->h].hue; + while((current = current ->next)); +} + + + + +T_Conversion_table * Optimize_palette(T_Bitmap24B image, int size, + T_Components * palette, int r, int g, int b) +{ + T_Occurrence_table * to; + T_Conversion_table * tc; + T_Cluster_set * cs; + T_Gradient_set * ds; + + // Création des éléments nécessaires au calcul de palette optimisée: + to = 0; tc = 0; cs = 0; ds = 0; + + to = OT_new(r, g, b); + if (to == NULL) + return 0; + + tc = CT_new(r, g, b); + if (tc == NULL) + { + OT_delete(to); + return 0; + } + + // Première étape : on compte les pixels de chaque couleur pour pouvoir trier là dessus + OT_count_occurrences(to, image, size); + + cs = CS_New(256, to); + if (cs == NULL) + { + CT_delete(tc); + OT_delete(to); + return 0; + } + //CS_Check(cs); + // C'est bon, on a pu tout allouer + + // On génère les clusters (avec l'algo du median cut) + CS_Generate(cs, to); + //CS_Check(cs); + + // On calcule la teinte de chaque pixel (Luminance et chrominance) + CS_Compute_colors(cs, to); + //CS_Check(cs); + + ds = GS_New(cs); + if (ds!= NULL) + { + GS_Generate(ds, cs); + GS_Delete(ds); + } + // Enfin on trie les clusters (donc les couleurs de la palette) dans un ordre + // sympa : par couleur, et par luminosité pour chaque couleur + CS_Sort_by_luminance(cs); + //CS_Check(cs); + CS_Sort_by_chrominance(cs); + //CS_Check(cs); + + // Enfin on génère la palette et la table de correspondance entre chaque + // couleur 24b et sa couleur palette associée. + CS_Generate_color_table_and_palette(cs, tc, palette); + //CS_Check(cs); + + CS_Delete(cs); + OT_delete(to); + return tc; +} + +int Modified_value(int value,int modif) +{ + value+=modif; + if (value<0) + { + value=0; + } + else if (value>255) + { + value=255; + } + return value; +} + +void Convert_24b_bitmap_to_256_Floyd_Steinberg(T_Bitmap256 dest,T_Bitmap24B source,int width,int height,T_Components * palette,T_Conversion_table * tc) +// Cette fonction dégrade au fur et à mesure le bitmap source, donc soit on ne +// s'en ressert pas, soit on passe à la fonction une copie de travail du +// bitmap original. +{ + T_Bitmap24B current; + T_Bitmap24B c_plus1; + T_Bitmap24B u_minus1; + T_Bitmap24B next; + T_Bitmap24B u_plus1; + T_Bitmap256 d; + int x_pos,y_pos; + int red,green,blue; + float e_red,e_green,e_blue; + + // On initialise les variables de parcours: + current =source; // Le pixel dont on s'occupe + next =current+width; // Le pixel en dessous + c_plus1 =current+1; // Le pixel à droite + u_minus1=next-1; // Le pixel en bas à gauche + u_plus1 =next+1; // Le pixel en bas à droite + d =dest; + + // On parcours chaque pixel: + for (y_pos=0;y_posR; + green =current->G; + blue =current->B; + // Cherche la couleur correspondant dans la palette et la range dans l'image de destination + *d=CT_get(tc,red,green,blue); + + // Puis on calcule pour chaque composante l'erreur dûe à l'approximation + red-=palette[*d].R; + green -=palette[*d].G; + blue -=palette[*d].B; + + // Et dans chaque pixel voisin on propage l'erreur + // A droite: + e_red=(red*7)/16.0; + e_green =(green *7)/16.0; + e_blue =(blue *7)/16.0; + if (x_pos+1R=Modified_value(c_plus1->R,e_red); + c_plus1->G=Modified_value(c_plus1->G,e_green ); + c_plus1->B=Modified_value(c_plus1->B,e_blue ); + } + // En bas à gauche: + if (y_pos+10) + { + u_minus1->R=Modified_value(u_minus1->R,e_red); + u_minus1->G=Modified_value(u_minus1->G,e_green ); + u_minus1->B=Modified_value(u_minus1->B,e_blue ); + } + // En bas: + e_red=(red*5/16.0); + e_green =(green*5 /16.0); + e_blue =(blue*5 /16.0); + next->R=Modified_value(next->R,e_red); + next->G=Modified_value(next->G,e_green ); + next->B=Modified_value(next->B,e_blue ); + // En bas à droite: + if (x_pos+1R=Modified_value(u_plus1->R,e_red); + u_plus1->G=Modified_value(u_plus1->G,e_green ); + u_plus1->B=Modified_value(u_plus1->B,e_blue ); + } + } + + // On passe au pixel suivant : + current++; + c_plus1++; + u_minus1++; + next++; + u_plus1++; + d++; + } + } +} + +void Convert_24b_bitmap_to_256_nearest_neighbor(T_Bitmap256 dest, + T_Bitmap24B source, int width, int height, T_Components * palette, + T_Conversion_table * tc) +{ + T_Bitmap24B current; + T_Bitmap256 d; + int x_pos, y_pos; + int red, green, blue; + + // On initialise les variables de parcours: + current =source; // Le pixel dont on s'occupe + + d =dest; + + // On parcours chaque pixel: + for (y_pos = 0; y_pos < height; y_pos++) + { + for (x_pos = 0 ;x_pos < width; x_pos++) + { + // On prends la meilleure couleur de la palette qui traduit la couleur + // 24 bits de la source: + red = current->R; + green = current->G; + blue = current->B; + // Cherche la couleur correspondant dans la palette et la range dans + // l'image de destination + *d = CT_get(tc, red, green, blue); + + // On passe au pixel suivant : + current++; + d++; + } + } +} + + +static const byte precision_24b[]= +{ + 8,8,8, + 6,6,6, + 6,6,5, + 5,6,5, + 5,5,5, + 5,5,4, + 4,5,4, + 4,4,4, + 4,4,3, + 3,4,3, + 3,3,3, + 3,3,2}; + + +// Convertie avec le plus de précision possible une image 24b en 256c +// Renvoie s'il y a eu une erreur ou pas.. + +// Cette fonction utilise l'algorithme "median cut" (Optimize_palette) pour trouver la palette, et diffuse les erreurs avec floyd-steinberg. + +int Convert_24b_bitmap_to_256(T_Bitmap256 dest,T_Bitmap24B source,int width,int height,T_Components * palette) +{ + T_Conversion_table * table; // table de conversion + int ip; // index de précision pour la conversion + + // On essaye d'obtenir une table de conversion qui loge en mémoire, avec la + // meilleure précision possible + for (ip=0;ip<(10*3);ip+=3) + { + table=Optimize_palette(source,width*height,palette,precision_24b[ip+0], + precision_24b[ip+1],precision_24b[ip+2]); + if (table!=0) + break; + } + + if (table!=0) + { + //Convert_24b_bitmap_to_256_Floyd_Steinberg(dest,source,width,height,palette,table); + Convert_24b_bitmap_to_256_nearest_neighbor(dest,source,width,height,palette,table); + CT_delete(table); + return 0; + } + else + return 1; +} + + + diff --git a/op_c.h b/op_c.h index ebd943fe..4f12fa30 100644 --- a/op_c.h +++ b/op_c.h @@ -1,213 +1,215 @@ -/* Grafx2 - The Ultimate 256-color bitmap paint program - - Copyright 2007 Adrien Destugues - Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) - - Grafx2 is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; version 2 - of the License. - - Grafx2 is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Grafx2; if not, see -*/ - -////////////////////////////////////////////////////////////////////////////// -///@file op_c.h -/// Color reduction and color conversion (24b->8b, RGB<->HSL). -/// This is called op_c because half of the process was originally -/// coded in op_asm, in assembler. -////////////////////////////////////////////////////////////////////////////// - -#ifndef _OP_C_H_ -#define _OP_C_H_ - -#include "struct.h" - -//////////////////////////////////////////////// Définition des types de base - -typedef T_Components * T_Bitmap24B; -typedef byte * T_Bitmap256; - - - -//////////////////////////////////////// Définition d'une table de conversion - -typedef struct -{ - int nbb_r; // Nb de bits de précision sur les rouges - int nbb_g; // Nb de bits de précision sur les verts - int nbb_b; // Nb de bits de précision sur les bleu - - int rng_r; // Nb de valeurs sur les rouges (= 1< +*/ + +////////////////////////////////////////////////////////////////////////////// +///@file op_c.h +/// Color reduction and color conversion (24b->8b, RGB<->HSL). +/// This is called op_c because half of the process was originally +/// coded in op_asm, in assembler. +////////////////////////////////////////////////////////////////////////////// + +#ifndef _OP_C_H_ +#define _OP_C_H_ + +#include "struct.h" + +//////////////////////////////////////////////// Définition des types de base + +typedef T_Components * T_Bitmap24B; +typedef byte * T_Bitmap256; + + + +//////////////////////////////////////// Définition d'une table de conversion + +typedef struct +{ + int nbb_r; // Nb de bits de précision sur les rouges + int nbb_g; // Nb de bits de précision sur les verts + int nbb_b; // Nb de bits de précision sur les bleu + + int rng_r; // Nb de valeurs sur les rouges (= 1< -*/ -#include -#include -#include - -#include "const.h" -#include "struct.h" -#include "global.h" -#include "misc.h" -#include "engine.h" -#include "graph.h" -#include "operatio.h" -#include "buttons.h" -#include "pages.h" -#include "errors.h" -#include "sdlscreen.h" -#include "brush.h" -#include "windows.h" - -#if defined(__GP2X__) - #define M_PI 3.14159265358979323846 -#endif - -/// Time (in SDL ticks) when the next airbrush drawing should be done. Also used for discontinuous freehand drawing. -Uint32 Airbrush_next_time; - -void Start_operation_stack(word new_operation) -{ - Brush_rotation_center_is_defined=0; - - // On mémorise l'opération précédente si on démarre une interruption - switch(new_operation) - { - case OPERATION_MAGNIFY : - case OPERATION_COLORPICK : - case OPERATION_GRAB_BRUSH : - case OPERATION_POLYBRUSH : - case OPERATION_STRETCH_BRUSH : - case OPERATION_ROTATE_BRUSH: - Operation_before_interrupt=Current_operation; - // On passe à l'operation demandée - Current_operation=new_operation; - break; - default : - // On passe à l'operation demandée - Current_operation=new_operation; - Operation_before_interrupt=Current_operation; - } - - // On spécifie si l'opération autorise le changement de couleur au clavier - switch(new_operation) - { - case OPERATION_CONTINUOUS_DRAW: - case OPERATION_DISCONTINUOUS_DRAW: - case OPERATION_AIRBRUSH: - case OPERATION_CENTERED_LINES: - Allow_color_change_during_operation=1; - break; - default : - Allow_color_change_during_operation=0; - } - - // Et on passe au curseur qui va avec - Cursor_shape=CURSOR_FOR_OPERATION[new_operation]; - Operation_stack_size=0; -} - - -void Init_start_operation(void) -{ - Operation_in_magnifier=(Mouse_X>=Main_X_zoom); - Smear_start=1; -} - - -void Operation_push(short value) -{ - Operation_stack[++Operation_stack_size]=value; -} - - -void Operation_pop(short * value) -{ - *value=Operation_stack[Operation_stack_size--]; -} - - -byte Paintbrush_shape_before_operation; -byte Paintbrush_hidden_before_scroll; - - - -short Distance(short x1, short y1, short x2, short y2) -{ - short x2_moins_x1=x2-x1; - short y2_minus_y1=y2-y1; - - return Round( sqrt( (x2_moins_x1*x2_moins_x1) + (y2_minus_y1*y2_minus_y1) ) ); -} - - -void Display_coords_rel_or_abs(short start_x, short start_y) -{ - char str[6]; - - if (Config.Coords_rel) - { - if (Menu_is_visible) - { - if (Paintbrush_X>start_x) - { - Num2str(Paintbrush_X-start_x,str,5); - str[0]='+'; - } - else if (Paintbrush_Xstart_y) - { - Num2str(Paintbrush_Y-start_y,str,5); - str[0]='+'; - } - else if (Paintbrush_YAirbrush_next_time) - { - Airbrush_next_time+=Airbrush_delay*10; - Hide_cursor(); - // On affiche définitivement le pinceau - Display_paintbrush(Paintbrush_X,Paintbrush_Y,Fore_color,0); - Display_cursor(); - } - } - - Operation_push(Paintbrush_X); - Operation_push(Paintbrush_Y); -} - -// ---------- - -void Freehand_mode2_2_0(void) -// Opération : OPERATION_DISCONTINUOUS_DRAW -// Click Souris: 2 -// Taille_Pile : 0 -// -// Souris effacée: Oui -{ - Init_start_operation(); - Backup(); - Shade_table=Shade_table_right; - Operation_push(Paintbrush_X); - Operation_push(Paintbrush_Y); - Print_coordinates(); - Airbrush_next_time = SDL_GetTicks() + Airbrush_delay*10; - // On affiche définitivement le pinceau - Display_paintbrush(Paintbrush_X,Paintbrush_Y,Back_color,0); -} - - -void Freehand_mode2_2_2(void) -// Opération : OPERATION_DISCONTINUOUS_DRAW -// Click Souris: 2 -// Taille_Pile : 2 -// -// Souris effacée: Non -{ - short start_x; - short start_y; - - Operation_pop(&start_y); - Operation_pop(&start_x); - - if ( (start_x!=Paintbrush_X) || (start_y!=Paintbrush_Y) ) - { - Print_coordinates(); - if (SDL_GetTicks()>Airbrush_next_time) - { - Airbrush_next_time+=Airbrush_delay*10; - Hide_cursor(); - // On affiche définitivement le pinceau - Display_paintbrush(Paintbrush_X,Paintbrush_Y,Back_color,0); - Display_cursor(); - } - } - - Operation_push(Paintbrush_X); - Operation_push(Paintbrush_Y); -} - - -////////////////////////////////////////////////////// OPERATION_POINT_DRAW - -void Freehand_mode3_1_0(void) -// Opération : OPERATION_POINT_DRAW -// Click Souris: 1 -// Taille_Pile : 0 -// -// Souris effacée: Oui -{ - Init_start_operation(); - Backup(); - Shade_table=Shade_table_left; - // On affiche définitivement le pinceau - Display_paintbrush(Paintbrush_X,Paintbrush_Y,Fore_color,0); - Operation_push(0); // On change simplement l'état de la pile... -} - - -void Freehand_Mode3_2_0(void) -// Opération : OPERATION_POINT_DRAW -// Click Souris: 2 -// Taille_Pile : 0 -// -// Souris effacée: Oui -{ - Init_start_operation(); - Backup(); - Shade_table=Shade_table_right; - // On affiche définitivement le pinceau - Display_paintbrush(Paintbrush_X,Paintbrush_Y,Back_color,0); - Operation_push(0); // On change simplement l'état de la pile... -} - - -void Freehand_mode3_0_1(void) -// Opération : OPERATION_POINT_DRAW -// Click Souris: 0 -// Taille_Pile : 1 -// -// Souris effacée: Non -{ - Operation_stack_size--; -} - - -///////////////////////////////////////////////////////////// OPERATION_LINE - -void Line_12_0(void) -// Opération : OPERATION_LINE -// Click Souris: 1 ou 2 -// Taille_Pile : 0 -// -// Souris effacée: Oui - -// Début du tracé d'une ligne (premier clic) -{ - Init_start_operation(); - Backup(); - Paintbrush_shape_before_operation=Paintbrush_shape; - Paintbrush_shape=PAINTBRUSH_SHAPE_POINT; - - if (Mouse_K==LEFT_SIDE) - { - Shade_table=Shade_table_left; - Pixel_figure_preview(Paintbrush_X,Paintbrush_Y,Fore_color); - Update_part_of_screen(Paintbrush_X,Paintbrush_Y,1,1); - Operation_push(Fore_color); - } - else - { - Shade_table=Shade_table_right; - Pixel_figure_preview(Paintbrush_X,Paintbrush_Y,Back_color); - Update_part_of_screen(Paintbrush_X,Paintbrush_Y,1,1); - Operation_push(Back_color); - } - - if ((Config.Coords_rel) && (Menu_is_visible)) - Print_in_menu("X:± 0 Y:± 0",0); - - Operation_push(Paintbrush_X); - Operation_push(Paintbrush_Y); - Operation_push(Paintbrush_X); - Operation_push(Paintbrush_Y); -} - - -void Line_12_5(void) -// Opération : OPERATION_LINE -// Click Souris: 1 -// Taille_Pile : 5 -// -// Souris effacée: Non - -// Poursuite du tracé d'une ligne (déplacement de la souris en gardant le curseur appuyé) -{ - short start_x; - short start_y; - short end_x; - short end_y; - - Operation_pop(&end_y); - Operation_pop(&end_x); - Operation_pop(&start_y); - Operation_pop(&start_x); - - // On corrige les coordonnées de la ligne si la touche shift est appuyée... - if(SDL_GetModState() & KMOD_SHIFT) - { - Clamp_coordinates_45_degrees(start_x,start_y,&Paintbrush_X,&Paintbrush_Y); - } - - // On vient de bouger - if ((Paintbrush_X!=end_x) || (Paintbrush_Y!=end_y)) - { - Hide_cursor(); - - Display_coords_rel_or_abs(start_x,start_y); - - Hide_line_preview(start_x,start_y,end_x,end_y); - if (Mouse_K==LEFT_SIDE) - { - Pixel_figure_preview (start_x,start_y,Fore_color); - Draw_line_preview (start_x,start_y,Paintbrush_X,Paintbrush_Y,Fore_color); - } - else - { - Pixel_figure_preview (start_x,start_y,Back_color); - Draw_line_preview (start_x,start_y,Paintbrush_X,Paintbrush_Y,Back_color); - } - - Operation_push(start_x); - Operation_push(start_y); - Operation_push(Paintbrush_X); - Operation_push(Paintbrush_Y); - - Display_cursor(); - } - else - { - Operation_push(start_x); - Operation_push(start_y); - Operation_push(end_x); - Operation_push(end_y); - } -} - - -void Line_0_5(void) -// Opération : OPERATION_LINE -// Click Souris: 0 -// Taille_Pile : 5 -// -// Souris effacée: Oui - -// End du tracé d'une ligne (relachage du bouton) -{ - short start_x; - short start_y; - short end_x; - short end_y; - short color; - - Operation_pop(&end_y); - Operation_pop(&end_x); - Operation_pop(&start_y); - Operation_pop(&start_x); - Operation_pop(&color); - - // On corrige les coordonnées de la ligne si la touche shift est appuyée... - if(SDL_GetModState() & KMOD_SHIFT) - Clamp_coordinates_45_degrees(start_x,start_y,&end_x,&end_y); - - Paintbrush_shape=Paintbrush_shape_before_operation; - - Pixel_figure_preview_auto (start_x,start_y); - Hide_line_preview (start_x,start_y,end_x,end_y); - Display_paintbrush (start_x,start_y,color,0); - Draw_line_permanet(start_x,start_y,end_x,end_y,color); - - if ( (Config.Coords_rel) && (Menu_is_visible) ) - { - Print_in_menu("X: Y: ",0); - Print_coordinates(); - } -} - - -/////////////////////////////////////////////////////////// OPERATION_K_LIGNE - - -void K_line_12_0(void) -// Opération : OPERATION_K_LIGNE -// Click Souris: 1 ou 2 -// Taille_Pile : 0 -// -// Souris effacée: Oui -{ - byte color; - - Init_start_operation(); - Backup(); - Shade_table=(Mouse_K==LEFT_SIDE)?Shade_table_left:Shade_table_right; - Paintbrush_shape_before_operation=Paintbrush_shape; - Paintbrush_shape=PAINTBRUSH_SHAPE_POINT; - - color=(Mouse_K==LEFT_SIDE)?Fore_color:Back_color; - - // On place temporairement le début de la ligne qui ne s'afficherait pas sinon - Pixel_figure_preview(Paintbrush_X,Paintbrush_Y,color); - - if ((Config.Coords_rel) && (Menu_is_visible)) - Print_in_menu("X:± 0 Y:± 0",0); - - Operation_push(Mouse_K | 0x80); - Operation_push(color); - Operation_push(Paintbrush_X); - Operation_push(Paintbrush_Y); - Operation_push(Paintbrush_X); - Operation_push(Paintbrush_Y); - // Taille de pile 6 : phase d'appui, non interruptible -} - - -void K_line_12_6(void) -// Opération : OPERATION_K_LIGNE -// Click Souris: 1 ou 2 | 0 -// Taille_Pile : 6 | 7 -// -// Souris effacée: Non -{ - short start_x; - short start_y; - short end_x; - short end_y; - short color; - - Operation_pop(&end_y); - Operation_pop(&end_x); - - if ((Paintbrush_X!=end_x) || (Paintbrush_Y!=end_y)) - { - Hide_cursor(); - Operation_pop(&start_y); - Operation_pop(&start_x); - Operation_pop(&color); - - Display_coords_rel_or_abs(start_x,start_y); - - Hide_line_preview(start_x,start_y,end_x,end_y); - Pixel_figure_preview (start_x,start_y,color); - Draw_line_preview (start_x,start_y,Paintbrush_X,Paintbrush_Y,color); - - Operation_push(color); - Operation_push(start_x); - Operation_push(start_y); - Display_cursor(); - } - - Operation_push(Paintbrush_X); - Operation_push(Paintbrush_Y); -} - - -void K_line_0_6(void) -// Opération : OPERATION_K_LIGNE -// Click Souris: 0 -// Taille_Pile : 6 -// -// Souris effacée: Oui -{ - short start_x; - short start_y; - short end_x; - short end_y; - short color; - short direction; - - Operation_pop(&end_y); - Operation_pop(&end_x); - Operation_pop(&start_y); - Operation_pop(&start_x); - Operation_pop(&color); - Operation_pop(&direction); - - if ((Config.Coords_rel) && (Menu_is_visible)) - Print_in_menu("X:± 0 Y:± 0",0); - - Pixel_figure_preview_auto (start_x,start_y); - Hide_line_preview (start_x,start_y,end_x,end_y); - /* Doesn't work if fast moving - Pixel_figure_preview_xor (start_x,start_y, 0); - Draw_line_preview_xor (start_x,start_y,end_x,end_y,0); - */ - Paintbrush_shape=Paintbrush_shape_before_operation; - if (direction & 0x80) - { - Display_paintbrush(start_x,start_y,color,0); - direction=(direction & 0x7F); - } - Draw_line_permanet(start_x,start_y,Paintbrush_X,Paintbrush_Y,color); - Paintbrush_shape=PAINTBRUSH_SHAPE_POINT; - - Operation_push(direction); - Operation_push(direction); // Valeur bidon servant de nouvel état de pile - Operation_push(color); - Operation_push(Paintbrush_X); - Operation_push(Paintbrush_Y); - Operation_push(Paintbrush_X); - Operation_push(Paintbrush_Y); - // Taille de pile 7 : phase de "repos", interruptible (comme Elliot Ness :)) -} - - -void K_line_12_7(void) -// Opération : OPERATION_K_LIGNE -// Click Souris: 1 ou 2 -// Taille_Pile : 7 -// -// Souris effacée: Oui -{ - short start_x; - short start_y; - short end_x; - short end_y; - short color; - short direction; - - Operation_pop(&end_y); - Operation_pop(&end_x); - Operation_pop(&start_y); - Operation_pop(&start_x); - Operation_pop(&color); - Operation_pop(&direction); - Operation_pop(&direction); - - if (direction==Mouse_K) - { - Operation_push(direction); - Operation_push(color); - Operation_push(start_x); - Operation_push(start_y); - Operation_push(end_x); - Operation_push(end_y); - // Taille de pile 6 : phase d'appui, non interruptible - } - else - { - // La série de ligne est terminée, il faut donc effacer la dernière - // preview de ligne - Pixel_figure_preview_auto (start_x,start_y); - Hide_line_preview (start_x,start_y,end_x,end_y); - - Display_cursor(); - Wait_end_of_click(); - Hide_cursor(); - Paintbrush_shape=Paintbrush_shape_before_operation; - - if ( (Config.Coords_rel) && (Menu_is_visible) ) - { - Print_in_menu("X: Y: ",0); - Print_coordinates(); - } - } -} - - -// ---------------------------------------------------------- OPERATION_MAGNIFY - - -void Magnifier_12_0(void) - -// Opération : 4 (item d'une Loupe) -// Click Souris: 1 ou 2 -// Taille_Pile : 0 -// -// Souris effacée: Oui - -{ - - // On passe en mode loupe - Main_magnifier_mode=1; - - // La fonction d'affichage dans la partie image est désormais un affichage - // spécial loupe. - Pixel_preview=Pixel_preview_magnifier; - - // On calcule l'origine de la loupe - Main_magnifier_offset_X=Mouse_X-(Main_magnifier_width>>1); - Main_magnifier_offset_Y=Mouse_Y-(Main_magnifier_height>>1); - - // Calcul du coin haut_gauche de la fenêtre devant être zoomée DANS L'ECRAN - if (Main_magnifier_offset_X+Main_magnifier_width>=Limit_right-Main_offset_X) - Main_magnifier_offset_X=Limit_right-Main_magnifier_width-Main_offset_X+1; - if (Main_magnifier_offset_Y+Main_magnifier_height>=Limit_bottom-Main_offset_Y) - Main_magnifier_offset_Y=Limit_bottom-Main_magnifier_height-Main_offset_Y+1; - - // Calcul des coordonnées absolues de ce coin DANS L'IMAGE - Main_magnifier_offset_X+=Main_offset_X; - Main_magnifier_offset_Y+=Main_offset_Y; - - if (Main_magnifier_offset_X<0) - Main_magnifier_offset_X=0; - if (Main_magnifier_offset_Y<0) - Main_magnifier_offset_Y=0; - - // On calcule les bornes visibles dans l'écran - Position_screen_according_to_zoom(); - Compute_limits(); - Display_all_screen(); - - // Repositionner le curseur en fonction des coordonnées visibles - Compute_paintbrush_coordinates(); - - // On fait de notre mieux pour restaurer l'ancienne opération: - Start_operation_stack(Operation_before_interrupt); - Display_cursor(); - Wait_end_of_click(); -} - -/////////////////////////////////////////////////// OPERATION_RECTANGLE_????? - -void Rectangle_12_0(void) -// Opération : OPERATION_EMPTY_RECTANGLE / OPERATION_FILLED_RECTANGLE -// Click Souris: 1 ou 2 -// Taille_Pile : 0 -// -// Souris effacée: Oui -{ - Init_start_operation(); - - if ((Config.Coords_rel) && (Menu_is_visible)) - Print_in_menu("\035: 1 \022: 1",0); - // On laisse une trace du curseur à l'écran - Display_cursor(); - - if (Mouse_K==LEFT_SIDE) - { - Shade_table=Shade_table_left; - Operation_push(Fore_color); - } - else - { - Shade_table=Shade_table_right; - Operation_push(Back_color); - } - - Operation_push(Paintbrush_X); - Operation_push(Paintbrush_Y); - Operation_push(Paintbrush_X); - Operation_push(Paintbrush_Y); -} - - -void Rectangle_12_5(void) -// Opération : OPERATION_EMPTY_RECTANGLE / OPERATION_FILLED_RECTANGLE -// Click Souris: 1 ou 2 -// Taille_Pile : 5 -// -// Souris effacée: Non -{ - short start_x; - short start_y; - short old_x; - short old_y; - char str[5]; - - Operation_pop(&old_y); - Operation_pop(&old_x); - - if ((Paintbrush_X!=old_x) || (Paintbrush_Y!=old_y)) - { - Operation_pop(&start_y); - Operation_pop(&start_x); - - if ((Config.Coords_rel) && (Menu_is_visible)) - { - Num2str(((start_xcenter_x)?tangent_x-center_x - :center_x-tangent_x; - vertical_radius =(tangent_y>center_y)?tangent_y-center_y - :center_y-tangent_y; - Hide_empty_ellipse_preview(center_x,center_y,horizontal_radius,vertical_radius); - - horizontal_radius=(Paintbrush_X>center_x)?Paintbrush_X-center_x - :center_x-Paintbrush_X; - vertical_radius =(Paintbrush_Y>center_y)?Paintbrush_Y-center_y - :center_y-Paintbrush_Y; - Draw_empty_ellipse_preview(center_x,center_y,horizontal_radius,vertical_radius,color); - - Display_cursor(); - } - - Operation_push(color); - Operation_push(center_x); - Operation_push(center_y); - Operation_push(Paintbrush_X); - Operation_push(Paintbrush_Y); -} - - -void Empty_ellipse_0_5(void) -// -// Opération : OPERATION_EMPTY_ELLIPSE -// Click Souris: 0 -// Taille_Pile : 5 (color, X_Centre, Y_Centre, X_Tangente, Y_Tangente) -// -// Souris effacée: Oui -// -{ - short tangent_x; - short tangent_y; - short center_x; - short center_y; - short color; - short horizontal_radius; - short vertical_radius; - - Operation_pop(&tangent_y); - Operation_pop(&tangent_x); - Operation_pop(¢er_y); - Operation_pop(¢er_x); - Operation_pop(&color); - - horizontal_radius=(tangent_x>center_x)?tangent_x-center_x - :center_x-tangent_x; - vertical_radius =(tangent_y>center_y)?tangent_y-center_y - :center_y-tangent_y; - Hide_empty_ellipse_preview(center_x,center_y,horizontal_radius,vertical_radius); - - Paintbrush_shape=Paintbrush_shape_before_operation; - - Draw_empty_ellipse_permanent(center_x,center_y,horizontal_radius,vertical_radius,color); - - if ( (Config.Coords_rel) && (Menu_is_visible) ) - { - Print_in_menu("X: Y: ",0); - Print_coordinates(); - } -} - - -void Filled_ellipse_0_5(void) -// -// Opération : OPERATION_FILLED_ELLIPSE -// Click Souris: 0 -// Taille_Pile : 5 (color, X_Centre, Y_Centre, X_Tangente, Y_Tangente) -// -// Souris effacée: Oui -// -{ - short tangent_x; - short tangent_y; - short center_x; - short center_y; - short color; - short horizontal_radius; - short vertical_radius; - - Operation_pop(&tangent_y); - Operation_pop(&tangent_x); - Operation_pop(¢er_y); - Operation_pop(¢er_x); - Operation_pop(&color); - - horizontal_radius=(tangent_x>center_x)?tangent_x-center_x - :center_x-tangent_x; - vertical_radius =(tangent_y>center_y)?tangent_y-center_y - :center_y-tangent_y; - Hide_empty_ellipse_preview(center_x,center_y,horizontal_radius,vertical_radius); - - Paintbrush_shape=Paintbrush_shape_before_operation; - - Draw_filled_ellipse(center_x,center_y,horizontal_radius,vertical_radius,color); - - if ( (Config.Coords_rel) && (Menu_is_visible) ) - { - Print_in_menu("X: Y: ",0); - Print_coordinates(); - } -} - - -////////////////////////////////////////////////////////////// OPERATION_FILL - - -void Fill_1_0(void) -// -// Opération : OPERATION_FILL -// Click Souris: 1 -// Taille_Pile : 0 -// -// Souris effacée: Oui -// -{ - Hide_cursor(); - // Pas besoin d'initialiser le début d'opération car le Smear n'affecte pas - // le Fill, et on se fout de savoir si on est dans la partie gauche ou - // droite de la loupe. - // On ne s'occupe pas de faire un Backup: c'est "Fill_general" qui s'en charge. - Shade_table=Shade_table_left; - Fill_general(Fore_color); - Display_cursor(); - Wait_end_of_click(); -} - - -void Fill_2_0(void) -// -// Opération : OPERATION_FILL -// Click Souris: 2 -// Taille_Pile : 0 -// -// Souris effacée: Oui -// -{ - Hide_cursor(); - // Pas besoin d'initialiser le début d'opération car le Smear n'affecte pas - // le Fill, et on se fout de savoir si on est dans la partie gauche ou - // droite de la loupe. - // On ne s'occupe pas de faire un Backup: c'est "Fill_general" qui s'en charge. - Shade_table=Shade_table_right; - Fill_general(Back_color); - Display_cursor(); - Wait_end_of_click(); -} - - -///////////////////////////////////////////////////////// OPERATION_REPLACE - - -void Replace_1_0(void) -// -// Opération : OPERATION_REPLACE -// Click Souris: 1 -// Taille_Pile : 0 -// -// Souris effacée: Oui -// -{ - Hide_cursor(); - // Pas besoin d'initialiser le début d'opération car le Smear n'affecte pas - // le Replace, et on se fout de savoir si on est dans la partie gauche ou - // droite de la loupe. - Backup(); -// Shade_table=Shade_table_left; - Replace(Fore_color); - Display_cursor(); - Wait_end_of_click(); -} - - -void Replace_2_0(void) -// -// Opération : OPERATION_REPLACE -// Click Souris: 2 -// Taille_Pile : 0 -// -// Souris effacée: Oui -// -{ - Hide_cursor(); - // Pas besoin d'initialiser le début d'opération car le Smear n'affecte pas - // le Replace, et on se fout de savoir si on est dans la partie gauche ou - // droite de la loupe. - Backup(); -// Shade_table=Shade_table_right; - Replace(Back_color); - Display_cursor(); - Wait_end_of_click(); -} - - -/////////////////////////////////////////////////////////// OPERATION_COLORPICK - - -void Colorpicker_12_0(void) -// -// Opération : OPERATION_COLORPICK -// Click Souris: 1 ou 2 -// Taille_Pile : 0 -// -// Souris effacée: Oui -// -{ - Init_start_operation(); - - if (Mouse_K==LEFT_SIDE) - { - Set_fore_color(Colorpicker_color); - } - else - { - Set_back_color(Colorpicker_color); - } - Operation_push(Mouse_K); -} - - -void Colorpicker_1_1(void) -// -// Opération : OPERATION_COLORPICK -// Click Souris: 1 -// Taille_Pile : 1 -// -// Souris effacée: Non -// -{ - char str[4]; - - if ( (Paintbrush_X>=0) && (Paintbrush_Y>=0) - && (Paintbrush_X=0) && (Paintbrush_Y>=0) - && (Paintbrush_X=Limit_left+3) - start_x=0; - else - start_x=3-(x_pos-Limit_left); - - if (y_pos>=Limit_top+3) - start_y=0; - else - start_y=3-(y_pos-Limit_top); - - if (x_pos<=Limit_visible_right-3) - end_x=6; - else - end_x=3+(Limit_visible_right-x_pos); - - if (y_pos<=Limit_visible_bottom-3) - end_y=6; - else - end_y=3+(Limit_visible_bottom-y_pos); - - if (start_x<=end_x && start_y<=end_y) - { - for (i=start_x; i<=end_x; i++) - { - temp=x_pos+i-3; - Pixel_preview(temp,y_pos,~Read_pixel(temp -Main_offset_X, - y_pos-Main_offset_Y)); - } - for (i=start_y; i<=end_y; i++) - { - temp=y_pos+i-3; - Pixel_preview(x_pos,temp,~Read_pixel(x_pos-Main_offset_X, - temp -Main_offset_Y)); - } - Update_part_of_screen(x_pos+start_x-3,y_pos+start_y-3,end_x-start_x+1,end_y-start_y+1); - } -} - - -void Curve_34_points_1_0(void) -// -// Opération : OPERATION_COURBE_?_POINTS -// Click Souris: 1 -// Taille_Pile : 0 -// -// Souris effacée: Oui -// -{ - Init_start_operation(); - Backup(); - Shade_table=Shade_table_left; - - Paintbrush_hidden=1; - - Pixel_figure_preview(Paintbrush_X,Paintbrush_Y,Fore_color); - Update_part_of_screen(Paintbrush_X,Paintbrush_Y,1,1); - - if ((Config.Coords_rel) && (Menu_is_visible)) - Print_in_menu("X:± 0 Y:± 0",0); - - Operation_push(Fore_color); - Operation_push(Paintbrush_X); - Operation_push(Paintbrush_Y); - Operation_push(Paintbrush_X); - Operation_push(Paintbrush_Y); -} - -void Curve_34_points_2_0(void) -// -// Opération : OPERATION_COURBE_?_POINTS -// Click Souris: 2 -// Taille_Pile : 0 -// -// Souris effacée: Oui -// -{ - Init_start_operation(); - Backup(); - Shade_table=Shade_table_right; - - Paintbrush_hidden=1; - - Pixel_figure_preview(Paintbrush_X,Paintbrush_Y,Back_color); - Update_part_of_screen(Paintbrush_X,Paintbrush_Y,1,1); - - if ((Config.Coords_rel) && (Menu_is_visible)) - Print_in_menu("X:± 0 Y:± 0",0); - - Operation_push(Back_color); - Operation_push(Paintbrush_X); - Operation_push(Paintbrush_Y); - Operation_push(Paintbrush_X); - Operation_push(Paintbrush_Y); -} - - -void Curve_34_points_1_5(void) -// -// Opération : OPERATION_COURBE_?_POINTS -// Click Souris: 1 -// Taille_Pile : 5 -// -// Souris effacée: Non -// -{ - short x1,x2,y1,y2; - - Operation_pop(&y2); - Operation_pop(&x2); - Operation_pop(&y1); - Operation_pop(&x1); - - if ( (y2!=Paintbrush_Y) || (x2!=Paintbrush_X) ) - { - Hide_cursor(); - Display_coords_rel_or_abs(x1,y1); - - Hide_line_preview(x1,y1,x2,y2); - Pixel_figure_preview (x1,y1,Fore_color); - Draw_line_preview (x1,y1,Paintbrush_X,Paintbrush_Y,Fore_color); - - Display_cursor(); - } - - Operation_push(x1); - Operation_push(y1); - Operation_push(Paintbrush_X); - Operation_push(Paintbrush_Y); -} - -void Curve_34_points_2_5(void) -// -// Opération : OPERATION_COURBE_?_POINTS -// Click Souris: 2 -// Taille_Pile : 5 -// -// Souris effacée: Non -// -{ - short x1,x2,y1,y2; - - Operation_pop(&y2); - Operation_pop(&x2); - Operation_pop(&y1); - Operation_pop(&x1); - - if ( (y2!=Paintbrush_Y) || (x2!=Paintbrush_X) ) - { - Hide_cursor(); - Display_coords_rel_or_abs(x1,y1); - - Hide_line_preview(x1,y1,x2,y2); - Pixel_figure_preview (x1,y1,Back_color); - Draw_line_preview (x1,y1,Paintbrush_X,Paintbrush_Y,Back_color); - - Display_cursor(); - } - - Operation_push(x1); - Operation_push(y1); - Operation_push(Paintbrush_X); - Operation_push(Paintbrush_Y); -} - - -byte Cursor_hidden_before_curve; - -void Curve_4_points_0_5(void) -// -// Opération : OPERATION_4_POINTS_CURVE -// Click Souris: 0 -// Taille_Pile : 5 -// -// Souris effacée: Oui -// -{ - short x1,y1,x2,y2,x3,y3,x4,y4; - short third_x,third_y; - short color; - - Operation_pop(&y4); - Operation_pop(&x4); - Operation_pop(&y1); - Operation_pop(&x1); - Operation_pop(&color); - - third_x=Round_div(abs(x4-x1),3); - third_y=Round_div(abs(y4-y1),3); - - if (x1B=(8/3) * C->P - *x3=Round((bx+x4)/2.0); // · _/·· P3 P2=milieu de [P1,B] - *y3=Round((by+y4)/2.0); // P4*-- P3=milieu de [P4,B] -} - - -void Curve_3_points_0_5(void) -// -// Opération : OPERATION_3_POINTS_CURVE -// Click Souris: 0 -// Taille_Pile : 5 -// -// Souris effacée: Oui -// -{ - short x1,y1,x2,y2,x3,y3,x4,y4; - short color; - - Operation_pop(&y4); - Operation_pop(&x4); - Operation_pop(&y1); - Operation_pop(&x1); - Operation_pop(&color); - - Compute_3_point_curve(x1,y1,x4,y4,&x2,&y2,&x3,&y3); - - Hide_line_preview(x1,y1,x4,y4); - Draw_curve_preview(x1,y1,x2,y2,x3,y3,x4,y4,color); - - if ( (Config.Coords_rel) && (Menu_is_visible) ) - { - Print_in_menu("X: Y: ",0); - Print_coordinates(); - } - - Operation_push(color); - Operation_push(x1); - Operation_push(y1); - Operation_push(x2); - Operation_push(y2); - Operation_push(x3); - Operation_push(y3); - Operation_push(x4); - Operation_push(y4); - Operation_push(Paintbrush_X); - Operation_push(Paintbrush_Y); -} - - -void Curve_3_points_0_11(void) -// -// Opération : OPERATION_3_POINTS_CURVE -// Click Souris: 0 -// Taille_Pile : 11 -// -// Souris effacée: Non -// -{ - short x1,y1,x2,y2,x3,y3,x4,y4; - short old_x,old_y; - short color; - - Operation_pop(&old_y); - Operation_pop(&old_x); - - if ( (Paintbrush_X!=old_x) || (Paintbrush_Y!=old_y) ) - { - Operation_pop(&y4); - Operation_pop(&x4); - Operation_pop(&y3); - Operation_pop(&x3); - Operation_pop(&y2); - Operation_pop(&x2); - Operation_pop(&y1); - Operation_pop(&x1); - Operation_pop(&color); - - Hide_cursor(); - Print_coordinates(); - - Hide_curve_preview(x1,y1,x2,y2,x3,y3,x4,y4,color); - Compute_3_point_curve(x1,y1,x4,y4,&x2,&y2,&x3,&y3); - Draw_curve_preview (x1,y1,x2,y2,x3,y3,x4,y4,color); - Display_cursor(); - - Operation_push(color); - Operation_push(x1); - Operation_push(y1); - Operation_push(x2); - Operation_push(y2); - Operation_push(x3); - Operation_push(y3); - Operation_push(x4); - Operation_push(y4); - } - Operation_push(Paintbrush_X); - Operation_push(Paintbrush_Y); -} - - -void Curve_3_points_12_11(void) -// -// Opération : OPERATION_3_POINTS_CURVE -// Click Souris: 1 ou 2 -// Taille_Pile : 11 -// -// Souris effacée: Oui -// -{ - short x1,y1,x2,y2,x3,y3,x4,y4; - short old_x,old_y; - short color; - - Operation_pop(&old_y); - Operation_pop(&old_x); - Operation_pop(&y4); - Operation_pop(&x4); - Operation_pop(&y3); - Operation_pop(&x3); - Operation_pop(&y2); - Operation_pop(&x2); - Operation_pop(&y1); - Operation_pop(&x1); - Operation_pop(&color); - - Paintbrush_hidden=0; - - Hide_cursor(); - - Hide_curve_preview (x1,y1,x2,y2,x3,y3,x4,y4,color); - Compute_3_point_curve(x1,y1,x4,y4,&x2,&y2,&x3,&y3); - Draw_curve_permanent(x1,y1,x2,y2,x3,y3,x4,y4,color); - - Display_cursor(); - Wait_end_of_click(); -} - - -///////////////////////////////////////////////////////////// OPERATION_AIRBRUSH - -void Airbrush_1_0(void) -// -// Opération : OPERATION_AIRBRUSH -// Click Souris: 1 -// Taille_Pile : 0 -// -// Souris effacée: Non -// -{ - Init_start_operation(); - Backup(); - Shade_table=Shade_table_left; - - Airbrush_next_time = SDL_GetTicks()+Airbrush_delay*10; - Airbrush(LEFT_SIDE); - - Operation_push(Paintbrush_X); - Operation_push(Paintbrush_Y); -} - -void Airbrush_2_0(void) -// -// Opération : OPERATION_AIRBRUSH -// Click Souris: 2 -// Taille_Pile : 0 -// -// Souris effacée: Non -// -{ - Init_start_operation(); - Backup(); - Shade_table=Shade_table_right; - Airbrush_next_time = SDL_GetTicks()+Airbrush_delay*10; - Airbrush(RIGHT_SIDE); - - Operation_push(Paintbrush_X); - Operation_push(Paintbrush_Y); -} - -void Airbrush_12_2(void) -// -// Opération : OPERATION_AIRBRUSH -// Click Souris: 1 ou 2 -// Taille_Pile : 2 -// -// Souris effacée: Non -// -{ - short old_x,old_y; - - Operation_pop(&old_y); - Operation_pop(&old_x); - - if ( (Menu_is_visible) && ((Paintbrush_X!=old_x) || (Paintbrush_Y!=old_y)) ) - { - Hide_cursor(); - Print_coordinates(); - Display_cursor(); - } - - if (SDL_GetTicks()>Airbrush_next_time) - { - Airbrush_next_time+=Airbrush_delay*10; - Airbrush(Mouse_K_unique); - } - - Operation_push(Paintbrush_X); - Operation_push(Paintbrush_Y); -} - -void Airbrush_0_2(void) -// -// Opération : OPERATION_AIRBRUSH -// Click Souris: 0 -// Taille_Pile : 2 -// -// Souris effacée: Non -// -{ - Operation_stack_size-=2; -} - - -////////////////////////////////////////////////////////// OPERATION_POLYGON - - -void Polygon_12_0(void) -// Opération : OPERATION_POLYGON -// Click Souris: 1 ou 2 -// Taille_Pile : 0 -// -// Souris effacée: Oui -{ - byte color; - - Init_start_operation(); - Backup(); - Shade_table=(Mouse_K==LEFT_SIDE)?Shade_table_left:Shade_table_right; - Paintbrush_shape_before_operation=Paintbrush_shape; - Paintbrush_shape=PAINTBRUSH_SHAPE_POINT; - - color=(Mouse_K==LEFT_SIDE)?Fore_color:Back_color; - - // On place temporairement le début de la ligne qui ne s'afficherait pas sinon - Pixel_figure_preview(Paintbrush_X,Paintbrush_Y,color); - Update_part_of_screen(Paintbrush_X,Paintbrush_Y,1,1); - - if ((Config.Coords_rel) && (Menu_is_visible)) - Print_in_menu("X:± 0 Y:± 0",0); - - Operation_push(Paintbrush_X); - Operation_push(Paintbrush_Y); - Operation_push(Mouse_K | 0x80); - Operation_push(color); - Operation_push(Paintbrush_X); - Operation_push(Paintbrush_Y); - Operation_push(Paintbrush_X); - Operation_push(Paintbrush_Y); - // Taille de pile 8 : phase d'appui, non interruptible -} - - - -void Polygon_12_9(void) -// Opération : OPERATION_POLYGON -// Click Souris: 1 ou 2 -// Taille_Pile : 9 -// -// Souris effacée: Oui -{ - short start_x; - short start_y; - short end_x; - short end_y; - short color; - short direction; - - Operation_pop(&end_y); - Operation_pop(&end_x); - Operation_pop(&start_y); - Operation_pop(&start_x); - Operation_pop(&color); - Operation_pop(&direction); - Operation_pop(&direction); - - if (direction==Mouse_K) - { - Operation_push(direction); - Operation_push(color); - Operation_push(start_x); - Operation_push(start_y); - Operation_push(end_x); - Operation_push(end_y); - // Taille de pile 8 : phase d'appui, non interruptible - } - else - { - // La série de ligne est terminée, il faut donc effacer la dernière - // preview de ligne et relier le dernier point avec le premier - Pixel_figure_preview_auto (start_x,start_y); - Hide_line_preview (start_x,start_y,end_x,end_y); - Operation_pop(&end_y); - Operation_pop(&end_x); - Paintbrush_shape=Paintbrush_shape_before_operation; - // Le pied aurait été de ne pas repasser sur le 1er point de la 1ère ligne - // mais c'est pas possible :( - Draw_line_permanet(start_x,start_y,end_x,end_y,color); - Paintbrush_shape=PAINTBRUSH_SHAPE_POINT; - - Display_cursor(); - Wait_end_of_click(); - Hide_cursor(); - - if ( (Config.Coords_rel) && (Menu_is_visible) ) - { - Print_in_menu("X: Y: ",0); - Print_coordinates(); - } - - Paintbrush_shape=Paintbrush_shape_before_operation; - } -} - - -////////////////////////////////////////////////////////// OPERATION_POLYFILL - -short * Polyfill_table_of_points; -int Polyfill_number_of_points; - -void Polyfill_12_0(void) -// Opération : OPERATION_POLYFILL -// Click Souris: 1 ou 2 -// Taille_Pile : 0 -// -// Souris effacée: Oui -{ - byte color; - - Init_start_operation(); - Backup(); - Shade_table=(Mouse_K==LEFT_SIDE)?Shade_table_left:Shade_table_right; - Paintbrush_hidden=1; - - color=(Mouse_K==LEFT_SIDE)?Fore_color:Back_color; - - Polyfill_table_of_points=(short *) malloc((Config.Nb_max_vertices_per_polygon<<1)*sizeof(short)); - Polyfill_table_of_points[0]=Paintbrush_X; - Polyfill_table_of_points[1]=Paintbrush_Y; - Polyfill_number_of_points=1; - - // On place temporairement le début de la ligne qui ne s'afficherait pas sinon - Pixel_figure_preview_xor(Paintbrush_X,Paintbrush_Y,0); - Update_part_of_screen(Paintbrush_X,Paintbrush_Y,1,1); - - if ((Config.Coords_rel) && (Menu_is_visible)) - Print_in_menu("X:± 0 Y:± 0",0); - - Operation_push(Paintbrush_X); - Operation_push(Paintbrush_Y); - Operation_push(Mouse_K | 0x80); - Operation_push(color); - Operation_push(Paintbrush_X); - Operation_push(Paintbrush_Y); - Operation_push(Paintbrush_X); - Operation_push(Paintbrush_Y); - // Taille de pile 8 : phase d'appui, non interruptible -} - - -void Polyfill_0_8(void) -// Opération : OPERATION_POLYFILL -// Click Souris: 0 -// Taille_Pile : 8 -// -// Souris effacée: Oui -{ - short start_x; - short start_y; - short end_x; - short end_y; - short color; - short direction; - - Operation_pop(&end_y); - Operation_pop(&end_x); - Operation_pop(&start_y); - Operation_pop(&start_x); - Operation_pop(&color); - Operation_pop(&direction); - - if ((Config.Coords_rel) && (Menu_is_visible)) - Print_in_menu("X:± 0 Y:± 0",0); - - Draw_line_preview_xor(start_x,start_y,end_x,end_y,0); - - if (direction & 0x80) - direction=(direction & 0x7F); - - Operation_push(direction); // Valeur bidon servant de nouvel état de pile - Operation_push(direction); - Operation_push(color); - - Draw_line_preview_xor(start_x,start_y,Paintbrush_X,Paintbrush_Y,0); - - if (Polyfill_number_of_points1) width--; - if (height>1) height--; - } - - Num2str(width,str,4); - Print_in_menu(str,2); - Num2str(height,str,4); - Print_in_menu(str,11); - } - else - Print_coordinates(); - } - - Display_all_screen(); - - x=Paintbrush_X; - y=Paintbrush_Y; - if (Snap_mode && Config.Adjust_brush_pick) - { - dx=Paintbrush_X-start_x; - dy=Paintbrush_Y-start_y; - if (dx<0) x++; else {if (dx>0) x--;} - if (dy<0) y++; else {if (dy>0) y--;} - Stretch_brush_preview(start_x,start_y,x,y); - } - else - Stretch_brush_preview(start_x,start_y,Paintbrush_X,Paintbrush_Y); - - old_x=Paintbrush_X; - old_y=Paintbrush_Y; - Paintbrush_X=start_x; - Paintbrush_Y=start_y; - Display_cursor(); - Paintbrush_X=old_x; - Paintbrush_Y=old_y; - Display_cursor(); - - Operation_stack_size-=2; - Operation_push(x); - Operation_push(y); - - Operation_push(start_x); - Operation_push(start_y); - } - - Operation_push(Paintbrush_X); - Operation_push(Paintbrush_Y); - Operation_push(2); -} - - - -void Stretch_brush_0_7(void) -// -// Opération : OPERATION_STRETCH_BRUSH -// Click Souris: 0 -// Taille_Pile : 7 -// -// Souris effacée: Non -// -{ - char str[5]; - short start_x; - short start_y; - short old_x; - short old_y; - short width=0; - short height=0; - byte size_change; - short prev_state; - - Operation_pop(&prev_state); - Operation_pop(&old_y); - Operation_pop(&old_x); - Operation_pop(&start_y); - Operation_pop(&start_x); - - if ((Paintbrush_X!=old_x) || (Paintbrush_Y!=old_y) || (prev_state!=3)) - { - if (Menu_is_visible) - { - if (Config.Coords_rel) - { - width=((start_x1)?start_x+(Brush_width>>1)-1:1; - height=(Brush_height>1)?start_y+(Brush_height>>1)-1:1; - break; - case 'X': // Moitié X - width=(Brush_width>1)?start_x+(Brush_width>>1)-1:1; - height=start_y+Brush_height-1; - break; - case 'Y': // Moitié Y - width=start_x+Brush_width-1; - height=(Brush_height>1)?start_y+(Brush_height>>1)-1:1; - break; - case 'n': // Normal - width=start_x+Brush_width-1; - height=start_y+Brush_height-1; - break; - default : - size_change=0; - } - Key_ANSI=0; - } - else - size_change=0; - - if (size_change) - { - // On efface la preview de la brosse (et la croix) - Display_all_screen(); - - old_x=Paintbrush_X; - old_y=Paintbrush_Y; - Paintbrush_X=start_x; - Paintbrush_Y=start_y; - Display_cursor(); - Paintbrush_X=old_x; - Paintbrush_Y=old_y; - - Stretch_brush_preview(start_x,start_y,width,height); - Display_cursor(); - - Operation_stack_size-=2; - Operation_push(width); - Operation_push(height); - } - - Operation_push(start_x); - Operation_push(start_y); - Operation_push(Paintbrush_X); - Operation_push(Paintbrush_Y); - Operation_push(3); -} - - -void Stretch_brush_2_7(void) -// -// Opération : OPERATION_STRETCH_BRUSH -// Click Souris: 2 -// Taille_Pile : 7 -// -// Souris effacée: Oui -// -{ - short computed_x; - short computed_y; - short start_x; - short start_y; - - - Operation_stack_size-=3; - Operation_pop(&start_y); - Operation_pop(&start_x); - Operation_pop(&computed_y); - Operation_pop(&computed_x); - - // On efface la preview de la brosse (et la croix) - Display_all_screen(); - - // Et enfin on stocke pour de bon la nouvelle brosse étirée - Stretch_brush(start_x,start_y,computed_x,computed_y); - - Return_to_draw_mode(); -} - - -//////////////////////////////////////////////////// OPERATION_ROTATE_BRUSH - - -void Rotate_brush_12_0(void) -// -// Opération : OPERATION_ROTATE_BRUSH -// Click Souris: 1 ou 2 -// Taille_Pile : 0 -// -// Souris effacée: Oui -// -{ - Init_start_operation(); - if (Mouse_K==LEFT_SIDE) - { - Brush_rotation_center_X=Paintbrush_X+(Brush_width>>1)-Brush_width; - Brush_rotation_center_Y=Paintbrush_Y; - Brush_rotation_center_is_defined=1; - Operation_push(Paintbrush_X); // Dernière position calculée X - Operation_push(Paintbrush_Y); // Dernière position calculée Y - Operation_push(Paintbrush_X); // Dernière position X - Operation_push(Paintbrush_Y); // Dernière position Y - Operation_push(1); // State précédent - - if ((Config.Coords_rel) && (Menu_is_visible)) - Print_in_menu("Angle: 0° ",0); - } - else - { - Start_operation_stack(Operation_before_interrupt); - Wait_end_of_click(); // FIXME: celui-la il donne un résultat pas très chouette en visuel - } -} - - - -void Rotate_brush_1_5(void) -// -// Opération : OPERATION_ROTATE_BRUSH -// Click Souris: 1 -// Taille_Pile : 5 -// -// Souris effacée: Non -// -{ - char str[4]; - short old_x; - short old_y; - short prev_state; - float angle; - int dx,dy; - - Operation_pop(&prev_state); - Operation_pop(&old_y); - Operation_pop(&old_x); - - if ( (Paintbrush_X!=old_x) || (Paintbrush_Y!=old_y) || (prev_state!=2) ) - { - if ( (Brush_rotation_center_X==Paintbrush_X) - && (Brush_rotation_center_Y==Paintbrush_Y) ) - angle=0.0; - else - { - dx=Paintbrush_X-Brush_rotation_center_X; - dy=Paintbrush_Y-Brush_rotation_center_Y; - angle=acos(((float)dx)/sqrt((dx*dx)+(dy*dy))); - if (dy>0) angle=M_2PI-angle; - } - - if (Menu_is_visible) - { - if (Config.Coords_rel) - { - Num2str((int)(angle*180.0/M_PI),str,3); - Print_in_menu(str,7); - } - else - Print_coordinates(); - } - - Display_all_screen(); - Rotate_brush_preview(angle); - Display_cursor(); - - Operation_stack_size-=2; - Operation_push(Paintbrush_X); - Operation_push(Paintbrush_Y); - } - - Operation_push(Paintbrush_X); - Operation_push(Paintbrush_Y); - Operation_push(2); -} - - - -void Rotate_brush_0_5(void) -// -// Opération : OPERATION_ROTATE_BRUSH -// Click Souris: 0 -// Taille_Pile : 5 -// -// Souris effacée: Non -// -{ - char str[4]; - short old_x; - short old_y; - short computed_x=0; - short computed_y=0; - byte angle_change; - short prev_state; - float angle=0.0; - int dx,dy; - - Operation_pop(&prev_state); - Operation_pop(&old_y); - Operation_pop(&old_x); - - if ((Paintbrush_X!=old_x) || (Paintbrush_Y!=old_y) || (prev_state!=3)) - { - if ( (Brush_rotation_center_X==Paintbrush_X) - && (Brush_rotation_center_Y==Paintbrush_Y) ) - angle=0.0; - else - { - dx=Paintbrush_X-Brush_rotation_center_X; - dy=Paintbrush_Y-Brush_rotation_center_Y; - angle=acos(((float)dx)/sqrt((dx*dx)+(dy*dy))); - if (dy>0) angle=M_2PI-angle; - } - - if (Menu_is_visible) - { - if (Config.Coords_rel) - { - Num2str(Round(angle*180.0/M_PI),str,3); - Print_in_menu(str,7); - } - else - Print_coordinates(); - } - } - - // Utilise Key_ANSI au lieu de Key, car Get_input() met ce dernier - // à zero si une operation est en cours (Operation_stack_size!=0) - if (Key_ANSI) - { - angle_change=1; - computed_x=Brush_rotation_center_X; - computed_y=Brush_rotation_center_Y; - switch (Key_ANSI) - { - case '6': angle= 0.0 ; computed_x++; break; - case '9': angle=M_PI*0.25; computed_x++; computed_y--; break; - case '8': angle=M_PI*0.5 ; computed_y--; break; - case '7': angle=M_PI*0.75; computed_x--; computed_y--; break; - case '4': angle=M_PI ; computed_x--; break; - case '1': angle=M_PI*1.25; computed_x--; computed_y++; break; - case '2': angle=M_PI*1.5 ; computed_y++; break; - case '3': angle=M_PI*1.75; computed_x++; computed_y++; break; - default : - angle_change=0; - } - Key_ANSI=0; - } - else - angle_change=0; - - if (angle_change) - { - // On efface la preview de la brosse - Display_all_screen(); - Rotate_brush_preview(angle); - Display_cursor(); - - Operation_stack_size-=2; - Operation_push(computed_x); - Operation_push(computed_y); - } - - Operation_push(Paintbrush_X); - Operation_push(Paintbrush_Y); - Operation_push(3); -} - - -void Rotate_brush_2_5(void) -// -// Opération : OPERATION_ROTATE_BRUSH -// Click Souris: 2 -// Taille_Pile : 5 -// -// Souris effacée: Oui -// -{ - short computed_x; - short computed_y; - int dx,dy; - float angle; - - - // On efface la preview de la brosse - Display_all_screen(); - - Operation_stack_size-=3; - Operation_pop(&computed_y); - Operation_pop(&computed_x); - - // Calcul de l'angle par rapport à la dernière position calculée - if ( (Brush_rotation_center_X==computed_x) - && (Brush_rotation_center_Y==computed_y) ) - angle=0.0; - else - { - dx=computed_x-Brush_rotation_center_X; - dy=computed_y-Brush_rotation_center_Y; - angle=acos(((float)dx)/sqrt((dx*dx)+(dy*dy))); - if (dy>0) angle=M_2PI-angle; - } - - // Et enfin on stocke pour de bon la nouvelle brosse étirée - Rotate_brush(angle); - - Return_to_draw_mode(); -} - -///////////////////////////////////////////////////// OPERATION_DISTORT_BRUSH - -/// Draws a 2x2 XOR square at the specified picture coordinates, on the screen. -void Draw_stretch_spot(short x_pos, short y_pos) -{ - short x,y; - - for (y=y_pos-1;y=Limit_top && y<=Limit_visible_bottom) - for (x=x_pos-1;x=Limit_left && x<=Limit_visible_right) - Pixel_preview(x,y,~Read_pixel(x-Main_offset_X,y-Main_offset_Y)); - Update_part_of_screen(x_pos-1, y_pos-1, 2, 2); -} - -void Distort_brush_0_0(void) -// -// Opération : OPERATION_DISTORT_BRUSH -// Click Souris: 0 -// Taille_Pile : 0 -// -// Souris effacée: Non -// -{ - if ( Menu_is_visible ) - { - Print_in_menu("POSITION BRUSH TO START ",0); - } -} - -void Distort_brush_1_0(void) -// -// Opération : OPERATION_DISTORT_BRUSH -// Click Souris: 1 -// Taille_Pile : 0 -// -// Souris effacée: Non -// -{ - short x_pos, y_pos; - - Init_start_operation(); - Paintbrush_hidden=1; - Hide_cursor(); - - // Top left angle - x_pos=Paintbrush_X-Brush_offset_X; - y_pos=Paintbrush_Y-Brush_offset_Y; - Draw_stretch_spot(x_pos,y_pos); - Operation_push(x_pos); - Operation_push(y_pos); - - // Top right angle - x_pos+=Brush_width; - Draw_stretch_spot(x_pos,y_pos); - Operation_push(x_pos); - Operation_push(y_pos); - - // Bottom right angle - y_pos+=Brush_height; - Draw_stretch_spot(x_pos,y_pos); - Operation_push(x_pos); - Operation_push(y_pos); - - // Bottom left angle - x_pos-=Brush_width; - Draw_stretch_spot(x_pos,y_pos); - Operation_push(x_pos); - Operation_push(y_pos); - - Distort_brush_preview( - Operation_stack[1], - Operation_stack[2], - Operation_stack[3], - Operation_stack[4], - Operation_stack[5], - Operation_stack[6], - Operation_stack[7], - Operation_stack[8]); - Display_cursor(); - Update_part_of_screen(Paintbrush_X-Brush_offset_X, Paintbrush_Y-Brush_offset_Y, Brush_width, Brush_height); - Wait_end_of_click(); - // Erase the message in status bar - if ( (Config.Coords_rel) && (Menu_is_visible) ) - { - Print_in_menu("X: Y: ",0); - } -} - -void Distort_brush_1_8(void) -// -// Opération : OPERATION_DISTORT_BRUSH -// Click Souris: 1 -// Taille_Pile : 8 -// -// Souris effacée: No -// -{ - // How far (in pixels) you can catch a handle - #define REACH_DISTANCE 100 - short i; - short x[4]; - short y[4]; - long best_distance=REACH_DISTANCE; - short best_spot=-1; - - for (i=3;i>=0;i--) - { - long distance; - Operation_pop(&y[i]); - Operation_pop(&x[i]); - distance=Distance(Paintbrush_X,Paintbrush_Y,x[i],y[i]); - if (distance-1) - { - Operation_push(best_spot); - } - if ( (Config.Coords_rel) && (Menu_is_visible) ) - { - Print_in_menu("X: Y: ",0); - Print_coordinates(); - } -} - -void Distort_brush_1_9(void) -// -// Opération : OPERATION_DISTORT_BRUSH -// Click Souris: 1 -// Taille_Pile : 9 -// -// Souris effacée: No -// -{ - short i; - short x[4]; - short y[4]; - short selected_corner; - - // Pop all arguments - Operation_pop(&selected_corner); - for (i=3;i>=0;i--) - { - Operation_pop(&y[i]); - Operation_pop(&x[i]); - } - - if (Paintbrush_X!=x[selected_corner] || Paintbrush_Y!=y[selected_corner]) - { - Hide_cursor(); - - // Easiest refresh mode: make no assumptions on how the brush was - // displayed before. - Display_all_screen(); - - x[selected_corner]=Paintbrush_X; - y[selected_corner]=Paintbrush_Y; - - for (i=0;i<4;i++) - Draw_stretch_spot(x[i],y[i]); - - Distort_brush_preview(x[0],y[0],x[1],y[1],x[2],y[2],x[3],y[3]); - - Display_cursor(); - - if ( (Config.Coords_rel) && (Menu_is_visible) ) - { - Print_in_menu("X: Y: ",0); - Print_coordinates(); - } - Update_rect(0,0,Screen_width,Menu_Y); - } - - // Push back all arguments - for (i=0;i<4;i++) - { - Operation_push(x[i]); - Operation_push(y[i]); - } - Operation_push(selected_corner); - -} -void Distort_brush_0_9(void) -// -// Opération : OPERATION_DISTORT_BRUSH -// Click Souris: 0 -// Taille_Pile : 9 -// -// Souris effacée: No -// -{ - short selected_corner; - Operation_pop(&selected_corner); - -} - -void Distort_brush_2_0(void) -// -// Opération : OPERATION_DISTORT_BRUSH -// Click Souris: 2 -// Taille_Pile : 0 -// -// Souris effacée: Oui -// -{ - Paintbrush_hidden=0; - Display_all_screen(); - // Erase the message in status bar - if ( (Config.Coords_rel) && (Menu_is_visible) ) - { - Print_in_menu("X: Y: ",0); - } - Return_to_draw_mode(); -} - -void Distort_brush_2_8(void) -// -// Opération : OPERATION_DISTORT_BRUSH -// Click Souris: 2 -// Taille_Pile : 8 -// -// Souris effacée: Oui -// -{ - short i; - short x[4]; - short y[4]; - - // Pop all arguments - for (i=3;i>=0;i--) - { - Operation_pop(&y[i]); - Operation_pop(&x[i]); - } - Distort_brush(x[0],y[0],x[1],y[1],x[2],y[2],x[3],y[3]); - - Paintbrush_hidden=0; - Display_all_screen(); - - Return_to_draw_mode(); -} - -//////////////////////////////////////////////////////////// OPERATION_SCROLL - - -byte Cursor_hidden_before_scroll; - -void Scroll_12_0(void) -// -// Opération : OPERATION_SCROLL -// Click Souris: 1 ou 2 -// Taille_Pile : 0 -// -// Souris effacée: Oui -// -{ - Init_start_operation(); - Backup(); - Operation_push(Paintbrush_X); - Operation_push(Paintbrush_Y); - Operation_push(Paintbrush_X); - Operation_push(Paintbrush_Y); - Cursor_hidden_before_scroll=Cursor_hidden; - Cursor_hidden=1; - if ((Config.Coords_rel) && (Menu_is_visible)) - Print_in_menu("X:± 0 Y:± 0",0); -} - - -void Scroll_12_4(void) -// -// Opération : OPERATION_SCROLL -// Click Souris: 1 ou 2 -// Taille_Pile : 4 -// -// Souris effacée: Non -// -{ - short center_x; - short center_y; - short x_pos; - short y_pos; - short x_offset; - short y_offset; - //char str[5]; - - Operation_pop(&y_pos); - Operation_pop(&x_pos); - Operation_pop(¢er_y); - Operation_pop(¢er_x); - - if ( (Paintbrush_X!=x_pos) || (Paintbrush_Y!=y_pos) ) - { - // L'utilisateur a bougé, il faut scroller l'image - - if (Paintbrush_X>=center_x) - x_offset=(Paintbrush_X-center_x)%Main_image_width; - else - x_offset=Main_image_width-((center_x-Paintbrush_X)%Main_image_width); - - if (Paintbrush_Y>=center_y) - y_offset=(Paintbrush_Y-center_y)%Main_image_height; - else - y_offset=Main_image_height-((center_y-Paintbrush_Y)%Main_image_height); - - Display_coords_rel_or_abs(center_x,center_y); - - Scroll_picture(x_offset,y_offset); - - Display_all_screen(); - } - - Operation_push(center_x); - Operation_push(center_y); - Operation_push(Paintbrush_X); - Operation_push(Paintbrush_Y); -} - -void Scroll_0_4(void) -// -// Opération : OPERATION_SCROLL -// Click Souris: 0 -// Taille_Pile : 4 -// -// Souris effacée: Oui -// -{ - Operation_stack_size-=4; - Cursor_hidden=Cursor_hidden_before_scroll; - if ((Config.Coords_rel) && (Menu_is_visible)) - { - Print_in_menu("X: Y: ",0); - Print_coordinates(); - } -} - - -//////////////////////////////////////////////////// OPERATION_GRAD_CIRCLE - - -void Grad_circle_12_0(void) -// -// Opération : OPERATION_GRAD_CIRCLE -// Click Souris: 1 ou 2 -// Taille_Pile : 0 -// -// Souris effacée: Oui -{ - byte color; - - Init_start_operation(); - Backup(); - - Shade_table=(Mouse_K==LEFT_SIDE)?Shade_table_left:Shade_table_right; - color=(Mouse_K==LEFT_SIDE)?Fore_color:Back_color; - - Paintbrush_hidden_before_scroll=Paintbrush_hidden; - Paintbrush_hidden=1; - - Pixel_figure_preview(Paintbrush_X,Paintbrush_Y,color); - Update_part_of_screen(Paintbrush_X,Paintbrush_Y,1,1); - - if ((Config.Coords_rel) && (Menu_is_visible)) - Print_in_menu("Radius: 0 ",0); - - Operation_push(Mouse_K); - Operation_push(color); - Operation_push(Paintbrush_X); - Operation_push(Paintbrush_Y); - Operation_push(Paintbrush_X); - Operation_push(Paintbrush_Y); -} - - -void Grad_circle_12_6(void) -// -// Opération : OPERATION_GRAD_CIRCLE -// Click Souris: 1 ou 2 -// Taille_Pile : 6 (Mouse_K, color, X_Centre, Y_Centre, X_Tangente, Y_Tangente) -// -// Souris effacée: Non -// -{ - short tangent_x; - short tangent_y; - short center_x; - short center_y; - short color; - short radius; - char str[5]; - - Operation_pop(&tangent_y); - Operation_pop(&tangent_x); - Operation_pop(¢er_y); - Operation_pop(¢er_x); - Operation_pop(&color); - - if ( (tangent_x!=Paintbrush_X) || (tangent_y!=Paintbrush_Y) ) - { - Hide_cursor(); - if ((Config.Coords_rel) && (Menu_is_visible)) - { - Num2str(Distance(center_x,center_y,Paintbrush_X,Paintbrush_Y),str,4); - Print_in_menu(str,7); - } - else - Print_coordinates(); - - Circle_limit=((tangent_x-center_x)*(tangent_x-center_x))+ - ((tangent_y-center_y)*(tangent_y-center_y)); - radius=sqrt(Circle_limit); - Hide_empty_circle_preview(center_x,center_y,radius); - - Circle_limit=((Paintbrush_X-center_x)*(Paintbrush_X-center_x))+ - ((Paintbrush_Y-center_y)*(Paintbrush_Y-center_y)); - radius=sqrt(Circle_limit); - Draw_empty_circle_preview(center_x,center_y,radius,color); - - Display_cursor(); - } - - Operation_push(color); - Operation_push(center_x); - Operation_push(center_y); - Operation_push(Paintbrush_X); - Operation_push(Paintbrush_Y); -} - - -void Grad_circle_0_6(void) -// -// Opération : OPERATION_GRAD_CIRCLE -// Click Souris: 0 -// Taille_Pile : 6 (Mouse_K, color, X_Centre, Y_Centre, X_Tangente, Y_Tangente) -// -// Souris effacée: Oui -// -{ - short tangent_x; - short tangent_y; - short center_x; - short center_y; - short color; - short click; - short radius; - - Operation_pop(&tangent_y); - Operation_pop(&tangent_x); - Operation_pop(¢er_y); - Operation_pop(¢er_x); - - Operation_pop(&color); - Operation_pop(&click); - - if (click==LEFT_SIDE) - { - Operation_push(click); - Operation_push(color); - - Operation_push(center_x); - Operation_push(center_y); - Operation_push(tangent_x); - Operation_push(tangent_y); - - Operation_push(Paintbrush_X); - Operation_push(Paintbrush_Y); - - // On change la forme du curseur - Cursor_shape=CURSOR_SHAPE_XOR_TARGET; - - // On affiche une croix XOR au centre du cercle - Draw_curve_cross(center_x,center_y); - - if (Menu_is_visible) - { - if (Config.Coords_rel) - Print_in_menu("X: Y:",0); - else - Print_in_menu("X: Y: ",0); - Display_coords_rel_or_abs(center_x,center_y); - } - } - else - { - Circle_limit=((tangent_x-center_x)*(tangent_x-center_x))+ - ((tangent_y-center_y)*(tangent_y-center_y)); - radius=sqrt(Circle_limit); - Hide_empty_circle_preview(center_x,center_y,radius); - - Paintbrush_hidden=Paintbrush_hidden_before_scroll; - Cursor_shape=CURSOR_SHAPE_TARGET; - - Draw_filled_circle(center_x,center_y,radius,Back_color); - - if ((Config.Coords_rel) && (Menu_is_visible)) - { - Print_in_menu("X: Y: ",0); - Print_coordinates(); - } - } -} - - -void Grad_circle_12_8(void) -// -// Opération : OPERATION_GRAD_CIRCLE -// Click Souris: 0 -// Taille_Pile : 8 (Mouse_K, color, X_Centre, Y_Centre, X_Tangente, Y_Tangente, old_x, old_y) -// -// Souris effacée: Oui -// -{ - short tangent_x; - short tangent_y; - short center_x; - short center_y; - short color; - short old_mouse_k; - - short radius; - - Operation_stack_size-=2; // On fait sauter les 2 derniers élts de la pile - Operation_pop(&tangent_y); - Operation_pop(&tangent_x); - Operation_pop(¢er_y); - Operation_pop(¢er_x); - Operation_pop(&color); - Operation_pop(&old_mouse_k); - - Hide_cursor(); - // On efface la croix XOR au centre du cercle - Draw_curve_cross(center_x,center_y); - - Circle_limit=((tangent_x-center_x)*(tangent_x-center_x))+ - ((tangent_y-center_y)*(tangent_y-center_y)); - radius=sqrt(Circle_limit); - Hide_empty_circle_preview(center_x,center_y,radius); - - Paintbrush_hidden=Paintbrush_hidden_before_scroll; - Cursor_shape=CURSOR_SHAPE_TARGET; - - if (Mouse_K==old_mouse_k) - Draw_grad_circle(center_x,center_y,radius,Paintbrush_X,Paintbrush_Y); - - Display_cursor(); - Wait_end_of_click(); - - if ((Config.Coords_rel) && (Menu_is_visible)) - { - Print_in_menu("X: Y: ",0); - Print_coordinates(); - } -} - - -void Grad_circle_or_ellipse_0_8(void) -// -// Opération : OPERATION_{CERCLE|ELLIPSE}_DEGRADE -// Click Souris: 0 -// Taille_Pile : 8 -// -// Souris effacée: Non -// -{ - short start_x; - short start_y; - short tangent_x; - short tangent_y; - short old_x; - short old_y; - - Operation_pop(&old_y); - Operation_pop(&old_x); - - if ((Paintbrush_X!=old_x) || (Paintbrush_Y!=old_y)) - { - Operation_pop(&tangent_y); - Operation_pop(&tangent_x); - Operation_pop(&start_y); - Operation_pop(&start_x); - Display_coords_rel_or_abs(start_x,start_y); - Operation_push(start_x); - Operation_push(start_y); - Operation_push(tangent_x); - Operation_push(tangent_y); - } - - Operation_push(Paintbrush_X); - Operation_push(Paintbrush_Y); -} - - -////////////////////////////////////////////////// OPERATION_GRAD_ELLIPSE - - -void Grad_ellipse_12_0(void) -// -// Opération : OPERATION_GRAD_ELLIPSE -// Click Souris: 1 ou 2 -// Taille_Pile : 0 -// -// Souris effacée: Oui -{ - byte color; - - Init_start_operation(); - Backup(); - - Shade_table=(Mouse_K==LEFT_SIDE)?Shade_table_left:Shade_table_right; - color=(Mouse_K==LEFT_SIDE)?Fore_color:Back_color; - - Paintbrush_hidden_before_scroll=Paintbrush_hidden; - Paintbrush_hidden=1; - - Pixel_figure_preview(Paintbrush_X,Paintbrush_Y,color); - Update_part_of_screen(Paintbrush_X,Paintbrush_Y,1,1); - - if ((Config.Coords_rel) && (Menu_is_visible)) - Print_in_menu("X:± 0 Y:± 0",0); - - Operation_push(Mouse_K); - Operation_push(color); - Operation_push(Paintbrush_X); - Operation_push(Paintbrush_Y); - Operation_push(Paintbrush_X); - Operation_push(Paintbrush_Y); -} - - -void Grad_ellipse_12_6(void) -// -// Opération : OPERATION_GRAD_ELLIPSE -// Click Souris: 1 ou 2 -// Taille_Pile : 6 (Mouse_K, color, X_Centre, Y_Centre, X_Tangente, Y_Tangente) -// -// Souris effacée: Non -// -{ - short tangent_x; - short tangent_y; - short center_x; - short center_y; - short color; - short horizontal_radius; - short vertical_radius; - - Operation_pop(&tangent_y); - Operation_pop(&tangent_x); - Operation_pop(¢er_y); - Operation_pop(¢er_x); - Operation_pop(&color); - - if ( (tangent_x!=Paintbrush_X) || (tangent_y!=Paintbrush_Y) ) - { - Hide_cursor(); - Display_coords_rel_or_abs(center_x,center_y); - - horizontal_radius=(tangent_x>center_x)?tangent_x-center_x - :center_x-tangent_x; - vertical_radius =(tangent_y>center_y)?tangent_y-center_y - :center_y-tangent_y; - Hide_empty_ellipse_preview(center_x,center_y,horizontal_radius,vertical_radius); - - horizontal_radius=(Paintbrush_X>center_x)?Paintbrush_X-center_x - :center_x-Paintbrush_X; - vertical_radius =(Paintbrush_Y>center_y)?Paintbrush_Y-center_y - :center_y-Paintbrush_Y; - Draw_empty_ellipse_preview(center_x,center_y,horizontal_radius,vertical_radius,color); - - Display_cursor(); - } - - Operation_push(color); - Operation_push(center_x); - Operation_push(center_y); - Operation_push(Paintbrush_X); - Operation_push(Paintbrush_Y); -} - - -void Grad_ellipse_0_6(void) -// -// Opération : OPERATION_GRAD_ELLIPSE -// Click Souris: 0 -// Taille_Pile : 6 (Mouse_K, color, X_Centre, Y_Centre, X_Tangente, Y_Tangente) -// -// Souris effacée: Oui -// -{ - short tangent_x; - short tangent_y; - short center_x; - short center_y; - short color; - short click; - //short radius; - short horizontal_radius; - short vertical_radius; - - Operation_pop(&tangent_y); - Operation_pop(&tangent_x); - Operation_pop(¢er_y); - Operation_pop(¢er_x); - - Operation_pop(&color); - Operation_pop(&click); - - if (click==LEFT_SIDE) - { - Operation_push(click); - Operation_push(color); - - Operation_push(center_x); - Operation_push(center_y); - Operation_push(tangent_x); - Operation_push(tangent_y); - - Operation_push(Paintbrush_X); - Operation_push(Paintbrush_Y); - - // On change la forme du curseur - Cursor_shape=CURSOR_SHAPE_XOR_TARGET; - - // On affiche une croix XOR au centre du cercle - Draw_curve_cross(center_x,center_y); - - if (Menu_is_visible) - { - if (Config.Coords_rel) - Print_in_menu("X: Y:",0); - else - Print_in_menu("X: Y: ",0); - Display_coords_rel_or_abs(center_x,center_y); - } - } - else - { - horizontal_radius=(tangent_x>center_x)?tangent_x-center_x - :center_x-tangent_x; - vertical_radius =(tangent_y>center_y)?tangent_y-center_y - :center_y-tangent_y; - Hide_empty_ellipse_preview(center_x,center_y,horizontal_radius,vertical_radius); - - Paintbrush_hidden=Paintbrush_hidden_before_scroll; - Cursor_shape=CURSOR_SHAPE_TARGET; - - Draw_filled_ellipse(center_x,center_y,horizontal_radius,vertical_radius,Back_color); - - if ((Config.Coords_rel) && (Menu_is_visible)) - { - Print_in_menu("X: Y: ",0); - Print_coordinates(); - } - } -} - - -void Grad_ellipse_12_8(void) -// -// Opération : OPERATION_GRAD_ELLIPSE -// Click Souris: 0 -// Taille_Pile : 8 (Mouse_K, color, X_Centre, Y_Centre, X_Tangente, Y_Tangente, old_x, old_y) -// -// Souris effacée: Oui -// -{ - short tangent_x; - short tangent_y; - short center_x; - short center_y; - short color; - short horizontal_radius; - short vertical_radius; - short old_mouse_k; - - Operation_stack_size-=2; // On fait sauter les 2 derniers élts de la pile - Operation_pop(&tangent_y); - Operation_pop(&tangent_x); - Operation_pop(¢er_y); - Operation_pop(¢er_x); - Operation_pop(&color); - Operation_pop(&old_mouse_k); - - Hide_cursor(); - // On efface la croix XOR au centre de l'ellipse - Draw_curve_cross(center_x,center_y); - - horizontal_radius=(tangent_x>center_x)?tangent_x-center_x - :center_x-tangent_x; - vertical_radius =(tangent_y>center_y)?tangent_y-center_y - :center_y-tangent_y; - Hide_empty_ellipse_preview(center_x,center_y,horizontal_radius,vertical_radius); - - Paintbrush_hidden=Paintbrush_hidden_before_scroll; - Cursor_shape=CURSOR_SHAPE_TARGET; - - if (Mouse_K==old_mouse_k) - Draw_grad_ellipse(center_x,center_y,horizontal_radius,vertical_radius,Paintbrush_X,Paintbrush_Y); - - Display_cursor(); - - Wait_end_of_click(); - - if ((Config.Coords_rel) && (Menu_is_visible)) - { - Print_in_menu("X: Y: ",0); - Print_coordinates(); - } -} - -/****************************** -* Operation_Rectangle_Degrade * -******************************/ - -// 1) tracé d'un rectangle classique avec les lignes XOR -// 2) tracé d'une ligne vecteur de dégradé, comme une ligne normale -// 3) dessin du dégradé - - -void Grad_rectangle_12_0(void) -// Opération : OPERATION_GRAD_RECTANGLE -// Click Souris: 1 ou 2 -// Taille_Pile : 0 -// -// Souris effacée: Oui - -// Initialisation de l'étape 1, on commence à dessiner le rectangle -{ - Init_start_operation(); - Backup(); - - if ((Config.Coords_rel) && (Menu_is_visible)) - Print_in_menu("\035: 1 \022: 1",0); - // On laisse une trace du curseur à l'écran - Display_cursor(); - - if (Mouse_K==LEFT_SIDE) - { - Shade_table=Shade_table_left; - Operation_push(Mouse_K); - } - else - { - Shade_table=Shade_table_right; - Operation_push(Mouse_K); - } - - Operation_push(Paintbrush_X); - Operation_push(Paintbrush_Y); - Operation_push(Paintbrush_X); - Operation_push(Paintbrush_Y); -} - - -void Grad_rectangle_12_5(void) -// Opération : OPERATION_GRAD_RECTANGLE -// Click Souris: 1 ou 2 -// Taille_Pile : 5 -// -// Souris effacée: Non - -// Modification de la taille du rectangle -{ - short start_x; - short start_y; - short old_x; - short old_y; - char str[5]; - - Operation_pop(&old_y); - Operation_pop(&old_x); - - if ((Paintbrush_X!=old_x) || (Paintbrush_Y!=old_y)) - { - Operation_pop(&start_y); - Operation_pop(&start_x); - - if ((Config.Coords_rel) && (Menu_is_visible)) - { - Num2str(((start_x Min(Main_image_width,Main_magnifier_mode?Main_separator_position:Screen_width)) // Tous les clippings à gérer sont là - offset_width = Max(rax,rbx) - Min(Main_image_width,Main_magnifier_mode?Main_separator_position:Screen_width); - - if (Max(ray,rby)-Main_offset_Y > Min(Main_image_height,Menu_Y)) - offset_height = Max(ray,rby) - Min(Main_image_height,Menu_Y); - - // Dessin dans la zone de dessin normale - Horizontal_XOR_line(Min(rax,rbx)-Main_offset_X,Min(ray,rby)-Main_offset_Y,width - offset_width); - if(offset_height == 0) - Horizontal_XOR_line(Min(rax,rbx)-Main_offset_X,Max(ray,rby)-1-Main_offset_Y,width - offset_width); - - Vertical_XOR_line(Min(rax,rbx)-Main_offset_X,Min(ray,rby)-Main_offset_Y,height-offset_height); - if (offset_width == 0) // Sinon cette ligne est en dehors de la zone image, inutile de la dessiner - Vertical_XOR_line(Max(rax,rbx)-1-Main_offset_X,Min(ray,rby)-Main_offset_Y,height-offset_height); - - Update_rect(Min(rax,rbx)-Main_offset_X,Min(ray,rby)-Main_offset_Y,width+1-offset_width,height+1-offset_height); - - // Dessin dans la zone zoomée - if(Main_magnifier_mode && Min(rax,rbx)Limit_left_zoom && Min(ray,rby)Limit_top_zoom ) - { - offset_width = 0; - offset_height=0; - - if(Min(rax,rbx)Limit_visible_right_zoom) // On dépasse du zoom à droite - offset_width += Max(rax,rbx) - Limit_visible_right_zoom; - - if(Min(ray,rby)Limit_visible_bottom_zoom) // On dépasse du zoom en bas - offset_height += Max(ray,rby) - Limit_visible_bottom_zoom; - - if(width > offset_width) - { - if(offset_top==0) // La ligne du haut est visible - Horizontal_XOR_line_zoom(offset_left>0?offset_left:Min(rax,rbx),Min(ray,rby),width-offset_width); - - if(Max(ray,rby)0?offset_left:Min(rax,rbx),Max(ray,rby),width-offset_width); - } - - if(height>offset_height) - { - if(offset_left==0) // La ligne de gauche est visible - Vertical_XOR_line_zoom(Min(rax,rbx),offset_top>0?offset_top:Min(ray,rby),height-offset_height); - - if(Max(rax,rbx)0?offset_top:Min(ray,rby),height-offset_height); - } - } - - Operation_push(rax); - Operation_push(ray); - Operation_push(rbx); - Operation_push(rby); - - // On ajoute des trucs dans la pile pour forcer le passage à l'étape suivante - Operation_push(rbx); - Operation_push(rby); -} - -void Grad_rectangle_0_7(void) -// OPERATION_GRAD_RECTANGLE -// click souris 0 -// Taile pile : 5 -// -// Souris effacée : non - -// On continue à attendre que l'utilisateur clique en gardant les coords à jour -{ - Operation_stack_size -= 2; - Print_coordinates(); - Operation_push(Paintbrush_X); - Operation_push(Paintbrush_Y); -} - -void Grad_rectangle_12_7(void) -// Opération : OPERATION_GRAD_RECTANGLE -// Click Souris: 1 ou 2 -// Taille_Pile : 7 -// -// Souris effacée: Oui - -// Début du tracé du vecteur (premier clic) -// On garde les anciennes coordonnées dans la pile, et on ajoute les nouvelles par dessus - -// Si l'utilisateur utilise le mauvais bouton, on annule le tracé. Mais ça nous oblige à vider toute la pile pour vérifier :( -{ - short rax,rbx,ray,rby,vax,vay,click; - - Operation_pop(&vay); - Operation_pop(&vax); - Operation_pop(&ray); - Operation_pop(&rax); - Operation_pop(&rby); - Operation_pop(&rbx); - Operation_pop(&click); - - - if(click==Mouse_K) - { - Operation_push(click); - Operation_push(rbx); - Operation_push(rby); - Operation_push(rax); - Operation_push(ray); - Operation_push(vax); - Operation_push(vay); - Operation_push(Paintbrush_X); - Operation_push(Paintbrush_Y); - - } - else - { - // Mauvais bouton > anulation de l'opération. - // On a déjà vidé la pile, il reste à effacer le rectangle XOR - short width, height; - short offset_width = 0; - short offset_height = 0; - short offset_left = 0; - short offset_top = 0; - - width = abs(rbx-rax); - height = abs(rby-ray); - - if (Max(rax,rbx)-Main_offset_X > Min(Main_image_width,Main_magnifier_mode?Main_separator_position:Screen_width)) // Tous les clippings à gérer sont là - offset_width = Max(rax,rbx) - Min(Main_image_width,Main_magnifier_mode?Main_separator_position:Screen_width); - - if (Max(ray,rby)-Main_offset_Y > Min(Main_image_height,Menu_Y)) - offset_height = Max(ray,rby) - Min(Main_image_height,Menu_Y); - - // Dessin dans la zone de dessin normale - Horizontal_XOR_line(Min(rax,rbx)-Main_offset_X,Min(ray,rby)-Main_offset_Y,width - offset_width); - if(offset_height == 0) - Horizontal_XOR_line(Min(rax,rbx)-Main_offset_X,Max(ray,rby)-1-Main_offset_Y,width - offset_width); - - Vertical_XOR_line(Min(rax,rbx)-Main_offset_X,Min(ray,rby)-Main_offset_Y,height-offset_height); - if (offset_width == 0) // Sinon cette ligne est en dehors de la zone image, inutile de la dessiner - Vertical_XOR_line(Max(rax,rbx)-1-Main_offset_X,Min(ray,rby)-Main_offset_Y,height-offset_height); - - Update_rect(Min(rax,rbx)-Main_offset_X,Min(ray,rby)-Main_offset_Y,width+1-offset_width,height+1-offset_height); - - // Dessin dans la zone zoomée - if(Main_magnifier_mode && Min(rax,rbx)Limit_left_zoom && Min(ray,rby)Limit_top_zoom ) - { - offset_width = 0; - offset_height=0; - - if(Min(rax,rbx)Limit_visible_right_zoom) // On dépasse du zoom à droite - offset_width += Max(rax,rbx) - Limit_visible_right_zoom; - - if(Min(ray,rby)Limit_visible_bottom_zoom) // On dépasse du zoom en bas - offset_height += Max(ray,rby) - Limit_visible_bottom_zoom; - - if(width > offset_width) - { - if(offset_top==0) // La ligne du haut est visible - Horizontal_XOR_line_zoom(offset_left>0?offset_left:Min(rax,rbx),Min(ray,rby),width-offset_width); - - if(Max(ray,rby)0?offset_left:Min(rax,rbx),Max(ray,rby),width-offset_width); - } - - if(height>offset_height) - { - if(offset_left==0) // La ligne de gauche est visible - Vertical_XOR_line_zoom(Min(rax,rbx),offset_top>0?offset_top:Min(ray,rby),height-offset_height); - - if(Max(rax,rbx)0?offset_top:Min(ray,rby),height-offset_height); - } - } - } -} - -void Grad_rectangle_12_9(void) - // Opération : OPERATION_GRAD_RECTANGLE - // Click Souris: 1 - // Taille_Pile : 5 - // - // Souris effacée: Oui - - // Poursuite du tracé du vecteur (déplacement de la souris en gardant le curseur appuyé) -{ - short start_x; - short start_y; - short end_x; - short end_y; - - Operation_pop(&end_y); - Operation_pop(&end_x); - Operation_pop(&start_y); - Operation_pop(&start_x); - - if ((Paintbrush_X!=end_x) || (Paintbrush_Y!=end_y)) - { - // On corrige les coordonnées de la ligne si la touche shift est appuyée... - if(SDL_GetModState() & KMOD_SHIFT) - Clamp_coordinates_45_degrees(start_x,start_y,&Paintbrush_X,&Paintbrush_Y); - - Display_coords_rel_or_abs(start_x,start_y); - - Draw_line_preview_xor(start_x,start_y,end_x,end_y,0); - Draw_line_preview_xor(start_x,start_y,Paintbrush_X,Paintbrush_Y,0); - - } - - - Operation_push(start_x); - Operation_push(start_y); - Operation_push(Paintbrush_X); - Operation_push(Paintbrush_Y); -} - -void Grad_rectangle_0_9(void) - // Opération : OPERATION_GRAD_RECTANGLE - // Click Souris: 0 - // Taille_Pile : 9 - // - // Souris effacée: Oui - - // Ouf, fini ! on dessine enfin le rectangle avec son dégradé -{ - short rect_start_x; - short rect_start_y; - short rect_end_x; - short rect_end_y; - - short vector_start_x; - short vector_start_y; - short vector_end_x; - short vector_end_y; - - Operation_pop(&vector_end_y); - Operation_pop(&vector_end_x); - Operation_pop(&vector_start_y); - Operation_pop(&vector_start_x); - Operation_pop(&rect_end_y); - Operation_pop(&rect_end_x); - Operation_pop(&rect_start_y); - Operation_pop(&rect_start_x); - Operation_stack_size--; - - Hide_cursor(); - // Maintenant on efface tout le bazar temporaire : rectangle et ligne XOR - Hide_line_preview(vector_start_x,vector_start_y,vector_end_x,vector_end_y); - - // Et enfin on trace le rectangle avec le dégradé dedans ! - if (vector_end_x==vector_start_x && vector_end_y==vector_start_y) - { - // Vecteur nul > pas de rectangle tracé - // Du coup on doit effacer la preview xor ... - short width, height; - short offset_width = 0; - short offset_height = 0; - short offset_left = 0; - short offset_top = 0; - - width = abs(rect_end_x-rect_start_x); - height = abs(rect_end_y-rect_start_y); - - if (Max(rect_start_x,rect_end_x)-Main_offset_X > Min(Main_image_width,Main_magnifier_mode?Main_separator_position:Screen_width)) // Tous les clippings à gérer sont là - offset_width = Max(rect_start_x,rect_end_x) - Min(Main_image_width,Main_magnifier_mode?Main_separator_position:Screen_width); - - if (Max(rect_start_y,rect_end_y)-Main_offset_Y > Min(Main_image_height,Menu_Y)) - offset_height = Max(rect_start_y,rect_end_y) - Min(Main_image_height,Menu_Y); - - // Dessin dans la zone de dessin normale - Horizontal_XOR_line(Min(rect_start_x,rect_end_x)-Main_offset_X,Min(rect_start_y,rect_end_y)-Main_offset_Y,width - offset_width); - if(offset_height == 0) - Horizontal_XOR_line(Min(rect_start_x,rect_end_x)-Main_offset_X,Max(rect_start_y,rect_end_y)-1-Main_offset_Y,width - offset_width); - - Vertical_XOR_line(Min(rect_start_x,rect_end_x)-Main_offset_X,Min(rect_start_y,rect_end_y)-Main_offset_Y,height-offset_height); - if (offset_width == 0) // Sinon cette ligne est en dehors de la zone image, inutile de la dessiner - Vertical_XOR_line(Max(rect_start_x,rect_end_x)-1-Main_offset_X,Min(rect_start_y,rect_end_y)-Main_offset_Y,height-offset_height); - - Update_rect(Min(rect_start_x,rect_end_x)-Main_offset_X,Min(rect_start_y,rect_end_y)-Main_offset_Y,width+1-offset_width,height+1-offset_height); - - // Dessin dans la zone zoomée - if(Main_magnifier_mode && Min(rect_start_x,rect_end_x)Limit_left_zoom && Min(rect_start_y,rect_end_y)Limit_top_zoom ) - { - offset_width = 0; - offset_height=0; - - if(Min(rect_start_x,rect_end_x)Limit_visible_right_zoom) // On dépasse du zoom à droite - offset_width += Max(rect_start_x,rect_end_x) - Limit_visible_right_zoom; - - if(Min(rect_start_y,rect_end_y)Limit_visible_bottom_zoom) // On dépasse du zoom en bas - offset_height += Max(rect_start_y,rect_end_y) - Limit_visible_bottom_zoom; - - if(width > offset_width) - { - if(offset_top==0) // La ligne du haut est visible - Horizontal_XOR_line_zoom(offset_left>0?offset_left:Min(rect_start_x,rect_end_x),Min(rect_start_y,rect_end_y),width-offset_width); - - if(Max(rect_start_y,rect_end_y)0?offset_left:Min(rect_start_x,rect_end_x),Max(rect_start_y,rect_end_y),width-offset_width); - } - - if(height>offset_height) - { - if(offset_left==0) // La ligne de gauche est visible - Vertical_XOR_line_zoom(Min(rect_start_x,rect_end_x),offset_top>0?offset_top:Min(rect_start_y,rect_end_y),height-offset_height); - - if(Max(rect_start_x,rect_end_x)0?offset_top:Min(rect_start_y,rect_end_y),height-offset_height); - } - } - } - else - Draw_grad_rectangle(rect_start_x,rect_start_y,rect_end_x,rect_end_y,vector_start_x,vector_start_y,vector_end_x,vector_end_y); - - Display_cursor(); - Wait_end_of_click(); - - if ((Config.Coords_rel) && (Menu_is_visible)) - { - Print_in_menu("X: Y: ",0); - Print_coordinates(); - } -} -/////////////////////////////////////////////////// OPERATION_CENTERED_LINES - - -void Centered_lines_12_0(void) - // Opération : OPERATION_CENTERED_LINES - // Click Souris: 1 ou 2 - // Taille_Pile : 0 - // - // Souris effacée: Oui -{ - Init_start_operation(); - Backup(); - Shade_table=(Mouse_K==LEFT_SIDE)?Shade_table_left:Shade_table_right; - - if ((Config.Coords_rel) && (Menu_is_visible)) - Print_in_menu("X:± 0 Y:± 0",0); - - Operation_push(Mouse_K); - Operation_push(Paintbrush_X); - Operation_push(Paintbrush_Y); -} - - -void Centered_lines_12_3(void) - // Opération : OPERATION_CENTERED_LINES - // Click Souris: 1 ou 2 - // Taille_Pile : 3 - // - // Souris effacée: Non -{ - short start_x; - short start_y; - - Operation_pop(&start_y); - Operation_pop(&start_x); - Operation_push(Paintbrush_X); - Operation_push(Paintbrush_Y); -} - - -void Centered_lines_0_3(void) - // Opération : OPERATION_CENTERED_LINES - // Click Souris: 0 - // Taille_Pile : 3 - // - // Souris effacée: Oui -{ - short start_x; - short start_y; - short Button; - short color; - - Operation_pop(&start_y); - Operation_pop(&start_x); - Operation_pop(&Button); - - color=(Button==LEFT_SIDE)?Fore_color:Back_color; - - Pixel_figure_preview(Paintbrush_X,Paintbrush_Y,color); - Paintbrush_shape_before_operation=Paintbrush_shape; - Paintbrush_shape=PAINTBRUSH_SHAPE_POINT; - - Operation_push(Button); - Operation_push(Paintbrush_X); // Nouveau début X - Operation_push(Paintbrush_Y); // Nouveau début Y - Operation_push(Paintbrush_X); // Nouvelle dernière fin X - Operation_push(Paintbrush_Y); // Nouvelle dernière fin Y - Operation_push(Paintbrush_X); // Nouvelle dernière position X - Operation_push(Paintbrush_Y); // Nouvelle dernière position Y -} - - -void Centered_lines_12_7(void) - // Opération : OPERATION_CENTERED_LINES - // Click Souris: 1 ou 2 - // Taille_Pile : 7 - // - // Souris effacée: Non -{ - short Button; - short start_x; - short start_y; - short end_x; - short end_y; - short last_x; - short last_y; - short color; - - Operation_pop(&last_y); - Operation_pop(&last_x); - Operation_pop(&end_y); - Operation_pop(&end_x); - Operation_pop(&start_y); - Operation_pop(&start_x); - Operation_pop(&Button); - - if (Mouse_K==Button) - { - if ( (end_x!=Paintbrush_X) || (end_y!=Paintbrush_Y) || - (last_x!=Paintbrush_X) || (last_y!=Paintbrush_Y) ) - { - Hide_cursor(); - - color=(Button==LEFT_SIDE)?Fore_color:Back_color; - - Paintbrush_shape=Paintbrush_shape_before_operation; - - Pixel_figure_preview_auto (start_x,start_y); - Hide_line_preview (start_x,start_y,last_x,last_y); - - Smear_start=1; - Display_paintbrush (start_x,start_y,color,0); - Draw_line_permanet(start_x,start_y,Paintbrush_X,Paintbrush_Y,color); - - Paintbrush_shape=PAINTBRUSH_SHAPE_POINT; - Pixel_figure_preview(Paintbrush_X,Paintbrush_Y,color); - Draw_line_preview(start_x,start_y,Paintbrush_X,Paintbrush_Y,color); - - Display_cursor(); - } - - Operation_push(Button); - Operation_push(start_x); - Operation_push(start_y); - Operation_push(Paintbrush_X); - Operation_push(Paintbrush_Y); - Operation_push(Paintbrush_X); - Operation_push(Paintbrush_Y); - } - else - { - Hide_cursor(); - - Paintbrush_shape=Paintbrush_shape_before_operation; - - Pixel_figure_preview_auto (start_x,start_y); - Hide_line_preview (start_x,start_y,last_x,last_y); - - if ( (Config.Coords_rel) && (Menu_is_visible) ) - { - Print_in_menu("X: Y: ",0); - Print_coordinates(); - } - - Display_cursor(); - Wait_end_of_click(); - } -} - - -void Centered_lines_0_7(void) - // Opération : OPERATION_CENTERED_LINES - // Click Souris: 0 - // Taille_Pile : 7 - // - // Souris effacée: Non -{ - short Button; - short start_x; - short start_y; - short end_x; - short end_y; - short last_x; - short last_y; - short color; - - Operation_pop(&last_y); - Operation_pop(&last_x); - Operation_pop(&end_y); - Operation_pop(&end_x); - - if ((Paintbrush_X!=last_x) || (Paintbrush_Y!=last_y)) - { - Hide_cursor(); - Operation_pop(&start_y); - Operation_pop(&start_x); - Operation_pop(&Button); - - color=(Button==LEFT_SIDE)?Fore_color:Back_color; - - Display_coords_rel_or_abs(start_x,start_y); - - Hide_line_preview(start_x,start_y,last_x,last_y); - - Pixel_figure_preview(start_x,start_y,color); - Draw_line_preview(start_x,start_y,Paintbrush_X,Paintbrush_Y,color); - - Operation_push(Button); - Operation_push(start_x); - Operation_push(start_y); - Display_cursor(); - } - - Operation_push(end_x); - Operation_push(end_y); - Operation_push(Paintbrush_X); - Operation_push(Paintbrush_Y); -} - - +/* Grafx2 - The Ultimate 256-color bitmap paint program + + Copyright 2007 Adrien Destugues + Copyright 2009 Franck Charlet + Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) + + Grafx2 is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 + of the License. + + Grafx2 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grafx2; if not, see +*/ +#include +#include +#include + +#include "const.h" +#include "struct.h" +#include "global.h" +#include "misc.h" +#include "engine.h" +#include "graph.h" +#include "operatio.h" +#include "buttons.h" +#include "pages.h" +#include "errors.h" +#include "sdlscreen.h" +#include "brush.h" +#include "windows.h" + +#if defined(__GP2X__) + #define M_PI 3.14159265358979323846 +#endif + +/// Time (in SDL ticks) when the next airbrush drawing should be done. Also used +/// for discontinuous freehand drawing. +Uint32 Airbrush_next_time; + +void Start_operation_stack(word new_operation) +{ + Brush_rotation_center_is_defined=0; + + // On mémorise l'opération précédente si on démarre une interruption + switch(new_operation) + { + case OPERATION_MAGNIFY : + case OPERATION_COLORPICK : + case OPERATION_GRAB_BRUSH : + case OPERATION_POLYBRUSH : + case OPERATION_STRETCH_BRUSH : + case OPERATION_ROTATE_BRUSH: + Operation_before_interrupt=Current_operation; + // On passe à l'operation demandée + Current_operation=new_operation; + break; + default : + // On passe à l'operation demandée + Current_operation=new_operation; + Operation_before_interrupt=Current_operation; + } + + // On spécifie si l'opération autorise le changement de couleur au clavier + switch(new_operation) + { + case OPERATION_CONTINUOUS_DRAW: + case OPERATION_DISCONTINUOUS_DRAW: + case OPERATION_AIRBRUSH: + case OPERATION_CENTERED_LINES: + Allow_color_change_during_operation=1; + break; + default : + Allow_color_change_during_operation=0; + } + + // Et on passe au curseur qui va avec + Cursor_shape=CURSOR_FOR_OPERATION[new_operation]; + Operation_stack_size=0; +} + + +void Init_start_operation(void) +{ + Operation_in_magnifier=(Mouse_X>=Main_X_zoom); + Smear_start=1; +} + + +void Operation_push(short value) +{ + Operation_stack[++Operation_stack_size]=value; +} + + +void Operation_pop(short * value) +{ + *value=Operation_stack[Operation_stack_size--]; +} + + +byte Paintbrush_shape_before_operation; +byte Paintbrush_hidden_before_scroll; + + + +short Distance(short x1, short y1, short x2, short y2) +{ + short x2_moins_x1=x2-x1; + short y2_minus_y1=y2-y1; + + return Round( sqrt( (x2_moins_x1*x2_moins_x1) + (y2_minus_y1*y2_minus_y1) ) ); +} + + +void Display_coords_rel_or_abs(short start_x, short start_y) +{ + char str[6]; + + if (Config.Coords_rel) + { + if (Menu_is_visible) + { + if (Paintbrush_X>start_x) + { + Num2str(Paintbrush_X-start_x,str,5); + str[0]='+'; + } + else if (Paintbrush_Xstart_y) + { + Num2str(Paintbrush_Y-start_y,str,5); + str[0]='+'; + } + else if (Paintbrush_YAirbrush_next_time) + { + Airbrush_next_time+=Airbrush_delay*10; + Hide_cursor(); + // On affiche définitivement le pinceau + Display_paintbrush(Paintbrush_X,Paintbrush_Y,Fore_color,0); + Display_cursor(); + } + } + + Operation_push(Paintbrush_X); + Operation_push(Paintbrush_Y); +} + +// ---------- + +void Freehand_mode2_2_0(void) +// Opération : OPERATION_DISCONTINUOUS_DRAW +// Click Souris: 2 +// Taille_Pile : 0 +// +// Souris effacée: Oui +{ + Init_start_operation(); + Backup(); + Shade_table=Shade_table_right; + Operation_push(Paintbrush_X); + Operation_push(Paintbrush_Y); + Print_coordinates(); + Airbrush_next_time = SDL_GetTicks() + Airbrush_delay*10; + // On affiche définitivement le pinceau + Display_paintbrush(Paintbrush_X,Paintbrush_Y,Back_color,0); +} + + +void Freehand_mode2_2_2(void) +// Opération : OPERATION_DISCONTINUOUS_DRAW +// Click Souris: 2 +// Taille_Pile : 2 +// +// Souris effacée: Non +{ + short start_x; + short start_y; + + Operation_pop(&start_y); + Operation_pop(&start_x); + + if ( (start_x!=Paintbrush_X) || (start_y!=Paintbrush_Y) ) + { + Print_coordinates(); + if (SDL_GetTicks()>Airbrush_next_time) + { + Airbrush_next_time+=Airbrush_delay*10; + Hide_cursor(); + // On affiche définitivement le pinceau + Display_paintbrush(Paintbrush_X,Paintbrush_Y,Back_color,0); + Display_cursor(); + } + } + + Operation_push(Paintbrush_X); + Operation_push(Paintbrush_Y); +} + + +////////////////////////////////////////////////////// OPERATION_POINT_DRAW + +void Freehand_mode3_1_0(void) +// Opération : OPERATION_POINT_DRAW +// Click Souris: 1 +// Taille_Pile : 0 +// +// Souris effacée: Oui +{ + Init_start_operation(); + Backup(); + Shade_table=Shade_table_left; + // On affiche définitivement le pinceau + Display_paintbrush(Paintbrush_X,Paintbrush_Y,Fore_color,0); + Operation_push(0); // On change simplement l'état de la pile... +} + + +void Freehand_Mode3_2_0(void) +// Opération : OPERATION_POINT_DRAW +// Click Souris: 2 +// Taille_Pile : 0 +// +// Souris effacée: Oui +{ + Init_start_operation(); + Backup(); + Shade_table=Shade_table_right; + // On affiche définitivement le pinceau + Display_paintbrush(Paintbrush_X,Paintbrush_Y,Back_color,0); + Operation_push(0); // On change simplement l'état de la pile... +} + + +void Freehand_mode3_0_1(void) +// Opération : OPERATION_POINT_DRAW +// Click Souris: 0 +// Taille_Pile : 1 +// +// Souris effacée: Non +{ + End_of_modification(); + Operation_stack_size--; +} + + +///////////////////////////////////////////////////////////// OPERATION_LINE + +void Line_12_0(void) +// Opération : OPERATION_LINE +// Click Souris: 1 ou 2 +// Taille_Pile : 0 +// +// Souris effacée: Oui + +// Début du tracé d'une ligne (premier clic) +{ + Init_start_operation(); + Backup(); + Paintbrush_shape_before_operation=Paintbrush_shape; + Paintbrush_shape=PAINTBRUSH_SHAPE_POINT; + + if (Mouse_K==LEFT_SIDE) + { + Shade_table=Shade_table_left; + Pixel_figure_preview(Paintbrush_X,Paintbrush_Y,Fore_color); + Update_part_of_screen(Paintbrush_X,Paintbrush_Y,1,1); + Operation_push(Fore_color); + } + else + { + Shade_table=Shade_table_right; + Pixel_figure_preview(Paintbrush_X,Paintbrush_Y,Back_color); + Update_part_of_screen(Paintbrush_X,Paintbrush_Y,1,1); + Operation_push(Back_color); + } + + if ((Config.Coords_rel) && (Menu_is_visible)) + Print_in_menu("X:± 0 Y:± 0",0); + + Operation_push(Paintbrush_X); + Operation_push(Paintbrush_Y); + Operation_push(Paintbrush_X); + Operation_push(Paintbrush_Y); +} + + +void Line_12_5(void) +// Opération : OPERATION_LINE +// Click Souris: 1 +// Taille_Pile : 5 +// +// Souris effacée: Non + +// Poursuite du tracé d'une ligne (déplacement de la souris en gardant le +// curseur appuyé) +{ + short start_x; + short start_y; + short end_x; + short end_y; + + short cursor_x; + short cursor_y; + + Operation_pop(&end_y); + Operation_pop(&end_x); + Operation_pop(&start_y); + Operation_pop(&start_x); + + cursor_x = Paintbrush_X; + cursor_y = Paintbrush_Y; + + // On corrige les coordonnées de la ligne si la touche shift est appuyée... + if(SDL_GetModState() & KMOD_SHIFT) + { + Clamp_coordinates_regular_angle(start_x,start_y,&cursor_x,&cursor_y); + } + + // On vient de bouger + if ((cursor_x!=end_x) || (cursor_y!=end_y)) + { + Hide_cursor(); + + Display_coords_rel_or_abs(start_x,start_y); + + Hide_line_preview(start_x,start_y,end_x,end_y); + if (Mouse_K==LEFT_SIDE) + { + Pixel_figure_preview (start_x,start_y,Fore_color); + Draw_line_preview (start_x,start_y,cursor_x,cursor_y,Fore_color); + } + else + { + Pixel_figure_preview (start_x,start_y,Back_color); + Draw_line_preview (start_x,start_y,cursor_x,cursor_y,Back_color); + } + + Operation_push(start_x); + Operation_push(start_y); + Operation_push(cursor_x); + Operation_push(cursor_y); + + Display_cursor(); + } + else + { + Operation_push(start_x); + Operation_push(start_y); + Operation_push(end_x); + Operation_push(end_y); + } +} + + +void Line_0_5(void) +// Opération : OPERATION_LINE +// Click Souris: 0 +// Taille_Pile : 5 +// +// Souris effacée: Oui + +// End du tracé d'une ligne (relachage du bouton) +{ + short start_x; + short start_y; + short end_x; + short end_y; + short color; + + Operation_pop(&end_y); + Operation_pop(&end_x); + Operation_pop(&start_y); + Operation_pop(&start_x); + Operation_pop(&color); + + Paintbrush_shape=Paintbrush_shape_before_operation; + + Pixel_figure_preview_auto (start_x,start_y); + Hide_line_preview (start_x,start_y,end_x,end_y); + Display_paintbrush (start_x,start_y,color,0); + Draw_line_permanent(start_x,start_y,end_x,end_y,color); + + End_of_modification(); + if ( (Config.Coords_rel) && (Menu_is_visible) ) + { + Print_in_menu("X: Y: ",0); + Print_coordinates(); + } +} + + +/////////////////////////////////////////////////////////// OPERATION_K_LIGNE + + +void K_line_12_0(void) +// Opération : OPERATION_K_LIGNE +// Click Souris: 1 ou 2 +// Taille_Pile : 0 +// +// Souris effacée: Oui +{ + byte color; + + Init_start_operation(); + Backup(); + Shade_table=(Mouse_K==LEFT_SIDE)?Shade_table_left:Shade_table_right; + Paintbrush_shape_before_operation=Paintbrush_shape; + Paintbrush_shape=PAINTBRUSH_SHAPE_POINT; + + color=(Mouse_K==LEFT_SIDE)?Fore_color:Back_color; + + // On place temporairement le début de la ligne qui ne s'afficherait pas sinon + Pixel_figure_preview(Paintbrush_X,Paintbrush_Y,color); + + if ((Config.Coords_rel) && (Menu_is_visible)) + Print_in_menu("X:± 0 Y:± 0",0); + + Operation_push(Mouse_K | 0x80); + Operation_push(color); + Operation_push(Paintbrush_X); + Operation_push(Paintbrush_Y); + Operation_push(Paintbrush_X); + Operation_push(Paintbrush_Y); + // Taille de pile 6 : phase d'appui, non interruptible +} + + +void K_line_12_6(void) +// Opération : OPERATION_K_LIGNE +// Click Souris: 1 ou 2 | 0 +// Taille_Pile : 6 | 7 +// +// Souris effacée: Non +{ + short start_x; + short start_y; + short end_x; + short end_y; + short color; + + Operation_pop(&end_y); + Operation_pop(&end_x); + + if ((Paintbrush_X!=end_x) || (Paintbrush_Y!=end_y)) + { + Hide_cursor(); + Operation_pop(&start_y); + Operation_pop(&start_x); + Operation_pop(&color); + + Display_coords_rel_or_abs(start_x,start_y); + + Hide_line_preview(start_x,start_y,end_x,end_y); + Pixel_figure_preview (start_x,start_y,color); + Draw_line_preview (start_x,start_y,Paintbrush_X,Paintbrush_Y,color); + + Operation_push(color); + Operation_push(start_x); + Operation_push(start_y); + Display_cursor(); + } + + Operation_push(Paintbrush_X); + Operation_push(Paintbrush_Y); +} + + +void K_line_0_6(void) +// Opération : OPERATION_K_LIGNE +// Click Souris: 0 +// Taille_Pile : 6 +// +// Souris effacée: Oui +{ + short start_x; + short start_y; + short end_x; + short end_y; + short color; + short direction; + + Operation_pop(&end_y); + Operation_pop(&end_x); + Operation_pop(&start_y); + Operation_pop(&start_x); + Operation_pop(&color); + Operation_pop(&direction); + + if ((Config.Coords_rel) && (Menu_is_visible)) + Print_in_menu("X:± 0 Y:± 0",0); + + Pixel_figure_preview_auto (start_x,start_y); + Hide_line_preview (start_x,start_y,end_x,end_y); + /* Doesn't work if fast moving + Pixel_figure_preview_xor (start_x,start_y, 0); + Draw_line_preview_xor (start_x,start_y,end_x,end_y,0); + */ + Paintbrush_shape=Paintbrush_shape_before_operation; + if (direction & 0x80) + { + Display_paintbrush(start_x,start_y,color,0); + direction=(direction & 0x7F); + } + Draw_line_permanent(start_x,start_y,Paintbrush_X,Paintbrush_Y,color); + Paintbrush_shape=PAINTBRUSH_SHAPE_POINT; + + Operation_push(direction); + Operation_push(direction); // Valeur bidon servant de nouvel état de pile + Operation_push(color); + Operation_push(Paintbrush_X); + Operation_push(Paintbrush_Y); + Operation_push(Paintbrush_X); + Operation_push(Paintbrush_Y); + // Taille de pile 7 : phase de "repos", interruptible (comme Elliot Ness :)) +} + + +void K_line_12_7(void) +// Opération : OPERATION_K_LIGNE +// Click Souris: 1 ou 2 +// Taille_Pile : 7 +// +// Souris effacée: Oui +{ + short start_x; + short start_y; + short end_x; + short end_y; + short color; + short direction; + + Operation_pop(&end_y); + Operation_pop(&end_x); + Operation_pop(&start_y); + Operation_pop(&start_x); + Operation_pop(&color); + Operation_pop(&direction); + Operation_pop(&direction); + + if (direction==Mouse_K) + { + Operation_push(direction); + Operation_push(color); + Operation_push(start_x); + Operation_push(start_y); + Operation_push(end_x); + Operation_push(end_y); + // Taille de pile 6 : phase d'appui, non interruptible + } + else + { + // La série de ligne est terminée, il faut donc effacer la dernière + // preview de ligne + Pixel_figure_preview_auto (start_x,start_y); + Hide_line_preview (start_x,start_y,end_x,end_y); + + Display_cursor(); + Wait_end_of_click(); + Hide_cursor(); + Paintbrush_shape=Paintbrush_shape_before_operation; + + End_of_modification(); + if ( (Config.Coords_rel) && (Menu_is_visible) ) + { + Print_in_menu("X: Y: ",0); + Print_coordinates(); + } + } +} + + +// ---------------------------------------------------------- OPERATION_MAGNIFY + + +void Magnifier_12_0(void) + +// Opération : 4 (item d'une Loupe) +// Click Souris: 1 ou 2 +// Taille_Pile : 0 +// +// Souris effacée: Oui + +{ + + // On passe en mode loupe + Main_magnifier_mode=1; + + // La fonction d'affichage dans la partie image est désormais un affichage + // spécial loupe. + Pixel_preview=Pixel_preview_magnifier; + + // On calcule l'origine de la loupe + Main_magnifier_offset_X=Mouse_X-(Main_magnifier_width>>1); + Main_magnifier_offset_Y=Mouse_Y-(Main_magnifier_height>>1); + + // Calcul du coin haut_gauche de la fenêtre devant être zoomée DANS L'ECRAN + if (Main_magnifier_offset_X+Main_magnifier_width>=Limit_right-Main_offset_X) + Main_magnifier_offset_X=Limit_right-Main_magnifier_width-Main_offset_X+1; + if (Main_magnifier_offset_Y+Main_magnifier_height>=Limit_bottom-Main_offset_Y) + Main_magnifier_offset_Y=Limit_bottom-Main_magnifier_height-Main_offset_Y+1; + + // Calcul des coordonnées absolues de ce coin DANS L'IMAGE + Main_magnifier_offset_X+=Main_offset_X; + Main_magnifier_offset_Y+=Main_offset_Y; + + if (Main_magnifier_offset_X<0) + Main_magnifier_offset_X=0; + if (Main_magnifier_offset_Y<0) + Main_magnifier_offset_Y=0; + + // On calcule les bornes visibles dans l'écran + Position_screen_according_to_zoom(); + Compute_limits(); + Display_all_screen(); + + // Repositionner le curseur en fonction des coordonnées visibles + Compute_paintbrush_coordinates(); + + // On fait de notre mieux pour restaurer l'ancienne opération: + Start_operation_stack(Operation_before_interrupt); + Display_cursor(); + Wait_end_of_click(); +} + +/////////////////////////////////////////////////// OPERATION_RECTANGLE_????? + +void Rectangle_12_0(void) +// Opération : OPERATION_EMPTY_RECTANGLE / OPERATION_FILLED_RECTANGLE +// Click Souris: 1 ou 2 +// Taille_Pile : 0 +// +// Souris effacée: Oui +{ + Init_start_operation(); + + if ((Config.Coords_rel) && (Menu_is_visible)) + Print_in_menu("\035: 1 \022: 1",0); + // On laisse une trace du curseur à l'écran + Display_cursor(); + + if (Mouse_K==LEFT_SIDE) + { + Shade_table=Shade_table_left; + Operation_push(Fore_color); + } + else + { + Shade_table=Shade_table_right; + Operation_push(Back_color); + } + + Operation_push(Paintbrush_X); + Operation_push(Paintbrush_Y); + Operation_push(Paintbrush_X); + Operation_push(Paintbrush_Y); +} + + +void Rectangle_12_5(void) +// Opération : OPERATION_EMPTY_RECTANGLE / OPERATION_FILLED_RECTANGLE +// Click Souris: 1 ou 2 +// Taille_Pile : 5 +// +// Souris effacée: Non +{ + short start_x; + short start_y; + short old_x; + short old_y; + char str[5]; + + Operation_pop(&old_y); + Operation_pop(&old_x); + + if ((Paintbrush_X!=old_x) || (Paintbrush_Y!=old_y)) + { + Operation_pop(&start_y); + Operation_pop(&start_x); + + if ((Config.Coords_rel) && (Menu_is_visible)) + { + Num2str(((start_xcenter_x)?tangent_x-center_x + :center_x-tangent_x; + vertical_radius =(tangent_y>center_y)?tangent_y-center_y + :center_y-tangent_y; + Hide_empty_ellipse_preview(center_x,center_y,horizontal_radius,vertical_radius); + + horizontal_radius=(Paintbrush_X>center_x)?Paintbrush_X-center_x + :center_x-Paintbrush_X; + vertical_radius =(Paintbrush_Y>center_y)?Paintbrush_Y-center_y + :center_y-Paintbrush_Y; + Draw_empty_ellipse_preview(center_x,center_y,horizontal_radius,vertical_radius,color); + + Display_cursor(); + } + + Operation_push(color); + Operation_push(center_x); + Operation_push(center_y); + Operation_push(Paintbrush_X); + Operation_push(Paintbrush_Y); +} + + +void Empty_ellipse_0_5(void) +// +// Opération : OPERATION_EMPTY_ELLIPSE +// Click Souris: 0 +// Taille_Pile : 5 (color, X_Centre, Y_Centre, X_Tangente, Y_Tangente) +// +// Souris effacée: Oui +// +{ + short tangent_x; + short tangent_y; + short center_x; + short center_y; + short color; + short horizontal_radius; + short vertical_radius; + + Operation_pop(&tangent_y); + Operation_pop(&tangent_x); + Operation_pop(¢er_y); + Operation_pop(¢er_x); + Operation_pop(&color); + + horizontal_radius=(tangent_x>center_x)?tangent_x-center_x + :center_x-tangent_x; + vertical_radius =(tangent_y>center_y)?tangent_y-center_y + :center_y-tangent_y; + Hide_empty_ellipse_preview(center_x,center_y,horizontal_radius,vertical_radius); + + Paintbrush_shape=Paintbrush_shape_before_operation; + + Draw_empty_ellipse_permanent(center_x,center_y,horizontal_radius,vertical_radius,color); + + End_of_modification(); + + if ( (Config.Coords_rel) && (Menu_is_visible) ) + { + Print_in_menu("X: Y: ",0); + Print_coordinates(); + } +} + + +void Filled_ellipse_0_5(void) +// +// Opération : OPERATION_FILLED_ELLIPSE +// Click Souris: 0 +// Taille_Pile : 5 (color, X_Centre, Y_Centre, X_Tangente, Y_Tangente) +// +// Souris effacée: Oui +// +{ + short tangent_x; + short tangent_y; + short center_x; + short center_y; + short color; + short horizontal_radius; + short vertical_radius; + + Operation_pop(&tangent_y); + Operation_pop(&tangent_x); + Operation_pop(¢er_y); + Operation_pop(¢er_x); + Operation_pop(&color); + + horizontal_radius=(tangent_x>center_x)?tangent_x-center_x + :center_x-tangent_x; + vertical_radius =(tangent_y>center_y)?tangent_y-center_y + :center_y-tangent_y; + Hide_empty_ellipse_preview(center_x,center_y,horizontal_radius,vertical_radius); + + Paintbrush_shape=Paintbrush_shape_before_operation; + + Draw_filled_ellipse(center_x,center_y,horizontal_radius,vertical_radius,color); + + End_of_modification(); + if ( (Config.Coords_rel) && (Menu_is_visible) ) + { + Print_in_menu("X: Y: ",0); + Print_coordinates(); + } +} + + +////////////////////////////////////////////////////////////// OPERATION_FILL + + +void Fill_1_0(void) +// +// Opération : OPERATION_FILL +// Click Souris: 1 +// Taille_Pile : 0 +// +// Souris effacée: Oui +// +{ + Hide_cursor(); + // Pas besoin d'initialiser le début d'opération car le Smear n'affecte pas + // le Fill, et on se fout de savoir si on est dans la partie gauche ou + // droite de la loupe. + // On ne s'occupe pas de faire un Backup: c'est "Fill_general" qui s'en charge. + Shade_table=Shade_table_left; + Fill_general(Fore_color); + Display_cursor(); + End_of_modification(); + Wait_end_of_click(); +} + + +void Fill_2_0(void) +// +// Opération : OPERATION_FILL +// Click Souris: 2 +// Taille_Pile : 0 +// +// Souris effacée: Oui +// +{ + Hide_cursor(); + // Pas besoin d'initialiser le début d'opération car le Smear n'affecte pas + // le Fill, et on se fout de savoir si on est dans la partie gauche ou + // droite de la loupe. + // On ne s'occupe pas de faire un Backup: c'est "Fill_general" qui s'en charge. + Shade_table=Shade_table_right; + Fill_general(Back_color); + Display_cursor(); + End_of_modification(); + Wait_end_of_click(); +} + + +///////////////////////////////////////////////////////// OPERATION_REPLACE + + +void Replace_1_0(void) +// +// Opération : OPERATION_REPLACE +// Click Souris: 1 +// Taille_Pile : 0 +// +// Souris effacée: Oui +// +{ + Hide_cursor(); + // Pas besoin d'initialiser le début d'opération car le Smear n'affecte pas + // le Replace, et on se fout de savoir si on est dans la partie gauche ou + // droite de la loupe. + Backup(); +// Shade_table=Shade_table_left; + Replace(Fore_color); + Display_cursor(); + End_of_modification(); + Wait_end_of_click(); +} + + +void Replace_2_0(void) +// +// Opération : OPERATION_REPLACE +// Click Souris: 2 +// Taille_Pile : 0 +// +// Souris effacée: Oui +// +{ + Hide_cursor(); + // Pas besoin d'initialiser le début d'opération car le Smear n'affecte pas + // le Replace, et on se fout de savoir si on est dans la partie gauche ou + // droite de la loupe. + Backup(); +// Shade_table=Shade_table_right; + Replace(Back_color); + Display_cursor(); + End_of_modification(); + Wait_end_of_click(); +} + + +/////////////////////////////////////////////////////////// OPERATION_COLORPICK + + +void Colorpicker_12_0(void) +// +// Opération : OPERATION_COLORPICK +// Click Souris: 1 ou 2 +// Taille_Pile : 0 +// +// Souris effacée: Oui +// +{ + Init_start_operation(); + + if (Mouse_K==LEFT_SIDE) + { + Set_fore_color(Colorpicker_color); + } + else + { + Set_back_color(Colorpicker_color); + } + Operation_push(Mouse_K); +} + + +void Colorpicker_1_1(void) +// +// Opération : OPERATION_COLORPICK +// Click Souris: 1 +// Taille_Pile : 1 +// +// Souris effacée: Non +// +{ + char str[4]; + + if ( (Paintbrush_X>=0) && (Paintbrush_Y>=0) + && (Paintbrush_X=0) && (Paintbrush_Y>=0) + && (Paintbrush_X=Limit_left+3) + start_x=0; + else + start_x=3-(x_pos-Limit_left); + + if (y_pos>=Limit_top+3) + start_y=0; + else + start_y=3-(y_pos-Limit_top); + + if (x_pos<=Limit_visible_right-3) + end_x=6; + else + end_x=3+(Limit_visible_right-x_pos); + + if (y_pos<=Limit_visible_bottom-3) + end_y=6; + else + end_y=3+(Limit_visible_bottom-y_pos); + + if (start_x<=end_x && start_y<=end_y) + { + for (i=start_x; i<=end_x; i++) + { + temp=x_pos+i-3; + Pixel_preview(temp,y_pos,~Read_pixel(temp -Main_offset_X, + y_pos-Main_offset_Y)); + } + for (i=start_y; i<=end_y; i++) + { + temp=y_pos+i-3; + Pixel_preview(x_pos,temp,~Read_pixel(x_pos-Main_offset_X, + temp -Main_offset_Y)); + } + Update_part_of_screen(x_pos+start_x-3,y_pos+start_y-3,end_x-start_x+1,end_y-start_y+1); + } +} + + +void Curve_34_points_1_0(void) +// +// Opération : OPERATION_COURBE_?_POINTS +// Click Souris: 1 +// Taille_Pile : 0 +// +// Souris effacée: Oui +// +{ + Init_start_operation(); + Backup(); + Shade_table=Shade_table_left; + + Paintbrush_hidden=1; + + Pixel_figure_preview(Paintbrush_X,Paintbrush_Y,Fore_color); + Update_part_of_screen(Paintbrush_X,Paintbrush_Y,1,1); + + if ((Config.Coords_rel) && (Menu_is_visible)) + Print_in_menu("X:± 0 Y:± 0",0); + + Operation_push(Fore_color); + Operation_push(Paintbrush_X); + Operation_push(Paintbrush_Y); + Operation_push(Paintbrush_X); + Operation_push(Paintbrush_Y); +} + +void Curve_34_points_2_0(void) +// +// Opération : OPERATION_COURBE_?_POINTS +// Click Souris: 2 +// Taille_Pile : 0 +// +// Souris effacée: Oui +// +{ + Init_start_operation(); + Backup(); + Shade_table=Shade_table_right; + + Paintbrush_hidden=1; + + Pixel_figure_preview(Paintbrush_X,Paintbrush_Y,Back_color); + Update_part_of_screen(Paintbrush_X,Paintbrush_Y,1,1); + + if ((Config.Coords_rel) && (Menu_is_visible)) + Print_in_menu("X:± 0 Y:± 0",0); + + Operation_push(Back_color); + Operation_push(Paintbrush_X); + Operation_push(Paintbrush_Y); + Operation_push(Paintbrush_X); + Operation_push(Paintbrush_Y); +} + + +void Curve_34_points_1_5(void) +// +// Opération : OPERATION_COURBE_?_POINTS +// Click Souris: 1 +// Taille_Pile : 5 +// +// Souris effacée: Non +// +{ + short x1,x2,y1,y2; + + Operation_pop(&y2); + Operation_pop(&x2); + Operation_pop(&y1); + Operation_pop(&x1); + + if ( (y2!=Paintbrush_Y) || (x2!=Paintbrush_X) ) + { + Hide_cursor(); + Display_coords_rel_or_abs(x1,y1); + + Hide_line_preview(x1,y1,x2,y2); + Pixel_figure_preview (x1,y1,Fore_color); + Draw_line_preview (x1,y1,Paintbrush_X,Paintbrush_Y,Fore_color); + + Display_cursor(); + } + + Operation_push(x1); + Operation_push(y1); + Operation_push(Paintbrush_X); + Operation_push(Paintbrush_Y); +} + +void Curve_34_points_2_5(void) +// +// Opération : OPERATION_COURBE_?_POINTS +// Click Souris: 2 +// Taille_Pile : 5 +// +// Souris effacée: Non +// +{ + short x1,x2,y1,y2; + + Operation_pop(&y2); + Operation_pop(&x2); + Operation_pop(&y1); + Operation_pop(&x1); + + if ( (y2!=Paintbrush_Y) || (x2!=Paintbrush_X) ) + { + Hide_cursor(); + Display_coords_rel_or_abs(x1,y1); + + Hide_line_preview(x1,y1,x2,y2); + Pixel_figure_preview (x1,y1,Back_color); + Draw_line_preview (x1,y1,Paintbrush_X,Paintbrush_Y,Back_color); + + Display_cursor(); + } + + Operation_push(x1); + Operation_push(y1); + Operation_push(Paintbrush_X); + Operation_push(Paintbrush_Y); +} + + +byte Cursor_hidden_before_curve; + +void Curve_4_points_0_5(void) +// +// Opération : OPERATION_4_POINTS_CURVE +// Click Souris: 0 +// Taille_Pile : 5 +// +// Souris effacée: Oui +// +{ + short x1,y1,x2,y2,x3,y3,x4,y4; + short third_x,third_y; + short color; + + Operation_pop(&y4); + Operation_pop(&x4); + Operation_pop(&y1); + Operation_pop(&x1); + Operation_pop(&color); + + third_x=Round_div(abs(x4-x1),3); + third_y=Round_div(abs(y4-y1),3); + + if (x1B=(8/3) * C->P + *x3=Round((bx+x4)/2.0); // · _/·· P3 P2=milieu de [P1,B] + *y3=Round((by+y4)/2.0); // P4*-- P3=milieu de [P4,B] +} + + +void Curve_3_points_0_5(void) +// +// Opération : OPERATION_3_POINTS_CURVE +// Click Souris: 0 +// Taille_Pile : 5 +// +// Souris effacée: Oui +// +{ + short x1,y1,x2,y2,x3,y3,x4,y4; + short color; + + Operation_pop(&y4); + Operation_pop(&x4); + Operation_pop(&y1); + Operation_pop(&x1); + Operation_pop(&color); + + Compute_3_point_curve(x1,y1,x4,y4,&x2,&y2,&x3,&y3); + + Hide_line_preview(x1,y1,x4,y4); + Draw_curve_preview(x1,y1,x2,y2,x3,y3,x4,y4,color); + + if ( (Config.Coords_rel) && (Menu_is_visible) ) + { + Print_in_menu("X: Y: ",0); + Print_coordinates(); + } + + Operation_push(color); + Operation_push(x1); + Operation_push(y1); + Operation_push(x2); + Operation_push(y2); + Operation_push(x3); + Operation_push(y3); + Operation_push(x4); + Operation_push(y4); + Operation_push(Paintbrush_X); + Operation_push(Paintbrush_Y); +} + + +void Curve_3_points_0_11(void) +// +// Opération : OPERATION_3_POINTS_CURVE +// Click Souris: 0 +// Taille_Pile : 11 +// +// Souris effacée: Non +// +{ + short x1,y1,x2,y2,x3,y3,x4,y4; + short old_x,old_y; + short color; + + Operation_pop(&old_y); + Operation_pop(&old_x); + + if ( (Paintbrush_X!=old_x) || (Paintbrush_Y!=old_y) ) + { + Operation_pop(&y4); + Operation_pop(&x4); + Operation_pop(&y3); + Operation_pop(&x3); + Operation_pop(&y2); + Operation_pop(&x2); + Operation_pop(&y1); + Operation_pop(&x1); + Operation_pop(&color); + + Hide_cursor(); + Print_coordinates(); + + Hide_curve_preview(x1,y1,x2,y2,x3,y3,x4,y4,color); + Compute_3_point_curve(x1,y1,x4,y4,&x2,&y2,&x3,&y3); + Draw_curve_preview (x1,y1,x2,y2,x3,y3,x4,y4,color); + Display_cursor(); + + Operation_push(color); + Operation_push(x1); + Operation_push(y1); + Operation_push(x2); + Operation_push(y2); + Operation_push(x3); + Operation_push(y3); + Operation_push(x4); + Operation_push(y4); + } + Operation_push(Paintbrush_X); + Operation_push(Paintbrush_Y); +} + + +void Curve_3_points_12_11(void) +// +// Opération : OPERATION_3_POINTS_CURVE +// Click Souris: 1 ou 2 +// Taille_Pile : 11 +// +// Souris effacée: Oui +// +{ + short x1,y1,x2,y2,x3,y3,x4,y4; + short old_x,old_y; + short color; + + Operation_pop(&old_y); + Operation_pop(&old_x); + Operation_pop(&y4); + Operation_pop(&x4); + Operation_pop(&y3); + Operation_pop(&x3); + Operation_pop(&y2); + Operation_pop(&x2); + Operation_pop(&y1); + Operation_pop(&x1); + Operation_pop(&color); + + Paintbrush_hidden=0; + + Hide_cursor(); + + Hide_curve_preview (x1,y1,x2,y2,x3,y3,x4,y4,color); + Compute_3_point_curve(x1,y1,x4,y4,&x2,&y2,&x3,&y3); + Draw_curve_permanent(x1,y1,x2,y2,x3,y3,x4,y4,color); + + End_of_modification(); + Display_cursor(); + Wait_end_of_click(); +} + + +///////////////////////////////////////////////////////////// OPERATION_AIRBRUSH + +void Airbrush_1_0(void) +// +// Opération : OPERATION_AIRBRUSH +// Click Souris: 1 +// Taille_Pile : 0 +// +// Souris effacée: Non +// +{ + Init_start_operation(); + Backup(); + Shade_table=Shade_table_left; + + Airbrush_next_time = SDL_GetTicks()+Airbrush_delay*10; + Airbrush(LEFT_SIDE); + + Operation_push(Paintbrush_X); + Operation_push(Paintbrush_Y); +} + +void Airbrush_2_0(void) +// +// Opération : OPERATION_AIRBRUSH +// Click Souris: 2 +// Taille_Pile : 0 +// +// Souris effacée: Non +// +{ + Init_start_operation(); + Backup(); + Shade_table=Shade_table_right; + Airbrush_next_time = SDL_GetTicks()+Airbrush_delay*10; + Airbrush(RIGHT_SIDE); + + Operation_push(Paintbrush_X); + Operation_push(Paintbrush_Y); +} + +void Airbrush_12_2(void) +// +// Opération : OPERATION_AIRBRUSH +// Click Souris: 1 ou 2 +// Taille_Pile : 2 +// +// Souris effacée: Non +// +{ + short old_x,old_y; + + Operation_pop(&old_y); + Operation_pop(&old_x); + + if ( (Menu_is_visible) && ((Paintbrush_X!=old_x) || (Paintbrush_Y!=old_y)) ) + { + Hide_cursor(); + Print_coordinates(); + Display_cursor(); + } + + if (SDL_GetTicks()>Airbrush_next_time) + { + Airbrush_next_time+=Airbrush_delay*10; + Airbrush(Mouse_K_unique); + } + + Operation_push(Paintbrush_X); + Operation_push(Paintbrush_Y); +} + +void Airbrush_0_2(void) +// +// Opération : OPERATION_AIRBRUSH +// Click Souris: 0 +// Taille_Pile : 2 +// +// Souris effacée: Non +// +{ + Operation_stack_size-=2; + End_of_modification(); +} + + +////////////////////////////////////////////////////////// OPERATION_POLYGON + + +void Polygon_12_0(void) +// Opération : OPERATION_POLYGON +// Click Souris: 1 ou 2 +// Taille_Pile : 0 +// +// Souris effacée: Oui +{ + byte color; + + Init_start_operation(); + Backup(); + Shade_table=(Mouse_K==LEFT_SIDE)?Shade_table_left:Shade_table_right; + Paintbrush_shape_before_operation=Paintbrush_shape; + Paintbrush_shape=PAINTBRUSH_SHAPE_POINT; + + color=(Mouse_K==LEFT_SIDE)?Fore_color:Back_color; + + // On place temporairement le début de la ligne qui ne s'afficherait pas sinon + Pixel_figure_preview(Paintbrush_X,Paintbrush_Y,color); + Update_part_of_screen(Paintbrush_X,Paintbrush_Y,1,1); + + if ((Config.Coords_rel) && (Menu_is_visible)) + Print_in_menu("X:± 0 Y:± 0",0); + + Operation_push(Paintbrush_X); + Operation_push(Paintbrush_Y); + Operation_push(Mouse_K | 0x80); + Operation_push(color); + Operation_push(Paintbrush_X); + Operation_push(Paintbrush_Y); + Operation_push(Paintbrush_X); + Operation_push(Paintbrush_Y); + // Taille de pile 8 : phase d'appui, non interruptible +} + + + +void Polygon_12_9(void) +// Opération : OPERATION_POLYGON +// Click Souris: 1 ou 2 +// Taille_Pile : 9 +// +// Souris effacée: Oui +{ + short start_x; + short start_y; + short end_x; + short end_y; + short color; + short direction; + + Operation_pop(&end_y); + Operation_pop(&end_x); + Operation_pop(&start_y); + Operation_pop(&start_x); + Operation_pop(&color); + Operation_pop(&direction); + Operation_pop(&direction); + + if (direction==Mouse_K) + { + Operation_push(direction); + Operation_push(color); + Operation_push(start_x); + Operation_push(start_y); + Operation_push(end_x); + Operation_push(end_y); + // Taille de pile 8 : phase d'appui, non interruptible + } + else + { + // La série de ligne est terminée, il faut donc effacer la dernière + // preview de ligne et relier le dernier point avec le premier + Pixel_figure_preview_auto (start_x,start_y); + Hide_line_preview (start_x,start_y,end_x,end_y); + Operation_pop(&end_y); + Operation_pop(&end_x); + Paintbrush_shape=Paintbrush_shape_before_operation; + // Le pied aurait été de ne pas repasser sur le 1er point de la 1ère ligne + // mais c'est pas possible :( + Draw_line_permanent(start_x,start_y,end_x,end_y,color); + Paintbrush_shape=PAINTBRUSH_SHAPE_POINT; + + Display_cursor(); + End_of_modification(); + Wait_end_of_click(); + Hide_cursor(); + + if ( (Config.Coords_rel) && (Menu_is_visible) ) + { + Print_in_menu("X: Y: ",0); + Print_coordinates(); + } + + Paintbrush_shape=Paintbrush_shape_before_operation; + } +} + + +////////////////////////////////////////////////////////// OPERATION_POLYFILL + +short * Polyfill_table_of_points; +int Polyfill_number_of_points; + +void Polyfill_12_0(void) +// Opération : OPERATION_POLYFILL +// Click Souris: 1 ou 2 +// Taille_Pile : 0 +// +// Souris effacée: Oui +{ + byte color; + + Init_start_operation(); + Backup(); + Shade_table=(Mouse_K==LEFT_SIDE)?Shade_table_left:Shade_table_right; + Paintbrush_hidden=1; + + color=(Mouse_K==LEFT_SIDE)?Fore_color:Back_color; + + Polyfill_table_of_points=(short *) malloc((Config.Nb_max_vertices_per_polygon<<1)*sizeof(short)); + Polyfill_table_of_points[0]=Paintbrush_X; + Polyfill_table_of_points[1]=Paintbrush_Y; + Polyfill_number_of_points=1; + + // On place temporairement le début de la ligne qui ne s'afficherait pas sinon + Pixel_figure_preview_xor(Paintbrush_X,Paintbrush_Y,0); + Update_part_of_screen(Paintbrush_X,Paintbrush_Y,1,1); + + if ((Config.Coords_rel) && (Menu_is_visible)) + Print_in_menu("X:± 0 Y:± 0",0); + + Operation_push(Paintbrush_X); + Operation_push(Paintbrush_Y); + Operation_push(Mouse_K | 0x80); + Operation_push(color); + Operation_push(Paintbrush_X); + Operation_push(Paintbrush_Y); + Operation_push(Paintbrush_X); + Operation_push(Paintbrush_Y); + // Taille de pile 8 : phase d'appui, non interruptible +} + + +void Polyfill_0_8(void) +// Opération : OPERATION_POLYFILL +// Click Souris: 0 +// Taille_Pile : 8 +// +// Souris effacée: Oui +{ + short start_x; + short start_y; + short end_x; + short end_y; + short color; + short direction; + + Operation_pop(&end_y); + Operation_pop(&end_x); + Operation_pop(&start_y); + Operation_pop(&start_x); + Operation_pop(&color); + Operation_pop(&direction); + + if ((Config.Coords_rel) && (Menu_is_visible)) + Print_in_menu("X:± 0 Y:± 0",0); + + Draw_line_preview_xor(start_x,start_y,end_x,end_y,0); + + if (direction & 0x80) + direction=(direction & 0x7F); + + Operation_push(direction); // Valeur bidon servant de nouvel état de pile + Operation_push(direction); + Operation_push(color); + + Draw_line_preview_xor(start_x,start_y,Paintbrush_X,Paintbrush_Y,0); + + if (Polyfill_number_of_points1) width--; + if (height>1) height--; + } + + Num2str(width,str,4); + Print_in_menu(str,2); + Num2str(height,str,4); + Print_in_menu(str,11); + } + else + Print_coordinates(); + } + + Display_all_screen(); + + x=Paintbrush_X; + y=Paintbrush_Y; + if (Snap_mode && Config.Adjust_brush_pick) + { + dx=Paintbrush_X-start_x; + dy=Paintbrush_Y-start_y; + if (dx<0) x++; else {if (dx>0) x--;} + if (dy<0) y++; else {if (dy>0) y--;} + Stretch_brush_preview(start_x,start_y,x,y); + } + else + Stretch_brush_preview(start_x,start_y,Paintbrush_X,Paintbrush_Y); + + old_x=Paintbrush_X; + old_y=Paintbrush_Y; + Paintbrush_X=start_x; + Paintbrush_Y=start_y; + Display_cursor(); + Paintbrush_X=old_x; + Paintbrush_Y=old_y; + Display_cursor(); + + Operation_stack_size-=2; + Operation_push(x); + Operation_push(y); + + Operation_push(start_x); + Operation_push(start_y); + } + + Operation_push(Paintbrush_X); + Operation_push(Paintbrush_Y); + Operation_push(2); +} + + + +void Stretch_brush_0_7(void) +// +// Opération : OPERATION_STRETCH_BRUSH +// Click Souris: 0 +// Taille_Pile : 7 +// +// Souris effacée: Non +// +{ + char str[5]; + short start_x; + short start_y; + short old_x; + short old_y; + short width=0; + short height=0; + byte size_change; + short prev_state; + + Operation_pop(&prev_state); + Operation_pop(&old_y); + Operation_pop(&old_x); + Operation_pop(&start_y); + Operation_pop(&start_x); + + if ((Paintbrush_X!=old_x) || (Paintbrush_Y!=old_y) || (prev_state!=3)) + { + if (Menu_is_visible) + { + if (Config.Coords_rel) + { + width=((start_x1)?start_x+(Brush_width>>1)-1:1; + height=(Brush_height>1)?start_y+(Brush_height>>1)-1:1; + break; + case 'X': // Moitié X + width=(Brush_width>1)?start_x+(Brush_width>>1)-1:1; + height=start_y+Brush_height-1; + break; + case 'Y': // Moitié Y + width=start_x+Brush_width-1; + height=(Brush_height>1)?start_y+(Brush_height>>1)-1:1; + break; + case 'n': // Normal + width=start_x+Brush_width-1; + height=start_y+Brush_height-1; + break; + default : + size_change=0; + } + Key_ANSI=0; + } + else + size_change=0; + + if (size_change) + { + // On efface la preview de la brosse (et la croix) + Display_all_screen(); + + old_x=Paintbrush_X; + old_y=Paintbrush_Y; + Paintbrush_X=start_x; + Paintbrush_Y=start_y; + Display_cursor(); + Paintbrush_X=old_x; + Paintbrush_Y=old_y; + + Stretch_brush_preview(start_x,start_y,width,height); + Display_cursor(); + + Operation_stack_size-=2; + Operation_push(width); + Operation_push(height); + } + + Operation_push(start_x); + Operation_push(start_y); + Operation_push(Paintbrush_X); + Operation_push(Paintbrush_Y); + Operation_push(3); +} + + +void Stretch_brush_2_7(void) +// +// Opération : OPERATION_STRETCH_BRUSH +// Click Souris: 2 +// Taille_Pile : 7 +// +// Souris effacée: Oui +// +{ + short computed_x; + short computed_y; + short start_x; + short start_y; + + + Operation_stack_size-=3; + Operation_pop(&start_y); + Operation_pop(&start_x); + Operation_pop(&computed_y); + Operation_pop(&computed_x); + + // On efface la preview de la brosse (et la croix) + Display_all_screen(); + + // Et enfin on stocke pour de bon la nouvelle brosse étirée + Stretch_brush(start_x,start_y,computed_x,computed_y); + + Return_to_draw_mode(); +} + + +//////////////////////////////////////////////////// OPERATION_ROTATE_BRUSH + + +void Rotate_brush_12_0(void) +// +// Opération : OPERATION_ROTATE_BRUSH +// Click Souris: 1 ou 2 +// Taille_Pile : 0 +// +// Souris effacée: Oui +// +{ + Init_start_operation(); + if (Mouse_K==LEFT_SIDE) + { + Brush_rotation_center_X=Paintbrush_X+(Brush_width>>1)-Brush_width; + Brush_rotation_center_Y=Paintbrush_Y; + Brush_rotation_center_is_defined=1; + Operation_push(Paintbrush_X); // Dernière position calculée X + Operation_push(Paintbrush_Y); // Dernière position calculée Y + Operation_push(Paintbrush_X); // Dernière position X + Operation_push(Paintbrush_Y); // Dernière position Y + Operation_push(1); // State précédent + + if ((Config.Coords_rel) && (Menu_is_visible)) + Print_in_menu("Angle: 0° ",0); + } + else + { + Start_operation_stack(Operation_before_interrupt); + Wait_end_of_click(); // FIXME: celui-la il donne un résultat pas très chouette en visuel + } +} + + + +void Rotate_brush_1_5(void) +// +// Opération : OPERATION_ROTATE_BRUSH +// Click Souris: 1 +// Taille_Pile : 5 +// +// Souris effacée: Non +// +{ + char str[4]; + short old_x; + short old_y; + short prev_state; + float angle; + int dx,dy; + + Operation_pop(&prev_state); + Operation_pop(&old_y); + Operation_pop(&old_x); + + if ( (Paintbrush_X!=old_x) || (Paintbrush_Y!=old_y) || (prev_state!=2) ) + { + if ( (Brush_rotation_center_X==Paintbrush_X) + && (Brush_rotation_center_Y==Paintbrush_Y) ) + angle=0.0; + else + { + dx=Paintbrush_X-Brush_rotation_center_X; + dy=Paintbrush_Y-Brush_rotation_center_Y; + angle=acos(((float)dx)/sqrt((dx*dx)+(dy*dy))); + if (dy>0) angle=M_2PI-angle; + } + + if (Menu_is_visible) + { + if (Config.Coords_rel) + { + Num2str((int)(angle*180.0/M_PI),str,3); + Print_in_menu(str,7); + } + else + Print_coordinates(); + } + + Display_all_screen(); + Rotate_brush_preview(angle); + Display_cursor(); + + Operation_stack_size-=2; + Operation_push(Paintbrush_X); + Operation_push(Paintbrush_Y); + } + + Operation_push(Paintbrush_X); + Operation_push(Paintbrush_Y); + Operation_push(2); +} + + + +void Rotate_brush_0_5(void) +// +// Opération : OPERATION_ROTATE_BRUSH +// Click Souris: 0 +// Taille_Pile : 5 +// +// Souris effacée: Non +// +{ + char str[4]; + short old_x; + short old_y; + short computed_x=0; + short computed_y=0; + byte angle_change; + short prev_state; + float angle=0.0; + int dx,dy; + + Operation_pop(&prev_state); + Operation_pop(&old_y); + Operation_pop(&old_x); + + if ((Paintbrush_X!=old_x) || (Paintbrush_Y!=old_y) || (prev_state!=3)) + { + if ( (Brush_rotation_center_X==Paintbrush_X) + && (Brush_rotation_center_Y==Paintbrush_Y) ) + angle=0.0; + else + { + dx=Paintbrush_X-Brush_rotation_center_X; + dy=Paintbrush_Y-Brush_rotation_center_Y; + angle=acos(((float)dx)/sqrt((dx*dx)+(dy*dy))); + if (dy>0) angle=M_2PI-angle; + } + + if (Menu_is_visible) + { + if (Config.Coords_rel) + { + Num2str(Round(angle*180.0/M_PI),str,3); + Print_in_menu(str,7); + } + else + Print_coordinates(); + } + } + + // Utilise Key_ANSI au lieu de Key, car Get_input() met ce dernier + // à zero si une operation est en cours (Operation_stack_size!=0) + if (Key_ANSI) + { + angle_change=1; + computed_x=Brush_rotation_center_X; + computed_y=Brush_rotation_center_Y; + switch (Key_ANSI) + { + case '6': angle= 0.0 ; computed_x++; break; + case '9': angle=M_PI*0.25; computed_x++; computed_y--; break; + case '8': angle=M_PI*0.5 ; computed_y--; break; + case '7': angle=M_PI*0.75; computed_x--; computed_y--; break; + case '4': angle=M_PI ; computed_x--; break; + case '1': angle=M_PI*1.25; computed_x--; computed_y++; break; + case '2': angle=M_PI*1.5 ; computed_y++; break; + case '3': angle=M_PI*1.75; computed_x++; computed_y++; break; + default : + angle_change=0; + } + Key_ANSI=0; + } + else + angle_change=0; + + if (angle_change) + { + // On efface la preview de la brosse + Display_all_screen(); + Rotate_brush_preview(angle); + Display_cursor(); + + Operation_stack_size-=2; + Operation_push(computed_x); + Operation_push(computed_y); + } + + Operation_push(Paintbrush_X); + Operation_push(Paintbrush_Y); + Operation_push(3); +} + + +void Rotate_brush_2_5(void) +// +// Opération : OPERATION_ROTATE_BRUSH +// Click Souris: 2 +// Taille_Pile : 5 +// +// Souris effacée: Oui +// +{ + short computed_x; + short computed_y; + int dx,dy; + float angle; + + + // On efface la preview de la brosse + Display_all_screen(); + + Operation_stack_size-=3; + Operation_pop(&computed_y); + Operation_pop(&computed_x); + + // Calcul de l'angle par rapport à la dernière position calculée + if ( (Brush_rotation_center_X==computed_x) + && (Brush_rotation_center_Y==computed_y) ) + angle=0.0; + else + { + dx=computed_x-Brush_rotation_center_X; + dy=computed_y-Brush_rotation_center_Y; + angle=acos(((float)dx)/sqrt((dx*dx)+(dy*dy))); + if (dy>0) angle=M_2PI-angle; + } + + // Et enfin on stocke pour de bon la nouvelle brosse étirée + Rotate_brush(angle); + + Return_to_draw_mode(); +} + +///////////////////////////////////////////////////// OPERATION_DISTORT_BRUSH + +/// Draws a 2x2 XOR square at the specified picture coordinates, on the screen. +void Draw_stretch_spot(short x_pos, short y_pos) +{ + short x,y; + + for (y=y_pos-1;y=Limit_top && y<=Limit_visible_bottom) + for (x=x_pos-1;x=Limit_left && x<=Limit_visible_right) + Pixel_preview(x,y,~Read_pixel(x-Main_offset_X,y-Main_offset_Y)); + Update_part_of_screen(x_pos-1, y_pos-1, 2, 2); +} + +void Distort_brush_0_0(void) +// +// Opération : OPERATION_DISTORT_BRUSH +// Click Souris: 0 +// Taille_Pile : 0 +// +// Souris effacée: Non +// +{ + if ( Menu_is_visible ) + { + Print_in_menu("POSITION BRUSH TO START ",0); + } +} + +void Distort_brush_1_0(void) +// +// Opération : OPERATION_DISTORT_BRUSH +// Click Souris: 1 +// Taille_Pile : 0 +// +// Souris effacée: Non +// +{ + short x_pos, y_pos; + + Init_start_operation(); + Paintbrush_hidden=1; + Hide_cursor(); + + // Top left angle + x_pos=Paintbrush_X-Brush_offset_X; + y_pos=Paintbrush_Y-Brush_offset_Y; + Draw_stretch_spot(x_pos,y_pos); + Operation_push(x_pos); + Operation_push(y_pos); + + // Top right angle + x_pos+=Brush_width; + Draw_stretch_spot(x_pos,y_pos); + Operation_push(x_pos); + Operation_push(y_pos); + + // Bottom right angle + y_pos+=Brush_height; + Draw_stretch_spot(x_pos,y_pos); + Operation_push(x_pos); + Operation_push(y_pos); + + // Bottom left angle + x_pos-=Brush_width; + Draw_stretch_spot(x_pos,y_pos); + Operation_push(x_pos); + Operation_push(y_pos); + + Distort_brush_preview( + Operation_stack[1], + Operation_stack[2], + Operation_stack[3], + Operation_stack[4], + Operation_stack[5], + Operation_stack[6], + Operation_stack[7], + Operation_stack[8]); + Display_cursor(); + Update_part_of_screen(Paintbrush_X-Brush_offset_X, Paintbrush_Y-Brush_offset_Y, Brush_width, Brush_height); + Wait_end_of_click(); + // Erase the message in status bar + if ( (Config.Coords_rel) && (Menu_is_visible) ) + { + Print_in_menu("X: Y: ",0); + } +} + +void Distort_brush_1_8(void) +// +// Opération : OPERATION_DISTORT_BRUSH +// Click Souris: 1 +// Taille_Pile : 8 +// +// Souris effacée: No +// +{ + // How far (in pixels) you can catch a handle + #define REACH_DISTANCE 100 + short i; + short x[4]; + short y[4]; + long best_distance=REACH_DISTANCE; + short best_spot=-1; + + for (i=3;i>=0;i--) + { + long distance; + Operation_pop(&y[i]); + Operation_pop(&x[i]); + distance=Distance(Paintbrush_X,Paintbrush_Y,x[i],y[i]); + if (distance-1) + { + Operation_push(best_spot); + } + if ( (Config.Coords_rel) && (Menu_is_visible) ) + { + Print_in_menu("X: Y: ",0); + Print_coordinates(); + } +} + +void Distort_brush_1_9(void) +// +// Opération : OPERATION_DISTORT_BRUSH +// Click Souris: 1 +// Taille_Pile : 9 +// +// Souris effacée: No +// +{ + short i; + short x[4]; + short y[4]; + short selected_corner; + + // Pop all arguments + Operation_pop(&selected_corner); + for (i=3;i>=0;i--) + { + Operation_pop(&y[i]); + Operation_pop(&x[i]); + } + + if (Paintbrush_X!=x[selected_corner] || Paintbrush_Y!=y[selected_corner]) + { + Hide_cursor(); + + // Easiest refresh mode: make no assumptions on how the brush was + // displayed before. + Display_all_screen(); + + x[selected_corner]=Paintbrush_X; + y[selected_corner]=Paintbrush_Y; + + for (i=0;i<4;i++) + Draw_stretch_spot(x[i],y[i]); + + Distort_brush_preview(x[0],y[0],x[1],y[1],x[2],y[2],x[3],y[3]); + + Display_cursor(); + + if ( (Config.Coords_rel) && (Menu_is_visible) ) + { + Print_in_menu("X: Y: ",0); + Print_coordinates(); + } + Update_rect(0,0,Screen_width,Menu_Y); + } + + // Push back all arguments + for (i=0;i<4;i++) + { + Operation_push(x[i]); + Operation_push(y[i]); + } + Operation_push(selected_corner); + +} +void Distort_brush_0_9(void) +// +// Opération : OPERATION_DISTORT_BRUSH +// Click Souris: 0 +// Taille_Pile : 9 +// +// Souris effacée: No +// +{ + short selected_corner; + Operation_pop(&selected_corner); + +} + +void Distort_brush_2_0(void) +// +// Opération : OPERATION_DISTORT_BRUSH +// Click Souris: 2 +// Taille_Pile : 0 +// +// Souris effacée: Oui +// +{ + Paintbrush_hidden=0; + Display_all_screen(); + // Erase the message in status bar + if ( (Config.Coords_rel) && (Menu_is_visible) ) + { + Print_in_menu("X: Y: ",0); + } + Return_to_draw_mode(); +} + +void Distort_brush_2_8(void) +// +// Opération : OPERATION_DISTORT_BRUSH +// Click Souris: 2 +// Taille_Pile : 8 +// +// Souris effacée: Oui +// +{ + short i; + short x[4]; + short y[4]; + + // Pop all arguments + for (i=3;i>=0;i--) + { + Operation_pop(&y[i]); + Operation_pop(&x[i]); + } + Distort_brush(x[0],y[0],x[1],y[1],x[2],y[2],x[3],y[3]); + + Paintbrush_hidden=0; + Display_all_screen(); + + Return_to_draw_mode(); +} + +//////////////////////////////////////////////////////////// OPERATION_SCROLL + + +byte Cursor_hidden_before_scroll; + +void Scroll_12_0(void) +// +// Opération : OPERATION_SCROLL +// Click Souris: 1 ou 2 +// Taille_Pile : 0 +// +// Souris effacée: Oui +// +{ + Init_start_operation(); + Backup(); + Operation_push(Paintbrush_X); + Operation_push(Paintbrush_Y); + Operation_push(Paintbrush_X); + Operation_push(Paintbrush_Y); + Cursor_hidden_before_scroll=Cursor_hidden; + Cursor_hidden=1; + if ((Config.Coords_rel) && (Menu_is_visible)) + Print_in_menu("X:± 0 Y:± 0",0); +} + + +void Scroll_12_4(void) +// +// Opération : OPERATION_SCROLL +// Click Souris: 1 ou 2 +// Taille_Pile : 4 +// +// Souris effacée: Non +// +{ + short center_x; + short center_y; + short x_pos; + short y_pos; + short x_offset; + short y_offset; + //char str[5]; + + Operation_pop(&y_pos); + Operation_pop(&x_pos); + Operation_pop(¢er_y); + Operation_pop(¢er_x); + + if ( (Paintbrush_X!=x_pos) || (Paintbrush_Y!=y_pos) ) + { + // L'utilisateur a bougé, il faut scroller l'image + + if (Paintbrush_X>=center_x) + x_offset=(Paintbrush_X-center_x)%Main_image_width; + else + x_offset=Main_image_width-((center_x-Paintbrush_X)%Main_image_width); + + if (Paintbrush_Y>=center_y) + y_offset=(Paintbrush_Y-center_y)%Main_image_height; + else + y_offset=Main_image_height-((center_y-Paintbrush_Y)%Main_image_height); + + Display_coords_rel_or_abs(center_x,center_y); + + Scroll_picture(x_offset,y_offset); + + Display_all_screen(); + } + + Operation_push(center_x); + Operation_push(center_y); + Operation_push(Paintbrush_X); + Operation_push(Paintbrush_Y); +} + +void Scroll_0_4(void) +// +// Opération : OPERATION_SCROLL +// Click Souris: 0 +// Taille_Pile : 4 +// +// Souris effacée: Oui +// +{ + Operation_stack_size-=4; + Cursor_hidden=Cursor_hidden_before_scroll; + End_of_modification(); + if ((Config.Coords_rel) && (Menu_is_visible)) + { + Print_in_menu("X: Y: ",0); + Print_coordinates(); + } +} + + +//////////////////////////////////////////////////// OPERATION_GRAD_CIRCLE + + +void Grad_circle_12_0(void) +// +// Opération : OPERATION_GRAD_CIRCLE +// Click Souris: 1 ou 2 +// Taille_Pile : 0 +// +// Souris effacée: Oui +{ + byte color; + + Init_start_operation(); + Backup(); + + Shade_table=(Mouse_K==LEFT_SIDE)?Shade_table_left:Shade_table_right; + color=(Mouse_K==LEFT_SIDE)?Fore_color:Back_color; + + Paintbrush_hidden_before_scroll=Paintbrush_hidden; + Paintbrush_hidden=1; + + Pixel_figure_preview(Paintbrush_X,Paintbrush_Y,color); + Update_part_of_screen(Paintbrush_X,Paintbrush_Y,1,1); + + if ((Config.Coords_rel) && (Menu_is_visible)) + Print_in_menu("Radius: 0 ",0); + + Operation_push(Mouse_K); + Operation_push(color); + Operation_push(Paintbrush_X); + Operation_push(Paintbrush_Y); + Operation_push(Paintbrush_X); + Operation_push(Paintbrush_Y); +} + + +void Grad_circle_12_6(void) +// +// Opération : OPERATION_GRAD_CIRCLE +// Click Souris: 1 ou 2 +// Taille_Pile : 6 (Mouse_K, color, X_Centre, Y_Centre, X_Tangente, Y_Tangente) +// +// Souris effacée: Non +// +{ + short tangent_x; + short tangent_y; + short center_x; + short center_y; + short color; + short radius; + char str[5]; + + Operation_pop(&tangent_y); + Operation_pop(&tangent_x); + Operation_pop(¢er_y); + Operation_pop(¢er_x); + Operation_pop(&color); + + if ( (tangent_x!=Paintbrush_X) || (tangent_y!=Paintbrush_Y) ) + { + Hide_cursor(); + if ((Config.Coords_rel) && (Menu_is_visible)) + { + Num2str(Distance(center_x,center_y,Paintbrush_X,Paintbrush_Y),str,4); + Print_in_menu(str,7); + } + else + Print_coordinates(); + + Circle_limit=((tangent_x-center_x)*(tangent_x-center_x))+ + ((tangent_y-center_y)*(tangent_y-center_y)); + radius=sqrt(Circle_limit); + Hide_empty_circle_preview(center_x,center_y,radius); + + Circle_limit=((Paintbrush_X-center_x)*(Paintbrush_X-center_x))+ + ((Paintbrush_Y-center_y)*(Paintbrush_Y-center_y)); + radius=sqrt(Circle_limit); + Draw_empty_circle_preview(center_x,center_y,radius,color); + + Display_cursor(); + } + + Operation_push(color); + Operation_push(center_x); + Operation_push(center_y); + Operation_push(Paintbrush_X); + Operation_push(Paintbrush_Y); +} + + +void Grad_circle_0_6(void) +// +// Opération : OPERATION_GRAD_CIRCLE +// Click Souris: 0 +// Taille_Pile : 6 (Mouse_K, color, X_Centre, Y_Centre, X_Tangente, Y_Tangente) +// +// Souris effacée: Oui +// +{ + short tangent_x; + short tangent_y; + short center_x; + short center_y; + short color; + short click; + short radius; + + Operation_pop(&tangent_y); + Operation_pop(&tangent_x); + Operation_pop(¢er_y); + Operation_pop(¢er_x); + + Operation_pop(&color); + Operation_pop(&click); + + if (click==LEFT_SIDE) + { + Operation_push(click); + Operation_push(color); + + Operation_push(center_x); + Operation_push(center_y); + Operation_push(tangent_x); + Operation_push(tangent_y); + + Operation_push(Paintbrush_X); + Operation_push(Paintbrush_Y); + + // On change la forme du curseur + Cursor_shape=CURSOR_SHAPE_XOR_TARGET; + + // On affiche une croix XOR au centre du cercle + Draw_curve_cross(center_x,center_y); + + if (Menu_is_visible) + { + if (Config.Coords_rel) + Print_in_menu("X: Y:",0); + else + Print_in_menu("X: Y: ",0); + Display_coords_rel_or_abs(center_x,center_y); + } + } + else + { + Circle_limit=((tangent_x-center_x)*(tangent_x-center_x))+ + ((tangent_y-center_y)*(tangent_y-center_y)); + radius=sqrt(Circle_limit); + Hide_empty_circle_preview(center_x,center_y,radius); + + Paintbrush_hidden=Paintbrush_hidden_before_scroll; + Cursor_shape=CURSOR_SHAPE_TARGET; + + Draw_filled_circle(center_x,center_y,radius,Back_color); + + End_of_modification(); + if ((Config.Coords_rel) && (Menu_is_visible)) + { + Print_in_menu("X: Y: ",0); + Print_coordinates(); + } + } +} + + +void Grad_circle_12_8(void) +// +// Opération : OPERATION_GRAD_CIRCLE +// Click Souris: 0 +// Taille_Pile : 8 (Mouse_K, color, X_Centre, Y_Centre, X_Tangente, Y_Tangente, old_x, old_y) +// +// Souris effacée: Oui +// +{ + short tangent_x; + short tangent_y; + short center_x; + short center_y; + short color; + short old_mouse_k; + + short radius; + + Operation_stack_size-=2; // On fait sauter les 2 derniers élts de la pile + Operation_pop(&tangent_y); + Operation_pop(&tangent_x); + Operation_pop(¢er_y); + Operation_pop(¢er_x); + Operation_pop(&color); + Operation_pop(&old_mouse_k); + + Hide_cursor(); + // On efface la croix XOR au centre du cercle + Draw_curve_cross(center_x,center_y); + + Circle_limit=((tangent_x-center_x)*(tangent_x-center_x))+ + ((tangent_y-center_y)*(tangent_y-center_y)); + radius=sqrt(Circle_limit); + Hide_empty_circle_preview(center_x,center_y,radius); + + Paintbrush_hidden=Paintbrush_hidden_before_scroll; + Cursor_shape=CURSOR_SHAPE_TARGET; + + if (Mouse_K==old_mouse_k) + Draw_grad_circle(center_x,center_y,radius,Paintbrush_X,Paintbrush_Y); + + Display_cursor(); + End_of_modification(); + Wait_end_of_click(); + + if ((Config.Coords_rel) && (Menu_is_visible)) + { + Print_in_menu("X: Y: ",0); + Print_coordinates(); + } +} + + +void Grad_circle_or_ellipse_0_8(void) +// +// Opération : OPERATION_{CERCLE|ELLIPSE}_DEGRADE +// Click Souris: 0 +// Taille_Pile : 8 +// +// Souris effacée: Non +// +{ + short start_x; + short start_y; + short tangent_x; + short tangent_y; + short old_x; + short old_y; + + Operation_pop(&old_y); + Operation_pop(&old_x); + + if ((Paintbrush_X!=old_x) || (Paintbrush_Y!=old_y)) + { + Operation_pop(&tangent_y); + Operation_pop(&tangent_x); + Operation_pop(&start_y); + Operation_pop(&start_x); + Display_coords_rel_or_abs(start_x,start_y); + Operation_push(start_x); + Operation_push(start_y); + Operation_push(tangent_x); + Operation_push(tangent_y); + } + + Operation_push(Paintbrush_X); + Operation_push(Paintbrush_Y); +} + + +////////////////////////////////////////////////// OPERATION_GRAD_ELLIPSE + + +void Grad_ellipse_12_0(void) +// +// Opération : OPERATION_GRAD_ELLIPSE +// Click Souris: 1 ou 2 +// Taille_Pile : 0 +// +// Souris effacée: Oui +{ + byte color; + + Init_start_operation(); + Backup(); + + Shade_table=(Mouse_K==LEFT_SIDE)?Shade_table_left:Shade_table_right; + color=(Mouse_K==LEFT_SIDE)?Fore_color:Back_color; + + Paintbrush_hidden_before_scroll=Paintbrush_hidden; + Paintbrush_hidden=1; + + Pixel_figure_preview(Paintbrush_X,Paintbrush_Y,color); + Update_part_of_screen(Paintbrush_X,Paintbrush_Y,1,1); + + if ((Config.Coords_rel) && (Menu_is_visible)) + Print_in_menu("X:± 0 Y:± 0",0); + + Operation_push(Mouse_K); + Operation_push(color); + Operation_push(Paintbrush_X); + Operation_push(Paintbrush_Y); + Operation_push(Paintbrush_X); + Operation_push(Paintbrush_Y); +} + + +void Grad_ellipse_12_6(void) +// +// Opération : OPERATION_GRAD_ELLIPSE +// Click Souris: 1 ou 2 +// Taille_Pile : 6 (Mouse_K, color, X_Centre, Y_Centre, X_Tangente, Y_Tangente) +// +// Souris effacée: Non +// +{ + short tangent_x; + short tangent_y; + short center_x; + short center_y; + short color; + short horizontal_radius; + short vertical_radius; + + Operation_pop(&tangent_y); + Operation_pop(&tangent_x); + Operation_pop(¢er_y); + Operation_pop(¢er_x); + Operation_pop(&color); + + if ( (tangent_x!=Paintbrush_X) || (tangent_y!=Paintbrush_Y) ) + { + Hide_cursor(); + Display_coords_rel_or_abs(center_x,center_y); + + horizontal_radius=(tangent_x>center_x)?tangent_x-center_x + :center_x-tangent_x; + vertical_radius =(tangent_y>center_y)?tangent_y-center_y + :center_y-tangent_y; + Hide_empty_ellipse_preview(center_x,center_y,horizontal_radius,vertical_radius); + + horizontal_radius=(Paintbrush_X>center_x)?Paintbrush_X-center_x + :center_x-Paintbrush_X; + vertical_radius =(Paintbrush_Y>center_y)?Paintbrush_Y-center_y + :center_y-Paintbrush_Y; + Draw_empty_ellipse_preview(center_x,center_y,horizontal_radius,vertical_radius,color); + + Display_cursor(); + } + + Operation_push(color); + Operation_push(center_x); + Operation_push(center_y); + Operation_push(Paintbrush_X); + Operation_push(Paintbrush_Y); +} + + +void Grad_ellipse_0_6(void) +// +// Opération : OPERATION_GRAD_ELLIPSE +// Click Souris: 0 +// Taille_Pile : 6 (Mouse_K, color, X_Centre, Y_Centre, X_Tangente, Y_Tangente) +// +// Souris effacée: Oui +// +{ + short tangent_x; + short tangent_y; + short center_x; + short center_y; + short color; + short click; + //short radius; + short horizontal_radius; + short vertical_radius; + + Operation_pop(&tangent_y); + Operation_pop(&tangent_x); + Operation_pop(¢er_y); + Operation_pop(¢er_x); + + Operation_pop(&color); + Operation_pop(&click); + + if (click==LEFT_SIDE) + { + Operation_push(click); + Operation_push(color); + + Operation_push(center_x); + Operation_push(center_y); + Operation_push(tangent_x); + Operation_push(tangent_y); + + Operation_push(Paintbrush_X); + Operation_push(Paintbrush_Y); + + // On change la forme du curseur + Cursor_shape=CURSOR_SHAPE_XOR_TARGET; + + // On affiche une croix XOR au centre du cercle + Draw_curve_cross(center_x,center_y); + + if (Menu_is_visible) + { + if (Config.Coords_rel) + Print_in_menu("X: Y:",0); + else + Print_in_menu("X: Y: ",0); + Display_coords_rel_or_abs(center_x,center_y); + } + } + else + { + horizontal_radius=(tangent_x>center_x)?tangent_x-center_x + :center_x-tangent_x; + vertical_radius =(tangent_y>center_y)?tangent_y-center_y + :center_y-tangent_y; + Hide_empty_ellipse_preview(center_x,center_y,horizontal_radius,vertical_radius); + + Paintbrush_hidden=Paintbrush_hidden_before_scroll; + Cursor_shape=CURSOR_SHAPE_TARGET; + + Draw_filled_ellipse(center_x,center_y,horizontal_radius,vertical_radius,Back_color); + + End_of_modification(); + if ((Config.Coords_rel) && (Menu_is_visible)) + { + Print_in_menu("X: Y: ",0); + Print_coordinates(); + } + } +} + + +void Grad_ellipse_12_8(void) +// +// Opération : OPERATION_GRAD_ELLIPSE +// Click Souris: 0 +// Taille_Pile : 8 (Mouse_K, color, X_Centre, Y_Centre, X_Tangente, Y_Tangente, old_x, old_y) +// +// Souris effacée: Oui +// +{ + short tangent_x; + short tangent_y; + short center_x; + short center_y; + short color; + short horizontal_radius; + short vertical_radius; + short old_mouse_k; + + Operation_stack_size-=2; // On fait sauter les 2 derniers élts de la pile + Operation_pop(&tangent_y); + Operation_pop(&tangent_x); + Operation_pop(¢er_y); + Operation_pop(¢er_x); + Operation_pop(&color); + Operation_pop(&old_mouse_k); + + Hide_cursor(); + // On efface la croix XOR au centre de l'ellipse + Draw_curve_cross(center_x,center_y); + + horizontal_radius=(tangent_x>center_x)?tangent_x-center_x + :center_x-tangent_x; + vertical_radius =(tangent_y>center_y)?tangent_y-center_y + :center_y-tangent_y; + Hide_empty_ellipse_preview(center_x,center_y,horizontal_radius,vertical_radius); + + Paintbrush_hidden=Paintbrush_hidden_before_scroll; + Cursor_shape=CURSOR_SHAPE_TARGET; + + if (Mouse_K==old_mouse_k) + Draw_grad_ellipse(center_x,center_y,horizontal_radius,vertical_radius,Paintbrush_X,Paintbrush_Y); + + Display_cursor(); + End_of_modification(); + Wait_end_of_click(); + + if ((Config.Coords_rel) && (Menu_is_visible)) + { + Print_in_menu("X: Y: ",0); + Print_coordinates(); + } +} + +/****************************** +* Operation_Rectangle_Degrade * +******************************/ + +// 1) tracé d'un rectangle classique avec les lignes XOR +// 2) tracé d'une ligne vecteur de dégradé, comme une ligne normale +// 3) dessin du dégradé + + +void Grad_rectangle_12_0(void) +// Opération : OPERATION_GRAD_RECTANGLE +// Click Souris: 1 ou 2 +// Taille_Pile : 0 +// +// Souris effacée: Oui + +// Initialisation de l'étape 1, on commence à dessiner le rectangle +{ + Init_start_operation(); + Backup(); + + if ((Config.Coords_rel) && (Menu_is_visible)) + Print_in_menu("\035: 1 \022: 1",0); + // On laisse une trace du curseur à l'écran + Display_cursor(); + + if (Mouse_K==LEFT_SIDE) + { + Shade_table=Shade_table_left; + Operation_push(Mouse_K); + } + else + { + Shade_table=Shade_table_right; + Operation_push(Mouse_K); + } + + Operation_push(Paintbrush_X); + Operation_push(Paintbrush_Y); + Operation_push(Paintbrush_X); + Operation_push(Paintbrush_Y); +} + + +void Grad_rectangle_12_5(void) +// Opération : OPERATION_GRAD_RECTANGLE +// Click Souris: 1 ou 2 +// Taille_Pile : 5 +// +// Souris effacée: Non + +// Modification de la taille du rectangle +{ + short start_x; + short start_y; + short old_x; + short old_y; + char str[5]; + + Operation_pop(&old_y); + Operation_pop(&old_x); + + if ((Paintbrush_X!=old_x) || (Paintbrush_Y!=old_y)) + { + Operation_pop(&start_y); + Operation_pop(&start_x); + + if ((Config.Coords_rel) && (Menu_is_visible)) + { + Num2str(((start_x Main_image_width || Min(ray, rby) > Main_image_height) + { + Operation_pop(&rby); // reset the stack + return; // cancel the operation + } + + // Handle clipping + if (Max(rax, rbx)-Main_offset_X > Min(Main_image_width, + Main_magnifier_mode?Main_separator_position:Screen_width)) + { + offset_width = Max(rax, rbx) - Min(Main_image_width, + Main_magnifier_mode?Main_separator_position:Screen_width); + } + + if (Max(ray, rby)-Main_offset_Y > Min(Main_image_height, Menu_Y)) + offset_height = Max(ray, rby) - Min(Main_image_height, Menu_Y); + + // Dessin dans la zone de dessin normale + Horizontal_XOR_line(Min(rax, rbx)-Main_offset_X, + Min(ray, rby) - Main_offset_Y, width - offset_width); + + // If not, this line is out of the picture so there is no need to draw it + if (offset_height == 0) + { + Horizontal_XOR_line(Min(rax, rbx) - Main_offset_X, Max(ray, rby) - 1 + - Main_offset_Y, width - offset_width); + } + + Vertical_XOR_line(Min(rax, rbx)-Main_offset_X, Min(ray, rby) + - Main_offset_Y, height - offset_height); + + if (offset_width == 0) + { + Vertical_XOR_line(Max(rax, rbx) - 1 - Main_offset_X, Min(ray, rby) + - Main_offset_Y, height - offset_height); + } + + Update_rect(Min(rax, rbx) - Main_offset_X, Min(ray, rby) - Main_offset_Y, + width + 1 - offset_width, height + 1 - offset_height); + + // Dessin dans la zone zoomée + if (Main_magnifier_mode && Min(rax, rbx) <= Limit_right_zoom + && Max(rax, rbx) > Limit_left_zoom + && Min(ray, rby) <= Limit_bottom_zoom + && Max(ray, rby) > Limit_top_zoom ) + { + offset_width = 0; + offset_height = 0; + + if (Min(rax, rbx)<=Limit_left_zoom) // On dépasse du zoom à gauche + { + offset_width += Limit_left_zoom - Min(rax, rbx); + offset_left = Limit_left_zoom; + } + + if(Max(rax,rbx)>Limit_right_zoom) // On dépasse du zoom à droite + offset_width += Max(rax,rbx) - Limit_right_zoom - 1; + + if(Min(ray,rby)Limit_bottom_zoom) // On dépasse du zoom en bas + offset_height += Max(ray,rby) - Limit_bottom_zoom - 1; + + if(width > offset_width) + { + if(offset_top==0) // La ligne du haut est visible + Horizontal_XOR_line_zoom(offset_left>0?offset_left:Min(rax,rbx),Min(ray,rby),width-offset_width); + + if(Max(ray,rby)<=Limit_bottom_zoom) // La ligne du bas est visible + Horizontal_XOR_line_zoom(offset_left>0?offset_left:Min(rax,rbx),Max(ray,rby),width-offset_width); + } + + if(height>offset_height) + { + if(offset_left==0) // La ligne de gauche est visible + Vertical_XOR_line_zoom(Min(rax,rbx),offset_top>0?offset_top:Min(ray,rby),height-offset_height); + + if(Max(rax,rbx)<=Limit_right_zoom) // La ligne de droite est visible + Vertical_XOR_line_zoom(Max(rax,rbx),offset_top>0?offset_top:Min(ray,rby),height-offset_height); + } + } + + Operation_push(rax); + Operation_push(ray); + Operation_push(rbx); + Operation_push(rby); + + // On ajoute des trucs dans la pile pour forcer le passage à l'étape suivante + Operation_push(rbx); + Operation_push(rby); +} + +void Grad_rectangle_0_7(void) +// OPERATION_GRAD_RECTANGLE +// click souris 0 +// Taile pile : 5 +// +// Souris effacée : non + +// On continue à attendre que l'utilisateur clique en gardant les coords à jour +{ + Operation_stack_size -= 2; + Print_coordinates(); + Operation_push(Paintbrush_X); + Operation_push(Paintbrush_Y); +} + +void Grad_rectangle_12_7(void) +// Opération : OPERATION_GRAD_RECTANGLE +// Click Souris: 1 ou 2 +// Taille_Pile : 7 +// +// Souris effacée: Oui + +// Début du tracé du vecteur (premier clic) +// On garde les anciennes coordonnées dans la pile, et on ajoute les nouvelles par dessus + +// Si l'utilisateur utilise le mauvais bouton, on annule le tracé. Mais ça nous oblige à vider toute la pile pour vérifier :( +{ + short rax,rbx,ray,rby,vax,vay,click; + + Operation_pop(&vay); + Operation_pop(&vax); + Operation_pop(&ray); + Operation_pop(&rax); + Operation_pop(&rby); + Operation_pop(&rbx); + Operation_pop(&click); + + + if(click==Mouse_K) + { + Operation_push(click); + Operation_push(rbx); + Operation_push(rby); + Operation_push(rax); + Operation_push(ray); + Operation_push(vax); + Operation_push(vay); + Operation_push(Paintbrush_X); + Operation_push(Paintbrush_Y); + + } + else + { + // Mauvais bouton > anulation de l'opération. + // On a déjà vidé la pile, il reste à effacer le rectangle XOR + short width, height; + short offset_width = 0; + short offset_height = 0; + short offset_left = 0; + short offset_top = 0; + + width = abs(rbx-rax); + height = abs(rby-ray); + + if (Max(rax,rbx)-Main_offset_X > Min(Main_image_width,Main_magnifier_mode?Main_separator_position:Screen_width)) // Tous les clippings à gérer sont là + offset_width = Max(rax,rbx) - Min(Main_image_width,Main_magnifier_mode?Main_separator_position:Screen_width); + + if (Max(ray,rby)-Main_offset_Y > Min(Main_image_height,Menu_Y)) + offset_height = Max(ray,rby) - Min(Main_image_height,Menu_Y); + + // Dessin dans la zone de dessin normale + Horizontal_XOR_line(Min(rax,rbx)-Main_offset_X,Min(ray,rby)-Main_offset_Y,width - offset_width); + if(offset_height == 0) + Horizontal_XOR_line(Min(rax,rbx)-Main_offset_X,Max(ray,rby)-1-Main_offset_Y,width - offset_width); + + Vertical_XOR_line(Min(rax,rbx)-Main_offset_X,Min(ray,rby)-Main_offset_Y,height-offset_height); + if (offset_width == 0) // Sinon cette ligne est en dehors de la zone image, inutile de la dessiner + Vertical_XOR_line(Max(rax,rbx)-1-Main_offset_X,Min(ray,rby)-Main_offset_Y,height-offset_height); + + Update_rect(Min(rax,rbx)-Main_offset_X,Min(ray,rby)-Main_offset_Y,width+1-offset_width,height+1-offset_height); + + // Dessin dans la zone zoomée + if (Main_magnifier_mode && Min(rax, rbx) <= Limit_right_zoom + && Max(rax, rbx)>Limit_left_zoom && Min(ray, rby) <= Limit_bottom_zoom + && Max(ray,rby)>Limit_top_zoom ) + { + offset_width = 0; + offset_height=0; + + if(Min(rax,rbx)Limit_right_zoom) // On dépasse du zoom à droite + offset_width += Max(rax,rbx) - Limit_right_zoom - 1; + + if(Min(ray,rby)Limit_bottom_zoom) // On dépasse du zoom en bas + offset_height += Max(ray,rby) - Limit_bottom_zoom - 1; + + if(width > offset_width) + { + if(offset_top==0) // La ligne du haut est visible + Horizontal_XOR_line_zoom(offset_left>0?offset_left:Min(rax,rbx),Min(ray,rby),width-offset_width); + + if(Max(ray,rby)0?offset_left:Min(rax,rbx),Max(ray,rby),width-offset_width); + } + + if(height>offset_height) + { + if(offset_left==0) // La ligne de gauche est visible + Vertical_XOR_line_zoom(Min(rax,rbx),offset_top>0?offset_top:Min(ray,rby),height-offset_height); + + if(Max(rax,rbx)<=Limit_right_zoom) // La ligne de droite est visible + Vertical_XOR_line_zoom(Max(rax,rbx),offset_top>0?offset_top:Min(ray,rby),height-offset_height); + } + } + } +} + +void Grad_rectangle_12_9(void) + // Opération : OPERATION_GRAD_RECTANGLE + // Click Souris: 1 + // Taille_Pile : 5 + // + // Souris effacée: Oui + + // Poursuite du tracé du vecteur (déplacement de la souris en gardant le curseur appuyé) +{ + short start_x; + short start_y; + short end_x; + short end_y; + short cursor_x; + short cursor_y; + + Operation_pop(&end_y); + Operation_pop(&end_x); + Operation_pop(&start_y); + Operation_pop(&start_x); + + cursor_x = Paintbrush_X; + cursor_y = Paintbrush_Y; + // On corrige les coordonnées de la ligne si la touche shift est appuyée... + if(SDL_GetModState() & KMOD_SHIFT) + Clamp_coordinates_regular_angle(start_x,start_y,&cursor_x,&cursor_y); + + if ((cursor_x!=end_x) || (cursor_y!=end_y)) + { + Display_coords_rel_or_abs(start_x,start_y); + + Draw_line_preview_xor(start_x,start_y,end_x,end_y,0); + Draw_line_preview_xor(start_x,start_y,cursor_x,cursor_y,0); + + } + + + Operation_push(start_x); + Operation_push(start_y); + Operation_push(cursor_x); + Operation_push(cursor_y); +} + +void Grad_rectangle_0_9(void) + // Opération : OPERATION_GRAD_RECTANGLE + // Click Souris: 0 + // Taille_Pile : 9 + // + // Souris effacée: Oui + + // Ouf, fini ! on dessine enfin le rectangle avec son dégradé +{ + short rect_start_x; + short rect_start_y; + short rect_end_x; + short rect_end_y; + + short vector_start_x; + short vector_start_y; + short vector_end_x; + short vector_end_y; + + Operation_pop(&vector_end_y); + Operation_pop(&vector_end_x); + Operation_pop(&vector_start_y); + Operation_pop(&vector_start_x); + Operation_pop(&rect_end_y); + Operation_pop(&rect_end_x); + Operation_pop(&rect_start_y); + Operation_pop(&rect_start_x); + Operation_stack_size--; + + Hide_cursor(); + // Maintenant on efface tout le bazar temporaire : rectangle et ligne XOR + Hide_line_preview(vector_start_x,vector_start_y,vector_end_x,vector_end_y); + + // Et enfin on trace le rectangle avec le dégradé dedans ! + if (vector_end_x==vector_start_x && vector_end_y==vector_start_y) + { + // Vecteur nul > pas de rectangle tracé + // Du coup on doit effacer la preview xor ... + short width, height; + short offset_width = 0; + short offset_height = 0; + short offset_left = 0; + short offset_top = 0; + + width = abs(rect_end_x-rect_start_x); + height = abs(rect_end_y-rect_start_y); + + if (Max(rect_start_x,rect_end_x)-Main_offset_X > Min(Main_image_width,Main_magnifier_mode?Main_separator_position:Screen_width)) // Tous les clippings à gérer sont là + offset_width = Max(rect_start_x,rect_end_x) - Min(Main_image_width,Main_magnifier_mode?Main_separator_position:Screen_width); + + if (Max(rect_start_y,rect_end_y)-Main_offset_Y > Min(Main_image_height,Menu_Y)) + offset_height = Max(rect_start_y,rect_end_y) - Min(Main_image_height,Menu_Y); + + // Dessin dans la zone de dessin normale + Horizontal_XOR_line(Min(rect_start_x,rect_end_x)-Main_offset_X,Min(rect_start_y,rect_end_y)-Main_offset_Y,width - offset_width); + if(offset_height == 0) + Horizontal_XOR_line(Min(rect_start_x,rect_end_x)-Main_offset_X,Max(rect_start_y,rect_end_y)-1-Main_offset_Y,width - offset_width); + + Vertical_XOR_line(Min(rect_start_x,rect_end_x)-Main_offset_X,Min(rect_start_y,rect_end_y)-Main_offset_Y,height-offset_height); + if (offset_width == 0) // Sinon cette ligne est en dehors de la zone image, inutile de la dessiner + Vertical_XOR_line(Max(rect_start_x,rect_end_x)-1-Main_offset_X,Min(rect_start_y,rect_end_y)-Main_offset_Y,height-offset_height); + + Update_rect(Min(rect_start_x,rect_end_x)-Main_offset_X,Min(rect_start_y,rect_end_y)-Main_offset_Y,width+1-offset_width,height+1-offset_height); + + // Dessin dans la zone zoomée + if (Main_magnifier_mode + && Min(rect_start_x, rect_end_x) <= Limit_right_zoom + && Max(rect_start_x, rect_end_x) > Limit_left_zoom + && Min(rect_start_y, rect_end_y) <= Limit_bottom_zoom + && Max(rect_start_y, rect_end_y) > Limit_top_zoom ) + { + offset_width = 0; + offset_height=0; + + if(Min(rect_start_x,rect_end_x)Limit_right_zoom) // On dépasse du zoom à droite + offset_width += Max(rect_start_x,rect_end_x) - Limit_right_zoom; + + if(Min(rect_start_y,rect_end_y)Limit_bottom_zoom) // On dépasse du zoom en bas + offset_height += Max(rect_start_y,rect_end_y) - Limit_bottom_zoom; + + if(width > offset_width) + { + if(offset_top==0) // La ligne du haut est visible + Horizontal_XOR_line_zoom(offset_left>0?offset_left:Min(rect_start_x,rect_end_x),Min(rect_start_y,rect_end_y),width-offset_width); + + if(Max(rect_start_y,rect_end_y) <= Limit_bottom_zoom) // La ligne du bas est visible + Horizontal_XOR_line_zoom(offset_left>0?offset_left:Min(rect_start_x,rect_end_x),Max(rect_start_y,rect_end_y),width-offset_width); + } + + if(height>offset_height) + { + if(offset_left==0) // La ligne de gauche est visible + Vertical_XOR_line_zoom(Min(rect_start_x,rect_end_x),offset_top>0?offset_top:Min(rect_start_y,rect_end_y),height-offset_height); + + if(Max(rect_start_x,rect_end_x) <= Limit_right_zoom) // La ligne de droite est visible + Vertical_XOR_line_zoom(Max(rect_start_x,rect_end_x),offset_top>0?offset_top:Min(rect_start_y,rect_end_y),height-offset_height); + } + } + } + else + Draw_grad_rectangle(rect_start_x,rect_start_y,rect_end_x,rect_end_y,vector_start_x,vector_start_y,vector_end_x,vector_end_y); + + Display_cursor(); + End_of_modification(); + Wait_end_of_click(); + + if ((Config.Coords_rel) && (Menu_is_visible)) + { + Print_in_menu("X: Y: ",0); + Print_coordinates(); + } +} +/////////////////////////////////////////////////// OPERATION_CENTERED_LINES + + +void Centered_lines_12_0(void) + // Opération : OPERATION_CENTERED_LINES + // Click Souris: 1 ou 2 + // Taille_Pile : 0 + // + // Souris effacée: Oui +{ + Init_start_operation(); + Backup(); + Shade_table=(Mouse_K==LEFT_SIDE)?Shade_table_left:Shade_table_right; + + if ((Config.Coords_rel) && (Menu_is_visible)) + Print_in_menu("X:± 0 Y:± 0",0); + + Operation_push(Mouse_K); + Operation_push(Paintbrush_X); + Operation_push(Paintbrush_Y); +} + + +void Centered_lines_12_3(void) + // Opération : OPERATION_CENTERED_LINES + // Click Souris: 1 ou 2 + // Taille_Pile : 3 + // + // Souris effacée: Non +{ + short start_x; + short start_y; + + Operation_pop(&start_y); + Operation_pop(&start_x); + Operation_push(Paintbrush_X); + Operation_push(Paintbrush_Y); +} + + +void Centered_lines_0_3(void) + // Opération : OPERATION_CENTERED_LINES + // Click Souris: 0 + // Taille_Pile : 3 + // + // Souris effacée: Oui +{ + short start_x; + short start_y; + short Button; + short color; + + Operation_pop(&start_y); + Operation_pop(&start_x); + Operation_pop(&Button); + + color=(Button==LEFT_SIDE)?Fore_color:Back_color; + + Pixel_figure_preview(Paintbrush_X,Paintbrush_Y,color); + Paintbrush_shape_before_operation=Paintbrush_shape; + Paintbrush_shape=PAINTBRUSH_SHAPE_POINT; + + Operation_push(Button); + Operation_push(Paintbrush_X); // Nouveau début X + Operation_push(Paintbrush_Y); // Nouveau début Y + Operation_push(Paintbrush_X); // Nouvelle dernière fin X + Operation_push(Paintbrush_Y); // Nouvelle dernière fin Y + Operation_push(Paintbrush_X); // Nouvelle dernière position X + Operation_push(Paintbrush_Y); // Nouvelle dernière position Y +} + + +void Centered_lines_12_7(void) + // Opération : OPERATION_CENTERED_LINES + // Click Souris: 1 ou 2 + // Taille_Pile : 7 + // + // Souris effacée: Non +{ + short Button; + short start_x; + short start_y; + short end_x; + short end_y; + short last_x; + short last_y; + short color; + + Operation_pop(&last_y); + Operation_pop(&last_x); + Operation_pop(&end_y); + Operation_pop(&end_x); + Operation_pop(&start_y); + Operation_pop(&start_x); + Operation_pop(&Button); + + if (Mouse_K==Button) + { + if ( (end_x!=Paintbrush_X) || (end_y!=Paintbrush_Y) || + (last_x!=Paintbrush_X) || (last_y!=Paintbrush_Y) ) + { + Hide_cursor(); + + color=(Button==LEFT_SIDE)?Fore_color:Back_color; + + Paintbrush_shape=Paintbrush_shape_before_operation; + + Pixel_figure_preview_auto (start_x,start_y); + Hide_line_preview (start_x,start_y,last_x,last_y); + + Smear_start=1; + Display_paintbrush (start_x,start_y,color,0); + Draw_line_permanent(start_x,start_y,Paintbrush_X,Paintbrush_Y,color); + + Paintbrush_shape=PAINTBRUSH_SHAPE_POINT; + Pixel_figure_preview(Paintbrush_X,Paintbrush_Y,color); + Draw_line_preview(start_x,start_y,Paintbrush_X,Paintbrush_Y,color); + + Display_cursor(); + } + + Operation_push(Button); + Operation_push(start_x); + Operation_push(start_y); + Operation_push(Paintbrush_X); + Operation_push(Paintbrush_Y); + Operation_push(Paintbrush_X); + Operation_push(Paintbrush_Y); + } + else + { + Hide_cursor(); + + Paintbrush_shape=Paintbrush_shape_before_operation; + + Pixel_figure_preview_auto (start_x,start_y); + Hide_line_preview (start_x,start_y,last_x,last_y); + + if ( (Config.Coords_rel) && (Menu_is_visible) ) + { + Print_in_menu("X: Y: ",0); + Print_coordinates(); + } + + Display_cursor(); + End_of_modification(); + Wait_end_of_click(); + } +} + + +void Centered_lines_0_7(void) + // Opération : OPERATION_CENTERED_LINES + // Click Souris: 0 + // Taille_Pile : 7 + // + // Souris effacée: Non +{ + short Button; + short start_x; + short start_y; + short end_x; + short end_y; + short last_x; + short last_y; + short color; + + Operation_pop(&last_y); + Operation_pop(&last_x); + Operation_pop(&end_y); + Operation_pop(&end_x); + + if ((Paintbrush_X!=last_x) || (Paintbrush_Y!=last_y)) + { + Hide_cursor(); + Operation_pop(&start_y); + Operation_pop(&start_x); + Operation_pop(&Button); + + color=(Button==LEFT_SIDE)?Fore_color:Back_color; + + Display_coords_rel_or_abs(start_x,start_y); + + Hide_line_preview(start_x,start_y,last_x,last_y); + + Pixel_figure_preview(start_x,start_y,color); + Draw_line_preview(start_x,start_y,Paintbrush_X,Paintbrush_Y,color); + + Operation_push(Button); + Operation_push(start_x); + Operation_push(start_y); + Display_cursor(); + } + + Operation_push(end_x); + Operation_push(end_y); + Operation_push(Paintbrush_X); + Operation_push(Paintbrush_Y); +} + + diff --git a/operatio.h b/operatio.h index 89428cca..41f6f133 100644 --- a/operatio.h +++ b/operatio.h @@ -1,219 +1,219 @@ -/* Grafx2 - The Ultimate 256-color bitmap paint program - - Copyright 2007 Adrien Destugues - Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) - - Grafx2 is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; version 2 - of the License. - - Grafx2 is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Grafx2; if not, see -*/ - -////////////////////////////////////////////////////////////////////////////// -///@file operatio.h -/// Code for the operations, ie all drawing tools. -////////////////////////////////////////////////////////////////////////////// - -/// Do some housekeeping before starting work on a operation. -void Start_operation_stack(word new_operation); -/// Put a value on ::Operation_stack -void Operation_push(short value); -/// Take a value off ::Operation_stack -void Operation_pop(short * value); - -//////////////////////////////////////////////////// OPERATION_CONTINUOUS_DRAW -void Freehand_mode1_1_0(void); -void Freehand_mode1_1_2(void); -void Freehand_mode12_0_2(void); -void Freehand_mode1_2_0(void); -void Freehand_mode1_2_2(void); - -///////////////////////////////////////////////// OPERATION_DISCONTINUOUS_DRAW -void Freehand_mode2_1_0(void); -void Freehand_mode2_1_2(void); -void Freehand_mode2_2_0(void); -void Freehand_mode2_2_2(void); - -////////////////////////////////////////////////////// OPERATION_POINT_DRAW -void Freehand_mode3_1_0(void); -void Freehand_Mode3_2_0(void); -void Freehand_mode3_0_1(void); - -///////////////////////////////////////////////////////////// OPERATION_LINE - -void Line_12_0(void); -void Line_12_5(void); -void Line_0_5(void); - -///////////////////////////////////////////////////////////// OPERATION_MAGNIFY - -void Magnifier_12_0(void); - -/////////////////////////////////////////////////// OPERATION_RECTANGLE_????? - -void Rectangle_12_0(void); -void Rectangle_12_5(void); -void Empty_rectangle_0_5(void); -void Filled_rectangle_0_5(void); - -////////////////////////////////////////////////////// OPERATION_CERCLE_????? - -void Circle_12_0(void); -void Circle_12_5(void); -void Empty_circle_0_5(void); -void Filled_circle_0_5(void); - -///////////////////////////////////////////////////// OPERATION_ELLIPSE_????? - -void Ellipse_12_0(void); -void Ellipse_12_5(void); -void Empty_ellipse_0_5(void); -void Filled_ellipse_0_5(void); - -////////////////////////////////////////////////////// OPERATION_GRAB_BRUSH - -void Brush_12_0(void); -void Brush_12_5(void); -void Brush_0_5(void); - -///////////////////////////////////////////////////// OPERATION_STRETCH_BRUSH - -void Stretch_brush_12_0(void); -void Stretch_brush_1_7(void); -void Stretch_brush_0_7(void); -void Stretch_brush_2_7(void); - -//////////////////////////////////////////////////// OPERATION_ROTATE_BRUSH - -void Rotate_brush_12_0(void); -void Rotate_brush_1_5(void); -void Rotate_brush_0_5(void); -void Rotate_brush_2_5(void); - -///////////////////////////////////////////////////// OPERATION_DISTORT_BRUSH - -void Distort_brush_0_0(void); -void Distort_brush_1_0(void); -void Distort_brush_2_0(void); -void Distort_brush_1_8(void); -void Distort_brush_2_8(void); -void Distort_brush_1_9(void); -void Distort_brush_0_9(void); - -//////////////////////////////////////////////////////// OPERATION_POLYBRUSH - -void Polybrush_12_8(void); - -////////////////////////////////////////////////////////////// OPERATION_FILL - -void Fill_1_0(void); -void Fill_2_0(void); - -///////////////////////////////////////////////////////// OPERATION_REPLACE - -void Replace_1_0(void); -void Replace_2_0(void); - -/////////////////////////////////////////////////////////// OPERATION_COLORPICK - -void Pipette_0_0(void); -void Colorpicker_12_0(void); -void Colorpicker_1_1(void); -void Colorpicker_2_1(void); -void Colorpicker_0_1(void); - -/////////////////////////////////////////////////////////// OPERATION_K_LIGNE - -void K_line_12_0(void); -void K_line_12_6(void); -void K_line_0_6(void); -void K_line_12_7(void); - -/////////////////////////////////////////////////// OPERATION_COURBE_?_POINTS - -void Curve_34_points_1_0(void); -void Curve_34_points_2_0(void); -void Curve_34_points_1_5(void); -void Curve_34_points_2_5(void); - -void Curve_4_points_0_5(void); -void Curve_4_points_1_9(void); -void Curve_4_points_2_9(void); - -void Curve_3_points_0_5(void); -void Curve_3_points_0_11(void); -void Curve_3_points_12_11(void); - -///////////////////////////////////////////////////////////// OPERATION_AIRBRUSH - -void Airbrush_1_0(void); -void Airbrush_2_0(void); -void Airbrush_12_2(void); -void Airbrush_0_2(void); - -//////////////////////////////////////////////////////////// OPERATION_*POLY* - -void Polygon_12_0(void); -void Polygon_12_9(void); - -void Polyfill_12_0(void); -void Polyfill_0_8(void); -void Polyfill_12_8(void); -void Polyfill_12_9(void); - -void Polyform_12_0(void); -void Polyform_12_8(void); -void Polyform_0_8(void); - -void Filled_polyform_12_0(void); -void Filled_polyform_12_8(void); -void Filled_polyform_0_8(void); -void Filled_contour_0_8(void); - -//////////////////////////////////////////////////////////// OPERATION_SCROLL - -void Scroll_12_0(void); -void Scroll_12_4(void); -void Scroll_0_4(void); - -//////////////////////////////////////////////////// OPERATION_GRAD_CIRCLE - -void Grad_circle_12_0(void); -void Grad_circle_12_6(void); -void Grad_circle_0_6(void); -void Grad_circle_12_8(void); -void Grad_circle_or_ellipse_0_8(void); - -////////////////////////////////////////////////// OPERATION_GRAD_ELLIPSE - -void Grad_ellipse_12_0(void); -void Grad_ellipse_12_6(void); -void Grad_ellipse_0_6(void); -void Grad_ellipse_12_8(void); - -///////////////////////////////////////////////// OPERATION_GRAD_RECTANGLE - -void Grad_rectangle_12_0(void); -void Grad_rectangle_12_5(void); -void Grad_rectangle_0_5(void); -void Grad_rectangle_0_7(void); -void Grad_rectangle_12_7(void); -void Grad_rectangle_12_9(void); -void Grad_rectangle_0_9(void); - -/////////////////////////////////////////////////// OPERATION_CENTERED_LINES - -void Centered_lines_12_0(void); -void Centered_lines_12_3(void); -void Centered_lines_0_3(void); -void Centered_lines_12_7(void); -void Centered_lines_0_7(void); - +/* Grafx2 - The Ultimate 256-color bitmap paint program + + Copyright 2007 Adrien Destugues + Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) + + Grafx2 is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 + of the License. + + Grafx2 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grafx2; if not, see +*/ + +////////////////////////////////////////////////////////////////////////////// +///@file operatio.h +/// Code for the operations, ie all drawing tools. +////////////////////////////////////////////////////////////////////////////// + +/// Do some housekeeping before starting work on a operation. +void Start_operation_stack(word new_operation); +/// Put a value on ::Operation_stack +void Operation_push(short value); +/// Take a value off ::Operation_stack +void Operation_pop(short * value); + +//////////////////////////////////////////////////// OPERATION_CONTINUOUS_DRAW +void Freehand_mode1_1_0(void); +void Freehand_mode1_1_2(void); +void Freehand_mode12_0_2(void); +void Freehand_mode1_2_0(void); +void Freehand_mode1_2_2(void); + +///////////////////////////////////////////////// OPERATION_DISCONTINUOUS_DRAW +void Freehand_mode2_1_0(void); +void Freehand_mode2_1_2(void); +void Freehand_mode2_2_0(void); +void Freehand_mode2_2_2(void); + +////////////////////////////////////////////////////// OPERATION_POINT_DRAW +void Freehand_mode3_1_0(void); +void Freehand_Mode3_2_0(void); +void Freehand_mode3_0_1(void); + +///////////////////////////////////////////////////////////// OPERATION_LINE + +void Line_12_0(void); +void Line_12_5(void); +void Line_0_5(void); + +///////////////////////////////////////////////////////////// OPERATION_MAGNIFY + +void Magnifier_12_0(void); + +/////////////////////////////////////////////////// OPERATION_RECTANGLE_????? + +void Rectangle_12_0(void); +void Rectangle_12_5(void); +void Empty_rectangle_0_5(void); +void Filled_rectangle_0_5(void); + +////////////////////////////////////////////////////// OPERATION_CERCLE_????? + +void Circle_12_0(void); +void Circle_12_5(void); +void Empty_circle_0_5(void); +void Filled_circle_0_5(void); + +///////////////////////////////////////////////////// OPERATION_ELLIPSE_????? + +void Ellipse_12_0(void); +void Ellipse_12_5(void); +void Empty_ellipse_0_5(void); +void Filled_ellipse_0_5(void); + +////////////////////////////////////////////////////// OPERATION_GRAB_BRUSH + +void Brush_12_0(void); +void Brush_12_5(void); +void Brush_0_5(void); + +///////////////////////////////////////////////////// OPERATION_STRETCH_BRUSH + +void Stretch_brush_12_0(void); +void Stretch_brush_1_7(void); +void Stretch_brush_0_7(void); +void Stretch_brush_2_7(void); + +//////////////////////////////////////////////////// OPERATION_ROTATE_BRUSH + +void Rotate_brush_12_0(void); +void Rotate_brush_1_5(void); +void Rotate_brush_0_5(void); +void Rotate_brush_2_5(void); + +///////////////////////////////////////////////////// OPERATION_DISTORT_BRUSH + +void Distort_brush_0_0(void); +void Distort_brush_1_0(void); +void Distort_brush_2_0(void); +void Distort_brush_1_8(void); +void Distort_brush_2_8(void); +void Distort_brush_1_9(void); +void Distort_brush_0_9(void); + +//////////////////////////////////////////////////////// OPERATION_POLYBRUSH + +void Polybrush_12_8(void); + +////////////////////////////////////////////////////////////// OPERATION_FILL + +void Fill_1_0(void); +void Fill_2_0(void); + +///////////////////////////////////////////////////////// OPERATION_REPLACE + +void Replace_1_0(void); +void Replace_2_0(void); + +/////////////////////////////////////////////////////////// OPERATION_COLORPICK + +void Pipette_0_0(void); +void Colorpicker_12_0(void); +void Colorpicker_1_1(void); +void Colorpicker_2_1(void); +void Colorpicker_0_1(void); + +/////////////////////////////////////////////////////////// OPERATION_K_LIGNE + +void K_line_12_0(void); +void K_line_12_6(void); +void K_line_0_6(void); +void K_line_12_7(void); + +/////////////////////////////////////////////////// OPERATION_COURBE_?_POINTS + +void Curve_34_points_1_0(void); +void Curve_34_points_2_0(void); +void Curve_34_points_1_5(void); +void Curve_34_points_2_5(void); + +void Curve_4_points_0_5(void); +void Curve_4_points_1_9(void); +void Curve_4_points_2_9(void); + +void Curve_3_points_0_5(void); +void Curve_3_points_0_11(void); +void Curve_3_points_12_11(void); + +///////////////////////////////////////////////////////////// OPERATION_AIRBRUSH + +void Airbrush_1_0(void); +void Airbrush_2_0(void); +void Airbrush_12_2(void); +void Airbrush_0_2(void); + +//////////////////////////////////////////////////////////// OPERATION_*POLY* + +void Polygon_12_0(void); +void Polygon_12_9(void); + +void Polyfill_12_0(void); +void Polyfill_0_8(void); +void Polyfill_12_8(void); +void Polyfill_12_9(void); + +void Polyform_12_0(void); +void Polyform_12_8(void); +void Polyform_0_8(void); + +void Filled_polyform_12_0(void); +void Filled_polyform_12_8(void); +void Filled_polyform_0_8(void); +void Filled_contour_0_8(void); + +//////////////////////////////////////////////////////////// OPERATION_SCROLL + +void Scroll_12_0(void); +void Scroll_12_4(void); +void Scroll_0_4(void); + +//////////////////////////////////////////////////// OPERATION_GRAD_CIRCLE + +void Grad_circle_12_0(void); +void Grad_circle_12_6(void); +void Grad_circle_0_6(void); +void Grad_circle_12_8(void); +void Grad_circle_or_ellipse_0_8(void); + +////////////////////////////////////////////////// OPERATION_GRAD_ELLIPSE + +void Grad_ellipse_12_0(void); +void Grad_ellipse_12_6(void); +void Grad_ellipse_0_6(void); +void Grad_ellipse_12_8(void); + +///////////////////////////////////////////////// OPERATION_GRAD_RECTANGLE + +void Grad_rectangle_12_0(void); +void Grad_rectangle_12_5(void); +void Grad_rectangle_0_5(void); +void Grad_rectangle_0_7(void); +void Grad_rectangle_12_7(void); +void Grad_rectangle_12_9(void); +void Grad_rectangle_0_9(void); + +/////////////////////////////////////////////////// OPERATION_CENTERED_LINES + +void Centered_lines_12_0(void); +void Centered_lines_12_3(void); +void Centered_lines_0_3(void); +void Centered_lines_12_7(void); +void Centered_lines_0_7(void); + diff --git a/pages.c b/pages.c index 6cd0d106..a52c9c22 100644 --- a/pages.c +++ b/pages.c @@ -49,21 +49,6 @@ void Init_page(T_Page * page) page->File_directory[0]='\0'; page->Filename[0]='\0'; page->File_format=DEFAULT_FILEFORMAT; -/* - page->X_offset=0; - page->Y_offset=0; - page->old_offset_x=0; - page->old_offset_y=0; - page->Split=0; - page->X_zoom=0; - page->Separator_proportion=INITIAL_SEPARATOR_PROPORTION; - page->Main_magnifier_mode=0; - page->Main_magnifier_factor=DEFAULT_ZOOM_FACTOR; - page->Main_magnifier_height=0; - page->Main_magnifier_width=0; - page->Main_magnifier_offset_X=0; - page->Main_magnifier_offset_Y=0; -*/ } } @@ -86,35 +71,7 @@ void Download_infos_page_main(T_Page * page) strcpy(Main_file_directory,page->File_directory); strcpy(Main_filename,page->Filename); Main_fileformat=page->File_format; -/* - Main_offset_X=page->X_offset; - Main_offset_Y=page->Y_offset; - // On corrige les décalages en fonction de la dimension de l'écran - if ( (Main_offset_X>0) && - (Main_offset_X+Screen_width>Main_image_width) ) - Main_offset_X=Max(0,Main_image_width-Screen_width); - if ( (Main_offset_Y>0) && - (Main_offset_Y+Menu_Y>Main_image_height) ) - Main_offset_Y=Max(0,Main_image_height-Menu_Y); - - Old_main_offset_X=page->old_offset_x; - Old_main_offset_Y=page->old_offset_y; - Main_separator_position=page->Split; - Main_X_zoom=page->X_zoom; - Main_separator_proportion=page->Separator_proportion; - Main_magnifier_mode=page->Main_magnifier_mode; - Main_magnifier_factor=page->Main_magnifier_factor; - Main_magnifier_height=page->Main_magnifier_height; - Main_magnifier_width=page->Main_magnifier_width; - Main_magnifier_offset_X=page->Main_magnifier_offset_X; - Main_magnifier_offset_Y=page->Main_magnifier_offset_Y; - - // Comme le facteur de zoom a des chances d'avoir changé, on appelle - // "Change_magnifier_factor". - for (factor_index=0; ZOOM_FACTOR[factor_index]!=Main_magnifier_factor; factor_index++); - Change_magnifier_factor(factor_index); -*/ if (size_is_modified) { Main_magnifier_mode=0; @@ -140,21 +97,6 @@ void Upload_infos_page_main(T_Page * page) strcpy(page->File_directory,Main_file_directory); strcpy(page->Filename,Main_filename); page->File_format=Main_fileformat; -/* - page->X_offset=Main_offset_X; - page->Y_offset=Main_offset_Y; - page->old_offset_x=Old_main_offset_X; - page->old_offset_x=Old_main_offset_Y; - page->Split=Main_separator_position; - page->X_zoom=Main_X_zoom; - page->Separator_proportion=Main_separator_proportion; - page->Main_magnifier_mode=Main_magnifier_mode; - page->Main_magnifier_factor=Main_magnifier_factor; - page->Main_magnifier_height=Main_magnifier_height; - page->Main_magnifier_width=Main_magnifier_width; - page->Main_magnifier_offset_X=Main_magnifier_offset_X; - page->Main_magnifier_offset_Y=Main_magnifier_offset_Y; -*/ } } @@ -170,21 +112,6 @@ void Download_infos_page_spare(T_Page * page) strcpy(Spare_file_directory,page->File_directory); strcpy(Spare_filename,page->Filename); Spare_fileformat=page->File_format; -/* - Spare_offset_X=page->X_offset; - Spare_offset_Y=page->Y_offset; - Old_spare_offset_X=page->old_offset_x; - Old_spare_offset_Y=page->old_offset_y; - Spare_separator_position=page->Split; - Spare_X_zoom=page->X_zoom; - Spare_separator_proportion=page->Separator_proportion; - Spare_magnifier_mode=page->Main_magnifier_mode; - Spare_magnifier_factor=page->Main_magnifier_factor; - Spare_magnifier_height=page->Main_magnifier_height; - Spare_magnifier_width=page->Main_magnifier_width; - Spare_magnifier_offset_X=page->Main_magnifier_offset_X; - Spare_magnifier_offset_Y=page->Main_magnifier_offset_Y; -*/ } } @@ -200,21 +127,6 @@ void Upload_infos_page_spare(T_Page * page) strcpy(page->File_directory,Spare_file_directory); strcpy(page->Filename,Spare_filename); page->File_format=Spare_fileformat; -/* - page->X_offset=Spare_offset_X; - page->Y_offset=Spare_offset_Y; - page->old_offset_x=Old_spare_offset_X; - page->old_offset_y=Old_spare_offset_Y; - page->Split=Spare_separator_position; - page->X_zoom=Spare_X_zoom; - page->Separator_proportion=Spare_separator_proportion; - page->Main_magnifier_mode=Spare_magnifier_mode; - page->Main_magnifier_factor=Spare_magnifier_factor; - page->Main_magnifier_height=Spare_magnifier_height; - page->Main_magnifier_width=Spare_magnifier_width; - page->Main_magnifier_offset_X=Spare_magnifier_offset_X; - page->Main_magnifier_offset_Y=Spare_magnifier_offset_Y; -*/ } } @@ -326,14 +238,14 @@ void Backward_in_list_of_pages(T_List_of_pages * list) { // Cette fonction fait l'équivalent d'un "Undo" dans la liste de pages. // Elle effectue une sorte de ROL (Rotation Left) sur la liste: - // ÉÍËÍÑÍÑÍÑÍÑÍÑÍÑÍÑÍÑÍÑÍ» | - // º0º1³2³3³4³5³6³7³8³9³Aº | - // ÈÍÊÍÏÍÏÍÏÍÏÍÏÍÏÍÏÍÏÍÏͼ | 0=page courante - // ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ |_ A=page la plus ancienne - // v v v v v v v v v v v | 1=Dernière page (1er backup) - // ÉÍËÍÑÍÑÍÑÍÑÍÑÍÑÍÑÍÑÍÑÍ» | - // º1º2³3³4³5³6³7³8³9³A³0º | - // ÈÍÊÍÏÍÏÍÏÍÏÍÏÍÏÍÏÍÏÍÏͼ | + // +---+-+-+-+-+-+-+-+-+-+ | + // ¦0¦1¦2¦3¦4¦5¦6¦7¦8¦9¦A¦ | + // +---+-+-+-+-+-+-+-+-+-+ | 0=page courante + // ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ |_ A=page la plus ancienne + // v v v v v v v v v v v | 1=DerniÞre page (1er backup) + // +---+-+-+-+-+-+-+-+-+-+ | + // ¦1¦2¦3¦4¦5¦6¦7¦8¦9¦A¦0¦ | + // +---+-+-+-+-+-+-+-+-+-+ | // Pour simuler un véritable Undo, l'appelant doit mettre la structure // de page courante à jour avant l'appel, puis en réextraire les infos en @@ -369,14 +281,14 @@ void Advance_in_list_of_pages(T_List_of_pages * list) { // Cette fonction fait l'équivalent d'un "Redo" dans la liste de pages. // Elle effectue une sorte de ROR (Rotation Right) sur la liste: - // ÉÍËÍÑÍÑÍÑÍÑÍÑÍÑÍÑÍÑÍÑÍ» | - // º0º1³2³3³4³5³6³7³8³9³Aº | - // ÈÍÊÍÏÍÏÍÏÍÏÍÏÍÏÍÏÍÏÍÏͼ | 0=page courante - // ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ |_ A=page la plus ancienne + // +-+-+-+-+-+-+-+-+-+-+-+ | + // |0|1|2|3|4|5|6|7|8|9|A| | + // +-+-+-+-+-+-+-+-+-+-+-+ | 0=page courante + // | | | | | | | | | | | |_ A=page la plus ancienne // v v v v v v v v v v v | 1=Dernière page (1er backup) - // ÉÍËÍÑÍÑÍÑÍÑÍÑÍÑÍÑÍÑÍÑÍ» | - // ºAº0³1³2³3³4³5³6³7³8³9º | - // ÈÍÊÍÏÍÏÍÏÍÏÍÏÍÏÍÏÍÏÍÏͼ | + // +-+-+-+-+-+-+-+-+-+-+-+ | + // |A|0|1|2|3|4|5|6|7|8|9| | + // +-+-+-+-+-+-+-+-+-+-+-+ | // Pour simuler un véritable Redo, l'appelant doit mettre la structure // de page courante à jour avant l'appel, puis en réextraire les infos en @@ -1018,3 +930,7 @@ void * Borrow_memory_from_page(int size) // Pour que le compilateur ne dise pas qu'il manque une valeur de sortie: return 0; } + +void End_of_modification(void) +{ +} diff --git a/pages.h b/pages.h index efc816e5..8a6c8ca4 100644 --- a/pages.h +++ b/pages.h @@ -1,93 +1,96 @@ -/* Grafx2 - The Ultimate 256-color bitmap paint program - - Copyright 2007 Adrien Destugues - Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) - - Grafx2 is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; version 2 - of the License. - - Grafx2 is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Grafx2; if not, see -*/ - -////////////////////////////////////////////////////////////////////////////// -///@file pages.h -/// Handler for the Undo/Redo system. -////////////////////////////////////////////////////////////////////////////// - -#ifndef _PAGES_H_ -#define _PAGES_H_ - - -////////////////////////////////////////////////////////////////////////// -/////////////////////////// GESTION DU BACKUP //////////////////////////// -////////////////////////////////////////////////////////////////////////// - - - /// - /// GESTION DES PAGES - /// - -void Init_page(T_Page * page); -void Download_infos_page_main(T_Page * page); -void Upload_infos_page_main(T_Page * page); -void Download_infos_page_spare(T_Page * page); -void Upload_infos_page_spare(T_Page * page); -void Download_infos_backup(T_List_of_pages * list); -void Free_a_page(T_Page * page); -void Copy_S_page(T_Page * dest,T_Page * source); -int Size_of_a_page(T_Page * page); - - - - /// - /// GESTION DES LISTES DE PAGES - /// - -void Init_list_of_pages(T_List_of_pages * list); -int Allocate_list_of_pages(T_List_of_pages * list,int size); -void Free_a_list_of_pages(T_List_of_pages * list); -int Size_of_a_list_of_pages(T_List_of_pages * list); -void Backward_in_list_of_pages(T_List_of_pages * list); -void Advance_in_list_of_pages(T_List_of_pages * list); -int New_page_is_possible(T_Page * new_page,T_List_of_pages * current_list,T_List_of_pages * secondary_list); -void Free_last_page_of_list(T_List_of_pages * list); -void Create_new_page(T_Page * new_page,T_List_of_pages * current_list,T_List_of_pages * secondary_list); -void Change_page_number_of_list(T_List_of_pages * list,int number); -void Free_page_of_a_list(T_List_of_pages * list); - - - - /// - /// GESTION DES BACKUPS - /// - -int Init_all_backup_lists(int size,int width,int height); -void Set_number_of_backups(int nb_backups); -int Backup_with_new_dimensions(int upload,int width,int height); -int Backup_and_resize_the_spare(int width,int height); -void Backup(void); -void Undo(void); -void Redo(void); -void Free_current_page(void); -void Exchange_main_and_spare(void); - - - - /// - /// GESTION DES EMPRUNTS DE MEMOIRE DE PAGE - /// - -int Can_borrow_memory_from_page(int size); -void * Borrow_memory_from_page(int size); - - - -#endif +/* Grafx2 - The Ultimate 256-color bitmap paint program + + Copyright 2007 Adrien Destugues + Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) + + Grafx2 is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 + of the License. + + Grafx2 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grafx2; if not, see +*/ + +////////////////////////////////////////////////////////////////////////////// +///@file pages.h +/// Handler for the Undo/Redo system. +////////////////////////////////////////////////////////////////////////////// + +#ifndef _PAGES_H_ +#define _PAGES_H_ + + +////////////////////////////////////////////////////////////////////////// +/////////////////////////// BACKUP /////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// + + +/// +/// INDIVIDUAL PAGES +/// + +void Download_infos_page_main(T_Page * page); +void Upload_infos_page_main(T_Page * page); + +// private +void Init_page(T_Page * page); +void Download_infos_page_spare(T_Page * page); +void Upload_infos_page_spare(T_Page * page); +void Download_infos_backup(T_List_of_pages * list); +void Free_a_page(T_Page * page); +void Copy_S_page(T_Page * dest,T_Page * source); +int Size_of_a_page(T_Page * page); + + + +/// +/// LISTS OF PAGES +/// + +void Init_list_of_pages(T_List_of_pages * list); +// private +int Allocate_list_of_pages(T_List_of_pages * list,int size); +void Free_a_list_of_pages(T_List_of_pages * list); +int Size_of_a_list_of_pages(T_List_of_pages * list); +void Backward_in_list_of_pages(T_List_of_pages * list); +void Advance_in_list_of_pages(T_List_of_pages * list); +int New_page_is_possible(T_Page * new_page,T_List_of_pages * current_list,T_List_of_pages * secondary_list); +void Free_last_page_of_list(T_List_of_pages * list); +void Create_new_page(T_Page * new_page,T_List_of_pages * current_list,T_List_of_pages * secondary_list); +void Change_page_number_of_list(T_List_of_pages * list,int number); +void Free_page_of_a_list(T_List_of_pages * list); + + + +/// +/// BACKUP HIGH-LEVEL FUNCTIONS +/// + +int Init_all_backup_lists(int size,int width,int height); +void Set_number_of_backups(int nb_backups); +int Backup_with_new_dimensions(int upload,int width,int height); +int Backup_and_resize_the_spare(int width,int height); +void Backup(void); +void Undo(void); +void Redo(void); +void Free_current_page(void); // 'Kill' button +void Exchange_main_and_spare(void); +void End_of_modification(void); + + +/// +/// BORROWING MEMORY FROM PAGE +/// + +void * Borrow_memory_from_page(int size); +// private +int Can_borrow_memory_from_page(int size); + + +#endif diff --git a/palette.c b/palette.c index 85591592..8a1abb81 100644 --- a/palette.c +++ b/palette.c @@ -1,2302 +1,2322 @@ -/* Grafx2 - The Ultimate 256-color bitmap paint program - - Copyright 2007 Adrien Destugues - Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) - - Grafx2 is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; version 2 - of the License. - - Grafx2 is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Grafx2; if not, see -*/ -#include -#include -#include -#include "const.h" -#include "struct.h" -#include "global.h" -#include "misc.h" -#include "engine.h" -#include "readline.h" -#include "buttons.h" -#include "pages.h" -#include "help.h" -#include "sdlscreen.h" -#include "errors.h" -#include "op_c.h" -#include "windows.h" -#include "input.h" -#include "palette.h" -#include "shade.h" - -byte Palette_view_is_RGB = 1; // Indique si on est en HSL ou en RGB - -// --------------------------- Menu des palettes ----------------------------- -char * Palette_reduce_label[7]= -{ - "128"," 64"," 32"," 16"," 8"," 4"," 2" -}; - -// Nombre de graduations pour une composante RGB -int RGB_scale = 256; // 24bit -//int RGB_scale = 64; // VGA -//int RGB_scale = 16; // Amiga -//int RGB_scale = 4; // MSX2 -//int RGB_scale = 3; // Amstrad CPC - -// Nombre de graduations pour une composante dans le mode actuel -int Color_count=256; -// Les composantes vont de 0 à (Color_count-1) -int Color_max=255; -// Le demi-pas est une quantité que l'on ajoute à une composante -// avant de faire un arrondi par division. -int Color_halfstep=0; - - -void Set_palette_RGB_scale(int scale) -{ - if (scale>= 2 && scale <= 256) - RGB_scale = scale; -} - -byte Round_palette_component(byte comp) -{ - return ((comp+128/RGB_scale)*(RGB_scale-1)/255*255+(RGB_scale&1?1:0))/(RGB_scale-1); -} - -// Définir les unités pour les graduations R G B ou H S V -void Componant_unit(int count) -{ - Color_count = count; - Color_max = count-1; - Color_halfstep = 256/count/2; -} - -void Set_HSL(T_Palette start_palette, T_Palette end_palette, byte color, short diff_h, short diff_s, short diff_l) -{ - byte h, s, l; - RGB_to_HSL(start_palette[color].R,start_palette[color].G,start_palette[color].B,&h,&s,&l); - // La teinte (Hue) est cyclique - h=(diff_h+256+h); - // Pour les autres (Saturation, Lightness), au lieu d'additionner, - // on va faire un ratio, cela utilise mieux la plage de valeurs 0-255 - if (diff_s<0) - s=(255+diff_s)*s/255; - else if (diff_s>0) - s=255-(255-diff_s)*(255-s)/255; - if (diff_l<0) - l=(255+diff_l)*l/255; - else if (diff_l>0) - l=255-(255-diff_l)*(255-l)/255; - HSL_to_RGB(h,s,l,&end_palette[color].R,&end_palette[color].G,&end_palette[color].B); -} - -void Set_red(byte color, short new_color, T_Palette palette) -{ - if (new_color< 0) - new_color= 0; - if (new_color>255) - new_color=255; - // Arrondi - new_color=Round_palette_component(new_color); - - palette[color].R=new_color; - Set_color(color,palette[color].R,palette[color].G,palette[color].B); -} - - -void Set_green(byte color, short new_color, T_Palette palette) -{ - if (new_color< 0) - new_color= 0; - if (new_color>255) - new_color=255; - // Arrondi - new_color=Round_palette_component(new_color); - - palette[color].G=new_color; - Set_color(color,palette[color].R,palette[color].G,palette[color].B); -} - - -void Set_blue(byte color, short new_color, T_Palette palette) -{ - if (new_color< 0) - new_color= 0; - if (new_color>255) - new_color=255; - // Arrondi - new_color=Round_palette_component(new_color); - - palette[color].B=new_color; - Set_color(color,palette[color].R,palette[color].G,palette[color].B); -} - -void Format_componant(byte value, char *str) -// Formate une chaine de 4 caractères+\0 : "nnn " -{ - Num2str(value,str,3); - str[3]=' '; - str[4]='\0'; -} - -void Spread_colors(short start,short end,T_Palette palette) -// Modifie la palette pour obtenir un dégradé de couleur entre les deux bornes -// passées en paramètre -{ - short start_red; - short start_green; - short start_blue; - short end_red; - short end_green; - short end_blue; - short index; - - // On vérifie qu'il y ait assez de couleurs entre le début et la fin pour - // pouvoir faire un dégradé: - if ( (start!=end) && (start+1!=end) ) - { - start_red=palette[start].R; - start_green =palette[start].G; - start_blue =palette[start].B; - - end_red =palette[end ].R; - end_green =palette[end ].G; - end_blue =palette[end ].B; - - for (index=start+1;index=Window_pos_Y) && (y_pos=Window_pos_X) && (x_pos=Menu_Y_before_window) - end_y=Menu_Y_before_window; - else - end_y=Main_image_height; - - if (!Main_magnifier_mode) - { - if (Main_image_width>=Screen_width) - end_x=Screen_width; - else - end_x=Main_image_width; - - } - else - { - if (Main_image_width>=Main_separator_position) - end_x=Main_separator_position; - else - end_x=Main_image_width; - - if ((Main_X_zoom+(Main_image_width*Main_magnifier_factor))>=Screen_width) - end_x_mag=Screen_width; - else - end_x_mag=(Main_X_zoom+(Main_image_width*Main_magnifier_factor)); - - if (Main_image_height*Main_magnifier_factor>=Menu_Y_before_window) - end_y_mag=Menu_Y_before_window; - else - end_y_mag=Main_image_height*Main_magnifier_factor; - } - - // On doit maintenant faire la traduction à l'écran - Remap_zone_highlevel(0,0,end_x,end_y,conversion_table); - - if (Main_magnifier_mode) - { - Remap_zone_highlevel(Main_separator_position,0,end_x_mag,end_y_mag,conversion_table); - // Il peut encore rester le bas de la barre de split à remapper si la - // partie zoomée ne descend pas jusqu'en bas... - Remap_zone_highlevel(Main_separator_position,end_y_mag, - (Main_separator_position+(SEPARATOR_WIDTH*Menu_factor_X)), - Menu_Y_before_window,conversion_table); - } - // Remappe tous les fonds de fenetre (qui doivent contenir un bout d'écran) - Remap_window_backgrounds(conversion_table, 0, Menu_Y_before_window); -} - - -void Swap(int with_remap,short block_1_start,short block_2_start,short block_size,T_Palette palette, dword * color_usage) -{ - short pos_1; - short pos_2; - short end_1; - short end_2; - dword temp; - byte conversion_table[256]; - - T_Components temp_palette[256]; - dword Utilisation_temporaire[256]; - - // On fait une copie de la palette - memcpy(temp_palette, palette, sizeof(T_Palette)); - - // On fait une copie de la table d'utilisation des couleurs - memcpy(Utilisation_temporaire, color_usage, sizeof(dword) * 256); - - // On commence à initialiser la table de conversion à un état où elle ne - // fera aucune conversion. - for (pos_1=0;pos_1<=255;pos_1++) - conversion_table[pos_1]=pos_1; - - // On calcul les dernières couleurs de chaque bloc. - end_1=block_1_start+block_size-1; - end_2=block_2_start+block_size-1; - - if ((block_2_start>=block_1_start) && (block_2_start<=end_1)) - { - // Le bloc destination commence dans le bloc source. - - for (pos_1=block_1_start,pos_2=end_1+1;pos_1<=end_2;pos_1++) - { - // Il faut transformer la couleur pos_1 en pos_2: - - conversion_table[pos_2]=pos_1; - color_usage[pos_1]=Utilisation_temporaire[pos_2]; - palette[pos_1].R=temp_palette[pos_2].R; - palette[pos_1].G=temp_palette[pos_2].G; - palette[pos_1].B=temp_palette[pos_2].B; - - // On gère la mise à jour de pos_2 - if (pos_2==end_2) - pos_2=block_1_start; - else - pos_2++; - } - } - else - if ((block_2_start=block_1_start)) - { - // Le bloc destination déborde dans le bloc source. - - for (pos_1=block_2_start,pos_2=block_1_start;pos_1<=end_1;pos_1++) - { - // Il faut transformer la couleur pos_1 en pos_2: - - conversion_table[pos_2]=pos_1; - color_usage[pos_1]=Utilisation_temporaire[pos_2]; - palette[pos_1].R=temp_palette[pos_2].R; - palette[pos_1].G=temp_palette[pos_2].G; - palette[pos_1].B=temp_palette[pos_2].B; - - // On gère la mise à jour de pos_2 - if (pos_2==end_1) - pos_2=block_2_start; - else - pos_2++; - } - } - else - { - // Le bloc source et le bloc destination sont distincts. - - for (pos_1=block_1_start,pos_2=block_2_start;pos_1<=end_1;pos_1++,pos_2++) - { - // Il va falloir permutter la couleur pos_1 avec la couleur pos_2 - conversion_table[pos_1]=pos_2; - conversion_table[pos_2]=pos_1; - - // On intervertit le nombre d'utilisation des couleurs pour garder une - // cohérence lors d'un éventuel "Zap unused". - temp =color_usage[pos_1]; - color_usage[pos_1]=color_usage[pos_2]; - color_usage[pos_2]=temp; - - // On fait un changement de teinte: - temp =palette[pos_1].R; - palette[pos_1].R=palette[pos_2].R; - palette[pos_2].R=temp; - - temp =palette[pos_1].G; - palette[pos_1].G=palette[pos_2].G; - palette[pos_2].G=temp; - - temp =palette[pos_1].B; - palette[pos_1].B=palette[pos_2].B; - palette[pos_2].B=temp; - } - } - - if (with_remap) - { - Remap_image_highlevel(conversion_table); - } -} - - - -void Set_nice_menu_colors(dword * color_usage,int not_picture) -{ - short index,index2; - byte color; - byte replace_table[256]; - T_Components rgb[4]; - short new_colors[4]={255,254,253,252}; - - // On initialise la table de remplacement - for (index=0; index<256; index++) - replace_table[index]=index; - - // On recherche les 4 couleurs les moins utilisées dans l'image pour pouvoir - // les remplacer par les nouvelles couleurs. - for (index2=0; index2<4; index2++) - for (index=255; index>=0; index--) - { - if ((index!=new_colors[0]) && (index!=new_colors[1]) - && (index!=new_colors[2]) && (index!=new_colors[3]) - && (color_usage[index]new_colors[index+1]) - { - index2 =new_colors[index]; - new_colors[index] =new_colors[index+1]; - new_colors[index+1]=index2; - color=1; - } - } - } while (color); - - // On sauvegarde dans rgb les teintes qu'on va remplacer et on met les - // couleurs du menu par défaut - for (index=0; index<4; index++) - { - color=new_colors[index]; - rgb[index].R=Main_palette[color].R; - rgb[index].G=Main_palette[color].G; - rgb[index].B=Main_palette[color].B; - Main_palette[color].R=Fav_menu_colors[index].R; - Main_palette[color].G=Fav_menu_colors[index].G; - Main_palette[color].B=Fav_menu_colors[index].B; - } - - // Maintenant qu'on a placé notre nouvelle palette, on va chercher quelles - // sont les couleurs qui peuvent remplacer les anciennes - Hide_cursor(); - for (index=0; index<4; index++) - replace_table[new_colors[index]]=Best_color_nonexcluded - (rgb[index].R,rgb[index].G,rgb[index].B); - - if (not_picture) - { - // Remap caused by preview. Only remap screen - Remap_zone_highlevel(0,0,Screen_width,Screen_height,replace_table); - } - else - { - // On fait un changement des couleurs visibles à l'écran et dans l'image - Remap_image_highlevel(replace_table); - } - Display_cursor(); -} - - - -void Reduce_palette(short * used_colors,int nb_colors_asked,T_Palette palette,dword * color_usage) -{ - char str[5]; // buffer d'affichage du compteur - byte conversion_table[256]; // Table de conversion - int color_1; // |_ Variables de balayages - int color_2; // | de la palette - int best_color_1=0; - int best_color_2=0; - int difference; - int best_difference; - dword Utilisation; - dword Meilleure_utilisation; - - // On commence par initialiser la table de conversion dans un état où - // aucune conversion ne sera effectuée. - for (color_1=0; color_1<=255; color_1++) - conversion_table[color_1]=color_1; - - // Si on ne connait pas encore le nombre de couleurs utilisées, on le - // calcule! (!!! La fonction appelée Efface puis Affiche le curseur !!!) - if ((*used_colors)<0) - Update_color_count(used_colors,color_usage); - - Hide_cursor(); - - // On tasse la palette vers le début parce qu'elle doit ressembler à - // du Gruyère (et comme Papouille il aime pas le fromage...) - - // Pour cela, on va scruter la couleur color_1 et se servir de l'indice - // color_2 comme position de destination. - for (color_1=color_2=0;color_1<=255;color_1++) - { - if (color_usage[color_1]) - { - // On commence par s'occuper des teintes de la palette - palette[color_2].R=palette[color_1].R; - palette[color_2].G=palette[color_1].G; - palette[color_2].B=palette[color_1].B; - - // Ensuite, on met à jour le tableau d'occupation des couleurs. - color_usage[color_2]=color_usage[color_1]; - - // On va maintenant s'occuper de la table de conversion: - conversion_table[color_1]=color_2; - - // Maintenant, la place désignée par color_2 est occupée, alors on - // doit passer à un indice de destination suivant. - color_2++; - } - } - - // On met toutes les couleurs inutilisées en noir - for (;color_2<256;color_2++) - { - palette[color_2].R=0; - palette[color_2].G=0; - palette[color_2].B=0; - color_usage[color_2]=0; - } - - // Maintenant qu'on a une palette clean, on va boucler en réduisant - // le nombre de couleurs jusqu'à ce qu'on atteigne le nombre désiré. - while ((*used_colors)>nb_colors_asked) - { - // Il s'agit de trouver les 2 couleurs qui se ressemblent le plus - // parmis celles qui sont utilisées (bien sûr) et de les remplacer par - // une seule couleur qui est la moyenne pondérée de ces 2 couleurs - // en fonction de leur utilisation dans l'image. - - best_difference =0x7FFF; - Meilleure_utilisation=0x7FFFFFFF; - - for (color_1=0;color_1<(*used_colors);color_1++) - for (color_2=color_1+1;color_2<(*used_colors);color_2++) - if (color_1!=color_2) - { - difference =abs((short)palette[color_1].R-palette[color_2].R)+ - abs((short)palette[color_1].G-palette[color_2].G)+ - abs((short)palette[color_1].B-palette[color_2].B); - - if (difference<=best_difference) - { - Utilisation=color_usage[color_1]+color_usage[color_2]; - if ((differencebest_color_2) - { - // La color_1 va scroller en arrière. - - // Donc on transfère son utilisation dans l'utilisation de la - // couleur qui la précède. - color_usage[color_1-1]=color_usage[color_1]; - - // Et on transfère ses teintes dans les teintes de la couleur qui - // la précède. - palette[color_1-1].R=palette[color_1].R; - palette[color_1-1].G=palette[color_1].G; - palette[color_1-1].B=palette[color_1].B; - } - - // Une fois la palette et la table d'utilisation gérées, on peut - // s'occuper de notre table de conversion. - if (conversion_table[color_1]>best_color_2) - // La color_1 avait l'intention de se faire remplacer par une - // couleur que l'on va (ou que l'on a déjà) bouger en arrière. - conversion_table[color_1]--; - } - - // On vient d'éjecter une couleur, donc on peut mettre à jour le nombre - // de couleurs utilisées. - (*used_colors)--; - - // A la fin, on doit passer (dans la palette) les teintes du dernier - // élément de notre ensemble en noir. - palette[*used_colors].R=0; - palette[*used_colors].G=0; - palette[*used_colors].B=0; - - // Au passage, on va s'assurer que l'on a pas oublié de la mettre à une - // utilisation nulle. - color_usage[*used_colors]=0; - - // Après avoir éjecté une couleur, on le fait savoir à l'utilisateur par - // l'intermédiaire du compteur de nombre utilisées. - Num2str(*used_colors,str,3); - Print_in_window(186,23,str,MC_Black,MC_Light); - } - - // Maintenant, tous ces calculs doivent êtres pris en compte dans la - // palette, l'image et à l'écran. - Remap_image_highlevel(conversion_table); // Et voila pour l'image et l'écran - Display_cursor(); -} - - - -void Set_palette_slider(T_Scroller_button * slider, - word nb_elements, word position, - char * value, short x_pos) -{ - slider->Nb_elements=nb_elements; - slider->Position=position; - Compute_slider_cursor_height(slider); - Window_draw_slider(slider); - Print_counter(x_pos,172,value,MC_Black,MC_Light); -} - - - -void Display_sliders(T_Scroller_button * red_slider, - T_Scroller_button * green_slider, - T_Scroller_button * blue_slider, - byte block_is_selected, T_Components * palette) -{ - char str[5]; - - if (block_is_selected) - { - Set_palette_slider(red_slider,Color_max*2+1,Color_max,"± 0",176); - Set_palette_slider(green_slider,Color_max*2+1,Color_max,"± 0",203); - Set_palette_slider(blue_slider,Color_max*2+1,Color_max,"± 0",230); - } - else - { - byte j1, j2, j3; - j1= palette[Fore_color].R; - j2= palette[Fore_color].G; - j3= palette[Fore_color].B; - if (!Palette_view_is_RGB) - { - RGB_to_HSL(j1,j2,j3,&j1,&j2,&j3); - } - - Format_componant(j1*Color_max/255,str); - Set_palette_slider(red_slider,Color_count,Color_max-j1*Color_max/255,str,176); - Format_componant(j2*Color_max/255,str); - Set_palette_slider(green_slider,Color_count,Color_max-j2*Color_max/255,str,203); - Format_componant(j3*Color_max/255,str); - Set_palette_slider(blue_slider,Color_count,Color_max-j3*Color_max/255,str,230); - } -} - - - -void Draw_all_palette_sliders(T_Scroller_button * red_slider, - T_Scroller_button * green_slider, - T_Scroller_button * blue_slider, - T_Palette palette,byte start,byte end) -{ - char str[5]; - - Hide_cursor(); - // Réaffichage des jauges: - if (start!=end) - { - // Dans le cas d'un bloc, tout à 0. - red_slider->Position =Color_max; - Window_draw_slider(red_slider); - Print_counter(176,172,"± 0",MC_Black,MC_Light); - - green_slider->Position =Color_max; - Window_draw_slider(green_slider); - Print_counter(203,172,"± 0",MC_Black,MC_Light); - - blue_slider->Position =Color_max; - Window_draw_slider(blue_slider); - Print_counter(230,172,"± 0",MC_Black,MC_Light); - } - else - { - // Dans le cas d'une seule couleur, composantes. - byte j1, j2, j3; - j1= palette[start].R; - j2= palette[start].G; - j3= palette[start].B; - if (!Palette_view_is_RGB) - { - RGB_to_HSL(j1,j2,j3,&j1,&j2,&j3); - } - Format_componant(j1*Color_max/255,str); - red_slider->Position=Color_max-j1*Color_max/255; - Window_draw_slider(red_slider); - Print_counter(176,172,str,MC_Black,MC_Light); - - Format_componant(j2*Color_max/255,str); - green_slider->Position=Color_max-j2*Color_max/255; - Window_draw_slider(green_slider); - Print_counter(203,172,str,MC_Black,MC_Light); - - Format_componant(j3*Color_max/255,str); - blue_slider->Position=Color_max-j3*Color_max/255; - Window_draw_slider(blue_slider); - Print_counter(230,172,str,MC_Black,MC_Light); - } - Display_cursor(); -} - - -void Button_Palette(void) -{ - static short reducer_index=0; - static short reduce_colors_number=256; - short temp_color; // Variable pouvant reservir pour différents calculs intermédiaires - dword temp; - byte color,click; // Variables pouvant reservir pour différents calculs intermédiaires - short clicked_button; - word old_mouse_x; - word old_mouse_y; - byte old_mouse_k; - byte block_start; - byte block_end; - byte first_color; - byte last_color; - char str[10]; - word i; - //short x_pos,y_pos; - T_Normal_button * button_used; - T_Scroller_button * red_slider; - T_Scroller_button * green_slider; - T_Scroller_button * blue_slider; - T_Scroller_button * reduce_slider; - byte image_is_backed_up=0; - byte need_to_remap=0; - - dword color_usage[256]; - short used_colors=-1; // -1 <=> Inconnu - byte conversion_table[256]; - - T_Components * backup_palette; - T_Components * temp_palette; - T_Components * working_palette; - - backup_palette =(T_Components *)malloc(sizeof(T_Palette)); - temp_palette=(T_Components *)malloc(sizeof(T_Palette)); - working_palette=(T_Components *)malloc(sizeof(T_Palette)); - - Componant_unit(RGB_scale); - - Open_window(299,188,"Palette"); - - memcpy(working_palette,Main_palette,sizeof(T_Palette)); - memcpy(backup_palette ,Main_palette,sizeof(T_Palette)); - memcpy(temp_palette,Main_palette,sizeof(T_Palette)); - - Window_set_palette_button(5,79); // 1 - - Window_display_frame (173, 67,121,116); - Window_display_frame (128, 16, 91, 39); - Window_display_frame (221, 16, 73, 39); - // Frame creux destiné à l'affichage de la(les) couleur(s) sélectionnée(s) - Window_display_frame_in(259, 88, 26, 74); - - // Graduation des jauges de couleur - Block(Window_pos_X+(Menu_factor_X*179),Window_pos_Y+(Menu_factor_Y*109),Menu_factor_X*17,Menu_factor_Y,MC_Dark); - Block(Window_pos_X+(Menu_factor_X*206),Window_pos_Y+(Menu_factor_Y*109),Menu_factor_X*17,Menu_factor_Y,MC_Dark); - Block(Window_pos_X+(Menu_factor_X*233),Window_pos_Y+(Menu_factor_Y*109),Menu_factor_X*17,Menu_factor_Y,MC_Dark); - Block(Window_pos_X+(Menu_factor_X*179),Window_pos_Y+(Menu_factor_Y*125),Menu_factor_X*17,Menu_factor_Y,MC_Dark); - Block(Window_pos_X+(Menu_factor_X*206),Window_pos_Y+(Menu_factor_Y*125),Menu_factor_X*17,Menu_factor_Y,MC_Dark); - Block(Window_pos_X+(Menu_factor_X*233),Window_pos_Y+(Menu_factor_Y*125),Menu_factor_X*17,Menu_factor_Y,MC_Dark); - Block(Window_pos_X+(Menu_factor_X*179),Window_pos_Y+(Menu_factor_Y*141),Menu_factor_X*17,Menu_factor_Y,MC_Dark); - Block(Window_pos_X+(Menu_factor_X*206),Window_pos_Y+(Menu_factor_Y*141),Menu_factor_X*17,Menu_factor_Y,MC_Dark); - Block(Window_pos_X+(Menu_factor_X*233),Window_pos_Y+(Menu_factor_Y*141),Menu_factor_X*17,Menu_factor_Y,MC_Dark); - // Jauges de couleur - Palette_view_is_RGB=1; - red_slider = Window_set_scroller_button(182, 81, 88,Color_count,1,Color_max-working_palette[Fore_color].R*Color_max/255);// 2 - green_slider = Window_set_scroller_button(209, 81, 88,Color_count,1,Color_max-working_palette[Fore_color].G*Color_max/255);// 3 - blue_slider = Window_set_scroller_button(236, 81, 88,Color_count,1,Color_max-working_palette[Fore_color].B*Color_max/255);// 4 - Print_in_window(184,71,"R",MC_Dark,MC_Light); - Print_in_window(211,71,"G",MC_Dark,MC_Light); - Print_in_window(238,71,"B",MC_Dark,MC_Light); - - first_color=last_color=block_start=block_end=Fore_color; - Tag_color_range(block_start,block_end); - - // Affichage dans le block de visu de la couleur en cours - Block(Window_pos_X+(Menu_factor_X*260),Window_pos_Y+(Menu_factor_Y*89),Menu_factor_X*24,Menu_factor_Y*72,Back_color); - Block(Window_pos_X+(Menu_factor_X*264),Window_pos_Y+(Menu_factor_Y*93),Menu_factor_X<<4,Menu_factor_Y*64,Fore_color); - - // Affichage des valeurs de la couleur courante (pour 1 couleur) - Format_componant(Main_palette[Fore_color].R*Color_max/255,str); - Print_counter(176,172,str,MC_Black,MC_Light); - Format_componant(Main_palette[Fore_color].G*Color_max/255,str); - Print_counter(203,172,str,MC_Black,MC_Light); - Format_componant(Main_palette[Fore_color].B*Color_max/255,str); - Print_counter(230,172,str,MC_Black,MC_Light); - - Print_in_window(129,58,"Color number:",MC_Dark,MC_Light); - Num2str(Fore_color,str,3); - Print_in_window(237,58,str,MC_Black,MC_Light); - - - Window_set_normal_button( 6,17,59,14,"Default",3,1,SDLK_f); // 5 - Window_set_normal_button(66,17,29,14,"Gry" ,1,1,SDLK_g); // 6 - Window_set_normal_button(66,47,29,14,"Swp" ,0,1,KEY_NONE); // 7 - Window_set_normal_button( 6,47,59,14,"X-Swap" ,1,1,SDLK_x); // 8 - Window_set_normal_button(66,32,29,14,"Cpy" ,1,1,SDLK_c); // 9 - Window_set_normal_button( 6,32,59,14,"Spread" ,4,1,SDLK_e); // 10 - - Window_set_normal_button(239,20,51,14,"Reduce" ,1,1,SDLK_r); // 11 - Print_in_window(241,41,"to",MC_Dark,MC_Light); - - Window_set_normal_button( 6,168,35,14,"Undo" ,1,1,SDLK_u); // 12 - Window_set_normal_button( 62,168,51,14,"Cancel",0,1,KEY_ESC); // 13 - Window_set_normal_button(117,168,51,14,"OK" ,0,1,SDLK_RETURN); // 14 - - button_used = Window_set_normal_button(132,20,83,14,"Used: ???",4,1,SDLK_d);// 15 - Window_set_normal_button(132,37,83,14,"Zap unused",0,1,SDLK_DELETE);//16 - - // Jauge de réduction de palette - reduce_slider = Window_set_scroller_button(225,20,31,7,1,reducer_index);// 17 - - Window_set_repeatable_button(266, 74,12,11,"+",0,1,SDLK_KP_PLUS); // 18 - Window_set_repeatable_button(266,165,12,11,"-",0,1,SDLK_KP_MINUS); // 19 - - Window_set_normal_button(96,17,29,14,"Neg" ,1,1,SDLK_n); // 20 - Window_set_normal_button(66,62,29,14,"Inv" ,1,1,SDLK_i); // 21 - Window_set_normal_button( 6,62,59,14,"X-Inv." ,5,1,SDLK_v); // 22 - - Window_set_input_button(263,39,3); // 23 - - Window_set_normal_button(96,32,29,14,"HSL" ,1,1,SDLK_h); // 24 - Window_set_normal_button(96,47,29,14,"Srt" ,1,1,SDLK_s); // 25 - // Affichage du facteur de réduction de la palette - Num2str(reduce_colors_number,str,3); - Print_in_window(265,41,str,MC_Black,MC_Light); - - // Dessin des petits effets spéciaux pour les boutons [+] et [-] - Draw_thingumajig(263, 74,MC_White,-1); - Draw_thingumajig(280, 74,MC_White,+1); - Draw_thingumajig(263,165,MC_Dark,-1); - Draw_thingumajig(280,165,MC_Dark,+1); - - Update_window_area(0,0,299,188); - - Display_cursor(); - - if (Config.Auto_nb_used) - Update_color_count(&used_colors,color_usage); - - do - { - old_mouse_x=Mouse_X; - old_mouse_y=Mouse_Y; - old_mouse_k=Mouse_K; - clicked_button=Window_clicked_button(); - - switch (clicked_button) - { - case 0 : // Nulle part - break; - case -1 : // Hors de la fenêtre - case 1 : // palette - if ( (Mouse_X!=old_mouse_x) || (Mouse_Y!=old_mouse_y) || (Mouse_K!=old_mouse_k) ) - { - Hide_cursor(); - temp_color=(clicked_button==1) ? Window_attribute2 : Read_pixel(Mouse_X,Mouse_Y); - if (Mouse_K==RIGHT_SIDE) - { - if (Back_color!=temp_color) - { - Back_color=temp_color; - // 4 blocks de back_color entourant la fore_color - Block(Window_pos_X+(Menu_factor_X*260),Window_pos_Y+(Menu_factor_Y* 89),Menu_factor_X*24,Menu_factor_Y<<2,Back_color); - Block(Window_pos_X+(Menu_factor_X*260),Window_pos_Y+(Menu_factor_Y*157),Menu_factor_X*24,Menu_factor_Y<<2,Back_color); - Block(Window_pos_X+(Menu_factor_X*260),Window_pos_Y+(Menu_factor_Y* 93),Menu_factor_X<<2,Menu_factor_Y<<6,Back_color); - Block(Window_pos_X+(Menu_factor_X*280),Window_pos_Y+(Menu_factor_Y* 93),Menu_factor_X<<2,Menu_factor_Y<<6,Back_color); - Update_rect(Window_pos_X+(Menu_factor_X*260),Window_pos_Y+(Menu_factor_Y* 89),Menu_factor_X*32,Menu_factor_Y*72); - } - } - else - { - if (!old_mouse_k) - { - // On vient de clicker sur une couleur (et une seule) - if ( (Fore_color!=temp_color) || (block_start!=block_end) ) - { - // La couleur en question est nouvelle ou elle annule un - // ancien bloc. Il faut donc sélectionner cette couleur comme - // unique couleur choisie. - - Fore_color=first_color=last_color=block_start=block_end=temp_color; - Tag_color_range(block_start,block_end); - - // Affichage du n° de la couleur sélectionnée - Block(Window_pos_X+(Menu_factor_X*237),Window_pos_Y+(Menu_factor_Y*58),Menu_factor_X*56,Menu_factor_Y*7,MC_Light); - Num2str(Fore_color,str,3); - Print_in_window(237,58,str,MC_Black,MC_Light); - Update_rect(Window_pos_X+(Menu_factor_X*237),Window_pos_Y+(Menu_factor_Y*58),Menu_factor_X*56,Menu_factor_Y*7); - - // Affichage des jauges - Block(Window_pos_X+(Menu_factor_X*176),Window_pos_Y+(Menu_factor_Y*172),Menu_factor_X*84,Menu_factor_Y*7,MC_Light); - Display_sliders(red_slider,green_slider,blue_slider,0,working_palette); - - // Affichage dans le block de visu de la couleur en cours - Block(Window_pos_X+(Menu_factor_X*264),Window_pos_Y+(Menu_factor_Y*93),Menu_factor_X<<4,Menu_factor_Y*64,Fore_color); - Update_rect(Window_pos_X+(Menu_factor_X*264),Window_pos_Y+(Menu_factor_Y*93),Menu_factor_X<<4,Menu_factor_Y*64); - - memcpy(backup_palette ,working_palette,sizeof(T_Palette)); - memcpy(temp_palette,working_palette,sizeof(T_Palette)); - } - } - else - { - // On maintient le click, on va donc tester si le curseur bouge - if (temp_color!=last_color) - { - // On commence par ordonner la 1ère et dernière couleur du bloc - if (first_colortemp_color) - { - block_start=temp_color; - block_end=first_color; - - // Affichage du n° de la couleur sélectionnée - Num2str(block_start,str ,3); - Num2str(block_end ,str+4,3); - str[3]=26; // Flèche vers la droite - Print_in_window(237,58,str,MC_Black,MC_Light); - - // Affichage des jauges - Display_sliders(red_slider,green_slider,blue_slider,1,NULL); - - // Affichage dans le block de visu du bloc (dégradé) en cours - Display_grad_block_in_window(264,93,block_start,block_end); - } - else - { - block_start=block_end=first_color; - Block(Window_pos_X+(Menu_factor_X*176),Window_pos_Y+(Menu_factor_Y*172),Menu_factor_X*84,Menu_factor_Y*7,MC_Light); - - // Affichage du n° de la couleur sélectionnée - Block(Window_pos_X+(Menu_factor_X*261),Window_pos_Y+(Menu_factor_Y*58),Menu_factor_X*32,Menu_factor_Y*7,MC_Light); - Num2str(Fore_color,str,3); - Print_in_window(237,58,str,MC_Black,MC_Light); - - // Affichage des jauges - Display_sliders(red_slider,green_slider,blue_slider,0,working_palette); - - // Affichage dans le block de visu de la couleur en cours - Block(Window_pos_X+(Menu_factor_X*264),Window_pos_Y+(Menu_factor_Y*93),Menu_factor_X<<4,Menu_factor_Y*64,Fore_color); - Update_rect(Window_pos_X+(Menu_factor_X*264),Window_pos_Y+(Menu_factor_Y*93),Menu_factor_X<<4,Menu_factor_Y*64); - } - - // On tagge le bloc (ou la couleur) - Tag_color_range(block_start,block_end); - } - - last_color=temp_color; - } - } - Display_cursor(); - } - break; - case 2 : // Jauge rouge - Hide_cursor(); - if (block_start==block_end) - { - if(Palette_view_is_RGB) - { - Set_red(Fore_color,(Color_max-red_slider->Position)*255/Color_max,working_palette); - Format_componant(working_palette[Fore_color].R*Color_max/255,str); - } - else - { - HSL_to_RGB( - 255-red_slider->Position, - 255-green_slider->Position, - 255-blue_slider->Position, - &working_palette[Fore_color].R, - &working_palette[Fore_color].G, - &working_palette[Fore_color].B); - Format_componant((int)255-red_slider->Position,str); - } - Print_counter(176,172,str,MC_Black,MC_Light); - } - else - { - if(Palette_view_is_RGB) - { - for (i=block_start; i<=block_end; i++) - Set_red(i,temp_palette[i].R+(Color_max-red_slider->Position)*255/Color_max,working_palette); - } - else - { - for (i=block_start; i<=block_end; i++) - Set_HSL( - temp_palette, - working_palette, - i, - Color_max-red_slider->Position, - Color_max-green_slider->Position, - Color_max-blue_slider->Position - ); - } - - if (red_slider->Position>Color_max) - { - // Jauge dans les négatifs: - Num2str(-(Color_max-red_slider->Position),str,4); - str[0]='-'; - } - else if (red_slider->PositionPosition ,str,4); - str[0]='+'; - } - else - { - // Jauge nulle: - strcpy(str,"± 0"); - } - Print_counter(176,172,str,MC_Black,MC_Light); - - } - - need_to_remap=1; - - Display_cursor(); - Set_palette(working_palette); - break; - case 3 : // Jauge verte - Hide_cursor(); - if (block_start==block_end) - { - if(Palette_view_is_RGB) - { - Set_green (Fore_color,(Color_max-green_slider->Position)*255/Color_max,working_palette); - Format_componant(working_palette[Fore_color].G*Color_max/255,str); - } - else - { - HSL_to_RGB( - 255-red_slider->Position, - 255-green_slider->Position, - 255-blue_slider->Position, - &working_palette[Fore_color].R, - &working_palette[Fore_color].G, - &working_palette[Fore_color].B); - Format_componant((int)255-green_slider->Position,str); - } - Print_counter(203,172,str,MC_Black,MC_Light); - } - else - { - if(Palette_view_is_RGB) - { - for (i=block_start; i<=block_end; i++) - Set_green (i,temp_palette[i].G+(Color_max-green_slider->Position)*255/Color_max,working_palette); - } - else - { - for (i=block_start; i<=block_end; i++) - Set_HSL( - temp_palette, - working_palette, - i, - Color_max-red_slider->Position, - Color_max-green_slider->Position, - Color_max-blue_slider->Position - ); - } - - if (green_slider->Position>Color_max) - { - // Jauge dans les négatifs: - Num2str(-(Color_max-green_slider->Position),str,4); - str[0]='-'; - } - else if (green_slider->PositionPosition ,str,4); - str[0]='+'; - } - else - { - // Jauge nulle: - strcpy(str,"± 0"); - } - Print_counter(203,172,str,MC_Black,MC_Light); - } - - need_to_remap=1; - - Display_cursor(); - Set_palette(working_palette); - break; - - case 4 : // Jauge bleue - Hide_cursor(); - if (block_start==block_end) - { - if(Palette_view_is_RGB) - { - Set_blue (Fore_color,(Color_max-blue_slider->Position)*255/Color_max,working_palette); - Format_componant(working_palette[Fore_color].B*Color_max/255,str); - } - else - { - HSL_to_RGB( - 255-red_slider->Position, - 255-green_slider->Position, - 255-blue_slider->Position, - &working_palette[Fore_color].R, - &working_palette[Fore_color].G, - &working_palette[Fore_color].B); - Format_componant((int)255-blue_slider->Position,str); - } - Print_counter(230,172,str,MC_Black,MC_Light); - } - else - { - if(Palette_view_is_RGB) - { - for (i=block_start; i<=block_end; i++) - Set_blue(i,temp_palette[i].B+(Color_max-blue_slider->Position)*255/Color_max,working_palette); - } - else - { - for (i=block_start; i<=block_end; i++) - Set_HSL( - temp_palette, - working_palette, - i, - Color_max-red_slider->Position, - Color_max-green_slider->Position, - Color_max-blue_slider->Position - ); - } - - if (blue_slider->Position>Color_max) - { - // Jauge dans les négatifs: - Num2str(-(Color_max-blue_slider->Position),str,4); - str[0]='-'; - } - else if (blue_slider->PositionPosition ,str,4); - str[0]='+'; - } - else - { - // Jauge nulle: - strcpy(str,"± 0"); - } - Print_counter(230,172,str,MC_Black,MC_Light); - } - - need_to_remap=1; - - Display_cursor(); - Set_palette(working_palette); - break; - - case 5 : // Default - memcpy(backup_palette,working_palette,sizeof(T_Palette)); - memcpy(working_palette,Default_palette,sizeof(T_Palette)); - memcpy(temp_palette,Default_palette,sizeof(T_Palette)); - Set_palette(Default_palette); - Draw_all_palette_sliders(red_slider,green_slider,blue_slider,working_palette,block_start,block_end); - // On prépare la "modifiabilité" des nouvelles couleurs - memcpy(temp_palette,working_palette,sizeof(T_Palette)); - - need_to_remap=1; - break; - - case 6 : // Grey scale - // Backup - memcpy(backup_palette,working_palette,sizeof(T_Palette)); - // Grey Scale - for (i=block_start;i<=block_end;i++) - { - temp_color=(dword)( ((dword)working_palette[i].R*30) + ((dword)working_palette[i].G*59) + ((dword)working_palette[i].B*11) )/100; - Set_red(i,temp_color,working_palette); - Set_green (i,temp_color,working_palette); - Set_blue (i,temp_color,working_palette); - } - Draw_all_palette_sliders(red_slider,green_slider,blue_slider,working_palette,block_start,block_end); - // On prépare la "modifiabilité" des nouvelles couleurs - Set_palette(working_palette); - memcpy(temp_palette,working_palette,sizeof(T_Palette)); - - need_to_remap=1; - break; - - case 7 : // Swap - case 8 : // X-Swap - temp_color=Wait_click_in_palette(Window_palette_button_list); - if ((temp_color>=0) - && (temp_color!=block_start)) - { - Hide_cursor(); - memcpy(backup_palette,working_palette,sizeof(T_Palette)); - - // On calcule le nombre de couleurs a swapper sans risquer de sortir - // de la palette (La var. first_color est utilisée pour économiser 1 var; c'est tout) - first_color=(temp_color+block_end-block_start<=255)?block_end+1-block_start:256-temp_color; - - if (clicked_button==8) // On ne fait de backup de l'image que si on - // est en mode X-SWAP. - if (!image_is_backed_up) - { - Backup(); - image_is_backed_up=1; - } - - Swap(clicked_button==8,block_start,temp_color,first_color,working_palette,color_usage); - - memcpy(temp_palette,working_palette,sizeof(T_Palette)); - - // On déplace le bloc vers les modifs: - last_color=block_end=temp_color+first_color-1; - Fore_color=first_color=block_start=temp_color; - // On raffiche le n° des bornes du bloc: - if (block_start!=block_end) - { - // Cas d'un bloc multi-couleur - Num2str(block_start,str ,3); - Num2str(block_end ,str+4,3); - str[3]=26; // Flèche vers la droite - // Affichage dans le block de visu du bloc (dégradé) en cours - Display_grad_block_in_window(264,93,block_start,block_end); - } - else - { - // Cas d'une seule couleur - Num2str(Fore_color,str,3); - Block(Window_pos_X+(Menu_factor_X*237),Window_pos_Y+(Menu_factor_Y*58),Menu_factor_X*56,Menu_factor_Y* 7,MC_Light); - // Affichage dans le block de visu de la couleur en cours - Block(Window_pos_X+(Menu_factor_X*264),Window_pos_Y+(Menu_factor_Y*93),Menu_factor_X<<4,Menu_factor_Y*64,Fore_color); - } - Print_in_window(237,58,str,MC_Black,MC_Light); - // On tag le bloc (ou la couleur) - Tag_color_range(block_start,block_end); - - need_to_remap=1; - - Set_palette(working_palette); - - Display_cursor(); - Draw_all_palette_sliders(red_slider,green_slider,blue_slider,working_palette,block_start,block_end); - - // En cas de X-Swap, tout l'ecran a pu changer de couleur. - if (clicked_button==8) - Update_rect(0, 0, Screen_width, Menu_Y_before_window); - Wait_end_of_click(); - } - break; - - case 9 : // Copy - temp_color=Wait_click_in_palette(Window_palette_button_list); - if ((temp_color>=0) && (temp_color!=block_start)) - { - Hide_cursor(); - memcpy(backup_palette,working_palette,sizeof(T_Palette)); - memcpy(working_palette+temp_color,backup_palette+block_start, - ((temp_color+block_end-block_start<=255)?block_end+1-block_start:256-temp_color)*3); - memcpy(temp_palette,working_palette,sizeof(T_Palette)); - Set_palette(working_palette); - // On déplace le bloc vers les modifs: - last_color=block_end=((temp_color+block_end-block_start<=255)?(temp_color+block_end-block_start):255); - Fore_color=first_color=block_start=temp_color; - // On raffiche le n° des bornes du bloc: - if (block_start!=block_end) - { - // Cas d'un bloc multi-couleur - Num2str(block_start,str ,3); - Num2str(block_end ,str+4,3); - str[3]=26; // Flèche vers la droite - // Affichage dans le block de visu du bloc (dégradé) en cours - Display_grad_block_in_window(264,93,block_start,block_end); - } - else - { - // Cas d'une seule couleur - Num2str(Fore_color,str,3); - Block(Window_pos_X+(Menu_factor_X*237),Window_pos_Y+(Menu_factor_Y*58),Menu_factor_X*56,Menu_factor_Y* 7,MC_Light); - // Affichage dans le block de visu de la couleur en cours - Block(Window_pos_X+(Menu_factor_X*264),Window_pos_Y+(Menu_factor_Y*93),Menu_factor_X<<4,Menu_factor_Y*64,Fore_color); - } - Print_in_window(237,58,str,MC_Black,MC_Light); - // On tag le bloc (ou la couleur) - Tag_color_range(block_start,block_end); - - need_to_remap=1; - - Display_cursor(); - Draw_all_palette_sliders(red_slider,green_slider,blue_slider,working_palette,block_start,block_end); - Wait_end_of_click(); - } - break; - - case 10 : // Spread - if (block_start!=block_end) - { - memcpy(backup_palette,working_palette,sizeof(T_Palette)); - Spread_colors(block_start,block_end,working_palette); - } - else - { - temp_color=Wait_click_in_palette(Window_palette_button_list); - if (temp_color>=0) - { - memcpy(backup_palette,working_palette,sizeof(T_Palette)); - if (temp_colorPosition) - { - reducer_index=reduce_slider->Position; - // Affichage du facteur de réduction de la palette - Hide_cursor(); - Print_in_window(265,41,Palette_reduce_label[reducer_index],MC_Black,MC_Light); - Display_cursor(); - reduce_colors_number=atoi(Palette_reduce_label[reducer_index]); - } - break; - - case 18 : // [+] - if (!Palette_view_is_RGB) - break; - Hide_cursor(); - if (block_start==block_end) - { - if (red_slider->Position) - { - (red_slider->Position)--; - Window_draw_slider(red_slider); - Set_red(Fore_color,(Color_max-red_slider->Position)*255/Color_max,working_palette); - Format_componant(working_palette[Fore_color].R*Color_max/255,str); - Print_counter(176,172,str,MC_Black,MC_Light); - } - if (green_slider->Position) - { - (green_slider->Position)--; - Window_draw_slider(green_slider); - Set_green (Fore_color,(Color_max-green_slider->Position)*255/Color_max,working_palette); - Format_componant(working_palette[Fore_color].G*Color_max/255,str); - Print_counter(203,172,str,MC_Black,MC_Light); - } - if (blue_slider->Position) - { - (blue_slider->Position)--; - Window_draw_slider(blue_slider); - Set_blue (Fore_color,(Color_max-blue_slider->Position)*255/Color_max,working_palette); - Format_componant(working_palette[Fore_color].B*Color_max/255,str); - Print_counter(230,172,str,MC_Black,MC_Light); - } - } - else - { - if (red_slider->Position) - { - (red_slider->Position)--; - Window_draw_slider(red_slider); - } - if (green_slider->Position) - { - (green_slider->Position)--; - Window_draw_slider(green_slider); - } - if (blue_slider->Position) - { - (blue_slider->Position)--; - Window_draw_slider(blue_slider); - } - - for (i=block_start; i<=block_end; i++) - { - Set_red(i,temp_palette[i].R+(Color_max-red_slider->Position)*255/Color_max,working_palette); - Set_green (i,temp_palette[i].G+(Color_max-green_slider->Position)*255/Color_max,working_palette); - Set_blue (i,temp_palette[i].B+(Color_max-blue_slider->Position)*255/Color_max,working_palette); - } - - // -- red -- - if (red_slider->Position>Color_max) - { - // Jauge dans les négatifs: - Num2str(-(Color_max-red_slider->Position),str,4); - str[0]='-'; - } - else if (red_slider->PositionPosition ,str,4); - str[0]='+'; - } - else - { - // Jauge nulle: - strcpy(str,"± 0"); - } - Print_counter(176,172,str,MC_Black,MC_Light); - - - // -- green -- - if (green_slider->Position>Color_max) - { - // Jauge dans les négatifs: - Num2str(-(Color_max-green_slider->Position),str,4); - str[0]='-'; - } - else if (green_slider->PositionPosition ,str,4); - str[0]='+'; - } - else - { - // Jauge nulle: - strcpy(str,"± 0"); - } - Print_counter(203,172,str,MC_Black,MC_Light); - - - // -- blue -- - if (blue_slider->Position>Color_max) - { - // Jauge dans les négatifs: - Num2str(-(Color_max-blue_slider->Position),str,4); - str[0]='-'; - } - else if (blue_slider->PositionPosition ,str,4); - str[0]='+'; - } - else - { - // Jauge nulle: - strcpy(str,"± 0"); - } - Print_counter(230,172,str,MC_Black,MC_Light); - } - - need_to_remap=1; - - Display_cursor(); - Set_palette(working_palette); - break; - - case 19 : // [-] - if (!Palette_view_is_RGB) - break; - Hide_cursor(); - if (block_start==block_end) - { - if (red_slider->PositionPosition)++; - Window_draw_slider(red_slider); - Set_red(Fore_color,(Color_max-red_slider->Position)*255/Color_max,working_palette); - Format_componant(working_palette[Fore_color].R*Color_max/255,str); - Print_counter(176,172,str,MC_Black,MC_Light); - } - if (green_slider->PositionPosition)++; - Window_draw_slider(green_slider); - Set_green (Fore_color,(Color_max-green_slider->Position)*255/Color_max,working_palette); - Format_componant(working_palette[Fore_color].G*Color_max/255,str); - Print_counter(203,172,str,MC_Black,MC_Light); - } - if (blue_slider->PositionPosition)++; - Window_draw_slider(blue_slider); - Set_blue (Fore_color,(Color_max-blue_slider->Position)*255/Color_max,working_palette); - Format_componant(working_palette[Fore_color].B*Color_max/255,str); - Print_counter(230,172,str,MC_Black,MC_Light); - } - } - else - { - if (red_slider->Position<(Color_max*2)) - { - (red_slider->Position)++; - Window_draw_slider(red_slider); - } - if (green_slider->Position<(Color_max*2)) - { - (green_slider->Position)++; - Window_draw_slider(green_slider); - } - if (blue_slider->Position<(Color_max*2)) - { - (blue_slider->Position)++; - Window_draw_slider(blue_slider); - } - - for (i=block_start; i<=block_end; i++) - { - Set_red(i,temp_palette[i].R+(Color_max-red_slider->Position)*255/Color_max,working_palette); - Set_green (i,temp_palette[i].G+(Color_max-green_slider->Position)*255/Color_max,working_palette); - Set_blue (i,temp_palette[i].B+(Color_max-blue_slider->Position)*255/Color_max,working_palette); - } - - // -- red -- - if (red_slider->Position>Color_max) - { - // Jauge dans les négatifs: - Num2str(-(Color_max-red_slider->Position),str,4); - str[0]='-'; - } - else if (red_slider->PositionPosition ,str,4); - str[0]='+'; - } - else - { - // Jauge nulle: - strcpy(str,"± 0"); - } - Print_counter(176,172,str,MC_Black,MC_Light); - - - // -- green -- - if (green_slider->Position>Color_max) - { - // Jauge dans les négatifs: - Num2str(-(Color_max-green_slider->Position),str,4); - str[0]='-'; - } - else if (green_slider->PositionPosition ,str,4); - str[0]='+'; - } - else - { - // Jauge nulle: - strcpy(str,"± 0"); - } - Print_counter(203,172,str,MC_Black,MC_Light); - - - // -- blue -- - if (blue_slider->Position>Color_max) - { - // Jauge dans les négatifs: - Num2str(-(Color_max-blue_slider->Position),str,4); - str[0]='-'; - } - else if (blue_slider->PositionPosition ,str,4); - str[0]='+'; - } - else - { - // Jauge nulle: - strcpy(str,"± 0"); - } - Print_counter(230,172,str,MC_Black,MC_Light); - } - - need_to_remap=1; - - Display_cursor(); - Set_palette(working_palette); - break; - - case 20 : // Negative - // Backup - memcpy(backup_palette,working_palette,sizeof(T_Palette)); - // Negative - for (i=block_start;i<=block_end;i++) - { - Set_red(i,255-working_palette[i].R,working_palette); - Set_green (i,255-working_palette[i].G,working_palette); - Set_blue (i,255-working_palette[i].B,working_palette); - } - Draw_all_palette_sliders(red_slider,green_slider,blue_slider,working_palette,block_start,block_end); - Set_palette(working_palette); - // On prépare la "modifiabilité" des nouvelles couleurs - memcpy(temp_palette,working_palette,sizeof(T_Palette)); - - need_to_remap=1; - break; - - case 21 : // Inversion - case 22 : // X-Inversion - // Backup - memcpy(backup_palette,working_palette,sizeof(T_Palette)); - // On initialise la table de conversion - for (i=0; i<=255; i++) - conversion_table[i]=i; - // Inversion - for (i=block_start;i<=block_end;i++) - { - temp_color=block_end-(i-block_start); - Set_red(i,backup_palette[temp_color].R,working_palette); - Set_green (i,backup_palette[temp_color].G,working_palette); - Set_blue (i,backup_palette[temp_color].B,working_palette); - if (clicked_button==22) - { - conversion_table[i]=temp_color; - conversion_table[temp_color]=i; - - temp=color_usage[i]; - color_usage[i]=color_usage[temp_color]; - color_usage[temp_color]=temp; - } - } - Draw_all_palette_sliders(red_slider,green_slider,blue_slider,working_palette,block_start,block_end); - // Si on est en X-Invert, on remap l'image (=> on fait aussi 1 backup) - if (clicked_button==22) - { - if (!image_is_backed_up) - { - Backup(); - image_is_backed_up=1; - } - Hide_cursor(); - Remap_image_highlevel(conversion_table); - Display_cursor(); - } - // On prépare la "modifiabilité" des nouvelles couleurs - Set_palette(working_palette); - memcpy(temp_palette,working_palette,sizeof(T_Palette)); - - need_to_remap=1; - break; - - case 23 : // Saisie du nombre de couleurs pour la réduction de palette - Num2str(reduce_colors_number,str,3); - - if (Readline(265,41,str,3,1)) - { - temp_color=atoi(str); - // Correction de la valeur lue - if ( (temp_color>256) || (temp_color<2) ) - { - if (temp_color>256) - temp_color=256; - else - temp_color=2; - - Num2str(temp_color,str,3); - Window_input_content(Window_special_button_list,str); - } - - reduce_colors_number=temp_color; - } - Display_cursor(); - break; - - case 24 : // HSL <> RGB - - // Acte les changements en cours sur une ou plusieurs couleurs - memcpy(temp_palette,working_palette,sizeof(T_Palette)); - memcpy(backup_palette ,working_palette,sizeof(T_Palette)); - - Palette_view_is_RGB = !Palette_view_is_RGB; - - if(! Palette_view_is_RGB) - { - // On passe en HSL - Print_in_window(184,71,"H",MC_Dark,MC_Light); - Print_in_window(211,71,"S",MC_Dark,MC_Light); - Print_in_window(238,71,"L",MC_Dark,MC_Light); - Componant_unit(256); - - // Display the + and - button as disabled - Window_draw_normal_bouton(266, 74,12,11,"+",0,0); - Window_draw_normal_bouton(266,165,12,11,"-",0,0); - } - else - { - // On passe en RGB - Print_in_window(184,71,"R",MC_Dark,MC_Light); - Print_in_window(211,71,"G",MC_Dark,MC_Light); - Print_in_window(238,71,"B",MC_Dark,MC_Light); - Componant_unit(RGB_scale); - - // Display the + and - button as enabled - Window_draw_normal_bouton(266, 74,12,11,"+",0,1); - Window_draw_normal_bouton(266,165,12,11,"-",0,1); - } - Display_sliders(red_slider,green_slider,blue_slider,(block_start!=block_end),working_palette); - Update_window_area(265,73,14,103); - break; - - case 25 : // Sort palette - { - byte h = 0, l = 0, s=0; - byte oh=0,ol=0,os=0; // Valeur pour la couleur précédente - int swap=1; - byte remap_table[256]; - byte inverted_table[256]; - byte begin, end; - - if(block_start==block_end) - { - begin = 0; - end = 255; - } - else - { - begin = block_start; - end = block_end; - } - - // Init remap table - for (i=0;i<256;i++) - remap_table[i]=i; - // Make a backup because remapping is an undoable modification - if (!image_is_backed_up) - { - Backup(); - image_is_backed_up=1; - } - - if(Window_attribute1==LEFT_SIDE) - // Laft click on button: Sort by Hue (H) and Lightness (L) - while(swap==1) - { - swap=0; - h=0;l=255;s=0; - for(temp_color=begin;temp_color<=end;temp_color++) - { - oh=h; ol=l; os=s; - RGB_to_HSL(working_palette[temp_color].R, - working_palette[temp_color].G, - working_palette[temp_color].B,&h,&s,&l); - - if( - ((s==0) && (os>0)) // A grey is before a saturated color - || ((s>0 && os > 0) && (hol))) // 2 saturated colors: sort by H, then by L - || ((os==0 && s==0) && l>ol)) // Two greys: sort by L only - { - // Swap color with the previous one - byte swap_color; - Swap(0,temp_color,temp_color-1,1,working_palette,color_usage); - - swap_color=remap_table[temp_color]; - remap_table[temp_color]=remap_table[temp_color-1]; - remap_table[temp_color-1]=swap_color; - - swap=1; - } - } - } - - else // Right click > Sort only on L - while(swap==1) - { - swap=0; - l=255; - for(temp_color=begin;temp_color<=end;temp_color++) - { - ol=l; - RGB_to_HSL(working_palette[temp_color].R, - working_palette[temp_color].G, - working_palette[temp_color].B,&h,&s,&l); - - if(l>ol) - { - // Swap color with the previous one - byte swap_color; - Swap(0,temp_color,temp_color-1,1,working_palette,color_usage); - - swap_color=remap_table[temp_color]; - remap_table[temp_color]=remap_table[temp_color-1]; - remap_table[temp_color-1]=swap_color; - - swap=1; - } - } - } - - for (i=0;i<256;i++) - inverted_table[remap_table[i]]=i; - Remap_image_highlevel(inverted_table); - // Maintenant, tous ces calculs doivent êtres pris en compte dans la - // palette, l'image et à l'écran. - Set_palette(working_palette); - need_to_remap=1; - } - break; - } - - - if (!Mouse_K) - { - switch (Key) - { - case SDLK_LEFTBRACKET : // Décaler Forecolor vers la gauche - if (block_start==block_end) - { - Fore_color--; - first_color--; - last_color--; - block_start--; - block_end--; - Draw_all_palette_sliders(red_slider,green_slider,blue_slider,working_palette,block_start,block_end); - Hide_cursor(); - Tag_color_range(block_start,block_end); - // Affichage du n° de la couleur sélectionnée - Num2str(Fore_color,str,3); - Print_in_window(237,58,str,MC_Black,MC_Light); - // Affichage dans le block de visu de la couleur en cours - Block(Window_pos_X+(Menu_factor_X*264),Window_pos_Y+(Menu_factor_Y*93),Menu_factor_X<<4,Menu_factor_Y*64,Fore_color); - Update_rect(Window_pos_X+(Menu_factor_X*264),Window_pos_Y+(Menu_factor_Y*93),Menu_factor_X<<4,Menu_factor_Y*64); - Display_cursor(); - } - Key=0; - break; - - case SDLK_RIGHTBRACKET : // Décaler Forecolor vers la droite - if (block_start==block_end) - { - Fore_color++; - first_color++; - last_color++; - block_start++; - block_end++; - Draw_all_palette_sliders(red_slider,green_slider,blue_slider,working_palette,block_start,block_end); - Hide_cursor(); - Tag_color_range(block_start,block_end); - // Affichage du n° de la couleur sélectionnée - Num2str(Fore_color,str,3); - Print_in_window(237,58,str,MC_Black,MC_Light); - // Affichage dans le block de visu de la couleur en cours - Block(Window_pos_X+(Menu_factor_X*264),Window_pos_Y+(Menu_factor_Y*93),Menu_factor_X<<4,Menu_factor_Y*64,Fore_color); - Update_rect(Window_pos_X+(Menu_factor_X*264),Window_pos_Y+(Menu_factor_Y*93),Menu_factor_X<<4,Menu_factor_Y*64); - Display_cursor(); - } - Key=0; - break; - - case (SDLK_LEFTBRACKET|MOD_SHIFT) : // Decaler Backcolor vers la gauche - Back_color--; - case (SDLK_RIGHTBRACKET|MOD_SHIFT) : // Decaler Backcolor vers la droite - // attention: pas de break ci-dessus - if (Key==(SDLK_RIGHTBRACKET|MOD_SHIFT)) - Back_color++; - Hide_cursor(); - Block(Window_pos_X+(Menu_factor_X*260),Window_pos_Y+(Menu_factor_Y* 89),Menu_factor_X*24,Menu_factor_Y<<2,Back_color); - Block(Window_pos_X+(Menu_factor_X*260),Window_pos_Y+(Menu_factor_Y*157),Menu_factor_X*24,Menu_factor_Y<<2,Back_color); - Block(Window_pos_X+(Menu_factor_X*260),Window_pos_Y+(Menu_factor_Y* 93),Menu_factor_X<<2,Menu_factor_Y<<6,Back_color); - Block(Window_pos_X+(Menu_factor_X*280),Window_pos_Y+(Menu_factor_Y* 93),Menu_factor_X<<2,Menu_factor_Y<<6,Back_color); - Update_rect(Window_pos_X+(Menu_factor_X*260),Window_pos_Y+(Menu_factor_Y* 89),Menu_factor_X*32,Menu_factor_Y*72); - Display_cursor(); - Key=0; - break; - - case SDLK_BACKSPACE : // Remise des couleurs du menu à l'état normal en essayant - // de ne pas trop modifier l'image. - if (!image_is_backed_up) - { - Backup(); - image_is_backed_up=1; - } - if (used_colors==-1) - Update_color_count(&used_colors,color_usage); - - memcpy(backup_palette,working_palette,sizeof(T_Palette)); - memcpy(temp_palette,Main_palette,sizeof(T_Palette)); - memcpy(Main_palette,working_palette,sizeof(T_Palette)); - Set_nice_menu_colors(color_usage,0); - memcpy(working_palette,Main_palette,sizeof(T_Palette)); - memcpy(Main_palette,temp_palette,sizeof(T_Palette)); - Set_palette(working_palette); - memcpy(temp_palette,working_palette,sizeof(T_Palette)); - Draw_all_palette_sliders(red_slider,green_slider,blue_slider,working_palette,block_start,block_end); - Update_color_count(&used_colors,color_usage); - need_to_remap=1; - Key=0; - break; - - case SDLK_BACKQUOTE : // Récupération d'une couleur derrière le menu - case SDLK_COMMA : - Get_color_behind_window(&color,&click); - if (click) - { - Hide_cursor(); - if (click==RIGHT_SIDE) - { - if (Back_color!=color) - { - Back_color=color; - // 4 blocks de back_color entourant la fore_color - Block(Window_pos_X+(Menu_factor_X*260),Window_pos_Y+(Menu_factor_Y* 89),Menu_factor_X*24,Menu_factor_Y<<2,Back_color); - Block(Window_pos_X+(Menu_factor_X*260),Window_pos_Y+(Menu_factor_Y*157),Menu_factor_X*24,Menu_factor_Y<<2,Back_color); - Block(Window_pos_X+(Menu_factor_X*260),Window_pos_Y+(Menu_factor_Y* 93),Menu_factor_X<<2,Menu_factor_Y<<6,Back_color); - Block(Window_pos_X+(Menu_factor_X*280),Window_pos_Y+(Menu_factor_Y* 93),Menu_factor_X<<2,Menu_factor_Y<<6,Back_color); - Update_rect(Window_pos_X+(Menu_factor_X*260),Window_pos_Y+(Menu_factor_Y* 89),Menu_factor_X*32,Menu_factor_Y*72); - } - } - else - { - Fore_color=first_color=last_color=block_start=block_end=color; - Tag_color_range(block_start,block_end); - - // Affichage du n° de la couleur sélectionnée - Block(Window_pos_X+(Menu_factor_X*261),Window_pos_Y+(Menu_factor_Y*58),Menu_factor_X*32,Menu_factor_Y*7,MC_Light); - Num2str(Fore_color,str,3); - Print_in_window(237,58,str,MC_Black,MC_Light); - - // Affichage des jauges - Display_sliders(red_slider,green_slider,blue_slider,0,working_palette); - - // Affichage dans le block de visu de la couleur en cours - Block(Window_pos_X+(Menu_factor_X*264),Window_pos_Y+(Menu_factor_Y*93),Menu_factor_X<<4,Menu_factor_Y*64,Fore_color); - Update_rect(Window_pos_X+(Menu_factor_X*264),Window_pos_Y+(Menu_factor_Y*93),Menu_factor_X<<4,Menu_factor_Y*64); - - memcpy(backup_palette ,working_palette,sizeof(T_Palette)); - memcpy(temp_palette,working_palette,sizeof(T_Palette)); - } - Display_cursor(); - Wait_end_of_click(); - } - Key=0; - break; - default: - if (Is_shortcut(Key,0x100+BUTTON_HELP)) - { - Key=0; - Window_help(BUTTON_PALETTE, NULL); - break; - } - } - - if (need_to_remap) - { - Hide_cursor(); - Compute_optimal_menu_colors(working_palette); - - // On remappe brutalement - Remap_screen_after_menu_colors_change(); - // Puis on remet les trucs qui ne devaient pas changer - Window_draw_palette_bouton(5,79); - Block(Window_pos_X+(Menu_factor_X*260),Window_pos_Y+(Menu_factor_Y*89),Menu_factor_X*24,Menu_factor_Y*72,Back_color); - Display_grad_block_in_window(264,93,block_start,block_end); - - Update_rect(Window_pos_X+8*Menu_factor_X,Window_pos_Y+82*Menu_factor_Y,Menu_factor_X*16*10,Menu_factor_Y*5*16); - - Display_cursor(); - need_to_remap=0; - } - } - } - while ((clicked_button!=13) && (clicked_button!=14)); - - if (clicked_button==14) // Sortie par OK - { - if ( (!image_is_backed_up) - && memcmp(Main_palette,working_palette,sizeof(T_Palette)) ) - Backup(); - memcpy(Main_palette,working_palette,sizeof(T_Palette)); - } - - Compute_optimal_menu_colors(Main_palette); - - // La variable employée ici n'a pas vraiment de rapport avec son nom... - need_to_remap=(Window_pos_Y+(Window_height*Menu_factor_Y)Position = rgb_scale_slider->Position>128?rgb_scale_slider->Position*2-256:0; - Num2str(256-rgb_scale_slider->Position,str,3); - Print_in_window(157,78,str,MC_Black,MC_Light); - Window_draw_slider(rgb_scale_slider); - break; - - case 10: - // /2 RGB scale - rgb_scale_slider->Position = rgb_scale_slider->Position>253?254:(rgb_scale_slider->Position)/2+128; - Num2str(256-rgb_scale_slider->Position,str,3); - Print_in_window(157,78,str,MC_Black,MC_Light); - Window_draw_slider(rgb_scale_slider); - } - } - while (clicked_button!=1 && clicked_button!=2 && clicked_button!=3 && clicked_button!=4); - - // We need to get the sliders positions before closing the window, because they will be freed. - palette_cols=256-columns_slider->Position; - palette_lines=16-lines_slider->Position; - rgb_scale=256-rgb_scale_slider->Position; - - Close_window(); - Unselect_button(BUTTON_PALETTE); - Display_cursor(); - - if (clicked_button==4) // Cancel - return; - - if (palette_vertical != Config.Palette_vertical) - { - Config.Palette_vertical=palette_vertical; - palette_needs_redraw=1; - } - if (palette_cols!=Config.Palette_cells_X || - palette_lines!=Config.Palette_cells_Y) - { - Config.Palette_cells_X = palette_cols; - Config.Palette_cells_Y = palette_lines; - palette_needs_redraw=1; - } - if (rgb_scale!=RGB_scale) - { - Set_palette_RGB_scale(rgb_scale); - Set_palette(Main_palette); - } - - if (clicked_button==1) - { - Menu_tag_colors("Tag colors to exclude",Exclude_color,&dummy,1, NULL); - } - else if (clicked_button==2) - { - // Open the menu with Shade settings. Same as the shortcut, except - // that this will not activate shade mode on exit. - Shade_settings_menu(); - } - - if (palette_needs_redraw) - { - Change_palette_cells(); - Display_menu(); - Display_sprite_in_menu(BUTTON_PAL_LEFT,18+(Config.Palette_vertical!=0)); - } -} +/* Grafx2 - The Ultimate 256-color bitmap paint program + + Copyright 2007 Adrien Destugues + Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) + + Grafx2 is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 + of the License. + + Grafx2 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grafx2; if not, see +*/ +#include +#include +#include +#include "const.h" +#include "struct.h" +#include "global.h" +#include "misc.h" +#include "engine.h" +#include "readline.h" +#include "buttons.h" +#include "pages.h" +#include "help.h" +#include "sdlscreen.h" +#include "errors.h" +#include "op_c.h" +#include "windows.h" +#include "input.h" +#include "palette.h" +#include "shade.h" + +byte Palette_view_is_RGB = 1; // Indique si on est en HSL ou en RGB + +// --------------------------- Menu des palettes ----------------------------- +char * Palette_reduce_label[7]= +{ + "128"," 64"," 32"," 16"," 8"," 4"," 2" +}; + +// Nombre de graduations pour une composante RGB +int RGB_scale = 256; // 24bit +//int RGB_scale = 64; // VGA +//int RGB_scale = 16; // Amiga +//int RGB_scale = 4; // MSX2 +//int RGB_scale = 3; // Amstrad CPC + +// Nombre de graduations pour une composante dans le mode actuel +int Color_count=256; +// Les composantes vont de 0 à (Color_count-1) +int Color_max=255; +// Le demi-pas est une quantité que l'on ajoute à une composante +// avant de faire un arrondi par division. +int Color_halfstep=0; + + +void Set_palette_RGB_scale(int scale) +{ + if (scale>= 2 && scale <= 256) + RGB_scale = scale; +} + +byte Round_palette_component(byte comp) +{ + return ((comp+128/RGB_scale)*(RGB_scale-1)/255*255+(RGB_scale&1?1:0))/(RGB_scale-1); +} + +// Définir les unités pour les graduations R G B ou H S V +void Componant_unit(int count) +{ + Color_count = count; + Color_max = count-1; + Color_halfstep = 256/count/2; +} + +void Set_HSL(T_Palette start_palette, T_Palette end_palette, byte color, short diff_h, short diff_s, short diff_l) +{ + byte h, s, l; + RGB_to_HSL(start_palette[color].R,start_palette[color].G,start_palette[color].B,&h,&s,&l); + // La teinte (Hue) est cyclique + h=(diff_h+256+h); + // Pour les autres (Saturation, Lightness), au lieu d'additionner, + // on va faire un ratio, cela utilise mieux la plage de valeurs 0-255 + if (diff_s<0) + s=(255+diff_s)*s/255; + else if (diff_s>0) + s=255-(255-diff_s)*(255-s)/255; + if (diff_l<0) + l=(255+diff_l)*l/255; + else if (diff_l>0) + l=255-(255-diff_l)*(255-l)/255; + HSL_to_RGB(h,s,l,&end_palette[color].R,&end_palette[color].G,&end_palette[color].B); +} + +void Set_red(byte color, short new_color, T_Palette palette) +{ + if (new_color< 0) + new_color= 0; + if (new_color>255) + new_color=255; + // Arrondi + new_color=Round_palette_component(new_color); + + palette[color].R=new_color; + Set_color(color,palette[color].R,palette[color].G,palette[color].B); +} + + +void Set_green(byte color, short new_color, T_Palette palette) +{ + if (new_color< 0) + new_color= 0; + if (new_color>255) + new_color=255; + // Arrondi + new_color=Round_palette_component(new_color); + + palette[color].G=new_color; + Set_color(color,palette[color].R,palette[color].G,palette[color].B); +} + + +void Set_blue(byte color, short new_color, T_Palette palette) +{ + if (new_color< 0) + new_color= 0; + if (new_color>255) + new_color=255; + // Arrondi + new_color=Round_palette_component(new_color); + + palette[color].B=new_color; + Set_color(color,palette[color].R,palette[color].G,palette[color].B); +} + +void Format_componant(byte value, char *str) +// Formate une chaine de 4 caractères+\0 : "nnn " +{ + Num2str(value,str,3); + str[3]=' '; + str[4]='\0'; +} + +void Spread_colors(short start,short end,T_Palette palette) +// Modifie la palette pour obtenir un dégradé de couleur entre les deux bornes +// passées en paramètre +{ + short start_red; + short start_green; + short start_blue; + short end_red; + short end_green; + short end_blue; + short index; + + // On vérifie qu'il y ait assez de couleurs entre le début et la fin pour + // pouvoir faire un dégradé: + if ( (start!=end) && (start+1!=end) ) + { + start_red=palette[start].R; + start_green =palette[start].G; + start_blue =palette[start].B; + + end_red =palette[end ].R; + end_green =palette[end ].G; + end_blue =palette[end ].B; + + for (index=start+1;index=Window_pos_Y) && (y_pos=Window_pos_X) && (x_pos=Menu_Y_before_window) + end_y=Menu_Y_before_window; + else + end_y=Main_image_height; + + if (!Main_magnifier_mode) + { + if (Main_image_width>=Screen_width) + end_x=Screen_width; + else + end_x=Main_image_width; + + } + else + { + if (Main_image_width>=Main_separator_position) + end_x=Main_separator_position; + else + end_x=Main_image_width; + + if ((Main_X_zoom+(Main_image_width*Main_magnifier_factor))>=Screen_width) + end_x_mag=Screen_width; + else + end_x_mag=(Main_X_zoom+(Main_image_width*Main_magnifier_factor)); + + if (Main_image_height*Main_magnifier_factor>=Menu_Y_before_window) + end_y_mag=Menu_Y_before_window; + else + end_y_mag=Main_image_height*Main_magnifier_factor; + } + + // On doit maintenant faire la traduction à l'écran + Remap_zone_highlevel(0,0,end_x,end_y,conversion_table); + + if (Main_magnifier_mode) + { + Remap_zone_highlevel(Main_separator_position,0,end_x_mag,end_y_mag,conversion_table); + // Il peut encore rester le bas de la barre de split à remapper si la + // partie zoomée ne descend pas jusqu'en bas... + Remap_zone_highlevel(Main_separator_position,end_y_mag, + (Main_separator_position+(SEPARATOR_WIDTH*Menu_factor_X)), + Menu_Y_before_window,conversion_table); + } + // Remappe tous les fonds de fenetre (qui doivent contenir un bout d'écran) + Remap_window_backgrounds(conversion_table, 0, Menu_Y_before_window); +} + + +void Swap(int with_remap,short block_1_start,short block_2_start,short block_size,T_Palette palette, dword * color_usage) +{ + short pos_1; + short pos_2; + short end_1; + short end_2; + dword temp; + byte conversion_table[256]; + + T_Components temp_palette[256]; + dword Utilisation_temporaire[256]; + + // On fait une copie de la palette + memcpy(temp_palette, palette, sizeof(T_Palette)); + + // On fait une copie de la table d'utilisation des couleurs + memcpy(Utilisation_temporaire, color_usage, sizeof(dword) * 256); + + // On commence à initialiser la table de conversion à un état où elle ne + // fera aucune conversion. + for (pos_1=0;pos_1<=255;pos_1++) + conversion_table[pos_1]=pos_1; + + // On calcul les dernières couleurs de chaque bloc. + end_1=block_1_start+block_size-1; + end_2=block_2_start+block_size-1; + + if ((block_2_start>=block_1_start) && (block_2_start<=end_1)) + { + // Le bloc destination commence dans le bloc source. + + for (pos_1=block_1_start,pos_2=end_1+1;pos_1<=end_2;pos_1++) + { + // Il faut transformer la couleur pos_1 en pos_2: + + conversion_table[pos_2]=pos_1; + color_usage[pos_1]=Utilisation_temporaire[pos_2]; + palette[pos_1].R=temp_palette[pos_2].R; + palette[pos_1].G=temp_palette[pos_2].G; + palette[pos_1].B=temp_palette[pos_2].B; + + // On gère la mise à jour de pos_2 + if (pos_2==end_2) + pos_2=block_1_start; + else + pos_2++; + } + } + else + if ((block_2_start=block_1_start)) + { + // Le bloc destination déborde dans le bloc source. + + for (pos_1=block_2_start,pos_2=block_1_start;pos_1<=end_1;pos_1++) + { + // Il faut transformer la couleur pos_1 en pos_2: + + conversion_table[pos_2]=pos_1; + color_usage[pos_1]=Utilisation_temporaire[pos_2]; + palette[pos_1].R=temp_palette[pos_2].R; + palette[pos_1].G=temp_palette[pos_2].G; + palette[pos_1].B=temp_palette[pos_2].B; + + // On gère la mise à jour de pos_2 + if (pos_2==end_1) + pos_2=block_2_start; + else + pos_2++; + } + } + else + { + // Le bloc source et le bloc destination sont distincts. + + for (pos_1=block_1_start,pos_2=block_2_start;pos_1<=end_1;pos_1++,pos_2++) + { + // Il va falloir permutter la couleur pos_1 avec la couleur pos_2 + conversion_table[pos_1]=pos_2; + conversion_table[pos_2]=pos_1; + + // On intervertit le nombre d'utilisation des couleurs pour garder une + // cohérence lors d'un éventuel "Zap unused". + temp =color_usage[pos_1]; + color_usage[pos_1]=color_usage[pos_2]; + color_usage[pos_2]=temp; + + // On fait un changement de teinte: + temp =palette[pos_1].R; + palette[pos_1].R=palette[pos_2].R; + palette[pos_2].R=temp; + + temp =palette[pos_1].G; + palette[pos_1].G=palette[pos_2].G; + palette[pos_2].G=temp; + + temp =palette[pos_1].B; + palette[pos_1].B=palette[pos_2].B; + palette[pos_2].B=temp; + } + } + + if (with_remap) + { + Remap_image_highlevel(conversion_table); + } +} + + + +void Set_nice_menu_colors(dword * color_usage,int not_picture) +{ + short index,index2; + byte color; + byte replace_table[256]; + T_Components rgb[4]; + short new_colors[4]={255,254,253,252}; + + // On initialise la table de remplacement + for (index=0; index<256; index++) + replace_table[index]=index; + + // On recherche les 4 couleurs les moins utilisées dans l'image pour pouvoir + // les remplacer par les nouvelles couleurs. + for (index2=0; index2<4; index2++) + for (index=255; index>=0; index--) + { + if ((index!=new_colors[0]) && (index!=new_colors[1]) + && (index!=new_colors[2]) && (index!=new_colors[3]) + && (color_usage[index]new_colors[index+1]) + { + index2 =new_colors[index]; + new_colors[index] =new_colors[index+1]; + new_colors[index+1]=index2; + color=1; + } + } + } while (color); + + // On sauvegarde dans rgb les teintes qu'on va remplacer et on met les + // couleurs du menu par défaut + for (index=0; index<4; index++) + { + color=new_colors[index]; + rgb[index].R=Main_palette[color].R; + rgb[index].G=Main_palette[color].G; + rgb[index].B=Main_palette[color].B; + Main_palette[color].R=Fav_menu_colors[index].R; + Main_palette[color].G=Fav_menu_colors[index].G; + Main_palette[color].B=Fav_menu_colors[index].B; + } + + // Maintenant qu'on a placé notre nouvelle palette, on va chercher quelles + // sont les couleurs qui peuvent remplacer les anciennes + Hide_cursor(); + for (index=0; index<4; index++) + replace_table[new_colors[index]]=Best_color_nonexcluded + (rgb[index].R,rgb[index].G,rgb[index].B); + + if (not_picture) + { + // Remap caused by preview. Only remap screen + Remap_zone_highlevel(0,0,Screen_width,Screen_height,replace_table); + } + else + { + // On fait un changement des couleurs visibles à l'écran et dans l'image + Remap_image_highlevel(replace_table); + } + Display_cursor(); +} + + + +void Reduce_palette(short * used_colors,int nb_colors_asked,T_Palette palette,dword * color_usage) +{ + char str[5]; // buffer d'affichage du compteur + byte conversion_table[256]; // Table de conversion + int color_1; // |_ Variables de balayages + int color_2; // | de la palette + int best_color_1=0; + int best_color_2=0; + int difference; + int best_difference; + dword Utilisation; + dword Meilleure_utilisation; + + // On commence par initialiser la table de conversion dans un état où + // aucune conversion ne sera effectuée. + for (color_1=0; color_1<=255; color_1++) + conversion_table[color_1]=color_1; + + // Si on ne connait pas encore le nombre de couleurs utilisées, on le + // calcule! (!!! La fonction appelée Efface puis Affiche le curseur !!!) + if ((*used_colors)<0) + Update_color_count(used_colors,color_usage); + + Hide_cursor(); + + // On tasse la palette vers le début parce qu'elle doit ressembler à + // du Gruyère (et comme Papouille il aime pas le fromage...) + + // Pour cela, on va scruter la couleur color_1 et se servir de l'indice + // color_2 comme position de destination. + for (color_1=color_2=0;color_1<=255;color_1++) + { + if (color_usage[color_1]) + { + // On commence par s'occuper des teintes de la palette + palette[color_2].R=palette[color_1].R; + palette[color_2].G=palette[color_1].G; + palette[color_2].B=palette[color_1].B; + + // Ensuite, on met à jour le tableau d'occupation des couleurs. + color_usage[color_2]=color_usage[color_1]; + + // On va maintenant s'occuper de la table de conversion: + conversion_table[color_1]=color_2; + + // Maintenant, la place désignée par color_2 est occupée, alors on + // doit passer à un indice de destination suivant. + color_2++; + } + } + + // On met toutes les couleurs inutilisées en noir + for (;color_2<256;color_2++) + { + palette[color_2].R=0; + palette[color_2].G=0; + palette[color_2].B=0; + color_usage[color_2]=0; + } + + // Maintenant qu'on a une palette clean, on va boucler en réduisant + // le nombre de couleurs jusqu'à ce qu'on atteigne le nombre désiré. + while ((*used_colors)>nb_colors_asked) + { + // Il s'agit de trouver les 2 couleurs qui se ressemblent le plus + // parmis celles qui sont utilisées (bien sûr) et de les remplacer par + // une seule couleur qui est la moyenne pondérée de ces 2 couleurs + // en fonction de leur utilisation dans l'image. + + best_difference =0x7FFF; + Meilleure_utilisation=0x7FFFFFFF; + + for (color_1=0;color_1<(*used_colors);color_1++) + for (color_2=color_1+1;color_2<(*used_colors);color_2++) + if (color_1!=color_2) + { + difference =abs((short)palette[color_1].R-palette[color_2].R)+ + abs((short)palette[color_1].G-palette[color_2].G)+ + abs((short)palette[color_1].B-palette[color_2].B); + + if (difference<=best_difference) + { + Utilisation=color_usage[color_1]+color_usage[color_2]; + if ((differencebest_color_2) + { + // La color_1 va scroller en arrière. + + // Donc on transfère son utilisation dans l'utilisation de la + // couleur qui la précède. + color_usage[color_1-1]=color_usage[color_1]; + + // Et on transfère ses teintes dans les teintes de la couleur qui + // la précède. + palette[color_1-1].R=palette[color_1].R; + palette[color_1-1].G=palette[color_1].G; + palette[color_1-1].B=palette[color_1].B; + } + + // Une fois la palette et la table d'utilisation gérées, on peut + // s'occuper de notre table de conversion. + if (conversion_table[color_1]>best_color_2) + // La color_1 avait l'intention de se faire remplacer par une + // couleur que l'on va (ou que l'on a déjà) bouger en arrière. + conversion_table[color_1]--; + } + + // On vient d'éjecter une couleur, donc on peut mettre à jour le nombre + // de couleurs utilisées. + (*used_colors)--; + + // A la fin, on doit passer (dans la palette) les teintes du dernier + // élément de notre ensemble en noir. + palette[*used_colors].R=0; + palette[*used_colors].G=0; + palette[*used_colors].B=0; + + // Au passage, on va s'assurer que l'on a pas oublié de la mettre à une + // utilisation nulle. + color_usage[*used_colors]=0; + + // Après avoir éjecté une couleur, on le fait savoir à l'utilisateur par + // l'intermédiaire du compteur de nombre utilisées. + Num2str(*used_colors,str,3); + Print_in_window(186,23,str,MC_Black,MC_Light); + } + + // Maintenant, tous ces calculs doivent êtres pris en compte dans la + // palette, l'image et à l'écran. + Remap_image_highlevel(conversion_table); // Et voila pour l'image et l'écran + Display_cursor(); +} + + + +void Set_palette_slider(T_Scroller_button * slider, + word nb_elements, word position, + char * value, short x_pos) +{ + slider->Nb_elements=nb_elements; + slider->Position=position; + Compute_slider_cursor_height(slider); + Window_draw_slider(slider); + Print_counter(x_pos,172,value,MC_Black,MC_Light); +} + + + +void Display_sliders(T_Scroller_button * red_slider, + T_Scroller_button * green_slider, + T_Scroller_button * blue_slider, + byte block_is_selected, T_Components * palette) +{ + char str[5]; + + if (block_is_selected) + { + Set_palette_slider(red_slider,Color_max*2+1,Color_max,"± 0",176); + Set_palette_slider(green_slider,Color_max*2+1,Color_max,"± 0",203); + Set_palette_slider(blue_slider,Color_max*2+1,Color_max,"± 0",230); + } + else + { + byte j1, j2, j3; + j1= palette[Fore_color].R; + j2= palette[Fore_color].G; + j3= palette[Fore_color].B; + if (!Palette_view_is_RGB) + { + RGB_to_HSL(j1,j2,j3,&j1,&j2,&j3); + } + + Format_componant(j1*Color_max/255,str); + Set_palette_slider(red_slider,Color_count,Color_max-j1*Color_max/255,str,176); + Format_componant(j2*Color_max/255,str); + Set_palette_slider(green_slider,Color_count,Color_max-j2*Color_max/255,str,203); + Format_componant(j3*Color_max/255,str); + Set_palette_slider(blue_slider,Color_count,Color_max-j3*Color_max/255,str,230); + } +} + + + +void Draw_all_palette_sliders(T_Scroller_button * red_slider, + T_Scroller_button * green_slider, + T_Scroller_button * blue_slider, + T_Palette palette,byte start,byte end) +{ + char str[5]; + + Hide_cursor(); + // Réaffichage des jauges: + if (start!=end) + { + // Dans le cas d'un bloc, tout à 0. + red_slider->Position =Color_max; + Window_draw_slider(red_slider); + Print_counter(176,172,"± 0",MC_Black,MC_Light); + + green_slider->Position =Color_max; + Window_draw_slider(green_slider); + Print_counter(203,172,"± 0",MC_Black,MC_Light); + + blue_slider->Position =Color_max; + Window_draw_slider(blue_slider); + Print_counter(230,172,"± 0",MC_Black,MC_Light); + } + else + { + // Dans le cas d'une seule couleur, composantes. + byte j1, j2, j3; + j1= palette[start].R; + j2= palette[start].G; + j3= palette[start].B; + if (!Palette_view_is_RGB) + { + RGB_to_HSL(j1,j2,j3,&j1,&j2,&j3); + } + Format_componant(j1*Color_max/255,str); + red_slider->Position=Color_max-j1*Color_max/255; + Window_draw_slider(red_slider); + Print_counter(176,172,str,MC_Black,MC_Light); + + Format_componant(j2*Color_max/255,str); + green_slider->Position=Color_max-j2*Color_max/255; + Window_draw_slider(green_slider); + Print_counter(203,172,str,MC_Black,MC_Light); + + Format_componant(j3*Color_max/255,str); + blue_slider->Position=Color_max-j3*Color_max/255; + Window_draw_slider(blue_slider); + Print_counter(230,172,str,MC_Black,MC_Light); + } + Display_cursor(); +} + + +void Button_Palette(void) +{ + static short reducer_index=0; + static short reduce_colors_number=256; + short temp_color; // Variable pouvant reservir pour différents calculs intermédiaires + dword temp; + byte color,click; // Variables pouvant reservir pour différents calculs intermédiaires + short clicked_button; + word old_mouse_x; + word old_mouse_y; + byte old_mouse_k; + byte block_start; + byte block_end; + byte first_color; + byte last_color; + char str[10]; + word i; + //short x_pos,y_pos; + T_Normal_button * button_used; + T_Scroller_button * red_slider; + T_Scroller_button * green_slider; + T_Scroller_button * blue_slider; + T_Scroller_button * reduce_slider; + byte image_is_backed_up=0; + byte need_to_remap=0; + + dword color_usage[256]; + short used_colors=-1; // -1 <=> Inconnu + byte conversion_table[256]; + + T_Components * backup_palette; + T_Components * temp_palette; + T_Components * working_palette; + + backup_palette =(T_Components *)malloc(sizeof(T_Palette)); + temp_palette=(T_Components *)malloc(sizeof(T_Palette)); + working_palette=(T_Components *)malloc(sizeof(T_Palette)); + + Componant_unit(RGB_scale); + + Open_window(299,188,"Palette"); + + memcpy(working_palette,Main_palette,sizeof(T_Palette)); + memcpy(backup_palette ,Main_palette,sizeof(T_Palette)); + memcpy(temp_palette,Main_palette,sizeof(T_Palette)); + + Window_set_palette_button(5,79); // 1 + + Window_display_frame (173, 67,121,116); + Window_display_frame (128, 16, 91, 39); + Window_display_frame (221, 16, 73, 39); + // Frame creux destiné à l'affichage de la(les) couleur(s) sélectionnée(s) + Window_display_frame_in(259, 88, 26, 74); + + // Graduation des jauges de couleur + Block(Window_pos_X+(Menu_factor_X*179),Window_pos_Y+(Menu_factor_Y*109),Menu_factor_X*17,Menu_factor_Y,MC_Dark); + Block(Window_pos_X+(Menu_factor_X*206),Window_pos_Y+(Menu_factor_Y*109),Menu_factor_X*17,Menu_factor_Y,MC_Dark); + Block(Window_pos_X+(Menu_factor_X*233),Window_pos_Y+(Menu_factor_Y*109),Menu_factor_X*17,Menu_factor_Y,MC_Dark); + Block(Window_pos_X+(Menu_factor_X*179),Window_pos_Y+(Menu_factor_Y*125),Menu_factor_X*17,Menu_factor_Y,MC_Dark); + Block(Window_pos_X+(Menu_factor_X*206),Window_pos_Y+(Menu_factor_Y*125),Menu_factor_X*17,Menu_factor_Y,MC_Dark); + Block(Window_pos_X+(Menu_factor_X*233),Window_pos_Y+(Menu_factor_Y*125),Menu_factor_X*17,Menu_factor_Y,MC_Dark); + Block(Window_pos_X+(Menu_factor_X*179),Window_pos_Y+(Menu_factor_Y*141),Menu_factor_X*17,Menu_factor_Y,MC_Dark); + Block(Window_pos_X+(Menu_factor_X*206),Window_pos_Y+(Menu_factor_Y*141),Menu_factor_X*17,Menu_factor_Y,MC_Dark); + Block(Window_pos_X+(Menu_factor_X*233),Window_pos_Y+(Menu_factor_Y*141),Menu_factor_X*17,Menu_factor_Y,MC_Dark); + // Jauges de couleur + red_slider = Window_set_scroller_button(182, 81, 88,Color_count,1,Color_max-working_palette[Fore_color].R*Color_max/255);// 2 + green_slider = Window_set_scroller_button(209, 81, 88,Color_count,1,Color_max-working_palette[Fore_color].G*Color_max/255);// 3 + blue_slider = Window_set_scroller_button(236, 81, 88,Color_count,1,Color_max-working_palette[Fore_color].B*Color_max/255);// 4 + + if(Palette_view_is_RGB==1) { + Print_in_window(184,71,"R",MC_Dark,MC_Light); + Print_in_window(211,71,"G",MC_Dark,MC_Light); + Print_in_window(238,71,"B",MC_Dark,MC_Light); + Componant_unit(RGB_scale); + } else { + Print_in_window(184,71,"H",MC_Dark,MC_Light); + Print_in_window(211,71,"S",MC_Dark,MC_Light); + Print_in_window(238,71,"L",MC_Dark,MC_Light); + Componant_unit(256); + } + + first_color=last_color=block_start=block_end=Fore_color; + Tag_color_range(block_start,block_end); + + // Affichage dans le block de visu de la couleur en cours + Block(Window_pos_X+(Menu_factor_X*260),Window_pos_Y+(Menu_factor_Y*89),Menu_factor_X*24,Menu_factor_Y*72,Back_color); + Block(Window_pos_X+(Menu_factor_X*264),Window_pos_Y+(Menu_factor_Y*93),Menu_factor_X<<4,Menu_factor_Y*64,Fore_color); + + // Affichage des valeurs de la couleur courante (pour 1 couleur) + Display_sliders(red_slider,green_slider,blue_slider,(block_start!=block_end),working_palette); + + Print_in_window(129,58,"Color number:",MC_Dark,MC_Light); + Num2str(Fore_color,str,3); + Print_in_window(237,58,str,MC_Black,MC_Light); + + + Window_set_normal_button( 6,17,59,14,"Default",3,1,SDLK_f); // 5 + Window_set_normal_button(66,17,29,14,"Gry" ,1,1,SDLK_g); // 6 + Window_set_normal_button(66,47,29,14,"Swp" ,0,1,KEY_NONE); // 7 + Window_set_normal_button( 6,47,59,14,"X-Swap" ,1,1,SDLK_x); // 8 + Window_set_normal_button(66,32,29,14,"Cpy" ,1,1,SDLK_c); // 9 + Window_set_normal_button( 6,32,59,14,"Spread" ,4,1,SDLK_e); // 10 + + Window_set_normal_button(239,20,51,14,"Reduce" ,1,1,SDLK_r); // 11 + Print_in_window(241,41,"to",MC_Dark,MC_Light); + + Window_set_normal_button( 6,168,35,14,"Undo" ,1,1,SDLK_u); // 12 + Window_set_normal_button( 62,168,51,14,"Cancel",0,1,KEY_ESC); // 13 + Window_set_normal_button(117,168,51,14,"OK" ,0,1,SDLK_RETURN); // 14 + + button_used = Window_set_normal_button(132,20,83,14,"Used: ???",4,1,SDLK_d);// 15 + Window_set_normal_button(132,37,83,14,"Zap unused",0,1,SDLK_DELETE);//16 + + // Jauge de réduction de palette + reduce_slider = Window_set_scroller_button(225,20,31,7,1,reducer_index);// 17 + + Window_set_repeatable_button(266, 74,12,11,"+",0,1,SDLK_KP_PLUS); // 18 + Window_set_repeatable_button(266,165,12,11,"-",0,1,SDLK_KP_MINUS); // 19 + + Window_set_normal_button(96,17,29,14,"Neg" ,1,1,SDLK_n); // 20 + Window_set_normal_button(66,62,29,14,"Inv" ,1,1,SDLK_i); // 21 + Window_set_normal_button( 6,62,59,14,"X-Inv." ,5,1,SDLK_v); // 22 + + Window_set_input_button(263,39,3); // 23 + + Window_set_normal_button(96,32,29,14,"HSL" ,1,1,SDLK_h); // 24 + Window_set_normal_button(96,47,29,14,"Srt" ,1,1,SDLK_s); // 25 + // Affichage du facteur de réduction de la palette + Num2str(reduce_colors_number,str,3); + Print_in_window(265,41,str,MC_Black,MC_Light); + + // Dessin des petits effets spéciaux pour les boutons [+] et [-] + Draw_thingumajig(263, 74,MC_White,-1); + Draw_thingumajig(280, 74,MC_White,+1); + Draw_thingumajig(263,165,MC_Dark,-1); + Draw_thingumajig(280,165,MC_Dark,+1); + + Update_window_area(0,0,299,188); + + Display_cursor(); + + if (Config.Auto_nb_used) + Update_color_count(&used_colors,color_usage); + + do + { + old_mouse_x=Mouse_X; + old_mouse_y=Mouse_Y; + old_mouse_k=Mouse_K; + clicked_button=Window_clicked_button(); + + switch (clicked_button) + { + case 0 : // Nulle part + break; + case -1 : // Hors de la fenêtre + case 1 : // palette + if ( (Mouse_X!=old_mouse_x) || (Mouse_Y!=old_mouse_y) || (Mouse_K!=old_mouse_k) ) + { + Hide_cursor(); + temp_color=(clicked_button==1) ? Window_attribute2 : Read_pixel(Mouse_X,Mouse_Y); + if (Mouse_K==RIGHT_SIDE) + { + if (Back_color!=temp_color) + { + Back_color=temp_color; + // 4 blocks de back_color entourant la fore_color + Block(Window_pos_X+(Menu_factor_X*260),Window_pos_Y+(Menu_factor_Y* 89),Menu_factor_X*24,Menu_factor_Y<<2,Back_color); + Block(Window_pos_X+(Menu_factor_X*260),Window_pos_Y+(Menu_factor_Y*157),Menu_factor_X*24,Menu_factor_Y<<2,Back_color); + Block(Window_pos_X+(Menu_factor_X*260),Window_pos_Y+(Menu_factor_Y* 93),Menu_factor_X<<2,Menu_factor_Y<<6,Back_color); + Block(Window_pos_X+(Menu_factor_X*280),Window_pos_Y+(Menu_factor_Y* 93),Menu_factor_X<<2,Menu_factor_Y<<6,Back_color); + Update_rect(Window_pos_X+(Menu_factor_X*260),Window_pos_Y+(Menu_factor_Y* 89),Menu_factor_X*32,Menu_factor_Y*72); + } + } + else + { + if (!old_mouse_k) + { + // On vient de clicker sur une couleur (et une seule) + if ( (Fore_color!=temp_color) || (block_start!=block_end) ) + { + // La couleur en question est nouvelle ou elle annule un + // ancien bloc. Il faut donc sélectionner cette couleur comme + // unique couleur choisie. + + Fore_color=first_color=last_color=block_start=block_end=temp_color; + Tag_color_range(block_start,block_end); + + // Affichage du n° de la couleur sélectionnée + Block(Window_pos_X+(Menu_factor_X*237),Window_pos_Y+(Menu_factor_Y*58),Menu_factor_X*56,Menu_factor_Y*7,MC_Light); + Num2str(Fore_color,str,3); + Print_in_window(237,58,str,MC_Black,MC_Light); + Update_rect(Window_pos_X+(Menu_factor_X*237),Window_pos_Y+(Menu_factor_Y*58),Menu_factor_X*56,Menu_factor_Y*7); + + // Affichage des jauges + Block(Window_pos_X+(Menu_factor_X*176),Window_pos_Y+(Menu_factor_Y*172),Menu_factor_X*84,Menu_factor_Y*7,MC_Light); + Display_sliders(red_slider,green_slider,blue_slider,0,working_palette); + + // Affichage dans le block de visu de la couleur en cours + Block(Window_pos_X+(Menu_factor_X*264),Window_pos_Y+(Menu_factor_Y*93),Menu_factor_X<<4,Menu_factor_Y*64,Fore_color); + Update_rect(Window_pos_X+(Menu_factor_X*264),Window_pos_Y+(Menu_factor_Y*93),Menu_factor_X<<4,Menu_factor_Y*64); + + memcpy(backup_palette ,working_palette,sizeof(T_Palette)); + memcpy(temp_palette,working_palette,sizeof(T_Palette)); + } + } + else + { + // On maintient le click, on va donc tester si le curseur bouge + if (temp_color!=last_color) + { + // On commence par ordonner la 1ère et dernière couleur du bloc + if (first_colortemp_color) + { + block_start=temp_color; + block_end=first_color; + + // Affichage du n° de la couleur sélectionnée + Num2str(block_start,str ,3); + Num2str(block_end ,str+4,3); + str[3]=26; // Flèche vers la droite + Print_in_window(237,58,str,MC_Black,MC_Light); + + // Affichage des jauges + Display_sliders(red_slider,green_slider,blue_slider,1,NULL); + + // Affichage dans le block de visu du bloc (dégradé) en cours + Display_grad_block_in_window(264,93,block_start,block_end); + } + else + { + block_start=block_end=first_color; + Block(Window_pos_X+(Menu_factor_X*176),Window_pos_Y+(Menu_factor_Y*172),Menu_factor_X*84,Menu_factor_Y*7,MC_Light); + + // Affichage du n° de la couleur sélectionnée + Block(Window_pos_X+(Menu_factor_X*261),Window_pos_Y+(Menu_factor_Y*58),Menu_factor_X*32,Menu_factor_Y*7,MC_Light); + Num2str(Fore_color,str,3); + Print_in_window(237,58,str,MC_Black,MC_Light); + + // Affichage des jauges + Display_sliders(red_slider,green_slider,blue_slider,0,working_palette); + + // Affichage dans le block de visu de la couleur en cours + Block(Window_pos_X+(Menu_factor_X*264),Window_pos_Y+(Menu_factor_Y*93),Menu_factor_X<<4,Menu_factor_Y*64,Fore_color); + Update_rect(Window_pos_X+(Menu_factor_X*264),Window_pos_Y+(Menu_factor_Y*93),Menu_factor_X<<4,Menu_factor_Y*64); + } + + // On tagge le bloc (ou la couleur) + Tag_color_range(block_start,block_end); + } + + last_color=temp_color; + } + } + Display_cursor(); + } + break; + case 2 : // Jauge rouge + Hide_cursor(); + if (block_start==block_end) + { + if(Palette_view_is_RGB) + { + Set_red(Fore_color,(Color_max-red_slider->Position)*255/Color_max,working_palette); + Format_componant(working_palette[Fore_color].R*Color_max/255,str); + } + else + { + HSL_to_RGB( + 255-red_slider->Position, + 255-green_slider->Position, + 255-blue_slider->Position, + &working_palette[Fore_color].R, + &working_palette[Fore_color].G, + &working_palette[Fore_color].B); + Format_componant((int)255-red_slider->Position,str); + } + Print_counter(176,172,str,MC_Black,MC_Light); + } + else + { + if(Palette_view_is_RGB) + { + for (i=block_start; i<=block_end; i++) + Set_red(i,temp_palette[i].R+(Color_max-red_slider->Position)*255/Color_max,working_palette); + } + else + { + for (i=block_start; i<=block_end; i++) + Set_HSL( + temp_palette, + working_palette, + i, + Color_max-red_slider->Position, + Color_max-green_slider->Position, + Color_max-blue_slider->Position + ); + } + + if (red_slider->Position>Color_max) + { + // Jauge dans les négatifs: + Num2str(-(Color_max-red_slider->Position),str,4); + str[0]='-'; + } + else if (red_slider->PositionPosition ,str,4); + str[0]='+'; + } + else + { + // Jauge nulle: + strcpy(str,"± 0"); + } + Print_counter(176,172,str,MC_Black,MC_Light); + + } + + need_to_remap=1; + + Display_cursor(); + Set_palette(working_palette); + break; + case 3 : // Jauge verte + Hide_cursor(); + if (block_start==block_end) + { + if(Palette_view_is_RGB) + { + Set_green (Fore_color,(Color_max-green_slider->Position)*255/Color_max,working_palette); + Format_componant(working_palette[Fore_color].G*Color_max/255,str); + } + else + { + HSL_to_RGB( + 255-red_slider->Position, + 255-green_slider->Position, + 255-blue_slider->Position, + &working_palette[Fore_color].R, + &working_palette[Fore_color].G, + &working_palette[Fore_color].B); + Format_componant((int)255-green_slider->Position,str); + } + Print_counter(203,172,str,MC_Black,MC_Light); + } + else + { + if(Palette_view_is_RGB) + { + for (i=block_start; i<=block_end; i++) + Set_green (i,temp_palette[i].G+(Color_max-green_slider->Position)*255/Color_max,working_palette); + } + else + { + for (i=block_start; i<=block_end; i++) + Set_HSL( + temp_palette, + working_palette, + i, + Color_max-red_slider->Position, + Color_max-green_slider->Position, + Color_max-blue_slider->Position + ); + } + + if (green_slider->Position>Color_max) + { + // Jauge dans les négatifs: + Num2str(-(Color_max-green_slider->Position),str,4); + str[0]='-'; + } + else if (green_slider->PositionPosition ,str,4); + str[0]='+'; + } + else + { + // Jauge nulle: + strcpy(str,"± 0"); + } + Print_counter(203,172,str,MC_Black,MC_Light); + } + + need_to_remap=1; + + Display_cursor(); + Set_palette(working_palette); + break; + + case 4 : // Jauge bleue + Hide_cursor(); + if (block_start==block_end) + { + if(Palette_view_is_RGB) + { + Set_blue (Fore_color,(Color_max-blue_slider->Position)*255/Color_max,working_palette); + Format_componant(working_palette[Fore_color].B*Color_max/255,str); + } + else + { + HSL_to_RGB( + 255-red_slider->Position, + 255-green_slider->Position, + 255-blue_slider->Position, + &working_palette[Fore_color].R, + &working_palette[Fore_color].G, + &working_palette[Fore_color].B); + Format_componant((int)255-blue_slider->Position,str); + } + Print_counter(230,172,str,MC_Black,MC_Light); + } + else + { + if(Palette_view_is_RGB) + { + for (i=block_start; i<=block_end; i++) + Set_blue(i,temp_palette[i].B+(Color_max-blue_slider->Position)*255/Color_max,working_palette); + } + else + { + for (i=block_start; i<=block_end; i++) + Set_HSL( + temp_palette, + working_palette, + i, + Color_max-red_slider->Position, + Color_max-green_slider->Position, + Color_max-blue_slider->Position + ); + } + + if (blue_slider->Position>Color_max) + { + // Jauge dans les négatifs: + Num2str(-(Color_max-blue_slider->Position),str,4); + str[0]='-'; + } + else if (blue_slider->PositionPosition ,str,4); + str[0]='+'; + } + else + { + // Jauge nulle: + strcpy(str,"± 0"); + } + Print_counter(230,172,str,MC_Black,MC_Light); + } + + need_to_remap=1; + + Display_cursor(); + Set_palette(working_palette); + break; + + case 5 : // Default + memcpy(backup_palette,working_palette,sizeof(T_Palette)); + memcpy(working_palette,Gfx->Default_palette,sizeof(T_Palette)); + memcpy(temp_palette,Gfx->Default_palette,sizeof(T_Palette)); + Set_palette(Gfx->Default_palette); + Draw_all_palette_sliders(red_slider,green_slider,blue_slider,working_palette,block_start,block_end); + // On prépare la "modifiabilité" des nouvelles couleurs + memcpy(temp_palette,working_palette,sizeof(T_Palette)); + + need_to_remap=1; + break; + + case 6 : // Grey scale + // Backup + memcpy(backup_palette,working_palette,sizeof(T_Palette)); + // Grey Scale + for (i=block_start;i<=block_end;i++) + { + temp_color=(dword)( ((dword)working_palette[i].R*30) + ((dword)working_palette[i].G*59) + ((dword)working_palette[i].B*11) )/100; + Set_red(i,temp_color,working_palette); + Set_green (i,temp_color,working_palette); + Set_blue (i,temp_color,working_palette); + } + Draw_all_palette_sliders(red_slider,green_slider,blue_slider,working_palette,block_start,block_end); + // On prépare la "modifiabilité" des nouvelles couleurs + Set_palette(working_palette); + memcpy(temp_palette,working_palette,sizeof(T_Palette)); + + need_to_remap=1; + break; + + case 7 : // Swap + case 8 : // X-Swap + temp_color=Wait_click_in_palette(Window_palette_button_list); + if ((temp_color>=0) + && (temp_color!=block_start)) + { + Hide_cursor(); + memcpy(backup_palette,working_palette,sizeof(T_Palette)); + + // On calcule le nombre de couleurs a swapper sans risquer de sortir + // de la palette (La var. first_color est utilisée pour économiser 1 var; c'est tout) + first_color=(temp_color+block_end-block_start<=255)?block_end+1-block_start:256-temp_color; + + if (clicked_button==8) // On ne fait de backup de l'image que si on + // est en mode X-SWAP. + if (!image_is_backed_up) + { + Backup(); + image_is_backed_up=1; + } + + Swap(clicked_button==8,block_start,temp_color,first_color,working_palette,color_usage); + + memcpy(temp_palette,working_palette,sizeof(T_Palette)); + + // On déplace le bloc vers les modifs: + last_color=block_end=temp_color+first_color-1; + Fore_color=first_color=block_start=temp_color; + // On raffiche le n° des bornes du bloc: + if (block_start!=block_end) + { + // Cas d'un bloc multi-couleur + Num2str(block_start,str ,3); + Num2str(block_end ,str+4,3); + str[3]=26; // Flèche vers la droite + // Affichage dans le block de visu du bloc (dégradé) en cours + Display_grad_block_in_window(264,93,block_start,block_end); + } + else + { + // Cas d'une seule couleur + Num2str(Fore_color,str,3); + Block(Window_pos_X+(Menu_factor_X*237),Window_pos_Y+(Menu_factor_Y*58),Menu_factor_X*56,Menu_factor_Y* 7,MC_Light); + // Affichage dans le block de visu de la couleur en cours + Block(Window_pos_X+(Menu_factor_X*264),Window_pos_Y+(Menu_factor_Y*93),Menu_factor_X<<4,Menu_factor_Y*64,Fore_color); + } + Print_in_window(237,58,str,MC_Black,MC_Light); + // On tag le bloc (ou la couleur) + Tag_color_range(block_start,block_end); + + need_to_remap=1; + + Set_palette(working_palette); + + Display_cursor(); + Draw_all_palette_sliders(red_slider,green_slider,blue_slider,working_palette,block_start,block_end); + + // En cas de X-Swap, tout l'ecran a pu changer de couleur. + if (clicked_button==8) + { + Update_rect(0, 0, Screen_width, Menu_Y_before_window); + End_of_modification(); + } + Wait_end_of_click(); + } + break; + + case 9 : // Copy + temp_color=Wait_click_in_palette(Window_palette_button_list); + if ((temp_color>=0) && (temp_color!=block_start)) + { + Hide_cursor(); + memcpy(backup_palette,working_palette,sizeof(T_Palette)); + memcpy(working_palette+temp_color,backup_palette+block_start, + ((temp_color+block_end-block_start<=255)?block_end+1-block_start:256-temp_color)*3); + memcpy(temp_palette,working_palette,sizeof(T_Palette)); + Set_palette(working_palette); + // On déplace le bloc vers les modifs: + last_color=block_end=((temp_color+block_end-block_start<=255)?(temp_color+block_end-block_start):255); + Fore_color=first_color=block_start=temp_color; + // On raffiche le n° des bornes du bloc: + if (block_start!=block_end) + { + // Cas d'un bloc multi-couleur + Num2str(block_start,str ,3); + Num2str(block_end ,str+4,3); + str[3]=26; // Flèche vers la droite + // Affichage dans le block de visu du bloc (dégradé) en cours + Display_grad_block_in_window(264,93,block_start,block_end); + } + else + { + // Cas d'une seule couleur + Num2str(Fore_color,str,3); + Block(Window_pos_X+(Menu_factor_X*237),Window_pos_Y+(Menu_factor_Y*58),Menu_factor_X*56,Menu_factor_Y* 7,MC_Light); + // Affichage dans le block de visu de la couleur en cours + Block(Window_pos_X+(Menu_factor_X*264),Window_pos_Y+(Menu_factor_Y*93),Menu_factor_X<<4,Menu_factor_Y*64,Fore_color); + } + Print_in_window(237,58,str,MC_Black,MC_Light); + // On tag le bloc (ou la couleur) + Tag_color_range(block_start,block_end); + + need_to_remap=1; + + Display_cursor(); + Draw_all_palette_sliders(red_slider,green_slider,blue_slider,working_palette,block_start,block_end); + Wait_end_of_click(); + } + break; + + case 10 : // Spread + if (block_start!=block_end) + { + memcpy(backup_palette,working_palette,sizeof(T_Palette)); + Spread_colors(block_start,block_end,working_palette); + } + else + { + temp_color=Wait_click_in_palette(Window_palette_button_list); + if (temp_color>=0) + { + memcpy(backup_palette,working_palette,sizeof(T_Palette)); + if (temp_colorPosition) + { + reducer_index=reduce_slider->Position; + // Affichage du facteur de réduction de la palette + Hide_cursor(); + Print_in_window(265,41,Palette_reduce_label[reducer_index],MC_Black,MC_Light); + Display_cursor(); + reduce_colors_number=atoi(Palette_reduce_label[reducer_index]); + } + break; + + case 18 : // [+] + if (!Palette_view_is_RGB) + break; + Hide_cursor(); + if (block_start==block_end) + { + if (red_slider->Position) + { + (red_slider->Position)--; + Window_draw_slider(red_slider); + Set_red(Fore_color,(Color_max-red_slider->Position)*255/Color_max,working_palette); + Format_componant(working_palette[Fore_color].R*Color_max/255,str); + Print_counter(176,172,str,MC_Black,MC_Light); + } + if (green_slider->Position) + { + (green_slider->Position)--; + Window_draw_slider(green_slider); + Set_green (Fore_color,(Color_max-green_slider->Position)*255/Color_max,working_palette); + Format_componant(working_palette[Fore_color].G*Color_max/255,str); + Print_counter(203,172,str,MC_Black,MC_Light); + } + if (blue_slider->Position) + { + (blue_slider->Position)--; + Window_draw_slider(blue_slider); + Set_blue (Fore_color,(Color_max-blue_slider->Position)*255/Color_max,working_palette); + Format_componant(working_palette[Fore_color].B*Color_max/255,str); + Print_counter(230,172,str,MC_Black,MC_Light); + } + } + else + { + if (red_slider->Position) + { + (red_slider->Position)--; + Window_draw_slider(red_slider); + } + if (green_slider->Position) + { + (green_slider->Position)--; + Window_draw_slider(green_slider); + } + if (blue_slider->Position) + { + (blue_slider->Position)--; + Window_draw_slider(blue_slider); + } + + for (i=block_start; i<=block_end; i++) + { + Set_red(i,temp_palette[i].R+(Color_max-red_slider->Position)*255/Color_max,working_palette); + Set_green (i,temp_palette[i].G+(Color_max-green_slider->Position)*255/Color_max,working_palette); + Set_blue (i,temp_palette[i].B+(Color_max-blue_slider->Position)*255/Color_max,working_palette); + } + + // -- red -- + if (red_slider->Position>Color_max) + { + // Jauge dans les négatifs: + Num2str(-(Color_max-red_slider->Position),str,4); + str[0]='-'; + } + else if (red_slider->PositionPosition ,str,4); + str[0]='+'; + } + else + { + // Jauge nulle: + strcpy(str,"± 0"); + } + Print_counter(176,172,str,MC_Black,MC_Light); + + + // -- green -- + if (green_slider->Position>Color_max) + { + // Jauge dans les négatifs: + Num2str(-(Color_max-green_slider->Position),str,4); + str[0]='-'; + } + else if (green_slider->PositionPosition ,str,4); + str[0]='+'; + } + else + { + // Jauge nulle: + strcpy(str,"± 0"); + } + Print_counter(203,172,str,MC_Black,MC_Light); + + + // -- blue -- + if (blue_slider->Position>Color_max) + { + // Jauge dans les négatifs: + Num2str(-(Color_max-blue_slider->Position),str,4); + str[0]='-'; + } + else if (blue_slider->PositionPosition ,str,4); + str[0]='+'; + } + else + { + // Jauge nulle: + strcpy(str,"± 0"); + } + Print_counter(230,172,str,MC_Black,MC_Light); + } + + need_to_remap=1; + + Display_cursor(); + Set_palette(working_palette); + break; + + case 19 : // [-] + if (!Palette_view_is_RGB) + break; + Hide_cursor(); + if (block_start==block_end) + { + if (red_slider->PositionPosition)++; + Window_draw_slider(red_slider); + Set_red(Fore_color,(Color_max-red_slider->Position)*255/Color_max,working_palette); + Format_componant(working_palette[Fore_color].R*Color_max/255,str); + Print_counter(176,172,str,MC_Black,MC_Light); + } + if (green_slider->PositionPosition)++; + Window_draw_slider(green_slider); + Set_green (Fore_color,(Color_max-green_slider->Position)*255/Color_max,working_palette); + Format_componant(working_palette[Fore_color].G*Color_max/255,str); + Print_counter(203,172,str,MC_Black,MC_Light); + } + if (blue_slider->PositionPosition)++; + Window_draw_slider(blue_slider); + Set_blue (Fore_color,(Color_max-blue_slider->Position)*255/Color_max,working_palette); + Format_componant(working_palette[Fore_color].B*Color_max/255,str); + Print_counter(230,172,str,MC_Black,MC_Light); + } + } + else + { + if (red_slider->Position<(Color_max*2)) + { + (red_slider->Position)++; + Window_draw_slider(red_slider); + } + if (green_slider->Position<(Color_max*2)) + { + (green_slider->Position)++; + Window_draw_slider(green_slider); + } + if (blue_slider->Position<(Color_max*2)) + { + (blue_slider->Position)++; + Window_draw_slider(blue_slider); + } + + for (i=block_start; i<=block_end; i++) + { + Set_red(i,temp_palette[i].R+(Color_max-red_slider->Position)*255/Color_max,working_palette); + Set_green (i,temp_palette[i].G+(Color_max-green_slider->Position)*255/Color_max,working_palette); + Set_blue (i,temp_palette[i].B+(Color_max-blue_slider->Position)*255/Color_max,working_palette); + } + + // -- red -- + if (red_slider->Position>Color_max) + { + // Jauge dans les négatifs: + Num2str(-(Color_max-red_slider->Position),str,4); + str[0]='-'; + } + else if (red_slider->PositionPosition ,str,4); + str[0]='+'; + } + else + { + // Jauge nulle: + strcpy(str,"± 0"); + } + Print_counter(176,172,str,MC_Black,MC_Light); + + + // -- green -- + if (green_slider->Position>Color_max) + { + // Jauge dans les négatifs: + Num2str(-(Color_max-green_slider->Position),str,4); + str[0]='-'; + } + else if (green_slider->PositionPosition ,str,4); + str[0]='+'; + } + else + { + // Jauge nulle: + strcpy(str,"± 0"); + } + Print_counter(203,172,str,MC_Black,MC_Light); + + + // -- blue -- + if (blue_slider->Position>Color_max) + { + // Jauge dans les négatifs: + Num2str(-(Color_max-blue_slider->Position),str,4); + str[0]='-'; + } + else if (blue_slider->PositionPosition ,str,4); + str[0]='+'; + } + else + { + // Jauge nulle: + strcpy(str,"± 0"); + } + Print_counter(230,172,str,MC_Black,MC_Light); + } + + need_to_remap=1; + + Display_cursor(); + Set_palette(working_palette); + break; + + case 20 : // Negative + // Backup + memcpy(backup_palette,working_palette,sizeof(T_Palette)); + // Negative + for (i=block_start;i<=block_end;i++) + { + Set_red(i,255-working_palette[i].R,working_palette); + Set_green (i,255-working_palette[i].G,working_palette); + Set_blue (i,255-working_palette[i].B,working_palette); + } + Draw_all_palette_sliders(red_slider,green_slider,blue_slider,working_palette,block_start,block_end); + Set_palette(working_palette); + // On prépare la "modifiabilité" des nouvelles couleurs + memcpy(temp_palette,working_palette,sizeof(T_Palette)); + + need_to_remap=1; + break; + + case 21 : // Inversion + case 22 : // X-Inversion + // Backup + memcpy(backup_palette,working_palette,sizeof(T_Palette)); + // On initialise la table de conversion + for (i=0; i<=255; i++) + conversion_table[i]=i; + // Inversion + for (i=block_start;i<=block_end;i++) + { + temp_color=block_end-(i-block_start); + Set_red(i,backup_palette[temp_color].R,working_palette); + Set_green (i,backup_palette[temp_color].G,working_palette); + Set_blue (i,backup_palette[temp_color].B,working_palette); + if (clicked_button==22) + { + conversion_table[i]=temp_color; + conversion_table[temp_color]=i; + + temp=color_usage[i]; + color_usage[i]=color_usage[temp_color]; + color_usage[temp_color]=temp; + } + } + Draw_all_palette_sliders(red_slider,green_slider,blue_slider,working_palette,block_start,block_end); + // Si on est en X-Invert, on remap l'image (=> on fait aussi 1 backup) + if (clicked_button==22) + { + if (!image_is_backed_up) + { + Backup(); + image_is_backed_up=1; + } + Hide_cursor(); + Remap_image_highlevel(conversion_table); + Display_cursor(); + End_of_modification(); + } + // On prépare la "modifiabilité" des nouvelles couleurs + Set_palette(working_palette); + memcpy(temp_palette,working_palette,sizeof(T_Palette)); + + need_to_remap=1; + break; + + case 23 : // Saisie du nombre de couleurs pour la réduction de palette + Num2str(reduce_colors_number,str,3); + + if (Readline(265,41,str,3,1)) + { + temp_color=atoi(str); + // Correction de la valeur lue + if ( (temp_color>256) || (temp_color<2) ) + { + if (temp_color>256) + temp_color=256; + else + temp_color=2; + + Num2str(temp_color,str,3); + Window_input_content(Window_special_button_list,str); + } + + reduce_colors_number=temp_color; + } + Display_cursor(); + break; + + case 24 : // HSL <> RGB + + // Acte les changements en cours sur une ou plusieurs couleurs + memcpy(temp_palette,working_palette,sizeof(T_Palette)); + memcpy(backup_palette, working_palette,sizeof(T_Palette)); + + Palette_view_is_RGB = !Palette_view_is_RGB; + + if(! Palette_view_is_RGB) + { + // On passe en HSL + Print_in_window(184,71,"H",MC_Dark,MC_Light); + Print_in_window(211,71,"S",MC_Dark,MC_Light); + Print_in_window(238,71,"L",MC_Dark,MC_Light); + Componant_unit(256); + + // Display the + and - button as disabled + Window_draw_normal_bouton(266, 74,12,11,"+",0,0); + Window_draw_normal_bouton(266,165,12,11,"-",0,0); + } + else + { + // On passe en RGB + Print_in_window(184,71,"R",MC_Dark,MC_Light); + Print_in_window(211,71,"G",MC_Dark,MC_Light); + Print_in_window(238,71,"B",MC_Dark,MC_Light); + Componant_unit(RGB_scale); + + // Display the + and - button as enabled + Window_draw_normal_bouton(266, 74,12,11,"+",0,1); + Window_draw_normal_bouton(266,165,12,11,"-",0,1); + } + Display_sliders(red_slider,green_slider,blue_slider,(block_start!=block_end),working_palette); + Update_window_area(265,73,14,103); + break; + + case 25 : // Sort palette + { + byte h = 0, l = 0, s=0; + byte oh=0,ol=0,os=0; // Valeur pour la couleur précédente + int swap=1; + byte remap_table[256]; + byte inverted_table[256]; + byte begin, end; + + if(block_start==block_end) + { + begin = 0; + end = 255; + } + else + { + begin = block_start; + end = block_end; + } + + // Init remap table + for (i=0;i<256;i++) + remap_table[i]=i; + // Make a backup because remapping is an undoable modification + if (!image_is_backed_up) + { + Backup(); + image_is_backed_up=1; + } + + if(Window_attribute1==LEFT_SIDE) + // Laft click on button: Sort by Hue (H) and Lightness (L) + while(swap==1) + { + swap=0; + h=0;l=255;s=0; + for(temp_color=begin;temp_color<=end;temp_color++) + { + oh=h; ol=l; os=s; + RGB_to_HSL(working_palette[temp_color].R, + working_palette[temp_color].G, + working_palette[temp_color].B,&h,&s,&l); + + if( + ((s==0) && (os>0)) // A grey is before a saturated color + || ((s>0 && os > 0) && (hol))) // 2 saturated colors: sort by H, then by L + || ((os==0 && s==0) && l>ol)) // Two greys: sort by L only + { + // Swap color with the previous one + byte swap_color; + Swap(0,temp_color,temp_color-1,1,working_palette,color_usage); + + swap_color=remap_table[temp_color]; + remap_table[temp_color]=remap_table[temp_color-1]; + remap_table[temp_color-1]=swap_color; + + swap=1; + } + } + } + + else // Right click > Sort only on L + while(swap==1) + { + swap=0; + l=255; + for(temp_color=begin;temp_color<=end;temp_color++) + { + ol=l; + RGB_to_HSL(working_palette[temp_color].R, + working_palette[temp_color].G, + working_palette[temp_color].B,&h,&s,&l); + + if(l>ol) + { + // Swap color with the previous one + byte swap_color; + Swap(0,temp_color,temp_color-1,1,working_palette,color_usage); + + swap_color=remap_table[temp_color]; + remap_table[temp_color]=remap_table[temp_color-1]; + remap_table[temp_color-1]=swap_color; + + swap=1; + } + } + } + + for (i=0;i<256;i++) + inverted_table[remap_table[i]]=i; + Remap_image_highlevel(inverted_table); + // Maintenant, tous ces calculs doivent êtres pris en compte dans la + // palette, l'image et à l'écran. + Set_palette(working_palette); + + End_of_modification(); + need_to_remap=1; + } + break; + } + + + if (!Mouse_K) + { + switch (Key) + { + case SDLK_LEFTBRACKET : // Décaler Forecolor vers la gauche + if (block_start==block_end) + { + Fore_color--; + first_color--; + last_color--; + block_start--; + block_end--; + Draw_all_palette_sliders(red_slider,green_slider,blue_slider,working_palette,block_start,block_end); + Hide_cursor(); + Tag_color_range(block_start,block_end); + // Affichage du n° de la couleur sélectionnée + Num2str(Fore_color,str,3); + Print_in_window(237,58,str,MC_Black,MC_Light); + // Affichage dans le block de visu de la couleur en cours + Block(Window_pos_X+(Menu_factor_X*264),Window_pos_Y+(Menu_factor_Y*93),Menu_factor_X<<4,Menu_factor_Y*64,Fore_color); + Update_rect(Window_pos_X+(Menu_factor_X*264),Window_pos_Y+(Menu_factor_Y*93),Menu_factor_X<<4,Menu_factor_Y*64); + Display_cursor(); + } + Key=0; + break; + + case SDLK_RIGHTBRACKET : // Décaler Forecolor vers la droite + if (block_start==block_end) + { + Fore_color++; + first_color++; + last_color++; + block_start++; + block_end++; + Draw_all_palette_sliders(red_slider,green_slider,blue_slider,working_palette,block_start,block_end); + Hide_cursor(); + Tag_color_range(block_start,block_end); + // Affichage du n° de la couleur sélectionnée + Num2str(Fore_color,str,3); + Print_in_window(237,58,str,MC_Black,MC_Light); + // Affichage dans le block de visu de la couleur en cours + Block(Window_pos_X+(Menu_factor_X*264),Window_pos_Y+(Menu_factor_Y*93),Menu_factor_X<<4,Menu_factor_Y*64,Fore_color); + Update_rect(Window_pos_X+(Menu_factor_X*264),Window_pos_Y+(Menu_factor_Y*93),Menu_factor_X<<4,Menu_factor_Y*64); + Display_cursor(); + } + Key=0; + break; + + case (SDLK_LEFTBRACKET|MOD_SHIFT) : // Decaler Backcolor vers la gauche + Back_color--; + case (SDLK_RIGHTBRACKET|MOD_SHIFT) : // Decaler Backcolor vers la droite + // attention: pas de break ci-dessus + if (Key==(SDLK_RIGHTBRACKET|MOD_SHIFT)) + Back_color++; + Hide_cursor(); + Block(Window_pos_X+(Menu_factor_X*260),Window_pos_Y+(Menu_factor_Y* 89),Menu_factor_X*24,Menu_factor_Y<<2,Back_color); + Block(Window_pos_X+(Menu_factor_X*260),Window_pos_Y+(Menu_factor_Y*157),Menu_factor_X*24,Menu_factor_Y<<2,Back_color); + Block(Window_pos_X+(Menu_factor_X*260),Window_pos_Y+(Menu_factor_Y* 93),Menu_factor_X<<2,Menu_factor_Y<<6,Back_color); + Block(Window_pos_X+(Menu_factor_X*280),Window_pos_Y+(Menu_factor_Y* 93),Menu_factor_X<<2,Menu_factor_Y<<6,Back_color); + Update_rect(Window_pos_X+(Menu_factor_X*260),Window_pos_Y+(Menu_factor_Y* 89),Menu_factor_X*32,Menu_factor_Y*72); + Display_cursor(); + Key=0; + break; + + case SDLK_BACKSPACE : // Remise des couleurs du menu à l'état normal en essayant + // de ne pas trop modifier l'image. + if (!image_is_backed_up) + { + Backup(); + image_is_backed_up=1; + } + if (used_colors==-1) + Update_color_count(&used_colors,color_usage); + + memcpy(backup_palette,working_palette,sizeof(T_Palette)); + memcpy(temp_palette,Main_palette,sizeof(T_Palette)); + memcpy(Main_palette,working_palette,sizeof(T_Palette)); + Set_nice_menu_colors(color_usage,0); + memcpy(working_palette,Main_palette,sizeof(T_Palette)); + memcpy(Main_palette,temp_palette,sizeof(T_Palette)); + Set_palette(working_palette); + memcpy(temp_palette,working_palette,sizeof(T_Palette)); + Draw_all_palette_sliders(red_slider,green_slider,blue_slider,working_palette,block_start,block_end); + Update_color_count(&used_colors,color_usage); + // End_of_modification(); + // Not really needed, the change was in palette entries + need_to_remap=1; + Key=0; + break; + + case SDLK_BACKQUOTE : // Récupération d'une couleur derrière le menu + case SDLK_COMMA : + Get_color_behind_window(&color,&click); + if (click) + { + Hide_cursor(); + if (click==RIGHT_SIDE) + { + if (Back_color!=color) + { + Back_color=color; + // 4 blocks de back_color entourant la fore_color + Block(Window_pos_X+(Menu_factor_X*260),Window_pos_Y+(Menu_factor_Y* 89),Menu_factor_X*24,Menu_factor_Y<<2,Back_color); + Block(Window_pos_X+(Menu_factor_X*260),Window_pos_Y+(Menu_factor_Y*157),Menu_factor_X*24,Menu_factor_Y<<2,Back_color); + Block(Window_pos_X+(Menu_factor_X*260),Window_pos_Y+(Menu_factor_Y* 93),Menu_factor_X<<2,Menu_factor_Y<<6,Back_color); + Block(Window_pos_X+(Menu_factor_X*280),Window_pos_Y+(Menu_factor_Y* 93),Menu_factor_X<<2,Menu_factor_Y<<6,Back_color); + Update_rect(Window_pos_X+(Menu_factor_X*260),Window_pos_Y+(Menu_factor_Y* 89),Menu_factor_X*32,Menu_factor_Y*72); + } + } + else + { + Fore_color=first_color=last_color=block_start=block_end=color; + Tag_color_range(block_start,block_end); + + // Affichage du n° de la couleur sélectionnée + Block(Window_pos_X+(Menu_factor_X*261),Window_pos_Y+(Menu_factor_Y*58),Menu_factor_X*32,Menu_factor_Y*7,MC_Light); + Num2str(Fore_color,str,3); + Print_in_window(237,58,str,MC_Black,MC_Light); + + // Affichage des jauges + Display_sliders(red_slider,green_slider,blue_slider,0,working_palette); + + // Affichage dans le block de visu de la couleur en cours + Block(Window_pos_X+(Menu_factor_X*264),Window_pos_Y+(Menu_factor_Y*93),Menu_factor_X<<4,Menu_factor_Y*64,Fore_color); + Update_rect(Window_pos_X+(Menu_factor_X*264),Window_pos_Y+(Menu_factor_Y*93),Menu_factor_X<<4,Menu_factor_Y*64); + + memcpy(backup_palette ,working_palette,sizeof(T_Palette)); + memcpy(temp_palette,working_palette,sizeof(T_Palette)); + } + Display_cursor(); + Wait_end_of_click(); + } + Key=0; + break; + default: + if (Is_shortcut(Key,0x100+BUTTON_HELP)) + { + Key=0; + Window_help(BUTTON_PALETTE, NULL); + break; + } + else if (Is_shortcut(Key,0x100+BUTTON_PALETTE)) + clicked_button=14; + } + + if (need_to_remap) + { + Hide_cursor(); + Compute_optimal_menu_colors(working_palette); + + // On remappe brutalement + Remap_screen_after_menu_colors_change(); + // Puis on remet les trucs qui ne devaient pas changer + Window_draw_palette_bouton(5,79); + Block(Window_pos_X+(Menu_factor_X*260),Window_pos_Y+(Menu_factor_Y*89),Menu_factor_X*24,Menu_factor_Y*72,Back_color); + Display_grad_block_in_window(264,93,block_start,block_end); + + Update_rect(Window_pos_X+8*Menu_factor_X,Window_pos_Y+82*Menu_factor_Y,Menu_factor_X*16*10,Menu_factor_Y*5*16); + + Display_cursor(); + need_to_remap=0; + } + } + } + while ((clicked_button!=13) && (clicked_button!=14)); + + if (clicked_button==14) // Sortie par OK + { + if ( (!image_is_backed_up) + && memcmp(Main_palette,working_palette,sizeof(T_Palette)) ) + Backup(); + memcpy(Main_palette,working_palette,sizeof(T_Palette)); + // End_of_modification(); + // Not really needed, the change was in palette entries + } + + Compute_optimal_menu_colors(Main_palette); + + // La variable employée ici n'a pas vraiment de rapport avec son nom... + need_to_remap=(Window_pos_Y+(Window_height*Menu_factor_Y)Position = rgb_scale_slider->Position>128?rgb_scale_slider->Position*2-256:0; + Num2str(256-rgb_scale_slider->Position,str,3); + Print_in_window(157,78,str,MC_Black,MC_Light); + Window_draw_slider(rgb_scale_slider); + break; + + case 10: + // /2 RGB scale + rgb_scale_slider->Position = rgb_scale_slider->Position>253?254:(rgb_scale_slider->Position)/2+128; + Num2str(256-rgb_scale_slider->Position,str,3); + Print_in_window(157,78,str,MC_Black,MC_Light); + Window_draw_slider(rgb_scale_slider); + } + } + while (clicked_button!=1 && clicked_button!=2 && clicked_button!=3 && clicked_button!=4); + + // We need to get the sliders positions before closing the window, because they will be freed. + palette_cols=256-columns_slider->Position; + palette_lines=16-lines_slider->Position; + rgb_scale=256-rgb_scale_slider->Position; + + Close_window(); + Unselect_button(BUTTON_PALETTE); + Display_cursor(); + + if (clicked_button==4) // Cancel + return; + + if (palette_vertical != Config.Palette_vertical) + { + Config.Palette_vertical=palette_vertical; + palette_needs_redraw=1; + } + if (palette_cols!=Config.Palette_cells_X || + palette_lines!=Config.Palette_cells_Y) + { + Config.Palette_cells_X = palette_cols; + Config.Palette_cells_Y = palette_lines; + palette_needs_redraw=1; + } + if (rgb_scale!=RGB_scale) + { + Set_palette_RGB_scale(rgb_scale); + Set_palette(Main_palette); + } + + if (clicked_button==1) + { + Menu_tag_colors("Tag colors to exclude",Exclude_color,&dummy,1, NULL, SPECIAL_EXCLUDE_COLORS_MENU); + } + else if (clicked_button==2) + { + // Open the menu with Shade settings. Same as the shortcut, except + // that this will not activate shade mode on exit. + Shade_settings_menu(); + } + + if (palette_needs_redraw) + { + Change_palette_cells(); + Display_menu(); + Display_sprite_in_menu(BUTTON_PAL_LEFT,18+(Config.Palette_vertical!=0)); + } +} diff --git a/palette.h b/palette.h index 273f792b..e28f280c 100644 --- a/palette.h +++ b/palette.h @@ -1,42 +1,42 @@ -/* Grafx2 - The Ultimate 256-color bitmap paint program - - Copyright 2007 Adrien Destugues - Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) - - Grafx2 is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; version 2 - of the License. - - Grafx2 is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Grafx2; if not, see -*/ -////////////////////////////////////////////////////////////////////////////// -///@file palette.h -/// Palette screen, and some palette-related high-level functions. -////////////////////////////////////////////////////////////////////////////// - -/// Open the palette menu and handles everything inside it. -void Button_Palette(void); -/// Open the secondary palette menu and handles it. -void Button_Secondary_palette(void); - -/// Choose the number of graduations for RGB components, from 2 to 256. -void Set_palette_RGB_scale(int); - -/// -/// Scale a component (R, G or B) according to the current RGB graduations. -/// Returns the resulting value, in the [0-255] range. -byte Round_palette_component(byte comp); - -/*! - Adds 4 menu colors in the current palette. - @param color_usage An up-to-date color usage table (byte[256]) (read only) - @param not_picture 0 if the caller is the palette screen, 1 if it's a preview in the file selector. -*/ -void Set_nice_menu_colors(dword * color_usage,int not_picture); +/* Grafx2 - The Ultimate 256-color bitmap paint program + + Copyright 2007 Adrien Destugues + Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) + + Grafx2 is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 + of the License. + + Grafx2 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grafx2; if not, see +*/ +////////////////////////////////////////////////////////////////////////////// +///@file palette.h +/// Palette screen, and some palette-related high-level functions. +////////////////////////////////////////////////////////////////////////////// + +/// Open the palette menu and handles everything inside it. +void Button_Palette(void); +/// Open the secondary palette menu and handles it. +void Button_Secondary_palette(void); + +/// Choose the number of graduations for RGB components, from 2 to 256. +void Set_palette_RGB_scale(int); + +/// +/// Scale a component (R, G or B) according to the current RGB graduations. +/// Returns the resulting value, in the [0-255] range. +byte Round_palette_component(byte comp); + +/*! + Adds 4 menu colors in the current palette. + @param color_usage An up-to-date color usage table (byte[256]) (read only) + @param not_picture 0 if the caller is the palette screen, 1 if it's a preview in the file selector. +*/ +void Set_nice_menu_colors(dword * color_usage,int not_picture); diff --git a/pversion.c b/pversion.c index 94351ab0..f09c8e6b 100644 --- a/pversion.c +++ b/pversion.c @@ -1 +1 @@ -char Program_version[]="2.0"; +char Program_version[]="2.1"; diff --git a/pxdouble.c b/pxdouble.c index a52ec1a2..c4f4fd3a 100644 --- a/pxdouble.c +++ b/pxdouble.c @@ -1,497 +1,504 @@ -/* Grafx2 - The Ultimate 256-color bitmap paint program - - Copyright 2008 Yves Rizoud - Copyright 2008 Franck Charlet - Copyright 2007 Adrien Destugues - Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) - - Grafx2 is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; version 2 - of the License. - - Grafx2 is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Grafx2; if not, see -*/ - -#include -#include -#include -#include "global.h" -#include "sdlscreen.h" -#include "misc.h" -#include "pxdouble.h" -#include "pxwide.h" // for Display_transparent_line_on_screen_wide() - -#define ZOOMX 2 -#define ZOOMY 2 - -void Pixel_double (word x,word y,byte color) -/* Affiche un pixel de la color aux coords x;y à l'écran */ -{ - *(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH)=color; - *(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH + 1)=color; - *(Screen_pixels + x * ZOOMX + (y*ZOOMY+1)* VIDEO_LINE_WIDTH)=color; - *(Screen_pixels + x * ZOOMX + (y*ZOOMY+1)* VIDEO_LINE_WIDTH + 1)=color; -} - -byte Read_pixel_double (word x,word y) -/* On retourne la couleur du pixel aux coords données */ -{ - return *( Screen_pixels + y * ZOOMY * VIDEO_LINE_WIDTH + x * ZOOMX); -} - -void Block_double (word start_x,word start_y,word width,word height,byte color) -/* On affiche un rectangle de la couleur donnée */ -{ - SDL_Rect rectangle; - rectangle.x=start_x*ZOOMX; - rectangle.y=start_y*ZOOMY; - rectangle.w=width*ZOOMX; - rectangle.h=height*ZOOMY; - SDL_FillRect(Screen_SDL,&rectangle,color); -} - -void Display_part_of_screen_double (word width,word height,word image_width) -/* Afficher une partie de l'image telle quelle sur l'écran */ -{ - byte* dest=Screen_pixels; //On va se mettre en 0,0 dans l'écran (dest) - byte* src=Main_offset_Y*image_width+Main_offset_X+Main_screen; //Coords de départ ds la source (src) - int y; - int dy; - - for(y=height;y!=0;y--) - // Pour chaque ligne - { - // On fait une copie de la ligne - for (dy=width;dy>0;dy--) - { - *(dest+1)=*dest=*src; - src++; - dest+=ZOOMX; - } - // On double la ligne qu'on vient de copier - memcpy(dest-width*ZOOMX+VIDEO_LINE_WIDTH,dest-width*ZOOMX,width*ZOOMX); - - // On passe à la ligne suivante - src+=image_width-width; - dest+=VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX; - } - //Update_rect(0,0,width,height); -} - -void Pixel_preview_normal_double (word x,word y,byte color) -/* Affichage d'un pixel dans l'écran, par rapport au décalage de l'image - * dans l'écran, en mode normal (pas en mode loupe) - * Note: si on modifie cette procédure, il faudra penser à faire également - * la modif dans la procédure Pixel_Preview_Loupe_SDL. */ -{ -// if(x-Main_offset_X >= 0 && y - Main_offset_Y >= 0) - Pixel_double(x-Main_offset_X,y-Main_offset_Y,color); -} - -void Pixel_preview_magnifier_double (word x,word y,byte color) -{ - // Affiche le pixel dans la partie non zoomée - Pixel_double(x-Main_offset_X,y-Main_offset_Y,color); - - // Regarde si on doit aussi l'afficher dans la partie zoomée - if (y >= Limit_top_zoom && y <= Limit_visible_bottom_zoom - && x >= Limit_left_zoom && x <= Limit_visible_right_zoom) - { - // On est dedans - int height; - int y_zoom = Main_magnifier_factor * (y-Main_magnifier_offset_Y); - - if (Menu_Y - y_zoom < Main_magnifier_factor) - // On ne doit dessiner qu'un morceau du pixel - // sinon on dépasse sur le menu - height = Menu_Y - y_zoom; - else - height = Main_magnifier_factor; - - Block_double( - Main_magnifier_factor * (x-Main_magnifier_offset_X) + Main_X_zoom, - y_zoom, Main_magnifier_factor, height, color - ); - } -} - -void Horizontal_XOR_line_double(word x_pos,word y_pos,word width) -{ - //On calcule la valeur initiale de dest: - byte* dest=y_pos*ZOOMY*VIDEO_LINE_WIDTH+x_pos*ZOOMX+Screen_pixels; - - int x; - - for (x=0;x0;i--) - { - *dest=*(dest+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+1)=~*dest; - dest+=VIDEO_LINE_WIDTH*ZOOMY; - } -} - -void Display_brush_color_double(word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width) -{ - // dest = Position à l'écran - byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX; - // src = Position dans la brosse - byte* src = Brush + y_offset * brush_width + x_offset; - - word x,y; - - // Pour chaque ligne - for(y = height;y > 0; y--) - { - // Pour chaque pixel - for(x = width;x > 0; x--) - { - // On vérifie que ce n'est pas la transparence - if(*src != transp_color) - { - *(dest+VIDEO_LINE_WIDTH+1) = *(dest+VIDEO_LINE_WIDTH) = *(dest+1) = *dest = *src; - } - - // Pixel suivant - src++; - dest+=ZOOMX; - } - - // On passe à la ligne suivante - dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX; - src = src + brush_width - width; - } - Update_rect(x_pos,y_pos,width,height); -} - -void Display_brush_mono_double(word x_pos, word y_pos, - word x_offset, word y_offset, word width, word height, - byte transp_color, byte color, word brush_width) -/* On affiche la brosse en monochrome */ -{ - byte* dest=y_pos*ZOOMY*VIDEO_LINE_WIDTH+x_pos*ZOOMX+Screen_pixels; // dest = adr destination à - // l'écran - byte* src=brush_width*y_offset+x_offset+Brush; // src = adr ds - // la brosse - int x,y; - - for(y=height;y!=0;y--) - //Pour chaque ligne - { - for(x=width;x!=0;x--) - //Pour chaque pixel - { - if (*src!=transp_color) - *(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+1)=*dest=color; - - // On passe au pixel suivant - src++; - dest+=ZOOMX; - } - - // On passe à la ligne suivante - src+=brush_width-width; - dest+=VIDEO_LINE_WIDTH*ZOOMY-width*ZOOMX; - } - Update_rect(x_pos,y_pos,width,height); -} - -void Clear_brush_double(word x_pos,word y_pos,__attribute__((unused)) word x_offset,__attribute__((unused)) word y_offset,word width,word height,__attribute__((unused))byte transp_color,word image_width) -{ - byte* dest=Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH; //On va se mettre en 0,0 dans l'écran (dest) - byte* src = ( y_pos + Main_offset_Y ) * image_width + x_pos + Main_offset_X + Main_screen; //Coords de départ ds la source (src) - int y; - int x; - - for(y=height;y!=0;y--) - // Pour chaque ligne - { - for(x=width;x!=0;x--) - //Pour chaque pixel - { - *(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+1)=*dest=*src; - - // On passe au pixel suivant - src++; - dest+=ZOOMX; - } - - // On passe à la ligne suivante - src+=image_width-width; - dest+=VIDEO_LINE_WIDTH*ZOOMY-width*ZOOMX; - } - Update_rect(x_pos,y_pos,width,height); -} - -// Affiche une brosse (arbitraire) à l'écran -void Display_brush_double(byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width) -{ - // dest = Position à l'écran - byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX; - // src = Position dans la brosse - byte* src = brush + y_offset * brush_width + x_offset; - - word x,y; - - // Pour chaque ligne - for(y = height;y > 0; y--) - { - // Pour chaque pixel - for(x = width;x > 0; x--) - { - // On vérifie que ce n'est pas la transparence - if(*src != transp_color) - { - *(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+1)=*dest=*src; - } - - // Pixel suivant - src++; dest+=ZOOMX; - } - - // On passe à la ligne suivante - dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX; - src = src + brush_width - width; - } -} - -void Remap_screen_double(word x_pos,word y_pos,word width,word height,byte * conversion_table) -{ - // dest = coords a l'écran - byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX; - int x,y; - - // Pour chaque ligne - for(y=height;y>0;y--) - { - // Pour chaque pixel - for(x=width;x>0;x--) - { - *(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+1)=*dest= - conversion_table[*dest]; - dest +=ZOOMX; - } - - dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX; - } - - Update_rect(x_pos,y_pos,width,height); -} - -void Display_line_on_screen_fast_double(word x_pos,word y_pos,word width,byte * line) -/* On affiche toute une ligne de pixels telle quelle. */ -/* Utilisée si le buffer contient déja des pixel doublés. */ -{ - memcpy(Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH,line,width*ZOOMX); - memcpy(Screen_pixels+x_pos*ZOOMX+(y_pos*ZOOMY+1)*VIDEO_LINE_WIDTH,line,width*ZOOMX); -} - -void Display_line_on_screen_double(word x_pos,word y_pos,word width,byte * line) -/* On affiche une ligne de pixels en les doublant. */ -{ - int x; - byte *dest; - dest=Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH; - for(x=width;x>0;x--) - { - *(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+1)=*dest=*line; - dest+=ZOOMX; - line++; - } -} -void Display_transparent_mono_line_on_screen_double( - word x_pos, word y_pos, word width, byte* line, - byte transp_color, byte color) -// Affiche une ligne à l'écran avec une couleur + transparence. -// Utilisé par les brosses en mode zoom -{ - byte* dest = Screen_pixels+ y_pos*VIDEO_LINE_WIDTH + x_pos*ZOOMX; - int x; - // Pour chaque pixel - for(x=0;x 0); - src += image_width; - } -// ATTENTION on n'arrive jamais ici ! -} - -// Affiche une partie de la brosse couleur zoomée -void Display_brush_color_zoom_double(word x_pos,word y_pos, - word x_offset,word y_offset, - word width, // width non zoomée - word end_y_pos,byte transp_color, - word brush_width, // width réelle de la brosse - byte * buffer) -{ - byte* src = Brush+y_offset*brush_width + x_offset; - word y = y_pos; - byte bx; - - // Pour chaque ligne - while(1) - { - Zoom_a_line(src,buffer,Main_magnifier_factor,width); - // On affiche facteur fois la ligne zoomée - for(bx=Main_magnifier_factor;bx>0;bx--) - { - Display_transparent_line_on_screen_wide(x_pos,y*ZOOMY,width*Main_magnifier_factor,buffer,transp_color); - memcpy(Screen_pixels + (y*ZOOMY+1)*VIDEO_LINE_WIDTH + x_pos*ZOOMX, Screen_pixels + y*ZOOMY*VIDEO_LINE_WIDTH + x_pos*ZOOMX, width*ZOOMX*Main_magnifier_factor); - y++; - if(y==end_y_pos) - { - return; - } - } - src += brush_width; - } - // ATTENTION zone jamais atteinte -} - -void Display_brush_mono_zoom_double(word x_pos, word y_pos, - word x_offset, word y_offset, - word width, // width non zoomée - word end_y_pos, - byte transp_color, byte color, - word brush_width, // width réelle de la brosse - byte * buffer -) - -{ - byte* src = Brush + y_offset * brush_width + x_offset; - int y=y_pos*ZOOMY; - - //Pour chaque ligne à zoomer : - while(1) - { - int bx; - // src = Ligne originale - // On éclate la ligne - Zoom_a_line(src,buffer,Main_magnifier_factor,width); - - // On affiche la ligne Facteur fois à l'écran (sur des - // lignes consécutives) - bx = Main_magnifier_factor*ZOOMY; - - // Pour chaque ligne écran - do - { - // On affiche la ligne zoomée - Display_transparent_mono_line_on_screen_double( - x_pos, y, width * Main_magnifier_factor, - buffer, transp_color, color - ); - // On passe à la ligne suivante - y++; - // On vérifie qu'on est pas à la ligne finale - if(y == end_y_pos*ZOOMY) - { - Update_rect( x_pos, y_pos, - width * Main_magnifier_factor, end_y_pos - y_pos ); - return; - } - bx --; - } - while (bx > 0); - - // Passage à la ligne suivante dans la brosse aussi - src+=brush_width; - } -} - -void Clear_brush_scaled_double(word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,__attribute__((unused)) byte transp_color,word image_width,byte * buffer) -{ - - // En fait on va recopier l'image non zoomée dans la partie zoomée ! - byte* src = Main_screen + y_offset * image_width + x_offset; - int y = y_pos; - int bx; - - // Pour chaque ligne à zoomer - while(1){ - Zoom_a_line(src,buffer,Main_magnifier_factor*ZOOMX,width); - - bx=Main_magnifier_factor; - - // Pour chaque ligne - do{ - Display_line_on_screen_fast_double(x_pos,y, - width * Main_magnifier_factor,buffer); - - // Ligne suivante - y++; - if(y==end_y_pos) - { - Update_rect(x_pos,y_pos, - width*Main_magnifier_factor,end_y_pos-y_pos); - return; - } - bx--; - }while(bx!=0); - - src+= image_width; - } -} - - +/* Grafx2 - The Ultimate 256-color bitmap paint program + + Copyright 2008 Yves Rizoud + Copyright 2008 Franck Charlet + Copyright 2007 Adrien Destugues + Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) + + Grafx2 is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 + of the License. + + Grafx2 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grafx2; if not, see +*/ + +#include +#include +#include +#include "global.h" +#include "sdlscreen.h" +#include "misc.h" +#include "graph.h" +#include "pxdouble.h" +#include "pxwide.h" // for Display_transparent_line_on_screen_wide() + +#define ZOOMX 2 +#define ZOOMY 2 + +void Pixel_double (word x,word y,byte color) +/* Affiche un pixel de la color aux coords x;y à l'écran */ +{ + *(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH)=color; + *(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH + 1)=color; + *(Screen_pixels + x * ZOOMX + (y*ZOOMY+1)* VIDEO_LINE_WIDTH)=color; + *(Screen_pixels + x * ZOOMX + (y*ZOOMY+1)* VIDEO_LINE_WIDTH + 1)=color; +} + +byte Read_pixel_double (word x,word y) +/* On retourne la couleur du pixel aux coords données */ +{ + return *( Screen_pixels + y * ZOOMY * VIDEO_LINE_WIDTH + x * ZOOMX); +} + +void Block_double (word start_x,word start_y,word width,word height,byte color) +/* On affiche un rectangle de la couleur donnée */ +{ + SDL_Rect rectangle; + rectangle.x=start_x*ZOOMX; + rectangle.y=start_y*ZOOMY; + rectangle.w=width*ZOOMX; + rectangle.h=height*ZOOMY; + SDL_FillRect(Screen_SDL,&rectangle,color); +} + +void Display_part_of_screen_double (word width,word height,word image_width) +/* Afficher une partie de l'image telle quelle sur l'écran */ +{ + byte* dest=Screen_pixels; //On va se mettre en 0,0 dans l'écran (dest) + byte* src=Main_offset_Y*image_width+Main_offset_X+Main_screen; //Coords de départ ds la source (src) + int y; + int dy; + + for(y=height;y!=0;y--) + // Pour chaque ligne + { + // On fait une copie de la ligne + for (dy=width;dy>0;dy--) + { + *(dest+1)=*dest=*src; + src++; + dest+=ZOOMX; + } + // On double la ligne qu'on vient de copier + memcpy(dest-width*ZOOMX+VIDEO_LINE_WIDTH,dest-width*ZOOMX,width*ZOOMX); + + // On passe à la ligne suivante + src+=image_width-width; + dest+=VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX; + } + //Update_rect(0,0,width,height); +} + +void Pixel_preview_normal_double (word x,word y,byte color) +/* Affichage d'un pixel dans l'écran, par rapport au décalage de l'image + * dans l'écran, en mode normal (pas en mode loupe) + * Note: si on modifie cette procédure, il faudra penser à faire également + * la modif dans la procédure Pixel_Preview_Loupe_SDL. */ +{ +// if(x-Main_offset_X >= 0 && y - Main_offset_Y >= 0) + Pixel_double(x-Main_offset_X,y-Main_offset_Y,color); +} + +void Pixel_preview_magnifier_double (word x,word y,byte color) +{ + // Affiche le pixel dans la partie non zoomée + Pixel_double(x-Main_offset_X,y-Main_offset_Y,color); + + // Regarde si on doit aussi l'afficher dans la partie zoomée + if (y >= Limit_top_zoom && y <= Limit_visible_bottom_zoom + && x >= Limit_left_zoom && x <= Limit_visible_right_zoom) + { + // On est dedans + int height; + int y_zoom = Main_magnifier_factor * (y-Main_magnifier_offset_Y); + + if (Menu_Y - y_zoom < Main_magnifier_factor) + // On ne doit dessiner qu'un morceau du pixel + // sinon on dépasse sur le menu + height = Menu_Y - y_zoom; + else + height = Main_magnifier_factor; + + Block_double( + Main_magnifier_factor * (x-Main_magnifier_offset_X) + Main_X_zoom, + y_zoom, Main_magnifier_factor, height, color + ); + } +} + +void Horizontal_XOR_line_double(word x_pos,word y_pos,word width) +{ + //On calcule la valeur initiale de dest: + byte* dest=y_pos*ZOOMY*VIDEO_LINE_WIDTH+x_pos*ZOOMX+Screen_pixels; + + int x; + + for (x=0;x0;i--) + { + *dest=*(dest+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+1)=~*dest; + dest+=VIDEO_LINE_WIDTH*ZOOMY; + } +} + +void Display_brush_color_double(word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width) +{ + // dest = Position à l'écran + byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX; + // src = Position dans la brosse + byte* src = Brush + y_offset * brush_width + x_offset; + + word x,y; + + // Pour chaque ligne + for(y = height;y > 0; y--) + { + // Pour chaque pixel + for(x = width;x > 0; x--) + { + // On vérifie que ce n'est pas la transparence + if(*src != transp_color) + { + *(dest+VIDEO_LINE_WIDTH+1) = *(dest+VIDEO_LINE_WIDTH) = *(dest+1) = *dest = *src; + } + + // Pixel suivant + src++; + dest+=ZOOMX; + } + + // On passe à la ligne suivante + dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX; + src = src + brush_width - width; + } + Update_rect(x_pos,y_pos,width,height); +} + +void Display_brush_mono_double(word x_pos, word y_pos, + word x_offset, word y_offset, word width, word height, + byte transp_color, byte color, word brush_width) +/* On affiche la brosse en monochrome */ +{ + byte* dest=y_pos*ZOOMY*VIDEO_LINE_WIDTH+x_pos*ZOOMX+Screen_pixels; // dest = adr destination à + // l'écran + byte* src=brush_width*y_offset+x_offset+Brush; // src = adr ds + // la brosse + int x,y; + + for(y=height;y!=0;y--) + //Pour chaque ligne + { + for(x=width;x!=0;x--) + //Pour chaque pixel + { + if (*src!=transp_color) + *(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+1)=*dest=color; + + // On passe au pixel suivant + src++; + dest+=ZOOMX; + } + + // On passe à la ligne suivante + src+=brush_width-width; + dest+=VIDEO_LINE_WIDTH*ZOOMY-width*ZOOMX; + } + Update_rect(x_pos,y_pos,width,height); +} + +void Clear_brush_double(word x_pos,word y_pos,__attribute__((unused)) word x_offset,__attribute__((unused)) word y_offset,word width,word height,__attribute__((unused))byte transp_color,word image_width) +{ + byte* dest=Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH; //On va se mettre en 0,0 dans l'écran (dest) + byte* src = ( y_pos + Main_offset_Y ) * image_width + x_pos + Main_offset_X + Main_screen; //Coords de départ ds la source (src) + int y; + int x; + + for(y=height;y!=0;y--) + // Pour chaque ligne + { + for(x=width;x!=0;x--) + //Pour chaque pixel + { + *(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+1)=*dest=*src; + + // On passe au pixel suivant + src++; + dest+=ZOOMX; + } + + // On passe à la ligne suivante + src+=image_width-width; + dest+=VIDEO_LINE_WIDTH*ZOOMY-width*ZOOMX; + } + Update_rect(x_pos,y_pos,width,height); +} + +// Affiche une brosse (arbitraire) à l'écran +void Display_brush_double(byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width) +{ + // dest = Position à l'écran + byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX; + // src = Position dans la brosse + byte* src = brush + y_offset * brush_width + x_offset; + + word x,y; + + // Pour chaque ligne + for(y = height;y > 0; y--) + { + // Pour chaque pixel + for(x = width;x > 0; x--) + { + // On vérifie que ce n'est pas la transparence + if(*src != transp_color) + { + *(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+1)=*dest=*src; + } + + // Pixel suivant + src++; dest+=ZOOMX; + } + + // On passe à la ligne suivante + dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX; + src = src + brush_width - width; + } +} + +void Remap_screen_double(word x_pos,word y_pos,word width,word height,byte * conversion_table) +{ + // dest = coords a l'écran + byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX; + int x,y; + + // Pour chaque ligne + for(y=height;y>0;y--) + { + // Pour chaque pixel + for(x=width;x>0;x--) + { + *(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+1)=*dest= + conversion_table[*dest]; + dest +=ZOOMX; + } + + dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX; + } + + Update_rect(x_pos,y_pos,width,height); +} + +void Display_line_on_screen_fast_double(word x_pos,word y_pos,word width,byte * line) +/* On affiche toute une ligne de pixels telle quelle. */ +/* Utilisée si le buffer contient déja des pixel doublés. */ +{ + memcpy(Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH,line,width*ZOOMX); + memcpy(Screen_pixels+x_pos*ZOOMX+(y_pos*ZOOMY+1)*VIDEO_LINE_WIDTH,line,width*ZOOMX); +} + +void Display_line_on_screen_double(word x_pos,word y_pos,word width,byte * line) +/* On affiche une ligne de pixels en les doublant. */ +{ + int x; + byte *dest; + dest=Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH; + for(x=width;x>0;x--) + { + *(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+1)=*dest=*line; + dest+=ZOOMX; + line++; + } +} +void Display_transparent_mono_line_on_screen_double( + word x_pos, word y_pos, word width, byte* line, + byte transp_color, byte color) +// Affiche une ligne à l'écran avec une couleur + transparence. +// Utilisé par les brosses en mode zoom +{ + byte* dest = Screen_pixels+ y_pos*VIDEO_LINE_WIDTH + x_pos*ZOOMX; + int x; + // Pour chaque pixel + for(x=0;x 0); + src += image_width; + } +// ATTENTION on n'arrive jamais ici ! +} + +// Affiche une partie de la brosse couleur zoomée +void Display_brush_color_zoom_double(word x_pos,word y_pos, + word x_offset,word y_offset, + word width, // width non zoomée + word end_y_pos,byte transp_color, + word brush_width, // width réelle de la brosse + byte * buffer) +{ + byte* src = Brush+y_offset*brush_width + x_offset; + word y = y_pos; + byte bx; + + // Pour chaque ligne + while(1) + { + Zoom_a_line(src,buffer,Main_magnifier_factor,width); + // On affiche facteur fois la ligne zoomée + for(bx=Main_magnifier_factor;bx>0;bx--) + { + Display_transparent_line_on_screen_wide(x_pos,y*ZOOMY,width*Main_magnifier_factor,buffer,transp_color); + memcpy(Screen_pixels + (y*ZOOMY+1)*VIDEO_LINE_WIDTH + x_pos*ZOOMX, Screen_pixels + y*ZOOMY*VIDEO_LINE_WIDTH + x_pos*ZOOMX, width*ZOOMX*Main_magnifier_factor); + y++; + if(y==end_y_pos) + { + return; + } + } + src += brush_width; + } + // ATTENTION zone jamais atteinte +} + +void Display_brush_mono_zoom_double(word x_pos, word y_pos, + word x_offset, word y_offset, + word width, // width non zoomée + word end_y_pos, + byte transp_color, byte color, + word brush_width, // width réelle de la brosse + byte * buffer +) + +{ + byte* src = Brush + y_offset * brush_width + x_offset; + int y=y_pos*ZOOMY; + + //Pour chaque ligne à zoomer : + while(1) + { + int bx; + // src = Ligne originale + // On éclate la ligne + Zoom_a_line(src,buffer,Main_magnifier_factor,width); + + // On affiche la ligne Facteur fois à l'écran (sur des + // lignes consécutives) + bx = Main_magnifier_factor*ZOOMY; + + // Pour chaque ligne écran + do + { + // On affiche la ligne zoomée + Display_transparent_mono_line_on_screen_double( + x_pos, y, width * Main_magnifier_factor, + buffer, transp_color, color + ); + // On passe à la ligne suivante + y++; + // On vérifie qu'on est pas à la ligne finale + if(y == end_y_pos*ZOOMY) + { + Redraw_grid( x_pos, y_pos, + width * Main_magnifier_factor, end_y_pos - y_pos ); + Update_rect( x_pos, y_pos, + width * Main_magnifier_factor, end_y_pos - y_pos ); + return; + } + bx --; + } + while (bx > 0); + + // Passage à la ligne suivante dans la brosse aussi + src+=brush_width; + } +} + +void Clear_brush_scaled_double(word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,__attribute__((unused)) byte transp_color,word image_width,byte * buffer) +{ + + // En fait on va recopier l'image non zoomée dans la partie zoomée ! + byte* src = Main_screen + y_offset * image_width + x_offset; + int y = y_pos; + int bx; + + // Pour chaque ligne à zoomer + while(1){ + Zoom_a_line(src,buffer,Main_magnifier_factor*ZOOMX,width); + + bx=Main_magnifier_factor; + + // Pour chaque ligne + do{ + Display_line_on_screen_fast_double(x_pos,y, + width * Main_magnifier_factor,buffer); + + // Ligne suivante + y++; + if(y==end_y_pos) + { + Redraw_grid(x_pos,y_pos, + width*Main_magnifier_factor,end_y_pos-y_pos); + Update_rect(x_pos,y_pos, + width*Main_magnifier_factor,end_y_pos-y_pos); + return; + } + bx--; + }while(bx!=0); + + src+= image_width; + } +} + + diff --git a/pxdouble.h b/pxdouble.h index e7655ce9..3d8296f8 100644 --- a/pxdouble.h +++ b/pxdouble.h @@ -1,48 +1,48 @@ -/* Grafx2 - The Ultimate 256-color bitmap paint program - - Copyright 2008 Yves Rizoud - Copyright 2007 Adrien Destugues - Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) - - Grafx2 is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; version 2 - of the License. - - Grafx2 is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Grafx2; if not, see -*/ - -////////////////////////////////////////////////////////////////////////////// -///@file pxdouble.h -/// Renderer for double pixels (2x2). -////////////////////////////////////////////////////////////////////////////// - -#include "struct.h" - - void Pixel_double (word x,word y,byte color); - byte Read_pixel_double (word x,word y); - void Block_double (word start_x,word start_y,word width,word height,byte color); - void Pixel_preview_normal_double (word x,word y,byte color); - void Pixel_preview_magnifier_double (word x,word y,byte color); - void Horizontal_XOR_line_double (word x_pos,word y_pos,word width); - void Vertical_XOR_line_double (word x_pos,word y_pos,word height); - void Display_brush_color_double (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width); - void Display_brush_mono_double (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,byte color,word brush_width); - void Clear_brush_double (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word image_width); - void Remap_screen_double (word x_pos,word y_pos,word width,word height,byte * conversion_table); - void Display_part_of_screen_double (word width,word height,word image_width); - void Display_line_on_screen_double (word x_pos,word y_pos,word width,byte * line); - void Read_line_screen_double (word x_pos,word y_pos,word width,byte * line); - void Display_part_of_screen_scaled_double(word width,word height,word image_width,byte * buffer); - void Display_brush_color_zoom_double (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,word brush_width,byte * buffer); - void Display_brush_mono_zoom_double (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,byte color,word brush_width,byte * buffer); - void Clear_brush_scaled_double (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,word image_width,byte * buffer); - void Display_brush_double (byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width); - - void Display_line_on_screen_fast_double (word x_pos,word y_pos,word width,byte * line); +/* Grafx2 - The Ultimate 256-color bitmap paint program + + Copyright 2008 Yves Rizoud + Copyright 2007 Adrien Destugues + Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) + + Grafx2 is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 + of the License. + + Grafx2 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grafx2; if not, see +*/ + +////////////////////////////////////////////////////////////////////////////// +///@file pxdouble.h +/// Renderer for double pixels (2x2). +////////////////////////////////////////////////////////////////////////////// + +#include "struct.h" + + void Pixel_double (word x,word y,byte color); + byte Read_pixel_double (word x,word y); + void Block_double (word start_x,word start_y,word width,word height,byte color); + void Pixel_preview_normal_double (word x,word y,byte color); + void Pixel_preview_magnifier_double (word x,word y,byte color); + void Horizontal_XOR_line_double (word x_pos,word y_pos,word width); + void Vertical_XOR_line_double (word x_pos,word y_pos,word height); + void Display_brush_color_double (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width); + void Display_brush_mono_double (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,byte color,word brush_width); + void Clear_brush_double (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word image_width); + void Remap_screen_double (word x_pos,word y_pos,word width,word height,byte * conversion_table); + void Display_part_of_screen_double (word width,word height,word image_width); + void Display_line_on_screen_double (word x_pos,word y_pos,word width,byte * line); + void Read_line_screen_double (word x_pos,word y_pos,word width,byte * line); + void Display_part_of_screen_scaled_double(word width,word height,word image_width,byte * buffer); + void Display_brush_color_zoom_double (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,word brush_width,byte * buffer); + void Display_brush_mono_zoom_double (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,byte color,word brush_width,byte * buffer); + void Clear_brush_scaled_double (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,word image_width,byte * buffer); + void Display_brush_double (byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width); + + void Display_line_on_screen_fast_double (word x_pos,word y_pos,word width,byte * line); diff --git a/pxquad.c b/pxquad.c index b257e316..1b1e328f 100644 --- a/pxquad.c +++ b/pxquad.c @@ -1,532 +1,539 @@ -/* Grafx2 - The Ultimate 256-color bitmap paint program - - Copyright 2008 Yves Rizoud - Copyright 2008 Franck Charlet - Copyright 2007 Adrien Destugues - Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) - - Grafx2 is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; version 2 - of the License. - - Grafx2 is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Grafx2; if not, see -*/ - -#include -#include -#include -#include "global.h" -#include "sdlscreen.h" -#include "misc.h" -#include "pxquad.h" - -#define ZOOMX 4 -#define ZOOMY 4 - -void Pixel_quad (word x,word y,byte color) -/* Affiche un pixel de la color aux coords x;y à l'écran */ -{ - *(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH)=color; - *(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH + 1)=color; - *(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH + 2)=color; - *(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH + 3)=color; - *(Screen_pixels + x * ZOOMX + (y*ZOOMY+1) * VIDEO_LINE_WIDTH)=color; - *(Screen_pixels + x * ZOOMX + (y*ZOOMY+1) * VIDEO_LINE_WIDTH + 1)=color; - *(Screen_pixels + x * ZOOMX + (y*ZOOMY+1) * VIDEO_LINE_WIDTH + 2)=color; - *(Screen_pixels + x * ZOOMX + (y*ZOOMY+1) * VIDEO_LINE_WIDTH + 3)=color; - *(Screen_pixels + x * ZOOMX + (y*ZOOMY+2) * VIDEO_LINE_WIDTH)=color; - *(Screen_pixels + x * ZOOMX + (y*ZOOMY+2) * VIDEO_LINE_WIDTH + 1)=color; - *(Screen_pixels + x * ZOOMX + (y*ZOOMY+2) * VIDEO_LINE_WIDTH + 2)=color; - *(Screen_pixels + x * ZOOMX + (y*ZOOMY+2) * VIDEO_LINE_WIDTH + 3)=color; - *(Screen_pixels + x * ZOOMX + (y*ZOOMY+3) * VIDEO_LINE_WIDTH)=color; - *(Screen_pixels + x * ZOOMX + (y*ZOOMY+3) * VIDEO_LINE_WIDTH + 1)=color; - *(Screen_pixels + x * ZOOMX + (y*ZOOMY+3) * VIDEO_LINE_WIDTH + 2)=color; - *(Screen_pixels + x * ZOOMX + (y*ZOOMY+3) * VIDEO_LINE_WIDTH + 3)=color; -} - -byte Read_pixel_quad (word x,word y) -/* On retourne la couleur du pixel aux coords données */ -{ - return *( Screen_pixels + y * ZOOMY * VIDEO_LINE_WIDTH + x * ZOOMX); -} - -void Block_quad (word start_x,word start_y,word width,word height,byte color) -/* On affiche un rectangle de la couleur donnée */ -{ - SDL_Rect rectangle; - rectangle.x=start_x*ZOOMX; - rectangle.y=start_y*ZOOMY; - rectangle.w=width*ZOOMX; - rectangle.h=height*ZOOMY; - SDL_FillRect(Screen_SDL,&rectangle,color); -} - -void Display_part_of_screen_quad (word width,word height,word image_width) -/* Afficher une partie de l'image telle quelle sur l'écran */ -{ - byte* dest=Screen_pixels; //On va se mettre en 0,0 dans l'écran (dest) - byte* src=Main_offset_Y*image_width+Main_offset_X+Main_screen; //Coords de départ ds la source (src) - int y; - int dy; - - for(y=height;y!=0;y--) - // Pour chaque ligne - { - // On fait une copie de la ligne - for (dy=width;dy>0;dy--) - { - *(dest+3)=*(dest+2)=*(dest+1)=*dest=*src; - src++; - dest+=ZOOMX; - } - // On double la ligne qu'on vient de copier - memcpy(dest-width*ZOOMX+VIDEO_LINE_WIDTH,dest-width*ZOOMX,width*ZOOMX); - // On la triple - memcpy(dest-width*ZOOMX+2*VIDEO_LINE_WIDTH,dest-width*ZOOMX,width*ZOOMX); - // On la quadruple - memcpy(dest-width*ZOOMX+3*VIDEO_LINE_WIDTH,dest-width*ZOOMX,width*ZOOMX); - - // On passe à la ligne suivante - src+=image_width-width; - dest+=VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX; - } - //Update_rect(0,0,width,height); -} - -void Pixel_preview_normal_quad (word x,word y,byte color) -/* Affichage d'un pixel dans l'écran, par rapport au décalage de l'image - * dans l'écran, en mode normal (pas en mode loupe) - * Note: si on modifie cette procédure, il faudra penser à faire également - * la modif dans la procédure Pixel_Preview_Loupe_SDL. */ -{ -// if(x-Main_offset_X >= 0 && y - Main_offset_Y >= 0) - Pixel_quad(x-Main_offset_X,y-Main_offset_Y,color); -} - -void Pixel_preview_magnifier_quad (word x,word y,byte color) -{ - // Affiche le pixel dans la partie non zoomée - Pixel_quad(x-Main_offset_X,y-Main_offset_Y,color); - - // Regarde si on doit aussi l'afficher dans la partie zoomée - if (y >= Limit_top_zoom && y <= Limit_visible_bottom_zoom - && x >= Limit_left_zoom && x <= Limit_visible_right_zoom) - { - // On est dedans - int height; - int y_zoom = Main_magnifier_factor * (y-Main_magnifier_offset_Y); - - if (Menu_Y - y_zoom < Main_magnifier_factor) - // On ne doit dessiner qu'un morceau du pixel - // sinon on dépasse sur le menu - height = Menu_Y - y_zoom; - else - height = Main_magnifier_factor; - - Block_quad( - Main_magnifier_factor * (x-Main_magnifier_offset_X) + Main_X_zoom, - y_zoom, Main_magnifier_factor, height, color - ); - } -} - -void Horizontal_XOR_line_quad(word x_pos,word y_pos,word width) -{ - //On calcule la valeur initiale de dest: - byte* dest=y_pos*ZOOMY*VIDEO_LINE_WIDTH+x_pos*ZOOMX+Screen_pixels; - - int x; - - for (x=0;x0;i--) - { - *(dest+3*VIDEO_LINE_WIDTH+3)=*(dest+3*VIDEO_LINE_WIDTH+2)=*(dest+3*VIDEO_LINE_WIDTH+1)=*(dest+3*VIDEO_LINE_WIDTH)=*(dest+2*VIDEO_LINE_WIDTH+3)=*(dest+2*VIDEO_LINE_WIDTH+2)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+3)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+3)=*(dest+2)=*(dest+1)=*(dest)=~*(dest); - dest+=VIDEO_LINE_WIDTH*ZOOMY; - } -} - -void Display_brush_color_quad(word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width) -{ - // dest = Position à l'écran - byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX; - // src = Position dans la brosse - byte* src = Brush + y_offset * brush_width + x_offset; - - word x,y; - - // Pour chaque ligne - for(y = height;y > 0; y--) - { - // Pour chaque pixel - for(x = width;x > 0; x--) - { - // On vérifie que ce n'est pas la transparence - if(*src != transp_color) - { - *(dest+3*VIDEO_LINE_WIDTH+3) = *(dest+3*VIDEO_LINE_WIDTH+2) = *(dest+3*VIDEO_LINE_WIDTH+1) = *(dest+3*VIDEO_LINE_WIDTH) = *(dest+2*VIDEO_LINE_WIDTH+3) = *(dest+2*VIDEO_LINE_WIDTH+2) = *(dest+2*VIDEO_LINE_WIDTH+1) = *(dest+2*VIDEO_LINE_WIDTH) = *(dest+VIDEO_LINE_WIDTH+3) = *(dest+VIDEO_LINE_WIDTH+2) = *(dest+VIDEO_LINE_WIDTH+1) = *(dest+VIDEO_LINE_WIDTH) = *(dest+3) = *(dest+2) = *(dest+1) = *dest = *src; - } - - // Pixel suivant - src++; - dest+=ZOOMX; - } - - // On passe à la ligne suivante - dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX; - src = src + brush_width - width; - } - Update_rect(x_pos,y_pos,width,height); -} - -void Display_brush_mono_quad(word x_pos, word y_pos, - word x_offset, word y_offset, word width, word height, - byte transp_color, byte color, word brush_width) -/* On affiche la brosse en monochrome */ -{ - byte* dest=y_pos*ZOOMY*VIDEO_LINE_WIDTH+x_pos*ZOOMX+Screen_pixels; // dest = adr destination à - // l'écran - byte* src=brush_width*y_offset+x_offset+Brush; // src = adr ds - // la brosse - int x,y; - - for(y=height;y!=0;y--) - //Pour chaque ligne - { - for(x=width;x!=0;x--) - //Pour chaque pixel - { - if (*src!=transp_color) - *(dest+3*VIDEO_LINE_WIDTH+3)=*(dest+3*VIDEO_LINE_WIDTH+2)=*(dest+3*VIDEO_LINE_WIDTH+1)=*(dest+3*VIDEO_LINE_WIDTH)=*(dest+2*VIDEO_LINE_WIDTH+3)=*(dest+2*VIDEO_LINE_WIDTH+2)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+3)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+3)=*(dest+2)=*(dest+1)=*dest=color; - - // On passe au pixel suivant - src++; - dest+=ZOOMX; - } - - // On passe à la ligne suivante - src+=brush_width-width; - dest+=VIDEO_LINE_WIDTH*ZOOMY-width*ZOOMX; - } - Update_rect(x_pos,y_pos,width,height); -} - -void Clear_brush_quad(word x_pos,word y_pos,__attribute__((unused)) word x_offset,__attribute__((unused)) word y_offset,word width,word height,__attribute__((unused))byte transp_color,word image_width) -{ - byte* dest=Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH; //On va se mettre en 0,0 dans l'écran (dest) - byte* src = ( y_pos + Main_offset_Y ) * image_width + x_pos + Main_offset_X + Main_screen; //Coords de départ ds la source (src) - int y; - int x; - - for(y=height;y!=0;y--) - // Pour chaque ligne - { - for(x=width;x!=0;x--) - //Pour chaque pixel - { - *(dest+3*VIDEO_LINE_WIDTH+3)=*(dest+3*VIDEO_LINE_WIDTH+2)=*(dest+3*VIDEO_LINE_WIDTH+1)=*(dest+3*VIDEO_LINE_WIDTH)=*(dest+2*VIDEO_LINE_WIDTH+3)=*(dest+2*VIDEO_LINE_WIDTH+2)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+3)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+3)=*(dest+2)=*(dest+1)=*dest=*src; - - // On passe au pixel suivant - src++; - dest+=ZOOMX; - } - - // On passe à la ligne suivante - src+=image_width-width; - dest+=VIDEO_LINE_WIDTH*ZOOMY-width*ZOOMX; - } - Update_rect(x_pos,y_pos,width,height); -} - -// Affiche une brosse (arbitraire) à l'écran -void Display_brush_quad(byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width) -{ - // dest = Position à l'écran - byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX; - // src = Position dans la brosse - byte* src = brush + y_offset * brush_width + x_offset; - - word x,y; - - // Pour chaque ligne - for(y = height;y > 0; y--) - { - // Pour chaque pixel - for(x = width;x > 0; x--) - { - // On vérifie que ce n'est pas la transparence - if(*src != transp_color) - { - *(dest+3*VIDEO_LINE_WIDTH+3)=*(dest+3*VIDEO_LINE_WIDTH+2)=*(dest+3*VIDEO_LINE_WIDTH+1)=*(dest+3*VIDEO_LINE_WIDTH)=*(dest+2*VIDEO_LINE_WIDTH+3)=*(dest+2*VIDEO_LINE_WIDTH+2)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+3)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+3)=*(dest+2)=*(dest+1)=*dest=*src; - } - - // Pixel suivant - src++; dest+=ZOOMX; - } - - // On passe à la ligne suivante - dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX; - src = src + brush_width - width; - } -} - -void Remap_screen_quad(word x_pos,word y_pos,word width,word height,byte * conversion_table) -{ - // dest = coords a l'écran - byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX; - int x,y; - - // Pour chaque ligne - for(y=height;y>0;y--) - { - // Pour chaque pixel - for(x=width;x>0;x--) - { - *(dest+3*VIDEO_LINE_WIDTH+3)=*(dest+3*VIDEO_LINE_WIDTH+2)=*(dest+3*VIDEO_LINE_WIDTH+1)=*(dest+3*VIDEO_LINE_WIDTH)=*(dest+2*VIDEO_LINE_WIDTH+3)=*(dest+2*VIDEO_LINE_WIDTH+2)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+3)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+3)=*(dest+2)=*(dest+1)=*dest= - conversion_table[*dest]; - dest +=ZOOMX; - } - - dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX; - } - - Update_rect(x_pos,y_pos,width,height); -} - -void Display_line_on_screen_fast_quad(word x_pos,word y_pos,word width,byte * line) -/* On affiche toute une ligne de pixels telle quelle. */ -/* Utilisée si le buffer contient déja des pixel doublés. */ -{ - memcpy(Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH,line,width*ZOOMX); - memcpy(Screen_pixels+x_pos*ZOOMX+(y_pos*ZOOMY+1)*VIDEO_LINE_WIDTH,line,width*ZOOMX); - memcpy(Screen_pixels+x_pos*ZOOMX+(y_pos*ZOOMY+2)*VIDEO_LINE_WIDTH,line,width*ZOOMX); - memcpy(Screen_pixels+x_pos*ZOOMX+(y_pos*ZOOMY+3)*VIDEO_LINE_WIDTH,line,width*ZOOMX); -} - -void Display_line_on_screen_quad(word x_pos,word y_pos,word width,byte * line) -/* On affiche une ligne de pixels en les doublant. */ -{ - int x; - byte *dest; - dest=Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH; - for(x=width;x>0;x--) - { - *(dest+3*VIDEO_LINE_WIDTH+3)=*(dest+3*VIDEO_LINE_WIDTH+2)=*(dest+3*VIDEO_LINE_WIDTH+1)=*(dest+3*VIDEO_LINE_WIDTH)=*(dest+2*VIDEO_LINE_WIDTH+3)=*(dest+2*VIDEO_LINE_WIDTH+2)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+3)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+3)=*(dest+2)=*(dest+1)=*dest=*line; - dest+=ZOOMX; - line++; - } -} -void Display_transparent_mono_line_on_screen_quad( - word x_pos, word y_pos, word width, byte* line, - byte transp_color, byte color) -// Affiche une ligne à l'écran avec une couleur + transparence. -// Utilisé par les brosses en mode zoom -{ - byte* dest = Screen_pixels+ y_pos*VIDEO_LINE_WIDTH + x_pos*ZOOMX; - int x; - // Pour chaque pixel - for(x=0;x 0); - src += image_width; - } -// ATTENTION on n'arrive jamais ici ! -} - -// Affiche une partie de la brosse couleur zoomée -void Display_brush_color_zoom_quad(word x_pos,word y_pos, - word x_offset,word y_offset, - word width, // width non zoomée - word end_y_pos,byte transp_color, - word brush_width, // width réelle de la brosse - byte * buffer) -{ - byte* src = Brush+y_offset*brush_width + x_offset; - word y = y_pos; - byte bx; - - // Pour chaque ligne - while(1) - { - Zoom_a_line(src,buffer,Main_magnifier_factor,width); - // On affiche facteur fois la ligne zoomée - for(bx=Main_magnifier_factor;bx>0;bx--) - { - byte* line_src = buffer; - byte* dest = Screen_pixels + y*ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX; - word x; - // Pour chaque pixel de la ligne - for(x = width*Main_magnifier_factor;x > 0;x--) - { - if(*line_src!=transp_color) - { - *(dest+3)=*(dest+2)=*(dest+1)=*dest = *line_src; - } - line_src++; - dest+=ZOOMX; - } - // Double the line - memcpy(Screen_pixels + (y*ZOOMY+1)*VIDEO_LINE_WIDTH + x_pos*ZOOMX, Screen_pixels + y*ZOOMY*VIDEO_LINE_WIDTH + x_pos*ZOOMX, width*ZOOMX*Main_magnifier_factor); - // Triple the line - memcpy(Screen_pixels + (y*ZOOMY+2)*VIDEO_LINE_WIDTH + x_pos*ZOOMX, Screen_pixels + y*ZOOMY*VIDEO_LINE_WIDTH + x_pos*ZOOMX, width*ZOOMX*Main_magnifier_factor); - // Quadruple it - memcpy(Screen_pixels + (y*ZOOMY+3)*VIDEO_LINE_WIDTH + x_pos*ZOOMX, Screen_pixels + y*ZOOMY*VIDEO_LINE_WIDTH + x_pos*ZOOMX, width*ZOOMX*Main_magnifier_factor); - y++; - if(y==end_y_pos) - { - return; - } - } - src += brush_width; - } - // ATTENTION zone jamais atteinte -} - -void Display_brush_mono_zoom_quad(word x_pos, word y_pos, - word x_offset, word y_offset, - word width, // width non zoomée - word end_y_pos, - byte transp_color, byte color, - word brush_width, // width réelle de la brosse - byte * buffer -) - -{ - byte* src = Brush + y_offset * brush_width + x_offset; - int y=y_pos*ZOOMY; - - //Pour chaque ligne à zoomer : - while(1) - { - int bx; - // src = Ligne originale - // On éclate la ligne - Zoom_a_line(src,buffer,Main_magnifier_factor,width); - - // On affiche la ligne Facteur fois à l'écran (sur des - // lignes consécutives) - bx = Main_magnifier_factor*ZOOMY; - - // Pour chaque ligne écran - do - { - // On affiche la ligne zoomée - Display_transparent_mono_line_on_screen_quad( - x_pos, y, width * Main_magnifier_factor, - buffer, transp_color, color - ); - // On passe à la ligne suivante - y++; - // On vérifie qu'on est pas à la ligne finale - if(y == end_y_pos*ZOOMY) - { - Update_rect( x_pos, y_pos, - width * Main_magnifier_factor, end_y_pos - y_pos ); - return; - } - bx --; - } - while (bx > 0); - - // Passage à la ligne suivante dans la brosse aussi - src+=brush_width; - } -} - -void Clear_brush_scaled_quad(word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,__attribute__((unused)) byte transp_color,word image_width,byte * buffer) -{ - - // En fait on va recopier l'image non zoomée dans la partie zoomée ! - byte* src = Main_screen + y_offset * image_width + x_offset; - int y = y_pos; - int bx; - - // Pour chaque ligne à zoomer - while(1){ - Zoom_a_line(src,buffer,Main_magnifier_factor*ZOOMX,width); - - bx=Main_magnifier_factor; - - // Pour chaque ligne - do{ - // TODO a verifier - Display_line_on_screen_fast_quad(x_pos,y, - width * Main_magnifier_factor,buffer); - - // Ligne suivante - y++; - if(y==end_y_pos) - { - Update_rect(x_pos,y_pos, - width*Main_magnifier_factor,end_y_pos-y_pos); - return; - } - bx--; - }while(bx!=0); - - src+= image_width; - } -} - - +/* Grafx2 - The Ultimate 256-color bitmap paint program + + Copyright 2008 Yves Rizoud + Copyright 2008 Franck Charlet + Copyright 2007 Adrien Destugues + Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) + + Grafx2 is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 + of the License. + + Grafx2 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grafx2; if not, see +*/ + +#include +#include +#include +#include "global.h" +#include "sdlscreen.h" +#include "misc.h" +#include "graph.h" +#include "pxquad.h" + +#define ZOOMX 4 +#define ZOOMY 4 + +void Pixel_quad (word x,word y,byte color) +/* Affiche un pixel de la color aux coords x;y à l'écran */ +{ + *(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH)=color; + *(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH + 1)=color; + *(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH + 2)=color; + *(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH + 3)=color; + *(Screen_pixels + x * ZOOMX + (y*ZOOMY+1) * VIDEO_LINE_WIDTH)=color; + *(Screen_pixels + x * ZOOMX + (y*ZOOMY+1) * VIDEO_LINE_WIDTH + 1)=color; + *(Screen_pixels + x * ZOOMX + (y*ZOOMY+1) * VIDEO_LINE_WIDTH + 2)=color; + *(Screen_pixels + x * ZOOMX + (y*ZOOMY+1) * VIDEO_LINE_WIDTH + 3)=color; + *(Screen_pixels + x * ZOOMX + (y*ZOOMY+2) * VIDEO_LINE_WIDTH)=color; + *(Screen_pixels + x * ZOOMX + (y*ZOOMY+2) * VIDEO_LINE_WIDTH + 1)=color; + *(Screen_pixels + x * ZOOMX + (y*ZOOMY+2) * VIDEO_LINE_WIDTH + 2)=color; + *(Screen_pixels + x * ZOOMX + (y*ZOOMY+2) * VIDEO_LINE_WIDTH + 3)=color; + *(Screen_pixels + x * ZOOMX + (y*ZOOMY+3) * VIDEO_LINE_WIDTH)=color; + *(Screen_pixels + x * ZOOMX + (y*ZOOMY+3) * VIDEO_LINE_WIDTH + 1)=color; + *(Screen_pixels + x * ZOOMX + (y*ZOOMY+3) * VIDEO_LINE_WIDTH + 2)=color; + *(Screen_pixels + x * ZOOMX + (y*ZOOMY+3) * VIDEO_LINE_WIDTH + 3)=color; +} + +byte Read_pixel_quad (word x,word y) +/* On retourne la couleur du pixel aux coords données */ +{ + return *( Screen_pixels + y * ZOOMY * VIDEO_LINE_WIDTH + x * ZOOMX); +} + +void Block_quad (word start_x,word start_y,word width,word height,byte color) +/* On affiche un rectangle de la couleur donnée */ +{ + SDL_Rect rectangle; + rectangle.x=start_x*ZOOMX; + rectangle.y=start_y*ZOOMY; + rectangle.w=width*ZOOMX; + rectangle.h=height*ZOOMY; + SDL_FillRect(Screen_SDL,&rectangle,color); +} + +void Display_part_of_screen_quad (word width,word height,word image_width) +/* Afficher une partie de l'image telle quelle sur l'écran */ +{ + byte* dest=Screen_pixels; //On va se mettre en 0,0 dans l'écran (dest) + byte* src=Main_offset_Y*image_width+Main_offset_X+Main_screen; //Coords de départ ds la source (src) + int y; + int dy; + + for(y=height;y!=0;y--) + // Pour chaque ligne + { + // On fait une copie de la ligne + for (dy=width;dy>0;dy--) + { + *(dest+3)=*(dest+2)=*(dest+1)=*dest=*src; + src++; + dest+=ZOOMX; + } + // On double la ligne qu'on vient de copier + memcpy(dest-width*ZOOMX+VIDEO_LINE_WIDTH,dest-width*ZOOMX,width*ZOOMX); + // On la triple + memcpy(dest-width*ZOOMX+2*VIDEO_LINE_WIDTH,dest-width*ZOOMX,width*ZOOMX); + // On la quadruple + memcpy(dest-width*ZOOMX+3*VIDEO_LINE_WIDTH,dest-width*ZOOMX,width*ZOOMX); + + // On passe à la ligne suivante + src+=image_width-width; + dest+=VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX; + } + //Update_rect(0,0,width,height); +} + +void Pixel_preview_normal_quad (word x,word y,byte color) +/* Affichage d'un pixel dans l'écran, par rapport au décalage de l'image + * dans l'écran, en mode normal (pas en mode loupe) + * Note: si on modifie cette procédure, il faudra penser à faire également + * la modif dans la procédure Pixel_Preview_Loupe_SDL. */ +{ +// if(x-Main_offset_X >= 0 && y - Main_offset_Y >= 0) + Pixel_quad(x-Main_offset_X,y-Main_offset_Y,color); +} + +void Pixel_preview_magnifier_quad (word x,word y,byte color) +{ + // Affiche le pixel dans la partie non zoomée + Pixel_quad(x-Main_offset_X,y-Main_offset_Y,color); + + // Regarde si on doit aussi l'afficher dans la partie zoomée + if (y >= Limit_top_zoom && y <= Limit_visible_bottom_zoom + && x >= Limit_left_zoom && x <= Limit_visible_right_zoom) + { + // On est dedans + int height; + int y_zoom = Main_magnifier_factor * (y-Main_magnifier_offset_Y); + + if (Menu_Y - y_zoom < Main_magnifier_factor) + // On ne doit dessiner qu'un morceau du pixel + // sinon on dépasse sur le menu + height = Menu_Y - y_zoom; + else + height = Main_magnifier_factor; + + Block_quad( + Main_magnifier_factor * (x-Main_magnifier_offset_X) + Main_X_zoom, + y_zoom, Main_magnifier_factor, height, color + ); + } +} + +void Horizontal_XOR_line_quad(word x_pos,word y_pos,word width) +{ + //On calcule la valeur initiale de dest: + byte* dest=y_pos*ZOOMY*VIDEO_LINE_WIDTH+x_pos*ZOOMX+Screen_pixels; + + int x; + + for (x=0;x0;i--) + { + *(dest+3*VIDEO_LINE_WIDTH+3)=*(dest+3*VIDEO_LINE_WIDTH+2)=*(dest+3*VIDEO_LINE_WIDTH+1)=*(dest+3*VIDEO_LINE_WIDTH)=*(dest+2*VIDEO_LINE_WIDTH+3)=*(dest+2*VIDEO_LINE_WIDTH+2)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+3)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+3)=*(dest+2)=*(dest+1)=*(dest)=~*(dest); + dest+=VIDEO_LINE_WIDTH*ZOOMY; + } +} + +void Display_brush_color_quad(word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width) +{ + // dest = Position à l'écran + byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX; + // src = Position dans la brosse + byte* src = Brush + y_offset * brush_width + x_offset; + + word x,y; + + // Pour chaque ligne + for(y = height;y > 0; y--) + { + // Pour chaque pixel + for(x = width;x > 0; x--) + { + // On vérifie que ce n'est pas la transparence + if(*src != transp_color) + { + *(dest+3*VIDEO_LINE_WIDTH+3) = *(dest+3*VIDEO_LINE_WIDTH+2) = *(dest+3*VIDEO_LINE_WIDTH+1) = *(dest+3*VIDEO_LINE_WIDTH) = *(dest+2*VIDEO_LINE_WIDTH+3) = *(dest+2*VIDEO_LINE_WIDTH+2) = *(dest+2*VIDEO_LINE_WIDTH+1) = *(dest+2*VIDEO_LINE_WIDTH) = *(dest+VIDEO_LINE_WIDTH+3) = *(dest+VIDEO_LINE_WIDTH+2) = *(dest+VIDEO_LINE_WIDTH+1) = *(dest+VIDEO_LINE_WIDTH) = *(dest+3) = *(dest+2) = *(dest+1) = *dest = *src; + } + + // Pixel suivant + src++; + dest+=ZOOMX; + } + + // On passe à la ligne suivante + dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX; + src = src + brush_width - width; + } + Update_rect(x_pos,y_pos,width,height); +} + +void Display_brush_mono_quad(word x_pos, word y_pos, + word x_offset, word y_offset, word width, word height, + byte transp_color, byte color, word brush_width) +/* On affiche la brosse en monochrome */ +{ + byte* dest=y_pos*ZOOMY*VIDEO_LINE_WIDTH+x_pos*ZOOMX+Screen_pixels; // dest = adr destination à + // l'écran + byte* src=brush_width*y_offset+x_offset+Brush; // src = adr ds + // la brosse + int x,y; + + for(y=height;y!=0;y--) + //Pour chaque ligne + { + for(x=width;x!=0;x--) + //Pour chaque pixel + { + if (*src!=transp_color) + *(dest+3*VIDEO_LINE_WIDTH+3)=*(dest+3*VIDEO_LINE_WIDTH+2)=*(dest+3*VIDEO_LINE_WIDTH+1)=*(dest+3*VIDEO_LINE_WIDTH)=*(dest+2*VIDEO_LINE_WIDTH+3)=*(dest+2*VIDEO_LINE_WIDTH+2)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+3)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+3)=*(dest+2)=*(dest+1)=*dest=color; + + // On passe au pixel suivant + src++; + dest+=ZOOMX; + } + + // On passe à la ligne suivante + src+=brush_width-width; + dest+=VIDEO_LINE_WIDTH*ZOOMY-width*ZOOMX; + } + Update_rect(x_pos,y_pos,width,height); +} + +void Clear_brush_quad(word x_pos,word y_pos,__attribute__((unused)) word x_offset,__attribute__((unused)) word y_offset,word width,word height,__attribute__((unused))byte transp_color,word image_width) +{ + byte* dest=Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH; //On va se mettre en 0,0 dans l'écran (dest) + byte* src = ( y_pos + Main_offset_Y ) * image_width + x_pos + Main_offset_X + Main_screen; //Coords de départ ds la source (src) + int y; + int x; + + for(y=height;y!=0;y--) + // Pour chaque ligne + { + for(x=width;x!=0;x--) + //Pour chaque pixel + { + *(dest+3*VIDEO_LINE_WIDTH+3)=*(dest+3*VIDEO_LINE_WIDTH+2)=*(dest+3*VIDEO_LINE_WIDTH+1)=*(dest+3*VIDEO_LINE_WIDTH)=*(dest+2*VIDEO_LINE_WIDTH+3)=*(dest+2*VIDEO_LINE_WIDTH+2)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+3)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+3)=*(dest+2)=*(dest+1)=*dest=*src; + + // On passe au pixel suivant + src++; + dest+=ZOOMX; + } + + // On passe à la ligne suivante + src+=image_width-width; + dest+=VIDEO_LINE_WIDTH*ZOOMY-width*ZOOMX; + } + Update_rect(x_pos,y_pos,width,height); +} + +// Affiche une brosse (arbitraire) à l'écran +void Display_brush_quad(byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width) +{ + // dest = Position à l'écran + byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX; + // src = Position dans la brosse + byte* src = brush + y_offset * brush_width + x_offset; + + word x,y; + + // Pour chaque ligne + for(y = height;y > 0; y--) + { + // Pour chaque pixel + for(x = width;x > 0; x--) + { + // On vérifie que ce n'est pas la transparence + if(*src != transp_color) + { + *(dest+3*VIDEO_LINE_WIDTH+3)=*(dest+3*VIDEO_LINE_WIDTH+2)=*(dest+3*VIDEO_LINE_WIDTH+1)=*(dest+3*VIDEO_LINE_WIDTH)=*(dest+2*VIDEO_LINE_WIDTH+3)=*(dest+2*VIDEO_LINE_WIDTH+2)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+3)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+3)=*(dest+2)=*(dest+1)=*dest=*src; + } + + // Pixel suivant + src++; dest+=ZOOMX; + } + + // On passe à la ligne suivante + dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX; + src = src + brush_width - width; + } +} + +void Remap_screen_quad(word x_pos,word y_pos,word width,word height,byte * conversion_table) +{ + // dest = coords a l'écran + byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX; + int x,y; + + // Pour chaque ligne + for(y=height;y>0;y--) + { + // Pour chaque pixel + for(x=width;x>0;x--) + { + *(dest+3*VIDEO_LINE_WIDTH+3)=*(dest+3*VIDEO_LINE_WIDTH+2)=*(dest+3*VIDEO_LINE_WIDTH+1)=*(dest+3*VIDEO_LINE_WIDTH)=*(dest+2*VIDEO_LINE_WIDTH+3)=*(dest+2*VIDEO_LINE_WIDTH+2)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+3)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+3)=*(dest+2)=*(dest+1)=*dest= + conversion_table[*dest]; + dest +=ZOOMX; + } + + dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX; + } + + Update_rect(x_pos,y_pos,width,height); +} + +void Display_line_on_screen_fast_quad(word x_pos,word y_pos,word width,byte * line) +/* On affiche toute une ligne de pixels telle quelle. */ +/* Utilisée si le buffer contient déja des pixel doublés. */ +{ + memcpy(Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH,line,width*ZOOMX); + memcpy(Screen_pixels+x_pos*ZOOMX+(y_pos*ZOOMY+1)*VIDEO_LINE_WIDTH,line,width*ZOOMX); + memcpy(Screen_pixels+x_pos*ZOOMX+(y_pos*ZOOMY+2)*VIDEO_LINE_WIDTH,line,width*ZOOMX); + memcpy(Screen_pixels+x_pos*ZOOMX+(y_pos*ZOOMY+3)*VIDEO_LINE_WIDTH,line,width*ZOOMX); +} + +void Display_line_on_screen_quad(word x_pos,word y_pos,word width,byte * line) +/* On affiche une ligne de pixels en les doublant. */ +{ + int x; + byte *dest; + dest=Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH; + for(x=width;x>0;x--) + { + *(dest+3*VIDEO_LINE_WIDTH+3)=*(dest+3*VIDEO_LINE_WIDTH+2)=*(dest+3*VIDEO_LINE_WIDTH+1)=*(dest+3*VIDEO_LINE_WIDTH)=*(dest+2*VIDEO_LINE_WIDTH+3)=*(dest+2*VIDEO_LINE_WIDTH+2)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+3)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+3)=*(dest+2)=*(dest+1)=*dest=*line; + dest+=ZOOMX; + line++; + } +} +void Display_transparent_mono_line_on_screen_quad( + word x_pos, word y_pos, word width, byte* line, + byte transp_color, byte color) +// Affiche une ligne à l'écran avec une couleur + transparence. +// Utilisé par les brosses en mode zoom +{ + byte* dest = Screen_pixels+ y_pos*VIDEO_LINE_WIDTH + x_pos*ZOOMX; + int x; + // Pour chaque pixel + for(x=0;x 0); + src += image_width; + } +// ATTENTION on n'arrive jamais ici ! +} + +// Affiche une partie de la brosse couleur zoomée +void Display_brush_color_zoom_quad(word x_pos,word y_pos, + word x_offset,word y_offset, + word width, // width non zoomée + word end_y_pos,byte transp_color, + word brush_width, // width réelle de la brosse + byte * buffer) +{ + byte* src = Brush+y_offset*brush_width + x_offset; + word y = y_pos; + byte bx; + + // Pour chaque ligne + while(1) + { + Zoom_a_line(src,buffer,Main_magnifier_factor,width); + // On affiche facteur fois la ligne zoomée + for(bx=Main_magnifier_factor;bx>0;bx--) + { + byte* line_src = buffer; + byte* dest = Screen_pixels + y*ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX; + word x; + // Pour chaque pixel de la ligne + for(x = width*Main_magnifier_factor;x > 0;x--) + { + if(*line_src!=transp_color) + { + *(dest+3)=*(dest+2)=*(dest+1)=*dest = *line_src; + } + line_src++; + dest+=ZOOMX; + } + // Double the line + memcpy(Screen_pixels + (y*ZOOMY+1)*VIDEO_LINE_WIDTH + x_pos*ZOOMX, Screen_pixels + y*ZOOMY*VIDEO_LINE_WIDTH + x_pos*ZOOMX, width*ZOOMX*Main_magnifier_factor); + // Triple the line + memcpy(Screen_pixels + (y*ZOOMY+2)*VIDEO_LINE_WIDTH + x_pos*ZOOMX, Screen_pixels + y*ZOOMY*VIDEO_LINE_WIDTH + x_pos*ZOOMX, width*ZOOMX*Main_magnifier_factor); + // Quadruple it + memcpy(Screen_pixels + (y*ZOOMY+3)*VIDEO_LINE_WIDTH + x_pos*ZOOMX, Screen_pixels + y*ZOOMY*VIDEO_LINE_WIDTH + x_pos*ZOOMX, width*ZOOMX*Main_magnifier_factor); + y++; + if(y==end_y_pos) + { + return; + } + } + src += brush_width; + } + // ATTENTION zone jamais atteinte +} + +void Display_brush_mono_zoom_quad(word x_pos, word y_pos, + word x_offset, word y_offset, + word width, // width non zoomée + word end_y_pos, + byte transp_color, byte color, + word brush_width, // width réelle de la brosse + byte * buffer +) + +{ + byte* src = Brush + y_offset * brush_width + x_offset; + int y=y_pos*ZOOMY; + + //Pour chaque ligne à zoomer : + while(1) + { + int bx; + // src = Ligne originale + // On éclate la ligne + Zoom_a_line(src,buffer,Main_magnifier_factor,width); + + // On affiche la ligne Facteur fois à l'écran (sur des + // lignes consécutives) + bx = Main_magnifier_factor*ZOOMY; + + // Pour chaque ligne écran + do + { + // On affiche la ligne zoomée + Display_transparent_mono_line_on_screen_quad( + x_pos, y, width * Main_magnifier_factor, + buffer, transp_color, color + ); + // On passe à la ligne suivante + y++; + // On vérifie qu'on est pas à la ligne finale + if(y == end_y_pos*ZOOMY) + { + Redraw_grid( x_pos, y_pos, + width * Main_magnifier_factor, end_y_pos - y_pos ); + Update_rect( x_pos, y_pos, + width * Main_magnifier_factor, end_y_pos - y_pos ); + return; + } + bx --; + } + while (bx > 0); + + // Passage à la ligne suivante dans la brosse aussi + src+=brush_width; + } +} + +void Clear_brush_scaled_quad(word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,__attribute__((unused)) byte transp_color,word image_width,byte * buffer) +{ + + // En fait on va recopier l'image non zoomée dans la partie zoomée ! + byte* src = Main_screen + y_offset * image_width + x_offset; + int y = y_pos; + int bx; + + // Pour chaque ligne à zoomer + while(1){ + Zoom_a_line(src,buffer,Main_magnifier_factor*ZOOMX,width); + + bx=Main_magnifier_factor; + + // Pour chaque ligne + do{ + // TODO a verifier + Display_line_on_screen_fast_quad(x_pos,y, + width * Main_magnifier_factor,buffer); + + // Ligne suivante + y++; + if(y==end_y_pos) + { + Redraw_grid(x_pos,y_pos, + width*Main_magnifier_factor,end_y_pos-y_pos); + Update_rect(x_pos,y_pos, + width*Main_magnifier_factor,end_y_pos-y_pos); + return; + } + bx--; + }while(bx!=0); + + src+= image_width; + } +} + + diff --git a/pxquad.h b/pxquad.h index e5618472..66ed0713 100644 --- a/pxquad.h +++ b/pxquad.h @@ -1,48 +1,48 @@ -/* Grafx2 - The Ultimate 256-color bitmap paint program - - Copyright 2008 Yves Rizoud - Copyright 2007 Adrien Destugues - Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) - - Grafx2 is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; version 2 - of the License. - - Grafx2 is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Grafx2; if not, see -*/ - -////////////////////////////////////////////////////////////////////////////// -///@file pxquad.h -/// Renderer for quadruple pixels (4x4). -////////////////////////////////////////////////////////////////////////////// - -#include "struct.h" - - void Pixel_quad (word x,word y,byte color); - byte Read_pixel_quad (word x,word y); - void Block_quad (word start_x,word start_y,word width,word height,byte color); - void Pixel_preview_normal_quad (word x,word y,byte color); - void Pixel_preview_magnifier_quad (word x,word y,byte color); - void Horizontal_XOR_line_quad (word x_pos,word y_pos,word width); - void Vertical_XOR_line_quad (word x_pos,word y_pos,word height); - void Display_brush_color_quad (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width); - void Display_brush_mono_quad (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,byte color,word brush_width); - void Clear_brush_quad (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word image_width); - void Remap_screen_quad (word x_pos,word y_pos,word width,word height,byte * conversion_table); - void Display_part_of_screen_quad (word width,word height,word image_width); - void Display_line_on_screen_quad (word x_pos,word y_pos,word width,byte * line); - void Read_line_screen_quad (word x_pos,word y_pos,word width,byte * line); - void Display_part_of_screen_scaled_quad(word width,word height,word image_width,byte * buffer); - void Display_brush_color_zoom_quad (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,word brush_width,byte * buffer); - void Display_brush_mono_zoom_quad (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,byte color,word brush_width,byte * buffer); - void Clear_brush_scaled_quad (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,word image_width,byte * buffer); - void Display_brush_quad (byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width); - - void Display_line_on_screen_fast_quad (word x_pos,word y_pos,word width,byte * line); +/* Grafx2 - The Ultimate 256-color bitmap paint program + + Copyright 2008 Yves Rizoud + Copyright 2007 Adrien Destugues + Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) + + Grafx2 is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 + of the License. + + Grafx2 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grafx2; if not, see +*/ + +////////////////////////////////////////////////////////////////////////////// +///@file pxquad.h +/// Renderer for quadruple pixels (4x4). +////////////////////////////////////////////////////////////////////////////// + +#include "struct.h" + + void Pixel_quad (word x,word y,byte color); + byte Read_pixel_quad (word x,word y); + void Block_quad (word start_x,word start_y,word width,word height,byte color); + void Pixel_preview_normal_quad (word x,word y,byte color); + void Pixel_preview_magnifier_quad (word x,word y,byte color); + void Horizontal_XOR_line_quad (word x_pos,word y_pos,word width); + void Vertical_XOR_line_quad (word x_pos,word y_pos,word height); + void Display_brush_color_quad (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width); + void Display_brush_mono_quad (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,byte color,word brush_width); + void Clear_brush_quad (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word image_width); + void Remap_screen_quad (word x_pos,word y_pos,word width,word height,byte * conversion_table); + void Display_part_of_screen_quad (word width,word height,word image_width); + void Display_line_on_screen_quad (word x_pos,word y_pos,word width,byte * line); + void Read_line_screen_quad (word x_pos,word y_pos,word width,byte * line); + void Display_part_of_screen_scaled_quad(word width,word height,word image_width,byte * buffer); + void Display_brush_color_zoom_quad (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,word brush_width,byte * buffer); + void Display_brush_mono_zoom_quad (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,byte color,word brush_width,byte * buffer); + void Clear_brush_scaled_quad (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,word image_width,byte * buffer); + void Display_brush_quad (byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width); + + void Display_line_on_screen_fast_quad (word x_pos,word y_pos,word width,byte * line); diff --git a/pxsimple.c b/pxsimple.c index c18020f0..f7bfdebb 100644 --- a/pxsimple.c +++ b/pxsimple.c @@ -1,470 +1,475 @@ -/* Grafx2 - The Ultimate 256-color bitmap paint program - - Copyright 2008 Yves Rizoud - Copyright 2008 Franck Charlet - Copyright 2007 Adrien Destugues - Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) - - Grafx2 is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; version 2 - of the License. - - Grafx2 is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Grafx2; if not, see -*/ - -#include -#include -#include -#include "global.h" -#include "sdlscreen.h" -#include "misc.h" -#include "pxsimple.h" - -void Pixel_simple (word x,word y,byte color) -/* Affiche un pixel de la color aux coords x;y à l'écran */ -{ - *(Screen_pixels + x + y * VIDEO_LINE_WIDTH)=color; -} - -byte Read_pixel_simple (word x,word y) -/* On retourne la couleur du pixel aux coords données */ -{ - return *( Screen_pixels + y * VIDEO_LINE_WIDTH + x ); -} - -void Block_simple (word start_x,word start_y,word width,word height,byte color) -/* On affiche un rectangle de la couleur donnée */ -{ - SDL_Rect rectangle; - rectangle.x=start_x; - rectangle.y=start_y; - rectangle.w=width; - rectangle.h=height; - SDL_FillRect(Screen_SDL,&rectangle,color); -} - -void Display_part_of_screen_simple (word width,word height,word image_width) -/* Afficher une partie de l'image telle quelle sur l'écran */ -{ - byte* dest=Screen_pixels; //On va se mettre en 0,0 dans l'écran (dest) - byte* src=Main_offset_Y*image_width+Main_offset_X+Main_screen; //Coords de départ ds la source (src) - int y; - - for(y=height;y!=0;y--) - // Pour chaque ligne - { - // On fait une copie de la ligne - memcpy(dest,src,width); - - // On passe à la ligne suivante - src+=image_width; - dest+=VIDEO_LINE_WIDTH; - } - //Update_rect(0,0,width,height); -} - -void Pixel_preview_normal_simple (word x,word y,byte color) -/* Affichage d'un pixel dans l'écran, par rapport au décalage de l'image - * dans l'écran, en mode normal (pas en mode loupe) - * Note: si on modifie cette procédure, il faudra penser à faire également - * la modif dans la procédure Pixel_Preview_Loupe_SDL. */ -{ -// if(x-Main_offset_X >= 0 && y - Main_offset_Y >= 0) - Pixel_simple(x-Main_offset_X,y-Main_offset_Y,color); -} - -void Pixel_preview_magnifier_simple (word x,word y,byte color) -{ - // Affiche le pixel dans la partie non zoomée - Pixel_simple(x-Main_offset_X,y-Main_offset_Y,color); - - // Regarde si on doit aussi l'afficher dans la partie zoomée - if (y >= Limit_top_zoom && y <= Limit_visible_bottom_zoom - && x >= Limit_left_zoom && x <= Limit_visible_right_zoom) - { - // On est dedans - int height; - int y_zoom = Main_magnifier_factor * (y-Main_magnifier_offset_Y); - - if (Menu_Y - y_zoom < Main_magnifier_factor) - // On ne doit dessiner qu'un morceau du pixel - // sinon on dépasse sur le menu - height = Menu_Y - y_zoom; - else - height = Main_magnifier_factor; - - Block_simple( - Main_magnifier_factor * (x-Main_magnifier_offset_X) + Main_X_zoom, - y_zoom, Main_magnifier_factor, height, color - ); - } -} - -void Horizontal_XOR_line_simple(word x_pos,word y_pos,word width) -{ - //On calcule la valeur initiale de dest: - byte* dest=y_pos*VIDEO_LINE_WIDTH+x_pos+Screen_pixels; - - int x; - - for (x=0;x 0; y--) - { - // Pour chaque pixel - for(x = width;x > 0; x--) - { - // On vérifie que ce n'est pas la transparence - if(*src != transp_color) - { - *dest = *src; - } - - // Pixel suivant - src++; dest++; - } - - // On passe à la ligne suivante - dest = dest + VIDEO_LINE_WIDTH - width; - src = src + brush_width - width; - } - Update_rect(x_pos,y_pos,width,height); -} - -void Display_brush_mono_simple(word x_pos, word y_pos, - word x_offset, word y_offset, word width, word height, - byte transp_color, byte color, word brush_width) -/* On affiche la brosse en monochrome */ -{ - byte* dest=y_pos*VIDEO_LINE_WIDTH+x_pos+Screen_pixels; // dest = adr Destination à - // l'écran - byte* src=brush_width*y_offset+x_offset+Brush; // src = adr ds - // la brosse - int x,y; - - for(y=height;y!=0;y--) - //Pour chaque ligne - { - for(x=width;x!=0;x--) - //Pour chaque pixel - { - if (*src!=transp_color) - *dest=color; - - // On passe au pixel suivant - src++; - dest++; - } - - // On passe à la ligne suivante - src+=brush_width-width; - dest+=VIDEO_LINE_WIDTH-width; - } - Update_rect(x_pos,y_pos,width,height); -} - -void Clear_brush_simple(word x_pos,word y_pos,__attribute__((unused)) word x_offset,__attribute__((unused)) word y_offset,word width,word height,__attribute__((unused))byte transp_color,word image_width) -{ - byte* dest=Screen_pixels+x_pos+y_pos*VIDEO_LINE_WIDTH; //On va se mettre en 0,0 dans l'écran (dest) - byte* src = ( y_pos + Main_offset_Y ) * image_width + x_pos + Main_offset_X + Main_screen; //Coords de départ ds la source (src) - int y; - - for(y=height;y!=0;y--) - // Pour chaque ligne - { - // On fait une copie de la ligne - memcpy(dest,src,width); - - // On passe à la ligne suivante - src+=image_width; - dest+=VIDEO_LINE_WIDTH; - } - Update_rect(x_pos,y_pos,width,height); -} - -// Affiche une brosse (arbitraire) à l'écran -void Display_brush_simple(byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width) -{ - // dest = Position à l'écran - byte* dest = Screen_pixels + y_pos * VIDEO_LINE_WIDTH + x_pos; - // src = Position dans la brosse - byte* src = brush + y_offset * brush_width + x_offset; - - word x,y; - - // Pour chaque ligne - for(y = height;y > 0; y--) - { - // Pour chaque pixel - for(x = width;x > 0; x--) - { - // On vérifie que ce n'est pas la transparence - if(*src != transp_color) - { - *dest = *src; - } - - // Pixel suivant - src++; dest++; - } - - // On passe à la ligne suivante - dest = dest + VIDEO_LINE_WIDTH - width; - src = src + brush_width - width; - } -} - -void Remap_screen_simple(word x_pos,word y_pos,word width,word height,byte * conversion_table) -{ - // dest = coords a l'écran - byte* dest = Screen_pixels + y_pos * VIDEO_LINE_WIDTH + x_pos; - int x,y; - - // Pour chaque ligne - for(y=height;y>0;y--) - { - // Pour chaque pixel - for(x=width;x>0;x--) - { - *dest = conversion_table[*dest]; - dest ++; - } - - dest = dest + VIDEO_LINE_WIDTH - width; - } - - Update_rect(x_pos,y_pos,width,height); -} - -void Display_line_on_screen_simple(word x_pos,word y_pos,word width,byte * line) -/* On affiche toute une ligne de pixels. Utilisé pour les textes. */ -{ - memcpy(Screen_pixels+x_pos+y_pos*VIDEO_LINE_WIDTH,line,width); -} - -void Display_transparent_mono_line_on_screen_simple( - word x_pos, word y_pos, word width, byte* line, - byte transp_color, byte color) -// Affiche une ligne à l'écran avec une couleur + transparence. -// Utilisé par les brosses en mode zoom -{ - byte* dest = Screen_pixels+ y_pos * VIDEO_LINE_WIDTH + x_pos; - int x; - // Pour chaque pixel - for(x=0;x 0); - src += image_width; - } -// ATTENTION on n'arrive jamais ici ! -} - -void Display_transparent_line_on_screen_simple(word x_pos,word y_pos,word width,byte* line,byte transp_color) -{ - byte* src = line; - byte* dest = Screen_pixels + y_pos * VIDEO_LINE_WIDTH + x_pos; - - word x; - - // Pour chaque pixel de la ligne - for(x = width;x > 0;x--) - { - if(*src!=transp_color) - *dest = *src; - src++; - dest++; - } -} - -// Affiche une partie de la brosse couleur zoomée -void Display_brush_color_zoom_simple(word x_pos,word y_pos, - word x_offset,word y_offset, - word width, // width non zoomée - word end_y_pos,byte transp_color, - word brush_width, // width réelle de la brosse - byte * buffer) -{ - byte* src = Brush+y_offset*brush_width + x_offset; - word y = y_pos; - byte bx; - - // Pour chaque ligne - while(1) - { - Zoom_a_line(src,buffer,Main_magnifier_factor,width); - // On affiche facteur fois la ligne zoomée - for(bx=Main_magnifier_factor;bx>0;bx--) - { - Display_transparent_line_on_screen_simple(x_pos,y,width*Main_magnifier_factor,buffer,transp_color); - y++; - if(y==end_y_pos) - { - return; - } - } - src += brush_width; - } - // ATTENTION zone jamais atteinte -} - -void Display_brush_mono_zoom_simple(word x_pos, word y_pos, - word x_offset, word y_offset, - word width, // width non zoomée - word end_y_pos, - byte transp_color, byte color, - word brush_width, // width réelle de la brosse - byte * buffer -) - -{ - byte* src = Brush + y_offset * brush_width + x_offset; - int y=y_pos; - - //Pour chaque ligne à zoomer : - while(1) - { - int bx; - // src = Ligne originale - // On éclate la ligne - Zoom_a_line(src,buffer,Main_magnifier_factor,width); - - // On affiche la ligne Facteur fois à l'écran (sur des - // lignes consécutives) - bx = Main_magnifier_factor; - - // Pour chaque ligne écran - do - { - // On affiche la ligne zoomée - Display_transparent_mono_line_on_screen_simple( - x_pos, y, width * Main_magnifier_factor, - buffer, transp_color, color - ); - // On passe à la ligne suivante - y++; - // On vérifie qu'on est pas à la ligne finale - if(y == end_y_pos) - { - Update_rect( x_pos, y_pos, - width * Main_magnifier_factor, end_y_pos - y_pos ); - return; - } - bx --; - } - while (bx > 0); - - // Passage à la ligne suivante dans la brosse aussi - src+=brush_width; - } -} - -void Clear_brush_scaled_simple(word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,__attribute__((unused)) byte transp_color,word image_width,byte * buffer) -{ - // En fait on va recopier l'image non zoomée dans la partie zoomée ! - byte* src = Main_screen + y_offset * image_width + x_offset; - int y = y_pos; - int bx; - - // Pour chaque ligne à zoomer - while(1){ - Zoom_a_line(src,buffer,Main_magnifier_factor,width); - - bx=Main_magnifier_factor; - - // Pour chaque ligne - do{ - Display_line_on_screen_simple(x_pos,y, - width * Main_magnifier_factor,buffer); - - // Ligne suivante - y++; - if(y==end_y_pos) - { - Update_rect(x_pos,y_pos, - width*Main_magnifier_factor,end_y_pos-y_pos); - return; - } - bx--; - }while(bx!=0); - - src+= image_width; - } -} - - +/* Grafx2 - The Ultimate 256-color bitmap paint program + + Copyright 2008 Yves Rizoud + Copyright 2008 Franck Charlet + Copyright 2007 Adrien Destugues + Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) + + Grafx2 is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 + of the License. + + Grafx2 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grafx2; if not, see +*/ + +#include +#include +#include +#include "global.h" +#include "sdlscreen.h" +#include "misc.h" +#include "graph.h" +#include "pxsimple.h" + +void Pixel_simple (word x,word y,byte color) +/* Affiche un pixel de la color aux coords x;y à l'écran */ +{ + *(Screen_pixels + x + y * VIDEO_LINE_WIDTH)=color; +} + +byte Read_pixel_simple (word x,word y) +/* On retourne la couleur du pixel aux coords données */ +{ + return *( Screen_pixels + y * VIDEO_LINE_WIDTH + x ); +} + +void Block_simple (word start_x,word start_y,word width,word height,byte color) +/* On affiche un rectangle de la couleur donnée */ +{ + SDL_Rect rectangle; + rectangle.x=start_x; + rectangle.y=start_y; + rectangle.w=width; + rectangle.h=height; + SDL_FillRect(Screen_SDL,&rectangle,color); +} + +void Display_part_of_screen_simple (word width,word height,word image_width) +/* Afficher une partie de l'image telle quelle sur l'écran */ +{ + byte* dest=Screen_pixels; //On va se mettre en 0,0 dans l'écran (dest) + byte* src=Main_offset_Y*image_width+Main_offset_X+Main_screen; //Coords de départ ds la source (src) + int y; + + for(y=height;y!=0;y--) + // Pour chaque ligne + { + // On fait une copie de la ligne + memcpy(dest,src,width); + + // On passe à la ligne suivante + src+=image_width; + dest+=VIDEO_LINE_WIDTH; + } + //Update_rect(0,0,width,height); +} + +void Pixel_preview_normal_simple (word x,word y,byte color) +/* Affichage d'un pixel dans l'écran, par rapport au décalage de l'image + * dans l'écran, en mode normal (pas en mode loupe) + * Note: si on modifie cette procédure, il faudra penser à faire également + * la modif dans la procédure Pixel_Preview_Loupe_SDL. */ +{ +// if(x-Main_offset_X >= 0 && y - Main_offset_Y >= 0) + Pixel_simple(x-Main_offset_X,y-Main_offset_Y,color); +} + +void Pixel_preview_magnifier_simple (word x,word y,byte color) +{ + // Affiche le pixel dans la partie non zoomée + Pixel_simple(x-Main_offset_X,y-Main_offset_Y,color); + + // Regarde si on doit aussi l'afficher dans la partie zoomée + if (y >= Limit_top_zoom && y <= Limit_visible_bottom_zoom + && x >= Limit_left_zoom && x <= Limit_visible_right_zoom) + { + // On est dedans + int height; + int y_zoom = Main_magnifier_factor * (y-Main_magnifier_offset_Y); + + if (Menu_Y - y_zoom < Main_magnifier_factor) + // On ne doit dessiner qu'un morceau du pixel + // sinon on dépasse sur le menu + height = Menu_Y - y_zoom; + else + height = Main_magnifier_factor; + + Block_simple( + Main_magnifier_factor * (x-Main_magnifier_offset_X) + Main_X_zoom, + y_zoom, Main_magnifier_factor, height, color + ); + } +} + +void Horizontal_XOR_line_simple(word x_pos,word y_pos,word width) +{ + //On calcule la valeur initiale de dest: + byte* dest=y_pos*VIDEO_LINE_WIDTH+x_pos+Screen_pixels; + + int x; + + for (x=0;x 0; y--) + { + // Pour chaque pixel + for(x = width;x > 0; x--) + { + // On vérifie que ce n'est pas la transparence + if(*src != transp_color) + { + *dest = *src; + } + + // Pixel suivant + src++; dest++; + } + + // On passe à la ligne suivante + dest = dest + VIDEO_LINE_WIDTH - width; + src = src + brush_width - width; + } + Update_rect(x_pos,y_pos,width,height); +} + +void Display_brush_mono_simple(word x_pos, word y_pos, + word x_offset, word y_offset, word width, word height, + byte transp_color, byte color, word brush_width) +/* On affiche la brosse en monochrome */ +{ + byte* dest=y_pos*VIDEO_LINE_WIDTH+x_pos+Screen_pixels; // dest = adr Destination à + // l'écran + byte* src=brush_width*y_offset+x_offset+Brush; // src = adr ds + // la brosse + int x,y; + + for(y=height;y!=0;y--) + //Pour chaque ligne + { + for(x=width;x!=0;x--) + //Pour chaque pixel + { + if (*src!=transp_color) + *dest=color; + + // On passe au pixel suivant + src++; + dest++; + } + + // On passe à la ligne suivante + src+=brush_width-width; + dest+=VIDEO_LINE_WIDTH-width; + } + Update_rect(x_pos,y_pos,width,height); +} + +void Clear_brush_simple(word x_pos,word y_pos,__attribute__((unused)) word x_offset,__attribute__((unused)) word y_offset,word width,word height,__attribute__((unused))byte transp_color,word image_width) +{ + byte* dest=Screen_pixels+x_pos+y_pos*VIDEO_LINE_WIDTH; //On va se mettre en 0,0 dans l'écran (dest) + byte* src = ( y_pos + Main_offset_Y ) * image_width + x_pos + Main_offset_X + Main_screen; //Coords de départ ds la source (src) + int y; + + for(y=height;y!=0;y--) + // Pour chaque ligne + { + // On fait une copie de la ligne + memcpy(dest,src,width); + + // On passe à la ligne suivante + src+=image_width; + dest+=VIDEO_LINE_WIDTH; + } + Update_rect(x_pos,y_pos,width,height); +} + +// Affiche une brosse (arbitraire) à l'écran +void Display_brush_simple(byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width) +{ + // dest = Position à l'écran + byte* dest = Screen_pixels + y_pos * VIDEO_LINE_WIDTH + x_pos; + // src = Position dans la brosse + byte* src = brush + y_offset * brush_width + x_offset; + + word x,y; + + // Pour chaque ligne + for(y = height;y > 0; y--) + { + // Pour chaque pixel + for(x = width;x > 0; x--) + { + // On vérifie que ce n'est pas la transparence + if(*src != transp_color) + { + *dest = *src; + } + + // Pixel suivant + src++; dest++; + } + + // On passe à la ligne suivante + dest = dest + VIDEO_LINE_WIDTH - width; + src = src + brush_width - width; + } +} + +void Remap_screen_simple(word x_pos,word y_pos,word width,word height,byte * conversion_table) +{ + // dest = coords a l'écran + byte* dest = Screen_pixels + y_pos * VIDEO_LINE_WIDTH + x_pos; + int x,y; + + // Pour chaque ligne + for(y=height;y>0;y--) + { + // Pour chaque pixel + for(x=width;x>0;x--) + { + *dest = conversion_table[*dest]; + dest ++; + } + + dest = dest + VIDEO_LINE_WIDTH - width; + } + + Update_rect(x_pos,y_pos,width,height); +} + +void Display_line_on_screen_simple(word x_pos,word y_pos,word width,byte * line) +/* On affiche toute une ligne de pixels. Utilisé pour les textes. */ +{ + memcpy(Screen_pixels+x_pos+y_pos*VIDEO_LINE_WIDTH,line,width); +} + +void Display_transparent_mono_line_on_screen_simple( + word x_pos, word y_pos, word width, byte* line, + byte transp_color, byte color) +// Affiche une ligne à l'écran avec une couleur + transparence. +// Utilisé par les brosses en mode zoom +{ + byte* dest = Screen_pixels+ y_pos * VIDEO_LINE_WIDTH + x_pos; + int x; + // Pour chaque pixel + for(x=0;x 0); + src += image_width; + } +// ATTENTION on n'arrive jamais ici ! +} + +void Display_transparent_line_on_screen_simple(word x_pos,word y_pos,word width,byte* line,byte transp_color) +{ + byte* src = line; + byte* dest = Screen_pixels + y_pos * VIDEO_LINE_WIDTH + x_pos; + + word x; + + // Pour chaque pixel de la ligne + for(x = width;x > 0;x--) + { + if(*src!=transp_color) + *dest = *src; + src++; + dest++; + } +} + +// Affiche une partie de la brosse couleur zoomée +void Display_brush_color_zoom_simple(word x_pos,word y_pos, + word x_offset,word y_offset, + word width, // width non zoomée + word end_y_pos,byte transp_color, + word brush_width, // width réelle de la brosse + byte * buffer) +{ + byte* src = Brush+y_offset*brush_width + x_offset; + word y = y_pos; + byte bx; + + // Pour chaque ligne + while(1) + { + Zoom_a_line(src,buffer,Main_magnifier_factor,width); + // On affiche facteur fois la ligne zoomée + for(bx=Main_magnifier_factor;bx>0;bx--) + { + Display_transparent_line_on_screen_simple(x_pos,y,width*Main_magnifier_factor,buffer,transp_color); + y++; + if(y==end_y_pos) + { + return; + } + } + src += brush_width; + } + // ATTENTION zone jamais atteinte +} + +void Display_brush_mono_zoom_simple(word x_pos, word y_pos, + word x_offset, word y_offset, + word width, // width non zoomée + word end_y_pos, + byte transp_color, byte color, + word brush_width, // width réelle de la brosse + byte * buffer +) + +{ + byte* src = Brush + y_offset * brush_width + x_offset; + int y=y_pos; + + //Pour chaque ligne à zoomer : + while(1) + { + int bx; + // src = Ligne originale + // On éclate la ligne + Zoom_a_line(src,buffer,Main_magnifier_factor,width); + + // On affiche la ligne Facteur fois à l'écran (sur des + // lignes consécutives) + bx = Main_magnifier_factor; + + // Pour chaque ligne écran + do + { + // On affiche la ligne zoomée + Display_transparent_mono_line_on_screen_simple( + x_pos, y, width * Main_magnifier_factor, + buffer, transp_color, color + ); + // On passe à la ligne suivante + y++; + // On vérifie qu'on est pas à la ligne finale + if(y == end_y_pos) + { + Redraw_grid( x_pos, y_pos, + width * Main_magnifier_factor, end_y_pos - y_pos ); + Update_rect( x_pos, y_pos, + width * Main_magnifier_factor, end_y_pos - y_pos ); + return; + } + bx --; + } + while (bx > 0); + + // Passage à la ligne suivante dans la brosse aussi + src+=brush_width; + } +} + +void Clear_brush_scaled_simple(word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,__attribute__((unused)) byte transp_color,word image_width,byte * buffer) +{ + // En fait on va recopier l'image non zoomée dans la partie zoomée ! + byte* src = Main_screen + y_offset * image_width + x_offset; + int y = y_pos; + int bx; + + // Pour chaque ligne à zoomer + while(1){ + Zoom_a_line(src,buffer,Main_magnifier_factor,width); + + bx=Main_magnifier_factor; + + // Pour chaque ligne + do{ + Display_line_on_screen_simple(x_pos,y, + width * Main_magnifier_factor,buffer); + + // Ligne suivante + y++; + if(y==end_y_pos) + { + Redraw_grid(x_pos,y_pos, + width*Main_magnifier_factor,end_y_pos-y_pos); + Update_rect(x_pos,y_pos, + width*Main_magnifier_factor,end_y_pos-y_pos); + return; + } + bx--; + }while(bx!=0); + + src+= image_width; + } +} diff --git a/pxsimple.h b/pxsimple.h index 2bca1cb9..785a96a5 100644 --- a/pxsimple.h +++ b/pxsimple.h @@ -1,51 +1,51 @@ -/* Grafx2 - The Ultimate 256-color bitmap paint program - - Copyright 2008 Yves Rizoud - Copyright 2007 Adrien Destugues - Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) - - Grafx2 is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; version 2 - of the License. - - Grafx2 is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Grafx2; if not, see -*/ - -////////////////////////////////////////////////////////////////////////////// -///@file pxsimple.h -/// Renderer for simple pixels (1x1). This is the normal one. -////////////////////////////////////////////////////////////////////////////// - -#include "struct.h" - - void Pixel_simple (word x,word y,byte color); - byte Read_pixel_simple (word x,word y); - void Block_simple (word start_x,word start_y,word width,word height,byte color); - void Pixel_preview_normal_simple (word x,word y,byte color); - void Pixel_preview_magnifier_simple (word x,word y,byte color); - void Horizontal_XOR_line_simple (word x_pos,word y_pos,word width); - void Vertical_XOR_line_simple (word x_pos,word y_pos,word height); - void Display_brush_color_simple (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width); - void Display_brush_mono_simple (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,byte color,word brush_width); - void Clear_brush_simple (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word image_width); - void Remap_screen_simple (word x_pos,word y_pos,word width,word height,byte * conversion_table); - void Display_part_of_screen_simple (word width,word height,word image_width); - void Display_line_on_screen_simple (word x_pos,word y_pos,word width,byte * line); - void Read_line_screen_simple (word x_pos,word y_pos,word width,byte * line); - void Display_part_of_screen_scaled_simple(word width,word height,word image_width,byte * buffer); - void Display_brush_color_zoom_simple (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,word brush_width,byte * buffer); - void Display_brush_mono_zoom_simple (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,byte color,word brush_width,byte * buffer); - void Clear_brush_scaled_simple (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,word image_width,byte * buffer); - void Display_brush_simple (byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width); - -void Display_transparent_mono_line_on_screen_simple( - word x_pos, word y_pos, word width, byte* line, - byte transp_color, byte color); -void Display_transparent_line_on_screen_simple(word x_pos,word y_pos,word width,byte* line,byte transp_color); +/* Grafx2 - The Ultimate 256-color bitmap paint program + + Copyright 2008 Yves Rizoud + Copyright 2007 Adrien Destugues + Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) + + Grafx2 is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 + of the License. + + Grafx2 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grafx2; if not, see +*/ + +////////////////////////////////////////////////////////////////////////////// +///@file pxsimple.h +/// Renderer for simple pixels (1x1). This is the normal one. +////////////////////////////////////////////////////////////////////////////// + +#include "struct.h" + + void Pixel_simple (word x,word y,byte color); + byte Read_pixel_simple (word x,word y); + void Block_simple (word start_x,word start_y,word width,word height,byte color); + void Pixel_preview_normal_simple (word x,word y,byte color); + void Pixel_preview_magnifier_simple (word x,word y,byte color); + void Horizontal_XOR_line_simple (word x_pos,word y_pos,word width); + void Vertical_XOR_line_simple (word x_pos,word y_pos,word height); + void Display_brush_color_simple (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width); + void Display_brush_mono_simple (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,byte color,word brush_width); + void Clear_brush_simple (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word image_width); + void Remap_screen_simple (word x_pos,word y_pos,word width,word height,byte * conversion_table); + void Display_part_of_screen_simple (word width,word height,word image_width); + void Display_line_on_screen_simple (word x_pos,word y_pos,word width,byte * line); + void Read_line_screen_simple (word x_pos,word y_pos,word width,byte * line); + void Display_part_of_screen_scaled_simple(word width,word height,word image_width,byte * buffer); + void Display_brush_color_zoom_simple (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,word brush_width,byte * buffer); + void Display_brush_mono_zoom_simple (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,byte color,word brush_width,byte * buffer); + void Clear_brush_scaled_simple (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,word image_width,byte * buffer); + void Display_brush_simple (byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width); + +void Display_transparent_mono_line_on_screen_simple( + word x_pos, word y_pos, word width, byte* line, + byte transp_color, byte color); +void Display_transparent_line_on_screen_simple(word x_pos,word y_pos,word width,byte* line,byte transp_color); diff --git a/pxtall.c b/pxtall.c index 8e4c326e..c63df96d 100644 --- a/pxtall.c +++ b/pxtall.c @@ -1,453 +1,460 @@ -/* Grafx2 - The Ultimate 256-color bitmap paint program - - Copyright 2008 Yves Rizoud - Copyright 2008 Franck Charlet - Copyright 2007 Adrien Destugues - Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) - - Grafx2 is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; version 2 - of the License. - - Grafx2 is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Grafx2; if not, see -*/ - -#include -#include -#include -#include "global.h" -#include "sdlscreen.h" -#include "misc.h" -#include "pxtall.h" -#include "pxsimple.h" - -#define ZOOMX 1 -#define ZOOMY 2 - -void Pixel_tall (word x,word y,byte color) -/* Affiche un pixel de la color aux coords x;y à l'écran */ -{ - *(Screen_pixels + x + y*ZOOMY*VIDEO_LINE_WIDTH)=color; - *(Screen_pixels + x + (y*ZOOMY+1)*VIDEO_LINE_WIDTH)=color; -} - -byte Read_pixel_tall (word x,word y) -/* On retourne la couleur du pixel aux coords données */ -{ - return *( Screen_pixels + y*ZOOMY*VIDEO_LINE_WIDTH + x ); -} - -void Block_tall (word start_x,word start_y,word width,word height,byte color) -/* On affiche un rectangle de la couleur donnée */ -{ - SDL_Rect rectangle; - rectangle.x=start_x; - rectangle.y=start_y*ZOOMY; - rectangle.w=width; - rectangle.h=height*ZOOMY; - SDL_FillRect(Screen_SDL,&rectangle,color); -} - -void Display_part_of_screen_tall (word width,word height,word image_width) -/* Afficher une partie de l'image telle quelle sur l'écran */ -{ - byte* dest=Screen_pixels; //On va se mettre en 0,0 dans l'écran (dest) - byte* src=Main_offset_Y*image_width+Main_offset_X+Main_screen; //Coords de départ ds la source (src) - int y; - - for(y=height;y!=0;y--) - // Pour chaque ligne - { - // On fait une copie de la ligne - memcpy(dest,src,width); - dest+=VIDEO_LINE_WIDTH; - memcpy(dest,src,width); - - // On passe à la ligne suivante - src+=image_width; - dest+=VIDEO_LINE_WIDTH; - } - //Update_rect(0,0,width,height); -} - -void Pixel_preview_normal_tall (word x,word y,byte color) -/* Affichage d'un pixel dans l'écran, par rapport au décalage de l'image - * dans l'écran, en mode normal (pas en mode loupe) - * Note: si on modifie cette procédure, il faudra penser à faire également - * la modif dans la procédure Pixel_Preview_Loupe_SDL. */ -{ -// if(x-Main_offset_X >= 0 && y - Main_offset_Y >= 0) - Pixel_tall(x-Main_offset_X,y-Main_offset_Y,color); -} - -void Pixel_preview_magnifier_tall (word x,word y,byte color) -{ - // Affiche le pixel dans la partie non zoomée - Pixel_tall(x-Main_offset_X,y-Main_offset_Y,color); - - // Regarde si on doit aussi l'afficher dans la partie zoomée - if (y >= Limit_top_zoom && y <= Limit_visible_bottom_zoom - && x >= Limit_left_zoom && x <= Limit_visible_right_zoom) - { - // On est dedans - int height; - int y_zoom = Main_magnifier_factor * (y-Main_magnifier_offset_Y); - - if (Menu_Y - y_zoom < Main_magnifier_factor) - // On ne doit dessiner qu'un morceau du pixel - // sinon on dépasse sur le menu - height = Menu_Y - y_zoom; - else - height = Main_magnifier_factor; - - Block_tall( - Main_magnifier_factor * (x-Main_magnifier_offset_X) + Main_X_zoom, - y_zoom, Main_magnifier_factor, height, color - ); - } -} - -void Horizontal_XOR_line_tall(word x_pos,word y_pos,word width) -{ - //On calcule la valeur initiale de dest: - byte* dest=y_pos*ZOOMY*VIDEO_LINE_WIDTH+x_pos+Screen_pixels; - - int x; - - for (x=0;x 0; y--) - { - // Pour chaque pixel - for(x = width;x > 0; x--) - { - // On vérifie que ce n'est pas la transparence - if(*src != transp_color) - { - *dest = *src; - *(dest+VIDEO_LINE_WIDTH) = *src; - } - - // Pixel suivant - src++; dest++; - } - - // On passe à la ligne suivante - dest = dest + ZOOMY*VIDEO_LINE_WIDTH - width; - src = src + brush_width - width; - } - Update_rect(x_pos,y_pos,width,height); -} - -void Display_brush_mono_tall(word x_pos, word y_pos, - word x_offset, word y_offset, word width, word height, - byte transp_color, byte color, word brush_width) -/* On affiche la brosse en monochrome */ -{ - byte* dest=y_pos*ZOOMY*VIDEO_LINE_WIDTH+x_pos+Screen_pixels; // dest = adr Destination à - // l'écran - byte* src=brush_width*y_offset+x_offset+Brush; // src = adr ds - // la brosse - int x,y; - - for(y=height;y!=0;y--) - //Pour chaque ligne - { - for(x=width;x!=0;x--) - //Pour chaque pixel - { - if (*src!=transp_color) - { - *dest=color; - *(dest+VIDEO_LINE_WIDTH)=color; - } - - // On passe au pixel suivant - src++; - dest++; - } - - // On passe à la ligne suivante - src+=brush_width-width; - dest+=ZOOMY*VIDEO_LINE_WIDTH-width; - } - Update_rect(x_pos,y_pos,width,height); -} - -void Clear_brush_tall(word x_pos,word y_pos,__attribute__((unused)) word x_offset,__attribute__((unused)) word y_offset,word width,word height,__attribute__((unused))byte transp_color,word image_width) -{ - byte* dest=Screen_pixels+x_pos+y_pos*ZOOMY*VIDEO_LINE_WIDTH; //On va se mettre en 0,0 dans l'écran (dest) - byte* src = ( y_pos + Main_offset_Y ) * image_width + x_pos + Main_offset_X + Main_screen; //Coords de départ ds la source (src) - int y; - - for(y=height;y!=0;y--) - // Pour chaque ligne - { - // On fait une copie de la ligne - memcpy(dest,src,width); - dest+=VIDEO_LINE_WIDTH; - memcpy(dest,src,width); - - // On passe à la ligne suivante - src+=image_width; - dest+=VIDEO_LINE_WIDTH; - } - Update_rect(x_pos,y_pos,width,height); -} - -// Affiche une brosse (arbitraire) à l'écran -void Display_brush_tall(byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width) -{ - // dest = Position à l'écran - byte* dest = Screen_pixels + y_pos*ZOOMY*VIDEO_LINE_WIDTH + x_pos; - // src = Position dans la brosse - byte* src = brush + y_offset * brush_width + x_offset; - - word x,y; - - // Pour chaque ligne - for(y = height;y > 0; y--) - { - // Pour chaque pixel - for(x = width;x > 0; x--) - { - // On vérifie que ce n'est pas la transparence - if(*src != transp_color) - { - *dest = *src; - *(dest+VIDEO_LINE_WIDTH) = *src; - } - - // Pixel suivant - src++; dest++; - } - - // On passe à la ligne suivante - dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width; - src = src + brush_width - width; - } -} - -void Remap_screen_tall(word x_pos,word y_pos,word width,word height,byte * conversion_table) -{ - // dest = coords a l'écran - byte* dest = Screen_pixels + y_pos*ZOOMY*VIDEO_LINE_WIDTH + x_pos; - int x,y; - - // Pour chaque ligne - for(y=height*ZOOMY;y>0;y--) - { - // Pour chaque pixel - for(x=width;x>0;x--) - { - *dest = conversion_table[*dest]; - dest ++; - } - - dest = dest + VIDEO_LINE_WIDTH - width; - } - - Update_rect(x_pos,y_pos,width,height); -} - -void Display_line_on_screen_tall(word x_pos,word y_pos,word width,byte * line) -/* On affiche toute une ligne de pixels. Utilisé pour les textes. */ -{ - memcpy(Screen_pixels+x_pos+y_pos*ZOOMY*VIDEO_LINE_WIDTH,line,width); - memcpy(Screen_pixels+x_pos+(y_pos*ZOOMY+1)*VIDEO_LINE_WIDTH,line,width); -} - -void Read_line_screen_tall(word x_pos,word y_pos,word width,byte * line) -{ - memcpy(line,VIDEO_LINE_WIDTH*ZOOMY*y_pos + x_pos + Screen_pixels,width); -} - -void Display_part_of_screen_scaled_tall( - word width, // width non zoomée - word height, // height zoomée - word image_width,byte * buffer) -{ - byte* src = Main_screen + Main_magnifier_offset_Y * image_width - + Main_magnifier_offset_X; - int y = 0; // Ligne en cours de traitement - - // Pour chaque ligne à zoomer - while(1) - { - int x; - - // On éclate la ligne - Zoom_a_line(src,buffer,Main_magnifier_factor,width); - // On l'affiche Facteur fois, sur des lignes consécutives - x = Main_magnifier_factor*ZOOMY; - // Pour chaque ligne - do{ - // On affiche la ligne zoomée - Display_line_on_screen_simple( - Main_X_zoom, y, width*Main_magnifier_factor, - buffer - ); - // On passe à la suivante - y++; - if(y==height*ZOOMY) - { - Update_rect(Main_X_zoom,0, - width*Main_magnifier_factor,height); - return; - } - x--; - }while (x > 0); - src += image_width; - } -// ATTENTION on n'arrive jamais ici ! -} - -// Affiche une partie de la brosse couleur zoomée -void Display_brush_color_zoom_tall(word x_pos,word y_pos, - word x_offset,word y_offset, - word width, // width non zoomée - word end_y_pos,byte transp_color, - word brush_width, // width réelle de la brosse - byte * buffer) -{ - byte* src = Brush+y_offset*brush_width + x_offset; - word y = y_pos; - byte bx; - - // Pour chaque ligne - while(1) - { - Zoom_a_line(src,buffer,Main_magnifier_factor,width); - // On affiche facteur fois la ligne zoomée - for(bx=Main_magnifier_factor;bx>0;bx--) - { - Display_transparent_line_on_screen_simple(x_pos,y*ZOOMY,width*Main_magnifier_factor,buffer,transp_color); - memcpy(Screen_pixels + (y*ZOOMY +1) * VIDEO_LINE_WIDTH + x_pos, Screen_pixels + y*ZOOMY*VIDEO_LINE_WIDTH + x_pos, width*Main_magnifier_factor); - y++; - if(y==end_y_pos) - { - return; - } - } - src += brush_width; - } - // ATTENTION zone jamais atteinte -} - -void Display_brush_mono_zoom_tall(word x_pos, word y_pos, - word x_offset, word y_offset, - word width, // width non zoomée - word end_y_pos, - byte transp_color, byte color, - word brush_width, // width réelle de la brosse - byte * buffer -) - -{ - byte* src = Brush + y_offset * brush_width + x_offset; - int y=y_pos*ZOOMY; - - //Pour chaque ligne à zoomer : - while(1) - { - int bx; - // src = Ligne originale - // On éclate la ligne - Zoom_a_line(src,buffer,Main_magnifier_factor,width); - - // On affiche la ligne Facteur fois à l'écran (sur des - // lignes consécutives) - bx = Main_magnifier_factor*ZOOMY; - - // Pour chaque ligne écran - do - { - // On affiche la ligne zoomée - Display_transparent_mono_line_on_screen_simple( - x_pos, y, width * Main_magnifier_factor, - buffer, transp_color, color - ); - // On passe à la ligne suivante - y++; - // On vérifie qu'on est pas à la ligne finale - if(y == end_y_pos*ZOOMY) - { - Update_rect( x_pos, y_pos, - width * Main_magnifier_factor, end_y_pos - y_pos ); - return; - } - bx --; - } - while (bx > 0); - - // Passage à la ligne suivante dans la brosse aussi - src+=brush_width; - } -} - -void Clear_brush_scaled_tall(word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,__attribute__((unused)) byte transp_color,word image_width,byte * buffer) -{ - // En fait on va recopier l'image non zoomée dans la partie zoomée ! - byte* src = Main_screen + y_offset * image_width + x_offset; - int y = y_pos; - int bx; - - // Pour chaque ligne à zoomer - while(1){ - Zoom_a_line(src,buffer,Main_magnifier_factor,width); - - bx=Main_magnifier_factor; - - // Pour chaque ligne - do{ - Display_line_on_screen_tall(x_pos,y, - width * Main_magnifier_factor,buffer); - - // Ligne suivante - y++; - if(y==end_y_pos) - { - Update_rect(x_pos,y_pos, - width*Main_magnifier_factor,end_y_pos-y_pos); - return; - } - bx--; - }while(bx!=0); - - src+= image_width; - } -} +/* Grafx2 - The Ultimate 256-color bitmap paint program + + Copyright 2008 Yves Rizoud + Copyright 2008 Franck Charlet + Copyright 2007 Adrien Destugues + Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) + + Grafx2 is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 + of the License. + + Grafx2 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grafx2; if not, see +*/ + +#include +#include +#include +#include "global.h" +#include "sdlscreen.h" +#include "misc.h" +#include "graph.h" +#include "pxtall.h" +#include "pxsimple.h" + +#define ZOOMX 1 +#define ZOOMY 2 + +void Pixel_tall (word x,word y,byte color) +/* Affiche un pixel de la color aux coords x;y à l'écran */ +{ + *(Screen_pixels + x + y*ZOOMY*VIDEO_LINE_WIDTH)=color; + *(Screen_pixels + x + (y*ZOOMY+1)*VIDEO_LINE_WIDTH)=color; +} + +byte Read_pixel_tall (word x,word y) +/* On retourne la couleur du pixel aux coords données */ +{ + return *( Screen_pixels + y*ZOOMY*VIDEO_LINE_WIDTH + x ); +} + +void Block_tall (word start_x,word start_y,word width,word height,byte color) +/* On affiche un rectangle de la couleur donnée */ +{ + SDL_Rect rectangle; + rectangle.x=start_x; + rectangle.y=start_y*ZOOMY; + rectangle.w=width; + rectangle.h=height*ZOOMY; + SDL_FillRect(Screen_SDL,&rectangle,color); +} + +void Display_part_of_screen_tall (word width,word height,word image_width) +/* Afficher une partie de l'image telle quelle sur l'écran */ +{ + byte* dest=Screen_pixels; //On va se mettre en 0,0 dans l'écran (dest) + byte* src=Main_offset_Y*image_width+Main_offset_X+Main_screen; //Coords de départ ds la source (src) + int y; + + for(y=height;y!=0;y--) + // Pour chaque ligne + { + // On fait une copie de la ligne + memcpy(dest,src,width); + dest+=VIDEO_LINE_WIDTH; + memcpy(dest,src,width); + + // On passe à la ligne suivante + src+=image_width; + dest+=VIDEO_LINE_WIDTH; + } + //Update_rect(0,0,width,height); +} + +void Pixel_preview_normal_tall (word x,word y,byte color) +/* Affichage d'un pixel dans l'écran, par rapport au décalage de l'image + * dans l'écran, en mode normal (pas en mode loupe) + * Note: si on modifie cette procédure, il faudra penser à faire également + * la modif dans la procédure Pixel_Preview_Loupe_SDL. */ +{ +// if(x-Main_offset_X >= 0 && y - Main_offset_Y >= 0) + Pixel_tall(x-Main_offset_X,y-Main_offset_Y,color); +} + +void Pixel_preview_magnifier_tall (word x,word y,byte color) +{ + // Affiche le pixel dans la partie non zoomée + Pixel_tall(x-Main_offset_X,y-Main_offset_Y,color); + + // Regarde si on doit aussi l'afficher dans la partie zoomée + if (y >= Limit_top_zoom && y <= Limit_visible_bottom_zoom + && x >= Limit_left_zoom && x <= Limit_visible_right_zoom) + { + // On est dedans + int height; + int y_zoom = Main_magnifier_factor * (y-Main_magnifier_offset_Y); + + if (Menu_Y - y_zoom < Main_magnifier_factor) + // On ne doit dessiner qu'un morceau du pixel + // sinon on dépasse sur le menu + height = Menu_Y - y_zoom; + else + height = Main_magnifier_factor; + + Block_tall( + Main_magnifier_factor * (x-Main_magnifier_offset_X) + Main_X_zoom, + y_zoom, Main_magnifier_factor, height, color + ); + } +} + +void Horizontal_XOR_line_tall(word x_pos,word y_pos,word width) +{ + //On calcule la valeur initiale de dest: + byte* dest=y_pos*ZOOMY*VIDEO_LINE_WIDTH+x_pos+Screen_pixels; + + int x; + + for (x=0;x 0; y--) + { + // Pour chaque pixel + for(x = width;x > 0; x--) + { + // On vérifie que ce n'est pas la transparence + if(*src != transp_color) + { + *dest = *src; + *(dest+VIDEO_LINE_WIDTH) = *src; + } + + // Pixel suivant + src++; dest++; + } + + // On passe à la ligne suivante + dest = dest + ZOOMY*VIDEO_LINE_WIDTH - width; + src = src + brush_width - width; + } + Update_rect(x_pos,y_pos,width,height); +} + +void Display_brush_mono_tall(word x_pos, word y_pos, + word x_offset, word y_offset, word width, word height, + byte transp_color, byte color, word brush_width) +/* On affiche la brosse en monochrome */ +{ + byte* dest=y_pos*ZOOMY*VIDEO_LINE_WIDTH+x_pos+Screen_pixels; // dest = adr Destination à + // l'écran + byte* src=brush_width*y_offset+x_offset+Brush; // src = adr ds + // la brosse + int x,y; + + for(y=height;y!=0;y--) + //Pour chaque ligne + { + for(x=width;x!=0;x--) + //Pour chaque pixel + { + if (*src!=transp_color) + { + *dest=color; + *(dest+VIDEO_LINE_WIDTH)=color; + } + + // On passe au pixel suivant + src++; + dest++; + } + + // On passe à la ligne suivante + src+=brush_width-width; + dest+=ZOOMY*VIDEO_LINE_WIDTH-width; + } + Update_rect(x_pos,y_pos,width,height); +} + +void Clear_brush_tall(word x_pos,word y_pos,__attribute__((unused)) word x_offset,__attribute__((unused)) word y_offset,word width,word height,__attribute__((unused))byte transp_color,word image_width) +{ + byte* dest=Screen_pixels+x_pos+y_pos*ZOOMY*VIDEO_LINE_WIDTH; //On va se mettre en 0,0 dans l'écran (dest) + byte* src = ( y_pos + Main_offset_Y ) * image_width + x_pos + Main_offset_X + Main_screen; //Coords de départ ds la source (src) + int y; + + for(y=height;y!=0;y--) + // Pour chaque ligne + { + // On fait une copie de la ligne + memcpy(dest,src,width); + dest+=VIDEO_LINE_WIDTH; + memcpy(dest,src,width); + + // On passe à la ligne suivante + src+=image_width; + dest+=VIDEO_LINE_WIDTH; + } + Update_rect(x_pos,y_pos,width,height); +} + +// Affiche une brosse (arbitraire) à l'écran +void Display_brush_tall(byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width) +{ + // dest = Position à l'écran + byte* dest = Screen_pixels + y_pos*ZOOMY*VIDEO_LINE_WIDTH + x_pos; + // src = Position dans la brosse + byte* src = brush + y_offset * brush_width + x_offset; + + word x,y; + + // Pour chaque ligne + for(y = height;y > 0; y--) + { + // Pour chaque pixel + for(x = width;x > 0; x--) + { + // On vérifie que ce n'est pas la transparence + if(*src != transp_color) + { + *dest = *src; + *(dest+VIDEO_LINE_WIDTH) = *src; + } + + // Pixel suivant + src++; dest++; + } + + // On passe à la ligne suivante + dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width; + src = src + brush_width - width; + } +} + +void Remap_screen_tall(word x_pos,word y_pos,word width,word height,byte * conversion_table) +{ + // dest = coords a l'écran + byte* dest = Screen_pixels + y_pos*ZOOMY*VIDEO_LINE_WIDTH + x_pos; + int x,y; + + // Pour chaque ligne + for(y=height*ZOOMY;y>0;y--) + { + // Pour chaque pixel + for(x=width;x>0;x--) + { + *dest = conversion_table[*dest]; + dest ++; + } + + dest = dest + VIDEO_LINE_WIDTH - width; + } + + Update_rect(x_pos,y_pos,width,height); +} + +void Display_line_on_screen_tall(word x_pos,word y_pos,word width,byte * line) +/* On affiche toute une ligne de pixels. Utilisé pour les textes. */ +{ + memcpy(Screen_pixels+x_pos+y_pos*ZOOMY*VIDEO_LINE_WIDTH,line,width); + memcpy(Screen_pixels+x_pos+(y_pos*ZOOMY+1)*VIDEO_LINE_WIDTH,line,width); +} + +void Read_line_screen_tall(word x_pos,word y_pos,word width,byte * line) +{ + memcpy(line,VIDEO_LINE_WIDTH*ZOOMY*y_pos + x_pos + Screen_pixels,width); +} + +void Display_part_of_screen_scaled_tall( + word width, // width non zoomée + word height, // height zoomée + word image_width,byte * buffer) +{ + byte* src = Main_screen + Main_magnifier_offset_Y * image_width + + Main_magnifier_offset_X; + int y = 0; // Ligne en cours de traitement + + // Pour chaque ligne à zoomer + while(1) + { + int x; + + // On éclate la ligne + Zoom_a_line(src,buffer,Main_magnifier_factor,width); + // On l'affiche Facteur fois, sur des lignes consécutives + x = Main_magnifier_factor*ZOOMY; + // Pour chaque ligne + do{ + // On affiche la ligne zoomée + Display_line_on_screen_simple( + Main_X_zoom, y, width*Main_magnifier_factor, + buffer + ); + // On passe à la suivante + y++; + if(y==height*ZOOMY) + { + Redraw_grid(Main_X_zoom,0, + width*Main_magnifier_factor,height); + Update_rect(Main_X_zoom,0, + width*Main_magnifier_factor,height); + return; + } + x--; + }while (x > 0); + src += image_width; + } +// ATTENTION on n'arrive jamais ici ! +} + +// Affiche une partie de la brosse couleur zoomée +void Display_brush_color_zoom_tall(word x_pos,word y_pos, + word x_offset,word y_offset, + word width, // width non zoomée + word end_y_pos,byte transp_color, + word brush_width, // width réelle de la brosse + byte * buffer) +{ + byte* src = Brush+y_offset*brush_width + x_offset; + word y = y_pos; + byte bx; + + // Pour chaque ligne + while(1) + { + Zoom_a_line(src,buffer,Main_magnifier_factor,width); + // On affiche facteur fois la ligne zoomée + for(bx=Main_magnifier_factor;bx>0;bx--) + { + Display_transparent_line_on_screen_simple(x_pos,y*ZOOMY,width*Main_magnifier_factor,buffer,transp_color); + memcpy(Screen_pixels + (y*ZOOMY +1) * VIDEO_LINE_WIDTH + x_pos, Screen_pixels + y*ZOOMY*VIDEO_LINE_WIDTH + x_pos, width*Main_magnifier_factor); + y++; + if(y==end_y_pos) + { + return; + } + } + src += brush_width; + } + // ATTENTION zone jamais atteinte +} + +void Display_brush_mono_zoom_tall(word x_pos, word y_pos, + word x_offset, word y_offset, + word width, // width non zoomée + word end_y_pos, + byte transp_color, byte color, + word brush_width, // width réelle de la brosse + byte * buffer +) + +{ + byte* src = Brush + y_offset * brush_width + x_offset; + int y=y_pos*ZOOMY; + + //Pour chaque ligne à zoomer : + while(1) + { + int bx; + // src = Ligne originale + // On éclate la ligne + Zoom_a_line(src,buffer,Main_magnifier_factor,width); + + // On affiche la ligne Facteur fois à l'écran (sur des + // lignes consécutives) + bx = Main_magnifier_factor*ZOOMY; + + // Pour chaque ligne écran + do + { + // On affiche la ligne zoomée + Display_transparent_mono_line_on_screen_simple( + x_pos, y, width * Main_magnifier_factor, + buffer, transp_color, color + ); + // On passe à la ligne suivante + y++; + // On vérifie qu'on est pas à la ligne finale + if(y == end_y_pos*ZOOMY) + { + Redraw_grid( x_pos, y_pos, + width * Main_magnifier_factor, end_y_pos - y_pos ); + Update_rect( x_pos, y_pos, + width * Main_magnifier_factor, end_y_pos - y_pos ); + return; + } + bx --; + } + while (bx > 0); + + // Passage à la ligne suivante dans la brosse aussi + src+=brush_width; + } +} + +void Clear_brush_scaled_tall(word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,__attribute__((unused)) byte transp_color,word image_width,byte * buffer) +{ + // En fait on va recopier l'image non zoomée dans la partie zoomée ! + byte* src = Main_screen + y_offset * image_width + x_offset; + int y = y_pos; + int bx; + + // Pour chaque ligne à zoomer + while(1){ + Zoom_a_line(src,buffer,Main_magnifier_factor,width); + + bx=Main_magnifier_factor; + + // Pour chaque ligne + do{ + Display_line_on_screen_tall(x_pos,y, + width * Main_magnifier_factor,buffer); + + // Ligne suivante + y++; + if(y==end_y_pos) + { + Redraw_grid(x_pos,y_pos, + width*Main_magnifier_factor,end_y_pos-y_pos); + Update_rect(x_pos,y_pos, + width*Main_magnifier_factor,end_y_pos-y_pos); + return; + } + bx--; + }while(bx!=0); + + src+= image_width; + } +} diff --git a/pxtall.h b/pxtall.h index 2533b809..0499cf33 100644 --- a/pxtall.h +++ b/pxtall.h @@ -1,46 +1,46 @@ -/* Grafx2 - The Ultimate 256-color bitmap paint program - - Copyright 2008 Yves Rizoud - Copyright 2007 Adrien Destugues - Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) - - Grafx2 is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; version 2 - of the License. - - Grafx2 is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Grafx2; if not, see -*/ - -////////////////////////////////////////////////////////////////////////////// -///@file pxtall.h -/// Renderer for tall pixels (1x2). -////////////////////////////////////////////////////////////////////////////// - -#include "struct.h" - - void Pixel_tall (word x,word y,byte color); - byte Read_pixel_tall (word x,word y); - void Block_tall (word start_x,word start_y,word width,word height,byte color); - void Pixel_preview_normal_tall (word x,word y,byte color); - void Pixel_preview_magnifier_tall (word x,word y,byte color); - void Horizontal_XOR_line_tall (word x_pos,word y_pos,word width); - void Vertical_XOR_line_tall (word x_pos,word y_pos,word height); - void Display_brush_color_tall (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width); - void Display_brush_mono_tall (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,byte color,word brush_width); - void Clear_brush_tall (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word image_width); - void Remap_screen_tall (word x_pos,word y_pos,word width,word height,byte * conversion_table); - void Display_part_of_screen_tall (word width,word height,word image_width); - void Display_line_on_screen_tall (word x_pos,word y_pos,word width,byte * line); - void Read_line_screen_tall (word x_pos,word y_pos,word width,byte * line); - void Display_part_of_screen_scaled_tall(word width,word height,word image_width,byte * buffer); - void Display_brush_color_zoom_tall (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,word brush_width,byte * buffer); - void Display_brush_mono_zoom_tall (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,byte color,word brush_width,byte * buffer); - void Clear_brush_scaled_tall (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,word image_width,byte * buffer); - void Display_brush_tall (byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width); +/* Grafx2 - The Ultimate 256-color bitmap paint program + + Copyright 2008 Yves Rizoud + Copyright 2007 Adrien Destugues + Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) + + Grafx2 is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 + of the License. + + Grafx2 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grafx2; if not, see +*/ + +////////////////////////////////////////////////////////////////////////////// +///@file pxtall.h +/// Renderer for tall pixels (1x2). +////////////////////////////////////////////////////////////////////////////// + +#include "struct.h" + + void Pixel_tall (word x,word y,byte color); + byte Read_pixel_tall (word x,word y); + void Block_tall (word start_x,word start_y,word width,word height,byte color); + void Pixel_preview_normal_tall (word x,word y,byte color); + void Pixel_preview_magnifier_tall (word x,word y,byte color); + void Horizontal_XOR_line_tall (word x_pos,word y_pos,word width); + void Vertical_XOR_line_tall (word x_pos,word y_pos,word height); + void Display_brush_color_tall (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width); + void Display_brush_mono_tall (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,byte color,word brush_width); + void Clear_brush_tall (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word image_width); + void Remap_screen_tall (word x_pos,word y_pos,word width,word height,byte * conversion_table); + void Display_part_of_screen_tall (word width,word height,word image_width); + void Display_line_on_screen_tall (word x_pos,word y_pos,word width,byte * line); + void Read_line_screen_tall (word x_pos,word y_pos,word width,byte * line); + void Display_part_of_screen_scaled_tall(word width,word height,word image_width,byte * buffer); + void Display_brush_color_zoom_tall (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,word brush_width,byte * buffer); + void Display_brush_mono_zoom_tall (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,byte color,word brush_width,byte * buffer); + void Clear_brush_scaled_tall (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,word image_width,byte * buffer); + void Display_brush_tall (byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width); diff --git a/pxtall2.c b/pxtall2.c index d4e4cf0e..ca4b1b0d 100644 --- a/pxtall2.c +++ b/pxtall2.c @@ -1,524 +1,531 @@ -/* Grafx2 - The Ultimate 256-color bitmap paint program - - Copyright 2008 Yves Rizoud - Copyright 2008 Franck Charlet - Copyright 2007 Adrien Destugues - Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) - - Grafx2 is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; version 2 - of the License. - - Grafx2 is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Grafx2; if not, see -*/ - -#include -#include -#include -#include "global.h" -#include "sdlscreen.h" -#include "misc.h" -#include "pxtall2.h" - -#define ZOOMX 2 -#define ZOOMY 4 - -void Pixel_tall2 (word x,word y,byte color) -/* Affiche un pixel de la color aux coords x;y à l'écran */ -{ - *(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH)=color; - *(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH + 1)=color; - *(Screen_pixels + x * ZOOMX + (y*ZOOMY+1) * VIDEO_LINE_WIDTH)=color; - *(Screen_pixels + x * ZOOMX + (y*ZOOMY+1) * VIDEO_LINE_WIDTH + 1)=color; - *(Screen_pixels + x * ZOOMX + (y*ZOOMY+2) * VIDEO_LINE_WIDTH)=color; - *(Screen_pixels + x * ZOOMX + (y*ZOOMY+2) * VIDEO_LINE_WIDTH + 1)=color; - *(Screen_pixels + x * ZOOMX + (y*ZOOMY+3) * VIDEO_LINE_WIDTH)=color; - *(Screen_pixels + x * ZOOMX + (y*ZOOMY+3) * VIDEO_LINE_WIDTH + 1)=color; -} - -byte Read_pixel_tall2 (word x,word y) -/* On retourne la couleur du pixel aux coords données */ -{ - return *( Screen_pixels + y * ZOOMY * VIDEO_LINE_WIDTH + x * ZOOMX); -} - -void Block_tall2 (word start_x,word start_y,word width,word height,byte color) -/* On affiche un rectangle de la couleur donnée */ -{ - SDL_Rect rectangle; - rectangle.x=start_x*ZOOMX; - rectangle.y=start_y*ZOOMY; - rectangle.w=width*ZOOMX; - rectangle.h=height*ZOOMY; - SDL_FillRect(Screen_SDL,&rectangle,color); -} - -void Display_part_of_screen_tall2 (word width,word height,word image_width) -/* Afficher une partie de l'image telle quelle sur l'écran */ -{ - byte* dest=Screen_pixels; //On va se mettre en 0,0 dans l'écran (dest) - byte* src=Main_offset_Y*image_width+Main_offset_X+Main_screen; //Coords de départ ds la source (src) - int y; - int dy; - - for(y=height;y!=0;y--) - // Pour chaque ligne - { - // On fait une copie de la ligne - for (dy=width;dy>0;dy--) - { - *(dest+1)=*dest=*src; - src++; - dest+=ZOOMX; - } - // On double la ligne qu'on vient de copier - memcpy(dest-width*ZOOMX+VIDEO_LINE_WIDTH,dest-width*ZOOMX,width*ZOOMX); - // On la triple - memcpy(dest-width*ZOOMX+2*VIDEO_LINE_WIDTH,dest-width*ZOOMX,width*ZOOMX); - // On la quadruple - memcpy(dest-width*ZOOMX+3*VIDEO_LINE_WIDTH,dest-width*ZOOMX,width*ZOOMX); - - // On passe à la ligne suivante - src+=image_width-width; - dest+=VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX; - } - //Update_rect(0,0,width,height); -} - -void Pixel_preview_normal_tall2 (word x,word y,byte color) -/* Affichage d'un pixel dans l'écran, par rapport au décalage de l'image - * dans l'écran, en mode normal (pas en mode loupe) - * Note: si on modifie cette procédure, il faudra penser à faire également - * la modif dans la procédure Pixel_Preview_Loupe_SDL. */ -{ -// if(x-Main_offset_X >= 0 && y - Main_offset_Y >= 0) - Pixel_tall2(x-Main_offset_X,y-Main_offset_Y,color); -} - -void Pixel_preview_magnifier_tall2 (word x,word y,byte color) -{ - // Affiche le pixel dans la partie non zoomée - Pixel_tall2(x-Main_offset_X,y-Main_offset_Y,color); - - // Regarde si on doit aussi l'afficher dans la partie zoomée - if (y >= Limit_top_zoom && y <= Limit_visible_bottom_zoom - && x >= Limit_left_zoom && x <= Limit_visible_right_zoom) - { - // On est dedans - int height; - int y_zoom = Main_magnifier_factor * (y-Main_magnifier_offset_Y); - - if (Menu_Y - y_zoom < Main_magnifier_factor) - // On ne doit dessiner qu'un morceau du pixel - // sinon on dépasse sur le menu - height = Menu_Y - y_zoom; - else - height = Main_magnifier_factor; - - Block_tall2( - Main_magnifier_factor * (x-Main_magnifier_offset_X) + Main_X_zoom, - y_zoom, Main_magnifier_factor, height, color - ); - } -} - -void Horizontal_XOR_line_tall2(word x_pos,word y_pos,word width) -{ - //On calcule la valeur initiale de dest: - byte* dest=y_pos*ZOOMY*VIDEO_LINE_WIDTH+x_pos*ZOOMX+Screen_pixels; - - int x; - - for (x=0;x0;i--) - { - *(dest+3*VIDEO_LINE_WIDTH+1)=*(dest+3*VIDEO_LINE_WIDTH)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+1)=*(dest)=~*(dest); - dest+=VIDEO_LINE_WIDTH*ZOOMY; - } -} - -void Display_brush_color_tall2(word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width) -{ - // dest = Position à l'écran - byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX; - // src = Position dans la brosse - byte* src = Brush + y_offset * brush_width + x_offset; - - word x,y; - - // Pour chaque ligne - for(y = height;y > 0; y--) - { - // Pour chaque pixel - for(x = width;x > 0; x--) - { - // On vérifie que ce n'est pas la transparence - if(*src != transp_color) - { - *(dest+3*VIDEO_LINE_WIDTH+1) = *(dest+3*VIDEO_LINE_WIDTH) = *(dest+2*VIDEO_LINE_WIDTH+1) = *(dest+2*VIDEO_LINE_WIDTH) = *(dest+VIDEO_LINE_WIDTH+1) = *(dest+VIDEO_LINE_WIDTH) = *(dest+1) = *dest = *src; - } - - // Pixel suivant - src++; - dest+=ZOOMX; - } - - // On passe à la ligne suivante - dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX; - src = src + brush_width - width; - } - Update_rect(x_pos,y_pos,width,height); -} - -void Display_brush_mono_tall2(word x_pos, word y_pos, - word x_offset, word y_offset, word width, word height, - byte transp_color, byte color, word brush_width) -/* On affiche la brosse en monochrome */ -{ - byte* dest=y_pos*ZOOMY*VIDEO_LINE_WIDTH+x_pos*ZOOMX+Screen_pixels; // dest = adr destination à - // l'écran - byte* src=brush_width*y_offset+x_offset+Brush; // src = adr ds - // la brosse - int x,y; - - for(y=height;y!=0;y--) - //Pour chaque ligne - { - for(x=width;x!=0;x--) - //Pour chaque pixel - { - if (*src!=transp_color) - *(dest+3*VIDEO_LINE_WIDTH+1)=*(dest+3*VIDEO_LINE_WIDTH)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+1)=*(dest)=color; - - // On passe au pixel suivant - src++; - dest+=ZOOMX; - } - - // On passe à la ligne suivante - src+=brush_width-width; - dest+=VIDEO_LINE_WIDTH*ZOOMY-width*ZOOMX; - } - Update_rect(x_pos,y_pos,width,height); -} - -void Clear_brush_tall2(word x_pos,word y_pos,__attribute__((unused)) word x_offset,__attribute__((unused)) word y_offset,word width,word height,__attribute__((unused))byte transp_color,word image_width) -{ - byte* dest=Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH; //On va se mettre en 0,0 dans l'écran (dest) - byte* src = ( y_pos + Main_offset_Y ) * image_width + x_pos + Main_offset_X + Main_screen; //Coords de départ ds la source (src) - int y; - int x; - - for(y=height;y!=0;y--) - // Pour chaque ligne - { - for(x=width;x!=0;x--) - //Pour chaque pixel - { - *(dest+3*VIDEO_LINE_WIDTH+1)=*(dest+3*VIDEO_LINE_WIDTH)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+1)=*(dest)=*src; - - // On passe au pixel suivant - src++; - dest+=ZOOMX; - } - - // On passe à la ligne suivante - src+=image_width-width; - dest+=VIDEO_LINE_WIDTH*ZOOMY-width*ZOOMX; - } - Update_rect(x_pos,y_pos,width,height); -} - -// Affiche une brosse (arbitraire) à l'écran -void Display_brush_tall2(byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width) -{ - // dest = Position à l'écran - byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX; - // src = Position dans la brosse - byte* src = brush + y_offset * brush_width + x_offset; - - word x,y; - - // Pour chaque ligne - for(y = height;y > 0; y--) - { - // Pour chaque pixel - for(x = width;x > 0; x--) - { - // On vérifie que ce n'est pas la transparence - if(*src != transp_color) - { - *(dest+3*VIDEO_LINE_WIDTH+1)=*(dest+3*VIDEO_LINE_WIDTH)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+1)=*(dest)=*src; - } - - // Pixel suivant - src++; dest+=ZOOMX; - } - - // On passe à la ligne suivante - dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX; - src = src + brush_width - width; - } -} - -void Remap_screen_tall2(word x_pos,word y_pos,word width,word height,byte * conversion_table) -{ - // dest = coords a l'écran - byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX; - int x,y; - - // Pour chaque ligne - for(y=height;y>0;y--) - { - // Pour chaque pixel - for(x=width;x>0;x--) - { - *(dest+3*VIDEO_LINE_WIDTH+1)=*(dest+3*VIDEO_LINE_WIDTH)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+1)=*(dest)= - conversion_table[*dest]; - dest +=ZOOMX; - } - - dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX; - } - - Update_rect(x_pos,y_pos,width,height); -} - -void Display_line_on_screen_fast_tall2(word x_pos,word y_pos,word width,byte * line) -/* On affiche toute une ligne de pixels telle quelle. */ -/* Utilisée si le buffer contient déja des pixel doublés. */ -{ - memcpy(Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH,line,width*ZOOMX); - memcpy(Screen_pixels+x_pos*ZOOMX+(y_pos*ZOOMY+1)*VIDEO_LINE_WIDTH,line,width*ZOOMX); - memcpy(Screen_pixels+x_pos*ZOOMX+(y_pos*ZOOMY+2)*VIDEO_LINE_WIDTH,line,width*ZOOMX); - memcpy(Screen_pixels+x_pos*ZOOMX+(y_pos*ZOOMY+3)*VIDEO_LINE_WIDTH,line,width*ZOOMX); -} - -void Display_line_on_screen_tall2(word x_pos,word y_pos,word width,byte * line) -/* On affiche une ligne de pixels en les doublant. */ -{ - int x; - byte *dest; - dest=Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH; - for(x=width;x>0;x--) - { - *(dest+3*VIDEO_LINE_WIDTH+1)=*(dest+3*VIDEO_LINE_WIDTH)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+1)=*(dest)=*line; - dest+=ZOOMX; - line++; - } -} -void Display_transparent_mono_line_on_screen_tall2( - word x_pos, word y_pos, word width, byte* line, - byte transp_color, byte color) -// Affiche une ligne à l'écran avec une couleur + transparence. -// Utilisé par les brosses en mode zoom -{ - byte* dest = Screen_pixels+ y_pos*VIDEO_LINE_WIDTH + x_pos*ZOOMX; - int x; - // Pour chaque pixel - for(x=0;x 0); - src += image_width; - } -// ATTENTION on n'arrive jamais ici ! -} - -// Affiche une partie de la brosse couleur zoomée -void Display_brush_color_zoom_tall2(word x_pos,word y_pos, - word x_offset,word y_offset, - word width, // width non zoomée - word end_y_pos,byte transp_color, - word brush_width, // width réelle de la brosse - byte * buffer) -{ - byte* src = Brush+y_offset*brush_width + x_offset; - word y = y_pos; - byte bx; - - // Pour chaque ligne - while(1) - { - Zoom_a_line(src,buffer,Main_magnifier_factor,width); - // On affiche facteur fois la ligne zoomée - for(bx=Main_magnifier_factor;bx>0;bx--) - { - byte* line_src = buffer; - byte* dest = Screen_pixels + y*ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX; - word x; - // Pour chaque pixel de la ligne - for(x = width*Main_magnifier_factor;x > 0;x--) - { - if(*line_src!=transp_color) - { - *(dest+1)=*dest = *line_src; - } - line_src++; - dest+=ZOOMX; - } - // Double the line - memcpy(Screen_pixels + (y*ZOOMY+1)*VIDEO_LINE_WIDTH + x_pos*ZOOMX, Screen_pixels + y*ZOOMY*VIDEO_LINE_WIDTH + x_pos*ZOOMX, width*ZOOMX*Main_magnifier_factor); - // Triple the line - memcpy(Screen_pixels + (y*ZOOMY+2)*VIDEO_LINE_WIDTH + x_pos*ZOOMX, Screen_pixels + y*ZOOMY*VIDEO_LINE_WIDTH + x_pos*ZOOMX, width*ZOOMX*Main_magnifier_factor); - // Quadruple it - memcpy(Screen_pixels + (y*ZOOMY+3)*VIDEO_LINE_WIDTH + x_pos*ZOOMX, Screen_pixels + y*ZOOMY*VIDEO_LINE_WIDTH + x_pos*ZOOMX, width*ZOOMX*Main_magnifier_factor); - y++; - if(y==end_y_pos) - { - return; - } - } - src += brush_width; - } - // ATTENTION zone jamais atteinte -} - -void Display_brush_mono_zoom_tall2(word x_pos, word y_pos, - word x_offset, word y_offset, - word width, // width non zoomée - word end_y_pos, - byte transp_color, byte color, - word brush_width, // width réelle de la brosse - byte * buffer -) - -{ - byte* src = Brush + y_offset * brush_width + x_offset; - int y=y_pos*ZOOMY; - - //Pour chaque ligne à zoomer : - while(1) - { - int bx; - // src = Ligne originale - // On éclate la ligne - Zoom_a_line(src,buffer,Main_magnifier_factor,width); - - // On affiche la ligne Facteur fois à l'écran (sur des - // lignes consécutives) - bx = Main_magnifier_factor*ZOOMY; - - // Pour chaque ligne écran - do - { - // On affiche la ligne zoomée - Display_transparent_mono_line_on_screen_tall2( - x_pos, y, width * Main_magnifier_factor, - buffer, transp_color, color - ); - // On passe à la ligne suivante - y++; - // On vérifie qu'on est pas à la ligne finale - if(y == end_y_pos*ZOOMY) - { - Update_rect( x_pos, y_pos, - width * Main_magnifier_factor, end_y_pos - y_pos ); - return; - } - bx --; - } - while (bx > 0); - - // Passage à la ligne suivante dans la brosse aussi - src+=brush_width; - } -} - -void Clear_brush_scaled_tall2(word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,__attribute__((unused)) byte transp_color,word image_width,byte * buffer) -{ - - // En fait on va recopier l'image non zoomée dans la partie zoomée ! - byte* src = Main_screen + y_offset * image_width + x_offset; - int y = y_pos; - int bx; - - // Pour chaque ligne à zoomer - while(1){ - Zoom_a_line(src,buffer,Main_magnifier_factor*ZOOMX,width); - - bx=Main_magnifier_factor; - - // Pour chaque ligne - do{ - // TODO a verifier - Display_line_on_screen_fast_tall2(x_pos,y, - width * Main_magnifier_factor,buffer); - - // Ligne suivante - y++; - if(y==end_y_pos) - { - Update_rect(x_pos,y_pos, - width*Main_magnifier_factor,end_y_pos-y_pos); - return; - } - bx--; - }while(bx!=0); - - src+= image_width; - } -} - - +/* Grafx2 - The Ultimate 256-color bitmap paint program + + Copyright 2008 Yves Rizoud + Copyright 2008 Franck Charlet + Copyright 2007 Adrien Destugues + Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) + + Grafx2 is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 + of the License. + + Grafx2 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grafx2; if not, see +*/ + +#include +#include +#include +#include "global.h" +#include "sdlscreen.h" +#include "misc.h" +#include "graph.h" +#include "pxtall2.h" + +#define ZOOMX 2 +#define ZOOMY 4 + +void Pixel_tall2 (word x,word y,byte color) +/* Affiche un pixel de la color aux coords x;y à l'écran */ +{ + *(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH)=color; + *(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH + 1)=color; + *(Screen_pixels + x * ZOOMX + (y*ZOOMY+1) * VIDEO_LINE_WIDTH)=color; + *(Screen_pixels + x * ZOOMX + (y*ZOOMY+1) * VIDEO_LINE_WIDTH + 1)=color; + *(Screen_pixels + x * ZOOMX + (y*ZOOMY+2) * VIDEO_LINE_WIDTH)=color; + *(Screen_pixels + x * ZOOMX + (y*ZOOMY+2) * VIDEO_LINE_WIDTH + 1)=color; + *(Screen_pixels + x * ZOOMX + (y*ZOOMY+3) * VIDEO_LINE_WIDTH)=color; + *(Screen_pixels + x * ZOOMX + (y*ZOOMY+3) * VIDEO_LINE_WIDTH + 1)=color; +} + +byte Read_pixel_tall2 (word x,word y) +/* On retourne la couleur du pixel aux coords données */ +{ + return *( Screen_pixels + y * ZOOMY * VIDEO_LINE_WIDTH + x * ZOOMX); +} + +void Block_tall2 (word start_x,word start_y,word width,word height,byte color) +/* On affiche un rectangle de la couleur donnée */ +{ + SDL_Rect rectangle; + rectangle.x=start_x*ZOOMX; + rectangle.y=start_y*ZOOMY; + rectangle.w=width*ZOOMX; + rectangle.h=height*ZOOMY; + SDL_FillRect(Screen_SDL,&rectangle,color); +} + +void Display_part_of_screen_tall2 (word width,word height,word image_width) +/* Afficher une partie de l'image telle quelle sur l'écran */ +{ + byte* dest=Screen_pixels; //On va se mettre en 0,0 dans l'écran (dest) + byte* src=Main_offset_Y*image_width+Main_offset_X+Main_screen; //Coords de départ ds la source (src) + int y; + int dy; + + for(y=height;y!=0;y--) + // Pour chaque ligne + { + // On fait une copie de la ligne + for (dy=width;dy>0;dy--) + { + *(dest+1)=*dest=*src; + src++; + dest+=ZOOMX; + } + // On double la ligne qu'on vient de copier + memcpy(dest-width*ZOOMX+VIDEO_LINE_WIDTH,dest-width*ZOOMX,width*ZOOMX); + // On la triple + memcpy(dest-width*ZOOMX+2*VIDEO_LINE_WIDTH,dest-width*ZOOMX,width*ZOOMX); + // On la quadruple + memcpy(dest-width*ZOOMX+3*VIDEO_LINE_WIDTH,dest-width*ZOOMX,width*ZOOMX); + + // On passe à la ligne suivante + src+=image_width-width; + dest+=VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX; + } + //Update_rect(0,0,width,height); +} + +void Pixel_preview_normal_tall2 (word x,word y,byte color) +/* Affichage d'un pixel dans l'écran, par rapport au décalage de l'image + * dans l'écran, en mode normal (pas en mode loupe) + * Note: si on modifie cette procédure, il faudra penser à faire également + * la modif dans la procédure Pixel_Preview_Loupe_SDL. */ +{ +// if(x-Main_offset_X >= 0 && y - Main_offset_Y >= 0) + Pixel_tall2(x-Main_offset_X,y-Main_offset_Y,color); +} + +void Pixel_preview_magnifier_tall2 (word x,word y,byte color) +{ + // Affiche le pixel dans la partie non zoomée + Pixel_tall2(x-Main_offset_X,y-Main_offset_Y,color); + + // Regarde si on doit aussi l'afficher dans la partie zoomée + if (y >= Limit_top_zoom && y <= Limit_visible_bottom_zoom + && x >= Limit_left_zoom && x <= Limit_visible_right_zoom) + { + // On est dedans + int height; + int y_zoom = Main_magnifier_factor * (y-Main_magnifier_offset_Y); + + if (Menu_Y - y_zoom < Main_magnifier_factor) + // On ne doit dessiner qu'un morceau du pixel + // sinon on dépasse sur le menu + height = Menu_Y - y_zoom; + else + height = Main_magnifier_factor; + + Block_tall2( + Main_magnifier_factor * (x-Main_magnifier_offset_X) + Main_X_zoom, + y_zoom, Main_magnifier_factor, height, color + ); + } +} + +void Horizontal_XOR_line_tall2(word x_pos,word y_pos,word width) +{ + //On calcule la valeur initiale de dest: + byte* dest=y_pos*ZOOMY*VIDEO_LINE_WIDTH+x_pos*ZOOMX+Screen_pixels; + + int x; + + for (x=0;x0;i--) + { + *(dest+3*VIDEO_LINE_WIDTH+1)=*(dest+3*VIDEO_LINE_WIDTH)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+1)=*(dest)=~*(dest); + dest+=VIDEO_LINE_WIDTH*ZOOMY; + } +} + +void Display_brush_color_tall2(word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width) +{ + // dest = Position à l'écran + byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX; + // src = Position dans la brosse + byte* src = Brush + y_offset * brush_width + x_offset; + + word x,y; + + // Pour chaque ligne + for(y = height;y > 0; y--) + { + // Pour chaque pixel + for(x = width;x > 0; x--) + { + // On vérifie que ce n'est pas la transparence + if(*src != transp_color) + { + *(dest+3*VIDEO_LINE_WIDTH+1) = *(dest+3*VIDEO_LINE_WIDTH) = *(dest+2*VIDEO_LINE_WIDTH+1) = *(dest+2*VIDEO_LINE_WIDTH) = *(dest+VIDEO_LINE_WIDTH+1) = *(dest+VIDEO_LINE_WIDTH) = *(dest+1) = *dest = *src; + } + + // Pixel suivant + src++; + dest+=ZOOMX; + } + + // On passe à la ligne suivante + dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX; + src = src + brush_width - width; + } + Update_rect(x_pos,y_pos,width,height); +} + +void Display_brush_mono_tall2(word x_pos, word y_pos, + word x_offset, word y_offset, word width, word height, + byte transp_color, byte color, word brush_width) +/* On affiche la brosse en monochrome */ +{ + byte* dest=y_pos*ZOOMY*VIDEO_LINE_WIDTH+x_pos*ZOOMX+Screen_pixels; // dest = adr destination à + // l'écran + byte* src=brush_width*y_offset+x_offset+Brush; // src = adr ds + // la brosse + int x,y; + + for(y=height;y!=0;y--) + //Pour chaque ligne + { + for(x=width;x!=0;x--) + //Pour chaque pixel + { + if (*src!=transp_color) + *(dest+3*VIDEO_LINE_WIDTH+1)=*(dest+3*VIDEO_LINE_WIDTH)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+1)=*(dest)=color; + + // On passe au pixel suivant + src++; + dest+=ZOOMX; + } + + // On passe à la ligne suivante + src+=brush_width-width; + dest+=VIDEO_LINE_WIDTH*ZOOMY-width*ZOOMX; + } + Update_rect(x_pos,y_pos,width,height); +} + +void Clear_brush_tall2(word x_pos,word y_pos,__attribute__((unused)) word x_offset,__attribute__((unused)) word y_offset,word width,word height,__attribute__((unused))byte transp_color,word image_width) +{ + byte* dest=Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH; //On va se mettre en 0,0 dans l'écran (dest) + byte* src = ( y_pos + Main_offset_Y ) * image_width + x_pos + Main_offset_X + Main_screen; //Coords de départ ds la source (src) + int y; + int x; + + for(y=height;y!=0;y--) + // Pour chaque ligne + { + for(x=width;x!=0;x--) + //Pour chaque pixel + { + *(dest+3*VIDEO_LINE_WIDTH+1)=*(dest+3*VIDEO_LINE_WIDTH)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+1)=*(dest)=*src; + + // On passe au pixel suivant + src++; + dest+=ZOOMX; + } + + // On passe à la ligne suivante + src+=image_width-width; + dest+=VIDEO_LINE_WIDTH*ZOOMY-width*ZOOMX; + } + Update_rect(x_pos,y_pos,width,height); +} + +// Affiche une brosse (arbitraire) à l'écran +void Display_brush_tall2(byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width) +{ + // dest = Position à l'écran + byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX; + // src = Position dans la brosse + byte* src = brush + y_offset * brush_width + x_offset; + + word x,y; + + // Pour chaque ligne + for(y = height;y > 0; y--) + { + // Pour chaque pixel + for(x = width;x > 0; x--) + { + // On vérifie que ce n'est pas la transparence + if(*src != transp_color) + { + *(dest+3*VIDEO_LINE_WIDTH+1)=*(dest+3*VIDEO_LINE_WIDTH)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+1)=*(dest)=*src; + } + + // Pixel suivant + src++; dest+=ZOOMX; + } + + // On passe à la ligne suivante + dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX; + src = src + brush_width - width; + } +} + +void Remap_screen_tall2(word x_pos,word y_pos,word width,word height,byte * conversion_table) +{ + // dest = coords a l'écran + byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX; + int x,y; + + // Pour chaque ligne + for(y=height;y>0;y--) + { + // Pour chaque pixel + for(x=width;x>0;x--) + { + *(dest+3*VIDEO_LINE_WIDTH+1)=*(dest+3*VIDEO_LINE_WIDTH)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+1)=*(dest)= + conversion_table[*dest]; + dest +=ZOOMX; + } + + dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX; + } + + Update_rect(x_pos,y_pos,width,height); +} + +void Display_line_on_screen_fast_tall2(word x_pos,word y_pos,word width,byte * line) +/* On affiche toute une ligne de pixels telle quelle. */ +/* Utilisée si le buffer contient déja des pixel doublés. */ +{ + memcpy(Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH,line,width*ZOOMX); + memcpy(Screen_pixels+x_pos*ZOOMX+(y_pos*ZOOMY+1)*VIDEO_LINE_WIDTH,line,width*ZOOMX); + memcpy(Screen_pixels+x_pos*ZOOMX+(y_pos*ZOOMY+2)*VIDEO_LINE_WIDTH,line,width*ZOOMX); + memcpy(Screen_pixels+x_pos*ZOOMX+(y_pos*ZOOMY+3)*VIDEO_LINE_WIDTH,line,width*ZOOMX); +} + +void Display_line_on_screen_tall2(word x_pos,word y_pos,word width,byte * line) +/* On affiche une ligne de pixels en les doublant. */ +{ + int x; + byte *dest; + dest=Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH; + for(x=width;x>0;x--) + { + *(dest+3*VIDEO_LINE_WIDTH+1)=*(dest+3*VIDEO_LINE_WIDTH)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+1)=*(dest)=*line; + dest+=ZOOMX; + line++; + } +} +void Display_transparent_mono_line_on_screen_tall2( + word x_pos, word y_pos, word width, byte* line, + byte transp_color, byte color) +// Affiche une ligne à l'écran avec une couleur + transparence. +// Utilisé par les brosses en mode zoom +{ + byte* dest = Screen_pixels+ y_pos*VIDEO_LINE_WIDTH + x_pos*ZOOMX; + int x; + // Pour chaque pixel + for(x=0;x 0); + src += image_width; + } +// ATTENTION on n'arrive jamais ici ! +} + +// Affiche une partie de la brosse couleur zoomée +void Display_brush_color_zoom_tall2(word x_pos,word y_pos, + word x_offset,word y_offset, + word width, // width non zoomée + word end_y_pos,byte transp_color, + word brush_width, // width réelle de la brosse + byte * buffer) +{ + byte* src = Brush+y_offset*brush_width + x_offset; + word y = y_pos; + byte bx; + + // Pour chaque ligne + while(1) + { + Zoom_a_line(src,buffer,Main_magnifier_factor,width); + // On affiche facteur fois la ligne zoomée + for(bx=Main_magnifier_factor;bx>0;bx--) + { + byte* line_src = buffer; + byte* dest = Screen_pixels + y*ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX; + word x; + // Pour chaque pixel de la ligne + for(x = width*Main_magnifier_factor;x > 0;x--) + { + if(*line_src!=transp_color) + { + *(dest+1)=*dest = *line_src; + } + line_src++; + dest+=ZOOMX; + } + // Double the line + memcpy(Screen_pixels + (y*ZOOMY+1)*VIDEO_LINE_WIDTH + x_pos*ZOOMX, Screen_pixels + y*ZOOMY*VIDEO_LINE_WIDTH + x_pos*ZOOMX, width*ZOOMX*Main_magnifier_factor); + // Triple the line + memcpy(Screen_pixels + (y*ZOOMY+2)*VIDEO_LINE_WIDTH + x_pos*ZOOMX, Screen_pixels + y*ZOOMY*VIDEO_LINE_WIDTH + x_pos*ZOOMX, width*ZOOMX*Main_magnifier_factor); + // Quadruple it + memcpy(Screen_pixels + (y*ZOOMY+3)*VIDEO_LINE_WIDTH + x_pos*ZOOMX, Screen_pixels + y*ZOOMY*VIDEO_LINE_WIDTH + x_pos*ZOOMX, width*ZOOMX*Main_magnifier_factor); + y++; + if(y==end_y_pos) + { + return; + } + } + src += brush_width; + } + // ATTENTION zone jamais atteinte +} + +void Display_brush_mono_zoom_tall2(word x_pos, word y_pos, + word x_offset, word y_offset, + word width, // width non zoomée + word end_y_pos, + byte transp_color, byte color, + word brush_width, // width réelle de la brosse + byte * buffer +) + +{ + byte* src = Brush + y_offset * brush_width + x_offset; + int y=y_pos*ZOOMY; + + //Pour chaque ligne à zoomer : + while(1) + { + int bx; + // src = Ligne originale + // On éclate la ligne + Zoom_a_line(src,buffer,Main_magnifier_factor,width); + + // On affiche la ligne Facteur fois à l'écran (sur des + // lignes consécutives) + bx = Main_magnifier_factor*ZOOMY; + + // Pour chaque ligne écran + do + { + // On affiche la ligne zoomée + Display_transparent_mono_line_on_screen_tall2( + x_pos, y, width * Main_magnifier_factor, + buffer, transp_color, color + ); + // On passe à la ligne suivante + y++; + // On vérifie qu'on est pas à la ligne finale + if(y == end_y_pos*ZOOMY) + { + Redraw_grid( x_pos, y_pos, + width * Main_magnifier_factor, end_y_pos - y_pos ); + Update_rect( x_pos, y_pos, + width * Main_magnifier_factor, end_y_pos - y_pos ); + return; + } + bx --; + } + while (bx > 0); + + // Passage à la ligne suivante dans la brosse aussi + src+=brush_width; + } +} + +void Clear_brush_scaled_tall2(word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,__attribute__((unused)) byte transp_color,word image_width,byte * buffer) +{ + + // En fait on va recopier l'image non zoomée dans la partie zoomée ! + byte* src = Main_screen + y_offset * image_width + x_offset; + int y = y_pos; + int bx; + + // Pour chaque ligne à zoomer + while(1){ + Zoom_a_line(src,buffer,Main_magnifier_factor*ZOOMX,width); + + bx=Main_magnifier_factor; + + // Pour chaque ligne + do{ + // TODO a verifier + Display_line_on_screen_fast_tall2(x_pos,y, + width * Main_magnifier_factor,buffer); + + // Ligne suivante + y++; + if(y==end_y_pos) + { + Redraw_grid(x_pos,y_pos, + width*Main_magnifier_factor,end_y_pos-y_pos); + Update_rect(x_pos,y_pos, + width*Main_magnifier_factor,end_y_pos-y_pos); + return; + } + bx--; + }while(bx!=0); + + src+= image_width; + } +} + + diff --git a/pxtall2.h b/pxtall2.h index 262c6e45..eaf40fe5 100644 --- a/pxtall2.h +++ b/pxtall2.h @@ -1,48 +1,48 @@ -/* Grafx2 - The Ultimate 256-color bitmap paint program - - Copyright 2008 Yves Rizoud - Copyright 2007 Adrien Destugues - Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) - - Grafx2 is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; version 2 - of the License. - - Grafx2 is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Grafx2; if not, see -*/ - -////////////////////////////////////////////////////////////////////////////// -///@file pxtall2.h -/// Renderer for double-tall pixels (2x4). -////////////////////////////////////////////////////////////////////////////// - -#include "struct.h" - - void Pixel_tall2 (word x,word y,byte color); - byte Read_pixel_tall2 (word x,word y); - void Block_tall2 (word start_x,word start_y,word width,word height,byte color); - void Pixel_preview_normal_tall2 (word x,word y,byte color); - void Pixel_preview_magnifier_tall2 (word x,word y,byte color); - void Horizontal_XOR_line_tall2 (word x_pos,word y_pos,word width); - void Vertical_XOR_line_tall2 (word x_pos,word y_pos,word height); - void Display_brush_color_tall2 (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width); - void Display_brush_mono_tall2 (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,byte color,word brush_width); - void Clear_brush_tall2 (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word image_width); - void Remap_screen_tall2 (word x_pos,word y_pos,word width,word height,byte * conversion_table); - void Display_part_of_screen_tall2 (word width,word height,word image_width); - void Display_line_on_screen_tall2 (word x_pos,word y_pos,word width,byte * line); - void Read_line_screen_tall2 (word x_pos,word y_pos,word width,byte * line); - void Display_part_of_screen_scaled_tall2(word width,word height,word image_width,byte * buffer); - void Display_brush_color_zoom_tall2 (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,word brush_width,byte * buffer); - void Display_brush_mono_zoom_tall2 (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,byte color,word brush_width,byte * buffer); - void Clear_brush_scaled_tall2 (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,word image_width,byte * buffer); - void Display_brush_tall2 (byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width); - - void Display_line_on_screen_fast_tall2 (word x_pos,word y_pos,word width,byte * line); +/* Grafx2 - The Ultimate 256-color bitmap paint program + + Copyright 2008 Yves Rizoud + Copyright 2007 Adrien Destugues + Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) + + Grafx2 is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 + of the License. + + Grafx2 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grafx2; if not, see +*/ + +////////////////////////////////////////////////////////////////////////////// +///@file pxtall2.h +/// Renderer for double-tall pixels (2x4). +////////////////////////////////////////////////////////////////////////////// + +#include "struct.h" + + void Pixel_tall2 (word x,word y,byte color); + byte Read_pixel_tall2 (word x,word y); + void Block_tall2 (word start_x,word start_y,word width,word height,byte color); + void Pixel_preview_normal_tall2 (word x,word y,byte color); + void Pixel_preview_magnifier_tall2 (word x,word y,byte color); + void Horizontal_XOR_line_tall2 (word x_pos,word y_pos,word width); + void Vertical_XOR_line_tall2 (word x_pos,word y_pos,word height); + void Display_brush_color_tall2 (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width); + void Display_brush_mono_tall2 (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,byte color,word brush_width); + void Clear_brush_tall2 (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word image_width); + void Remap_screen_tall2 (word x_pos,word y_pos,word width,word height,byte * conversion_table); + void Display_part_of_screen_tall2 (word width,word height,word image_width); + void Display_line_on_screen_tall2 (word x_pos,word y_pos,word width,byte * line); + void Read_line_screen_tall2 (word x_pos,word y_pos,word width,byte * line); + void Display_part_of_screen_scaled_tall2(word width,word height,word image_width,byte * buffer); + void Display_brush_color_zoom_tall2 (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,word brush_width,byte * buffer); + void Display_brush_mono_zoom_tall2 (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,byte color,word brush_width,byte * buffer); + void Clear_brush_scaled_tall2 (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,word image_width,byte * buffer); + void Display_brush_tall2 (byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width); + + void Display_line_on_screen_fast_tall2 (word x_pos,word y_pos,word width,byte * line); diff --git a/pxtriple.c b/pxtriple.c index eb14ff20..99f58efd 100644 --- a/pxtriple.c +++ b/pxtriple.c @@ -1,520 +1,527 @@ -/* Grafx2 - The Ultimate 256-color bitmap paint program - - Copyright 2008 Yves Rizoud - Copyright 2008 Franck Charlet - Copyright 2007 Adrien Destugues - Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) - - Grafx2 is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; version 2 - of the License. - - Grafx2 is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Grafx2; if not, see -*/ - -#include -#include -#include -#include "global.h" -#include "sdlscreen.h" -#include "misc.h" -#include "pxtriple.h" - -#define ZOOMX 3 -#define ZOOMY 3 - -void Pixel_triple (word x,word y,byte color) -/* Affiche un pixel de la color aux coords x;y à l'écran */ -{ - *(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH)=color; - *(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH + 1)=color; - *(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH + 2)=color; - *(Screen_pixels + x * ZOOMX + (y*ZOOMY+1) * VIDEO_LINE_WIDTH)=color; - *(Screen_pixels + x * ZOOMX + (y*ZOOMY+1) * VIDEO_LINE_WIDTH + 1)=color; - *(Screen_pixels + x * ZOOMX + (y*ZOOMY+1) * VIDEO_LINE_WIDTH + 2)=color; - *(Screen_pixels + x * ZOOMX + (y*ZOOMY+2) * VIDEO_LINE_WIDTH)=color; - *(Screen_pixels + x * ZOOMX + (y*ZOOMY+2) * VIDEO_LINE_WIDTH + 1)=color; - *(Screen_pixels + x * ZOOMX + (y*ZOOMY+2) * VIDEO_LINE_WIDTH + 2)=color; -} - -byte Read_pixel_triple (word x,word y) -/* On retourne la couleur du pixel aux coords données */ -{ - return *( Screen_pixels + y * ZOOMY * VIDEO_LINE_WIDTH + x * ZOOMX); -} - -void Block_triple (word start_x,word start_y,word width,word height,byte color) -/* On affiche un rectangle de la couleur donnée */ -{ - SDL_Rect rectangle; - rectangle.x=start_x*ZOOMX; - rectangle.y=start_y*ZOOMY; - rectangle.w=width*ZOOMX; - rectangle.h=height*ZOOMY; - SDL_FillRect(Screen_SDL,&rectangle,color); -} - -void Display_part_of_screen_triple (word width,word height,word image_width) -/* Afficher une partie de l'image telle quelle sur l'écran */ -{ - byte* dest=Screen_pixels; //On va se mettre en 0,0 dans l'écran (dest) - byte* src=Main_offset_Y*image_width+Main_offset_X+Main_screen; //Coords de départ ds la source (src) - int y; - int dy; - - for(y=height;y!=0;y--) - // Pour chaque ligne - { - // On fait une copie de la ligne - for (dy=width;dy>0;dy--) - { - *(dest+2)=*(dest+1)=*dest=*src; - src++; - dest+=ZOOMX; - } - // On double la ligne qu'on vient de copier - memcpy(dest-width*ZOOMX+VIDEO_LINE_WIDTH,dest-width*ZOOMX,width*ZOOMX); - // On la triple - memcpy(dest-width*ZOOMX+2*VIDEO_LINE_WIDTH,dest-width*ZOOMX,width*ZOOMX); - - // On passe à la ligne suivante - src+=image_width-width; - dest+=VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX; - } - //Update_rect(0,0,width,height); -} - -void Pixel_preview_normal_triple (word x,word y,byte color) -/* Affichage d'un pixel dans l'écran, par rapport au décalage de l'image - * dans l'écran, en mode normal (pas en mode loupe) - * Note: si on modifie cette procédure, il faudra penser à faire également - * la modif dans la procédure Pixel_Preview_Loupe_SDL. */ -{ -// if(x-Main_offset_X >= 0 && y - Main_offset_Y >= 0) - Pixel_triple(x-Main_offset_X,y-Main_offset_Y,color); -} - -void Pixel_preview_magnifier_triple (word x,word y,byte color) -{ - // Affiche le pixel dans la partie non zoomée - Pixel_triple(x-Main_offset_X,y-Main_offset_Y,color); - - // Regarde si on doit aussi l'afficher dans la partie zoomée - if (y >= Limit_top_zoom && y <= Limit_visible_bottom_zoom - && x >= Limit_left_zoom && x <= Limit_visible_right_zoom) - { - // On est dedans - int height; - int y_zoom = Main_magnifier_factor * (y-Main_magnifier_offset_Y); - - if (Menu_Y - y_zoom < Main_magnifier_factor) - // On ne doit dessiner qu'un morceau du pixel - // sinon on dépasse sur le menu - height = Menu_Y - y_zoom; - else - height = Main_magnifier_factor; - - Block_triple( - Main_magnifier_factor * (x-Main_magnifier_offset_X) + Main_X_zoom, - y_zoom, Main_magnifier_factor, height, color - ); - } -} - -void Horizontal_XOR_line_triple(word x_pos,word y_pos,word width) -{ - //On calcule la valeur initiale de dest: - byte* dest=y_pos*ZOOMY*VIDEO_LINE_WIDTH+x_pos*ZOOMX+Screen_pixels; - - int x; - - for (x=0;x0;i--) - { - *(dest+2*VIDEO_LINE_WIDTH+2)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+2)=*(dest+1)=*dest=~*dest; - dest+=VIDEO_LINE_WIDTH*ZOOMY; - } -} - -void Display_brush_color_triple(word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width) -{ - // dest = Position à l'écran - byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX; - // src = Position dans la brosse - byte* src = Brush + y_offset * brush_width + x_offset; - - word x,y; - - // Pour chaque ligne - for(y = height;y > 0; y--) - { - // Pour chaque pixel - for(x = width;x > 0; x--) - { - // On vérifie que ce n'est pas la transparence - if(*src != transp_color) - { - *(dest+2*VIDEO_LINE_WIDTH+2) = *(dest+2*VIDEO_LINE_WIDTH+1) = *(dest+2*VIDEO_LINE_WIDTH) = *(dest+VIDEO_LINE_WIDTH+2) = *(dest+VIDEO_LINE_WIDTH+1) = *(dest+VIDEO_LINE_WIDTH) = *(dest+2) = *(dest+1) = *dest = *src; - } - - // Pixel suivant - src++; - dest+=ZOOMX; - } - - // On passe à la ligne suivante - dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX; - src = src + brush_width - width; - } - Update_rect(x_pos,y_pos,width,height); -} - -void Display_brush_mono_triple(word x_pos, word y_pos, - word x_offset, word y_offset, word width, word height, - byte transp_color, byte color, word brush_width) -/* On affiche la brosse en monochrome */ -{ - byte* dest=y_pos*ZOOMY*VIDEO_LINE_WIDTH+x_pos*ZOOMX+Screen_pixels; // dest = adr destination à - // l'écran - byte* src=brush_width*y_offset+x_offset+Brush; // src = adr ds - // la brosse - int x,y; - - for(y=height;y!=0;y--) - //Pour chaque ligne - { - for(x=width;x!=0;x--) - //Pour chaque pixel - { - if (*src!=transp_color) - *(dest+2*VIDEO_LINE_WIDTH+2)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+2)=*(dest+1)=*dest=color; - - // On passe au pixel suivant - src++; - dest+=ZOOMX; - } - - // On passe à la ligne suivante - src+=brush_width-width; - dest+=VIDEO_LINE_WIDTH*ZOOMY-width*ZOOMX; - } - Update_rect(x_pos,y_pos,width,height); -} - -void Clear_brush_triple(word x_pos,word y_pos,__attribute__((unused)) word x_offset,__attribute__((unused)) word y_offset,word width,word height,__attribute__((unused))byte transp_color,word image_width) -{ - byte* dest=Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH; //On va se mettre en 0,0 dans l'écran (dest) - byte* src = ( y_pos + Main_offset_Y ) * image_width + x_pos + Main_offset_X + Main_screen; //Coords de départ ds la source (src) - int y; - int x; - - for(y=height;y!=0;y--) - // Pour chaque ligne - { - for(x=width;x!=0;x--) - //Pour chaque pixel - { - *(dest+2*VIDEO_LINE_WIDTH+2)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+2)=*(dest+1)=*dest=*src; - - // On passe au pixel suivant - src++; - dest+=ZOOMX; - } - - // On passe à la ligne suivante - src+=image_width-width; - dest+=VIDEO_LINE_WIDTH*ZOOMY-width*ZOOMX; - } - Update_rect(x_pos,y_pos,width,height); -} - -// Affiche une brosse (arbitraire) à l'écran -void Display_brush_triple(byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width) -{ - // dest = Position à l'écran - byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX; - // src = Position dans la brosse - byte* src = brush + y_offset * brush_width + x_offset; - - word x,y; - - // Pour chaque ligne - for(y = height;y > 0; y--) - { - // Pour chaque pixel - for(x = width;x > 0; x--) - { - // On vérifie que ce n'est pas la transparence - if(*src != transp_color) - { - *(dest+2*VIDEO_LINE_WIDTH+2)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+2)=*(dest+1)=*dest=*src; - } - - // Pixel suivant - src++; dest+=ZOOMX; - } - - // On passe à la ligne suivante - dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX; - src = src + brush_width - width; - } -} - -void Remap_screen_triple(word x_pos,word y_pos,word width,word height,byte * conversion_table) -{ - // dest = coords a l'écran - byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX; - int x,y; - - // Pour chaque ligne - for(y=height;y>0;y--) - { - // Pour chaque pixel - for(x=width;x>0;x--) - { - *(dest+2*VIDEO_LINE_WIDTH+2)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+2)=*(dest+1)=*dest= - conversion_table[*dest]; - dest +=ZOOMX; - } - - dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX; - } - - Update_rect(x_pos,y_pos,width,height); -} - -void Display_line_on_screen_fast_triple(word x_pos,word y_pos,word width,byte * line) -/* On affiche toute une ligne de pixels telle quelle. */ -/* Utilisée si le buffer contient déja des pixel doublés. */ -{ - memcpy(Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH,line,width*ZOOMX); - memcpy(Screen_pixels+x_pos*ZOOMX+(y_pos*ZOOMY+1)*VIDEO_LINE_WIDTH,line,width*ZOOMX); - memcpy(Screen_pixels+x_pos*ZOOMX+(y_pos*ZOOMY+2)*VIDEO_LINE_WIDTH,line,width*ZOOMX); -} - -void Display_line_on_screen_triple(word x_pos,word y_pos,word width,byte * line) -/* On affiche une ligne de pixels en les doublant. */ -{ - int x; - byte *dest; - dest=Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH; - for(x=width;x>0;x--) - { - *(dest+2*VIDEO_LINE_WIDTH+2)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+2)=*(dest+1)=*dest=*line; - dest+=ZOOMX; - line++; - } -} -void Display_transparent_mono_line_on_screen_triple( - word x_pos, word y_pos, word width, byte* line, - byte transp_color, byte color) -// Affiche une ligne à l'écran avec une couleur + transparence. -// Utilisé par les brosses en mode zoom -{ - byte* dest = Screen_pixels+ y_pos*VIDEO_LINE_WIDTH + x_pos*ZOOMX; - int x; - // Pour chaque pixel - for(x=0;x 0); - src += image_width; - } -// ATTENTION on n'arrive jamais ici ! -} - -// Affiche une partie de la brosse couleur zoomée -void Display_brush_color_zoom_triple(word x_pos,word y_pos, - word x_offset,word y_offset, - word width, // width non zoomée - word end_y_pos,byte transp_color, - word brush_width, // width réelle de la brosse - byte * buffer) -{ - byte* src = Brush+y_offset*brush_width + x_offset; - word y = y_pos; - byte bx; - - // Pour chaque ligne - while(1) - { - Zoom_a_line(src,buffer,Main_magnifier_factor,width); - // On affiche facteur fois la ligne zoomée - for(bx=Main_magnifier_factor;bx>0;bx--) - { - byte* line_src = buffer; - byte* dest = Screen_pixels + y*ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX; - word x; - // Pour chaque pixel de la ligne - for(x = width*Main_magnifier_factor;x > 0;x--) - { - if(*line_src!=transp_color) - { - *(dest+2)=*(dest+1)=*dest = *line_src; - } - line_src++; - dest+=ZOOMX; - } - // Double the line - memcpy(Screen_pixels + (y*ZOOMY+1)*VIDEO_LINE_WIDTH + x_pos*ZOOMX, Screen_pixels + y*ZOOMY*VIDEO_LINE_WIDTH + x_pos*ZOOMX, width*ZOOMX*Main_magnifier_factor); - // Triple the line - memcpy(Screen_pixels + (y*ZOOMY+2)*VIDEO_LINE_WIDTH + x_pos*ZOOMX, Screen_pixels + y*ZOOMY*VIDEO_LINE_WIDTH + x_pos*ZOOMX, width*ZOOMX*Main_magnifier_factor); - y++; - if(y==end_y_pos) - { - return; - } - } - src += brush_width; - } - // ATTENTION zone jamais atteinte -} - -void Display_brush_mono_zoom_triple(word x_pos, word y_pos, - word x_offset, word y_offset, - word width, // width non zoomée - word end_y_pos, - byte transp_color, byte color, - word brush_width, // width réelle de la brosse - byte * buffer -) - -{ - byte* src = Brush + y_offset * brush_width + x_offset; - int y=y_pos*ZOOMY; - - //Pour chaque ligne à zoomer : - while(1) - { - int bx; - // src = Ligne originale - // On éclate la ligne - Zoom_a_line(src,buffer,Main_magnifier_factor,width); - - // On affiche la ligne Facteur fois à l'écran (sur des - // lignes consécutives) - bx = Main_magnifier_factor*ZOOMY; - - // Pour chaque ligne écran - do - { - // On affiche la ligne zoomée - Display_transparent_mono_line_on_screen_triple( - x_pos, y, width * Main_magnifier_factor, - buffer, transp_color, color - ); - // On passe à la ligne suivante - y++; - // On vérifie qu'on est pas à la ligne finale - if(y == end_y_pos*ZOOMY) - { - Update_rect( x_pos, y_pos, - width * Main_magnifier_factor, end_y_pos - y_pos ); - return; - } - bx --; - } - while (bx > 0); - - // Passage à la ligne suivante dans la brosse aussi - src+=brush_width; - } -} - -void Clear_brush_scaled_triple(word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,__attribute__((unused)) byte transp_color,word image_width,byte * buffer) -{ - - // En fait on va recopier l'image non zoomée dans la partie zoomée ! - byte* src = Main_screen + y_offset * image_width + x_offset; - int y = y_pos; - int bx; - - // Pour chaque ligne à zoomer - while(1){ - Zoom_a_line(src,buffer,Main_magnifier_factor*ZOOMX,width); - - bx=Main_magnifier_factor; - - // Pour chaque ligne - do{ - // TODO a verifier - Display_line_on_screen_fast_triple(x_pos,y, - width * Main_magnifier_factor,buffer); - - // Ligne suivante - y++; - if(y==end_y_pos) - { - Update_rect(x_pos,y_pos, - width*Main_magnifier_factor,end_y_pos-y_pos); - return; - } - bx--; - }while(bx!=0); - - src+= image_width; - } -} - - +/* Grafx2 - The Ultimate 256-color bitmap paint program + + Copyright 2008 Yves Rizoud + Copyright 2008 Franck Charlet + Copyright 2007 Adrien Destugues + Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) + + Grafx2 is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 + of the License. + + Grafx2 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grafx2; if not, see +*/ + +#include +#include +#include +#include "global.h" +#include "sdlscreen.h" +#include "misc.h" +#include "graph.h" +#include "pxtriple.h" + +#define ZOOMX 3 +#define ZOOMY 3 + +void Pixel_triple (word x,word y,byte color) +/* Affiche un pixel de la color aux coords x;y à l'écran */ +{ + *(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH)=color; + *(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH + 1)=color; + *(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH + 2)=color; + *(Screen_pixels + x * ZOOMX + (y*ZOOMY+1) * VIDEO_LINE_WIDTH)=color; + *(Screen_pixels + x * ZOOMX + (y*ZOOMY+1) * VIDEO_LINE_WIDTH + 1)=color; + *(Screen_pixels + x * ZOOMX + (y*ZOOMY+1) * VIDEO_LINE_WIDTH + 2)=color; + *(Screen_pixels + x * ZOOMX + (y*ZOOMY+2) * VIDEO_LINE_WIDTH)=color; + *(Screen_pixels + x * ZOOMX + (y*ZOOMY+2) * VIDEO_LINE_WIDTH + 1)=color; + *(Screen_pixels + x * ZOOMX + (y*ZOOMY+2) * VIDEO_LINE_WIDTH + 2)=color; +} + +byte Read_pixel_triple (word x,word y) +/* On retourne la couleur du pixel aux coords données */ +{ + return *( Screen_pixels + y * ZOOMY * VIDEO_LINE_WIDTH + x * ZOOMX); +} + +void Block_triple (word start_x,word start_y,word width,word height,byte color) +/* On affiche un rectangle de la couleur donnée */ +{ + SDL_Rect rectangle; + rectangle.x=start_x*ZOOMX; + rectangle.y=start_y*ZOOMY; + rectangle.w=width*ZOOMX; + rectangle.h=height*ZOOMY; + SDL_FillRect(Screen_SDL,&rectangle,color); +} + +void Display_part_of_screen_triple (word width,word height,word image_width) +/* Afficher une partie de l'image telle quelle sur l'écran */ +{ + byte* dest=Screen_pixels; //On va se mettre en 0,0 dans l'écran (dest) + byte* src=Main_offset_Y*image_width+Main_offset_X+Main_screen; //Coords de départ ds la source (src) + int y; + int dy; + + for(y=height;y!=0;y--) + // Pour chaque ligne + { + // On fait une copie de la ligne + for (dy=width;dy>0;dy--) + { + *(dest+2)=*(dest+1)=*dest=*src; + src++; + dest+=ZOOMX; + } + // On double la ligne qu'on vient de copier + memcpy(dest-width*ZOOMX+VIDEO_LINE_WIDTH,dest-width*ZOOMX,width*ZOOMX); + // On la triple + memcpy(dest-width*ZOOMX+2*VIDEO_LINE_WIDTH,dest-width*ZOOMX,width*ZOOMX); + + // On passe à la ligne suivante + src+=image_width-width; + dest+=VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX; + } + //Update_rect(0,0,width,height); +} + +void Pixel_preview_normal_triple (word x,word y,byte color) +/* Affichage d'un pixel dans l'écran, par rapport au décalage de l'image + * dans l'écran, en mode normal (pas en mode loupe) + * Note: si on modifie cette procédure, il faudra penser à faire également + * la modif dans la procédure Pixel_Preview_Loupe_SDL. */ +{ +// if(x-Main_offset_X >= 0 && y - Main_offset_Y >= 0) + Pixel_triple(x-Main_offset_X,y-Main_offset_Y,color); +} + +void Pixel_preview_magnifier_triple (word x,word y,byte color) +{ + // Affiche le pixel dans la partie non zoomée + Pixel_triple(x-Main_offset_X,y-Main_offset_Y,color); + + // Regarde si on doit aussi l'afficher dans la partie zoomée + if (y >= Limit_top_zoom && y <= Limit_visible_bottom_zoom + && x >= Limit_left_zoom && x <= Limit_visible_right_zoom) + { + // On est dedans + int height; + int y_zoom = Main_magnifier_factor * (y-Main_magnifier_offset_Y); + + if (Menu_Y - y_zoom < Main_magnifier_factor) + // On ne doit dessiner qu'un morceau du pixel + // sinon on dépasse sur le menu + height = Menu_Y - y_zoom; + else + height = Main_magnifier_factor; + + Block_triple( + Main_magnifier_factor * (x-Main_magnifier_offset_X) + Main_X_zoom, + y_zoom, Main_magnifier_factor, height, color + ); + } +} + +void Horizontal_XOR_line_triple(word x_pos,word y_pos,word width) +{ + //On calcule la valeur initiale de dest: + byte* dest=y_pos*ZOOMY*VIDEO_LINE_WIDTH+x_pos*ZOOMX+Screen_pixels; + + int x; + + for (x=0;x0;i--) + { + *(dest+2*VIDEO_LINE_WIDTH+2)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+2)=*(dest+1)=*dest=~*dest; + dest+=VIDEO_LINE_WIDTH*ZOOMY; + } +} + +void Display_brush_color_triple(word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width) +{ + // dest = Position à l'écran + byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX; + // src = Position dans la brosse + byte* src = Brush + y_offset * brush_width + x_offset; + + word x,y; + + // Pour chaque ligne + for(y = height;y > 0; y--) + { + // Pour chaque pixel + for(x = width;x > 0; x--) + { + // On vérifie que ce n'est pas la transparence + if(*src != transp_color) + { + *(dest+2*VIDEO_LINE_WIDTH+2) = *(dest+2*VIDEO_LINE_WIDTH+1) = *(dest+2*VIDEO_LINE_WIDTH) = *(dest+VIDEO_LINE_WIDTH+2) = *(dest+VIDEO_LINE_WIDTH+1) = *(dest+VIDEO_LINE_WIDTH) = *(dest+2) = *(dest+1) = *dest = *src; + } + + // Pixel suivant + src++; + dest+=ZOOMX; + } + + // On passe à la ligne suivante + dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX; + src = src + brush_width - width; + } + Update_rect(x_pos,y_pos,width,height); +} + +void Display_brush_mono_triple(word x_pos, word y_pos, + word x_offset, word y_offset, word width, word height, + byte transp_color, byte color, word brush_width) +/* On affiche la brosse en monochrome */ +{ + byte* dest=y_pos*ZOOMY*VIDEO_LINE_WIDTH+x_pos*ZOOMX+Screen_pixels; // dest = adr destination à + // l'écran + byte* src=brush_width*y_offset+x_offset+Brush; // src = adr ds + // la brosse + int x,y; + + for(y=height;y!=0;y--) + //Pour chaque ligne + { + for(x=width;x!=0;x--) + //Pour chaque pixel + { + if (*src!=transp_color) + *(dest+2*VIDEO_LINE_WIDTH+2)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+2)=*(dest+1)=*dest=color; + + // On passe au pixel suivant + src++; + dest+=ZOOMX; + } + + // On passe à la ligne suivante + src+=brush_width-width; + dest+=VIDEO_LINE_WIDTH*ZOOMY-width*ZOOMX; + } + Update_rect(x_pos,y_pos,width,height); +} + +void Clear_brush_triple(word x_pos,word y_pos,__attribute__((unused)) word x_offset,__attribute__((unused)) word y_offset,word width,word height,__attribute__((unused))byte transp_color,word image_width) +{ + byte* dest=Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH; //On va se mettre en 0,0 dans l'écran (dest) + byte* src = ( y_pos + Main_offset_Y ) * image_width + x_pos + Main_offset_X + Main_screen; //Coords de départ ds la source (src) + int y; + int x; + + for(y=height;y!=0;y--) + // Pour chaque ligne + { + for(x=width;x!=0;x--) + //Pour chaque pixel + { + *(dest+2*VIDEO_LINE_WIDTH+2)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+2)=*(dest+1)=*dest=*src; + + // On passe au pixel suivant + src++; + dest+=ZOOMX; + } + + // On passe à la ligne suivante + src+=image_width-width; + dest+=VIDEO_LINE_WIDTH*ZOOMY-width*ZOOMX; + } + Update_rect(x_pos,y_pos,width,height); +} + +// Affiche une brosse (arbitraire) à l'écran +void Display_brush_triple(byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width) +{ + // dest = Position à l'écran + byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX; + // src = Position dans la brosse + byte* src = brush + y_offset * brush_width + x_offset; + + word x,y; + + // Pour chaque ligne + for(y = height;y > 0; y--) + { + // Pour chaque pixel + for(x = width;x > 0; x--) + { + // On vérifie que ce n'est pas la transparence + if(*src != transp_color) + { + *(dest+2*VIDEO_LINE_WIDTH+2)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+2)=*(dest+1)=*dest=*src; + } + + // Pixel suivant + src++; dest+=ZOOMX; + } + + // On passe à la ligne suivante + dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX; + src = src + brush_width - width; + } +} + +void Remap_screen_triple(word x_pos,word y_pos,word width,word height,byte * conversion_table) +{ + // dest = coords a l'écran + byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX; + int x,y; + + // Pour chaque ligne + for(y=height;y>0;y--) + { + // Pour chaque pixel + for(x=width;x>0;x--) + { + *(dest+2*VIDEO_LINE_WIDTH+2)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+2)=*(dest+1)=*dest= + conversion_table[*dest]; + dest +=ZOOMX; + } + + dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX; + } + + Update_rect(x_pos,y_pos,width,height); +} + +void Display_line_on_screen_fast_triple(word x_pos,word y_pos,word width,byte * line) +/* On affiche toute une ligne de pixels telle quelle. */ +/* Utilisée si le buffer contient déja des pixel doublés. */ +{ + memcpy(Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH,line,width*ZOOMX); + memcpy(Screen_pixels+x_pos*ZOOMX+(y_pos*ZOOMY+1)*VIDEO_LINE_WIDTH,line,width*ZOOMX); + memcpy(Screen_pixels+x_pos*ZOOMX+(y_pos*ZOOMY+2)*VIDEO_LINE_WIDTH,line,width*ZOOMX); +} + +void Display_line_on_screen_triple(word x_pos,word y_pos,word width,byte * line) +/* On affiche une ligne de pixels en les doublant. */ +{ + int x; + byte *dest; + dest=Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH; + for(x=width;x>0;x--) + { + *(dest+2*VIDEO_LINE_WIDTH+2)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+2)=*(dest+1)=*dest=*line; + dest+=ZOOMX; + line++; + } +} +void Display_transparent_mono_line_on_screen_triple( + word x_pos, word y_pos, word width, byte* line, + byte transp_color, byte color) +// Affiche une ligne à l'écran avec une couleur + transparence. +// Utilisé par les brosses en mode zoom +{ + byte* dest = Screen_pixels+ y_pos*VIDEO_LINE_WIDTH + x_pos*ZOOMX; + int x; + // Pour chaque pixel + for(x=0;x 0); + src += image_width; + } +// ATTENTION on n'arrive jamais ici ! +} + +// Affiche une partie de la brosse couleur zoomée +void Display_brush_color_zoom_triple(word x_pos,word y_pos, + word x_offset,word y_offset, + word width, // width non zoomée + word end_y_pos,byte transp_color, + word brush_width, // width réelle de la brosse + byte * buffer) +{ + byte* src = Brush+y_offset*brush_width + x_offset; + word y = y_pos; + byte bx; + + // Pour chaque ligne + while(1) + { + Zoom_a_line(src,buffer,Main_magnifier_factor,width); + // On affiche facteur fois la ligne zoomée + for(bx=Main_magnifier_factor;bx>0;bx--) + { + byte* line_src = buffer; + byte* dest = Screen_pixels + y*ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX; + word x; + // Pour chaque pixel de la ligne + for(x = width*Main_magnifier_factor;x > 0;x--) + { + if(*line_src!=transp_color) + { + *(dest+2)=*(dest+1)=*dest = *line_src; + } + line_src++; + dest+=ZOOMX; + } + // Double the line + memcpy(Screen_pixels + (y*ZOOMY+1)*VIDEO_LINE_WIDTH + x_pos*ZOOMX, Screen_pixels + y*ZOOMY*VIDEO_LINE_WIDTH + x_pos*ZOOMX, width*ZOOMX*Main_magnifier_factor); + // Triple the line + memcpy(Screen_pixels + (y*ZOOMY+2)*VIDEO_LINE_WIDTH + x_pos*ZOOMX, Screen_pixels + y*ZOOMY*VIDEO_LINE_WIDTH + x_pos*ZOOMX, width*ZOOMX*Main_magnifier_factor); + y++; + if(y==end_y_pos) + { + return; + } + } + src += brush_width; + } + // ATTENTION zone jamais atteinte +} + +void Display_brush_mono_zoom_triple(word x_pos, word y_pos, + word x_offset, word y_offset, + word width, // width non zoomée + word end_y_pos, + byte transp_color, byte color, + word brush_width, // width réelle de la brosse + byte * buffer +) + +{ + byte* src = Brush + y_offset * brush_width + x_offset; + int y=y_pos*ZOOMY; + + //Pour chaque ligne à zoomer : + while(1) + { + int bx; + // src = Ligne originale + // On éclate la ligne + Zoom_a_line(src,buffer,Main_magnifier_factor,width); + + // On affiche la ligne Facteur fois à l'écran (sur des + // lignes consécutives) + bx = Main_magnifier_factor*ZOOMY; + + // Pour chaque ligne écran + do + { + // On affiche la ligne zoomée + Display_transparent_mono_line_on_screen_triple( + x_pos, y, width * Main_magnifier_factor, + buffer, transp_color, color + ); + // On passe à la ligne suivante + y++; + // On vérifie qu'on est pas à la ligne finale + if(y == end_y_pos*ZOOMY) + { + Redraw_grid( x_pos, y_pos, + width * Main_magnifier_factor, end_y_pos - y_pos ); + Update_rect( x_pos, y_pos, + width * Main_magnifier_factor, end_y_pos - y_pos ); + return; + } + bx --; + } + while (bx > 0); + + // Passage à la ligne suivante dans la brosse aussi + src+=brush_width; + } +} + +void Clear_brush_scaled_triple(word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,__attribute__((unused)) byte transp_color,word image_width,byte * buffer) +{ + + // En fait on va recopier l'image non zoomée dans la partie zoomée ! + byte* src = Main_screen + y_offset * image_width + x_offset; + int y = y_pos; + int bx; + + // Pour chaque ligne à zoomer + while(1){ + Zoom_a_line(src,buffer,Main_magnifier_factor*ZOOMX,width); + + bx=Main_magnifier_factor; + + // Pour chaque ligne + do{ + // TODO a verifier + Display_line_on_screen_fast_triple(x_pos,y, + width * Main_magnifier_factor,buffer); + + // Ligne suivante + y++; + if(y==end_y_pos) + { + Redraw_grid(x_pos,y_pos, + width*Main_magnifier_factor,end_y_pos-y_pos); + Update_rect(x_pos,y_pos, + width*Main_magnifier_factor,end_y_pos-y_pos); + return; + } + bx--; + }while(bx!=0); + + src+= image_width; + } +} + + diff --git a/pxtriple.h b/pxtriple.h index 15c03e6d..6e470548 100644 --- a/pxtriple.h +++ b/pxtriple.h @@ -1,48 +1,48 @@ -/* Grafx2 - The Ultimate 256-color bitmap paint program - - Copyright 2008 Yves Rizoud - Copyright 2007 Adrien Destugues - Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) - - Grafx2 is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; version 2 - of the License. - - Grafx2 is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Grafx2; if not, see -*/ - -////////////////////////////////////////////////////////////////////////////// -///@file pxtriple.h -/// Renderer for triple pixels (3x3). -////////////////////////////////////////////////////////////////////////////// - -#include "struct.h" - - void Pixel_triple (word x,word y,byte color); - byte Read_pixel_triple (word x,word y); - void Block_triple (word start_x,word start_y,word width,word height,byte color); - void Pixel_preview_normal_triple (word x,word y,byte color); - void Pixel_preview_magnifier_triple (word x,word y,byte color); - void Horizontal_XOR_line_triple (word x_pos,word y_pos,word width); - void Vertical_XOR_line_triple (word x_pos,word y_pos,word height); - void Display_brush_color_triple (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width); - void Display_brush_mono_triple (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,byte color,word brush_width); - void Clear_brush_triple (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word image_width); - void Remap_screen_triple (word x_pos,word y_pos,word width,word height,byte * conversion_table); - void Display_part_of_screen_triple (word width,word height,word image_width); - void Display_line_on_screen_triple (word x_pos,word y_pos,word width,byte * line); - void Read_line_screen_triple (word x_pos,word y_pos,word width,byte * line); - void Display_part_of_screen_scaled_triple(word width,word height,word image_width,byte * buffer); - void Display_brush_color_zoom_triple (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,word brush_width,byte * buffer); - void Display_brush_mono_zoom_triple (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,byte color,word brush_width,byte * buffer); - void Clear_brush_scaled_triple (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,word image_width,byte * buffer); - void Display_brush_triple (byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width); - - void Display_line_on_screen_fast_triple (word x_pos,word y_pos,word width,byte * line); +/* Grafx2 - The Ultimate 256-color bitmap paint program + + Copyright 2008 Yves Rizoud + Copyright 2007 Adrien Destugues + Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) + + Grafx2 is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 + of the License. + + Grafx2 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grafx2; if not, see +*/ + +////////////////////////////////////////////////////////////////////////////// +///@file pxtriple.h +/// Renderer for triple pixels (3x3). +////////////////////////////////////////////////////////////////////////////// + +#include "struct.h" + + void Pixel_triple (word x,word y,byte color); + byte Read_pixel_triple (word x,word y); + void Block_triple (word start_x,word start_y,word width,word height,byte color); + void Pixel_preview_normal_triple (word x,word y,byte color); + void Pixel_preview_magnifier_triple (word x,word y,byte color); + void Horizontal_XOR_line_triple (word x_pos,word y_pos,word width); + void Vertical_XOR_line_triple (word x_pos,word y_pos,word height); + void Display_brush_color_triple (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width); + void Display_brush_mono_triple (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,byte color,word brush_width); + void Clear_brush_triple (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word image_width); + void Remap_screen_triple (word x_pos,word y_pos,word width,word height,byte * conversion_table); + void Display_part_of_screen_triple (word width,word height,word image_width); + void Display_line_on_screen_triple (word x_pos,word y_pos,word width,byte * line); + void Read_line_screen_triple (word x_pos,word y_pos,word width,byte * line); + void Display_part_of_screen_scaled_triple(word width,word height,word image_width,byte * buffer); + void Display_brush_color_zoom_triple (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,word brush_width,byte * buffer); + void Display_brush_mono_zoom_triple (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,byte color,word brush_width,byte * buffer); + void Clear_brush_scaled_triple (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,word image_width,byte * buffer); + void Display_brush_triple (byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width); + + void Display_line_on_screen_fast_triple (word x_pos,word y_pos,word width,byte * line); diff --git a/pxwide.c b/pxwide.c index ffabba61..f0d60074 100644 --- a/pxwide.c +++ b/pxwide.c @@ -1,506 +1,513 @@ -/* Grafx2 - The Ultimate 256-color bitmap paint program - - Copyright 2008 Yves Rizoud - Copyright 2008 Franck Charlet - Copyright 2007 Adrien Destugues - Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) - - Grafx2 is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; version 2 - of the License. - - Grafx2 is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Grafx2; if not, see -*/ - -#include -#include -#include -#include "global.h" -#include "sdlscreen.h" -#include "misc.h" -#include "pxwide.h" - -#define ZOOMX 2 -#define ZOOMY 1 - -void Pixel_wide (word x,word y,byte color) -/* Affiche un pixel de la color aux coords x;y à l'écran */ -{ - *(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH)=color; - *(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH + 1)=color; -} - -byte Read_pixel_wide (word x,word y) -/* On retourne la couleur du pixel aux coords données */ -{ - return *( Screen_pixels + y * ZOOMY * VIDEO_LINE_WIDTH + x * ZOOMX); -} - -void Block_wide (word start_x,word start_y,word width,word height,byte color) -/* On affiche un rectangle de la couleur donnée */ -{ - SDL_Rect rectangle; - rectangle.x=start_x*ZOOMX; - rectangle.y=start_y*ZOOMY; - rectangle.w=width*ZOOMX; - rectangle.h=height*ZOOMY; - SDL_FillRect(Screen_SDL,&rectangle,color); -} - -void Display_part_of_screen_wide (word width,word height,word image_width) -/* Afficher une partie de l'image telle quelle sur l'écran */ -{ - byte* dest=Screen_pixels; //On va se mettre en 0,0 dans l'écran (dest) - byte* src=Main_offset_Y*image_width+Main_offset_X+Main_screen; //Coords de départ ds la source (src) - int y; - int dy; - - for(y=height;y!=0;y--) - // Pour chaque ligne - { - // On fait une copie de la ligne - for (dy=width;dy>0;dy--) - { - *(dest+1)=*dest=*src; - src++; - dest+=ZOOMX; - } - - // On passe à la ligne suivante - src+=image_width-width; - dest+=VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX; - } - //Update_rect(0,0,width,height); -} - -void Pixel_preview_normal_wide (word x,word y,byte color) -/* Affichage d'un pixel dans l'écran, par rapport au décalage de l'image - * dans l'écran, en mode normal (pas en mode loupe) - * Note: si on modifie cette procédure, il faudra penser à faire également - * la modif dans la procédure Pixel_Preview_Loupe_SDL. */ -{ -// if(x-Main_offset_X >= 0 && y - Main_offset_Y >= 0) - Pixel_wide(x-Main_offset_X,y-Main_offset_Y,color); -} - -void Pixel_preview_magnifier_wide (word x,word y,byte color) -{ - // Affiche le pixel dans la partie non zoomée - Pixel_wide(x-Main_offset_X,y-Main_offset_Y,color); - - // Regarde si on doit aussi l'afficher dans la partie zoomée - if (y >= Limit_top_zoom && y <= Limit_visible_bottom_zoom - && x >= Limit_left_zoom && x <= Limit_visible_right_zoom) - { - // On est dedans - int height; - int y_zoom = Main_magnifier_factor * (y-Main_magnifier_offset_Y); - - if (Menu_Y - y_zoom < Main_magnifier_factor) - // On ne doit dessiner qu'un morceau du pixel - // sinon on dépasse sur le menu - height = Menu_Y - y_zoom; - else - height = Main_magnifier_factor; - - Block_wide( - Main_magnifier_factor * (x-Main_magnifier_offset_X) + Main_X_zoom, - y_zoom, Main_magnifier_factor, height, color - ); - } -} - -void Horizontal_XOR_line_wide(word x_pos,word y_pos,word width) -{ - //On calcule la valeur initiale de dest: - byte* dest=y_pos*ZOOMY*VIDEO_LINE_WIDTH+x_pos*ZOOMX+Screen_pixels; - - int x; - - for (x=0;x0;i--) - { - *dest=*(dest+1)=~*dest; - dest+=VIDEO_LINE_WIDTH*ZOOMY; - } -} - -void Display_brush_color_wide(word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width) -{ - // dest = Position à l'écran - byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX; - // src = Position dans la brosse - byte* src = Brush + y_offset * brush_width + x_offset; - - word x,y; - - // Pour chaque ligne - for(y = height;y > 0; y--) - { - // Pour chaque pixel - for(x = width;x > 0; x--) - { - // On vérifie que ce n'est pas la transparence - if(*src != transp_color) - { - *(dest+1) = *dest = *src; - } - - // Pixel suivant - src++; - dest+=ZOOMX; - } - - // On passe à la ligne suivante - dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX; - src = src + brush_width - width; - } - Update_rect(x_pos,y_pos,width,height); -} - -void Display_brush_mono_wide(word x_pos, word y_pos, - word x_offset, word y_offset, word width, word height, - byte transp_color, byte color, word brush_width) -/* On affiche la brosse en monochrome */ -{ - byte* dest=y_pos*ZOOMY*VIDEO_LINE_WIDTH+x_pos*ZOOMX+Screen_pixels; // dest = adr destination à - // l'écran - byte* src=brush_width*y_offset+x_offset+Brush; // src = adr ds - // la brosse - int x,y; - - for(y=height;y!=0;y--) - //Pour chaque ligne - { - for(x=width;x!=0;x--) - //Pour chaque pixel - { - if (*src!=transp_color) - *(dest+1)=*dest=color; - - // On passe au pixel suivant - src++; - dest+=ZOOMX; - } - - // On passe à la ligne suivante - src+=brush_width-width; - dest+=VIDEO_LINE_WIDTH*ZOOMY-width*ZOOMX; - } - Update_rect(x_pos,y_pos,width,height); -} - -void Clear_brush_wide(word x_pos,word y_pos,__attribute__((unused)) word x_offset,__attribute__((unused)) word y_offset,word width,word height,__attribute__((unused))byte transp_color,word image_width) -{ - byte* dest=Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH; //On va se mettre en 0,0 dans l'écran (dest) - byte* src = ( y_pos + Main_offset_Y ) * image_width + x_pos + Main_offset_X + Main_screen; //Coords de départ ds la source (src) - int y; - int x; - - for(y=height;y!=0;y--) - // Pour chaque ligne - { - for(x=width;x!=0;x--) - //Pour chaque pixel - { - *(dest+1)=*dest=*src; - - // On passe au pixel suivant - src++; - dest+=ZOOMX; - } - - // On passe à la ligne suivante - src+=image_width-width; - dest+=VIDEO_LINE_WIDTH*ZOOMY-width*ZOOMX; - } - Update_rect(x_pos,y_pos,width,height); -} - -// Affiche une brosse (arbitraire) à l'écran -void Display_brush_wide(byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width) -{ - // dest = Position à l'écran - byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX; - // src = Position dans la brosse - byte* src = brush + y_offset * brush_width + x_offset; - - word x,y; - - // Pour chaque ligne - for(y = height;y > 0; y--) - { - // Pour chaque pixel - for(x = width;x > 0; x--) - { - // On vérifie que ce n'est pas la transparence - if(*src != transp_color) - { - *(dest+1) = *dest = *src; - } - - // Pixel suivant - src++; dest+=ZOOMX; - } - - // On passe à la ligne suivante - dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX; - src = src + brush_width - width; - } -} - -void Remap_screen_wide(word x_pos,word y_pos,word width,word height,byte * conversion_table) -{ - // dest = coords a l'écran - byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX; - int x,y; - - // Pour chaque ligne - for(y=height;y>0;y--) - { - // Pour chaque pixel - for(x=width;x>0;x--) - { - *(dest+1) = *dest = conversion_table[*dest]; - dest +=ZOOMX; - } - - dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX; - } - - Update_rect(x_pos,y_pos,width,height); -} - -void Display_line_on_screen_fast_wide(word x_pos,word y_pos,word width,byte * line) -/* On affiche toute une ligne de pixels telle quelle. */ -/* Utilisée si le buffer contient déja des pixel doublés. */ -{ - memcpy(Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH,line,width*ZOOMX); -} - -void Display_line_on_screen_wide(word x_pos,word y_pos,word width,byte * line) -/* On affiche une ligne de pixels en les doublant. */ -{ - int x; - byte *dest; - dest=Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH; - for(x=width;x>0;x--) - { - *(dest+1)=*dest=*line; - dest+=ZOOMX; - line++; - } -} -void Display_transparent_mono_line_on_screen_wide( - word x_pos, word y_pos, word width, byte* line, - byte transp_color, byte color) -// Affiche une ligne à l'écran avec une couleur + transparence. -// Utilisé par les brosses en mode zoom -{ - byte* dest = Screen_pixels+ y_pos*VIDEO_LINE_WIDTH + x_pos*ZOOMX; - int x; - // Pour chaque pixel - for(x=0;x 0); - src += image_width; - } -// ATTENTION on n'arrive jamais ici ! -} - -void Display_transparent_line_on_screen_wide(word x_pos,word y_pos,word width,byte* line,byte transp_color) -{ - byte* src = line; - byte* dest = Screen_pixels+ y_pos*VIDEO_LINE_WIDTH + x_pos*ZOOMX; - word x; - - // Pour chaque pixel de la ligne - for(x = width;x > 0;x--) - { - if(*src!=transp_color) - { - *(dest+1) = *dest = *src; - } - src++; - dest+=ZOOMX; - } -} - -// Affiche une partie de la brosse couleur zoomée -void Display_brush_color_zoom_wide(word x_pos,word y_pos, - word x_offset,word y_offset, - word width, // width non zoomée - word end_y_pos,byte transp_color, - word brush_width, // width réelle de la brosse - byte * buffer) -{ - byte* src = Brush+y_offset*brush_width + x_offset; - word y = y_pos; - byte bx; - - // Pour chaque ligne - while(1) - { - Zoom_a_line(src,buffer,Main_magnifier_factor,width); - // On affiche facteur fois la ligne zoomée - for(bx=Main_magnifier_factor;bx>0;bx--) - { - Display_transparent_line_on_screen_wide(x_pos,y*ZOOMY,width*Main_magnifier_factor,buffer,transp_color); - y++; - if(y==end_y_pos) - { - return; - } - } - src += brush_width; - } - // ATTENTION zone jamais atteinte -} - -void Display_brush_mono_zoom_wide(word x_pos, word y_pos, - word x_offset, word y_offset, - word width, // width non zoomée - word end_y_pos, - byte transp_color, byte color, - word brush_width, // width réelle de la brosse - byte * buffer -) - -{ - byte* src = Brush + y_offset * brush_width + x_offset; - int y=y_pos*ZOOMY; - - //Pour chaque ligne à zoomer : - while(1) - { - int bx; - // src = Ligne originale - // On éclate la ligne - Zoom_a_line(src,buffer,Main_magnifier_factor,width); - - // On affiche la ligne Facteur fois à l'écran (sur des - // lignes consécutives) - bx = Main_magnifier_factor*ZOOMY; - - // Pour chaque ligne écran - do - { - // On affiche la ligne zoomée - Display_transparent_mono_line_on_screen_wide( - x_pos, y, width * Main_magnifier_factor, - buffer, transp_color, color - ); - // On passe à la ligne suivante - y++; - // On vérifie qu'on est pas à la ligne finale - if(y == end_y_pos*ZOOMY) - { - Update_rect( x_pos, y_pos, - width * Main_magnifier_factor, end_y_pos - y_pos ); - return; - } - bx --; - } - while (bx > 0); - - // Passage à la ligne suivante dans la brosse aussi - src+=brush_width; - } -} - -void Clear_brush_scaled_wide(word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,__attribute__((unused)) byte transp_color,word image_width,byte * buffer) -{ - // En fait on va recopier l'image non zoomée dans la partie zoomée ! - byte* src = Main_screen + y_offset * image_width + x_offset; - int y = y_pos; - int bx; - - // Pour chaque ligne à zoomer - while(1){ - Zoom_a_line(src,buffer,Main_magnifier_factor*ZOOMX,width); - - bx=Main_magnifier_factor; - - // Pour chaque ligne - do{ - Display_line_on_screen_fast_wide(x_pos,y, - width * Main_magnifier_factor,buffer); - - // Ligne suivante - y++; - if(y==end_y_pos) - { - Update_rect(x_pos,y_pos, - width*Main_magnifier_factor,end_y_pos-y_pos); - return; - } - bx--; - }while(bx!=0); - - src+= image_width; - } -} - - +/* Grafx2 - The Ultimate 256-color bitmap paint program + + Copyright 2008 Yves Rizoud + Copyright 2008 Franck Charlet + Copyright 2007 Adrien Destugues + Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) + + Grafx2 is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 + of the License. + + Grafx2 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grafx2; if not, see +*/ + +#include +#include +#include +#include "global.h" +#include "sdlscreen.h" +#include "misc.h" +#include "graph.h" +#include "pxwide.h" + +#define ZOOMX 2 +#define ZOOMY 1 + +void Pixel_wide (word x,word y,byte color) +/* Affiche un pixel de la color aux coords x;y à l'écran */ +{ + *(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH)=color; + *(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH + 1)=color; +} + +byte Read_pixel_wide (word x,word y) +/* On retourne la couleur du pixel aux coords données */ +{ + return *( Screen_pixels + y * ZOOMY * VIDEO_LINE_WIDTH + x * ZOOMX); +} + +void Block_wide (word start_x,word start_y,word width,word height,byte color) +/* On affiche un rectangle de la couleur donnée */ +{ + SDL_Rect rectangle; + rectangle.x=start_x*ZOOMX; + rectangle.y=start_y*ZOOMY; + rectangle.w=width*ZOOMX; + rectangle.h=height*ZOOMY; + SDL_FillRect(Screen_SDL,&rectangle,color); +} + +void Display_part_of_screen_wide (word width,word height,word image_width) +/* Afficher une partie de l'image telle quelle sur l'écran */ +{ + byte* dest=Screen_pixels; //On va se mettre en 0,0 dans l'écran (dest) + byte* src=Main_offset_Y*image_width+Main_offset_X+Main_screen; //Coords de départ ds la source (src) + int y; + int dy; + + for(y=height;y!=0;y--) + // Pour chaque ligne + { + // On fait une copie de la ligne + for (dy=width;dy>0;dy--) + { + *(dest+1)=*dest=*src; + src++; + dest+=ZOOMX; + } + + // On passe à la ligne suivante + src+=image_width-width; + dest+=VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX; + } + //Update_rect(0,0,width,height); +} + +void Pixel_preview_normal_wide (word x,word y,byte color) +/* Affichage d'un pixel dans l'écran, par rapport au décalage de l'image + * dans l'écran, en mode normal (pas en mode loupe) + * Note: si on modifie cette procédure, il faudra penser à faire également + * la modif dans la procédure Pixel_Preview_Loupe_SDL. */ +{ +// if(x-Main_offset_X >= 0 && y - Main_offset_Y >= 0) + Pixel_wide(x-Main_offset_X,y-Main_offset_Y,color); +} + +void Pixel_preview_magnifier_wide (word x,word y,byte color) +{ + // Affiche le pixel dans la partie non zoomée + Pixel_wide(x-Main_offset_X,y-Main_offset_Y,color); + + // Regarde si on doit aussi l'afficher dans la partie zoomée + if (y >= Limit_top_zoom && y <= Limit_visible_bottom_zoom + && x >= Limit_left_zoom && x <= Limit_visible_right_zoom) + { + // On est dedans + int height; + int y_zoom = Main_magnifier_factor * (y-Main_magnifier_offset_Y); + + if (Menu_Y - y_zoom < Main_magnifier_factor) + // On ne doit dessiner qu'un morceau du pixel + // sinon on dépasse sur le menu + height = Menu_Y - y_zoom; + else + height = Main_magnifier_factor; + + Block_wide( + Main_magnifier_factor * (x-Main_magnifier_offset_X) + Main_X_zoom, + y_zoom, Main_magnifier_factor, height, color + ); + } +} + +void Horizontal_XOR_line_wide(word x_pos,word y_pos,word width) +{ + //On calcule la valeur initiale de dest: + byte* dest=y_pos*ZOOMY*VIDEO_LINE_WIDTH+x_pos*ZOOMX+Screen_pixels; + + int x; + + for (x=0;x0;i--) + { + *dest=*(dest+1)=~*dest; + dest+=VIDEO_LINE_WIDTH*ZOOMY; + } +} + +void Display_brush_color_wide(word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width) +{ + // dest = Position à l'écran + byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX; + // src = Position dans la brosse + byte* src = Brush + y_offset * brush_width + x_offset; + + word x,y; + + // Pour chaque ligne + for(y = height;y > 0; y--) + { + // Pour chaque pixel + for(x = width;x > 0; x--) + { + // On vérifie que ce n'est pas la transparence + if(*src != transp_color) + { + *(dest+1) = *dest = *src; + } + + // Pixel suivant + src++; + dest+=ZOOMX; + } + + // On passe à la ligne suivante + dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX; + src = src + brush_width - width; + } + Update_rect(x_pos,y_pos,width,height); +} + +void Display_brush_mono_wide(word x_pos, word y_pos, + word x_offset, word y_offset, word width, word height, + byte transp_color, byte color, word brush_width) +/* On affiche la brosse en monochrome */ +{ + byte* dest=y_pos*ZOOMY*VIDEO_LINE_WIDTH+x_pos*ZOOMX+Screen_pixels; // dest = adr destination à + // l'écran + byte* src=brush_width*y_offset+x_offset+Brush; // src = adr ds + // la brosse + int x,y; + + for(y=height;y!=0;y--) + //Pour chaque ligne + { + for(x=width;x!=0;x--) + //Pour chaque pixel + { + if (*src!=transp_color) + *(dest+1)=*dest=color; + + // On passe au pixel suivant + src++; + dest+=ZOOMX; + } + + // On passe à la ligne suivante + src+=brush_width-width; + dest+=VIDEO_LINE_WIDTH*ZOOMY-width*ZOOMX; + } + Update_rect(x_pos,y_pos,width,height); +} + +void Clear_brush_wide(word x_pos,word y_pos,__attribute__((unused)) word x_offset,__attribute__((unused)) word y_offset,word width,word height,__attribute__((unused))byte transp_color,word image_width) +{ + byte* dest=Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH; //On va se mettre en 0,0 dans l'écran (dest) + byte* src = ( y_pos + Main_offset_Y ) * image_width + x_pos + Main_offset_X + Main_screen; //Coords de départ ds la source (src) + int y; + int x; + + for(y=height;y!=0;y--) + // Pour chaque ligne + { + for(x=width;x!=0;x--) + //Pour chaque pixel + { + *(dest+1)=*dest=*src; + + // On passe au pixel suivant + src++; + dest+=ZOOMX; + } + + // On passe à la ligne suivante + src+=image_width-width; + dest+=VIDEO_LINE_WIDTH*ZOOMY-width*ZOOMX; + } + Update_rect(x_pos,y_pos,width,height); +} + +// Affiche une brosse (arbitraire) à l'écran +void Display_brush_wide(byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width) +{ + // dest = Position à l'écran + byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX; + // src = Position dans la brosse + byte* src = brush + y_offset * brush_width + x_offset; + + word x,y; + + // Pour chaque ligne + for(y = height;y > 0; y--) + { + // Pour chaque pixel + for(x = width;x > 0; x--) + { + // On vérifie que ce n'est pas la transparence + if(*src != transp_color) + { + *(dest+1) = *dest = *src; + } + + // Pixel suivant + src++; dest+=ZOOMX; + } + + // On passe à la ligne suivante + dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX; + src = src + brush_width - width; + } +} + +void Remap_screen_wide(word x_pos,word y_pos,word width,word height,byte * conversion_table) +{ + // dest = coords a l'écran + byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX; + int x,y; + + // Pour chaque ligne + for(y=height;y>0;y--) + { + // Pour chaque pixel + for(x=width;x>0;x--) + { + *(dest+1) = *dest = conversion_table[*dest]; + dest +=ZOOMX; + } + + dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX; + } + + Update_rect(x_pos,y_pos,width,height); +} + +void Display_line_on_screen_fast_wide(word x_pos,word y_pos,word width,byte * line) +/* On affiche toute une ligne de pixels telle quelle. */ +/* Utilisée si le buffer contient déja des pixel doublés. */ +{ + memcpy(Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH,line,width*ZOOMX); +} + +void Display_line_on_screen_wide(word x_pos,word y_pos,word width,byte * line) +/* On affiche une ligne de pixels en les doublant. */ +{ + int x; + byte *dest; + dest=Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH; + for(x=width;x>0;x--) + { + *(dest+1)=*dest=*line; + dest+=ZOOMX; + line++; + } +} +void Display_transparent_mono_line_on_screen_wide( + word x_pos, word y_pos, word width, byte* line, + byte transp_color, byte color) +// Affiche une ligne à l'écran avec une couleur + transparence. +// Utilisé par les brosses en mode zoom +{ + byte* dest = Screen_pixels+ y_pos*VIDEO_LINE_WIDTH + x_pos*ZOOMX; + int x; + // Pour chaque pixel + for(x=0;x 0); + src += image_width; + } +// ATTENTION on n'arrive jamais ici ! +} + +void Display_transparent_line_on_screen_wide(word x_pos,word y_pos,word width,byte* line,byte transp_color) +{ + byte* src = line; + byte* dest = Screen_pixels+ y_pos*VIDEO_LINE_WIDTH + x_pos*ZOOMX; + word x; + + // Pour chaque pixel de la ligne + for(x = width;x > 0;x--) + { + if(*src!=transp_color) + { + *(dest+1) = *dest = *src; + } + src++; + dest+=ZOOMX; + } +} + +// Affiche une partie de la brosse couleur zoomée +void Display_brush_color_zoom_wide(word x_pos,word y_pos, + word x_offset,word y_offset, + word width, // width non zoomée + word end_y_pos,byte transp_color, + word brush_width, // width réelle de la brosse + byte * buffer) +{ + byte* src = Brush+y_offset*brush_width + x_offset; + word y = y_pos; + byte bx; + + // Pour chaque ligne + while(1) + { + Zoom_a_line(src,buffer,Main_magnifier_factor,width); + // On affiche facteur fois la ligne zoomée + for(bx=Main_magnifier_factor;bx>0;bx--) + { + Display_transparent_line_on_screen_wide(x_pos,y*ZOOMY,width*Main_magnifier_factor,buffer,transp_color); + y++; + if(y==end_y_pos) + { + return; + } + } + src += brush_width; + } + // ATTENTION zone jamais atteinte +} + +void Display_brush_mono_zoom_wide(word x_pos, word y_pos, + word x_offset, word y_offset, + word width, // width non zoomée + word end_y_pos, + byte transp_color, byte color, + word brush_width, // width réelle de la brosse + byte * buffer +) + +{ + byte* src = Brush + y_offset * brush_width + x_offset; + int y=y_pos*ZOOMY; + + //Pour chaque ligne à zoomer : + while(1) + { + int bx; + // src = Ligne originale + // On éclate la ligne + Zoom_a_line(src,buffer,Main_magnifier_factor,width); + + // On affiche la ligne Facteur fois à l'écran (sur des + // lignes consécutives) + bx = Main_magnifier_factor*ZOOMY; + + // Pour chaque ligne écran + do + { + // On affiche la ligne zoomée + Display_transparent_mono_line_on_screen_wide( + x_pos, y, width * Main_magnifier_factor, + buffer, transp_color, color + ); + // On passe à la ligne suivante + y++; + // On vérifie qu'on est pas à la ligne finale + if(y == end_y_pos*ZOOMY) + { + Redraw_grid( x_pos, y_pos, + width * Main_magnifier_factor, end_y_pos - y_pos ); + Update_rect( x_pos, y_pos, + width * Main_magnifier_factor, end_y_pos - y_pos ); + return; + } + bx --; + } + while (bx > 0); + + // Passage à la ligne suivante dans la brosse aussi + src+=brush_width; + } +} + +void Clear_brush_scaled_wide(word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,__attribute__((unused)) byte transp_color,word image_width,byte * buffer) +{ + // En fait on va recopier l'image non zoomée dans la partie zoomée ! + byte* src = Main_screen + y_offset * image_width + x_offset; + int y = y_pos; + int bx; + + // Pour chaque ligne à zoomer + while(1){ + Zoom_a_line(src,buffer,Main_magnifier_factor*ZOOMX,width); + + bx=Main_magnifier_factor; + + // Pour chaque ligne + do{ + Display_line_on_screen_fast_wide(x_pos,y, + width * Main_magnifier_factor,buffer); + + // Ligne suivante + y++; + if(y==end_y_pos) + { + Redraw_grid(x_pos,y_pos, + width*Main_magnifier_factor,end_y_pos-y_pos); + Update_rect(x_pos,y_pos, + width*Main_magnifier_factor,end_y_pos-y_pos); + return; + } + bx--; + }while(bx!=0); + + src+= image_width; + } +} + + diff --git a/pxwide.h b/pxwide.h index f7003c54..b1db7ec4 100644 --- a/pxwide.h +++ b/pxwide.h @@ -1,49 +1,49 @@ -/* Grafx2 - The Ultimate 256-color bitmap paint program - - Copyright 2008 Yves Rizoud - Copyright 2007 Adrien Destugues - Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) - - Grafx2 is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; version 2 - of the License. - - Grafx2 is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Grafx2; if not, see -*/ - -////////////////////////////////////////////////////////////////////////////// -///@file pxwide.h -/// Renderer for wide pixels (2x1). -////////////////////////////////////////////////////////////////////////////// - -#include "struct.h" - - void Pixel_wide (word x,word y,byte color); - byte Read_pixel_wide (word x,word y); - void Block_wide (word start_x,word start_y,word width,word height,byte color); - void Pixel_preview_normal_wide (word x,word y,byte color); - void Pixel_preview_magnifier_wide (word x,word y,byte color); - void Horizontal_XOR_line_wide (word x_pos,word y_pos,word width); - void Vertical_XOR_line_wide (word x_pos,word y_pos,word height); - void Display_brush_color_wide (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width); - void Display_brush_mono_wide (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,byte color,word brush_width); - void Clear_brush_wide (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word image_width); - void Remap_screen_wide (word x_pos,word y_pos,word width,word height,byte * conversion_table); - void Display_part_of_screen_wide (word width,word height,word image_width); - void Display_line_on_screen_wide (word x_pos,word y_pos,word width,byte * line); - void Read_line_screen_wide (word x_pos,word y_pos,word width,byte * line); - void Display_part_of_screen_scaled_wide(word width,word height,word image_width,byte * buffer); - void Display_brush_color_zoom_wide (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,word brush_width,byte * buffer); - void Display_brush_mono_zoom_wide (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,byte color,word brush_width,byte * buffer); - void Clear_brush_scaled_wide (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,word image_width,byte * buffer); - void Display_brush_wide (byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width); - - void Display_line_on_screen_fast_wide (word x_pos,word y_pos,word width,byte * line); - void Display_transparent_line_on_screen_wide(word x_pos,word y_pos,word width,byte* line,byte transp_color); +/* Grafx2 - The Ultimate 256-color bitmap paint program + + Copyright 2008 Yves Rizoud + Copyright 2007 Adrien Destugues + Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) + + Grafx2 is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 + of the License. + + Grafx2 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grafx2; if not, see +*/ + +////////////////////////////////////////////////////////////////////////////// +///@file pxwide.h +/// Renderer for wide pixels (2x1). +////////////////////////////////////////////////////////////////////////////// + +#include "struct.h" + + void Pixel_wide (word x,word y,byte color); + byte Read_pixel_wide (word x,word y); + void Block_wide (word start_x,word start_y,word width,word height,byte color); + void Pixel_preview_normal_wide (word x,word y,byte color); + void Pixel_preview_magnifier_wide (word x,word y,byte color); + void Horizontal_XOR_line_wide (word x_pos,word y_pos,word width); + void Vertical_XOR_line_wide (word x_pos,word y_pos,word height); + void Display_brush_color_wide (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width); + void Display_brush_mono_wide (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,byte color,word brush_width); + void Clear_brush_wide (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word image_width); + void Remap_screen_wide (word x_pos,word y_pos,word width,word height,byte * conversion_table); + void Display_part_of_screen_wide (word width,word height,word image_width); + void Display_line_on_screen_wide (word x_pos,word y_pos,word width,byte * line); + void Read_line_screen_wide (word x_pos,word y_pos,word width,byte * line); + void Display_part_of_screen_scaled_wide(word width,word height,word image_width,byte * buffer); + void Display_brush_color_zoom_wide (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,word brush_width,byte * buffer); + void Display_brush_mono_zoom_wide (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,byte color,word brush_width,byte * buffer); + void Clear_brush_scaled_wide (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,word image_width,byte * buffer); + void Display_brush_wide (byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width); + + void Display_line_on_screen_fast_wide (word x_pos,word y_pos,word width,byte * line); + void Display_transparent_line_on_screen_wide(word x_pos,word y_pos,word width,byte* line,byte transp_color); diff --git a/pxwide2.c b/pxwide2.c index 15358dbb..d0d2f400 100644 --- a/pxwide2.c +++ b/pxwide2.c @@ -1,514 +1,521 @@ -/* Grafx2 - The Ultimate 256-color bitmap paint program - - Copyright 2008 Yves Rizoud - Copyright 2008 Franck Charlet - Copyright 2007 Adrien Destugues - Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) - - Grafx2 is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; version 2 - of the License. - - Grafx2 is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Grafx2; if not, see -*/ - -#include -#include -#include -#include "global.h" -#include "sdlscreen.h" -#include "misc.h" -#include "pxwide2.h" - -#define ZOOMX 4 -#define ZOOMY 2 - -void Pixel_wide2 (word x,word y,byte color) -/* Affiche un pixel de la color aux coords x;y à l'écran */ -{ - *(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH)=color; - *(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH + 1)=color; - *(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH + 2)=color; - *(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH + 3)=color; - *(Screen_pixels + x * ZOOMX + (y*ZOOMY+1) * VIDEO_LINE_WIDTH)=color; - *(Screen_pixels + x * ZOOMX + (y*ZOOMY+1) * VIDEO_LINE_WIDTH + 1)=color; - *(Screen_pixels + x * ZOOMX + (y*ZOOMY+1) * VIDEO_LINE_WIDTH + 2)=color; - *(Screen_pixels + x * ZOOMX + (y*ZOOMY+1) * VIDEO_LINE_WIDTH + 3)=color; -} - -byte Read_pixel_wide2 (word x,word y) -/* On retourne la couleur du pixel aux coords données */ -{ - return *( Screen_pixels + y * ZOOMY * VIDEO_LINE_WIDTH + x * ZOOMX); -} - -void Block_wide2 (word start_x,word start_y,word width,word height,byte color) -/* On affiche un rectangle de la couleur donnée */ -{ - SDL_Rect rectangle; - rectangle.x=start_x*ZOOMX; - rectangle.y=start_y*ZOOMY; - rectangle.w=width*ZOOMX; - rectangle.h=height*ZOOMY; - SDL_FillRect(Screen_SDL,&rectangle,color); -} - -void Display_part_of_screen_wide2 (word width,word height,word image_width) -/* Afficher une partie de l'image telle quelle sur l'écran */ -{ - byte* dest=Screen_pixels; //On va se mettre en 0,0 dans l'écran (dest) - byte* src=Main_offset_Y*image_width+Main_offset_X+Main_screen; //Coords de départ ds la source (src) - int y; - int dy; - - for(y=height;y!=0;y--) - // Pour chaque ligne - { - // On fait une copie de la ligne - for (dy=width;dy>0;dy--) - { - *(dest+3)=*(dest+2)=*(dest+1)=*dest=*src; - src++; - dest+=ZOOMX; - } - // On double la ligne qu'on vient de copier - memcpy(dest-width*ZOOMX+VIDEO_LINE_WIDTH,dest-width*ZOOMX,width*ZOOMX); - - // On passe à la ligne suivante - src+=image_width-width; - dest+=VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX; - } - //Update_rect(0,0,width,height); -} - -void Pixel_preview_normal_wide2 (word x,word y,byte color) -/* Affichage d'un pixel dans l'écran, par rapport au décalage de l'image - * dans l'écran, en mode normal (pas en mode loupe) - * Note: si on modifie cette procédure, il faudra penser à faire également - * la modif dans la procédure Pixel_Preview_Loupe_SDL. */ -{ -// if(x-Main_offset_X >= 0 && y - Main_offset_Y >= 0) - Pixel_wide2(x-Main_offset_X,y-Main_offset_Y,color); -} - -void Pixel_preview_magnifier_wide2 (word x,word y,byte color) -{ - // Affiche le pixel dans la partie non zoomée - Pixel_wide2(x-Main_offset_X,y-Main_offset_Y,color); - - // Regarde si on doit aussi l'afficher dans la partie zoomée - if (y >= Limit_top_zoom && y <= Limit_visible_bottom_zoom - && x >= Limit_left_zoom && x <= Limit_visible_right_zoom) - { - // On est dedans - int height; - int y_zoom = Main_magnifier_factor * (y-Main_magnifier_offset_Y); - - if (Menu_Y - y_zoom < Main_magnifier_factor) - // On ne doit dessiner qu'un morceau du pixel - // sinon on dépasse sur le menu - height = Menu_Y - y_zoom; - else - height = Main_magnifier_factor; - - Block_wide2( - Main_magnifier_factor * (x-Main_magnifier_offset_X) + Main_X_zoom, - y_zoom, Main_magnifier_factor, height, color - ); - } -} - -void Horizontal_XOR_line_wide2(word x_pos,word y_pos,word width) -{ - //On calcule la valeur initiale de dest: - byte* dest=y_pos*ZOOMY*VIDEO_LINE_WIDTH+x_pos*ZOOMX+Screen_pixels; - - int x; - - for (x=0;x0;i--) - { - *(dest+VIDEO_LINE_WIDTH+3)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+3)=*(dest+2)=*(dest+1)=*(dest)=~*(dest); - dest+=VIDEO_LINE_WIDTH*ZOOMY; - } -} - -void Display_brush_color_wide2(word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width) -{ - // dest = Position à l'écran - byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX; - // src = Position dans la brosse - byte* src = Brush + y_offset * brush_width + x_offset; - - word x,y; - - // Pour chaque ligne - for(y = height;y > 0; y--) - { - // Pour chaque pixel - for(x = width;x > 0; x--) - { - // On vérifie que ce n'est pas la transparence - if(*src != transp_color) - { - *(dest+VIDEO_LINE_WIDTH+3) = *(dest+VIDEO_LINE_WIDTH+2) = *(dest+VIDEO_LINE_WIDTH+1) = *(dest+VIDEO_LINE_WIDTH) = *(dest+3) = *(dest+2) = *(dest+1) = *dest = *src; - } - - // Pixel suivant - src++; - dest+=ZOOMX; - } - - // On passe à la ligne suivante - dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX; - src = src + brush_width - width; - } - Update_rect(x_pos,y_pos,width,height); -} - -void Display_brush_mono_wide2(word x_pos, word y_pos, - word x_offset, word y_offset, word width, word height, - byte transp_color, byte color, word brush_width) -/* On affiche la brosse en monochrome */ -{ - byte* dest=y_pos*ZOOMY*VIDEO_LINE_WIDTH+x_pos*ZOOMX+Screen_pixels; // dest = adr destination à - // l'écran - byte* src=brush_width*y_offset+x_offset+Brush; // src = adr ds - // la brosse - int x,y; - - for(y=height;y!=0;y--) - //Pour chaque ligne - { - for(x=width;x!=0;x--) - //Pour chaque pixel - { - if (*src!=transp_color) - *(dest+VIDEO_LINE_WIDTH+3)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+3)=*(dest+2)=*(dest+1)=*dest=color; - - // On passe au pixel suivant - src++; - dest+=ZOOMX; - } - - // On passe à la ligne suivante - src+=brush_width-width; - dest+=VIDEO_LINE_WIDTH*ZOOMY-width*ZOOMX; - } - Update_rect(x_pos,y_pos,width,height); -} - -void Clear_brush_wide2(word x_pos,word y_pos,__attribute__((unused)) word x_offset,__attribute__((unused)) word y_offset,word width,word height,__attribute__((unused))byte transp_color,word image_width) -{ - byte* dest=Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH; //On va se mettre en 0,0 dans l'écran (dest) - byte* src = ( y_pos + Main_offset_Y ) * image_width + x_pos + Main_offset_X + Main_screen; //Coords de départ ds la source (src) - int y; - int x; - - for(y=height;y!=0;y--) - // Pour chaque ligne - { - for(x=width;x!=0;x--) - //Pour chaque pixel - { - *(dest+VIDEO_LINE_WIDTH+3)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+3)=*(dest+2)=*(dest+1)=*dest=*src; - - // On passe au pixel suivant - src++; - dest+=ZOOMX; - } - - // On passe à la ligne suivante - src+=image_width-width; - dest+=VIDEO_LINE_WIDTH*ZOOMY-width*ZOOMX; - } - Update_rect(x_pos,y_pos,width,height); -} - -// Affiche une brosse (arbitraire) à l'écran -void Display_brush_wide2(byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width) -{ - // dest = Position à l'écran - byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX; - // src = Position dans la brosse - byte* src = brush + y_offset * brush_width + x_offset; - - word x,y; - - // Pour chaque ligne - for(y = height;y > 0; y--) - { - // Pour chaque pixel - for(x = width;x > 0; x--) - { - // On vérifie que ce n'est pas la transparence - if(*src != transp_color) - { - *(dest+VIDEO_LINE_WIDTH+3)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+3)=*(dest+2)=*(dest+1)=*dest=*src; - } - - // Pixel suivant - src++; dest+=ZOOMX; - } - - // On passe à la ligne suivante - dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX; - src = src + brush_width - width; - } -} - -void Remap_screen_wide2(word x_pos,word y_pos,word width,word height,byte * conversion_table) -{ - // dest = coords a l'écran - byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX; - int x,y; - - // Pour chaque ligne - for(y=height;y>0;y--) - { - // Pour chaque pixel - for(x=width;x>0;x--) - { - *(dest+VIDEO_LINE_WIDTH+3)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+3)=*(dest+2)=*(dest+1)=*dest= - conversion_table[*dest]; - dest +=ZOOMX; - } - - dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX; - } - - Update_rect(x_pos,y_pos,width,height); -} - -void Display_line_on_screen_fast_wide2(word x_pos,word y_pos,word width,byte * line) -/* On affiche toute une ligne de pixels telle quelle. */ -/* Utilisée si le buffer contient déja des pixel doublés. */ -{ - memcpy(Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH,line,width*ZOOMX); - memcpy(Screen_pixels+x_pos*ZOOMX+(y_pos*ZOOMY+1)*VIDEO_LINE_WIDTH,line,width*ZOOMX); -} - -void Display_line_on_screen_wide2(word x_pos,word y_pos,word width,byte * line) -/* On affiche une ligne de pixels en les doublant. */ -{ - int x; - byte *dest; - dest=Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH; - for(x=width;x>0;x--) - { - *(dest+VIDEO_LINE_WIDTH+3)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+3)=*(dest+2)=*(dest+1)=*dest=*line; - dest+=ZOOMX; - line++; - } -} -void Display_transparent_mono_line_on_screen_wide2( - word x_pos, word y_pos, word width, byte* line, - byte transp_color, byte color) -// Affiche une ligne à l'écran avec une couleur + transparence. -// Utilisé par les brosses en mode zoom -{ - byte* dest = Screen_pixels+ y_pos*VIDEO_LINE_WIDTH + x_pos*ZOOMX; - int x; - // Pour chaque pixel - for(x=0;x 0); - src += image_width; - } -// ATTENTION on n'arrive jamais ici ! -} - -// Affiche une partie de la brosse couleur zoomée -void Display_brush_color_zoom_wide2(word x_pos,word y_pos, - word x_offset,word y_offset, - word width, // width non zoomée - word end_y_pos,byte transp_color, - word brush_width, // width réelle de la brosse - byte * buffer) -{ - byte* src = Brush+y_offset*brush_width + x_offset; - word y = y_pos; - byte bx; - - // Pour chaque ligne - while(1) - { - Zoom_a_line(src,buffer,Main_magnifier_factor,width); - // On affiche facteur fois la ligne zoomée - for(bx=Main_magnifier_factor;bx>0;bx--) - { - byte* line_src = buffer; - byte* dest = Screen_pixels + y*ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX; - word x; - // Pour chaque pixel de la ligne - for(x = width*Main_magnifier_factor;x > 0;x--) - { - if(*line_src!=transp_color) - { - *(dest+3)=*(dest+2)=*(dest+1)=*dest = *line_src; - } - line_src++; - dest+=ZOOMX; - } - // Double the line - memcpy(Screen_pixels + (y*ZOOMY+1)*VIDEO_LINE_WIDTH + x_pos*ZOOMX, Screen_pixels + y*ZOOMY*VIDEO_LINE_WIDTH + x_pos*ZOOMX, width*ZOOMX*Main_magnifier_factor); - y++; - if(y==end_y_pos) - { - return; - } - } - src += brush_width; - } - // ATTENTION zone jamais atteinte -} - -void Display_brush_mono_zoom_wide2(word x_pos, word y_pos, - word x_offset, word y_offset, - word width, // width non zoomée - word end_y_pos, - byte transp_color, byte color, - word brush_width, // width réelle de la brosse - byte * buffer -) - -{ - byte* src = Brush + y_offset * brush_width + x_offset; - int y=y_pos*ZOOMY; - - //Pour chaque ligne à zoomer : - while(1) - { - int bx; - // src = Ligne originale - // On éclate la ligne - Zoom_a_line(src,buffer,Main_magnifier_factor,width); - - // On affiche la ligne Facteur fois à l'écran (sur des - // lignes consécutives) - bx = Main_magnifier_factor*ZOOMY; - - // Pour chaque ligne écran - do - { - // On affiche la ligne zoomée - Display_transparent_mono_line_on_screen_wide2( - x_pos, y, width * Main_magnifier_factor, - buffer, transp_color, color - ); - // On passe à la ligne suivante - y++; - // On vérifie qu'on est pas à la ligne finale - if(y == end_y_pos*ZOOMY) - { - Update_rect( x_pos, y_pos, - width * Main_magnifier_factor, end_y_pos - y_pos ); - return; - } - bx --; - } - while (bx > 0); - - // Passage à la ligne suivante dans la brosse aussi - src+=brush_width; - } -} - -void Clear_brush_scaled_wide2(word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,__attribute__((unused)) byte transp_color,word image_width,byte * buffer) -{ - - // En fait on va recopier l'image non zoomée dans la partie zoomée ! - byte* src = Main_screen + y_offset * image_width + x_offset; - int y = y_pos; - int bx; - - // Pour chaque ligne à zoomer - while(1){ - Zoom_a_line(src,buffer,Main_magnifier_factor*ZOOMX,width); - - bx=Main_magnifier_factor; - - // Pour chaque ligne - do{ - // TODO a verifier - Display_line_on_screen_fast_wide2(x_pos,y, - width * Main_magnifier_factor,buffer); - - // Ligne suivante - y++; - if(y==end_y_pos) - { - Update_rect(x_pos,y_pos, - width*Main_magnifier_factor,end_y_pos-y_pos); - return; - } - bx--; - }while(bx!=0); - - src+= image_width; - } -} - - +/* Grafx2 - The Ultimate 256-color bitmap paint program + + Copyright 2008 Yves Rizoud + Copyright 2008 Franck Charlet + Copyright 2007 Adrien Destugues + Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) + + Grafx2 is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 + of the License. + + Grafx2 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grafx2; if not, see +*/ + +#include +#include +#include +#include "global.h" +#include "sdlscreen.h" +#include "misc.h" +#include "graph.h" +#include "pxwide2.h" + +#define ZOOMX 4 +#define ZOOMY 2 + +void Pixel_wide2 (word x,word y,byte color) +/* Affiche un pixel de la color aux coords x;y à l'écran */ +{ + *(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH)=color; + *(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH + 1)=color; + *(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH + 2)=color; + *(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH + 3)=color; + *(Screen_pixels + x * ZOOMX + (y*ZOOMY+1) * VIDEO_LINE_WIDTH)=color; + *(Screen_pixels + x * ZOOMX + (y*ZOOMY+1) * VIDEO_LINE_WIDTH + 1)=color; + *(Screen_pixels + x * ZOOMX + (y*ZOOMY+1) * VIDEO_LINE_WIDTH + 2)=color; + *(Screen_pixels + x * ZOOMX + (y*ZOOMY+1) * VIDEO_LINE_WIDTH + 3)=color; +} + +byte Read_pixel_wide2 (word x,word y) +/* On retourne la couleur du pixel aux coords données */ +{ + return *( Screen_pixels + y * ZOOMY * VIDEO_LINE_WIDTH + x * ZOOMX); +} + +void Block_wide2 (word start_x,word start_y,word width,word height,byte color) +/* On affiche un rectangle de la couleur donnée */ +{ + SDL_Rect rectangle; + rectangle.x=start_x*ZOOMX; + rectangle.y=start_y*ZOOMY; + rectangle.w=width*ZOOMX; + rectangle.h=height*ZOOMY; + SDL_FillRect(Screen_SDL,&rectangle,color); +} + +void Display_part_of_screen_wide2 (word width,word height,word image_width) +/* Afficher une partie de l'image telle quelle sur l'écran */ +{ + byte* dest=Screen_pixels; //On va se mettre en 0,0 dans l'écran (dest) + byte* src=Main_offset_Y*image_width+Main_offset_X+Main_screen; //Coords de départ ds la source (src) + int y; + int dy; + + for(y=height;y!=0;y--) + // Pour chaque ligne + { + // On fait une copie de la ligne + for (dy=width;dy>0;dy--) + { + *(dest+3)=*(dest+2)=*(dest+1)=*dest=*src; + src++; + dest+=ZOOMX; + } + // On double la ligne qu'on vient de copier + memcpy(dest-width*ZOOMX+VIDEO_LINE_WIDTH,dest-width*ZOOMX,width*ZOOMX); + + // On passe à la ligne suivante + src+=image_width-width; + dest+=VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX; + } + //Update_rect(0,0,width,height); +} + +void Pixel_preview_normal_wide2 (word x,word y,byte color) +/* Affichage d'un pixel dans l'écran, par rapport au décalage de l'image + * dans l'écran, en mode normal (pas en mode loupe) + * Note: si on modifie cette procédure, il faudra penser à faire également + * la modif dans la procédure Pixel_Preview_Loupe_SDL. */ +{ +// if(x-Main_offset_X >= 0 && y - Main_offset_Y >= 0) + Pixel_wide2(x-Main_offset_X,y-Main_offset_Y,color); +} + +void Pixel_preview_magnifier_wide2 (word x,word y,byte color) +{ + // Affiche le pixel dans la partie non zoomée + Pixel_wide2(x-Main_offset_X,y-Main_offset_Y,color); + + // Regarde si on doit aussi l'afficher dans la partie zoomée + if (y >= Limit_top_zoom && y <= Limit_visible_bottom_zoom + && x >= Limit_left_zoom && x <= Limit_visible_right_zoom) + { + // On est dedans + int height; + int y_zoom = Main_magnifier_factor * (y-Main_magnifier_offset_Y); + + if (Menu_Y - y_zoom < Main_magnifier_factor) + // On ne doit dessiner qu'un morceau du pixel + // sinon on dépasse sur le menu + height = Menu_Y - y_zoom; + else + height = Main_magnifier_factor; + + Block_wide2( + Main_magnifier_factor * (x-Main_magnifier_offset_X) + Main_X_zoom, + y_zoom, Main_magnifier_factor, height, color + ); + } +} + +void Horizontal_XOR_line_wide2(word x_pos,word y_pos,word width) +{ + //On calcule la valeur initiale de dest: + byte* dest=y_pos*ZOOMY*VIDEO_LINE_WIDTH+x_pos*ZOOMX+Screen_pixels; + + int x; + + for (x=0;x0;i--) + { + *(dest+VIDEO_LINE_WIDTH+3)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+3)=*(dest+2)=*(dest+1)=*(dest)=~*(dest); + dest+=VIDEO_LINE_WIDTH*ZOOMY; + } +} + +void Display_brush_color_wide2(word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width) +{ + // dest = Position à l'écran + byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX; + // src = Position dans la brosse + byte* src = Brush + y_offset * brush_width + x_offset; + + word x,y; + + // Pour chaque ligne + for(y = height;y > 0; y--) + { + // Pour chaque pixel + for(x = width;x > 0; x--) + { + // On vérifie que ce n'est pas la transparence + if(*src != transp_color) + { + *(dest+VIDEO_LINE_WIDTH+3) = *(dest+VIDEO_LINE_WIDTH+2) = *(dest+VIDEO_LINE_WIDTH+1) = *(dest+VIDEO_LINE_WIDTH) = *(dest+3) = *(dest+2) = *(dest+1) = *dest = *src; + } + + // Pixel suivant + src++; + dest+=ZOOMX; + } + + // On passe à la ligne suivante + dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX; + src = src + brush_width - width; + } + Update_rect(x_pos,y_pos,width,height); +} + +void Display_brush_mono_wide2(word x_pos, word y_pos, + word x_offset, word y_offset, word width, word height, + byte transp_color, byte color, word brush_width) +/* On affiche la brosse en monochrome */ +{ + byte* dest=y_pos*ZOOMY*VIDEO_LINE_WIDTH+x_pos*ZOOMX+Screen_pixels; // dest = adr destination à + // l'écran + byte* src=brush_width*y_offset+x_offset+Brush; // src = adr ds + // la brosse + int x,y; + + for(y=height;y!=0;y--) + //Pour chaque ligne + { + for(x=width;x!=0;x--) + //Pour chaque pixel + { + if (*src!=transp_color) + *(dest+VIDEO_LINE_WIDTH+3)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+3)=*(dest+2)=*(dest+1)=*dest=color; + + // On passe au pixel suivant + src++; + dest+=ZOOMX; + } + + // On passe à la ligne suivante + src+=brush_width-width; + dest+=VIDEO_LINE_WIDTH*ZOOMY-width*ZOOMX; + } + Update_rect(x_pos,y_pos,width,height); +} + +void Clear_brush_wide2(word x_pos,word y_pos,__attribute__((unused)) word x_offset,__attribute__((unused)) word y_offset,word width,word height,__attribute__((unused))byte transp_color,word image_width) +{ + byte* dest=Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH; //On va se mettre en 0,0 dans l'écran (dest) + byte* src = ( y_pos + Main_offset_Y ) * image_width + x_pos + Main_offset_X + Main_screen; //Coords de départ ds la source (src) + int y; + int x; + + for(y=height;y!=0;y--) + // Pour chaque ligne + { + for(x=width;x!=0;x--) + //Pour chaque pixel + { + *(dest+VIDEO_LINE_WIDTH+3)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+3)=*(dest+2)=*(dest+1)=*dest=*src; + + // On passe au pixel suivant + src++; + dest+=ZOOMX; + } + + // On passe à la ligne suivante + src+=image_width-width; + dest+=VIDEO_LINE_WIDTH*ZOOMY-width*ZOOMX; + } + Update_rect(x_pos,y_pos,width,height); +} + +// Affiche une brosse (arbitraire) à l'écran +void Display_brush_wide2(byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width) +{ + // dest = Position à l'écran + byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX; + // src = Position dans la brosse + byte* src = brush + y_offset * brush_width + x_offset; + + word x,y; + + // Pour chaque ligne + for(y = height;y > 0; y--) + { + // Pour chaque pixel + for(x = width;x > 0; x--) + { + // On vérifie que ce n'est pas la transparence + if(*src != transp_color) + { + *(dest+VIDEO_LINE_WIDTH+3)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+3)=*(dest+2)=*(dest+1)=*dest=*src; + } + + // Pixel suivant + src++; dest+=ZOOMX; + } + + // On passe à la ligne suivante + dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX; + src = src + brush_width - width; + } +} + +void Remap_screen_wide2(word x_pos,word y_pos,word width,word height,byte * conversion_table) +{ + // dest = coords a l'écran + byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX; + int x,y; + + // Pour chaque ligne + for(y=height;y>0;y--) + { + // Pour chaque pixel + for(x=width;x>0;x--) + { + *(dest+VIDEO_LINE_WIDTH+3)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+3)=*(dest+2)=*(dest+1)=*dest= + conversion_table[*dest]; + dest +=ZOOMX; + } + + dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX; + } + + Update_rect(x_pos,y_pos,width,height); +} + +void Display_line_on_screen_fast_wide2(word x_pos,word y_pos,word width,byte * line) +/* On affiche toute une ligne de pixels telle quelle. */ +/* Utilisée si le buffer contient déja des pixel doublés. */ +{ + memcpy(Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH,line,width*ZOOMX); + memcpy(Screen_pixels+x_pos*ZOOMX+(y_pos*ZOOMY+1)*VIDEO_LINE_WIDTH,line,width*ZOOMX); +} + +void Display_line_on_screen_wide2(word x_pos,word y_pos,word width,byte * line) +/* On affiche une ligne de pixels en les doublant. */ +{ + int x; + byte *dest; + dest=Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH; + for(x=width;x>0;x--) + { + *(dest+VIDEO_LINE_WIDTH+3)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+3)=*(dest+2)=*(dest+1)=*dest=*line; + dest+=ZOOMX; + line++; + } +} +void Display_transparent_mono_line_on_screen_wide2( + word x_pos, word y_pos, word width, byte* line, + byte transp_color, byte color) +// Affiche une ligne à l'écran avec une couleur + transparence. +// Utilisé par les brosses en mode zoom +{ + byte* dest = Screen_pixels+ y_pos*VIDEO_LINE_WIDTH + x_pos*ZOOMX; + int x; + // Pour chaque pixel + for(x=0;x 0); + src += image_width; + } +// ATTENTION on n'arrive jamais ici ! +} + +// Affiche une partie de la brosse couleur zoomée +void Display_brush_color_zoom_wide2(word x_pos,word y_pos, + word x_offset,word y_offset, + word width, // width non zoomée + word end_y_pos,byte transp_color, + word brush_width, // width réelle de la brosse + byte * buffer) +{ + byte* src = Brush+y_offset*brush_width + x_offset; + word y = y_pos; + byte bx; + + // Pour chaque ligne + while(1) + { + Zoom_a_line(src,buffer,Main_magnifier_factor,width); + // On affiche facteur fois la ligne zoomée + for(bx=Main_magnifier_factor;bx>0;bx--) + { + byte* line_src = buffer; + byte* dest = Screen_pixels + y*ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX; + word x; + // Pour chaque pixel de la ligne + for(x = width*Main_magnifier_factor;x > 0;x--) + { + if(*line_src!=transp_color) + { + *(dest+3)=*(dest+2)=*(dest+1)=*dest = *line_src; + } + line_src++; + dest+=ZOOMX; + } + // Double the line + memcpy(Screen_pixels + (y*ZOOMY+1)*VIDEO_LINE_WIDTH + x_pos*ZOOMX, Screen_pixels + y*ZOOMY*VIDEO_LINE_WIDTH + x_pos*ZOOMX, width*ZOOMX*Main_magnifier_factor); + y++; + if(y==end_y_pos) + { + return; + } + } + src += brush_width; + } + // ATTENTION zone jamais atteinte +} + +void Display_brush_mono_zoom_wide2(word x_pos, word y_pos, + word x_offset, word y_offset, + word width, // width non zoomée + word end_y_pos, + byte transp_color, byte color, + word brush_width, // width réelle de la brosse + byte * buffer +) + +{ + byte* src = Brush + y_offset * brush_width + x_offset; + int y=y_pos*ZOOMY; + + //Pour chaque ligne à zoomer : + while(1) + { + int bx; + // src = Ligne originale + // On éclate la ligne + Zoom_a_line(src,buffer,Main_magnifier_factor,width); + + // On affiche la ligne Facteur fois à l'écran (sur des + // lignes consécutives) + bx = Main_magnifier_factor*ZOOMY; + + // Pour chaque ligne écran + do + { + // On affiche la ligne zoomée + Display_transparent_mono_line_on_screen_wide2( + x_pos, y, width * Main_magnifier_factor, + buffer, transp_color, color + ); + // On passe à la ligne suivante + y++; + // On vérifie qu'on est pas à la ligne finale + if(y == end_y_pos*ZOOMY) + { + Redraw_grid( x_pos, y_pos, + width * Main_magnifier_factor, end_y_pos - y_pos ); + Update_rect( x_pos, y_pos, + width * Main_magnifier_factor, end_y_pos - y_pos ); + return; + } + bx --; + } + while (bx > 0); + + // Passage à la ligne suivante dans la brosse aussi + src+=brush_width; + } +} + +void Clear_brush_scaled_wide2(word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,__attribute__((unused)) byte transp_color,word image_width,byte * buffer) +{ + + // En fait on va recopier l'image non zoomée dans la partie zoomée ! + byte* src = Main_screen + y_offset * image_width + x_offset; + int y = y_pos; + int bx; + + // Pour chaque ligne à zoomer + while(1){ + Zoom_a_line(src,buffer,Main_magnifier_factor*ZOOMX,width); + + bx=Main_magnifier_factor; + + // Pour chaque ligne + do{ + // TODO a verifier + Display_line_on_screen_fast_wide2(x_pos,y, + width * Main_magnifier_factor,buffer); + + // Ligne suivante + y++; + if(y==end_y_pos) + { + Redraw_grid(x_pos,y_pos, + width*Main_magnifier_factor,end_y_pos-y_pos); + Update_rect(x_pos,y_pos, + width*Main_magnifier_factor,end_y_pos-y_pos); + return; + } + bx--; + }while(bx!=0); + + src+= image_width; + } +} + + diff --git a/pxwide2.h b/pxwide2.h index bcc5eed0..15dff2d9 100644 --- a/pxwide2.h +++ b/pxwide2.h @@ -1,48 +1,48 @@ -/* Grafx2 - The Ultimate 256-color bitmap paint program - - Copyright 2008 Yves Rizoud - Copyright 2007 Adrien Destugues - Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) - - Grafx2 is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; version 2 - of the License. - - Grafx2 is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Grafx2; if not, see -*/ - -////////////////////////////////////////////////////////////////////////////// -///@file pxwide2.h -/// Renderer for double-wide pixels (4x2). -////////////////////////////////////////////////////////////////////////////// - -#include "struct.h" - - void Pixel_wide2 (word x,word y,byte color); - byte Read_pixel_wide2 (word x,word y); - void Block_wide2 (word start_x,word start_y,word width,word height,byte color); - void Pixel_preview_normal_wide2 (word x,word y,byte color); - void Pixel_preview_magnifier_wide2 (word x,word y,byte color); - void Horizontal_XOR_line_wide2 (word x_pos,word y_pos,word width); - void Vertical_XOR_line_wide2 (word x_pos,word y_pos,word height); - void Display_brush_color_wide2 (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width); - void Display_brush_mono_wide2 (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,byte color,word brush_width); - void Clear_brush_wide2 (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word image_width); - void Remap_screen_wide2 (word x_pos,word y_pos,word width,word height,byte * conversion_table); - void Display_part_of_screen_wide2 (word width,word height,word image_width); - void Display_line_on_screen_wide2 (word x_pos,word y_pos,word width,byte * line); - void Read_line_screen_wide2 (word x_pos,word y_pos,word width,byte * line); - void Display_part_of_screen_scaled_wide2(word width,word height,word image_width,byte * buffer); - void Display_brush_color_zoom_wide2 (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,word brush_width,byte * buffer); - void Display_brush_mono_zoom_wide2 (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,byte color,word brush_width,byte * buffer); - void Clear_brush_scaled_wide2 (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,word image_width,byte * buffer); - void Display_brush_wide2 (byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width); - - void Display_line_on_screen_fast_wide2 (word x_pos,word y_pos,word width,byte * line); +/* Grafx2 - The Ultimate 256-color bitmap paint program + + Copyright 2008 Yves Rizoud + Copyright 2007 Adrien Destugues + Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) + + Grafx2 is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 + of the License. + + Grafx2 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grafx2; if not, see +*/ + +////////////////////////////////////////////////////////////////////////////// +///@file pxwide2.h +/// Renderer for double-wide pixels (4x2). +////////////////////////////////////////////////////////////////////////////// + +#include "struct.h" + + void Pixel_wide2 (word x,word y,byte color); + byte Read_pixel_wide2 (word x,word y); + void Block_wide2 (word start_x,word start_y,word width,word height,byte color); + void Pixel_preview_normal_wide2 (word x,word y,byte color); + void Pixel_preview_magnifier_wide2 (word x,word y,byte color); + void Horizontal_XOR_line_wide2 (word x_pos,word y_pos,word width); + void Vertical_XOR_line_wide2 (word x_pos,word y_pos,word height); + void Display_brush_color_wide2 (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width); + void Display_brush_mono_wide2 (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,byte color,word brush_width); + void Clear_brush_wide2 (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word image_width); + void Remap_screen_wide2 (word x_pos,word y_pos,word width,word height,byte * conversion_table); + void Display_part_of_screen_wide2 (word width,word height,word image_width); + void Display_line_on_screen_wide2 (word x_pos,word y_pos,word width,byte * line); + void Read_line_screen_wide2 (word x_pos,word y_pos,word width,byte * line); + void Display_part_of_screen_scaled_wide2(word width,word height,word image_width,byte * buffer); + void Display_brush_color_zoom_wide2 (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,word brush_width,byte * buffer); + void Display_brush_mono_zoom_wide2 (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,byte color,word brush_width,byte * buffer); + void Clear_brush_scaled_wide2 (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,word image_width,byte * buffer); + void Display_brush_wide2 (byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width); + + void Display_line_on_screen_fast_wide2 (word x_pos,word y_pos,word width,byte * line); diff --git a/readini.c b/readini.c index 7c3b7cb6..a3cf1e7b 100644 --- a/readini.c +++ b/readini.c @@ -519,17 +519,10 @@ int Load_INI(T_Config * conf) if ((return_code=Load_INI_get_values (file,buffer,"Menu_ratio",1,values))) goto Erreur_Retour; - if ((values[0]<0) || (values[0]>2)) + if (values[0]>2) goto Erreur_ERREUR_INI_CORROMPU; conf->Ratio=values[0]; - if ((return_code=Load_INI_get_values (file,buffer,"Font",1,values))) - goto Erreur_Retour; - if ((values[0]<1) || (values[0]>2)) - goto Erreur_ERREUR_INI_CORROMPU; - conf->Font=values[0]-1; - - if ((return_code=Load_INI_reach_group(file,buffer,"[FILE_SELECTOR]"))) goto Erreur_Retour; @@ -788,7 +781,7 @@ int Load_INI(T_Config * conf) break; } conf->Palette_vertical=0; - // Optionnel, vertical palette option (>98.0%) + // Optional, vertical palette option (>98.0%) if (!Load_INI_get_values (file,buffer,"Palette_vertical",1,values)) { if ((values[0]<0) || (values[0]>1)) @@ -804,7 +797,42 @@ int Load_INI(T_Config * conf) conf->Window_pos_x = values[0]; conf->Window_pos_y = values[1]; } + + conf->Double_click_speed=500; + // Optional, speed of double-click (>2.0) + if (!Load_INI_get_values (file,buffer,"Double_click_speed",1,values)) + { + if ((values[0]>0) || (values[0]<=2000)) + conf->Double_click_speed=values[0]; + } + conf->Double_key_speed=500; + // Optional, speed of double-keypress (>2.0) + if (!Load_INI_get_values (file,buffer,"Double_key_speed",1,values)) + { + if ((values[0]>0) || (values[0]<=2000)) + conf->Double_key_speed=values[0]; + } + + // Optional, name of skin file. (>2.0) + if(!Load_INI_get_string(file,buffer,"Skin_file",value_label,1)) + conf->Skin_file = strdup(value_label); + else + conf->Skin_file = strdup("skin_modern.png"); + + // Optional, name of font file. (>2.0) + if(!Load_INI_get_string(file,buffer,"Font_file",value_label,1)) + conf->Font_file = strdup(value_label); + else + conf->Font_file = strdup("font_Classic.png"); + + conf->Grid_XOR_color=255; + // Optional, XOR color for grid overlay (>2.0) + if (!Load_INI_get_values (file,buffer,"Grid_XOR_color",1,values)) + { + if ((values[0]>0) || (values[0]<=255)) + conf->Grid_XOR_color=values[0]; + } fclose(file); diff --git a/readini.h b/readini.h index 7715ac8b..02188f3d 100644 --- a/readini.h +++ b/readini.h @@ -1,27 +1,27 @@ -/* Grafx2 - The Ultimate 256-color bitmap paint program - - Copyright 2007 Adrien Destugues - Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) - - Grafx2 is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; version 2 - of the License. - - Grafx2 is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Grafx2; if not, see -*/ - -////////////////////////////////////////////////////////////////////////////// -///@file readini.h -/// Reading settings in gfx2.ini -////////////////////////////////////////////////////////////////////////////// - -int Load_INI(T_Config * conf); -int Load_INI_seek_pattern(char * buffer,char * pattern); -void Load_INI_clear_string(char * str, byte keep_comments); +/* Grafx2 - The Ultimate 256-color bitmap paint program + + Copyright 2007 Adrien Destugues + Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) + + Grafx2 is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 + of the License. + + Grafx2 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grafx2; if not, see +*/ + +////////////////////////////////////////////////////////////////////////////// +///@file readini.h +/// Reading settings in gfx2.ini +////////////////////////////////////////////////////////////////////////////// + +int Load_INI(T_Config * conf); +int Load_INI_seek_pattern(char * buffer,char * pattern); +void Load_INI_clear_string(char * str, byte keep_comments); diff --git a/readline.c b/readline.c index 293de1b5..8f2a509f 100644 --- a/readline.c +++ b/readline.c @@ -1,350 +1,353 @@ -/* Grafx2 - The Ultimate 256-color bitmap paint program - - Copyright 2008 Yves Rizoud - Copyright 2007 Adrien Destugues - Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) - - Grafx2 is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; version 2 - of the License. - - Grafx2 is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Grafx2; if not, see -*/ -/************************************************************************ -* * -* READLINE (procédure permettant de saisir une chaîne de caractères) * -* * -************************************************************************/ - -#include -#include - -#include "const.h" -#include "struct.h" -#include "global.h" -#include "misc.h" -#include "errors.h" -#include "const.h" -#include "sdlscreen.h" -#include "readline.h" -#include "windows.h" -#include "input.h" - -#define TEXT_COLOR MC_Black -#define BACKGROUND_COLOR MC_Light -#define CURSOR_COLOR MC_Black -#define CURSOR_BACKGROUND_COLOR MC_Dark - -// Suppresion d'un caractère à une certaine POSITION dans une CHAINE. -void Remove_character(char * str, byte position) -{ - for (;str[position]!='\0';position++) - str[position]=str[position+1]; -} - - -void Insert_character(char * str, char letter, byte position) -// Insertion d'une LETTRE à une certaine POSITION -// dans une CHAINE d'une certaine TAILLE. -{ - char temp_char; - - for (;letter!='\0';position++) - { - // On mémorise le caractère qui se trouve en "position" - temp_char=str[position]; - // On splotch la lettre à insérer - str[position]=letter; - // On place le caractère mémorisé dans "letter" comme nouvelle lettre à insérer - letter=temp_char; - } - // On termine la chaine - str[position]='\0'; -} - -int Valid_character(int c) -{ - // Sous Linux: Seul le / est strictement interdit, mais beaucoup - // d'autres poseront des problèmes au shell, alors on évite. - // Sous Windows : c'est moins grave car le fopen() échouerait de toutes façons. - // AmigaOS4: Pas de ':' car utilisé pour les volumes. - #if defined(__WIN32__) - char forbidden_char[] = {'/', '|', '?', '*', '<', '>', ':', '\\'}; - #elif defined (__amigaos4__) - char forbidden_char[] = {'/', '|', '?', '*', '<', '>', ':'}; - #else - char forbidden_char[] = {'/', '|', '?', '*', '<', '>'}; - #endif - int position; - - if (c < ' ' || c > 255) - return 0; - - for (position=0; position<(long)sizeof(forbidden_char); position++) - if (c == forbidden_char[position]) - return 0; - return 1; -} - -void Display_whole_string(word x_pos,word y_pos,char * str,byte position) -{ - Print_in_window(x_pos,y_pos,str,TEXT_COLOR,BACKGROUND_COLOR); - Print_char_in_window(x_pos+(position<<3),y_pos,str[position],CURSOR_COLOR,CURSOR_BACKGROUND_COLOR); -} - -/**************************************************************************** -* Enhanced super scanf deluxe pro plus giga mieux :-) * -****************************************************************************/ -byte Readline(word x_pos,word y_pos,char * str,byte visible_size,byte input_type) -// Paramètres: -// x_pos, y_pos : Coordonnées de la saisie dans la fenêtre -// str : Chaîne recevant la saisie (et contenant éventuellement une valeur initiale) -// max_size : Nombre de caractères logeant dans la zone de saisie -// input_type : 0=Chaîne, 1=Nombre, 2=Nom de fichier -// Sortie: -// 0: Sortie par annulation (Esc.) / 1: sortie par acceptation (Return) -{ - byte max_size; - // Grosse astuce pour les noms de fichiers: La taille affichée est différente - // de la taille maximum gérée. - if (input_type == 2) - max_size = 255; - else - max_size = visible_size; - return Readline_ex(x_pos,y_pos,str,visible_size,max_size,input_type); -} - -/**************************************************************************** -* Enhanced super scanf deluxe pro plus giga mieux :-) * -****************************************************************************/ -byte Readline_ex(word x_pos,word y_pos,char * str,byte visible_size,byte max_size, byte input_type) -// Paramètres: -// x_pos, y_pos : Coordonnées de la saisie dans la fenêtre -// str : Chaîne recevant la saisie (et contenant éventuellement une valeur initiale) -// max_size : Nombre de caractères logeant dans la zone de saisie -// input_type : 0=Chaîne, 1=Nombre, 2=Nom de fichier -// Sortie: -// 0: Sortie par annulation (Esc.) / 1: sortie par acceptation (Return) -{ - char initial_string[256]; - char display_string[256]; - byte position; - byte size; - word input_key=0; - byte is_authorized; - - byte offset=0; // index du premier caractère affiché - - Hide_cursor(); - // Effacement de la chaîne - Block(Window_pos_X+(x_pos*Menu_factor_X),Window_pos_Y+(y_pos*Menu_factor_Y), - visible_size*(Menu_factor_X<<3),(Menu_factor_Y<<3),BACKGROUND_COLOR); - Update_rect(Window_pos_X+(x_pos*Menu_factor_X),Window_pos_Y+(y_pos*Menu_factor_Y), - visible_size*(Menu_factor_X<<3),(Menu_factor_Y<<3)); - - // Mise à jour des variables se rapportant à la chaîne en fonction de la chaîne initiale - strcpy(initial_string,str); - - // Si on a commencé à editer par un clic-droit, on vide la chaine. - if (Mouse_K==RIGHT_SIDE) - str[0]='\0'; - else if (input_type==1) - snprintf(str,10,"%d",atoi(str)); // On tasse la chaine à gauche - - - size=strlen(str); - position=(sizevisible_size) - offset=position-visible_size+1; - // Formatage d'une partie de la chaine (si trop longue pour tenir) - strncpy(display_string, str + offset, visible_size); - display_string[visible_size]='\0'; - if (offset>0) - display_string[0]=LEFT_TRIANGLE_CHARACTER; - if (visible_size + offset + 1 < size ) - display_string[visible_size-1]=RIGHT_TRIANGLE_CHARACTER; - - Display_whole_string(x_pos,y_pos,display_string,position - offset); - Update_rect(Window_pos_X+(x_pos*Menu_factor_X),Window_pos_Y+(y_pos*Menu_factor_Y), - visible_size*(Menu_factor_X<<3),(Menu_factor_Y<<3)); - Flush_update(); - - while ((input_key!=SDLK_RETURN) && (input_key!=KEY_ESC)) - { - Display_cursor(); - do - { - if(!Get_input()) SDL_Delay(20); - input_key=Key_ANSI; - } while(input_key==0); - Hide_cursor(); - switch (input_key) - { - case SDLK_DELETE : // Suppr. - if (position0) - { - // Effacement de la chaîne - if (position==size) - Block(Window_pos_X+(x_pos*Menu_factor_X),Window_pos_Y+(y_pos*Menu_factor_Y), - visible_size*(Menu_factor_X<<3),(Menu_factor_Y<<3),BACKGROUND_COLOR); - position--; - if (offset > 0 && (position == 0 || position < (offset + 1))) - offset--; - goto affichage; - } - break; - case SDLK_RIGHT : // Droite - if ((position visible_size + offset - 2) - //if (offset + visible_size < max_size && (position == size || (position > visible_size + offset - 2))) - if (display_string[position-offset]==RIGHT_TRIANGLE_CHARACTER || position-offset>=visible_size) - offset++; - goto affichage; - } - break; - case SDLK_HOME : // Home - if (position) - { - // Effacement de la chaîne - if (position==size) - Block(Window_pos_X+(x_pos*Menu_factor_X),Window_pos_Y+(y_pos*Menu_factor_Y), - visible_size*(Menu_factor_X<<3),(Menu_factor_Y<<3),BACKGROUND_COLOR); - position = 0; - offset = 0; - goto affichage; - } - break; - case SDLK_END : // End - if ((positionvisible_size) - offset=position-visible_size+1; - goto affichage; - } - break; - case SDLK_BACKSPACE : // Backspace : combinaison de gauche + suppr - - if (position) - { - position--; - if (offset > 0 && (position == 0 || position < (offset + 1))) - offset--; - Remove_character(str,position); - size--; - // Effacement de la chaîne - Block(Window_pos_X+(x_pos*Menu_factor_X),Window_pos_Y+(y_pos*Menu_factor_Y), - visible_size*(Menu_factor_X<<3),(Menu_factor_Y<<3),BACKGROUND_COLOR); - goto affichage; - } - break; - case SDLK_RETURN : - break; - - case KEY_ESC : - // On restaure la chaine initiale - strcpy(str,initial_string); - size=strlen(str); - break; - default : - if (size=' ' && input_key<= 255) - is_authorized=1; - break; - case 1 : // Nombre - if ( (input_key>='0') && (input_key<='9') ) - is_authorized=1; - break; - default : // Nom de fichier - // On regarde si la touche est autorisée - if ( Valid_character(input_key)) - is_authorized=1; - } // End du "switch(input_type)" - - // Si la touche était autorisée... - if (is_authorized) - { - // ... alors on l'insère ... - Insert_character(str,input_key,position/*,size*/); - // ce qui augmente la taille de la chaine - size++; - // et qui risque de déplacer le curseur vers la droite - if (size=visible_size) - offset++; - } - // Enfin, on raffiche la chaine - goto affichage; - } // End du test d'autorisation de touche - } // End du test de place libre - break; - -affichage: - size=strlen(str); - // Formatage d'une partie de la chaine (si trop longue pour tenir) - strncpy(display_string, str + offset, visible_size); - display_string[visible_size]='\0'; - if (offset>0) - display_string[0]=LEFT_TRIANGLE_CHARACTER; - if (visible_size + offset + 0 < size ) - display_string[visible_size-1]=RIGHT_TRIANGLE_CHARACTER; - - Display_whole_string(x_pos,y_pos,display_string,position - offset); - Update_rect(Window_pos_X+(x_pos*Menu_factor_X),Window_pos_Y+(y_pos*Menu_factor_Y), - visible_size*(Menu_factor_X<<3),(Menu_factor_Y<<3)); - } // End du "switch(input_key)" - Flush_update(); - - } // End du "while" - - // Effacement de la chaîne - Block(Window_pos_X+(x_pos*Menu_factor_X),Window_pos_Y+(y_pos*Menu_factor_Y), - visible_size*(Menu_factor_X<<3),(Menu_factor_Y<<3),BACKGROUND_COLOR); - // On raffiche la chaine correctement - if (input_type==1) - { - if (str[0]=='\0') - { - strcpy(str,"0"); - size=1; - } - Print_in_window(x_pos+((max_size-size)<<3),y_pos,str,TEXT_COLOR,BACKGROUND_COLOR); - } - else - { - Print_in_window_limited(x_pos,y_pos,str,visible_size,TEXT_COLOR,BACKGROUND_COLOR); - } - Update_rect(Window_pos_X+(x_pos*Menu_factor_X),Window_pos_Y+(y_pos*Menu_factor_Y), - visible_size*(Menu_factor_X<<3),(Menu_factor_Y<<3)); - - return (input_key==SDLK_RETURN); -} +/* Grafx2 - The Ultimate 256-color bitmap paint program + + Copyright 2008 Yves Rizoud + Copyright 2007 Adrien Destugues + Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) + + Grafx2 is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 + of the License. + + Grafx2 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grafx2; if not, see +*/ +/************************************************************************ +* * +* READLINE (procédure permettant de saisir une chaîne de caractères) * +* * +************************************************************************/ + +#include +#include + +#include "const.h" +#include "struct.h" +#include "global.h" +#include "misc.h" +#include "errors.h" +#include "const.h" +#include "sdlscreen.h" +#include "readline.h" +#include "windows.h" +#include "input.h" + +#define TEXT_COLOR MC_Black +#define BACKGROUND_COLOR MC_Light +#define CURSOR_COLOR MC_Black +#define CURSOR_BACKGROUND_COLOR MC_Dark + +// Suppresion d'un caractère à une certaine POSITION dans une CHAINE. +void Remove_character(char * str, byte position) +{ + for (;str[position]!='\0';position++) + str[position]=str[position+1]; +} + + +void Insert_character(char * str, char letter, byte position) +// Insertion d'une LETTRE à une certaine POSITION +// dans une CHAINE d'une certaine TAILLE. +{ + char temp_char; + + for (;letter!='\0';position++) + { + // On mémorise le caractère qui se trouve en "position" + temp_char=str[position]; + // On splotch la lettre à insérer + str[position]=letter; + // On place le caractère mémorisé dans "letter" comme nouvelle lettre à insérer + letter=temp_char; + } + // On termine la chaine + str[position]='\0'; +} + +int Valid_character(int c) +{ + // Sous Linux: Seul le / est strictement interdit, mais beaucoup + // d'autres poseront des problèmes au shell, alors on évite. + // Sous Windows : c'est moins grave car le fopen() échouerait de toutes façons. + // AmigaOS4: Pas de ':' car utilisé pour les volumes. + #if defined(__WIN32__) + char forbidden_char[] = {'/', '|', '?', '*', '<', '>', ':', '\\'}; + #elif defined (__amigaos4__) + char forbidden_char[] = {'/', '|', '?', '*', '<', '>', ':'}; + #else + char forbidden_char[] = {'/', '|', '?', '*', '<', '>'}; + #endif + int position; + + if (c < ' ' || c > 255) + return 0; + + for (position=0; position<(long)sizeof(forbidden_char); position++) + if (c == forbidden_char[position]) + return 0; + return 1; +} + +void Display_whole_string(word x_pos,word y_pos,char * str,byte position) +{ + Print_in_window(x_pos,y_pos,str,TEXT_COLOR,BACKGROUND_COLOR); + Print_char_in_window(x_pos+(position<<3),y_pos,str[position],CURSOR_COLOR,CURSOR_BACKGROUND_COLOR); +} + +/**************************************************************************** +* Enhanced super scanf deluxe pro plus giga mieux :-) * +****************************************************************************/ +byte Readline(word x_pos,word y_pos,char * str,byte visible_size,byte input_type) +// Paramètres: +// x_pos, y_pos : Coordonnées de la saisie dans la fenêtre +// str : Chaîne recevant la saisie (et contenant éventuellement une valeur initiale) +// max_size : Nombre de caractères logeant dans la zone de saisie +// input_type : 0=Chaîne, 1=Nombre, 2=Nom de fichier +// Sortie: +// 0: Sortie par annulation (Esc.) / 1: sortie par acceptation (Return) +{ + byte max_size; + // Grosse astuce pour les noms de fichiers: La taille affichée est différente + // de la taille maximum gérée. + if (input_type == 2) + max_size = 255; + else + max_size = visible_size; + return Readline_ex(x_pos,y_pos,str,visible_size,max_size,input_type); +} + +/**************************************************************************** +* Enhanced super scanf deluxe pro plus giga mieux :-) * +****************************************************************************/ +byte Readline_ex(word x_pos,word y_pos,char * str,byte visible_size,byte max_size, byte input_type) +// Paramètres: +// x_pos, y_pos : Coordonnées de la saisie dans la fenêtre +// str : Chaîne recevant la saisie (et contenant éventuellement une valeur initiale) +// max_size : Nombre de caractères logeant dans la zone de saisie +// input_type : 0=Chaîne, 1=Nombre, 2=Nom de fichier +// Sortie: +// 0: Sortie par annulation (Esc.) / 1: sortie par acceptation (Return) +{ + char initial_string[256]; + char display_string[256]; + byte position; + byte size; + word input_key=0; + byte is_authorized; + + byte offset=0; // index du premier caractère affiché + + // Si on a commencé à editer par un clic-droit, on vide la chaine. + if (Mouse_K==RIGHT_SIDE) + str[0]='\0'; + else if (input_type==1) + snprintf(str,10,"%d",atoi(str)); // On tasse la chaine à gauche + + Wait_end_of_click(); + Keyboard_click_allowed = 0; + Hide_cursor(); + + // Effacement de la chaîne + Block(Window_pos_X+(x_pos*Menu_factor_X),Window_pos_Y+(y_pos*Menu_factor_Y), + visible_size*(Menu_factor_X<<3),(Menu_factor_Y<<3),BACKGROUND_COLOR); + Update_rect(Window_pos_X+(x_pos*Menu_factor_X),Window_pos_Y+(y_pos*Menu_factor_Y), + visible_size*(Menu_factor_X<<3),(Menu_factor_Y<<3)); + + // Mise à jour des variables se rapportant à la chaîne en fonction de la chaîne initiale + strcpy(initial_string,str); + + size=strlen(str); + position=(sizevisible_size) + offset=position-visible_size+1; + // Formatage d'une partie de la chaine (si trop longue pour tenir) + strncpy(display_string, str + offset, visible_size); + display_string[visible_size]='\0'; + if (offset>0) + display_string[0]=LEFT_TRIANGLE_CHARACTER; + if (visible_size + offset + 1 < size ) + display_string[visible_size-1]=RIGHT_TRIANGLE_CHARACTER; + + Display_whole_string(x_pos,y_pos,display_string,position - offset); + Update_rect(Window_pos_X+(x_pos*Menu_factor_X),Window_pos_Y+(y_pos*Menu_factor_Y), + visible_size*(Menu_factor_X<<3),(Menu_factor_Y<<3)); + Flush_update(); + + while ((input_key!=SDLK_RETURN) && (input_key!=KEY_ESC) && Mouse_K == 0) + { + Display_cursor(); + do + { + if(!Get_input()) SDL_Delay(20); + input_key=Key_ANSI; + } while(input_key==0 && Mouse_K == 0); + Hide_cursor(); + switch (input_key) + { + case SDLK_DELETE : // Suppr. + if (position0) + { + // Effacement de la chaîne + if (position==size) + Block(Window_pos_X+(x_pos*Menu_factor_X),Window_pos_Y+(y_pos*Menu_factor_Y), + visible_size*(Menu_factor_X<<3),(Menu_factor_Y<<3),BACKGROUND_COLOR); + position--; + if (offset > 0 && (position == 0 || position < (offset + 1))) + offset--; + goto affichage; + } + break; + case SDLK_RIGHT : // Droite + if ((position visible_size + offset - 2) + //if (offset + visible_size < max_size && (position == size || (position > visible_size + offset - 2))) + if (display_string[position-offset]==RIGHT_TRIANGLE_CHARACTER || position-offset>=visible_size) + offset++; + goto affichage; + } + break; + case SDLK_HOME : // Home + if (position) + { + // Effacement de la chaîne + if (position==size) + Block(Window_pos_X+(x_pos*Menu_factor_X),Window_pos_Y+(y_pos*Menu_factor_Y), + visible_size*(Menu_factor_X<<3),(Menu_factor_Y<<3),BACKGROUND_COLOR); + position = 0; + offset = 0; + goto affichage; + } + break; + case SDLK_END : // End + if ((positionvisible_size) + offset=position-visible_size+1; + goto affichage; + } + break; + case SDLK_BACKSPACE : // Backspace : combinaison de gauche + suppr + + if (position) + { + position--; + if (offset > 0 && (position == 0 || position < (offset + 1))) + offset--; + Remove_character(str,position); + size--; + // Effacement de la chaîne + Block(Window_pos_X+(x_pos*Menu_factor_X),Window_pos_Y+(y_pos*Menu_factor_Y), + visible_size*(Menu_factor_X<<3),(Menu_factor_Y<<3),BACKGROUND_COLOR); + goto affichage; + } + break; + case SDLK_RETURN : + break; + + case KEY_ESC : + // On restaure la chaine initiale + strcpy(str,initial_string); + size=strlen(str); + break; + default : + if (size=' ' && input_key<= 255) + is_authorized=1; + break; + case 1 : // Nombre + if ( (input_key>='0') && (input_key<='9') ) + is_authorized=1; + break; + default : // Nom de fichier + // On regarde si la touche est autorisée + if ( Valid_character(input_key)) + is_authorized=1; + } // End du "switch(input_type)" + + // Si la touche était autorisée... + if (is_authorized) + { + // ... alors on l'insère ... + Insert_character(str,input_key,position/*,size*/); + // ce qui augmente la taille de la chaine + size++; + // et qui risque de déplacer le curseur vers la droite + if (size=visible_size) + offset++; + } + // Enfin, on raffiche la chaine + goto affichage; + } // End du test d'autorisation de touche + } // End du test de place libre + break; + +affichage: + size=strlen(str); + // Formatage d'une partie de la chaine (si trop longue pour tenir) + strncpy(display_string, str + offset, visible_size); + display_string[visible_size]='\0'; + if (offset>0) + display_string[0]=LEFT_TRIANGLE_CHARACTER; + if (visible_size + offset + 0 < size ) + display_string[visible_size-1]=RIGHT_TRIANGLE_CHARACTER; + + Display_whole_string(x_pos,y_pos,display_string,position - offset); + Update_rect(Window_pos_X+(x_pos*Menu_factor_X),Window_pos_Y+(y_pos*Menu_factor_Y), + visible_size*(Menu_factor_X<<3),(Menu_factor_Y<<3)); + } // End du "switch(input_key)" + Flush_update(); + + } // End du "while" + Keyboard_click_allowed = 1; + + // Effacement de la chaîne + Block(Window_pos_X+(x_pos*Menu_factor_X),Window_pos_Y+(y_pos*Menu_factor_Y), + visible_size*(Menu_factor_X<<3),(Menu_factor_Y<<3),BACKGROUND_COLOR); + // On raffiche la chaine correctement + if (input_type==1) + { + if (str[0]=='\0') + { + strcpy(str,"0"); + size=1; + } + Print_in_window(x_pos+((max_size-size)<<3),y_pos,str,TEXT_COLOR,BACKGROUND_COLOR); + } + else + { + Print_in_window_limited(x_pos,y_pos,str,visible_size,TEXT_COLOR,BACKGROUND_COLOR); + } + Update_rect(Window_pos_X+(x_pos*Menu_factor_X),Window_pos_Y+(y_pos*Menu_factor_Y), + visible_size*(Menu_factor_X<<3),(Menu_factor_Y<<3)); + + return (input_key==SDLK_RETURN || Mouse_K != 0); +} diff --git a/readline.h b/readline.h index b2a3675f..f76242a3 100644 --- a/readline.h +++ b/readline.h @@ -1,44 +1,44 @@ -/* Grafx2 - The Ultimate 256-color bitmap paint program - - Copyright 2007 Adrien Destugues - Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) - - Grafx2 is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; version 2 - of the License. - - Grafx2 is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Grafx2; if not, see -*/ - -////////////////////////////////////////////////////////////////////////////// -///@file readline.h -/// Text input functions. -////////////////////////////////////////////////////////////////////////////// - -/// -/// Lets the user input a line of text, exit by Esc or Return. -/// @param x_pos Coordinates of input, in window coordinates before scaling. -/// @param y_pos Coordinates of input, in window coordinates before scaling. -/// @param str The original string value (will be modified, unless user cancels. -/// @param visible_size Number of characters visible and editable. -/// @param input_type 0=string, 1=number, 2=filename (255 editable characters) -/// @return 0 if user cancelled (esc), 1 if accepted (return) -byte Readline(word x_pos,word y_pos,char * str,byte visible_size,byte input_type); - -/// -/// Lets the user input a line of text, exit by Esc or Return. -/// @param x_pos Coordinates of input, in window coordinates before scaling. -/// @param y_pos Coordinates of input, in window coordinates before scaling. -/// @param str The original string value (will be modified, unless user cancels. -/// @param visible_size Number of characters visible. -/// @param max_size Number of characters editable. -/// @param input_type 0=string, 1=number, 2=filename (255 editable characters) -/// @return 0 if user cancelled (esc), 1 if accepted (return) -byte Readline_ex(word x_pos,word y_pos,char * str,byte visible_size,byte max_size, byte input_type); +/* Grafx2 - The Ultimate 256-color bitmap paint program + + Copyright 2007 Adrien Destugues + Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) + + Grafx2 is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 + of the License. + + Grafx2 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grafx2; if not, see +*/ + +////////////////////////////////////////////////////////////////////////////// +///@file readline.h +/// Text input functions. +////////////////////////////////////////////////////////////////////////////// + +/// +/// Lets the user input a line of text, exit by Esc or Return. +/// @param x_pos Coordinates of input, in window coordinates before scaling. +/// @param y_pos Coordinates of input, in window coordinates before scaling. +/// @param str The original string value (will be modified, unless user cancels. +/// @param visible_size Number of characters visible and editable. +/// @param input_type 0=string, 1=number, 2=filename (255 editable characters) +/// @return 0 if user cancelled (esc), 1 if accepted (return) +byte Readline(word x_pos,word y_pos,char * str,byte visible_size,byte input_type); + +/// +/// Lets the user input a line of text, exit by Esc or Return. +/// @param x_pos Coordinates of input, in window coordinates before scaling. +/// @param y_pos Coordinates of input, in window coordinates before scaling. +/// @param str The original string value (will be modified, unless user cancels. +/// @param visible_size Number of characters visible. +/// @param max_size Number of characters editable. +/// @param input_type 0=string, 1=number, 2=filename (255 editable characters) +/// @return 0 if user cancelled (esc), 1 if accepted (return) +byte Readline_ex(word x_pos,word y_pos,char * str,byte visible_size,byte max_size, byte input_type); diff --git a/saveini.c b/saveini.c index ac8e53d3..39a153b6 100644 --- a/saveini.c +++ b/saveini.c @@ -93,6 +93,7 @@ int Save_INI_char_in_value_alphabet(char c) (c<='z') ) || (c == '$') // Symbole d'hexadécimal + || (c== '.') // Point (dans les noms de fichiers) ) return 1; else @@ -475,11 +476,6 @@ int Save_INI(T_Config * conf) if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Menu_ratio",1,values,0))) goto Erreur_Retour; - values[0]=(conf->Font)+1; - if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Font",1,values,0))) - goto Erreur_Retour; - - if ((return_code=Save_INI_reach_group(Ancien_fichier,Nouveau_fichier,buffer,"[FILE_SELECTOR]"))) goto Erreur_Retour; @@ -635,6 +631,23 @@ int Save_INI(T_Config * conf) if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Window_position",2,values,0))) goto Erreur_Retour; + values[0]=(conf->Double_click_speed); + if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Double_click_speed",1,values,0))) + goto Erreur_Retour; + + values[0]=(conf->Double_key_speed); + if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Double_key_speed",1,values,0))) + goto Erreur_Retour; + + if ((return_code=Save_INI_set_strings (Ancien_fichier,Nouveau_fichier,buffer,"Skin_file",conf->Skin_file))) + goto Erreur_Retour; + + if ((return_code=Save_INI_set_strings (Ancien_fichier,Nouveau_fichier,buffer,"Font_file",conf->Font_file))) + goto Erreur_Retour; + + values[0]=(conf->Grid_XOR_color); + if ((return_code=Save_INI_set_values (Ancien_fichier,Nouveau_fichier,buffer,"Grid_XOR_color",1,values,0))) + goto Erreur_Retour; Save_INI_flush(Ancien_fichier,Nouveau_fichier,buffer); diff --git a/saveini.h b/saveini.h index 6d1f58df..93f9647b 100644 --- a/saveini.h +++ b/saveini.h @@ -1,25 +1,25 @@ -/* Grafx2 - The Ultimate 256-color bitmap paint program - - Copyright 2007 Adrien Destugues - Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) - - Grafx2 is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; version 2 - of the License. - - Grafx2 is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Grafx2; if not, see -*/ - -////////////////////////////////////////////////////////////////////////////// -///@file saveini.h -/// Saving settings in gfx2.ini -////////////////////////////////////////////////////////////////////////////// - -int Save_INI(T_Config * conf); +/* Grafx2 - The Ultimate 256-color bitmap paint program + + Copyright 2007 Adrien Destugues + Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) + + Grafx2 is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 + of the License. + + Grafx2 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grafx2; if not, see +*/ + +////////////////////////////////////////////////////////////////////////////// +///@file saveini.h +/// Saving settings in gfx2.ini +////////////////////////////////////////////////////////////////////////////// + +int Save_INI(T_Config * conf); diff --git a/sdlscreen.c b/sdlscreen.c index 6dd348d4..df0594a6 100644 --- a/sdlscreen.c +++ b/sdlscreen.c @@ -61,8 +61,9 @@ void Set_mode_SDL(int *width, int *height, int fullscreen) Screen_pixels=Screen_SDL->pixels; } else + { DEBUG("Error: Unable to change video mode!",0); - + } SDL_ShowCursor(0); // Hide the SDL mouse cursor, we use our own } diff --git a/setup.c b/setup.c index 054b97af..4e259390 100644 --- a/setup.c +++ b/setup.c @@ -1,181 +1,182 @@ -/* Grafx2 - The Ultimate 256-color bitmap paint program - - Copyright 2008 Peter Gordon - Copyright 2008 Yves Rizoud - Copyright 2008 Franck Charlet - Copyright 2007 Adrien Destugues - Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) - - Grafx2 is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; version 2 - of the License. - - Grafx2 is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Grafx2; if not, see -*/ - -#include -#include -#include -#include -#include -#if defined(__WIN32__) - #include - #include // Mingw's _mkdir() -#elif defined(__macosx__) - #import - #import -#elif defined(__FreeBSD__) - #import -#endif - -#include "struct.h" -#include "io.h" -#include "setup.h" - -int Create_ConfigDirectory(char * config_dir) -{ - #ifdef __WIN32__ - // Mingw's mkdir has a weird name and only one argument - return _mkdir(config_dir); - #else - return mkdir(config_dir,S_IRUSR|S_IWUSR|S_IXUSR); - #endif -} - -#if defined(__macosx__) || defined(__amigaos4__) || defined(__AROS__) || defined(__MORPHOS__) || defined(__amigaos__) - #define ARG_UNUSED __attribute__((unused)) -#else - #define ARG_UNUSED -#endif -// Determine which directory contains the executable. -// IN: Main's argv[0], some platforms need it, some don't. -// OUT: Write into program_dir. Trailing / or \ is kept. -// Note : in fact this is only used to check for the datafiles and fonts in this same directory. -void Set_program_directory(ARG_UNUSED const char * argv0,char * program_dir) -{ - #undef ARG_UNUSED - - // MacOSX - #if defined(__macosx__) - CFURLRef url = CFBundleCopyBundleURL(CFBundleGetMainBundle()); - CFURLGetFileSystemRepresentation(url,true,(UInt8*)program_dir,MAXPATHLEN); - CFRelease(url); - // Append trailing slash - strcat(program_dir ,"/"); - - // AmigaOS and alike: hard-coded volume name. - #elif defined(__amigaos4__) || defined(__AROS__) || defined(__MORPHOS__) || defined(__amigaos__) - strcpy(program_dir,"PROGDIR:"); - - // Others: The part of argv[0] before the executable name. - // Keep the last \ or /. - // Note that on Unix, once installed, the executable is called from a shell script - // sitting in /usr/local/bin/, this allows argv[0] to contain the full path. - // On Windows, Mingw32 already provides the full path in all cases. - #else - Extract_path(program_dir, argv0); - #endif -} - -// Determine which directory contains the read-only data. -// IN: The directory containing the executable -// OUT: Write into data_dir. Trailing / or \ is kept. -void Set_data_directory(const char * program_dir, char * data_dir) -{ - // On all platforms, data is in the executable's directory - strcpy(data_dir,program_dir); - // Except MacOSX, here it is stored in a special folder: - #if defined(__macosx__) - strcat(data_dir,"Contents/Resources/"); - #endif -} - -// Determine which directory should store the user's configuration. -// -// For most Unix and Windows platforms: -// If a config file already exists in program_dir, it will return it in priority -// (Useful for development, and possibly for upgrading from DOS version) -// If the standard directory doesn't exist yet, this function will attempt -// to create it ($(HOME)/.grafx2, or %APPDATA%\GrafX2) -// If it cannot be created, this function will return the executable's -// own directory. -// IN: The directory containing the executable -// OUT: Write into config_dir. Trailing / or \ is kept. -void Set_config_directory(const char * program_dir, char * config_dir) -{ - // MacOSX - #if defined(__macosx__) - strcpy(config_dir,program_dir); - strcat(config_dir,"Contents/Resources/"); - // AmigaOS4 - #elif defined(__amigaos4__) || defined(__AROS__) - strcpy(config_dir,"PROGDIR:"); - // GP2X - #elif defined(__GP2X__) - // On the GP2X, the program is installed to the sdcard, and we don't want to mess with the system tree which is - // on an internal flash chip. So, keep these settings locals. - strcpy(config_dir,program_dir); - #else - char filename[MAX_PATH_CHARACTERS]; - - // In priority: check own directory - strcpy(config_dir, program_dir); - strcpy(filename, config_dir); - strcat(filename, "gfx2.cfg"); - - if (!File_exists(filename)) - { - char *config_parent_dir; - #if defined(__WIN32__) - // "%APPDATA%\GrafX2" - const char* Config_SubDir = "GrafX2"; - config_parent_dir = getenv("APPDATA"); - #elif defined(__BEOS__) || defined(__HAIKU__) - // "~/.grafx2", the BeOS way - const char* Config_SubDir = ".grafx2"; - config_parent_dir = getenv("$HOME"); - #else - // "~/.grafx2" - const char* Config_SubDir = ".grafx2"; - config_parent_dir = getenv("HOME"); - #endif - - if (config_parent_dir && config_parent_dir[0]!='\0') - { - int size = strlen(config_parent_dir); - strcpy(config_dir, config_parent_dir); - if (config_parent_dir[size-1] != '\\' && config_parent_dir[size-1] != '/') - { - strcat(config_dir,PATH_SEPARATOR); - } - strcat(config_dir,Config_SubDir); - if (Directory_exists(config_dir)) - { - // Répertoire trouvé, ok - strcat(config_dir,PATH_SEPARATOR); - } - else - { - // Tentative de création - if (!Create_ConfigDirectory(config_dir)) - { - // Réussi - strcat(config_dir,PATH_SEPARATOR); - } - else - { - // Echec: on se rabat sur le repertoire de l'executable. - strcpy(config_dir,program_dir); - } - } - } - } - #endif -} +/* Grafx2 - The Ultimate 256-color bitmap paint program + + Copyright 2008 Peter Gordon + Copyright 2008 Yves Rizoud + Copyright 2008 Franck Charlet + Copyright 2007 Adrien Destugues + Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) + + Grafx2 is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 + of the License. + + Grafx2 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grafx2; if not, see +*/ + +#include +#include +#include +#include +#include +#if defined(__WIN32__) + #include + #include // Mingw's _mkdir() +#elif defined(__macosx__) + #import + #import +#elif defined(__FreeBSD__) + #import +#endif + +#include "struct.h" +#include "io.h" +#include "setup.h" + +int Create_ConfigDirectory(char * config_dir) +{ + #ifdef __WIN32__ + // Mingw's mkdir has a weird name and only one argument + return _mkdir(config_dir); + #else + return mkdir(config_dir,S_IRUSR|S_IWUSR|S_IXUSR); + #endif +} + +#if defined(__macosx__) || defined(__amigaos4__) || defined(__AROS__) || defined(__MORPHOS__) || defined(__amigaos__) + #define ARG_UNUSED __attribute__((unused)) +#else + #define ARG_UNUSED +#endif +// Determine which directory contains the executable. +// IN: Main's argv[0], some platforms need it, some don't. +// OUT: Write into program_dir. Trailing / or \ is kept. +// Note : in fact this is only used to check for the datafiles and fonts in +// this same directory. +void Set_program_directory(ARG_UNUSED const char * argv0,char * program_dir) +{ + #undef ARG_UNUSED + + // MacOSX + #if defined(__macosx__) + CFURLRef url = CFBundleCopyBundleURL(CFBundleGetMainBundle()); + CFURLGetFileSystemRepresentation(url,true,(UInt8*)program_dir,MAXPATHLEN); + CFRelease(url); + // Append trailing slash + strcat(program_dir ,"/"); + + // AmigaOS and alike: hard-coded volume name. + #elif defined(__amigaos4__) || defined(__AROS__) || defined(__MORPHOS__) || defined(__amigaos__) + strcpy(program_dir,"PROGDIR:"); + + // Others: The part of argv[0] before the executable name. + // Keep the last \ or /. + // Note that on Unix, once installed, the executable is called from a shell + // script sitting in /usr/local/bin/, this allows argv[0] to contain the full + // path. On Windows, Mingw32 already provides the full path in all cases. + #else + Extract_path(program_dir, argv0); + #endif +} + +// Determine which directory contains the read-only data. +// IN: The directory containing the executable +// OUT: Write into data_dir. Trailing / or \ is kept. +void Set_data_directory(const char * program_dir, char * data_dir) +{ + // On all platforms, data is in the executable's directory + strcpy(data_dir,program_dir); + // Except MacOSX, here it is stored in a special folder: + #if defined(__macosx__) + strcat(data_dir,"Contents/Resources/"); + #endif +} + +// Determine which directory should store the user's configuration. +// +// For most Unix and Windows platforms: +// If a config file already exists in program_dir, it will return it in priority +// (Useful for development, and possibly for upgrading from DOS version) +// If the standard directory doesn't exist yet, this function will attempt +// to create it ($(HOME)/.grafx2, or %APPDATA%\GrafX2) +// If it cannot be created, this function will return the executable's +// own directory. +// IN: The directory containing the executable +// OUT: Write into config_dir. Trailing / or \ is kept. +void Set_config_directory(const char * program_dir, char * config_dir) +{ + // AmigaOS4 + #if defined(__amigaos4__) || defined(__AROS__) + strcpy(config_dir,"PROGDIR:"); + // GP2X + #elif defined(__GP2X__) + // On the GP2X, the program is installed to the sdcard, and we don't want to mess with the system tree which is + // on an internal flash chip. So, keep these settings locals. + strcpy(config_dir,program_dir); + #else + char filename[MAX_PATH_CHARACTERS]; + + // In priority: check own directory + strcpy(config_dir, program_dir); + strcpy(filename, config_dir); + strcat(filename, "gfx2.cfg"); + + if (!File_exists(filename)) + { + char *config_parent_dir; + #if defined(__WIN32__) + // "%APPDATA%\GrafX2" + const char* Config_SubDir = "GrafX2"; + config_parent_dir = getenv("APPDATA"); + #elif defined(__BEOS__) || defined(__HAIKU__) + // "~/.grafx2", the BeOS way + const char* Config_SubDir = ".grafx2"; + config_parent_dir = getenv("$HOME"); + #elif defined(__macosx__) + // "~/Library/Preferences/com.googlecode.grafx2" + const char* Config_SubDir = "Library/Preferences/com.googlecode.grafx2"; + config_parent_dir = getenv("HOME"); + #else + // "~/.grafx2" + const char* Config_SubDir = ".grafx2"; + config_parent_dir = getenv("HOME"); + #endif + + if (config_parent_dir && config_parent_dir[0]!='\0') + { + int size = strlen(config_parent_dir); + strcpy(config_dir, config_parent_dir); + if (config_parent_dir[size-1] != '\\' && config_parent_dir[size-1] != '/') + { + strcat(config_dir,PATH_SEPARATOR); + } + strcat(config_dir,Config_SubDir); + if (Directory_exists(config_dir)) + { + // Répertoire trouvé, ok + strcat(config_dir,PATH_SEPARATOR); + } + else + { + // Tentative de création + if (!Create_ConfigDirectory(config_dir)) + { + // Réussi + strcat(config_dir,PATH_SEPARATOR); + } + else + { + // Echec: on se rabat sur le repertoire de l'executable. + strcpy(config_dir,program_dir); + } + } + } + } + #endif +} diff --git a/setup.h b/setup.h index c4df3f40..0fc2e25e 100644 --- a/setup.h +++ b/setup.h @@ -1,54 +1,54 @@ -/* Grafx2 - The Ultimate 256-color bitmap paint program - - Copyright 2008 Peter Gordon - Copyright 2008 Yves Rizoud - Copyright 2008 Franck Charlet - Copyright 2007 Adrien Destugues - Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) - - Grafx2 is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; version 2 - of the License. - - Grafx2 is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Grafx2; if not, see -*/ - -////////////////////////////////////////////////////////////////////////////// -///@file setup.h -/// Functions that determine where grafx2 is running, finds its data, and -/// reads and writes configuration files. -////////////////////////////////////////////////////////////////////////////// - -/// -/// Determine which directory contains the executable. -/// - IN: Main's argv[0], some platforms need it, some don't. -/// - OUT: Write into program_dir. Trailing / or \ is kept. -/// Note : in fact this is only used to check for the datafiles and fonts in this same directory. -void Set_program_directory(const char * argv0,char * program_dir); - -/// -/// Determine which directory contains the read-only data. -/// IN: The directory containing the executable -/// OUT: Write into data_dir. Trailing / or \ is kept. -void Set_data_directory(const char * program_dir, char * data_dir); - -/// -/// Determine which directory should store the user's configuration. -/// For most Unix and Windows platforms: -/// If a config file already exists in program_dir, it will return it in priority -/// (Useful for development, and possibly for upgrading from DOS version) -/// If the standard directory doesn't exist yet, this function will attempt -/// to create it ($(HOME)/.grafx2, or %APPDATA%\\GrafX2) -/// If it cannot be created, this function will return the executable's -/// own directory. -/// IN: The directory containing the executable -/// OUT: Write into config_dir. Trailing / or \ is kept. -void Set_config_directory(const char * program_dir, char * config_dir); - +/* Grafx2 - The Ultimate 256-color bitmap paint program + + Copyright 2008 Peter Gordon + Copyright 2008 Yves Rizoud + Copyright 2008 Franck Charlet + Copyright 2007 Adrien Destugues + Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) + + Grafx2 is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 + of the License. + + Grafx2 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grafx2; if not, see +*/ + +////////////////////////////////////////////////////////////////////////////// +///@file setup.h +/// Functions that determine where grafx2 is running, finds its data, and +/// reads and writes configuration files. +////////////////////////////////////////////////////////////////////////////// + +/// +/// Determine which directory contains the executable. +/// - IN: Main's argv[0], some platforms need it, some don't. +/// - OUT: Write into program_dir. Trailing / or \ is kept. +/// Note : in fact this is only used to check for the datafiles and fonts in this same directory. +void Set_program_directory(const char * argv0,char * program_dir); + +/// +/// Determine which directory contains the read-only data. +/// IN: The directory containing the executable +/// OUT: Write into data_dir. Trailing / or \ is kept. +void Set_data_directory(const char * program_dir, char * data_dir); + +/// +/// Determine which directory should store the user's configuration. +/// For most Unix and Windows platforms: +/// If a config file already exists in program_dir, it will return it in priority +/// (Useful for development, and possibly for upgrading from DOS version) +/// If the standard directory doesn't exist yet, this function will attempt +/// to create it ($(HOME)/.grafx2, or %APPDATA%\\GrafX2) +/// If it cannot be created, this function will return the executable's +/// own directory. +/// IN: The directory containing the executable +/// OUT: Write into config_dir. Trailing / or \ is kept. +void Set_config_directory(const char * program_dir, char * config_dir); + diff --git a/shade.c b/shade.c index 7d8e5782..32d0dfed 100644 --- a/shade.c +++ b/shade.c @@ -978,6 +978,8 @@ int Menu_shade(void) Key=0; Window_help(BUTTON_EFFECTS, "SHADE"); } + else if (Is_shortcut(Key,SPECIAL_SHADE_MENU)) + clicked_button=5; } } while ((clicked_button!=4) && (clicked_button!=5)); @@ -1097,6 +1099,8 @@ void Button_Quick_shade_menu(void) } if (Is_shortcut(Key,0x100+BUTTON_HELP)) Window_help(BUTTON_EFFECTS, "QUICK SHADE"); + else if (Is_shortcut(Key,SPECIAL_QUICK_SHADE_MENU)) + clicked_button=1; } while ((clicked_button!=1) && (clicked_button!=2)); diff --git a/shade.h b/shade.h index 2a0d0b69..7f9e23c8 100644 --- a/shade.h +++ b/shade.h @@ -1,32 +1,32 @@ -/* Grafx2 - The Ultimate 256-color bitmap paint program - - Copyright 2007 Adrien Destugues - Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) - - Grafx2 is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; version 2 - of the License. - - Grafx2 is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Grafx2; if not, see -*/ -////////////////////////////////////////////////////////////////////////////// -///@file shade.h -/// Screens for Shade and Quick-shade settings. -////////////////////////////////////////////////////////////////////////////// - - -#ifndef SHADE_H_INCLUDED -#define SHADE_H_INCLUDED - -void Button_Quick_shade_menu(void); - -int Shade_settings_menu(void); - -#endif // SHADE_H_INCLUDED +/* Grafx2 - The Ultimate 256-color bitmap paint program + + Copyright 2007 Adrien Destugues + Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) + + Grafx2 is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 + of the License. + + Grafx2 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grafx2; if not, see +*/ +////////////////////////////////////////////////////////////////////////////// +///@file shade.h +/// Screens for Shade and Quick-shade settings. +////////////////////////////////////////////////////////////////////////////// + + +#ifndef SHADE_H_INCLUDED +#define SHADE_H_INCLUDED + +void Button_Quick_shade_menu(void); + +int Shade_settings_menu(void); + +#endif // SHADE_H_INCLUDED diff --git a/skins/base.gif b/skins/base.gif deleted file mode 100644 index a4ec6bfb..00000000 Binary files a/skins/base.gif and /dev/null differ diff --git a/skins/font_Classic.png b/skins/font_Classic.png new file mode 100644 index 00000000..8db8d5fc Binary files /dev/null and b/skins/font_Classic.png differ diff --git a/skins/font_Fairlight.png b/skins/font_Fairlight.png new file mode 100644 index 00000000..5d4f9818 Binary files /dev/null and b/skins/font_Fairlight.png differ diff --git a/skins/font_Fun.png b/skins/font_Fun.png new file mode 100644 index 00000000..a1e36add Binary files /dev/null and b/skins/font_Fun.png differ diff --git a/skins/font_Melon.png b/skins/font_Melon.png new file mode 100644 index 00000000..efa4d4f0 Binary files /dev/null and b/skins/font_Melon.png differ diff --git a/skins/ilkke.png b/skins/ilkke.png deleted file mode 100644 index 9de1b6f2..00000000 Binary files a/skins/ilkke.png and /dev/null differ diff --git a/skins/skin_classic.png b/skins/skin_classic.png new file mode 100644 index 00000000..6ce4c024 Binary files /dev/null and b/skins/skin_classic.png differ diff --git a/skins/skin_modern.png b/skins/skin_modern.png new file mode 100644 index 00000000..4247fc14 Binary files /dev/null and b/skins/skin_modern.png differ diff --git a/special.c b/special.c index 61a09152..492037b4 100644 --- a/special.c +++ b/special.c @@ -1,364 +1,413 @@ -/* Grafx2 - The Ultimate 256-color bitmap paint program - - Copyright 2007 Adrien Destugues - Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) - - Grafx2 is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; version 2 - of the License. - - Grafx2 is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Grafx2; if not, see -*/ -#include -#include -#include "const.h" -#include "struct.h" -#include "global.h" -#include "graph.h" -#include "engine.h" -#include "windows.h" -#include "special.h" - - - -//---------------------- Modifier le pinceau spécial ------------------------- - -void Set_paintbrush_size(int width, int height) -{ - int x_pos,y_pos; - int x,y; - float radius2; - - if (width<1) width=1; - if (height<1) height=1; - if (width>MAX_PAINTBRUSH_SIZE) width=MAX_PAINTBRUSH_SIZE; - if (height>MAX_PAINTBRUSH_SIZE) height=MAX_PAINTBRUSH_SIZE; - Paintbrush_width=width; - Paintbrush_height=height; - Paintbrush_offset_X=Paintbrush_width>>1; - Paintbrush_offset_Y=Paintbrush_height>>1; - switch (Paintbrush_shape) - { - case PAINTBRUSH_SHAPE_ROUND : - radius2=Paintbrush_offset_X+0.414213562; // [0.410..0.415[ - radius2*=radius2; - for (y_pos=0; y_pos>1; - for (y_pos=0; y_pos>1; - for (y_pos=0; y_pos>1; - for (y_pos=0; y_pos>1; - for (y_pos=0; y_pos>1; - for (y_pos=0; y_pos1) - || (Paintbrush_height>1) ) ) - { - Hide_cursor(); - switch (Paintbrush_shape) - { - case PAINTBRUSH_SHAPE_ROUND: - case PAINTBRUSH_SHAPE_SIEVE_ROUND: - case PAINTBRUSH_SHAPE_CROSS: - case PAINTBRUSH_SHAPE_PLUS: - case PAINTBRUSH_SHAPE_DIAMOND: - case PAINTBRUSH_SHAPE_RANDOM: - if (Paintbrush_width&1) - Set_paintbrush_size(Paintbrush_width-2,Paintbrush_height-2); - else - Set_paintbrush_size(Paintbrush_width-1,Paintbrush_height-1); - break; - case PAINTBRUSH_SHAPE_SQUARE: - case PAINTBRUSH_SHAPE_SLASH: - case PAINTBRUSH_SHAPE_ANTISLASH: - case PAINTBRUSH_SHAPE_SIEVE_SQUARE: - Set_paintbrush_size(Paintbrush_width-1,Paintbrush_height-1); - break; - case PAINTBRUSH_SHAPE_HORIZONTAL_BAR: - Set_paintbrush_size(Paintbrush_width-1,1); - break; - case PAINTBRUSH_SHAPE_VERTICAL_BAR: - Set_paintbrush_size(1,Paintbrush_height-1); - } - Display_paintbrush_in_menu(); - Display_cursor(); - } -} - -void Bigger_paintbrush(void) -{ - if ( (Paintbrush_shapeMain_image_width) - temp_x_offset=Main_image_width-Screen_width; - if (temp_y_offset+Menu_Y>Main_image_height) - temp_y_offset=Main_image_height-Menu_Y; - if (temp_x_offset<0) - temp_x_offset=0; - if (temp_y_offset<0) - temp_y_offset=0; - - if ( (Main_offset_X!=temp_x_offset) || - (Main_offset_Y!=temp_y_offset) ) - { - Hide_cursor(); - Main_offset_X=temp_x_offset; - Main_offset_Y=temp_y_offset; - - Compute_limits(); - Compute_paintbrush_coordinates(); - - Display_all_screen(); // <=> Display_screen + Display_image_limits - Display_cursor(); - } -} - - -// ---------------------- Scroller la fenêtre de la loupe -------------------- -void Scroll_magnifier(short delta_x,short delta_y) -{ - short temp_x_offset; - short temp_y_offset; - - temp_x_offset=Main_magnifier_offset_X+delta_x; - temp_y_offset=Main_magnifier_offset_Y+delta_y; - - if (temp_x_offset+Main_magnifier_width>Main_image_width) - temp_x_offset=Main_image_width-Main_magnifier_width; - if (temp_y_offset+Main_magnifier_height>Main_image_height) - temp_y_offset=Main_image_height-Main_magnifier_height; - if (temp_x_offset<0) - temp_x_offset=0; - if (temp_y_offset<0) - temp_y_offset=0; - - if ( (Main_magnifier_offset_X!=temp_x_offset) || - (Main_magnifier_offset_Y!=temp_y_offset) ) - { - Hide_cursor(); - Main_magnifier_offset_X=temp_x_offset; - Main_magnifier_offset_Y=temp_y_offset; - - Position_screen_according_to_zoom(); - - Compute_limits(); - Compute_paintbrush_coordinates(); - - Display_all_screen(); - Display_cursor(); - } -} - - -// -------------- Changer le Zoom (grâce aux touches [+] et [-]) ------------- -void Zoom(short delta) -{ - short index; - for (index=0; ZOOM_FACTOR[index]!=Main_magnifier_factor; index++); - index+=delta; - - if ( (index>=0) && (index +*/ +#include +#include +#include "const.h" +#include "struct.h" +#include "global.h" +#include "graph.h" +#include "engine.h" +#include "windows.h" +#include "special.h" + + + +//---------------------- Modifier le pinceau spécial ------------------------- + +int Circle_squared_diameter(int diameter) +{ + int result = diameter*diameter; + // Trick to make some circles rounder, even though + // mathematically incorrect. + if (diameter==3 || diameter==9) + return result-2; + if (diameter==11) + return result-6; + if (diameter==14) + return result-4; + + return result; +} + +void Set_paintbrush_size(int width, int height) +{ + int x_pos,y_pos; + int x,y; + int radius2; + + if (width<1) width=1; + if (height<1) height=1; + if (width>MAX_PAINTBRUSH_SIZE) width=MAX_PAINTBRUSH_SIZE; + if (height>MAX_PAINTBRUSH_SIZE) height=MAX_PAINTBRUSH_SIZE; + Paintbrush_width=width; + Paintbrush_height=height; + Paintbrush_offset_X=Paintbrush_width>>1; + Paintbrush_offset_Y=Paintbrush_height>>1; + switch (Paintbrush_shape) + { + case PAINTBRUSH_SHAPE_ROUND : + radius2=Circle_squared_diameter(Paintbrush_width); + + for (y_pos=0, y=1-Paintbrush_height; y_pos>1; + for (y_pos=0; y_pos>1; + for (y_pos=0; y_pos>1; + for (y_pos=0; y_pos>1; + for (y_pos=0; y_pos>1; + for (y_pos=0; y_pos0) + Paintbrush_sprite[(y_pos*MAX_PAINTBRUSH_SIZE)+x_pos-1]=0; + if (y_pos>0) + Paintbrush_sprite[((y_pos-1)*MAX_PAINTBRUSH_SIZE)+x_pos]=0; + } + } + } +} + +void Smaller_paintbrush(void) +{ + if ( (Paintbrush_shape1) + || (Paintbrush_height>1) ) ) + { + Hide_cursor(); + switch (Paintbrush_shape) + { + case PAINTBRUSH_SHAPE_CROSS: + case PAINTBRUSH_SHAPE_PLUS: + case PAINTBRUSH_SHAPE_DIAMOND: + if (Paintbrush_width&1) + Set_paintbrush_size(Paintbrush_width-2,Paintbrush_height-2); + else + Set_paintbrush_size(Paintbrush_width-1,Paintbrush_height-1); + break; + case PAINTBRUSH_SHAPE_SQUARE: + case PAINTBRUSH_SHAPE_SLASH: + case PAINTBRUSH_SHAPE_ANTISLASH: + case PAINTBRUSH_SHAPE_SIEVE_SQUARE: + case PAINTBRUSH_SHAPE_ROUND: + case PAINTBRUSH_SHAPE_SIEVE_ROUND: + case PAINTBRUSH_SHAPE_RANDOM: + Set_paintbrush_size(Paintbrush_width-1,Paintbrush_height-1); + break; + case PAINTBRUSH_SHAPE_HORIZONTAL_BAR: + Set_paintbrush_size(Paintbrush_width-1,1); + break; + case PAINTBRUSH_SHAPE_VERTICAL_BAR: + Set_paintbrush_size(1,Paintbrush_height-1); + } + Display_paintbrush_in_menu(); + Display_cursor(); + } +} + +void Bigger_paintbrush(void) +{ + if ( (Paintbrush_shapeMain_image_width) + temp_x_offset=Main_image_width-Screen_width; + if (temp_y_offset+Menu_Y>Main_image_height) + temp_y_offset=Main_image_height-Menu_Y; + if (temp_x_offset<0) + temp_x_offset=0; + if (temp_y_offset<0) + temp_y_offset=0; + + if ( (Main_offset_X!=temp_x_offset) || + (Main_offset_Y!=temp_y_offset) ) + { + Hide_cursor(); + Main_offset_X=temp_x_offset; + Main_offset_Y=temp_y_offset; + + Compute_limits(); + Compute_paintbrush_coordinates(); + + Display_all_screen(); // <=> Display_screen + Display_image_limits + Display_cursor(); + } +} + + +// ---------------------- Scroller la fenêtre de la loupe -------------------- +void Scroll_magnifier(short delta_x,short delta_y) +{ + short temp_x_offset; + short temp_y_offset; + + temp_x_offset=Main_magnifier_offset_X+delta_x; + temp_y_offset=Main_magnifier_offset_Y+delta_y; + + if (temp_x_offset+Main_magnifier_width>Main_image_width) + temp_x_offset=Main_image_width-Main_magnifier_width; + if (temp_y_offset+Main_magnifier_height>Main_image_height) + temp_y_offset=Main_image_height-Main_magnifier_height; + if (temp_x_offset<0) + temp_x_offset=0; + if (temp_y_offset<0) + temp_y_offset=0; + + if ( (Main_magnifier_offset_X!=temp_x_offset) || + (Main_magnifier_offset_Y!=temp_y_offset) ) + { + Hide_cursor(); + Main_magnifier_offset_X=temp_x_offset; + Main_magnifier_offset_Y=temp_y_offset; + + Position_screen_according_to_zoom(); + + Compute_limits(); + Compute_paintbrush_coordinates(); + + Display_all_screen(); + Display_cursor(); + } +} + + +// -------------- Changer le Zoom (grâce aux touches [+] et [-]) ------------- +void Zoom(short delta) +{ + short index; + for (index=0; ZOOM_FACTOR[index]!=Main_magnifier_factor; index++); + index+=delta; + + if ( (index>=0) && (index -*/ - -////////////////////////////////////////////////////////////////////////////// -///@file special.h -/// Editor functions that can be hooked to a keyboard shortcut, but don't have -/// a menu button associated to them. -////////////////////////////////////////////////////////////////////////////// - -void Set_paintbrush_size(int width, int height); -void Smaller_paintbrush(void); -void Bigger_paintbrush(void); - -void Special_next_forecolor(void); -void Special_previous_forecolor(void); -void Special_next_backcolor(void); -void Special_previous_backcolor(void); - -void Special_next_user_forecolor(void); -void Special_previous_user_forecolor(void); -void Special_next_user_backcolor(void); -void Special_previous_user_backcolor(void); - -void Scroll_screen(short delta_x,short delta_y); -void Scroll_magnifier(short delta_x,short delta_y); - -void Zoom(short delta); +/* Grafx2 - The Ultimate 256-color bitmap paint program + + Copyright 2007 Adrien Destugues + Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) + + Grafx2 is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 + of the License. + + Grafx2 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grafx2; if not, see +*/ + +////////////////////////////////////////////////////////////////////////////// +///@file special.h +/// Editor functions that can be hooked to a keyboard shortcut, but don't have +/// a menu button associated to them. +////////////////////////////////////////////////////////////////////////////// + +void Set_paintbrush_size(int width, int height); +void Smaller_paintbrush(void); +void Bigger_paintbrush(void); + +void Special_next_forecolor(void); +void Special_previous_forecolor(void); +void Special_next_backcolor(void); +void Special_previous_backcolor(void); + +void Special_next_user_forecolor(void); +void Special_previous_user_forecolor(void); +void Special_next_user_backcolor(void); +void Special_previous_user_backcolor(void); + +void Scroll_screen(short delta_x,short delta_y); +void Scroll_magnifier(short delta_x,short delta_y); + +void Zoom(short delta); +void Zoom_set(int index); + +void Display_stored_brush_in_window(word x,word y,int number); +void Store_brush(int index); +byte Restore_brush(int index); \ No newline at end of file diff --git a/struct.h b/struct.h index 81f26b0d..7ffed0b4 100644 --- a/struct.h +++ b/struct.h @@ -1,307 +1,424 @@ -/* Grafx2 - The Ultimate 256-color bitmap paint program - - Copyright 2008 Yves Rizoud - Copyright 2007 Adrien Destugues - Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) - - Grafx2 is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; version 2 - of the License. - - Grafx2 is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Grafx2; if not, see -*/ - -////////////////////////////////////////////////////////////////////////////// -///@file struct.h -/// Structures that can be used in the whole program. -////////////////////////////////////////////////////////////////////////////// -#ifndef _STRUCT_H_ -#define _STRUCT_H_ - -#if defined(__BEOS__) - #include -#else - #include -#endif - -#include "const.h" - -// Definition of the base data types -/// 8bit unsigned integer -#define byte uint8_t -/// 16bit unsigned integer -#define word uint16_t -/// 32bit unsigned integer -#define dword uint32_t -/// 64bit unsigned integer -#define qword uint64_t - -// Named function prototypes -typedef void (* Func_action) (void); -typedef void (* Func_pixel) (word,word,byte); -typedef byte (* Func_read) (word,word); -typedef void (* Func_clear) (byte); -typedef void (* Func_display) (word,word,word); -typedef byte (* Func_effect) (word,word,byte); -typedef void (* Func_block) (word,word,word,word,byte); -typedef void (* Func_line_XOR) (word,word,word); -typedef void (* Func_display_brush_color) (word,word,word,word,word,word,byte,word); -typedef void (* Func_display_brush_mono) (word,word,word,word,word,word,byte,byte,word); -typedef void (* Func_gradient) (long,short,short); -typedef void (* Func_remap) (word,word,word,word,byte *); -typedef void (* Func_procsline) (word,word,word,byte *); -typedef void (* Func_display_zoom) (word,word,word,byte *); -typedef void (* Func_display_brush_color_zoom) (word,word,word,word,word,word,byte,word,byte *); -typedef void (* Func_display_brush_mono_zoom) (word,word,word,word,word,word,byte,byte,word,byte *); -typedef void (* Func_draw_brush) (byte *,word,word,word,word,word,word,byte,word); - -/// A set of RGB values. -typedef struct -{ - byte R; ///< Red - byte G; ///< Green - byte B; ///< Blue -}__attribute__ ((__packed__)) T_Components, T_Palette[256]; ///< A complete 256-entry RGB palette (768 bytes). - -/// A normal rectangular button in windows and menus. -typedef struct T_Normal_button -{ - short Number; ///< Unique identifier for all controls - word Pos_X; ///< Coordinate for top of button, relative to the window, before scaling. - word Pos_Y; ///< Coordinate for left of button, relative to the window, before scaling. - word Width; ///< Width before scaling - word Height; ///< Height before scaling - byte Clickable; ///< Boolean, unused. - byte Repeatable; ///< Boolean, true if the button activates repeatedly until you release the mouse button. Used for "+" buttons, for example. - word Shortcut; ///< Keyboard shortcut that will emulate a click on this button. - struct T_Normal_button * Next;///< Pointer to the next normal button of current window. -} T_Normal_button; - -/// A window control that shows a complete 256-color palette -typedef struct T_Palette_button -{ - short Number; ///< Unique identifier for all controls - word Pos_X; ///< Coordinate for top of button, relative to the window, before scaling. - word Pos_Y; ///< Coordinate for left of button, relative to the window, before scaling. - struct T_Palette_button * Next;///< Pointer to the next palette of current window. -} T_Palette_button; - -/// A window control that represents a vertical scrollbar, with a slider, and two arrow buttons. -typedef struct T_Scroller_button -{ - short Number; ///< Unique identifier for all controls - word Pos_X; ///< Coordinate for top of button, relative to the window, before scaling. - word Pos_Y; ///< Coordinate for left of button, relative to the window, before scaling. - word Height; ///< Height before scaling. - word Nb_elements; ///< Number of distinct values it can take. - word Nb_visibles; ///< If this slider is meant to show several elements of a collection, this is their number (otherwise, it's 1). - word Position; ///< Current position of the slider: which item it's pointing. - word Cursor_height; ///< Vertical dimension of the slider, in pixels before scaling. - struct T_Scroller_button * Next;///< Pointer to the next scroller of current window. -} T_Scroller_button; - -/// -/// A window control that only has a rectangular "active" area which catches mouse clicks, -// but no visible shape. It's used for custom controls where the drawing is done on -// a case by case basis. -typedef struct T_Special_button -{ - short Number; ///< Unique identifier for all controls - word Pos_X; ///< Coordinate for top of button, relative to the window, before scaling. - word Pos_Y; ///< Coordinate for left of button, relative to the window, before scaling. - word Width; ///< Width before scaling - word Height; ///< Height before scaling - struct T_Special_button * Next;///< Pointer to the next special button of current window. -} T_Special_button; - -/// Data for a dropdown item, ie. one proposed choice. -typedef struct T_Dropdown_choice -{ - short Number; ///< Value that identifies the choice (for this dropdown only) - const char * Label; ///< String to display in the dropdown panel - struct T_Dropdown_choice * Next;///< Pointer to the next choice for this dropdown. -} T_Dropdown_choice; - -/// A window control that behaves like a dropdown button. -typedef struct T_Dropdown_button -{ - short Number; ///< Unique identifier for all controls - word Pos_X; ///< Coordinate for top of button, relative to the window, before scaling. - word Pos_Y; ///< Coordinate for left of button, relative to the window, before scaling. - word Width; ///< Width before scaling - word Height; ///< Height before scaling - byte Display_choice; ///< Boolean, true if the engine should print the selected item's label in the dropdown area when the user chooses it. - byte Display_centered; ///< Boolean, true to center the labels (otherwise, align left) - byte Display_arrow; ///< Boolean, true to display a "down" arrow box in top right - byte Active_button; ///< Determines which mouse button(s) cause the dropdown panel to open: LEFT_SIDE || RIGHT_SIDE || (LEFT_SIDE|RIGHT_SIDE) - word Dropdown_width; ///< Width of the dropdown panel when it's open. Use 0 for "same as the dropdown button" - T_Dropdown_choice * First_item; ///< Linked list with the choices available for this dropdown. - struct T_Dropdown_button * Next;///< Pointer to the next dropdown button of current window. -} T_Dropdown_button; - -/// Data for one item (file, directory) in a fileselector. -typedef struct T_Fileselector_item -{ - char Short_name[19]; ///< Name to display. - char Full_name[256]; ///< Filesystem value. - byte Type; ///< Type of item: 0 = File, 1 = Directory, 2 = Drive - - struct T_Fileselector_item * Next; ///< Pointer to next item of the current fileselector. - struct T_Fileselector_item * Previous;///< Pointer to previous item of the current fileselector. -} T_Fileselector_item; - -/// Data for one line of the "Help" screens. -typedef struct { - char Line_type; ///< Kind of line: 'N' for normal line, 'S' for a bold line, 'K' for a line with keyboard shortcut, 'T' and '-' for upper and lower titles. - char * Text; ///< Displayed string. - int Line_parameter; ///< Generic parameter depending on line type. For 'K' lines: a shortcut identifier. For others: unused. -} T_Help_table; - -/// Data for one section of the "Help" screens, ie a page. -typedef struct -{ - const T_Help_table* Help_table; ///< Pointer to the array of ::T_Help_table that contains the lines - word Length; ///< Size of the array of lines -} T_Help_section; - -/// Data for one setting of gradients. Warning, this one is saved/loaded as binary. -typedef struct -{ - byte Start; ///< First color - byte End; ///< Last color - dword Inverse; ///< Boolean, true if the gradient goes in descending order - dword Mix; ///< Amount of randomness to add to the mix (0-255) - dword Technique;///< Gradient technique: 0 (no pattern) 1 (dithering), or 2 (big dithering) -} T_Gradient_array; - -/// Data for one setting of shade. Warning, this one is saved/loaded as binary. -typedef struct -{ - word List[512]; ///< List of entries, each one is either a color (0-255) or -1 for empty. - byte Step; ///< Step to increment/decrement on left-clicks. - byte Mode; ///< Shade mode: Normal, Loop, or No-saturation see ::SHADE_MODES -} T_Shade; - -/// Data for one fullscreen video mode in configuration file. Warning, this one is saved/loaded as binary. -typedef struct -{ - byte State; ///< How good is the mode supported. 0:Good (white) 1:OK (light) 2:So-so (dark) 4:User-disabled (black); +128 => System doesn't support it at all. - word Width; ///< Videomode width in pixels. - word Height;///< Videomode height in pixels. -} __attribute__((__packed__)) T_Config_video_mode; - -/// Header for gfx2.cfg. Warning, this one is saved/loaded as binary. -typedef struct -{ - char Signature[3]; ///< Signature for the file format. "CFG". - byte Version1; ///< Major version number (ex: 2) - byte Version2; ///< Minor version number (ex: 0) - byte Beta1; ///< Major beta version number (ex: 96) - byte Beta2; ///< Major beta version number (ex: 5) -} __attribute__((__packed__)) T_Config_header; - -/// Header for a config chunk in for gfx2.cfg. Warning, this one is saved/loaded as binary. -typedef struct -{ - byte Number; ///< Section identfier. Possible values are in enum ::CHUNKS_CFG - word Size; ///< Size of the configuration block that follows, in bytes. -} T_Config_chunk; - -/// Configuration for one keyboard shortcut in gfx2.cfg. Warning, this one is saved/loaded as binary. -typedef struct -{ - word Number; ///< Indicates the shortcut action. This is a number starting from 0, which matches ::T_Key_config.Number - word Key; ///< Keyboard shortcut: SDLK_something, or -1 for none - word Key2; ///< Alternate keyboard shortcut: SDLK_something, or -1 for none -} __attribute__((__packed__)) T_Config_shortcut_info; - -/// This structure holds all the settings which are saved and loaded as gfx2.ini. -typedef struct -{ - byte Font; ///< Boolean, true to use the "fun" font in menus, false to use the classic one. - int Show_hidden_files; ///< Boolean, true to show hidden files in fileselectors. - int Show_hidden_directories; ///< Boolean, true to show hidden directories in fileselectors. -// int Show_system_directories; ///< (removed when converted from DOS) - byte Display_image_limits; ///< Boolean, true to display a dotted line at the borders of the image if it's smaller than screen. - byte Cursor; ///< Mouse cursor aspect: 1 Solid, 2 Transparent, 3 Thin - byte Maximize_preview; ///< Boolean, true to make previews in fileselector fit the whole rectangle. - byte Auto_set_res; ///< Boolean, true to make grafx2 switch to a new resolution whenever you load an image. - byte Coords_rel; ///< Boolean, true to display coordinates as relative (instead of absolute) - byte Backup; ///< Boolean, true to backup the original file whenever you save an image. - byte Adjust_brush_pick; ///< Boolean, true to omit the right and bottom edges when grabbing a brush in Grid mode. - byte Auto_save; ///< Boolean, true to save configuration when exiting program. - byte Max_undo_pages; ///< Number of steps to memorize for Undo/Redo. - byte Mouse_sensitivity_index_x; ///< Mouse sensitivity in X axis - byte Mouse_sensitivity_index_y; ///< Mouse sensitivity in Y axis - byte Mouse_fix_factor_X; ///< Mouse correction factor in X axis. - byte Mouse_fix_factor_Y; ///< Mouse correction factor in Y axis. - byte Mouse_merge_movement; ///< Number of SDL mouse events that are merged into a single change of mouse coordinates. - byte Delay_left_click_on_slider; ///< Delay (in 1/100s) between two activations of a repeatable button when you hold left-click. - byte Delay_right_click_on_slider; ///< Delay (in 1/100s) between two activations of a repeatable button when you hold left-click. - long Timer_delay; ///< Delay (in 1/55s) before showing a preview in a fileselector. - T_Components Fav_menu_colors[4]; ///< Favorite colors to use for the menu. - int Nb_max_vertices_per_polygon; ///< Limit for the number of vertices in polygon tools. - byte Clear_palette; ///< Boolean, true to reset the palette (to black) before loading an image. - byte Set_resolution_according_to; ///< When Auto_set_res is on, this determines if the mode should be chosen according to the "original screen" information in the file (1) or the picture dimensons (2) - byte Ratio; ///< Determines the scaling of menu and windows: 0 no scaling, 1 scaling, 2 slight scaling. - byte Fast_zoom; ///< Boolean, true if the magnifier shortcut should automatically view the mouse area. - byte Find_file_fast; ///< In fileselectors, this determines which entries should be sought when typing letters: 0 all, 1 files only, 2 directories only. - byte Separate_colors; ///< Boolean, true if the menu palette should separate color cells with a black outline. - word Palette_cells_X; ///< Number of colors to show in a row of the menu palette. - word Palette_cells_Y; ///< Number of colors to show in a column of the menu palette. - byte Palette_vertical; ///< Boolean, true if the menu palette should go top to bottom instead of left to right - byte FX_Feedback; ///< Boolean, true if drawing effects should read the image being modified (instead of the image before clicking) - byte Safety_colors; ///< Boolean, true to make the palette automatically re-create menu colors if needed after a "Zap" or color reduction. - byte Opening_message; ///< Boolean, true to display the splash screen on strtup. - byte Clear_with_stencil; ///< Boolean, true to take the stencil into effect (if active) when using the Clear function. - byte Auto_discontinuous; ///< Boolean, true to automatically switch to the discontinuous freehand draw after grabbing a brush. - byte Screen_size_in_GIF; ///< Boolean, true to store current resolution in GIF files. - byte Auto_nb_used; ///< Boolean, true to count colors in Palette screen. - byte Default_resolution; ///< Default video mode to use on startup. Index in ::Video_mode. - char *Bookmark_directory[NB_BOOKMARKS];///< Bookmarked directories in fileselectors: This is the full dierctory name. - char Bookmark_label[NB_BOOKMARKS][8+1];///< Bookmarked directories in fileselectors: This is the displayed name. - int Window_pos_x; ///< Last window x position (9999 if unsupportd/irrelevant for the platform) - int Window_pos_y; ///< Last window y position (9999 if unsupportd/irrelevant for the platform) -} T_Config; - -// Structures utilisées pour les descriptions de pages et de liste de pages. -// Lorsqu'on gèrera les animations, il faudra aussi des listes de listes de -// pages. - -// Ces structures sont manipulées à travers des fonctions de gestion du -// backup dans "graph.c". - -/// This is the data for one step of Undo/Redo, for one image. -typedef struct -{ - byte * Image; ///< Pixel data for the image. - int Width; ///< Image width in pixels. - int Height; ///< Image height in pixels. - T_Palette Palette; ///< Image palette. - - char Comment[COMMENT_SIZE+1]; ///< Comment to store in the image file. - - char File_directory[MAX_PATH_CHARACTERS];///< Directory that contains the file. - char Filename[MAX_PATH_CHARACTERS]; ///< Filename without directory. - byte File_format; ///< File format, in enum ::FILE_FORMATS - -} T_Page; - -/// Collection of undo/redo steps. -typedef struct -{ - int List_size; /// Number of ::T_Page in the vector "Pages". - int Nb_pages_allocated;/// Number of ::T_Page used so far in the vector "Pages". - T_Page * Pages; /// Vector of Pages, each one being a undo/redo step. -} T_List_of_pages; - - - -#endif +/* Grafx2 - The Ultimate 256-color bitmap paint program + + Copyright 2008 Yves Rizoud + Copyright 2007 Adrien Destugues + Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) + + Grafx2 is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 + of the License. + + Grafx2 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grafx2; if not, see +*/ + +////////////////////////////////////////////////////////////////////////////// +///@file struct.h +/// Structures that can be used in the whole program. +////////////////////////////////////////////////////////////////////////////// +#ifndef _STRUCT_H_ +#define _STRUCT_H_ + +#if defined(__BEOS__) + #include +#else + #include +#endif + +#include "const.h" + + +// POSIX calls it strcasecmp, Windows uses stricmp... no ANSI standard. +#ifdef WIN32 + #define strcasecmp stricmp +#endif + +// Definition of the base data types +/// 8bit unsigned integer +#define byte uint8_t +/// 16bit unsigned integer +#define word uint16_t +/// 32bit unsigned integer +#define dword uint32_t +/// 64bit unsigned integer +#define qword uint64_t + +// Named function prototypes +typedef void (* Func_action) (void); +typedef void (* Func_pixel) (word,word,byte); +typedef byte (* Func_read) (word,word); +typedef void (* Func_clear) (byte); +typedef void (* Func_display) (word,word,word); +typedef byte (* Func_effect) (word,word,byte); +typedef void (* Func_block) (word,word,word,word,byte); +typedef void (* Func_line_XOR) (word,word,word); +typedef void (* Func_display_brush_color) (word,word,word,word,word,word,byte,word); +typedef void (* Func_display_brush_mono) (word,word,word,word,word,word,byte,byte,word); +typedef void (* Func_gradient) (long,short,short); +typedef void (* Func_remap) (word,word,word,word,byte *); +typedef void (* Func_procsline) (word,word,word,byte *); +typedef void (* Func_display_zoom) (word,word,word,byte *); +typedef void (* Func_display_brush_color_zoom) (word,word,word,word,word,word,byte,word,byte *); +typedef void (* Func_display_brush_mono_zoom) (word,word,word,word,word,word,byte,byte,word,byte *); +typedef void (* Func_draw_brush) (byte *,word,word,word,word,word,word,byte,word); +typedef void (* Func_draw_list_item) (word,word,word,byte); + +/// A set of RGB values. +typedef struct +{ + byte R; ///< Red + byte G; ///< Green + byte B; ///< Blue +}__attribute__ ((__packed__)) T_Components, T_Palette[256]; ///< A complete 256-entry RGB palette (768 bytes). + +/// A normal rectangular button in windows and menus. +typedef struct T_Normal_button +{ + short Number; ///< Unique identifier for all controls + word Pos_X; ///< Coordinate for top of button, relative to the window, before scaling. + word Pos_Y; ///< Coordinate for left of button, relative to the window, before scaling. + word Width; ///< Width before scaling + word Height; ///< Height before scaling + byte Clickable; ///< Boolean, unused. + byte Repeatable; ///< Boolean, true if the button activates repeatedly until you release the mouse button. Used for "+" buttons, for example. + word Shortcut; ///< Keyboard shortcut that will emulate a click on this button. + struct T_Normal_button * Next;///< Pointer to the next normal button of current window. +} T_Normal_button; + +/// A window control that shows a complete 256-color palette +typedef struct T_Palette_button +{ + short Number; ///< Unique identifier for all controls + word Pos_X; ///< Coordinate for top of button, relative to the window, before scaling. + word Pos_Y; ///< Coordinate for left of button, relative to the window, before scaling. + struct T_Palette_button * Next;///< Pointer to the next palette of current window. +} T_Palette_button; + +/// A window control that represents a vertical scrollbar, with a slider, and two arrow buttons. +typedef struct T_Scroller_button +{ + short Number; ///< Unique identifier for all controls + word Pos_X; ///< Coordinate for top of button, relative to the window, before scaling. + word Pos_Y; ///< Coordinate for left of button, relative to the window, before scaling. + word Height; ///< Height before scaling. + word Nb_elements; ///< Number of distinct values it can take. + word Nb_visibles; ///< If this slider is meant to show several elements of a collection, this is their number (otherwise, it's 1). + word Position; ///< Current position of the slider: which item it's pointing. + word Cursor_height; ///< Vertical dimension of the slider, in pixels before scaling. + struct T_Scroller_button * Next;///< Pointer to the next scroller of current window. +} T_Scroller_button; + +/// +/// A window control that only has a rectangular "active" area which catches mouse clicks, +// but no visible shape. It's used for custom controls where the drawing is done on +// a case by case basis. +typedef struct T_Special_button +{ + short Number; ///< Unique identifier for all controls + word Pos_X; ///< Coordinate for top of button, relative to the window, before scaling. + word Pos_Y; ///< Coordinate for left of button, relative to the window, before scaling. + word Width; ///< Width before scaling + word Height; ///< Height before scaling + struct T_Special_button * Next;///< Pointer to the next special button of current window. +} T_Special_button; + +/// Data for a dropdown item, ie. one proposed choice. +typedef struct T_Dropdown_choice +{ + short Number; ///< Value that identifies the choice (for this dropdown only) + const char * Label; ///< String to display in the dropdown panel + struct T_Dropdown_choice * Next;///< Pointer to the next choice for this dropdown. +} T_Dropdown_choice; + +/// A window control that behaves like a dropdown button. +typedef struct T_Dropdown_button +{ + short Number; ///< Unique identifier for all controls + word Pos_X; ///< Coordinate for top of button, relative to the window, before scaling. + word Pos_Y; ///< Coordinate for left of button, relative to the window, before scaling. + word Width; ///< Width before scaling + word Height; ///< Height before scaling + byte Display_choice; ///< Boolean, true if the engine should print the selected item's label in the dropdown area when the user chooses it. + byte Display_centered; ///< Boolean, true to center the labels (otherwise, align left) + byte Display_arrow; ///< Boolean, true to display a "down" arrow box in top right + byte Active_button; ///< Determines which mouse button(s) cause the dropdown panel to open: LEFT_SIDE || RIGHT_SIDE || (LEFT_SIDE|RIGHT_SIDE) + word Dropdown_width; ///< Width of the dropdown panel when it's open. Use 0 for "same as the dropdown button" + T_Dropdown_choice * First_item; ///< Linked list with the choices available for this dropdown. + struct T_Dropdown_button * Next;///< Pointer to the next dropdown button of current window. +} T_Dropdown_button; + +/// Data for one item (file, directory) in a fileselector. +typedef struct T_Fileselector_item +{ + char Short_name[19]; ///< Name to display. + char Full_name[256]; ///< Filesystem value. + byte Type; ///< Type of item: 0 = File, 1 = Directory, 2 = Drive + + struct T_Fileselector_item * Next; ///< Pointer to next item of the current fileselector. + struct T_Fileselector_item * Previous;///< Pointer to previous item of the current fileselector. +} T_Fileselector_item; + +/// Data for a fileselector +typedef struct T_Fileselector +{ + /// Number of elements in the current fileselector's ::Filelist + short Nb_elements; + /// Number of files in the current fileselector's ::Filelist + short Nb_files; + /// Number of directories in the current fileselector's ::Filelist + short Nb_directories; + /// Head of the linked list for the fileselector. + T_Fileselector_item * First; + /// Index for direct access to element number N + T_Fileselector_item ** Index; +} T_Fileselector; + +typedef struct T_List_button +{ + short Number; ///< Unique identifier for all controls + short List_start; ///< Index of the font to appear as first line + short Cursor_position; ///< Index of the selected line (0=top) + + T_Special_button * Entry_button; ///< Pointer to the associated selection control. + T_Scroller_button * Scroller; ///< Pointer to the associated scroller + + Func_draw_list_item Draw_list_item; ///< + + struct T_List_button * Next; ///< Pointer to the next list button of current window. +} T_List_button; + +/// Data for one line of the "Help" screens. +typedef struct { + char Line_type; ///< Kind of line: 'N' for normal line, 'S' for a bold line, 'K' for a line with keyboard shortcut, 'T' and '-' for upper and lower titles. + char * Text; ///< Displayed string. + int Line_parameter; ///< Generic parameter depending on line type. For 'K' lines: a shortcut identifier. For others: unused. +} T_Help_table; + +/// Data for one section of the "Help" screens, ie a page. +typedef struct +{ + const T_Help_table* Help_table; ///< Pointer to the array of ::T_Help_table that contains the lines + word Length; ///< Size of the array of lines +} T_Help_section; + +/// Data for one setting of gradients. Warning, this one is saved/loaded as binary. +typedef struct +{ + byte Start; ///< First color + byte End; ///< Last color + dword Inverse; ///< Boolean, true if the gradient goes in descending order + dword Mix; ///< Amount of randomness to add to the mix (0-255) + dword Technique;///< Gradient technique: 0 (no pattern) 1 (dithering), or 2 (big dithering) +} T_Gradient_array; + +/// Data for one setting of shade. Warning, this one is saved/loaded as binary. +typedef struct +{ + word List[512]; ///< List of entries, each one is either a color (0-255) or -1 for empty. + byte Step; ///< Step to increment/decrement on left-clicks. + byte Mode; ///< Shade mode: Normal, Loop, or No-saturation see ::SHADE_MODES +} T_Shade; + +/// Data for one fullscreen video mode in configuration file. Warning, this one is saved/loaded as binary. +typedef struct +{ + byte State; ///< How good is the mode supported. 0:Good (white) 1:OK (light) 2:So-so (dark) 4:User-disabled (black); +128 => System doesn't support it at all. + word Width; ///< Videomode width in pixels. + word Height;///< Videomode height in pixels. +} __attribute__((__packed__)) T_Config_video_mode; + +/// Header for gfx2.cfg. Warning, this one is saved/loaded as binary. +typedef struct +{ + char Signature[3]; ///< Signature for the file format. "CFG". + byte Version1; ///< Major version number (ex: 2) + byte Version2; ///< Minor version number (ex: 0) + byte Beta1; ///< Major beta version number (ex: 96) + byte Beta2; ///< Major beta version number (ex: 5) +} __attribute__((__packed__)) T_Config_header; + +/// Header for a config chunk in for gfx2.cfg. Warning, this one is saved/loaded as binary. +typedef struct +{ + byte Number; ///< Section identfier. Possible values are in enum ::CHUNKS_CFG + word Size; ///< Size of the configuration block that follows, in bytes. +} T_Config_chunk; + +/// Configuration for one keyboard shortcut in gfx2.cfg. Warning, this one is saved/loaded as binary. +typedef struct +{ + word Number; ///< Indicates the shortcut action. This is a number starting from 0, which matches ::T_Key_config.Number + word Key; ///< Keyboard shortcut: SDLK_something, or -1 for none + word Key2; ///< Alternate keyboard shortcut: SDLK_something, or -1 for none +} __attribute__((__packed__)) T_Config_shortcut_info; + +/// This structure holds all the settings saved and loaded as gfx2.ini. +typedef struct +{ + char *Font_file; ///< Name of the font used in the menus. Matches file skins/font_*.png (Case-sensitive on some filesystems) + char *Skin_file; ///< String, name of the file where all the graphic data is stored + int Show_hidden_files; ///< Boolean, true to show hidden files in fileselectors. + int Show_hidden_directories; ///< Boolean, true to show hidden directories in fileselectors. +// int Show_system_directories; ///< (removed when converted from DOS) + byte Display_image_limits; ///< Boolean, true to display a dotted line at the borders of the image if it's smaller than screen. + byte Cursor; ///< Mouse cursor aspect: 1 Solid, 2 Transparent, 3 Thin + byte Maximize_preview; ///< Boolean, true to make previews in fileselector fit the whole rectangle. + byte Auto_set_res; ///< Boolean, true to make grafx2 switch to a new resolution whenever you load an image. + byte Coords_rel; ///< Boolean, true to display coordinates as relative (instead of absolute) + byte Backup; ///< Boolean, true to backup the original file whenever you save an image. + byte Adjust_brush_pick; ///< Boolean, true to omit the right and bottom edges when grabbing a brush in Grid mode. + byte Auto_save; ///< Boolean, true to save configuration when exiting program. + byte Max_undo_pages; ///< Number of steps to memorize for Undo/Redo. + byte Mouse_sensitivity_index_x; ///< Mouse sensitivity in X axis + byte Mouse_sensitivity_index_y; ///< Mouse sensitivity in Y axis + byte Mouse_fix_factor_X; ///< Mouse correction factor in X axis. + byte Mouse_fix_factor_Y; ///< Mouse correction factor in Y axis. + byte Mouse_merge_movement; ///< Number of SDL mouse events that are merged into a single change of mouse coordinates. + byte Delay_left_click_on_slider; ///< Delay (in 1/100s) between two activations of a repeatable button when you hold left-click. + byte Delay_right_click_on_slider; ///< Delay (in 1/100s) between two activations of a repeatable button when you hold left-click. + long Timer_delay; ///< Delay (in 1/55s) before showing a preview in a fileselector. + T_Components Fav_menu_colors[4]; ///< Favorite colors to use for the menu. + int Nb_max_vertices_per_polygon; ///< Limit for the number of vertices in polygon tools. + byte Clear_palette; ///< Boolean, true to reset the palette (to black) before loading an image. + byte Set_resolution_according_to; ///< When Auto_set_res is on, this determines if the mode should be chosen according to the "original screen" information in the file (1) or the picture dimensons (2) + int8_t Ratio; ///< Determines the scaling of menu and windows: 0 no scaling, 1 scaling, 2 slight scaling, negative= opposite of max scaling + byte Fast_zoom; ///< Boolean, true if the magnifier shortcut should automatically view the mouse area. + byte Find_file_fast; ///< In fileselectors, this determines which entries should be sought when typing letters: 0 all, 1 files only, 2 directories only. + byte Separate_colors; ///< Boolean, true if the menu palette should separate color cells with a black outline. + word Palette_cells_X; ///< Number of colors to show in a row of the menu palette. + word Palette_cells_Y; ///< Number of colors to show in a column of the menu palette. + byte Palette_vertical; ///< Boolean, true if the menu palette should go top to bottom instead of left to right + byte FX_Feedback; ///< Boolean, true if drawing effects should read the image being modified (instead of the image before clicking) + byte Safety_colors; ///< Boolean, true to make the palette automatically re-create menu colors if needed after a "Zap" or color reduction. + byte Opening_message; ///< Boolean, true to display the splash screen on strtup. + byte Clear_with_stencil; ///< Boolean, true to take the stencil into effect (if active) when using the Clear function. + byte Auto_discontinuous; ///< Boolean, true to automatically switch to the discontinuous freehand draw after grabbing a brush. + byte Screen_size_in_GIF; ///< Boolean, true to store current resolution in GIF files. + byte Auto_nb_used; ///< Boolean, true to count colors in Palette screen. + byte Default_resolution; ///< Default video mode to use on startup. Index in ::Video_mode. + char *Bookmark_directory[NB_BOOKMARKS];///< Bookmarked directories in fileselectors: This is the full dierctory name. + char Bookmark_label[NB_BOOKMARKS][8+1];///< Bookmarked directories in fileselectors: This is the displayed name. + int Window_pos_x; ///< Last window x position (9999 if unsupportd/irrelevant for the platform) + int Window_pos_y; ///< Last window y position (9999 if unsupportd/irrelevant for the platform) + word Double_click_speed; ///< Maximum delay for double-click, in ms. + word Double_key_speed; ///< Maximum delay for double-keypress, in ms. + byte Grid_XOR_color; ///< XOR value to apply for grid color. +} T_Config; + +// Structures utilisées pour les descriptions de pages et de liste de pages. +// Lorsqu'on gèrera les animations, il faudra aussi des listes de listes de +// pages. + +// Ces structures sont manipulées à travers des fonctions de gestion du +// backup dans "graph.c". + +/// This is the data for one step of Undo/Redo, for one image. +typedef struct +{ + byte * Image; ///< Pixel data for the image. + int Width; ///< Image width in pixels. + int Height; ///< Image height in pixels. + T_Palette Palette; ///< Image palette. + + char Comment[COMMENT_SIZE+1]; ///< Comment to store in the image file. + + char File_directory[MAX_PATH_CHARACTERS];///< Directory that contains the file. + char Filename[MAX_PATH_CHARACTERS]; ///< Filename without directory. + byte File_format; ///< File format, in enum ::FILE_FORMATS + +} T_Page; + +/// Collection of undo/redo steps. +typedef struct +{ + int List_size; ///< Number of ::T_Page in the vector "Pages". + int Nb_pages_allocated;///< Number of ::T_Page used so far in the vector "Pages". + T_Page * Pages; ///< Vector of Pages, each one being a undo/redo step. +} T_List_of_pages; + +/// A single memorized brush from the Brush Container +typedef struct +{ + byte Paintbrush_shape; ///< Kind of brush + byte Thumbnail[BRUSH_CONTAINER_PREVIEW_WIDTH][BRUSH_CONTAINER_PREVIEW_HEIGHT]; + // Data for color brush + word Width; + word Height; + byte * Brush; /// < Color brush (if any) + T_Palette Palette; + byte Transp_color; +} T_Brush_template; + + +/// GUI skin data +typedef struct +{ + // Mouse + + /// X coordinate of the mouse cursor's "hot spot". It is < ::CURSOR_SPRITE_WIDTH + word Cursor_offset_X[NB_CURSOR_SPRITES]; + /// Y coordinate of the mouse cursor's "hot spot". It is < ::CURSOR_SPRITE_HEIGHT + word Cursor_offset_Y[NB_CURSOR_SPRITES]; + /// Graphic resources for the mouse cursor. + byte Cursor_sprite[NB_CURSOR_SPRITES][CURSOR_SPRITE_HEIGHT][CURSOR_SPRITE_WIDTH]; + + // Preset paintbrushes + + /// Graphic resources for the preset paintbrushes. + byte Paintbrush_sprite [NB_PAINTBRUSH_SPRITES][PAINTBRUSH_HEIGHT][PAINTBRUSH_WIDTH]; + /// Width of the preset paintbrushes. + word Preset_paintbrush_width[NB_PAINTBRUSH_SPRITES]; + /// Height of the preset paintbrushes. + word Preset_paintbrush_height[NB_PAINTBRUSH_SPRITES]; + /// Type of the preset paintbrush: index in enum PAINTBRUSH_SHAPES + byte Paintbrush_type[NB_PAINTBRUSH_SPRITES]; + /// Brush handle for the preset brushes. Generally ::Preset_paintbrush_width[]/2 + word Preset_paintbrush_offset_X[NB_PAINTBRUSH_SPRITES]; + /// Brush handle for the preset brushes. Generally ::Preset_paintbrush_height[]/2 + word Preset_paintbrush_offset_Y[NB_PAINTBRUSH_SPRITES]; + + // Sieve patterns + + /// Preset sieve patterns, stored as binary (one word per line) + word Sieve_pattern[12][16]; + + // Menu and other graphics + + /// Bitmap data for the menu, a single rectangle. + byte Menu_block[MENU_HEIGHT][MENU_WIDTH]; + /// Bitmap data for the icons that are displayed over the menu. + byte Menu_sprite[NB_MENU_SPRITES][MENU_SPRITE_HEIGHT][MENU_SPRITE_WIDTH]; + /// Bitmap data for the different "effects" icons. + byte Effect_sprite[NB_EFFECTS_SPRITES][MENU_SPRITE_HEIGHT][MENU_SPRITE_WIDTH]; + /// Bitmap data for the Grafx2 logo that appears on splash screen. All 256 colors allowed. + byte Logo_grafx2[231*56]; + /// Bitmap data for the 6x8 font used in help screens. + byte Help_font_norm [256][6][8]; + /// Bitmap data for the 6x8 font used in help screens ("bold" verstion). + byte Bold_font [256][6][8]; + // 12 + // 34 + /// Bitmap data for the title font used in help screens. Top-left quarter. + byte Help_font_t1 [64][6][8]; + /// Bitmap data for the title font used in help screens. Top-right quarter. + byte Help_font_t2 [64][6][8]; + /// Bitmap data for the title font used in help screens. Bottom-left quarter. + byte Help_font_t3 [64][6][8]; + /// Bitmap data for the title font used in help screens. Bottom-right quarter. + byte Help_font_t4 [64][6][8]; + /// Bitmap data for the small 8x8 icons. + byte Icon_sprite[NB_ICON_SPRITES][ICON_SPRITE_HEIGHT][ICON_SPRITE_WIDTH]; + + /// A default 256-color palette. + T_Palette Default_palette; + + +} T_Gui_skin; + +#endif diff --git a/text.h b/text.h index 11b0f7e8..cb96813a 100644 --- a/text.h +++ b/text.h @@ -1,54 +1,54 @@ -/* Grafx2 - The Ultimate 256-color bitmap paint program - - Copyright 2008 Yves Rizoud - Copyright 2008 Adrien Destugues - Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) - - Grafx2 is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; version 2 - of the License. - - Grafx2 is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Grafx2; if not, see -*/ - -////////////////////////////////////////////////////////////////////////////// -///@file text.h -/// Functions related to rendering text as a brush, using TrueType or SFont. -////////////////////////////////////////////////////////////////////////////// - -/// Initialization of text settings, needs to be called once on program startup. -void Init_text(void); -/// Returns true if text.c was compiled with TrueType support. -int TrueType_is_supported(void); -/// Add a new font to the list to propose to the user. -void Add_font(const char *name); -/// -/// Creates a brush, from the parameters given: -/// @param str The text to render -/// @param font_number The index of the font to use. Pass 0 for the first font you declared with ::Add_font(), 1 for the second etc. -/// @param size The size in points (unused for bitmap fonts) -/// @param antialias Boolean, true to use antialiasing in TrueType -/// @param bold Boolean, true to use bold rendering in TrueType -/// @param italic Boolean, true to use italic rendering in TrueType -/// @param width Returns the width of the created brush, in pixels. -/// @param height Returns the height of the created brush, in pixels. -/// Returns true on success. -byte *Render_text(const char *str, int font_number, int size, int antialias, int bold, int italic, int *width, int *height); - -/// Finds a label to display for a font declared with ::Add_font(). -char * Font_label(int index); -/// Finds the filename of a font declared with ::Add_font(). -char * Font_name(int index); -/// Returns true if the font of this number is TrueType, false if it's a SFont bitmap. -char * TrueType_font(int index); -/// -/// Number of fonts declared with a series of ::Add_font(). This is public for -/// convenience, but functionaly it is read-only. -extern int Nb_fonts; +/* Grafx2 - The Ultimate 256-color bitmap paint program + + Copyright 2008 Yves Rizoud + Copyright 2008 Adrien Destugues + Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) + + Grafx2 is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 + of the License. + + Grafx2 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grafx2; if not, see +*/ + +////////////////////////////////////////////////////////////////////////////// +///@file text.h +/// Functions related to rendering text as a brush, using TrueType or SFont. +////////////////////////////////////////////////////////////////////////////// + +/// Initialization of text settings, needs to be called once on program startup. +void Init_text(void); +/// Returns true if text.c was compiled with TrueType support. +int TrueType_is_supported(void); +/// Add a new font to the list to propose to the user. +void Add_font(const char *name); +/// +/// Creates a brush, from the parameters given: +/// @param str The text to render +/// @param font_number The index of the font to use. Pass 0 for the first font you declared with ::Add_font(), 1 for the second etc. +/// @param size The size in points (unused for bitmap fonts) +/// @param antialias Boolean, true to use antialiasing in TrueType +/// @param bold Boolean, true to use bold rendering in TrueType +/// @param italic Boolean, true to use italic rendering in TrueType +/// @param width Returns the width of the created brush, in pixels. +/// @param height Returns the height of the created brush, in pixels. +/// Returns true on success. +byte *Render_text(const char *str, int font_number, int size, int antialias, int bold, int italic, int *width, int *height); + +/// Finds a label to display for a font declared with ::Add_font(). +char * Font_label(int index); +/// Finds the filename of a font declared with ::Add_font(). +char * Font_name(int index); +/// Returns true if the font of this number is TrueType, false if it's a SFont bitmap. +char * TrueType_font(int index); +/// +/// Number of fonts declared with a series of ::Add_font(). This is public for +/// convenience, but functionaly it is read-only. +extern int Nb_fonts; diff --git a/transform.c b/transform.c index 3f30c081..1707ab6f 100644 --- a/transform.c +++ b/transform.c @@ -1,409 +1,412 @@ -/* Grafx2 - The Ultimate 256-color bitmap paint program - - Copyright 2009 Yves Rizoud - Copyright 2009 Adrien Destugues - Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) - - Grafx2 is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; version 2 - of the License. - - Grafx2 is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Grafx2; if not, see -*/ -#include -#include - -#include "global.h" -#include "struct.h" -#include "transform.h" -#include "engine.h" -#include "sdlscreen.h" -#include "windows.h" -#include "input.h" -#include "help.h" -#include "misc.h" // Num2str -#include "readline.h" -#include "buttons.h" // Message_out_of_memory() -#include "pages.h" // Backup_with_new_dimensions() - -/// Reduces a fraction A/B to its smallest representation. ie (40,60) becomes (2/3) -void Factorize(short *a, short *b) -{ - // Method: brute-force. - short factor; - - factor=2; - while (factor<=*a && factor<=*b) - { - if (((*a % factor) == 0) && ((*b % factor) == 0)) - { - // common factor is found - *a/=factor; - *b/=factor; - // restart - factor=2; - } - else - factor++; - } -} - -/// Multiplies original_size by new_ratio/old_ratio, but keeps result in 1-9999 range. -short Compute_dimension(short original_size, short new_ratio, short old_ratio) -{ - long amount; - amount = (long)original_size*new_ratio/old_ratio; - if (amount>9999) - return 9999; - else if (amount<1) - return 1; - else - return amount; -} - -void Button_Transform_menu(void) -{ - enum RESIZE_UNIT { - UNIT_PIXELS = 1, - UNIT_PERCENT = 2, - UNIT_RATIO = 3 - }; - - char buffer[5]; - short clicked_button; - const char * unit_label[] = { - "", - "Pixels ", - "Percent", - "Ratio "}; - short last_unit_index = -1; - short old_ratio_width; - short old_ratio_height; - short new_ratio_width; - short new_ratio_height; - short new_width=Main_image_width; - short new_height=Main_image_height; - byte need_display_size = 0; - - // Persistent data - static short unit_index = 1; // 1= Pixels, 2= Percent, 3=Ratio - static short ratio_is_locked = 1; // True if X and Y resize should go together - - T_Dropdown_button * unit_button; - T_Special_button * input_button[4]; - short *input_value[4]; - - // Set initial ratio - if (unit_index == UNIT_PERCENT) - new_ratio_width=old_ratio_width=new_ratio_height=old_ratio_height=100; - else - new_ratio_width=old_ratio_width=new_ratio_height=old_ratio_height=1; - - Open_window(215,165,"Picture transform"); - - Window_display_frame( 5, 15,205,91); - Window_display_frame( 5,110, 55,49); - Window_display_frame(64,110, 85,49); - - Window_set_normal_button(154,140, 54,14,"Cancel",0,1,KEY_ESC); // 1 - - Print_in_window( 9,114,"Mirror",MC_Dark,MC_Light); - Window_set_normal_button( 17,125, 27,14,"X\035" ,1,1,SDLK_x); // 2 - Window_set_normal_button( 17,140, 27,14,"Y\022" ,1,1,SDLK_y); // 3 - - Print_in_window( 84,114,"Rotate",MC_Dark,MC_Light); - Window_set_normal_button( 69,125, 37,14,"-90°" ,0,1,SDLK_LAST); // 4 - Window_set_normal_button(107,125, 37,14,"+90°" ,0,1,SDLK_LAST); // 5 - Window_set_normal_button( 69,140, 75,14,"180°" ,0,1,SDLK_LAST); // 6 - - Print_in_window( 87, 19,"Resize",MC_Dark,MC_Light); - Window_set_normal_button( 80, 86, 60,14,"RESIZE",1,1,SDLK_r); // 7 - Print_in_window( 51, 34,"New",MC_Dark,MC_Light); - Print_in_window( 96, 34,"Old",MC_Dark,MC_Light); - Print_in_window( 30, 44,"X:",MC_Dark,MC_Light); - Print_in_window( 30, 59,"Y:",MC_Dark,MC_Light); - Print_in_window( 80, 44,":",MC_Dark,MC_Light); - Print_in_window( 80, 59,":",MC_Dark,MC_Light); - Print_in_window( 44, 75,"Lock proportions",MC_Dark,MC_Light); - - Window_set_normal_button( 28, 72, 13,13,ratio_is_locked?"X":" ",0,1,SDLK_l);// 8 - unit_button = Window_set_dropdown_button(128,50,69,11,69,unit_label[unit_index],1,0,1,LEFT_SIDE|RIGHT_SIDE);// 9 - Window_dropdown_add_item(unit_button,UNIT_PIXELS,unit_label[UNIT_PIXELS]); - Window_dropdown_add_item(unit_button,UNIT_PERCENT,unit_label[UNIT_PERCENT]); - Window_dropdown_add_item(unit_button,UNIT_RATIO,unit_label[UNIT_RATIO]); - - input_button[0] = Window_set_input_button(45,43,4); // 10 - input_button[1] = Window_set_input_button(89,43,4); // 11 - input_button[2] = Window_set_input_button(45,58,4); // 12 - input_button[3] = Window_set_input_button(89,58,4); // 13 - - Update_window_area(0,0,Window_width, Window_height); - - Display_cursor(); - - do - { - // Display the coordinates with the right unit - if (last_unit_index != unit_index) - { - switch(unit_index) - { - case UNIT_PIXELS: - default: - input_value[0]=&new_width; - input_value[1]=&Main_image_width; // Don't worry, it's read-only - input_value[2]=&new_height; - input_value[3]=&Main_image_height; // Don't worry, it's read-only - break; - case UNIT_PERCENT: - case UNIT_RATIO: - input_value[0]=&new_ratio_width; - input_value[1]=&old_ratio_width; - input_value[2]=&new_ratio_height; - input_value[3]=&old_ratio_height; - break; - } - need_display_size=1; - last_unit_index=unit_index; - } - if (need_display_size) - { - short i; - Hide_cursor(); - for (i=0;i<4;i++) - { - // "Old" values are not editable, unless the unit is "ratio" - byte color = ((unit_index!=UNIT_RATIO) && (i==1 || i==3)) ? MC_Dark : MC_Black; - Num2str(*(input_value[i]),buffer,4); - Print_in_window_limited(input_button[i]->Pos_X+2,input_button[i]->Pos_Y+2,buffer,input_button[i]->Width/8,color,MC_Light); - } - Display_cursor(); - need_display_size=0; - } - - clicked_button=Window_clicked_button(); - - // Contextual help - if (Is_shortcut(Key,0x100+BUTTON_HELP)) - { - Key=0; - Window_help(BUTTON_ADJUST, "PICTURE TRANSFORM"); - } - else switch(clicked_button) - { - case 9: // Unit - switch(Window_attribute2) - { - case UNIT_PIXELS: - // Do nothing, pixel size was already computed. - break; - case UNIT_PERCENT: - if (unit_index == UNIT_RATIO) - { - // Approximate from current ratio - new_ratio_width = Compute_dimension(new_ratio_width,100,old_ratio_width); - new_ratio_height = Compute_dimension(new_ratio_height,100,old_ratio_height); - old_ratio_width = 100; - old_ratio_height = 100; - // Update pixel dimensions, to match percentage exactly - new_width=Compute_dimension(Main_image_width, new_ratio_width, old_ratio_width); - new_height=Compute_dimension(Main_image_height, new_ratio_height, old_ratio_height); - } - else // unit_index == UNIT_PIXELS - { - // Approximate from current pixel size - new_ratio_width = new_width*100/Main_image_width; - new_ratio_height = new_height*100/Main_image_height; - old_ratio_width = 100; - old_ratio_height = 100; - } - break; - case UNIT_RATIO: - if (unit_index == UNIT_PERCENT) - { - // Compute simplest ratio from current % - Factorize(&new_ratio_width, &old_ratio_width); - Factorize(&new_ratio_height, &old_ratio_height); - } - else // unit_index == UNIT_PIXELS - { - // Compute simplest ratio from current pixel size - new_ratio_width = new_width; - new_ratio_height = new_height; - old_ratio_width = Main_image_width; - old_ratio_height = Main_image_height; - Factorize(&new_ratio_width, &old_ratio_width); - Factorize(&new_ratio_height, &old_ratio_height); - } - break; - } - - unit_index = Window_attribute2; - break; - - case 8: // Lock proportions - ratio_is_locked = ! ratio_is_locked; - Hide_cursor(); - Print_in_window(31,75,(ratio_is_locked)?"X":" ",MC_Black,MC_Light); - Display_cursor(); - break; - - case 11: // input old width - case 13: // input old height - // "Old" values are not editable, unless the unit is "ratio" - if (unit_index!=UNIT_RATIO) - break; - case 10: // input new width - case 12: // input new height - Num2str(*( input_value[clicked_button-10]),buffer,4); - Hide_cursor(); - if (Readline(input_button[clicked_button-10]->Pos_X+2, - input_button[clicked_button-10]->Pos_Y+2, - buffer, - 4, - 1)) - { - // Accept entered value - *(input_value[clicked_button-10])=atoi(buffer); - // 0 is not acceptable size - if (*(input_value[clicked_button-10])==0) - { - *(input_value[clicked_button-10])=1; - } - // Adapt the other coordinate if X and Y are locked - if (ratio_is_locked) - { - if (clicked_button == 10 || clicked_button == 11 ) - { - // Get Y value because X changed - if (unit_index == UNIT_PIXELS) - { - new_height=Compute_dimension(Main_image_height, new_width, Main_image_width); - } - else - { - // Copy the whole ratio - new_ratio_height=new_ratio_width; - old_ratio_height=old_ratio_width; - } - } - else // (clicked_button == 12 || clicked_button == 13) - { - // Get X value because Y changed - if (unit_index == UNIT_PIXELS) - { - new_width=Compute_dimension(Main_image_width, new_height, Main_image_height); - } - else - { - // Copy the whole ratio - new_ratio_width=new_ratio_height; - old_ratio_width=old_ratio_height; - } - } - } - - // Re-compute ratio from size in pixels - if (unit_index == UNIT_PIXELS) - { - //new_width=(long)Main_image_width*new_ratio_width/old_ratio_width; - //new_height=(long)Main_image_height*new_ratio_height/old_ratio_height; - } - else // Re-compute size in pixels from ratio - { - new_width=Compute_dimension(Main_image_width,new_ratio_width,old_ratio_width); - new_height=Compute_dimension(Main_image_height,new_ratio_height,old_ratio_height); - } - need_display_size=1; - } - Display_cursor(); - break; - } - } - while (clicked_button<=0 || clicked_button>=8); - - Close_window(); - - // The Scroll operation uses the same button as transformation menu. - if (Current_operation != OPERATION_SCROLL) - Unselect_button(BUTTON_ADJUST); - - if (clicked_button != 1) // 1 is Cancel - { - short old_width; - short old_height; - - // Determine new image dimensions - switch (clicked_button) - { - case 7 : // Resize - // Keep new_width and new_height as entered. - break; - case 2 : // Flip X - case 3 : // Flip Y - case 6 : // 180° Rotation - new_width=Main_image_width; - new_height=Main_image_height; - break; - - case 4 : // -90° Rotation - case 5 : // +90° Rotation - - new_width=Main_image_height; - new_height=Main_image_width; - break; - } - // Memorize the current dimensions - old_width=Main_image_width; - old_height=Main_image_height; - - // Allocate a new page - if (Backup_with_new_dimensions(1,new_width,new_height)) - { - // The new image is allocated, the new dimensions are already updated. - - Main_image_is_modified=1; - - // Process the transformation: - switch(clicked_button) - { - case 2 : // Flip X - memcpy(Main_screen,Screen_backup,Main_image_width*Main_image_height); - Flip_X_lowlevel(Main_screen, Main_image_width, Main_image_height); - break; - case 3 : // Flip Y - memcpy(Main_screen,Screen_backup,Main_image_width*Main_image_height); - Flip_Y_lowlevel(Main_screen, Main_image_width, Main_image_height); - break; - case 4 : // -90° Rotation - Rotate_270_deg_lowlevel(Screen_backup, Main_screen, old_width, old_height); - break; - case 5 : // +90° Rotation - Rotate_90_deg_lowlevel(Screen_backup, Main_screen, old_width, old_height); - break; - case 6 : // 180° Rotation - memcpy(Main_screen,Screen_backup,Main_image_width*Main_image_height); - Rotate_180_deg_lowlevel(Main_screen, Main_image_width, Main_image_height); - break; - case 7 : // Resize - Rescale(Screen_backup, old_width, old_height, Main_screen, Main_image_width, Main_image_height, 0, 0); - break; - } - Display_all_screen(); - } - else - { - Display_cursor(); - Message_out_of_memory(); - Hide_cursor(); - } - } - Display_cursor(); -} +/* Grafx2 - The Ultimate 256-color bitmap paint program + + Copyright 2009 Yves Rizoud + Copyright 2009 Adrien Destugues + Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) + + Grafx2 is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 + of the License. + + Grafx2 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grafx2; if not, see +*/ +#include +#include + +#include "global.h" +#include "struct.h" +#include "transform.h" +#include "engine.h" +#include "sdlscreen.h" +#include "windows.h" +#include "input.h" +#include "help.h" +#include "misc.h" // Num2str +#include "readline.h" +#include "buttons.h" // Message_out_of_memory() +#include "pages.h" // Backup_with_new_dimensions() + +/// Reduces a fraction A/B to its smallest representation. ie (40,60) becomes (2/3) +void Factorize(short *a, short *b) +{ + // Method: brute-force. + short factor; + + factor=2; + while (factor<=*a && factor<=*b) + { + if (((*a % factor) == 0) && ((*b % factor) == 0)) + { + // common factor is found + *a/=factor; + *b/=factor; + // restart + factor=2; + } + else + factor++; + } +} + +/// Multiplies original_size by new_ratio/old_ratio, but keeps result in 1-9999 range. +short Compute_dimension(short original_size, short new_ratio, short old_ratio) +{ + long amount; + amount = (long)original_size*new_ratio/old_ratio; + if (amount>9999) + return 9999; + else if (amount<1) + return 1; + else + return amount; +} + +void Button_Transform_menu(void) +{ + enum RESIZE_UNIT { + UNIT_PIXELS = 1, + UNIT_PERCENT = 2, + UNIT_RATIO = 3 + }; + + char buffer[5]; + short clicked_button; + const char * unit_label[] = { + "", + "Pixels ", + "Percent", + "Ratio "}; + short last_unit_index = -1; + short old_ratio_width; + short old_ratio_height; + short new_ratio_width; + short new_ratio_height; + short new_width=Main_image_width; + short new_height=Main_image_height; + byte need_display_size = 0; + + // Persistent data + static short unit_index = 1; // 1= Pixels, 2= Percent, 3=Ratio + static short ratio_is_locked = 1; // True if X and Y resize should go together + + T_Dropdown_button * unit_button; + T_Special_button * input_button[4]; + short *input_value[4]; + + // Set initial ratio + if (unit_index == UNIT_PERCENT) + new_ratio_width=old_ratio_width=new_ratio_height=old_ratio_height=100; + else + new_ratio_width=old_ratio_width=new_ratio_height=old_ratio_height=1; + + Open_window(215,165,"Picture transform"); + + Window_display_frame( 5, 15,205,91); + Window_display_frame( 5,110, 55,49); + Window_display_frame(64,110, 85,49); + + Window_set_normal_button(154,140, 54,14,"Cancel",0,1,KEY_ESC); // 1 + + Print_in_window( 9,114,"Mirror",MC_Dark,MC_Light); + Window_set_normal_button( 17,125, 27,14,"X\035" ,1,1,SDLK_x); // 2 + Window_set_normal_button( 17,140, 27,14,"Y\022" ,1,1,SDLK_y); // 3 + + Print_in_window( 84,114,"Rotate",MC_Dark,MC_Light); + Window_set_normal_button( 69,125, 37,14,"-90°" ,0,1,SDLK_LAST); // 4 + Window_set_normal_button(107,125, 37,14,"+90°" ,0,1,SDLK_LAST); // 5 + Window_set_normal_button( 69,140, 75,14,"180°" ,0,1,SDLK_LAST); // 6 + + Print_in_window( 87, 19,"Resize",MC_Dark,MC_Light); + Window_set_normal_button( 80, 86, 60,14,"RESIZE",1,1,SDLK_r); // 7 + Print_in_window( 51, 34,"New",MC_Dark,MC_Light); + Print_in_window( 96, 34,"Old",MC_Dark,MC_Light); + Print_in_window( 30, 44,"X:",MC_Dark,MC_Light); + Print_in_window( 30, 59,"Y:",MC_Dark,MC_Light); + Print_in_window( 80, 44,":",MC_Dark,MC_Light); + Print_in_window( 80, 59,":",MC_Dark,MC_Light); + Print_in_window( 44, 75,"Lock proportions",MC_Dark,MC_Light); + + Window_set_normal_button( 28, 72, 13,13,ratio_is_locked?"X":" ",0,1,SDLK_l);// 8 + unit_button = Window_set_dropdown_button(128,50,69,11,69,unit_label[unit_index],1,0,1,LEFT_SIDE|RIGHT_SIDE);// 9 + Window_dropdown_add_item(unit_button,UNIT_PIXELS,unit_label[UNIT_PIXELS]); + Window_dropdown_add_item(unit_button,UNIT_PERCENT,unit_label[UNIT_PERCENT]); + Window_dropdown_add_item(unit_button,UNIT_RATIO,unit_label[UNIT_RATIO]); + + input_button[0] = Window_set_input_button(45,43,4); // 10 + input_button[1] = Window_set_input_button(89,43,4); // 11 + input_button[2] = Window_set_input_button(45,58,4); // 12 + input_button[3] = Window_set_input_button(89,58,4); // 13 + + Update_window_area(0,0,Window_width, Window_height); + + Display_cursor(); + + do + { + // Display the coordinates with the right unit + if (last_unit_index != unit_index) + { + switch(unit_index) + { + case UNIT_PIXELS: + default: + input_value[0]=&new_width; + input_value[1]=&Main_image_width; // Don't worry, it's read-only + input_value[2]=&new_height; + input_value[3]=&Main_image_height; // Don't worry, it's read-only + break; + case UNIT_PERCENT: + case UNIT_RATIO: + input_value[0]=&new_ratio_width; + input_value[1]=&old_ratio_width; + input_value[2]=&new_ratio_height; + input_value[3]=&old_ratio_height; + break; + } + need_display_size=1; + last_unit_index=unit_index; + } + if (need_display_size) + { + short i; + Hide_cursor(); + for (i=0;i<4;i++) + { + // "Old" values are not editable, unless the unit is "ratio" + byte color = ((unit_index!=UNIT_RATIO) && (i==1 || i==3)) ? MC_Dark : MC_Black; + Num2str(*(input_value[i]),buffer,4); + Print_in_window_limited(input_button[i]->Pos_X+2,input_button[i]->Pos_Y+2,buffer,input_button[i]->Width/8,color,MC_Light); + } + Display_cursor(); + need_display_size=0; + } + + clicked_button=Window_clicked_button(); + + // Contextual help + if (Is_shortcut(Key,0x100+BUTTON_HELP)) + { + Key=0; + Window_help(BUTTON_ADJUST, "PICTURE TRANSFORM"); + } + else if (Is_shortcut(Key,0x200+BUTTON_ADJUST)) + clicked_button=1; + + else switch(clicked_button) + { + case 9: // Unit + switch(Window_attribute2) + { + case UNIT_PIXELS: + // Do nothing, pixel size was already computed. + break; + case UNIT_PERCENT: + if (unit_index == UNIT_RATIO) + { + // Approximate from current ratio + new_ratio_width = Compute_dimension(new_ratio_width,100,old_ratio_width); + new_ratio_height = Compute_dimension(new_ratio_height,100,old_ratio_height); + old_ratio_width = 100; + old_ratio_height = 100; + // Update pixel dimensions, to match percentage exactly + new_width=Compute_dimension(Main_image_width, new_ratio_width, old_ratio_width); + new_height=Compute_dimension(Main_image_height, new_ratio_height, old_ratio_height); + } + else // unit_index == UNIT_PIXELS + { + // Approximate from current pixel size + new_ratio_width = new_width*100/Main_image_width; + new_ratio_height = new_height*100/Main_image_height; + old_ratio_width = 100; + old_ratio_height = 100; + } + break; + case UNIT_RATIO: + if (unit_index == UNIT_PERCENT) + { + // Compute simplest ratio from current % + Factorize(&new_ratio_width, &old_ratio_width); + Factorize(&new_ratio_height, &old_ratio_height); + } + else // unit_index == UNIT_PIXELS + { + // Compute simplest ratio from current pixel size + new_ratio_width = new_width; + new_ratio_height = new_height; + old_ratio_width = Main_image_width; + old_ratio_height = Main_image_height; + Factorize(&new_ratio_width, &old_ratio_width); + Factorize(&new_ratio_height, &old_ratio_height); + } + break; + } + + unit_index = Window_attribute2; + break; + + case 8: // Lock proportions + ratio_is_locked = ! ratio_is_locked; + Hide_cursor(); + Print_in_window(31,75,(ratio_is_locked)?"X":" ",MC_Black,MC_Light); + Display_cursor(); + break; + + case 11: // input old width + case 13: // input old height + // "Old" values are not editable, unless the unit is "ratio" + if (unit_index!=UNIT_RATIO) + break; + case 10: // input new width + case 12: // input new height + Num2str(*( input_value[clicked_button-10]),buffer,4); + Hide_cursor(); + if (Readline(input_button[clicked_button-10]->Pos_X+2, + input_button[clicked_button-10]->Pos_Y+2, + buffer, + 4, + 1)) + { + // Accept entered value + *(input_value[clicked_button-10])=atoi(buffer); + // 0 is not acceptable size + if (*(input_value[clicked_button-10])==0) + { + *(input_value[clicked_button-10])=1; + } + // Adapt the other coordinate if X and Y are locked + if (ratio_is_locked) + { + if (clicked_button == 10 || clicked_button == 11 ) + { + // Get Y value because X changed + if (unit_index == UNIT_PIXELS) + { + new_height=Compute_dimension(Main_image_height, new_width, Main_image_width); + } + else + { + // Copy the whole ratio + new_ratio_height=new_ratio_width; + old_ratio_height=old_ratio_width; + } + } + else // (clicked_button == 12 || clicked_button == 13) + { + // Get X value because Y changed + if (unit_index == UNIT_PIXELS) + { + new_width=Compute_dimension(Main_image_width, new_height, Main_image_height); + } + else + { + // Copy the whole ratio + new_ratio_width=new_ratio_height; + old_ratio_width=old_ratio_height; + } + } + } + + // Re-compute ratio from size in pixels + if (unit_index == UNIT_PIXELS) + { + //new_width=(long)Main_image_width*new_ratio_width/old_ratio_width; + //new_height=(long)Main_image_height*new_ratio_height/old_ratio_height; + } + else // Re-compute size in pixels from ratio + { + new_width=Compute_dimension(Main_image_width,new_ratio_width,old_ratio_width); + new_height=Compute_dimension(Main_image_height,new_ratio_height,old_ratio_height); + } + need_display_size=1; + } + Display_cursor(); + break; + } + } + while (clicked_button<=0 || clicked_button>=8); + + Close_window(); + + // The Scroll operation uses the same button as transformation menu. + if (Current_operation != OPERATION_SCROLL) + Unselect_button(BUTTON_ADJUST); + + if (clicked_button != 1) // 1 is Cancel + { + short old_width; + short old_height; + + // Determine new image dimensions + switch (clicked_button) + { + case 7 : // Resize + // Keep new_width and new_height as entered. + break; + case 2 : // Flip X + case 3 : // Flip Y + case 6 : // 180° Rotation + new_width=Main_image_width; + new_height=Main_image_height; + break; + + case 4 : // -90° Rotation + case 5 : // +90° Rotation + + new_width=Main_image_height; + new_height=Main_image_width; + break; + } + // Memorize the current dimensions + old_width=Main_image_width; + old_height=Main_image_height; + + // Allocate a new page + if (Backup_with_new_dimensions(1,new_width,new_height)) + { + // The new image is allocated, the new dimensions are already updated. + + Main_image_is_modified=1; + + // Process the transformation: + switch(clicked_button) + { + case 2 : // Flip X + memcpy(Main_screen,Screen_backup,Main_image_width*Main_image_height); + Flip_X_lowlevel(Main_screen, Main_image_width, Main_image_height); + break; + case 3 : // Flip Y + memcpy(Main_screen,Screen_backup,Main_image_width*Main_image_height); + Flip_Y_lowlevel(Main_screen, Main_image_width, Main_image_height); + break; + case 4 : // -90° Rotation + Rotate_270_deg_lowlevel(Screen_backup, Main_screen, old_width, old_height); + break; + case 5 : // +90° Rotation + Rotate_90_deg_lowlevel(Screen_backup, Main_screen, old_width, old_height); + break; + case 6 : // 180° Rotation + memcpy(Main_screen,Screen_backup,Main_image_width*Main_image_height); + Rotate_180_deg_lowlevel(Main_screen, Main_image_width, Main_image_height); + break; + case 7 : // Resize + Rescale(Screen_backup, old_width, old_height, Main_screen, Main_image_width, Main_image_height, 0, 0); + break; + } + Display_all_screen(); + } + else + { + Display_cursor(); + Message_out_of_memory(); + Hide_cursor(); + } + } + Display_cursor(); +} diff --git a/transform.h b/transform.h index 38b91db6..899c4443 100644 --- a/transform.h +++ b/transform.h @@ -1,27 +1,27 @@ -/* Grafx2 - The Ultimate 256-color bitmap paint program - - Copyright 2009 Yves Rizoud - Copyright 2009 Adrien Destugues - Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) - - Grafx2 is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; version 2 - of the License. - - Grafx2 is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Grafx2; if not, see -*/ - -////////////////////////////////////////////////////////////////////////////// -///@file transform.h -/// Screen and functions for picture transform. -////////////////////////////////////////////////////////////////////////////// - -/// Opens and handles the Picture transform screen. -void Button_Transform_menu(void); +/* Grafx2 - The Ultimate 256-color bitmap paint program + + Copyright 2009 Yves Rizoud + Copyright 2009 Adrien Destugues + Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud) + + Grafx2 is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 + of the License. + + Grafx2 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grafx2; if not, see +*/ + +////////////////////////////////////////////////////////////////////////////// +///@file transform.h +/// Screen and functions for picture transform. +////////////////////////////////////////////////////////////////////////////// + +/// Opens and handles the Picture transform screen. +void Button_Transform_menu(void); diff --git a/windows.c b/windows.c index 8e36219c..93d52f02 100644 --- a/windows.c +++ b/windows.c @@ -32,6 +32,7 @@ #include "misc.h" #include "sdlscreen.h" #include "errors.h" +#include "input.h" // L'encapsulation tente une percée...ou un dernier combat. @@ -409,8 +410,7 @@ int Pick_color_in_palette() return color; } - // -- Afficher tout le menu -- - +/// Display the whole menu void Display_menu(void) { word x_pos; @@ -420,17 +420,17 @@ void Display_menu(void) if (Menu_is_visible) { - // Affichage du sprite du menu + // display menu sprite for (y_pos=0;y_posMenu_block[y_pos][x_pos]); + // Grey area for filename below palette Block(MENU_WIDTH*Menu_factor_X,Menu_status_Y-Menu_factor_Y,Screen_width-(MENU_WIDTH*Menu_factor_X),9*Menu_factor_Y,MC_Light); - // Affichage de la palette + // Display palette Display_menu_palette(); - // Affichage des couleurs de travail + // Display selected colors Display_foreback(); @@ -439,12 +439,14 @@ void Display_menu(void) if ((Mouse_Y=Main_X_zoom) )) { - // Dans ces deux cas, on met dans la barre les XY courant, même s'il y a des chances que ça soit recouvert si la souris est sur un bouton (trop chiant à vérifier) + // Prepare display of XY coordinates even if in some cases they will be + // erased with some other text if ( (Current_operation!=OPERATION_COLORPICK) && (Current_operation!=OPERATION_REPLACE) ) Print_in_menu("X: Y: ",0); else { + // The colorpicker display the color id between the parentheses Print_in_menu("X: Y: ( )",0); Num2str(Colorpicker_color,str,3); Print_in_menu(str,20); @@ -454,7 +456,8 @@ void Display_menu(void) } Print_filename(); } - Update_rect(0,Menu_Y,Screen_width,MENU_HEIGHT*Menu_factor_Y); // on met toute la largur à jour, ça inclut la palette et la zone d'état avec le nom du fichier + // Now update the area: menu height and whole screen width (including palette) + Update_rect(0,Menu_Y,Screen_width,MENU_HEIGHT*Menu_factor_Y); } } @@ -834,7 +837,7 @@ byte Confirmation_box(char * message) -//---- Fenêtre avertissant de quelque chose et attendant un click sur OK ----- +/// Window that show a warning message and wait for a click on the OK button void Warning_message(char * message) { short clicked_button; @@ -860,6 +863,47 @@ void Warning_message(char * message) Display_cursor(); } +/// Window that shows a big message, and waits for a click on OK +void Verbose_error_message(char * message) +{ + short clicked_button; + int line; + int i; + char buffer[36]; // 35 characters + \0 + + Open_window(300,160,"Error!"); + + // Word-wrap the message + for (line=0; line < 10; line++) + { + for (i=0;i<35 && *message!='\0';i++) + { + if (*message == '\n') + { + message++; + break; + } + buffer[i]=*message; + message++; + } + buffer[i]='\0'; + Print_in_window(10,20+line*8,buffer,MC_Black,MC_Light); + if (*message=='\0') + break; + } + + Window_set_normal_button(300/2-20,160-23,40,14,"OK",1,1,SDLK_RETURN); // 1 + Update_window_area(0,0,Window_width,Window_height); + Display_cursor(); + + do + clicked_button=Window_clicked_button(); + while ((clicked_button<=0) && (Key!=KEY_ESC) && (Key!=SDLK_o)); + Key=0; + + Close_window(); + Display_cursor(); +} // -- Redessiner le sprite d'un bouton dans le menu -- @@ -883,9 +927,9 @@ void Display_sprite_in_menu(int btn_number,int sprite_number) for (y_pos=0;y_posMenu_sprite[sprite_number][y_pos][x_pos]; Pixel_in_menu(menu_x_pos+x_pos,menu_y_pos+y_pos,color); - GFX_menu_block[menu_y_pos+y_pos][menu_x_pos+x_pos]=color; + Gfx->Menu_block[menu_y_pos+y_pos][menu_x_pos+x_pos]=color; } Update_rect(Menu_factor_X*(Buttons_Pool[btn_number].X_offset+1), (Buttons_Pool[btn_number].Y_offset+1)*Menu_factor_Y+Menu_Y, @@ -909,9 +953,9 @@ void Display_paintbrush_in_menu(void) for (menu_y_pos=2,y_pos=0;y_posMenu_sprite[4][y_pos][x_pos]; Pixel_in_menu(menu_x_pos,menu_y_pos,color); - GFX_menu_block[menu_y_pos][menu_x_pos]=color; + Gfx->Menu_block[menu_y_pos][menu_x_pos]=color; } break; default : // Pinceau @@ -920,7 +964,7 @@ void Display_paintbrush_in_menu(void) for (menu_x_pos=1,x_pos=0;x_posMenu_block[menu_y_pos][menu_x_pos]=MC_Light; } // On affiche le nouveau menu_start_x=8-Paintbrush_offset_X; @@ -946,7 +990,7 @@ void Display_paintbrush_in_menu(void) { color=(Paintbrush_sprite[(y_pos*MAX_PAINTBRUSH_SIZE)+x_pos])?MC_Black:MC_Light; Pixel_in_menu(menu_x_pos,menu_y_pos,color); - GFX_menu_block[menu_y_pos][menu_x_pos]=color; + Gfx->Menu_block[menu_y_pos][menu_x_pos]=color; } } Update_rect(0,Menu_Y,MENU_SPRITE_WIDTH*Menu_factor_X+3,MENU_SPRITE_HEIGHT*Menu_factor_Y+3); @@ -973,18 +1017,18 @@ void Display_paintbrush_in_window(word x,word y,int number) if (y_size<1) y_size=1; - origin_x = (x + 8)*Menu_factor_X - (Preset_paintbrush_offset_X[number])*x_size+Window_pos_X; - origin_y = (y + 8)*Menu_factor_Y - (Preset_paintbrush_offset_Y[number])*y_size+Window_pos_Y; + origin_x = (x + 8)*Menu_factor_X - (Gfx->Preset_paintbrush_offset_X[number])*x_size+Window_pos_X; + origin_y = (y + 8)*Menu_factor_Y - (Gfx->Preset_paintbrush_offset_Y[number])*y_size+Window_pos_Y; - for (window_y_pos=0,y_pos=0; y_posPreset_paintbrush_height[number]; window_y_pos++,y_pos++) + for (window_x_pos=0,x_pos=0; x_posPreset_paintbrush_width[number]; window_x_pos++,x_pos++) + Block(origin_x+window_x_pos*x_size,origin_y+window_y_pos*y_size,x_size,y_size,(Gfx->Paintbrush_sprite[number][y_pos][x_pos])?MC_Black:MC_Light); // On n'utilise pas Pixel_in_window() car on ne dessine pas // forcément avec la même taille de pixel. Update_rect( ToWinX(origin_x), ToWinY(origin_y), - ToWinL(Preset_paintbrush_width[number]), - ToWinH(Preset_paintbrush_height[number]) + ToWinL(Gfx->Preset_paintbrush_width[number]), + ToWinH(Gfx->Preset_paintbrush_height[number]) ); } @@ -1041,7 +1085,7 @@ void Window_display_icon_sprite(word x_pos,word y_pos,byte type) for (j=0; jIcon_sprite[type][j][i]); Update_rect(ToWinX(x_pos),ToWinY(y_pos),ToWinL(ICON_SPRITE_WIDTH),ToWinH(ICON_SPRITE_HEIGHT)); } @@ -1234,6 +1278,46 @@ void Compute_paintbrush_coordinates(void) Paintbrush_X=(((Paintbrush_X+(Snap_width>>1)-Snap_offset_X)/Snap_width)*Snap_width)+Snap_offset_X; Paintbrush_Y=(((Paintbrush_Y+(Snap_height>>1)-Snap_offset_Y)/Snap_height)*Snap_height)+Snap_offset_Y; } + + // Handling the snap axis mode, when shift is pressed. + switch (Current_operation) + { + // Operations that don't implement it + case OPERATION_LINE: + Snap_axis=0; + break; + // Operations that implement it + default: + if (Snap_axis==0 && (SDL_GetModState() & KMOD_SHIFT)) + { + // Start "Snap axis" mode + Snap_axis=1; + Snap_axis_origin_X=Paintbrush_X; + Snap_axis_origin_Y=Paintbrush_Y; + } + } + + if (Snap_axis==1) + { + // Cursor moved + if (Paintbrush_X != Snap_axis_origin_X || Paintbrush_Y != Snap_axis_origin_Y) + { + if ((Paintbrush_X-Snap_axis_origin_X)*(Paintbrush_X-Snap_axis_origin_X) > + (Paintbrush_Y-Snap_axis_origin_Y)*(Paintbrush_Y-Snap_axis_origin_Y)) + // Displacement was bigger on X axis: lock Y + Snap_axis=2; + else + Snap_axis=3; + } + } + if (Snap_axis==2) + { + Paintbrush_Y = Snap_axis_origin_Y; + } + else if (Snap_axis==3) + { + Paintbrush_X = Snap_axis_origin_X; + } } @@ -1522,7 +1606,7 @@ void Display_cursor(void) short end_y; short x_pos; short y_pos; - short counter_x; + short counter_x = 0; short counter_y; int temp; byte color; @@ -1567,21 +1651,23 @@ void Display_cursor(void) else { temp=(Config.Cursor)?CURSOR_SHAPE_THIN_TARGET:CURSOR_SHAPE_TARGET; - start_x=Mouse_X-Cursor_offset_X[temp]; - start_y=Mouse_Y-Cursor_offset_Y[temp]; + start_x=Mouse_X-Gfx->Cursor_offset_X[temp]; + start_y=Mouse_Y-Gfx->Cursor_offset_Y[temp]; - for (x_pos=start_x,counter_x=0;counter_x<15 && x_pos < Screen_width;x_pos++,counter_x++) - { - if( x_pos < 0 ) continue; - for (y_pos=start_y,counter_y=0;counter_y<15 && y_pos < Screen_height;y_pos++,counter_y++) - { - if( y_pos < 0 || y_pos >= Screen_height) continue; - color=GFX_cursor_sprite[temp][counter_y][counter_x]; - CURSOR_BACKGROUND[counter_y][counter_x]=Read_pixel(x_pos,y_pos); - if (color!=MC_Trans) - Pixel(x_pos,y_pos,color); + for (y_pos=start_y,counter_y=0; counter_y<15 && y_pos < Screen_height; + y_pos++,counter_y++) + { + if( y_pos < 0 ) continue; + for (x_pos=start_x,counter_x=0; + counter_x<15 && x_pos < Screen_width; x_pos++,counter_x++) + { + if( x_pos < 0 ) continue; + color=Gfx->Cursor_sprite[temp][counter_y][counter_x]; + Cursor_background[counter_y][counter_x]=Read_pixel(x_pos,y_pos); + if (color!=MC_Trans) + Pixel(x_pos,y_pos,color); } - } + } Update_rect(Max(start_x,0),Max(start_y,0),counter_x,counter_y); } @@ -1634,25 +1720,24 @@ void Display_cursor(void) } else { - DEBUG("B",0); temp=(Config.Cursor)?CURSOR_SHAPE_THIN_COLORPICKER:CURSOR_SHAPE_COLORPICKER; - start_x=Mouse_X-Cursor_offset_X[temp]; - start_y=Mouse_Y-Cursor_offset_Y[temp]; + start_x=Mouse_X-Gfx->Cursor_offset_X[temp]; + start_y=Mouse_Y-Gfx->Cursor_offset_Y[temp]; - for (x_pos=start_x,counter_x=0;counter_x<15;x_pos++,counter_x++) + for (y_pos=start_y,counter_y=0;counter_y<15;y_pos++,counter_y++) { + if(y_pos<0) continue; + if(y_pos>=Screen_height) break; + for (x_pos=start_x,counter_x=0;counter_x<15;x_pos++,counter_x++) + { if(x_pos<0) continue; if(x_pos>=Screen_width) break; - for (y_pos=start_y,counter_y=0;counter_y<15;y_pos++,counter_y++) - { - if(y_pos<0) continue; - if(y_pos>=Screen_height) break; - color=GFX_cursor_sprite[temp][counter_y][counter_x]; - // On sauvegarde dans CURSOR_BACKGROUND pour restaurer plus tard - CURSOR_BACKGROUND[counter_y][counter_x]=Read_pixel(x_pos,y_pos); - if (color!=MC_Trans) - Pixel(x_pos,y_pos,color); - } + color=Gfx->Cursor_sprite[temp][counter_y][counter_x]; + // On sauvegarde dans Cursor_background pour restaurer plus tard + Cursor_background[counter_y][counter_x]=Read_pixel(x_pos,y_pos); + if (color!=MC_Trans) + Pixel(x_pos,y_pos,color); + } } Update_rect(Max(start_x,0),Max(start_y,0),counter_x,counter_y); } @@ -1666,20 +1751,20 @@ void Display_cursor(void) case CURSOR_SHAPE_ARROW : case CURSOR_SHAPE_HOURGLASS : - start_x=Mouse_X-Cursor_offset_X[shape]; - start_y=Mouse_Y-Cursor_offset_Y[shape]; - for (x_pos=start_x,counter_x=0;counter_x<15;x_pos++,counter_x++) + start_x=Mouse_X-Gfx->Cursor_offset_X[shape]; + start_y=Mouse_Y-Gfx->Cursor_offset_Y[shape]; + for (y_pos=start_y,counter_y=0;counter_y<15;y_pos++,counter_y++) { - if(x_pos<0) continue; - if(x_pos>=Screen_width) break; - for (y_pos=start_y,counter_y=0;counter_y<15;y_pos++,counter_y++) - { - if(y_pos<0) continue; - if(y_pos>=Screen_height) break; - color=GFX_cursor_sprite[shape][counter_y][counter_x]; - // On sauvegarde dans CURSOR_BACKGROUND pour restaurer plus tard - CURSOR_BACKGROUND[counter_y][counter_x]=Read_pixel(x_pos,y_pos); - if (color!=MC_Trans) + if(y_pos<0) continue; + if(y_pos>=Screen_height) break; + for (x_pos=start_x,counter_x=0;counter_x<15;x_pos++,counter_x++) + { + if(x_pos<0) continue; + if(x_pos>=Screen_width) break; + color=Gfx->Cursor_sprite[shape][counter_y][counter_x]; + // On sauvegarde dans Cursor_background pour restaurer plus tard + Cursor_background[counter_y][counter_x]=Read_pixel(x_pos,y_pos); + if (color!=MC_Trans) Pixel(x_pos,y_pos,color); } } @@ -1826,14 +1911,11 @@ void Hide_cursor(void) int start_y; short end_x; short end_y; - int x_pos; + int x_pos = 0; int y_pos; - short counter_x; + short counter_x = 0; short counter_y; - //short end_counter_x; // Position X ou s'arrête l'affichage de la brosse/pinceau - //short end_counter_y; // Position Y ou s'arrête l'affichage de la brosse/pinceau int temp; - //byte color; float cos_a,sin_a; short x1,y1,x2,y2,x3,y3,x4,y4; @@ -1873,17 +1955,18 @@ void Hide_cursor(void) else { temp=(Config.Cursor)?CURSOR_SHAPE_THIN_TARGET:CURSOR_SHAPE_TARGET; - start_x=Mouse_X-Cursor_offset_X[temp]; - start_y=Mouse_Y-Cursor_offset_Y[temp]; + start_x=Mouse_X-Gfx->Cursor_offset_X[temp]; + start_y=Mouse_Y-Gfx->Cursor_offset_Y[temp]; for (y_pos=start_y,counter_y=0;counter_y<15;y_pos++,counter_y++) { + if(y_pos < 0) continue; if(y_pos>=Screen_height) break; for (x_pos=start_x,counter_x=0;counter_x<15;x_pos++,counter_x++) { - if ( (x_pos<0) || (y_pos < 0)) continue; + if(x_pos < 0) continue; else if (x_pos>=Screen_width) break; - Pixel(x_pos,y_pos,CURSOR_BACKGROUND[counter_y][counter_x]); + Pixel(x_pos,y_pos,Cursor_background[counter_y][counter_x]); } } @@ -1941,21 +2024,21 @@ void Hide_cursor(void) else { temp=(Config.Cursor)?CURSOR_SHAPE_THIN_COLORPICKER:CURSOR_SHAPE_COLORPICKER; - start_x=Mouse_X-Cursor_offset_X[temp]; - start_y=Mouse_Y-Cursor_offset_Y[temp]; + start_x=Mouse_X-Gfx->Cursor_offset_X[temp]; + start_y=Mouse_Y-Gfx->Cursor_offset_Y[temp]; - for (x_pos=start_x,counter_x=0;counter_x<15;x_pos++,counter_x++) + for (y_pos=start_y,counter_y=0;counter_y<15;y_pos++,counter_y++) { + if(y_pos<0) continue; + if(y_pos>=Screen_height) break; + for (x_pos=start_x,counter_x=0;counter_x<15;x_pos++,counter_x++) + { if(x_pos<0) continue; if(x_pos>=Screen_width) break; - for (y_pos=start_y,counter_y=0;counter_y<15;y_pos++,counter_y++) - { - if(y_pos<0) continue; - if(y_pos>=Screen_height) break; - Pixel(x_pos,y_pos,CURSOR_BACKGROUND[counter_y][counter_x]); - } + Pixel(x_pos,y_pos,Cursor_background[counter_y][counter_x]); } - Update_rect(Max(start_x,0),Max(start_y,0),counter_x,counter_y); + } + Update_rect(Max(start_x,0),Max(start_y,0),counter_x,counter_y); } } if (!Paintbrush_hidden) @@ -1969,18 +2052,18 @@ void Hide_cursor(void) case CURSOR_SHAPE_ARROW : case CURSOR_SHAPE_HOURGLASS : - start_x=Mouse_X-Cursor_offset_X[shape]; - start_y=Mouse_Y-Cursor_offset_Y[shape]; + start_x=Mouse_X-Gfx->Cursor_offset_X[shape]; + start_y=Mouse_Y-Gfx->Cursor_offset_Y[shape]; - for (x_pos=start_x,counter_x=0;counter_x<15;x_pos++,counter_x++) + for (y_pos=start_y,counter_y=0;counter_y<15;y_pos++,counter_y++) { - if(x_pos<0) continue; - if(x_pos>=Screen_width) break; - for (y_pos=start_y,counter_y=0;counter_y<15;y_pos++,counter_y++) - { - if(y_pos<0) continue; - if(y_pos>=Screen_height) break; - Pixel(x_pos,y_pos,CURSOR_BACKGROUND[counter_y][counter_x]); + if(y_pos<0) continue; + if(y_pos>=Screen_height) break; + for (x_pos=start_x,counter_x=0;counter_x<15;x_pos++,counter_x++) + { + if(x_pos<0) continue; + if(x_pos>=Screen_width) break; + Pixel(x_pos,y_pos,Cursor_background[counter_y][counter_x]); } } Update_rect(Max(start_x,0),Max(start_y,0),counter_x,counter_y); @@ -2492,52 +2575,52 @@ void Compute_optimal_menu_colors(T_Components * palette) for (k=0; kCursor_sprite[k][j][i]); // Le menu for (j=0; jMenu_block[j][i]); // Sprites du menu for (k=0; kMenu_sprite[k][j][i]); // Sprites d'effets for (k=0; kEffect_sprite[k][j][i]); // Fontes de l'aide for (k=0; k<256; k++) for (j=0; j<8; j++) for (i=0; i<6; i++) - Remap_pixel(&GFX_help_font_norm[k][i][j]); + Remap_pixel(&Gfx->Help_font_norm[k][i][j]); for (k=0; k<256; k++) for (j=0; j<8; j++) for (i=0; i<6; i++) - Remap_pixel(&GFX_bold_font[k][i][j]); + Remap_pixel(&Gfx->Bold_font[k][i][j]); for (k=0; k<64; k++) for (j=0; j<8; j++) for (i=0; i<6; i++) - Remap_pixel(&GFX_help_font_t1[k][i][j]); + Remap_pixel(&Gfx->Help_font_t1[k][i][j]); for (k=0; k<64; k++) for (j=0; j<8; j++) for (i=0; i<6; i++) - Remap_pixel(&GFX_help_font_t2[k][i][j]); + Remap_pixel(&Gfx->Help_font_t2[k][i][j]); for (k=0; k<64; k++) for (j=0; j<8; j++) for (i=0; i<6; i++) - Remap_pixel(&GFX_help_font_t3[k][i][j]); + Remap_pixel(&Gfx->Help_font_t3[k][i][j]); for (k=0; k<64; k++) for (j=0; j<8; j++) for (i=0; i<6; i++) - Remap_pixel(&GFX_help_font_t4[k][i][j]); + Remap_pixel(&Gfx->Help_font_t4[k][i][j]); // Sprites de lecteurs (drives) for (k=0; kIcon_sprite[k][j][i]); } Clear_border(MC_Black); } diff --git a/windows.h b/windows.h index 219ba3da..7feff36f 100644 --- a/windows.h +++ b/windows.h @@ -70,6 +70,7 @@ void Print_counter(short x,short y,const char * str,byte text_color,byte backgro byte Confirmation_box(char * message); void Warning_message(char * message); +void Verbose_error_message(char * message); void Display_image_limits(void); void Display_all_screen(void);