diff --git a/ARRL.DX b/ARRL.DX new file mode 100644 index 0000000..4bbc512 --- /dev/null +++ b/ARRL.DX @@ -0,0 +1,423 @@ +! ARRL DXCC COUNTRIES LIST For MMLOG +! +AP ;AP-AS,6P-6S ;PAKISTAN ;AS ;E +!A1 ;A1 ;ABU AIL ;AS +A2 ;A2,8O ;BOTSWANA ;AF ;B +A3 ;A3 ;TONGA ;OC ;N +A4 ;A4 ;OMAN ;AS ;D +A5 ;A5 ;BHUTAN ;AS ;F +A6 ;A6 ;UNITED ARAB ;AS ;D +A7 ;A7 ;QATAR ;AS ;C +A9 ;A9 ;BAHRAIN ;AS ;C +BV9P ;BV9P\,BQ9P\ ;PRATAS IS. ;AS ;H +BV ;BV,BX ;TAIWAN ;AS ;H +BS7 ;BS7H\ ;SCARBOROUGH REEF ;AS ;H +BY ;BA-BZ,3H-3U,B1-B9 ;CHINA ;AS ;H +CE0X ;CE0X,XQ0X-XR0X,CE0AA ;SAN FELIX IS. ;SA ;R +CE0Z ;CE0Z,CE0I,CE0OGZ,XQ0Z-XR0Z,XQ0I-XR0I,CE0/JA7XYE; FERNANDEZ ;SA ;R +CE0 ;CE0,XQ0-XR0 ;EASTER IS. ;SA ;T +CE ;CA-CE,XQ-XR,3G ;CHILE ;SA ;Q +CM ;CL-CM,CO,T4 ;CUBA ;NA ;R +CN ;CN,5C-5G ;MOROCCO ;AF ;Z +CP ;CP ;BOLIVIA ;SA ;Q +CT3 ;CS3,CT3,CR9 ;MADEIRAI IS.(PORTUGAL) ;AF ;Z +CU ;CU ;AZORES IS.(PORTUGAL) ;EU ;Z +CT ;CQ-CU ;PORTUGAL ;EU ;Z +CY9 ;CY9,CY0SPI ;ST PAUL IS. ;NA ;Q +CY0 ;CY0 ;SABLE IS. ;NA ;Q +CX ;CV-CX ;URUGUAY ;SA ;P +C2 ;C2 ;NAURU ;OC ;M +C3 ;C3 ;ANDORRA ;EU ;A +C5 ;C5 ;THE GAMBIA ;AF ;Z +C6 ;C6 ;BAHAMA IS. ;NA ;R +C8 ;C8-C9 ;MOZAMBIQUE ;AF ;B +DL ;DA-DR,Y2-Y9 ;GERMANY ;EU ;A +DU ;DU-DZ,4D-4I ;PHILIPPINES ;OC ;H +D2 ;D2-D3 ;ANGOLA ;AF ;A +D4 ;D4 ;CAPE VERDE ;AF ;A +D6 ;D6 ;COMOROS ;AF ;C +EA6 ;EA6-EH6,AM6-AO6 ;BALEARIC ;EU ;A +EA8 ;EA8-EH8,AM8-AO8 ;CANARY ;AF ;A +EA9 ;EA9-EH9,AM9-AO9 ;CEUTA & MELILLA(SPAIN) ;AF ;A +EA ;EA-EH,AM-AO ;SPAIN ;EU ;A +EI ;EI-EJ ;IRELAND ;EU ;Z +EK ;EK ;ARMENIA (ex UG) ;AS ;D +EL ;EL,5L-5M,A8,D5,6Z ;LIBERIA ;AF ;Z +EP ;EP-EQ,HN,9B-9D ;IRAN ;AS ;c +ER ;ER ;MOLDOVA (ex UO) ;EU ;C +ES ;ES ;ESTONIA ;EU ;C +ET ;ET,9E-9F ;ETHIOPIA ;AF ;C +EU ;EU-EW ;BELARUS (ex UC) ;EU ;C +EX ;EX ;KYRGYZSTAN (ex UM) ;AS ;F +EY ;EY ;TAJIKISTAN (ex UJ) ;AS ;F +EZ ;EZ ;TURKMENISTAN (ex UH) ;AS ;F +E4 ;E4 ;PALESTINE ;AS ;B +E3 ;E3 ;ERITREA ;AF ;C +FG ;FG ;GUADELOUPE ;NA ;Q +FH ;FH ;MAYOTTE ;AF ;C +FJ ;FJ,FS ;SAINT MARTIN ;NA ;Q +FK ;FK,TX8 ;NEW CALEDONIA ;OC ;L +FM ;FM ;MARTINIQUE ;NA ;Q +FO/C ;FO0X,FO0AAA ;CLIPPERTON IS. ;NA ;T +FO ;FO ;FRENCH POLYNESIA ;OC ;W +FO/A ;FO ;AUSTRAL IS ;OC ;W +FO/M ;FO ;MARQUESAS IS ;OC ;W +FP ;FP ;ST.PIERRE & MIQUELON IS. ;NA ;Q +FR/J ;FR*/J,FR*/E ;JUAN DE NOVA & EUROPA IS. ;AF ;C +FR/G ;FR*/G ;GLORIOSO IS. ;AF ;C +FR/T ;FR*/T ;TROMELIN ;AF ;C +FR ; ;REUNION IS. ;AF ;C +FR/? ;FR ;REUNION IS. /GLORIOSO IS. /JUAN DE NOVA & EUROPA ;AF ;C +FT5W ;FT8W,FT2W,FT4W,FT5W,FT0W ;CROZET IS. ;AF ;C +FT5X ;FT8X,FT2X,FT4X,FT5X,FT0X ;KERGUELEN IS. ;AF ;E +FT5Z ;FT8Z,FT2Z,FT4Z,FT5Z,FT0Z ;AMSTERDAM & ST PAUL IS. ;AF ;E +FW ;FW ;WALLIS & FUTUNA IS. ;OC ;M +FY ;FY ;FRENCH GUIANA ;SA ;P +F ;F,HW-HY,TM,TO-TQ ;FRANCE ;EU ;A +GD ;GD,GT,MA6-MB6,2A6,MD ;ISLE OF MAN ;EU ;Z +GI ;GI,GN,MA5-MB5,2A5,MI ;NORTHERN IRELAND ;EU ;Z +GJ ;GH,GJ,MA7-MB7,2A7,MJ ;JERSEY ;EU ;Z +GM ;GM,GS,MA3-MB3,2A3,MM ;SCOTLAND ;EU ;Z +GU ;GU,GP,MA8-MB8,2A8,MG ;GUERNSEY ;EU ;Z +GW ;GW,GC,MA4-MB4,2A4,MW ;WALES,U.K ;EU ;Z +G ;G,2,M ;ENGLAND(U.K) ;EU ;Z +HA ;HA,HG ;HUNGARY ;EU ;A +HB0 ;HB0,HE0 ;LIECHTENSTEIN ;EU ;A +HB ;HB,HE,4U1VIC ;SWITZERLAND ;EU ;A +HC8 ;HC8-HD8 ;GALAPAGOS IS.(ECUADOR) ;SA ;R +HC ;HC,HD ;ECUADOR ;SA ;R +HH ;HH,4V ;HAITI ;NA ;R +HI ;HI ;DOMINICAN REPUBLIC ;NA ;R +HK0/M ;HK0M,5J0M,HK0TU ;MALPELO IS. ;NA ;R +HK0/A ;HK0,5J0 ;SAN ANDRES ;NA ;R +HK ;HJ-HK,5J-5K ;COLOMBIA ;SA ;R +HL ;HL,DS-DT,6K-6N,D7-D9,KL9 ;REPUBLIC OF KOREA (SOUTH KOREA) ;AS ;I +HP ;HO-HP,3E-3F,H3,H8-H9 ;PANAMA ;NA ;R +HR ;HQ-HR ;HONDURAS ;NA ;S +HS ;HS,E2 ;THAILAND ;AS ;G +HV ;HV ;VATICAN ;EU ;A +HZ ;HZ,7Z-8Z ;SAUDI ARABIA ;AS ;C +H40 ;H40 ;TEMOTU IS ;OC ;L +H4 ;H4 ;SOLOMON IS. ;OC ;L +IS ;IS,IM0,IU0 ;SARDINIA ;EU ;A +I ;I ;ITALY ;EU ;A +JD1/M ;JD1YAA,JD1BIY ;MINAMI TORISHIMA ;OC ;I +JD1 ;JD1BIC ;OGASAWARA ;AS ;I +JD1/? ;JD1 ;OGASAWARA, /MINAMI TORISHIMA ;I +JA ;JA-JS,7J-7N,8J-8N ;JAPAN ;AS ;I +JT ;JT-JV ;MONGOLIA ;AS ;H +JW ;JW ;SVALBARD IS. ;EU ;A +JX ;JX ;JA MAYEN IS. ;EU ;Z +JY ;JY ;JORDAN ;AS ;B +J2 ;J2 ;DJIBOUTI ;AF ;C +J3 ;J3 ;GRENADA ;NA ;Q +J5 ;J5 ;GUINEA-BISSAU ;AF ;Z +J6 ;J6 ;ST LUCIA ;NA ;Q +J7 ;J7 ;DOMINICA ;NA ;Q +J8 ;J8 ;ST VINCENT & DEPENDENCIES ;NA ;Q +KC4 ;8J1R?\,R1A,FB8Y,CE9A,ZL5,Y88,Y90ANT,ZS8BBB,ZS8AAA,KC4AAC,KC4USV,Y73SOP,KC4AAA,KC4USB,KC4USX,3G9A,3Y9WT,8J1RY,AT0A,IA0PS,OR4,XS7ANT,Y83ANT,ZL0AIC,ZS7ANT,VK0DS,KC4AAE ;ANTARCTICA ;AN +KC6 ;T8,KC6??\ ;(WESTERN CAROLINE IS.) BELAU ;OC ;I +KG4 ;KG4??\ ;GUANTANAMO BAY ;NA ;R +KH0 ;AH0,KH0,NH0,WH0 ;MARIANA IS. ;OC ;K +KH1 ;AH1,KH1,NH1,WH1 ;BAKER & HOWLAND IS. ;OC ;X +KH2 ;AH2,KH2,NH2,WH2 ;GUAM ;OC ;K +KH3 ;AH3,KH3,NH3,WH3 ;JOHNSTON IS. ;OC ;X +KH4 ;AH4,KH4,NH4,WH4 ;MIDWAY IS. ;OC ;M +KH5K ;AH5K,KH5K,NH5K,WH5K ;KINGMAN REEF ;OC ;W +KH5 ;AH5,KH5,NH5,WH5 ;PALMYRA & JARVIS ;OC ;W +KH7K ;AH7K,KH7K,NH7K,WH7K ;KURE IS. ;OC ;M +KH6 ;AH6-AH7,KH6-KH7,NH6-NH7,WH6-WH7 ;HAWAIIAN IS. ;OC ;W +KH8 ;AH8,KH8,NH8,WH8 ;AMERICAN SAMOA ;OC ;W +KH9 ;AH9,KH9,NH9,WH9 ;WAKE IS. ;OC ;L +KL7 ;AL,KL0-KL8,NL,WL ;ALASKA ;NA ;W +KP1 ;KP1,NP1,WP1 ;NAVASSA IS. ;NA ;Q +KP2 ;KP2,NP2,WP2 ;AM.VIRGIN IS. ;NA ;Q +KP4 ;KP3-KP4,NP3-NP4,WP3-WP4 ;PUERTO RICO ;NA ;Q +KP5 ;KP5,NP5,WP5 ;DESECHEO IS. ;NA ;Q +W ;AA6-AK6,K6,N6,W6,K?6,N?6,W?6 ;U.S.A. ;NA ;U +W ;AA7-AK7,K7,N7,W7,K?7,N?7,W?7 ;U.S.A. ;NA ;T +W ;AA0-AK0,K0,N0,W0,K?0,N?0,W?0,AA5-AK5,K5,N5,W5,K?5,N?5,W?5,AA9-AK9,K9,N9,W9,K?9,N?9,W?9 ;U.S.A. ;NA ;S +W ;AA-AL,K,N,W,4U1WB ;U.S.A. ;NA ;R +LA ;LA-LN ;NORWAY ;EU ;A +LU ;LO-LW,AY-AZ,L2-L9 ;ARGENTINA ;SA ;P +LX ;LX ;LUXEMBOURG ;EU ;A +LY ;LY ;LITHUANIA ;EU ;C +LZ ;LZ ;BULGARIA ;EU ;B +OA ;OA-OC,4T ;PERU ;SA ;R +OD ;OD ;LEBANON ;AS ;B +OE ;OE ;AUSTRIA ;EU ;A +OH0 ;OH0,OF0 ;ALAND IS. ;EU ;B +OJ0 ;OJ0 ;MARKET REEF ;EU ;B +OH ;OF-OJ ;FINLAND ;EU ;B +OK ;OK-OL ;CZECH REPUBLIC ;EU ;A +OM ;OM ;SLOVAK REPUBLIC ;EU ;A +ON ;ON-OT ;BELGIUM ;EU ;A +OX ;OX ;GREENLAND ;NA ;Q +OY ;OY ;FAROES ;EU ;Z +OZ ;OU-OZ,XP,5P-5Q ;DENMARK ;EU ;A +PJ8 ;PJ5-PJ8,PJ0J,PJ1F ;SINT MAARTEN ;NA ;Q +PJ9 ;PJ ;NETHERLANDS ANTILLES ;SA ;Q +PA ;PA-PI ;NETHERLANDS ;EU ;A +PY0/S ;PP0S-PY0S,ZV0S-ZZ0S,PY0DX,PT0MI,PS0WH-PT0WH,PY0RO,PW0PP,PP0ZS-PY0ZS ;ST PETER ;SA ;P +PY0/T ;PP0T-PY0T,ZV0T-ZZ0T ;TRINDADE ;SA ;P +PY0 ;PP0-PY0,ZV0-ZZ0 ;FERNANDO DE NORONHA ;SA ;P +PY ;PP-PY,ZV-ZZ ;BRAZIL ;SA ;P +PZ ;PZ ;SURINAM ;SA ;Q +P2 ;P2 ;PAPUA NEW GUINEA ;OC ;K +P4 ;P4 ;ARUBA ;SA ;Q +P5 ;P5-P9,HM ;NORTH KOREA (DPRK) ;AS ;I +R1/MVI ;4J1FS,R1M,*/MVI,MVI/* ;MALYJ VYSOTSKIJ IS. (ex 4J1) ;EU ;C +R1/FJL ;R1F,*/FJL,FJL/* ;FRANZ JOSEPH LAND (ex UA1/4K2) ;EU ;C +SM ;SA-SM,7S-8S ;SWEDEN ;EU ;A +SP ;SN-SR,HF,3Z ;POLAND ;EU ;A +!ST0 ;ST0,6T0-6U0 ;SOUTHEN SUDAN ;AF ;B +ST ;ST,6T-6U ;SUDAN ;AF ;B +SU ;SU,6A-6B ;EGYPT ;AF ;B +SV/A ;SY1MA,SV*/A,*/SV/A ;MT ATHOS ;EU ;B +SV5 ;SV5-SZ5,J45 ;DODECANESE IS. ;EU ;B +SV9 ;SV9-SZ9,J49 ;CRETE ;EU ;B +SV ;SV-SZ,J4 ;GREECE ;EU ;B +S2 ;S2-S3 ;BANGLADESH ;AS ;F +S5 ;S5 ;SLOVENIA (ex YU3) ;EU ;A +S7 ;S7 ;SEYCHELLES ;AF ;C +S9 ;S9 ;SAO TOME & PRINCIPE ;AF ;B +S0 ;S0 ;WESTERN SAHARA ;AF ;Z +TA ;TA1-TC1,YM1 ;TURKEY (EU) ;EU ;C +TA ;TA2-TA9,TB2-TB9,TC2-TC9,YM2-YM9;TURKEY (AS) ;AS ;C +TF ;TF ;ICELAND ;EU ;Z +TG ;TG,TD ;GUATEMALA ;NA ;S +TI9 ;TI9,TE9 ;COCOS IS. ;NA ;S +TI ;TI,TE ;COSTA RICA ;NA ;S +TJ ;TJ ;CAMEROON ;AF ;A +TK ;TK ;CORSICA ;EU ;A +TL ;TL ;CENTRAL AFRICAN REP ;AF ;A +TN ;TN ;CONGO ;AF ;A +TR ;TR ;GABON ;AF ;A +TT ;TT ;CHAD ;AF ;A +TU ;TU ;IVORY COAST ;AF ;Z +TY ;TY ;BENIN ;AF ;Z +TX0 ;TX0 ;CHESTERFIELD IS. ;OC ;L +TZ ;TZ ;MALI ;AF ;Z +T2 ;T2 ;TUVALU ;OC ;M +T30 ;T30 ;WEST KIRIBATI(GILBERT IS.) ;OC ;X +T31 ;T31 ;CENTRAL KIRIBATI(BRITISH PHOENIX IS.) ;OC ;X +T32 ;T32 ;EAST KIRIBATI(LINE IS.) ;OC ;W +T33 ;T33 ;BANABA IS(OCEAN IS.) ;OC ;M +T5 ;T5,6O ;SOMALIA ;AF ;C +T7 ;T7 ;SAN MARINO ;EU ;A +T9 ;T9 ;BOSNIA-HERZEGOVINA (ex YU4,4N4) ;EU ;A +UJ ;UJ-UM ;UZBEKISTAN (ex UI) ;AS ;E +UN ;UN-UQ ;KAZAKHSTAN (ex UL) ;AS ;E +UR ;UR-UZ,EM-EO ;UKRAINE (ex UB) ;EU ;B +UA2 ;U?2,R?2 ;KALININGRAD ;EU ;C +UA/EU ;U?1-U?6,R?1-R?6,U1-U6,R1-R6 ;EUROPEAN RUSSIA ;EU ;C +UA/AS ;U?9,R?9,U9,R9 ;ASIATIC RUSSIA ;AS ;E +UA/AS ;U?8,U?0,R?8,R?0,U8,U0,R8,R0 ;ASIATIC RUSSIA ;AS ;I +VE ;VA7-VG7,VX7,CF7-CK7,XJ7-XO7,VY1 ;CANADA ;NA ;U +VE ;VA6-VG6,VX6,CF6-CK6,XJ6-XO6,VA5-VG5,VX5,CF5-CK5,XJ5-XO5 ;CANADA ;NA ;T +VE ;VA4-VG4,VX4,CF4-CK4,XJ4-XO4 ;CANADA ;NA ;S +VE ;VA3-VG3,VX3,CF3-CK3,XJ3-XO3,VA2-VG2,VX2,CF2-CK2,XJ2-XO2 ;CANADA ;NA ;R +VE ;VA-VG,VO,VX-VY,CF-CK,CY-CZ,XJ-XO ;CANADA ;NA ;Q +VK9L ;VK9L,AX9L ;LORD HOWE IS. ;OC ;L +VK9M ;VK9JW,VK9ZR,VK9MR,VK9ZM ;MELLISH REEF ;OC ;K +VK9N ;VK9N,AX9N ;NORFOLK IS. ;OC ;L +VK9W ;VK9Z,AX9Z,VK9TR ;WILLIS IS. ;OC ;K +VK9X ;VK9X,AX9X ;CHRISTMAS IS. ;OC ;H +VK9C ;VK9Y,AX9Y,VK9WB,VK9EW ;COCOS-KEELING IS. ;OC ;H +VK9? ;VK9 ;COCOS-KEELING IS., /LORD HOWE IS., /MELLISH IS., /NORFOLK IS., /WILLIS IS., /CHRISTMAS IS. ;OC ;K +VK0/M ;VK0AE,VK0GC,VK0WH ;MACQUARIE ;OC ;K +VK0/H ;VK0HM,VK0HI,VK0CW,VK0DA,VK0IR ;HEARD IS. ;AF ;E +VK0/? ;VK0 ;HEARD IS., /MACQUARIE IS. +VK ;VH-VN,VZ,AX ;AUSTRALIA ;OC ;K +VP2E ;VP2E,VP25E ;ANGUILLA ;NA ;Q +VP2M ;VP2M ;MONTSERRAT ;NA ;Q +VP2V ;VP2V ;BRITISH VIRGIN IS. ;NA ;Q +VP5 ;VP5 ;TURKS & CAICOS IS. ;NA ;R +VP8/G ;VP8BUB,VP8CDJ,VP8SGP ;SOUTH GEORGIA ;SA ;P +VP8/O ;LU1Z,VP8BXK ;SOUTH ORKNEY ;SA ;P +VP8/S ;LU2Z,4K1F,CX0XY,HF0POL,LU5ZI,ZX0ECF,VP8CQS,VP8CQR,LZ0A ;SOUTH SHETLAND ;SA ;P +VP8/SW ;VP8SSI ;SOUTH SANDWICH IS. ;SA ;P +VP8 ;VP8CSA ;FALKLAND IS. ;SA ;Q +VP8/? ;VP8,LU?Z ;FALKLAND IS., /SOUTH GEORGIA IS., /SOUTH ORKNEY IS., /SOUTH SANDWICH IS., /SOUTH SHETLAND IS. ;SA ;P +VP9 ;VP9 ;BERMUDA IS. ;NA +VQ9 ;VQ9 ;CHAGOS IS. ;AF ;E +VR6 ;VR6,VP6 ;PITCAIRN IS. ;OC ;U +VR2 ;VS6,VS96,VS97,VR97,VR98,VR2 ;HONG KONG ;AS ;H +VU/A ;VU2JPS ;ANDAMAN & NICOBAR IS. ;AS ;e +VU/L ; ;LACCADIVE IS. ;AS ;e +VU ; ;INDIA ;AS ;e +VU/? ;VT-VW,AT-AW,8T-8Y ;INDIA, /ANDAMAN & NICOBAR IS., /LACCADIVE IS. ;AS ;e +V2 ;V2 ;ANTIGUA & BARBUDA ;NA ;Q +V3 ;V3 ;BELIZE ;NA ;S +V4 ;V4 ;ST KITTS & NEVIS ;NA ;Q +V5 ;V5 ;NAMIBIA ;AF ;B +V6 ;V6 ;MICRONESIA(E CAROLINE IS.) ;OC ;L +V7 ;V7 ;MARSHALL IS. ;OC ;M +V8 ;V8 ;BRUNEI ;OC ;H +XF4 ;XA4-XI4,4A4-4C4,6D4-6J4 ;REVILLA GIGEDO ;NA ;T +XE ;XA-XI,4A-4C,6D-6J ;MEXICO ;NA ;S +XT ;XT ;BURKINA-FASO ;AF ;Z +XU ;XU ;CAMBODIA ;AS ;G +XV ;XV,3W ;VIETNAM ;AS ;G +XW ;XW ;LAOS ;AS ;G +XX9 ;XX9 ;MACAO ;AS ;H +XZ ;XY-XZ,1Z ;MYANMAR ;AS ;f +YA ;YA,T6 ;AFGHANISTAN ;AS ;d +YB ;YB-YH,JZ,PK-PO,7A-7I,8A-8I ;INDONESIA ;OC ;H +YI ;YI ;IRAQ ;AS ;C +YJ ;YJ ;VANUATU ;OC ;L +YK ;YK,6C ;SYRIA ;AS ;B +YL ;YL,UQ ;LATVIA ;EU ;C +YN ;YN,HT,H6-H7 ;NICARAGUA ;NA ;S +YO ;YO-YR ;ROMANIA ;EU ;B +YS ;YS,HU ;EL SALVADOR ;NA ;S +YU ;YT,YU,YZ,4N-4O ;YUGOSLAVIA ;EU ;A +YV0 ;YV0-YY0,4M0 ;AVES IS. ;NA ;Q +YV ;YV-YY,4M ;VENEZUELA ;SA ;Q +ZA ;ZA ;ALBANIA ;EU ;A +ZB ;ZB ;GIBRALTAR ;EU ;A +ZC ;ZC ;UK SOVEREIGN BASES ON CYPRUS ;AS ;B +ZD7 ;ZD7 ;ST HELENA ;AF ;Z +ZD8 ;ZD8 ;ASCENSION IS. ;AF ;Z +ZD9 ;ZD9 ;TRISTAN DE CUNHA & GOUGH IS. ;AF ;Z +ZF ;ZF ;CAYMAN IS. ;NA ;R +ZK1/N ;ZK1CQ,ZK1RS,ZK1BY,ZK1WL,ZK1XP,ZK1XY ;NORTH COOK IS. ;OC ;W +ZK1/S ; ;SOUTH COOK IS ;OC ;W +ZK1/? ;ZK1 ;NORTH COOK IS., /SOUTH COOK IS. ;OC ;W +ZK2 ;ZK2 ;NIUE ;OC ;X +ZK3 ;ZK3 ;TOKELAU IS. ;OC ;X +ZL7 ;ZL7-ZM7 ;CHATHAM IS. ;OC ;M +ZL8 ;ZL8-ZM8 ;KERMADEC IS. ;OC ;M +ZL9 ;ZL9-ZM9 ;AUKLAND & CAMPBELL IS. ;OC ;M +ZL ;ZL-ZM ;NEW ZEALAND ;OC ;M +ZP ;ZP ;PARAGUAY ;SA ;Q +ZS8 ;ZS8MI,ZT8M-ZU8M,ZR8M,ZS8IR ;PRINCE EDWARD & MARION IS. ;AF ;B +!ZS9 ;ZS9 ;WALVIS BAY ;AF +ZS ;ZR-ZU ;REP OF SOUTH AFRICA ;AF ;B +Z2 ;Z2 ;ZIMBABWE ;AF ;B +Z3 ;Z3 ;MACEDONIA (ex YU5,4N5) ;EU ;A +1A0 ;1A0 ;SOVEREIGN MILLITARY ORDER OF MALTA ;EU ;A +1S ;1S,9M0,9M6OO ;SPRATLY IS. ;AS ;H +3A ;3A ;MONACO ;EU ;A +3B6 ;3B6-3B7 ;AGALEGA & ST BRANDON IS. ;AF ;C +3B8 ;3B8 ;MAURITIUS IS. ;AF ;C +3B9 ;3B9 ;RODRIGUEZ IS. ;AF ;C +3C0 ;3C0 ;ANNOBON IS. ;AF ;A +3C ;3C ;EQUATORIAL GUINEA ;AF ;A +3D2/C ;3D2CR,3D2WV,3D2HL,3D2VT,3D2AM,3D2CU,3D2CT,3D2*/C ;CONWAY REEF ;OC ;M +3D2/R ;3D2XX,3D2RJ,3D2XV,3D2XR,3D2AP,3D2RO,3D2OQ,3D2RW,3D2*/R ;ROTUMA IS ;OC ;M +3D2 ;3D2 ;FIJI IS. ;OC ;M +3DA ;3DA ;SWAZILAND ;AF ;B +3V ;3V,TS ;TUNISIA ;AF ;A +3X ;3X ;GUINEA ;AF ;Z +3Y ;3Y1VC,3Y5X ;BOUVET ;AF ;Z +3Y/P ;3Y1EE,3Y2GV ;PETER 1 IS. ;AN ;S +3Y/? ;3Y ;BOUVET, /PETER 1 IS. ;AF,AN +4J ;4J-4K ;AZERBAIJAN (ex UD) ;AS ;F +4L ;4L ;GEORGIA (ex UF) ;AS ;F +4S ;4P-4S ;SRI LANKA ;AS ;e +4U1/U ;4U1U,4U43-4U44,4U45UN ;UN HEADQUATERS NEW YORK ;NA ;R +4U1/I ;4U?ITU ;ITU GENEVA ;EU ;A +4U1/? ;4U ;UN HEADQUATERS NEW YORK, /ITU GENEVA, etc +!4W ;4W ;YEMEN :AS +4W ;4W ;EAST TIMOR ;OC ;H +4X ;4X,4Z ;ISRAEL ;AS ;B +5A ;5A ;LIBYA ;AF ;B +5B ;5B,C4,H2,P3 ;CYPRUS ;AS ;B +5H ;5H-5I ;TANZANIA ;AF ;C +5N ;5N-5O ;NIGERIA ;AF ;A +5R ;5R-5S,6X ;MADAGASCAR ;AF ;C +5T ;5T ;MAURITANIA ;AF ;Z +5U ;5U ;NIGER ;AF ;A +5V ;5V ;TOGO ;AF ;Z +5W ;5W ;WESTERN SAMOA ;OC ;X +5X ;5X ;UGANDA ;AF ;C +5Y ;5Y-5Z ;KENYA ;AF ;C +6W ;6V-6W ;SENEGAL ;AF ;Z +6Y ;6Y ;JAMAICA ;NA ;R +7O ;7O ;REP OF YEMEN ;AS ;C +7P ;7P ;LESOTHO ;AF ;B +7Q ;7Q ;MALAWI ;AF ;B +7X ;7T-7Y ;ALGERIA ;AF ;Z +8P ;8P ;BARBADOS ;NA ;Q +8Q ;8Q ;MALDIVES ;AS,AF ;E +8R ;8R ;GUYANA ;SA ;P +9A ;9A ;CROATIA (ex YU2) ;EU ;A +9G ;9G ;GHANA ;AF ;Z +9H ;9H ;MALTA ;EU ;A +9J ;9I-9J ;ZAMBIA ;AF ;B +9K ;9K ;KUWAIT ;AS ;C +9L ;9L ;SIERRA LEONE ;AF ;Z +9M2 ;9M2,9M4,9W2,9W4 ;WEST MALAYSIA ;AS ;H +9M6 ;9M6,9M8,9W6,9W8 ;EAST MALAYSIA ;OC ;H +9N ;9N ;NEPAL ;AS ;e +9Q ;9O-9T ;ZAIRE ;AF ;B +9U ;9U ;BURUNDI ;AF ;B +9V ;9V,S6 ;SINGAPORE ;AS ;H +9X ;9X ;RWANDA ;AF ;B +9Y ;9Y-9Z ;TRINIDAD & TOBAGO ;SA ;Q +$END +!---------------------------------------------------------------------------- +!ファイルの形式 +! カントリ名 ; カントリ識別子 ; QTH ; 大陸名 ; タイムゾーン +! +!● 行の先頭のはコメントコード,<$>は終了コード +!● カントリ名は8文字以内。 +!● カントリ識別子は<,>で区切って複数個記述可。 +!● QTHは任意の文字列 +!● 大陸名は NA, SA, EU, OC, AF, AS, AN +!● タイムゾーンはA〜Z(Jを除く)で記述する。小文字は+30分 +!● コードは任意の位置にあっても良い +!● 1行255文字以内。 +!● 定義する行(コメント行を除く)は最大512行まで +!● このファイルをネット等で流通させる場合は、最後の変更履歴に追加記載する +! ことをお勧めします。 +! +!カントリ識別子 +! 1.プリフィックス(コールサイン)の羅列 +! 9M2,9M4,9W2,9W4 +! JD1YAA,JD1BIY +! ※ コールサインが短い場合は終端記号(\)を付加したほうが良い +! BV9P → BV9PAも含まれる +! BV9P\ → BV9Pのみ +! +! 2.範囲の指定 +! DA-DR,Y2-Y9 +! EA6-EH6,AM6-AO6 +! 範囲は同じ位置の1ヶ所のみを昇順で記述 +! JA-JS EA6-EH6 OK +! JS-JA(降順) EA6-EH7(2ヶ所) NG +! +! 3.ワイルドカード(範囲の複合可) +! U?1-U?6,R?1-R?6 +! SV*/A,*/SV/A +! =すべての文字, <*>=すべての文字列 +! +! 4.最初に定義したほうが優先される +! JD1/M ;JD1YAA ; MINAMI TORISHIMA ;OC +! JA ;JA-JS ; JAPAN ;AS +! 上記の例ではJD1YAAはJA-JSにも含まれるが、その前にJD1/Mの定義 +! があるのでそちらが優先される +! +!<<<変更履歴>>> +! Jan 15, 1996 - BV9P追加 JE3HHT +! Feb 15, 1996 - BS7H追加 JE3HHT +! Aug. 4, 1998 - VR98追加 JQ3UDL +! Aug. 4, 1998 - TA(AS)変更 JQ3UDL +! Nov. 15, 1998 - BQ9P追加 JQ3UDL +! Feb. 7, 1999 - FO0/M追加 JQ3UDL +! Feb. 7, 1999 - FO0/A追加 JQ3UDL +! Feb. 7, 1999 - H40追加 JQ3UDL +! Jul. 10, 1999 - E4追加  JQ3UDL +! Nov. 15. 1999 - 9M6OO追加 JQ3UDL +! Nov. 20. 1999 - B1-B9追加 JQ3UDL +! Jan. 06. 2000 - ST0削除 JE3HHT +! Feb. 15. 2000 - VR6にVP6追加 JE3HHT +! Mar. 03. 2000 - FO0XにFO0AAA追加 JE3HHT +! Mar. 20. 2000 - FO0X=>FO/C,FO0/M=>FO/M,FO0/A=>FO/Aに変更 JQ3UDL +! Mar. 20. 2000 - 4W追加 JQ3UDL +! Mar. 21. 2000 - TX0追加 JE3HHT +! Jan. 07. 2001 - P2の範囲変更 JQ3UDL +! Jan. 08. 2001 - KG4範囲変更 JQ3UDL +! Jan. 08. 2001 - LZ0A追加 JQ3UDL + \ No newline at end of file diff --git a/BitMask.cpp b/BitMask.cpp new file mode 100644 index 0000000..bcc8afb --- /dev/null +++ b/BitMask.cpp @@ -0,0 +1,968 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "Clipbrd.hpp" +#include "ComLib.h" +#include "PicRect.h" +#include "PicFilte.h" +#include "BitMask.h" +#include "Main.h" +//--------------------------------------------------------------------- +#pragma resource "*.dfm" +//TBitMaskDlg *BitMaskDlg; +//--------------------------------------------------------------------- +void __fastcall MakeBitmapPtn(Graphics::TBitmap *pBmp, int hw, int sw, TColor col1, TColor col2) +{ + CWaitCursor wait; + AdjustBitmapFormat(pBmp); + hw /= 3; + TCanvas *pCanvas = pBmp->Canvas; + int x, y, f, v; + for( y = 0; y < pBmp->Height; y++ ){ + for( x = 0; x < pBmp->Width; x++ ){ + f = x / hw; + switch(sw){ + case 0: + if( (y/2) & 1 ){ + v = (x/2) & 1; + } + else { + v = !((x/2) & 1); + } + break; + case 1: + if( (y/4) & 1 ){ + v = (x/2) & 1; + } + else { + v = !((x/2) & 1); + } + break; + case 2: + if( (y/2) & 1 ){ + v = (x/4) & 1; + } + else { + v = !((x/4) & 1); + } + break; + case 3: + if( (y/4) & 1 ){ + v = (x/4) & 1; + } + else { + v = !((x/4) & 1); + } + break; + case 4: + switch(f){ + case 0: + v = (y/2) & 1; + break; + case 1: + v = (y/4) & 1; + break; + default: + v = (y/8) & 1; + break; + } + break; + case 5: + switch(f){ + case 0: + v = (x/2) & 1; + break; + case 1: + v = (x/4) & 1; + break; + default: + v = (x/8) & 1; + break; + } + break; + case 6: + switch(f){ + case 0: + v = ((y+x)/2) & 1; + break; + case 1: + v = ((y+x)/4) & 1; + break; + default: + v = ((y+x)/8) & 1; + break; + } + break; + case 7: + switch(f){ + case 0: + v = ((x-y+1024)/2) & 1; + break; + case 1: + v = ((x-y+1024)/4) & 1; + break; + default: + v = ((x-y+1024)/8) & 1; + break; + } + break; + } + pCanvas->Pixels[x][y] = v ? col1 : col2; + } + } +#if 0 + + // pBmp->PixelFormat = pf24bit; + TCanvas *pCanvas = pBmp->Canvas; + int x, y; + for( y = 0; y < pBmp->Height; y++ ){ + for( x = 0; x < pBmp->Width; x++ ){ + switch(sw){ + case 0: + if( (y/2) & 1 ){ + pCanvas->Pixels[x][y] = (x/2) & 1 ? col1 : col2; + } + else { + pCanvas->Pixels[x][y] = (x/2) & 1 ? col2 : col1; + } + break; + case 1: + if( (y/4) & 1 ){ + pCanvas->Pixels[x][y] = (x/2) & 1 ? col1 : col2; + } + else { + pCanvas->Pixels[x][y] = (x/2) & 1 ? col2 : col1; + } + break; + case 2: + if( (y/2) & 1 ){ + pCanvas->Pixels[x][y] = (x/4) & 1 ? col1 : col2; + } + else { + pCanvas->Pixels[x][y] = (x/4) & 1 ? col2 : col1; + } + break; + case 3: + if( (y/4) & 1 ){ + pCanvas->Pixels[x][y] = (x/4) & 1 ? col1 : col2; + } + else { + pCanvas->Pixels[x][y] = (x/4) & 1 ? col2 : col1; + } + break; + case 4: + pCanvas->Pixels[x][y] = (y/4) & 1 ? col1 : col2; + break; + case 5: + pCanvas->Pixels[x][y] = (x/2) & 1 ? col1 : col2; + break; + case 6: + pCanvas->Pixels[x][y] = ((y+x)/4) & 1 ? col1 : col2; + break; + case 7: + pCanvas->Pixels[x][y] = ((x-y+1024)/2) & 1 ? col1 : col2; + break; + } + } + } +#endif +} +//--------------------------------------------------------------------- +__fastcall TBitMaskDlg::TBitMaskDlg(TComponent* AOwner) + : TForm(AOwner) +{ + m_DisEvent = TRUE; + FormStyle = ((TForm *)AOwner)->FormStyle; + Font->Name = ((TForm *)AOwner)->Font->Name; + Font->Charset = ((TForm *)AOwner)->Font->Charset; + if( MsgEng ){ + Caption = "Bitmap mask"; + CancelBtn->Caption = "Cancel"; + L1->Caption = "Size"; + GB2->Caption = "Make and Edit mask"; + PaintBtn->Caption = "Edit"; + + SBPaste->Hint = "Paste mask from the clipboard"; + SBCopy->Hint = "Copy mask to the clipboard"; + SBColAdj->Hint = "Adjusts mask image"; + GB1->Caption = "User definition mask"; + L3->Caption = "Drag&&Drop for registration"; + } + SBPaste->Glyph->Assign(Mmsstv->SBPaste->Glyph); + SBColAdj->Glyph->Assign(Mmsstv->SBHistFil->Glyph); + SBCopy->Glyph->Assign(Mmsstv->SBCopy->Glyph); + pBitmap = new Graphics::TBitmap(); + AdjustBitmapFormat(pBitmap); + pBitmap->Width = PBox->Width; + pBitmap->Height = PBox->Height; + m_pCustomBmp = NULL; + m_pUserBmp = NULL; + m_pListBmp = NULL; + m_X = m_Y = 0; + m_Size = 0; + char name[256]; + sprintf(name, "%sTextArt.bmp", BgnDir); + m_ListName = name; + UDL->Position = (SHORT)sys.m_MaskUserPage; + PC1->Color = sys.m_MaskCol1; + PC2->Color = sys.m_MaskCol2; + m_hClipNext = ::SetClipboardViewer(Handle); + ShowHint = WinNT; +} +//--------------------------------------------------------------------------- +void __fastcall TBitMaskDlg::FormDestroy(TObject *Sender) +{ + sys.m_MaskUserPage = UDL->Position; + sys.m_MaskCol1 = PC1->Color; + sys.m_MaskCol2 = PC2->Color; + ::ChangeClipboardChain(Handle, m_hClipNext); + g_ExecPB.Cancel(); + if( pBitmap != NULL ){ + delete pBitmap; + pBitmap = NULL; + } + if( m_pCustomBmp != NULL ){ + delete m_pCustomBmp; + m_pCustomBmp = NULL; + } + if( m_pListBmp != NULL ){ + if( m_pListBmp->Modified ){ + m_pListBmp->SaveToFile(m_ListName); + } + delete m_pListBmp; + m_pListBmp = NULL; + } + if( m_pUserBmp != NULL ){ + delete m_pUserBmp; + m_pUserBmp = NULL; + } +} +//--------------------------------------------------------------------------- +int __fastcall TBitMaskDlg::Execute(Graphics::TBitmap *pBmp, CDrawText *pText) +{ + m_Text.Start(PBoxText->Canvas, 0, 0); // キャンバスのセット + m_Text.Copy(pText); + m_Text.UpdateText(); + pBitmap->Width = pBmp->Width; + pBitmap->Height = pBmp->Height; + m_XW = pBitmap->Width; + m_YW = pBitmap->Height; + UpdateCBSize(m_XW, m_YW); + FillBitmap(pBitmap, clGray); + pBitmap->Canvas->Draw(0, 0, pBmp); + UpdateSB(); + m_DisEvent = FALSE; + if( ShowModal() == IDOK ){ + pBmp->Width = m_XW < pBitmap->Width ? m_XW : pBitmap->Width; + pBmp->Height = m_YW < pBitmap->Height ? m_YW : pBitmap->Height; + pBmp->Canvas->Draw(-m_X, -m_Y, pBitmap); + return TRUE; + } + return FALSE; +} +//--------------------------------------------------------------------- +void __fastcall TBitMaskDlg::PBoxPaint(TObject *Sender) +{ +#if 0 + TRect rc; + rc.Left = 0; rc.Top = 0; + rc.Right = PBox->Width; rc.Bottom = PBox->Height; + TCanvas *pCanvas = PBox->Canvas; + pCanvas->Brush->Color = clBtnFace; + pCanvas->FillRect(rc); +#endif + PBox->Canvas->Draw(-SBH->Position, -SBV->Position, pBitmap); + DrawCursor(); +} +//--------------------------------------------------------------------------- +void __fastcall TBitMaskDlg::UpdateSB(void) +{ + SBH->Position = 0; SBV->Position = 0; + int hmax, vmax; + if( pBitmap ){ + int xw = pBitmap->Width; + int yw = pBitmap->Height; + hmax = xw - PBox->ClientWidth; + vmax = yw - PBox->ClientHeight; + } + else { + hmax = vmax = -1; + } + SBH->Max = (hmax > 0) ? hmax : 0; + SBV->Max = (vmax > 0) ? vmax : 0; + SBH->Enabled = (hmax > 0) ? TRUE : FALSE; + SBV->Enabled = (vmax > 0) ? TRUE : FALSE; +} +//--------------------------------------------------------------------------- +void __fastcall TBitMaskDlg::LoadBtnClick(TObject *Sender) +{ + TOpenDialog *pDialog = Mmsstv->OpenDialog; + pDialog->Options >> ofCreatePrompt; + pDialog->Options << ofFileMustExist; + if( MsgEng ){ + pDialog->Title = "Load picture from file"; + } + else { + pDialog->Title = "画像のロード"; + } + pDialog->Filter = GetPicFilter(); + pDialog->FileName = ""; + pDialog->DefaultExt = "jpg"; + pDialog->InitialDir = BitmapDir; + SetDisPaint(); + NormalWindow(this); + if( Mmsstv->OpenDialogExecute(TRUE) == TRUE ){ + SetDirName(BitmapDir, AnsiString(pDialog->FileName).c_str()); + if( LoadImage(pBitmap, AnsiString(pDialog->FileName).c_str()) == TRUE ){ + UpdateSrc(TRUE); + UpdateUser(); + } + } + ResDisPaint(); + TopWindow(this); +} +//--------------------------------------------------------------------------- +void __fastcall TBitMaskDlg::UpdateCBSize(int xw, int yw) +{ + m_DisEvent++; + int f = TRUE; + if( xw == yw ){ + switch(xw){ + case 8: + CBSize->ItemIndex = 0; + break; + case 16: + CBSize->ItemIndex = 1; + break; + case 24: + CBSize->ItemIndex = 2; + break; + case 32: + CBSize->ItemIndex = 3; + break; + default: + f = FALSE; + break; + } + } + else { + f = FALSE; + } + if( f ){ + if( CBSize->Items->Count > 4 ) CBSize->Items->Delete(4); + } + else { + char bf[256]; + sprintf(bf, "%ux%u", xw, yw); + if( CBSize->Items->Count > 4 ){ + CBSize->Items->Strings[4] = bf; + } + else { + CBSize->Items->Add(bf); + } + CBSize->ItemIndex = 4; + } + m_DisEvent--; +} +//--------------------------------------------------------------------------- +void __fastcall TBitMaskDlg::AdjustSize(void) +{ + m_X = m_Y = 0; + int xw = pBitmap->Width; + int yw = pBitmap->Height; + + if( (xw == yw) && (xw <= 32) ){ + switch(xw){ + case 8: + case 16: + case 24: + case 32: + m_XW = m_YW = xw; + break; + } + } + else if( (xw >= 32) && (yw >= 32) ){ + m_XW = m_YW = 32; + } + UpdateCBSize(m_XW, m_YW); +} +//--------------------------------------------------------------------------- +void __fastcall TBitMaskDlg::DrawCursor(void) +{ + int xw = m_XW; + int yw = m_YW; + int xo = -SBH->Position; + int yo = -SBV->Position; + TCanvas *tp = PBox->Canvas; + tp->Pen->Width = 1; + tp->Pen->Style = psDot; + tp->MoveTo(xo+m_X, yo+m_Y); + int rop = ::SetROP2(tp->Handle, R2_NOT); + tp->LineTo(xo+m_X+xw, yo+m_Y); + tp->LineTo(xo+m_X+xw, yo+m_Y+yw); + tp->LineTo(xo+m_X, yo+m_Y+yw); + tp->LineTo(xo+m_X, yo+m_Y); + ::SetROP2(tp->Handle, rop); +} +//--------------------------------------------------------------------------- +void __fastcall TBitMaskDlg::UpdateText(void) +{ + CWaitCursor w; + + int xw = m_XW; + int yw = m_YW; + if( xw <= 0 ) xw = 1; + if( yw <= 0 ) yw = 1; + Graphics::TBitmap *pBmp = CreateBitmap(xw, yw, -1); + pBmp->Canvas->Draw(-m_X, -m_Y, pBitmap); + CopyBitmap(m_Text.pBrushBitmap, pBmp); + delete pBmp; + m_Text.UpdateText(); + PBoxTextPaint(NULL); +} +//--------------------------------------------------------------------------- +void __fastcall TBitMaskDlg::BtnClick(int n) +{ + pBitmap->Width = PBox->Width; + pBitmap->Height = PBox->Height; + MakeBitmapPtn(pBitmap, PBox->Width, n, PC1->Color, PC2->Color); + m_XW = m_YW = 8; + UpdateCBSize(m_XW, m_YW); + UpdateSrc(FALSE); + UpdateUser(); +} +//--------------------------------------------------------------------------- +void __fastcall TBitMaskDlg::PCClick(TObject *Sender) +{ + TPanel *pPanel = (TPanel *)Sender; + TColorDialog *pDialog = Mmsstv->ColorDialog; + InitCustomColor(pDialog); + AddCustomColor(pDialog, PC1->Color); + AddCustomColor(pDialog, PC2->Color); + pDialog->Color = pPanel->Color; + SetDisPaint(); + if( pDialog->Execute() == TRUE ){ + pPanel->Color = pDialog->Color; + UpdateCustom(); + PBoxCSPaint(NULL); + } + ResDisPaint(); +} +//--------------------------------------------------------------------------- +void __fastcall TBitMaskDlg::PBoxMouseDown(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( Button == mbLeft ){ + X += SBH->Position; Y += SBV->Position; + m_X = X; m_Y = Y; + m_Size = 1; + } + else { + m_X = 0; m_Y = 0; + } + UpdateText(); + PBox->Invalidate(); + UpdateUser(); +} +//--------------------------------------------------------------------------- +void __fastcall TBitMaskDlg::PBoxMouseMove(TObject *Sender, + TShiftState Shift, int X, int Y) +{ + if( m_Size ){ + X += SBH->Position; Y += SBV->Position; + if( m_Size == 1 ){ + if( (ABS(X-m_X)>4) || (ABS(Y-m_Y)>4) ){ + m_Size++; + } + } + if( m_Size == 2 ){ + DrawCursor(); + m_XW = ABS(X - m_X); + m_YW = ABS(Y - m_Y); + if( !m_XW ) m_XW = 1; + if( !m_YW ) m_YW = 1; + DrawCursor(); + UpdateCBSize(m_XW, m_YW); + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TBitMaskDlg::PBoxMouseUp(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( m_Size == 2 ){ + UpdateText(); + PBox->Invalidate(); + UpdateUser(); + } + m_Size = 0; +} +//--------------------------------------------------------------------------- +void __fastcall TBitMaskDlg::PaintBtnClick(TObject *Sender) +{ + g_ExecPB.Exec(pBitmap, (HWND)Handle, CM_EDITEXIT, 0); +} +//--------------------------------------------------------------------------- +void __fastcall TBitMaskDlg::OnEditExit(TMessage Message) +{ + if( Message.LParam ) return; + + if( g_ExecPB.LoadBitmap(pBitmap, TRUE) ){ + UpdateSrc(FALSE); + UpdateUser(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TBitMaskDlg::OnDrawClipboard(TMessage Message) +{ + SBPaste->Enabled = Clipboard()->HasFormat(CF_BITMAP); + if( m_hClipNext ) ::SendMessage(m_hClipNext, WM_DRAWCLIPBOARD, Message.WParam, Message.LParam); +} +//--------------------------------------------------------------------------- +void __fastcall TBitMaskDlg::OnChangeCbChain(TMessage Message) +{ + if( (HWND)Message.WParam == m_hClipNext ){ + m_hClipNext = (HWND)Message.LParam; + } + if( m_hClipNext ) ::SendMessage(m_hClipNext, WM_CHANGECBCHAIN, Message.WParam, Message.LParam); + Message.Result = 0; +} +//--------------------------------------------------------------------------- +static void __fastcall DrawBmpPBoxBtn(TCanvas *pCanvas, int x, int y, int w, BOOL sw) +{ + pCanvas->Pen->Style = psSolid; + pCanvas->Pen->Width = 1; + pCanvas->Pen->Color = sw ? clBlack : clWhite; + w++; + pCanvas->MoveTo(x+w, y); + pCanvas->LineTo(x, y); + pCanvas->LineTo(x, y+w); + pCanvas->LineTo(x+1, y+w); + pCanvas->Pen->Color = sw ? clWhite : clBlack; + pCanvas->LineTo(x+w, y+w); + pCanvas->LineTo(x+w, y); +} +#if 0 +//--------------------------------------------------------------------------- +static void __fastcall DrawBmpPBox(TCanvas *pCanvas, int x, int y, Graphics::TBitmap *pBmp) +{ + pCanvas->Draw(x+1, y+1, pBmp); + DrawBmpPBoxBtn(pCanvas, x, y, pBmp->Width, FALSE); +} +#endif +//--------------------------------------------------------------------------- +static void __fastcall DrawBmpPBox(TCanvas *pCanvas, int s, int w, int ws, int x, int y, Graphics::TBitmap *pBmp) +{ + TRect src, drc; + + src.Left = ((y*8)+x)*ws; + src.Right = src.Left + w; + src.Top = 0; src.Bottom = w; + drc.Left = 1 + x*s; + drc.Right = drc.Left + w; +// drc.Top = 1 + y*s; + drc.Top = 1; + drc.Bottom = drc.Top + w; + pCanvas->CopyRect(drc, pBmp->Canvas, src); + DrawBmpPBoxBtn(pCanvas, x*s, y*s, w, FALSE); +} +//--------------------------------------------------------------------------- +static int __fastcall GetIndex(int w, int m, int x, int y) +{ + if( ((x % w) < 1) || ((x % w) >= (w-1)) ) return -1; + if( ((y % w) < 1) || ((y % w) >= (w-1)) ) return -1; + x /= w; + y /= w; + int n = (y * 8) + x; + if( n >= m ) n = m-1; + return n; +} +//--------------------------------------------------------------------------- +void __fastcall TBitMaskDlg::UpdateCustom(void) +{ + if( !m_pCustomBmp ) m_pCustomBmp = CreateBitmap(16*8, 16, -1); + Graphics::TBitmap *pBmp = CreateBitmap(16, 16, -1); + int i; + for( i = 0; i < 8; i++ ){ + MakeBitmapPtn(pBmp, PBox->Width, i, PC1->Color, PC2->Color); + m_pCustomBmp->Canvas->Draw(i*16, 0, pBmp); + } + delete pBmp; +} +//--------------------------------------------------------------------------- +void __fastcall TBitMaskDlg::PBoxCSPaint(TObject *Sender) +{ + if( !m_pCustomBmp ){ + UpdateCustom(); + if( !m_pCustomBmp ) return; + } + MultProc(); + int x; + for( x = 0; x < 8; x++ ){ + DrawBmpPBox(PBoxCS->Canvas, 18, 16, 16, x, 0, m_pCustomBmp); + } +} +//--------------------------------------------------------------------------- + +void __fastcall TBitMaskDlg::PBoxCSMouseDown(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( Button == mbLeft ){ + m_MIndex = GetIndex(18, 8, X, Y); + if( m_MIndex >= 0 ){ + DrawBmpPBoxBtn(PBoxCS->Canvas, 18*(m_MIndex%8), 0, 16, TRUE); + BtnClick(m_MIndex); + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TBitMaskDlg::PBoxCSMouseUp(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( (Button == mbLeft) && (m_MIndex >= 0) ){ + DrawBmpPBoxBtn(PBoxCS->Canvas, 18*(m_MIndex%8), 0, 16, FALSE); + } +} +//--------------------------------------------------------------------------- +void __fastcall TBitMaskDlg::CBSizeChange(TObject *Sender) +{ + switch(CBSize->ItemIndex){ + case 0: + m_XW = m_YW = 8; + break; + case 1: + m_XW = m_YW = 16; + break; + case 2: + m_XW = m_YW = 24; + break; + case 3: + m_XW = m_YW = 32; + break; + } + UpdateText(); + PBox->Invalidate(); +} +//--------------------------------------------------------------------------- +void __fastcall TBitMaskDlg::PBoxTextPaint(TObject *Sender) +{ + if( !m_Text.pBitmap ) m_Text.UpdateText(); + PBoxText->Canvas->Draw(0, 0, m_Text.pBitmap); +} +//--------------------------------------------------------------------------- +void __fastcall TBitMaskDlg::SBPasteClick(TObject *Sender) +{ + pBitmap->LoadFromClipboardFormat(CF_BITMAP, Clipboard()->GetAsHandle(CF_BITMAP), 0); + UpdateSrc(TRUE); + UpdateUser(); +} +//--------------------------------------------------------------------------- +void __fastcall TBitMaskDlg::SBCopyClick(TObject *Sender) +{ + Mmsstv->CopyBitmap(pBitmap); +} +//--------------------------------------------------------------------------- +void __fastcall TBitMaskDlg::SBColAdjClick(TObject *Sender) +{ + TPicFilterDlg *pBox = new TPicFilterDlg(this); + if( pBox->Execute(pBitmap) == TRUE ){ + UpdateSrc(FALSE); + UpdateUser(); + } + delete pBox; +} +//--------------------------------------------------------------------------- +void __fastcall TBitMaskDlg::SBClipClick(TObject *Sender) +{ + Graphics::TBitmap *pBmp = DupeBitmap(pBitmap, -1); + TPicRectDlg *pBox = new TPicRectDlg(this); + CopyBitmap(pBox->pBitmap, pBmp); + pBmp->Width = PBox->Width; + pBmp->Height = PBox->Height; + if( pBox->Execute(pBmp) == TRUE ){ + CopyBitmap(pBitmap, pBmp); + UpdateSrc(TRUE); + } + delete pBox; + delete pBmp; +} +//--------------------------------------------------------------------------- +void __fastcall TBitMaskDlg::UpdateSrc(BOOL fSize) +{ + if( fSize ) AdjustSize(); + UpdateSB(); + UpdateText(); + PBox->Invalidate(); + CBSize->SetFocus(); +} +//--------------------------------------------------------------------------- +void __fastcall TBitMaskDlg::UpdateUser(void) +{ + if( !m_pUserBmp ){ + m_pUserBmp = CreateBitmap(32, 32, pf24bit); + } + Graphics::TBitmap *pSrc = m_Text.pBrushBitmap; + for( int y = 0; y < 32; y += pSrc->Height){ + for( int x = 0; x < 32; x += pSrc->Width ){ + m_pUserBmp->Canvas->Draw(x, y, pSrc); + } + } + PBoxUPaint(NULL); +} +//--------------------------------------------------------------------------- +void __fastcall TBitMaskDlg::PBoxUPaint(TObject *Sender) +{ + if( !m_pUserBmp ){ + UpdateUser(); + } + else { + DrawBmpPBox(PBoxU->Canvas, 30, 28, 32, 0, 0, m_pUserBmp); + } +} +//--------------------------------------------------------------------------- +void __fastcall TBitMaskDlg::PBoxUMouseDown(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( Button == mbLeft ){ + DrawBmpPBoxBtn(PBoxU->Canvas, 0, 0, 28, TRUE); + if( !IsSameBitmap(m_pUserBmp, m_Text.pBrushBitmap, FALSE) ){ + CopyBitmap(pBitmap, m_pUserBmp); + UpdateSrc(TRUE); + } + ::Sleep(100); + DrawBmpPBoxBtn(PBoxU->Canvas, 0, 0, 28, FALSE); + PBoxU->BeginDrag(FALSE,0); + } +} +//--------------------------------------------------------------------------- +int __fastcall TBitMaskDlg::IsSameBitmap(Graphics::TBitmap *pDest, Graphics::TBitmap *pSrc, int fSize) +{ + int xw = pSrc->Width; + int yw = pSrc->Height; + if( xw > pDest->Width ) return FALSE; + if( yw > pDest->Height ) return FALSE; + if( fSize ){ + if( xw != pDest->Width ) return FALSE; + if( yw != pDest->Height ) return FALSE; + } + int x, y; + for( y = 0; y < yw; y++ ){ + for( x = 0; x < xw; x++ ){ + if( pSrc->Canvas->Pixels[x][y] != pDest->Canvas->Pixels[x][y] ) return FALSE; + } + } + return TRUE; +} +//--------------------------------------------------------------------------- +int __fastcall TBitMaskDlg::IsMList(int n) +{ + int yw = m_pListBmp->Height; + int x, y; + for( y = 0; y < yw; y++ ){ + LPBYTE p = (LPBYTE)m_pListBmp->ScanLine[y]; + p += (n * 32) * 3; + for( x = 0; x < 32; x++ ){ + if( *p++ ) return TRUE; + if( *p++ ) return TRUE; + if( *p++ ) return TRUE; + } + } + return FALSE; +} +//--------------------------------------------------------------------------- +void __fastcall TBitMaskDlg::PBoxLPaint(TObject *Sender) +{ + if( !m_pListBmp ){ + if( IsFile(m_ListName.c_str()) ){ + m_pListBmp = new Graphics::TBitmap; + m_pListBmp->LoadFromFile(m_ListName); + } + else { + m_pListBmp = CreateBitmap(32*72, 32, pf24bit); + FillBitmap(m_pListBmp, clBlack); + } + m_pListBmp->Modified = FALSE; + } + int y = UDL->Position; + int x; + for( x = 0; x < 8; x++ ){ + DrawBmpPBox(PBoxL->Canvas, 30, 28, 32, x, y, m_pListBmp); + } + char bf[32]; + sprintf(bf, "%u/9", y + 1); + LP->Caption = bf; +} +//--------------------------------------------------------------------------- +void __fastcall TBitMaskDlg::PBoxLMouseDown(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + m_MIndex = GetIndex(30, 8, X, Y); + if( m_MIndex >= 0 ){ + m_MIndex += (UDL->Position * 8); + if( (Button == mbLeft) && IsMList(m_MIndex) ){ + DrawBmpPBoxBtn(PBoxL->Canvas, (m_MIndex%8)*30, 0, 28, TRUE); + + Graphics::TBitmap *pBmp = CreateBitmap(32, 32, pf24bit); + pBmp->Canvas->Draw(-m_MIndex*32, 0, m_pListBmp); + if( !IsSameBitmap(pBmp, m_Text.pBrushBitmap, TRUE) ){ + CopyBitmap(pBitmap, pBmp); + UpdateSrc(TRUE); + } + delete pBmp; + + ::Sleep(100); + DrawBmpPBoxBtn(PBoxL->Canvas, (m_MIndex%8)*30, 0, 28, FALSE); + PBoxL->BeginDrag(FALSE,0); + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TBitMaskDlg::PBoxLDragOver(TObject *Sender, + TObject *Source, int X, int Y, TDragState State, bool &Accept) +{ + Accept = FALSE; + + int index = GetIndex(30, 8, X, Y); + if( index >= 0 ){ + index += (UDL->Position * 8); + if( Source == PBoxL ){ + if( index != m_MIndex ) Accept = TRUE; + } + else { + Accept = TRUE; + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TBitMaskDlg::PBoxLDragDrop(TObject *Sender, + TObject *Source, int X, int Y) +{ + int index = GetIndex(30, 8, X, Y); + if( index >= 0 ){ + index += (UDL->Position * 8); + if( Source == PBoxL ){ + Graphics::TBitmap *pBmp = CreateBitmap(32, 32, pf24bit); + Graphics::TBitmap *pBmp2 = CreateBitmap(32, 32, pf24bit); + pBmp2->Canvas->Draw(-index*32, 0, m_pListBmp); + pBmp->Canvas->Draw(-m_MIndex*32, 0, m_pListBmp); + m_pListBmp->Canvas->Draw(index*32, 0, pBmp); + m_pListBmp->Canvas->Draw(m_MIndex*32, 0, pBmp2); + delete pBmp2; + delete pBmp; + } + else { + m_pListBmp->Canvas->Draw(index*32, 0, m_pUserBmp); + } + PBoxUPaint(NULL); + PBoxLPaint(NULL); + m_pListBmp->Modified = TRUE; + } +} +//--------------------------------------------------------------------------- +void __fastcall TBitMaskDlg::PBoxUDragOver(TObject *Sender, + TObject *Source, int X, int Y, TDragState State, bool &Accept) +{ + Accept = ((Source == PBoxL) && (m_MIndex >= 0)); +} +//--------------------------------------------------------------------------- +void __fastcall TBitMaskDlg::PBoxUDragDrop(TObject *Sender, + TObject *Source, int X, int Y) +{ + if( m_MIndex >= 0 ){ + m_pUserBmp->Canvas->Draw(-m_MIndex*32, 0, m_pListBmp); + Graphics::TBitmap *pBmp = CreateBitmap(32, 32, pf24bit); + FillBitmap(pBmp, clBlack); + m_pListBmp->Canvas->Draw(m_MIndex*32, 0, pBmp); + delete pBmp; + PBoxUPaint(NULL); + PBoxLPaint(NULL); + } +} +//--------------------------------------------------------------------------- +void __fastcall TBitMaskDlg::UDLClick(TObject *Sender, TUDBtnType Button) +{ + PBoxLPaint(NULL); +} +//--------------------------------------------------------------------------- + +void __fastcall TBitMaskDlg::FormKeyDown(TObject *Sender, WORD &Key, + TShiftState Shift) +{ + TShiftState sf1, sf2; + sf1 << ssShift; + sf2 << ssShift; + sf1 *= Shift; + int sft = (sf1 == sf2); + + DrawCursor(); + int x = m_X; + int y = m_Y; + int xw = m_XW; + int yw = m_YW; + switch(Key){ + case VK_LEFT: + if( sft ){ + if( m_XW >= 2 ) m_XW--; + } + else { + if( m_X ) m_X--; + } + Key = 0; + break; + case VK_RIGHT: + if( sft ){ + m_XW++; + } + else { + m_X++; + } + Key = 0; + break; + case VK_UP: + if( sft ){ + if( m_YW >= 2 ) m_YW--; + } + else { + if( m_Y ) m_Y--; + } + Key = 0; + break; + case VK_DOWN: + if( sft ){ + m_YW++; + } + else { + m_Y++; + } + Key = 0; + break; + } + DrawCursor(); + if( (x != m_X) || (y != m_Y) || (xw != m_XW) || (yw != m_YW) ){ + UpdateCBSize(m_XW, m_YW); + UpdateText(); + UpdateUser(); + } +} +//--------------------------------------------------------------------------- + diff --git a/BitMask.dfm b/BitMask.dfm new file mode 100644 index 0000000..ddd24f0 Binary files /dev/null and b/BitMask.dfm differ diff --git a/BitMask.h b/BitMask.h new file mode 100644 index 0000000..5018491 --- /dev/null +++ b/BitMask.h @@ -0,0 +1,165 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//---------------------------------------------------------------------------- +#ifndef BitMaskH +#define BitMaskH +//---------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "Draw.h" +#include +//---------------------------------------------------------------------------- +extern void __fastcall MakeBitmapPtn(Graphics::TBitmap *pBmp, int hw, int sw, TColor col1, TColor col2); +//---------------------------------------------------------------------------- +class TBitMaskDlg : public TForm +{ +__published: + TButton *OKBtn; + TButton *CancelBtn; + TPanel *Panel; + TGroupBox *GB2; + TButton *LoadBtn; + TPaintBox *PBox; + TPanel *PC1; + TPanel *PC2; + TButton *PaintBtn; + TScrollBar *SBV; + TScrollBar *SBH; + TPaintBox *PBoxCS; + TComboBox *CBSize; + TLabel *L1; + TPaintBox *PBoxText; + TSpeedButton *SBPaste; + TSpeedButton *SBColAdj; + TSpeedButton *SBCopy; + TSpeedButton *SBClip; + TGroupBox *GB1; + TPaintBox *PBoxU; + TPaintBox *PBoxL; + TLabel *L2; + TUpDown *UDL; + TLabel *LP; + TLabel *L3; + void __fastcall PBoxPaint(TObject *Sender); + void __fastcall LoadBtnClick(TObject *Sender); + void __fastcall PBoxMouseDown(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + void __fastcall PCClick(TObject *Sender); + void __fastcall PBoxMouseMove(TObject *Sender, TShiftState Shift, + int X, int Y); + void __fastcall PBoxMouseUp(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + void __fastcall PaintBtnClick(TObject *Sender); + void __fastcall FormDestroy(TObject *Sender); + + void __fastcall PBoxCSPaint(TObject *Sender); + void __fastcall PBoxCSMouseDown(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + void __fastcall PBoxCSMouseUp(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + void __fastcall CBSizeChange(TObject *Sender); + + void __fastcall PBoxTextPaint(TObject *Sender); + void __fastcall SBPasteClick(TObject *Sender); + void __fastcall SBCopyClick(TObject *Sender); + void __fastcall SBColAdjClick(TObject *Sender); + void __fastcall SBClipClick(TObject *Sender); + void __fastcall PBoxLPaint(TObject *Sender); + void __fastcall PBoxUPaint(TObject *Sender); + void __fastcall PBoxLMouseDown(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + void __fastcall PBoxLDragDrop(TObject *Sender, TObject *Source, int X, + int Y); + void __fastcall PBoxLDragOver(TObject *Sender, TObject *Source, int X, + int Y, TDragState State, bool &Accept); + void __fastcall PBoxUDragOver(TObject *Sender, TObject *Source, int X, + int Y, TDragState State, bool &Accept); + void __fastcall PBoxUDragDrop(TObject *Sender, TObject *Source, int X, + int Y); + + void __fastcall UDLClick(TObject *Sender, TUDBtnType Button); + void __fastcall FormKeyDown(TObject *Sender, WORD &Key, + TShiftState Shift); + void __fastcall PBoxUMouseDown(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); +private: + int m_DisEvent; + + Graphics::TBitmap *pBitmap; + CDrawText m_Text; + + int m_XW; + int m_YW; + int m_X; + int m_Y; + int m_X2; + int m_Y2; + int m_Size; + void __fastcall DrawCursor(void); + void __fastcall BtnClick(int n); + void __fastcall UpdateSB(void); + + Graphics::TBitmap *m_pCustomBmp; + int m_MIndex; + void __fastcall UpdateCustom(void); + void __fastcall UpdateText(void); + void __fastcall UpdateCBSize(int xw, int yw); + DYNAMIC void __fastcall AdjustSize(void); + + void __fastcall UpdateSrc(BOOL fSize); + + AnsiString m_ListName; + Graphics::TBitmap *m_pUserBmp; + Graphics::TBitmap *m_pListBmp; + void __fastcall UpdateUser(void); + int __fastcall IsMList(int n); + int __fastcall IsSameBitmap(Graphics::TBitmap *pDest, Graphics::TBitmap *pSrc, int fSize); + + HWND m_hClipNext; +public: + virtual __fastcall TBitMaskDlg(TComponent* AOwner); + + int __fastcall Execute(Graphics::TBitmap *pBmp, CDrawText *pText); + +#define CM_EDITEXIT WM_USER+404 +protected: + void __fastcall OnEditExit(TMessage Message); + void __fastcall OnDrawClipboard(TMessage Message); + void __fastcall OnChangeCbChain(TMessage Message); + +BEGIN_MESSAGE_MAP + MESSAGE_HANDLER(CM_EDITEXIT, TMessage, OnEditExit) + MESSAGE_HANDLER(WM_DRAWCLIPBOARD, TMessage, OnDrawClipboard) + MESSAGE_HANDLER(WM_CHANGECBCHAIN, TMessage, OnChangeCbChain) +END_MESSAGE_MAP(TForm) +}; +//---------------------------------------------------------------------------- +//extern PACKAGE TBitMaskDlg *BitMaskDlg; +//---------------------------------------------------------------------------- +#endif + diff --git a/CItems/CUSTOM.TXT b/CItems/CUSTOM.TXT new file mode 100644 index 0000000..2f04d68 --- /dev/null +++ b/CItems/CUSTOM.TXT @@ -0,0 +1,383 @@ +MMSSTVカスタムアイテム + + 本書ではMMSSTVのテンプレートに埋めこみ可能なカスタムアイテムについて解説します。 + +======================== +○カスタムアイテムの概要 +======================== + カスタムアイテムはMMSSTVのテンプレートに埋めこみ可能な任意のオブジェクトを実装するための機能です。カスタムアイテムにはMMSSTVの組み込みアイテムと同じように、受信履歴イメージの自動参照やマクロテキストの自動展開の機能を持たせることもできます。またストックテンプレートやファイルに保存することができ、既存の組み込みアイテムとまったく同じように扱う事ができます。 + + カスタムアイテムのすべての機能は、特定のインターフェースを持ったDLLファイルで提供されます。MMSSTVはユーザーが選択したDLLファイルを動的に読みこみそれを実行するための仕組みを持つだけです。アイテムの動作や外観、編集のためのユーザーインターフェースは、すべてそのDLL内に実装するコードによって決定されます。 + + カスタムアイテムの利点はMMSSTVの本体プログラムを変更することなく、テンプレートの機能を外部からいくらでも拡張できる点です。DLLファイルは単にいずれかのフォルダ(通常はMMSSTVフォルダ)に存在するだけで良く、OLEカスタムコントロール(ActiveX)のようなWindowsレジストリへの登録は必要ありません。 + + カスタムアイテムには以下の3種類が存在します。 + +1.スタティックイメージ +~~~~~~~~~~~~~~~~~~~~~~ + テンプレート内にイメージを描画します。描画するイメージはそのオブジェクトが保持するプロパティに従い、MMSSTVの受信履歴イメージやマクロ変換テキストは参照しません。MMSSTVテンプレートのOLEオブジェクトと類似した動作になります。 + +2.アクティブイメージ +~~~~~~~~~~~~~~~~~~~~ + テンプレート内にイメージを描画します。描画するイメージはそのオブジェクトが保持するプロパティおよび、MMSSTVの受信履歴イメージを参照して作成されます。MMSSTVテンプレートの画像アイテムを拡張した動作になります。 + +3.アクティブテキスト +~~~~~~~~~~~~~~~~~~~~ + テンプレート内に文字イメージを描画します。描画するイメージはそのオブジェクトが保持するプロパティおよび、MMSSTVのマクロ変換テキストを参照して作成されます。MMSSTVテンプレートの文字アイテムを拡張した動作になります。 + + + カスタムアイテムを作成する開発環境は、Windowsの32bitコードのDLLファイルが作成できるものならば何でも構いません。DLLファイルがエクスポートするファンクションに関しては、本書の「エクスポートファンクション」および「ファンクションの解説」の項を参照して下さい。 + + +========== +○アイコン +========== + カスタムアイテムのDLLファイルは、そのアイテムの特徴を現した32x32のアイコンのリソースを保持してください。 + MMSSTVはフォルダのサムネイルのファイルの種類で「カスタムアイテム」が選択されたとき、DLLファイルから(1つ目の)アイコンをロードしてそれをサムネイルに表示します。 + + このアイコンは必須ではありませんが、フォルダのサムネイルからテンプレートにアイテムをドロップする際の助けになります。 + + +============================ +○エクスポートファンクション +============================ + カスタムアイテムのDLLファイルは、以下のファンクションをエクスポートします。 + +extern "C" __declspec(dllexport) void mcmLanguage(long lang); +extern "C" __declspec(dllexport) void mcmAboutDialog(HWND hWnd); +extern "C" __declspec(dllexport) HANDLE mcmCreateObject(const BYTE *pStorage, DWORD Size); +extern "C" __declspec(dllexport) void mcmDeleteObject(HANDLE hObj); +extern "C" __declspec(dllexport) long mcmGetItemType(HANDLE hObj); +extern "C" __declspec(dllexport) void mcmPos(HANDLE hObj, DWORD pos, DWORD size, DWORD tsize); +extern "C" __declspec(dllexport) const BYTE* mcmCreateStorage(HANDLE hObj, LPDWORD pSize); +extern "C" __declspec(dllexport) void mcmDeleteStorage(HANDLE hObj, const BYTE *pStorage); +extern "C" __declspec(dllexport) long mcmEdit(HANDLE hObj, HWND hWnd); +extern "C" __declspec(dllexport) long mcmFont(HANDLE hObj, HWND hWnd); +extern "C" __declspec(dllexport) DWORD mcmGetOrgSize(HANDLE hObj); +extern "C" __declspec(dllexport) LPCSTR mcmGetUserText(HANDLE hObj); +extern "C" __declspec(dllexport) HBITMAP mcmUpdateText(HANDLE hObj, HBITMAP hbDest, LPCSTR pText); +extern "C" __declspec(dllexport) HBITMAP mcmUpdateImage(HANDLE hObj, HBITMAP hbDest, HBITMAP hbSrc); +extern "C" __declspec(dllexport) void mcmSetDraft(HANDLE hObj, DWORD sw); + + エクスポートするファンクションは__cdecl呼び出し規約に従った、Cの修飾名でなければなりません。MMSSTVは例えばmcmAboutDialog()の場合、そのエントリポイントを"_mcmAboutDialog"または"mcmAboutDialog"の名前でDLL内から探します。 + + 必須のファンクションは、mcmCreateObject()、mcmDeleteObject()および、mcmGetItemType()です。これ以外のファンクションはそのアイテムの動作に必要がなければエクスポートする必要はありません。 + + +====================== +○ファンクションの解説 +====================== + +void mcmLanguage(long lang) +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +[パラメータ] lang : 0-日本語, 1-英語 +[解説] + 現在のMMSSTVの動作言語モードが設定されます。アイテムのユーザーインターフェースで使用する言語は、ここで設定された言語とできるだけ一致させてください。または日本語をサポートしない場合、この値に関係なく常に英語を使用しても構いません。 + + +void mcmAboutDialog(HWND hWnd) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +[パラメータ] hWnd : MMSSTVウインドウのハンドル +[解説] + そのアイテムの名前やバージョン番号を表示するダイアログボックスを表示します。ダイアログボックスはhWndを親ウインドウとしてモーダル状態で実行します。 + このファンクションは、MMSSTVのテンプレートで、「オブジェクト」->「プロパティ」が選択された時に呼び出されます。 + + +HANDLE mcmCreateObject(const BYTE *pStorage, DWORD Size) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +[パラメータ] pStorage: ストレージのポインタ + Size : ストレージのサイズ +[戻り値] + 作成したオブジェクトのハンドル +[解説] + アイテムのオブジェクトを1つ作成します。作成するオブジェクトはpStorageの内容で初期化されなければなりません。ストレージはオブジェクトを再構築するためにファイルにシリアライズされるデータです。詳細はmcmCreateStorage()を参照して下さい。 + MMSSTVはこのファンクションを呼び出した直後、pStorageの領域を自動的に削除します。したがってそのポインタ自体をオブジェクト内に保持してはいけません。 + + MMSSTVがオブジェクトを新規に作成する場合、pStorageはNULLで呼び出されます。この場合、そのオブジェクトはデフォルトで初期化されなければなりません。 + + MMSSTVはhObjの内容について一切関知しません。従ってhObjにはどのような構造のデータが格納されていても構いません。ただしhObjはアイテムを識別するための0以外のユニークな値でなければなりません。 + 一般的な方法として例えば動的に構築した構造体またはクラスのポインタを返す次のようなコードを記述します。 + +[Cの場合] + typedef struct { + : + : + }SMyObj; + + SMyObj *pObj = (SMyObj *)malloc(sizeof(SMyObj)); + if( pObj != NULL ){ + InitMyObject(pObj); + CreateMyObject(pObj, pStorage, Size); + } + return (HANDLE)pObj; + +[C++の場合] + class CMyObj { + : + : + }; + + CMyObj *pObj = new CMyObj; + if( pObj != NULL ) pObj->Create(pStorage, Size); + return (HANDLE)pObj; + + + オブジェクトは可能な限りGDIリソースを節約してください。例えばデバイスコンテキストそのものや、ビットマップ、パレット、フォント、ブラシ、ペンなどのGDIリソースを描画時以外に大量に保持しないようにして下さい。これらを大量に保持すると、特にWin95/98/SE/ME系のOSの場合に問題を引き起こす可能性があります。 + + +void mcmDeleteObject(HANDLE hObj) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +[パラメータ] hObj : オブジェクトのハンドル +[解説] + mcmCreateObject()で作成したオブジェクトを削除します。hObjが保持するメモリやリソースはすべて解放されなければなりません。 + 一般的な方法として例えば動的に構築した構造体またはクラスを削除する次のようなコードを記述します。 + +[Cの場合] + SMyObj *pObj = (SMyObj *)hObj; + DeleteMyObj(pObj); + free(pObj); + +[C++の場合] + CMyObj *pObj = (CMyObj *)hObj; + delete pObj; + + +DWORD mcmGetItemType(HANDLE hObj) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +[パラメータ] hObj : オブジェクトのハンドル +[戻り値] アイテム種別を表す32bitの値 + 00ao00uth + t : 種別 + 0-スタッティクイメージ + 1-アクティブイメージ + 2-アクティブテキスト + o : 表示 + 0-通常表示 + 1-オーバーレイ表示 + u : 更新 + 0-サイズ変更時 + 1-サイズ変更時とアイテム移動時 + a : 配置 + 0-左上詰め, 1-右上詰め, 2-左下詰め + 3-右下詰め, 4-横中央, 8-縦中央 +[解説] + hObjのアイテム種別を返します。 + + MMSSTVはそのオブジェクトの種別をmcmCreateObjectを呼び出した直後、およびmcmEdit()を呼び出した直後に読み取ります。オブジェクトはその種別をmcmEdit()内のユーザーインターフェースで変更しても構いません。 + + オーバーレイ表示(o)に関しては本書の「テンプレートの背景色とオーバーレイ」の項を参照して下さい。 + + 更新(u)は、テンプレート上でのアイテム枠のドラッグ操作により、アイテムの表示位置が変更された際に、mcmUpdateText()およびmcmUpdateImage()を呼び出すかどうかを指定します。 + + 配置(a)はそのアイテムをテンプレート上でどのように配置するかを指定します。mcmUpdateImage()およびmcmUpdateText()で引き渡されるhbDestのサイズを変更しない場合、テンプレート上での配置は変化せずMMSSTVはこのフラグを無視します。しかしmcmUpdateImage()およびmcmUpdateText()内で新しいビットマップを作成しそのハンドルを返す場合、MMSSTVは表示サイズが変更されたアイテムをテンプレート上にどのように再配置するかをこのフラグにより決定します。 + + +const BYTE* mcmCreateStorage(HANDLE hObj, LPDWORD pSize) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +[パラメータ] hObj : オブジェクトのハンドル + pSize : ストレージのサイズを格納するポインタ +[戻り値] 作成したストレージのポインタ +[解説] + ストレージを1つ作成しそのポインタを返します。pSizeのアドレスに作成したストレージのバイト数を格納して下さい。 + + MMSSTVはテンプレートファイル(MTM, MTI)にそのアイテムを保存する際、このファンクションを呼び出して、返されたストレージを保存します。作成するストレージの構造は自由ですが、必ず2次記憶メディアに保存可能な形式でなければなりません。例えばストレージ内にポインタを格納してはなりません。 + + MMSSTVがテンプレートファイルをロードする際、mcmCreateObject()のpStorageで引き渡すストレージは、このファンクションで作成されたストーレージと同じ内容です。従って作成するストレージは、必ずオブジェクトが再構築できる形式でなければなりません。 + + ストレージの構造が変化した場合に予期しない動作に陥らないために、ストレージ内にそのバージョン番号を格納するのは良いアイデアです。 + + ストレージは動的な領域、または(オブジェクト内の)静的な領域のいずれに作成しても構いません。MMSSTVは返されたストレージをファイルに保存した直後、必ずmcmDeleteStorage()を呼び出して、動的に作成されたストレージを削除する機会を提供します。ストレージを動的に作成しなかった場合、mcmDeleteStorage()では何もする必要はありません。 + + +void mcmDeleteStorage(HANDLE hObj, const BYTE *pStorage) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +[パラメータ] hObj : オブジェクトのハンドル + pStorage: ストレージのポインタ +[解説] + mcmCreateStorage()で作成したストレージを削除します。 + + +DWORD mcmEdit(HANDLE hObj, HWND hWnd) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +[パラメータ] hObj : オブジェクトのハンドル + hWnd : MMSSTVウインドウのハンドル +[戻り値] + TRUE : オブジェクトが変更された時。 + FALSE : オブジェクトが変更されなかった時。 +[解説] + オブジェクトを編集するためのダイアログボックスを表示します。ダイアログボックスはhWndを親ウインドウとしてモーダル状態で実行します。 + + 戻り値がTRUEの場合、MMSSTVはそのアイテムの外観を更新するために、mcmUpdateImage()またはmcmUpdateText()を呼び出します。 + + このファンクションは、MMSSTVのテンプレートで、そのアイテムがダブルクリックされるか、または「色の設定」ボタンが押された時に呼び出されます。 + + +DWORD mcmFont(HANDLE hObj, HWND hWnd) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +[パラメータ] hObj : オブジェクトのハンドル + hWnd : MMSSTVウインドウのハンドル +[戻り値] + TRUE : オブジェクトが変更された時。 + FALSE : オブジェクトが変更されなかった時。 +[解説] + オブジェクトのフォントを変更するためのダイアログボックスを表示します。ダイアログボックスはhWndを親ウインドウとしてモーダル状態で実行します。 + このファンクションは、アクティブテキストの場合に、MMSSTVのテンプレートで、「フォント設定」ボタンが押された時に呼び出されます。 + + 戻り値がTRUEの場合、MMSSTVはそのアイテムの外観を更新するために、mcmUpdateText()を呼び出します。 + + このファンクションは必須ではありませんが、オブジェクトがフォントを持つ場合はできるだけエクスポートするようにして下さい。これによりユーザーはフォントの変更をワンタッチで行うことができます。このファンクションがエクスポートされていない場合、MMSSTVは代わりにmcmEdit()を呼び出します。 + + +DWORD mcmGetOrgSize(HANDLE hObj) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +[パラメータ] hObj : オブジェクトのハンドル +[戻り値] + 下位16ビット: 横幅 + 上位16ビット: 縦幅 +[解説] + アイテムの固有のサイズを返します。 + + アイテムが固有のサイズを持つ場合、テンプレートに表示されているサイズ(mcmUpdateImage()およびmcmUpdateText()のhbDestのサイズ)は必ずしもそれに一致しているとは限りません。 + MMSSTVはテンプレートのポップアップメニューの「アスペクト比を保つ」および「オリジナルのサイズに戻す」の2つの機能を実装するために、このファンクションを呼び出します。 + + アイテムが固有のサイズを持たない場合、mcmUpdateImage()のhbSrcのサイズ、またはmcmUpdateText()のhbDestのサイズを保持しておき、それを返すようにして下さい。 + + +void mcmPos(HANDLE hObj, DWORD pos, DWORD size, DWORD tsize) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +[パラメータ] hObj : オブジェクトのハンドル + pos : テンプレート上の位置(X:下位16bit, Y:上位16bit) + size : テンプレート上のサイズ(X:下位16bit, Y:上位16bit) + tsize : テンプレートのサイズ(X:下位16bit, Y:上位16bit) +[解説] + アイテムが表示されるテンプレート上の位置、サイズおよび現在のテンプレートのサイズの情報が設定されます。 + このファンクションは必須ではありませんが、テンプレート上の位置によってビットマップの更新処理を変更する必要がある場合にエクスポートします。 + + +LPCSTR mcmGetUserText(HANDLE hObj) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +[パラメータ] hObj : オブジェクトのハンドル +[戻り値] オブジェクトが保持するユーザ定義文字列のポインタ +[解説] + ユーザー定義文字列を返します。このファンクションは、アクティブテキストの場合にのみ呼び出されます。 + + 定義文字列とはユーザが設定したマクロを含む文字列です。通常この文字列はmcmEdit()で編集できるようにします。 + MMSSTVはmcmUpdateText()を呼び出す際、必ず直前にmcmGetUserText()を呼び出してユーザー定義文字列を参照します。 + + MMSSTVは返された定義文字列をマクロ変換し、それをmcmUpdateText()のpTextに引き渡します。その際行うマルチバイト文字コード処理は、常にそのPCのコードページに依存する動作になります。例えば英語版Windows上ではマルチバイト文字コード処理は行われません。 + + +HBITMAP mcmUpdateText(HANDLE hObj, HBITMAP hbDest, LPCSTR pText) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +[パラメータ] hObj : オブジェクトのハンドル + hbDest : 描画用ビットマップのハンドル + pText : 描画する文字列 +[戻り値] 新規に作成した描画用ビットマップのハンドル +[解説] + pTextの内容で描画用のイメージを作成します。 + このファンクションは、アクティブテキストの場合にのみ呼び出されます。 + + hbDestは必ず24bitフォーマットのDIBです。新規に描画用ビットマップを作成した場合、hbDestをDeleteObject()関数で削除し、作成したビットマップのハンドルを返して下さい。描画用ビットマップとしてhbDestを更新した場合、必ずNULLを返して下さい。新規に作成するビットマップはDDBでも構いませんが、できるだけDIBにして下さい。テンプレート内に表示されるイメージのサイズはhbDestのサイズまたは返されたビットマップのサイズになります。 + + MMSSTVはアイテムの外観を更新する必要があると判断した時、このファンクションを呼び出します。 + + +[例] + 例えばpTextを単純にhbDestに展開するコードは次のようになります。 + + extern "C" __declspec(dllexport) + HBITMAP mcmUpdateText(HANDLE hObj, HBITMAP hbDest, LPCSTR pText) + { + DIBSECTION ds; + if( !GetObject(hbDest, sizeof(DIBSECTION), &ds) ) + return NULL; + + HDC hdcScreen = CreateDC("DISPLAY", NULL, NULL, NULL); + HDC hdcDest = CreateCompatibleDC(hdcScreen); + HBITMAP hbOld = SelectObject(hdcDest, hbDest); + TextOut(hdcDest, 0, 0, pText, strlen(pText)); + SelectObject(hdcDest, hbOld); + DeleteDC(hdcDest); + DeleteDC(hdcScreen); + return NULL; + } + + +HBITMAP mcmUpdateImage(HANDLE hObj, HBITMAP hbDest, HBITMAP hbSrc) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +[パラメータ] hObj : オブジェクトのハンドル + hbDest : 描画用ビットマップのハンドル + hbSrc : 履歴画像ビットマップのハンドル +[戻り値] 新規に作成した描画用ビットマップのハンドル +[解説] + 描画用イメージを作成します。 + このファンクションは、スタティックイメージまたはアクティブイメージの場合に呼び出されます。スタティックイメージの場合hbSrcは必ずNULLで呼び出されます。 + + hbDestおよびhbSrcは必ず24bitフォーマットのDIBです。新規に描画用ビットマップを作成した場合、hbDestをDeleteObject()関数で削除し、作成したビットマップのハンドルを返して下さい。描画用ビットマップとしてhbDestを更新した場合、必ずNULLを返して下さい。新規に作成するビットマップはDDBでも構いませんが、できるだけDIBにして下さい。テンプレート内に表示されるイメージのサイズはhbDestのサイズまたは返されたビットマップのサイズになります。 + + MMSSTVはアイテムの外観を更新する必要があると判断した時、このファンクションを呼び出します。 + + +[例] + 例えば現在のWindowsスクリーンをhbDestに伸縮展開するコードは次のようになります。 + + extern "C" __declspec(dllexport) + HBITMAP mcmUpdateImage(HANDLE hObj, HBITMAP hbDest, HBITMAP hbSrc) + { + DIBSECTION ds; + if( !GetObject(hbDest, sizeof(DIBSECTION), &ds) ) + return NULL; + + HDC hdcScreen = CreateDC("DISPLAY", NULL, NULL, NULL); + HDC hdcDest = CreateCompatibleDC(hdcScreen); + HBITMAP hbOld = SelectObject(hdcDest, hbDest); + SetStretchBltMode(hdcDest, HALFTONE); + StretchBlt(hdcDest, 0, 0, + ds.dsBm.bmWidth, ds.dsBm.bmHeight, + hdcScreen, 0, 0, + GetSystemMetrics(SM_CXSCREEN), + GetSystemMetrics(SM_CYSCREEN), + SRCCOPY); + SelectObject(hdcDest, hbOld); + DeleteDC(hdcDest); + DeleteDC(hdcScreen); + return NULL; + } + + +void mcmSetDraft(HANDLE hObj, DWORD sw) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +[パラメータ] hObj : オブジェクトのハンドル + sw : 0-詳細描画, 1-ドラフト描画 +[解説] + mcmUpdateText()およびmcmUpdateImage()でビットマップを更新(または作成)する方法が設定されます。 + 「ドラフト描画」が指定された場合、mcmUpdateText()およびmcmUpdateImage()で更新するビットマップは、その品質よりも速度が要求されます。「ドラフト描画」が設定されるのはストックテンプレート上でアイテムが描画される際に、MMSSTVで「高速描画」のチェックが付けられている場合だけです。 + MMSSTVはオブジェクトを作成後このフラグを初期化しません。従ってオブジェクトの初期値は必ず「詳細描画」の状態にして下さい。 + + ビットマップの更新に時間を要しない場合、ドラフト描画をサポートする必要はありません。その場合、このフラグを無視するか、またはこのファンクションそのものをエクスポートする必要はありません。 + + +==================================== +○テンプレートの背景色とオーバーレイ +==================================== + カスタムアイテムはMMSSTVのテンプレートに一旦描画されます。その後テンプレートと送信素材画像が重畳されて送信画像が作成されます。 + したがってアイテムのオーバーレイの状態に関係なく、常にテンプレートは送信素材画像に対してオーバーレイです。その時の透過色はテンプレートの背景色としてユーザが設定します。つまりアイテムがオーバーレイでない場合でも、アイテム内にテンプレートの背景色と同じ色が存在する場合、その色はすべて透過になります。 + ただし複数のアイテムがテンプレート上に重なった状態では、アイテムのオーバーレイを指定しないと、アイテム間で透過されません。 + + テンプレートの背景色は、mcmUpdateImage()およびmcmUpdateText()のhbDestの初期色で得ることができます。この色は動作時のビデオモードでの純色に調整されています。従ってそのアイテムをオーバーレイ描画する場合、そのアイテムの透過色をテンプレートの背景色に一致させるのが最も好ましい方法です。 + + 一方、アイテムをオーバーレイで描画しない場合、アイテム内のすべての色はテンプレートの背景色と同じ色にしてはなりません。またオーバーレイで描画する場合でも、透過色以外の部分はテンプレートの背景色と同じ色にしてはなりません。 + 例えばmcmUpdateImageで、hbSrcからhbDestを作成する場合、hbDestに格納する色をテンプレートの背景色と一致させないようにします。この最も簡単な方法は一致する色の値を1値だけ変化させます。この方法ではビデオモードがフルカラーの場合、アイテム内のすべての色が送信画像に展開されます。ただしビデオモードが16bitカラーの場合、色の値を1値だけ変化させても結果として同じ色になる可能性が高いので、ユーザーがテンプレートの背景色を変化させなければならない場合があります。 + + +======================== +○カスタムアイテムの配布 +======================== + あなたが作成したカスタムアイテムは、あなたの裁量で自由に公開配布して下さい。 + + カスタムアイテムのDLLファイルはMMSSTV以外から利用されることはありません。したがってDLLファイルは通常はMMSSTVフォルダ内にインストールします。インストールプログラムで配布する場合、インストール先のフォルダが選択できるようになっているのが好ましいと思います。 + + 配布するカスタムアイテムが大量の他のファイルを保持、または作成する場合、専用のフォルダにそれらをインストールし、そのDLLファイルのショートカット(.LNK)をMMSSTVフォルダ内に1つだけ作成するのは良い考えです。 + + +73, Mako diff --git a/CItems/ECUSTOM.TXT b/CItems/ECUSTOM.TXT new file mode 100644 index 0000000..027bf3f --- /dev/null +++ b/CItems/ECUSTOM.TXT @@ -0,0 +1,371 @@ +MMSSTV Custom Item + March 24, 2002 + Written by JE3HHT Makoto Mori + Translated into English by JA7UDE Nob Oba + +This document explains how to make the MMSSTV custom item. + + +======================== +Overview of the custom item +======================== + + The custom item is an implementation scheme of an object that can be embedded in the MMSSTV template. The custom item can have various functions, such as the automatic reference to the receive history images and the automatic conversion of macro texts. The custom item is stored in the stock template or file so that it can be treated as a conventional embedded item. + + All the functions provided in the custom item are offered as a DLL file, which has the specific interface to MMSSTV. MMSSTV merely loads the DLL on-the-fly and runs it. The operation, the appearance, and the user interface of the custom item are all defined in the DLL. + + The biggest advantage of the custom item is high expandability. Using the custom item, the user can add any kind of functions to the MMSSTV template without modifying the MMSSTV program. The DLL file can be stored in any folder (normally in the MMSSTV directory), and does not need to be registered in Windows registry. + + The custom items are categorized into the following three types: + +1. Static image + The static image is displayed as an image in the template. The image is controlled by its own property; it does not refer to the MMSSTV receive history or the macro conversion text. It is similar to the OLE object of the MMSSTV template. + +2. Active image + The active image is displayed as an image in the template. The image is controlled by its own property and the MMSSTV receive history. It offers an extended function of the image item in the MMSSTV template. + +3. Active text + The active text is shown as a text image in the template. The text image is controlled by its own property and the MMSSTV macro conversion. It offers an extended function of the text item in the MMSSTV template. + + To make a custom item, any development suite that generates Windows 32-bit DLL can be used. For further information, refer to the sections of Export Function and Function Details in this document. + + +========== +Icon +========== + +The custom item DLL should include a 32x32 icon resource, which represents the feature of the item. MMSSTV loads and displays the (first) icon in the thumbnail window when the custom item is selected as the file type in the folder thumbnail. + +The icon is not a must, but it makes the drag&drop operation easier for the user. + + +============================ +Export Function +============================ + +The custom item DLL exports the following functions: + +extern "C" __declspec(dllexport) void mcmLanguage(long lang); +extern "C" __declspec(dllexport) void mcmAboutDialog(HWND hWnd); +extern "C" __declspec(dllexport) HANDLE mcmCreateObject(const BYTE *pStorage, DWORD Size); +extern "C" __declspec(dllexport) void mcmDeleteObject(HANDLE hObj); +extern "C" __declspec(dllexport) long mcmGetItemType(HANDLE hObj); +extern "C" __declspec(dllexport) void mcmPos(HANDLE hObj, DWORD pos, DWORD size, DWORD tsize); +extern "C" __declspec(dllexport) const BYTE* mcmCreateStorage(HANDLE hObj, LPDWORD pSize); +extern "C" __declspec(dllexport) void mcmDeleteStorage(HANDLE hObj, const BYTE *pStorage); +extern "C" __declspec(dllexport) long mcmEdit(HANDLE hObj, HWND hWnd); +extern "C" __declspec(dllexport) long mcmFont(HANDLE hObj, HWND hWnd); +extern "C" __declspec(dllexport) DWORD mcmGetOrgSize(HANDLE hObj); +extern "C" __declspec(dllexport) LPCSTR mcmGetUserText(HANDLE hObj); +extern "C" __declspec(dllexport) HBITMAP mcmUpdateText(HANDLE hObj, HBITMAP hbDest, LPCSTR pText); +extern "C" __declspec(dllexport) HBITMAP mcmUpdateImage(HANDLE hObj, HBITMAP hbDest, HBITMAP hbSrc); +extern "C" __declspec(dllexport) void mcmSetDraft(HANDLE hObj, DWORD sw); + +All the export functions must comply with __cdecl C calling rule. For example, MMSSTV looks for entry point "_mcmAboutDiaglog" or "mcmAboutDialog" in the DLL when it calls mcmAboutDialog(). + +The DLL must have at least three functions exported: mcmCreateObject(), mcmDeleteObject(), and mcmGetItemType(). All the other functions are optional and do not have to be exported if not needed. + + +====================== +Function Details +====================== + +void mcmLanguage(long lang) +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +[Parameter] lang : 0 - Japanese, 1 - English +[Details] + It specifies the language mode of MMSSTV. The language used in the user interface of the custom item should conform to the language specified here. If the item does not support Japanese, simply use the English mode. + +void mcmAboutDialog(HWND hWnd) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +[Parameter] hWnd : MMSSTV window handle +[Details] + It displays a dialog box including the item name and the version number. The dialog box has hWnd as its parent window handle and appears as a modal window. + + This function is called when the user selects Object -> Property in the MMSSTV template. + +HANDLE mcmCreateObject(const BYTE *pStorage, DWORD Size) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +[Parameters] pStorage: pointer to the storage + Size : storage size +[Return value] + The handle of the created object + +[Details] + This function creates an item object. The object must be initialized with the content of pStorage. The Storage contains the data that is serialized into the file for reconstructing the object. For more information, refer to mcmCreateStorage(). + + MMSSTV automatically deletes the pStorage area after calling this function. Therefore, the pointer itself must not be stored in the pStorage area. + When MMSSTV newly creates the object, it calls the function with pStorage = NULL. In that case, the object must be initialized in default. + MMSSTV does not care about the content of hObj, and therefore hObj can have any kinds of data structure. However, hObj must be a unique number other than 0 to identify the item. + + Here is a typical example that returns the class pointer to the dynamically created structure. + +[Example in C] + typedef struct { + : + : + }SMyObj; + + SMyObj *pObj = (SMyObj *)malloc(sizeof(SMyObj)); + if( pObj != NULL ){ + InitMyObject(pObj); + CreateMyObject(pObj, pStorage, Size); + } + return (HANDLE)pObj; + +[Example in C++] + class CMyObj { + : + : + }; + + CMyObj *pObj = new CMyObj; + if( pObj != NULL ) pObj->Create(pStorage, Size); + return (HANDLE)pObj; + + The object should use as few GDI resources as possible. More specifically, the object should not have the device context itself, bitmap, palette, font, brush, or pen, except that they are needed in drawing operations. If the object keeps many GDI resources, it would cause resource shortage in Windows 95/98/SE/ME operating systems. + +void mcmDeleteObject(HANDLE hObj) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +[Parameter] hObj : Object handle +[Details] + This function deletes the object that have been created by mcmCreateObject(). All the memory and resources sustained by hObj must be released. + + Let me give you a typical code that deletes the dynamically created structure. + +[Example in C] + SMyObj *pObj = (SMyObj *)hObj; + DeleteMyObj(pObj); + free(pObj); + +[Example in C++] + CMyObj *pObj = (CMyObj *)hObj; + delete pObj; + + +DWORD mcmGetItemType(HANDLE hObj) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +[Parameter] hObj : Object handle +[Return value] 32-bit value that identifies the item type + 00ao00uth + t : type + + 0 - Static image + 1 - Active image + 2 - Active text + o : display + 0 - normal display + 1 - overlay display + u : update + 0 - updated on resize + 1 - updated on resize and move + a : alignment + 0 - upper_left, 1 - upper_right, 2 - lower_left + 3 - lower_right, 4 - horizontally_center, 8 - vertically_center + +[Details] + This function returns the type of hObj. + MMSSTV reads the object type immediately after calling mcmCreateObject() or mcmEdit(). The object can change its type in the user interface in mcmEdit(). + For details of the overlay display, refer to the section of Background color of the template and overlay. + The update (u) specifies whether mcmUpdateText() and mcmUpdateImage() are called or not when the item is moved in the template by dragging. + The alignment (a) specifies how the item is placed in the template. In case the size hbDest, which is passed through mcmUpdateImage() and mcmUpdateText(), is not changed, MMSSTV ignores this flag. If a new bitmap is created in mcmUpdateImage() and mcmUdateText(), and its handle is returned, MMSSTV uses this flag to determine how to place the new item in the template. + + +const BYTE* mcmCreateStorage(HANDLE hObj, LPDWORD pSize) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +[Parameters] hObj : object handle + pSize : pointer to the storage size +[Return value] pointer to the created storage +[Details] + This function creates a storage and returns a pointer to it. Put the storage size in byte to pSize. + + + When MMSSTV stores the item in the template file (MTM/MTI), it calls this function and saves the storage returned. Any type of storage can be used here, but it must take a form that can be stored in the secondary storage. For example, the pointer must not be included in the storage itself. + When MMSSTV load the templage file, it passes the same storage specified by pStorage in mcmCreateObject(). For this reason, the storage to be created must have the reconstructable form. + It is a good idea to have a version number available in the storage to avoid unexpected behavior in case the storage structure changes. + The storage can be allocated in dynamic or (in-object) static area. MMSSTV always calls mcmDeleteStorage() to offer a chance of deleting the dynamically allocated storage after it saves the storage to a file. If you do not dynamically allocate the storage, mcmDeleteStorage() need to do nothing. + + +void mcmDeleteStorage(HANDLE hObj, const BYTE *pStorage) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +[Parameters] hObj : object handle + pStorage: pointer to storage +[Details] + This function deletes the storage created by mcmCreateStorage(). + + +DWORD mcmEdit(HANDLE hObj, HWND hWnd) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +[Parameters] hObj : Object handle + hWnd : MMSSTV window handle +[Return value] + TRUE : Object changed + FALSE : Object not changed +[Details] + The function displays a dialog box to edit the object. The dialog box has hWnd as its parent window handle and appears as a modal window. + + If it returns TRUE, MMSSTV calls mcmUpdateImage() or mcmUpdateText() to update the item's appearance. + This function is called when the item is double clicked in the MMSSTV template or when the Set color button is pressed. + + +DWORD mcmFont(HANDLE hObj, HWND hWnd) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +[Parameters] hObj : object handle + hWnd : MMSSTV window handle +[Return value] + TRUE : Object changed + FALSE : Object not changed +[Details] + This function displays a dialog box to change the font. The dialog box has hWnd as its parent window handle and appears as a modal window. + + This function is called when the Set font button is pressed in the MMSSTV template. + If the return value is TRUE, MMSSTV calls mcmUpdateText() to update the item appearance. + This is not a mandatory function, but it should be exported if the item has a font, so that the font change is a snap. If the function is not exported, MMSSTV calls mcmEdit() instead. + + +DWORD mcmGetOrgSize(HANDLE hObj) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +[Parameter] hObj : object handle +[Return value] + Lower 16 bits: item width + Upper 16 bits: item height +[Details] + This function returns the item size in width and height. + If the item has its own size property, it may not always concur to the size displayed in the template (hbDest size in mcmUpdateImage(), mcmUpdateText()). MMSSTV call this function to perform the "Keep aspect ratio" and "Return to the original size" functions in the pop-up menu. + + If the item has no own size property, save hbSrc of mcmUpdateImage() or hbDest of mcmUpdateText() and return it in response. + + +void mcmPos(HANDLE hObj, DWORD pos, DWORD size, DWORD tsize) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +[Parameters] hObj : object handle + pos : position in the template (X: lower 16 bits, Y: upper 16 bits) + size : size in the template (X: lower 16 bits, Y: upper 16 bits) + tsize : template size (X: lower 16 bits, Y: upper 16 bits) +[Deltails] + This function specifies the position and size of the item, and also the template size. This is not a mandatory function, but it should be exported if the bitmap is updated in accordance with the position and size. + + +LPCSTR mcmGetUserText(HANDLE hObj) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +[Parameter] hObj : object handle +[Return value] pointer to the user-defined string in the object +[Details] + This function returns the user-defined character string. It is called for the active text. + + The user-defined string is the character string that contains user-specified macro. The string should be edited by mcmEdit(). MMSSTV always calls mcmGetUserText() just before calling mcmUpdateText() in order to refer to the user-define string. + MMSSTV does the macro conversion on the returned string and passes it to pText of mcmUpdateText(). The multi-byte code conversion depends on the code page of the PC. On English Windows operating system, for instance, the multi-byte conversion does not take place. + + +HBITMAP mcmUpdateText(HANDLE hObj, HBITMAP hbDest, LPCSTR pText) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +[Parameters] hObj : object handle + hbDest : handle of drawing bitmap + pText : character string to be drawn +[Return value] handle of newly created drawing bitmap +[Details] + This function creates a drawing image based on the content of pText. This function is called only in active text handling. + + + hbDest is always 24-bit format DIB. If you create a new drawing bitmap, you have to delete hbDest by using DeleteObject() and return the bitmap handle. If you update hbDest as the drawing bitmap, you have to return NULL. The bitmap can be DDB, but it is strongly recommended to use DIB. The image size shown in the template is the bitmap size or hbDest. + + MMSSTV call this function if it detects the need in updating the item appearance. + +[Example] + The following example code simply unfolds pText to hbDest. + + + extern "C" __declspec(dllexport) + HBITMAP mcmUpdateText(HANDLE hObj, HBITMAP hbDest, LPCSTR pText) + { + DIBSECTION ds; + if( !GetObject(hbDest, sizeof(DIBSECTION), &ds) ) + return NULL; + + HDC hdcScreen = CreateDC("DISPLAY", NULL, NULL, NULL); + HDC hdcDest = CreateCompatibleDC(hdcScreen); + HBITMAP hbOld = SelectObject(hdcDest, hbDest); + TextOut(hdcDest, 0, 0, pText, strlen(pText)); + SelectObject(hdcDest, hbOld); + DeleteDC(hdcDest); + DeleteDC(hdcScreen); + return NULL; + } + + +HBITMAP mcmUpdateImage(HANDLE hObj, HBITMAP hbDest, HBITMAP hbSrc) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +[Parameters] hObj : object handle + hbDest : handle of drawing picture + hbSrc : handle of history bitmap +[Retruen value] handle of newly created drawing bitmap +[Details] + This function creates a drawing bitmap. This function is called for static and active images. For the static image, hbSrc must be NULL. + hbDest and hbSrc are always 24-bit DIB. When you create a new drawing bitmap, delete hbDest using DeleteObject() and return the handle of the created drawing bitmap. If hbDest was updated as a drawing bitmap, return NULL. The bitmap can be DDB, but it is strongly recommended to use DIB. The image size in the templage becomes the size of hbDest or the returned bitmap size. + + MMSSTV calls this function if it detects the need in updating the item appearance. + + +[Example] + The following example code stretches and maps the current Windows screen to hbDest. + + + extern "C" __declspec(dllexport) + HBITMAP mcmUpdateImage(HANDLE hObj, HBITMAP hbDest, HBITMAP hbSrc) + { + DIBSECTION ds; + if( !GetObject(hbDest, sizeof(DIBSECTION), &ds) ) + return NULL; + + HDC hdcScreen = CreateDC("DISPLAY", NULL, NULL, NULL); + HDC hdcDest = CreateCompatibleDC(hdcScreen); + HBITMAP hbOld = SelectObject(hdcDest, hbDest); + SetStretchBltMode(hdcDest, HALFTONE); + StretchBlt(hdcDest, 0, 0, + ds.dsBm.bmWidth, ds.dsBm.bmHeight, + hdcScreen, 0, 0, + GetSystemMetrics(SM_CXSCREEN), + GetSystemMetrics(SM_CYSCREEN), + SRCCOPY); + SelectObject(hdcDest, hbOld); + DeleteDC(hdcDest); + DeleteDC(hdcScreen); + return NULL; + } + + +void mcmSetDraft(HANDLE hObj, DWORD sw) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +[Prameters] hObj : object handle + sw : 0 ? full drawing, 1 ? draft drawing +[Details] + This function specifies the update mode of the bitmap in mcmUpdateText() and mcmUpdateImage(). The draft drawing mode is used if Draft is checked in the main MMSSTV window. The draft drawing mode gives priority to the speed over the quality. + + MMSSTV does not initialize this flag after creating the object, and therefore the initial mode must be set to the full drawing mode. + You do not have to support the draft drawing mode if it does not take plenty of time to update the bitmap. Just ignore this flag or do not export this function. + + +==================================== +Background color of the template and overlay +==================================== + + The custom item is first drawn in the template, and then the template is superimposed to the TX material image in order to make up the SSTV TX picture. For this reason, the template is overlaid on the TX material image regardless of the overlay status of the item. The background color of the template is supposed to be the transparent color. Even if the item is not overlaid on the template, the color in the item, which is the same as the background color, could be transparent in that case. + + The background of the template can be obtained by the initial color in mcmUpdateImage() or mcmUpdateText(). The color is adjusted to the pure color in accordance with the video mode, and therefore it is desirable that the transparent color of the item be set to the background color of the template. + + If you do not overlay the item in the template, you must not use the template background color for the any part of the item. If you overlay the item in the template, you must not use the template background color for the any part except the transparent pixels. + For example, if you make hbDest from hbSrc by using mcmUpdateImage(), you do not use the template background color for hbDest. The simplest way to do this is to change the same color by 1. This is effective for the full color video because the change affects the whole TX image. The 16-bit color video, however, the change by 1 would not affect the result, and the user may have to change the template background color. + + +======================== +Distribution of the custom item +======================== + + You can freely distribute your custom items as you like. + + The DLL file of the custom item will be used only by MMSSTV. Thus, the DLL file normally is installed in the MMSSTV directory. It is preferable that the user can select the destination folder for the installation. + + If the custom item contains or generates many file, it is good idea to get them installed in another folder and make the shortcut (foo.lnk) in the MMSSTV directory. + +73, Mako + diff --git a/CItems/PERIMG/About.cpp b/CItems/PERIMG/About.cpp new file mode 100644 index 0000000..531a7a6 --- /dev/null +++ b/CItems/PERIMG/About.cpp @@ -0,0 +1,33 @@ +//--------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "About.h" +#include "ComLib.h" +//--------------------------------------------------------------------- +#pragma resource "*.dfm" +//TAboutDlg *AboutDlg; +#if UseHWND +__fastcall TAboutDlg::TAboutDlg(HWND hWnd) + : TForm(hWnd) +#else +__fastcall TAboutDlg::TAboutDlg(TComponent* AOwner) + : TForm(AOwner) +#endif +{ + if( sys.m_MsgEng ){ + Font->Name = "Arial"; + Font->Charset = ANSI_CHARSET; + Caption = TTL; + } + else { + Caption = TTLJ; + } + LVer->Caption = VER" "AUT; + HICON hIcon = ::LoadIcon(HInstance, (LPCSTR)8000); + TIcon *pIcon = new TIcon; + pIcon->Handle = hIcon; + Image->Picture->Icon = pIcon; +} +//--------------------------------------------------------------------- + diff --git a/CItems/PERIMG/About.dfm b/CItems/PERIMG/About.dfm new file mode 100644 index 0000000..0e17e4b Binary files /dev/null and b/CItems/PERIMG/About.dfm differ diff --git a/CItems/PERIMG/About.h b/CItems/PERIMG/About.h new file mode 100644 index 0000000..d021393 --- /dev/null +++ b/CItems/PERIMG/About.h @@ -0,0 +1,34 @@ +//---------------------------------------------------------------------------- +#ifndef OCRH +#define OCRH +//---------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ComLib.h" +//---------------------------------------------------------------------------- +class TAboutDlg : public TForm +{ +__published: + TButton *OKBtn; + TLabel *LVer; + TImage *Image; +private: +public: +#if UseHWND + virtual __fastcall TAboutDlg(HWND hWnd); +#else + virtual __fastcall TAboutDlg(TComponent* AOwner); +#endif +}; +//---------------------------------------------------------------------------- +//extern PACKAGE TAboutDlg *AboutDlg; +//---------------------------------------------------------------------------- +#endif diff --git a/CItems/PERIMG/Comlib.cpp b/CItems/PERIMG/Comlib.cpp new file mode 100644 index 0000000..917ee42 --- /dev/null +++ b/CItems/PERIMG/Comlib.cpp @@ -0,0 +1,1155 @@ +//--------------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "ComLib.h" +SYS sys; +// +//--------------------------------------------------------------------------- +//void mcmFunc(DWORD index, FARPROC pFunc) +// +//MMSSTV calls this function at the first time, if the function was exported. +//You can use following functions which are in the MMSSTV. +// +// index : Index of the function. +// pFunc : Address of the function. +// +//indexes and functions are as follows. +// +// 0 : HBITMAP (__cdecl *mmLoadImageMenu)(int sw, int xw, int yw); +// sw - 0 : Invoke image-clipper (xw and yw are the size of the bitmap) +// sw - 1 : no image-clipper (xw and yw will be ignored) +// +// 1 : HBITMAP (__cdecl *mmLoadImage)(LPCSTR pName); +// pName is a pathname of the image (BMP, JPG, WMF) +// +// 2 : HBITMAP (__cdecl *mmLoadHistImage)(void); +// +// 3 : int (__cdecl *mmSaveImageMenu)(HBITMAP hb, LPCSTR pName, LPCSTR pFolder); +// pName is a filename of the image (BMP, JPG) +// pFolder is a folder name (if it is NULL, MMSSTV uses a default) +// +// 4 : int (__cdecl *mmSaveImage)(HBITMAP hb, LPCSTR pName); +// pName is a pathname of the image (BMP, JPG) +// +// 5 : HBITMAP (__cdecl *mmPasteImage)(int sw, int xw, int yw); +// sw - 0 : Invoke image-clipper (xw and yw are the size of the bitmap) +// sw - 1 : no image-clipper (xw and yw will be ignored) +// +// 6 : int (__cdecl *mmGetMacKey)(LPSTR pDest, int cbDest); +// Invoke macro dialog box and can choose keyword +// +// 7 : int (__cdecl *mmConvMac)(LPSTR pDest, LPCSTR pSrc, int cbDest); +// Convert macro keyword (pSrc) to the text (pDest) +// +// 8 : HBITMAP (__cdecl *mmCreateDIB)(int xw, int yw); +// Create 24bit DIB +// +// 9 : void (__cdecl *mmMultProc)(void); +// 10 : void (__cdecl *mmMultProcA)(void); +// Do decoding and encoding with the DSP in MMSSTV +// +// 11 : int (__cdecl *mmColorComp)(LPDWORD pCol); +// Invoke color components dialog and can choose a color component +// +extern "C" __declspec(dllexport) +void mcmFunc(DWORD fID, FARPROC pFunc) +{ + switch(fID){ + case 0: + sys.m_fLoadImageMenu = (mmLoadImageMenu)pFunc; + break; + case 2: + sys.m_fLoadHistImage = (mmLoadHistImage)pFunc; + break; + case 9: + sys.m_fMultProc = (mmMultProc)pFunc; + break; + case 13: + sys.m_fView = (mmView)pFunc; + break; + default: + break; + } +} +//--------------------------------------------------------------------------- +void __fastcall MultProc(void) +{ + if( sys.m_fMultProc ) sys.m_fMultProc(); +} +//--------------------------------------------------------------------------- +Graphics::TBitmap * __fastcall CreateBitmap(int xw, int yw) +{ + Graphics::TBitmap *pBitmap = new Graphics::TBitmap; + pBitmap->PixelFormat = pf24bit; + pBitmap->Width = xw; + pBitmap->Height = yw; + return pBitmap; +} +//--------------------------------------------------------------------------- +void __fastcall CopyBitmap(Graphics::TBitmap *pDest, Graphics::TBitmap *pSrc) +{ + pDest->Width = pSrc->Width; + pDest->Height = pSrc->Height; + pDest->Palette = NULL; + pDest->Canvas->Draw(0, 0, pSrc); +} +//--------------------------------------------------------------------------- +//アスペクト比を保持する +void __fastcall KeepAspect(int &sx, int &sy, int bx, int by) +{ + double ass = double(sx) / double(sy); + double asb = double(bx) / double(by); + if( asb < ass ){ // ソースの方が横長 + sx = (double(sy) * asb) + 0.5; + } + else { + sy = (double(sx) / asb) + 0.5; + } +} +//--------------------------------------------------------------------------- +//アスペクト比を保持する +void __fastcall KeepAspectCopy(Graphics::TBitmap *pDest, int xm, int ym, Graphics::TBitmap *pSrc, int mode) +{ + if( (xm < pSrc->Width) || (ym < pSrc->Height) ){ + KeepAspect(xm, ym, pSrc->Width, pSrc->Height); + pDest->Width = xm; + pDest->Height = ym; + pDest->Palette = NULL; + TRect tc; + tc.Left = tc.Top = 0; + tc.Right = xm; tc.Bottom = ym; + int Sop = ::SetStretchBltMode(pDest->Canvas->Handle, mode); + pDest->Canvas->StretchDraw(tc, pSrc); + ::SetStretchBltMode(pDest->Canvas->Handle, Sop); + } + else { + CopyBitmap(pDest, pSrc); + } +} +//--------------------------------------------------------------------------- +void __fastcall DrawBitmap(TPaintBox *pBox, Graphics::TBitmap *pBitmap) +{ + if( pBitmap == NULL ) return; + + if( (pBitmap->Width != pBox->Width)||(pBitmap->Height != pBox->Height) ){ + int xm = pBox->Width; + int ym = pBox->Height; + KeepAspect(xm, ym, pBitmap->Width, pBitmap->Height); + TRect rc; + rc.Left = 0; rc.Right = xm; + rc.Top = 0, rc.Bottom = ym; + int Sop = ::SetStretchBltMode(pBox->Canvas->Handle, HALFTONE); + pBox->Canvas->StretchDraw(rc, pBitmap); + ::SetStretchBltMode(pBox->Canvas->Handle, Sop); + } + else { + pBox->Canvas->Draw(0, 0, pBitmap); + } +} +// +// +//--------------------------------------------------------------------------- +// Matrix +// +// n[] = l[] * m[] +// +static void __fastcall Matrix(double l[4][4], double m[4][4], double n[4][4]) +{ + int i, j, k; + double d; + + for( i = 0; i < 4; i++ ){ + for( j = 0; j < 4; j++ ){ + for( k = 0, d = 0.0; k < 4; k++ ) d += l[i][k] * m[k][j]; + n[i][j] = d; + } + } +} +static void __fastcall Matrix(double l[3][3], double m[3][3], double n[3][3]) +{ + int i, j, k; + double d; + + for( i = 0; i < 3; i++ ){ + for( j = 0; j < 3; j++ ){ + for( k = 0, d = 0.0; k < 3; k++ ) d += l[i][k] * m[k][j]; + n[i][j] = d; + } + } +} +//--------------------------------------------------------------------------- +// Perspect +// +void __fastcall SetMatrix(double k[3][3], LPCSPERSPECT pPar, int xs, int ys) +{ + double l[4][4]; double m[4][4]; double n[4][4]; + double k1, k2, k3, k4, k5, k6, k7, k8, k9; + double u, v, w; + + u = pPar->rx * PI / 180; + v = pPar->ry * PI / 180; + w = pPar->rz * PI / 180; + memset(l, 0, sizeof(l)); memset(m, 0, sizeof(m)); + l[0][0] = 1.0/xs; l[1][1] = -1.0/xs; l[2][2] = 1.0; l[3][3] = 1.0; + m[0][0] = pPar->ax; m[1][1] = pPar->ay; m[2][2] = 1.0; m[3][3] = 1.0; + Matrix(l, m, n); + memset(l, 0, sizeof(l)); + l[0][0] = 1.0; l[1][1] = 1.0; l[2][2] = 1.0; + l[3][0] = pPar->px; l[3][1] = pPar->py; l[3][2] = pPar->pz; l[3][3] = 1.0; + Matrix(n, l, m); + memset(n, 0, sizeof(n)); + n[0][0] = cos(w); n[0][1] = sin(w); + n[1][0] = -n[0][1]; n[1][1] = n[0][0]; + n[2][2] = 1.0; n[3][3] = 1.0; + Matrix(m, n, l); + memset(m, 0, sizeof(m)); + m[0][0] = 1.0; m[1][1] = cos(u); m[1][2] = sin(u); + m[2][1] = -m[1][2]; m[2][2] = m[1][1]; m[3][3] = 1.0; + Matrix(l, m, n); + memset(l, 0, sizeof(l)); + l[0][0] = cos(v); l[0][2] = sin(v); l[1][1] = 1.0; + l[2][0] = -l[0][2]; l[2][2] = l[0][0]; l[3][3] = 1.0; + Matrix(n, l, m); + memset(n, 0, sizeof(n)); + n[0][0] = 1.0; n[1][1] = 1.0; n[2][2] = -1.0; n[3][2] = -pPar->v; n[3][3] = 1.0; + Matrix(m, n, l); + memset(m, 0, sizeof(m)); + m[0][0] = 1.0; m[1][1] = 1.0; m[2][2] = 1/pPar->s; m[2][3] = m[2][2]; + m[3][2] = -1.0; + Matrix(l, m, n); + memset(l, 0, sizeof(l)); + l[0][0] = xs; l[1][1] = -xs; l[2][2] = 1.0; l[3][3] = 1.0; + Matrix(n, l, m); + + k1 = m[0][3]; k2 = m[1][3]; k3 = m[3][3]; + k4 = m[0][0]; k5 = m[1][0]; k6 = m[3][0]; + k7 = m[0][1]; k8 = m[1][1]; k9 = m[3][1]; + + k[0][0] = k7*k2 - k8*k1; k[0][1] = k5*k1 - k4*k2; k[0][2] = k4*k8 - k7*k5; + k[1][0] = k8*k3 - k9*k2; k[2][0] = k9*k1 - k7*k5; k[1][1] = k6*k2 - k5*k3; + k[2][1] = k4*k3 - k6*k1; k[1][2] = k5*k9 - k8*k6; k[2][2] = k7*k6 - k4*k9; + + if( pPar->r != 0.0 ){ // simple rotation + double r = pPar->r * PI / 180.0; + double m[3][3]; + double z[3][3]; + memset(m, 0, sizeof(m)); + m[0][0] = cos(r); m[0][1] = sin(r); + m[1][0] = -m[0][1]; m[1][1] = m[0][0]; + m[2][2] = 1.0; + Matrix(k, m, z); + memcpy(k, z, sizeof(z)); + } +} +#define TMAX 400 +//--------------------------------------------------------------------------- +// Create mapping table +LPCDOUBLE __fastcall MapTable(int wave, int xs, int ys, double ks) +{ +#define VMAX 32767.0 +#define VMIN (1.0/VMAX) + LPDOUBLE pTbl, dp; + double d; + switch(wave){ + case 6: + { + double ky = 0.5 * PI / ys; + dp = pTbl = new double[ys*2]; + for( int y = -ys; y < ys; y++, dp++ ){ + d = cos(y * ky); + if( ABS(d) >= VMIN ){ + d = 1.0 * ks / d; + } + else { + d = VMAX; + } + *dp = d * 0.8; + } + } + break; + case 9: + { + dp = pTbl = new double[xs*2]; + double kd = xs * xs; + for( int x = -xs; x < xs; x++, dp++ ){ + d = kd - x * x; + if( d >= 0 ){ + d = sqrt(d); + *dp = (d > VMIN) ? xs * ks / d : VMAX; + } + else { + *dp = 1.0; + } + } + } + break; + case 14: + { + dp = pTbl = new double[ys*2]; + double kd = ys * ys; + for( int y = -ys; y < ys; y++, dp++ ){ + d = kd - y * y; + if( d >= 0 ){ + d = sqrt(d); + *dp = (d > VMIN) ? ys / d : VMAX; + } + else { + *dp = 1.0; + } + } + } + break; + case 10: + case 11: + { + dp = pTbl = new double[xs*2]; + double kd = xs * xs; + double kc = xs * 0.25; + for( int x = -xs; x < xs; x++, dp++ ){ + d = kd - x * x; + if( d >= 0 ){ + *dp = sqrt(d) * 0.5 * ks - kc; + if( wave == 10 ) *dp = -*dp; + } + else { + *dp = 1.0; + } + } + } + break; + case 7: + case 8: + case 12: + case 13: + case 15: + case 25: + pTbl = NULL; + break; + case 16: + { + dp = pTbl = new double[ys*2]; + double kc = ks * PI /(4 * ys); + double d; + for( int y = -ys; y < ys; y++, dp++ ){ + d = fabs(sin((y + ys)*kc)); + *dp = d > VMIN ? 1.0 / d : VMAX; + } + } + break; + case 17: + { + dp = pTbl = new double[ys*2]; + double kc = ks * PI /(4 * ys); + double d; + for( int y = ys-1; y >= -ys; y--, dp++ ){ + d = fabs(sin((y + ys)*kc)); + *dp = d > VMIN ? 1.0 / d : VMAX; + } + } + break; + case 22: + { + dp = pTbl = new double[ys*2]; + double kc = PI * (ks-0.85)/ (ys * ys); + double d; + for( int y = -ys; y < ys; y++, dp++ ){ + d = y * y * kc + (PI/4); + *dp = ABS(d) >= VMIN ? (1.0 / d) : VMAX; + } + } + break; + case 28: + case 29: + { + dp = pTbl = new double[xs*2]; + double kd = xs * xs; + double kc = ks*0.5 + 0.05; + for( int x = -xs; x < xs; x++, dp++ ){ + d = kd - x * x; + if( d >= 0 ){ + d = sqrt(d); + *dp = (d > VMIN) ? xs * kc / d : VMAX; + } + else { + *dp = 1.0; + } + } + } + break; + case 36: + { + dp = pTbl = new double[xs*2]; + double kx = PI * 0.5 / xs; + double ky = ys * ks * 0.125; + double ko = ks * ys * 0.1875; + for( int x = -xs; x < xs; x++, dp++ ){ + *dp = ky * ((xs-x) * kx) - ko; + } + } + break; + case 38: + { + dp = pTbl = new double[ys*2]; + double ky = PI * 0.5 / ys; + double kx = xs * ks * 0.25; + double ko = ks * xs * 0.375; + for( int y = -ys; y < ys; y++, dp++ ){ + *dp = kx * ((ys-y) * ky) - ko; + } + } + break; + default: + { + double kx = PI / xs; + double ky = ys * ks/ 8; + dp = pTbl = new double[xs*2]; + for( int x = -xs; x < xs; x++, dp++ ){ + switch(wave){ + case 1: + *dp = ky * sin(x * kx); + break; + case 2: + *dp = ky * sin(-x * kx); + break; + case 3: + *dp = ky * sin(x * kx + PI/2); + break; + case 4: + *dp = ky * sin(-x * kx - PI/2); + break; + case 5: + d = cos(x * kx * 0.5); + if( ABS(d) >= VMIN ){ + d = 1.0 * ks/ d; + } + else { + d = VMAX; + } + *dp = d * 0.8; + break; + case 18: + d = ABS(x) * kx + (PI/2) * ks; + if( ABS(d) >= VMIN ){ + d = PI / d; + } + else { + d = VMAX; + } + *dp = d * 0.8; + break; + case 19: + case 34: + case 35: + d = fabs(sin(x * kx)) + 0.25 * ks; + if( ABS(d) >= VMIN ){ + d = 1.0 / d; + } + else { + d = VMAX; + } + *dp = d * 0.8; + break; + case 20: + case 30: + case 32: + d = (x+xs) * kx * 0.5 + (PI/2) * ks; + if( ABS(d) >= VMIN ){ + d = PI / d; + } + else { + d = VMAX; + } + *dp = d * 0.8; + break; + case 21: + case 31: + case 33: + d = (xs-x) * kx * 0.5 + (PI/2) * ks; + if( ABS(d) >= VMIN ){ + d = PI / d; + } + else { + d = VMAX; + } + *dp = d * 0.8; + break; + case 23: + d = x * x * kx * kx + (PI * (ks+1.0)); + *dp = ABS(d) >= VMIN ? (PI * 2.0 / d) : VMAX; + break; + case 24: + case 26: + case 27: + d = (xs-ABS(x)) * kx + (PI/2) * ks; + *dp = ABS(d) >= VMIN ? (PI * 0.8 / d) : VMAX; + break; + case 37: + *dp = ky * (ABS(x) * kx * 0.5); + break; + default: + break; + } + } + } + break; + } + return pTbl; +} +//--------------------------------------------------------------------------- +Graphics::TBitmap* __fastcall CItem::Perspect(Graphics::TBitmap* pDest, Graphics::TBitmap *pSrc) +{ + ASSERT(pSrc->PixelFormat == pf24bit); + + Graphics::TBitmap *pSrcBak = pSrc; + TColor back = m_Back; + LPCSPERSPECT pPar = &m_sperspect; + if( (pDest == NULL) || (pDest->PixelFormat != pf24bit) ){ + if( pDest != NULL ) delete pDest; + pDest = new Graphics::TBitmap; + pDest->PixelFormat = pf24bit; + } + + if( (pSrc->Width < 2) || (pSrc->Height < 2) ){ + pDest->Width = pSrc->Width; + pDest->Height = pSrc->Width; + CopyBitmap(pDest, pSrc); + } + else { + int flag = pPar->flag & 0x0000ffff; + int wave = pPar->flag >> 16; + int bw = (pSrc->Width & 1) ? pSrc->Width - 1 : pSrc->Width; + int bh = (pSrc->Height & 1) ? pSrc->Height - 1 : pSrc->Height; + pDest->Width = bw; + pDest->Height = bh; + int i, j, m, n; + double x, y, w, p, q; + double k[3][3]; + int xs = bw / 2; + int ys = bh / 2; + SetMatrix(k, pPar, xs, ys); + BYTE *sp1, *sp2; + BYTE *tp; + + BYTE br, bg, bb; + if( flag == 2 ){ // Overlay on source + tp = (BYTE *)pSrc->ScanLine[0]; + bb = *tp++; + bg = *tp++; + br = *tp; + } + else { // Overlay on template + bb = (BYTE)(DWORD(back)>>16); + bg = (BYTE)(DWORD(back)>> 8); + br = (BYTE)(DWORD(back)); + } + if( m_Frame ){ + pSrc = CreateBitmap(pSrcBak->Width, pSrcBak->Height); + CopyBitmap(pSrc, pSrcBak); + int ww = (m_Frame + 1) * 2; + TRect rc; + rc.Left = ww/2; rc.Top = ww/2; + rc.Right = pSrc->Width - ww/2; rc.Bottom = pSrc->Height - ww/2; + pSrc->Canvas->Pen->Color = m_FrameCol; + pSrc->Canvas->Pen->Width = ww; + pSrc->Canvas->MoveTo(rc.Left, rc.Top); + pSrc->Canvas->LineTo(rc.Right, rc.Top); + pSrc->Canvas->LineTo(rc.Right, rc.Bottom); + pSrc->Canvas->LineTo(rc.Left, rc.Bottom); + pSrc->Canvas->LineTo(rc.Left, rc.Top); + } + int r, g, b; + LPCDOUBLE pTbl = NULL; + double ks = 1.0 + (double(m_SC) * 0.05); + if( wave ) pTbl = MapTable(wave, xs, ys, ks); + double kc, kc3, kx, kc7; + switch(wave){ + case 7: + case 8: + kc7 = ((wave == 7) ? 0.6 : 0.8)*double(ys)/double(xs); + kx = xs * ((wave == 7) ? 4.0 * ks : 2.994) / PI; + kc3 = ys/3; + if( wave == 8 ){ + kc7 *= ks; + kc3 *= ks; + } + break; + case 13: + if( m_SC >= (88-30) ) m_SC = 88-30; + if( m_SC <= -30 ) m_SC = -29; + kc = 30 + m_SC; + kc3 = 1.0/tan(kc*PI/180); + kx = 1.0/cos(kc*PI/180); + kc7 = 1.0/sin(kc*PI/180); + break; + case 14: + kc3 = ys * 7 /8; + break; + case 15: + kc3 = ks + 0.75; + break; + case 25: + kc7 = 0.6*double(ys)/double(xs); + kx = xs * (4.0 * ks) / PI; + kc3 = ys/3; + break; + case 26: + case 27: + case 34: + case 35: + kc3 = (ABS(ks) > VMIN) ? (1.0 / ks) : VMAX; + break; + case 28: + case 29: + kc3 = (ABS(ks) > VMIN) ? (ks) : VMAX; + break; + case 30: + case 31: + case 32: + case 33: + kc3 = (ABS(ks) > VMIN) ? (0.8 / ks) : VMAX; + break; + } + kc = double(xs)/double(ys); + for( i = -ys; i < ys; i++ ){ + tp = (BYTE *)pDest->ScanLine[i+ys]; + for( j = -xs; j < xs; j++ ){ + w = k[0][0] * j + k[0][1] * i + k[0][2]; + x = k[1][0] * j + k[1][1] * i + k[1][2]; + y = k[2][0] * j + k[2][1] * i + k[2][2]; + if( w ){ + x = x / w; + y = y / w; + } + else { + x = y = 10000.0; + } + if( wave ){ + switch(wave){ + case 1: + case 2: + case 3: + case 4: + ASSERT(pTbl); + m = x + xs; + if( m >= bw ) m = bw-1; + if( m < 0 ) m = 0; + y += pTbl[m]; + break; + case 5: + ASSERT(pTbl); + x *= 0.8; + m = x + xs; + if( m >= bw ) m = bw-1; + if( m < 0 ) m = 0; + y *= pTbl[m]; + break; + case 6: + ASSERT(pTbl); + y *= 0.8; + m = y + ys; + if( m >= bh ) m = bh-1; + if( m < 0 ) m = 0; + x *= pTbl[m]; + break; + case 7: + case 8: + if( wave == 7 ){ + y -= ys; + } + x *= kc7; + y *= kc7; + q = -y * kc; + w = (y||x) ? atan2(x, q) : 0.0; + p = sqrt(q * q + x * x); + x = w * kx; + if( p >= kc3 ){ + if( wave == 8 ){ + x += xs; + if( x < 0 ) x += 2*xs; + x = fmod(x, 2*xs-1); + x -= xs; + } + p = (p - kc3) * 3; + y = (-(p) + ys); + } + else { + y = ys; + } + break; + case 9: + ASSERT(pTbl); + m = x + xs; + if( m >= bw ) m = bw-1; + if( m < 0 ) m = 0; + y *= pTbl[m]; + break; + case 10: + case 11: + case 36: + case 37: + ASSERT(pTbl); + m = x + xs; + if( m >= bw ) m = bw-1; + if( m < 0 ) m = 0; + y += pTbl[m]; + break; + case 12: + x *= 0.8; + p = (y+ys)*0.5; + w = xs * xs - x * x; + if( w >= 0 ){ + w = sqrt(w) * ks/2.0 - xs*0.25; + y -= w; + } + else { + y = ys; + } + + w = ys * ys - p * p; + if( w > 0 ){ + w = ys / sqrt(w); + x *= w; + } + else { + x = xs; + } + break; + case 13: + x += xs / 3; + y += ys / 3; + x *= 0.75; + y *= 0.75; + if( (y >= 0) && (x >= 0) ){ // C + y = y * 2 - ys; + x = x * 2 - xs; + } + else if( (-y*kc3 >= -x) ){ // A + x = (x - y*kc3) * 2 - xs; + y = y * kc7 * 3 + ys; + } + else { // B + y = (y - x/kc3) * 2 - ys; + x = x * kx * 3 * kc + xs; + } +// m = int(y); n = int(x); +// if( (n ==(-xs+1))||(n==(xs-1))||(m==(-ys+1))||(m==(ys-1)) ){ +// x = xs-1; y = ys-1; +// } + break; + case 14: + y += kc3; + w = (x||y) ? atan2(x, y*kc) : 0.0; + p = fabs(ks + cos(w)); + p = (p > VMIN) ? 1.0 / p : VMAX; + y *= p; + ASSERT(pTbl); + m = y; + if( m >= ys ) m = ys-1; + if( m < -ys ) m = -ys; + x *= p * pTbl[m+ys]; + break; + case 15: + x *= 1.7; y *= 1.7; + p = fabs(x); q = fabs(y); + w = (x||y) ? atan2(p, q*kc) : 0.0; + p = 1 + sin(w * kc3); + p = (p > VMIN) ? 1.0 / p : VMAX; + x *= p; + y *= p; + break; + case 16: + case 17: + case 22: + ASSERT(pTbl); + m = y + ys; + if( m >= bh ) m = bh-1; + if( m < 0 ) m = 0; + x *= pTbl[m]; + break; + case 18: + case 20: + case 21: + case 24: + ASSERT(pTbl); + y *= 1.50; + m = x + xs; + if( m >= bw ) m = bw-1; + if( m < 0 ) m = 0; + y *= pTbl[m]; + break; + case 19: + ASSERT(pTbl); + y *= 1.30; + m = x + xs; + if( m >= bw ) m = bw-1; + if( m < 0 ) m = 0; + y *= pTbl[m]; + break; + case 23: + ASSERT(pTbl); + y *= 2.00; + m = x + xs; + if( m >= bw ) m = bw-1; + if( m < 0 ) m = 0; + y *= pTbl[m]; + break; + case 25: + y += ys; + x *= kc7; + y *= kc7; + q = y * kc; + w = (y||x) ? atan2(x, q) : 0.0; + p = sqrt(q * q + x * x); + x = w * kx; + if( p >= kc3 ){ + p = (p - kc3) * 3; + y = p - ys; + } + else { + y = -ys; + } + break; + case 26: + case 28: + case 30: + case 31: + case 34: + ASSERT(pTbl); + if( y < 0 ){ + y *= 1.3; + m = x + xs; + if( m >= bw ) m = bw-1; + if( m < 0 ) m = 0; + y *= pTbl[m]; + } + else { + y *= kc3; + } + break; + case 27: + case 29: + case 32: + case 33: + case 35: + ASSERT(pTbl); + if( y > 0 ){ + y *= 1.3; + m = x + xs; + if( m >= bw ) m = bw-1; + if( m < 0 ) m = 0; + y *= pTbl[m]; + } + else { + y *= kc3; + } + break; + case 38: + ASSERT(pTbl); + m = y + ys; + if( m >= bh ) m = bh-1; + if( m < 0 ) m = 0; + x += pTbl[m]; + break; + default: + break; + } + } + if( y > 0 ){ m = int(y); } else { m = int(y-1); } + if( x > 0 ){ n = int(x); } else { n = int(x-1); } + q = y - m; + p = x - n; + double pp = 1.0 - p; + double qq = 1.0 - q; + if( (m >= -ys) && (m < ys-1) && (n >= -xs) && (n < xs-1) ){ + sp1 = (BYTE *)pSrc->ScanLine[m+ys] + (n+xs)*3; + sp2 = (BYTE *)pSrc->ScanLine[m+ys+1] + (n+xs)*3; + if( (*sp1 != *sp2) || (*sp1 != *(sp1+3)) || (*sp1 != *(sp2+3)) ){ + b = (int)(qq*(pp*(*sp1) + p*(*(sp1+3))) + + q * (pp*(*sp2) + p*(*(sp2+3)))); + if( b < 0 ) b = 0; + if( b > 255 ) b = 255; + } + else { + b = *sp1; + } + sp1++; sp2++; + if( (*sp1 != *sp2) || (*sp1 != *(sp1+3)) || (*sp1 != *(sp2+3)) ){ + g = (int)(qq*(pp*(*sp1) + p*(*(sp1+3))) + + q * (pp*(*sp2) + p*(*(sp2+3)))); + if( g < 0 ) g = 0; + if( g > 255 ) g = 255; + } + else { + g = *sp1; + } + sp1++; sp2++; + if( (*sp1 != *sp2) || (*sp1 != *(sp1+3)) || (*sp1 != *(sp2+3)) ){ + r = (int)(qq*(pp*(*sp1) + p*(*(sp1+3))) + + q * (pp*(*sp2) + p*(*(sp2+3)))); + if( r < 0 ) r = 0; + if( r > 255 ) r = 255; + } + else { + r = *sp1; + } + if( (br == r) && (bg == g) && (bb == b) && (flag != 2) ){ + if( r ){ r--; } + else if( g ){ g--; } + else if( b ){ b--; } + else { r++; } + } + *tp++ = BYTE(b); + *tp++ = BYTE(g); + *tp++ = BYTE(r); + } + else { + *tp++ = bb; + *tp++ = bg; + *tp++ = br; + } + } + } + if( pTbl != NULL ) delete pTbl; + } + if( pSrcBak != pSrc ) delete pSrc; + return pDest; +} +// +// +//--------------------------------------------------------------------------- +// CItem class +// +__fastcall CItem::CItem(void) +{ + m_pMemStream = NULL; + m_pBitmap = NULL; + + // Init as default + m_sperspect.ver = 3; + m_sperspect.flag = 0; + m_sperspect.ax = 3.0; m_sperspect.ay = 3.0; + m_sperspect.px = m_sperspect.py = m_sperspect.pz = 0.0; + m_sperspect.rz = -180; m_sperspect.rx = m_sperspect.ry = 0; + m_sperspect.v = 10; m_sperspect.s = 2.3; + m_sperspect.r = 0.0; + m_SC = 0; + + m_Back = clBlack; + m_OrgXW = m_OrgYW = 16; + m_Draft = 0; + + m_Frame = 0; + m_FrameCol = clWhite; +} +//--------------------------------------------------------------------------- +__fastcall CItem::~CItem() +{ + if( m_pMemStream != NULL ) delete m_pMemStream; + if( m_pBitmap != NULL ) delete m_pBitmap; +} +//--------------------------------------------------------------------------- +void __fastcall CItem::Create(LPCBYTE ps, DWORD size) +{ + if( (ps != NULL) && size ){ + LPSPERSPECT lps = (LPSPERSPECT)ps; + if( lps->ver <= m_sperspect.ver ){ + int ver = m_sperspect.ver; + if( !(lps->flag & 0x0000ffff) && (size <= sizeof(SPERSPECT)) ){ + memcpy(&m_sperspect, lps, size); + m_sperspect.flag &= 0xffff0000; + } + else { + TMemoryStream *pMem = new TMemoryStream; + try{ + pMem->Clear(); + pMem->Write(ps, size); + pMem->Seek(soFromBeginning, 0); + SPERSPECT sperspect; + pMem->Read(&sperspect, sizeof(SPERSPECT)); + memcpy(&m_sperspect, &sperspect, sizeof(m_sperspect)); + m_SC = 0; + if( m_sperspect.ver >= 2 ){ + pMem->Read(&m_SC, sizeof(m_SC)); + } + if( m_sperspect.flag & 0x0000ffff ){ + if( m_pBitmap == NULL ) m_pBitmap = CreateBitmap(16, 16); + m_pBitmap->LoadFromStream(pMem); + m_OrgXW = m_pBitmap->Width; + m_OrgYW = m_pBitmap->Height; + } + m_Frame = 0; + m_FrameCol = clWhite; + if( m_sperspect.ver >= 3 ){ + pMem->Read(&m_Frame, sizeof(m_Frame)); + pMem->Read(&m_FrameCol, sizeof(m_FrameCol)); + } + } + catch(...){ + ASSERT(0); + } + delete pMem; + } + m_sperspect.ver = ver; + } + } +} +//--------------------------------------------------------------------------- +DWORD __fastcall CItem::GetItemType(void) +{ + return (m_sperspect.flag & 0x0000ffff) ? 0x00010000 : 0x00010001; +} +//--------------------------------------------------------------------------- +LPCBYTE __fastcall CItem::CreateStorage(LPDWORD pSize) +{ + ASSERT(pSize); + + if( m_pMemStream != NULL ) delete m_pMemStream; + m_pMemStream = new TMemoryStream; + m_pMemStream->Clear(); + m_pMemStream->Write(&m_sperspect, sizeof(m_sperspect)); + m_pMemStream->Write(&m_SC, sizeof(m_SC)); + if( (m_sperspect.flag & 0x0000ffff) && (m_pBitmap != NULL) ){ + m_pBitmap->SaveToStream(m_pMemStream); + } + m_pMemStream->Write(&m_Frame, sizeof(m_Frame)); + m_pMemStream->Write(&m_FrameCol, sizeof(m_FrameCol)); + *pSize = m_pMemStream->Position; + return (LPCBYTE)m_pMemStream->Memory; +} +//--------------------------------------------------------------------------- +void __fastcall CItem::DeleteStorage(LPCBYTE pStorage) +{ + ASSERT(pStorage); + + if( m_pMemStream != NULL ){ + ASSERT(pStorage == (LPCBYTE)m_pMemStream->Memory); + delete m_pMemStream; + m_pMemStream = NULL; + } +} +//--------------------------------------------------------------------------- +void __fastcall CItem::Copy(CItem *sp) +{ + ASSERT(sp); + + memcpy(&m_sperspect, &sp->m_sperspect, sizeof(m_sperspect)); + m_Frame = sp->m_Frame; + m_FrameCol = sp->m_FrameCol; + m_SC = sp->m_SC; + if( sp->m_pBitmap != NULL ){ + CopySource(sp->m_pBitmap); + } + m_Back = sp->m_Back; + m_OrgXW = sp->m_OrgXW; + m_OrgYW = sp->m_OrgYW; +} +//--------------------------------------------------------------------------- +void __fastcall CItem::CopySource(Graphics::TBitmap *pSrc) +{ + ASSERT(pSrc); + + int xm = pSrc->Width; + int ym = pSrc->Height; + if( xm > 400 ) xm = 400; + if( ym > 320 ) ym = 320; + if( m_pBitmap == NULL ) m_pBitmap = CreateBitmap(320, 256); + KeepAspectCopy(m_pBitmap, xm, ym, pSrc, ((m_sperspect.flag & 3)!=2) ? HALFTONE : COLORONCOLOR); + m_OrgXW = m_pBitmap->Width; + m_OrgYW = m_pBitmap->Height; +} +//--------------------------------------------------------------------------- +void __fastcall CItem::CopyFromHistory(void) +{ + ASSERT(sys.m_fLoadHistImage); + + if( m_pBitmap == NULL ) m_pBitmap = CreateBitmap(16, 16); + m_pBitmap->Handle = sys.m_fLoadHistImage(); + m_OrgXW = m_pBitmap->Width; + m_OrgYW = m_pBitmap->Height; +} +//--------------------------------------------------------------------------- +void __fastcall CItem::DeleteSource(void) +{ + if( m_pBitmap != NULL ){ + delete m_pBitmap; + m_pBitmap = NULL; + } +} +//--------------------------------------------------------------------------- +DWORD __fastcall CItem::GetOrgSize(void) +{ + DWORD w = m_OrgXW; + DWORD h = m_OrgYW; + return (h << 16) + w; +} +//--------------------------------------------------------------------------- +void __fastcall CItem::Draw(Graphics::TBitmap *pDest) +{ + if( m_pBitmap == NULL ) return; // No source image + + m_Back = pDest->Canvas->Pixels[0][0]; + + + Graphics::TBitmap *pSrc = m_pBitmap; + if( m_Draft ){ + int xm = pSrc->Width; + int ym = pSrc->Height; + if( xm > 80 ) xm = 80; + if( ym > 64 ) ym = 64; + pSrc = CreateBitmap(xm, ym); + KeepAspectCopy(pSrc, xm, ym, m_pBitmap, COLORONCOLOR); + } + // Do perspect + Graphics::TBitmap *pBitmap = Perspect(NULL, pSrc); + if( pSrc != m_pBitmap ) delete pSrc; + + // pBitmap -> pDest + TRect rc; + rc.Left = rc.Top = 0; + rc.Right = pDest->Width; + rc.Bottom = pDest->Height; + int Sop = ::SetStretchBltMode(pDest->Canvas->Handle, COLORONCOLOR); + pDest->Canvas->StretchDraw(rc, pBitmap); + ::SetStretchBltMode(pDest->Canvas->Handle, Sop); + + delete pBitmap; + + // Delete source for saving resource + if( !(m_sperspect.flag & 0x0000ffff) ) DeleteSource(); + + // set transparent color to (0,0) for overlay + if( (m_sperspect.flag & 0x0000ffff) != 2 ){ + LPBYTE p = (LPBYTE)pDest->ScanLine[0]; + ASSERT(p); + *p++ = (BYTE)(DWORD(m_Back)>>16); + *p++ = (BYTE)(DWORD(m_Back)>> 8); + *p = (BYTE)(DWORD(m_Back)); + } +} +///------------------------------------------------------ +/// +///CWaitCursor クラス +/// +CWaitCursor::CWaitCursor() +{ + sv = Screen->Cursor; + Screen->Cursor = crHourGlass; +} + +CWaitCursor::~CWaitCursor() +{ + Screen->Cursor = sv; +} + +void CWaitCursor::Delete(void) +{ + Screen->Cursor = sv; +} + +void CWaitCursor::Wait(void) +{ + Screen->Cursor = crHourGlass; +} + + \ No newline at end of file diff --git a/CItems/PERIMG/Comlib.h b/CItems/PERIMG/Comlib.h new file mode 100644 index 0000000..22afd25 --- /dev/null +++ b/CItems/PERIMG/Comlib.h @@ -0,0 +1,129 @@ +#ifndef ComLibH +#define ComLibH +#include +#include +#include +#include +#include + +#define UseHWND 0 + +#define NDEBUG // Remove this symbol, if you would like to do debug +#include +#define ASSERT(c) assert(c) + +#define AN(c) (sizeof(c)/sizeof(c[0])) +#define ABS(c) (((c)<0)?(-(c)):(c)) +#define PI 3.1415926535897932384626433832795 + +typedef const BYTE* LPCBYTE; +typedef double* LPDOUBLE; +typedef const double* LPCDOUBLE; + +extern int MsgEng; +#define VER "PerImg Version 1.08" +#define AUT "(C) JE3HHT 2002." +#define TTL "MMSSTV custom item" +#define TTLJ "MMSSTV カスタムアイテム" // Japanese code + +// These prototypes are the functions in the MMSSTV. +// ---- Refer to the comment of the mcmFunc() --- +/*0*/typedef HBITMAP (__cdecl *mmLoadImageMenu)(int sw, int xw, int yw); +/*1*/typedef HBITMAP (__cdecl *mmLoadImage)(LPCSTR pName); +/*2*/typedef HBITMAP (__cdecl *mmLoadHistImage)(void); +/*3*/typedef int (__cdecl *mmSaveImageMenu)(HBITMAP hb, LPCSTR pName, LPCSTR pFolder); +/*4*/typedef int (__cdecl *mmSaveImage)(HBITMAP hb, LPCSTR pName); +/*5*/typedef HBITMAP (__cdecl *mmPasteImage)(int sw, int xw, int yw); +/*6*/typedef int (__cdecl *mmGetMacKey)(LPSTR pDest, int cbDest); +/*7*/typedef int (__cdecl *mmConvMac)(LPSTR pDest, LPCSTR pSrc, int cbDest); +/*8*/typedef HBITMAP (__cdecl *mmCreateDIB)(int xw, int yw); +/*9*/typedef void (__cdecl *mmMultProc)(void); +/*10*/typedef void (__cdecl *mmMultProcA)(void); +/*11*/typedef int (__cdecl *mmColorComp)(LPDWORD pCol); +/*12*/typedef HBITMAP (__cdecl *mmLoadRxImage)(void); +/*13*/typedef void (__cdecl *mmView)(HBITMAP hb); +extern mmLoadImageMenu fLoadImageMenu; +extern mmLoadHistImage fLoadHistImage; +extern mmMultProc fMultProc; + + +Graphics::TBitmap * __fastcall CreateBitmap(int xw, int yw); +void __fastcall CopyBitmap(Graphics::TBitmap *pDest, Graphics::TBitmap *pSrc); +void __fastcall DrawBitmap(TPaintBox *pBox, Graphics::TBitmap *pBitmap); +void __fastcall MultProc(void); + +typedef struct { // Do not change the format + int ver; + int flag; + double ax; + double ay; + double px; + double py; + double pz; + double rz; + double rx; + double ry; + double v; + double s; + double r; +}SPERSPECT; +typedef SPERSPECT* LPSPERSPECT; +typedef const SPERSPECT* LPCSPERSPECT; +//Graphics::TBitmap* __fastcall Perspect(Graphics::TBitmap* pDest, Graphics::TBitmap *pSrc, LPCSPERSPECT pPar, TColor back); + +class CItem { +public: + SPERSPECT m_sperspect; + Graphics::TBitmap *m_pBitmap; + TColor m_Back; + TMemoryStream *m_pMemStream; + int m_SC; + int m_OrgXW; + int m_OrgYW; + int m_Draft; + int m_Frame; + TColor m_FrameCol; +public: + __fastcall CItem(void); + __fastcall ~CItem(); + void __fastcall Create(LPCBYTE ps, DWORD size); + DWORD __fastcall GetItemType(void); + LPCBYTE __fastcall CreateStorage(LPDWORD psize); + void __fastcall DeleteStorage(LPCBYTE pStorage); + void __fastcall Copy(CItem *sp); + void __fastcall CopySource(Graphics::TBitmap *pSrc); + void __fastcall CopyFromHistory(void); + void __fastcall DeleteSource(void); + DWORD __fastcall GetOrgSize(void); + void __fastcall Draw(Graphics::TBitmap *pDest); + inline void __fastcall SetDraft(DWORD draft){ + m_Draft = draft; + }; + Graphics::TBitmap* __fastcall Perspect(Graphics::TBitmap* pDest, Graphics::TBitmap *pSrc); +}; +// +// +typedef struct { + DWORD m_dwVersion; + int m_WinNT; + int m_MsgEng; + mmLoadImageMenu m_fLoadImageMenu; + mmLoadHistImage m_fLoadHistImage; + mmMultProc m_fMultProc; + mmView m_fView; +}SYS; +extern SYS sys; +// +// +// +class CWaitCursor +{ +private: + TCursor sv; +public: + CWaitCursor(); + ~CWaitCursor(); + void Delete(void); + void Wait(void); +}; +#endif diff --git a/CItems/PERIMG/Item.ico b/CItems/PERIMG/Item.ico new file mode 100644 index 0000000..4c2283d Binary files /dev/null and b/CItems/PERIMG/Item.ico differ diff --git a/CItems/PERIMG/PerDlg.cpp b/CItems/PERIMG/PerDlg.cpp new file mode 100644 index 0000000..936e160 --- /dev/null +++ b/CItems/PERIMG/PerDlg.cpp @@ -0,0 +1,597 @@ +//--------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "PerDlg.h" +//--------------------------------------------------------------------- +#pragma resource "*.dfm" +//--------------------------------------------------------------------- +#if UseHWND +__fastcall TPerDlgBox::TPerDlgBox(HWND hWnd) + : TForm(hWnd) +#else +__fastcall TPerDlgBox::TPerDlgBox(TComponent* AOwner) + : TForm(AOwner) +#endif +{ + m_Loaded = 0; + m_DisEvent = 1; + if( sys.m_MsgEng ){ + Font->Name = "Arial"; + Font->Charset = ANSI_CHARSET; + Caption = VER" - "TTL; + CancelBtn->Caption = "Cancel"; + DefBtn->Caption = "Default"; + L1->Caption = "Rot.X"; + L2->Caption = "Rot.Y"; + L3->Caption = "Rot.Z"; + L4->Caption = "Move.Z"; + L5->Caption = "Move.Y"; + L6->Caption = "Move.X"; + L7->Caption = "ViewP."; + L8->Caption = "Scale.X"; + L9->Caption = "Scale.Y"; + L10->Caption = "Rot"; + L11->Caption = "Defo."; + RGSRC->Caption = "Source"; + RGSRC->Items->Strings[0] = "History"; + RGSRC->Items->Strings[1] = "Loaded image"; + RGSRC->Items->Strings[2] = "Overlay"; + ViewBtn->Caption = "Show"; + PasteBtn->Caption = "Paste"; + DefBtn->Hint = "Return to the default"; + LoadBtn->Hint = "Load image file"; + PasteBtn->Hint = "Load from the clipboard"; + ViewBtn->Hint = "Show source image"; + SBR->Hint = "Return to the default"; + L12->Caption = "Frame W."; + CBF->Items->Strings[0] = "None"; + PC->Hint = "Set frame color"; + } + else { + Caption = VER" - "TTLJ; + } + m_pBitmap = NULL; + m_pItem = NULL; + m_XC = -1; + m_Wave = 0; + for( int i = 0; i < AN(m_DirTB); i++ ){ + m_DirTB[i] = 1; + } + m_hClipNext = ::SetClipboardViewer(Handle); + ShowHint = sys.m_WinNT; + MultProc(); +} +//--------------------------------------------------------------------------- +void __fastcall TPerDlgBox::FormDestroy(TObject *Sender) +{ + ::ChangeClipboardChain(Handle, m_hClipNext); + if( m_pBitmap != NULL ) delete m_pBitmap; +} +//--------------------------------------------------------------------------- +int __fastcall TPerDlgBox::Execute(CItem *pItem) +{ + m_pItem = pItem; + m_Item.Copy(pItem); + if( m_Item.m_pBitmap == NULL ) m_Item.CopyFromHistory(); + m_Back = m_Item.m_Back; + LPSPERSPECT psp = &m_Item.m_sperspect; + + MultProc(); + + TBAX->Position = psp->ax * 20.0 + 0.5; + TBAY->Position = psp->ay * 20.0 + 0.5; + TBPX->Position = psp->px * 40.0; + TBPY->Position = psp->py * 40.0; + TBPZ->Position = psp->pz * 40.0; + TBRX->Position = psp->rx; + TBRY->Position = psp->ry; + TBRZ->Position = psp->rz; + TBS->Position = psp->s * 10.0 + 0.5; + TBR->Position = psp->r; + RGSRC->ItemIndex = psp->flag & 0x0000ffff; + SBSC->Position = SHORT(m_Item.m_SC); + m_Wave = psp->flag >> 16; + CBF->ItemIndex = pItem->m_Frame; + PC->Color = pItem->m_FrameCol; + + UpdateWaveBtn(0); + UpdateBitmap(); + UpdateBtn(); + m_DisEvent = 0; + MultProc(); + if( ShowModal() == IDOK ){ + MultProc(); + psp = &pItem->m_sperspect; + psp->ax = double(TBAX->Position)/20.0; + psp->ay = double(TBAY->Position)/20.0; + psp->px = double(TBPX->Position)/40.0; + psp->py = double(TBPY->Position)/40.0; + psp->pz = double(TBPZ->Position)/40.0; + psp->rx = TBRX->Position; + psp->ry = TBRY->Position; + psp->rz = TBRZ->Position; + psp->s = double(TBS->Position)/10.0; + psp->r = TBR->Position; + pItem->m_SC = SBSC->Position; + pItem->m_Frame = CBF->ItemIndex; + pItem->m_FrameCol = PC->Color; + + UpdateWaveBtn(1); + psp->flag = RGSRC->ItemIndex | (m_Wave << 16); + if( (psp->flag & 0x0000ffff) && m_Loaded && (m_Item.m_pBitmap != NULL) ){ + pItem->CopySource(m_Item.m_pBitmap); + } + return TRUE; + } + MultProc(); + return FALSE; +} +//--------------------------------------------------------------------- +void __fastcall TPerDlgBox::UpdateWaveBtn(int dir) +{ + TSpeedButton *tbl[]={ + SB, SBZ1, SBZ2, SBZ3, SBZ4, SBZ5, SBZ6, SBZ7, + SBZ8, SBZ9, SBZ10, SBZ11, SBZ12, SBZ13, SBZ14, + SBZ15, SBZ16, SBZ17, SBZ18, SBZ19, SBZ20, SBZ21, + SBZ22, SBZ23, SBZ24, SBZ25, SBZ26, SBZ27, SBZ28, + SBZ29, SBZ30, SBZ31, SBZ32, SBZ33, SBZ34, SBZ35, + SBZ36, SBZ37, SBZ38, + NULL, + }; + if( dir ){ + for( int i = 0; tbl[i] != NULL; i++ ){ + if( tbl[i]->Down ){ + m_Wave = i; + break; + } + } + } + else { + if( m_Wave >= (AN(tbl)-1) ) m_Wave = 0; + tbl[m_Wave]->Down = TRUE; + } +} +//--------------------------------------------------------------------- +void __fastcall TPerDlgBox::UpdateBitmap(void) +{ + if( m_Item.m_pBitmap == NULL ) return; + + m_Item.m_sperspect.ax = double(TBAX->Position)/20.0; + m_Item.m_sperspect.ay = double(TBAY->Position)/20.0; + + m_Item.m_sperspect.px = double(TBPX->Position)/40.0; + m_Item.m_sperspect.py = double(TBPY->Position)/40.0; + m_Item.m_sperspect.pz = double(TBPZ->Position)/40.0; + + m_Item.m_sperspect.rx = TBRX->Position; + m_Item.m_sperspect.ry = TBRY->Position; + m_Item.m_sperspect.rz = TBRZ->Position; + m_Item.m_sperspect.s = double(TBS->Position)/10.0; + m_Item.m_sperspect.r = TBR->Position; + m_Item.m_SC = SBSC->Position; + m_Item.m_Frame = CBF->ItemIndex; + m_Item.m_FrameCol = PC->Color; + m_pBitmap = m_Item.Perspect(m_pBitmap, m_Item.m_pBitmap); + UpdateHint(); + UpdateTB(); + if( ShowHint ) Application->CancelHint(); +} +//--------------------------------------------------------------------- +void __fastcall TPerDlgBox::PBoxPaint(TObject *Sender) +{ + DrawBitmap(PBox, m_pBitmap); +} +//--------------------------------------------------------------------- +void __fastcall TPerDlgBox::UpdateHint(void) +{ + if( sys.m_WinNT ){ + char bf[128]; + wsprintf(bf, "VP: %d", TBS->Position); + TBS->Hint = bf; + wsprintf(bf, "SX: %d", TBAX->Position); + TBAX->Hint = bf; + wsprintf(bf, "SY: %d", TBAY->Position); + TBAY->Hint = bf; + wsprintf(bf, "PX: %d", TBPX->Position); + TBPX->Hint = bf; + wsprintf(bf, "PY: %d", TBPY->Position); + TBPY->Hint = bf; + wsprintf(bf, "PZ: %d", TBPZ->Position); + TBPZ->Hint = bf; + wsprintf(bf, "RX: %d", TBRX->Position); + TBRX->Hint = bf; + wsprintf(bf, "RY: %d", TBRY->Position); + TBRY->Hint = bf; + wsprintf(bf, "RZ: %d", TBRZ->Position); + TBRZ->Hint = bf; + wsprintf(bf, "R: %d", TBR->Position); + TBR->Hint = bf; + wsprintf(bf, "%d", SBSC->Position); + SBSC->Hint = bf; + } +} +//--------------------------------------------------------------------------- +void __fastcall TPerDlgBox::DefBtnClick(TObject *Sender) +{ +#if 0 // for to get default + FILE *fp = fopen("TEST.TXT", "wt"); + fprintf(fp, "%d\n", TBAX->Position); + fprintf(fp, "%d\n", TBAY->Position); + fprintf(fp, "%d\n", TBPX->Position); + fprintf(fp, "%d\n", TBPY->Position); + fprintf(fp, "%d\n", TBPZ->Position); + fprintf(fp, "%d\n", TBRX->Position); + fprintf(fp, "%d\n", TBRY->Position); + fprintf(fp, "%d\n", TBRZ->Position); + fprintf(fp, "%d\n\n", TBS->Position); + + SPERSPECT *psp = &m_Item.m_sperspect; + fprintf(fp, "%f\n", psp->ax); + fprintf(fp, "%f\n", psp->ay); + fprintf(fp, "%f\n", psp->px); + fprintf(fp, "%f\n", psp->py); + fprintf(fp, "%f\n", psp->pz); + fprintf(fp, "%f\n", psp->rx); + fprintf(fp, "%f\n", psp->ry); + fprintf(fp, "%f\n", psp->rz); + fprintf(fp, "%f\n", psp->s); + fclose(fp); +#else + m_DisEvent++; + TBAX->Position = 60; + TBAY->Position = 60; + TBPX->Position = 0; + TBPY->Position = 0; + TBPZ->Position = 0; + TBRX->Position = 0; + TBRY->Position = 0; + TBRZ->Position = -180; + TBR->Position = 0; + TBS->Position = 23; + SBSC->Position = 0; + m_DisEvent--; + UpdateItem(); + UpdateBtn(); +#endif +} +//--------------------------------------------------------------------------- +void __fastcall TPerDlgBox::UpdateBtn(void) +{ + LoadBtn->Enabled = RGSRC->ItemIndex && sys.m_fLoadImageMenu; + PasteBtn->Enabled = RGSRC->ItemIndex && Clipboard()->HasFormat(CF_BITMAP); + ViewBtn->Visible = sys.m_fView && (m_Item.m_pBitmap != NULL); + SBSC->Enabled = !SB->Down; + SBR->Enabled = !SB->Down && SBSC->Position; +} +//--------------------------------------------------------------------------- +void __fastcall TPerDlgBox::RGSRCClick(TObject *Sender) +{ + if( m_DisEvent ) return; + + if( !RGSRC->ItemIndex ){ + if( m_Item.m_sperspect.flag & 0x0000ffff ) m_Item.CopyFromHistory(); + } + else if( !(m_Item.m_sperspect.flag & 0x0000ffff) ){ + if( m_pItem->m_pBitmap != NULL ){ + m_Item.CopySource(m_pItem->m_pBitmap); + m_Loaded = 0; + } + else { + m_Loaded = 1; + } + } + UpdateWaveBtn(1); + m_Item.m_sperspect.flag = RGSRC->ItemIndex | (m_Wave << 16); + UpdateBitmap(); +// PBoxPaint(NULL); + PBox->Invalidate(); + UpdateBtn(); +} +//--------------------------------------------------------------------------- +void __fastcall TPerDlgBox::PBoxMouseDown(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( m_pBitmap == NULL ) return; + + m_SCX = double(m_pBitmap->Width) / double(PBox->Width); + m_SCY = double(m_pBitmap->Height) / double(PBox->Height); + X = X * m_SCX; + Y = Y * m_SCY; + + m_XC = m_pBitmap->Width / 2; + m_YC = m_pBitmap->Height / 2; + int x = X - m_XC; + int y = m_YC - Y; + if( x || y ){ + m_Deg = atan2(y, x); + } + else { + m_Deg = 0; + } + m_Dist = sqrt(x * x + y * y); + m_SDeg = TBR->Position; + m_SDistX = TBAX->Position; + m_SDistY = TBAY->Position; +} +//--------------------------------------------------------------------------- +void __fastcall TPerDlgBox::PBoxMouseMove(TObject *Sender, + TShiftState Shift, int X, int Y) +{ + if( m_XC > 0 ){ + X = X * m_SCX; + Y = Y * m_SCY; + + int x = X - m_XC; + int y = m_YC - Y; + double Deg; + if( x || y ){ + Deg = atan2(y, x); + } + else { + Deg = 0; + } + Deg = (m_Deg - Deg) * 180.0 / PI; + Deg += m_SDeg; + if( Deg < -180 ) Deg += 360.0; + if( Deg > 180 ) Deg -= 360.0; + TBR->Position = SHORT(Deg); + + double Dist = sqrt(x * x + y * y); + Dist = (Dist - m_Dist)/2; + int d = Dist + m_SDistX; + if( d > 201 ) d = 201; + if( d < 2 ) d = 2; + TBAX->Position = d; + d = Dist + m_SDistY; + if( d > 201 ) d = 201; + if( d < 2 ) d = 2; + TBAY->Position = d; + + UpdateItem(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TPerDlgBox::PBoxMouseUp(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + m_XC = -1; +} +//--------------------------------------------------------------------------- +void __fastcall TPerDlgBox::LoadBtnClick(TObject *Sender) +{ + if( sys.m_fLoadImageMenu ){ + NoTopMost(); + CWaitCursor w; + HBITMAP hb = sys.m_fLoadImageMenu(1, 16, 16); + if( hb != NULL ){ + Graphics::TBitmap *pBitmap = new Graphics::TBitmap; + pBitmap->Handle = hb; + m_Item.CopySource(pBitmap); + m_Loaded = 1; + UpdateBitmap(); + PBox->Invalidate(); + delete pBitmap; + } + TopMost(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TPerDlgBox::PasteBtnClick(TObject *Sender) +{ + NoTopMost(); + TClipboard *pCB = Clipboard(); + if (pCB->HasFormat(CF_BITMAP)){ + CWaitCursor w; + Graphics::TBitmap *pBitmap = new Graphics::TBitmap; + try + { + pBitmap->LoadFromClipboardFormat(CF_BITMAP, pCB->GetAsHandle(CF_BITMAP), 0); + m_Item.CopySource(pBitmap); + m_Loaded = 1; + UpdateBitmap(); + PBox->Invalidate(); + } + catch(...){ + ASSERT(0); + } + delete pBitmap; + } + TopMost(); +} +//--------------------------------------------------------------------------- +void __fastcall TPerDlgBox::TopMost(void) +{ +#if UseHWND + ::SetWindowPos(Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); +#endif +} +//--------------------------------------------------------------------------- +void __fastcall TPerDlgBox::NoTopMost(void) +{ +#if UseHWND + ::SetWindowPos(Handle, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); +#endif +} +//--------------------------------------------------------------------------- +void __fastcall TPerDlgBox::FormActivate(TObject *Sender) +{ + TopMost(); +} +//--------------------------------------------------------------------------- +void __fastcall TPerDlgBox::FormDeactivate(TObject *Sender) +{ + NoTopMost(); +} +//--------------------------------------------------------------------------- +void __fastcall TPerDlgBox::ViewBtnClick(TObject *Sender) +{ + if( sys.m_fView && (m_Item.m_pBitmap != NULL) ){ + NoTopMost(); + sys.m_fView(m_Item.m_pBitmap->Handle); + TopMost(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TPerDlgBox::SBRClick(TObject *Sender) +{ + m_DisEvent++; + SBSC->Position = 0; + m_DisEvent--; + UpdateItem(); + UpdateBtn(); +} +//--------------------------------------------------------------------------- +void __fastcall TPerDlgBox::SBClick(TObject *Sender) +{ + UpdateWaveBtn(1); + m_Item.m_sperspect.flag = RGSRC->ItemIndex | (m_Wave << 16); + UpdateBitmap(); + PBoxPaint(NULL); + UpdateBtn(); +} +//--------------------------------------------------------------------------- +void __fastcall TPerDlgBox::CBFChange(TObject *Sender) +{ + if( m_DisEvent ) return; + + UpdateItem(); + UpdateBtn(); +} +//--------------------------------------------------------------------------- +void __fastcall TPerDlgBox::PCClick(TObject *Sender) +{ + ColorDialog->Color = PC->Color; + if( ColorDialog->Execute() == TRUE ){ + PC->Color = ColorDialog->Color; + CBFChange(NULL); + } +} +//--------------------------------------------------------------------------- +static void __fastcall UpdateDefTB(TTrackBar *pBar, int f, int def, int &dir) +{ + if( f ){ + pBar->Position = pBar->Position + (pBar->PageSize * dir); + if( pBar->Position == pBar->Max ){ + dir = -1; + } + else if( pBar->Position == pBar->Min ){ + dir = 1; + } + } + else { + pBar->Position = def; + } + pBar->SetFocus(); +} +//--------------------------------------------------------------------------- +void __fastcall TPerDlgBox::LDefMouseDown(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( (Button != mbLeft) && (Button != mbRight) ) return; + BOOL f = (Button != mbLeft); + + TLabel *_tt[]={L7, L8, L9, L6, L5, L4, L1, L2, L3, L10}; + + int i; + for( i = 0; i < AN(_tt); i++ ){ + if( _tt[i] == (TLabel *)Sender ) break; + } + m_DisEvent++; + switch(i){ + case 0: + UpdateDefTB(TBS, f, 23, m_DirTB[0]); + break; + case 1: + UpdateDefTB(TBAX, f, 60, m_DirTB[1]); + break; + case 2: + UpdateDefTB(TBAY, f, 60, m_DirTB[2]); + break; + case 3: + UpdateDefTB(TBPX, f, 0, m_DirTB[3]); + break; + case 4: + UpdateDefTB(TBPY, f, 0, m_DirTB[4]); + break; + case 5: + UpdateDefTB(TBPZ, f, 0, m_DirTB[5]); + break; + case 6: + UpdateDefTB(TBRX, f, 0, m_DirTB[6]); + break; + case 7: + UpdateDefTB(TBRY, f, 0, m_DirTB[7]); + break; + case 8: + UpdateDefTB(TBRZ, f, -180, m_DirTB[8]); + break; + case 9: + UpdateDefTB(TBR, f, 0, m_DirTB[9]); + break; + } + m_DisEvent--; + UpdateItem(); +} +//--------------------------------------------------------------------------- +void __fastcall TPerDlgBox::UpdateTB(void) +{ + m_SBar[0] = TBS->Position; + m_SBar[1] = TBAX->Position; + m_SBar[2] = TBAY->Position; + m_SBar[3] = TBPX->Position; + m_SBar[4] = TBPY->Position; + m_SBar[5] = TBPZ->Position; + m_SBar[6] = TBRX->Position; + m_SBar[7] = TBRY->Position; + m_SBar[8] = TBRZ->Position; + m_SBar[9] = TBR->Position; +} +//--------------------------------------------------------------------------- +void __fastcall TPerDlgBox::UpdateItem(void) +{ + if( m_DisEvent ) return; + + UpdateBitmap(); + PBoxPaint(NULL); +} +//--------------------------------------------------------------------------- +void __fastcall TPerDlgBox::TBSChange(TObject *Sender) +{ + if( m_DisEvent ) return; + + TTrackBar *_tt[]={TBS, TBAX, TBAY, TBPX, TBPY, TBPZ, TBRX, TBRY, TBRZ, TBR}; + TTrackBar *pBar = (TTrackBar *)Sender; + + int i; + for( i = 0; i < AN(_tt); i++ ){ + if( _tt[i] == pBar ) break; + } + if( m_SBar[i] != pBar->Position ){ + m_SBar[i] = pBar->Position; + UpdateItem(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TPerDlgBox::SBSCChange(TObject *Sender) +{ + UpdateItem(); + UpdateBtn(); +} +//--------------------------------------------------------------------------- +void __fastcall TPerDlgBox::OnDrawClipboard(TMessage Message) +{ + PasteBtn->Enabled = RGSRC->ItemIndex && ::IsClipboardFormatAvailable(CF_BITMAP); + if( m_hClipNext ) ::SendMessage(m_hClipNext, WM_DRAWCLIPBOARD, Message.WParam, Message.LParam); +} +//--------------------------------------------------------------------------- +void __fastcall TPerDlgBox::OnChangeCbChain(TMessage Message) +{ + if( (HWND)Message.WParam == m_hClipNext ){ + m_hClipNext = (HWND)Message.LParam; + } + if( m_hClipNext ) ::SendMessage(m_hClipNext, WM_CHANGECBCHAIN, Message.WParam, Message.LParam); + Message.Result = 0; +} +//--------------------------------------------------------------------------- + diff --git a/CItems/PERIMG/PerDlg.dfm b/CItems/PERIMG/PerDlg.dfm new file mode 100644 index 0000000..4ccbb26 Binary files /dev/null and b/CItems/PERIMG/PerDlg.dfm differ diff --git a/CItems/PERIMG/PerDlg.h b/CItems/PERIMG/PerDlg.h new file mode 100644 index 0000000..4f4a398 --- /dev/null +++ b/CItems/PERIMG/PerDlg.h @@ -0,0 +1,171 @@ +//---------------------------------------------------------------------------- +#ifndef PerSpectDlgH +#define PerSpectDlgH +//---------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//---------------------------------------------------------------------------- +#include "ComLib.h" +#include +//---------------------------------------------------------------------------- +class TPerDlgBox : public TForm +{ +__published: + TButton *OKBtn; + TButton *CancelBtn; + TTrackBar *TBAX; + TTrackBar *TBAY; + TTrackBar *TBRX; + TTrackBar *TBRY; + TTrackBar *TBRZ; + TPaintBox *PBox; + TTrackBar *TBS; + TTrackBar *TBPX; + TTrackBar *TBPY; + TTrackBar *TBPZ; + TLabel *L1; + TLabel *L2; + TLabel *L3; + TLabel *L4; + TLabel *L5; + TLabel *L6; + TLabel *L7; + TLabel *L8; + TLabel *L9; + TButton *DefBtn; + TRadioGroup *RGSRC; + TTrackBar *TBR; + TLabel *L10; + TPanel *Panel; + TSpeedButton *SB; + TButton *ViewBtn; + TSpeedButton *SBR; + TButton *LoadBtn; + TButton *PasteBtn; + TLabel *L11; + TComboBox *CBF; + TPanel *PC; + TLabel *L12; + TColorDialog *ColorDialog; + TSpeedButton *SBZ1; + TSpeedButton *SBZ2; + TSpeedButton *SBZ3; + TSpeedButton *SBZ4; + TSpeedButton *SBZ5; + TSpeedButton *SBZ6; + TSpeedButton *SBZ7; + TSpeedButton *SBZ25; + TSpeedButton *SBZ8; + TSpeedButton *SBZ9; + TSpeedButton *SBZ10; + TSpeedButton *SBZ11; + TSpeedButton *SBZ12; + TSpeedButton *SBZ13; + TSpeedButton *SBZ14; + TSpeedButton *SBZ15; + TSpeedButton *SBZ16; + TSpeedButton *SBZ17; + TSpeedButton *SBZ18; + TSpeedButton *SBZ24; + TSpeedButton *SBZ19; + TSpeedButton *SBZ20; + TSpeedButton *SBZ21; + TSpeedButton *SBZ22; + TSpeedButton *SBZ23; + TSpeedButton *SBZ26; + TSpeedButton *SBZ27; + TSpeedButton *SBZ28; + TSpeedButton *SBZ29; + TSpeedButton *SBZ30; + TSpeedButton *SBZ31; + TSpeedButton *SBZ32; + TSpeedButton *SBZ33; + TSpeedButton *SBZ34; + TSpeedButton *SBZ35; + TSpeedButton *SBZ36; + TSpeedButton *SBZ37; + TSpeedButton *SBZ38; + TScrollBar *SBSC; + void __fastcall PBoxPaint(TObject *Sender); + void __fastcall TBSChange(TObject *Sender); + void __fastcall DefBtnClick(TObject *Sender); + void __fastcall RGSRCClick(TObject *Sender); + + void __fastcall FormDestroy(TObject *Sender); + void __fastcall PBoxMouseDown(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + void __fastcall PBoxMouseMove(TObject *Sender, TShiftState Shift, + int X, int Y); + void __fastcall PBoxMouseUp(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + void __fastcall LoadBtnClick(TObject *Sender); + void __fastcall PasteBtnClick(TObject *Sender); + void __fastcall FormActivate(TObject *Sender); + void __fastcall FormDeactivate(TObject *Sender); + void __fastcall ViewBtnClick(TObject *Sender); + + void __fastcall SBRClick(TObject *Sender); + void __fastcall SBClick(TObject *Sender); + void __fastcall CBFChange(TObject *Sender); + void __fastcall PCClick(TObject *Sender); + void __fastcall LDefMouseDown(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + void __fastcall SBSCChange(TObject *Sender); + +private: + int m_DisEvent; + Graphics::TBitmap *m_pBitmap; + CItem m_Item; + CItem *m_pItem; + TColor m_Back; + int m_Wave; + void __fastcall UpdateWaveBtn(int dir); + void __fastcall UpdateBitmap(void); + void __fastcall UpdateHint(void); + void __fastcall TopMost(void); + void __fastcall NoTopMost(void); + + int m_XC, m_YC; + double m_SCX, m_SCY; + double m_Deg, m_SDeg; + double m_Dist, m_SDistX, m_SDistY; + + void __fastcall UpdateBtn(void); + int m_Loaded; + + void __fastcall UpdateTB(void); + void __fastcall UpdateItem(void); + int m_SBar[10]; + int m_DirTB[10]; + + HWND m_hClipNext; + +public: +#if UseHWND + virtual __fastcall TPerDlgBox(HWND hWnd); +#else + virtual __fastcall TPerDlgBox(TComponent* AOwner); +#endif + int __fastcall Execute(CItem *pItem); + +protected: + void __fastcall OnDrawClipboard(TMessage Message); + void __fastcall OnChangeCbChain(TMessage Message); +BEGIN_MESSAGE_MAP + MESSAGE_HANDLER(WM_DRAWCLIPBOARD, TMessage, OnDrawClipboard) + MESSAGE_HANDLER(WM_CHANGECBCHAIN, TMessage, OnChangeCbChain) +END_MESSAGE_MAP(TForm) + +}; +//---------------------------------------------------------------------------- +#endif diff --git a/CItems/PERIMG/PerImg.bpr b/CItems/PERIMG/PerImg.bpr new file mode 100644 index 0000000..9df06d6 --- /dev/null +++ b/CItems/PERIMG/PerImg.bpr @@ -0,0 +1,181 @@ +# --------------------------------------------------------------------------- +!if !$d(BCB) +BCB = $(MAKEDIR)\.. +!endif + +# --------------------------------------------------------------------------- +# IDE セクション +# --------------------------------------------------------------------------- +# プロジェクトメイクファイルの以下のセクションは、IDE によって管理されます。 +# このセクションを変更する場合は、できるだけ IDE を使用するようにして +# ください。 +# --------------------------------------------------------------------------- + +VERSION = BCB.03 +# --------------------------------------------------------------------------- +PROJECT = PerImg.dll +OBJFILES = PerImg.obj Comlib.obj About.obj PerDlg.obj +RESFILES = perimg.res +DEFFILE = +RESDEPEN = $(RESFILES) About.dfm PerDlg.dfm +LIBFILES = +LIBRARIES = VCL35.lib +SPARELIBS = VCL35.lib +PACKAGES = VCLX35.bpi VCL35.bpi VCLDB35.bpi VCLDBX35.bpi bcbsmp35.bpi dclocx35.bpi \ + QRPT35.bpi TEEUI35.bpi VCLSMP35.bpi TEEDB35.bpi TEE35.bpi ibsmp35.bpi \ + NMFAST35.bpi INETDB35.bpi INET35.bpi +# --------------------------------------------------------------------------- +PATHCPP = .; +PATHASM = .; +PATHPAS = .; +PATHRC = .; +DEBUGLIBPATH = $(BCB)\lib\debug +RELEASELIBPATH = $(BCB)\lib\release +# --------------------------------------------------------------------------- +CFLAG1 = -WD -O2 -Hc -w -Ve -d -k- -vi -c -b- -w-par -w-inl -Vx +CFLAG2 = -I$(BCB)\include;$(BCB)\include\vcl -H=$(BCB)\lib\vcl35.csm +CFLAG3 = -Tkh30000 +PFLAGS = -U$(BCB)\lib\obj;$(BCB)\lib;$(RELEASELIBPATH) \ + -I$(BCB)\include;$(BCB)\include\vcl -$L- -$D- -v -JPHN -M +RFLAGS = -i$(BCB)\include;$(BCB)\include\vcl +AFLAGS = /i$(BCB)\include /i$(BCB)\include\vcl /mx /w2 /zn /d_RTLDLL +LFLAGS = -L$(BCB)\lib\obj;$(BCB)\lib;$(RELEASELIBPATH) -aa -Tpd -x -Gn +IFLAGS = +# --------------------------------------------------------------------------- +ALLOBJ = c0d32.obj sysinit.obj $(OBJFILES) +ALLRES = $(RESFILES) +ALLLIB = $(LIBFILES) $(LIBRARIES) import32.lib cp32mt.lib +# --------------------------------------------------------------------------- +!ifdef IDEOPTIONS + +[Version Info] +IncludeVerInfo=0 +AutoIncBuild=0 +MajorVer=1 +MinorVer=0 +Release=0 +Build=0 +Debug=0 +PreRelease=0 +Special=0 +Private=0 +DLL=0 +Locale=1041 +CodePage=932 + +[Version Info Keys] +CompanyName= +FileDescription= +FileVersion=1.0.0.0 +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion=1.0.0.0 +Comments= + +[HistoryLists\hlIncludePath] +Count=1 +Item0=$(BCB)\include;$(BCB)\include\vcl + +[HistoryLists\hlLibraryPath] +Count=1 +Item0=$(BCB)\lib\obj;$(BCB)\lib + +[HistoryLists\hlDebugSourcePath] +Count=1 +Item0=$(BCB)\source\vcl + +[HistoryLists\hlConditionals] +Count=2 +Item0=_RTLDLL +Item1=_RTLDLL;USEPACKAGES + +[HistoryLists\hlHostApplication] +Count=1 +Item0=D:\Mmsstv\Mmsstv.exe + +[Debugging] +DebugSourceDirs=$(BCB)\source\vcl + +[Parameters] +RunParams= +HostApplication=D:\Mmsstv\Mmsstv.exe + +!endif + +# --------------------------------------------------------------------------- +# MAKE セクション +# --------------------------------------------------------------------------- +# IDE はプロジェクトファイルのこのセクションは使用していません。 +# コマンドラインの MAKE ユーティリティを使用してビルドするためのものです。 +# --------------------------------------------------------------------------- + +.autodepend +# --------------------------------------------------------------------------- +!if !$d(BCC32) +BCC32 = bcc32 +!endif + +!if !$d(DCC32) +DCC32 = dcc32 +!endif + +!if !$d(TASM32) +TASM32 = tasm32 +!endif + +!if !$d(LINKER) +LINKER = ilink32 +!endif + +!if !$d(BRCC32) +BRCC32 = brcc32 +!endif +# --------------------------------------------------------------------------- +!if $d(PATHCPP) +.PATH.CPP = $(PATHCPP) +.PATH.C = $(PATHCPP) +!endif + +!if $d(PATHPAS) +.PATH.PAS = $(PATHPAS) +!endif + +!if $d(PATHASM) +.PATH.ASM = $(PATHASM) +!endif + +!if $d(PATHRC) +.PATH.RC = $(PATHRC) +!endif +# --------------------------------------------------------------------------- +$(PROJECT): $(OBJFILES) $(RESDEPEN) $(DEFFILE) + $(BCB)\BIN\$(LINKER) @&&! + $(LFLAGS) + + $(ALLOBJ), + + $(PROJECT),, + + $(ALLLIB), + + $(DEFFILE), + + $(ALLRES) +! +# --------------------------------------------------------------------------- +.pas.hpp: + $(BCB)\BIN\$(DCC32) $(PFLAGS) {$< } + +.pas.obj: + $(BCB)\BIN\$(DCC32) $(PFLAGS) {$< } + +.cpp.obj: + $(BCB)\BIN\$(BCC32) $(CFLAG1) $(CFLAG2) $(CFLAG3) -n$(@D) {$< } + +.c.obj: + $(BCB)\BIN\$(BCC32) $(CFLAG1) $(CFLAG2) $(CFLAG3) -n$(@D) {$< } + +.asm.obj: + $(BCB)\BIN\$(TASM32) $(AFLAGS) $<, $@ + +.rc.res: + $(BCB)\BIN\$(BRCC32) $(RFLAGS) -fo$@ $< +# --------------------------------------------------------------------------- diff --git a/CItems/PERIMG/PerImg.cpp b/CItems/PERIMG/PerImg.cpp new file mode 100644 index 0000000..eae56d5 --- /dev/null +++ b/CItems/PERIMG/PerImg.cpp @@ -0,0 +1,169 @@ +//--------------------------------------------------------------------------- +#include +#pragma hdrstop +//--------------------------------------------------------------------------- +#include "PerDlg.h" +#include "About.h" +//--------------------------------------------------------------------------- +USEUNIT("Comlib.cpp"); +USEFORM("About.cpp", AboutDlg); +USEFORM("PerDlg.cpp", PerDlgBox); +USERC("perimg.rc"); +//--------------------------------------------------------------------------- +int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void*) +{ + switch(reason){ + case DLL_PROCESS_ATTACH: + { + memset(&sys, 0, sizeof(sys)); + + sys.m_dwVersion = ::GetVersion(); + sys.m_WinNT = (sys.m_dwVersion < 0x80000000) ? TRUE : FALSE; + + HWND hMM = ::FindWindow("TMmsstv", NULL); + if( hMM != NULL ) Application->Handle = hMM; + } + break; + case DLL_PROCESS_DETACH: + sys.m_fMultProc = NULL; + break; + } + return 1; +} +//--------------------------------------------------------------------------- +extern "C" __declspec(dllexport) +void mcmLanguage(DWORD lang) +{ + sys.m_MsgEng = lang; +} +//--------------------------------------------------------------------------- +extern "C" __declspec(dllexport) +void mcmAboutDialog(HWND hWnd) +{ +#if UseHWND + TAboutDlg *pBox = new TAboutDlg(hWnd); +#else + TAboutDlg *pBox = new TAboutDlg(NULL); +#endif + pBox->ShowModal(); + delete pBox; +#if UseHWND + ::SetForegroundWindow(hWnd); +#endif +} +//--------------------------------------------------------------------- +extern "C" __declspec(dllexport) +HANDLE mcmCreateObject(LPCBYTE pStorage, DWORD Size) +{ + CItem *pItem = new CItem; + ASSERT(pItem); + if( pItem != NULL ) pItem->Create(pStorage, Size); + return (HANDLE)pItem; +} +//--------------------------------------------------------------------- +extern "C" __declspec(dllexport) +DWORD mcmGetItemType(HANDLE hObj) +{ + ASSERT(hObj); + CItem *pItem = (CItem *)hObj; + return pItem->GetItemType(); +} +//--------------------------------------------------------------------- +extern "C" __declspec(dllexport) +LPCBYTE mcmCreateStorage(HANDLE hObj, LPDWORD pSize) +{ + ASSERT(hObj); + CItem *pItem = (CItem *)hObj; + return pItem->CreateStorage(pSize); +} +//--------------------------------------------------------------------- +extern "C" __declspec(dllexport) +void mcmDeleteStorage(HANDLE hObj, LPCBYTE pStorage) +{ + ASSERT(hObj); + CItem *pItem = (CItem *)hObj; + pItem->DeleteStorage(pStorage); +} +//--------------------------------------------------------------------- +extern "C" __declspec(dllexport) +void mcmDeleteObject(HANDLE hObj) +{ + ASSERT(hObj); + CItem *pItem = (CItem *)hObj; + if( pItem != NULL ) delete pItem; +} +//--------------------------------------------------------------------- +extern "C" __declspec(dllexport) +DWORD mcmEdit(HANDLE hObj, HWND hWnd) +{ + ASSERT(hObj); + CItem *pItem = (CItem *)hObj; + +#if UseHWND + TPerDlgBox *pBox = new TPerDlgBox(hWnd); +#else + TPerDlgBox *pBox = new TPerDlgBox(NULL); +#endif + DWORD r = (DWORD)pBox->Execute(pItem); + delete pBox; +#if UseHWND + ::SetForegroundWindow(hWnd); +#endif + return r; +} +//--------------------------------------------------------------------- +extern "C" __declspec(dllexport) +DWORD mcmGetOrgSize(HANDLE hObj) +{ + ASSERT(hObj); + CItem *pItem = (CItem *)hObj; + return pItem->GetOrgSize(); +} +//--------------------------------------------------------------------- +extern "C" __declspec(dllexport) +LPCSTR mcmGetUserText(HANDLE hObj) +{ + ASSERT(0); // This function should not be called + return ""; +} +//--------------------------------------------------------------------- +extern "C" __declspec(dllexport) +HBITMAP mcmUpdateText(HANDLE hObj, HBITMAP hDest, LPCSTR pText) +{ + ASSERT(0); // This function should not be called + return NULL; +} +//--------------------------------------------------------------------- +extern "C" __declspec(dllexport) +HBITMAP mcmUpdateImage(HANDLE hObj, HBITMAP hDest, HBITMAP hSrc) +{ + ASSERT(hObj); + ASSERT(hDest); + CItem *pItem = (CItem *)hObj; + if( (hSrc != NULL) && !(pItem->m_sperspect.flag & 0x0000ffff) ){ + // Copy hSrc to the object + Graphics::TBitmap *pSrc = new Graphics::TBitmap; + pSrc->Handle = hSrc; + pItem->CopySource(pSrc); + pSrc->ReleaseHandle(); + delete pSrc; + } + + // Draw object to hDest + Graphics::TBitmap *pDest = new Graphics::TBitmap; + pDest->Handle = hDest; + pItem->Draw(pDest); + + HBITMAP hb = pDest->ReleaseHandle(); + ASSERT(hb); + delete pDest; + return (hb != hDest) ? hb : NULL; +} +//--------------------------------------------------------------------- +extern "C" __declspec(dllexport) +void mcmSetDraft(HANDLE hObj, DWORD draft) +{ + ASSERT(hObj); + CItem *pItem = (CItem *)hObj; + pItem->SetDraft(draft); +} diff --git a/CItems/PERIMG/PerSpect.cpp b/CItems/PERIMG/PerSpect.cpp new file mode 100644 index 0000000..eaf2ed9 --- /dev/null +++ b/CItems/PERIMG/PerSpect.cpp @@ -0,0 +1,287 @@ +//--------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "PerSpect.h" +//--------------------------------------------------------------------- +#pragma resource "*.dfm" +//--------------------------------------------------------------------- +__fastcall TPerSpectDlg::TPerSpectDlg(TComponent* AOwner) + : TForm(AOwner) +{ + m_Loaded = 0; + m_DisEvent = 1; + if( MsgEng ){ + Font->Name = "Arial"; + Font->Charset = ANSI_CHARSET; + Caption = VER" - "TTL; + CancelBtn->Caption = "Cancel"; + DefBtn->Caption = "Default"; + L1->Caption = "Rot.X"; + L2->Caption = "Rot.Y"; + L3->Caption = "Rot.Z"; + L4->Caption = "Move.Z"; + L5->Caption = "Move.Y"; + L6->Caption = "Move.X"; + L7->Caption = "ViewP."; + L8->Caption = "Scale.X"; + L9->Caption = "Scale.Y"; + L10->Caption = "Rot"; + RGSRC->Caption = "Source"; + RGSRC->Items->Strings[0] = "History"; + RGSRC->Items->Strings[1] = "Loaded image"; + RGSRC->Items->Strings[2] = "Overlay"; + PasteBtn->Caption = "Paste"; + } + else { + Caption = VER" - "TTLJ; + } + pBitmap = NULL; + m_pObj = NULL; + m_XC = -1; +} +//--------------------------------------------------------------------------- +void __fastcall TPerSpectDlg::FormDestroy(TObject *Sender) +{ + if( pBitmap != NULL ) delete pBitmap; +} +//--------------------------------------------------------------------------- +int __fastcall TPerSpectDlg::Execute(CObj *pObj) +{ + m_pObj = pObj; + m_Obj.Copy(pObj); + m_Back = m_Obj.m_Back; + LPSPERSPECT psp = &m_Obj.m_sperspect; + + TBAX->Position = psp->ax * 20.0; + TBAY->Position = psp->ay * 20.0; + TBPX->Position = psp->px * 40.0; + TBPY->Position = psp->py * 40.0; + TBPZ->Position = psp->pz * 40.0; + TBRX->Position = psp->rx; + TBRY->Position = psp->ry; + TBRZ->Position = psp->rz; + TBS->Position = psp->s * 10.0; + TBR->Position = psp->r; + RGSRC->ItemIndex = psp->flag; + + UpdateBitmap(); + UpdateBtn(); + m_DisEvent = 0; + if( ShowModal() == IDOK ){ + psp = &pObj->m_sperspect; + psp->ax = double(TBAX->Position)/20.0; + psp->ay = double(TBAY->Position)/20.0; + psp->px = double(TBPX->Position)/40.0; + psp->py = double(TBPY->Position)/40.0; + psp->pz = double(TBPZ->Position)/40.0; + psp->rx = TBRX->Position; + psp->ry = TBRY->Position; + psp->rz = TBRZ->Position; + psp->s = double(TBS->Position)/10.0; + psp->r = TBR->Position; + psp->flag = RGSRC->ItemIndex; + if( psp->flag && m_Loaded && (m_Obj.pBitmap != NULL) ){ + pObj->CopySource(m_Obj.pBitmap); + } + return TRUE; + } + return FALSE; +} +//--------------------------------------------------------------------- +void __fastcall TPerSpectDlg::UpdateBitmap(void) +{ + if( m_Obj.pBitmap == NULL ) return; + + m_Obj.m_sperspect.ax = double(TBAX->Position)/20.0; + m_Obj.m_sperspect.ay = double(TBAY->Position)/20.0; + + m_Obj.m_sperspect.px = double(TBPX->Position)/40.0; + m_Obj.m_sperspect.py = double(TBPY->Position)/40.0; + m_Obj.m_sperspect.pz = double(TBPZ->Position)/40.0; + + m_Obj.m_sperspect.rx = TBRX->Position; + m_Obj.m_sperspect.ry = TBRY->Position; + m_Obj.m_sperspect.rz = TBRZ->Position; + m_Obj.m_sperspect.s = double(TBS->Position)/10.0; + m_Obj.m_sperspect.r = TBR->Position; + + pBitmap = Perspect(pBitmap, m_Obj.pBitmap, &m_Obj.m_sperspect, m_Back); +} +//--------------------------------------------------------------------- +void __fastcall TPerSpectDlg::PBoxPaint(TObject *Sender) +{ + DrawBitmap(PBox, pBitmap); +} +//--------------------------------------------------------------------------- +void __fastcall TPerSpectDlg::TBAXChange(TObject *Sender) +{ + if( m_DisEvent ) return; + + UpdateBitmap(); + PBoxPaint(NULL); +} +//--------------------------------------------------------------------------- +void __fastcall TPerSpectDlg::DefBtnClick(TObject *Sender) +{ +#if 0 // for to get default + FILE *fp = fopen("TEST.TXT", "wt"); + fprintf(fp, "%d\n", TBAX->Position); + fprintf(fp, "%d\n", TBAY->Position); + fprintf(fp, "%d\n", TBPX->Position); + fprintf(fp, "%d\n", TBPY->Position); + fprintf(fp, "%d\n", TBPZ->Position); + fprintf(fp, "%d\n", TBRX->Position); + fprintf(fp, "%d\n", TBRY->Position); + fprintf(fp, "%d\n", TBRZ->Position); + fprintf(fp, "%d\n\n", TBS->Position); + + SPERSPECT *psp = &m_Obj.m_sperspect; + fprintf(fp, "%f\n", psp->ax); + fprintf(fp, "%f\n", psp->ay); + fprintf(fp, "%f\n", psp->px); + fprintf(fp, "%f\n", psp->py); + fprintf(fp, "%f\n", psp->pz); + fprintf(fp, "%f\n", psp->rx); + fprintf(fp, "%f\n", psp->ry); + fprintf(fp, "%f\n", psp->rz); + fprintf(fp, "%f\n", psp->s); + fclose(fp); +#else + m_DisEvent++; + TBAX->Position = 59; + TBAY->Position = 59; + TBPX->Position = 0; + TBPY->Position = 0; + TBPZ->Position = 0; + TBRX->Position = 0; + TBRY->Position = 0; + TBRZ->Position = -180; + TBR->Position = 0; + TBS->Position = 23; + m_DisEvent--; + TBAXChange(NULL); +#endif +} +//--------------------------------------------------------------------------- +void __fastcall TPerSpectDlg::UpdateBtn(void) +{ + LoadBtn->Enabled = RGSRC->ItemIndex && fLoadImageMenu; + PasteBtn->Enabled = LoadBtn->Enabled && Clipboard()->HasFormat(CF_BITMAP); +} +//--------------------------------------------------------------------------- +void __fastcall TPerSpectDlg::RGSRCClick(TObject *Sender) +{ + if( !RGSRC->ItemIndex ){ + if( m_Obj.m_sperspect.flag && fLoadHistImage ){ + if( m_Obj.pBitmap == NULL ) m_Obj.pBitmap = CreateBitmap(16, 16); + m_Obj.pBitmap->Handle = fLoadHistImage(); + } + } + else if( !m_Obj.m_sperspect.flag ){ + if( m_pObj->pBitmap != NULL ) m_Obj.CopySource(m_pObj->pBitmap); + } + m_Obj.m_sperspect.flag = RGSRC->ItemIndex; + UpdateBitmap(); + PBox->Invalidate(); + UpdateBtn(); +} +//--------------------------------------------------------------------------- +void __fastcall TPerSpectDlg::PBoxMouseDown(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + m_XC = PBox->Width / 2; + m_YC = PBox->Height / 2; + int x = X - m_XC; + int y = m_YC - Y; + if( x || y ){ + m_Deg = atan2(y, x); + } + else { + m_Deg = 0; + } + m_Dist = sqrt(x * x + y * y); + m_SDeg = TBR->Position; + m_SDistX = TBAX->Position; + m_SDistY = TBAY->Position; +} +//--------------------------------------------------------------------------- +void __fastcall TPerSpectDlg::PBoxMouseMove(TObject *Sender, + TShiftState Shift, int X, int Y) +{ + if( m_XC > 0 ){ + int x = X - m_XC; + int y = m_YC - Y; + double Deg; + if( x || y ){ + Deg = atan2(y, x); + } + else { + Deg = 0; + } + Deg = (m_Deg - Deg) * 180.0 / PI; + Deg += m_SDeg; + if( Deg < -180 ) Deg += 360.0; + if( Deg > 180 ) Deg -= 360.0; + TBR->Position = SHORT(Deg); + + double Dist = sqrt(x * x + y * y); + Dist = (Dist - m_Dist)/2; + int d = Dist + m_SDistX; + if( d > 201 ) d = 201; + if( d < 2 ) d = 2; + TBAX->Position = d; + d = Dist + m_SDistY; + if( d > 201 ) d = 201; + if( d < 2 ) d = 2; + TBAY->Position = d; + + TBAXChange(NULL); + } +} +//--------------------------------------------------------------------------- +void __fastcall TPerSpectDlg::PBoxMouseUp(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + m_XC = -1; +} +//--------------------------------------------------------------------------- +void __fastcall TPerSpectDlg::LoadBtnClick(TObject *Sender) +{ + if( fLoadImageMenu ){ + HBITMAP hb = fLoadImageMenu(1, 320, 256); + if( hb != NULL ){ + if( m_Obj.pBitmap == NULL ) m_Obj.pBitmap = CreateBitmap(16, 16); + m_Obj.pBitmap->Handle = hb; + m_Loaded = 1; + TBAXChange(NULL); + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TPerSpectDlg::PasteBtnClick(TObject *Sender) +{ + TClipboard *pCB = Clipboard(); + if (pCB->HasFormat(CF_BITMAP)){ + Graphics::TBitmap *pbmp = new Graphics::TBitmap; + try + { + pbmp->LoadFromClipboardFormat(CF_BITMAP, pCB->GetAsHandle(CF_BITMAP), 0); + m_Obj.CopySource(pbmp); + m_Loaded = 1; + TBAXChange(NULL); + } + catch(...){ + } + delete pbmp; + } +} +//--------------------------------------------------------------------------- +void __fastcall TPerSpectDlg::TimerTimer(TObject *Sender) +{ + if( LoadBtn->Enabled ){ + PasteBtn->Enabled = Clipboard()->HasFormat(CF_BITMAP); + } +} +//--------------------------------------------------------------------------- + diff --git a/CItems/PERIMG/PerSpect.dfm b/CItems/PERIMG/PerSpect.dfm new file mode 100644 index 0000000..ecfbba1 Binary files /dev/null and b/CItems/PERIMG/PerSpect.dfm differ diff --git a/CItems/PERIMG/PerSpect.h b/CItems/PERIMG/PerSpect.h new file mode 100644 index 0000000..f7b8f67 --- /dev/null +++ b/CItems/PERIMG/PerSpect.h @@ -0,0 +1,87 @@ +//---------------------------------------------------------------------------- +#ifndef PerSpectDlgH +#define PerSpectDlgH +//---------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//---------------------------------------------------------------------------- +#include "ComLib.h" +//---------------------------------------------------------------------------- +class TPerSpectDlg : public TForm +{ +__published: + TButton *OKBtn; + TButton *CancelBtn; + TTrackBar *TBAX; + TTrackBar *TBAY; + TTrackBar *TBRX; + TTrackBar *TBRY; + TTrackBar *TBRZ; + TPaintBox *PBox; + TTrackBar *TBS; + TTrackBar *TBPX; + TTrackBar *TBPY; + TTrackBar *TBPZ; + TLabel *L1; + TLabel *L2; + TLabel *L3; + TLabel *L4; + TLabel *L5; + TLabel *L6; + TLabel *L7; + TLabel *L8; + TLabel *L9; + TButton *DefBtn; + TRadioGroup *RGSRC; + TTrackBar *TBR; + TLabel *L10; + TButton *LoadBtn; + TButton *PasteBtn; + TTimer *Timer; + void __fastcall PBoxPaint(TObject *Sender); + void __fastcall TBAXChange(TObject *Sender); + void __fastcall DefBtnClick(TObject *Sender); + void __fastcall RGSRCClick(TObject *Sender); + + void __fastcall FormDestroy(TObject *Sender); + void __fastcall PBoxMouseDown(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + void __fastcall PBoxMouseMove(TObject *Sender, TShiftState Shift, + int X, int Y); + void __fastcall PBoxMouseUp(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + void __fastcall LoadBtnClick(TObject *Sender); + void __fastcall PasteBtnClick(TObject *Sender); + void __fastcall TimerTimer(TObject *Sender); + +private: + int m_DisEvent; + Graphics::TBitmap *pBitmap; + CObj m_Obj; + CObj *m_pObj; + TColor m_Back; + void __fastcall UpdateBitmap(void); + + int m_XC, m_YC; + double m_Deg, m_SDeg; + double m_Dist, m_SDistX, m_SDistY; + + void __fastcall UpdateBtn(void); + int m_Loaded; +public: + virtual __fastcall TPerSpectDlg(TComponent* AOwner); + + int __fastcall Execute(CObj *pObj); +}; +//---------------------------------------------------------------------------- +#endif diff --git a/CItems/PERIMG/perimg.rc b/CItems/PERIMG/perimg.rc new file mode 100644 index 0000000..0e32c13 --- /dev/null +++ b/CItems/PERIMG/perimg.rc @@ -0,0 +1,2 @@ +8000 ICON DISCARDABLE "Item.ico" + \ No newline at end of file diff --git a/CItems/PERIMG/perimg.res b/CItems/PERIMG/perimg.res new file mode 100644 index 0000000..5f5245c Binary files /dev/null and b/CItems/PERIMG/perimg.res differ diff --git a/CItems/PERIMG/res/SB.bmp b/CItems/PERIMG/res/SB.bmp new file mode 100644 index 0000000..f8dff21 Binary files /dev/null and b/CItems/PERIMG/res/SB.bmp differ diff --git a/CItems/PERIMG/res/SBA.bmp b/CItems/PERIMG/res/SBA.bmp new file mode 100644 index 0000000..b4b4f8e Binary files /dev/null and b/CItems/PERIMG/res/SBA.bmp differ diff --git a/CItems/PERIMG/res/SBB.bmp b/CItems/PERIMG/res/SBB.bmp new file mode 100644 index 0000000..6d1f4fa Binary files /dev/null and b/CItems/PERIMG/res/SBB.bmp differ diff --git a/CItems/PERIMG/res/SBC.bmp b/CItems/PERIMG/res/SBC.bmp new file mode 100644 index 0000000..39683d6 Binary files /dev/null and b/CItems/PERIMG/res/SBC.bmp differ diff --git a/CItems/PERIMG/res/SBD.bmp b/CItems/PERIMG/res/SBD.bmp new file mode 100644 index 0000000..bdba52d Binary files /dev/null and b/CItems/PERIMG/res/SBD.bmp differ diff --git a/CItems/PERIMG/res/SBE.bmp b/CItems/PERIMG/res/SBE.bmp new file mode 100644 index 0000000..992aef9 Binary files /dev/null and b/CItems/PERIMG/res/SBE.bmp differ diff --git a/CItems/PERIMG/res/SBF.bmp b/CItems/PERIMG/res/SBF.bmp new file mode 100644 index 0000000..769f4ad Binary files /dev/null and b/CItems/PERIMG/res/SBF.bmp differ diff --git a/CItems/PERIMG/res/SBG.bmp b/CItems/PERIMG/res/SBG.bmp new file mode 100644 index 0000000..37059fc Binary files /dev/null and b/CItems/PERIMG/res/SBG.bmp differ diff --git a/CItems/PERIMG/res/SBH.bmp b/CItems/PERIMG/res/SBH.bmp new file mode 100644 index 0000000..6a19934 Binary files /dev/null and b/CItems/PERIMG/res/SBH.bmp differ diff --git a/CItems/PERIMG/res/SBI.bmp b/CItems/PERIMG/res/SBI.bmp new file mode 100644 index 0000000..49be86c Binary files /dev/null and b/CItems/PERIMG/res/SBI.bmp differ diff --git a/CItems/PERIMG/res/SBJ.bmp b/CItems/PERIMG/res/SBJ.bmp new file mode 100644 index 0000000..1359fe4 Binary files /dev/null and b/CItems/PERIMG/res/SBJ.bmp differ diff --git a/CItems/PERIMG/res/SBK.bmp b/CItems/PERIMG/res/SBK.bmp new file mode 100644 index 0000000..e5c9bfa Binary files /dev/null and b/CItems/PERIMG/res/SBK.bmp differ diff --git a/CItems/PERIMG/res/SBL.bmp b/CItems/PERIMG/res/SBL.bmp new file mode 100644 index 0000000..3a32561 Binary files /dev/null and b/CItems/PERIMG/res/SBL.bmp differ diff --git a/CItems/PERIMG/res/SBM.bmp b/CItems/PERIMG/res/SBM.bmp new file mode 100644 index 0000000..ad31e40 Binary files /dev/null and b/CItems/PERIMG/res/SBM.bmp differ diff --git a/CItems/PERIMG/res/SBN.bmp b/CItems/PERIMG/res/SBN.bmp new file mode 100644 index 0000000..a37f336 Binary files /dev/null and b/CItems/PERIMG/res/SBN.bmp differ diff --git a/CItems/PERIMG/res/SBO.bmp b/CItems/PERIMG/res/SBO.bmp new file mode 100644 index 0000000..049a999 Binary files /dev/null and b/CItems/PERIMG/res/SBO.bmp differ diff --git a/CItems/PERIMG/res/SBP.bmp b/CItems/PERIMG/res/SBP.bmp new file mode 100644 index 0000000..4871f9b Binary files /dev/null and b/CItems/PERIMG/res/SBP.bmp differ diff --git a/CItems/PERIMG/res/SBQ.bmp b/CItems/PERIMG/res/SBQ.bmp new file mode 100644 index 0000000..caa4457 Binary files /dev/null and b/CItems/PERIMG/res/SBQ.bmp differ diff --git a/CItems/QSLBox/About.cpp b/CItems/QSLBox/About.cpp new file mode 100644 index 0000000..205c6d9 --- /dev/null +++ b/CItems/QSLBox/About.cpp @@ -0,0 +1,29 @@ +//--------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "About.h" +#include "ComLib.h" +//--------------------------------------------------------------------- +#pragma resource "*.dfm" +//TAboutDlg *AboutDlg; +//--------------------------------------------------------------------- +__fastcall TAboutDlg::TAboutDlg(HWND hWnd) + : TForm(hWnd) +{ + if( sys.m_MsgEng ){ + Font->Name = "Arial"; + Font->Charset = ANSI_CHARSET; + Caption = TTL; + } + else { + Caption = TTLJ; + } + LVer->Caption = VER" "AUT; + HICON hIcon = ::LoadIcon(HInstance, (LPCSTR)8000); + TIcon *pIcon = new TIcon; + pIcon->Handle = hIcon; + Image->Picture->Icon = pIcon; +} +//--------------------------------------------------------------------- + diff --git a/CItems/QSLBox/About.dfm b/CItems/QSLBox/About.dfm new file mode 100644 index 0000000..0e17e4b Binary files /dev/null and b/CItems/QSLBox/About.dfm differ diff --git a/CItems/QSLBox/About.h b/CItems/QSLBox/About.h new file mode 100644 index 0000000..5910040 --- /dev/null +++ b/CItems/QSLBox/About.h @@ -0,0 +1,29 @@ +//---------------------------------------------------------------------------- +#ifndef OCRH +#define OCRH +//---------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//---------------------------------------------------------------------------- +class TAboutDlg : public TForm +{ +__published: + TButton *OKBtn; + TLabel *LVer; + TImage *Image; +private: +public: + virtual __fastcall TAboutDlg(HWND hWnd); +}; +//---------------------------------------------------------------------------- +//extern PACKAGE TAboutDlg *AboutDlg; +//---------------------------------------------------------------------------- +#endif diff --git a/CItems/QSLBox/Comlib.cpp b/CItems/QSLBox/Comlib.cpp new file mode 100644 index 0000000..85e17a5 --- /dev/null +++ b/CItems/QSLBox/Comlib.cpp @@ -0,0 +1,2165 @@ +//--------------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "ComLib.h" +#include "TextDlg.h" +SYS sys; +// +//--------------------------------------------------------------------------- +//void mcmFunc(DWORD index, FARPROC pFunc) +// +//MMSSTV calls this function at the first time, if the function was exported. +//You can use following functions which are in the MMSSTV. +// +// index : Index of the function. +// pFunc : Address of the function. +// +//indexes and functions are as follows. +// +// 0 : HBITMAP (__cdecl *mmLoadImageMenu)(int sw, int xw, int yw); +// sw - 0 : Invoke image-clipper (xw and yw are the size of the bitmap) +// sw - 1 : no image-clipper (xw and yw will be ignored) +// +// 1 : HBITMAP (__cdecl *mmLoadImage)(LPCSTR pName); +// pName is a pathname of the image (BMP, JPG, WMF) +// +// 2 : HBITMAP (__cdecl *mmLoadHistImage)(void); +// +// 3 : int (__cdecl *mmSaveImageMenu)(HBITMAP hb, LPCSTR pName, LPCSTR pFolder); +// pName is a filename of the image (BMP, JPG) +// pFolder is a folder name (if it is NULL, MMSSTV uses a default) +// +// 4 : int (__cdecl *mmSaveImage)(HBITMAP hb, LPCSTR pName); +// pName is a pathname of the image (BMP, JPG) +// +// 5 : HBITMAP (__cdecl *mmPasteImage)(int sw, int xw, int yw); +// sw - 0 : Invoke image-clipper (xw and yw are the size of the bitmap) +// sw - 1 : no image-clipper (xw and yw will be ignored) +// +// 6 : int (__cdecl *mmGetMacKey)(LPSTR pDest, int cbDest); +// Invoke macro dialog box and can choose keyword +// +// 7 : int (__cdecl *mmConvMac)(LPSTR pDest, LPCSTR pSrc, int cbDest); +// Convert macro keyword (pSrc) to the text (pDest) +// +// 8 : HBITMAP (__cdecl *mmCreateDIB)(int xw, int yw); +// Create 24bit DIB +// +// 9 : void (__cdecl *mmMultProc)(void); +// 10 : void (__cdecl *mmMultProcA)(void); +// Do decoding and encoding with the DSP in MMSSTV +// +// 11 : int (__cdecl *mmColorComp)(LPDWORD pCol); +// Invoke color components dialog and can choose a color component +// +extern "C" __declspec(dllexport) +void mcmFunc(DWORD index, FARPROC pFunc) +{ + switch(index){ + case 6: + sys.m_fGetMacKey = (mmGetMacKey)pFunc; + break; + case 7: + sys.m_fConvMac = (mmConvMac)pFunc; + break; + case 9: + sys.m_fMultProc = (mmMultProc)pFunc; + break; + case 11: + sys.m_fColorComp = (mmColorComp)pFunc; + break; + default: + break; + } +} +//--------------------------------------------------------------------------- +void __fastcall MultProc(void) +{ + if( sys.m_fMultProc ) sys.m_fMultProc(); +} +//--------------------------------------------------------------------------- +char __fastcall LastC(LPCSTR p) +{ + char c = 0; + + if( *p ){ + c = *(p + strlen(p) - 1); + } + return c; +} +//--------------------------------------------------------------------------- +void __fastcall SetCurDir(LPSTR t, int size) +{ + if( !::GetCurrentDirectory(size-1, t) ){ + *t = 0; + } + else { + if( LastC(t) != '\\' ){ + strcat(t, "\\"); + } + } +} +//--------------------------------------------------------------------------- +void __fastcall SetDirName(LPSTR t, LPCSTR pName) +{ + char drive[_MAX_DRIVE]; + char dir[_MAX_DIR]; + char name[_MAX_FNAME]; + char ext[_MAX_EXT]; + AnsiString Dir; + + ::_splitpath( pName, drive, dir, name, ext ); + Dir = drive; + Dir += dir; + strncpy(t, Dir.c_str(), 128); +} +///---------------------------------------------------------------- +void __fastcall Yen2CrLf(AnsiString &ws, AnsiString cs) +{ + ws = ""; + LPCSTR p; + int f; + int dlm = 0; + + p = cs.c_str(); + if( *p == 0x22 ){ + p++; + dlm++; + } + for( f = 0; *p; p++ ){ + if( f ){ + f = 0; + ws += *p; + } + else if( _mbsbtype((const unsigned char *)p, 0) == _MBC_LEAD ){ + f = 1; + ws += *p; + } + else if( *p == '\\' ){ + switch(*(p+1)){ + case 'r': + ws += "\r"; + p++; + break; + case 'n': + ws += "\n"; + p++; + break; + case 't': + ws += "\t"; + p++; + break; + case '\\': + ws += "\\"; + p++; + break; + default: + p++; + ws += *p; + break; + } + } + else if( !dlm || (*p!=0x22) || *(p+1) ){ + ws += *p; + } + } +} +//--------------------------------------------------------------------------- +void __fastcall CrLf2Yen(AnsiString &ws, AnsiString cs) +{ + ws = "\x22"; + LPCSTR p; + int f = 0; + + for( p = cs.c_str(); *p; p++ ){ + if( f ){ + ws += *p; + f = 0; + } + else if( _mbsbtype((const unsigned char *)p, 0) == _MBC_LEAD ){ + f = 1; + ws += *p; + } + else if( *p == 0x0d ){ + ws += "\\r"; + } + else if( *p == 0x0a ){ + ws += "\\n"; + } + else if( *p == '\t' ){ + ws += "\\t"; + } + else if( *p == '\\' ){ + ws += "\\\\"; + } + else { + ws += *p; + } + } + ws += "\x22"; +} +//--------------------------------------------------------------------------- +void __fastcall LoadStringsFromIniFile(TStrings *pList, LPCSTR pSect, LPCSTR pName) +{ + char fname[512]; + sprintf(fname, "%s%s", sys.m_BgnDir, pName); + TIniFile *pIniFile = new TIniFile(fname); + int count = pIniFile->ReadInteger(pSect, "Count", 0); + int i; + AnsiString as; + for( i = 0; i < count; i++ ){ + char bf[32]; + sprintf(bf, "Text%u", i); + as = pIniFile->ReadString(pSect, bf, ""); + if( !as.IsEmpty() ){ + pList->Add(as.c_str()); + } + } + delete pIniFile; +} +//--------------------------------------------------------------------------- +void __fastcall SaveStringsToIniFile(TStrings *pList, LPCSTR pSect, LPCSTR pName) +{ + char fname[512]; + sprintf(fname, "%s%s", sys.m_BgnDir, pName); + TIniFile *pIniFile = new TIniFile(fname); + pIniFile->WriteInteger(pSect, "Count", pList->Count); + int i; + for( i = 0; i < pList->Count; i++ ){ + char bf[32]; + sprintf(bf, "Text%u", i); + pIniFile->WriteString(pSect, bf, pList->Strings[i]); + } + delete pIniFile; +} +//--------------------------------------------------------------------- +void __fastcall InitCustomColor(TColorDialog *tp) +{ + tp->CustomColors->Text = ""; +} +//--------------------------------------------------------------------- +void __fastcall AddCustomColor(TColorDialog *tp, TColor col) +{ + char bf[256]; + + sprintf(bf, "Color%c=%06lX", tp->CustomColors->Count + 'A', DWORD(col) & 0x00ffffff); + tp->CustomColors->Add(bf); +} +//--------------------------------------------------------------------- +LPSTR __fastcall ZeroConv(LPCSTR p, BYTE charset) +{ + LPSTR bp = new char[(strlen(p)*2) + 1]; + LPSTR t = bp; + int f = 0; + for( ; *p; p++ ){ + if( f ){ + *t++ = *p; + f = 0; + } + else if( _mbsbtype((const unsigned char *)p, 0) == _MBC_LEAD ){ + *t++ = *p; + f = 1; + } + else if( *p == '0' ){ + switch(charset){ + case SHIFTJIS_CHARSET: + *t++ = 0x83; + *t++ = 0xd3; + break; + case HANGEUL_CHARSET: + *t++ = 0xa8; // 0xa9 + *t++ = 0xaa; + break; + case CHINESEBIG5_CHARSET: // 台湾 + *t++ = 0xa3; + *t++ = 0x58; + break; + case 134: // 中国語簡略 + *t++ = 0xa6; + *t++ = 0xd5; + break; + default: + switch(sys.m_CodePage){ + case 949: // HANGEUL + *t++ = 0xa8; // 0xa9 + *t++ = 0xaa; + break; + case 950: // CHINESEBIG5 + *t++ = 0xa3; + *t++ = 0x58; + break; + case 936: // CHINESE 簡略 + *t++ = 0xa6; + *t++ = 0xd5; + break; + default: + *t++ = 'リ'; + break; + } + break; + } + } + else { + *t++ = *p; + } + } + *t = 0; + return bp; +} +//--------------------------------------------------------------------------- +Graphics::TBitmap * __fastcall CreateBitmap(int xw, int yw) +{ + Graphics::TBitmap *pBitmap = new Graphics::TBitmap; + pBitmap->PixelFormat = pf24bit; + pBitmap->Width = xw; + pBitmap->Height = yw; + return pBitmap; +} +//--------------------------------------------------------------------------- +void __fastcall FillBitmap(Graphics::TBitmap *pDest, UCOL ucol) +{ + TRect rc; + rc.Left = rc.Top = 0; + rc.Right = pDest->Width; + rc.Bottom = pDest->Height; + pDest->Canvas->Brush->Color = ucol.c; + pDest->Canvas->FillRect(rc); +} +//--------------------------------------------------------------------------- +void __fastcall CopyBitmap(Graphics::TBitmap *pDest, Graphics::TBitmap *pSrc) +{ + pDest->Width = pSrc->Width; + pDest->Height = pSrc->Height; + pDest->Palette = NULL; + pDest->Canvas->Draw(0, 0, pSrc); +} +//--------------------------------------------------------------------------- +//アスペクト比を保持する +void __fastcall KeepAspect(int &sx, int &sy, int bx, int by) +{ + double ass = double(sx) / double(sy); + double asb = double(bx) / double(by); + if( asb < ass ){ // ソースの方が横長 + sx = (double(sy) * asb) + 0.5; + } + else { + sy = (double(sx) / asb) + 0.5; + } +} +//--------------------------------------------------------------------------- +//アスペクト比を保持する +void __fastcall KeepAspectCopy(Graphics::TBitmap *pDest, int xm, int ym, Graphics::TBitmap *pSrc, int mode) +{ + if( (xm < pSrc->Width) || (ym < pSrc->Height) ){ + KeepAspect(xm, ym, pSrc->Width, pSrc->Height); + pDest->Width = xm; + pDest->Height = ym; + pDest->Palette = NULL; + TRect tc; + tc.Left = tc.Top = 0; + tc.Right = xm; tc.Bottom = ym; + int Sop = ::SetStretchBltMode(pDest->Canvas->Handle, mode); + pDest->Canvas->StretchDraw(tc, pSrc); + ::SetStretchBltMode(pDest->Canvas->Handle, Sop); + } + else { + CopyBitmap(pDest, pSrc); + } +} +//--------------------------------------------------------------------------- +void __fastcall DrawBitmap(TPaintBox *pBox, Graphics::TBitmap *pBitmap) +{ + if( pBitmap == NULL ) return; + + if( (pBitmap->Width != pBox->Width)||(pBitmap->Height != pBox->Height) ){ + TRect rc; + rc.Left = 0; rc.Right = pBox->Width; + rc.Top = 0, rc.Bottom = pBox->Height; + int Sop = ::SetStretchBltMode(pBox->Canvas->Handle, HALFTONE); + pBox->Canvas->StretchDraw(rc, pBitmap); + ::SetStretchBltMode(pBox->Canvas->Handle, Sop); + } + else { + pBox->Canvas->Draw(0, 0, pBitmap); + } +} +//--------------------------------------------------------------------------- +UCOL __fastcall GetUniqueColor(HDC hdc, UCOL ucol) +{ + ucol.d = ucol.d & 0x00e0e0e0; + UCOL c = ucol; + + while(c.d == ucol.d){ +#if (RANDMAX >= 0x00ffffff) + c.d = rand() & 0x00e0e0e0; +#else + c.b.r = (BYTE)(rand() & 0x00e0); + c.b.g = (BYTE)(rand() & 0x00e0); + c.b.b = (BYTE)(rand() & 0x00e0); +#endif + } + c.d = GetNearestColor(hdc, (COLORREF)c.d); + return c; +} +//--------------------------------------------------------------------------- +UCOL __fastcall GetGrade2(UCOL s[2], int x, int xw) +{ + if( x < 0 ) x = 0; + if( x > xw ) x = xw; + UCOL r; + int c = s[0].b.b + ((int(s[1].b.b) - int(s[0].b.b)) * x / xw); + if( c < 0 ) c = 0; + if( c > 255 ) c = 255; + r.b.b = BYTE(c); + c = s[0].b.g + ((int(s[1].b.g) - int(s[0].b.g)) * x / xw); + if( c < 0 ) c = 0; + if( c > 255 ) c = 255; + r.b.g = BYTE(c); + c = s[0].b.r + ((int(s[1].b.r) - int(s[0].b.r)) * x / xw); + if( c < 0 ) c = 0; + if( c > 255 ) c = 255; + r.b.r = BYTE(c); + return r; +} +//--------------------------------------------------------------------------- +UCOL __fastcall GetGrade4(UCOL s[4], int x, int xw) +{ + int xw3 = xw/3; + if( x < xw3 ){ + return GetGrade2(s, x, xw3); + } + x -= xw3; + if( x < xw3 ){ + return GetGrade2(&s[1], x, xw3); + } + x -= xw3; + return GetGrade2(&s[2], x, xw3); +} +//--------------------------------------------------------------------------- +void __fastcall WriteString(TStream *ps, AnsiString &as) +{ + int len = as.Length(); + ps->Write(&len, sizeof(len)); + if( len ){ + ps->Write(as.c_str(), len); + } +} +void __fastcall ReadString(TStream *ps, AnsiString &as) +{ + as = ""; + int len; + ps->Read(&len, sizeof(len)); + if( len ){ + LPSTR p = new char[len+1]; + ps->Read(p, len); + p[len] = 0; + as = p; + delete p; + } +} +//--------------------------------------------------------------------------- +int FontStyle2Code(TFontStyles style) +{ + int code = 0; + + TFontStyles fa; + TFontStyles fb; + + fa << fsBold; + fb << fsBold; + fa *= style; + if( fa == fb ) code |= FSBOLD; + + fa >> fsBold; + fb >> fsBold; + fa << fsItalic; + fb << fsItalic; + fa *= style; + if( fa == fb ) code |= FSITALIC; + + fa >> fsItalic; + fb >> fsItalic; + fa << fsUnderline; + fb << fsUnderline; + fa *= style; + if( fa == fb ) code |= FSUNDERLINE; + + fa >> fsUnderline; + fb >> fsUnderline; + fa << fsStrikeOut; + fb << fsStrikeOut; + fa *= style; + if( fa == fb ) code |= FSSTRIKEOUT; + + return code; +} + +TFontStyles Code2FontStyle(int code) +{ + TFontStyles fs; + + if( code & FSBOLD ) fs << fsBold; + if( code & FSITALIC ) fs << fsItalic; + if( code & FSUNDERLINE ) fs << fsUnderline; + if( code & FSSTRIKEOUT ) fs << fsStrikeOut; + return fs; +} +//--------------------------------------------------------------------------- +void __fastcall WriteFont(TStream *ps, TFont *pFont) +{ + int d; + if( pFont != NULL ){ + d = 1; + ps->Write(&d, sizeof(d)); + WriteString(ps, pFont->Name); + d = pFont->Charset; + ps->Write(&d, sizeof(d)); + d = pFont->Height; + ps->Write(&d, sizeof(d)); + TFontStyles ts = pFont->Style; + d = FontStyle2Code(ts); + ps->Write(&d, sizeof(d)); + } + else { + d = 0; + ps->Write(&d, sizeof(d)); + } +} +//--------------------------------------------------------------------------- +TFont* __fastcall ReadFont(TStream *ps) +{ + TFont *pFont = NULL; + int d; + ps->Read(&d, sizeof(d)); + if( d == 1 ){ + pFont = new TFont; + AnsiString as; + ReadString(ps, as); + pFont->Name = as; + ps->Read(&d, sizeof(d)); + pFont->Charset = BYTE(d); + ps->Read(&d, sizeof(d)); + pFont->Height = d; + ps->Read(&d, sizeof(d)); + TFontStyles ts = Code2FontStyle(d); + pFont->Style = ts; + } + return pFont; +} +//--------------------------------------------------------------------------- +int __fastcall IsInside(POINT &pnt, RECT &rc) +{ + if( rc.left < rc.right ){ + if( pnt.x < rc.left ) return FALSE; + if( pnt.x > rc.right ) return FALSE; + } + else { + if( pnt.x > rc.left ) return FALSE; + if( pnt.x < rc.right ) return FALSE; + } + if( rc.top > rc.bottom ){ + if( pnt.y > rc.top ) return FALSE; + if( pnt.y < rc.bottom ) return FALSE; + } + else { + if( pnt.y < rc.top ) return FALSE; + if( pnt.y > rc.bottom ) return FALSE; + } + return TRUE; +} + +int __fastcall IsNear(POINT &pnt, POINT &tpnt, int Width) +{ + RECT rc; + rc.left = tpnt.x - Width; + rc.right = tpnt.x + Width; + rc.top = tpnt.y + Width; + rc.bottom = tpnt.y - Width; + return IsInside(pnt, rc); +} + +int __fastcall IsLine(POINT &pnt, POINT &spnt, POINT &tpnt, int Width) +{ + int Xw = tpnt.x - spnt.x; + int Yw = tpnt.y - spnt.y; + double A, B; + int C; + + if( IsNear(pnt, spnt, Width)==TRUE ){ + return HT_P1; /* 始点と一致 */ + } + else if( IsNear(pnt, tpnt, Width)==TRUE ){ + return HT_P2; /* 終点と一致 */ + } + if( spnt.x > tpnt.x ){ /* X方向の入れ替え */ + POINT bpnt = spnt; + spnt = tpnt; + tpnt = bpnt; + } + if( (pnt.x >= (spnt.x-Width)) && (pnt.x <= (tpnt.x+Width)) ){ + if( Xw ){ + A = double(Yw)/double(Xw); + B = double(spnt.y) - (A * double(spnt.x)); + C = int((A * double(pnt.x)) + B); + A = A < 0.0 ? -A : A; + if( A >= 1.0 ){ + Width = int(double(Width) * A); + } + if( (pnt.y < (C+Width)) && (pnt.y >= (C-Width)) ){ + return HT_PM; + } + } + else if( spnt.y > tpnt.y ){ + if( (pnt.y < spnt.y) && (pnt.y > tpnt.y) ){ + return HT_PM; + } + } + else if( (pnt.y > spnt.y) && (pnt.y < tpnt.y) ){ + return HT_PM; + } + } + return 0; +} + +int __fastcall IsLine(POINT &pnt, POINT &spnt, POINT &tpnt) +{ + int r = IsLine(pnt, spnt, tpnt, 4); + if( (r == HT_P1)||(r == HT_P2) ) return r; + return IsLine(pnt, spnt, tpnt, 10) ? HT_PM : 0; +} +//*************************************************************************** +//DrawGroupクラス +//--------------------------------------------------------------------------- +__fastcall CDraw::CDraw() +{ + m_Ver = 0; + m_Cursor = 0; + m_CX1 = m_CY1 = 0; + m_CX2 = m_CY2 = 0; + m_LineColor.c = clBlack; + m_LineStyle = psSolid; + m_LineWidth = 1; + m_X1 = m_Y1 = m_X2 = m_Y2 = 0; + m_BX = m_BY = m_MF = 0; + m_pCanvas = NULL; +} + +void __fastcall CDraw::Start(TCanvas *pCanvas, int x, int y) +{ + m_pCanvas = pCanvas; + m_CX1 = m_X1 = x; + m_CY1 = m_Y1 = y; +} + +void __fastcall CDraw::StartMove(TCanvas *pCanvas, int x, int y, int code) +{ + m_pCanvas = pCanvas; + m_BX = x; + m_BY = y; + m_MF = 0; + m_MC = code; + m_CX1 = m_X1; + m_CX2 = m_X2; + m_CY1 = m_Y1; + m_CY2 = m_Y2; +} + +int __fastcall CDraw::Edit(void) +{ +#if 0 + TLineSetDlg *pBox = new TLineSetDlg(Mmsstv); + int r = pBox->Execute(this); + delete pBox; + return r; +#endif +} + +int __fastcall CDraw::Color(void) +{ +#if 0 + InitCustomColor(Mmsstv->ColorDialog); + AddCustomColor(Mmsstv->ColorDialog, m_LineColor); + Mmsstv->ColorDialog->Color = m_LineColor; + DisPaint++; + if( Mmsstv->ColorDialog->Execute() == TRUE ){ + m_LineColor = Mmsstv->ColorDialog->Color; + DisPaint--; + return TRUE; + } + DisPaint--; + return FALSE; +#endif +} + +void __fastcall CDraw::SaveToStream(TStream *sp) +{ + sp->Write(&m_Command, sizeof(m_Command)); + sp->Write(&m_Ver, sizeof(m_Ver)); + sp->Write(&m_X1, sizeof(m_X1)); + sp->Write(&m_Y1, sizeof(m_Y1)); + sp->Write(&m_X2, sizeof(m_X2)); + sp->Write(&m_Y2, sizeof(m_Y2)); + sp->Write(&m_LineColor, sizeof(m_LineColor)); + sp->Write(&m_LineStyle, sizeof(m_LineStyle)); + sp->Write(&m_LineWidth, sizeof(m_LineWidth)); +} + +int __fastcall CDraw::LoadFromStream(TStream *sp) +{ + try { + pc = tp; + sp->Read(&m_Ver, sizeof(m_Ver)); + sp->Read(&m_X1, sizeof(m_X1)); + sp->Read(&m_Y1, sizeof(m_Y1)); + sp->Read(&m_X2, sizeof(m_X2)); + sp->Read(&m_Y2, sizeof(m_Y2)); + sp->Read(&m_LineColor, sizeof(m_LineColor)); + sp->Read(&m_LineStyle, sizeof(m_LineStyle)); + sp->Read(&m_LineWidth, sizeof(m_LineWidth)); + return TRUE; + } + catch(...){ + return FALSE; + } +} + +void __fastcall CDraw::Copy(CDraw *dp) +{ +} + +void __fastcall CDraw::Normal(void) +{ + NormalRect(m_X1, m_Y1, m_X2, m_Y2); +} + +//--------------------------------------------------------------------------- +__fastcall CDrawLine::CDrawLine() +{ + m_Command = CM_LINE; + m_Cursor = 0; +} + +int __fastcall CDrawLine::Finish(int x, int y) +{ + m_X2 = x; + m_Y2 = y; + return ((m_X1 != m_X2)||(m_Y1 != m_Y2)) ? TRUE : FALSE; +} + +void __fastcall CDrawLine::Draw(TCanvas *pCanvas) +{ + m_pCanvas = pCanvas; + pCanvas->Pen->Color = m_LineColor; + pCanvas->Pen->Style = m_LineStyle; + pCanvas->Pen->Width = m_LineWidth; + pCanvas->MoveTo(m_X1, m_Y1); + pCanvas->LineTo(m_X2, m_Y2); +} + +void __fastcall CDrawLine::DrawSel(TCanvas *pCanvas, int sw) +{ + m_pCanvas = pCanvas; + pCanvas->Pen->Color = clBlue; + pCanvas->Pen->Style = psDot; + pCanvas->Pen->Width = 1; + pCanvas->MoveTo(m_X1, m_Y1); + int rop = ::SetROP2(pCanvas->Handle, sw ? R2_NOT : R2_COPYPEN); + pCanvas->LineTo(m_X2, m_Y2); + ::SetROP2(pCanvas->Handle, rop); +} + +void __fastcall CDrawLine::DrawCursor(void) +{ + ASSERT(m_pCanvas); + m_pCanvas->Pen->Style = psDot; + m_pCanvas->Pen->Width = 1; + m_pCanvas->MoveTo(m_CX1, m_CY1); + int Sop = ::SetROP2(m_pCanvas->Handle, R2_NOT); + m_pCanvas->LineTo(m_CX2, m_CY2); + ::SetROP2(m_pCanvas->Handle, Sop); +} + +void __fastcall CDrawLine::Making(int x, int y) +{ + if( m_Cursor ) DrawCursor(); + m_CX2 = x; + m_CY2 = y; + DrawCursor(); + m_Cursor = 1; +} + +int __fastcall CDrawLine::HitTest(int x, int y) +{ + POINT N; + POINT B, E; + N.x = x; N.y = y; + B.x = m_X1; B.y = m_Y1; + E.x = m_X2; E.y = m_Y2; + return IsLine(N, B, E, 5) ? HT_I : HT_NONE; +} + +void __fastcall CDrawLine::Moving(int x, int y) +{ + if( m_Cursor ) DrawCursor(); + if( !m_MF ){ + if( m_BX != x ) m_MF = 1; + if( m_BY != y ) m_MF = 1; + } + x -= m_BX; + y -= m_BY; + m_CX1 = m_X1 + x; + m_CX2 = m_X2 + x; + m_CY1 = m_Y1 + y; + m_CY2 = m_Y2 + y; + DrawCursor(); + m_Cursor = 1; +} + +void __fastcall CDrawLine::Move(int x, int y) +{ + m_X1 = m_CX1; + m_Y1 = m_CY1; + m_X2 = m_CX2; + m_Y2 = m_CY2; +} + +//--------------------------------------------------------------------------- +__fastcall CDrawBox::CDrawBox() +{ + m_Command = CM_BOX; +} + +int __fastcall CDrawBox::Finish(int x, int y) +{ + m_X2 = x; + m_Y2 = y; + Normal(); + return ((m_X1 != m_X2)&&(m_Y1 != m_Y2)) ? TRUE : FALSE; +} + +void __fastcall CDrawBox::Draw(TCanvas *pCanvas) +{ + if( m_LineStyle < 0 ) return; + + pCanvas->Pen->Color = m_LineColor; + pCanvas->Pen->Style = m_LineStyle; + pCanvas->Pen->Width = m_LineWidth; + pCanvas->MoveTo(m_X1, m_Y1); + pCanvas->LineTo(m_X2, m_Y1); + pCanvas->LineTo(m_X2, m_Y2); + pCanvas->LineTo(m_X1, m_Y2); + pCanvas->LineTo(m_X1, m_Y1); +} + +void __fastcall CDrawBox::DrawSel(TCanvas *pCanvas, int sw) +{ + pCanvas->Brush->Color = clWhite; + pCanvas->Pen->Color = clBlue; + pCanvas->Pen->Width = 1; + pCanvas->Pen->Style = psDot; + pCanvas->MoveTo(m_X1, m_Y1); + int rop = ::SetROP2(pCanvas->Handle, sw ? R2_NOT : R2_COPYPEN); + pCanvas->LineTo(m_X2, m_Y1); + pCanvas->LineTo(m_X2, m_Y2); + pCanvas->LineTo(m_X1, m_Y2); + pCanvas->LineTo(m_X1, m_Y1); + ::SetROP2(pCanvas->Handle, rop); +} + +void __fastcall CDrawBox::DrawCursor(void) +{ + ASSERT(m_pCanvas); + m_pCanvas->Pen->Style = psDot; + m_pCanvas->Pen->Width = 1; + m_pCanvas->MoveTo(m_CX1, m_CY1); + int Sop = ::SetROP2(m_pCanvas->Handle, R2_NOT); + m_pCanvas->LineTo(m_CX2, m_CY1); + m_pCanvas->LineTo(m_CX2, m_CY2); + m_pCanvas->LineTo(m_CX1, m_CY2); + m_pCanvas->LineTo(m_CX1, m_CY1); + ::SetROP2(m_pCanvas->Handle, Sop); +} + +void __fastcall CDrawBox::Making(int x, int y) +{ + if( m_Cursor ) DrawCursor(); + m_CX2 = x; + m_CY2 = y; + DrawCursor(); + m_Cursor = 1; +} + +int __fastcall CDrawBox::HitTest(int x, int y) +{ + POINT N; + POINT B, E; + N.x = x; N.y = y; + B.x = m_X1; B.y = m_Y1; + E.x = m_X2; E.y = m_Y1; + int r = IsLine(N, B, E, 5); + if( r ){ + switch(r){ + case HT_P1: + return HT_LT; + case HT_P2: + return HT_RT; + default: + return HT_T; + } + } + B.x = m_X2; B.y = m_Y1; + E.x = m_X2; E.y = m_Y2; + r = IsLine(N, B, E, 5); + if( r ){ + switch(r){ + case HT_P1: + return HT_RT; + case HT_P2: + return HT_RB; + default: + return HT_R; + } + } + B.x = m_X2; B.y = m_Y2; + E.x = m_X1; E.y = m_Y2; + r = IsLine(N, B, E, 5); + if( r ){ + switch(r){ + case HT_P1: + return HT_RB; + case HT_P2: + return HT_LB; + default: + return HT_B; + } + } + B.x = m_X1; B.y = m_Y2; + E.x = m_X1; E.y = m_Y1; + r = IsLine(N, B, E, 5); + if( r ){ + switch(r){ + case HT_P1: + return HT_LB; + case HT_P2: + return HT_LT; + default: + return HT_L; + } + } + if( (x < m_X1) || (x > m_X2) ) return FALSE; + if( (y < m_Y1) || (y > m_Y2) ) return FALSE; + return HT_I; +} + +void __fastcall CDrawBox::Moving(int x, int y) +{ + if( m_Cursor ) DrawCursor(); + if( !m_MF ){ + if( m_BX != x ) m_MF = 1; + if( m_BY != y ) m_MF = 1; + } + x -= m_BX; + y -= m_BY; + switch(m_MC){ + case HT_LT: + m_CX1 = m_X1 + x; + m_CY1 = m_Y1 + y; + break; + case HT_T: + m_CY1 = m_Y1 + y; + break; + case HT_RT: + m_CX2 = m_X2 + x; + m_CY1 = m_Y1 + y; + break; + case HT_R: + m_CX2 = m_X2 + x; + break; + case HT_RB: + m_CX2 = m_X2 + x; + m_CY2 = m_Y2 + y; + break; + case HT_B: + m_CY2 = m_Y2 + y; + break; + case HT_LB: + m_CX1 = m_X1 + x; + m_CY2 = m_Y2 + y; + break; + case HT_L: + m_CX1 = m_X1 + x; + break; + default: + m_CX1 = m_X1 + x; + m_CX2 = m_X2 + x; + m_CY1 = m_Y1 + y; + m_CY2 = m_Y2 + y; + break; + } + DrawCursor(); + m_Cursor = 1; +} + +void __fastcall CDrawBox::Move(int x, int y) +{ + m_X1 = m_CX1; + m_Y1 = m_CY1; + m_X2 = m_CX2; + m_Y2 = m_CY2; + Normal(); + AdjustRect(); +} +// +//--------------------------------------------------------------------------- +__fastcall CDrawText::CDrawText() +{ + m_Command = CM_TEXT; + +} + + +//*************************************************************************** +//DrawGroupクラス +//--------------------------------------------------------------------------- +__fastcall CDrawGroup::CDrawGroup() +{ + m_Command = CM_GROUP; + m_Cnt = 0; + m_Max = 0; + m_TransX = 319; + m_TransY = 255; + m_TransCol = TColor(0x00f8f8f8); + m_SX = 320; + m_SY = 256; + m_Ver = 2; + m_pBase = NULL; + m_pSel = NULL; +} + +__fastcall CDrawGroup::~CDrawGroup() +{ + FreeItem(); + Free(); +} + +void __fastcall CDrawGroup::Free(void) +{ + if( m_pBase != NULL ){ + delete m_pBase; + m_pBase = NULL; + } + m_Cnt = m_Max = 0; +} + +void __fastcall CDrawGroup::FreeItem(void) +{ + if( m_pBase == NULL ) return; + + for( int i = 0; i < m_Cnt; i++ ){ + delete m_pBase[i]; + } + delete pBase; + m_pBase = NULL; + m_Cnt = m_Max = 0; + m_pSel = NULL; + m_TransX = 319; + m_TransY = 255; + m_TransCol = TColor(0x00f8f8f8); +} + +void __fastcall CDrawGroup::AddItem(CDraw *dp) +{ + if( m_Cnt >= m_Max ){ + m_Max = m_Max ? m_Max * 2 : 4; + CDraw **pNewBase = new CDraw*[m_Max]; + if( m_pBase != NULL ){ + memcpy(pNewBase, m_pBase, sizeof(CDraw*)*m_Cnt); + delete m_pBase; + } + m_pBase = pNewBase; + } + m_pBase[m_Cnt] = dp; + m_Cnt++; +} + +void __fastcall CDrawGroup::DeleteItem(CDraw *dp) +{ + if( m_pBase == NULL ) return; + + for( int i = 0; i < m_Cnt; i++ ){ + if( m_pBase[i] == dp ){ + delete m_pBase[i]; + for( ; i < (m_Cnt - 1); i++ ){ + m_pBase[i] = m_pBase[i+1]; + } + m_pBase[i] = NULL; + m_Cnt--; + return; + } + } +} + +void __fastcall CDrawGroup::ReleaseItem(CDraw *dp) +{ + if( m_pBase == NULL ) return; + + for( int i = 0; i < m_Cnt; i++ ){ + if( m_pBase[i] == dp ){ + for( ; i < (m_Cnt - 1); i++ ){ + m_pBase[i] = m_pBase[i+1]; + } + m_pBase[i] = NULL; + m_Cnt--; + return; + } + } +} + +CDraw * __fastcall CDrawGroup::AddItemCopy(CDraw *dp) +{ + CDraw *pItem = MakeItem(dp->m_Command); + pItem->Copy(dp); + AddItem(pItem); + return pItem; +} + +void __fastcall CDrawGroup::Draw(TCanvas *pCanvas) +{ + if( m_pBase == NULL ) return; + + TransCol = m_TransCol; + for( int i = 0; i < m_Cnt; i++ ){ + pBase[i]->Draw(pCanvas); + } +} + +CDraw* __fastcall CDrawGroup::SelectItem(int X, int Y) +{ + if( m_pBase == NULL ) return NULL; + + for( int i = m_Cnt - 1; i >= 0; i-- ){ + if( (m_Hit = m_pBase[i]->HitTest(X, Y)) != 0 ){ + return m_pBase[i]; + } + } + return NULL; +} + +CDraw* __fastcall CDrawGroup::MakeItem(int cmd) +{ + CDraw *pItem = NULL; + switch(cmd){ + case CM_LINE: + pItem = new CDrawLine; + break; + case CM_BOX: + pItem = new CDrawBox; + break; + case CM_TEXT: + pItem = new CDrawText; + break; + case CM_GROUP: + pItem = new CDrawGroup; + break; + } + return pItem; +} + +void __fastcall CDrawGroup::SaveToStream(TStream *sp) +{ + m_Ver = 0; + CDrawBox::SaveToStream(sp); + + sp->Write(&m_TransX, sizeof(m_TransX)); + sp->Write(&m_TransY, sizeof(m_TransY)); + sp->Write(&m_TransCol, sizeof(m_TransCol)); + sp->Write(&m_SX, sizeof(m_SX)); + sp->Write(&m_SY, sizeof(m_SY)); + sp->Write(&m_Cnt, sizeof(m_Cnt)); + for( int i = 0; i < m_Cnt; i++ ){ + m_pBase[i]->SaveToStream(sp); + } +} + +int __fastcall CDrawGroup::LoadFromStream(TStream *sp) +{ + FreeItem(); + MultProc(); + try { + int cnt, cmd; + sp->Read(&cmd, sizeof(cmd)); + if( cmd != CM_GROUP ){ + goto _err; + } + + if( CDrawBox::LoadFromStream(tp, sp) == FALSE ) goto _err; + sp->Read(&m_TransX, sizeof(m_TransX)); + sp->Read(&m_TransY, sizeof(m_TransY)); + sp->Read(&m_TransCol, sizeof(m_TransCol)); + sp->Read(&m_SX, sizeof(m_SX)); + sp->Read(&m_SY, sizeof(m_SY)); + m_pSel = NULL; + sp->Read(&cnt, sizeof(cnt)); + for( int i = 0; i < cnt; i++ ){ + MultProcA(); + sp->Read(&cmd, sizeof(cmd)); + CDraw *pItem = MakeItem(cmd); + if( pItem != NULL ){ + if( pItem->LoadFromStream(sp) == FALSE ){ + delete pItem; + goto _err; + } + AddItem(pItem); + } + else { + goto _err; + } + } + if( !m_Cnt ) m_TransCol = TColor(0x00f8f8f8); + return TRUE; + } + catch(...){ + } +_err:; + FreeItem(); + return FALSE; +} + +void __fastcall CDrawGroup::BackItem(CDraw *pItem) +{ + int i, k; + for( i = m_Cnt - 1; i >= 0; i-- ){ + if( m_pBase[i] == pItem ){ + for( k = i; k > 0; k-- ){ + m_pBase[k] = m_pBase[k-1]; + } + m_pBase[0] = pItem; + break; + } + } +} + +void __fastcall CDrawGroup::FrontItem(CDraw *pItem) +{ + int i, k; + for( i = 0; i < m_Cnt; i++ ){ + if( m_pBase[i] == pItem ){ + for( k = i; k < m_Cnt - 1; k++ ){ + m_pBase[k] = m_pBase[k+1]; + } + m_pBase[k] = pItem; + break; + } + } +} + +int __fastcall CDrawGroup::UpItem(int n) +{ + if( n ){ + CDraw *pItem = pBase[n-1]; + pBase[n-1] = pBase[n]; + pBase[n] = pItem; + return TRUE; + } + return FALSE; +} + +int __fastcall CDrawGroup::DownItem(int n) +{ + if( n < (m_Cnt - 1) ){ + CDraw *pItem = pBase[n+1]; + pBase[n+1] = pBase[n]; + pBase[n] = pItem; + return TRUE; + } + return FALSE; +} +//-------------------------------------------------------------------------- +void __fastcall CDrawGroup::AdjustTransPoint(void) +{ + MultProc(); + int i; + int f = 0; + int XW = 320; + int YW = 256; + for( i = 0; i < m_Cnt; i++ ){ + if( m_pBase[i]->HitTest(m_TransX, m_TransY) ){ + for( m_TransX = XW-1; m_TransX >= 0; m_TransX -= 5 ){ + for( m_TransY = YW-1; m_TransY >= 0; m_TransY-- ){ + f = 0; + for( i = 0; i < m_Cnt; i++ ){ + if( m_pBase[i]->HitTest(m_TransX, m_TransY) ){ + f++; + break; + } + } + if( !f ) return; + } + MultProc(); + } + break; + } + } + if( f ){ + m_TransX = XW-1; + m_TransY = YW-1; + } +} +//-------------------------------------------------------------------------- +CDraw* __fastcall CDrawGroup::GetLastItem(void) +{ + return m_Cnt ? pBase[m_Cnt-1]: NULL; +} +// +// +//--------------------------------------------------------------------------- +// CItem class +// +__fastcall CItem::CItem(void) +{ + m_pMemStream = NULL; + + m_Ver = 0; + m_ASize = 1; + m_Align = 0; + m_Grade = 0; + m_Shadow = 2; + m_Line = 1; + m_Zero = 0; + m_3d = 0x00000404; + m_Text = "TX\tFT1000MP\r\nANT\tMagnetic loop\r\nSOFT\tHome-made"; + m_pFont = NULL; + m_ColG[0].d = 255; + m_ColG[1].d = 16711935; + m_ColG[2].d = 65535; + m_ColG[3].d = 16776960; + m_ColB[0].c = clBlack; + m_ColB[1].c = clWhite; + m_ColB[2].c = clBlue; + m_ColB[3].c = clRed; + + m_OrgXW = -1; + m_OrgYW = -1; + m_TextXW = -1; + m_TextYW = -1; + m_Draft = 0; + m_IniSize = 0; +} +//--------------------------------------------------------------------------- +__fastcall CItem::~CItem() +{ + if( m_pFont != NULL ) delete m_pFont; + if( m_pMemStream != NULL ) delete m_pMemStream; +} +//--------------------------------------------------------------------------- +void __fastcall CItem::LoadDefault(void) +{ + if( sys.m_pDefStg != NULL ) return; + + CItem *pItem = new CItem; + pItem->LoadFromInifile("Default", ININAME); + LPCBYTE p = pItem->CreateStorage(&sys.m_DefStgSize); + sys.m_pDefStg = new BYTE[sys.m_DefStgSize]; + memcpy(sys.m_pDefStg, p, sys.m_DefStgSize); + pItem->DeleteStorage(p); + delete pItem; +} +//--------------------------------------------------------------------------- +void __fastcall CItem::UpdateDefault(void) +{ + if( sys.m_pDefStg != NULL ){ + delete sys.m_pDefStg; + sys.m_pDefStg = NULL; + } + LPCBYTE p = CreateStorage(&sys.m_DefStgSize); + sys.m_pDefStg = new BYTE[sys.m_DefStgSize]; + memcpy(sys.m_pDefStg, p, sys.m_DefStgSize); + DeleteStorage(p); +} +//--------------------------------------------------------------------------- +void __fastcall CItem::Create(LPCBYTE ps, DWORD size) +{ + if( (ps == NULL) || !size ){ + if( sys.m_pDefStg == NULL ) LoadDefault(); + ps = sys.m_pDefStg; + size = sys.m_DefStgSize; + } + + TMemoryStream *pMem = new TMemoryStream; + pMem->Clear(); + pMem->Write(ps, size); + pMem->Seek(soFromBeginning, 0); + int ver; + pMem->Read(&ver, sizeof(ver)); + if( ver <= m_Ver ){ + pMem->Read(&m_TextXW, sizeof(m_TextXW)); + pMem->Read(&m_TextYW, sizeof(m_TextYW)); + pMem->Read(&m_OrgXW, sizeof(m_OrgXW)); + pMem->Read(&m_OrgYW, sizeof(m_OrgYW)); + pMem->Read(&m_ASize, sizeof(m_ASize)); + pMem->Read(&m_Align, sizeof(m_Align)); + pMem->Read(&m_Grade, sizeof(m_Grade)); + pMem->Read(&m_Shadow, sizeof(m_Shadow)); + pMem->Read(&m_Line, sizeof(m_Line)); + pMem->Read(&m_Zero, sizeof(m_Zero)); + pMem->Read(&m_3d, sizeof(m_3d)); + pMem->Read(&m_ColG, sizeof(m_ColG)); + pMem->Read(&m_ColB, sizeof(m_ColB)); + ReadString(pMem, m_Text); + if( m_pFont != NULL ) delete m_pFont; + m_pFont = ReadFont(pMem); + UpdateFont(); + } + delete pMem; +} +//--------------------------------------------------------------------------- +LPCBYTE __fastcall CItem::CreateStorage(LPDWORD pSize) +{ + ASSERT(pSize); + + if( m_pMemStream != NULL ) delete m_pMemStream; + m_pMemStream = new TMemoryStream; + m_pMemStream->Clear(); + m_Ver = 0; + m_pMemStream->Write(&m_Ver, sizeof(m_Ver)); + m_pMemStream->Write(&m_TextXW, sizeof(m_TextXW)); + m_pMemStream->Write(&m_TextYW, sizeof(m_TextYW)); + m_pMemStream->Write(&m_OrgXW, sizeof(m_OrgXW)); + m_pMemStream->Write(&m_OrgYW, sizeof(m_OrgYW)); + m_pMemStream->Write(&m_ASize, sizeof(m_ASize)); + m_pMemStream->Write(&m_Align, sizeof(m_Align)); + m_pMemStream->Write(&m_Grade, sizeof(m_Grade)); + m_pMemStream->Write(&m_Shadow, sizeof(m_Shadow)); + m_pMemStream->Write(&m_Line, sizeof(m_Line)); + m_pMemStream->Write(&m_Zero, sizeof(m_Zero)); + m_pMemStream->Write(&m_3d, sizeof(m_3d)); + m_pMemStream->Write(&m_ColG, sizeof(m_ColG)); + m_pMemStream->Write(&m_ColB, sizeof(m_ColB)); + WriteString(m_pMemStream, m_Text); + WriteFont(m_pMemStream, m_pFont); + *pSize = m_pMemStream->Position; + return (LPCBYTE)m_pMemStream->Memory; +} +//--------------------------------------------------------------------------- +void __fastcall CItem::LoadFromInifile(LPCSTR pSect, LPCSTR pName) +{ + char fname[512]; + sprintf(fname, "%s%s", sys.m_BgnDir, pName); + TIniFile *pIniFile = new TIniFile(fname); + MultProc(); + m_ASize = pIniFile->ReadInteger(pSect, "AutoSize", m_ASize); + m_Align = pIniFile->ReadInteger(pSect, "Align", m_Align); + m_Grade = pIniFile->ReadInteger(pSect, "Grade", m_Grade); + m_Shadow = pIniFile->ReadInteger(pSect, "Shadow", m_Shadow); + m_Line = pIniFile->ReadInteger(pSect, "Line", m_Line); + m_Zero = pIniFile->ReadInteger(pSect, "Zero", 0); + m_3d = pIniFile->ReadInteger(pSect, "3D", m_3d); + int i; + for( i = 0; i < 4; i++ ){ + char bf[32]; + sprintf(bf, "ColG%u", i); + m_ColG[i].d = pIniFile->ReadInteger(pSect, bf, m_ColG[i].d); + sprintf(bf, "ColB%u", i); + m_ColB[i].d = pIniFile->ReadInteger(pSect, bf, m_ColB[i].d); + } + if( m_ASize ){ + m_OrgXW = m_OrgYW = -1; + m_TextXW = m_TextYW = -1; + } + else { + m_TextXW = pIniFile->ReadInteger(pSect, "Width", m_TextXW); + m_TextYW = pIniFile->ReadInteger(pSect, "Height", m_TextYW); + m_IniSize = 1; + } + AnsiString as, cs; + ::CrLf2Yen(cs, m_Text); + as = pIniFile->ReadString(pSect, "Text", cs); + ::Yen2CrLf(m_Text, as); + + if( pIniFile->ReadInteger(pSect, "Font", 0) ){ + if( m_pFont != NULL ) delete m_pFont; + m_pFont = new TFont; + m_pFont->Name = pIniFile->ReadString(pSect, "FontName", m_pFont->Name); + m_pFont->Charset = (BYTE)pIniFile->ReadInteger(pSect, "FontSet", m_pFont->Charset); + m_pFont->Height = pIniFile->ReadInteger(pSect, "FontSize", m_pFont->Height); + TFontStyles ts = m_pFont->Style; + DWORD d = FontStyle2Code(ts); + d = pIniFile->ReadInteger(pSect, "FontStyle", d); + m_fsCode = d; + ts = Code2FontStyle(d); + m_pFont->Style = ts; + } + delete pIniFile; +} +//--------------------------------------------------------------------------- +void __fastcall CItem::SaveToInifile(LPCSTR pSect, LPCSTR pName) +{ + char fname[512]; + sprintf(fname, "%s%s", sys.m_BgnDir, pName); + + TIniFile *pIniFile = new TIniFile(fname); + MultProc(); + try { + pIniFile->WriteInteger(pSect, "AutoSize", m_ASize); + pIniFile->WriteInteger(pSect, "Align", m_Align); + pIniFile->WriteInteger(pSect, "Grade", m_Grade); + pIniFile->WriteInteger(pSect, "Shadow", m_Shadow); + pIniFile->WriteInteger(pSect, "Line", m_Line); + pIniFile->WriteInteger(pSect, "Zero", m_Zero); + pIniFile->WriteInteger(pSect, "3D", m_3d); + int i; + for( i = 0; i < 4; i++ ){ + char bf[32]; + sprintf(bf, "ColG%u", i); + pIniFile->WriteInteger(pSect, bf, m_ColG[i].d); + sprintf(bf, "ColB%u", i); + pIniFile->WriteInteger(pSect, bf, m_ColB[i].d); + } + pIniFile->WriteInteger(pSect, "Width", m_TextXW); + pIniFile->WriteInteger(pSect, "Height", m_TextYW); + AnsiString cs; + ::CrLf2Yen(cs, m_Text); + pIniFile->WriteString(pSect, "Text", cs); + + pIniFile->WriteInteger(pSect, "Font", m_pFont != NULL ? 1 : 0); + if( m_pFont != NULL ){ + pIniFile->WriteString(pSect, "FontName", m_pFont->Name); + pIniFile->WriteInteger(pSect, "FontSet", m_pFont->Charset); + pIniFile->WriteInteger(pSect, "FontSize", m_pFont->Height); + TFontStyles ts = m_pFont->Style; + DWORD d = FontStyle2Code(ts); + pIniFile->WriteInteger(pSect, "FontStyle", d); + } + } + catch(...){ + } + delete pIniFile; +} +//--------------------------------------------------------------------------- +void __fastcall CItem::DeleteInifile(LPCSTR pSect, LPCSTR pName) +{ + char fname[512]; + sprintf(fname, "%s%s", sys.m_BgnDir, pName); + + TIniFile *pIniFile = new TIniFile(fname); + MultProc(); + try { + pIniFile->EraseSection(pSect); + } + catch(...){ + } + delete pIniFile; +} +//--------------------------------------------------------------------------- +DWORD __fastcall CItem::GetItemType(void) +{ + DWORD type = 0x00010002; // Active text as Overlay + if( m_ASize ){ + switch(m_Align){ + case 1: + type |= 0x00400000; // align center + break; + case 2: + type |= 0x00100000; // aling right-top + break; + default: + break; + } + } + return type; +} +//--------------------------------------------------------------------------- +void __fastcall CItem::DeleteStorage(LPCBYTE pStorage) +{ + if( m_pMemStream != NULL ){ + ASSERT(pStorage == (LPCBYTE)m_pMemStream->Memory); + delete m_pMemStream; + m_pMemStream = NULL; + } +} +//--------------------------------------------------------------------------- +void __fastcall CItem::Copy(CItem *sp) +{ + ASSERT(sp); + + DWORD size; + LPCBYTE ps = sp->CreateStorage(&size); + Create(ps, size); + sp->DeleteStorage(ps); + m_Back = sp->m_Back; + if( m_ASize ){ + m_OrgXW = m_OrgYW = -1; + m_TextXW = m_TextYW = -1; + } + else { + m_IniSize = 1; + } +} +//--------------------------------------------------------------------------- +DWORD __fastcall CItem::GetOrgSize(void) +{ + if(m_OrgXW >= 0){ + DWORD w = m_OrgXW; + DWORD h = m_OrgYW; + return (h << 16) + w; + } + else { + return (128 << 16) + 160; + } +} +//--------------------------------------------------------------------------- +void __fastcall CItem::SetFontSize(Graphics::TBitmap *pDest) +{ + ASSERT(m_OrgXW > 0); + ASSERT(m_OrgYW > 0); + if( (m_OrgXW <= 0) || (m_OrgYW <= 0) ) return; + + int size = m_pFont->Height; + if( m_OrgXW < pDest->Width ){ + size = size * pDest->Width / m_OrgXW; + } + else if( m_OrgYW < pDest->Height ){ + size = size * pDest->Height / m_OrgYW; + } + else if( m_OrgXW > pDest->Width ){ + size = size * pDest->Width / m_OrgXW; + } + else if( m_OrgYW > pDest->Height ){ + size = size * pDest->Height / m_OrgYW; + } + m_pFont->Height = size; +} +//--------------------------------------------------------------------------- +void __fastcall CItem::SetTextSize(Graphics::TBitmap *pDest) +{ + ASSERT(m_OrgXW > 0); + ASSERT(m_OrgYW > 0); + if( (m_OrgXW <= 0) || (m_OrgYW <= 0) ) return; + + if( m_OrgXW < pDest->Width ){ + m_TextXW = m_TextXW * pDest->Width / m_OrgXW; + } + else if( m_OrgYW < pDest->Height ){ + m_TextYW = m_TextYW * pDest->Height / m_OrgYW; + } + else if( m_OrgXW > pDest->Width ){ + m_TextXW = m_TextXW * pDest->Width / m_OrgXW; + } + else if( m_OrgYW > pDest->Height ){ + m_TextYW = m_TextYW * pDest->Height / m_OrgYW; + } +} +//--------------------------------------------------------------------------- +int __fastcall CItem::GetMaxWH(int &W, int &H, Graphics::TBitmap *pDest, LPCSTR pText) +{ + int lf = 1; + int n = 0; + W = H = 0; + char bf[1024]; + LPSTR t; + for( t = bf; 1; pText++ ){ + if( *pText != 0x0d ){ + if( (*pText == 0x0a) || !*pText ){ + if( lf && *pText ){ + n++; + } + *t = 0; + if( bf[0] ){ + DWORD wh = ::GetTabbedTextExtent(pDest->Canvas->Handle, bf, strlen(bf), 0, NULL); + int w = wh & 0x0000ffff; + int h = wh >> 16; + if( H < h ) H = h; + if( W < w ) W = w; + } + if( !*pText ) break; + lf = 1; + t = bf; + } + else { + if( lf ){ + lf = 0; + n++; + } + *t++ = *pText; + } + } + } + return n; +} +//--------------------------------------------------------------------------- +UINT __fastcall CItem::GetDrawFormat(void) +{ + UINT wFormat = DT_NOPREFIX|DT_NOCLIP|DT_EXPANDTABS; + switch(m_Align){ + case 1: + wFormat |= DT_CENTER; + break; + case 2: + wFormat |= DT_RIGHT; + break; + default: + wFormat |= DT_LEFT; + break; + } + if( !m_ASize ) wFormat |= DT_WORDBREAK; + return wFormat; +} +//--------------------------------------------------------------------------- +void __fastcall CItem::DrawText(RECT rc, int xoff, int yoff, Graphics::TBitmap *pDest, LPCSTR pText, UCOL ucol) +{ + rc.left += xoff; rc.top += yoff; + rc.right += xoff; rc.bottom += yoff; + pDest->Canvas->Font = m_pFont; + pDest->Canvas->Font->Color = ucol.c; + HDC hdc = pDest->Canvas->Handle; + ::SetBkMode(hdc, TRANSPARENT); + ::DrawText(hdc, pText, strlen(pText), &rc, GetDrawFormat()); +} +//--------------------------------------------------------------------------- +void __fastcall CItem::DrawTrans(Graphics::TBitmap *pDest, int x, int y, Graphics::TBitmap *pSrc) +{ + Graphics::TBitmap *pbmp = pSrc; + if( sys.m_BitPixel == 16 ){ + pbmp = new Graphics::TBitmap; + pbmp->Width = pSrc->Width; + pbmp->Height = pSrc->Height; + pbmp->Canvas->Draw(0, 0, pSrc); + } + pbmp->Transparent = TRUE; + pbmp->TransparentMode = tmAuto; + pDest->Canvas->Draw(x, y, pbmp); + if( pbmp != pSrc ) delete pbmp; +} +//--------------------------------------------------------------------------- +LPBYTE __fastcall CItem::CreateTable(Graphics::TBitmap *pDest) +{ + int XW = pDest->Width; + int YW = pDest->Height; + LPBYTE pTbl = new BYTE[XW*YW]; + memset(pTbl, 0, XW*YW); + LPBYTE wp = pTbl; + int x, y; + + BYTE br = m_cBack.b.r; + BYTE bg = m_cBack.b.g; + BYTE bb = m_cBack.b.b; + for( y = 0; y < YW; y++ ){ + LPBYTE p = (LPBYTE)pDest->ScanLine[y]; + for( x = 0; x < XW; x++, wp++, p+=3 ){ + if( (bb != *p) || (bg != *(p+1)) || (br != *(p+2)) ){ + *wp = 1; + } + } + } + return pTbl; +} +//--------------------------------------------------------------------------- +int __fastcall CItem::EditDialog(HWND hWnd) +{ + TTextDlgBox *pBox = new TTextDlgBox(hWnd); + if( pBox == NULL ) return FALSE; + + int r = pBox->Execute(this); + delete pBox; + if( r == TRUE ) UpdateDefault(); + return r; +} +//--------------------------------------------------------------------------- +int __fastcall CItem::FontDialog(HWND hWnd) +{ + if( m_pFont == NULL ) m_pFont = new TFont; + TFontDialog *pDlg = new TFontDialog(NULL); + if( pDlg == NULL ) return FALSE; + + ASSERT(m_pFont); + pDlg->Font->Assign(m_pFont); + pDlg->Font->Color = m_ColG[0].c; + MultProc(); + int r = pDlg->Execute(); + MultProc(); + if( r == TRUE ){ + m_pFont->Assign(pDlg->Font); + m_ColG[0].c = pDlg->Font->Color; + UpdateFont(); + UpdateDefault(); + } + delete pDlg; + return r; +} +//--------------------------------------------------------------------------- +void __fastcall CItem::UpdateFont(void) +{ + if( m_pFont == NULL ) return; + + TFontStyles ts = m_pFont->Style; + m_fsCode = FontStyle2Code(ts); +} +//--------------------------------------------------------------------------- +void __fastcall CItem::Draw3D(RECT &rc, Graphics::TBitmap *pDest, LPCSTR pText, UCOL cl[2]) +{ + int xm = m_3d & 0x00ff; + int ym = (m_3d >> 8) & 0x00ff; + if( xm & 0x0080 ) xm |= 0xffffff80; + if( ym & 0x0080 ) ym |= 0xffffff80; + int max = ABS(xm) > ABS(ym) ? ABS(xm) : ABS(ym); + for( int i = max; i > 0; i-- ){ + int x = xm * i / max; + int y = ym * i / max; + DrawText(rc, x, y, pDest, pText, GetGrade2(cl, i, max)); + } +} +//--------------------------------------------------------------------------- +Graphics::TBitmap* __fastcall CItem::DrawExt(Graphics::TBitmap *pDest, RECT &rc, LPCSTR pText) +{ + MultProc(); + int xw = pDest->Width; + int yw = pDest->Height; + LPBYTE pTbl = NULL; + if( m_Grade || (m_Shadow == 2) ) pTbl = CreateTable(pDest); + + LPBYTE wp, p; + if( m_Grade ){ + MultProc(); + ASSERT(pTbl); + RECT mc; + mc.left = rc.right; mc.top = rc.bottom; + mc.right = rc.left; mc.bottom = rc.top; + wp = pTbl; + int x, y; + for( y = 0; y < yw; y++ ){ + for( x = 0; x < xw; x++, wp++ ){ + if( *wp ){ + if( mc.left > x ) mc.left = x; + if( mc.right < x ) mc.right = x; + if( mc.top > y ) mc.top = y; + if( mc.bottom < y ) mc.bottom = y; + } + } + } + int bw = mc.right - mc.left + 1; + int bh = mc.bottom - mc.top + 1; + int bd = sqrt(bw*bw + bh*bh); + UCOL c; + for( y = mc.top; y <= mc.bottom; y++ ){ + p = (LPBYTE)pDest->ScanLine[y]; + wp = &pTbl[y*xw]; + for( x = 0; x < xw; x++, wp++, p+=3 ){ + if( *wp ){ + int xx = x - mc.left; + int yy = y - mc.top; + switch(m_Grade){ + case 1: + c = GetGrade4(m_ColG, xx, bw); + break; + case 2: + c = GetGrade4(m_ColG, yy, bh); + break; + case 3: + c = GetGrade4(m_ColG, sqrt(xx*xx + yy*yy), bd); + break; + } + *p++ = c.b.b; + *p++ = c.b.g; + *p = c.b.r; + p -= 2; + } + } + } + } + MultProc(); + switch(m_Shadow){ + case 1: + { + Graphics::TBitmap* pbmp = CreateBitmap(xw, yw); + FillBitmap(pbmp, m_cBack); + if( m_3d & 0x00010000 ){ + Draw3D(rc, pbmp, pText, &m_ColB[1]); + } + else { + for( int i = m_Line - 1; i >= 0; i-- ){ + DrawText(rc, i+1, i+1, pbmp, pText, m_ColB[0]); + } + } + DrawTrans(pbmp, 0, 0, pDest); + delete pDest; + pDest = pbmp; + } + break; + case 2: + { + ASSERT(pTbl); + if( m_3d & 0x00010000 ){ + Graphics::TBitmap* pbmp = CreateBitmap(xw, yw); + FillBitmap(pbmp, m_cBack); + Draw3D(rc, pbmp, pText, &m_ColB[1]); + DrawTrans(pbmp, 0, 0, pDest); + delete pDest; + pDest = pbmp; + } + int f; + int x, y; + for( y = 0; y < yw; y++ ){ + wp = &pTbl[y*xw]; + p = (LPBYTE)pDest->ScanLine[y]; + f = 0; + for( x = 0; x < xw; x++, wp++, p+=3 ){ + if( *wp ){ + if( !m_Grade ){ + *p++ = m_ColG[0].b.b; + *p++ = m_ColG[0].b.g; + *p = m_ColG[0].b.r; + p -= 2; + } + f = m_Line; + } + else if( f ){ + f--; + if( !*wp ){ + *p++ = m_ColB[0].b.b; + *p++ = m_ColB[0].b.g; + *p = m_ColB[0].b.r; + p -= 2; + *wp = BYTE(f); + } + } + } + f = 0; + wp--; + p -= 3; + x--; + for( ; x >= 0; x--, wp--, p-=3 ){ + if( *wp ){ + f = m_Line; + } + else if( f ){ + f--; + if( !*wp ){ + *p++ = m_ColB[0].b.b; + *p++ = m_ColB[0].b.g; + *p = m_ColB[0].b.r; + p -= 2; + *wp = BYTE(f); + } + } + } + + } + int ax = 0; + for( x = 0; x < xw; x++, ax+=3 ){ + wp = &pTbl[x]; + f = 0; + for( y = 0; y < yw; y++, wp += xw ){ + if( *wp ){ + f = m_Line; + } + else if( f ){ + f--; + if( !*wp ){ + p = (LPBYTE)pDest->ScanLine[y]; + p += ax; + *p++ = m_ColB[0].b.b; + *p++ = m_ColB[0].b.g; + *p = m_ColB[0].b.r; + *wp = BYTE(f); + } + } + } + f = 0; + y--; + wp -= xw; + for( ; y >= 0; y--, wp -= xw ){ + if( *wp ){ + f = m_Line; + } + else if( f ){ + f--; + if( !*wp ){ + p = (LPBYTE)pDest->ScanLine[y]; + p += ax; + *p++ = m_ColB[0].b.b; + *p++ = m_ColB[0].b.g; + *p = m_ColB[0].b.r; + } + } + } + } + } + break; + case 3: + { + Graphics::TBitmap* pbmp = CreateBitmap(xw, yw); + FillBitmap(pbmp, m_cBack); + if( m_3d & 0x00010000 ){ + rc.left++; rc.right++; + rc.top++; rc.bottom++; + int xm = m_3d & 0x00ff; + int ym = (m_3d >> 8) & 0x00ff; + Draw3D(rc, pbmp, pText, &m_ColB[1]); + DrawText(rc, (xm & 0x80) ? 1 : -1, (ym & 0x80) ? 1 : -1, pbmp, pText, m_ColB[0]); + } + else { + for( int i = m_Line - 1; i >= 0; i-- ){ + DrawText(rc, i+2, i+2, pbmp, pText, m_ColB[0]); + } + DrawText(rc, 0, 0, pbmp, pText, m_ColB[1]); + } + DrawTrans(pbmp, 1, 1, pDest); + delete pDest; + pDest = pbmp; + } + break; + default: + break; + } + if( pTbl != NULL ) delete pTbl; + + return pDest; +} +//--------------------------------------------------------------------------- +Graphics::TBitmap* __fastcall CItem::Draw(Graphics::TBitmap *pDest, LPCSTR pText) +{ + if( (pText == NULL) || !*pText ) return pDest; + AnsiString as; + if( m_Align ){ + as = pText; + for( LPSTR t = as.c_str(); *t; t++ ){ + if( *t == '\t' ) *t = ' '; + } + pText = as.c_str(); + } + m_Back.c = pDest->Canvas->Pixels[0][0]; + m_cBack = m_Back; + if( m_pFont == NULL ){ + m_pFont = new TFont(); + m_pFont->Assign(pDest->Canvas->Font); + m_pFont->Size = 18; + UpdateFont(); + } + else if( m_OrgXW >= 0 ){ + if( m_ASize ) SetFontSize(pDest); + } + + LPCSTR pOrgText = pText; + if( m_Zero ){ + pText = ZeroConv(pText, m_pFont->Charset); + } + + pDest->Canvas->Font = m_pFont; + + int xw, yw; + if( m_ASize ){ + int n = GetMaxWH(xw, yw, pDest, pText); + yw *= n; + if( m_fsCode & FSITALIC ){ + xw += yw / 12; + } + } + else if( m_IniSize || (m_OrgXW < 0) ){ + m_IniSize = 0; + if( m_TextXW > 0 ){ + xw = m_TextXW; + yw = m_TextYW; + } + else { + xw = pDest->Width; + yw = pDest->Height; + } + } + else { + SetTextSize(pDest); + xw = m_TextXW; + yw = m_TextYW; + } + m_TextXW = xw; + m_TextYW = yw; + + if( m_Shadow && (m_cBack.d == m_ColB[0].d) ){ + m_cBack = GetUniqueColor(pDest->Canvas->Handle, m_cBack); + } + if( m_cBack.d == m_ColG[0].d ){ + m_cBack = GetUniqueColor(pDest->Canvas->Handle, m_cBack); + } + + MultProc(); + + RECT rc; + rc.left = rc.top = 0; + rc.right = xw; + rc.bottom = yw; + + if( m_3d & 0x00010000 ){ + int xm = m_3d & 0x00ff; + int ym = (m_3d >> 8) & 0x00ff; + if( xm & 0x0080 ) xm |= 0xffffff80; + if( ym & 0x0080 ) ym |= 0xffffff80; + if( xm < 0 ){ + rc.left -= xm; + rc.right -= xm; + } + if( ym < 0 ){ + rc.top -= ym; + rc.bottom -= ym; + } + xw += ABS(xm); + yw += ABS(ym); + } + + switch(m_Shadow){ + case 1: + xw += m_Line; + yw += m_Line; + break; + case 2: + rc.left += m_Line; + rc.right += m_Line; + rc.top += m_Line; + rc.bottom += m_Line; + xw += m_Line*2; + yw += m_Line*2; + break; + case 3: + xw += m_Line*2; + yw += m_Line*2; + break; + } + + if( (m_fsCode & FSITALIC) && (m_Align == 2) ){ + int ow = yw / 12; + rc.left -= ow; + rc.right -= ow; + } + + Graphics::TBitmap *pBmp = pDest; + if( (pDest->Width != xw) || (pDest->Height != yw) ){ + pBmp = CreateBitmap(xw, yw); + FillBitmap(pBmp, m_cBack); + } + else if( m_Back.d != m_cBack.d ){ + FillBitmap(pBmp, m_cBack); + } + + MultProc(); + DrawText(rc, 0, 0, pBmp, pText, m_ColG[0]); + Graphics::TBitmap *pNew = pBmp; + if( !m_Draft ){ + pNew = DrawExt(pBmp, rc, pText); + } + m_OrgXW = xw; + m_OrgYW = yw; + if( pBmp != pDest ) delete pDest; + pDest = pNew; + if( pOrgText != pText ) delete pText; + + // set transparent color to (0,0) for overlay + LPBYTE p = (LPBYTE)pDest->ScanLine[0]; + ASSERT(p); + *p++ = m_cBack.b.b; + *p++ = m_cBack.b.g; + *p = m_cBack.b.r; + + MultProc(); + return pDest; +} + + diff --git a/CItems/QSLBox/Comlib.h b/CItems/QSLBox/Comlib.h new file mode 100644 index 0000000..8cb46db --- /dev/null +++ b/CItems/QSLBox/Comlib.h @@ -0,0 +1,372 @@ +#ifndef ComLibH +#define ComLibH +#include +#include +#include +#include +#include +#include +#include + +#define NDEBUG // Remove this symbol, if you would like to do debug +#include +#define ASSERT(c) assert(c) + +#define ABS(c) (((c)<0)?(-(c)):(c)) +#define PI 3.1415926535897932384626433832795 + +typedef const BYTE* LPCBYTE; +typedef double* LPDOUBLE; +typedef const double* LPCDOUBLE; +typedef union { + struct { + BYTE r; + BYTE g; + BYTE b; + BYTE s; + }b; + DWORD d; + TColor c; +}UCOL; + +#define VER "QSLBox Version 1.00" +#define AUT "(C) JE3HHT 2002." +#define TTL "MMSSTV custom item" +#define TTLJ "MMSSTV カスタムアイテム" // Japanese code + +#define ININAME "QSLBox.ini" + +#define FSBOLD 1 +#define FSITALIC 2 +#define FSUNDERLINE 4 +#define FSSTRIKEOUT 8 + +// These prototypes are the functions in the MMSSTV. +// ---- Refer to the comment of the mcmFunc() --- +typedef HBITMAP (__cdecl *mmLoadImageMenu)(int sw, int xw, int yw); +typedef HBITMAP (__cdecl *mmLoadImage)(LPCSTR pName); +typedef HBITMAP (__cdecl *mmLoadHistImage)(void); +typedef int (__cdecl *mmSaveImageMenu)(HBITMAP hb, LPCSTR pName, LPCSTR pFolder); +typedef int (__cdecl *mmSaveImage)(HBITMAP hb, LPCSTR pName); +typedef HBITMAP (__cdecl *mmPasteImage)(int sw, int xw, int yw); +typedef int (__cdecl *mmGetMacKey)(LPSTR pDest, int cbDest); +typedef int (__cdecl *mmConvMac)(LPSTR pDest, LPCSTR pSrc, int cbDest); +typedef HBITMAP (__cdecl *mmCreateDIB)(int xw, int yw); +typedef void (__cdecl *mmMultProc)(void); +typedef void (__cdecl *mmMultProcA)(void); +typedef int (__cdecl *mmColorComp)(LPDWORD pCol); + +void __fastcall MultProc(void); +char __fastcall LastC(LPCSTR p); +void __fastcall SetCurDir(LPSTR t, int size); +void __fastcall SetDirName(LPSTR t, LPCSTR pName); +void __fastcall Yen2CrLf(AnsiString &ws, AnsiString cs); +void __fastcall CrLf2Yen(AnsiString &ws, AnsiString cs); +void __fastcall LoadStringsFromIniFile(TStrings *pList, LPCSTR pSect, LPCSTR pName); +void __fastcall SaveStringsToIniFile(TStrings *pList, LPCSTR pSect, LPCSTR pName); +void __fastcall InitCustomColor(TColorDialog *tp); +void __fastcall AddCustomColor(TColorDialog *tp, TColor col); +Graphics::TBitmap * __fastcall CreateBitmap(int xw, int yw); +void __fastcall FillBitmap(Graphics::TBitmap *pDest, UCOL ucol); +void __fastcall CopyBitmap(Graphics::TBitmap *pDest, Graphics::TBitmap *pSrc); +void __fastcall DrawBitmap(TPaintBox *pBox, Graphics::TBitmap *pBitmap); + +//*********************************************************** +//CDraw item class +//*********************************************************** +enum { + HT_NONE, + HT_P1, // line + HT_P2, // line + HT_PM, // line + HT_LT, // box + HT_RT, + HT_LB, + HT_RB, + HT_L, + HT_T, + HT_R, + HT_B, + HT_I, +}; + +class CDraw +{ +public: + int m_Command; + int m_Ver; + int m_X1, m_Y1; + int m_X2, m_Y2; + UCOL m_LineColor; + TPenStyle m_LineStyle; + int m_LineWidth; + +public: + int m_Cursor; + int m_CX1, m_CY1; + int m_CX2, m_CY2; + int m_BX, m_BY; + int m_MF; + int m_MC; +public: + TCanvas *m_pCanvas; + +public: + __fastcall CDraw(); + virtual __fastcall ~CDraw(){}; + virtual void __fastcall Start(TCanvas *tp, int X, int Y); + virtual int __fastcall Finish(int X, int Y){return FALSE;}; + virtual void __fastcall Draw(TCanvas *tp){}; + virtual void __fastcall DrawFast(TCanvas *tp){Draw(tp);}; + virtual void __fastcall DrawSel(TCanvas *tp, int sw){}; + virtual void __fastcall Making(int X, int Y){}; + virtual int __fastcall HitTest(int x, int y){return FALSE;}; + virtual void __fastcall StartMove(TCanvas *tp, int X, int Y, int code); + virtual void __fastcall Moving(int X, int Y){}; + virtual void __fastcall Move(int X, int Y){}; + virtual int __fastcall IsMove(void){return m_MF;}; + virtual int __fastcall Edit(void); + virtual void __fastcall SaveToStream(TStream *sp); + virtual int __fastcall LoadFromStream(TCanvas *tp, TStream *sp); + virtual void __fastcall Copy(CDraw *dp); + void __fastcall Normal(void); +}; + +class CDrawLine : public CDraw +{ +private: + void __fastcall DrawCursor(void); + +protected: +public: + __fastcall CDrawLine(); + virtual __fastcall ~CDrawLine(){}; + virtual int __fastcall Finish(int X, int Y); + virtual void __fastcall Draw(TCanvas *tp); + virtual void __fastcall DrawSel(TCanvas *tp, int sw); + virtual void __fastcall Making(int X, int Y); + virtual int __fastcall HitTest(int x, int y); + virtual void __fastcall Moving(int X, int Y); + virtual void __fastcall Move(int X, int Y); +}; + +class CDrawBox : public CDraw +{ +private: + +protected: + void __fastcall DrawCursor(void); +public: + __fastcall CDrawBox(); + virtual __fastcall ~CDrawBox(){}; + + virtual int __fastcall Finish(int X, int Y); + virtual void __fastcall Draw(TCanvas *tp); + virtual void __fastcall DrawSel(TCanvas *tp, int sw); + virtual void __fastcall Making(int X, int Y); + virtual int __fastcall HitTest(int X, int Y); + virtual void __fastcall Moving(int X, int Y); + virtual void __fastcall Move(int X, int Y); +}; + +class CDrawText : public CDrawBoxS +{ +public: + int m_Grade; + int m_Shadow; + int m_Zero; + int m_Rot; + int m_RightAdj; + int m_PerSpect; + int m_Stack; + int m_StackPara; + int m_Vert; + int m_VertH; + SPERSPECT m_sperspect; + AnsiString m_Text; + TFont *pFont; + TColor m_Col1; + TColor m_Col2; + TColor m_Col3; + TColor m_Col4; + TColor m_ColS; + TColor m_ColB; + Graphics::TBitmap *pBitmap; + Graphics::TBitmap *pBrushBitmap; + int m_X; + int m_Y; +private: + Graphics::TBitmap * __fastcall DupeB(TColor col); + void __fastcall MakeBitmap(); + int __fastcall ZeroConv(BYTE charset, LPSTR p); + int __fastcall GetMaxWidth(int &n, LPCSTR p); + void __fastcall DrawTextVert(TCanvas *tp, int xc, int y, int fh, LPCSTR p); + void __fastcall DrawTextHoriANSI(TCanvas *tp, int xc, int y, LPCSTR p); + void __fastcall DrawText(TCanvas *cp, int x, int y, LPCSTR p, int zc); +protected: +public: + __fastcall CDrawText(); + __fastcall ~CDrawText(); + +// virtual int HitTest(int x, int y){return CDrawBox::HitTest(x, y) ? HT_I : HT_NONE;}; + int __fastcall Finish(int X, int Y); + void __fastcall Move(int X, int Y); + void __fastcall Draw(TCanvas *tp); + void __fastcall DrawFast(TCanvas *tp); + int __fastcall Edit(void); + int __fastcall Color(void){return Edit();}; + inline void __fastcall UpdateFont(TFont *pf); + + void __fastcall SaveToStream(TStream *sp); + int __fastcall LoadFromStream(TCanvas *tp, TStream *sp); + void __fastcall Copy(CDraw *dp); + void __fastcall Copy(CDraw *dp, int sw); + void __fastcall UpdateText(void); + void __fastcall UpdateTimeText(void); + int __fastcall IsTimeMacro(void); + void __fastcall ReleaseResource(void); +}; + +class CDrawGroup : public CDrawBox +{ +public: + int m_Max; + int m_Cnt; + int m_TransX, m_TransY; + int m_SX, m_SY; + TColor m_TransCol; + CDraw **pBase; + CDraw *pSel; +public: + int m_Hit; +protected: +public: + __fastcall CDrawGroup(); + __fastcall ~CDrawGroup(); + void __fastcall Free(void); + void __fastcall FreeItem(void); + void __fastcall AddItem(CDraw *dp); + void __fastcall DeleteItem(CDraw *dp); + void __fastcall ReleaseItem(CDraw *dp); + void __fastcall UpdatePic(Graphics::TBitmap *pBmp); + void __fastcall FillPic(TCanvas *tp, TColor col, int sw, double sx, double sy, int off); + void __fastcall Draw(TCanvas *tp); + void __fastcall DrawFast(TCanvas *tp); + void __fastcall DrawNotSel(TCanvas *tp); + CDraw* __fastcall SelectItem(int X, int Y); + int __fastcall HitTest(int x, int y){return CDrawBox::HitTest(x, y) ? HT_I : HT_NONE;}; + + CDraw * __fastcall MakeItem(int cmd); + CDraw * __fastcall AddItemCopy(CDraw *dp); + virtual void __fastcall SaveToStream(TStream *sp); + virtual int __fastcall LoadFromStream(TCanvas *tp, TStream *sp); + + virtual void __fastcall Copy(CDraw *dp); + void __fastcall UpdateText(void); + void __fastcall UpdateTimeText(void); + int __fastcall IsTimeMacro(void); + + void __fastcall BackItem(CDraw *pItem); + void __fastcall FrontItem(CDraw *pItem); + int __fastcall UpItem(int n); + int __fastcall DownItem(int n); + void __fastcall DrawTrans(TCanvas *tp); + + int __fastcall IsMacro(LPCSTR pKey); + void __fastcall AdjustTransPoint(void); + void __fastcall AdjustTransColor(Graphics::TBitmap *pBmp); + void __fastcall ReleaseResource(void); + void __fastcall GetColorBarPos(int &Y1, int &Y2); + CDraw * __fastcall GetLastItem(void); + + int __fastcall IsConvBitmap(CDraw *pItem); + void __fastcall ConvBitmap(CDraw *pItem); + CDrawPic* __fastcall MakePic(int x, int y, Graphics::TBitmap *pBitmap, int ov); +}; + +class CItem +{ +public: + int m_Ver; + int m_ASize; + int m_Align; + int m_Grade; + int m_Shadow; + int m_Line; + int m_Zero; + DWORD m_3d; + AnsiString m_Text; + TFont *m_pFont; + UCOL m_ColG[4]; + UCOL m_ColB[4]; + UCOL m_Back; + int m_OrgXW; + int m_OrgYW; + int m_TextXW; + int m_TextYW; +private: + UCOL m_cBack; + int m_Draft; + int m_fsCode; + int m_IniSize; + TMemoryStream *m_pMemStream; +private: + void __fastcall LoadDefault(void); + void __fastcall UpdateDefault(void); + void __fastcall SetFontSize(Graphics::TBitmap *pDest); + void __fastcall SetTextSize(Graphics::TBitmap *pDest); + int __fastcall GetMaxWH(int &W, int &H, Graphics::TBitmap *pDest, LPCSTR pText); + UINT __fastcall GetDrawFormat(void); + void __fastcall DrawText(RECT rc, int xoff, int yoff, Graphics::TBitmap *pDest, LPCSTR pText, UCOL ucol); + void __fastcall DrawTrans(Graphics::TBitmap *pDest, int x, int y, Graphics::TBitmap *pSrc); + LPBYTE __fastcall CreateTable(Graphics::TBitmap *pDest); + void __fastcall Draw3D(RECT &rc, Graphics::TBitmap *pDest, LPCSTR pText, UCOL cl[2]); + Graphics::TBitmap* __fastcall DrawExt(Graphics::TBitmap *pDest, RECT &rc, LPCSTR pText); + +protected: +public: + __fastcall CItem(void); + __fastcall ~CItem(); + void __fastcall Create(LPCBYTE ps, DWORD size); + DWORD __fastcall GetItemType(void); + LPCBYTE __fastcall CreateStorage(LPDWORD psize); + void __fastcall DeleteStorage(LPCBYTE pStorage); + void __fastcall Copy(CItem *sp); + int __fastcall EditDialog(HWND hWnd); + int __fastcall FontDialog(HWND hWnd); + DWORD __fastcall GetOrgSize(void); + inline LPCSTR __fastcall GetText(void){ + return m_Text.c_str(); + }; + inline void __fastcall SetDraft(int draft){ + m_Draft = draft; + }; + void __fastcall UpdateFont(void); + void __fastcall LoadFromInifile(LPCSTR pSect, LPCSTR pName); + void __fastcall SaveToInifile(LPCSTR pSect, LPCSTR pName); + void __fastcall DeleteInifile(LPCSTR pSect, LPCSTR pName); + Graphics::TBitmap* __fastcall Draw(Graphics::TBitmap *pDest, LPCSTR pText); +}; + +//*********************************************************** +//Common structer +//*********************************************************** +typedef struct { + DWORD m_dwVersion; + int m_WinNT; + UINT m_CodePage; + int m_MsgEng; + int m_BitPixel; + mmGetMacKey m_fGetMacKey; + mmConvMac m_fConvMac; + mmMultProc m_fMultProc; + mmColorComp m_fColorComp; + DWORD m_DefStgSize; + LPBYTE m_pDefStg; + TStringList *m_pTextList; + TStringList *m_pStyleList; + char m_BgnDir[512]; +}SYS; +extern SYS sys; +#endif + diff --git a/CItems/QSLBox/Item.ico b/CItems/QSLBox/Item.ico new file mode 100644 index 0000000..b709881 Binary files /dev/null and b/CItems/QSLBox/Item.ico differ diff --git a/CItems/QSLBox/TextDlg.cpp b/CItems/QSLBox/TextDlg.cpp new file mode 100644 index 0000000..f9327a0 --- /dev/null +++ b/CItems/QSLBox/TextDlg.cpp @@ -0,0 +1,671 @@ +//--------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "TextDlg.h" +//--------------------------------------------------------------------- +#pragma resource "*.dfm" +//TTextDlgBox *TextDlgBox; +//--------------------------------------------------------------------- +__fastcall TTextDlgBox::TTextDlgBox(HWND hWnd) + : TForm(hWnd) +{ + MultProc(); + m_DisEvent = 1; + m_pBitmap = NULL; + m_Change = 0; + m_DropProfile = 0; + m_FText = ""; + if( sys.m_MsgEng ){ + Font->Name = "Arial"; + Font->Charset = ANSI_CHARSET; + + Caption = "Set text and colors - "VER" "TTL; + CancelBtn->Caption = "Cancel"; + FontBtn->Caption = "Font"; + SBM->Caption = "Mac"; + GBG->Caption = "Gradation"; + GBS->Caption = "Shadow"; + GBA->Caption = "Misc"; + CBFixed->Caption = "Fixed box-size"; + CBZero->Caption = "Slash zero"; + SBLD->Caption = "Del"; + SBLW->Caption = "Add"; + GBY->Caption = "Style profiles"; + L1->Caption = "Align"; + L2->Caption = "Style name"; + SBYD->Caption = "Del"; + SBYW->Caption = "Add"; + CBY->Text = "Untitled"; + SBM->Hint = "Insert macro-keyword"; + SBC->Hint = "Choose color's component"; + SBLD->Hint = "Delete the text in the list"; + SBLW->Hint = "Add current text into the list"; + SBYD->Hint = "Delete the style in the profiles"; + SBYW->Hint = "Add current style into the profiles"; + SB3DD->Hint = "Make the shadow shorter"; + SB3DI->Hint = "Make the shadow longer"; + FontBtn->Hint = "Choose font"; + SBFD->Hint = "Make the font smaller"; + SBFI->Hint = "Make the font bigger"; + } + else { + Caption = "テキストと色の設定 - "VER" "TTLJ; + CBY->Text = "無題"; + } + SBFD->Glyph->Assign(SB3DD->Glyph); + SBFI->Glyph->Assign(SB3DI->Glyph); + MultProc(); + if( sys.m_pTextList == NULL ){ + sys.m_pTextList = new TStringList; + LoadStringsFromIniFile(sys.m_pTextList, "Strings", ININAME); + MultProc(); + if(!sys.m_pTextList->Count){ + sys.m_pTextList->Add("%c\\r\\nur %r\\r\\nde %m"); + sys.m_pTextList->Add("Tnx for nice PIC\\r\\nur %r\\r\\nde %m"); + sys.m_pTextList->Add("%n\\r\\nBest 73\\r\\nde %m"); + } + } + ASSERT(sys.m_pTextList); + CBList->Items->Assign(sys.m_pTextList); + if( sys.m_pStyleList == NULL ){ + sys.m_pStyleList = new TStringList; + LoadStringsFromIniFile(sys.m_pStyleList, "Styles", ININAME); + MultProc(); + } + CBY->Items->Assign(sys.m_pStyleList); + CBY->Sorted = TRUE; + ShowHint = sys.m_WinNT; + MultProc(); +} +//--------------------------------------------------------------------- +void __fastcall TTextDlgBox::FormDestroy(TObject *Sender) +{ + if( m_pBitmap != NULL ) delete m_pBitmap; + MultProc(); + ASSERT(sys.m_pTextList); + sys.m_pTextList->Assign(CBList->Items); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::TopMost(void) +{ + ::SetWindowPos(Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::NoTopMost(void) +{ + ::SetWindowPos(Handle, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::UpdateUI(void) +{ + m_DisEvent++; + int f = SBG1->Down ? FALSE : TRUE; + PG2->Visible = f; + PG3->Visible = f; + PG4->Visible = f; + SBC->Visible = f && sys.m_fColorComp; + f = !SBS1->Down; + if( !f ) CB3D->Checked = FALSE; + CB3D->Enabled = f; + PB1->Visible = f && (!SBS2->Down || !CB3D->Checked); + PB2->Visible = f && (SBS4->Down || CB3D->Checked); + PB3->Visible = f && CB3D->Checked; + UDL->Enabled = f && (SBS3->Down || !CB3D->Checked); + SBLW->Enabled = (!m_FText.IsEmpty() && CBList->Items->IndexOf(m_FText) < 0) ? TRUE : FALSE; + SBLD->Enabled = CBList->ItemIndex >= 0 ? TRUE : FALSE; + SBYW->Enabled = !CBY->Text.IsEmpty(); + SBYD->Enabled = !CBY->Text.IsEmpty() && (sys.m_pStyleList->IndexOf(CBY->Text) >= 0); + UDX->Enabled = CB3D->Checked; + UDY->Enabled = CB3D->Checked; + SB3DI->Enabled = CB3D->Checked; + SB3DD->Enabled = CB3D->Checked; + if( sys.m_WinNT ){ + char bf[32]; + sprintf(bf, "W = %d", UDL->Position); + UDL->Hint = bf; + sprintf(bf, "3D(Y) = %d", UDY->Position); + UDY->Hint = bf; + sprintf(bf, "3D(X) = %d", UDX->Position); + UDX->Hint = bf; + } + m_DisEvent--; +} +//--------------------------------------------------------------------- +void __fastcall TTextDlgBox::UpdateMemoFont(BYTE charset) +{ + switch(charset){ + case SHIFTJIS_CHARSET: + case HANGEUL_CHARSET: + case CHINESEBIG5_CHARSET: // + case 134: // 簡略 + break; + default: + charset = Font->Charset; + break; + } + m_DisEvent++; + if( Memo->Font->Charset != charset ){ + Memo->Font->Charset = charset; + } + m_DisEvent--; +} +//--------------------------------------------------------------------- +int __fastcall TTextDlgBox::Execute(CItem *pItem) +{ + MultProc(); + m_Item.Copy(pItem); + UpdateDialog(&m_Item); + UpdateBitmap(); + m_DisEvent = 0; + MultProc(); + if( ShowModal() == IDOK ){ + MultProc(); + pItem->Copy(&m_Item); + if( pItem->m_ASize ){ + pItem->m_OrgXW = -1; + } + MultProc(); + return TRUE; + } + else { + MultProc(); + return FALSE; + } +} +//--------------------------------------------------------------------- +void __fastcall TTextDlgBox::UpdateFText(void) +{ + AnsiString as; + if( Memo->Text.IsEmpty() ){ + m_FText = ""; + } + else { + ::CrLf2Yen(as, Memo->Text); + LPSTR p = as.c_str(); + if( *p ){ + *(p+strlen(p)-1) = 0; + m_FText = p+1; + } + } + m_DisEvent++; + CBList->ItemIndex = CBList->Items->IndexOf(m_FText); + m_DisEvent--; +} +//--------------------------------------------------------------------- +void __fastcall TTextDlgBox::UpdateItem(CItem *pItem) +{ + UpdateUI(); + if( SBG1->Down ){ + pItem->m_Grade = 0; + } + else if( SBG2->Down ){ + pItem->m_Grade = 1; + } + else if( SBG3->Down ){ + pItem->m_Grade = 2; + } + else { + pItem->m_Grade = 3; + } + if( SBS1->Down ){ + pItem->m_Shadow = 0; + } + else if( SBS2->Down ){ + pItem->m_Shadow = 1; + } + else if( SBS3->Down ){ + pItem->m_Shadow = 2; + } + else { + pItem->m_Shadow = 3; + } + if( SBA1->Down ){ + pItem->m_Align = 0; + } + else if( SBA2->Down ){ + pItem->m_Align = 1; + } + else { + pItem->m_Align = 2; + } + pItem->m_ColB[0].c = PB1->Color; + pItem->m_ColB[1].c = PB2->Color; + pItem->m_ColB[2].c = PB3->Color; + pItem->m_ColG[0].c = PG1->Color; + pItem->m_ColG[1].c = PG2->Color; + pItem->m_ColG[2].c = PG3->Color; + pItem->m_ColG[3].c = PG4->Color; + pItem->m_Line = UDL->Position; + pItem->m_ASize = !CBFixed->Checked; + pItem->m_Zero = CBZero->Checked; + pItem->m_Text = Memo->Text.c_str(); + pItem->m_3d = (CB3D->Enabled && CB3D->Checked) ? 0x00010000 : 0; + pItem->m_3d |= ((UDY->Position << 8)&0x0000ff00); + pItem->m_3d |= (UDX->Position & 0x000000ff); +} +//--------------------------------------------------------------------- +void __fastcall TTextDlgBox::UpdateDialog(CItem *pItem) +{ + m_DisEvent++; + switch(pItem->m_Grade){ + case 1: + SBG2->Down = TRUE; + break; + case 2: + SBG3->Down = TRUE; + break; + case 3: + SBG4->Down = TRUE; + break; + default: + SBG1->Down = TRUE; + break; + } + switch(pItem->m_Shadow){ + case 1: + SBS2->Down = TRUE; + break; + case 2: + SBS3->Down = TRUE; + break; + case 3: + SBS4->Down = TRUE; + break; + default: + SBS1->Down = TRUE; + break; + } + switch(pItem->m_Align){ + case 1: + SBA2->Down = TRUE; + break; + case 2: + SBA3->Down = TRUE; + break; + default: + SBA1->Down = TRUE; + break; + } + PB1->Color = pItem->m_ColB[0].c; + PB2->Color = pItem->m_ColB[1].c; + PB3->Color = pItem->m_ColB[2].c; + PG1->Color = pItem->m_ColG[0].c; + PG2->Color = pItem->m_ColG[1].c; + PG3->Color = pItem->m_ColG[2].c; + PG4->Color = pItem->m_ColG[3].c; + UDL->Position = SHORT(pItem->m_Line); + CBFixed->Checked = !pItem->m_ASize; + CBZero->Checked = pItem->m_Zero; + CB3D->Checked = pItem->m_3d & 0x00010000; + int xm = pItem->m_3d & 0x000000ff; + int ym = (pItem->m_3d >> 8) & 0x000000ff; + if( xm & 0x0080 ) xm |= 0xffffff80; + if( ym & 0x0080 ) ym |= 0xffffff80; + UDY->Position = SHORT(ym); + UDX->Position = SHORT(xm); + if( pItem->m_pFont != NULL ){ + UpdateMemoFont(pItem->m_pFont->Charset); + } + Memo->Text = pItem->m_Text.c_str(); + UpdateFText(); + m_DisEvent--; +} +//--------------------------------------------------------------------- +void __fastcall TTextDlgBox::UpdateBitmap(void) +{ + MultProc(); + m_Change = 0; + UpdateItem(&m_Item); + char bf[1024]; + sys.m_fConvMac(bf, m_Item.GetText(), sizeof(bf)-1); + MultProc(); + if( m_pBitmap == NULL ){ + int xw = m_Item.m_OrgXW; + int yw = m_Item.m_OrgYW; + if( (xw < 0)||(yw < 0) ){ + xw = 160; + yw = 128; + } + m_pBitmap = CreateBitmap(xw, yw); + } + FillBitmap(m_pBitmap, m_Item.m_Back); + MultProc(); + m_pBitmap = m_Item.Draw(m_pBitmap, bf); + PBox->Invalidate(); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::PBoxPaint(TObject *Sender) +{ + if( m_pBitmap == NULL ) return; + + Graphics::TBitmap *pBitmap = m_pBitmap; + if( sys.m_BitPixel == 16 ){ + pBitmap = new Graphics::TBitmap; + pBitmap->Width = m_pBitmap->Width; + pBitmap->Height = m_pBitmap->Height; + pBitmap->Canvas->Draw(0, 0, m_pBitmap); + } + pBitmap->Transparent = TRUE; + pBitmap->TransparentMode = tmFixed; + pBitmap->TransparentColor = pBitmap->Canvas->Pixels[0][0]; + PBox->Canvas->Draw(0, 0, pBitmap); + pBitmap->Transparent = FALSE; + if( pBitmap != m_pBitmap ) delete pBitmap; +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::MemoChange(TObject *Sender) +{ + if( m_DisEvent ) return; + + m_Change = 2; + Timer->Enabled = TRUE; + UpdateFText(); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::TimerTimer(TObject *Sender) +{ + if( m_Change ){ + m_Change--; + if( !m_Change ){ + Timer->Enabled = FALSE; + UpdateBitmap(); + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::SBG1Click(TObject *Sender) +{ + if( m_DisEvent ) return; + + UpdateBitmap(); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::PB1Click(TObject *Sender) +{ + TPanel *pPanel = (TPanel *)Sender; + InitCustomColor(ColorDialog); + AddCustomColor(ColorDialog, PG1->Color); + AddCustomColor(ColorDialog, PG2->Color); + AddCustomColor(ColorDialog, PG3->Color); + AddCustomColor(ColorDialog, PG4->Color); + AddCustomColor(ColorDialog, PB1->Color); + AddCustomColor(ColorDialog, PB2->Color); + AddCustomColor(ColorDialog, m_Item.m_Back.c); + + ColorDialog->Color = pPanel->Color; + NoTopMost(); + int r = ColorDialog->Execute(); + TopMost(); + if( r == TRUE ){ + pPanel->Color = ColorDialog->Color; + UpdateBitmap(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::FormActivate(TObject *Sender) +{ + TopMost(); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::FormDeactivate(TObject *Sender) +{ + NoTopMost(); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::UDLClick(TObject *Sender, TUDBtnType Button) +{ + if( m_DisEvent ) return; + + UpdateBitmap(); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::FontBtnClick(TObject *Sender) +{ + FontDialog->Font->Assign(m_Item.m_pFont); + FontDialog->Font->Color = PG1->Color; + NoTopMost(); + int r = FontDialog->Execute(); + TopMost(); + if( r == TRUE ){ + m_Item.m_pFont->Assign(FontDialog->Font); + PG1->Color = FontDialog->Font->Color; + m_Item.UpdateFont(); + if( m_Item.m_pFont != NULL ){ + UpdateMemoFont(m_Item.m_pFont->Charset); + } + UpdateBitmap(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::SBMClick(TObject *Sender) +{ + if( sys.m_fGetMacKey ){ + char bf[256]; + NoTopMost(); + int r = sys.m_fGetMacKey(bf, sizeof(bf)); + TopMost(); + if( r ){ + Memo->SetFocus(); + for( LPCSTR p = bf; *p; p++ ){ + ::PostMessage(Memo->Handle, WM_CHAR, *p, 0); + } + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::SBCClick(TObject *Sender) +{ + if( sys.m_fColorComp ){ + UCOL col[4]; + col[0].c = PG1->Color; + col[1].c = PG2->Color; + col[2].c = PG3->Color; + col[3].c = PG4->Color; + NoTopMost(); + int r = sys.m_fColorComp(&col[0].d); + TopMost(); + if( r ){ + PG1->Color = col[0].c; + PG2->Color = col[1].c; + PG3->Color = col[2].c; + PG4->Color = col[3].c; + UpdateBitmap(); + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::SBLWClick(TObject *Sender) +{ + m_DisEvent++; + CBList->Items->Add(m_FText); + CBList->ItemIndex = CBList->Items->IndexOf(m_FText); + UpdateUI(); + m_DisEvent--; +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::SBLDClick(TObject *Sender) +{ + m_DisEvent++; + if( CBList->ItemIndex >= 0 ){ + int n = CBList->ItemIndex; + CBList->ItemIndex = -1; + CBList->Items->Delete(n); + UpdateUI(); + } + m_DisEvent--; +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::CBListChange(TObject *Sender) +{ + if( m_DisEvent ) return; + if( CBList->ItemIndex < 0 ) return; + + m_DisEvent++; + AnsiString cs; + AnsiString as = CBList->Items->Strings[CBList->ItemIndex]; + m_FText = as; + ::Yen2CrLf(cs, as); + Memo->Text = cs; + UpdateBitmap(); + m_DisEvent--; +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::SBYWClick(TObject *Sender) +{ + m_DisEvent++; + int r = sys.m_pStyleList->IndexOf(CBY->Text); + if( r < 0 ) r = sys.m_pStyleList->Count; + + CItem *pItem = new CItem; + pItem->Copy(&m_Item); + pItem->m_Text = CBY->Text; + char bf[64]; + sprintf(bf, "Style.%u", r); + pItem->SaveToInifile(bf, ININAME); + delete pItem; + + if( r == sys.m_pStyleList->Count ){ + CBY->Items->Add(CBY->Text); + sys.m_pStyleList->Add(CBY->Text); + UpdateUI(); + } + m_DisEvent--; +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::SBYDClick(TObject *Sender) +{ + m_DisEvent++; + int r = sys.m_pStyleList->IndexOf(CBY->Text); + if( r >= 0 ){ + char bf[64]; + CItem *pItem = new CItem; + int i; + for( i = r; i < sys.m_pStyleList->Count - 1; i++ ){ + sprintf(bf, "Style.%u", i+1); + pItem->LoadFromInifile(bf, ININAME); + sprintf(bf, "Style.%u", i); + pItem->SaveToInifile(bf, ININAME); + MultProc(); + } + sprintf(bf, "Style.%u", i); + pItem->DeleteInifile(bf, ININAME); + delete pItem; + sys.m_pStyleList->Delete(r); + r = CBY->Items->IndexOf(CBY->Text); + if( r >= 0 ) CBY->Items->Delete(r); + UpdateUI(); + } + m_DisEvent--; +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::CBYChange(TObject *Sender) +{ + if( m_DisEvent ) return; + if( !m_DropProfile ){ + UpdateUI(); + return; + } + m_DropProfile = 0; + + m_DisEvent++; + int r = sys.m_pStyleList->IndexOf(CBY->Text); + if( r >= 0 ){ + AnsiString as = m_Item.m_Text; + CItem *pItem = new CItem; + char bf[64]; + sprintf(bf, "Style.%u", r); + pItem->LoadFromInifile(bf, ININAME); + m_Item.Copy(pItem); + delete pItem; + m_Item.m_Text = as; + UpdateDialog(&m_Item); + UpdateBitmap(); + } + m_DisEvent--; +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::CBYKeyPress(TObject *Sender, char &Key) +{ + m_DropProfile = 0; + UpdateUI(); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::CBYDropDown(TObject *Sender) +{ + m_DropProfile = 1; +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::PBoxMouseDown(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( m_DisEvent ) return; + + m_DisEvent++; + if( Button == mbRight ){ + CB3D->Checked = FALSE; + } + else { + CB3D->Checked = TRUE; + int xc = m_pBitmap->Width / 2; + int yc = m_pBitmap->Height / 2; + int x = X - xc; + int y = Y - yc; + x = x * 48 / xc; + y = y * 48 / yc; + UDX->Position = SHORT(x); + UDY->Position = SHORT(y); + } + m_DisEvent--; + UpdateBitmap(); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::UD3D(int a) +{ + m_DisEvent++; + int x = UDX->Position; + int y = UDY->Position; + int xs = (x >= 0) ? 1 : -1; + int ys = (y >= 0) ? 1 : -1; + x = ABS(x); + y = ABS(y); + if( (x == y) && !(x & 1) ){ + x += a; + y += a; + if( x < 4 ) x = 4; + if( y < 4 ) y = 4; + if( x > 48 ) x = 48; + if( y > 48 ) y = 48; + } + else { + if( x < y ) x = y; + x &= 0xfffffffc; + y = x; + } + x *= xs; y *= ys; + UDX->Position = SHORT(x); + UDY->Position = SHORT(y); + m_DisEvent--; + UpdateBitmap(); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::SB3DIClick(TObject *Sender) +{ + UD3D((Sender == SB3DI) ? 4 : -4); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::SBFDClick(TObject *Sender) +{ + if( m_Item.m_pFont == NULL ) return; + + if( Sender == SBFD ){ + if( m_Item.m_pFont->Height < -1 ) m_Item.m_pFont->Height++; + UpdateBitmap(); + } + else { + m_Item.m_pFont->Height--; + UpdateBitmap(); + } +} +//--------------------------------------------------------------------------- + diff --git a/CItems/QSLBox/TextDlg.dfm b/CItems/QSLBox/TextDlg.dfm new file mode 100644 index 0000000..796b40f Binary files /dev/null and b/CItems/QSLBox/TextDlg.dfm differ diff --git a/CItems/QSLBox/TextDlg.h b/CItems/QSLBox/TextDlg.h new file mode 100644 index 0000000..f7a95da --- /dev/null +++ b/CItems/QSLBox/TextDlg.h @@ -0,0 +1,127 @@ +//---------------------------------------------------------------------------- +#ifndef TextDlgH +#define TextDlgH +//---------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//---------------------------------------------------------------------------- +#include "ComLib.h" +#include +#include +//---------------------------------------------------------------------------- +class TTextDlgBox : public TForm +{ +__published: + TButton *OKBtn; + TButton *CancelBtn; + TButton *FontBtn; + TMemo *Memo; + TGroupBox *GBG; + TSpeedButton *SBM; + TSpeedButton *SBG1; + TSpeedButton *SBG2; + TSpeedButton *SBG3; + TSpeedButton *SBG4; + TPanel *PG1; + TPanel *PG2; + TPanel *PG3; + TPanel *PG4; + TSpeedButton *SBC; + TGroupBox *GBS; + TSpeedButton *SBS1; + TSpeedButton *SBS2; + TSpeedButton *SBS3; + TSpeedButton *SBS4; + TPanel *PB1; + TPanel *PB2; + TPanel *PB3; + TUpDown *UDL; + TGroupBox *GB3D; + TCheckBox *CB3D; + TUpDown *UDY; + TUpDown *UDX; + TSpeedButton *SB3DI; + TSpeedButton *SB3DD; + TLabel *L1; + TLabel *LY; + TLabel *LX; + TGroupBox *GBA; + TSpeedButton *SBA1; + TSpeedButton *SBA2; + TSpeedButton *SBA3; + TCheckBox *CBFixed; + TCheckBox *CBZero; + TComboBox *CBList; + TSpeedButton *SBLW; + TSpeedButton *SBLD; + TGroupBox *GBY; + TComboBox *CBY; + TLabel *L2; + TSpeedButton *SBYW; + TSpeedButton *SBYD; + TPaintBox *PBox; + TFontDialog *FontDialog; + TColorDialog *ColorDialog; + TTimer *Timer; + TSpeedButton *SBFD; + TSpeedButton *SBFI; + void __fastcall FormDestroy(TObject *Sender); + void __fastcall PBoxPaint(TObject *Sender); + void __fastcall MemoChange(TObject *Sender); + void __fastcall TimerTimer(TObject *Sender); + void __fastcall SBG1Click(TObject *Sender); + void __fastcall PB1Click(TObject *Sender); + void __fastcall FormActivate(TObject *Sender); + void __fastcall FormDeactivate(TObject *Sender); + void __fastcall UDLClick(TObject *Sender, TUDBtnType Button); + void __fastcall FontBtnClick(TObject *Sender); + void __fastcall SBMClick(TObject *Sender); + void __fastcall SBCClick(TObject *Sender); + void __fastcall SBLWClick(TObject *Sender); + void __fastcall SBLDClick(TObject *Sender); + void __fastcall CBListChange(TObject *Sender); + void __fastcall SBYWClick(TObject *Sender); + void __fastcall SBYDClick(TObject *Sender); + void __fastcall CBYChange(TObject *Sender); + void __fastcall CBYKeyPress(TObject *Sender, char &Key); + void __fastcall CBYDropDown(TObject *Sender); + void __fastcall PBoxMouseDown(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + + void __fastcall SB3DIClick(TObject *Sender); + void __fastcall SBFDClick(TObject *Sender); +private: + int m_DisEvent; + int m_DropProfile; + Graphics::TBitmap *m_pBitmap; + CItem m_Item; + int m_Change; + AnsiString m_FText; + void __fastcall TopMost(void); + void __fastcall NoTopMost(void); + void __fastcall UpdateMemoFont(BYTE charset); + void __fastcall UpdateFText(void); + void __fastcall UpdateUI(void); + void __fastcall UpdateItem(CItem *pItem); + void __fastcall UpdateDialog(CItem *pItem); + void __fastcall UpdateBitmap(void); + void __fastcall UD3D(int a); + +public: + virtual __fastcall TTextDlgBox(HWND hWnd); + + int __fastcall Execute(CItem *pItem); +}; +//---------------------------------------------------------------------------- +//extern PACKAGE TTextDlgBox *TextDlgBox; +//---------------------------------------------------------------------------- +#endif + \ No newline at end of file diff --git a/CItems/QSLBox/qslbox.bpr b/CItems/QSLBox/qslbox.bpr new file mode 100644 index 0000000..754f354 --- /dev/null +++ b/CItems/QSLBox/qslbox.bpr @@ -0,0 +1,182 @@ +# --------------------------------------------------------------------------- +!if !$d(BCB) +BCB = $(MAKEDIR)\.. +!endif + +# --------------------------------------------------------------------------- +# IDE セクション +# --------------------------------------------------------------------------- +# プロジェクトメイクファイルの以下のセクションは、IDE によって管理されます。 +# このセクションを変更する場合は、できるだけ IDE を使用するようにして +# ください。 +# --------------------------------------------------------------------------- + +VERSION = BCB.03 +# --------------------------------------------------------------------------- +PROJECT = qslbox.dll +OBJFILES = qslbox.obj Comlib.obj About.obj TextDlg.obj +RESFILES = qslbox.res +DEFFILE = +RESDEPEN = $(RESFILES) About.dfm TextDlg.dfm +LIBFILES = +LIBRARIES = VCL35.lib +SPARELIBS = VCL35.lib +PACKAGES = VCLX35.bpi VCL35.bpi VCLDB35.bpi VCLDBX35.bpi bcbsmp35.bpi dclocx35.bpi \ + QRPT35.bpi TEEUI35.bpi VCLSMP35.bpi TEEDB35.bpi TEE35.bpi ibsmp35.bpi \ + NMFAST35.bpi INETDB35.bpi INET35.bpi +# --------------------------------------------------------------------------- +PATHCPP = .; +PATHASM = .; +PATHPAS = .; +PATHRC = .; +DEBUGLIBPATH = $(BCB)\lib\debug +RELEASELIBPATH = $(BCB)\lib\release +# --------------------------------------------------------------------------- +CFLAG1 = -WD -O2 -Hc -w -Ve -d -k- -vi -c -b- -w-par -w-inl -Vx +CFLAG2 = -I$(BCB)\include;$(BCB)\include\vcl -H=$(BCB)\lib\vcl35.csm +CFLAG3 = -Tkh30000 +PFLAGS = -U$(BCB)\lib\obj;$(BCB)\lib;$(RELEASELIBPATH) \ + -I$(BCB)\include;$(BCB)\include\vcl -$L- -$D- -v -JPHN -M +RFLAGS = -i$(BCB)\include;$(BCB)\include\vcl +AFLAGS = /i$(BCB)\include /i$(BCB)\include\vcl /mx /w2 /zn /d_RTLDLL +LFLAGS = -L$(BCB)\lib\obj;$(BCB)\lib;$(RELEASELIBPATH) -aa -Tpd -x -Gn +IFLAGS = +# --------------------------------------------------------------------------- +ALLOBJ = c0d32.obj sysinit.obj $(OBJFILES) +ALLRES = $(RESFILES) +ALLLIB = $(LIBFILES) $(LIBRARIES) import32.lib cp32mt.lib +# --------------------------------------------------------------------------- +!ifdef IDEOPTIONS + +[Version Info] +IncludeVerInfo=0 +AutoIncBuild=0 +MajorVer=1 +MinorVer=0 +Release=0 +Build=0 +Debug=0 +PreRelease=0 +Special=0 +Private=0 +DLL=0 +Locale=1041 +CodePage=932 + +[Version Info Keys] +CompanyName= +FileDescription= +FileVersion=1.0.0.0 +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion=1.0.0.0 +Comments= + +[HistoryLists\hlIncludePath] +Count=1 +Item0=$(BCB)\include;$(BCB)\include\vcl + +[HistoryLists\hlLibraryPath] +Count=1 +Item0=$(BCB)\lib\obj;$(BCB)\lib + +[HistoryLists\hlDebugSourcePath] +Count=1 +Item0=$(BCB)\source\vcl + +[HistoryLists\hlConditionals] +Count=2 +Item0=_RTLDLL +Item1=_RTLDLL;USEPACKAGES + +[HistoryLists\hlHostApplication] +Count=1 +Item0=D:\Mmsstv\Mmsstv.exe + +[Debugging] +DebugSourceDirs=$(BCB)\source\vcl + +[Parameters] +RunParams= +HostApplication=D:\Mmsstv\Mmsstv.exe + +!endif + +# --------------------------------------------------------------------------- +# MAKE セクション +# --------------------------------------------------------------------------- +# IDE はプロジェクトファイルのこのセクションは使用していません。 +# コマンドラインの MAKE ユーティリティを使用してビルドするためのものです。 +# --------------------------------------------------------------------------- + +.autodepend +# --------------------------------------------------------------------------- +!if !$d(BCC32) +BCC32 = bcc32 +!endif + +!if !$d(DCC32) +DCC32 = dcc32 +!endif + +!if !$d(TASM32) +TASM32 = tasm32 +!endif + +!if !$d(LINKER) +LINKER = ilink32 +!endif + +!if !$d(BRCC32) +BRCC32 = brcc32 +!endif +# --------------------------------------------------------------------------- +!if $d(PATHCPP) +.PATH.CPP = $(PATHCPP) +.PATH.C = $(PATHCPP) +!endif + +!if $d(PATHPAS) +.PATH.PAS = $(PATHPAS) +!endif + +!if $d(PATHASM) +.PATH.ASM = $(PATHASM) +!endif + +!if $d(PATHRC) +.PATH.RC = $(PATHRC) +!endif +# --------------------------------------------------------------------------- +$(PROJECT): $(OBJFILES) $(RESDEPEN) $(DEFFILE) + $(BCB)\BIN\$(LINKER) @&&! + $(LFLAGS) + + $(ALLOBJ), + + $(PROJECT),, + + $(ALLLIB), + + $(DEFFILE), + + $(ALLRES) +! +# --------------------------------------------------------------------------- +.pas.hpp: + $(BCB)\BIN\$(DCC32) $(PFLAGS) {$< } + +.pas.obj: + $(BCB)\BIN\$(DCC32) $(PFLAGS) {$< } + +.cpp.obj: + $(BCB)\BIN\$(BCC32) $(CFLAG1) $(CFLAG2) $(CFLAG3) -n$(@D) {$< } + +.c.obj: + $(BCB)\BIN\$(BCC32) $(CFLAG1) $(CFLAG2) $(CFLAG3) -n$(@D) {$< } + +.asm.obj: + $(BCB)\BIN\$(TASM32) $(AFLAGS) $<, $@ + +.rc.res: + $(BCB)\BIN\$(BRCC32) $(RFLAGS) -fo$@ $< +# --------------------------------------------------------------------------- + \ No newline at end of file diff --git a/CItems/QSLBox/qslbox.cpp b/CItems/QSLBox/qslbox.cpp new file mode 100644 index 0000000..8aa137f --- /dev/null +++ b/CItems/QSLBox/qslbox.cpp @@ -0,0 +1,184 @@ +//--------------------------------------------------------------------------- +#include +#pragma hdrstop +//--------------------------------------------------------------------------- +#include "ComLib.h" +#include "About.h" +//--------------------------------------------------------------------------- +USEUNIT("Comlib.cpp"); +USEFORM("About.cpp", AboutDlg); +USERC("qslbox.rc"); +USEFORM("TextDlg.cpp", TextDlgBox); +//--------------------------------------------------------------------------- +int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void*) +{ + switch(reason){ + case DLL_PROCESS_ATTACH: + { + memset(&sys, 0, sizeof(sys)); + + sys.m_dwVersion = ::GetVersion(); + sys.m_WinNT = (sys.m_dwVersion < 0x80000000) ? TRUE : FALSE; + sys.m_CodePage = ::GetACP(); // Get codepage + + char bf[512]; + ::GetModuleFileName(hinst, bf, sizeof(bf)); + ::SetDirName(sys.m_BgnDir, bf); + + HDC hdcScreen = ::CreateDC("DISPLAY", NULL, NULL, NULL); + sys.m_BitPixel = ::GetDeviceCaps(hdcScreen, BITSPIXEL); + ::DeleteDC(hdcScreen); + + _setmbcp(_MB_CP_ANSI); + } + break; + case DLL_PROCESS_DETACH: + sys.m_fMultProc = NULL; + if( sys.m_pDefStg != NULL ){ + CItem *pItem = new CItem; + pItem->Create(NULL, 0); + pItem->SaveToInifile("Default", ININAME); + delete pItem; + delete sys.m_pDefStg; + sys.m_pDefStg = NULL; + } + if( sys.m_pTextList != NULL ){ + SaveStringsToIniFile(sys.m_pTextList, "Strings", ININAME); + delete sys.m_pTextList; + sys.m_pTextList = NULL; + } + if( sys.m_pStyleList != NULL ){ + SaveStringsToIniFile(sys.m_pStyleList, "Styles", ININAME); + delete sys.m_pStyleList; + sys.m_pStyleList = NULL; + } + break; + } + return 1; +} +//--------------------------------------------------------------------------- +extern "C" __declspec(dllexport) +void mcmLanguage(DWORD lang) +{ + sys.m_MsgEng = lang; +} +//--------------------------------------------------------------------------- +extern "C" __declspec(dllexport) +void mcmAboutDialog(HWND hWnd) +{ + TAboutDlg *pBox = new TAboutDlg(hWnd); + pBox->ShowModal(); + delete pBox; + ::SetForegroundWindow(hWnd); +} +//--------------------------------------------------------------------- +extern "C" __declspec(dllexport) +HANDLE mcmCreateObject(LPCBYTE pStorage, DWORD Size) +{ + CItem *pItem = new CItem; + ASSERT(pItem); + if( pItem != NULL ) pItem->Create(pStorage, Size); + return (HANDLE)pItem; +} +//--------------------------------------------------------------------- +extern "C" __declspec(dllexport) +DWORD mcmGetItemType(HANDLE hObj) +{ + ASSERT(hObj); + CItem *pItem = (CItem *)hObj; + return pItem->GetItemType(); +} +//--------------------------------------------------------------------- +extern "C" __declspec(dllexport) +LPCBYTE mcmCreateStorage(HANDLE hObj, LPDWORD pSize) +{ + ASSERT(hObj); + CItem *pItem = (CItem *)hObj; + return pItem->CreateStorage(pSize); +} +//--------------------------------------------------------------------- +extern "C" __declspec(dllexport) +void mcmDeleteStorage(HANDLE hObj, LPCBYTE pStorage) +{ + ASSERT(hObj); + CItem *pItem = (CItem *)hObj; + pItem->DeleteStorage(pStorage); +} +//--------------------------------------------------------------------- +extern "C" __declspec(dllexport) +void mcmDeleteObject(HANDLE hObj) +{ + ASSERT(hObj); + CItem *pItem = (CItem *)hObj; + if( pItem != NULL ) delete pItem; +} +//--------------------------------------------------------------------- +extern "C" __declspec(dllexport) +DWORD mcmEdit(HANDLE hObj, HWND hWnd) +{ + ASSERT(hObj); + CItem *pItem = (CItem *)hObj; + int r = pItem->EditDialog(hWnd); + ::SetForegroundWindow(hWnd); + return r; +} +//--------------------------------------------------------------------- +extern "C" __declspec(dllexport) +DWORD mcmFont(HANDLE hObj, HWND hWnd) +{ + ASSERT(hObj); + CItem *pItem = (CItem *)hObj; + + int r = pItem->FontDialog(hWnd); + ::SetForegroundWindow(hWnd); + return r; +} +//--------------------------------------------------------------------- +extern "C" __declspec(dllexport) +DWORD mcmGetOrgSize(HANDLE hObj) +{ + ASSERT(hObj); + CItem *pItem = (CItem *)hObj; + return pItem->GetOrgSize(); +} +//--------------------------------------------------------------------- +extern "C" __declspec(dllexport) +LPCSTR mcmGetUserText(HANDLE hObj) +{ + ASSERT(hObj); + CItem *pItem = (CItem *)hObj; + return pItem->GetText(); +} +//--------------------------------------------------------------------- +extern "C" __declspec(dllexport) +HBITMAP mcmUpdateText(HANDLE hObj, HBITMAP hDest, LPCSTR pText) +{ + ASSERT(hObj); + ASSERT(hDest); + CItem *pItem = (CItem *)hObj; + + // Draw object to hDest + Graphics::TBitmap *pDest = new Graphics::TBitmap; + pDest->Handle = hDest; + pDest = pItem->Draw(pDest, pText); + + HBITMAP hb = pDest->ReleaseHandle(); + delete pDest; + return (hb != hDest) ? hb : NULL; +} +//--------------------------------------------------------------------- +extern "C" __declspec(dllexport) +HBITMAP mcmUpdateImage(HANDLE hObj, HBITMAP hDest, HBITMAP hSrc) +{ + ASSERT(0); // This function should not be called + return NULL; +} +//--------------------------------------------------------------------- +extern "C" __declspec(dllexport) +void mcmSetDraft(HANDLE hObj, DWORD draft) +{ + ASSERT(hObj); + CItem *pItem = (CItem *)hObj; + + pItem->SetDraft(draft); +} \ No newline at end of file diff --git a/CItems/QSLBox/qslbox.rc b/CItems/QSLBox/qslbox.rc new file mode 100644 index 0000000..0e32c13 --- /dev/null +++ b/CItems/QSLBox/qslbox.rc @@ -0,0 +1,2 @@ +8000 ICON DISCARDABLE "Item.ico" + \ No newline at end of file diff --git a/CItems/QSLBox/qslbox.res b/CItems/QSLBox/qslbox.res new file mode 100644 index 0000000..4dd7390 Binary files /dev/null and b/CItems/QSLBox/qslbox.res differ diff --git a/CItems/QSLBox/qslbox.tds b/CItems/QSLBox/qslbox.tds new file mode 100644 index 0000000..457c258 Binary files /dev/null and b/CItems/QSLBox/qslbox.tds differ diff --git a/CItems/QSLBox/res/SB3DD.bmp b/CItems/QSLBox/res/SB3DD.bmp new file mode 100644 index 0000000..1c74fe6 Binary files /dev/null and b/CItems/QSLBox/res/SB3DD.bmp differ diff --git a/CItems/QSLBox/res/SB3DI.bmp b/CItems/QSLBox/res/SB3DI.bmp new file mode 100644 index 0000000..c162a1f Binary files /dev/null and b/CItems/QSLBox/res/SB3DI.bmp differ diff --git a/CItems/QSLBox/res/SBA1.bmp b/CItems/QSLBox/res/SBA1.bmp new file mode 100644 index 0000000..732f99b Binary files /dev/null and b/CItems/QSLBox/res/SBA1.bmp differ diff --git a/CItems/QSLBox/res/SBA2.bmp b/CItems/QSLBox/res/SBA2.bmp new file mode 100644 index 0000000..74ba1fb Binary files /dev/null and b/CItems/QSLBox/res/SBA2.bmp differ diff --git a/CItems/QSLBox/res/SBA3.bmp b/CItems/QSLBox/res/SBA3.bmp new file mode 100644 index 0000000..768947d Binary files /dev/null and b/CItems/QSLBox/res/SBA3.bmp differ diff --git a/CItems/QSLBox/res/SBC.bmp b/CItems/QSLBox/res/SBC.bmp new file mode 100644 index 0000000..3f96f65 Binary files /dev/null and b/CItems/QSLBox/res/SBC.bmp differ diff --git a/CItems/QSLBox/res/SBG1.bmp b/CItems/QSLBox/res/SBG1.bmp new file mode 100644 index 0000000..939b20f Binary files /dev/null and b/CItems/QSLBox/res/SBG1.bmp differ diff --git a/CItems/QSLBox/res/SBG2.bmp b/CItems/QSLBox/res/SBG2.bmp new file mode 100644 index 0000000..a737fbe Binary files /dev/null and b/CItems/QSLBox/res/SBG2.bmp differ diff --git a/CItems/QSLBox/res/SBG3.bmp b/CItems/QSLBox/res/SBG3.bmp new file mode 100644 index 0000000..3d99ffb Binary files /dev/null and b/CItems/QSLBox/res/SBG3.bmp differ diff --git a/CItems/QSLBox/res/SBG4.bmp b/CItems/QSLBox/res/SBG4.bmp new file mode 100644 index 0000000..8cb6c5e Binary files /dev/null and b/CItems/QSLBox/res/SBG4.bmp differ diff --git a/CItems/QSLBox/res/SBS1.bmp b/CItems/QSLBox/res/SBS1.bmp new file mode 100644 index 0000000..593f6fd Binary files /dev/null and b/CItems/QSLBox/res/SBS1.bmp differ diff --git a/CItems/QSLBox/res/SBS2.bmp b/CItems/QSLBox/res/SBS2.bmp new file mode 100644 index 0000000..3e9baf8 Binary files /dev/null and b/CItems/QSLBox/res/SBS2.bmp differ diff --git a/CItems/QSLBox/res/SBS3.bmp b/CItems/QSLBox/res/SBS3.bmp new file mode 100644 index 0000000..55fc484 Binary files /dev/null and b/CItems/QSLBox/res/SBS3.bmp differ diff --git a/CItems/QSLBox/res/SBS4.bmp b/CItems/QSLBox/res/SBS4.bmp new file mode 100644 index 0000000..b6e587b Binary files /dev/null and b/CItems/QSLBox/res/SBS4.bmp differ diff --git a/CItems/TEXTBOX/About.cpp b/CItems/TEXTBOX/About.cpp new file mode 100644 index 0000000..41af7ae --- /dev/null +++ b/CItems/TEXTBOX/About.cpp @@ -0,0 +1,35 @@ +//--------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "About.h" +#include "ComLib.h" +//--------------------------------------------------------------------- +#pragma resource "*.dfm" +//TAboutDlg *AboutDlg; +//--------------------------------------------------------------------- +#if UseHWND +__fastcall TAboutDlg::TAboutDlg(HWND hWnd) + : TForm(hWnd) +#else +__fastcall TAboutDlg::TAboutDlg(TComponent* AOwner) + : TForm(AOwner) +#endif +{ + if( sys.m_MsgEng ){ + Font->Name = "Arial"; + Font->Charset = ANSI_CHARSET; + Caption = TTL; + } + else { + Caption = TTLJ; + } + LVer->Caption = VER" "AUT; + HICON hIcon = ::LoadIcon(HInstance, (LPCSTR)8000); + TIcon *pIcon = new TIcon; + pIcon->Handle = hIcon; + Image->Picture->Icon = pIcon; +} +//--------------------------------------------------------------------- + + \ No newline at end of file diff --git a/CItems/TEXTBOX/About.dfm b/CItems/TEXTBOX/About.dfm new file mode 100644 index 0000000..aaa1fcc Binary files /dev/null and b/CItems/TEXTBOX/About.dfm differ diff --git a/CItems/TEXTBOX/About.h b/CItems/TEXTBOX/About.h new file mode 100644 index 0000000..21c19b6 --- /dev/null +++ b/CItems/TEXTBOX/About.h @@ -0,0 +1,35 @@ +//---------------------------------------------------------------------------- +#ifndef OCRH +#define OCRH +//---------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ComLib.h" +//---------------------------------------------------------------------------- +class TAboutDlg : public TForm +{ +__published: + TButton *OKBtn; + TLabel *LVer; + TImage *Image; +private: +public: +#if UseHWND + virtual __fastcall TAboutDlg(HWND hWnd); +#else + virtual __fastcall TAboutDlg(TComponent* AOwner); +#endif +}; +//---------------------------------------------------------------------------- +//extern PACKAGE TAboutDlg *AboutDlg; +//---------------------------------------------------------------------------- +#endif + \ No newline at end of file diff --git a/CItems/TEXTBOX/CodeVw.cpp b/CItems/TEXTBOX/CodeVw.cpp new file mode 100644 index 0000000..93c54af --- /dev/null +++ b/CItems/TEXTBOX/CodeVw.cpp @@ -0,0 +1,479 @@ +//--------------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "CodeVw.h" +//--------------------------------------------------------------------------- +#pragma package(smart_init) +#pragma resource "*.dfm" +//TCodeView *CodeView; +//--------------------------------------------------------------------------- +__fastcall TCodeView::TCodeView(TComponent* Owner) + : TForm(Owner) +{ + if( sys.m_MsgEng ){ + Font->Name = "Arial"; + Font->Charset = ANSI_CHARSET; + +// Caption = "Character code list"; + SBClose->Caption = "Close"; + SBOut->Caption = "EUDC"; + SBEdit->Caption = "Edit"; + SBClear->Caption = "Clear"; + + SBFont->Hint = "Choose font"; + SBClear->Font->Size = 10; + SBOut->Font->Size = 10; + SBEdit->Font->Size = 10; + } + SBA->Hint = "Webdings"; + SBB->Hint = "Wingdings"; + SBC->Hint = "Symbol"; + SBUS->Hint = "English(ANSI)"; + SBJA->Hint = sys.m_MsgEng ? "Japanese(Shift-JIS)" : "日本語(シフトJIS)"; + SBHL->Hint = sys.m_MsgEng ? "Korean(Hangul)" : "韓国語(ハングル)"; + SBBY->Hint = sys.m_MsgEng ? "Chinese(GB2312)" : "中国語(簡体)"; + SBBV->Hint = sys.m_MsgEng ? "Chinese(BIG5)" : "中国語(繁体)"; + SBOut->Hint = "EUDC(End-user-defined-characters)"; + m_hWnd = NULL; + m_pFont = NULL; + m_Base = 0; + m_MouseDown = 0; + CheckFontCharset(); + SBJA->Enabled = sys.m_tFontFam[fmJA]; + SBHL->Enabled = sys.m_tFontFam[fmHL] || sys.m_tFontFam[fmJOHAB]; + SBBV->Enabled = sys.m_tFontFam[fmBV]; + SBBY->Enabled = sys.m_tFontFam[fmBY]; + + UpdateXW(); + int YW = GetSystemMetrics(SM_CYFULLSCREEN); + Left = sys.m_CodeLeft; + Top = sys.m_CodeTop; + if( Left < 0 ) Left = 0; + if( Top + Height > YW ) Top = YW - Height; + SBEdit->Enabled = sys.m_fEudc; + ShowHint = sys.m_WinNT; +} +//--------------------------------------------------------------------------- +WORD __fastcall TCodeView::GetEUDC(int y, int x) +{ +const WORD _tOut[]={0xf040, 0xf050, 0xf060, 0xf070, + 0xf080, 0xf090, 0xf0a0, 0xf0b0, + 0xf0c0, 0xf0d0, 0xf0e0, 0xf0f0, + 0xf140, 0xf150, 0xf160, 0xf170, +}; +const WORD _tOutHL[]={0xc9a0, 0xc9b0, 0xc9c0, 0xc9d0, + 0xc9e0, 0xc9f0, 0xfea0, 0xfeb0, + 0xfec0, 0xfed0, 0xfee0, 0xfef0, + 0, 0, 0, 0, +}; +const WORD _tOutBV[]={0xfa40, 0xfa50, 0xfa60, 0xfa70, + 0xfaa0, 0xfab0, 0xfac0, 0xfad0, + 0xfae0, 0xfaf0, 0xfb40, 0xfb50, + 0xfb60, 0xfb70, 0xfba0, 0xfbb0, +}; +const WORD _tOutBY[]={0xaaa0, 0xaab0, 0xaac0, 0xaad0, + 0xaae0, 0xaaf0, 0xaba0, 0xabb0, + 0xabc0, 0xabd0, 0xabe0, 0xabf0, + 0xaca0, 0xacb0, 0xacc0, 0xacd0, +}; + int c; + switch(m_pFont->Charset){ + case SHIFTJIS_CHARSET: + c = _tOut[y] + x; + if( (c==0xf07f)||(c==0xf0fd)||(c==0xf0fe)||(c==0xf0ff)||(c==0xf17f) ) c = 0; + break; + case HANGEUL_CHARSET: + c = _tOutHL[y]; + if( c ){ + c += x; + if( (c==0xc9a0)||(c==0xfea0)||(c==0xc9ff)||(c==0xfeff) ) c = 0; + } + break; + case CHINESEBIG5_CHARSET: // 台湾 + c = _tOutBV[y] + x; + if( (c==0xfa7f)||(c==0xfaa0)||(c==0xfaff)||(c==0xfb7f)||(c==0xfba0) ) c = 0; + break; + case 134: // 中国語簡略 + c = _tOutBY[y] + x; + if( (c==0xaaa0)||(c==0xaaff)||(c==0xaba0)||(c==0xabff)||(c==0xaca0) ) c = 0; + break; + default: + c = 0; + break; + } + return WORD(c); +} +//--------------------------------------------------------------------------- +void __fastcall TCodeView::UpdateTitle(void) +{ + AnsiString as = sys.m_MsgEng ? "Character code list" : "文字コード表"; + as += " ["; + as += m_pFont->Name; + AddStyle(as, m_pFont->Charset, 0); + as += "]"; + Caption = as; +} +//--------------------------------------------------------------------------- +void __fastcall TCodeView::UpdateXW(void) +{ + if( SBOut->Down || m_Base ){ + m_XW = PBox->Width / 17; + m_XW--; + m_YW1 = m_YW = PBox->Height / 17; + m_XW1 = PBox->Width - (m_XW * 16); + SBEdit->Visible = SBOut->Down; + UDMB->Visible = m_Base ? TRUE : FALSE; + } + else { + m_XW1 = m_XW = PBox->Width / 17; + m_YW1 = m_YW = PBox->Height / 17; + SBEdit->Visible = FALSE; + UDMB->Visible = FALSE; + } +} +//--------------------------------------------------------------------------- +void __fastcall TCodeView::SetPBoxFont(TCanvas *pCanvas) +{ + pCanvas->Font = m_pFont; + pCanvas->Font->Height = -(m_YW-5); + TFontStyles fs; + fs = Code2FontStyle(0); + pCanvas->Font->Style = fs; +} +//--------------------------------------------------------------------------- +void __fastcall TCodeView::DrawChar(TCanvas *pCanvas, int c, BOOL f) +{ + + int x = c % 16; + int y = c / 16; + char bf[32]; + LPSTR t = bf; + if( SBOut->Down ){ + c = GetEUDC(y, x); + } + else if( c ){ + c += m_Base; + } + if( !c ) return; + if( c & 0x00ff00 ) *t++ = BYTE(c>>8); + *t++ = BYTE(c); + *t = 0; + pCanvas->Font->Color = f ? clWhite : clBlack; + int fw = pCanvas->TextWidth(bf); + int fh = pCanvas->TextHeight(bf); + int xx = m_XW1 + x * m_XW + (m_XW-fw)/2; + int yy = m_YW1 + y * m_YW + (m_YW-fh)/2; + ::SetBkMode(pCanvas->Handle, TRANSPARENT); + pCanvas->TextOut(xx, yy, bf); +} +//--------------------------------------------------------------------------- +void __fastcall TCodeView::DrawCursor(TCanvas *pCanvas, int c, BOOL f) +{ + TRect rc; + + int x = c % 16; + int y = c / 16; + rc.Left = 1 + m_XW1 + x * m_XW; + rc.Top = 1 + m_YW1 + y * m_YW; + rc.Right = rc.Left + m_XW - 1; + rc.Bottom = rc.Top + m_YW - 1; + TColor col; + if( f ){ + col = clBlue; + } + else if( (!SBOut->Down && !m_Base) && m_tPfx[c] ){ + col = clGray; + } + else { + col = clWhite; + } + pCanvas->Pen->Color = col; + pCanvas->Brush->Color = col; + pCanvas->FillRect(rc); + DrawChar(pCanvas, c, f); +} +//--------------------------------------------------------------------------- +void __fastcall TCodeView::PBoxPaint(TObject *Sender) +{ + if( !m_pFont ) return; + + CWaitCursor w; + Graphics::TBitmap *pBmp = new Graphics::TBitmap; + pBmp->Width = PBox->Width; + pBmp->Height = PBox->Height; + TCanvas *pCanvas = pBmp->Canvas; + BOOL eud = SBOut->Down; + if( !m_Base && !eud ) memset(m_tPfx, 0, sizeof(m_tPfx)); + SetPBoxFont(pCanvas); + if( !eud ) SetMBCP(m_pFont->Charset); + int x, y, xx, yy, fw, fh; + char bf[16]; + int c = 0; + for( y = 0; y < 16; y++ ){ + for( x = 0; x < 16; x++ ){ + if( eud ){ + DrawChar(pCanvas, c, FALSE); + } + else { + if( !m_Base && (_mbsbtype((const unsigned char *)&c, 0) == _MBC_LEAD) ){ + m_tPfx[c] = TRUE; + DrawCursor(pCanvas, c, FALSE); + } + else { + DrawChar(pCanvas, c, FALSE); + } + } + c++; + } + } + pCanvas->Font = Font; + pCanvas->Pen->Color = clBlack; + ::SetBkMode(pCanvas->Handle, TRANSPARENT); + for( y = 0; y < 16; y++ ){ + wsprintf(bf, "%X", y); + fw = pCanvas->TextWidth(bf); + fh = pCanvas->TextHeight(bf); + xx = m_XW1 + y*m_XW + (m_XW-fw)/2; + yy = (m_YW1-fh)/2; + pCanvas->TextOut(xx, yy, bf); + + if( eud ){ + c = GetEUDC(y, 1) & 0xfff0; + if( c ){ + wsprintf(bf, "%04x", c); + } + else { + bf[0] = 0; + } + } + else if( m_Base ){ + wsprintf(bf, "%04x", y*16 + m_Base); + } + else { + wsprintf(bf, "%02X", y*16); + } + fw = pCanvas->TextWidth(bf); + fh = pCanvas->TextHeight(bf); + xx = (m_XW1-fw)/2; + yy = m_YW1 + y*m_YW + (m_YW-fh)/2; + pCanvas->TextOut(xx, yy, bf); + + pCanvas->Pen->Width = y ? 1 : 2; + pCanvas->MoveTo(0, m_YW1 + y*m_YW); + pCanvas->LineTo(PBox->Width, m_YW1 + y*m_YW); + pCanvas->MoveTo(m_XW1 + y*m_XW, 0); + pCanvas->LineTo(m_XW1 + y*m_XW, PBox->Height); + } + PBox->Canvas->Draw(0, 0, pBmp); + delete pBmp; + m_pfxCount = 0; + for( x = 0; x < 256; x++ ){ + if( m_tPfx[x] ){ + m_tPfxIdx[m_pfxCount] = x; + m_pfxCount++; + } + } + if( m_pfxCount != UDMB->Max ) UDMB->Max = short(m_pfxCount - 1); +} +//--------------------------------------------------------------------------- +void __fastcall TCodeView::ReqClose(void) +{ + sys.m_CodeLeft = Left; + sys.m_CodeTop = Top; + if( SBOut->Visible ) sys.m_CodeOut = SBOut->Down; + ::PostMessage(m_hWnd, WM_FORMCLOSE, 0, DWORD(this)); +} +//--------------------------------------------------------------------------- +void __fastcall TCodeView::FormClose(TObject *Sender, TCloseAction &Action) +{ + if( Action == caHide ) ReqClose(); +} +//--------------------------------------------------------------------------- +void __fastcall TCodeView::Execute(HWND hWnd, TFont *pFont) +{ + int f = Visible; + if( f && SBOut->Visible ) sys.m_CodeOut = SBOut->Down; + m_hWnd = hWnd; + m_pFont = pFont; + m_Base = 0; + SBOut->Visible = GetEUDC(0, 1) ? TRUE : FALSE; + SBOut->Down = SBOut->Visible && sys.m_CodeOut; + UpdateXW(); + UpdateTitle(); + Visible = TRUE; + if( f ) PBoxPaint(NULL); +} +//--------------------------------------------------------------------------- +void __fastcall TCodeView::SBCloseClick(TObject *Sender) +{ + Close(); +} +//--------------------------------------------------------------------------- +void __fastcall TCodeView::PBoxMouseDown(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( (Button == mbRight) && (m_Base || SBOut->Down) ){ + if( m_Base ){ + m_Base = 0; + } + else { + SBOut->Down = FALSE; + } + UpdateXW(); PBoxPaint(NULL); + return; + } + if( Button != mbLeft ) return; + + X -= m_XW1; + Y -= m_YW1; + if( X < 0 ) return; + if( Y < 0 ) return; + X /= m_XW; + Y /= m_YW; + if( X >= 16 ) X = 15; + if( Y >= 16 ) Y = 15; + int code = (Y * 16) + X; + m_MouseDown = code + 1; + TCanvas *pCanvas = PBox->Canvas; + SetPBoxFont(pCanvas); + DrawCursor(pCanvas, code, TRUE); + if( SBOut->Down ){ + code = GetEUDC(Y, X); + if( !code ) return; + } + else { + if( m_Base ){ + code |= m_Base | 0x00010000; +// PBoxPaint(NULL); + } + else if( m_tPfx[code] ){ + for( int i = 0; i < m_pfxCount; i++ ){ + if( m_tPfxIdx[i] == code ){ + UDMB->Position = short(i); + break; + } + } + m_Base = (code << 8); + UpdateXW(); PBoxPaint(NULL); + m_MouseDown = FALSE; + return; + } + } + ::PostMessage(m_hWnd, WM_CODEINSERT, code, DWORD(this)); +} +//--------------------------------------------------------------------------- +void __fastcall TCodeView::PBoxMouseUp(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( !m_MouseDown ) return; + + m_MouseDown--; + TCanvas *pCanvas = PBox->Canvas; + SetPBoxFont(pCanvas); + DrawCursor(pCanvas, m_MouseDown, FALSE); + m_MouseDown = 0; +} +//--------------------------------------------------------------------------- +void __fastcall TCodeView::SBClearClick(TObject *Sender) +{ + ::PostMessage(m_hWnd, WM_CODEINSERT, 0xffffffff, DWORD(this)); +} +//--------------------------------------------------------------------------- +void __fastcall TCodeView::SBFontClick(TObject *Sender) +{ + ::PostMessage(m_hWnd, WM_CODEINSERT, 0xfffffffe, DWORD(this)); +} +//--------------------------------------------------------------------------- +void __fastcall TCodeView::SBOutClick(TObject *Sender) +{ + m_Base = 0; + UpdateXW(); + PBoxPaint(NULL); +} +//--------------------------------------------------------------------------- +void __fastcall TCodeView::SBEditClick(TObject *Sender) +{ + LPCSTR pName = "EUDCEDIT.EXE"; + if( sys.m_Eudc.IsEmpty() ){ + char dir[MAX_PATH]; + char bf[512]; + if( ::GetSystemDirectory(dir, sizeof(dir)) ){ + wsprintf(bf, "%s\\%s", dir, pName); + if( IsFile(bf) ) sys.m_Eudc = bf; + } + if( sys.m_Eudc.IsEmpty() && ::GetWindowsDirectory(dir, sizeof(dir)) ){ + wsprintf(bf, "%s\\%s", dir, pName); + if( IsFile(bf) ) sys.m_Eudc = bf; + } + if( sys.m_Eudc.IsEmpty() ){ + wsprintf(bf, "%c:\\Program Files\\Accessories\\%s", dir[0], pName); + if( IsFile(bf) ) sys.m_Eudc = bf; + } + if( sys.m_Eudc.IsEmpty() ) sys.m_Eudc = pName; + } + if( ::WinExec(sys.m_Eudc.c_str(), SW_SHOWDEFAULT) > 31 ){ + ReqClose(); + } + else { + SBEdit->Enabled = FALSE; + sys.m_fEudc = FALSE; + } +} +//--------------------------------------------------------------------------- +void __fastcall TCodeView::SBAClick(TObject *Sender) +{ + DWORD dw = 0xfffffff2; + if( Sender == SBA ){ + dw = 0xfffffff0; + } + else if( Sender == SBB ){ + dw = 0xfffffff1; + } + ::PostMessage(m_hWnd, WM_CODEINSERT, dw, DWORD(this)); +} +//--------------------------------------------------------------------------- +void __fastcall TCodeView::SBUSClick(TObject *Sender) +{ + DWORD sw; + if( Sender == SBJA ){ + sw = 0xfffffff4; + } + else if( Sender == SBHL ){ + sw = 0xfffffff5; + } + else if( Sender == SBBY ){ + sw = 0xfffffff6; + } + else if( Sender == SBBV ){ + sw = 0xfffffff7; + } + else { + sw = 0xfffffff3; + } + ::PostMessage(m_hWnd, WM_CODEINSERT, sw, DWORD(this)); +} +//--------------------------------------------------------------------------- +void __fastcall TCodeView::UDMBClick(TObject *Sender, TUDBtnType Button) +{ + m_Base = m_tPfxIdx[UDMB->Position] << 8; + UpdateXW(); PBoxPaint(NULL); +} +//--------------------------------------------------------------------------- +int CALLBACK EnumFontFamExProc(ENUMLOGFONT FAR* lpelf, NEWTEXTMETRIC FAR* lpntm, DWORD FontType, LPARAM lParam) +{ switch(lpelf->elfLogFont.lfCharSet){ case SHIFTJIS_CHARSET: sys.m_tFontFam[fmJA] = TRUE; break; case HANGEUL_CHARSET: sys.m_tFontFam[fmHL] = TRUE; break; case JOHAB_CHARSET: sys.m_tFontFam[fmJOHAB] = TRUE; break; case CHINESEBIG5_CHARSET: // 台湾 sys.m_tFontFam[fmBV] = TRUE; break; case 134: // 中国語簡略 sys.m_tFontFam[fmBY] = TRUE; break; default: break; } int r = FALSE; for( int i = 0; i < fmEND; i++ ){ if( !sys.m_tFontFam[i] ) r = TRUE; } return r; } //--------------------------------------------------------------------------- +void __fastcall TCodeView::CheckFontCharset(void) +{ + if( sys.m_fFontFam ) return; + + sys.m_fFontFam = TRUE; + memset(sys.m_tFontFam, 0, sizeof(sys.m_tFontFam)); + LOGFONT logfont; + memset(&logfont, 0, sizeof(logfont)); + logfont.lfCharSet = DEFAULT_CHARSET; + HDC hDC = ::CreateDC("DISPLAY", NULL, NULL, NULL); + ::EnumFontFamiliesEx(hDC, &logfont, (int (_stdcall *)())EnumFontFamExProc, LPARAM(this), 0); + ::DeleteDC(hDC); +} +//--------------------------------------------------------------------------- + diff --git a/CItems/TEXTBOX/CodeVw.dfm b/CItems/TEXTBOX/CodeVw.dfm new file mode 100644 index 0000000..8d98b33 Binary files /dev/null and b/CItems/TEXTBOX/CodeVw.dfm differ diff --git a/CItems/TEXTBOX/CodeVw.h b/CItems/TEXTBOX/CodeVw.h new file mode 100644 index 0000000..7808ed5 --- /dev/null +++ b/CItems/TEXTBOX/CodeVw.h @@ -0,0 +1,81 @@ +//--------------------------------------------------------------------------- +#ifndef CodeVwH +#define CodeVwH +//--------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include + +#include "ComLib.h" +#include +#define WM_FORMCLOSE (WM_USER+410) +#define WM_CODEINSERT (WM_USER+411) +//--------------------------------------------------------------------------- +class TCodeView : public TForm +{ +__published: // IDE 管理のコンポーネント + TPanel *Panel; + TPaintBox *PBox; + TSpeedButton *SBClose; + TSpeedButton *SBClear; + TSpeedButton *SBFont; + TSpeedButton *SBOut; + TSpeedButton *SBEdit; + TSpeedButton *SBA; + TSpeedButton *SBB; + TSpeedButton *SBC; + TSpeedButton *SBUS; + TSpeedButton *SBJA; + TSpeedButton *SBHL; + TSpeedButton *SBBY; + TSpeedButton *SBBV; + TUpDown *UDMB; + void __fastcall PBoxPaint(TObject *Sender); + void __fastcall FormClose(TObject *Sender, TCloseAction &Action); + void __fastcall SBCloseClick(TObject *Sender); + void __fastcall PBoxMouseDown(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + void __fastcall SBClearClick(TObject *Sender); + void __fastcall SBFontClick(TObject *Sender); + + void __fastcall SBOutClick(TObject *Sender); + void __fastcall SBEditClick(TObject *Sender); + void __fastcall SBAClick(TObject *Sender); + + void __fastcall SBUSClick(TObject *Sender); + void __fastcall UDMBClick(TObject *Sender, TUDBtnType Button); + void __fastcall PBoxMouseUp(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); +private: // ユーザー宣言 + HWND m_hWnd; + TFont *m_pFont; + int m_XW1; + int m_YW1; + int m_XW; + int m_YW; + int m_MouseDown; + int m_Base; + BOOL m_tPfx[256]; + int m_pfxCount; + int m_tPfxIdx[256]; + void __fastcall UpdateTitle(void); + void __fastcall ReqClose(void); + void __fastcall UpdateXW(void); + void __fastcall SetPBoxFont(TCanvas *pCanvas); + void __fastcall DrawChar(TCanvas *pCanvas, int c, BOOL f); + void __fastcall DrawCursor(TCanvas *pCanvas, int c, BOOL f); + WORD __fastcall GetEUDC(int y, int x); + void __fastcall CheckFontCharset(void); + +public: // ユーザー宣言 + __fastcall TCodeView(TComponent* Owner); + + void __fastcall Execute(HWND hWnd, TFont *pFont); +}; +//--------------------------------------------------------------------------- +//extern PACKAGE TCodeView *CodeView; +//--------------------------------------------------------------------------- +#endif diff --git a/CItems/TEXTBOX/Comlib.cpp b/CItems/TEXTBOX/Comlib.cpp new file mode 100644 index 0000000..3f09c6f --- /dev/null +++ b/CItems/TEXTBOX/Comlib.cpp @@ -0,0 +1,2000 @@ +//--------------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "ComLib.h" +#include "TextDlg.h" +SYS sys; +//--------------------------------------------------------------------------- +void __fastcall InitSys(void) +{ + sys.m_dwVersion = 0; + sys.m_WinNT = 0; + sys.m_CodePage = 0; + sys.m_MsgEng = 0; + sys.m_BitPixel = 0; + sys.m_fGetMacKey = 0; + sys.m_fConvMac = 0; + sys.m_fMultProc = 0; + sys.m_fColorComp = 0; + sys.m_DefStgSize = 0; + sys.m_pDefStg = NULL; + sys.m_pTextList = NULL; + sys.m_pStyleList = NULL; + sys.m_BgnDir[0] = 0; + sys.m_pFontList = NULL; + sys.m_pBitmapTemp = NULL; + + sys.m_CodeLeft = 0; + sys.m_CodeTop = 0; + sys.m_CodeOut = 0; + + sys.m_fFontFam = FALSE; + memset(sys.m_tFontFam, 0, sizeof(sys.m_tFontFam)); + + sys.m_dwVersion = ::GetVersion(); + sys.m_WinNT = (sys.m_dwVersion < 0x80000000) ? TRUE : FALSE; + sys.m_CodePage = ::GetACP(); // Get codepage + + HDC hdcScreen = ::CreateDC("DISPLAY", NULL, NULL, NULL); + sys.m_BitPixel = ::GetDeviceCaps(hdcScreen, BITSPIXEL); + ::DeleteDC(hdcScreen); + + sys.m_fEudc = TRUE; + sys.m_Eudc = ""; +} +// +//--------------------------------------------------------------------------- +//void mcmFunc(DWORD index, FARPROC pFunc) +// +//MMSSTV calls this function at the first time, if the function was exported. +//You can use following functions which are in the MMSSTV. +// +// index : Index of the function. +// pFunc : Address of the function. +// +//indexes and functions are as follows. +// +// 0 : HBITMAP (__cdecl *mmLoadImageMenu)(int sw, int xw, int yw); +// sw - 0 : Invoke image-clipper (xw and yw are the size of the bitmap) +// sw - 1 : no image-clipper (xw and yw will be ignored) +// +// 1 : HBITMAP (__cdecl *mmLoadImage)(LPCSTR pName); +// pName is a pathname of the image (BMP, JPG, WMF) +// +// 2 : HBITMAP (__cdecl *mmLoadHistImage)(void); +// +// 3 : int (__cdecl *mmSaveImageMenu)(HBITMAP hb, LPCSTR pName, LPCSTR pFolder); +// pName is a filename of the image (BMP, JPG) +// pFolder is a folder name (if it is NULL, MMSSTV uses a default) +// +// 4 : int (__cdecl *mmSaveImage)(HBITMAP hb, LPCSTR pName); +// pName is a pathname of the image (BMP, JPG) +// +// 5 : HBITMAP (__cdecl *mmPasteImage)(int sw, int xw, int yw); +// sw - 0 : Invoke image-clipper (xw and yw are the size of the bitmap) +// sw - 1 : no image-clipper (xw and yw will be ignored) +// +// 6 : int (__cdecl *mmGetMacKey)(LPSTR pDest, int cbDest); +// Invoke macro dialog box and can choose keyword +// +// 7 : int (__cdecl *mmConvMac)(LPSTR pDest, LPCSTR pSrc, int cbDest); +// Convert macro keyword (pSrc) to the text (pDest) +// +// 8 : HBITMAP (__cdecl *mmCreateDIB)(int xw, int yw); +// Create 24bit DIB +// +// 9 : void (__cdecl *mmMultProc)(void); +// 10 : void (__cdecl *mmMultProcA)(void); +// Do decoding and encoding with the DSP in MMSSTV +// +// 11 : int (__cdecl *mmColorComp)(LPDWORD pCol); +// Invoke color components dialog and can choose a color component +// +extern "C" __declspec(dllexport) +void mcmFunc(DWORD index, FARPROC pFunc) +{ + switch(index){ + case 6: + sys.m_fGetMacKey = (mmGetMacKey)pFunc; + break; + case 7: + sys.m_fConvMac = (mmConvMac)pFunc; + break; + case 9: + sys.m_fMultProc = (mmMultProc)pFunc; + break; + case 11: + sys.m_fColorComp = (mmColorComp)pFunc; + break; + default: + break; + } +} +//--------------------------------------------------------------------------- +void __fastcall MultProc(void) +{ + if( sys.m_fMultProc ) sys.m_fMultProc(); +} +//--------------------------------------------------------------------------- +char __fastcall LastC(LPCSTR p) +{ + char c = 0; + + if( *p ){ + c = *(p + strlen(p) - 1); + } + return c; +} +//--------------------------------------------------------------------------- +void __fastcall SetCurDir(LPSTR t, int size) +{ + if( !::GetCurrentDirectory(size-1, t) ){ + *t = 0; + } + else { + if( LastC(t) != '\\' ){ + strcat(t, "\\"); + } + } +} +//--------------------------------------------------------------------------- +void __fastcall SetDirName(LPSTR t, LPCSTR pName) +{ + char drive[_MAX_DRIVE]; + char dir[_MAX_DIR]; + char name[_MAX_FNAME]; + char ext[_MAX_EXT]; + AnsiString Dir; + + ::_splitpath( pName, drive, dir, name, ext ); + Dir = drive; + Dir += dir; + strncpy(t, Dir.c_str(), 128); +} +///---------------------------------------------------------------- +void __fastcall Yen2CrLf(AnsiString &ws, AnsiString cs) +{ + ws = ""; + LPCSTR p; + int f; + int dlm = 0; + + p = cs.c_str(); + if( *p == 0x22 ){ + p++; + dlm++; + } + for( f = 0; *p; p++ ){ + if( f ){ + f = 0; + ws += *p; + } + else if( _mbsbtype((const unsigned char *)p, 0) == _MBC_LEAD ){ + f = 1; + ws += *p; + } + else if( *p == '\\' ){ + switch(*(p+1)){ + case 'r': + ws += "\r"; + p++; + break; + case 'n': + ws += "\n"; + p++; + break; + case 't': + ws += "\t"; + p++; + break; + case '\\': + ws += "\\"; + p++; + break; + default: + p++; + ws += *p; + break; + } + } + else if( !dlm || (*p!=0x22) || *(p+1) ){ + ws += *p; + } + } +} +//--------------------------------------------------------------------------- +void __fastcall CrLf2Yen(AnsiString &ws, AnsiString cs) +{ + ws = "\x22"; + LPCSTR p; + int f = 0; + + for( p = cs.c_str(); *p; p++ ){ + if( f ){ + ws += *p; + f = 0; + } + else if( _mbsbtype((const unsigned char *)p, 0) == _MBC_LEAD ){ + f = 1; + ws += *p; + } + else if( *p == 0x0d ){ + ws += "\\r"; + } + else if( *p == 0x0a ){ + ws += "\\n"; + } + else if( *p == '\t' ){ + ws += "\\t"; + } + else if( *p == '\\' ){ + ws += "\\\\"; + } + else { + ws += *p; + } + } + ws += "\x22"; +} +///---------------------------------------------------------------- +/// 文字列を数値に変換する +/// +int htoin(LPCSTR sp, int n) +{ + int d = 0; + + for( ; *sp && n; sp++, n-- ){ + d = d * 16; + d += *sp & 0x0f; + if( *sp >= 'A' ) d += 9; + } + return d; + +} +//--------------------------------------------------------------------------- +void __fastcall AddStyle(AnsiString &as, BYTE charset, DWORD style) +{ + switch(charset){ + case ANSI_CHARSET: + as += sys.m_MsgEng ? "/ANSI" : "/欧文"; + break; + case SHIFTJIS_CHARSET: + as += sys.m_MsgEng ? "/Japanese" : "/日本語"; + break; + case HANGEUL_CHARSET: + as += sys.m_MsgEng ? "/Korean(Hangul)" : "/ハングル"; + break; + case JOHAB_CHARSET: + as += sys.m_MsgEng ? "/Korean(Johab)" : "/ハングル(Johab)"; + break; + case CHINESEBIG5_CHARSET: // 台湾 + as += sys.m_MsgEng ? "/Chinese(BIG5)" : "/中国語(繁体)"; + break; + case 134: // 中国語簡略 + as += sys.m_MsgEng ? "/Chinese(GB2312)" : "/中国語(簡体)"; + break; + case SYMBOL_CHARSET: + as += sys.m_MsgEng ? "/Symbol" : "/シンボル"; + break; + default: + break; + } + if( style & FSBOLD ) as += sys.m_MsgEng ? "/Bold" : "/太字"; + if( style & FSITALIC ) as += sys.m_MsgEng ? "/Italic" : "/斜体"; + if( style & FSUNDERLINE ) as += sys.m_MsgEng ? "/UnderLine" : "/下線"; + if( style & FSSTRIKEOUT ) as += sys.m_MsgEng ? "/StrikeOut" : "/取消し線"; +} +//--------------------------------------------------------------------------- +int __fastcall IsFile(LPCSTR pName) +{ + WIN32_FIND_DATA fdata; + HANDLE hFind = ::FindFirstFile(pName, &fdata); + if( hFind != INVALID_HANDLE_VALUE ){ + FindClose(hFind); + return TRUE; + } + else { + return FALSE; + } +} +//--------------------------------------------------------------------------- +void __fastcall SetMBCP(BYTE charset) +{ + UINT cp; + switch(charset){ + case SHIFTJIS_CHARSET: + cp = 932; + break; + case HANGEUL_CHARSET: + cp = 949; + break; + case JOHAB_CHARSET: + cp = 1361; + break; + case CHINESEBIG5_CHARSET: // + cp = 950; + break; + case 134: // 簡略 + cp = 936; + break; + case ANSI_CHARSET: + case SYMBOL_CHARSET: + cp = 1252; + break; + default: + cp = _MB_CP_ANSI; + break; + } + if( cp != _MB_CP_ANSI ){ + CPINFO info; + if( GetCPInfo(cp, &info) != TRUE ){ + cp = _MB_CP_ANSI; + } + } + _setmbcp(cp); +} +//--------------------------------------------------------------------------- +void __fastcall LoadStringsFromIniFile(TStrings *pList, LPCSTR pSect, LPCSTR pName, int msg) +{ + char fname[512]; + sprintf(fname, "%s%s", sys.m_BgnDir, pName); + TMemIniFile *pIniFile = new TMemIniFile(fname); + int count = pIniFile->ReadInteger(pSect, "Count", 0); + int i; + AnsiString as; + for( i = 0; i < count; i++ ){ + char bf[32]; + sprintf(bf, "Text%u", i); + as = pIniFile->ReadString(pSect, bf, ""); + if( !as.IsEmpty() ){ + pList->Add(as.c_str()); + } + } + if( msg ){ + as = pIniFile->ReadString(pSect, "MSG", ""); + ::Yen2CrLf(sys.m_Msg, as); + } + delete pIniFile; +} +//--------------------------------------------------------------------------- +void __fastcall SaveStringsToIniFile(TStrings *pList, LPCSTR pSect, LPCSTR pName, int msg) +{ + char fname[512]; + sprintf(fname, "%s%s", sys.m_BgnDir, pName); + TMemIniFile *pIniFile = new TMemIniFile(fname); + pIniFile->WriteInteger(pSect, "Count", pList->Count); + int i; + for( i = 0; i < pList->Count; i++ ){ + char bf[32]; + sprintf(bf, "Text%u", i); + pIniFile->WriteString(pSect, bf, pList->Strings[i]); + } + if( msg ){ + AnsiString as; + ::CrLf2Yen(as, sys.m_Msg); + pIniFile->WriteString(pSect, "MSG", as); + } + pIniFile->UpdateFile(); + delete pIniFile; +} +//--------------------------------------------------------------------- +void __fastcall InitCustomColor(TColorDialog *tp) +{ + tp->CustomColors->Text = ""; +} +//--------------------------------------------------------------------- +void __fastcall AddCustomColor(TColorDialog *tp, TColor col) +{ + char bf[256]; + + sprintf(bf, "Color%c=%06lX", tp->CustomColors->Count + 'A', DWORD(col) & 0x00ffffff); + tp->CustomColors->Add(bf); +} +//--------------------------------------------------------------------- +LPSTR __fastcall ZeroConv(LPCSTR p, BYTE charset) +{ + LPSTR bp = new char[(strlen(p)*2) + 1]; + LPSTR t = bp; + int f = 0; + for( ; *p; p++ ){ + if( f ){ + *t++ = *p; + f = 0; + } + else if( _mbsbtype((const unsigned char *)p, 0) == _MBC_LEAD ){ + *t++ = *p; + f = 1; + } + else if( *p == '0' ){ + switch(charset){ + case SHIFTJIS_CHARSET: + *t++ = 0x83; + *t++ = 0xd3; + break; + case HANGEUL_CHARSET: + *t++ = 0xa8; // 0xa9 + *t++ = 0xaa; + break; + case CHINESEBIG5_CHARSET: // 台湾 + *t++ = 0xa3; + *t++ = 0x58; + break; + case 134: // 中国語簡略 + *t++ = 0xa6; + *t++ = 0xd5; + break; + default: + switch(sys.m_CodePage){ + case 949: // HANGEUL + *t++ = 0xa8; // 0xa9 + *t++ = 0xaa; + break; + case 950: // CHINESEBIG5 + *t++ = 0xa3; + *t++ = 0x58; + break; + case 936: // CHINESE 簡略 + *t++ = 0xa6; + *t++ = 0xd5; + break; + default: + *t++ = 'リ'; + break; + } + break; + } + } + else { + *t++ = *p; + } + } + *t = 0; + return bp; +} +//--------------------------------------------------------------------------- +Graphics::TBitmap * __fastcall CreateBitmap(int xw, int yw) +{ + Graphics::TBitmap *pBitmap = new Graphics::TBitmap; + pBitmap->PixelFormat = pf24bit; + pBitmap->Width = xw; + pBitmap->Height = yw; + return pBitmap; +} +//--------------------------------------------------------------------------- +void __fastcall FillBitmap(Graphics::TBitmap *pDest, UCOL ucol) +{ + TRect rc; + rc.Left = rc.Top = 0; + rc.Right = pDest->Width; + rc.Bottom = pDest->Height; + pDest->Canvas->Brush->Color = ucol.c; + pDest->Canvas->FillRect(rc); +} +//--------------------------------------------------------------------------- +void __fastcall CopyBitmap(Graphics::TBitmap *pDest, Graphics::TBitmap *pSrc) +{ + pDest->Width = pSrc->Width; + pDest->Height = pSrc->Height; + pDest->Palette = NULL; + pDest->Canvas->Draw(0, 0, pSrc); +} +//--------------------------------------------------------------------------- +//アスペクト比を保持する +void __fastcall KeepAspect(int &sx, int &sy, int bx, int by) +{ + double ass = double(sx) / double(sy); + double asb = double(bx) / double(by); + if( asb < ass ){ // ソースの方が横長 + sx = (double(sy) * asb) + 0.5; + } + else { + sy = (double(sx) / asb) + 0.5; + } +} +//--------------------------------------------------------------------------- +//アスペクト比を保持する +void __fastcall KeepAspectCopy(Graphics::TBitmap *pDest, int xm, int ym, Graphics::TBitmap *pSrc, int mode) +{ + if( (xm < pSrc->Width) || (ym < pSrc->Height) ){ + KeepAspect(xm, ym, pSrc->Width, pSrc->Height); + pDest->Width = xm; + pDest->Height = ym; + pDest->Palette = NULL; + TRect tc; + tc.Left = tc.Top = 0; + tc.Right = xm; tc.Bottom = ym; + int Sop = ::SetStretchBltMode(pDest->Canvas->Handle, mode); + pDest->Canvas->StretchDraw(tc, pSrc); + ::SetStretchBltMode(pDest->Canvas->Handle, Sop); + } + else { + CopyBitmap(pDest, pSrc); + } +} +//--------------------------------------------------------------------------- +void __fastcall DrawBitmap(TPaintBox *pBox, Graphics::TBitmap *pBitmap) +{ + if( pBitmap == NULL ) return; + + if( (pBitmap->Width != pBox->Width)||(pBitmap->Height != pBox->Height) ){ + TRect rc; + rc.Left = 0; rc.Right = pBox->Width; + rc.Top = 0, rc.Bottom = pBox->Height; + int Sop = ::SetStretchBltMode(pBox->Canvas->Handle, HALFTONE); + pBox->Canvas->StretchDraw(rc, pBitmap); + ::SetStretchBltMode(pBox->Canvas->Handle, Sop); + } + else { + pBox->Canvas->Draw(0, 0, pBitmap); + } +} +//--------------------------------------------------------------------------- +UCOL __fastcall GetUniqueColor(UCOL ucol) +{ + ucol.d = ucol.d & 0x00f0f0f0; + UCOL c = ucol; + DWORD r; + + while(!c.d || (c.d == ucol.d)){ +#if (RANDMAX >= 0x00ffffff) + c.d = rand() & 0x00f0f0f0; +#else + r = rand(); r = r << 4; + c.b.r = (BYTE)(r & 0x00f0); r = r >> 4; + c.b.g = (BYTE)(r & 0x00f0); r = r >> 4; + c.b.b = (BYTE)(r & 0x00f0); +#endif + } + if( sys.m_pBitmapTemp ){ + sys.m_pBitmapTemp->Canvas->Pixels[0][0] = c.c; + c.c = sys.m_pBitmapTemp->Canvas->Pixels[0][0]; + } + return c; +} +//--------------------------------------------------------------------------- +UCOL __fastcall GetGrade2(UCOL s[2], int x, int xw) +{ + if( x < 0 ) x = 0; + if( x > xw ) x = xw; + UCOL r; + int c = s[0].b.b + ((int(s[1].b.b) - int(s[0].b.b)) * x / xw); + if( c < 0 ) c = 0; + if( c > 255 ) c = 255; + r.b.b = BYTE(c); + c = s[0].b.g + ((int(s[1].b.g) - int(s[0].b.g)) * x / xw); + if( c < 0 ) c = 0; + if( c > 255 ) c = 255; + r.b.g = BYTE(c); + c = s[0].b.r + ((int(s[1].b.r) - int(s[0].b.r)) * x / xw); + if( c < 0 ) c = 0; + if( c > 255 ) c = 255; + r.b.r = BYTE(c); + return r; +} +//--------------------------------------------------------------------------- +UCOL __fastcall GetGrade4(UCOL s[4], int x, int xw) +{ + int xw3 = xw/3; + if( x < xw3 ){ + return GetGrade2(s, x, xw3); + } + x -= xw3; + if( x < xw3 ){ + return GetGrade2(&s[1], x, xw3); + } + x -= xw3; + return GetGrade2(&s[2], x, xw3); +} +//--------------------------------------------------------------------------- +void __fastcall WriteString(TStream *ps, AnsiString &as) +{ + int len = as.Length(); + ps->Write(&len, sizeof(len)); + if( len ){ + ps->Write(as.c_str(), len); + } +} +void __fastcall ReadString(TStream *ps, AnsiString &as) +{ + as = ""; + int len; + ps->Read(&len, sizeof(len)); + if( len ){ + LPSTR p = new char[len+1]; + ps->Read(p, len); + p[len] = 0; + as = p; + delete p; + } +} +//--------------------------------------------------------------------------- +int FontStyle2Code(TFontStyles style) +{ + int code = 0; + + TFontStyles fa; + TFontStyles fb; + + fa << fsBold; + fb << fsBold; + fa *= style; + if( fa == fb ) code |= FSBOLD; + + fa >> fsBold; + fb >> fsBold; + fa << fsItalic; + fb << fsItalic; + fa *= style; + if( fa == fb ) code |= FSITALIC; + + fa >> fsItalic; + fb >> fsItalic; + fa << fsUnderline; + fb << fsUnderline; + fa *= style; + if( fa == fb ) code |= FSUNDERLINE; + + fa >> fsUnderline; + fb >> fsUnderline; + fa << fsStrikeOut; + fb << fsStrikeOut; + fa *= style; + if( fa == fb ) code |= FSSTRIKEOUT; + + return code; +} + +TFontStyles Code2FontStyle(int code) +{ + TFontStyles fs; + + if( code & FSBOLD ) fs << fsBold; + if( code & FSITALIC ) fs << fsItalic; + if( code & FSUNDERLINE ) fs << fsUnderline; + if( code & FSSTRIKEOUT ) fs << fsStrikeOut; + return fs; +} +//--------------------------------------------------------------------------- +void __fastcall WriteFont(TStream *ps, TFont *pFont) +{ + int d; + if( pFont != NULL ){ + d = 1; + ps->Write(&d, sizeof(d)); + WriteString(ps, pFont->Name); + d = pFont->Charset; + ps->Write(&d, sizeof(d)); + d = pFont->Height; + ps->Write(&d, sizeof(d)); + TFontStyles ts = pFont->Style; + d = FontStyle2Code(ts); + ps->Write(&d, sizeof(d)); + } + else { + d = 0; + ps->Write(&d, sizeof(d)); + } +} +//--------------------------------------------------------------------------- +TFont* __fastcall ReadFont(TStream *ps) +{ + TFont *pFont = NULL; + int d; + ps->Read(&d, sizeof(d)); + if( d == 1 ){ + pFont = new TFont; + AnsiString as; + ReadString(ps, as); + pFont->Name = as; + ps->Read(&d, sizeof(d)); + pFont->Charset = BYTE(d); + ps->Read(&d, sizeof(d)); + pFont->Height = d; + ps->Read(&d, sizeof(d)); + TFontStyles ts = Code2FontStyle(d); + pFont->Style = ts; + } + return pFont; +} +///------------------------------------------------------ +/// +///CWaitCursor クラス +/// +CWaitCursor::CWaitCursor() +{ + sv = Screen->Cursor; + Screen->Cursor = crHourGlass; +} + +CWaitCursor::CWaitCursor(BOOL sw) +{ + sv = Screen->Cursor; + if( sw ){ + Screen->Cursor = crHourGlass; + } +} + +CWaitCursor::~CWaitCursor() +{ + Screen->Cursor = sv; +} + +void CWaitCursor::Delete(void) +{ + Screen->Cursor = sv; +} + +void CWaitCursor::Wait(void) +{ + Screen->Cursor = crHourGlass; +} +// +// +//--------------------------------------------------------------------------- +// CItem class +// +__fastcall CItem::CItem(void) +{ + m_pMemStream = NULL; + + m_Ver = 1; + m_ASize = 1; + m_Align = 0; + m_Grade = 0; + m_Shadow = 2; + m_Line = 1; + m_Zero = 0; + m_3d = 0x00000404; + m_Text = "TX\tFT1000MP\r\nANT\tMagnetic loop\r\nSOFT\tHome-made"; + m_pFont = NULL; + m_ColG[0].d = 255; + m_ColG[1].d = 16711935; + m_ColG[2].d = 65535; + m_ColG[3].d = 16776960; + m_ColB[0].c = clBlack; + m_ColB[1].c = clWhite; + m_ColB[2].c = clBlue; + m_ColB[3].c = clRed; + + m_OrgXW = -1; + m_OrgYW = -1; + m_TextXW = -1; + m_TextYW = -1; + m_Draft = 0; + m_IniSize = 0; + m_Pos = 0; + m_Ex = 0; + m_OYW = 0; + m_Rot = 0; +} +//--------------------------------------------------------------------------- +__fastcall CItem::~CItem() +{ + if( m_pFont != NULL ) delete m_pFont; + if( m_pMemStream != NULL ) delete m_pMemStream; +} +//--------------------------------------------------------------------------- +void __fastcall CItem::LoadDefault(void) +{ + if( sys.m_pDefStg != NULL ) return; + + CItem *pItem = new CItem; + pItem->LoadFromInifile("Default", ININAME); + LPCBYTE p = pItem->CreateStorage(&sys.m_DefStgSize); + sys.m_pDefStg = new BYTE[sys.m_DefStgSize]; + memcpy(sys.m_pDefStg, p, sys.m_DefStgSize); + pItem->DeleteStorage(p); + delete pItem; +} +//--------------------------------------------------------------------------- +void __fastcall CItem::UpdateDefault(void) +{ + if( sys.m_pDefStg != NULL ){ + delete sys.m_pDefStg; + sys.m_pDefStg = NULL; + } + LPCBYTE p = CreateStorage(&sys.m_DefStgSize); + sys.m_pDefStg = new BYTE[sys.m_DefStgSize]; + memcpy(sys.m_pDefStg, p, sys.m_DefStgSize); + DeleteStorage(p); +} +//--------------------------------------------------------------------------- +void __fastcall CItem::Create(LPCBYTE ps, DWORD size) +{ + if( (ps == NULL) || !size ){ + if( sys.m_pDefStg == NULL ) LoadDefault(); + ps = sys.m_pDefStg; + size = sys.m_DefStgSize; + } + + TMemoryStream *pMem = new TMemoryStream; + pMem->Clear(); + pMem->Write(ps, size); + pMem->Seek(soFromBeginning, 0); + int ver; + pMem->Read(&ver, sizeof(ver)); + if( ver <= m_Ver ){ + pMem->Read(&m_TextXW, sizeof(m_TextXW)); + pMem->Read(&m_TextYW, sizeof(m_TextYW)); + pMem->Read(&m_OrgXW, sizeof(m_OrgXW)); + pMem->Read(&m_OrgYW, sizeof(m_OrgYW)); + pMem->Read(&m_ASize, sizeof(m_ASize)); + pMem->Read(&m_Align, sizeof(m_Align)); + pMem->Read(&m_Grade, sizeof(m_Grade)); + pMem->Read(&m_Shadow, sizeof(m_Shadow)); + pMem->Read(&m_Line, sizeof(m_Line)); + pMem->Read(&m_Zero, sizeof(m_Zero)); + pMem->Read(&m_3d, sizeof(m_3d)); + pMem->Read(&m_ColG, sizeof(m_ColG)); + pMem->Read(&m_ColB, sizeof(m_ColB)); + if( ver >= 1 ){ + pMem->Read(&m_OYW, sizeof(m_OYW)); + pMem->Read(&m_Rot, sizeof(m_Rot)); + } + ReadString(pMem, m_Text); + if( m_pFont != NULL ) delete m_pFont; + m_pFont = ReadFont(pMem); + UpdateFont(); + } + delete pMem; +} +//--------------------------------------------------------------------------- +LPCBYTE __fastcall CItem::CreateStorage(LPDWORD pSize) +{ + ASSERT(pSize); + + if( m_pMemStream != NULL ) delete m_pMemStream; + m_pMemStream = new TMemoryStream; + m_pMemStream->Clear(); + m_Ver = 1; + m_pMemStream->Write(&m_Ver, sizeof(m_Ver)); + m_pMemStream->Write(&m_TextXW, sizeof(m_TextXW)); + m_pMemStream->Write(&m_TextYW, sizeof(m_TextYW)); + m_pMemStream->Write(&m_OrgXW, sizeof(m_OrgXW)); + m_pMemStream->Write(&m_OrgYW, sizeof(m_OrgYW)); + m_pMemStream->Write(&m_ASize, sizeof(m_ASize)); + m_pMemStream->Write(&m_Align, sizeof(m_Align)); + m_pMemStream->Write(&m_Grade, sizeof(m_Grade)); + m_pMemStream->Write(&m_Shadow, sizeof(m_Shadow)); + m_pMemStream->Write(&m_Line, sizeof(m_Line)); + m_pMemStream->Write(&m_Zero, sizeof(m_Zero)); + m_pMemStream->Write(&m_3d, sizeof(m_3d)); + m_pMemStream->Write(&m_ColG, sizeof(m_ColG)); + m_pMemStream->Write(&m_ColB, sizeof(m_ColB)); + m_pMemStream->Write(&m_OYW, sizeof(m_OYW)); + m_pMemStream->Write(&m_Rot, sizeof(m_Rot)); + WriteString(m_pMemStream, m_Text); + WriteFont(m_pMemStream, m_pFont); + *pSize = m_pMemStream->Position; + return (LPCBYTE)m_pMemStream->Memory; +} +//--------------------------------------------------------------------------- +void __fastcall LoadFontFromInifile(TFont *pFont, LPCSTR pSect, TMemIniFile *pIniFile) +{ + if( pFont == NULL ) return; + + pFont->Name = pIniFile->ReadString(pSect, "FontName", pFont->Name); + pFont->Charset = (BYTE)pIniFile->ReadInteger(pSect, "FontSet", pFont->Charset); + pFont->Height = pIniFile->ReadInteger(pSect, "FontSize", pFont->Height); + TFontStyles ts = pFont->Style; + DWORD d = FontStyle2Code(ts); + d = pIniFile->ReadInteger(pSect, "FontStyle", d); + ts = Code2FontStyle(d); + pFont->Style = ts; +} +//--------------------------------------------------------------------------- +void __fastcall SaveFontToInifile(TFont *pFont, LPCSTR pSect, TMemIniFile *pIniFile) +{ + if( pFont == NULL ) return; + + pIniFile->WriteString(pSect, "FontName", pFont->Name); + pIniFile->WriteInteger(pSect, "FontSet", pFont->Charset); + pIniFile->WriteInteger(pSect, "FontSize", pFont->Height); + TFontStyles ts = pFont->Style; + DWORD d = FontStyle2Code(ts); + pIniFile->WriteInteger(pSect, "FontStyle", d); +} +//--------------------------------------------------------------------------- +void __fastcall CItem::LoadFromInifile(LPCSTR pSect, LPCSTR pName) +{ + char fname[512]; + sprintf(fname, "%s%s", sys.m_BgnDir, pName); + TMemIniFile *pIniFile = new TMemIniFile(fname); + MultProc(); + m_ASize = pIniFile->ReadInteger(pSect, "AutoSize", m_ASize); + m_Align = pIniFile->ReadInteger(pSect, "Align", m_Align); + m_Grade = pIniFile->ReadInteger(pSect, "Grade", m_Grade); + m_Shadow = pIniFile->ReadInteger(pSect, "Shadow", m_Shadow); + m_Line = pIniFile->ReadInteger(pSect, "Line", m_Line); + m_Zero = pIniFile->ReadInteger(pSect, "Zero", 0); + m_3d = pIniFile->ReadInteger(pSect, "3D", m_3d); + m_OYW = pIniFile->ReadInteger(pSect, "OYW", m_OYW); + m_Rot = pIniFile->ReadInteger(pSect, "Rot", m_Rot); + int i; + for( i = 0; i < 4; i++ ){ + char bf[32]; + sprintf(bf, "ColG%u", i); + m_ColG[i].d = pIniFile->ReadInteger(pSect, bf, m_ColG[i].d); + sprintf(bf, "ColB%u", i); + m_ColB[i].d = pIniFile->ReadInteger(pSect, bf, m_ColB[i].d); + } + if( m_ASize ){ + m_OrgXW = m_OrgYW = -1; + m_TextXW = m_TextYW = -1; + } + else { + m_TextXW = pIniFile->ReadInteger(pSect, "Width", m_TextXW); + m_TextYW = pIniFile->ReadInteger(pSect, "Height", m_TextYW); + m_IniSize = 1; + } + AnsiString as, cs; + ::CrLf2Yen(cs, m_Text); + as = pIniFile->ReadString(pSect, "Text", cs); + ::Yen2CrLf(m_Text, as); + + if( pIniFile->ReadInteger(pSect, "Font", 0) ){ + if( m_pFont != NULL ) delete m_pFont; + m_pFont = new TFont; +#if 1 + LoadFontFromInifile(m_pFont, pSect, pIniFile); + UpdateFont(); +#else + m_pFont->Name = pIniFile->ReadString(pSect, "FontName", m_pFont->Name); + m_pFont->Charset = (BYTE)pIniFile->ReadInteger(pSect, "FontSet", m_pFont->Charset); + m_pFont->Height = pIniFile->ReadInteger(pSect, "FontSize", m_pFont->Height); + TFontStyles ts = m_pFont->Style; + DWORD d = FontStyle2Code(ts); + d = pIniFile->ReadInteger(pSect, "FontStyle", d); + m_fsCode = d; + ts = Code2FontStyle(d); + m_pFont->Style = ts; +#endif + } + delete pIniFile; +} +//--------------------------------------------------------------------------- +void __fastcall CItem::SaveToInifile(LPCSTR pSect, LPCSTR pName) +{ + char fname[512]; + sprintf(fname, "%s%s", sys.m_BgnDir, pName); + + TMemIniFile *pIniFile = new TMemIniFile(fname); + MultProc(); + try { + pIniFile->WriteInteger(pSect, "AutoSize", m_ASize); + pIniFile->WriteInteger(pSect, "Align", m_Align); + pIniFile->WriteInteger(pSect, "Grade", m_Grade); + pIniFile->WriteInteger(pSect, "Shadow", m_Shadow); + pIniFile->WriteInteger(pSect, "Line", m_Line); + pIniFile->WriteInteger(pSect, "Zero", m_Zero); + pIniFile->WriteInteger(pSect, "3D", m_3d); + pIniFile->WriteInteger(pSect, "OYW", GetTrueOYW()); + pIniFile->WriteInteger(pSect, "Rot", m_Rot); + int i; + for( i = 0; i < 4; i++ ){ + char bf[32]; + sprintf(bf, "ColG%u", i); + pIniFile->WriteInteger(pSect, bf, m_ColG[i].d); + sprintf(bf, "ColB%u", i); + pIniFile->WriteInteger(pSect, bf, m_ColB[i].d); + } + pIniFile->WriteInteger(pSect, "Width", m_TextXW); + pIniFile->WriteInteger(pSect, "Height", m_TextYW); + AnsiString cs; + ::CrLf2Yen(cs, m_Text); + pIniFile->WriteString(pSect, "Text", cs); + + pIniFile->WriteInteger(pSect, "Font", m_pFont != NULL ? 1 : 0); + if( m_pFont != NULL ){ +#if 1 + SaveFontToInifile(m_pFont, pSect, pIniFile); +#else + pIniFile->WriteString(pSect, "FontName", m_pFont->Name); + pIniFile->WriteInteger(pSect, "FontSet", m_pFont->Charset); + pIniFile->WriteInteger(pSect, "FontSize", m_pFont->Height); + TFontStyles ts = m_pFont->Style; + DWORD d = FontStyle2Code(ts); + pIniFile->WriteInteger(pSect, "FontStyle", d); +#endif + } + } + catch(...){ + } + pIniFile->UpdateFile(); + delete pIniFile; +} +//--------------------------------------------------------------------------- +void __fastcall CItem::DeleteInifile(LPCSTR pSect, LPCSTR pName) +{ + char fname[512]; + sprintf(fname, "%s%s", sys.m_BgnDir, pName); + + TMemIniFile *pIniFile = new TMemIniFile(fname); + MultProc(); + try { + pIniFile->EraseSection(pSect); + } + catch(...){ + } + pIniFile->UpdateFile(); + delete pIniFile; +} +//--------------------------------------------------------------------------- +DWORD __fastcall CItem::GetItemType(void) +{ + DWORD type = 0x00010002; // Active text as Overlay + if( m_ASize ){ + switch(m_Align){ + case 1: + type |= 0x00400000; // align center + break; + case 2: + type |= 0x00100000; // aling right-top + break; + case 3: + type |= m_Pos << 20; + type |= 0x00000010; + break; + default: + break; + } + } + return type; +} +//--------------------------------------------------------------------------- +void __fastcall CItem::SetPos(DWORD pos, DWORD size, DWORD tsize) +{ + int x = pos & 0x0000ffff; + int y = pos >> 16; + if( x & 0x00008000 ) x |= 0xffff8000; + if( y & 0x00008000 ) y |= 0xffff8000; + int xw = size & 0x0000ffff; + int yw = size >> 16; + int txw = tsize & 0x0000ffff; + int tyw = tsize >> 16; + + int xr = x + xw; + int yb = y + yw; + m_Pos = 0; + if( xr > (txw * 7/8) ){ + m_Pos |= 1; + } + else if( x > (txw / 8) ){ + m_Pos |= 4; + } + if( yb > (tyw * 6/8) ){ + m_Pos |= 2; + } + else if( y > (tyw * 2 / 8) ){ + m_Pos |= 8; + } +} +//--------------------------------------------------------------------------- +void __fastcall CItem::DeleteStorage(LPCBYTE pStorage) +{ + if( m_pMemStream != NULL ){ + ASSERT(pStorage == (LPCBYTE)m_pMemStream->Memory); + delete m_pMemStream; + m_pMemStream = NULL; + } +} +//--------------------------------------------------------------------------- +int __fastcall CItem::GetTrueOYW(void) +{ + int oyw = int((SHORT)m_OYW); + int oyh = m_OYW >> 16; + if( oyh > 0 ){ + int fw = oyh >> 8; + oyh &= 0x00ff; + oyw = oyw * fw / oyh; + } + return oyw; +} +//--------------------------------------------------------------------------- +void __fastcall CItem::Copy(CItem *sp) +{ + ASSERT(sp); + + DWORD size; + LPCBYTE ps = sp->CreateStorage(&size); + Create(ps, size); + sp->DeleteStorage(ps); + m_Back = sp->m_Back; + if( m_ASize ){ + m_OrgXW = m_OrgYW = -1; + m_TextXW = m_TextYW = -1; + } + else { + m_IniSize = 1; + } + m_Pos = sp->m_Pos; + m_Ex = sp->m_Ex; +} +//--------------------------------------------------------------------------- +DWORD __fastcall CItem::GetOrgSize(void) +{ + if(m_OrgXW >= 0){ + DWORD w = m_OrgXW; + DWORD h = m_OrgYW; + return (h << 16) + w; + } + else { + return (128 << 16) + 160; + } +} +//--------------------------------------------------------------------------- +void __fastcall CItem::SetFontSize(Graphics::TBitmap *pDest) +{ + ASSERT(m_OrgXW > 0); + ASSERT(m_OrgYW > 0); + if( (m_OrgXW <= 0) || (m_OrgYW <= 0) ) return; + + int size = m_pFont->Height; + if( m_OrgXW < pDest->Width ){ + size = size * pDest->Width / m_OrgXW; + if( size == m_pFont->Height ) size--; + } + else if( m_OrgYW < pDest->Height ){ + size = size * pDest->Height / m_OrgYW; + if( size == m_pFont->Height ) size--; + } + else if( m_OrgXW > pDest->Width ){ + size = size * pDest->Width / m_OrgXW; + if( size == m_pFont->Height ) size++; + } + else if( m_OrgYW > pDest->Height ){ + size = size * pDest->Height / m_OrgYW; + if( size == m_pFont->Height ) size++; + } + if( !size ) size = -1; + m_pFont->Height = size; +} +//--------------------------------------------------------------------------- +void __fastcall CItem::SetTextSize(Graphics::TBitmap *pDest) +{ + ASSERT(m_OrgXW > 0); + ASSERT(m_OrgYW > 0); + if( (m_OrgXW <= 0) || (m_OrgYW <= 0) ) return; + + if( m_OrgXW < pDest->Width ){ + m_TextXW = m_TextXW * pDest->Width / m_OrgXW; + } + else if( m_OrgYW < pDest->Height ){ + m_TextYW = m_TextYW * pDest->Height / m_OrgYW; + } + else if( m_OrgXW > pDest->Width ){ + m_TextXW = m_TextXW * pDest->Width / m_OrgXW; + } + else if( m_OrgYW > pDest->Height ){ + m_TextYW = m_TextYW * pDest->Height / m_OrgYW; + } +} +//--------------------------------------------------------------------------- +int __fastcall CItem::GetMaxWH(int &W, int &H, Graphics::TBitmap *pDest, LPCSTR pText) +{ + int lf = 1; + int n = 0; + W = H = 0; + char bf[1024]; + LPSTR t; + for( t = bf; 1; pText++ ){ + if( *pText != 0x0d ){ + if( (*pText == 0x0a) || !*pText ){ + if( lf && *pText ){ + n++; + } + *t = 0; + if( bf[0] ){ + DWORD wh = ::GetTabbedTextExtent(pDest->Canvas->Handle, bf, strlen(bf), 0, NULL); + int w = wh & 0x0000ffff; + int h = wh >> 16; + if( H < h ) H = h; + if( W < w ) W = w; + } + if( !*pText ) break; + lf = 1; + t = bf; + } + else { + if( lf ){ + lf = 0; + n++; + } + *t++ = *pText; + } + } + } + return n; +} +//--------------------------------------------------------------------------- +UINT __fastcall CItem::GetPosFormat(void) +{ + UINT wFormat; + switch(m_Align){ + case 1: + wFormat = DT_CENTER; + break; + case 2: + wFormat = DT_RIGHT; + break; + case 3: + if( m_Pos & 4 ){ + wFormat = DT_CENTER; + } + else { + wFormat = (m_Pos & 1) ? DT_RIGHT : DT_LEFT; + } + break; + default: + wFormat = DT_LEFT; + break; + } + return wFormat; +} +//--------------------------------------------------------------------------- +UINT __fastcall CItem::GetDrawFormat(void) +{ + UINT wFormat = DT_NOPREFIX|DT_NOCLIP|DT_EXPANDTABS; + if( m_Rot ){ + wFormat |= DT_LEFT; + } + else { + wFormat |= GetPosFormat(); + } + if( !m_ASize ) wFormat |= DT_WORDBREAK; + return wFormat; +} +//--------------------------------------------------------------------------- +void __fastcall CItem::GetFont(LOGFONT *pLogfont) +{ + memset(pLogfont, 0, sizeof(LOGFONT)); + pLogfont->lfHeight = m_pFont->Height; + pLogfont->lfWidth = 0; + pLogfont->lfEscapement = m_Rot * 10; + pLogfont->lfOrientation = m_Rot * 10; + TFontStyles ts = m_pFont->Style; + int fsw = FontStyle2Code(ts); + pLogfont->lfWeight = fsw & FSBOLD ? 700 : 400; + pLogfont->lfItalic = BYTE(fsw & FSITALIC ? TRUE : FALSE); + pLogfont->lfUnderline = BYTE(fsw & FSUNDERLINE ? TRUE : FALSE); + pLogfont->lfStrikeOut = BYTE(fsw & FSSTRIKEOUT ? TRUE : FALSE); + pLogfont->lfCharSet = m_pFont->Charset; + pLogfont->lfOutPrecision = OUT_CHARACTER_PRECIS; + pLogfont->lfClipPrecision = CLIP_DEFAULT_PRECIS; + pLogfont->lfQuality = NONANTIALIASED_QUALITY; + pLogfont->lfPitchAndFamily = DEFAULT_PITCH; + strcpy(pLogfont->lfFaceName, m_pFont->Name.c_str()); +} +//--------------------------------------------------------------------------- +void __fastcall CItem::SetFont(LOGFONT *pLogfont) +{ + if( m_pFont == NULL ) m_pFont = new TFont; + m_pFont->Name = pLogfont->lfFaceName; + m_pFont->Charset = pLogfont->lfCharSet; + if( pLogfont->lfHeight ){ + m_pFont->Height = pLogfont->lfHeight; + } + else { + m_pFont->Size = pLogfont->lfWidth; + } + DWORD d = 0; + if( pLogfont->lfWeight > 600 ) d |= FSBOLD; + if( pLogfont->lfItalic ) d |= FSITALIC; + if( pLogfont->lfUnderline ) d |= FSUNDERLINE; + if( pLogfont->lfStrikeOut ) d |= FSSTRIKEOUT; + m_fsCode = d; + TFontStyles ts = Code2FontStyle(d); + m_pFont->Style = ts; + m_Rot = pLogfont->lfEscapement / 10; +} +//--------------------------------------------------------------------------- +void __fastcall CItem::DrawText(RECT rc, int xoff, int yoff, Graphics::TBitmap *pDest, LPCSTR pText, UCOL ucol) +{ + if( m_Rot || (m_Ex & DISFONTSMOOTHING) ){ + LOGFONT lf; +#if 1 + GetFont(&lf); +#else + memset(&lf, 0, sizeof(lf)); + lf.lfHeight = m_pFont->Height; + lf.lfWidth = 0; + lf.lfEscapement = m_Rot * 10; + lf.lfOrientation = m_Rot * 10; + TFontStyles ts = m_pFont->Style; + int fsw = FontStyle2Code(ts); + lf.lfWeight = fsw & FSBOLD ? 700 : 400; + lf.lfItalic = BYTE(fsw & FSITALIC ? TRUE : FALSE); + lf.lfUnderline = BYTE(fsw & FSUNDERLINE ? TRUE : FALSE); + lf.lfStrikeOut = BYTE(fsw & FSSTRIKEOUT ? TRUE : FALSE); + lf.lfCharSet = m_pFont->Charset; + lf.lfOutPrecision = OUT_CHARACTER_PRECIS; + lf.lfClipPrecision = CLIP_DEFAULT_PRECIS; + lf.lfQuality = NONANTIALIASED_QUALITY; + lf.lfPitchAndFamily = DEFAULT_PITCH; + strcpy(lf.lfFaceName, m_pFont->Name.c_str()); +#endif + pDest->Canvas->Font->Handle = CreateFontIndirect(&lf); + } + else { + pDest->Canvas->Font = m_pFont; + } + pDest->Canvas->Font->Color = ucol.c; + + if( m_OYWC || m_Rot ){ + TStringList *pList = new TStringList; + pList->Text = pText; + UINT wFormat = GetPosFormat(); + int xw = rc.right - rc.left; + for( int i = 0; i < pList->Count; i++ ){ + RECT trc; + trc = rc; + int txw = pDest->Canvas->TextWidth(pList->Strings[i].c_str()); + if( m_Rot ){ // 回転時の位置補正 + int x; + switch(wFormat){ + case DT_CENTER: + x = (xw - txw)/2; + trc.left += x * m_CosX; + trc.right += x * m_CosX; + trc.top -= x * m_SinX; + break; + case DT_RIGHT: + x = xw - txw; + trc.left += x * m_CosX; + trc.right += x * m_CosX; + trc.top -= x * m_SinX; + break; + } + } + DrawText_(trc, xoff, yoff, pDest, pList->Strings[i].c_str()); + int N = m_ASize ? 1 : ((txw - 1)/ xw) + 1; + if( m_Rot ){ + rc.left += (m_FW + m_OYWC) * N * m_SinX; + rc.right += (m_FW + m_OYWC) * N * m_SinX; + rc.top += (m_FW + m_OYWC) * N * m_CosX; + } + else { + rc.top += (m_FW + m_OYWC) * N; + } + } + delete pList; + } + else { + DrawText_(rc, xoff, yoff, pDest, pText); + } +} +//--------------------------------------------------------------------------- +void __fastcall CItem::DrawText_(RECT rc, int xoff, int yoff, Graphics::TBitmap *pDest, LPCSTR pText) +{ + rc.left += xoff; rc.top += yoff; + rc.right += xoff; rc.bottom += yoff; + HDC hdc = pDest->Canvas->Handle; + ::SetBkMode(hdc, TRANSPARENT); + if( m_ASize && (m_Row <= 1) ){ + pDest->Canvas->TextOut(rc.left, rc.top, pText); + } + else { + ::DrawText(hdc, pText, strlen(pText), &rc, GetDrawFormat()); + } +} +//--------------------------------------------------------------------------- +void __fastcall CItem::DrawTrans(Graphics::TBitmap *pDest, int x, int y, Graphics::TBitmap *pSrc) +{ + Graphics::TBitmap *pbmp = pSrc; + if( sys.m_BitPixel == 16 ){ + pbmp = new Graphics::TBitmap; + pbmp->Width = pSrc->Width; + pbmp->Height = pSrc->Height; + pbmp->Canvas->Draw(0, 0, pSrc); + } + pbmp->Transparent = TRUE; + pbmp->TransparentMode = tmAuto; + pDest->Canvas->Draw(x, y, pbmp); + if( pbmp != pSrc ) delete pbmp; +} +//--------------------------------------------------------------------------- +LPBYTE __fastcall CItem::CreateTable(LPBYTE* &pAdr, Graphics::TBitmap *pDest) +{ + int XW = pDest->Width; + int YW = pDest->Height; + LPBYTE pTbl = new BYTE[XW*YW]; + memset(pTbl, 0, XW*YW); + LPBYTE wp = pTbl; + int x, y; + + pAdr = new BYTE*[YW]; + BYTE br = m_cBack.b.r; + BYTE bg = m_cBack.b.g; + BYTE bb = m_cBack.b.b; + for( y = 0; y < YW; y++ ){ + LPBYTE p = (LPBYTE)pDest->ScanLine[y]; + pAdr[y] = p; + for( x = 0; x < XW; x++, wp++, p+=3 ){ + if( (bb != *p) || (bg != *(p+1)) || (br != *(p+2)) ){ + *wp = 1; + } + } + } + return pTbl; +} +//--------------------------------------------------------------------------- +int __fastcall CItem::EditDialog(HWND hWnd) +{ +#if UseHWND + TTextDlgBox *pBox = new TTextDlgBox(hWnd); +#else + TTextDlgBox *pBox = new TTextDlgBox(NULL); +#endif + if( pBox == NULL ) return FALSE; + + int r = pBox->Execute(this); + delete pBox; + if( r == TRUE ) UpdateDefault(); + return r; +} +//--------------------------------------------------------------------------- +int __fastcall CItem::FontDialog(HWND hWnd) +{ + if( m_pFont == NULL ) m_pFont = new TFont; + TFontDialog *pDlg = new TFontDialog(NULL); + if( pDlg == NULL ) return FALSE; + + ASSERT(m_pFont); + pDlg->Font->Assign(m_pFont); + pDlg->Font->Color = m_ColG[0].c; + MultProc(); + int r = pDlg->Execute(); + MultProc(); + if( r == TRUE ){ + m_pFont->Assign(pDlg->Font); + m_ColG[0].c = pDlg->Font->Color; + UpdateFont(); + UpdateDefault(); + } + delete pDlg; + return r; +} +//--------------------------------------------------------------------------- +void __fastcall CItem::UpdateFont(void) +{ + if( m_pFont == NULL ) return; + + TFontStyles ts = m_pFont->Style; + m_fsCode = FontStyle2Code(ts); +} +//--------------------------------------------------------------------------- +void __fastcall CItem::Draw3D(RECT &rc, Graphics::TBitmap *pDest, LPCSTR pText, UCOL cl[2]) +{ + int xm = m_3d & 0x00ff; + int ym = (m_3d >> 8) & 0x00ff; + if( xm & 0x0080 ) xm |= 0xffffff80; + if( ym & 0x0080 ) ym |= 0xffffff80; + if( m_Rot ){ + int x = xm * m_CosX + ym * m_SinX; + int y = -xm * m_SinX + ym * m_CosX; + xm = x; + ym = y; + } + + int max = ABS(xm) > ABS(ym) ? ABS(xm) : ABS(ym); + for( int i = max; i > 0; i-- ){ + int x = xm * i / max; + int y = ym * i / max; + DrawText(rc, x, y, pDest, pText, GetGrade2(cl, i, max)); + } +} +//--------------------------------------------------------------------------- +Graphics::TBitmap* __fastcall CItem::DrawExt(Graphics::TBitmap *pDest, RECT &rc, LPCSTR pText) +{ + MultProc(); + int xw = pDest->Width; + int yw = pDest->Height; + LPBYTE pTbl = NULL; + BYTE **pAdr = NULL; + if( m_Grade || (m_Shadow == 2) ) pTbl = CreateTable(pAdr, pDest); + + LPBYTE wp, p; + if( m_Grade ){ + MultProc(); + ASSERT(pTbl); + RECT mc; + mc.left = rc.right; mc.top = rc.bottom; + mc.right = rc.left; mc.bottom = rc.top; + wp = pTbl; + int x, y; + for( y = 0; y < yw; y++ ){ + for( x = 0; x < xw; x++, wp++ ){ + if( *wp ){ + if( mc.left > x ) mc.left = x; + if( mc.right < x ) mc.right = x; + if( mc.top > y ) mc.top = y; + if( mc.bottom < y ) mc.bottom = y; + } + } + } + int bw = mc.right - mc.left + 1; + int bh = mc.bottom - mc.top + 1; + int bd = sqrt(bw*bw + bh*bh); + UCOL c; + for( y = mc.top; y <= mc.bottom; y++ ){ +// p = (LPBYTE)pDest->ScanLine[y]; + p = pAdr[y]; + wp = &pTbl[y*xw]; + for( x = 0; x < xw; x++, wp++, p+=3 ){ + if( *wp ){ + int xx = x - mc.left; + int yy = y - mc.top; + switch(m_Grade){ + case 1: + c = GetGrade4(m_ColG, xx, bw); + break; + case 2: + c = GetGrade4(m_ColG, yy, bh); + break; + case 3: + c = GetGrade4(m_ColG, sqrt(xx*xx + yy*yy), bd); + break; + } + *p++ = c.b.b; + *p++ = c.b.g; + *p = c.b.r; + p -= 2; + } + } + } + } + MultProc(); + switch(m_Shadow){ + case 1: + { + Graphics::TBitmap* pbmp = CreateBitmap(xw, yw); + FillBitmap(pbmp, m_cBack); + if( m_3d & 0x00010000 ){ + Draw3D(rc, pbmp, pText, &m_ColB[1]); + } + else { + for( int i = m_Line - 1; i >= 0; i-- ){ + DrawText(rc, i+1, i+1, pbmp, pText, m_ColB[0]); + } + } + DrawTrans(pbmp, 0, 0, pDest); + delete pDest; + pDest = pbmp; + } + break; + case 2: + { + ASSERT(pTbl); + if( m_3d & 0x00010000 ){ + Graphics::TBitmap* pbmp = CreateBitmap(xw, yw); + FillBitmap(pbmp, m_cBack); + Draw3D(rc, pbmp, pText, &m_ColB[1]); + DrawTrans(pbmp, 0, 0, pDest); + delete pDest; + pDest = pbmp; + for( int y = 0; y < yw; y++ ) pAdr[y] = (LPBYTE)pDest->ScanLine[y]; + } + int f; + int x, y; + for( y = 0; y < yw; y++ ){ + wp = &pTbl[y*xw]; +// p = (LPBYTE)pDest->ScanLine[y]; + p = pAdr[y]; + f = 0; + for( x = 0; x < xw; x++, wp++, p+=3 ){ + if( *wp ){ + if( !m_Grade ){ + *p++ = m_ColG[0].b.b; + *p++ = m_ColG[0].b.g; + *p = m_ColG[0].b.r; + p -= 2; + } + f = m_Line; + } + else if( f ){ + f--; + *p++ = m_ColB[0].b.b; + *p++ = m_ColB[0].b.g; + *p = m_ColB[0].b.r; + p -= 2; + *wp = BYTE((m_Line >= 2) ? 1 : f); +// *wp = BYTE(f); + } + } + f = 0; + wp--; + p -= 3; + x--; + for( ; x >= 0; x--, wp--, p-=3 ){ + if( *wp ){ + f = m_Line; + } + else if( f ){ + f--; + *p++ = m_ColB[0].b.b; + *p++ = m_ColB[0].b.g; + *p = m_ColB[0].b.r; + p -= 2; + *wp = BYTE((m_Line >= 2) ? 1 : f); +// *wp = BYTE(f); + } + } + + } + int ax = 0; + for( x = 0; x < xw; x++, ax+=3 ){ + wp = &pTbl[x]; + f = 0; + for( y = 0; y < yw; y++, wp += xw ){ + if( *wp ){ + f = m_Line; + } + else if( f ){ + f--; +// p = (LPBYTE)pDest->ScanLine[y]; + p = pAdr[y]; + p += ax; + *p++ = m_ColB[0].b.b; + *p++ = m_ColB[0].b.g; + *p = m_ColB[0].b.r; + *wp = BYTE((m_Line >= 2) ? 1 : f); +// *wp = BYTE(f); + } + } + f = 0; + y--; + wp -= xw; + for( ; y >= 0; y--, wp -= xw ){ + if( *wp ){ + f = m_Line; + } + else if( f ){ + f--; +// p = (LPBYTE)pDest->ScanLine[y]; + p = pAdr[y]; + p += ax; + *p++ = m_ColB[0].b.b; + *p++ = m_ColB[0].b.g; + *p = m_ColB[0].b.r; + } + } + } + } + break; + case 3: + { + Graphics::TBitmap* pbmp = CreateBitmap(xw, yw); + FillBitmap(pbmp, m_cBack); + if( m_3d & 0x00010000 ){ + rc.left++; rc.right++; + rc.top++; rc.bottom++; + int xm = m_3d & 0x00ff; + int ym = (m_3d >> 8) & 0x00ff; + Draw3D(rc, pbmp, pText, &m_ColB[1]); + DrawText(rc, (xm & 0x80) ? 1 : -1, (ym & 0x80) ? 1 : -1, pbmp, pText, m_ColB[0]); + } + else { + for( int i = m_Line - 1; i >= 0; i-- ){ + DrawText(rc, i+2, i+2, pbmp, pText, m_ColB[0]); + } + DrawText(rc, 0, 0, pbmp, pText, m_ColB[1]); + } + DrawTrans(pbmp, 1, 1, pDest); + delete pDest; + pDest = pbmp; + } + break; + default: + break; + } + if( pAdr != NULL ) delete pAdr; + if( pTbl != NULL ) delete pTbl; + +#if ADJUST_MINIMIZED + pTbl = CreateTable(pDest); + rc.left = rc.right; rc.right = 0; + rc.top = rc.bottom; rc.bottom = 0; + wp = pTbl; + int x, y; + for( y = 0; y < yw; y++ ){ + for( x = 0; x < xw; x++, wp++ ){ + if( *wp ){ + if( rc.left > x ) rc.left = x; + if( rc.right < x ) rc.right = x; + if( rc.top > y ) rc.top = y; + if( rc.bottom < y ) rc.bottom = y; + } + } + } + delete pTbl; +#endif + return pDest; +} +//--------------------------------------------------------------------------- +void __fastcall CItem::ConvChar(LPSTR pStr) +{ + char bf[8192]; + LPCSTR p; + LPSTR t = bf; + for( p = pStr; *p; p++ ){ + if( (_mbsbtype((const unsigned char *)p, 0) == _MBC_LEAD) && *(p+1) ){ + *t++ = *p++; + *t++ = *p; + } + else if( (*p == '\\') && (*(p+1)=='x') ){ + p+=2; + *t++ = (char)htoin(p, 2); + p++; + } + else if( (*p == '\\') && (*(p+1)=='$') ){ + p+=2; + *t++ = (char)htoin(p, 2); + p+=2; + *t++ = (char)htoin(p, 2); + p++; + } + else if( (*p == '\t') && (m_Align) ){ + *t++ = ' '; + } + else { + *t++ = *p; + } + } + *t = 0; + strcpy(pStr, bf); +} +//--------------------------------------------------------------------------- +Graphics::TBitmap* __fastcall CItem::Draw(Graphics::TBitmap *pDest, LPCSTR pText) +{ + if( (pText == NULL) || !*pText ) return pDest; + + m_Back.c = pDest->Canvas->Pixels[0][0]; + m_Back.d &= 0x00ffffff; + m_cBack = m_Back; + if( m_pFont == NULL ){ + m_pFont = new TFont(); + m_pFont->Assign(pDest->Canvas->Font); + m_pFont->Size = 18; + UpdateFont(); + } + else if( m_OrgXW >= 0 ){ + if( m_ASize ) SetFontSize(pDest); + } + SetMBCP(m_pFont->Charset); + AnsiString as = pText; + ConvChar(as.c_str()); + pText = as.c_str(); + + LPCSTR pOrgText = pText; + if( m_Zero ){ + pText = ZeroConv(pText, m_pFont->Charset); + } + + pDest->Canvas->Font = m_pFont; + m_FW = pDest->Canvas->TextHeight(pText); + + m_OYWC = int((short)m_OYW); + if( m_OYW ){ + int oyh = m_OYW >> 16; + if( oyh <= 0 ){ // 最初のフォントサイズの設定 + m_OYW &= 0x0000ffff; + m_OYW |= (m_FW << 24)|(m_FW << 16); + } + else { // フォントサイズによる換算 + m_OYW &= 0x00ffffff; + m_OYW |= m_FW << 24; + oyh &= 0x00ff; + if( oyh ) m_OYWC = m_OYWC * m_FW / oyh; + } + } + int xw, yw; + if( m_ASize ){ + int n = GetMaxWH(xw, yw, pDest, pText); + m_FW = yw; + m_Row = n; + if( m_OYWC && n ){ + yw = (yw + m_OYWC) * (n - 1) + yw; + if( yw < m_FW ) yw = m_FW; + } + else { + yw *= n; + } + if( m_fsCode & FSITALIC ){ +// xw += yw / 12; + xw += m_FW / 4; + } + } + else if( m_IniSize || (m_OrgXW < 0) ){ + m_IniSize = 0; + if( m_TextXW > 0 ){ + xw = m_TextXW; + yw = m_TextYW; + } + else { + xw = pDest->Width; + yw = pDest->Height; + } + } + else { + SetTextSize(pDest); + xw = m_TextXW; + yw = m_TextYW; + } + m_TextXW = xw; + m_TextYW = yw; + + if( m_Shadow && (m_cBack.d == m_ColB[0].d) ){ + m_cBack = GetUniqueColor(m_cBack); + } + if( m_cBack.d == m_ColG[0].d ){ + m_cBack = GetUniqueColor(m_cBack); + } + + MultProc(); + + RECT rc; + rc.left = rc.top = 0; + rc.right = xw; + rc.bottom = yw; + + if( m_Rot ){ + if( ABS(m_Rot - 90) < 10 ) rc.right += m_FW/6; + if( ABS(m_Rot - 180) < 10 ) rc.right += m_FW/6; + if( ABS(m_Rot - 270) < 10 ) rc.right += m_FW/6; +// rc.right += m_FW/2; +// rc.bottom += m_FW/2; + double s = 2 * PI * m_Rot / 360; + m_CosX = cos(s); + m_SinX = sin(s); + int xc = rc.right/2; + int yc = rc.bottom/2; + POINT N[5]; + N[0].x = -xc; + N[0].y = -yc; + N[1].x = xc; + N[1].y = -yc; + N[2].x = xc; + N[2].y = yc; + N[3].x = -xc; + N[3].y = yc; + N[4].x = rc.left - xc; + N[4].y = rc.top - yc; + int i; + for( i = 0; i < 5; i++ ){ + int x = N[i].x * m_CosX + N[i].y * m_SinX; + int y = -N[i].x * m_SinX + N[i].y * m_CosX; + N[i].x = x + xc; N[i].y = y + yc; + } + int x1, x2, y1, y2; + x1 = x2 = N[0].x; y1 = y2 = N[0].y; + for( i = 1; i < 4; i++ ){ + if( x1 > N[i].x ) x1 = N[i].x; + if( x2 < N[i].x ) x2 = N[i].x; + if( y1 > N[i].y ) y1 = N[i].y; + if( y2 < N[i].y ) y2 = N[i].y; + } + int xo = N[4].x - x1; + int yo = N[4].y - y1; + if( ABS(m_Rot - 90) < 10 ) yo += m_FW/12; + if( ABS(m_Rot - 180) < 10 ) xo += m_FW/12; +// if( ABS(m_Rot - 270) < 10 ) yo += m_FW/12; + rc.left += xo; rc.right += xo; + rc.top += yo; rc.bottom += yo; + xw = x2 - x1 + 1; yw = y2 - y1 + 1; + } + + if( m_3d & 0x00010000 ){ + int xm = m_3d & 0x00ff; + int ym = (m_3d >> 8) & 0x00ff; + if( xm & 0x0080 ) xm |= 0xffffff80; + if( ym & 0x0080 ) ym |= 0xffffff80; + if( m_Rot ){ + int x = xm * m_CosX + ym * m_SinX; + int y = -xm * m_SinX + ym * m_CosX; + xm = x; + ym = y; + } + if( xm < 0 ){ + rc.left -= xm; + rc.right -= xm; + } + if( ym < 0 ){ + rc.top -= ym; + rc.bottom -= ym; + } + xw += ABS(xm); + yw += ABS(ym); + } + + switch(m_Shadow){ + case 1: + xw += m_Line; + yw += m_Line; + break; + case 2: + rc.left += m_Line; + rc.right += m_Line; + rc.top += m_Line; + rc.bottom += m_Line; + xw += m_Line*2; + yw += m_Line*2; + break; + case 3: + xw += m_Line*2; + yw += m_Line*2; + break; + } + + if( m_fsCode & FSITALIC ){ // イタリックの場合の位置補正 + int oxw = 0; + int oyw = 0; + switch(GetPosFormat()){ + case DT_CENTER: + oxw = m_FW / 8; + if( m_Rot ){ + oxw *= m_CosX; + } + break; + case DT_RIGHT: + oxw = m_FW / 4; + if( m_Rot ){ + oxw *= m_CosX; + oyw = -(m_FW / 4) * m_SinX; + } + break; + default: + break; + } + rc.left -= oxw; + rc.right -= oxw; + rc.top -= oyw; + rc.bottom -= oyw; + } + + Graphics::TBitmap *pBmp = pDest; + if( (pDest->Width != xw) || (pDest->Height != yw) ){ + pBmp = CreateBitmap(xw, yw); + FillBitmap(pBmp, m_cBack); + } + else if( m_Back.d != m_cBack.d ){ + FillBitmap(pBmp, m_cBack); + } + + MultProc(); + UCOL col = m_ColG[0]; + if( m_Draft && (col.d == m_Back.d) ) col.d = col.d ^ 0x00ffffff; + DrawText(rc, 0, 0, pBmp, pText, col); + Graphics::TBitmap *pNew = pBmp; + if( !m_Draft ){ + pNew = DrawExt(pBmp, rc, pText); +#if ADJUST_MINIMIZED + if( rc.left || rc.top ){ + xw = rc.right - rc.left + 1; + yw = rc.bottom - rc.top + 1; + Graphics::TBitmap *pbmp = CreateBitmap(xw, yw); + pbmp->Canvas->Draw(-rc.left, -rc.top, pNew); + delete pNew; + pNew = pbmp; + } +#endif + } + m_OrgXW = xw; + m_OrgYW = yw; + if( pBmp != pDest ) delete pDest; + pDest = pNew; + if( pOrgText != pText ) delete pText; + + // set transparent color to (0,0) for overlay + LPBYTE p = (LPBYTE)pDest->ScanLine[0]; + ASSERT(p); + *p++ = m_cBack.b.b; + *p++ = m_cBack.b.g; + *p = m_cBack.b.r; + + MultProc(); + return pDest; +} + + + \ No newline at end of file diff --git a/CItems/TEXTBOX/Comlib.h b/CItems/TEXTBOX/Comlib.h new file mode 100644 index 0000000..f833dec --- /dev/null +++ b/CItems/TEXTBOX/Comlib.h @@ -0,0 +1,234 @@ +#ifndef ComLibH +#define ComLibH +#include +#include +#include +#include +#include +#include +#include + +#define UseHWND 0 +#define ADJUST_MINIMIZED FALSE + +#define NDEBUG // Remove this symbol, if you would like to do debug +#include +#define ASSERT(c) assert(c) + +#define ABS(c) (((c)<0)?(-(c)):(c)) +#define PI 3.1415926535897932384626433832795 + +typedef const BYTE* LPCBYTE; +typedef double* LPDOUBLE; +typedef const double* LPCDOUBLE; +typedef union { + struct { + BYTE r; + BYTE g; + BYTE b; + BYTE s; + }b; + DWORD d; + TColor c; +}UCOL; + +#define VER "TextBox Version 1.09" +#define AUT "(C) JE3HHT 2002-2003." +#define TTL "MMSSTV custom item" +#define TTLJ "MMSSTV カスタムアイテム" // Japanese code + +#define ININAME "TextBox.ini" + +#define FSBOLD 1 +#define FSITALIC 2 +#define FSUNDERLINE 4 +#define FSSTRIKEOUT 8 + +#define DISFONTSMOOTHING 0x00000001 + +// These prototypes are the functions in the MMSSTV. +// ---- Refer to the comment of the mcmFunc() --- +typedef HBITMAP (__cdecl *mmLoadImageMenu)(int sw, int xw, int yw); +typedef HBITMAP (__cdecl *mmLoadImage)(LPCSTR pName); +typedef HBITMAP (__cdecl *mmLoadHistImage)(void); +typedef int (__cdecl *mmSaveImageMenu)(HBITMAP hb, LPCSTR pName, LPCSTR pFolder); +typedef int (__cdecl *mmSaveImage)(HBITMAP hb, LPCSTR pName); +typedef HBITMAP (__cdecl *mmPasteImage)(int sw, int xw, int yw); +typedef int (__cdecl *mmGetMacKey)(LPSTR pDest, int cbDest); +typedef int (__cdecl *mmConvMac)(LPSTR pDest, LPCSTR pSrc, int cbDest); +typedef HBITMAP (__cdecl *mmCreateDIB)(int xw, int yw); +typedef void (__cdecl *mmMultProc)(void); +typedef void (__cdecl *mmMultProcA)(void); +typedef int (__cdecl *mmColorComp)(LPDWORD pCol); + +void __fastcall InitSys(void); +void __fastcall MultProc(void); +char __fastcall LastC(LPCSTR p); +void __fastcall SetCurDir(LPSTR t, int size); +void __fastcall SetDirName(LPSTR t, LPCSTR pName); +void __fastcall Yen2CrLf(AnsiString &ws, AnsiString cs); +void __fastcall CrLf2Yen(AnsiString &ws, AnsiString cs); +void __fastcall LoadStringsFromIniFile(TStrings *pList, LPCSTR pSect, LPCSTR pName, int msg); +void __fastcall SaveStringsToIniFile(TStrings *pList, LPCSTR pSect, LPCSTR pName, int msg); +void __fastcall InitCustomColor(TColorDialog *tp); +void __fastcall AddCustomColor(TColorDialog *tp, TColor col); +Graphics::TBitmap * __fastcall CreateBitmap(int xw, int yw); +void __fastcall FillBitmap(Graphics::TBitmap *pDest, UCOL ucol); +void __fastcall CopyBitmap(Graphics::TBitmap *pDest, Graphics::TBitmap *pSrc); +void __fastcall DrawBitmap(TPaintBox *pBox, Graphics::TBitmap *pBitmap); + +int __fastcall IsFile(LPCSTR pName); +void __fastcall SetMBCP(BYTE charset); +void __fastcall AddStyle(AnsiString &as, BYTE charset, DWORD style); +void __fastcall LoadFontFromInifile(TFont *pFont, LPCSTR pSect, TMemIniFile *pIniFile); +void __fastcall SaveFontToInifile(TFont *pFont, LPCSTR pSect, TMemIniFile *pIniFile); + +class CWaitCursor +{ +private: + TCursor sv; +public: + CWaitCursor(BOOL sw); + CWaitCursor(); + ~CWaitCursor(); + void Delete(void); + void Wait(void); +}; + +int FontStyle2Code(TFontStyles style); +TFontStyles Code2FontStyle(int code); + +class CItem +{ +public: + int m_Ver; + int m_ASize; + int m_Align; + int m_Grade; + int m_Shadow; + int m_Line; + int m_Zero; + DWORD m_3d; + AnsiString m_Text; + TFont *m_pFont; + UCOL m_ColG[4]; + UCOL m_ColB[4]; + UCOL m_Back; + int m_OrgXW; + int m_OrgYW; + int m_TextXW; + int m_TextYW; + int m_OYW; + int m_Rot; +private: + UCOL m_cBack; + int m_Draft; + int m_fsCode; + int m_IniSize; + int m_Pos; + DWORD m_Ex; + int m_FW; + double m_SinX; + double m_CosX; + int m_OYWC; + int m_Row; + TMemoryStream *m_pMemStream; +private: + void __fastcall LoadDefault(void); + void __fastcall UpdateDefault(void); + void __fastcall SetFontSize(Graphics::TBitmap *pDest); + void __fastcall SetTextSize(Graphics::TBitmap *pDest); + int __fastcall GetMaxWH(int &W, int &H, Graphics::TBitmap *pDest, LPCSTR pText); + UINT __fastcall GetPosFormat(void); + UINT __fastcall GetDrawFormat(void); + void __fastcall DrawText(RECT rc, int xoff, int yoff, Graphics::TBitmap *pDest, LPCSTR pText, UCOL ucol); + void __fastcall DrawText_(RECT rc, int xoff, int yoff, Graphics::TBitmap *pDest, LPCSTR pText); + void __fastcall DrawTrans(Graphics::TBitmap *pDest, int x, int y, Graphics::TBitmap *pSrc); + LPBYTE __fastcall CreateTable(LPBYTE* &pAdr, Graphics::TBitmap *pDest); + void __fastcall Draw3D(RECT &rc, Graphics::TBitmap *pDest, LPCSTR pText, UCOL cl[2]); + Graphics::TBitmap* __fastcall DrawExt(Graphics::TBitmap *pDest, RECT &rc, LPCSTR pText); + + void __fastcall ConvChar(LPSTR pStr); +protected: +public: + __fastcall CItem(void); + __fastcall ~CItem(); + void __fastcall Create(LPCBYTE ps, DWORD size); + DWORD __fastcall GetItemType(void); + LPCBYTE __fastcall CreateStorage(LPDWORD psize); + void __fastcall DeleteStorage(LPCBYTE pStorage); + void __fastcall Copy(CItem *sp); + int __fastcall EditDialog(HWND hWnd); + int __fastcall FontDialog(HWND hWnd); + DWORD __fastcall GetOrgSize(void); + void __fastcall SetPos(DWORD pos, DWORD size, DWORD tsize); + inline LPCSTR __fastcall GetText(void){ + return m_Text.c_str(); + }; + inline void __fastcall SetDraft(int draft){ + m_Draft = draft; + }; + void __fastcall UpdateFont(void); + void __fastcall LoadFromInifile(LPCSTR pSect, LPCSTR pName); + void __fastcall SaveToInifile(LPCSTR pSect, LPCSTR pName); + void __fastcall DeleteInifile(LPCSTR pSect, LPCSTR pName); + Graphics::TBitmap* __fastcall Draw(Graphics::TBitmap *pDest, LPCSTR pText); + inline void __fastcall SetEx(DWORD ex){ m_Ex = ex;}; + inline DWORD __fastcall GetEx(void){return m_Ex;}; + inline void __fastcall SetPos(int pos){ m_Pos = pos;}; + inline DWORD __fastcall GetPos(void){return m_Pos;}; + int __fastcall GetTrueOYW(void); + + void __fastcall GetFont(LOGFONT *pLogfont); + void __fastcall SetFont(LOGFONT *pLogfont); + +}; + +typedef struct { + AnsiString m_Name; + int m_Height; + BYTE m_Charset; + DWORD m_Style; +}FONTDATA; + +enum { + fmJA, + fmHL, + fmJOHAB, + fmBV, + fmBY, + fmEND, +}; +typedef struct { + DWORD m_dwVersion; + int m_WinNT; + UINT m_CodePage; + int m_MsgEng; + int m_BitPixel; + mmGetMacKey m_fGetMacKey; + mmConvMac m_fConvMac; + mmMultProc m_fMultProc; + mmColorComp m_fColorComp; + DWORD m_DefStgSize; + LPBYTE m_pDefStg; + TStringList *m_pTextList; + TStringList *m_pStyleList; + char m_BgnDir[512]; + + AnsiString m_Msg; + TStringList *m_pFontList; + + Graphics::TBitmap *m_pBitmapTemp; + + int m_CodeLeft; + int m_CodeTop; + int m_CodeOut; + + BOOL m_fEudc; + AnsiString m_Eudc; + + BOOL m_fFontFam; + BOOL m_tFontFam[fmEND]; +}SYS; +extern SYS sys; +#endif diff --git a/CItems/TEXTBOX/Item.ico b/CItems/TEXTBOX/Item.ico new file mode 100644 index 0000000..b709881 Binary files /dev/null and b/CItems/TEXTBOX/Item.ico differ diff --git a/CItems/TEXTBOX/TextBox.bpr b/CItems/TEXTBOX/TextBox.bpr new file mode 100644 index 0000000..33d9e3d --- /dev/null +++ b/CItems/TEXTBOX/TextBox.bpr @@ -0,0 +1,184 @@ +# --------------------------------------------------------------------------- +!if !$d(BCB) +BCB = $(MAKEDIR)\.. +!endif + +# --------------------------------------------------------------------------- +# IDE セクション +# --------------------------------------------------------------------------- +# プロジェクトメイクファイルの以下のセクションは、IDE によって管理されます。 +# このセクションを変更する場合は、できるだけ IDE を使用するようにして +# ください。 +# --------------------------------------------------------------------------- + +VERSION = BCB.03 +# --------------------------------------------------------------------------- +PROJECT = TextBox.dll +OBJFILES = TextBox.obj Comlib.obj About.obj TextDlg.obj CodeVw.obj +RESFILES = textbox.res +DEFFILE = +RESDEPEN = $(RESFILES) About.dfm TextDlg.dfm CodeVw.dfm +LIBFILES = +LIBRARIES = VCL35.lib +SPARELIBS = VCL35.lib +PACKAGES = VCLX35.bpi VCL35.bpi VCLDB35.bpi VCLDBX35.bpi bcbsmp35.bpi dclocx35.bpi \ + QRPT35.bpi TEEUI35.bpi VCLSMP35.bpi TEEDB35.bpi TEE35.bpi ibsmp35.bpi \ + NMFAST35.bpi INETDB35.bpi INET35.bpi +# --------------------------------------------------------------------------- +PATHCPP = .; +PATHASM = .; +PATHPAS = .; +PATHRC = .; +DEBUGLIBPATH = $(BCB)\lib\debug +RELEASELIBPATH = $(BCB)\lib\release +# --------------------------------------------------------------------------- +CFLAG1 = -WD -O2 -Hc -w -Ve -d -k- -vi -c -b- -w-par -w-inl -Vx +CFLAG2 = -I..\textart;$(BCB)\include;$(BCB)\include\vcl -H=$(BCB)\lib\vcl35.csm +CFLAG3 = -Tkh30000 +PFLAGS = -U..\textart;$(BCB)\lib\obj;$(BCB)\lib;$(RELEASELIBPATH) \ + -I..\textart;$(BCB)\include;$(BCB)\include\vcl -$L- -$D- -v -JPHN -M +RFLAGS = -i..\textart;$(BCB)\include;$(BCB)\include\vcl +AFLAGS = /i..\textart /i$(BCB)\include /i$(BCB)\include\vcl /mx /w2 /zn /d_RTLDLL +LFLAGS = -L..\textart;$(BCB)\lib\obj;$(BCB)\lib;$(RELEASELIBPATH) -aa -Tpd -x -Gn +IFLAGS = +# --------------------------------------------------------------------------- +ALLOBJ = c0d32.obj sysinit.obj $(OBJFILES) +ALLRES = $(RESFILES) +ALLLIB = $(LIBFILES) $(LIBRARIES) import32.lib cp32mt.lib +# --------------------------------------------------------------------------- +!ifdef IDEOPTIONS + +[Version Info] +IncludeVerInfo=0 +AutoIncBuild=0 +MajorVer=1 +MinorVer=0 +Release=0 +Build=0 +Debug=0 +PreRelease=0 +Special=0 +Private=0 +DLL=0 +Locale=1041 +CodePage=932 + +[Version Info Keys] +CompanyName= +FileDescription= +FileVersion=1.0.0.0 +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion=1.0.0.0 +Comments= + +[HistoryLists\hlIncludePath] +Count=2 +Item0=..\textart;$(BCB)\include;$(BCB)\include\vcl +Item1=$(BCB)\include;$(BCB)\include\vcl + +[HistoryLists\hlLibraryPath] +Count=2 +Item0=..\textart;$(BCB)\lib\obj;$(BCB)\lib +Item1=$(BCB)\lib\obj;$(BCB)\lib + +[HistoryLists\hlDebugSourcePath] +Count=1 +Item0=$(BCB)\source\vcl + +[HistoryLists\hlConditionals] +Count=2 +Item0=_RTLDLL +Item1=_RTLDLL;USEPACKAGES + +[HistoryLists\hlHostApplication] +Count=1 +Item0=D:\Mmsstv\Mmsstv.exe + +[Debugging] +DebugSourceDirs=$(BCB)\source\vcl + +[Parameters] +RunParams= +HostApplication=D:\Mmsstv\Mmsstv.exe + +!endif + +# --------------------------------------------------------------------------- +# MAKE セクション +# --------------------------------------------------------------------------- +# IDE はプロジェクトファイルのこのセクションは使用していません。 +# コマンドラインの MAKE ユーティリティを使用してビルドするためのものです。 +# --------------------------------------------------------------------------- + +.autodepend +# --------------------------------------------------------------------------- +!if !$d(BCC32) +BCC32 = bcc32 +!endif + +!if !$d(DCC32) +DCC32 = dcc32 +!endif + +!if !$d(TASM32) +TASM32 = tasm32 +!endif + +!if !$d(LINKER) +LINKER = ilink32 +!endif + +!if !$d(BRCC32) +BRCC32 = brcc32 +!endif +# --------------------------------------------------------------------------- +!if $d(PATHCPP) +.PATH.CPP = $(PATHCPP) +.PATH.C = $(PATHCPP) +!endif + +!if $d(PATHPAS) +.PATH.PAS = $(PATHPAS) +!endif + +!if $d(PATHASM) +.PATH.ASM = $(PATHASM) +!endif + +!if $d(PATHRC) +.PATH.RC = $(PATHRC) +!endif +# --------------------------------------------------------------------------- +$(PROJECT): $(OBJFILES) $(RESDEPEN) $(DEFFILE) + $(BCB)\BIN\$(LINKER) @&&! + $(LFLAGS) + + $(ALLOBJ), + + $(PROJECT),, + + $(ALLLIB), + + $(DEFFILE), + + $(ALLRES) +! +# --------------------------------------------------------------------------- +.pas.hpp: + $(BCB)\BIN\$(DCC32) $(PFLAGS) {$< } + +.pas.obj: + $(BCB)\BIN\$(DCC32) $(PFLAGS) {$< } + +.cpp.obj: + $(BCB)\BIN\$(BCC32) $(CFLAG1) $(CFLAG2) $(CFLAG3) -n$(@D) {$< } + +.c.obj: + $(BCB)\BIN\$(BCC32) $(CFLAG1) $(CFLAG2) $(CFLAG3) -n$(@D) {$< } + +.asm.obj: + $(BCB)\BIN\$(TASM32) $(AFLAGS) $<, $@ + +.rc.res: + $(BCB)\BIN\$(BRCC32) $(RFLAGS) -fo$@ $< +# --------------------------------------------------------------------------- + \ No newline at end of file diff --git a/CItems/TEXTBOX/TextBox.cpp b/CItems/TEXTBOX/TextBox.cpp new file mode 100644 index 0000000..eff5836 --- /dev/null +++ b/CItems/TEXTBOX/TextBox.cpp @@ -0,0 +1,237 @@ +//--------------------------------------------------------------------------- +#include +#pragma hdrstop +//--------------------------------------------------------------------------- +#include "ComLib.h" +#include "About.h" +//--------------------------------------------------------------------------- +USEUNIT("Comlib.cpp"); +USEFORM("About.cpp", AboutDlg); +USERC("textbox.rc"); +USEFORM("TextDlg.cpp", TextDlgBox); +USEFORM("CodeVw.cpp", CodeView); +//--------------------------------------------------------------------------- +int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void*) +{ + switch(reason){ + case DLL_PROCESS_ATTACH: + { + InitSys(); + + char bf[512]; + ::GetModuleFileName(hinst, bf, sizeof(bf)); + ::SetDirName(sys.m_BgnDir, bf); + + _setmbcp(_MB_CP_ANSI); + HWND hMM = ::FindWindow("TMmsstv", NULL); + if( hMM != NULL ) Application->Handle = hMM; + + if( sys.m_BitPixel < 24 ){ + sys.m_pBitmapTemp = new Graphics::TBitmap; + sys.m_pBitmapTemp->Width = 1; + sys.m_pBitmapTemp->Height = 1; + } + } + break; + case DLL_PROCESS_DETACH: + sys.m_fMultProc = NULL; + if( sys.m_pDefStg != NULL ){ + CItem *pItem = new CItem; + pItem->Create(NULL, 0); + pItem->SaveToInifile("Default", ININAME); + delete pItem; + delete sys.m_pDefStg; + sys.m_pDefStg = NULL; + } + if( sys.m_pTextList != NULL ){ + SaveStringsToIniFile(sys.m_pTextList, "Strings", ININAME, TRUE); + delete sys.m_pTextList; + sys.m_pTextList = NULL; + } + if( sys.m_pStyleList != NULL ){ + SaveStringsToIniFile(sys.m_pStyleList, "Styles", ININAME, FALSE); + delete sys.m_pStyleList; + sys.m_pStyleList = NULL; + } + if( sys.m_pFontList != NULL ){ + delete sys.m_pFontList; + sys.m_pFontList = NULL; + } + if( sys.m_pBitmapTemp != NULL ){ + delete sys.m_pBitmapTemp; + sys.m_pBitmapTemp = NULL; + } + break; + } + return 1; +} +//--------------------------------------------------------------------------- +extern "C" __declspec(dllexport) +void mcmLanguage(DWORD lang) +{ + sys.m_MsgEng = lang; +} +//--------------------------------------------------------------------------- +extern "C" __declspec(dllexport) +void mcmAboutDialog(HWND hWnd) +{ +#if UseHWND + TAboutDlg *pBox = new TAboutDlg(hWnd); +#else + TAboutDlg *pBox = new TAboutDlg(NULL); +#endif + pBox->ShowModal(); + delete pBox; +#if UseHWND + ::SetForegroundWindow(hWnd); +#endif +} +//--------------------------------------------------------------------- +extern "C" __declspec(dllexport) +HANDLE mcmCreateObject(LPCBYTE pStorage, DWORD Size) +{ + CItem *pItem = new CItem; + ASSERT(pItem); + if( pItem != NULL ) pItem->Create(pStorage, Size); + return (HANDLE)pItem; +} +//--------------------------------------------------------------------- +extern "C" __declspec(dllexport) +DWORD mcmGetItemType(HANDLE hObj) +{ + ASSERT(hObj); + CItem *pItem = (CItem *)hObj; + return pItem->GetItemType(); +} +//--------------------------------------------------------------------- +extern "C" __declspec(dllexport) +LPCBYTE mcmCreateStorage(HANDLE hObj, LPDWORD pSize) +{ + ASSERT(hObj); + CItem *pItem = (CItem *)hObj; + return pItem->CreateStorage(pSize); +} +//--------------------------------------------------------------------- +extern "C" __declspec(dllexport) +void mcmDeleteStorage(HANDLE hObj, LPCBYTE pStorage) +{ + ASSERT(hObj); + CItem *pItem = (CItem *)hObj; + pItem->DeleteStorage(pStorage); +} +//--------------------------------------------------------------------- +extern "C" __declspec(dllexport) +void mcmDeleteObject(HANDLE hObj) +{ + ASSERT(hObj); + CItem *pItem = (CItem *)hObj; + if( pItem != NULL ) delete pItem; +} +//--------------------------------------------------------------------- +extern "C" __declspec(dllexport) +DWORD mcmEdit(HANDLE hObj, HWND hWnd) +{ + ASSERT(hObj); + CItem *pItem = (CItem *)hObj; + int r = pItem->EditDialog(hWnd); +#if UseHWND + ::SetForegroundWindow(hWnd); +#endif + return r; +} +//--------------------------------------------------------------------- +extern "C" __declspec(dllexport) +DWORD mcmFont(HANDLE hObj, HWND hWnd) +{ + ASSERT(hObj); + CItem *pItem = (CItem *)hObj; + + int r = pItem->FontDialog(hWnd); + ::SetForegroundWindow(hWnd); + return r; +} +//--------------------------------------------------------------------- +extern "C" __declspec(dllexport) +DWORD mcmGetOrgSize(HANDLE hObj) +{ + ASSERT(hObj); + CItem *pItem = (CItem *)hObj; + return pItem->GetOrgSize(); +} +//--------------------------------------------------------------------- +extern "C" __declspec(dllexport) +void mcmPos(HANDLE hObj, DWORD pos, DWORD size, DWORD tsize) +{ + ASSERT(hObj); + CItem *pItem = (CItem *)hObj; + pItem->SetPos(pos, size, tsize); +} +//--------------------------------------------------------------------- +extern "C" __declspec(dllexport) +LPCSTR mcmGetUserText(HANDLE hObj) +{ + ASSERT(hObj); + CItem *pItem = (CItem *)hObj; + return pItem->GetText(); +} +//--------------------------------------------------------------------- +extern "C" __declspec(dllexport) +HBITMAP mcmUpdateText(HANDLE hObj, HBITMAP hDest, LPCSTR pText) +{ + ASSERT(hObj); + ASSERT(hDest); + CItem *pItem = (CItem *)hObj; + + // Draw object to hDest + Graphics::TBitmap *pDest = new Graphics::TBitmap; + pDest->Handle = hDest; + pDest = pItem->Draw(pDest, pText); + + HBITMAP hb = pDest->ReleaseHandle(); + delete pDest; + return (hb != hDest) ? hb : NULL; +} +//--------------------------------------------------------------------- +extern "C" __declspec(dllexport) +HBITMAP mcmUpdateImage(HANDLE hObj, HBITMAP hDest, HBITMAP hSrc) +{ + ASSERT(0); // This function should not be called + return NULL; +} +//--------------------------------------------------------------------- +extern "C" __declspec(dllexport) +void mcmSetDraft(HANDLE hObj, DWORD draft) +{ + ASSERT(hObj); + CItem *pItem = (CItem *)hObj; + + pItem->SetDraft(draft); +} +//--------------------------------------------------------------------- +extern "C" __declspec(dllexport) +void mcmSetEx(HANDLE hObj, DWORD ex) +{ + ASSERT(hObj); + CItem *pItem = (CItem *)hObj; + + pItem->SetEx(ex); +} +//--------------------------------------------------------------------- +extern "C" __declspec(dllexport) +void mcmGetFont(HANDLE hObj, LOGFONT *pLogfont) +{ + ASSERT(hObj); + CItem *pItem = (CItem *)hObj; + + pItem->GetFont(pLogfont); +} +//--------------------------------------------------------------------- +extern "C" __declspec(dllexport) +void mcmSetFont(HANDLE hObj, LOGFONT *pLogfont) +{ + ASSERT(hObj); + CItem *pItem = (CItem *)hObj; + + pItem->SetFont(pLogfont); +} + diff --git a/CItems/TEXTBOX/TextBox.rc b/CItems/TEXTBOX/TextBox.rc new file mode 100644 index 0000000..0e32c13 --- /dev/null +++ b/CItems/TEXTBOX/TextBox.rc @@ -0,0 +1,2 @@ +8000 ICON DISCARDABLE "Item.ico" + \ No newline at end of file diff --git a/CItems/TEXTBOX/TextBox.res b/CItems/TEXTBOX/TextBox.res new file mode 100644 index 0000000..4dd7390 Binary files /dev/null and b/CItems/TEXTBOX/TextBox.res differ diff --git a/CItems/TEXTBOX/TextDlg.cpp b/CItems/TEXTBOX/TextDlg.cpp new file mode 100644 index 0000000..8dca206 --- /dev/null +++ b/CItems/TEXTBOX/TextDlg.cpp @@ -0,0 +1,1217 @@ +//--------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "TextDlg.h" +//--------------------------------------------------------------------- +#pragma resource "*.dfm" +//TTextDlgBox *TextDlgBox; +//--------------------------------------------------------------------- +#if UseHWND +__fastcall TTextDlgBox::TTextDlgBox(HWND hWnd) + : TForm(hWnd) +#else +__fastcall TTextDlgBox::TTextDlgBox(TComponent* AOwner) + : TForm(AOwner) +#endif +{ + MultProc(); + m_DisEvent = 1; + m_pBitmap = NULL; + m_Change = 0; + m_DropProfile = 0; + m_FText = ""; + m_MemoDown = 0; + m_MouseHold = 0; + m_pCodeView = NULL; + if( sys.m_MsgEng ){ + Font->Name = "Arial"; + Font->Charset = ANSI_CHARSET; + + Caption = "Set text and colors - "VER" "TTL; + CancelBtn->Caption = "Cancel"; + FontBtn->Caption = "Font"; + SBM->Caption = "Mac"; + SBL->Caption = "Code"; + GBG->Caption = "Gradation"; + GBS->Caption = "Shadow"; + GBA->Caption = "Misc"; + CBFixed->Caption = "Fixed size"; + CBZero->Caption = "Slash zero"; + SBLD->Caption = "Del"; + SBLW->Caption = "Add"; + GBY->Caption = "Style profiles"; + L1->Caption = "Align"; + L2->Caption = "Style name"; + L33->Caption = "V.space"; + L34->Caption = "Rot."; + SBYD->Caption = "Del"; + SBYW->Caption = "Add"; + CBY->Text = "Untitled"; + SBM->Hint = "Insert macro-keyword"; + SBL->Hint = "Character code list"; + SBC->Hint = "Choose color's component"; + SBLD->Hint = "Delete the text in the list"; + SBLW->Hint = "Add current text into the list"; + SBYD->Hint = "Delete the style in the profiles"; + SBYW->Hint = "Add current style into the profiles"; + SB3DD->Hint = "Make the shadow shorter"; + SB3DI->Hint = "Make the shadow longer"; + SBA1->Hint = "Left"; + SBA2->Hint = "Center"; + SBA3->Hint = "Right"; + SBA4->Hint = "Auto"; +// FontBtn->Hint = "Choose font"; + SBFD->Hint = "Make the font smaller"; + SBFI->Hint = "Make the font bigger"; + SBB->Hint = "Bold"; + SBI->Hint = "Italic"; + SBMSG->Hint = "Show messages list"; + Msg->Hint = "Copy the message to the text box with double click"; + } + else { + Caption = "テキストと色の設定 - "VER" "TTLJ; + CBY->Text = "無題"; + } + SBFD->Glyph->Assign(SB3DD->Glyph); + SBFI->Glyph->Assign(SB3DI->Glyph); + MultProc(); + if( sys.m_pTextList == NULL ){ + sys.m_pTextList = new TStringList; + LoadStringsFromIniFile(sys.m_pTextList, "Strings", ININAME, TRUE); + MultProc(); + if(!sys.m_pTextList->Count){ + sys.m_pTextList->Add("%c\\r\\nur %r\\r\\nde %m"); + sys.m_pTextList->Add("Tnx for nice PIC\\r\\nur %r\\r\\nde %m"); + sys.m_pTextList->Add("%n\\r\\nBest 73\\r\\nde %m"); + } + } + ASSERT(sys.m_pTextList); + CBList->Items->Assign(sys.m_pTextList); + if( sys.m_pStyleList == NULL ){ + sys.m_pStyleList = new TStringList; + LoadStringsFromIniFile(sys.m_pStyleList, "Styles", ININAME, FALSE); + MultProc(); + } + CBY->Items->Assign(sys.m_pStyleList); + CBY->Sorted = TRUE; + int i; + if( sys.m_pFontList == NULL ){ + sys.m_pFontList = new TStringList; + char fname[512]; + sprintf(fname, "%s%s", sys.m_BgnDir, ININAME); + TMemIniFile *pIniFile = new TMemIniFile(fname); + for( i = 0; i < 5; i++ ){ + char bf[32]; + sprintf(bf, "Font.%u", i); + AnsiString as = pIniFile->ReadString(bf, "FontName", ""); + if( !as.IsEmpty() ){ + BYTE charset = (BYTE)pIniFile->ReadInteger(bf, "FontSet", 0); + DWORD style = pIniFile->ReadInteger(bf, "FontStyle", 0); + AddStyle(as, charset, style); + } + sys.m_pFontList->Add(as); + } + delete pIniFile; + } + for( i = 0; i < 5; i++ ) SetSBF(i); + ShowHint = sys.m_WinNT; + MultProc(); +} +//--------------------------------------------------------------------- +void __fastcall TTextDlgBox::FormDestroy(TObject *Sender) +{ + if( m_pBitmap != NULL ) delete m_pBitmap; + if( m_pCodeView ) delete m_pCodeView; + MultProc(); + ASSERT(sys.m_pTextList); + sys.m_pTextList->Assign(CBList->Items); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::TopMost(void) +{ +#if UseHWND + ::SetWindowPos(Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); +#endif +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::NoTopMost(void) +{ +#if UseHWND + ::SetWindowPos(Handle, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); +#endif +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::UpdateUI(void) +{ + m_DisEvent++; + int f = SBG1->Down ? FALSE : TRUE; + PG2->Visible = f; + PG3->Visible = f; + PG4->Visible = f; + SBC->Visible = f && sys.m_fColorComp; + f = !SBS1->Down; + if( !f ) CB3D->Checked = FALSE; + CB3D->Enabled = f; + PB1->Visible = f && (!SBS2->Down || !CB3D->Checked); + PB2->Visible = f && (SBS4->Down || CB3D->Checked); + PB3->Visible = f && CB3D->Checked; + UDL->Enabled = f && (SBS3->Down || !CB3D->Checked); + SBLW->Enabled = (!m_FText.IsEmpty() && CBList->Items->IndexOf(m_FText) < 0) ? TRUE : FALSE; + SBLD->Enabled = CBList->ItemIndex >= 0 ? TRUE : FALSE; + SBYW->Enabled = !CBY->Text.IsEmpty(); + SBYD->Enabled = !CBY->Text.IsEmpty() && (sys.m_pStyleList->IndexOf(CBY->Text) >= 0); + UDX->Enabled = CB3D->Checked; + UDY->Enabled = CB3D->Checked; + SB3DI->Enabled = CB3D->Checked; + SB3DD->Enabled = CB3D->Checked; + if( ShowHint ){ + char bf[32]; + sprintf(bf, "W = %d", UDL->Position); + UDL->Hint = bf; + sprintf(bf, "3D(Y) = %d", UDY->Position); + UDY->Hint = bf; + sprintf(bf, "3D(X) = %d", UDX->Position); + UDX->Hint = bf; + } + Msg->Visible = SBMSG->Down; + m_DisEvent--; +} +//--------------------------------------------------------------------- +void __fastcall TTextDlgBox::UpdateMemoFont(BYTE charset) +{ + switch(charset){ + case SHIFTJIS_CHARSET: + case HANGEUL_CHARSET: + case CHINESEBIG5_CHARSET: // + case 134: // 簡略 + break; + default: + charset = Font->Charset; + break; + } + m_DisEvent++; + if( Memo->Font->Charset != charset ){ + Memo->Font->Charset = charset; + } + m_DisEvent--; + UpdateFontBtnHint(); +} +//--------------------------------------------------------------------- +int __fastcall TTextDlgBox::Execute(CItem *pItem) +{ + MultProc(); + m_Item.Copy(pItem); + UpdateDialog(&m_Item); + UpdateBitmap(); + m_DisEvent = 0; + MultProc(); + int r = ShowModal(); + if( Msg->Modified ) sys.m_Msg = Msg->Text; + if( r == IDOK ){ + MultProc(); + pItem->Copy(&m_Item); + if( pItem->m_ASize ){ + pItem->m_OrgXW = -1; + } + MultProc(); + return TRUE; + } + else { + MultProc(); + return FALSE; + } +} +//--------------------------------------------------------------------- +void __fastcall TTextDlgBox::UpdateFText(void) +{ + AnsiString as; + if( Memo->Text.IsEmpty() ){ + m_FText = ""; + } + else { + ::CrLf2Yen(as, Memo->Text); + LPSTR p = as.c_str(); + if( *p ){ + *(p+strlen(p)-1) = 0; + m_FText = p+1; + } + } + m_DisEvent++; + CBList->ItemIndex = CBList->Items->IndexOf(m_FText); + m_DisEvent--; +} +//--------------------------------------------------------------------- +void __fastcall TTextDlgBox::UpdateItem(CItem *pItem) +{ + UpdateUI(); + if( SBG1->Down ){ + pItem->m_Grade = 0; + } + else if( SBG2->Down ){ + pItem->m_Grade = 1; + } + else if( SBG3->Down ){ + pItem->m_Grade = 2; + } + else { + pItem->m_Grade = 3; + } + if( SBS1->Down ){ + pItem->m_Shadow = 0; + } + else if( SBS2->Down ){ + pItem->m_Shadow = 1; + } + else if( SBS3->Down ){ + pItem->m_Shadow = 2; + } + else { + pItem->m_Shadow = 3; + } + if( SBA1->Down ){ + pItem->m_Align = 0; + } + else if( SBA2->Down ){ + pItem->m_Align = 1; + } + else if( SBA3->Down ){ + pItem->m_Align = 2; + } + else { + pItem->m_Align = 3; + } + pItem->m_ColB[0].c = PB1->Color; + pItem->m_ColB[1].c = PB2->Color; + pItem->m_ColB[2].c = PB3->Color; + pItem->m_ColG[0].c = PG1->Color; + pItem->m_ColG[1].c = PG2->Color; + pItem->m_ColG[2].c = PG3->Color; + pItem->m_ColG[3].c = PG4->Color; + pItem->m_Line = UDL->Position; + pItem->m_ASize = !CBFixed->Checked; + pItem->m_Zero = CBZero->Checked; + pItem->m_Text = Memo->Text.c_str(); + pItem->m_3d = (CB3D->Enabled && CB3D->Checked) ? 0x00010000 : 0; + pItem->m_3d |= ((UDY->Position << 8)&0x0000ff00); + pItem->m_3d |= (UDX->Position & 0x000000ff); + pItem->m_OYW = UDOYW->Position & 0x0000ffff; + pItem->m_Rot = UDRot->Position; +} +//--------------------------------------------------------------------- +void __fastcall TTextDlgBox::UpdateDialog(CItem *pItem) +{ + m_DisEvent++; + switch(pItem->m_Grade){ + case 1: + SBG2->Down = TRUE; + break; + case 2: + SBG3->Down = TRUE; + break; + case 3: + SBG4->Down = TRUE; + break; + default: + SBG1->Down = TRUE; + break; + } + switch(pItem->m_Shadow){ + case 1: + SBS2->Down = TRUE; + break; + case 2: + SBS3->Down = TRUE; + break; + case 3: + SBS4->Down = TRUE; + break; + default: + SBS1->Down = TRUE; + break; + } + switch(pItem->m_Align){ + case 1: + SBA2->Down = TRUE; + break; + case 2: + SBA3->Down = TRUE; + break; + case 3: + SBA4->Down = TRUE; + break; + default: + SBA1->Down = TRUE; + break; + } + PB1->Color = pItem->m_ColB[0].c; + PB2->Color = pItem->m_ColB[1].c; + PB3->Color = pItem->m_ColB[2].c; + PG1->Color = pItem->m_ColG[0].c; + PG2->Color = pItem->m_ColG[1].c; + PG3->Color = pItem->m_ColG[2].c; + PG4->Color = pItem->m_ColG[3].c; + UDL->Position = SHORT(pItem->m_Line); + CBFixed->Checked = !pItem->m_ASize; + CBZero->Checked = pItem->m_Zero; + CB3D->Checked = pItem->m_3d & 0x00010000; + int xm = pItem->m_3d & 0x000000ff; + int ym = (pItem->m_3d >> 8) & 0x000000ff; + if( xm & 0x0080 ) xm |= 0xffffff80; + if( ym & 0x0080 ) ym |= 0xffffff80; + UDY->Position = SHORT(ym); + UDX->Position = SHORT(xm); + if( pItem->m_pFont != NULL ){ + UpdateMemoFont(pItem->m_pFont->Charset); + UpdateFontBtnHint(); + } + Memo->Text = pItem->m_Text.c_str(); + + UDOYW->Position = (SHORT)pItem->GetTrueOYW(); + UDRot->Position = (SHORT)pItem->m_Rot; + UpdateFText(); + m_DisEvent--; +} +//--------------------------------------------------------------------- +void __fastcall TTextDlgBox::UpdateBitmap(void) +{ + MultProc(); + m_Change = 0; + UpdateItem(&m_Item); + char bf[1024]; + sys.m_fConvMac(bf, m_Item.GetText(), sizeof(bf)-1); + MultProc(); + if( m_pBitmap == NULL ){ + int xw = m_Item.m_OrgXW; + int yw = m_Item.m_OrgYW; + if( (xw < 0)||(yw < 0) ){ + xw = 160; + yw = 128; + } + m_pBitmap = CreateBitmap(xw, yw); + } + FillBitmap(m_pBitmap, m_Item.m_Back); + MultProc(); + m_pBitmap = m_Item.Draw(m_pBitmap, bf); + PBox->Invalidate(); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::PBoxPaint(TObject *Sender) +{ + if( m_pBitmap == NULL ) return; + + Graphics::TBitmap *pBitmap = m_pBitmap; + if( sys.m_BitPixel == 16 ){ + pBitmap = new Graphics::TBitmap; + pBitmap->Width = m_pBitmap->Width; + pBitmap->Height = m_pBitmap->Height; + pBitmap->Canvas->Draw(0, 0, m_pBitmap); + } + pBitmap->Transparent = TRUE; + pBitmap->TransparentMode = tmFixed; + pBitmap->TransparentColor = pBitmap->Canvas->Pixels[0][0]; + PBox->Canvas->Draw(0, 0, pBitmap); + pBitmap->Transparent = FALSE; + if( pBitmap != m_pBitmap ) delete pBitmap; + if( m_MouseHold ){ + PBox->Canvas->Pen->Color = clBlue; + PBox->Canvas->MoveTo(0, m_MouseYC); + PBox->Canvas->LineTo(PBox->Width, m_MouseYC); + PBox->Canvas->MoveTo(m_MouseXC, 0); + PBox->Canvas->LineTo(m_MouseXC, PBox->Height); + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::MemoChange(TObject *Sender) +{ + if( m_DisEvent ) return; + + m_Change = 2; + Timer->Enabled = TRUE; + UpdateFText(); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::TimerTimer(TObject *Sender) +{ + if( m_Change ){ + m_Change--; + if( !m_Change ){ + Timer->Enabled = FALSE; + UpdateBitmap(); + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::SBG1Click(TObject *Sender) +{ + if( m_DisEvent ) return; + + UpdateBitmap(); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::PB1Click(TObject *Sender) +{ + TPanel *pPanel = (TPanel *)Sender; + InitCustomColor(ColorDialog); + AddCustomColor(ColorDialog, PG1->Color); + AddCustomColor(ColorDialog, PG2->Color); + AddCustomColor(ColorDialog, PG3->Color); + AddCustomColor(ColorDialog, PG4->Color); + AddCustomColor(ColorDialog, PB1->Color); + AddCustomColor(ColorDialog, PB2->Color); + AddCustomColor(ColorDialog, m_Item.m_Back.c); + + ColorDialog->Color = pPanel->Color; + NoTopMost(); + int r = ColorDialog->Execute(); + TopMost(); + if( r == TRUE ){ + pPanel->Color = ColorDialog->Color; + UpdateBitmap(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::FormActivate(TObject *Sender) +{ + TopMost(); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::FormDeactivate(TObject *Sender) +{ + NoTopMost(); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::UDLClick(TObject *Sender, TUDBtnType Button) +{ + if( m_DisEvent ) return; + + UpdateBitmap(); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::FontBtnClick(TObject *Sender) +{ + FontDialog->Font->Assign(m_Item.m_pFont); + FontDialog->Font->Color = PG1->Color; + NoTopMost(); + int r = FontDialog->Execute(); + TopMost(); + if( r == TRUE ){ + m_Item.m_pFont->Assign(FontDialog->Font); + PG1->Color = FontDialog->Font->Color; + m_Item.UpdateFont(); + if( m_Item.m_pFont != NULL ){ + UpdateMemoFont(m_Item.m_pFont->Charset); + } + UpdateBitmap(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::SBMClick(TObject *Sender) +{ + if( sys.m_fGetMacKey ){ + char bf[256]; + NoTopMost(); + int r = sys.m_fGetMacKey(bf, sizeof(bf)); + TopMost(); + if( r ){ + HWND hWnd; + if( SBMSG->Down ){ + Msg->SetFocus(); + hWnd = Msg->Handle; + } + else { + Memo->SetFocus(); + hWnd = Memo->Handle; + } + for( LPCSTR p = bf; *p; p++ ){ + ::PostMessage(hWnd, WM_CHAR, *p, 0); + } + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::SBCClick(TObject *Sender) +{ + if( sys.m_fColorComp ){ + UCOL col[4]; + col[0].c = PG1->Color; + col[1].c = PG2->Color; + col[2].c = PG3->Color; + col[3].c = PG4->Color; + NoTopMost(); + int r = sys.m_fColorComp(&col[0].d); + TopMost(); + if( r ){ + PG1->Color = col[0].c; + PG2->Color = col[1].c; + PG3->Color = col[2].c; + PG4->Color = col[3].c; + UpdateBitmap(); + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::SBLWClick(TObject *Sender) +{ + m_DisEvent++; + CBList->Items->Add(m_FText); + CBList->ItemIndex = CBList->Items->IndexOf(m_FText); + UpdateUI(); + m_DisEvent--; +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::SBLDClick(TObject *Sender) +{ + m_DisEvent++; + if( CBList->ItemIndex >= 0 ){ + int n = CBList->ItemIndex; + CBList->ItemIndex = -1; + CBList->Items->Delete(n); + UpdateUI(); + } + m_DisEvent--; +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::CBListChange(TObject *Sender) +{ + if( m_DisEvent ) return; + if( CBList->ItemIndex < 0 ) return; + + m_DisEvent++; + AnsiString cs; + AnsiString as = CBList->Items->Strings[CBList->ItemIndex]; + m_FText = as; + ::Yen2CrLf(cs, as); + Memo->Text = cs; + UpdateBitmap(); + m_DisEvent--; +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::SBYWClick(TObject *Sender) +{ + m_DisEvent++; + int r = sys.m_pStyleList->IndexOf(CBY->Text); + if( r < 0 ) r = sys.m_pStyleList->Count; + + CItem *pItem = new CItem; + pItem->Copy(&m_Item); + pItem->m_Text = CBY->Text; + char bf[64]; + sprintf(bf, "Style.%u", r); + pItem->SaveToInifile(bf, ININAME); + delete pItem; + + if( r == sys.m_pStyleList->Count ){ + CBY->Items->Add(CBY->Text); + sys.m_pStyleList->Add(CBY->Text); + UpdateUI(); + } + m_DisEvent--; +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::SBYDClick(TObject *Sender) +{ + m_DisEvent++; + int r = sys.m_pStyleList->IndexOf(CBY->Text); + if( r >= 0 ){ + char bf[64]; + CItem *pItem = new CItem; + int i; + for( i = r; i < sys.m_pStyleList->Count - 1; i++ ){ + sprintf(bf, "Style.%u", i+1); + pItem->LoadFromInifile(bf, ININAME); + sprintf(bf, "Style.%u", i); + pItem->SaveToInifile(bf, ININAME); + MultProc(); + } + sprintf(bf, "Style.%u", i); + pItem->DeleteInifile(bf, ININAME); + delete pItem; + sys.m_pStyleList->Delete(r); + r = CBY->Items->IndexOf(CBY->Text); + if( r >= 0 ) CBY->Items->Delete(r); + UpdateUI(); + } + m_DisEvent--; +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::CBYChange(TObject *Sender) +{ + if( m_DisEvent ) return; + if( !m_DropProfile ){ + UpdateUI(); + return; + } + m_DropProfile = 0; + + m_DisEvent++; + int r = sys.m_pStyleList->IndexOf(CBY->Text); + if( r >= 0 ){ + AnsiString as = m_Item.m_Text; + DWORD ex = m_Item.GetEx(); + int pos = m_Item.GetPos(); + CItem *pItem = new CItem; + char bf[64]; + sprintf(bf, "Style.%u", r); + pItem->LoadFromInifile(bf, ININAME); + m_Item.Copy(pItem); + delete pItem; + m_Item.m_Text = as; + m_Item.SetEx(ex); + m_Item.SetPos(pos); + UpdateDialog(&m_Item); + UpdateBitmap(); + } + m_DisEvent--; +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::CBYKeyPress(TObject *Sender, char &Key) +{ + m_DropProfile = 0; + UpdateUI(); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::CBYDropDown(TObject *Sender) +{ + m_DropProfile = 1; +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::PBoxMouseDown(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( m_DisEvent ) return; + + m_DisEvent++; + if( Button == mbRight ){ + CB3D->Checked = CB3D->Checked ? FALSE : TRUE; + } + else { + CB3D->Checked = TRUE; + m_MouseHold = TRUE; + int xc = m_pBitmap->Width / 2; + int yc = m_pBitmap->Height / 2; + m_MouseXC = xc; + m_MouseYC = yc; + int x = X - xc; + int y = Y - yc; + x = x * 48 / xc; + y = y * 48 / yc; + double s = -UDRot->Position * PI / 180.0; + double cosk = cos(s); + double sink = sin(s); + short xx = x * cosk + y * sink; + short yy = -x * sink + y * cosk; + UDX->Position = SHORT(xx); + UDY->Position = SHORT(yy); + Screen->Cursor = crSizeAll; + } + m_DisEvent--; + UpdateBitmap(); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::PBoxMouseMove(TObject *Sender, + TShiftState Shift, int X, int Y) +{ + if( m_MouseHold ){ + X = X - m_MouseXC; + Y = Y - m_MouseYC; + double s = -UDRot->Position * PI / 180.0; + double cosk = cos(s); + double sink = sin(s); + short x = X * cosk + Y * sink; + short y = -X * sink + Y * cosk; + short UX = UDX->Position; + short UY = UDY->Position; + m_DisEvent++; + UDX->Position = short(x); + UDY->Position = short(y); + m_DisEvent--; + if( (UX != UDX->Position) || (UY != UDY->Position) ){ + UpdateBitmap(); + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::PBoxMouseUp(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( m_MouseHold ){ + m_MouseHold = 0; + PBox->Invalidate(); + } + Screen->Cursor = crDefault; +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::UD3D(int a) +{ + m_DisEvent++; + int x = UDX->Position; + int y = UDY->Position; + int xs = (x >= 0) ? 1 : -1; + int ys = (y >= 0) ? 1 : -1; + x = ABS(x); + y = ABS(y); + if( x == y ){ + int ad; + if( x < 4 ){ + ad = 1; + } + else if( x < 12 ){ + ad = 2; + } + else { + ad = 4; + } + ad *= a; + x += ad; + y += ad; + if( x < 2 ) x = 2; + if( y < 2 ) y = 2; + if( x > 48 ) x = 48; + if( y > 48 ) y = 48; + } + else { + if( x < y ) x = y; + x &= 0xfffffffc; + y = x; + } + x *= xs; y *= ys; + UDX->Position = SHORT(x); + UDY->Position = SHORT(y); + m_DisEvent--; + UpdateBitmap(); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::SB3DIClick(TObject *Sender) +{ + UD3D((Sender == SB3DI) ? 1 : -1); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::SBMSGClick(TObject *Sender) +{ + Msg->Visible = SBMSG->Down; + if( SBMSG->Down ){ + Msg->Text = sys.m_Msg; + Msg->Modified = FALSE; + Msg->SelLength = 0; + Msg->SetFocus(); + } + else { + if( Msg->Modified ){ + sys.m_Msg = Msg->Text; + Msg->Modified = FALSE; + } + Memo->SetFocus(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::MsgDblClick(TObject *Sender) +{ + AnsiString as; + AnsiString cs; + + m_DisEvent++; + if( Msg->Lines->Count ){ + int e = Msg->SelStart; + LPCSTR p = Msg->Text.c_str(); + int n = 0; + for( int i = 0; i < e; i++, p++ ){ + if( *p == '\n' ) n++; + } + if( n > Msg->Lines->Count ) n = Msg->Lines->Count - 1; + as = Msg->Lines->Strings[n]; + } + m_FText = as; + ::Yen2CrLf(cs, as); + Memo->Text = cs; + m_DisEvent--; + SBMSG->Down = FALSE; + SBMSGClick(NULL); + MultProc(); + UpdateFText(); + UpdateBitmap(); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::MemoStartDrag(TObject *Sender, + TDragObject *&DragObject) +{ + if( !SBMSG->Down ){ + SBMSG->Down = TRUE; + SBMSGClick(NULL); + } +} +//--------------------------------------------------------------------------- + +void __fastcall TTextDlgBox::MsgDragDrop(TObject *Sender, TObject *Source, + int X, int Y) +{ + Msg->Lines->Add(m_FText); +} +//--------------------------------------------------------------------------- + +void __fastcall TTextDlgBox::MsgDragOver(TObject *Sender, TObject *Source, + int X, int Y, TDragState State, bool &Accept) +{ + if( Source == Memo ) Accept = TRUE; +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::MemoMouseDown(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + m_MemoX = X; + m_MemoY = Y; + m_MemoDown = 1; +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::MemoMouseMove(TObject *Sender, + TShiftState Shift, int X, int Y) +{ + if( m_MemoDown == 1 ){ + X -= m_MemoX; + Y -= m_MemoY; + if( (X*X)+(Y*Y) > 64 ){ + m_MemoDown = 2; + Memo->BeginDrag(TRUE); + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::MemoMouseUp(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + m_MemoDown = 0; +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::FontBtnMouseDown(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( Button == mbRight ){ + BYTE cset; + UINT cp = ::GetACP(); + switch(cp){ + case 932: + cset = SHIFTJIS_CHARSET; + break; + case 949: + cset = HANGEUL_CHARSET; + break; + case 950: + cset = CHINESEBIG5_CHARSET; + break; + case 936: + cset = 134; // 簡略 + break; + default: + cset = DEFAULT_CHARSET; + break; + } + int charset = m_Item.m_pFont->Charset; + m_Item.m_pFont->Charset = BYTE((charset != ANSI_CHARSET) ? ANSI_CHARSET : cset); + m_Item.UpdateFont(); + if( m_Item.m_pFont != NULL ){ + UpdateMemoFont(m_Item.m_pFont->Charset); + } + UpdateBitmap(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::UpdateFontBtnHint(void) +{ + AnsiString as = sys.m_MsgEng ? "Choose font" : "フォントの選択"; + if( m_Item.m_pFont ){ + as += " ["; + as += m_Item.m_pFont->Name; + TFontStyles ts = m_Item.m_pFont->Style; + DWORD d = FontStyle2Code(ts); + AddStyle(as, m_Item.m_pFont->Charset, d); + as += "]"; + SBB->Down = d & FSBOLD; + SBI->Down = d & FSITALIC; + if( m_pCodeView ) m_pCodeView->Execute(Handle, m_Item.m_pFont); + } + FontBtn->Hint = as; +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::SetSBF(int n) +{ + if( !sys.m_pFontList ) return; + + TSpeedButton* _tt[]={SBF1, SBF2, SBF3, SBF4, SBF5, NULL}; + + TSpeedButton* pButton = _tt[n]; + AnsiString es = sys.m_MsgEng ? "Registration = Right button" : "登録=右ボタン"; + AnsiString fs = sys.m_pFontList->Strings[n]; + int undef = fs.IsEmpty(); + if( undef ) fs = sys.m_MsgEng ? "Load registered font" : "登録フォントの読み出し"; + char bf[256]; + sprintf(bf, "%s (%s)", fs.c_str(), es.c_str()); + pButton->Hint = bf; + pButton->Font->Color = undef ? clGrayText : clBlack; +} +//--------------------------------------------------------------------------- +int __fastcall TTextDlgBox::GetSBFIndex(TObject *Sender) +{ + TSpeedButton* _tt[]={SBF1, SBF2, SBF3, SBF4, SBF5, NULL}; + + for( int i = 0; _tt[i]; i++ ){ + if( Sender == _tt[i] ) return i; + } + return 0; +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::SBFClick(TObject *Sender) +{ + if( !sys.m_pFontList ) return; + int N = GetSBFIndex(Sender); + if( sys.m_pFontList->Strings[N].IsEmpty() ) return; + + FontDialog->Font->Assign(m_Item.m_pFont); + + char fname[512]; + sprintf(fname, "%s%s", sys.m_BgnDir, ININAME); + TMemIniFile *pIniFile = new TMemIniFile(fname); + { + char bf[32]; + sprintf(bf, "Font.%u", N); + int ht = m_Item.m_pFont->Height; + LoadFontFromInifile(m_Item.m_pFont, bf, pIniFile); + int hs = m_Item.m_pFont->Height; + m_Item.m_pFont->Height = ht; + int oyw = (short)pIniFile->ReadInteger(bf, "OYW", UDOYW->Position); + if( hs ) oyw = ht * oyw / hs; + UDOYW->Position = (short)oyw; + } + delete pIniFile; + + m_Item.UpdateFont(); + if( m_Item.m_pFont != NULL ){ + UpdateMemoFont(m_Item.m_pFont->Charset); + } + UpdateBitmap(); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::SBFMouseDown(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( Button == mbRight ){ + FontDialog->Font->Assign(m_Item.m_pFont); + FontDialog->Font->Color = clBlack; + NoTopMost(); + int r = FontDialog->Execute(); + TopMost(); + if( r == TRUE ){ + char fname[512]; + sprintf(fname, "%s%s", sys.m_BgnDir, ININAME); + TMemIniFile *pIniFile = new TMemIniFile(fname); + { + int N = GetSBFIndex(Sender); + char bf[32]; + sprintf(bf, "Font.%u", N); + SaveFontToInifile(FontDialog->Font, bf, pIniFile); + pIniFile->WriteInteger(bf, "OYW", UDOYW->Position); + pIniFile->UpdateFile(); + if( sys.m_pFontList ){ + AnsiString as = FontDialog->Font->Name; + TFontStyles ts = FontDialog->Font->Style; + DWORD d = FontStyle2Code(ts); + AddStyle(as, FontDialog->Font->Charset, d); + sys.m_pFontList->Strings[N] = as; + SetSBF(N); + } + } + delete pIniFile; + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::SBBClick(TObject *Sender) +{ + if( !m_Item.m_pFont ) return; + + TFontStyles ts = m_Item.m_pFont->Style; + DWORD d = FontStyle2Code(ts); + d ^= FSBOLD; + ts = Code2FontStyle(d); + m_Item.m_pFont->Style = ts; + + m_Item.UpdateFont(); + if( m_Item.m_pFont != NULL ){ + UpdateMemoFont(m_Item.m_pFont->Charset); + } + UpdateBitmap(); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::SBIClick(TObject *Sender) +{ + if( !m_Item.m_pFont ) return; + + TFontStyles ts = m_Item.m_pFont->Style; + DWORD d = FontStyle2Code(ts); + d ^= FSITALIC; + ts = Code2FontStyle(d); + m_Item.m_pFont->Style = ts; + + m_Item.UpdateFont(); + if( m_Item.m_pFont != NULL ){ + UpdateMemoFont(m_Item.m_pFont->Charset); + } + UpdateBitmap(); +} +//--------------------------------------------------------------------------- + +void __fastcall TTextDlgBox::SBFDMouseDown(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( m_Item.m_pFont == NULL ) return; + + int ad = 0; + int h = m_Item.m_pFont->Height; + if( Sender == SBFD ){ + if( Button == mbLeft ){ + if( h < -2 ) ad = 1; + } + else if( Button == mbRight ){ + if( h < -6 ) ad = 4; + } + UpdateBitmap(); + } + else { + if( Button == mbLeft ){ + ad = -1; + } + else if( Button == mbRight ){ + ad = -4; + } + } + if( ad ){ + m_Item.m_pFont->Height = h + ad; + UpdateBitmap(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::SBLClick(TObject *Sender) +{ + if( !sys.m_CodeLeft ) sys.m_CodeLeft = Left - 120; + if( !sys.m_CodeTop ) sys.m_CodeTop = Top + 80; + if( !m_pCodeView ){ + m_pCodeView = new TCodeView(this); + } + m_pCodeView->Execute((HWND)Handle, m_Item.m_pFont); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::OnCodeViewClose(TMessage Message) +{ + if( Message.LParam == int(m_pCodeView) ){ + TCodeView *pView = m_pCodeView; + m_pCodeView = NULL; + delete pView; + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::OnCodeInsert(TMessage Message) +{ + switch(Message.WParam){ + case 0xfffffff0: + case 0xfffffff1: + case 0xfffffff2: + case 0xfffffff3: + case 0xfffffff4: + case 0xfffffff5: + case 0xfffffff6: + case 0xfffffff7: + if( m_Item.m_pFont != NULL ){ + TFont *pFont = m_Item.m_pFont; + int dfs = 0; + switch(Message.WParam & 7){ + case 0: + pFont->Name = "Webdings"; + pFont->Charset = 2; + break; + case 1: + pFont->Name = "Wingdings"; + pFont->Charset = 2; + break; + case 2: + pFont->Name = "Symbol"; + pFont->Charset = 2; + break; + case 3: + pFont->Name = "Arial"; + pFont->Charset = ANSI_CHARSET; + dfs = FSBOLD; + break; + case 4: + pFont->Name = sys.m_MsgEng ? "MS UI Gothic" : "MS Pゴシック"; + pFont->Charset = SHIFTJIS_CHARSET; + dfs = FSBOLD; + break; + case 5: + pFont->Name = "DotumChe"; + pFont->Charset = HANGEUL_CHARSET; + if( !sys.m_tFontFam[fmHL] && sys.m_tFontFam[fmJOHAB] ){ + pFont->Charset = JOHAB_CHARSET; + } + dfs = FSBOLD; + break; + case 6: + pFont->Name = "SimHei"; + pFont->Charset = 134; + dfs = FSBOLD; + break; + case 7: + pFont->Name = "PMingLiU"; + pFont->Charset = CHINESEBIG5_CHARSET; + dfs = FSBOLD; + break; + } + TFontStyles fs; + fs = Code2FontStyle(dfs); + pFont->Style = fs; + m_Item.UpdateFont(); + UpdateMemoFont(m_Item.m_pFont->Charset); + UpdateBitmap(); + } + break; + case 0xfffffffe: + ::SetWindowPos(m_pCodeView->Handle, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); +// m_pCodeView->Visible = FALSE; + FontBtnClick(NULL); + ::SetWindowPos(m_pCodeView->Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); +// m_pCodeView->Visible = TRUE; + break; + case 0xffffffff: + Memo->Clear(); + UpdateBitmap(); + break; + default: + if( Message.WParam ){ + HWND hWnd; + Memo->SetFocus(); + hWnd = Memo->Handle; + char bf[16]; + if( Message.WParam & 0x00ff0000 ){ + wsprintf(bf, "\\$%04x", Message.WParam & 0x00ffff); + } + else if( Message.WParam & 0x00ff00 ){ + bf[0] = BYTE(Message.WParam >> 8); + bf[1] = BYTE(Message.WParam); + bf[2] = 0; + } + else if( (Message.WParam == 0x0d) || (Message.WParam == 0x0a) ){ + bf[0] = 0x0d; bf[1] = 0; + } + else if( (Message.WParam != '%') && ((Message.WParam >= 0x20) && (Message.WParam <= 0x7f)) ){ + bf[0] = (char)Message.WParam; bf[1] = 0; + } + else { + wsprintf(bf, "\\x%02x", Message.WParam); + } + for( LPCSTR p = bf; *p; p++ ){ + ::PostMessage(hWnd, WM_CHAR, *p & 0x00ff, 0); + } + } + break; + } +} +//--------------------------------------------------------------------------- + diff --git a/CItems/TEXTBOX/TextDlg.dfm b/CItems/TEXTBOX/TextDlg.dfm new file mode 100644 index 0000000..8c3f678 Binary files /dev/null and b/CItems/TEXTBOX/TextDlg.dfm differ diff --git a/CItems/TEXTBOX/TextDlg.h b/CItems/TEXTBOX/TextDlg.h new file mode 100644 index 0000000..db34e85 --- /dev/null +++ b/CItems/TEXTBOX/TextDlg.h @@ -0,0 +1,192 @@ +//---------------------------------------------------------------------------- +#ifndef TextDlgH +#define TextDlgH +//---------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//---------------------------------------------------------------------------- +#include "ComLib.h" +#include +#include +#include "CodeVw.h" +//---------------------------------------------------------------------------- +class TTextDlgBox : public TForm +{ +__published: + TButton *OKBtn; + TButton *CancelBtn; + TButton *FontBtn; + TMemo *Memo; + TGroupBox *GBG; + TSpeedButton *SBM; + TSpeedButton *SBG1; + TSpeedButton *SBG2; + TSpeedButton *SBG3; + TSpeedButton *SBG4; + TPanel *PG1; + TPanel *PG2; + TPanel *PG3; + TPanel *PG4; + TSpeedButton *SBC; + TGroupBox *GBS; + TSpeedButton *SBS1; + TSpeedButton *SBS2; + TSpeedButton *SBS3; + TSpeedButton *SBS4; + TPanel *PB1; + TPanel *PB2; + TPanel *PB3; + TUpDown *UDL; + TGroupBox *GB3D; + TCheckBox *CB3D; + TUpDown *UDY; + TUpDown *UDX; + TSpeedButton *SB3DI; + TSpeedButton *SB3DD; + TLabel *L1; + TLabel *LY; + TLabel *LX; + TGroupBox *GBA; + TSpeedButton *SBA1; + TSpeedButton *SBA2; + TSpeedButton *SBA3; + TCheckBox *CBFixed; + TCheckBox *CBZero; + TComboBox *CBList; + TSpeedButton *SBLW; + TSpeedButton *SBLD; + TGroupBox *GBY; + TComboBox *CBY; + TLabel *L2; + TSpeedButton *SBYW; + TSpeedButton *SBYD; + TPaintBox *PBox; + TFontDialog *FontDialog; + TColorDialog *ColorDialog; + TTimer *Timer; + TSpeedButton *SBFD; + TSpeedButton *SBFI; + TSpeedButton *SBA4; + TMemo *Msg; + TSpeedButton *SBMSG; + TLabel *L33; + TComboBox *CBOYW; + TUpDown *UDOYW; + TLabel *L34; + TComboBox *CBRot; + TUpDown *UDRot; + TSpeedButton *SBF1; + TSpeedButton *SBF2; + TSpeedButton *SBF3; + TSpeedButton *SBF4; + TSpeedButton *SBF5; + TSpeedButton *SBB; + TSpeedButton *SBI; + TSpeedButton *SBL; + void __fastcall FormDestroy(TObject *Sender); + void __fastcall PBoxPaint(TObject *Sender); + void __fastcall MemoChange(TObject *Sender); + void __fastcall TimerTimer(TObject *Sender); + void __fastcall SBG1Click(TObject *Sender); + void __fastcall PB1Click(TObject *Sender); + void __fastcall FormActivate(TObject *Sender); + void __fastcall FormDeactivate(TObject *Sender); + void __fastcall UDLClick(TObject *Sender, TUDBtnType Button); + void __fastcall FontBtnClick(TObject *Sender); + void __fastcall SBMClick(TObject *Sender); + void __fastcall SBCClick(TObject *Sender); + void __fastcall SBLWClick(TObject *Sender); + void __fastcall SBLDClick(TObject *Sender); + void __fastcall CBListChange(TObject *Sender); + void __fastcall SBYWClick(TObject *Sender); + void __fastcall SBYDClick(TObject *Sender); + void __fastcall CBYChange(TObject *Sender); + void __fastcall CBYKeyPress(TObject *Sender, char &Key); + void __fastcall CBYDropDown(TObject *Sender); + void __fastcall PBoxMouseDown(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + + void __fastcall SB3DIClick(TObject *Sender); + void __fastcall SBMSGClick(TObject *Sender); + void __fastcall MsgDblClick(TObject *Sender); + void __fastcall MemoStartDrag(TObject *Sender, + TDragObject *&DragObject); + void __fastcall MsgDragDrop(TObject *Sender, TObject *Source, int X, + int Y); + void __fastcall MsgDragOver(TObject *Sender, TObject *Source, int X, + int Y, TDragState State, bool &Accept); + void __fastcall MemoMouseDown(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + + void __fastcall MemoMouseMove(TObject *Sender, TShiftState Shift, + int X, int Y); + void __fastcall MemoMouseUp(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + void __fastcall PBoxMouseMove(TObject *Sender, TShiftState Shift, int X, + int Y); + void __fastcall PBoxMouseUp(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + void __fastcall FontBtnMouseDown(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + void __fastcall SBFClick(TObject *Sender); + void __fastcall SBFMouseDown(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + void __fastcall SBBClick(TObject *Sender); + void __fastcall SBIClick(TObject *Sender); + void __fastcall SBFDMouseDown(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + void __fastcall SBLClick(TObject *Sender); +private: + int m_DisEvent; + int m_DropProfile; + Graphics::TBitmap *m_pBitmap; + CItem m_Item; + int m_Change; + AnsiString m_FText; + int m_MouseXC, m_MouseYC, m_MouseHold; + int m_MemoX, m_MemoY, m_MemoDown; + + void __fastcall TopMost(void); + void __fastcall NoTopMost(void); + void __fastcall UpdateMemoFont(BYTE charset); + void __fastcall UpdateFText(void); + void __fastcall UpdateUI(void); + void __fastcall UpdateItem(CItem *pItem); + void __fastcall UpdateDialog(CItem *pItem); + void __fastcall UpdateBitmap(void); + void __fastcall UD3D(int a); + void __fastcall UpdateFontBtnHint(void); + int __fastcall GetSBFIndex(TObject *Sender); + void __fastcall SetSBF(int n); + + TCodeView *m_pCodeView; +public: +#if UseHWND + virtual __fastcall TTextDlgBox(HWND hWnd); +#else + virtual __fastcall TTextDlgBox(TComponent* AOwner); +#endif + + int __fastcall Execute(CItem *pItem); + +protected: + void __fastcall OnCodeViewClose(TMessage Message); + void __fastcall OnCodeInsert(TMessage Message); +BEGIN_MESSAGE_MAP + MESSAGE_HANDLER(WM_FORMCLOSE, TMessage, OnCodeViewClose) + MESSAGE_HANDLER(WM_CODEINSERT, TMessage, OnCodeInsert) +END_MESSAGE_MAP(TForm) +}; +//---------------------------------------------------------------------------- +//extern PACKAGE TTextDlgBox *TextDlgBox; +//---------------------------------------------------------------------------- +#endif + diff --git a/CItems/TEXTBOX/res/SB3DD.bmp b/CItems/TEXTBOX/res/SB3DD.bmp new file mode 100644 index 0000000..1c74fe6 Binary files /dev/null and b/CItems/TEXTBOX/res/SB3DD.bmp differ diff --git a/CItems/TEXTBOX/res/SB3DI.bmp b/CItems/TEXTBOX/res/SB3DI.bmp new file mode 100644 index 0000000..c162a1f Binary files /dev/null and b/CItems/TEXTBOX/res/SB3DI.bmp differ diff --git a/CItems/TEXTBOX/res/SBA1.bmp b/CItems/TEXTBOX/res/SBA1.bmp new file mode 100644 index 0000000..732f99b Binary files /dev/null and b/CItems/TEXTBOX/res/SBA1.bmp differ diff --git a/CItems/TEXTBOX/res/SBA2.bmp b/CItems/TEXTBOX/res/SBA2.bmp new file mode 100644 index 0000000..74ba1fb Binary files /dev/null and b/CItems/TEXTBOX/res/SBA2.bmp differ diff --git a/CItems/TEXTBOX/res/SBA3.bmp b/CItems/TEXTBOX/res/SBA3.bmp new file mode 100644 index 0000000..768947d Binary files /dev/null and b/CItems/TEXTBOX/res/SBA3.bmp differ diff --git a/CItems/TEXTBOX/res/SBA4.bmp b/CItems/TEXTBOX/res/SBA4.bmp new file mode 100644 index 0000000..efc171b Binary files /dev/null and b/CItems/TEXTBOX/res/SBA4.bmp differ diff --git a/CItems/TEXTBOX/res/SBC.bmp b/CItems/TEXTBOX/res/SBC.bmp new file mode 100644 index 0000000..3f96f65 Binary files /dev/null and b/CItems/TEXTBOX/res/SBC.bmp differ diff --git a/CItems/TEXTBOX/res/SBG1.bmp b/CItems/TEXTBOX/res/SBG1.bmp new file mode 100644 index 0000000..939b20f Binary files /dev/null and b/CItems/TEXTBOX/res/SBG1.bmp differ diff --git a/CItems/TEXTBOX/res/SBG2.bmp b/CItems/TEXTBOX/res/SBG2.bmp new file mode 100644 index 0000000..a737fbe Binary files /dev/null and b/CItems/TEXTBOX/res/SBG2.bmp differ diff --git a/CItems/TEXTBOX/res/SBG3.bmp b/CItems/TEXTBOX/res/SBG3.bmp new file mode 100644 index 0000000..3d99ffb Binary files /dev/null and b/CItems/TEXTBOX/res/SBG3.bmp differ diff --git a/CItems/TEXTBOX/res/SBG4.bmp b/CItems/TEXTBOX/res/SBG4.bmp new file mode 100644 index 0000000..8cb6c5e Binary files /dev/null and b/CItems/TEXTBOX/res/SBG4.bmp differ diff --git a/CItems/TEXTBOX/res/SBS1.bmp b/CItems/TEXTBOX/res/SBS1.bmp new file mode 100644 index 0000000..593f6fd Binary files /dev/null and b/CItems/TEXTBOX/res/SBS1.bmp differ diff --git a/CItems/TEXTBOX/res/SBS2.bmp b/CItems/TEXTBOX/res/SBS2.bmp new file mode 100644 index 0000000..3e9baf8 Binary files /dev/null and b/CItems/TEXTBOX/res/SBS2.bmp differ diff --git a/CItems/TEXTBOX/res/SBS3.bmp b/CItems/TEXTBOX/res/SBS3.bmp new file mode 100644 index 0000000..55fc484 Binary files /dev/null and b/CItems/TEXTBOX/res/SBS3.bmp differ diff --git a/CItems/TEXTBOX/res/SBS4.bmp b/CItems/TEXTBOX/res/SBS4.bmp new file mode 100644 index 0000000..b6e587b Binary files /dev/null and b/CItems/TEXTBOX/res/SBS4.bmp differ diff --git a/CItems/TextArt/About.cpp b/CItems/TextArt/About.cpp new file mode 100644 index 0000000..41af7ae --- /dev/null +++ b/CItems/TextArt/About.cpp @@ -0,0 +1,35 @@ +//--------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "About.h" +#include "ComLib.h" +//--------------------------------------------------------------------- +#pragma resource "*.dfm" +//TAboutDlg *AboutDlg; +//--------------------------------------------------------------------- +#if UseHWND +__fastcall TAboutDlg::TAboutDlg(HWND hWnd) + : TForm(hWnd) +#else +__fastcall TAboutDlg::TAboutDlg(TComponent* AOwner) + : TForm(AOwner) +#endif +{ + if( sys.m_MsgEng ){ + Font->Name = "Arial"; + Font->Charset = ANSI_CHARSET; + Caption = TTL; + } + else { + Caption = TTLJ; + } + LVer->Caption = VER" "AUT; + HICON hIcon = ::LoadIcon(HInstance, (LPCSTR)8000); + TIcon *pIcon = new TIcon; + pIcon->Handle = hIcon; + Image->Picture->Icon = pIcon; +} +//--------------------------------------------------------------------- + + \ No newline at end of file diff --git a/CItems/TextArt/About.dfm b/CItems/TextArt/About.dfm new file mode 100644 index 0000000..aaa1fcc Binary files /dev/null and b/CItems/TextArt/About.dfm differ diff --git a/CItems/TextArt/About.h b/CItems/TextArt/About.h new file mode 100644 index 0000000..21c19b6 --- /dev/null +++ b/CItems/TextArt/About.h @@ -0,0 +1,35 @@ +//---------------------------------------------------------------------------- +#ifndef OCRH +#define OCRH +//---------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ComLib.h" +//---------------------------------------------------------------------------- +class TAboutDlg : public TForm +{ +__published: + TButton *OKBtn; + TLabel *LVer; + TImage *Image; +private: +public: +#if UseHWND + virtual __fastcall TAboutDlg(HWND hWnd); +#else + virtual __fastcall TAboutDlg(TComponent* AOwner); +#endif +}; +//---------------------------------------------------------------------------- +//extern PACKAGE TAboutDlg *AboutDlg; +//---------------------------------------------------------------------------- +#endif + \ No newline at end of file diff --git a/CItems/TextArt/CodeVw.cpp b/CItems/TextArt/CodeVw.cpp new file mode 100644 index 0000000..00ba601 --- /dev/null +++ b/CItems/TextArt/CodeVw.cpp @@ -0,0 +1,479 @@ +//--------------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "CodeVw.h" +//--------------------------------------------------------------------------- +#pragma package(smart_init) +#pragma resource "*.dfm" +//TCodeView *CodeView; +//--------------------------------------------------------------------------- +__fastcall TCodeView::TCodeView(TComponent* Owner) + : TForm(Owner) +{ + if( sys.m_MsgEng ){ + Font->Name = "Arial"; + Font->Charset = ANSI_CHARSET; + +// Caption = "Character code list"; + SBClose->Caption = "Close"; + SBOut->Caption = "EUDC"; + SBEdit->Caption = "Edit"; + SBClear->Caption = "Clear"; + + SBFont->Hint = "Choose font"; + SBClear->Font->Size = 10; + SBOut->Font->Size = 10; + SBEdit->Font->Size = 10; + } + SBA->Hint = "Webdings"; + SBB->Hint = "Wingdings"; + SBC->Hint = "Symbol"; + SBUS->Hint = "English(ANSI)"; + SBJA->Hint = sys.m_MsgEng ? "Japanese(Shift-JIS)" : "日本語(シフトJIS)"; + SBHL->Hint = sys.m_MsgEng ? "Korean(Hangul)" : "韓国語(ハングル)"; + SBBY->Hint = sys.m_MsgEng ? "Chinese(GB2312)" : "中国語(簡体)"; + SBBV->Hint = sys.m_MsgEng ? "Chinese(BIG5)" : "中国語(繁体)"; + SBOut->Hint = "EUDC(End-user-defined-characters)"; + m_hWnd = NULL; + m_pFont = NULL; + m_Base = 0; + m_MouseDown = 0; + CheckFontCharset(); + SBJA->Enabled = sys.m_tFontFam[fmJA]; + SBHL->Enabled = sys.m_tFontFam[fmHL] || sys.m_tFontFam[fmJOHAB]; + SBBV->Enabled = sys.m_tFontFam[fmBV]; + SBBY->Enabled = sys.m_tFontFam[fmBY]; + + UpdateXW(); + int YW = GetSystemMetrics(SM_CYFULLSCREEN); + Left = sys.m_CodeLeft; + Top = sys.m_CodeTop; + if( Left < 0 ) Left = 0; + if( Top + Height > YW ) Top = YW - Height; + SBEdit->Enabled = sys.m_fEudc; + ShowHint = sys.m_WinNT; +} +//--------------------------------------------------------------------------- +WORD __fastcall TCodeView::GetEUDC(int y, int x) +{ +const WORD _tOut[]={0xf040, 0xf050, 0xf060, 0xf070, + 0xf080, 0xf090, 0xf0a0, 0xf0b0, + 0xf0c0, 0xf0d0, 0xf0e0, 0xf0f0, + 0xf140, 0xf150, 0xf160, 0xf170, +}; +const WORD _tOutHL[]={0xc9a0, 0xc9b0, 0xc9c0, 0xc9d0, + 0xc9e0, 0xc9f0, 0xfea0, 0xfeb0, + 0xfec0, 0xfed0, 0xfee0, 0xfef0, + 0, 0, 0, 0, +}; +const WORD _tOutBV[]={0xfa40, 0xfa50, 0xfa60, 0xfa70, + 0xfaa0, 0xfab0, 0xfac0, 0xfad0, + 0xfae0, 0xfaf0, 0xfb40, 0xfb50, + 0xfb60, 0xfb70, 0xfba0, 0xfbb0, +}; +const WORD _tOutBY[]={0xaaa0, 0xaab0, 0xaac0, 0xaad0, + 0xaae0, 0xaaf0, 0xaba0, 0xabb0, + 0xabc0, 0xabd0, 0xabe0, 0xabf0, + 0xaca0, 0xacb0, 0xacc0, 0xacd0, +}; + int c; + switch(m_pFont->Charset){ + case SHIFTJIS_CHARSET: + c = _tOut[y] + x; + if( (c==0xf07f)||(c==0xf0fd)||(c==0xf0fe)||(c==0xf0ff)||(c==0xf17f) ) c = 0; + break; + case HANGEUL_CHARSET: + c = _tOutHL[y]; + if( c ){ + c += x; + if( (c==0xc9a0)||(c==0xfea0)||(c==0xc9ff)||(c==0xfeff) ) c = 0; + } + break; + case CHINESEBIG5_CHARSET: // 台湾 + c = _tOutBV[y] + x; + if( (c==0xfa7f)||(c==0xfaa0)||(c==0xfaff)||(c==0xfb7f)||(c==0xfba0) ) c = 0; + break; + case 134: // 中国語簡略 + c = _tOutBY[y] + x; + if( (c==0xaaa0)||(c==0xaaff)||(c==0xaba0)||(c==0xabff)||(c==0xaca0) ) c = 0; + break; + default: + c = 0; + break; + } + return WORD(c); +} +//--------------------------------------------------------------------------- +void __fastcall TCodeView::UpdateTitle(void) +{ + AnsiString as = sys.m_MsgEng ? "Character code list" : "文字コード表"; + as += " ["; + as += m_pFont->Name; + AddStyle(as, m_pFont->Charset, 0); + as += "]"; + Caption = as; +} +//--------------------------------------------------------------------------- +void __fastcall TCodeView::UpdateXW(void) +{ + if( SBOut->Down || m_Base ){ + m_XW = PBox->Width / 17; + m_XW--; + m_YW1 = m_YW = PBox->Height / 17; + m_XW1 = PBox->Width - (m_XW * 16); + SBEdit->Visible = SBOut->Down; + UDMB->Visible = m_Base ? TRUE : FALSE; + } + else { + m_XW1 = m_XW = PBox->Width / 17; + m_YW1 = m_YW = PBox->Height / 17; + SBEdit->Visible = FALSE; + UDMB->Visible = FALSE; + } +} +//--------------------------------------------------------------------------- +void __fastcall TCodeView::SetPBoxFont(TCanvas *pCanvas) +{ + pCanvas->Font = m_pFont; + pCanvas->Font->Height = -(m_YW-5); + TFontStyles fs; + fs = Code2FontStyle(0); + pCanvas->Font->Style = fs; +} +//--------------------------------------------------------------------------- +void __fastcall TCodeView::DrawChar(TCanvas *pCanvas, int c, BOOL f) +{ + + int x = c % 16; + int y = c / 16; + char bf[32]; + LPSTR t = bf; + if( SBOut->Down ){ + c = GetEUDC(y, x); + } + else if( c ){ + c += m_Base; + } + if( !c ) return; + if( c & 0x00ff00 ) *t++ = BYTE(c>>8); + *t++ = BYTE(c); + *t = 0; + pCanvas->Font->Color = f ? clWhite : clBlack; + int fw = pCanvas->TextWidth(bf); + int fh = pCanvas->TextHeight(bf); + int xx = m_XW1 + x * m_XW + (m_XW-fw)/2; + int yy = m_YW1 + y * m_YW + (m_YW-fh)/2; + ::SetBkMode(pCanvas->Handle, TRANSPARENT); + pCanvas->TextOut(xx, yy, bf); +} +//--------------------------------------------------------------------------- +void __fastcall TCodeView::DrawCursor(TCanvas *pCanvas, int c, BOOL f) +{ + TRect rc; + + int x = c % 16; + int y = c / 16; + rc.Left = 1 + m_XW1 + x * m_XW; + rc.Top = 1 + m_YW1 + y * m_YW; + rc.Right = rc.Left + m_XW - 1; + rc.Bottom = rc.Top + m_YW - 1; + TColor col; + if( f ){ + col = clBlue; + } + else if( (!SBOut->Down && !m_Base) && m_tPfx[c] ){ + col = clGray; + } + else { + col = clWhite; + } + pCanvas->Pen->Color = col; + pCanvas->Brush->Color = col; + pCanvas->FillRect(rc); + DrawChar(pCanvas, c, f); +} +//--------------------------------------------------------------------------- +void __fastcall TCodeView::PBoxPaint(TObject *Sender) +{ + if( !m_pFont ) return; + + CWaitCursor w; + Graphics::TBitmap *pBmp = new Graphics::TBitmap; + pBmp->Width = PBox->Width; + pBmp->Height = PBox->Height; + TCanvas *pCanvas = pBmp->Canvas; + BOOL eud = SBOut->Down; + if( !m_Base && !eud ) memset(m_tPfx, 0, sizeof(m_tPfx)); + SetPBoxFont(pCanvas); + if( !eud ) SetMBCP(m_pFont->Charset); + int x, y, xx, yy, fw, fh; + char bf[16]; + int c = 0; + for( y = 0; y < 16; y++ ){ + for( x = 0; x < 16; x++ ){ + if( eud ){ + DrawChar(pCanvas, c, FALSE); + } + else { + if( !m_Base && (_mbsbtype((const unsigned char *)&c, 0) == _MBC_LEAD) ){ + m_tPfx[c] = TRUE; + DrawCursor(pCanvas, c, FALSE); + } + else { + DrawChar(pCanvas, c, FALSE); + } + } + c++; + } + } + pCanvas->Font = Font; + pCanvas->Pen->Color = clBlack; + ::SetBkMode(pCanvas->Handle, TRANSPARENT); + for( y = 0; y < 16; y++ ){ + wsprintf(bf, "%X", y); + fw = pCanvas->TextWidth(bf); + fh = pCanvas->TextHeight(bf); + xx = m_XW1 + y*m_XW + (m_XW-fw)/2; + yy = (m_YW1-fh)/2; + pCanvas->TextOut(xx, yy, bf); + + if( eud ){ + c = GetEUDC(y, 1) & 0xfff0; + if( c ){ + wsprintf(bf, "%04x", c); + } + else { + bf[0] = 0; + } + } + else if( m_Base ){ + wsprintf(bf, "%04x", y*16 + m_Base); + } + else { + wsprintf(bf, "%02X", y*16); + } + fw = pCanvas->TextWidth(bf); + fh = pCanvas->TextHeight(bf); + xx = (m_XW1-fw)/2; + yy = m_YW1 + y*m_YW + (m_YW-fh)/2; + pCanvas->TextOut(xx, yy, bf); + + pCanvas->Pen->Width = y ? 1 : 2; + pCanvas->MoveTo(0, m_YW1 + y*m_YW); + pCanvas->LineTo(PBox->Width, m_YW1 + y*m_YW); + pCanvas->MoveTo(m_XW1 + y*m_XW, 0); + pCanvas->LineTo(m_XW1 + y*m_XW, PBox->Height); + } + PBox->Canvas->Draw(0, 0, pBmp); + delete pBmp; + m_pfxCount = 0; + for( x = 0; x < 256; x++ ){ + if( m_tPfx[x] ){ + m_tPfxIdx[m_pfxCount] = x; + m_pfxCount++; + } + } + if( m_pfxCount != UDMB->Max ) UDMB->Max = short(m_pfxCount - 1); +} +//--------------------------------------------------------------------------- +void __fastcall TCodeView::ReqClose(void) +{ + sys.m_CodeLeft = Left; + sys.m_CodeTop = Top; + if( SBOut->Visible ) sys.m_CodeOut = SBOut->Down; + ::PostMessage(m_hWnd, WM_FORMCLOSE, 0, DWORD(this)); +} +//--------------------------------------------------------------------------- +void __fastcall TCodeView::FormClose(TObject *Sender, TCloseAction &Action) +{ + if( Action == caHide ) ReqClose(); +} +//--------------------------------------------------------------------------- +void __fastcall TCodeView::Execute(HWND hWnd, TFont *pFont) +{ + int f = Visible; + if( f && SBOut->Visible ) sys.m_CodeOut = SBOut->Down; + m_hWnd = hWnd; + m_pFont = pFont; + m_Base = 0; + SBOut->Visible = GetEUDC(0, 1) ? TRUE : FALSE; + SBOut->Down = SBOut->Visible && sys.m_CodeOut; + UpdateXW(); + UpdateTitle(); + Visible = TRUE; + if( f ) PBoxPaint(NULL); +} +//--------------------------------------------------------------------------- +void __fastcall TCodeView::SBCloseClick(TObject *Sender) +{ + Close(); +} +//--------------------------------------------------------------------------- +void __fastcall TCodeView::PBoxMouseDown(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( (Button == mbRight) && (m_Base || SBOut->Down) ){ + if( m_Base ){ + m_Base = 0; + } + else { + SBOut->Down = FALSE; + } + UpdateXW(); PBoxPaint(NULL); + return; + } + if( Button != mbLeft ) return; + + X -= m_XW1; + Y -= m_YW1; + if( X < 0 ) return; + if( Y < 0 ) return; + X /= m_XW; + Y /= m_YW; + if( X >= 16 ) X = 15; + if( Y >= 16 ) Y = 15; + int code = (Y * 16) + X; + m_MouseDown = code + 1; + TCanvas *pCanvas = PBox->Canvas; + SetPBoxFont(pCanvas); + DrawCursor(pCanvas, code, TRUE); + if( SBOut->Down ){ + code = GetEUDC(Y, X); + if( !code ) return; + } + else { + if( m_Base ){ + code |= m_Base | 0x00010000; +// PBoxPaint(NULL); + } + else if( m_tPfx[code] ){ + for( int i = 0; i < m_pfxCount; i++ ){ + if( m_tPfxIdx[i] == code ){ + UDMB->Position = short(i); + break; + } + } + m_Base = (code << 8); + UpdateXW(); PBoxPaint(NULL); + m_MouseDown = FALSE; + return; + } + } + ::PostMessage(m_hWnd, WM_CODEINSERT, code, DWORD(this)); +} +//--------------------------------------------------------------------------- +void __fastcall TCodeView::PBoxMouseUp(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( !m_MouseDown ) return; + + m_MouseDown--; + TCanvas *pCanvas = PBox->Canvas; + SetPBoxFont(pCanvas); + DrawCursor(pCanvas, m_MouseDown, FALSE); + m_MouseDown = 0; +} +//--------------------------------------------------------------------------- +void __fastcall TCodeView::SBClearClick(TObject *Sender) +{ + ::PostMessage(m_hWnd, WM_CODEINSERT, 0xffffffff, DWORD(this)); +} +//--------------------------------------------------------------------------- +void __fastcall TCodeView::SBFontClick(TObject *Sender) +{ + ::PostMessage(m_hWnd, WM_CODEINSERT, 0xfffffffe, DWORD(this)); +} +//--------------------------------------------------------------------------- +void __fastcall TCodeView::SBOutClick(TObject *Sender) +{ + m_Base = 0; + UpdateXW(); + PBoxPaint(NULL); +} +//--------------------------------------------------------------------------- +void __fastcall TCodeView::SBEditClick(TObject *Sender) +{ + LPCSTR pName = "EUDCEDIT.EXE"; + if( sys.m_Eudc.IsEmpty() ){ + char dir[MAX_PATH]; + char bf[512]; + if( ::GetSystemDirectory(dir, sizeof(dir)) ){ + wsprintf(bf, "%s\\%s", dir, pName); + if( IsFile(bf) ) sys.m_Eudc = bf; + } + if( sys.m_Eudc.IsEmpty() && ::GetWindowsDirectory(dir, sizeof(dir)) ){ + wsprintf(bf, "%s\\%s", dir, pName); + if( IsFile(bf) ) sys.m_Eudc = bf; + } + if( sys.m_Eudc.IsEmpty() ){ + wsprintf(bf, "%c:\\Program Files\\Accessories\\%s", dir[0], pName); + if( IsFile(bf) ) sys.m_Eudc = bf; + } + if( sys.m_Eudc.IsEmpty() ) sys.m_Eudc = pName; + } + if( ::WinExec(sys.m_Eudc.c_str(), SW_SHOWDEFAULT) > 31 ){ + ReqClose(); + } + else { + SBEdit->Enabled = FALSE; + sys.m_fEudc = FALSE; + } +} +//--------------------------------------------------------------------------- +void __fastcall TCodeView::SBAClick(TObject *Sender) +{ + DWORD dw = 0xfffffff2; + if( Sender == SBA ){ + dw = 0xfffffff0; + } + else if( Sender == SBB ){ + dw = 0xfffffff1; + } + ::PostMessage(m_hWnd, WM_CODEINSERT, dw, DWORD(this)); +} +//--------------------------------------------------------------------------- +void __fastcall TCodeView::SBUSClick(TObject *Sender) +{ + DWORD sw; + if( Sender == SBJA ){ + sw = 0xfffffff4; + } + else if( Sender == SBHL ){ + sw = 0xfffffff5; + } + else if( Sender == SBBY ){ + sw = 0xfffffff6; + } + else if( Sender == SBBV ){ + sw = 0xfffffff7; + } + else { + sw = 0xfffffff3; + } + ::PostMessage(m_hWnd, WM_CODEINSERT, sw, DWORD(this)); +} +//--------------------------------------------------------------------------- +void __fastcall TCodeView::UDMBClick(TObject *Sender, TUDBtnType Button) +{ + m_Base = m_tPfxIdx[UDMB->Position] << 8; + UpdateXW(); PBoxPaint(NULL); +} +//--------------------------------------------------------------------------- +int CALLBACK EnumFontFamExProc(ENUMLOGFONT FAR* lpelf, NEWTEXTMETRIC FAR* lpntm, DWORD FontType, LPARAM lParam) +{ // TCodeView *pView = (TCodeView*)lParam; switch(lpelf->elfLogFont.lfCharSet){ case SHIFTJIS_CHARSET: sys.m_tFontFam[fmJA] = TRUE; break; case HANGEUL_CHARSET: sys.m_tFontFam[fmHL] = TRUE; break; case JOHAB_CHARSET: sys.m_tFontFam[fmJOHAB] = TRUE; break; case CHINESEBIG5_CHARSET: // 台湾 sys.m_tFontFam[fmBV] = TRUE; break; case 134: // 中国語簡略 sys.m_tFontFam[fmBY] = TRUE; break; default: break; } int r = FALSE; for( int i = 0; i < fmEND; i++ ){ if( !sys.m_tFontFam[i] ) r = TRUE; } return r; } //--------------------------------------------------------------------------- +void __fastcall TCodeView::CheckFontCharset(void) +{ + if( sys.m_fFontFam ) return; + + sys.m_fFontFam = TRUE; + memset(sys.m_tFontFam, 0, sizeof(sys.m_tFontFam)); + LOGFONT logfont; + memset(&logfont, 0, sizeof(logfont)); + logfont.lfCharSet = DEFAULT_CHARSET; + HDC hDC = ::CreateDC("DISPLAY", NULL, NULL, NULL); + ::EnumFontFamiliesEx(hDC, &logfont, (int (_stdcall *)())EnumFontFamExProc, LPARAM(this), 0); + ::DeleteDC(hDC); +} +//--------------------------------------------------------------------------- + diff --git a/CItems/TextArt/CodeVw.dfm b/CItems/TextArt/CodeVw.dfm new file mode 100644 index 0000000..8d98b33 Binary files /dev/null and b/CItems/TextArt/CodeVw.dfm differ diff --git a/CItems/TextArt/CodeVw.h b/CItems/TextArt/CodeVw.h new file mode 100644 index 0000000..7808ed5 --- /dev/null +++ b/CItems/TextArt/CodeVw.h @@ -0,0 +1,81 @@ +//--------------------------------------------------------------------------- +#ifndef CodeVwH +#define CodeVwH +//--------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include + +#include "ComLib.h" +#include +#define WM_FORMCLOSE (WM_USER+410) +#define WM_CODEINSERT (WM_USER+411) +//--------------------------------------------------------------------------- +class TCodeView : public TForm +{ +__published: // IDE 管理のコンポーネント + TPanel *Panel; + TPaintBox *PBox; + TSpeedButton *SBClose; + TSpeedButton *SBClear; + TSpeedButton *SBFont; + TSpeedButton *SBOut; + TSpeedButton *SBEdit; + TSpeedButton *SBA; + TSpeedButton *SBB; + TSpeedButton *SBC; + TSpeedButton *SBUS; + TSpeedButton *SBJA; + TSpeedButton *SBHL; + TSpeedButton *SBBY; + TSpeedButton *SBBV; + TUpDown *UDMB; + void __fastcall PBoxPaint(TObject *Sender); + void __fastcall FormClose(TObject *Sender, TCloseAction &Action); + void __fastcall SBCloseClick(TObject *Sender); + void __fastcall PBoxMouseDown(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + void __fastcall SBClearClick(TObject *Sender); + void __fastcall SBFontClick(TObject *Sender); + + void __fastcall SBOutClick(TObject *Sender); + void __fastcall SBEditClick(TObject *Sender); + void __fastcall SBAClick(TObject *Sender); + + void __fastcall SBUSClick(TObject *Sender); + void __fastcall UDMBClick(TObject *Sender, TUDBtnType Button); + void __fastcall PBoxMouseUp(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); +private: // ユーザー宣言 + HWND m_hWnd; + TFont *m_pFont; + int m_XW1; + int m_YW1; + int m_XW; + int m_YW; + int m_MouseDown; + int m_Base; + BOOL m_tPfx[256]; + int m_pfxCount; + int m_tPfxIdx[256]; + void __fastcall UpdateTitle(void); + void __fastcall ReqClose(void); + void __fastcall UpdateXW(void); + void __fastcall SetPBoxFont(TCanvas *pCanvas); + void __fastcall DrawChar(TCanvas *pCanvas, int c, BOOL f); + void __fastcall DrawCursor(TCanvas *pCanvas, int c, BOOL f); + WORD __fastcall GetEUDC(int y, int x); + void __fastcall CheckFontCharset(void); + +public: // ユーザー宣言 + __fastcall TCodeView(TComponent* Owner); + + void __fastcall Execute(HWND hWnd, TFont *pFont); +}; +//--------------------------------------------------------------------------- +//extern PACKAGE TCodeView *CodeView; +//--------------------------------------------------------------------------- +#endif diff --git a/CItems/TextArt/Comlib.cpp b/CItems/TextArt/Comlib.cpp new file mode 100644 index 0000000..ec5f2eb --- /dev/null +++ b/CItems/TextArt/Comlib.cpp @@ -0,0 +1,3366 @@ +//--------------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "ComLib.h" +#include "TextDlg.h" +SYS sys; +//--------------------------------------------------------------------------- +void __fastcall InitSys(HINSTANCE hinst) +{ + sys.m_hInstance = hinst; + sys.m_dwVersion = 0; + sys.m_WinNT = 0; + sys.m_CodePage = 0; + sys.m_MsgEng = 0; + sys.m_BitPixel = 0; + sys.m_fLoadImageMenu = 0; + sys.m_fPasteImage = 0; + sys.m_fGetMacKey = 0; + sys.m_fConvMac = 0; + sys.m_fMultProc = 0; + sys.m_fColorComp = 0; + sys.m_fAdjCol = 0; + sys.m_fClip = 0; + sys.m_DefStgSize = 0; + sys.m_pDefStg = NULL; + sys.m_pTextList = NULL; + sys.m_pStyleList = NULL; + sys.m_BgnDir[0] = 0; + sys.m_pFontList = NULL; + sys.m_pBitmapTemp = NULL; + sys.m_DefaultPage = 0; + sys.m_SBMListState = 0; + + sys.m_MaskC1.c = clYellow; + sys.m_MaskC2.c = clBlack; + + sys.m_CodeLeft = 0; + sys.m_CodeTop = 0; + sys.m_CodeOut = 0; + + sys.m_fFontFam = FALSE; + memset(sys.m_tFontFam, 0, sizeof(sys.m_tFontFam)); + + sys.m_dwVersion = ::GetVersion(); + sys.m_WinNT = (sys.m_dwVersion < 0x80000000) ? TRUE : FALSE; + sys.m_CodePage = ::GetACP(); // Get codepage + + HDC hdcScreen = ::CreateDC("DISPLAY", NULL, NULL, NULL); + sys.m_BitPixel = ::GetDeviceCaps(hdcScreen, BITSPIXEL); + ::DeleteDC(hdcScreen); + + char bf[512]; + ::GetModuleFileName(hinst, bf, sizeof(bf)); + ::SetDirName(sys.m_BgnDir, bf); + + if( sys.m_BitPixel < 24 ){ + sys.m_pBitmapTemp = new Graphics::TBitmap; + sys.m_pBitmapTemp->Width = 1; + sys.m_pBitmapTemp->Height = 1; + } + + sys.m_fEudc = TRUE; + sys.m_Eudc = ""; +} +// +//--------------------------------------------------------------------------- +//void mcmFunc(DWORD index, FARPROC pFunc) +// +//MMSSTV calls this function at the first time, if the function was exported. +//You can use following functions which are in the MMSSTV. +// +// index : Index of the function. +// pFunc : Address of the function. +// +//indexes and functions are as follows. +// +// 0 : HBITMAP (__cdecl *mmLoadImageMenu)(int sw, int xw, int yw); +// sw - 0 : Invoke image-clipper (xw and yw are the size of the bitmap) +// sw - 1 : no image-clipper (xw and yw will be ignored) +// +// 1 : HBITMAP (__cdecl *mmLoadImage)(LPCSTR pName); +// pName is a pathname of the image (BMP, JPG, WMF) +// +// 2 : HBITMAP (__cdecl *mmLoadHistImage)(void); +// +// 3 : int (__cdecl *mmSaveImageMenu)(HBITMAP hb, LPCSTR pName, LPCSTR pFolder); +// pName is a filename of the image (BMP, JPG) +// pFolder is a folder name (if it is NULL, MMSSTV uses a default) +// +// 4 : int (__cdecl *mmSaveImage)(HBITMAP hb, LPCSTR pName); +// pName is a pathname of the image (BMP, JPG) +// +// 5 : HBITMAP (__cdecl *mmPasteImage)(int sw, int xw, int yw); +// sw - 0 : Invoke image-clipper (xw and yw are the size of the bitmap) +// sw - 1 : no image-clipper (xw and yw will be ignored) +// +// 6 : int (__cdecl *mmGetMacKey)(LPSTR pDest, int cbDest); +// Invoke macro dialog box and can choose keyword +// +// 7 : int (__cdecl *mmConvMac)(LPSTR pDest, LPCSTR pSrc, int cbDest); +// Convert macro keyword (pSrc) to the text (pDest) +// +// 8 : HBITMAP (__cdecl *mmCreateDIB)(int xw, int yw); +// Create 24bit DIB +// +// 9 : void (__cdecl *mmMultProc)(void); +// 10 : void (__cdecl *mmMultProcA)(void); +// Do decoding and encoding with the DSP in MMSSTV +// +// 11 : int (__cdecl *mmColorComp)(LPDWORD pCol); +// Invoke color components dialog and can choose a color component +// +extern "C" __declspec(dllexport) +void mcmFunc(DWORD index, FARPROC pFunc) +{ + switch(index){ + case 0: + sys.m_fLoadImageMenu = (mmLoadImageMenu)pFunc; + break; + case 5: + sys.m_fPasteImage = (mmPasteImage)pFunc; + break; + case 6: + sys.m_fGetMacKey = (mmGetMacKey)pFunc; + break; + case 7: + sys.m_fConvMac = (mmConvMac)pFunc; + break; + case 9: + sys.m_fMultProc = (mmMultProc)pFunc; + break; + case 11: + sys.m_fColorComp = (mmColorComp)pFunc; + break; + case 14: + sys.m_fAdjCol = (mmAdjCol)pFunc; + break; + case 15: + sys.m_fClip = (mmClip)pFunc; + break; + default: + break; + } +} +//--------------------------------------------------------------------------- +void __fastcall MultProc(void) +{ + if( sys.m_fMultProc ) sys.m_fMultProc(); +} +//--------------------------------------------------------------------------- +char __fastcall LastC(LPCSTR p) +{ + char c = 0; + + if( *p ){ + c = *(p + strlen(p) - 1); + } + return c; +} +//--------------------------------------------------------------------------- +void __fastcall SetCurDir(LPSTR t, int size) +{ + if( !::GetCurrentDirectory(size-1, t) ){ + *t = 0; + } + else { + if( LastC(t) != '\\' ){ + strcat(t, "\\"); + } + } +} +//--------------------------------------------------------------------------- +void __fastcall SetDirName(LPSTR t, LPCSTR pName) +{ + char drive[_MAX_DRIVE]; + char dir[_MAX_DIR]; + char name[_MAX_FNAME]; + char ext[_MAX_EXT]; + AnsiString Dir; + + ::_splitpath( pName, drive, dir, name, ext ); + Dir = drive; + Dir += dir; + strncpy(t, Dir.c_str(), 128); +} +//--------------------------------------------------------------------------- +int __fastcall IsFile(LPCSTR pName) +{ + WIN32_FIND_DATA fdata; + HANDLE hFind = ::FindFirstFile(pName, &fdata); + if( hFind != INVALID_HANDLE_VALUE ){ + FindClose(hFind); + return TRUE; + } + else { + return FALSE; + } +} +//--------------------------------------------------------------------------- +void __fastcall SetMBCP(BYTE charset) +{ + UINT cp; + switch(charset){ + case SHIFTJIS_CHARSET: + cp = 932; + break; + case HANGEUL_CHARSET: + cp = 949; + break; + case JOHAB_CHARSET: + cp = 1361; + break; + case CHINESEBIG5_CHARSET: // + cp = 950; + break; + case 134: // 簡略 + cp = 936; + break; + case ANSI_CHARSET: + case SYMBOL_CHARSET: + cp = 1252; + break; + default: + cp = _MB_CP_ANSI; + break; + } + if( cp != _MB_CP_ANSI ){ + CPINFO info; + if( GetCPInfo(cp, &info) != TRUE ){ + cp = _MB_CP_ANSI; + } + } + _setmbcp(cp); +} +///---------------------------------------------------------------- +void __fastcall Yen2CrLf(AnsiString &ws, AnsiString cs) +{ + _setmbcp(_MB_CP_ANSI); + ws = ""; + LPCSTR p; + int f; + int dlm = 0; + + p = cs.c_str(); + if( *p == 0x22 ){ + p++; + dlm++; + } + for( f = 0; *p; p++ ){ + if( f ){ + f = 0; + ws += *p; + } + else if( _mbsbtype((const unsigned char *)p, 0) == _MBC_LEAD ){ + f = 1; + ws += *p; + } + else if( *p == '\\' ){ + switch(*(p+1)){ + case 'r': + ws += "\r"; + p++; + break; + case 'n': + ws += "\n"; + p++; + break; + case 't': + ws += "\t"; + p++; + break; + case '\\': + ws += "\\"; + p++; + break; + default: + p++; + ws += *p; + break; + } + } + else if( !dlm || (*p!=0x22) || *(p+1) ){ + ws += *p; + } + } +} +//--------------------------------------------------------------------------- +void __fastcall CrLf2Yen(AnsiString &ws, AnsiString cs) +{ + _setmbcp(_MB_CP_ANSI); + ws = "\x22"; + LPCSTR p; + int f = 0; + + for( p = cs.c_str(); *p; p++ ){ + if( f ){ + ws += *p; + f = 0; + } + else if( _mbsbtype((const unsigned char *)p, 0) == _MBC_LEAD ){ + f = 1; + ws += *p; + } + else if( *p == 0x0d ){ + ws += "\\r"; + } + else if( *p == 0x0a ){ + ws += "\\n"; + } + else if( *p == '\t' ){ + ws += "\\t"; + } + else if( *p == '\\' ){ + ws += "\\\\"; + } + else { + ws += *p; + } + } + ws += "\x22"; +} +///---------------------------------------------------------------- +/// 文字列を数値に変換する +/// +int htoin(LPCSTR sp, int n) +{ + int d = 0; + + for( ; *sp && n; sp++, n-- ){ + d = d * 16; + d += *sp & 0x0f; + if( *sp >= 'A' ) d += 9; + } + return d; + +} +//--------------------------------------------------------------------------- +int __fastcall GetActiveIndex(TPageControl *pp) +{ + int i; + for( i = 0; i < pp->PageCount; i++ ){ + if( pp->ActivePage == pp->Pages[i] ) return i; + } + return 0; +} +//--------------------------------------------------------------------------- +void __fastcall LoadStringsFromIniFile(TStrings *pList, LPCSTR pSect, LPCSTR pName, int msg) +{ + char fname[512]; + sprintf(fname, "%s%s", sys.m_BgnDir, pName); + TMemIniFile *pIniFile = new TMemIniFile(fname); + int count = pIniFile->ReadInteger(pSect, "Count", 0); + int i; + AnsiString as; + for( i = 0; i < count; i++ ){ + char bf[32]; + sprintf(bf, "Text%u", i); + as = pIniFile->ReadString(pSect, bf, ""); + if( !as.IsEmpty() ){ + pList->Add(as.c_str()); + } + } + if( msg ){ + as = pIniFile->ReadString(pSect, "MSG", ""); + ::Yen2CrLf(sys.m_Msg, as); + } + delete pIniFile; +} +//--------------------------------------------------------------------------- +void __fastcall SaveStringsToIniFile(TStrings *pList, LPCSTR pSect, LPCSTR pName, int msg) +{ + char fname[512]; + sprintf(fname, "%s%s", sys.m_BgnDir, pName); + TMemIniFile *pIniFile = new TMemIniFile(fname); + pIniFile->WriteInteger(pSect, "Count", pList->Count); + int i; + for( i = 0; i < pList->Count; i++ ){ + char bf[32]; + sprintf(bf, "Text%u", i); + pIniFile->WriteString(pSect, bf, pList->Strings[i]); + } + if( msg ){ + AnsiString as; + ::CrLf2Yen(as, sys.m_Msg); + pIniFile->WriteString(pSect, "MSG", as); + } + pIniFile->UpdateFile(); + delete pIniFile; +} +//--------------------------------------------------------------------- +void __fastcall InitCustomColor(TColorDialog *tp) +{ + tp->CustomColors->Text = ""; +} +//--------------------------------------------------------------------- +void __fastcall AddCustomColor(TColorDialog *tp, TColor col) +{ + char bf[256]; + + sprintf(bf, "Color%c=%06lX", tp->CustomColors->Count + 'A', DWORD(col) & 0x00ffffff); + tp->CustomColors->Add(bf); +} +//--------------------------------------------------------------------- +LPSTR __fastcall ZeroConv(LPCSTR p, BYTE charset) +{ + LPSTR bp = new char[(strlen(p)*2) + 1]; + LPSTR t = bp; + int f = 0; + for( ; *p; p++ ){ + if( f ){ + *t++ = *p; + f = 0; + } + else if( _mbsbtype((const unsigned char *)p, 0) == _MBC_LEAD ){ + *t++ = *p; + f = 1; + } + else if( *p == '0' ){ + switch(charset){ + case SHIFTJIS_CHARSET: + *t++ = 0x83; + *t++ = 0xd3; + break; + case HANGEUL_CHARSET: + *t++ = 0xa8; // 0xa9 + *t++ = 0xaa; + break; + case CHINESEBIG5_CHARSET: // 台湾 + *t++ = 0xa3; + *t++ = 0x58; + break; + case 134: // 中国語簡略 + *t++ = 0xa6; + *t++ = 0xd5; + break; + default: + switch(sys.m_CodePage){ + case 949: // HANGEUL + *t++ = 0xa8; // 0xa9 + *t++ = 0xaa; + break; + case 950: // CHINESEBIG5 + *t++ = 0xa3; + *t++ = 0x58; + break; + case 936: // CHINESE 簡略 + *t++ = 0xa6; + *t++ = 0xd5; + break; + default: + *t++ = 'リ'; + break; + } + break; + } + } + else { + *t++ = *p; + } + } + *t = 0; + return bp; +} +#if 1 +//--------------------------------------------------------------------------- +void __fastcall ExecPB(LPCSTR pName) +{ + char bf[512]; + + MultProc(); + strcpy(bf, "mspaint.exe"); + if( pName != NULL ){ + wsprintf(&bf[strlen(bf)], " \x22%s\x22", pName); + } + if( ::WinExec(bf, SW_SHOWDEFAULT) <= 31 ){ + strcpy(bf, "PBRUSH.EXE"); + if( pName != NULL ){ + wsprintf(&bf[strlen(bf)], " \x22%s\x22", pName); + } + ::WinExec(bf, SW_SHOWDEFAULT); + } +} +//--------------------------------------------------------------------------- +HWND __fastcall IsPB(void) +{ + return FindWindow("MSPaintApp", NULL); +} +#endif +//--------------------------------------------------------------------------- +Graphics::TBitmap * __fastcall CreateBitmap(int xw, int yw) +{ + Graphics::TBitmap *pBitmap = new Graphics::TBitmap; + pBitmap->PixelFormat = pf24bit; + pBitmap->Width = xw; + pBitmap->Height = yw; + return pBitmap; +} +//--------------------------------------------------------------------------- +void __fastcall FillBitmap(Graphics::TBitmap *pDest, UCOL ucol) +{ + TRect rc; + rc.Left = rc.Top = 0; + rc.Right = pDest->Width; + rc.Bottom = pDest->Height; + pDest->Canvas->Brush->Color = ucol.c; + pDest->Canvas->FillRect(rc); +} +//--------------------------------------------------------------------------- +BOOL __fastcall IsSameBitmap(Graphics::TBitmap *pDest, Graphics::TBitmap *pSrc) +{ + int xw = pSrc->Width; + int yw = pSrc->Height; + if( pDest->Width != xw ) return FALSE; + if( pDest->Height != yw ) return FALSE; + int x, y; + for( y = 0; y < yw; y++ ){ + LPBYTE p = (LPBYTE)pSrc->ScanLine[y]; + LPBYTE t = (LPBYTE)pDest->ScanLine[y]; + for( x = 0; x < xw; x++ ){ + if( *p++ != *t++ ) return FALSE; + if( *p++ != *t++ ) return FALSE; + if( *p++ != *t++ ) return FALSE; + } + } + return TRUE; +} +//--------------------------------------------------------------------------- +void __fastcall FillBitmap(Graphics::TBitmap *pDest, TColor col) +{ + UCOL c; + c.c = col; + FillBitmap(pDest, c); +} +//--------------------------------------------------------------------------- +void __fastcall CopyBitmap(Graphics::TBitmap *pDest, Graphics::TBitmap *pSrc) +{ + pDest->Width = pSrc->Width; + pDest->Height = pSrc->Height; + pDest->Palette = NULL; + pDest->Canvas->Draw(0, 0, pSrc); +} +//--------------------------------------------------------------------------- +void __fastcall CopyBitmap(Graphics::TBitmap *pBitmap) +{ + int DataHandle; + HPALETTE APalette; + unsigned short MyFormat; + pBitmap->SaveToClipboardFormat(MyFormat, DataHandle, APalette); + Clipboard()->SetAsHandle(MyFormat,DataHandle); +} +//--------------------------------------------------------------------------- +//アスペクト比を保持する +void __fastcall KeepAspect(int &sx, int &sy, int bx, int by) +{ + double ass = double(sx) / double(sy); + double asb = double(bx) / double(by); + if( asb < ass ){ // ソースの方が横長 + sx = (double(sy) * asb) + 0.5; + } + else { + sy = (double(sx) / asb) + 0.5; + } +} +//--------------------------------------------------------------------------- +//伸縮コピー +void __fastcall StretchCopy(Graphics::TBitmap *pDest, Graphics::TBitmap *pSrc, int mode) +{ + TRect tc; + tc.Left = tc.Top = 0; + tc.Right = pDest->Width; tc.Bottom = pDest->Height; + int Sop = ::SetStretchBltMode(pDest->Canvas->Handle, mode); + pDest->Canvas->StretchDraw(tc, pSrc); + ::SetStretchBltMode(pDest->Canvas->Handle, Sop); +} +//--------------------------------------------------------------------------- +//アスペクト比を保持する +void __fastcall KeepAspectCopy(Graphics::TBitmap *pDest, int xm, int ym, Graphics::TBitmap *pSrc, int mode) +{ + if( (xm < pSrc->Width) || (ym < pSrc->Height) ){ + KeepAspect(xm, ym, pSrc->Width, pSrc->Height); + pDest->Width = xm; + pDest->Height = ym; + pDest->Palette = NULL; + TRect tc; + tc.Left = tc.Top = 0; + tc.Right = xm; tc.Bottom = ym; + int Sop = ::SetStretchBltMode(pDest->Canvas->Handle, mode); + pDest->Canvas->StretchDraw(tc, pSrc); + ::SetStretchBltMode(pDest->Canvas->Handle, Sop); + } + else { + CopyBitmap(pDest, pSrc); + } +} +#if 0 +//--------------------------------------------------------------------------- +//サイズ変更 +Graphics::TBitmap* __fastcall ChangeSize(Graphics::TBitmap *pSrc, int xw, int yw, int dir) +{ + int XW = xw; + int YW = yw; + if( dir ){ // 縮小 + XW /= 4; YW /= 4; + } + Graphics::TBitmap *pDest = CreateBitmap(XW, YW); + StretchCopy(pDest, pSrc, HALFTONE); + delete pSrc; + return pDest; +} +#endif +//--------------------------------------------------------------------------- +void __fastcall DrawBitmap(TPaintBox *pBox, Graphics::TBitmap *pBitmap) +{ + if( pBitmap == NULL ) return; + + if( (pBitmap->Width != pBox->Width)||(pBitmap->Height != pBox->Height) ){ + TRect rc; + rc.Left = 0; rc.Right = pBox->Width; + rc.Top = 0, rc.Bottom = pBox->Height; + int Sop = ::SetStretchBltMode(pBox->Canvas->Handle, HALFTONE); + pBox->Canvas->StretchDraw(rc, pBitmap); + ::SetStretchBltMode(pBox->Canvas->Handle, Sop); + } + else { + pBox->Canvas->Draw(0, 0, pBitmap); + } +} +//--------------------------------------------------------------------------- +UCOL __fastcall GetUniqueColor(UCOL ucol) +{ + ucol.d = ucol.d & 0x00f0f0f0; + UCOL c = ucol; + DWORD r; + + while(!c.d || (c.d == ucol.d)){ +#if (RANDMAX >= 0x00ffffff) + c.d = rand() & 0x00f0f0f0; +#else + r = rand(); r = r << 4; + c.b.r = (BYTE)(r & 0x00f0); r = r >> 4; + c.b.g = (BYTE)(r & 0x00f0); r = r >> 4; + c.b.b = (BYTE)(r & 0x00f0); +#endif + } + if( sys.m_pBitmapTemp ){ + sys.m_pBitmapTemp->Canvas->Pixels[0][0] = c.c; + c.c = sys.m_pBitmapTemp->Canvas->Pixels[0][0]; + } + return c; +} +//--------------------------------------------------------------------------- +UCOL __fastcall GetGrade2(UCOL s[2], int x, int xw) +{ + if( x < 0 ) x = 0; + if( x > xw ) x = xw; + UCOL r; + int c = s[0].b.b + ((int(s[1].b.b) - int(s[0].b.b)) * x / xw); + if( c < 0 ) c = 0; + if( c > 255 ) c = 255; + r.b.b = BYTE(c); + c = s[0].b.g + ((int(s[1].b.g) - int(s[0].b.g)) * x / xw); + if( c < 0 ) c = 0; + if( c > 255 ) c = 255; + r.b.g = BYTE(c); + c = s[0].b.r + ((int(s[1].b.r) - int(s[0].b.r)) * x / xw); + if( c < 0 ) c = 0; + if( c > 255 ) c = 255; + r.b.r = BYTE(c); + return r; +} +//--------------------------------------------------------------------------- +UCOL __fastcall GetGrade4(UCOL s[4], int x, int xw) +{ + int xw3 = xw/3; + if( x < xw3 ){ + return GetGrade2(s, x, xw3); + } + x -= xw3; + if( x < xw3 ){ + return GetGrade2(&s[1], x, xw3); + } + x -= xw3; + return GetGrade2(&s[2], x, xw3); +} +//--------------------------------------------------------------------------- +void __fastcall WriteString(TStream *ps, AnsiString &as) +{ + int len = as.Length(); + ps->Write(&len, sizeof(len)); + if( len ){ + ps->Write(as.c_str(), len); + } +} +void __fastcall ReadString(TStream *ps, AnsiString &as) +{ + as = ""; + int len; + ps->Read(&len, sizeof(len)); + if( len ){ + LPSTR p = new char[len+1]; + ps->Read(p, len); + p[len] = 0; + as = p; + delete p; + } +} +//--------------------------------------------------------------------------- +int FontStyle2Code(TFontStyles style) +{ + int code = 0; + + TFontStyles fa; + TFontStyles fb; + + fa << fsBold; + fb << fsBold; + fa *= style; + if( fa == fb ) code |= FSBOLD; + + fa >> fsBold; + fb >> fsBold; + fa << fsItalic; + fb << fsItalic; + fa *= style; + if( fa == fb ) code |= FSITALIC; + + fa >> fsItalic; + fb >> fsItalic; + fa << fsUnderline; + fb << fsUnderline; + fa *= style; + if( fa == fb ) code |= FSUNDERLINE; + + fa >> fsUnderline; + fb >> fsUnderline; + fa << fsStrikeOut; + fb << fsStrikeOut; + fa *= style; + if( fa == fb ) code |= FSSTRIKEOUT; + + return code; +} + +TFontStyles Code2FontStyle(int code) +{ + TFontStyles fs; + + if( code & FSBOLD ) fs << fsBold; + if( code & FSITALIC ) fs << fsItalic; + if( code & FSUNDERLINE ) fs << fsUnderline; + if( code & FSSTRIKEOUT ) fs << fsStrikeOut; + return fs; +} +//--------------------------------------------------------------------------- +void __fastcall WriteFont(TStream *ps, TFont *pFont) +{ + int d; + if( pFont != NULL ){ + d = 1; + ps->Write(&d, sizeof(d)); + WriteString(ps, pFont->Name); + d = pFont->Charset; + ps->Write(&d, sizeof(d)); + d = pFont->Height; + ps->Write(&d, sizeof(d)); + TFontStyles ts = pFont->Style; + d = FontStyle2Code(ts); + ps->Write(&d, sizeof(d)); + } + else { + d = 0; + ps->Write(&d, sizeof(d)); + } +} +//--------------------------------------------------------------------------- +TFont* __fastcall ReadFont(TStream *ps) +{ + TFont *pFont = NULL; + int d; + ps->Read(&d, sizeof(d)); + if( d == 1 ){ + pFont = new TFont; + AnsiString as; + ReadString(ps, as); + pFont->Name = as; + ps->Read(&d, sizeof(d)); + pFont->Charset = BYTE(d); + ps->Read(&d, sizeof(d)); + pFont->Height = d; + ps->Read(&d, sizeof(d)); + TFontStyles ts = Code2FontStyle(d); + pFont->Style = ts; + } + return pFont; +} +//--------------------------------------------------------------------------- +//CBitStreamクラス +///--------------------------------------------------------- +const BYTE _btt[]={0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01}; +///--------------------------------------------------------- +DWORD CBitStream::GetData(int n) +{ + const BYTE *pData; + DWORD d = 0; + for( int i = 0; i < n; i++, m_BitCount++ ){ + d = d << 1; + pData = &m_pBase[m_BitCount / 8]; + if( *pData & _btt[m_BitCount % 8] ) d |= 1; + } + return d; +} +///--------------------------------------------------------- +void CBitStream::GetText(LPSTR p, int n) +{ + for( int i = 0; i < n; i++, p++ ){ + *p = (char)GetData(8); + } + *p = 0; +} +///--------------------------------------------------------- +void CBitStream::PutData(DWORD d, int n) +{ + BYTE *pData; + DWORD mask = 1; + int i; + for( i = 1; i < n; i++ ) mask = mask << 1; + for( i = 0; i < n; i++, m_BitCount++, mask = mask >> 1 ){ + pData = &m_pBase[m_BitCount / 8]; + if( !(m_BitCount % 8) ) *pData = 0; + if( d & mask ) *pData |= _btt[m_BitCount % 8]; + } +} +///--------------------------------------------------------- +void CBitStream::PutText(LPCSTR p, int n) +{ + int i; + for( i = 0; (i < n) && *p; i++, p++ ){ + PutData(*p, 8); + } + for( ; i < n; i++ ) PutData(0, 8); +} +///--------------------------------------------------------- +BYTE CBitStream::GetSum(void) +{ + int n = (m_BitCount + 7) / 8; + BYTE sum = 0; + BYTE *pData = m_pBase; + for( int i = 0; i < n; i++, pData++ ){ + sum += *pData; + } + return sum; +} +///--------------------------------------------------------- +/// pBase : バッファのポインタ +/// n : チェックサムコードの位置(1 〜 ) +BOOL CheckSum(const void *pBase, int n) +{ + const BYTE *p = (const BYTE *)pBase; + n--; + BYTE sum = 0; + for( int i = 0; i < n; i++, p++ ){ + sum += *p; + } + return sum == *p; +} +///------------------------------------------------------ +/// +///CWaitCursor クラス +/// +CWaitCursor::CWaitCursor() +{ + sv = Screen->Cursor; + Screen->Cursor = crHourGlass; +} + +CWaitCursor::CWaitCursor(BOOL sw) +{ + sv = Screen->Cursor; + if( sw ){ + Screen->Cursor = crHourGlass; + } +} + +CWaitCursor::~CWaitCursor() +{ + Screen->Cursor = sv; +} + +void CWaitCursor::Delete(void) +{ + Screen->Cursor = sv; +} + +void CWaitCursor::Wait(void) +{ + Screen->Cursor = crHourGlass; +} +// +// +//--------------------------------------------------------------------------- +// CItem class +// +__fastcall CItem::CItem(void) +{ + m_pMemStream = NULL; + + m_Ver = 5; + m_Align = 0; + m_Grade = 0; + m_Shadow = 2; + m_Line = 1; + m_Zero = 0; + m_3d = 0x00000404; + m_Text = "de %m"; + m_pFont = NULL; + m_ColG[0].d = 255; + m_ColG[1].d = 16711935; + m_ColG[2].d = 65535; + m_ColG[3].d = 16776960; + m_ColB[0].c = clBlack; + m_ColB[1].c = clWhite; + m_ColB[2].c = clBlue; + m_ColB[3].c = clRed; + + m_ColF[0].d = RGB(255,0,0); + m_ColF[1].d = RGB(255,255,0); + m_ColF[2].d = RGB(0,255,0); + m_ColF[3].d = RGB(0,255,255); + m_ColF[4].d = RGB(0,0,255); + m_ColF[5].d = RGB(255,0,255); + + m_OrgXW = -1; + m_OrgYW = -1; + m_BmpXW = -1; + m_BmpYW = -1; + m_Draft = 0; + m_Pos = 0; + m_Ex = 0; + m_OYW = 0; + m_OYWS = 0; + m_Rot = 0; + m_Filter = 0; + + // Init as default + m_sperspect.ver = 3; + m_sperspect.flag = 1; + m_sperspect.ax = 3.0; m_sperspect.ay = 3.0; + m_sperspect.px = m_sperspect.py = m_sperspect.pz = 0.0; + m_sperspect.rz = -180; m_sperspect.rx = m_sperspect.ry = 0; + m_sperspect.v = 10; m_sperspect.s = 1.5; + m_sperspect.r = 0.0; + m_SC = 0; + + m_pMaskBmp = NULL; +} +//--------------------------------------------------------------------------- +__fastcall CItem::~CItem() +{ + if( m_pFont != NULL ) delete m_pFont; + if( m_pMemStream != NULL ) delete m_pMemStream; + if( m_pMaskBmp != NULL ) delete m_pMaskBmp; +} +//--------------------------------------------------------------------------- +void __fastcall CItem::LoadDefault(void) +{ + if( sys.m_pDefStg != NULL ) return; + + CItem *pItem = new CItem; + pItem->LoadFromInifile("Default", ININAME, FALSE); + LPCBYTE p = pItem->CreateStorage(&sys.m_DefStgSize); + sys.m_pDefStg = new BYTE[sys.m_DefStgSize]; + memcpy(sys.m_pDefStg, p, sys.m_DefStgSize); + pItem->DeleteStorage(p); + delete pItem; +} +//--------------------------------------------------------------------------- +void __fastcall CItem::UpdateDefault(void) +{ + if( sys.m_pDefStg != NULL ){ + delete sys.m_pDefStg; + sys.m_pDefStg = NULL; + } + LPCBYTE p = CreateStorage(&sys.m_DefStgSize); + sys.m_pDefStg = new BYTE[sys.m_DefStgSize]; + memcpy(sys.m_pDefStg, p, sys.m_DefStgSize); + DeleteStorage(p); +} +//--------------------------------------------------------------------------- +void __fastcall CItem::Create(LPCBYTE ps, DWORD size) +{ + if( (ps == NULL) || !size ){ + if( sys.m_pDefStg == NULL ) LoadDefault(); + ps = sys.m_pDefStg; + size = sys.m_DefStgSize; + } + + m_OYWS = 0; + TMemoryStream *pMem = new TMemoryStream; + pMem->Clear(); + pMem->Write(ps, size); + pMem->Seek(soFromBeginning, 0); + int ver; + pMem->Read(&ver, sizeof(ver)); + if( ver <= m_Ver ){ + pMem->Read(&m_BmpXW, sizeof(m_BmpXW)); + pMem->Read(&m_BmpYW, sizeof(m_BmpYW)); + if( ver <= 1 ){ + m_BmpXW = m_BmpYW = -1; + } + pMem->Read(&m_OrgXW, sizeof(m_OrgXW)); + pMem->Read(&m_OrgYW, sizeof(m_OrgYW)); + pMem->Read(&m_Align, sizeof(m_Align)); + pMem->Read(&m_Grade, sizeof(m_Grade)); + pMem->Read(&m_Shadow, sizeof(m_Shadow)); + pMem->Read(&m_Line, sizeof(m_Line)); + pMem->Read(&m_Zero, sizeof(m_Zero)); + pMem->Read(&m_3d, sizeof(m_3d)); + pMem->Read(&m_ColG, sizeof(m_ColG)); + pMem->Read(&m_ColB, sizeof(m_ColB)); + if( ver >= 5 ){ + pMem->Read(&m_ColF, sizeof(m_ColF)); + } + pMem->Read(&m_OYW, sizeof(m_OYW)); + pMem->Read(&m_Rot, sizeof(m_Rot)); + if( ver >= 4 ){ + pMem->Read(&m_Filter, sizeof(m_Filter)); + } + ReadString(pMem, m_Text); + if( m_pFont != NULL ) delete m_pFont; + m_pFont = ReadFont(pMem); + UpdateFont(); + pMem->Read(&m_SC, sizeof(m_SC)); + pMem->Read(&m_sperspect, sizeof(m_sperspect)); + if( m_pMaskBmp ){ + delete m_pMaskBmp; + m_pMaskBmp = NULL; + } + if( ver >= 3 ){ + int fBmp; + pMem->Read(&fBmp, sizeof(fBmp)); + if( fBmp ){ + m_pMaskBmp = new Graphics::TBitmap; + m_pMaskBmp->LoadFromStream(pMem); + } + } + } + delete pMem; +} +//--------------------------------------------------------------------------- +LPCBYTE __fastcall CItem::CreateStorage(LPDWORD pSize) +{ + ASSERT(pSize); + + if( m_pMemStream != NULL ) delete m_pMemStream; + m_pMemStream = new TMemoryStream; + m_pMemStream->Clear(); + m_Ver = 5; + m_pMemStream->Write(&m_Ver, sizeof(m_Ver)); + m_pMemStream->Write(&m_BmpXW, sizeof(m_BmpXW)); + m_pMemStream->Write(&m_BmpYW, sizeof(m_BmpYW)); + m_pMemStream->Write(&m_OrgXW, sizeof(m_OrgXW)); + m_pMemStream->Write(&m_OrgYW, sizeof(m_OrgYW)); + m_pMemStream->Write(&m_Align, sizeof(m_Align)); + m_pMemStream->Write(&m_Grade, sizeof(m_Grade)); + m_pMemStream->Write(&m_Shadow, sizeof(m_Shadow)); + m_pMemStream->Write(&m_Line, sizeof(m_Line)); + m_pMemStream->Write(&m_Zero, sizeof(m_Zero)); + m_pMemStream->Write(&m_3d, sizeof(m_3d)); + m_pMemStream->Write(&m_ColG, sizeof(m_ColG)); + m_pMemStream->Write(&m_ColB, sizeof(m_ColB)); + m_pMemStream->Write(&m_ColF, sizeof(m_ColF)); + int oyw = GetTrueOYW(); + m_pMemStream->Write(&oyw, sizeof(oyw)); + m_pMemStream->Write(&m_Rot, sizeof(m_Rot)); + m_pMemStream->Write(&m_Filter, sizeof(m_Filter)); + WriteString(m_pMemStream, m_Text); + WriteFont(m_pMemStream, m_pFont); + m_pMemStream->Write(&m_SC, sizeof(m_SC)); + m_pMemStream->Write(&m_sperspect, sizeof(m_sperspect)); + int fBmp = m_pMaskBmp != NULL; + m_pMemStream->Write(&fBmp, sizeof(fBmp)); + if( fBmp ) m_pMaskBmp->SaveToStream(m_pMemStream); + + *pSize = m_pMemStream->Position; + return (LPCBYTE)m_pMemStream->Memory; +} +//--------------------------------------------------------------------------- +void __fastcall SaveMaskToIniFile(Graphics::TBitmap *pBitmap, LPCSTR pSect, TMemIniFile *pIniFile) +{ + if( pBitmap ){ + int xw = pBitmap->Width; + int yw = pBitmap->Height; + pIniFile->WriteInteger(pSect, "M.Size", (yw << 16) + xw); + + LPBYTE bp = new BYTE[xw*yw*3+1]; + LPBYTE wp = bp; + int x, y; + for( y = 0; y < yw; y++ ){ + LPBYTE p = (LPBYTE)pBitmap->ScanLine[y]; + for( x = 0; x < xw; x++ ){ + *wp++ = *p++; + *wp++ = *p++; + *wp++ = *p++; + } + } + int bsize = xw * yw * 3 * 8; + int csize = (bsize + 6) / 7; + char *sp = new char[csize + 1]; + LPSTR t = sp; + CBitStream cb(bp); + BYTE c; + for( x = 0; x < csize; x++ ){ + c = (BYTE)(cb.GetData(7) + 0x30); + if( c >= 0x70 ) c += (BYTE)0x30; + *t++ = c; + } + *t = 0; + pIniFile->WriteString(pSect, "M.Data", sp); + delete sp; + delete bp; + } + else { + pIniFile->WriteInteger(pSect, "M.Size", 0); + pIniFile->WriteString(pSect, "M.Data", ""); + } +} +//--------------------------------------------------------------------------- +Graphics::TBitmap *__fastcall LoadMaskFromIniFile(LPCSTR pSect, TMemIniFile *pIniFile) +{ + Graphics::TBitmap *pBitmap = NULL; + int xw = pIniFile->ReadInteger(pSect, "M.Size", 0); + if( xw ){ + AnsiString as = pIniFile->ReadString(pSect, "M.Data", ""); + int yw = xw >> 16; + xw &= 0x0000ffff; + + int x, y; + int bsize = xw * yw * 3 * 8; + int csize = (bsize + 6) / 7; + LPBYTE bp = new BYTE[xw*yw*3+1]; + CBitStream cb(bp); + LPCSTR p = as.c_str(); + BYTE c; + for( x = 0; (x < csize) && *p; x++, p++ ){ + c = BYTE(*p - 0x30); + if( c >= 0x40 ) c -= (BYTE)0x30; + cb.PutData(c, 7); + } + pBitmap = CreateBitmap(xw, yw); + LPBYTE sp = bp; + for( y = 0; y < yw; y++ ){ + LPBYTE wp = (LPBYTE)pBitmap->ScanLine[y]; + for( x = 0; x < xw; x++ ){ + *wp++ = *sp++; + *wp++ = *sp++; + *wp++ = *sp++; + } + } + delete bp; + } + return pBitmap; +} +//--------------------------------------------------------------------------- +void __fastcall LoadFontFromInifile(TFont *pFont, LPCSTR pSect, TMemIniFile *pIniFile) +{ + if( pFont == NULL ) return; + + pFont->Name = pIniFile->ReadString(pSect, "FontName", pFont->Name); + pFont->Charset = (BYTE)pIniFile->ReadInteger(pSect, "FontSet", pFont->Charset); + pFont->Height = pIniFile->ReadInteger(pSect, "FontSize", pFont->Height); + TFontStyles ts = pFont->Style; + DWORD d = FontStyle2Code(ts); + d = pIniFile->ReadInteger(pSect, "FontStyle", d); + ts = Code2FontStyle(d); + pFont->Style = ts; +} +//--------------------------------------------------------------------------- +void __fastcall SaveFontToInifile(TFont *pFont, LPCSTR pSect, TMemIniFile *pIniFile) +{ + if( pFont == NULL ) return; + + pIniFile->WriteString(pSect, "FontName", pFont->Name); + pIniFile->WriteInteger(pSect, "FontSet", pFont->Charset); + pIniFile->WriteInteger(pSect, "FontSize", pFont->Height); + TFontStyles ts = pFont->Style; + DWORD d = FontStyle2Code(ts); + pIniFile->WriteInteger(pSect, "FontStyle", d); +} +//--------------------------------------------------------------------------- +void __fastcall SavePerToInifile(LPCSTR pSect, SPERSPECT *pPer, int sc, TMemIniFile *pIniFile) +{ + pIniFile->WriteInteger(pSect, "P.Flag", pPer->flag); + pIniFile->WriteInteger(pSect, "P.AX", pPer->ax * 1000); + pIniFile->WriteInteger(pSect, "P.AY", pPer->ay * 1000); + pIniFile->WriteInteger(pSect, "P.PX", pPer->px * 1000); + pIniFile->WriteInteger(pSect, "P.PY", pPer->py * 1000); + pIniFile->WriteInteger(pSect, "P.PZ", pPer->pz * 1000); + pIniFile->WriteInteger(pSect, "P.RX", pPer->rx * 1000); + pIniFile->WriteInteger(pSect, "P.RY", pPer->ry * 1000); + pIniFile->WriteInteger(pSect, "P.RZ", pPer->rz * 1000); + pIniFile->WriteInteger(pSect, "P.S", pPer->s * 1000); + pIniFile->WriteInteger(pSect, "P.R", pPer->r * 1000); + pIniFile->WriteInteger(pSect, "P.SC", sc); +} +//--------------------------------------------------------------------------- +void __fastcall LoadPerFromInifile(LPCSTR pSect, SPERSPECT *pPer, int &sc, TMemIniFile *pIniFile) +{ + pPer->flag = pIniFile->ReadInteger(pSect, "P.Flag", pPer->flag); + pPer->ax = pIniFile->ReadInteger(pSect, "P.AX", pPer->ax * 1000)/1000.0; + pPer->ay = pIniFile->ReadInteger(pSect, "P.AY", pPer->ay * 1000)/1000.0; + pPer->px = pIniFile->ReadInteger(pSect, "P.PX", pPer->px * 1000)/1000.0; + pPer->py = pIniFile->ReadInteger(pSect, "P.PY", pPer->py * 1000)/1000.0; + pPer->pz = pIniFile->ReadInteger(pSect, "P.PZ", pPer->pz * 1000)/1000.0; + pPer->rx = pIniFile->ReadInteger(pSect, "P.RX", pPer->rx * 1000)/1000.0; + pPer->ry = pIniFile->ReadInteger(pSect, "P.RY", pPer->ry * 1000)/1000.0; + pPer->rz = pIniFile->ReadInteger(pSect, "P.RZ", pPer->rz * 1000)/1000.0; + pPer->s = pIniFile->ReadInteger(pSect, "P.S", pPer->s * 1000)/1000.0; + pPer->r = pIniFile->ReadInteger(pSect, "P.R", pPer->r * 1000)/1000.0; + sc = pIniFile->ReadInteger(pSect, "P.SC", sc); +} +//--------------------------------------------------------------------------- +void __fastcall CItem::LoadFromInifile(LPCSTR pSect, LPCSTR pName, BOOL fMask) +{ + char fname[512]; + sprintf(fname, "%s%s", sys.m_BgnDir, pName); + TMemIniFile *pIniFile = new TMemIniFile(fname); + MultProc(); + m_Align = pIniFile->ReadInteger(pSect, "Align", m_Align); + m_Grade = pIniFile->ReadInteger(pSect, "Grade", m_Grade); + m_Shadow = pIniFile->ReadInteger(pSect, "Shadow", m_Shadow); + m_Line = pIniFile->ReadInteger(pSect, "Line", m_Line); + m_Zero = pIniFile->ReadInteger(pSect, "Zero", 0); + m_3d = pIniFile->ReadInteger(pSect, "3D", m_3d); + m_OYW = pIniFile->ReadInteger(pSect, "OYW", m_OYW); + m_Rot = pIniFile->ReadInteger(pSect, "Rot", m_Rot); + m_Filter = pIniFile->ReadInteger(pSect, "Filter", m_Filter); + int i; + for( i = 0; i < 4; i++ ){ + char bf[32]; + sprintf(bf, "ColG%u", i); + m_ColG[i].d = pIniFile->ReadInteger(pSect, bf, m_ColG[i].d); + sprintf(bf, "ColB%u", i); + m_ColB[i].d = pIniFile->ReadInteger(pSect, bf, m_ColB[i].d); + } + m_OrgXW = m_OrgYW = -1; + m_BmpXW = m_BmpYW = -1; + AnsiString as, cs; + ::CrLf2Yen(cs, m_Text); + as = pIniFile->ReadString(pSect, "Text", cs); + ::Yen2CrLf(m_Text, as); + + if( pIniFile->ReadInteger(pSect, "Font", 0) ){ + if( m_pFont != NULL ) delete m_pFont; + m_pFont = new TFont; + LoadFontFromInifile(m_pFont, pSect, pIniFile); + UpdateFont(); + } + LoadPerFromInifile(pSect, &m_sperspect, m_SC, pIniFile); + + if( fMask ){ + if( m_pMaskBmp ) delete m_pMaskBmp; + m_pMaskBmp = LoadMaskFromIniFile(pSect, pIniFile); + } + delete pIniFile; +} +//--------------------------------------------------------------------------- +void __fastcall CItem::SaveToInifile(LPCSTR pSect, LPCSTR pName, BOOL fMask) +{ + char fname[512]; + sprintf(fname, "%s%s", sys.m_BgnDir, pName); + + TMemIniFile *pIniFile = new TMemIniFile(fname); + MultProc(); + try { + pIniFile->WriteInteger(pSect, "Align", m_Align); + pIniFile->WriteInteger(pSect, "Grade", m_Grade); + pIniFile->WriteInteger(pSect, "Shadow", m_Shadow); + pIniFile->WriteInteger(pSect, "Line", m_Line); + pIniFile->WriteInteger(pSect, "Zero", m_Zero); + pIniFile->WriteInteger(pSect, "3D", m_3d); + pIniFile->WriteInteger(pSect, "OYW", GetTrueOYW()); + pIniFile->WriteInteger(pSect, "Rot", m_Rot); + pIniFile->WriteInteger(pSect, "Filter", m_Filter); + int i; + for( i = 0; i < 4; i++ ){ + char bf[32]; + sprintf(bf, "ColG%u", i); + pIniFile->WriteInteger(pSect, bf, m_ColG[i].d); + sprintf(bf, "ColB%u", i); + pIniFile->WriteInteger(pSect, bf, m_ColB[i].d); + } + pIniFile->WriteInteger(pSect, "Width", m_BmpXW); + pIniFile->WriteInteger(pSect, "Height", m_BmpYW); + AnsiString cs; + ::CrLf2Yen(cs, m_Text); + pIniFile->WriteString(pSect, "Text", cs); + + pIniFile->WriteInteger(pSect, "Font", m_pFont != NULL ? 1 : 0); + if( m_pFont != NULL ){ + SaveFontToInifile(m_pFont, pSect, pIniFile); + } + SavePerToInifile(pSect, &m_sperspect, m_SC, pIniFile); + if( fMask ){ + SaveMaskToIniFile(m_pMaskBmp, pSect, pIniFile); + } + } + catch(...){ + } + pIniFile->UpdateFile(); + delete pIniFile; +} +//--------------------------------------------------------------------------- +void __fastcall CItem::DeleteInifile(LPCSTR pSect, LPCSTR pName) +{ + char fname[512]; + sprintf(fname, "%s%s", sys.m_BgnDir, pName); + + TMemIniFile *pIniFile = new TMemIniFile(fname); + MultProc(); + try { + pIniFile->EraseSection(pSect); + } + catch(...){ + } + pIniFile->UpdateFile(); + delete pIniFile; +} +//--------------------------------------------------------------------------- +DWORD __fastcall CItem::GetItemType(void) +{ + DWORD type = 0x00010002; // Active text as Overlay + switch(m_Align){ + case 1: + type |= 0x00400000; // align center + break; + case 2: + type |= 0x00100000; // aling right-top + break; + case 3: + type |= m_Pos << 20; + type |= 0x00000010; + break; + default: + break; + } + return type; +} +//--------------------------------------------------------------------------- +void __fastcall CItem::SetPos(DWORD pos, DWORD size, DWORD tsize) +{ + int x = pos & 0x0000ffff; + int y = pos >> 16; + if( x & 0x00008000 ) x |= 0xffff8000; + if( y & 0x00008000 ) y |= 0xffff8000; + int xw = size & 0x0000ffff; + int yw = size >> 16; + int txw = tsize & 0x0000ffff; + int tyw = tsize >> 16; + + int xr = x + xw; + int yb = y + yw; + m_Pos = 0; + if( xr > (txw * 7/8) ){ + m_Pos |= 1; + } + else if( x > (txw / 8) ){ + m_Pos |= 4; + } + if( yb > (tyw * 6/8) ){ + m_Pos |= 2; + } + else if( y > (tyw * 2 / 8) ){ + m_Pos |= 8; + } +} +//--------------------------------------------------------------------------- +void __fastcall CItem::DeleteStorage(LPCBYTE pStorage) +{ + if( m_pMemStream != NULL ){ + ASSERT(pStorage == (LPCBYTE)m_pMemStream->Memory); + delete m_pMemStream; + m_pMemStream = NULL; + } +} +//--------------------------------------------------------------------------- +int __fastcall CItem::GetTrueOYW(void) +{ + int oyw = int((SHORT)m_OYW); + if( m_OYWS ){ + int fwh = m_OYWS >> 16; + int fwl = m_OYWS & 0x0000ffff; + if( fwl ) oyw = oyw * fwh / fwl; + } + return oyw; +} +//--------------------------------------------------------------------------- +void __fastcall CItem::Copy(CItem *sp) +{ + ASSERT(sp); + + DWORD size; + LPCBYTE ps = sp->CreateStorage(&size); + Create(ps, size); + sp->DeleteStorage(ps); + m_Back = sp->m_Back; + m_OrgXW = m_OrgYW = -1; +// m_TextXW = m_TextYW = -1; + m_Pos = sp->m_Pos; + m_Ex = sp->m_Ex; +} +//--------------------------------------------------------------------------- +DWORD __fastcall CItem::GetOrgSize(void) +{ + if(m_OrgXW >= 0){ + DWORD w = m_OrgXW; + DWORD h = m_OrgYW; + return (h << 16) + w; + } + else { + return (128 << 16) + 160; + } +} +//--------------------------------------------------------------------------- +void __fastcall CItem::SetFontSize(Graphics::TBitmap *pDest) +{ + ASSERT(m_OrgXW > 0); + ASSERT(m_OrgYW > 0); + if( (m_OrgXW <= 0) || (m_OrgYW <= 0) ) return; + + int size = m_pFont->Height; + if( m_OrgXW < pDest->Width ){ + size = size * pDest->Width / m_OrgXW; + if( size == m_pFont->Height ) size--; + } + else if( m_OrgYW < pDest->Height ){ + size = size * pDest->Height / m_OrgYW; + if( size == m_pFont->Height ) size--; + } + else if( m_OrgXW > pDest->Width ){ + size = size * pDest->Width / m_OrgXW; + if( size == m_pFont->Height ) size++; + } + else if( m_OrgYW > pDest->Height ){ + size = size * pDest->Height / m_OrgYW; + if( size == m_pFont->Height ) size++; + } + if( !size ) size = -1; + m_pFont->Height = size; +} +//--------------------------------------------------------------------------- +static int __fastcall TextWidth(TCanvas *pCanvas, LPCSTR p) +{ + char bf[8]; + + int w = 0; + while(*p){ + if( (_mbsbtype((const unsigned char *)p, 0) == _MBC_LEAD) && *(p+1) ){ + bf[0] = *p++; bf[1] = *p++; bf[2] = 0; + } + else { + bf[0] = *p++; bf[1] = 0; + } + w += pCanvas->TextWidth(bf); + } + return w; +} +//--------------------------------------------------------------------------- +int __fastcall CItem::GetMaxWH(int &W, int &H, Graphics::TBitmap *pDest, LPCSTR pText) +{ + TCanvas *pCanvas = pDest->Canvas; + int lf = 1; + int n = 0; + W = H = 0; + char bf[1024]; + int w, h; + LPSTR t; + for( t = bf; 1; pText++ ){ + if( *pText != 0x0d ){ + if( (*pText == 0x0a) || !*pText ){ + if( lf && *pText ){ + n++; + } + *t = 0; + if( bf[0] ){ + if( m_Grade == 4 ){ + w = TextWidth(pCanvas, bf); + h = pCanvas->TextHeight(bf); + } + else { + DWORD wh = ::GetTabbedTextExtent(pCanvas->Handle, bf, strlen(bf), 0, NULL); + w = wh & 0x0000ffff; h = wh >> 16; + } + if( H < h ) H = h; + if( W < w ) W = w; + } + if( !*pText ) break; + lf = 1; + t = bf; + } + else { + if( lf ){ + lf = 0; + n++; + } + *t++ = *pText; + } + } + } + return n; +} +//--------------------------------------------------------------------------- +UINT __fastcall CItem::GetPosFormat(void) +{ + UINT wFormat; + switch(m_Align){ + case 1: + wFormat = DT_CENTER; + break; + case 2: + wFormat = DT_RIGHT; + break; + case 3: + if( m_Pos & 4 ){ + wFormat = DT_CENTER; + } + else { + wFormat = (m_Pos & 1) ? DT_RIGHT : DT_LEFT; + } + break; + default: + wFormat = DT_LEFT; + break; + } + return wFormat; +} +//--------------------------------------------------------------------------- +UINT __fastcall CItem::GetDrawFormat(void) +{ + UINT wFormat = DT_NOPREFIX|DT_NOCLIP|DT_EXPANDTABS; + if( m_Rot ){ + wFormat |= DT_LEFT; + } + else { + wFormat |= GetPosFormat(); + } + return wFormat; +} +//--------------------------------------------------------------------------- +void __fastcall CItem::GetFont(LOGFONT *pLogfont) +{ + memset(pLogfont, 0, sizeof(LOGFONT)); + pLogfont->lfHeight = m_pFont->Height; + pLogfont->lfWidth = 0; + pLogfont->lfEscapement = m_Rot * 10; + pLogfont->lfOrientation = m_Rot * 10; + TFontStyles ts = m_pFont->Style; + int fsw = FontStyle2Code(ts); + pLogfont->lfWeight = fsw & FSBOLD ? 700 : 400; + pLogfont->lfItalic = BYTE(fsw & FSITALIC ? TRUE : FALSE); + pLogfont->lfUnderline = BYTE(fsw & FSUNDERLINE ? TRUE : FALSE); + pLogfont->lfStrikeOut = BYTE(fsw & FSSTRIKEOUT ? TRUE : FALSE); + pLogfont->lfCharSet = m_pFont->Charset; + pLogfont->lfOutPrecision = OUT_CHARACTER_PRECIS; + pLogfont->lfClipPrecision = CLIP_DEFAULT_PRECIS; + pLogfont->lfQuality = NONANTIALIASED_QUALITY; + pLogfont->lfPitchAndFamily = DEFAULT_PITCH; + strcpy(pLogfont->lfFaceName, m_pFont->Name.c_str()); +} +//--------------------------------------------------------------------------- +void __fastcall CItem::SetFont(LOGFONT *pLogfont) +{ + if( m_pFont == NULL ) m_pFont = new TFont; + m_pFont->Name = pLogfont->lfFaceName; + m_pFont->Charset = pLogfont->lfCharSet; + if( pLogfont->lfHeight ){ + m_pFont->Height = pLogfont->lfHeight; + } + else { + m_pFont->Size = pLogfont->lfWidth; + } + DWORD d = 0; + if( pLogfont->lfWeight > 600 ) d |= FSBOLD; + if( pLogfont->lfItalic ) d |= FSITALIC; + if( pLogfont->lfUnderline ) d |= FSUNDERLINE; + if( pLogfont->lfStrikeOut ) d |= FSSTRIKEOUT; + m_fsCode = d; + TFontStyles ts = Code2FontStyle(d); + m_pFont->Style = ts; + m_Rot = pLogfont->lfEscapement / 10; +} +//--------------------------------------------------------------------------- +static TColor __fastcall GetIndexColor(int index) +{ + index++; + UCOL c; + c.d = 0; + c.b.r = BYTE(index & 1 ? 255 : 0); + c.b.g = BYTE(index & 2 ? 255 : 0); + c.b.b = BYTE(index & 4 ? 255 : 0); + return c.c; +} +//--------------------------------------------------------------------------- +static int __fastcall GetColorIndex(UCOL c) +{ + int n = 0; + if( c.b.r >= 0x80 ) n |= 1; + if( c.b.g >= 0x80 ) n |= 2; + if( c.b.b >= 0x80 ) n |= 4; + n--; + if( (n < 0) || (n >= 6) ) n = 0; + return n; +} +//--------------------------------------------------------------------------- +void __fastcall CItem::DrawText(RECT rc, Graphics::TBitmap *pDest, LPCSTR pText, UCOL ucol) +{ + if( m_Rot || (m_Ex & DISFONTSMOOTHING) || (m_Grade==4) ){ + LOGFONT lf; +#if 1 + GetFont(&lf); +#else + memset(&lf, 0, sizeof(lf)); + lf.lfHeight = m_pFont->Height; + lf.lfWidth = 0; + lf.lfEscapement = m_Rot * 10; + lf.lfOrientation = m_Rot * 10; + TFontStyles ts = m_pFont->Style; + int fsw = FontStyle2Code(ts); + lf.lfWeight = fsw & FSBOLD ? 700 : 400; + lf.lfItalic = BYTE(fsw & FSITALIC ? TRUE : FALSE); + lf.lfUnderline = BYTE(fsw & FSUNDERLINE ? TRUE : FALSE); + lf.lfStrikeOut = BYTE(fsw & FSSTRIKEOUT ? TRUE : FALSE); + lf.lfCharSet = m_pFont->Charset; + lf.lfOutPrecision = OUT_CHARACTER_PRECIS; + lf.lfClipPrecision = CLIP_DEFAULT_PRECIS; + lf.lfQuality = NONANTIALIASED_QUALITY; + lf.lfPitchAndFamily = DEFAULT_PITCH; + strcpy(lf.lfFaceName, m_pFont->Name.c_str()); +#endif + pDest->Canvas->Font->Handle = CreateFontIndirect(&lf); + } + else { + pDest->Canvas->Font = m_pFont; + } + pDest->Canvas->Font->Color = ucol.c; + + int nc = 0; + if( m_OYWC || m_Rot || (m_Grade == 4) ){ + TStringList *pList = new TStringList; + pList->Text = pText; + UINT wFormat = GetPosFormat(); + int xw = rc.right - rc.left; + for( int i = 0; i < pList->Count; i++ ){ + RECT trc; + trc = rc; + int txw = pDest->Canvas->TextWidth(pList->Strings[i].c_str()); + if( m_Rot ){ // 回転時の位置補正 + int x; + switch(wFormat){ + case DT_CENTER: + x = (xw - txw)/2; + trc.left += x * m_CosX; + trc.right += x * m_CosX; + trc.top -= x * m_SinX; + break; + case DT_RIGHT: + x = xw - txw; + trc.left += x * m_CosX; + trc.right += x * m_CosX; + trc.top -= x * m_SinX; + break; + } + } + DrawText_(trc, pDest, pList->Strings[i].c_str(), nc); + if( m_Rot ){ + rc.left += (m_FW + m_OYWC) * m_SinX; + rc.right += (m_FW + m_OYWC) * m_SinX; + rc.top += (m_FW + m_OYWC) * m_CosX; + } + else { + rc.top += (m_FW + m_OYWC); + } + } + delete pList; + } + else { + DrawText_(rc, pDest, pText, nc); + } +} +//--------------------------------------------------------------------------- +void __fastcall CItem::DrawText_(RECT rc, Graphics::TBitmap *pDest, LPCSTR pText, int &nc) +{ + TCanvas *pCanvas = pDest->Canvas; + HDC hdc = pCanvas->Handle; + ::SetBkMode(hdc, TRANSPARENT); + if( (m_Grade == 4) && (m_pMaskBmp == NULL) ){ + double x = rc.left; + double y = rc.top; + char bf[32]; + int fw = TextWidth(pCanvas, pText); + if( !m_Rot ){ + int pos = GetPosFormat(); + switch(pos){ + case DT_CENTER: + fw = ((rc.right-rc.left)-fw)/2; + x += fw; + break; + case DT_RIGHT: + fw = ((rc.right-rc.left)-fw); + x += fw; + break; + } + } + while(*pText){ + if( (_mbsbtype((const unsigned char *)pText, 0) == _MBC_LEAD) && *(pText+1) ){ + bf[0] = *pText++; bf[1] = *pText++; bf[2] = 0; + } + else { + bf[0] = *pText++; bf[1] = 0; + } + pCanvas->Font->Color = GetIndexColor(nc); + fw = pCanvas->TextWidth(bf); +// rc.left = x; rc.top = y; + pCanvas->TextOut(x, y, bf); + if( m_Rot ){ + x += fw * m_CosX; + y -= fw * m_SinX; + } + else { + x += fw; + } + if( (bf[0] != ' ') && strcmp(bf, " ") ){ + nc++; + if( nc >= AN(m_ColF) ) nc = 0; + } + } + } + else if( m_Row >= 2 ){ + ::DrawText(hdc, pText, strlen(pText), &rc, GetDrawFormat()); + } + else { + pCanvas->TextOut(rc.left, rc.top, pText); + } +} +#if 0 +//--------------------------------------------------------------------------- +void __fastcall CItem::DrawTrans(Graphics::TBitmap *pDest, Graphics::TBitmap *pSrc, LPBYTE pTbl) +{ + int xw = pSrc->Width; + int yw = pSrc->Height; + LPBYTE sp, tp; + int x, y; + for( y = 0; y < yw; y++ ){ + sp = (LPBYTE)pSrc->ScanLine[y]; + tp = (LPBYTE)pDest->ScanLine[y]; + for( x = 0; x < xw; x++, pTbl++ ){ + if( *pTbl ){ + *tp++ = *sp++; + *tp++ = *sp++; + *tp++ = *sp++; + } + else { + tp += 3; + sp += 3; + } + } + } +} +#endif +//--------------------------------------------------------------------------- +void __fastcall CItem::CreateTable(Graphics::TBitmap *pDest) +{ + int XW = pDest->Width; + int YW = pDest->Height; + m_XW = XW; + m_YW = YW; + + LPBYTE pTbl = new BYTE[XW*YW]; + memset(pTbl, 0, XW*YW); + LPBYTE wp = pTbl; + int x, y; + + LPBYTE *pAdr = new BYTE*[YW]; + BYTE br = m_cBack.b.r; + BYTE bg = m_cBack.b.g; + BYTE bb = m_cBack.b.b; + if( m_Grade != 4 ){ + for( y = 0; y < YW; y++ ){ + LPBYTE p = (LPBYTE)pDest->ScanLine[y]; + pAdr[y] = p; + for( x = 0; x < XW; x++, wp++, p+=3 ){ + if( (bb != *p) || (bg != *(p+1)) || (br != *(p+2)) ){ + *wp = 0x80; + } + } + } + } + else { + UCOL c; + c.d = 0; + for( y = 0; y < YW; y++ ){ + LPBYTE p = (LPBYTE)pDest->ScanLine[y]; + pAdr[y] = p; + for( x = 0; x < XW; x++, wp++ ){ + c.b.b = *p++; + c.b.g = *p++; + c.b.r = *p++; + if( (bb != c.b.b) || (bg != c.b.g) || (br != c.b.r) ){ + *wp = BYTE(0x80 + GetColorIndex(c)); + } + } + } + } + m_pAdr = pAdr; + m_pTbl = pTbl; +} +//--------------------------------------------------------------------------- +int __fastcall CItem::EditDialog(HWND hWnd) +{ + TTextDlgBox *pBox = new TTextDlgBox(NULL); + if( pBox == NULL ) return FALSE; + + int r = pBox->Execute(this); + delete pBox; + if( r == TRUE ) UpdateDefault(); + return r; +} +//--------------------------------------------------------------------------- +int __fastcall CItem::FontDialog(HWND hWnd) +{ + if( m_pFont == NULL ) m_pFont = new TFont; + TFontDialog *pDlg = new TFontDialog(NULL); + if( pDlg == NULL ) return FALSE; + + ASSERT(m_pFont); + pDlg->Font->Assign(m_pFont); + int hOrg = pDlg->Font->Height; + int h = hOrg / 4; + pDlg->Font->Height = h; + pDlg->Font->Color = m_ColG[0].c; + MultProc(); + int r = pDlg->Execute(); + MultProc(); + if( r == TRUE ){ + m_pFont->Assign(pDlg->Font); + if( h != m_pFont->Height ){ + hOrg = m_pFont->Height * 4; + } + m_pFont->Height = hOrg; + m_ColG[0].c = pDlg->Font->Color; + UpdateFont(); + UpdateDefault(); + } + delete pDlg; + return r; +} +//--------------------------------------------------------------------------- +void __fastcall CItem::UpdateFont(void) +{ + if( m_pFont == NULL ) return; + + TFontStyles ts = m_pFont->Style; + m_fsCode = FontStyle2Code(ts); +} +//--------------------------------------------------------------------------- +void __fastcall CItem::Draw3D(UCOL cl[2]) +{ + int xm = m_3d & 0x00ff; + int ym = (m_3d >> 8) & 0x00ff; + if( xm & 0x0080 ) xm |= 0xffffff80; + if( ym & 0x0080 ) ym |= 0xffffff80; + if( m_Rot ){ + int x = xm * m_CosX + ym * m_SinX; + int y = -xm * m_SinX + ym * m_CosX; + xm = x; + ym = y; + } + + int max = ABS(xm) > ABS(ym) ? ABS(xm) : ABS(ym); + int ax, ay; + ax = ay = 32768; + for( int i = max; i > 0; i-- ){ + int x = xm * i / max; + int y = ym * i / max; + if( (ax != x) || (ay != y) ){ + DrawColorMask(x, y, GetGrade2(cl, i, max)); + ax = x; ay = y; + } + } +} +//--------------------------------------------------------------------------- +void __fastcall CItem::DrawColorMask(int X, int Y, UCOL col) +{ + ASSERT(m_pTbl); ASSERT(m_pAdr); + + int xw = m_XW; + int yw = m_YW; + int x, y, xx, yy; + LPBYTE pTbl = m_pTbl; + LPBYTE *pAdr = m_pAdr; + LPBYTE wp; + yy = Y; + for( y = 0; y < yw; y++, yy++ ){ + if( yy < 0 ){ + pTbl += xw; + continue; + } + else if( yy >= yw ){ + break; + } + wp = (LPBYTE)pAdr[yy] + (X*3); + xx = X; + for( x = 0; x < xw; x++, xx++, pTbl++ ){ + if( *pTbl && (xx>=0) && (xx= 0; i-- ){ + DrawColorMask(i+1, i+1, m_ColB[0]); + } + } + } + break; + case 2: + { + ASSERT(m_pTbl); ASSERT(m_pAdr); + if( m_3d & 0x00010000 ){ + Draw3D(&m_ColB[1]); + } + int f; + int x, y; + for( y = 0; y < yw; y++ ){ + wp = &m_pTbl[y*xw]; + p = m_pAdr[y]; + f = 0; + for( x = 0; x < xw; x++, wp++, p+=3 ){ + if( *wp ){ + if( !m_Grade ){ + *p++ = m_ColG[0].b.b; + *p++ = m_ColG[0].b.g; + *p = m_ColG[0].b.r; + p -= 2; + } + f = m_Line; + } + else if( f ){ + f--; + *p++ = m_ColB[0].b.b; + *p++ = m_ColB[0].b.g; + *p = m_ColB[0].b.r; + p -= 2; + *wp = BYTE((m_Line >= 2) ? 2 : (f ? 2 : 0)); + } + } + f = 0; + wp--; + p -= 3; + x--; + for( ; x >= 0; x--, wp--, p-=3 ){ + if( *wp ){ + f = m_Line; + } + else if( f ){ + f--; + *p++ = m_ColB[0].b.b; + *p++ = m_ColB[0].b.g; + *p = m_ColB[0].b.r; + p -= 2; + *wp = BYTE((m_Line >= 2) ? 2 : (f ? 2 : 0)); + } + } + + } + int ax = 0; + for( x = 0; x < xw; x++, ax+=3 ){ + wp = &m_pTbl[x]; + f = 0; + for( y = 0; y < yw; y++, wp += xw ){ + if( *wp ){ + f = m_Line; + } + else if( f ){ + f--; + p = m_pAdr[y]; + p += ax; + *p++ = m_ColB[0].b.b; + *p++ = m_ColB[0].b.g; + *p = m_ColB[0].b.r; + *wp = BYTE((m_Line >= 2) ? 2 : (f ? 2 : 0)); + } + } + f = 0; + y--; + wp -= xw; + for( ; y >= 0; y--, wp -= xw ){ + if( *wp ){ + f = m_Line; + } + else if( f ){ + f--; + p = m_pAdr[y]; + p += ax; + *p++ = m_ColB[0].b.b; + *p++ = m_ColB[0].b.g; + *p = m_ColB[0].b.r; + } + } + } + } + break; + case 3: + { + if( m_3d & 0x00010000 ){ + int xm = m_3d & 0x00ff; + int ym = (m_3d >> 8) & 0x00ff; + Draw3D(&m_ColB[1]); + DrawColorMask((xm & 0x80) ? 1 : -1, (ym & 0x80) ? 1 : -1, m_ColB[0]); + } + else { + for( int i = m_Line - 1; i >= 0; i-- ){ + DrawColorMask(i+1, i+1, m_ColB[0]); + } + DrawColorMask(-1, -1, m_ColB[1]); + } + } + break; + default: + break; + } + + MultProc(); + int x, y; + RECT mc = m_rc; + int bw = mc.right - mc.left + 1; + int bh = mc.bottom - mc.top + 1; + int bd = sqrt(bw*bw + bh*bh); + UCOL c; + int ao = mc.left * 3; + int yy = mc.top; + + int Grade = m_Grade; + int maskxw, maskyw; + LPBYTE sp; + if( m_pMaskBmp ){ + maskxw = m_pMaskBmp->Width; + maskyw = m_pMaskBmp->Height; + Grade = 5; + } + for( y = 0; y < bh; y++, yy++ ){ + p = m_pAdr[yy] + ao; + wp = &m_pTbl[yy*xw] + mc.left; + if( Grade == 5 ){ + sp = (LPBYTE)m_pMaskBmp->ScanLine[y % maskyw]; + } + for( x = 0; x < bw; x++, wp++ ){ + if( *wp & 0x80 ){ + switch(Grade){ + case 0: + c = m_ColG[0]; + break; + case 1: + c = GetGrade4(m_ColG, x, bw); + break; + case 2: + c = GetGrade4(m_ColG, y, bh); + break; + case 3: + c = GetGrade4(m_ColG, sqrt(x*x + y*y), bd); + break; + case 4: + c = m_ColF[*wp & 0x07]; + break; + case 5: + { + LPBYTE s = sp + ((x % maskxw) * 3); + c.b.b = *s++; + c.b.g = *s++; + c.b.r = *s; + } + break; + } + *p++ = c.b.b; + *p++ = c.b.g; + *p++ = c.b.r; + } + else { + p += 3; + } + } + } + + if( m_pAdr != NULL ) delete m_pAdr; + if( m_pTbl != NULL ) delete m_pTbl; + + return pDest; +} +//--------------------------------------------------------------------------- +Graphics::TBitmap* __fastcall CItem::AdjustMinimized(Graphics::TBitmap *pSrc) +{ + int xw = pSrc->Width; + int yw = pSrc->Height; + int x, y; + RECT rc; + rc.left = xw; rc.right = 0; + rc.top = yw; rc.bottom = 0; + BYTE br = m_cBack.b.r; + BYTE bg = m_cBack.b.g; + BYTE bb = m_cBack.b.b; + for( y = 0; y < xw; y++ ){ + LPBYTE p = (LPBYTE)pSrc->ScanLine[y]; + for( x = 0; x < yw; x++, p+=3 ){ + if( (bb != *p) || (bg != *(p+1)) || (br != *(p+2)) ){ + if( rc.left > x ) rc.left = x; + if( rc.right < x ) rc.right = x; + if( rc.top > y ) rc.top = y; + if( rc.bottom < y ) rc.bottom = y; + } + } + } + xw = rc.right - rc.left + 1; + yw = rc.bottom - rc.top + 1; + if( xw <= 0 ) xw = 1; + if( yw <= 0 ) yw = 1; + Graphics::TBitmap *pbmp = CreateBitmap(xw, yw); + pbmp->Canvas->Draw(-rc.left, -rc.top, pSrc); + delete pSrc; + return pbmp; +} +// +// +//--------------------------------------------------------------------------- +// Matrix +// +// n[] = l[] * m[] +// +static void __fastcall Matrix(double l[4][4], double m[4][4], double n[4][4]) +{ + int i, j, k; + double d; + + for( i = 0; i < 4; i++ ){ + for( j = 0; j < 4; j++ ){ + for( k = 0, d = 0.0; k < 4; k++ ) d += l[i][k] * m[k][j]; + n[i][j] = d; + } + } +} +static void __fastcall Matrix(double l[3][3], double m[3][3], double n[3][3]) +{ + int i, j, k; + double d; + + for( i = 0; i < 3; i++ ){ + for( j = 0; j < 3; j++ ){ + for( k = 0, d = 0.0; k < 3; k++ ) d += l[i][k] * m[k][j]; + n[i][j] = d; + } + } +} +//--------------------------------------------------------------------------- +// Perspect +// +void __fastcall SetMatrix(double k[3][3], LPCSPERSPECT pPar, int xs, int ys) +{ + double l[4][4]; double m[4][4]; double n[4][4]; + double k1, k2, k3, k4, k5, k6, k7, k8, k9; + double u, v, w; + + u = pPar->rx * PI / 180; + v = pPar->ry * PI / 180; + w = pPar->rz * PI / 180; + memset(l, 0, sizeof(l)); memset(m, 0, sizeof(m)); + l[0][0] = 1.0/xs; l[1][1] = -1.0/xs; l[2][2] = 1.0; l[3][3] = 1.0; + m[0][0] = pPar->ax; m[1][1] = pPar->ay; m[2][2] = 1.0; m[3][3] = 1.0; + Matrix(l, m, n); + memset(l, 0, sizeof(l)); + l[0][0] = 1.0; l[1][1] = 1.0; l[2][2] = 1.0; + l[3][0] = pPar->px; l[3][1] = pPar->py; l[3][2] = pPar->pz; l[3][3] = 1.0; + Matrix(n, l, m); + memset(n, 0, sizeof(n)); + n[0][0] = cos(w); n[0][1] = sin(w); + n[1][0] = -n[0][1]; n[1][1] = n[0][0]; + n[2][2] = 1.0; n[3][3] = 1.0; + Matrix(m, n, l); + memset(m, 0, sizeof(m)); + m[0][0] = 1.0; m[1][1] = cos(u); m[1][2] = sin(u); + m[2][1] = -m[1][2]; m[2][2] = m[1][1]; m[3][3] = 1.0; + Matrix(l, m, n); + memset(l, 0, sizeof(l)); + l[0][0] = cos(v); l[0][2] = sin(v); l[1][1] = 1.0; + l[2][0] = -l[0][2]; l[2][2] = l[0][0]; l[3][3] = 1.0; + Matrix(n, l, m); + memset(n, 0, sizeof(n)); + n[0][0] = 1.0; n[1][1] = 1.0; n[2][2] = -1.0; n[3][2] = -pPar->v; n[3][3] = 1.0; + Matrix(m, n, l); + memset(m, 0, sizeof(m)); + m[0][0] = 1.0; m[1][1] = 1.0; m[2][2] = 1/pPar->s; m[2][3] = m[2][2]; + m[3][2] = -1.0; + Matrix(l, m, n); + memset(l, 0, sizeof(l)); + l[0][0] = xs; l[1][1] = -xs; l[2][2] = 1.0; l[3][3] = 1.0; + Matrix(n, l, m); + + k1 = m[0][3]; k2 = m[1][3]; k3 = m[3][3]; + k4 = m[0][0]; k5 = m[1][0]; k6 = m[3][0]; + k7 = m[0][1]; k8 = m[1][1]; k9 = m[3][1]; + + k[0][0] = k7*k2 - k8*k1; k[0][1] = k5*k1 - k4*k2; k[0][2] = k4*k8 - k7*k5; + k[1][0] = k8*k3 - k9*k2; k[2][0] = k9*k1 - k7*k5; k[1][1] = k6*k2 - k5*k3; + k[2][1] = k4*k3 - k6*k1; k[1][2] = k5*k9 - k8*k6; k[2][2] = k7*k6 - k4*k9; + + if( pPar->r != 0.0 ){ // simple rotation + double r = pPar->r * PI / 180.0; + double m[3][3]; + double z[3][3]; + memset(m, 0, sizeof(m)); + m[0][0] = cos(r); m[0][1] = sin(r); + m[1][0] = -m[0][1]; m[1][1] = m[0][0]; + m[2][2] = 1.0; + Matrix(k, m, z); + memcpy(k, z, sizeof(z)); + } +} +#define TMAX 400 +//--------------------------------------------------------------------------- +// Create mapping table +LPCDOUBLE __fastcall MapTable(int wave, int xs, int ys, double ks) +{ +#define VMAX 32767.0 +#define VMIN (1.0/VMAX) + LPDOUBLE pTbl, dp; + double d; + switch(wave){ + case 6: + { + double ky = 0.5 * PI / ys; + dp = pTbl = new double[ys*2]; + for( int y = -ys; y < ys; y++, dp++ ){ + d = cos(y * ky); + if( ABS(d) >= VMIN ){ + d = 1.0 * ks / d; + } + else { + d = VMAX; + } + *dp = d * 0.8; + } + } + break; + case 9: + { + dp = pTbl = new double[xs*2]; + double kd = xs * xs; + for( int x = -xs; x < xs; x++, dp++ ){ + d = kd - x * x; + if( d >= 0 ){ + d = sqrt(d); + *dp = (d > VMIN) ? xs * ks / d : VMAX; + } + else { + *dp = 1.0; + } + } + } + break; + case 14: + { + dp = pTbl = new double[ys*2]; + double kd = ys * ys; + for( int y = -ys; y < ys; y++, dp++ ){ + d = kd - y * y; + if( d >= 0 ){ + d = sqrt(d); + *dp = (d > VMIN) ? ys / d : VMAX; + } + else { + *dp = 1.0; + } + } + } + break; + case 10: + case 11: + { + dp = pTbl = new double[xs*2]; + double kd = xs * xs; + double kc = xs * 0.25; + for( int x = -xs; x < xs; x++, dp++ ){ + d = kd - x * x; + if( d >= 0 ){ + *dp = sqrt(d) * 0.5 * ks - kc; + if( wave == 10 ) *dp = -*dp; + } + else { + *dp = 1.0; + } + } + } + break; + case 7: + case 8: + case 12: + case 13: + case 15: + case 25: + pTbl = NULL; + break; + case 16: + { + dp = pTbl = new double[ys*2]; + double kc = ks * PI /(4 * ys); + double d; + for( int y = -ys; y < ys; y++, dp++ ){ + d = fabs(sin((y + ys)*kc)); + *dp = d > VMIN ? 1.0 / d : VMAX; + } + } + break; + case 17: + { + dp = pTbl = new double[ys*2]; + double kc = ks * PI /(4 * ys); + double d; + for( int y = ys-1; y >= -ys; y--, dp++ ){ + d = fabs(sin((y + ys)*kc)); + *dp = d > VMIN ? 1.0 / d : VMAX; + } + } + break; + case 22: + { + dp = pTbl = new double[ys*2]; + double kc = PI * ks/ (ys * ys); + double d; + for( int y = -ys; y < ys; y++, dp++ ){ + d = y * y * kc + (PI/4); + *dp = ABS(d) >= VMIN ? (1.0 / d) : VMAX; + } + } + break; + case 28: + case 29: + { + dp = pTbl = new double[xs*2]; + double kd = xs * xs; + double kc = ks*0.5 + 0.05; + for( int x = -xs; x < xs; x++, dp++ ){ + d = kd - x * x; + if( d >= 0 ){ + d = sqrt(d); + *dp = (d > VMIN) ? xs * kc / d : VMAX; + } + else { + *dp = 1.0; + } + } + } + break; + case 36: + { + dp = pTbl = new double[xs*2]; + double kx = PI * 0.5 / xs; + double ky = ys * ks * 0.125; + double ko = ks * ys * 0.1875; + for( int x = -xs; x < xs; x++, dp++ ){ + *dp = ky * ((xs-x) * kx) - ko; + } + } + break; + case 38: + { + dp = pTbl = new double[ys*2]; + double ky = PI * 0.5 / ys; + double kx = xs * ks * 0.25; + double ko = ks * xs * 0.375; + for( int y = -ys; y < ys; y++, dp++ ){ + *dp = kx * ((ys-y) * ky) - ko; + } + } + break; + default: + { + double kx = PI / xs; + double ky = ys * ks/ 8; + dp = pTbl = new double[xs*2]; + for( int x = -xs; x < xs; x++, dp++ ){ + switch(wave){ + case 1: + *dp = ky * sin(x * kx); + break; + case 2: + *dp = ky * sin(-x * kx); + break; + case 3: + *dp = ky * sin(x * kx + PI/2); + break; + case 4: + *dp = ky * sin(-x * kx - PI/2); + break; + case 5: + d = cos(x * kx * 0.5); + if( ABS(d) >= VMIN ){ + d = 1.0 * ks/ d; + } + else { + d = VMAX; + } + *dp = d * 0.8; + break; + case 18: + d = ABS(x) * kx + (PI/2) * ks; + if( ABS(d) >= VMIN ){ + d = PI / d; + } + else { + d = VMAX; + } + *dp = d * 0.8; + break; + case 19: + case 34: + case 35: + d = fabs(sin(x * kx)) + 0.25 * ks; + if( ABS(d) >= VMIN ){ + d = 1.0 / d; + } + else { + d = VMAX; + } + *dp = d * 0.8; + break; + case 20: + case 30: + case 32: + d = (x+xs) * kx * 0.5 + (PI/2) * ks; + if( ABS(d) >= VMIN ){ + d = PI / d; + } + else { + d = VMAX; + } + *dp = d * 0.8; + break; + case 21: + case 31: + case 33: + d = (xs-x) * kx * 0.5 + (PI/2) * ks; + if( ABS(d) >= VMIN ){ + d = PI / d; + } + else { + d = VMAX; + } + *dp = d * 0.8; + break; + case 23: + d = x * x * kx * kx + (PI * ks); + *dp = ABS(d) >= VMIN ? (PI * 2.0 / d) : VMAX; + break; + case 24: + case 26: + case 27: + d = (xs-ABS(x)) * kx + (PI/2) * ks; + *dp = ABS(d) >= VMIN ? (PI * 0.8 / d) : VMAX; + break; + case 37: + *dp = ky * (ABS(x) * kx * 0.5); + break; + default: + break; + } + } + } + break; + } + return pTbl; +} +//--------------------------------------------------------------------------- +void __fastcall CItem::Perspect(void) +{ + if( (m_XW <= 2) && (m_YW <= 2) ) return; + + LPCSPERSPECT pPar = &m_sperspect; + + LPBYTE pDest = new BYTE[m_XW*m_YW]; + LPBYTE pSrc = m_pTbl; +#if MeasureAccuracy + QueryPerformanceCounter(&m_liPOldPer); +#endif + int wave = pPar->flag; + int bw = m_YW; + int bh = m_XW; + int i, j, m, n; + double x, y, w, p, q; + double k[3][3]; + int xs = bw / 2; + int ys = bh / 2; + SetMatrix(k, pPar, xs, ys); + + LPCDOUBLE pTbl = NULL; + double ks = 1.0 + (double(m_SC) * 0.05); + if( wave ) pTbl = MapTable(wave, xs, ys, ks); + double kc, kc3, kx, kc7; + switch(wave){ + case 7: + case 8: + kc7 = ((wave == 7) ? 0.6 : 0.8)*double(ys)/double(xs); + kx = xs * ((wave == 7) ? 4.0 * ks : 2.994) / PI; + kc3 = ys/3; + if( wave == 8 ){ + kc7 *= ks; + kc3 *= ks; + } + break; + case 13: + if( m_SC >= (88-30) ) m_SC = 88-30; + if( m_SC <= -30 ) m_SC = -29; + kc = 30 + m_SC; + kc3 = 1.0/tan(kc*PI/180); + kx = 1.0/cos(kc*PI/180); + kc7 = 1.0/sin(kc*PI/180); + break; + case 14: + kc3 = ys * 7 /8; + break; + case 15: + kc3 = ks + 0.75; + break; + case 25: + kc7 = 0.6*double(ys)/double(xs); + kx = xs * (4.0 * ks) / PI; + kc3 = ys/3; + break; + case 26: + case 27: + case 34: + case 35: + kc3 = (ABS(ks) > VMIN) ? (1.0 / ks) : VMAX; + break; + case 28: + case 29: + kc3 = (ABS(ks) > VMIN) ? (ks) : VMAX; + break; + case 30: + case 31: + case 32: + case 33: + kc3 = (ABS(ks) > VMIN) ? (0.8 / ks) : VMAX; + break; + } + kc = double(xs)/double(ys); +#if MeasureAccuracy + if( QueryPerformanceCounter(&m_liPCurPer) ){ + m_dlDiffPer1 = m_liPCurPer.QuadPart - m_liPOldPer.QuadPart; + m_liPOldPer = m_liPCurPer; + } +#endif + LPBYTE tp = pDest; + for( i = -ys; i < ys; i++ ){ + for( j = -xs; j < xs; j++ ){ + w = k[0][0] * j + k[0][1] * i + k[0][2]; + x = k[1][0] * j + k[1][1] * i + k[1][2]; + y = k[2][0] * j + k[2][1] * i + k[2][2]; + if( w ){ + x = x / w; + y = y / w; + } + else { + x = y = 10000.0; + } + switch(wave){ + case 1: + case 2: + case 3: + case 4: + ASSERT(pTbl); + m = x + xs; + if( m >= bw ) m = bw-1; + if( m < 0 ) m = 0; + y += pTbl[m]; + break; + case 5: + ASSERT(pTbl); +// x *= 0.8; + m = x + xs; + if( m >= bw ) m = bw-1; + if( m < 0 ) m = 0; + y *= pTbl[m]; + break; + case 6: + ASSERT(pTbl); + y *= 0.8; + m = y + ys; + if( m >= bh ) m = bh-1; + if( m < 0 ) m = 0; + x *= pTbl[m]; + break; + case 7: + case 8: + if( wave == 7 ){ + y -= ys; + } + x *= kc7; + y *= kc7; + q = -y * kc; + w = (y||x) ? atan2(x, q) : 0.0; + p = sqrt(q * q + x * x); + x = w * kx; + if( p >= kc3 ){ + if( wave == 8 ){ + x += xs; + if( x < 0 ) x += 2*xs; + x = fmod(x, 2*xs-1); + x -= xs; + } + p = (p - kc3) * 3; + y = (-(p) + ys); + } + else { + y = ys; + } + break; + case 9: + ASSERT(pTbl); + m = x + xs; + if( m >= bw ) m = bw-1; + if( m < 0 ) m = 0; + y *= pTbl[m]; + break; + case 10: + case 11: + case 36: + case 37: + ASSERT(pTbl); + m = x + xs; + if( m >= bw ) m = bw-1; + if( m < 0 ) m = 0; + y += pTbl[m]; + break; + case 12: + x *= 0.8; + p = (y+ys)*0.5; + w = xs * xs - x * x; + if( w >= 0 ){ + w = sqrt(w) * ks/2.0 - xs*0.25; + y -= w; + } + else { + y = ys; + } + + w = ys * ys - p * p; + if( w > 0 ){ + w = ys / sqrt(w); + x *= w; + } + else { + x = xs; + } + break; + case 13: + x += xs / 3; + y += ys / 3; + x *= 0.75; + y *= 0.75; + if( (y >= 0) && (x >= 0) ){ // C + y = y * 2 - ys; + x = x * 2 - xs; + } + else if( (-y*kc3 >= -x) ){ // A + x = (x - y*kc3) * 2 - xs; + y = y * kc7 * 3 + ys; + } + else { // B + y = (y - x/kc3) * 2 - ys; + x = x * kx * 3 * kc + xs; + } +// m = int(y); n = int(x); +// if( (n ==(-xs+1))||(n==(xs-1))||(m==(-ys+1))||(m==(ys-1)) ){ +// x = xs-1; y = ys-1; +// } + break; + case 14: + y += kc3; + w = (x||y) ? atan2(x, y*kc) : 0.0; + p = fabs(ks + cos(w)); + p = (p > VMIN) ? 1.0 / p : VMAX; + y *= p; + ASSERT(pTbl); + m = y + ys; + if( m >= bh ) m = bh-1; + if( m < 0 ) m = 0; + x *= p * pTbl[m]; + break; + case 15: + x *= 1.7; y *= 1.7; + p = fabs(x); q = fabs(y); + w = (x||y) ? atan2(p, q*kc) : 0.0; + p = 1 + sin(w * kc3); + p = (p > VMIN) ? 1.0 / p : VMAX; + x *= p; + y *= p; + break; + case 16: + case 17: + case 22: + ASSERT(pTbl); + m = y + ys; + if( m >= bh ) m = bh-1; + if( m < 0 ) m = 0; + x *= pTbl[m]; + break; + case 18: + case 19: + case 20: + case 21: + case 23: + case 24: + ASSERT(pTbl); + m = x + xs; + if( m >= bw ) m = bw-1; + if( m < 0 ) m = 0; + y *= pTbl[m]; + break; + case 25: + y += ys; + x *= kc7; + y *= kc7; + q = y * kc; + w = (y||x) ? atan2(x, q) : 0.0; + p = sqrt(q * q + x * x); + x = w * kx; + if( p >= kc3 ){ + p = (p - kc3) * 3; + y = p - ys; + } + else { + y = -ys; + } + break; + case 26: + case 28: + case 30: + case 31: + case 34: + ASSERT(pTbl); + if( y < 0 ){ + m = x + xs; + if( m >= bw ) m = bw-1; + if( m < 0 ) m = 0; + y *= pTbl[m]; + } + else { + y *= kc3; + } + break; + case 27: + case 29: + case 32: + case 33: + case 35: + ASSERT(pTbl); + if( y > 0 ){ + m = x + xs; + if( m >= bw ) m = bw-1; + if( m < 0 ) m = 0; + y *= pTbl[m]; + } + else { + y *= kc3; + } + break; + case 38: + ASSERT(pTbl); + m = y + ys; + if( m >= bh ) m = bh-1; + if( m < 0 ) m = 0; + x += pTbl[m]; + break; + default: + break; + } + if( y > 0 ){ m = int(y); } else { m = int(y-1); } + if( x > 0 ){ n = int(x); } else { n = int(x-1); } +#if 0 + double q = y - m; + double p = x - n; + double pp = 1.0 - p; + double qq = 1.0 - q; + if( (m >= -ys) && (m < ys-1) && (n >= -xs) && (n < xs-1) ){ + LPBYTE sp1 = &pSrc[((m+ys)*bw) + n + xs]; + LPBYTE sp2 = &pSrc[((m+ys+1)*bw) + n + xs]; + if( (*sp1 != *sp2) || (*sp1 != *(sp1+3)) || (*sp1 != *(sp2+3)) ){ + int b = (int)(qq*(pp*(*sp1) + p*(*(sp1+3))) + + q * (pp*(*sp2) + p*(*(sp2+3)))); + *tp++ = b >= 0x40 ? 0x80 : 0; + } + else { + *tp++ = *sp1; + } + } + else { + *tp++ = 0; + } +#else + if( (m >= -ys) && (m < ys-1) && (n >= -xs) && (n < xs-1) ){ + *tp++ = pSrc[((m+ys)*bw) + n + xs]; + } + else { + *tp++ = 0; + } +#endif + } + } + if( pTbl ) delete pTbl; +#if MeasureAccuracy + if( QueryPerformanceCounter(&m_liPCurPer) ){ + m_dlDiffPer2 = m_liPCurPer.QuadPart - m_liPOldPer.QuadPart; + m_liPOldPer = m_liPCurPer; + } +#endif + { + LPBYTE sp = pDest; + RECT mc; + mc.left = m_XW; mc.right = 0; + mc.top = m_YW; mc.bottom = 0; + int x, y; + for( y = 0; y < m_YW; y++ ){ + for( x = 0; x < m_XW; x++, sp++ ){ + if( *sp ){ + if( mc.left > x ) mc.left = x; + if( mc.right < x ) mc.right = x; + if( mc.top > y ) mc.top = y; + if( mc.bottom < y ) mc.bottom = y; + } + } + } + m_rc = mc; + } + if( m_Filter & 0x30000 ){ + MFilter(pDest); + } + else { + delete m_pTbl; + m_pTbl = pDest; + } +} +//--------------------------------------------------------------------------- +// メディアンフィルタ +void __fastcall CItem::MFilter(LPBYTE pSrc) +{ + int XW = m_XW; + int YW = m_YW; + int x, y; + LPBYTE sp, tp, rp; + RECT mc = m_rc; + if( !mc.left ) mc.left++; + if( !mc.top ) mc.top++; + LPBYTE pDest = m_pTbl; + memset(pDest, 0, XW*YW); + int n; + int count = m_Filter & 0x00ff; + int sw = (m_Filter >> 16) - 1; + for( int i = 0; i <= count; i++ ){ + if( i ){ + if( pSrc != m_pTbl ){ + pDest = pSrc; + pSrc = m_pTbl; + } + else { + pSrc = pDest; + pDest = m_pTbl; + } + memset(pDest, 0, XW*YW); + } + if( m_Grade == 4 ){ + LPBYTE zp; + if( sw ){ + for( y = mc.top; y <= mc.bottom; y++ ){ + sp = &pSrc[y*XW+mc.left]; + tp = &pDest[y*XW+mc.left]; + for( x = mc.left; x <= mc.right; x++, sp++, tp++ ){ + n = 0; + rp = sp - 1; + if( *rp ){ n++; zp = rp;} + if( *++rp ){ n++; zp = rp;} + if( *++rp ){ n++; zp = rp;} + rp = sp - XW - 1; + if( *rp ){ n++; zp = rp;} + if( *++rp ){ n++; zp = rp;} + if( *++rp ){ n++; zp = rp;} + rp = sp + XW - 1; + if( *rp ){ n++; zp = rp;} + if( *++rp ){ n++; zp = rp;} + if( *++rp ){ n++; zp = rp;} + if( n >= 5 ){ + *tp = *zp; + } + } + } + } + else { + for( y = mc.top; y <= mc.bottom; y++ ){ + sp = &pSrc[y*XW+mc.left]; + tp = &pDest[y*XW+mc.left]; + for( x = mc.left; x <= mc.right; x++, sp++, tp++ ){ + n = 0; + rp = sp - 1; + if( *rp ){ n++; zp = rp;} + if( *++rp ){ n++; zp = rp;} + if( *++rp ){ n++; zp = rp;} + rp = sp - XW; + if( *rp ){ n++; zp = rp;} + rp = sp + XW; + if( *rp ){ n++; zp = rp;} + if( n >= 3 ) *tp = *zp; + } + } + } + } + else { + if( sw ){ + for( y = mc.top; y <= mc.bottom; y++ ){ + sp = &pSrc[y*XW+mc.left]; + tp = &pDest[y*XW+mc.left]; + for( x = mc.left; x <= mc.right; x++, sp++, tp++ ){ + n = 0; + rp = sp - 1; + if( *rp++ ) n++; + if( *rp++ ) n++; + if( *rp ) n++; + rp = sp - XW - 1; + if( *rp++ ) n++; + if( *rp++ ) n++; + if( *rp ) n++; + rp = sp + XW - 1; + if( *rp++ ) n++; + if( *rp++ ) n++; + if( *rp ) n++; + if( n >= 5 ){ + *tp = 0x80; + } + } + } + } + else { + for( y = mc.top; y <= mc.bottom; y++ ){ + sp = &pSrc[y*XW+mc.left]; + tp = &pDest[y*XW+mc.left]; + for( x = mc.left; x <= mc.right; x++, sp++, tp++ ){ + n = 0; + rp = sp - 1; + if( *rp++ ) n++; + if( *rp++ ) n++; + if( *rp ) n++; + if( *(sp-XW) ) n++; + if( *(sp+XW) ) n++; + if( n >= 3 ) *tp = 0x80; + } + } + } + } + } + if( pDest == m_pTbl ){ + delete pSrc; + } + else { + delete m_pTbl; + m_pTbl = pDest; + } + MultProc(); +} +//--------------------------------------------------------------------------- +void __fastcall CItem::ConvChar(LPSTR pStr) +{ + char bf[8192]; + LPCSTR p; + LPSTR t = bf; + for( p = pStr; *p; p++ ){ + if( (_mbsbtype((const unsigned char *)p, 0) == _MBC_LEAD) && *(p+1) ){ + *t++ = *p++; + *t++ = *p; + } + else if( (*p == '\\') && (*(p+1)=='x') ){ + p+=2; + *t++ = (char)htoin(p, 2); + p++; + } + else if( (*p == '\\') && (*(p+1)=='$') ){ + p+=2; + *t++ = (char)htoin(p, 2); + p+=2; + *t++ = (char)htoin(p, 2); + p++; + } + else if( (*p == '\t') && (m_Align) ){ + *t++ = ' '; + } + else { + *t++ = *p; + } + } + *t = 0; + strcpy(pStr, bf); +} +//--------------------------------------------------------------------------- +void __fastcall AddStyle(AnsiString &as, BYTE charset, DWORD style) +{ + switch(charset){ + case ANSI_CHARSET: + as += sys.m_MsgEng ? "/ANSI" : "/欧文"; + break; + case SHIFTJIS_CHARSET: + as += sys.m_MsgEng ? "/Japanese" : "/日本語"; + break; + case HANGEUL_CHARSET: + as += sys.m_MsgEng ? "/Korean(Hangul)" : "/ハングル"; + break; + case JOHAB_CHARSET: + as += sys.m_MsgEng ? "/Korean(Johab)" : "/ハングル(Johab)"; + break; + case CHINESEBIG5_CHARSET: // 台湾 + as += sys.m_MsgEng ? "/Chinese(BIG5)" : "/中国語(繁体)"; + break; + case 134: // 中国語簡略 + as += sys.m_MsgEng ? "/Chinese(GB2312)" : "/中国語(簡体)"; + break; + case SYMBOL_CHARSET: + as += sys.m_MsgEng ? "/Symbol" : "/シンボル"; + break; + default: + break; + } + if( style & FSBOLD ) as += sys.m_MsgEng ? "/Bold" : "/太字"; + if( style & FSITALIC ) as += sys.m_MsgEng ? "/Italic" : "/斜体"; + if( style & FSUNDERLINE ) as += sys.m_MsgEng ? "/UnderLine" : "/下線"; + if( style & FSSTRIKEOUT ) as += sys.m_MsgEng ? "/StrikeOut" : "/取消し線"; +} +//--------------------------------------------------------------------------- +Graphics::TBitmap* __fastcall CItem::Draw(Graphics::TBitmap *pDest, LPCSTR pText) +{ + if( (pText == NULL) || !*pText ) return pDest; + + CWaitCursor w(!m_Draft); + + m_Back.c = pDest->Canvas->Pixels[0][0]; + m_Back.d &= 0x00ffffff; + m_cBack = m_Back; + if( m_pFont == NULL ){ + m_pFont = new TFont(); + m_pFont->Assign(pDest->Canvas->Font); + m_pFont->Size = 18*6; + UpdateFont(); + } + else if( m_OrgXW >= 0 ){ + SetFontSize(pDest); + } + SetMBCP(m_pFont->Charset); + + AnsiString as = pText; + ConvChar(as.c_str()); + pText = as.c_str(); + + LPCSTR pOrgText = pText; + if( m_Zero ){ + pText = ZeroConv(pText, m_pFont->Charset); + } + + pDest->Canvas->Font = m_pFont; + m_FW = pDest->Canvas->TextHeight(pText); + if( !m_FW ) m_FW++; + m_OYWC = int((short)m_OYW); + if( m_OYW ){ + if( m_OYWS ){ + m_OYWS &= 0x0000ffff; + m_OYWS |= m_FW << 16; + int oyw = m_OYWS & 0x0000ffff; + if( oyw ) m_OYWC = m_OYWC * m_FW / oyw; + } + else { // 最初のフォントサイズの設定 + m_OYWS = (m_FW << 16) | m_FW; + } + } + int xw, yw; + int n = GetMaxWH(xw, yw, pDest, pText); + m_Row = n; + m_FW = yw; + if( m_OYWC && n ){ + yw = (yw + m_OYWC) * (n - 1) + yw; + if( yw < m_FW ) yw = m_FW; + } + else { + yw *= n; + } + if( m_fsCode & FSITALIC ){ +// xw += yw / 12; + xw += m_FW / 4; + } + if( !yw ) yw = 2; + if( !xw ) xw = 2; + + if( m_Shadow && (m_cBack.d == m_ColB[0].d) ){ + m_cBack = GetUniqueColor(m_cBack); + } + if( m_Grade == 4 ){ + while(1){ + int f = TRUE; + for( int i = 0; i < AN(m_ColF); i++ ){ + if( m_cBack.c == GetIndexColor(i) ){ + f = FALSE; + break; + } + } + if( f ){ + break; + } + else { + m_cBack = GetUniqueColor(m_cBack); + } + } + } + else if( m_cBack.d == m_ColG[0].d ){ + m_cBack = GetUniqueColor(m_cBack); + } + + MultProc(); + + RECT rc; + rc.left = rc.top = 0; + rc.right = xw; + rc.bottom = yw; + + if( m_Rot ){ + if( ABS(m_Rot - 90) < 10 ) rc.right += m_FW/6; + if( ABS(m_Rot - 180) < 10 ) rc.right += m_FW/6; + if( ABS(m_Rot - 270) < 10 ) rc.right += m_FW/6; +// rc.right += m_FW/2; +// rc.bottom += m_FW/2; + double s = 2 * PI * m_Rot / 360; + m_CosX = cos(s); + m_SinX = sin(s); + int xc = rc.right/2; + int yc = rc.bottom/2; + POINT N[5]; + N[0].x = -xc; + N[0].y = -yc; + N[1].x = xc; + N[1].y = -yc; + N[2].x = xc; + N[2].y = yc; + N[3].x = -xc; + N[3].y = yc; + N[4].x = rc.left - xc; + N[4].y = rc.top - yc; + int i; + for( i = 0; i < 5; i++ ){ + int x = N[i].x * m_CosX + N[i].y * m_SinX; + int y = -N[i].x * m_SinX + N[i].y * m_CosX; + N[i].x = x + xc; N[i].y = y + yc; + } + int x1, x2, y1, y2; + x1 = x2 = N[0].x; y1 = y2 = N[0].y; + for( i = 1; i < 4; i++ ){ + if( x1 > N[i].x ) x1 = N[i].x; + if( x2 < N[i].x ) x2 = N[i].x; + if( y1 > N[i].y ) y1 = N[i].y; + if( y2 < N[i].y ) y2 = N[i].y; + } + int xo = N[4].x - x1; + int yo = N[4].y - y1; + if( ABS(m_Rot - 90) < 10 ) yo += m_FW/12; + if( ABS(m_Rot - 180) < 10 ) xo += m_FW/12; +// if( ABS(m_Rot - 270) < 10 ) yo += m_FW/12; + rc.left += xo; rc.right += xo; + rc.top += yo; rc.bottom += yo; + xw = x2 - x1 + 1; yw = y2 - y1 + 1; + } + + if( m_3d & 0x00010000 ){ + int xm = m_3d & 0x00ff; + int ym = (m_3d >> 8) & 0x00ff; + if( xm & 0x0080 ) xm |= 0xffffff80; + if( ym & 0x0080 ) ym |= 0xffffff80; + if( m_Rot ){ + int x = xm * m_CosX + ym * m_SinX; + int y = -xm * m_SinX + ym * m_CosX; + xm = x; + ym = y; + } + if( xm < 0 ){ + rc.left -= xm; + rc.right -= xm; + } + if( ym < 0 ){ + rc.top -= ym; + rc.bottom -= ym; + } + xw += ABS(xm); + yw += ABS(ym); + } + + switch(m_Shadow){ + case 1: + xw += m_Line; + yw += m_Line; + break; + case 2: + rc.left += m_Line; + rc.right += m_Line; + rc.top += m_Line; + rc.bottom += m_Line; + xw += m_Line*2; + yw += m_Line*2; + break; + case 3: + xw += m_Line*2; + yw += m_Line*2; + break; + } + + if( m_fsCode & FSITALIC ){ // イタリックの場合の位置補正 + int oxw = 0; + int oyw = 0; + switch(GetPosFormat()){ + case DT_CENTER: + oxw = m_FW / 8; + if( m_Rot ){ + oxw *= m_CosX; + } + break; + case DT_RIGHT: + oxw = m_FW / 4; + if( m_Rot ){ + oxw *= m_CosX; + oyw = -(m_FW / 4) * m_SinX; + } + break; + default: + break; + } + rc.left -= oxw; + rc.right -= oxw; + rc.top -= oyw; + rc.bottom -= oyw; + } + + if( xw & 1 ) xw++; + if( yw & 1 ) yw++; + Graphics::TBitmap *pBmp = pDest; + if( !m_Draft ){ + if( xw > yw ){ + rc.top += (xw - yw)/2; + rc.bottom += (xw - yw)/2; + yw = xw; + } + else { + rc.left += (yw - xw)/2; + rc.right += (yw - xw)/2; + xw = yw; + } + } + if( (pDest->Width != xw) || (pDest->Height != yw) ){ + pBmp = CreateBitmap(xw, yw); + FillBitmap(pBmp, m_cBack); + } + else if( m_Back.d != m_cBack.d ){ + FillBitmap(pBmp, m_cBack); + } + + MultProc(); + UCOL col = m_ColG[0]; + if( m_Draft && (col.d == m_Back.d) ) col.d = col.d ^ 0x00ffffff; + DrawText(rc, pBmp, pText, col); + Graphics::TBitmap *pNew = pBmp; + if( m_Draft ){ + if( m_BmpXW < 0 ){ + double sc = m_sperspect.s * 3.0 / m_sperspect.v; + xw *= sc; + yw *= sc; + } + else { + xw = m_BmpXW; + yw = m_BmpYW; + } + pNew = CreateBitmap(xw, yw); + StretchCopy(pNew, pBmp, HALFTONE); + if( pDest != pBmp ) delete pBmp; + pBmp = pNew; + } + else if( !m_Draft ){ + CreateTable(pBmp); + +#if MeasureAccuracy + QueryPerformanceCounter(&m_liPOld); +#endif + Perspect(); +#if MeasureAccuracy + if( QueryPerformanceCounter(&m_liPCur) ){ + m_dlDiff1 = m_liPCur.QuadPart - m_liPOld.QuadPart; + m_liPOld = m_liPCur; + } +#endif + pNew = DrawExt(pBmp); +#if MeasureAccuracy + if( QueryPerformanceCounter(&m_liPCur) ){ + m_dlDiff2 = m_liPCur.QuadPart - m_liPOld.QuadPart; + m_liPOld = m_liPCur; + } +#endif + pNew = AdjustMinimized(pNew); + xw = pNew->Width; + yw = pNew->Height; +#if MeasureAccuracy + if( QueryPerformanceCounter(&m_liPCur) ){ + m_dlDiff3 = m_liPCur.QuadPart - m_liPOld.QuadPart; + m_liPOld = m_liPCur; + } +#endif + m_BmpXW = xw; + m_BmpYW = yw; + } + m_OrgXW = xw; + m_OrgYW = yw; + if( pBmp != pDest ) delete pDest; + pDest = pNew; + if( pOrgText != pText ) delete pText; + + // set transparent color to (0,0) for overlay + LPBYTE p = (LPBYTE)pDest->ScanLine[0]; + ASSERT(p); + *p++ = m_cBack.b.b; + *p++ = m_cBack.b.g; + *p = m_cBack.b.r; + + MultProc(); + return pDest; +} + + + \ No newline at end of file diff --git a/CItems/TextArt/Comlib.h b/CItems/TextArt/Comlib.h new file mode 100644 index 0000000..aeec450 --- /dev/null +++ b/CItems/TextArt/Comlib.h @@ -0,0 +1,329 @@ +#ifndef ComLibH +#define ComLibH +#include +#include +#include +#include +#include +#include +#include +#include + +#define MeasureAccuracy FALSE + +#define NDEBUG // Remove this symbol, if you would like to do debug +#include +#define ASSERT(c) assert(c) + +#define AN(c) (sizeof(c)/sizeof(c[0])) +#define ABS(c) (((c)<0)?(-(c)):(c)) +#define PI 3.1415926535897932384626433832795 + +typedef const BYTE* LPCBYTE; +typedef double* LPDOUBLE; +typedef const double* LPCDOUBLE; +typedef union { + struct { + BYTE r; + BYTE g; + BYTE b; + BYTE s; + }b; + DWORD d; + TColor c; +}UCOL; + +#define VER "TextArt Version 1.06" +#define AUT "(C) JE3HHT 2002-2003." +#define TTL "MMSSTV custom item" +#define TTLJ "MMSSTV カスタムアイテム" // Japanese code + +#define ININAME "TextArt.ini" +#define USERMASK "TextArt.bmp" + +#define FSBOLD 1 +#define FSITALIC 2 +#define FSUNDERLINE 4 +#define FSSTRIKEOUT 8 + +#define DISFONTSMOOTHING 0x00000001 + +// These prototypes are the functions in the MMSSTV. +// ---- Refer to the comment of the mcmFunc() --- +/*0*/typedef HBITMAP (__cdecl *mmLoadImageMenu)(int sw, int xw, int yw); +/*1*/typedef HBITMAP (__cdecl *mmLoadImage)(LPCSTR pName); +/*2*/typedef HBITMAP (__cdecl *mmLoadHistImage)(void); +/*3*/typedef int (__cdecl *mmSaveImageMenu)(HBITMAP hb, LPCSTR pName, LPCSTR pFolder); +/*4*/typedef int (__cdecl *mmSaveImage)(HBITMAP hb, LPCSTR pName); +/*5*/typedef HBITMAP (__cdecl *mmPasteImage)(int sw, int xw, int yw); +/*6*/typedef int (__cdecl *mmGetMacKey)(LPSTR pDest, int cbDest); +/*7*/typedef int (__cdecl *mmConvMac)(LPSTR pDest, LPCSTR pSrc, int cbDest); +/*8*/typedef HBITMAP (__cdecl *mmCreateDIB)(int xw, int yw); +/*9*/typedef void (__cdecl *mmMultProc)(void); +/*10*/typedef void (__cdecl *mmMultProcA)(void); +/*11*/typedef int (__cdecl *mmColorComp)(LPDWORD pCol); +/*12*/typedef HBITMAP (__cdecl *mmLoadRxImage)(void); +/*13*/typedef void (__cdecl *mmView)(HBITMAP hb); +/*14*/typedef int (__cdecl *mmAdjCol)(HBITMAP hb); +/*15*/typedef int (__cdecl *mmClip)(HBITMAP hbDest, HBITMAP hbSrc); + +void __fastcall InitSys(HINSTANCE hinst); +void __fastcall MultProc(void); +char __fastcall LastC(LPCSTR p); +void __fastcall SetCurDir(LPSTR t, int size); +void __fastcall SetDirName(LPSTR t, LPCSTR pName); +void __fastcall Yen2CrLf(AnsiString &ws, AnsiString cs); +void __fastcall CrLf2Yen(AnsiString &ws, AnsiString cs); +int __fastcall GetActiveIndex(TPageControl *pp); +void __fastcall LoadStringsFromIniFile(TStrings *pList, LPCSTR pSect, LPCSTR pName, int msg); +void __fastcall SaveStringsToIniFile(TStrings *pList, LPCSTR pSect, LPCSTR pName, int msg); +void __fastcall InitCustomColor(TColorDialog *tp); +void __fastcall AddCustomColor(TColorDialog *tp, TColor col); +Graphics::TBitmap * __fastcall CreateBitmap(int xw, int yw); +BOOL __fastcall IsSameBitmap(Graphics::TBitmap *pDest, Graphics::TBitmap *pSrc); +void __fastcall FillBitmap(Graphics::TBitmap *pDest, UCOL ucol); +void __fastcall FillBitmap(Graphics::TBitmap *pDest, TColor col); +void __fastcall CopyBitmap(Graphics::TBitmap *pDest, Graphics::TBitmap *pSrc); +void __fastcall CopyBitmap(Graphics::TBitmap *pBitmap); +void __fastcall DrawBitmap(TPaintBox *pBox, Graphics::TBitmap *pBitmap); +void __fastcall StretchCopy(Graphics::TBitmap *pDest, Graphics::TBitmap *pSrc, int mode); + +int __fastcall IsFile(LPCSTR pName); +void __fastcall SetMBCP(BYTE charset); +void __fastcall AddStyle(AnsiString &as, BYTE charset, DWORD style); +void __fastcall LoadFontFromInifile(TFont *pFont, LPCSTR pSect, TMemIniFile *pIniFile); +void __fastcall SaveFontToInifile(TFont *pFont, LPCSTR pSect, TMemIniFile *pIniFile); + +void __fastcall ExecPB(LPCSTR pName); +HWND __fastcall IsPB(void); + +int FontStyle2Code(TFontStyles style); +TFontStyles Code2FontStyle(int code); + +//--------------------------------------------------------------------------- +//CBitStreamクラス +class CBitStream { +private: + BYTE *m_pBase; + int m_BitCount; + int m_Alloc; +public: + CBitStream(void *pData){ SetData(pData); }; + CBitStream(){ SetData(NULL); }; + void SetData(void *pData){ + m_pBase = (BYTE *)pData; + m_BitCount = 0; + m_Alloc = FALSE; + }; + DWORD GetData(int n); + void GetText(LPSTR p, int n); + void Skip(int n){ m_BitCount += n;}; + + void PutData(DWORD d, int n); + void PutText(LPCSTR p, int n); + BYTE GetSum(void); +}; + +//--------------------------------------------------------------------------- +//CItemクラス +typedef struct { // Do not change the format + int ver; + int flag; + double ax; + double ay; + double px; + double py; + double pz; + double rz; + double rx; + double ry; + double v; + double s; + double r; +}SPERSPECT; +typedef SPERSPECT* LPSPERSPECT; +typedef const SPERSPECT* LPCSPERSPECT; + +class CItem +{ +public: + int m_Ver; + int m_Align; + int m_Grade; + int m_Shadow; + int m_Line; + int m_Zero; + DWORD m_3d; + AnsiString m_Text; + TFont *m_pFont; + UCOL m_ColG[4]; + UCOL m_ColB[4]; + UCOL m_ColF[6]; + UCOL m_Back; + int m_OrgXW; + int m_OrgYW; + int m_BmpXW; + int m_BmpYW; + int m_OYW; + DWORD m_OYWS; + int m_Rot; + int m_Filter; + + int m_SC; + SPERSPECT m_sperspect; + + Graphics::TBitmap *m_pMaskBmp; // ビットマップマスク +#if MeasureAccuracy + LARGE_INTEGER m_liPCur, m_liPOld; + DWORDLONG m_dlDiff1, m_dlDiff2, m_dlDiff3; + LARGE_INTEGER m_liPCurPer, m_liPOldPer; + DWORDLONG m_dlDiffPer1, m_dlDiffPer2; +#endif +private: + UCOL m_cBack; + int m_Draft; + int m_fsCode; + int m_Pos; + DWORD m_Ex; + int m_FW; + double m_SinX; + double m_CosX; + int m_OYWC; + int m_Row; + TMemoryStream *m_pMemStream; + + + // 3D展開用のワーク + int m_XW, m_YW; + LPBYTE m_pTbl; + LPBYTE *m_pAdr; + RECT m_rc; +private: + void __fastcall LoadDefault(void); + void __fastcall UpdateDefault(void); + void __fastcall SetFontSize(Graphics::TBitmap *pDest); + int __fastcall GetMaxWH(int &W, int &H, Graphics::TBitmap *pDest, LPCSTR pText); + UINT __fastcall GetPosFormat(void); + UINT __fastcall GetDrawFormat(void); + void __fastcall DrawText(RECT rc, Graphics::TBitmap *pDest, LPCSTR pText, UCOL ucol); + void __fastcall DrawText_(RECT rc, Graphics::TBitmap *pDest, LPCSTR pText, int &nc); + void __fastcall CreateTable(Graphics::TBitmap *pDest); + Graphics::TBitmap* __fastcall DrawExt(Graphics::TBitmap *pDest); + Graphics::TBitmap* __fastcall AdjustMinimized(Graphics::TBitmap *pSrc); + void __fastcall Draw3D(UCOL cl[2]); + void __fastcall DrawColorMask(int X, int Y, UCOL col); + + void __fastcall Perspect(void); + void __fastcall MFilter(LPBYTE pSrc); + void __fastcall ConvChar(LPSTR pStr); + +protected: +public: + __fastcall CItem(void); + __fastcall ~CItem(); + void __fastcall Create(LPCBYTE ps, DWORD size); + DWORD __fastcall GetItemType(void); + LPCBYTE __fastcall CreateStorage(LPDWORD psize); + void __fastcall DeleteStorage(LPCBYTE pStorage); + void __fastcall Copy(CItem *sp); + int __fastcall EditDialog(HWND hWnd); + int __fastcall FontDialog(HWND hWnd); + DWORD __fastcall GetOrgSize(void); + void __fastcall SetPos(DWORD pos, DWORD size, DWORD tsize); + inline LPCSTR __fastcall GetText(void){ + return m_Text.c_str(); + }; + inline void __fastcall SetDraft(int draft){ + m_Draft = draft; + }; + void __fastcall UpdateFont(void); + void __fastcall LoadFromInifile(LPCSTR pSect, LPCSTR pName, BOOL fMask); + void __fastcall SaveToInifile(LPCSTR pSect, LPCSTR pName, BOOL fMask); + void __fastcall DeleteInifile(LPCSTR pSect, LPCSTR pName); + Graphics::TBitmap* __fastcall Draw(Graphics::TBitmap *pDest, LPCSTR pText); + inline void __fastcall SetEx(DWORD ex){ m_Ex = ex;}; + inline DWORD __fastcall GetEx(void){return m_Ex;}; + inline void __fastcall SetPos(int pos){ m_Pos = pos;}; + inline DWORD __fastcall GetPos(void){return m_Pos;}; + int __fastcall GetTrueOYW(void); + + void __fastcall GetFont(LOGFONT *pLogfont); + void __fastcall SetFont(LOGFONT *pLogfont); + +#if MeasureAccuracy + int __fastcall Get1stXW(){return m_XW;}; + int __fastcall Get1stYW(){return m_YW;}; +#endif +}; + +class CWaitCursor +{ +private: + TCursor sv; +public: + CWaitCursor(BOOL sw); + CWaitCursor(); + ~CWaitCursor(); + void Delete(void); + void Wait(void); +}; + +typedef struct { + AnsiString m_Name; + int m_Height; + BYTE m_Charset; + DWORD m_Style; +}FONTDATA; + +enum { + fmJA, + fmHL, + fmJOHAB, + fmBV, + fmBY, + fmEND, +}; +typedef struct { + HINSTANCE m_hInstance; + + DWORD m_dwVersion; + int m_WinNT; + UINT m_CodePage; + int m_MsgEng; + int m_BitPixel; + mmLoadImageMenu m_fLoadImageMenu; + mmPasteImage m_fPasteImage; + mmGetMacKey m_fGetMacKey; + mmConvMac m_fConvMac; + mmMultProc m_fMultProc; + mmColorComp m_fColorComp; + mmAdjCol m_fAdjCol; + mmClip m_fClip; + DWORD m_DefStgSize; + LPBYTE m_pDefStg; + TStringList *m_pTextList; + TStringList *m_pStyleList; + char m_BgnDir[512]; + + AnsiString m_Msg; + TStringList *m_pFontList; + + Graphics::TBitmap *m_pBitmapTemp; + int m_DefaultPage; + int m_SBMListState; + + UCOL m_MaskC1; + UCOL m_MaskC2; + + int m_CodeLeft; + int m_CodeTop; + int m_CodeOut; + + BOOL m_fEudc; + AnsiString m_Eudc; + + BOOL m_fFontFam; + BOOL m_tFontFam[fmEND]; +}SYS; +extern SYS sys; +#endif diff --git a/CItems/TextArt/Item.ico b/CItems/TextArt/Item.ico new file mode 100644 index 0000000..0e2c0b2 Binary files /dev/null and b/CItems/TextArt/Item.ico differ diff --git a/CItems/TextArt/TextArt.bmp b/CItems/TextArt/TextArt.bmp new file mode 100644 index 0000000..1c489a9 Binary files /dev/null and b/CItems/TextArt/TextArt.bmp differ diff --git a/CItems/TextArt/TextArt.bpr b/CItems/TextArt/TextArt.bpr new file mode 100644 index 0000000..dd2c607 --- /dev/null +++ b/CItems/TextArt/TextArt.bpr @@ -0,0 +1,182 @@ +# --------------------------------------------------------------------------- +!if !$d(BCB) +BCB = $(MAKEDIR)\.. +!endif + +# --------------------------------------------------------------------------- +# IDE セクション +# --------------------------------------------------------------------------- +# プロジェクトメイクファイルの以下のセクションは、IDE によって管理されます。 +# このセクションを変更する場合は、できるだけ IDE を使用するようにして +# ください。 +# --------------------------------------------------------------------------- + +VERSION = BCB.03 +# --------------------------------------------------------------------------- +PROJECT = TextArt.dll +OBJFILES = TextArt.obj Comlib.obj About.obj TextDlg.obj CodeVw.obj +RESFILES = textart.res +DEFFILE = +RESDEPEN = $(RESFILES) About.dfm TextDlg.dfm CodeVw.dfm +LIBFILES = +LIBRARIES = vclx35.lib VCL35.lib +SPARELIBS = VCL35.lib vclx35.lib +PACKAGES = VCLX35.bpi VCL35.bpi VCLDB35.bpi VCLDBX35.bpi bcbsmp35.bpi dclocx35.bpi \ + QRPT35.bpi TEEUI35.bpi VCLSMP35.bpi TEEDB35.bpi TEE35.bpi ibsmp35.bpi \ + NMFAST35.bpi INETDB35.bpi INET35.bpi +# --------------------------------------------------------------------------- +PATHCPP = .; +PATHASM = .; +PATHPAS = .; +PATHRC = .; +DEBUGLIBPATH = $(BCB)\lib\debug +RELEASELIBPATH = $(BCB)\lib\release +# --------------------------------------------------------------------------- +CFLAG1 = -WD -O2 -Hc -w -Ve -d -k- -vi -c -b- -w-par -w-inl -Vx +CFLAG2 = -I$(BCB)\include;$(BCB)\include\vcl -H=$(BCB)\lib\vcl35.csm +CFLAG3 = -Tkh30000 -ff +PFLAGS = -U$(BCB)\lib\obj;$(BCB)\lib;$(RELEASELIBPATH) \ + -I$(BCB)\include;$(BCB)\include\vcl -$L- -$D- -v -JPHN -M +RFLAGS = -i$(BCB)\include;$(BCB)\include\vcl +AFLAGS = /i$(BCB)\include /i$(BCB)\include\vcl /mx /w2 /zn /d_RTLDLL +LFLAGS = -L$(BCB)\lib\obj;$(BCB)\lib;$(RELEASELIBPATH) -aa -Tpd -x -Gn +IFLAGS = +# --------------------------------------------------------------------------- +ALLOBJ = c0d32.obj sysinit.obj $(OBJFILES) +ALLRES = $(RESFILES) +ALLLIB = $(LIBFILES) $(LIBRARIES) import32.lib cp32mt.lib +# --------------------------------------------------------------------------- +!ifdef IDEOPTIONS + +[Version Info] +IncludeVerInfo=0 +AutoIncBuild=0 +MajorVer=1 +MinorVer=0 +Release=0 +Build=0 +Debug=0 +PreRelease=0 +Special=0 +Private=0 +DLL=0 +Locale=1041 +CodePage=932 + +[Version Info Keys] +CompanyName= +FileDescription= +FileVersion=1.0.0.0 +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion=1.0.0.0 +Comments= + +[HistoryLists\hlIncludePath] +Count=1 +Item0=$(BCB)\include;$(BCB)\include\vcl + +[HistoryLists\hlLibraryPath] +Count=1 +Item0=$(BCB)\lib\obj;$(BCB)\lib + +[HistoryLists\hlDebugSourcePath] +Count=1 +Item0=$(BCB)\source\vcl + +[HistoryLists\hlConditionals] +Count=2 +Item0=_RTLDLL +Item1=_RTLDLL;USEPACKAGES + +[HistoryLists\hlHostApplication] +Count=1 +Item0=D:\Mmsstv\Mmsstv.exe + +[Debugging] +DebugSourceDirs=$(BCB)\source\vcl + +[Parameters] +RunParams= +HostApplication=D:\Mmsstv\Mmsstv.exe + +!endif + +# --------------------------------------------------------------------------- +# MAKE セクション +# --------------------------------------------------------------------------- +# IDE はプロジェクトファイルのこのセクションは使用していません。 +# コマンドラインの MAKE ユーティリティを使用してビルドするためのものです。 +# --------------------------------------------------------------------------- + +.autodepend +# --------------------------------------------------------------------------- +!if !$d(BCC32) +BCC32 = bcc32 +!endif + +!if !$d(DCC32) +DCC32 = dcc32 +!endif + +!if !$d(TASM32) +TASM32 = tasm32 +!endif + +!if !$d(LINKER) +LINKER = ilink32 +!endif + +!if !$d(BRCC32) +BRCC32 = brcc32 +!endif +# --------------------------------------------------------------------------- +!if $d(PATHCPP) +.PATH.CPP = $(PATHCPP) +.PATH.C = $(PATHCPP) +!endif + +!if $d(PATHPAS) +.PATH.PAS = $(PATHPAS) +!endif + +!if $d(PATHASM) +.PATH.ASM = $(PATHASM) +!endif + +!if $d(PATHRC) +.PATH.RC = $(PATHRC) +!endif +# --------------------------------------------------------------------------- +$(PROJECT): $(OBJFILES) $(RESDEPEN) $(DEFFILE) + $(BCB)\BIN\$(LINKER) @&&! + $(LFLAGS) + + $(ALLOBJ), + + $(PROJECT),, + + $(ALLLIB), + + $(DEFFILE), + + $(ALLRES) +! +# --------------------------------------------------------------------------- +.pas.hpp: + $(BCB)\BIN\$(DCC32) $(PFLAGS) {$< } + +.pas.obj: + $(BCB)\BIN\$(DCC32) $(PFLAGS) {$< } + +.cpp.obj: + $(BCB)\BIN\$(BCC32) $(CFLAG1) $(CFLAG2) $(CFLAG3) -n$(@D) {$< } + +.c.obj: + $(BCB)\BIN\$(BCC32) $(CFLAG1) $(CFLAG2) $(CFLAG3) -n$(@D) {$< } + +.asm.obj: + $(BCB)\BIN\$(TASM32) $(AFLAGS) $<, $@ + +.rc.res: + $(BCB)\BIN\$(BRCC32) $(RFLAGS) -fo$@ $< +# --------------------------------------------------------------------------- + \ No newline at end of file diff --git a/CItems/TextArt/TextArt.cpp b/CItems/TextArt/TextArt.cpp new file mode 100644 index 0000000..826ed25 --- /dev/null +++ b/CItems/TextArt/TextArt.cpp @@ -0,0 +1,217 @@ +//--------------------------------------------------------------------------- +#include +#pragma hdrstop +//--------------------------------------------------------------------------- +#include "ComLib.h" +#include "About.h" +//--------------------------------------------------------------------------- +USEUNIT("Comlib.cpp"); +USEFORM("About.cpp", AboutDlg); +USERC("textart.rc"); +USEFORM("TextDlg.cpp", TextDlgBox); +USEFORM("CodeVw.cpp", CodeView); +//--------------------------------------------------------------------------- +int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void*) +{ + switch(reason){ + case DLL_PROCESS_ATTACH: + { + InitSys(hinst); + + _setmbcp(_MB_CP_ANSI); + HWND hMM = ::FindWindow("TMmsstv", NULL); + if( hMM != NULL ) Application->Handle = hMM; + } + break; + case DLL_PROCESS_DETACH: + sys.m_fMultProc = NULL; + if( sys.m_pDefStg != NULL ){ + CItem *pItem = new CItem; + pItem->Create(NULL, 0); + pItem->SaveToInifile("Default", ININAME, FALSE); + delete pItem; + delete sys.m_pDefStg; + sys.m_pDefStg = NULL; + } + if( sys.m_pTextList != NULL ){ + SaveStringsToIniFile(sys.m_pTextList, "Strings", ININAME, TRUE); + delete sys.m_pTextList; + sys.m_pTextList = NULL; + } + if( sys.m_pStyleList != NULL ){ + SaveStringsToIniFile(sys.m_pStyleList, "Styles", ININAME, FALSE); + delete sys.m_pStyleList; + sys.m_pStyleList = NULL; + } + if( sys.m_pFontList != NULL ){ + delete sys.m_pFontList; + sys.m_pFontList = NULL; + } + if( sys.m_pBitmapTemp != NULL ){ + delete sys.m_pBitmapTemp; + sys.m_pBitmapTemp = NULL; + } + break; + } + return 1; +} +//--------------------------------------------------------------------------- +extern "C" __declspec(dllexport) +void mcmLanguage(DWORD lang) +{ + sys.m_MsgEng = lang; +} +//--------------------------------------------------------------------------- +extern "C" __declspec(dllexport) +void mcmAboutDialog(HWND hWnd) +{ + TAboutDlg *pBox = new TAboutDlg(NULL); + pBox->ShowModal(); + delete pBox; +} +//--------------------------------------------------------------------- +extern "C" __declspec(dllexport) +HANDLE mcmCreateObject(LPCBYTE pStorage, DWORD Size) +{ + CItem *pItem = new CItem; + ASSERT(pItem); + if( pItem != NULL ) pItem->Create(pStorage, Size); + return (HANDLE)pItem; +} +//--------------------------------------------------------------------- +extern "C" __declspec(dllexport) +DWORD mcmGetItemType(HANDLE hObj) +{ + ASSERT(hObj); + CItem *pItem = (CItem *)hObj; + return pItem->GetItemType(); +} +//--------------------------------------------------------------------- +extern "C" __declspec(dllexport) +LPCBYTE mcmCreateStorage(HANDLE hObj, LPDWORD pSize) +{ + ASSERT(hObj); + CItem *pItem = (CItem *)hObj; + return pItem->CreateStorage(pSize); +} +//--------------------------------------------------------------------- +extern "C" __declspec(dllexport) +void mcmDeleteStorage(HANDLE hObj, LPCBYTE pStorage) +{ + ASSERT(hObj); + CItem *pItem = (CItem *)hObj; + pItem->DeleteStorage(pStorage); +} +//--------------------------------------------------------------------- +extern "C" __declspec(dllexport) +void mcmDeleteObject(HANDLE hObj) +{ + ASSERT(hObj); + CItem *pItem = (CItem *)hObj; + if( pItem != NULL ) delete pItem; +} +//--------------------------------------------------------------------- +extern "C" __declspec(dllexport) +DWORD mcmEdit(HANDLE hObj, HWND hWnd) +{ + ASSERT(hObj); + CItem *pItem = (CItem *)hObj; + int r = pItem->EditDialog(hWnd); + return r; +} +//--------------------------------------------------------------------- +extern "C" __declspec(dllexport) +DWORD mcmFont(HANDLE hObj, HWND hWnd) +{ + ASSERT(hObj); + CItem *pItem = (CItem *)hObj; + + int r = pItem->FontDialog(hWnd); + ::SetForegroundWindow(hWnd); + return r; +} +//--------------------------------------------------------------------- +extern "C" __declspec(dllexport) +DWORD mcmGetOrgSize(HANDLE hObj) +{ + ASSERT(hObj); + CItem *pItem = (CItem *)hObj; + return pItem->GetOrgSize(); +} +//--------------------------------------------------------------------- +extern "C" __declspec(dllexport) +void mcmPos(HANDLE hObj, DWORD pos, DWORD size, DWORD tsize) +{ + ASSERT(hObj); + CItem *pItem = (CItem *)hObj; + pItem->SetPos(pos, size, tsize); +} +//--------------------------------------------------------------------- +extern "C" __declspec(dllexport) +LPCSTR mcmGetUserText(HANDLE hObj) +{ + ASSERT(hObj); + CItem *pItem = (CItem *)hObj; + return pItem->GetText(); +} +//--------------------------------------------------------------------- +extern "C" __declspec(dllexport) +HBITMAP mcmUpdateText(HANDLE hObj, HBITMAP hDest, LPCSTR pText) +{ + ASSERT(hObj); + ASSERT(hDest); + CItem *pItem = (CItem *)hObj; + + // Draw object to hDest + Graphics::TBitmap *pDest = new Graphics::TBitmap; + pDest->Handle = hDest; + pDest = pItem->Draw(pDest, pText); + + HBITMAP hb = pDest->ReleaseHandle(); + delete pDest; + return (hb != hDest) ? hb : NULL; +} +//--------------------------------------------------------------------- +extern "C" __declspec(dllexport) +HBITMAP mcmUpdateImage(HANDLE hObj, HBITMAP hDest, HBITMAP hSrc) +{ + ASSERT(0); // This function should not be called + return NULL; +} +//--------------------------------------------------------------------- +extern "C" __declspec(dllexport) +void mcmSetDraft(HANDLE hObj, DWORD draft) +{ + ASSERT(hObj); + CItem *pItem = (CItem *)hObj; + + pItem->SetDraft(draft); +} +//--------------------------------------------------------------------- +extern "C" __declspec(dllexport) +void mcmSetEx(HANDLE hObj, DWORD ex) +{ + ASSERT(hObj); + CItem *pItem = (CItem *)hObj; + + pItem->SetEx(ex); +} +//--------------------------------------------------------------------- +extern "C" __declspec(dllexport) +void mcmGetFont(HANDLE hObj, LOGFONT *pLogfont) +{ + ASSERT(hObj); + CItem *pItem = (CItem *)hObj; + + pItem->GetFont(pLogfont); +} +//--------------------------------------------------------------------- +extern "C" __declspec(dllexport) +void mcmSetFont(HANDLE hObj, LOGFONT *pLogfont) +{ + ASSERT(hObj); + CItem *pItem = (CItem *)hObj; + + pItem->SetFont(pLogfont); +} + diff --git a/CItems/TextArt/TextArt.rc b/CItems/TextArt/TextArt.rc new file mode 100644 index 0000000..6dfcdc1 --- /dev/null +++ b/CItems/TextArt/TextArt.rc @@ -0,0 +1,4 @@ +#include "res.h" + +ID_ICON ICON DISCARDABLE "Item.ico" +ID_BUILTIN BITMAP DISCARDABLE "res\P.bmp" diff --git a/CItems/TextArt/TextDlg.cpp b/CItems/TextArt/TextDlg.cpp new file mode 100644 index 0000000..949bb7e --- /dev/null +++ b/CItems/TextArt/TextDlg.cpp @@ -0,0 +1,3438 @@ +//--------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "res.h" +#include "TextDlg.h" +//--------------------------------------------------------------------- +#pragma resource "*.dfm" +//TTextDlgBox *TextDlgBox; +//--------------------------------------------------------------------- +__fastcall TTextDlgBox::TTextDlgBox(TComponent* AOwner) + : TForm(AOwner) +{ + MultProc(); + m_DisEvent = 1; + m_pBitmap = NULL; + m_pMaskBmp = NULL; + m_Change = 0; + m_DropProfile = 0; + m_FText = ""; + m_MemoDown = 0; + m_MouseHold = 0; + if( sys.m_MsgEng ){ + Font->Name = "Arial"; + Font->Charset = ANSI_CHARSET; + + Caption = VER" "TTL; + TabChar->Caption = "Set text and colors"; + TabMask->Caption = "Bitmap Mask"; + TabPer->Caption = "Deformations"; + CancelBtn->Caption = "Cancel"; + CancelBtn2->Caption = "Cancel"; + CancelBtn3->Caption = "Cancel"; + FontBtn->Caption = "Font"; + SBM->Caption = "Mac"; + SBL->Caption = "Code"; + GBG->Caption = "Gradation"; + GBS->Caption = "Shadow"; + GBA->Caption = "Misc"; + CBZero->Caption = "Slash zero"; + SBLD->Caption = "Del"; + SBLW->Caption = "Add"; + GBY->Caption = "Style profiles"; + L1->Caption = "Align"; + L2->Caption = "Style name"; + L33->Caption = "V.space"; + L34->Caption = "Rot."; + SBYD->Caption = "Del"; + SBYW->Caption = "Add"; + CBY->Text = "Untitled"; + + SBM->Hint = "Insert macro-keyword"; + SBL->Hint = "Character code list"; + SBC->Hint = "Choose color's component"; + SBLD->Hint = "Delete the text in the list"; + SBLW->Hint = "Add current text into the list"; + SBYD->Hint = "Delete the style in the profiles"; + SBYW->Hint = "Add current style into the profiles"; + SB3DD->Hint = "Make the shadow shorter"; + SB3DI->Hint = "Make the shadow longer"; + SBA1->Hint = "Left"; + SBA2->Hint = "Center"; + SBA3->Hint = "Right"; + SBA4->Hint = "Auto"; +// FontBtn->Hint = "Choose font"; + SBFD->Hint = "Make the font smaller"; + SBFI->Hint = "Make the font bigger"; + SBB->Hint = "Bold"; + SBI->Hint = "Italic"; + SBMSG->Hint = "Show messages list"; + Msg->Hint = "Copy the message to the text box with double click"; + SBGRev->Hint = "Reverses color's order"; + SBGRot->Hint = "Rotates color's order"; + SBGA->Hint = "Default combination"; + SBGRand->Hint = "Random combination"; + DefBtn->Caption = "Default"; + L51->Caption = "Rot.X"; + L52->Caption = "Rot.Y"; + L53->Caption = "Rot.Z"; + L54->Caption = "Move.Z"; + L55->Caption = "Move.Y"; + L56->Caption = "Move.X"; + L57->Caption = "ViewP."; + L58->Caption = "Scale.X"; + L59->Caption = "Scale.Y"; + L60->Caption = "Rot"; + L61->Caption = "Deformation rate"; + DefBtn->Hint = "Return to the default"; + SBR->Hint = "Return to the default"; + + L80->Caption = "Bitmap mask"; + CBBMask->Caption = "Enable bitmap mask"; + GB1->Caption = "Mask"; + GB2->Caption = "Built-in mask"; + GB3->Caption = "Edit mask"; + SBMLoad->Hint = "Load mask from file"; + SBMPaste->Hint = "Paste mask from the clipboard"; + SBMCopy->Hint = "Copy mask to the clipboard"; + SBMRot->Hint = "Rotates right"; + SBMMir->Hint = "Right and left turning over"; + SBAdjCol->Hint = "Adjusts mask image"; + SBClip->Hint = "Clipper"; + SBInvCol->Hint = "Inverts mask color"; + SBRotCol->Hint = "Rotates mask color"; + SBPtn->Hint = "Make random pattern"; + SBMEdit->Hint = "Edit mask"; + + GB4->Caption = "User definition mask"; + L90->Caption = "Drag&&Drop for registration"; + SBMList->Hint = "User definition mask"; + + GB5->Caption = "Filter"; + } + else { + Caption = VER" "TTLJ; + CBY->Text = "無題"; + } + SBFD->Glyph->Assign(SB3DD->Glyph); + SBFI->Glyph->Assign(SB3DI->Glyph); + MultProc(); + if( sys.m_pTextList == NULL ){ + sys.m_pTextList = new TStringList; + LoadStringsFromIniFile(sys.m_pTextList, "Strings", ININAME, TRUE); + MultProc(); + if(!sys.m_pTextList->Count){ + sys.m_pTextList->Add("%c\\r\\nde %m"); + sys.m_pTextList->Add("CQSSTV"); + sys.m_pTextList->Add("Best 73"); + } + } + ASSERT(sys.m_pTextList); + CBList->Items->Assign(sys.m_pTextList); + if( sys.m_pStyleList == NULL ){ + sys.m_pStyleList = new TStringList; + LoadStringsFromIniFile(sys.m_pStyleList, "Styles", ININAME, FALSE); + MultProc(); + } + CBY->Items->Assign(sys.m_pStyleList); + CBY->Sorted = TRUE; + int i; + if( sys.m_pFontList == NULL ){ + sys.m_pFontList = new TStringList; + char fname[512]; + sprintf(fname, "%s%s", sys.m_BgnDir, ININAME); + TMemIniFile *pIniFile = new TMemIniFile(fname); + for( i = 0; i < 5; i++ ){ + char bf[32]; + sprintf(bf, "Font.%u", i); + AnsiString as = pIniFile->ReadString(bf, "FontName", ""); + if( !as.IsEmpty() ){ + BYTE charset = (BYTE)pIniFile->ReadInteger(bf, "FontSet", 0); + DWORD style = pIniFile->ReadInteger(bf, "FontStyle", 0); + AddStyle(as, charset, style); + } + sys.m_pFontList->Add(as); + } + delete pIniFile; + } + for( i = 0; i < 5; i++ ) SetSBF(i); + ShowHint = sys.m_WinNT; + MultProc(); + m_XC = -1; + + for( i = 0; i < AN(m_DirTB); i++ ){ + m_DirTB[i] = 1; + } + HBITMAP hb = ::LoadBitmap(sys.m_hInstance, MAKEINTRESOURCE(ID_BUILTIN)); + m_pBuiltInBmp = new Graphics::TBitmap; + m_pBuiltInBmp->Handle = hb; + + m_pMaskBak = NULL; + m_pCustomBmp = NULL; + m_pMListBmp = NULL; + m_pMLSrcBmp = NULL; + m_MLIndex = -1; + + PC1->Color = sys.m_MaskC1.c; + PC2->Color = sys.m_MaskC2.c; + m_MaskMouseCapture = FALSE; + m_MaskXW = m_MaskYW = 32; + m_MaskX = m_MaskY = 0; + m_pCodeView = NULL; + m_hClipNext = ::SetClipboardViewer(Handle); +#if UseDraft + m_Draft = 0; +#endif + m_ExecPB = 0; + srand(::GetTickCount()); + +#if 0 // 組み込みマスクビットマップの作成 +#define CUSTOMMAX 16 + Graphics::TBitmap *pBmp = CreateBitmap(32*CUSTOMMAX, 32); + Graphics::TBitmap *pSrc; + char name[256]; + for( i = 0; i < CUSTOMMAX; i++ ){ + wsprintf(name, "%sres\\P%u.bmp", sys.m_BgnDir, i+1); + FILE *fp = fopen(name, "rb"); + if( fp != NULL ){ + fclose(fp); + pSrc = new Graphics::TBitmap; + pSrc->LoadFromFile(name); + pBmp->Canvas->Draw(i*32, 0, pSrc); + delete pSrc; + } + } + wsprintf(name, "%sres\\P.bmp", sys.m_BgnDir); + pBmp->SaveToFile(name); + delete pBmp; +#endif +} +//--------------------------------------------------------------------- +void __fastcall TTextDlgBox::FormDestroy(TObject *Sender) +{ + Timer->Enabled = FALSE; + ::ChangeClipboardChain(Handle, m_hClipNext); + if( m_pBitmap != NULL ) delete m_pBitmap; + if( m_pMaskBmp != NULL ) delete m_pMaskBmp; + if( m_pMLSrcBmp != NULL ) delete m_pMLSrcBmp; + if( m_pCustomBmp != NULL ) delete m_pCustomBmp; + DeleteMaskSrc(); + if( m_pBuiltInBmp != NULL ) delete m_pBuiltInBmp; + if( m_pMaskBak ) delete m_pMaskBak; + MultProc(); + if( m_pMListBmp != NULL ){ + if( m_pMListBmp->Modified ){ + char name[256]; + wsprintf(name, "%s"USERMASK, sys.m_BgnDir); + try { + m_pMListBmp->SaveToFile(name); + } + catch(...){ + } + } + delete m_pMListBmp; + } + if( m_pCodeView ) delete m_pCodeView; + + ASSERT(sys.m_pTextList); + sys.m_pTextList->Assign(CBList->Items); + sys.m_MaskC1.c = PC1->Color; + sys.m_MaskC2.c = PC2->Color; + if( m_ExecPB ) QuitPB(FALSE); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::TopMost(void) +{ +#if UseHWND + ::SetWindowPos(Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); +#endif +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::NoTopMost(void) +{ +#if UseHWND + ::SetWindowPos(Handle, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); +#endif +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::UpdateUI(void) +{ + m_DisEvent++; + int f; + if( CBBMask->Checked ){ + SBG1->Visible = FALSE; + SBG2->Visible = FALSE; + SBG3->Visible = FALSE; + SBG4->Visible = FALSE; + SBG5->Visible = FALSE; + PG1->Visible = FALSE; + PG2->Visible = FALSE; + PG3->Visible = FALSE; + PG4->Visible = FALSE; + PG5->Visible = FALSE; + PG6->Visible = FALSE; + SBC->Visible = FALSE; + SBGA->Visible = FALSE; + SBGRand->Visible = FALSE; + SBGRot->Visible = FALSE; + SBGRev->Visible = FALSE; + L80->Visible = TRUE; + } + else { + SBG1->Visible = TRUE; + SBG2->Visible = TRUE; + SBG3->Visible = TRUE; + SBG4->Visible = TRUE; + SBG5->Visible = TRUE; + PG1->Visible = TRUE; + L80->Visible = FALSE; + int f = SBG1->Down ? FALSE : TRUE; + int f2 = SBG5->Down; + PG2->Visible = f; + PG3->Visible = f; + PG4->Visible = f; + SBC->Visible = f && !f2 && sys.m_fColorComp; + PG5->Visible = f2; + PG6->Visible = f2; + SBGA->Visible = f2; + SBGRand->Visible = f2; + SBGRot->Visible = f; + SBGRev->Visible = f; + } + f = !SBS1->Down; + if( !f ) CB3D->Checked = FALSE; + CB3D->Enabled = f; + PB1->Visible = f && (!SBS2->Down || !CB3D->Checked); + PB2->Visible = f && (SBS4->Down || CB3D->Checked); + PB3->Visible = f && CB3D->Checked; + UDL->Enabled = f && (SBS3->Down || !CB3D->Checked); + SBLW->Enabled = (!m_FText.IsEmpty() && CBList->Items->IndexOf(m_FText) < 0) ? TRUE : FALSE; + SBLD->Enabled = CBList->ItemIndex >= 0 ? TRUE : FALSE; + SBYW->Enabled = !CBY->Text.IsEmpty(); + SBYD->Enabled = !CBY->Text.IsEmpty() && (sys.m_pStyleList->IndexOf(CBY->Text) >= 0); + UDX->Enabled = CB3D->Checked; + UDY->Enabled = CB3D->Checked; + SB3DI->Enabled = CB3D->Checked; + SB3DD->Enabled = CB3D->Checked; + if( ShowHint ){ + char bf[32]; + sprintf(bf, "W = %d", UDL->Position); + UDL->Hint = bf; + sprintf(bf, "3D(Y) = %d", UDY->Position); + UDY->Hint = bf; + sprintf(bf, "3D(X) = %d", UDX->Position); + UDX->Hint = bf; + } + Msg->Visible = SBMSG->Down; + CBMSize->Enabled = CBBMask->Checked; + SBAdjCol->Visible = sys.m_fAdjCol != NULL; + SBClip->Visible = sys.m_fClip != NULL; + f = m_pMaskBmp != NULL; + SBMCopy->Enabled = f; + SBMRot->Enabled = f; + SBMMir->Enabled = f; + SBInvCol->Enabled = f; + SBRotCol->Enabled = f; + SBAdjCol->Enabled = f; + SBClip->Enabled = f; + + f = SBMList->Down; + GB1->Visible = !f; + GB4->Visible = f; + + f = !SB->Down; + TBSC->Enabled = f; + SBR->Enabled = f; + + TBF->Enabled = !SBFN->Down; + m_DisEvent--; +} +//--------------------------------------------------------------------- +void __fastcall TTextDlgBox::UpdateMemoFont(BYTE charset) +{ + switch(charset){ + case SHIFTJIS_CHARSET: + case HANGEUL_CHARSET: + case JOHAB_CHARSET: + case CHINESEBIG5_CHARSET: // + case 134: // 簡略 + break; + default: + charset = Font->Charset; + break; + } + m_DisEvent++; + if( Memo->Font->Charset != charset ){ + Memo->Font->Charset = charset; + } + m_DisEvent--; + UpdateFontBtnHint(); +} +//--------------------------------------------------------------------- +int __fastcall TTextDlgBox::Execute(CItem *pItem) +{ + MultProc(); + m_Item.Copy(pItem); + + if( (sys.m_DefaultPage >= 0) && (sys.m_DefaultPage < Page->PageCount) ){ + Page->ActivePage = Page->Pages[sys.m_DefaultPage]; + } + + UpdateDialog(&m_Item); + UpdateBitmap(); + UpdateSBSrc(); + m_DisEvent = 0; + SBMList->Down = sys.m_SBMListState; + if( SBMList->Down ) SBMListClick(NULL); + MultProc(); + int r = ShowModal(); + sys.m_DefaultPage = GetActiveIndex(Page); + sys.m_SBMListState = SBMList->Down; + if( Msg->Modified ) sys.m_Msg = Msg->Text; + if( r == IDOK ){ + MultProc(); +#if UseDraft + if( m_Draft ){ + m_Draft = 0; + UpdateItem(&m_Item); + } +#endif + pItem->Copy(&m_Item); + pItem->m_OrgXW = -1; + MultProc(); + return TRUE; + } + else { + MultProc(); + return FALSE; + } +} +//--------------------------------------------------------------------- +void __fastcall TTextDlgBox::UpdateFText(void) +{ + AnsiString as; + if( Memo->Text.IsEmpty() ){ + m_FText = ""; + } + else { + ::CrLf2Yen(as, Memo->Text); + LPSTR p = as.c_str(); + if( *p ){ + *(p+strlen(p)-1) = 0; + m_FText = p+1; + } + } + m_DisEvent++; + CBList->ItemIndex = CBList->Items->IndexOf(m_FText); + m_DisEvent--; +} +//--------------------------------------------------------------------- +void __fastcall TTextDlgBox::UpdateItem(CItem *pItem) +{ + UpdateUI(); + if( SBG1->Down ){ + pItem->m_Grade = 0; + } + else if( SBG2->Down ){ + pItem->m_Grade = 1; + } + else if( SBG3->Down ){ + pItem->m_Grade = 2; + } + else if( SBG4->Down ){ + pItem->m_Grade = 3; + } + else { + pItem->m_Grade = 4; + } + if( SBS1->Down ){ + pItem->m_Shadow = 0; + } + else if( SBS2->Down ){ + pItem->m_Shadow = 1; + } + else if( SBS3->Down ){ + pItem->m_Shadow = 2; + } + else { + pItem->m_Shadow = 3; + } + if( SBA1->Down ){ + pItem->m_Align = 0; + } + else if( SBA2->Down ){ + pItem->m_Align = 1; + } + else if( SBA3->Down ){ + pItem->m_Align = 2; + } + else { + pItem->m_Align = 3; + } + pItem->m_ColB[0].c = PB1->Color; + pItem->m_ColB[1].c = PB2->Color; + pItem->m_ColB[2].c = PB3->Color; + if( pItem->m_Grade == 4 ){ + pItem->m_ColF[0].c = PG1->Color; + pItem->m_ColF[1].c = PG2->Color; + pItem->m_ColF[2].c = PG3->Color; + pItem->m_ColF[3].c = PG4->Color; + pItem->m_ColF[4].c = PG5->Color; + pItem->m_ColF[5].c = PG6->Color; + } + else { + pItem->m_ColG[0].c = PG1->Color; + pItem->m_ColG[1].c = PG2->Color; + pItem->m_ColG[2].c = PG3->Color; + pItem->m_ColG[3].c = PG4->Color; + } + pItem->m_Line = UDL->Position; + pItem->m_Zero = CBZero->Checked; + pItem->m_Text = Memo->Text.c_str(); + pItem->m_3d = (CB3D->Enabled && CB3D->Checked) ? 0x00010000 : 0; + pItem->m_3d |= ((UDY->Position << 8)&0x0000ff00); + pItem->m_3d |= (UDX->Position & 0x000000ff); + pItem->m_OYW = UDOYW->Position & 0x0000ffff; + pItem->m_OYWS = 0; + pItem->m_Rot = UDRot->Position; + + LPSPERSPECT psp = &pItem->m_sperspect; + psp->ax = double(TBAX->Position)/20.0; + psp->ay = double(TBAY->Position)/20.0; + psp->px = double(TBPX->Position)/20.0; + psp->py = double(TBPY->Position)/20.0; + psp->pz = double(TBPZ->Position)/20.0; + psp->rx = TBRX->Position; + psp->ry = TBRY->Position; + psp->rz = TBRZ->Position; + psp->s = double(TBS->Position)/10.0; + psp->r = TBR->Position; + UpdateWaveBtn(1); + psp->flag = m_Wave; + pItem->m_SC = TBSC->Position; + + pItem->m_Filter = 0; + if( SBFA->Down ){ + pItem->m_Filter = 0x10000; + } + else if( SBFB->Down ){ + pItem->m_Filter = 0x20000; + } + pItem->m_Filter |= TBF->Position; + +#if UseDraft + if( m_Draft ){ + psp->s *= 2; + pItem->m_OYW = (UDOYW->Position/2) & 0x0000ffff; + } + pItem->m_pFont->Height = m_Draft ? m_FontHeight / 2 : m_FontHeight; +#else + pItem->m_pFont->Height = m_FontHeight; +#endif + pItem->UpdateFont(); + +#if 0 + static int count = 0; + char bf[256]; + wsprintf(bf, "%u - %u", m_Draft, count++ ); + Caption = bf; +#endif +} +//--------------------------------------------------------------------- +void __fastcall TTextDlgBox::UpdateDialog(CItem *pItem) +{ + m_DisEvent++; + switch(pItem->m_Grade){ + case 1: + SBG2->Down = TRUE; + break; + case 2: + SBG3->Down = TRUE; + break; + case 3: + SBG4->Down = TRUE; + break; + case 4: + SBG5->Down = TRUE; + break; + default: + SBG1->Down = TRUE; + break; + } + switch(pItem->m_Shadow){ + case 1: + SBS2->Down = TRUE; + break; + case 2: + SBS3->Down = TRUE; + break; + case 3: + SBS4->Down = TRUE; + break; + default: + SBS1->Down = TRUE; + break; + } + switch(pItem->m_Align){ + case 1: + SBA2->Down = TRUE; + break; + case 2: + SBA3->Down = TRUE; + break; + case 3: + SBA4->Down = TRUE; + break; + default: + SBA1->Down = TRUE; + break; + } + PB1->Color = pItem->m_ColB[0].c; + PB2->Color = pItem->m_ColB[1].c; + PB3->Color = pItem->m_ColB[2].c; + if( SBG5->Down ){ + PG1->Color = pItem->m_ColF[0].c; + PG2->Color = pItem->m_ColF[1].c; + PG3->Color = pItem->m_ColF[2].c; + PG4->Color = pItem->m_ColF[3].c; + PG5->Color = pItem->m_ColF[4].c; + PG6->Color = pItem->m_ColF[5].c; + } + else { + PG1->Color = pItem->m_ColG[0].c; + PG2->Color = pItem->m_ColG[1].c; + PG3->Color = pItem->m_ColG[2].c; + PG4->Color = pItem->m_ColG[3].c; + } + UDL->Position = SHORT(pItem->m_Line); + CBZero->Checked = pItem->m_Zero; + CB3D->Checked = pItem->m_3d & 0x00010000; + int xm = pItem->m_3d & 0x000000ff; + int ym = (pItem->m_3d >> 8) & 0x000000ff; + if( xm & 0x0080 ) xm |= 0xffffff80; + if( ym & 0x0080 ) ym |= 0xffffff80; + UDY->Position = SHORT(ym); + UDX->Position = SHORT(xm); + if( pItem->m_pFont != NULL ){ + m_FontHeight = pItem->m_pFont->Height; + UpdateMemoFont(pItem->m_pFont->Charset); + UpdateFontBtnHint(); + } + Memo->Text = pItem->m_Text.c_str(); + + UDOYW->Position = (SHORT)pItem->GetTrueOYW(); + UDRot->Position = (SHORT)pItem->m_Rot; + switch(pItem->m_Filter & 0x30000){ + case 0x10000: + SBFA->Down = TRUE; + break; + case 0x20000: + SBFB->Down = TRUE; + break; + default: + SBFN->Down = TRUE; + break; + } + TBF->Position = pItem->m_Filter & 0x00ff; + UpdateFText(); + + + LPSPERSPECT psp = &pItem->m_sperspect; + TBAX->Position = psp->ax * 20.0 + 0.5; + TBAY->Position = psp->ay * 20.0 + 0.5; + TBPX->Position = psp->px * 20.0; + TBPY->Position = psp->py * 20.0; + TBPZ->Position = psp->pz * 20.0; + TBRX->Position = psp->rx; + TBRY->Position = psp->ry; + TBRZ->Position = psp->rz; + TBS->Position = psp->s * 10.0 + 0.5; + TBR->Position = psp->r; + m_Wave = psp->flag; + UpdateWaveBtn(0); + TBSC->Position = (SHORT)pItem->m_SC; + UpdateHint(); + UpdateTB(); + + CBBMask->Checked = pItem->m_pMaskBmp != NULL; + if( pItem->m_pMaskBmp ){ + if( m_pMaskBmp ) delete m_pMaskBmp; + m_MaskXW = pItem->m_pMaskBmp->Width; + m_MaskYW = pItem->m_pMaskBmp->Height; + m_MaskX = m_MaskY = 0; + m_pMaskBmp = CreateBitmap(m_MaskXW, m_MaskYW); + m_pMaskBmp->Canvas->Draw(0, 0, pItem->m_pMaskBmp); + UpdateCBMSize(); + UpdateSBSrc(); + } + m_DisEvent--; +} +//--------------------------------------------------------------------- +void __fastcall TTextDlgBox::UpdateHint(void) +{ + if( sys.m_WinNT ){ + char bf[128]; + wsprintf(bf, "VP: %d", TBS->Position); + TBS->Hint = bf; + wsprintf(bf, "SX: %d", TBAX->Position); + TBAX->Hint = bf; + wsprintf(bf, "SY: %d", TBAY->Position); + TBAY->Hint = bf; + wsprintf(bf, "PX: %d", TBPX->Position); + TBPX->Hint = bf; + wsprintf(bf, "PY: %d", TBPY->Position); + TBPY->Hint = bf; + wsprintf(bf, "PZ: %d", TBPZ->Position); + TBPZ->Hint = bf; + wsprintf(bf, "RX: %d", TBRX->Position); + TBRX->Hint = bf; + wsprintf(bf, "RY: %d", TBRY->Position); + TBRY->Hint = bf; + wsprintf(bf, "RZ: %d", TBRZ->Position); + TBRZ->Hint = bf; + wsprintf(bf, "R: %d", TBR->Position); + TBR->Hint = bf; + wsprintf(bf, "%d", TBSC->Position); + TBSC->Hint = bf; + wsprintf(bf, "Level:%d", TBF->Position + 1); + TBF->Hint = bf; + } +} +//--------------------------------------------------------------------- +void __fastcall TTextDlgBox::UpdateWaveBtn(int dir) +{ + TSpeedButton *tbl[]={ + SB, SBZ1, SBZ2, SBZ3, SBZ4, SBZ5, SBZ6, SBZ7, + SBZ8, SBZ9, SBZ10, SBZ11, SBZ12, SBZ13, SBZ14, + SBZ15, SBZ16, SBZ17, SBZ18, SBZ19, SBZ20, SBZ21, + SBZ22, SBZ23, SBZ24, SBZ25, SBZ26, SBZ27, SBZ28, + SBZ29, SBZ30, SBZ31, SBZ32, SBZ33, SBZ34, SBZ35, + SBZ36, SBZ37, SBZ38, + NULL, + }; + if( dir ){ + for( int i = 0; tbl[i] != NULL; i++ ){ + if( tbl[i]->Down ){ + m_Wave = i; + break; + } + } + } + else { + if( m_Wave >= (AN(tbl)-1) ) m_Wave = 0; + tbl[m_Wave]->Down = TRUE; + } +} +//--------------------------------------------------------------------- +void __fastcall TTextDlgBox::UpdateBitmap(void) +{ + MultProc(); + m_Change = 0; + UpdateItem(&m_Item); + char bf[1024]; + sys.m_fConvMac(bf, m_Item.GetText(), sizeof(bf)-1); + MultProc(); + if( m_pBitmap == NULL ){ + int xw = m_Item.m_OrgXW; + int yw = m_Item.m_OrgYW; + if( (xw < 0)||(yw < 0) ){ + xw = 160; + yw = 128; + } + m_pBitmap = CreateBitmap(xw, yw); + } + FillBitmap(m_pBitmap, m_Item.m_Back); + MultProc(); +#if MeasureAccuracy + LARGE_INTEGER liFreq; + + QueryPerformanceFrequency(&liFreq); + m_pBitmap = m_Item.Draw(m_pBitmap, bf); + int t1 = int(m_Item.m_dlDiff1 * 100000 / liFreq.QuadPart); + int t2 = int(m_Item.m_dlDiff2 * 100000 / liFreq.QuadPart); + int t3 = int(m_Item.m_dlDiff3 * 100000 / liFreq.QuadPart); + int t4 = t1 + t2 + t3; + int t1p = int(m_Item.m_dlDiffPer1 * 100000 / liFreq.QuadPart); + int t2p = int(m_Item.m_dlDiffPer2 * 100000 / liFreq.QuadPart); + int xw = m_Item.Get1stXW(); + int yw = m_Item.Get1stYW(); + sprintf(bf, "%ux%u, %u.%02u + %u.%02u + %u.%02u = %u.%02u (%u.%02u + %u.%02u)", + xw, yw, + t1 / 100, t1 % 100, + t2 / 100, t2 % 100, + t3 / 100, t3 % 100, + t4 / 100, t4 % 100, + t1p / 100, t1p % 100, + t2p / 100, t2p % 100 + ); + Caption = bf; +#else + m_pBitmap = m_Item.Draw(m_pBitmap, bf); +#endif +#if 1 + PBoxPaint(NULL); +#else + if( Page->ActivePage == TabChar ){ + PBox->Invalidate(); + } + else { + PBoxPer->Invalidate(); + } +#endif + UpdateHint(); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::FillPBox(TPaintBox *pBox) +{ + TRect rc; + rc.Left = 0; + rc.Top = 0; + rc.Right = pBox->Width; + rc.Bottom = pBox->Height; + pBox->Canvas->Brush->Color = clBtnFace; + pBox->Canvas->FillRect(rc); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::PBoxPaint(TObject *Sender) +{ + if( !IsWindowVisible(Handle) ) return; + if( m_pBitmap == NULL ) return; + + Graphics::TBitmap *pBitmap = m_pBitmap; + if( sys.m_BitPixel == 16 ){ + pBitmap = new Graphics::TBitmap; + pBitmap->Width = m_pBitmap->Width; + pBitmap->Height = m_pBitmap->Height; + pBitmap->Canvas->Draw(0, 0, m_pBitmap); + } + pBitmap->Transparent = TRUE; + pBitmap->TransparentMode = tmFixed; + pBitmap->TransparentColor = pBitmap->Canvas->Pixels[0][0]; + if( Page->ActivePage == TabChar ){ + FillPBox(PBox); + PBox->Canvas->Draw(0, 0, pBitmap); + } + else if( Page->ActivePage == TabMask ){ + FillPBox(PBoxMask); + PBoxMask->Canvas->Draw(0, 0, pBitmap); + } + else { + FillPBox(PBoxPer); + PBoxPer->Canvas->Draw(0, 0, pBitmap); + } + pBitmap->Transparent = FALSE; + if( pBitmap != m_pBitmap ) delete pBitmap; + if( m_MouseHold ){ + PBox->Canvas->Pen->Color = clBlue; + PBox->Canvas->MoveTo(0, m_MouseYC); + PBox->Canvas->LineTo(PBox->Width, m_MouseYC); + PBox->Canvas->MoveTo(m_MouseXC, 0); + PBox->Canvas->LineTo(m_MouseXC, PBox->Height); + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::MemoChange(TObject *Sender) +{ + if( m_DisEvent ) return; + + m_Change = 2; + Timer->Enabled = TRUE; + UpdateFText(); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::TimerTimer(TObject *Sender) +{ + if( m_Change ){ + m_Change--; + if( !m_Change ){ + Timer->Enabled = m_ExecPB ? TRUE : FALSE; +#if UseDraft + m_Draft = 0; +#endif + UpdateBitmap(); + } + } +#if UseDraft + if( m_Draft ){ + Timer->Enabled = FALSE; + m_Draft = 0; + UpdateBitmap(); + } +#endif + + if( m_ExecPB ){ + if( !m_ExecPBCount || (m_ExecPBCount < 0) ){ + if( !m_ExecPBCount ) m_ExecPBCount = 4; // 2[s] Interval + CheckPBFinished(); + } + if( m_ExecPBCount > 0 ){ + m_ExecPBCount--; + } + else { + m_ExecPBCount++; + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::SBGClick(TObject *Sender) +{ + if( m_DisEvent ) return; + + UpdateBitmap(); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::PB1Click(TObject *Sender) +{ + TPanel *pPanel = (TPanel *)Sender; + InitCustomColor(ColorDialog); + AddCustomColor(ColorDialog, PG1->Color); + AddCustomColor(ColorDialog, PG2->Color); + AddCustomColor(ColorDialog, PG3->Color); + AddCustomColor(ColorDialog, PG4->Color); + AddCustomColor(ColorDialog, PB1->Color); + AddCustomColor(ColorDialog, PB2->Color); + AddCustomColor(ColorDialog, m_Item.m_Back.c); + if( SBG5->Down ){ + AddCustomColor(ColorDialog, PG5->Color); + AddCustomColor(ColorDialog, PG6->Color); + } + + ColorDialog->Color = pPanel->Color; + NoTopMost(); + int r = ColorDialog->Execute(); + TopMost(); + if( r == TRUE ){ + pPanel->Color = ColorDialog->Color; + if( (pPanel == PC1) || (pPanel == PC2) ){ + UpdateCustom(); PBoxCS->Invalidate(); + } + else { + UpdateBitmap(); + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::FormActivate(TObject *Sender) +{ + TopMost(); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::FormDeactivate(TObject *Sender) +{ + NoTopMost(); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::FontBtnClick(TObject *Sender) +{ + FontDialog->Font->Assign(m_Item.m_pFont); + int hOrg = m_FontHeight; + int h = hOrg / 4; + FontDialog->Font->Height = h; + FontDialog->Font->Color = PG1->Color; + NoTopMost(); + int r = FontDialog->Execute(); + TopMost(); + if( r == TRUE ){ + m_Item.m_pFont->Assign(FontDialog->Font); + if( h != m_Item.m_pFont->Height ){ + hOrg = m_Item.m_pFont->Height * 4; + } + m_Item.m_pFont->Height = hOrg; + m_FontHeight = hOrg; + PG1->Color = FontDialog->Font->Color; + m_Item.UpdateFont(); + if( m_Item.m_pFont != NULL ){ + UpdateMemoFont(m_Item.m_pFont->Charset); + } + UpdateBitmap(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::SBMClick(TObject *Sender) +{ + if( sys.m_fGetMacKey ){ + char bf[256]; + NoTopMost(); + int r = sys.m_fGetMacKey(bf, sizeof(bf)); + TopMost(); + if( r ){ + HWND hWnd; + if( SBMSG->Down ){ + Msg->SetFocus(); + hWnd = Msg->Handle; + } + else { + Memo->SetFocus(); + hWnd = Memo->Handle; + } + for( LPCSTR p = bf; *p; p++ ){ + ::PostMessage(hWnd, WM_CHAR, *p, 0); + } + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::SBCClick(TObject *Sender) +{ + if( sys.m_fColorComp ){ + UCOL col[4]; + col[0].c = PG1->Color; + col[1].c = PG2->Color; + col[2].c = PG3->Color; + col[3].c = PG4->Color; + NoTopMost(); + int r = sys.m_fColorComp(&col[0].d); + TopMost(); + if( r ){ + PG1->Color = col[0].c; + PG2->Color = col[1].c; + PG3->Color = col[2].c; + PG4->Color = col[3].c; + UpdateBitmap(); + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::SBLWClick(TObject *Sender) +{ + m_DisEvent++; + CBList->Items->Add(m_FText); + CBList->ItemIndex = CBList->Items->IndexOf(m_FText); + UpdateUI(); + m_DisEvent--; +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::SBLDClick(TObject *Sender) +{ + m_DisEvent++; + if( CBList->ItemIndex >= 0 ){ + int n = CBList->ItemIndex; + CBList->ItemIndex = -1; + CBList->Items->Delete(n); + UpdateUI(); + } + m_DisEvent--; +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::CBListChange(TObject *Sender) +{ + if( m_DisEvent ) return; + if( CBList->ItemIndex < 0 ) return; + + m_DisEvent++; + AnsiString cs; + AnsiString as = CBList->Items->Strings[CBList->ItemIndex]; + m_FText = as; + ::Yen2CrLf(cs, as); + Memo->Text = cs; + UpdateBitmap(); + m_DisEvent--; + Memo->SetFocus(); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::SBYWClick(TObject *Sender) +{ + m_DisEvent++; + int r = sys.m_pStyleList->IndexOf(CBY->Text); + if( r < 0 ) r = sys.m_pStyleList->Count; + + CItem *pItem = new CItem; + pItem->Copy(&m_Item); + pItem->m_Text = CBY->Text; + char bf[64]; + sprintf(bf, "Style.%u", r); + pItem->SaveToInifile(bf, ININAME, TRUE); + delete pItem; + + if( r == sys.m_pStyleList->Count ){ + CBY->Items->Add(CBY->Text); + sys.m_pStyleList->Add(CBY->Text); + UpdateUI(); + } + m_DisEvent--; +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::SBYDClick(TObject *Sender) +{ + m_DisEvent++; + int r = sys.m_pStyleList->IndexOf(CBY->Text); + if( r >= 0 ){ + char bf[64]; + CItem *pItem = new CItem; + int i; + for( i = r; i < sys.m_pStyleList->Count - 1; i++ ){ + sprintf(bf, "Style.%u", i+1); + pItem->LoadFromInifile(bf, ININAME, TRUE); + sprintf(bf, "Style.%u", i); + pItem->SaveToInifile(bf, ININAME, TRUE); + MultProc(); + } + sprintf(bf, "Style.%u", i); + pItem->DeleteInifile(bf, ININAME); + delete pItem; + sys.m_pStyleList->Delete(r); + r = CBY->Items->IndexOf(CBY->Text); + if( r >= 0 ) CBY->Items->Delete(r); + UpdateUI(); + } + m_DisEvent--; +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::CBYChange(TObject *Sender) +{ + if( m_DisEvent ) return; + if( !m_DropProfile ){ + UpdateUI(); + return; + } + m_DropProfile = 0; + + m_DisEvent++; + int r = sys.m_pStyleList->IndexOf(CBY->Text); + if( r >= 0 ){ + AnsiString as = m_Item.m_Text; + DWORD ex = m_Item.GetEx(); + int pos = m_Item.GetPos(); + CItem *pItem = new CItem; + char bf[64]; + sprintf(bf, "Style.%u", r); + pItem->LoadFromInifile(bf, ININAME, TRUE); + m_Item.Copy(pItem); + delete pItem; + m_Item.m_Text = as; + m_Item.SetEx(ex); + m_Item.SetPos(pos); + UpdateDialog(&m_Item); + UpdateBitmap(); + } + m_DisEvent--; +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::CBYKeyPress(TObject *Sender, char &Key) +{ + m_DropProfile = 0; + UpdateUI(); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::CBYDropDown(TObject *Sender) +{ + m_DropProfile = 1; +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::PBoxMouseDown(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( m_DisEvent ) return; + + m_DisEvent++; + if( Button == mbRight ){ + CB3D->Checked = CB3D->Checked ? FALSE : TRUE; + } + else { + CB3D->Checked = TRUE; + m_MouseHold = TRUE; + int xc = m_pBitmap->Width / 2; + int yc = m_pBitmap->Height / 2; + m_MouseXC = xc; + m_MouseYC = yc; + int x = X - xc; + int y = Y - yc; + x = x * 48 / xc; + y = y * 48 / yc; + double s = -UDRot->Position * PI / 180.0; + double cosk = cos(s); + double sink = sin(s); + short xx = x * cosk + y * sink; + short yy = -x * sink + y * cosk; + UDX->Position = SHORT(xx); + UDY->Position = SHORT(yy); + Screen->Cursor = crSizeAll; + } + m_DisEvent--; + UpdateBitmap(); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::PBoxMouseMove(TObject *Sender, + TShiftState Shift, int X, int Y) +{ + if( m_MouseHold ){ + X = X - m_MouseXC; + Y = Y - m_MouseYC; + double s = -UDRot->Position * PI / 180.0; + double cosk = cos(s); + double sink = sin(s); + short x = X * cosk + Y * sink; + short y = -X * sink + Y * cosk; + short UX = UDX->Position; + short UY = UDY->Position; + m_DisEvent++; + UDX->Position = short(x); + UDY->Position = short(y); + m_DisEvent--; + if( (UX != UDX->Position) || (UY != UDY->Position) ){ +#if UseDraft + m_Draft = TRUE; + Timer->Enabled = TRUE; +#endif + UpdateBitmap(); + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::PBoxMouseUp(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( m_MouseHold ){ + m_MouseHold = 0; + PBox->Invalidate(); + } + Screen->Cursor = crDefault; +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::UDLClick(TObject *Sender, TUDBtnType Button) +{ + SBGClick(NULL); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::UD3D(int a) +{ + m_DisEvent++; + int x = UDX->Position; + int y = UDY->Position; + int xs = (x >= 0) ? 1 : -1; + int ys = (y >= 0) ? 1 : -1; + x = ABS(x); + y = ABS(y); + if( x == y ){ + int ad; + if( x < 4 ){ + ad = 1; + } + else if( x < 12 ){ + ad = 2; + } + else { + ad = 4; + } + ad *= a; + x += ad; + y += ad; + if( x < 2 ) x = 2; + if( y < 2 ) y = 2; + if( x > 48 ) x = 48; + if( y > 48 ) y = 48; + } + else { + if( x < y ) x = y; + x &= 0xfffffffc; + y = x; + } + x *= xs; y *= ys; + UDX->Position = SHORT(x); + UDY->Position = SHORT(y); + m_DisEvent--; + UpdateBitmap(); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::SB3DIClick(TObject *Sender) +{ + UD3D((Sender == SB3DI) ? 1 : -1); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::SBMSGClick(TObject *Sender) +{ + Msg->Visible = SBMSG->Down; + if( SBMSG->Down ){ + Msg->Text = sys.m_Msg; + Msg->Modified = FALSE; + Msg->SelLength = 0; + Msg->SetFocus(); + } + else { + if( Msg->Modified ){ + sys.m_Msg = Msg->Text; + Msg->Modified = FALSE; + } + Memo->SetFocus(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::MsgDblClick(TObject *Sender) +{ + AnsiString as; + AnsiString cs; + + m_DisEvent++; + if( Msg->Lines->Count ){ + int e = Msg->SelStart; + LPCSTR p = Msg->Text.c_str(); + int n = 0; + for( int i = 0; i < e; i++, p++ ){ + if( *p == '\n' ) n++; + } + if( n > Msg->Lines->Count ) n = Msg->Lines->Count - 1; + as = Msg->Lines->Strings[n]; + } + m_FText = as; + ::Yen2CrLf(cs, as); + Memo->Text = cs; + m_DisEvent--; + SBMSG->Down = FALSE; + SBMSGClick(NULL); + MultProc(); + UpdateFText(); + UpdateBitmap(); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::MemoStartDrag(TObject *Sender, + TDragObject *&DragObject) +{ + if( !SBMSG->Down ){ + SBMSG->Down = TRUE; + SBMSGClick(NULL); + } +} +//--------------------------------------------------------------------------- + +void __fastcall TTextDlgBox::MsgDragDrop(TObject *Sender, TObject *Source, + int X, int Y) +{ + Msg->Lines->Add(m_FText); +} +//--------------------------------------------------------------------------- + +void __fastcall TTextDlgBox::MsgDragOver(TObject *Sender, TObject *Source, + int X, int Y, TDragState State, bool &Accept) +{ + if( Source == Memo ) Accept = TRUE; +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::MemoMouseDown(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + m_MemoX = X; + m_MemoY = Y; + m_MemoDown = 1; +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::MemoMouseMove(TObject *Sender, + TShiftState Shift, int X, int Y) +{ + if( m_MemoDown == 1 ){ + X -= m_MemoX; + Y -= m_MemoY; + if( (X*X)+(Y*Y) > 64 ){ + m_MemoDown = 2; + Memo->BeginDrag(TRUE); + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::MemoMouseUp(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + m_MemoDown = 0; +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::FontBtnMouseDown(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( Button == mbRight ){ + BYTE cset; + UINT cp = ::GetACP(); + switch(cp){ + case 932: + cset = SHIFTJIS_CHARSET; + break; + case 949: + cset = HANGEUL_CHARSET; + break; + case 950: + cset = CHINESEBIG5_CHARSET; + break; + case 936: + cset = 134; // 簡略 + break; + default: + cset = DEFAULT_CHARSET; + break; + } + int charset = m_Item.m_pFont->Charset; + m_Item.m_pFont->Charset = BYTE((charset != ANSI_CHARSET) ? ANSI_CHARSET : cset); + m_Item.UpdateFont(); + if( m_Item.m_pFont != NULL ){ + UpdateMemoFont(m_Item.m_pFont->Charset); + } + UpdateBitmap(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::UpdateFontBtnHint(void) +{ + AnsiString as = sys.m_MsgEng ? "Choose font" : "フォントの選択"; + if( m_Item.m_pFont ){ + as += " ["; + as += m_Item.m_pFont->Name; + TFontStyles ts = m_Item.m_pFont->Style; + DWORD d = FontStyle2Code(ts); + AddStyle(as, m_Item.m_pFont->Charset, d); + as += "]"; + SBB->Down = d & FSBOLD; + SBI->Down = d & FSITALIC; + if( m_pCodeView ) m_pCodeView->Execute(Handle, m_Item.m_pFont); + } + FontBtn->Hint = as; +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::SetSBF(int n) +{ + if( !sys.m_pFontList ) return; + + TSpeedButton* _tt[]={SBF1, SBF2, SBF3, SBF4, SBF5, NULL}; + + TSpeedButton* pButton = _tt[n]; + AnsiString es = sys.m_MsgEng ? "Registration = Right button" : "登録=右ボタン"; + AnsiString fs = sys.m_pFontList->Strings[n]; + int undef = fs.IsEmpty(); + if( undef ) fs = sys.m_MsgEng ? "Load registered font" : "登録フォントの読み出し"; + char bf[256]; + sprintf(bf, "%s (%s)", fs.c_str(), es.c_str()); + pButton->Hint = bf; + pButton->Font->Color = undef ? clGrayText : clBlack; +} +//--------------------------------------------------------------------------- +int __fastcall TTextDlgBox::GetSBFIndex(TObject *Sender) +{ + TSpeedButton* _tt[]={SBF1, SBF2, SBF3, SBF4, SBF5, NULL}; + + for( int i = 0; _tt[i]; i++ ){ + if( Sender == _tt[i] ) return i; + } + return 0; +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::SBFClick(TObject *Sender) +{ + if( !sys.m_pFontList ) return; + int N = GetSBFIndex(Sender); + if( sys.m_pFontList->Strings[N].IsEmpty() ) return; + + FontDialog->Font->Assign(m_Item.m_pFont); + + char fname[512]; + sprintf(fname, "%s%s", sys.m_BgnDir, ININAME); + TMemIniFile *pIniFile = new TMemIniFile(fname); + { + char bf[32]; + sprintf(bf, "Font.%u", N); + int ht = m_Item.m_pFont->Height; + LoadFontFromInifile(m_Item.m_pFont, bf, pIniFile); + int hs = m_Item.m_pFont->Height; + m_Item.m_pFont->Height = ht; + m_FontHeight = ht; + int oyw = (short)pIniFile->ReadInteger(bf, "OYW", UDOYW->Position); + if( hs ) oyw = ht * oyw / hs; + UDOYW->Position = (short)oyw; + } + delete pIniFile; + + m_Item.UpdateFont(); + if( m_Item.m_pFont != NULL ){ + UpdateMemoFont(m_Item.m_pFont->Charset); + } + UpdateBitmap(); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::SBFMouseDown(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( Button == mbRight ){ + FontDialog->Font->Assign(m_Item.m_pFont); + FontDialog->Font->Color = clBlack; + NoTopMost(); + int r = FontDialog->Execute(); + TopMost(); + if( r == TRUE ){ + char fname[512]; + sprintf(fname, "%s%s", sys.m_BgnDir, ININAME); + TMemIniFile *pIniFile = new TMemIniFile(fname); + { + int N = GetSBFIndex(Sender); + char bf[32]; + sprintf(bf, "Font.%u", N); + SaveFontToInifile(FontDialog->Font, bf, pIniFile); + pIniFile->WriteInteger(bf, "OYW", UDOYW->Position); + pIniFile->UpdateFile(); + if( sys.m_pFontList ){ + AnsiString as = FontDialog->Font->Name; + TFontStyles ts = FontDialog->Font->Style; + DWORD d = FontStyle2Code(ts); + AddStyle(as, FontDialog->Font->Charset, d); + sys.m_pFontList->Strings[N] = as; + SetSBF(N); + } + } + delete pIniFile; + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::SBBClick(TObject *Sender) +{ + if( !m_Item.m_pFont ) return; + + TFontStyles ts = m_Item.m_pFont->Style; + DWORD d = FontStyle2Code(ts); + d ^= FSBOLD; + ts = Code2FontStyle(d); + m_Item.m_pFont->Style = ts; + + m_Item.UpdateFont(); + if( m_Item.m_pFont != NULL ){ + UpdateMemoFont(m_Item.m_pFont->Charset); + } + UpdateBitmap(); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::SBIClick(TObject *Sender) +{ + if( !m_Item.m_pFont ) return; + + TFontStyles ts = m_Item.m_pFont->Style; + DWORD d = FontStyle2Code(ts); + d ^= FSITALIC; + ts = Code2FontStyle(d); + m_Item.m_pFont->Style = ts; + + m_Item.UpdateFont(); + if( m_Item.m_pFont != NULL ){ + UpdateMemoFont(m_Item.m_pFont->Charset); + } + UpdateBitmap(); +} +//--------------------------------------------------------------------------- + +void __fastcall TTextDlgBox::SBFDMouseDown(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( m_Item.m_pFont == NULL ) return; + + int ad = 0; + int h = m_FontHeight; + if( Sender == SBFD ){ + if( Button == mbLeft ){ + if( h < -2 ) ad = 1; + } + else if( Button == mbRight ){ + if( h < -6 ) ad = 4; + } + } + else { + if( Button == mbLeft ){ + ad = -1; + } + else if( Button == mbRight ){ + ad = -4; + } + } + if( ad ){ + m_FontHeight = h + ad; + UpdateBitmap(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::DefBtnClick(TObject *Sender) +{ + m_DisEvent++; + TBAX->Position = 60; + TBAY->Position = 60; + TBPX->Position = 0; + TBPY->Position = 0; + TBPZ->Position = 0; + TBRX->Position = 0; + TBRY->Position = 0; + TBRZ->Position = -180; + TBR->Position = 0; + TBS->Position = 15; + TBSC->Position = 0; + m_DisEvent--; + UpdateTB(); + SBGClick(NULL); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::SBRClick(TObject *Sender) +{ + if( TBSC->Position ){ + m_DisEvent++; + TBSC->Position = 0; + m_DisEvent--; + SBGClick(NULL); + } + TBSC->SetFocus(); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::PBoxPerMouseDown(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( m_pBitmap == NULL ) return; + + m_SCX = double(m_pBitmap->Width) / double(PBoxPer->Width); + m_SCY = double(m_pBitmap->Height) / double(PBoxPer->Height); + X = X * m_SCX; + Y = Y * m_SCY; + + m_XC = m_pBitmap->Width / 2; + m_YC = m_pBitmap->Height / 2; + int x = X - m_XC; + int y = m_YC - Y; + if( x || y ){ + m_Deg = atan2(y, x); + } + else { + m_Deg = 0; + } + m_Dist = sqrt(x * x + y * y); + m_SDeg = TBR->Position; + m_SDistX = TBAX->Position; + m_SDistY = TBAY->Position; + Screen->Cursor = crSizeAll; +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::PBoxPerMouseMove(TObject *Sender, + TShiftState Shift, int X, int Y) +{ + if( m_XC > 0 ){ + X = X * m_SCX; + Y = Y * m_SCY; + + int x = X - m_XC; + int y = m_YC - Y; + double Deg; + if( x || y ){ + Deg = atan2(y, x); + } + else { + Deg = 0; + } + Deg = (m_Deg - Deg) * 180.0 / PI; + Deg += m_SDeg; + if( Deg < -180 ) Deg += 360.0; + if( Deg > 180 ) Deg -= 360.0; + TBR->Position = SHORT(Deg); + + double Dist = sqrt(x * x + y * y); + Dist = (Dist - m_Dist)/2; + int d = Dist + m_SDistX; + if( d > 201 ) d = 201; + if( d < 2 ) d = 2; + TBAX->Position = d; + d = Dist + m_SDistY; + if( d > 201 ) d = 201; + if( d < 2 ) d = 2; + TBAY->Position = d; + + UpdateTB(); +#if UseDraft + m_Draft = TRUE; + Timer->Enabled = TRUE; +#endif + UpdateBitmap(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::PBoxPerMouseUp(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + m_XC = -1; + Screen->Cursor = crDefault; +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::TBSCChange(TObject *Sender) +{ + if( m_DisEvent ) return; + if( m_Item.m_SC != TBSC->Position ){ + UpdateBitmap(); + } +} +//--------------------------------------------------------------------------- +static void __fastcall UpdateDefTB(TTrackBar *pBar, int f, int def, int &dir) +{ + if( f ){ + pBar->Position = pBar->Position + (pBar->PageSize * dir); + if( pBar->Position == pBar->Max ){ + dir = -1; + } + else if( pBar->Position == pBar->Min ){ + dir = 1; + } + } + else { + pBar->Position = def; + } + pBar->SetFocus(); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::LDefMouseDown(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( (Button != mbLeft) && (Button != mbRight) ) return; + BOOL f = (Button != mbLeft); + + TLabel *_tt[]={L57, L58, L59, L56, L55, L54, L51, L52, L53, L60}; + + int i; + for( i = 0; i < AN(_tt); i++ ){ + if( _tt[i] == (TLabel *)Sender ) break; + } + m_DisEvent++; + switch(i){ + case 0: + UpdateDefTB(TBS, f, 15, m_DirTB[0]); + break; + case 1: + UpdateDefTB(TBAX, f, 60, m_DirTB[1]); + break; + case 2: + UpdateDefTB(TBAY, f, 60, m_DirTB[2]); + break; + case 3: + UpdateDefTB(TBPX, f, 0, m_DirTB[3]); + break; + case 4: + UpdateDefTB(TBPY, f, 0, m_DirTB[4]); + break; + case 5: + UpdateDefTB(TBPZ, f, 0, m_DirTB[5]); + break; + case 6: + UpdateDefTB(TBRX, f, 0, m_DirTB[6]); + break; + case 7: + UpdateDefTB(TBRY, f, 0, m_DirTB[7]); + break; + case 8: + UpdateDefTB(TBRZ, f, -180, m_DirTB[8]); + break; + case 9: + UpdateDefTB(TBR, f, 0, m_DirTB[9]); + break; + } + m_DisEvent--; + UpdateTB(); + SBGClick(NULL); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::UpdateTB(void) +{ + m_SBar[0] = TBS->Position; + m_SBar[1] = TBAX->Position; + m_SBar[2] = TBAY->Position; + m_SBar[3] = TBPX->Position; + m_SBar[4] = TBPY->Position; + m_SBar[5] = TBPZ->Position; + m_SBar[6] = TBRX->Position; + m_SBar[7] = TBRY->Position; + m_SBar[8] = TBRZ->Position; + m_SBar[9] = TBR->Position; +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::TBSChange(TObject *Sender) +{ + if( m_DisEvent ) return; + + TTrackBar *_tt[]={TBS, TBAX, TBAY, TBPX, TBPY, TBPZ, TBRX, TBRY, TBRZ, TBR}; + TTrackBar *pBar = (TTrackBar *)Sender; + + int i; + for( i = 0; i < AN(_tt); i++ ){ + if( _tt[i] == pBar ) break; + } + if( m_SBar[i] != pBar->Position ){ + m_SBar[i] = pBar->Position; + UpdateBitmap(); + } +} +//--------------------------------------------------------------------- +void __fastcall MakeBitmapPtn(Graphics::TBitmap *pBmp, int hw, int sw, UCOL col1, UCOL col2) +{ + hw /= 3; + CWaitCursor wait; + TCanvas *pCanvas = pBmp->Canvas; + int x, y, f, v; + for( y = 0; y < pBmp->Height; y++ ){ + for( x = 0; x < pBmp->Width; x++ ){ + f = x / hw; + switch(sw){ + case 0: + if( (y/2) & 1 ){ + v = (x/2) & 1; + } + else { + v = !((x/2) & 1); + } + break; + case 1: + if( (y/4) & 1 ){ + v = (x/2) & 1; + } + else { + v = !((x/2) & 1); + } + break; + case 2: + if( (y/2) & 1 ){ + v = (x/4) & 1; + } + else { + v = !((x/4) & 1); + } + break; + case 3: + if( (y/4) & 1 ){ + v = (x/4) & 1; + } + else { + v = !((x/4) & 1); + } + break; + case 4: + switch(f){ + case 0: + v = (y/2) & 1; + break; + case 1: + v = (y/4) & 1; + break; + default: + v = (y/8) & 1; + break; + } + break; + case 5: + switch(f){ + case 0: + v = (x/2) & 1; + break; + case 1: + v = (x/4) & 1; + break; + default: + v = (x/8) & 1; + break; + } + break; + case 6: + switch(f){ + case 0: + v = ((y+x)/2) & 1; + break; + case 1: + v = ((y+x)/4) & 1; + break; + default: + v = ((y+x)/8) & 1; + break; + } + break; + case 7: + switch(f){ + case 0: + v = ((x-y+1024)/2) & 1; + break; + case 1: + v = ((x-y+1024)/4) & 1; + break; + default: + v = ((x-y+1024)/8) & 1; + break; + } + break; + } + pCanvas->Pixels[x][y] = v ? col1.c : col2.c; + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::CBBMaskClick(TObject *Sender) +{ + if( m_DisEvent ) return; + + if( CBBMask->Checked ){ + if( !m_pMaskBmp ){ + if( m_pMaskBak ){ + m_pMaskBmp = m_pMaskBak; + m_pMaskBak = NULL; + UpdateMaskSrc(TRUE); + } + else { + m_pMaskBmp = CreateBitmap(PBoxSrc->Width, PBoxSrc->Height); + UCOL c1, c2; + c1.c = PC1->Color; c2.c = PC2->Color; + MakeBitmapPtn(m_pMaskBmp, PBoxSrc->Width, 0, c1, c2); + m_MaskX = m_MaskY = 0; m_MaskXW = m_MaskYW = 8; + } + UpdateItemMask(); + } + } + else { + if( m_pMaskBmp ){ + delete m_pMaskBmp; + m_pMaskBmp = NULL; + } + if( m_Item.m_pMaskBmp ){ + if( m_pMaskBak ) delete m_pMaskBak; + m_pMaskBak = m_Item.m_pMaskBmp; + m_Item.m_pMaskBmp = NULL; + } + } + PBoxSrcPaint(NULL); + UpdateBitmap(); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::L80Click(TObject *Sender) +{ + Page->ActivePage = TabMask; +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::DrawMaskCursor(int x1, int y1, int x2, int y2) +{ + x1 -= SBH->Position; + x2 -= SBH->Position; + y1 -= SBV->Position; + y2 -= SBV->Position; + TCanvas *tp = PBoxSrc->Canvas; + tp->Pen->Width = 1; + tp->Pen->Style = psSolid; + tp->MoveTo(x1, y1); + int rop = ::SetROP2(tp->Handle, R2_NOT); + tp->LineTo(x2, y1); + tp->LineTo(x2, y2); + tp->LineTo(x1, y2); + tp->LineTo(x1, y1); + ::SetROP2(tp->Handle, rop); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::DrawMaskCursor(void) +{ + DrawMaskCursor(m_MaskX, m_MaskY, m_MaskX+m_MaskXW, m_MaskY+m_MaskYW); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::PBoxSrcPaint(TObject *Sender) +{ + if( (Sender != SBV) && (Sender != SBH) ) FillPBox(PBoxSrc); + if( m_pMaskBmp ){ + PBoxSrc->Canvas->Draw(-SBH->Position, -SBV->Position, m_pMaskBmp); + DrawMaskCursor(); + } +} +//--------------------------------------------------------------------------- +static void __fastcall DrawBmpPBoxBtn(TCanvas *pCanvas, int x, int y, int w, BOOL sw) +{ + pCanvas->Pen->Style = psSolid; + pCanvas->Pen->Width = 1; + pCanvas->Pen->Color = sw ? clBlack : clWhite; + w++; + pCanvas->MoveTo(x+w, y); + pCanvas->LineTo(x, y); + pCanvas->LineTo(x, y+w); + pCanvas->LineTo(x+1, y+w); + pCanvas->Pen->Color = sw ? clWhite : clBlack; + pCanvas->LineTo(x+w, y+w); + pCanvas->LineTo(x+w, y); +} +//--------------------------------------------------------------------------- +static void __fastcall DrawBmpPBox(TCanvas *pCanvas, int x, int y, Graphics::TBitmap *pBmp) +{ + pCanvas->Draw(x+1, y+1, pBmp); + DrawBmpPBoxBtn(pCanvas, x, y, pBmp->Width, FALSE); +} +//--------------------------------------------------------------------------- +static int __fastcall GetIndex(int w, int m, int x, int y) +{ + if( ((x % w) < 1) || ((x % w) >= (w-1)) ) return -1; + if( ((y % w) < 1) || ((y % w) >= (w-1)) ) return -1; + x /= w; + y /= w; + int n = (y * 8) + x; + if( n >= m ) n = m-1; + return n; +} +//--------------------------------------------------------------------------- +static void __fastcall DrawBmpPBox(TCanvas *pCanvas, int s, int w, int ws, int x, int y, Graphics::TBitmap *pBmp) +{ + TRect src, drc; + + src.Left = ((y*8)+x)*ws; + src.Right = src.Left + w; + src.Top = 0; src.Bottom = w; + drc.Left = 1 + x*s; + drc.Right = drc.Left + w; + drc.Top = 1 + y*s; + drc.Bottom = drc.Top + w; + pCanvas->CopyRect(drc, pBmp->Canvas, src); + DrawBmpPBoxBtn(pCanvas, x*s, y*s, w, FALSE); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::PBoxBMPaint(TObject *Sender) +{ + int x, y; + for( y = 0; y < 2; y++ ){ + for( x = 0; x < 8; x++ ){ + DrawBmpPBox(PBoxBM->Canvas, 33, 30, 32, x, y, m_pBuiltInBmp); + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::PBoxBMMouseDown(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( Button == mbLeft ){ + m_MIndex = GetIndex(33, 16, X, Y); + if( m_MIndex >= 0 ){ + DrawBmpPBoxBtn(PBoxBM->Canvas, 33*(m_MIndex%8), 33*(m_MIndex/8), 30, TRUE); + Graphics::TBitmap *pBmp = CreateBitmap(32, 32); + pBmp->Canvas->Draw(-m_MIndex*32, 0, m_pBuiltInBmp); + if( !m_pMaskBmp ) m_pMaskBmp = CreateBitmap(32, 32); + if( !IsSameBitmap(pBmp, m_pMaskBmp) ){ + delete m_pMaskBmp; + m_pMaskBmp = pBmp; + UpdateMaskSrc(TRUE); + } + else { + delete pBmp; + } + CBMSize->SetFocus(); + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::PBoxBMMouseUp(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( (Button == mbLeft) && (m_MIndex >= 0) ){ + DrawBmpPBoxBtn(PBoxBM->Canvas, 33*(m_MIndex%8), 33*(m_MIndex/8), 30, FALSE); + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::UpdateCustom(void) +{ + if( !m_pCustomBmp ) m_pCustomBmp = CreateBitmap(16*8, 16); + Graphics::TBitmap *pBmp = CreateBitmap(16, 16); + int i; + for( i = 0; i < 8; i++ ){ + UCOL c1, c2; + c1.c = PC1->Color; c2.c = PC2->Color; + MakeBitmapPtn(pBmp, PBoxSrc->Width, i, c1, c2); + m_pCustomBmp->Canvas->Draw(i*16, 0, pBmp); + } + delete pBmp; +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::PBoxCSPaint(TObject *Sender) +{ + if( !m_pCustomBmp ){ + UpdateCustom(); + if( !m_pCustomBmp ) return; + } + MultProc(); + int x; + for( x = 0; x < 8; x++ ){ + DrawBmpPBox(PBoxCS->Canvas, 18, 16, 16, x, 0, m_pCustomBmp); + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::PBoxCSMouseDown(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( Button == mbLeft ){ + m_MIndex = GetIndex(18, 8, X, Y); + if( m_MIndex >= 0 ){ + DrawBmpPBoxBtn(PBoxCS->Canvas, 18*(m_MIndex%8), 0, 16, TRUE); + + Graphics::TBitmap *pBmp = CreateBitmap(PBoxSrc->Width, PBoxSrc->Height); + UCOL c1, c2; + c1.c = PC1->Color; c2.c = PC2->Color; + MakeBitmapPtn(pBmp, PBoxSrc->Width, m_MIndex, c1, c2); + if( m_pMaskBmp ) delete m_pMaskBmp; + DeleteMaskSrc(); + m_pMaskBmp = pBmp; + m_MaskX = m_MaskY = 0; m_MaskXW = m_MaskYW = 8; + UpdateMaskSrc(FALSE); + CBMSize->SetFocus(); + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::PBoxCSMouseUp(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( (Button == mbLeft) && (m_MIndex >= 0) ){ + DrawBmpPBoxBtn(PBoxCS->Canvas, 18*(m_MIndex%8), 0, 16, FALSE); + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::UpdateItemMask(void) +{ + m_DisEvent++; + CBBMask->Checked = TRUE; + UpdateCBMSize(); + + if( m_pMaskBak ){ + delete m_pMaskBak; + m_pMaskBak = NULL; + } + if( m_Item.m_pMaskBmp ) delete m_Item.m_pMaskBmp; + m_Item.m_pMaskBmp = CreateBitmap(m_MaskXW, m_MaskYW); + m_Item.m_pMaskBmp->Canvas->Draw(-m_MaskX, -m_MaskY, m_pMaskBmp); + m_DisEvent--; +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::PBoxSrcMouseDown(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( !m_pMaskBmp ) return; + + if( Button == mbLeft ){ + X += SBH->Position; Y += SBV->Position; + DrawMaskCursor(); + m_MaskAX = m_MaskX = X; + m_MaskAY = m_MaskY = Y; + m_MaskAXW = m_MaskXW; m_MaskAYW = m_MaskYW; + DrawMaskCursor(); + UpdateItemMask(); + UpdateBitmap(); + m_MaskMouseCapture = 1; + } + else if( Button == mbRight ){ + if( (m_MaskXW > 32) || (m_MaskYW > 32) ){ + Graphics::TBitmap *pSrc = CreateBitmap(m_MaskXW, m_MaskYW); + pSrc->Canvas->Draw(-m_MaskX, -m_MaskY, m_pMaskBmp); + + delete m_pMaskBmp; + m_pMaskBmp = CreateBitmap(32, 32); + StretchCopy(m_pMaskBmp, pSrc, HALFTONE); + delete pSrc; + + m_MaskX = m_MaskY = 0; + m_MaskXW = m_MaskYW = 32; + DeleteMaskSrc(); + } + else { + m_MaskX = m_MaskY = 0; + } + SBH->Position = 0; SBV->Position = 0; + UpdateItemMask(); + PBoxSrcPaint(NULL); + UpdateBitmap(); + } + CBMSize->SetFocus(); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::PBoxSrcMouseMove(TObject *Sender, + TShiftState Shift, int X, int Y) +{ + if( m_MaskMouseCapture ){ + X += SBH->Position; Y += SBV->Position; + if( m_MaskMouseCapture == 1 ){ + m_MaskMouseCapture++; + DrawMaskCursor(); + } + else { + DrawMaskCursor(m_MaskX, m_MaskY, m_MaskAX, m_MaskAY); + } + m_MaskAX = X; m_MaskAY = Y; + DrawMaskCursor(m_MaskX, m_MaskY, m_MaskAX, m_MaskAY); + X = ABS(m_MaskX-m_MaskAX); Y = ABS(m_MaskY-m_MaskAY); + if( (X != m_MaskAXW)||(Y != m_MaskAYW) ){ + m_MaskAXW = X; m_MaskAYW = Y; + UpdateCBMSize(X, Y); + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::PBoxSrcMouseUp(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( m_MaskMouseCapture ){ + X += SBH->Position; Y += SBV->Position; + if( m_MaskMouseCapture != 1 ){ + DrawMaskCursor(m_MaskX, m_MaskY, m_MaskAX, m_MaskAY); + if( (ABS(X-m_MaskX) >= 2) && (ABS(Y-m_MaskY) >= 2) ){ + m_MaskXW = ABS(X-m_MaskX); + m_MaskYW = ABS(Y-m_MaskY); + if( X < m_MaskX ) m_MaskX = X; + if( Y < m_MaskY ) m_MaskY = Y; + UpdateItemMask(); + UpdateBitmap(); + } + DrawMaskCursor(); + } + m_MaskMouseCapture = 0; + UpdateCBMSize(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::UpdateSBSrc(void) +{ + SBH->Position = 0; SBV->Position = 0; + int hmax, vmax; + if( m_pMaskBmp ){ + int xw = m_pMaskBmp->Width; + int yw = m_pMaskBmp->Height; + hmax = xw - PBoxSrc->ClientWidth; + vmax = yw - PBoxSrc->ClientHeight; + } + else { + hmax = vmax = -1; + } + SBH->Max = (hmax > 0) ? hmax : 0; + SBV->Max = (vmax > 0) ? vmax : 0; + SBH->Enabled = (hmax > 0) ? TRUE : FALSE; + SBV->Enabled = (vmax > 0) ? TRUE : FALSE; +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::UpdateMaskSrc(BOOL sw) +{ + DeleteMaskSrc(); + int xw = m_pMaskBmp->Width; + int yw = m_pMaskBmp->Height; + if( sw ){ + m_MaskX = m_MaskY = 0; + if( ((xw <= 32) && (yw <= 32)) ){ + m_MaskXW = xw; m_MaskYW = yw; + } + } + else { + if( m_MaskX >= xw ) m_MaskX = 0; + if( m_MaskY >= yw ) m_MaskY = 0; + } + UpdateSBSrc(); + UpdateItemMask(); + PBoxSrcPaint(NULL); + UpdateBitmap(); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::UpdateMaskSrc(HBITMAP hb) +{ + if( hb != NULL ){ + Graphics::TBitmap *pBmp = new Graphics::TBitmap; + pBmp->Handle = hb; + if( m_pMaskBmp ) delete m_pMaskBmp; + m_pMaskBmp = CreateBitmap(pBmp->Width, pBmp->Height); + m_pMaskBmp->Canvas->Draw(0, 0, pBmp); + delete pBmp; + UpdateMaskSrc(FALSE); + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::SBMLoadClick(TObject *Sender) +{ + if( !sys.m_fLoadImageMenu ) return; + UpdateMaskSrc(sys.m_fLoadImageMenu(1, PBoxSrc->Width, PBoxSrc->Height)); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::SBMPasteClick(TObject *Sender) +{ + if( !sys.m_fPasteImage ) return; + UpdateMaskSrc(sys.m_fPasteImage(1, PBoxSrc->Width, PBoxSrc->Height)); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::SBMCopyClick(TObject *Sender) +{ + if( !m_pMaskBmp ) return; + CopyBitmap(m_pMaskBmp); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::SBClipClick(TObject *Sender) +{ + if( !sys.m_fClip ) return; + + Graphics::TBitmap *pBmp = CreateBitmap(PBoxSrc->Width, PBoxSrc->Height); + if( sys.m_fClip(pBmp->Handle, m_pMaskBmp->Handle) ){ + delete m_pMaskBmp; + m_pMaskBmp = pBmp; + UpdateMaskSrc(FALSE); + } + else { + delete pBmp; + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::UpdateCBMSize(void) +{ + UpdateCBMSize(m_MaskXW, m_MaskYW); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::UpdateCBMSize(int xw, int yw) +{ + m_DisEvent++; + int f = TRUE; + if( xw == yw ){ + switch(xw){ + case 8: + CBMSize->ItemIndex = 0; + break; + case 16: + CBMSize->ItemIndex = 1; + break; + case 24: + CBMSize->ItemIndex = 2; + break; + case 32: + CBMSize->ItemIndex = 3; + break; + default: + f = FALSE; + break; + } + } + else { + f = FALSE; + } + if( f ){ + if( CBMSize->Items->Count > 4 ) CBMSize->Items->Delete(4); + } + else { + char bf[256]; + wsprintf(bf, "%ux%u", xw, yw); + if( CBMSize->Items->Count > 4 ){ + CBMSize->Items->Strings[4] = bf; + } + else { + CBMSize->Items->Add(bf); + } + CBMSize->ItemIndex = 4; + } + m_DisEvent--; +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::CBMSizeChange(TObject *Sender) +{ + if( m_DisEvent ) return; + + switch(CBMSize->ItemIndex){ + case 0: + m_MaskXW = m_MaskYW = 8; + break; + case 1: + m_MaskXW = m_MaskYW = 16; + break; + case 2: + m_MaskXW = m_MaskYW = 24; + break; + case 3: + m_MaskXW = m_MaskYW = 32; + break; + } + if( m_pMaskBmp ){ + if( (m_MaskXW > m_pMaskBmp->Width) || (m_MaskYW > m_pMaskBmp->Height) ){ + Graphics::TBitmap *pBmp = CreateBitmap(m_MaskXW, m_MaskYW); + int x, y; + y = 0; + while(y < m_MaskYW){ + x = 0; + while(x < m_MaskXW){ + pBmp->Canvas->Draw(x, y, m_pMaskBmp); + x += m_pMaskBmp->Width; + } + y += m_pMaskBmp->Height; + } + delete m_pMaskBmp; + m_pMaskBmp = pBmp; + } + } + UpdateItemMask(); + PBoxSrcPaint(NULL); + UpdateBitmap(); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::FormKeyDown(TObject *Sender, WORD &Key, + TShiftState Shift) +{ + if( Page->ActivePage == TabMask ){ + TShiftState sf1, sf2; + sf1 << ssShift; + sf2 << ssShift; + sf1 *= Shift; + int sft = (sf1 == sf2); + int MaskXW = m_MaskXW; + int MaskYW = m_MaskYW; + int MaskX = m_MaskX; + int MaskY = m_MaskY; + switch(Key){ + case VK_LEFT: + if( sft ){ + if( m_MaskXW > 4 ) m_MaskXW--; + } + else { + if( m_MaskX ) m_MaskX--; + } + Key = 0; + break; + case VK_RIGHT: + if( sft ){ + m_MaskXW++; + } + else { + m_MaskX++; + } + Key = 0; + break; + case VK_UP: + if( sft ){ + if( m_MaskYW > 4 ) m_MaskYW--; + } + else { + if( m_MaskY ) m_MaskY--; + } + Key = 0; + break; + case VK_DOWN: + if( sft ){ + m_MaskYW++; + } + else { + m_MaskY++; + } + Key = 0; + break; + } + if( (MaskX!=m_MaskX)||(MaskY!=m_MaskY)||(MaskXW!=m_MaskXW)||(MaskYW!=m_MaskYW) ){ + UpdateItemMask(); + PBoxSrcPaint(NULL); + UpdateBitmap(); + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::OnDrawClipboard(TMessage Message) +{ + SBMPaste->Enabled = ::IsClipboardFormatAvailable(CF_BITMAP); + if( m_hClipNext ) ::SendMessage(m_hClipNext, WM_DRAWCLIPBOARD, Message.WParam, Message.LParam); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::OnChangeCbChain(TMessage Message) +{ + if( (HWND)Message.WParam == m_hClipNext ){ + m_hClipNext = (HWND)Message.LParam; + } + if( m_hClipNext ) ::SendMessage(m_hClipNext, WM_CHANGECBCHAIN, Message.WParam, Message.LParam); + Message.Result = 0; +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::SBMRotMouseDown(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( !m_pMaskBmp ) return; + if( (Button != mbLeft) && (Button != mbRight) ) return; + + BOOL f = (Button == mbLeft); + CWaitCursor w; + int xw = m_pMaskBmp->Width; + int yw = m_pMaskBmp->Height; + Graphics::TBitmap *pBmp = CreateBitmap(yw, xw); + int x, y; + BYTE *sp, *tp; + for( y = 0; y < yw; y++ ){ + sp = (BYTE *)m_pMaskBmp->ScanLine[y]; + for( x = 0; x < xw; x++ ){ + if( f ){ + tp = (BYTE *)pBmp->ScanLine[x]; + tp += ((yw - y - 1) * 3); + } + else { + tp = (BYTE *)pBmp->ScanLine[xw - x - 1]; + tp += (y * 3); + } + *tp++ = *sp++; + *tp++ = *sp++; + *tp = *sp++; + } + } + delete m_pMaskBmp; + m_pMaskBmp = pBmp; + UpdateMaskSrc(FALSE); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::SBMMirMouseDown(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( !m_pMaskBmp ) return; + if( (Button != mbLeft) && (Button != mbRight) ) return; + + CWaitCursor w; + int xw = m_pMaskBmp->Width; + int yw = m_pMaskBmp->Height; + Graphics::TBitmap *pBmp = CreateBitmap(xw, yw); + int x, y; + BYTE *sp, *tp; + for( y = 0; y < yw; y++ ){ + if( Button == mbLeft ){ + sp = (BYTE *)m_pMaskBmp->ScanLine[y]; + tp = (BYTE *)pBmp->ScanLine[y]; + tp += ((xw - 1) * 3); + for( x = 0; x < xw; x++ ){ + *tp++ = *sp++; + *tp++ = *sp++; + *tp = *sp++; + tp -= 5; + } + } + else { + sp = (BYTE *)m_pMaskBmp->ScanLine[y]; + tp = (BYTE *)pBmp->ScanLine[yw - y - 1]; + for( x = 0; x < xw; x++ ){ + *tp++ = *sp++; + *tp++ = *sp++; + *tp++ = *sp++; + } + } + } + delete m_pMaskBmp; + m_pMaskBmp = pBmp; + UpdateMaskSrc(FALSE); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::SBAdjColClick(TObject *Sender) +{ + if( !m_pMaskBmp ) return; + if( !sys.m_fAdjCol ) return; + + if( sys.m_fAdjCol(m_pMaskBmp->Handle) ){ + DeleteMaskSrc(); + UpdateItemMask(); + PBoxSrcPaint(NULL); + UpdateBitmap(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::DeleteMaskSrc(void) +{ + if( m_pMaskBmpSrc ){ + delete m_pMaskBmpSrc; + m_pMaskBmpSrc = NULL; + } + m_RotCol = 0; +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::SBInvColClick(TObject *Sender) +{ + if( !m_pMaskBmp ) return; + + int xw = m_pMaskBmp->Width; + int yw = m_pMaskBmp->Height; + int x, y; + for( y = 0; y < yw; y++ ){ + LPBYTE p = (LPBYTE)m_pMaskBmp->ScanLine[y]; + for( x = 0; x < xw; x++ ){ + *p = BYTE(~*p); p++; + *p = BYTE(~*p); p++; + *p = BYTE(~*p); p++; + } + } + DeleteMaskSrc(); + UpdateItemMask(); + PBoxSrcPaint(NULL); + UpdateBitmap(); + +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::SBRotColMouseDown(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( !m_pMaskBmp ) return; + + int f = 0; + if( Button == mbLeft ){ + f = 1; + } + else if( Button == mbRight ){ + f = -1; + } + if( f ){ + CWaitCursor w; + if( !m_pMaskBmpSrc ){ + m_pMaskBmpSrc = CreateBitmap(m_pMaskBmp->Width, m_pMaskBmp->Height); + m_pMaskBmpSrc->Canvas->Draw(0, 0, m_pMaskBmp); + m_RotCol = 0; + } + m_RotCol += f; + if( m_RotCol >= 16 ) m_RotCol = 0; + if( m_RotCol < 0 ) m_RotCol = 15; + if( !m_RotCol ){ + m_pMaskBmp->Canvas->Draw(0, 0, m_pMaskBmpSrc); + } + else { + double ad = m_RotCol * 6.283185307179586476925286766559 / 16.0; + int x, y; + int xw = m_pMaskBmp->Width; + int yw = m_pMaskBmp->Height; + int R, G, B; + double Y, RY, BY, S, H; + UCOL c; + for( y = 0; y < yw; y++ ){ + LPBYTE sp = (LPBYTE)m_pMaskBmpSrc->ScanLine[y]; + LPBYTE wp = (LPBYTE)m_pMaskBmp->ScanLine[y]; + for( x = 0; x < xw; x++ ){ + c.b.b = *sp++; + c.b.g = *sp++; + c.b.r = *sp++; + + Y = 0.3 * c.b.r + 0.59 * c.b.g + 0.11 * c.b.b; + RY = 0.7 * c.b.r - 0.59 * c.b.g - 0.11 * c.b.b; + BY = -0.3 * c.b.r - 0.59 * c.b.g + 0.89 * c.b.b; + + S = sqrt(RY*RY + BY*BY); + if( BY ){ + H = atan2(RY, BY); + H += ad; + RY = S * sin(H); + BY = S * cos(H); + + R = Y + RY; + G = Y - 0.3 * RY / 0.59 - 0.11 * BY / 0.59; + B = Y + BY; + if( R > 255 ) R = 255; + if( R < 0 ) R = 0; + if( G > 255 ) G = 255; + if( G < 0 ) G = 0; + if( B > 255 ) B = 255; + if( B < 0 ) B = 0; + } + else { + R = c.b.r; G = c.b.g; B = c.b.b; + } + + *wp++ = (BYTE)B; + *wp++ = (BYTE)G; + *wp++ = (BYTE)R; + } + } + } + UpdateItemMask(); + PBoxSrcPaint(NULL); + UpdateBitmap(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::SBMListClick(TObject *Sender) +{ + if( m_DisEvent ) return; + + if( SBMList->Down ){ + if( m_pMLSrcBmp ) delete m_pMLSrcBmp; + m_pMLSrcBmp = CreateBitmap(32, 32); + FillBitmap(m_pMLSrcBmp, clBlack); + if( m_Item.m_pMaskBmp ){ + int x, y; + int xw = m_Item.m_pMaskBmp->Width; + int yw = m_Item.m_pMaskBmp->Height; + for( y = 0; y < 32; y += yw){ + for( x = 0; x < 32; x += xw){ + m_pMLSrcBmp->Canvas->Draw(x, y, m_Item.m_pMaskBmp); + } + } + } + } + else { + if( m_pMLSrcBmp ) delete m_pMLSrcBmp; + m_pMLSrcBmp = NULL; + } + UpdateUI(); +} +//--------------------------------------------------------------------------- +int __fastcall TTextDlgBox::GetMLIndex(int x, int y) +{ + return GetIndex(35, 9*8, x, y); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::PBoxMListPaint(TObject *Sender) +{ + Graphics::TBitmap *pBmp; + if( !m_pMListBmp ){ + char name[256]; + wsprintf(name, "%s"USERMASK, sys.m_BgnDir); + FILE *fp = fopen(name, "rb"); + if( fp != NULL ){ + fclose(fp); + pBmp = new Graphics::TBitmap; + try { + pBmp->LoadFromFile(name); + } + catch(...){ + } + if( pBmp->Width < (32*72) ) pBmp->Width = 32*72; + if( pBmp->Height < 32 ) pBmp->Height = 32; + + if( pBmp->PixelFormat != pf24bit ){ + m_pMListBmp = CreateBitmap(pBmp->Width, pBmp->Height); + m_pMListBmp->Canvas->Draw(0, 0, pBmp); + delete pBmp; + } + else { + m_pMListBmp = pBmp; + } + } + else { + m_pMListBmp = CreateBitmap(32*72, 32); + FillBitmap(m_pMListBmp, clBlack); + } + m_pMListBmp->Modified = FALSE; + } + MultProc(); + int x, y; + for( y = 0; y < 9; y++ ){ + for( x = 0; x < 8; x++ ){ + DrawBmpPBox(PBoxMList->Canvas, 35, 32, 32, x, y, m_pMListBmp); + } + } +} +//--------------------------------------------------------------------------- +int __fastcall TTextDlgBox::IsMList(int n) +{ + int yw = m_pMListBmp->Height; + int x, y; + for( y = 0; y < yw; y++ ){ + LPBYTE p = (LPBYTE)m_pMListBmp->ScanLine[y]; + p += (n * 32) * 3; + for( x = 0; x < 32; x++ ){ + if( *p++ ) return TRUE; + if( *p++ ) return TRUE; + if( *p++ ) return TRUE; + } + } + return FALSE; +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::PBoxMListMouseDown(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( !m_pMListBmp ) return; + m_MLIndex = GetMLIndex(X, Y); + if( (m_MLIndex >= 0) && IsMList(m_MLIndex) ){ + if( Button == mbLeft ){ + DrawBmpPBoxBtn(PBoxMList->Canvas, (m_MLIndex%8)*35, (m_MLIndex/8)*35, 32, TRUE); + Graphics::TBitmap *pBmp = CreateBitmap(32, 32); + pBmp->Canvas->Draw(-m_MLIndex*32, 0, m_pMListBmp); + if( !m_pMaskBmp ) m_pMaskBmp = CreateBitmap(32, 32); + if( !IsSameBitmap(pBmp, m_pMaskBmp) ){ + delete m_pMaskBmp; + m_pMaskBmp = pBmp; + UpdateMaskSrc(TRUE); + } + else { + delete pBmp; + } + ::Sleep(100); + DrawBmpPBoxBtn(PBoxMList->Canvas, (m_MLIndex%8)*35, (m_MLIndex/8)*35, 32, FALSE); + PBoxMList->BeginDrag(FALSE); + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::PBoxMLSrcPaint(TObject *Sender) +{ + FillPBox(PBoxMLSrc); + if( m_pMLSrcBmp ){ + DrawBmpPBox(PBoxMLSrc->Canvas, 0, 0, m_pMLSrcBmp); + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::PBoxMListDragDrop(TObject *Sender, + TObject *Source, int X, int Y) +{ + if( Source == PBoxMLSrc ){ + int n = GetMLIndex(X, Y); + if( n >= 0 ){ + m_pMListBmp->Canvas->Draw(n*32, 0, m_pMLSrcBmp); + m_pMListBmp->Modified = TRUE; + PBoxMListPaint(NULL); + } + } + else if( Source == PBoxMList ){ + X = GetMLIndex(X, Y); + if( (X >= 0) && (X != m_MLIndex) ){ + Graphics::TBitmap *pBmp = CreateBitmap(32, 32); + Graphics::TBitmap *pBmp2 = CreateBitmap(32, 32); + pBmp->Canvas->Draw(-m_MLIndex*32, 0, m_pMListBmp); + pBmp2->Canvas->Draw(-X*32, 0, m_pMListBmp); + m_pMListBmp->Canvas->Draw(X*32, 0, pBmp); + m_pMListBmp->Canvas->Draw(m_MLIndex*32, 0, pBmp2); + delete pBmp; + delete pBmp2; + m_pMListBmp->Modified = TRUE; + PBoxMListPaint(NULL); + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::PBoxMListDragOver(TObject *Sender, + TObject *Source, int X, int Y, TDragState State, bool &Accept) +{ + Accept = FALSE; + if( Source == PBoxMLSrc ){ + if( GetMLIndex(X, Y) >= 0 ){ + Accept = TRUE; + } + } + else if( Source == PBoxMList ){ + X = GetMLIndex(X, Y); + if( (X >= 0) && (X != m_MLIndex) ){ + Accept = TRUE; + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::PBoxMLSrcMouseDown(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( !m_pMLSrcBmp ) return; + + if( Button == mbLeft ){ + DrawBmpPBoxBtn(PBoxMLSrc->Canvas, 0, 0, 32, TRUE); + if( m_Item.m_pMaskBmp ){ + if( !IsSameBitmap(m_pMLSrcBmp, m_Item.m_pMaskBmp) ){ + CopyBitmap(m_pMaskBmp, m_pMLSrcBmp); + UpdateMaskSrc(TRUE); + } + } + ::Sleep(100); + DrawBmpPBoxBtn(PBoxMLSrc->Canvas, 0, 0, 32, FALSE); + PBoxMLSrc->BeginDrag(FALSE); + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::PBoxMLSrcDragOver(TObject *Sender, + TObject *Source, int X, int Y, TDragState State, bool &Accept) +{ + Accept = (Source == PBoxMList) && (m_MLIndex >= 0); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::PBoxMLSrcDragDrop(TObject *Sender, + TObject *Source, int X, int Y) +{ + if( (Source == PBoxMList) && (m_MLIndex >= 0) ){ + m_pMLSrcBmp->Canvas->Draw(-m_MLIndex*32, 0, m_pMListBmp); + Graphics::TBitmap *pBmp = CreateBitmap(32, 32); + FillBitmap(pBmp, clBlack); + m_pMListBmp->Canvas->Draw(m_MLIndex*32, 0, pBmp); + delete pBmp; + m_pMListBmp->Modified = TRUE; + PBoxMListPaint(NULL); + PBoxMLSrcPaint(NULL); + } +} +#if 0 +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::DrawCrack(TCanvas *pCanvas, int xw, int yw, double &x, double &y, double &dir) +{ +#if 0 + if( !(rand() % 32) ){ + double xs = x; + double ys = y; + double ds = dir + 90; + for( int i = 0; i < 8; i++ ){ + DrawCrack(pCanvas, xw, yw, xs, ys, ds); + } + } +#endif + + double d = dir * 3.1415926535 / 180.0; + + UCOL c; + double d1 = d + 0.78539816339744830961566084581988; + double d2 = d - 0.78539816339744830961566084581988; + int xx, yy; + xx = cos(d1); yy = sin(d1); + c.c = pCanvas->Pixels[x+xx][y+yy]; + c.b.b /= 2; c.b.r /= 2; c.b.g /= 2; + pCanvas->Pixels[x+xx][y+yy] = c.c; + + xx = cos(d2); yy = sin(d2); + c.c = pCanvas->Pixels[x+xx][y+yy]; + c.b.b /= 2; c.b.r /= 2; c.b.g /= 2; + pCanvas->Pixels[x+xx][y+yy] = c.c; + + pCanvas->Pixels[x][y] = clBlack; + + x += cos(d); + y += sin(d); + if( !(rand() % 2) ) dir += (15 - (rand() % 30)); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::CreateCrack(void) +{ + TCanvas *pCanvas = m_pMaskBmp->Canvas; + int xw = m_pMaskBmp->Width; + int yw = m_pMaskBmp->Height; + int max = sqrt(xw*xw + yw*yw); + for( int i = 0; i < max/16; i++ ){ + double x = rand() % xw; + double y = rand() % yw; + double deg = rand() % 360; + for( int j = 0; j < max; j++ ){ + DrawCrack(pCanvas, xw, yw, x, y, deg); + } + } + UpdateMaskSrc(FALSE); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::SBMEditClick(TObject *Sender) +{ + char name[256]; + wsprintf(name, "%s$TextArt.bmp", sys.m_BgnDir); +// m_MaskTempName = name; + Graphics::TBitmap *pBmp; + if( !m_pMaskBmp ){ + pBmp = CreateBitmap(32, 32); + FillBitmap(pBmp, clBlack); + pBmp->SaveToFile(name); + delete pBmp; + } + else { + m_pMaskBmp->SaveToFile(name); + } + ExecPB(name); +} +#endif +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::SBMEditClick(TObject *Sender) +{ + CWaitCursor w; + + m_ExecPBCount = 0; + m_ExecPB = FALSE; + Timer->Enabled = FALSE; + QuitPB(TRUE); + + char name[256]; + wsprintf(name, "%sTextArt$.bmp", sys.m_BgnDir); + m_MaskTempName = name; + Graphics::TBitmap *pBmp; + if( !m_pMaskBmp ){ + pBmp = CreateBitmap(32, 32); + FillBitmap(pBmp, clBlack); + pBmp->SaveToFile(name); + delete pBmp; + } + else { + m_pMaskBmp->SaveToFile(name); + } + ExecPB(name); + for( int i = 0; i < 100; i++ ){ + ::Sleep(100); + if( IsPB() ){ + m_ExecPB = 1; + Timer->Enabled = TRUE; + break; + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::OnActivateApp(TMessage Message) +{ + if( m_ExecPB ){ + m_ExecPBCount = -6; // 3[s] continued check + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::QuitPB(BOOL fWait) +{ + HWND hWndA = NULL; + while(1){ + HWND hWnd = IsPB(); + if( (hWnd != NULL) && (hWnd != hWndA) ){ + hWndA = hWnd; + ::PostMessage(hWnd, WM_QUIT, 0, 0); + if( fWait ){ + for( int i = 0; i < 30; i++ ){ + ::Sleep(100); + MultProc(); + if( IsPB() != hWnd ) break; + } + } + else { + break; + } + } + else { + break; + } + } +} +//--------------------------------------------------------------------------- +BOOL __fastcall TTextDlgBox::CheckPBFinished(void) +{ + if( !m_ExecPB ) return FALSE; + + if( !IsPB() ){ // ペイントブラシの終了を検出 + m_ExecPB = FALSE; + Timer->Enabled = FALSE; + LoadEditedMask(); + return TRUE; + } + else { + return FALSE; + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::LoadEditedMask(void) +{ + Graphics::TBitmap *pBmp = new Graphics::TBitmap; + try { + pBmp->LoadFromFile(m_MaskTempName); + } + catch(...){ + } + BOOL f = FALSE; + if( !m_pMaskBmp ){ + f = TRUE; + m_pMaskBmp = CreateBitmap(32, 32); + FillBitmap(m_pMaskBmp, clBlack); + } + if( !IsSameBitmap(pBmp, m_pMaskBmp) ){ + CopyBitmap(m_pMaskBmp, pBmp); + UpdateMaskSrc(FALSE); + } + else if( f ){ + delete m_pMaskBmp; + m_pMaskBmp = NULL; + } + delete pBmp; + ::DeleteFile(m_MaskTempName.c_str()); +} +//--------------------------------------------------------------------------- +static void __fastcall DrawPtn(TCanvas *pCanvas, int X, int Y, int xw, int yw, int w, int max, BOOL sw) +{ + const COLORREF tt[]={ + RGB(0,0,255), RGB(0,255,0), RGB(0,255,255), RGB(255,0,0), + RGB(255,0,255), RGB(255,255,0), RGB(255,0,0), RGB(255,255,0) + }; + int x, y, i; + UCOL c; + POINT P[10]; + if( sw == 3 ) w+=4; + for( i = 0; i < max; i++ ){ + x = X + (rand() % xw); + y = Y + (rand() % yw); + c.d = tt[rand()%AN(tt)]; + pCanvas->Pen->Color = (w < 3) ? c.c : clBlack; + pCanvas->Brush->Color = c.c; + switch(sw){ + case 0: + pCanvas->Ellipse(x-w, y-w, x+w, y+w); + break; + case 1: + pCanvas->Rectangle(x-w, y-w, x+w, y+w); + break; + case 2: + P[0].x = x-w/3; + P[0].y = y-w; + P[1].x = x-w; + P[1].y = y; + P[2].x = x-w/3; + P[2].y = y+w; + P[3].x = x+w/3; + P[3].y = y+w; + P[4].x = x+w; + P[4].y = y; + P[5].x = x+w/3; + P[5].y = y-w; + pCanvas->Polygon(P, 5); + break; + case 3: + P[0].x = x; + P[0].y = y-w; + P[1].x = x-w/3; + P[1].y = y-w/3; + P[2].x = x-w; + P[2].y = y-w/3; + P[3].x = x-w/2; + P[3].y = y+w/4; + P[4].x = x-w*2/3; + P[4].y = y+w; + P[5].x = x; + P[5].y = y+w/2; + P[6].x = x+w*2/3; + P[6].y = y+w; + P[7].x = x+w/2; + P[7].y = y+w/4; + P[8].x = x+w; + P[8].y = y-w/3; + P[9].x = x+w/3; + P[9].y = y-w/3; + pCanvas->Polygon(P, 9); + break; + } + } +} +//--------------------------------------------------------------------------- +static void __fastcall SetBrushColor(COLORREF ttm[4], int sw) +{ + if( sw ){ + const COLORREF ttc[][4]={ + {RGB(0,0,255), RGB(255,255,0), RGB(255,0,0), RGB(0,255,0),}, + {RGB(0,0,255), RGB(255,255,0), RGB(255,0,0), RGB(0,255,255),}, + {RGB(0,0,0), RGB(255,255,0), RGB(255,0,0), RGB(0,255,0),}, + {RGB(0,0,0), RGB(255,255,0), RGB(255,0,0), RGB(0,255,255),}, + {RGB(255,0,0), RGB(0,255,255), RGB(0,0,0), RGB(0,255,0),}, + {RGB(255,255,0), RGB(0,255,255), RGB(255,0,0), RGB(0,0,255),}, + }; + + static int N = 0; + memcpy(ttm, ttc[N], sizeof(COLORREF)*4); + N++; + if( N >= AN(ttc) ) N = 0; + } + else { + const COLORREF tt[]={ + RGB(0,255,0), RGB(0,255,255), RGB(255,0,0), + RGB(255,0,255), RGB(255,255,0), RGB(255,0,0), RGB(255,255,0), + RGB(255,255,255) + }; + COLORREF c = 0; + for( int i = 0; i < 4; i++ ){ + while(1){ + ttm[i] = tt[rand() % AN(tt)]; + if( c != ttm[i] ) break; + } + c = ttm[i]; + } + } +} +//--------------------------------------------------------------------------- +static UCOL __fastcall GetGradeColor(UCOL c, int sw) +{ + switch(sw%4){ + case 1: + case 2: + c.b.r = (BYTE)(c.b.r * 2 / 3); + c.b.g = (BYTE)(c.b.g * 2 / 3); + c.b.b = (BYTE)(c.b.b * 2 / 3); + break; + case 3: + c.b.r = (BYTE)(c.b.r / 2); + c.b.g = (BYTE)(c.b.g / 2); + c.b.b = (BYTE)(c.b.b / 2); + break; + } + return c; +} +//--------------------------------------------------------------------------- +static void __fastcall DrawBrush(TCanvas *pCanvas, COLORREF ttm[4], int X, int Y, int xw, int yw, int sw) +{ + int x, y, v, w; + UCOL c; + for( y = Y; y < Y+yw; y++ ){ + for( x = X; x < X+xw; x++ ){ + switch(sw){ + case 0: + case 4: + v = (y/4); + w = y; + break; + case 1: + case 5: + v = (x/4); + w = x; + break; + case 2: + case 6: + v = (x+y)/4; + w = x + y; + break; + case 3: + case 7: + v = (x-y+1024)/4; + w = x-y+1024; + break; + } + c.d = ttm[v % 4]; + if( sw < 4 ) c = GetGradeColor(c, w); + pCanvas->Pixels[x][y] = c.c; + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::SBPtnMouseDown(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( (Button != mbLeft) && (Button != mbRight) ) return; + + CWaitCursor w; + + int xw = PBoxSrc->Width; + int yw = PBoxSrc->Height; + + Graphics::TBitmap *pBmp = CreateBitmap(xw, yw); + if( m_pMaskBmp ){ + int x, y; + for( y = 0; y < yw; y += m_pMaskBmp->Height){ + for( x = 0; x < xw; x += m_pMaskBmp->Width ){ + pBmp->Canvas->Draw(x, y, m_pMaskBmp); + } + } + } + else { + FillBitmap(pBmp, clBlack); + } + + xw = (xw*10+5)/30; + yw = (yw*10+5)/20; + int sw = (Button != mbLeft) ? 1 : 0; + TCanvas *pCanvas = pBmp->Canvas; + int max = xw * yw; + int sww = sw * 2; + DrawPtn(pCanvas, 0, 0, xw, yw, 2, max/16, sww); + DrawPtn(pCanvas, 0, 0, xw, yw, 3, max/16, sww); + DrawPtn(pCanvas, 0, 0, xw, yw, 4, max/256, sww); + DrawPtn(pCanvas, 0, 0, xw, yw, 5, max/1024, sww); + + DrawPtn(pCanvas, 0, yw, xw, yw, 2, max/16, 1+sww); + DrawPtn(pCanvas, 0, yw, xw, yw, 3, max/16, 1+sww); + DrawPtn(pCanvas, 0, yw, xw, yw, 4, max/256, 1+sww); + DrawPtn(pCanvas, 0, yw, xw, yw, 5, max/1024, 1+sww); + + COLORREF ttm[4]; + SetBrushColor(ttm, sw); + sww *= 2; + DrawBrush(pCanvas, ttm, xw, 0, xw, yw, 0 + sww); + DrawBrush(pCanvas, ttm, xw, yw, xw, yw, 1 + sww); + DrawBrush(pCanvas, ttm, xw+xw, 0, xw, yw, 2 + sww); + DrawBrush(pCanvas, ttm, xw+xw, yw, xw, yw, 3 + sww); + + if( m_pMaskBmp ) delete m_pMaskBmp; + m_pMaskBmp = pBmp; + m_MaskXW = m_MaskYW = 32; + UpdateMaskSrc(FALSE); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::SBG1Click(TObject *Sender) +{ + CItem *pItem = &m_Item; + if( SBG1->Down ){ + pItem->m_Grade = 0; + } + else if( SBG2->Down ){ + pItem->m_Grade = 1; + } + else if( SBG3->Down ){ + pItem->m_Grade = 2; + } + else if( SBG4->Down ){ + pItem->m_Grade = 3; + } + else { + pItem->m_Grade = 4; + } + UpdateDialog(&m_Item); + SBGClick(NULL); +} +//--------------------------------------------------------------------------- +TPanel* __fastcall TTextDlgBox::GetPG(int index) +{ + TPanel *_tt[]={PG1, PG2, PG3, PG4, PG5, PG6}; + return _tt[index % 6]; +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::SBGRevClick(TObject *Sender) +{ + TColor c[6]; + int m = SBG5->Down ? 6 : 4; + int i; + for( i = 0; i < m; i++ ) c[i] = GetPG(i)->Color; + for( i = 0; i < m; i++ ) GetPG(m-i-1)->Color = c[i]; + SBGClick(NULL); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::SBGRotClick(TObject *Sender) +{ + int i; + int m = SBG5->Down ? 5 : 3; + TColor c = GetPG(0)->Color; + for( i = 0; i < m; i++ ) GetPG(i)->Color = GetPG(i+1)->Color; + GetPG(i)->Color = c; + SBGClick(NULL); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::SBGRandClick(TObject *Sender) +{ + UCOL c[6]; + UCOL cc; + int i, j, f, n; + + cc.d = 0; + for( i = 0; i < 6; i++ ){ + do { + n = rand() % 7; + n++; + if( (n==7) && (rand()&7) ) n = (rand()%6)+1; + cc.b.r = BYTE(n & 1 ? 255 : 0); + cc.b.g = BYTE(n & 2 ? 255 : 0); + cc.b.b = BYTE(n & 4 ? 255 : 0); + f = FALSE; + for( j = 0; j < i; j++ ){ + if( cc.d == c[j].d ){ + f = TRUE; + break; + } + } + } while (f); + c[i] = cc; + GetPG(i)->Color = cc.c; + } + SBGClick(NULL); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::SBGAClick(TObject *Sender) +{ + const COLORREF tt[]={ + RGB(255,0,0), RGB(255,255,0), RGB(0,255,0), RGB(0,255,255), RGB(0,0,255), RGB(255,0,255), + }; + + int i; + const COLORREF *p = tt; + for( i = 0; i < 6; i++, p++ ){ + GetPG(i)->Color = TColor(*p); + } + SBGClick(NULL); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::SBLClick(TObject *Sender) +{ + if( !sys.m_CodeLeft ) sys.m_CodeLeft = Left - 120; + if( !sys.m_CodeTop ) sys.m_CodeTop = Top + 110; + if( !m_pCodeView ){ + m_pCodeView = new TCodeView(this); + } + m_pCodeView->Execute((HWND)Handle, m_Item.m_pFont); +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::OnCodeViewClose(TMessage Message) +{ + if( Message.LParam == int(m_pCodeView) ){ + TCodeView *pView = m_pCodeView; + m_pCodeView = NULL; + delete pView; + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::OnCodeInsert(TMessage Message) +{ + if( Message.LParam != int(m_pCodeView) ) return; + + switch(Message.WParam){ + case 0xfffffff0: + case 0xfffffff1: + case 0xfffffff2: + case 0xfffffff3: + case 0xfffffff4: + case 0xfffffff5: + case 0xfffffff6: + case 0xfffffff7: + if( m_Item.m_pFont != NULL ){ + TFont *pFont = m_Item.m_pFont; + int dfs = 0; + switch(Message.WParam & 7){ + case 0: + pFont->Name = "Webdings"; + pFont->Charset = 2; + break; + case 1: + pFont->Name = "Wingdings"; + pFont->Charset = 2; + break; + case 2: + pFont->Name = "Symbol"; + pFont->Charset = 2; + break; + case 3: + pFont->Name = "Arial"; + pFont->Charset = ANSI_CHARSET; + dfs = FSBOLD; + break; + case 4: + pFont->Name = sys.m_MsgEng ? "MS UI Gothic" : "MS Pゴシック"; + pFont->Charset = SHIFTJIS_CHARSET; + dfs = FSBOLD; + break; + case 5: + pFont->Name = "DotumChe"; + pFont->Charset = HANGEUL_CHARSET; + if( !sys.m_tFontFam[fmHL] && sys.m_tFontFam[fmJOHAB] ){ + pFont->Charset = JOHAB_CHARSET; + } + dfs = FSBOLD; + break; + case 6: + pFont->Name = "SimHei"; + pFont->Charset = 134; + dfs = FSBOLD; + break; + case 7: + pFont->Name = "PMingLiU"; + pFont->Charset = CHINESEBIG5_CHARSET; + dfs = FSBOLD; + break; + } + TFontStyles fs; + fs = Code2FontStyle(dfs); + pFont->Style = fs; + m_Item.UpdateFont(); + UpdateMemoFont(m_Item.m_pFont->Charset); + UpdateBitmap(); + } + break; + case 0xfffffffe: + ::SetWindowPos(m_pCodeView->Handle, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); +// m_pCodeView->Visible = FALSE; + FontBtnClick(NULL); + ::SetWindowPos(m_pCodeView->Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); +// m_pCodeView->Visible = TRUE; + break; + case 0xffffffff: + Memo->Clear(); + SBGClick(NULL); + break; + default: + if( Message.WParam ){ + if( Page->ActivePage != TabChar ) Page->ActivePage = TabChar; + HWND hWnd; + Memo->SetFocus(); + hWnd = Memo->Handle; + char bf[16]; + if( Message.WParam & 0x00ff0000 ){ + wsprintf(bf, "\\$%04x", Message.WParam & 0x00ffff); + } + else if( Message.WParam & 0x00ff00 ){ + bf[0] = BYTE(Message.WParam >> 8); + bf[1] = BYTE(Message.WParam); + bf[2] = 0; + } + else if( (Message.WParam == 0x0d) || (Message.WParam == 0x0a) ){ + bf[0] = 0x0d; bf[1] = 0; + } + else if( (Message.WParam != '%') && ((Message.WParam >= 0x20) && (Message.WParam <= 0x7f)) ){ + bf[0] = (char)Message.WParam; bf[1] = 0; + } + else { + wsprintf(bf, "\\x%02x", Message.WParam); + } + for( LPCSTR p = bf; *p; p++ ){ + ::PostMessage(hWnd, WM_CHAR, *p & 0x00ff, 0); + } + } + break; + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextDlgBox::PageChange(TObject *Sender) +{ + if( !m_pCodeView ) return; + + m_pCodeView->Visible = (Page->ActivePage == TabChar) ? TRUE : FALSE; +} +//--------------------------------------------------------------------------- + + \ No newline at end of file diff --git a/CItems/TextArt/TextDlg.dfm b/CItems/TextArt/TextDlg.dfm new file mode 100644 index 0000000..4ba4b34 Binary files /dev/null and b/CItems/TextArt/TextDlg.dfm differ diff --git a/CItems/TextArt/TextDlg.h b/CItems/TextArt/TextDlg.h new file mode 100644 index 0000000..acc271a --- /dev/null +++ b/CItems/TextArt/TextDlg.h @@ -0,0 +1,468 @@ +//---------------------------------------------------------------------------- +#ifndef TextDlgH +#define TextDlgH +//---------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//---------------------------------------------------------------------------- +#include "ComLib.h" +#include +#include +#include "CodeVw.h" +//---------------------------------------------------------------------------- +#define UseDraft FALSE +//---------------------------------------------------------------------------- +class TTextDlgBox : public TForm +{ +__published: + TButton *OKBtn; + TButton *CancelBtn; + TButton *FontBtn; + TMemo *Memo; + TGroupBox *GBG; + TSpeedButton *SBM; + TSpeedButton *SBG1; + TSpeedButton *SBG2; + TSpeedButton *SBG3; + TSpeedButton *SBG4; + TSpeedButton *SBG5; + TPanel *PG1; + TPanel *PG2; + TPanel *PG3; + TPanel *PG4; + TPanel *PG5; + TPanel *PG6; + TSpeedButton *SBGRev; + TSpeedButton *SBGRand; + TSpeedButton *SBGRot; + TSpeedButton *SBGA; + TSpeedButton *SBC; + TGroupBox *GBS; + TSpeedButton *SBS1; + TSpeedButton *SBS2; + TSpeedButton *SBS3; + TSpeedButton *SBS4; + TPanel *PB1; + TPanel *PB2; + TPanel *PB3; + TUpDown *UDL; + TGroupBox *GB3D; + TCheckBox *CB3D; + TUpDown *UDY; + TUpDown *UDX; + TSpeedButton *SB3DI; + TSpeedButton *SB3DD; + TLabel *L1; + TLabel *LY; + TLabel *LX; + TGroupBox *GBA; + TSpeedButton *SBA1; + TSpeedButton *SBA2; + TSpeedButton *SBA3; + TCheckBox *CBZero; + TComboBox *CBList; + TSpeedButton *SBLW; + TSpeedButton *SBLD; + TGroupBox *GBY; + TComboBox *CBY; + TLabel *L2; + TSpeedButton *SBYW; + TSpeedButton *SBYD; + TPaintBox *PBox; + TFontDialog *FontDialog; + TColorDialog *ColorDialog; + TTimer *Timer; + TSpeedButton *SBFD; + TSpeedButton *SBFI; + TSpeedButton *SBA4; + TMemo *Msg; + TSpeedButton *SBMSG; + TLabel *L33; + TComboBox *CBOYW; + TUpDown *UDOYW; + TLabel *L34; + TComboBox *CBRot; + TUpDown *UDRot; + TSpeedButton *SBF1; + TSpeedButton *SBF2; + TSpeedButton *SBF3; + TSpeedButton *SBF4; + TSpeedButton *SBF5; + TSpeedButton *SBB; + TSpeedButton *SBI; + TPageControl *Page; + TTabSheet *TabChar; + TTabSheet *TabPer; + + + TTrackBar *TBAX; + TTrackBar *TBAY; + TTrackBar *TBRX; + TTrackBar *TBRY; + TTrackBar *TBRZ; + TTrackBar *TBS; + TTrackBar *TBPX; + TTrackBar *TBPY; + TTrackBar *TBPZ; + TLabel *L51; + TLabel *L52; + TLabel *L53; + TLabel *L54; + TLabel *L55; + TLabel *L56; + TLabel *L57; + TLabel *L58; + TLabel *L59; + TButton *DefBtn; + TTrackBar *TBR; + TLabel *L60; + TPanel *Panel; + TSpeedButton *SB; + TSpeedButton *SBZ1; + TSpeedButton *SBZ2; + TSpeedButton *SBZ3; + TSpeedButton *SBZ4; + TSpeedButton *SBZ5; + TSpeedButton *SBZ6; + TSpeedButton *SBZ7; + TSpeedButton *SBZ8; + TSpeedButton *SBZ9; + TSpeedButton *SBZ10; + TSpeedButton *SBZ11; + TSpeedButton *SBZ12; + TSpeedButton *SBZ13; + TSpeedButton *SBZ14; + TPaintBox *PBoxPer; + TSpeedButton *SBZ15; + TSpeedButton *SBZ16; + TSpeedButton *SBZ17; + TButton *OKBtn2; + TButton *CancelBtn2; + TTabSheet *TabMask; + TCheckBox *CBBMask; + TLabel *L80; + TGroupBox *GB1; + TPaintBox *PBoxMask; + TButton *OKBtn3; + TButton *CancelBtn3; + TGroupBox *GB2; + TGroupBox *GB3; + TPanel *PM; + TPaintBox *PBoxSrc; + TSpeedButton *SBMLoad; + TPanel *PC1; + TPanel *PC2; + TComboBox *CBMSize; + TSpeedButton *SBMPaste; + TSpeedButton *SBMRot; + TSpeedButton *SBMMir; + TSpeedButton *SBAdjCol; + TSpeedButton *SBMCopy; + TSpeedButton *SBRotCol; + TScrollBar *SBH; + TScrollBar *SBV; + TGroupBox *GB4; + TPaintBox *PBoxMList; + TSpeedButton *SBMList; + TPaintBox *PBoxMLSrc; + TLabel *L90; + TPaintBox *PBoxBM; + TPaintBox *PBoxCS; + TSpeedButton *SBInvCol; + TSpeedButton *SBMEdit; + TSpeedButton *SBPtn; + TSpeedButton *SBZ18; + TSpeedButton *SBZ19; + TLabel *L61; + TSpeedButton *SBR; + TSpeedButton *SBZ20; + TSpeedButton *SBZ21; + TSpeedButton *SBZ22; + TScrollBar *TBSC; + TSpeedButton *SBZ23; + TSpeedButton *SBZ24; + TSpeedButton *SBZ25; + TSpeedButton *SBZ26; + TSpeedButton *SBZ27; + TSpeedButton *SBZ28; + TSpeedButton *SBZ29; + TSpeedButton *SBZ30; + TSpeedButton *SBZ31; + TSpeedButton *SBZ32; + TSpeedButton *SBZ33; + TSpeedButton *SBZ34; + TSpeedButton *SBZ35; + TSpeedButton *SBZ36; + TSpeedButton *SBZ37; + TSpeedButton *SBZ38; + TGroupBox *GB5; + TSpeedButton *SBFN; + TSpeedButton *SBFA; + TSpeedButton *SBFB; + TScrollBar *TBF; + TSpeedButton *SBClip; + TSpeedButton *SBL; + void __fastcall FormDestroy(TObject *Sender); + void __fastcall PBoxPaint(TObject *Sender); + void __fastcall MemoChange(TObject *Sender); + void __fastcall TimerTimer(TObject *Sender); + void __fastcall SBGClick(TObject *Sender); + void __fastcall PB1Click(TObject *Sender); + void __fastcall FormActivate(TObject *Sender); + void __fastcall FormDeactivate(TObject *Sender); + void __fastcall FontBtnClick(TObject *Sender); + void __fastcall SBMClick(TObject *Sender); + void __fastcall SBCClick(TObject *Sender); + void __fastcall SBLWClick(TObject *Sender); + void __fastcall SBLDClick(TObject *Sender); + void __fastcall CBListChange(TObject *Sender); + void __fastcall SBYWClick(TObject *Sender); + void __fastcall SBYDClick(TObject *Sender); + void __fastcall CBYChange(TObject *Sender); + void __fastcall CBYKeyPress(TObject *Sender, char &Key); + void __fastcall CBYDropDown(TObject *Sender); + void __fastcall PBoxMouseDown(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + + void __fastcall SB3DIClick(TObject *Sender); + void __fastcall SBMSGClick(TObject *Sender); + void __fastcall MsgDblClick(TObject *Sender); + void __fastcall MemoStartDrag(TObject *Sender, + TDragObject *&DragObject); + void __fastcall MsgDragDrop(TObject *Sender, TObject *Source, int X, + int Y); + void __fastcall MsgDragOver(TObject *Sender, TObject *Source, int X, + int Y, TDragState State, bool &Accept); + void __fastcall MemoMouseDown(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + + void __fastcall MemoMouseMove(TObject *Sender, TShiftState Shift, + int X, int Y); + void __fastcall MemoMouseUp(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + void __fastcall PBoxMouseMove(TObject *Sender, TShiftState Shift, int X, + int Y); + void __fastcall PBoxMouseUp(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + void __fastcall FontBtnMouseDown(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + void __fastcall SBFClick(TObject *Sender); + void __fastcall SBFMouseDown(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + void __fastcall SBBClick(TObject *Sender); + void __fastcall SBIClick(TObject *Sender); + void __fastcall SBFDMouseDown(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + void __fastcall DefBtnClick(TObject *Sender); + + void __fastcall SBRClick(TObject *Sender); + void __fastcall PBoxPerMouseDown(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + void __fastcall PBoxPerMouseMove(TObject *Sender, TShiftState Shift, + int X, int Y); + void __fastcall PBoxPerMouseUp(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + + void __fastcall TBSChange(TObject *Sender); + + void __fastcall CBBMaskClick(TObject *Sender); + + void __fastcall L80Click(TObject *Sender); + void __fastcall PBoxSrcPaint(TObject *Sender); + void __fastcall PBoxSrcMouseDown(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + void __fastcall PBoxSrcMouseMove(TObject *Sender, TShiftState Shift, + int X, int Y); + void __fastcall PBoxSrcMouseUp(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + void __fastcall SBMLoadClick(TObject *Sender); + + void __fastcall CBMSizeChange(TObject *Sender); + void __fastcall SBMPasteClick(TObject *Sender); + void __fastcall FormKeyDown(TObject *Sender, WORD &Key, + TShiftState Shift); + void __fastcall SBAdjColClick(TObject *Sender); + void __fastcall SBMCopyClick(TObject *Sender); + void __fastcall SBRotColMouseDown(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + + + + void __fastcall SBMListClick(TObject *Sender); + void __fastcall PBoxMListPaint(TObject *Sender); + void __fastcall PBoxMListMouseDown(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + void __fastcall PBoxMLSrcPaint(TObject *Sender); + void __fastcall PBoxMListDragDrop(TObject *Sender, TObject *Source, int X, + int Y); + void __fastcall PBoxMListDragOver(TObject *Sender, TObject *Source, int X, + int Y, TDragState State, bool &Accept); + + void __fastcall PBoxMLSrcMouseDown(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + void __fastcall PBoxMLSrcDragOver(TObject *Sender, TObject *Source, int X, + int Y, TDragState State, bool &Accept); + void __fastcall PBoxMLSrcDragDrop(TObject *Sender, TObject *Source, int X, + int Y); + void __fastcall SBMMirMouseDown(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + void __fastcall SBMRotMouseDown(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + + void __fastcall PBoxBMPaint(TObject *Sender); + void __fastcall PBoxBMMouseDown(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + void __fastcall PBoxBMMouseUp(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + void __fastcall PBoxCSPaint(TObject *Sender); + void __fastcall PBoxCSMouseDown(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + void __fastcall PBoxCSMouseUp(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + void __fastcall SBInvColClick(TObject *Sender); + void __fastcall SBMEditClick(TObject *Sender); + + void __fastcall SBPtnMouseDown(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + void __fastcall LDefMouseDown(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + + void __fastcall TBSCChange(TObject *Sender); + + void __fastcall UDLClick(TObject *Sender, TUDBtnType Button); + + + void __fastcall SBClipClick(TObject *Sender); + + void __fastcall SBG1Click(TObject *Sender); + void __fastcall SBGRevClick(TObject *Sender); + + void __fastcall SBGRandClick(TObject *Sender); + void __fastcall SBGRotClick(TObject *Sender); + void __fastcall SBGAClick(TObject *Sender); + + + void __fastcall SBLClick(TObject *Sender); + void __fastcall PageChange(TObject *Sender); +private: + int m_DisEvent; + int m_DropProfile; + Graphics::TBitmap *m_pBitmap; + CItem m_Item; + int m_Change; + AnsiString m_FText; + int m_MouseXC, m_MouseYC, m_MouseHold; + int m_MemoX, m_MemoY, m_MemoDown; + + void __fastcall TopMost(void); + void __fastcall NoTopMost(void); + void __fastcall UpdateMemoFont(BYTE charset); + void __fastcall UpdateFText(void); + void __fastcall UpdateUI(void); + void __fastcall UpdateItem(CItem *pItem); + void __fastcall UpdateDialog(CItem *pItem); + void __fastcall UpdateBitmap(void); + void __fastcall UD3D(int a); + void __fastcall UpdateFontBtnHint(void); + int __fastcall GetSBFIndex(TObject *Sender); + void __fastcall SetSBF(int n); + + int m_XC, m_YC; + double m_SCX, m_SCY; + double m_Deg, m_SDeg; + double m_Dist, m_SDistX, m_SDistY; + + int m_Wave; + void __fastcall UpdateWaveBtn(int dir); + void __fastcall UpdateHint(void); + void __fastcall FillPBox(TPaintBox *pBox); + +#if UseDraft + int m_Draft; +#endif + int m_FontHeight; + + int m_DirTB[10]; + void __fastcall UpdateTB(void); + int m_SBar[10]; + + Graphics::TBitmap *m_pBuiltInBmp; + + Graphics::TBitmap *m_pMaskBak; + Graphics::TBitmap *m_pMaskBmpSrc; + Graphics::TBitmap *m_pMaskBmp; + int m_MaskMouseCapture; + int m_MaskX, m_MaskY, m_MaskXW, m_MaskYW; + int m_MaskAX, m_MaskAY, m_MaskAXW, m_MaskAYW; + void __fastcall DrawMaskCursor(int x1, int y1, int x2, int y2); + void __fastcall DrawMaskCursor(void); + void __fastcall UpdateSBSrc(void); + void __fastcall UpdateMaskSrc(BOOL sw); + void __fastcall UpdateMaskSrc(HBITMAP hb); + void __fastcall UpdateItemMask(void); + + int m_MIndex; + + Graphics::TBitmap *m_pCustomBmp; + void __fastcall UpdateCustom(void); + + void __fastcall UpdateCBMSize(int xw, int yw); + void __fastcall UpdateCBMSize(void); + + void __fastcall DeleteMaskSrc(void); + int m_RotCol; + + Graphics::TBitmap *m_pMListBmp; + Graphics::TBitmap *m_pMLSrcBmp; + int m_MLIndex; + int __fastcall IsMList(int n); + int __fastcall GetMLIndex(int x, int y); + +// void __fastcall DrawCrack(TCanvas *pCanvas, int xw, int yw, double &x, double &y, double &dir); +// void __fastcall CreateCrack(void); + + int m_ExecPB; + int m_ExecPBCount; + AnsiString m_MaskTempName; + BOOL __fastcall CheckPBFinished(void); + void __fastcall LoadEditedMask(void); + void __fastcall QuitPB(BOOL fWait); + + TPanel* __fastcall GetPG(int index); + + TCodeView* m_pCodeView; + + HWND m_hClipNext; +public: + virtual __fastcall TTextDlgBox(TComponent* AOwner); + + int __fastcall Execute(CItem *pItem); + +protected: + void __fastcall OnDrawClipboard(TMessage Message); + void __fastcall OnChangeCbChain(TMessage Message); + void __fastcall OnActivateApp(TMessage Message); + void __fastcall OnCodeViewClose(TMessage Message); + void __fastcall OnCodeInsert(TMessage Message); +BEGIN_MESSAGE_MAP + MESSAGE_HANDLER(WM_DRAWCLIPBOARD, TMessage, OnDrawClipboard) + MESSAGE_HANDLER(WM_CHANGECBCHAIN, TMessage, OnChangeCbChain) + MESSAGE_HANDLER(WM_ACTIVATEAPP, TMessage, OnActivateApp) + MESSAGE_HANDLER(WM_FORMCLOSE, TMessage, OnCodeViewClose) + MESSAGE_HANDLER(WM_CODEINSERT, TMessage, OnCodeInsert) +END_MESSAGE_MAP(TForm) +}; +//---------------------------------------------------------------------------- +//extern PACKAGE TTextDlgBox *TextDlgBox; +//---------------------------------------------------------------------------- +#endif + + \ No newline at end of file diff --git a/CItems/TextArt/res.h b/CItems/TextArt/res.h new file mode 100644 index 0000000..a059e79 --- /dev/null +++ b/CItems/TextArt/res.h @@ -0,0 +1,3 @@ +#define ID_ICON 8000 +#define ID_BUILTIN 8001 + diff --git a/CItems/TextArt/res/P.bmp b/CItems/TextArt/res/P.bmp new file mode 100644 index 0000000..0974443 Binary files /dev/null and b/CItems/TextArt/res/P.bmp differ diff --git a/CItems/TextArt/res/P1.bmp b/CItems/TextArt/res/P1.bmp new file mode 100644 index 0000000..1a4d911 Binary files /dev/null and b/CItems/TextArt/res/P1.bmp differ diff --git a/CItems/TextArt/res/P10.bmp b/CItems/TextArt/res/P10.bmp new file mode 100644 index 0000000..3edddfd Binary files /dev/null and b/CItems/TextArt/res/P10.bmp differ diff --git a/CItems/TextArt/res/P11.bmp b/CItems/TextArt/res/P11.bmp new file mode 100644 index 0000000..4e9fa09 Binary files /dev/null and b/CItems/TextArt/res/P11.bmp differ diff --git a/CItems/TextArt/res/P12.bmp b/CItems/TextArt/res/P12.bmp new file mode 100644 index 0000000..899f284 Binary files /dev/null and b/CItems/TextArt/res/P12.bmp differ diff --git a/CItems/TextArt/res/P13.bmp b/CItems/TextArt/res/P13.bmp new file mode 100644 index 0000000..33bbfa8 Binary files /dev/null and b/CItems/TextArt/res/P13.bmp differ diff --git a/CItems/TextArt/res/P14.bmp b/CItems/TextArt/res/P14.bmp new file mode 100644 index 0000000..cd01038 Binary files /dev/null and b/CItems/TextArt/res/P14.bmp differ diff --git a/CItems/TextArt/res/P15.bmp b/CItems/TextArt/res/P15.bmp new file mode 100644 index 0000000..848eb5b Binary files /dev/null and b/CItems/TextArt/res/P15.bmp differ diff --git a/CItems/TextArt/res/P16.bmp b/CItems/TextArt/res/P16.bmp new file mode 100644 index 0000000..498c237 Binary files /dev/null and b/CItems/TextArt/res/P16.bmp differ diff --git a/CItems/TextArt/res/P2.bmp b/CItems/TextArt/res/P2.bmp new file mode 100644 index 0000000..b342a86 Binary files /dev/null and b/CItems/TextArt/res/P2.bmp differ diff --git a/CItems/TextArt/res/P3.bmp b/CItems/TextArt/res/P3.bmp new file mode 100644 index 0000000..87df076 Binary files /dev/null and b/CItems/TextArt/res/P3.bmp differ diff --git a/CItems/TextArt/res/P4.bmp b/CItems/TextArt/res/P4.bmp new file mode 100644 index 0000000..0868ca3 Binary files /dev/null and b/CItems/TextArt/res/P4.bmp differ diff --git a/CItems/TextArt/res/P5.bmp b/CItems/TextArt/res/P5.bmp new file mode 100644 index 0000000..a8ea54f Binary files /dev/null and b/CItems/TextArt/res/P5.bmp differ diff --git a/CItems/TextArt/res/P6.bmp b/CItems/TextArt/res/P6.bmp new file mode 100644 index 0000000..79203ab Binary files /dev/null and b/CItems/TextArt/res/P6.bmp differ diff --git a/CItems/TextArt/res/P7.bmp b/CItems/TextArt/res/P7.bmp new file mode 100644 index 0000000..ccd6cc8 Binary files /dev/null and b/CItems/TextArt/res/P7.bmp differ diff --git a/CItems/TextArt/res/P8.bmp b/CItems/TextArt/res/P8.bmp new file mode 100644 index 0000000..479d4b8 Binary files /dev/null and b/CItems/TextArt/res/P8.bmp differ diff --git a/CItems/TextArt/res/P9.bmp b/CItems/TextArt/res/P9.bmp new file mode 100644 index 0000000..9e03217 Binary files /dev/null and b/CItems/TextArt/res/P9.bmp differ diff --git a/CItems/TextArt/res/SB3DD.bmp b/CItems/TextArt/res/SB3DD.bmp new file mode 100644 index 0000000..1c74fe6 Binary files /dev/null and b/CItems/TextArt/res/SB3DD.bmp differ diff --git a/CItems/TextArt/res/SB3DI.bmp b/CItems/TextArt/res/SB3DI.bmp new file mode 100644 index 0000000..c162a1f Binary files /dev/null and b/CItems/TextArt/res/SB3DI.bmp differ diff --git a/CItems/TextArt/res/SBA1.bmp b/CItems/TextArt/res/SBA1.bmp new file mode 100644 index 0000000..732f99b Binary files /dev/null and b/CItems/TextArt/res/SBA1.bmp differ diff --git a/CItems/TextArt/res/SBA2.bmp b/CItems/TextArt/res/SBA2.bmp new file mode 100644 index 0000000..74ba1fb Binary files /dev/null and b/CItems/TextArt/res/SBA2.bmp differ diff --git a/CItems/TextArt/res/SBA3.bmp b/CItems/TextArt/res/SBA3.bmp new file mode 100644 index 0000000..768947d Binary files /dev/null and b/CItems/TextArt/res/SBA3.bmp differ diff --git a/CItems/TextArt/res/SBA4.bmp b/CItems/TextArt/res/SBA4.bmp new file mode 100644 index 0000000..efc171b Binary files /dev/null and b/CItems/TextArt/res/SBA4.bmp differ diff --git a/CItems/TextArt/res/SBAdj.bmp b/CItems/TextArt/res/SBAdj.bmp new file mode 100644 index 0000000..f2fbf4d Binary files /dev/null and b/CItems/TextArt/res/SBAdj.bmp differ diff --git a/CItems/TextArt/res/SBC.bmp b/CItems/TextArt/res/SBC.bmp new file mode 100644 index 0000000..3f96f65 Binary files /dev/null and b/CItems/TextArt/res/SBC.bmp differ diff --git a/CItems/TextArt/res/SBClip.bmp b/CItems/TextArt/res/SBClip.bmp new file mode 100644 index 0000000..7156250 Binary files /dev/null and b/CItems/TextArt/res/SBClip.bmp differ diff --git a/CItems/TextArt/res/SBCopy.bmp b/CItems/TextArt/res/SBCopy.bmp new file mode 100644 index 0000000..3ebde5b Binary files /dev/null and b/CItems/TextArt/res/SBCopy.bmp differ diff --git a/CItems/TextArt/res/SBG1.bmp b/CItems/TextArt/res/SBG1.bmp new file mode 100644 index 0000000..939b20f Binary files /dev/null and b/CItems/TextArt/res/SBG1.bmp differ diff --git a/CItems/TextArt/res/SBG2.bmp b/CItems/TextArt/res/SBG2.bmp new file mode 100644 index 0000000..a737fbe Binary files /dev/null and b/CItems/TextArt/res/SBG2.bmp differ diff --git a/CItems/TextArt/res/SBG3.bmp b/CItems/TextArt/res/SBG3.bmp new file mode 100644 index 0000000..3d99ffb Binary files /dev/null and b/CItems/TextArt/res/SBG3.bmp differ diff --git a/CItems/TextArt/res/SBG4.bmp b/CItems/TextArt/res/SBG4.bmp new file mode 100644 index 0000000..8cb6c5e Binary files /dev/null and b/CItems/TextArt/res/SBG4.bmp differ diff --git a/CItems/TextArt/res/SBG5.bmp b/CItems/TextArt/res/SBG5.bmp new file mode 100644 index 0000000..860b0e1 Binary files /dev/null and b/CItems/TextArt/res/SBG5.bmp differ diff --git a/CItems/TextArt/res/SBGA.bmp b/CItems/TextArt/res/SBGA.bmp new file mode 100644 index 0000000..53fda08 Binary files /dev/null and b/CItems/TextArt/res/SBGA.bmp differ diff --git a/CItems/TextArt/res/SBGB.bmp b/CItems/TextArt/res/SBGB.bmp new file mode 100644 index 0000000..8415c9c Binary files /dev/null and b/CItems/TextArt/res/SBGB.bmp differ diff --git a/CItems/TextArt/res/SBGRand.bmp b/CItems/TextArt/res/SBGRand.bmp new file mode 100644 index 0000000..7c87138 Binary files /dev/null and b/CItems/TextArt/res/SBGRand.bmp differ diff --git a/CItems/TextArt/res/SBGRev.bmp b/CItems/TextArt/res/SBGRev.bmp new file mode 100644 index 0000000..1b05185 Binary files /dev/null and b/CItems/TextArt/res/SBGRev.bmp differ diff --git a/CItems/TextArt/res/SBGRot.bmp b/CItems/TextArt/res/SBGRot.bmp new file mode 100644 index 0000000..d7e9a1d Binary files /dev/null and b/CItems/TextArt/res/SBGRot.bmp differ diff --git a/CItems/TextArt/res/SBInvCol.bmp b/CItems/TextArt/res/SBInvCol.bmp new file mode 100644 index 0000000..a49bdc9 Binary files /dev/null and b/CItems/TextArt/res/SBInvCol.bmp differ diff --git a/CItems/TextArt/res/SBLoad.bmp b/CItems/TextArt/res/SBLoad.bmp new file mode 100644 index 0000000..46855af Binary files /dev/null and b/CItems/TextArt/res/SBLoad.bmp differ diff --git a/CItems/TextArt/res/SBMIR.bmp b/CItems/TextArt/res/SBMIR.bmp new file mode 100644 index 0000000..640b251 Binary files /dev/null and b/CItems/TextArt/res/SBMIR.bmp differ diff --git a/CItems/TextArt/res/SBMList.bmp b/CItems/TextArt/res/SBMList.bmp new file mode 100644 index 0000000..7131ad5 Binary files /dev/null and b/CItems/TextArt/res/SBMList.bmp differ diff --git a/CItems/TextArt/res/SBPB.bmp b/CItems/TextArt/res/SBPB.bmp new file mode 100644 index 0000000..ddfb547 Binary files /dev/null and b/CItems/TextArt/res/SBPB.bmp differ diff --git a/CItems/TextArt/res/SBPaste.bmp b/CItems/TextArt/res/SBPaste.bmp new file mode 100644 index 0000000..8ff5a9f Binary files /dev/null and b/CItems/TextArt/res/SBPaste.bmp differ diff --git a/CItems/TextArt/res/SBPtn.bmp b/CItems/TextArt/res/SBPtn.bmp new file mode 100644 index 0000000..86c2cb8 Binary files /dev/null and b/CItems/TextArt/res/SBPtn.bmp differ diff --git a/CItems/TextArt/res/SBRR.bmp b/CItems/TextArt/res/SBRR.bmp new file mode 100644 index 0000000..80c600f Binary files /dev/null and b/CItems/TextArt/res/SBRR.bmp differ diff --git a/CItems/TextArt/res/SBS1.bmp b/CItems/TextArt/res/SBS1.bmp new file mode 100644 index 0000000..593f6fd Binary files /dev/null and b/CItems/TextArt/res/SBS1.bmp differ diff --git a/CItems/TextArt/res/SBS2.bmp b/CItems/TextArt/res/SBS2.bmp new file mode 100644 index 0000000..3e9baf8 Binary files /dev/null and b/CItems/TextArt/res/SBS2.bmp differ diff --git a/CItems/TextArt/res/SBS3.bmp b/CItems/TextArt/res/SBS3.bmp new file mode 100644 index 0000000..55fc484 Binary files /dev/null and b/CItems/TextArt/res/SBS3.bmp differ diff --git a/CItems/TextArt/res/SBS4.bmp b/CItems/TextArt/res/SBS4.bmp new file mode 100644 index 0000000..b6e587b Binary files /dev/null and b/CItems/TextArt/res/SBS4.bmp differ diff --git a/CItems/TextArt/res/SBSftCol.bmp b/CItems/TextArt/res/SBSftCol.bmp new file mode 100644 index 0000000..0b92bea Binary files /dev/null and b/CItems/TextArt/res/SBSftCol.bmp differ diff --git a/CItems/TextArt/res/SBZ0.bmp b/CItems/TextArt/res/SBZ0.bmp new file mode 100644 index 0000000..f0fe756 Binary files /dev/null and b/CItems/TextArt/res/SBZ0.bmp differ diff --git a/CItems/TextArt/res/SBZ1.bmp b/CItems/TextArt/res/SBZ1.bmp new file mode 100644 index 0000000..a5bb9cd Binary files /dev/null and b/CItems/TextArt/res/SBZ1.bmp differ diff --git a/CItems/TextArt/res/SBZ10.bmp b/CItems/TextArt/res/SBZ10.bmp new file mode 100644 index 0000000..9649fd2 Binary files /dev/null and b/CItems/TextArt/res/SBZ10.bmp differ diff --git a/CItems/TextArt/res/SBZ11.bmp b/CItems/TextArt/res/SBZ11.bmp new file mode 100644 index 0000000..6029648 Binary files /dev/null and b/CItems/TextArt/res/SBZ11.bmp differ diff --git a/CItems/TextArt/res/SBZ12.bmp b/CItems/TextArt/res/SBZ12.bmp new file mode 100644 index 0000000..2ccf9f3 Binary files /dev/null and b/CItems/TextArt/res/SBZ12.bmp differ diff --git a/CItems/TextArt/res/SBZ13.bmp b/CItems/TextArt/res/SBZ13.bmp new file mode 100644 index 0000000..ad31dc6 Binary files /dev/null and b/CItems/TextArt/res/SBZ13.bmp differ diff --git a/CItems/TextArt/res/SBZ14.bmp b/CItems/TextArt/res/SBZ14.bmp new file mode 100644 index 0000000..cc8b5a8 Binary files /dev/null and b/CItems/TextArt/res/SBZ14.bmp differ diff --git a/CItems/TextArt/res/SBZ15.bmp b/CItems/TextArt/res/SBZ15.bmp new file mode 100644 index 0000000..03ab1d4 Binary files /dev/null and b/CItems/TextArt/res/SBZ15.bmp differ diff --git a/CItems/TextArt/res/SBZ16.bmp b/CItems/TextArt/res/SBZ16.bmp new file mode 100644 index 0000000..9d7f6ae Binary files /dev/null and b/CItems/TextArt/res/SBZ16.bmp differ diff --git a/CItems/TextArt/res/SBZ17.bmp b/CItems/TextArt/res/SBZ17.bmp new file mode 100644 index 0000000..dcf6895 Binary files /dev/null and b/CItems/TextArt/res/SBZ17.bmp differ diff --git a/CItems/TextArt/res/SBZ18.bmp b/CItems/TextArt/res/SBZ18.bmp new file mode 100644 index 0000000..553614f Binary files /dev/null and b/CItems/TextArt/res/SBZ18.bmp differ diff --git a/CItems/TextArt/res/SBZ19.bmp b/CItems/TextArt/res/SBZ19.bmp new file mode 100644 index 0000000..6f1e125 Binary files /dev/null and b/CItems/TextArt/res/SBZ19.bmp differ diff --git a/CItems/TextArt/res/SBZ2.bmp b/CItems/TextArt/res/SBZ2.bmp new file mode 100644 index 0000000..027803b Binary files /dev/null and b/CItems/TextArt/res/SBZ2.bmp differ diff --git a/CItems/TextArt/res/SBZ20.bmp b/CItems/TextArt/res/SBZ20.bmp new file mode 100644 index 0000000..1155a26 Binary files /dev/null and b/CItems/TextArt/res/SBZ20.bmp differ diff --git a/CItems/TextArt/res/SBZ21.bmp b/CItems/TextArt/res/SBZ21.bmp new file mode 100644 index 0000000..c5dca01 Binary files /dev/null and b/CItems/TextArt/res/SBZ21.bmp differ diff --git a/CItems/TextArt/res/SBZ22.bmp b/CItems/TextArt/res/SBZ22.bmp new file mode 100644 index 0000000..14d60bf Binary files /dev/null and b/CItems/TextArt/res/SBZ22.bmp differ diff --git a/CItems/TextArt/res/SBZ23.bmp b/CItems/TextArt/res/SBZ23.bmp new file mode 100644 index 0000000..7c5e24a Binary files /dev/null and b/CItems/TextArt/res/SBZ23.bmp differ diff --git a/CItems/TextArt/res/SBZ24.bmp b/CItems/TextArt/res/SBZ24.bmp new file mode 100644 index 0000000..d28a43a Binary files /dev/null and b/CItems/TextArt/res/SBZ24.bmp differ diff --git a/CItems/TextArt/res/SBZ25.bmp b/CItems/TextArt/res/SBZ25.bmp new file mode 100644 index 0000000..31d2dcd Binary files /dev/null and b/CItems/TextArt/res/SBZ25.bmp differ diff --git a/CItems/TextArt/res/SBZ26.bmp b/CItems/TextArt/res/SBZ26.bmp new file mode 100644 index 0000000..56d9d07 Binary files /dev/null and b/CItems/TextArt/res/SBZ26.bmp differ diff --git a/CItems/TextArt/res/SBZ27.bmp b/CItems/TextArt/res/SBZ27.bmp new file mode 100644 index 0000000..4d0fc30 Binary files /dev/null and b/CItems/TextArt/res/SBZ27.bmp differ diff --git a/CItems/TextArt/res/SBZ28.bmp b/CItems/TextArt/res/SBZ28.bmp new file mode 100644 index 0000000..d478ce1 Binary files /dev/null and b/CItems/TextArt/res/SBZ28.bmp differ diff --git a/CItems/TextArt/res/SBZ29.bmp b/CItems/TextArt/res/SBZ29.bmp new file mode 100644 index 0000000..67b40a1 Binary files /dev/null and b/CItems/TextArt/res/SBZ29.bmp differ diff --git a/CItems/TextArt/res/SBZ3.bmp b/CItems/TextArt/res/SBZ3.bmp new file mode 100644 index 0000000..9389526 Binary files /dev/null and b/CItems/TextArt/res/SBZ3.bmp differ diff --git a/CItems/TextArt/res/SBZ30.bmp b/CItems/TextArt/res/SBZ30.bmp new file mode 100644 index 0000000..35291d8 Binary files /dev/null and b/CItems/TextArt/res/SBZ30.bmp differ diff --git a/CItems/TextArt/res/SBZ31.bmp b/CItems/TextArt/res/SBZ31.bmp new file mode 100644 index 0000000..08a4d42 Binary files /dev/null and b/CItems/TextArt/res/SBZ31.bmp differ diff --git a/CItems/TextArt/res/SBZ32.bmp b/CItems/TextArt/res/SBZ32.bmp new file mode 100644 index 0000000..9604681 Binary files /dev/null and b/CItems/TextArt/res/SBZ32.bmp differ diff --git a/CItems/TextArt/res/SBZ33.bmp b/CItems/TextArt/res/SBZ33.bmp new file mode 100644 index 0000000..99bfa24 Binary files /dev/null and b/CItems/TextArt/res/SBZ33.bmp differ diff --git a/CItems/TextArt/res/SBZ34.bmp b/CItems/TextArt/res/SBZ34.bmp new file mode 100644 index 0000000..ff20965 Binary files /dev/null and b/CItems/TextArt/res/SBZ34.bmp differ diff --git a/CItems/TextArt/res/SBZ35.bmp b/CItems/TextArt/res/SBZ35.bmp new file mode 100644 index 0000000..3a1563a Binary files /dev/null and b/CItems/TextArt/res/SBZ35.bmp differ diff --git a/CItems/TextArt/res/SBZ36.bmp b/CItems/TextArt/res/SBZ36.bmp new file mode 100644 index 0000000..acc5f75 Binary files /dev/null and b/CItems/TextArt/res/SBZ36.bmp differ diff --git a/CItems/TextArt/res/SBZ37.bmp b/CItems/TextArt/res/SBZ37.bmp new file mode 100644 index 0000000..9044d70 Binary files /dev/null and b/CItems/TextArt/res/SBZ37.bmp differ diff --git a/CItems/TextArt/res/SBZ38.bmp b/CItems/TextArt/res/SBZ38.bmp new file mode 100644 index 0000000..7defb99 Binary files /dev/null and b/CItems/TextArt/res/SBZ38.bmp differ diff --git a/CItems/TextArt/res/SBZ4.bmp b/CItems/TextArt/res/SBZ4.bmp new file mode 100644 index 0000000..fa2e392 Binary files /dev/null and b/CItems/TextArt/res/SBZ4.bmp differ diff --git a/CItems/TextArt/res/SBZ5.bmp b/CItems/TextArt/res/SBZ5.bmp new file mode 100644 index 0000000..23a49a4 Binary files /dev/null and b/CItems/TextArt/res/SBZ5.bmp differ diff --git a/CItems/TextArt/res/SBZ6.bmp b/CItems/TextArt/res/SBZ6.bmp new file mode 100644 index 0000000..5d0a7d2 Binary files /dev/null and b/CItems/TextArt/res/SBZ6.bmp differ diff --git a/CItems/TextArt/res/SBZ7.bmp b/CItems/TextArt/res/SBZ7.bmp new file mode 100644 index 0000000..13f3433 Binary files /dev/null and b/CItems/TextArt/res/SBZ7.bmp differ diff --git a/CItems/TextArt/res/SBZ8.bmp b/CItems/TextArt/res/SBZ8.bmp new file mode 100644 index 0000000..23bc7ab Binary files /dev/null and b/CItems/TextArt/res/SBZ8.bmp differ diff --git a/CItems/TextArt/res/SBZ9.bmp b/CItems/TextArt/res/SBZ9.bmp new file mode 100644 index 0000000..0349de0 Binary files /dev/null and b/CItems/TextArt/res/SBZ9.bmp differ diff --git a/CItems/TextArt/res/Z.bmp b/CItems/TextArt/res/Z.bmp new file mode 100644 index 0000000..d5157c8 Binary files /dev/null and b/CItems/TextArt/res/Z.bmp differ diff --git a/CItems/TextArt/res/temp.bmp b/CItems/TextArt/res/temp.bmp new file mode 100644 index 0000000..d0d6efa Binary files /dev/null and b/CItems/TextArt/res/temp.bmp differ diff --git a/CItems/TextArt/textart.res b/CItems/TextArt/textart.res new file mode 100644 index 0000000..ea95db9 Binary files /dev/null and b/CItems/TextArt/textart.res differ diff --git a/COPYING.LESSER.txt b/COPYING.LESSER.txt new file mode 100644 index 0000000..02bbb60 --- /dev/null +++ b/COPYING.LESSER.txt @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. \ No newline at end of file diff --git a/COPYING.txt b/COPYING.txt new file mode 100644 index 0000000..20d40b6 --- /dev/null +++ b/COPYING.txt @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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 3 of the License, 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 . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. \ No newline at end of file diff --git a/ClockAdj.cpp b/ClockAdj.cpp new file mode 100644 index 0000000..45150c7 --- /dev/null +++ b/ClockAdj.cpp @@ -0,0 +1,478 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "ClockAdj.h" +#include "Main.h" +//--------------------------------------------------------------------- +#pragma resource "*.dfm" +//TClockAdjDlg *ClockAdjDlg; +static int s_Gain = 0x0108; +//--------------------------------------------------------------------- +__fastcall TClockAdjDlg::TClockAdjDlg(TComponent* AOwner) + : TForm(AOwner) +{ + FormStyle = ((TForm *)AOwner)->FormStyle; + Font->Name = ((TForm *)AOwner)->Font->Name; + Font->Charset = ((TForm *)AOwner)->Font->Charset; + EntryAlignControl(); + + pBitmap = new Graphics::TBitmap(); + if( sys.m_Palette ) pBitmap->PixelFormat = pf16bit; + pBitmap->Width = PaintBox->Width; + pBitmap->Height = PaintBox->Height; + + + pDem = NULL; + pTick = NULL; + m_agcMax = 8192; + m_agcMin = 0; + m_agcSumMax = 8192 * AGCAVG; + m_Point = 0; + m_Samp = 11025; + m_rBase = 0; + m_MaxP = 0; + m_MaxD = 0; +} +//--------------------------------------------------------------------- +__fastcall TClockAdjDlg::~TClockAdjDlg() +{ + if( pTick != NULL ){ + delete pTick; + pTick = NULL; + } + pDem = NULL; + pBitmap->Palette = NULL; + delete pBitmap; + pBitmap = NULL; +} +//--------------------------------------------------------------------------- +// サイズ変更コントロールの登録 +void __fastcall TClockAdjDlg::EntryAlignControl(void) +{ + RECT rc; + rc.left = 0; + rc.top = 0; + rc.right = ClientWidth-1; + rc.bottom = ClientHeight-1; + + AlignList.EntryControl(OKBtn, &rc, OKBtn->Font); + AlignList.EntryControl(CancelBtn, &rc, CancelBtn->Font); + AlignList.EntryControl(Panel, &rc, NULL); + AlignList.EntryControl(TBGAIN, &rc, NULL); + AlignList.EntryControl(SBAGC, &rc, SBAGC->Font); + AlignList.EntryControl(MarkFreq, &rc, MarkFreq->Font); + AlignList.EntryControl(UDMark, &rc, NULL); + AlignList.EntryControl(Label2, &rc, Label2->Font); + AlignList.EntryControl(LPPM, &rc, LPPM->Font); + AlignList.EntryControl(EditClock, &rc, EditClock->Font); + AlignList.EntryControl(UDSamp, &rc, NULL); + AlignList.EntryControl(Label1, &rc, Label1->Font); + +// int CX = ::GetSystemMetrics(SM_CXFULLSCREEN); +// int CY = ::GetSystemMetrics(SM_CYFULLSCREEN); + int CX = ::GetSystemMetrics(SM_CXSCREEN); + int CY = ::GetSystemMetrics(SM_CYSCREEN); + if( (CX < Width)||(CY < Height) ){ + Top = 0; + Left = 0; + Width = CX; + Height = CY; + } +#if 0 + else { + Top = 0; + Left = 0; + Width = 600; + Height = 400; + } +#endif + FormCenter(this, CX, CY); + if( Owner != NULL ){ + WindowState = ((TForm *)Owner)->WindowState; + } + m_rBase = 0; +} +//--------------------------------------------------------------------------- +void __fastcall TClockAdjDlg::FormResize(TObject *Sender) +{ + CWaitCursor tw; + AlignList.NewAlign(this); + if( pBitmap != NULL ){ + delete pBitmap; + } + pBitmap = new Graphics::TBitmap(); + if( sys.m_Palette ) pBitmap->PixelFormat = pf16bit; + pBitmap->Width = PaintBox->Width; + pBitmap->Height = PaintBox->Height; + + TRect rc; + int XL = 0; + int XR = pBitmap->Width - 1; + int YT = 0; + int YB = pBitmap->Height - 1; + rc.Left = XL; + rc.Right = XR; + rc.Top = YT; + rc.Bottom = YB+1; + TCanvas *cp = pBitmap->Canvas; + cp->Brush->Color = clBlack; + cp->FillRect(rc); + + m_CursorX = XR - 20; + + cp->Font->Name = Font->Name; + cp->Font->Charset = Font->Charset; + cp->Font->Color = clWhite; + cp->Font->Size = 10; + int FH = cp->TextHeight("A"); + int Y = 5; + if( MsgEng ){ + Caption = "Calibrating the Sound Card with a Time Standard Broadcast Station"; +// "Adjust Sampling Frequency using an off-air time signal"; +// Caption = "Adjust Sampling freq. (Recive WWV tick sound on Mark freq.)"; + CancelBtn->Caption = "Cancel"; + + cp->TextOut(10, Y, "1) Receive standard radio wave (e.g., WWV, BPM)."); Y+=FH; + cp->TextOut(10, Y, "2) Tune into the tick sound."); Y+=FH; + cp->TextOut(10, Y, "3) Continue listening to the sound for a while. You have a vertical line."); Y+=FH; + cp->TextOut(10, Y, "4) Click the lower point of the line."); Y+=FH; + cp->TextOut(10, Y, "5) Click the upper point of the line."); Y+=FH; + Y+=FH; + cp->TextOut(10, Y, "You could use FAX broadcasting instead of WWV or JJY, but be sure it has"); Y+=FH; + cp->TextOut(10, Y, "exact timing."); + } + else { + cp->TextOut(10, Y, "1.BPMをAMまたはSSBで受信し、この画面の下にあるToneに1000Hzまたは"); Y+=FH; + cp->TextOut(10, Y, " 1600Hzを設定します."); Y+=FH; + cp->TextOut(10, Y, "2.SSBの場合は1秒チック音がToneに重なるように受信周波数を調整します."); Y+=FH; + cp->TextOut(10, Y, "3.しばらく受信して縦または斜めの帯線が表示されるのを待ちます(数分)."); Y+=FH; + cp->TextOut(10, Y, "4.表示された帯線の下の端点をクリックします."); Y+=FH; + cp->TextOut(10, Y, "5.更に同じ帯線の上の端点をクリックするとクロック値が自動的に"); Y+=FH; + cp->TextOut(10, Y, " 設定されます.(2点間の距離が長いほうが正確です)"); Y+=FH; + cp->TextOut(10, Y, "傾斜が非常に大きい場合、上記の手続きをもう一度繰り返して下さい."); Y+=FH+FH; + cp->TextOut(10, Y, "BPMの代わりに、JMH,JMGなどのFAX放送の0.5秒毎のデッドセクタを利用しても"); Y+=FH; + cp->TextOut(10, Y, "OKのようです."); Y+=FH; + cp->TextOut(10, Y, "左クリック - 調整の開始"); Y+=FH; + cp->TextOut(10, Y, "右クリック - 垂直カーソル移動"); + } +} +//--------------------------------------------------------------------------- +void __fastcall TClockAdjDlg::UpdateTB(void) +{ + TBGAIN->Enabled = !SBAGC->Down; + LG->Font->Color = SBAGC->Down ? clGrayText : clBlack; +} +//--------------------------------------------------------------------- +void __fastcall TClockAdjDlg::UpdatePPM(void) +{ + double dd = ((m_Samp - SampBase) * 1000000.0 / SampBase); + + char bf[64]; + sprintf(bf, "%d ppm", int(dd+0.5)); + LPPM->Caption = bf; +} +//--------------------------------------------------------------------- +int __fastcall TClockAdjDlg::Execute(TSound *p, double &Samp) +{ + pSound = p; + pDem = &p->SSTVDEM; + pTick = new CTICK; + pDem->pTick = pTick; + m_Samp = Samp; + pTick->m_Samp = int(Samp+0.5); + InitColorTable(clBlack, clWhite); + char bf[128]; + sprintf(bf, "%.2lf", m_Samp); + EditClock->Text = bf; + pTick->Init(); + pDem->m_Tick = 1; + m_DisEvent++; + UDMark->Position = 1000; + pDem->SetTickFreq(1000); + TBGAIN->Position = s_Gain & 0x00ff; + SBAGC->Down = s_Gain & 0xff00 ? 1 : 0; + UpdateTB(); + m_DisEvent--; + UpdatePPM(); + Mmsstv->PBoxG->Invalidate(); + int r = ShowModal(); + pDem->m_Tick = 0; + pDem->pTick = NULL; + InitColorTable(sys.m_ColorLow, sys.m_ColorHigh); + s_Gain = (s_Gain & 0x00ff) | (SBAGC->Down ? 0x0100 : 0); + delete pTick; + pTick = NULL; + pDem->SetTickFreq(0); + Mmsstv->PBoxG->Invalidate(); + if( r == IDOK ){ + Samp = m_Samp; + return TRUE; + } + else { + return FALSE; + } +} +//--------------------------------------------------------------------- +void __fastcall TClockAdjDlg::TimerTimer(TObject *Sender) +{ + if( pBitmap == NULL ) return; + if( pDem == NULL ) return; + if( pTick == NULL ) return; + + int *p = pTick->GetData(); + if( p == NULL ) return; + + TCanvas *tp = pBitmap->Canvas; + + int mx = -MAXINT; + int mi = MAXINT; + int x, xx, d; + double k1 = 16384.0/double(m_agcMax - m_agcMin); + double k2; + if( SBAGC->Down ){ + k2 = 128.0 / 16384.0; + } + else { + k2 = (128.0 * (s_Gain & 0x00ff)) / (4096 * 16); + } + int ax = -1; + for( xx = 0; xx < pTick->m_Samp; xx++ ){ + int xv = xx + m_rBase; + x = fmod(xv, m_Samp); + x = x * pBitmap->Width / m_Samp; + if( ax != x ){ + ax = x; + if( !x ){ + if( m_MaxD ){ + tp->Pixels[m_MaxP][0] = clRed; + } + m_MaxD = 0; + m_MaxP = 0; + TRect rc; + rc.Left = 0; + rc.Right = pBitmap->Width - 1; + rc.Top = 0; + rc.Bottom = pBitmap->Height - 2; + TRect src(rc); + src.Bottom--; + rc.Top++; + tp->CopyRect(rc, tp, src); + } + d = p[xx]; + if( m_MaxD < d ){ + m_MaxD = d; + m_MaxP = x; + } + if( mx < d ) mx = d; + if( mi > d ) mi = d; + if( SBAGC->Down ){ + d -= m_agcMin; + if( m_agcMax > 0 ) d = double(d) * k1; + } + d = double(d) * k2; + + if( d >= 128 ) d = 127; + if( d <= 0 ) d = 0; + tp->Pixels[x][0] = TColor(ColorTable[127-d]); + } + } + m_rBase += pTick->m_Samp; +#if 0 + for( x = 0; x < XR; x++){ + xx = (x * pTick->m_Samp)/pBitmap->Width; + d = p[xx]; + if( mx < d ) mx = d; + if( mi > d ) mi = d; + if( SBAGC->Down ){ + d -= m_agcMin; + if( m_agcMax > 0 ) d = double(d) * k1; + } + d = double(d) * k2; + + if( d >= 128 ) d = 127; + if( d <= 0 ) d = 0; + tp->Pixels[x][0] = TColor(ColorTable[127-d]); + } +#endif + m_agcSumMax -= m_agcMax; + m_agcSumMax += mx; + if( m_agcSumMax < (4096*AGCAVG) ) m_agcSumMax = (4096*AGCAVG); + m_agcMax = m_agcSumMax / AGCAVG; + m_agcMin = mi; + if( m_agcMin > 2048 ) m_agcMin = 2048; + m_PointY++; + PaintBox->Canvas->Draw(0, 0, (TGraphic*)pBitmap); + PaintCursor(); +} +//--------------------------------------------------------------------------- +void __fastcall TClockAdjDlg::DrawMessage(LPCSTR p) +{ + int xr = PaintBox->Canvas->TextWidth(p); + int xl = (PaintBox->Width - xr)/2; + xr += xl; + int FH = PaintBox->Canvas->TextHeight(p); + int VC = PaintBox->Height - FH; + PaintBox->Canvas->Pen->Color = clWhite; + PaintBox->Canvas->Brush->Color = clBlack; + PaintBox->Canvas->RoundRect(xl-10, VC-FH, xr+10, VC+FH, 10, 10); + PaintBox->Canvas->Font->Color = clWhite; + PaintBox->Canvas->TextOut(xl, VC-FH/2, p); +} +//--------------------------------------------------------------------------- +void __fastcall TClockAdjDlg::PaintCursor(void) +{ + PaintBox->Canvas->Pen->Color = clLime; + PaintBox->Canvas->Pen->Style = psDot; + PaintBox->Canvas->MoveTo(m_CursorX, 0); + int rop = ::SetROP2(PaintBox->Canvas->Handle, R2_MASKPENNOT); + PaintBox->Canvas->LineTo(m_CursorX, pBitmap->Height - 1); + ::SetROP2(PaintBox->Canvas->Handle, rop); + if( m_Point ){ + PaintBox->Canvas->Pen->Color = clYellow; + PaintBox->Canvas->Pen->Style = psSolid; + PaintBox->Canvas->MoveTo(m_PointX, m_PointY); + ::SetROP2(PaintBox->Canvas->Handle, R2_MASKPENNOT); + PaintBox->Canvas->LineTo(m_PointX2, m_PointY2); + ::SetROP2(PaintBox->Canvas->Handle, rop); + char bf[256]; + if( MsgEng ){ + sprintf( bf, "OK : Left button, Cancel : Right button Clock=%.2lf", GetPointSamp()); + } + else { + sprintf( bf, "決定 : 左ボタン, 中止 : 右ボタン Clock=%.2lf", GetPointSamp()); + } + DrawMessage(bf); + if( PaintBox->Cursor != crCross ) PaintBox->Cursor = crCross; + } + else { + if( PaintBox->Cursor != crDefault ) PaintBox->Cursor = crDefault; + } +} +//--------------------------------------------------------------------------- +void __fastcall TClockAdjDlg::PaintBoxPaint(TObject *Sender) +{ + PaintBox->Canvas->Draw(0, 0, (TGraphic*)pBitmap); + PaintCursor(); +} +//--------------------------------------------------------------------------- +void __fastcall TClockAdjDlg::PaintBoxMouseUp(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( Button == mbLeft ){ + if( m_Point ){ + m_Point = 0; + if( m_PointY2 != m_PointY ){ + m_Samp = GetPointSamp(); + ModalResult = mrOk; + } + } + else { + m_PointX2 = m_PointX = X; + m_PointY2 = m_PointY = Y; + m_Point = 1; + } + } + else if( m_Point ){ + m_Point = 0; + } + else { + m_CursorX = X; + } + PaintBox->Canvas->Draw(0, 0, (TGraphic*)pBitmap); + PaintCursor(); +} +//--------------------------------------------------------------------------- +void __fastcall TClockAdjDlg::MarkFreqChange(TObject *Sender) +{ + if( m_DisEvent ) return; + + int dd; + if( sscanf(AnsiString(MarkFreq->Text).c_str(), "%lu", &dd ) == 1){ //ja7ude 0428 + if( (dd >= 300) && (dd <= 2700) ){ + m_DisEvent++; + UDMark->Position = SHORT(dd); + pDem->SetTickFreq(dd); + Mmsstv->PBoxG->Invalidate(); + m_DisEvent--; + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TClockAdjDlg::TBGAINChange(TObject *Sender) +{ + s_Gain = (s_Gain & 0xff00) | TBGAIN->Position; +} +//--------------------------------------------------------------------------- +void __fastcall TClockAdjDlg::UDMarkClick(TObject *Sender, TUDBtnType Button) +{ + if( m_DisEvent ) return; + + pDem->SetTickFreq(UDMark->Position); + Mmsstv->PBoxG->Invalidate(); +} +//--------------------------------------------------------------------------- +void __fastcall TClockAdjDlg::SBAGCClick(TObject *Sender) +{ + UpdateTB(); +} +//--------------------------------------------------------------------------- +double __fastcall TClockAdjDlg::GetPointSamp(void) +{ + if( m_PointY == m_PointY2 ) return m_Samp; + double d = (m_PointX2 - m_PointX); + d = d * m_Samp / pBitmap->Width; + d /= (m_PointY - m_PointY2); + d += m_Samp; + d = NormalSampFreq(d, 100); + return d; +} +//--------------------------------------------------------------------------- +void __fastcall TClockAdjDlg::PaintBoxMouseMove(TObject *Sender, + TShiftState Shift, int X, int Y) +{ + if( m_Point ){ + m_PointX2 = X; + m_PointY2 = Y; + PaintBox->Canvas->Draw(0, 0, (TGraphic*)pBitmap); + PaintCursor(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TClockAdjDlg::UDSampClick(TObject *Sender, + TUDBtnType Button) +{ + if( Button == btNext ){ + m_Samp += 0.02; + } + else { + m_Samp -= 0.02; + } + m_Samp = NormalSampFreq(m_Samp, 50); + m_rBase += (1.0 - (m_Samp / pTick->m_Samp)) * pTick->m_Samp; + char bf[128]; + sprintf(bf, "%.2lf", m_Samp); + EditClock->Text = bf; + UpdatePPM(); +} +//--------------------------------------------------------------------------- + diff --git a/ClockAdj.dfm b/ClockAdj.dfm new file mode 100644 index 0000000..bc23c8f Binary files /dev/null and b/ClockAdj.dfm differ diff --git a/ClockAdj.h b/ClockAdj.h new file mode 100644 index 0000000..e4a5da6 --- /dev/null +++ b/ClockAdj.h @@ -0,0 +1,118 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//---------------------------------------------------------------------------- +#ifndef ClockAdjH +#define ClockAdjH +//---------------------------------------------------------------------------- +//ja7ude 0428 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Comlib.h" +#include "sound.h" +//---------------------------------------------------------------------------- +#define AGCAVG 4 +//---------------------------------------------------------------------------- +class TClockAdjDlg : public TForm +{ +__published: + TButton *OKBtn; + TButton *CancelBtn; + TPanel *Panel; + TPaintBox *PaintBox; + TEdit *EditClock; + TLabel *Label1; + TTimer *Timer; + TComboBox *MarkFreq; + TLabel *Label2; + TLabel *LPPM; + TTrackBar *TBGAIN; + TUpDown *UDMark; + TSpeedButton *SBAGC; + TLabel *LG; + TUpDown *UDSamp; + void __fastcall TimerTimer(TObject *Sender); + void __fastcall PaintBoxPaint(TObject *Sender); + void __fastcall PaintBoxMouseUp(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + + void __fastcall MarkFreqChange(TObject *Sender); + void __fastcall TBGAINChange(TObject *Sender); + + void __fastcall UDMarkClick(TObject *Sender, TUDBtnType Button); + void __fastcall SBAGCClick(TObject *Sender); + void __fastcall PaintBoxMouseMove(TObject *Sender, TShiftState Shift, int X, + int Y); + + void __fastcall FormResize(TObject *Sender); + void __fastcall UDSampClick(TObject *Sender, TUDBtnType Button); +private: + CAlignList AlignList; + void __fastcall EntryAlignControl(void); + + Graphics::TBitmap *pBitmap; + TSound *pSound; + CSSTVDEM *pDem; + CTICK *pTick; + + int m_DisEvent; + double m_Samp; + + int m_agcMin; + int m_agcMax; + int m_agcSumMax; + + void __fastcall UpdateTB(void); + void __fastcall UpdatePPM(void); + void __fastcall PaintCursor(void); + int m_CursorX; + + void __fastcall DrawMessage(LPCSTR p); + double __fastcall GetPointSamp(void); + int m_Point; + int m_PointX; + int m_PointY; + int m_PointX2; + int m_PointY2; + + int m_MaxP; + double m_MaxD; + + int m_rBase; + AnsiString m_Help; +public: + virtual __fastcall TClockAdjDlg(TComponent* AOwner); + __fastcall TClockAdjDlg::~TClockAdjDlg(); + + int __fastcall Execute(TSound *p, double &Samp); +}; +//---------------------------------------------------------------------------- +//extern TClockAdjDlg *ClockAdjDlg; +//---------------------------------------------------------------------------- +#endif diff --git a/ColorBar.cpp b/ColorBar.cpp new file mode 100644 index 0000000..b435b83 --- /dev/null +++ b/ColorBar.cpp @@ -0,0 +1,258 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "ColorBar.h" +#include "Main.h" +#include "ColorSet.h" +#include "BitMask.h" +#include "PicRect.h" +//--------------------------------------------------------------------- +#pragma resource "*.dfm" +//--------------------------------------------------------------------- +__fastcall TColorBarDlg::TColorBarDlg(TComponent* AOwner) + : TForm(AOwner) +{ + FormStyle = ((TForm *)AOwner)->FormStyle; + Font->Name = ((TForm *)AOwner)->Font->Name; + Font->Charset = ((TForm *)AOwner)->Font->Charset; + if( MsgEng ){ + Caption = "Color bar"; + CancelBtn->Caption = "Cancel"; + RGType->Caption = "Affects"; + RGType->Items->Strings[0] = "Mono tone"; + RGType->Items->Strings[1] = "Two tones"; + RGType->Items->Strings[2] = "Colors"; + RGType->Items->Strings[3] = "Bitmap"; + RGType->Items->Strings[4] = "Sound"; + CBColVert->Caption = "Vertical gradation"; + LLine->Caption = "Line"; + SelBtn->Caption = "Components"; + BitBtn->Caption = "Bitmap"; + GB2->Caption = "Musical scale (1-8)"; + } + pBitmap = NULL; + pItem = NULL; +} +//--------------------------------------------------------------------- +__fastcall TColorBarDlg::~TColorBarDlg() +{ + if( pBitmap != NULL ){ + delete pBitmap; + } +} +//--------------------------------------------------------------------- +void __fastcall TColorBarDlg::UpdateUI(void) +{ + switch(RGType->ItemIndex){ + case 3: + PC1->Visible = FALSE; + PC2->Visible = FALSE; + PC3->Visible = FALSE; + PC4->Visible = FALSE; + SelBtn->Enabled = FALSE; + BitBtn->Enabled = TRUE; + CBColVert->Enabled = FALSE; + LineCnt->Enabled = TRUE; + LLine->Enabled = TRUE; + Sound->Enabled = FALSE; + break; + case 4: + PC1->Visible = FALSE; + PC2->Visible = FALSE; + PC3->Visible = FALSE; + PC4->Visible = FALSE; + SelBtn->Enabled = FALSE; + BitBtn->Enabled = FALSE; + CBColVert->Enabled = FALSE; + LineCnt->Enabled = FALSE; + LLine->Enabled = FALSE; + Sound->Enabled = TRUE; + break; + default: + PC1->Visible = TRUE; + PC2->Visible = RGType->ItemIndex >= 1 ? TRUE : FALSE; + PC3->Visible = RGType->ItemIndex >= 2 ? TRUE : FALSE; + PC4->Visible = RGType->ItemIndex >= 2 ? TRUE : FALSE; + CBColVert->Enabled = PC2->Visible; + SelBtn->Enabled = RGType->ItemIndex >= 2 ? TRUE : FALSE; + BitBtn->Enabled = FALSE; + LineCnt->Enabled = TRUE; + LLine->Enabled = TRUE; + Sound->Enabled = FALSE; + break; + } +} +//--------------------------------------------------------------------- +int __fastcall TColorBarDlg::Execute(CDrawTitle *p) +{ + pItem = p; + RGType->ItemIndex = pItem->m_Type; + PC1->Color = pItem->m_Col1; + PC2->Color = pItem->m_Col2; + PC3->Color = pItem->m_Col3; + PC4->Color = pItem->m_Col4; + LineCnt->Text = pItem->m_Y2 - pItem->m_Y1 + 1; + CBColVert->Checked = pItem->m_ColVert; + Sound->Text = pItem->m_Sound; + if( pItem->pBitmap != NULL ){ + pBitmap = DupeBitmap(pItem->pBitmap, -1); + } + UpdateUI(); + if( ShowModal() == IDOK ){ + pItem->m_Type = RGType->ItemIndex; + pItem->m_Col1 = PC1->Color; + pItem->m_Col2 = PC2->Color; + pItem->m_Col3 = PC3->Color; + pItem->m_Col4 = PC4->Color; + pItem->m_ColVert = CBColVert->Checked; + pItem->m_Sound = Sound->Text; + int d; + if( pItem->m_Type == 4 ){ + d = strlen(pItem->m_Sound.c_str()) - 1; + if( d < 3 ) d = 3; + pItem->m_Y2 = pItem->m_Y1 + d; + } + else if( sscanf(AnsiString(LineCnt->Text).c_str(), "%u", &d) == 1 ){ //ja7ude 0428 + if( (d >= 1) && (d <= 256) ){ + pItem->m_Y2 = pItem->m_Y1 + d - 1; + if( pItem->m_Y2 > 255 ){ + d = pItem->m_Y2 - 255; + pItem->m_Y1 -= d; + pItem->m_Y2 -= d; + } + } + } + if( (RGType->ItemIndex == 3) && (pBitmap != NULL) ){ + if( pItem->pBitmap == NULL ){ + pItem->pBitmap = new Graphics::TBitmap(); + AdjustBitmapFormat(pItem->pBitmap); + } + pItem->pBitmap->Width = pBitmap->Width; + pItem->pBitmap->Height = pBitmap->Height; + pItem->pBitmap->Canvas->Draw(0, 0, pBitmap); + } + else if( pItem->pBitmap != NULL ){ + delete pItem->pBitmap; + pItem->pBitmap = NULL; + } + return TRUE; + } + return FALSE; +} +//--------------------------------------------------------------------- +void __fastcall TColorBarDlg::PCClick(TObject *Sender) +{ + TPanel *tp = (TPanel *)Sender; + TColorDialog *pDialog = Mmsstv->ColorDialog; + InitCustomColor(pDialog); + AddCustomColor(pDialog, PC1->Color); + AddCustomColor(pDialog, PC2->Color); + AddCustomColor(pDialog, PC3->Color); + AddCustomColor(pDialog, PC4->Color); + pDialog->Color = tp->Color; + SetDisPaint(); + if( pDialog->Execute() == TRUE ){ + tp->Color = pDialog->Color; + } + ResDisPaint(); +} +//--------------------------------------------------------------------------- + +void __fastcall TColorBarDlg::RGTypeClick(TObject *Sender) +{ + UpdateUI(); +} +//--------------------------------------------------------------------------- + +void __fastcall TColorBarDlg::SelBtnClick(TObject *Sender) +{ + TColorSetDlg *pBox = new TColorSetDlg(this); + TColor col[4]; + col[0] = PC1->Color; + col[1] = PC2->Color; + col[2] = PC3->Color; + col[3] = PC4->Color; + if( pBox->Execute(col) == TRUE ){ + PC1->Color = col[0]; + PC2->Color = col[1]; + PC3->Color = col[2]; + PC4->Color = col[3]; + } + delete pBox; +} +//--------------------------------------------------------------------------- +void __fastcall TColorBarDlg::BitBtnClick(TObject *Sender) +{ + TOpenDialog *pDialog = Mmsstv->OpenDialog; + pDialog->Options >> ofCreatePrompt; + pDialog->Options << ofFileMustExist; + if( MsgEng ){ + pDialog->Title = "Load picture from file"; + } + else { + pDialog->Title = "画像のロード"; + } + pDialog->Filter = GetPicFilter(); + pDialog->FileName = ""; + pDialog->DefaultExt = "jpg"; + pDialog->InitialDir = BitmapDir; + SetDisPaint(); + NormalWindow(this); + if( Mmsstv->OpenDialogExecute(TRUE) == TRUE ){ + SetDirName(BitmapDir, AnsiString(pDialog->FileName).c_str()); //ja7ude 0428 + TPicRectDlg *pBox = new TPicRectDlg(this); + if( ::LoadImage(pBox->pBitmap, AnsiString(pDialog->FileName).c_str()) == TRUE ){ //ja7ude 0428 + Graphics::TBitmap *pBmp = new Graphics::TBitmap(); + AdjustBitmapFormat(pBmp); + pBmp->Width = pBox->pBitmap->Width < 320 ? pBox->pBitmap->Width : 320; + int H = 16; + int d; + if( sscanf(AnsiString(LineCnt->Text).c_str(), "%u", &d) == 1 ){ //ja7ude 0428 + if( (d >= 1) && (d <= 256) ){ + H = d; + } + } + pBmp->Height = pBox->pBitmap->Height < H ? pBox->pBitmap->Height : H; + if( pBox->Execute(pBmp) == TRUE ){ + if( pBitmap == NULL ){ + pBitmap = new Graphics::TBitmap(); + } + AdjustBitmapFormat(pBitmap); + pBitmap->Width = 320; + pBitmap->Height = H; + int x, y; + for( y = 0; y < pBitmap->Height; y += pBmp->Height){ + for( x = 0; x < pBitmap->Width; x += pBmp->Width){ + pBitmap->Canvas->Draw(x, y, pBmp); + } + } + } + delete pBmp; + } + delete pBox; + } + ResDisPaint(); + TopWindow(this); +} +//--------------------------------------------------------------------------- + diff --git a/ColorBar.dfm b/ColorBar.dfm new file mode 100644 index 0000000..61e6249 Binary files /dev/null and b/ColorBar.dfm differ diff --git a/ColorBar.h b/ColorBar.h new file mode 100644 index 0000000..f5760ae --- /dev/null +++ b/ColorBar.h @@ -0,0 +1,71 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//---------------------------------------------------------------------------- +#ifndef OCBH +#define OCBH +//---------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//---------------------------------------------------------------------------- +#include "Draw.h" +//---------------------------------------------------------------------------- +class TColorBarDlg : public TForm +{ +__published: + TButton *OKBtn; + TButton *CancelBtn; + TRadioGroup *RGType; + TPanel *PC1; + TPanel *PC2; + TPanel *PC3; + TPanel *PC4; + TButton *SelBtn; + TLabel *LLine; + TComboBox *LineCnt; + TButton *BitBtn; + TCheckBox *CBColVert; + TGroupBox *GB2; + TEdit *Sound; + void __fastcall PCClick(TObject *Sender); + void __fastcall RGTypeClick(TObject *Sender); + void __fastcall SelBtnClick(TObject *Sender); + void __fastcall BitBtnClick(TObject *Sender); + +private: + void __fastcall UpdateUI(void); + Graphics::TBitmap *pBitmap; + CDrawTitle *pItem; +public: + virtual __fastcall TColorBarDlg(TComponent* AOwner); + __fastcall TColorBarDlg::~TColorBarDlg(); + + int __fastcall TColorBarDlg::Execute(CDrawTitle *pItem); +}; +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +#endif diff --git a/ColorSet.cpp b/ColorSet.cpp new file mode 100644 index 0000000..ba8ae2f --- /dev/null +++ b/ColorSet.cpp @@ -0,0 +1,125 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "ComLib.h" +#include "ColorSet.h" +#include "Main.h" +//--------------------------------------------------------------------- +#pragma resource "*.dfm" +//--------------------------------------------------------------------- +__fastcall TColorSetDlg::TColorSetDlg(TComponent* AOwner) + : TForm(AOwner) +{ + FormStyle = ((TForm *)AOwner)->FormStyle; + Font->Name = ((TForm *)AOwner)->Font->Name; + Font->Charset = ((TForm *)AOwner)->Font->Charset; + if( MsgEng ){ + Caption = "Color components"; + CancelBtn->Caption = "Cancel"; + } +} +//--------------------------------------------------------------------- +TPanel *__fastcall TColorSetDlg::GetItem(int n, int x) +{ + TPanel *_tb[]={ + PC11, PC12, PC13, PC14, + PC21, PC22, PC23, PC24, + PC31, PC32, PC33, PC34, + PC41, PC42, PC43, PC44, + PC51, PC52, PC53, PC54, + PC61, PC62, PC63, PC64, + PC71, PC72, PC73, PC74, + PC81, PC82, PC83, PC84, + }; + return _tb[n * 4 + x]; +} +//--------------------------------------------------------------------- +int __fastcall TColorSetDlg::Execute(TColor *pcol) +{ + int i, x, f; + int n = 0; + int pos = -1; + for( i = 0; i < 8; i++ ){ + f = 0; + for( x = 0; x < 4; x++, n++ ){ + GetItem(i, x)->Color = sys.m_ColorSet[n]; + if( pcol[x] != sys.m_ColorSet[n] ) f++; + } + if( !f ){ + pos = i; + } + } + RGSet->ItemIndex = pos; + if( ShowModal() == IDOK ){ + n = 0; + for( i = 0; i < 8; i++ ){ + for( x = 0; x < 4; x++, n++ ){ + sys.m_ColorSet[n] = GetItem(i, x)->Color; + } + } + if( RGSet->ItemIndex >= 0 ){ + for( x = 0; x < 4; x++ ){ + pcol[x] = GetItem(RGSet->ItemIndex, x)->Color; + } + return TRUE; + } + } + return FALSE; +} +//--------------------------------------------------------------------- +void __fastcall TColorSetDlg::PCClick(TObject *Sender) +{ + int i, x, pos; + pos = -1; + for( i = 0; (i < 8) && (pos < 0); i++ ){ + for(x = 0; x < 4; x++ ){ + if( Sender == GetItem(i, x) ){ + pos = i; + break; + } + } + } + TColorDialog *pDialog = Mmsstv->ColorDialog; + InitCustomColor(pDialog); + + TPanel *pPanel[4]; + for( i = 0; i < 4; i++ ){ + pPanel[i] = GetItem(pos, i); + AddCustomColor(pDialog, pPanel[i]->Color); + } + + pDialog->Color = ((TPanel *)Sender)->Color; + SetDisPaint(); + if( pDialog->Execute() == TRUE ){ + ((TPanel *)Sender)->Color = pDialog->Color; + if( (pPanel[0]->Color == pPanel[1]->Color) && (pPanel[2]->Color == pPanel[3]->Color) ){ + if( YesNoMB( MsgEng ? "Change to two colors gradation?" : "2色のグラデーションに変更しますか?" ) == IDYES ){ + pPanel[1]->Color = GetCol(pPanel[0]->Color, pPanel[3]->Color, 2, 4); + pPanel[2]->Color = GetCol(pPanel[0]->Color, pPanel[3]->Color, 3, 4); + } + } + } + ResDisPaint(); +} +//--------------------------------------------------------------------------- + diff --git a/ColorSet.dfm b/ColorSet.dfm new file mode 100644 index 0000000..f6e32f9 Binary files /dev/null and b/ColorSet.dfm differ diff --git a/ColorSet.h b/ColorSet.h new file mode 100644 index 0000000..8889ddb --- /dev/null +++ b/ColorSet.h @@ -0,0 +1,84 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//---------------------------------------------------------------------------- +#ifndef ColorSetH +#define ColorSetH +//---------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//---------------------------------------------------------------------------- +class TColorSetDlg : public TForm +{ +__published: + TButton *OKBtn; + TButton *CancelBtn; + TRadioGroup *RGSet; + TPanel *PC11; + TPanel *PC12; + TPanel *PC13; + TPanel *PC14; + TPanel *PC21; + TPanel *PC22; + TPanel *PC23; + TPanel *PC24; + TPanel *PC31; + TPanel *PC32; + TPanel *PC33; + TPanel *PC34; + TPanel *PC41; + TPanel *PC42; + TPanel *PC43; + TPanel *PC44; + TPanel *PC51; + TPanel *PC52; + TPanel *PC53; + TPanel *PC54; + TPanel *PC61; + TPanel *PC62; + TPanel *PC63; + TPanel *PC64; + TPanel *PC71; + TPanel *PC72; + TPanel *PC73; + TPanel *PC74; + TPanel *PC81; + TPanel *PC82; + TPanel *PC83; + TPanel *PC84; + void __fastcall PCClick(TObject *Sender); +private: + TPanel *__fastcall GetItem(int n, int x); + +public: + virtual __fastcall TColorSetDlg(TComponent* AOwner); + + int __fastcall Execute(TColor *pcol); +}; +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +#endif diff --git a/ComLib.cpp b/ComLib.cpp new file mode 100644 index 0000000..0f216f4 --- /dev/null +++ b/ComLib.cpp @@ -0,0 +1,3848 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------------- +#include //ja7ude 0521 +#pragma hdrstop + +#include "ComLib.h" +#include "PicRect.h" +#include "LogFile.h" +#include "sstv.h" +#include "jhandle.h" +#include "main.h" +//--------------------------------------------------------------------------- +//#define SYSMB 1 // MessageBox 0-Application, 1-System +// +char BgnDir[256]; // 起動ディレクトリ + +char HistDir[256]; +char StockDir[256]; + +char BitmapDir[256]; // ビットマップロード・セーブ +char SBitmapDir[256]; // ビットマップロード・セーブ +char MMLogDir[256]; // MMLOGファイルのディレクトリ +char ExtLogDir[256]; // エクスポートファイルのディレクトリ +char RecDir[256]; // 録音ファイルのディレクトリ +char TemplateDir[256]; // ビットマップロード・セーブ + +AnsiString JanHelp; + +double SampFreq = 11025.0; // サンプリング周波数 +double SampBase = 11025.0; +int DemOver = 1; +int SampType = 0; +int SampSize = 2048; + +double FFTSamp = 11025.0; +int FFTSampType = 0; +int FFT_SIZE=2048; + +SYSSET sys; +LCID lcid; // ロケール情報 +DWORD ColorTable[128]; +int DisPaint; +int MsgEng; +//HPALETTE UsrPal; +int WinNT; +int WinVista; + +CExecPB g_ExecPB; + +const int SampTable[]={11025, 8000, 6000, 12000, 16000, 18000, 22050, 24000, 44100, 48000}; + +//--------------------------------------------------------------------------- +void __fastcall SetDisPaint(void) +{ + DisPaint++; +} +void __fastcall ResDisPaint(void) +{ + if( DisPaint ) DisPaint--; +} +//--------------------------------------------------------------------------- +void ShowHelp(int index) +{ + if( !JanHelp.IsEmpty() ){ + HWND hd; + if( Screen->ActiveForm != NULL ){ + hd = Screen->ActiveForm->Handle; + } + else { + hd = Application->MainForm->Handle; + } + char bf[256]; + sprintf(bf, "%s%s", BgnDir, JanHelp.c_str()); + if( !strcmpi(GetEXT(JanHelp.c_str()), "HLP") ){ + if( index != -1 ){ + ::WinHelp(hd, bf, HELP_CONTEXT, index); + } + else { + ::WinHelp(hd, bf, HELP_FINDER, 0); + } + } + else { + ::ShellExecute(hd, "open", bf, NULL, NULL, SW_SHOWDEFAULT); + } + } +} +//--------------------------------------------------------------------------- +void InitSampType(void) +{ + + if( SampFreq >= 46000.0 ){ + SampType = 9; + SampBase = 48000.0; + SampSize = (48000*2048)/11025; + DemOver = 0; + FFTSamp = SampFreq * 0.25; + FFTSampType = 2; // X4 over sampling + FFT_SIZE = 2048; + } + else if( SampFreq >= 43000.0 ){ + SampType = 8; + SampBase = 44100.0; + SampSize = (44100*2048)/11025; + DemOver = 0; + FFTSamp = SampFreq * 0.25; + FFTSampType = 2; // X4 over sampling + FFT_SIZE = 2048; + } + else if( SampFreq >= 23000.0 ){ + SampType = 7; + SampBase = 24000.0; + SampSize = (24000*2048)/11025; + DemOver = 0; + FFTSamp = SampFreq * 0.5; + FFTSampType = 1; // X2 over sampling + FFT_SIZE = 2048; + } + else if( SampFreq >= 20000.0 ){ + SampType = 6; + SampBase = 22050.0; + SampSize = (22050*2048)/11025; + DemOver = 0; + FFTSamp = SampFreq * 0.5; + FFTSampType = 1; // X2 over sampling + FFT_SIZE = 2048; + } + else if( SampFreq >= 17000.0 ){ + SampType = 5; + SampBase = 18000.0; + SampSize = (18000*2048)/11025; + DemOver = 0; + FFTSamp = SampFreq * 0.5; + FFTSampType = 1; // X2 over sampling + FFT_SIZE = 2048; + } + else if( SampFreq >= 15000.0 ){ + SampType = 4; + SampBase = 16000.0; + SampSize = (16000*2048)/11025; + DemOver = 0; + FFTSamp = SampFreq; + FFTSampType = 0; + FFT_SIZE = 2048; + } + else if( SampFreq >= 11600.0 ){ + SampType = 3; + SampBase = 12000.0; + SampSize = (12000*2048)/11025; + DemOver = 0; + FFTSamp = SampFreq; + FFTSampType = 0; + FFT_SIZE = 2048; + } + else if( SampFreq >= 10000.0 ){ + SampType = 0; + SampBase = 11025.0; + SampSize = 2048; + DemOver = 0; + FFTSamp = SampFreq; + FFTSampType = 0; + FFT_SIZE = 2048; + } + else if( SampFreq >= 7000.0 ){ + SampType = 1; + SampBase = 8000.0; + SampSize = (8000*2048)/11025; + DemOver = 0; + FFTSamp = SampFreq; + FFTSampType = 0; + FFT_SIZE = 1024; + } + else if( SampFreq >= 5000.0 ){ + SampType = 2; + SampBase = 6000.0; + SampSize = (6000*2048)/11025; + DemOver = 0; + FFTSamp = SampFreq; + FFTSampType = 0; + FFT_SIZE = 1024; + } + if( SampSize & 1 ) SampSize++; + if( SampSize > 8192 ) SampSize = 8192; +} +//--------------------------------------------------------------------------- +double NormalSampFreq(double d, double m) +{ + d = double(int((d * m) + 0.5)/m); + return d; +} +//--------------------------------------------------------------------------- +int IsFile(LPCSTR pName) +{ + FILE *fp; + fp = fopen(pName, "rb"); + if( fp != NULL ){ + fclose(fp); + return 1; + } + else { + return 0; + } +} +//--------------------------------------------------------------------------- +int SetTimeOffsetInfo(int &Hour, int &Min) +{ + TIME_ZONE_INFORMATION tz; + + int off; + switch(GetTimeZoneInformation(&tz)){ + case TIME_ZONE_ID_STANDARD: + off = tz.StandardBias; + break; + case TIME_ZONE_ID_DAYLIGHT: + off = tz.DaylightBias; + break; + default: + return FALSE; + } + if( off >= 0 ){ + Hour = -(off / 60); + Min = (off % 60); + } + else { + off = -off; + Hour = off / 60; + Min = off % 60; + } + return TRUE; +} +//--------------------------------------------------------------------------- +void AddjustOffset(SYSTEMTIME *tp) +{ + if( sys.m_TimeOffset || sys.m_TimeOffsetMin ){ +//typedef struct _SYSTEMTIME { /* st */ +// WORD wYear; +// WORD wMonth; +// WORD wDayOfWeek; +// WORD wDay; +// WORD wHour; +// WORD wMinute; +// WORD wSecond; +// WORD wMilliseconds; +//} SYSTEMTIME; + + + LPCSTR mt; + int Hour = tp->wHour; + int Min = tp->wMinute; + Min += sys.m_TimeOffsetMin; + if( Min >= 60 ){ + Hour++; + Min -= 60; + } + else if( Min < 0 ){ + Hour--; + Min += 60; + } + tp->wMinute = WORD(Min); + Hour += sys.m_TimeOffset; + if( Hour >= 24 ){ + tp->wHour = WORD(Hour - 24); + tp->wDay++; + if( tp->wYear % 4 ){ + mt = MONN; + } + else { + mt = MONU; + } + if( tp->wDay > mt[tp->wMonth] ){ + tp->wDay = 1; + tp->wMonth++; + if( tp->wMonth > 12 ){ + tp->wMonth = 1; + tp->wYear++; + } + } + } + else if( Hour < 0 ){ + tp->wHour = WORD(Hour + 24); + tp->wDay--; + if( tp->wDay < 1 ){ + tp->wMonth--; + if( tp->wMonth < 1 ){ + tp->wMonth = 12; + tp->wYear--; + } + if( tp->wYear % 4 ){ + tp->wDay = MONN[tp->wMonth]; + } + else { + tp->wDay = MONU[tp->wMonth]; + } + } + } + else { + tp->wHour = WORD(Hour); + } + } +} +//--------------------------------------------------------------------------- +void GetUTC(SYSTEMTIME *tp) +{ + ::GetSystemTime(tp); + AddjustOffset(tp); +} +//--------------------------------------------------------------------------- +void GetLocal(SYSTEMTIME *tp) +{ + ::GetLocalTime(tp); + AddjustOffset(tp); +} +//--------------------------------------------------------------------------- +LPSTR StrDupe(LPCSTR s) +{ + LPSTR p = new char[strlen(s)+1]; + strcpy(p, s); + return p; +} +//--------------------------------------------------------------------------- +void InitColorTable(TColor cl, TColor ch) +{ + int br = (ch & 0x000000ff); + int bg = (ch & 0x0000ff00) >> 8; + int bb = (ch & 0x00ff0000) >> 16; + int er = (cl & 0x000000ff); + int eg = (cl & 0x0000ff00) >> 8; + int eb = (cl & 0x00ff0000) >> 16; + + int brw = er - br + 1; + int bgw = eg - bg + 1; + int bbw = eb - bb + 1; + int r, g, b; + + ColorTable[0] = DWORD( br | (bg<<8) | (bb<<16) ); + int i; + for( i = 1; i < 127; i++ ){ + r = (br + (i * brw/128)) & 0x000000ff; + g = (bg + (i * bgw/128)) & 0x000000ff; + b = (bb + (i * bbw/128)) & 0x000000ff; + ColorTable[i] = DWORD( r | (g<<8) | (b<<16) ); + } + ColorTable[127] = DWORD( er | (eg<<8) | (eb<<16) ); +} + +#if 0 +const DEFKEYTBL KEYTBL[]={ + { VK_F1, "F1" }, + { VK_F2, "F2" }, + { VK_F3, "F3" }, + { VK_F4, "F4" }, + { VK_F5, "F5" }, + { VK_F6, "F6" }, + { VK_F7, "F7" }, + { VK_F8, "F8" }, + { VK_F9, "F9" }, + { VK_F10, "F10" }, + { VK_F11, "F11" }, + { VK_F12, "F12" }, + + { VK_LEFT, "←"}, + { VK_RIGHT, "→"}, + { VK_UP, "↑"}, + { VK_DOWN, "↓"}, + { VK_PRIOR, "PageUp"}, + { VK_NEXT, "PageDown"}, + { VK_HOME, "Home" }, + { VK_END, "End" }, + { VK_INSERT, "Insert" }, + { VK_DELETE, "Delete" }, + { VK_HELP, "Help" }, + { VK_ESCAPE, "ESC" }, + + + { VK_F1 | 0x400, "Shift+F1" }, + { VK_F2 | 0x400, "Shift+F2" }, + { VK_F3 | 0x400, "Shift+F3" }, + { VK_F4 | 0x400, "Shift+F4" }, + { VK_F5 | 0x400, "Shift+F5" }, + { VK_F6 | 0x400, "Shift+F6" }, + { VK_F7 | 0x400, "Shift+F7" }, + { VK_F8 | 0x400, "Shift+F8" }, + { VK_F9 | 0x400, "Shift+F9" }, + { VK_F10 | 0x400, "Shift+F10" }, + { VK_F11 | 0x400, "Shift+F11" }, + { VK_F12 | 0x400, "Shift+F12" }, + + { VK_LEFT | 0x400, "Shift+←"}, + { VK_RIGHT | 0x400, "Shift+→"}, + { VK_UP | 0x400, "Shift+↑"}, + { VK_DOWN | 0x400, "Shift+↓"}, + { VK_PRIOR | 0x400, "Shift+PageUp"}, + { VK_NEXT | 0x400, "Shift+PageDown"}, + { VK_HOME | 0x400, "Shift+Home" }, + { VK_END | 0x400, "Shift+End" }, + { VK_INSERT | 0x400, "Shift+Insert" }, + { VK_DELETE | 0x400, "Shift+Delete" }, + { VK_HELP | 0x400, "Shift+Help" }, + { VK_ESCAPE | 0x400, "Shift+ESC" }, + + { VK_F1 | 0x100, "Ctrl+F1" }, + { VK_F2 | 0x100, "Ctrl+F2" }, + { VK_F3 | 0x100, "Ctrl+F3" }, + { VK_F4 | 0x100, "Ctrl+F4" }, + { VK_F5 | 0x100, "Ctrl+F5" }, + { VK_F6 | 0x100, "Ctrl+F6" }, + { VK_F7 | 0x100, "Ctrl+F7" }, + { VK_F8 | 0x100, "Ctrl+F8" }, + { VK_F9 | 0x100, "Ctrl+F9" }, + { VK_F10 | 0x100, "Ctrl+F10" }, + { VK_F11 | 0x100, "Ctrl+F11" }, + { VK_F12 | 0x100, "Ctrl+F12" }, + { '1' | 0x100, "Ctrl+1" }, + { '2' | 0x100, "Ctrl+2" }, + { '3' | 0x100, "Ctrl+3" }, + { '4' | 0x100, "Ctrl+4" }, + { '5' | 0x100, "Ctrl+5" }, + { '6' | 0x100, "Ctrl+6" }, + { '7' | 0x100, "Ctrl+7" }, + { '8' | 0x100, "Ctrl+8" }, + { '9' | 0x100, "Ctrl+9" }, + { '0' | 0x100, "Ctrl+0" }, + { 'A' | 0x100, "Ctrl+A" }, + { 'B' | 0x100, "Ctrl+B" }, + { 'C' | 0x100, "Ctrl+C" }, + { 'D' | 0x100, "Ctrl+D" }, + { 'E' | 0x100, "Ctrl+E" }, + { 'F' | 0x100, "Ctrl+F" }, + { 'G' | 0x100, "Ctrl+G" }, +// { 'H' | 0x100, "Ctrl+H" }, +// { 'I' | 0x100, "Ctrl+I" }, + { 'K' | 0x100, "Ctrl+K" }, + { 'L' | 0x100, "Ctrl+L" }, +// { 'M' | 0x100, "Ctrl+M" }, + { 'N' | 0x100, "Ctrl+N" }, + { 'O' | 0x100, "Ctrl+O" }, + { 'P' | 0x100, "Ctrl+P" }, + { 'Q' | 0x100, "Ctrl+Q" }, + { 'R' | 0x100, "Ctrl+R" }, + { 'S' | 0x100, "Ctrl+S" }, + { 'T' | 0x100, "Ctrl+T" }, + { 'U' | 0x100, "Ctrl+U" }, + { 'V' | 0x100, "Ctrl+V" }, + { 'W' | 0x100, "Ctrl+W" }, + { 'X' | 0x100, "Ctrl+X" }, + { 'Y' | 0x100, "Ctrl+Y" }, + { 'Z' | 0x100, "Ctrl+Z" }, + + { VK_LEFT | 0x100, "Ctrl+←"}, + { VK_RIGHT | 0x100, "Ctrl+→"}, + { VK_UP | 0x100, "Ctrl+↑"}, + { VK_DOWN | 0x100, "Ctrl+↓"}, + { VK_PRIOR | 0x100, "Ctrl+PageUp"}, + { VK_NEXT | 0x100, "Ctrl+PageDown"}, + { VK_HOME | 0x100, "Ctrl+Home" }, + { VK_END | 0x100, "Ctrl+End" }, + { VK_INSERT | 0x100, "Ctrl+Insert" }, + { VK_DELETE | 0x100, "Ctrl+Delete" }, + { VK_HELP | 0x100, "Ctrl+Help" }, + { VK_ESCAPE | 0x100, "Ctrl+ESC" }, + + { VK_F1 | 0x200, "Alt+F1" }, + { VK_F2 | 0x200, "Alt+F2" }, + { VK_F3 | 0x200, "Alt+F3" }, + { VK_F4 | 0x200, "Alt+F4" }, + { VK_F5 | 0x200, "Alt+F5" }, + { VK_F6 | 0x200, "Alt+F6" }, + { VK_F7 | 0x200, "Alt+F7" }, + { VK_F8 | 0x200, "Alt+F8" }, + { VK_F9 | 0x200, "Alt+F9" }, + { VK_F10 | 0x200, "Alt+F10" }, + { VK_F11 | 0x200, "Alt+F11" }, + { VK_F12 | 0x200, "Alt+F12" }, + { '1' | 0x200, "Alt+1" }, + { '2' | 0x200, "Alt+2" }, + { '3' | 0x200, "Alt+3" }, + { '4' | 0x200, "Alt+4" }, + { '5' | 0x200, "Alt+5" }, + { '6' | 0x200, "Alt+6" }, + { '7' | 0x200, "Alt+7" }, + { '8' | 0x200, "Alt+8" }, + { '9' | 0x200, "Alt+9" }, + { '0' | 0x200, "Alt+0" }, + { 'A' | 0x200, "Alt+A" }, + { 'B' | 0x200, "Alt+B" }, + { 'C' | 0x200, "Alt+C" }, + { 'D' | 0x200, "Alt+D" }, + { 'E' | 0x200, "Alt+E" }, + { 'F' | 0x200, "Alt+F" }, + { 'G' | 0x200, "Alt+G" }, + { 'H' | 0x200, "Alt+H" }, + { 'I' | 0x200, "Alt+I" }, + { 'K' | 0x200, "Alt+K" }, + { 'L' | 0x200, "Alt+L" }, + { 'M' | 0x200, "Alt+M" }, + { 'N' | 0x200, "Alt+N" }, + { 'O' | 0x200, "Alt+O" }, + { 'P' | 0x200, "Alt+P" }, + { 'Q' | 0x200, "Alt+Q" }, + { 'R' | 0x200, "Alt+R" }, + { 'S' | 0x200, "Alt+S" }, + { 'T' | 0x200, "Alt+T" }, + { 'U' | 0x200, "Alt+U" }, + { 'V' | 0x200, "Alt+V" }, + { 'W' | 0x200, "Alt+W" }, + { 'X' | 0x200, "Alt+X" }, + { 'Y' | 0x200, "Alt+Y" }, + { 'Z' | 0x200, "Alt+Z" }, + + { VK_LEFT | 0x200, "Alt+←"}, + { VK_RIGHT | 0x200, "Alt+→"}, + { VK_UP | 0x200, "Alt+↑"}, + { VK_DOWN | 0x200, "Alt+↓"}, + { VK_PRIOR | 0x200, "Alt+PageUp"}, + { VK_NEXT | 0x200, "Alt+PageDown"}, + { VK_HOME | 0x200, "Alt+Home" }, + { VK_END | 0x200, "Alt+End" }, + { VK_INSERT | 0x200, "Alt+Insert" }, + { VK_DELETE | 0x200, "Alt+Delete" }, + { VK_HELP | 0x200, "Alt+Help" }, + { VK_ESCAPE | 0x200, "Alt+ESC" }, + { 0, "" }, +}; +//--------------------------------------------------------------------------- +LPCSTR ToDXKey(LPCSTR s) +{ + if( MsgEng && *s ){ + LPSTR p; + static char bf[32]; + strcpy(bf, s); + if( (p = strstr(bf, "←"))!=NULL ){ + strcpy(p, "ArrowLeft"); + return bf; + } + else if( (p = strstr(bf, "→"))!=NULL ){ + strcpy(p, "ArrowRight"); + return bf; + } + else if( (p = strstr(bf, "↓"))!=NULL ){ + strcpy(p, "ArrowDown"); + return bf; + } + else if( (p = strstr(bf, "↑"))!=NULL ){ + strcpy(p, "ArrowUp"); + return bf; + } + } + return s; +} +//--------------------------------------------------------------------------- +LPCSTR ToJAKey(LPCSTR s) +{ + if( MsgEng && *s ){ + LPSTR p; + static char bf[32]; + strcpy(bf, s); + if( (p = strstr(bf, "ArrowLeft"))!=NULL ){ + strcpy(p, "←"); + return bf; + } + else if( (p = strstr(bf, "ArrowRight"))!=NULL ){ + strcpy(p, "→"); + return bf; + } + else if( (p = strstr(bf, "ArrowDown"))!=NULL ){ + strcpy(p, "↓"); + return bf; + } + else if( (p = strstr(bf, "ArrowUp"))!=NULL ){ + strcpy(p, "↑"); + return bf; + } + } + return s; +} +//--------------------------------------------------------------------------- +LPCSTR GetKeyName(WORD Key) +{ + int i; + for( i = 0; KEYTBL[i].Key; i++ ){ + if( Key == KEYTBL[i].Key ){ + break; + } + } + return ToDXKey(KEYTBL[i].pName); +} +//--------------------------------------------------------------------------- +WORD GetKeyCode(LPCSTR pName) +{ + LPCSTR p = ToJAKey(pName); + int i; + for( i = 0; KEYTBL[i].Key; i++ ){ + if( !strcmp(p, KEYTBL[i].pName) ) break; + } + return KEYTBL[i].Key; +} +#endif + +//--------------------------------------------------------------------------- +int SetTBValue(double d, double dmax, int imax) +{ + if( d ){ + int dd = int(sqrt(d * dmax * dmax / imax) + 0.5); + if( dd > imax ) dd = imax; + return dd; + } + else { + return 0; + } +} + +double GetTBValue(int d, double dmax, int imax) +{ + return (d * d) * imax/ (dmax * dmax); +} + +LPUSTR jstrupr(LPUSTR s) +{ + LPUSTR p = s; + int kf; + + for( kf = 0; *p; p++ ){ + if( kf ){ + kf = 0; + } + else if( _mbsbtype((unsigned char *)p, 0) == _MBC_LEAD ){ + kf = 1; + } + else { + *p = (unsigned char)toupper(*p); + } + } + return s; +} +/*#$% +=============================================================== + 時刻を調整する +--------------------------------------------------------------- + t : 時刻(UTC) + c : 時差コード +--------------------------------------------------------------- + ローカルタイム +--------------------------------------------------------------- + A-Z + a-z +30min +=============================================================== +*/ +WORD AdjustRolTimeUTC(WORD tim, char c) +{ + const char tdf[]={ +/* A B C D E F G H I J K L M N O P Q R S T U V W X Y Z */ + 1,2,3,4,5,6,7,8,9,9,10,11,12,23,22,21,20,19,18,17,16,15,14,13,12,0 + }; + int cc; + + cc = toupper(c); + if( (cc >= 'A')&&(cc <= 'Z') ){ + // JST to UTC +#if 0 + if( tim >= (9*60*30) ){ + tim -= WORD(9 * 60 * 30); + } + else { + tim += WORD(15 * 60 * 30); + } +#endif + tim /= WORD(30); + tim += WORD(tdf[cc-'A'] * 60); + if( c >= 'a' ) tim += WORD(30); + while( tim >= (24 * 60) ){ + tim -= WORD(24 * 60); + } + tim *= WORD(30); + if( !tim ) tim++; + } + else { + tim = 0; + } + return tim; +} +///---------------------------------------------------------------- +/// ウィンドウをクライアントセンターにする +void FormCenter(TForm *tp, int XW, int YW) +{ + int top = (YW - tp->Height)/2; + int left = (XW - tp->Width)/2; + if( top < 0 ) top = 0; + if( left < 0 ) left = 0; + tp->Top = top; + tp->Left = left; +} +/*#$% +======================================================== + 最後の文字コードを返す +-------------------------------------------------------- + p : 文字列のポインタ +-------------------------------------------------------- + 文字コード +-------------------------------------------------------- +======================================================== +*/ +char *lastp(char *p) +{ + if( *p ){ + for( ; *p; p++ ); + p--; + return(p); + } + else { + return(p); + } +} +/*#$% +======================================================== + 末尾のスペースとTABを取る +-------------------------------------------------------- + s : 文字列のポインタ +-------------------------------------------------------- + 文字列のポインタ +-------------------------------------------------------- +======================================================== +*/ +char *clipsp(char *s) +{ + char *p; + + if( *s ){ + for( p = lastp(s); p >= s; p-- ){ + if( (*p == ' ')||(*p == 0x09) ){ + *p = 0; + } + else { + break; + } + } + } + return(s); +} +//--------------------------------------------------------------------------- +LPCSTR _strdmcpy(LPSTR t, LPCSTR p, char c) +{ + for( ; *p && (*p != c); p++, t++ ) *t = *p; + *t = 0; + if( *p == c ) p++; + return(p); +} +const char *StrDlmCpy(char *t, const char *p, char Dlm, int len) +{ + const char _tt1[]="[{(「<"; + const char _tt2[]="]})」>"; + const char *pp; + int r = FALSE; + + char Key; + if( (pp = strchr(_tt2, Dlm))!=NULL ){ + Key = _tt1[pp - _tt2]; + } + else { + Key = 0; + } + int f, k; + for( f = k = 0; *p; p++ ){ + if( k ){ // 漢字2バイト目 + k = 0; + } + else if( _mbsbtype((const unsigned char *)p, 0) == _MBC_LEAD ){ // 漢字1バイト目 + k = 1; + } + else if( *p == Key ){ + f++; + } + else if( *p == Dlm ){ + if( f ){ + f--; + } + else { + r = TRUE; + p++; + break; + } + } + if( len ){ + *t++ = *p; + len--; + } + } + *t = 0; + return (r == TRUE) ? p : NULL; +} + +const char *StrDlmCpyK(char *t, const char *p, char Dlm, int len) +{ + const char _tt1[]="[{(「<"; + const char _tt2[]="]})」>"; + const char *pp; + int r = FALSE; + + char Key; + if( (pp = strchr(_tt2, Dlm))!=NULL ){ + Key = _tt1[pp - _tt2]; + } + else { + Key = 0; + } + int f, k; + for( f = k = 0; *p; p++ ){ + if( k ){ // 漢字2バイト目 + k = 0; + } + else if( _mbsbtype((const unsigned char *)p, 0) == _MBC_LEAD ){ // 漢字1バイト目 + k = 1; + } + else if( (pp = strchr(_tt1, *p))!=NULL ){ + Key = _tt2[pp - _tt1]; + f++; + } + else if( f && (*p == Key) ){ + f--; + Key = 0; + } + else if( *p == Dlm ){ + if( !f ){ + r = TRUE; + p++; + break; + } + } + if( len ){ + *t++ = *p; + len--; + } + } + *t = 0; + return (r == TRUE) ? p : NULL; +} +//--------------------------------------------------------------------------- +void StrCopy(LPSTR t, LPCSTR s, int n) +{ + for( ; *s && n; n--, s++, t++){ + *t = *s; + } + *t = 0; +} +//--------------------------------------------------------------------------- +char LastC(LPCSTR p) +{ + char c = 0; + + if( *p ){ + c = *(p + strlen(p) - 1); + } + return c; +} + +/*#$% +======================================================== + 拡張子を得る +-------------------------------------------------------- + p : 文字列のポインタ +-------------------------------------------------------- + 文字コード +-------------------------------------------------------- +======================================================== +*/ +LPCSTR GetEXT(LPCSTR Fname) +{ + if( *Fname ){ + LPCSTR p = Fname + (strlen(Fname) - 1); + for( ; p > Fname; p-- ){ + if( *p == '.' ) return p+1; + } + } + return ""; +} + +void SetEXT(LPSTR pName, LPSTR pExt) +{ + if( *pName ){ + LPSTR p; + + for( p = &pName[strlen(pName)-1]; p >= pName; p-- ){ + if( *p == '.' ){ + strcpy(p, pExt); + return; + } + } + strcat(pName, pExt); + } +} + +BOOL __fastcall CheckEXT(LPCSTR pName, LPCSTR pExt) +{ + return !strcmpi(GetEXT(pName), pExt); +} + +void SetCurDir(LPSTR t, int size) +{ + if( !::GetCurrentDirectory(size-1, t) ){ + *t = 0; + } + else { + if( LastC(t) != '\\' ){ + strcat(t, "\\"); + } + } +} + +void SetDirName(LPSTR t, LPCSTR pName) +{ + char drive[_MAX_DRIVE]; + char dir[_MAX_DIR]; + char name[_MAX_FNAME]; + char ext[_MAX_EXT]; + AnsiString Dir; + + ::_splitpath( pName, drive, dir, name, ext ); + Dir = drive; + Dir += dir; + strncpy(t, Dir.c_str(), 128); +} + +LPCSTR StrDbl(double d) +{ + static char bf[64]; + LPSTR p; + + sprintf(bf, "%lf", d); + for( p = &bf[strlen(bf)-1]; p >= bf; p-- ){ + if( (*p == '0')&&(*(p-1)!='.') ){ + *p = 0; + } + else { + break; + } + } + return bf; +} + +LPCSTR StrDblE(double d) +{ + static char bf[32]; + + sprintf(bf, "%le", d); + return bf; +} + +double ReadDoubleIniFile(TMemIniFile *p, LPCSTR c1, LPCSTR c2, double d) +{ + AnsiString cs = StrDblE(d); + AnsiString rs = p->ReadString(c1, c2, cs); + if( sscanf(rs.c_str(), "%lf", &d) != 1 ) d = 0.0; + return d; +} + +void WriteDoubleIniFile(TMemIniFile *p, LPCSTR c1, LPCSTR c2, double d) +{ + AnsiString cs = StrDblE(d); + p->WriteString(c1, c2, cs); +} + +///---------------------------------------------------------------- +/// CR/LFを削除 +/// +void ClipLF(LPSTR sp) +{ + for( ; *sp; sp++ ){ + if( (*sp == LF)||(*sp == CR) ){ + *sp = 0; + break; + } + } +} +///---------------------------------------------------------------- +/// コメントを削除(スペースおよびTABも削除) +/// +void DeleteComment(LPSTR bf) +{ + LPSTR sp, tp; + + for( sp = tp = bf; *sp; sp++ ){ + if( (*sp == ';')||(*sp == CR)||(*sp == LF) ){ + break; + } + else if( (*sp!=' ')&&(*sp!=TAB) ){ + *tp++ = *sp; + } + } + *tp = 0; +} + +LPSTR FillSpace(LPSTR s, int n) +{ + LPSTR p = s; + int i = 0; + for( ; *p && (i < n); i++, p++ ); + for( ; i < n; i++, p++ ){ + *p = ' '; + } + *p = 0; + return s; +} +///---------------------------------------------------------------- +/// ホワイトスペースのスキップ +/// +LPSTR SkipSpace(LPSTR sp) +{ + for( ; *sp; sp++ ){ + if( (*sp != ' ')&&(*sp != TAB) ) break; + } + return sp; +} + +LPCSTR SkipSpace(LPCSTR sp) +{ + for( ; *sp; sp++ ){ + if( (*sp != ' ')&&(*sp != TAB) ) break; + } + return sp; +} + +///---------------------------------------------------------------- +/// デリミッタ分解を行う +/// +LPSTR StrDlm(LPSTR &t, LPSTR p) +{ + return StrDlm(t, p, ','); +} + +///---------------------------------------------------------------- +/// デリミッタ分解を行う +/// +LPSTR StrDlm(LPSTR &t, LPSTR p, char c) +{ + int f, k; + LPSTR d1=NULL; + LPSTR d2=NULL; + + t = p; + f = k = 0; + while(*p){ + if( k ){ // 漢字2バイト目 + k = 0; + } + else if( _mbsbtype((const unsigned char *)p, 0) == _MBC_LEAD ){ // 漢字1バイト目 + k = 1; + } + else if( *p == 0x22 ){ + if( !f ){ + if( d1 == NULL ) d1 = p+1; + f++; + } + else { + d2 = p; + f--; + } + } + else if( !f && (*p == c) ){ + *p = 0; + p++; + break; + } + p++; + } + + if( (d1!=NULL)&&(d2!=NULL) ){ + if( ((t+1)==d1) && ( ((p-2)==d2)||((p-1)==d2) ) ){ + t = d1; + *d2 = 0; + } + } + return(p); +} + +///---------------------------------------------------------------- +/// +void ChgString(LPSTR t, char a, char b) +{ + for( ; *t; t++ ){ + if( *t == a ) *t = b; + } +} + +///---------------------------------------------------------------- +/// +void DelChar(LPSTR t, char a) +{ + for( ; *t; t++ ){ + if( *t == a ){ + strcpy(t, t+1); + t--; + } + } +} + +//--------------------------------------------------------------------------- +BOOL __fastcall ATOI(int &d, LPCSTR s) +{ + LPCSTR p = SkipSpace(s); + if( *p == '-' ) p++; + while(*p){ + if( !isdigit(*p++) ) return FALSE; + } + if( sscanf(s, "%d", &d) != 1 ) return FALSE; + return TRUE; +} + +/*#$% +======================================================== + デシマルアスキーを数値に変換する +-------------------------------------------------------- + p : 文字列のポインタ + n : 変換桁数 +-------------------------------------------------------- + 数値 +-------------------------------------------------------- +======================================================== +*/ +int atoin(const char *p, int n) +{ + int d; + + for( d = 0; *p && n; p++, n-- ){ + d *= 10; + d += (*p & 0x0f); + } + return(d); +} +/*#$% +======================================================== + 16進アスキーを数値に変換する +-------------------------------------------------------- + p : 文字列のポインタ + n : 変換桁数 +-------------------------------------------------------- + 数値 +-------------------------------------------------------- +======================================================== +*/ +int htoin(const char *p, int n) +{ + if( *p == 'x' ) return 0; + int d; + + for( d = 0; *p && n; p++, n-- ){ + d = d << 4; + d += (*p & 0x0f); + if( *p >= 'A' ) d += 9; + } + return(d); +} +//--------------------------------------------------------------------------- +int InvMenu(TMenuItem *pItem) +{ + pItem->Checked = pItem->Checked ? FALSE : TRUE; + return pItem->Checked; +} +//--------------------------------------------------------------------------- +void AdjustBitmapFormat(Graphics::TBitmap *pBitmap) +{ + if( sys.m_UseB24 ){ + pBitmap->PixelFormat = pf24bit; + } + else { + if( sys.m_Palette ) pBitmap->PixelFormat = pf24bit; + } +} +//--------------------------------------------------------------------------- +Graphics::TBitmap *Bitmap24bit(Graphics::TBitmap *pBitmap) +{ + if( pBitmap->PixelFormat != pf24bit ){ + Graphics::TBitmap *pBmp = DupeBitmap(pBitmap, pf24bit); + delete pBitmap; + pBitmap = pBmp; + } + return pBitmap; +} +//--------------------------------------------------------------------------- +int SaveBitmap24(Graphics::TBitmap *pBitmap, LPCSTR pName) +{ + int r; + + if( pBitmap->PixelFormat != pf24bit ){ + Graphics::TBitmap *pBmp = DupeBitmap(pBitmap, pf24bit); + r = SaveBitmap(pBmp, pName); + delete pBmp; + } + else { + r = SaveBitmap(pBitmap, pName); + } + return r; +} +//--------------------------------------------------------------------------- +int SaveBitmap(Graphics::TBitmap *pBitmap, LPCSTR pName) +{ + CWaitCursor wait; + try { + pBitmap->SaveToFile(pName); + } + catch(...){ + ErrorFWrite(pName); + return FALSE; + } + return TRUE; +} +//--------------------------------------------------------------------------- +int LoadBitmap(Graphics::TBitmap *pBitmap, LPCSTR pName) +{ + if( pBitmap == NULL ) return FALSE; + + CWaitCursor wait; + try { + pBitmap->LoadFromFile(pName); + } + catch(...){ + ErrorMB( "Could not load from '%s'", pName ); + return FALSE; + } + return TRUE; +} +//--------------------------------------------------------------------- +void FillBitmap(Graphics::TBitmap *pBitmap, TColor col) +{ + TRect rc; + rc.Top = 0; + rc.Left = 0; + rc.Right = pBitmap->Width; + rc.Bottom = pBitmap->Height; + pBitmap->Canvas->Brush->Style = bsSolid; + pBitmap->Canvas->Brush->Color = col; + pBitmap->Canvas->FillRect(rc); +} +//--------------------------------------------------------------------------- +int SaveJPEG(Graphics::TBitmap *pBitmap, LPCSTR pName) +{ + CWaitCursor wait; + int r = TRUE; + int YW = pBitmap->Height; + int XW = pBitmap->Width; + + image_buffer = new BYTE[YW * XW * 3]; + image_height = YW; + image_width = XW; + int f24 = ((pBitmap->PixelFormat == pf24bit) && (pBitmap->Palette==NULL)) ? 1 : 0; + BYTE *bp = image_buffer; + int x, y; + if( f24 ){ + for( y = 0; y < YW; y++ ){ + BYTE *s = (BYTE *)pBitmap->ScanLine[y]; + for( x = 0; x < XW; x++ ){ + *bp++ = *(s + 2); + *bp++ = *(s + 1); + *bp++ = *s; + s += 3; + } + } + } + else { + COLD c; + for( y = 0; y < YW; y++ ){ + for( x = 0; x < XW; x++ ){ + c.c = pBitmap->Canvas->Pixels[x][y]; + *bp++ = c.b.r; + *bp++ = c.b.g; + *bp++ = c.b.b; + } + } + } + if( !write_JPEG_file(pName, sys.m_JPEGQuality) ){ + ErrorFWrite(pName); + r = FALSE; + } + delete image_buffer; + image_buffer = NULL; + return r; +} +//--------------------------------------------------------------------- +int SaveImage(Graphics::TBitmap *pBitmap, LPCSTR pName) +{ + LPCSTR pExt = GetEXT(pName); + if( !strcmpi(pExt, "BMP") ){ + return SaveBitmap24(pBitmap, pName); + } + else if( !strcmpi(pExt, "JPG") ){ + return SaveJPEG(pBitmap, pName); + } + else { + return FALSE; + } +} +//--------------------------------------------------------------------------- +static Graphics::TBitmap *pBitmapLoad; +static int JpegPlane; +void SetJPEGSize(int height, int width, int plane) +{ + if( pBitmapLoad == NULL ) return; + pBitmapLoad->Height = height; + pBitmapLoad->Width = width; + JpegPlane = plane; +} + +void SetJPEGImage(BYTE *p, int line) +{ + if( pBitmapLoad == NULL ) return; + if( !line ) return; + if( !(line & 0x007f) ) MultProcA(); + + int x; + + BYTE *t = (BYTE *)pBitmapLoad->ScanLine[line-1]; + if( JpegPlane == 1 ){ + for( x = 0; x < pBitmapLoad->Width; x++ ){ + *t++ = *p; + *t++ = *p; + *t++ = *p++; + } + } + else if( JpegPlane >= 3 ){ + for( x = 0; x < pBitmapLoad->Width; x++ ){ + *t++ = *(p+2); + *t++ = *(p+1); + *t++ = *p; + p+=3; + } + } +} +//--------------------------------------------------------------------------- +int LoadJPEG(Graphics::TBitmap *pBitmap, LPCSTR pName) +{ + if( pBitmap == NULL ) return FALSE; + + CWaitCursor wait; + pBitmapLoad = pBitmap; + pBitmapLoad->PixelFormat = pf24bit; + pBitmapLoad->Palette = NULL; + return read_JPEG_file(pName) ? TRUE : FALSE; +} +//--------------------------------------------------------------------------- +int LoadWMF(Graphics::TBitmap *pBitmap, LPCSTR pName) +{ + if( pBitmap == NULL ) return FALSE; + + CWaitCursor wait; + + int r = FALSE; + TMetafile *pMeta = new TMetafile; + try { + pMeta->Enhanced = FALSE; + pMeta->LoadFromFile(pName); + pBitmap->PixelFormat = pf24bit; + pBitmap->Width = pMeta->Width; + pBitmap->Height = pMeta->Height; + if( pMeta->Transparent ) FillBitmap(pBitmap, clBtnFace); + pBitmap->Canvas->Draw(0, 0, pMeta); + r = TRUE; + } + catch(...){ + ErrorMB( "Could not load from '%s'", pName ); + } + delete pMeta; + return r; +} +//--------------------------------------------------------------------- +int IsPic(LPCSTR pExt) +{ + return (!strcmpi(pExt, "BMP") || !strcmpi(pExt, "JPG") || !strcmpi(pExt, "WMF")); +} + +LPCSTR GetPicFilter(void) +{ + return MsgEng ? "Picture files(*.jpg;*.bmp;*.wmf)|*.jpg;*.bmp;*.wmf" : "画像ファイル(*.jpg;*.bmp;*.wmf)|*.jpg;*.bmp;*.wmf"; +} +LPCSTR GetTempMFilter(void) +{ + return MsgEng ? "Templates(*.mtm)|*.mtm" : "テンプレート(*.mtm)|*.mtm"; +} +LPCSTR GetTempIFilter(void) +{ + return MsgEng ? "Template items(*.mti)|*.mti" : "テンプレートアイテム(*.mti)|*.mti"; +} +LPCSTR GetTempFilter(void) +{ + return MsgEng ? "Templates(*.mtm)|*.mtm|Template items(*.mti)|*.mti" : "テンプレート(*.mtm)|*.mtm|テンプレートアイテム(*.mti)|*.mti"; +} +LPCSTR GetLibFilter(void) +{ + return MsgEng ? "Custom items(*.dll)|*.dll" : "カスタムアイテム(*.dll)|*.dll"; +} +//--------------------------------------------------------------------- +int LoadImage(Graphics::TBitmap *pBitmap, LPCSTR pName) +{ + LPCSTR pExt = GetEXT(pName); + if( !strcmpi(pExt, "BMP") ){ + return LoadBitmap(pBitmap, pName); + } + else if( !strcmpi(pExt, "JPG") ){ + return LoadJPEG(pBitmap, pName); + } + else if( !strcmpi(pExt, "WMF") ){ + return LoadWMF(pBitmap, pName); + } + else { + return FALSE; + } +} +//--------------------------------------------------------------------- +void InitCustomColor(TColorDialog *tp) +{ + tp->CustomColors->Text = ""; +} +//--------------------------------------------------------------------- +void AddCustomColor(TColorDialog *tp, TColor col) +{ + char bf[256]; + + sprintf(bf, "Color%c=%06lX", tp->CustomColors->Count + 'A', DWORD(col) & 0x00ffffff); + tp->CustomColors->Add(bf); +} +///---------------------------------------------------------------- +HWND GetMBHandle(int &flag) +{ + HWND hd; + if( Screen->ActiveForm != NULL ){ + hd = Screen->ActiveForm->Handle; + } + else { + hd = NULL; + } + flag = MB_SETFOREGROUND; + flag |= MB_TOPMOST; + flag |= (hd == NULL) ? MB_TASKMODAL : MB_APPLMODAL; + return hd; +} +static int MsgBoxFlag = 0; +///---------------------------------------------------------------- +/// メッセージの表示 +/// +///---------------------------------------------------------------- +/// メッセージの表示 +/// +void InfoMB(LPCSTR fmt, ...) +{ + if( MsgBoxFlag ) return; + MsgBoxFlag++; + va_list pp; + char bf[1024]; + + va_start(pp, fmt); + vsprintf( bf, fmt, pp ); + va_end(pp); + + int flag; + HWND hd = GetMBHandle(flag); + SetDisPaint(); + flag |= (MB_OK | MB_ICONINFORMATION); +// Application->NormalizeTopMosts(); + ::MessageBox(hd, bf, "MMSSTV", flag); +// Application->RestoreTopMosts(); + ResDisPaint(); + MsgBoxFlag--; +} +///---------------------------------------------------------------- +/// エラーメッセージの表示 +/// +void ErrorMB(LPCSTR fmt, ...) +{ + if( MsgBoxFlag ) return; + MsgBoxFlag++; + va_list pp; + char bf[1024]; + + va_start(pp, fmt); + vsprintf( bf, fmt, pp ); + va_end(pp); + + int flag; + HWND hd = GetMBHandle(flag); + SetDisPaint(); + flag |= (MB_OK | MB_ICONEXCLAMATION); +// Application->NormalizeTopMosts(); + ::MessageBox(hd, bf, MsgEng ? "Error":"エラー", flag); +// Application->RestoreTopMosts(); + ResDisPaint(); + MsgBoxFlag--; +} + +///---------------------------------------------------------------- +/// 警告メッセージの表示 +/// +void WarningMB(LPCSTR fmt, ...) +{ + if( MsgBoxFlag ) return; + MsgBoxFlag++; + va_list pp; + char bf[1024]; + + va_start(pp, fmt); + vsprintf( bf, fmt, pp ); + va_end(pp); + + int flag; + HWND hd = GetMBHandle(flag); + SetDisPaint(); + flag |= (MB_OK | MB_ICONEXCLAMATION); +// Application->NormalizeTopMosts(); + ::MessageBox(hd, bf, MsgEng?"Warning":"警告", flag); +// Application->RestoreTopMosts(); + ResDisPaint(); + MsgBoxFlag--; +} + +///---------------------------------------------------------------- +/// 実行選択メッセージの表示 +/// +int YesNoMB(LPCSTR fmt, ...) +{ + if( MsgBoxFlag ) return IDNO; + MsgBoxFlag++; + va_list pp; + char bf[1024]; + + va_start(pp, fmt); + vsprintf( bf, fmt, pp ); + va_end(pp); + + int flag; + HWND hd = GetMBHandle(flag); + SetDisPaint(); +// if( Screen->ActiveForm != NULL ) NormalWindow(Screen->ActiveForm); + flag |= (MB_YESNO | MB_ICONQUESTION); +// Application->NormalizeTopMosts(); + int r = ::MessageBox(hd, bf, "MMSSTV", flag); +// Application->RestoreTopMosts(); + ResDisPaint(); + MsgBoxFlag--; + return r; +} + +///---------------------------------------------------------------- +/// 実行選択メッセージの表示 +/// +int YesNoCancelMB(LPCSTR fmt, ...) +{ + if( MsgBoxFlag ) return IDCANCEL; + MsgBoxFlag++; + va_list pp; + char bf[1024]; + + va_start(pp, fmt); + vsprintf( bf, fmt, pp ); + va_end(pp); + + int flag; + HWND hd = GetMBHandle(flag); + SetDisPaint(); + flag |= (MB_YESNOCANCEL | MB_ICONQUESTION); +// Application->NormalizeTopMosts(); + int r = ::MessageBox(hd, bf, "MMSSTV", flag); +// Application->RestoreTopMosts(); + ResDisPaint(); + MsgBoxFlag--; + return r; +} +///---------------------------------------------------------------- +/// 実行選択メッセージの表示 +/// +int OkCancelMB(LPCSTR fmt, ...) +{ + if( MsgBoxFlag ) return IDCANCEL; + MsgBoxFlag++; + va_list pp; + char bf[1024]; + + va_start(pp, fmt); + vsprintf( bf, fmt, pp ); + va_end(pp); + + int flag; + HWND hd = GetMBHandle(flag); + SetDisPaint(); + flag |= (MB_OKCANCEL | MB_ICONQUESTION); +// Application->NormalizeTopMosts(); + int r = ::MessageBox(hd, bf, "MMSSTV", flag); +// Application->RestoreTopMosts(); + ResDisPaint(); + MsgBoxFlag--; + return r; +} +///---------------------------------------------------------------- +/// +void ErrorFWrite(LPCSTR pName) +{ + DWORD dw = ::GetFileAttributes(pName); + if( (dw != 0xffffffff) && (dw & FILE_ATTRIBUTE_READONLY) ){ + ErrorMB(MsgEng ? "'%s' is read-only (fail to update)." : "'%s'が 読み取り専用 に設定されているため更新に失敗しました.", pName); + } + else { + ErrorMB(MsgEng ? "Could not update '%s'" : "'%s' の更新に失敗しました.", pName ); + } +} +///---------------------------------------------------------------- +/// +int RemoveL2(LPSTR t, LPSTR ss, LPCSTR pKey, int size) +{ + char c; + int k; + LPCSTR pp; + LPSTR s; + const char _tt1[]="[{(「<"; + const char _tt2[]="]})」>"; + + int len = strlen(pKey); + char ac = ';'; + for( k = 0, s = ss; *s; s++ ){ + if( k ){ // 漢字2バイト目 + k = 0; + ac = 0x1e; + } + else if( _mbsbtype((const unsigned char *)s, 0) == _MBC_LEAD ){ // 漢字1バイト目 + k = 1; + if( (len >= 2) && (strchr(" ,./;:*\t[{(「<]})」>", ac)!=NULL) && (!strnicmp(s, pKey, len)) ){ + pp = s + len; + if( (pp = strchr(_tt1, *pp))!=NULL ){ + c = _tt2[pp - _tt1]; + if( *(s+len+1) ){ + StrDlmCpy(t, s+len+1, c, size); + if( *t ){ + strcpy((ac == ' ')?(s-1):s, s+len+2+strlen(t)); + return TRUE; + } + } + } + } + } + else if( (strchr(" ,./;:*\t\x1e[{(「<]})」>", ac)!=NULL) && (!strnicmp(s, pKey, len)) ){ + pp = s + len; + if( (pp = strchr(_tt1, *pp))!=NULL ){ + c = _tt2[pp - _tt1]; + if( *(s+len+1) ){ + StrDlmCpy(t, s+len+1, c, size); + if( *t ){ + strcpy((ac == ' ')?(s-1):s, s+len+2+strlen(t)); + return TRUE; + } + } + } + ac = *s; + } + else { + ac = *s; + } + } + return FALSE; +} + +void AddL2(LPSTR t, LPCSTR pKey, LPCSTR s, UCHAR c1, UCHAR c2, int size) +{ + if( *s ){ + int len = strlen(t); + int lenkey = strlen(pKey); + int lenData = strlen(s); + if( (len + lenkey + lenData + 2) < size ){ + t += len; + if( len ) *t++ = ' '; + if( *pKey ){ + strcpy(t, pKey); + t += lenkey; + } + *t++ = c1; + strcpy(t, s); + t += lenData; + *t++ = c2; + *t = 0; + } + } +} +///---------------------------------------------------------------- +/// 数字が含まれるかどうか調べる +/// +int IsNumbs(LPCSTR p) +{ + for( ; *p; p++ ){ + if( isdigit(*p) ) return 1; + } + return 0; +} +///---------------------------------------------------------------- +/// 数字が含まれるかどうか調べる +/// +int IsAlphas(LPCSTR p) +{ + for( ; *p; p++ ){ + if( isalpha(*p) ) return 1; + } + return 0; +} +///---------------------------------------------------------------- +/// RSTかどうか調べる +/// +int IsRST(LPCSTR p) +{ + if( strlen(p) < 3 ) return 0; + if( (*p < '1') || (*p > '5') ) return 0; + p++; + if( (*p < '1') || (*p > '9') ) return 0; + p++; + if( (*p < '1') || (*p > '9') ) return 0; + return 1; +} +///---------------------------------------------------------------- +int IsCallChar(char c) +{ + if( !isalpha(c) && !isdigit(c) && (c != '/') ) return 0; + if( islower(c) ) return 0; + return 1; +} +///---------------------------------------------------------------- +/// コールサインかどうか調べる +/// +int IsCall(LPCSTR p) +{ + int l = strlen(p); + if( l > 16 ) return 0; + if( l < 3 ) return 0; + if( isdigit(*p) ){ // 先頭が数字 + if( l <= 3 ) return 0; // 3文字以下の時NG + if( isdigit(*(p+1)) ) return 0; // 2文字目が数字の時NG + } + if( isdigit(LastC(p)) ){ // 最後が数字 + if( l <= 4 ) return 0; // 4文字以下の時NG +// if( !strchr(p, '/')==NULL ) return0; // /が含まれていない時NG +// if( p[l-2] != '/' ) return 0; // 最後の1つ前が/以外の時NG + } + int i; + for( i = 0; i < l-1; i++, p++ ){ + if( isdigit(*p) ) return 1; // 数字が含まれていればOK + } + return 0; +} +/*#$% +====================================================== + JAとDXの区別をする +------------------------------------------------------ + s : コールサイン文字列のポインタ +------------------------------------------------------ + 1 : JA + 0 : DX (JD1 INCLUDEED) +------------------------------------------------------ +====================================================== +*/ +int IsJA(const char *s) +{ + if( (!memcmp(s, "8J1R", 4) && (strlen(s) == 5))||(strstr(s, "/JD1")!=NULL) ){ + return(0); + } + else if( strchr(s, '/') ){ + char bf[MLCALL+1]; + StrCopy(bf, s, MLCALL); + char *p; + char *t; + for( p = bf; *p; ){ + p = StrDlm(t, p, '/'); + if( *t ){ + if( (strlen(t) >= 2) && isdigit((unsigned char)LastC(t)) ){ + if( *t == 'J' ){ + t++; + if( *t == 'D' ) return(0); + if( (*t >= 'A')&&(*t <= 'S' ) ) return(1); + } + else if( *t == '7' ){ + t++; + if( (*t >= 'J')&&(*t <= 'N' ) ) return(1); + } + else if( *t == '8' ){ + t++; + if( (*t >= 'J')&&(*t <= 'N' ) ) return(1); + } + else { + return 0; + } + } + } + } + } + if( *s == 'J' ){ + s++; + if( *s == 'D' ) return(0); + if( (*s >= 'A')&&(*s <= 'S' ) ) return(1); + } + else if( *s == '7' ){ + s++; + if( (*s >= 'J')&&(*s <= 'N' ) ) return(1); + } + else if( *s == '8' ){ + s++; + if( (*s >= 'J')&&(*s <= 'N' ) ) return(1); + } + return(0); +} +/*#$% +====================================================== + コールサインをクリップする +------------------------------------------------------ + s : コールサイン文字列のポインタ +------------------------------------------------------ + クリップコールのポインタ +------------------------------------------------------ +====================================================== +*/ +LPCSTR ClipCall(LPCSTR s) +{ + static char bf[MLCALL+1]; + LPCSTR p1, p2; + + if( (p1=strchr(s, '/'))!=NULL ){ + if( (p2=strchr(p1+1, '/'))!=NULL ){ /* 3分割 */ + if( (int(strlen(p2+1)) < int((p2 - p1)+1)) || (!IsCall(p2+1)) ){ /* 最後より途中が長い */ + if( ((p2-p1) < (p1-s))||(!IsCall(p1+1)) ){ /* 途中より最初が長い */ + StrCopy(bf, s, MLCALL); + *strchr(bf, '/') = 0; + return(bf); + } + else { + strcpy(bf, p1+1); + *strchr(bf, '/') = 0; + return(bf); + } + } + else if( int(strlen(p2+1)) < int((p1 - s)+1) ){ /* 最後より最初が長い */ + StrCopy(bf, s, MLCALL); + *strchr(bf, '/') = 0; + return(bf); + } + else { + return(p2+1); + } + } + else { /* 2分割 */ + if( (int(strlen(p1+1)) < int((p1 - s)+1)) || (!IsCall(p1+1)) ){ + StrCopy(bf, s, MLCALL); + *strchr(bf, '/') = 0; + return(bf); + } + else { + return(p1+1); + } + } + } + else { + return(s); + } +} + +/*#$% +====================================================== + ポータブル表記を調べる +------------------------------------------------------ + p : コールサイン文字列のポインタ +------------------------------------------------------ + 数値のポインタ +------------------------------------------------------ +====================================================== +*/ +static LPSTR chkptb(LPSTR p) +{ + if( *p ){ + p = lastp(p); + if( isdigit(*p) && ((*(p-1))=='/') ){ + return(p); + } + } + return(NULL); +} + +/*#$% +====================================================== + ポータブル表記の入れ替え +------------------------------------------------------ + s : コールサイン文字列のポインタ +------------------------------------------------------ +------------------------------------------------------ + 元の文字列を破壊する +====================================================== +*/ +void chgptb(LPSTR s) +{ + LPSTR p, t; + + if( (p = chkptb(s))!=NULL ){ + t = p; + for( p--; p > s; p-- ){ + if( isdigit(*p) ){ + *p = *t; + t--; + *t = 0; + break; + } + } + } +} + +/*#$% +====================================================== + コールサインからカントリの元をクリップする +------------------------------------------------------ + s : コールサイン文字列のポインタ +------------------------------------------------------ + カントリのポインタ +------------------------------------------------------ +====================================================== +*/ +LPCSTR ClipCC(LPCSTR s) +{ + static char bf[MLCALL+1]; + LPSTR p, t; + + StrCopy(bf, s, MLCALL); + chgptb(bf); /* ポータブル表記の入れ替え */ + for( p = bf; *p; ){ + if( *p ){ + p = StrDlm(t, p, '/'); + if( (strlen(t) > 1) && (isdigit(*t) || isdigit(LastC(t))) ) return(t); + } + } + for( p = bf; *p; ){ + if( *p ){ + p = StrDlm(t, p, '/'); + if( (strlen(t) > 1) && (*t!='Q') && strcmp(t, "MM") ) return(t); + } + } + return ClipCall(s); +} + +///---------------------------------------------------------------- +/// 文字列変換 +/// +void Yen2CrLf(AnsiString &ws, AnsiString cs) +{ + ws = ""; + LPCSTR p; + int f; + int dlm = 0; + + p = cs.c_str(); + if( *p == 0x22 ){ + p++; + dlm++; + } + for( f = 0; *p; p++ ){ + if( f ){ + f = 0; + ws += *p; + } + else if( _mbsbtype((const unsigned char *)p, 0) == _MBC_LEAD ){ + f = 1; + ws += *p; + } + else if( *p == '\\' ){ + switch(*(p+1)){ + case 'r': + ws += "\r"; + p++; + break; + case 'n': + ws += "\n"; + p++; + break; + case 't': + ws += "\t"; + p++; + break; + case '\\': + ws += "\\"; + p++; + break; + default: + p++; + ws += *p; + break; + } + } + else if( !dlm || (*p!=0x22) || *(p+1) ){ + ws += *p; + } + } +} + +void CrLf2Yen(AnsiString &ws, AnsiString cs) +{ + ws = "\x22"; + LPCSTR p; + int f = 0; + + for( p = cs.c_str(); *p; p++ ){ + if( f ){ + f = 0; + ws += *p; + } + else if( _mbsbtype((const unsigned char *)p, 0) == _MBC_LEAD ){ + f = 1; + ws += *p; + } + else if( *p == 0x0d ){ + ws += "\\r"; + } + else if( *p == 0x0a ){ + ws += "\\n"; + } + else if( *p == TAB ){ + ws += "\\t"; + } + else if( *p == '\\' ){ + ws += "\\\\"; + } + else { + ws += *p; + } + } + ws += "\x22"; +} + + +//--------------------------------------------------------------------------- +// コンボBOXに文字列を設定する +void SetComboBox(TComboBox *pCombo, LPCSTR pList) +{ + pCombo->Clear(); + LPSTR s = strdup(pList); + LPSTR p = s; + LPSTR t; + while(*p){ + p = StrDlm(t, p); + clipsp(t); + t = SkipSpace(t); + if( *t ) pCombo->Items->Add(t); + } + free(s); +} + +//--------------------------------------------------------------------------- +// コンボBOXに文字列を設定する +void GetComboBox(AnsiString &as, TComboBox *pCombo) +{ + as = ""; + int i; + for( i = 0; i < pCombo->Items->Count; i++ ){ + if( i ) as += ','; + as += pCombo->Items->Strings[i]; + } +} + +//--------------------------------------------------------------------------- +void ExecPB(LPCSTR pName) +{ + char bf[512]; + + MultProc(); + strcpy(bf, "mspaint.exe"); + if( pName != NULL ){ + sprintf(lastp(bf)+1, " \x22%s\x22", pName); + } + if( ::WinExec(bf, SW_SHOWDEFAULT) <= 31 ){ + strcpy(bf, "PBRUSH.EXE"); + if( pName != NULL ){ + sprintf(lastp(bf)+1, " \x22%s\x22", pName); + } + ::WinExec(bf, SW_SHOWDEFAULT); + } +} +//--------------------------------------------------------------------------- +int FontStyle2Code(TFontStyles style) +{ + int code = 0; + + TFontStyles fa; + TFontStyles fb; + + fa << fsBold; + fb << fsBold; + fa *= style; + if( fa == fb ) code |= FSBOLD; + + fa >> fsBold; + fb >> fsBold; + fa << fsItalic; + fb << fsItalic; + fa *= style; + if( fa == fb ) code |= FSITALIC; + + fa >> fsItalic; + fb >> fsItalic; + fa << fsUnderline; + fb << fsUnderline; + fa *= style; + if( fa == fb ) code |= FSUNDERLINE; + + fa >> fsUnderline; + fb >> fsUnderline; + fa << fsStrikeOut; + fb << fsStrikeOut; + fa *= style; + if( fa == fb ) code |= FSSTRIKEOUT; + + return code; +} + +TFontStyles Code2FontStyle(int code) +{ + TFontStyles fs; + + if( code & FSBOLD ) fs << fsBold; + if( code & FSITALIC ) fs << fsItalic; + if( code & FSUNDERLINE ) fs << fsUnderline; + if( code & FSSTRIKEOUT ) fs << fsStrikeOut; + return fs; +} + +//--------------------------------------------------------------------------- +void TopWindow(TForm *tp) +{ + if( tp->FormStyle == fsStayOnTop ){ + ::SetWindowPos(tp->Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); + } +} +void NormalWindow(TForm *tp) +{ + if( tp->FormStyle == fsStayOnTop ){ + ::SetWindowPos(tp->Handle, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); + } +} +///--------------------------------------------------------- +/// テキスト文字列ストリーマー +int __fastcall CTextString::LoadText(LPSTR tp, int len) +{ + char c; + int n = 0; + if( !(*rp) ) return FALSE; + while(*rp){ + c = *rp++; + if( c == LF ){ + *tp = 0; + return TRUE; + } + else if( (c != CR)&&(c != 0x1a) ){ + if( n < (len-1) ){ + *tp++ = c; + n++; + } + } + } + *tp = 0; + return TRUE; +} +///---------------------------------------------------------------- +/// CAlignクラス +void CAlign::InitControl(TControl *p, TControl *pB, TFont *pF /*= NULL*/) +{ + tp = p; + OTop = p->Top; + OLeft = p->Left; + OWidth = p->Width; + OHeight = p->Height; + if( pF != NULL ){ + fp = pF; + OFontHeight = pF->Height; + } + + BTop = pB->Top; + BLeft = pB->Left; + BWidth = pB->ClientWidth; + BHeight = pB->ClientHeight; +} + +void CAlign::InitControl(TControl *p, RECT *rp, TFont *pF /*= NULL*/) +{ + tp = p; + OTop = p->Top; + OLeft = p->Left; + OWidth = p->Width; + OHeight = p->Height; + if( pF != NULL ){ + fp = pF; + OFontHeight = pF->Height; + } + + BTop = rp->top; + BLeft = rp->left; + BWidth = rp->right - rp->left + 1; + BHeight = rp->bottom - rp->top + 1; +} + +void CAlign::NewAlign(TControl *pB) +{ + double Sx = double(pB->ClientWidth)/double(BWidth); + double Sy = double(pB->ClientHeight)/double(BHeight); + tp->SetBounds(int(OLeft * Sx), int(OTop * Sy), int(OWidth * Sx), int(OHeight * Sy)); + if( fp != NULL ){ + if( Sx > Sy ) Sx = Sy; + fp->Height = int(OFontHeight * Sx) - sys.m_FontAdjSize; + m_FontAdj = Sx; + } + if( tp->ClassNameIs("TComboBox") ){ + ((TComboBox *)tp)->SelLength = 0; + } + else if( tp->ClassNameIs("TLabel") ){ + TLabel *lp = ((TLabel *)tp); + if( lp->Alignment == taRightJustify ){ + lp->AutoSize = FALSE; + lp->AutoSize = TRUE; + } + } +} + +void CAlign::NewAlign(TControl *pB, double hx) +{ + double Sx = double(pB->ClientWidth)/double(BWidth); + double Sy = double(pB->ClientHeight)/double(BHeight); + Sy *= hx; + tp->SetBounds(int(OLeft * Sx), int(OTop * Sy), int(OWidth * Sx), int(OHeight * Sy)); + if( fp != NULL ){ + if( Sx > Sy ) Sx = Sy; + fp->Height = int(OFontHeight * Sx) - sys.m_FontAdjSize; + m_FontAdj = Sx; + } + if( tp->ClassNameIs("TComboBox") ){ + ((TComboBox *)tp)->SelLength = 0; + } +} + +void CAlign::NewFont(AnsiString &FontName, BYTE Charset, TFontStyles fs) +{ + if( fp != NULL ){ + fp->Name = FontName; + fp->Charset = Charset; + fp->Style = fs; + if( tp->ClassNameIs("TComboBox") ){ + ((TComboBox *)tp)->SelLength = 0; + } + } +} + +void CAlign::NewFixAlign(TControl *pB, int XR) +{ + double Sx = double(pB->ClientWidth - XR) / double(BWidth - XR); + + tp->SetBounds(XR + (OLeft - XR) * Sx, OTop, OWidth * Sx, OHeight); + if( fp != NULL ){ + fp->Height = int(OFontHeight * (Sx < 1.0 ? Sx : 1.0)) - sys.m_FontAdjSize; + m_FontAdj = Sx; + } + if( tp->ClassNameIs("TComboBox") ){ + ((TComboBox *)tp)->SelLength = 0; + } +} + +void CAlign::Resume(void) +{ + if( tp != NULL ){ + tp->Top = OTop; + tp->Left = OLeft; + tp->Width = OWidth; + tp->Height = OHeight; + if( fp != NULL ){ + fp->Height = OFontHeight; + } + } +} +///---------------------------------------------------------------- +/// CAlignListクラス +CAlignList::CAlignList(void) +{ + Max = 0; + Cnt = 0; + AlignList = NULL; +} + +CAlignList::~CAlignList(){ + if( AlignList != NULL ){ + for( int i = 0; i < Cnt; i++ ){ + delete AlignList[i]; + } + delete AlignList; + AlignList = NULL; + } +} + +void CAlignList::Alloc(void) +{ + if( Cnt >= Max ){ + Max = Max ? Max * 2 : 16; + CAlign **np = (CAlign **)new BYTE[sizeof(CAlign*) * Max]; + if( AlignList != NULL ){ + for( int i = 0; i < Cnt; i++ ){ + np[i] = AlignList[i]; + } + delete AlignList; + } + AlignList = np; + } + AlignList[Cnt] = new CAlign; +} +void CAlignList::EntryControl(TControl *tp, TControl *pB, TFont *pF /*= NULL*/) +{ + Alloc(); + AlignList[Cnt]->InitControl(tp, pB, pF); + Cnt++; +} + +void CAlignList::EntryControl(TControl *tp, RECT *rp, TFont *pF /*= NULL*/){ + Alloc(); + AlignList[Cnt]->InitControl(tp, rp, pF); + Cnt++; +} + +void CAlignList::EntryControl(TControl *tp, int XW, int YW, TFont *pF /*= NULL*/){ + RECT rc; + rc.left = rc.top = 0; + rc.right = XW; rc.bottom = YW; + Alloc(); + AlignList[Cnt]->InitControl(tp, &rc, pF); + Cnt++; +} + +void CAlignList::NewAlign(TControl *pB) +{ + if( AlignList == NULL ) return; + for( int i = 0; i < Cnt; i++ ){ + AlignList[i]->NewAlign(pB); + } +} + +double CAlignList::GetFontAdj(TControl *pB) +{ + for( int i = 0; i < Cnt; i++ ){ + if( AlignList[i]->GetControl() == pB ){ + return AlignList[i]->GetFontAdj(); + } + } + return 1.0; +} + +void CAlignList::NewAlign(TControl *pB, TControl *pS, double hx) +{ + for( int i = 0; i < Cnt; i++ ){ + if( AlignList[i]->GetControl() == pS ){ + AlignList[i]->NewAlign(pB, hx); + break; + } + } +} +void CAlignList::NewFont(AnsiString &FontName, BYTE Charset, TFontStyles fs) +{ + if( AlignList == NULL ) return; + for( int i = 0; i < Cnt; i++ ){ + AlignList[i]->NewFont(FontName, Charset, fs); + } +} + +void CAlignList::NewFixAlign(TControl *pB, int XR) +{ + if( AlignList == NULL ) return; + for( int i = 0; i < Cnt; i++ ){ + AlignList[i]->NewFixAlign(pB, XR); + } +} + +void CAlignList::Resume(TControl *pB) +{ + if( AlignList == NULL ) return; + for( int i = 0; i < Cnt; i++ ){ + if( pB == NULL ){ + AlignList[i]->Resume(); + } + else if( pB == AlignList[i]->GetControl() ){ + AlignList[i]->Resume(); + break; + } + } +} + +///---------------------------------------------------------------- +/// CAlignGridクラス +void CAlignGrid::InitGrid(TStringGrid *p) +{ + BWidth = p->Width; + BHeight = p->Height; + BRowHeight = p->DefaultRowHeight; + Max = p->ColCount; + bp = new int[Max]; + for( int i = 0; i < Max; i++ ){ + bp[i] = p->ColWidths[i]; + } +} + +void CAlignGrid::NewAlign(TStringGrid *p) +{ + double Sx = double(p->Width)/double(BWidth); + double Sy = double(p->Height)/double(BHeight); + p->DefaultRowHeight = int(BRowHeight * Sy); + for( int i = 0; (i < Max) && (i < p->ColCount); i++ ){ + p->ColWidths[i] = int(bp[i] * Sx); + } +} + + +///------------------------------------------------------ +/// +///CWebRef クラス +/// +void MakeCommand(LPSTR t, LPCSTR s, LPCSTR p) +{ + for( ;*s; s++ ){ + if( *s == '%' ){ + s++; + if( *s == '%' ){ + *t++ = '%'; + } + else if( (p != NULL) && (*s == '1') ){ + strcpy(t, p); + t += strlen(t); + p = NULL; + } + } + else { + *t++ = *s; + } + } + *t = 0; + if( p != NULL ){ + *t++ = ' '; + strcpy(t, p); + } +} + +CWebRef::CWebRef() +{ + HTML = ""; + + HKEY hkey=NULL; /* オープン キーのハンドル */ + + char bf[512], name[512]; + ULONG namelen, len; + if( !RegOpenKeyEx(HKEY_CLASSES_ROOT, "http", 0, KEY_READ, &hkey) ){ + if( !RegOpenKeyEx(hkey, "shell", 0, KEY_READ, &hkey) ){ + if( !RegOpenKeyEx(hkey, "open", 0, KEY_READ, &hkey) ){ + if( !RegOpenKeyEx(hkey, "command", 0, KEY_READ, &hkey) ){ + namelen = sizeof(name); + len = sizeof(bf); + if( !::RegEnumValue(hkey, 0, name, &namelen, NULL, + NULL, (LPBYTE)bf, &len) ){ + HTML = bf; + } + } + } + } + } + ::RegCloseKey(hkey); +} + +void CWebRef::ShowHTML(LPCSTR url) +{ + char cmd[1024]; + MakeCommand(cmd, HTML.c_str(), url); + ::WinExec(cmd, SW_SHOWDEFAULT); +} + + +///------------------------------------------------------ +/// +///CWaitCursor クラス +/// +CWaitCursor::CWaitCursor() +{ + sv = Screen->Cursor; + Screen->Cursor = crHourGlass; +} + +CWaitCursor::~CWaitCursor() +{ + Screen->Cursor = sv; +} + +void CWaitCursor::Delete(void) +{ + Screen->Cursor = sv; +} + +void CWaitCursor::Wait(void) +{ + Screen->Cursor = crHourGlass; +} + +///------------------------------------------------------- +/// CRecentMenuクラス + +CRecentMenu::CRecentMenu() +{ + InsPos = 0; + Max = RECMENUMAX; + int i; + for( i = 0; i < RECMENUMAX; i++ ){ + Caption[i] = ""; + Items[i] = NULL; + } + Items[i] = NULL; +} +void CRecentMenu::Init(int pos, TMenuItem *pmenu, int max) +{ + InsPos = pos; + pMenu = pmenu; + Max = max; +} +void CRecentMenu::Init(TMenuItem *pi, TMenuItem *pmenu, int max) +{ + Init(pmenu->IndexOf(pi), pmenu, max); +} +int CRecentMenu::GetCount(void) +{ + int i, n; + for( i = n = 0; i < RECMENUMAX; i++, n++ ){ + if( Caption[i].IsEmpty() ) break; + } + return n; +} +LPCSTR CRecentMenu::GetItemText(int n) +{ + if( (n >= 0) && (n < RECMENUMAX) ){ + return Caption[n].c_str(); + } + else { + return NULL; + } +} +void CRecentMenu::SetItemText(int n, LPCSTR p) +{ + if( (n >= 0) && (n < RECMENUMAX) ){ + Caption[n] = p; + } +} +int CRecentMenu::IsAdd(LPCSTR pNew) +{ + return strcmp(Caption[0].c_str(), pNew); +} +void CRecentMenu::Add(LPCSTR pNew) +{ + if( !IsAdd(pNew) ) return; + int i; + for( i = 1; i < RECMENUMAX; i++ ){ + if( !strcmp(pNew, Caption[i].c_str()) ){ + for( ; i < (RECMENUMAX - 1); i++ ){ + Caption[i] = Caption[i+1]; + } + Caption[i] = ""; + break; + } + } + for( i = RECMENUMAX - 1; i > 0; i-- ){ + Caption[i] = Caption[i-1]; + } + Caption[0] = pNew; +} +void CRecentMenu::Delete(LPCSTR pName) +{ + int i; + for( i = 0; i < RECMENUMAX; i++ ){ + if( !strcmp(pName, Caption[i].c_str()) ){ + for( ; i < (RECMENUMAX - 1); i++ ){ + Caption[i] = Caption[i+1]; + } + Caption[i] = ""; + break; + } + } +} +void CRecentMenu::ExtFilter(LPCSTR pExt) +{ + int i, j; + + for( i = 0; i < RECMENUMAX; i++ ){ + if( (!Caption[i].IsEmpty()) && strcmpi(GetEXT(Caption[i].c_str()), pExt) ){ + for( j = i; j < (RECMENUMAX - 1); j++ ){ + Caption[j] = Caption[j+1]; + } + Caption[j] = ""; + i--; + } + } +} +void CRecentMenu::Clear(void) +{ + Delete(); + for( int i = 0; i < RECMENUMAX; i++ ){ + Caption[i] = ""; + } +} +void CRecentMenu::Insert(TObject *op, Classes::TNotifyEvent pEvent) +{ + int n = GetCount(); + int i; + int pos = InsPos; + if( n > Max ) n = Max; + char bf[256]; + for( i = 0; i < n; i++, pos++ ){ + Items[i] = new TMenuItem((TComponent *)op); + sprintf(bf, "&%d %s", (i + 1) % 10, Caption[i].c_str()); + Items[i]->Caption = bf; + Items[i]->OnClick = pEvent; + pMenu->Insert(pos, Items[i]); + } + if( n ){ + Items[i] = new TMenuItem((TComponent *)op); + Items[i]->Caption = "-"; + Items[i]->OnClick = NULL; + pMenu->Insert(pos, Items[n]); + } +} +void CRecentMenu::Delete(void) +{ + for( int i = 0; i < RECMENUMAX+1; i++ ){ + if( Items[i] != NULL ){ + pMenu->Delete(InsPos); + Items[i] = NULL; + } + } +} +int CRecentMenu::FindItem(TMenuItem *mp) +{ + for( int i = 0; i < RECMENUMAX; i++ ){ + if( Items[i] == mp ){ + return i; + } + } + return -1; +} +LPCSTR CRecentMenu::FindItemText(TMenuItem *mp) +{ + return GetItemText(FindItem(mp)); +} + +///------------------------------------------------------- +/// CBitmapHistクラス +int CBitmapHist::Open(void) +{ + Close(); + char bf[256]; + sprintf(bf, "%s"HISTNAME, HistDir); + FILE *fp = fopen(bf, "rb"); + if( fp == NULL ){ + if( (fp = fopen(bf, "wb"))!=NULL ){ + m_Head.m_Max = sys.m_HistMax; + fwrite(&m_Head, 1, sizeof(m_Head), fp); + fwrite(&m_File, 1, sizeof(m_File), fp); + fclose(fp); + m_FileName = bf; + return TRUE; + } + else { + ErrorFWrite(bf); + return FALSE; + } + } + else { + fread(&m_Head, 1, sizeof(m_Head), fp); + fread(&m_File, 1, sizeof(m_File), fp); + fclose(fp); + m_FileName = bf; + ChangeMax(sys.m_HistMax); + return TRUE; + } +} +void CBitmapHist::Close(void) +{ + if( !m_FileName.IsEmpty() ){ + if( !OverWrite() ){ + ErrorFWrite(m_FileName.c_str()); + } + m_FileName = ""; + } +} + +int CBitmapHist::OverWrite(void) +{ + int r = FALSE; + if( !m_FileName.IsEmpty() ){ + FILE *fp; + if( (fp = fopen(m_FileName.c_str(), "wb"))!=NULL ){ + fwrite(&m_Head, 1, sizeof(m_Head), fp); + fwrite(&m_File, 1, sizeof(m_File), fp); + fclose(fp); + r = TRUE; + } + } + return r; +} + +void CBitmapHist::ChangeMax(int max) +{ + if( m_Head.m_Max == max ) return; + + CWaitCursor wait; + int i, s, t; + HEADFH sFile[HISTMAX]; + memset(sFile, 0, sizeof(sFile)); + char sname[256]; + char tname[256]; + s = m_Head.m_wPnt - 1; + t = max - 1; + for( i = 0; i < m_Head.m_Cnt; i++, s--, t-- ){ + if( s < 0 ) s += m_Head.m_Max; + if( t < 0 ) t += max; + sprintf(sname, m_UseJPEG ? "%sHist%d.jpg" : "%sHist%d.bmp", HistDir, s + 1); + sprintf(tname, m_UseJPEG ? "%sHist%d.$pg" : "%sHist%d.$mp", HistDir, t + 1); + if( i >= max ){ + unlink(sname); + } + else { + rename(sname, tname); + sFile[t] = m_File[s]; + } + } + t = max - 1; + for( i = 0; i < max; i++, t-- ){ + if( t < 0 ) t += max; + sprintf(sname, m_UseJPEG ? "%sHist%d.$pg" : "%sHist%d.$mp", HistDir, t + 1); + sprintf(tname, m_UseJPEG ? "%sHist%d.jpg" : "%sHist%d.bmp", HistDir, t + 1); + rename(sname, tname); + } + memcpy(m_File, sFile, sizeof(m_File)); + if( m_Head.m_Cnt >= max ) m_Head.m_Cnt = max; + m_Head.m_wPnt = 0; + m_Head.m_Max = max; +} + +int CBitmapHist::Read(Graphics::TBitmap *pBitmap, int slot) +{ + char bf[256]; + sprintf(bf, m_UseJPEG ? "%sHist%d.jpg" : "%sHist%d.bmp", HistDir, slot + 1); + + int r = FALSE; + FILE *fp; + if( (fp = fopen(bf, "rb"))!=NULL ){ + fclose(fp); + m_CurRead = slot; + if( m_UseJPEG ){ + LoadJPEG(pBitmap, bf); + } + else { + LoadBitmap(pBitmap, bf); + } + r = TRUE; + } + else { + FillBitmap(pBitmap, clWhite); + } + return r; +} + +void CBitmapHist::Write(Graphics::TBitmap *pBitmap, int slot) +{ + char bf[256]; + sprintf(bf, m_UseJPEG ? "%sHist%d.jpg" : "%sHist%d.bmp", HistDir, slot + 1); + + try { + if( m_UseJPEG ){ + SaveJPEG(pBitmap, bf); + } + else { + pBitmap->SaveToFile(bf); + } + m_File[slot].m_Flag |= 1; + } + catch(...){ + ErrorFWrite(bf); + } +} + +void CBitmapHist::Add(Graphics::TBitmap *pBitmap, SYSTEMTIME *pTime, int mode) +{ + m_CurRead = m_Head.m_wPnt; + memcpy(&m_File[m_Head.m_wPnt].m_UTC, pTime, sizeof(SYSTEMTIME)); + mode++; + m_File[m_Head.m_wPnt].m_Flag = mode << 16; + Write(pBitmap, m_Head.m_wPnt); + m_Head.m_wPnt++; + if( m_Head.m_wPnt >= m_Head.m_Max ){ + m_Head.m_wPnt = 0; + } + if( m_Head.m_Cnt < m_Head.m_Max ){ + m_Head.m_Cnt++; + } + m_CurAdd = 1; + OverWrite(); +} + +void CBitmapHist::Update(Graphics::TBitmap *pBitmap) +{ + int n = m_Head.m_wPnt - 1; + if( n < 0 ) n += m_Head.m_Max; + Write(pBitmap, n); +} + +//--------------------------------------------------------------------------- +void CBitmapHist::Delete(int n) +{ + if( !m_Head.m_Cnt ) return; + + CWaitCursor wait; + char tname[256]; + char sname[256]; + int max = m_Head.m_Cnt - n - 1; // Copy count + int i, s, t; + t = m_Head.m_wPnt - n - 1; + if( t < 0 ) t += m_Head.m_Max; + if( m_Head.m_Cnt == 1 ){ + sprintf(tname, "%sHist%d.bmp", HistDir, t + 1); + unlink(tname); + m_Head.m_Cnt--; + memset(&m_File[t], 0, sizeof(HEADFH)); + return; + } + for( i = 0; i < max; i++ ){ + s = t - 1; + if( s < 0 ) s += m_Head.m_Max; + sprintf(sname, m_UseJPEG ? "%sHist%d.jpg" : "%sHist%d.bmp", HistDir, s + 1); + sprintf(tname, m_UseJPEG ? "%sHist%d.jpg" : "%sHist%d.bmp", HistDir, t + 1); + if( !i ){ + unlink(tname); + } + MoveFile(sname, tname); + m_File[t] = m_File[s]; + t--; + if( t < 0 ) t = m_Head.m_Max - 1; + } + memset(&m_File[t], 0, sizeof(HEADFH)); + m_Head.m_Cnt--; +} + +//--------------------------------------------------------------------------- +void CBitmapHist::DeleteAll(void) +{ + if( !m_Head.m_Cnt ) return; + + CWaitCursor wait; + char tname[256]; + char sname[256]; + for( int i = 0; i < m_Head.m_Max; i++ ){ + sprintf(sname, "%sHist%d.bmp", HistDir, i + 1); + sprintf(tname, "%sHist%d.jpg", HistDir, i + 1); + unlink(sname); + unlink(tname); + } + memset(&m_File, 0, sizeof(m_File)); + m_Head.m_Cnt = 0; + m_Head.m_wPnt = 0; + m_CurAdd = 0; + m_CurRead = 0; +} + +//--------------------------------------------------------------------------- +void CBitmapHist::MoveDir(LPCSTR pNewDir) +{ + if( !strcmp(pNewDir, HistDir) ) return; + + CWaitCursor wait; + char tname[256]; + char sname[256]; + sprintf(tname, "%s"HISTNAME, pNewDir); + FILE *fp = fopen(tname, "wb"); + if( fp == NULL ){ + strcpy(sname, pNewDir); + if( *lastp(sname) == '\\' ) *lastp(sname) = 0; + mkdir(sname); + fp = fopen(tname, "wb"); + } + if( fp == NULL ){ + ErrorMB( MsgEng ? "'%s' does not exsit" : "フォルダ '%s' が存在しません", pNewDir ); + return; + } + else { + fclose(fp); + } + Close(); + sprintf(sname, "%s"HISTNAME, HistDir); + if( CopyFile(sname, tname, FALSE) == FALSE ){ + if( YesNoMB( MsgEng ? "Fail to copy the files. Memory to change to the folder?" : "ファイルのコピーに失敗しました. このフォルダへの変更を記憶しますか?" ) == IDYES ){ + strcpy(HistDir, pNewDir); + } + Open(); + return; + } + unlink(sname); + int i; + for( i = 0; i < m_Head.m_Max; i++ ){ + sprintf(sname, m_UseJPEG ? "%sHist%d.jpg" : "%sHist%d.bmp", HistDir, i + 1); + sprintf(tname, m_UseJPEG ? "%sHist%d.jpg" : "%sHist%d.bmp", pNewDir, i + 1); + CopyFile(sname, tname, FALSE); + unlink(sname); + } + if( *lastp(HistDir) == '\\' ) *lastp(HistDir) = 0; + _rmdir(HistDir); + strcpy(HistDir, pNewDir); + Open(); +} + +//--------------------------------------------------------------------------- +void CBitmapHist::ChangeFormat(int sw) +{ + if( m_UseJPEG == sw ) return; + if( !m_Head.m_Cnt ){ + m_UseJPEG = sw; + return; + } + CWaitCursor wait; + Graphics::TBitmap *pBitmap = new Graphics::TBitmap(); + AdjustBitmapFormat(pBitmap); + + FILE *fp; + char tname[256]; + char sname[256]; + int i; + for( i = 0; i < m_Head.m_Max; i++ ){ + sprintf(sname, sw ? "%sHist%d.bmp" : "%sHist%d.jpg", HistDir, i + 1); + sprintf(tname, sw ? "%sHist%d.jpg" : "%sHist%d.bmp", HistDir, i + 1); + if( (fp = fopen(sname, "rb")) != NULL ){ + fclose(fp); + if( sw ){ + LoadBitmap(pBitmap, sname); + SaveJPEG(pBitmap, tname); + } + else { + LoadJPEG(pBitmap, sname); + SaveBitmap(pBitmap, tname); + } + unlink(sname); + } + } + delete pBitmap; + m_UseJPEG = sw; +} +///------------------------------------------------------- +/// CExecPBクラス +//--------------------------------------------------------------------------- +HWND __fastcall IsPB(void) +{ + return FindWindow("MSPaintApp", NULL); +} +//--------------------------------------------------------------------------- +void __fastcall QuitPB(BOOL fWait) +{ + HWND hWndA = NULL; + while(1){ + HWND hWnd = IsPB(); + if( (hWnd != NULL) && (hWnd != hWndA) ){ + hWndA = hWnd; + ::PostMessage(hWnd, WM_QUIT, 0, 0); + if( fWait ){ + for( int i = 0; i < 30; i++ ){ + ::Sleep(100); + MultProc(); + if( IsPB() != hWnd ) break; + } + } + else { + break; + } + } + else { + break; + } + } +} + +//--------------------------------------------------------------------------- +__fastcall CExecPB::CExecPB() +{ + m_Flag = FALSE; + m_hWndMsg = NULL; + m_dwCount = 0; +} + +//--------------------------------------------------------------------------- +__fastcall CExecPB::~CExecPB() +{ + Cancel(); +} + +//--------------------------------------------------------------------------- +BOOL __fastcall CExecPB::Timer(void) +{ + if( !m_Flag ) return TRUE; + + if( (m_dwCount & 1) && !IsPB() ){ + m_Flag = FALSE; + if( m_hWndMsg && m_uMsg ){ + ::PostMessage(m_hWndMsg, m_uMsg, 0, m_dwID); + } + return TRUE; + } + m_dwCount++; + return FALSE; +} +//--------------------------------------------------------------------------- +BOOL __fastcall CExecPB::Exec(LPCSTR pName, HWND hWnd, UINT uMsg, DWORD dwID) +{ + CWaitCursor w; + + m_Flag = FALSE; + QuitPB(TRUE); + + m_Name = pName; + WIN32_FIND_DATA FileData; + HANDLE hFind = ::FindFirstFile(pName, &FileData); + if( hFind ) ::FindClose(hFind); + m_nFileSizeLow = FileData.nFileSizeLow; + m_ftLastWriteTime = FileData.ftLastWriteTime; + + m_hWndMsg = hWnd; + m_uMsg = uMsg; + m_dwID = dwID; + + ExecPB(pName); + for( int i = 0; i < 100; i++ ){ + ::Sleep(100); + if( IsPB() ){ + m_Flag = TRUE; + return TRUE; + } + } + return FALSE; +} +//--------------------------------------------------------------------------- +BOOL __fastcall CExecPB::Exec(Graphics::TBitmap *pBitmap, HWND hWnd, UINT uMsg, DWORD dwID) +{ + char name[256]; + sprintf(name, "%sTemp$.bmp", BgnDir); + try { + pBitmap->SaveToFile(name); + return Exec(name, hWnd, uMsg, dwID); + } + catch(...){ + return FALSE; + } +} +//--------------------------------------------------------------------------- +BOOL __fastcall CExecPB::IsChanged(void) +{ + WIN32_FIND_DATA FileData; + HANDLE hFind = ::FindFirstFile(m_Name.c_str(), &FileData); + if( !hFind ) return FALSE; + ::FindClose(hFind); + + if( FileData.nFileSizeLow != m_nFileSizeLow ) return TRUE; + return memcmp(&FileData.ftLastWriteTime, &m_ftLastWriteTime, sizeof(FILETIME)); +} +//--------------------------------------------------------------------------- +BOOL __fastcall CExecPB::LoadBitmap(Graphics::TBitmap *pBitmap, BOOL sw) +{ + BOOL r = FALSE; + + if( IsChanged() ){ +#if 1 + TPicRectDlg *pBox = new TPicRectDlg(Mmsstv); + try + { + pBox->pBitmap->LoadFromFile(m_Name); + if( sw ){ + ::CopyBitmap(pBitmap, pBox->pBitmap); + r = TRUE; + } + else if( pBox->Copy(pBitmap) == TRUE ){ + r = TRUE; + } + } + catch (...) + { + } + delete pBox; +#else + Graphics::TBitmap *pBmp = new Graphics::TBitmap; + try { + pBmp->LoadFromFile(m_Name); + if( sw ){ + ::CopyBitmap(pBitmap, pBmp); + } + else { + ::StretchCopyBitmapHW(pBitmap, pBmp); + } + r = TRUE; + } + catch(...){ + } + delete pBmp; +#endif + } + ::DeleteFile(m_Name.c_str()); + return r; +} +//--------------------------------------------------------------------------- +void __fastcall CExecPB::Cancel(void) +{ + if( m_Flag ){ + m_Flag = FALSE; + QuitPB(FALSE); + } +} +//--------------------------------------------------------------------------- +Graphics::TBitmap* __fastcall CreateBitmap(int xw, int yw, int fmt) +{ + Graphics::TBitmap *pBitmap = new Graphics::TBitmap; + if( fmt == -1 ){ + AdjustBitmapFormat(pBitmap); + } + else { + pBitmap->PixelFormat = TPixelFormat(fmt); + } + pBitmap->Width = xw; + pBitmap->Height = yw; + return pBitmap; +} +//--------------------------------------------------------------------------- +void __fastcall StretchCopyBitmap(Graphics::TBitmap *pTer, Graphics::TBitmap *pSrc) +{ + if( (pTer->Width != pSrc->Width)||(pTer->Height != pSrc->Height) ){ + Graphics::TBitmap *pbmp = pTer; + if( pTer->PixelFormat != pf24bit ){ + pbmp = CreateBitmap(pTer->Width, pTer->Height, pf24bit); + } + pbmp->Palette = NULL; + StretchCopy(pbmp, NULL, pSrc, NULL); + if( pbmp != pTer ){ + pTer->Palette = NULL; + pTer->Canvas->Draw(0, 0, pbmp); + delete pbmp; + } + } + else { + pTer->Palette = NULL; + pTer->Canvas->Draw(0, 0, pSrc); + } +} +//--------------------------------------------------------------------------- +//アスペクト比を保持する +void __fastcall KeepAspect(int &sx, int &sy, int bx, int by) +{ + double ass = double(sx) / double(sy); + double asb = double(bx) / double(by); + if( asb < ass ){ // ソースの方が横長 + sx = (double(sy) * asb) + 0.5; + } + else { + sy = (double(sx) / asb) + 0.5; + } +} +//--------------------------------------------------------------------------- +//アスペクト比を保持する +void __fastcall KeepAspectDraw(TCanvas *tp, int sx, int sy, Graphics::TBitmap *pBitmap) +{ + KeepAspect(sx, sy, pBitmap->Width, pBitmap->Height); + TRect tc; + tc.Left = 0; tc.Top = 0; + tc.Right = sx; tc.Bottom = sy; + int Sop = ::SetStretchBltMode(tp->Handle, HALFTONE); + tp->StretchDraw(tc, pBitmap); + ::SetStretchBltMode(tp->Handle, Sop); +} +//--------------------------------------------------------------------------- +//アスペクト比を保持して最大範囲を伸縮コピーする +void __fastcall StretchCopyBitmapHW(Graphics::TBitmap *pTer, Graphics::TBitmap *pSrc) +{ + if( (pTer->Width != pSrc->Width)||(pTer->Height != pSrc->Height) ){ + Graphics::TBitmap *pbmp = pTer; + if( pTer->PixelFormat != pf24bit ){ + pbmp = CreateBitmap(pTer->Width, pTer->Height, pf24bit); + } + TRect sc; + sc.Left = 0; sc.Top = 0; + double ass = double(pSrc->Width) / double(pSrc->Height); + double ast = double(pTer->Width) / double(pTer->Height); + if( ast < ass ){ // ソースの方が横長 + sc.Bottom = pSrc->Height; + sc.Right = double(pSrc->Height) * ast; + } + else { + sc.Right = pSrc->Width; + sc.Bottom = double(pSrc->Width) / ast; + } + int w; + if( sc.Right < pSrc->Width ){ + w = (pSrc->Width - sc.Right) / 2; + sc.Left += w; + sc.Right += w; + } + if( sc.Bottom < pSrc->Height ){ + w = (pSrc->Height - sc.Bottom) / 2; + sc.Top += w; + sc.Bottom += w; + } + if( sc.Right >= pSrc->Width + 1 ) sc.Right = pSrc->Width; + if( sc.Bottom >= pSrc->Height + 1 ) sc.Bottom = pSrc->Height; + pbmp->Palette = NULL; + StretchCopy(pbmp, NULL, pSrc, &sc); + if( pbmp != pTer ){ + pTer->Palette = NULL; + pTer->Canvas->Draw(0, 0, pbmp); + delete pbmp; + } + } + else { + pTer->Palette = NULL; + pTer->Canvas->Draw(0, 0, pSrc); + } +} +//--------------------------------------------------------------------------- +Graphics::TBitmap *__fastcall DupeBitmap(Graphics::TBitmap *pSrc, int fmt) +{ + Graphics::TBitmap *pBitmap = new Graphics::TBitmap; + if( fmt == -1 ){ + AdjustBitmapFormat(pBitmap); + } + else { + pBitmap->PixelFormat = TPixelFormat(fmt); + } + pBitmap->Height = pSrc->Height; + pBitmap->Width = pSrc->Width; + pBitmap->Palette = NULL; + pBitmap->Canvas->Draw(0, 0, pSrc); + return pBitmap; +} +//--------------------------------------------------------------------------- +Graphics::TBitmap *__fastcall RemakeBitmap(Graphics::TBitmap *pBitmap, int fmt) +{ + int w, h; + if( pBitmap != NULL ){ + w = pBitmap->Width; + h = pBitmap->Height; + delete pBitmap; + } + else { + w = 320; + h = 256; + } + pBitmap = CreateBitmap(w, h, fmt); + return pBitmap; +} +//--------------------------------------------------------------------------- +void __fastcall CopyBitmap(Graphics::TBitmap *pTer, Graphics::TBitmap *pSrc) +{ + if( (pTer->Width != pSrc->Width)||(pTer->Height != pSrc->Height) ){ + pTer->Width = pSrc->Width; + pTer->Height = pSrc->Height; + } + pTer->Palette = NULL; + pTer->Canvas->Draw(0, 0, pSrc); +} +//--------------------------------------------------------------------------- +// APIの伸縮コピー +void __fastcall StretchCopy(Graphics::TBitmap *pTer, Graphics::TBitmap *pSrc, int mode) +{ + TRect rc; + rc.Left = 0; rc.Top = 0; + rc.Right = pTer->Width; + rc.Bottom = pTer->Height; + int Sop = ::SetStretchBltMode(pTer->Canvas->Handle, mode); //ja7ude 0521 + pTer->Palette = NULL; + pTer->Canvas->StretchDraw(rc, pSrc); + ::SetStretchBltMode(pTer->Canvas->Handle, Sop); //ja7ude 0521 +} +//--------------------------------------------------------------------------- +// 高度な伸縮コピー +void __fastcall StretchCopy(Graphics::TBitmap *pBitmap, TRect *tc, Graphics::TBitmap *pbmp, TRect *rp) +{ + if( pBitmap == NULL ) return; + CWaitCursor wait; + + Graphics::TBitmap *psrc; + + if( pbmp->PixelFormat != pf24bit ){ + psrc = DupeBitmap(pbmp, pf24bit); + } + else { + psrc = pbmp; + } +// DecBitmap(pBitmap, tc, psrc, rp); + int top = 0; + int left = 0; + int w = pBitmap->Width; + int h = pBitmap->Height; + pBitmap->PixelFormat = pf24bit; + pBitmap->Width = w; + pBitmap->Height = h; + if( tc != NULL ){ + w = tc->Right - tc->Left; + h = tc->Bottom - tc->Top; + left = tc->Left; + top = tc->Top; + } + + double zy; + double zx; + int sw, sh; + int xss, yss, xoff, yoff; + if( rp != NULL ){ + sh = rp->Bottom - rp->Top; + sw = rp->Right - rp->Left; + yoff = rp->Top; + xoff = rp->Left; + } + else { + sh = psrc->Height; + sw = psrc->Width; + yoff = xoff = 0; + } + xss = sw / 2; + yss = sh / 2; + zy = double(h)/double(sh); + zx = double(w)/double(sw); + + if( (sw > w) && (sh > h) ){ + MultProc(); + TRect RC, TC; + if( tc != NULL ){ + TC = *tc; + } + else { + TC.Left = 0; TC.Right = pBitmap->Width; + TC.Top = 0; TC.Bottom = pBitmap->Height; + } + if( rp != NULL ){ + RC = *rp; + } + else { + RC.Left = 0; RC.Top = 0; + RC.Right = pbmp->Width; RC.Bottom = pbmp->Height; + } + int Sop = ::SetStretchBltMode(pBitmap->Canvas->Handle, HALFTONE); + pBitmap->Palette = NULL; + pBitmap->Canvas->CopyRect(TC, pbmp->Canvas, RC); + ::SetStretchBltMode(pBitmap->Canvas->Handle, Sop); + if( psrc != pbmp ) delete psrc; + return; + } + + MultProc(); + int xs = w / 2; + int ys = h / 2; + int i, j, m, n; + int r, g, b; + double x, y, p, q, pp, qq; + BYTE *tp, *ssp1, *ssp2, *sp1, *sp2; + for( i = -ys; i < ys; i++ ){ + tp = (BYTE *)pBitmap->ScanLine[i+ys+top]; + if( left ) tp += left * 3; + y = double(i)/zy; + if( y > 0 ){ + m = int(y); + } + else { + m = int(y-1); + } + q = y - double(m); + if( int(q) == 1 ){ + q = 0; m++; + } + qq = 1.0 - q; + if( m < -yss ) m = -yss; + if( (m + yss + 1) >= psrc->Height ) m = psrc->Height - yss - 1; + ssp1 = (BYTE *)psrc->ScanLine[yoff + m + yss]; + ssp2 = (BYTE *)psrc->ScanLine[yoff + m + 1 + yss]; + if( (m + yss + 1) >= psrc->Height ) ssp2 = ssp1; + if( xoff ) ssp1 += xoff * 3; + if( xoff ) ssp2 += xoff * 3; + for( j = -xs; j < xs; j++ ){ + x = double(j)/zx; + if( x > 0 ){ + n = int(x); + } + else { + n = int(x-1); + } + p = x - double(n); + if( int(p) == 1 ){ + p = 0; n++; + } + if( n < -xss ) n = -xss; + if( (n + xss + 1) >= psrc->Width ) n = psrc->Width - xss - 1; + + sp1 = ssp1 + (n + xss) * 3; + sp2 = ssp2 + (n + xss) * 3; + pp = 1.0 - p; + if( (n + xss + 1) >= psrc->Width ){ + r = (int)(qq*(pp*(*sp1)) + + q * (pp*(*sp2)) ); + sp1++; sp2++; + g = (int)(qq*(pp*(*sp1)) + + q * (pp*(*sp2)) ); + sp1++; sp2++; + b = (int)(qq*(pp*(*sp1)) + + q * (pp*(*sp2)) ); + } + else { + r = (int)(qq*(pp*(*sp1) + p*(*(sp1+3))) + + q * (pp*(*sp2) + p*(*(sp2+3)))); + sp1++; sp2++; + g = (int)(qq*(pp*(*sp1) + p*(*(sp1+3))) + + q * (pp*(*sp2) + p*(*(sp2+3)))); + sp1++; sp2++; + b = (int)(qq*(pp*(*sp1) + p*(*(sp1+3))) + + q * (pp*(*sp2) + p*(*(sp2+3)))); + } + LimitRGB(r, g, b); + *tp++ = BYTE(r); + *tp++ = BYTE(g); + *tp++ = BYTE(b); + } + MultProc(); + } + if( psrc != pbmp ) delete psrc; +} +//--------------------------------------------------------------------------- +void __fastcall SetGroupEnabled(TGroupBox *gp) +{ + int enb = gp->Enabled; + TControl *tp; + int i; + for( i = 0; i < gp->ControlCount; i++ ){ + tp = gp->Controls[i]; + if( tp != NULL ){ + tp->Enabled = enb; + if( tp->ClassNameIs("TGroupBox") ){ + SetGroupEnabled((TGroupBox *)tp); + } + } + } + gp->Font->Color = gp->Enabled ? clBlack : clGrayText; + for( i = 0; i < gp->ControlCount; i++ ){ + tp = gp->Controls[i]; + if( tp != NULL ){ + if( tp->ClassNameIs("TComboBox") ){ + ((TComboBox *)tp)->SelLength = 0; + } + } + } +} +//--------------------------------------------------------------------------- +int __fastcall Limit256(int d) +{ + if( d < 0 ) d = 0; + if( d > 255 ) d = 255; + return d; +} +//--------------------------------------------------------------------------- +void __fastcall LimitRGB(int &R, int &G, int &B) +{ + R = Limit256(R); + G = Limit256(G); + B = Limit256(B); +} +//--------------------------------------------------------------------------- +void __fastcall YCtoRGB(int &R, int &G, int &B, int Y, int RY, int BY) +{ + Y = Y - 16; + R = 1.164457*Y + 1.596128*RY; + G = 1.164457*Y - 0.813022*RY - 0.391786*BY; + B = 1.164457*Y + 2.017364*BY; + LimitRGB(R, G, B); +} +//--------------------------------------------------------------------------- +TColor __fastcall YCtoTColor(int Y, int RY, int BY) +{ + int R, G, B; + YCtoRGB(R, G, B, Y, RY, BY); + return TColor((B << 16) + (G << 8) + R); +} +//--------------------------------------------------------------------------- +int __fastcall ColorToFreq(int d) +{ + d = d * (2300 - 1500) / 256; + return d + 1500; +} +//--------------------------------------------------------------------------- +int __fastcall ColorToFreqNarrow(int d) +{ + d = d * NARROW_BW / 256; + return d + NARROW_LOW; +} +//--------------------------------------------------------------------------- +void __fastcall MultProc(void) +{ + Mmsstv->MultProc(); +} +//--------------------------------------------------------------------------- +void __fastcall MultProcA(void) +{ + if( Mmsstv->pSound->IsBusy() ) Mmsstv->MultProc(); +} +//--------------------------------------------------------------------------- +void __fastcall DrawBitmap(TPaintBox *pBox, Graphics::TBitmap *pBitmap) +{ + if( (pBox->Height >= 256) && ((pBitmap->Width != pBox->Width)||(pBitmap->Height != pBox->Height)) ){ + TRect rc; + rc.Left = 0; rc.Right = pBox->Width; + rc.Top = 0; rc.Bottom = pBox->Height; + int Sop = ::SetStretchBltMode(pBox->Canvas->Handle, HALFTONE); + pBox->Canvas->StretchDraw(rc, pBitmap); + ::SetStretchBltMode(pBox->Canvas->Handle, Sop); + } + else { + pBox->Canvas->Draw(0, 0, pBitmap); + } +} +//--------------------------------------------------------------------------- +void __fastcall ReSizeBitmap(Graphics::TBitmap *pBitmap, int w, int h) +{ + if( (pBitmap->Width != w) || (pBitmap->Height != h) ){ + Graphics::TBitmap *pbmp = CreateBitmap(w, h, pf24bit); + ::StretchCopy(pbmp, NULL, pBitmap, NULL); + pBitmap->Width = w; + pBitmap->Height = h; + pBitmap->Canvas->Draw(0, 0, pbmp); + delete pbmp; + } +} +//--------------------------------------------------------------------------- +// メディアンフィルタ +static int _cmp(const void *s, const void *t) +{ + return *((BYTE *)s) - *((BYTE *)t); +} +Graphics::TBitmap *__fastcall MFilter(Graphics::TBitmap *pTer, Graphics::TBitmap *pSrc, int sw) +{ + CWaitCursor wait; + Graphics::TBitmap *pBitmapS; + if( pSrc->PixelFormat != pf24bit ){ + pBitmapS = DupeBitmap(pSrc, pf24bit); + } + else { + pBitmapS = pSrc; + } + int XW = pBitmapS->Width; + int YW = pBitmapS->Height; + if( pTer == NULL ){ + pTer = new Graphics::TBitmap(); + } + pTer->PixelFormat = pf24bit; + pTer->Width = XW; + pTer->Height = YW; + + + MultProc(); + BYTE *bp = new BYTE[XW * YW * 3]; + int x, y; + BYTE *tp = bp; + BYTE *sp; + for( y = 0; y < YW; y++ ){ + sp = (BYTE*)pBitmapS->ScanLine[y]; + for( x = 0; x < XW; x++ ){ + *tp++ = *sp++; + *tp++ = *sp++; + *tp++ = *sp++; + } + } + int xw = XW * 3; // 960 + int xwm = (XW - 1) * 3; + BYTE List[9]; + if( sw ){ + for( y = 1; y < (YW - 1); y++ ){ + sp = &bp[y*xw+3]; + tp = (BYTE*)pTer->ScanLine[y] + 3; + for( x = 1; x < xwm; x++, sp++, tp++ ){ + List[0] = *sp; + List[1] = *(sp+3); + List[2] = *(sp-3); + List[3] = *(sp-xw); + List[4] = *(sp-xw+3); + List[5] = *(sp-xw-3); + List[6] = *(sp+xw); + List[7] = *(sp+xw+3); + List[8] = *(sp+xw-3); + qsort(List, 9, 1, _cmp); +// *tp = List[5]; + *tp = List[4]; + } + MultProcA(); + } + } + else { + for( y = 1; y < (YW - 1); y++ ){ + sp = &bp[y*xw+3]; + tp = (BYTE*)pTer->ScanLine[y] + 3; + for( x = 1; x < xwm; x++, sp++, tp++ ){ + List[0] = *sp; + List[1] = *(sp+3); + List[2] = *(sp-3); + List[3] = *(sp-xw); + List[4] = *(sp+xw); + qsort(List, 5, 1, _cmp); +// *tp = List[3]; + *tp = List[2]; + } + MultProcA(); + } + } + MultProc(); + delete bp; + if( pSrc != pBitmapS ) delete pBitmapS; + return pTer; +} + +void __fastcall CopyAutoSize(Graphics::TBitmap *pTer, Graphics::TBitmap *pSrc) +{ + if( (pSrc->Width == pTer->Width) && ((pSrc->Height == 240)||(pSrc->Height == 480)) ){ + switch(sys.m_Way240){ + case 0: + StretchCopyBitmap(pTer, pSrc); + break; + case 1: + StretchCopyBitmapHW(pTer, pSrc); + break; + case 2: + FillBitmap(pTer, sys.m_PicClipColor); + pTer->Canvas->Draw(0, 0, pSrc); + break; + default: + FillBitmap(pTer, sys.m_PicClipColor); + pTer->Canvas->Draw(0, 16, pSrc); + break; + } + } + else { + StretchCopyBitmapHW(pTer, pSrc); + } +} +//--------------------------------------------------------------------------- +void __fastcall GetRY(int &Y, int &RY, int &BY, TColor col) +{ + BYTE *p = (BYTE *)&col; + double R = *p++; + double G = *p++; + double B = *p; +#if 0 + Y = 16.0 + (.003906 * ((65.738 * R) + (129.057 * G) + (25.064 * B))); + RY = 128.0 + (.003906 * ((112.439 * R) + (-94.154 * G) + (-18.285 * B))); + BY = 128.0 + (.003906 * ((-37.945 * R) + (-74.494 * G) + (112.439 * B))); +#else + Y = 16.0 + (0.256773*R + 0.504097*G + 0.097900*B); + RY = 128.0 + (0.439187*R - 0.367766*G - 0.071421*B); + BY = 128.0 + (-0.148213*R - 0.290974*G + 0.439187*B); +#endif + LimitRGB(Y, RY, BY); +} +//--------------------------------------------------------------------------- +void __fastcall DownColor(Graphics::TBitmap *pbmp, TColor bcol, int lm) +{ + CWaitCursor w; + + int lm2 = lm * 3; + int SY, SR, SB; + int TY, TR, TB; + TColor tcol; + GetRY(SY, SR, SB, bcol); + int x, y; + for( y = 0; y < pbmp->Height; y++ ){ + MultProc(); + for( x = 0; x < pbmp->Width; x++ ){ + tcol = pbmp->Canvas->Pixels[x][y]; + if( bcol != tcol ){ + GetRY(TY, TR, TB, tcol); + if( (ABS(SY - TY) <= lm2)&& + (ABS(SR - TR) <= lm)&& + (ABS(SB - TB) <= lm) + ){ + pbmp->Canvas->Pixels[x][y] = bcol; + } + } + } + } +} +//--------------------------------------------------------------------------- +void KeyEvent(const short *p) +{ + for( ; *p; p++ ){ + keybd_event(BYTE(*p), 0, *p&0x8000 ? KEYEVENTF_KEYUP : 0, 0); + MultProc(); + } +} +//--------------------------------------------------------------------------- +void __fastcall SetThumbnailSize(TRect &rc, int sw) +{ + switch(sw){ + case 0: + rc.Right = 50; + rc.Bottom = 40; + break; + case 1: + rc.Right = 64; + rc.Bottom = 51; + break; + case 2: + rc.Right = 80; + rc.Bottom = 64; + break; + default: + rc.Right = 100; + rc.Bottom = 80; + break; + } +} +//--------------------------------------------------------------------------- +void __fastcall NormalRect(long *x1, long *y1, long *x2, long *y2) //ja7ude 0521 +{ + if( *x1 > *x2 ){ + int d = *x1; + *x1 = *x2; + *x2 = d; + } + if( *y1 > *y2 ){ + int d = *y1; + *y1 = *y2; + *y2 = d; + } +} +void __fastcall NormalRect(int &x1, int &y1, int &x2, int &y2) //ja7ude 0521 +{ + if( x1 > x2 ){ + int d = x1; + x1 = x2; + x2 = d; + } + if( y1 > y2 ){ + int d = y1; + y1 = y2; + y2 = d; + } +} +//--------------------------------------------------------------------------- +void __fastcall NormalRect(TRect *rc) +{ + NormalRect(&(rc->Left), &(rc->Top), &(rc->Right), &(rc->Bottom)); //ja7ude 0521 +} +//--------------------------------------------------------------------------- +int __fastcall GetActiveIndex(TPageControl *pp) +{ + int i; + for( i = 0; i < pp->PageCount; i++ ){ + if( pp->ActivePage == pp->Pages[i] ) return i; + } + return 0; +} +//--------------------------------------------------------------------------- +void __fastcall SetMBCP(void) +{ + _setmbcp(_MB_CP_ANSI); +} +//--------------------------------------------------------------------------- +static int CodeErr = 0; +//--------------------------------------------------------------------------- +void __fastcall ClearCodeErr(void) +{ + CodeErr = 0; +} +//--------------------------------------------------------------------------- +void __fastcall SetMBCP(BYTE charset) +{ + UINT cp; + switch(charset){ + case SHIFTJIS_CHARSET: + cp = 932; + break; + case HANGEUL_CHARSET: + cp = 949; + break; + case CHINESEBIG5_CHARSET: // + cp = 950; + break; + case 134: // 簡略 + cp = 936; + break; + default: + cp = _MB_CP_ANSI; + break; + } + if( cp != _MB_CP_ANSI ){ + CPINFO info; + if( GetCPInfo(cp, &info) != TRUE ){ + if( !CodeErr ){ + CodeErr++; + InfoMB("CodePage %d is not supported on your PC.", cp); + } + cp = _MB_CP_ANSI; + } + } + _setmbcp(cp); +} +//--------------------------------------------------------------------------- +void __fastcall MoveParent(TWinControl *pNew, TWinControl *pOld, TWinControl *pCtr) +{ + pOld->RemoveControl(pCtr); + pNew->InsertControl(pCtr); + pCtr->Parent = pNew; +} +//--------------------------------------------------------------------------- +BYTE __fastcall InvFontCharset(BYTE charset) +{ + BYTE cset; + UINT cp = ::GetACP(); + switch(cp){ + case 932: + cset = SHIFTJIS_CHARSET; + break; + case 949: + cset = HANGEUL_CHARSET; + break; + case 950: + cset = CHINESEBIG5_CHARSET; + break; + case 936: + cset = 134; // 簡略 + break; + default: + cset = DEFAULT_CHARSET; + break; + } + return BYTE((charset != ANSI_CHARSET) ? ANSI_CHARSET : cset); +} +//--------------------------------------------------------------------------- +void __fastcall InvFontCharset(TFont *pFont) +{ + pFont->Charset = InvFontCharset(pFont->Charset); +} +//--------------------------------------------------------------------------- + + diff --git a/ComLib.h b/ComLib.h new file mode 100644 index 0000000..1d89b85 --- /dev/null +++ b/ComLib.h @@ -0,0 +1,801 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +#ifndef ComLibH +#define ComLibH +#include +#include //JA7UDE 0428 +#include +#include +#include +#include +#include +#include +#include + +#define DEBUG FALSE +#define DEBUGFSKID FALSE +#define VARITEST FALSE +#define SHOWAFCFQ FALSE + +#if DEBUG +#include +#define ASSERT(c) assert(c) +#else +#define ASSERT(c) +#endif + +/* +1.12 JASTAコンテスト 重複チェックの修正 +*/ +#define VERBETA "A" +#define VERID "Ver 1.13" +#define VERTTL2 "MMSSTV "VERID VERBETA +#define VERTTL VERTTL2" (C) JE3HHT 2001-2010." + +#define CLOCKMAX 48500 +#define FPAGEMAX 10 // フォルダのサムネイルのページ数 +#define CWMENUMAX 128 + +#define HISTNAME "History.bin" +#define TEMPV105 "CurTemp.bin" // V1.05までの名前 +#define TEMPV105B "CurTemp.old" +#define TEMPV106C "Current.mtm" // V1.06からの名前 +#define TEMPV106L "List.mtm" // V1.06からの名前 +//#define SHIFTL 10 +//#define MARKL 300 +//#define SPACEH 2700 + +#define FSBOLD 1 +#define FSITALIC 2 +#define FSUNDERLINE 4 +#define FSSTRIKEOUT 8 + +enum { + pgSync, + pgRX, + pgHist, + pgTX, + pgTemp, +}; + +extern LCID lcid; // ロケール情報 +extern int DisPaint; +extern int MsgEng; +extern int WinNT; +extern int WinVista; + +extern double SampFreq; // サンプリング周波数 +extern double SampBase; +extern int SampType; +extern int SampSize; +extern int DemOver; +extern const int SampTable[]; + +extern double FFTSamp; +extern int FFTSampType; +extern int FFT_SIZE; + +extern char BgnDir[256]; + +extern char HistDir[256]; +extern char StockDir[256]; +extern char BitmapDir[256]; +extern char SBitmapDir[256]; +extern char TemplateDir[256]; + +extern char MMLogDir[256]; +extern char ExtLogDir[256]; +extern char RecDir[256]; // 録音ファイルのディレクトリ + +//extern HPALETTE UsrPal; + +extern AnsiString JanHelp; + +extern const char MONN[]; +extern const char MONU[]; + +#ifndef LPCUSTR +typedef const unsigned char * LPCUSTR; +typedef unsigned char * LPUSTR; +#endif + +extern DWORD ColorTable[128]; + +#pragma option -a- // パックの指示 +typedef union { + struct { + BYTE r; + BYTE g; + BYTE b; + BYTE d; + }b; + TColor c; + DWORD d; +}COLD; +#pragma option -a. // パック解除の指示 + +#define ABS(c) (((c)<0)?(-(c)):(c)) +#define AN(p) (int)(sizeof(p)/sizeof(*(p))) +#define CR 0x0d +#define LF 0x0a +#define TAB '\t' + +typedef struct { + AnsiString Name; + double VCOGain; + int loopOrder; + double loopFC; + int OutOrder; + double OutFC; + + int Type; + int crossType; + double crossSmooz; + int crossOutOrder; + double crossOutFC; + + double DemOff; + double DemWhite; + double DemBlack; + int DemCalibration; + double Dem17[17]; + + int Differentiator; + double DiffLevel; +}PRODEM; + +typedef struct { + AnsiString m_Name; + BYTE m_Charset; + int m_Height; + DWORD m_Style; +}FONTDATA; + +//#define MSGLISTMAX 64 +typedef struct { + int m_Priority; + + int m_SoundPriority; + AnsiString m_SoundDevice; + int m_SoundStereo; + int m_StereoTX; + AnsiString m_SoundMMW; + + AnsiString m_Call; + + int m_FontAdjSize; + int m_WindowState; + + int m_ExtMode[8]; + AnsiString m_ExtCmd[8]; + AnsiString m_ExtName[8]; + + AnsiString m_TxRxName; + int m_TxRxLock; + int m_RTSonRX; + + int m_lmsbpf; + int m_echo; + + int m_AutoTimeOffset; + int m_TimeOffset; + int m_TimeOffsetMin; + int m_LogLink; + + AnsiString m_LogName; + + int m_SoundFifoRX; + int m_SoundFifoTX; + + int m_Palette; + int m_BitPixel; + + TColor m_ColorLow; + TColor m_ColorHigh; + TColor m_ColorFFTB; + TColor m_ColorFFT; + TColor m_ColorFFTStg; + TColor m_ColorFFTSync; + TColor m_ColorFFTFreq; + + AnsiString m_WinFontName; + BYTE m_WinFontCharset; + int m_WinFontStyle; + + int m_FFTType; + int m_FFTGain; + int m_FFTResp; + int m_FFTStg; + int m_FFTWidth; + int m_FFTAGC; + int m_FFTPriority; + double m_SampFreq; + double m_TxSampOff; + + int m_StayOnTop; + int m_MemWindow; + + int m_HelpNotePad; + int m_TuneTXTime; + int m_TuneSat; + + int m_TestDem; + double m_DemOff; + double m_DemWhite; + double m_DemBlack; + int m_DemCalibration; + double m_Dem17[17]; + + int m_PicClipType; + int m_PicClipRatio; + int m_PicClipMode; + int m_PicClipView; + TColor m_PicClipColor; + int m_HistMax; + + int m_Way240; + int m_AutoMargin; + + int m_UseRxBuff; + int m_AutoStop; + int m_AutoSync; + int m_CWID; + int m_CWIDFreq; + AnsiString m_CWIDText; + int m_CWIDSpeed; + int m_CWIDWPM; + AnsiString m_MMVID; + AnsiString m_CWText; + + int m_nCWMenu; + AnsiString m_CWMenu[CWMENUMAX]; + + int m_VOX; + AnsiString m_VOXSound; + + int m_TXFSKID; + + int m_UseJPEG; + int m_JPEGQuality; + + int m_RxViewTop; + int m_RxViewLeft; + int m_RxViewWidth; + int m_RxViewHeight; + + int m_SyncViewTop; + int m_SyncViewLeft; + int m_SyncViewWidth; + int m_SyncViewHeight; + + int m_HistViewTB; + int m_HistViewTop; + int m_HistViewLeft; + int m_HistViewWidth; + int m_HistViewHeight; + int m_HistViewSize; + + int m_PreViewTop; + int m_PreViewLeft; + int m_PreViewWidth; + int m_PreViewHeight; + + int m_CtrBtnTop; + int m_CtrBtnLeft; + int m_CtrBtnWidth; + int m_CtrBtnHeight; + + int m_FileViewFlag[8]; + int m_FileViewSize[8]; + int m_FileViewMode[8]; + int m_FileViewTop[8]; + int m_FileViewLeft[8]; + int m_FileViewWidth[8]; + int m_FileViewHeight[8]; + int m_FileViewMaxPage[8]; + int m_FileViewCurPage[8]; + int m_FileViewFMPage[8][FPAGEMAX]; + AnsiString m_FileViewFolder[8][FPAGEMAX]; + AnsiString m_FileViewName[8][10]; + int m_FileViewKeep; + int m_FileViewShowSize; + + int m_DivMode; + int m_StockViewTop; + int m_StockViewLeft; + int m_StockViewWidth; + int m_StockViewHeight; + + int m_WaterViewTop; + int m_WaterViewLeft; + int m_WaterViewWidth; + int m_WaterViewHeight; + + int m_LogViewTop; + int m_LogViewLeft; + int m_LogViewWidth; + int m_LogViewHeight; + + TColor m_ColText[6]; + TColor m_ColBar[4]; + AnsiString m_AutoSaveDir; + TColor m_ColorSet[32]; + + int m_FixedTxMode; + AnsiString m_TextList[16]; + + int m_TextGrade; + int m_TextShadow; + int m_TextZero; + int m_TextRot; + int m_TextVert; + int m_TextVertH; + int m_TextStack; + + int m_PicShape; + int m_PicAdjust; + int m_PicLineStyle; + TColor m_PicLineColor; + + int m_PicSelRTM; + int m_PicSelSmooz; + TColor m_PicSelCurCol; + + int m_Sharp2D; + int m_Differentiator; + double m_DiffLevelP; + double m_DiffLevelM; + + TColor m_ColorRXB; + int m_HDDSize; + + int m_ShowSizeRX; + int m_ShowSizeHist; + int m_ShowSizeTX; + int m_ShowSizeTemp; + int m_ShowSizeStock; + + int m_Repeater; + int m_RepSenseLvl; // トーン検出感度 + AnsiString m_RepAnsCW; + int m_RepTimeA; // トーン検出時間 + int m_RepTimeB; // トーン検出からAnsCW出力までの時間 + int m_RepTimeC; // 受信待機のタイムアウト + int m_RepTimeD; // リプレイ送信の遅延時間 + + int m_RepBeacon; + int m_RepBeaconMode; + AnsiString m_RepTempTX; + AnsiString m_RepTempBeacon; + int m_RepBottomAdj; + int m_RepQuietnessTime; + int m_RepBeaconFilter; + AnsiString m_RepFolder; + + int m_UseB24; + AnsiString m_Msg; + int m_DisFontSmooth; + + int m_TempDelay; + FONTDATA m_RegFont[4]; + + int m_Temp24; + + int m_MaskUserPage; + TColor m_MaskCol1; + TColor m_MaskCol2; + + int m_bCQ100; +}SYSSET; + +extern SYSSET sys; + +///--------------------------------------------------------- +/// テキスト文字列ストリーマー +class CTextString +{ +private: + LPCSTR rp; +public: + inline __fastcall CTextString(LPCSTR p){ + rp = p; + }; + inline __fastcall CTextString(AnsiString &As){ + rp = As.c_str(); + }; + int __fastcall LoadText(LPSTR tp, int len); +}; +///--------------------------------------------------------- +/// コントロールのアラインの管理クラス +class CAlign +{ +private: + int BTop, BLeft; + int BWidth, BHeight; + int OTop, OLeft; + int OWidth, OHeight; + int OFontHeight; + double m_FontAdj; + + TControl *tp; + TFont *fp; +public: + inline CAlign(void){ + tp = NULL; + fp = NULL; + m_FontAdj = 1.0; + }; + inline ~CAlign(){ + }; + void InitControl(TControl *p, TControl *pB, TFont *pF = NULL); + void InitControl(TControl *p, RECT *rp, TFont *pF = NULL); + void NewAlign(TControl *pB); + inline double GetFontAdj(void){return fabs(m_FontAdj);}; + inline TControl *GetControl(void){return tp;}; + void NewAlign(TControl *pB, double hx); + void NewFont(AnsiString &FontName, BYTE Charset, TFontStyles fs); + void NewFixAlign(TControl *pB, int XR); + void Resume(void); +}; + +///--------------------------------------------------------- +/// コントロールのアラインの管理クラス +class CAlignList +{ +private: + int Max; + int Cnt; + CAlign **AlignList; + void Alloc(void); +public: + CAlignList(void); + ~CAlignList(); + void EntryControl(TControl *tp, TControl *pB, TFont *pF = NULL); + void EntryControl(TControl *tp, RECT *rp, TFont *pF = NULL); + void EntryControl(TControl *tp, int XW, int YW, TFont *pF = NULL); + void NewAlign(TControl *pB); + double GetFontAdj(TControl *pB); + void NewAlign(TControl *pB, TControl *pS, double hx); + void NewFont(AnsiString &FontName, BYTE Charset, TFontStyles fs); + void NewFixAlign(TControl *pB, int XR); + void Resume(TControl *pB); +}; + +class CAlignGrid +{ +private: + int BWidth; + int BHeight; + int BRowHeight; + + int Max; + int *bp; +public: + inline CAlignGrid(void){ + Max = 0; + bp = NULL; + }; + inline ~CAlignGrid(){ + if( bp != NULL ){ + delete bp; + } + }; + void InitGrid(TStringGrid *p); + void NewAlign(TStringGrid *p); +}; + +class CWebRef +{ +private: + AnsiString HTML; +public: + CWebRef(); + inline bool IsHTML(void){ + return !HTML.IsEmpty(); + }; + void ShowHTML(LPCSTR url); +}; + +class CWaitCursor +{ +private: + TCursor sv; +public: + CWaitCursor(); + ~CWaitCursor(); + void Delete(void); + void Wait(void); +}; + +///------------------------------------------------------- +/// CRecentMenuクラス +#define RECMENUMAX 4 // 処理できる最大の数 +class CRecentMenu +{ +private: +public: + int InsPos; // メニュー挿入位置の番号 + int Max; // 処理する数 + AnsiString Caption[RECMENUMAX]; + TMenuItem *pMenu; + TMenuItem *Items[RECMENUMAX+1]; + +public: + CRecentMenu(); + void Init(int pos, TMenuItem *pmenu, int max); + void Init(TMenuItem *pi, TMenuItem *pmenu, int max); + int GetCount(void); + LPCSTR GetItemText(int n); + void SetItemText(int n, LPCSTR p); + int IsAdd(LPCSTR pNew); + void Add(LPCSTR pNew); + void ExtFilter(LPCSTR pExt); + void Clear(void); + void Insert(TObject *op, Classes::TNotifyEvent pEvent); + void Delete(void); + void Delete(LPCSTR pName); + int FindItem(TMenuItem *mp); + LPCSTR FindItemText(TMenuItem *mp); +}; + +///------------------------------------------------------- +/// CBitmapHistクラス +#define HISTMAX 256 +typedef struct { + int m_Ver; + int m_Max; + int m_Cnt; + int m_wPnt; +}HEADBH; +typedef struct { + int m_Flag; + SYSTEMTIME m_UTC; +}HEADFH; +class CBitmapHist +{ +public: + HEADBH m_Head; + HEADFH m_File[256]; + AnsiString m_FileName; + int m_CurAdd; + int m_CurRead; + int m_UseJPEG; +private: + +public: + CBitmapHist(){ + m_CurAdd = 0; + m_CurRead = 0; + m_FileName = ""; + m_UseJPEG = 0; + + m_Head.m_Ver = 0; + m_Head.m_Max = 64; + m_Head.m_Cnt = 0; + m_Head.m_wPnt = 0; + }; + ~CBitmapHist(){ + Close(); + }; + int Open(void); + void Close(void); + int OverWrite(void); + int Read(Graphics::TBitmap *pBitmap, int slot); + void Write(Graphics::TBitmap *pBitmap, int slot); + void Add(Graphics::TBitmap *pBitmap, SYSTEMTIME *pTime, int mode); + void ClearAddFlag(void){m_CurAdd = 0;}; + void Update(Graphics::TBitmap *pBitmap); + int IsAddFlag(void){return m_CurAdd;}; + void ChangeMax(int max); + void MoveDir(LPCSTR pNewDir); + void Delete(int n); + void DeleteAll(void); + void ChangeFormat(int sw); +}; + +///------------------------------------------------------- +/// CExecPBクラス +class CExecPB +{ +private: + int m_Flag; + DWORD m_dwCount; + DWORD m_dwID; // ID値 + UINT m_uMsg; // メッセージ値 + HWND m_hWndMsg; // メッセージの送信先 + + AnsiString m_Name; + DWORD m_nFileSizeLow; + FILETIME m_ftLastWriteTime; +public: + __fastcall CExecPB(); + __fastcall ~CExecPB(); + + BOOL __fastcall Timer(void); + void __fastcall Cancel(void); + BOOL __fastcall Exec(LPCSTR pName, HWND hWnd, UINT uMsg, DWORD nID); + BOOL __fastcall Exec(Graphics::TBitmap *pBitmap, HWND hWnd, UINT uMsg, DWORD nID); + BOOL __fastcall IsChanged(void); + BOOL __fastcall LoadBitmap(Graphics::TBitmap *pBitmap, BOOL sw); +}; + +void __fastcall SetDisPaint(void); +void __fastcall ResDisPaint(void); + +void ShowHelp(int index); +void InitSampType(void); +double NormalSampFreq(double d, double m); +int IsFile(LPCSTR pName); + +void GetUTC(SYSTEMTIME *tp); +void GetLocal(SYSTEMTIME *tp); +LPSTR StrDupe(LPCSTR s); + +void InitColorTable(TColor cl, TColor ch); +LPCSTR GetKeyName(WORD Key); +WORD GetKeyCode(LPCSTR pName); +LPCSTR ToDXKey(LPCSTR s); +LPCSTR ToJAKey(LPCSTR s); + +//int InputMB(LPCSTR pMsg, LPCSTR pTitle, AnsiString &as); + +int SetTBValue(double d, double dmax, int imax); +double GetTBValue(int d, double dmax, int imax); +LPUSTR jstrupr(LPUSTR s); +inline LPSTR jstrupr(LPSTR s){return (LPSTR)jstrupr(LPUSTR(s));}; + +int SetTimeOffsetInfo(int &Hour, int &Min); +WORD AdjustRolTimeUTC(WORD tim, char c); +void FormCenter(TForm *tp, int XW, int YW); +char *lastp(char *p); +char *clipsp(char *s); +LPCSTR _strdmcpy(LPSTR t, LPCSTR p, char c); +const char *StrDlmCpy(char *t, const char *p, char Dlm, int len); +const char *StrDlmCpyK(char *t, const char *p, char Dlm, int len); +void StrCopy(LPSTR t, LPCSTR s, int n); +char LastC(LPCSTR p); +LPCSTR GetEXT(LPCSTR Fname); +void SetEXT(LPSTR pName, LPSTR pExt); +BOOL __fastcall CheckEXT(LPCSTR pName, LPCSTR pExt); +void SetCurDir(LPSTR t, int size); +void SetDirName(LPSTR t, LPCSTR pName); +LPCSTR StrDbl(double d); +LPCSTR StrDblE(double d); +double ReadDoubleIniFile(TMemIniFile *p, LPCSTR c1, LPCSTR c2, double d); +void WriteDoubleIniFile(TMemIniFile *p, LPCSTR c1, LPCSTR c2, double d); +void ClipLF(LPSTR sp); +void DeleteComment(LPSTR bf); +LPSTR FillSpace(LPSTR s, int n); +LPSTR SkipSpace(LPSTR sp); +LPCSTR SkipSpace(LPCSTR sp); +LPSTR StrDlm(LPSTR &t, LPSTR p); +LPSTR StrDlm(LPSTR &t, LPSTR p, char c); +void ChgString(LPSTR t, char a, char b); +void DelChar(LPSTR t, char a); +int atoin(const char *p, int n); +int htoin(const char *p, int n); +BOOL __fastcall ATOI(int &d, LPCSTR s); + +int InvMenu(TMenuItem *pItem); +void AdjustBitmapFormat(Graphics::TBitmap *pBitmap); +Graphics::TBitmap *Bitmap24bit(Graphics::TBitmap *pBitmap); +int LoadBitmap(Graphics::TBitmap *pBitmap, LPCSTR pName); +int SaveBitmap24(Graphics::TBitmap *pBitmap, LPCSTR pName); +int SaveBitmap(Graphics::TBitmap *pBitmap, LPCSTR pName); +void FillBitmap(Graphics::TBitmap *pBitmap, TColor col); +int SaveJPEG(Graphics::TBitmap *pBitmap, LPCSTR pName); +int LoadJPEG(Graphics::TBitmap *pBitmap, LPCSTR pName); +int IsPic(LPCSTR pExt); +LPCSTR GetPicFilter(void); +LPCSTR GetTempFilter(void); +LPCSTR GetTempMFilter(void); +LPCSTR GetTempIFilter(void); +LPCSTR GetLibFilter(void); +int LoadImage(Graphics::TBitmap *pBitmap, LPCSTR pName); +int SaveImage(Graphics::TBitmap *pBitmap, LPCSTR pName); + +void InitCustomColor(TColorDialog *tp); +void AddCustomColor(TColorDialog *tp, TColor col); + +void InfoMB(LPCSTR fmt, ...); +void ErrorMB(LPCSTR fmt, ...); +void WarningMB(LPCSTR fmt, ...); +int YesNoMB(LPCSTR fmt, ...); +int YesNoCancelMB(LPCSTR fmt, ...); +int OkCancelMB(LPCSTR fmt, ...); +void ErrorFWrite(LPCSTR pName); + +int RemoveL2(LPSTR t, LPSTR ss, LPCSTR pKey, int size); +void AddL2(LPSTR t, LPCSTR pKey, LPCSTR s, UCHAR c1, UCHAR c2, int size); + +void Yen2CrLf(AnsiString &ws, AnsiString cs); +void CrLf2Yen(AnsiString &ws, AnsiString cs); + +void SetComboBox(TComboBox *pCombo, LPCSTR pList); +void GetComboBox(AnsiString &as, TComboBox *pCombo); +void ExecPB(LPCSTR pName); + +int IsNumbs(LPCSTR p); +int IsAlphas(LPCSTR p); +int IsRST(LPCSTR p); +int IsCallChar(char c); +int IsCall(LPCSTR p); +int IsJA(const char *s); +LPCSTR ClipCall(LPCSTR s); +LPCSTR ClipCC(LPCSTR s); + +/* JA7UDE 0428 +inline LPUSTR StrDlm(LPUSTR &t, LPUSTR p, char c){return (LPUSTR)StrDlm(LPSTR(t), LPSTR(p), c);}; +inline LPUSTR StrDlm(LPUSTR &t, LPUSTR p){return (LPUSTR)StrDlm(LPSTR(t), LPSTR(p));}; +inline LPUSTR StrDlm(LPUSTR &t, LPSTR p, char c){return (LPUSTR)StrDlm(LPSTR(t), p, c);}; +inline LPUSTR StrDlm(LPUSTR &t, LPSTR p){return (LPUSTR)StrDlm(LPSTR(t), p);}; +*/ + +void TopWindow(TForm *tp); +void NormalWindow(TForm *tp); + +int FontStyle2Code(TFontStyles style); +TFontStyles Code2FontStyle(int code); + +void __fastcall KeepAspect(int &sx, int &sy, int bx, int by); +void __fastcall KeepAspectDraw(TCanvas *tp, int sx, int sy, Graphics::TBitmap *pBitmap); +Graphics::TBitmap *__fastcall DupeBitmap(Graphics::TBitmap *pSrc, int fmt); +Graphics::TBitmap *__fastcall RemakeBitmap(Graphics::TBitmap *pBitmap, int fmt); +Graphics::TBitmap* __fastcall CreateBitmap(int xw, int yw, int fmt); +void __fastcall StretchCopyBitmap(Graphics::TBitmap *pTer, Graphics::TBitmap *pSrc); +void __fastcall StretchCopyBitmapHW(Graphics::TBitmap *pTer, Graphics::TBitmap *pSrc); +void __fastcall CopyBitmap(Graphics::TBitmap *pTer, Graphics::TBitmap *pSrc); +void __fastcall StretchCopy(Graphics::TBitmap *pTer, Graphics::TBitmap *pSrc, int mode); +void __fastcall StretchCopy(Graphics::TBitmap *pBitmap, TRect *tc, Graphics::TBitmap *pbmp, TRect *rp); +void __fastcall SetGroupEnabled(TGroupBox *gp); + +int __fastcall Limit256(int d); +void __fastcall LimitRGB(int &R, int &G, int &B); +void __fastcall YCtoRGB(int &R, int &G, int &B, int Y, int RY, int BY); +TColor __fastcall YCtoTColor(int Y, int RY, int BY); +int __fastcall ColorToFreq(int d); +int __fastcall ColorToFreqNarrow(int d); +void __fastcall MultProc(void); +void __fastcall MultProcA(void); + +void __fastcall DrawBitmap(TPaintBox *pBox, Graphics::TBitmap *pBitmap); +void __fastcall ReSizeBitmap(Graphics::TBitmap *pBitmap, int w, int h); +Graphics::TBitmap *__fastcall MFilter(Graphics::TBitmap *pTer, Graphics::TBitmap *pSrc, int sw); +void __fastcall CopyAutoSize(Graphics::TBitmap *pTer, Graphics::TBitmap *pSrc); +void __fastcall GetRY(int &Y, int &RY, int &BY, TColor col); +void __fastcall DownColor(Graphics::TBitmap *pbmp, TColor bcol, int lm); + +void KeyEvent(const short *p); +void __fastcall SetThumbnailSize(TRect &rc, int sw); +void __fastcall NormalRect(long *x1, long *y1, long *x2, long *y2); //ja7ude 0521 +void __fastcall NormalRect(int &x1, int &y1, int &x2, int &y2); //ja7ude 0521 +void __fastcall NormalRect(TRect *rc); +int __fastcall GetActiveIndex(TPageControl *pp); + +void __fastcall ClearCodeErr(void); +void __fastcall SetMBCP(void); +void __fastcall SetMBCP(BYTE charset); +void __fastcall MoveParent(TWinControl *pNew, TWinControl *pOld, TWinControl *pCtr); +BYTE __fastcall InvFontCharset(BYTE charset); +void __fastcall InvFontCharset(TFont *pFont); + +extern CExecPB g_ExecPB; +#endif + diff --git a/Comm.cpp b/Comm.cpp new file mode 100644 index 0000000..db7a27f --- /dev/null +++ b/Comm.cpp @@ -0,0 +1,295 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------------- +#include //ja7ude 0521 +#pragma hdrstop + +#include "Comm.h" +#include "ComLib.h" + +#define WAITSTAT 0 + +#define DEFFSOUND 3 + +COMMPARA COMM; +void InitCOMMPara(void) +{ + COMM.change = 1; +} + +__fastcall CComm::CComm(void) +{ + m_CreateON = FALSE; // クリエイトフラグ + m_Command = 0; + m_fHnd = NULL; // ファイルハンドル + m_ptt = m_scan = 0; + m_pEXT = NULL; +} + +/*#$% +============================================================== + 通信回線をクローズする +-------------------------------------------------------------- +-------------------------------------------------------------- +-------------------------------------------------------------- +============================================================== +*/ +void __fastcall CComm::Close(void) +{ + if( m_CreateON == TRUE ){ + if( m_pEXT != NULL ){ + delete m_pEXT; + m_pEXT = NULL; + } + else { + ::CloseHandle(m_fHnd); + } + m_CreateON = FALSE; + } +} + +/*#$% +============================================================== + 通信回線をオープンする +-------------------------------------------------------------- +PortName : 回線の名前 +pCP : COMMPARAのポインタ(ヌルの時はデフォルトで初期化) +RBufSize : 受信バッファのサイズ(default=2048) +TBufSize : 送信バッファのサイズ(default=2048) +-------------------------------------------------------------- +TRUE/FALSE +-------------------------------------------------------------- +============================================================== +*/ +BOOL __fastcall CComm::Open(LPCTSTR PortName) +{ + if( m_CreateON == TRUE ) Close(); + m_fHnd = ::CreateFile( PortName, GENERIC_READ | GENERIC_WRITE, + 0, NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL + ); + if( m_fHnd == INVALID_HANDLE_VALUE ){ + AnsiString as = "\\\\.\\"; + as += PortName; + m_fHnd = ::CreateFile( as.c_str(), GENERIC_READ | GENERIC_WRITE, + 0, NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL + ); + } + if( m_fHnd == INVALID_HANDLE_VALUE ){ + m_pEXT = new CEXTFSK(PortName); + if( m_pEXT->IsLib() ){ + LONG para; + para = (45 << 16) | (5 << 2); + m_pEXT->Open(para); + m_CreateON = TRUE; + return TRUE; + } + else { + delete m_pEXT; + m_pEXT = NULL; + } + return FALSE; + } + // setup device buffers + if( ::SetupComm( m_fHnd, DWORD(1024), DWORD(2) ) == FALSE ){ + ::CloseHandle(m_fHnd); + return FALSE; + } + + // purge any information in the buffer + ::PurgeComm( m_fHnd, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR ); + + // set up for overlapped I/O + COMMTIMEOUTS TimeOut; + + TimeOut.ReadIntervalTimeout = 0xffffffff; + TimeOut.ReadTotalTimeoutMultiplier = 0; + TimeOut.ReadTotalTimeoutConstant = 0; + TimeOut.WriteTotalTimeoutMultiplier = 0; + TimeOut.WriteTotalTimeoutConstant = 20000; +// TimeOut.WriteTotalTimeoutConstant = 1; + if( !::SetCommTimeouts( m_fHnd, &TimeOut ) ){ + ::CloseHandle( m_fHnd ); + return FALSE; + } + ::GetCommState( m_fHnd, &m_dcb ); + m_dcb.BaudRate = 9600; + m_dcb.fBinary = TRUE; + m_dcb.ByteSize = 8; + m_dcb.Parity = NOPARITY; + m_dcb.StopBits = ONESTOPBIT; + m_dcb.XonChar = 0x11; // XON + m_dcb.XoffChar = 0x13; // XOFF + m_dcb.fParity = 0; + m_dcb.fOutxCtsFlow = FALSE; + m_dcb.fInX = m_dcb.fOutX = FALSE; + m_dcb.fOutxDsrFlow = FALSE; + m_dcb.EvtChar = 0x0d; + + m_dcb.fRtsControl = RTS_CONTROL_DISABLE; // 送信禁止 + m_dcb.fDtrControl = DTR_CONTROL_DISABLE; // 送信禁止 + +// m_dcb.fTXContinueOnXoff = TRUE; + m_dcb.XonLim = USHORT(1024/4); // 1/4 of RBufSize + m_dcb.XoffLim = USHORT(1024*3/4); // 3/4 of RBufSize + m_dcb.DCBlength = sizeof( DCB ); + + if( !::SetCommState( m_fHnd, &m_dcb ) ){ + ::CloseHandle( m_fHnd ); + return FALSE; + } + + // get any early notifications + if( !::SetCommMask( m_fHnd, EV_RXFLAG ) ){ + ::CloseHandle(m_fHnd); + return FALSE; + } + m_CreateON = TRUE; + return TRUE; +} +//----------------------------------------------------------------- +// PTT切り替え用 +int __fastcall CComm::PTTOpen(void) +{ + if( m_CreateON == FALSE ){ + if( !strcmpi(sys.m_TxRxName.c_str(), "NONE") ) return FALSE; + Open(sys.m_TxRxName.c_str()); + if( m_CreateON == FALSE ) return FALSE; + } + return TRUE; +} +//----------------------------------------------------------------- +// PTT切り替え用 +int __fastcall CComm::SetPTT(void) +{ + int rts = m_ptt; + if( m_pEXT != NULL ){ + if( sys.m_RTSonRX && m_scan ) rts |= 2; + m_pEXT->SetPTT(rts); + } + else { + if( sys.m_RTSonRX ){ + rts |= m_scan; + ::EscapeCommFunction(m_fHnd, m_scan ? SETBREAK : CLRBREAK); + } + ::EscapeCommFunction(m_fHnd, rts ? SETRTS : CLRRTS); + ::EscapeCommFunction(m_fHnd, m_ptt ? SETDTR : CLRDTR); + } + return rts | m_ptt; +} +//----------------------------------------------------------------- +// PTT切り替え用 +void __fastcall CComm::SetPTT(int sw) +{ + m_ptt = sw; + + if( !PTTOpen() ) return; + if( !SetPTT() && (!sys.m_TxRxLock) ) Close(); +} +//----------------------------------------------------------------- +// RX-SCAN信号 +void __fastcall CComm::SetScan(int scan) +{ + m_scan = scan; + + if( !sys.m_RTSonRX ) return; + if( !PTTOpen() ) return; + if( !SetPTT() && (!sys.m_TxRxLock) ) Close(); +} + +/******************************************************************* + EXTFSK.DLL +*******************************************************************/ +__fastcall CEXTFSK::CEXTFSK(LPCSTR pName) +{ + char Name[128]; + sprintf(Name, "%s.%s", pName, strcmpi(pName, "EXTFSK") ? "fsk" : "dll"); + + fextfskOpen = NULL; + fextfskClose = NULL; + fextfskIsTxBusy = NULL; + fextfskPutChar = NULL; + fextfskSetPTT = NULL; + + m_hLib = ::LoadLibrary(Name); + if( m_hLib != NULL ){ + fextfskOpen = (extfskOpen)GetProc("_extfskOpen"); + fextfskClose = (extfskClose)GetProc("_extfskClose"); + fextfskIsTxBusy = (extfskIsTxBusy)GetProc("_extfskIsTxBusy"); + fextfskPutChar = (extfskPutChar)GetProc("_extfskPutChar"); + fextfskSetPTT = (extfskSetPTT)GetProc("_extfskSetPTT"); + } +} + +//--------------------------------------------------------------------- +__fastcall CEXTFSK::~CEXTFSK() +{ + if( m_hLib != NULL ){ + Close(); + ::FreeLibrary(m_hLib); + m_hLib = NULL; + } +} + +//--------------------------------------------------------------------- +FARPROC CEXTFSK::GetProc(LPCSTR pName) +{ + FARPROC fn = ::GetProcAddress(m_hLib, pName+1); + if( fn == NULL ){ + fn = ::GetProcAddress(m_hLib, pName); + } + return fn; +} + +long __fastcall CEXTFSK::Open(long para) +{ + if( !m_hLib || !fextfskOpen ) return FALSE; + return fextfskOpen(para); +} + +void __fastcall CEXTFSK::Close(void) +{ + if( !m_hLib || !fextfskClose ) return; + fextfskClose(); +} + +long __fastcall CEXTFSK::IsTxBusy(void) +{ + if( !m_hLib || !fextfskIsTxBusy ) return FALSE; + return fextfskIsTxBusy(); +} + +void __fastcall CEXTFSK::PutChar(BYTE c) +{ + if( !m_hLib || !fextfskPutChar ) return; + fextfskPutChar(c); +} + +void __fastcall CEXTFSK::SetPTT(long tx) +{ + if( !m_hLib || !fextfskSetPTT ) return; + fextfskSetPTT(tx); +} + diff --git a/Comm.h b/Comm.h new file mode 100644 index 0000000..1b153dc --- /dev/null +++ b/Comm.h @@ -0,0 +1,114 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +///---------------------------------------------------------- +/// RS232C通信クラス +/// +/// (C) JE3HHT Makoto.Mori +/// +//--------------------------------------------------------------------------- +#ifndef CommH +#define CommH +#include "sstv.h" +//--------------------------------------------------------------------------- +#include //JA7UDE 0428 +//--------------------------------------------------------------------------- +#define CR 0x0d +#define LF 0x0a +#define COMM_CLOSE 1 + +typedef struct { + int change; + + int Baud; + int BitLen; + int Stop; + int Parity; +}COMMPARA; +extern COMMPARA COMM; + +typedef long (__stdcall *extfskOpen)(long para); +typedef void (__stdcall *extfskClose)(void); +typedef long (__stdcall *extfskIsTxBusy)(void); +typedef void (__stdcall *extfskPutChar)(BYTE c); +typedef void (__stdcall *extfskSetPTT)(long tx); + +class CEXTFSK +{ +private: + //HANDLE m_hLib; //ja7ude 0521 + HINSTANCE m_hLib; + extfskOpen fextfskOpen; + extfskClose fextfskClose; + extfskIsTxBusy fextfskIsTxBusy; + extfskPutChar fextfskPutChar; + extfskSetPTT fextfskSetPTT; +private: + FARPROC GetProc(LPCSTR pName); + +public: + __fastcall CEXTFSK(LPCSTR pName); + __fastcall ~CEXTFSK(); + long __fastcall IsLib(void){return m_hLib != NULL;}; + long __fastcall Open(long para); + void __fastcall Close(void); + long __fastcall IsTxBusy(void); + void __fastcall PutChar(BYTE c); + void __fastcall SetPTT(long tx); +}; + +#define COMM_TXBUFSIZE MODBUFMAX +class CComm +{ +public: + BOOL m_CreateON; // クリエイトフラグ + volatile int m_Command; + DCB m_dcb; // DCB + HANDLE m_fHnd; // ファイルハンドル + + int m_ptt; + int m_scan; + CEXTFSK *m_pEXT; +protected: +private: + int __fastcall PTTOpen(void); + +public: + __fastcall CComm(void); + __fastcall ~CComm(){ + Close(); + }; + inline BOOL __fastcall IsOpen(void){ + return m_CreateON; + }; + BOOL __fastcall Open(LPCTSTR PortName); + void __fastcall Close(void); + int __fastcall SetPTT(void); + void __fastcall SetPTT(int sw); + void __fastcall SetScan(int sw); +}; + +void InitCOMMPara(void); +#endif + + + + + + diff --git a/ConvDef.cpp b/ConvDef.cpp new file mode 100644 index 0000000..093c335 --- /dev/null +++ b/ConvDef.cpp @@ -0,0 +1,401 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "ConvDef.h" +//--------------------------------------------------------------------- +#pragma resource "*.dfm" +//TConvDefDlg *ConvDefDlg; +//--------------------------------------------------------------------- +__fastcall TConvDefDlg::TConvDefDlg(TComponent* AOwner) + : TForm(AOwner) +{ + FormStyle = ((TForm *)AOwner)->FormStyle; + Font->Name = ((TForm *)AOwner)->Font->Name; + Font->Charset = ((TForm *)AOwner)->Font->Charset; + if( MsgEng ){ + Caption = "Define Conversion"; + ConvSel->Caption = "Delimiter Type"; + ConvSel->Items->Strings[0] = "comma(,)"; + ConvSel->Items->Strings[1] = "TAB"; + ConvSel->Items->Strings[2] = "NONE"; + LConv->Caption = "Conv."; + CheckDBL->Caption = "Double"; + GrpRef->Caption = "Ref."; + SBBack->Caption = "<"; + SBNext->Caption = ">"; + CancelBtn->Caption = "Cancel"; + InitBtn->Caption = "All Del"; + UpBtn->Caption = "Up"; + DownBtn->Caption = "Down"; + InitMax->Caption = "Init Max"; + } + + Grid->RowCount = TEXTCONVMAX + 1; + m_Mode = 0; + m_Bgn = m_End = m_Cur = 0; + m_DisEvent = 0; +} +//--------------------------------------------------------------------- +void __fastcall TConvDefDlg::UpdateUI(int n) +{ + SBBack->Enabled = m_Cur > m_Bgn ? TRUE : FALSE; + SBNext->Enabled = m_Cur < m_End ? TRUE : FALSE; + UpBtn->Enabled = (n > 0) ? TRUE : FALSE; + DownBtn->Enabled = (n < TEXTCONVMAX - 1) ? TRUE : FALSE; + CheckDBL->Enabled = m_Mode && (ConvSel->ItemIndex < 2); +} +//--------------------------------------------------------------------- +void __fastcall TConvDefDlg::GridDrawCell(TObject *Sender, int Col, + int Row, TRect &Rect, TGridDrawState State) +{ + char bf[1024]; + SDMMLOG sd; + + Grid->Canvas->FillRect(Rect); + int X = Rect.Left + 4; + int Y = Rect.Top + 2; + + if( Row ){ + Row--; + bf[0] = 0; + switch(Col){ + case 0: // Key + strcpy(bf, Conv[Row].Key.c_str()); + break; + case 1: // Size + if( !Conv[Row].Key.IsEmpty() && (Conv[Row].Key != "%EOD") ){ + sprintf(bf, "%u", Conv[Row].w); + } + break; + case 2: // Data + if( m_Mode ){ + if( !Conv[Row].Key.IsEmpty() && (Conv[Row].Key != "%EOD") ){ + Log.GetData(&sd, m_Cur); + MMLOG2Text(bf, &sd, Conv[Row].Key); + } + } + else { + strcpy(bf, m_line[Row].c_str()); + } + break; + } + Grid->Canvas->TextOut(X, Y, bf); + } + else if( MsgEng ){ + LPCSTR _tte[]={ + "Conv.","Max","Ref.", + }; + Grid->Canvas->TextOut(X, Y, _tte[Col]); + } + else { // タイトル + LPCSTR _tt[]={ + "変換式","Max","参照", + }; + Grid->Canvas->TextOut(X, Y, _tt[Col]); + } +} +//--------------------------------------------------------------------- +void __fastcall TConvDefDlg::SetupComBox(void) +{ + m_DisEvent++; + ConvText->Clear(); + int i; + for( i = 0; ConvTbl[i] != NULL; i++ ){ + ConvText->Items->Add(ConvTbl[i]); + } + m_DisEvent--; +} +//--------------------------------------------------------------------- +int __fastcall TConvDefDlg::Execute(TCONV *tp, int &delm, int &utc, int &dbl, int b, int e) +{ + m_DisEvent++; + int i; + for( i = 0; i < TEXTCONVMAX; i++ ){ + Conv[i].Key = tp[i].Key; + Conv[i].w = tp[i].w; + } + m_Mode = 1; + m_Cur = m_Bgn = b; + m_End = e; + CheckUTC->Checked = utc; + ConvSel->ItemIndex = delm; + CheckDBL->Checked = dbl; + SetupComBox(); + ConvText->Text = Conv[0].Key; + UpdateUI(Grid->Row - 1); + m_DisEvent--; + if( ShowModal() == IDOK ){ + for( i = 0; i < TEXTCONVMAX; i++ ){ + tp[i].Key = Conv[i].Key; + tp[i].w = Conv[i].w; + } + delm = ConvSel->ItemIndex; + utc = CheckUTC->Checked; + dbl = CheckDBL->Checked; + return TRUE; + } + else { + return FALSE; + } +} +//--------------------------------------------------------------------- +int __fastcall TConvDefDlg::Execute(TCONV *tp, int &delm, int &utc, int &dbl, LPCSTR pName) +{ + m_DisEvent++; + int i; + for( i = 0; i < TEXTCONVMAX; i++ ){ + Conv[i].Key = tp[i].Key; + Conv[i].w = tp[i].w; + } + m_Mode = 0; + CheckUTC->Checked = utc; + ConvSel->ItemIndex = delm; + CheckDBL->Checked = dbl; + SetupComBox(); + ConvText->Text = Conv[0].Key; + LoadText(pName); + UpdateUI(Grid->Row - 1); + UpdateLine(); + m_DisEvent--; + if( ShowModal() == IDOK ){ + for( i = 0; i < TEXTCONVMAX; i++ ){ + tp[i].Key = Conv[i].Key; + tp[i].w = Conv[i].w; + } + delm = ConvSel->ItemIndex; + utc = CheckUTC->Checked; + dbl = CheckDBL->Checked; + return TRUE; + } + else { + return FALSE; + } +} +//--------------------------------------------------------------------- +void __fastcall TConvDefDlg::LoadText(LPCSTR pName) +{ + FILE *fp; + char bf[2048]; + + m_Cur = m_Bgn = m_End = 0; + if( (fp = fopen(pName, "rt")) != NULL ){ + while(!feof(fp)){ + if( fgets(bf, sizeof(bf), fp) != NULL ){ + ClipLF(bf); + m_text[m_End] = bf; + m_End++; + if( m_End >= PREREADMAX ) break; + } + } + fclose(fp); + } + if( m_End ) m_End--; +} +//--------------------------------------------------------------------- +void __fastcall TConvDefDlg::UpdateLine(void) +{ + char rbf[2048]; + + StrCopy(rbf, m_text[m_Cur].c_str(), 2043); + + char bf[512]; + char dlm = ConvSel->ItemIndex ? TAB : ','; + LPSTR p, t; + + int i; + p = rbf; + for( i = 0; i < TEXTCONVMAX; i++ ){ + if( ConvSel->ItemIndex == 2 ){ + StrCopy(bf, p, Conv[i].w); + p += strlen(bf); + t = bf; + } + else { + p = StrDlm(t, p, dlm); + } + clipsp(t); + t = SkipSpace(t); + m_line[i] = t; + } +} +//--------------------------------------------------------------------------- +void __fastcall TConvDefDlg::ConvTextChange(TObject *Sender) +{ + if( m_DisEvent ) return; + + m_DisEvent++; + if( Grid->Row ){ + int Row = Grid->Row - 1; + Conv[Row].Key = ConvText->Text; + Grid->Invalidate(); + } + m_DisEvent--; +} +//--------------------------------------------------------------------------- +void __fastcall TConvDefDlg::GridSelectCell(TObject *Sender, int Col, + int Row, bool &CanSelect) +{ + if( m_DisEvent ) return; + + m_DisEvent++; + if( Row ){ + Row--; + ConvText->Text = Conv[Row].Key; + UpdateUI(Row); + } + m_DisEvent--; +} +//--------------------------------------------------------------------------- +void __fastcall TConvDefDlg::SBBackClick(TObject *Sender) +{ + if( m_Cur > m_Bgn ){ + m_Cur--; + UpdateUI(Grid->Row - 1); + if( !m_Mode ) UpdateLine(); + Grid->Invalidate(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TConvDefDlg::SBNextClick(TObject *Sender) +{ + if( m_Cur < m_End ){ + m_Cur++; + UpdateUI(Grid->Row - 1); + if( !m_Mode ) UpdateLine(); + Grid->Invalidate(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TConvDefDlg::GridGetEditText(TObject *Sender, int ACol, + int ARow, AnsiString &Value) +{ + char bf[512]; + + if( ARow ) ARow--; + bf[0] = 0; + switch(ACol){ + case 0: // Key + strcpy(bf, Conv[ARow].Key.c_str()); + break; + case 1: // Size + if( !Conv[ARow].Key.IsEmpty() && (Conv[ARow].Key != "%EOD") ){ + sprintf(bf, "%u", Conv[ARow].w); + } + break; + case 2: // Data + break; + } + Value = bf; +} +//--------------------------------------------------------------------------- +void __fastcall TConvDefDlg::GridSetEditText(TObject *Sender, int ACol, + int ARow, const AnsiString Value) +{ + int d; + + if( ARow ) ARow--; + switch(ACol){ + case 0: // Key + Conv[ARow].Key = Value; + Grid->Invalidate(); + break; + case 1: // Size + sscanf(Value.c_str(), "%u", &d); + if( (d >= 0) && (d<=256) ){ + Conv[ARow].w = d; + if( !m_Mode ){ + UpdateLine(); + Grid->Invalidate(); + } + } + break; + case 2: // Data + break; + } +} +//--------------------------------------------------------------------------- +void __fastcall TConvDefDlg::InitBtnClick(TObject *Sender) +{ + if( YesNoMB( MsgEng ? "Delete All setup. Are you sure?":"すべての定義を消去しますか?" ) == IDYES ){ + for( int i = 0; i < TEXTCONVMAX; i++ ){ + Conv[i].Key = ""; + Conv[i].w = 0; + } + Grid->Invalidate(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TConvDefDlg::UpBtnClick(TObject *Sender) +{ + int n = Grid->Row - 1; + if( n ){ + TCONV td = Conv[n]; + Conv[n] = Conv[n-1]; + Conv[n-1] = td; + Grid->Row--; + UpdateUI(Grid->Row - 1); + Grid->Invalidate(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TConvDefDlg::DownBtnClick(TObject *Sender) +{ + int n = Grid->Row - 1; + + if( n < (TEXTCONVMAX - 1) ){ + TCONV td = Conv[n]; + Conv[n] = Conv[n+1]; + Conv[n+1] = td; + Grid->Row++; + UpdateUI(Grid->Row - 1); + Grid->Invalidate(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TConvDefDlg::InitMaxClick(TObject *Sender) +{ + if( YesNoMB( MsgEng ? "Delete All Length. Are you sure?":"すべての文字列長の制限を無くしますか?" ) == IDYES ){ + for( int i = 0; i < TEXTCONVMAX; i++ ){ + Conv[i].w = 0; + } + Grid->Invalidate(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TConvDefDlg::ConvSelClick(TObject *Sender) +{ + UpdateUI(Grid->Row-1); + if( !m_Mode ){ + UpdateLine(); + Grid->Invalidate(); + } +} +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- + diff --git a/ConvDef.dfm b/ConvDef.dfm new file mode 100644 index 0000000..a0b4c0e Binary files /dev/null and b/ConvDef.dfm differ diff --git a/ConvDef.h b/ConvDef.h new file mode 100644 index 0000000..30a59b9 --- /dev/null +++ b/ConvDef.h @@ -0,0 +1,104 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//---------------------------------------------------------------------------- +#ifndef ConvDefH +#define ConvDefH +//---------------------------------------------------------------------------- +// JA7UDE 0428 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//---------------------------------------------------------------------------- +#include "LogConv.h" +//---------------------------------------------------------------------------- +#define PREREADMAX 100 +class TConvDefDlg : public TForm +{ +__published: + TButton *OKBtn; + TButton *CancelBtn; + TStringGrid *Grid; + TComboBox *ConvText; + TLabel *LConv; + TGroupBox *GrpRef; + TSpeedButton *SBBack; + TSpeedButton *SBNext; + TRadioGroup *ConvSel; + TButton *InitBtn; + TButton *UpBtn; + TButton *DownBtn; + TButton *InitMax; + TCheckBox *CheckUTC; + TCheckBox *CheckDBL;void __fastcall ConvTextChange(TObject *Sender); + void __fastcall SBBackClick(TObject *Sender); + void __fastcall SBNextClick(TObject *Sender); + + + void __fastcall InitBtnClick(TObject *Sender); + void __fastcall UpBtnClick(TObject *Sender); + void __fastcall DownBtnClick(TObject *Sender); + void __fastcall InitMaxClick(TObject *Sender); + void __fastcall ConvSelClick(TObject *Sender); + void __fastcall GridSetEditText(TObject *Sender, int ACol, int ARow, + const AnsiString Value); + void __fastcall GridSelectCell(TObject *Sender, int Col, int Row, + bool &CanSelect); + void __fastcall GridGetEditText(TObject *Sender, int ACol, int ARow, + AnsiString &Value); + void __fastcall GridDrawCell(TObject *Sender, int Col, int Row, + TRect &Rect, TGridDrawState State); +private: + TCONV Conv[TEXTCONVMAX]; + + int m_Mode; + int m_DisEvent; + + int m_Bgn; + int m_End; + int m_Cur; + + void __fastcall UpdateUI(int n); + void __fastcall SetupComBox(void); + + AnsiString m_text[PREREADMAX]; + AnsiString m_line[TEXTCONVMAX]; + + void __fastcall LoadText(LPCSTR pName); + void __fastcall UpdateLine(void); + +public: + virtual __fastcall TConvDefDlg(TComponent* AOwner); + + int __fastcall Execute(TCONV *tp, int &delm, int &utc, int &dbl, int b, int e); + int __fastcall Execute(TCONV *tp, int &delm, int &utc, int &dbl, LPCSTR pName); +}; +//---------------------------------------------------------------------------- +//extern TConvDefDlg *ConvDefDlg; +//---------------------------------------------------------------------------- +#endif diff --git a/CtrBtn.cpp b/CtrBtn.cpp new file mode 100644 index 0000000..f0fdf2d --- /dev/null +++ b/CtrBtn.cpp @@ -0,0 +1,123 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "CtrBtn.h" +#include "Main.h" +//--------------------------------------------------------------------------- +#pragma package(smart_init) +#pragma resource "*.dfm" +//TCtrBtnWnd *CtrBtnWnd; +//--------------------------------------------------------------------------- +__fastcall TCtrBtnWnd::TCtrBtnWnd(TComponent* Owner) + : TForm(Owner) +{ + Font->Name = sys.m_WinFontName; + Font->Charset = sys.m_WinFontCharset; + if( MsgEng ){ + SBRXStop->Caption = "Stop RX"; + SBLock->Caption = "Lock RX"; +// SBSync->Caption = "ReSync"; + SBHist->Caption = "CopyHist"; + SBTX->Caption = "TX(F9)"; + } + SBSync->Caption = Mmsstv->KRFS->Caption; + AlignView.EntryControl(SBRXStop, this, SBRXStop->Font); + AlignView.EntryControl(SBLock, this, SBLock->Font); + AlignView.EntryControl(SBSync, this, SBSync->Font); + AlignView.EntryControl(SBHist, this, SBHist->Font); + AlignView.EntryControl(SBTX, this, SBTX->Font); + SBTX->OnMouseDown = Mmsstv->SBTXMouseDown; +// Caption = ""; +} +//--------------------------------------------------------------------------- +void __fastcall TCtrBtnWnd::UpdateBtn(void) +{ + if( Mmsstv->pDem->m_Sync ){ + SBRXStop->Enabled = TRUE; + SBSync->Enabled = (SSTVSET.m_Mode != smAVT) ? TRUE : FALSE; + } + else { + SBRXStop->Enabled = (Mmsstv->pDem->m_SyncMode != -1) ? FALSE : TRUE; + SBSync->Enabled = FALSE; + SBRXStop->Down = SBRXStop->Enabled; + } + SBLock->Down = Mmsstv->SBLK->Down; + SBHist->Enabled = Mmsstv->SBWHist->Enabled && !Mmsstv->pDem->m_Sync; + SBTX->Down = Mmsstv->SBTX->Down; + if( sys.m_Repeater ) SBTX->Update(); +} +//--------------------------------------------------------------------------- +void __fastcall TCtrBtnWnd::SBRXStopClick(TObject *Sender) +{ + Mmsstv->RxAutoPush(TRUE); + UpdateBtn(); +} +//--------------------------------------------------------------------------- +void __fastcall TCtrBtnWnd::SBHistClick(TObject *Sender) +{ + Mmsstv->SBWHistClick(NULL); + if( Mmsstv->pSound->m_Tx && !Mmsstv->SBTune->Down && Mmsstv->SBUseTemp->Down ){ + MultProc(); + Mmsstv->SBUseTemp->Down = FALSE; + Mmsstv->SBUseTempClick(NULL); + } + UpdateBtn(); +} +//--------------------------------------------------------------------------- +void __fastcall TCtrBtnWnd::SBTXClick(TObject *Sender) +{ + Mmsstv->AdjustPage(pgTX); + Mmsstv->SBTX->Down = Mmsstv->SBTX->Down ? FALSE : TRUE; + Mmsstv->SBTXClick(NULL); + UpdateBtn(); +} +//--------------------------------------------------------------------------- +void __fastcall TCtrBtnWnd::FormKeyDown(TObject *Sender, WORD &Key, + TShiftState Shift) +{ + Mmsstv->FormKeyDown(Sender, Key, Shift); +} +//--------------------------------------------------------------------------- +void __fastcall TCtrBtnWnd::FormKeyUp(TObject *Sender, WORD &Key, + TShiftState Shift) +{ + Mmsstv->FormKeyUp(Sender, Key, Shift); +} +//--------------------------------------------------------------------------- +void __fastcall TCtrBtnWnd::FormResize(TObject *Sender) +{ + AlignView.NewAlign(this); +} +//--------------------------------------------------------------------------- +void __fastcall TCtrBtnWnd::SBLockClick(TObject *Sender) +{ + Mmsstv->SBLK->Down = SBLock->Down; + Mmsstv->SBLKClick(NULL); +} +//--------------------------------------------------------------------------- +void __fastcall TCtrBtnWnd::SBSyncClick(TObject *Sender) +{ + Mmsstv->KRFSClick(NULL); +} +//--------------------------------------------------------------------------- + diff --git a/CtrBtn.dfm b/CtrBtn.dfm new file mode 100644 index 0000000..a53a64e Binary files /dev/null and b/CtrBtn.dfm differ diff --git a/CtrBtn.h b/CtrBtn.h new file mode 100644 index 0000000..da76931 --- /dev/null +++ b/CtrBtn.h @@ -0,0 +1,75 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------------- +#ifndef CtrBtnH +#define CtrBtnH +//--------------------------------------------------------------------------- +#include +#include +#include +#include +#include +//--------------------------------------------------------------------------- +#include "ComLib.h" +//--------------------------------------------------------------------------- +class TCtrBtnWnd : public TForm +{ +__published: // IDE 管理のコンポーネント + TSpeedButton *SBRXStop; + TSpeedButton *SBHist; + TSpeedButton *SBTX; + TSpeedButton *SBLock; + TSpeedButton *SBSync; + void __fastcall SBTXClick(TObject *Sender); + void __fastcall SBRXStopClick(TObject *Sender); + void __fastcall SBHistClick(TObject *Sender); + void __fastcall FormKeyDown(TObject *Sender, WORD &Key, + TShiftState Shift); + void __fastcall FormKeyUp(TObject *Sender, WORD &Key, + TShiftState Shift); + void __fastcall FormResize(TObject *Sender); + void __fastcall SBLockClick(TObject *Sender); + + void __fastcall SBSyncClick(TObject *Sender); + +private: // ユーザー宣言 + CAlignList AlignView; + +public: // ユーザー宣言 + __fastcall TCtrBtnWnd(TComponent* Owner); + void __fastcall UpdateBtn(void); + void __fastcall GetViewPos(int &x, int &y, int &w, int &h){ + x = Left; + y = Top; + w = ClientWidth; + h = ClientHeight; + }; + void __fastcall SetViewPos(int x, int y, int w, int h){ + Left = x; + Top = y; + ClientWidth = w; + ClientHeight = h; + }; +}; +//--------------------------------------------------------------------------- +//extern PACKAGE TCtrBtnWnd *CtrBtnWnd; +//--------------------------------------------------------------------------- +#endif + diff --git a/Draw.cpp b/Draw.cpp new file mode 100644 index 0000000..2652b9d --- /dev/null +++ b/Draw.cpp @@ -0,0 +1,5929 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "Draw.h" +#include "main.h" + +#include "LineSet.h" +#include "TextIn.h" +#include "ColorBar.h" +#include "PicSel.h" +#include "PicRect.h" +#include "MacroKey.h" +#include "ColorSet.h" +#include "ZoomView.h" +#include "PicFilte.h" + +TColor TransCol; +CDrawGroup DrawPara; +CLIBL Libl; + +LPCSTR _ShapePIC[2][7]={ + { "Rectangle", "Round Rect 1", "Round Rect 2", "Round Rect 3", "Ellipse", "Polygon", NULL }, + { "長方形", "丸長方形1", "丸長方形2", "丸長方形3", "楕円", "多角形", NULL }, +}; +LPCSTR _ShapeBOX[2][7]={ + { "Rectangle", "Round Rect 1", "Round Rect 2", "Round Rect 3", "Ellipse", "Circle", NULL }, + { "長方形", "丸長方形1", "丸長方形2", "丸長方形3", "楕円", "円", NULL }, +}; + +int SXW; +int SYW; +void __fastcall SetDrawSize(int x, int y) +{ + if( x >= 320 ) SXW = x; + if( y >= 256 ) SYW = y; +} +//--------------------------------------------------------------------------- +static CDrawText CurText; +//--------------------------------------------------------------------------- +int __fastcall IsInside(POINT &pnt, RECT &rc) +{ + if( rc.left < rc.right ){ + if( pnt.x < rc.left ) return FALSE; + if( pnt.x > rc.right ) return FALSE; + } + else { + if( pnt.x > rc.left ) return FALSE; + if( pnt.x < rc.right ) return FALSE; + } + if( rc.top > rc.bottom ){ + if( pnt.y > rc.top ) return FALSE; + if( pnt.y < rc.bottom ) return FALSE; + } + else { + if( pnt.y < rc.top ) return FALSE; + if( pnt.y > rc.bottom ) return FALSE; + } + return TRUE; +} + +int __fastcall IsNear(POINT &pnt, POINT &tpnt, int Width) +{ + RECT rc; + rc.left = tpnt.x - Width; + rc.right = tpnt.x + Width; + rc.top = tpnt.y + Width; + rc.bottom = tpnt.y - Width; + return IsInside(pnt, rc); +} + +int __fastcall IsLine(POINT &pnt, POINT &spnt, POINT &tpnt, int Width) +{ + int Xw = tpnt.x - spnt.x; + int Yw = tpnt.y - spnt.y; + double A, B; + int C; + + if( IsNear(pnt, spnt, Width)==TRUE ){ + return HT_P1; /* 始点と一致 */ + } + else if( IsNear(pnt, tpnt, Width)==TRUE ){ + return HT_P2; /* 終点と一致 */ + } + if( spnt.x > tpnt.x ){ /* X方向の入れ替え */ + POINT bpnt = spnt; + spnt = tpnt; + tpnt = bpnt; + } + if( (pnt.x >= (spnt.x-Width)) && (pnt.x <= (tpnt.x+Width)) ){ + if( Xw ){ + A = double(Yw)/double(Xw); + B = double(spnt.y) - (A * double(spnt.x)); + C = int((A * double(pnt.x)) + B); + A = A < 0.0 ? -A : A; + if( A >= 1.0 ){ + Width = int(double(Width) * A); + } + if( (pnt.y < (C+Width)) && (pnt.y >= (C-Width)) ){ + return HT_PM; + } + } + else if( spnt.y > tpnt.y ){ + if( (pnt.y < spnt.y) && (pnt.y > tpnt.y) ){ + return HT_PM; + } + } + else if( (pnt.y > spnt.y) && (pnt.y < tpnt.y) ){ + return HT_PM; + } + } + return 0; +} + +int __fastcall IsLine(POINT &pnt, POINT &spnt, POINT &tpnt) +{ + int r = IsLine(pnt, spnt, tpnt, 4); + if( (r == HT_P1)||(r == HT_P2) ) return r; + return IsLine(pnt, spnt, tpnt, 10) ? HT_PM : 0; +} + +//--------------------------------------------------------------------------- +// 実現色を返す +TColor __fastcall GetNearestColor(TColor col) +{ + if( (sys.m_BitPixel < 24) && Mmsstv->pBitmapNearest ){ + TCanvas *pCanvas = Mmsstv->pBitmapNearest->Canvas; + pCanvas->Pixels[0][0] = TColor(col); + col = pCanvas->Pixels[0][0]; + } + return col; +} +//--------------------------------------------------------------------------- +TColor __fastcall GetUniqueColor(TColor col) +{ +#if 1 + col = TColor(DWORD(col) & 0x00f0f0f0); + COLD c; + c.c = col; + DWORD r; + + while(!c.d || (c.c == col)){ + r = rand(); r = r << 4; + c.b.r = (BYTE)(r & 0x00f0); r = r >> 4; + c.b.g = (BYTE)(r & 0x00f0); r = r >> 4; + c.b.b = (BYTE)(r & 0x00f0); + } + col = GetNearestColor(c.c); + return col; +#else + col = TColor(DWORD(col) & 0x00e0e0e0); + DWORD c = DWORD(col); + + while(!c || (c == DWORD(col))){ + + c = (rand() & 0x00e0) + ((rand() & 0x00e0) << 8) + ((rand() & 0x00e0) << 16); + } + col = GetNearestColor(TColor(c)); + return col; +#endif +} +//--------------------------------------------------------------------------- +HBITMAP __cdecl mmLoadImageMenu(DWORD sw, int xw, int yw) +{ + HBITMAP hb = NULL; + + int x = xw; + int y = yw; + if( sw ){ + x = 320; y = 256; + } + Graphics::TBitmap* pBitmap = CreateBitmap(x, y, pf24bit); + if( Mmsstv->LoadBitmapMenu(pBitmap, sw) ){ + hb = pBitmap->ReleaseHandle(); + } + delete pBitmap; + return hb; +} +//--------------------------------------------------------------------------- +HBITMAP __cdecl mmLoadImage(LPCSTR pName) +{ + HBITMAP hb = NULL; + + Graphics::TBitmap* pBitmap = new Graphics::TBitmap; + pBitmap->PixelFormat = pf24bit; + if( LoadImage(pBitmap, pName) ){ + hb = pBitmap->ReleaseHandle(); + } + delete pBitmap; + return hb; +} +//--------------------------------------------------------------------------- +HBITMAP __fastcall LoadRefImage(Graphics::TBitmap *pRef) +{ + Graphics::TBitmap* pBitmap = new Graphics::TBitmap; + pBitmap->PixelFormat = pf24bit; + CopyBitmap(pBitmap, pRef); + HBITMAP hb = pBitmap->ReleaseHandle(); + delete pBitmap; + return hb; +} +//--------------------------------------------------------------------------- +HBITMAP __cdecl mmLoadHistImage(void) +{ + return LoadRefImage(Mmsstv->pBitmapHist); +} +//--------------------------------------------------------------------------- +HBITMAP __cdecl mmLoadRxImage(void) +{ + return LoadRefImage(Mmsstv->pBitmapRX); +} +//--------------------------------------------------------------------------- +int __cdecl mmSaveImageMenu(HBITMAP hb, LPCSTR pName, LPCSTR pFolder) +{ + Graphics::TBitmap* pBitmap = new Graphics::TBitmap; + pBitmap->Handle = hb; + int r = Mmsstv->SaveBitmapMenu(pBitmap, pName, pFolder); + pBitmap->ReleaseHandle(); + delete pBitmap; + return r; +} +//--------------------------------------------------------------------------- +int __cdecl mmSaveImage(HBITMAP hb, LPCSTR pName) +{ + Graphics::TBitmap* pBitmap = new Graphics::TBitmap; + pBitmap->Handle = hb; + int r = SaveImage(pBitmap, pName); + pBitmap->ReleaseHandle(); + delete pBitmap; + return r; +} +//--------------------------------------------------------------------------- +HBITMAP __cdecl mmPasteImage(int sw, int xw, int yw) +{ + HBITMAP hb = NULL; + + int x = xw; + int y = yw; + if( sw ){ + x = 16; y = 16; + } + Graphics::TBitmap* pBitmap = CreateBitmap(x, y, pf24bit); + if( Mmsstv->PasteBitmap(pBitmap, sw) ){ + hb = pBitmap->ReleaseHandle(); + } + delete pBitmap; + return hb; +} +//--------------------------------------------------------------------------- +int __cdecl mmGetMacKey(LPSTR tDest, int len) +{ + int r = FALSE; + TMacroKeyDlg *pBox = new TMacroKeyDlg(Mmsstv); + AnsiString as; + if( pBox->Execute(as) > 0 ){ + StrCopy(tDest, as.c_str(), len - 1); + r = TRUE; + } + delete pBox; + return r; +} +//--------------------------------------------------------------------------- +int __cdecl mmConvMac(LPSTR tDest, LPCSTR pKey, int len) +{ + return Mmsstv->MacroText(tDest, pKey, len-1); +} +//--------------------------------------------------------------------------- +HBITMAP __cdecl mmCreateDIB(int xw, int yw) +{ + Graphics::TBitmap* pBitmap = CreateBitmap(xw, yw, pf24bit); + HBITMAP hb = pBitmap->ReleaseHandle(); + delete pBitmap; + return hb; +} +//--------------------------------------------------------------------------- +int __cdecl mmColorComp(LPDWORD pCol) +{ + TColorSetDlg *pBox = new TColorSetDlg(Mmsstv); + int r = pBox->Execute((TColor *)pCol); + delete pBox; + return r; +} +//--------------------------------------------------------------------------- +void __cdecl mmView(HBITMAP hb) +{ + Graphics::TBitmap* pBitmap = new Graphics::TBitmap; + pBitmap->Handle = hb; + TZoomViewDlg *pBox = new TZoomViewDlg(Mmsstv); + pBox->SetInitSize(pBitmap->Width, pBitmap->Height); + pBox->Execute(pBitmap, FALSE); + delete pBox; + pBitmap->ReleaseHandle(); + delete pBitmap; +} +//--------------------------------------------------------------------------- +int __cdecl mmAdjCol(HBITMAP hb) +{ + Graphics::TBitmap* pBitmap = new Graphics::TBitmap; + pBitmap->Handle = hb; + + TPicFilterDlg *pBox = new TPicFilterDlg(Mmsstv); + int r = pBox->Execute(pBitmap); + delete pBox; + pBitmap->ReleaseHandle(); + delete pBitmap; + return r; +} +//--------------------------------------------------------------------------- +int __cdecl mmClip(HBITMAP hbDest, HBITMAP hbSrc) +{ + Graphics::TBitmap* pSrc = new Graphics::TBitmap; + pSrc->Handle = hbSrc; + Graphics::TBitmap* pDest = new Graphics::TBitmap; + pDest->Handle = hbDest; + + TPicRectDlg *pBox = new TPicRectDlg(Mmsstv); + CopyBitmap(pBox->pBitmap, pSrc); + int r = pBox->Execute(pDest); + delete pBox; + pSrc->ReleaseHandle(); + pDest->ReleaseHandle(); + delete pSrc; delete pDest; + return r; +} +// +// +// +//--------------------------------------------------------------------------- +__fastcall CDraw::CDraw() +{ + m_Ver = 0; + m_Cursor = 0; + m_CX1 = m_CY1 = 0; + m_CX2 = m_CY2 = 0; + m_LineColor = clBlack; + m_LineStyle = psSolid; + m_LineWidth = 1; + m_X1 = m_Y1 = m_X2 = m_Y2 = 0; + m_BX = m_BY = m_MF = 0; + m_BoxStyle = 0; + pc = NULL; + pBox = NULL; +} + +void __fastcall CDraw::Start(TCanvas *tp, int x, int y) +{ + pc = tp; + m_CX1 = m_X1 = x; + m_CY1 = m_Y1 = y; +} + +void __fastcall CDraw::StartMove(TCanvas *tp, int x, int y, int code) +{ + pc = tp; + m_BX = x; + m_BY = y; + m_MF = 0; + m_MC = code; + m_CX1 = m_X1; + m_CX2 = m_X2; + m_CY1 = m_Y1; + m_CY2 = m_Y2; +} + +int __fastcall CDraw::Edit(void) +{ + TLineSetDlg *pBox = new TLineSetDlg(Mmsstv); + int r = pBox->Execute(this); + delete pBox; + return r; +} + +int __fastcall CDraw::Color(void) +{ + TColorDialog *pDialog = Mmsstv->ColorDialog; + InitCustomColor(pDialog); + AddCustomColor(pDialog, m_LineColor); + pDialog->Color = m_LineColor; + SetDisPaint(); + if( pDialog->Execute() == TRUE ){ + m_LineColor = pDialog->Color; + ResDisPaint(); + return TRUE; + } + ResDisPaint(); + return FALSE; +} + +void __fastcall CDraw::SaveToStream(TStream *sp) +{ + sp->Write(&m_Command, sizeof(m_Command)); + sp->Write(&m_Ver, sizeof(m_Ver)); + sp->Write(&m_X1, sizeof(m_X1)); + sp->Write(&m_Y1, sizeof(m_Y1)); + sp->Write(&m_X2, sizeof(m_X2)); + sp->Write(&m_Y2, sizeof(m_Y2)); + sp->Write(&m_LineColor, sizeof(m_LineColor)); + sp->Write(&m_LineStyle, sizeof(m_LineStyle)); + if( m_BoxStyle ){ + DWORD bver = 0x55aa0000; + sp->Write(&bver, sizeof(bver)); + sp->Write(&m_BoxStyle, sizeof(m_BoxStyle)); + } + sp->Write(&m_LineWidth, sizeof(m_LineWidth)); +} + +int __fastcall CDraw::LoadFromStream(TCanvas *tp, TStream *sp) +{ + try { + pc = tp; + sp->Read(&m_Ver, sizeof(m_Ver)); + sp->Read(&m_X1, sizeof(m_X1)); + sp->Read(&m_Y1, sizeof(m_Y1)); + sp->Read(&m_X2, sizeof(m_X2)); + sp->Read(&m_Y2, sizeof(m_Y2)); + sp->Read(&m_LineColor, sizeof(m_LineColor)); + sp->Read(&m_LineStyle, sizeof(m_LineStyle)); + DWORD bver; + sp->Read(&bver, sizeof(bver)); + if( (bver & 0xffff0000) != 0x55aa0000 ){ + m_LineWidth = bver; + m_BoxStyle = 0; + } + else { + bver &= 0x0000ffff; + sp->Read(&m_BoxStyle, sizeof(m_BoxStyle)); + sp->Read(&m_LineWidth, sizeof(m_LineWidth)); + } +// sp->Read(&m_LineWidth, sizeof(m_LineWidth)); + return TRUE; + } + catch(...){ + return FALSE; + } +} + +void __fastcall CDraw::SaveBitmap(TStream *sp, Graphics::TBitmap *pBitmap) +{ + int xw = 0; + int yw = 0; + if( pBitmap != NULL ){ + xw = pBitmap->Width; + yw = pBitmap->Height; + } + sp->Write(&xw, sizeof(xw)); + sp->Write(&yw, sizeof(yw)); + if( xw && yw ){ + pBitmap->SaveToStream(sp); + } +} + +int __fastcall CDraw::LoadBitmap(TStream *sp, Graphics::TBitmap *pBitmap) +{ + try { + int xw; + int yw; + sp->Read(&xw, sizeof(xw)); + sp->Read(&yw, sizeof(yw)); + if( xw && yw ){ + pBitmap->LoadFromStream(sp); + } + return TRUE; + } + catch(...){ + return FALSE; + } +} + +void __fastcall CDraw::Copy(CDraw *dp) +{ + m_X1 = dp->m_X1; + m_Y1 = dp->m_Y1; + m_X2 = dp->m_X2; + m_Y2 = dp->m_Y2; + m_LineColor = dp->m_LineColor; + m_LineStyle = dp->m_LineStyle; + m_LineWidth = dp->m_LineWidth; + m_BoxStyle = dp->m_BoxStyle; + pc = dp->pc; +} + +void __fastcall CDraw::SaveString(TStream *sp, AnsiString &as) +{ + int len = strlen(as.c_str()); + sp->Write(&len, sizeof(len)); + if( len ){ + sp->Write(as.c_str(), len); + } +} + +void __fastcall CDraw::LoadString(TStream *sp, AnsiString &as) +{ + int len; + sp->Read(&len, sizeof(len)); + if( len ){ + LPSTR bp = new char[len + 1]; + sp->Read(bp, len); + bp[len] = 0; + as = bp; + delete bp; + } + else { + as = ""; + } +} + +TColor __fastcall GetCol(TColor c1, TColor c2, int x, int xw) +{ + if( xw ){ + int R1 = DWORD(c1) & 0x000000ff; + int G1 = (DWORD(c1) >> 8) & 0x000000ff; + int B1 = (DWORD(c1) >> 16) & 0x000000ff; + int R2 = DWORD(c2) & 0x000000ff; + int G2 = (DWORD(c2) >> 8) & 0x000000ff; + int B2 = (DWORD(c2) >> 16) & 0x000000ff; + if( x > xw ) x = xw; + R1 += (R2 - R1) * x / xw; + G1 += (G2 - G1) * x / xw; + B1 += (B2 - B1) * x / xw; + LimitRGB(R1, G1, B1); + return TColor((B1 << 16) + (G1 << 8) + R1); + } + else { + return c1; + } +} + +void __fastcall CDraw::Normal(void) +{ + NormalRect(m_X1, m_Y1, m_X2, m_Y2); +} + +void __fastcall CDraw::AdjustRect(void) +{ + int XW = SXW - 1; + int YW = SYW - 1; + if( m_X1 > XW ){ + m_X1 = XW - (m_X2 - m_X1); + m_X2 = XW; + } + else if( m_X2 < 0 ){ + m_X2 = m_X2 - m_X1; + m_X1 = 0; + } + if( m_Y1 > YW ){ + m_Y1 = YW - (m_Y2 - m_Y1); + m_Y2 = YW; + } + else if( m_Y2 < 0 ){ + m_Y2 = m_Y2 - m_Y1; + m_Y1 = 0; + } + +} + +//--------------------------------------------------------------------------- +__fastcall CDrawLine::CDrawLine() +{ + m_Command = CM_LINE; + m_Cursor = 0; +} + +int __fastcall CDrawLine::Finish(int x, int y) +{ + m_X2 = x; + m_Y2 = y; + return ((m_X1 != m_X2)||(m_Y1 != m_Y2)) ? TRUE : FALSE; +} + +void __fastcall DrawSiege(TCanvas *tp, int X1, int Y1, int X2, int Y2, TColor SCol, int e) +{ + e = (e == 5) ? 4 : 3; + int x1 = X1; + int y1 = Y1; + int x2 = X2; + int y2 = Y2; + TColor col = SCol; + TColor tcol = SCol == clBlack ? clWhite : clBlack; + int i; + for( i = 0; i < e; i++ ){ + tp->Pen->Color = GetCol(col, tcol, i, e); + tp->MoveTo(x1, y1); + tp->LineTo(x2, y2); + if( ABS(x2 - x1) > ABS(y2 - y1) ){ + y1--; y2--; + } + else { + x1--; x2--; + } + } + x1 = X1; + y1 = Y1; + x2 = X2; + y2 = Y2; + for( i = 0; i < e; i++ ){ + tp->Pen->Color = GetCol(col, tcol, i, e); + tp->MoveTo(x1, y1); + tp->LineTo(x2, y2); + if( ABS(x2 - x1) > ABS(y2 - y1) ){ + y1++; y2++; + } + else { + x1++; x2++; + } + } +} + +void __fastcall CDrawLine::Draw(TCanvas *tp) +{ + tp->Pen->Color = m_LineColor; + if( m_LineStyle >= 5 ){ + tp->Pen->Style = psSolid; + tp->Pen->Width = 1; + DrawSiege(tp, m_X1, m_Y1, m_X2, m_Y2, m_LineColor, m_LineStyle); + } + else if( m_LineStyle >= 0 ){ + tp->Pen->Style = m_LineStyle; + tp->Pen->Width = m_LineWidth; + tp->MoveTo(m_X1, m_Y1); + tp->LineTo(m_X2, m_Y2); + } +} + +void __fastcall CDrawLine::DrawSel(TCanvas *tp, int sw) +{ + tp->Pen->Color = clBlue; + tp->Pen->Style = psDot; + tp->Pen->Width = 1; + tp->MoveTo(m_X1, m_Y1); + int rop = ::SetROP2(tp->Handle, sw ? R2_NOT : R2_COPYPEN); + tp->LineTo(m_X2, m_Y2); + ::SetROP2(tp->Handle, rop); +} + +void __fastcall CDrawLine::DrawCursor(void) +{ + pc->Pen->Style = psDot; + pc->Pen->Width = 1; + pc->MoveTo(m_CX1, m_CY1); + int Sop = ::SetROP2(pc->Handle, R2_NOT); + pc->LineTo(m_CX2, m_CY2); + ::SetROP2(pc->Handle, Sop); +} + +void __fastcall CDrawLine::Making(int x, int y) +{ + if( m_Cursor ) DrawCursor(); + m_CX2 = x; + m_CY2 = y; + DrawCursor(); + m_Cursor = 1; +} + +int __fastcall CDrawLine::HitTest(int x, int y) +{ + POINT N; + POINT B, E; + N.x = x; N.y = y; + B.x = m_X1; B.y = m_Y1; + E.x = m_X2; E.y = m_Y2; + return IsLine(N, B, E, 5) ? HT_I : HT_NONE; +} + +void __fastcall CDrawLine::Moving(int x, int y) +{ + if( m_Cursor ) DrawCursor(); + if( !m_MF ){ + if( m_BX != x ) m_MF = 1; + if( m_BY != y ) m_MF = 1; + } + x -= m_BX; + y -= m_BY; + m_CX1 = m_X1 + x; + m_CX2 = m_X2 + x; + m_CY1 = m_Y1 + y; + m_CY2 = m_Y2 + y; + DrawCursor(); + m_Cursor = 1; +} + +void __fastcall CDrawLine::Move(int x, int y) +{ + m_X1 = m_CX1; + m_Y1 = m_CY1; + m_X2 = m_CX2; + m_Y2 = m_CY2; +} + +//--------------------------------------------------------------------------- +__fastcall CDrawBox::CDrawBox() +{ + m_Command = CM_BOX; +} + +int __fastcall CDrawBox::Finish(int x, int y) +{ + m_X2 = x; + m_Y2 = y; + Normal(); + return ((m_X1 != m_X2)&&(m_Y1 != m_Y2)) ? TRUE : FALSE; +} + +static void __fastcall DBox(TCanvas *tp, int cmd, int x1, int y1, int x2, int y2) +{ + int xw = ABS(x2 - x1); + int yw = ABS(y2 - y1); + switch(cmd){ + case 0: + tp->MoveTo(x1, y1); + tp->LineTo(x2, y1); + tp->LineTo(x2, y2); + tp->LineTo(x1, y2); + tp->LineTo(x1, y1); + break; + case 1: + tp->RoundRect(x1, y1, x2, y2, xw/3, yw/3); + break; + case 2: + tp->RoundRect(x1, y1, x2, y2, xw/2, yw/2); + break; + case 3: + tp->RoundRect(x1, y1, x2, y2, xw*3/4, yw*3/4); + break; + case 4: + case 5: + tp->Ellipse(x1, y1, x2, y2); + break; + } +} + +void __fastcall CDrawBox::RoundRect(TCanvas *tp, int xw, int yw) +{ + if( m_LineStyle < 0 ) return; + + if( m_LineStyle >= 5 ){ + int e = (m_LineStyle == 5) ? 4 : 3; + tp->Pen->Style = psSolid; + tp->Pen->Width = 1; + int x1 = m_X1; + int y1 = m_Y1; + int x2 = m_X2; + int y2 = m_Y2; + int xxw = xw; + int yyw = yw; + TColor col = m_LineColor; + TColor tcol = m_LineColor == clBlack ? clWhite : clBlack; +// TColor tcol = TColor(DWORD(m_LineColor) ^ 0x00ffffff); + int i; + for( i = 0; i < e; i++ ){ + tp->Pen->Color = GetCol(col, tcol, i, e); + tp->RoundRect(x1, y1, x2, y2, xxw, yyw); + x1--; y1--; + x2++; y2++; + xxw += 2; + yyw += 2; + } + x1 = m_X1+1; + y1 = m_Y1+1; + x2 = m_X2-1; + y2 = m_Y2-1; + xxw = xw; + yyw = yw; + for( i = 1; i < e; i++ ){ + tp->Pen->Color = GetCol(col, tcol, i, e); + tp->RoundRect(x1, y1, x2, y2, xxw, yyw); + x1++; y1++; + x2--; y2--; + xxw -= 2; + yyw -= 2; + } + } + else { + tp->Pen->Style = m_LineStyle; + tp->Pen->Width = m_LineWidth; + tp->RoundRect(m_X1, m_Y1, m_X2, m_Y2, xw, yw); + } +} + +void __fastcall CDrawBox::Draw(TCanvas *tp) +{ + tp->Pen->Color = m_LineColor; + int xw = m_X2 - m_X1; + int yw = m_Y2 - m_Y1; + HBRUSH hold = (HBRUSH)::SelectObject(tp->Handle, GetStockObject(NULL_BRUSH)); //ja7ude 0521 + switch(m_BoxStyle){ + case 0: + RoundRect(tp, 0, 0); + break; + case 1: + RoundRect(tp, xw/3, yw/3); + break; + case 2: + RoundRect(tp, xw/2, yw/2); + break; + case 3: + RoundRect(tp, xw*3/4, yw*3/4); + break; + case 4: + case 5: + RoundRect(tp, xw, yw); + break; + } + ::SelectObject(tp->Handle, hold); +} + +void __fastcall CDrawBox::DrawSel(TCanvas *tp, int sw) +{ + if( m_BoxStyle ){ + Draw(tp); + } + tp->Brush->Color = clWhite; + tp->Pen->Color = clBlue; + tp->Pen->Width = 1; + tp->Pen->Style = psDot; + tp->MoveTo(m_X1, m_Y1); + int rop = ::SetROP2(tp->Handle, sw ? R2_NOT : R2_COPYPEN); + tp->LineTo(m_X2, m_Y1); + tp->LineTo(m_X2, m_Y2); + tp->LineTo(m_X1, m_Y2); + tp->LineTo(m_X1, m_Y1); + ::SetROP2(tp->Handle, rop); +} + +void __fastcall CDrawBox::DrawCursor(void) +{ + pc->Pen->Style = psDot; + pc->Pen->Width = 1; + pc->MoveTo(m_CX1, m_CY1); + int Sop = ::SetROP2(pc->Handle, R2_NOT); + pc->LineTo(m_CX2, m_CY1); + pc->LineTo(m_CX2, m_CY2); + pc->LineTo(m_CX1, m_CY2); + pc->LineTo(m_CX1, m_CY1); + ::SetROP2(pc->Handle, Sop); +} + +void __fastcall CDrawBox::Making(int x, int y) +{ + if( m_Cursor ) DrawCursor(); + m_CX2 = x; + m_CY2 = y; + DrawCursor(); + m_Cursor = 1; +} + +int __fastcall CDrawBox::HitTest(int x, int y) +{ + POINT N; + POINT B, E; + N.x = x; N.y = y; + B.x = m_X1; B.y = m_Y1; + E.x = m_X2; E.y = m_Y1; + int r = IsLine(N, B, E, 5); + if( r ){ + switch(r){ + case HT_P1: + return HT_LT; + case HT_P2: + return HT_RT; + default: + return HT_T; + } + } + B.x = m_X2; B.y = m_Y1; + E.x = m_X2; E.y = m_Y2; + r = IsLine(N, B, E, 5); + if( r ){ + switch(r){ + case HT_P1: + return HT_RT; + case HT_P2: + return HT_RB; + default: + return HT_R; + } + } + B.x = m_X2; B.y = m_Y2; + E.x = m_X1; E.y = m_Y2; + r = IsLine(N, B, E, 5); + if( r ){ + switch(r){ + case HT_P1: + return HT_RB; + case HT_P2: + return HT_LB; + default: + return HT_B; + } + } + B.x = m_X1; B.y = m_Y2; + E.x = m_X1; E.y = m_Y1; + r = IsLine(N, B, E, 5); + if( r ){ + switch(r){ + case HT_P1: + return HT_LB; + case HT_P2: + return HT_LT; + default: + return HT_L; + } + } + if( (x < m_X1) || (x > m_X2) ) return FALSE; + if( (y < m_Y1) || (y > m_Y2) ) return FALSE; + return HT_I; +} + +void __fastcall CDrawBox::Moving(int x, int y) +{ + if( m_Cursor ) DrawCursor(); + if( !m_MF ){ + if( m_BX != x ) m_MF = 1; + if( m_BY != y ) m_MF = 1; + } + x -= m_BX; + y -= m_BY; + int bs = 0; + switch(m_MC){ + case HT_LT: + m_CX1 = m_X1 + x; + m_CY1 = m_Y1 + y; + if( m_BoxStyle == 5 ) bs = 3; + break; + case HT_T: + m_CY1 = m_Y1 + y; + if( m_BoxStyle == 5 ) bs = 1; + break; + case HT_RT: + m_CX2 = m_X2 + x; + m_CY1 = m_Y1 + y; + if( m_BoxStyle == 5 ) bs = 1; + break; + case HT_R: + m_CX2 = m_X2 + x; + if( m_BoxStyle == 5 ) bs = 2; + break; + case HT_RB: + m_CX2 = m_X2 + x; + m_CY2 = m_Y2 + y; + if( m_BoxStyle == 5 ) bs = 2; + break; + case HT_B: + m_CY2 = m_Y2 + y; + if( m_BoxStyle == 5 ) bs = 1; + break; + case HT_LB: + m_CX1 = m_X1 + x; + m_CY2 = m_Y2 + y; + if( m_BoxStyle == 5 ) bs = 2; + break; + case HT_L: + m_CX1 = m_X1 + x; + if( m_BoxStyle == 5 ) bs = 2; + break; + default: + m_CX1 = m_X1 + x; + m_CX2 = m_X2 + x; + m_CY1 = m_Y1 + y; + m_CY2 = m_Y2 + y; + break; + } + switch(bs){ + case 1: + m_CX2 = m_CX1 + (m_CY2 - m_CY1); + break; + case 2: + m_CY2 = m_CY1 + (m_CX2 - m_CX1); + break; + case 3: + m_CX1 = m_CX2 - (m_CY2 - m_CY1); + break; + } + DrawCursor(); + m_Cursor = 1; +} + +void __fastcall CDrawBox::Move(int x, int y) +{ + m_X1 = m_CX1; + m_Y1 = m_CY1; + m_X2 = m_CX2; + m_Y2 = m_CY2; + Normal(); + AdjustRect(); +} + +//--------------------------------------------------------------------------- +__fastcall CDrawBoxS::CDrawBoxS() +{ + m_Command = CM_BOXS; + m_LineStyle = TPenStyle(-1); +} + +void __fastcall CDrawBoxS::Draw(TCanvas *tp) +{ + tp->Brush->Color = m_LineColor; + tp->Pen->Color = m_LineColor; + tp->Pen->Style = psSolid; + tp->Pen->Style = m_LineStyle < 5 ? m_LineStyle : psSolid; + tp->Pen->Width = m_LineWidth; + if( m_BoxStyle ){ + tp->Pen->Style = m_LineStyle; + tp->Pen->Width = m_LineWidth; + DBox(tp, m_BoxStyle, m_X1, m_Y1, m_X2, m_Y2); + } + else { + TRect rc; + rc.Left = m_X1; rc.Top = m_Y1; + rc.Right = m_X2; rc.Bottom = m_Y2; + tp->FillRect(rc); + } + TColor col = m_LineColor; + m_LineColor = clWhite; + CDrawBox::Draw(tp); + m_LineColor = col; +} + +//--------------------------------------------------------------------------- +__fastcall CDrawTitle::CDrawTitle() +{ + m_Command = CM_TITLE; + m_Type = 1; + m_Col1 = sys.m_ColBar[0]; + m_Col2 = sys.m_ColBar[1]; + m_Col3 = sys.m_ColBar[2]; + m_Col4 = sys.m_ColBar[3]; + m_X1 = m_Y1 = 0; + m_X2 = 319; + m_Y2 = 15; + m_Ver = 3; + m_ColVert = 0; + m_Sound = "1356865313568888"; +// m_Sound = "5888531133865555"; +// m_Sound = "1588531133531111"; +// m_Sound = "1355135585313533"; + pBitmap = NULL; +} + +__fastcall CDrawTitle::~CDrawTitle() +{ + if( pBitmap != NULL ){ + delete pBitmap; + pBitmap = NULL; + } +} + +int __fastcall CDrawTitle::HitTest(int x, int y) +{ + int r = CDrawBox::HitTest(x, y); + switch(r){ + case 0: + return HT_NONE; + case HT_B: + return r; + default: + return HT_I; + } +}; + +void __fastcall CDrawTitle::Start(TCanvas *tp, int x, int y) +{ + pc = tp; + m_CY1 = m_Y1 = y; + m_CX1 = m_X1; + m_CX2 = m_X2; +} + +int __fastcall CDrawTitle::Finish(int x, int y) +{ + m_X1 = 0; + m_X2 = SXW - 1; + m_Y1 = y; + m_Y2 = y + 15; + return TRUE; +} + +void __fastcall CDrawTitle::FillPic(TCanvas *tp, TColor col, int sw, double sx, double sy, int off) +{ + TRect rc; + switch(sw){ + case 2: + rc.Left = m_X1; + rc.Top = m_Y1 - 16; + rc.Right = m_X2 + 1; + rc.Bottom = m_Y2 - 16; + break; + case 4: + rc.Left = m_X1; + rc.Top = m_Y1 * 240 / 256; + rc.Right = m_X2 + 1; + rc.Bottom = (m_Y2 * 240 / 256); + break; + case -1: + rc.Left = m_X1; + rc.Top = m_Y1 + off; + rc.Right = (m_X2 + 1); + rc.Bottom = m_Y2 + off; + break; + default: + rc.Left = m_X1 * sx; + rc.Top = m_Y1 * sy; + rc.Right = (m_X2 + 1) * sx; + rc.Bottom = m_Y2 * sy; + break; + } + rc.Bottom++; + tp->Brush->Color = col; + tp->Pen->Color = col; + tp->FillRect(rc); +} + +void __fastcall CDrawTitle::Draw(TCanvas *tp) +{ + m_X2 = SXW - 1; + int x, y; + int X1, X2, Y1, Y2; + int XW, YW; + tp->Pen->Style = psSolid; + switch(m_Type){ + case 0: + { + TRect rc; + rc.Top = m_Y1; + rc.Left = m_X1; + rc.Right = m_X2 + 1; + rc.Bottom = m_Y2 + 1; + tp->Brush->Style = bsSolid; + tp->Brush->Color = m_Col1; + tp->FillRect(rc); + } + break; + case 1: + if( m_ColVert ){ + for( y = m_Y1; y <= m_Y2; y++ ){ + tp->Pen->Color = GetCol(m_Col1, m_Col2, y, m_Y2); + tp->MoveTo(m_X1, y); tp->LineTo(m_X2+1, y); + } + } + else { + for( x = m_X1; x <= m_X2; x++ ){ + tp->Pen->Color = GetCol(m_Col1, m_Col2, x, m_X2); + tp->MoveTo(x, m_Y1); tp->LineTo(x, m_Y2+1); + } + } + break; + case 2: + if( m_ColVert ){ + YW = (m_Y2 - m_Y1) / 3; + Y1 = YW + m_Y1; + Y2 = YW + Y1; + for( y = m_Y1; y < Y1; y++ ){ + tp->Pen->Color = GetCol(m_Col1, m_Col2, y - m_Y1, YW); + tp->MoveTo(m_X1, y); tp->LineTo(m_X2+1, y); + } + for( ; y < Y2; y++ ){ + tp->Pen->Color = GetCol(m_Col2, m_Col3, y - Y1, YW); + tp->MoveTo(m_X1, y); tp->LineTo(m_X2+1, y); + } + for( ; y <= m_Y2; y++ ){ + tp->Pen->Color = GetCol(m_Col3, m_Col4, y - Y2, YW); + tp->MoveTo(m_X1, y); tp->LineTo(m_X2+1, y); + } + } + else { + XW = (m_X2 - m_X1) / 3; + X1 = XW + m_X1; + X2 = XW + X1; + for( x = m_X1; x < X1; x++ ){ + tp->Pen->Color = GetCol(m_Col1, m_Col2, x - m_X1, XW); + tp->MoveTo(x, m_Y1); tp->LineTo(x, m_Y2+1); + } + for( ; x < X2; x++ ){ + tp->Pen->Color = GetCol(m_Col2, m_Col3, x - X1, XW); + tp->MoveTo(x, m_Y1); tp->LineTo(x, m_Y2+1); + } + for( ; x <= m_X2; x++ ){ + tp->Pen->Color = GetCol(m_Col3, m_Col4, x - X2, XW); + tp->MoveTo(x, m_Y1); tp->LineTo(x, m_Y2+1); + } + } + break; + case 3: + if( pBitmap != NULL ){ + if( pBitmap->Height != (m_Y2 - m_Y1 + 1) ){ + TRect rc; + rc.Left = m_X1; rc.Top = m_Y1; + rc.Right = m_X2 + 1; + rc.Bottom = m_Y2 + 1; + int Sop = ::SetStretchBltMode(tp->Handle, HALFTONE); + tp->StretchDraw(rc, pBitmap); + ::SetStretchBltMode(tp->Handle, Sop); + } + else { + tp->Draw(m_X1, m_Y1, pBitmap); + } + } + break; + case 4: + { + const BYTE _ft[]={0, 29, 60, 92, 126, 162, 201, 242}; + LPCSTR p = m_Sound.c_str(); + DWORD col; + for( y = m_Y1; *p; p++, y++ ){ + if( (*p >= '1') && (*p <= '8') ){ + col = _ft[(*p & 0x0f) - 1]; + tp->Pen->Color = TColor(col + (col * 256) + (col * 65536)); + tp->MoveTo(m_X1, y); tp->LineTo(m_X2+1, y); + } + } + } + break; + } +} + +void __fastcall CDrawTitle::DrawFast(TCanvas *tp) +{ + m_X2 = SXW - 1; + TRect rc; + rc.Left = m_X1; + rc.Top = m_Y1; + rc.Right = m_X2 + 1; + rc.Bottom = m_Y2; + tp->Brush->Color = m_Col1; + tp->Pen->Color = m_Col1; + tp->FillRect(rc); +} + +void __fastcall CDrawTitle::Moving(int x, int y) +{ + if( m_Cursor ) DrawCursor(); + if( !m_MF ){ + if( m_BY != y ) m_MF = 1; + } + y -= m_BY; + int h = m_Y2 - m_Y1; + switch(m_MC){ + case HT_I: + y += m_Y1; + if( y < 0 ) y = 0; + if( y > (SYW - h) ) y = SYW - h; + m_CY1 = y; + m_CY2 = m_CY1 + h; + break; + case HT_B: + y += m_Y2; + if( y < 0 ) y = 0; + if( y > (SYW-1) ) y = SYW-1; + if( y != m_CY1 ) m_CY2 = y; + break; + } + DrawCursor(); + m_Cursor = 1; +} + +void __fastcall CDrawTitle::StartMove(TCanvas *tp, int x, int y, int code) +{ + pc = tp; + m_BY = y; + m_MF = 0; + m_MC = code; + m_CX1 = m_X1; + m_CX2 = m_X2; + m_Cursor = 0; +} + +void __fastcall CDrawTitle::Move(int x, int y) +{ + if( m_CY1 < m_CY2 ){ + m_Y1 = m_CY1; + m_Y2 = m_CY2; + } + else { + m_Y1 = m_CY2; + m_Y2 = m_CY1; + } +} + +void __fastcall CDrawTitle::Copy(CDraw *dp) +{ + CDrawBox::Copy(dp); + + CDrawTitle *sp = (CDrawTitle *)dp; + m_Type = sp->m_Type; + m_ColVert = sp->m_ColVert; + m_Col1 = sp->m_Col1; + m_Col2 = sp->m_Col2; + m_Col3 = sp->m_Col3; + m_Col4 = sp->m_Col4; + m_Sound = sp->m_Sound; + if( sp->pBitmap != NULL ){ + if( pBitmap == NULL ){ + pBitmap = new Graphics::TBitmap(); + AdjustBitmapFormat(pBitmap); + } + pBitmap->Assign(sp->pBitmap); + } + else if( pBitmap != NULL ){ + delete pBitmap; + pBitmap = NULL; + } +} + +int __fastcall CDrawTitle::Edit(void) +{ + TColorBarDlg *pBox = new TColorBarDlg(Mmsstv); + int r = pBox->Execute(this); + delete pBox; + if( r == TRUE ){ + m_X2 = SXW - 1; + sys.m_ColBar[0] = m_Col1; + sys.m_ColBar[1] = m_Col2; + sys.m_ColBar[2] = m_Col3; + sys.m_ColBar[3] = m_Col4; + } + return r; +} + +void __fastcall CDrawTitle::SaveToStream(TStream *sp) +{ + m_Ver = 3; + CDrawBox::SaveToStream(sp); + + sp->Write(&m_Type, sizeof(m_Type)); + sp->Write(&m_ColVert, sizeof(m_ColVert)); + sp->Write(&m_Col1, sizeof(m_Col1)); + sp->Write(&m_Col2, sizeof(m_Col2)); + sp->Write(&m_Col3, sizeof(m_Col3)); + sp->Write(&m_Col4, sizeof(m_Col4)); + if( m_Type == 4 ) SaveString(sp, m_Sound); + if( m_Type == 3 ){ + SaveBitmap(sp, pBitmap); + } +} + +int __fastcall CDrawTitle::LoadFromStream(TCanvas *tp, TStream *sp) +{ + if( CDrawBox::LoadFromStream(tp, sp) == FALSE ) return FALSE; + + try { + if( m_Ver >= 1 ){ + sp->Read(&m_Type, sizeof(m_Type)); + if( m_Ver >= 2 ){ + sp->Read(&m_ColVert, sizeof(m_ColVert)); + } + sp->Read(&m_Col1, sizeof(m_Col1)); + sp->Read(&m_Col2, sizeof(m_Col2)); + sp->Read(&m_Col3, sizeof(m_Col3)); + sp->Read(&m_Col4, sizeof(m_Col4)); + if( (m_Ver >= 3) && (m_Type == 4) ){ + LoadString(sp, m_Sound); + } + if( m_Type == 3 ){ + if( pBitmap == NULL ){ + pBitmap = new Graphics::TBitmap(); + AdjustBitmapFormat(pBitmap); + } + LoadBitmap(sp, pBitmap); + } + } + return TRUE; + } + catch(...){ + return FALSE; + } +} +//--------------------------------------------------------------------------- +__fastcall CDrawText::CDrawText() +{ + m_Command = CM_TEXT; + + m_Grade = sys.m_TextGrade; + m_Shadow = sys.m_TextShadow; + m_Zero = sys.m_TextZero; + m_Rot = sys.m_TextRot; + m_RightAdj = 0; + m_X2 = m_Y2 = 0; + m_LineColor = clBlack; + m_LineStyle = psSolid; + m_Stack = sys.m_TextStack >> 16; + m_StackPara = sys.m_TextStack & 0x0000ffff; + m_Vert = sys.m_TextVert; + m_VertH = sys.m_TextVertH; + + m_Text = sys.m_TextList[0].c_str(); + m_Col1 = sys.m_ColText[0]; + m_Col2 = sys.m_ColText[1]; + m_Col3 = sys.m_ColText[2]; + m_Col4 = sys.m_ColText[3]; + m_ColS = sys.m_ColText[4]; + m_ColB = sys.m_ColText[5]; + + pFont = NULL; + pBitmap = NULL; + pBrushBitmap = NULL; + + m_PerSpect = 0; + m_sperspect.ax = 2.0; m_sperspect.ay = 6.0; + m_sperspect.px = 0.05; + m_sperspect.py = m_sperspect.pz = 0.0; + m_sperspect.rz = -180; m_sperspect.rx = -70; m_sperspect.ry = 0; + m_sperspect.v = 10; m_sperspect.s = 4.9; + + m_Ver = 7; +} + +//--------------------------------------------------------------------------- +__fastcall CDrawText::~CDrawText() +{ + if( pFont != NULL ){ + delete pFont; + pFont = NULL; + } + if( pBitmap != NULL ){ + delete pBitmap; + pBitmap = NULL; + } + if( pBrushBitmap != NULL ){ + delete pBrushBitmap; + pBrushBitmap = NULL; + } +} + +void __fastcall CDrawText::ReleaseResource(void) +{ + if( pBitmap != NULL ){ + delete pBitmap; + pBitmap = NULL; + } +} + +int __fastcall CDrawText::ZeroConv(BYTE charset, LPSTR s) +{ + int f = 0; + + char bf[1228]; + LPSTR t = bf; + LPSTR p = s; + for( ; *p; p++ ){ + if( *p == '0' ){ + switch(charset){ + case SHIFTJIS_CHARSET: + *t++ = 0x83; + *t++ = 0xd3; + break; + case HANGEUL_CHARSET: + *t++ = 0xa8; // 0xa9 + *t++ = 0xaa; + break; + case CHINESEBIG5_CHARSET: // 台湾 + *t++ = 0xa3; + *t++ = 0x58; + break; + case 134: // 中国語簡略 + *t++ = 0xa6; + *t++ = 0xd5; + break; + default: + if( (lcid == LANG_KOREAN) || (lcid == LANG_CHINESE) ){ + f++; + *t++ = '0'; + } + else { + *t++ = 'リ'; + } + break; + } + } + else { + *t++ = *p; + } + } + *t = 0; + StrCopy(s, bf, 1023); + return f; +} + +int __fastcall CDrawText::GetMaxWidth(int &n, LPCSTR p) +{ + n = 0; + int max = 0; + + char bf[4]; + while(*p){ + if( (_mbsbtype((const unsigned char *)p, 0) == _MBC_LEAD) && *(p+1) ){ +// if( IsDBCSLeadByte(*(const unsigned char *)p) && *(p+1) ){ + bf[0] = *p++; + bf[1] = *p++; + bf[2] = 0; + } + else { + bf[0] = *p++; + bf[1] = 0; + } + int len = pc->TextWidth(bf); + if( max < len ){ + max = len; + } + n++; + } + return max; +} + +inline TXOut(TCanvas *cp, int x, int y, LPCSTR p){cp->TextOut(x, y, p); return 0;}; + +void __fastcall CDrawText::DrawTextVert(TCanvas *tp, int xc, int y, int fh, LPCSTR p) +{ + char bf[4]; + + int tm = ::SetBkMode(tp->Handle, TRANSPARENT); + while(*p){ + if( (_mbsbtype((const unsigned char *)p, 0) == _MBC_LEAD) && *(p+1) ){ + bf[0] = *p++; + bf[1] = *p++; + bf[2] = 0; + } + else if( (*p == '0') && m_Zero ){ + bf[0] = 'リ'; + bf[1] = 0; + p++; + } + else { + bf[0] = *p++; + bf[1] = 0; + } + int FW = tp->TextWidth(bf); + int FH = tp->TextHeight(bf); +#if 1 + TXOut(tp, xc - (FW/2), y, bf); +#else + tp->TextOut(xc - (FW/2), y, bf); +#endif + y += (FH + fh); + } + ::SetBkMode(tp->Handle, tm); +} + +void __fastcall CDrawText::DrawTextHoriANSI(TCanvas *tp, int x, int y, LPCSTR p) +{ + char bf[4]; + + int tm = ::SetBkMode(tp->Handle, TRANSPARENT); + int FW; + double rot = m_Rot * PI/180.0; + while(*p){ + if( (_mbsbtype((const unsigned char *)p, 0) == _MBC_LEAD) && *(p+1) ){ + bf[0] = *p++; + bf[1] = *p++; + bf[2] = 0; + } + else if( *p == '0' ){ + bf[0] = 'リ'; + bf[1] = 0; + p++; + } + else { + bf[0] = *p++; + bf[1] = 0; + } + FW = tp->TextWidth(bf); +#if 1 + TXOut(tp, x, y, bf); +#else + tp->TextOut(x, y, bf); +#endif + if( m_Rot ){ + x += FW * cos(rot); + y -= FW * sin(rot); + } + else { + x += FW; + } + } + ::SetBkMode(tp->Handle, tm); +} + +void __fastcall CDrawText::DrawText(TCanvas *cp, int x, int y, LPCSTR p, int zc) +{ + if( m_Vert ){ + DrawTextVert(cp, x, y, m_VertH, p); + } + else if( zc ){ + DrawTextHoriANSI(cp, x, y, p); + } + else { +#if 1 + TXOut(cp, x, y, p); +#else + cp->TextOut(x, y, p); +#endif +// DrawTextHoriANSI(cp, x, y, p); // test of Korean Windows + } +} + +Graphics::TBitmap * __fastcall CDrawText::DupeB(TColor col) +{ + MultProc(); + pBitmap->Transparent = TRUE; + pBitmap->TransparentMode = tmAuto; + Graphics::TBitmap *pBit = new Graphics::TBitmap(); +// AdjustBitmapFormat(pBit); + pBit->Assign(pBitmap); + MultProc(); + FillBitmap(pBit, col); + return pBit; +} + +Graphics::TBitmap * __fastcall CDrawText::ConvToDDB(Graphics::TBitmap *pBmp) +{ + if( (sys.m_BitPixel == 16) && (pBmp->PixelFormat == pf24bit) ){ + pBmp->Transparent = FALSE; + Graphics::TBitmap *pNew = DupeBitmap(pBmp, -1); + pNew->Canvas->Font->Assign(pBmp->Canvas->Font); + delete pBmp; + pBmp = pNew; + } + return pBmp; +} + +Graphics::TBitmap * __fastcall CDrawText::ConvToDIB(Graphics::TBitmap *pBmp) +{ + if( pBmp->PixelFormat != pf24bit ){ + pBmp->Transparent = FALSE; + Graphics::TBitmap *pNew = DupeBitmap(pBmp, pf24bit); + delete pBmp; + pBmp = pNew; + } + return pBmp; +} + +void __fastcall CDrawText::MakeBitmap(void) +{ + if( m_Text.IsEmpty() ) return; + char bf[1024]; + Mmsstv->MacroText(bf, m_Text.c_str(), sizeof(bf)-1); + int ZC = 0; + if( m_Zero ) ZC = ZeroConv(pFont->Charset, bf); + + CWaitCursor wait; + if( pBitmap != NULL ){ + delete pBitmap; + } + pc->Font->Assign(pFont); + int wx = (pFont->Size + 15)/ 16; + int x2 = m_X2; + int y2 = m_Y2; + if( m_Rot ){ + m_X1 = m_X; + m_Y1 = m_Y; + } + else { + m_X = m_X1; + m_Y = m_Y1; + } + if( m_Vert ){ + SetMBCP(pFont->Charset); + int len; + m_X2 = m_X1 + GetMaxWidth(len, bf); + m_Y2 = m_Y1 + ((pc->TextHeight(bf) + m_VertH) * len) + wx + wx; + } + else { + m_X2 = m_X1 + pc->TextWidth(bf) + wx + wx; + m_Y2 = m_Y1 + pc->TextHeight(bf) + wx; + if( ZC ) m_X2 += (pc->TextWidth("0") * ZC); + } + int xt, yt; + switch(m_Shadow){ + case 1: + xt = yt = m_LineWidth + 1; + break; + case 4: + case 5: + if( !m_Stack ){ + xt = yt = 0; + break; + } + case 6: + case 7: + xt = yt = 2; + break; + default: + xt = yt = 0; + break; + } + if( m_Vert ) xt += (m_X2-m_X1)/2; + if( m_Rot ){ + m_Y1 -= wx; + m_X1 -= wx; + m_X2 += wx; + m_Y2 += wx; + double s = 2 * PI * m_Rot / 360; + double cosk = cos(s); + double sink = sin(s); + int xc = (m_X1 + m_X2)/2; + int yc = (m_Y1 + m_Y2)/2; + POINT N[5]; + N[0].x = m_X1 - xc; + N[0].y = m_Y1 - yc; + N[1].x = m_X2 - xc; + N[1].y = m_Y1 - yc; + N[2].x = m_X2 - xc; + N[2].y = m_Y2 - yc; + N[3].x = m_X1 - xc; + N[3].y = m_Y2 - yc; + N[4].x = xt + m_X1 - xc; + N[4].y = yt + m_Y1 - yc; + int i; + for( i = 0; i < 5; i++ ){ + int x = N[i].x * cosk + N[i].y * sink; + int y = -N[i].x * sink + N[i].y * cosk; + N[i].x = x + xc; N[i].y = y + yc; + } + m_X1 = m_X2 = N[0].x; m_Y1 = m_Y2 = N[0].y; + for( i = 1; i < 4; i++ ){ + if( m_X1 > N[i].x ) m_X1 = N[i].x; + if( m_X2 < N[i].x ) m_X2 = N[i].x; + if( m_Y1 > N[i].y ) m_Y1 = N[i].y; + if( m_Y2 < N[i].y ) m_Y2 = N[i].y; + } + xt = N[4].x - m_X1; + yt = N[4].y - m_Y1; + } + switch(m_Shadow){ + case 0: + break; + case 1: + m_X2 += m_LineWidth + m_LineWidth + 2; + m_Y2 += m_LineWidth + m_LineWidth + 2; + break; + case 2: + case 3: + case 4: + case 5: + case 7: + m_X2 += wx; + m_Y2 += wx; + case 6: + m_X2 += wx + wx; + m_Y2 += wx; + break; + } + int ax, ay; + if( m_Stack ){ + ax = int(char(m_StackPara & 0x000000ff)); + ay = int(char((m_StackPara >> 8) & 0x000000ff)); + if( ax > 0 ){ + xt += ax; + } + m_X2 += ABS(ax); + if( ay > 0 ){ + yt += ay; + } + m_Y2 += ABS(ay); + ax = -ax; ay = -ay; + } + AdjustRect(); + TFontStyles ts = pFont->Style; + int fsw = FontStyle2Code(ts); + if( fsw & FSITALIC ) m_X2 += wx * 3; + int pf24 = sys.m_Temp24; + pBitmap = CreateBitmap(m_X2 - m_X1 + 1, m_Y2 - m_Y1 + 1, pf24 ? pf24bit : -1); + COLD cBack; + cBack.c = TransCol; + if( cBack.c == m_Col1 ){ + cBack.c = GetUniqueColor(m_Col1); + } + if( m_Shadow && (cBack.c == m_ColS) ){ + cBack.c = GetUniqueColor(cBack.c); + } + FillBitmap(pBitmap, cBack.c); + cBack.c = pBitmap->Canvas->Pixels[0][0]; + if( m_RightAdj ){ + if( m_Vert && y2 ){ + y2 = m_Y2 - y2; + m_Y1 -= y2; m_Y2 -= y2; + } + else if( x2 ){ + x2 = m_X2 - x2; + m_X1 -= x2; m_X2 -= x2; + } + } + MultProc(); + + if( m_Rot || sys.m_DisFontSmooth ){ + LOGFONT lf; + memset(&lf, 0, sizeof(lf)); + lf.lfHeight = pFont->Height; + lf.lfWidth = 0; + lf.lfEscapement = m_Rot * 10; + lf.lfOrientation = m_Rot * 10; + lf.lfWeight = fsw & FSBOLD ? 700 : 400; + lf.lfItalic = BYTE(fsw & FSITALIC ? TRUE : FALSE); + lf.lfUnderline = BYTE(fsw & FSUNDERLINE ? TRUE : FALSE); + lf.lfStrikeOut = BYTE(fsw & FSSTRIKEOUT ? TRUE : FALSE); + lf.lfCharSet = pFont->Charset; + lf.lfOutPrecision = OUT_CHARACTER_PRECIS; + lf.lfClipPrecision = CLIP_DEFAULT_PRECIS; + lf.lfQuality = BYTE(sys.m_DisFontSmooth ? NONANTIALIASED_QUALITY : PROOF_QUALITY); + lf.lfPitchAndFamily = DEFAULT_PITCH; + strcpy(lf.lfFaceName, AnsiString(pFont->Name).c_str()); //ja7ude 0521 + + pBitmap->Canvas->Font->Handle = CreateFontIndirect(&lf); + } + else { + pBitmap->Canvas->Font = pFont; + } + pBitmap->Canvas->Font->Color = m_Col1; + DrawText(pBitmap->Canvas, xt, yt, bf, ZC); + + COLD col; + int x, y; + int XW = pBitmap->Width; + int YW = pBitmap->Height; + int XL = XW; + int XR = 0; + int YT = YW; + int YB = 0; + BYTE **pY = NULL; + BYTE *bp = NULL; + BYTE *sp; + BYTE *wp; + if( m_Grade || m_Shadow ){ + bp = new BYTE[XW * YW]; + wp = bp; + if( pf24 ){ + col.d = 0; + pY = new BYTE*[YW]; + for( y = 0; y < YW; y++ ){ + sp = (BYTE *)pBitmap->ScanLine[y]; + pY[y] = sp; + for( x = 0; x < XW; x++, wp++ ){ + col.b.b = *sp++; + col.b.g = *sp++; + col.b.r = *sp++; + if( col.c != cBack.c ){ + if( XL > x ) XL = x; + if( XR < x ) XR = x; + if( YT > y ) YT = y; + if( YB < y ) YB = y; + *wp = 1; + } + else { + *wp = 0; + } + } + } + } + else { + for( y = 0; y < YW; y++ ){ + for( x = 0; x < XW; x++, wp++ ){ + if( pBitmap->Canvas->Pixels[x][y] != cBack.c ){ + if( XL > x ) XL = x; + if( XR < x ) XR = x; + if( YT > y ) YT = y; + if( YB < y ) YB = y; + *wp = 1; + } + else { + *wp = 0; + } + } + } + } + MultProc(); + } + int X1, X2, Y1, Y2; + switch(m_Grade){ + case 0: + if( m_Shadow ){ + col.c = m_Col1; + if( pf24 ){ + for( y = YT; y <= YB; y++ ){ + sp = &bp[y*XW + XL]; +// wp = (BYTE *)pBitmap->ScanLine[y] + (XL * 3); + wp = (BYTE *)pY[y] + (XL * 3); + for( x = XL; x <= XR; x++, sp++ ){ + if( *sp ){ + *wp++ = col.b.b; + *wp++ = col.b.g; + *wp++ = col.b.r; + } + else { + wp += 3; + } + } + } + } + else { + for( y = YT; y <= YB; y++ ){ + sp = &bp[y*XW + XL]; + for( x = XL; x <= XR; x++, sp++ ){ + if( *sp ){ + pBitmap->Canvas->Pixels[x][y] = col.c; + } + } + } + } + } + break; + case 1: + if( pf24 ){ + X1 = (XR - XL) / 3; + for( x = XL; x < X1+XL; x++ ){ + col.c = GetCol(m_Col1, m_Col2, x - XL, X1); + sp = &bp[YT*XW + x]; + for( y = YT; y <= YB; y++, sp += XW ){ + if( *sp ){ +// wp = (BYTE *)pBitmap->ScanLine[y] + (x * 3); + wp = (BYTE *)pY[y] + (x * 3); + *wp++ = col.b.b; + *wp++ = col.b.g; + *wp = col.b.r; + } + } + } + MultProc(); + X2 = X1+X1; + for( ; x < X2+XL; x++ ){ + col.c = GetCol(m_Col2, m_Col3, x - X1 - XL, X1); + sp = &bp[YT*XW + x]; + for( y = YT; y <= YB; y++, sp += XW ){ + if( *sp ){ +// wp = (BYTE *)pBitmap->ScanLine[y] + (x * 3); + wp = (BYTE *)pY[y] + (x * 3); + *wp++ = col.b.b; + *wp++ = col.b.g; + *wp = col.b.r; + } + } + } + MultProc(); + for( ; x <= XR; x++ ){ + col.c = GetCol(m_Col3, m_Col4, x - X2 - XL, X1); + sp = &bp[YT*XW + x]; + for( y = YT; y <= YB; y++, sp += XW ){ + if( *sp ){ +// wp = (BYTE *)pBitmap->ScanLine[y] + (x * 3); + wp = (BYTE *)pY[y] + (x * 3); + *wp++ = col.b.b; + *wp++ = col.b.g; + *wp = col.b.r; + } + } + } + } + else { + X1 = (XR - XL) / 3; + for( x = XL; x < X1+XL; x++ ){ + col.c = GetCol(m_Col1, m_Col2, x - XL, X1); + sp = &bp[YT*XW + x]; + for( y = YT; y <= YB; y++, sp += XW ){ + if( *sp ){ + pBitmap->Canvas->Pixels[x][y] = col.c; + } + } + } + MultProc(); + X2 = X1+X1; + for( ; x < X2+XL; x++ ){ + col.c = GetCol(m_Col2, m_Col3, x - X1 - XL, X1); + sp = &bp[YT*XW + x]; + for( y = YT; y <= YB; y++, sp += XW ){ + if( *sp ){ + pBitmap->Canvas->Pixels[x][y] = col.c; + } + } + } + MultProc(); + for( ; x <= XR; x++ ){ + col.c = GetCol(m_Col3, m_Col4, x - X2 - XL, X1); + sp = &bp[YT*XW + x]; + for( y = YT; y <= YB; y++, sp += XW ){ + if( *sp ){ + pBitmap->Canvas->Pixels[x][y] = col.c; + } + } + } + } + break; + case 2: + if( pf24 ){ + Y1 = (YB - YT) / 3; + for( y = YT; y < Y1+YT; y++ ){ + col.c = GetCol(m_Col1, m_Col2, y - YT, Y1); + sp = &bp[y*XW + XL]; +// wp = (BYTE *)pBitmap->ScanLine[y] + (XL * 3); + wp = (BYTE *)pY[y] + (XL * 3); + for( x = XL; x <= XR; x++, sp++ ){ + if( *sp ){ + *wp++ = col.b.b; + *wp++ = col.b.g; + *wp++ = col.b.r; + } + else { + wp += 3; + } + } + } + MultProc(); + Y2 = Y1+Y1; + for( ; y < Y2 + YT; y++ ){ + col.c = GetCol(m_Col2, m_Col3, y - Y1 - YT, Y1); + sp = &bp[y*XW + XL]; +// wp = (BYTE *)pBitmap->ScanLine[y] + (XL * 3); + wp = (BYTE *)pY[y] + (XL * 3); + for( x = XL; x <= XR; x++, sp++ ){ + if( *sp ){ + *wp++ = col.b.b; + *wp++ = col.b.g; + *wp++ = col.b.r; + } + else { + wp += 3; + } + } + } + MultProc(); + for( ; y <= YB; y++ ){ + col.c = GetCol(m_Col3, m_Col4, y - Y2 - YT, Y1); + sp = &bp[y*XW + XL]; +// wp = (BYTE *)pBitmap->ScanLine[y] + (XL * 3); + wp = (BYTE *)pY[y] + (XL * 3); + for( x = XL; x <= XR; x++, sp++ ){ + if( *sp ){ + *wp++ = col.b.b; + *wp++ = col.b.g; + *wp++ = col.b.r; + } + else { + wp += 3; + } + } + } + } + else { + Y1 = (YB - YT) / 3; + for( y = YT; y < Y1+YT; y++ ){ + col.c = GetCol(m_Col1, m_Col2, y - YT, Y1); + sp = &bp[y*XW + XL]; + for( x = XL; x <= XR; x++, sp++ ){ + if( *sp ){ + pBitmap->Canvas->Pixels[x][y] = col.c; + } + } + } + MultProc(); + Y2 = Y1+Y1; + for( ; y < Y2 + YT; y++ ){ + col.c = GetCol(m_Col2, m_Col3, y - Y1 - YT, Y1); + sp = &bp[y*XW + XL]; + for( x = XL; x <= XR; x++, sp++ ){ + if( *sp ){ + pBitmap->Canvas->Pixels[x][y] = col.c; + } + } + } + MultProc(); + for( ; y <= YB; y++ ){ + col.c = GetCol(m_Col3, m_Col4, y - Y2 - YT, Y1); + sp = &bp[y*XW + XL]; + for( x = XL; x <= XR; x++, sp++ ){ + if( *sp ){ + pBitmap->Canvas->Pixels[x][y] = col.c; + } + } + } + } + break; + case 3: + if( (pBrushBitmap != NULL) && pBrushBitmap->Width && pBrushBitmap->Height ){ + if( pf24 ){ + for( y = YT; y <= YB; y++ ){ + sp = &bp[y*XW + XL]; +// wp = (BYTE *)pBitmap->ScanLine[y] + (XL * 3); + wp = (BYTE *)pY[y] + (XL * 3); + for( x = XL; x <= XR; x++, sp++ ){ + if( *sp ){ + col.c = pBrushBitmap->Canvas->Pixels[x % pBrushBitmap->Width][y % pBrushBitmap->Height]; + *wp++ = col.b.b; + *wp++ = col.b.g; + *wp++ = col.b.r; + } + else { + wp += 3; + } + } + } + } + else { + for( y = YT; y <= YB; y++ ){ + sp = &bp[y*XW + XL]; + for( x = XL; x <= XR; x++, sp++ ){ + if( *sp ){ + pBitmap->Canvas->Pixels[x][y] = pBrushBitmap->Canvas->Pixels[x % pBrushBitmap->Width][y % pBrushBitmap->Height]; + } + } + } + } + } + break; + } + + MultProc(); + + Graphics::TBitmap *pBit; + int f, lw; + switch(m_Shadow){ + case 1: + // if( wx > 1 ) wx--; + col.c = m_ColS; + lw = m_LineWidth; +_sh1: + if( pf24 ){ + for( x = 0; x < XW; x++ ){ + f = 0; + sp = &bp[x]; + for( y = 0; y < YW; y++, sp += XW ){ + if( *sp ){ + f = lw; + } + else if( f ){ +// wp = (BYTE *)pBitmap->ScanLine[y] + (x * 3); + wp = (BYTE *)pY[y] + (x * 3); + *wp++ = col.b.b; + *wp++ = col.b.g; + *wp = col.b.r; + *sp = 1; + f--; + } + } + f = 0; + y = YW - 1; + sp = &bp[y*XW+x]; + for( ; y > 0; y--, sp -= XW ){ + if( *sp ){ + f = lw; + } + else if( f ){ +// wp = (BYTE *)pBitmap->ScanLine[y] + (x * 3); + wp = (BYTE *)pY[y] + (x * 3); + *wp++ = col.b.b; + *wp++ = col.b.g; + *wp = col.b.r; + *sp = 1; + f--; + } + } + } + MultProc(); + for( y = 0; y < YW; y++ ){ + f = 0; + sp = &bp[y*XW]; +// wp = (BYTE *)pBitmap->ScanLine[y]; + wp = (BYTE *)pY[y]; + for( x = 0; x < XW; x++, sp++, wp+=3 ){ + if( *sp ){ + f = lw; + } + else if( f ){ + *wp++ = col.b.b; + *wp++ = col.b.g; + *wp = col.b.r; + wp -= 2; + *sp = 1; + f--; + } + } + f = 0; + x = XW - 1; + sp = &bp[y*XW+x]; +// wp = (BYTE *)pBitmap->ScanLine[y] + (x * 3); + wp = (BYTE *)pY[y] + (x * 3); + for( ; x > 0; x--, sp--, wp-=3 ){ + if( *sp ){ + f = lw; + } + else if( f ){ + *wp++ = col.b.b; + *wp++ = col.b.g; + *wp = col.b.r; + wp -= 2; + f--; + } + } + } + } + else { + for( x = 0; x < XW; x++ ){ + f = 0; + sp = &bp[x]; + for( y = 0; y < YW; y++, sp += XW ){ + if( *sp ){ + f = lw; + } + else if( f ){ + pBitmap->Canvas->Pixels[x][y] = col.c; + *sp = 1; + f--; + } + } + f = 0; + y = YW - 1; + sp = &bp[y*XW+x]; + for( ; y > 0; y--, sp -= XW ){ + if( *sp ){ + f = lw; + } + else if( f ){ + pBitmap->Canvas->Pixels[x][y] = col.c; + *sp = 1; + f--; + } + } + } + MultProc(); + for( y = 0; y < YW; y++ ){ + f = 0; + sp = &bp[y*XW]; + for( x = 0; x < XW; x++, sp++ ){ + if( *sp ){ + f = lw; + } + else if( f ){ + pBitmap->Canvas->Pixels[x][y] = col.c; + *sp = 1; + f--; + } + } + f = 0; + x = XW - 1; + sp = &bp[y*XW+x]; + for( ; x > 0; x--, sp-- ){ + if( *sp ){ + f = lw; + } + else if( f ){ + pBitmap->Canvas->Pixels[x][y] = col.c; + f--; + } + } + } + } + break; + case 2: + if( pf24 ) pBitmap = ConvToDDB(pBitmap); + pBit = DupeB(cBack.c); + pBit->Canvas->Font = pBitmap->Canvas->Font; + pBit->Canvas->Font->Color = m_ColS; + DrawText(pBit->Canvas, xt+wx, yt+wx, bf, ZC); + pBit->Canvas->Draw(0, 0, pBitmap); + delete pBitmap; + pBitmap = pBit; + break; + case 3: + if( pf24 ){ + col.c = m_ColS; + for( x = 0; x < XW; x++ ){ + f = 0; + sp = &bp[x]; + for( y = 0; y < YW; y++, sp += XW ){ + if( *sp ){ + f = wx; + } + else if( f ){ +// wp = (BYTE *)pBitmap->ScanLine[y] + (x * 3); + wp = (BYTE *)pY[y] + (x * 3); + *wp++ = col.b.b; + *wp++ = col.b.g; + *wp = col.b.r; + *sp = 1; + f--; + } + } + } + MultProc(); + for( y = 0; y < YW; y++ ){ + f = 0; + sp = &bp[y*XW]; +// wp = (BYTE *)pBitmap->ScanLine[y]; + wp = (BYTE *)pY[y]; + for( x = 0; x < XW; x++, sp++, wp+=3 ){ + if( *sp ){ + f = wx; + } + else if( f ){ + *wp++ = col.b.b; + *wp++ = col.b.g; + *wp = col.b.r; + wp -= 2; + f--; + } + } + } + } + else { + col.c = m_ColS; + for( x = 0; x < XW; x++ ){ + f = 0; + sp = &bp[x]; + for( y = 0; y < YW; y++, sp += XW ){ + if( *sp ){ + f = wx; + } + else if( f ){ + pBitmap->Canvas->Pixels[x][y] = col.c; + *sp = 1; + f--; + } + } + } + MultProc(); + for( y = 0; y < YW; y++ ){ + f = 0; + sp = &bp[y*XW]; + for( x = 0; x < XW; x++, sp++ ){ + if( *sp ){ + f = wx; + } + else if( f ){ + pBitmap->Canvas->Pixels[x][y] = col.c; + f--; + } + } + } + } + break; + case 4: + case 5: + case 6: + if( pf24 ) pBitmap = ConvToDDB(pBitmap); + pBit = DupeB(cBack.c); + pBit->Canvas->Font = pBitmap->Canvas->Font; + { + if( !m_Stack ){ + switch(m_Shadow){ + case 4: + ax = wx; + ay = wx*2; + break; + case 5: + ax = wx*2; + ay = wx; + break; + case 6: + ax = wx*2; + ay = wx*2; + break; + } + ax++; ay++; + } + int m = ABS(ax); + if( ABS(ax) < ABS(ay) ) m = ABS(ay); + if( m_StackPara ){ + for( f = m; f > 0; f-- ){ + col.c = GetCol(m_ColS, m_ColB, f-1, m); + pBit->Canvas->Font->Color = col.c; + ::SetBkMode(pBit->Canvas->Handle, TRANSPARENT); + DrawText(pBit->Canvas, xt+(f*ax/m), yt+(f*ay/m), bf, ZC); + } + } + MultProc(); + pBit->Canvas->Draw(0, 0, pBitmap); + delete pBitmap; + pBitmap = pBit; + } + if( (m_Shadow == 6) || m_Stack ){ + lw = 1; + switch(m_Shadow){ + case 4: + col.c = clBlack; + break; + case 5: + col.c = clWhite; + break; + case 6: + col.c = m_LineColor; + lw = m_LineWidth; + break; + } + MultProc(); + if( pf24 ) pBitmap = ConvToDIB(pBitmap); + if( pY ){ + for( y = 0; y < YW; y++ ){ + pY[y] = (BYTE *)pBitmap->ScanLine[y]; + } + } + goto _sh1; + } + break; + case 7: + if( pf24 ) pBitmap = ConvToDDB(pBitmap); + pBit = DupeB(cBack.c); + pBit->Canvas->Font = pBitmap->Canvas->Font; + pBit->Canvas->Font->Color = m_ColS; + ::SetBkMode(pBit->Canvas->Handle, TRANSPARENT); + DrawText(pBit->Canvas, xt-1, yt-1, bf, ZC); + pBit->Canvas->Font->Color = m_ColB; + ::SetBkMode(pBit->Canvas->Handle, TRANSPARENT); + DrawText(pBit->Canvas, xt+1, yt+1, bf, ZC); + pBit->Canvas->Draw(0, 0, pBitmap); + delete pBitmap; + pBitmap = pBit; + break; + } + if( bp != NULL ) delete bp; + if( pY != NULL ) delete pY; + if( m_Stack && m_StackPara && ((m_Shadow < 4) || (m_Shadow > 6)) ){ + MultProc(); + if( pf24 ) pBitmap = ConvToDDB(pBitmap); + pBit = DupeB(cBack.c); + int m = ABS(ax); + if( ABS(ax) < ABS(ay) ) m = ABS(ay); + for( f = m; f >= 0; f-- ){ + pBit->Canvas->Draw(f*ax/m, f*ay/m, pBitmap); + } + delete pBitmap; + pBitmap = pBit; + } + if( m_PerSpect ){ + MultProc(); + pBit = CreateBitmap(pBitmap->Width, pBitmap->Height, -1); + pBitmap->Transparent = FALSE; + Perspect(pBitmap, pBit, &m_sperspect, cBack.c); + delete pBitmap; + pBitmap = pBit; + pBitmap->Transparent = TRUE; + pBitmap->TransparentMode = tmFixed; + pBitmap->TransparentColor = pBitmap->Canvas->Pixels[0][0]; + } + else { + if( pf24 ) pBitmap = ConvToDDB(pBitmap); + pBitmap->Transparent = TRUE; + pBitmap->TransparentMode = tmAuto; + } + if( m_Vert ) SetMBCP(); +} + +#if 0 +void __fastcall CDrawText::MakeBitmap16(void) +{ + if( m_Text.IsEmpty() ) return; + char bf[1024]; + Mmsstv->MacroText(bf, m_Text.c_str(), sizeof(bf)-1); + int ZC = 0; + if( m_Zero ) ZC = ZeroConv(pFont->Charset, bf); + + CWaitCursor wait; + if( pBitmap != NULL ){ + delete pBitmap; + } + pc->Font->Assign(pFont); + int wx = (pFont->Size + 15)/ 16; + int x2 = m_X2; + int y2 = m_Y2; + if( m_Rot ){ + m_X1 = m_X; + m_Y1 = m_Y; + } + else { + m_X = m_X1; + m_Y = m_Y1; + } + if( m_Vert ){ + SetMBCP(pFont->Charset); + int len; + m_X2 = m_X1 + GetMaxWidth(len, bf); + m_Y2 = m_Y1 + ((pc->TextHeight(bf) + m_VertH) * len) + wx + wx; + } + else { + m_X2 = m_X1 + pc->TextWidth(bf) + wx + wx; + m_Y2 = m_Y1 + pc->TextHeight(bf) + wx; + if( ZC ) m_X2 += (pc->TextWidth("0") * ZC); + } + int xt, yt; + switch(m_Shadow){ + case 1: + xt = yt = m_LineWidth + 1; + break; + case 4: + case 5: + if( !m_Stack ){ + xt = yt = 0; + break; + } + case 6: + case 7: + xt = yt = 2; + break; + default: + xt = yt = 0; + break; + } + if( m_Vert ) xt += (m_X2-m_X1)/2; + if( m_Rot ){ + m_Y1 -= wx; + m_X1 -= wx; + m_X2 += wx; + m_Y2 += wx; + double s = 2 * PI * m_Rot / 360; + double cosk = cos(s); + double sink = sin(s); + int xc = (m_X1 + m_X2)/2; + int yc = (m_Y1 + m_Y2)/2; + POINT N[5]; + N[0].x = m_X1 - xc; + N[0].y = m_Y1 - yc; + N[1].x = m_X2 - xc; + N[1].y = m_Y1 - yc; + N[2].x = m_X2 - xc; + N[2].y = m_Y2 - yc; + N[3].x = m_X1 - xc; + N[3].y = m_Y2 - yc; + N[4].x = xt + m_X1 - xc; + N[4].y = yt + m_Y1 - yc; + int i; + for( i = 0; i < 5; i++ ){ + int x = N[i].x * cosk + N[i].y * sink; + int y = -N[i].x * sink + N[i].y * cosk; + N[i].x = x + xc; N[i].y = y + yc; + } + m_X1 = m_X2 = N[0].x; m_Y1 = m_Y2 = N[0].y; + for( i = 1; i < 4; i++ ){ + if( m_X1 > N[i].x ) m_X1 = N[i].x; + if( m_X2 < N[i].x ) m_X2 = N[i].x; + if( m_Y1 > N[i].y ) m_Y1 = N[i].y; + if( m_Y2 < N[i].y ) m_Y2 = N[i].y; + } + xt = N[4].x - m_X1; + yt = N[4].y - m_Y1; + } + switch(m_Shadow){ + case 0: + break; + case 1: + m_X2 += m_LineWidth + m_LineWidth + 2; + m_Y2 += m_LineWidth + m_LineWidth + 2; + break; + case 2: + case 3: + case 4: + case 5: + case 7: + m_X2 += wx; + m_Y2 += wx; + case 6: + m_X2 += wx + wx; + m_Y2 += wx; + break; + } + int ax, ay; + if( m_Stack ){ + ax = int(char(m_StackPara & 0x000000ff)); + ay = int(char((m_StackPara >> 8) & 0x000000ff)); + if( ax > 0 ){ + xt += ax; + } + m_X2 += ABS(ax); + if( ay > 0 ){ + yt += ay; + } + m_Y2 += ABS(ay); + ax = -ax; ay = -ay; + } + AdjustRect(); + TFontStyles ts = pFont->Style; + int fsw = FontStyle2Code(ts); + if( fsw & FSITALIC ) m_X2 += wx * 3; + pBitmap = CreateBitmap(m_X2 - m_X1 + 1, m_Y2 - m_Y1 + 1, -1); + TColor cBack = TransCol; + if( cBack == m_Col1 ){ + cBack = GetUniqueColor(m_Col1); + } + if( m_Shadow && (cBack == m_ColS) ){ + cBack = GetUniqueColor(cBack); + } + FillBitmap(pBitmap, cBack); + cBack = pBitmap->Canvas->Pixels[0][0]; + + if( m_RightAdj ){ + if( m_Vert && y2 ){ + y2 = m_Y2 - y2; + m_Y1 -= y2; m_Y2 -= y2; + } + else if( x2 ){ + x2 = m_X2 - x2; + m_X1 -= x2; m_X2 -= x2; + } + } + + MultProc(); + + if( m_Rot || sys.m_DisFontSmooth ){ + LOGFONT lf; + memset(&lf, 0, sizeof(lf)); + lf.lfHeight = pFont->Height; + lf.lfWidth = 0; + lf.lfEscapement = m_Rot * 10; + lf.lfOrientation = m_Rot * 10; + lf.lfWeight = fsw & FSBOLD ? 700 : 400; + lf.lfItalic = BYTE(fsw & FSITALIC ? TRUE : FALSE); + lf.lfUnderline = BYTE(fsw & FSUNDERLINE ? TRUE : FALSE); + lf.lfStrikeOut = BYTE(fsw & FSSTRIKEOUT ? TRUE : FALSE); + lf.lfCharSet = pFont->Charset; + lf.lfOutPrecision = OUT_CHARACTER_PRECIS; + lf.lfClipPrecision = CLIP_DEFAULT_PRECIS; + lf.lfQuality = BYTE(sys.m_DisFontSmooth ? NONANTIALIASED_QUALITY : PROOF_QUALITY); + lf.lfPitchAndFamily = DEFAULT_PITCH; + strcpy(lf.lfFaceName, pFont->Name.c_str()); + + pBitmap->Canvas->Font->Handle = CreateFontIndirect(&lf); + } + else { + pBitmap->Canvas->Font = pFont; + } + pBitmap->Canvas->Font->Color = m_Col1; + DrawText(pBitmap->Canvas, xt, yt, bf, ZC); + + TColor col; + int x, y; + int XW = pBitmap->Width; + int YW = pBitmap->Height; + int XL = XW; + int XR = 0; + int YT = YW; + int YB = 0; + BYTE *bp = NULL; + BYTE *sp; + if( m_Grade || m_Shadow ){ + bp = new BYTE[XW * YW]; + sp = bp; + for( y = 0; y < YW; y++ ){ + for( x = 0; x < XW; x++, sp++ ){ + if( pBitmap->Canvas->Pixels[x][y] != cBack ){ + if( XL > x ) XL = x; + if( XR < x ) XR = x; + if( YT > y ) YT = y; + if( YB < y ) YB = y; + *sp = 1; + } + else { + *sp = 0; + } + } + } + MultProc(); + } + int X1, X2, Y1, Y2; + switch(m_Grade){ + case 0: + if( m_Shadow ){ + for( y = YT; y <= YB; y++ ){ + sp = &bp[y*XW + XL]; + for( x = XL; x <= XR; x++, sp++ ){ + if( *sp ){ + pBitmap->Canvas->Pixels[x][y] = m_Col1; + } + } + } + } + break; + case 1: + X1 = (XR - XL) / 3; + for( x = XL; x < X1+XL; x++ ){ + col = GetCol(m_Col1, m_Col2, x - XL, X1); + sp = &bp[YT*XW + x]; + for( y = YT; y <= YB; y++, sp += XW ){ + if( *sp ){ + pBitmap->Canvas->Pixels[x][y] = col; + } + } + } + MultProc(); + X2 = X1+X1; + for( ; x < X2+XL; x++ ){ + col = GetCol(m_Col2, m_Col3, x - X1 - XL, X1); + sp = &bp[YT*XW + x]; + for( y = YT; y <= YB; y++, sp += XW ){ + if( *sp ){ + pBitmap->Canvas->Pixels[x][y] = col; + } + } + } + MultProc(); + for( ; x <= XR; x++ ){ + col = GetCol(m_Col3, m_Col4, x - X2 - XL, X1); + sp = &bp[YT*XW + x]; + for( y = YT; y <= YB; y++, sp += XW ){ + if( *sp ){ + pBitmap->Canvas->Pixels[x][y] = col; + } + } + } + break; + case 2: + Y1 = (YB - YT) / 3; + for( y = YT; y < Y1+YT; y++ ){ + col = GetCol(m_Col1, m_Col2, y - YT, Y1); + sp = &bp[y*XW + XL]; + for( x = XL; x <= XR; x++, sp++ ){ + if( *sp ){ + pBitmap->Canvas->Pixels[x][y] = col; + } + } + } + MultProc(); + Y2 = Y1+Y1; + for( ; y < Y2 + YT; y++ ){ + col = GetCol(m_Col2, m_Col3, y - Y1 - YT, Y1); + sp = &bp[y*XW + XL]; + for( x = XL; x <= XR; x++, sp++ ){ + if( *sp ){ + pBitmap->Canvas->Pixels[x][y] = col; + } + } + } + MultProc(); + for( ; y <= YB; y++ ){ + col = GetCol(m_Col3, m_Col4, y - Y2 - YT, Y1); + sp = &bp[y*XW + XL]; + for( x = XL; x <= XR; x++, sp++ ){ + if( *sp ){ + pBitmap->Canvas->Pixels[x][y] = col; + } + } + } + break; + case 3: + if( (pBrushBitmap != NULL) && pBrushBitmap->Width && pBrushBitmap->Height ){ + for( y = YT; y <= YB; y++ ){ + sp = &bp[y*XW + XL]; + for( x = XL; x <= XR; x++, sp++ ){ + if( *sp ){ + pBitmap->Canvas->Pixels[x][y] = pBrushBitmap->Canvas->Pixels[x % pBrushBitmap->Width][y % pBrushBitmap->Height]; + } + } + } + } + break; + } + + MultProc(); + + Graphics::TBitmap *pBit; + int f, lw; + switch(m_Shadow){ + case 1: + // if( wx > 1 ) wx--; + col = m_ColS; + lw = m_LineWidth; +_sh1: + for( x = 0; x < XW; x++ ){ + f = 0; + sp = &bp[x]; + for( y = 0; y < pBitmap->Height; y++, sp += XW ){ + if( *sp ){ + f = lw; + } + else if( f ){ + pBitmap->Canvas->Pixels[x][y] = col; + *sp = 1; + f--; + } + } + f = 0; + y = YW - 1; + sp = &bp[y*XW+x]; + for( ; y > 0; y--, sp -= XW ){ + if( *sp ){ + f = lw; + } + else if( f ){ + pBitmap->Canvas->Pixels[x][y] = col; + *sp = 1; + f--; + } + } + } + MultProc(); + for( y = 0; y < YW; y++ ){ + f = 0; + sp = &bp[y*XW]; + for( x = 0; x < XW; x++, sp++ ){ + if( *sp ){ + f = lw; + } + else if( f ){ + pBitmap->Canvas->Pixels[x][y] = col; + *sp = 1; + f--; + } + } + f = 0; + x = XW - 1; + sp = &bp[y*XW+x]; + for( ; x > 0; x--, sp-- ){ + if( *sp ){ + f = lw; + } + else if( f ){ + pBitmap->Canvas->Pixels[x][y] = col; + f--; + } + } + } + break; + case 2: + pBit = DupeB(cBack); + pBit->Canvas->Font = pBitmap->Canvas->Font; + pBit->Canvas->Font->Color = m_ColS; + DrawText(pBit->Canvas, xt+wx, yt+wx, bf, ZC); + pBit->Canvas->Draw(0, 0, pBitmap); + delete pBitmap; + pBitmap = pBit; + break; + case 3: + col = m_ColS; + for( x = 0; x < XW; x++ ){ + f = 0; + sp = &bp[x]; + for( y = 0; y < YW; y++, sp += XW ){ + if( *sp ){ + f = wx; + } + else if( f ){ + pBitmap->Canvas->Pixels[x][y] = col; + *sp = 1; + f--; + } + } + } + MultProc(); + for( y = 0; y < YW; y++ ){ + f = 0; + sp = &bp[y*XW]; + for( x = 0; x < XW; x++, sp++ ){ + if( *sp ){ + f = wx; + } + else if( f ){ + pBitmap->Canvas->Pixels[x][y] = col; + f--; + } + } + } + break; + case 4: + case 5: + case 6: + pBit = DupeB(cBack); + pBit->Canvas->Font = pBitmap->Canvas->Font; + { + if( !m_Stack ){ + switch(m_Shadow){ + case 4: + ax = wx; + ay = wx*2; + break; + case 5: + ax = wx*2; + ay = wx; + break; + case 6: + ax = wx*2; + ay = wx*2; + break; + } + ax++; ay++; + } + int m = ABS(ax); + if( ABS(ax) < ABS(ay) ) m = ABS(ay); + if( m_StackPara ){ + for( f = m; f > 0; f-- ){ + col = GetCol(m_ColS, m_ColB, f-1, m); + pBit->Canvas->Font->Color = col; + ::SetBkMode(pBit->Canvas->Handle, TRANSPARENT); + DrawText(pBit->Canvas, xt+(f*ax/m), yt+(f*ay/m), bf, ZC); + } + } + MultProc(); + pBit->Canvas->Draw(0, 0, pBitmap); + delete pBitmap; + pBitmap = pBit; + } + if( (m_Shadow == 6) || m_Stack ){ + lw = 1; + switch(m_Shadow){ + case 4: + col = clBlack; + break; + case 5: + col = clWhite; + break; + case 6: + col = m_LineColor; + lw = m_LineWidth; + break; + } + MultProc(); + goto _sh1; + } + break; + case 7: + pBit = DupeB(cBack); + pBit->Canvas->Font = pBitmap->Canvas->Font; + pBit->Canvas->Font->Color = m_ColS; + ::SetBkMode(pBit->Canvas->Handle, TRANSPARENT); + DrawText(pBit->Canvas, xt-1, yt-1, bf, ZC); + pBit->Canvas->Font->Color = m_ColB; + ::SetBkMode(pBit->Canvas->Handle, TRANSPARENT); + DrawText(pBit->Canvas, xt+1, yt+1, bf, ZC); + pBit->Canvas->Draw(0, 0, pBitmap); + delete pBitmap; + pBitmap = pBit; + break; + } + if( bp != NULL ) delete bp; + if( m_Stack && m_StackPara && ((m_Shadow < 4) || (m_Shadow > 6)) ){ + MultProc(); + pBit = DupeB(cBack); + int m = ABS(ax); + if( ABS(ax) < ABS(ay) ) m = ABS(ay); + for( f = m; f >= 0; f-- ){ + pBit->Canvas->Draw(f*ax/m, f*ay/m, pBitmap); + } + delete pBitmap; + pBitmap = pBit; + } + if( m_PerSpect ){ + MultProc(); + pBit = CreateBitmap(pBitmap->Width, pBitmap->Height, pBitmap->PixelFormat); + pBitmap->Transparent = FALSE; + Perspect(pBitmap, pBit, &m_sperspect, cBack); + delete pBitmap; + pBitmap = pBit; + pBitmap->Transparent = TRUE; + pBitmap->TransparentMode = tmFixed; + pBitmap->TransparentColor = pBitmap->Canvas->Pixels[0][0]; + } + else { + pBitmap->Transparent = TRUE; + pBitmap->TransparentMode = tmAuto; + } + if( m_Vert ) SetMBCP(); +} +#endif + +void __fastcall CDrawText::Move(int x, int y) +{ + if( (m_CX1 == m_CX2) || (m_CY1 == m_CY2) ){ + return; + } + if( m_MC != HT_I ){ + double dx = fabs(double(m_CX2 - m_CX1)/double(m_X2 - m_X1)); + double dy = fabs(double(m_CY2 - m_CY1)/double(m_Y2 - m_Y1)); + double dxx = fabs(dx - 1.0); + double dyy = fabs(dy - 1.0); + if( dxx < dyy ) dx = dy; + int sz = pFont->Size; + sz = sz * dx + 0.5; + if( sz && (sz != pFont->Size) ){ + pFont->Size = sz; + CDrawBox::Move(x, y); + MakeBitmap(); + } + } + else { + int xx = m_X1; + int yy = m_Y1; + CDrawBox::Move(x, y); + m_X += m_X1 - xx; + m_Y += m_Y1 - yy; + } +} + +int __fastcall CDrawText::Finish(int x, int y) +{ + m_X2 = x; + m_Y2 = y; + m_X = m_X1; + m_Y = m_Y1; + pFont = new TFont(); + if( CurText.pFont != NULL ){ + pFont->Assign(CurText.pFont); + } + else { + pFont->Assign(pc->Font); + pFont->Size = 18; + } + MakeBitmap(); + return Edit(); +} + +void __fastcall CDrawText::Draw(TCanvas *tp) +{ + if( pBitmap == NULL ){ + MakeBitmap(); + if( pBitmap == NULL ) return; + } + tp->Draw(m_X1, m_Y1, pBitmap); +} + +void __fastcall CDrawText::DrawFast(TCanvas *tp) +{ +// CDrawBoxS::Draw(tp); + + if( m_Text.IsEmpty() ) return; + char bf[1024]; + Mmsstv->MacroText(bf, m_Text.c_str(), sizeof(bf)-1); + + tp->Font->Assign(pFont); + tp->Font = pFont; + tp->Font->Color = (m_Col1 != tp->Brush->Color) ? m_Col1 : TColor(m_Col1 ^ 0x00ffffff); + int tm = ::SetBkMode(tp->Handle, TRANSPARENT); + if( m_Vert ){ + DrawTextVert(tp, m_X1 + ((m_X2 - m_X1)/2), m_Y1, m_VertH, bf); + } + else { + int x = m_X1; + int y = m_Y1; + if( m_RightAdj ){ + x = m_X2 - tp->TextWidth(bf); + } + if( m_Shadow == 1 ){ + x += m_LineWidth + 1; + y += m_LineWidth + 1; + } + tp->TextOut(x, y, bf); + } + ::SetBkMode(tp->Handle, tm); +} + +int __fastcall CDrawText::Edit(void) +{ + TTextInDlg *pBox = new TTextInDlg(Mmsstv); + int r = pBox->Execute(this); + delete pBox; + if( r == TRUE ){ + if( m_Text.IsEmpty() ){ + r = FALSE; + } + else { + MakeBitmap(); + sys.m_ColText[0] = m_Col1; + sys.m_ColText[1] = m_Col2; + sys.m_ColText[2] = m_Col3; + sys.m_ColText[3] = m_Col4; + sys.m_ColText[4] = m_ColS; + sys.m_ColText[5] = m_ColB; + + sys.m_TextGrade = m_Grade; + sys.m_TextShadow = m_Shadow; + sys.m_TextZero = m_Zero; + sys.m_TextRot = m_Rot; + sys.m_TextVert = m_Vert; + sys.m_TextVertH = m_VertH; + sys.m_TextStack = (m_Stack << 16) | m_StackPara; + if( CurText.pFont == NULL ){ + CurText.pFont = new TFont; + } + CurText.pFont->Assign(pFont); + } + } + return r; +} + +void __fastcall CDrawText::UpdateFont(TFont *pf) +{ + if( pFont == NULL ){ + pFont = new TFont(); + } + pFont->Assign(pf); + MakeBitmap(); + if( CurText.pFont == NULL ){ + CurText.pFont = new TFont(); + } + CurText.pFont->Assign(pFont); +} + +void __fastcall CDrawText::SaveToStream(TStream *sp) +{ + m_Ver = 7; + CDrawBox::SaveToStream(sp); + + sp->Write(&m_Grade, sizeof(m_Grade)); + sp->Write(&m_Shadow, sizeof(m_Shadow)); + sp->Write(&m_Zero, sizeof(m_Zero)); + sp->Write(&m_Rot, sizeof(m_Rot)); + sp->Write(&m_X, sizeof(m_X)); + sp->Write(&m_Y, sizeof(m_Y)); + sp->Write(&m_RightAdj, sizeof(m_RightAdj)); + sp->Write(&m_Stack, sizeof(m_Stack)); + sp->Write(&m_StackPara, sizeof(m_StackPara)); + sp->Write(&m_PerSpect, sizeof(m_PerSpect)); + if( m_PerSpect ){ + sp->Write(&m_sperspect, sizeof(m_sperspect)); + } + sp->Write(&m_Vert, sizeof(m_Vert)); + sp->Write(&m_VertH, sizeof(m_VertH)); + + SaveString(sp, m_Text); + sp->Write(&m_Col1, sizeof(m_Col1)); + sp->Write(&m_Col2, sizeof(m_Col2)); + sp->Write(&m_Col3, sizeof(m_Col3)); + sp->Write(&m_Col4, sizeof(m_Col4)); + sp->Write(&m_ColS, sizeof(m_ColS)); + sp->Write(&m_ColB, sizeof(m_ColB)); + + AnsiString pFontName = pFont->Name; + SaveString(sp, pFontName); //ja7ude 0521 + int d = pFont->Charset; + sp->Write(&d, sizeof(d)); + d = pFont->Height; + if( d >= 0 ) d = -d; + sp->Write(&d, sizeof(d)); + TFontStyles ts = pFont->Style; + d = FontStyle2Code(ts); + sp->Write(&d, sizeof(d)); + d = 0; + sp->Write(&d, sizeof(d)); // dummy + if( m_Grade == 3 ){ + SaveBitmap(sp, pBrushBitmap); + } +} + +int __fastcall CDrawText::LoadFromStream(TCanvas *tp, TStream *sp) +{ + if( CDrawBox::LoadFromStream(tp, sp) == FALSE ) return FALSE; + + try { + sp->Read(&m_Grade, sizeof(m_Grade)); + sp->Read(&m_Shadow, sizeof(m_Shadow)); + if( m_Ver >= 1 ){ + sp->Read(&m_Zero, sizeof(m_Zero)); + } + if( m_Ver >= 2 ){ + sp->Read(&m_Rot, sizeof(m_Rot)); + sp->Read(&m_X, sizeof(m_X)); + sp->Read(&m_Y, sizeof(m_Y)); + } + else { + m_X = m_X1; m_Y = m_Y1; + } + if( m_Ver >= 4 ){ + sp->Read(&m_RightAdj, sizeof(m_RightAdj)); + } + else { + m_X2 = 0; + } + if( m_Ver >= 5 ){ + sp->Read(&m_Stack, sizeof(m_Stack)); + sp->Read(&m_StackPara, sizeof(m_StackPara)); + + sp->Read(&m_PerSpect, sizeof(m_PerSpect)); + if( m_PerSpect ){ + sp->Read(&m_sperspect, sizeof(m_sperspect)); + } + } + else { + m_Stack = 0; + m_PerSpect = 0; + } + if( m_Ver >= 6 ){ + sp->Read(&m_Vert, sizeof(m_Vert)); + sp->Read(&m_VertH, sizeof(m_VertH)); + } + else { + m_Vert = 0; m_VertH = -6; + } + LoadString(sp, m_Text); + sp->Read(&m_Col1, sizeof(m_Col1)); + sp->Read(&m_Col2, sizeof(m_Col2)); + sp->Read(&m_Col3, sizeof(m_Col3)); + sp->Read(&m_Col4, sizeof(m_Col4)); + sp->Read(&m_ColS, sizeof(m_ColS)); + if( m_Ver >= 3 ){ + sp->Read(&m_ColB, sizeof(m_ColB)); + } + if( pFont == NULL ){ + pFont = new TFont(); + } + + AnsiString as; + LoadString(sp, as); + pFont->Name = as; + int d; + sp->Read(&d, sizeof(d)); + pFont->Charset = BYTE(d); + sp->Read(&d, sizeof(d)); + if( d < 0 ){ + pFont->Height = d; + } + else { + pFont->Size = d; + } + sp->Read(&d, sizeof(d)); + TFontStyles ts = Code2FontStyle(d); + pFont->Style = ts; + sp->Read(&d, sizeof(d)); // dummy + if( m_Grade == 3 ){ + if( pBrushBitmap == NULL ){ + pBrushBitmap = new Graphics::TBitmap(); + AdjustBitmapFormat(pBrushBitmap); + } + LoadBitmap(sp, pBrushBitmap); + } + if( (m_Ver <= 6) && (m_Shadow == 6) && !m_Stack ){ + m_LineColor = m_ColS; + } + return TRUE; + } + catch(...){ + return FALSE; + } +} + + +void __fastcall CDrawText::Copy(CDraw *dp) +{ + Copy(dp, 1); +} + +void __fastcall CDrawText::Copy(CDraw *dp, int sw) +{ + CDrawBox::Copy(dp); + CDrawText *sp = (CDrawText *)dp; + + m_Grade = sp->m_Grade; + m_Shadow = sp->m_Shadow; + m_Zero = sp->m_Zero; + m_Rot = sp->m_Rot; + m_RightAdj = sp->m_RightAdj; + m_PerSpect = sp->m_PerSpect; + memcpy(&m_sperspect, &sp->m_sperspect, sizeof(m_sperspect)); + m_Stack = sp->m_Stack; + m_StackPara = sp->m_StackPara; + m_Vert = sp->m_Vert; + m_VertH = sp->m_VertH; + m_X = sp->m_X; + m_Y = sp->m_Y; + m_Text = sp->m_Text; + if( pFont == NULL ){ + pFont = new TFont; + } + pFont->Assign(sp->pFont); + if( sp->pBrushBitmap != NULL ){ + if( pBrushBitmap == NULL ){ + pBrushBitmap = new Graphics::TBitmap(); + AdjustBitmapFormat(pBrushBitmap); + } + pBrushBitmap->Assign(sp->pBrushBitmap); + } + else if( pBrushBitmap != NULL ){ + delete pBrushBitmap; + pBrushBitmap = NULL; + } + m_Col1 = sp->m_Col1; + m_Col2 = sp->m_Col2; + m_Col3 = sp->m_Col3; + m_Col4 = sp->m_Col4; + m_ColS = sp->m_ColS; + m_ColB = sp->m_ColB; + if( sw ){ + MakeBitmap(); + } + else if( pBitmap == NULL ){ + pBitmap = new Graphics::TBitmap(); + AdjustBitmapFormat(pBitmap); + } +} + +void __fastcall CDrawText::UpdateText(void) +{ + MakeBitmap(); +} + +void __fastcall CDrawText::UpdateTimeText(void) +{ + if( IsTimeMacro() ){ + MakeBitmap(); + } +} + +int __fastcall CDrawText::IsTimeMacro(void) +{ + char bf[1024]; + return Mmsstv->MacroText(bf, m_Text.c_str(), sizeof(bf)-1); +} + +//--------------------------------------------------------------------------- +__fastcall CDrawPic::CDrawPic() +{ + m_Command = CM_PIC; + m_Type = 0; + m_Shape = sys.m_PicShape; + m_Adjust = sys.m_PicAdjust; + m_TransPoint = 0; + m_Ver = 5; + pBitmap = NULL; + pLoadBitmap = NULL; + m_LineStyle = TPenStyle(sys.m_PicLineStyle); + m_LineColor = sys.m_PicLineColor; +} + +__fastcall CDrawPic::~CDrawPic() +{ + if( pBitmap != NULL ){ + delete pBitmap; + pBitmap = NULL; + } + if( pLoadBitmap != NULL ){ + delete pLoadBitmap; + pLoadBitmap = NULL; + } +} + +int __fastcall CDrawPic::Finish(int x, int y) +{ + m_X2 = x; + m_Y2 = y; + Normal(); + if( !((m_X1 != m_X2) && (m_Y1 != m_Y2)) ) return FALSE; + CreateBitmap(); + StretchCopy(pBitmap, Mmsstv->pBitmapHistF, HALFTONE); + SetLoadBitmap(Mmsstv->pBitmapHistF); + return Edit(); +} + +void __fastcall CDrawPic::CreateBitmap(void) +{ + pBitmap = ::CreateBitmap(m_X2 - m_X1 - 1, m_Y2 - m_Y1 - 1, -1); +} + +int __fastcall CDrawPic::FinishR(int x, int y) +{ + m_X2 = x; + m_Y2 = y; + Normal(); + if( !((m_X1 != m_X2) && (m_Y1 != m_Y2)) ) return FALSE; + CreateBitmap(); + return TRUE; +} + +void __fastcall CDrawPic::SetLoadBitmap(Graphics::TBitmap *pBmp) +{ + if( pLoadBitmap != NULL ) delete pLoadBitmap; + pLoadBitmap = DupeBitmap(pBmp, -1); +} + +void __fastcall CDrawPic::AdjustSize(void) +{ + ASSERT(pBitmap); + if( (m_Type == 2) && (sys.m_BitPixel == 16) ){ + pBitmap = RemakeBitmap(pBitmap, -1); + } + pBitmap->Width = m_X2 - m_X1 - 1; + pBitmap->Height = m_Y2 - m_Y1 - 1; + if( m_Type && (pLoadBitmap != NULL) ){ + if( m_Type == 2 ){ + StretchCopy(pBitmap, pLoadBitmap, COLORONCOLOR); + } + else { + StretchCopy(pBitmap, NULL, pLoadBitmap, NULL); + } + } + m_DrawPolygon.Copy(&m_Polygon); + m_DrawPolygon.XW = pBitmap->Width; + m_DrawPolygon.YW = pBitmap->Height; + m_DrawPolygon.Stretch(m_Polygon); +} + +//--------------------------------------------------------------------------- +int __fastcall CDrawPic::IsOrgSize(void) +{ + Graphics::TBitmap *pSrc = m_Type ? pLoadBitmap : Mmsstv->pBitmapHist; + if( pSrc == NULL ) return TRUE; + + if( (pBitmap->Width) != pSrc->Width ) return FALSE; + if( (pBitmap->Height) != pSrc->Height ) return FALSE; + return TRUE; +} + +//--------------------------------------------------------------------------- +void __fastcall CDrawPic::SetOrgSize(void) +{ + Graphics::TBitmap *pSrc = m_Type ? pLoadBitmap : Mmsstv->pBitmapHist; + if( pSrc == NULL ) return; + + m_X2 = m_X1 + pSrc->Width + 1; + m_Y2 = m_Y1 + pSrc->Height + 1; + AdjustSize(); +} + +//--------------------------------------------------------------------------- +void __fastcall CDrawPic::KeepAspect(void) +{ + Graphics::TBitmap *pSrc = m_Type ? pLoadBitmap : Mmsstv->pBitmapHist; + if( pSrc == NULL ) return; + + int lx = pBitmap->Width; + int ly = pBitmap->Height; + ::KeepAspect(lx, ly, pSrc->Width, pSrc->Height); + m_X2 = m_X1 + lx + 1; + m_Y2 = m_Y1 + ly + 1; + AdjustSize(); +} + +void __fastcall CDrawPic::Move(int x, int y) +{ + CDrawBox::Move(x, y); + if( (m_X1 == m_X2) || (m_Y1 == m_Y2) ){ + return; + } + if( m_MC != HT_I ){ + if( pBitmap == NULL ){ + pBitmap = new Graphics::TBitmap(); + } + else if( m_Type && (pLoadBitmap == NULL) ){ + pBitmap->Transparent = FALSE; + pLoadBitmap = DupeBitmap(pBitmap, -1); + } + AdjustBitmapFormat(pBitmap); + AdjustSize(); + } +} + +#if 0 +void __fastcall CDrawPic::RoundRect(TCanvas *tp, int xw, int yw) +{ + if( m_LineStyle < 0 ) return; + + if( m_LineStyle >= 5 ){ + int e = (m_LineStyle == 5) ? 4 : 3; + tp->Pen->Style = psSolid; + tp->Pen->Width = 1; + int x1 = m_X1; + int y1 = m_Y1; + int x2 = m_X2; + int y2 = m_Y2; + int xxw = xw; + int yyw = yw; + TColor col = m_LineColor; + TColor tcol = m_LineColor == clBlack ? clWhite : clBlack; +// TColor tcol = TColor(DWORD(m_LineColor) ^ 0x00ffffff); + int i; + for( i = 0; i < e; i++ ){ + tp->Pen->Color = GetCol(col, tcol, i, e); + tp->RoundRect(x1, y1, x2, y2, xxw, yyw); + x1--; y1--; + x2++; y2++; + xxw += 2; + yyw += 2; + } + x1 = m_X1+1; + y1 = m_Y1+1; + x2 = m_X2-1; + y2 = m_Y2-1; + xxw = xw; + yyw = yw; + for( i = 1; i < e; i++ ){ + tp->Pen->Color = GetCol(col, tcol, i, e); + tp->RoundRect(x1, y1, x2, y2, xxw, yyw); + x1++; y1++; + x2--; y2--; + xxw -= 2; + yyw -= 2; + } + } + else { + tp->Pen->Style = m_LineStyle; + tp->RoundRect(m_X1, m_Y1, m_X2, m_Y2, xw, yw); + } +} +#endif + +void __fastcall CDrawPic::Draw(TCanvas *tp) +{ + if( m_Type ){ + if( pBitmap == NULL ) return; + } + else { + if( pBitmap == NULL ) CreateBitmap(); + UpdateHistPic(Mmsstv->pBitmapHistF); + } + + if( m_Type == 2 ){ // オバーレイ + int x = m_TransPoint & 0x0000ffff; + int y = m_TransPoint >> 16; + if( m_TransPoint && (pLoadBitmap != NULL) ){ + x = x * pBitmap->Width / pLoadBitmap->Width; + y = y * pBitmap->Height / pLoadBitmap->Height; + } + pBitmap->Transparent = TRUE; + pBitmap->TransparentMode = tmFixed; + pBitmap->TransparentColor = pBitmap->Canvas->Pixels[x][y]; + tp->Draw(m_X1 + 1, m_Y1 + 1, pBitmap); + pBitmap->Transparent = FALSE; + } + else if( m_Shape ){ + TRect rc; + rc.Left = 0; rc.Top = 0; + rc.Right = pBitmap->Width; + rc.Bottom = pBitmap->Height; + + Graphics::TBitmap *pbmpS = DupeBitmap(pBitmap, pBitmap->PixelFormat); + MultProc(); + Graphics::TBitmap *pbmp = ::CreateBitmap(pBitmap->Width, pBitmap->Height, -1); + pbmp->Canvas->Brush->Color = tp->Brush->Color; + pbmp->Canvas->Pen->Color = tp->Brush->Color; + pbmp->Canvas->FillRect(rc); +#if 1 + TColor bcol = pbmp->Canvas->Pixels[0][0]; +#else + TColor bcol = tp->Brush->Color; +#endif + if( bcol != clBlack ){ + pbmp->Canvas->Brush->Color = clBlack; + pbmp->Canvas->Pen->Color = clBlack; + } + else { + pbmp->Canvas->Brush->Color = clYellow; + pbmp->Canvas->Pen->Color = clYellow; + } + switch(m_Shape){ + case 1: + case 2: + case 3: + case 4: + DBox(pbmp->Canvas, m_Shape, 0, 0, pBitmap->Width, pBitmap->Height); + break; + case 5: + pbmp->Canvas->Polygon((TPoint*)m_DrawPolygon.pBase, m_DrawPolygon.Cnt - 1); + break; + } + MultProc(); + pbmp->Transparent = TRUE; + pbmp->TransparentMode = tmFixed; + pbmp->TransparentColor = pbmp->Canvas->Brush->Color; + pbmpS->Canvas->Draw(0, 0, pbmp); + MultProc(); + pbmpS->Transparent = TRUE; + pbmpS->TransparentMode = tmFixed; + pbmpS->TransparentColor = bcol; + MultProc(); + tp->Draw(m_X1 + 1, m_Y1 + 1, pbmpS); + delete pbmp; + delete pbmpS; + MultProc(); +// if( (m_LineStyle >= 0) && ((m_LineColor != clWhite) || (m_LineStyle != psSolid)) ){ + if( m_LineStyle >= 0 ){ + tp->Pen->Color = m_LineColor; + tp->Pen->Style = m_LineStyle < 5 ? m_LineStyle : psSolid; + tp->Pen->Width = m_LineWidth; + tp->Brush->Style = bsClear; + switch(m_Shape){ + case 1: + RoundRect(tp, pBitmap->Width/3, pBitmap->Height/3); + break; + case 2: + RoundRect(tp, pBitmap->Width/2, pBitmap->Height/2); + break; + case 3: + RoundRect(tp, pBitmap->Width*3/4, pBitmap->Height*3/4); + break; + case 4: + RoundRect(tp, pBitmap->Width, pBitmap->Height); +// tp->Ellipse(m_X1, m_Y1, m_X2, m_Y2); + break; + case 5: + if( m_LineStyle >= 5 ){ + CPolygon Pol; + Pol.Copy(&m_DrawPolygon); + Pol.DrawOffsetSiege(tp, m_X1, m_Y1, m_LineColor, m_LineStyle); + } + else { + CPolygon Pol; + Pol.Copy(&m_DrawPolygon); + Pol.Stretch(m_X2-m_X1+1, m_Y2-m_Y1+1, Pol.XW, Pol.YW); + Pol.DrawOffset(tp, m_X1, m_Y1); + } + break; + } + tp->Brush->Style = bsSolid; + } + } + else { + tp->Draw(m_X1 + 1, m_Y1 + 1, pBitmap); + CDrawBox::Draw(tp); + } +} + +void __fastcall CDrawPic::FillPic(TCanvas *tp, TColor col, int sw, double sx, double sy, int off) +{ + if( pBitmap == NULL ) return; + if( m_Type == 2 ) return; + + TRect rc; + switch(sw){ + case 2: + rc.Left = m_X1; + rc.Top = m_Y1 - 16; + rc.Right = m_X2; + rc.Bottom = m_Y2 - 16; + break; + case 4: + rc.Left = m_X1; + rc.Top = m_Y1 * 240 / 256; + rc.Right = m_X2; + rc.Bottom = (m_Y2 * 240 / 256); + break; + case -1: + rc.Left = m_X1; + rc.Top = m_Y1 + off; + rc.Right = (m_X2 + 1); + rc.Bottom = m_Y2 + off; + break; + default: + rc.Left = m_X1 * sx; + rc.Top = m_Y1 * sy; + rc.Right = m_X2 * sx; + rc.Bottom = m_Y2 * sy; + break; + } + if( m_LineStyle == 5 ){ + rc.Top -= 2; + rc.Left -= 2; + rc.Right += 2; + rc.Bottom += 2; + } + else if( m_LineStyle == 6 ){ + rc.Top--; + rc.Left--; + } + else if( m_LineStyle < 0 ){ + rc.Top++; + rc.Left++; + } + tp->Brush->Color = col; + tp->Pen->Color = col; + switch(m_Shape){ + case 0: + tp->FillRect(rc); + break; + case 1: + tp->RoundRect(rc.Left, rc.Top, rc.Right, rc.Bottom, pBitmap->Width/3, pBitmap->Height/3); + break; + case 2: + tp->RoundRect(rc.Left, rc.Top, rc.Right, rc.Bottom, pBitmap->Width/2, pBitmap->Height/2); + break; + case 3: + tp->RoundRect(rc.Left, rc.Top, rc.Right, rc.Bottom, pBitmap->Width*3/4, pBitmap->Height*3/4); + break; + case 4: + tp->Ellipse(rc.Left, rc.Top, rc.Right, rc.Bottom); + break; + case 5: + { + CPolygon Pol; + Pol.Copy(&m_DrawPolygon); + Pol.Stretch(rc.Right-rc.Left, rc.Bottom-rc.Top, m_X2-m_X1, m_Y2-m_Y1); + Pol.DrawOffset(tp, rc.Left+1, rc.Top+1); + } + break; + } +} + +void __fastcall CDrawPic::UpdateHistPic(Graphics::TBitmap *pBmp) +{ + if( pBitmap == NULL ) return; + if( m_Type ) return; + + TRect rc; + rc.Left = 0; rc.Top = 0; + rc.Right = pBitmap->Width; + rc.Bottom = pBitmap->Height; + int Sop = ::SetStretchBltMode(pBitmap->Canvas->Handle, HALFTONE); + if( m_Adjust && (m_Shape != 5) ){ + int x; + int y = pBmp->Height - 1; + TColor col = pBmp->Canvas->Pixels[0][y]; + for( ; y >= 0; y-- ){ + if( pBmp->Canvas->Pixels[0][y] == col ){ + for( x = 1; x < pBmp->Width; x++ ){ + if( pBmp->Canvas->Pixels[x][y] != col ) break; + } + if( x != pBmp->Width ) break; + } + else { + break; + } + } + if( y == (pBmp->Height - 1) ){ + pBitmap->Canvas->StretchDraw(rc, (TGraphic*)pBmp); + } + else if( y ){ + TRect sc; + sc.Left = 0; sc.Top = 0; + sc.Right = pBmp->Width; + sc.Bottom = y + 1; + pBitmap->Canvas->CopyRect(rc, pBmp->Canvas, sc); + } + else { + FillBitmap(pBitmap, col); + } + } + else { + pBitmap->Canvas->StretchDraw(rc, (TGraphic*)pBmp); + } + ::SetStretchBltMode(pBitmap->Canvas->Handle, Sop); +} + +void __fastcall CDrawPic::SaveToStream(TStream *sp) +{ + m_Ver = 5; + CDrawBox::SaveToStream(sp); + + sp->Write(&m_Type, sizeof(m_Type)); + sp->Write(&m_Shape, sizeof(m_Shape)); + sp->Write(&m_Adjust, sizeof(m_Adjust)); + sp->Write(&m_TransPoint, sizeof(m_TransPoint)); + if( m_Type ){ + SaveBitmap(sp, pBitmap); + } + if( m_Shape == 5 ){ + m_Polygon.SaveToStream(sp); + } +} + +int __fastcall CDrawPic::LoadFromStream(TCanvas *tp, TStream *sp) +{ + if( CDrawBox::LoadFromStream(tp, sp) == FALSE ) return FALSE; + + try { + if( pLoadBitmap != NULL ){ + delete pLoadBitmap; + pLoadBitmap = NULL; + } + if( pBitmap != NULL ){ + delete pBitmap; + pBitmap = NULL; + } + CreateBitmap(); + if( m_Ver >= 1 ){ + sp->Read(&m_Type, sizeof(m_Type)); + if( m_Ver >= 2 ){ + sp->Read(&m_Shape, sizeof(m_Shape)); + } + if( m_Ver >= 4 ){ + sp->Read(&m_Adjust, sizeof(m_Adjust)); + } + if( m_Ver >= 5 ){ + sp->Read(&m_TransPoint, sizeof(m_TransPoint)); + } + if( m_Type ){ + LoadBitmap(sp, pBitmap); + if( (m_Type == 2) && (sys.m_BitPixel == 16) ){ + Graphics::TBitmap *pbmp = DupeBitmap(pBitmap, -1); + delete pBitmap; + pBitmap = pbmp; + } + } + if( m_Shape == 5 ){ + m_Polygon.LoadFromStream(sp); + m_DrawPolygon.Copy(&m_Polygon); + m_DrawPolygon.XW = pBitmap->Width; + m_DrawPolygon.YW = pBitmap->Height; + m_DrawPolygon.Stretch(m_Polygon); + } + } + return TRUE; + } + catch(...){ + return FALSE; + } +} + +void __fastcall CDrawPic::Copy(CDraw *dp) +{ + CDrawBox::Copy(dp); + if( pBitmap != NULL ){ + delete pBitmap; + pBitmap = NULL; + } + if( pLoadBitmap != NULL ){ + delete pLoadBitmap; + pLoadBitmap = NULL; + } + CreateBitmap(); + CDrawPic *sp = (CDrawPic *)dp; + m_Type = sp->m_Type; + m_Shape = sp->m_Shape; + m_Adjust = sp->m_Adjust; + m_TransPoint = sp->m_TransPoint; + if( m_Type && (sp->pBitmap != NULL) ){ + pBitmap->Assign(sp->pBitmap); + } + m_Polygon.Copy(&sp->m_Polygon); + m_DrawPolygon.Copy(&m_Polygon); + m_DrawPolygon.XW = pBitmap->Width; + m_DrawPolygon.YW = pBitmap->Height; + m_DrawPolygon.Stretch(m_Polygon); +} + +int __fastcall CDrawPic::Edit(void) +{ + TPicSelDlg *pBox = new TPicSelDlg(Mmsstv); + int r = pBox->Execute(this); + if( r == TRUE ){ + if( m_Shape != 5 ){ + sys.m_PicShape = m_Shape; + sys.m_PicAdjust = m_Adjust; + sys.m_PicLineStyle = m_LineStyle; + sys.m_PicLineColor = m_LineColor; + } + } + delete pBox; + return r; +} +/// +/// +//--------------------------------------------------------------------------- +__fastcall CDrawOle::CDrawOle() +{ + m_Command = CM_OLE; + m_Ver = 1; + m_Trans = 1; + m_Stretch = 0; + pContainer = NULL; + m_LineStyle = TPenStyle(-1); + m_LineColor = clWhite; + m_X1 = 0; m_Y1 = 0; + m_X2 = m_OrgXW = 160; m_Y2 = m_OrgYW = 128; + pOleView = NULL; +} +//--------------------------------------------------------------------------- +__fastcall CDrawOle::~CDrawOle() +{ + if( pContainer != NULL ){ + delete pContainer; + pContainer = NULL; + } + if( pOleView != NULL ){ + delete pOleView; + } +} +//--------------------------------------------------------------------------- +int __fastcall CDrawOle::Finish(int x, int y) +{ + m_X2 = x; + m_Y2 = y; + Normal(); + if( !((m_X1 != m_X2) && (m_Y1 != m_Y2)) ) return FALSE; + return Edit(); +} + +//--------------------------------------------------------------------------- +Graphics::TBitmap* __fastcall CDrawOle::MakeBitmap(void) +{ + if( pContainer == NULL ) return NULL; + + Graphics::TBitmap *pBitmap = new Graphics::TBitmap(); + AdjustBitmapFormat(pBitmap); + if( m_Stretch ){ + pContainer->SizeMode = smAutoSize; + pBitmap->Width = pContainer->ClientWidth; + pBitmap->Height = pContainer->ClientHeight; + } + else { + pBitmap->Width = m_X2 - m_X1; + pBitmap->Height = m_Y2 - m_Y1; + pContainer->ClientWidth = ABS(m_X2 - m_X1); + pContainer->ClientHeight = ABS(m_Y2 - m_Y1); + } + pBitmap->Transparent = FALSE; + pContainer->PaintTo(pBitmap->Canvas->Handle, 0, 0); + if( m_Stretch ){ + pContainer->SizeMode = smStretch; + Graphics::TBitmap *pBmp = CreateBitmap(m_X2 - m_X1, m_Y2 - m_Y1, -1); + TRect rc; + rc.Left = 0; rc.Right = pBmp->Width; + rc.Top = 0; rc.Bottom = pBmp->Height; + ::SetStretchBltMode(pBmp->Canvas->Handle, m_Trans ? COLORONCOLOR : HALFTONE); + pBmp->Canvas->StretchDraw(rc, pBitmap); + delete pBitmap; + pBitmap = pBmp; + } + return pBitmap; +} +//--------------------------------------------------------------------------- +void __fastcall CDrawOle::Draw(TCanvas *tp) +{ + if( pContainer == NULL ) return; + + Graphics::TBitmap *pBitmap = MakeBitmap(); + if( m_Trans ){ + pBitmap->Transparent = TRUE; + pBitmap->TransparentMode = tmFixed; + pBitmap->TransparentColor = pBitmap->Canvas->Pixels[0][0]; + } + tp->Draw(m_X1, m_Y1, pBitmap); + delete pBitmap; + CDrawBox::Draw(tp); +} +//--------------------------------------------------------------------------- +void __fastcall CDrawOle::SaveToStream(TStream *sp) +{ + m_Ver = 1; + CDrawBox::SaveToStream(sp); + + sp->Write(&m_Trans, sizeof(m_Trans)); + sp->Write(&m_Stretch, sizeof(m_Stretch)); + pContainer->SaveToStream(sp); +} +//--------------------------------------------------------------------------- +int __fastcall CDrawOle::LoadFromStream(TCanvas *tp, TStream *sp) +{ + if( CDrawBox::LoadFromStream(tp, sp) == FALSE ) return FALSE; + + sp->Read(&m_Trans, sizeof(m_Trans)); + sp->Read(&m_Stretch, sizeof(m_Stretch)); + try { + MakeItem(); + pContainer->LoadFromStream(sp); + if( pContainer->Linked ) pContainer->UpdateObject(); + GetOrgSize(); + return TRUE; + } + catch(...){ + return FALSE; + } +} +//--------------------------------------------------------------------------- +void __fastcall CDrawOle::Copy(CDraw *dp) +{ + CDrawOle *sp = (CDrawOle *)dp; + if( sp->pContainer == NULL ) return; + + CDrawBox::Copy(dp); + m_Trans = sp->m_Trans; + m_Stretch = sp->m_Stretch; + m_OrgXW = sp->m_OrgXW; + m_OrgYW = sp->m_OrgYW; + TMemoryStream *tm = new TMemoryStream; + tm->Seek(0, soFromBeginning); + sp->pContainer->SaveToStream(tm); + MakeItem(); + tm->Seek(0, soFromBeginning); + pContainer->LoadFromStream(tm); + delete tm; +} +//--------------------------------------------------------------------------- +void __fastcall CDrawOle::GetOrgSize(void) +{ + pContainer->SizeMode = smAutoSize; + m_OrgXW = pContainer->ClientWidth; + m_OrgYW = pContainer->ClientHeight; + pContainer->SizeMode = smStretch; + if( m_OrgXW <= 0 ) m_OrgXW = 16; + if( m_OrgYW <= 0 ) m_OrgYW = 16; +} +//--------------------------------------------------------------------------- +void __fastcall CDrawOle::SetInitSize(void) +{ + int lx = 256; + int ly = 200; + if( lx > m_OrgXW ) lx = m_OrgXW; + if( ly > m_OrgYW ) ly = m_OrgYW; + ::KeepAspect(lx, ly, m_OrgXW, m_OrgYW); + if( m_X1 < 0 ){ + m_X1 = (Mmsstv->DrawMain.m_SX - lx) / 2; + m_Y1 = (Mmsstv->DrawMain.m_SY - ly) / 2; + } + m_X2 = m_X1 + lx; + m_Y2 = m_Y1 + ly; +} +//--------------------------------------------------------------------------- +void __fastcall CDrawOle::MakeItem(void) +{ + if( pContainer != NULL ){ + delete pContainer; + pContainer = NULL; + } + pContainer = new TOleContainer(Mmsstv); + pContainer->Visible = FALSE; + pContainer->Caption = "MMSSTV"; + pContainer->Parent = Mmsstv->PanelTemp; + pContainer->TabStop = FALSE; + pContainer->Left = 0; + pContainer->Top = 0; + pContainer->ClientWidth = 256; + pContainer->ClientHeight = 200; + pContainer->BorderStyle = bsNone; + pContainer->SizeMode = smStretch; + pContainer->AllowInPlace = FALSE; + pContainer->AutoActivate = aaManual; + pContainer->AllowActiveDoc = FALSE; + pContainer->AutoVerbMenu = FALSE; + pContainer->OldStreamFormat = FALSE; +} +//--------------------------------------------------------------------------- +void __fastcall CDrawOle::SyncVerb(void) +{ + while(pContainer->State == osOpen){ + Application->ProcessMessages(); + if( !Mmsstv->Timer->Enabled ) return; + MultProc(); + ::Sleep(1); + } +} +//--------------------------------------------------------------------------- +void __fastcall CDrawOle::ViewVerb(int sw) +{ + if( sw ){ + if( pOleView == NULL ){ + pOleView = new TForm(Mmsstv); + pOleView->AutoScroll = FALSE; + pOleView->Scaled = FALSE; + } + pOleView->SetBounds(-m_OrgXW, -m_OrgYW, m_OrgXW, m_OrgYW); + pContainer->Parent = pOleView; + pContainer->Visible = TRUE; + pOleView->Visible = TRUE; + } + else if( pOleView != NULL ){ + pOleView->Visible = FALSE; + pContainer->Visible = FALSE; + pContainer->Parent = Mmsstv->PanelTemp; + delete pOleView; + pOleView = NULL; + } +} +//--------------------------------------------------------------------------- +void __fastcall CDrawOle::MakeError(void) +{ + delete pContainer; + pContainer = NULL; + InfoMB( "Can not handle the object." ); +} +//--------------------------------------------------------------------------- +int __fastcall CDrawOle::Edit(void) +{ + SetDisPaint(); + int First = FALSE; + CWaitCursor w; + if( pContainer == NULL ){ + First = TRUE; + MakeItem(); + MultProc(); + if( pContainer->InsertObjectDialog() != TRUE ){ + MultProc(); + ResDisPaint(); + return FALSE; + } + } + MultProc(); + try { + if( !First || !pContainer->Linked ){ + pContainer->AllowInPlace = FALSE; + ViewVerb(1); + pContainer->DoVerb(ovShow); + SyncVerb(); + ViewVerb(0); + } + GetOrgSize(); + if( First ){ + SetInitSize(); + } + } + catch(...){ + ViewVerb(0); + if( First ){ + MakeError(); + } + } + ResDisPaint(); + return (pContainer != NULL) ? TRUE : FALSE; +} +//--------------------------------------------------------------------------- +int __fastcall CDrawOle::LoadFromFile(int x, int y, LPCSTR pName) +{ + int r = TRUE; + CWaitCursor w; + + MakeItem(); + m_X1 = x; + m_Y1 = y; + try { + MultProc(); + pContainer->CreateObjectFromFile(pName, FALSE); + MultProc(); + GetOrgSize(); + SetInitSize(); + } + catch(...){ + MakeError(); + r = FALSE; + } + return r; +} +//--------------------------------------------------------------------------- +void __fastcall CDrawOle::LoadFromBitmap(int x, int y, Graphics::TBitmap *pBmp) +{ + CWaitCursor w; + + char name[256]; + sprintf(name, "%sTEMP.bmp", BgnDir); + if( SaveBitmap24(pBmp, name) == TRUE ){ + LoadFromFile(x, y, name); + } + unlink(name); +} +//--------------------------------------------------------------------------- +int __fastcall CDrawOle::Paste(void) +{ + int r = TRUE; + MakeItem(); + try { + pContainer->Paste(); + GetOrgSize(); + SetInitSize(); + } + catch(...){ + MakeError(); + r = FALSE; + } + return r; +} +//--------------------------------------------------------------------------- +void __fastcall CDrawOle::DoPrimary(void) +{ + if( pContainer != NULL ){ + SetDisPaint(); + try { + ViewVerb(1); + pContainer->DoVerb(ovPrimary); + SyncVerb(); + ViewVerb(0); + GetOrgSize(); + } + catch(...){ + ViewVerb(0); + } + ResDisPaint(); + } +} +//--------------------------------------------------------------------------- +int __fastcall CDrawOle::ObjectProperties(void) +{ + SetDisPaint(); + int r = FALSE; + try { + ViewVerb(1); + r = pContainer->ObjectPropertiesDialog(); + ViewVerb(0); + } + catch(...){ + ViewVerb(0); + } + ResDisPaint(); + return r; +} +//--------------------------------------------------------------------------- +int __fastcall CDrawOle::IsOrgSize(void) +{ + if( (m_X2 - m_X1) != m_OrgXW ) return FALSE; + if( (m_Y2 - m_Y1) != m_OrgYW ) return FALSE; + return TRUE; +} +//--------------------------------------------------------------------------- +void __fastcall CDrawOle::SetOrgSize(void) +{ + m_X2 = m_X1 + m_OrgXW; + m_Y2 = m_Y1 + m_OrgYW; +} +//--------------------------------------------------------------------------- +void __fastcall CDrawOle::KeepAspect(void) +{ + int lx = m_X2 - m_X1; + int ly = m_Y2 - m_Y1; + ::KeepAspect(lx, ly, m_OrgXW, m_OrgYW); + m_X2 = m_X1 + lx + 1; + m_Y2 = m_Y1 + ly + 1; +} +//*************************************************************************** +//DrawLibクラス +//--------------------------------------------------------------------------- +__fastcall CDrawLib::CDrawLib() +{ + m_Command = CM_LIB; + m_Ver = 1; + m_Type = 0; + m_Name = ""; + hLib = NULL; + hObj = NULL; + pBitmap = NULL; + m_LineStyle = TPenStyle(-1); + m_LineColor = clWhite; + m_X1 = 0; m_Y1 = 0; + m_X2 = m_OrgXW = 160; m_Y2 = m_OrgYW = 128; + m_Text = ""; + Delete(); +} +//--------------------------------------------------------------------------- +__fastcall CDrawLib::~CDrawLib() +{ + Delete(); +} +//--------------------------------------------------------------------------- +void __fastcall CDrawLib::Delete(void) +{ + if( hObj != NULL ){ + if( hLib && fDeleteObject ) fDeleteObject(hObj); + hObj = NULL; + } + hLib = NULL; + if( pBitmap != NULL ){ + delete pBitmap; + pBitmap = NULL; + } + + fFunc=NULL; + fLanguage=NULL; + fAboutDialog = NULL; + fGetItemType = NULL; + fCreateObject = NULL; + fCreateStorage = NULL; + fDeleteStorage = NULL; + fDeleteObject = NULL; + fEdit = NULL; + fFont = NULL; + fGetOrgSize = NULL; + fPos = NULL; + fGetUserText = NULL; + fUpdateText = NULL; + fUpdateImage = NULL; + fSetDraft = NULL; + fSetEx = NULL; + fGetFont = NULL; + fSetFont = NULL; + m_Type = 0; +} +//--------------------------------------------------------------------------- +FARPROC __fastcall CDrawLib::GetProc(LPCSTR pName) +{ + FARPROC fp = ::GetProcAddress(hLib, pName); + if( fp != NULL ) return fp; + fp = ::GetProcAddress(hLib, pName+1); + return fp; +} +//--------------------------------------------------------------------------- +void __fastcall CDrawLib::LoadLib(int emsg) +{ + hLib = NULL; + if( m_Name.IsEmpty() ) return; + LPCSTR pName = m_Name.c_str(); + hLib = (HINSTANCE)Libl.LoadLibrary(pName); + if( hLib != NULL ){ + fGetItemType = (mcmGetItemType)GetProc("_mcmGetItemType"); + fCreateObject = (mcmCreateObject)GetProc("_mcmCreateObject"); + fDeleteObject = (mcmDeleteObject)GetProc("_mcmDeleteObject"); + if( !fGetItemType || !fCreateObject || !fDeleteObject ){ + Libl.DeleteLibrary(hLib); + hLib = NULL; + if( emsg ) InfoMB( "Can not invoke %s as MMSSTV's custom item.", pName); + return; + } + fFunc = (mcmFunc)GetProc("_mcmFunc"); + fLanguage = (mcmLanguage)GetProc("_mcmLanguage"); + fAboutDialog = (mcmAboutDialog)GetProc("_mcmAboutDialog"); + fCreateStorage = (mcmCreateStorage)GetProc("_mcmCreateStorage"); + fDeleteStorage = (mcmDeleteStorage)GetProc("_mcmDeleteStorage"); + fEdit = (mcmEdit)GetProc("_mcmEdit"); + fFont = (mcmEdit)GetProc("_mcmFont"); + fGetOrgSize = (mcmGetOrgSize)GetProc("_mcmGetOrgSize"); + fPos = (mcmPos)GetProc("_mcmPos"); + fGetUserText = (mcmGetUserText)GetProc("_mcmGetUserText"); + fUpdateText = (mcmUpdateText)GetProc("_mcmUpdateText"); + fUpdateImage = (mcmUpdateImage)GetProc("_mcmUpdateImage"); + fSetDraft = (mcmSetDraft)GetProc("_mcmSetDraft"); + fSetEx = (mcmSetEx)GetProc("_mcmSetEx"); + fGetFont = (mcmGetFont)GetProc("_mcmGetFont"); + fSetFont = (mcmSetFont)GetProc("_mcmSetFont"); + if( fFunc ){ + fFunc(0, (FARPROC)mmLoadImageMenu); + fFunc(1, (FARPROC)mmLoadImage); + fFunc(2, (FARPROC)mmLoadHistImage); + fFunc(3, (FARPROC)mmSaveImageMenu); + fFunc(4, (FARPROC)mmSaveImage); + fFunc(5, (FARPROC)mmPasteImage); + fFunc(6, (FARPROC)mmGetMacKey); + fFunc(7, (FARPROC)mmConvMac); + fFunc(8, (FARPROC)mmCreateDIB); + fFunc(9, (FARPROC)MultProcA); + fFunc(10, (FARPROC)MultProc); + fFunc(11, (FARPROC)mmColorComp); + fFunc(12, (FARPROC)mmLoadRxImage); + fFunc(13, (FARPROC)mmView); + fFunc(14, (FARPROC)mmAdjCol); + fFunc(15, (FARPROC)mmClip); + } + if( fLanguage ) fLanguage(MsgEng); + } + else if( emsg ){ + InfoMB( "Can not load '%s'", pName); + } +} +//--------------------------------------------------------------------------- +int __fastcall CDrawLib::MakeR(LPCSTR pName) +{ + char drive[_MAX_DRIVE]; + char dir[_MAX_DIR]; + char name[_MAX_FNAME]; + char ext[_MAX_EXT]; + ::_splitpath( pName, drive, dir, name, ext ); + m_Name = drive; + m_Name += dir; + if( !strcmpi(m_Name.c_str(), BgnDir) ){ + m_Name = name; + m_Name += ext; + } + else { + m_Name = pName; + } + if( m_Name.IsEmpty() ) return FALSE; + LoadLib(TRUE); + if( hLib == NULL ) return FALSE; + hObj = fCreateObject(NULL, 0); + if( hObj == NULL ){ + InfoMB( "Fail to create the object from '%s'", m_Name.c_str()); + return FALSE; + } + Pos(); + m_Type = fGetItemType(hObj); + if( m_Type & 3 ) Update(); + return TRUE; +} +//--------------------------------------------------------------------------- +int __fastcall CDrawLib::Finish(int x, int y) +{ + m_X2 = x; + m_Y2 = y; + Normal(); + if( !((m_X1 != m_X2) && (m_Y1 != m_Y2)) ) return FALSE; + TOpenDialog *pDialog = Mmsstv->OpenDialog; + pDialog->Options >> ofCreatePrompt; + pDialog->Options << ofFileMustExist; + pDialog->Title = Mmsstv->KTCI->Caption; + pDialog->Filter = GetLibFilter(); + pDialog->FileName = ""; + pDialog->DefaultExt = "dll"; + pDialog->InitialDir = BgnDir; + SetDisPaint(); + if( Mmsstv->OpenDialogExecute(FALSE) == TRUE ){ + ResDisPaint(); + if( MakeR(AnsiString(pDialog->FileName).c_str()) ){ //ja7ude 0521 + return Edit(); + } + else { + return FALSE; + } + } + ResDisPaint(); + return FALSE; +} +//--------------------------------------------------------------------------- +void __fastcall CDrawLib::Move(int x, int y) +{ + CDrawBox::Move(x, y); + if( (m_X1 == m_X2) || (m_Y1 == m_Y2) ){ + return; + } + if( (m_MC != HT_I) || (m_Type & 0x00000010) ){ + Update(); + } +} +//--------------------------------------------------------------------------- +void __fastcall CDrawLib::SwapHandle(HBITMAP hb) +{ + if( hb ){ + pBitmap->ReleaseHandle(); + pBitmap->Handle = hb; + int x2 = m_X2; + int y2 = m_Y2; + m_X2 = m_X1 + pBitmap->Width; + m_Y2 = m_Y1 + pBitmap->Height; + Pos(); + m_Type = fGetItemType(hObj); + if( m_Type & 0x00400000 ){ // X中央 + int xw = (m_X2 - x2)/2; + m_X1 -= xw; m_X2 -= xw; + } + else if( m_Type & 0x00100000 ){ // 右詰 + int xw = m_X2 - x2; + m_X1 -= xw; m_X2 -= xw; + } + if( m_Type & 0x00800000 ){ // Y中央 + int yw = (m_Y2 - y2)/2; + m_Y1 -= yw; m_Y2 -= yw; + } + else if( m_Type & 0x00200000 ){ // 下詰 + int yw = m_Y2 - y2; + m_Y1 -= yw; m_Y2 -= yw; + } + AdjustRect(); + Pos(); + } + if( fGetOrgSize ){ + ULONG size = fGetOrgSize(hObj); + m_OrgXW = size & 0x0000ffff; + m_OrgYW = size >> 16; + } +} +//--------------------------------------------------------------------------- +void __fastcall CDrawLib::Pos(void) +{ + if( !fPos ) return; + + DWORD pos = m_X1 + (m_Y1 << 16); + DWORD size = (m_X2 - m_X1) + ((m_Y2 - m_Y1) << 16); + DWORD tsize = SXW + (SYW << 16); + fPos(hObj, pos, size, tsize); +} +//--------------------------------------------------------------------------- +void __fastcall CDrawLib::Update(void) +{ + if( !hLib ) return; + if( !hObj ) return; + + switch(m_Type & 3){ + case 0: + if( !fUpdateImage ) return; + + SetBitmapSize(); + Pos(); + SwapHandle(fUpdateImage(hObj, pBitmap->Handle, NULL)); + break; + case 1: + UpdatePic(Mmsstv->pBitmapHistF); + break; + default: + UpdateText(); + break; + } +} +//--------------------------------------------------------------------------- +void __fastcall CDrawLib::SetBitmapSize(void) +{ + if( pBitmap == NULL ){ + pBitmap = new Graphics::TBitmap; + } + pBitmap->PixelFormat = pf24bit; + pBitmap->Width = m_X2 - m_X1; + pBitmap->Height = m_Y2 - m_Y1; + FillBitmap(pBitmap, TransCol); +} +//--------------------------------------------------------------------------- +void __fastcall CDrawLib::DrawFast(TCanvas *tp) +{ + if( hLib && hObj ){ + if( fSetDraft ) fSetDraft(hObj, 1); + Draw(tp); + if( fSetDraft ) fSetDraft(hObj, 0); + } +} +//--------------------------------------------------------------------------- +void __fastcall CDrawLib::Draw(TCanvas *tp) +{ + if( !hLib || !hObj ){ + SetBitmapSize(); + pBitmap->Canvas->Font->Color = clRed; + pBitmap->Canvas->TextOut(1, 1, m_Name); + m_Type = 0; + } + if( pBitmap == NULL ){ + Update(); + if( pBitmap == NULL ) return; + } + + ASSERT(pBitmap); + + Graphics::TBitmap *pbmp = pBitmap; + if( sys.m_BitPixel == 16 ){ + pbmp = DupeBitmap(pBitmap, -1); + } + + if( m_Type & 0x00010000 ){ + pbmp->Transparent = TRUE; + pbmp->TransparentMode = tmFixed; + pbmp->TransparentColor = pbmp->Canvas->Pixels[0][0]; + } + + tp->Draw(m_X1, m_Y1, pbmp); + pbmp->Transparent = FALSE; + if( pbmp != pBitmap ) delete pbmp; + CDrawBox::Draw(tp); +} +//--------------------------------------------------------------------------- +int __fastcall CDrawLib::Edit(int sw) +{ + int r; + if( hLib ){ + if( !hObj ) return FALSE; + + if( fLanguage ) fLanguage(MsgEng); + SetDisPaint(); + MultProc(); + if( sw ){ + r = fFont(hObj, Screen->ActiveForm->Handle); + } + else { + r = fEdit(hObj, Screen->ActiveForm->Handle); + } + MultProc(); + ResDisPaint(); + if( r ){ + Pos(); + m_Type = fGetItemType(hObj); + Update(); + } + } + else { + r = Finish(m_X2, m_Y2); + } + return r; +} +//--------------------------------------------------------------------------- +int __fastcall CDrawLib::Edit(void) +{ + if( !fEdit ) return FALSE; + return Edit(0); +} +//--------------------------------------------------------------------------- +int __fastcall CDrawLib::Font(void) +{ + if( !fFont ) return Edit(); + return Edit(1); +} +//--------------------------------------------------------------------------- +void __fastcall CDrawLib::ObjectProperties(void) +{ + if( hLib ){ + if( !fAboutDialog ) return; + + if( fLanguage ) fLanguage(MsgEng); + fAboutDialog(Screen->ActiveForm->Handle); + } + else { + InfoMB( "Could not load '%s', the item is inactive.", m_Name.c_str()); + } +} +//--------------------------------------------------------------------------- +void __fastcall CDrawLib::SaveToStream(TStream *sp) +{ + m_Ver = 1; + CDrawBox::SaveToStream(sp); + + SaveString(sp, m_Name); + ULONG size = 0; + const BYTE *p = NULL; + if( fCreateStorage ) p = fCreateStorage(hObj, &size); + if( p == NULL ) size = 0; + sp->Write(&size, sizeof(size)); + if( size ) sp->Write(p, size); + if( fDeleteStorage ) fDeleteStorage(hObj, p); +} +//--------------------------------------------------------------------------- +int __fastcall CDrawLib::LoadFromStream(TCanvas *tp, TStream *sp) +{ + Delete(); + if( CDrawBox::LoadFromStream(tp, sp) == FALSE ) return FALSE; + + LoadString(sp, m_Name); + ULONG size = 0; + BYTE *p = NULL; + sp->Read(&size, sizeof(size)); + if( size ){ + p = new BYTE[size]; + sp->Read(p, size); + } + LoadLib(FALSE); + if( hLib && fCreateObject ){ + hObj = fCreateObject(p, size); + if( hObj != NULL ){ + Pos(); + m_Type = fGetItemType(hObj); + } + } + if( p != NULL ) delete p; + return TRUE; +} +//--------------------------------------------------------------------------- +void __fastcall CDrawLib::Copy(CDraw *dp) +{ + CDrawLib *sp = (CDrawLib *)dp; + + TMemoryStream *tm = new TMemoryStream; + tm->Seek(0, soFromBeginning); + sp->SaveToStream(tm); + tm->Seek(0, soFromBeginning); + int cmd; + tm->Read(&cmd, sizeof(cmd)); + if( cmd == CM_LIB ){ + LoadFromStream(Mmsstv->pBitmapTemp->Canvas, tm); + } + delete tm; +} +//--------------------------------------------------------------------------- +int __fastcall CDrawLib::IsOrgSize(void) +{ + if( !hLib ) return TRUE; + + if( m_OrgXW != (m_X2 - m_X1) ) return FALSE; + if( m_OrgYW != (m_Y2 - m_Y1) ) return FALSE; + return TRUE; +} +//--------------------------------------------------------------------------- +void __fastcall CDrawLib::SetOrgSize(void) +{ + if( !hLib ) return; + + m_X2 = m_X1 + m_OrgXW; + m_Y2 = m_Y1 + m_OrgYW; + Update(); +} +//--------------------------------------------------------------------------- +void __fastcall CDrawLib::KeepAspect(void) +{ + if( !hLib ) return; + + int lx = m_X2 - m_X1; + int ly = m_Y2 - m_Y1; + ::KeepAspect(lx, ly, m_OrgXW, m_OrgYW); + m_X2 = m_X1 + lx + 1; + m_Y2 = m_Y1 + ly + 1; + Update(); +} +//--------------------------------------------------------------------------- +void __fastcall CDrawLib::UpdatePic(Graphics::TBitmap *pBmp) +{ + if( !(m_Type & 1) ) return; + if( !hLib ) return; + if( !hObj ) return; + if( !fUpdateImage ) return; + + SetBitmapSize(); + Pos(); + Graphics::TBitmap *ps = (pBmp->PixelFormat != pf24bit) ? DupeBitmap(pBmp, pf24bit) : pBmp; + SwapHandle(fUpdateImage(hObj, pBitmap->Handle, ps->Handle)); + if( ps != pBmp ) delete ps; +} +//--------------------------------------------------------------------------- +void __fastcall CDrawLib::UpdateText(int f) +{ + if( !(m_Type & 2) ) return; + if( !hLib ) return; + if( !hObj ) return; + if( !fGetUserText ) return; + if( !fUpdateText ) return; + + if( fSetEx ) fSetEx(hObj, sys.m_DisFontSmooth); + + char bf[1024]; + LPCSTR pText = fGetUserText(hObj); + if( Mmsstv->MacroText(bf, pText, sizeof(bf)-1) || f ){ + SetBitmapSize(); + Pos(); + SwapHandle(fUpdateText(hObj, pBitmap->Handle, bf)); + } + m_Text = pText; +} +//--------------------------------------------------------------------------- +void __fastcall CDrawLib::UpdateText(void) +{ + UpdateText(1); +} +//--------------------------------------------------------------------------- +void __fastcall CDrawLib::UpdateTimeText(void) +{ + UpdateText(0); +} +//--------------------------------------------------------------------------- +int __fastcall CDrawLib::IsTimeMacro(void) +{ + char bf[1024]; + return Mmsstv->MacroText(bf, m_Text.c_str(), sizeof(bf)-1); +} +//--------------------------------------------------------------------------- +int __fastcall CDrawLib::GetFont(LOGFONT *pLogfont) +{ + if( !hLib || !hObj || !fGetFont ) return FALSE; + fGetFont(hObj, pLogfont); + return TRUE; +} +//--------------------------------------------------------------------------- +int __fastcall CDrawLib::SetFont(LOGFONT *pLogfont) +{ + if( !hLib || !hObj || !fGetFont ) return FALSE; + fSetFont(hObj, pLogfont); + Update(); + return TRUE; +} +//*************************************************************************** +//DrawGroupクラス +//--------------------------------------------------------------------------- +__fastcall CDrawGroup::CDrawGroup() +{ + m_Command = CM_GROUP; + m_Cnt = 0; + m_Max = 0; + m_TransX = 319; + m_TransY = 255; + m_TransCol = TColor(0x00f8f8f8); + m_SX = 320; + m_SY = 256; + m_Ver = 2; + pBase = NULL; + pSel = NULL; +} + +__fastcall CDrawGroup::~CDrawGroup() +{ + Free(); +} + +void __fastcall CDrawGroup::Free(void) +{ + if( pBase != NULL ){ + delete pBase; + pBase = NULL; + } + m_Cnt = m_Max = 0; +} + +void __fastcall CDrawGroup::FreeItem(void) +{ + if( pBase == NULL ) return; + + for( int i = 0; i < m_Cnt; i++ ){ + if( pBase[i]->m_Command == CM_GROUP ){ + ((CDrawGroup *)(pBase[i]))->FreeItem(); + } + delete pBase[i]; + } + delete pBase; + pBase = NULL; + m_Cnt = m_Max = 0; + pSel = NULL; + m_TransX = 319; + m_TransY = 255; + m_TransCol = TColor(0x00f8f8f8); +} + +void __fastcall CDrawGroup::ReleaseResource(void) +{ + if( pBase == NULL ) return; + + for( int i = 0; i < m_Cnt; i++ ){ + pBase[i]->ReleaseResource(); + } +} + +void __fastcall CDrawGroup::UpdatePic(Graphics::TBitmap *pBmp) +{ + if( pBase == NULL ) return; + + TransCol = m_TransCol; + for( int i = 0; i < m_Cnt; i++ ){ + pBase[i]->UpdatePic(pBmp); + } +} + +void __fastcall CDrawGroup::AddItem(CDraw *dp) +{ + if( m_Cnt >= m_Max ){ + m_Max = m_Max ? m_Max * 2 : 16; + CDraw **np = new CDraw*[m_Max]; + if( pBase != NULL ){ + memcpy(np, pBase, sizeof(CDraw*)*m_Cnt); + delete pBase; + } + pBase = np; + } + pBase[m_Cnt] = dp; + m_Cnt++; +} + +void __fastcall CDrawGroup::DeleteItem(CDraw *dp) +{ + if( pBase == NULL ) return; + + for( int i = 0; i < m_Cnt; i++ ){ + if( pBase[i] == dp ){ + delete pBase[i]; + for( ; i < (m_Cnt - 1); i++ ){ + pBase[i] = pBase[i+1]; + } + pBase[i] = NULL; + m_Cnt--; + return; + } + } +} + +void __fastcall CDrawGroup::ReleaseItem(CDraw *dp) +{ + if( pBase == NULL ) return; + + for( int i = 0; i < m_Cnt; i++ ){ + if( pBase[i] == dp ){ + for( ; i < (m_Cnt - 1); i++ ){ + pBase[i] = pBase[i+1]; + } + pBase[i] = NULL; + m_Cnt--; + return; + } + } +} + +CDraw * __fastcall CDrawGroup::AddItemCopy(CDraw *dp) +{ + CDraw *pItem = MakeItem(dp->m_Command); + pItem->Copy(dp); + AddItem(pItem); + return pItem; +} + +void __fastcall CDrawGroup::FillPic(TCanvas *tp, TColor col, int sw, double sx, double sy, int off) +{ + if( pBase == NULL ) return; + + for( int i = 0; i < m_Cnt; i++ ){ + pBase[i]->FillPic(tp, col, sw, sx, sy, off); + } +} + +void __fastcall CDrawGroup::Draw(TCanvas *tp) +{ + if( pBase == NULL ) return; + + TransCol = m_TransCol; + SetDrawSize(m_SX, m_SY); + for( int i = 0; i < m_Cnt; i++ ){ + tp->Brush->Color = m_TransCol; + pBase[i]->Draw(tp); + } +} + +void __fastcall CDrawGroup::DrawFast(TCanvas *tp) +{ + if( pBase == NULL ) return; + + TransCol = m_TransCol; + SetDrawSize(m_SX, m_SY); + for( int i = 0; i < m_Cnt; i++ ){ + tp->Brush->Color = m_TransCol; + pBase[i]->DrawFast(tp); + } +} + +void __fastcall CDrawGroup::DrawNotSel(TCanvas *tp) +{ + if( pBase == NULL ) return; + + TransCol = m_TransCol; + SetDrawSize(m_SX, m_SY); + for( int i = 0; i < m_Cnt; i++ ){ + if( (pBase[i] != pSel) || + (pBase[i]->m_Command == CM_TEXT) || + (pBase[i]->m_Command == CM_PIC) || + (pBase[i]->m_Command == CM_BOXS) || + (pBase[i]->m_Command == CM_OLE) || + (pBase[i]->m_Command == CM_LIB) || + (pBase[i]->m_Command == CM_GROUP) + ){ + tp->Brush->Color = m_TransCol; + pBase[i]->Draw(tp); + } + } +} + +CDraw* __fastcall CDrawGroup::SelectItem(int X, int Y) +{ + if( pBase == NULL ) return NULL; + + for( int i = m_Cnt - 1; i >= 0; i-- ){ + if( (m_Hit = pBase[i]->HitTest(X, Y)) != 0 ){ + return pBase[i]; + } + } + return NULL; +} + +CDraw* __fastcall CDrawGroup::MakeItem(int cmd) +{ + TransCol = m_TransCol; + CDraw *pItem = NULL; + switch(cmd){ + case CM_LINE: + pItem = new CDrawLine; + break; + case CM_BOX: + pItem = new CDrawBox; + break; + case CM_BOXS: + pItem = new CDrawBoxS; + break; + case CM_TEXT: + pItem = new CDrawText; + break; + case CM_PIC: + pItem = new CDrawPic; + break; + case CM_TITLE: + pItem = new CDrawTitle; + break; + case CM_OLE: + pItem = new CDrawOle; + break; + case CM_LIB: + pItem = new CDrawLib; + break; + case CM_GROUP: + pItem = new CDrawGroup; + break; + } + return pItem; +} + +void __fastcall CDrawGroup::SaveToStream(TStream *sp) +{ + m_Ver = 2; + CDrawBox::SaveToStream(sp); + + sp->Write(&m_TransX, sizeof(m_TransX)); + sp->Write(&m_TransY, sizeof(m_TransY)); + sp->Write(&m_TransCol, sizeof(m_TransCol)); + sp->Write(&m_SX, sizeof(m_SX)); + sp->Write(&m_SY, sizeof(m_SY)); + sp->Write(&m_Cnt, sizeof(m_Cnt)); + for( int i = 0; i < m_Cnt; i++ ){ + pBase[i]->SaveToStream(sp); + } +} + +int __fastcall CDrawGroup::LoadFromStream(TCanvas *tp, TStream *sp) +{ + FreeItem(); + MultProc(); + try { + int cnt, cmd; + sp->Read(&cmd, sizeof(cmd)); + if( cmd != CM_GROUP ){ + goto _err; + } + + if( CDrawBox::LoadFromStream(tp, sp) == FALSE ) goto _err; + if( m_Ver >= 1 ){ + sp->Read(&m_TransX, sizeof(m_TransX)); + sp->Read(&m_TransY, sizeof(m_TransY)); + sp->Read(&m_TransCol, sizeof(m_TransCol)); + } + if( m_Ver >= 2 ){ + sp->Read(&m_SX, sizeof(m_SX)); + sp->Read(&m_SY, sizeof(m_SY)); + } + SetDrawSize(m_SX, m_SY); + pSel = NULL; + sp->Read(&cnt, sizeof(cnt)); + for( int i = 0; i < cnt; i++ ){ + MultProcA(); + sp->Read(&cmd, sizeof(cmd)); + CDraw *pItem = MakeItem(cmd); + if( pItem != NULL ){ + if( pItem->LoadFromStream(tp, sp) == FALSE ){ + delete pItem; + goto _err; + } + AddItem(pItem); + } + else { + goto _err; + } + } + if( !m_Cnt ) m_TransCol = TColor(0x00f8f8f8); + m_Ver = 2; + return TRUE; + } + catch(...){ + } +_err:; + FreeItem(); + m_Ver = 1; + return FALSE; +} + +void __fastcall CDrawGroup::Copy(CDraw *dp) +{ + FreeItem(); + + CDrawGroup *sp = (CDrawGroup *)dp; + SetDrawSize(sp->m_SX, sp->m_SY); + m_TransX = sp->m_TransX; + m_TransY = sp->m_TransY; + m_TransCol = sp->m_TransCol; + m_SX = sp->m_SX; + m_SY = sp->m_SY; + for( int i = 0; i < sp->m_Cnt; i++ ){ + AddItemCopy(sp->pBase[i]); + } +} + +void __fastcall CDrawGroup::UpdateText(void) +{ + CWaitCursor w; + + TransCol = m_TransCol; + SetDrawSize(m_SX, m_SY); + for( int i = 0; i < m_Cnt; i++ ){ + pBase[i]->UpdateText(); + } +} + +void __fastcall CDrawGroup::UpdateTimeText(void) +{ + TransCol = m_TransCol; + SetDrawSize(m_SX, m_SY); + for( int i = 0; i < m_Cnt; i++ ){ + pBase[i]->UpdateTimeText(); + } +} + +int __fastcall CDrawGroup::IsMacro(LPCSTR pKey) +{ + LPCSTR pText; + for( int i = 0; i < m_Cnt; i++ ){ + pText = pBase[i]->GetText(); + if( pText != NULL ){ + if( strstr(pText, pKey) != NULL ) return 1; + } +#if 0 + if( pBase[i]->m_Command == CM_TEXT ){ + LPCSTR p = ((CDrawText *)pBase[i])->m_Text.c_str(); + if( strstr(p, pKey) != NULL ) return 1; + } +#endif + } + return 0; +} + +int __fastcall CDrawGroup::IsTimeMacro(void) +{ + for( int i = 0; i < m_Cnt; i++ ){ + if( pBase[i]->IsTimeMacro() ) return 1; + } + return 0; +} + +void __fastcall CDrawGroup::BackItem(CDraw *pItem) +{ + int i, k; + for( i = m_Cnt - 1; i >= 0; i-- ){ + if( pBase[i] == pItem ){ + for( k = i; k > 0; k-- ){ + pBase[k] = pBase[k-1]; + } + pBase[0] = pItem; + break; + } + } +} + +void __fastcall CDrawGroup::FrontItem(CDraw *pItem) +{ + int i, k; + for( i = 0; i < m_Cnt; i++ ){ + if( pBase[i] == pItem ){ + for( k = i; k < m_Cnt - 1; k++ ){ + pBase[k] = pBase[k+1]; + } + pBase[k] = pItem; + break; + } + } +} + +int __fastcall CDrawGroup::UpItem(int n) +{ + if( n ){ + CDraw *pItem = pBase[n-1]; + pBase[n-1] = pBase[n]; + pBase[n] = pItem; + return TRUE; + } + return FALSE; +} + +int __fastcall CDrawGroup::DownItem(int n) +{ + if( n < (m_Cnt - 1) ){ + CDraw *pItem = pBase[n+1]; + pBase[n+1] = pBase[n]; + pBase[n] = pItem; + return TRUE; + } + return FALSE; +} +//-------------------------------------------------------------------------- +void __fastcall DrawTrans(TCanvas *tp, int x, int y) +{ + int rop = ::SetROP2(tp->Handle, R2_NOT); + tp->MoveTo(x - 5, y - 5); + tp->LineTo(x + 5, y - 5); + tp->LineTo(x + 5, y + 5); + tp->LineTo(x - 5, y + 5); + tp->LineTo(x - 5, y - 5); + tp->MoveTo(x - 5, y - 5); + tp->LineTo(x + 5, y + 5); + tp->MoveTo(x - 5, y + 5); + tp->LineTo(x + 5, y - 5); + ::SetROP2(tp->Handle, rop); +} +//-------------------------------------------------------------------------- +void __fastcall CDrawGroup::DrawTrans(TCanvas *tp) +{ + ::DrawTrans(tp, m_TransX, m_TransY); +} +//-------------------------------------------------------------------------- +void __fastcall CDrawGroup::AdjustTransPoint(void) +{ + MultProc(); + int i; + int f = 0; + int XW = 320; + int YW = 256; + for( i = 0; i < m_Cnt; i++ ){ + if( pBase[i]->HitTest(m_TransX, m_TransY) ){ + for( m_TransX = XW-1; m_TransX >= 0; m_TransX -= 5 ){ + for( m_TransY = YW-1; m_TransY >= 0; m_TransY-- ){ + f = 0; + for( i = 0; i < m_Cnt; i++ ){ + if( pBase[i]->HitTest(m_TransX, m_TransY) ){ + f++; + break; + } + } + if( !f ) return; + } + MultProc(); + } + break; + } + } + if( f ){ + for( i = 0; i < m_Cnt; i++ ){ + if( pBase[i]->m_Command == CM_PIC ){ + CDrawPic *pPic = (CDrawPic *)pBase[i]; + if( pPic->m_Type == 2 ){ + m_TransX = pPic->m_X1 + (pPic->m_TransPoint & 0x0000ffff) + 1; + m_TransY = pPic->m_Y1 + (pPic->m_TransPoint >> 16) + 1; + if( m_TransX < 0 ) m_TransX = 0; + if( m_TransY < 0 ) m_TransY = 0; + if( m_TransX >= XW ) m_TransX = XW-1; + if( m_TransY >= YW ) m_TransY = YW-1; + return; + } + } + } + m_TransX = XW-1; + m_TransY = YW-1; + } +} +//-------------------------------------------------------------------------- +void __fastcall CDrawGroup::AdjustTransColor(Graphics::TBitmap *pBmp) +{ + TColor org = m_TransCol; +// m_TransCol = clWhite; + m_TransCol = GetUniqueColor(m_TransCol); + if( !m_Cnt ) return; + + CWaitCursor wait; + + int XW = pBmp->Width; + int YW = pBmp->Height; + int i, y, x, f; + for( i = 0; i < 512; i++ ){ + f = 0; + for( y = 0; y < YW; y++ ){ + for( x = 0; x < XW; x++ ){ + if( pBmp->Canvas->Pixels[x][y] == m_TransCol ){ + f++; + break; + } + } + if( f ) break; + } + if( !f ) break; + m_TransCol = GetUniqueColor(m_TransCol); + MultProc(); + } + if( org != m_TransCol ){ + UpdateText(); + } +} + +//-------------------------------------------------------------------------- +void __fastcall CDrawGroup::GetColorBarPos(int &Y1, int &Y2) +{ + int H = Y2; + int i; + for( i = 0; i < m_Cnt; i++ ){ + CDraw *pItem = pBase[i]; + if( pItem->m_Command == CM_TITLE ){ + if( pItem->m_Y2 < 20 ){ + Y1 = pItem->m_Y2; + } + else if( pItem->m_Y1 >= (H - 20) ){ + Y2 = pItem->m_Y1; + } + } + } + if( Y1 < 0 ) Y1 = 0; + if( Y2 > H ) Y2 = H; +} +//-------------------------------------------------------------------------- +CDraw* __fastcall CDrawGroup::GetLastItem(void) +{ + return m_Cnt ? pBase[m_Cnt-1]: NULL; +} +//-------------------------------------------------------------------------- +int __fastcall CDrawGroup::IsConvBitmap(CDraw *pItem) +{ + if( pItem == NULL ) return FALSE; + + switch(pItem->m_Command){ + case CM_PIC: + { + CDrawPic *pPic = (CDrawPic *)pItem; + return pPic->m_Type != 1 ? TRUE : FALSE; + } + case CM_TEXT: + { + CDrawText *pText = (CDrawText *)pItem; + if( pText->pBitmap == NULL ) return FALSE; + } + return TRUE; + case CM_OLE: + return TRUE; + case CM_LIB: + return TRUE; + } + return FALSE; +} +//-------------------------------------------------------------------------- +CDrawPic* __fastcall CDrawGroup::MakePic(int x, int y, Graphics::TBitmap *pBitmap, int ov) +{ + CDrawPic *pPic = new CDrawPic; + pPic->Start(Mmsstv->PBoxTemp->Canvas, x, y); + if( pPic->FinishR(x + pBitmap->Width + 1, y + pBitmap->Height + 1) ){ + pPic->m_Type = ov ? 2 : 1; + pPic->m_Shape = 0; + pPic->m_LineStyle = TPenStyle(-1); + pBitmap->Transparent = FALSE; + pPic->pBitmap->Canvas->Draw(0, 0, pBitmap); + return pPic; + } + return NULL; +} +//-------------------------------------------------------------------------- +void __fastcall CDrawGroup::ConvBitmap(CDraw *pItem) +{ + if( pItem == NULL ) return; + + int i; + for( i = 0; i < m_Cnt; i++ ){ + if( pBase[i] == pItem ){ + switch(pItem->m_Command){ + case CM_PIC: + { + CDrawPic *pPic = (CDrawPic *)pItem; + pPic->m_Type = 1; + } + break; + case CM_TEXT: + { + CDrawText *pText = (CDrawText *)pItem; + if( pText->pBitmap == NULL ) return; + pSel = MakePic(pText->m_X1 - 1, pText->m_Y1 - 1, pText->pBitmap, 1); + if( pSel != NULL ){ + pBase[i] = pSel; + delete pText; + } + } + break; + case CM_OLE: + { + CDrawOle *pOle = (CDrawOle *)pItem; + Graphics::TBitmap *pBitmap = pOle->MakeBitmap(); + pSel = MakePic(pOle->m_X1 - 1, pOle->m_Y1 - 1, pBitmap, pOle->m_Trans); + if( pSel != NULL ){ + pBase[i] = pSel; + delete pOle; + } + delete pBitmap; + } + break; + case CM_LIB: + { + CDrawLib *pLib = (CDrawLib *)pItem; + if( pLib->pBitmap == NULL ) return; + pSel = MakePic(pLib->m_X1 - 1, pLib->m_Y1 - 1, pLib->pBitmap, pLib->m_Type & 0x00010000); + if( pSel != NULL ){ + pBase[i] = pSel; + delete pLib; + } + } + break; + } + break; + } + } +} +//************************************************************************** +// +//--------------------------------------------------------------------------- +// ファイルからロード +int __fastcall LoadTemplate(CDrawGroup *pItem, LPCSTR pName, TCanvas *tp) +{ + int r = FALSE; + try { + TFileStream *sp = new TFileStream(pName, fmOpenRead); + r = pItem->LoadFromStream((tp != NULL) ? tp : Mmsstv->PBoxTemp->Canvas, sp); + delete sp; + r = TRUE; + } + catch(...){ + } + if( r == FALSE ){ + if( IsFile(pName) ){ + ErrorMB( MsgEng ? "The template file (%s) is not a correct format":"テンプレート(%s)は正しいファイル形式ではありません.", pName); + unlink(pName); + } + } + MultProc(); + return r; +} +//--------------------------------------------------------------------------- +// ファイルへのセーブ +int __fastcall SaveTemplate(CDrawGroup *pItem, LPCSTR pName) +{ + int r = FALSE; + try { + TFileStream *sp = new TFileStream(pName, fmCreate); + pItem->SaveToStream(sp); + delete sp; + r = TRUE; + } + catch(...){ + if( IsFile(pName) && (GetFileAttributes(pName) & FILE_ATTRIBUTE_READONLY) ){ + ErrorMB("'%s' is read-only.", pName); + } + else { + ErrorMB( MsgEng ? "Cannot update '%s":"'%s'を更新できません.", pName); + } + } + MultProc(); + return r; +} +//************************************************************************** +// +//-------------------------------------------------------------------------- +void __fastcall CPolygon::Free(void) +{ + if( pBase != NULL ){ + delete pBase; + pBase = NULL; + } +} + +void __fastcall CPolygon::AddPoint(int X, int Y) +{ + if( Cnt ){ + if( (pBase[Cnt-1].x == X) && (pBase[Cnt-1].y == Y) ) return; + } + if( Cnt >= Max ){ + int max = Max ? Max * 2 : 4; + POINT *pNew = new POINT[max]; + if( pBase != NULL ){ + memcpy(pNew, pBase, Cnt * sizeof(POINT)); + delete pBase; + } + pBase = pNew; + Max = max; + } + pBase[Cnt].x = X; + pBase[Cnt].y = Y; + Cnt++; +} + +void __fastcall CPolygon::SaveToStream(TStream *sp) +{ + int id = 0x55aa2233; + sp->Write(&id, sizeof(id)); + sp->Write(&Cnt, sizeof(Cnt)); + sp->Write(&XW, sizeof(XW)); + sp->Write(&YW, sizeof(YW)); + int i; + POINT *p = pBase; + for( i = 0; i < Cnt; i++, p++ ){ + sp->Write(p, sizeof(POINT)); + } +} + +int __fastcall CPolygon::LoadFromStream(TStream *sp) +{ + sp->Read(&Cnt, sizeof(Cnt)); + if( Cnt == 0x55aa2233 ){ + sp->Read(&Cnt, sizeof(Cnt)); + sp->Read(&XW, sizeof(XW)); + sp->Read(&YW, sizeof(YW)); + } + else { + XW = 256; + YW = 200; + } + if( pBase != NULL ){ + delete pBase; + } + Max = Cnt; + if( Cnt ){ + pBase = new POINT[Max]; + POINT *p = pBase; + for( Cnt = 0; Cnt < Max; Cnt++, p++ ){ + sp->Read(p, sizeof(POINT)); + if( XW != 320 ) p->x = p->x * 320 / XW; + if( YW != 256 ) p->y = p->y * 256 / XW; + } + } + XW = 320; + YW = 256; + return TRUE; +} + +void __fastcall CPolygon::Draw(TCanvas *tp, int loop) +{ + if( !Cnt ) return; + + tp->Brush->Color = clWhite; + tp->Pen->Color = sys.m_PicSelCurCol; +// tp->Pen->Color = clBlue; + tp->Pen->Width = 2; + tp->Pen->Style = psSolid; +// int rop = ::SetROP2(tp->Handle, R2_MERGEPENNOT); + for( int i = 0; i < Cnt; i++ ){ + if( i ){ + tp->LineTo(pBase[i].x, pBase[i].y); + } + else { + tp->MoveTo(pBase[i].x, pBase[i].y); + } + } + if( loop ){ + tp->LineTo(pBase[0].x, pBase[0].y); + } +// ::SetROP2(tp->Handle, rop); +} + +void __fastcall CPolygon::Copy(CPolygon *p) +{ + if( pBase != NULL ){ + delete pBase; + } + Max = Cnt = p->Cnt; + pBase = new POINT[Max]; + memcpy(pBase, p->pBase, sizeof(POINT) * Cnt); + XW = p->XW; + YW = p->YW; +} + +void __fastcall CPolygon::GetCenter(int &xc, int &yc) +{ + if( Cnt < 3 ){ + xc = XW/2; + yc = YW/2; + } + else { + int X, Y; + int XL = 640; + int YT = 496; + int XR = 0; + int YB = 0; + int i; + for( i = 0; i < Cnt; i++ ){ + X = pBase[i].x; + Y = pBase[i].y; + if( XL > X ) XL = X; + if( XR < X ) XR = X; + if( YT > Y ) YT = Y; + if( YB < Y ) YB = Y; + } + xc = (XR + XL)/2; + yc = (YB + YT)/2; + } +} + +void __fastcall CPolygon::DrawOffset(TCanvas *tp, int x, int y) +{ + POINT *pTemp = new POINT[Cnt]; + for( int i = 0; i < Cnt; i++ ){ + pTemp[i].x = pBase[i].x + x; + pTemp[i].y = pBase[i].y + y; + } + tp->Polygon(pTemp, Cnt-1); + delete pTemp; +} + +void __fastcall CPolygon::DrawOffsetSiege(TCanvas *tp, int x, int y, TColor SCol, int e) +{ + if( Cnt < 3 ) return; + int XC, YC; + GetCenter(XC, YC); + + e = e == 5 ? 4 : 3; + int i, j; + POINT *pTemp = new POINT[Cnt]; + tp->Pen->Style = psSolid; + tp->Pen->Width = 1; + tp->Brush->Style = bsClear; + TColor col = SCol; + TColor tcol = SCol == clBlack ? clWhite : clBlack; + double deg, r, xx, yy; + for( i = 0; i < e; i++ ){ + for( j = 0; j < Cnt; j++ ){ +#if 0 + if( pBase[j].x > XC ){ + pTemp[j].x = x + pBase[j].x + i; + } + else { + pTemp[j].x = x + pBase[j].x - i; + } + if( pBase[j].y > YC ){ + pTemp[j].y = y + pBase[j].y + i; + } + else { + pTemp[j].y = y + pBase[j].y - i; + } +#else + xx = pBase[j].x - XC; + yy = YC - pBase[j].y; + if( xx > 0 ){ + deg = atan(double(yy)/double(xx)); + r = sqrt(xx * xx + yy * yy); + } + else if( xx < 0 ){ + deg = atan(double(yy)/double(xx)); + deg += PI; + r = sqrt(xx * xx + yy * yy); + } + else { + deg = yy < 0 ? -PI/2 : PI/2; + r = ABS(yy); + } + r += i; + pTemp[j].x = x + XC + r * cos(deg) + 0.5; + pTemp[j].y = y + YC - r * sin(deg) + 0.5; +#endif + } + tp->Pen->Color = GetCol(col, tcol, i, e); + tp->Polygon(pTemp, Cnt - 1); + } + for( i = 1; i < e; i++ ){ + for( j = 0; j < Cnt; j++ ){ +#if 0 + if( pBase[j].x > XC ){ + pTemp[j].x = x + pBase[j].x - i; + } + else { + pTemp[j].x = x + pBase[j].x + i; + } + if( pBase[j].y > YC ){ + pTemp[j].y = y + pBase[j].y - i; + } + else { + pTemp[j].y = y + pBase[j].y + i; + } +#else + xx = pBase[j].x - XC; + yy = YC - pBase[j].y; + if( xx > 0 ){ + deg = atan(double(yy)/double(xx)); + r = sqrt(xx * xx + yy * yy); + } + else if( xx < 0 ){ + deg = atan(double(yy)/double(xx)); + deg += PI; + r = sqrt(xx * xx + yy * yy); + } + else { + deg = yy < 0 ? -PI/2 : PI/2; + r = ABS(yy); + } + r -= i; + pTemp[j].x = x + XC + r * cos(deg) + 0.5; + pTemp[j].y = y + YC - r * sin(deg) + 0.5; +#endif + } + tp->Pen->Color = GetCol(col, tcol, i, e); + tp->Polygon(pTemp, Cnt - 1); + } + delete pTemp; + tp->Brush->Style = bsSolid; +} + +void __fastcall CPolygon::Stretch(int xw, int yw, int oxw, int oyw) +{ + if( (xw == oxw) && (oxw == oyw) ) return; + + double sx = double(xw)/double(oxw); + double sy = double(yw)/double(oyw); + for( int i = 0; i < Cnt; i++ ){ + pBase[i].x *= sx; + pBase[i].y *= sy; + } +} + +void __fastcall CPolygon::Stretch(CPolygon &pol) +{ + Stretch(XW, YW, pol.XW, pol.YW); +} + +//--------------------------------------------------------------------------- +// 透視変換 +static void __fastcall Matrix(double l[4][4], double m[4][4], double n[4][4]) +{ + int i, j, k; + double d; + + for( i = 0; i < 4; i++ ){ + for( j = 0; j < 4; j++ ){ + for( k = 0, d = 0.0; k < 4; k++ ) d += l[i][k] * m[k][j]; + n[i][j] = d; + } + } +} + +void __fastcall PerspectPara(double k[9], const SPERSPECT *pPar, int xs, int ys) +{ + double l[4][4]; double m[4][4]; double n[4][4]; + double k1, k2, k3, k4, k5, k6, k7, k8, k9; + double u, v, w; + + u = pPar->rx * PI / 180; + v = pPar->ry * PI / 180; + w = pPar->rz * PI / 180; + memset(l, 0, sizeof(l)); memset(m, 0, sizeof(m)); + l[0][0] = 1.0/xs; l[1][1] = -1.0/xs; l[2][2] = 1.0; l[3][3] = 1.0; + m[0][0] = pPar->ax; m[1][1] = pPar->ay; m[2][2] = 1.0; m[3][3] = 1.0; + Matrix(l, m, n); + memset(l, 0, sizeof(l)); + l[0][0] = 1.0; l[1][1] = 1.0; l[2][2] = 1.0; + l[3][0] = pPar->px; l[3][1] = pPar->py; l[3][2] = pPar->pz; l[3][3] = 1.0; + Matrix(n, l, m); + memset(n, 0, sizeof(n)); + n[0][0] = cos(w); n[0][1] = sin(w); + n[1][0] = -n[0][1]; n[1][1] = n[0][0]; + n[2][2] = 1.0; n[3][3] = 1.0; + Matrix(m, n, l); + memset(m, 0, sizeof(m)); + m[0][0] = 1.0; m[1][1] = cos(u); m[1][2] = sin(u); + m[2][1] = -m[1][2]; m[2][2] = m[1][1]; m[3][3] = 1.0; + Matrix(l, m, n); + memset(l, 0, sizeof(l)); + l[0][0] = cos(v); l[0][2] = sin(v); l[1][1] = 1.0; + l[2][0] = -l[0][2]; l[2][2] = l[0][0]; l[3][3] = 1.0; + Matrix(n, l, m); + memset(n, 0, sizeof(n)); + n[0][0] = 1.0; n[1][1] = 1.0; n[2][2] = -1.0; n[3][2] = -pPar->v; n[3][3] = 1.0; + Matrix(m, n, l); + memset(m, 0, sizeof(m)); + m[0][0] = 1.0; m[1][1] = 1.0; m[2][2] = 1/pPar->s; m[2][3] = m[2][2]; + m[3][2] = -1.0; + Matrix(l, m, n); + memset(l, 0, sizeof(l)); + l[0][0] = xs; l[1][1] = -xs; l[2][2] = 1.0; l[3][3] = 1.0; + Matrix(n, l, m); + + k1 = m[0][3]; k2 = m[1][3]; k3 = m[3][3]; + k4 = m[0][0]; k5 = m[1][0]; k6 = m[3][0]; + k7 = m[0][1]; k8 = m[1][1]; k9 = m[3][1]; + + k[0] = k7*k2 - k8*k1; k[1] = k5*k1 - k4*k2; k[2] = k4*k8 - k7*k5; + k[3] = k8*k3 - k9*k2; k[6] = k9*k1 - k7*k5; k[4] = k6*k2 - k5*k3; + k[7] = k4*k3 - k6*k1; k[5] = k5*k9 - k8*k6; k[8] = k7*k6 - k4*k9; +} + +void __fastcall Perspect(Graphics::TBitmap *pSrc, Graphics::TBitmap *pTer, const SPERSPECT *pPar, TColor back) +{ + if( (pSrc->Width < 2) || (pSrc->Height < 2) ){ + CopyBitmap(pTer, pSrc); + } + else { + Graphics::TBitmap *pS = DupeBitmap(pSrc, pf24bit); + Graphics::TBitmap *pT = new Graphics::TBitmap; + pT->PixelFormat = pf24bit; + pT->Width = pTer->Width; + pT->Height = pTer->Height; + if( pT->Width & 1 ) pT->Width--; + if( pT->Height & 1 ) pT->Height--; + int i, j, m, n; + double x, y, w, p, q; + double k[9]; + int xs = pT->Width / 2; + int ys = pT->Height / 2; + PerspectPara(k, pPar, xs, ys); + BYTE *sp1, *sp2; + BYTE *tp; + sp1 = (BYTE *)pS->ScanLine[0]; + BYTE br = *sp1++; + BYTE bg = *sp1++; + BYTE bb = *sp1; + int r, g, b; + for( i = -ys; i < ys; i++ ){ + tp = (BYTE *)pT->ScanLine[i+ys]; + for( j = -xs; j < xs; j++ ){ + w = k[0] * j + k[1] * i + k[2]; + x = k[3] * j + k[4] * i + k[5]; + y = k[6] * j + k[7] * i + k[8]; + x = x / w; + y = y / w; + if( y > 0 ){ m = int(y); } else { m = int(y-1); } + if( x > 0 ){ n = int(x); } else { n = int(x-1); } + q = y - m; + p = x - n; + double pp = 1.0 - p; + double qq = 1.0 - q; + if( (m >= -ys) && (m < ys-1) && (n >= -xs) && (n < xs-1) ){ + sp1 = (BYTE *)pS->ScanLine[m+ys] + (n+xs)*3; + sp2 = (BYTE *)pS->ScanLine[m+ys+1] + (n+xs)*3; + if( (*sp1 != *sp2) || (*sp1 != *(sp1+3)) || (*sp1 != *(sp2+3)) ){ + r = (int)(qq*(pp*(*sp1) + p*(*(sp1+3))) + + q * (pp*(*sp2) + p*(*(sp2+3)))); +// if( ABS(r-br) < 16 ) r = br; + } + else { + r = *sp1; + } + sp1++; sp2++; + if( (*sp1 != *sp2) || (*sp1 != *(sp1+3)) || (*sp1 != *(sp2+3)) ){ + g = (int)(qq*(pp*(*sp1) + p*(*(sp1+3))) + + q * (pp*(*sp2) + p*(*(sp2+3)))); +// if( ABS(g-bg) < 16 ) g = bg; + } + else { + g = *sp1; + } + sp1++; sp2++; + if( (*sp1 != *sp2) || (*sp1 != *(sp1+3)) || (*sp1 != *(sp2+3)) ){ + b = (int)(qq*(pp*(*sp1) + p*(*(sp1+3))) + + q * (pp*(*sp2) + p*(*(sp2+3)))); +// if( ABS(b-bb) < 16 ) b = bb; + } + else { + b = *sp1; + } + if( r < 0 ) r = 0; + if( r > 255 ) r = 255; + if( g < 0 ) g = 0; + if( g > 255 ) g = 255; + if( b < 0 ) b = 0; + if( b > 255 ) b = 255; + *tp++ = BYTE(r); + *tp++ = BYTE(g); + *tp++ = BYTE(b); + } + else { + *tp++ = br; + *tp++ = bg; + *tp++ = bb; + } + } + } + pTer->Width = pT->Width; + pTer->Height = pT->Height; + pTer->Palette = NULL; + pTer->Canvas->Draw(0, 0, pT); + delete pT; + delete pS; + } +} +// +// +//*************************************************************************** +//CLIBLクラス +//*************************************************************************** +// +// +//--------------------------------------------------------------------------- +void __fastcall CLIBL::Alloc(void) +{ + int am = m_AMax ? (m_AMax * 2) : 16; + LIBD *pN = new LIBD[am]; + if( m_pBase != NULL ){ + memcpy(pN, m_pBase, sizeof(LIBD)*m_Count); + delete m_pBase; + } + m_pBase = pN; + m_AMax = am; +} +//--------------------------------------------------------------------------- +void __fastcall CLIBL::Delete(void) +{ + if( m_pBase != NULL ){ + LIBD *cp = m_pBase; + for( int i = 0; i < m_Count; i++, cp++ ){ + delete cp->pName; + ::FreeLibrary(cp->hLib); + } + delete m_pBase; + } + m_pBase = NULL; + m_AMax = 0; + m_Count = 0; +} +//--------------------------------------------------------------------------- +void __fastcall CLIBL::Add(LPCSTR pName, HANDLE hLib) +{ + if( m_Count >= m_AMax ) Alloc(); + LIBD *cp = &m_pBase[m_Count]; + cp->pName = StrDupe(pName); + cp->hLib = (HINSTANCE)hLib; + m_Count++; +} +//--------------------------------------------------------------------------- +HANDLE __fastcall CLIBL::LoadLibrary(LPCSTR pName) +{ + LIBD *cp = m_pBase; + for( int i = 0; i < m_Count; i++, cp++ ){ + if( !strcmpi(cp->pName, pName) ){ + if( cp->hLib == NULL ){ + cp->hLib = ::LoadLibrary(pName); + } + return cp->hLib; + } + } + HANDLE hLib = ::LoadLibrary(pName); + if( hLib != NULL ) Add(pName, hLib); + return hLib; +} +//--------------------------------------------------------------------------- +void __fastcall CLIBL::DeleteLibrary(HANDLE hLib) +{ + if( hLib == NULL ) return; + + LIBD *cp = m_pBase; + for( int i = 0; i < m_Count; i++, cp++ ){ + if( cp->hLib == hLib ){ + ::FreeLibrary((HINSTANCE)hLib); + cp->hLib = NULL; + break; + } + } +} + +#if 0 +//--------------------------------------------------------------------------- +__fastcall CGrid::CGrid() +{ + m_Flag = 0; + m_Intval = 16; +} +//--------------------------------------------------------------------------- +void __fastcall CGrid::Draw(TCanvas *tp, int xw, int yw) +{ + if( !m_Flag ) return; + + int x, y, xx, yy; + + tp->Pen->Width = 1; + int rop = ::SetROP2(tp->Handle, R2_NOT); + for( x = 0; x < xw; x += m_Intval ){ + xx = x * 320 / xw; + tp->MoveTo(xx, 0); + tp->LineTo(xx, yw-1); + } + for( y = 0; y < yw; y += m_Intval ){ + yy = y * 256 / yw; + tp->MoveTo(0, yy); + tp->LineTo(xw-1, yy); + } + ::SetROP2(tp->Handle, rop); +} +//--------------------------------------------------------------------------- +void __fastcall CGrid::Align(int &x1, int &y1, int &x2, int &y2) +{ + if( !m_Flag ) return; + + int xw = x2 - x1; + int yw = y2 - y1; + x1 = int((double(x1) / m_Intval) + 0.5) * m_Intval; + x2 = x1 + xw; + y1 = int((double(y1) / m_Intval) + 0.5) * m_Intval; + y2 = y1 + yw; +} +//--------------------------------------------------------------------------- +void __fastcall CGrid::Align(CDraw *pItem) +{ + Align(pItem->m_X1, pItem->m_Y1, pItem->m_X2, pItem->m_Y2); +} +#endif + +#pragma package(smart_init) + diff --git a/Draw.h b/Draw.h new file mode 100644 index 0000000..17f4d22 --- /dev/null +++ b/Draw.h @@ -0,0 +1,605 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------------- +#ifndef DrawH +#define DrawH +#include +//--------------------------------------------------------------------------- +extern LPCSTR _ShapePIC[2][7]; +extern LPCSTR _ShapeBOX[2][7]; + +#define TEXT24BIT FALSE + + +#define POINT TPoint + +TColor __fastcall GetNearestColor(TColor col); +void __fastcall DrawTrans(TCanvas *tp, int x, int y); +//--------------------------------------------------------------------------- +// CLIBLクラス +typedef struct { + LPCSTR pName; + //HANDLE hLib; + HINSTANCE hLib; //ja7ude 0521 +}LIBD; + +class CLIBL { +public: + int m_AMax; + int m_Count; + LIBD *m_pBase; +private: + void __fastcall Alloc(void); + void __fastcall Add(LPCSTR pName, HANDLE hLib); +public: + CLIBL(){ + m_pBase = NULL; + Delete(); + }; + ~CLIBL(){ + Delete(); + }; + void __fastcall Delete(void); + HANDLE __fastcall LoadLibrary(LPCSTR pName); + void __fastcall DeleteLibrary(HANDLE hLib); +}; +//--------------------------------------------------------------------------- +typedef struct { + double ax; + double ay; + double px; + double py; + double pz; + double rz; + double rx; + double ry; + double v; + double s; +}SPERSPECT; +void __fastcall Perspect(Graphics::TBitmap *pSrc, Graphics::TBitmap *pTer, const SPERSPECT *pPar, TColor back); + +enum { + CM_SELECT, + CM_GROUP, + CM_LINE, + CM_BOX, + CM_TEXT, + CM_PIC, + CM_BOXS, + CM_TITLE, + CM_OLE, + CM_LIB, + + CM_TLIST=0x8000, +}; + +enum { + HT_NONE, + HT_P1, // line + HT_P2, // line + HT_PM, // line + HT_LT, // box + HT_RT, + HT_LB, + HT_RB, + HT_L, + HT_T, + HT_R, + HT_B, + HT_I, +}; + +class CDraw +{ +public: + int m_Command; + int m_Ver; + int m_X1, m_Y1; + int m_X2, m_Y2; + TColor m_LineColor; + TPenStyle m_LineStyle; + int m_LineWidth; + int m_BoxStyle; + +public: + int m_Cursor; + int m_CX1, m_CY1; + int m_CX2, m_CY2; + int m_BX, m_BY; + int m_MF; + int m_MC; +public: + TCanvas *pc; + TPaintBox *pBox; + +public: + __fastcall CDraw(); + virtual __fastcall ~CDraw(){}; + virtual void __fastcall Start(TCanvas *tp, int X, int Y); + virtual int __fastcall Finish(int X, int Y){return FALSE;}; + virtual void __fastcall Draw(TCanvas *tp){}; + virtual void __fastcall DrawFast(TCanvas *tp){Draw(tp);}; + virtual void __fastcall DrawSel(TCanvas *tp, int sw){}; + virtual void __fastcall FillPic(TCanvas *tp, TColor col, int sw, double sx, double sy, int off){}; + virtual void __fastcall Making(int X, int Y){}; + virtual void __fastcall UpdatePic(Graphics::TBitmap *pBmp){}; + virtual int __fastcall HitTest(int x, int y){return FALSE;}; + virtual void __fastcall StartMove(TCanvas *tp, int X, int Y, int code); + virtual void __fastcall Moving(int X, int Y){}; + virtual void __fastcall Move(int X, int Y){}; + virtual int __fastcall IsMove(void){return m_MF;}; + virtual int __fastcall Edit(void); + virtual int __fastcall Color(void); + virtual void __fastcall SaveToStream(TStream *sp); + virtual int __fastcall LoadFromStream(TCanvas *tp, TStream *sp); + virtual void __fastcall Copy(CDraw *dp); + virtual void __fastcall SaveString(TStream *sp, AnsiString &as); + virtual void __fastcall LoadString(TStream *sp, AnsiString &as); + virtual void __fastcall UpdateText(void){}; + virtual void __fastcall UpdateTimeText(void){}; + virtual int __fastcall IsTimeMacro(void){return 0;}; +// TColor GetCol(TColor c1, TColor c2, int x, int xw); + void __fastcall Normal(void); + void __fastcall SaveBitmap(TStream *sp, Graphics::TBitmap *pBitmap); + int __fastcall LoadBitmap(TStream *sp, Graphics::TBitmap *pBitmap); + void __fastcall AdjustRect(void); + virtual void __fastcall ReleaseResource(void){}; + virtual int __fastcall IsOrgSize(void){return TRUE;}; + virtual void __fastcall SetOrgSize(void){}; + virtual void __fastcall KeepAspect(void){}; + virtual LPCSTR __fastcall GetText(void){return NULL;}; +}; + +class CDrawLine : public CDraw +{ +private: + void __fastcall DrawCursor(void); + +protected: +public: + __fastcall CDrawLine(); + virtual __fastcall ~CDrawLine(){}; + virtual int __fastcall Finish(int X, int Y); + virtual void __fastcall Draw(TCanvas *tp); + virtual void __fastcall DrawSel(TCanvas *tp, int sw); + virtual void __fastcall Making(int X, int Y); + virtual int __fastcall HitTest(int x, int y); + virtual void __fastcall Moving(int X, int Y); + virtual void __fastcall Move(int X, int Y); +}; + +class CDrawBox : public CDraw +{ +private: +protected: + void __fastcall DrawCursor(void); + void __fastcall RoundRect(TCanvas *tp, int xw, int yw); +public: + __fastcall CDrawBox(); + virtual __fastcall ~CDrawBox(){}; + + virtual int __fastcall Finish(int X, int Y); + virtual void __fastcall Draw(TCanvas *tp); + virtual void __fastcall DrawSel(TCanvas *tp, int sw); + virtual void __fastcall Making(int X, int Y); + virtual int __fastcall HitTest(int X, int Y); + virtual void __fastcall Moving(int X, int Y); + virtual void __fastcall Move(int X, int Y); +}; + +class CDrawBoxS : public CDrawBox +{ +private: + +protected: +public: + __fastcall CDrawBoxS(); + virtual __fastcall ~CDrawBoxS(){}; + + virtual void __fastcall Draw(TCanvas *tp); +}; + +class CDrawTitle : public CDrawBox +{ +private: +public: + int m_Type; + int m_ColVert; + TColor m_Col1; + TColor m_Col2; + TColor m_Col3; + TColor m_Col4; + AnsiString m_Sound; + Graphics::TBitmap *pBitmap; + +protected: +public: + __fastcall CDrawTitle(); + __fastcall ~CDrawTitle(); + +// virtual int HitTest(int x, int y){return CDrawBox::HitTest(x, y) ? HT_I : HT_NONE;}; + int __fastcall HitTest(int x, int y); + void __fastcall Start(TCanvas *tp, int X, int Y); + int __fastcall Finish(int X, int Y); + void __fastcall FillPic(TCanvas *tp, TColor col, int sw, double sx, double sy, int off); + void __fastcall Draw(TCanvas *tp); + void __fastcall DrawFast(TCanvas *tp); + void __fastcall StartMove(TCanvas *tp, int X, int Y, int code); + void __fastcall Moving(int X, int Y); + void __fastcall Move(int X, int Y); + int __fastcall Edit(void); + int __fastcall Color(void){return Edit();}; + void __fastcall Copy(CDraw *dp); + + void __fastcall SaveToStream(TStream *sp); + int __fastcall LoadFromStream(TCanvas *tp, TStream *sp); +}; + +class CDrawText : public CDrawBoxS +{ +public: + int m_Grade; + int m_Shadow; + int m_Zero; + int m_Rot; + int m_RightAdj; + int m_PerSpect; + int m_Stack; + int m_StackPara; + int m_Vert; + int m_VertH; + SPERSPECT m_sperspect; + AnsiString m_Text; + TFont *pFont; + TColor m_Col1; + TColor m_Col2; + TColor m_Col3; + TColor m_Col4; + TColor m_ColS; + TColor m_ColB; + Graphics::TBitmap *pBitmap; + Graphics::TBitmap *pBrushBitmap; + int m_X; + int m_Y; +private: + Graphics::TBitmap * __fastcall ConvToDDB(Graphics::TBitmap *pBmp); + Graphics::TBitmap * __fastcall ConvToDIB(Graphics::TBitmap *pBmp); + Graphics::TBitmap * __fastcall DupeB(TColor col); + + void __fastcall MakeBitmap(); + int __fastcall ZeroConv(BYTE charset, LPSTR p); + int __fastcall GetMaxWidth(int &n, LPCSTR p); + void __fastcall DrawTextVert(TCanvas *tp, int xc, int y, int fh, LPCSTR p); + void __fastcall DrawTextHoriANSI(TCanvas *tp, int xc, int y, LPCSTR p); + void __fastcall DrawText(TCanvas *cp, int x, int y, LPCSTR p, int zc); +protected: +public: + __fastcall CDrawText(); + __fastcall ~CDrawText(); + +// virtual int HitTest(int x, int y){return CDrawBox::HitTest(x, y) ? HT_I : HT_NONE;}; + int __fastcall Finish(int X, int Y); + void __fastcall Move(int X, int Y); + void __fastcall Draw(TCanvas *tp); + void __fastcall DrawFast(TCanvas *tp); + int __fastcall Edit(void); + int __fastcall Color(void){return Edit();}; + void __fastcall UpdateFont(TFont *pf); + + void __fastcall SaveToStream(TStream *sp); + int __fastcall LoadFromStream(TCanvas *tp, TStream *sp); + void __fastcall Copy(CDraw *dp); + void __fastcall Copy(CDraw *dp, int sw); + void __fastcall UpdateText(void); + void __fastcall UpdateTimeText(void); + int __fastcall IsTimeMacro(void); + void __fastcall ReleaseResource(void); + LPCSTR __fastcall GetText(void){return m_Text.c_str();}; +}; + +class CPolygon +{ +public: + int XW; + int YW; + int Max; // 最大点数 + int Cnt; // 現在の登録点数 + POINT *pBase; // ポイントの配列のポインタ +public: + __fastcall CPolygon(){ + Max = Cnt = 0; + pBase = NULL; + XW = 320; + YW = 256; + }; + __fastcall ~CPolygon(){ + Free(); + }; + void __fastcall Free(void); + void __fastcall AddPoint(int X, int Y); + void __fastcall SaveToStream(TStream *sp); + int __fastcall LoadFromStream(TStream *sp); + void __fastcall Draw(TCanvas *tp, int loop); + void __fastcall DrawOffset(TCanvas *tp, int x, int y); + void __fastcall DrawOffsetSiege(TCanvas *tp, int x, int y, TColor SCol, int e); + void __fastcall GetCenter(int &xc, int &yc); + void __fastcall Copy(CPolygon *p); + void __fastcall Stretch(int xw, int yw, int oxw, int oyw); + void __fastcall Stretch(CPolygon &pol); + void __fastcall Clear(void){ + Cnt = 0; + }; +}; + +class CDrawPic : public CDrawBox +{ +private: +public: + int m_Type; + int m_Shape; + int m_Adjust; + int m_TransPoint; + CPolygon m_Polygon; + CPolygon m_DrawPolygon; + Graphics::TBitmap *pBitmap; + Graphics::TBitmap *pLoadBitmap; +private: + void __fastcall CreateBitmap(void); + void __fastcall AdjustSize(void); + void __fastcall UpdateHistPic(Graphics::TBitmap *pBmp); + +protected: + void __fastcall DrawCursor(void); +public: + __fastcall CDrawPic(); + __fastcall ~CDrawPic(); + + int __fastcall Finish(int X, int Y); + int __fastcall FinishR(int X, int Y); + int __fastcall Color(void){return Edit();}; + void __fastcall Move(int X, int Y); + void __fastcall Draw(TCanvas *tp); + void __fastcall FillPic(TCanvas *tp, TColor col, int sw, double sx, double sy, int off); + void __fastcall SetLoadBitmap(Graphics::TBitmap *pBmp); + + void __fastcall SaveToStream(TStream *sp); + int __fastcall LoadFromStream(TCanvas *tp, TStream *sp); + void __fastcall Copy(CDraw *dp); + + int __fastcall Edit(void); + int __fastcall IsOrgSize(void); + void __fastcall SetOrgSize(void); + void __fastcall KeepAspect(void); +}; + +class CDrawOle : public CDrawBox +{ +public: + int m_Trans; + int m_Stretch; + TOleContainer *pContainer; + int m_OrgXW; + int m_OrgYW; +private: + void __fastcall GetOrgSize(void); + void __fastcall SetInitSize(void); + void __fastcall MakeItem(void); + void __fastcall MakeError(void); + void __fastcall SyncVerb(void); + void __fastcall ViewVerb(int sw); + TForm *pOleView; + +public: + __fastcall CDrawOle(); + __fastcall ~CDrawOle(); + + int __fastcall Finish(int X, int Y); + int __fastcall Color(void){return Edit();}; + Graphics::TBitmap* __fastcall MakeBitmap(void); + void __fastcall Draw(TCanvas *tp); + void __fastcall SaveToStream(TStream *sp); + int __fastcall LoadFromStream(TCanvas *tp, TStream *sp); + void __fastcall Copy(CDraw *dp); + int __fastcall Edit(void); + int __fastcall LoadFromFile(int x, int y, LPCSTR pName); + void __fastcall LoadFromBitmap(int x, int y, Graphics::TBitmap *pBmp); + int __fastcall Paste(void); + void __fastcall DoPrimary(void); + int __fastcall ObjectProperties(void); + int __fastcall IsOrgSize(void); + void __fastcall SetOrgSize(void); + void __fastcall KeepAspect(void); +}; + +#define DISFONTSMOOTHING 0x00000001 +typedef void (__cdecl *mcmFunc)(DWORD func, FARPROC pFunc); +typedef void (__cdecl *mcmLanguage)(DWORD lang); +typedef void (__cdecl *mcmAboutDialog)(HWND hWnd); +typedef HANDLE (__cdecl *mcmCreateObject)(const BYTE *pStorage, DWORD Size); +typedef const BYTE* (__cdecl *mcmCreateStorage)(HANDLE hObj, LPDWORD pSize); +typedef void (__cdecl *mcmDeleteStorage)(HANDLE hObj, const BYTE *pStorage); +typedef void (__cdecl *mcmDeleteObject)(HANDLE hObj); +typedef DWORD (__cdecl *mcmGetItemType)(HANDLE hObj); +typedef DWORD (__cdecl *mcmEdit)(HANDLE hObj, HWND hWnd); +typedef ULONG (__cdecl *mcmGetOrgSize)(HANDLE hObj); +typedef void (__cdecl *mcmPos)(HANDLE hObj, DWORD pos, DWORD size, DWORD tsize); +typedef LPCSTR (__cdecl *mcmGetUserText)(HANDLE hObj); +typedef HBITMAP (__cdecl *mcmUpdateText)(HANDLE hObj, HBITMAP hDest, LPCSTR pText); +typedef HBITMAP (__cdecl *mcmUpdateImage)(HANDLE hObj, HBITMAP hDest, HBITMAP hSrc); +typedef void (__cdecl *mcmSetDraft)(HANDLE hObj, DWORD sw); +typedef void (__cdecl *mcmSetEx)(HANDLE hObj, DWORD ex); +typedef void (__cdecl *mcmGetFont)(HANDLE hObj, LOGFONT *pLogfont); +typedef void (__cdecl *mcmSetFont)(HANDLE hObj, LOGFONT *pLogfont); +class CDrawLib : public CDrawBox +{ +public: + int m_Type; // 0:Static, 1-Text, 2-Image + AnsiString m_Name; // Name of custom item + HINSTANCE hLib; //ja7ude 0521 + HANDLE hObj; + Graphics::TBitmap *pBitmap; + int m_OrgXW; + int m_OrgYW; +private: + mcmFunc fFunc; + mcmLanguage fLanguage; + mcmAboutDialog fAboutDialog; + mcmGetItemType fGetItemType; + mcmCreateObject fCreateObject; + mcmCreateStorage fCreateStorage; + mcmDeleteStorage fDeleteStorage; + mcmDeleteObject fDeleteObject; + mcmEdit fEdit; + mcmEdit fFont; + mcmGetOrgSize fGetOrgSize; + mcmPos fPos; + mcmGetUserText fGetUserText; + mcmUpdateText fUpdateText; + mcmUpdateImage fUpdateImage; + mcmSetDraft fSetDraft; + mcmSetEx fSetEx; + mcmGetFont fGetFont; + mcmSetFont fSetFont; + AnsiString m_Text; + + FARPROC __fastcall GetProc(LPCSTR pName); + void __fastcall Delete(void); + void __fastcall LoadLib(int emsg); + void __fastcall SetBitmapSize(void); + void __fastcall UpdateText(int f); + void __fastcall SwapHandle(HBITMAP hb); + void __fastcall Pos(void); + void __fastcall Update(void); + int __fastcall Edit(int sw); +public: + __fastcall CDrawLib(); + __fastcall ~CDrawLib(); + + int __fastcall MakeR(LPCSTR pName); + int __fastcall Finish(int X, int Y); + int __fastcall Color(void){return Edit();}; + void __fastcall Move(int X, int Y); + void __fastcall Draw(TCanvas *tp); + void __fastcall DrawFast(TCanvas *tp); + void __fastcall SaveToStream(TStream *sp); + int __fastcall LoadFromStream(TCanvas *tp, TStream *sp); + void __fastcall Copy(CDraw *dp); + int __fastcall Edit(void); + int __fastcall Font(void); + void __fastcall ObjectProperties(void); + void __fastcall UpdatePic(Graphics::TBitmap *pBmp); + void __fastcall UpdateText(void); + void __fastcall UpdateTimeText(void); + int __fastcall IsOrgSize(void); + void __fastcall SetOrgSize(void); + void __fastcall KeepAspect(void); + LPCSTR __fastcall GetItemText(void){ + if( !hLib || !hObj || !fGetUserText ) return "???"; + return fGetUserText(hObj); + }; + int __fastcall IsTimeMacro(void); + LPCSTR __fastcall GetText(void){return m_Text.c_str();}; + + int __fastcall GetFont(LOGFONT *pLogfont); + int __fastcall SetFont(LOGFONT *pLogfont); +}; + +class CDrawGroup : public CDrawBox +{ +public: + int m_Max; + int m_Cnt; + int m_TransX, m_TransY; + int m_SX, m_SY; + TColor m_TransCol; + CDraw **pBase; + CDraw *pSel; +public: + int m_Hit; +protected: +public: + __fastcall CDrawGroup(); + __fastcall ~CDrawGroup(); + void __fastcall Free(void); + void __fastcall FreeItem(void); + void __fastcall AddItem(CDraw *dp); + void __fastcall DeleteItem(CDraw *dp); + void __fastcall ReleaseItem(CDraw *dp); + void __fastcall UpdatePic(Graphics::TBitmap *pBmp); + void __fastcall FillPic(TCanvas *tp, TColor col, int sw, double sx, double sy, int off); + void __fastcall Draw(TCanvas *tp); + void __fastcall DrawFast(TCanvas *tp); + void __fastcall DrawNotSel(TCanvas *tp); + CDraw* __fastcall SelectItem(int X, int Y); + int __fastcall HitTest(int x, int y){return CDrawBox::HitTest(x, y) ? HT_I : HT_NONE;}; + + CDraw * __fastcall MakeItem(int cmd); + CDraw * __fastcall AddItemCopy(CDraw *dp); + virtual void __fastcall SaveToStream(TStream *sp); + virtual int __fastcall LoadFromStream(TCanvas *tp, TStream *sp); + + virtual void __fastcall Copy(CDraw *dp); + void __fastcall UpdateText(void); + void __fastcall UpdateTimeText(void); + int __fastcall IsTimeMacro(void); + + void __fastcall BackItem(CDraw *pItem); + void __fastcall FrontItem(CDraw *pItem); + int __fastcall UpItem(int n); + int __fastcall DownItem(int n); + void __fastcall DrawTrans(TCanvas *tp); + + int __fastcall IsMacro(LPCSTR pKey); + void __fastcall AdjustTransPoint(void); + void __fastcall AdjustTransColor(Graphics::TBitmap *pBmp); + void __fastcall ReleaseResource(void); + void __fastcall GetColorBarPos(int &Y1, int &Y2); + CDraw * __fastcall GetLastItem(void); + + int __fastcall IsConvBitmap(CDraw *pItem); + void __fastcall ConvBitmap(CDraw *pItem); + CDrawPic* __fastcall MakePic(int x, int y, Graphics::TBitmap *pBitmap, int ov); +}; + + +#if 0 +//--------------------------------------------------------------------------- +class CGrid { +public: + int m_Flag; + int m_Intval; +public: + __fastcall CGrid(); + void __fastcall Draw(TCanvas *tp, int xw, int yw); + void __fastcall Align(int &x1, int &y1, int &x2, int &y2); + void __fastcall Align(CDraw *pItem); +}; +#endif + +//--------------------------------------------------------------------------- +int __fastcall LoadTemplate(CDrawGroup *pItem, LPCSTR pName, TCanvas *tp); +int __fastcall SaveTemplate(CDrawGroup *pItem, LPCSTR pName); + +void __fastcall SetDrawSize(int x, int y); +TColor __fastcall GetCol(TColor c1, TColor c2, int x, int xw); + +extern CDrawGroup DrawPara; +#endif + diff --git a/EMMSSTV.TXT b/EMMSSTV.TXT new file mode 100644 index 0000000..6275efd --- /dev/null +++ b/EMMSSTV.TXT @@ -0,0 +1,784 @@ +Basic operations of MMSSTV + +Version 1.08 - July 12, 2002 by JE3HHT Makoto Mori +Translated into English by JA7UDE Nobuyuki Oba + +======== +Preface +======== + +This program is for transmitting and receiving SSTV using a PC soundcard. I was making a utility to adjust the soundcard clock for PSK31 programs. However, I have changed my mind, and the utility has eventually become an SSTV program. + +I thought that I should have made at least one SSTV QSO with this MMSSTV and then declared it as the release version 1.0. However, I am very busy on my own business and will have no time for amateur radio. In addition, there seem to be some people already using this program. At this time, I have decided to release this version as 1.00. + +======================== +Uninstall MMSSTV +======================== + +MMSSTV does not add anything to the Windows registry. +Delete the entire directory where MMSSTV is installed. + + +======== +System requirement +======== + +OS: Windows 95, 98, 98SE, ME, NT, 2000 +Soundcard: 16-bit 11025Hz or 22050Hz +Video adaptor: 256 or more colors (16- or 24-bit video adaptor is +recommended) +RAM: 32MB or more + +I managed to run MMSSTV on my old PC with a Pentium 100MHz, but I strongly recommend a faster CPU. + +The operation speed of MMSSTV is highly dependent on the performance of the video adaptor. In other words, even if two PCs have the same CPU, they should give different performance in accordance with the equipped video adaptor. In particular, the 256-color video adaptor is likely to consume more CPU power for the pallet calculation. For this reason, a 16- or 24-bit color adaptor is strongly recommended. +If a 256-color video adaptor is used, the displayed colors are affected by the performance of the pallet calculation. + +To save the CPU power, try the following steps. + - Increase the FIFO size of the soundcard. + (select Option, select the Misc tab, and increase the value + in the sound FIFO size) + - Disable the RxBPF + (select Option, select the RX tab, and check RxBPF OFF) + - Choose RX buffer FILE or turn it off + (select Option, select the RX tab, and check NONE or FILE + in the RX buffer pane) + - Turn the TX BPF off + (select Option, select TX tab, and uncheck Tx BPF) + +In default, the Loopback is turned off. When it is turned on, MMSSTV performs TX and RX in parallel and increases the CPU load. Make sure you turn it off if your PC cannot afford to run them in parallel. + + +--- IMPORTANT NOTICE --- +The RX buffer temporarily stores the receiving or just received image to get it back to the RX window after adjusting the slant and phase. The buffer stores 270-second sound data, and therefore it would cause page swapping if the RAM is selected or if the physical memory size of your PC is not sufficient to keep the data on the memory. If you have intermittent halts during the receive operation, please select FILE or turn it off. + +The size of the receive buffer is BIG; probably bigger than you expect. If you do not use the automatic slant adjustment function, you should not have any operation difficulties without the receive buffer. + + +======== +PC and radio hookup +======== + +You can use the same interface of MMTTY. +Refer to the MMTTY help. + +======== +PTT +======== + +You can use the same interface of MMTTY. +Refer to the MMTTY help. + + +======== +SSTV modes +======== + +MMSSTV supports the following SSTV modes. + +Mode Duration (sec) Size Method +Robot B/W 8 8 160x120 Mono tone +Robot B/W 12 12 160x120 Mono tone +Robot 24 24 160x120 Color differentiation +Robot 36 36 320x240 Color differentiation +Robot 72 72 320x240 Color differentiation +AVT 90 90 320x240 RGB (no synchronization pulse involved) +Scottie 1 110 320x256 RGB +Scottie 2 71 320x256 RGB +Scottie DX 269 320x256 RGB +Martin 1 114 320x256 RGB +Martin 2 58 320x256 RGB +SC2-180 182 320x256 RGB +SC2-120 122 320x256 RGB +SC2-60 62 320x256 RGB +PD50 50 320x256 Color differentiation +PD90 90 320x256 Color differentiation +PD120 126 640x496 Color differentiation +PD160 161 512x400 Color differentiation +PD180 187 640x496 Color differentiation +PD240 248 640x496 Color differentiation +PD290 289 800x616 Color differentiation +P3 203 640x496 RGB +P5 305 640x496 RGB +P7 406 640x496 RGB + +As far as I know, all the domestic SSTV QSOs in JA are made in the Scottie 1 mode. In US, Scottie 1 and 2 are commonly used. In EU, Martin 1 and 2 are commonly used. + +The following modes are in the experimental phase. + +MP73 73 320x256 Color differentiation +MP115 115 320x256 Color differentiation +MP140 140 320x256 Color differentiation +MP175 175 320x256 Color differentiation +MR73 73 320x256 Color differentiation +MR90 90 320x256 Color differentiation +MR115 115 320x256 Color differentiation +MR140 140 320x256 Color differentiation +MR175 175 320x256 Color differentiation +ML180 180 640x496 Color differentiation +ML240 240 640x496 Color differentiation +ML280 280 640x496 Color differentiation +ML320 320 640x496 Color differentiation + +MP mode: It is based on the color difference scheme that the PD mode uses. This mode should be useful for reducing multi-path distortion and jitter. The scan time for each pixel is longer than the other modes, but the color information along the vertical axis is compressed. + +MR/ML mode: It is based on the color difference scheme that the Robot 24/72 mode uses. This mode is aimed for offering good resolution in good condx. The color information along the horizontal axis is compressed. + +These modes are not new to SSTV actually, but I have added them by way of trial. In particular, I have considered good trade-off between the transmission time, picture size, and quality. As a new trial, the VIS signal is expanded to 16 bits. + + +======== +SSTV operating frequencies +======== + +In JA, the most active frequency is 7.033 MHz LSB. The common frequencies in the world are: 14.230, 21.340, and 28.680 MHz USB. I have noticed that these frequencies are crowded nowadays. I recommend you make QSY after you once made a contact at these call frequencies to avoid unexpected QRM. + + +======== +Receive SSTV +======== + +(1) Tone frequency + +SSTV's tone frequencies are defined as follows: + Synchronization pulse 1200 Hz + Low level of the image 1500 Hz + High level of the image 2300 Hz + +There are four marker lines in the spectrum window of MMSSTV. From left to right: + Green line 1200Hz Synchronization pulse + Yellow line 1500Hz Low level of the image + Yellow dotted line 1900Hz Center level of the image + Yellow line 2300Hz High level of the image + +To tune the frequency, make the signal energy be laid between the 1500Hz and 2300Hz marker lines. Alternatively, you can tune the receiver so that the synchronization pulses are on the 1200Hz marker line. +However, the synchronization pulse is very short, so it might take time for you to get used to adjusting the frequency in this way. + +Since SSTV QSOs are made on the fixed common frequencies, you probably do not have difficulty in tuning the radio after you have done once. + +(2) Automatic start + +When the Auto button in the RX mode pane is depressed, MMSSTV automatically starts the receive operation in response to the start trigger signal. +The start trigger signal is called VIS signal, which consists of the 1200MHz marker signal and the SSTV mode code (1100Hz and 1300Hz FSK). MMSSTV detects the signal by using a resonant FSK demodulator, and automatically starts the receive operation if it finds the mode supported. + +To automatically start receiving, MMSSTV provides another method, which measures the interval time of the synchronization pulses. If you do not want to use this method, go to Option, select RX tab and choose 'VIS only' in the auto start option. + +* Squelch +Four levels (Lowest, Lower, Higher, and Highest) for the trigger threshold can be selected. +Lowest makes MMSSTV trigger with the weakest signal. +Highest makes MMSSTV trigger with the strongest signal. In other words, only the strong signal can kick off the receive operation. + +(3) Manual start + +In case MMSSTV does not automatically start receiving or you want to start receiving not from the beginning, push one of the mode buttons below the Auto button. In JA, HL, and US, try Scottie 1. In EU, try Martin 1. + +(4) Automatic stop, restart and resync + +When the auto stop in the RX window of the Setup MMSSTV is checked, MMSSTV automatically stops receiving in case it has lost the synchronization signal (this does not work in AVT90). + +When the auto start in the RX window of the Setup MMSSTV is checked, MMSSTV restarts the receiving from the beginning in case it detects the VIS signal even during the receive operation. It should be noted, however, that MMSSTV would not be able to detect the VIS signal because of the RxBPF effect. + +When the auto resync box in the RX window of MMSSTV Setup is checked, MMSSTV automatically attempts to re-synchronize the RX image. This is useful if the MMSSTV has lost the synchronization during RX. +However, a couple of lines are displayed with the old synchronization timing and therefore they might appear as a thin bar. + + +(5) Slant adjustment + +MMSSTV latches the SSTV signal with respect to the soundcard clock. For this reason, you would have a slanted image if the soundcard clock of your PC is not correctly calibrated or if the timing of the received signal is discriminated. There are three ways to adjust the slant. + +- High-accuracy slant adjustment +- Automatic slant adjustment +- Manual slant adjustment + +High-accuracy slant adjustment and Automatic slant adjustment analyze the timing of the received signal to automatically adjust the slant. They, however, might not work well in the situations of QRM, multipath, or weak signals. + + +The adjusted clock timing is applied only to the current image; it is not memorized in the MMSSTV. If you want to keep the timing adjusted, push the Mem button. The adjusted timing is used for all the images afterwards. + + +== High-accuracy slant adjustment == + +In this method, MMSSTV uses the least square method to solve the linear equation for analyzing the synchronization timings. For high quality RX signals, it will give the error less than 2ppm. +To start the high-accuracy slant adjustment, push the NicoNico button (comment by JA7UDE: the smiley button). You also can start it by right clicking on the sync or RX window and selecting "High-accuracy slant adjustment" in the pop-up menu. It should be noted that you must have received at least 16 scan lines to make this adjustment operational. The more the scan lines, the better the accuracy. + + +* You cannot use this method if you turn the RX buffer off. + + +== Automatic slant adjustment == + + +In Automatic slant adjustment, MMSSTV periodically measures the interval of the synchronization signals and automatically adjust the slant. When you leave this mode turned on, MMSSTV adjust the image in real time, but it gives slightly less accuracy than the High-accuracy slant adjustment. + +To start this method, check the Auto slant box in the RX tab of the Setup MMSSTV menu. You also can start it by right clicking on the RX window and selecting Auto slant adjustment in the pop-up menu. + + +* You cannot use this method if you turn the RX buffer off. + + + +== Manual slant adjustment == + Click the Sync tab of the main window and do the following procedure. + +1) Push Slant button +2) Click the upper right edge of the synchronization signal (white line) +3) Click the lower right edge of the synchronization signal (same white line) + +The synchronization signal is displayed in a relatively fat line, so you must click the same side. Immediately after you click once on the line, a guide cursor is displayed. Adjust the cursor in parallel with the synchronization signal line, and click again. + +According to this procedure, MMSSTV recalculates the sampling clock of the soundcard and adjusts the receiving or just received image. If you do not obtain the acceptable result, repeat the procedure. + +In case of small slant, it is a good idea to use the up-down button at the bottom of the Sync window. Click on the View menu, select Always show RX viewer, push the up-down button with looking at the slant of the image. + + +When you have obtained the successful adjustment and want to use it as the default frequency, push the Mem button; otherwise MMSSTV applies the adjustment to the current image only. + +* If you turn the RX buffer off, you cannot redraw the picture after adjusting the slant. + + +(6) Fine tune of the synchronization point + +MMSSTV automatically gets the receive operation synchronized with the transmitted image except in case of AVT90. However, it at times fails to do so in very bad conditions. You should immediately become aware of such a condition because the image is ill colored. + +If you are aware of the case, try the procedure below: + +1) Push Sync tab of the main window. +2) Push Phase button. +3) Click the left edge of the synchronization line (fat white line). + +MMSSTV arranges the image so that the clicked point becomes the leftmost position of the image window. If you do not get it right position, repeat the procedure. + +AVT90 does not have the synchronization signal in the image data. For this reason, you will see only a monochrome image in the Sync window. You can click one of the gaps (there are three gaps). + +* If you turn the RX buffer off, you cannot redraw the picture after you adjust the phase. + + + +======== +Receive history +======== + +MMSSTV can store up to 32 received images in default. To increase or decrease this number, click Option, select Setup, click Misc tab, and change the value in the History max box. If the number of stored images would exceed the specified value, the oldest image is erased in an FIFO manner. + +It should be noted that one image requires about 200KB disk space, and thus 256 images require about 50MB. Pay attention to the disk space of your PC. + +To reduce the disk space, you could use the JPEG format. Click the picture with the right button of your mouse and select Use JPEG format in the pop-up menu. + +The RX history is only used for a temporary buffer. The old pictures will automatically be deleted. If you want to keep them, right click and check the auto copy to another folder. + +With this automatic copy function turned on, MMSSTV records the index into the QSL field of the log so that it can retrieve the picture later. + +To manually copy the history picture to another folder, drag and drop the picture in the history window to the QSL box in the log window. To use this function, you must define the name of the target folder in advance. + +MMSSTV automatically records the index in the QSL field of the log, either if the auto copy is turned on or if the history image is dropped in the QSL box. Using the MMSSTV log facility, you anytime can refer to the image by pressing the Image button. + + + +======== +Transmit SSTV +======== + +To transmit an SSTV image, click TX tab of the main window. The image you see there is transmitted (What You See is What You Transmit). Adjust the mic gain appropriately. + + ***** DO NOT USE SPEECH PROCESSOR ***** + +(1) TX image preparation + +There are several ways to prepare the TX image. + +1. Drag&drop an image from the stocked picture gallery at the bottom in the main window to the TX window. + +2. Drag&drop an image from the thumbnail window of the folder (View -> Always show thumbnails of files folder) to the TX window. + +3. Drag&drop an image from Windows file manager (Explorer) to the TX window. + +4. Drag&drop an image from another image manipulation tool that supports Drag&drop to the TX window. + +5. Copy&paste an image from another image manipulation tool to the TX window through the Windows clipboard. + +You can make the TX image superimposed with a template. The template operation is explained in the later section of this document. + +Click the TX image with the right button of the mouse to get a pop-up menu that facilitates image manipulations, such as file load and save. Drag&drop from Internet Explore is also supported. + + +(2) Mode selection + +Select the SSTV mode. + +* If you uncheck "SSTV mode fixed" in the TX page of MMSSTV Setup option, MMSSTV automatically uses the SSTV mode that was used by the most recently received RX image. + + +(3) Transmission + +Push the TX button at the left bottom of the window to start transmission. The horizontal marker line moves from top to bottom as the image is transmitted. MMSSTV automatically returns to RX after it completes the transmission. If you want to abort the transmission, push the TX button again. + +MMSSTV has a 12-second sound buffer, which should be big enough in the normal environment. If your PC is not powerful, you had better not do other operations during the transmission. + +If MMSSTV has lost the timing during TX, it shows a caution message after the TX completion. In this particular case, you might be able to solve this problem by increasing the number of FIFO in the Misc page of the Setup window. + + +(4) Adjustment of the slant of the TX image + +Some soundcards (especially PCI form factors') have slightly different frequencies for recording and playing. In this particular case, even if you have correctly adjusted the clock in RX, you would have a slant image in TX. + +MMSSTV has a means to adjust the soundcard clock for TX and RX independently. Refer to the Soundcard section at the end of this document for details. + +(5) Tune button and CWID + +For repeaters in US, MMSSTV has a tone generator. Push the Tune button to transmit a 1750Hz tone. + +You can send a CWID after the TX completion. Check the CWID box in the TX of the Setup window. This is for a European friend of mine. + + + +======== +Template +======== + +Using a template, you can make a simple picture, which is superimposed to the TX image. For example, you can use a macro command that puts his/her call sign on the TX image. + + +MMSSTV provides primitive image-manipulation functions, but has no support for the group operations now. + +Make picture items using the tool buttons at the bottom of the window. + +- Arrow button Turn on/off the selection mode +- Line button Draw line + +- Square button Draw rectangle +- Shaded square button Draw rectangle with color pasted +- T button Draw text +- Picture button Insert picture or history image +- Color bar button Draw color bar +- Scissors button Cut the item +- Paste button Paste the item +- Color palette button Change the color +- L button Change the property of the selected item +- f button Change the font + +To use a macro text, for example, push T button and then click the point in the window where the text is placed. The text input dialog box is displayed. Push Macro button and select %c to place his/her callsign there. + +To move the item, push Arrow button and use drag&drop it. + +Here I do not cover all the operations, but they are similar to the DRAW software. Give it a try by yourself. + +* You can use drag&drop to copy an image (BMP or JPG) from a file manager (e.g., Explorer) to the template box. + + +====== +Superimpose the template over the TX image +====== + +When you use a template, MMSSTV superimposes all the colors except a transparent one in the template over the TX image. The default transparent color is defined at the bottom right position of the template window. You can change the position by right clicking at the arbitrary spot in the window. However, you must click the spot where no template item resides in. + +Special care should be taken if you place a template item at the bottom right of the window. + +In version 0.21 or later, the function that automatically replaces the transparent point is default ON. Therefore, the transparent point is automatically moved to where no template item exists. + +You can use any color as the transparent (background) color, but you must choose the color that you do not use in the template. However, a color bar and an image are the exceptions. In other words, you even can choose a color that is used in a color bar or an image as a transparent one. + +* You can settle a background color that is not used in the template by right clicking on the template and selecting "find unique background color." + +If you want to create or edit the TX picture during the QSO, I would recommend you use other editing software programs, which have excellent capability in manipulating images. + +The template of MMSSTV is supposed to offer the macro functions, such as his/her call sign, RSV report, and contest numbers. Therefore, you would not find good reason to use templates if you do not use the logging function. + + + +======== +Stock area +======== + +MMSSTV has a stock area, which can stores up to 300 images. Each stocked image has the image data and the template information. To manipulate the clipboard, save and load files, click the stock image with the right button of the mouse. You will have a popup menu. + +To save the disk space, you can use the JPEG format for the stocked images. +Right click the image and select Use JPEG format in the pop-up menu. + +It is a good idea to make a template picture in association with the TX image in advance. The stocked area can store the images and the templates independently. However, if you use drag&drop to copy the stock image to the TX window, MMSSTV copies the associated template, too. +This is effective only if the Show superimposed templates box is checked. +If the box is not checked, MMSSTV copies the image and the template independently. + +The following table shows how MMSSTV performs the drag&drop operation. + + +[Show superimposed templates ON] + +From To Action +---------------------------------------------------------------------- +S.pic TX window Copy the image and template +S.template Template window Copy the template only +TX window S.pic Copy the image and template +Template window S.template Copy the template only + + +[Show superimposed templates OFF] + +From To Action +---------------------------------------------------------------------- +S.pic TX window Copy the image only +S.template Template window Copy the template only +TX window S.pic Copy the image only +Template window S.template Copy the template only + + +You can drag&drop an image from Explorer or My Computer to the stock. + +It takes substantial time to make the text change in effect in the template. +For this reason, the window redraw is slowed down during superimposing of the template in the stocked image area. If you do not like it, try checking off Show superimposed templates or checking on Draft. In addition, the JPEG format will require a little bit longer time to re-read the file. + +* If you get the thumbnail window of the folder displayed on the stocked images window, MMSSTV will use the thumbnail window on behalf of the stocked image window. +MMSSTV temporarily hides the thumbnail window when you switch to the stocked template window. + + +====================== +Picture size and header +====================== + +The number of scan lines in the Robot and AVT modes is 240. On the other hand, that in the Scottie and Martin modes is 256. This difference is due to the domestic TV modes on which the SSTV modes are based. +Robot and AVT were devised in the US and defined to have 240 scan lines after the NTSC. Scottie and Martin were devised in the UK and defined to have 256 scan lines. My guess is that, to make them compatible to Robot and AVT, the first 16 lines are used for the header that has no picture data. +When the receiver uses a scan converter and an NTSC TV set, he/she should see only the 240 scan lines on the TV set. + +I think, however, the 16 lines make no sense in the SSTV using PC. The 16 lines could have some information on the sending picture. + +MMSSTV allows users to define the header (16 scan lines) by using the template item. The following TX modes are supported. + +----- Raw picture has 240 lines; the SSTV mode has 256 lines (e.g., Scottie) +1) Define the header in the template. +2) Push "Shift picture for the header color bar" button to shift down the raw picture. +or +2) Preserve the upper margin in the picture clipper and copy it to the TX window. + +----- Raw picture has 256 lines; the SSTV mode has 256 lines (e.g., Scottie) +You can put a header to the first 16 lines, or you put no header. Either is OK. Bear in mind, however, that some receivers/converters will not be able to display the first 16 lines. + +When you use the header, you could push the "Adjust picture for the header color bar" button in the TX window so as not to get the raw picture hidden behind the color bar. In this case, the aspect ratio of the raw picture is changed. + +----- Raw picture has 240 lines; the SSTV mode has 240 lines (e.g., Robot) +MMSSTV transmits the image without a header. + +----- Raw picture has 256 lines; the SSTV mode has 240 lines (e.g., Robot) +1) Define the header in the template. +2) Push the "Shift picture and template for 240 line mode" button to shift up the raw picture and the template. The upper 16 lines of the raw picture are not transmitted. +or +Define the template without a header. The lower 16 lines of the raw picture are not transmitted. If you push "Adjust picture and template for 240 line mode" button, you do not lose the lower 16 lines but the aspect ratio of the picture is changed. + + + +==================== +Program menu +==================== + +With the program menu, you can instantly start your favorite programs, such as an image manipulation tool, PSK31, RTTY, and MFSK16 programs. + +If you check Suspend box in the Assign menu, MMSSTV automatically goes down to the suspended state and starts the selected program. In this state, MMSSTV has released the COM and soundcard resources in order to allow the other program to use them. To restart MMSSTV, first terminate the program and then click the MMSSTV icon in the Windows task bar. + +When you want to start the program that is not assigned to the MMSSTV program menu, you can select Suspend in the Program option. +MMSSTV has released the hardware resources of the COM and soundcard and makes itself iconized. + +If you wake MMSSTV up again while the other program that uses the COM and soundcard resources is running, MMSSTV would show an error message. +In this case, MMSSTV will not be iconized again. To resume MMSSTV, terminate the other program and wake MMSSTV up again, or select Restore in the Program menu. + +* You do not have to check Suspend for an image manipulation tool, because it typically does not use the COM or soundcard. + + +======== +Radio command +======== + + +Refer to the MMTTY manual. + + + +======== +Demodulator +======== + +This section describes the digital signal processing used in MMSSTV. Refer to Digital.Txt of MMTTY for basic DSP operations. + +MMSSTV has three types of demodulators. + +(1) Demodulator configuration + +MMSSTV's demodulator has the following configuration. + +Sound --> BPF (FIR) --+> BPF1100 (IIR) --> VIS symbol '1' + | + +> BPF1300 (IIR) --> VIS symbol '0' + | + +> BPF1200 (IIR) --> Sync + | + ---> Zero cross det. --> Picture data + (1500 to 2300) + or + | + ---> PLL(1500 to 2300) --> Picture data + or + | + ---> Hilbert(1500 to 2300) --> Picture data + + +The zero cross detector's configuration is + + ---> Differentiator ---> Counter ---> Out LPF ---> Pic. data + + +The next figure shows the PLL configuration + + ---> Phase det. ---> Loop LPF ----> Out LPF ----> Pic. data + | | + <---- VCO <------------- + +The next figure shows the Hilbert transform configuration. I got this idea from JA6UHL Nishimura-san (MNI TNX to JA6UHL). + + --+-> Delay(N) -> Real + | |==> ATAN -> Differentiator -> LPF -> Pic. data + --> FIR(2N) --> Image + + +According to my experiences, they have the following pros and cons. Please give it a try by yourself to find your favorite method. + +Decoder Zero-cross PLL Hilbert transform +Color accuracy Fair Good Good +Image resolution Fair Fair Good +QSB Good Fair Good +CPU load Low Low High +Sampling freq. HB* HB* ---------- + +*HB: The higher, the better. + + +In the zero-cross and PLL methods, you can set the cut-off frequency of the OutLPF higher. + +In the Hilbert transform, the accuracy of the phase differentiation degrades as the sampling frequency increases. The default sampling frequency, 11025Hz, gives better results, though MMSSTV does the decimation to keep the transform accuracy. + + +(2) Zero cross detector parameters + +[Out LPF] +This filter smoothes the frequency ingredients obtained by the counter. +If you want a sharp image, increase the cut-off frequency. +If you want a low-noise image, decrease the cut-off frequency. +You can select an IIR or FIR filter for the Out LPF. However, it seems that they have no significant difference. The FIR filter is better for low sampling frequency because it consumes lower CPU power than the IIR filter. + + +(3) PLL parameters + +The parameters of the PLL affect the picture quality. Since the behavior of this PLL is just the same as that of the hardware PLL, try adjusting the parameters as you have better results. + +[VCO Gain] +VCO gain strongly affects the response of PLL. Higher VCO gain gives quicker response; lower VCO gain gives slower response. To high VCO gain would result in the oscillation of the decoded signal. + +[Loop LPF] +In addition to VCO, the Loop LPF is an important parameter that dominates the loop dumping factor. Always use a one-order filter. If you increase the cut-off frequency, the oscillation amplitude of the decoded signal becomes bigger. + + +[Out LPF] +The Out LPF filter does not affect the response of the PLL because it sits outside of the loop. It, however, should be noted that it strongly affects the picture quality. If you want a sharp picture, set the cut-off frequency higher. If you want a low-noise picture, set it lower. Adjust it according to your preference. + + +(4) Differentiator + +When the Differentiator box is checked, MMSSTV compensates the LPF effect by boosting the high-frequency ingredient of the received image. +However, it makes the receive image be more likely affected by the noise. +Try adjusting the effect with the slider for your preference. As the slider goes right, the differentiator takes sharper effect. + +*The differentiator is not related to the differentiator of the zero-cross detector. + + +(5) Level converter + +The level converter translates the frequency value derived by the decoder into the color amplitude values. MMSSTV provides two types of converters, which can be selected in the RX window of MMSSTV Setup. + +- Linear converter (uncheck the polynomial box) +It assumes that the frequency and the color level are linearly related. It is simple, but the frequency characteristics of the decoder must be linear. + +- Polynomial converter (check the polynomial box) +It uses a 17-th order polynomial formula for the level conversion. It works better if the frequency characteristics of the decoder are not linear. Since the converter uses a pre-calculated table to boost the processing speed, it should not require much more CPU load. + +It is a good idea to use the polynomial converter for the 11025MHz zero-cross detector because it has a little linearity problem in 2200 to 2300Hz. As the sampling frequency goes higher, the decoder will have better linearity. However, even in 11025Hz, the conversion error is 2/256 - 3/256, and therefore the error might not be visible. + +MMSSTV starts the automatic calibration by pressing the calibration button in the RX window of MMSSTV Setup. It takes about 20 seconds. +After the calibration, MMSSTV shows the frequency characteristics figure. +If the line of the figure goes straight down to the right, you can uncheck the polynomial converter (you can use the linear converter). + +=============== +Profile +=============== +The default demodulator parameters are settled according to my experiments, which, however, are very limited. I have had no sufficient time for the parameter optimization. If you are a master of SSTV, you already have found good parameters. + +With the Profile function, you can easily save and load up to 8 sets of the demodulator parameters. Each set can be named, as you like. + +It is a good idea to save your favorite demodulator parameter set as MyDefault before you try many different parameters. If you got lost in the parameter setting, you will be able to step back to the start point. + +MMSSTV has a special profile "MMSSTV Default," which cannot be modified by the user. This is the MMSSTV default parameter set. + +* It should be noted that the Profile memorizes the demodulator parameters only. + + +==================== +Supplemental RX filters +==================== + +MMSSTV has three supplemental RX filters. + + Sound ---> Notch ---> LMS -+-> BPF ---> Demodulator + | + --> Spectrum display + +[Notch] + This is a simple BEF (band elimination filter) of FIR type. The notch filter is engaged when the user left clicks on the spectrum or waterfall window. To disable the filter, just right click. + The notch filter eliminates a beat, but it possibly degrades the image quality if the notch frequency is set in the image transmission frequency range. If the frequency of the filter is on or close to the synchronization signal, MMSSTV would stop RX for weak SSTV signals if Auto stop function is turned on. + + +[LMS] + It is an adaptive filter based on Leaky LMS (Least mean Square) method. It can be turned on/off using the LMS button in the main window. + The default mode is noise smoothing. You can select automatic notch modes by right clicking on the LMS button. + + The response of the automatic notch filter is intentionally set slow so as not to degrade the image quality. Even set so, some images will be affected. + + + +[BPF] +It is a simple FIR band-pass filter. You can choose the sharpness in the RX page of the setup MMSSTV menu. As it is sharper, it is more likely to exclude adjacent QRMs, but on the other hand it degrades the horizontal resolution. + + +================ +TX filter + +================ + +MMSSTV generates the TX signal with the flow shown below. + +Picture data ---> LPF ---> VCO ---> BPF ---> D/A ---> Sound data + ON/OFF ON/OFF + +LPF and BPF are used to limit the frequency of the digital output as insurance. +If the CPU load is too high for TX, you can turn them off. However, I strongly recommend that you turn the BPF on when you use CWID. + + +[LPF] +This filter smoothes the signal translation from the image to the frequency domain. +As a result, the frequency bandwidth is substantially limited and the horizontal resolution of the TX image is slightly sacrificed. + +[BPF] +This filter limits the bandwidth of the TX signal. It is useful to limit the spectrum spread for CWID. + +======== +Sample frequency +======== + +MMSSTV has an option that allows the following sampling frequencies: + + 8000 Hz Secondary standard frequency + 11025 Hz Primary standard frequency + 12000 Hz + 14000 Hz + 16000 Hz + 18000 Hz + 22050 Hz Primary standard frequency + 24000 Hz + 44100 Hz Primary standard frequency + +You will have better quality in the RX images by increasing the sampling frequency and setting the cut-off frequency higher in the zero-cross and PLL decoders. In the Hilbert transform decoder, on the other hand, I recommend the default sampling frequency 11025Hz. + + + It should be noted that not all the soundcards support the frequencies listed above all. All the soundcards, however, should support 11025Hz, 22050Hz and 44100Hz. In addition, the high frequency dissipates more CPU power and more memory space. + +Tips: +* MMSSTV always calculates the FFT with 2048 points. To obtain the proper frequency resolution, MMSSTV uses a half frequency for FFT in case the sampling frequency is 18000Hz or higher. In the same manner, MMSSTV uses a quarter frequency in case of 44100Hz. + + +======== +Clock calibration +======== + +In SSTV, the discrimination of the clock appears as a slanted image. For MMSSTV, you are not required to have the absolute and exact clock frequency value (e.g. 11025Hz). But it is important to get MMSSTV informed on what the frequency of your soundcard has. + + +In normal situations, you would only have to adjust the slant by using the Sync window. If you want to calibrate your soundcard very accurately, listen to the standard radio or fax wave. + +1) Go Option, Setup, Misc page, and push Adj button. +2) Receive standard radio wave (e.g., WWV and JJY). +3) Tune into the tick sound. +4) Continue listening to the sound for a while. You have a vertical line. +5) Click the upper point of the line. +6) Click the lower point of the line. + +You could use FAX broadcasting instead of WWV or JJY, but be sure it has exact timing. Refer to the MMTTY help for details. + +If your soundcard seems to have different clock sampling frequencies for TX and RX, adjust the offset frequency with the following procedure. + +1) Adjust the slant in RX. +2) Go Option, Setup, and TX page. Select External in the Loopback. +3) Connect the Line-out to the Line-in of your soundcard. +4) Transmit an image with Martin 1. +5) You should have an image through the external feedback. +6) After completing the image receive, go Sync page and adjust the slant. + - You could use the High-accuracy slant adjustment. + - Do not push the Mem button +7) Push the TX(TX offset) button in the sync page. +8) Make sure that you have no slant in the TX. If you still have slant, repeat from (6). + +It is a good idea to use the High-accuracy slant adjustment at Step 6. If you are not satisfied with the result, start it again. Never push the Mem button at this step. + +You can use the LoopBack function of a mixer program instead of using the external feedback line. + +Although this procedure can be applied only for the soundcard that supports the full-duplex mode, the soundcard that does not support the full-duplex mode should not have different frequencies for TX and RX, and therefore you do not need this calibration. + +If you have a report that your TX image is greatly slanted, try changing the soundcard modes, monaural or stereo (Source in the Misc window of Setup MMSSTV). + +Some soundcards seem to use different sampling frequencies for the full-duplex and no-full-duplex operations. +In such a case, the offset calibration using the external loop back does not help. You should always have the loop back External or consult the QSO report. + + + +========== +Setup MMSSTV Misc +========== + +[FIFO] +FIFO specifies the number of the buffer for the low-level sound processing. As the number is increased, the possibility of timing loss is decreased because of larger sound processing margin. +Enlarge the RX-FIFO if you lose the timing in RX. Enlarge the TX-FIFO if you lose the timing in TX. + +[Priority] +Priority defines the task priority for low level sound processing. If you lose the sound during RX or TX, raise the priority. If the response of the menu operations is slow, lower the priority. Normal is the lowest and Critical is the highest priority. + +[DeviceID] +DeviceID specifies the ID number of the sound card. When you have only one sound card, put -1 or 0 to DeviceID. -1 uses the default sound card. The sound card IDs are sequentially assigned as 0, 1, 2, .... When you have two sound cards, for example, and want to use the second one for MMSSTV, put 1 to DeviceID. + +[Source] +Source defines the channel of the sound card. Mono makes the sound card work in the monaural mode. Left or Right makes the sound card work in the stereo mode and uses one of the channels. In TX, MMSSTV outputs the sound to both channels irrespective of the Source setting. + +[Clock] +Clock is the sampling frequency of MMSSTV. Refer to Sample frequency and Clock calibration sections. + + +============================ +Font set up for Hangul and Chinese Windows +============================ + +For Hangul and Chinese Windows users, try the following set up. +1. Click on Option and Setup MMSSTV. +2. Click on Misc tab. +3. Push the Misc button in the System font pane. +4. Select Hangul or Chinese font. Use the font that has small character spacing. +5. Push the OK button. + +After this setup, you can use Hangul or Chinese FEP for the text input boxes. + +It seems that Hangul and Japanese Windows manipulate 8-bit characters in a different manner from English font. MMSSTV version 1.05 or earlier could not handle the slash zero properly. MMSSTV 1.05D (1.06 hopefully) has special routine to work around this problem. + +====== +Closing remarks +====== +MMSSTV is a freeware program for amateur radio use. You can redistribute it as you like. Please join the following reflector for detailed information, + + http://groups.yahoo.com/group/MM-SSTV/ + +The JPEG converter in MMSSTV is based on the freeware source code, "IJG code," provided by Independent JPEG Group. + + +73 de JE3HHT Mako + + \ No newline at end of file diff --git a/EUPDATE.TXT b/EUPDATE.TXT new file mode 100644 index 0000000..bacfea0 --- /dev/null +++ b/EUPDATE.TXT @@ -0,0 +1,860 @@ +What's new in MMSSTV Version 1.13A + September 29, 2010 + JE3HHT Makoto Mori + Translated into English by JA7UDE Oba + +*********************************************************************** +Revision history Ver1.13 -> Ver1.13A +*********************************************************************** +- Fixed the sound card selection problem +- Fixed minor glitches and improved several functions + +*********************************************************************** +Revision history Ver1.12 -> Ver1.13 +*********************************************************************** +- Fixed the custom sound, which was disabled in version 1.12 +- Updated the URL of the English web site +- Updated the introduction for the JASTA contest +- Added COM8 to COM16 selections +- Added CW menu (right click on the CW button) +- Added radio command menu +- Added radio command for some Yaesu radios +- Added an option that lowers the tone frequency by 1000Hz (use -i option on start) + +*********************************************************************** +Revision history Ver1.11G -> Ver1.12 +*********************************************************************** +- Updated the duplication checker of the JASTA contest +- Changed the sound card selection scheme + +*********************************************************************** +Revision history Ver1.11 -> Ver1.11G +*********************************************************************** +- Added a link to the English CHM help file +- Fixed the log file location, the same folder where the EXE file resides +- Added the RX window clear button to the pop-up menu +- Added a gateway to Turbo Hamlog/Win version 5 (Tnx to JG1MOU) +- Added narrow band modes (MP-N, MC-N) +- Added FSKID.TXT in the package +- Improved AFC for narrow band modes +- Fixed typo in the English mode + +*********************************************************************** +Revision history Ver1.10 -> Ver1.11 +*********************************************************************** +- Fixed a bug of the FSKID (Contest NR) + +*********************************************************************** +Revision history Ver1.09 -> Ver1.10 +*********************************************************************** + +- Added links to the call for participations of NVCG and JASTA contests to +the Help menu. + +- Added the CW button to the TX window. Right click on the button to +specify the text to send. + +- Added the contest number option to the FSKID. Click on Setup logging +option and Misc tab. Check Add contest NR to the FSKID box. + +- Added the sound option to the template color bar. + +- Added an option that allows the user to select right or left channel for +the sound output. On the source pane of the Misc tab, selecting Right or +Left enables the TxCH check box. If the TxCH is checked, MMSSTV outputs the +TX sound only on the right or left channel selected. + +- Added TxID button in the Log pane of the main window. + +- Replaced the Clear button in the RX window with the Lock button. If +LOCKed, MMSSTV will not stop the RX scan even in QRM or QSB. + +- Added the log backup function. Select Setup logging and click on Misc +tab. Check Make backup box to enable the function. MMSSTV automatically +makes the log backup with the name of "xxxx_BAK.MDT". + +- Improved the function and manipulation of image clipper. Pop-up menus are +moved to Main menus. Added Make space button. Added Rotation buttons. + +- Improved the text and color setup functions in the template window. +Added the increase and decrease font size buttons. +Added the bold and italic font buttons. +Added the user-customizable font buttons (F1-F4). Right click on them +to register fonts. + +- Improved the speed of character mapping in the template window. +Added the fast code option in the pop-up menu. Some PCs running in the +16-bit color mode does not work well with this code. In that case, +unselect the fast code option. + +- Revised the rule of NVCG contest (1.09F) + +- Improved the precision of the TONE frequency (1.09F) + +- Added the 48KHz sound clock option for the optical connection (S/PDIF) + (may use more CPU power) + +- Improved the DSP calculation speed (1.09F) + +- Fixed some minor bugs and applied a few improvements. + +*********************************************************************** +Revision history Ver1.08 -> Ver1.09 +*********************************************************************** +- Improved the program termination speed +- Added an option that turns off the font smoothing. +- Added EXTPTT port function (EXTFSK.DLL required). +- Added custom log link +- Added custom RadioCommand +- Added custom sound +- Fixed minor bugs and improved several functions. + +============================== +Font smoothing +============================== +When the Windows option "Smooth edges of screen fonts" is engaged, the +background color of the template sometimes leaks at the edges of characters +on the MMSSTV template window. + +There are two ways to solve this problem. +1) Turn the Windows option off. To do so, you will find the option select +at: + Windows XP: Control Panel, System, Advanced, Performance, Visual effects + Windows 2000: Control Panel, Screen, Effects + Windows 98: Control Panel, Screen, Effects +2) Change the MMSSTV template option. Right click on the template window, +select Options, and check Disable font smoothing. When this option is +selected, the font smoothing function of Windows is disabled only within the +MMSSTV template window. + + +==================== +EXTPTT port +==================== +EXTPTT port is provided for the PTT operation using a special USB device, +which was originally made for FSK keying. To make use of this port, select +EXTPTT in the PTT port drop-down list of TX pane of Setup MMSSTV. +EXTFSK.DLL is prerequisite for the operation. For more information, refer +to the following web site. +http://www.archi.is.tohoku.ac.jp/~ooba/ja7ude/homebrew.htm + + + +*********************************************************************** +Revision history Ver1.07 -> Ver1.08 +*********************************************************************** + +- Added notch filter +- Added a function that automatically readjusts the off-synchronized image +when filters are switched +- Added MSG button in the text & color window +- Changed the number of S.Templates-image pages to 4 +- Added dupe check scheme for JASTA contest +- Added LMS filter modes +- Fixed minor bugs and put fine improvements to the program + +================ +Notch filter +================ + +I have added an FIR notch filter in RX. To activate the notch filter, left +click in the spectrum or waterfall window. The notch frequency is marked +with a small triangle. To deactivate the notch filter, right click anywhere +in the window. + +The notch filter eliminates the beat, but it slightly degrades the image +quality. If the notch filter frequency is put closely to the +synchronization signal, the RX operation sometimes stops for the weak +signals if auto-stop function is turned on. + + + Sound ---> Notch ---> LMS -+-> BPF ---> Demodulator + | + --> Spectrum display + +============================================= +MSG button in the "Text & Color" window +============================================= +In the template window, you can add text by pushing "T" button just under +the template window. Double clicking the added text gets the Text & Color +window popped up. You can find MSG button at the bottom center of the +window. When you push the button, a big square pane appears in the window. +Input pre-defined text lines in the window. The text can include macro +keywords. Double clicked line is copied to the text box. +For example, input the text lines in the white pane as follows. + Hello + Good morning + Good afternoon + Good evening + 73 +If you double click on 73, the content of the text box becomes 73. + + + +=================================================== +Added dupe check scheme for JASTA +=================================================== +Click on Option and select Setup logging. Select MISC tab. You will find +JASTA contest in Dupe check pane. If MMSSTV detects dupe, the color of the +callsign in the main window changes red. The dupe conditions are: + +Callsign only + If the same callsign has been found regardless of band or mode + +Hit on the same band + If the same callsign has been found in the same band + +JASTA contest + If the same callsign has been found "in the SSTV mode" and "on the same +day" and "on 14MHz or upper bands." + + + + +============================= +LMS filter selection +============================= +Three LMS filter modes can be selected by right clicking on the LMS button +in the DSP pane of the main window. + +- Noise smoothing: Conventional (default) +- Auto notch (fast): Automatic notch filter with fast response +- Auto notch (slow): Automatic notch filter with slow response + +The response of the automatic notch filter is intentionally set slow so as +not to degrade the image quality. Even set so, some images will be +affected. + + + +*********************************************************************** +Revision history Ver1.06 -> Ver1.07 +*********************************************************************** + +- Added multipage for folder thumbnail +- Implemented fast thumbnail browsing +- Added OLE support +- Fixed some bugs and applied minor improvements + + +====================================== +Multipage for folder thumbnail +====================================== + +The thumbnail window is useful for managing your picture resources. With +MMSSTV 1.07, you can view the pictures stored in two or more different +folders in one thumbnail window. + +To open the thumbnail window, click on "View" and select "Always show +thumbnails of files folder." Right click on any thumbnail in the thumbnail +window and select "Options" and "Create new page." Select the folder that +you want to add the thumbnail window. You will find a new tab added at the +top of the window. If you want to change the tab name, select "Options" and +"Rename page." The window can have up to 10 pages. + + +================================== +Fast thumbnail browsing +================================== + +If the size of the picture or template is large, it should take substantial +time to load and show all the thumbnail images in the folder thumbnail +window. To get the load and show operation faster, MMSSTV version 1.07 +makes an index of the thumbnails once while loaded. MMSSTV uses the index +for the next time on for faster thumbnail browsing. + +MMSSTV creates the index in the FIndex folder under the MMSSTV directory. +The index contains the view information and the thumbnail bitmaps. The +index uses some disk spaces, but it significantly saves the memory and +resources. + +If you do not want to make the index, right click on the thumbnail, select +"Options" and uncheck "Fast access with index." MMSSTV does not make the +index as version 1.06 or earlier. You can individually enable or disable +this indexing feature for each folder. + +* MMSSTV does not generate any file in the referred folders. + +=============== +OLE support +=============== + +MMSSTV now supports OLE (Object Linking and Embedding). If the object is +embedded (or linked) in the template, you can make use of the various +functions offered in the object. + +* Object means the whole or some part of the document in another +application. + +* What kind of object can you utilize in MMSSTV? It is dependent on the OLE +application you have. If you have installed a word processor, for example, +you can use the word processor document as well as all the functions, such +as character effect and picture drawing, provided in the word processor. + + +1. Object embedding + +To embed an object in the template, use one of the following five methods. + +- Right click on the template window of MMSSTV, select Object -> Insert, and +make a new object to embed. You can embed the existing file or place a link +to it in the template, too. + +- Make an object in the other application and copy it to the clip board. +Right click on the template window of MMSSTV, and select Object -> Paste. + +- Drag and drop the target object file from Explorer or My computer to the +MMSSTV template. It should be noted, however, that BMP, JPG, WMF, MTM, MTI, +and DLL files are not embedded as an OLE object. + +- Open the folder thumbnail window (View -> Always show thumbnails of files +folder), and right click on the target picture in the window. Select "Embed +to Template as OLE." In this case, the embedded picture always becomes a +bitmap OLE. + +- Open the thumbnail folder as the OLE object type and double click the +target thumbnail. You can use drag&drop, too. + +2. Object editing + +To edit the embedded object, just double click it. Another way to do this +is keep the object selected and push the Set color button. If you cannot +start the server application, right click on the target object and select +Object -> Edit. + +The server application of the embedded object works as the editor. Please +refer to the help file of the server application. For example, Windows +Paint is invoked for the target application when a BMP file is double +clicked. + +3. Object displaying and resizing + +MMSSTV displays the object in the overlay mode. If you do not want to get +the background transparent, right click on the object, select Object, and +uncheck Overlay. + +When "Object" -> "Stretch as bitmap" is checked, MMSSTV uses a bitmap +resizing code instead of a metafile resizing code. Generally speaking, the +metafile resizing code gives better results for the characters with special +effect. The bitmap resizing code, on the other hand, gives better result +for image objects like photographs. + +4. Custom item + +If you are not satisfied with the MMSSTV graphic tools or the OLE functions, +you can embed a custom item that you have created by yourself. + +To embed a custom item, go with "Object" -> "Insert custom item," and select +the target item. Another way to do this is to open the folder thumbnail as +Custom item type and double click the target thumbnail (or drag & drop it to +the template). + +For the implementation of the custom item, refer to ECUSTOM.TXT, which is +included in the PerImg package. + + + + +*********************************************************************** +Revision history Ver1.05 -> Ver1.06 +*********************************************************************** + +- Added VFO polling for JRC JST-245 +- Supported the slash zero in Hangul font +- Added several SSTV modes +- Improved the automatic synchronization function +- Had the timing of the B/W 8-sec mode adjusted to Robot 1200C +- Added a special font manipulation for East Asian languages +- Added customizable VOX tone +- Took measures not to lost sound +- Added RTS control for muting audio while receiving a picture +- Added overlay function +- Fixed some bugs and applied minor improvements + + +========================== +Special font manipulation for East Asian languages +========================== + +Version 1.05G has a special font manipulation for East Asian languages. In +case you want to use a new language that is different from your default one, +you must install the font and code page of the new one. If you have only +the font installed, you might encounter problems in several operations +including vertical unfolding. + +MMSSTV treats the codepages of the following languages in a special manner: + + 932 Japanese Verified + 949 Hangul Verified + 950 Chinese (BIG5) Not verified + 936 Chinese (GB2312) Not verified + + +====================== +Sound lost +====================== + +I have figured out that some soundcards are likely to lose sound, which +results in synchronization drift. I have added a code to try fixing the +problem. It is effective in some degree, but does not completely solve the +problem. I recommend you to install the latest device driver of your +soundcard. + +If you still have the problem, try turning off LoopBack in the TX page and +increasing the FIFO depth in the Misc page. + + +============== +MP/MR/ML modes +============== + + +MP mode: It is based on the color difference scheme that the PD mode uses. +This mode should be useful for reducing multi-path distortion and jitter. +The scan time for each pixel is longer than the other modes, but the color +information along the vertical axis is compressed. + +MR/ML mode: It is based on the color difference scheme that the Robot 24/72 +mode uses. This mode is aimed for offering good resolution in good condx. +The color information along the horizontal axis is compressed. + +These modes are not new to SSTV actually, but I have added them by way of +trial. In particular, I have considered good trade-off between the +transmission time, picture size, and quality. As a new trial, the VIS +signal is expanded to 16 bits. Refer to Mode.txt for the details of the new +modes and their VIS format. + + + +================ +B/W 8-sec mode +================ + +Changing with times including the old monochrome generation, the B/W 8-sec +mode seems to have several "dialects" in terms of the aspect ratio and the +timing. +MMSSTV has adjusted the timing to the Robot 1200C scan converter, which is +used as the standard of the VIS signals. When you come across a picture +with different timing, turn Auto slant on or push the niconico mark button +in the Sync window. + + + +================ +RTS control while scan +================ + +I have added "RTS while scan" option in the MMSSTV Setup window. The +behavior of the COM port signals, that is, DTR, RTS, and TXD can be selected +as follows: + +[RTS while scan = OFF] + RX TX SCAN (receiving a picture) + DTR OFF ON OFF + RTS OFF ON OFF + TXD --- --- --- (no control) + +[RTS while scan = ON] + RX TX SCAN (receiving a picture) + DTR OFF ON OFF + RTS OFF ON ON + TXD NoBreak NoBreak Break + + +========== +VOX tone +========== + +If you use the COM port to switch PTT or if you have a responsive VOX +interface, you can eliminate the VOX tone, which is sent before the picture. + Select "User defined" in the VOX tone pane on the TX page of Setup MMSSTV. + Push Edit button and delete all the definitions. MMSSTV no longer +generates the tone for triggering VOX prior to sending a picture. + + +============== +Overlay (superimpose) function +============== + +In the template, you can place an image that is superimposed on the TX +picture. By using an image that has a uniform background color, such as an +illustration, you would be able to make amusing effects on your picture. + +In the image, all the pixels that have the transparent color are +transparent, that is, invisible on the TX picture. The transparent color is +defined by the color of the transparent point in the image. The default +position of the transparent point is the upper left corner of the image. + +Here is a sample procedure to use the overlay function. In the template +window, push Draw picture button (a small button whose face has the sun and +mountains), and draw a rectangle that specifies the image size and position +in the template window. You should have the Choose picture window popped +up. Select Overlay in the source pane, and load an image. Left click on +somewhere in the picture. The clicked point is the new transparent point, +that is, the color of the point becomes the new transparent color. Try +right clicking somewhere in the image. All the pixels that have the same +color of the clicked point are changed to the current transparent color. + +If the source image is stored in the JPEG format, the background color is +not always uniform owing to the image compression effect. This results in +color leak in the overlay image. In such a case, try using the color +smoothing function, which is available at the right side of the Choose +picture window, in order to alleviate the color leak. + +When the size of the overlay image is changed in the template window, MMSSTV +gives priority to the color smoothness over the image quality. If the image +quality is degraded, change the size of the image in the bitmap format, and +then convert it to the overlay image. The size change in the bitmap format, +however, gives priority to the image quality, and thus it would degrade the +color smoothness. In this case, try using the color smoothing function to +alleviate the color leak. + + + + +*********************************************************************** +Revision history Ver1.04 -> Ver1.05 +*********************************************************************** +- Added two window layouts +- Added an optional window for the control buttons +- Added an option that attaches the RX window to the WINDOWS desktop. +- Added double-click short-cut operations for the stocked pictures, stocked +templates, folder thumbnails. +- Added 320x240 image manipulating schemes +- Added a repeater function +- Fixed a bug that caused the resource shortage in Windows 95/98/ME +- Fixed some bugs and applied minor improvements + + +============ +Window layouts +============ +You can select one of three window layouts by clicking "View" and selecting +"Design." + +[Standard] + This is the conventional MMSSTV window layout. All the information is +shown in one window. + +[Separate stock view] + The stock window is detached from the main window. + +[Separate all views] + All the windows are separated. + +Each detached window can be moved and resized independently. + + +==================== +Control buttons window + +==================== + Click on "View" and select "Always show control buttons" to open an +optional window dedicated to the control buttons. + +[Stop RX] + Stop the RX operation immediately and go into the stand-by state (Auto). + +[ReSync] + Make the synchronization again. + +[Lock RX] + When the button is depressed, MMSSTV turns off "Auto stop" and "Auto +restart," and therefore it won't stop the RX scan even in QRM and/or QSB. +When the button is not depressed, "Auto stop" and "Auto restart" are +resumed. + +[CopyHist] + If the RX image is not copied to the history, press this button to force +the copy. + +[TX(F9)] + It functions just same as the TX button of the TX window. You can use F9 +key to switch TX/RX. + + +============================================== +Attaching the RX window to the WINDOWS desktop +============================================== + When you have activated "Always show RX viewer" option, you can attach the +window to the WINDOWS desktop. Right click the RX window and select "Child +of a desktop window" in the pop-up menu. + In this mode, the RX viewer remains active, even if the main MMSSTV window +is minimized. + + +========================= +320x240 image manipulation +========================= + Click on "Edit" and select "Handling of 320x240" to settle how to +manipulate 320x240 image sources. This selection is also applied to the +combination of the 640x480 source and 640x496 TX images. + +[Vertical stretching] + The image is vertically stretched. The image aspect ratio is not +reserved. + +[Auto stretching] + The image is horizontally and vertically stretched. The aspect ratio is +reserved. The original image slightly loses the left and right edges. This +is the operation that MMSSTV used in the earlier versions. + +[No stretching] + The image size is unchanged. The TX image has 16 vacant lines at the +bottom. + +[Shift picture for the header] + The image size is unchanged. The TX image has 16 vacant lines at the top +for the header. + + It should be noted that this manipulation does not work for the image that +derived through the image clipper. + + +================ +SSTV repeater function +================ + MMSSTV can work as an SSTV repeater. Refer to Repeater.txt for details. + + +*********************************************************************** +Revision history Ver1.03 -> Ver1.04 +*********************************************************************** +- Improved the user interface for the character input in the template +- Added perspective and 3-D effects for the template text +- Corrected some bugs and applied minor improvements + +*********************************************************************** +Revision history Ver1.02 -> Ver1.03 +*********************************************************************** +- Added "FFT demodulator" mode in the spectrum display +- Added AFC +- Added Undo in the pop-up menu for the template +- Corrected some bugs and applied minor improvements + +================ +Spectrum display +================ +The user can select one of "OFF," "FFT," or "FM demodulator" mode for the +spectrum display. The default has been set to FM demodulator. If you want +to use the conventional FFT mode, change back it to "FFT." + +* If you draw CMT-HELL, which was made by PY4ZBZ, in the waterfall of +MMSSTV, you must select "FFT." + +The FM demodulator uses another wide-band FM demodulator in addition to the +picture demodulator. It draws the chart as the function of the rate of +incidence at each frequency. Because its computation process is much +simpler than the FFT, it gives good response even to the short pulse like a +synchronization signal, but it does not reflect the signal level. + +The FFT and FM demodulator observe the signal before the SSTV BPF in order +to see the signals outside of the BPF, too. + + --- Sound in --+--> SSTV demodulator + | + ---> Spectral (FFT / FM demodulator) + + +============== +AFC +============== +AFC is activated by pushing the AFC button in the DSP pane on the main +window. The default is ON. +When AFC is locked to the signal, the triangle marker on the synchronization +frequency line is displayed in blue. When AFC is unlocked, the triangle +marker is displayed in red. During in red, the response to the frequency +discrimination becomes slow. + +* The AGC in the previous versions was deleted because it seemed to offer no +improvements. + + +*********************************************************************** +Revision history: Ver1.01 -> Ver1.02 +*********************************************************************** +- Added the Hilbert transform method in the FM decoder +- Improved the processing speed of the low-level sound processing +- Added the TX-offset button on the Sync window +- Added High-accuracy slant adjustment method +- Added Vari-SSTV function +- Debugged the automatic start function +- Corrected some bugs and enhanced some functions + + +================================== +Added Hilbert transform method in the FM decoder +================================== +The figure below shows the flow of the Hilbert transform decoder. This idea +was given by JA6UHL Nishimura-san (MNI TNX to JA6UHL). + + --+> Delay(N) -> Real + | |==> ATAN --> Differentiator --> LPF --> Pic. data + --> FIR(2N) --> Image + + +======================== +Low-level sound buffer +======================== +I enhanced the sound buffer processing. You can set the FIFO sizes for TX +and RX in the option menu. +If you often loose the sound, that is, loose the synchronization, try +enlarging the RX FIFO or TX FIFO. Giving higher priority to the sound +processing is another way of alleviate the sound loosing. + + +============== +High-accuracy slant adjustment +============== +MMSSTV uses the least square method to solve the linear equation for +analyzing the synchronization timings. For high quality RX signals, it will +give the error less than 2ppm. +To start the high-accuracy slant adjustment, push the NikoNiko button +(comment by JA7UDE: the smiley button). You also can start it by right +clicking on the sync or RX window and selecting High-accuracy slant +adjustment in the pop-up menu. It should be noted that you must have +received at least 16 scan lines to make this adjustment operational. The +more the scan lines, the better the accuracy. + + +=============== +Adjustment of TX offset +=============== +Assuming that you have the RX clock calibrated, MMSSTV transmits the signal +and receives it through the external loop back. +After you have adjusted the slant (push the NikoNiko smiley button), push +the TX button in the Sync window. MMSSTV automatically records the TX +offset frequency. + + +======== +VariSSTV +======== +VariSSTV, which is proposed by Mr. Samuel Hunt, is a method to protect the +final device of the TX. He says that different colors have different +brightness and therefore making the power lower in the way shown below gives +better noise immunity. + +Sync signal 100% +Red 29.8% +Green 58.8% +Blue 11% + +For details, visit http://www.supersam.co.uk/sstvpwer.htm. + +I have no idea how it is effective. Please give it a try by yourself. Go +Option, Setup MMSSTV, TX tab, and check the VariSSTV box under the digital +output level slider. This is not operational in Robot36 or Robot72. + + +*********************************************************************** +Revision history Ver1.00 -> Ver1.01 +*********************************************************************** +- Added several SSTV modes +- Improved the image clipper function +- Added the preview tool for selecting files +- Fixed some bugs and improved some operations + + +================ +New SSTV modes +================ + +The following SSTV modes have been added. + + Name Time(s) Size Method + --------------------------------------------------- + SC2-120 122 320x256 RGB + SC2-60 62 320x256 RGB + PD50 50 320x256 Color discrimination + PD90 90 320x256 Color discrimination + PD120 126 640x496 Color discrimination + PD160 161 512x400 Color discrimination + PD180 187 640x496 Color discrimination + PD240 248 640x496 Color discrimination + PD290 289 800x616 Color discrimination + P3 203 640x496 RGB + P5 305 640x496 RGB + P7 406 640x496 RGB + +To use one of these modes, click the mode button in TX or RX window with the +right button of the mouse and select it from the pop-up menu. + +PD120 - PD290 and P3 - P5 have bigger image sizes than 320 x 256 (from now +on, I call them high-resolution modes). The image view board of the MMSSTV +main window is designed to show a 320x256 image. For this reason, MMSSTV +shrinks and displays the images (resized to 320x256) in those +high-resolution modes. In other words, the sizes of the actual image and +that displayed in the RX window would not be the same. + +To view the high-resolution images in the original size, push the magnifier +button under the RX or History window, or at the Always Show RX viewer, +right click and select Resize to RX size in the pop up menu. + +To view the high-resolution TX images in the original size, push the +magnifier button under the TX window. + +If the sizes in the TX mode and in the original image are different, MMSSTV +does not resize the original image. If you want to resize the image, right +click the TX window and select 'Stretch TX image by different size' in the +pop-up menu. In this case, however, the image resolution sometimes +degrades, particularly when you get it bigger. In addition, bear in mind +that different modes have different aspect ratios. + +Anyhow, it is recommended that you reload the image into the TX window if +you use images in different sizes. + +MMSSTV templates, therefore, have several sizes. It is a good idea to use +the template whose size is the same as the image. In default, MMSSTV tries +to get the template size to fit the image. However, the layout of the +template components is not reserved. + + +You can resize the template size by selecting Size entry in the pop-up menu, +which appears by right clicking the Template window. If the size of the +template is different from that of the image, MMSSTV resizes the template +and gets it superimposed to the image. It should be noted that the quality +of the template would get worse, but you can continue to use the templates +that you designed in different sizes. + +The image size in the Stocked pictures is predefined as 320x256. If you +want to change it, right click the Stocked pictures area and select Size in +the pop-up menu. + +When you drag & drop an image from the TX window to the Stocked pictures +window, MMSSTV uses the TX image size. + +In PD290, P5, and P7 modes, the RAM, which is used for the automatic slant +adjustment, cannot store the whole image data. The slant and phase +adjustment can be applied only to some portion of the data. To avoid this +problem, select FILE for the RX buffer. + + +======================== +New functions in the image clipper +======================== + +The following new functions have been added. + +- Copy and paste without changing the original image size +- Rotate the image in 90 degrees +- Adjust the image +- Copy to the clipboard + +- Save an image to a file + +To use these functions, right click the image clipper window. You will get +the pop-up menu for the functions. + + +================================ +Preview in file selection +================================ + +In the dialog box for loading an image file, you can preview the image by +clicking the file name. +The preview window is appeared at the top left corner for the first time, +but you can change the size and position as you like. + +73, Mako + diff --git a/ExtCmd.cpp b/ExtCmd.cpp new file mode 100644 index 0000000..693b91a --- /dev/null +++ b/ExtCmd.cpp @@ -0,0 +1,92 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "ExtCmd.h" +#include "Main.h" +//--------------------------------------------------------------------- +#pragma resource "*.dfm" +//--------------------------------------------------------------------- +__fastcall TExtCmdDlg::TExtCmdDlg(TComponent* AOwner) + : TForm(AOwner) +{ + FormStyle = ((TForm *)AOwner)->FormStyle; + Font->Name = ((TForm *)AOwner)->Font->Name; + Font->Charset = ((TForm *)AOwner)->Font->Charset; + if( MsgEng ){ + Caption = "Assign program"; + CancelBtn->Caption = "Cancel"; + L1->Caption = "Menu name"; + L2->Caption = "Program file"; + RefBtn->Caption = "Ref."; + CBR->Caption = "Suspend (This program will use same sound card)"; + } +} +//--------------------------------------------------------------------- +int __fastcall TExtCmdDlg::Execute(AnsiString &Name, AnsiString &Cmd, int &Susp) +{ + EM->Text = Name; + EC->Text = Cmd; + CBR->Checked = Susp; + if( ShowModal() == IDOK ){ + if( !EC->Text.IsEmpty() ){ + Name = EM->Text; + Cmd = EC->Text; + Susp = CBR->Checked; + return TRUE; + } + } + return FALSE; +} +//--------------------------------------------------------------------- +void __fastcall TExtCmdDlg::RefBtnClick(TObject *Sender) +{ + char bf[256]; + SetDirName(bf, AnsiString(EC->Text).c_str()); //ja7ude 0428 + if( !bf[0] ){ + strcpy(bf, "C:\\Program Files"); + } + TOpenDialog *pDialog = Mmsstv->OpenDialog; + pDialog->Options >> ofCreatePrompt; + pDialog->Options << ofFileMustExist; + if( MsgEng ){ + pDialog->Title = "Program file"; + pDialog->Filter = "Program files(*.exe;*.lnk)|*.exe;*.lnk|"; + } + else { + pDialog->Title = "プログラムファイル"; + pDialog->Filter = "プログラムファイル(*.exe;*.lnk)|*.exe;*.lnk|"; + } + pDialog->FileName = ""; + pDialog->DefaultExt = "exe"; + pDialog->InitialDir = bf; + SetDisPaint(); + NormalWindow(this); + if( Mmsstv->OpenDialogExecute(FALSE) == TRUE ){ + EC->Text = pDialog->FileName.c_str(); + } + ResDisPaint(); + TopWindow(this); +} +//--------------------------------------------------------------------------- + + diff --git a/ExtCmd.dfm b/ExtCmd.dfm new file mode 100644 index 0000000..f7ee1ae Binary files /dev/null and b/ExtCmd.dfm differ diff --git a/ExtCmd.h b/ExtCmd.h new file mode 100644 index 0000000..9334e75 --- /dev/null +++ b/ExtCmd.h @@ -0,0 +1,55 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//---------------------------------------------------------------------------- +#ifndef ExtCmdDlgH +#define ExtCmdDlgH +//---------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//---------------------------------------------------------------------------- +class TExtCmdDlg : public TForm +{ +__published: + TButton *OKBtn; + TButton *CancelBtn; + TEdit *EM; + TEdit *EC; + TCheckBox *CBR; + TLabel *L1; + TLabel *L2; + TButton *RefBtn; + void __fastcall RefBtnClick(TObject *Sender); +private: +public: + virtual __fastcall TExtCmdDlg(TComponent* AOwner); + + int __fastcall Execute(AnsiString &Name, AnsiString &Cmd, int &Susp); +}; +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +#endif diff --git a/Fft.cpp b/Fft.cpp new file mode 100644 index 0000000..59e86d0 --- /dev/null +++ b/Fft.cpp @@ -0,0 +1,871 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +#include //ja7ude 0521 +#pragma hdrstop + +#include +#include "fft.h" +#include "ComLib.h" + +#define PI 3.1415926535897932384626433832795 +#define PI2 (2*PI) + +#define SCALEADJ_1 (-5.5) +#define SCALEADJ_2 (-6.5) +#define SCALEADJ_3 (-7.8) +#define SCALEADJ_4 (-9.0) +#define LOGADJ (2.81458e4) + +#define SCALEPOW_1 (1.0/4.0) +#define SCALEPOW_ADJ_1 0.0018 +#define SCALEPOW_2 (1.0/5.0) +#define SCALEPOW_ADJ_2 0.008 +#define SCALEPOW_3 (1.0/6.0) +#define SCALEPOW_ADJ_3 0.022 +#define SCALEPOW_4 (1.0/7.0) +#define SCALEPOW_ADJ_4 0.048 +//------------------------------------------------- +// FFT処理クラス +CFFT::CFFT() +{ + m_FFTDIS = 0; + memset(m_fft, 0, sizeof(m_fft)); + m_CollectFFT = 1; + m_CollectrPage = m_CollectwPage = 0; + m_CollectFFTCount = 0; + m_tWindow = new double[FFT_BUFSIZE]; + m_tSinCos = new double[FFT_BUFSIZE/2]; + m_Work = new int[SQRT_FFT_SIZE+2]; + memset(m_Work, 0, sizeof(int[SQRT_FFT_SIZE+2])); + pStgBuf = new double[FFT_BUFSIZE]; + m_Work[0] = 0; + makewt(FFT_SIZE/4, m_Work, m_tSinCos); + makect(FFT_SIZE/4, m_Work, m_tSinCos + m_Work[0]); + for(int i = 0; i < FFT_SIZE; i++){ + pStgBuf[i] = 1.0; + m_tWindow[i] = (0.5 - 0.5*cos( (PI2*i)/(FFT_SIZE-1) )); //ハニング窓 +// m_tWindow[i] = 1.0; + } + m_StgSize = 1; + m_StgScale = 1.0; + m_StgK = 0.0; + m_StgSW = FALSE; + m_CollectFlag = 0; + m_Handle = NULL; + m_CollectCount = 0; + m_CollectFFT = 0; + + m_fqc.SetSampFreq(FFTSamp); + m_fqc.m_Limit = 0; + m_fqc.m_outOrder = 2; + m_fqc.m_outFC = 400; + m_fqc.CalcLPF(); +} + +//------------------------------------------------- +// FFT処理クラスの再初期化 +void CFFT::InitFFT(void) +{ + m_CollectFFT = 0; + m_CollectFFTCount = 0; + m_CollectFFT = 0; + m_CollectFFTCount = 0; + memset(m_Work, 0, sizeof(int[SQRT_FFT_SIZE+2])); + makewt(FFT_SIZE/4, m_Work, m_tSinCos); + makect(FFT_SIZE/4, m_Work, m_tSinCos + m_Work[0]); + for(int i = 0; i < FFT_SIZE; i++){ + pStgBuf[i] = 1.0; +// m_tWindow[i] = 1.0; +// m_tWindow[i] = (0.5 - 0.5*cos( (PI2*i)/(FFT_SIZE-1) )); //ハニング窓 + m_tWindow[i] = (0.5 - 0.5*cos( (PI2*i)/FFT_SIZE )); //ハニング窓 +// m_tWindow[i] = 0.46 - 0.5*cos( (PI2*i)/FFT_SIZE ) + 0.08*cos(2*PI2*i/FFT_SIZE); //ハニング窓 + } + m_StgSize = 1; + m_StgScale = 1.0; + m_StgK = 0.0; + m_StgSW = FALSE; + m_CollectFlag = 0; + m_CollectCount = 0; + m_CollectFFT = 0; +} + +//------------------------------------------------- +CFFT::~CFFT() +{ + if(pStgBuf){ + delete pStgBuf; + pStgBuf = NULL; + } + if(m_Work){ + delete m_Work; + m_Work = NULL; + } + if(m_tSinCos){ + delete m_tSinCos; + m_tSinCos = NULL; + } + if(m_tWindow){ + delete m_tWindow; + m_tWindow = NULL; + } +} + +//------------------------------------------------- +// データ収集(スレッド外で実行する) +void CFFT::TrigFFT(void) +{ + m_CollectFFT = 1; + m_CollectFFTCount = 0; + m_CollectrPage = m_CollectwPage = 0; + m_CollectCount = 0; + m_fqc.m_fq = ZEROFQ; + m_CollectFFT = 0; // 次の収集をトリガ +} +//------------------------------------------------- +// データ収集(スレッド内で実行する) +void CFFT::CollectFFT(double *lp, int dsize) +{ + if( DisPaint || m_CollectFFT ) return; + + if( sys.m_FFTPriority ){ + while( (m_CollectCount < 3) && dsize ){ + double *tp; + int i; + int size; + switch(FFTSampType){ + case 1: + size = dsize / 2; + if( (size + m_CollectFFTCount) > FFT_SIZE ){ + size = FFT_SIZE - m_CollectFFTCount; + } + dsize -= (size * 2); + for( tp = &m_CollectFFTBuf[m_CollectwPage][m_CollectFFTCount], i = 0; i < size; i++, tp++, lp+=2 ){ + *tp = *lp; + } + break; + case 2: + size = dsize / 4; + if( (size + m_CollectFFTCount) > FFT_SIZE ){ + size = FFT_SIZE - m_CollectFFTCount; + } + dsize -= (size * 4); + for( tp = &m_CollectFFTBuf[m_CollectwPage][m_CollectFFTCount], i = 0; i < size; i++, tp++, lp+=4 ){ + *tp = *lp; + } + break; + default: + size = dsize; + if( (size + m_CollectFFTCount) > FFT_SIZE ){ + size = FFT_SIZE - m_CollectFFTCount; + } + dsize -= size; + memcpy(&m_CollectFFTBuf[m_CollectwPage][m_CollectFFTCount], lp, sizeof(double)*size); + lp += size; + break; + } + m_CollectFFTCount += size; + if( m_CollectFFTCount >= FFT_SIZE ){ + int page = m_CollectwPage; + m_CollectwPage++; + if( m_CollectwPage >= 3 ) m_CollectwPage = 0; + m_CollectCount++; + switch(sys.m_FFTPriority){ + case 1: + m_CollectFFTCount = 0; + break; + case 2: + m_CollectFFTCount = 128; + memcpy(m_CollectFFTBuf[m_CollectwPage], &m_CollectFFTBuf[page][FFT_SIZE-128], sizeof(double)*128); + break; + case 3: + m_CollectFFTCount = 256; + memcpy(m_CollectFFTBuf[m_CollectwPage], &m_CollectFFTBuf[page][FFT_SIZE-256], sizeof(double)*256); + break; + default: + m_CollectFFTCount = 512; + memcpy(m_CollectFFTBuf[m_CollectwPage], &m_CollectFFTBuf[page][FFT_SIZE-512], sizeof(double)*512); + break; + } + if( m_Handle != NULL ){ + ::PostMessage(m_Handle, CM_FFT, 0, 0); + } + } + } + } + else if( !m_CollectCount ){ + double *tp; + int i; + int size; + switch(FFTSampType){ + case 1: + size = dsize / 2; + if( (size + m_CollectFFTCount) > FFT_SIZE ){ + size = FFT_SIZE - m_CollectFFTCount; + } + for( tp = &m_CollectFFTBuf[m_CollectwPage][m_CollectFFTCount], i = 0; i < size; i++, tp++, lp+=2 ){ + *tp = *lp; + } + break; + case 2: + size = dsize / 4; + if( (size + m_CollectFFTCount) > FFT_SIZE ){ + size = FFT_SIZE - m_CollectFFTCount; + } + for( tp = &m_CollectFFTBuf[m_CollectwPage][m_CollectFFTCount], i = 0; i < size; i++, tp++, lp+=4 ){ + *tp = *lp; + } + break; + default: + size = dsize; + if( (size + m_CollectFFTCount) > FFT_SIZE ){ + size = FFT_SIZE - m_CollectFFTCount; + } + memcpy(&m_CollectFFTBuf[m_CollectwPage][m_CollectFFTCount], lp, sizeof(double)*size); + break; + } + m_CollectFFTCount += size; + if( m_CollectFFTCount >= FFT_SIZE ){ + m_CollectwPage++; + if( m_CollectwPage >= 3 ) m_CollectwPage = 0; + m_CollectCount++; + m_CollectFFTCount = 0; + } + } +} +//------------------------------------------------- +// 計算(スレッド外で実行する) +void CFFT::CalcFFT(int size, double gain, int stg) +{ + if( sys.m_FFTType == 2 ){ + CalcFQC(m_CollectFFTBuf[m_CollectrPage], size, gain, stg, m_fft); + } + else { + Calc(m_CollectFFTBuf[m_CollectrPage], size, gain, stg, m_fft); + } + m_CollectrPage++; + if( m_CollectrPage >= 3 ) m_CollectrPage = 0; + if( m_CollectCount ) m_CollectCount--; +} + +void CFFT::makewt(int nw, int *ip, double *w) +{ + int nwh, j; + double delta, x, y; + + ip[0] = nw; + ip[1] = 1; + if(nw > 2){ + nwh = nw >> 1; + delta = atan(1.0) / nwh; + w[0] = 1; + w[1] = 0; + w[nwh] = cos(delta * nwh); + w[nwh + 1] = w[nwh]; + for(j = 2; j < nwh; j += 2){ + x = cos(delta * j); + y = sin(delta * j); + w[j] = x; + w[j + 1] = y; + w[nw - j] = y; + w[nw - j + 1] = x; + } + bitrv2(nw, ip + 2, w); + } +} +//------------------------------------------------- +// データの処理化 +void CFFT::makect(int nc, int *ip, double *c) +{ + int nch, j; + double delta; + + ip[1] = nc; + if(nc > 1){ + nch = nc >> 1; + delta = atan(1.0) / nch; + c[0] = cos(delta * nch); + c[nch] = 0.5 * c[0]; + for(j = 1; j < nch; j++){ + c[j] = 0.5 * cos(delta * j); + c[nc - j] = 0.5 * sin(delta * j); + } + } +} +//------------------------------------------------- +// データの処理化 +void CFFT::bitrv2(int n, int *ip, double *a) +{ + int j, j1, k, k1, l, m, m2; + double xr, xi; + + ip[0] = 0; + l = n; + m = 1; + while((m << 2) < l){ + l >>= 1; + for (j = 0; j < m; j++) { + ip[m + j] = ip[j] + l; + } + m <<= 1; + } + if((m << 2) > l){ + for (k = 1; k < m; k++) { + for (j = 0; j < k; j++) { + j1 = (j << 1) + ip[k]; + k1 = (k << 1) + ip[j]; + xr = a[j1]; + xi = a[j1 + 1]; + a[j1] = a[k1]; + a[j1 + 1] = a[k1 + 1]; + a[k1] = xr; + a[k1 + 1] = xi; + } + } + } else { + m2 = m << 1; + for(k = 1; k < m; k++){ + for(j = 0; j < k; j++){ + j1 = (j << 1) + ip[k]; + k1 = (k << 1) + ip[j]; + xr = a[j1]; + xi = a[j1 + 1]; + a[j1] = a[k1]; + a[j1 + 1] = a[k1 + 1]; + a[k1] = xr; + a[k1 + 1] = xi; + j1 += m2; + k1 += m2; + xr = a[j1]; + xi = a[j1 + 1]; + a[j1] = a[k1]; + a[j1 + 1] = a[k1 + 1]; + a[k1] = xr; + a[k1 + 1] = xi; + } + } + } +} +//------------------------------------------------- +void CFFT::cftfsub(int n, double *a, double *w) +{ + int j, j1, j2, j3, l; + double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; + + l = 2; + if(n > 8){ + cft1st(n, a, w); + l = 8; + while((l << 2) < n){ + cftmdl(n, l, a, w); + l <<= 2; + } + } + if((l << 2) == n){ + for(j = 0; j < l; j += 2){ + j1 = j + l; + j2 = j1 + l; + j3 = j2 + l; + x0r = a[j] + a[j1]; + x0i = a[j + 1] + a[j1 + 1]; + x1r = a[j] - a[j1]; + x1i = a[j + 1] - a[j1 + 1]; + x2r = a[j2] + a[j3]; + x2i = a[j2 + 1] + a[j3 + 1]; + x3r = a[j2] - a[j3]; + x3i = a[j2 + 1] - a[j3 + 1]; + a[j] = x0r + x2r; + a[j + 1] = x0i + x2i; + a[j2] = x0r - x2r; + a[j2 + 1] = x0i - x2i; + a[j1] = x1r - x3i; + a[j1 + 1] = x1i + x3r; + a[j3] = x1r + x3i; + a[j3 + 1] = x1i - x3r; + } + } else { + for(j = 0; j < l; j += 2){ + j1 = j + l; + x0r = a[j] - a[j1]; + x0i = a[j + 1] - a[j1 + 1]; + a[j] += a[j1]; + a[j + 1] += a[j1 + 1]; + a[j1] = x0r; + a[j1 + 1] = x0i; + } + } +} +//------------------------------------------------- +void CFFT::cft1st(int n, double *a, double *w) +{ + int j, k1, k2; + double wk1r, wk1i, wk2r, wk2i, wk3r, wk3i; + double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; + + x0r = a[0] + a[2]; + x0i = a[1] + a[3]; + x1r = a[0] - a[2]; + x1i = a[1] - a[3]; + x2r = a[4] + a[6]; + x2i = a[5] + a[7]; + x3r = a[4] - a[6]; + x3i = a[5] - a[7]; + a[0] = x0r + x2r; + a[1] = x0i + x2i; + a[4] = x0r - x2r; + a[5] = x0i - x2i; + a[2] = x1r - x3i; + a[3] = x1i + x3r; + a[6] = x1r + x3i; + a[7] = x1i - x3r; + wk1r = w[2]; + x0r = a[8] + a[10]; + x0i = a[9] + a[11]; + x1r = a[8] - a[10]; + x1i = a[9] - a[11]; + x2r = a[12] + a[14]; + x2i = a[13] + a[15]; + x3r = a[12] - a[14]; + x3i = a[13] - a[15]; + a[8] = x0r + x2r; + a[9] = x0i + x2i; + a[12] = x2i - x0i; + a[13] = x0r - x2r; + x0r = x1r - x3i; + x0i = x1i + x3r; + a[10] = wk1r * (x0r - x0i); + a[11] = wk1r * (x0r + x0i); + x0r = x3i + x1r; + x0i = x3r - x1i; + a[14] = wk1r * (x0i - x0r); + a[15] = wk1r * (x0i + x0r); + k1 = 0; + for(j = 16; j < n; j += 16){ + k1 += 2; + k2 = k1 << 1; + wk2r = w[k1]; + wk2i = w[k1 + 1]; + wk1r = w[k2]; + wk1i = w[k2 + 1]; + wk3r = wk1r - 2 * wk2i * wk1i; + wk3i = 2 * wk2i * wk1r - wk1i; + x0r = a[j] + a[j + 2]; + x0i = a[j + 1] + a[j + 3]; + x1r = a[j] - a[j + 2]; + x1i = a[j + 1] - a[j + 3]; + x2r = a[j + 4] + a[j + 6]; + x2i = a[j + 5] + a[j + 7]; + x3r = a[j + 4] - a[j + 6]; + x3i = a[j + 5] - a[j + 7]; + a[j] = x0r + x2r; + a[j + 1] = x0i + x2i; + x0r -= x2r; + x0i -= x2i; + a[j + 4] = wk2r * x0r - wk2i * x0i; + a[j + 5] = wk2r * x0i + wk2i * x0r; + x0r = x1r - x3i; + x0i = x1i + x3r; + a[j + 2] = wk1r * x0r - wk1i * x0i; + a[j + 3] = wk1r * x0i + wk1i * x0r; + x0r = x1r + x3i; + x0i = x1i - x3r; + a[j + 6] = wk3r * x0r - wk3i * x0i; + a[j + 7] = wk3r * x0i + wk3i * x0r; + wk1r = w[k2 + 2]; + wk1i = w[k2 + 3]; + wk3r = wk1r - 2 * wk2r * wk1i; + wk3i = 2 * wk2r * wk1r - wk1i; + x0r = a[j + 8] + a[j + 10]; + x0i = a[j + 9] + a[j + 11]; + x1r = a[j + 8] - a[j + 10]; + x1i = a[j + 9] - a[j + 11]; + x2r = a[j + 12] + a[j + 14]; + x2i = a[j + 13] + a[j + 15]; + x3r = a[j + 12] - a[j + 14]; + x3i = a[j + 13] - a[j + 15]; + a[j + 8] = x0r + x2r; + a[j + 9] = x0i + x2i; + x0r -= x2r; + x0i -= x2i; + a[j + 12] = -wk2i * x0r - wk2r * x0i; + a[j + 13] = -wk2i * x0i + wk2r * x0r; + x0r = x1r - x3i; + x0i = x1i + x3r; + a[j + 10] = wk1r * x0r - wk1i * x0i; + a[j + 11] = wk1r * x0i + wk1i * x0r; + x0r = x1r + x3i; + x0i = x1i - x3r; + a[j + 14] = wk3r * x0r - wk3i * x0i; + a[j + 15] = wk3r * x0i + wk3i * x0r; + } +} +//------------------------------------------------- +void CFFT::cftmdl(int n, int l, double *a, double *w) +{ + int j, j1, j2, j3, k, k1, k2, m, m2; + double wk1r, wk1i, wk2r, wk2i, wk3r, wk3i; + double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; + + m = l << 2; + for(j = 0; j < l; j += 2){ + j1 = j + l; + j2 = j1 + l; + j3 = j2 + l; + x0r = a[j] + a[j1]; + x0i = a[j + 1] + a[j1 + 1]; + x1r = a[j] - a[j1]; + x1i = a[j + 1] - a[j1 + 1]; + x2r = a[j2] + a[j3]; + x2i = a[j2 + 1] + a[j3 + 1]; + x3r = a[j2] - a[j3]; + x3i = a[j2 + 1] - a[j3 + 1]; + a[j] = x0r + x2r; + a[j + 1] = x0i + x2i; + a[j2] = x0r - x2r; + a[j2 + 1] = x0i - x2i; + a[j1] = x1r - x3i; + a[j1 + 1] = x1i + x3r; + a[j3] = x1r + x3i; + a[j3 + 1] = x1i - x3r; + } + wk1r = w[2]; + for(j = m; j < l + m; j += 2){ + j1 = j + l; + j2 = j1 + l; + j3 = j2 + l; + x0r = a[j] + a[j1]; + x0i = a[j + 1] + a[j1 + 1]; + x1r = a[j] - a[j1]; + x1i = a[j + 1] - a[j1 + 1]; + x2r = a[j2] + a[j3]; + x2i = a[j2 + 1] + a[j3 + 1]; + x3r = a[j2] - a[j3]; + x3i = a[j2 + 1] - a[j3 + 1]; + a[j] = x0r + x2r; + a[j + 1] = x0i + x2i; + a[j2] = x2i - x0i; + a[j2 + 1] = x0r - x2r; + x0r = x1r - x3i; + x0i = x1i + x3r; + a[j1] = wk1r * (x0r - x0i); + a[j1 + 1] = wk1r * (x0r + x0i); + x0r = x3i + x1r; + x0i = x3r - x1i; + a[j3] = wk1r * (x0i - x0r); + a[j3 + 1] = wk1r * (x0i + x0r); + } + k1 = 0; + m2 = m << 1; + for(k = m2; k < n; k += m2){ + k1 += 2; + k2 = k1 << 1; + wk2r = w[k1]; + wk2i = w[k1 + 1]; + wk1r = w[k2]; + wk1i = w[k2 + 1]; + wk3r = wk1r - 2 * wk2i * wk1i; + wk3i = 2 * wk2i * wk1r - wk1i; + for(j = k; j < l + k; j += 2){ + j1 = j + l; + j2 = j1 + l; + j3 = j2 + l; + x0r = a[j] + a[j1]; + x0i = a[j + 1] + a[j1 + 1]; + x1r = a[j] - a[j1]; + x1i = a[j + 1] - a[j1 + 1]; + x2r = a[j2] + a[j3]; + x2i = a[j2 + 1] + a[j3 + 1]; + x3r = a[j2] - a[j3]; + x3i = a[j2 + 1] - a[j3 + 1]; + a[j] = x0r + x2r; + a[j + 1] = x0i + x2i; + x0r -= x2r; + x0i -= x2i; + a[j2] = wk2r * x0r - wk2i * x0i; + a[j2 + 1] = wk2r * x0i + wk2i * x0r; + x0r = x1r - x3i; + x0i = x1i + x3r; + a[j1] = wk1r * x0r - wk1i * x0i; + a[j1 + 1] = wk1r * x0i + wk1i * x0r; + x0r = x1r + x3i; + x0i = x1i - x3r; + a[j3] = wk3r * x0r - wk3i * x0i; + a[j3 + 1] = wk3r * x0i + wk3i * x0r; + } + wk1r = w[k2 + 2]; + wk1i = w[k2 + 3]; + wk3r = wk1r - 2 * wk2r * wk1i; + wk3i = 2 * wk2r * wk1r - wk1i; + for(j = k + m; j < l + (k + m); j += 2){ + j1 = j + l; + j2 = j1 + l; + j3 = j2 + l; + x0r = a[j] + a[j1]; + x0i = a[j + 1] + a[j1 + 1]; + x1r = a[j] - a[j1]; + x1i = a[j + 1] - a[j1 + 1]; + x2r = a[j2] + a[j3]; + x2i = a[j2 + 1] + a[j3 + 1]; + x3r = a[j2] - a[j3]; + x3i = a[j2 + 1] - a[j3 + 1]; + a[j] = x0r + x2r; + a[j + 1] = x0i + x2i; + x0r -= x2r; + x0i -= x2i; + a[j2] = -wk2i * x0r - wk2r * x0i; + a[j2 + 1] = -wk2i * x0i + wk2r * x0r; + x0r = x1r - x3i; + x0i = x1i + x3r; + a[j1] = wk1r * x0r - wk1i * x0i; + a[j1 + 1] = wk1r * x0i + wk1i * x0r; + x0r = x1r + x3i; + x0i = x1i - x3r; + a[j3] = wk3r * x0r - wk3i * x0i; + a[j3 + 1] = wk3r * x0i + wk3i * x0r; + } + } +} +//--------------------------------------------------------------------------- +void CFFT::Calc(double * InBuf, int size, double gain, int stg, int* OutBuf) +{ + if( m_FFTDIS ) return; // for math error + m_FFTDIS++; + int i; + + if( stg > 1 ){ + m_StgSW = TRUE; + } + else { + m_StgSW = FALSE; + } + m_StgSize = stg; + if( stg ){ + m_StgScale = 1.0 / double(m_StgSize); + m_StgK = 1.0 - m_StgScale; + } + else { + m_StgScale = 1.0; + m_StgK = 0.0; + } + double *dp = InBuf; + for(i=0; i < FFT_SIZE; i++, dp++){ + if( *dp > 32768.0 ){ + *dp = 32768.0; + } + else if( *dp < -32768.0 ){ + *dp = -32768.0; + } + (*dp) *= m_tWindow[i]; + } + bitrv2(FFT_SIZE, m_Work + 2, InBuf); + cftfsub(FFT_SIZE, InBuf, m_tSinCos); + rftfsub(FFT_SIZE, InBuf, m_Work[1], m_tSinCos + m_Work[0]); + for( i = 0, dp = pStgBuf; i <= size; i++, dp+=2 ){ + OutBuf[i] = int((gain * (*dp))); + } + m_FFTDIS--; +} + +//--------------------------------------------------------------------------- +void CFFT::CalcFQC(double * InBuf, int size, double gain, int stg, int* OutBuf) +{ + double *dp = InBuf; + double d; + int i, r; + memset(OutBuf, 0, sizeof(int)*size); + int ad, ad2, max; + switch(sys.m_FFTGain&3){ + case 0: + ad = 30; + max = ad * 32; + break; + case 1: + ad = 30; + max = ad * 24; + break; + case 2: + ad = 40; + max = ad * 16; + break; + default: + ad = 50; + max = ad * 12; + break; + } + ad2 = ad / 2; + int *op; + size--; + for( i = 0; i < FFT_SIZE; i++, dp++ ){ + d = m_fqc.Do(*dp); + d = 1900.0 - (d * 400 / 16384.0); + r = d * FFT_SIZE / FFTSamp; + if( (r >= 1) && (r < size) ){ + op = &OutBuf[r]; + if( *op < max ){ + *op += ad; + *(op-1) += ad2; + *(op+1) += ad2; + } + } + } +} +//--------------------------------------------------------------------------- +void CFFT::rftfsub(int n, double *a, int nc, double *c) +{ + int j, k, kk, ks, m; + double wkr, wki, xr, xi, yr, yi; + double d; + + ks = (nc << 2) / n; + kk = 0; + m = n >> 1; + j = n - 2; + if(m_StgSW){ + for (k = 2; k <= m; k += 2, j -= 2 ){ + kk += ks; + wkr = 0.5 - c[nc - kk]; + wki = c[kk]; + xr = a[k] - a[j]; + xi = a[k + 1] + a[j + 1]; + yr = wkr * xr - wki * xi; + yi = wkr * xi + wki * xr; + a[k] -= yr; + xi = a[k]*a[k]; + a[k+1] -= yi; + xi += ( a[k+1]*a[k+1]); + a[j] += yr; + xr = a[j]*a[j]; + a[j+1] -= yi; + xr += (a[j+1]*a[j+1]); + if( xi <= 0 ) xi = 0.0001; + if( xi >= 1e38 ) xi = 1e38; + if( xr <= 0 ) xr = 0.0001; + if( xr >= 1e38 ) xr = 1e38; + if( FFT_SIZE == 1024 ){ + xi *= 4; + xr *= 4; + } + switch(sys.m_FFTGain){ + case 0: + pStgBuf[k] = m_StgK*pStgBuf[k] + m_StgScale*(log10(xi+LOGADJ) + SCALEADJ_1); + pStgBuf[j] = m_StgK*pStgBuf[j] + m_StgScale*(log10(xr+LOGADJ) + SCALEADJ_1); + break; + case 1: + pStgBuf[k] = m_StgK*pStgBuf[k] + m_StgScale*(log10(xi+LOGADJ) + SCALEADJ_2); + pStgBuf[j] = m_StgK*pStgBuf[j] + m_StgScale*(log10(xr+LOGADJ) + SCALEADJ_2); + break; + case 2: + pStgBuf[k] = m_StgK*pStgBuf[k] + m_StgScale*(log10(xi+LOGADJ) + SCALEADJ_3); + pStgBuf[j] = m_StgK*pStgBuf[j] + m_StgScale*(log10(xr+LOGADJ) + SCALEADJ_3); + break; + case 3: + pStgBuf[k] = m_StgK*pStgBuf[k] + m_StgScale*(log10(xi+LOGADJ) + SCALEADJ_4); + pStgBuf[j] = m_StgK*pStgBuf[j] + m_StgScale*(log10(xr+LOGADJ) + SCALEADJ_4); + break; + case 4: + d = xi * 32e-10; + pStgBuf[k] = m_StgK*pStgBuf[k] + m_StgScale*d; + d = xr * 32e-10; + pStgBuf[j] = m_StgK*pStgBuf[j] + d; + break; + case 5: + d = xi * 96e-10; + pStgBuf[k] = m_StgK*pStgBuf[k] + m_StgScale*d; + d = xr * 96e-10; + pStgBuf[j] = m_StgK*pStgBuf[j] + d; + break; + case 6: + d = xi * 256e-10; + pStgBuf[k] = m_StgK*pStgBuf[k] + m_StgScale*d; + d = xr * 256e-10; + pStgBuf[j] = m_StgK*pStgBuf[j] + d; + break; + default: + d = xi * 512e-10; + pStgBuf[k] = m_StgK*pStgBuf[k] + m_StgScale*d; + d = xr * 512e-10; + pStgBuf[j] = m_StgK*pStgBuf[j] + d; + break; + } + } + } + else { + for (k = 2; k <= m; k += 2, j -= 2 ){ + kk += ks; + wkr = 0.5 - c[nc - kk]; + wki = c[kk]; + xr = a[k] - a[j]; + xi = a[k + 1] + a[j + 1]; + yr = wkr * xr - wki * xi; + yi = wkr * xi + wki * xr; + a[k] -= yr; + xi = a[k]*a[k]; + a[k+1] -= yi; + xi += ( a[k+1]*a[k+1]); + a[j] += yr; + xr = a[j]*a[j]; + a[j+1] -= yi; + xr += (a[j+1]*a[j+1]); + if( xi <= 0 ) xi = 0.0001; + if( xi >= 1e38 ) xi = 1e38; + if( xr <= 0 ) xr = 0.0001; + if( xr >= 1e38 ) xr = 1e38; + if( FFT_SIZE == 1024 ){ + xi *= 4; + xr *= 4; + } + switch(sys.m_FFTGain){ + case 0: + pStgBuf[k] = log10(xi+LOGADJ)+SCALEADJ_1; + pStgBuf[j] = log10(xr+LOGADJ)+SCALEADJ_1; + break; + case 1: + pStgBuf[k] = log10(xi+LOGADJ)+SCALEADJ_2; + pStgBuf[j] = log10(xr+LOGADJ)+SCALEADJ_2; + break; + case 2: + pStgBuf[k] = log10(xi+LOGADJ)+SCALEADJ_3; + pStgBuf[j] = log10(xr+LOGADJ)+SCALEADJ_3; + break; + case 3: + pStgBuf[k] = log10(xi+LOGADJ)+SCALEADJ_4; + pStgBuf[j] = log10(xr+LOGADJ)+SCALEADJ_4; + break; + case 4: + pStgBuf[k] = xi * 32e-10; + pStgBuf[j] = xr * 32e-10; + break; + case 5: + pStgBuf[k] = xi * 96e-10; + pStgBuf[j] = xr * 96e-10; + break; + case 6: + pStgBuf[k] = xi * 256e-10; + pStgBuf[j] = xr * 256e-10; + break; + default: + pStgBuf[k] = xi * 512e-10; + pStgBuf[j] = xr * 512e-10; + break; + } + } + } + pStgBuf[FFT_SIZE/2] = pStgBuf[(FFT_SIZE/2) - 2]; +} + diff --git a/Fft.h b/Fft.h new file mode 100644 index 0000000..2283b04 --- /dev/null +++ b/Fft.h @@ -0,0 +1,77 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +#ifndef FFT_H +#define FFT_H +//--------------------------------------------------------------------------- +#define FFT_BUFSIZE 2048 +#define SQRT_FFT_SIZE 46//sqrt(2048) + +#define CM_FFT WM_USER+403 + +#include "sstv.h" + +class CFFT +{ +public: + CFFT(); + virtual ~CFFT(); + void InitFFT(void); + + int IsData(void){ + return m_CollectCount; + }; + int m_CollectFFT; + HWND m_Handle; + void CollectFFT(double *lp, int size); + void CalcFFT(int size, double gain, int stg); + void TrigFFT(void); + int m_FFTDIS; + int m_fft[2048]; +private: + void Calc(double * InBuf, int size, double gain, int stg, int* OutBuf); + void CalcFQC(double * InBuf, int size, double gain, int stg, int* OutBuf); + BOOL m_StgSW; + int m_StgSize; + double m_StgScale; + double m_StgK; + + int m_CollectFlag; + int m_CollectrPage; + int m_CollectwPage; + int m_CollectCount; + int m_CollectFFTCount; + double m_CollectFFTBuf[3][2048]; + + double *m_tSinCos; + double *m_tWindow; + double *pStgBuf; + int *m_Work; + void makewt(int nw, int *ip, double *w); + void makect(int nc, int *ip, double *c); + void bitrv2(int n, int *ip, double *a); + void cftfsub(int n, double *a, double *w); + void rftfsub(int n, double *a, int nc, double *c); + void cft1st(int n, double *a, double *w); + void cftmdl(int n, int l, double *a, double *w); + + CFQC m_fqc; +}; + +#endif diff --git a/FreqDisp.cpp b/FreqDisp.cpp new file mode 100644 index 0000000..7062b90 --- /dev/null +++ b/FreqDisp.cpp @@ -0,0 +1,187 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "FreqDisp.h" +//--------------------------------------------------------------------- +#pragma resource "*.dfm" +TFreqDispDlg *FreqDispDlg; +//--------------------------------------------------------------------- +__fastcall TFreqDispDlg::TFreqDispDlg(TComponent* AOwner) + : TForm(AOwner) +{ + FormStyle = ((TForm *)AOwner)->FormStyle; + Font->Name = ((TForm *)AOwner)->Font->Name; + Font->Charset = ((TForm *)AOwner)->Font->Charset; + + m_H1 = NULL; + m_Tap1 = 0; + m_Over1 = 1; + m_H2 = NULL; + m_Tap2 = 0; + m_Over2 = 1; + m_Max = 0; + + pBitmap = new Graphics::TBitmap(); + pBitmap->Width = PaintBox->Width; + pBitmap->Height = PaintBox->Height; + if( MsgEng ){ + CancelBtn->Caption = "Close"; + BwBtn->Caption = "Width"; + Caption = "frequency characteristic"; + } +} +__fastcall TFreqDispDlg::~TFreqDispDlg() +{ + delete pBitmap; +} +//--------------------------------------------------------------------- +void __fastcall TFreqDispDlg::Execute(const double *H, int Tap, int Over) +{ + m_type = 0; + m_H1 = H; + m_Tap1 = Tap; + m_Over1 = Over; + m_Tap2 = 0; + ShowModal(); +} +//--------------------------------------------------------------------- +void __fastcall TFreqDispDlg::Execute(const double *H1, const double *H2, int Tap, int Over) +{ + m_type = 0; + m_H1 = H1; + m_Tap1 = Tap; + m_Over1 = Over; + m_H2 = H2; + m_Tap2 = Tap; + m_Over2 = Over; + ShowModal(); +} +//--------------------------------------------------------------------- +void __fastcall TFreqDispDlg::Execute(double a10, double b11, double b12, double a20, double b21, double b22, int Over) +{ + m_type = 1; + m_Over1 = Over; + m_a10 = a10; + m_b11 = b11; + m_b12 = b12; + m_a20 = a20; + m_b21 = b21; + m_b22 = b22; + ShowModal(); +} +//--------------------------------------------------------------------- +void __fastcall TFreqDispDlg::Execute(CIIR *ip, int Over, double max) +{ + m_type = 2; + m_piir = ip; + m_Over1 = Over; + m_Max = max; + ShowModal(); +} +//--------------------------------------------------------------------- +void __fastcall TFreqDispDlg::Execute(const double *H, int Tap, int Over, double max) +{ + m_type = 3; + m_H1 = H; + m_Tap1 = Tap; + m_Over1 = Over; + m_Tap2 = 0; + m_Max = max; + ShowModal(); +} +//--------------------------------------------------------------------- +void __fastcall TFreqDispDlg::PaintBoxPaint(TObject *Sender) +{ + if( m_type == 0 ){ // FIR + if( Timer->Enabled ){ + memcpy(m_HT, m_H1, sizeof(double)*(m_Tap1+1)); + DrawGraph(pBitmap, m_H1, m_Tap1, m_Over1, m_Max, 1, clBlue); + } + else { + DrawGraph(pBitmap, m_H1, m_Tap1, m_Over1, m_Max, 1, clBlue); + if( m_Tap2 ){ + DrawGraph(pBitmap, m_H2, m_Tap2, m_Over2, m_Max, 0, clRed); + } + } + } + else if( m_type == 1 ){ // IIR Tank + DrawGraphIIR(pBitmap, m_a10, 0, 0, -m_b11, -m_b12, m_Over1, m_Max, 1, clBlue); + DrawGraphIIR(pBitmap, m_a20, 0, 0, -m_b21, -m_b22, m_Over1, m_Max, 0, clRed); + } + else if( m_type == 2 ){ // IIR +#if 1 + DrawGraphIIR(pBitmap, m_piir, m_Over1, m_Max, 1, clBlue); +#else + CIIR iir; + iir.MakeIIR(2600, SampFreq, 10, 0, 0); + m_Max = 6000.0; + DrawGraphIIR(pBitmap, &iir, 1, m_Max, 1, clBlue); +#endif + } + else if( m_type == 3 ){ // FIR-Avg + DrawGraph(pBitmap, m_H1, m_Tap1, m_Over1, m_Max, 1, clBlue); + } + PaintBox->Canvas->Draw(0, 0, (TGraphic*)pBitmap); +} +//--------------------------------------------------------------------------- +void __fastcall TFreqDispDlg::BwBtnClick(TObject *Sender) +{ + if( m_type >= 2 ){ + switch(m_Max){ + case 100: + m_Max = 200; + break; + case 200: + m_Max = 400; + break; + case 400: + m_Max = 800; + break; + case 800: + m_Max = 3000; + break; + default: + m_Max = 100; + break; + } + } + else { + switch(m_Max){ + case 3000: + m_Max = 4000; + break; + case 4000: + m_Max = 6000; + break; + case 6000: + m_Max = 2000; + break; + default: + m_Max = 3000; + break; + } + } + PaintBoxPaint(NULL); +} +//--------------------------------------------------------------------------- + diff --git a/FreqDisp.dfm b/FreqDisp.dfm new file mode 100644 index 0000000..1206a75 Binary files /dev/null and b/FreqDisp.dfm differ diff --git a/FreqDisp.h b/FreqDisp.h new file mode 100644 index 0000000..b7dc98c --- /dev/null +++ b/FreqDisp.h @@ -0,0 +1,83 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//---------------------------------------------------------------------------- +#ifndef FreqDispH +#define FreqDispH +//---------------------------------------------------------------------------- + //ja7ude 0428 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//---------------------------------------------------------------------------- +#include "fir.h" +//---------------------------------------------------------------------------- +class TFreqDispDlg : public TForm +{ +__published: + TButton *CancelBtn; + TPanel *Panel; + TPaintBox *PaintBox; + TTimer *Timer; + TButton *BwBtn; + void __fastcall PaintBoxPaint(TObject *Sender); + + void __fastcall BwBtnClick(TObject *Sender); +private: + Graphics::TBitmap *pBitmap; + + int m_type; + double m_a10, m_a20; + double m_b11, m_b12; + double m_b21, m_b22; + + CIIR *m_piir; + + const double *m_H1; + int m_Tap1; + int m_Over1; + const double *m_H2; + int m_Tap2; + int m_Over2; + + double m_HT[TAPMAX+1]; +public: + virtual __fastcall TFreqDispDlg(TComponent* AOwner); + __fastcall ~TFreqDispDlg(); + + void __fastcall Execute(const double *H, int Tap, int Over); + void __fastcall Execute(const double *H1, const double *H2, int Tap, int Over); + void __fastcall Execute(double a10, double b11, double b12, double a20, double b21, double b22, int Over); + void __fastcall Execute(CIIR *ip, int Over, double max); + void __fastcall Execute(const double *H, int Tap, int Over, double max); + + int m_Max; +}; +//---------------------------------------------------------------------------- +extern TFreqDispDlg *FreqDispDlg; +//---------------------------------------------------------------------------- +#endif + diff --git a/Hamlog5.cpp b/Hamlog5.cpp new file mode 100644 index 0000000..6a20e4d --- /dev/null +++ b/Hamlog5.cpp @@ -0,0 +1,632 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "ComLib.h" +#include "LogFile.h" +#include "Hamlog5.h" +#include "LogConv.h" +//-------------------------------------------- +const LPCSTR g_Hamlog5Key[]={ + "CALLS", "IGN", "DATE", "TIME", "CODE", "GL", "QSL", "FLAG", "HIS", "MY", + "FREQ", "MODE", "NAME", "QTH", "RMK1", "RMK2", NULL +}; +const BYTE g_Hamlog5Len[]={ + 8, 12, 4, 2, 6, 6, 3, 2, 3, 3, + 7, 4, 12, 28, 54, 54, 0 +}; +//-------------------------------------------- +void __fastcall GetHamlog5FieldsLen(AnsiString &as) +{ + as = ""; + for( int i = 8; i < 15; i++ ){ + if( i > 8 ) as += ","; + as += Log.m_LogSet.m_Hamlog5Len[i]; + } +} +//-------------------------------------------- +void __fastcall SetHamlog5FieldsLen(AnsiString &as) +{ + LPSTR pBF = StrDupe(as.c_str()); + LPSTR p, t; + p = pBF; + for( int i = 8; i < 15; i++ ){ + p = StrDlm(t, p); + Log.m_LogSet.m_Hamlog5Len[i] = BYTE(atoin(t, -1)); + } + delete pBF; +} +//-------------------------------------------- +//コンストラクタ +CHamlog5::CHamlog5() +{ + m_fCreate = FALSE; + m_RecMax = 0; // レコード数 + m_FilMax = 0; // フィールド数 + m_RecWidth = 0; // レコードの幅 + m_FilOff = 0; // ヘッダオフセット + m_bp = NULL; + m_OpenFlag = FALSE; + m_WriteFlag = FALSE; // 書き込みフラグ +} + +//-------------------------------------------- +//デストラクタ +CHamlog5::~CHamlog5() +{ + Close(); +} + +//-------------------------------------------- +//ヘッダデータセットアップ +BOOL CHamlog5::SetupHeader(void) +{ + if( fread(&m_Head, 1, sizeof(m_Head), m_fp)!=sizeof(m_Head) ){ + return FALSE; // 異なるフォーマット + } + + if( (m_Head.Type != 0x03)&&(m_Head.Type != 0x1a ) ) return FALSE; + + m_RecMax = m_Head.RecMax; + m_FilOff = m_Head.FilOff; + m_RecWidth = m_Head.RecWidth; + if( !m_FilOff ) return FALSE; + + hamlog5DBRHD slot; + ULONG fPos; + for( m_FilMax = 0; m_FilMax < HamlogDBMAX; m_FilMax++ ){ + fPos = (32L*m_FilMax)+32L; + if( fPos > ULONG(m_FilOff) ) break; + if( fread(&slot, 1, sizeof(slot), m_fp)!=sizeof(slot) ) break; + if( slot.Name[0] == 0x0d ) break; + slot.Name[10] = 0; + m_StrTable[m_FilMax] = slot.Name; + m_TypeTable[m_FilMax] = slot.Type; + m_LenTable[m_FilMax] = USHORT(slot.Len); + } + for( int i = 8; (i < 15) && (i < m_FilMax); i++ ){ + Log.m_LogSet.m_Hamlog5Len[i] = m_LenTable[i]; + } + +// if( (m_Head.Type == 0x1a) && !m_RecMax ){ +// m_RecMax = (m_fStatus.m_size - ULONG(m_FilOff)) / ULONG(m_RecWidth); +// } + + USHORT i; + USHORT Pos = 1; + for( i = 0; i < m_FilMax; i++ ){ + m_PosTable[i] = Pos; + Pos += m_LenTable[i]; + } + return TRUE; +} + +//-------------------------------------------- +//ヘッダデータ作成 +BOOL CHamlog5::MakeHeader(const LPCSTR _NT[], const BYTE _LT[]) +{ + hamlog5DBRHD slot; + + memset(&m_Head, 0, sizeof(m_Head)); + fseek(m_fp, 0, SEEK_SET); + fwrite(&m_Head, 1, sizeof(m_Head), m_fp); + m_FilOff = sizeof(m_Head); + m_RecWidth = 1; + for( m_FilMax = 0; _LT[m_FilMax]; m_FilMax++ ){ + memset(&slot, 0, sizeof(slot)); + strcpy(slot.Name, _NT[m_FilMax]); + slot.Len = _LT[m_FilMax]; + slot.Type = 'C'; + fwrite(&slot, 1, sizeof(slot), m_fp); + m_PosTable[m_FilMax] = m_RecWidth; + m_RecWidth += USHORT(_LT[m_FilMax]); + m_FilOff += USHORT(sizeof(slot)); + m_StrTable[m_FilMax] = _NT[m_FilMax]; + m_TypeTable[m_FilMax] = 'C'; + m_LenTable[m_FilMax] = USHORT(_LT[m_FilMax]); + } + char Term = 0x0d; + fwrite(&Term, 1, 1, m_fp); + m_FilOff++; + m_Head.Type = 3; + SYSTEMTIME st; + ::GetLocalTime(&st); + m_Head.Year = BYTE(st.wYear % 100); + m_Head.Mon = BYTE(st.wMonth); + m_Head.Day = BYTE(st.wDay); + m_Head.RecMax = 0; + m_Head.FilOff = m_FilOff; + m_Head.RecWidth = m_RecWidth; + fseek(m_fp, 0, SEEK_SET); + fwrite(&m_Head, 1, sizeof(m_Head), m_fp); + return TRUE; +} + +//-------------------------------------------- +//オープン +BOOL CHamlog5::Open(LPCSTR Name, BOOL fMsg) +{ + if( (m_OpenFlag == TRUE) ) Close(); + m_WriteFlag = FALSE; // 書き込みフラグ + if( (m_fp = fopen(Name, "rb")) == NULL ){ + if( fMsg ) ErrorMB("%sがオープンできません.", Name); + return FALSE; // ファイルがオープンできない + } + m_OpenFlag = TRUE; + m_fCreate = FALSE; + if( SetupHeader() == FALSE ){ + Close(); + if( fMsg ) ErrorMB("ファイルフォーマットが認識できません."); + return FALSE; + } + if( m_bp ) delete m_bp; + m_bp = new char[m_RecWidth]; + if( Seek(0) == FALSE ){ + Close(); + if( fMsg ) ErrorMB("データーレコードが存在しません."); + return FALSE; + } + return TRUE; +} + +//-------------------------------------------- +//オープン +BOOL CHamlog5::Create(LPCSTR Name) +{ + if( (m_OpenFlag == TRUE) ) Close(); + m_WriteFlag = FALSE; // 書き込みフラグ + if( (m_fp = fopen(Name, "wb")) == NULL ){ + ErrorMB("%sを作成できません.", Name); + return FALSE; // ファイルがオープンできない + } + m_OpenFlag = TRUE; + m_fCreate = TRUE; + if( MakeHeader(g_Hamlog5Key, Log.m_LogSet.m_Hamlog5Len) == FALSE ){ + Close(); + ErrorMB("%sを作成できません.", Name); + return FALSE; + } + if( m_bp ) delete m_bp; + m_bp = new char[m_RecWidth]; + return TRUE; +} + +//-------------------------------------------- +//クローズ +void CHamlog5::Close(void) +{ + if( m_OpenFlag == TRUE ){ + Update(); + if( m_RecMax != m_Head.RecMax ){ // データが追加されている + m_Head.RecMax = m_RecMax; + fseek(m_fp, 0, SEEK_SET); + fwrite(&m_Head, 1, sizeof(m_Head), m_fp); + } + int r = fclose(m_fp); + m_fp = NULL; + if( r && m_fCreate ){ + ErrorMB("ファイルの作成に失敗しました."); + } + m_OpenFlag = FALSE; + } + if( m_bp != NULL ){ + delete m_bp; + m_bp = NULL; + } +} + +//-------------------------------------------- +//レコードシーク +BOOL CHamlog5::Seek(ULONG Index) +{ + if( m_OpenFlag == FALSE ) return FALSE; + if( Update() == FALSE ) return FALSE; + m_Index = Index; + m_Pos = (Index * ULONG(m_RecWidth)) + ULONG(m_FilOff); + fseek(m_fp, m_Pos, SEEK_SET); + if( Index < m_RecMax ){ + if( fread(m_bp, 1, m_RecWidth, m_fp) != ULONG(m_RecWidth) ){ + return FALSE; + } + } + else { + memset(m_bp, ' ', m_RecWidth); + } + return TRUE; +} + +//-------------------------------------------- +//マークのチェック +BOOL CHamlog5::IsData(void) +{ + return (*m_bp == ' ') ? TRUE : FALSE; +} + +//-------------------------------------------- +//データの読み込み +BOOL CHamlog5::GetData(USHORT SubIndex, AnsiString &cs) +{ + char bf[1024]; + + if( SubIndex >= m_FilMax ) return FALSE; + + int len = m_LenTable[SubIndex]; + if( len >= 1023 ) len = 1023; + StrCopy(bf, m_bp + m_PosTable[SubIndex], len); + cs = bf; + return TRUE; +} +//-------------------------------------------- +//データの読み込み +BOOL CHamlog5::GetData(USHORT SubIndex, LPSTR pStore) +{ + if( SubIndex >= m_FilMax ) return FALSE; + + int len = m_LenTable[SubIndex]; + if( len >= 1023 ) len = 1023; + StrCopy(pStore, m_bp + m_PosTable[SubIndex], len); + return TRUE; +} + +//-------------------------------------------- +//データの読み込み +int CHamlog5::GetData(USHORT SubIndex, LPBYTE pData, int len) +{ + if( SubIndex >= m_FilMax ) return 0; + + int rlen = m_LenTable[SubIndex]; + if( rlen >= 1023 ) rlen = 1023; + if( rlen > len ) rlen = len; + memcpy(pData, m_bp + m_PosTable[SubIndex], rlen); + return rlen; +} + +//-------------------------------------------- +//データの書き込み(バッファを更新するのみ) +BOOL CHamlog5::SetData(USHORT SubIndex, LPCSTR p) +{ + if( SubIndex >= m_FilMax ) return FALSE; + + int len = m_LenTable[SubIndex]; + LPSTR t; + int i; + for( i = 0, t = m_bp + m_PosTable[SubIndex]; i < len; i++, t++ ){ + if( *p ){ + *t = *p++; + } + else { + *t = ' '; + } + } + m_WriteFlag = TRUE; + return TRUE; +} +//-------------------------------------------- +//データの書き込み(バッファを更新するのみ) +BOOL CHamlog5::SetBinary(USHORT SubIndex, LPBYTE p) +{ + if( SubIndex >= m_FilMax ) return FALSE; + + int len = m_LenTable[SubIndex]; + LPSTR t; + int i; + for( i = 0, t = m_bp + m_PosTable[SubIndex]; i < len; i++, t++ ){ + *t = *p++; + } + m_WriteFlag = TRUE; + return TRUE; +} + +//-------------------------------------------- +//データの書き込み(バッファの内容を反映させる) +BOOL CHamlog5::Update(void) +{ + if( m_OpenFlag == FALSE ) return FALSE; + + if( m_WriteFlag == TRUE ){ + m_WriteFlag = FALSE; + fseek(m_fp, m_Pos, SEEK_SET); + fwrite(m_bp, 1, m_RecWidth, m_fp); + if( m_Index >= m_RecMax ){ + m_RecMax++; + } + } + return TRUE; +} +//-------------------------------------------- +//データのデコード +void CHamlog5::DecodeData(SDMMLOG *sp) +{ + memset(sp, 0, sizeof(SDMMLOG)); + char bf[1024]; + + + int YY, MM, DD, HH, mm; + GetData(itemhamlog5DATE, LPBYTE(bf), 4); + YY = bf[1]; + MM = bf[2]; + DD = bf[3]; + GetData(itemhamlog5TIME, LPBYTE(bf), 2); + HH = bf[0]; + mm = bf[1] & 0x7f; + if( bf[1] & 0x80 ){ + UTCtoJST(YY, MM, DD, HH); + } + sp->year = BYTE(YY); + sp->date = WORD(MM * 100 + DD); + sp->btime = WORD(((HH * 60 + mm) * 30)); + if(!sp->btime) sp->btime++; + + USHORT usFlag; // コールサインの形式 + GetData(itemhamlog5FLAG, LPBYTE(&usFlag), sizeof(usFlag)); + + LPSTR t, p; + AnsiString call; + if( (usFlag & bithamlog5DX) && (usFlag & bithamlog5RevOdr) ){ // KH6/JE3HHT + AnsiString Add; + GetData(itemhamlog5IGN, bf); + p = bf; + if( *p != ' ' ){ + p = StrDlm(t, p, ' '); + Add = t; + } + p = SkipSpace(p); + p = StrDlm(t, p, '/'); + call = t; + GetData(itemhamlog5CALLS, bf); clipsp(bf); + if( !call.IsEmpty() ) call += '/'; + call += SkipSpace(bf); + call += Add; + if( *p ){ + call += '/'; + call += p; + } + } + else { // JE3HHT/KH6 + GetData(itemhamlog5CALLS, bf); clipsp(bf); + call = SkipSpace(bf); + GetData(itemhamlog5IGN, bf); + p = bf; + if( *p != ' ' ){ + p = StrDlm(t, p, ' '); + call += t; + } + p = SkipSpace(p); + if( *p ){ + call += '/'; + call += p; + } + } + + StrCopy(sp->call, call.c_str(), MLCALL); + GetData(itemhamlog5HIS, bf); clipsp(bf); + StrCopy(sp->ur, bf, MLRST); + GetData(itemhamlog5MY, bf); clipsp(bf); + StrCopy(sp->my, bf, MLRST); + GetData(itemhamlog5MODE, bf); clipsp(bf); + Log.SetMode(sp, bf); + GetData(itemhamlog5FREQ, bf); clipsp(bf); + Log.SetFreq(sp, bf); + GetData(itemhamlog5NAME, bf); clipsp(bf); + StrCopy(sp->name, bf, MLNAME); + GetData(itemhamlog5QTH, bf); clipsp(bf); + StrCopy(sp->qth, bf, MLQTH); + + GetData(itemhamlog5RMK1, bf); + SetMMLOGKey(sp, bf); + clipsp(bf); + StrCopy(sp->rem, SkipSpace(bf), MLREM); + GetData(itemhamlog5RMK2, bf); + SetMMLOGKey(sp, bf); + clipsp(bf); + StrCopy(sp->qsl, SkipSpace(bf), MLQSL); + GetData(itemhamlog5QSL, LPBYTE(bf), 3); + sprintf(&bf[32], "QSL[%.3s]", bf); + Log.SetOptStr(2, sp, &bf[32]); + if( bf[0] == 'N' ){ + sp->send = 'N'; + } + else if( bf[1] == ' ' ){ // 未発送 + if( (bf[0] == 'J')||(bf[0] == ' ') ){ + sp->send = 0; + } + else { + sp->send = BYTE(tolower(bf[0])); + } + } + else { // 発送済み + sp->send = BYTE(toupper(bf[1])); + } + sp->recv = bf[2]; + if( sp->recv == ' ' ) sp->recv = 0; + GetData(itemhamlog5CODE, LPBYTE(bf), 6); clipsp(bf); + StrCopy(sp->opt1, bf, 6); + GetData(itemhamlog5GL, LPBYTE(bf), 6); clipsp(bf); + StrCopy(sp->opt2, bf, 6); + if( !sp->etime ) sp->etime = sp->btime; +} +//-------------------------------------------- +//データのエンコード +void CHamlog5::EncodeData(SDMMLOG *sp) +{ + char bf[1024]; + + int YY = sp->year; + int MM = sp->date / 100; + int DD = sp->date % 100; + int tim = sp->btime / 30; + int HH = tim / 60; + int mm = tim % 60; + switch(Log.m_LogSet.m_THTZ){ + case 0: + if( !IsJA(sp->call) ){ + JSTtoUTC(YY, MM, DD, HH); + mm |= 0x80; + } + break; + case 1: + JSTtoUTC(YY, MM, DD, HH); + mm |= 0x80; + break; + default: + break; + } + bf[0] = BYTE(YY > 50 ? 19 : 20); + bf[1] = BYTE(YY); + bf[2] = BYTE(MM); + bf[3] = BYTE(DD); + SetBinary(itemhamlog5DATE, LPBYTE(bf)); + bf[0] = BYTE(HH); + bf[1] = BYTE(mm); + SetBinary(itemhamlog5TIME, LPBYTE(bf)); + + SetData(itemhamlog5NAME, sp->name); + SetData(itemhamlog5CODE, sp->opt1); + SetData(itemhamlog5GL, sp->opt2); + SetData(itemhamlog5QTH, sp->qth); + strcpy(bf, Log.GetModeString(sp->mode)); + SetData(itemhamlog5MODE, bf); + strcpy(bf, Log.GetFreqString(sp->band, sp->fq)); + SetData(itemhamlog5FREQ, bf); + + SetData(itemhamlog5HIS, sp->ur); + SetData(itemhamlog5MY, sp->my); + + AnsiString REM1, REM2; + REM1 = sp->rem; + REM2 = sp->qsl; + int l = GetLMode(sp->mode); + if( sp->ur[l] ) AddMMLOGKey(REM1, REM2, &sp->ur[l], "SN"); + if( sp->my[l] ) AddMMLOGKey(REM1, REM2, &sp->my[l], "RN"); + + if( sp->etime ){ + tim = sp->etime / 30; + sprintf(bf, "%02u%02u", tim / 60, tim % 60); + AddMMLOGKey(REM1, REM2, bf, "END"); + } + if( sp->env ){ + sprintf(bf, "%u", sp->env); + AddMMLOGKey(REM1, REM2, bf, "ENV"); + } + AddMMLOGKey(REM1, REM2, sp->pow, "POW"); + if( sp->cq ){ + bf[0] = sp->cq; bf[1] = 0; + AddMMLOGKey(REM1, REM2, bf, "M"); + } + strcpy(bf, Log.GetOptStr(2, sp)); + char rbf[32]; + char qsl[3]; + if(RemoveL2(rbf, bf, "QSL", sizeof(rbf)-1) == TRUE){ + qsl[0] = rbf[0]; + qsl[1] = rbf[1]; + qsl[2] = rbf[2]; + } + else { + qsl[2] = sp->recv; + if( !qsl[2] ) qsl[2] = ' '; + if( sp->send == 'N' ){ + qsl[0] = 'N'; + qsl[1] = ' '; + } + else if( !sp->send ){ + qsl[0] = 'J'; + qsl[1] = ' '; + } + else if( (sp->send >= 0x60)||(sp->send == '?') ){ + qsl[0] = BYTE(toupper(sp->send)); + qsl[1] = ' '; + } + else if( isalpha(sp->send) ){ + qsl[0] = sp->send; + qsl[1] = '*'; + } + else { + qsl[0] = 'J'; + qsl[1] = sp->send; + } + } + SetData(itemhamlog5QSL, qsl); + SetData(itemhamlog5RMK1, REM1.c_str()); + SetData(itemhamlog5RMK2, REM2.c_str()); + + BOOL fJA = IsJA(sp->call); + USHORT usFlag = USHORT(fJA ? 0 : bithamlog5DX); + AnsiString Calls, Ign; + strcpy(bf, sp->call); + LPSTR pp, p2, t; + t = bf; + if( (pp = strchr(bf, '/')) != NULL ){ // KH6/JE3HHT or JE3HHT/KH6 の形式 + *pp = 0; + pp++; + int LenC = strlen(t); + int LenP = strlen(pp); + if( (p2 = strchr(pp, '/')) != NULL ){ // KH6/JE3HHT/P JE3HHT/QRP/3 + // t = KH6, pp = JE3HHT, p2 = P + *p2 = 0; p2++; + if( fJA ){ + Calls = t; + Ign = pp; + Ign += "/"; + Ign += p2; + } + else { + Calls = pp; + Ign = t; + Ign += "/"; + Ign += p2; + usFlag |= bithamlog5RevOdr; + } + } + else { + if( LenC < LenP ){ + Calls = pp; + Ign = t; + if( usFlag ) usFlag |= bithamlog5RevOdr; + } + else { + Calls = t; + Ign = pp; + if( usFlag ) usFlag |= bithamlog5NorOdr; + } + } + } + else { + Calls = sp->call; + } + SetBinary(itemhamlog5FLAG, LPBYTE(&usFlag)); + SetData(itemhamlog5CALLS, Calls.c_str()); + LPCSTR pCall = Calls.c_str(); + memset(bf, ' ', 12); bf[13] = 0; + l = strlen(pCall); + if( l > 8 ){ + pCall += 8; + l -= 8; + memcpy(bf, pCall, l); + } + l = strlen(Ign.c_str()); + if( l ){ + if( l > 12 ) l = 12; + memcpy(&bf[12 - l], Ign.c_str(), l); + } + SetData(itemhamlog5IGN, bf); +} + diff --git a/Hamlog5.h b/Hamlog5.h new file mode 100644 index 0000000..89fabf3 --- /dev/null +++ b/Hamlog5.h @@ -0,0 +1,119 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +#ifndef Hamlog5H +#define Hamlog5H + +// MMQSL用Hamlog Ver5のドライバ + +#include "ComLib.h" +#include "LogFile.h" +extern const LPCSTR g_Hamlog5Key[]; +extern const BYTE g_Hamlog5Len[]; + +typedef enum { + itemhamlog5CALLS, + itemhamlog5IGN, + itemhamlog5DATE, + itemhamlog5TIME, + itemhamlog5CODE, + itemhamlog5GL, + itemhamlog5QSL, + itemhamlog5FLAG, + itemhamlog5HIS, + itemhamlog5MY, + itemhamlog5FREQ, + itemhamlog5MODE, + itemhamlog5NAME, + itemhamlog5QTH, + itemhamlog5RMK1, + itemhamlog5RMK2, +}HAMLOG5_ITEMS; + +#define bithamlog5DX 8 +#define bithamlog5NorOdr 1 +#define bithamlog5RevOdr 2 + +#pragma pack(1) +typedef struct { + BYTE Type; + BYTE Year; + BYTE Mon; + BYTE Day; + ULONG RecMax; + USHORT FilOff; + USHORT RecWidth; + BYTE dm1[20]; +}hamlog5DBHD; +typedef struct { + char Name[11]; + BYTE Type; + BYTE dm1[4]; + BYTE Len; + BYTE dm2[15]; +}hamlog5DBRHD; +#pragma pack() + +#define HamlogDBMAX 16 +class CHamlog5 +{ +private: + BOOL m_fCreate; + hamlog5DBHD m_Head; // ヘッダ情報 + ULONG m_RecMax; // レコード数 + USHORT m_FilMax; // フィールド数 + USHORT m_RecWidth; // レコードの幅 + USHORT m_FilOff; // ヘッダオフセット + FILE *m_fp; + AnsiString m_StrTable[HamlogDBMAX]; // テーブル名の配列 + USHORT m_PosTable[HamlogDBMAX]; // フィールド位置の配列 + USHORT m_LenTable[HamlogDBMAX]; // フィールド長さの配列 + char m_TypeTable[HamlogDBMAX]; // 型情報の配列 + BOOL m_OpenFlag; // ファイルオープンフラグ + + ULONG m_Index; // シーク時のインデックス + ULONG m_Pos; // シーク時のファイル位置 + LPSTR m_bp; // バッファのポインタ + BOOL m_WriteFlag; // 書き込みフラグ + BOOL SetupHeader(void); // ヘッダセットアップ + BOOL MakeHeader(const LPCSTR _NT[], const BYTE _LT[]); +public: + CHamlog5(); + ~CHamlog5(); + BOOL Open(LPCSTR Name, BOOL fMsg); + BOOL Create(LPCSTR Name); + void Close(void); + inline ULONG GetRCount(void){return m_RecMax;}; + inline USHORT GetFCount(void){return m_FilMax;}; + AnsiString *GetStrBase(void){return m_StrTable;}; + BOOL Seek(ULONG Index); + BOOL IsData(void); + BOOL GetData(USHORT SubIndex, AnsiString &cs); + BOOL GetData(USHORT SubIndex, LPSTR pStore); + BOOL SetData(USHORT SubIndex, LPCSTR p); + BOOL SetBinary(USHORT SubIndex, LPBYTE p); + int GetData(USHORT SubIndex, LPBYTE pData, int len); + BOOL Update(void); + void DecodeData(SDMMLOG *sp); + void EncodeData(SDMMLOG *sp); +}; + +void __fastcall GetHamlog5FieldsLen(AnsiString &as); +void __fastcall SetHamlog5FieldsLen(AnsiString &as); +#endif diff --git a/HistView.cpp b/HistView.cpp new file mode 100644 index 0000000..eae8103 --- /dev/null +++ b/HistView.cpp @@ -0,0 +1,313 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "Main.h" +#include "HistView.h" +//--------------------------------------------------------------------------- +#pragma package(smart_init) +#pragma resource "*.dfm" +//--------------------------------------------------------------------------- +__fastcall THistViewDlg::THistViewDlg(TComponent* Owner) + : TForm(Owner) +{ + for( int i = 0; i < AHDMAX; i++ ){ + pBitmapH[i] = NULL; + pPanel[i] = NULL; + pBox[i] = NULL; + } + pPopup = NULL; + m_Col = 6; + m_Line = 1; + m_RectS.Left = 0; + m_RectS.Top = 0; + m_RectS.Right = 80; + m_RectS.Bottom = 64; + m_Max = m_Col = m_Line = 0; + SetThumbnailSize(m_RectS, sys.m_HistViewSize); + m_DisEvent = 0; +} +//--------------------------------------------------------------------------- +__fastcall THistViewDlg::~THistViewDlg() +{ + for( int i = 0; i < AHDMAX; i++ ){ + if( pBitmapH[i] != NULL ){ + delete pBitmapH[i]; + } + } +} +//--------------------------------------------------------------------------- +void __fastcall THistViewDlg::UpdateTitle(LPCSTR pTime) +{ + if( BorderStyle == bsNone ) return; + + LPCSTR pTTL; + + if( pTime != NULL ){ + pTTL = pTime; + } + else { + pTTL = MsgEng ? "Thumbnails of recent history" : "最近の履歴のサムネイル"; + } + Caption = pTTL; +} +//--------------------------------------------------------------------------- +void __fastcall THistViewDlg::UpdateTitlebar(void) +{ + if( m_TitleBar ){ + BorderStyle = bsSizeable; + } + else { + BorderStyle = bsNone; + } +} +//--------------------------------------------------------------------------- +void __fastcall THistViewDlg::FormResize(TObject *Sender) +{ + if( m_DisEvent ) return; + + int WW = m_RectS.Right + 6; + int HH = m_RectS.Bottom + 6; + if( BorderStyle == bsNone ){ + int ch = m_Line * HH; + int cw = m_Col * WW; + m_DisEvent++; + ClientHeight = ch; + ClientWidth = cw; + m_DisEvent--; + return; + } + int OldMax = m_Max; + int h = int((double(ClientHeight)/ HH) + 0.5); + if( !h ) h = 1; + int w = int((double(ClientWidth)/ WW) + 0.5); + if( !w ) w = 1; + while( (h * w) > AHDMAX ){ + if( w > 1 ){ + w--; + } + else if( h > 1 ){ + h--; + } + } + int ch = h * HH; + int cw = w * WW; + m_Col = w; + m_Line = h; + m_Max = h * w; + int i; + for( i = 0; i < m_Max; i++ ){ + if( pBitmapH[i] == NULL ){ + pBitmapH[i] = new Graphics::TBitmap(); + AdjustBitmapFormat(pBitmapH[i]); + } + pBitmapH[i]->Width = m_RectS.Right; + pBitmapH[i]->Height = m_RectS.Bottom; + if( pPanel[i] == NULL ){ + pPanel[i] = new TPanel(this); + InsertControl(pPanel[i]); + pPanel[i]->Parent = this; + pPanel[i]->Width = WW; + pPanel[i]->Height = HH; + pPanel[i]->BorderStyle = bsSingle; + pBox[i] = new TPaintBox(this); + pPanel[i]->InsertControl(pBox[i]); + pBox[i]->Parent = pPanel[i]; + pBox[i]->Align = alClient; + pBox[i]->OnPaint = PBPaint; + pBox[i]->OnMouseDown = PBMouseDown; + pBox[i]->OnMouseMove = PBMouseMove; + pBox[i]->OnDblClick = PBDblClick; + pBox[i]->PopupMenu = pPopup; + } + else { + pPanel[i]->Visible = FALSE; + pPanel[i]->Width = WW; + pPanel[i]->Height = HH; + } + MultProc(); + } + for( ; i < AHDMAX; i++ ){ + if( pBitmapH[i] != NULL ){ + delete pBitmapH[i]; + pBitmapH[i] = NULL; + } + if( pPanel[i] != NULL ){ + pPanel[i]->Visible = FALSE; + } + MultProc(); + } + m_DisEvent++; + ClientHeight = ch; + ClientWidth = cw; + for( i = 0; i < m_Max; i++ ){ + pPanel[i]->Left = (i % m_Col) * WW; + pPanel[i]->Top = (i / m_Col) * HH; + pPanel[i]->Visible = TRUE; + } + m_DisEvent--; + if( OldMax < m_Max ){ + LoadHist(OldMax); + } +} +//--------------------------------------------------------------------------- +int __fastcall THistViewDlg::IsPBox(TObject *Sender) +{ + for( int i = 0; i < m_Max; i++ ){ + if( Sender == pBox[i] ) return i; + } + return -1; +} +//--------------------------------------------------------------------------- +void __fastcall THistViewDlg::UpdateBitmap(void) +{ + for( int i = 0; i < m_Max; i++ ){ + pBox[i]->Invalidate(); + } +} +//--------------------------------------------------------------------------- +void __fastcall THistViewDlg::SetPopup(TPopupMenu *tp) +{ + pPopup = tp; + for( int i = 0; i < m_Max; i++ ){ + pBox[i]->PopupMenu = tp; + } +} +//--------------------------------------------------------------------------- +void __fastcall THistViewDlg::LoadHist(int b) +{ + if( !m_Max ) return; + CWaitCursor wait; + Graphics::TBitmap *pBitmap = new Graphics::TBitmap(); + pBitmap->Width = 320; + pBitmap->Height = 256; + + int SaveCur = Mmsstv->RxHist.m_CurRead; + int n = (Mmsstv->RxHist.m_Head.m_wPnt - 1) - b; + int i; + for( i = b; (i < m_Max) && (i < Mmsstv->RxHist.m_Head.m_Cnt); i++, n-- ){ + if( n < 0 ) n += Mmsstv->RxHist.m_Head.m_Max; + if( n >= Mmsstv->RxHist.m_Head.m_Max ) n -= Mmsstv->RxHist.m_Head.m_Max; + Mmsstv->RxHist.Read(pBitmap, n); + ::SetStretchBltMode(pBitmapH[i]->Canvas->Handle, HALFTONE); + pBitmapH[i]->Canvas->StretchDraw(m_RectS, pBitmap); + MultProc(); + } + for( ; i < m_Max; i++ ){ + FillBitmap(pBitmapH[i], clWhite); + MultProc(); + } + Mmsstv->RxHist.m_CurRead = SaveCur; + delete pBitmap; + UpdateBitmap(); +} +//--------------------------------------------------------------------------- +void __fastcall THistViewDlg::Add(Graphics::TBitmap *pBitmap) +{ + for( int i = m_Max-1; i; i-- ){ + pBitmapH[i]->Assign(pBitmapH[i-1]); + } + ::SetStretchBltMode(pBitmapH[0]->Canvas->Handle, HALFTONE); + pBitmapH[0]->Canvas->StretchDraw(m_RectS, pBitmap); + UpdateBitmap(); +} +//--------------------------------------------------------------------------- +void __fastcall THistViewDlg::PBPaint(TObject *Sender) +{ + int r = IsPBox(Sender); + if( r >= 0 ){ + pBox[r]->Canvas->Draw(0, 0, pBitmapH[r]); + } +} +//--------------------------------------------------------------------------- +void __fastcall THistViewDlg::PBClick(int n) +{ + if( n < Mmsstv->RxHist.m_Head.m_Cnt ){ + if( Mmsstv->UDHist->Position != SHORT(n) ){ + Mmsstv->UDHist->Position = SHORT(n); + Mmsstv->UpdateHist(); + } + else { + Mmsstv->DispHistStat(); + } + } +} +//--------------------------------------------------------------------------- +void __fastcall THistViewDlg::PBDblClick(TObject *Sender) +{ + Mmsstv->AdjustPage(pgHist); +} +//--------------------------------------------------------------------------- +void __fastcall THistViewDlg::PBMouseDown(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ +// if( Mmsstv->SBTX->Down ) return; + + int r = IsPBox(Sender); + if( r >= 0 ){ + PBClick(r); + m_XX = X; + m_YY = Y; +// if( Button == mbLeft ){ +// ((TPaintBox *)Sender)->BeginDrag(TRUE); +// } + } +} +//--------------------------------------------------------------------------- +void __fastcall THistViewDlg::PBMouseMove(TObject *Sender, + TShiftState Shift, int X, int Y) +{ + TShiftState sc1, sc2; + sc1 << ssLeft; + sc2 << ssLeft; + sc1 *= Shift; + if( sc1 == sc2 ){ // Left button + if( (ABS(m_XX-X) + ABS(m_YY-Y)) >= 10 ){ + ((TPaintBox *)Sender)->BeginDrag(TRUE,0); + } + } +} +//--------------------------------------------------------------------------- +void __fastcall THistViewDlg::FormClose(TObject *Sender, + TCloseAction &Action) +{ + Mmsstv->m_FileViewClose = 1; +} +//--------------------------------------------------------------------------- +void __fastcall THistViewDlg::FormKeyDown(TObject *Sender, WORD &Key, + TShiftState Shift) +{ + Mmsstv->FormKeyDown(Sender, Key, Shift); +} +//--------------------------------------------------------------------------- +void __fastcall THistViewDlg::FormKeyUp(TObject *Sender, WORD &Key, + TShiftState Shift) +{ + Mmsstv->FormKeyUp(Sender, Key, Shift); +} +//--------------------------------------------------------------------------- +void __fastcall THistViewDlg::FormDeactivate(TObject *Sender) +{ + UpdateTitle(NULL); +} +//--------------------------------------------------------------------------- + diff --git a/HistView.dfm b/HistView.dfm new file mode 100644 index 0000000..eabc20c Binary files /dev/null and b/HistView.dfm differ diff --git a/HistView.h b/HistView.h new file mode 100644 index 0000000..123af6e --- /dev/null +++ b/HistView.h @@ -0,0 +1,93 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------------- +#ifndef HistViewH +#define HistViewH +//--------------------------------------------------------------------------- +#include +#include +#include +#include +#include +//--------------------------------------------------------------------------- +class THistViewDlg : public TForm +{ +__published: // IDE 管理のコンポーネント + void __fastcall FormResize(TObject *Sender); + void __fastcall FormClose(TObject *Sender, TCloseAction &Action); + void __fastcall FormKeyDown(TObject *Sender, WORD &Key, + TShiftState Shift); + void __fastcall FormKeyUp(TObject *Sender, WORD &Key, + TShiftState Shift); + void __fastcall FormDeactivate(TObject *Sender); +private: // ユーザー宣言 +#define AHDMAX 64 + Graphics::TBitmap *pBitmapH[AHDMAX]; + TPanel *pPanel[AHDMAX]; + TPaintBox *pBox[AHDMAX]; + TPopupMenu *pPopup; + + TRect m_RectS; + + int m_Max; + int m_Col; + int m_Line; + int m_DisEvent; + + int m_XX; + int m_YY; + + void __fastcall PBClick(int n); + void __fastcall PBPaint(TObject *Sender); + void __fastcall PBMouseDown(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + void __fastcall PBMouseMove(TObject *Sender, + TShiftState Shift, int X, int Y); + void __fastcall PBDblClick(TObject *Sender); + + +public: // ユーザー宣言 + __fastcall THistViewDlg(TComponent* Owner); + __fastcall ~THistViewDlg(); + + int m_TitleBar; + void __fastcall LoadHist(int b); + void __fastcall Add(Graphics::TBitmap *pBitmap); + void __fastcall GetViewPos(int &x, int &y, int &w, int &h){ + x = Left; + y = Top; + w = ClientWidth; + h = ClientHeight; + }; + void __fastcall SetViewPos(int x, int y, int w, int h){ + Left = x; + Top = y; + ClientWidth = w; + ClientHeight = h; + }; + void __fastcall UpdateBitmap(void); + int __fastcall IsPBox(TObject *Sender); + void __fastcall SetPopup(TPopupMenu *tp); + void __fastcall UpdateTitlebar(void); + void __fastcall UpdateTitle(LPCSTR pTime); +}; +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- +#endif diff --git a/History/History.bin b/History/History.bin new file mode 100644 index 0000000..70a731c Binary files /dev/null and b/History/History.bin differ diff --git a/InputWin.cpp b/InputWin.cpp new file mode 100644 index 0000000..92ccb28 --- /dev/null +++ b/InputWin.cpp @@ -0,0 +1,91 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "InputWin.h" +#include "MacroKey.h" +#include "ComLib.h" +//--------------------------------------------------------------------- +#pragma resource "*.dfm" +//--------------------------------------------------------------------- +__fastcall TInputWinDlg::TInputWinDlg(TComponent* AOwner) + : TForm(AOwner) +{ + FormStyle = ((TForm *)AOwner)->FormStyle; + Font->Name = ((TForm *)AOwner)->Font->Name; + Font->Charset = ((TForm *)AOwner)->Font->Charset; + if( MsgEng ){ + CancelBtn->Caption = "Cancel"; + BMac->Caption = "Macro"; + } +} +//--------------------------------------------------------------------- +int InputMB(LPCSTR pTitle, LPCSTR pMsg, AnsiString &as, BOOL fMac) +{ + TForm *fp; + if( Screen->ActiveForm != NULL ){ + fp = Screen->ActiveForm; + } + else if( Application->MainForm != NULL ){ + fp = Application->MainForm; + } + else { + fp = NULL; + } + + TInputWinDlg *pBox = new TInputWinDlg(fp); + pBox->BMac->Visible = fMac; + pBox->LMsg->Caption = pMsg; + pBox->Caption = pTitle ? pTitle : "MMSSTV"; + pBox->Edit->Text = as.c_str(); + int r = FALSE; + if( pBox->ShowModal() == IDOK ){ + as = pBox->Edit->Text.c_str(); + r = TRUE; + } + delete pBox; + return r; +} +//--------------------------------------------------------------------- +int InputMB(LPCSTR pTitle, LPCSTR pMsg, AnsiString &as) +{ + return InputMB(pTitle, pMsg, as, FALSE); +} +//--------------------------------------------------------------------- +void __fastcall TInputWinDlg::BMacClick(TObject *Sender) +{ + TMacroKeyDlg *pBox = new TMacroKeyDlg(this); + AnsiString as = Edit->Text; + if( pBox->Execute(as) > 0 ){ + HWND hWnd; + Edit->SetFocus(); + Edit->SelStart = strlen(AnsiString(Edit->Text).c_str()); //ja7ude 0428 + Edit->SelLength = 0; + hWnd = Edit->Handle; + for( LPCSTR p = as.c_str(); *p; p++ ){ + ::PostMessage(hWnd, WM_CHAR, *p, 0); + } + } + delete pBox; +} +//--------------------------------------------------------------------------- + diff --git a/InputWin.dfm b/InputWin.dfm new file mode 100644 index 0000000..fec9fcc Binary files /dev/null and b/InputWin.dfm differ diff --git a/InputWin.h b/InputWin.h new file mode 100644 index 0000000..4b6b3fa --- /dev/null +++ b/InputWin.h @@ -0,0 +1,52 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//---------------------------------------------------------------------------- +#ifndef InputWinH +#define InputWinH +//---------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//---------------------------------------------------------------------------- +class TInputWinDlg : public TForm +{ +__published: + TButton *OKBtn; + TButton *CancelBtn; + TEdit *Edit; + TLabel *LMsg; + TButton *BMac; + void __fastcall BMacClick(TObject *Sender); +private: +public: + virtual __fastcall TInputWinDlg(TComponent* AOwner); +}; +int InputMB(LPCSTR pTitle, LPCSTR pMsg, AnsiString &as, BOOL fMac); +int InputMB(LPCSTR pTitle, LPCSTR pMsg, AnsiString &as); +//---------------------------------------------------------------------------- +#endif + diff --git a/JASTA.txt b/JASTA.txt new file mode 100644 index 0000000..9001ded --- /dev/null +++ b/JASTA.txt @@ -0,0 +1,219 @@ +***** The 2010 JASTA SSTV Activity Contest Rules***** + + http://homepage3.nifty.com/jasta/english/index.html + +1.Contest periods +~~~~~~~~~~~~~~~~~~ + From August 1st 2010 (00:00 UTC) to August 31 (24:00 UTC) + +2.Bands +~~~~~~~~ + 3.5MHz and all upper bands.Use Only frequencies which are authorized by each individual station license. + +3.Categories of Entry +~~~~~~~~~~~~~~~~~~~~~ +a) "J" Category (Japanese only): Japanese domestic stations + +b) "S" Category(DX station): All stations operating outside of Japan. If a Japanese station operates outside Japan, this will be considered a DX contact. + +4.QSO Point +~~~~~~~~~~~~~ + Exchange the usual RSV plus a progressive QSO number starting with 001 which should be displayed in the picture exchange. Regardless of bands used, a station may only be worked once each UTC day . + If possible, during the exchange, include one's own face picture or some kind of illustration. QSO points authorized by bands. + + 3.5-28MHz ... 1 point + 50-430MHz ... 2 points + 1200MHz & upper ... 3 points + +5.Multipliers +~~~~~~~~~~~~ + Work all Japanese callsign districts(JA1-JA0 total 10) + DXCC Countries worked. Use DXCC List. Do not count Japan as a DXCC country + Number of days on the air. (10 days at the maximum even if a station operates more than 10 days) + +note:Prefix 7K-7N's are all JA1 area + +6.Scoring +~~~~~~~~~ + The final score is computed by multiplying the sum of the QSO points by the sum of multipliers as described in Paragraph 5. + +7.Contest awards +~~~~~~~~~~~~~~~~~ +1) A shield award will be sent to the 1st, the 2nd and the 3rd Score of each sections. But when the number of stations are less than 10, awards will be sent to the 1st place winner only. + +2) A special activity award will be sent to some of the stations who work over 10 days by lot. + (A JASTA T-shirts to 20 stations) + +3) New face certificate will be sent to the 1st of new comers. so please annotate your summary sheets "new Comer" on summary sheets. + +4) YL certificate will be sent to the 1st place YL stations. + +8.Logs +~~~~~~~ + Summary sheets and Log sheets should be arranged and mailed to the Contest manager. Email contest Summary sheet and logs to: JASTA Contest Secretary ja3wzt@mue.biglobe.ne.jp The log should be in a text file format. Email (text format) summary. E-Mail logs are acceptable now. Both Summary and logs should be forwarded to ja3wzt@mue.biglobe.ne.jp Assure you station callsign is in the e-mail subject line. + +* DX stations, "CQ WW" contest format is acceptable. Please enclose SASE and 1 IRC for reply. The log in a text file by Email is also acceptable now. + +9.Deadline for log entries +~~~~~~~~~~~~~~~~~~~~~~~~~ + Log entries with a stamp of a local POST office dated not later than September 30, 2010.(UTC) In case of Email, it must be received by the same above deadline.(UTC) + +10.Regulations +~~~~~~~~~~~~~~ +1) All Amateur Radio stations who has a license to transmit SSTV signal. + +2) Output power: Up to maximum power officially authorized by the operators class license . + +3) Both B/W and Color Picture QSO are accepted. + +4) A contest QSO should be one station to one station QSO. Round table style QSO’s between multiple stations will not be counted. + +5) Cross band QSO will not be counted as a contest QSO. + +6) All the QSO; JA to JA station, JA to DX station, DX to DX station will be counted and accepted as contest QSOs. + +11.JASTA Contest Results +~~~~~~~~~~~~~~~~~~~~~~~~~~ + The contest results will be sent to all stations who include a SASE. Aditionally announcement will be made on JASTA homepage and Japanese "CQ ham radio" magazine . + +12.The Contest Manager and Mailing Address +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +JASTA Contest Secretariat Email:ja3wzt@mue.biglobe.ne.jp +c/o YOSHIKAZU TANABE JA3WZT/1 +905-8,SHIMOTANIGANUKI,IRUMA,SAITAMA,358 JAPAN + +%%%Japanese ========================================== + JASTA主催SSTVアクティビティコンテスト (2010) + + http://homepage3.nifty.com/jasta/ + +期間 +~~~~~ + 国際標準時間の8月1日(日)0時 〜 8月31日(火)24時 + (日本時間 8月1日 9時 〜 9月1日 9時まで) + +参加資格 +~~~~~~~~~ + アマチュア無線の資格を持ち、SSTVの免許を受けている局。 + +運用周波数 +~~~~~~~~~~~~ + 3.5MHz帯以上で自局に免許された周波数帯 + (電波法および郵政省令に定められた周波数帯で運用)。 + +空中線電力 +~~~~~~~~~~~~ + 免許された電力の範囲内 + +コンテストナンバー +~~~~~~~~~~~~~~~~~~ + RSV+001から始まる連番。連番の桁が足りなくなったら桁を増やしてください。 + + 例えば信号レポートが595で、期間中20局目のQSOであれば、コンテストナンバーは「595020」。 + +ポイント +~~~~~~~ + 可能なかぎり、自分の顔が写っている画像(手描きのイラストも可)に自局のコールサインとコンテストナンバーを入れて送信する。完全なコンテストナンバー交換をもって下記に示すポイント点とする。画像の白黒、カラーは問わない。コンテストでのQSOは、相手局と1対1とし、ラウンドQSOは認めない。海外局との交信もポイントとして認める。なお、同一局との交信は周波数にかかわらず一日一回のみ有効。 + + 注意:同一日は、国際標準時間を基準として判定すること。時差の異なる海外局とのQSOにおいて、日本時間で日付が変っていても国際標準時間で同一であればポイントとして認めない。 + + (1)3.5〜28MHz帯 :1点 (7MHz帯は7.1MHz以上の周波数での交信を推奨します) + (2)50〜430MHz帯 :2点 + (3)1200MHz帯以上 :3点 + +マルチ +~~~~~~ + バンドに関係なく以下の項目をマルチとして計上できる。 + + (1)JAのエリア(10エリア) + (2)JAを除くDXCCエンティティ +    ・JDはDXCCのエンティティとしカウントする +    ・ DXCCエンティティ内のエリアはマルチとしてカウント出来ません。 + (3)運用日数 +    1日の運用は1マルチとし最大10マルチ(10日以上の運用をしても10とする)。 + +総得点 +~~~~~~~ +  (ポイントの和)×(マルチの和)。 + + 例えば、14MHz帯で15局、50MHz帯で8局、430MHz帯で7局、1200MHz帯で5局のコンテストナンバ交換した場合、交信ポイントは + 15×1+(8+7)×2+5×3=60となる。 + + さらにマルチがJAの10エリア、DXCC 5エンティティ、運用日数12日の場合、総得点は + 60×(10+5+10)=1500となる。 + +エントリー部門 +~~~~~~~~~~~~~~ + 国内部門(J部門):日本国内からのエントリー局 + 海外部門(S部門):海外からのエントリー局(日本の局が海外カントリーから運用した場合この部門となる。) + + 今回のコンテストで初めてサマリーを提出し初参加か否かの区別およびOM、YL(XYL)の区別も記入願います。 + +賞 +~~~ + 各部門、上位3位までに楯を送る。各部門参加局が10局に満たない場合は、1位にのみ楯を送る。 + またニューフェース賞を、今回のコンテストが初参加の申告があった局の中から、得点が1位の局に送る。 + さらにYL(XYL)のエントリがあった場合、その中で得点が1位の局にベストYL(XYL)賞を送る。 + 運用日数が10日以上の局にはアクティビティ賞として、抽選で20名にJASTA特性の + + T−シャツ(提出するサマリシートにJASTA特性T-シャツのサイズを記入願います。なお記入のない場合はLサイズとさせていただきます)を送る。 + なお、同一オペレータが、DXペディション等、国外で運用した場合は、国内コールでの運用日数と国外コールでの運用日数を合算できる。たとえば、国内運用7日、DXペディ運用4日とすれば、合計11日となり、アクテイブ賞対象となる。 + + +ログの提出 +~~~~~~~~~~~ + ログは、以下の2方法のどちらかで提出してください。両方での提出は、混乱の原因になりますので絶対にしないようにお願いします。 + + (1)郵送の場合 + JARLのコンテストサマリーまたは、JASTAが定めた書式のフォーマットで記入したサマリー、およびマルチに計上する 交信のログを下記の提出先にSASE(定形の封筒に80円切手をはり、宛先を明記した封筒を同封する)にて郵送する + (結果の送付を必要としない場合は、SASEにする必要はない。) + + (2)e−mailで送付する場合 + JASATが定めた書式のフォーマットで記入したサマリーおよびマルチに計上する交信のログを、下記のアドレスにe−mailで送付する。 + e−mailで受付けた場合は、メールを受領した事を示す返信を事務局より送信します。2週間たっても受領確認のメールが来ない場合は再送信してください。 + + コンテストルール違反、サマリシート記入不備の場合は書類不備をして扱います。 + サマリーシートの参加部門欄に、エントリー部門(J、またはS)、今回のコンテストが初参加か否かの区分、およびOM,YL(XYL)の区別を明記のこと。 + + JARLのコンテストサマリーに記入する場合、JAのエリア、DXCCカントリーのマルチは合計して、バンドの欄に「エリア+DXCC]と追記しマルチプライヤーの欄に記入して下さい。また運用日数のマルチについては、バンドの欄に「運用日数」と追記し、マルチプライヤーの欄にコンテストで運用した日数を記入して下さい。 + + JASTAが定める書式については、JASTA事務局のホームページ(http://homepage3.nifty.com/jasta/)で準備します。ダウンロードしてそれに記入してください。 + +ログの締切 +~~~~~~~~~~~ + 2010年9月30日消印またはタイムスタンプ有効。これ以降は無効。 + +ログの提出先 +~~~~~~~~~~~~~~ + (1)郵送の場合 +    〒358−0041 埼玉県入間市下谷ケ貫905−8 +    田辺 義和方 日本アマチュアSSTV協会 コンテスト事務局 + + (2)e−mailで送付する場合 +    ja3wzt@mue.biglobe.ne.jp + +注意点 +~~~~~~~ + ・相手局を呼び出すときは、先に音声で呼び出し、応答を確認してから画像を送信するようにしてください。 +  いきなり画像で呼び出すようなことは避けてください。 + + ・CQを送信する際は十分にワッチし、音声で周波数が使われていない事を確認してから送信してください。 + ・同一局との交信はHF、VHFを問わず1日1回のポイントしか認めない。クロスバンドによる交信は認めない。 + ・同一日は国際標準時間で定義する。 + ・同時に2波以上の電波の発射によるものはポイントとしない。 + ・ラウンドQSOを認めないので、実質少ないチャネルしか使用できない周波数帯では、長時間周波数を占有しないように運用して下さい。 + ・バンドプランを遵守し、各局の自主的な判断で多くの局にチャンスが得られるように運用を心掛けてください。 + ・コンテスト中、「自分の自画像」を送らない局との交信も得点として認めますが、可能な限り自画像を入れた画像で交信してください。 + ・参加者のみなさんの良識で、サマリシートの提出を、お願いします。 + ・サマリシートの内容が、不明な場合等にはログの提出を求めることがあります。 + +結果発表 +~~~~~~~~~ + ログをSASEにて送付された局には郵送で通知。 + その他、JASTA事務局のホームページ、CQ誌等に結果を掲載。 + +その他 +~~~~~~~ + ・送信画像にJASATのロゴマークを貼り付けて使用できるよう、JASTA事務局のホームページ上にロゴマークを置きますので、ダウンロードし積極的にご活用ください。 + ・特定局だけとのナンバー交換を避けて多くの局との交信を、また1日でも多くの運用を楽しんでください。 + +上記の通りコンテストを実施いたしますので、奮ってご参加下さい。 + JASTAコンテスト事務局 diff --git a/JASTA/ARRL.DX b/JASTA/ARRL.DX new file mode 100644 index 0000000..4bbc512 --- /dev/null +++ b/JASTA/ARRL.DX @@ -0,0 +1,423 @@ +! ARRL DXCC COUNTRIES LIST For MMLOG +! +AP ;AP-AS,6P-6S ;PAKISTAN ;AS ;E +!A1 ;A1 ;ABU AIL ;AS +A2 ;A2,8O ;BOTSWANA ;AF ;B +A3 ;A3 ;TONGA ;OC ;N +A4 ;A4 ;OMAN ;AS ;D +A5 ;A5 ;BHUTAN ;AS ;F +A6 ;A6 ;UNITED ARAB ;AS ;D +A7 ;A7 ;QATAR ;AS ;C +A9 ;A9 ;BAHRAIN ;AS ;C +BV9P ;BV9P\,BQ9P\ ;PRATAS IS. ;AS ;H +BV ;BV,BX ;TAIWAN ;AS ;H +BS7 ;BS7H\ ;SCARBOROUGH REEF ;AS ;H +BY ;BA-BZ,3H-3U,B1-B9 ;CHINA ;AS ;H +CE0X ;CE0X,XQ0X-XR0X,CE0AA ;SAN FELIX IS. ;SA ;R +CE0Z ;CE0Z,CE0I,CE0OGZ,XQ0Z-XR0Z,XQ0I-XR0I,CE0/JA7XYE; FERNANDEZ ;SA ;R +CE0 ;CE0,XQ0-XR0 ;EASTER IS. ;SA ;T +CE ;CA-CE,XQ-XR,3G ;CHILE ;SA ;Q +CM ;CL-CM,CO,T4 ;CUBA ;NA ;R +CN ;CN,5C-5G ;MOROCCO ;AF ;Z +CP ;CP ;BOLIVIA ;SA ;Q +CT3 ;CS3,CT3,CR9 ;MADEIRAI IS.(PORTUGAL) ;AF ;Z +CU ;CU ;AZORES IS.(PORTUGAL) ;EU ;Z +CT ;CQ-CU ;PORTUGAL ;EU ;Z +CY9 ;CY9,CY0SPI ;ST PAUL IS. ;NA ;Q +CY0 ;CY0 ;SABLE IS. ;NA ;Q +CX ;CV-CX ;URUGUAY ;SA ;P +C2 ;C2 ;NAURU ;OC ;M +C3 ;C3 ;ANDORRA ;EU ;A +C5 ;C5 ;THE GAMBIA ;AF ;Z +C6 ;C6 ;BAHAMA IS. ;NA ;R +C8 ;C8-C9 ;MOZAMBIQUE ;AF ;B +DL ;DA-DR,Y2-Y9 ;GERMANY ;EU ;A +DU ;DU-DZ,4D-4I ;PHILIPPINES ;OC ;H +D2 ;D2-D3 ;ANGOLA ;AF ;A +D4 ;D4 ;CAPE VERDE ;AF ;A +D6 ;D6 ;COMOROS ;AF ;C +EA6 ;EA6-EH6,AM6-AO6 ;BALEARIC ;EU ;A +EA8 ;EA8-EH8,AM8-AO8 ;CANARY ;AF ;A +EA9 ;EA9-EH9,AM9-AO9 ;CEUTA & MELILLA(SPAIN) ;AF ;A +EA ;EA-EH,AM-AO ;SPAIN ;EU ;A +EI ;EI-EJ ;IRELAND ;EU ;Z +EK ;EK ;ARMENIA (ex UG) ;AS ;D +EL ;EL,5L-5M,A8,D5,6Z ;LIBERIA ;AF ;Z +EP ;EP-EQ,HN,9B-9D ;IRAN ;AS ;c +ER ;ER ;MOLDOVA (ex UO) ;EU ;C +ES ;ES ;ESTONIA ;EU ;C +ET ;ET,9E-9F ;ETHIOPIA ;AF ;C +EU ;EU-EW ;BELARUS (ex UC) ;EU ;C +EX ;EX ;KYRGYZSTAN (ex UM) ;AS ;F +EY ;EY ;TAJIKISTAN (ex UJ) ;AS ;F +EZ ;EZ ;TURKMENISTAN (ex UH) ;AS ;F +E4 ;E4 ;PALESTINE ;AS ;B +E3 ;E3 ;ERITREA ;AF ;C +FG ;FG ;GUADELOUPE ;NA ;Q +FH ;FH ;MAYOTTE ;AF ;C +FJ ;FJ,FS ;SAINT MARTIN ;NA ;Q +FK ;FK,TX8 ;NEW CALEDONIA ;OC ;L +FM ;FM ;MARTINIQUE ;NA ;Q +FO/C ;FO0X,FO0AAA ;CLIPPERTON IS. ;NA ;T +FO ;FO ;FRENCH POLYNESIA ;OC ;W +FO/A ;FO ;AUSTRAL IS ;OC ;W +FO/M ;FO ;MARQUESAS IS ;OC ;W +FP ;FP ;ST.PIERRE & MIQUELON IS. ;NA ;Q +FR/J ;FR*/J,FR*/E ;JUAN DE NOVA & EUROPA IS. ;AF ;C +FR/G ;FR*/G ;GLORIOSO IS. ;AF ;C +FR/T ;FR*/T ;TROMELIN ;AF ;C +FR ; ;REUNION IS. ;AF ;C +FR/? ;FR ;REUNION IS. /GLORIOSO IS. /JUAN DE NOVA & EUROPA ;AF ;C +FT5W ;FT8W,FT2W,FT4W,FT5W,FT0W ;CROZET IS. ;AF ;C +FT5X ;FT8X,FT2X,FT4X,FT5X,FT0X ;KERGUELEN IS. ;AF ;E +FT5Z ;FT8Z,FT2Z,FT4Z,FT5Z,FT0Z ;AMSTERDAM & ST PAUL IS. ;AF ;E +FW ;FW ;WALLIS & FUTUNA IS. ;OC ;M +FY ;FY ;FRENCH GUIANA ;SA ;P +F ;F,HW-HY,TM,TO-TQ ;FRANCE ;EU ;A +GD ;GD,GT,MA6-MB6,2A6,MD ;ISLE OF MAN ;EU ;Z +GI ;GI,GN,MA5-MB5,2A5,MI ;NORTHERN IRELAND ;EU ;Z +GJ ;GH,GJ,MA7-MB7,2A7,MJ ;JERSEY ;EU ;Z +GM ;GM,GS,MA3-MB3,2A3,MM ;SCOTLAND ;EU ;Z +GU ;GU,GP,MA8-MB8,2A8,MG ;GUERNSEY ;EU ;Z +GW ;GW,GC,MA4-MB4,2A4,MW ;WALES,U.K ;EU ;Z +G ;G,2,M ;ENGLAND(U.K) ;EU ;Z +HA ;HA,HG ;HUNGARY ;EU ;A +HB0 ;HB0,HE0 ;LIECHTENSTEIN ;EU ;A +HB ;HB,HE,4U1VIC ;SWITZERLAND ;EU ;A +HC8 ;HC8-HD8 ;GALAPAGOS IS.(ECUADOR) ;SA ;R +HC ;HC,HD ;ECUADOR ;SA ;R +HH ;HH,4V ;HAITI ;NA ;R +HI ;HI ;DOMINICAN REPUBLIC ;NA ;R +HK0/M ;HK0M,5J0M,HK0TU ;MALPELO IS. ;NA ;R +HK0/A ;HK0,5J0 ;SAN ANDRES ;NA ;R +HK ;HJ-HK,5J-5K ;COLOMBIA ;SA ;R +HL ;HL,DS-DT,6K-6N,D7-D9,KL9 ;REPUBLIC OF KOREA (SOUTH KOREA) ;AS ;I +HP ;HO-HP,3E-3F,H3,H8-H9 ;PANAMA ;NA ;R +HR ;HQ-HR ;HONDURAS ;NA ;S +HS ;HS,E2 ;THAILAND ;AS ;G +HV ;HV ;VATICAN ;EU ;A +HZ ;HZ,7Z-8Z ;SAUDI ARABIA ;AS ;C +H40 ;H40 ;TEMOTU IS ;OC ;L +H4 ;H4 ;SOLOMON IS. ;OC ;L +IS ;IS,IM0,IU0 ;SARDINIA ;EU ;A +I ;I ;ITALY ;EU ;A +JD1/M ;JD1YAA,JD1BIY ;MINAMI TORISHIMA ;OC ;I +JD1 ;JD1BIC ;OGASAWARA ;AS ;I +JD1/? ;JD1 ;OGASAWARA, /MINAMI TORISHIMA ;I +JA ;JA-JS,7J-7N,8J-8N ;JAPAN ;AS ;I +JT ;JT-JV ;MONGOLIA ;AS ;H +JW ;JW ;SVALBARD IS. ;EU ;A +JX ;JX ;JA MAYEN IS. ;EU ;Z +JY ;JY ;JORDAN ;AS ;B +J2 ;J2 ;DJIBOUTI ;AF ;C +J3 ;J3 ;GRENADA ;NA ;Q +J5 ;J5 ;GUINEA-BISSAU ;AF ;Z +J6 ;J6 ;ST LUCIA ;NA ;Q +J7 ;J7 ;DOMINICA ;NA ;Q +J8 ;J8 ;ST VINCENT & DEPENDENCIES ;NA ;Q +KC4 ;8J1R?\,R1A,FB8Y,CE9A,ZL5,Y88,Y90ANT,ZS8BBB,ZS8AAA,KC4AAC,KC4USV,Y73SOP,KC4AAA,KC4USB,KC4USX,3G9A,3Y9WT,8J1RY,AT0A,IA0PS,OR4,XS7ANT,Y83ANT,ZL0AIC,ZS7ANT,VK0DS,KC4AAE ;ANTARCTICA ;AN +KC6 ;T8,KC6??\ ;(WESTERN CAROLINE IS.) BELAU ;OC ;I +KG4 ;KG4??\ ;GUANTANAMO BAY ;NA ;R +KH0 ;AH0,KH0,NH0,WH0 ;MARIANA IS. ;OC ;K +KH1 ;AH1,KH1,NH1,WH1 ;BAKER & HOWLAND IS. ;OC ;X +KH2 ;AH2,KH2,NH2,WH2 ;GUAM ;OC ;K +KH3 ;AH3,KH3,NH3,WH3 ;JOHNSTON IS. ;OC ;X +KH4 ;AH4,KH4,NH4,WH4 ;MIDWAY IS. ;OC ;M +KH5K ;AH5K,KH5K,NH5K,WH5K ;KINGMAN REEF ;OC ;W +KH5 ;AH5,KH5,NH5,WH5 ;PALMYRA & JARVIS ;OC ;W +KH7K ;AH7K,KH7K,NH7K,WH7K ;KURE IS. ;OC ;M +KH6 ;AH6-AH7,KH6-KH7,NH6-NH7,WH6-WH7 ;HAWAIIAN IS. ;OC ;W +KH8 ;AH8,KH8,NH8,WH8 ;AMERICAN SAMOA ;OC ;W +KH9 ;AH9,KH9,NH9,WH9 ;WAKE IS. ;OC ;L +KL7 ;AL,KL0-KL8,NL,WL ;ALASKA ;NA ;W +KP1 ;KP1,NP1,WP1 ;NAVASSA IS. ;NA ;Q +KP2 ;KP2,NP2,WP2 ;AM.VIRGIN IS. ;NA ;Q +KP4 ;KP3-KP4,NP3-NP4,WP3-WP4 ;PUERTO RICO ;NA ;Q +KP5 ;KP5,NP5,WP5 ;DESECHEO IS. ;NA ;Q +W ;AA6-AK6,K6,N6,W6,K?6,N?6,W?6 ;U.S.A. ;NA ;U +W ;AA7-AK7,K7,N7,W7,K?7,N?7,W?7 ;U.S.A. ;NA ;T +W ;AA0-AK0,K0,N0,W0,K?0,N?0,W?0,AA5-AK5,K5,N5,W5,K?5,N?5,W?5,AA9-AK9,K9,N9,W9,K?9,N?9,W?9 ;U.S.A. ;NA ;S +W ;AA-AL,K,N,W,4U1WB ;U.S.A. ;NA ;R +LA ;LA-LN ;NORWAY ;EU ;A +LU ;LO-LW,AY-AZ,L2-L9 ;ARGENTINA ;SA ;P +LX ;LX ;LUXEMBOURG ;EU ;A +LY ;LY ;LITHUANIA ;EU ;C +LZ ;LZ ;BULGARIA ;EU ;B +OA ;OA-OC,4T ;PERU ;SA ;R +OD ;OD ;LEBANON ;AS ;B +OE ;OE ;AUSTRIA ;EU ;A +OH0 ;OH0,OF0 ;ALAND IS. ;EU ;B +OJ0 ;OJ0 ;MARKET REEF ;EU ;B +OH ;OF-OJ ;FINLAND ;EU ;B +OK ;OK-OL ;CZECH REPUBLIC ;EU ;A +OM ;OM ;SLOVAK REPUBLIC ;EU ;A +ON ;ON-OT ;BELGIUM ;EU ;A +OX ;OX ;GREENLAND ;NA ;Q +OY ;OY ;FAROES ;EU ;Z +OZ ;OU-OZ,XP,5P-5Q ;DENMARK ;EU ;A +PJ8 ;PJ5-PJ8,PJ0J,PJ1F ;SINT MAARTEN ;NA ;Q +PJ9 ;PJ ;NETHERLANDS ANTILLES ;SA ;Q +PA ;PA-PI ;NETHERLANDS ;EU ;A +PY0/S ;PP0S-PY0S,ZV0S-ZZ0S,PY0DX,PT0MI,PS0WH-PT0WH,PY0RO,PW0PP,PP0ZS-PY0ZS ;ST PETER ;SA ;P +PY0/T ;PP0T-PY0T,ZV0T-ZZ0T ;TRINDADE ;SA ;P +PY0 ;PP0-PY0,ZV0-ZZ0 ;FERNANDO DE NORONHA ;SA ;P +PY ;PP-PY,ZV-ZZ ;BRAZIL ;SA ;P +PZ ;PZ ;SURINAM ;SA ;Q +P2 ;P2 ;PAPUA NEW GUINEA ;OC ;K +P4 ;P4 ;ARUBA ;SA ;Q +P5 ;P5-P9,HM ;NORTH KOREA (DPRK) ;AS ;I +R1/MVI ;4J1FS,R1M,*/MVI,MVI/* ;MALYJ VYSOTSKIJ IS. (ex 4J1) ;EU ;C +R1/FJL ;R1F,*/FJL,FJL/* ;FRANZ JOSEPH LAND (ex UA1/4K2) ;EU ;C +SM ;SA-SM,7S-8S ;SWEDEN ;EU ;A +SP ;SN-SR,HF,3Z ;POLAND ;EU ;A +!ST0 ;ST0,6T0-6U0 ;SOUTHEN SUDAN ;AF ;B +ST ;ST,6T-6U ;SUDAN ;AF ;B +SU ;SU,6A-6B ;EGYPT ;AF ;B +SV/A ;SY1MA,SV*/A,*/SV/A ;MT ATHOS ;EU ;B +SV5 ;SV5-SZ5,J45 ;DODECANESE IS. ;EU ;B +SV9 ;SV9-SZ9,J49 ;CRETE ;EU ;B +SV ;SV-SZ,J4 ;GREECE ;EU ;B +S2 ;S2-S3 ;BANGLADESH ;AS ;F +S5 ;S5 ;SLOVENIA (ex YU3) ;EU ;A +S7 ;S7 ;SEYCHELLES ;AF ;C +S9 ;S9 ;SAO TOME & PRINCIPE ;AF ;B +S0 ;S0 ;WESTERN SAHARA ;AF ;Z +TA ;TA1-TC1,YM1 ;TURKEY (EU) ;EU ;C +TA ;TA2-TA9,TB2-TB9,TC2-TC9,YM2-YM9;TURKEY (AS) ;AS ;C +TF ;TF ;ICELAND ;EU ;Z +TG ;TG,TD ;GUATEMALA ;NA ;S +TI9 ;TI9,TE9 ;COCOS IS. ;NA ;S +TI ;TI,TE ;COSTA RICA ;NA ;S +TJ ;TJ ;CAMEROON ;AF ;A +TK ;TK ;CORSICA ;EU ;A +TL ;TL ;CENTRAL AFRICAN REP ;AF ;A +TN ;TN ;CONGO ;AF ;A +TR ;TR ;GABON ;AF ;A +TT ;TT ;CHAD ;AF ;A +TU ;TU ;IVORY COAST ;AF ;Z +TY ;TY ;BENIN ;AF ;Z +TX0 ;TX0 ;CHESTERFIELD IS. ;OC ;L +TZ ;TZ ;MALI ;AF ;Z +T2 ;T2 ;TUVALU ;OC ;M +T30 ;T30 ;WEST KIRIBATI(GILBERT IS.) ;OC ;X +T31 ;T31 ;CENTRAL KIRIBATI(BRITISH PHOENIX IS.) ;OC ;X +T32 ;T32 ;EAST KIRIBATI(LINE IS.) ;OC ;W +T33 ;T33 ;BANABA IS(OCEAN IS.) ;OC ;M +T5 ;T5,6O ;SOMALIA ;AF ;C +T7 ;T7 ;SAN MARINO ;EU ;A +T9 ;T9 ;BOSNIA-HERZEGOVINA (ex YU4,4N4) ;EU ;A +UJ ;UJ-UM ;UZBEKISTAN (ex UI) ;AS ;E +UN ;UN-UQ ;KAZAKHSTAN (ex UL) ;AS ;E +UR ;UR-UZ,EM-EO ;UKRAINE (ex UB) ;EU ;B +UA2 ;U?2,R?2 ;KALININGRAD ;EU ;C +UA/EU ;U?1-U?6,R?1-R?6,U1-U6,R1-R6 ;EUROPEAN RUSSIA ;EU ;C +UA/AS ;U?9,R?9,U9,R9 ;ASIATIC RUSSIA ;AS ;E +UA/AS ;U?8,U?0,R?8,R?0,U8,U0,R8,R0 ;ASIATIC RUSSIA ;AS ;I +VE ;VA7-VG7,VX7,CF7-CK7,XJ7-XO7,VY1 ;CANADA ;NA ;U +VE ;VA6-VG6,VX6,CF6-CK6,XJ6-XO6,VA5-VG5,VX5,CF5-CK5,XJ5-XO5 ;CANADA ;NA ;T +VE ;VA4-VG4,VX4,CF4-CK4,XJ4-XO4 ;CANADA ;NA ;S +VE ;VA3-VG3,VX3,CF3-CK3,XJ3-XO3,VA2-VG2,VX2,CF2-CK2,XJ2-XO2 ;CANADA ;NA ;R +VE ;VA-VG,VO,VX-VY,CF-CK,CY-CZ,XJ-XO ;CANADA ;NA ;Q +VK9L ;VK9L,AX9L ;LORD HOWE IS. ;OC ;L +VK9M ;VK9JW,VK9ZR,VK9MR,VK9ZM ;MELLISH REEF ;OC ;K +VK9N ;VK9N,AX9N ;NORFOLK IS. ;OC ;L +VK9W ;VK9Z,AX9Z,VK9TR ;WILLIS IS. ;OC ;K +VK9X ;VK9X,AX9X ;CHRISTMAS IS. ;OC ;H +VK9C ;VK9Y,AX9Y,VK9WB,VK9EW ;COCOS-KEELING IS. ;OC ;H +VK9? ;VK9 ;COCOS-KEELING IS., /LORD HOWE IS., /MELLISH IS., /NORFOLK IS., /WILLIS IS., /CHRISTMAS IS. ;OC ;K +VK0/M ;VK0AE,VK0GC,VK0WH ;MACQUARIE ;OC ;K +VK0/H ;VK0HM,VK0HI,VK0CW,VK0DA,VK0IR ;HEARD IS. ;AF ;E +VK0/? ;VK0 ;HEARD IS., /MACQUARIE IS. +VK ;VH-VN,VZ,AX ;AUSTRALIA ;OC ;K +VP2E ;VP2E,VP25E ;ANGUILLA ;NA ;Q +VP2M ;VP2M ;MONTSERRAT ;NA ;Q +VP2V ;VP2V ;BRITISH VIRGIN IS. ;NA ;Q +VP5 ;VP5 ;TURKS & CAICOS IS. ;NA ;R +VP8/G ;VP8BUB,VP8CDJ,VP8SGP ;SOUTH GEORGIA ;SA ;P +VP8/O ;LU1Z,VP8BXK ;SOUTH ORKNEY ;SA ;P +VP8/S ;LU2Z,4K1F,CX0XY,HF0POL,LU5ZI,ZX0ECF,VP8CQS,VP8CQR,LZ0A ;SOUTH SHETLAND ;SA ;P +VP8/SW ;VP8SSI ;SOUTH SANDWICH IS. ;SA ;P +VP8 ;VP8CSA ;FALKLAND IS. ;SA ;Q +VP8/? ;VP8,LU?Z ;FALKLAND IS., /SOUTH GEORGIA IS., /SOUTH ORKNEY IS., /SOUTH SANDWICH IS., /SOUTH SHETLAND IS. ;SA ;P +VP9 ;VP9 ;BERMUDA IS. ;NA +VQ9 ;VQ9 ;CHAGOS IS. ;AF ;E +VR6 ;VR6,VP6 ;PITCAIRN IS. ;OC ;U +VR2 ;VS6,VS96,VS97,VR97,VR98,VR2 ;HONG KONG ;AS ;H +VU/A ;VU2JPS ;ANDAMAN & NICOBAR IS. ;AS ;e +VU/L ; ;LACCADIVE IS. ;AS ;e +VU ; ;INDIA ;AS ;e +VU/? ;VT-VW,AT-AW,8T-8Y ;INDIA, /ANDAMAN & NICOBAR IS., /LACCADIVE IS. ;AS ;e +V2 ;V2 ;ANTIGUA & BARBUDA ;NA ;Q +V3 ;V3 ;BELIZE ;NA ;S +V4 ;V4 ;ST KITTS & NEVIS ;NA ;Q +V5 ;V5 ;NAMIBIA ;AF ;B +V6 ;V6 ;MICRONESIA(E CAROLINE IS.) ;OC ;L +V7 ;V7 ;MARSHALL IS. ;OC ;M +V8 ;V8 ;BRUNEI ;OC ;H +XF4 ;XA4-XI4,4A4-4C4,6D4-6J4 ;REVILLA GIGEDO ;NA ;T +XE ;XA-XI,4A-4C,6D-6J ;MEXICO ;NA ;S +XT ;XT ;BURKINA-FASO ;AF ;Z +XU ;XU ;CAMBODIA ;AS ;G +XV ;XV,3W ;VIETNAM ;AS ;G +XW ;XW ;LAOS ;AS ;G +XX9 ;XX9 ;MACAO ;AS ;H +XZ ;XY-XZ,1Z ;MYANMAR ;AS ;f +YA ;YA,T6 ;AFGHANISTAN ;AS ;d +YB ;YB-YH,JZ,PK-PO,7A-7I,8A-8I ;INDONESIA ;OC ;H +YI ;YI ;IRAQ ;AS ;C +YJ ;YJ ;VANUATU ;OC ;L +YK ;YK,6C ;SYRIA ;AS ;B +YL ;YL,UQ ;LATVIA ;EU ;C +YN ;YN,HT,H6-H7 ;NICARAGUA ;NA ;S +YO ;YO-YR ;ROMANIA ;EU ;B +YS ;YS,HU ;EL SALVADOR ;NA ;S +YU ;YT,YU,YZ,4N-4O ;YUGOSLAVIA ;EU ;A +YV0 ;YV0-YY0,4M0 ;AVES IS. ;NA ;Q +YV ;YV-YY,4M ;VENEZUELA ;SA ;Q +ZA ;ZA ;ALBANIA ;EU ;A +ZB ;ZB ;GIBRALTAR ;EU ;A +ZC ;ZC ;UK SOVEREIGN BASES ON CYPRUS ;AS ;B +ZD7 ;ZD7 ;ST HELENA ;AF ;Z +ZD8 ;ZD8 ;ASCENSION IS. ;AF ;Z +ZD9 ;ZD9 ;TRISTAN DE CUNHA & GOUGH IS. ;AF ;Z +ZF ;ZF ;CAYMAN IS. ;NA ;R +ZK1/N ;ZK1CQ,ZK1RS,ZK1BY,ZK1WL,ZK1XP,ZK1XY ;NORTH COOK IS. ;OC ;W +ZK1/S ; ;SOUTH COOK IS ;OC ;W +ZK1/? ;ZK1 ;NORTH COOK IS., /SOUTH COOK IS. ;OC ;W +ZK2 ;ZK2 ;NIUE ;OC ;X +ZK3 ;ZK3 ;TOKELAU IS. ;OC ;X +ZL7 ;ZL7-ZM7 ;CHATHAM IS. ;OC ;M +ZL8 ;ZL8-ZM8 ;KERMADEC IS. ;OC ;M +ZL9 ;ZL9-ZM9 ;AUKLAND & CAMPBELL IS. ;OC ;M +ZL ;ZL-ZM ;NEW ZEALAND ;OC ;M +ZP ;ZP ;PARAGUAY ;SA ;Q +ZS8 ;ZS8MI,ZT8M-ZU8M,ZR8M,ZS8IR ;PRINCE EDWARD & MARION IS. ;AF ;B +!ZS9 ;ZS9 ;WALVIS BAY ;AF +ZS ;ZR-ZU ;REP OF SOUTH AFRICA ;AF ;B +Z2 ;Z2 ;ZIMBABWE ;AF ;B +Z3 ;Z3 ;MACEDONIA (ex YU5,4N5) ;EU ;A +1A0 ;1A0 ;SOVEREIGN MILLITARY ORDER OF MALTA ;EU ;A +1S ;1S,9M0,9M6OO ;SPRATLY IS. ;AS ;H +3A ;3A ;MONACO ;EU ;A +3B6 ;3B6-3B7 ;AGALEGA & ST BRANDON IS. ;AF ;C +3B8 ;3B8 ;MAURITIUS IS. ;AF ;C +3B9 ;3B9 ;RODRIGUEZ IS. ;AF ;C +3C0 ;3C0 ;ANNOBON IS. ;AF ;A +3C ;3C ;EQUATORIAL GUINEA ;AF ;A +3D2/C ;3D2CR,3D2WV,3D2HL,3D2VT,3D2AM,3D2CU,3D2CT,3D2*/C ;CONWAY REEF ;OC ;M +3D2/R ;3D2XX,3D2RJ,3D2XV,3D2XR,3D2AP,3D2RO,3D2OQ,3D2RW,3D2*/R ;ROTUMA IS ;OC ;M +3D2 ;3D2 ;FIJI IS. ;OC ;M +3DA ;3DA ;SWAZILAND ;AF ;B +3V ;3V,TS ;TUNISIA ;AF ;A +3X ;3X ;GUINEA ;AF ;Z +3Y ;3Y1VC,3Y5X ;BOUVET ;AF ;Z +3Y/P ;3Y1EE,3Y2GV ;PETER 1 IS. ;AN ;S +3Y/? ;3Y ;BOUVET, /PETER 1 IS. ;AF,AN +4J ;4J-4K ;AZERBAIJAN (ex UD) ;AS ;F +4L ;4L ;GEORGIA (ex UF) ;AS ;F +4S ;4P-4S ;SRI LANKA ;AS ;e +4U1/U ;4U1U,4U43-4U44,4U45UN ;UN HEADQUATERS NEW YORK ;NA ;R +4U1/I ;4U?ITU ;ITU GENEVA ;EU ;A +4U1/? ;4U ;UN HEADQUATERS NEW YORK, /ITU GENEVA, etc +!4W ;4W ;YEMEN :AS +4W ;4W ;EAST TIMOR ;OC ;H +4X ;4X,4Z ;ISRAEL ;AS ;B +5A ;5A ;LIBYA ;AF ;B +5B ;5B,C4,H2,P3 ;CYPRUS ;AS ;B +5H ;5H-5I ;TANZANIA ;AF ;C +5N ;5N-5O ;NIGERIA ;AF ;A +5R ;5R-5S,6X ;MADAGASCAR ;AF ;C +5T ;5T ;MAURITANIA ;AF ;Z +5U ;5U ;NIGER ;AF ;A +5V ;5V ;TOGO ;AF ;Z +5W ;5W ;WESTERN SAMOA ;OC ;X +5X ;5X ;UGANDA ;AF ;C +5Y ;5Y-5Z ;KENYA ;AF ;C +6W ;6V-6W ;SENEGAL ;AF ;Z +6Y ;6Y ;JAMAICA ;NA ;R +7O ;7O ;REP OF YEMEN ;AS ;C +7P ;7P ;LESOTHO ;AF ;B +7Q ;7Q ;MALAWI ;AF ;B +7X ;7T-7Y ;ALGERIA ;AF ;Z +8P ;8P ;BARBADOS ;NA ;Q +8Q ;8Q ;MALDIVES ;AS,AF ;E +8R ;8R ;GUYANA ;SA ;P +9A ;9A ;CROATIA (ex YU2) ;EU ;A +9G ;9G ;GHANA ;AF ;Z +9H ;9H ;MALTA ;EU ;A +9J ;9I-9J ;ZAMBIA ;AF ;B +9K ;9K ;KUWAIT ;AS ;C +9L ;9L ;SIERRA LEONE ;AF ;Z +9M2 ;9M2,9M4,9W2,9W4 ;WEST MALAYSIA ;AS ;H +9M6 ;9M6,9M8,9W6,9W8 ;EAST MALAYSIA ;OC ;H +9N ;9N ;NEPAL ;AS ;e +9Q ;9O-9T ;ZAIRE ;AF ;B +9U ;9U ;BURUNDI ;AF ;B +9V ;9V,S6 ;SINGAPORE ;AS ;H +9X ;9X ;RWANDA ;AF ;B +9Y ;9Y-9Z ;TRINIDAD & TOBAGO ;SA ;Q +$END +!---------------------------------------------------------------------------- +!ファイルの形式 +! カントリ名 ; カントリ識別子 ; QTH ; 大陸名 ; タイムゾーン +! +!● 行の先頭のはコメントコード,<$>は終了コード +!● カントリ名は8文字以内。 +!● カントリ識別子は<,>で区切って複数個記述可。 +!● QTHは任意の文字列 +!● 大陸名は NA, SA, EU, OC, AF, AS, AN +!● タイムゾーンはA〜Z(Jを除く)で記述する。小文字は+30分 +!● コードは任意の位置にあっても良い +!● 1行255文字以内。 +!● 定義する行(コメント行を除く)は最大512行まで +!● このファイルをネット等で流通させる場合は、最後の変更履歴に追加記載する +! ことをお勧めします。 +! +!カントリ識別子 +! 1.プリフィックス(コールサイン)の羅列 +! 9M2,9M4,9W2,9W4 +! JD1YAA,JD1BIY +! ※ コールサインが短い場合は終端記号(\)を付加したほうが良い +! BV9P → BV9PAも含まれる +! BV9P\ → BV9Pのみ +! +! 2.範囲の指定 +! DA-DR,Y2-Y9 +! EA6-EH6,AM6-AO6 +! 範囲は同じ位置の1ヶ所のみを昇順で記述 +! JA-JS EA6-EH6 OK +! JS-JA(降順) EA6-EH7(2ヶ所) NG +! +! 3.ワイルドカード(範囲の複合可) +! U?1-U?6,R?1-R?6 +! SV*/A,*/SV/A +! =すべての文字, <*>=すべての文字列 +! +! 4.最初に定義したほうが優先される +! JD1/M ;JD1YAA ; MINAMI TORISHIMA ;OC +! JA ;JA-JS ; JAPAN ;AS +! 上記の例ではJD1YAAはJA-JSにも含まれるが、その前にJD1/Mの定義 +! があるのでそちらが優先される +! +!<<<変更履歴>>> +! Jan 15, 1996 - BV9P追加 JE3HHT +! Feb 15, 1996 - BS7H追加 JE3HHT +! Aug. 4, 1998 - VR98追加 JQ3UDL +! Aug. 4, 1998 - TA(AS)変更 JQ3UDL +! Nov. 15, 1998 - BQ9P追加 JQ3UDL +! Feb. 7, 1999 - FO0/M追加 JQ3UDL +! Feb. 7, 1999 - FO0/A追加 JQ3UDL +! Feb. 7, 1999 - H40追加 JQ3UDL +! Jul. 10, 1999 - E4追加  JQ3UDL +! Nov. 15. 1999 - 9M6OO追加 JQ3UDL +! Nov. 20. 1999 - B1-B9追加 JQ3UDL +! Jan. 06. 2000 - ST0削除 JE3HHT +! Feb. 15. 2000 - VR6にVP6追加 JE3HHT +! Mar. 03. 2000 - FO0XにFO0AAA追加 JE3HHT +! Mar. 20. 2000 - FO0X=>FO/C,FO0/M=>FO/M,FO0/A=>FO/Aに変更 JQ3UDL +! Mar. 20. 2000 - 4W追加 JQ3UDL +! Mar. 21. 2000 - TX0追加 JE3HHT +! Jan. 07. 2001 - P2の範囲変更 JQ3UDL +! Jan. 08. 2001 - KG4範囲変更 JQ3UDL +! Jan. 08. 2001 - LZ0A追加 JQ3UDL + \ No newline at end of file diff --git a/JASTA/App.ico b/JASTA/App.ico new file mode 100644 index 0000000..746e4d9 Binary files /dev/null and b/JASTA/App.ico differ diff --git a/JASTA/ComLib.cpp b/JASTA/ComLib.cpp new file mode 100644 index 0000000..4a8fef7 --- /dev/null +++ b/JASTA/ComLib.cpp @@ -0,0 +1,1618 @@ +//--------------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "ComLib.h" +#include "LogFile.h" +#include "main.h" +//--------------------------------------------------------------------------- +char BgnDir[256]; // 起動ディレクトリ +char MMLogDir[256]; + +LCID lcid; +int MsgEng; +SYSSET sys; + +//--------------------------------------------------------------------------- +int IsFile(LPCSTR pName) +{ + FILE *fp; + fp = fopen(pName, "rb"); + if( fp != NULL ){ + fclose(fp); + return 1; + } + else { + return 0; + } +} +//--------------------------------------------------------------------------- +LPSTR StrDupe(LPCSTR s) +{ + LPSTR p = new char[strlen(s)+1]; + strcpy(p, s); + return p; +} + + +LPUSTR jstrupr(LPUSTR s) +{ + LPUSTR p = s; + int kf; + + for( kf = 0; *p; p++ ){ + if( kf ){ + kf = 0; + } + else if( _mbsbtype((unsigned char *)p, 0) == _MBC_LEAD ){ + kf = 1; + } + else { + *p = (unsigned char)toupper(*p); + } + } + return s; +} +/*#$% +=============================================================== + 時刻を調整する +--------------------------------------------------------------- + t : 時刻(UTC) + c : 時差コード +--------------------------------------------------------------- + ローカルタイム +--------------------------------------------------------------- + A-Z + a-z +30min +=============================================================== +*/ +WORD AdjustRolTimeUTC(WORD tim, char c) +{ + const char tdf[]={ +/* A B C D E F G H I J K L M N O P Q R S T U V W X Y Z */ + 1,2,3,4,5,6,7,8,9,9,10,11,12,23,22,21,20,19,18,17,16,15,14,13,12,0 + }; + int cc; + + cc = toupper(c); + if( (cc >= 'A')&&(cc <= 'Z') ){ + // JST to UTC +#if 0 + if( tim >= (9*60*30) ){ + tim -= WORD(9 * 60 * 30); + } + else { + tim += WORD(15 * 60 * 30); + } +#endif + tim /= WORD(30); + tim += WORD(tdf[cc-'A'] * 60); + if( c >= 'a' ) tim += WORD(30); + while( tim >= (24 * 60) ){ + tim -= WORD(24 * 60); + } + tim *= WORD(30); + if( !tim ) tim++; + } + else { + tim = 0; + } + return tim; +} +///---------------------------------------------------------------- +/// ウィンドウをクライアントセンターにする +void FormCenter(TForm *tp, int XW, int YW) +{ + int top = (YW - tp->Height)/2; + int left = (XW - tp->Width)/2; + if( top < 0 ) top = 0; + if( left < 0 ) left = 0; + tp->Top = top; + tp->Left = left; +} +/*#$% +======================================================== + 最後の文字コードを返す +-------------------------------------------------------- + p : 文字列のポインタ +-------------------------------------------------------- + 文字コード +-------------------------------------------------------- +======================================================== +*/ +char *lastp(char *p) +{ + if( *p ){ + for( ; *p; p++ ); + p--; + return(p); + } + else { + return(p); + } +} +/*#$% +======================================================== + 末尾のスペースとTABを取る +-------------------------------------------------------- + s : 文字列のポインタ +-------------------------------------------------------- + 文字列のポインタ +-------------------------------------------------------- +======================================================== +*/ +char *clipsp(char *s) +{ + char *p; + + if( *s ){ + for( p = lastp(s); p >= s; p-- ){ + if( (*p == ' ')||(*p == 0x09) ){ + *p = 0; + } + else { + break; + } + } + } + return(s); +} +//--------------------------------------------------------------------------- +LPCSTR _strdmcpy(LPSTR t, LPCSTR p, char c) +{ + for( ; *p && (*p != c); p++, t++ ) *t = *p; + *t = 0; + if( *p == c ) p++; + return(p); +} +const char *StrDlmCpy(char *t, const char *p, char Dlm, int len) +{ + const char _tt1[]="[{(「<"; + const char _tt2[]="]})」>"; + const char *pp; + int r = FALSE; + + char Key; + if( (pp = strchr(_tt2, Dlm))!=NULL ){ + Key = _tt1[pp - _tt2]; + } + else { + Key = 0; + } + int f, k; + for( f = k = 0; *p; p++ ){ + if( k ){ // 漢字2バイト目 + k = 0; + } + else if( _mbsbtype((const unsigned char *)p, 0) == _MBC_LEAD ){ // 漢字1バイト目 + k = 1; + } + else if( *p == Key ){ + f++; + } + else if( *p == Dlm ){ + if( f ){ + f--; + } + else { + r = TRUE; + p++; + break; + } + } + if( len ){ + *t++ = *p; + len--; + } + } + *t = 0; + return (r == TRUE) ? p : NULL; +} + +const char *StrDlmCpyK(char *t, const char *p, char Dlm, int len) +{ + const char _tt1[]="[{(「<"; + const char _tt2[]="]})」>"; + const char *pp; + int r = FALSE; + + char Key; + if( (pp = strchr(_tt2, Dlm))!=NULL ){ + Key = _tt1[pp - _tt2]; + } + else { + Key = 0; + } + int f, k; + for( f = k = 0; *p; p++ ){ + if( k ){ // 漢字2バイト目 + k = 0; + } + else if( _mbsbtype((const unsigned char *)p, 0) == _MBC_LEAD ){ // 漢字1バイト目 + k = 1; + } + else if( (pp = strchr(_tt1, *p))!=NULL ){ + Key = _tt2[pp - _tt1]; + f++; + } + else if( f && (*p == Key) ){ + f--; + Key = 0; + } + else if( *p == Dlm ){ + if( !f ){ + r = TRUE; + p++; + break; + } + } + if( len ){ + *t++ = *p; + len--; + } + } + *t = 0; + return (r == TRUE) ? p : NULL; +} +//--------------------------------------------------------------------------- +void StrCopy(LPSTR t, LPCSTR s, int n) +{ + for( ; *s && n; n--, s++, t++){ + *t = *s; + } + *t = 0; +} +//--------------------------------------------------------------------------- +char LastC(LPCSTR p) +{ + char c = 0; + + if( *p ){ + c = *(p + strlen(p) - 1); + } + return c; +} + +/*#$% +======================================================== + 拡張子を得る +-------------------------------------------------------- + p : 文字列のポインタ +-------------------------------------------------------- + 文字コード +-------------------------------------------------------- +======================================================== +*/ +LPCSTR GetEXT(LPCSTR Fname) +{ + if( *Fname ){ + LPCSTR p = Fname + (strlen(Fname) - 1); + for( ; p > Fname; p-- ){ + if( *p == '.' ) return p+1; + } + } + return ""; +} + +void SetEXT(LPSTR pName, LPSTR pExt) +{ + if( *pName ){ + LPSTR p; + + for( p = &pName[strlen(pName)-1]; p >= pName; p-- ){ + if( *p == '.' ){ + strcpy(p, pExt); + return; + } + } + strcat(pName, pExt); + } +} + +void SetCurDir(LPSTR t, int size) +{ + if( !::GetCurrentDirectory(size-1, t) ){ + *t = 0; + } + else { + if( LastC(t) != '\\' ){ + strcat(t, "\\"); + } + } +} + +void SetDirName(LPSTR t, LPCSTR pName) +{ + char drive[_MAX_DRIVE]; + char dir[_MAX_DIR]; + char name[_MAX_FNAME]; + char ext[_MAX_EXT]; + AnsiString Dir; + + ::_splitpath( pName, drive, dir, name, ext ); + Dir = drive; + Dir += dir; + strncpy(t, Dir.c_str(), 128); +} + +///---------------------------------------------------------------- +/// CR/LFを削除 +/// +void ClipLF(LPSTR sp) +{ + for( ; *sp; sp++ ){ + if( (*sp == LF)||(*sp == CR) ){ + *sp = 0; + break; + } + } +} +///---------------------------------------------------------------- +/// コメントを削除(スペースおよびTABも削除) +/// +void DeleteComment(LPSTR bf) +{ + LPSTR sp, tp; + + for( sp = tp = bf; *sp; sp++ ){ + if( (*sp == ';')||(*sp == CR)||(*sp == LF) ){ + break; + } + else if( (*sp!=' ')&&(*sp!=TAB) ){ + *tp++ = *sp; + } + } + *tp = 0; +} + +LPSTR FillSpace(LPSTR s, int n) +{ + LPSTR p = s; + int i = 0; + for( ; *p && (i < n); i++, p++ ); + for( ; i < n; i++, p++ ){ + *p = ' '; + } + *p = 0; + return s; +} +///---------------------------------------------------------------- +/// ホワイトスペースのスキップ +/// +LPSTR SkipSpace(LPSTR sp) +{ + for( ; *sp; sp++ ){ + if( (*sp != ' ')&&(*sp != TAB) ) break; + } + return sp; +} + +LPCSTR SkipSpace(LPCSTR sp) +{ + for( ; *sp; sp++ ){ + if( (*sp != ' ')&&(*sp != TAB) ) break; + } + return sp; +} +///---------------------------------------------------------------- +LPSTR DelLastSpace(LPSTR t) +{ + int l = strlen(t); + if( l ){ + LPSTR p; + for( p = t + l - 1; p >= t; p-- ){ + if( (*p == ' ') || (*p == TAB) ){ + *p = 0; + } + else { + break; + } + } + } + return t; +} +///---------------------------------------------------------------- +/// デリミッタ分解を行う +/// +LPSTR StrDlm(LPSTR &t, LPSTR p) +{ + return StrDlm(t, p, ','); +} + +///---------------------------------------------------------------- +/// デリミッタ分解を行う +/// +LPSTR StrDlm(LPSTR &t, LPSTR p, char c) +{ + int f, k; + LPSTR d1=NULL; + LPSTR d2=NULL; + + t = p; + f = k = 0; + while(*p){ + if( k ){ // 漢字2バイト目 + k = 0; + } + else if( _mbsbtype((const unsigned char *)p, 0) == _MBC_LEAD ){ // 漢字1バイト目 + k = 1; + } + else if( *p == 0x22 ){ + if( !f ){ + if( d1 == NULL ) d1 = p+1; + f++; + } + else { + d2 = p; + f--; + } + } + else if( !f && (*p == c) ){ + *p = 0; + p++; + break; + } + p++; + } + if( (d1!=NULL)&&(d2!=NULL) ){ + if( ((t+1)==d1) && ( ((p-2)==d2)||((p-1)==d2) ) ){ + t = d1; + *d2 = 0; + } + } + return(p); +} + +///---------------------------------------------------------------- +/// +void ChgString(LPSTR t, char a, char b) +{ + for( ; *t; t++ ){ + if( *t == a ) *t = b; + } +} + +///---------------------------------------------------------------- +/// +void DelChar(LPSTR t, char a) +{ + for( ; *t; t++ ){ + if( *t == a ){ + strcpy(t, t+1); + t--; + } + } +} + +/*#$% +======================================================== + デシマルアスキーを数値に変換する +-------------------------------------------------------- + p : 文字列のポインタ + n : 変換桁数 +-------------------------------------------------------- + 数値 +-------------------------------------------------------- +======================================================== +*/ +int atoin(const char *p, int n) +{ + int d; + + for( d = 0; *p && n; p++, n-- ){ + d *= 10; + d += (*p & 0x0f); + } + return(d); +} +/*#$% +======================================================== + 16進アスキーを数値に変換する +-------------------------------------------------------- + p : 文字列のポインタ + n : 変換桁数 +-------------------------------------------------------- + 数値 +-------------------------------------------------------- +======================================================== +*/ +int htoin(const char *p, int n) +{ + if( *p == 'x' ) return 0; + int d; + + for( d = 0; *p && n; p++, n-- ){ + d = d << 4; + d += (*p & 0x0f); + if( *p >= 'A' ) d += 9; + } + return(d); +} +//--------------------------------------------------------------------------- +int InvMenu(TMenuItem *pItem) +{ + pItem->Checked = pItem->Checked ? FALSE : TRUE; + return pItem->Checked; +} +///---------------------------------------------------------------- +HWND GetMBHandle(int &flag) +{ + HWND hd; + if( Screen->ActiveForm != NULL ){ + hd = Screen->ActiveForm->Handle; + } + else { + hd = NULL; + } + flag = MB_SETFOREGROUND; + flag |= MB_TOPMOST; + flag |= (hd == NULL) ? MB_TASKMODAL : MB_APPLMODAL; + return hd; +} +static int MsgBoxFlag = 0; +///---------------------------------------------------------------- +/// メッセージの表示 +/// +void InfoMB(LPCSTR fmt, ...) +{ + if( MsgBoxFlag ) return; + MsgBoxFlag++; + va_list pp; + char bf[1024]; + + va_start(pp, fmt); + vsprintf( bf, fmt, pp ); + va_end(pp); + + int flag; + HWND hd = GetMBHandle(flag); + flag |= (MB_OK | MB_ICONINFORMATION); +// Application->NormalizeTopMosts(); + ::MessageBox(hd, bf, "MMJASTA", flag); +// Application->RestoreTopMosts(); + MsgBoxFlag--; +} +///---------------------------------------------------------------- +/// エラーメッセージの表示 +/// +void ErrorMB(LPCSTR fmt, ...) +{ + if( MsgBoxFlag ) return; + MsgBoxFlag++; + va_list pp; + char bf[1024]; + + va_start(pp, fmt); + vsprintf( bf, fmt, pp ); + va_end(pp); + + int flag; + HWND hd = GetMBHandle(flag); + flag |= (MB_OK | MB_ICONEXCLAMATION); +// Application->NormalizeTopMosts(); + ::MessageBox(hd, bf, MsgEng ? "Error":"エラー", flag); +// Application->RestoreTopMosts(); + MsgBoxFlag--; +} + +///---------------------------------------------------------------- +/// 警告メッセージの表示 +/// +void WarningMB(LPCSTR fmt, ...) +{ + if( MsgBoxFlag ) return; + MsgBoxFlag++; + va_list pp; + char bf[1024]; + + va_start(pp, fmt); + vsprintf( bf, fmt, pp ); + va_end(pp); + + int flag; + HWND hd = GetMBHandle(flag); + flag |= (MB_OK | MB_ICONEXCLAMATION); +// Application->NormalizeTopMosts(); + ::MessageBox(hd, bf, MsgEng?"Warning":"警告", flag); +// Application->RestoreTopMosts(); + MsgBoxFlag--; +} + +///---------------------------------------------------------------- +/// 実行選択メッセージの表示 +/// +int YesNoMB(LPCSTR fmt, ...) +{ + if( MsgBoxFlag ) return IDNO; + MsgBoxFlag++; + va_list pp; + char bf[1024]; + + va_start(pp, fmt); + vsprintf( bf, fmt, pp ); + va_end(pp); + + int flag; + HWND hd = GetMBHandle(flag); +// if( Screen->ActiveForm != NULL ) NormalWindow(Screen->ActiveForm); + flag |= (MB_YESNO | MB_ICONQUESTION); +// Application->NormalizeTopMosts(); + int r = ::MessageBox(hd, bf, "MMJASTA", flag); +// Application->RestoreTopMosts(); + MsgBoxFlag--; + return r; +} + +///---------------------------------------------------------------- +/// 実行選択メッセージの表示 +/// +int YesNoCancelMB(LPCSTR fmt, ...) +{ + if( MsgBoxFlag ) return IDCANCEL; + MsgBoxFlag++; + va_list pp; + char bf[1024]; + + va_start(pp, fmt); + vsprintf( bf, fmt, pp ); + va_end(pp); + + int flag; + HWND hd = GetMBHandle(flag); + flag |= (MB_YESNOCANCEL | MB_ICONQUESTION); +// Application->NormalizeTopMosts(); + int r = ::MessageBox(hd, bf, "MMJASTA", flag); +// Application->RestoreTopMosts(); + MsgBoxFlag--; + return r; +} +///---------------------------------------------------------------- +/// 実行選択メッセージの表示 +/// +int OkCancelMB(LPCSTR fmt, ...) +{ + if( MsgBoxFlag ) return IDCANCEL; + MsgBoxFlag++; + va_list pp; + char bf[1024]; + + va_start(pp, fmt); + vsprintf( bf, fmt, pp ); + va_end(pp); + + int flag; + HWND hd = GetMBHandle(flag); + flag |= (MB_OKCANCEL | MB_ICONQUESTION); +// Application->NormalizeTopMosts(); + int r = ::MessageBox(hd, bf, "MMJASTA", flag); +// Application->RestoreTopMosts(); + MsgBoxFlag--; + return r; +} +///---------------------------------------------------------------- +/// +void ErrorFWrite(LPCSTR pName) +{ + if( GetFileAttributes(pName) & FILE_ATTRIBUTE_READONLY ){ + ErrorMB(MsgEng ? "'%s' is read-only (fail to update)." : "'%s'が 読み取り専用 に設定されているため更新に失敗しました.", pName); + } + else { + ErrorMB( "Could not update '%s'", pName ); + } +} +///---------------------------------------------------------------- +/// +int RemoveL2(LPSTR t, LPSTR ss, LPCSTR pKey, int size) +{ + char c; + int k; + LPCSTR pp; + LPSTR s; + const char _tt1[]="[{(「<"; + const char _tt2[]="]})」>"; + + int len = strlen(pKey); + char ac = ';'; + for( k = 0, s = ss; *s; s++ ){ + if( k ){ // 漢字2バイト目 + k = 0; + ac = 0x1e; + } + else if( _mbsbtype((const unsigned char *)s, 0) == _MBC_LEAD ){ // 漢字1バイト目 + k = 1; + if( (len >= 2) && (strchr(" ,./;:*\t[{(「<]})」>", ac)!=NULL) && (!strnicmp(s, pKey, len)) ){ + pp = s + len; + if( (pp = strchr(_tt1, *pp))!=NULL ){ + c = _tt2[pp - _tt1]; + if( *(s+len+1) ){ + StrDlmCpy(t, s+len+1, c, size); + if( *t ){ + strcpy((ac == ' ')?(s-1):s, s+len+2+strlen(t)); + return TRUE; + } + } + } + } + } + else if( (strchr(" ,./;:*\t\x1e[{(「<]})」>", ac)!=NULL) && (!strnicmp(s, pKey, len)) ){ + pp = s + len; + if( (pp = strchr(_tt1, *pp))!=NULL ){ + c = _tt2[pp - _tt1]; + if( *(s+len+1) ){ + StrDlmCpy(t, s+len+1, c, size); + if( *t ){ + strcpy((ac == ' ')?(s-1):s, s+len+2+strlen(t)); + return TRUE; + } + } + } + ac = *s; + } + else { + ac = *s; + } + } + return FALSE; +} + +void AddL2(LPSTR t, LPCSTR pKey, LPCSTR s, UCHAR c1, UCHAR c2, int size) +{ + if( *s ){ + int len = strlen(t); + int lenkey = strlen(pKey); + int lenData = strlen(s); + if( (len + lenkey + lenData + 2) < size ){ + t += len; + if( len ) *t++ = ' '; + if( *pKey ){ + strcpy(t, pKey); + t += lenkey; + } + *t++ = c1; + strcpy(t, s); + t += lenData; + *t++ = c2; + *t = 0; + } + } +} +///---------------------------------------------------------------- +void NumCopy(LPSTR t, LPCSTR p) +{ + p = SkipSpace(p); + for( ; *p; p++ ){ + if( isdigit(*p) ){ + *t++ = *p; + } + else { + break; + } + } + *t = 0; +} +///---------------------------------------------------------------- +/// 数字が含まれるかどうか調べる +/// +int IsNumbs(LPCSTR p) +{ + for( ; *p; p++ ){ + if( isdigit(*p) ) return 1; + } + return 0; +} +///---------------------------------------------------------------- +/// 数字が含まれるかどうか調べる +/// +int IsNumbAll(LPCSTR p) +{ + for( ; *p; p++ ){ + if( !isdigit(*p) ) return 0; + } + return 1; +} +///---------------------------------------------------------------- +/// 数字が含まれるかどうか調べる +/// +int IsAlphas(LPCSTR p) +{ + for( ; *p; p++ ){ + if( isalpha(*p) ) return 1; + } + return 0; +} +///---------------------------------------------------------------- +/// RSTかどうか調べる +/// +int IsRST(LPCSTR p) +{ + if( strlen(p) < 3 ) return 0; + if( (*p < '1') || (*p > '5') ) return 0; + p++; + if( (*p < '1') || (*p > '9') ) return 0; + p++; + if( (*p < '1') || (*p > '9') ) return 0; + return 1; +} +///---------------------------------------------------------------- +int IsCallChar(char c) +{ + if( !isalpha(c) && !isdigit(c) && (c != '/') ) return 0; + if( islower(c) ) return 0; + return 1; +} +///---------------------------------------------------------------- +/// コールサインかどうか調べる +/// +int IsCall(LPCSTR p) +{ + int l = strlen(p); + if( l > 16 ) return 0; + if( l < 3 ) return 0; + if( isdigit(*p) ){ // 先頭が数字 + if( l <= 3 ) return 0; // 3文字以下の時NG + if( isdigit(*(p+1)) ) return 0; // 2文字目が数字の時NG + } + if( isdigit(LastC(p)) ){ // 最後が数字 + if( l <= 4 ) return 0; // 4文字以下の時NG +// if( !strchr(p, '/')==NULL ) return0; // /が含まれていない時NG +// if( p[l-2] != '/' ) return 0; // 最後の1つ前が/以外の時NG + } + int i; + for( i = 0; i < l-1; i++, p++ ){ + if( isdigit(*p) ) return 1; // 数字が含まれていればOK + } + return 0; +} +/*#$% +====================================================== + JAとDXの区別をする +------------------------------------------------------ + s : コールサイン文字列のポインタ +------------------------------------------------------ + 1 : JA + 0 : DX (JD1 INCLUDEED) +------------------------------------------------------ +====================================================== +*/ +int IsJA(const char *s) +{ + if( (!memcmp(s, "8J1R", 4) && (strlen(s) == 5))||(strstr(s, "/JD1")!=NULL) ){ + return(0); + } + else if( strchr(s, '/') ){ + char bf[MLCALL+1]; + StrCopy(bf, s, MLCALL); + char *p; + char *t; + for( p = bf; *p; ){ + p = StrDlm(t, p, '/'); + if( *t ){ + if( (strlen(t) >= 2) && isdigit((unsigned char)LastC(t)) ){ + if( *t == 'J' ){ + t++; + if( *t == 'D' ) return(0); + if( (*t >= 'A')&&(*t <= 'S' ) ) return(1); + } + else if( *t == '7' ){ + t++; + if( (*t >= 'J')&&(*t <= 'N' ) ) return(1); + } + else if( *t == '8' ){ + t++; + if( (*t >= 'J')&&(*t <= 'N' ) ) return(1); + } + else { + return 0; + } + } + } + } + } + if( *s == 'J' ){ + s++; + if( *s == 'D' ) return(0); + if( (*s >= 'A')&&(*s <= 'S' ) ) return(1); + } + else if( *s == '7' ){ + s++; + if( (*s >= 'J')&&(*s <= 'N' ) ) return(1); + } + else if( *s == '8' ){ + s++; + if( (*s >= 'J')&&(*s <= 'N' ) ) return(1); + } + return(0); +} +/*#$% +====================================================== + コールサインをクリップする +------------------------------------------------------ + s : コールサイン文字列のポインタ +------------------------------------------------------ + クリップコールのポインタ +------------------------------------------------------ +====================================================== +*/ +LPCSTR ClipCall(LPCSTR s) +{ + static char bf[MLCALL+1]; + LPCSTR p1, p2; + + if( (p1=strchr(s, '/'))!=NULL ){ + if( (p2=strchr(p1+1, '/'))!=NULL ){ /* 3分割 */ + if( (int(strlen(p2+1)) < int((p2 - p1)+1)) || (!IsCall(p2+1)) ){ /* 最後より途中が長い */ + if( ((p2-p1) < (p1-s))||(!IsCall(p1+1)) ){ /* 途中より最初が長い */ + StrCopy(bf, s, MLCALL); + *strchr(bf, '/') = 0; + return(bf); + } + else { + strcpy(bf, p1+1); + *strchr(bf, '/') = 0; + return(bf); + } + } + else if( int(strlen(p2+1)) < int((p1 - s)+1) ){ /* 最後より最初が長い */ + StrCopy(bf, s, MLCALL); + *strchr(bf, '/') = 0; + return(bf); + } + else { + return(p2+1); + } + } + else { /* 2分割 */ + if( (int(strlen(p1+1)) < int((p1 - s)+1)) || (!IsCall(p1+1)) ){ + StrCopy(bf, s, MLCALL); + *strchr(bf, '/') = 0; + return(bf); + } + else { + return(p1+1); + } + } + } + else { + return(s); + } +} + +/*#$% +====================================================== + ポータブル表記を調べる +------------------------------------------------------ + p : コールサイン文字列のポインタ +------------------------------------------------------ + 数値のポインタ +------------------------------------------------------ +====================================================== +*/ +static LPSTR chkptb(LPSTR p) +{ + if( *p ){ + p = lastp(p); + if( isdigit(*p) && ((*(p-1))=='/') ){ + return(p); + } + } + return(NULL); +} + +/*#$% +====================================================== + ポータブル表記の入れ替え +------------------------------------------------------ + s : コールサイン文字列のポインタ +------------------------------------------------------ +------------------------------------------------------ + 元の文字列を破壊する +====================================================== +*/ +void chgptb(LPSTR s) +{ + LPSTR p, t; + + if( (p = chkptb(s))!=NULL ){ + t = p; + for( p--; p > s; p-- ){ + if( isdigit(*p) ){ + *p = *t; + t--; + *t = 0; + break; + } + } + } +} + +/*#$% +====================================================== + コールサインからカントリの元をクリップする +------------------------------------------------------ + s : コールサイン文字列のポインタ +------------------------------------------------------ + カントリのポインタ +------------------------------------------------------ +====================================================== +*/ +LPCSTR ClipCC(LPCSTR s) +{ + static char bf[MLCALL+1]; + LPSTR p, t; + + StrCopy(bf, s, MLCALL); + chgptb(bf); /* ポータブル表記の入れ替え */ + for( p = bf; *p; ){ + if( *p ){ + p = StrDlm(t, p, '/'); + if( (strlen(t) > 1) && (isdigit(*t) || isdigit(LastC(t))) ) return(t); + } + } + for( p = bf; *p; ){ + if( *p ){ + p = StrDlm(t, p, '/'); + if( (strlen(t) > 1) && (*t!='Q') && strcmp(t, "MM") ) return(t); + } + } + return ClipCall(s); +} + +///---------------------------------------------------------------- +/// 文字列変換 +/// +void Yen2CrLf(AnsiString &ws, AnsiString cs) +{ + ws = ""; + LPCSTR p; + int f; + int dlm = 0; + + p = cs.c_str(); + if( *p == 0x22 ){ + p++; + dlm++; + } + for( f = 0; *p; p++ ){ + if( f ){ + f = 0; + ws += *p; + } + else if( _mbsbtype((const unsigned char *)p, 0) == _MBC_LEAD ){ + f = 1; + ws += *p; + } + else if( *p == '\\' ){ + switch(*(p+1)){ + case 'r': + ws += "\r"; + p++; + break; + case 'n': + ws += "\n"; + p++; + break; + case 't': + ws += "\t"; + p++; + break; + case '\\': + ws += "\\"; + p++; + break; + default: + p++; + ws += *p; + break; + } + } + else if( !dlm || (*p!=0x22) || *(p+1) ){ + ws += *p; + } + } +} + +void CrLf2Yen(AnsiString &ws, AnsiString cs) +{ + ws = "\x22"; + LPCSTR p; + int f = 0; + + for( p = cs.c_str(); *p; p++ ){ + if( f ){ + f = 0; + ws += *p; + } + else if( _mbsbtype((const unsigned char *)p, 0) == _MBC_LEAD ){ + f = 1; + ws += *p; + } + else if( *p == 0x0d ){ + ws += "\\r"; + } + else if( *p == 0x0a ){ + ws += "\\n"; + } + else if( *p == TAB ){ + ws += "\\t"; + } + else if( *p == '\\' ){ + ws += "\\\\"; + } + else { + ws += *p; + } + } + ws += "\x22"; +} + + +///--------------------------------------------------------- +/// テキスト文字列ストリーマー +int __fastcall CTextString::LoadText(LPSTR tp, int len) +{ + char c; + int n = 0; + if( !(*rp) ) return FALSE; + while(*rp){ + c = *rp++; + if( c == LF ){ + *tp = 0; + return TRUE; + } + else if( (c != CR)&&(c != 0x1a) ){ + if( n < (len-1) ){ + *tp++ = c; + n++; + } + } + } + *tp = 0; + return TRUE; +} +///------------------------------------------------------ +/// +///CWebRef クラス +/// +void MakeCommand(LPSTR t, LPCSTR s, LPCSTR p) +{ + for( ;*s; s++ ){ + if( *s == '%' ){ + s++; + if( *s == '%' ){ + *t++ = '%'; + } + else if( (p != NULL) && (*s == '1') ){ + strcpy(t, p); + t += strlen(t); + p = NULL; + } + } + else { + *t++ = *s; + } + } + *t = 0; + if( p != NULL ){ + *t++ = ' '; + strcpy(t, p); + } +} + +CWebRef::CWebRef() +{ + HTML = ""; + + HKEY hkey=NULL; /* オープン キーのハンドル */ + + char bf[512], name[512]; + ULONG namelen, len; + if( !RegOpenKeyEx(HKEY_CLASSES_ROOT, "http", 0, KEY_READ, &hkey) ){ + if( !RegOpenKeyEx(hkey, "shell", 0, KEY_READ, &hkey) ){ + if( !RegOpenKeyEx(hkey, "open", 0, KEY_READ, &hkey) ){ + if( !RegOpenKeyEx(hkey, "command", 0, KEY_READ, &hkey) ){ + namelen = sizeof(name); + len = sizeof(bf); + if( !::RegEnumValue(hkey, 0, name, &namelen, NULL, + NULL, (LPBYTE)bf, &len) ){ + HTML = bf; + } + } + } + } + } + ::RegCloseKey(hkey); +} + +void CWebRef::ShowHTML(LPCSTR url) +{ + char cmd[1024]; + MakeCommand(cmd, HTML.c_str(), url); + ::WinExec(cmd, SW_SHOWDEFAULT); +} + + +///------------------------------------------------------ +/// +///CWaitCursor クラス +/// +CWaitCursor::CWaitCursor() +{ + sv = Screen->Cursor; + Screen->Cursor = crHourGlass; +} + +CWaitCursor::~CWaitCursor() +{ + Screen->Cursor = sv; +} + +void CWaitCursor::Delete(void) +{ + Screen->Cursor = sv; +} + +void CWaitCursor::Wait(void) +{ + Screen->Cursor = crHourGlass; +} + +///---------------------------------------------------------------- +/// CAlignクラス +void CAlign::InitControl(TControl *p, TControl *pB, TFont *pF /*= NULL*/) +{ + tp = p; + OTop = p->Top; + OLeft = p->Left; + OWidth = p->Width; + OHeight = p->Height; + if( pF != NULL ){ + fp = pF; + OFontHeight = pF->Height; + } + + BTop = pB->Top; + BLeft = pB->Left; + BWidth = pB->ClientWidth; + BHeight = pB->ClientHeight; +} + +void CAlign::InitControl(TControl *p, RECT *rp, TFont *pF /*= NULL*/) +{ + tp = p; + OTop = p->Top; + OLeft = p->Left; + OWidth = p->Width; + OHeight = p->Height; + if( pF != NULL ){ + fp = pF; + OFontHeight = pF->Height; + } + + BTop = rp->top; + BLeft = rp->left; + BWidth = rp->right - rp->left + 1; + BHeight = rp->bottom - rp->top + 1; +} + +void CAlign::NewAlign(TControl *pB) +{ + double Sx = double(pB->ClientWidth)/double(BWidth); + double Sy = double(pB->ClientHeight)/double(BHeight); + tp->SetBounds(int(OLeft * Sx), int(OTop * Sy), int(OWidth * Sx), int(OHeight * Sy)); + if( fp != NULL ){ + if( Sx > Sy ) Sx = Sy; + fp->Height = int(OFontHeight * Sx); + m_FontAdj = Sx; + } + if( tp->ClassNameIs("TComboBox") ){ + ((TComboBox *)tp)->SelLength = 0; + } + else if( tp->ClassNameIs("TLabel") ){ + TLabel *lp = ((TLabel *)tp); + if( lp->Alignment == taRightJustify ){ + lp->AutoSize = FALSE; + lp->AutoSize = TRUE; + } + } +} + +void CAlign::NewAlign(TControl *pB, double hx) +{ + double Sx = double(pB->ClientWidth)/double(BWidth); + double Sy = double(pB->ClientHeight)/double(BHeight); + Sy *= hx; + tp->SetBounds(int(OLeft * Sx), int(OTop * Sy), int(OWidth * Sx), int(OHeight * Sy)); + if( fp != NULL ){ + if( Sx > Sy ) Sx = Sy; + fp->Height = int(OFontHeight * Sx); + m_FontAdj = Sx; + } + if( tp->ClassNameIs("TComboBox") ){ + ((TComboBox *)tp)->SelLength = 0; + } +} + +void CAlign::NewFont(AnsiString &FontName, BYTE Charset, TFontStyles fs) +{ + if( fp != NULL ){ + fp->Name = FontName; + fp->Charset = Charset; + fp->Style = fs; + if( tp->ClassNameIs("TComboBox") ){ + ((TComboBox *)tp)->SelLength = 0; + } + } +} + +void CAlign::NewFixAlign(TControl *pB, int XR) +{ + double Sx = double(pB->ClientWidth - XR) / double(BWidth - XR); + + tp->SetBounds(XR + (OLeft - XR) * Sx, OTop, OWidth * Sx, OHeight); + if( fp != NULL ){ + fp->Height = int(OFontHeight * (Sx < 1.0 ? Sx : 1.0)); + m_FontAdj = Sx; + } + if( tp->ClassNameIs("TComboBox") ){ + ((TComboBox *)tp)->SelLength = 0; + } +} + +void CAlign::Resume(void) +{ + if( tp != NULL ){ + tp->Top = OTop; + tp->Left = OLeft; + tp->Width = OWidth; + tp->Height = OHeight; + if( fp != NULL ){ + fp->Height = OFontHeight; + } + } +} +///---------------------------------------------------------------- +/// CAlignListクラス +CAlignList::CAlignList(void) +{ + Max = 0; + Cnt = 0; + AlignList = NULL; +} + +CAlignList::~CAlignList(){ + if( AlignList != NULL ){ + for( int i = 0; i < Cnt; i++ ){ + delete AlignList[i]; + } + delete AlignList; + AlignList = NULL; + } +} + +void CAlignList::Alloc(void) +{ + if( Cnt >= Max ){ + Max = Max ? Max * 2 : 16; + CAlign **np = (CAlign **)new BYTE[sizeof(CAlign*) * Max]; + if( AlignList != NULL ){ + for( int i = 0; i < Cnt; i++ ){ + np[i] = AlignList[i]; + } + delete AlignList; + } + AlignList = np; + } + AlignList[Cnt] = new CAlign; +} +void CAlignList::EntryControl(TControl *tp, TControl *pB, TFont *pF /*= NULL*/) +{ + Alloc(); + AlignList[Cnt]->InitControl(tp, pB, pF); + Cnt++; +} + +void CAlignList::EntryControl(TControl *tp, RECT *rp, TFont *pF /*= NULL*/){ + Alloc(); + AlignList[Cnt]->InitControl(tp, rp, pF); + Cnt++; +} + +void CAlignList::EntryControl(TControl *tp, int XW, int YW, TFont *pF /*= NULL*/){ + RECT rc; + rc.left = rc.top = 0; + rc.right = XW; rc.bottom = YW; + Alloc(); + AlignList[Cnt]->InitControl(tp, &rc, pF); + Cnt++; +} + +void CAlignList::NewAlign(TControl *pB) +{ + if( AlignList == NULL ) return; + for( int i = 0; i < Cnt; i++ ){ + AlignList[i]->NewAlign(pB); + } +} + +double CAlignList::GetFontAdj(TControl *pB) +{ + for( int i = 0; i < Cnt; i++ ){ + if( AlignList[i]->GetControl() == pB ){ + return AlignList[i]->GetFontAdj(); + } + } + return 1.0; +} + +void CAlignList::NewAlign(TControl *pB, TControl *pS, double hx) +{ + for( int i = 0; i < Cnt; i++ ){ + if( AlignList[i]->GetControl() == pS ){ + AlignList[i]->NewAlign(pB, hx); + break; + } + } +} +void CAlignList::NewFont(AnsiString &FontName, BYTE Charset, TFontStyles fs) +{ + if( AlignList == NULL ) return; + for( int i = 0; i < Cnt; i++ ){ + AlignList[i]->NewFont(FontName, Charset, fs); + } +} + +void CAlignList::NewFixAlign(TControl *pB, int XR) +{ + if( AlignList == NULL ) return; + for( int i = 0; i < Cnt; i++ ){ + AlignList[i]->NewFixAlign(pB, XR); + } +} + +void CAlignList::Resume(TControl *pB) +{ + if( AlignList == NULL ) return; + for( int i = 0; i < Cnt; i++ ){ + if( pB == NULL ){ + AlignList[i]->Resume(); + } + else if( pB == AlignList[i]->GetControl() ){ + AlignList[i]->Resume(); + break; + } + } +} + +//--------------------------------------------------------------------------- +void __fastcall SetGroupEnabled(TGroupBox *gp) +{ + TControl *tp; + int i; + for( i = 0; i < gp->ControlCount; i++ ){ + tp = gp->Controls[i]; + if( tp != NULL ){ + tp->Enabled = gp->Enabled; + if( tp->ClassNameIs("TComboBox") ){ + ((TComboBox *)tp)->SelLength = 0; + } + else if( tp->ClassNameIs("TGroupBox") ){ + SetGroupEnabled((TGroupBox *)tp); + } + } + } + gp->Font->Color = gp->Enabled ? clBlack : clGrayText; +} +//--------------------------------------------------------------------------- +void KeyEvent(const short *p) +{ + for( ; *p; p++ ){ + keybd_event(BYTE(*p), 0, *p&0x8000 ? KEYEVENTF_KEYUP : 0, 0); + } +} +//--------------------------------------------------------------------------- +// CMULTクラス +CMULT::CMULT() +{ + m_pBase = NULL; + m_CNT = m_MAX = 0; +} +//--------------------------------------------------------------------------- +void CMULT::Clear(void) +{ + for( int i = 0; i < m_CNT; i++ ){ + delete m_pBase[i].pStr; + } + delete m_pBase; + m_pBase = NULL; + m_CNT = m_MAX = 0; +} +//--------------------------------------------------------------------------- +void CMULT::Alloc(void) +{ + int max = m_MAX ? (m_MAX * 2) : 256; + MULTSET *pBase = new MULTSET[max]; + if( m_pBase != NULL ){ + memcpy(pBase, m_pBase, sizeof(MULTSET) * m_CNT); + delete m_pBase; + } + m_pBase = pBase; + m_MAX = max; +} +//--------------------------------------------------------------------------- +int CMULT::Add(LPCSTR pKey) +{ + for( int i = 0; i < m_CNT; i++ ){ + if( !strcmp(m_pBase[i].pStr, pKey) ){ + m_pBase[i].Count++; + return 0; + } + } + if( m_CNT >= m_MAX ) Alloc(); + m_pBase[m_CNT].pStr = StrDupe(pKey); + m_pBase[m_CNT].Count = 1; + m_CNT++; + return 1; +} +//--------------------------------------------------------------------------- +int CMULT::Set(LPCSTR pKey, int n) +{ + for( int i = 0; i < m_CNT; i++ ){ + if( !strcmp(m_pBase[i].pStr, pKey) ){ + m_pBase[i].Count = n; + return 0; + } + } + if( m_CNT >= m_MAX ) Alloc(); + m_pBase[m_CNT].pStr = StrDupe(pKey); + m_pBase[m_CNT].Count = n; + m_CNT++; + return 1; +} +//--------------------------------------------------------------------------- +static int CMULTcmpCall(const void *s, const void *t) +{ + MULTSET *sp = (MULTSET *)s; + MULTSET *tp = (MULTSET *)t; + return strcmp(sp->pStr, tp->pStr); +} +static int CMULTcmpCount(const void *s, const void *t) +{ + MULTSET *sp = (MULTSET *)s; + MULTSET *tp = (MULTSET *)t; + if( sp->Count == tp->Count ){ + return strcmp(sp->pStr, tp->pStr); + } + else { + return tp->Count - sp->Count; + } +} +void CMULT::Sort(void) +{ + if( m_CNT < 2 ) return; + qsort(m_pBase, m_CNT, sizeof(MULTSET), CMULTcmpCall); +} +void CMULT::SortCount(void) +{ + if( m_CNT < 2 ) return; + qsort(m_pBase, m_CNT, sizeof(MULTSET), CMULTcmpCount); +} +//--------------------------------------------------------------------------- +int CMULT::GetCount(LPCSTR pKey) +{ + for( int i = 0; i < m_CNT; i++ ){ + if( !strcmp(m_pBase[i].pStr, pKey) ) return m_pBase[i].Count; + } + return 0; +} +//--------------------------------------------------------------------------- +int CMULT::GetTotal(void) +{ + int sum = 0; + for( int i = 0; i < m_CNT; i++ ){ + sum += m_pBase[i].Count; + } + return sum; +} +//--------------------------------------------------------------------------- + + \ No newline at end of file diff --git a/JASTA/ComLib.h b/JASTA/ComLib.h new file mode 100644 index 0000000..9e098b1 --- /dev/null +++ b/JASTA/ComLib.h @@ -0,0 +1,327 @@ +#ifndef ComLibH +#define ComLibH +//ja7ude 0525 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEBUG 0 +#if DEBUG +#include +#define ASSERT(c) assert(c) +#else +#define ASSERT(c) +#endif + +#define VERBETA "" +#define VERID "Ver 1.14" +#define VERTTL2 "MMJASTA "VERID VERBETA +#define VERTTL VERTTL2" (C) JE3HHT 2002-2010." + +extern LCID lcid; + +extern int MsgEng; +extern char BgnDir[256]; +extern char MMLogDir[256]; + +extern const char MONN[]; +extern const char MONU[]; + +#ifndef LPCUSTR +typedef const unsigned char * LPCUSTR; +typedef unsigned char * LPUSTR; +#endif + +enum TFontPitch { fpDefault, fpVariable, fpFixed }; //ja7ude 0525 + +#define ABS(c) (((c)<0)?(-(c)):(c)) +#define AN(p) (sizeof(p)/sizeof(*(p))) +#define CR 0x0d +#define LF 0x0a +#define TAB '\t' + +typedef struct { + int m_HelpNotePad; + int m_Year; + AnsiString m_CName; + + AnsiString m_Call; + int m_First; + int m_Category; + AnsiString m_Name; + AnsiString m_Zip; + AnsiString m_Adr; + AnsiString m_Mail; + AnsiString m_License; + AnsiString m_Pow; + BOOL m_Sexual; + int m_TSize; // S, M, L, LL, アクテイブ賞のT−シャツ当選時の希望サイズ +}SYSSET; +extern SYSSET sys; +///--------------------------------------------------------- +/// テキスト文字列ストリーマー +class CTextString +{ +private: + LPCSTR rp; +public: + inline __fastcall CTextString(LPCSTR p){ + rp = p; + }; + inline __fastcall CTextString(AnsiString &As){ + rp = As.c_str(); + }; + int __fastcall LoadText(LPSTR tp, int len); +}; + +class CWebRef +{ +private: + AnsiString HTML; +public: + CWebRef(); + inline bool IsHTML(void){ + return !HTML.IsEmpty(); + }; + void ShowHTML(LPCSTR url); +}; + +///--------------------------------------------------------- +/// テキストバッファストリーマー +class StrText{ +public: + char *Bp; + char *Wp; + inline StrText(int max){ + Bp = new char[max]; + Clear(); + }; + inline ~StrText(){ + delete Bp; + }; + inline char *Printf(char *ct, ...){ + va_list pp; + + va_start(pp, ct); + vsprintf(Wp, ct, pp ); + va_end(pp); + ct = Wp; + Wp += strlen(Wp); + return(ct); + }; + inline void Add(LPCSTR sp){ + strcpy(Wp, sp); + Wp += strlen(Wp); + }; + inline void Write(void *p, int n){ + memcpy(Wp, p, n); + Wp += n; + *Wp = 0; + }; + inline int GetCnt(void){ + return Wp - Bp; + }; + inline void Clear(void){ + Wp = Bp; + *Wp = 0; + }; + inline char *GetText(void){ + return Bp; + }; +}; + +class CWaitCursor +{ +private: + TCursor sv; +public: + CWaitCursor(); + ~CWaitCursor(); + void Delete(void); + void Wait(void); +}; + +///--------------------------------------------------------- +/// コントロールのアラインの管理クラス +class CAlign +{ +private: + int BTop, BLeft; + int BWidth, BHeight; + int OTop, OLeft; + int OWidth, OHeight; + int OFontHeight; + double m_FontAdj; + + TControl *tp; + TFont *fp; +public: + inline CAlign(void){ + tp = NULL; + fp = NULL; + m_FontAdj = 1.0; + }; + inline ~CAlign(){ + }; + void InitControl(TControl *p, TControl *pB, TFont *pF = NULL); + void InitControl(TControl *p, RECT *rp, TFont *pF = NULL); + void NewAlign(TControl *pB); + inline double GetFontAdj(void){return fabs(m_FontAdj);}; + inline TControl *GetControl(void){return tp;}; + void NewAlign(TControl *pB, double hx); + void NewFont(AnsiString &FontName, BYTE Charset, TFontStyles fs); + void NewFixAlign(TControl *pB, int XR); + void Resume(void); +}; + +///--------------------------------------------------------- +/// コントロールのアラインの管理クラス +class CAlignList +{ +private: + int Max; + int Cnt; + CAlign **AlignList; + void Alloc(void); +public: + CAlignList(void); + ~CAlignList(); + void EntryControl(TControl *tp, TControl *pB, TFont *pF = NULL); + void EntryControl(TControl *tp, RECT *rp, TFont *pF = NULL); + void EntryControl(TControl *tp, int XW, int YW, TFont *pF = NULL); + void NewAlign(TControl *pB); + double GetFontAdj(TControl *pB); + void NewAlign(TControl *pB, TControl *pS, double hx); + void NewFont(AnsiString &FontName, BYTE Charset, TFontStyles fs); + void NewFixAlign(TControl *pB, int XR); + void Resume(TControl *pB); +}; + +int IsFile(LPCSTR pName); + +LPSTR StrDupe(LPCSTR s); + +LPUSTR jstrupr(LPUSTR s); +inline LPSTR jstrupr(LPSTR s){return (LPSTR)jstrupr(LPUSTR(s));}; + +int SetTimeOffsetInfo(int &Hour, int &Min); +WORD AdjustRolTimeUTC(WORD tim, char c); +void FormCenter(TForm *tp, int XW, int YW); +char *lastp(char *p); +char *clipsp(char *s); +LPCSTR _strdmcpy(LPSTR t, LPCSTR p, char c); +const char *StrDlmCpy(char *t, const char *p, char Dlm, int len); +const char *StrDlmCpyK(char *t, const char *p, char Dlm, int len); +void StrCopy(LPSTR t, LPCSTR s, int n); +char LastC(LPCSTR p); +LPCSTR GetEXT(LPCSTR Fname); +void SetEXT(LPSTR pName, LPSTR pExt); +void SetCurDir(LPSTR t, int size); +void SetDirName(LPSTR t, LPCSTR pName); +void ClipLF(LPSTR sp); +void DeleteComment(LPSTR bf); +LPSTR FillSpace(LPSTR s, int n); +LPSTR SkipSpace(LPSTR sp); +LPCSTR SkipSpace(LPCSTR sp); +LPSTR DelLastSpace(LPSTR t); +LPSTR StrDlm(LPSTR &t, LPSTR p); +LPSTR StrDlm(LPSTR &t, LPSTR p, char c); +void ChgString(LPSTR t, char a, char b); +void DelChar(LPSTR t, char a); +int atoin(const char *p, int n); +int htoin(const char *p, int n); + +int InvMenu(TMenuItem *pItem); + +void InfoMB(LPCSTR fmt, ...); +void ErrorMB(LPCSTR fmt, ...); +void WarningMB(LPCSTR fmt, ...); +int YesNoMB(LPCSTR fmt, ...); +int YesNoCancelMB(LPCSTR fmt, ...); +int OkCancelMB(LPCSTR fmt, ...); +void ErrorFWrite(LPCSTR pName); + +int RemoveL2(LPSTR t, LPSTR ss, LPCSTR pKey, int size); +void AddL2(LPSTR t, LPCSTR pKey, LPCSTR s, UCHAR c1, UCHAR c2, int size); + +void Yen2CrLf(AnsiString &ws, AnsiString cs); +void CrLf2Yen(AnsiString &ws, AnsiString cs); + +void NumCopy(LPSTR t, LPCSTR p); +int IsNumbs(LPCSTR p); +int IsNumbAll(LPCSTR p); +int IsAlphas(LPCSTR p); +int IsRST(LPCSTR p); +int IsCallChar(char c); +int IsCall(LPCSTR p); +int IsJA(const char *s); +LPCSTR ClipCall(LPCSTR s); +LPCSTR ClipCC(LPCSTR s); + +/* ja7ude 0525 +inline LPUSTR StrDlm(LPUSTR &t, LPUSTR p, char c){return (LPUSTR)StrDlm(LPSTR(t), LPSTR(p), c);}; +inline LPUSTR StrDlm(LPUSTR &t, LPUSTR p){return (LPUSTR)StrDlm(LPSTR(t), LPSTR(p));}; +inline LPUSTR StrDlm(LPUSTR &t, LPSTR p, char c){return (LPUSTR)StrDlm(LPSTR(t), p, c);}; +inline LPUSTR StrDlm(LPUSTR &t, LPSTR p){return (LPUSTR)StrDlm(LPSTR(t), p);}; +*/ + +void __fastcall SetGroupEnabled(TGroupBox *gp); +void KeyEvent(const short *p); + +typedef struct { + LPSTR pStr; + int Count; +}MULTSET; + +class CMULT +{ +private: + int m_CNT; + int m_MAX; + MULTSET *m_pBase; +// LPSTR *m_pStr; +// LPSTR m_pStr[MULTMAX]; +private: + void Alloc(void); + +public: + CMULT(); + ~CMULT(){ + Clear(); + }; + void Clear(void); + int Add(LPCSTR pKey); + int Set(LPCSTR pKey, int n); + int GetCount(void){ + return m_CNT; + }; + void Sort(void); + void SortCount(void); + LPCSTR GetText(int n){ + if( (n >= 0) && (n < m_CNT) ){ + return m_pBase[n].pStr; + } + else { + return NULL; + } + }; + int GetCount(int n){ + if( (n >= 0) && (n < m_CNT) ){ + return m_pBase[n].Count; + } + else { + return 0; + } + }; + int GetCount(LPCSTR pKey); + int GetTotal(void); +}; +#endif + + \ No newline at end of file diff --git a/JASTA/EMMJASTA.TXT b/JASTA/EMMJASTA.TXT new file mode 100644 index 0000000..6f13e56 --- /dev/null +++ b/JASTA/EMMJASTA.TXT @@ -0,0 +1,54 @@ +MMJASTA.EXE + JE3HHT Makoto Mori + First version released on September 3, 2002 + Last revised on September 8, 2004 + Translated into English by JA7UDE Nobuyuki Oba + +MMJASTA.EXE is a program that generates the log and summary sheets for JASTA Activity Contest, which regularly is held in August. +MMJASTA.EXE reads the log data of MMSSTV, calculates the score and generates the log and summary sheets for JA and non-JA stations. + +--------------- +1. Setup +--------------- +Start MMJASTA.EXE, click on File menu, select Setup, and fill out the form. The items you have entered are recorded in MMJASTA.INI, so that you will not have to enter them in the next time. +Select Japanese if you are JA, or English if you are not JA. MMJASTA.EXE generates Japanese or English summary according to this selection. MMJASTA.EXE automatically selects the language by referring to the Windows locale. + +--------------------- +2. Load the log file +--------------------- +Click on File menu and select Load log. Specify the log file that is generated by MMSSTV. The file extension is MDT. MMJASTA.EXE calculates the sore and generates the log and summary sheets. + +MMJASTA.EXE generates the following files in the directory where MMJASTA.EXE exists. + Log sheet Callsign.txt + Summary sheet Callsign.sum + Analysis file Callsign.ana + +MMJASTA automatically picks out the contest QSOs by referring to the date and HisRSV fields. Therefore, the log file can contain non-contest QSOs. + +-------------------- +DX entities +-------------------- +MMJASTA and MMSSTV automatically detect the DX entities and continents in most cases. If MMJASTA.EXE cannot identify the entity from the call sign, MMJASTA.EXE outputs an error message in the lower window, like below. + +194 10/21 1502Z 14 JD1ABC 59940 59999 : DXCC Unknown [JD1/?] + +Double click on the error message. MMJASTA.EXE opens a new window, with which you can edit the multi and continent. Push the OK button after inputting the correct multi and continent information. MMJASTA.EXE changes the entry not only in the JASTA log sheet but also in the original MMSSTV log file. +After editing all the DXCC unknown entries, click on File menu and Re-totalize. + +* The JASTA contest rule as of 2002 does not take account of continents, but MMJASTA.EXE allows the user to edit the continent field for future use. + +----------------------- +4. Invalid QSO +----------------------- +MMJASTA.EXE treat the QSO invalid if +- Two or more QSOs with the same station on the same day (UTC). MMJASTA only counts the first QSO. +- Rcvd contest NR is empty +- REM field has NOF or NOFACE. User should put NOF or NOFACE in the REM field if the face picture was not received. + +-------------- +5. Note +-------------- +MMJASTA automatically calculates the score and generates the log and summary sheets, but DO NOT FORGET TO CHECK ON THE LOG AND SUMMARY SHEETS BY YOURSELF. +This program has just been made and not quite tested. It is highly likely to have bugs.... + +73, Mako diff --git a/JASTA/FEdit.cpp b/JASTA/FEdit.cpp new file mode 100644 index 0000000..da98d1f --- /dev/null +++ b/JASTA/FEdit.cpp @@ -0,0 +1,188 @@ +//--------------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "FEdit.h" +//--------------------------------------------------------------------------- +#pragma package(smart_init) +#pragma resource "*.dfm" +TFileEdit *FileEdit; +//--------------------------------------------------------------------------- +__fastcall TFileEdit::TFileEdit(TComponent* Owner) + : TForm(Owner) +{ + m_FileName = ""; + REdit->Font->Pitch = fpFixed; + if( MsgEng ){ + REdit->Font->Name = "Courier New"; + REdit->Font->Charset = 0; + } + else { + REdit->Font->Name = "MS ゴシック"; + REdit->Font->Charset = SHIFTJIS_CHARSET; + + KF->Caption = "ファイル(&F)"; + KFN->Caption = "メモ帳に切り替え(&N)"; + KFX->Caption = "終了(&X)"; + KE->Caption = "編集(&E)"; + KFA->Caption = "名前を付けて保存(&A)..."; + KEU->Caption = "元に戻す(&U)"; + KEC->Caption = "切り取り(&T)"; + KECP->Caption = "コピー(&C)"; + KEP->Caption = "貼り付け(&P)"; + KEA->Caption = "すべて選択(&L)"; + KS->Caption = "検索(&S)"; + KSS->Caption = "検索(&F)..."; + KSN->Caption = "次を検索(&N)"; + } + for( int i = 0; i < KE->Count; i++ ){ + TMenuItem *pMenu = new TMenuItem(this); + pMenu->Caption = KE->Items[i]->Caption; + pMenu->OnClick = KE->Items[i]->OnClick; + PopupMenu->Items->Add(pMenu); + } +} +//--------------------------------------------------------------------------- +void __fastcall TFileEdit::Execute(LPCSTR pName) +{ + Caption = pName; + CWaitCursor tw; + m_FileName = pName; + REdit->Lines->LoadFromFile(pName); + REdit->Modified = FALSE; + Show(); +} +//--------------------------------------------------------------------- +void __fastcall TFileEdit::FormCloseQuery(TObject *Sender, bool &CanClose) +{ + if( REdit->Modified ){ + int r = YesNoCancelMB(MsgEng ? "Overwrite to the file (%s) ?" : "ファイル (%s) に上書きしますか?", m_FileName.c_str()); + switch(r){ + case IDYES: + { + CWaitCursor w; + REdit->Lines->SaveToFile(m_FileName); + } + break; + case IDCANCEL: + CanClose = FALSE; + return; + } + } + CanClose = TRUE; +} +//--------------------------------------------------------------------------- +void __fastcall TFileEdit::KECClick(TObject *Sender) +{ + REdit->CutToClipboard(); +} +//--------------------------------------------------------------------------- +void __fastcall TFileEdit::KECPClick(TObject *Sender) +{ + REdit->CopyToClipboard(); +} +//--------------------------------------------------------------------------- +void __fastcall TFileEdit::KEPClick(TObject *Sender) +{ + REdit->PasteFromClipboard(); +} +//--------------------------------------------------------------------------- +void __fastcall TFileEdit::KEUClick(TObject *Sender) +{ + if( REdit->HandleAllocated() ){ + SendMessage(REdit->Handle, EM_UNDO, 0, 0); + } +} +//--------------------------------------------------------------------------- +void __fastcall TFileEdit::KEAClick(TObject *Sender) +{ + REdit->SelectAll(); +} +//--------------------------------------------------------------------------- +void __fastcall TFileEdit::KEClick(TObject *Sender) +{ + KEU->Enabled = REdit->Modified; + KEC->Enabled = REdit->SelLength; + KECP->Enabled = KEC->Enabled; + KEP->Enabled = ::IsClipboardFormatAvailable(CF_TEXT); +} +//--------------------------------------------------------------------------- +void __fastcall TFileEdit::KFAClick(TObject *Sender) +{ + AnsiString FileName = m_FileName.c_str(); + SetEXT(FileName.c_str(), ""); + LPCSTR pEXT = GetEXT(m_FileName.c_str()); + SaveDialog->FileName = FileName; + SaveDialog->DefaultExt = pEXT; + if( !strcmpi(pEXT, "SUM") ) SaveDialog->FilterIndex = 2; + if( !strcmpi(pEXT, "CHK") ) SaveDialog->FilterIndex = 3; + if( !strcmpi(pEXT, "ANA") ) SaveDialog->FilterIndex = 4; + if( SaveDialog->Execute() ) { + // Options + OverwritePrompt = True thus no need to check. + REdit->Lines->SaveToFile(SaveDialog->FileName); + m_FileName = SaveDialog->FileName; + REdit->Modified = FALSE; + } +} +//--------------------------------------------------------------------------- +void __fastcall TFileEdit::KFXClick(TObject *Sender) +{ + Close(); +} +//--------------------------------------------------------------------------- +void __fastcall TFileEdit::PopupMenuPopup(TObject *Sender) +{ + KEClick(NULL); + for( int i = 0; i < PopupMenu->Items->Count; i++ ){ + PopupMenu->Items->Items[i]->Enabled = KE->Items[i]->Enabled; + } +} +//--------------------------------------------------------------------------- +void __fastcall TFileEdit::KSSClick(TObject *Sender) +{ + FindDialog->Execute(); +} +//--------------------------------------------------------------------------- +void __fastcall TFileEdit::FindDialogFind(TObject *Sender) +{ + int FoundAt, StartPos, ToEnd; + // 検索は現在選択されている場所から開始される + // 何も選択されていない場合は, + // テキストの最初から開始される + if(REdit->SelLength){ + StartPos = REdit->SelStart + REdit->SelLength; + } + else { + StartPos = 0; + } + // ToEnd は検索範囲の文字数を示す + ToEnd = REdit->Text.Length() - StartPos; + + + TSearchTypes stype; + if( FindDialog->Options.Contains(frMatchCase) ) stype << stMatchCase; + if( FindDialog->Options.Contains(frWholeWord) ) stype << stWholeWord; + FoundAt = REdit->FindText(FindDialog->FindText, StartPos, ToEnd, stype); + if( FoundAt != -1 ){ + REdit->SetFocus(); + REdit->SelStart = FoundAt; + REdit->SelLength = FindDialog->FindText.Length(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TFileEdit::KSClick(TObject *Sender) +{ + KSN->Enabled = !FindDialog->FindText.IsEmpty(); +} +//--------------------------------------------------------------------------- +void __fastcall TFileEdit::KFNClick(TObject *Sender) +{ + Close(); + + char bf[256]; + sprintf(bf, "NOTEPAD %s", m_FileName.c_str()); + WinExec(bf, SW_SHOWDEFAULT); +} +//--------------------------------------------------------------------------- + + diff --git a/JASTA/FEdit.dfm b/JASTA/FEdit.dfm new file mode 100644 index 0000000..dfc6dd0 Binary files /dev/null and b/JASTA/FEdit.dfm differ diff --git a/JASTA/FEdit.h b/JASTA/FEdit.h new file mode 100644 index 0000000..8cd9041 --- /dev/null +++ b/JASTA/FEdit.h @@ -0,0 +1,66 @@ +//--------------------------------------------------------------------------- +#ifndef FEditH +#define FEditH +//--------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +//--------------------------------------------------------------------------- +#include "ComLib.h" +#include +//--------------------------------------------------------------------------- +class TFileEdit : public TForm +{ +__published: // IDE 管理のコンポーネント + TRichEdit *REdit; + TMainMenu *MainMenu1; + TMenuItem *KF; + TMenuItem *KE; + TMenuItem *KFA; + TMenuItem *KEC; + TMenuItem *KECP; + TMenuItem *KEP; + TSaveDialog *SaveDialog; + TMenuItem *N1; + TMenuItem *KEU; + TMenuItem *N2; + TMenuItem *KEA; + TMenuItem *N3; + TMenuItem *KFX; + TPopupMenu *PopupMenu; + TFindDialog *FindDialog; + TMenuItem *KS; + TMenuItem *KSS; + TMenuItem *KSN; + TMenuItem *KFN; + void __fastcall FormCloseQuery(TObject *Sender, bool &CanClose); + + void __fastcall KECClick(TObject *Sender); + void __fastcall KECPClick(TObject *Sender); + void __fastcall KEPClick(TObject *Sender); + void __fastcall KFAClick(TObject *Sender); + void __fastcall KEUClick(TObject *Sender); + void __fastcall KEAClick(TObject *Sender); + + void __fastcall KEClick(TObject *Sender); + void __fastcall KFXClick(TObject *Sender); + void __fastcall PopupMenuPopup(TObject *Sender); + + void __fastcall KSSClick(TObject *Sender); + void __fastcall FindDialogFind(TObject *Sender); + void __fastcall KSClick(TObject *Sender); + void __fastcall KFNClick(TObject *Sender); + +private: // ユーザー宣言 + AnsiString m_FileName; +public: // ユーザー宣言 + __fastcall TFileEdit(TComponent* Owner); + void __fastcall Execute(LPCSTR pName); +}; +//--------------------------------------------------------------------------- +extern PACKAGE TFileEdit *FileEdit; +//--------------------------------------------------------------------------- +#endif diff --git a/JASTA/LogConv.cpp b/JASTA/LogConv.cpp new file mode 100644 index 0000000..3509c65 --- /dev/null +++ b/JASTA/LogConv.cpp @@ -0,0 +1,2033 @@ +//--------------------------------------------------------------------------- +#include +#pragma hdrstop + +#include +#include "LogConv.h" +#include "country.h" +#include "main.h" +CLogText LogText; +//*************************************************************************** +// CLogConv 基本 クラス +CLogConv::CLogConv() +{ + m_Mode = 0; + m_fp = NULL; +} + +CLogConv::~CLogConv() +{ +} +//*************************************************************************** +// CLogText クラス +CLogText::CLogText() +{ + m_Type = 0; + m_Double = 0; + m_Delm = 0; + m_err = 0; + m_UTC = (lcid != LANG_JAPANESE) ? 1 : 0; + int i; + for( i = 0; i < TEXTCONVMAX; i++ ){ + m_tConv[i].Key = ""; + m_tConv[i].w = 0; + } + m_tConv[0].Key = "%YYYY-MM-DD"; + m_tConv[1].Key = "%HHMM"; + m_tConv[2].Key = "%EHHMM"; + m_tConv[3].Key = "%CALL"; + m_tConv[4].Key = "%HIS"; + m_tConv[5].Key = "%MY"; + m_tConv[6].Key = "%FREQ"; + m_tConv[7].Key = "%MODE"; + m_tConv[8].Key = "%POWER"; + m_tConv[9].Key = "%NAME"; + m_tConv[10].Key = "%QTH"; + m_tConv[11].Key = "%REM"; + m_tConv[12].Key = "%QSL"; + m_tConv[13].Key = "%S"; + m_tConv[14].Key = "%R"; + m_tConv[15].Key = "%EOD"; + for( i = 0; i < TEXTCONVMAX; i++ ){ + m_rConv[i] = m_tConv[i]; + } +} +//--------------------------------------------------------------------------- +// テキストファイルのオープン +int CLogText::Open(LPCSTR pName) +{ + Close(); + m_Mode = 0; + m_err = 0; + + m_fp = fopen(pName, "rt"); + + if( m_fp != NULL ){ + setvbuf(m_fp, NULL, _IOFBF, 16384); + m_FileName = pName; + m_Mode = 0; + return TRUE; + } + else { + ErrorMB( MsgEng ? "Can't open '%s'":"'%s'がオープンできません.", pName); + return FALSE; + } +} +//--------------------------------------------------------------------------- +// テキストファイルの作成 +int CLogText::Create(LPCSTR pName) +{ + Close(); + m_Mode = 1; + + m_fp = fopen(pName, "wt"); + if( m_fp != NULL ){ + setvbuf(m_fp, NULL, _IOFBF, 16384); + m_FileName = pName; + m_Mode = 0; + return TRUE; + } + else { + ErrorMB( MsgEng ? "Can't write to '%s'":"'%s'が作成できません.", pName); + return FALSE; + } +} +//--------------------------------------------------------------------------- +// テキストファイルのオープン +int CLogText::Close(void) +{ + int r = 0; + if( m_fp != NULL ){ + r = fclose(m_fp); + m_fp = NULL; + if( r ){ + ErrorMB( MsgEng ? "Can't close '%s'":"'%s'が正しくクローズできませんでした.", m_FileName.c_str()); + } + else if( m_Mode ){ + InfoMB(MsgEng ? "Done (write to '%s')":"'%s'への書きこみを終了しました.", m_FileName.c_str()); + } + } + return r ? FALSE : TRUE; +} +//--------------------------------------------------------------------------- +// テキストファイルの読み出し +int CLogText::Read(SDMMLOG *sp) +{ + if( !IsOpen() ) return FALSE; + + if( !feof(m_fp) ){ + if( fgets(m_bf, sizeof(m_bf), m_fp) != NULL ){ + ClipLF(m_bf); + return Text2MMLOG(sp, m_bf, m_err); + } + else { + return FALSE; + } + } + else { + return FALSE; + } +} +//--------------------------------------------------------------------------- +// 出力変換 +int CLogText::Write(SDMMLOG *sp) +{ + if( !IsOpen() ) return FALSE; + + MMLOG2Text(m_bf, sp); + fputs(m_bf, m_fp); + fputs("\n", m_fp); + return ferror(m_fp) ? FALSE : TRUE; +} + +const LPCSTR ConvTbl[]={ + "%NULL", + "%YYYY-MM-DD", "%YY-MM-DD", "%YYYY/MM/DD", "%YY/MM/DD", + "%DD MON, YYYY","%YYMMDD", "%YYYYMMDD", + "%YY", "%YYYY", "%MM", "%MON", "%MON2", "%DD", "%HHMM", "%HH:MM","%HH:MM:SS", + "%EHHMM", "%EHH:MM", "%EHH:MM:SS", "%CALL", + "%M", "%MY", "%HIS", "%MYRST", "%HISRST", "%MYNR", "%HISNR", "%FREQ", "%KHZ", + "%MBAND", "%MODE", "%POWER", "%NAME", "%QTH", "%REM", "%QSL", + "%S", "%R", "%ENV", "%OPT1", "%OPT2", "%USR1", "%USR2", + "%EOD", + NULL, +}; + +const char *MONT1[]={"","JAN","FEB","MAR","APR","MAY","JUN","JUL","AUG","SEP","OCT","NOV","DEC"}; +const char *MONT2[]={"","Jan.","Feb.","Mar.","Apr.","May","June","July","Aug.","Sept.","Oct.","Nov.","Dec."}; + +//--------------------------------------------------------------------------- +void MMLOG2Text(LPSTR t, SDMMLOG *sp, AnsiString &Key) +{ + int tim, l; + + if( Key == "%YYYY-MM-DD" ){ + sprintf(t, "%04u-%02u-%02u", YEAR(sp->year), sp->date/100, sp->date%100); + } + else if( Key == "%YY-MM-DD" ){ + sprintf(t, "%2u-%02u-%02u", sp->year, sp->date/100, sp->date%100); + } + else if( Key == "%YYYY/MM/DD" ){ + sprintf(t, "%04u/%02u/%02u", YEAR(sp->year), sp->date/100, sp->date%100); + } + else if( Key == "%YY/MM/DD" ){ + sprintf(t, "%2u/%02u/%02u", sp->year, sp->date/100, sp->date%100); + } + else if( Key == "%DD MON, YYYY" ){ + sprintf(t, "%02u %s, %04u", sp->date%100, MONT1[sp->date/100], YEAR(sp->year)); + } + else if( Key == "%YYYYMMDD" ){ + sprintf(t, "%04u%02u%02u", YEAR(sp->year), sp->date/100, sp->date%100); + } + else if( Key == "%YYMMDD" ){ + sprintf(t, "%02u%02u%02u", sp->year, sp->date/100, sp->date%100); + } + else if( Key == "%YY" ){ + sprintf(t, "%02u", sp->year); + } + else if( Key == "%YYYY" ){ + sprintf(t, "%04u", YEAR(sp->year)); + } + else if( Key == "%MM" ){ + sprintf(t, "%02u", sp->date / 100); + } + else if( Key == "%MON" ){ + strcpy(t, MONT1[sp->date/100]); + } + else if( Key == "%MON2" ){ + strcpy(t, MONT2[sp->date/100]); + } + else if( Key == "%DD" ){ + sprintf(t, "%02u", sp->date % 100); + } + else if( Key == "%HHMM" ){ + if( sp->btime ){ + tim = sp->btime / 30; + sprintf(t, "%02u%02u", tim / 60, tim % 60); + } + else { + *t = 0; + } + } + else if( Key == "%HH:MM" ){ + if( sp->btime ){ + tim = sp->btime / 30; + sprintf(t, "%02u:%02u", tim / 60, tim % 60); + } + else { + *t = 0; + } + } + else if( Key == "%HH:MM:SS" ){ + if( sp->btime ){ + tim = sp->btime / 30; + sprintf(t, "%02u:%02u:%02u", tim / 60, tim % 60, (sp->btime * 2) % 60); + } + else { + *t = 0; + } + } + else if( Key == "%EHHMM" ){ + if( sp->etime ){ + tim = sp->etime / 30; + sprintf(t, "%02u%02u", tim / 60, tim % 60); + } + else { + *t = 0; + } + } + else if( Key == "%EHH:MM" ){ + if( sp->etime ){ + tim = sp->btime / 30; + sprintf(t, "%02u:%02u", tim / 60, tim % 60); + } + else { + *t = 0; + } + } + else if( Key == "%EHH:MM:SS" ){ + if( sp->etime ){ + tim = sp->btime / 30; + sprintf(t, "%02u:%02u:%02u", tim / 60, tim % 60, (sp->etime * 2) % 60); + } + else { + *t = 0; + } + } + else if( Key == "%CALL" ){ + strcpy(t, sp->call); + } + else if( Key == "%M" ){ + *t = sp->send; + *(t+1) = 0; + } + else if( Key == "%HIS" ){ + strcpy(t, sp->ur); + } + else if( Key == "%MY" ){ + strcpy(t, sp->my); + } + else if( Key == "%HISRST" ){ + StrCopy(t, sp->ur, GetLMode(sp->mode)); + } + else if( Key == "%MYRST" ){ + StrCopy(t, sp->my, GetLMode(sp->mode)); + } + else if( Key == "%HISNR" ){ + l = GetLMode(sp->mode); + if( (int)strlen(sp->ur) >= l ){ + strcpy(t, &sp->ur[l]); + } + else { + *t = 0; + } + } + else if( Key == "%MYNR" ){ + l = GetLMode(sp->mode); + if( (int)strlen(sp->my) >= l ){ + strcpy(t, &sp->my[l]); + } + else { + *t = 0; + } + } + else if( Key == "%FREQ" ){ + strcpy(t, Log.GetFreqString(sp->band, sp->fq)); + } + else if( Key == "%MBAND" ){ + strcpy(t, FreqTomBand(sp)); + } + else if( Key == "%KHZ" ){ + char bf[32]; + double dd; + strcpy(bf, Log.GetFreqString(sp->band, sp->fq)); + sscanf(bf, "%lf", &dd); + sprintf(t, "%.2lf", dd * 1000.0); + } + else if( Key == "%MODE" ){ + strcpy(t, Log.GetModeString(sp->mode)); + } + else if( Key == "%POWER" ){ + strcpy(t, sp->pow); + } + else if( Key == "%NAME" ){ + strcpy(t, sp->name); + } + else if( Key == "%QTH" ){ + strcpy(t, sp->qth); + } + else if( Key == "%REM" ){ + strcpy(t, sp->rem); + } + else if( Key == "%QSL" ){ + strcpy(t, sp->qsl); + } + else if( Key == "%S" ){ + *t = sp->send; + *(t+1) = 0; + } + else if( Key == "%R" ){ + *t = sp->recv; + *(t+1) = 0; + } + else if( Key == "%ENV" ){ + sprintf(t, "%u", sp->env); + } + else if( Key == "%OPT1" ){ + strcpy(t, sp->opt1); + } + else if( Key == "%OPT2" ){ + strcpy(t, sp->opt2); + } + else if( Key == "%USR1" ){ + strcpy(t, Log.GetOptStr(2, sp)); + } + else if( Key == "%USR2" ){ + strcpy(t, Log.GetOptStr(3, sp)); + } + else if( (Key == "%EOD")||(Key == "%NULL") ){ + *t = 0; + } + else { + strcpy(t, Key.c_str()); + } +} +//--------------------------------------------------------------------------- +// 1行の出力変換 +void CLogText::MMLOG2Text(LPSTR t, SDMMLOG *sp) +{ + char bf[512]; + char dlm = m_Delm ? TAB : ','; + + if( m_UTC ) JSTtoUTC(sp); + int i; + for( i = 0; i < TEXTCONVMAX; i++ ){ + if( (!m_tConv[i].Key.IsEmpty())&&(m_tConv[i].Key != "%EOD") ){ + ::MMLOG2Text(bf, sp, m_tConv[i].Key); + switch(m_Delm){ + case 0: // CSV + case 1: // TAB + if( i ) *t++ = dlm; + if( m_Double || (strchr(bf, dlm) != NULL) ) *t++ = 0x22; + if( m_tConv[i].w ){ + StrCopy(t, bf, m_tConv[i].w); + } + else { + strcpy(t, bf); + } + t += strlen(t); + if( m_Double || (strchr(bf, dlm) != NULL) ) *t++ = 0x22; + break; + default: // Format Text + if( m_tConv[i].w ){ + StrCopy(t, bf, m_tConv[i].w); + FillSpace(t, m_tConv[i].w); + } + else { + strcpy(t, bf); + } + t += strlen(t); + break; + } + } + else { + break; + } + } + *t = 0; +} +//--------------------------------------------------------------------------- +int GetMonth(LPCSTR p) +{ + for( int i = 1; i <=12; i++ ){ + if( !strcmpi(MONT1[i], p) ) return i; + if( !strcmpi(MONT2[i], p) ) return i; + } + return 0; +} +//--------------------------------------------------------------------------- +int Text2MMLOG(SDMMLOG *sp, LPCSTR s, AnsiString &Key) +{ + int y, m, d, h; + int tim; + + if( (Key == "%YYYY-MM-DD")||(Key == "%YY-MM-DD") ){ + if( sscanf(s, "%u-%u-%u", &y, &m, &d) != 3 ) return FALSE; + sp->year = BYTE(y % 100); + sp->date = WORD(m * 100 + d); + } + else if( (Key == "%YYYY/MM/DD")||(Key == "%YY/MM/DD") ){ + if( sscanf(s, "%u/%u/%u", &y, &m, &d) != 3 ) return FALSE; + sp->year = BYTE(y % 100); + sp->date = WORD(m * 100 + d); + } + else if( Key == "%DD MON, YYYY" ){ + d = atoin(s, 2); + s += 3; + char bf[4]; + StrCopy(bf, s, 3); + m = GetMonth(bf); + s = SkipSpace(s+1); + y = atoin(s, -1); + sp->year = BYTE(y % 100); + sp->date = WORD(m * 100 + d); + } + else if( Key == "%YYYYMMDD" ){ + y = atoin(s, 4); s += 4; + m = atoin(s, 2); s += 2; + d = atoin(s, 2); + sp->year = BYTE(y % 100); + sp->date = WORD(m * 100 + d); + } + else if( Key == "%YYMMDD" ){ + y = atoin(s, 2); s += 2; + m = atoin(s, 2); s += 2; + d = atoin(s, 2); + sp->year = BYTE(y % 100); + sp->date = WORD(m * 100 + d); + } + else if( (Key == "%YY")||(Key == "%YYYY") ){ + if( sscanf(s, "%u", &y) != 1 ) return FALSE; + sp->year = BYTE(y % 100); + } + else if( Key == "%MM" ){ + if( sscanf(s, "%u", &m) != 1 ) return FALSE; + sp->date = WORD((sp->date % 100) + m * 100); + } + else if( (Key == "%MON")||(Key == "%MON2") ){ + m = GetMonth(s); + sp->date = WORD((sp->date % 100) + m * 100); + } + else if( Key == "%DD" ){ + if( sscanf(s, "%u", &d) != 1 ) return FALSE; + sp->date = WORD(((sp->date / 100) * 100) + d); + } + else if( Key == "%HHMM" ){ + if( *s ){ + if( sscanf(s, "%u", &d) != 1 ) return FALSE; + h = d / 100; + m = d % 100; + tim = (h * 60 + m) * 30; + if( !tim ) tim++; + sp->btime = WORD(tim); + } + } + else if( (Key == "%HH:MM")||(Key == "%HH:MM:SS") ){ + if( *s ){ + if( sscanf(s, "%u:%u:%u", &h, &m, &d ) != 3 ){ + d = 0; + if( sscanf(s, "%u:%u", &h, &m) != 2 ) return FALSE; + } + tim = (h * 60 + m) * 30 + (d / 2); + if( !tim ) tim++; + sp->btime = WORD(tim); + } + } + else if( Key == "%EHHMM" ){ + if( *s ){ + if( sscanf(s, "%u", &d) != 1 ) return FALSE; + h = d / 100; + m = d % 100; + tim = (h * 60 + m) * 30; + if( !tim ) tim++; + sp->etime = WORD(tim); + } + } + else if( (Key == "%EHH:MM")||(Key == "%EHH:MM:SS") ){ + if( *s ){ + if( sscanf(s, "%u:%u:%u", &h, &m, &d ) != 3 ){ + d = 0; + if( sscanf(s, "%u:%u", &h, &m) != 2 ) return FALSE; + } + tim = (h * 60 + m) * 30 + (d / 2); + if( !tim ) tim++; + sp->etime = WORD(tim); + } + } + else if( Key == "%CALL" ){ + if( sp->call[0] ){ + char bf[256]; + sprintf(bf, "%s/%s", sp->call, s); + StrCopy(sp->call, bf, MLCALL); + } + else { + StrCopy(sp->call, s, MLCALL); + } + } + else if( Key == "%M" ){ + sp->send = *s; + } + else if( (Key == "%HIS")||(Key == "%HISRST") ){ + StrCopy(sp->ur, s, MLRST); + } + else if( (Key == "%MY")||(Key=="%MYRST") ){ + StrCopy(sp->my, s, MLRST); + } + else if( Key == "%FREQ" ){ + Log.SetFreq(sp, s); + } + else if( Key == "%MBAND" ){ + mBandToBand(sp, s); + } + else if( Key == "%KHZ" ){ + double dd; + sscanf(s, "%lf", &dd); + char bf[32]; + sprintf(bf, "%.03lf", dd / 1000.0); + Log.SetFreq(sp, bf); + } + else if( Key == "%MODE" ){ + Log.SetMode(sp, s); + } + else if( Key == "%POWER" ){ + StrCopy(sp->pow, s, MLPOW); + } + else if( Key == "%NAME" ){ + StrCopy(sp->name, s, MLNAME); + } + else if( Key == "%QTH" ){ + StrCopy(sp->qth, s, MLQTH); + } + else if( Key == "%REM" ){ + StrCopy(sp->rem, s, MLREM); + } + else if( Key == "%QSL" ){ + StrCopy(sp->qsl, s, MLQSL); + } + else if( Key == "%S" ){ + sp->send = *s; + } + else if( Key == "%R" ){ + sp->recv = *s; + } + else if( Key == "%ENV" ){ + if( sscanf(s, "%u", &d) != 1 ) return FALSE; + sp->env = WORD(d); + } + else if( Key == "%OPT1" ){ + StrCopy(sp->opt1, s, MLOPT); + } + else if( Key == "%OPT2" ){ + StrCopy(sp->opt2, s, MLOPT); + } + else if( Key == "%USR1" ){ + Log.SetOptStr(2, sp, s); + } + else if( Key == "%USR2" ){ + Log.SetOptStr(3, sp, s); + } + else if( (Key != "%EOD")&&(Key != "%NULL") ){ + if( Key != s ){ + return FALSE; + } + } + return TRUE; +} +//--------------------------------------------------------------------------- +// 1行の入力変換 +int CLogText::Text2MMLOG(SDMMLOG *sp, LPSTR p, int &err) +{ + char bf[512]; + char dlm = m_Delm ? TAB : ','; + LPSTR t; + + memset(sp, 0, sizeof(SDMMLOG)); + int i; + for( i = 0; i < TEXTCONVMAX; i++ ){ + if( (!m_rConv[i].Key.IsEmpty())&&(m_rConv[i].Key != "%EOD") ){ + if( m_Delm == 2 ){ + StrCopy(bf, p, m_rConv[i].w); + p += strlen(bf); + t = bf; + } + else { + p = StrDlm(t, p, dlm); + } + clipsp(t); + t = SkipSpace(t); + if( ::Text2MMLOG(sp, t, m_rConv[i].Key ) == FALSE ){ + if( !err ){ + ErrorMB(MsgEng ? "An error occurred with conversion type [%s]." : "変換式[%s]でエラーが発生しました.", m_rConv[i].Key.c_str() ); + } + err++; + } + } + else { + break; + } + } + if( !sp->etime ) sp->etime = sp->btime; + if( m_UTC ) UTCtoJST(sp); + return err ? FALSE : TRUE; +} +// +// +//*************************************************************************** +// CLog200 クラス +CLog200::CLog200() +{ + m_Type = 1; + m_err = 0; +} +//--------------------------------------------------------------------------- +// LOG200ファイルのオープン +int CLog200::Open(LPCSTR pName) +{ + Close(); + m_Index = 0; + m_err = 0; + + m_fp = fopen(pName, "rb"); + if( m_fp != NULL ){ + m_FileName = pName; + m_Mode = 0; + return TRUE; + } + else { + ErrorMB("'%s'がオープンできません.", pName); + return FALSE; + } +} +//--------------------------------------------------------------------------- +// LOG200ファイルの作成 +int CLog200::Create(LPCSTR pName) +{ + Close(); + m_Mode = 1; + m_err = 0; + + int add = 0; + if( (m_fp = fopen(pName, "rb"))!=NULL ){ + fclose(m_fp); + m_fp = NULL; + add = 1; + char BackName[256]; + strcpy(BackName, pName); + SetEXT(BackName, ".BAK"); + int r = YesNoCancelMB( "'%s'は既に存在しています.\r\nMMTTYはこのファイルにデータを追加します.\r\n\r\n" + "この操作を実行する前に元のログファイルのバックアップファイル\r\n\r\n" + "'%s' -> '%s'\r\n\r\nを作成しますか?\r\n\r\n" + "[重要]\r\n念のためにバックアップを作成する事をお勧めします.", pName, pName, BackName); + if( r == IDYES ){ + CWaitCursor w; + if( ::CopyFile(pName, BackName, FALSE) == FALSE ){ + ErrorMB("バックアップの作成に失敗しました.\r\nこの処理は中断されます.元のログファイルは変更されません."); + return FALSE; + } + } + else if( r == IDCANCEL ){ + return FALSE; + } + } + m_fp = fopen(pName, add ? "ab":"wb"); + if( m_fp != NULL ){ + m_FileName = pName; + m_Mode = 0; + return TRUE; + } + else { + ErrorMB( "'%s'が作成できません.", pName); + return FALSE; + } +} +//--------------------------------------------------------------------------- +// LOG200ファイルのクローズ +int CLog200::Close(void) +{ + int r = 0; + if( m_fp != NULL ){ + r = fclose(m_fp); + m_fp = NULL; + if( r ){ + ErrorMB("'%s'が正しくクローズできませんでした.", m_FileName.c_str()); + } + else if( m_Mode ){ + InfoMB("'%s'への追加を終了しました.", m_FileName.c_str()); + } + } + return r ? FALSE : TRUE; +} +//--------------------------------------------------------------------------- +// LOG200 -> MMLOG フォーマットの変換 +void LOG200toMMLOG(SDMMLOG *sp, LPSTR s) +{ + LPSTR t; + int y, m, d, h, tim; + char bf[256]; + + memset(sp, 0, sizeof(SDMMLOG)); + s = StrDlm(t, s, 0x1e); /* DATE */ + y = atoin(t, 2); t += 2; + m = atoin(t, 2); t += 2; + d = atoin(t, 2); + sp->year = BYTE(y % 100); + sp->date = WORD(m * 100 + d); + + s = StrDlm(t, s, 0x1e); /* BGN */ + d = atoin(t, 4); + h = d / 100; + m = d % 100; + tim = (h * 60 + m) * 30; + if( !tim ) tim++; + sp->btime = WORD(tim); + + s = StrDlm(t, s, 0x1e); /* END */ + d = atoin(t, 4); + h = d / 100; + m = d % 100; + tim = (h * 60 + m) * 30; + if( !tim ) tim++; + sp->etime = WORD(tim); + + s = StrDlm(t, s, 0x1e); /* CALL */ + clipsp(t); + StrCopy(sp->call, t, MLCALL); + + s = StrDlm(t, s, 0x1e); /* FREQ */ + if( LastC(t) == '.' ){ + *lastp(t) = 0; + } + Log.SetFreq(sp, t); + + s = StrDlm(t, s, 0x1e); /* MODE */ + Log.SetMode(sp, t); + + s = StrDlm(t, s, 0x1e); /* RST */ + clipsp(t); + StrCopy(sp->ur, t, MLRST); + + s = StrDlm(t, s, 0x1e); /* MyRST*/ + clipsp(t); + StrCopy(sp->my, t, MLRST); + + s = StrDlm(t, s, 0x1e); /* QTH */ + clipsp(t); + StrCopy(sp->qth, t, MLQTH); + + s = StrDlm(t, s, 0x1e); /* NAME */ + clipsp(t); + StrCopy(sp->name, t, MLNAME); + + s = StrDlm(t, s, 0x1e); /* RIG */ + clipsp(t); + LPSTR pRIG = t; + + s = StrDlm(t, s, 0x1e); /* CONTEST */ + clipsp(t); + LPSTR pContest = t; + + s = StrDlm(t, s, 0x1e); /* Rem */ + clipsp(t); + + if( (strlen(sp->call) == 15) && (RemoveL2(bf, t, "CALL", sizeof(bf)-1) == TRUE) ){ + StrCopy(sp->call, bf, MLCALL); + } + if( RemoveL2(bf, t, "POW", sizeof(bf)-1) == TRUE ){ + StrCopy(sp->pow, bf, MLPOW); + } + if( RemoveL2(bf, t, "ENV", sizeof(bf)-1) == TRUE ){ + sp->env = WORD(atoin(bf, -1)); + } + if( RemoveL2(bf, t, "M", sizeof(bf)-1) == TRUE ){ + sp->cq = bf[0]; + } + if( RemoveL2(bf, t, "OPT1", sizeof(bf)-1) == TRUE ){ + StrCopy(sp->opt1, bf, MLOPT); + } + if( RemoveL2(bf, t, "OPT2", sizeof(bf)-1) == TRUE ){ + StrCopy(sp->opt2, bf, MLOPT); + } + if( RemoveL2(bf, t, "USR1", sizeof(bf)-1) == TRUE ){ + Log.SetOptStr(2, sp, bf); + } + if( RemoveL2(bf, t, "USR2", sizeof(bf)-1) == TRUE ){ + Log.SetOptStr(3, sp, bf); + } + if( RemoveL2(bf, t, "MQSL", sizeof(bf)-1) == TRUE ){ + StrCopy(sp->qsl, bf, MLQSL); + } + clipsp(t); + t = SkipSpace(t); + StrCopy(sp->rem, t, MLREM); + + s = StrDlm(t, s, 0x1e); /* MyQTH*/ + if( *t ) AddL2(sp->qsl, "MyQTH", t, '[', ']', MLQSL); + + s = StrDlm(t, s, 0x1e); /* MyRig*/ + if( *t ) AddL2(sp->qsl, "MyRIG", t, '[', ']', MLQSL); + + s = StrDlm(t, s, 0x1e); /* Send */ + sp->send = *t; + StrDlm(t, s, 0x1e); /* Recv */ + sp->recv = *t; + + if( *pRIG ) AddL2(sp->qsl, "RIG", pRIG, '[', ']', MLQSL); + if( *pContest ) AddL2(sp->qsl, "TEST", pContest, '[', ']', MLQSL); +} +//--------------------------------------------------------------------------- +// LOG200ファイルの読み出し +int CLog200::Read(SDMMLOG *sp) +{ + if( !IsOpen() ) return FALSE; + + if( fread(m_bf, 1, 200, m_fp) == 200 ){ + LOG200toMMLOG(sp, m_bf); + m_Index++; + return TRUE; + } + else { + return FALSE; + } +} + +//--------------------------------------------------------------------------- +// MMLOG -> LOG200フォーマット変換 +void MMLOGtoLOG200(LPSTR t, SDMMLOG *sp, int &err) +{ + LPSTR s = t; + int h, m; + char bf[256]; + + memset(t, ' ', 200); + // YYMMDD + sprintf(t, "%02u%02u%02u\x1e", sp->year, sp->date / 100, sp->date % 100); + t += strlen(t); + // BGN(HHMM) + h = sp->btime / 1800; + m = (sp->btime % 1800) / 30; + sprintf(t, "%02u%02u\x1e", h, m); + t += strlen(t); + // END + h = sp->etime / 1800; + m = (sp->etime % 1800) / 30; + sprintf(t, "%02u%02u\x1e", h, m); + t += strlen(t); + // CALL + StrCopy(t, sp->call, 15); // 15文字に制限されている + t += strlen(t); + *t++ = 0x1e; + // FREQ + sprintf(bf, "%s", Log.GetFreqString(sp->band, sp->fq)); + if( bf[0] ){ + double dd; + if( sscanf(bf, "%lf", &dd) == 1 ){ + sprintf(bf, "%.3lf", dd); + } + } + strcpy(t, bf); + t += strlen(t); + *t++ = 0x1e; + // MODE + sprintf(t, "%s\x1e", Log.GetModeString(sp->mode)); + t += strlen(t); + // HisRST + sprintf(t, "%s\x1e", sp->ur); + t += strlen(t); + // MyRST + sprintf(t, "%s\x1e", sp->my); + t += strlen(t); + // QTH + sprintf(t, "%s\x1e", sp->qth); + t += strlen(t); + // NAME + sprintf(t, "%s\x1e", sp->name); + t += strlen(t); + // RIG + if( RemoveL2(bf, sp->qsl, "Rig", sizeof(bf)-1) == TRUE ){ + strcpy(t, bf); + } + *t++ = 0x1e; + // CONTEST + if( RemoveL2(bf, sp->qsl, "TEST", sizeof(bf)-1) == TRUE ){ + strcpy(t, bf); + } + *t++ = 0x1e; + char MyRig[200]; + char MyQTH[200]; + MyRig[0] = MyQTH[0] = 0; + if( RemoveL2(bf, sp->qsl, "MyRig", sizeof(bf)-1) == TRUE ){ + strcpy(MyRig, bf); + } + if( RemoveL2(bf, sp->qsl, "MyQTH", sizeof(bf)-1) == TRUE ){ + strcpy(MyQTH, bf); + } + clipsp(sp->qsl); + LPSTR p = SkipSpace(sp->qsl); + + // REM + strcpy(bf, sp->rem); + char bbf[128]; + if( strlen(sp->call) > 11 ){ + AddL2(bf, "CALL", sp->call, '[', ']', MLQSL); + } + if( sp->cq ){ + bbf[0] = sp->cq; bbf[1] = 0; + AddL2(bf, "M", bbf, '[', ']', MLQSL); + } + if( sp->pow[0] ) AddL2(bf, "POW", sp->pow, '[', ']', MLQSL); + if( sp->env ){ + sprintf(bbf, "%u", sp->env); + AddL2(bf, "ENV", bbf, '[', ']', MLQSL); + } + if( sp->opt1[0] ) AddL2(bf, "OPT1", sp->opt1, '[', ']', MLQSL); + if( sp->opt2[0] ) AddL2(bf, "OPT2", sp->opt2, '[', ']', MLQSL); + LPCSTR pp = Log.GetOptStr(2, sp); + if( *pp ) AddL2(bf, "USR1", pp, '[', ']', MLQSL); + pp = Log.GetOptStr(3, sp); + if( *pp ) AddL2(bf, "USR2", pp, '[', ']', MLQSL); + + if( *p ) AddL2(bf, "MQSL", p, '[', ']', MLQSL); + int len = (t - s) + strlen(bf) + 1 + strlen(MyQTH) + 1 + strlen(MyRig) + 1 + 2; + if( len >= 199 ){ + if( !err ){ + err++; + WarningMB("変換した結果がLOG200レコード長を越えました.\r\n\r\nリマークフィールドの長さを調整します."); + } + len -= 199; + bf[strlen(bf)-len] = 0; + } + + sprintf(t, "%s\x1e", bf); + t += strlen(t); + + // MyQTH + sprintf(t, "%s\x1e", MyQTH); + t += strlen(t); + // MyRIG + sprintf(t, "%s\x1e", MyRig); + t += strlen(t); + // S + if( sp->send ) *t++ = sp->send; + *t++ = 0x1e; + // R + if( sp->recv ) *t++ = sp->recv; + *t = 0x1e; + + s[198] = '\r'; s[199] = '\n'; +} +//--------------------------------------------------------------------------- +// LOG200ファイルの書きこみ +int CLog200::Write(SDMMLOG *sp) +{ + if( !IsOpen() ) return FALSE; + + MMLOGtoLOG200(m_bf, sp, m_err); + if( fwrite(m_bf, 1, 200, m_fp) != 200 ){ + ErrorMB("'%s'に書き込み中にエラーが発生しました.", m_FileName.c_str()); + return FALSE; + } + else { + m_Index++; + return TRUE; + } +} +// +// +//*************************************************************************** +// CHamLog クラス +//--------------------------------------------------------------------------- +CHamLog::CHamLog() +{ + m_Type = 2; + m_err = 0; + + m_DBRName = ""; // DBRファイルの名前 + m_dbrfp = NULL; // DBRファイルのファイルポインタ +} +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- +// HamLogファイルのオープン +int CHamLog::Open(LPCSTR pName) +{ + Close(); + m_Index = 0; + m_err = 0; + m_Mode = 0; + + m_fp = fopen(pName, "rb"); // DBSのオープン + + if( m_fp == NULL ){ + ErrorMB( "'%s'がオープンできません.", pName); + return FALSE; + } + m_FileName = pName; + if( (fread(&m_hd, 1, sizeof(m_hd), m_fp)!=sizeof(m_hd)) || + (m_hd.Memo != 0x1a) || + (m_hd.HeadLen != 449) || + (m_hd.DataLen != sizeof(m_RecBuf)) + ){ + fclose(m_fp); + m_fp = NULL; + ErrorMB("予期しないファイル形式です."); + return FALSE; + } + char dbrName[256]; + strcpy(dbrName, pName); + SetEXT(dbrName, ".DBR"); + m_DBRName = dbrName; + m_dbrfp = fopen(dbrName, "rb"); + if( m_dbrfp == NULL ){ + WarningMB( "'%s'がオープンできません.", dbrName); + } + else if( fread(&m_dbrhd, 1, sizeof(m_dbrhd), m_dbrfp)!=sizeof(m_dbrhd) ){ + ErrorMB( "'%s'が正常に読みこめません. 処理を中断します.", dbrName); + fclose(m_fp); + m_fp = NULL; + fclose(m_dbrfp); + m_dbrfp = NULL; + return FALSE; + } + + if( Seek(0) == FALSE ){ + Close(); + ErrorMB("最初のレコードが見つかりません."); + return FALSE; + } + return TRUE; +} + +int CHamLog::Close(void) +{ + int r = 0; + if( m_fp != NULL ){ + if( m_Mode ){ // 書きこみ + fseek(m_fp, 0, SEEK_SET); + if( fwrite(&m_hd, 1, sizeof(m_hd), m_fp) != sizeof(m_hd) ) r = 1; + } + if( fclose(m_fp) ) r = 1;; + m_fp = NULL; + } + if( m_dbrfp != NULL ){ + if( m_Mode ){ + fseek(m_dbrfp, 0, SEEK_SET); + if( fwrite(&m_dbrhd, 1, sizeof(m_dbrhd), m_dbrfp) != sizeof(m_dbrhd) ) r = 1; + } + if( fclose(m_dbrfp) ) r = 1; + m_dbrfp = NULL; + } + if( r ){ + ErrorMB("ファイルのクローズに失敗しました."); + } + else if( m_Mode ){ + InfoMB("'%s'への追加を終了しました.", m_FileName.c_str()); + } + return r ? FALSE : TRUE; +} + +//---------------------------------------------------------------------- +int CHamLog::Seek(DWORD Index) +{ + long Pos = 449 + (Index * sizeof(m_RecBuf)); + if( fseek(m_fp, Pos, SEEK_SET) ) return FALSE; + m_Index = Index; + return TRUE; +} + +//--------------------------------------------------------------------------- +// HamLogファイルの読み出し +int CHamLog::Read(SDMMLOG *sp) +{ + if( !IsOpen() ) return FALSE; + + Seek(m_Index); + if( fread(&m_RecBuf, 1, sizeof(m_RecBuf), m_fp) == sizeof(m_RecBuf) ){ + HAMLOGtoMMLOG(sp, &m_RecBuf, m_dbrfp); + m_Index++; + return TRUE; + } + else { + return FALSE; + } +} +//---------------------------------------------------------------------- +//HAMLOGの周波数記録方式を通常の文字列に変換 +void DecBand(LPSTR t, BYTE *pBand) +{ + if( pBand[3] & 0x80 ){ // 5〜7文字の文字列 + int DotPos = pBand[3] & 0x7f; + int Len = (DotPos >> 3) & 0x07; + DotPos &= 0x07; + LPSTR p = t; + wsprintf(p, "%-7lu", (*((LONG *)pBand) & 0x00ffffffL)); + if( Len < 4 ){ // Ver3.19までの記録方式 + for(int i = 6; i > 3; i--){ + if(p[i]>'0'){ + break; + } + else if(p[i] == '0'){ + p[i] = ' '; + } + } + } + else { + if( Len < 6 ) p[6] = ' '; + if( Len == 4 ) p[5] = ' '; + } + p[DotPos] = '.'; + p[8] = 0; + } + else { // そのまま + StrCopy(t, (LPCSTR)pBand, 4); + } + clipsp(t); + if( LastC(t) == '.' ){ + *lastp(t) = 0; + } +} + +void SetMMLOGKey(SDMMLOG *sp, LPSTR bf) +{ + char rbf[512]; + + if( RemoveL2(rbf, bf, "ToRadio", sizeof(rbf)-1) == TRUE ){ + StrCopy(sp->call, rbf, MLCALL); + } + else if( RemoveL2(rbf, bf, "CALL", sizeof(rbf)-1) == TRUE ){ + StrCopy(sp->call, rbf, MLCALL); + } + + if( RemoveL2(rbf, bf, "ENV", sizeof(rbf)-1) == TRUE ){ + sp->env = WORD(atoin(rbf, -1)); + } + if( RemoveL2(rbf, bf, "END", sizeof(rbf)-1) == TRUE ){ + int tim = atoin(rbf, -1); + int hh = tim / 100; + int mm = tim % 100; + sp->etime = WORD((hh * 60 + mm) * 30); + if( !sp->etime ) sp->etime++; + } + if( RemoveL2(rbf, bf, "POW", sizeof(rbf)-1) == TRUE ){ + StrCopy(sp->pow, rbf, MLPOW); + } + if( RemoveL2(rbf, bf, "M", sizeof(rbf)-1) == TRUE ){ + sp->cq = rbf[0]; + } + if( RemoveL2(rbf, bf, "SN", sizeof(rbf)-1) == TRUE ){ + strcat(sp->ur, rbf); + } + if( RemoveL2(rbf, bf, "RN", sizeof(rbf)-1) == TRUE ){ + strcat(sp->my, rbf); + } +} +//--------------------------------------------------------------------------- +// HamLog -> MMLOG フォーマットの変換 +void HAMLOGtoMMLOG(SDMMLOG *sp, SDHAMLOG *hp, FILE *dbrfp) +{ + int CallOrder = 0; + char bf[512]; + + memset(sp, 0, sizeof(SDMMLOG)); + DecBand(bf, (BYTE *)hp->freq); + Log.SetFreq(sp, bf); + + StrCopy(bf, hp->mode, 3); + clipsp(bf); + if( !strcmp(bf, Log.m_LogSet.m_THRTTY.c_str()) || !strcmp(bf, "RTY") || !strcmp(bf, "TTY") || !strcmp(bf, "RTT") ){ + strcpy(bf, "RTTY"); + } + else if( !strcmp(bf, Log.m_LogSet.m_THSSTV.c_str()) || !strcmp(bf, "STV")|| !strcmp(bf, "SST") ){ + strcpy(bf, "SSTV"); + } + else if( !strcmp(bf, "FTV") ){ + strcpy(bf, "FSTV"); + } + Log.SetMode(sp, bf); + + StrCopy(sp->name, hp->name, 12); + clipsp(sp->name); + + sprintf(sp->ur, "%02u", BYTE(hp->hiss[0])); + if( hp->hiss[1] != ' ' ) sp->ur[2] = hp->hiss[1]; + + sprintf(sp->my, "%02u", BYTE(hp->myrs[0])); + if( hp->myrs[1] != ' ' ) sp->my[2] = hp->myrs[1]; + + int YY, MM, DD, HH, mm; + YY = hp->date[0] & 0x007f; + YY %= 100; + MM = hp->date[1]; + DD = hp->date[2]; + HH = hp->time[0]; + mm = hp->time[1] & 0x7f; + if( hp->time[1] & 0x80 ){ + UTCtoJST(YY, MM, DD, HH); + } + sp->year = BYTE(YY); + sp->date = WORD(MM * 100 + DD); + sp->btime = WORD(((HH * 60 + mm) * 30)); + if(!sp->btime) sp->btime++; + + if( hp->ofs && (dbrfp != NULL) ){ + FHDDBR fhdbr; + if( fseek(dbrfp, hp->ofs, SEEK_SET) ) goto _ex; + if( fread(&fhdbr, 1, sizeof(fhdbr), dbrfp) != sizeof(fhdbr) ){ + goto _ex; + } + if( fhdbr.LenQTH ){ + if( fread(bf, 1, fhdbr.LenQTH, dbrfp)!=size_t(fhdbr.LenQTH) ){ + goto _ex; + } + bf[fhdbr.LenQTH] = 0; + clipsp(bf); + StrCopy(sp->qth, bf, MLQTH); + } + if( fhdbr.LenREM1 ){ + if( fread(bf, 1, fhdbr.LenREM1, dbrfp)!=size_t(fhdbr.LenREM1) ){ + goto _ex; + } + bf[fhdbr.LenREM1] = 0; + SetMMLOGKey(sp, bf); + clipsp(bf); + if( strstr(bf, "$DX" ) != NULL ) CallOrder = 1; + StrCopy(sp->rem, SkipSpace(bf), MLREM); + } + if( fhdbr.LenREM2 ){ + if( fread(bf, 1, fhdbr.LenREM2, dbrfp)!=size_t(fhdbr.LenREM2) ){ + goto _ex; + } + bf[fhdbr.LenREM2] = 0; + SetMMLOGKey(sp, bf); + clipsp(bf); + if( strstr(bf, "$DX" ) != NULL ) CallOrder = 1; + StrCopy(sp->qsl, SkipSpace(bf), MLQSL); + } + } +_ex:; + sprintf(bf, "QSL[%.3s]", hp->qsl); + Log.SetOptStr(2, sp, bf); + if( hp->qsl[0] == 'N' ){ + sp->send = 'N'; + } + else if( hp->send[0] == ' ' ){ // 未発送 + if( (hp->qsl[0] == 'J')||(hp->qsl[0] == ' ') ){ + sp->send = 0; + } + else { + sp->send = BYTE(tolower(hp->qsl[0])); + } + } + else { // 発送済み + sp->send = BYTE(toupper(hp->send[0])); + } + sp->recv = hp->rcv[0]; + if( sp->recv == ' ' ) sp->recv = 0; + + StrCopy(sp->opt1, hp->code, 6); + StrCopy(sp->opt2, hp->glid, 6); + + if( !sp->call[0] ){ + if( CallOrder && (hp->potbl[0] != ' ') ){ /* KH6/JE3HHTの形式 */ + StrCopy(bf, hp->potbl, 3); + clipsp(bf); + strcat(sp->call, bf); + if( sp->call[0] ) strcat(sp->call, "/"); + StrCopy(bf, hp->calls, 7); + clipsp(bf); + strcat(sp->call, bf); + } + else { /* JE3HHT/KH6の形式 */ + StrCopy(bf, hp->calls, 7); + clipsp(bf); + strcat(sp->call, bf); + if( hp->potbl[0] != ' ' ){ + if( sp->call[0] ) strcat(sp->call, "/"); + StrCopy(bf, hp->potbl, 3); + clipsp(bf); + strcat(sp->call, bf); + } + } + } + if( !sp->etime ) sp->etime = sp->btime; +} +//---------------------------------------------------------------------- +//文字列のコピー(ヌルはセットされない) +void SpaceCopy(LPSTR t, LPCSTR s, int n) +{ + for( ; n && *s; s++, t++, n-- ){ + *t = *s; + } +} +//---------------------------------------------------------------------- +//RST文字列をHAMLOG形式に変換して格納 +void SetRST(char *pRST, LPCSTR p, BYTE mode) +{ + char rs[3]; + int rst; + + StrCopy(rs, p, 2); + if( sscanf(rs, "%d", &rst) == 1 ){ + *pRST = BYTE(rst); + } + else { + *pRST = 59; + } + if( strlen(p) < 3 ) return; + if( GetLMode(mode) == 2 ) return; + pRST[1] = *(p+2); +} +//---------------------------------------------------------------------- +//周波数の文字列をHAMLOGの周波数記録方式に変換 +void EncBand(BYTE *pBand, LPCSTR pStr) +{ + char bf[32]; + StrCopy(bf, pStr, 7); + + int Len = strlen(bf); + if( Len <= 4 ){ + memset(pBand, ' ', 4); + SpaceCopy(LPSTR(pBand), bf, 4); + } + else { + LPSTR p = strchr(bf, '.'); + int DotPos; + if( p != NULL ){ + DotPos = p - bf; + *p = '0'; + } + else { + DotPos = Len; + } + long Freq; + sscanf(bf, "%lu", &Freq); + *(ULONG *)pBand = Freq; + pBand[3] = BYTE(0x0080 | (Len << 3) | DotPos); + } +} + +void AddMMLOGKey(AnsiString &REM1, AnsiString &REM2, LPCSTR s, LPCSTR pKey) +{ + if( !*s ) return; + + int len1 = strlen(REM1.c_str()); + int len2 = strlen(REM2.c_str()); + int len = strlen(s); + if( pKey == NULL ){ + len++; + } + else { + len += strlen(pKey) + 3; + } + AnsiString *ap; + if( (len2 + len) < 54 ){ + ap = &REM2; + } + else if( (len1 + len) < 54 ){ + ap = &REM1; + } + else { + return; + } + if( !ap->IsEmpty() ){ + *ap += " "; + } + if( pKey != NULL ){ + *ap += pKey; + *ap += '['; + } + *ap += s; + if( pKey != NULL ){ + *ap += ']'; + } +} +//--------------------------------------------------------------------------- +// MMLOG -> HamLog フォーマットの変換 +int MMLOGtoHAMLOG(SDHAMLOG *hp, SDMMLOG *sp, FILE *dbrfp) +{ + char bf[512]; + + int CallOrder = FALSE; + memset(hp, ' ', sizeof(SDHAMLOG)); + int YY = sp->year; + int MM = sp->date / 100; + int DD = sp->date % 100; + int tim = sp->btime / 30; + int HH = tim / 60; + int mm = tim % 60; + switch(Log.m_LogSet.m_THTZ){ + case 0: + if( !IsJA(sp->call) ){ + JSTtoUTC(YY, MM, DD, HH); + mm |= 0x80; + } + break; + case 1: + JSTtoUTC(YY, MM, DD, HH); + mm |= 0x80; + break; + default: + break; + } + hp->date[0] = BYTE(YY < 50 ? YY + 128 : YY); + hp->date[1] = BYTE(MM); + hp->date[2] = BYTE(DD); + hp->time[0] = BYTE(HH); + hp->time[1] = BYTE(mm); + + SpaceCopy(hp->name, sp->name, 12); + SpaceCopy(hp->code, sp->opt1, 6); + SpaceCopy(hp->glid, sp->opt2, 6); + AnsiString QTH = sp->qth; + AnsiString REM1 = sp->rem; + AnsiString REM2 = sp->qsl; + + strcpy(bf, sp->call); + LPSTR pp, p2, t; + t = bf; + if( (pp = strchr(bf, '/')) != NULL ){ // KH6/JE3HHT or JE3HHT/KH6 の形式 + *pp = 0; + pp++; + int LenC = strlen(t); + int LenP = strlen(pp); + if( ((p2 = strchr(pp, '/')) != NULL)|| + (LenC > 7) || + (LenP > 7) || + ((LenC > LenP) && (LenP>3)) || + ((LenC < LenP) && (LenC>3)) + ){ + // HAMLOGでは表現できない表記の場合 + AddMMLOGKey(REM1, REM2, sp->call, "ToRadio"); + if( p2 != NULL ){ + *p2 = 0; + LenP = strlen(pp); + } + } + if( LenC < LenP ){ + p2 = t; + t = pp; + pp = p2; + CallOrder = TRUE; + } + SpaceCopy(hp->potbl, pp, 3); + } + else if( strlen(t) > 7 ){ + AddMMLOGKey(REM1, REM2, sp->call, "ToRadio"); + } + SpaceCopy(hp->calls, t, 7); + strcpy(bf, Log.GetModeString(sp->mode)); + if( !strcmp(bf, "RTTY") ){ + StrCopy(bf, Log.m_LogSet.m_THRTTY.c_str(), 3); + } + else if( !strcmp(bf, "SSTV") ){ + StrCopy(bf, Log.m_LogSet.m_THSSTV.c_str(), 3); + } + else if( !strcmp(bf, "FSTV") ){ + strcpy(bf, "FTV"); + } + else if( !strcmp(bf, "BPSK") ){ + strcpy(bf, "PSK"); + } + else if( !strcmp(bf, "QPSK") ){ + strcpy(bf, "PSK"); + } + SpaceCopy(hp->mode, bf, 3); + SetRST(hp->hiss, sp->ur, sp->mode); + SetRST(hp->myrs, sp->my, sp->mode); + + int l = GetLMode(sp->mode); + if( sp->ur[l] ) AddMMLOGKey(REM1, REM2, &sp->ur[l], "SN"); + if( sp->my[l] ) AddMMLOGKey(REM1, REM2, &sp->my[l], "RN"); + + strcpy(bf, Log.GetFreqString(sp->band, sp->fq)); + EncBand((BYTE *)hp->freq, bf); + + + if( CallOrder && (!strstr(sp->rem, "$DX")) && (!strstr(sp->qsl, "$DX")) ){ + AddMMLOGKey(REM1, REM2, "$DX", NULL); + } + + if( sp->etime ){ + tim = sp->etime / 30; + sprintf(bf, "%02u%02u", tim / 60, tim % 60); + AddMMLOGKey(REM1, REM2, bf, "END"); + } + if( sp->env ){ + sprintf(bf, "%u", sp->env); + AddMMLOGKey(REM1, REM2, bf, "ENV"); + } + AddMMLOGKey(REM1, REM2, sp->pow, "POW"); + if( sp->cq ){ + bf[0] = sp->cq; bf[1] = 0; + AddMMLOGKey(REM1, REM2, bf, "M"); + } + strcpy(bf, Log.GetOptStr(2, sp)); + char rbf[32]; + if(RemoveL2(rbf, bf, "QSL", sizeof(rbf)-1) == TRUE){ + hp->qsl[0] = rbf[0]; + hp->send[0] = rbf[1]; + hp->rcv[0] = rbf[2]; + } + else { + hp->rcv[0] = sp->recv; + if( !hp->rcv[0] ) hp->rcv[0] = ' '; + if( sp->send == 'N' ){ + hp->qsl[0] = 'N'; + hp->send[0] = ' '; + } + else if( !sp->send ){ + hp->qsl[0] = 'J'; + hp->send[0] = ' '; + } + else if( (sp->send >= 0x60)||(sp->send == '?') ){ + hp->qsl[0] = BYTE(toupper(sp->send)); + hp->send[0] = ' '; + } + else if( isalpha(sp->send) ){ + hp->qsl[0] = sp->send; + hp->send[0] = '*'; + } + else { + hp->qsl[0] = 'J'; + hp->send[0] = sp->send; + } + } + + if( !QTH.IsEmpty() || !REM1.IsEmpty() || !REM2.IsEmpty() ){ + FHDDBR fhdbr; + memset(&fhdbr, 0, sizeof(fhdbr)); + hp->ofs = ftell(dbrfp); + fhdbr.LenQTH = BYTE(strlen(QTH.c_str())); + fhdbr.LenREM1 = BYTE(strlen(REM1.c_str())); + fhdbr.LenREM2 = BYTE(strlen(REM2.c_str())); + if( fhdbr.LenQTH > 28 ){ + fhdbr.LenQTH = 28; + } + if( fhdbr.LenREM1 > 54 ){ + fhdbr.LenREM1 = 54; + } + if( fhdbr.LenREM2 > 54 ){ + fhdbr.LenREM2 = 54; + } + if( fwrite(&fhdbr, 1, sizeof(fhdbr), dbrfp) != sizeof(fhdbr) ) return FALSE; + if( fhdbr.LenQTH ){ + if( fwrite(QTH.c_str(), 1, fhdbr.LenQTH, dbrfp) != size_t(fhdbr.LenQTH) ) return FALSE; + } + if( fhdbr.LenREM1 ){ + if( fwrite(REM1.c_str(), 1, fhdbr.LenREM1, dbrfp) != size_t(fhdbr.LenREM1) ) return FALSE; + } + if( fhdbr.LenREM2 ){ + if( fwrite(REM2.c_str(), 1, fhdbr.LenREM2, dbrfp) != size_t(fhdbr.LenREM2) ) return FALSE; + } + } + else { + hp->ofs = 0L; + } + return TRUE; +} + +//*************************************************************************** +// CLogADIF クラス +CLogADIF::CLogADIF() +{ + m_bf[sizeof(m_bf)-1] = 0; +} +//--------------------------------------------------------------------------- +// ADIFファイルのオープン +int CLogADIF::Open(LPCSTR pName) +{ + Close(); + m_Mode = 0; + + m_p = NULL; + m_conv = 1; + m_fp = fopen(pName, "rt"); + if( m_fp != NULL ){ + setvbuf(m_fp, NULL, _IOFBF, 16384); + m_FileName = pName; + m_Mode = 0; + return TRUE; + } + else { + ErrorMB(MsgEng ? "Can't open '%s'": "'%s'がオープンできません.", pName); + return FALSE; + } +} +//--------------------------------------------------------------------------- +// ADIFファイルの作成 +int CLogADIF::Create(LPCSTR pName) +{ + Close(); + m_Mode = 1; + + m_fp = fopen(pName, "wt"); + if( m_fp != NULL ){ + setvbuf(m_fp, NULL, _IOFBF, 16384); + m_FileName = pName; + m_Mode = 1; + fprintf(m_fp, "ADIF Export from %s\n", VERTTL); + fprintf(m_fp, "\n\n"); + return TRUE; + } + else { + ErrorMB( MsgEng ? "Can't write to '%s'":"'%s'が作成できません.", pName); + return FALSE; + } +} +//--------------------------------------------------------------------------- +// テキストファイルのオープン +int CLogADIF::Close(void) +{ + int r = 0; + if( m_fp != NULL ){ + r = fclose(m_fp); + m_fp = NULL; + if( r ){ + ErrorMB(MsgEng ? "Can't write to '%s'":"'%s'が正しくクローズできませんでした.", m_FileName.c_str()); + } + else if( m_Mode ){ + InfoMB(MsgEng ? "Done (write to '%s')":"'%s'への書きこみを終了しました.", m_FileName.c_str()); + } + } + return r ? FALSE : TRUE; +} +const char *_BandText[]={ + "","160m","80m","80m","40m","30m","20m","17m","15m","12m","10m","6m", + "2m","70cm","23cm","13cm","6cm","3cm","3cm","1.25cm","6mm", + "4mm","2mm","1mm","65m","1.25m",NULL, +}; +//--------------------------------------------------------------------------- +// ADIFファイルの読み出し +void CLogADIF::SetData(SDMMLOG *sp, LPCSTR pKey, LPSTR pData) +{ + int l; + + if( !strcmpi(pKey, "CALL") ){ + StrCopy(sp->call, pData, MLCALL); + } + else if( !strcmpi(pKey, "QSO_DATE") ){ + sp->year = BYTE(atoin(pData, 4) % 100); + sp->date = WORD(atoin(pData+4, 4)); + } + else if( !strcmpi(pKey, "TIME_ON") ){ + int hh, mm, ss; + hh = atoin(pData, 2); + mm = atoin(pData+2, 2); + ss = pData[4] ? atoin(pData+4, 2) : 0; + sp->btime = WORD((hh * 60 + mm) * 30 + ss); + if( !sp->btime ) sp->btime++; + } + else if( !strcmpi(pKey, "TIME_OFF") ){ + int hh, mm, ss; + hh = atoin(pData, 2); + mm = atoin(pData+2, 2); + ss = pData[4] ? atoin(pData+4, 2) : 0; + sp->btime = WORD((hh * 60 + mm) * 30 + ss); + if( !sp->etime ) sp->btime++; + } + else if( !strcmpi(pKey, "FREQ") ){ + Log.SetFreq(sp, pData); + } + else if( !strcmpi(pKey, "BAND") ){ + if( !sp->band ){ + int i; + for( i = 1; _BandText[i] != NULL; i++ ){ + if( !strcmpi(_BandText[i], pData) ) break; + } + if( _BandText[i] == NULL ) i = 0; + sp->band = BYTE(i); + } + } + else if( !strcmpi(pKey, "MODE") ){ + Log.SetMode(sp, pData); + } + else if( !strcmpi(pKey, "TX_PWR") ){ + StrCopy(sp->pow, pData, MLPOW); + } + else if( !strcmpi(pKey, "RST_SENT") ){ + if( sp->ur[0] ){ + char bf[MLRST+1]; + strcpy(bf, sp->ur); + StrCopy(sp->ur, pData, MLRST); + l = strlen(sp->ur); + StrCopy(&sp->ur[l], bf, MLRST - l); + } + else { + StrCopy(sp->ur, pData, MLRST); + } + } + else if( !strcmpi(pKey, "RST_RCVD") ){ + if( sp->my[0] ){ + char bf[MLRST+1]; + strcpy(bf, sp->my); + StrCopy(sp->my, pData, MLRST); + l = strlen(sp->my); + StrCopy(&sp->my[l], bf, MLRST - l); + } + else { + StrCopy(sp->my, pData, MLRST); + } + } + else if( !strcmpi(pKey, "STX") ){ + l = strlen(sp->ur); + StrCopy(&sp->ur[l], pData, MLRST - l); + } + else if( !strcmpi(pKey, "SRX") ){ + l = strlen(sp->my); + StrCopy(&sp->my[l], pData, MLRST - l); + } + else if( !strcmpi(pKey, "QSL_SENT") ){ + if( *pData == ' ' ) *pData = 0; + sp->send = *pData; + } + else if( !strcmpi(pKey, "QSL_RCVD") ){ + if( *pData == ' ' ) *pData = 0; + sp->recv = *pData; + } + else if( !strcmpi(pKey, "NAME") ){ + StrCopy(sp->name, pData, MLNAME); + } + else if( !strcmpi(pKey, "QTH") ){ + StrCopy(sp->qth, pData, MLQTH); + } + else if( !strcmpi(pKey, "COMMENT") ){ + StrCopy(sp->rem, pData, MLREM); + } + else if( !strcmpi(pKey, "QSLMSG") ){ + StrCopy(sp->qsl, pData, MLQSL); + } + else if( !strcmpi(pKey, "CONT") ){ + StrCopy(sp->opt2, pData, MLOPT); + } +} +//--------------------------------------------------------------------------- +void CLogADIF::AdjustData(SDMMLOG *sp) +{ + if( !sp->etime ) sp->etime = sp->btime; + UTCtoJST(sp); + if( sp->call[0] ){ + LPCSTR pCC = ClipCC(sp->call); + Log.SetOptStr(0, sp, Cty.GetCountry(pCC)); + if( !sp->opt2[0] ) Log.SetOptStr(1, sp, Cty.GetCont(pCC)); + } + if( !sp->ur[0] ) StrCopy(sp->ur, "599", GetLMode(sp->mode)); + if( !sp->my[0] ) StrCopy(sp->my, "599", GetLMode(sp->mode)); +} +//--------------------------------------------------------------------------- +// ADIFファイルの読み出し +int CLogADIF::Read(SDMMLOG *sp) +{ + if( !IsOpen() ) return FALSE; + + LPSTR p, t, tt; + char bf[1024]; + + while(1){ + if( (m_p == NULL) || !(*m_p) ){ + if( !feof(m_fp) ){ + if( fgets(m_bf, sizeof(m_bf), m_fp) != NULL ){ + ClipLF(m_bf); + m_p = m_bf; + } + else if( sp->btime && sp->call[0] && m_conv ){ + AdjustData(sp); + m_p = NULL; + return TRUE; + } + else { + return FALSE; + } + } + else { + return FALSE; + } + } + m_p = SkipSpace(m_p); + if( *m_p == '<' ){ + m_p = StrDlm(p, m_p+1, '>'); + p = StrDlm(t, p, ':'); + p = StrDlm(tt, p, ':'); + bf[0] = 0; + int n = *tt ? atoin(tt, -1) : 0; + if( (n >= 0) && (n < 1023) && (n <= (int)strlen(m_p)) ){ + if( n ) memcpy(bf, m_p, n); + bf[n] = 0; + } + if( !strcmpi(t, "EOR") ){ + if( m_conv ){ + AdjustData(sp); + return TRUE; + } + } + if( !strcmpi(t, "EOH") ){ + m_conv = 1; + } + else if( m_conv ){ + SetData(sp, t, bf); +#if 0 + FILE *fp = fopen("F:\\TEST.TXT", "at"); + fprintf(fp, "%s:%s\n", t, bf); + fclose(fp); +#endif + m_p += n; + } + } + else if( *m_p ){ + m_p++; + } + } +} +//--------------------------------------------------------------------------- +void CLogADIF::OutF(int &col, FILE *fp, LPCSTR fmt, ...) +{ + va_list pp; + char bf[512]; + + va_start(pp, fmt); + vsprintf(bf, fmt, pp ); + va_end(pp); + if( col ){ + fputs(" ", fp); + col++; + } + int l = strlen(bf); + if( (col + l) > 80 ){ + fputs("\n", fp); + col = 0; + } + fputs(bf, fp); + col += l; +} +//--------------------------------------------------------------------------- +// 出力変換 +// +//KD4MUL 19930921 223558 150000 +//3.690 80M CW 100 599 +//599 Y N ROY STRUNK +//KY FIRST CW CONTACT WB4TXW +int CLogADIF::Write(SDMMLOG *sp) +{ + if( !IsOpen() ) return FALSE; + + int col = 0; + JSTtoUTC(sp); + OutF(col, m_fp, "%s", strlen(sp->call), sp->call); + OutF(col, m_fp, "%04u%02u%02u", YEAR(sp->year), sp->date/100, sp->date%100); + int tim = sp->btime / 30; + OutF(col, m_fp, "%02u%02u%02u", tim/60, tim%60, (sp->btime % 30)*2); + tim = sp->etime / 30; + OutF(col, m_fp, "%02u%02u%02u", tim/60, tim%60, (sp->etime % 30)*2); + LPCSTR p = Log.GetFreqString(sp->band, sp->fq); + if( *p ) OutF(col, m_fp, "%s", strlen(p), p); + p = _BandText[sp->band]; + if( *p ) OutF(col, m_fp, "%s", strlen(p), p); + p = Log.GetModeString(sp->mode); + if( *p ) OutF(col, m_fp, "%s", strlen(p), p); + if( sp->pow[0] ) OutF(col, m_fp, "%s", strlen(sp->pow), sp->pow); + int l = GetLMode(sp->mode); + if( Log.m_LogSet.m_ClipRSTADIF ){ + if( sp->ur[l] ) OutF(col, m_fp, "%s", strlen(&sp->ur[l]), &sp->ur[l]); + if( sp->my[l] ) OutF(col, m_fp, "%s", strlen(&sp->my[l]), &sp->my[l]); + sp->ur[GetLMode(sp->mode)] = 0; + sp->my[GetLMode(sp->mode)] = 0; + } + if( sp->ur[0] ) OutF(col, m_fp, "%s", strlen(sp->ur), sp->ur); + if( sp->my[0] ) OutF(col, m_fp, "%s", strlen(sp->my), sp->my); + if( sp->send ) OutF(col, m_fp, "%c", sp->send); + if( sp->recv ) OutF(col, m_fp, "%c", sp->recv); + if( sp->name[0] ) OutF(col, m_fp, "%s", strlen(sp->name), sp->name); + if( sp->qth[0] ) OutF(col, m_fp, "%s", strlen(sp->qth), sp->qth); + if( sp->rem[0] ) OutF(col, m_fp, "%s", strlen(sp->rem), sp->rem); + if( sp->opt2[0] ) OutF(col, m_fp, "%s", strlen(sp->opt2), sp->opt2); + if( sp->qsl[0] ) OutF(col, m_fp, "%s", strlen(sp->qsl), sp->qsl); + OutF(col, m_fp, "\n"); + return ferror(m_fp) ? FALSE : TRUE; +} + + +//*************************************************************************** +// CLogCabrillo クラス +CLogCabrillo::CLogCabrillo() +{ + m_bf[sizeof(m_bf)-1] = 0; +} +//--------------------------------------------------------------------------- +// LogCabrilloファイルのオープン +int CLogCabrillo::Open(LPCSTR pName) +{ + Close(); + m_Mode = 0; + + m_p = NULL; + m_SNR = ""; + m_fp = fopen(pName, "rt"); + if( m_fp != NULL ){ + setvbuf(m_fp, NULL, _IOFBF, 16384); + m_FileName = pName; + m_Mode = 0; + return TRUE; + } + else { + ErrorMB(MsgEng ? "Can't open '%s'": "'%s'がオープンできません.", pName); + return FALSE; + } +} +//--------------------------------------------------------------------------- +// LogCabrilloファイルの作成 +int CLogCabrillo::Create(LPCSTR pName) +{ + Close(); + m_Mode = 1; + + m_fp = fopen(pName, "wt"); + if( m_fp != NULL ){ + setvbuf(m_fp, NULL, _IOFBF, 16384); + m_FileName = pName; + m_Mode = 1; + fprintf( m_fp, "START-OF-LOG: 2.0\n"); + fprintf( m_fp, "ARRL-SECTION: \n" ); + fprintf( m_fp, "CONTEST: <== e.g. ARRL-RTTY, CQ-WW-RTTY, CQ-WPX-RTTY, BARTG-SPRINT, BARTG-RTTY\n"); + fprintf( m_fp, "CALLSIGN: %s\n", sys.m_Call.c_str() ); + fprintf( m_fp, "CATEGORY: <== e.g. SINGLE-OP ALL HIGH, SINGLE-OP-ASSISTED 20M LOW\n" ); + fprintf( m_fp, "CLAIMED-SCORE: \n"); + fprintf( m_fp, "OPERATORS:\n" ); + fprintf( m_fp, "CLUB:\n" ); + fprintf( m_fp, "NAME: <== your name\n" ); + fprintf( m_fp, "ADDRESS: <== your postal address\n" ); + fprintf( m_fp, "SOAPBOX: \n" ); + fprintf( m_fp, "CREATED-BY: %s\n", VERTTL2); + return TRUE; + } + else { + ErrorMB( MsgEng ? "Can't write to '%s'":"'%s'が作成できません.", pName); + return FALSE; + } +} +//--------------------------------------------------------------------------- +// テキストファイルのオープン +int CLogCabrillo::Close(void) +{ + int r = 0; + if( m_fp != NULL ){ + fprintf(m_fp, "END-OF-LOG:\n"); + r = fclose(m_fp); + m_fp = NULL; + if( r ){ + ErrorMB(MsgEng ? "Can't write to '%s'":"'%s'が正しくクローズできませんでした.", m_FileName.c_str()); + } + else if( m_Mode ){ + InfoMB(MsgEng ? "Done (write to '%s')\r\n\r\nMMSSTV did only make QSO section.\r\nEdit to the contest name, category, your name and address, etc... in the file.":"'%s'への書きこみを終了しました.\r\n\r\nMMSSTVはQSOセクションしか作成しません。\r\nコンテスト名、参加カテゴリ等を編集してください.", m_FileName.c_str()); + sprintf(m_bf, "NOTEPAD.EXE %s", m_FileName.c_str()); + WinExec(m_bf, SW_SHOWDEFAULT); + } + } + return r ? FALSE : TRUE; +} +//--------------------------------------------------------------------------- +// LogCabrilloファイルの読み出し +int CLogCabrillo::Read(SDMMLOG *sp) +{ + return FALSE; +} +//--------------------------------------------------------------------------- +// 出力変換 +// +int CLogCabrillo::Write(SDMMLOG *sp) +{ + if( !IsOpen() ) return FALSE; +// "","1.9","3.5","3.8","7","10","14","18","21","24","28","50", +// "144","430","1200","2400","5600","10.1G","10.4G","24G","47G", +// "75G","142G","248G","4630","220",NULL, + const char *_bandc[]={ + "??","1800","3500","3500","7000","10000","14000","18000","21000","24000","28000", + "A", "B","D","E","F","H","I","J","K","M", + "N","P","R","?","C",NULL, + }; + +// "CW","SSB","AM","FM","RTTY","PAC","FAX","SSTV","ATV","TV","FSTV", +// "A1","A2","A3","A3A","A3H","A3J","A4","A5","A5C","A5J", +// "A9","A9C","F1","F2","F3","F4","F5","F9","P0","P1", +// "P2D","P2E","P2F","P3D","P3E","P3F","P9", +// "U1","U2","U3","U4", +// "PSK","BPSK","QPSK","HELL","MFSK", + const char *_modec[]={ + "??", + "CW","PH","PH","FM","RY","RY","??","TV","TV","TV","TV", + "CW","CW","PH","PH","PH","PH","??","??","??","??", + "??","??","RY","RY","FM","??","??","??", + "??","??","??","??","??","??","??","??","??", + "??","??","??","??", + "RY","RY","RY","CW","RY", + NULL, + }; + + JSTtoUTC(sp); + int tim = sp->btime / 30; + char SNO[MLRST+1]; + char RNO[MLRST+1]; + int mno = sp->mode >= MODEMAX ? 0 : sp->mode; + int len = GetLMode(BYTE(mno)); + strcpy(SNO, &sp->ur[len]); + strcpy(RNO, &sp->my[len]); + sp->ur[len] = 0; + sp->my[len] = 0; + fprintf( m_fp, "QSO:%6s %2s %04u-%02u-%02u %02u%02u %-13s %-3s %-6s %-13s %-3s %-6s\n", + _bandc[sp->band], _modec[mno], + (sp->year <= 50) ? sp->year + 2000 : sp->year + 1900, + sp->date / 100, sp->date % 100, + tim/60, tim%60, sys.m_Call.c_str(), + sp->ur, SNO, + sp->call, sp->my, RNO + ); + return ferror(m_fp) ? FALSE : TRUE; +} + + \ No newline at end of file diff --git a/JASTA/LogConv.h b/JASTA/LogConv.h new file mode 100644 index 0000000..2523670 --- /dev/null +++ b/JASTA/LogConv.h @@ -0,0 +1,228 @@ +//--------------------------------------------------------------------------- +#ifndef LogConvH +#define LogConvH +#include "LogFile.h" + +extern const char *MONT1[]; +extern const char *MONT2[]; +extern const char *_BandText[]; +//************************************************************* +// ログ変換の基本クラス +// +class CLogConv +{ +protected: + int m_Type; // 0-TEXT, 1-LOG200, 2-HAMLOG, 3-DBASE + int m_Mode; // 0-Read, 1-Write + FILE *m_fp; + + AnsiString m_FileName; // 変換中のファイル名 +public: + CLogConv(); + virtual ~CLogConv(); + virtual int IsOpen(void){return m_fp != NULL ? 1 : 0;}; + virtual int Open(LPCSTR pName)=0; + virtual int Create(LPCSTR pName)=0; + virtual int Close(void)=0; + virtual int Read(SDMMLOG *sp)=0; + virtual int Write(SDMMLOG *sp)=0; +}; + +#define TEXTCONVMAX 64 +typedef struct { + int w; + AnsiString Key; +}TCONV; + +//************************************************************* +// テキストファイルアクセスのクラス +// +class CLogText : public CLogConv +{ +public: + int m_Double; + int m_Delm; + TCONV m_rConv[TEXTCONVMAX]; + TCONV m_tConv[TEXTCONVMAX]; + int m_UTC; + int m_err; +protected: + char m_bf[2048]; // ファイルバッファ + +private: + int Text2MMLOG(SDMMLOG *sp, LPSTR p, int &err); + void MMLOG2Text(LPSTR t, SDMMLOG *sp); + +public: + CLogText(); + virtual int Open(LPCSTR pName); + virtual int Create(LPCSTR pName); + virtual int Close(void); + virtual int Read(SDMMLOG *sp); + virtual int Write(SDMMLOG *sp); + +}; + +void MMLOG2Text(LPSTR t, SDMMLOG *sp, AnsiString &Key); +int Text2MMLOG(SDMMLOG *sp, LPCSTR s, AnsiString &Key); +extern const LPCSTR ConvTbl[]; +extern CLogText LogText; + +//************************************************************* +// LOG200ファイルアクセスのクラス +// +#define LOG200WIDTH 200 +class CLog200 : public CLogConv +{ +public: + int m_Index; + int m_err; +protected: + char m_bf[200]; // ファイルバッファ +private: +public: + CLog200(); + virtual int Open(LPCSTR pName); + virtual int Create(LPCSTR pName); + virtual int Close(void); + virtual int Read(SDMMLOG *sp); + virtual int Write(SDMMLOG *sp); +}; + +//************************************************************* +// HAMLOGファイルアクセスのクラス +// +#pragma option -a- // パックの指示 +typedef struct { + char Memo; // 03h=メモフィールド無し 83h=メモフィールド有り(HAMLOGでは 1Ah) + char YY, MM, DD; // 最終更新年月日 + long Max; // レコード件数 + WORD HeadLen; // ヘッダの長さ(HAMLOG.DBSは 449) + WORD DataLen; // レコードの長さ(HAMLOG.DBSは 58) + char dummy[20]; // 00h +}DBSHD; + +typedef struct { + char Memo; // 03h=メモフィールド無し 83h=メモフィールド有り(HAMLOGでは 1Ah) + char YY, MM, DD; // 最終更新年月日 + long Max; // レコード件数 + char dm1; + char m1; // 01h + char dm2; + char dummy[21]; // 00h + char dummy2[255-32]; // 00h + char term; // 1ah +}DBRHD; + +typedef struct { + char Name[11]; + BYTE Type; + BYTE dm1[4]; + BYTE Len; + BYTE dm2[15]; +}DBSLOT; + +typedef struct { + char del[1]; /* 削除マーク */ + char calls[7]; /* コールサイン */ + char potbl[3]; /* 移動エリア */ + char code[6]; /* JCCコード */ + char glid[6]; /* グリッドロケーター */ + char freq[4]; /* 周波数 */ + char mode[3]; /* モード */ + char name[12]; /* 氏名 */ + char qsl [1]; /* QSL via */ + char send[1]; /* QSL SEND */ + char rcv[1]; /* QSL RCV */ + char date[3]; /* 日付 */ + char time[2]; /* 時間 */ + char hiss[2]; /* HIS RST */ + char myrs[2]; /* MY RST */ + long ofs; /* HAMLOG.DBR オフセットアドレス */ +}SDHAMLOG; + +typedef struct { /* DBRのフィールド位置データ */ + BYTE LenQTH; + BYTE LenREM1; + BYTE LenREM2; +}FHDDBR; +#pragma option -a. // パック解除の指示 + +class CHamLog : public CLogConv +{ +public: + int m_Index; + int m_err; +protected: + DBSHD m_hd; // DBSヘッダ + SDHAMLOG m_RecBuf; // レコードバッファ + + AnsiString m_DBRName; // DBRファイルの名前 + FILE *m_dbrfp; // DBRファイルのファイルポインタ + DBRHD m_dbrhd; // DBRヘッダ +private: + int Seek(DWORD Index); + +public: + CHamLog(); + virtual int Create(LPCSTR pName){return FALSE;}; + virtual int Open(LPCSTR pName); + virtual int Close(void); + virtual int Read(SDMMLOG *sp); + virtual int Write(SDMMLOG *sp){return FALSE;}; +}; + +void HAMLOGtoMMLOG(SDMMLOG *sp, SDHAMLOG *hp, FILE *dbrfp); +int MMLOGtoHAMLOG(SDHAMLOG *hp, SDMMLOG *sp, FILE *dbrfp); +void AddMMLOGKey(AnsiString &REM1, AnsiString &REM2, LPCSTR s, LPCSTR pKey); + +//************************************************************* +// ADIFアクセスのクラス +// +class CLogADIF : public CLogConv +{ +public: +protected: + char m_bf[1024]; // ファイルバッファ + LPSTR m_p; + int m_conv; +private: + void MMLOG2ADIF(LPSTR t, SDMMLOG *sp); + void SetData(SDMMLOG *sp, LPCSTR pKey, LPSTR pData); + void AdjustData(SDMMLOG *sp); + void OutF(int &col, FILE *fp, LPCSTR fmt, ...); + +public: + CLogADIF(); + virtual int Open(LPCSTR pName); + virtual int Create(LPCSTR pName); + virtual int Close(void); + virtual int Read(SDMMLOG *sp); + virtual int Write(SDMMLOG *sp); + +}; + +//************************************************************* +// Cabrillo アクセスのクラス +// +class CLogCabrillo : public CLogConv +{ +public: +protected: + char m_bf[1024]; // ファイルバッファ + LPSTR m_p; + AnsiString m_SNR; +private: + void MMLOG2Cabrillo(LPSTR t, SDMMLOG *sp); + void AdjustData(SDMMLOG *sp); + +public: + CLogCabrillo(); + virtual int Open(LPCSTR pName); + virtual int Create(LPCSTR pName); + virtual int Close(void); + virtual int Read(SDMMLOG *sp); + virtual int Write(SDMMLOG *sp); +}; + +#endif diff --git a/JASTA/LogFile.cpp b/JASTA/LogFile.cpp new file mode 100644 index 0000000..09a4ff7 --- /dev/null +++ b/JASTA/LogFile.cpp @@ -0,0 +1,1541 @@ +//--------------------------------------------------------------------------- +#include +#pragma hdrstop + +#include +#include +#include +#include "LogFile.h" +#include "Main.h" +CLogFile Log; + + +const char *_mBand[]={ + "","160","80","75","40","30","20","17","15","12","10","6", + "2","430","1200","2400","5600","10.1G","10.4G","24G","47G", + "75G","142G","248G","4630","220","SAT", NULL, +}; +const char *_band[]={ + "","1.9","3.5","3.8","7","10","14","18","21","24","28","50", + "144","430","1200","2400","5600","10.1G","10.4G","24G","47G", + "75G","142G","248G","4630","220","SAT", NULL, +}; +static const char *_mode[]={ + "", + "CW","SSB","AM","FM","RTTY","PAC","FAX","SSTV","ATV","TV","FSTV", + "A1","A2","A3","A3A","A3H","A3J","A4","A5","A5C","A5J", + "A9","A9C","F1","F2","F3","F4","F5","F9","P0","P1", + "P2D","P2E","P2F","P3D","P3E","P3F","P9", + "U1","U2","U3","U4", + "PSK","BPSK","QPSK","HELL","MFSK", + NULL, +}; +const char lmode[]={ + 3, 3, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, + 3, 3, 3, 3, 2, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, + 3, 3, 3, 3, 3, +}; +const char MONN[]={31,31,28,31,30,31,30,31,31,30,31,30,31}; +const char MONU[]={31,31,29,31,30,31,30,31,31,30,31,30,31}; +//--------------------------------------------------------------------------- +// CIndexクラス +int GetLMode(BYTE m) +{ + if( m < MODEMAX ){ + return lmode[m]; + } + else { + return 3; + } +} +//--------------------------------------------------------------------------- +// CIndexクラス +CIndex::CIndex() +{ + m_IndexMax = 0; // 確保中のインデックスの数 + m_IndexCnt = 0; // 現在のインデックスの数 + pIndex = NULL; // インデックス領域のポインタ(16バイトインデックス) + pMult = NULL; +} +CIndex::~CIndex() +{ + if( pIndex != NULL ){ + delete pIndex; + pIndex = NULL; + } + if( pMult != NULL ){ + delete pMult; + pMult = NULL; + } +} +void CIndex::AllocIndex(int n) +{ + if( n >= m_IndexMax ){ + int max = m_IndexMax ? (m_IndexMax * 2) : 32768; + LPSTR np = new char[16*max]; + if( pIndex != NULL ){ + memcpy(np, pIndex, m_IndexCnt*16); + delete pIndex; + } + pIndex = np; + m_IndexMax = max; + } +} + +void CIndex::ClearIndex(void) +{ + m_IndexCnt = 0; +} + +void CIndex::WriteIndex(LPCSTR pCall, int n) +{ + AllocIndex(n); + memcpy(&pIndex[n*16], pCall, 16); + if( n >= m_IndexCnt ) m_IndexCnt = n + 1; +} + +void CIndex::ReadIndex(LPSTR pCall, int n) +{ + memcpy(pCall, &pIndex[n*16], 16); + pCall[16] = 0; +} + +LPSTR CIndex::PointIndex(int n) +{ + return &pIndex[n*16]; +} + +void CIndex::AddBlock(LPCSTR p, int len) +{ + int n = len/16; + AllocIndex(n + m_IndexCnt); + memcpy(&pIndex[m_IndexCnt*16], p, len); + m_IndexCnt += n; +} +//--------------------------------------------------------------------------- +int CIndex::ReadIndex(int handle, FHD *hp) +{ + int r = TRUE; + int BUFSIZE=32768; + + CWaitCursor w; + if( lseek(handle, (hp->size * (ULONG)sizeof(SDMMLOG)) + FHDOFF, SEEK_SET) != -1L ){ + if( hp->hash != 2 ){ // 16バイトインデックスと異なる + if( hp->hash ){ // 2バイトインデックスのスキップ + lseek(handle, hp->size * 2, SEEK_CUR); + } + r = FALSE; + } + else { // 16バイトインデックス + LPSTR bp = new char[BUFSIZE]; + int len = hp->size * 16; + int rlen, wlen; + while(len){ + rlen = (len > BUFSIZE) ? BUFSIZE : len; + wlen = read(handle, bp, rlen); + if( rlen != wlen ){ + r = FALSE; + break; + } + AddBlock(bp, wlen); + len -= wlen; + } + delete bp; + } + if( pMult == NULL ) pMult = new BYTE[32768]; + read(handle, pMult, hp->mlt); + } + else { + r = FALSE; + } + return r; +} + +void CIndex::MakeIndex(int handle, FHD *hp) +{ + CWaitCursor w; + + lseek(handle, (ULONG)FHDOFF, SEEK_SET); + ClearIndex(); + + FHD fh; + memset(&fh, 0, sizeof(fh)); + + int i, rlen; + SDMMLOG sd; + for( i = 0; i < hp->size; i++ ){ + rlen = read(handle, &sd, sizeof(sd)); + if( rlen != sizeof(sd) ) break; + WriteIndex(sd.call, i); + if( sd.mode >= MODEMAX ){ + int m = sd.mode - MODEMAX; + int f = 0; + int n; + char sbf[7]; + StrCopy(sbf, hp->mode[m], 6); + for( n = 0; (n < UMODEMAX) && fh.mode[n][0] ; n++ ){ + char tbf[7]; + StrCopy(tbf, fh.mode[n], 6); + if( !strcmp(sbf, tbf) ){ + if( m != n ){ + f++; + sd.mode = BYTE(n + MODEMAX); + break; + } + } + } + if( !fh.mode[n][0] ){ + StrCopy(fh.mode[n], sbf, 6); + if( m != n ){ + sd.mode = BYTE(n + MODEMAX); + f++; + } + } + if( f ){ + lseek( handle, -long(sizeof(sd)), SEEK_CUR); + write(handle, &sd, sizeof(sd)); + } + } + } + memcpy(hp->mode, fh.mode, sizeof(fh.mode)); + lseek( handle, (hp->size * (ULONG)sizeof(SDMMLOG)) + FHDOFF, SEEK_SET); + hp->hash = 2; // 16バイトインデックス +} + +//--------------------------------------------------------------------------- +int CIndex::WriteIndex(int handle, FHD *hp) +{ + int r = TRUE; + int BUFSIZE=32768; + + CWaitCursor w; + + if( lseek(handle, (hp->size * (ULONG)sizeof(SDMMLOG)) + FHDOFF, SEEK_SET) != -1L ){ + hp->hash = 2; + int len = hp->size * 16; + int vlen, wlen; + LPSTR cp = pIndex; + while(len){ + wlen = (len > BUFSIZE) ? BUFSIZE : len; + vlen = write(handle, cp, wlen); + if( wlen != vlen ) r = FALSE; + len -= vlen; + cp += vlen; + } + if( pMult != NULL ){ + write(handle, pMult, hp->mlt); + } + } + else { + r = FALSE; + } + return r; +} + +//--------------------------------------------------------------------------- +// CLogFindクラス +CLogFind::CLogFind() +{ + m_FindCnt = 0; + pFindTbl = new int[FINDMAX]; +} +//--------------------------------------------------------------------------- +CLogFind::~CLogFind() +{ + delete pFindTbl; + pFindTbl = NULL; +} +//--------------------------------------------------------------------------- +int CLogFind::Add(int n) +{ + if( m_FindCnt >= FINDMAX ) return 0; + + for( int i = 0; i < m_FindCnt; i++ ){ + if( pFindTbl[i] == n ) return 0; + } + pFindTbl[m_FindCnt] = n; + m_FindCnt++; + return 1; +} +//--------------------------------------------------------------------------- +void CLogFind::Ins(int n) +{ + if( m_FindCnt >= FINDMAX ) return; + + int i; + for( i = 0; i < m_FindCnt; i++ ){ + if( pFindTbl[i] == n ) return; + } + for( i = m_FindCnt - 1; i > 0; i-- ){ + pFindTbl[i] = pFindTbl[i-1]; + } + pFindTbl[0] = n; + m_FindCnt++; + m_FindCmp1Max++; + m_FindCmp2Max++; + m_FindStr1Max++; + m_FindStr2Max++; +} +//--------------------------------------------------------------------------- +// CLogFileクラス +CLogFile::CLogFile() +{ + memset(&m_sd, 0, sizeof(SDMMLOG)); + memset(&m_bak, 0, sizeof(SDMMLOG)); + + m_Open = 0; // オープンフラグ + m_EditFlag = 0; + m_Handle = 0; + m_ReadOnly = 0; + memset(&m_fhd, 0, sizeof(m_fhd)); // 現在オープン中のファイルヘッダ + MakePathName("TEMP.MDT"); + m_CurNo = 0; + + // LogSet のデフォルト + + m_LogSet.m_TimeZone = 'I'; // JA + + m_LogSet.m_UpperName = 0; // 大文字への変換 + m_LogSet.m_UpperQTH = 0; // 大文字への変換 + m_LogSet.m_UpperREM = 0; // 大文字への変換 + m_LogSet.m_UpperQSL = 0; // 大文字への変換 + + m_LogSet.m_DefMyRST = 0; // 0-OFF, 1-ON + + m_LogSet.m_CopyFreq = 1; // 0-Band, 1-Freq + m_LogSet.m_CopyHis = 0; // 0-599, 1-599001, 2-599UTC + m_LogSet.m_CopyName = 1; // 0-OFF, 1-ON + m_LogSet.m_CopyQTH = 1; // 0-OFF, 1-ON + m_LogSet.m_CopyREM = 0; // 0-OFF, 1-ON + m_LogSet.m_CopyQSL = 0; // 0-OFF, 1-ON + + m_LogSet.m_AutoSave = 0; + m_LogSet.m_CheckBand = 1; + + m_LogSet.m_THRTTY = "RTY"; + m_LogSet.m_THSSTV = "STV"; + m_LogSet.m_THTZ = 0; + m_LogSet.m_ClipRSTADIF = 1; + m_LogSet.m_DateType = 0; +} + +CLogFile::~CLogFile() +{ + Close(); +} + +void CLogFile::ReadIniFile(LPCSTR pKey, TIniFile *pIniFile) +{ + m_LogSet.m_DateType = pIniFile->ReadInteger(pKey, "DateType", m_LogSet.m_DateType); + m_LogSet.m_TimeZone = (char)pIniFile->ReadInteger(pKey, "TimeZone", m_LogSet.m_TimeZone); + + m_LogSet.m_UpperName = pIniFile->ReadInteger(pKey, "UpperName", m_LogSet.m_UpperName); + m_LogSet.m_UpperQTH = pIniFile->ReadInteger(pKey, "UpperQTH", m_LogSet.m_UpperQTH); + m_LogSet.m_UpperREM = pIniFile->ReadInteger(pKey, "UpperREM", m_LogSet.m_UpperREM); + m_LogSet.m_UpperQSL = pIniFile->ReadInteger(pKey, "UpperQSL", m_LogSet.m_UpperQSL); + + m_LogSet.m_DefMyRST = pIniFile->ReadInteger(pKey, "DefMyRST", m_LogSet.m_DefMyRST); + + m_LogSet.m_CopyFreq = pIniFile->ReadInteger(pKey, "CopyFreq", m_LogSet.m_CopyFreq); + m_LogSet.m_CopyHis = pIniFile->ReadInteger(pKey, "CopyHis", m_LogSet.m_CopyHis); + m_LogSet.m_CopyName = pIniFile->ReadInteger(pKey, "CopyName", m_LogSet.m_CopyName); + m_LogSet.m_CopyQTH = pIniFile->ReadInteger(pKey, "CopyQTH", m_LogSet.m_CopyQTH); + m_LogSet.m_CopyREM = pIniFile->ReadInteger(pKey, "CopyREM", m_LogSet.m_CopyREM); + m_LogSet.m_CopyQSL = pIniFile->ReadInteger(pKey, "CopyQSL", m_LogSet.m_CopyQSL); + + m_LogSet.m_CheckBand = pIniFile->ReadInteger(pKey, "CheckBand", m_LogSet.m_CheckBand); + + m_LogSet.m_AutoSave = pIniFile->ReadInteger(pKey, "AutoSave", m_LogSet.m_AutoSave); + m_LogSet.m_THRTTY = pIniFile->ReadString(pKey, "THRTTY", m_LogSet.m_THRTTY); + m_LogSet.m_THSSTV = pIniFile->ReadString(pKey, "THSSTV", m_LogSet.m_THSSTV); + m_LogSet.m_THTZ = pIniFile->ReadInteger(pKey, "THTZ", m_LogSet.m_THTZ); + m_LogSet.m_ClipRSTADIF = pIniFile->ReadInteger(pKey, "ClipRSTADIF", m_LogSet.m_ClipRSTADIF); +} + +void CLogFile::WriteIniFile(LPCSTR pKey, TIniFile *pIniFile) +{ + pIniFile->WriteInteger(pKey, "TimeZone", m_LogSet.m_TimeZone); + pIniFile->WriteInteger(pKey, "DateType", m_LogSet.m_DateType); + + pIniFile->WriteInteger(pKey, "UpperName", m_LogSet.m_UpperName); + pIniFile->WriteInteger(pKey, "UpperQTH", m_LogSet.m_UpperQTH); + pIniFile->WriteInteger(pKey, "UpperREM", m_LogSet.m_UpperREM); + pIniFile->WriteInteger(pKey, "UpperQSL", m_LogSet.m_UpperQSL); + + pIniFile->WriteInteger(pKey, "DefMyRST", m_LogSet.m_DefMyRST); + + pIniFile->WriteInteger(pKey, "CopyFreq", m_LogSet.m_CopyFreq); + pIniFile->WriteInteger(pKey, "CopyHis", m_LogSet.m_CopyHis); + pIniFile->WriteInteger(pKey, "CopyName", m_LogSet.m_CopyName); + pIniFile->WriteInteger(pKey, "CopyQTH", m_LogSet.m_CopyQTH); + pIniFile->WriteInteger(pKey, "CopyREM", m_LogSet.m_CopyREM); + pIniFile->WriteInteger(pKey, "CopyQSL", m_LogSet.m_CopyQSL); + + pIniFile->WriteInteger(pKey, "CheckBand", m_LogSet.m_CheckBand); + + pIniFile->WriteInteger(pKey, "AutoSave", m_LogSet.m_AutoSave); + pIniFile->WriteString(pKey, "THRTTY", m_LogSet.m_THRTTY); + pIniFile->WriteString(pKey, "THSSTV", m_LogSet.m_THSSTV); + pIniFile->WriteInteger(pKey, "THTZ", m_LogSet.m_THTZ); + pIniFile->WriteInteger(pKey, "ClipRSTADIF", m_LogSet.m_ClipRSTADIF); +} + +void CLogFile::MakeIndex(void) +{ + if( !m_Open ) return; + + m_Index.MakeIndex(m_Handle, &m_fhd); + m_EditFlag = 1; +} + +void CLogFile::MakePathName(LPCSTR pName) +{ + char bf[256]; + + m_Name = pName; + sprintf(bf, "%s%s", LogDir, pName); + SetEXT(bf, ".MDT"); + m_FileName = bf; +} + +void CLogFile::MakeName(LPCSTR pPathName) +{ + if( pPathName != m_FileName.c_str() ) m_FileName = pPathName; + + char drive[_MAX_DRIVE]; + char dir[_MAX_DIR]; + char name[_MAX_FNAME]; + char ext[_MAX_EXT]; + AnsiString Dir; + + ::_splitpath( pPathName, drive, dir, name, ext ); + Dir = drive; + Dir += dir; + strncpy(LogDir, Dir.c_str(), 128); + + m_Name = name; + m_Name += ext; +} + +int CLogFile::Close(void) +{ + int r = TRUE; + if( m_Open ){ + if( m_EditFlag && (!m_ReadOnly) ){ + if( m_fhd.size ){ + SDMMLOG sd; + + GetData(&sd, m_fhd.size - 1); + if( !sd.date || !sd.btime ){ + DeleteLast(); + } + } + chsize(m_Handle, (m_fhd.size * (ULONG)sizeof(SDMMLOG))+(ULONG)FHDOFF ); + m_Index.WriteIndex(m_Handle, &m_fhd); // インデックスの格納 + lseek(m_Handle, 0L, SEEK_SET); + if( write( m_Handle, &m_fhd, sizeof(m_fhd) ) != sizeof(m_fhd) ){ + ErrorFWrite(m_FileName.c_str()); + r = FALSE; + } + } + if( close(m_Handle) ){ + if( r != FALSE ){ + ErrorFWrite(m_FileName.c_str()); + r = FALSE; + } + } + if( !m_fhd.size && (!m_ReadOnly) ) unlink(m_FileName.c_str()); // 0件の時は消去 + m_Open = 0; + } + m_EditFlag = 0; + m_Index.ClearIndex(); + return r; +} + +int CLogFile::Open(LPCSTR pName, int enbwrt) +{ + m_ReadOnly = enbwrt ? 0 : 1; + Close(); + if( pName == NULL ) pName = m_FileName.c_str(); + int f = 0; + if( IsFile(pName) ){ + f = 1; + } + else { + ::Sleep(1000); + } + int OFLAG, SFLAG; + if( m_ReadOnly ){ + OFLAG = O_RDONLY|O_BINARY; + SFLAG = S_IREAD; + } + else { + OFLAG = O_RDWR|O_BINARY|O_CREAT; + SFLAG = S_IREAD|S_IWRITE; + } + if( (m_Handle = open(pName, OFLAG, SFLAG)) > 0 ){ + if( read(m_Handle, &m_fhd, sizeof(m_fhd)) == sizeof(m_fhd) ){ + if( !strcmp(m_fhd.id, MMLOGID) ){ + if( m_Index.ReadIndex(m_Handle, &m_fhd) != TRUE ){ + m_Index.MakeIndex(m_Handle, &m_fhd); + } + m_Open = 1; + MakeName(pName); + m_Find.Clear(); + SetLastPos(); + memcpy(&m_asd, &m_sd, sizeof(m_asd)); + return TRUE; + } + else { + close(m_Handle); + ErrorMB("'%s' is not a correct format.", pName); + } + } + else if( f ){ // 既存のフィアル + close(m_Handle); + ErrorMB("'%s' is not a correct format.", pName); + } + else if( !m_ReadOnly ){ /* 新規ファイル */ + memset(&m_fhd, 0, sizeof(m_fhd)); + strcpy(m_fhd.id, MMLOGID); + m_fhd.size = 0L; + m_fhd.mlt = 0; + if( write(m_Handle, &m_fhd, sizeof(m_fhd)) != sizeof(m_fhd) ){ + close(m_Handle); + ErrorMB("Cannot open '%s'.", pName); + } + else { + m_Open = 1; + MakeName(pName); + m_Index.ClearIndex(); + m_Find.Clear(); + SetLastPos(); + memcpy(&m_asd, &m_sd, sizeof(m_asd)); + return TRUE; + } + } + else { + close(m_Handle); + ErrorMB("Cannot open '%s'.", pName); + return FALSE; + } + } + else if( f && (GetFileAttributes(pName) & FILE_ATTRIBUTE_READONLY) ){ + ErrorMB("'%s' is read-only.", pName); + } + else { + ErrorMB("Cannot open '%s'.", pName); + } + return FALSE; +} + +void CLogFile::InitCur(void) +{ + SetLastPos(); +} + +void CLogFile::SetLastPos(void) +{ + m_CurNo = m_fhd.size; + memset(&m_sd, 0, sizeof(SDMMLOG)); + + int n = m_CurNo - 1; + if( n >= 0 ){ + SDMMLOG sd; + + GetData(&sd, n); + if( !sd.etime ){ + m_CurNo = n; + memcpy(&m_sd, &sd, sizeof(SDMMLOG)); + } + } + else { +#if 0 + if( lcid != LANG_JAPANESE ){ + m_sd.band = B_14; + m_sd.fq = 230; + } + else { + m_sd.band = B_7; + m_sd.fq = 33; + } +#else + m_sd.band = B_14; + m_sd.fq = 230; +#endif + m_sd.mode = 8; + m_sd.env = 1; + } + CopyAF(); + m_CurChg = 0; +} + +int CLogFile::GetData(SDMMLOG *sp, int n) +{ + if( !m_Open || (n >= m_fhd.size) ){ + memset(sp, 0, sizeof(SDMMLOG)); + if( !n ){ + m_sd.band = B_14; + m_sd.mode = 5; + } + return FALSE; + } + if( lseek(m_Handle, (ULONG)FHDOFF + ((ULONG)n * (ULONG)sizeof(SDMMLOG)), SEEK_SET) == -1L ){ + memset(sp, 0, sizeof(SDMMLOG)); + return FALSE; + } + if( read( m_Handle, sp, sizeof(SDMMLOG) ) != sizeof(SDMMLOG) ){ + memset(sp, 0, sizeof(SDMMLOG)); + return FALSE; + } + else { + return TRUE; + } +} + +int CLogFile::PutData(SDMMLOG *sp, int n) +{ + if( m_ReadOnly ) return FALSE; + if( !m_Open ){ + if( m_FileName.IsEmpty() ){ + ErrorMB("ログファイルの名前が定義されていません."); + return FALSE; + } + if( Open(m_FileName.c_str(), TRUE) != TRUE ) return FALSE; + } + if( lseek(m_Handle, (ULONG)FHDOFF + ((ULONG)n * (ULONG)sizeof(SDMMLOG)), SEEK_SET) == -1L ){ + ErrorFWrite(m_FileName.c_str()); + return FALSE; + } + if( write( m_Handle, sp, sizeof(SDMMLOG) ) != sizeof(SDMMLOG) ){ + ErrorFWrite(m_FileName.c_str()); + return FALSE; + } + else { + m_EditFlag = 1; + if( m_CurNo == n ) m_CurChg = 1; + if( n >= m_fhd.size ) m_fhd.size = n + 1; + m_Index.WriteIndex(sp->call, n); + } + return TRUE; +} + +LPCSTR CLogFile::GetOptStr(int n, SDMMLOG *sp) +{ + switch(n){ + case 0: + return sp->opt1; + case 1: + return sp->opt2; + case 2: + if( !sp->ur[MLRST-MLOPT-1] && sp->ur[MLRST-MLOPT] ){ + return &sp->ur[MLRST-MLOPT]; + } + else { + return ""; + } + case 3: + if( !sp->my[MLRST-MLOPT-1] && sp->my[MLRST-MLOPT] ){ + return &sp->my[MLRST-MLOPT]; + } + else { + return ""; + } + default: + return ""; + } +} + +void CLogFile::SetOptStr(int n, SDMMLOG *sp, LPCSTR pOpt) +{ + switch(n){ + case 0: + StrCopy(sp->opt1, pOpt, MLOPT); + jstrupr(sp->opt1); + break; + case 1: + StrCopy(sp->opt2, pOpt, MLOPT); + jstrupr(sp->opt2); + break; + case 2: + if( *pOpt ){ + StrCopy(&sp->ur[MLRST-MLOPT], pOpt, MLOPT); + jstrupr(&sp->ur[MLRST-MLOPT]); + sp->ur[MLRST-MLOPT-1] = 0; + } + else if( !sp->ur[MLRST-MLOPT-1] ){ + sp->ur[MLRST-MLOPT] = 0; + } + break; + case 3: + if( *pOpt ){ + StrCopy(&sp->my[MLRST-MLOPT], pOpt, MLOPT); + jstrupr(&sp->my[MLRST-MLOPT]); + sp->my[MLRST-MLOPT-1] = 0; + } + else if( !sp->my[MLRST-MLOPT-1] ){ + sp->my[MLRST-MLOPT] = 0; + } + break; + default: + break; + } +} + +void CLogFile::SetHisRST(SDMMLOG *sp) +{ + int n, tim; + + switch(m_LogSet.m_CopyHis){ + case 0: + if( sp == NULL ){ + strcpy(m_sd.ur, "595"); + } + else { + strcpy(m_sd.ur, sp->ur); + memcpy(m_sd.ur, "595", 3); + } + break; + case 1: + if( sp == NULL ){ + strcpy(m_sd.ur, "595001"); + } + else { + if( sp->ur[0] ){ + n = atoin(&sp->ur[3], -1); + } + else { + n = 0; + } + n++; + if( n >= 10000 ){ + sprintf(m_sd.ur, "595%04u", n); + } + else { + sprintf(m_sd.ur, "595%03u", n); + } + } + break; + case 2: + if( m_sd.btime ){ + tim = m_sd.btime / 30; + if( tim >= (9 * 60) ){ + tim -= 9 * 60; + } + else { + tim += 15 * 60; + } + sprintf(m_sd.ur, "595%02u%02u", tim/60, tim%60); + } + break; + } +} + +void CLogFile::CopyAF(void) +{ + int n = m_CurNo - 1; + if( n >= 0 ){ + SDMMLOG sd; + GetData(&sd, n); + if( !m_sd.band ){ + m_sd.band = sd.band; + if( m_LogSet.m_CopyFreq ){ + m_sd.fq = sd.fq; + } + else { + m_sd.fq = 0; + } + } + if( !m_sd.env ){ + m_sd.env = sd.env; + } + if( !m_sd.pow[0] ){ + strcpy(m_sd.pow, sd.pow); + } + if( !m_sd.ur[0] ){ + SetHisRST(&sd); + } + } + else { + if( !m_sd.band ){ + m_sd.band = B_14; + m_sd.fq = 0; + } + if( !m_sd.env ){ + m_sd.env = 1; + } + if( !m_sd.ur[0] ){ + SetHisRST(NULL); + } + } + if( !m_sd.mode ) m_sd.mode = 8; // SSTV + if( m_LogSet.m_DefMyRST ){ + if( !m_sd.my[0] ){ + strcpy(m_sd.my, "595"); + } + } +} + +static int _cmpdate(SDMMLOG *s, SDMMLOG *t) +{ + int r = YEAR(s->year) - YEAR(t->year); + if( r ) return r; + r = s->date - t->date; + if( r ) return r; + return s->btime - t->btime; +} + +void CLogFile::SortDate(int bb, int eb) +{ + int gap, i, j, em; + SDMMLOG sd1, sd2; + + if( eb >= m_fhd.size ) eb = m_fhd.size - 1; + CWaitCursor w; + if( bb != eb ){ + em = eb - bb; + for( gap = (em + 1)/2; gap > 0; gap /= 2 ){ + for( i = gap; i <= em; i++ ){ + for( j = i - gap; j >= 0; j -= gap ){ + GetData(&sd1, bb+j); + GetData(&sd2, bb+j+gap); + if( _cmpdate(&sd1, &sd2) <= 0 ) break; + PutData(&sd1, bb+j+gap); + PutData(&sd2, bb+j); + } + } + } + } + m_EditFlag = 1; +} + +int CLogFile::FindSameBand(void) +{ + if( !m_sd.call[0] ) return 0; + char call[MLCALL+1]; + SDMMLOG sd; + + int i; + for( i = 0; i < m_Find.GetCount(); i++ ){ + m_Index.ReadIndex(call, m_Find.pFindTbl[i]); + if( !strcmp(call, m_sd.call) ){ + GetData(&sd, m_Find.pFindTbl[i]); + if( (sd.band == m_sd.band)&&(sd.mode == m_sd.mode) ) return 1; + } + } + return 0; +} + +int CLogFile::FindSameDate(SYSTEMTIME *pUTC) +{ + if( !m_sd.call[0] ) return 0; + char call[MLCALL+1]; + SDMMLOG sd; + + int i; + for( i = 0; i < m_Find.GetCount(); i++ ){ + m_Index.ReadIndex(call, m_Find.pFindTbl[i]); + if( !strcmp(call, m_sd.call) ){ + GetData(&sd, m_Find.pFindTbl[i]); + JSTtoUTC(&sd); + int yy = sd.year + 2000; + int mm = sd.date / 100; + int dd = sd.date % 100; + if( (sd.mode == 8) && (sd.band >= B_14) && (yy == pUTC->wYear) && (mm == pUTC->wMonth) && (dd == pUTC->wDay) ) return 1; + } + } + return 0; +} + +void CLogFile::FindStrSet(CLogFind *fp, LPCSTR pCall) +{ + if( !*pCall ) return; + if( fp->GetCount() >= FINDMAX ) return; + char call[MLCALL+1]; + + int i; + for( i = m_fhd.size - 1; i >= 0; i-- ){ + m_Index.ReadIndex(call, i); + if( strstr(call, pCall)!=NULL ){ + fp->Add(i); + if( fp->GetCount() >= FINDMAX ) break; + } + } +} + +int CLogFile::FindCmpSet(CLogFind *fp, LPCSTR pCall) +{ + if( fp->GetCount() >= FINDMAX ) return 0; + char call[MLCALL+1]; + + int i; + for( i = m_fhd.size - 1; i >= 0; i-- ){ + if( *pCall ){ + m_Index.ReadIndex(call, i); + if( !strcmp(call, pCall) ){ + fp->Write(i); + } + } + else { + fp->Write(i); + } + if( fp->GetCount() >= FINDMAX ) break; + } + return fp->GetCount(); +} + +int CLogFile::FindClipSet(CLogFind *fp, LPCSTR pCall) +{ + if( !*pCall ) return 0; + if( fp->GetCount() >= FINDMAX ) return 0; + char call[MLCALL+1]; + + int i; + for( i = m_fhd.size - 1; i >= 0; i-- ){ + m_Index.ReadIndex(call, i); + if( !strcmp(ClipCall(call), pCall) ){ + fp->Add(i); + } + if( fp->GetCount() >= FINDMAX ) break; + } + return fp->GetCount(); +} + +int CLogFile::FindSet(CLogFind *fp, LPCSTR pCall) +{ + fp->SetText(pCall); + fp->Clear(); + int r = FindCmpSet(fp, pCall); + fp->m_FindCmp1Max = fp->m_FindCnt; + char clipcall[MLCALL+1]; + strcpy(clipcall, ClipCall(pCall)); + if( FindClipSet(fp, clipcall) ){ + r = 1; + } + fp->m_FindCmp2Max = fp->m_FindCnt; + FindStrSet(fp, pCall); + fp->m_FindStr1Max = fp->m_FindStr2Max = fp->m_FindCnt; + if( strcmp(pCall, clipcall) ){ + FindStrSet(fp, clipcall); + fp->m_FindStr2Max = fp->m_FindCnt; + } + return r; +} + +int CLogFile::Find(LPCSTR pCall, int b, int dir) +{ + if( !m_fhd.size ) return -1; + char call[MLCALL+1]; + + int i; + if( dir ){ + for( i = b; i >= 0; i-- ){ + m_Index.ReadIndex(call, i); + if( strstr(call, pCall) != NULL ) return i; + } + } + else { + for( i = b; i < m_fhd.size; i++ ){ + m_Index.ReadIndex(call, i); + if( strstr(call, pCall) != NULL ) return i; + } + } + return -1; +} + +int CLogFile::IsAlready(LPCSTR pCall) +{ + if( !m_fhd.size ) return -1; + char call[MLCALL+1]; + + for( int i = m_CurNo; i >= 0; i-- ){ + m_Index.ReadIndex(call, i); + if( !strcmp(call, pCall) ) return i; + } + return -1; +} + +void CLogFile::DeleteAll(void) +{ + m_fhd.size = 0; + m_CurNo = m_fhd.size; + m_CurChg = 1; + m_EditFlag = 1; +} + +void CLogFile::DeleteLast(void) +{ + if( m_fhd.size ){ + m_fhd.size--; + } + m_CurNo = m_fhd.size; + m_CurChg = 1; + m_EditFlag = 1; +} + +void CLogFile::Delete(int top, int end) +{ + if( !m_fhd.size ) return; + + if( end >= (m_fhd.size - 1) ){ // 最後まで削除する場合 + m_fhd.size = top; + m_CurNo = m_fhd.size; + } + else { // 途中を削除する場合 + int i, j; + SDMMLOG sd; + for( i = top, j = end + 1; j < m_fhd.size; i++, j++ ){ + GetData(&sd, j); + PutData(&sd, i); + } + m_fhd.size -= end - top + 1; + m_CurNo = m_fhd.size; + } + SetLastPos(); + m_CurChg = 1; + m_EditFlag = 1; +} + +void CLogFile::Insert(int n, SDMMLOG *sp) +{ + if( n >= m_fhd.size ){ // 最終位置の場合は追加と同じ + PutData(sp, n); + m_CurNo++; + } + else { // 途中を削除する場合 + int i, j; + SDMMLOG sd; + i = m_fhd.size; + j = i - 1; + for( ; i > n; i--, j-- ){ + GetData(&sd, j); + PutData(&sd, i); + } + PutData(sp, n); + m_CurNo++; + m_CurChg = 0; + } + m_EditFlag = 1; +} + +LPCSTR CLogFile::GetDateString(SDMMLOG *sp, int sw) +{ + static char bf[12]; + + if( sp->date ){ + switch(sw){ + case 1: // yyyy-mm-dd + sprintf(bf, "%04u.%02u.%02u", YEAR(sp->year), sp->date/100, sp->date%100); + break; + case 2: // dd-mm-yy + sprintf(bf, "%02u.%02u.%02u", sp->date%100, sp->date/100, sp->year); + break; + case 3: // dd-mm-yyyy + sprintf(bf, "%02u.%02u.%04u", sp->date%100, sp->date/100, YEAR(sp->year)); + break; + case 4: // mm-dd-yy + sprintf(bf, "%02u.%02u.%02u", sp->date/100, sp->date%100, sp->year); + break; + case 5: // mm-dd-yyyy + sprintf(bf, "%02u.%02u.%04u", sp->date/100, sp->date%100, YEAR(sp->year)); + break; + default: // yy-mm-dd + sprintf(bf, "%02u.%02u.%02u", sp->year, sp->date/100, sp->date%100); + break; + } + } + else { + bf[0] = 0; + } + return bf; +} + +LPCSTR CLogFile::GetTimeString(WORD d) +{ + static char bf[8]; + + if( d ){ + d = WORD(d / 30); + sprintf(bf, "%02u%02u", d / 60, d % 60); + } + else { + bf[0] = 0; + } + return bf; +} + +LPCSTR CLogFile::GetModeString(BYTE m) +{ + if( m < MODEMAX ){ + return _mode[m]; + } + else { + m -= BYTE(MODEMAX); + StrCopy(m_modebuf, m_fhd.mode[m], 6); + return m_modebuf; + } +} + +void CLogFile::SetMode(SDMMLOG *sp, LPCSTR s) +{ + if( !*s ){ + sp->mode = 0; + return; + } + + int n; + const char **t; + char bf[7]; + StrCopy(bf, s, 6); + jstrupr(bf); + s = bf; + int len = strlen(s); + for( n = 0, t = _mode; *t != NULL; t++, n++ ){ + if( !strcmp(*t, s) ){ + sp->mode = BYTE(n); + return; + } + } + for( n = 0; (n < UMODEMAX) && m_fhd.mode[n][0] ; n++ ){ + char vbf[7]; + StrCopy(vbf, m_fhd.mode[n], 6); + if( !strcmp(vbf, s) ){ + sp->mode = BYTE(n + MODEMAX); + return; + } + } + if( n < UMODEMAX ){ + if( len < 6 ){ + strcpy(m_fhd.mode[n], s); + } + else { + memcpy(m_fhd.mode[n], s, 6); + } + sp->mode = BYTE(n + MODEMAX); + } + else { + sp->mode = 0; + } +} + +LPCSTR CLogFile::GetFreqString(BYTE b, short fq) +{ + static char bf[12]; + int d; + + if( fq < 0 ){ + sprintf( bf, "%s/%s", _band[b], _band[-fq]); + return(bf); + } + else if( fq ){ + switch(b){ + case 0: + return ""; + case B_19: /* 1.9 */ + if( fq == 800 ){ + strcpy(bf, "1.8"); + } + else { + sprintf( bf, "1.%03u", fq ); + } + break; + case B_35: /* 3.5 */ + sprintf( bf, "3.%03u", fq ); + break; + case B_38: /* 3.8 */ + sprintf( bf, "3.%03u", fq ); + break; + case B_1200: + d = 1240 + (fq / 100); + sprintf( bf, "%u.%02u", d, fq % 100 ); + break; + case B_2400: + d = 2350 + (fq / 100); + sprintf( bf, "%u.%02u", d, fq % 100 ); + break; + case B_220: + d = 220 + (fq / 1000); + sprintf( bf, "%u.%03u", d, fq % 1000 ); + break; + default: + if( b <= B_24 ){ + sprintf( bf, "%s.%03u", _band[b], fq ); + } + else if( b <= B_430 ){ + d = atoin(_band[b], -1) + (fq / 1000); + sprintf( bf, "%u.%03u", d, fq % 1000 ); + } + else { + return(_band[b]); + } + break; + } + return(bf); + } + else { + return(_band[b]); + } +} + +/*#$% +=============================================================== + バンド番号を得る +--------------------------------------------------------------- + p : 文字列のポインタ +--------------------------------------------------------------- +--------------------------------------------------------------- +=============================================================== +*/ +static BYTE _bandno_(LPCSTR p) +{ + char n; + const char **t; + + for( n = 0, t = _band; *t != NULL; t++, n++ ){ + if( !strcmp(*t, p) ) return(n); + } + return(0); +} + +/*#$% +=============================================================== + バンド番号を得る +--------------------------------------------------------------- + p : 文字列のポインタ +--------------------------------------------------------------- +--------------------------------------------------------------- +=============================================================== +*/ +void CLogFile::SetFreq(SDMMLOG *sp, LPCSTR p) +{ + BYTE n; + char ub[16], db[16]; + int ud, d; + + sp->fq = 0; + if( strchr(p, '/' )!=NULL ){ + p = _strdmcpy(ub, p, '/'); + if( (n = _bandno_(ub))!= 0 ){ + if( (sp->fq = _bandno_(p))!= 0 ){ + sp->fq = SHORT(-sp->fq); + sp->band = n; + return; + } + } + sp->band = 0; + return; + } + if( (n = _bandno_(p))!= 0 ){ + sp->band = n; + return; + } + if( strchr(p, '.')!=NULL ){ + p = _strdmcpy(ub, p, '.'); + memset(db, 0, 4); + strcpy(db, p); + db[3] = 0; + for( n = 0; n < 3; n++ ){ + if( !db[n] ) db[n] = '0'; + } + ud = atoin(ub, -1); + d = atoin(db, -1); + } + else { + ud = atoin(p, -1); + d = 0; + } + if( ud == 1 ){ + sp->fq = SHORT(d); + sp->band = B_19; + } + else if( ud == 3 ){ + sp->fq = SHORT(d); + if( d >= 700 ){ + n = B_38; + } + else { + n = B_35; + } + sp->band = n; + } + else if( (ud >= 7) && (ud <= 24) ){ + sp->fq = SHORT(d); + if( (n = _bandno_(ub))!= 0 ){ + sp->band = n; + return; + } + sp->fq = 0; + sp->band = 0; + } + else if( (ud >= 28)&&(ud <= 29) ){ + sp->fq = SHORT(((ud - 28) * 1000) + d); + sp->band = B_28; + } + else if( (ud >= 50)&&(ud <= 54) ){ + sp->fq = SHORT(((ud - 50) * 1000) + d); + sp->band = B_50; + } + else if( (ud >= 144) && (ud <= 147) ){ + sp->fq = SHORT(((ud - 144) * 1000) + d); + sp->band = B_144; + } + else if( (ud >= 430) && (ud <= 440) ){ + sp->fq = SHORT(((ud - 430) * 1000) + d); + sp->band = B_430; + } + else if( (ud >= 220) && (ud <= 225) ){ + sp->fq = SHORT(((ud - 220) * 1000) + d); + sp->band = B_220; + } + else if( (ud >= 1240) && (ud <= 1300) ){ + sp->fq = SHORT(((ud - 1240) * 100) + (d/10)); + sp->band = B_1200; + } + else if( (ud >= 2350) && (ud <= 2450) ){ + sp->fq = SHORT(((ud - 2350) * 100) + (d/10)); + sp->band = B_2400; + } + else { + sp->band = 0; + } +} + +int CLogFile::ReadAscii(SDMMLOG *sp, LPSTR p) +{ + LPSTR t; + int y, m, d; + + memset(sp, 0, sizeof(SDMMLOG)); + p = StrDlm(t, p); /* DATE */ + if( sscanf(t, "%u.%u.%u", &y, &m, &d )!=3 ) return FALSE; + sp->year = BYTE(y % 100); + sp->date = WORD((m * 100) + d); + p = StrDlm(t, p); /* BGN */ + if( sscanf(t, "%u.%u", &d, &y) != 2 ){ + d = atoin(t, -1); + y = 0; + } + m = d / 100; + d = d % 100; + y /= 2; + sp->btime = WORD((((m * 60) + d) * 30) + y); + p = StrDlm(t, p); /* CALL */ + StrCopy(sp->call, t, MLCALL); + p = StrDlm(t, p); /* UR */ + StrCopy(sp->ur, t, MLRST); + p = StrDlm(t, p); /* MY */ + StrCopy(sp->my, t, MLRST); + p = StrDlm(t, p); /* BAND */ + SetFreq(sp, t); + p = StrDlm(t, p); /* MODE */ + SetMode(sp, t); + p = StrDlm(t, p); /* POW */ + StrCopy(sp->pow, t, MLPOW); + p = StrDlm(t, p); /* NAME */ + StrCopy(sp->name, t, MLNAME); + p = StrDlm(t, p); /* QTH */ + StrCopy(sp->qth, t, MLQTH); + p = StrDlm(t, p); /* REM */ + StrCopy(sp->rem, t, MLREM); + p = StrDlm(t, p); /* QSL */ + StrCopy(sp->qsl, t, MLQSL); + p = StrDlm(t, p); /* ETIME*/ + d = atoin(t, -1); + m = d / 100; + d = d % 100; + sp->etime = WORD(((m * 60) + d) * 30); + p = StrDlm(t, p); /* S */ + sp->send = *t; + p = StrDlm(t, p); /* R */ + sp->recv = *t; + p = StrDlm(t, p); /* M */ + sp->cq = *t; + p = StrDlm(t, p); /* ENV */ + sp->env = WORD(atoin(t, -1)); + p = StrDlm(t, p); /* OPT1 */ + StrCopy(sp->opt1, t, MLOPT); + p = StrDlm(t, p); /* OPT2 */ + StrCopy(sp->opt2, t, MLOPT); + p = StrDlm(t, p); /* USR1 */ + if( *t ) SetOptStr(2, sp, t); + StrDlm(t, p); /* USR2 */ + if( *t ) SetOptStr(3, sp, t); + return TRUE; +} + +void JSTtoUTC(int &Year, int &Mon, int &Day, int &Hour) +{ + + Hour -= 9; + if( Hour < 0 ){ + Hour += 24; + Day--; + if( Day < 1 ){ + Mon--; + if( Mon < 1 ){ + Mon = 12; + if( Year ){ + Year--; + } + else { + Year = 99; + } + } + if( Year % 4 ){ + Day = MONN[Mon]; + } + else { + Day = MONU[Mon]; + } + } + } +} + +void JSTtoUTC(SDMMLOG *sp) +{ + int Year = sp->year; + int Mon = sp->date / 100; + int Day = sp->date % 100; + int Hour = sp->btime / (60*30); + if( sp->date || sp->btime ){ + JSTtoUTC(Year, Mon, Day, Hour); + sp->year = BYTE(Year); + sp->date = WORD(Mon * 100 + Day); + sp->btime = WORD((sp->btime % 1800) + (Hour * 1800)); + } + if( sp->etime ){ + // JST to UTC + if( sp->etime >= (9*60*30) ){ + sp->etime -= WORD(9 * 60 * 30); + } + else { + sp->etime += WORD(15 * 60 * 30); + } + if( !sp->etime ) sp->etime++; + } +} + +void UTCtoJST(int &Year, int &Mon, int &Day, int &Hour) +{ + LPCSTR mt; + + Hour += 9; + if( Hour >= 24 ){ + Hour -= 24; + Day++; + if( Year % 4 ){ + mt = MONN; + } + else { + mt = MONU; + } + if( Day > mt[Mon] ){ + Day = 1; + Mon++; + if( Mon > 12 ){ + Mon = 1; + Year++; + if( Year >= 100 ) Year = 0; + } + } + } +} + +void UTCtoJST(SDMMLOG *sp) +{ + int Year = sp->year; + int Mon = sp->date / 100; + int Day = sp->date % 100; + int Hour = sp->btime / (60*30); + if( sp->date || sp->btime ){ + UTCtoJST(Year, Mon, Day, Hour); + sp->year = BYTE(Year); + sp->date = WORD(Mon * 100 + Day); + sp->btime = WORD((sp->btime % 1800) + (Hour * 1800)); + } + if( sp->etime ){ + // UTC to JST + if( sp->etime >= (15*60*30) ){ + sp->etime -= WORD(15 * 60 * 30); + } + else { + sp->etime += WORD(9 * 60 * 30); + } + if( !sp->etime ) sp->etime++; + } +} + +void UTCtoJST(SYSTEMTIME *tp) +{ + int y = tp->wYear; + int m = tp->wMonth; + int d = tp->wDay; + int h = tp->wHour; + UTCtoJST(y, m, d, h); + tp->wYear = WORD(y); + tp->wMonth = WORD(m); + tp->wDay = WORD(d); + tp->wHour = WORD(h); +} + +void mBandToBand(SDMMLOG *sp, LPCSTR p) +{ + int m; + + sp->fq = 0; + if( !strcmpi(p, "SAT") ){ + sp->band = 0; + } + else if( sscanf(p, "%u", &m) == 1 ){ + switch(m){ + case 2: + sp->band = B_144; + break; + case 6: + sp->band = B_50; + break; + case 10: + sp->band = B_28; + break; + case 12: + sp->band = B_24; + break; + case 15: + sp->band = B_21; + break; + case 17: + sp->band = B_18; + break; + case 20: + sp->band = B_14; + break; + case 30: + sp->band = B_10; + break; + case 40: + sp->band = B_7; + break; + case 75: + sp->band = B_38; + break; + case 80: + sp->band = B_35; + break; + case 160: + sp->band = B_19; + sp->fq = 800; + break; + } + } +} + +LPCSTR FreqTomBand(SDMMLOG *sp) +{ + return _mBand[sp->band]; +} + + + \ No newline at end of file diff --git a/JASTA/LogFile.h b/JASTA/LogFile.h new file mode 100644 index 0000000..412e95f --- /dev/null +++ b/JASTA/LogFile.h @@ -0,0 +1,290 @@ +//--------------------------------------------------------------------------- +#ifndef LogFileH +#define LogFileH + +#include "ComLib.h" +//--------------------------------------------------------------------------- +#define MMLOGID "MMLOG DATA Ver1.00\032" + +extern const char *_band[]; + +//--------------------------------------------------------------------------- +// MMLOG Constant +// +enum BD { /* バンドの番号 */ + B_NULL, + B_19, + B_35, + B_38, + B_7, + B_10, + B_14, + B_18, + B_21, + B_24, + B_28, + B_50, + B_144, + B_430, + B_1200, + B_2400, + B_5600, + B_101G, + B_104G, + B_24G, + B_47G, + B_75G, + B_142G, + B_248G, + B_4630, + B_220, + B_SAT, +}; + +typedef struct { // Logの動作オプション + char m_TimeZone; // 表示用タイムゾーン + + int m_UpperName; // 大文字への変換 + int m_UpperQTH; // 大文字への変換 + int m_UpperREM; // 大文字への変換 + int m_UpperQSL; // 大文字への変換 + + int m_DefMyRST; // 0-OFF, 1-ON + + int m_CopyFreq; // 0-Band, 1-Freq + int m_CopyHis; // 0-599, 1-599001, 2-599UTC + int m_CopyName; // 0-OFF, 1-ON + int m_CopyQTH; // 0-OFF, 1-ON + int m_CopyREM; // 0-OFF, 1-ON + int m_CopyQSL; // 0-OFF, 1-ON + + int m_AutoSave; // 自動セーブ + + int m_QSOMacroFlag; // 0-OFF, 1-ON + int m_CheckBand; // 同一バンドでの重複をチェック + int m_QSOMacro[5]; // 0-Run 1st, 1-Run 2nd, 2-Run Dupe, 3-S&P 1st, 4-S&P 2nd + WORD m_QSOMacroKey[5]; + AnsiString m_QSOMacroStr[5]; + + AnsiString m_THRTTY; + AnsiString m_THSSTV; + int m_THTZ; + int m_ClipRSTADIF; + int m_DateType; +}LOGSET; + +#define MLCALL 16 /* コールサインの長さ */ +#define MLRST 20 /* RSTナンバの長さ */ +#define MLREM 56 /* 記事の長さ */ +#define MLNAME 16 /* 名前の長さ */ +#define MLQTH 28 /* QTHの長さ */ +#define MLQSL 54 /* QSLの長さ */ +#define MLPOW 4 /* 電力 */ +#define MLOPT 8 /* オプション */ + +#define MODEMAX 48 + +#define YEAR(c) (((c)<50)?(2000+(c)):(1900+(c))) + +#pragma option -a- // パックの指示 +typedef struct { /* MMLOGデータ形式 */ + BYTE year; /* 年 */ + WORD date; /* 日付 */ + WORD btime; /* 開始時刻 */ + WORD etime; /* 終了時刻 */ + char call[MLCALL+1]; /* コールサイン */ + char ur[MLRST+1]; /* T リポート */ + char my[MLRST+1]; /* R リポート */ + BYTE band; /* バンド */ + SHORT fq; /* 周波数 */ + BYTE mode; /* モード */ + char pow[MLPOW+1]; /* 電力 */ + char name[MLNAME+1]; /* 名前 */ + char qth[MLQTH+1]; /* QTH */ + char qsl[MLQSL+1]; /* QSL */ + char send; /* QSL 送信 */ + char recv; /* QSL 受信 */ + char cq; /* cq/call */ + WORD env; /* 自局環境 */ + char rem[MLREM+1]; /* 記事 */ + char opt1[MLOPT+1]; /* オプション */ + char opt2[MLOPT+1]; /* オプション2 */ +}SDMMLOG; + +#define FHDOFF 256 /* 先頭のヘッダのオフセット */ +#define UMODEMAX 32 +typedef struct { + char id[20]; /* ファイルバージョン */ + char dmy[4]; /* ダミー領域 */ + USHORT mlt; /* マルチ情報のサイズ */ + char td; /* 時差コード */ + char hash; /* ハッシュデータ格納フラグ */ + long size; /* データサイズ */ + char master; /* マスターファイルフラグ */ + char dm2[15]; /* ダミー2 */ + char mode[UMODEMAX][6]; /* ユーザ定義モード */ +}FHD; +#pragma option -a. // パック解除の指示 + +class CIndex +{ +private: + int m_IndexMax; // 確保中のインデックスの数 + int m_IndexCnt; // 現在のインデックスの数 + LPSTR pIndex; // インデックス領域のポインタ(16バイトインデックス) + BYTE *pMult; // マルチ情報のポインタ +public: + CIndex(); + ~CIndex(); + void AllocIndex(int n); + void ClearIndex(void); + void WriteIndex(LPCSTR pCall, int n); + void ReadIndex(LPSTR pCall, int n); + LPSTR PointIndex(int n); + void AddBlock(LPCSTR p, int len); + int ReadIndex(int handle, FHD *hp); + void MakeIndex(int handle, FHD *hp); + int WriteIndex(int handle, FHD *hp); + + +}; + +#define FINDMAX 32768 +class CLogFind +{ +public: + int m_FindCnt; + int m_FindCmp1Max; + int m_FindCmp2Max; + int m_FindStr1Max; + int m_FindStr2Max; + + int *pFindTbl; + AnsiString m_FindStr; +public: + CLogFind(); + ~CLogFind(); + inline int GetCount(void){return m_FindCnt;}; + inline void Clear(void){ + m_FindCnt = m_FindCmp1Max = m_FindCmp2Max = m_FindStr1Max = m_FindStr2Max = 0; + }; + int Add(int n); + void Ins(int n); + + inline void Write(int n){ + pFindTbl[m_FindCnt] = n; + m_FindCnt++; + }; + inline void SetText(LPCSTR p){ + if( p != m_FindStr.c_str() ){ + m_FindStr = p; + } + }; + inline LPCSTR GetText(void){ + return m_FindStr.c_str(); + }; + inline void ClearText(void){ + m_FindStr = ""; + }; +}; + +class CLogFile +{ +private: + int m_Open; // オープンフラグ + int m_ReadOnly; + int m_EditFlag; // 編集フラグ + int m_Handle; // ファイルハンドル + CIndex m_Index; // 現在オープン中のインデックス + FHD m_fhd; // 現在オープン中のファイルヘッダ + AnsiString m_Name; // ログファイルの名前 + char m_modebuf[8]; + char LogDir[256]; +public: + AnsiString m_FileName; // ログファイルの名前(フルパス) + + int m_CurNo; + int m_CurChg; + SDMMLOG m_sd; + SDMMLOG m_bak; + SDMMLOG m_asd; + + CLogFind m_Find; // カレント検索データ + LOGSET m_LogSet; +private: + void SetHisRST(SDMMLOG *sp); + +public: + CLogFile(); + ~CLogFile(); + + int Open(LPCSTR pName, int enbwrt); + int Close(void); + + void ReadIniFile(LPCSTR pKey, TIniFile *pIniFile); + void WriteIniFile(LPCSTR pKey, TIniFile *pIniFile); + + void MakeIndex(void); + + inline IsEdit(void){return m_EditFlag;}; + void MakePathName(LPCSTR pName); + void MakeName(LPCSTR pName); + inline LPCSTR GetName(void){return m_Name.c_str();}; + + inline int GetCount(void){return m_fhd.size;}; + inline int IsOpen(void){return m_Open;}; + int GetData(SDMMLOG *sp, int n); + int PutData(SDMMLOG *sp, int n); + + LPCSTR GetDateString(SDMMLOG *sp, int sw); + inline LPCSTR GetDateString(SDMMLOG *sp){ return GetDateString(sp, m_LogSet.m_DateType); }; + LPCSTR GetTimeString(WORD d); + + + LPCSTR GetModeString(BYTE m); + void SetMode(SDMMLOG *sp, LPCSTR s); + + LPCSTR GetFreqString(BYTE b, short fq); + void SetFreq(SDMMLOG *sp, LPCSTR p); + LPCSTR GetOptStr(int n, SDMMLOG *sp); + void SetOptStr(int n, SDMMLOG *sp, LPCSTR pOpt); + + void CopyAF(void); + + void SortDate(int bb, int eb); + int FindSameBand(void); + int FindSameDate(SYSTEMTIME *pUTC); + + void FindStrSet(CLogFind *fp, LPCSTR pCall); + int FindCmpSet(CLogFind *fp, LPCSTR pCall); + int FindClipSet(CLogFind *fp, LPCSTR pCall); + int FindSet(CLogFind *fp, LPCSTR pCall); + int Find(LPCSTR pCall, int b, int dir); + int IsAlready(LPCSTR pCall); + void DeleteAll(void); + void DeleteLast(void); + void Delete(int top, int end); + void Insert(int n, SDMMLOG *sp); + + void InitCur(void); + void SetLastPos(void); + + int ReadAscii(SDMMLOG *sp, LPSTR p); + CIndex *GetIndex(void){return &m_Index;}; +}; + +void JSTtoUTC(int &Year, int &Mon, int &Day, int &Hour); +void JSTtoUTC(SDMMLOG *sp); +void UTCtoJST(int &Year, int &Mon, int &Day, int &Hour); +void UTCtoJST(SDMMLOG *sp); +void UTCtoJST(SYSTEMTIME *tp); +void mBandToBand(SDMMLOG *sp, LPCSTR p); +LPCSTR FreqTomBand(SDMMLOG *sp); +int GetLMode(BYTE m); + +extern CLogFile Log; +extern const char MONN[]; +extern const char MONU[]; +#endif + + \ No newline at end of file diff --git a/JASTA/MMJASTA.bpr b/JASTA/MMJASTA.bpr new file mode 100644 index 0000000..b46ebc3 --- /dev/null +++ b/JASTA/MMJASTA.bpr @@ -0,0 +1,161 @@ +# --------------------------------------------------------------------------- +!if !$d(BCB) +BCB = $(MAKEDIR)\.. +!endif + +# --------------------------------------------------------------------------- +# IDE セクション +# --------------------------------------------------------------------------- +# プロジェクトメイクファイルの以下のセクションは、IDE によって管理されます。 +# このセクションを変更する場合は、できるだけ IDE を使用するようにして +# ください。 +# --------------------------------------------------------------------------- + +VERSION = BCB.03 +# --------------------------------------------------------------------------- +PROJECT = MMJASTA.exe +OBJFILES = MMJASTA.obj Main.obj ComLib.obj LogFile.obj OptDlg.obj TextEdit.obj QsoDlg.obj \ + country.obj FEdit.obj LogConv.obj +RESFILES = MMJASTA.res +DEFFILE = +RESDEPEN = $(RESFILES) Main.dfm OptDlg.dfm TextEdit.dfm QsoDlg.dfm FEdit.dfm +LIBFILES = +LIBRARIES = VCL35.lib +SPARELIBS = VCL35.lib +PACKAGES = VCLX35.bpi VCL35.bpi VCLDB35.bpi VCLDBX35.bpi bcbsmp35.bpi dclocx35.bpi \ + QRPT35.bpi TEEUI35.bpi VCLSMP35.bpi TEEDB35.bpi TEE35.bpi ibsmp35.bpi \ + NMFAST35.bpi INETDB35.bpi INET35.bpi +# --------------------------------------------------------------------------- +PATHCPP = .; +PATHASM = .; +PATHPAS = .; +PATHRC = .; +DEBUGLIBPATH = $(BCB)\lib\debug +RELEASELIBPATH = $(BCB)\lib\release +# --------------------------------------------------------------------------- +CFLAG1 = -O2 -Hc -w -Ve -d -k- -vi -c -b- -w-par -w-inl -Vx -tW +CFLAG2 = -I$(BCB)\include;$(BCB)\include\vcl -H=$(BCB)\lib\vcl35.csm +CFLAG3 = -Tkh30000 +PFLAGS = -U$(BCB)\lib\obj;$(BCB)\lib;$(RELEASELIBPATH) \ + -I$(BCB)\include;$(BCB)\include\vcl -$L- -$D- -v -JPHN -M +RFLAGS = -i$(BCB)\include;$(BCB)\include\vcl +AFLAGS = /i$(BCB)\include /i$(BCB)\include\vcl /mx /w2 /zn /d_RTLDLL +LFLAGS = -L$(BCB)\lib\obj;$(BCB)\lib;$(RELEASELIBPATH) -aa -Tpe -x -Gn +IFLAGS = +# --------------------------------------------------------------------------- +ALLOBJ = c0w32.obj sysinit.obj $(OBJFILES) +ALLRES = $(RESFILES) +ALLLIB = $(LIBFILES) $(LIBRARIES) import32.lib cp32mt.lib +# --------------------------------------------------------------------------- +!ifdef IDEOPTIONS + +[Version Info] +IncludeVerInfo=0 +AutoIncBuild=0 +MajorVer=1 +MinorVer=0 +Release=0 +Build=0 +Debug=0 +PreRelease=0 +Special=0 +Private=0 +DLL=0 +Locale=1041 +CodePage=932 + +[Version Info Keys] +CompanyName= +FileDescription= +FileVersion=1.0.0.0 +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion=1.0.0.0 +Comments= + +[Debugging] +DebugSourceDirs=$(BCB)\source\vcl + +[Parameters] +RunParams= +HostApplication= + +!endif + +# --------------------------------------------------------------------------- +# MAKE セクション +# --------------------------------------------------------------------------- +# IDE はプロジェクトファイルのこのセクションは使用していません。 +# コマンドラインの MAKE ユーティリティを使用してビルドするためのものです。 +# --------------------------------------------------------------------------- + +.autodepend +# --------------------------------------------------------------------------- +!if !$d(BCC32) +BCC32 = bcc32 +!endif + +!if !$d(DCC32) +DCC32 = dcc32 +!endif + +!if !$d(TASM32) +TASM32 = tasm32 +!endif + +!if !$d(LINKER) +LINKER = ilink32 +!endif + +!if !$d(BRCC32) +BRCC32 = brcc32 +!endif +# --------------------------------------------------------------------------- +!if $d(PATHCPP) +.PATH.CPP = $(PATHCPP) +.PATH.C = $(PATHCPP) +!endif + +!if $d(PATHPAS) +.PATH.PAS = $(PATHPAS) +!endif + +!if $d(PATHASM) +.PATH.ASM = $(PATHASM) +!endif + +!if $d(PATHRC) +.PATH.RC = $(PATHRC) +!endif +# --------------------------------------------------------------------------- +$(PROJECT): $(OBJFILES) $(RESDEPEN) $(DEFFILE) + $(BCB)\BIN\$(LINKER) @&&! + $(LFLAGS) + + $(ALLOBJ), + + $(PROJECT),, + + $(ALLLIB), + + $(DEFFILE), + + $(ALLRES) +! +# --------------------------------------------------------------------------- +.pas.hpp: + $(BCB)\BIN\$(DCC32) $(PFLAGS) {$< } + +.pas.obj: + $(BCB)\BIN\$(DCC32) $(PFLAGS) {$< } + +.cpp.obj: + $(BCB)\BIN\$(BCC32) $(CFLAG1) $(CFLAG2) $(CFLAG3) -n$(@D) {$< } + +.c.obj: + $(BCB)\BIN\$(BCC32) $(CFLAG1) $(CFLAG2) $(CFLAG3) -n$(@D) {$< } + +.asm.obj: + $(BCB)\BIN\$(TASM32) $(AFLAGS) $<, $@ + +.rc.res: + $(BCB)\BIN\$(BRCC32) $(RFLAGS) -fo$@ $< +# --------------------------------------------------------------------------- diff --git a/JASTA/MMJASTA.cbproj b/JASTA/MMJASTA.cbproj new file mode 100644 index 0000000..889e7b0 --- /dev/null +++ b/JASTA/MMJASTA.cbproj @@ -0,0 +1,282 @@ +サソ + + {9DBCB72F-C3F6-4D05-819D-D09F90510086} + CppVCLApplication + MMJASTA.cpp + True + Debug + VCL + 14.6 + Win32 + 1 + Application + + + true + + + true + Base + true + + + true + Base + true + + + true + Base + true + + + true + Cfg_1 + true + true + + + true + Cfg_1 + true + true + + + true + Base + true + + + true + Cfg_2 + true + true + + + true + Cfg_2 + true + true + + + 1041 + Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace) + CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=;CFBundleName=;CFBundleDisplayName=;UIDeviceFamily=;CFBundleIdentifier=;CFBundleVersion=;CFBundlePackageType=;CFBundleSignature=;CFBundleAllowMixedLocalizations=;UISupportedInterfaceOrientations=;CFBundleExecutable=;CFBundleResourceSpecification=;LSRequiresIPhoneOS=;CFBundleInfoDictionaryVersion=;CFBundleDevelopmentRegion= + vclx.bpi;rtl.bpi;vcl.bpi;dbrtl.bpi;vcldb.bpi;bdertl.bpi;vcldbx.bpi;bcbsmp.bpi;teeui.bpi;vclsmp.bpi;teedb.bpi;tee.bpi;ibsmp.bpi;inetdb.bpi;inet.bpi;$(PackageImports) + rtl.lib;vcl.lib + None + $(BDS)\lib\obj;$(BDS)\lib;$(BDS)\lib\psdk;$(ILINK_LibraryPath) + true + .\;$(BDS)\lib;$(BDS)\lib\obj;$(DCC_IncludePath) + $(BDS)\include;$(BDS)\include\vcl;$(BCC_IncludePath) + .\;$(BDS)\lib;$(BDS)\lib\obj;$(DCC_UnitSearchPath) + exe + . + Level2 + $(BDS)\include;$(BDS)\include\vcl;$(TASM_IncludePath) + JPHNE + $(BDS)\include;$(BDS)\include\vcl;$(BRCC_IncludePath) + /w2 + Windows + -M + true + + + -tWM -Tkh30000 -Vx -d -Ve + Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) + _RTLDLL;$(BCC_Defines) + 1033 + $(BDSINCLUDE)\windows\vcl;$(IncludePath) + CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments= + _RTLDLL;USEPACKAGES;$(BRCC_Defines) + true + MMJASTA_Icon.ico + _RTLDLL;USEPACKAGES;$(TASM_Defines) + $(BDS)\bin\default_app.manifest + + + _RTLDLL;$(BCC_Defines) + $(BDSINCLUDE)\windows\vcl;$(IncludePath) + _RTLDLL;USEPACKAGES;$(TASM_Defines) + _RTLDLL;USEPACKAGES;$(BRCC_Defines) + MMJASTA_Icon.ico + + + true + Full + Debug_Build + false + true + $(BDS)\lib\debug;$(ILINK_LibraryPath);$(ILINK_LibraryPath) + true + true + DEBUG;$(DCC_Define);$(DCC_Define) + true + true + -M -V + true + + + -tWM -Tkh30000 -Vx -d -Ve -k + _DEBUG;$(BCC_Defines);$(BCC_Defines) + 1033 + rtl.lib;vcl.lib + true + None + CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments= + + + _DEBUG;$(BCC_Defines);$(BCC_Defines) + + + Release_Build + $(BDS)\lib\release;$(ILINK_LibraryPath);$(ILINK_LibraryPath) + -M -$O+ + + + NDEBUG;$(BCC_Defines);$(BCC_Defines) + -tWM -Tkh30000 -Vx -d -Ve -r + + + NDEBUG;$(BCC_Defines);$(BCC_Defines) + + + + 3 + ComLib.h + 10 + + + 8 + country.h + 2 + + + 9 +
FileEdit
+ FEdit.h + 4 +
+ + 3 + LogConv.h + 10 + + + 9 + LogFile.h + 4 + + + 8 +
MainWnd
+ Main.h + 2 +
+ + -1 + 0 + + + -1 + 1 + + +
OptDlgBox
+ OptDlg.h + 5 +
+ + 7 +
QSODlgBox
+ QsoDlg.h + 0 +
+ + 6 +
TextEditDlg
+ TextEdit.h + 1 +
+ + + + + + + Cfg_2 + Base + + + Base + + + Cfg_1 + Base + +
+ + + CPlusPlusBuilder.Personality.12 + CppVCLApplication + + + + False + False + 1 + 0 + 0 + 0 + False + False + False + False + False + 1041 + 932 + + + + + 1.0.0.0 + + + + + + 1.0.0.0 + + + + + + + + + + + + + + + + + + False + True + True + + + MMJASTA.cpp + + + + True + False + + + 12 + + +
diff --git a/JASTA/MMJASTA.cbproj.local b/JASTA/MMJASTA.cbproj.local new file mode 100644 index 0000000..b3811b7 --- /dev/null +++ b/JASTA/MMJASTA.cbproj.local @@ -0,0 +1,2 @@ +サソ + diff --git a/JASTA/MMJASTA.cpp b/JASTA/MMJASTA.cpp new file mode 100644 index 0000000..1b4b003 --- /dev/null +++ b/JASTA/MMJASTA.cpp @@ -0,0 +1,29 @@ +//--------------------------------------------------------------------------- +#include +#pragma hdrstop +USERES("MMJASTA.res"); +USEFORM("Main.cpp", MainWnd); +USEUNIT("ComLib.cpp"); +USEUNIT("LogFile.cpp"); +USEFORM("OptDlg.cpp", OptDlgBox); +USEFORM("TextEdit.cpp", TextEditDlg); +USEFORM("QsoDlg.cpp", QSODlgBox); +USEUNIT("country.cpp"); +USEFORM("FEdit.cpp", FileEdit); +USEUNIT("LogConv.cpp"); +//--------------------------------------------------------------------------- +WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) +{ + try + { + Application->Initialize(); + Application->CreateForm(__classid(TMainWnd), &MainWnd); + Application->Run(); + } + catch (Exception &exception) + { + Application->ShowException(&exception); + } + return 0; +} +//--------------------------------------------------------------------------- diff --git a/JASTA/MMJASTA.ini b/JASTA/MMJASTA.ini new file mode 100644 index 0000000..ed26e44 --- /dev/null +++ b/JASTA/MMJASTA.ini @@ -0,0 +1,17 @@ +[Language] +English=0 +[Folder] +Log=C:\MMSSTV +Index=1 +[Define] +Call= +Name= +Zip= +Adr= +Mail= +License= +Power= +Sexual=0 +TSize=2 +Category=0 +First=0 diff --git a/JASTA/MMJASTA.map b/JASTA/MMJASTA.map new file mode 100644 index 0000000..3eab8fa --- /dev/null +++ b/JASTA/MMJASTA.map @@ -0,0 +1,6 @@ + + Start Length Name Class + 0001:00401000 000303FDCH _TEXT CODE + 0002:00705000 000018028H _DATA DATA + 0003:0071D028 000021050H _BSS BSS + 0004:00000000 0000000F8H _TLS TLS diff --git a/JASTA/MMJASTA.res b/JASTA/MMJASTA.res new file mode 100644 index 0000000..ac5d04d Binary files /dev/null and b/JASTA/MMJASTA.res differ diff --git a/JASTA/MMJASTA.tds b/JASTA/MMJASTA.tds new file mode 100644 index 0000000..38378f5 Binary files /dev/null and b/JASTA/MMJASTA.tds differ diff --git a/JASTA/MMJASTA_Icon.ico b/JASTA/MMJASTA_Icon.ico new file mode 100644 index 0000000..746e4d9 Binary files /dev/null and b/JASTA/MMJASTA_Icon.ico differ diff --git a/JASTA/Main.cpp b/JASTA/Main.cpp new file mode 100644 index 0000000..a85ab73 --- /dev/null +++ b/JASTA/Main.cpp @@ -0,0 +1,1369 @@ +//--------------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "Main.h" +#include "OptDlg.h" +#include "TextEdit.h" +#include "QsoDlg.h" +#include "LogConv.h" +//--------------------------------------------------------------------------- +#pragma package(smart_init) +#pragma resource "*.dfm" +TMainWnd *MainWnd; +//--------------------------------------------------------------------------- +#define TEMPLOGNAME "MMJASTA.MDT" +//--------------------------------------------------------------------------- +__fastcall TMainWnd::TMainWnd(TComponent* Owner) + : TForm(Owner) +{ + lcid = GetThreadLocale() & 0x00ff; + if( lcid != LANG_JAPANESE ){ // English + MsgEng = 1; + sys.m_Category = 1; + } + else { + MsgEng = 0; + sys.m_Category = 0; + } + + if( ParamCount() >= 0 ){ + SetDirName(BgnDir, AnsiString(ParamStr(0)).c_str()); + } + else { + SetCurDir(BgnDir, sizeof(BgnDir)); + } + strcpy(MMLogDir, "C:\\MMSSTV"); + ::GetLocalTime(&m_now); + sys.m_Year = m_now.wYear; + if( m_now.wMonth < 8 ) sys.m_Year--; + sys.m_Call = ""; + sys.m_CName = "JASTA SSTV activity contest"; + sys.m_TSize = 2; + m_FIndex = 1; + Caption = VERTTL; + ReadRegister(); + SetLanguage(); + + char bf[256]; + sprintf(bf, "%sARRL.DX", BgnDir); + Cty.Load(bf); + + m_ReCalc = 0; + m_pEditLog = NULL; + m_pEditSum = NULL; + m_pEditAna = NULL; +} +//--------------------------------------------------------------------------- +void __fastcall TMainWnd::SetLanguage(void) +{ + Memo->Font->Pitch = fpFixed; + if( MsgEng ){ + Font->Name = "Arial"; + Font->Charset = ANSI_CHARSET; + Memo->Font->Name = "Courier New"; + Memo->Font->Charset = ANSI_CHARSET; + + KF->Caption = "&File"; + KV->Caption = "&View"; + KH->Caption = "&Help"; + KFS->Caption = "&Setup..."; + KFL->Caption = "&Load log..."; + KFR->Caption = "&Re-totalize"; + KVL->Caption = "Log sheet..."; + KVS->Caption = "Summary sheet..."; + KVA->Caption = "Analysis file..."; + KHM->Caption = "Download latest version..."; + KHR->Caption = "Reflector..."; + KHW->Caption = "JASTA Home page..."; + } + else { + Font->Name = "MS Pゴシック"; + Font->Charset = SHIFTJIS_CHARSET; + Memo->Font->Name = "MS ゴシック"; + Memo->Font->Charset = SHIFTJIS_CHARSET; + + KF->Caption = "ファイル(&F)"; + KV->Caption = "表示(&V)"; + KH->Caption = "ヘルプ(&H)"; + KFS->Caption = "セットアップ(&S)..."; + KFL->Caption = "ログファイルのロード(&L)..."; + KFR->Caption = "再集計(&R)"; + KVL->Caption = "ログシート..."; + KVS->Caption = "サマリシート..."; + KVA->Caption = "分析ファイル..."; + KHM->Caption = "最新版のダウンロード..."; + KHR->Caption = "メーリングリスト..."; + KHW->Caption = "JASTAのホームページ..."; + } +} +//--------------------------------------------------------------------------- +void __fastcall TMainWnd::FormCloseQuery(TObject *Sender, bool &CanClose) +{ + Log.Close(); + unlink(Log.m_FileName.c_str()); + WriteRegister(); + + if( m_pEditLog != NULL ) delete m_pEditLog; + if( m_pEditSum != NULL ) delete m_pEditSum; + if( m_pEditAna != NULL ) delete m_pEditAna; + CanClose = TRUE; +} +//--------------------------------------------------------------------------- +// レジストリからの読み出し +void __fastcall TMainWnd::ReadRegister(void) +{ + char bf[256]; + + sprintf(bf, "%sMMJASTA.ini", BgnDir); + TIniFile *pIniFile = new TIniFile(bf); + + MsgEng = pIniFile->ReadInteger("Language", "English", MsgEng); + + + AnsiString as; + as = pIniFile->ReadString("Folder", "Log", MMLogDir); + StrCopy(MMLogDir, as.c_str(), sizeof(MMLogDir)-1); + m_FIndex = pIniFile->ReadInteger("Folder", "Index", m_FIndex); + + sys.m_Call = pIniFile->ReadString("Define", "Call", sys.m_Call); + sys.m_Name = pIniFile->ReadString("Define", "Name", sys.m_Name); + sys.m_Zip = pIniFile->ReadString("Define", "Zip", sys.m_Zip); + sys.m_Adr = pIniFile->ReadString("Define", "Adr", sys.m_Adr); + sys.m_Mail = pIniFile->ReadString("Define", "Mail", sys.m_Mail); + sys.m_License = pIniFile->ReadString("Define", "License", sys.m_License); + sys.m_Pow = pIniFile->ReadString("Define", "Power", sys.m_Pow); + sys.m_Sexual = pIniFile->ReadInteger("Define", "Sexual", sys.m_Sexual); + sys.m_TSize = pIniFile->ReadInteger("Define", "TSize", sys.m_TSize); + + sys.m_Category = pIniFile->ReadInteger("Define", "Category", sys.m_Category); + sys.m_First = pIniFile->ReadInteger("Define", "First", sys.m_First); + delete pIniFile; +} +//--------------------------------------------------------------------------- +// レジストリへの書き込み +void __fastcall TMainWnd::WriteRegister(void) +{ + CWaitCursor wait; + char bf[256]; + sprintf(bf, "%sMMJASTA.ini", BgnDir); + + try{ + TIniFile *pIniFile = new TIniFile(bf); + + pIniFile->WriteInteger("Language", "English", MsgEng); + pIniFile->WriteString("Folder", "Log", MMLogDir); + pIniFile->WriteInteger("Folder", "Index", m_FIndex); + + pIniFile->WriteString("Define", "Call", sys.m_Call); + pIniFile->WriteString("Define", "Call", sys.m_Call); + pIniFile->WriteString("Define", "Name", sys.m_Name); + pIniFile->WriteString("Define", "Zip", sys.m_Zip); + pIniFile->WriteString("Define", "Adr", sys.m_Adr); + pIniFile->WriteString("Define", "Mail", sys.m_Mail); + pIniFile->WriteString("Define", "License", sys.m_License); + pIniFile->WriteString("Define", "Power", sys.m_Pow); + pIniFile->WriteInteger("Define", "Sexual", sys.m_Sexual); + pIniFile->WriteInteger("Define", "TSize", sys.m_TSize); + + pIniFile->WriteInteger("Define", "Category", sys.m_Category); + pIniFile->WriteInteger("Define", "First", sys.m_First); + delete pIniFile; + + } + catch(...){ + ErrorMB(MsgEng?"Cannot update MMJASTA.INI":"MMJASTA.INIを更新できません."); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMainWnd::SetTitle(void) +{ + if( m_SrcName.IsEmpty() ){ + Caption = VERTTL; + } + else { + char bf[256]; + sprintf(bf, "%s [%s]", VERTTL, m_SrcName.c_str()); + Caption = bf; + } +} +//--------------------------------------------------------------------------- +void __fastcall TMainWnd::GridDrawCell(TObject *Sender, int Col, + int Row, TRect &Rect, TGridDrawState State) +{ + char bf[256]; + + Grid->Canvas->FillRect(Rect); + int X = Rect.Left + 4; + int Y = Rect.Top + 2; + + if( Row ){ + Row--; + bf[0] = 0; + SDMMLOG sd; + int f = ( Row < Log.GetCount() ) ? TRUE : FALSE; + if( f ) Log.GetData(&sd, Row); + switch(Col){ + case 0: // No + wsprintf(bf, "%u", Row + 1); + break; + case 1: // Date + if( f ) wsprintf(bf, "%02u/%02u/%02u", sd.year, sd.date / 100, sd.date % 100); + break; + case 2: // Time + if( f ) wsprintf(bf, "%02u%02u", (sd.btime / 30) / 60, (sd.btime / 30) % 60); + break; + case 3: // Band + if( f ) wsprintf(bf, "%s", _band[sd.band]); + break; + case 4: // Call + if( f ) strcpy(bf, sd.call); + break; + case 5: + if( f ) strcpy(bf, sd.ur); + break; + case 6: + if( f ) strcpy(bf, sd.my); + break; + case 7: + if( f ) strcpy(bf, sd.opt1); + break; + case 8: + if( f ) strcpy(bf, sd.qsl); + break; + } + Grid->Canvas->TextRect(Rect, X, Y, bf); + } + else { // タイトル + LPCSTR _tt[]={ + "No","Date","UTC","Band","Call","Sent","Rcvd","Multi","Point" + }; + Grid->Canvas->TextRect(Rect, X, Y, _tt[Col]); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMainWnd::KFLClick(TObject *Sender) +{ + if( sys.m_Call.IsEmpty() ){ + KFSClick(NULL); + if( sys.m_Call.IsEmpty() ) return; + } + OpenDialog->Filter = MsgEng ? "MMLOG data files(mdt)|*.mdt|ADIF files(adi)|*.adi|LOG200 files(l2)|*.l2|Turbo HAMLOG files(dbs)|*.dbs" : + "MMLOGデータファイル(mdt)|*.mdt|ADIF ファイル(adi)|*.adi|LOG200 ファイル(l2)|*.l2|Turbo HAMLOG ファイル(dbs)|*.dbs"; + OpenDialog->FilterIndex = m_FIndex; + OpenDialog->InitialDir = MMLogDir; + if( OpenDialog->Execute() == TRUE ){ + SetDirName(MMLogDir, AnsiString(OpenDialog->FileName).c_str()); //ja7ude 0525 + m_FIndex = OpenDialog->FilterIndex; + m_SrcName = OpenDialog->FileName.c_str(); + Exec(m_SrcName.c_str(), TRUE); + SetTitle(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMainWnd::Exec(LPCSTR pName, int loadorg) +{ + m_ReCalc = 0; + CWaitCursor w; + + LPCSTR pEXT = GetEXT(pName); + if( !strcmpi(pEXT, "ADI") ){ + pName = ConvADIF(pName, loadorg); + if( pName == NULL ) return; + } + else if( !strcmpi(pEXT, "L2") ){ + pName = ConvLog200(pName, loadorg); + if( pName == NULL ) return; + } + else if( !strcmpi(pEXT, "DBS") ){ + pName = ConvHAMLOG(pName, loadorg); + if( pName == NULL ) return; + } + + CLogFile orgLog; + orgLog.Open(pName, FALSE); + if( !orgLog.IsOpen() ) return; + + char templog[256]; + sprintf(templog, "%sJASTA.$$$", BgnDir); + Log.Open(templog, TRUE); + if( !Log.IsOpen() ) return; + Log.DeleteAll(); + + m_errNOF = m_errDUP = m_errINV = m_errMLT = m_errBND = 0; + + SDMMLOG sd; + int i, n; + n = 0; + for( i = 0; i < orgLog.GetCount(); i++ ){ + orgLog.GetData(&sd, i); + JSTtoUTC(&sd); + int yy = sd.year + 2000; + int mm = sd.date / 100; + if( (sd.mode == 8) && (sd.band >= B_35) && (yy == sys.m_Year) && (mm == 8) && IsValidRST(sd.ur) ){ + AdjustData(&sd); + Log.PutData(&sd, n); + n++; + } + } + orgLog.Close(); + Log.SortDate(0, Log.GetCount()); + Grid->RowCount = (n >= 8) ? (n + 1) : 9; + Grid->Invalidate(); + Calc(ClipCall(sys.m_Call.c_str())); +} +//--------------------------------------------------------------------------- +int __fastcall TMainWnd::IsValidRST(LPSTR pRST) +{ + int l = strlen(pRST); + if( l <= 3 ) return 0; + LPCSTR p = pRST; + for( ; *p; p++ ){ + if( !isdigit(*p) ) return 0; + } + int n = atoin(&pRST[3], -1); + if( (n < 1000) && (l != 6) ){ + sprintf(&pRST[3], "%03u", n); + } + return 1; +} +//--------------------------------------------------------------------------- +void __fastcall TMainWnd::AdjustData(SDMMLOG *sp) +{ + if( sp->band <= B_28 ){ + strcpy(sp->qsl, "1"); + } + else if( sp->band <= B_430 ){ + strcpy(sp->qsl, "2"); + } + else { + strcpy(sp->qsl, "3"); + } + if( IsJA(sp->call) ){ + char c; + char bf[MLCALL+1]; + StrCopy(bf, ClipCC(sp->call), MLCALL); + if( (bf[0] == '7') && (bf[1] != 'J') ){ + c = '1'; + } + else { + c = bf[2]; + } + sprintf(sp->opt1, "JA%c", c); + strcpy(sp->opt2, "AS"); + } + else if( Cty.IsData() ){ + int ref = Cty.GetRefP(sp->call); + if( !ref ){ + LPCSTR pCC = ClipCC(sp->call); + ref = Cty.GetRefP(pCC); + } + if( ref ){ + LPCSTR pDX = Cty.GetCountry(ref); + if( (pDX != NULL) && *pDX && (strchr(pDX, '?') == NULL) ){ + LPCSTR p = lastp(sp->opt1); + p+=2; + if( *p != 0x01 ) StrCopy(sp->opt1, pDX, MLOPT); + } + pDX = Cty.GetCont(ref); + if( (pDX != NULL) && *pDX && (strchr(pDX, '?') == NULL) ){ + LPCSTR p = lastp(sp->opt2); + p+=2; + if( *p != 0x01 ) StrCopy(sp->opt2, pDX, MLOPT); + } + } + } + DelLastSpace(sp->opt1); + DelLastSpace(sp->opt2); + if( !IsValidRST(sp->my) ){ + strcpy(sp->qsl, "0"); + strcpy(sp->opt1, "*INV*"); + m_errINV++; + } + else if( (strstr(sp->rem, "NOF") != NULL) || (strstr(sp->rem, "nof") != NULL) ){ + strcpy(sp->qsl, "0"); + strcpy(sp->opt1, "*NOF*"); + m_errNOF++; + } +} +void __fastcall TMainWnd::ShowErr(StrText *tp, int n, SDMMLOG *sp, LPCSTR pKey) +{ + m_ShowErrCount++; + if( m_ShowErrCount >= 100 ){ + if( m_ShowErrCount == 100 ){ + tp->Printf("Too many Warnings\r\n"); + } + } + else { + tp->Printf("%-4u %u/%02u %02u%02uZ %5s %-13s %-7s %-7s : %s\r\n", + n+1, + sp->date/100, sp->date%100, + (sp->btime/30)/60, (sp->btime/30)%60, + _band[sp->band], + sp->call, sp->ur, sp->my, + pKey + ); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMainWnd::Calc(LPCSTR pName) +{ + StrText str(32768); + m_ShowErrCount = 0; + + m_Days = 0; + if( pName == NULL ){ + pName = "OUTPUT"; + } + sprintf(m_LogName, "%s%s.txt", BgnDir, pName); + sprintf(m_SumName, "%s%s.sum", BgnDir, pName); + sprintf(m_AnaName, "%s%s.ana", BgnDir, pName); + FILE *pfLog = fopen(m_LogName, "wt"); + + fprintf(pfLog, "JASTA Contest Log. Year:%04u Contest Name:%s\n", sys.m_Year, sys.m_CName.c_str()); + fprintf(pfLog, "Call Sign:%s\n\n", sys.m_Call.c_str()); + fprintf(pfLog, "Date Time UTC Band Station WKD. Sent No. RCVD No. Multi. Point\n\n"); + + int Score = 0; + int i; + int add = -1; + m_CountHF = m_CountVU = m_CountS = 0; + m_MJA.Clear(); + m_MDX.Clear(); + m_DUP.Clear(); + char mlt[32]; + int mf = 0; + for( i = 0; i < Log.GetCount(); i++ ){ + SDMMLOG sd; + Log.GetData(&sd, i); + int wf = 0; + mlt[0] = 0; + int dd = sd.date % 100; + if( add != dd ){ // 日付マルチ + add = dd; + m_Days++; + m_DUP.Clear(); + } + if( sd.opt1[0] != '*' ){ + if( !m_DUP.Add(clipsp(sd.call)) ){ + strcpy(sd.qsl, "0"); + strcpy(sd.opt1, "*DUP*"); + m_errDUP++; + wf++; + } + else if( (!sd.opt1[0]) || + (strchr(sd.opt1, '?') != NULL) || + (!strcmp(sd.opt1, "JA")) || + IsNumbAll(sd.opt1) + ){ + m_errMLT++; + char bf[128]; + sprintf(bf, "DXCC Unknown [%s]", sd.opt1); + ShowErr(&str, i, &sd, bf); + if( !mf ){ + MoveGrid(i); + mf++; + } + } + else if( !strncmp(sd.opt1, "JA", 2) ){ + if( m_MJA.Add(sd.opt1) ) strcpy(mlt, sd.opt1); + } + else { + if( sd.band >= B_144 ){ + m_errBND++; + char bf[128]; + sprintf(bf, "DX on 2m & down"); + ShowErr(&str, i, &sd, bf); + if( !mf ){ + MoveGrid(i); + mf++; + } + } + if( m_MDX.Add(sd.opt1) ) strcpy(mlt, sd.opt1); + } + int d = atoin(sd.qsl, -1); + Score += d; + switch(d){ + case 1: + m_CountHF++; + break; + case 2: + m_CountVU++; + break; + case 3: + m_CountS++; + break; + } + } + if( wf ) Log.PutData(&sd, i); + if( sd.opt1[0] == '*' ){ + strcpy(mlt, sd.opt1); + ShowErr(&str, i, &sd, sd.opt1); + } +// 1 123456789011231234567890123123456789012345678912345678 +// 8/01 12:34U     14 JA1QRZ 595001 595010 JA1 1 + + fprintf(pfLog, "%u/%02u %02u:%02uU%11s %-13s%-10s%-9s%-8s%s\n", + sd.date / 100, sd.date % 100, + (sd.btime/30)/60, (sd.btime/30)%60, + _band[sd.band], + sd.call, + sd.ur, + sd.my, + mlt, + sd.qsl + ); + } + + int MJA = m_MJA.GetCount(); + int MDX = m_MDX.GetCount(); + int MDAY = m_Days; + if( MDAY > 10 ) MDAY = 10; + int MALL = MJA+MDX+MDAY; + int Total = MALL * Score; + + if( m_errMLT || m_errINV || m_errDUP || m_errNOF || m_errBND ){ + str.Printf("Warning\t" ); + if( m_errDUP ) str.Printf("DUP(%u)\t", m_errDUP); + if( m_errNOF ) str.Printf("NOFACE(%u)\t", m_errNOF); + if( m_errINV ) str.Printf("Invalid(%u)\t", m_errINV); + if( m_errMLT ) str.Printf("DXCC Unknown(%u)\t", m_errMLT); + if( m_errBND ) str.Printf("DX on 2m & down(%u)", m_errBND); + str.Printf("\r\n" ); + } + else { + str.Printf("No Warning\r\n"); + } + str.Printf("\r\nMulti\tJAs(%u) + DX(%u) + DAYs(%u/%u) = %u \r\n", MJA, MDX, MDAY, m_Days, MALL); + str.Printf("Points\tHF(%u)+VU(%u)+S(%u) = %u\r\n", m_CountHF, m_CountVU*2, m_CountS*3, Score); + str.Printf("Total\t%u x %u = %u\r\n", Score, MALL, Total); + str.Printf("Output\t%s %s", m_LogName, m_SumName); + Memo->Text = str.GetText(); + + fprintf(pfLog, "-------------------------------------------------------------------\n"); + fprintf(pfLog, "Total JA's area:%u\n", MJA); + fprintf(pfLog, "%2u days DXCC :%-3u %9u Points\n",m_Days, MDX, Score); + fprintf(pfLog, "Total point %u*(%u+%u+%u)=%u\n", Score, MJA, MDX, MDAY, Total); + if( m_errDUP || m_errNOF || m_errINV ){ + fprintf(pfLog, "\n[Note]\n"); + if( m_errDUP ) fprintf(pfLog, "*DUP* : Duplicate QSO\n"); + if( m_errNOF ) fprintf(pfLog, "*NOF* : Nothing his/her face in the received PIC\n"); + if( m_errINV ) fprintf(pfLog, "*INV* : Invalid QSO\n"); + } + fclose(pfLog); + + + const LPCSTR _tsize[]={"S","M","L","LL","?","?"}; + + pfLog = fopen(m_SumName, "wt"); + if( MsgEng ){ + fprintf(pfLog, "\n%04u JASTA SSTV CONTEST SUMMARY SHEET\n\n", sys.m_Year); + fprintf(pfLog, "1. Contest Name : %s\n", sys.m_CName.c_str()); + fprintf(pfLog, "2. Entry Section : %s\n", sys.m_Category ? "S" : "J"); + fprintf(pfLog, "3. First time entry : %s\n", sys.m_First ? "Yes" : "No"); + fprintf(pfLog, "4. OM or YL(XYL) : %s\n", sys.m_Sexual ? "YL/XYL":"OM"); + fprintf(pfLog, "5. Size of T-shirts : %s (for an Activity Premium)\n", _tsize[sys.m_TSize]); + fprintf(pfLog, "6. Callsign : %s\n", sys.m_Call.c_str()); + fprintf(pfLog, "7. Address : Postal Zip Code %s\n", sys.m_Zip.c_str()); + fprintf(pfLog, " : %s\n", sys.m_Adr.c_str()); + fprintf(pfLog, " e-mail : %s\n", sys.m_Mail.c_str()); + fprintf(pfLog, "8. Name : %s\n", sys.m_Name.c_str()); + fprintf(pfLog, "9. Licensed Class : %s\n", sys.m_License.c_str()); + fprintf(pfLog, "10.Output Power : %s\n", sys.m_Pow.c_str()); + fprintf(pfLog, "11.Result\n"); + fprintf(pfLog, " (1)Confirmed QSO number of 3.5-28MHz %5u x 1 = %u points\n", m_CountHF, m_CountHF); + fprintf(pfLog, " (2)Confirmed QSO number of 50-430MHz %5u x 2 = %u points\n", m_CountVU, m_CountVU*2); + fprintf(pfLog, " (3)Confirmed QSO number of 1200MHz&UP %5u x 3 = %u points\n", m_CountS, m_CountS*3); + fprintf(pfLog, "\n\n"); + fprintf(pfLog, " Total QSO points : (%u)+(%u)+(%u) = %u\n", m_CountHF, m_CountVU*2, m_CountS*3, Score); + fprintf(pfLog, "\n"); + fprintf(pfLog, " (4)Total Areas of JA's = %u\n", MJA); + fprintf(pfLog, " (5)Total Entity of DXCC except JA = %u\n", MDX); + fprintf(pfLog, " (6)Total Worked Days(Maximum 10 days) = %u\n", MDAY ); + fprintf(pfLog, "\n"); + fprintf(pfLog, " Total Multi : (%u)+(%u)+(%u) = %u\n", MJA, MDX, MDAY, MALL); + fprintf(pfLog, "\n\n"); + fprintf(pfLog, " Total Points : %u x %u = %u points\n", Score, MALL, Total); + fprintf(pfLog, "\n"); + fprintf(pfLog, "I declare my honor that in this contest I have operated\n" ); + fprintf(pfLog, "my station within the limitations of my license and have\n" ); + fprintf(pfLog, "observed fully the rules and regulations of the contest.\n" ); + fprintf(pfLog, "\n" ); + fprintf(pfLog, " %04u.%02u.%02u\n", m_now.wYear, m_now.wMonth, m_now.wDay); + fprintf(pfLog, " Singnature _________________\n" ); + fprintf(pfLog, "\n"); + fprintf(pfLog, "***************************************************************************\n"); + fprintf(pfLog, "(Remarks)\n\n\n"); + fprintf(pfLog, "---------------------------------------------------------------------------\n"); + } + else { + fprintf(pfLog, "\nJASTA 主催SSTVコンテストサマリーシート(様式AS)\n\n"); + fprintf(pfLog, "1.コンテスト名称 : %s\n", sys.m_CName.c_str()); + fprintf(pfLog, "2.参加部門 : %s\n", sys.m_Category ? "S" : "J"); + fprintf(pfLog, "3.初参加の区別 : %s\n", sys.m_First ? "初参加" : "過去にも参加した"); + fprintf(pfLog, "4.性別 : %s\n", sys.m_Sexual ? "YL/XYL":"OM"); + fprintf(pfLog, "5. Tシャツのサイズ : %s (アクティブ賞当選時用)\n", _tsize[sys.m_TSize]); + fprintf(pfLog, "6.コールサイン : %s\n", sys.m_Call.c_str()); + fprintf(pfLog, "7.住所 : 〒%s\n", sys.m_Zip.c_str()); + fprintf(pfLog, " : %s\n", sys.m_Adr.c_str()); + fprintf(pfLog, " e-mail : %s\n", sys.m_Mail.c_str()); + fprintf(pfLog, "8. 氏名 : %s\n", sys.m_Name.c_str()); + fprintf(pfLog, "9. 無線従事者の資格 : %s\n", sys.m_License.c_str()); + fprintf(pfLog, "10. 空中線電力 : %s\n", sys.m_Pow.c_str()); + fprintf(pfLog, "11. 結果\n"); + fprintf(pfLog, " (1) 3.5〜28MHz帯での交信局数 %5u x 1 = %u 点\n", m_CountHF, m_CountHF); + fprintf(pfLog, " (2) 50〜430MHz帯での交信局数 %5u x 2 = %u 点\n", m_CountVU, m_CountVU*2); + fprintf(pfLog, " (3) 1200MHz帯以上での交信局数 %5u x 3 = %u 点\n", m_CountS, m_CountS*3); + fprintf(pfLog, "\n\n"); + fprintf(pfLog, " 交信点数:(%u)+(%u)+(%u) = %u\n", m_CountHF, m_CountVU*2, m_CountS*3, Score); + fprintf(pfLog, "\n"); + fprintf(pfLog, " (4) 交信したJAのエリア数 = %u\n", MJA); + fprintf(pfLog, " (5) 交信したDXCCエンティティ数(JAを除く)= %u\n", MDX); + fprintf(pfLog, " (6) 運用日数(最大10) = %u\n", MDAY ); + fprintf(pfLog, "\n"); + fprintf(pfLog, " マルチ:(%u)+(%u)+(%u) = %u\n", MJA, MDX, MDAY, MALL); + fprintf(pfLog, "\n\n"); + fprintf(pfLog, " 総得点:交信点数×マルチ = %u × %u = %u 点\n", Score, MALL, Total); + fprintf(pfLog, "\n"); + fprintf(pfLog, " 以上、ここに提出するサマリーは運用した事実と相違ない事を誓います。\n"); + fprintf(pfLog, "\n"); + fprintf(pfLog, " %04u年 %02u月 %02u日\n", m_now.wYear, m_now.wMonth, m_now.wDay); + fprintf(pfLog, "\n"); + fprintf(pfLog, "***************************************************************************\n"); + fprintf(pfLog, "(意見等あればこの欄に記入下さい。)\n\n\n"); + fprintf(pfLog, "---------------------------------------------------------------------------\n"); + } + fclose(pfLog); + + MakeANA(); + if( m_errMLT ){ + WarningMB(MsgEng ? "There are unknown DXCC entities.\r\nDouble click on [DXCC Unknown] in the status window, and then edit the multi." : "未確定のDXCCエンティティが存在します.\r\n「DXCC Unknown」をダブルクリックし修正して下さい."); + return; + } + + KVAClick(NULL); + KVLClick(NULL); + KVSClick(NULL); +} +//--------------------------------------------------------------------------- +int __fastcall TMainWnd::GetBNO(int b) +{ + // 3.5, 7, 14, 18, 21, 24, 28, 50, 144, 430, 1200, 2400+ + if( b >= B_2400 ){ + b = 9; + } + else { + switch(b){ + case B_35: + case B_38: + b = 0; + break; + case B_7: + b = 1; + break; + default: + if( b >= B_14 ){ + b -= B_14; + b += 2; + } + else { + b = 11; + } + break; + } + } + return b; +} +//--------------------------------------------------------------------------- +// 解析フィアルを作成する +void __fastcall TMainWnd::MakeANA(void) +{ + FILE *fp = fopen(m_AnaName, "wt"); + if( fp == NULL ) return; + fprintf(fp, "\nAnalysis of %04u JASTA SSTV CONTEST\n\n", sys.m_Year); + + SDMMLOG sd; + CMULT MTMP; + int i, n; + for( i = 0; i < Log.GetCount(); i++ ){ + Log.GetData(&sd, i); + n = atoin(sd.qsl, -1); + if( n ){ + MTMP.Add(clipsp(sd.call)); + } + } + MTMP.SortCount(); + + int b; + int max = MTMP.GetCount(); + fprintf(fp, "[Number of QSOs according to a callsign (%u/%u)]\n", max, MTMP.GetTotal()); + int col, row; + int base = 0; + while(1){ + for( row = 0; row < 50; row++ ){ + fprintf(fp, "%-4u ", base + row + 1); + for( col = 0; col < 4; col++ ){ + int n = base + (col * 50 + row); + if( n < max ){ + fprintf(fp, "(%2u) %-13s", MTMP.GetCount(n), MTMP.GetText(n)); + } + else { + continue; + } + } + fprintf(fp, "\n"); + } + fprintf(fp, "\n"); + base += 200; + if( base >= max ) break; + } + + int sum; + CMULT MDX[16]; + for( i = 0; i < Log.GetCount(); i++ ){ + Log.GetData(&sd, i); + n = atoin(sd.qsl, -1); + if( n && m_MJA.GetCount(sd.opt1) ){ + b = GetBNO(sd.band); + MDX[b].Add(sd.opt1); + } + } + for( b = 0; b < 11; b++ ){ + MDX[b].Set("all", MDX[b].GetTotal()); + } + m_MJA.Sort(); + fprintf(fp, "[Number of QSOs according to a JA's area (%u/%u)]\n", m_MJA.GetCount(), m_MJA.GetTotal()); + fprintf(fp, "Area 3.5 7 14 18 21 24 28 50 144 430 1200 2400+ all\n"); + m_MJA.Add("all"); + for( row = 0; row < m_MJA.GetCount(); row++ ){ + LPCSTR pDX = m_MJA.GetText(row); + fprintf(fp, "%-5s ", pDX); + sum = 0; + for( b = 0; b < 12; b++ ){ + n = MDX[b].GetCount(pDX); + sum += n; + fprintf(fp, n ? "%4u " : " - ", n); + } + fprintf(fp, sum ? "%4u\n" : " -\n", sum); + } + fprintf(fp, "\n"); + + for( b = 0; b < 11; b++ ){ + MDX[b].Clear(); + } + for( i = 0; i < Log.GetCount(); i++ ){ + Log.GetData(&sd, i); + n = atoin(sd.qsl, -1); + if( n && m_MDX.GetCount(sd.opt1) ){ + b = GetBNO(sd.band); + MDX[b].Add(sd.opt1); + } + } + for( b = 0; b < 11; b++ ){ + MDX[b].Set("all", MDX[b].GetTotal()); + } + m_MDX.Sort(); + fprintf(fp, "[Number of QSOs according to a DX entity (%u/%u)]\n", m_MDX.GetCount(), m_MDX.GetTotal()); + fprintf(fp, "Entity 3.5 7 14 18 21 24 28 50 144 430 1200 2400+ all\n"); + m_MDX.Add("all"); + for( row = 0; row < m_MDX.GetCount(); row++ ){ + LPCSTR pDX = m_MDX.GetText(row); + fprintf(fp, "%-5s ", pDX); + sum = 0; + for( b = 0; b < 12; b++ ){ + n = MDX[b].GetCount(pDX); + sum += n; + fprintf(fp, n ? "%4u " : " - ", n); + } + fprintf(fp, sum ? "%4u\n" : " -\n", sum); + } + fprintf(fp, "\n"); + + for( b = 0; b < 11; b++ ) MDX[b].Clear(); + MTMP.Clear(); + for( i = 0; i < Log.GetCount(); i++ ){ + Log.GetData(&sd, i); + n = atoin(sd.qsl, -1); + if( n ){ + b = GetBNO(sd.band); + MTMP.Add(sd.opt2); + MDX[b].Add(sd.opt2); + } + + } + for( b = 0; b < 11; b++ ){ + MDX[b].Set("all", MDX[b].GetTotal()); + } + MTMP.Sort(); + MTMP.Add("all"); + fprintf(fp, "[Number of QSOs according to a continent]\n"); + fprintf(fp, "Conti. 3.5 7 14 18 21 24 28 50 144 430 1200 2400+ all\n"); + for( row = 0; row < MTMP.GetCount(); row++ ){ + LPCSTR pDX = MTMP.GetText(row); + fprintf(fp, "%-5s ", pDX); + sum = 0; + for( b = 0; b < 12; b++ ){ + n = MDX[b].GetCount(pDX); + sum += n; + fprintf(fp, n ? "%4u " : " - ", n); + } + fprintf(fp, sum ? "%4u\n" : " -\n", sum); + } + fprintf(fp, "\n"); + + + int QSODs[16][32]; + int QSOHs[16][25]; + memset(QSODs, 0, sizeof(QSODs)); + memset(QSOHs, 0, sizeof(QSOHs)); + for( i = 0; i < Log.GetCount(); i++ ){ + Log.GetData(&sd, i); + n = atoin(sd.qsl, -1); + if( n ){ + b = GetBNO(sd.band); + n = sd.date % 100; + if( (n >= 1) && (n <= 31) ){ + n--; + QSODs[b][n]++; + } + n = (sd.btime / 30) / 60; + if( (n >= 0) && (n <= 23) ){ + QSOHs[b][n]++; + } + } + } + fprintf(fp, "[Number of QSOs according to a day(UTC)]\n"); + fprintf(fp, "Day 3.5 7 14 18 21 24 28 50 144 430 1200 2400+ all\n"); + for( row = 0; row < 32; row++ ){ + fprintf(fp, row == 31 ? "all " : "%02u ", row + 1); + int sum = 0; + for( b = 0; b < 12; b++ ){ + n = QSODs[b][row]; + sum += n; + fprintf(fp, n ? "%4u " : " - ", n); + QSODs[b][31] += n; + } + fprintf(fp, sum ? "%4u" : " -", sum); + fprintf(fp, "\n"); + } + fprintf(fp, "\n"); + + fprintf(fp, "[Number of QSOs according to an hour(UTC)]\n"); + fprintf(fp, "Hour 3.5 7 14 18 21 24 28 50 144 430 1200 2400+ all\n"); + for( row = 0; row < 25; row++ ){ + fprintf(fp, row == 24 ? "all " : "%02u ", row); + int sum = 0; + for( b = 0; b < 12; b++ ){ + n = QSOHs[b][row]; + sum += n; + fprintf(fp, n ? "%4u " : " - ", n); + QSOHs[b][24] += n; + } + fprintf(fp, sum ? "%4u" : " -", sum); + fprintf(fp, "\n"); + } + fprintf(fp, "\n"); + + memset(QSODs, 0, sizeof(QSODs)); + memset(QSOHs, 0, sizeof(QSOHs)); + for( i = 0; i < Log.GetCount(); i++ ){ + Log.GetData(&sd, i); + n = atoin(sd.qsl, -1); + if( n && !IsJA(sd.call) ){ + b = GetBNO(sd.band); + n = sd.date % 100; + if( (n >= 1) && (n <= 31) ){ + n--; + QSODs[b][n]++; + } + n = (sd.btime / 30) / 60; + if( (n >= 0) && (n <= 23) ){ + QSOHs[b][n]++; + } + } + } + fprintf(fp, "[Number of QSOs (DX) according to a day(UTC)]\n"); + fprintf(fp, "Day 3.5 7 14 18 21 24 28 50 144 430 1200 2400+ all\n"); + for( row = 0; row < 32; row++ ){ + fprintf(fp, row == 31 ? "all " : "%02u ", row + 1); + int sum = 0; + for( b = 0; b < 12; b++ ){ + n = QSODs[b][row]; + sum += n; + fprintf(fp, n ? "%4u " : " - ", n); + QSODs[b][31] += n; + } + fprintf(fp, sum ? "%4u" : " -", sum); + fprintf(fp, "\n"); + } + fprintf(fp, "\n"); + fprintf(fp, "[Number of QSOs (DX) according to an hour(UTC)]\n"); + fprintf(fp, "Hour 3.5 7 14 18 21 24 28 50 144 430 1200 2400+ all\n"); + for( row = 0; row < 25; row++ ){ + fprintf(fp, row == 24 ? "all " : "%02u ", row); + int sum = 0; + for( b = 0; b < 12; b++ ){ + n = QSOHs[b][row]; + sum += n; + fprintf(fp, n ? "%4u " : " - ", n); + QSOHs[b][24] += n; + } + fprintf(fp, sum ? "%4u" : " -", sum); + fprintf(fp, "\n"); + } + fprintf(fp, "\n"); + + memset(QSODs, 0, sizeof(QSODs)); + memset(QSOHs, 0, sizeof(QSOHs)); + for( i = 0; i < Log.GetCount(); i++ ){ + Log.GetData(&sd, i); + n = atoin(sd.qsl, -1); + if( n && IsJA(sd.call) ){ + b = GetBNO(sd.band); + n = sd.date % 100; + if( (n >= 1) && (n <= 31) ){ + n--; + QSODs[b][n]++; + } + n = (sd.btime / 30) / 60; + if( (n >= 0) && (n <= 23) ){ + QSOHs[b][n]++; + } + } + } + fprintf(fp, "[Number of QSOs (JA) according to a day(UTC)]\n"); + fprintf(fp, "Day 3.5 7 14 18 21 24 28 50 144 430 1200 2400+ all\n"); + for( row = 0; row < 32; row++ ){ + fprintf(fp, row == 31 ? "all " : "%02u ", row + 1); + int sum = 0; + for( b = 0; b < 12; b++ ){ + n = QSODs[b][row]; + sum += n; + fprintf(fp, n ? "%4u " : " - ", n); + QSODs[b][31] += n; + } + fprintf(fp, sum ? "%4u" : " -", sum); + fprintf(fp, "\n"); + } + fprintf(fp, "\n"); + + fprintf(fp, "[Number of QSOs (JA) according to an hour(UTC)]\n"); + fprintf(fp, "Hour 3.5 7 14 18 21 24 28 50 144 430 1200 2400+ all\n"); + for( row = 0; row < 25; row++ ){ + fprintf(fp, row == 24 ? "all " : "%02u ", row); + int sum = 0; + for( b = 0; b < 12; b++ ){ + n = QSOHs[b][row]; + sum += n; + fprintf(fp, n ? "%4u " : " - ", n); + QSOHs[b][24] += n; + } + fprintf(fp, sum ? "%4u" : " -", sum); + fprintf(fp, "\n"); + } + fprintf(fp, "\n"); + + memset(QSODs, 0, sizeof(QSODs)); + memset(QSOHs, 0, sizeof(QSOHs)); + CMULT MLTD, MLTH; + for( i = 0; i < Log.GetCount(); i++ ){ + Log.GetData(&sd, i); + n = atoin(sd.qsl, -1); + if( n && sd.opt1[0] && !IsJA(sd.call) && (strchr(sd.opt1, '?')==NULL) ){ + b = GetBNO(sd.band); + n = sd.date % 100; + if( (n >= 1) && (n <= 31) ){ + n--; + if( MLTD.Add(sd.opt1) ) QSODs[b][n]++; + } + n = (sd.btime / 30) / 60; + if( (n >= 0) && (n <= 23) ){ + if( MLTH.Add(sd.opt1) ) QSOHs[b][n]++; + } + } + } + fprintf(fp, "[Number of NEW MULTIs (DX) according to a day(UTC)]\n"); + fprintf(fp, "Day 3.5 7 14 18 21 24 28 50 144 430 1200 2400+ all\n"); + for( row = 0; row < 32; row++ ){ + fprintf(fp, row == 31 ? "all " : "%02u ", row + 1); + int sum = 0; + for( b = 0; b < 12; b++ ){ + n = QSODs[b][row]; + sum += n; + fprintf(fp, n ? "%4u " : " - ", n); + QSODs[b][31] += n; + } + fprintf(fp, sum ? "%4u" : " -", sum); + fprintf(fp, "\n"); + } + fprintf(fp, "\n"); + + fprintf(fp, "[Number of NEW MULTIs (DX) according to an hour(UTC)]\n"); + fprintf(fp, "Hour 3.5 7 14 18 21 24 28 50 144 430 1200 2400+ all\n"); + for( row = 0; row < 25; row++ ){ + fprintf(fp, row == 24 ? "all " : "%02u ", row); + int sum = 0; + for( b = 0; b < 12; b++ ){ + n = QSOHs[b][row]; + sum += n; + fprintf(fp, n ? "%4u " : " - ", n); + QSOHs[b][24] += n; + } + fprintf(fp, sum ? "%4u" : " -", sum); + fprintf(fp, "\n"); + } + fprintf(fp, "\n"); + + memset(QSODs, 0, sizeof(QSODs)); + memset(QSOHs, 0, sizeof(QSOHs)); + MLTD.Clear(); + MLTH.Clear(); + for( i = 0; i < Log.GetCount(); i++ ){ + Log.GetData(&sd, i); + n = atoin(sd.qsl, -1); + if( n && sd.opt1[0] && IsJA(sd.call) && (strchr(sd.opt1, '?')==NULL) ){ + b = GetBNO(sd.band); + n = sd.date % 100; + if( (n >= 1) && (n <= 31) ){ + n--; + if( MLTD.Add(sd.opt1) ) QSODs[b][n]++; + } + n = (sd.btime / 30) / 60; + if( (n >= 0) && (n <= 23) ){ + if( MLTH.Add(sd.opt1) ) QSOHs[b][n]++; + } + } + } + fprintf(fp, "[Number of NEW MULTIs (JA) according to a day(UTC)]\n"); + fprintf(fp, "Day 3.5 7 14 18 21 24 28 50 144 430 1200 2400+ all\n"); + for( row = 0; row < 32; row++ ){ + fprintf(fp, row == 31 ? "all " : "%02u ", row + 1); + int sum = 0; + for( b = 0; b < 12; b++ ){ + n = QSODs[b][row]; + sum += n; + fprintf(fp, n ? "%4u " : " - ", n); + QSODs[b][31] += n; + } + fprintf(fp, sum ? "%4u" : " -", sum); + fprintf(fp, "\n"); + } + fprintf(fp, "\n"); + + fprintf(fp, "[Number of NEW MULTIs (JA) according to an hour(UTC)]\n"); + fprintf(fp, "Hour 3.5 7 14 18 21 24 28 50 144 430 1200 2400+ all\n"); + for( row = 0; row < 25; row++ ){ + fprintf(fp, row == 24 ? "all " : "%02u ", row); + int sum = 0; + for( b = 0; b < 12; b++ ){ + n = QSOHs[b][row]; + sum += n; + fprintf(fp, n ? "%4u " : " - ", n); + QSOHs[b][24] += n; + } + fprintf(fp, sum ? "%4u" : " -", sum); + fprintf(fp, "\n"); + } + fprintf(fp, "\n"); + + fclose(fp); +} +//--------------------------------------------------------------------------- +void __fastcall TMainWnd::KFSClick(TObject *Sender) +{ + int meng = MsgEng; + TOptDlgBox *pBox = new TOptDlgBox(this); + int r = pBox->Execute(); + delete pBox; + if( meng != MsgEng ) SetLanguage(); + if( (r == TRUE) && Log.IsOpen() && !m_SrcName.IsEmpty() ){ + m_ReCalc = TRUE; + if( YesNoMB(MsgEng ? "Does totalize once again?" : "集計しなおしますか ?") == IDYES ){ + Exec(m_SrcName.c_str(), FALSE); + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TMainWnd::KVLClick(TObject *Sender) +{ + if( m_pEditLog != NULL ) delete m_pEditLog; + if( m_LogName[0] ){ + m_pEditLog = new TFileEdit(this); + m_pEditLog->Execute(m_LogName); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMainWnd::KVSClick(TObject *Sender) +{ + if( m_pEditSum != NULL ) delete m_pEditSum; + if( m_SumName[0] ){ + m_pEditSum = new TFileEdit(this); + m_pEditSum->Execute(m_SumName); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMainWnd::KVAClick(TObject *Sender) +{ + if( m_pEditAna != NULL ) delete m_pEditAna; + if( m_AnaName[0] ){ + m_pEditAna = new TFileEdit(this); + m_pEditAna->Execute(m_AnaName); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMainWnd::KVClick(TObject *Sender) +{ + KVL->Enabled = m_LogName[0] && IsFile(m_LogName) ? TRUE : FALSE; + KVS->Enabled = m_SumName[0] && IsFile(m_SumName) ? TRUE : FALSE; + KVA->Enabled = m_AnaName[0] && IsFile(m_AnaName) ? TRUE : FALSE; +} +//--------------------------------------------------------------------------- +void __fastcall TMainWnd::MoveGrid(int n) +{ + Grid->Row = n + 1; + if( (Grid->Row < Grid->TopRow) || (Grid->Row >= (Grid->TopRow+8)) ){ + Grid->TopRow = Grid->Row; + } +} +//--------------------------------------------------------------------------- +void __fastcall TMainWnd::MemoClick(TObject *Sender) +{ + m_GridMove = FALSE; + if( Memo->Lines->Count ){ + int e = Memo->SelStart; + LPCSTR p = AnsiString(Memo->Text).c_str(); //ja7ude 0525 + int n = 0; + for( int i = 0; i < e; i++, p++ ){ + if( *p == LF ) n++; + } + if( n > Memo->Lines->Count ) n = Memo->Lines->Count - 1; + char bf[256]; + StrCopy(bf, AnsiString(Memo->Lines->Strings[n]).c_str(), sizeof(bf)-1); + if( isdigit(bf[0]) ){ + LPSTR t; + StrDlm(t, bf, ' '); + n = atoin(t, -1) - 1; + if( (n >= 0) && (n < Log.GetCount()) ){ + MoveGrid(n); + m_GridMove = TRUE; + } + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TMainWnd::MemoDblClick(TObject *Sender) +{ + if( m_GridMove ){ + GridDblClick(NULL); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMainWnd::KHTClick(TObject *Sender) +{ + ShowHelp(this, MsgEng ? "EMMJASTA.TXT":"MMJASTA.TXT"); +} +//--------------------------------------------------------------------------- +void __fastcall TMainWnd::KHMClick(TObject *Sender) +{ + WebRef.ShowHTML(MsgEng ? "http://www.qsl.net/mmhamsoft/" : "http://plaza27.mbn.or.jp/~je3hht/mmsstv/index.html"); +} +//--------------------------------------------------------------------------- +void __fastcall TMainWnd::KHRClick(TObject *Sender) +{ + WebRef.ShowHTML(MsgEng ? "http://groups.yahoo.com/group/MM-SSTV/" : "http://www.egroups.co.jp/group/mmhamsoft/"); +} +//--------------------------------------------------------------------------- +void __fastcall TMainWnd::KHWClick(TObject *Sender) +{ + WebRef.ShowHTML("http://homepage3.nifty.com/jasta/"); +} +//--------------------------------------------------------------------------- +void __fastcall TMainWnd::GridDblClick(TObject *Sender) +{ + if( m_SrcName.IsEmpty() ) return; + if( !Log.IsOpen() ) return; + + int n = Grid->Row - 1; + if( (n >= 0) && (n < Log.GetCount()) ){ + TQSODlgBox *pBox = new TQSODlgBox(this); + SDMMLOG sd, rsd; + Log.GetData(&sd, n); + memcpy(&rsd, &sd, sizeof(sd)); + if( pBox->Execute(&sd) == TRUE ){ + DelLastSpace(sd.opt1); + DelLastSpace(sd.opt2); + if( strcmp(sd.opt1, rsd.opt1) || strcmp(sd.opt2, rsd.opt2) ){ + LPSTR p = lastp(sd.opt1); + p+=2; + *p = 0x01; + p = lastp(sd.opt2); + p+=2; + *p = 0x01; + + CLogFile orgLog; + orgLog.Open(m_SrcName.c_str(), TRUE); + if( !orgLog.IsOpen() ) return; + + m_ReCalc = TRUE; + int i; + for( i = 0; i < Log.GetCount(); i++ ){ + Log.GetIndex()->ReadIndex(rsd.call, i); + if( !strcmp(sd.call, rsd.call) ){ + Log.GetData(&rsd, i); + memcpy(rsd.opt1, sd.opt1, MLOPT); + memcpy(rsd.opt2, sd.opt2, MLOPT); + Log.PutData(&rsd, i); + } + } + + for( i = 0; i < orgLog.GetCount(); i++ ){ + orgLog.GetIndex()->ReadIndex(rsd.call, i); + if( !strcmp(sd.call, rsd.call) ){ + orgLog.GetData(&rsd, i); + memcpy(rsd.opt1, sd.opt1, MLOPT); + memcpy(rsd.opt2, sd.opt2, MLOPT); + orgLog.PutData(&rsd, i); + } + } + orgLog.Close(); + } + } + Grid->Invalidate(); + delete pBox; + } +} +//--------------------------------------------------------------------------- +void __fastcall TMainWnd::KFRClick(TObject *Sender) +{ + if( m_ReCalc ){ + Exec(m_SrcName.c_str(), FALSE); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMainWnd::KFClick(TObject *Sender) +{ + KFR->Enabled = m_ReCalc && (!m_SrcName.IsEmpty()); +} +//--------------------------------------------------------------------------- +LPCSTR __fastcall TMainWnd::ConvADIF(LPCSTR pName, int loadorg) +{ + AnsiString LogName = pName; + + char TmpName[256]; + sprintf(TmpName, "%s"TEMPLOGNAME, BgnDir); + m_SrcName = TmpName; + + if( !loadorg ) return m_SrcName.c_str(); + + CLogADIF adif; + if( adif.Open(LogName.c_str()) == FALSE ) return NULL; + + CLogFile tmpLog; + tmpLog.Open(TmpName, TRUE); + if( !tmpLog.IsOpen() ) return NULL; + tmpLog.DeleteAll(); + + SDMMLOG sd; + memset(&sd, 0, sizeof(sd)); + CWaitCursor w; + while(adif.Read(&sd)==TRUE){ + if( (sd.mode == 8) && (sd.band >= B_35) ){ + sd.opt1[0] = 0; sd.opt2[0] = 0; + tmpLog.PutData(&sd, tmpLog.GetCount()); + } + memset(&sd, 0, sizeof(sd)); + } + adif.Close(); + tmpLog.Close(); + + return m_SrcName.c_str(); +} +//--------------------------------------------------------------------------- +LPCSTR __fastcall TMainWnd::ConvLog200(LPCSTR pName, int loadorg) +{ + AnsiString LogName = pName; + + char TmpName[256]; + sprintf(TmpName, "%s"TEMPLOGNAME, BgnDir); + m_SrcName = TmpName; + + if( !loadorg ) return m_SrcName.c_str(); + + CLog200 log; + if( log.Open(LogName.c_str()) == FALSE ) return NULL; + + CLogFile tmpLog; + tmpLog.Open(TmpName, TRUE); + if( !tmpLog.IsOpen() ) return NULL; + tmpLog.DeleteAll(); + + SDMMLOG sd; + CWaitCursor w; + while(log.Read(&sd)==TRUE){ + if( (sd.mode == 8) && (sd.band >= B_35) ){ + sd.opt1[0] = 0; sd.opt2[0] = 0; + tmpLog.PutData(&sd, tmpLog.GetCount()); + } + } + log.Close(); + tmpLog.Close(); + + return m_SrcName.c_str(); +} +//--------------------------------------------------------------------------- +LPCSTR __fastcall TMainWnd::ConvHAMLOG(LPCSTR pName, int loadorg) +{ + AnsiString LogName = pName; + + char TmpName[256]; + sprintf(TmpName, "%s"TEMPLOGNAME, BgnDir); + m_SrcName = TmpName; + + if( !loadorg ) return m_SrcName.c_str(); + + CHamLog log; + if( log.Open(LogName.c_str()) == FALSE ) return NULL; + + CLogFile tmpLog; + tmpLog.Open(TmpName, TRUE); + if( !tmpLog.IsOpen() ) return NULL; + tmpLog.DeleteAll(); + + SDMMLOG sd; + CWaitCursor w; + while(log.Read(&sd)==TRUE){ + if( (sd.mode == 8) && (sd.band >= B_35) ){ + sd.opt1[0] = 0; sd.opt2[0] = 0; + AdjustHamlogRSV(&sd); + tmpLog.PutData(&sd, tmpLog.GetCount()); + } + } + log.Close(); + tmpLog.Close(); + + return m_SrcName.c_str(); +} +//--------------------------------------------------------------------------- +void __fastcall TMainWnd::AdjustHamlogRSV(SDMMLOG *sp) +{ + char bf[MLREM+1]; + if( strlen(sp->ur) <= 3 ){ + NumCopy(bf, sp->rem); + if( bf[0] ){ + int n = atoin(bf, -1); + sprintf(bf, "%03u", n); + strcat(sp->ur, bf); + } + } + if( strlen(sp->my) <= 3 ){ + NumCopy(bf, sp->qsl); + if( bf[0] ){ + int n = atoin(bf, -1); + sprintf(bf, "%03u", n); + strcat(sp->my, bf); + } + } +} +//--------------------------------------------------------------------------- + + \ No newline at end of file diff --git a/JASTA/Main.dfm b/JASTA/Main.dfm new file mode 100644 index 0000000..21db139 Binary files /dev/null and b/JASTA/Main.dfm differ diff --git a/JASTA/Main.h b/JASTA/Main.h new file mode 100644 index 0000000..87b42ac --- /dev/null +++ b/JASTA/Main.h @@ -0,0 +1,122 @@ +//--------------------------------------------------------------------------- +#ifndef MainH +#define MainH +//--------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +//--------------------------------------------------------------------------- +#include "LogFile.h" +#include "Country.h" +#include "FEdit.h" + +//--------------------------------------------------------------------------- +class TMainWnd : public TForm +{ +__published: // IDE 管理のコンポーネント + TMainMenu *MainMenu; + TStringGrid *Grid; + TMenuItem *KF; + TMemo *Memo; + TMenuItem *KFL; + TOpenDialog *OpenDialog; + TMenuItem *KFS; + TMenuItem *KV; + TMenuItem *KVL; + TMenuItem *KVS; + TMenuItem *KH; + TMenuItem *KHT; + TMenuItem *KHW; + TMenuItem *N1; + TMenuItem *KHM; + TMenuItem *KHR; + TMenuItem *N2; + TMenuItem *KFR; + TMenuItem *KVA; + void __fastcall GridDrawCell(TObject *Sender, int Col, int Row, + TRect &Rect, TGridDrawState State); + + void __fastcall KFLClick(TObject *Sender); + void __fastcall FormCloseQuery(TObject *Sender, bool &CanClose); + void __fastcall KFSClick(TObject *Sender); + void __fastcall KVLClick(TObject *Sender); + void __fastcall KVSClick(TObject *Sender); + void __fastcall KVClick(TObject *Sender); + void __fastcall MemoClick(TObject *Sender); + + void __fastcall KHWClick(TObject *Sender); + void __fastcall KHTClick(TObject *Sender); + void __fastcall KHMClick(TObject *Sender); + void __fastcall KHRClick(TObject *Sender); + void __fastcall GridDblClick(TObject *Sender); + void __fastcall MemoDblClick(TObject *Sender); + void __fastcall KFRClick(TObject *Sender); + void __fastcall KFClick(TObject *Sender); + void __fastcall KVAClick(TObject *Sender); +private: // ユーザー宣言 + AnsiString m_SrcName; + SYSTEMTIME m_now; + int m_FIndex; + int m_Year; + int m_Days; + + int m_ShowErrCount; + + int m_CountHF; + int m_CountVU; + int m_CountS; + + CMULT m_MJA; + CMULT m_MDX; + CMULT m_DUP; + + int m_errDUP; + int m_errINV; + int m_errNOF; + int m_errMLT; + int m_errBND; + + char m_LogName[256]; + char m_SumName[256]; + char m_AnaName[256]; + + TFileEdit *m_pEditLog; + TFileEdit *m_pEditSum; + TFileEdit *m_pEditAna; + + CWebRef WebRef; + + int m_GridMove; + int m_ReCalc; + + void __fastcall SetTitle(void); + void __fastcall SetLanguage(void); + void __fastcall ReadRegister(void); + void __fastcall WriteRegister(void); + int __fastcall IsValidRST(LPSTR pRST); + void __fastcall AdjustData(SDMMLOG *sp); + void __fastcall ShowErr(StrText *tp, int n, SDMMLOG *sp, LPCSTR pKey); + void __fastcall Exec(LPCSTR pName, int loadorg); + void __fastcall Calc(LPCSTR pName); + void __fastcall MoveGrid(int n); + int __fastcall GetBNO(int b); + void __fastcall MakeANA(void); + + LPCSTR __fastcall ConvADIF(LPCSTR pName, int loadorg); + LPCSTR __fastcall ConvLog200(LPCSTR pName, int loadorg); + LPCSTR __fastcall ConvHAMLOG(LPCSTR pName, int loadorg); + void __fastcall AdjustHamlogRSV(SDMMLOG *sp); + +public: // ユーザー宣言 + __fastcall TMainWnd(TComponent* Owner); +}; +//--------------------------------------------------------------------------- +extern PACKAGE TMainWnd *MainWnd; +//--------------------------------------------------------------------------- +#endif + + \ No newline at end of file diff --git a/JASTA/OptDlg.cpp b/JASTA/OptDlg.cpp new file mode 100644 index 0000000..ab11fb6 --- /dev/null +++ b/JASTA/OptDlg.cpp @@ -0,0 +1,117 @@ +//--------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "OptDlg.h" +#include "Country.h" +//--------------------------------------------------------------------- +#pragma resource "*.dfm" +//TOptDlgBox *OptDlgBox; +//--------------------------------------------------------------------- +__fastcall TOptDlgBox::TOptDlgBox(TComponent* AOwner) + : TForm(AOwner) +{ +} +//--------------------------------------------------------------------- +void __fastcall TOptDlgBox::SetLanguage(void) +{ + if( RGL->ItemIndex ){ + Caption = "Setup"; + Font->Name = "Arial"; + Font->Charset = ANSI_CHARSET; + + RGL->Caption = "Language"; + RGL->Items->Strings[0] = "Japanese"; + RGL->Items->Strings[1] = "English"; + L1->Caption = "Callsign"; + L2->Caption = "Year"; + RGC->Caption = "Entry Section"; + RGC->Items->Strings[0] = "J (Japan)"; + RGC->Items->Strings[1] = "S"; + RGF->Caption = "First time entry"; + RGF->Items->Strings[0] = "No"; + RGF->Items->Strings[1] = "Yes"; + L3->Caption = "ZIP"; + L4->Caption = "Address"; +// L5->Caption = "E-Mail"; + L6->Caption = "Name"; + L7->Caption = "License"; + L9->Caption = "Size of T-shirts as an Activity Premium"; + + CancelBtn->Caption = "Cancel"; + } + else { + Caption = "セットアップ"; + Font->Name = "MS Pゴシック"; + Font->Charset = SHIFTJIS_CHARSET; + + RGL->Caption = "言語 (Language)"; + RGL->Items->Strings[0] = "日本語(Japanese)"; + RGL->Items->Strings[1] = "英語(English)"; + L1->Caption = "コールサイン"; + L2->Caption = "集計年度"; + RGC->Caption = "参加部門"; + RGC->Items->Strings[0] = "J (日本国内)"; + RGC->Items->Strings[1] = "S (海外)"; + RGF->Caption = "初参加"; + RGF->Items->Strings[0] = "過去にも参加した"; + RGF->Items->Strings[1] = "初参加"; + L3->Caption = "郵便番号"; + L4->Caption = "住所"; +// L5->Caption = "E-Mail"; + L6->Caption = "氏名"; + L7->Caption = "資格"; + L9->Caption = "アクティブ賞のT−シャツ当選時の希望サイズ"; + CancelBtn->Caption = "キャンセル"; + } +} +//--------------------------------------------------------------------- +int __fastcall TOptDlgBox::Execute(void) +{ + RGL->ItemIndex = MsgEng; + SetLanguage(); + + EditCall->Text = sys.m_Call; + EditYear->Text = sys.m_Year; + RGC->ItemIndex = sys.m_Category; + RGF->ItemIndex = sys.m_First; + EditZip->Text = sys.m_Zip; + EditAdr->Text = sys.m_Adr; + EditMail->Text = sys.m_Mail; + EditName->Text = sys.m_Name; + EditLicense->Text = sys.m_License; + EditPow->Text = sys.m_Pow; + CBSex->ItemIndex = sys.m_Sexual; + CBTSize->ItemIndex = sys.m_TSize; + + if( ShowModal() == IDOK ){ + sys.m_Call = EditCall->Text.c_str(); + jstrupr(sys.m_Call.c_str()); + sscanf(AnsiString(EditYear->Text).c_str(), "%u", &sys.m_Year); + + sys.m_Category = RGC->ItemIndex; + sys.m_First = RGF->ItemIndex; + sys.m_Zip = EditZip->Text; + sys.m_Adr = EditAdr->Text; + sys.m_Mail = EditMail->Text; + sys.m_Name = EditName->Text; + sys.m_License = EditLicense->Text; + sys.m_Pow = EditPow->Text; + sys.m_Sexual = CBSex->ItemIndex; + sys.m_TSize = CBTSize->ItemIndex; + + MsgEng = RGL->ItemIndex; + return TRUE; + } + else { + return FALSE; + } +} +//--------------------------------------------------------------------- +void __fastcall TOptDlgBox::RGLClick(TObject *Sender) +{ + SetLanguage(); +} +//--------------------------------------------------------------------------- + + \ No newline at end of file diff --git a/JASTA/OptDlg.dfm b/JASTA/OptDlg.dfm new file mode 100644 index 0000000..6beb05e Binary files /dev/null and b/JASTA/OptDlg.dfm differ diff --git a/JASTA/OptDlg.h b/JASTA/OptDlg.h new file mode 100644 index 0000000..0c152ad --- /dev/null +++ b/JASTA/OptDlg.h @@ -0,0 +1,56 @@ +//---------------------------------------------------------------------------- +#ifndef OCBH +#define OCBH +//---------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//---------------------------------------------------------------------------- +#include "ComLib.h" +//---------------------------------------------------------------------------- +class TOptDlgBox : public TForm +{ +__published: + TButton *OKBtn; + TButton *CancelBtn; + TLabel *L1; + TEdit *EditCall; + TLabel *L2; + TComboBox *EditYear; + TRadioGroup *RGC; + TRadioGroup *RGF; + TLabel *L3; + TEdit *EditZip; + TLabel *L4; + TEdit *EditAdr; + TLabel *L5; + TEdit *EditMail; + TLabel *L6; + TEdit *EditName; + TLabel *L7; + TEdit *EditLicense; + TLabel *L8; + TEdit *EditPow; + TRadioGroup *RGL; + TComboBox *CBSex; + TLabel *L9; + TComboBox *CBTSize; + void __fastcall RGLClick(TObject *Sender); +private: + void __fastcall SetLanguage(void); + +public: + virtual __fastcall TOptDlgBox(TComponent* AOwner); + int __fastcall Execute(void); +}; +//---------------------------------------------------------------------------- +//extern PACKAGE TOptDlgBox *OptDlgBox; +//---------------------------------------------------------------------------- +#endif diff --git a/JASTA/QsoDlg.cpp b/JASTA/QsoDlg.cpp new file mode 100644 index 0000000..fa45592 --- /dev/null +++ b/JASTA/QsoDlg.cpp @@ -0,0 +1,49 @@ +//--------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "QsoDlg.h" +//--------------------------------------------------------------------- +#pragma resource "*.dfm" +//TQSODlgBox *QSODlgBox; +//--------------------------------------------------------------------- +__fastcall TQSODlgBox::TQSODlgBox(TComponent* AOwner) + : TForm(AOwner) +{ + if( MsgEng ){ + Font->Name = "Arial"; + Font->Charset = ANSI_CHARSET; + + L2->Caption = "Continent"; + CancelBtn->Caption = "Cancel"; + } +} +//--------------------------------------------------------------------- +int __fastcall TQSODlgBox::Execute(SDMMLOG *sp) +{ + char bf[256]; + + sprintf(bf, "%s %2u/%02u %02u%02u %s %s %s %s\n", + _band[sp->band], + sp->date / 100, sp->date % 100, + (sp->btime/30)/60, (sp->btime/30)%60, + sp->call, + sp->my, + sp->opt1, + sp->opt2 + ); + LOrg->Caption = bf; + EditDXCC->Text = sp->opt1; + EditCont->Text = sp->opt2; + if( ShowModal() == IDOK ){ + StrCopy(sp->opt1, AnsiString(EditDXCC->Text).c_str(), MLOPT); //ja7ude 0525 + jstrupr(sp->opt1); + StrCopy(sp->opt2, AnsiString(EditCont->Text).c_str(), MLOPT); //ja7ude 0525 + jstrupr(sp->opt2); + return TRUE; + } + else { + return FALSE; + } +} +//--------------------------------------------------------------------- diff --git a/JASTA/QsoDlg.dfm b/JASTA/QsoDlg.dfm new file mode 100644 index 0000000..f7582ae Binary files /dev/null and b/JASTA/QsoDlg.dfm differ diff --git a/JASTA/QsoDlg.h b/JASTA/QsoDlg.h new file mode 100644 index 0000000..8b973ef --- /dev/null +++ b/JASTA/QsoDlg.h @@ -0,0 +1,37 @@ +//---------------------------------------------------------------------------- +#ifndef QSODlgH +#define QSODlgH +//---------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//---------------------------------------------------------------------------- +#include "LogFile.h" +//---------------------------------------------------------------------------- +class TQSODlgBox : public TForm +{ +__published: + TButton *OKBtn; + TButton *CancelBtn; + TLabel *LOrg; + TLabel *L1; + TLabel *L2; + TEdit *EditDXCC; + TComboBox *EditCont; +private: +public: + virtual __fastcall TQSODlgBox(TComponent* AOwner); + + int __fastcall Execute(SDMMLOG *sp); +}; +//---------------------------------------------------------------------------- +//extern PACKAGE TQSODlgBox *QSODlgBox; +//---------------------------------------------------------------------------- +#endif diff --git a/JASTA/TextEdit.cpp b/JASTA/TextEdit.cpp new file mode 100644 index 0000000..2560875 --- /dev/null +++ b/JASTA/TextEdit.cpp @@ -0,0 +1,144 @@ +//--------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "ComLib.h" +#include "TextEdit.h" +//--------------------------------------------------------------------- +#pragma resource "*.dfm" + +//TTextEditDlg *TextEditDlg; +//--------------------------------------------------------------------- +__fastcall TTextEditDlg::TTextEditDlg(TComponent* AOwner) + : TForm(AOwner) +{ + FormStyle = ((TForm *)AOwner)->FormStyle; + ap = NULL; + Memo->Font->Pitch = fpFixed; + EntryAlignControl(); + Font->Name = ((TForm *)AOwner)->Font->Name; + Font->Charset = ((TForm *)AOwner)->Font->Charset; + if( MsgEng ){ + CancelBtn->Caption = "Cancel"; + FontBtn->Caption = "Font"; + Memo->Font->Name = "Courier New"; + Memo->Font->Charset = 0; + } +} +//--------------------------------------------------------------------- +int __fastcall TTextEditDlg::Execute(AnsiString &as, int flag, LPCSTR pTitle /* = NULL*/) +{ + CWaitCursor tw; + ap = as.c_str(); + if( flag != TRUE ){ + OKBtn->Visible = FALSE; + CancelBtn->Caption = MsgEng ? "Close":"閉じる"; + Memo->ReadOnly = TRUE; + } + if( pTitle != NULL ){ + Caption = pTitle; + } + tw.Delete(); + int r = ShowModal(); + if( r == IDOK ){ + if( Memo->Modified == FALSE ) return FALSE; + if( flag == TRUE ){ + as = Memo->Text; + } + return TRUE; + } + return FALSE; +} + +void __fastcall TTextEditDlg::FontBtnClick(TObject *Sender) +{ + FontDialog->Font->Assign(Memo->Font); + if( FontDialog->Execute() == TRUE ){ + CWaitCursor tw; + Memo->Font->Assign(FontDialog->Font); + Memo->Update(); + } +} +//--------------------------------------------------------------------------- +// サイズ変更コントロールの登録 +void __fastcall TTextEditDlg::EntryAlignControl(void) +{ + RECT rc; + rc.left = 0; + rc.top = 0; + rc.right = 792-1; + rc.bottom = 572-1; + + AlignList.EntryControl(OKBtn, &rc, OKBtn->Font); + AlignList.EntryControl(CancelBtn, &rc, CancelBtn->Font); + AlignList.EntryControl(FontBtn, &rc, FontBtn->Font); + AlignList.EntryControl(Memo, &rc, Memo->Font); + + int CX = ::GetSystemMetrics(SM_CXFULLSCREEN); + int CY = ::GetSystemMetrics(SM_CYFULLSCREEN); +// int CX = ::GetSystemMetrics(SM_CXSCREEN); +// int CY = ::GetSystemMetrics(SM_CYSCREEN); + if( (CX < Width)||(CY < Height) ){ + Top = 0; + Left = 0; + Width = CX; + Height = CY; + } + FormCenter(this, CX, CY); + if( Owner != NULL ){ + WindowState = ((TForm *)Owner)->WindowState; + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextEditDlg::FormResize(TObject *Sender) +{ + CWaitCursor tw; + AlignList.NewAlign(this); +} +//--------------------------------------------------------------------------- +void __fastcall TTextEditDlg::FormPaint(TObject *Sender) +{ + if( ap == NULL ) return; + CWaitCursor tw; + Memo->Text = ap; + ap = NULL; + Memo->Update(); +} +//--------------------------------------------------------------------------- +// テキストヘルプの表示 +void __fastcall ShowHelp(TForm *pForm, LPCSTR pName) +{ + char bf[2048]; + char Name[256]; + FILE *fp; + + sprintf(Name, "%s%s", BgnDir, pName); + CWaitCursor w; + if( (fp = fopen(Name, "rt"))!=NULL ){ + if( sys.m_HelpNotePad ){ + fclose(fp); + sprintf( bf, "NOTEPAD.EXE %s", Name); + WinExec(bf, SW_SHOWDEFAULT); + } + else { + AnsiString in; + while(!feof(fp)){ + if( fgets(bf, 2048, fp) != NULL ){ + ClipLF(bf); + in += bf; + in += "\r\n"; + } + } + fclose(fp); + TTextEditDlg *Box = new TTextEditDlg(pForm); + Box->Execute(in, FALSE, pName); + delete Box; + } + } + else { + ErrorMB( MsgEng ? "'%s' was not found.\r\n\r\nProbably this file will be provided in the future." : "'%s'が見つかりません.", Name); + } +} +//--------------------------------------------------------------------------- + + \ No newline at end of file diff --git a/JASTA/TextEdit.dfm b/JASTA/TextEdit.dfm new file mode 100644 index 0000000..26faaba Binary files /dev/null and b/JASTA/TextEdit.dfm differ diff --git a/JASTA/TextEdit.h b/JASTA/TextEdit.h new file mode 100644 index 0000000..7b50947 --- /dev/null +++ b/JASTA/TextEdit.h @@ -0,0 +1,52 @@ +//---------------------------------------------------------------------------- +#ifndef TextEditH +#define TextEditH +//---------------------------------------------------------------------------- +//ja7ude 0525 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//--------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +class TTextEditDlg : public TForm +{ +__published: + TButton *OKBtn; + TButton *CancelBtn; + TMemo *Memo; + TButton *FontBtn; + TFontDialog *FontDialog; + void __fastcall FontBtnClick(TObject *Sender); + void __fastcall FormResize(TObject *Sender); + + + + + void __fastcall FormPaint(TObject *Sender); + + +private: + int InitFlag; + LPCSTR ap; + + CAlignList AlignList; + void __fastcall EntryAlignControl(void); +public: + virtual __fastcall TTextEditDlg(TComponent* AOwner); + + int __fastcall Execute(AnsiString &as, int flag, LPCSTR pTitle = NULL); +}; +//---------------------------------------------------------------------------- +//extern TTextEditDlg *TextEditDlg; + +extern void __fastcall ShowHelp(TForm *pForm, LPCSTR pName); +//---------------------------------------------------------------------------- +#endif diff --git a/JASTA/country.cpp b/JASTA/country.cpp new file mode 100644 index 0000000..b10bcba --- /dev/null +++ b/JASTA/country.cpp @@ -0,0 +1,396 @@ +/************************************************************************ + カントリ識別処理モジュール + + Copyright (C) JE3HHT 1993-2000. +************************************************************************/ +//--------------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "ComLib.h" +#include "Country.h" +#include "string.h" +#include "stdlib.h" + +CCountry Cty; +/*#$% +======================================================== + 文字列から指定の文字をクリップする +-------------------------------------------------------- + s : 文字列のポインタ +-------------------------------------------------------- +-------------------------------------------------------- +======================================================== +*/ +static char *_delchr(char *s, char c) +{ + char *p; + + for( p = s; *p; p++ ){ + if( *p == c ){ + strcpy(p, p+1); + p--; + } + } + return(s); +} + +/*#$% +====================================================== + 異なる文字列のポインタを返す +------------------------------------------------------ + n : 範囲数の格納位置のポインタ + t : プリフィックスのポインタ + p : プリフィックスのポインタ +------------------------------------------------------ +------------------------------------------------------ +====================================================== +*/ +static LPSTR lcmpp(int *n, LPSTR s, LPSTR p) +{ + LPSTR t; + + for( t = s; *p && *t; p++, t++ ){ + if( *p != *t ){ + *n = (*p - *t) + 1; + if( *n > 26 ) *n = 26; + return(t); + } + } + *n = 0; + return(s); +} + +/*#$% +====================================================== + 文字列の比較を行う +------------------------------------------------------ + t : 対象文字列 + s : 基準文字列 +------------------------------------------------------ +------------------------------------------------------ +====================================================== +*/ +static int strcmpv(LPCSTR t, LPCSTR s) +{ + for( ; *s; s++, t++ ){ + if( *t != *s ) return(1); + } + return(0); +} + +static int svf; /* 完全一致フラグ */ +/*#$% +================================================================ + プリフィックス検索用文字列比較 +---------------------------------------------------------------- +---------------------------------------------------------------- +---------------------------------------------------------------- +================================================================ +*/ +static int _strcmp(LPCSTR t, LPCSTR v) +{ +/* printf( "<%s>-<%s>\n", v, t ); */ + for( ; *v; v++, t++ ){ + if( *v == '*' ){ + for( v++; *t && strcmpv(t, v); t++ ); + if( !*t ) return(1); + } + else if( *v == '\\' ){ + if( *t ) return(1); + } + else if( (*v!='?') && (*v != *t) ){ + return(1); + } + } + if( svf && *t ) return(1); + return(0); +} + +/*#$% +====================================================== + コンストラクター +------------------------------------------------------ +------------------------------------------------------ +------------------------------------------------------ +====================================================== +*/ +CCountry::CCountry() +{ + Init(); +} + +CCountry::~CCountry(void) +{ + Free(); +} + +/*#$% +====================================================== + DXCC定義領域を開放する +------------------------------------------------------ +------------------------------------------------------ +------------------------------------------------------ +====================================================== +*/ +void CCountry::Init(void) +{ + cmax = 0; + memset(ctl, 0, sizeof(ctl)); +} + +/*#$% +====================================================== + DXCC定義領域を開放する +------------------------------------------------------ +------------------------------------------------------ +------------------------------------------------------ +====================================================== +*/ +void CCountry::Free(void) +{ + int i; + CTL *cp; + + for( cp = ctl, i = 0; i < cmax; i++, cp++ ){ + if( cp->Name != NULL ) delete cp->Name; + if( cp->Code != NULL ) delete cp->Code; + if( cp->QTH != NULL ) delete cp->QTH; + if( cp->Cont != NULL ) delete cp->Cont; + if( cp->TD != NULL ) delete cp->TD; + } + Init(); +} + + +/*#$% +====================================================== + プリフィックスからカントリコードを得る +------------------------------------------------------ + p : プリフィックスのポインタ +------------------------------------------------------ + カントリコード +------------------------------------------------------ +====================================================== +*/ +int CCountry::GetNo(LPCSTR s) +{ + LPSTR p, pb, t, pp; + int i; + int j; + + if( !*s ) return(0); + for( i = 0; i < cmax; i++ ){ + strcpy(wbf, ctl[i].Code); + for( p = wbf; *p; ){ + p = StrDlm(pb, p, ','); + if( (t = strchr(pb, '-')) != NULL ){ + *t = 0; + t++; + if( (*pb == *s) || (*pb != *t) ){ + for( pp = lcmpp(&j, pb, t); j; (*pp)++, j-- ){ + if( !_strcmp(s, pb) ) return(i+1); + } + } + } + else { + if( !_strcmp(s, pb) ) return(i+1); + } + } + } + return(0); +} + +/*#$% +====================================================== + コールサインからポインタを得る +------------------------------------------------------ + p : コールサインのポインタ +------------------------------------------------------ + ポインタ +------------------------------------------------------ +====================================================== +*/ +int CCountry::GetNoP(LPCSTR p) +{ + int n; + + svf = 1; + if( (n = GetNo(p))!=0 ) return(n); + svf = 0; + if( (n = GetNo(p))!=0 ) return(n); + return(0); +} +/*#$% +====================================================== + コールサインからポインタを得る +------------------------------------------------------ + p : コールサインのポインタ +------------------------------------------------------ + ポインタ +------------------------------------------------------ +====================================================== +*/ +int CCountry::GetRefP(LPCSTR p) +{ + if( !cmax ) return 0; + int n; + + if( !(*p) ) return 0; + if( ((n = GetNoP(p))!=0) && (ctl[n-1].Name != NULL) ){ + return n; + } + else { + return 0; + } +} +/*#$% +====================================================== + コールサインからカントリ名を得る +------------------------------------------------------ + p : コールサインのポインタ +------------------------------------------------------ + カントリ名のポインタ +------------------------------------------------------ +====================================================== +*/ +LPCSTR CCountry::GetCountry(int n) +{ + if( n ){ + strcpy(wbf, ctl[n-1].Name); + return(wbf); + } + else { + return("?"); + } +} +/*#$% +====================================================== + コールサインから大陸名を得る +------------------------------------------------------ + p : コールサインのポインタ +------------------------------------------------------ + カントリ名のポインタ +------------------------------------------------------ +====================================================== +*/ +LPCSTR CCountry::GetCont(int n) +{ + if( n ){ + strcpy(wbf, ctl[n-1].Cont); + return(wbf); + } + else { + return("?"); + } +} +/*#$% +====================================================== + コールサインからカントリ名を得る +------------------------------------------------------ + p : コールサインのポインタ +------------------------------------------------------ + カントリ名のポインタ +------------------------------------------------------ +====================================================== +*/ +LPCSTR CCountry::GetCountry(LPCSTR p) +{ + if( !cmax ) return ""; + int n; + + if( !(*p) ) return("?"); + if( ((n = GetNoP(p))!=0) && (ctl[n-1].Name != NULL) ){ + strcpy(wbf, ctl[n-1].Name); + return(wbf); + } + else { + return("?"); + } +} + +/*#$% +====================================================== + コールサインから大陸名を得る +------------------------------------------------------ + p : コールサインのポインタ +------------------------------------------------------ + カントリ名のポインタ +------------------------------------------------------ +====================================================== +*/ +LPCSTR CCountry::GetCont(LPCSTR p) +{ + if( !cmax ) return ""; + int n; + + if( !(*p) ) return("?"); + if( ((n = GetNoP(p))!=0) && (ctl[n-1].Cont != NULL) ){ + strcpy(wbf, ctl[n-1].Cont); + return(wbf); + } + else { + return("?"); + } +} + +/*#$% +====================================================== + DXCC定義ファイルを読み込む +------------------------------------------------------ + fm : ファイル名のポインタ +------------------------------------------------------ +------------------------------------------------------ +====================================================== +*/ +void CCountry::Load(LPCSTR fm) +{ + FILE *fp; + LPCSTR p; + char hbf[512]; + + Free(); + if( (fp = fopen(fm, "rt"))!=NULL ){ + while( !feof(fp) ){ + if( fgets(hbf, 512, fp)!=NULL ){ + if( hbf[0] == '$' ) break; + ClipLF(hbf); + _delchr(hbf, TAB); + if( hbf[0] != '!' ){ + p = StrDlmCpy(wbf, hbf, ';', 512); + clipsp(wbf); + ctl[cmax].Name = StrDupe(wbf); + if( p != NULL ){ + p = StrDlmCpy(wbf, p, ';', 512); + clipsp(wbf); + ctl[cmax].Code = StrDupe(wbf); + } + if( p != NULL ){ + p = StrDlmCpy(wbf, p, ';', 512); + clipsp(wbf); + ctl[cmax].QTH = StrDupe(wbf); + } + if( p != NULL ){ + p = StrDlmCpy(wbf, p, ';', 512); + clipsp(wbf); + ctl[cmax].Cont = StrDupe(wbf); + } + if( p != NULL ){ + StrDlmCpy(wbf, p, ';', 512); + clipsp(wbf); + ctl[cmax].TD = StrDupe(wbf); + } + cmax++; + if( cmax >= CTMAX ) break; + } + } + } + fclose(fp); + } + else { + WarningMB(MsgEng ? "'ARRL.DX' was not found.\r\n\r\nYou cannot use a re-creating DX entity function.\r\nThis is not a problem if you do not need it":"'ARRL.DX'が見つかりません.\r\n\r\nDXエンティティの再構築機能は使用できません."); + } +} + + + \ No newline at end of file diff --git a/JASTA/country.h b/JASTA/country.h new file mode 100644 index 0000000..9ccd03c --- /dev/null +++ b/JASTA/country.h @@ -0,0 +1,46 @@ +#ifndef CountryH +#define CountryH + +extern LPSTR StrDupe(LPCSTR s); +//---------------------------------------------------------------------------- + +#define CTMAX 512 +typedef struct { + LPSTR Name; + LPSTR Code; + LPSTR QTH; + LPSTR Cont; + LPSTR TD; +}CTL; + +class CCountry +{ +private: + int cmax; + CTL ctl[CTMAX]; + + char wbf[512]; +public: + CCountry(); + ~CCountry(void); + + inline CTL *GetCTL(int n){ return &ctl[n];}; + void Init(void); + void Free(void); + int GetNo(LPCSTR s); + int GetNoP(LPCSTR p); + int GetRefP(LPCSTR p); + LPCSTR GetCountry(int n); + LPCSTR GetCont(int n); + + LPCSTR GetCountry(LPCSTR p); + LPCSTR GetCont(LPCSTR p); + void Load(LPCSTR fm); + inline int IsData(void){ + return cmax; + }; +}; + +extern CCountry Cty; +#endif + diff --git a/JASTA/mmjasta.txt b/JASTA/mmjasta.txt new file mode 100644 index 0000000..38bd7c7 --- /dev/null +++ b/JASTA/mmjasta.txt @@ -0,0 +1,96 @@ +MMJASTA.EXE + + 初版 2002年9月 3日 JE3HHT 森 誠 + 改訂 2004年9月 8日 JE3HHT 森 誠 + + MMJASTAは、JASTA主宰のアクティビティコンテスト(8月開催)のログシートおよびサマリーシート(日本語様式および英語様式)を作成するためのコンテスト集計用プログラムです。 + MMSSTVで記録されたログデータから自動的にログシートおよびサマリーシートを作成することができます。 + +------------------------------------------------ +変更履歴 +- 3D2/Rの判定ミスを修正(2005/SEP/02) +- アクティブ賞当選時のTシャツサイズをサマリに追加(2005/AUG/09) +- OM/YL区別を追加 (2004/SEP/08) +- 得点計算から衛星通信の区別を削除 (2004/SEP/08) +------------------------------------------------ + +1.環境設定 +~~~~~~~~~~~~ + MMJASTAを起動し、ファイルメニューの「セットアップ」で必要な項目をすべて記入して下さい。ここで記録した情報は「MMJASTA.INI」ファイルに記録されますので、次回起動時に失うことはありません。 + + 使用言語は、日本国内局の場合「日本語」、それ以外の局の場合は「英語」を選択して下さい。それぞれ日本語様式、英語様式のサマリを作成できます。なおこの選択は初回起動時にWindowsのロケール情報により自動的に設定されます。 + + +2.ログファイルのロード +~~~~~~~~~~~~~~~~~~~~~~~~ + ファイルメニューの「ログファイルのロード」を選択し、MMSSTVで記録されたログファイル(拡張子はMDT)を選択して下さい。これで自動的に集計計算し、ログシートとサマリーシートを作成します。 + + MMJASTAが生成するファイルの名前は以下のようになり、MMJASTA.EXEが存在するフォルダに作成されます。 + + ログシート Callsign.txt + サマリシート Callsign.sum + 分析ファイル Callsign.ana + + MMJASTAは日付およびHisRSVのナンバーの有無でフィルタをかけますので、読みこむログは、コンテスト以外のQSOが記録されていても構いません。 + + +3.DXエンティティ +~~~~~~~~~~~~~~~~~~ + MMJASTAおよびMMSSTVは、ほとんどのDXエンティティの名前と大陸区分を、自動的に判定します。しかしコールサインからDXエンティティが一意に確定できない場合、例えば「JD1/?」のようにエンティティ名が生成され、MMJASTAでエラーメッセージが表示されます。 + + この場合、MMJASTAのウインドウ下側の警告表示を見ます。未確定のDXエンティティ名があると、 + +194 8/21 1502Z 14 JD1ABC 595194 595131 : DXCC Unknown [JD1/?] + +のように表示されていますので、この行をダブルクリックします。 + マルチ修正用の画面が表示されますので、そこで、マルチを「JD1/M」、大陸名を「OC」のように修正して「OK」ボタンを押します。この操作で参照元(オリジナル)のログファイルの同一コールサインのOPT1およびOPT2フィールドがすべて修正されます。 + + 上記の操作を繰り返し、すべての「DXCC Unknown」を修正したら、ファイルメニューの「再集計(R)」を実行し、集計しなおせばOKです。 + +*2002年現在のJASTAコンテストのルールでは、大陸名は得点に影響しませんが、将来の拡張用として修正できるようにしてあります。 + + +4.無効なQSOの取り扱い +~~~~~~~~~~~~~~~~~~~~~~~ + MMJASTAは以下のいずれかの場合、無効なQSOとしてそのQSOについてポイントおよびマルチを計上しません。 + ・同一日(UTC)に同じ局とのQSOが重複している場合(後者を無効化) + ・RcvdのコンテストNRが未記入の場合 + ・REMフィールドに「NOF」または「NOFACE」の文字列が存在する場合 + (相手局の画像に顔写真が存在しない場合にNOFを記録しておく) + + +5.他の形式のログファイル +~~~~~~~~~~~~~~~~~~~~~~~~~~ + MMJASTAは以下のログフォーマットを変換して読み込むこともできます。 + + - ADIF形式 (ADI) + - Log200形式 (L2) + - Turbo HAMLOG形式 (DBS, DBR) + + これらの形式のファイルが指定された場合、MMJASTAは"MMJASTA.MDT"というMDT形式のファイルを一旦作成しそこにデータを変換します。その後の動作は、MDTファイルを扱う場合と同じです。MMJASTAで「DXCC Unknown」を修正した場合、MMJASTA.MDTは更新されますが、参照元ファイルは更新されません。 + + 参照元ファイル -> MMJASTA.MDT -> 集計 + + + 各形式についてMMJASTAは以下の条件を適用します。 + +[ADIF形式] + モードの名前はSSTVでなければなりません。 + STXおよびSRXにコンテストNRが記録されていなければなりません。 + +[Log200形式] + モードの名前はSSTVでなければなりません。 + HisRSTおよびMyRSTに595001の形式でRSVとコンテストNRが連続して記録されていなければなりません。 + +[Turbo HAMLOG形式]  + モードの名前はSTVまたはSSTでなければなりません。 + 以下のいずれかの方法でコンテストNRが記録されていなければなりません。 + - REM1またはREM2にSN[...], RN[...]の形式で記録 + - REM1とREM2にそれぞれSentおよびRcvdのNRが先頭から記録 + + +6.使用上の注意 +~~~~~~~~~~~~~~~~ + MMJASTAはコンテストの集計を自動化しますが、必ず最後にログとサマリの確認を、あなた自身の手で行って下さい。 + +73, Mako diff --git a/LineSet.cpp b/LineSet.cpp new file mode 100644 index 0000000..8b9e1db --- /dev/null +++ b/LineSet.cpp @@ -0,0 +1,178 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "Comlib.h" +#include "LineSet.h" +#include "Main.h" +//--------------------------------------------------------------------- +#pragma resource "*.dfm" +//TLineSetDlg *LineSetDlg; +LPCSTR pStyle[2][9]={ + {"なし","実線", "破線", "点線", "一点鎖線", "二点鎖線","縁取り線", "縁取り線(細)", NULL}, + {"None","Solid", "Dash", "Dot", "DashDot", "DashDotDot", "Siege", "Siege(narrow)", NULL}, +}; +int LineTable[]={-1, psSolid, psDash, psDot, psDashDot, psDashDotDot, 5, 6}; +//--------------------------------------------------------------------- +__fastcall TLineSetDlg::TLineSetDlg(TComponent* AOwner) + : TForm(AOwner) +{ + FormStyle = ((TForm *)AOwner)->FormStyle; + Font->Name = ((TForm *)AOwner)->Font->Name; + Font->Charset = ((TForm *)AOwner)->Font->Charset; + if( MsgEng ){ + Caption = "Line"; + CancelBtn->Caption = "Cancel"; + LS->Caption = "Style"; + LW->Caption = "Width"; + LC->Caption = "Color"; + LT->Caption = "Shape"; + m_lmode = 1; + } + else { + m_lmode = 0; + } + LineStyle->Clear(); + for( int i = 0; pStyle[m_lmode][i] != NULL; i++ ){ + LineStyle->Items->Add(pStyle[m_lmode][i]); + } +} +//--------------------------------------------------------------------- +void __fastcall TLineSetDlg::UpdateUI(void) +{ + int f = (LineStyle->ItemIndex != 1) ? FALSE : TRUE; + LW->Enabled = f; + LineWidth->Enabled = f; +} +//--------------------------------------------------------------------- +int __fastcall TLineSetDlg::Execute(CDraw *pItem) +{ + int cmd = pItem->m_Command; + LineStyle->ItemIndex = 1; + int i; + for( i = 0; pStyle[0][i] != NULL; i++ ){ + if( LineTable[i] == pItem->m_LineStyle ){ + LineStyle->ItemIndex = i; + } + } + LineWidth->Text = pItem->m_LineWidth; + CDrawText *pText = (CDrawText *)pItem; + CDrawPic *pPic = (CDrawPic *)pItem; + LPCSTR *pTbl = NULL; + switch(cmd){ + case CM_PIC: + if( pPic->m_Type < 2 ){ + pTbl = MsgEng ? _ShapePIC[0] : _ShapePIC[1]; + } + break; + case CM_BOX: + case CM_BOXS: + pTbl = MsgEng ? _ShapeBOX[0] : _ShapeBOX[1]; + break; + } + if( pTbl != NULL ){ + while(*pTbl){ + BoxStyle->Items->Add(*pTbl++); + } + } + BoxStyle->ItemIndex = cmd != CM_PIC ? pItem->m_BoxStyle : pPic->m_Shape; + if( cmd == CM_TEXT ){ + pItem->m_LineStyle = psSolid; + LineStyle->ItemIndex = 1; + LS->Enabled = FALSE; + LineStyle->Enabled = FALSE; + PCol->Color = ( pText->m_Shadow == 6 ) ? pText->m_LineColor : pText->m_ColS; + } + else { + PCol->Color = pItem->m_LineColor; + } + if( pTbl != NULL ){ + LT->Enabled = TRUE; + BoxStyle->Enabled = TRUE; + } + else { + LT->Enabled = FALSE; + BoxStyle->Enabled = FALSE; + } + UpdateUI(); + if( ShowModal() == IDOK ){ + pItem->m_LineStyle = TPenStyle(LineTable[LineStyle->ItemIndex]); + int d; + sscanf(AnsiString(LineWidth->Text).c_str(), "%d", &d); //ja7ude 0521 + if( (d >= 1) && (d < 1024) ){ + pItem->m_LineWidth = d; + } + if( LineStyle->ItemIndex != 1 ){ + pItem->m_LineWidth = 1; + } + if( (pItem->m_Command == CM_TEXT) && (pText->m_Shadow != 6) ){ + pText->m_ColS = PCol->Color; + } + else { + pItem->m_LineColor = PCol->Color; + } + pItem->m_BoxStyle = 0; + if( pTbl != NULL ){ + if( cmd == CM_PIC ){ + pPic->m_Shape = BoxStyle->ItemIndex; + } + else { + pItem->m_BoxStyle = BoxStyle->ItemIndex; + } + if( pItem->m_BoxStyle == 5 ){ + int xl = pItem->m_X2 - pItem->m_X1; + int yl = pItem->m_Y2 - pItem->m_Y1; + if( xl != yl ){ + if( xl > yl ){ + pItem->m_Y2 = pItem->m_Y1 + xl; + } + else { + pItem->m_X2 = pItem->m_X1 + yl; + } + } + } + } + return TRUE; + } + return FALSE; +} +//--------------------------------------------------------------------- +void __fastcall TLineSetDlg::PColClick(TObject *Sender) +{ + TColorDialog *pDialog = Mmsstv->ColorDialog; + InitCustomColor(pDialog); + AddCustomColor(pDialog, PCol->Color); + pDialog->Color = PCol->Color; + SetDisPaint(); + if( pDialog->Execute() == TRUE ){ + PCol->Color = pDialog->Color; + } + ResDisPaint(); +} +//--------------------------------------------------------------------------- + +void __fastcall TLineSetDlg::LineStyleChange(TObject *Sender) +{ + UpdateUI(); +} +//--------------------------------------------------------------------------- + diff --git a/LineSet.dfm b/LineSet.dfm new file mode 100644 index 0000000..fc34def Binary files /dev/null and b/LineSet.dfm differ diff --git a/LineSet.h b/LineSet.h new file mode 100644 index 0000000..a3114ab --- /dev/null +++ b/LineSet.h @@ -0,0 +1,65 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//---------------------------------------------------------------------------- +#ifndef LineSetH +#define LineSetH +//---------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//---------------------------------------------------------------------------- +#include "Draw.h" +//---------------------------------------------------------------------------- +class TLineSetDlg : public TForm +{ +__published: + TButton *OKBtn; + TButton *CancelBtn; + TLabel *LS; + TLabel *LW; + TComboBox *LineStyle; + TComboBox *LineWidth; + TLabel *LC; + TPanel *PCol; + TLabel *LT; + TComboBox *BoxStyle; + void __fastcall PColClick(TObject *Sender); + + void __fastcall LineStyleChange(TObject *Sender); +private: + int m_lmode; + void __fastcall UpdateUI(void); + +public: + virtual __fastcall TLineSetDlg(TComponent* AOwner); + + int __fastcall Execute(CDraw *pItem); +}; +//---------------------------------------------------------------------------- +//extern PACKAGE TLineSetDlg *LineSetDlg; +//---------------------------------------------------------------------------- +#endif diff --git a/LinearDs.cpp b/LinearDs.cpp new file mode 100644 index 0000000..a935e0c --- /dev/null +++ b/LinearDs.cpp @@ -0,0 +1,127 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "ComLib.h" +#include "LinearDs.h" +//--------------------------------------------------------------------- +#pragma resource "*.dfm" +//--------------------------------------------------------------------- +__fastcall TLinearDspDlg::TLinearDspDlg(TComponent* AOwner) + : TForm(AOwner) +{ + FormStyle = ((TForm *)AOwner)->FormStyle; + Font->Name = ((TForm *)AOwner)->Font->Name; + Font->Charset = ((TForm *)AOwner)->Font->Charset; + if( MsgEng ){ + Caption = "frequency characteristic"; + } + pData = NULL; +} +//--------------------------------------------------------------------- +void __fastcall TLinearDspDlg::Execute(double *D) +{ + pData = D; + ShowModal(); +} +//--------------------------------------------------------------------- +void __fastcall TLinearDspDlg::PBoxPaint(TObject *Sender) +{ + PBox->Canvas->Font->Size = 8; + int XL = PBox->Canvas->TextWidth("-16000") + 10; + int YT = PBox->Canvas->TextHeight("-16000"); + int YB = PBox->Height - YT - 10; + int XR = PBox->Width - (XL/2); + + int i, fq, x, y; + char bf[32]; + PBox->Canvas->Pen->Color = clGray; + for( fq = 1500, i = 0; i <= 16; i++, fq += 50 ){ + x = XL + i * (XR - XL)/16; + PBox->Canvas->Pen->Style = i & 1 ? psDot : psSolid; + PBox->Canvas->MoveTo(x, YT); + PBox->Canvas->LineTo(x, YB); + if( !(i & 1) ){ + sprintf(bf, "%4u", fq); + int w = PBox->Canvas->TextWidth(bf)/2; + PBox->Canvas->TextOut(x - w, YB + 5, bf); + } + } + int vm; + if( *pData >= 16000 ){ + vm = 20000; + } + else if( *pData >= 10000 ){ + vm = 16000; + } + else if( *pData >= 8000 ){ + vm = 10000; + } + else if( *pData >= 6000 ){ + vm = 8000; + } + else if( *pData >= 5000 ){ + vm = 6000; + } + else if( *pData >= 4000 ){ + vm = 5000; + } + else if( *pData >= 2000 ){ + vm = 4000; + } + else if( *pData >= 1000 ){ + vm = 2000; + } + else { + vm = 1000; + } + fq = vm; + for( i = 0; i <= 4; i++, fq -= (vm / 2) ){ + y = YT + i * (YB - YT)/4; + PBox->Canvas->Pen->Style = i & 1 ? psDot : psSolid; + PBox->Canvas->MoveTo(XL, y); + PBox->Canvas->LineTo(XR, y); + sprintf(bf, "%d", fq); + int w = PBox->Canvas->TextWidth(bf); + int h = PBox->Canvas->TextHeight(bf); + if( i < 4 ) h /= 2; + PBox->Canvas->TextOut(XL-w-3, y - h, bf); + } + if( pData == NULL ) return; + + PBox->Canvas->Pen->Color = clBlue; + PBox->Canvas->Pen->Style = psSolid; + for( i = 0; i <= 16; i++ ){ + x = XL + i * (XR - XL)/16; + y = pData[i] * (YB - YT) / (vm * 2); + y += (YB - YT)/2; + y = YB - y; + if( i ){ + PBox->Canvas->LineTo(x, y); + } + else { + PBox->Canvas->MoveTo(x, y); + } + } +} +//--------------------------------------------------------------------------- + diff --git a/LinearDs.dfm b/LinearDs.dfm new file mode 100644 index 0000000..0427a0c Binary files /dev/null and b/LinearDs.dfm differ diff --git a/LinearDs.h b/LinearDs.h new file mode 100644 index 0000000..f4c9464 --- /dev/null +++ b/LinearDs.h @@ -0,0 +1,51 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//---------------------------------------------------------------------------- +#ifndef OCBH +#define OCBH +//---------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//---------------------------------------------------------------------------- +#define LINEARDATAMAX 16 +class TLinearDspDlg : public TForm +{ +__published: + TPanel *Panel; + TPaintBox *PBox; + void __fastcall PBoxPaint(TObject *Sender); +private: + double *pData; +public: + virtual __fastcall TLinearDspDlg(TComponent* AOwner); + + void __fastcall Execute(double *D); +}; +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +#endif diff --git a/ListText.cpp b/ListText.cpp new file mode 100644 index 0000000..d3a8daf --- /dev/null +++ b/ListText.cpp @@ -0,0 +1,320 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "ComLib.h" +#include "Main.h" +#include "ListText.h" +//--------------------------------------------------------------------- +#pragma resource "*.dfm" +static int SaveTopRow; +static int SaveRow; +//--------------------------------------------------------------------- +__fastcall TListTextDlg::TListTextDlg(TComponent* AOwner) + : TForm(AOwner) +{ + MultProc(); + FormStyle = ((TForm *)AOwner)->FormStyle; + Font->Name = ((TForm *)AOwner)->Font->Name; + Font->Charset = ((TForm *)AOwner)->Font->Charset; + if( MsgEng ){ + Caption = "Defined text"; + CancelBtn->Caption = "Cancel"; + DelBtn->Caption = "Delete"; + EditBtn->Caption = "Edit"; + UpBtn->Caption = "Up"; + DwnBtn->Caption = "Down"; + m_Jpn = 0; + } + else { + m_Jpn = 1; + } + pList = NULL; + MultProc(); +} +//--------------------------------------------------------------------- +void __fastcall TListTextDlg::UpdateUI(void) +{ + if( Grid->Row && (Grid->Row <= pList->m_Cnt) ){ + DelBtn->Enabled = TRUE; + OKBtn->Enabled = TRUE; + } + else { + DelBtn->Enabled = FALSE; + OKBtn->Enabled = FALSE; + } + EditBtn->Enabled = Grid->Row ? TRUE : FALSE; + UpBtn->Enabled = (Grid->Row > 1) && (Grid->Row <= pList->m_Cnt) ? TRUE : FALSE; + DwnBtn->Enabled = (Grid->Row <= (pList->m_Cnt - 1)) ? TRUE : FALSE; +} +//--------------------------------------------------------------------- +CDraw *__fastcall TListTextDlg::Execute(CDrawGroup *pg, int pos) +{ + pList = pg; + Grid->RowCount = pList->m_Cnt + 2; + if( pos < 0 ){ + Grid->Row = Grid->RowCount - 2; + int n = Grid->Row - 11; + if( n < 1 ) n = 1; + Grid->TopRow = n; + } + else if( SaveRow && SaveTopRow ){ + Grid->TopRow = SaveTopRow; + Grid->Row = SaveRow; + } + UpdateUI(); + MultProc(); + int r = ShowModal(); + MultProc(); + SaveTopRow = Grid->TopRow; + SaveRow = Grid->Row; + if( r == IDOK ){ + return (CDraw *)pList->pBase[Grid->Row - 1]; + } + return NULL; +} +//--------------------------------------------------------------------- +void __fastcall TListTextDlg::DrawGrade(CDrawText *pItem, TRect &Rect) +{ + TRect rc = Rect; + rc.Top += 2; + rc.Bottom -= 2; + int xw = (Rect.Right - Rect.Left)/4; + int yw = (Rect.Bottom - Rect.Top)/4; + switch(pItem->m_Grade){ + case 0: + Grid->Canvas->Brush->Color = pItem->m_Col1; + Grid->Canvas->FillRect(rc); + break; + case 1: + rc.Right = rc.Left + xw; + Grid->Canvas->Brush->Color = pItem->m_Col1; + Grid->Canvas->FillRect(rc); + rc.Left += xw; + rc.Right += xw; + Grid->Canvas->Brush->Color = pItem->m_Col2; + Grid->Canvas->FillRect(rc); + rc.Left += xw; + rc.Right += xw; + Grid->Canvas->Brush->Color = pItem->m_Col3; + Grid->Canvas->FillRect(rc); + rc.Left += xw; + rc.Right += xw; + Grid->Canvas->Brush->Color = pItem->m_Col4; + Grid->Canvas->FillRect(rc); + break; + case 2: + rc.Bottom = rc.Top + yw; + Grid->Canvas->Brush->Color = pItem->m_Col1; + Grid->Canvas->FillRect(rc); + rc.Top += yw; + rc.Bottom += yw; + Grid->Canvas->Brush->Color = pItem->m_Col2; + Grid->Canvas->FillRect(rc); + rc.Top += yw; + rc.Bottom += yw; + Grid->Canvas->Brush->Color = pItem->m_Col3; + Grid->Canvas->FillRect(rc); + rc.Top += yw; + rc.Bottom += yw; + Grid->Canvas->Brush->Color = pItem->m_Col4; + Grid->Canvas->FillRect(rc); + break; + } +} +//--------------------------------------------------------------------- +void __fastcall TListTextDlg::DrawShadow(CDrawText *pItem, TRect &Rect) +{ + LPCSTR _tt[2][9]={ + {"None","Siege", "Shadow1", "Shadow2", "Shadow3", "Shadow4", "Shadow5", "Shadow6", "?",}, + {"なし","縁取り", "影1", "影2","影3","影4","影5","影6","?"}, + }; + int X = Rect.Left + 4; + int Y = Rect.Top + 2; + TRect rc = Rect; + rc.Top += 2; + rc.Bottom -= 2; + rc.Left = rc.Right - (Rect.Right - Rect.Left)/4; + int n = pItem->m_Shadow; + if( (n < 0) || (n > 8) ) n = 8; + Grid->Canvas->TextOut(X, Y, _tt[m_Jpn][n]); + if( pItem->m_Shadow ){ + Grid->Canvas->Brush->Color = pItem->m_ColS; + Grid->Canvas->FillRect(rc); + } +} +//--------------------------------------------------------------------- +static void __fastcall ConvCRLF(LPSTR s) +{ + LPSTR p = s; + for( ; *p; p++ ){ + if( (*p == CR) || (*p == LF) ){ + *p = '\\'; + } + } +} +//--------------------------------------------------------------------- +void __fastcall TListTextDlg::GridDrawCell(TObject *Sender, int Col, + int Row, TRect &Rect, TGridDrawState State) +{ + if( pList == NULL ) return; + + char bf[256]; + + Grid->Canvas->FillRect(Rect); + int X = Rect.Left + 4; + int Y = Rect.Top + 2; + + if( Row ){ + Row--; + bf[0] = 0; + int ec = 4; + if( Row < pList->m_Cnt ){ +// strcpy(bf, "-"); + bf[0] = 0; + LPCSTR p; + CDraw *pItem = pList->pBase[Row]; + CDrawLib *pLib = (CDrawLib *)pItem; + CDrawText *pText = (CDrawText *)pItem; + if( (pItem->m_Command != CM_TEXT) && (pItem->m_Command != CM_LIB) ) return; + if( pItem->m_Command == CM_LIB ) ec = 6; + switch(Col){ + case 0: // No. + sprintf(bf, "%u%s", Row+1, (pItem->m_Command == CM_LIB)?" c":""); + break; + case 1: // text + p = (pItem->m_Command == CM_TEXT) ? pText->m_Text.c_str() : pLib->GetItemText(); + StrCopy(bf, p, sizeof(bf)-1); + ConvCRLF(bf); + break; + case 2: // text + p = (pItem->m_Command == CM_TEXT) ? pText->m_Text.c_str() : pLib->GetItemText(); + Mmsstv->MacroText(bf, p, sizeof(bf)-1); + ConvCRLF(bf); + break; + case 3: // text + if( pItem->m_Command == CM_TEXT ){ + sprintf(bf, "%u", pText->pFont->Size); + } + break; + case 4: // color + if( pItem->m_Command == CM_TEXT ){ + DrawGrade(pText, Rect); + } + break; + case 5: // Shadow + if( pItem->m_Command == CM_TEXT ){ + DrawShadow(pText, Rect); + } + break; + } + if( pItem->m_Command == CM_TEXT ){ + if( ((Col == 1) || (Col == 2)) && (pText->pFont != NULL) ){ + Grid->Canvas->Font->Name = pText->pFont->Name; + Grid->Canvas->Font->Charset = pText->pFont->Charset; + } + } + else { + Grid->Canvas->Font->Name = Font->Name; + Grid->Canvas->Font->Charset = Font->Charset; + } + } + if( Col < ec ){ + Grid->Canvas->TextRect(Rect, X, Y, bf); + } + } + else { // タイトル + LPCSTR _tt[2][6]={ + {"No.","Defined Text", "Macro conversion", "Size", "Color", "Shadow",}, + {"No.","定義文字列", "マクロ変換", "サイズ","色","影",}, + }; + Grid->Canvas->TextRect(Rect, X, Y, _tt[m_Jpn][Col]); + } + if( !Col ) MultProc(); +} +//--------------------------------------------------------------------------- + +void __fastcall TListTextDlg::DelBtnClick(TObject *Sender) +{ + if( Grid->Row && (Grid->Row <= pList->m_Cnt) ){ + pList->DeleteItem(pList->pBase[Grid->Row-1]); + Grid->RowCount = pList->m_Cnt + 2; + Grid->Invalidate(); + UpdateUI(); + } +} +//--------------------------------------------------------------------------- + +void __fastcall TListTextDlg::GridClick(TObject *Sender) +{ + UpdateUI(); +} +//--------------------------------------------------------------------------- + +void __fastcall TListTextDlg::EditBtnClick(TObject *Sender) +{ + if( Grid->Row ){ + if( Grid->Row <= pList->m_Cnt ){ + if( pList->pBase[Grid->Row-1]->Edit() == TRUE ){ + Grid->Invalidate(); + } + } + else { + CDrawText *pItem = (CDrawText *)pList->MakeItem(CM_TEXT); + pItem->Start(Mmsstv->PBoxTemp->Canvas, 0, 0); + if( pItem->Finish(0, 0) ){ + pList->AddItem(pItem); + Grid->RowCount = pList->m_Cnt + 2; + Grid->Invalidate(); + UpdateUI(); + } + else { + delete pItem; + } + } + } +} +//--------------------------------------------------------------------------- + +void __fastcall TListTextDlg::UpBtnClick(TObject *Sender) +{ + if( Grid->Row > 1 ){ + Grid->Row--; + pList->UpItem(Grid->Row); + Grid->Invalidate(); + UpdateUI(); + } +} +//--------------------------------------------------------------------------- + +void __fastcall TListTextDlg::DwnBtnClick(TObject *Sender) +{ + if( Grid->Row <= (pList->m_Cnt - 1) ){ + pList->DownItem(Grid->Row-1); + Grid->Row++; + Grid->Invalidate(); + UpdateUI(); + } +} +//--------------------------------------------------------------------------- + + diff --git a/ListText.dfm b/ListText.dfm new file mode 100644 index 0000000..219de0e Binary files /dev/null and b/ListText.dfm differ diff --git a/ListText.h b/ListText.h new file mode 100644 index 0000000..4500433 --- /dev/null +++ b/ListText.h @@ -0,0 +1,71 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//---------------------------------------------------------------------------- +#ifndef OCBH +#define OCBH +//---------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//---------------------------------------------------------------------------- +#include "Draw.h" +//---------------------------------------------------------------------------- +class TListTextDlg : public TForm +{ +__published: + TButton *OKBtn; + TButton *CancelBtn; + TStringGrid *Grid; + TButton *DelBtn; + TButton *EditBtn; + TButton *UpBtn; + TButton *DwnBtn; + void __fastcall GridDrawCell(TObject *Sender, int Col, int Row, + TRect &Rect, TGridDrawState State); + void __fastcall DelBtnClick(TObject *Sender); + void __fastcall GridClick(TObject *Sender); + void __fastcall EditBtnClick(TObject *Sender); + void __fastcall UpBtnClick(TObject *Sender); + void __fastcall DwnBtnClick(TObject *Sender); +private: + CDrawGroup *pList; + int m_Jpn; + + void __fastcall UpdateUI(void); + + void __fastcall DrawGrade(CDrawText *pItem, TRect &Rect); + void __fastcall DrawShadow(CDrawText *pItem, TRect &Rect); + +public: + virtual __fastcall TListTextDlg(TComponent* AOwner); + + CDraw *__fastcall Execute(CDrawGroup *pg, int pos); +}; +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +#endif diff --git a/LogConv.cpp b/LogConv.cpp new file mode 100644 index 0000000..7ba3561 --- /dev/null +++ b/LogConv.cpp @@ -0,0 +1,2224 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------------- +#include +#pragma hdrstop + +#include +#include "LogConv.h" +#include "country.h" +#include "main.h" +CLogText LogText; +//*************************************************************************** +// CLogConv 基本 クラス +CLogConv::CLogConv() +{ + m_Mode = 0; + m_fp = NULL; +} + +CLogConv::~CLogConv() +{ +} +//*************************************************************************** +// CLogText クラス +CLogText::CLogText() +{ + m_Type = 0; + m_Double = 0; + m_Delm = 0; + m_err = 0; + m_UTC = (lcid != LANG_JAPANESE) ? 1 : 0; + int i; + for( i = 0; i < TEXTCONVMAX; i++ ){ + m_tConv[i].Key = ""; + m_tConv[i].w = 0; + } + m_tConv[0].Key = "%YYYY-MM-DD"; + m_tConv[1].Key = "%HHMM"; + m_tConv[2].Key = "%EHHMM"; + m_tConv[3].Key = "%CALL"; + m_tConv[4].Key = "%HIS"; + m_tConv[5].Key = "%MY"; + m_tConv[6].Key = "%FREQ"; + m_tConv[7].Key = "%MODE"; + m_tConv[8].Key = "%POWER"; + m_tConv[9].Key = "%NAME"; + m_tConv[10].Key = "%QTH"; + m_tConv[11].Key = "%REM"; + m_tConv[12].Key = "%QSL"; + m_tConv[13].Key = "%S"; + m_tConv[14].Key = "%R"; + m_tConv[15].Key = "%EOD"; + for( i = 0; i < TEXTCONVMAX; i++ ){ + m_rConv[i] = m_tConv[i]; + } +} +//--------------------------------------------------------------------------- +// テキストファイルのオープン +int CLogText::Open(LPCSTR pName) +{ + Close(); + m_Mode = 0; + m_err = 0; + + m_fp = fopen(pName, "rt"); + + if( m_fp != NULL ){ + setvbuf(m_fp, NULL, _IOFBF, 16384); + m_FileName = pName; + m_Mode = 0; + return TRUE; + } + else { + ErrorMB( MsgEng ? "Can't open '%s'":"'%s'がオープンできません.", pName); + return FALSE; + } +} +//--------------------------------------------------------------------------- +// テキストファイルの作成 +int CLogText::Create(LPCSTR pName) +{ + Close(); + m_Mode = 1; + + m_fp = fopen(pName, "wt"); + if( m_fp != NULL ){ + setvbuf(m_fp, NULL, _IOFBF, 16384); + m_FileName = pName; + m_Mode = 0; + return TRUE; + } + else { + ErrorMB( MsgEng ? "Can't write to '%s'":"'%s'が作成できません.", pName); + return FALSE; + } +} +//--------------------------------------------------------------------------- +// テキストファイルのオープン +int CLogText::Close(void) +{ + int r = 0; + if( m_fp != NULL ){ + r = fclose(m_fp); + m_fp = NULL; + if( r ){ + ErrorMB( MsgEng ? "Can't close '%s'":"'%s'が正しくクローズできませんでした.", m_FileName.c_str()); + } + else if( m_Mode ){ + InfoMB(MsgEng ? "Done (write to '%s')":"'%s'への書きこみを終了しました.", m_FileName.c_str()); + } + } + return r ? FALSE : TRUE; +} +//--------------------------------------------------------------------------- +// テキストファイルの読み出し +int CLogText::Read(SDMMLOG *sp) +{ + if( !IsOpen() ) return FALSE; + + if( !feof(m_fp) ){ + if( fgets(m_bf, sizeof(m_bf), m_fp) != NULL ){ + ClipLF(m_bf); + return Text2MMLOG(sp, m_bf, m_err); + } + else { + return FALSE; + } + } + else { + return FALSE; + } +} +//--------------------------------------------------------------------------- +// 出力変換 +int CLogText::Write(SDMMLOG *sp) +{ + if( !IsOpen() ) return FALSE; + + MMLOG2Text(m_bf, sp); + fputs(m_bf, m_fp); + fputs("\n", m_fp); + return ferror(m_fp) ? FALSE : TRUE; +} + +const LPCSTR ConvTbl[]={ + "%NULL", + "%YYYY-MM-DD", "%YY-MM-DD", "%YYYY/MM/DD", "%YY/MM/DD", + "%DD MON, YYYY","%YYMMDD", "%YYYYMMDD", + "%YY", "%YYYY", "%MM", "%MON", "%MON2", "%DD", "%HHMM", "%HH:MM","%HH:MM:SS", + "%EHHMM", "%EHH:MM", "%EHH:MM:SS", "%CALL", + "%M", "%MY", "%HIS", "%MYRST", "%HISRST", "%MYNR", "%HISNR", "%FREQ", "%KHZ", + "%MBAND", "%MODE", "%POWER", "%NAME", "%QTH", "%REM", "%QSL", + "%S", "%R", "%ENV", "%OPT1", "%OPT2", "%USR1", "%USR2", + "%EOD", + NULL, +}; + +const char *MONT1[]={"","JAN","FEB","MAR","APR","MAY","JUN","JUL","AUG","SEP","OCT","NOV","DEC"}; +const char *MONT2[]={"","Jan.","Feb.","Mar.","Apr.","May","June","July","Aug.","Sept.","Oct.","Nov.","Dec."}; + +//--------------------------------------------------------------------------- +void MMLOG2Text(LPSTR t, SDMMLOG *sp, AnsiString &Key) +{ + int tim, l; + + if( Key == "%YYYY-MM-DD" ){ + sprintf(t, "%04u-%02u-%02u", YEAR(sp->year), sp->date/100, sp->date%100); + } + else if( Key == "%YY-MM-DD" ){ + sprintf(t, "%2u-%02u-%02u", sp->year, sp->date/100, sp->date%100); + } + else if( Key == "%YYYY/MM/DD" ){ + sprintf(t, "%04u/%02u/%02u", YEAR(sp->year), sp->date/100, sp->date%100); + } + else if( Key == "%YY/MM/DD" ){ + sprintf(t, "%2u/%02u/%02u", sp->year, sp->date/100, sp->date%100); + } + else if( Key == "%DD MON, YYYY" ){ + sprintf(t, "%02u %s, %04u", sp->date%100, MONT1[sp->date/100], YEAR(sp->year)); + } + else if( Key == "%YYYYMMDD" ){ + sprintf(t, "%04u%02u%02u", YEAR(sp->year), sp->date/100, sp->date%100); + } + else if( Key == "%YYMMDD" ){ + sprintf(t, "%02u%02u%02u", sp->year, sp->date/100, sp->date%100); + } + else if( Key == "%YY" ){ + sprintf(t, "%02u", sp->year); + } + else if( Key == "%YYYY" ){ + sprintf(t, "%04u", YEAR(sp->year)); + } + else if( Key == "%MM" ){ + sprintf(t, "%02u", sp->date / 100); + } + else if( Key == "%MON" ){ + strcpy(t, MONT1[sp->date/100]); + } + else if( Key == "%MON2" ){ + strcpy(t, MONT2[sp->date/100]); + } + else if( Key == "%DD" ){ + sprintf(t, "%02u", sp->date % 100); + } + else if( Key == "%HHMM" ){ + if( sp->btime ){ + tim = sp->btime / 30; + sprintf(t, "%02u%02u", tim / 60, tim % 60); + } + else { + *t = 0; + } + } + else if( Key == "%HH:MM" ){ + if( sp->btime ){ + tim = sp->btime / 30; + sprintf(t, "%02u:%02u", tim / 60, tim % 60); + } + else { + *t = 0; + } + } + else if( Key == "%HH:MM:SS" ){ + if( sp->btime ){ + tim = sp->btime / 30; + sprintf(t, "%02u:%02u:%02u", tim / 60, tim % 60, (sp->btime * 2) % 60); + } + else { + *t = 0; + } + } + else if( Key == "%EHHMM" ){ + if( sp->etime ){ + tim = sp->etime / 30; + sprintf(t, "%02u%02u", tim / 60, tim % 60); + } + else { + *t = 0; + } + } + else if( Key == "%EHH:MM" ){ + if( sp->etime ){ + tim = sp->btime / 30; + sprintf(t, "%02u:%02u", tim / 60, tim % 60); + } + else { + *t = 0; + } + } + else if( Key == "%EHH:MM:SS" ){ + if( sp->etime ){ + tim = sp->btime / 30; + sprintf(t, "%02u:%02u:%02u", tim / 60, tim % 60, (sp->etime * 2) % 60); + } + else { + *t = 0; + } + } + else if( Key == "%CALL" ){ + strcpy(t, sp->call); + } + else if( Key == "%M" ){ + *t = sp->send; + *(t+1) = 0; + } + else if( Key == "%HIS" ){ + strcpy(t, sp->ur); + } + else if( Key == "%MY" ){ + strcpy(t, sp->my); + } + else if( Key == "%HISRST" ){ + StrCopy(t, sp->ur, GetLMode(sp->mode)); + } + else if( Key == "%MYRST" ){ + StrCopy(t, sp->my, GetLMode(sp->mode)); + } + else if( Key == "%HISNR" ){ + l = GetLMode(sp->mode); + if( (int)strlen(sp->ur) >= l ){ + strcpy(t, &sp->ur[l]); + } + else { + *t = 0; + } + } + else if( Key == "%MYNR" ){ + l = GetLMode(sp->mode); + if( (int)strlen(sp->my) >= l ){ + strcpy(t, &sp->my[l]); + } + else { + *t = 0; + } + } + else if( Key == "%FREQ" ){ + strcpy(t, Log.GetFreqString(sp->band, sp->fq)); + } + else if( Key == "%MBAND" ){ + strcpy(t, FreqTomBand(sp)); + } + else if( Key == "%KHZ" ){ + char bf[32]; + double dd; + strcpy(bf, Log.GetFreqString(sp->band, sp->fq)); + sscanf(bf, "%lf", &dd); + sprintf(t, "%.2lf", dd * 1000.0); + } + else if( Key == "%MODE" ){ + strcpy(t, Log.GetModeString(sp->mode)); + } + else if( Key == "%POWER" ){ + strcpy(t, sp->pow); + } + else if( Key == "%NAME" ){ + strcpy(t, sp->name); + } + else if( Key == "%QTH" ){ + strcpy(t, sp->qth); + } + else if( Key == "%REM" ){ + strcpy(t, sp->rem); + } + else if( Key == "%QSL" ){ + strcpy(t, sp->qsl); + } + else if( Key == "%S" ){ + *t = sp->send; + *(t+1) = 0; + } + else if( Key == "%R" ){ + *t = sp->recv; + *(t+1) = 0; + } + else if( Key == "%ENV" ){ + sprintf(t, "%u", sp->env); + } + else if( Key == "%OPT1" ){ + strcpy(t, sp->opt1); + } + else if( Key == "%OPT2" ){ + strcpy(t, sp->opt2); + } + else if( Key == "%USR1" ){ + strcpy(t, Log.GetOptStr(2, sp)); + } + else if( Key == "%USR2" ){ + strcpy(t, Log.GetOptStr(3, sp)); + } + else if( (Key == "%EOD")||(Key == "%NULL") ){ + *t = 0; + } + else { + strcpy(t, Key.c_str()); + } +} +//--------------------------------------------------------------------------- +// 1行の出力変換 +void CLogText::MMLOG2Text(LPSTR t, SDMMLOG *sp) +{ + char bf[512]; + char dlm = m_Delm ? TAB : ','; + + if( m_UTC ) JSTtoUTC(sp); + int i; + for( i = 0; i < TEXTCONVMAX; i++ ){ + if( (!m_tConv[i].Key.IsEmpty())&&(m_tConv[i].Key != "%EOD") ){ + ::MMLOG2Text(bf, sp, m_tConv[i].Key); + switch(m_Delm){ + case 0: // CSV + case 1: // TAB + if( i ) *t++ = dlm; + if( m_Double || (strchr(bf, dlm) != NULL) ) *t++ = 0x22; + if( m_tConv[i].w ){ + StrCopy(t, bf, m_tConv[i].w); + } + else { + strcpy(t, bf); + } + t += strlen(t); + if( m_Double || (strchr(bf, dlm) != NULL) ) *t++ = 0x22; + break; + default: // Format Text + if( m_tConv[i].w ){ + StrCopy(t, bf, m_tConv[i].w); + FillSpace(t, m_tConv[i].w); + } + else { + strcpy(t, bf); + } + t += strlen(t); + break; + } + } + else { + break; + } + } + *t = 0; +} +//--------------------------------------------------------------------------- +int GetMonth(LPCSTR p) +{ + for( int i = 1; i <=12; i++ ){ + if( !strcmpi(MONT1[i], p) ) return i; + if( !strcmpi(MONT2[i], p) ) return i; + } + return 0; +} +//--------------------------------------------------------------------------- +int Text2MMLOG(SDMMLOG *sp, LPCSTR s, AnsiString &Key) +{ + int y, m, d, h; + int tim; + + if( (Key == "%YYYY-MM-DD")||(Key == "%YY-MM-DD") ){ + if( sscanf(s, "%u-%u-%u", &y, &m, &d) != 3 ) return FALSE; + sp->year = BYTE(y % 100); + sp->date = WORD(m * 100 + d); + } + else if( (Key == "%YYYY/MM/DD")||(Key == "%YY/MM/DD") ){ + if( sscanf(s, "%u/%u/%u", &y, &m, &d) != 3 ) return FALSE; + sp->year = BYTE(y % 100); + sp->date = WORD(m * 100 + d); + } + else if( Key == "%DD MON, YYYY" ){ + d = atoin(s, 2); + s += 3; + char bf[4]; + StrCopy(bf, s, 3); + m = GetMonth(bf); + s = SkipSpace(s+1); + y = atoin(s, -1); + sp->year = BYTE(y % 100); + sp->date = WORD(m * 100 + d); + } + else if( Key == "%YYYYMMDD" ){ + y = atoin(s, 4); s += 4; + m = atoin(s, 2); s += 2; + d = atoin(s, 2); + sp->year = BYTE(y % 100); + sp->date = WORD(m * 100 + d); + } + else if( Key == "%YYMMDD" ){ + y = atoin(s, 2); s += 2; + m = atoin(s, 2); s += 2; + d = atoin(s, 2); + sp->year = BYTE(y % 100); + sp->date = WORD(m * 100 + d); + } + else if( (Key == "%YY")||(Key == "%YYYY") ){ + if( sscanf(s, "%u", &y) != 1 ) return FALSE; + sp->year = BYTE(y % 100); + } + else if( Key == "%MM" ){ + if( sscanf(s, "%u", &m) != 1 ) return FALSE; + sp->date = WORD((sp->date % 100) + m * 100); + } + else if( (Key == "%MON")||(Key == "%MON2") ){ + m = GetMonth(s); + sp->date = WORD((sp->date % 100) + m * 100); + } + else if( Key == "%DD" ){ + if( sscanf(s, "%u", &d) != 1 ) return FALSE; + sp->date = WORD(((sp->date / 100) * 100) + d); + } + else if( Key == "%HHMM" ){ + if( *s ){ + if( sscanf(s, "%u", &d) != 1 ) return FALSE; + h = d / 100; + m = d % 100; + tim = (h * 60 + m) * 30; + if( !tim ) tim++; + sp->btime = WORD(tim); + } + } + else if( (Key == "%HH:MM")||(Key == "%HH:MM:SS") ){ + if( *s ){ + if( sscanf(s, "%u:%u:%u", &h, &m, &d ) != 3 ){ + d = 0; + if( sscanf(s, "%u:%u", &h, &m) != 2 ) return FALSE; + } + tim = (h * 60 + m) * 30 + (d / 2); + if( !tim ) tim++; + sp->btime = WORD(tim); + } + } + else if( Key == "%EHHMM" ){ + if( *s ){ + if( sscanf(s, "%u", &d) != 1 ) return FALSE; + h = d / 100; + m = d % 100; + tim = (h * 60 + m) * 30; + if( !tim ) tim++; + sp->etime = WORD(tim); + } + } + else if( (Key == "%EHH:MM")||(Key == "%EHH:MM:SS") ){ + if( *s ){ + if( sscanf(s, "%u:%u:%u", &h, &m, &d ) != 3 ){ + d = 0; + if( sscanf(s, "%u:%u", &h, &m) != 2 ) return FALSE; + } + tim = (h * 60 + m) * 30 + (d / 2); + if( !tim ) tim++; + sp->etime = WORD(tim); + } + } + else if( Key == "%CALL" ){ + if( sp->call[0] ){ + char bf[256]; + sprintf(bf, "%s/%s", sp->call, s); + StrCopy(sp->call, bf, MLCALL); + } + else { + StrCopy(sp->call, s, MLCALL); + } + } + else if( Key == "%M" ){ + sp->send = *s; + } + else if( (Key == "%HIS")||(Key == "%HISRST") ){ + StrCopy(sp->ur, s, MLRST); + } + else if( (Key == "%MY")||(Key=="%MYRST") ){ + StrCopy(sp->my, s, MLRST); + } + else if( Key == "%FREQ" ){ + Log.SetFreq(sp, s); + } + else if( Key == "%MBAND" ){ + mBandToBand(sp, s); + } + else if( Key == "%KHZ" ){ + double dd; + sscanf(s, "%lf", &dd); + char bf[32]; + sprintf(bf, "%.03lf", dd / 1000.0); + Log.SetFreq(sp, bf); + } + else if( Key == "%MODE" ){ + Log.SetMode(sp, s); + } + else if( Key == "%POWER" ){ + StrCopy(sp->pow, s, MLPOW); + } + else if( Key == "%NAME" ){ + StrCopy(sp->name, s, MLNAME); + } + else if( Key == "%QTH" ){ + StrCopy(sp->qth, s, MLQTH); + } + else if( Key == "%REM" ){ + StrCopy(sp->rem, s, MLREM); + } + else if( Key == "%QSL" ){ + StrCopy(sp->qsl, s, MLQSL); + } + else if( Key == "%S" ){ + sp->send = *s; + } + else if( Key == "%R" ){ + sp->recv = *s; + } + else if( Key == "%ENV" ){ + if( sscanf(s, "%u", &d) != 1 ) return FALSE; + sp->env = WORD(d); + } + else if( Key == "%OPT1" ){ + StrCopy(sp->opt1, s, MLOPT); + } + else if( Key == "%OPT2" ){ + StrCopy(sp->opt2, s, MLOPT); + } + else if( Key == "%USR1" ){ + Log.SetOptStr(2, sp, s); + } + else if( Key == "%USR2" ){ + Log.SetOptStr(3, sp, s); + } + else if( (Key != "%EOD")&&(Key != "%NULL") ){ + if( Key != s ){ + return FALSE; + } + } + return TRUE; +} +//--------------------------------------------------------------------------- +// 1行の入力変換 +int CLogText::Text2MMLOG(SDMMLOG *sp, LPSTR p, int &err) +{ + char bf[512]; + char dlm = m_Delm ? TAB : ','; + LPSTR t; + + memset(sp, 0, sizeof(SDMMLOG)); + int i; + for( i = 0; i < TEXTCONVMAX; i++ ){ + if( (!m_rConv[i].Key.IsEmpty())&&(m_rConv[i].Key != "%EOD") ){ + if( m_Delm == 2 ){ + StrCopy(bf, p, m_rConv[i].w); + p += strlen(bf); + t = bf; + } + else { + p = StrDlm(t, p, dlm); + } + clipsp(t); + t = SkipSpace(t); + if( ::Text2MMLOG(sp, t, m_rConv[i].Key ) == FALSE ){ + if( !err ){ + ErrorMB(MsgEng ? "An error occurred with conversion type [%s]." : "変換式[%s]でエラーが発生しました.", m_rConv[i].Key.c_str() ); + } + err++; + } + } + else { + break; + } + } + if( !sp->etime ) sp->etime = sp->btime; + if( m_UTC ) UTCtoJST(sp); + return err ? FALSE : TRUE; +} +// +// +//*************************************************************************** +// CLog200 クラス +CLog200::CLog200() +{ + m_Type = 1; + m_err = 0; +} +//--------------------------------------------------------------------------- +// LOG200ファイルのオープン +int CLog200::Open(LPCSTR pName) +{ + Close(); + m_Index = 0; + m_err = 0; + + m_fp = fopen(pName, "rb"); + if( m_fp != NULL ){ + m_FileName = pName; + m_Mode = 0; + return TRUE; + } + else { + ErrorMB("'%s'がオープンできません.", pName); + return FALSE; + } +} +//--------------------------------------------------------------------------- +// LOG200ファイルの作成 +int CLog200::Create(LPCSTR pName) +{ + Close(); + m_Mode = 1; + m_err = 0; + + int add = 0; + if( (m_fp = fopen(pName, "rb"))!=NULL ){ + fclose(m_fp); + m_fp = NULL; + add = 1; + char BackName[256]; + strcpy(BackName, pName); + SetEXT(BackName, ".BAK"); + int r = YesNoCancelMB( "'%s'は既に存在しています.\r\nMMTTYはこのファイルにデータを追加します.\r\n\r\n" + "この操作を実行する前に元のログファイルのバックアップファイル\r\n\r\n" + "'%s' -> '%s'\r\n\r\nを作成しますか?\r\n\r\n" + "[重要]\r\n念のためにバックアップを作成する事をお勧めします.", pName, pName, BackName); + if( r == IDYES ){ + CWaitCursor w; + if( ::CopyFile(pName, BackName, FALSE) == FALSE ){ + ErrorMB("バックアップの作成に失敗しました.\r\nこの処理は中断されます.元のログファイルは変更されません."); + return FALSE; + } + } + else if( r == IDCANCEL ){ + return FALSE; + } + } + m_fp = fopen(pName, add ? "ab":"wb"); + if( m_fp != NULL ){ + m_FileName = pName; + m_Mode = 0; + return TRUE; + } + else { + ErrorMB( "'%s'が作成できません.", pName); + return FALSE; + } +} +//--------------------------------------------------------------------------- +// LOG200ファイルのクローズ +int CLog200::Close(void) +{ + int r = 0; + if( m_fp != NULL ){ + r = fclose(m_fp); + m_fp = NULL; + if( r ){ + ErrorMB("'%s'が正しくクローズできませんでした.", m_FileName.c_str()); + } + else if( m_Mode ){ + InfoMB("'%s'への追加を終了しました.", m_FileName.c_str()); + } + } + return r ? FALSE : TRUE; +} +//--------------------------------------------------------------------------- +// LOG200 -> MMLOG フォーマットの変換 +void LOG200toMMLOG(SDMMLOG *sp, LPSTR s) +{ + LPSTR t; + int y, m, d, h, tim; + char bf[256]; + + memset(sp, 0, sizeof(SDMMLOG)); + s = StrDlm(t, s, 0x1e); /* DATE */ + y = atoin(t, 2); t += 2; + m = atoin(t, 2); t += 2; + d = atoin(t, 2); + sp->year = BYTE(y % 100); + sp->date = WORD(m * 100 + d); + + s = StrDlm(t, s, 0x1e); /* BGN */ + d = atoin(t, 4); + h = d / 100; + m = d % 100; + tim = (h * 60 + m) * 30; + if( !tim ) tim++; + sp->btime = WORD(tim); + + s = StrDlm(t, s, 0x1e); /* END */ + d = atoin(t, 4); + h = d / 100; + m = d % 100; + tim = (h * 60 + m) * 30; + if( !tim ) tim++; + sp->etime = WORD(tim); + + s = StrDlm(t, s, 0x1e); /* CALL */ + clipsp(t); + StrCopy(sp->call, t, MLCALL); + + s = StrDlm(t, s, 0x1e); /* FREQ */ + if( LastC(t) == '.' ){ + *lastp(t) = 0; + } + Log.SetFreq(sp, t); + + s = StrDlm(t, s, 0x1e); /* MODE */ + Log.SetMode(sp, t); + + s = StrDlm(t, s, 0x1e); /* RST */ + clipsp(t); + StrCopy(sp->ur, t, MLRST); + + s = StrDlm(t, s, 0x1e); /* MyRST*/ + clipsp(t); + StrCopy(sp->my, t, MLRST); + + s = StrDlm(t, s, 0x1e); /* QTH */ + clipsp(t); + StrCopy(sp->qth, t, MLQTH); + + s = StrDlm(t, s, 0x1e); /* NAME */ + clipsp(t); + StrCopy(sp->name, t, MLNAME); + + s = StrDlm(t, s, 0x1e); /* RIG */ + clipsp(t); + LPSTR pRIG = t; + + s = StrDlm(t, s, 0x1e); /* CONTEST */ + clipsp(t); + LPSTR pContest = t; + + s = StrDlm(t, s, 0x1e); /* Rem */ + clipsp(t); + + if( (strlen(sp->call) == 15) && (RemoveL2(bf, t, "CALL", sizeof(bf)-1) == TRUE) ){ + StrCopy(sp->call, bf, MLCALL); + } + if( RemoveL2(bf, t, "POW", sizeof(bf)-1) == TRUE ){ + StrCopy(sp->pow, bf, MLPOW); + } + if( RemoveL2(bf, t, "ENV", sizeof(bf)-1) == TRUE ){ + sp->env = WORD(atoin(bf, -1)); + } + if( RemoveL2(bf, t, "M", sizeof(bf)-1) == TRUE ){ + sp->cq = bf[0]; + } + if( RemoveL2(bf, t, "OPT1", sizeof(bf)-1) == TRUE ){ + StrCopy(sp->opt1, bf, MLOPT); + } + if( RemoveL2(bf, t, "OPT2", sizeof(bf)-1) == TRUE ){ + StrCopy(sp->opt2, bf, MLOPT); + } + if( RemoveL2(bf, t, "USR1", sizeof(bf)-1) == TRUE ){ + Log.SetOptStr(2, sp, bf); + } + if( RemoveL2(bf, t, "USR2", sizeof(bf)-1) == TRUE ){ + Log.SetOptStr(3, sp, bf); + } + if( RemoveL2(bf, t, "MQSL", sizeof(bf)-1) == TRUE ){ + StrCopy(sp->qsl, bf, MLQSL); + } + clipsp(t); + t = SkipSpace(t); + StrCopy(sp->rem, t, MLREM); + + s = StrDlm(t, s, 0x1e); /* MyQTH*/ + if( *t ) AddL2(sp->qsl, "MyQTH", t, '[', ']', MLQSL); + + s = StrDlm(t, s, 0x1e); /* MyRig*/ + if( *t ) AddL2(sp->qsl, "MyRIG", t, '[', ']', MLQSL); + + s = StrDlm(t, s, 0x1e); /* Send */ + sp->send = *t; + StrDlm(t, s, 0x1e); /* Recv */ + sp->recv = *t; + + if( *pRIG ) AddL2(sp->qsl, "RIG", pRIG, '[', ']', MLQSL); + if( *pContest ) AddL2(sp->qsl, "TEST", pContest, '[', ']', MLQSL); +} +//--------------------------------------------------------------------------- +// LOG200ファイルの読み出し +int CLog200::Read(SDMMLOG *sp) +{ + if( !IsOpen() ) return FALSE; + + if( fread(m_bf, 1, 200, m_fp) == 200 ){ + LOG200toMMLOG(sp, m_bf); + m_Index++; + return TRUE; + } + else { + return FALSE; + } +} + +//--------------------------------------------------------------------------- +// MMLOG -> LOG200フォーマット変換 +void MMLOGtoLOG200(LPSTR t, SDMMLOG *sp, int &err) +{ + LPSTR s = t; + int h, m; + char bf[256]; + + memset(t, ' ', 200); + // YYMMDD + sprintf(t, "%02u%02u%02u\x1e", sp->year, sp->date / 100, sp->date % 100); + t += strlen(t); + // BGN(HHMM) + h = sp->btime / 1800; + m = (sp->btime % 1800) / 30; + sprintf(t, "%02u%02u\x1e", h, m); + t += strlen(t); + // END + h = sp->etime / 1800; + m = (sp->etime % 1800) / 30; + sprintf(t, "%02u%02u\x1e", h, m); + t += strlen(t); + // CALL + StrCopy(t, sp->call, 15); // 15文字に制限されている + t += strlen(t); + *t++ = 0x1e; + // FREQ + sprintf(bf, "%s", Log.GetFreqString(sp->band, sp->fq)); + if( bf[0] ){ + double dd; + if( sscanf(bf, "%lf", &dd) == 1 ){ + sprintf(bf, "%.3lf", dd); + } + } + strcpy(t, bf); + t += strlen(t); + *t++ = 0x1e; + // MODE + sprintf(t, "%s\x1e", Log.GetModeString(sp->mode)); + t += strlen(t); + // HisRST + sprintf(t, "%s\x1e", sp->ur); + t += strlen(t); + // MyRST + sprintf(t, "%s\x1e", sp->my); + t += strlen(t); + // QTH + sprintf(t, "%s\x1e", sp->qth); + t += strlen(t); + // NAME + sprintf(t, "%s\x1e", sp->name); + t += strlen(t); + // RIG + if( RemoveL2(bf, sp->qsl, "Rig", sizeof(bf)-1) == TRUE ){ + strcpy(t, bf); + } + *t++ = 0x1e; + // CONTEST + if( RemoveL2(bf, sp->qsl, "TEST", sizeof(bf)-1) == TRUE ){ + strcpy(t, bf); + } + *t++ = 0x1e; + char MyRig[200]; + char MyQTH[200]; + MyRig[0] = MyQTH[0] = 0; + if( RemoveL2(bf, sp->qsl, "MyRig", sizeof(bf)-1) == TRUE ){ + strcpy(MyRig, bf); + } + if( RemoveL2(bf, sp->qsl, "MyQTH", sizeof(bf)-1) == TRUE ){ + strcpy(MyQTH, bf); + } + clipsp(sp->qsl); + LPSTR p = SkipSpace(sp->qsl); + + // REM + strcpy(bf, sp->rem); + char bbf[128]; + if( strlen(sp->call) > 11 ){ + AddL2(bf, "CALL", sp->call, '[', ']', MLQSL); + } + if( sp->cq ){ + bbf[0] = sp->cq; bbf[1] = 0; + AddL2(bf, "M", bbf, '[', ']', MLQSL); + } + if( sp->pow[0] ) AddL2(bf, "POW", sp->pow, '[', ']', MLQSL); + if( sp->env ){ + sprintf(bbf, "%u", sp->env); + AddL2(bf, "ENV", bbf, '[', ']', MLQSL); + } + if( sp->opt1[0] ) AddL2(bf, "OPT1", sp->opt1, '[', ']', MLQSL); + if( sp->opt2[0] ) AddL2(bf, "OPT2", sp->opt2, '[', ']', MLQSL); + LPCSTR pp = Log.GetOptStr(2, sp); + if( *pp ) AddL2(bf, "USR1", pp, '[', ']', MLQSL); + pp = Log.GetOptStr(3, sp); + if( *pp ) AddL2(bf, "USR2", pp, '[', ']', MLQSL); + + if( *p ) AddL2(bf, "MQSL", p, '[', ']', MLQSL); + int len = (t - s) + strlen(bf) + 1 + strlen(MyQTH) + 1 + strlen(MyRig) + 1 + 2; + if( len >= 199 ){ + if( !err ){ + err++; + WarningMB("変換した結果がLOG200レコード長を越えました.\r\n\r\nリマークフィールドの長さを調整します."); + } + len -= 199; + bf[strlen(bf)-len] = 0; + } + + sprintf(t, "%s\x1e", bf); + t += strlen(t); + + // MyQTH + sprintf(t, "%s\x1e", MyQTH); + t += strlen(t); + // MyRIG + sprintf(t, "%s\x1e", MyRig); + t += strlen(t); + // S + if( sp->send ) *t++ = sp->send; + *t++ = 0x1e; + // R + if( sp->recv ) *t++ = sp->recv; + *t = 0x1e; + + s[198] = '\r'; s[199] = '\n'; +} +//--------------------------------------------------------------------------- +// LOG200ファイルの書きこみ +int CLog200::Write(SDMMLOG *sp) +{ + if( !IsOpen() ) return FALSE; + + MMLOGtoLOG200(m_bf, sp, m_err); + if( fwrite(m_bf, 1, 200, m_fp) != 200 ){ + ErrorMB("'%s'に書き込み中にエラーが発生しました.", m_FileName.c_str()); + return FALSE; + } + else { + m_Index++; + return TRUE; + } +} +// +// +//*************************************************************************** +// CHamLog クラス +//--------------------------------------------------------------------------- +CHamLog::CHamLog() +{ + m_Type = 2; + m_err = 0; + + m_DBRName = ""; // DBRファイルの名前 + m_dbrfp = NULL; // DBRファイルのファイルポインタ +} +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- +// HamLogファイルのオープン +int CHamLog::Open(LPCSTR pName) +{ + Close(); + m_Index = 0; + m_err = 0; + m_Mode = 0; + + m_fp = fopen(pName, "rb"); // DBSのオープン + + if( m_fp == NULL ){ + ErrorMB( "'%s'がオープンできません.", pName); + return FALSE; + } + m_FileName = pName; + if( (fread(&m_hd, 1, sizeof(m_hd), m_fp)!=sizeof(m_hd)) || + (m_hd.Memo != 0x1a) || + (m_hd.HeadLen != 449) || + (m_hd.DataLen != sizeof(m_RecBuf)) + ){ + fclose(m_fp); + m_fp = NULL; + ErrorMB("予期しないファイル形式です."); + return FALSE; + } + char dbrName[256]; + strcpy(dbrName, pName); + SetEXT(dbrName, ".DBR"); + m_DBRName = dbrName; + m_dbrfp = fopen(dbrName, "rb"); + if( m_dbrfp == NULL ){ + WarningMB( "'%s'がオープンできません.", dbrName); + } + else if( fread(&m_dbrhd, 1, sizeof(m_dbrhd), m_dbrfp)!=sizeof(m_dbrhd) ){ + ErrorMB( "'%s'が正常に読みこめません. 処理を中断します.", dbrName); + fclose(m_fp); + m_fp = NULL; + fclose(m_dbrfp); + m_dbrfp = NULL; + return FALSE; + } + + if( Seek(0) == FALSE ){ + Close(); + ErrorMB("最初のレコードが見つかりません."); + return FALSE; + } + return TRUE; +} + +int CHamLog::Close(void) +{ + int r = 0; + if( m_fp != NULL ){ + if( m_Mode ){ // 書きこみ + fseek(m_fp, 0, SEEK_SET); + if( fwrite(&m_hd, 1, sizeof(m_hd), m_fp) != sizeof(m_hd) ) r = 1; + } + if( fclose(m_fp) ) r = 1;; + m_fp = NULL; + } + if( m_dbrfp != NULL ){ + if( m_Mode ){ + fseek(m_dbrfp, 0, SEEK_SET); + if( fwrite(&m_dbrhd, 1, sizeof(m_dbrhd), m_dbrfp) != sizeof(m_dbrhd) ) r = 1; + } + if( fclose(m_dbrfp) ) r = 1; + m_dbrfp = NULL; + } + if( r ){ + ErrorMB("ファイルのクローズに失敗しました."); + } + else if( m_Mode ){ + InfoMB("'%s'への追加を終了しました.", m_FileName.c_str()); + } + return r ? FALSE : TRUE; +} + +//--------------------------------------------------------------------------- +// HamLogファイルの作成 +int CHamLog::Create(LPCSTR pName) +{ + Close(); + m_Mode = 1; + m_err = 0; + + char dbrName[256]; + strcpy(dbrName, pName); + SetEXT(dbrName, ".DBR"); + + int add = 0; + if( (m_fp = fopen(pName, "rt"))!=NULL ){ + fclose(m_fp); + add = 1; + char BackNameDBS[256]; + strcpy(BackNameDBS, pName); + SetEXT(BackNameDBS, ".$BS"); + char BackNameDBR[256]; + strcpy(BackNameDBR, dbrName); + SetEXT(BackNameDBR, ".$BR"); + int r = YesNoCancelMB( "'%s'は既に存在しています. データはこのファイルに追加されます.\r\n\r\nこの操作を実行する前に元のログファイルのバックアップファイル\r\n\r\n'%s'->'%s'\r\n'%s'->'%s'\r\n\r\nを作成しますか?\r\n\r\n" + "[重要]\r\n念のためにバックアップを作成する事をお勧めします.", pName, pName, BackNameDBS, dbrName, BackNameDBR); + if( r == IDYES ){ + CWaitCursor w; + if( ::CopyFile(pName, BackNameDBS, FALSE) == FALSE ){ + ErrorMB("バックアップの作成に失敗しました.\r\nこの処理は中断されます.元のログファイルは変更されません."); + return FALSE; + } + if( ::CopyFile(dbrName, BackNameDBR, FALSE) == FALSE ){ + ErrorMB("バックアップの作成に失敗しました.\r\nこの処理は中断されます.元のログファイルは変更されません."); + return FALSE; + } + } + else if( r == IDCANCEL ){ + return FALSE; + } + } + m_fp = fopen(pName, add ? "r+b":"wb"); + if( m_fp == NULL ){ + ErrorMB( "'%s'がオープンできません.", pName); + return FALSE; + } + m_dbrfp = fopen(dbrName, add ? "r+b":"wb"); + if( m_dbrfp == NULL ){ + ErrorMB( "'%s'がオープンできません.", dbrName); + return FALSE; + } + + if( add ){ // 追加の時 + if( (fread(&m_hd, 1, sizeof(m_hd), m_fp)!=sizeof(m_hd)) || + (m_hd.Memo != 0x1a) || + (m_hd.HeadLen != 449) || + (m_hd.DataLen != sizeof(m_RecBuf)) + ){ + fclose(m_fp); + m_fp = NULL; + fclose(m_dbrfp); + m_dbrfp = NULL; + ErrorMB("'%s'は予期しないファイル形式です.", pName); + return FALSE; + } + if( (fread(&m_dbrhd, 1, sizeof(m_dbrhd), m_dbrfp)!=sizeof(m_dbrhd)) || + (m_dbrhd.Memo != 0x1a) || + (m_dbrhd.term != 0x1a) + ){ + fclose(m_fp); + m_fp = NULL; + fclose(m_dbrfp); + m_dbrfp = NULL; + ErrorMB("'%s'は予期しないファイル形式です.", dbrName); + return FALSE; + } + fseek(m_dbrfp, 0, SEEK_END); // DBRの最後に移動 + } + else { // 新規の時 + MakeHD(); + } + m_FileName = pName; + m_Mode = 1; + m_DBRName = dbrName; + m_Index = m_hd.Max; + return TRUE; +} + +//---------------------------------------------------------------------- +int CHamLog::Seek(DWORD Index) +{ + long Pos = 449 + (Index * sizeof(m_RecBuf)); + if( fseek(m_fp, Pos, SEEK_SET) ) return FALSE; + m_Index = Index; + return TRUE; +} + +//---------------------------------------------------------------------- +//HAMLOGのヘッダを作成 +BOOL CHamLog::MakeHD(void) +{ + memset(&m_hd, 0, sizeof(m_hd)); + memset(&m_dbrhd, 0, sizeof(m_dbrhd)); + m_hd.Memo = 0x1a; + SYSTEMTIME st; + ::GetLocal(&st); + m_hd.YY = BYTE(st.wYear % 100); + m_hd.MM = BYTE(st.wMonth); + m_hd.DD = BYTE(st.wDay); + m_hd.Max = 0; + memcpy(&m_dbrhd, &m_hd, sizeof(m_hd)); + m_hd.HeadLen = 449; + m_hd.DataLen = sizeof(m_RecBuf); + if( fwrite(&m_hd, 1, sizeof(m_hd), m_fp) != sizeof(m_hd) ) return FALSE; + + LPCSTR _Name[]={"CALLS","IGN","POTBL","CODE","GL","FREQ","MODE","NAME","QSL","DATE","TIME","RST","OFS"}; + BYTE _Len[]={6, 1, 3, 6, 6, 4, 3, 12, 3, 3, 2, 4, 4, 0}; + DBSLOT slot; + for( int i = 0; _Len[i]; i++ ){ + memset(&slot, 0, sizeof(slot)); + strcpy(slot.Name, _Name[i]); + slot.Type = 'C'; + slot.Len = _Len[i]; + if( fwrite(&slot, 1, sizeof(slot), m_fp)!=sizeof(slot) ) return FALSE; + } + slot.Name[0] = 0x0d; + if( fwrite(&slot, 1, 1, m_fp)!=1 ) return FALSE; + + m_dbrhd.m1 = 1; + m_dbrhd.term = 0x1a; + if( fwrite(&m_dbrhd, 1, sizeof(m_dbrhd), m_dbrfp)!=sizeof(m_dbrhd) ) return FALSE; + return TRUE; +} + +//--------------------------------------------------------------------------- +// HamLogファイルの読み出し +int CHamLog::Read(SDMMLOG *sp) +{ + if( !IsOpen() ) return FALSE; + + Seek(m_Index); + if( fread(&m_RecBuf, 1, sizeof(m_RecBuf), m_fp) == sizeof(m_RecBuf) ){ + HAMLOGtoMMLOG(sp, &m_RecBuf, m_dbrfp); + m_Index++; + return TRUE; + } + else { + return FALSE; + } +} +//--------------------------------------------------------------------------- +// HamLogファイルの書きこみ +int CHamLog::Write(SDMMLOG *sp) +{ + if( !IsOpen() ) return FALSE; + + if( MMLOGtoHAMLOG(&m_RecBuf, sp, m_dbrfp) == FALSE ){ + ErrorMB("'%s'に書き込み中にエラーが発生しました.", m_DBRName.c_str()); + return FALSE; + } + Seek(m_hd.Max); + if( fwrite(&m_RecBuf, 1, sizeof(m_RecBuf), m_fp) != sizeof(m_RecBuf) ){ + ErrorMB("'%s'に書き込み中にエラーが発生しました.", m_FileName.c_str()); + return FALSE; + } + else { + m_hd.Max++; + m_dbrhd.Max++; + return TRUE; + } +} +//---------------------------------------------------------------------- +//HAMLOGの周波数記録方式を通常の文字列に変換 +void DecBand(LPSTR t, BYTE *pBand) +{ + if( pBand[3] & 0x80 ){ // 5〜7文字の文字列 + int DotPos = pBand[3] & 0x7f; + int Len = (DotPos >> 3) & 0x07; + DotPos &= 0x07; + LPSTR p = t; + wsprintf(p, "%-7lu", (*((LONG *)pBand) & 0x00ffffffL)); + if( Len < 4 ){ // Ver3.19までの記録方式 + for(int i = 6; i > 3; i--){ + if(p[i]>'0'){ + break; + } + else if(p[i] == '0'){ + p[i] = ' '; + } + } + } + else { + if( Len < 6 ) p[6] = ' '; + if( Len == 4 ) p[5] = ' '; + } + p[DotPos] = '.'; + p[8] = 0; + } + else { // そのまま + StrCopy(t, (LPCSTR)pBand, 4); + } + clipsp(t); + if( LastC(t) == '.' ){ + *lastp(t) = 0; + } +} + +void SetMMLOGKey(SDMMLOG *sp, LPSTR bf) +{ + char rbf[512]; + + if( RemoveL2(rbf, bf, "ToRadio", sizeof(rbf)-1) == TRUE ){ + StrCopy(sp->call, rbf, MLCALL); + } + else if( RemoveL2(rbf, bf, "CALL", sizeof(rbf)-1) == TRUE ){ + StrCopy(sp->call, rbf, MLCALL); + } + + if( RemoveL2(rbf, bf, "ENV", sizeof(rbf)-1) == TRUE ){ + sp->env = WORD(atoin(rbf, -1)); + } + if( RemoveL2(rbf, bf, "END", sizeof(rbf)-1) == TRUE ){ + int tim = atoin(rbf, -1); + int hh = tim / 100; + int mm = tim % 100; + sp->etime = WORD((hh * 60 + mm) * 30); + if( !sp->etime ) sp->etime++; + } + if( RemoveL2(rbf, bf, "POW", sizeof(rbf)-1) == TRUE ){ + StrCopy(sp->pow, rbf, MLPOW); + } + if( RemoveL2(rbf, bf, "M", sizeof(rbf)-1) == TRUE ){ + sp->cq = rbf[0]; + } + if( RemoveL2(rbf, bf, "SN", sizeof(rbf)-1) == TRUE ){ + int l = GetLMode(sp->mode); + if( l ) sp->ur[l] = 0; + strcat(sp->ur, rbf); + } + if( RemoveL2(rbf, bf, "RN", sizeof(rbf)-1) == TRUE ){ + int l = GetLMode(sp->mode); + if( l ) sp->my[l] = 0; + strcat(sp->my, rbf); + } +} +//--------------------------------------------------------------------------- +// HamLog -> MMLOG フォーマットの変換 +void HAMLOGtoMMLOG(SDMMLOG *sp, SDHAMLOG *hp, FILE *dbrfp) +{ + int CallOrder = 0; + char bf[512]; + + memset(sp, 0, sizeof(SDMMLOG)); + DecBand(bf, (BYTE *)hp->freq); + Log.SetFreq(sp, bf); + + StrCopy(bf, hp->mode, 3); + clipsp(bf); + if( !strcmp(bf, Log.m_LogSet.m_THRTTY.c_str()) || !strcmp(bf, "RTY") || !strcmp(bf, "TTY") || !strcmp(bf, "RTT") ){ + strcpy(bf, "RTTY"); + } + else if( !strcmp(bf, Log.m_LogSet.m_THSSTV.c_str()) || !strcmp(bf, "STV")|| !strcmp(bf, "SST") ){ + strcpy(bf, "SSTV"); + } + else if( !strcmp(bf, "FTV") ){ + strcpy(bf, "FSTV"); + } + Log.SetMode(sp, bf); + + StrCopy(sp->name, hp->name, 12); + clipsp(sp->name); + + sprintf(sp->ur, "%02u", BYTE(hp->hiss[0])); + if( hp->hiss[1] != ' ' ) sp->ur[2] = hp->hiss[1]; + + sprintf(sp->my, "%02u", BYTE(hp->myrs[0])); + if( hp->myrs[1] != ' ' ) sp->my[2] = hp->myrs[1]; + + int YY, MM, DD, HH, mm; + YY = hp->date[0] & 0x007f; + YY %= 100; + MM = hp->date[1]; + DD = hp->date[2]; + HH = hp->time[0]; + mm = hp->time[1] & 0x7f; + if( hp->time[1] & 0x80 ){ + UTCtoJST(YY, MM, DD, HH); + } + sp->year = BYTE(YY); + sp->date = WORD(MM * 100 + DD); + sp->btime = WORD(((HH * 60 + mm) * 30)); + if(!sp->btime) sp->btime++; + + if( hp->ofs && (dbrfp != NULL) ){ + FHDDBR fhdbr; + if( fseek(dbrfp, hp->ofs, SEEK_SET) ) goto _ex; + if( fread(&fhdbr, 1, sizeof(fhdbr), dbrfp) != sizeof(fhdbr) ){ + goto _ex; + } + if( fhdbr.LenQTH ){ + if( fread(bf, 1, fhdbr.LenQTH, dbrfp)!=size_t(fhdbr.LenQTH) ){ + goto _ex; + } + bf[fhdbr.LenQTH] = 0; + clipsp(bf); + StrCopy(sp->qth, bf, MLQTH); + } + if( fhdbr.LenREM1 ){ + if( fread(bf, 1, fhdbr.LenREM1, dbrfp)!=size_t(fhdbr.LenREM1) ){ + goto _ex; + } + bf[fhdbr.LenREM1] = 0; + SetMMLOGKey(sp, bf); + clipsp(bf); + if( strstr(bf, "$DX" ) != NULL ) CallOrder = 1; + StrCopy(sp->rem, SkipSpace(bf), MLREM); + } + if( fhdbr.LenREM2 ){ + if( fread(bf, 1, fhdbr.LenREM2, dbrfp)!=size_t(fhdbr.LenREM2) ){ + goto _ex; + } + bf[fhdbr.LenREM2] = 0; + SetMMLOGKey(sp, bf); + clipsp(bf); + if( strstr(bf, "$DX" ) != NULL ) CallOrder = 1; + StrCopy(sp->qsl, SkipSpace(bf), MLQSL); + } + } +_ex:; + sprintf(bf, "QSL[%.3s]", hp->qsl); + Log.SetOptStr(2, sp, bf); + if( hp->qsl[0] == 'N' ){ + sp->send = 'N'; + } + else if( hp->send[0] == ' ' ){ // 未発送 + if( (hp->qsl[0] == 'J')||(hp->qsl[0] == ' ') ){ + sp->send = 0; + } + else { + sp->send = BYTE(tolower(hp->qsl[0])); + } + } + else { // 発送済み + sp->send = BYTE(toupper(hp->send[0])); + } + sp->recv = hp->rcv[0]; + if( sp->recv == ' ' ) sp->recv = 0; + + StrCopy(sp->opt1, hp->code, 6); + StrCopy(sp->opt2, hp->glid, 6); + + if( !sp->call[0] ){ + if( CallOrder && (hp->potbl[0] != ' ') ){ /* KH6/JE3HHTの形式 */ + StrCopy(bf, hp->potbl, 3); + clipsp(bf); + strcat(sp->call, bf); + if( sp->call[0] ) strcat(sp->call, "/"); + StrCopy(bf, hp->calls, 7); + clipsp(bf); + strcat(sp->call, bf); + } + else { /* JE3HHT/KH6の形式 */ + StrCopy(bf, hp->calls, 7); + clipsp(bf); + strcat(sp->call, bf); + if( hp->potbl[0] != ' ' ){ + if( sp->call[0] ) strcat(sp->call, "/"); + StrCopy(bf, hp->potbl, 3); + clipsp(bf); + strcat(sp->call, bf); + } + } + } + if( !sp->etime ) sp->etime = sp->btime; +} +//---------------------------------------------------------------------- +//文字列のコピー(ヌルはセットされない) +void SpaceCopy(LPSTR t, LPCSTR s, int n) +{ + for( ; n && *s; s++, t++, n-- ){ + *t = *s; + } +} +//---------------------------------------------------------------------- +//RST文字列をHAMLOG形式に変換して格納 +void SetRST(char *pRST, LPCSTR p, BYTE mode) +{ + char rs[3]; + int rst; + + StrCopy(rs, p, 2); + if( sscanf(rs, "%d", &rst) == 1 ){ + *pRST = BYTE(rst); + } + else { + *pRST = 59; + } + if( strlen(p) < 3 ) return; + if( GetLMode(mode) == 2 ) return; + pRST[1] = *(p+2); +} +//---------------------------------------------------------------------- +//周波数の文字列をHAMLOGの周波数記録方式に変換 +void EncBand(BYTE *pBand, LPCSTR pStr) +{ + char bf[32]; + StrCopy(bf, pStr, 7); + + int Len = strlen(bf); + if( Len <= 4 ){ + memset(pBand, ' ', 4); + SpaceCopy(LPSTR(pBand), bf, 4); + } + else { + LPSTR p = strchr(bf, '.'); + int DotPos; + if( p != NULL ){ + DotPos = p - bf; + *p = '0'; + } + else { + DotPos = Len; + } + long Freq; + sscanf(bf, "%lu", &Freq); + *(ULONG *)pBand = Freq; + pBand[3] = BYTE(0x0080 | (Len << 3) | DotPos); + } +} + +void AddMMLOGKey(AnsiString &REM1, AnsiString &REM2, LPCSTR s, LPCSTR pKey) +{ + if( !*s ) return; + + int len1 = strlen(REM1.c_str()); + int len2 = strlen(REM2.c_str()); + int len = strlen(s); + if( pKey == NULL ){ + len++; + } + else { + len += strlen(pKey) + 3; + } + AnsiString *ap; + if( (len2 + len) < 54 ){ + ap = &REM2; + } + else if( (len1 + len) < 54 ){ + ap = &REM1; + } + else { + return; + } + if( !ap->IsEmpty() ){ + *ap += " "; + } + if( pKey != NULL ){ + *ap += pKey; + *ap += '['; + } + *ap += s; + if( pKey != NULL ){ + *ap += ']'; + } +} +//--------------------------------------------------------------------------- +// MMLOG -> HamLog フォーマットの変換 +int MMLOGtoHAMLOG(SDHAMLOG *hp, SDMMLOG *sp, FILE *dbrfp) +{ + char bf[512]; + + int CallOrder = FALSE; + memset(hp, ' ', sizeof(SDHAMLOG)); + int YY = sp->year; + int MM = sp->date / 100; + int DD = sp->date % 100; + int tim = sp->btime / 30; + int HH = tim / 60; + int mm = tim % 60; + switch(Log.m_LogSet.m_THTZ){ + case 0: + if( !IsJA(sp->call) ){ + JSTtoUTC(YY, MM, DD, HH); + mm |= 0x80; + } + break; + case 1: + JSTtoUTC(YY, MM, DD, HH); + mm |= 0x80; + break; + default: + break; + } + hp->date[0] = BYTE(YY < 50 ? YY + 128 : YY); + hp->date[1] = BYTE(MM); + hp->date[2] = BYTE(DD); + hp->time[0] = BYTE(HH); + hp->time[1] = BYTE(mm); + + SpaceCopy(hp->name, sp->name, 12); + SpaceCopy(hp->code, sp->opt1, 6); + SpaceCopy(hp->glid, sp->opt2, 6); + AnsiString QTH = sp->qth; + AnsiString REM1 = sp->rem; + AnsiString REM2 = sp->qsl; + + strcpy(bf, sp->call); + LPSTR pp, p2, t; + t = bf; + if( (pp = strchr(bf, '/')) != NULL ){ // KH6/JE3HHT or JE3HHT/KH6 の形式 + *pp = 0; + pp++; + int LenC = strlen(t); + int LenP = strlen(pp); + if( ((p2 = strchr(pp, '/')) != NULL)|| + (LenC > 7) || + (LenP > 7) || + ((LenC > LenP) && (LenP>3)) || + ((LenC < LenP) && (LenC>3)) + ){ + // HAMLOGでは表現できない表記の場合 + AddMMLOGKey(REM1, REM2, sp->call, "ToRadio"); + if( p2 != NULL ){ + *p2 = 0; + LenP = strlen(pp); + } + } + if( LenC < LenP ){ + p2 = t; + t = pp; + pp = p2; + CallOrder = TRUE; + } + SpaceCopy(hp->potbl, pp, 3); + } + else if( strlen(t) > 7 ){ + AddMMLOGKey(REM1, REM2, sp->call, "ToRadio"); + } + SpaceCopy(hp->calls, t, 7); + strcpy(bf, Log.GetModeString(sp->mode)); + if( !strcmp(bf, "RTTY") ){ + StrCopy(bf, Log.m_LogSet.m_THRTTY.c_str(), 3); + } + else if( !strcmp(bf, "SSTV") ){ + StrCopy(bf, Log.m_LogSet.m_THSSTV.c_str(), 3); + } + else if( !strcmp(bf, "FSTV") ){ + strcpy(bf, "FTV"); + } + else if( !strcmp(bf, "BPSK") ){ + strcpy(bf, "PSK"); + } + else if( !strcmp(bf, "QPSK") ){ + strcpy(bf, "PSK"); + } + SpaceCopy(hp->mode, bf, 3); + SetRST(hp->hiss, sp->ur, sp->mode); + SetRST(hp->myrs, sp->my, sp->mode); + + int l = GetLMode(sp->mode); + if( sp->ur[l] ) AddMMLOGKey(REM1, REM2, &sp->ur[l], "SN"); + if( sp->my[l] ) AddMMLOGKey(REM1, REM2, &sp->my[l], "RN"); + + strcpy(bf, Log.GetFreqString(sp->band, sp->fq)); + EncBand((BYTE *)hp->freq, bf); + + + if( CallOrder && (!strstr(sp->rem, "$DX")) && (!strstr(sp->qsl, "$DX")) ){ + AddMMLOGKey(REM1, REM2, "$DX", NULL); + } + + if( sp->etime ){ + tim = sp->etime / 30; + sprintf(bf, "%02u%02u", tim / 60, tim % 60); + AddMMLOGKey(REM1, REM2, bf, "END"); + } + if( sp->env ){ + sprintf(bf, "%u", sp->env); + AddMMLOGKey(REM1, REM2, bf, "ENV"); + } + AddMMLOGKey(REM1, REM2, sp->pow, "POW"); + if( sp->cq ){ + bf[0] = sp->cq; bf[1] = 0; + AddMMLOGKey(REM1, REM2, bf, "M"); + } + strcpy(bf, Log.GetOptStr(2, sp)); + char rbf[32]; + if(RemoveL2(rbf, bf, "QSL", sizeof(rbf)-1) == TRUE){ + hp->qsl[0] = rbf[0]; + hp->send[0] = rbf[1]; + hp->rcv[0] = rbf[2]; + } + else { + hp->rcv[0] = sp->recv; + if( !hp->rcv[0] ) hp->rcv[0] = ' '; + if( sp->send == 'N' ){ + hp->qsl[0] = 'N'; + hp->send[0] = ' '; + } + else if( !sp->send ){ + hp->qsl[0] = 'J'; + hp->send[0] = ' '; + } + else if( (sp->send >= 0x60)||(sp->send == '?') ){ + hp->qsl[0] = BYTE(toupper(sp->send)); + hp->send[0] = ' '; + } + else if( isalpha(sp->send) ){ + hp->qsl[0] = sp->send; + hp->send[0] = '*'; + } + else { + hp->qsl[0] = 'J'; + hp->send[0] = sp->send; + } + } + + if( !QTH.IsEmpty() || !REM1.IsEmpty() || !REM2.IsEmpty() ){ + FHDDBR fhdbr; + memset(&fhdbr, 0, sizeof(fhdbr)); + hp->ofs = ftell(dbrfp); + fhdbr.LenQTH = BYTE(strlen(QTH.c_str())); + fhdbr.LenREM1 = BYTE(strlen(REM1.c_str())); + fhdbr.LenREM2 = BYTE(strlen(REM2.c_str())); + if( fhdbr.LenQTH > 28 ){ + fhdbr.LenQTH = 28; + } + if( fhdbr.LenREM1 > 54 ){ + fhdbr.LenREM1 = 54; + } + if( fhdbr.LenREM2 > 54 ){ + fhdbr.LenREM2 = 54; + } + if( fwrite(&fhdbr, 1, sizeof(fhdbr), dbrfp) != sizeof(fhdbr) ) return FALSE; + if( fhdbr.LenQTH ){ + if( fwrite(QTH.c_str(), 1, fhdbr.LenQTH, dbrfp) != size_t(fhdbr.LenQTH) ) return FALSE; + } + if( fhdbr.LenREM1 ){ + if( fwrite(REM1.c_str(), 1, fhdbr.LenREM1, dbrfp) != size_t(fhdbr.LenREM1) ) return FALSE; + } + if( fhdbr.LenREM2 ){ + if( fwrite(REM2.c_str(), 1, fhdbr.LenREM2, dbrfp) != size_t(fhdbr.LenREM2) ) return FALSE; + } + } + else { + hp->ofs = 0L; + } + return TRUE; +} + +//*************************************************************************** +// CLogADIF クラス +CLogADIF::CLogADIF() +{ + m_bf[sizeof(m_bf)-1] = 0; +} +//--------------------------------------------------------------------------- +// ADIFファイルのオープン +int CLogADIF::Open(LPCSTR pName) +{ + Close(); + m_Mode = 0; + + m_p = NULL; + m_conv = 1; + m_fp = fopen(pName, "rt"); + if( m_fp != NULL ){ + setvbuf(m_fp, NULL, _IOFBF, 16384); + m_FileName = pName; + m_Mode = 0; + return TRUE; + } + else { + ErrorMB(MsgEng ? "Can't open '%s'": "'%s'がオープンできません.", pName); + return FALSE; + } +} +//--------------------------------------------------------------------------- +// ADIFファイルの作成 +int CLogADIF::Create(LPCSTR pName) +{ + Close(); + m_Mode = 1; + + m_fp = fopen(pName, "wt"); + if( m_fp != NULL ){ + setvbuf(m_fp, NULL, _IOFBF, 16384); + m_FileName = pName; + m_Mode = 1; + fprintf(m_fp, "ADIF Export from %s\n", VERTTL); + fprintf(m_fp, "\n\n"); + return TRUE; + } + else { + ErrorMB( MsgEng ? "Can't write to '%s'":"'%s'が作成できません.", pName); + return FALSE; + } +} +//--------------------------------------------------------------------------- +// テキストファイルのオープン +int CLogADIF::Close(void) +{ + int r = 0; + if( m_fp != NULL ){ + r = fclose(m_fp); + m_fp = NULL; + if( r ){ + ErrorMB(MsgEng ? "Can't write to '%s'":"'%s'が正しくクローズできませんでした.", m_FileName.c_str()); + } + else if( m_Mode ){ + InfoMB(MsgEng ? "Done (write to '%s')":"'%s'への書きこみを終了しました.", m_FileName.c_str()); + } + } + return r ? FALSE : TRUE; +} +const char *_BandText[]={ + "","160m","80m","80m","40m","30m","20m","17m","15m","12m","10m","6m", + "2m","70cm","23cm","13cm","6cm","3cm","3cm","1.25cm","6mm", + "4mm","2mm","1mm","65m","1.25m",NULL, +}; +//--------------------------------------------------------------------------- +// ADIFファイルの読み出し +void CLogADIF::SetData(SDMMLOG *sp, LPCSTR pKey, LPSTR pData) +{ + int l; + + if( !strcmpi(pKey, "CALL") ){ + StrCopy(sp->call, pData, MLCALL); + } + else if( !strcmpi(pKey, "QSO_DATE") ){ + sp->year = BYTE(atoin(pData, 4) % 100); + sp->date = WORD(atoin(pData+4, 4)); + } + else if( !strcmpi(pKey, "TIME_ON") ){ + int hh, mm, ss; + hh = atoin(pData, 2); + mm = atoin(pData+2, 2); + ss = pData[4] ? atoin(pData+4, 2) : 0; + sp->btime = WORD((hh * 60 + mm) * 30 + ss); + if( !sp->btime ) sp->btime++; + } + else if( !strcmpi(pKey, "TIME_OFF") ){ + int hh, mm, ss; + hh = atoin(pData, 2); + mm = atoin(pData+2, 2); + ss = pData[4] ? atoin(pData+4, 2) : 0; + sp->btime = WORD((hh * 60 + mm) * 30 + ss); + if( !sp->etime ) sp->btime++; + } + else if( !strcmpi(pKey, "FREQ") ){ + Log.SetFreq(sp, pData); + } + else if( !strcmpi(pKey, "BAND") ){ + if( !sp->band ){ + int i; + for( i = 1; _BandText[i] != NULL; i++ ){ + if( !strcmpi(_BandText[i], pData) ) break; + } + if( _BandText[i] == NULL ) i = 0; + sp->band = BYTE(i); + } + } + else if( !strcmpi(pKey, "MODE") ){ + Log.SetMode(sp, pData); + } + else if( !strcmpi(pKey, "TX_PWR") ){ + StrCopy(sp->pow, pData, MLPOW); + } + else if( !strcmpi(pKey, "RST_SENT") ){ + if( sp->ur[0] ){ + char bf[MLRST+1]; + strcpy(bf, sp->ur); + StrCopy(sp->ur, pData, MLRST); + l = strlen(sp->ur); + StrCopy(&sp->ur[l], bf, MLRST - l); + } + else { + StrCopy(sp->ur, pData, MLRST); + } + } + else if( !strcmpi(pKey, "RST_RCVD") ){ + if( sp->my[0] ){ + char bf[MLRST+1]; + strcpy(bf, sp->my); + StrCopy(sp->my, pData, MLRST); + l = strlen(sp->my); + StrCopy(&sp->my[l], bf, MLRST - l); + } + else { + StrCopy(sp->my, pData, MLRST); + } + } + else if( !strcmpi(pKey, "STX") ){ + l = strlen(sp->ur); + StrCopy(&sp->ur[l], pData, MLRST - l); + } + else if( !strcmpi(pKey, "SRX") ){ + l = strlen(sp->my); + StrCopy(&sp->my[l], pData, MLRST - l); + } + else if( !strcmpi(pKey, "QSL_SENT") ){ + if( *pData == ' ' ) *pData = 0; + sp->send = *pData; + } + else if( !strcmpi(pKey, "QSL_RCVD") ){ + if( *pData == ' ' ) *pData = 0; + sp->recv = *pData; + } + else if( !strcmpi(pKey, "NAME") ){ + StrCopy(sp->name, pData, MLNAME); + } + else if( !strcmpi(pKey, "QTH") ){ + StrCopy(sp->qth, pData, MLQTH); + } + else if( !strcmpi(pKey, "COMMENT") ){ + StrCopy(sp->rem, pData, MLREM); + } + else if( !strcmpi(pKey, "QSLMSG") ){ + StrCopy(sp->qsl, pData, MLQSL); + } + else if( !strcmpi(pKey, "CONT") ){ + StrCopy(sp->opt2, pData, MLOPT); + } + else if( !strcmpi(pKey, "QSL_VIA") ){ + AddL2(sp->qsl, "QSL", pData, '[', ']', MLQSL); + } +} +//--------------------------------------------------------------------------- +void CLogADIF::AdjustData(SDMMLOG *sp) +{ + if( !sp->etime ) sp->etime = sp->btime; + UTCtoJST(sp); + if( sp->call[0] ){ + LPCSTR pCC = ClipCC(sp->call); + Log.SetOptStr(0, sp, Cty.GetCountry(pCC)); + if( !sp->opt2[0] ) Log.SetOptStr(1, sp, Cty.GetCont(pCC)); + } + if( !sp->ur[0] ) StrCopy(sp->ur, "599", GetLMode(sp->mode)); + if( !sp->my[0] ) StrCopy(sp->my, "599", GetLMode(sp->mode)); +} +//--------------------------------------------------------------------------- +// ADIFファイルの読み出し +int CLogADIF::Read(SDMMLOG *sp) +{ + if( !IsOpen() ) return FALSE; + + LPSTR p, t, tt; + char bf[1024]; + + while(1){ + if( (m_p == NULL) || !(*m_p) ){ + if( !feof(m_fp) ){ + if( fgets(m_bf, sizeof(m_bf), m_fp) != NULL ){ + ClipLF(m_bf); + m_p = m_bf; + } + else if( sp->btime && sp->call[0] && m_conv ){ + AdjustData(sp); + m_p = NULL; + return TRUE; + } + else { + return FALSE; + } + } + else { + return FALSE; + } + } + m_p = SkipSpace(m_p); + if( *m_p == '<' ){ + m_p = StrDlm(p, m_p+1, '>'); + p = StrDlm(t, p, ':'); + p = StrDlm(tt, p, ':'); + bf[0] = 0; + int n = *tt ? atoin(tt, -1) : 0; + if( (n >= 0) && (n < 1023) && (n <= (int)strlen(m_p)) ){ + if( n ) memcpy(bf, m_p, n); + bf[n] = 0; + } + if( !strcmpi(t, "EOR") ){ + if( m_conv ){ + AdjustData(sp); + return TRUE; + } + } + if( !strcmpi(t, "EOH") ){ + m_conv = 1; + } + else if( m_conv ){ + SetData(sp, t, bf); +#if 0 + FILE *fp = fopen("F:\\TEST.TXT", "at"); + fprintf(fp, "%s:%s\n", t, bf); + fclose(fp); +#endif + m_p += n; + } + } + else if( *m_p ){ + m_p++; + } + } +} +//--------------------------------------------------------------------------- +void CLogADIF::OutF(int &col, FILE *fp, LPCSTR fmt, ...) +{ + va_list pp; + char bf[512]; + + va_start(pp, fmt); + vsprintf(bf, fmt, pp ); + va_end(pp); + if( col ){ + fputs(" ", fp); + col++; + } + int l = strlen(bf); + if( (col + l) > 80 ){ + fputs("\n", fp); + col = 0; + } + fputs(bf, fp); + col += l; +} +//--------------------------------------------------------------------------- +// 出力変換 +// +//KD4MUL 19930921 223558 150000 +//3.690 80M CW 100 599 +//599 Y N ROY STRUNK +//KY FIRST CW CONTACT WB4TXW +int CLogADIF::Write(SDMMLOG *sp) +{ + if( !IsOpen() ) return FALSE; + + int col = 0; + JSTtoUTC(sp); + OutF(col, m_fp, "%s", strlen(sp->call), sp->call); + OutF(col, m_fp, "%04u%02u%02u", YEAR(sp->year), sp->date/100, sp->date%100); + int tim = sp->btime / 30; + OutF(col, m_fp, "%02u%02u%02u", tim/60, tim%60, (sp->btime % 30)*2); + tim = sp->etime / 30; + OutF(col, m_fp, "%02u%02u%02u", tim/60, tim%60, (sp->etime % 30)*2); + LPCSTR p = Log.GetFreqString(sp->band, sp->fq); + if( *p ) OutF(col, m_fp, "%s", strlen(p), p); + p = _BandText[sp->band]; + if( *p ) OutF(col, m_fp, "%s", strlen(p), p); + p = Log.GetModeString(sp->mode); + if( *p ) OutF(col, m_fp, "%s", strlen(p), p); + if( sp->pow[0] ) OutF(col, m_fp, "%s", strlen(sp->pow), sp->pow); + int l = GetLMode(sp->mode); + if( Log.m_LogSet.m_ClipRSTADIF ){ + if( sp->ur[l] ) OutF(col, m_fp, "%s", strlen(&sp->ur[l]), &sp->ur[l]); + if( sp->my[l] ) OutF(col, m_fp, "%s", strlen(&sp->my[l]), &sp->my[l]); + sp->ur[GetLMode(sp->mode)] = 0; + sp->my[GetLMode(sp->mode)] = 0; + } + if( sp->ur[0] ) OutF(col, m_fp, "%s", strlen(sp->ur), sp->ur); + if( sp->my[0] ) OutF(col, m_fp, "%s", strlen(sp->my), sp->my); + if( sp->send ) OutF(col, m_fp, "%c", sp->send); + if( sp->recv ) OutF(col, m_fp, "%c", sp->recv); + if( sp->name[0] ) OutF(col, m_fp, "%s", strlen(sp->name), sp->name); + if( sp->qth[0] ) OutF(col, m_fp, "%s", strlen(sp->qth), sp->qth); + if( sp->rem[0] ) OutF(col, m_fp, "%s", strlen(sp->rem), sp->rem); + if( sp->opt2[0] ) OutF(col, m_fp, "%s", strlen(sp->opt2), sp->opt2); + if( sp->qsl[0] ){ + char via[MLQSL+1]; + char qsl[MLQSL+1]; + StrCopy(qsl, sp->qsl, MLQSL); + if( !RemoveL2(via, qsl, "QSL", sizeof(via)-1) ){ + via[0] = 0; + } + if( qsl[0] ) OutF(col, m_fp, "%s", strlen(qsl), qsl); + if( via[0] ) OutF(col, m_fp, "%s", strlen(via), via); + } + OutF(col, m_fp, "\n"); + return ferror(m_fp) ? FALSE : TRUE; +} + + +//*************************************************************************** +// CLogCabrillo クラス +CLogCabrillo::CLogCabrillo() +{ + m_bf[sizeof(m_bf)-1] = 0; +} +//--------------------------------------------------------------------------- +// LogCabrilloファイルのオープン +int CLogCabrillo::Open(LPCSTR pName) +{ + Close(); + m_Mode = 0; + + m_p = NULL; + m_SNR = ""; + m_fp = fopen(pName, "rt"); + if( m_fp != NULL ){ + setvbuf(m_fp, NULL, _IOFBF, 16384); + m_FileName = pName; + m_Mode = 0; + return TRUE; + } + else { + ErrorMB(MsgEng ? "Can't open '%s'": "'%s'がオープンできません.", pName); + return FALSE; + } +} +//--------------------------------------------------------------------------- +// LogCabrilloファイルの作成 +int CLogCabrillo::Create(LPCSTR pName) +{ + Close(); + m_Mode = 1; + + m_fp = fopen(pName, "wt"); + if( m_fp != NULL ){ + setvbuf(m_fp, NULL, _IOFBF, 16384); + m_FileName = pName; + m_Mode = 1; + fprintf( m_fp, "START-OF-LOG: 2.0\n"); + fprintf( m_fp, "ARRL-SECTION: \n" ); + fprintf( m_fp, "CONTEST: <== e.g. ARRL-RTTY, CQ-WW-RTTY, CQ-WPX-RTTY, BARTG-SPRINT, BARTG-RTTY\n"); + fprintf( m_fp, "CALLSIGN: %s\n", sys.m_Call.c_str() ); + fprintf( m_fp, "CATEGORY: <== e.g. SINGLE-OP ALL HIGH, SINGLE-OP-ASSISTED 20M LOW\n" ); + fprintf( m_fp, "CLAIMED-SCORE: \n"); + fprintf( m_fp, "OPERATORS:\n" ); + fprintf( m_fp, "CLUB:\n" ); + fprintf( m_fp, "NAME: <== your name\n" ); + fprintf( m_fp, "ADDRESS: <== your postal address\n" ); + fprintf( m_fp, "SOAPBOX: \n" ); + fprintf( m_fp, "CREATED-BY: %s\n", VERTTL2); + return TRUE; + } + else { + ErrorMB( MsgEng ? "Can't write to '%s'":"'%s'が作成できません.", pName); + return FALSE; + } +} +//--------------------------------------------------------------------------- +// テキストファイルのオープン +int CLogCabrillo::Close(void) +{ + int r = 0; + if( m_fp != NULL ){ + fprintf(m_fp, "END-OF-LOG:\n"); + r = fclose(m_fp); + m_fp = NULL; + if( r ){ + ErrorMB(MsgEng ? "Can't write to '%s'":"'%s'が正しくクローズできませんでした.", m_FileName.c_str()); + } + else if( m_Mode ){ + InfoMB(MsgEng ? "Done (write to '%s')\r\n\r\nMMSSTV did only make QSO section.\r\nEdit to the contest name, category, your name and address, etc... in the file.":"'%s'への書きこみを終了しました.\r\n\r\nMMSSTVはQSOセクションしか作成しません。\r\nコンテスト名、参加カテゴリ等を編集してください.", m_FileName.c_str()); + sprintf(m_bf, "NOTEPAD.EXE %s", m_FileName.c_str()); + WinExec(m_bf, SW_SHOWDEFAULT); + } + } + return r ? FALSE : TRUE; +} +//--------------------------------------------------------------------------- +// LogCabrilloファイルの読み出し +int CLogCabrillo::Read(SDMMLOG *sp) +{ + return FALSE; +} +//--------------------------------------------------------------------------- +// 出力変換 +// +int CLogCabrillo::Write(SDMMLOG *sp) +{ + if( !IsOpen() ) return FALSE; +// "","1.9","3.5","3.8","7","10","14","18","21","24","28","50", +// "144","430","1200","2400","5600","10.1G","10.4G","24G","47G", +// "75G","142G","248G","4630","220",NULL, + const char *_bandc[]={ + "??","1800","3500","3500","7000","10000","14000","18000","21000","24000","28000", + "A", "B","D","E","F","H","I","J","K","M", + "N","P","R","?","C",NULL, + }; + +// "CW","SSB","AM","FM","RTTY","PAC","FAX","SSTV","ATV","TV","FSTV", +// "A1","A2","A3","A3A","A3H","A3J","A4","A5","A5C","A5J", +// "A9","A9C","F1","F2","F3","F4","F5","F9","P0","P1", +// "P2D","P2E","P2F","P3D","P3E","P3F","P9", +// "U1","U2","U3","U4", +// "PSK","BPSK","QPSK","HELL","MFSK", + const char *_modec[]={ + "??", + "CW","PH","PH","FM","RY","RY","??","TV","TV","TV","TV", + "CW","CW","PH","PH","PH","PH","??","??","??","??", + "??","??","RY","RY","FM","??","??","??", + "??","??","??","??","??","??","??","??","??", + "??","??","??","??", + "RY","RY","RY","CW","RY", + NULL, + }; + + JSTtoUTC(sp); + int tim = sp->btime / 30; + char SNO[MLRST+1]; + char RNO[MLRST+1]; + int mno = sp->mode >= MODEMAX ? 0 : sp->mode; + int len = GetLMode(BYTE(mno)); + strcpy(SNO, &sp->ur[len]); + strcpy(RNO, &sp->my[len]); + sp->ur[len] = 0; + sp->my[len] = 0; + if( !SNO[0] ){ + if( m_SNR.IsEmpty() ){ + int r; + if( MsgEng ){ + r = InputMB("Does not exist the Sent-NR information", "Enter contest number which you sent", m_SNR); + } + else { + r = InputMB("Sent-NR情報が存在しません", "Sent-NRを入力して下さい", m_SNR); + } + if( r == FALSE ) return FALSE; + } + strcpy(SNO, m_SNR.c_str()); + } + fprintf( m_fp, "QSO:%6s %2s %04u-%02u-%02u %02u%02u %-13s %-3s %-6s %-13s %-3s %-6s\n", + _bandc[sp->band], _modec[mno], + (sp->year <= 50) ? sp->year + 2000 : sp->year + 1900, + sp->date / 100, sp->date % 100, + tim/60, tim%60, sys.m_Call.c_str(), + sp->ur, SNO, + sp->call, sp->my, RNO + ); + return ferror(m_fp) ? FALSE : TRUE; +} + diff --git a/LogConv.h b/LogConv.h new file mode 100644 index 0000000..edd377a --- /dev/null +++ b/LogConv.h @@ -0,0 +1,249 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------------- +#ifndef LogConvH +#define LogConvH +#include "LogFile.h" + +extern const char *MONT1[]; +extern const char *MONT2[]; +extern const char *_BandText[]; +//************************************************************* +// ログ変換の基本クラス +// +class CLogConv +{ +protected: + int m_Type; // 0-TEXT, 1-LOG200, 2-HAMLOG, 3-DBASE + int m_Mode; // 0-Read, 1-Write + FILE *m_fp; + + AnsiString m_FileName; // 変換中のファイル名 +public: + CLogConv(); + virtual ~CLogConv(); + virtual int IsOpen(void){return m_fp != NULL ? 1 : 0;}; + virtual int Open(LPCSTR pName)=0; + virtual int Create(LPCSTR pName)=0; + virtual int Close(void)=0; + virtual int Read(SDMMLOG *sp)=0; + virtual int Write(SDMMLOG *sp)=0; +}; + +#define TEXTCONVMAX 64 +typedef struct { + int w; + AnsiString Key; +}TCONV; + +//************************************************************* +// テキストファイルアクセスのクラス +// +class CLogText : public CLogConv +{ +public: + int m_Double; + int m_Delm; + TCONV m_rConv[TEXTCONVMAX]; + TCONV m_tConv[TEXTCONVMAX]; + int m_UTC; + int m_err; +protected: + char m_bf[2048]; // ファイルバッファ + +private: + int Text2MMLOG(SDMMLOG *sp, LPSTR p, int &err); + void MMLOG2Text(LPSTR t, SDMMLOG *sp); + +public: + CLogText(); + virtual int Open(LPCSTR pName); + virtual int Create(LPCSTR pName); + virtual int Close(void); + virtual int Read(SDMMLOG *sp); + virtual int Write(SDMMLOG *sp); + +}; + +void MMLOG2Text(LPSTR t, SDMMLOG *sp, AnsiString &Key); +int Text2MMLOG(SDMMLOG *sp, LPCSTR s, AnsiString &Key); +extern const LPCSTR ConvTbl[]; +extern CLogText LogText; + +//************************************************************* +// LOG200ファイルアクセスのクラス +// +#define LOG200WIDTH 200 +class CLog200 : public CLogConv +{ +public: + int m_Index; + int m_err; +protected: + char m_bf[200]; // ファイルバッファ +private: +public: + CLog200(); + virtual int Open(LPCSTR pName); + virtual int Create(LPCSTR pName); + virtual int Close(void); + virtual int Read(SDMMLOG *sp); + virtual int Write(SDMMLOG *sp); +}; + +//************************************************************* +// HAMLOGファイルアクセスのクラス +// +#pragma option -a- // パックの指示 +typedef struct { + char Memo; // 03h=メモフィールド無し 83h=メモフィールド有り(HAMLOGでは 1Ah) + char YY, MM, DD; // 最終更新年月日 + long Max; // レコード件数 + WORD HeadLen; // ヘッダの長さ(HAMLOG.DBSは 449) + WORD DataLen; // レコードの長さ(HAMLOG.DBSは 58) + char dummy[20]; // 00h +}DBSHD; + +typedef struct { + char Memo; // 03h=メモフィールド無し 83h=メモフィールド有り(HAMLOGでは 1Ah) + char YY, MM, DD; // 最終更新年月日 + long Max; // レコード件数 + char dm1; + char m1; // 01h + char dm2; + char dummy[21]; // 00h + char dummy2[255-32]; // 00h + char term; // 1ah +}DBRHD; + +typedef struct { + char Name[11]; + BYTE Type; + BYTE dm1[4]; + BYTE Len; + BYTE dm2[15]; +}DBSLOT; + +typedef struct { + char del[1]; /* 削除マーク */ + char calls[7]; /* コールサイン */ + char potbl[3]; /* 移動エリア */ + char code[6]; /* JCCコード */ + char glid[6]; /* グリッドロケーター */ + char freq[4]; /* 周波数 */ + char mode[3]; /* モード */ + char name[12]; /* 氏名 */ + char qsl [1]; /* QSL via */ + char send[1]; /* QSL SEND */ + char rcv[1]; /* QSL RCV */ + char date[3]; /* 日付 */ + char time[2]; /* 時間 */ + char hiss[2]; /* HIS RST */ + char myrs[2]; /* MY RST */ + long ofs; /* HAMLOG.DBR オフセットアドレス */ +}SDHAMLOG; + +typedef struct { /* DBRのフィールド位置データ */ + BYTE LenQTH; + BYTE LenREM1; + BYTE LenREM2; +}FHDDBR; +#pragma option -a. // パック解除の指示 + +class CHamLog : public CLogConv +{ +public: + int m_Index; + int m_err; +protected: + DBSHD m_hd; // DBSヘッダ + SDHAMLOG m_RecBuf; // レコードバッファ + + AnsiString m_DBRName; // DBRファイルの名前 + FILE *m_dbrfp; // DBRファイルのファイルポインタ + DBRHD m_dbrhd; // DBRヘッダ +private: + int Seek(DWORD Index); + BOOL MakeHD(void); + +public: + CHamLog(); + virtual int Open(LPCSTR pName); + virtual int Create(LPCSTR pName); + virtual int Close(void); + virtual int Read(SDMMLOG *sp); + virtual int Write(SDMMLOG *sp); +}; + +void HAMLOGtoMMLOG(SDMMLOG *sp, SDHAMLOG *hp, FILE *dbrfp); +int MMLOGtoHAMLOG(SDHAMLOG *hp, SDMMLOG *sp, FILE *dbrfp); +void AddMMLOGKey(AnsiString &REM1, AnsiString &REM2, LPCSTR s, LPCSTR pKey); +void SetMMLOGKey(SDMMLOG *sp, LPSTR bf); + +//************************************************************* +// ADIFアクセスのクラス +// +class CLogADIF : public CLogConv +{ +public: +protected: + char m_bf[1024]; // ファイルバッファ + LPSTR m_p; + int m_conv; +private: + void MMLOG2ADIF(LPSTR t, SDMMLOG *sp); + void SetData(SDMMLOG *sp, LPCSTR pKey, LPSTR pData); + void AdjustData(SDMMLOG *sp); + void OutF(int &col, FILE *fp, LPCSTR fmt, ...); + +public: + CLogADIF(); + virtual int Open(LPCSTR pName); + virtual int Create(LPCSTR pName); + virtual int Close(void); + virtual int Read(SDMMLOG *sp); + virtual int Write(SDMMLOG *sp); + +}; + +//************************************************************* +// Cabrillo アクセスのクラス +// +class CLogCabrillo : public CLogConv +{ +public: +protected: + char m_bf[1024]; // ファイルバッファ + LPSTR m_p; + AnsiString m_SNR; +private: + void MMLOG2Cabrillo(LPSTR t, SDMMLOG *sp); + void AdjustData(SDMMLOG *sp); + +public: + CLogCabrillo(); + virtual int Open(LPCSTR pName); + virtual int Create(LPCSTR pName); + virtual int Close(void); + virtual int Read(SDMMLOG *sp); + virtual int Write(SDMMLOG *sp); +}; + +#endif diff --git a/LogFile.cpp b/LogFile.cpp new file mode 100644 index 0000000..941b018 --- /dev/null +++ b/LogFile.cpp @@ -0,0 +1,1667 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------------- +#include //ja7ude 0521 +#pragma hdrstop + +#include +#include +#include +#include +#include "LogFile.h" +#include "Main.h" +#include "Hamlog5.h" +CLogFile Log; + + +//--------------------------------------------------------------------------- +// MMLOG Constant +// +enum BD { /* バンドの番号 */ + B_NULL, + B_19, + B_35, + B_38, + B_7, + B_10, + B_14, + B_18, + B_21, + B_24, + B_28, + B_50, + B_144, + B_430, + B_1200, + B_2400, + B_5600, + B_101G, + B_104G, + B_24G, + B_47G, + B_75G, + B_142G, + B_248G, + B_4630, + B_220, + B_SAT, +}; + +const char *_mBand[]={ + "","160","80","75","40","30","20","17","15","12","10","6", + "2","430","1200","2400","5600","10.1G","10.4G","24G","47G", + "75G","142G","248G","4630","220",NULL, +}; +const char *_band[]={ + "","1.9","3.5","3.8","7","10","14","18","21","24","28","50", + "144","430","1200","2400","5600","10.1G","10.4G","24G","47G", + "75G","142G","248G","4630","220",NULL, +}; +static const char *_mode[]={ + "", + "CW","SSB","AM","FM","RTTY","PAC","FAX","SSTV","ATV","TV","FSTV", + "A1","A2","A3","A3A","A3H","A3J","A4","A5","A5C","A5J", + "A9","A9C","F1","F2","F3","F4","F5","F9","P0","P1", + "P2D","P2E","P2F","P3D","P3E","P3F","P9", + "U1","U2","U3","U4", + "PSK","BPSK","QPSK","HELL","MFSK", + NULL, +}; +const char lmode[]={ + 3, 3, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, + 3, 3, 3, 3, 2, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, + 3, 3, 3, 3, 3, +}; +const char MONN[]={31,31,28,31,30,31,30,31,31,30,31,30,31}; +const char MONU[]={31,31,29,31,30,31,30,31,31,30,31,30,31}; +//--------------------------------------------------------------------------- +// CIndexクラス +int GetLMode(BYTE m) +{ + if( m < MODEMAX ){ + return lmode[m]; + } + else { + return 3; + } +} +//--------------------------------------------------------------------------- +// CIndexクラス +CIndex::CIndex() +{ + m_IndexMax = 0; // 確保中のインデックスの数 + m_IndexCnt = 0; // 現在のインデックスの数 + pIndex = NULL; // インデックス領域のポインタ(16バイトインデックス) + pMult = NULL; +} +CIndex::~CIndex() +{ + if( pIndex != NULL ){ + delete pIndex; + pIndex = NULL; + } + if( pMult != NULL ){ + delete pMult; + pMult = NULL; + } +} +void CIndex::AllocIndex(int n) +{ + if( n >= m_IndexMax ){ + int max = m_IndexMax ? (m_IndexMax * 2) : 32768; + LPSTR np = new char[16*max]; + if( pIndex != NULL ){ + memcpy(np, pIndex, m_IndexCnt*16); + delete pIndex; + } + pIndex = np; + m_IndexMax = max; + } +} + +void CIndex::ClearIndex(void) +{ + m_IndexCnt = 0; +} + +void CIndex::WriteIndex(LPCSTR pCall, int n) +{ + AllocIndex(n); + memcpy(&pIndex[n*16], pCall, 16); + if( n >= m_IndexCnt ) m_IndexCnt = n + 1; +} + +void CIndex::ReadIndex(LPSTR pCall, int n) +{ + memcpy(pCall, &pIndex[n*16], 16); + pCall[16] = 0; +} + +LPSTR CIndex::PointIndex(int n) +{ + return &pIndex[n*16]; +} + +void CIndex::AddBlock(LPCSTR p, int len) +{ + int n = len/16; + AllocIndex(n + m_IndexCnt); + memcpy(&pIndex[m_IndexCnt*16], p, len); + m_IndexCnt += n; +} +//--------------------------------------------------------------------------- +int CIndex::ReadIndex(int handle, FHD *hp) +{ + int r = TRUE; + int BUFSIZE=32768; + + CWaitCursor w; + if( lseek(handle, (hp->size * (ULONG)sizeof(SDMMLOG)) + FHDOFF, SEEK_SET) != -1L ){ + if( hp->hash != 2 ){ // 16バイトインデックスと異なる + if( hp->hash ){ // 2バイトインデックスのスキップ + lseek(handle, hp->size * 2, SEEK_CUR); + } + r = FALSE; + } + else { // 16バイトインデックス + LPSTR bp = new char[BUFSIZE]; + int len = hp->size * 16; + int rlen, wlen; + while(len){ + rlen = (len > BUFSIZE) ? BUFSIZE : len; + wlen = read(handle, bp, rlen); + if( rlen != wlen ){ + r = FALSE; + break; + } + AddBlock(bp, wlen); + len -= wlen; + } + delete bp; + } + if( pMult == NULL ) pMult = new BYTE[32768]; + read(handle, pMult, hp->mlt); + } + else { + r = FALSE; + } + return r; +} + +void CIndex::MakeIndex(int handle, FHD *hp) +{ + CWaitCursor w; + + lseek(handle, (ULONG)FHDOFF, SEEK_SET); + ClearIndex(); + + FHD fh; + memset(&fh, 0, sizeof(fh)); + + int i, rlen; + SDMMLOG sd; + for( i = 0; i < hp->size; i++ ){ + rlen = read(handle, &sd, sizeof(sd)); + if( rlen != (int)sizeof(sd) ) break; //ja7ude 0525 + WriteIndex(sd.call, i); + if( sd.mode >= MODEMAX ){ + int m = sd.mode - MODEMAX; + int f = 0; + int n; + char sbf[7]; + StrCopy(sbf, hp->mode[m], 6); + for( n = 0; (n < UMODEMAX) && fh.mode[n][0] ; n++ ){ + char tbf[7]; + StrCopy(tbf, fh.mode[n], 6); + if( !strcmp(sbf, tbf) ){ + if( m != n ){ + f++; + sd.mode = BYTE(n + MODEMAX); + break; + } + } + } + if( !fh.mode[n][0] ){ + StrCopy(fh.mode[n], sbf, 6); + if( m != n ){ + sd.mode = BYTE(n + MODEMAX); + f++; + } + } + if( f ){ + lseek( handle, -long(sizeof(sd)), SEEK_CUR); + write(handle, &sd, sizeof(sd)); + } + } + } + memcpy(hp->mode, fh.mode, sizeof(fh.mode)); + lseek( handle, (hp->size * (ULONG)sizeof(SDMMLOG)) + FHDOFF, SEEK_SET); + hp->hash = 2; // 16バイトインデックス +} + +//--------------------------------------------------------------------------- +int CIndex::WriteIndex(int handle, FHD *hp) +{ + int r = TRUE; + int BUFSIZE=32768; + + CWaitCursor w; + + if( lseek(handle, (hp->size * (ULONG)sizeof(SDMMLOG)) + FHDOFF, SEEK_SET) != -1L ){ + hp->hash = 2; + int len = hp->size * 16; + int vlen, wlen; + LPSTR cp = pIndex; + while(len){ + wlen = (len > BUFSIZE) ? BUFSIZE : len; + vlen = write(handle, cp, wlen); + if( wlen != vlen ) r = FALSE; + len -= vlen; + cp += vlen; + } + if( pMult != NULL ){ + write(handle, pMult, hp->mlt); + } + } + else { + r = FALSE; + } + return r; +} + +//--------------------------------------------------------------------------- +// CLogFindクラス +CLogFind::CLogFind() +{ + m_FindCnt = 0; + pFindTbl = new int[FINDMAX]; +} +//--------------------------------------------------------------------------- +CLogFind::~CLogFind() +{ + delete pFindTbl; + pFindTbl = NULL; +} +//--------------------------------------------------------------------------- +int CLogFind::Add(int n) +{ + if( m_FindCnt >= FINDMAX ) return 0; + + for( int i = 0; i < m_FindCnt; i++ ){ + if( pFindTbl[i] == n ) return 0; + } + pFindTbl[m_FindCnt] = n; + m_FindCnt++; + return 1; +} +//--------------------------------------------------------------------------- +void CLogFind::Ins(int n) +{ + if( m_FindCnt >= FINDMAX ) return; + + int i; + for( i = 0; i < m_FindCnt; i++ ){ + if( pFindTbl[i] == n ) return; + } + for( i = m_FindCnt - 1; i > 0; i-- ){ + pFindTbl[i] = pFindTbl[i-1]; + } + pFindTbl[0] = n; + m_FindCnt++; + m_FindCmp1Max++; + m_FindCmp2Max++; + m_FindStr1Max++; + m_FindStr2Max++; +} +//--------------------------------------------------------------------------- +// CLogFileクラス +CLogFile::CLogFile() +{ + memset(&m_sd, 0, sizeof(SDMMLOG)); + memset(&m_bak, 0, sizeof(SDMMLOG)); + + m_Open = 0; // オープンフラグ + m_EditFlag = 0; + m_Handle = 0; + memset(&m_fhd, 0, sizeof(m_fhd)); // 現在オープン中のファイルヘッダ + MakePathName("TEMP.MDT"); + m_CurNo = 0; + + // LogSet のデフォルト + + m_LogSet.m_TimeZone = 'I'; // JA + + m_LogSet.m_UpperName = 0; // 大文字への変換 + m_LogSet.m_UpperQTH = 0; // 大文字への変換 + m_LogSet.m_UpperREM = 0; // 大文字への変換 + m_LogSet.m_UpperQSL = 0; // 大文字への変換 + + m_LogSet.m_DefMyRST = 0; // 0-OFF, 1-ON + + m_LogSet.m_CopyFreq = 1; // 0-Band, 1-Freq + m_LogSet.m_CopyHis = 0; // 0-599, 1-599001, 2-599UTC + m_LogSet.m_CopyName = 1; // 0-OFF, 1-ON + m_LogSet.m_CopyQTH = 1; // 0-OFF, 1-ON + m_LogSet.m_CopyREM = 0; // 0-OFF, 1-ON + m_LogSet.m_CopyQSL = 0; // 0-OFF, 1-ON + m_LogSet.m_CopyREMB4 = 0; // 0-OFF, 1-ON + + m_LogSet.m_AutoSave = 1; + m_LogSet.m_CheckBand = 1; + + m_LogSet.m_THRTTY = "RTY"; + m_LogSet.m_THSSTV = "STV"; + m_LogSet.m_THTZ = 0; + m_LogSet.m_ClipRSTADIF = 1; + m_LogSet.m_DateType = 0; + + m_LogSet.m_FSKNR = 1; + m_LogSet.m_Backup = 1; + memcpy(m_LogSet.m_Hamlog5Len, g_Hamlog5Len, 17); +} + +CLogFile::~CLogFile() +{ + Close(); +} + +void CLogFile::ReadIniFile(LPCSTR pKey, TMemIniFile *pIniFile) +{ + m_LogSet.m_DateType = pIniFile->ReadInteger(pKey, "DateType", m_LogSet.m_DateType); + m_LogSet.m_TimeZone = (char)pIniFile->ReadInteger(pKey, "TimeZone", m_LogSet.m_TimeZone); + + m_LogSet.m_UpperName = pIniFile->ReadInteger(pKey, "UpperName", m_LogSet.m_UpperName); + m_LogSet.m_UpperQTH = pIniFile->ReadInteger(pKey, "UpperQTH", m_LogSet.m_UpperQTH); + m_LogSet.m_UpperREM = pIniFile->ReadInteger(pKey, "UpperREM", m_LogSet.m_UpperREM); + m_LogSet.m_UpperQSL = pIniFile->ReadInteger(pKey, "UpperQSL", m_LogSet.m_UpperQSL); + + m_LogSet.m_DefMyRST = pIniFile->ReadInteger(pKey, "DefMyRST", m_LogSet.m_DefMyRST); + + m_LogSet.m_CopyFreq = pIniFile->ReadInteger(pKey, "CopyFreq", m_LogSet.m_CopyFreq); + m_LogSet.m_CopyHis = pIniFile->ReadInteger(pKey, "CopyHis", m_LogSet.m_CopyHis); + m_LogSet.m_CopyName = pIniFile->ReadInteger(pKey, "CopyName", m_LogSet.m_CopyName); + m_LogSet.m_CopyQTH = pIniFile->ReadInteger(pKey, "CopyQTH", m_LogSet.m_CopyQTH); + m_LogSet.m_CopyREM = pIniFile->ReadInteger(pKey, "CopyREM", m_LogSet.m_CopyREM); + m_LogSet.m_CopyQSL = pIniFile->ReadInteger(pKey, "CopyQSL", m_LogSet.m_CopyQSL); + m_LogSet.m_CopyREMB4 = pIniFile->ReadInteger(pKey, "CopyREMB4", m_LogSet.m_CopyREMB4); + + m_LogSet.m_CheckBand = pIniFile->ReadInteger(pKey, "CheckBand", m_LogSet.m_CheckBand); + + m_LogSet.m_AutoSave = pIniFile->ReadInteger(pKey, "AutoSave", m_LogSet.m_AutoSave); + m_LogSet.m_THRTTY = pIniFile->ReadString(pKey, "THRTTY", m_LogSet.m_THRTTY); + m_LogSet.m_THSSTV = pIniFile->ReadString(pKey, "THSSTV", m_LogSet.m_THSSTV); + m_LogSet.m_THTZ = pIniFile->ReadInteger(pKey, "THTZ", m_LogSet.m_THTZ); + m_LogSet.m_ClipRSTADIF = pIniFile->ReadInteger(pKey, "ClipRSTADIF", m_LogSet.m_ClipRSTADIF); + + m_LogSet.m_FSKNR = pIniFile->ReadInteger(pKey, "FSKNR", m_LogSet.m_FSKNR); + m_LogSet.m_Backup = pIniFile->ReadInteger(pKey, "Backup", m_LogSet.m_Backup); + AnsiString ss; + GetHamlog5FieldsLen(ss); + AnsiString as = pIniFile->ReadString(pKey, "TH5Fields", ss); + SetHamlog5FieldsLen(as); +} + +void CLogFile::WriteIniFile(LPCSTR pKey, TMemIniFile *pIniFile) +{ + pIniFile->WriteInteger(pKey, "TimeZone", m_LogSet.m_TimeZone); + pIniFile->WriteInteger(pKey, "DateType", m_LogSet.m_DateType); + + pIniFile->WriteInteger(pKey, "UpperName", m_LogSet.m_UpperName); + pIniFile->WriteInteger(pKey, "UpperQTH", m_LogSet.m_UpperQTH); + pIniFile->WriteInteger(pKey, "UpperREM", m_LogSet.m_UpperREM); + pIniFile->WriteInteger(pKey, "UpperQSL", m_LogSet.m_UpperQSL); + + pIniFile->WriteInteger(pKey, "DefMyRST", m_LogSet.m_DefMyRST); + + pIniFile->WriteInteger(pKey, "CopyFreq", m_LogSet.m_CopyFreq); + pIniFile->WriteInteger(pKey, "CopyHis", m_LogSet.m_CopyHis); + pIniFile->WriteInteger(pKey, "CopyName", m_LogSet.m_CopyName); + pIniFile->WriteInteger(pKey, "CopyQTH", m_LogSet.m_CopyQTH); + pIniFile->WriteInteger(pKey, "CopyREM", m_LogSet.m_CopyREM); + pIniFile->WriteInteger(pKey, "CopyQSL", m_LogSet.m_CopyQSL); + pIniFile->WriteInteger(pKey, "CopyREMB4", m_LogSet.m_CopyREMB4); + + pIniFile->WriteInteger(pKey, "CheckBand", m_LogSet.m_CheckBand); + + pIniFile->WriteInteger(pKey, "AutoSave", m_LogSet.m_AutoSave); + pIniFile->WriteString(pKey, "THRTTY", m_LogSet.m_THRTTY); + pIniFile->WriteString(pKey, "THSSTV", m_LogSet.m_THSSTV); + pIniFile->WriteInteger(pKey, "THTZ", m_LogSet.m_THTZ); + pIniFile->WriteInteger(pKey, "ClipRSTADIF", m_LogSet.m_ClipRSTADIF); + + pIniFile->WriteInteger(pKey, "FSKNR", m_LogSet.m_FSKNR); + pIniFile->WriteInteger(pKey, "Backup", m_LogSet.m_Backup); + AnsiString ss; + GetHamlog5FieldsLen(ss); + pIniFile->WriteString(pKey, "TH5Fields", ss); +} + +void CLogFile::MakeIndex(void) +{ + if( !m_Open ) return; + + m_Index.MakeIndex(m_Handle, &m_fhd); + m_EditFlag = 1; +} + +void CLogFile::MakePathName(LPCSTR pName) +{ + char bf[256]; + + m_Name = pName; + sprintf(bf, "%s%s", MMLogDir, pName); + SetEXT(bf, ".MDT"); + m_FileName = bf; +} + +void CLogFile::MakeName(LPCSTR pPathName) +{ + if( pPathName != m_FileName.c_str() ) m_FileName = pPathName; + + char drive[_MAX_DRIVE]; + char dir[_MAX_DIR]; + char name[_MAX_FNAME]; + char ext[_MAX_EXT]; + AnsiString Dir; + + ::_splitpath( pPathName, drive, dir, name, ext ); + Dir = drive; + Dir += dir; + m_Name = name; + m_Name += ext; + if( Dir.IsEmpty() ){ + if( !MMLogDir[0] ) strcpy(MMLogDir, BgnDir); + MakePathName(m_Name.c_str()); + } + else { + strncpy(MMLogDir, Dir.c_str(), 128); + } +} + +void CLogFile::DoBackup(void) +{ + if( !Log.m_LogSet.m_Backup ) return; + if( m_FileName.IsEmpty() ) return; + + FILE *sfp = fopen(m_FileName.c_str(), "rb"); + if( sfp == NULL ) return; + + char tname[256]; + strcpy(tname, m_FileName.c_str()); + SetEXT(tname, "_BAK.MDT"); + FILE *tfp = fopen(tname, "rb"); + if( tfp != NULL ){ + long slen = filelength(fileno(sfp)); + long tlen = filelength(fileno(tfp)); + fclose(tfp); + if( slen <= tlen ){ + fclose(sfp); + return; + } + } + fclose(sfp); + ::CopyFile(m_FileName.c_str(), tname, FALSE); +} + +int CLogFile::Close(void) +{ + int r = TRUE; + if( m_Open ){ + if( m_EditFlag ){ + if( m_fhd.size ){ + SDMMLOG sd; + + GetData(&sd, m_fhd.size - 1); + if( !sd.date || !sd.btime ){ + DeleteLast(); + } + } + ULONG size = (m_fhd.size * (ULONG)sizeof(SDMMLOG))+(ULONG)FHDOFF; + if( chsize(m_Handle, size) ){ + ErrorFWrite(m_FileName.c_str()); + r = FALSE; + lseek(m_Handle, size, SEEK_SET); + } + m_Index.WriteIndex(m_Handle, &m_fhd); // インデックスの格納 + lseek(m_Handle, 0L, SEEK_SET); + if( write( m_Handle, &m_fhd, (int)sizeof(m_fhd) ) != (int)sizeof(m_fhd) ){ + ErrorFWrite(m_FileName.c_str()); + r = FALSE; + } + } + if( close(m_Handle) ){ + if( r != FALSE ){ + ErrorFWrite(m_FileName.c_str()); + r = FALSE; + } + } +// if( !m_fhd.size ) unlink(m_FileName.c_str()); // 0件の時は消去 + m_Open = 0; + } + m_EditFlag = 0; + m_Index.ClearIndex(); + return r; +} + +void CLogFile::InitHeader(void) +{ + memset(&m_fhd, 0, sizeof(m_fhd)); + strcpy(m_fhd.id, MMLOGID); + m_fhd.size = 0L; + m_fhd.mlt = 0; +} + +int CLogFile::Open(LPCSTR pName, BOOL fNew) +{ + CWaitCursor w; + Close(); + InitHeader(); + + if( pName == NULL ) pName = m_FileName.c_str(); + int omode = O_RDWR|O_BINARY; // 初回は新規作成なしでオープン + int n = 0; + while(1){ + if( (m_Handle = open(pName, omode, S_IREAD|S_IWRITE)) > 0 ){ + if( read(m_Handle, &m_fhd, (int)sizeof(m_fhd)) == (int)sizeof(m_fhd) ){ //ja7ude 0525 + if( !strcmp(m_fhd.id, MMLOGID) ){ + if( m_Index.ReadIndex(m_Handle, &m_fhd) != TRUE ){ + m_Index.MakeIndex(m_Handle, &m_fhd); + } + m_Open = 1; + MakeName(pName); + m_Find.Clear(); + SetLastPos(); + memcpy(&m_asd, &m_sd, sizeof(m_asd)); + return TRUE; + } + else { + close(m_Handle); + ErrorMB("'%s' is not a correct format.", pName); + } + } + else if( omode & O_CREAT ){ // 新規ファイル 2回目のパスのみ + InitHeader(); + if( write(m_Handle, &m_fhd, (int)sizeof(m_fhd)) != (int)sizeof(m_fhd) ){ //ja7ude 0525 + close(m_Handle); + ErrorMB("Cannot open '%s'.", pName); + } + else { + m_Open = 1; + MakeName(pName); + m_Index.ClearIndex(); + m_Find.Clear(); + SetLastPos(); + memcpy(&m_asd, &m_sd, sizeof(m_asd)); + return TRUE; + } + } + else { // 既存のフィアル + close(m_Handle); + ErrorMB("Cannot open '%s'.", pName); + } + return FALSE; + } + // オープンエラーの場合 + if( !(omode & O_CREAT) && (errno == ENOENT) ){ // 1回目でファイルが存在しない場合 + n++; + if( n >= 2 ){ + if( fNew ){ + if( YesNoMB(MsgEng ? "Log file (%s) does not exist, create it ?" : "ログファイル(%s)が見つかりません. 新規に作成しますか ?", pName) != IDYES ) return FALSE; + } + omode |= O_CREAT; // 2回目は新規作成付きでオープン + } + else { + ::Sleep(1000); + } + } + else if( IsFile(pName) && (GetFileAttributes(pName) & FILE_ATTRIBUTE_READONLY) ){ + ErrorMB("'%s' is read-only.", pName); + return FALSE; + } + else { + ErrorMB("Cannot open '%s'.", pName); + return FALSE; + } + } +} + +void CLogFile::InitCur(void) +{ + SetLastPos(); +} + +void CLogFile::SetLastPos(void) +{ + m_CurNo = m_fhd.size; + memset(&m_sd, 0, sizeof(SDMMLOG)); + + int n = m_CurNo - 1; + if( n >= 0 ){ + SDMMLOG sd; + + GetData(&sd, n); + if( !sd.etime ){ + m_CurNo = n; + memcpy(&m_sd, &sd, sizeof(SDMMLOG)); + } + } + else { +#if 0 + if( lcid != LANG_JAPANESE ){ + m_sd.band = B_14; + m_sd.fq = 230; + } + else { + m_sd.band = B_7; + m_sd.fq = 33; + } +#else + m_sd.band = B_14; + m_sd.fq = 230; +#endif + m_sd.mode = 8; + m_sd.env = 1; + } + CopyAF(); + m_CurChg = 0; +} + +int CLogFile::GetData(SDMMLOG *sp, int n) +{ + if( !m_Open || (n >= m_fhd.size) ){ + memset(sp, 0, sizeof(SDMMLOG)); + if( !n ){ + m_sd.band = B_14; + m_sd.mode = 5; + } + return FALSE; + } + if( lseek(m_Handle, (ULONG)FHDOFF + ((ULONG)n * (ULONG)sizeof(SDMMLOG)), SEEK_SET) == -1L ){ + memset(sp, 0, sizeof(SDMMLOG)); + return FALSE; + } + if( read( m_Handle, sp, (int)sizeof(SDMMLOG) ) != (int)sizeof(SDMMLOG) ){ //ja7ude 0525 + memset(sp, 0, sizeof(SDMMLOG)); + return FALSE; + } + else { + return TRUE; + } +} + +int CLogFile::PutData(SDMMLOG *sp, int n) +{ + if( !m_Open ){ + if( m_FileName.IsEmpty() ){ + ErrorMB("ログファイルの名前が定義されていません."); + return FALSE; + } + if( Open(m_FileName.c_str(), TRUE) != TRUE ) return FALSE; + } + if( lseek(m_Handle, (ULONG)FHDOFF + ((ULONG)n * (ULONG)sizeof(SDMMLOG)), SEEK_SET) == -1L ){ + ErrorFWrite(m_FileName.c_str()); + return FALSE; + } + if( write( m_Handle, sp, (int)sizeof(SDMMLOG) ) != (int)sizeof(SDMMLOG) ){ //ja7ude 0525 + ErrorFWrite(m_FileName.c_str()); + return FALSE; + } + else { + m_EditFlag = 1; + if( m_CurNo == n ) m_CurChg = 1; + if( n >= m_fhd.size ) m_fhd.size = n + 1; + m_Index.WriteIndex(sp->call, n); + } + return TRUE; +} + +LPCSTR CLogFile::GetOptStr(int n, SDMMLOG *sp) +{ + switch(n){ + case 0: + return sp->opt1; + case 1: + return sp->opt2; + case 2: + if( !sp->ur[MLRST-MLOPT-1] && sp->ur[MLRST-MLOPT] ){ + return &sp->ur[MLRST-MLOPT]; + } + else { + return ""; + } + case 3: + if( !sp->my[MLRST-MLOPT-1] && sp->my[MLRST-MLOPT] ){ + return &sp->my[MLRST-MLOPT]; + } + else { + return ""; + } + default: + return ""; + } +} + +void CLogFile::SetOptStr(int n, SDMMLOG *sp, LPCSTR pOpt) +{ + switch(n){ + case 0: + StrCopy(sp->opt1, pOpt, MLOPT); + jstrupr(sp->opt1); + break; + case 1: + StrCopy(sp->opt2, pOpt, MLOPT); + jstrupr(sp->opt2); + break; + case 2: + if( *pOpt ){ + StrCopy(&sp->ur[MLRST-MLOPT], pOpt, MLOPT); + jstrupr(&sp->ur[MLRST-MLOPT]); + sp->ur[MLRST-MLOPT-1] = 0; + } + else if( !sp->ur[MLRST-MLOPT-1] ){ + sp->ur[MLRST-MLOPT] = 0; + } + break; + case 3: + if( *pOpt ){ + StrCopy(&sp->my[MLRST-MLOPT], pOpt, MLOPT); + jstrupr(&sp->my[MLRST-MLOPT]); + sp->my[MLRST-MLOPT-1] = 0; + } + else if( !sp->my[MLRST-MLOPT-1] ){ + sp->my[MLRST-MLOPT] = 0; + } + break; + default: + break; + } +} + +void CLogFile::SetHisRST(SDMMLOG *sp) +{ + int n, tim; + + switch(m_LogSet.m_CopyHis){ + case 0: + if( sp == NULL ){ + strcpy(m_sd.ur, "595"); + } + else { + strcpy(m_sd.ur, sp->ur); + memcpy(m_sd.ur, "595", 3); + } + break; + case 1: + if( sp == NULL ){ + strcpy(m_sd.ur, "595001"); + } + else { + if( sp->ur[0] ){ + n = atoin(&sp->ur[3], -1); + } + else { + n = 0; + } + n++; + if( n >= 10000 ){ + sprintf(m_sd.ur, "595%04u", n); + } + else { + sprintf(m_sd.ur, "595%03u", n); + } + } + break; + case 2: + if( m_sd.btime ){ + tim = m_sd.btime / 30; + if( tim >= (9 * 60) ){ + tim -= 9 * 60; + } + else { + tim += 15 * 60; + } + sprintf(m_sd.ur, "595%02u%02u", tim/60, tim%60); + } + break; + } +} + +void CLogFile::CopyAF(void) +{ + int n = m_CurNo - 1; + if( n >= 0 ){ + SDMMLOG sd; + GetData(&sd, n); + if( !m_sd.band ){ + m_sd.band = sd.band; + if( m_LogSet.m_CopyFreq ){ + m_sd.fq = sd.fq; + } + else { + m_sd.fq = 0; + } + } + if( !m_sd.env ){ + m_sd.env = sd.env; + } + if( !m_sd.pow[0] ){ + strcpy(m_sd.pow, sd.pow); + } + if( !m_sd.ur[0] ){ + SetHisRST(&sd); + } + if( m_LogSet.m_CopyREMB4 ){ + strcpy(m_sd.rem, sd.rem); + } + } + else { + if( !m_sd.band ){ + m_sd.band = B_14; + m_sd.fq = 0; + } + if( !m_sd.env ){ + m_sd.env = 1; + } + if( !m_sd.ur[0] ){ + SetHisRST(NULL); + } + } + if( !m_sd.mode ) m_sd.mode = 8; // SSTV + if( m_LogSet.m_DefMyRST ){ + if( !m_sd.my[0] ){ + strcpy(m_sd.my, "595"); + } + } +} + +static int _cmpdate(SDMMLOG *s, SDMMLOG *t) +{ + int r = YEAR(s->year) - YEAR(t->year); + if( r ) return r; + r = s->date - t->date; + if( r ) return r; + return s->btime - t->btime; +} + +void CLogFile::SortDate(int bb, int eb) +{ + int gap, i, j, em; + SDMMLOG sd1, sd2; + + CWaitCursor w; + if( bb != eb ){ + em = eb - bb; + for( gap = (em + 1)/2; gap > 0; gap /= 2 ){ + for( i = gap; i <= em; i++ ){ + for( j = i - gap; j >= 0; j -= gap ){ + GetData(&sd1, bb+j); + GetData(&sd2, bb+j+gap); + if( _cmpdate(&sd1, &sd2) <= 0 ) break; + PutData(&sd1, bb+j+gap); + PutData(&sd2, bb+j); + } + } + } + } + m_EditFlag = 1; +} + +int CLogFile::FindSameBand(void) +{ + if( !m_sd.call[0] ) return 0; + char call[MLCALL+1]; + SDMMLOG sd; + + MultProc(); + int i; + for( i = 0; i < m_Find.GetCount(); i++ ){ + m_Index.ReadIndex(call, m_Find.pFindTbl[i]); + if( !strcmp(call, m_sd.call) ){ + GetData(&sd, m_Find.pFindTbl[i]); + MultProc(); + if( !sd.etime && (i == (m_Find.GetCount()-1)) ) break; + if( (sd.band == m_sd.band)&&(sd.mode == m_sd.mode) ) return 1; + } + } + return 0; +} + +int CLogFile::FindSameDate(void) +{ + if( !m_sd.call[0] ) return 0; + char call[MLCALL+1]; + SDMMLOG sd; + + SYSTEMTIME utc; + GetUTC(&utc); + MultProc(); + int i; + for( i = 0; i < m_Find.GetCount(); i++ ){ + m_Index.ReadIndex(call, m_Find.pFindTbl[i]); + if( !strcmp(call, m_sd.call) ){ + GetData(&sd, m_Find.pFindTbl[i]); + MultProc(); + if( !sd.etime && (i == (m_Find.GetCount()-1)) ) break; + WORD btime = sd.btime; + JSTtoUTC(&sd); + int yy = sd.year + 2000; + int mm = sd.date / 100; + int dd = sd.date % 100; + if( (sd.mode == 8) && (btime != m_sd.btime) && (yy == utc.wYear) && (mm == utc.wMonth) && (dd == utc.wDay) ) return 1; + } + } + return 0; +} + +void CLogFile::FindStrSet(CLogFind *fp, LPCSTR pCall) +{ + if( !*pCall ) return; + if( fp->GetCount() >= FINDMAX ) return; + char call[MLCALL+1]; + + MultProc(); + int i; + for( i = m_fhd.size - 1; i >= 0; i-- ){ + m_Index.ReadIndex(call, i); + if( strstr(call, pCall)!=NULL ){ + fp->Add(i); + if( fp->GetCount() >= FINDMAX ) break; + } + } +} + +int CLogFile::FindCmpSet(CLogFind *fp, LPCSTR pCall) +{ + if( fp->GetCount() >= FINDMAX ) return 0; + char call[MLCALL+1]; + + MultProc(); + int i; + for( i = m_fhd.size - 1; i >= 0; i-- ){ + if( *pCall ){ + m_Index.ReadIndex(call, i); + if( !strcmp(call, pCall) ){ + fp->Write(i); + } + } + else { + fp->Write(i); + } + if( fp->GetCount() >= FINDMAX ) break; + } + return fp->GetCount(); +} + +int CLogFile::FindClipSet(CLogFind *fp, LPCSTR pCall) +{ + if( !*pCall ) return 0; + if( fp->GetCount() >= FINDMAX ) return 0; + char call[MLCALL+1]; + + MultProc(); + int i; + for( i = m_fhd.size - 1; i >= 0; i-- ){ + m_Index.ReadIndex(call, i); + if( !strcmp(ClipCall(call), pCall) ){ + fp->Add(i); + } + if( fp->GetCount() >= FINDMAX ) break; + } + return fp->GetCount(); +} + +int CLogFile::FindSet(CLogFind *fp, LPCSTR pCall) +{ + fp->SetText(pCall); + fp->Clear(); + int r = FindCmpSet(fp, pCall); + fp->m_FindCmp1Max = fp->m_FindCnt; + char clipcall[MLCALL+1]; + strcpy(clipcall, ClipCall(pCall)); + if( FindClipSet(fp, clipcall) ){ + r = 1; + } + fp->m_FindCmp2Max = fp->m_FindCnt; + FindStrSet(fp, pCall); + fp->m_FindStr1Max = fp->m_FindStr2Max = fp->m_FindCnt; + if( strcmp(pCall, clipcall) ){ + FindStrSet(fp, clipcall); + fp->m_FindStr2Max = fp->m_FindCnt; + } + return r; +} + +int CLogFile::Find(LPCSTR pCall, int b, int dir) +{ + if( !m_fhd.size ) return -1; + char call[MLCALL+1]; + + MultProc(); + int i; + if( dir ){ + for( i = b; i >= 0; i-- ){ + m_Index.ReadIndex(call, i); + if( strstr(call, pCall) != NULL ) return i; + } + } + else { + for( i = b; i < m_fhd.size; i++ ){ + m_Index.ReadIndex(call, i); + if( strstr(call, pCall) != NULL ) return i; + } + } + return -1; +} + +int CLogFile::IsAlready(LPCSTR pCall) +{ + if( !m_fhd.size ) return -1; + char call[MLCALL+1]; + + for( int i = m_CurNo; i >= 0; i-- ){ + m_Index.ReadIndex(call, i); + if( !strcmp(call, pCall) ) return i; + } + return -1; +} + +void CLogFile::DeleteAll(void) +{ + m_fhd.size = 0; + m_CurNo = m_fhd.size; + m_CurChg = 1; + m_EditFlag = 1; +} + +void CLogFile::DeleteLast(void) +{ + if( m_fhd.size ){ + m_fhd.size--; + } + m_CurNo = m_fhd.size; + m_CurChg = 1; + m_EditFlag = 1; +} + +void CLogFile::Delete(int top, int end) +{ + if( !m_fhd.size ) return; + + if( end >= (m_fhd.size - 1) ){ // 最後まで削除する場合 + m_fhd.size = top; + m_CurNo = m_fhd.size; + } + else { // 途中を削除する場合 + int i, j; + SDMMLOG sd; + for( i = top, j = end + 1; j < m_fhd.size; i++, j++ ){ + GetData(&sd, j); + PutData(&sd, i); + } + m_fhd.size -= end - top + 1; + m_CurNo = m_fhd.size; + } + SetLastPos(); + m_CurChg = 1; + m_EditFlag = 1; +} + +void CLogFile::Insert(int n, SDMMLOG *sp) +{ + if( n >= m_fhd.size ){ // 最終位置の場合は追加と同じ + PutData(sp, n); + m_CurNo++; + } + else { // 途中を削除する場合 + int i, j; + SDMMLOG sd; + i = m_fhd.size; + j = i - 1; + for( ; i > n; i--, j-- ){ + GetData(&sd, j); + PutData(&sd, i); + } + PutData(sp, n); + m_CurNo++; + m_CurChg = 0; + } + m_EditFlag = 1; +} + +LPCSTR CLogFile::GetDateString(SDMMLOG *sp, int sw) +{ + static char bf[12]; + + if( sp->date ){ + switch(sw){ + case 1: // yyyy-mm-dd + sprintf(bf, "%04u.%02u.%02u", YEAR(sp->year), sp->date/100, sp->date%100); + break; + case 2: // dd-mm-yy + sprintf(bf, "%02u.%02u.%02u", sp->date%100, sp->date/100, sp->year); + break; + case 3: // dd-mm-yyyy + sprintf(bf, "%02u.%02u.%04u", sp->date%100, sp->date/100, YEAR(sp->year)); + break; + case 4: // mm-dd-yy + sprintf(bf, "%02u.%02u.%02u", sp->date/100, sp->date%100, sp->year); + break; + case 5: // mm-dd-yyyy + sprintf(bf, "%02u.%02u.%04u", sp->date/100, sp->date%100, YEAR(sp->year)); + break; + default: // yy-mm-dd + sprintf(bf, "%02u.%02u.%02u", sp->year, sp->date/100, sp->date%100); + break; + } + } + else { + bf[0] = 0; + } + return bf; +} + +LPCSTR CLogFile::GetTimeString(WORD d) +{ + static char bf[8]; + + if( d ){ + d = WORD(d / 30); + sprintf(bf, "%02u%02u", d / 60, d % 60); + } + else { + bf[0] = 0; + } + return bf; +} + +LPCSTR CLogFile::GetModeString(BYTE m) +{ + if( m < MODEMAX ){ + return _mode[m]; + } + else { + m -= BYTE(MODEMAX); + StrCopy(m_modebuf, m_fhd.mode[m], 6); + return m_modebuf; + } +} + +void CLogFile::SetMode(SDMMLOG *sp, LPCSTR s) +{ + if( !*s ){ + sp->mode = 0; + return; + } + + int n; + const char **t; + char bf[7]; + StrCopy(bf, s, 6); + jstrupr(bf); + s = bf; + int len = strlen(s); + for( n = 0, t = _mode; *t != NULL; t++, n++ ){ + if( !strcmp(*t, s) ){ + sp->mode = BYTE(n); + return; + } + } + for( n = 0; (n < UMODEMAX) && m_fhd.mode[n][0] ; n++ ){ + char vbf[7]; + StrCopy(vbf, m_fhd.mode[n], 6); + if( !strcmp(vbf, s) ){ + sp->mode = BYTE(n + MODEMAX); + return; + } + } + if( n < UMODEMAX ){ + if( len < 6 ){ + strcpy(m_fhd.mode[n], s); + } + else { + memcpy(m_fhd.mode[n], s, 6); + } + sp->mode = BYTE(n + MODEMAX); + } + else { + sp->mode = 0; + } +} + +LPCSTR CLogFile::GetFreqString(BYTE b, short fq) +{ + static char bf[12]; + int d; + + if( fq < 0 ){ + sprintf( bf, "%s/%s", _band[b], _band[-fq]); + return(bf); + } + else if( fq ){ + switch(b){ + case 0: + return ""; + case B_19: /* 1.9 */ + if( fq == 800 ){ + strcpy(bf, "1.8"); + } + else { + sprintf( bf, "1.%03u", fq ); + } + break; + case B_35: /* 3.5 */ + sprintf( bf, "3.%03u", fq ); + break; + case B_38: /* 3.8 */ + sprintf( bf, "3.%03u", fq ); + break; + case B_1200: + d = 1240 + (fq / 100); + sprintf( bf, "%u.%02u", d, fq % 100 ); + break; + case B_2400: + d = 2350 + (fq / 100); + sprintf( bf, "%u.%02u", d, fq % 100 ); + break; + case B_220: + d = 220 + (fq / 1000); + sprintf( bf, "%u.%03u", d, fq % 1000 ); + break; + default: + if( b <= B_24 ){ + sprintf( bf, "%s.%03u", _band[b], fq ); + } + else if( b <= B_430 ){ + d = atoin(_band[b], -1) + (fq / 1000); + sprintf( bf, "%u.%03u", d, fq % 1000 ); + } + else { + return(_band[b]); + } + break; + } + return(bf); + } + else { + return(_band[b]); + } +} + +/*#$% +=============================================================== + バンド番号を得る +--------------------------------------------------------------- + p : 文字列のポインタ +--------------------------------------------------------------- +--------------------------------------------------------------- +=============================================================== +*/ +static BYTE _bandno_(LPCSTR p) +{ + char n; + const char **t; + + for( n = 0, t = _band; *t != NULL; t++, n++ ){ + if( !strcmp(*t, p) ) return(n); + } + return(0); +} + +/*#$% +=============================================================== + バンド番号を得る +--------------------------------------------------------------- + p : 文字列のポインタ +--------------------------------------------------------------- +--------------------------------------------------------------- +=============================================================== +*/ +void CLogFile::SetFreq(SDMMLOG *sp, LPCSTR p) +{ + BYTE n; + char ub[16], db[16]; + int ud, d; + + sp->fq = 0; + if( strchr(p, '/' )!=NULL ){ + p = _strdmcpy(ub, p, '/'); + if( (n = _bandno_(ub))!= 0 ){ + if( (sp->fq = _bandno_(p))!= 0 ){ + sp->fq = SHORT(-sp->fq); + sp->band = n; + return; + } + } + sp->band = 0; + return; + } + if( (n = _bandno_(p))!= 0 ){ + sp->band = n; + return; + } + if( strchr(p, '.')!=NULL ){ + p = _strdmcpy(ub, p, '.'); + memset(db, 0, 4); + strcpy(db, p); + db[3] = 0; + for( n = 0; n < 3; n++ ){ + if( !db[n] ) db[n] = '0'; + } + ud = atoin(ub, -1); + d = atoin(db, -1); + } + else { + ud = atoin(p, -1); + d = 0; + } + if( ud == 1 ){ + sp->fq = SHORT(d); + sp->band = B_19; + } + else if( ud == 3 ){ + sp->fq = SHORT(d); + if( d >= 700 ){ + n = B_38; + } + else { + n = B_35; + } + sp->band = n; + } + else if( (ud >= 7) && (ud <= 24) ){ + sp->fq = SHORT(d); + if( (n = _bandno_(ub))!= 0 ){ + sp->band = n; + return; + } + sp->fq = 0; + sp->band = 0; + } + else if( (ud >= 28)&&(ud <= 29) ){ + sp->fq = SHORT(((ud - 28) * 1000) + d); + sp->band = B_28; + } + else if( (ud >= 50)&&(ud <= 54) ){ + sp->fq = SHORT(((ud - 50) * 1000) + d); + sp->band = B_50; + } + else if( (ud >= 144) && (ud <= 147) ){ + sp->fq = SHORT(((ud - 144) * 1000) + d); + sp->band = B_144; + } + else if( (ud >= 430) && (ud <= 440) ){ + sp->fq = SHORT(((ud - 430) * 1000) + d); + sp->band = B_430; + } + else if( (ud >= 220) && (ud <= 225) ){ + sp->fq = SHORT(((ud - 220) * 1000) + d); + sp->band = B_220; + } + else if( (ud >= 1240) && (ud <= 1300) ){ + sp->fq = SHORT(((ud - 1240) * 100) + (d/10)); + sp->band = B_1200; + } + else if( (ud >= 2350) && (ud <= 2450) ){ + sp->fq = SHORT(((ud - 2350) * 100) + (d/10)); + sp->band = B_2400; + } + else { + sp->band = 0; + } +} + +int CLogFile::ReadAscii(SDMMLOG *sp, LPSTR p) +{ + LPSTR t; + int y, m, d; + + memset(sp, 0, sizeof(SDMMLOG)); + p = StrDlm(t, p); /* DATE */ + if( sscanf(t, "%u.%u.%u", &y, &m, &d )!=3 ) return FALSE; + sp->year = BYTE(y % 100); + sp->date = WORD((m * 100) + d); + p = StrDlm(t, p); /* BGN */ + if( sscanf(t, "%u.%u", &d, &y) != 2 ){ + d = atoin(t, -1); + y = 0; + } + m = d / 100; + d = d % 100; + y /= 2; + sp->btime = WORD((((m * 60) + d) * 30) + y); + p = StrDlm(t, p); /* CALL */ + StrCopy(sp->call, t, MLCALL); + p = StrDlm(t, p); /* UR */ + StrCopy(sp->ur, t, MLRST); + p = StrDlm(t, p); /* MY */ + StrCopy(sp->my, t, MLRST); + p = StrDlm(t, p); /* BAND */ + SetFreq(sp, t); + p = StrDlm(t, p); /* MODE */ + SetMode(sp, t); + p = StrDlm(t, p); /* POW */ + StrCopy(sp->pow, t, MLPOW); + p = StrDlm(t, p); /* NAME */ + StrCopy(sp->name, t, MLNAME); + p = StrDlm(t, p); /* QTH */ + StrCopy(sp->qth, t, MLQTH); + p = StrDlm(t, p); /* REM */ + StrCopy(sp->rem, t, MLREM); + p = StrDlm(t, p); /* QSL */ + StrCopy(sp->qsl, t, MLQSL); + p = StrDlm(t, p); /* ETIME*/ + d = atoin(t, -1); + m = d / 100; + d = d % 100; + sp->etime = WORD(((m * 60) + d) * 30); + p = StrDlm(t, p); /* S */ + sp->send = *t; + p = StrDlm(t, p); /* R */ + sp->recv = *t; + p = StrDlm(t, p); /* M */ + sp->cq = *t; + p = StrDlm(t, p); /* ENV */ + sp->env = WORD(atoin(t, -1)); + p = StrDlm(t, p); /* OPT1 */ + StrCopy(sp->opt1, t, MLOPT); + p = StrDlm(t, p); /* OPT2 */ + StrCopy(sp->opt2, t, MLOPT); + p = StrDlm(t, p); /* USR1 */ + if( *t ) SetOptStr(2, sp, t); + StrDlm(t, p); /* USR2 */ + if( *t ) SetOptStr(3, sp, t); + return TRUE; +} + +void JSTtoUTC(int &Year, int &Mon, int &Day, int &Hour) +{ + + Hour -= 9; + if( Hour < 0 ){ + Hour += 24; + Day--; + if( Day < 1 ){ + Mon--; + if( Mon < 1 ){ + Mon = 12; + if( Year ){ + Year--; + } + else { + Year = 99; + } + } + if( Year % 4 ){ + Day = MONN[Mon]; + } + else { + Day = MONU[Mon]; + } + } + } +} + +void JSTtoUTC(SDMMLOG *sp) +{ + int Year = sp->year; + int Mon = sp->date / 100; + int Day = sp->date % 100; + int Hour = sp->btime / (60*30); + if( sp->date || sp->btime ){ + JSTtoUTC(Year, Mon, Day, Hour); + sp->year = BYTE(Year); + sp->date = WORD(Mon * 100 + Day); + sp->btime = WORD((sp->btime % 1800) + (Hour * 1800)); + } + if( sp->etime ){ + // JST to UTC + if( sp->etime >= (9*60*30) ){ + sp->etime -= WORD(9 * 60 * 30); + } + else { + sp->etime += WORD(15 * 60 * 30); + } + if( !sp->etime ) sp->etime++; + } +} + +void UTCtoJST(int &Year, int &Mon, int &Day, int &Hour) +{ + LPCSTR mt; + + Hour += 9; + if( Hour >= 24 ){ + Hour -= 24; + Day++; + if( Year % 4 ){ + mt = MONN; + } + else { + mt = MONU; + } + if( Day > mt[Mon] ){ + Day = 1; + Mon++; + if( Mon > 12 ){ + Mon = 1; + Year++; + if( Year >= 100 ) Year = 0; + } + } + } +} + +void UTCtoJST(SDMMLOG *sp) +{ + int Year = sp->year; + int Mon = sp->date / 100; + int Day = sp->date % 100; + int Hour = sp->btime / (60*30); + if( sp->date || sp->btime ){ + UTCtoJST(Year, Mon, Day, Hour); + sp->year = BYTE(Year); + sp->date = WORD(Mon * 100 + Day); + sp->btime = WORD((sp->btime % 1800) + (Hour * 1800)); + } + if( sp->etime ){ + // UTC to JST + if( sp->etime >= (15*60*30) ){ + sp->etime -= WORD(15 * 60 * 30); + } + else { + sp->etime += WORD(9 * 60 * 30); + } + if( !sp->etime ) sp->etime++; + } +} + +void UTCtoJST(SYSTEMTIME *tp) +{ + int y = tp->wYear; + int m = tp->wMonth; + int d = tp->wDay; + int h = tp->wHour; + UTCtoJST(y, m, d, h); + tp->wYear = WORD(y); + tp->wMonth = WORD(m); + tp->wDay = WORD(d); + tp->wHour = WORD(h); +} + +void mBandToBand(SDMMLOG *sp, LPCSTR p) +{ + int m; + + sp->fq = 0; + if( !strcmpi(p, "SAT") ){ + sp->band = 0; + } + else if( sscanf(p, "%u", &m) == 1 ){ + switch(m){ + case 2: + sp->band = B_144; + break; + case 6: + sp->band = B_50; + break; + case 10: + sp->band = B_28; + break; + case 12: + sp->band = B_24; + break; + case 15: + sp->band = B_21; + break; + case 17: + sp->band = B_18; + break; + case 20: + sp->band = B_14; + break; + case 30: + sp->band = B_10; + break; + case 40: + sp->band = B_7; + break; + case 75: + sp->band = B_38; + break; + case 80: + sp->band = B_35; + break; + case 160: + sp->band = B_19; + sp->fq = 800; + break; + } + } +} + +LPCSTR FreqTomBand(SDMMLOG *sp) +{ + return _mBand[sp->band]; +} + + diff --git a/LogFile.h b/LogFile.h new file mode 100644 index 0000000..3e6e99b --- /dev/null +++ b/LogFile.h @@ -0,0 +1,280 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------------- +#ifndef LogFileH +#define LogFileH + +#include "ComLib.h" +//--------------------------------------------------------------------------- +#define MMLOGID "MMLOG DATA Ver1.00\032" + +typedef struct { // Logの動作オプション + char m_TimeZone; // 表示用タイムゾーン + + int m_UpperName; // 大文字への変換 + int m_UpperQTH; // 大文字への変換 + int m_UpperREM; // 大文字への変換 + int m_UpperQSL; // 大文字への変換 + + int m_DefMyRST; // 0-OFF, 1-ON + + int m_CopyFreq; // 0-Band, 1-Freq + int m_CopyHis; // 0-599, 1-599001, 2-599UTC + int m_CopyName; // 0-OFF, 1-ON + int m_CopyQTH; // 0-OFF, 1-ON + int m_CopyREM; // 0-OFF, 1-ON + int m_CopyQSL; // 0-OFF, 1-ON + int m_CopyREMB4; // 0-OFF, 1-ON + + int m_AutoSave; // 自動セーブ + + int m_QSOMacroFlag; // 0-OFF, 1-ON + int m_CheckBand; // 同一バンドでの重複をチェック + int m_QSOMacro[5]; // 0-Run 1st, 1-Run 2nd, 2-Run Dupe, 3-S&P 1st, 4-S&P 2nd + WORD m_QSOMacroKey[5]; + AnsiString m_QSOMacroStr[5]; + + AnsiString m_THRTTY; + AnsiString m_THSSTV; + int m_THTZ; + int m_ClipRSTADIF; + int m_DateType; + + int m_FSKNR; // コンテストNRをFSKIDに含める + int m_Backup; // バックアップ作成 + + BYTE m_Hamlog5Len[17]; +}LOGSET; + +#define MLCALL 16 /* コールサインの長さ */ +#define MLRST 20 /* RSTナンバの長さ */ +#define MLREM 56 /* 記事の長さ */ +#define MLNAME 16 /* 名前の長さ */ +#define MLQTH 28 /* QTHの長さ */ +#define MLQSL 54 /* QSLの長さ */ +#define MLPOW 4 /* 電力 */ +#define MLOPT 8 /* オプション */ + +#define MODEMAX 48 + +#define YEAR(c) (((c)<50)?(2000+(c)):(1900+(c))) + +#pragma option -a- // パックの指示 +typedef struct { /* MMLOGデータ形式 */ + BYTE year; /* 年 */ + WORD date; /* 日付 */ + WORD btime; /* 開始時刻 */ + WORD etime; /* 終了時刻 */ + char call[MLCALL+1]; /* コールサイン */ + char ur[MLRST+1]; /* T リポート */ + char my[MLRST+1]; /* R リポート */ + BYTE band; /* バンド */ + SHORT fq; /* 周波数 */ + BYTE mode; /* モード */ + char pow[MLPOW+1]; /* 電力 */ + char name[MLNAME+1]; /* 名前 */ + char qth[MLQTH+1]; /* QTH */ + char qsl[MLQSL+1]; /* QSL */ + char send; /* QSL 送信 */ + char recv; /* QSL 受信 */ + char cq; /* cq/call */ + WORD env; /* 自局環境 */ + char rem[MLREM+1]; /* 記事 */ + char opt1[MLOPT+1]; /* オプション */ + char opt2[MLOPT+1]; /* オプション2 */ +}SDMMLOG; + +#define FHDOFF 256 /* 先頭のヘッダのオフセット */ +#define UMODEMAX 32 +typedef struct { + char id[20]; /* ファイルバージョン */ + char dmy[4]; /* ダミー領域 */ + USHORT mlt; /* マルチ情報のサイズ */ + char td; /* 時差コード */ + char hash; /* ハッシュデータ格納フラグ */ + long size; /* データサイズ */ + char master; /* マスターファイルフラグ */ + char dm2[15]; /* ダミー2 */ + char mode[UMODEMAX][6]; /* ユーザ定義モード */ +}FHD; +#pragma option -a. // パック解除の指示 + +class CIndex +{ +private: + int m_IndexMax; // 確保中のインデックスの数 + int m_IndexCnt; // 現在のインデックスの数 + LPSTR pIndex; // インデックス領域のポインタ(16バイトインデックス) + BYTE *pMult; // マルチ情報のポインタ +public: + CIndex(); + ~CIndex(); + void AllocIndex(int n); + void ClearIndex(void); + void WriteIndex(LPCSTR pCall, int n); + void ReadIndex(LPSTR pCall, int n); + LPSTR PointIndex(int n); + void AddBlock(LPCSTR p, int len); + int ReadIndex(int handle, FHD *hp); + void MakeIndex(int handle, FHD *hp); + int WriteIndex(int handle, FHD *hp); + + +}; + +#define FINDMAX 32768 +class CLogFind +{ +public: + int m_FindCnt; + int m_FindCmp1Max; + int m_FindCmp2Max; + int m_FindStr1Max; + int m_FindStr2Max; + + int *pFindTbl; + AnsiString m_FindStr; +public: + CLogFind(); + ~CLogFind(); + inline int GetCount(void){return m_FindCnt;}; + inline void Clear(void){ + m_FindCnt = m_FindCmp1Max = m_FindCmp2Max = m_FindStr1Max = m_FindStr2Max = 0; + }; + int Add(int n); + void Ins(int n); + + inline void Write(int n){ + pFindTbl[m_FindCnt] = n; + m_FindCnt++; + }; + inline void SetText(LPCSTR p){ + if( p != m_FindStr.c_str() ){ + m_FindStr = p; + } + }; + inline LPCSTR GetText(void){ + return m_FindStr.c_str(); + }; + inline void ClearText(void){ + m_FindStr = ""; + }; +}; + +class CLogFile +{ +private: + int m_Open; // オープンフラグ + int m_EditFlag; // 編集フラグ + int m_Handle; // ファイルハンドル + CIndex m_Index; // 現在オープン中のインデックス + FHD m_fhd; // 現在オープン中のファイルヘッダ + AnsiString m_Name; // ログファイルの名前 + char m_modebuf[8]; +public: + AnsiString m_FileName; // ログファイルの名前(フルパス) + + int m_CurNo; + int m_CurChg; + SDMMLOG m_sd; + SDMMLOG m_bak; + SDMMLOG m_asd; + + CLogFind m_Find; // カレント検索データ + LOGSET m_LogSet; +private: + void SetHisRST(SDMMLOG *sp); + void InitHeader(void); + +public: + CLogFile(); + ~CLogFile(); + + void DoBackup(void); + + int Open(LPCSTR pName, BOOL fNew); + int Close(void); + + void ReadIniFile(LPCSTR pKey, TMemIniFile *pIniFile); + void WriteIniFile(LPCSTR pKey, TMemIniFile *pIniFile); + + void MakeIndex(void); + + inline IsEdit(void){return m_EditFlag;}; + void MakePathName(LPCSTR pName); + void MakeName(LPCSTR pName); + inline LPCSTR GetName(void){return m_Name.c_str();}; + + inline int GetCount(void){return m_fhd.size;}; + inline int IsOpen(void){return m_Open;}; + int GetData(SDMMLOG *sp, int n); + int PutData(SDMMLOG *sp, int n); + + LPCSTR GetDateString(SDMMLOG *sp, int sw); + inline LPCSTR GetDateString(SDMMLOG *sp){ return GetDateString(sp, m_LogSet.m_DateType); }; + LPCSTR GetTimeString(WORD d); + + + LPCSTR GetModeString(BYTE m); + void SetMode(SDMMLOG *sp, LPCSTR s); + + LPCSTR GetFreqString(BYTE b, short fq); + void SetFreq(SDMMLOG *sp, LPCSTR p); + LPCSTR GetOptStr(int n, SDMMLOG *sp); + void SetOptStr(int n, SDMMLOG *sp, LPCSTR pOpt); + + void CopyAF(void); + + void SortDate(int bb, int eb); + int FindSameBand(void); + int FindSameDate(void); + + void FindStrSet(CLogFind *fp, LPCSTR pCall); + int FindCmpSet(CLogFind *fp, LPCSTR pCall); + int FindClipSet(CLogFind *fp, LPCSTR pCall); + int FindSet(CLogFind *fp, LPCSTR pCall); + int Find(LPCSTR pCall, int b, int dir); + int IsAlready(LPCSTR pCall); + void DeleteAll(void); + void DeleteLast(void); + void Delete(int top, int end); + void Insert(int n, SDMMLOG *sp); + + void InitCur(void); + void SetLastPos(void); + + int ReadAscii(SDMMLOG *sp, LPSTR p); + +}; + +void JSTtoUTC(int &Year, int &Mon, int &Day, int &Hour); +void JSTtoUTC(SDMMLOG *sp); +void UTCtoJST(int &Year, int &Mon, int &Day, int &Hour); +void UTCtoJST(SDMMLOG *sp); +void UTCtoJST(SYSTEMTIME *tp); +void mBandToBand(SDMMLOG *sp, LPCSTR p); +LPCSTR FreqTomBand(SDMMLOG *sp); +int GetLMode(BYTE m); + +extern CLogFile Log; +extern const char MONN[]; +extern const char MONU[]; +#endif + diff --git a/LogList.cpp b/LogList.cpp new file mode 100644 index 0000000..0848984 --- /dev/null +++ b/LogList.cpp @@ -0,0 +1,1143 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "LogList.h" +#include "QsoDlg.h" +#include "TextEdit.h" +#include "LogConv.h" +#include "ConvDef.h" +#include "LogSet.h" +#include "country.h" +#include "Main.h" +#include "Hamlog5.h" +#include "TH5Len.h" +//--------------------------------------------------------------------- +#pragma resource "*.dfm" +//TLogListDlg *LogListDlg; +//--------------------------------------------------------------------- +__fastcall TLogListDlg::TLogListDlg(TComponent* AOwner) + : TForm(AOwner) +{ + FormStyle = ((TForm *)AOwner)->FormStyle; + Font->Name = ((TForm *)AOwner)->Font->Name; + Font->Charset = ((TForm *)AOwner)->Font->Charset; + if( MsgEng ){ + Grid->Font->Name = ((TForm *)AOwner)->Font->Name; + Grid->Font->Charset = ((TForm *)AOwner)->Font->Charset; + KFile->Caption = "File(&F)"; + KEdit->Caption = "Edit(&E)"; + KFind->Caption = "Find(&S)"; + KOpt->Caption = "Option(&O)"; + KHelp->Caption = "Help(&H)"; + + KOpen->Caption = "Open LogData File(&O)..."; + KFlush->Caption = "Save data now(&M)"; + KReIndex->Caption = "Make Index"; + KMTextRead->Caption = "Load MMLOG TextFile(&R)..."; + KMTextWrite->Caption = "Save selected range to MMLOG TextFile(&W)..."; + KImport->Caption = "Import"; + KImportText->Caption = "Text File..."; + KImportLog200->Caption = "Log200 File..."; + KImportHamlog->Caption = "Hamlog File..."; + KImportADIF->Caption = "ADIF File..."; + KExport->Caption = "Export selected range"; + KExportText->Caption = "Text File..."; + KExportADIF->Caption = "ADIF File..."; + KExportLog200->Caption = "Log200 File..."; + KExportHamlog->Caption = "Hamlog File..."; + KExportCabrillo->Caption = "Cabrillo file..."; + KExit->Caption = "Return to MMSSTV(&X)"; + + KDelCur->Caption = "Cut"; + KInsCur->Caption = "Insert"; + KSelAll->Caption = "Select All"; + KDelSel->Caption = "Delete selected range"; + KSortDate->Caption = "Sort(Date/Time)"; + + KTop->Caption = "Move Top"; + KBottom->Caption = "Move Last"; + KFindTop->Caption = "Search forward..."; + KFindBottom->Caption = "Search backward..."; + KFindConT->Caption = "Search forward again"; + KFindConB->Caption = "Search backward again"; + + KLogOpt->Caption = "Setup Logging..."; + } + if( !JanHelp.IsEmpty() ) KHlpLog->Caption = "MMSSTV Log"; + + int CX = ::GetSystemMetrics(SM_CXFULLSCREEN); + int CY = ::GetSystemMetrics(SM_CYFULLSCREEN); + if( (CX < Width)||(CY < Height) ){ + Top = 0; + Left = 0; + Width = CX; + Height = CY; + } + m_DateWidth = Grid->ColWidths[0]; + FormCenter(this, CX, CY); + if( Owner != NULL ){ + WindowState = ((TForm *)Owner)->WindowState; + } + SetTimeZone(); +} +//--------------------------------------------------------------------------- +void __fastcall TLogListDlg::SetTimeZone(void) +{ + switch(Log.m_LogSet.m_TimeZone){ + case 'I': + if( lcid == LANG_KOREAN ){ + m_TimeZone = "KST"; + } + else { + m_TimeZone = "JST"; + } + break; + default: + m_TimeZone = "UTC"; + break; + } + if(Log.m_LogSet.m_DateType & 1){ + Grid->ColWidths[0] = (m_DateWidth * 10) / 8; + } + else { + Grid->ColWidths[0] = m_DateWidth; + } +} +//--------------------------------------------------------------------------- +// アイドル処理 +void __fastcall TLogListDlg::OnIdle(TObject *Sender, bool &Done) +{ + UpdateMenu(); +} +//--------------------------------------------------------------------------- +void __fastcall TLogListDlg::UpdateLogCount(int sw) +{ + Grid->RowCount = Log.GetCount() + 2; + + if( sw ){ + Grid->Row = Log.GetCount() + 1; + AdjustTopRow(); + char bf[256]; + if( Log.IsOpen() ){ + sprintf(bf, MsgEng ? "%s - [%u QSO data(s)]" : "%s - [%u件のデータがあります]", Log.m_FileName.c_str(), Log.GetCount()); + } + else { + sprintf(bf, "%s is not opened.", Log.m_FileName.c_str()); + } + Caption = bf; + } + Grid->Col = 0; + Grid->Invalidate(); +} + +void __fastcall TLogListDlg::AdjustTopRow(void) +{ + int GridLine = Grid->GridHeight/Grid->RowHeights[1] - 1; + int Top = Grid->Row - GridLine + 1; + if( Top < 1 ) Top = 1; + Grid->TopRow = Top; + Grid->Invalidate(); +} + +void __fastcall TLogListDlg::Execute(void) +{ + if( !Log.IsOpen() ){ + Log.Open(NULL, TRUE); + } + Application->OnIdle = OnIdle; + UpdateLogCount(1); + ShowModal(); + Application->OnIdle = NULL; +} +//--------------------------------------------------------------------------- +void __fastcall TLogListDlg::GridDrawCell(TObject *Sender, int Col, + int Row, TRect &Rect, TGridDrawState State) +{ + + char bf[256]; + SDMMLOG sd; + + Grid->Canvas->FillRect(Rect); + int X = Rect.Left + 4; + int Y = Rect.Top + 2; + + if( Row ){ + Row--; + bf[0] = 0; + if( Row < Log.GetCount() ){ + Log.GetData(&sd, Row); + } + else { + memset(&sd, 0, sizeof(SDMMLOG)); + } + if( Log.m_LogSet.m_TimeZone != 'I' ){ + JSTtoUTC(&sd); + } + switch(Col){ + case 0: // Date + MultProc(); + strcpy(bf, Log.GetDateString(&sd)); + break; + case 1: // Time + strcpy(bf, Log.GetTimeString(sd.btime)); + break; + case 2: // Call + strcpy(bf, sd.call); + break; + case 3: // M + bf[0] = sd.cq; + bf[1] = 0; + break; + case 4: // HisRST + strcpy(bf, sd.ur); + break; + case 5: // MyRST + strcpy(bf, sd.my); + break; + case 6: // Band + strcpy(bf, Log.GetFreqString(sd.band, sd.fq)); + break; + case 7: // Mode + strcpy(bf, Log.GetModeString(sd.mode)); + break; + case 8: // Pow + strcpy(bf, sd.pow); + break; + case 9: // Name + strcpy(bf, sd.name); + break; + case 10: // QTH + strcpy(bf, sd.qth); + break; + case 11: // S + bf[0] = sd.send; + bf[1] = 0; + break; + case 12: // R + bf[0] = sd.recv; + bf[1] = 0; + break; + case 13: // REM + strcpy(bf, sd.rem); + break; + case 14: // QSL + strcpy(bf, sd.qsl); + break; + case 15: // etime; + strcpy(bf, Log.GetTimeString(sd.etime)); + break; + case 16: // Env + if( sd.env ) sprintf(bf, "%u", sd.env); + break; + case 17: // Opt1 + strcpy(bf, sd.opt1); + break; + case 18: // Opt2 + strcpy(bf, sd.opt2); + break; + case 19: // Usr1 + strcpy(bf, Log.GetOptStr(2, &sd)); + break; + case 20: // Usr2 + strcpy(bf, Log.GetOptStr(3, &sd)); + break; + } + Grid->Canvas->TextRect(Rect, X, Y, bf); + } + else { // タイトル + LPCSTR _tt[]={ + "Date","JST","Call","M", "His","My","Band","Mode","Pow","Name","QTH","S","R", + "Note","QSL", "End", "Env", "Opt1", "Opt2", "Usr1", "Usr2", + }; + if( Col == 1 ){ + Grid->Canvas->TextRect(Rect, X, Y, m_TimeZone.c_str()); + } + else { + Grid->Canvas->TextRect(Rect, X, Y, _tt[Col]); + } + } +} +//--------------------------------------------------------------------------- +// リターンキーの処理 +void __fastcall TLogListDlg::GridKeyPress(TObject *Sender, char &Key) +{ + if( Key == 0x0d ){ + GridDblClick(NULL); + Key = 0; + } +} +//--------------------------------------------------------------------------- +void __fastcall TLogListDlg::UpdateMenu(void) +{ + int f = Log.IsOpen(); + KFlush->Enabled = f && Log.IsEdit(); + KDelCur->Enabled = f && (Grid->Row <= Log.GetCount()) && (Grid->Row >= 1); + KInsCur->Enabled = f && (Grid->Row <= Log.GetCount()) && (Grid->Row >= 1); + KDelSel->Enabled = f && (Grid->Selection.Top < Grid->Selection.Bottom); + KTop->Enabled = f && Log.GetCount(); + KBottom->Enabled = f && Log.GetCount(); + KFindTop->Enabled = f && Log.GetCount(); + KFindBottom->Enabled = f && Log.GetCount(); + KFindConT->Enabled = f && Log.GetCount(); + KFindConB->Enabled = f && Log.GetCount(); + KSortDate->Enabled = f && Log.GetCount() && (Grid->Selection.Top < Grid->Selection.Bottom); + KSelAll->Enabled = f && Log.GetCount(); + KMTextRead->Enabled = f; + KMTextWrite->Enabled = f && Log.GetCount() && (Grid->Selection.Top <= Log.GetCount()); + KExport->Enabled = f && Log.GetCount() && (Grid->Selection.Top <= Log.GetCount()); + KReIndex->Enabled = f; +} +//--------------------------------------------------------------------------- +void __fastcall TLogListDlg::KOpenClick(TObject *Sender) +{ +#if 1 + Mmsstv->KLogOpenClick(NULL); + UpdateLogCount(1); +#else + OpenDialog->Options >> ofCreatePrompt; + OpenDialog->Options >> ofFileMustExist; + if(MsgEng){ + OpenDialog->Title = "Open LogData File"; + OpenDialog->Filter = "MMLOG Data File(*.mdt)|*.mdt|"; + } + else { + OpenDialog->Title = "ログファイルのオープン"; + OpenDialog->Filter = "MMLOG Data File(*.mdt)|*.mdt|"; + } + OpenDialog->FileName = ""; + OpenDialog->DefaultExt = "mdt"; + OpenDialog->InitialDir = MMLogDir; + NormalWindow(this); + if( OpenDialog->Execute() == TRUE ){ + Log.Close(); + Log.MakeName(OpenDialog->FileName.c_str()); + Log.Open(NULL, TRUE); + UpdateLogCount(1); + } + TopWindow(this); +#endif +} +//--------------------------------------------------------------------------- +void __fastcall TLogListDlg::KFlushClick(TObject *Sender) +{ + Log.Close(); + Log.Open(NULL, TRUE); + UpdateLogCount(0); +} +//--------------------------------------------------------------------------- +void __fastcall TLogListDlg::KDelCurClick(TObject *Sender) +{ + int n = Grid->Row - 1; + SDMMLOG sd; + Log.GetData(&sd, n); + memcpy(&Log.m_bak, &sd, sizeof(SDMMLOG)); + Log.Delete(n, n); + UpdateLogCount(0); +} +//--------------------------------------------------------------------------- +void __fastcall TLogListDlg::KInsCurClick(TObject *Sender) +{ + int n = Grid->Row - 1; + Log.Insert(n, &Log.m_bak); + UpdateLogCount(0); +} +//--------------------------------------------------------------------------- +void __fastcall TLogListDlg::KDelSelClick(TObject *Sender) +{ + if( YesNoMB( MsgEng ? "Delete Selection.(will not be able to restore) Are you sure?":"現在選択されている範囲を削除します.削除した内容は復元できません\r\n\r\nよろしおまっか?") == IDYES ){ + int top = Grid->Selection.Top - 1; + int end = Grid->Selection.Bottom - 1; + Log.Delete(top, end); + UpdateLogCount(0); + Grid->Row = top + 1; + } +} +//--------------------------------------------------------------------------- +void __fastcall TLogListDlg::KExitClick(TObject *Sender) +{ + ModalResult = mrOk; +} +//--------------------------------------------------------------------------- +void __fastcall TLogListDlg::KFindTopClick(TObject *Sender) +{ + if( m_FindCall.IsEmpty() || (Sender == KFindTop) ){ + AnsiString as = m_FindCall; + if( InputMB(NULL, MsgEng ? "Callsign":"検索するコールサイン", as) == FALSE ) return; + jstrupr(as.c_str()); + m_FindCall = as; + } + int n = Log.Find(m_FindCall.c_str(), Grid->Row, 0); + if( n >= 0 ){ + Grid->Row = n + 1; + } + else { + WarningMB(MsgEng ? "'%s' was not found" : "'%s'は見つかりませんでした.", m_FindCall.c_str()); + } +} +//--------------------------------------------------------------------------- +void __fastcall TLogListDlg::KFindBottomClick(TObject *Sender) +{ + if( m_FindCall.IsEmpty() || (Sender == KFindBottom) ){ + AnsiString as = m_FindCall; + if( InputMB(NULL, MsgEng ? "Callsign":"検索するコールサイン", as) == FALSE ) return; + jstrupr(as.c_str()); + m_FindCall = as; + } + int n = Log.Find(m_FindCall.c_str(), Grid->Row - 2, 1); + if( n >= 0 ){ + Grid->Row = n + 1; + } + else { + WarningMB(MsgEng ? "'%s' was not found" : "'%s'は見つかりませんでした.", m_FindCall.c_str()); + } +} +//--------------------------------------------------------------------------- +void __fastcall TLogListDlg::KTopClick(TObject *Sender) +{ + Grid->Row = 1; + Grid->TopRow = 1; +} +//--------------------------------------------------------------------------- +void __fastcall TLogListDlg::KBottomClick(TObject *Sender) +{ + Grid->Row = Log.GetCount() + 1; + AdjustTopRow(); +} +//--------------------------------------------------------------------------- +void __fastcall TLogListDlg::KSortDateClick(TObject *Sender) +{ + if( YesNoMB( MsgEng ? "It may take substantial time. Are you sure?":"この処理はメチャンコ時間がかかるかも知れません.\r\n\r\nよろしおまっか?" ) == IDYES ){ + int top = Grid->Selection.Top - 1; + int end = Grid->Selection.Bottom - 1; + if( top == end ){ + top = 0; + end = Log.GetCount() - 1; + } + Log.SortDate(top, end); + Grid->Invalidate(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TLogListDlg::GridDblClick(TObject *Sender) +{ + int n = Grid->Row - 1; + if( (n >= 0) && (n < Log.GetCount()) ){ + TQSODlgBox *pBox = new TQSODlgBox(this); + SDMMLOG sd; + Log.GetData(&sd, n); + CLogFind Find; + + Log.FindSet(&Find, sd.call); + + pBox->Execute(&Find, &sd, n); + Grid->Invalidate(); + delete pBox; + } +} +//--------------------------------------------------------------------------- +// MMLOGテキストファイルのロード +void __fastcall TLogListDlg::KMTextReadClick(TObject *Sender) +{ + OpenDialog->Options >> ofCreatePrompt; + OpenDialog->Options << ofFileMustExist; + if( MsgEng ){ + OpenDialog->Title = "Load MMLOG Text file"; + OpenDialog->Filter = "MMLOG Text Files(*.log)|*.log|"; + } + else { + OpenDialog->Title = "MMLOGテキストファイルのロード"; + OpenDialog->Filter = "MMLOGテキストファイル(*.log)|*.log|"; + } + OpenDialog->FileName = ""; + OpenDialog->DefaultExt = "log"; + OpenDialog->InitialDir = MMLogDir; + NormalWindow(this); + if( OpenDialog->Execute() == TRUE ){ + LoadMmlogText(AnsiString(OpenDialog->FileName).c_str()); //JA7UDE 0428 + } + TopWindow(this); +} +//--------------------------------------------------------------------------- +void __fastcall TLogListDlg::KMTextWriteClick(TObject *Sender) +{ + SaveDialog->Options << ofOverwritePrompt; + if( MsgEng ){ + SaveDialog->Title = "Save MMLOG Text File"; + SaveDialog->Filter = "MMLOG Text Files(*.log)|*.log|"; + } + else { + SaveDialog->Title = "MMLOGテキストファイルの作成"; + SaveDialog->Filter = "MMLOGテキストファイル(*.log)|*.log|"; + } + char bf[256]; + strcpy(bf, Log.GetName()); + SetEXT(bf, ".log"); + SaveDialog->FileName = bf; + SaveDialog->DefaultExt = "log"; + SaveDialog->InitialDir = MMLogDir; + NormalWindow(this); + if( SaveDialog->Execute() == TRUE ){ + SaveMmlogText(AnsiString(SaveDialog->FileName).c_str()); //JA7UDE 0428 + } + TopWindow(this); +} +//--------------------------------------------------------------------------- +int __fastcall TLogListDlg::SureRead(void) +{ + int r; + if( MsgEng ){ + r = YesNoCancelMB("MMSSTV has QSO data(s) already. Add QSO data from file?\r\n\r\n\tAdded to the end\r\n\tOverwrite\r\n\t(All the current data are deleted, and replaced by the read data)\r\n\tAbort this function"); + } + else { + r = YesNoCancelMB("現在MMSSTVにログデータが存在します. 追加読みこみしますか?\r\n\r\n<はい>\t現在のログデータの最後に読み込んだデータが追加される.\r\n<いいえ>\t現在のログデータは全て削除され読み込んだデータに置き換わる.\r\n<キャンセル>\t処理中止"); + } + switch(r){ + case IDCANCEL: + return 0; + case IDNO: + if( MsgEng ){ + r = OkCancelMB("Delete All QSO data(s)...(will not be able to restore) Are you sure?"); + } + else { + r = OkCancelMB("現在MMSSTVが保持しているログデータを全て失います.\r\n\r\nほんまにええでっか?"); + } + switch(r){ + case IDOK: + Log.DeleteAll(); + break; + case IDCANCEL: + return 0; + } + break; + default: + break; + } + return 1; +} +//--------------------------------------------------------------------------- +void __fastcall TLogListDlg::LoadMmlogText(LPCSTR pName) +{ + char bf[1024]; + + if( Log.GetCount() ){ + if( !SureRead() ) return; + } + FILE *fp = fopen(pName, "rt"); + if( fp != NULL ){ + int r = IDNO; + if( MsgEng ){ + r = YesNoMB("This function exists for compatibility with old software which handle JST.\r\n\r\nAre recorded data UTC?"); + } + CWaitCursor w; + SDMMLOG sd; + while(!feof(fp)){ + if( fgets(bf, 1023, fp) != NULL ){ + ClipLF(bf); + if( bf[0] ){ + if( Log.ReadAscii(&sd, bf) == TRUE ){ + if( r == IDYES ) UTCtoJST(&sd); + Log.PutData(&sd, Log.GetCount()); + } + } + } + } + fclose(fp); + } + else { + ErrorMB(MsgEng ? "Can't open '%s'" : "'%s'が見つかりません.", pName); + } + UpdateLogCount(1); +} +//--------------------------------------------------------------------------- +void __fastcall TLogListDlg::SaveMmlogText(LPCSTR pName) +{ + FILE *fp = fopen(pName, "wt"); + if( fp != NULL ){ + int r = IDNO; + if( MsgEng ){ + r = YesNoMB("This function exists for compatibility with old software which handle JST.\r\n\r\nDo you want UTC?"); + } + SDMMLOG sd; + int b = Grid->Selection.Top - 1; + int e = Grid->Selection.Bottom - 1; + if( e >= Log.GetCount() ) e--; + int i; + CWaitCursor w; + for( i = b; i <= e; i++ ){ + Log.GetData(&sd, i); + if( r == IDYES ) JSTtoUTC(&sd); + fprintf(fp, "\042%s\042,\042%s.%02u\042,\042%s\042,\042%s\042,\042%s\042,\042%s\042,", + Log.GetDateString(&sd, 0), + Log.GetTimeString(sd.btime), (sd.btime % 30 * 2), + sd.call, sd.ur, sd.my, + Log.GetFreqString(sd.band, sd.fq) + ); + + fprintf(fp, "\042%s\042,\042%s\042,\042%s\042,\042%s\042,\042%s\042,\042%s\042,", + Log.GetModeString(sd.mode), + sd.pow, sd.name, sd.qth, sd.rem, sd.qsl + ); + fprintf(fp, "\042%s\042,\042%.1s\042,\042%.1s\042,\042%.1s\042,\042%u\042,", + Log.GetTimeString(sd.etime), + &sd.send, &sd.recv, &sd.cq, sd.env + ); + fprintf(fp, "\042%s\042,\042%s\042,", sd.opt1, sd.opt2 ); + fprintf(fp, "\042%s\042,", Log.GetOptStr(2, &sd)); + fprintf(fp, "\042%s\042\n", Log.GetOptStr(3, &sd)); + if( ferror(fp) ) break; + } + if( fclose(fp) ){ + ErrorMB( MsgEng ? "Can't save to '%s'" : "'%s'が正しく作成できませんでした.", pName); + } + } + else { + ErrorMB(MsgEng ? "Can't save to '%s'" : "'%s'が作成できません.", pName); + } +} +//--------------------------------------------------------------------------- +void __fastcall TLogListDlg::KSelAllClick(TObject *Sender) +{ + TGridRect gRect; + gRect.Top = 1; + gRect.Bottom = Grid->RowCount - 1; + gRect.Left = 0; + gRect.Right = 20; + + Grid->Selection = gRect; +} +//--------------------------------------------------------------------------- +void __fastcall TLogListDlg::KHlpLogClick(TObject *Sender) +{ + ShowHelp(this, MsgEng ? "EMSTVLOG.TXT":"MSTVLOG.TXT"); +} +//--------------------------------------------------------------------------- +void __fastcall TLogListDlg::KReIndexClick(TObject *Sender) +{ + Log.MakeIndex(); +} +//--------------------------------------------------------------------------- +int __fastcall TLogListDlg::LoadText(LPCSTR pName) +{ + TConvDefDlg *pBox = new TConvDefDlg(this); + int r = pBox->Execute(LogText.m_rConv, LogText.m_Delm, LogText.m_UTC, LogText.m_Double, pName); + delete pBox; + if( r == FALSE ) return FALSE; + + if( Log.GetCount() ){ + if( !SureRead() ) return FALSE; + } + + if( LogText.Open(pName) ){ + SDMMLOG sd; + CWaitCursor w; + while(LogText.Read(&sd)==TRUE){ + Log.PutData(&sd, Log.GetCount()); + } + LogText.Close(); + } + else { + UpdateLogCount(1); + return FALSE; + } + UpdateLogCount(1); + return TRUE; +} +//--------------------------------------------------------------------------- +int __fastcall TLogListDlg::SaveText(LPCSTR pName) +{ + int b = Grid->Selection.Top - 1; + int e = Grid->Selection.Bottom - 1; + if( e >= Log.GetCount() ) e--; + + TConvDefDlg *pBox = new TConvDefDlg(this); + int r = pBox->Execute(LogText.m_tConv, LogText.m_Delm, LogText.m_UTC, LogText.m_Double, b, e); + delete pBox; + if( r == FALSE ) return FALSE; + if( LogText.Create(pName) ){ + SDMMLOG sd; + int i; + CWaitCursor w; + for( i = b; i <= e; i++ ){ + Log.GetData(&sd, i); + if( LogText.Write(&sd) == FALSE ) break; + } + LogText.Close(); + } + return TRUE; +} +//--------------------------------------------------------------------------- +void __fastcall TLogListDlg::KExportTextClick(TObject *Sender) +{ + SaveDialog->Options << ofOverwritePrompt; + if( MsgEng ){ + SaveDialog->Title = "Save Text File"; + SaveDialog->Filter = "Text Files(*.csv;*.txt)|*.csv;*.txt|"; + } + else { + SaveDialog->Title = "テキストファイルの作成"; + SaveDialog->Filter = "テキストファイル(*.csv;*.txt)|*.csv;*.txt|"; + } + char bf[256]; + strcpy(bf, Log.GetName()); + SetEXT(bf, ".csv"); + SaveDialog->FileName = bf; + SaveDialog->DefaultExt = "csv"; + SaveDialog->InitialDir = ExtLogDir; + NormalWindow(this); + if( SaveDialog->Execute() == TRUE ){ + SaveText(AnsiString(SaveDialog->FileName).c_str()); //JA7UDE 0428 + SetDirName(ExtLogDir, AnsiString(SaveDialog->FileName).c_str()); //JA7UDE 0428 + } + TopWindow(this); +} +//--------------------------------------------------------------------------- +void __fastcall TLogListDlg::KImportTextClick(TObject *Sender) +{ + OpenDialog->Options >> ofCreatePrompt; + OpenDialog->Options >> ofFileMustExist; + if( MsgEng ){ + OpenDialog->Title = "Load Text File"; + OpenDialog->Filter = "Text File(*.csv;*.txt)|*.csv;*.txt|"; + } + else { + OpenDialog->Title = "テキストファイルのロード"; + OpenDialog->Filter = "テキストファイル(*.csv;*.txt)|*.csv;*.txt|"; + } + OpenDialog->FileName = ""; + OpenDialog->DefaultExt = "csv"; + OpenDialog->InitialDir = ExtLogDir; + NormalWindow(this); + if( OpenDialog->Execute() == TRUE ){ + LoadText(AnsiString(OpenDialog->FileName).c_str()); //ja7ude 0428 + SetDirName(ExtLogDir, AnsiString(OpenDialog->FileName).c_str()); //ja7ude 0428 + } + TopWindow(this); +} +//--------------------------------------------------------------------------- +int __fastcall TLogListDlg::LoadLog200(LPCSTR pName) +{ + if( Log.GetCount() ){ + if( !SureRead() ) return FALSE; + } + + CLog200 log200; + if( log200.Open(pName) ){ + SDMMLOG sd; + CWaitCursor w; + while(log200.Read(&sd)==TRUE){ + Log.PutData(&sd, Log.GetCount()); + } + log200.Close(); + } + else { + UpdateLogCount(1); + return FALSE; + } + UpdateLogCount(1); + return TRUE; +} +//--------------------------------------------------------------------------- +int __fastcall TLogListDlg::SaveLog200(LPCSTR pName) +{ + int b = Grid->Selection.Top - 1; + int e = Grid->Selection.Bottom - 1; + if( e >= Log.GetCount() ) e--; + + CLog200 log200; + if( log200.Create(pName) ){ + SDMMLOG sd; + int i; + CWaitCursor w; + for( i = b; i <= e; i++ ){ + Log.GetData(&sd, i); + if( log200.Write(&sd) == FALSE ) break; + } + log200.Close(); + } + return TRUE; +} +//--------------------------------------------------------------------------- +void __fastcall TLogListDlg::KExportLog200Click(TObject *Sender) +{ + SaveDialog->Options << ofOverwritePrompt; + if( MsgEng ){ + SaveDialog->Title = "Save LOG200 Data file"; + SaveDialog->Filter = "LOG200 Data File(*.l2)|*.l2|"; + } + else { + SaveDialog->Title = "LOG200データファイルの作成"; + SaveDialog->Filter = "LOG200データファイル(*.l2)|*.l2|"; + } + char bf[256]; + strcpy(bf, Log.GetName()); + SetEXT(bf, ".l2"); + SaveDialog->FileName = bf; + SaveDialog->DefaultExt = "l2"; + SaveDialog->InitialDir = ExtLogDir; + NormalWindow(this); + if( SaveDialog->Execute() == TRUE ){ + SaveLog200(AnsiString(SaveDialog->FileName).c_str()); //ja7ude 0428 + SetDirName(ExtLogDir, AnsiString(SaveDialog->FileName).c_str()); //ja7ude 0428 + } + TopWindow(this); +} +//--------------------------------------------------------------------------- +void __fastcall TLogListDlg::KImportLog200Click(TObject *Sender) +{ + OpenDialog->Options >> ofCreatePrompt; + OpenDialog->Options >> ofFileMustExist; + if( MsgEng ){ + OpenDialog->Title = "Load LOG200 Data File"; + OpenDialog->Filter = "LOG200 Data File(*.l2)|*.l2|"; + } + else { + OpenDialog->Title = "LOG200データファイルのロード"; + OpenDialog->Filter = "LOG200データファイル(*.l2)|*.l2|"; + } + OpenDialog->FileName = ""; + OpenDialog->DefaultExt = "l2"; + OpenDialog->InitialDir = ExtLogDir; + NormalWindow(this); + if( OpenDialog->Execute() == TRUE ){ + LoadLog200(AnsiString(OpenDialog->FileName).c_str()); //ja7ude 0428 + SetDirName(ExtLogDir, AnsiString(OpenDialog->FileName).c_str()); //ja7ude 0428 + } + TopWindow(this); +} +//--------------------------------------------------------------------------- +int __fastcall TLogListDlg::LoadHamLog(LPCSTR pName) +{ + if( Log.GetCount() ){ + if( !SureRead() ) return FALSE; + } + + CHamLog HamLog; + if( HamLog.Open(pName) ){ + SDMMLOG sd; + CWaitCursor w; + while(HamLog.Read(&sd)==TRUE){ + Log.PutData(&sd, Log.GetCount()); + } + HamLog.Close(); + } + else { + UpdateLogCount(1); + return FALSE; + } + UpdateLogCount(1); + return TRUE; +} +//--------------------------------------------------------------------------- +int __fastcall TLogListDlg::LoadHamLog5(LPCSTR pName) +{ + if( Log.GetCount() ){ + if( !SureRead() ) return FALSE; + } + + CHamlog5 HamLog; + if( HamLog.Open(pName, TRUE) ){ + SDMMLOG sd; + CWaitCursor w; + DWORD Pos; + for( Pos = 0; Pos < HamLog.GetRCount(); Pos++ ){ + if( HamLog.Seek(Pos) ){ + HamLog.DecodeData(&sd); + Log.PutData(&sd, Log.GetCount()); + } + } + HamLog.Close(); + } + else { + UpdateLogCount(1); + return FALSE; + } + UpdateLogCount(1); + return TRUE; +} +//--------------------------------------------------------------------------- +int __fastcall TLogListDlg::SaveHamLog(LPCSTR pName) +{ + int b = Grid->Selection.Top - 1; + int e = Grid->Selection.Bottom - 1; + if( e >= Log.GetCount() ) e--; + + CHamLog HamLog; + if( HamLog.Create(pName) ){ + SDMMLOG sd; + int i; + CWaitCursor w; + for( i = b; i <= e; i++ ){ + Log.GetData(&sd, i); + if( HamLog.Write(&sd) == FALSE ) break; + } + HamLog.Close(); + } + return TRUE; +} +//--------------------------------------------------------------------------- +int __fastcall TLogListDlg::SaveHamLog5(LPCSTR pName) +{ + int b = Grid->Selection.Top - 1; + int e = Grid->Selection.Bottom - 1; + if( e >= Log.GetCount() ) e--; + + + char master[256]; + SetDirName(master, pName); + strcat(master, "HAMLOG.HDB"); + CHamlog5 HamLog; + if( HamLog.Open(master, FALSE) ){ // フィールド情報を読み込む + HamLog.Close(); + } + else { // フィールド情報を問い合わせ + TTH5LenDlg *pBox = new TTH5LenDlg(this); + if( !pBox->Execute() ){ + return FALSE; + } + } + + if( HamLog.Create(pName) ){ + SDMMLOG sd; + int i; + int n = 0; + CWaitCursor w; + for( i = b; i <= e; i++, n++ ){ + Log.GetData(&sd, i); + HamLog.Seek(n); + HamLog.EncodeData(&sd); + if( HamLog.Update() == FALSE ) break; + } + HamLog.Close(); + } + return TRUE; +} +//--------------------------------------------------------------------------- +void __fastcall TLogListDlg::KImportHamlogClick(TObject *Sender) +{ + OpenDialog->Options >> ofCreatePrompt; + OpenDialog->Options >> ofFileMustExist; + if( MsgEng ){ + OpenDialog->Title = "Load HamLog Data File"; + OpenDialog->Filter = "HamLog Data File(*.hdb;*.dbs)|*.hdb;*.dbs|"; + } + else { + OpenDialog->Title = "HamLogデータファイルのロード"; + OpenDialog->Filter = "HamLogデータファイル(*.hdb;*.dbs)|*.hdb;*.dbs|"; + } + OpenDialog->FileName = ""; + OpenDialog->DefaultExt = "hdb"; + OpenDialog->InitialDir = ExtLogDir; + NormalWindow(this); + if( OpenDialog->Execute() == TRUE ){ + LPCSTR pName = AnsiString(OpenDialog->FileName).c_str(); //ja7ude 0428 + if( !strcmpi(GetEXT(pName), "HDB") ){ + LoadHamLog5(pName); + } + else { + LoadHamLog(pName); + } + SetDirName(ExtLogDir, pName); + } + TopWindow(this); +} +//--------------------------------------------------------------------------- +void __fastcall TLogListDlg::KExportHamlogClick(TObject *Sender) +{ + SaveDialog->Options << ofOverwritePrompt; + if( MsgEng ){ + SaveDialog->Title = "Save HAMLOG Data File"; + SaveDialog->Filter = "HAMLOG (Ver5) Data File(*.hdb)|*.hdb|HAMLOG Data File(*.dbs)|*.dbs|"; + } + else { + SaveDialog->Title = "HAMLOGデータファイルの作成"; + SaveDialog->Filter = "HAMLOG (Ver5) データファイル(*.hdb)|*.hdb|HAMLOGデータファイル(*.dbs)|*.dbs|"; + } + char bf[256]; + strcpy(bf, Log.GetName()); + SetEXT(bf, ".hdb"); + SaveDialog->FileName = bf; + SaveDialog->DefaultExt = "hdb"; + SaveDialog->InitialDir = ExtLogDir; + NormalWindow(this); + if( SaveDialog->Execute() == TRUE ){ + LPCSTR pName = AnsiString(SaveDialog->FileName).c_str(); //ja7ude 0428 + if( !strcmpi(GetEXT(pName), "HDB") ){ + SaveHamLog5(pName); + } + else { + SaveHamLog(pName); + } + SetDirName(ExtLogDir, pName); + } + TopWindow(this); +} +//--------------------------------------------------------------------------- +void __fastcall TLogListDlg::KLogOptClick(TObject *Sender) +{ + TLogSetDlg *pBox = new TLogSetDlg(this); + pBox->Execute(); + delete pBox; + SetTimeZone(); + Grid->Invalidate(); +} +//--------------------------------------------------------------------------- +int __fastcall TLogListDlg::SaveADIF(LPCSTR pName) +{ + int b = Grid->Selection.Top - 1; + int e = Grid->Selection.Bottom - 1; + if( e >= Log.GetCount() ) e--; + + CLogADIF logADIF; + if( logADIF.Create(pName) ){ + SDMMLOG sd; + int i; + CWaitCursor w; + for( i = b; i <= e; i++ ){ + Log.GetData(&sd, i); + if( logADIF.Write(&sd) == FALSE ) break; + } + logADIF.Close(); + } + return TRUE; +} +//--------------------------------------------------------------------------- +int __fastcall TLogListDlg::LoadADIF(LPCSTR pName) +{ + if( Log.GetCount() ){ + if( !SureRead() ) return FALSE; + } + + CLogADIF logADIF; + if( logADIF.Open(pName) ){ + SDMMLOG sd; + memset(&sd, 0, sizeof(sd)); + CWaitCursor w; + while(logADIF.Read(&sd)==TRUE){ + Log.PutData(&sd, Log.GetCount()); + memset(&sd, 0, sizeof(sd)); + } + logADIF.Close(); + } + else { + UpdateLogCount(1); + return FALSE; + } + UpdateLogCount(1); + return TRUE; +} +//--------------------------------------------------------------------------- +void __fastcall TLogListDlg::KExportADIFClick(TObject *Sender) +{ + SaveDialog->Options << ofOverwritePrompt; + if( MsgEng ){ + SaveDialog->Title = "Save ADIF File"; + SaveDialog->Filter = "ADIF Files(*.adi)|*.adi|"; + } + else { + SaveDialog->Title = "ADIF ファイルの作成"; + SaveDialog->Filter = "ADIF ファイル(*.adi)|*.adi|"; + } + char bf[256]; + strcpy(bf, Log.GetName()); + SetEXT(bf, ".adi"); + SaveDialog->FileName = bf; + SaveDialog->DefaultExt = "adi"; + SaveDialog->InitialDir = ExtLogDir; + NormalWindow(this); + if( SaveDialog->Execute() == TRUE ){ + SaveADIF(AnsiString(SaveDialog->FileName).c_str()); //ja7ude 0428 + SetDirName(ExtLogDir, AnsiString(SaveDialog->FileName).c_str()); //ja7ude 0428 + } + TopWindow(this); +} +//--------------------------------------------------------------------------- +void __fastcall TLogListDlg::KImportADIFClick(TObject *Sender) +{ + OpenDialog->Options >> ofCreatePrompt; + OpenDialog->Options >> ofFileMustExist; + if( MsgEng ){ + OpenDialog->Title = "Load ADIF File"; + OpenDialog->Filter = "ADIF Files(*.adi;*.txt)|*.adi;*.txt|"; + } + else { + OpenDialog->Title = "ADIF ファイルのロード"; + OpenDialog->Filter = "ADIF ファイル(*.adi;*.txt)|*.adi;*.txt|"; + } + OpenDialog->FileName = ""; + OpenDialog->DefaultExt = "adi"; + OpenDialog->InitialDir = ExtLogDir; + NormalWindow(this); + if( OpenDialog->Execute() == TRUE ){ + LoadADIF(AnsiString(OpenDialog->FileName).c_str()); + SetDirName(ExtLogDir, AnsiString(OpenDialog->FileName).c_str()); + } + TopWindow(this); +} +//--------------------------------------------------------------------------- +int __fastcall TLogListDlg::SaveCabrillo(LPCSTR pName) +{ + int b = Grid->Selection.Top - 1; + int e = Grid->Selection.Bottom - 1; + if( e >= Log.GetCount() ) e--; + + CLogCabrillo logCabrillo; + if( logCabrillo.Create(pName) ){ + SDMMLOG sd; + int i; + CWaitCursor w; + for( i = b; i <= e; i++ ){ + Log.GetData(&sd, i); + if( logCabrillo.Write(&sd) == FALSE ) break; + } + logCabrillo.Close(); + } + return TRUE; +} +//--------------------------------------------------------------------------- +void __fastcall TLogListDlg::KExportCabrilloClick(TObject *Sender) +{ + SaveDialog->Options << ofOverwritePrompt; + if( MsgEng ){ + SaveDialog->Title = "Save Cabrillo File"; + SaveDialog->Filter = "Cabrillo Files(*.txt)|*.txt|"; + } + else { + SaveDialog->Title = "Cabrillo ファイルの作成"; + SaveDialog->Filter = "Cabrillo ファイル(*.txt)|*.txt|"; + } + char bf[256]; + strcpy(bf, Log.GetName()); + SetEXT(bf, ".txt"); + SaveDialog->FileName = bf; + SaveDialog->DefaultExt = "txt"; + SaveDialog->InitialDir = ExtLogDir; + NormalWindow(this); + if( SaveDialog->Execute() == TRUE ){ + SaveCabrillo(AnsiString(SaveDialog->FileName).c_str()); //ja7ude 0428 + SetDirName(ExtLogDir, AnsiString(SaveDialog->FileName).c_str()); //ja7ude 0428 + } + TopWindow(this); +} +//--------------------------------------------------------------------------- + + diff --git a/LogList.dfm b/LogList.dfm new file mode 100644 index 0000000..9f105b7 Binary files /dev/null and b/LogList.dfm differ diff --git a/LogList.h b/LogList.h new file mode 100644 index 0000000..cb9f593 --- /dev/null +++ b/LogList.h @@ -0,0 +1,161 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//---------------------------------------------------------------------------- +#ifndef LogListH +#define LogListH +//---------------------------------------------------------------------------- +/* JA7UDE 0428 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +*/ +//---------------------------------------------------------------------------- +#include "LogFile.h" +#include +#include +#include +#include +#include +//---------------------------------------------------------------------------- +class TLogListDlg : public TForm +{ +__published: + TStringGrid *Grid; + TMainMenu *MainMenu; + TMenuItem *KFile; + TMenuItem *KOpen; + TOpenDialog *OpenDialog; + TMenuItem *KEdit; + TMenuItem *KFlush; + TMenuItem *KDelCur; + TMenuItem *KDelSel; + TMenuItem *N1; + TMenuItem *KExit; + TMenuItem *KFind; + TMenuItem *KFindTop; + TMenuItem *KFindBottom; + TMenuItem *KFindConT; + TMenuItem *KFindConB; + TMenuItem *N2; + TMenuItem *KTop; + TMenuItem *KBottom; + TMenuItem *N3; + TMenuItem *KSortDate; + TMenuItem *KInsCur; + TMenuItem *N4; + TMenuItem *N5; + TMenuItem *KMTextRead; + TMenuItem *KMTextWrite; + TSaveDialog *SaveDialog; + TMenuItem *KSelAll; + TMenuItem *KHelp; + TMenuItem *KHlpLog; + TMenuItem *N6; + TMenuItem *KReIndex; + TMenuItem *N7; + TMenuItem *KExport; + TMenuItem *KExportText; + TMenuItem *KImport; + TMenuItem *KImportText; + TMenuItem *KImportLog200; + TMenuItem *KExportLog200; + TMenuItem *KImportHamlog; + TMenuItem *KExportHamlog; + TMenuItem *KLogOpt; + TMenuItem *KOpt; + TMenuItem *KExportADIF; + TMenuItem *KImportADIF; + TMenuItem *KExportCabrillo;void __fastcall GridKeyPress(TObject *Sender, char &Key); + void __fastcall KOpenClick(TObject *Sender); + void __fastcall KFlushClick(TObject *Sender); + void __fastcall KDelCurClick(TObject *Sender); + void __fastcall KDelSelClick(TObject *Sender); + void __fastcall KExitClick(TObject *Sender); + void __fastcall KFindTopClick(TObject *Sender); + void __fastcall KFindBottomClick(TObject *Sender); + void __fastcall KTopClick(TObject *Sender); + void __fastcall KBottomClick(TObject *Sender); + void __fastcall KSortDateClick(TObject *Sender); + + void __fastcall GridDblClick(TObject *Sender); + void __fastcall KInsCurClick(TObject *Sender); + void __fastcall KMTextReadClick(TObject *Sender); + void __fastcall KMTextWriteClick(TObject *Sender); + void __fastcall KSelAllClick(TObject *Sender); + void __fastcall KHlpLogClick(TObject *Sender); + void __fastcall KReIndexClick(TObject *Sender); + + void __fastcall KExportTextClick(TObject *Sender); + void __fastcall KImportTextClick(TObject *Sender); + void __fastcall KExportLog200Click(TObject *Sender); + void __fastcall KImportLog200Click(TObject *Sender); + void __fastcall KImportHamlogClick(TObject *Sender); + void __fastcall KExportHamlogClick(TObject *Sender); + void __fastcall KLogOptClick(TObject *Sender); + void __fastcall KExportADIFClick(TObject *Sender); + void __fastcall KImportADIFClick(TObject *Sender); + void __fastcall KExportCabrilloClick(TObject *Sender); + void __fastcall GridDrawCell(TObject *Sender, int Col, int Row, + TRect &Rect, TGridDrawState State); +private: + void __fastcall AdjustTopRow(void); + void __fastcall UpdateLogCount(int sw); + void __fastcall UpdateMenu(void); + void __fastcall OnIdle(TObject *Sender, bool &Done); + + int __fastcall SureRead(void); + + void __fastcall LoadMmlogText(LPCSTR pName); + void __fastcall SaveMmlogText(LPCSTR pName); + int __fastcall LoadText(LPCSTR pName); + int __fastcall SaveText(LPCSTR pName); + int __fastcall LoadLog200(LPCSTR pName); + int __fastcall SaveLog200(LPCSTR pName); + int __fastcall LoadHamLog(LPCSTR pName); + int __fastcall SaveHamLog(LPCSTR pName); + int __fastcall LoadHamLog5(LPCSTR pName); + int __fastcall SaveHamLog5(LPCSTR pName); + + int __fastcall LoadADIF(LPCSTR pName); + int __fastcall SaveADIF(LPCSTR pName); + + int __fastcall SaveCabrillo(LPCSTR pName); + + AnsiString m_FindCall; + + void __fastcall SetTimeZone(void); + AnsiString m_TimeZone; + int m_DateWidth; +public: + virtual __fastcall TLogListDlg(TComponent* AOwner); + + void __fastcall TLogListDlg::Execute(void); +}; +//---------------------------------------------------------------------------- +//extern TLogListDlg *LogListDlg; +//---------------------------------------------------------------------------- +#endif diff --git a/LogPic.cpp b/LogPic.cpp new file mode 100644 index 0000000..1911a61 --- /dev/null +++ b/LogPic.cpp @@ -0,0 +1,211 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "ComLib.h" +#include "LogPic.h" +#include "Main.h" +#include "ZoomView.h" +//--------------------------------------------------------------------- +#pragma resource "*.dfm" +//--------------------------------------------------------------------- +__fastcall TLogPicDlg::TLogPicDlg(TComponent* AOwner) + : TForm(AOwner) +{ + FormStyle = ((TForm *)AOwner)->FormStyle; + Font->Name = ((TForm *)AOwner)->Font->Name; + Font->Charset = ((TForm *)AOwner)->Font->Charset; + if( MsgEng ){ + OKBtn->Caption = "Close"; + } + pBitmap = new Graphics::TBitmap(); + pBitmap->Width = PB->Width; + pBitmap->Height = PB->Height; + for( int i = 0; i < 5; i++ ){ + pBitmapS[i] = new Graphics::TBitmap(); + pBitmapS[i]->Width = PB->Width; + pBitmapS[i]->Height = PB->Height; + } + m_RectS.Left = 0; + m_RectS.Top = 0; + m_RectS.Right = PB1->Width; + m_RectS.Bottom = PB1->Height; + SBCopy->Glyph->Assign(Mmsstv->SBCopy->Glyph); + SBZoom->Glyph->Assign(Mmsstv->SBHView->Glyph); +} +//--------------------------------------------------------------------- +__fastcall TLogPicDlg::~TLogPicDlg() +{ + delete pBitmap; + pBitmap = NULL; + for( int i = 0; i < 5; i++ ){ + delete pBitmapS[i]; + pBitmapS[i] = NULL; + } +} +//--------------------------------------------------------------------- +// 200102211234 +int __fastcall IsDateFormat(LPCSTR p) +{ + if( !*p ) return 0; + if( strlen(p) != 10 ) return 0; + for( ; *p; p++ ){ + if( !isdigit(*p) ) return 0; + } + return 1; +} +//--------------------------------------------------------------------- +void __fastcall TLogPicDlg::LoadPic(void) +{ + m_Cur = 0; + int i; + for( i = 0; i < m_Cnt; i++ ){ + char fname[256]; + char abf[2]; + abf[0] = abf[1] = 0; + if( LastC(sys.m_AutoSaveDir.c_str()) != '\\' ) abf[0] = '\\'; + sprintf(fname, "%s%s20%s.jpg", sys.m_AutoSaveDir.c_str(), abf, m_List[i].c_str()); + if( LoadJPEG(pBitmapS[i], fname) != TRUE ){ + sprintf(fname, "%s%s20%s.bmp", sys.m_AutoSaveDir.c_str(), abf, m_List[i].c_str()); + if( LoadBitmap(pBitmapS[i], fname) != TRUE ){ + FillBitmap(pBitmapS[i], clWhite); + } + } + } + pBitmap->Assign(pBitmapS[0]); +} +//--------------------------------------------------------------------- +int __fastcall IsLogPic(LPCSTR pNote) +{ + char bf[256]; + strcpy(bf, pNote); + LPSTR t; + LPSTR p = bf; + while(*p){ + p = StrDlm(t, p); + if( IsDateFormat(t) ) return 1; + } + return 0; +} + +//--------------------------------------------------------------------- +void __fastcall TLogPicDlg::Execute(LPCSTR pNote) +{ + char bf[256]; + strcpy(bf, pNote); + LPSTR t; + LPSTR p = bf; + m_Cur = 0; + m_Cnt = 0; + while(*p){ + p = StrDlm(t, p); + if( IsDateFormat(t) ){ + m_List[m_Cnt] = t; + m_Cnt++; + if( m_Cnt >= 5 ) break; + } + } + LoadPic(); + ShowModal(); +} +//--------------------------------------------------------------------- +void __fastcall TLogPicDlg::PBPaint(TObject *Sender) +{ + DrawBitmap(PB, pBitmap); +// PB->Canvas->Draw(0, 0, pBitmap); +} +//--------------------------------------------------------------------------- +void __fastcall TLogPicDlg::PaintS(TPaintBox *tp, Graphics::TBitmap *pbmp) +{ + ::SetStretchBltMode(tp->Canvas->Handle, HALFTONE); + tp->Canvas->StretchDraw(m_RectS, pbmp); +} +//--------------------------------------------------------------------------- +void __fastcall TLogPicDlg::PB1Paint(TObject *Sender) +{ + PaintS(PB1, pBitmapS[0]); +} +//--------------------------------------------------------------------------- +void __fastcall TLogPicDlg::PB2Paint(TObject *Sender) +{ + PaintS(PB2, pBitmapS[1]); +} +//--------------------------------------------------------------------------- +void __fastcall TLogPicDlg::PB3Paint(TObject *Sender) +{ + PaintS(PB3, pBitmapS[2]); +} +//--------------------------------------------------------------------------- +void __fastcall TLogPicDlg::PB4Paint(TObject *Sender) +{ + PaintS(PB4, pBitmapS[3]); +} +//--------------------------------------------------------------------------- +void __fastcall TLogPicDlg::PB5Paint(TObject *Sender) +{ + PaintS(PB5, pBitmapS[4]); +} +//--------------------------------------------------------------------------- +void __fastcall TLogPicDlg::PB1Click(TObject *Sender) +{ + pBitmap->Assign(pBitmapS[0]); + PB->Invalidate(); +} +//--------------------------------------------------------------------------- +void __fastcall TLogPicDlg::PB2Click(TObject *Sender) +{ + pBitmap->Assign(pBitmapS[1]); + PB->Invalidate(); +} +//--------------------------------------------------------------------------- +void __fastcall TLogPicDlg::PB3Click(TObject *Sender) +{ + pBitmap->Assign(pBitmapS[2]); + PB->Invalidate(); +} +//--------------------------------------------------------------------------- +void __fastcall TLogPicDlg::PB4Click(TObject *Sender) +{ + pBitmap->Assign(pBitmapS[3]); + PB->Invalidate(); +} +//--------------------------------------------------------------------------- +void __fastcall TLogPicDlg::PB5Click(TObject *Sender) +{ + pBitmap->Assign(pBitmapS[4]); + PB->Invalidate(); +} +//--------------------------------------------------------------------------- +void __fastcall TLogPicDlg::SBCopyClick(TObject *Sender) +{ + Mmsstv->CopyBitmap(pBitmap); +} +//--------------------------------------------------------------------------- + +void __fastcall TLogPicDlg::SBZoomClick(TObject *Sender) +{ + TZoomViewDlg *pBox = new TZoomViewDlg(this); + pBox->Execute(pBitmap, FALSE); + delete pBox; +} +//--------------------------------------------------------------------------- + diff --git a/LogPic.dfm b/LogPic.dfm new file mode 100644 index 0000000..f0fdc8f Binary files /dev/null and b/LogPic.dfm differ diff --git a/LogPic.h b/LogPic.h new file mode 100644 index 0000000..1261957 --- /dev/null +++ b/LogPic.h @@ -0,0 +1,88 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//---------------------------------------------------------------------------- +#ifndef OCBH +#define OCBH +//---------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//---------------------------------------------------------------------------- +class TLogPicDlg : public TForm +{ +__published: + TButton *OKBtn; + TPanel *PS1; + TPanel *PS2; + TPanel *PS3; + TPanel *PS; + TPaintBox *PB1; + TPaintBox *PB2; + TPaintBox *PB3; + TPaintBox *PB; + TSpeedButton *SBCopy; + TPanel *PC4; + TPaintBox *PB4; + TPanel *PC5; + TPaintBox *PB5; + TSpeedButton *SBZoom; + void __fastcall PBPaint(TObject *Sender); + void __fastcall PB1Paint(TObject *Sender); + void __fastcall PB2Paint(TObject *Sender); + void __fastcall PB3Paint(TObject *Sender); + void __fastcall PB1Click(TObject *Sender); + void __fastcall PB2Click(TObject *Sender); + void __fastcall PB3Click(TObject *Sender); + void __fastcall SBCopyClick(TObject *Sender); + void __fastcall PB4Paint(TObject *Sender); + void __fastcall PB4Click(TObject *Sender); + void __fastcall PB5Click(TObject *Sender); + void __fastcall PB5Paint(TObject *Sender); + void __fastcall SBZoomClick(TObject *Sender); +private: + AnsiString m_List[5]; + Graphics::TBitmap *pBitmapS[5]; + Graphics::TBitmap *pBitmap; + + int m_Cnt; + int m_Cur; + TRect m_RectS; + void __fastcall LoadPic(void); + void __fastcall PaintS(TPaintBox *tp, Graphics::TBitmap *pbmp); + +public: + virtual __fastcall TLogPicDlg(TComponent* AOwner); + __fastcall ~TLogPicDlg(); + + + void __fastcall Execute(LPCSTR pNote); +}; +int __fastcall IsDateFormat(LPCSTR p); +int __fastcall IsLogPic(LPCSTR pNote); +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +#endif diff --git a/LogSet.cpp b/LogSet.cpp new file mode 100644 index 0000000..9884c9a --- /dev/null +++ b/LogSet.cpp @@ -0,0 +1,235 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "LogSet.h" +#include "country.h" +#include "Loglink.h" +//--------------------------------------------------------------------- +#pragma resource "*.dfm" +//TLogSetDlg *LogSetDlg; +static int PageIndex = 0; +//--------------------------------------------------------------------- +__fastcall TLogSetDlg::TLogSetDlg(TComponent* AOwner) + : TForm(AOwner) +{ + m_DisEvent = 1; + FormStyle = ((TForm *)AOwner)->FormStyle; + Font->Name = ((TForm *)AOwner)->Font->Name; + Font->Charset = ((TForm *)AOwner)->Font->Charset; + if( MsgEng ){ + TabConv->Caption = "Conversion"; + TabMisc->Caption = "Misc"; + CancelBtn->Caption = "Cancel"; + Caption = "Setup Logging"; + TabFlag->Caption = "Input"; + GrpConv->Caption = "Convert UpperCase"; + GrpCopy->Caption = "Copy Before Data"; + CopyFreq->Caption = "Copy Band or Freq."; + CopyFreq->Items->Strings[0] = "Copy Band"; + CopyFreq->Items->Strings[1] = "Copy Freq."; + DefMyRST->Caption = "595 Default"; + + RGDupe->Caption = "Dupe Check (Show Red)"; + RGDupe->Items->Strings[0] = "Callsign only"; + RGDupe->Items->Strings[1] = "Hit on the same band"; + AutoZone->Caption = "Ignore daylight saving"; + CBBackup->Caption = "Make backup"; + CBFSKNR->Caption = "Add contest NR to the FSKID"; + CBRemC->Visible = FALSE; + L1->Caption = "Delay time"; + GB7->Caption = "Template"; + GB9->Caption = "Mode"; + } + else { + LLink->Caption = "Hamlogの環境設定-設定1で\r\n「交信履歴表示で一旦停止」のチェックは付けないで下さい."; + } + if( lcid == LANG_KOREAN ){ + TimeZone->Items->Strings[0] = "Korea"; + } + else { + TimeZone->Items->Strings[0] = "Japan"; + } + m_MMList.QueryList("MML"); + for( int i = 0; i < m_MMList.GetCount(); i++ ){ + CBMMLink->Items->Add(m_MMList.GetItemName(i)); + } +} +//--------------------------------------------------------------------- +void __fastcall TLogSetDlg::UpdateUI(void) +{ + int f = !AutoZone->Checked; + TimeOff->Enabled = f; + MinOff->Enabled = f; + UDOffset->Enabled = f; + UDMin->Enabled = f; + ClearOff->Enabled = f; + CBPoll->Enabled = RGLink->ItemIndex ? TRUE : FALSE; + if( !MsgEng ){ + LLink->Visible = (RGLink->ItemIndex == 1) ? TRUE : FALSE; + } + CBMMLink->Enabled = (RGLink->ItemIndex == 2) ? TRUE : FALSE; + LT->Enabled = CBMMLink->Enabled; +} +//--------------------------------------------------------------------- +int __fastcall TLogSetDlg::Execute(void) +{ + int i; + for( i = 0; i < 5; i++ ){ + m_MacroStr[i] = Log.m_LogSet.m_QSOMacroStr[i]; + m_MacroKey[i] = Log.m_LogSet.m_QSOMacroKey[i]; + } + UpperName->Checked = Log.m_LogSet.m_UpperName; + UpperQTH->Checked = Log.m_LogSet.m_UpperQTH; + UpperREM->Checked = Log.m_LogSet.m_UpperREM; + UpperQSL->Checked = Log.m_LogSet.m_UpperQSL; + + DefMyRST->Checked = Log.m_LogSet.m_DefMyRST; + + CopyFreq->ItemIndex = Log.m_LogSet.m_CopyFreq; + CopyHis->ItemIndex = Log.m_LogSet.m_CopyHis; + CopyName->Checked = Log.m_LogSet.m_CopyName; + CopyQTH->Checked = Log.m_LogSet.m_CopyQTH; + CopyREM->Checked = Log.m_LogSet.m_CopyREM; + CopyQSL->Checked = Log.m_LogSet.m_CopyQSL; + CBBackup->Checked = Log.m_LogSet.m_Backup; + CBRemC->Checked = Log.m_LogSet.m_CopyREMB4; + CBFSKNR->Checked = Log.m_LogSet.m_FSKNR; + + if( Log.m_LogSet.m_TimeZone != 'I' ){ + TimeZone->ItemIndex = 1; + } + else { + TimeZone->ItemIndex = 0; + } + AutoSave->Checked = Log.m_LogSet.m_AutoSave; + RGDupe->ItemIndex = Log.m_LogSet.m_CheckBand; + + THRTTY->Text = Log.m_LogSet.m_THRTTY; + THSSTV->Text = Log.m_LogSet.m_THSSTV; + THTZ->ItemIndex = Log.m_LogSet.m_THTZ; + ClipRSTADIF->Checked = Log.m_LogSet.m_ClipRSTADIF; + DateType->ItemIndex = Log.m_LogSet.m_DateType; + AutoZone->Checked = sys.m_AutoTimeOffset; + UDOffset->Position = short(sys.m_TimeOffset); + UDMin->Position = short(sys.m_TimeOffsetMin); + RGLink->ItemIndex = sys.m_LogLink; + CBPoll->Checked = LogLink.IsPolling(); + CBPTT->Checked = LogLink.GetPTTEnabled(); + CBMMLink->ItemIndex = CBMMLink->Items->IndexOf(LogLink.GetItemName()); + if( m_MMList.GetCount() ){ + RGLink->Controls[2]->Enabled = TRUE; + if( CBMMLink->ItemIndex < 0 ){ + CBMMLink->ItemIndex = 0; + } + } + else { + RGLink->Controls[2]->Enabled = FALSE; + } + CBTDelay->ItemIndex = sys.m_TempDelay; + if( (PageIndex >= 0) && (PageIndex < Page->PageCount) ){ + if( Page->Pages[PageIndex]->TabVisible == FALSE ){ + PageIndex = 0; + } + Page->ActivePage = Page->Pages[PageIndex]; + } + int r = FALSE; + UpdateUI(); + m_DisEvent = 0; + if( ShowModal() == IDOK ){ + Log.m_LogSet.m_UpperName = UpperName->Checked; + Log.m_LogSet.m_UpperQTH = UpperQTH->Checked; + Log.m_LogSet.m_UpperREM = UpperREM->Checked; + Log.m_LogSet.m_UpperQSL = UpperQSL->Checked; + + Log.m_LogSet.m_DefMyRST = DefMyRST->Checked; + + Log.m_LogSet.m_CopyFreq = CopyFreq->ItemIndex; + Log.m_LogSet.m_CopyHis = CopyHis->ItemIndex; + Log.m_LogSet.m_CopyName = CopyName->Checked; + Log.m_LogSet.m_CopyQTH = CopyQTH->Checked; + Log.m_LogSet.m_CopyREM = CopyREM->Checked; + Log.m_LogSet.m_CopyQSL = CopyQSL->Checked; + Log.m_LogSet.m_CopyREMB4 = ( Font->Charset != SHIFTJIS_CHARSET ) ? 0 : CBRemC->Checked; + + if( TimeZone->ItemIndex ){ + Log.m_LogSet.m_TimeZone = 'Z'; + } + else { + Log.m_LogSet.m_TimeZone = 'I'; + } + + Log.m_LogSet.m_AutoSave = AutoSave->Checked; + Log.m_LogSet.m_CheckBand = RGDupe->ItemIndex; + + Log.m_LogSet.m_THRTTY = THRTTY->Text; + Log.m_LogSet.m_THSSTV = THSSTV->Text; + Log.m_LogSet.m_THTZ = THTZ->ItemIndex; + Log.m_LogSet.m_ClipRSTADIF = ClipRSTADIF->Checked; + Log.m_LogSet.m_DateType = DateType->ItemIndex; + Log.m_LogSet.m_Backup = CBBackup->Checked; + Log.m_LogSet.m_FSKNR = CBFSKNR->Checked; + + sys.m_AutoTimeOffset = AutoZone->Checked; + sys.m_TimeOffset = UDOffset->Position; + sys.m_TimeOffsetMin = UDMin->Position; + if( sys.m_AutoTimeOffset ){ + SetTimeOffsetInfo(sys.m_TimeOffset, sys.m_TimeOffsetMin); + } + sys.m_LogLink = RGLink->ItemIndex; + LogLink.SetPolling(CBPoll->Checked); + LogLink.SetPTTEnabled(CBPTT->Checked); + if( CBMMLink->ItemIndex >= 0 ){ + LogLink.SetItemName(AnsiString(CBMMLink->Items->Strings[CBMMLink->ItemIndex]).c_str()); //ja7ude 0428 + } + sys.m_TempDelay = CBTDelay->ItemIndex; + r = TRUE; + } + PageIndex = GetActiveIndex(Page); + return r; +} +//--------------------------------------------------------------------- +void __fastcall TLogSetDlg::ClearOffClick(TObject *Sender) +{ + UDOffset->Position = 0; + UDMin->Position = 0; +} +//--------------------------------------------------------------------------- +void __fastcall TLogSetDlg::AutoZoneClick(TObject *Sender) +{ + if( AutoZone->Checked ){ + int hour, min; + SetTimeOffsetInfo(hour, min); + UDOffset->Position = short(hour); + UDMin->Position = short(min); + } + UpdateUI(); +} +//--------------------------------------------------------------------------- +void __fastcall TLogSetDlg::RGLinkClick(TObject *Sender) +{ + if( m_DisEvent ) return; + + UpdateUI(); +} +//--------------------------------------------------------------------------- + diff --git a/LogSet.dfm b/LogSet.dfm new file mode 100644 index 0000000..d55cd06 Binary files /dev/null and b/LogSet.dfm differ diff --git a/LogSet.h b/LogSet.h new file mode 100644 index 0000000..9c50352 --- /dev/null +++ b/LogSet.h @@ -0,0 +1,125 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//---------------------------------------------------------------------------- +#ifndef LogSetH +#define LogSetH +//---------------------------------------------------------------------------- +// JA7UDE 0428 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//---------------------------------------------------------------------------- +#include "LogFile.h" +#include "MMLink.h" +//---------------------------------------------------------------------------- +class TLogSetDlg : public TForm +{ +__published: + TButton *OKBtn; + TButton *CancelBtn; + TPageControl *Page; + TTabSheet *TabFlag; + TGroupBox *GrpConv; + TCheckBox *UpperName; + TCheckBox *UpperQTH; + TCheckBox *UpperREM; + TCheckBox *UpperQSL; + TGroupBox *GrpCopy; + TCheckBox *CopyName; + TCheckBox *CopyQTH; + TCheckBox *CopyREM; + TCheckBox *CopyQSL; + TRadioGroup *CopyHis; + TRadioGroup *CopyFreq; + TGroupBox *GB5; + TCheckBox *DefMyRST; + TRadioGroup *TimeZone; + TTabSheet *TabConv; + TGroupBox *GB1; + TGroupBox *GB2; + TCheckBox *ClipRSTADIF; + TTabSheet *TabMisc; + TGroupBox *GTime; + TEdit *TimeOff; + TUpDown *UDOffset; + TRadioGroup *DateType; + TEdit *MinOff; + TUpDown *UDMin; + TLabel *Label4; + TLabel *Label5; + TButton *ClearOff; + TCheckBox *AutoSave; + TCheckBox *AutoZone; + TGroupBox *GB3; + TRadioGroup *RGLink; + TCheckBox *CBPoll; + TRadioGroup *THTZ; + TRadioGroup *RGDupe; + TLabel *LLink; + TCheckBox *CBRemC; + TComboBox *CBMMLink; + TLabel *LT; + TCheckBox *CBFSKNR; + TGroupBox *GB7; + TLabel *L1; + TComboBox *CBTDelay; + TLabel *L2; + TCheckBox *CBBackup; + TCheckBox *CBPTT; + TGroupBox *GB9; + TLabel *Label2; + TEdit *THRTTY; + TLabel *Label3; + TEdit *THSSTV; + void __fastcall ClearOffClick(TObject *Sender); + void __fastcall AutoZoneClick(TObject *Sender); + + + + void __fastcall RGLinkClick(TObject *Sender); + +private: + int m_DisEvent; + AnsiString m_MacroStr[5]; + WORD m_MacroKey[5]; + + CMMList m_MMList; + + void __fastcall MacroBtnClick(int n); + void __fastcall UpdateUI(void); + +public: + virtual __fastcall TLogSetDlg(TComponent* AOwner); + + int __fastcall Execute(void); + +}; +//---------------------------------------------------------------------------- +//extern TLogSetDlg *LogSetDlg; +//---------------------------------------------------------------------------- +#endif diff --git a/Loglink.cpp b/Loglink.cpp new file mode 100644 index 0000000..925d36a --- /dev/null +++ b/Loglink.cpp @@ -0,0 +1,865 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------------- +#include //ja7ude 0521 +#pragma hdrstop + +#define MMSSTV 1 // MMTTYでは0 +#if MMSSTV +#include "Main.h" +#endif + +#include "LogLink.h" +CLogLink LogLink; +//--------------------------------------------------------------------------- +// CLogLinkクラス +CLogLink::CLogLink() +{ + m_Enabled = FALSE; + m_Count = m_Count2 = 0; + m_hLog = NULL; + m_hLogIn = NULL; + m_CStat = 0; + m_hApp = NULL; + m_hMain = NULL; + m_Error = 0; + m_1stSession = TRUE; + m_fHLV5 = TRUE; + + m_Polling = 1; + m_PTTEnabled = FALSE; + + m_AStat = FALSE; + m_MMStat = FALSE; + m_pLink = NULL; + m_strMode[0] = 0; +} + +CLogLink::~CLogLink() +{ + CloseMMLink(); +} +//--------------------------------------------------------------------------- +void __fastcall CLogLink::CloseMMLink(void) +{ + if( m_pLink != NULL ){ + delete m_pLink; + m_pLink = NULL; + } +} +//--------------------------------------------------------------------------- +// 送信用ウインドウハンドルの設定 +void CLogLink::SetHandle(HWND hMain, UINT uMsg) +{ + m_hMain = hMain; + m_uMsg = uMsg; + m_hApp = Application->Handle; + if( m_pLink == NULL ) return; + m_pLink->SetHandle(hMain, uMsg); +} +//--------------------------------------------------------------------------- +BOOL __fastcall CLogLink::IsLink(void) +{ + switch(m_Enabled){ + case 1: + return m_hLog != NULL ? TRUE : FALSE; + case 2: + return m_MMStat; + default: + return FALSE; + } +} +//--------------------------------------------------------------------------- +LPCSTR __fastcall CLogLink::GetSessionName(void) +{ + switch(m_Enabled){ + case 1: +// return "Turbo HAMLOG/Win"; + return m_AppName.c_str(); + case 2: + if( m_pLink == NULL ) return NULL; + return m_pLink->GetSessionName(); + default: + return NULL; + } +} +//--------------------------------------------------------------------------- +// リンクの許可設定 +void CLogLink::UpdateLink(int sw) +{ + if( (m_Enabled != sw) || + ((m_pLink != NULL) && strcmp(m_ItemName.c_str(), m_pLink->GetItemName()) ) + ){ + m_Enabled = sw; + switch(sw){ + case 0: + m_hLog = NULL; + m_hLogIn = NULL; + CloseMMLink(); + break; + case 1: + m_Count = 0; + m_Error = 0; + CloseMMLink(); + break; + case 2: + m_Count = 0; + m_Error = 0; + if( !m_pLink ){ + m_pLink = new CMMLink(m_hMain, m_uMsg); + } + m_pLink->Open(m_ItemName.c_str()); + break; + } + } +} +//--------------------------------------------------------------------------- +// コールサインを分離 +static void DevCall(AnsiString &CALL, AnsiString &PTB, LPCSTR pCall) +{ + char bf[1024]; + + CALL = ""; + PTB = ""; + strcpy(bf, pCall); + LPSTR pp, p2, t; + t = bf; + if( (pp = strchr(bf, '/')) != NULL ){ // KH6/JE3HHT or JE3HHT/KH6 の形式 + *pp = 0; + pp++; + int LenC = strlen(t); + int LenP = strlen(pp); + if( ((p2 = strchr(pp, '/')) != NULL)|| + (LenC > 7) || + (LenP > 7) || + ((LenC > LenP) && (LenP>3)) || + ((LenC < LenP) && (LenC>3)) + ){ + // HAMLOGでは表現できない表記の場合 + if( p2 != NULL ){ + *p2 = 0; + LenP = strlen(pp); + } + } + if( LenC < LenP ){ + p2 = t; + t = pp; + pp = p2; + } + PTB = pp; + } + CALL = t; +} +//--------------------------------------------------------------------------- +static void __fastcall SetHamlogMode(LPSTR bf) +{ + if( !strcmp(bf, "RTTY") ){ + StrCopy(bf, Log.m_LogSet.m_THRTTY.c_str(), 3); + } + else if( !strcmp(bf, "SSTV") ){ + StrCopy(bf, Log.m_LogSet.m_THSSTV.c_str(), 3); + } + else if( !strcmp(bf, "GMSK") ){ + strcpy(bf, "MSK"); + } + else if( !strcmp(bf, "FSTV") ){ + strcpy(bf, "FTV"); + } + else if( !strcmp(bf, "BPSK") ){ + strcpy(bf, "PSK"); + } + else if( !strcmp(bf, "QPSK") ){ + strcpy(bf, "PSK"); + } +} +//--------------------------------------------------------------------------- +// MM -> HamLog フォーマットの一括変換 +static void MMtoHAMLOG(LPSTR tp, SDMMLOG *sp, BOOL fHLV5) +{ + char bf[512]; + + AnsiString DATE; + AnsiString TIME; + + int CallOrder = FALSE; + + if( sp->btime ){ + int YY = sp->year; + int MM = sp->date / 100; + int DD = sp->date % 100; + int tim = sp->btime / 30; + int HH = tim / 60; + int mm = tim % 60; + char tz = 'J'; + switch(Log.m_LogSet.m_THTZ){ + case 0: + if( !IsJA(sp->call) ){ + JSTtoUTC(YY, MM, DD, HH); + tz = 'U'; + } + break; + case 1: + JSTtoUTC(YY, MM, DD, HH); + tz = 'U'; + break; + default: + break; + } + sprintf(bf, "%02u/%02u/%02u", YY, MM, DD); + DATE = bf; + sprintf(bf, "%02u:%02u%c", HH, mm, tz); + TIME = bf; + } + + AnsiString NAME = sp->name; + AnsiString QTH = sp->qth; + AnsiString REM1 = sp->rem; + AnsiString REM2 = sp->qsl; + + AnsiString CALL; + AnsiString PTB; + + if( fHLV5 ){ // Ver 5.00以降 + CALL = sp->call; + } + else { // Ver 4.xx + strcpy(bf, sp->call); + LPSTR pp, p2, t; + t = bf; + if( (pp = strchr(bf, '/')) != NULL ){ // KH6/JE3HHT or JE3HHT/KH6 の形式 + *pp = 0; + pp++; + int LenC = strlen(t); + int LenP = strlen(pp); + if( ((p2 = strchr(pp, '/')) != NULL)|| + (LenC > 7) || + (LenP > 7) || + ((LenC > LenP) && (LenP>3)) || + ((LenC < LenP) && (LenC>3)) + ){ + // HAMLOGでは表現できない表記の場合 + AddMMLOGKey(REM1, REM2, sp->call, "ToRadio"); + if( p2 != NULL ){ + *p2 = 0; + LenP = strlen(pp); + } + } + if( LenC < LenP ){ + p2 = t; + t = pp; + pp = p2; + CallOrder = TRUE; + } + PTB = pp; + } + else if( strlen(t) > 7 ){ + AddMMLOGKey(REM1, REM2, sp->call, "ToRadio"); + } + CALL = t; + } + strcpy(bf, Log.GetModeString(sp->mode)); + if( !fHLV5 ){ + SetHamlogMode(bf); + } + AnsiString MODE = bf; + + AnsiString HIS, MY; + int l = GetLMode(sp->mode); + if( fHLV5 ){ + HIS = sp->ur; + MY = sp->my; + } + else { + strcpy(bf, sp->ur); + bf[l] = 0; + HIS = bf; + strcpy(bf, sp->my); + bf[l] = 0; + MY = bf; + } + if( sp->ur[l] ) AddMMLOGKey(REM1, REM2, &sp->ur[l], "SN"); + if( sp->my[l] ) AddMMLOGKey(REM1, REM2, &sp->my[l], "RN"); + + strcpy(bf, Log.GetFreqString(sp->band, sp->fq)); + AnsiString FREQ = bf; + + if( !fHLV5 ){ + if( CallOrder && (!strstr(sp->rem, "$DX")) && (!strstr(sp->qsl, "$DX")) ){ + AddMMLOGKey(REM1, REM2, "$DX", NULL); + } + } + + if( sp->etime ){ + int tim = sp->etime / 30; + sprintf(bf, "%02u%02u", tim / 60, tim % 60); + AddMMLOGKey(REM1, REM2, bf, "END"); + } + if( sp->env ){ + sprintf(bf, "%u", sp->env); + AddMMLOGKey(REM1, REM2, bf, "ENV"); + } + AddMMLOGKey(REM1, REM2, sp->pow, "POW"); + if( sp->cq ){ + bf[0] = sp->cq; bf[1] = 0; + AddMMLOGKey(REM1, REM2, bf, "M"); + } + AnsiString CODE; + if( (strlen(sp->opt1) >= 3) && isdigit(sp->opt1[0]) && isdigit(sp->opt1[1]) ){ + CODE = sp->opt1; + } + sprintf(bf, "%s\r\n%s\r\n%s\r\n%s\r\n%s\r\n%s\r\n%s\r\n%s\r\n%s\r\n%s\r\n%s\r\n%s\r\n%s\r\n%s\r\n%s\r\n", + CALL.c_str(), PTB.c_str(), DATE.c_str(), TIME.c_str(), + HIS.c_str(), MY.c_str(), FREQ.c_str(), MODE.c_str(), CODE.c_str(), "", "", + NAME.c_str(), QTH.c_str(), REM1.c_str(), REM2.c_str() + ); + strcpy(tp, bf); +} + +//--------------------------------------------------------------------------- +// ウインドウフォーカスを自身に戻す +void CLogLink::Foreground(void) +{ + if( m_Enabled != 1 ) return; + + ::SetWindowPos(m_hApp, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); + ::SetFocus(m_hApp); +} +//--------------------------------------------------------------------------- +// ログのリンクのチェック +BOOL CLogLink::CheckLink(void) +{ + if( m_Error ) return FALSE; + + switch(m_Enabled){ + case 1: + { + HWND hLog = ::FindWindow("TThwin", NULL); + if( hLog != m_hLog ){ + if( hLog ){ + m_AppVer = 0; + char bf[128]; + LPSTR p; + ::GetWindowText(hLog, bf, sizeof(bf)); + clipsp(bf); + m_AppName = bf; + if( (p = strstr(bf, "Ver")) != NULL ){ + p += 3; + LPSTR t; + for( t = p; *t; t++ ){ + if( (*t != '.') && !isdigit(*t) ) break; + } + *t = 0; + double d; + if( sscanf(p, "%lf", &d) == 1 ){ + m_AppVer = d * 100; + } + } + else { + m_Count = 1000/LINKINTERVAL; + return FALSE; + } + m_fHLV5 = (m_AppVer >= 500); + } + m_hLog = hLog; + m_CStat = TRUE; + } + return m_hLog != NULL ? TRUE : FALSE; + } + case 2: + { + if( m_pLink == NULL ) return FALSE; + m_MMStat = m_pLink->IsConnected(); + if( m_MMStat != m_AStat ){ + m_AStat = m_MMStat; + m_CStat = TRUE; + } + return m_MMStat; + } + default: + return FALSE; + } +} +//--------------------------------------------------------------------------- +// 定期的なログのリンクの監視(200ms毎にコール) +BOOL CLogLink::TimerLogLink(void) +{ + if( !m_Enabled ) return FALSE; + + if( !m_Count ){ + m_Count = 5000/LINKINTERVAL; // 5[s]毎のチェック + BOOL f = m_hLog != NULL; + CheckLink(); + if( m_hLog && !f ) m_1stSession = TRUE; + } + m_Count--; + if( m_CStat ){ + m_CStat = 0; + return TRUE; + } + else { + return FALSE; + } +} +//--------------------------------------------------------------------------- +// 定期的な周波数ポーリング +void CLogLink::EventGetFreq(void) +{ + if( !m_Polling ) return; + + if( !m_Count2 ){ + m_Count2 = 2000/LINKINTERVAL; // 2[s]毎のチェック + switch(m_Enabled){ + case 1: + { + if( m_hLog == NULL ) return; + int af = Application->Active; + m_cds.dwData = 106; + m_cds.cbData = 0; + m_cds.lpData = NULL; + ::SendMessage(m_hLog, WM_COPYDATA, WPARAM(m_hMain), LPARAM(&m_cds)); + if( af && m_1stSession ) Foreground(); + m_1stSession = FALSE; + + } + break; + case 2: + if( m_pLink == NULL ) return; + m_pLink->EventVFO(); + break; + } + } + m_Count2--; +} +//--------------------------------------------------------------------------- +// 周波数の設定 +void CLogLink::SetFreq(LPSTR pFreq) +{ + if( !CheckLink() ) return; + + switch(m_Enabled){ + case 1: + m_cds.dwData = 6; + m_cds.cbData = strlen(pFreq); + m_cds.lpData = pFreq; + m_hLogIn = (HWND)::SendMessage(m_hLog, WM_COPYDATA, WPARAM(m_hApp), LPARAM(&m_cds)); + break; + case 2: + if( m_pLink == NULL ) return; + m_pLink->SetFreq(pFreq); + break; + } +} +//--------------------------------------------------------------------------- +// モードの設定 +void CLogLink::SetMode(LPCSTR pMode) +{ + if( !CheckLink() ) return; + + switch(m_Enabled){ + case 1: + if( pMode && (pMode != m_strMode) ){ + StrCopy(m_strMode, pMode, sizeof(m_strMode)-1); + if( !m_fHLV5 ){ + SetHamlogMode(m_strMode); + } + } + if( m_strMode[0] ){ + m_cds.dwData = 7; + m_cds.cbData = strlen(m_strMode); + m_cds.lpData = m_strMode; + m_hLogIn = (HWND)::SendMessage(m_hLog, WM_COPYDATA, WPARAM(m_hApp), LPARAM(&m_cds)); + } + break; + case 2: +// if( m_pLink == NULL ) return; +// m_pLink->SetMode(pMode); + break; + } +} +//--------------------------------------------------------------------------- +void __fastcall CLogLink::SetPTT(int ptt) +{ + if( !m_PTTEnabled ) return; + if( !CheckLink() ) return; + switch(m_Enabled){ + case 1: + { + int af = Application->Active; + m_cds.dwData = ptt ? 23 : 24; + m_cds.cbData = 0; + m_cds.lpData = NULL; + ::SendMessage(m_hLog, WM_COPYDATA, af ? WPARAM(m_hApp) : NULL, LPARAM(&m_cds)); + if( af && m_1stSession ) Foreground(); + m_1stSession = FALSE; + } + break; + case 2: + if( !m_pLink ) return; + m_pLink->SetPTT(ptt); + break; + } +} +//--------------------------------------------------------------------------- +// クリア +void CLogLink::Clear(void) +{ + if( !CheckLink() ) return; + + switch(m_Enabled){ + case 1: + { + int af = Application->Active; + m_cds.dwData = 16; + m_cds.cbData = 0; + m_cds.lpData = NULL; + m_hLogIn = (HWND)::SendMessage(m_hLog, WM_COPYDATA, af ? WPARAM(m_hApp) : NULL, LPARAM(&m_cds)); +// m_hLogIn = (HWND)::SendMessage(m_hLog, WM_COPYDATA, NULL, LPARAM(&m_cds)); + if( !::IsWindow(m_hLogIn) ){ + m_hLog = NULL; + m_CStat = TRUE; + m_Error = TRUE; + } + if( af ) Foreground(); + break; + } + case 2: + m_QueryCall = ""; + if( m_pLink == NULL ) return; + m_pLink->Clear(); + break; + } +} +//--------------------------------------------------------------------------- +// Hamlogにフォーカスを設定 +void CLogLink::SetFocus(void) +{ + if( m_Enabled != 1 ) return; + if( m_hLog == NULL ) return; + if( m_hLogIn == NULL ) return; + + ::SetForegroundWindow(m_hLogIn); +} +//--------------------------------------------------------------------------- +// コールサインの転送 +void CLogLink::SetCall(LPSTR pCall, int sw) +{ + if( !CheckLink() ) return; + + switch(m_Enabled){ + case 1: + { + int af = Application->Active; + Clear(); + if( m_hLog == NULL ) return; +#if MMSSTV + MultProc(); +#endif + + AnsiString CALL; + AnsiString PTB; + + if( m_fHLV5 ){ + CALL = pCall; + m_cds.dwData = IsJA(pCall) ? 26 : 25; + m_cds.cbData = 0; + m_cds.lpData = NULL; + m_hLogIn = (HWND)::SendMessage(m_hLog, WM_COPYDATA, WPARAM(m_hApp), LPARAM(&m_cds)); + m_cds.dwData = 0; + if( sw ) m_cds.dwData |= THW_ENTER; + m_cds.cbData = strlen(CALL.c_str()); + m_cds.lpData = CALL.c_str(); + m_hLogIn = (HWND)::SendMessage(m_hLog, WM_COPYDATA, WPARAM(m_hApp), LPARAM(&m_cds)); + } + else { + DevCall(CALL, PTB, pCall); + m_cds.dwData = 0; + if( sw ) m_cds.dwData |= THW_ENTER; + m_cds.cbData = strlen(CALL.c_str()); + m_cds.lpData = CALL.c_str(); + m_hLogIn = (HWND)::SendMessage(m_hLog, WM_COPYDATA, WPARAM(m_hApp), LPARAM(&m_cds)); +#if MMSSTV + MultProc(); +#endif + m_cds.dwData = 1; + if( sw ) m_cds.dwData |= THW_ENTER; + m_cds.cbData = strlen(PTB.c_str()); + m_cds.lpData = PTB.c_str(); + m_hLogIn = (HWND)::SendMessage(m_hLog, WM_COPYDATA, WPARAM(m_hApp), LPARAM(&m_cds)); + } + if( af ) Foreground(); + } + case 2: + m_QueryCall = pCall; + if( m_pLink == NULL ) return; + m_pLink->Query(pCall); + break; + } +} +//--------------------------------------------------------------------------- +// コールサインの検索 +void CLogLink::FindCall(LPSTR pCall) +{ + if( !CheckLink() ) return; + + switch(m_Enabled){ + case 1: + { + int af = Application->Active; + SetCall(pCall, FALSE); + if( m_hLog == NULL ) return; +#if MMSSTV + MultProc(); +#endif + m_cds.dwData = 17; + m_cds.cbData = 0; + m_cds.lpData = NULL; + ::SendMessage(m_hLog, WM_COPYDATA, WPARAM(m_hApp), LPARAM(&m_cds)); + +#if MMSSTV + MultProc(); +#endif + + m_cds.dwData = 115; + m_cds.cbData = 0; + m_cds.lpData = NULL; + ::SendMessage(m_hLog, WM_COPYDATA, WPARAM(m_hMain), LPARAM(&m_cds)); + if( af ) Foreground(); + } + break; + case 2: + m_QueryCall = pCall; + if( m_pLink == NULL ) return; + m_pLink->Query(pCall); + break; + } +} +//--------------------------------------------------------------------------- +// ログの記録 +// 0-データの設定のみ +// 1-データの設定とRETキー/問い合わせの実行(QSOの開始時) +// 2-書きこみを実行(QSOの終了時) +void CLogLink::Write(SDMMLOG *sp, int sw) +{ + if( !CheckLink() ) return; + + switch(m_Enabled){ + case 1: + { + int af = Application->Active; + if( m_fHLV5 && (sw == 1) ){ + m_cds.dwData = IsJA(sp->call) ? 26 : 25; + m_cds.cbData = 0; + m_cds.lpData = NULL; + m_hLogIn = (HWND)::SendMessage(m_hLog, WM_COPYDATA, WPARAM(m_hApp), LPARAM(&m_cds)); + m_cds.dwData = 0; + m_cds.cbData = strlen(sp->call); + m_cds.lpData = sp->call; + m_hLogIn = (HWND)::SendMessage(m_hLog, WM_COPYDATA, WPARAM(m_hApp), LPARAM(&m_cds)); + } + char bf[1024]; + MMtoHAMLOG(bf, sp, m_fHLV5); + m_cds.dwData = 15; + if( sw ) m_cds.dwData |= THW_ENTER; + m_cds.cbData = strlen(bf); + m_cds.lpData = bf; + m_hLogIn = (HWND)::SendMessage(m_hLog, WM_COPYDATA, WPARAM(m_hApp), LPARAM(&m_cds)); + +#if MMSSTV + MultProc(); +#endif + switch(sw){ + case 1: + m_cds.dwData = 115; + m_cds.cbData = 0; + m_cds.lpData = NULL; + ::SendMessage(m_hLog, WM_COPYDATA, WPARAM(m_hMain), LPARAM(&m_cds)); + break; + case 2: + m_cds.dwData = 18 | THW_SAVEBOX_OFF; + m_cds.cbData = 0; + m_cds.lpData = NULL; + ::SendMessage(m_hLog, WM_COPYDATA, WPARAM(m_hApp), LPARAM(&m_cds)); + break; + } + if( af ) Foreground(); + } + break; + case 2: + if( m_pLink == NULL ) return; + m_QueryCall = sp->call; + m_pLink->LogWrite(sp, sw); + break; + } +} +//--------------------------------------------------------------------------- +int __fastcall GetLFCount(LPCSTR p) +{ + int n = 0; + for(; *p; p++ ){ + if( *p == LF ) n++; + } + return n; +} +//--------------------------------------------------------------------------- +// Hamlogからの返信メッセージからName,QTH,REM1を得る +int CLogLink::AnaData(SDMMLOG *sp, COPYDATASTRUCT *cp) +{ + BOOL r = FALSE; + + char bf[1024]; + int len = cp->cbData; + if( len >= 1023 ) len = 1023; + if( len && (cp->lpData != NULL) ){ + StrCopy(bf, LPCSTR(cp->lpData), len); + int lfLen = GetLFCount(bf); + LPSTR t, p; + if( len < 10 ){ // 周波数情報 + if( m_Polling ){ + t = SkipSpace(bf); ClipLF(t); clipsp(t); + if( *t ){ + Log.SetFreq(&Log.m_sd, t); + r = 106; + } + } + } + else if( lfLen >= 10 ){ // 検索結果情報 + p = StrDlm(t, bf, LF); // Call + p = StrDlm(t, p, LF); // PTB + p = StrDlm(t, p, LF); // Date + p = StrDlm(t, p, LF); // Time + p = StrDlm(t, p, LF); // His + p = StrDlm(t, p, LF); // My + p = StrDlm(t, p, LF); // Freq + p = StrDlm(t, p, LF); // Mode + p = StrDlm(t, p, LF); // Code + t = SkipSpace(t); ClipLF(t); clipsp(t); + if( *t ){ + StrCopy(sp->opt1, t, MLOPT); + r = 115; + } + p = StrDlm(t, p, LF); // GL + p = StrDlm(t, p, LF); // QSL + p = StrDlm(t, p, LF); // Name + if( !sp->name[0] ){ + t = SkipSpace(t); ClipLF(t); clipsp(t); + if( *t ){ + StrCopy(sp->name, t, MLNAME); + r = 115; + } + } + p = StrDlm(t, p, LF); // QTH +// if( !sp->qth[0] ){ + if( !sp->qth[0] || !IsJA(sp->call) ){ + t = SkipSpace(t); ClipLF(t); clipsp(t); + if( *t ){ + StrCopy(sp->qth, t, MLQTH); + r = 115; + } + } + StrDlm(t, p, LF); // REM1 + if( !sp->rem[0] ){ + t = SkipSpace(t); ClipLF(t); clipsp(t); + if( *t ){ + StrCopy(sp->rem, t, MLREM); + r = 115; + } + } + } + } + return r; +} +//--------------------------------------------------------------------------- +void __fastcall CLogLink::NotifySession(LPCSTR pSession) +{ + if( m_pLink == NULL ) return; + + m_pLink->NotifySession(pSession); + CheckLink(); +} +//--------------------------------------------------------------------------- +int __fastcall CLogLink::QReturn(SDMMLOG *sp, const mmLOGDATA *pLog) +{ + if( pLog == NULL ) return FALSE; + int r = FALSE; + + mmLOGDATA logdata; + memcpy(&logdata, pLog, sizeof(logdata)); + + if( stricmp(logdata.m_Call, m_QueryCall.c_str()) ) return FALSE; + LPSTR t; + if(!sp->name[0] ){ + t = SkipSpace(logdata.m_Name); ClipLF(t); clipsp(t); + if( *t ){ + StrCopy(sp->name, t, MLNAME); + r = TRUE; + } + } + if( !sp->qth[0] ){ + t = SkipSpace(logdata.m_QTH); ClipLF(t); clipsp(t); + if( *t ){ + StrCopy(sp->qth, t, MLQTH); + r = TRUE; + } + } + if( !sp->rem[0] ){ + t = SkipSpace(logdata.m_Note); ClipLF(t); clipsp(t); + if( *t ){ + StrCopy(sp->rem, t, MLREM); + r = TRUE; + } + } + return r; +} +//--------------------------------------------------------------------------- +void __fastcall CLogLink::SetTime(SYSTEMTIME *tp, int sw) +{ + if( m_pLink == NULL ) return; + + m_pLink->SetTime(tp, sw); +} +//--------------------------------------------------------------------------- +LPCSTR __fastcall CLogLink::GetItemName(void) +{ + return m_ItemName.c_str(); +} +//--------------------------------------------------------------------------- +void __fastcall CLogLink::SetItemName(LPCSTR pName) +{ + m_ItemName = pName; +} +//--------------------------------------------------------------------------- +void __fastcall CLogLink::LoadMMLink(TMemIniFile *pIni) +{ + m_ItemName = pIni->ReadString("MMLink", "Name", ""); +} +//--------------------------------------------------------------------------- +void __fastcall CLogLink::SaveMMLink(TMemIniFile *pIni) +{ + pIni->WriteString("MMLink", "Name", m_ItemName); +} +//--------------------------------------------------------------------------- +BOOL __fastcall CLogLink::IsCopyData(void) +{ + if( m_Enabled != 2 ) return FALSE; + if( !m_pLink ) return FALSE; + return (m_pLink->GetCaps() & capWMCOPYDATA); +} +//--------------------------------------------------------------------------- + diff --git a/Loglink.h b/Loglink.h new file mode 100644 index 0000000..999f98f --- /dev/null +++ b/Loglink.h @@ -0,0 +1,123 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------------- +#ifndef LogLinkH +#define LogLinkH + +#include +#include +#include + +#include "ComLib.h" +#include "LogConv.h" +#include "MMLink.h" + +#define LINKINTERVAL 200 + +//------------ Command of Hamlog ------------- +#define THW_ENTER 0x10000 +#define THW_FOCUS 0x20000 +#define THW_SAVEBOX_ON 0x40000 +#define THW_SAVEBOX_OFF 0x80000 +#define THW_APPLIHWND 0x100000 + +//--------------------------------------------------------------------------- +// CLogLinkクラス +class CLogLink +{ +private: + int m_Enabled; // リンクの許可 + int m_Polling; // 周波数ポーリング + BOOL m_PTTEnabled; // PTTコントロール + BOOL m_1stSession; + + HWND m_hLog; // Hamlogプログラムのハンドル + HWND m_hLogIn; // Hamlog入力ウインドウのハンドル + + COPYDATASTRUCT m_cds; // インターフェース構造体 + int m_Count; // 監視カウンタ + int m_CStat; // 状態変更セマフォ + int m_Count2; // ポーリングカウンタ + + HWND m_hMain; // メイン画面のウインドウハンドル + HWND m_hApp; // アプリケーションのウインドウハンドル + BOOL m_fHLV5; // Hamlog Ver 5.0 + + int m_Error; + + AnsiString m_ItemName; + AnsiString m_QueryCall; + AnsiString m_AppName; + int m_AppVer; + int m_MMStat; + int m_AStat; + UINT m_uMsg; + + char m_strMode[16]; +public: + CMMLink *m_pLink; +private: + void __fastcall CloseMMLink(void); + +public: + CLogLink(); + ~CLogLink(); + void SetHandle(HWND hMain, UINT uMsg); + BOOL IsEnabled(void){return m_Enabled;}; + void UpdateLink(int sw); + void Foreground(void); + BOOL IsError(void){return m_Error;}; + void ClearError(void){m_Error = 0;}; + BOOL __fastcall IsLink(void); + LPCSTR __fastcall GetSessionName(void); + + BOOL CheckLink(void); + BOOL TimerLogLink(void); + void Clear(void); + void SetFocus(void); + void SetCall(LPSTR pCall, int sw); + void FindCall(LPSTR pCall); + void Write(SDMMLOG *sp, int sw); + int AnaData(SDMMLOG *sp, COPYDATASTRUCT *cp); + + BOOL IsPolling(void){return m_Polling;}; + void SetPolling(int sw){m_Polling = sw;}; + void EventGetFreq(void); + void SetFreq(LPSTR pFreq); + void SetMode(LPCSTR pMode); + void __fastcall SetPTT(int ptt); + + void __fastcall SetTime(SYSTEMTIME *tp, int sw); + +public: + void __fastcall LoadMMLink(TMemIniFile *pIni); + void __fastcall SaveMMLink(TMemIniFile *pIni); + void __fastcall NotifySession(LPCSTR pSession); + int __fastcall QReturn(SDMMLOG *sp, const mmLOGDATA *pLog); + LPCSTR __fastcall GetItemName(void); + void __fastcall SetItemName(LPCSTR pName); + BOOL __fastcall IsCopyData(void); + + inline BOOL __fastcall GetPTTEnabled(void){return m_PTTEnabled;}; + inline void __fastcall SetPTTEnabled(BOOL e){m_PTTEnabled = e;}; +}; +extern CLogLink LogLink; +#endif + diff --git a/MMCG.DEF b/MMCG.DEF new file mode 100644 index 0000000..b78a832 --- /dev/null +++ b/MMCG.DEF @@ -0,0 +1,1776 @@ +!=========================================================================== +! AJA番号定義ファイル For MMTTY, MMSSTV, MMVARI +! +!※ 読みは<,>で区切って複数個記述する事ができます。ひらがなやカタカナ +! を記述しても良いでしょう。 +! +! 例> 2509 高槻市 TAKATUKI,たかつき,タカツキ,タカツキ +! +! ただし、あまりファイルサイズが大きくなると、レスポンスが悪くなり +! ますので注意が必要です。 +! +!※ このファイルをネット等に流通させる場合は、変更履歴を追加記載する +! 事をお勧めします。 +! +!<<<変更履歴>>> +! Feb 4, 1996 - 1029(あきる野市)追加 JE3HHT +! Jun 5, 1997 - 0134(北広島市)追加 JE3HHT +! Jun 5, 1997 - 2212(京田辺市)追加 JE3HHT +! Jan 10, 2000 - 0135,1231,1343,1422,2722,4029追加 +! SBAE=>SABAE,SINNANJO=>SINNANYOU,UDO=>UTO +! 27017,01029消滅 JQ3UDL +! Aug 25, 2010 - JARL公開のリストから再構築 JE3HHT +!========================================================================== +01 % HOKKAIDO +0101 札幌市 SAPPORO +0102 旭川市 ASAHIKAWA +0103 小樽市 OTARU +0104 函館市 HAKODATE +0105 室蘭市 MURORAN +0106 釧路市 KUSIRO +0107 帯広市 OBIHIRO +0108 北見市 KITAMI +0109 夕張市 YUBARI +0110 岩見沢市 IWAMIZAWA +0111 網走市 ABASIRI +0112 留萌市 RUMOI +0113 苫小牧市 TOMAKOMAI +0114 稚内市 WAKKANAI +0115 美唄市 BIBAI +0116 芦別市 ASIBETU +0117 江別市 EBETU +0118 赤平市 AKABIRA +0119 紋別市 MOMBETU +0120 士別市 SIBETU +0121 名寄市 NAYORO +0122 三笠市 MIKASA +0123 根室市 NEMURO +0124 千歳市 CITOSE +0125 滝川市 TAKIKAWA +0126 砂川市 SUNAGAWA +0127 歌志内市 UTASINAI +0128 深川市 FUKAGAWA +0129 富良野市 FURANO +0130 登別市 NOBORIBETU +0131 恵庭市 ENIWA +0132 亀田市* +0133 伊達市 DATE +0134 北広島市 KITAHIROSIMA +0135 石狩市 ISIKARI +0136 北斗市 HOKUTO +01001 阿寒群 AKAN +01002 足寄群 ASHORO +01003 厚岸群 ATUKESI +01004 厚田群* +01005 網走群 ABASIRI +01006 虻田群(後志) ABUTA,SIRIBESI +01007 虻田群(胆振) ABUTA,IBURI +01008 石狩群 ISIKARI +01009 磯谷群 ISOYA +01010 岩内群 IWANAI +01011 有珠群 USU +01012 歌棄群* +01013 浦河群 URAKAWA +01014 雨竜群(空知) URYU,SORACI +01015 枝幸群 ESASI +01016 奥尻群 OKUSIRI +01017 忍路群* +01018 河西群 KASAI +01019 河東群 KATO +01020 樺戸群 KABATO +01021 上磯群 KAMIISO +01022 上川群(十勝) KAMIKAWA,TOKACI +01023 上川群(上川) KAMIKAWA +01024 亀田群 KAMEDA +01025 茅部群 KAYABE +01026 川上群 KAWAKAMI +01027 釧路群 KUSIRO +01028 久遠群 KUDO +01029 札幌群* +01030 様似群 SAMANI +01031 沙流群 SARU +01032 静内群* +01033 標津群 SIBETU +01034 島牧群 SIMAMAKI +01035 積丹群 SHAKOTAN +01036 斜里群 SHARI +01037 白老群 SIRAOI +01038 白糠群 SIRANUKA +01039 寿都群 SUTTU +01040 瀬棚群 SETANA +01041 宗谷群 SOYA +01042 空知群(空知) SORACI +01043 空知群(上川) SORACI,KAMIKAWA +01044 千歳群* +01045 天塩群(留萌) TESIO,RUMOI +01046 天塩群(宗谷) TESIO,SOYA +01047 十勝群 TOKACI +01048 常呂群 TOKORO +01049 苫前群 TOMAMAE +01050 中川群(上川) NAKAGAWA,KAMIKAWA +01051 中川群(十勝) NAKAGAWA,TOKACI +01052 新冠群 NIIKAPPU +01053 爾志群 NISI +01054 根室群* +01055 野付群 NOTUKE +01056 花咲群* +01057 浜益群* +01058 美国群* +01059 檜山群 HIYAMA +01060 広尾群 HIROO +01061 太櫓群* +01062 古宇群 FURUU +01063 古平群 FURUBIRA +01064 幌泉群 HOROIZUMI +01065 幌別群* +01066 増毛群 MASIKE +01067 松前群 MATUMAE +01068 三石群* +01069 目梨群 MENASI +01070 紋別群 MOMBETU +01071 山越群 YAMAKOSI +01072 夕張群 YUBARI +01073 勇払群(胆振) YUFUTU,IBURI +01074 勇払群(上川) YUFUTU,KAMIKAWA +01075 余市群 YOICI +01076 利尻群 RISIRI +01077 留萌群 RUMOI +01078 礼文群 REBUN +01079 二海群 FUTAMI +01080 日高群 HIDAKA +01081 雨竜群(上川) URYU,KAMIKAWA +010101 札幌市中央区 CHUO +010102 札幌市北区 KITA +010103 札幌市東区 HIGASI +010104 札幌市白石区 SIROISI +010105 札幌市豊平区 TOYOHIRA +010106 札幌市南区 MINAMI +010107 札幌市西区 NISI +010108 札幌市厚別区 ATUBETU +010109 札幌市手稲区 TEINE +010110 札幌市清田区 KIYOTA +02 % AOMORI +0201 青森市 AOMORI +0202 弘前市 HIROSAKI +0203 八戸市 HACINOHE +0204 黒石市 KUROISI +0205 五所川原市 GOSHOGAWARA +0206 十和田市 TOWADA +0207 三沢市 MISAWA +0208 むつ市 MUTU +0209 つがる市 TUGARU +0210 平川市 HIRAKAWA +02001 上北群 KAMIKITA +02002 北津軽群 KITATUGARU +02003 三戸群 SANNOHE +02004 下北群 SIMOKITA +02005 中津軽群 NAKATUGARU +02006 西津軽群 NISITUGARU +02007 東津軽群 HIGASITUGARU +02008 南津軽群 MINAMITUGARU +03 % IWATE +0301 盛岡市 MORIOKA +0302 釜石市 KAMAISI +0303 宮古市 MIYAKO +0304 一関市 ICINOSEKI +0305 大船渡市 OFUNATO +0306 水沢市* +0307 花巻市 HANAMAKI +0308 北上市 KITAKAMI +0309 久慈市 KUJI +0310 遠野市 TONO +0311 陸前高田市 RIKUZENTAKATA +0312 江刺市* +0313 二戸市 NINOHE +0314 八幡平市 HACIMANTAI +0315 奥州市 OSHU +03001 胆沢群 ISAWA +03002 岩手群 IWATE +03003 江刺群* +03004 上閉伊群 KAMIHEI +03005 九戸群 KUNOHE +03006 気仙群 KESEN +03007 下閉伊群 SIMOHEI +03008 紫波群 SIWA +03009 西磐井群 NISIIWAI +03010 二戸群 NINOHE +03011 稗貫群* +03012 東磐井群 HIGASIIWAI +03013 和賀群 WAGA +04 % AKITA +0401 秋田市 AKITA +0402 能代市 NOSIRO +0403 大館市 ODATE +0404 横手市 YOKOTE +0405 本荘市* +0406 男鹿市 OGA +0407 湯沢市 YUZAWA +0408 大曲市* +0409 鹿角市 KAZUNO +0410 由利本荘市 YURIHONJO +0411 潟上市 KATAGAMI +0412 大仙市 DAISEN +0413 北秋田市 KITAAKITA +0414 にかほ市 NIKAHO +0415 仙北市 SENBOKU +04001 雄勝群 OGACI +04002 鹿角群 KAZUNO +04003 河辺群* +04004 北秋田群 KITAAKITA +04005 仙北群 SEMBOKU +04006 平鹿群* +04007 南秋田群 MINAMIAKITA +04008 山本群 YAMAMOTO +04009 由利群* +05 % YAMAGATA +0501 山形市 YAMAGATA +0502 米沢市 YONEZAWA +0503 鶴岡市 TURUOKA +0504 酒田市 SAKATA +0505 新庄市 SINJO +0506 寒河江市 SAGAE +0507 上山市 KAMINOYAMA +0508 村山市 MURAYAMA +0509 長井市 NAGAI +0510 天童市 TENDO +0511 東根市 HIGASINE +0512 尾花沢市 OBANAZAWA +0513 南陽市 NAN'YO +05001 飽海群 AKUMI +05002 北村山群 KITAMURAYAMA +05003 西置賜群 NISIOKITAMA +05004 西田川群* +05005 西村山群 NISIMURAYAMA +05006 東置賜群 HIGASIOKITAMA +05007 東田川群 HIGASITAGAWA +05008 東村山群 HIGASIMURAYAMA +05009 南置賜群* +05010 南村山群* +05011 最上群 MOGAMI +06 % MIYAZAKI +0601 仙台市 SENDAI +0602 石巻市 ISINOMAKI +0603 塩竈市 SIOGAMA +0604 古川市* +0605 気仙沼市 KESENNUMA +0606 白石市 SIROISI +0607 名取市 NATORI +0608 角田市 KAKUDA +0609 多賀城市 TAGAJO +0610 泉市* +0611 岩沼市 IWANUMA +0612 登米市 TOME +0613 栗原市 KURIHARA +0614 東松島市 HIGASIMATUSIMA +0615 大崎市 OSAKI +06001 伊具群 IGU +06002 牡鹿群 OSIKA +06003 刈田群 KATTA +06004 加美群 KAMI +06005 栗原群* +06006 黒川群 KUROKAWA +06007 志田群* +06008 柴田群 SIBATA +06009 玉造群* +06010 遠田群 TODA +06011 登米群* +06012 名取群* +06013 宮城群 MIYAGI +06014 本吉群 MOTOYOSI +06015 桃生群* +06016 亘理群 WATARI +060101 仙台市青葉区 AOBA +060102 仙台市宮城野区 MIYAGINO +060103 仙台市若林区 WAKABAYASI +060104 仙台市太白区 TAIHAKU +060105 仙台市泉区 IZUMI +07 % FUKUSIMA +0701 福島市 FUKUSIMA +0702 会津若松市 AIZUWAKAMATU +0703 郡山市 KORIYAMA +0704 平市* +0705 白河市 SIRAKAWA +0706 原町市* +0707 須賀川市 SUKAGAWA +0708 喜多方市 KITAKATA +0709 常磐市* +0710 磐城市* +0711 相馬市 SOMA +0712 内郷市* +0713 勿来市* +0714 二本松市 NIHONMATU +0715 いわき市 IWAKI +0716 若松市* +0717 田村市 TAMURA +0718 南相馬市 MINAMISOMA +0719 伊達市 DATE +0720 本宮市 MOTOMIYA +07001 安積群* +07002 安達群 ADACI +07003 石川群 ISIKAWA +07004 石城群* +07005 岩瀬群 IWASE +07006 大沼群 ONUMA +07007 河沼群 KAWANUMA +07008 北会津群* +07009 信夫群* +07010 相馬群 SOMA +07011 伊達群 DATE +07012 田村群 TAMURA +07013 西白河群 NISISIRAKAWA +07014 東白川群 HIGASISIRAKAWA +07015 双葉群 FUTABA +07016 南会津群 MINAMIAIZU +07017 耶麻群 YAMA +08 % NIGATA +0801 新潟市 NIIGATA +0802 長岡市 NAGAOKA +0803 高田市* +0804 三条市 SANJO +0805 柏崎市 KASIWAZAKI +0806 新発田市 SIBATA +0807 新津市* +0808 小千谷市 OJIYA +0809 加茂市 KAMO +0810 十日町市 TOKAMACI +0811 見附市 MITUKE +0812 村上市 MURAKAMI +0813 燕市 TUBAME +0814 直江津市* +0815 栃尾市* +0816 糸魚川市 ITOIGAWA +0817 新井市* +0818 五泉市 GOSEN +0819 両津市* +0820 白根市* +0821 豊栄市* +0822 上越市 JOETU +0823 阿賀野市 AGANO +0824 佐渡市 SADO +0825 魚沼市 UONUMA +0826 南魚沼市 MINAMIUONUMA +0827 妙高市 MYOKO +0828 胎内市 TAINAI +08001 岩船群 IWAFUNE +08002 刈羽群 KARIWA +08003 北魚沼群* +08004 北蒲原群 KITAKAMBARA +08005 古志群* +08006 佐渡群* +08007 三島群 SANTO +08008 中魚沼群 NAKAUONUMA +08009 中蒲原群* +08010 中頸城群* +08011 西蒲原群 NISIKAMBARA +08012 西頸城群* +08013 東蒲原群 HIGASIKAMBARA +08014 東頸城群* +08015 南魚沼群 MINAMIUONUMA +08016 南蒲原群 MINAMIKAMBARA +080101 新潟市北区 KITA +080102 新潟市東区 HIGASI +080103 新潟市中央区 CHUO +080104 新潟市江南区 KONAN +080105 新潟市秋葉区 AKIHA +080106 新潟市南区 MINAMI +080107 新潟市西区 NISI +080108 新潟市西蒲区 NISIKAN +09 % NAGANO +0901 長野市 NAGANO +0902 松本市 MATUMOTO +0903 上田市 UEDA +0904 岡谷市 OKAYA +0905 飯田市 IIDA +0906 諏訪市 SUWA +0907 須坂市 SUZAKA +0908 小諸市 KOMORO +0909 伊那市 INA +0910 駒ヶ根市 KOMAGANE +0911 中野市 NAKANO +0912 大町市 OMACI +0913 飯山市 IIYAMA +0914 茅野市 CINO +0915 塩尻市 SIOJIRI +0916 篠ノ井市* +0917 更埴市* +0918 佐久市 SAKU +0919 千曲市 CIKUMA +0920 東御市 TOUMI +0921 安曇野市 AZUMINO +09001 上伊那群 KAMIINA +09002 上高井群 KAMITAKAI +09003 上水内群 KAMIMINOCI +09004 木曽群 KISO +09005 北安曇群 KITAAZUMI +09006 北佐久群 KITASAKU +09007 更級群* +09008 下伊那群 SIMOINA +09009 下高井群 SIMOTAKAI +09010 下水内群 SIMOMINOCI +09011 諏訪群 SUWA +09012 小県群 CIISAGATA +09013 群(欠番)* +09014 埴科群 HANISINA +09015 東筑摩群 HIGASICIKUMA +09016 南安曇群* +09017 南佐久群 MINAMISAKU +10 % TOKYO +1001 23区* +1002 八王子市 HACIOJI +1003 立川市 TACIKAWA +1004 武蔵野市 MUSASINO +1005 三鷹市 MITAKA +1006 青梅市 OME +1007 府中市 FUCHU +1008 昭島市 AKISIMA +1009 調布市 CHOFU +1010 町田市 MACIDA +1011 小金井市 KOGANEI +1012 小平市 KODAIRA +1013 日野市 HINO +1014 東村山市 HIGASIMURAYAMA +1015 国分寺市 KOKUBUNJI +1016 国立市 KUNITACI +1017 保谷市* +1018 田無市* +1019 福生市 FUSSA +1020 狛江市 KOMAE +1021 東大和市 HIGASIYAMATO +1022 清瀬市 KIYOSE +1023 東久留米市 HIGASIKURUME +1024 武蔵村山市 MUSASIMURAYAMA +1025 多摩市 TAMA +1026 稲城市 INAGI +1027 秋川市* +1028 羽村市 HAMURA +1029 あきる野市 AKIRUNO +1030 西東京市 NISITOKYO +10001 北多摩群* +10002 西多摩群 NISITAMA +10003 南多摩群* +10004 大島支庁群 OSIMA-SICHO +10005 三宅支庁群 MIYAKE-SICHO +10006 八丈支庁群 HACIJO-SICHO +10007 小笠原支庁群 OGASAWARA-SICHO +100101 東京都千代田区 CIYODA +100102 東京都中央区 CHUO +100103 東京都港区 MINATO +100104 東京都新宿区 SINJUKU +100105 東京都文京区 BUNKYO +100106 東京都台東区 TAITO +100107 東京都墨田区 SUMIDA +100108 東京都江東区 KOTO +100109 東京都品川区 SINAGAWA +100110 東京都目黒区 MEGURO +100111 東京都大田区 OTA +100112 東京都世田谷区 SETAGAYA +100113 東京都渋谷区 SIBUYA +100114 東京都中野区 NAKANO +100115 東京都杉並区 SUGINAMI +100116 東京都豊島区 TOSIMA +100117 東京都北区 KITA +100118 東京都荒川区 ARAKAWA +100119 東京都板橋区 ITABASI +100120 東京都練馬区 NERIMA +100121 東京都足立区 ADACI +100122 東京都葛飾区 KATUSIKA +100123 東京都江戸川区 EDOGAWA +11 % KANAGAWA +1101 横浜市 YOKOHAMA +1102 横須賀市 YOKOSUKA +1103 川崎市 KAWASAKI +1104 平塚市 HIRATUKA +1105 鎌倉市 KAMAKURA +1106 藤沢市 FUJISAWA +1107 小田原市 ODAWARA +1108 茅ヶ崎市 CIGASAKI +1109 逗子市 ZUSI +1110 相模原市 SAGAMIHARA +1111 三浦市 MIURA +1112 秦野市 HADANO +1113 厚木市 ATUGI +1114 大和市 YAMATO +1115 伊勢原市 ISEHARA +1116 海老名市 EBINA +1117 座間市 ZAMA +1118 南足柄市 MINAMIASIGARA +1119 綾瀬市 AYASE +11001 愛甲群 AIKO +11002 足柄上群 ASIGARAKAMI +11003 足柄下群 ASIGARASIMO +11004 高座群 KOZA +11005 津久井群* +11006 中群 NAKA +11007 三浦群 MIURA +110101 横浜市鶴見区 TURUMI +110102 横浜市神奈川区 KANAGAWA +110103 横浜市西区 NISI +110104 横浜市中区 NAKA +110105 横浜市南区 MINAMI +110106 横浜市保土ヶ谷区 HODOGAYA +110107 横浜市磯子区 ISOGO +110108 横浜市金沢区 KANAZAWA +110109 横浜市港北区 KOHOKU +110110 横浜市戸塚区 TOTUKA +110111 横浜市港南区 KONAN +110112 横浜市旭区 ASAHI +110113 横浜市緑区 MIDORI +110114 横浜市瀬谷区 SEYA +110115 横浜市栄区 SAKAE +110116 横浜市泉区 IZUMI +110117 横浜市青葉区 AOBA +110118 横浜市都筑区 TUZUKI +110301 川崎市川崎区 KAWASAKI +110302 川崎市幸区 SAIWAI +110303 川崎市中原区 NAKAHARA +110304 川崎市高津区 TAKATU +110305 川崎市多摩区 TAMA +110306 川崎市宮前区 MIYAMAE +110307 川崎市麻生区 ASAO +111001 相模原市緑区 MIDORI +111002 相模原市中央区 CHUO +111003 相模原市南区 MINAMI +12 % CIBA +1201 千葉市 CIBA +1202 銚子市 CHOSI +1203 市川市 ICIKAWA +1204 船橋市 FUNABASI +1205 館山市 TATEYAMA +1206 木更津市 KISARAZU +1207 松戸市 MATUDO +1208 野田市 NODA +1209 佐原市* +1210 茂原市 MOBARA +1211 成田市 NARITA +1212 佐倉市 SAKURA +1213 東金市 TOGANE +1214 八日市場市* +1215 旭市 ASAHI +1216 習志野市 NARASINO +1217 柏市 KASIWA +1218 勝浦市 KATUURA +1219 市原市 ICIHARA +1220 流山市 NAGAREYAMA +1221 八千代市 YACIYO +1222 我孫子市 ABIKO +1223 鴨川市 KAMOGAWA +1224 君津市 KIMITU +1225 鎌ヶ谷市 KAMAGAYA +1226 富津市 FUTTU +1227 浦安市 URAYASU +1228 四街道市 YOTUKAIDO +1229 袖ヶ浦市 SODEGAURA +1230 八街市 YACIMATA +1231 印西市 INZAI +1232 白井市 SIROI +1233 富里市 TOMISATO +1234 南房総市 MINAMIBOSO +1235 匝瑳市 SOSA +1236 香取市 KATORI +1237 山武市 SANMU +1238 いすみ市 ISUMI +12001 安房群 AWA +12002 夷隅群 ISUMI +12003 市原群* +12004 印旛群 INBA +12005 海上群* +12006 香取群 KATORI +12007 君津群* +12008 山武群 SAMBU +12009 匝瑳群* +12010 千葉群* +12011 長生群 CHOSEI +12012 東葛飾群* +120101 千葉市中央区 CHUO +120102 千葉市花見川区 HANAMIGAWA +120103 千葉市稲毛区 INAGE +120104 千葉市若葉区 WAKABA +120105 千葉市緑区 MIDORI +120106 千葉市美浜区 MIHAMA +13 % SAITAMA +1301 浦和市* +1302 川越市 KAWAGOE +1303 熊谷市 KUMAGAYA +1304 川口市 KAWAGUCI +1305 大宮市* +1306 行田市 GYODA +1307 秩父市 CICIBU +1308 所沢市 TOKOROZAWA +1309 飯能市 HANNO +1310 加須市 KAZO +1311 本庄市 HONJO +1312 東松山市 HIGASIMATUYAMA +1313 岩槻市* +1314 春日部市 KASUKABE +1315 狭山市 SAYAMA +1316 羽生市 HANYU +1317 鴻巣市 KONOSU +1318 深谷市 FUKAYA +1319 上尾市 AGEO +1320 与野市* +1321 草加市 SOKA +1322 越谷市 KOSIGAYA +1323 蕨市 WARABI +1324 戸田市 TODA +1325 入間市 IRUMA +1326 鳩ヶ谷市 HATOGAYA +1327 朝霞市 ASAKA +1328 志木市 SIKI +1329 和光市 WAKO +1330 新座市 NIIZA +1331 桶川市 OKEGAWA +1332 久喜市 KUKI +1333 北本市 KITAMOTO +1334 八潮市 YASIO +1335 上福岡市* +1336 富士見市 FUJIMI +1337 三郷市 MISATO +1338 蓮田市 HASUDA +1339 坂戸市 SAKADO +1340 幸手市 SATTE +1341 鶴ヶ島市 TURUGASIMA +1342 日高市 HIDAKA +1343 吉川市 YOSIKAWA +1344 さいたま市 SAITAMA +1345 ふじみ野市 FUJIMINO +13001 入間群 IRUMA +13002 大里群 OSATO +13003 北足立群 KITAADACI +13004 北葛飾群 KITAKATUSIKA +13005 北埼玉群* +13006 児玉群 KODAMA +13007 秩父群 CICIBU +13008 比企群 HIKI +13009 南埼玉群 MINAMISAITAMA +134401 さいたま市西区 NISI +134402 さいたま市北区 KITA +134403 さいたま市大宮区 OMIYA +134404 さいたま市見沼区 MINUMA +134405 さいたま市中央区 CHUO +134406 さいたま市桜区 SAKURA +134407 さいたま市浦和区 URAWA +134408 さいたま市南区 MINAMI +134409 さいたま市緑区 MIDORI +134410 さいたま市岩槻区 IWATUKI +14 % IBARAGI +1401 水戸市 MITO +1402 日立市 HITACI +1403 土浦市 TUCIURA +1404 古河市 KOGA +1405 石岡市 ISIOKA +1406 下館市* +1407 結城市 YUKI +1408 龍ヶ崎市 RYUGASAKI +1409 那珂湊市* +1410 下妻市 SIMOTUMA +1411 水海道市* +1412 常陸太田市 HITACIOTA +1413 勝田市* +1414 高萩市 TAKAHAGI +1415 北茨城市 KITAIBARAKI +1416 笠間市 KASAMA +1417 取手市 TORIDE +1418 岩井市* +1419 牛久市 USIKU +1420 つくば市 TUKUBA +1421 ひたちなか市 HITACINAKA +1422 鹿嶋市 KASIMA +1423 潮来市 ITAKO +1424 守谷市 MORIYA +1425 常陸大宮市 HITACIOMIYA +1426 那珂市 NAKA +1427 筑西市 CIKUSEI +1428 坂東市 BANDOU +1429 稲敷市 INASIKI +1430 かすみがうら市 KASUMIGAURA +1431 桜川市 SAKURAGAWA +1432 神栖市 KAMISU +1433 行方市 NAMEGATA +1434 鉾田市 HOKOTA +1435 常総市 JOSO +1436 つくばみらい市 TUKUBAMIRAI +1437 小美玉市 OMITAMA +14001 稲敷群 INASIKI +14002 鹿島群* +14003 北相馬群 KITASOMA +14004 久慈群 KUJI +14005 猿島群 SASIMA +14006 多賀群* +14007 筑波群* +14008 那珂群 NAKA +14009 行方群* +14010 新治群* +14011 西茨城群* +14012 東茨城群 HIGASIIBARAKI +14013 真壁群* +14014 結城群 YUKI +15 % TOCIGI +1501 宇都宮市 UTUNOMIYA +1502 足利市 ASIKAGA +1503 栃木市 TOCIGI +1504 佐野市 SANO +1505 鹿沼市 KANUMA +1506 日光市 NIKKO +1507 今市市* +1508 小山市 OYAMA +1509 真岡市 MOOKA +1510 大田原市 OTAWARA +1511 矢板市 YAITA +1512 黒磯市* +1513 那須塩原市 NASUSIOBARA +1514 さくら市 SAKURA +1515 那須烏山市 NASUKARASUYAMA +1516 下野市 SIMOTUKE +15001 足利群* +15002 安蘇群* +15003 上都賀群 KAMITUGA +15004 河内群 KAWACI +15005 塩谷群 SIOYA +15006 下都賀群 SIMOTUGA +15007 那須群 NASU +15008 芳賀群 HAGA +16 % GUNMA +1601 前橋市 MAEBASI +1602 高崎市 TAKASAKI +1603 桐生市 KIRYU +1604 伊勢崎市 ISESAKI +1605 太田市 OTA +1606 沼田市 NUMATA +1607 館林市 TATEBAYASI +1608 渋川市 SIBUKAWA +1609 藤岡市 FUJIOKA +1610 富岡市 TOMIOKA +1611 安中市 ANNAKA +1612 みどり市 MIDORI +16001 吾妻群 AGATUMA +16002 碓氷群* +16003 邑楽群 ORA +16004 甘楽群 KANRA +16005 北群馬群 KITAGUMMA +16006 群馬群* +16007 佐波群 SAWA +16008 勢多群* +16009 多野群 TANO +16010 利根群 TONE +16011 新田群* +16012 山田群* +17 % YAMANASI +1701 甲府市 KOFU +1702 富士吉田市 FUJIYOSIDA +1703 塩山市* +1704 都留市 TURU +1705 山梨市 YAMANASI +1706 大月市 OTUKI +1707 韮崎市 NIRASAKI +1708 南アルプス市 MINAMI-ALPS +1709 北杜市 HOKUTO +1710 甲斐市 KAI +1711 笛吹市 FUEFUKI +1712 上野原市 UENOHARA +1713 甲州市 KOSHU +1714 中央市 CHUO +17001 北巨摩群* +17002 北都留群 KITATURU +17003 中巨摩群 NAKAKOMA +17004 西八代群 NISIYATUSIRO +17005 東八代群* +17006 東山梨群* +17007 南巨摩群 MINAMIKOMA +17008 南都留群 MINAMITURU +18 % SIZUOKA +1801 静岡市 SIZUOKA +1802 浜松市 HAMAMATU +1803 沼津市 NUMAZU +1804 清水市* +1805 熱海市 ATAMI +1806 三島市 MISIMA +1807 富士宮市 FUJINOMIYA +1808 伊東市 ITO +1809 島田市 SIMADA +1810 吉原市* +1811 磐田市 IWATA +1812 焼津市 YAIZU +1813 富士市 FUJI +1814 掛川市 KAKEGAWA +1815 藤枝市 FUJIEDA +1816 御殿場市 GOTEMBA +1817 袋井市 FUKUROI +1818 天竜市* +1819 浜北市* +1820 下田市 SIMODA +1821 裾野市 SUSONO +1822 湖西市 KOSAI +1823 伊豆市 IZU +1824 御前崎市 OMAEZAKI +1825 菊川市 KIKUGAWA +1826 伊豆の国市 IZUNOKUNI +1827 牧之原市 MAKINOHARA +18001 安倍群* +18002 引佐群* +18003 庵原群* +18004 磐田群* +18005 小笠群* +18006 賀茂群 KAMO +18007 志太群* +18008 周智群 SHUCI +18009 駿東群 SUNTO +18010 田方群 TAGATA +18011 榛原群 HAIBARA +18012 浜名群* +18013 富士群* +180101 静岡市葵区 AOI +180102 静岡市駿河区 SURUGA +180103 静岡市清水区 SIMIZU +180201 浜松市中区 NAKA +180202 浜松市東区 HIGASI +180203 浜松市西区 NISI +180204 浜松市南区 MINAMI +180205 浜松市北区 KITA +180206 浜松市浜北区 HAMAKITA +180207 浜松市天竜区 TENRYU +19 % GIFU +1901 岐阜市 GIFU +1902 大垣市 OGAKI +1903 高山市 TAKAYAMA +1904 多治見市 TAJIMI +1905 関市 SEKI +1906 中津川市 NAKATUGAWA +1907 美濃市 MINO +1908 瑞浪市 MIZUNAMI +1909 羽島市 HASIMA +1910 恵那市 ENA +1911 美濃加茂市 MINOKAMO +1912 土岐市 TOKI +1913 各務原市 KAKAMIGAHARA +1914 可児市 KANI +1915 山県市 YAMAGATA +1916 瑞穂市 MIZUHO +1917 飛騨市 HIDA +1918 本巣市 MOTOSU +1919 郡上市 GUJO +1920 下呂市 GERO +1921 海津市 KAIZU +19001 安八群 AMPACI +19002 稲葉群* +19003 揖斐群 IBI +19004 恵那群* +19005 大野群 ONO +19006 海津群* +19007 可児群 KANI +19008 加茂群 KAMO +19009 郡上群* +19010 土岐群* +19011 羽島群 HASIMA +19012 不破群 FUWA +19013 益田群* +19014 武儀群* +19015 本巣群 MOTOSU +19016 山県群* +19017 養老群 YORO +19018 吉城群* +20 % AICI +2001 名古屋市 NAGOYA +2002 豊橋市 TOYOHASI +2003 岡崎市 OKAZAKI +2004 一宮市 ICINOMIYA +2005 瀬戸市 SETO +2006 半田市 HANDA +2007 春日井市 KASUGAI +2008 豊川市 TOYOKAWA +2009 津島市 TUSIMA +2010 碧南市 HEKINAN +2011 刈谷市 KARIYA +2012 豊田市 TOYOTA +2013 安城市 ANJO +2014 西尾市 NISIO +2015 蒲郡市 GAMAGORI +2016 犬山市 INUYAMA +2017 常滑市 TOKONAME +2018 守山市* +2019 江南市 KONAN +2020 尾西市* +2021 小牧市 KOMAKI +2022 稲沢市 INAZAWA +2023 新城市 SINSIRO +2024 東海市 TOKAI +2025 大府市 OBU +2026 知多市 CITA +2027 高浜市 TAKAHAMA +2028 知立市 CIRYU +2029 尾張旭市 OWARIASAHI +2030 岩倉市 IWAKURA +2031 豊明市 TOYOAKE +2032 日進市 NISSIN +2033 田原市 TAHARA +2034 愛西市 AISAI +2035 清須市 KIYOSU +2036 北名古屋市 KITANAGOYA +2037 弥富市 YATOMI +2038 みよし市 MIYOSI +2039 あま市 AMA +20001 愛知群 AICI +20002 渥美群* +20003 海部群 AMA +20004 北設楽群 KITASITARA +20005 知多群 CITA +20006 中島群* +20007 西春日井群 NISIKASUGAI +20008 西加茂群* +20009 丹羽群 NIWA +20010 額田群 NUKATA +20011 葉栗群* +20012 幡豆群 HAZU +20013 東春日井群* +20014 東加茂群* +20015 碧海群* +20016 宝飯群* +20017 南設楽群* +20018 八名群* +200101 名古屋市千種区 CIKUSA +200102 名古屋市東区 HIGASI +200103 名古屋市北区 KITA +200104 名古屋市西区 NISI +200105 名古屋市中村区 NAKAMURA +200106 名古屋市中区 NAKA +200107 名古屋市昭和区 SHOWA +200108 名古屋市瑞穂区 MIZUHO +200109 名古屋市熱田区 ATUTA +200110 名古屋市中川区 NAKAGAWA +200111 名古屋市港区 MINATO +200112 名古屋市南区 MINAMI +200113 名古屋市守山区 MORIYAMA +200114 名古屋市緑区 MIDORI +200115 名古屋市名東区 MEITO +200116 名古屋市天白区 TENPAKU +21 % MIE +2101 津市 TU +2102 四日市市 YOKKAICI +2103 伊勢市 ISE +2104 松阪市 MATUSAKA +2105 桑名市 KUWANA +2106 上野市* +2107 鈴鹿市 SUZUKA +2108 名張市 NABARI +2109 尾鷲市 OWASE +2110 亀山市 KAMEYAMA +2111 鳥羽市 TOBA +2112 熊野市 KUMANO +2113 久居市* +2114 宇治山田市* +2115 いなべ市 INABE +2116 志摩市 SIMA +2117 伊賀市 IGA +21001 安芸群* +21002 安濃群* +21003 阿山群* +21004 飯南群* +21005 一志群* +21006 員弁群 INABE +21007 河芸群* +21008 北牟婁群 KITAMURO +21009 桑名群 KUWANA +21010 志摩群* +21011 鈴鹿群* +21012 多気群 TAKI +21013 名賀群* +21014 三重群 MIE +21015 南牟婁群 MINAMIMURO +21016 度会群 WATARAI +22 % KYOTO +2201 京都市 KYOTO +2202 福知山市 FUKUCIYAMA +2203 舞鶴市 MAIZURU +2204 綾部市 AYABE +2205 宇治市 UJI +2206 宮津市 MIYAZU +2207 亀岡市 KAMEOKA +2208 城陽市 JOYO +2209 長岡京市 NAGAOKAKYO +2210 向日市 MUKO +2211 八幡市 YAWATA +2212 京田辺市 KYOTANABE +2213 京丹後市 KYOTANGO +2214 南丹市 NANTAN +2215 木津川市 KIZUGAWA +22001 天田群* +22002 何鹿群* +22003 乙訓群 OTOKUNI +22004 加佐群* +22005 北桑田群* +22006 久世群 KUSE +22007 熊野群* +22008 相楽群 SORAKU +22009 竹野群* +22010 綴喜群 TUZUKI +22011 中群* +22012 船井群 FUNAI +22013 南桑田群* +22014 与謝群 YOZA +220101 京都市北区 KITA +220102 京都市上京区 KAMIGYO +220103 京都市左京区 SAKYO +220104 京都市中京区 NAKAGYO +220105 京都市東山区 HIGASIYAMA +220106 京都市下京区 SIMOGYO +220107 京都市南区 MINAMI +220108 京都市右京区 UKYO +220109 京都市伏見区 FUSIMI +220110 京都市山科区 YAMASINA +220111 京都市西京区 NISIKYO +23 % SIGA +2301 大津市 OTU +2302 彦根市 HIKONE +2303 長浜市 NAGAHAMA +2304 近江八幡市 OMIHACIMAN +2305 八日市市* +2306 草津市 KUSATU +2307 守山市 MORIYAMA +2308 栗東市 RITTO +2309 甲賀市 KOKA +2310 野洲市 YASU +2311 湖南市 KONAN +2312 高島市 TAKASIMA +2313 東近江市 HIGASIOUMI +2314 米原市 MAIBARA +23001 伊香群* +23002 犬上群 INUKAMI +23003 愛知群 ECI +23004 蒲生群 GAMOU +23005 神崎群* +23006 栗太群* +23007 甲賀群* +23008 坂田群* +23009 滋賀群* +23010 高島群* +23011 東浅井群* +23012 野洲群* +24 % NARA +2401 奈良市 NARA +2402 大和高田市 YAMATOTAKADA +2403 大和郡山市 YAMATOKORIYAMA +2404 天理市 TENRI +2405 橿原市 KASIHARA +2406 桜井市 SAKURAI +2407 五條市 GOJO +2408 御所市 GOSE +2409 生駒市 IKOMA +2410 香芝市 KASIBA +2411 葛城市 KATURAGI +2412 宇陀市 UDA +24001 生駒群 IKOMA +24002 宇陀群 UDA +24003 宇智群* +24004 北葛城群 KITAKATURAGI +24005 磯城群 SIKI +24006 添上群* +24007 高市群 TAKAICI +24008 南葛城群* +24009 山辺群 YAMABE +24010 吉野群 YOSINO +25 % OSAKA +2501 大阪市 OSAKA +2502 堺市 SAKAI +2503 岸和田市 KISIWADA +2504 豊中市 TOYONAKA +2505 布施市* +2506 池田市 IKEDA +2507 吹田市 SUITA +2508 泉大津市 IZUMIOTU +2509 高槻市 TAKATUKI +2510 貝塚市 KAIZUKA +2511 守口市 MORIGUCI +2512 枚方市 HIRAKATA +2513 茨木市 IBARAKI +2514 八尾市 YAO +2515 泉佐野市 IZUMISANO +2516 富田林市 TONDABAYASI +2517 寝屋川市 NEYAGAWA +2518 河内長野市 KAWACINAGANO +2519 枚岡市* +2520 河内市* +2521 松原市 MATUBARA +2522 大東市 DAITO +2523 和泉市 IZUMI +2524 箕面市 MINO +2525 柏原市 KASIWARA +2526 羽曳野市 HABIKINO +2527 門真市 KADOMA +2528 摂津市 SETTU +2529 藤井寺市 FUJIIDERA +2530 高石市 TAKAISI +2531 東大阪市 HIGASIOSAKA +2532 泉南市 SENNAN +2533 四條畷市 SIJONAWATE +2534 交野市 KATANO +2535 大阪狭山市 OSAKASAYAMA +2536 阪南市 HANNAN +25001 北河内群* +25002 泉南群 SENNAN +25003 泉北群 SENBOKU +25004 豊能群 TOYONO +25005 中河内群* +25006 三島群 MISIMA +25007 南河内群 MINAMIKAWACI +250101 大阪市北区 KITA +250102 大阪市都島区 MIYAKOJIMA +250103 大阪市福島区 FUKUSIMA +250104 大阪市此花区 KONOHANA +250105 大阪市東区* +250106 大阪市西区 NISI +250107 大阪市港区 MINATO +250108 大阪市大正区 TAISHO +250109 大阪市天王寺区 TENNOJI +250110 大阪市南区* +250111 大阪市浪速区 NANIWA +250112 大阪市大淀区* +250113 大阪市西淀川区 NISIYODOGAWA +250114 大阪市東淀川区 HIGASIYODOGAWA +250115 大阪市東成区 HIGASINARI +250116 大阪市生野区 IKUNO +250117 大阪市旭区 ASAHI +250118 大阪市城東区 JOTO +250119 大阪市阿倍野区 ABENO +250120 大阪市住吉区 SUMIYOSI +250121 大阪市東住吉区 HIGASISUMIYOSI +250122 大阪市西成区 NISINARI +250123 大阪市淀川区 YODOGAWA +250124 大阪市鶴見区 TURUMI +250125 大阪市住之江区 SUMINOE +250126 大阪市平野区 HIRANO +250127 大阪市中央区 CHUO +250201 堺市堺区 SAKAI +250202 堺市中区 NAKA +250203 堺市東区 HIGASI +250204 堺市西区 NISI +250205 堺市南区 MINAMI +250206 堺市北区 KITA +250207 堺市美原区 MIHARA +26 % WAKAYAMA +2601 和歌山市 WAKAYAMA +2602 新宮市 SINGU +2603 海南市 KAINAN +2604 田辺市 TANABE +2605 御坊市 GOBO +2606 橋本市 HASIMOTO +2607 有田市 ARIDA +2608 紀の川市 KINOKAWA +2609 岩出市 IWADE +26001 有田群 ARIDA +26002 伊都群 ITO +26003 海草群 KAISO +26004 那賀群* +26005 西牟婁群 NISIMURO +26006 東牟婁群 HIGASIMURO +26007 日高群 HIDAKA +27 % HYOGO +2701 神戸市 KOBE +2702 姫路市 HIMEJI +2703 尼崎市 AMAGASAKI +2704 明石市 AKASI +2705 西宮市 NISINOMIYA +2706 洲本市 SUMOTO +2707 芦屋市 ASIYA +2708 伊丹市 ITAMI +2709 相生市 AIOI +2710 豊岡市 TOYOOKA +2711 加古川市 KAKOGAWA +2712 龍野市* +2713 赤穂市 AKO +2714 西脇市 NISIWAKI +2715 宝塚市 TAKARAZUKA +2716 三木市 MIKI +2717 高砂市 TAKASAGO +2718 川西市 KAWANISI +2719 小野市 ONO +2720 三田市 SANDA +2721 加西市 KASAI +2722 篠山市 SASAYAMA +2723 養父市 YABU +2724 丹波市 TANBA +2725 南あわじ市 MINAMIAWAJI +2726 朝来市 ASAGO +2727 淡路市 AWAJI +2728 宍粟市 SISO +2729 加東市 KATO +2730 たつの市 TATUNO +27001 赤穂群 AKOU +27002 朝来群* +27003 有馬群* +27004 出石群* +27005 揖保群 IBO +27006 印南群* +27007 加古群 KAKO +27008 加西群* +27009 加東群* +27010 川辺群 KAWABE +27011 神崎群 KANZAKI +27012 城崎群* +27013 佐用群 SAYO +27014 飾磨群* +27015 宍粟群* +27016 多可群 TAKA +27017 多紀群* +27018 津名群* +27019 氷上群* +27020 美方群 MIKATA +27021 美嚢群* +27022 三原群* +27023 武庫群* +27024 養父群* +270101 神戸市東灘区 HIGASINADA +270102 神戸市灘区 NADA +270103 神戸市兵庫区 HYOGO +270104 神戸市長田区 NAGATA +270105 神戸市須磨区 SUMA +270106 神戸市垂水区 TARUMI +270107 神戸市北区 KITA +270108 神戸市中央区 CHUO +270109 神戸市西区 NISI +270110 神戸市葺合区* +270111 神戸市生田区* +28 % TOYAMA +2801 富山市 TOYAMA +2802 高岡市 TAKAOKA +2803 新湊市* +2804 魚津市 UOZU +2805 氷見市 HIMI +2806 滑川市 NAMERIKAWA +2807 黒部市 KUROBE +2808 砺波市 TONAMI +2809 小矢部市 OYABE +2810 南砺市 NANTO +2811 射水市 IMIZU +28001 射水群* +28002 上新川群* +28003 下新川群 SIMONIIKAWA +28004 中新川群 NAKANIIKAWA +28005 西砺波群* +28006 婦負群* +28007 氷見群* +28008 東砺波群* +29 % FUKUI +2901 福井市 FUKUI +2902 敦賀市 TURUGA +2903 武生市* +2904 小浜市 OBAMA +2905 大野市 ONO +2906 勝山市 KATUYAMA +2907 鯖江市 SABAE +2908 あわら市 AWARA +2909 越前市 ECIZEN +2910 坂井市 SAKAI +29001 足羽群* +29002 今立群 IMADATE +29003 大飯群 OI +29004 大野群* +29005 遠敷群* +29006 坂井群* +29007 敦賀群* +29008 南条群 NANJO +29009 丹生群 NYUU +29010 三方群 MIKATA +29011 吉田群 YOSIDA +29012 三方上中群 MIKATAKAMINAKA +30 % ISIKAWA +3001 金沢市 KANAZAWA +3002 七尾市 NANAO +3003 小松市 KOMATU +3004 輪島市 WAJIMA +3005 珠洲市 SUZU +3006 加賀市 KAGA +3007 羽咋市 HAKUI +3008 松任市* +3009 かほく市 KAHOKU +3010 白山市 HAKUSAN +3011 能美市 NOMI +30001 石川群 ISIKAWA +30002 江沼群* +30003 鹿島群 KASIMA +30004 河北群 KAHOKU +30005 珠洲群* +30006 能美群 NOMI +30007 羽咋群 HAKUI +30008 鳳至群* +30009 鳳珠群 HOUSU +31 % OKAYAMA +3101 岡山市 OKAYAMA +3102 倉敷市 KURASIKI +3103 津山市 TUYAMA +3104 玉野市 TAMANO +3105 児島市* +3106 玉島市* +3107 笠岡市 KASAOKA +3108 西大寺市* +3109 井原市 IBARA +3110 総社市 SOJA +3111 高梁市 TAKAHASI +3112 新見市 NIIMI +3113 備前市 BIZEN +3114 瀬戸内市 SETOUCI +3115 赤磐市 AKAIWA +3116 真庭市 MANIWA +3117 美作市 MIMASAKA +3118 浅口市 ASAKUCI +31001 英田群 AIDA +31002 赤磐群* +31003 浅口群 ASAKUCI +31004 阿哲群* +31005 邑久群* +31006 小田群 ODA +31007 勝田群 KATUTA +31008 川上群* +31009 吉備群* +31010 久米群 KUME +31011 児島群* +31012 後月群* +31013 上道群* +31014 上房群* +31015 都窪群 TUKUBO +31016 苫田群 TOMATA +31017 真庭群 MANIWA +31018 御津群* +31019 和気群 WAKE +31020 加賀群 KAGA +310101 岡山市北区 KITA +310102 岡山市中区 NAKA +310103 岡山市東区 HINAGASI +310104 岡山市南区 MINAMI +32 % SIMANE +3201 松江市 MATUE +3202 浜田市 HAMADA +3203 出雲市 IZUMO +3204 益田市 MASUDA +3205 大田市 ODA +3206 安来市 YASUGI +3207 江津市 GOTU +3208 平田市* +3209 雲南市 UNNAN +32001 安濃群* +32002 海士群* +32003 飯石群 IISI +32004 邑智群 OCI +32005 大原群* +32006 隠岐群 OKI +32007 隠地群* +32008 鹿足群 KANOASI +32009 周吉群* +32010 知夫群* +32011 那賀群* +32012 仁多群 NITA +32013 迩摩群* +32014 能義群* +32015 簸川群 HIKAWA +32016 美濃群* +32017 八束群 YATUKA +33 % YAMAGUCI +3301 山口市 YAMAGUCI +3302 下関市 SIMONOSEKI +3303 宇部市 UBE +3304 萩市 HAGI +3305 徳山市* +3306 防府市 HOFU +3307 下松市 KUDAMATU +3308 岩国市 IWAKUNI +3309 小野田市* +3310 光市 HIKARI +3311 長門市 NAGATO +3312 柳井市 YANAI +3313 美祢市 MINE +3314 新南陽市* +3315 周南市 SHUNAN +3316 山陽小野田市 SAN'YOONODA +33001 厚狭群* +33002 阿武群 ABU +33003 大島群 OSIMA +33004 大津群* +33005 玖珂群 KUGA +33006 熊毛群 KUMAGE +33007 佐波群* +33008 都濃群* +33009 豊浦群* +33010 美祢群* +33011 吉敷群* +34 % TOTTRI +3401 鳥取市 TOTTORI +3402 倉吉市 KURAYOSI +3403 米子市 YONAGO +3404 境港市 SAKAIMINATO +34001 岩美群 IWAMI +34002 気高群* +34003 西伯群 SAIHAKU +34004 東伯群 TOHAKU +34005 日野群 HINO +34006 八頭群 YAZU +35 % HIROSIMA +3501 広島市 HIROSIMA +3502 呉市 KURE +3503 竹原市 TAKEHARA +3504 三原市 MIHARA +3505 尾道市 ONOMICI +3506 因島市* +3507 松永市* +3508 福山市 FUKUYAMA +3509 府中市 FUCHU +3510 三次市 MIYOSI +3511 庄原市 SYOUBARA +3512 大竹市 OTAKE +3513 東広島市 HIGASIHIROSIMA +3514 廿日市市 HATUKAICI +3515 安芸高田市 AKITAKATA +3516 江田島市 ETAJIMA +35001 安芸群 AKI +35002 安佐群* +35003 芦品群* +35004 賀茂群* +35005 甲奴群* +35006 佐伯群* +35007 神石群 JINSEKI +35008 世羅群 SERA +35009 高田群* +35010 豊田群 TOYOTA +35011 沼隈群* +35012 比婆群* +35013 深安群* +35014 双三群* +35015 御調群* +35016 山県群 YAMAGATA +350101 広島市中区 NAKA +350102 広島市東区 HIGASI +350103 広島市南区 MINAMI +350104 広島市西区 NISI +350105 広島市安佐南区 ASAMINAMI +350106 広島市安佐北区 ASAKITA +350107 広島市安芸区 AKI +350108 広島市佐伯区 SAEKI +36 % KAGAWA +3601 高松市 TAKAMATU +3602 丸亀市 MARUGAME +3603 坂出市 SAKAIDE +3604 善通寺市 ZENTUJI +3605 観音寺市 KAN'ONJI +3606 さぬき市 SANUKI +3607 東かがわ市 HIGASIKAGAWA +3608 三豊市 MITOYO +36001 綾歌群 AYAUTA +36002 大川群* +36003 香川群 KAGAWA +36004 木田群 KITA +36005 小豆群 SYOZU +36006 仲多度群 NAKATADO +36007 三豊群* +37 % TOKUSIMA +3701 徳島市 TOKUSIMA +3702 鳴門市 NARUTO +3703 小松島市 KOMATUSIMA +3704 阿南市 ANAN +3705 吉野川市 YOSINOGAWA +3706 阿波市 AWA +3707 美馬市 MIMA +3708 三好市 MIYOSI +37001 阿波群* +37002 板野群 ITANO +37003 麻植群* +37004 海部群 KAIFU +37005 勝浦群 KATUURA +37006 那賀群 NAKA +37007 名西群 MYOZAI +37008 名東群 MYODO +37009 美馬群 MIMA +37010 三好群 MIYOSI +38 % EHIME +3801 松山市 MATUYAMA +3802 今治市 IMABARI +3803 宇和島市 UWAJIMA +3804 八幡浜市 YAWATAHAMA +3805 新居浜市 NIIHAMA +3806 西条市 SAIJO +3807 大洲市 OZU +3808 伊予三島市* +3809 川之江市* +3810 伊予市 IYO +3811 北条市* +3812 東予市* +3813 四国中央市 SIKOKUCHUO +3814 西予市 SEIYO +3815 東温市 TOON +38001 伊予群 IYO +38002 宇摩群* +38003 越智群 OCI +38004 温泉群* +38005 上浮穴群 KAMIUKENA +38006 喜多群 KITA +38007 北宇和群 KITAUWA +38008 周桑群* +38009 新居群* +38010 西宇和群 NISIUWA +38011 東宇和群* +38012 南宇和群 MINAMIUWA +39 % KOCI +3901 高知市 KOCI +3902 室戸市 MUROTO +3903 安芸市 AKI +3904 土佐市 TOSA +3905 須崎市 SUSAKI +3906 中村市* +3907 宿毛市 SUKUMO +3908 土佐清水市 TOSASIMIZU +3909 南国市 NANKOKU +3910 四万十市 SIMANTO +3911 香南市 KONAN +3912 香美市 KAMI +39001 吾川群 AGAWA +39002 安芸群 AKI +39003 香美群* +39004 高岡群 TAKAOKA +39005 土佐群 TOSA +39006 長岡群 NAGAOKA +39007 幡多群 HATA +40 % FUKUOKA +4001 福岡市 FUKUOKA +4002 小倉市* +4003 門司市* +4004 八幡市* +4005 戸畑市* +4006 若松市* +4007 久留米市 KURUME +4008 大牟田市 OMUTA +4009 直方市 NOOGATA +4010 飯塚市 IIZUKA +4011 田川市 TAGAWA +4012 柳川市 YANAGAWA +4013 甘木市* +4014 山田市* +4015 八女市 YAME +4016 筑後市 CIKUGO +4017 大川市 OKAWA +4018 行橋市 YUKUHASI +4019 豊前市 BUZEN +4020 中間市 NAKAMA +4021 北九州市 KITAKYUSHU +4022 小郡市 OGOORI +4023 春日市 KASUGA +4024 筑紫野市 CIKUSINO +4025 大野城市 ONOJO +4026 宗像市 MUNAKATA +4027 太宰府市 DAZAIFU +4028 前原市* +4029 古賀市 KOGA +4030 福津市 FUKUTU +4031 うきは市 UKIHA +4032 宮若市 MIYAWAKA +4033 嘉麻市 KAMA +4034 朝倉市 ASAKURA +4035 みやま市 MIYAMA +4036 糸島市 ITOSIMA +40001 朝倉群 ASAKURA +40002 糸島群* +40003 浮羽群* +40004 遠賀群 ONGA +40005 糟屋群 KASUYA +40006 嘉穂群 KAHO +40007 鞍手群 KURATE +40008 早良群* +40009 田川群 TAGAWA +40010 筑紫群 CIKUSI +40011 築上群 CIKUJO +40012 三井群 MII +40013 三池群* +40014 三潴群 MIZUMA +40015 京都群 MIYAKO +40016 宗像群* +40017 山門群* +40018 八女群 YAME +400101 福岡市東区 HIGASI +400102 福岡市博多区 HAKATA +400103 福岡市中央区 CHUO +400104 福岡市南区 MINAMI +400105 福岡市西区 NISI +400106 福岡市城南区 JONAN +400107 福岡市早良区 SAWARA +402101 北九州市門司区 MOJI +402102 北九州市若松区 WAKAMATU +402103 北九州市戸畑区 TOBATA +402104 北九州市小倉北区 KOKURAKITA +402105 北九州市小倉南区 KOKURAMINAMI +402106 北九州市八幡東区 YAHATAHIGASI +402107 北九州市八幡西区 YAHATANISI +402108 北九州市八幡区* +402109 北九州市小倉区* +41 % SAGA +4101 佐賀市 SAGA +4102 唐津市 KARATU +4103 鳥栖市 TOSU +4104 多久市 TAKU +4105 伊万里市 IMARI +4106 武雄市 TAKEO +4107 鹿島市 KASIMA +4108 小城市 OGI +4109 嬉野市 URESINO +4110 神埼市 KANZAKI +41001 小城群* +41002 神埼群 KANZAKI +41003 杵島群 KISIMA +41004 佐賀群* +41005 西松浦群 NISIMATUURA +41006 東松浦群 HIGASIMATUURA +41007 藤津群 FUJITU +41008 三養基群 MIYAKI +42 % NAGASAKI +4201 長崎市 NAGASAKI +4202 佐世保市 SASEBO +4203 島原市 SIMABARA +4204 諫早市 ISAHAYA +4205 大村市 OMURA +4206 福江市* +4207 平戸市 HIRADO +4208 松浦市 MATUURA +4209 対馬市 TUSIMA +4210 壱岐市 IKI +4211 五島市 GOTO +4212 西海市 SAIKAI +4213 雲仙市 UNZEN +4214 南島原市 MINAMISIMABARA +42001 壱岐群* +42002 上県群* +42003 北高来群* +42004 北松浦群 KITAMATUURA +42005 下県群* +42006 西彼杵群 NISISONOGI +42007 東彼杵群 HIGASISONOGI +42008 南高来群* +42009 南松浦群 MINAMIMATUURA +43 % KUMAMOTO +4301 熊本市 KUMAMOTO +4302 八代市 YATUSIRO +4303 人吉市 HITOYOSI +4304 荒尾市 ARAO +4305 水俣市 MINAMATA +4306 玉名市 TAMANA +4307 本渡市* +4308 山鹿市 YAMAGA +4309 牛深市* +4310 菊池市 KIKUCI +4311 宇土市 UTO +4312 上天草市 KAMIAMAKUSA +4313 宇城市 UKI +4314 阿蘇市 ASO +4315 天草市 AMAKUSA +4316 合志市 KOSI +43001 葦北群 ASIKITA +43002 阿蘇群 ASO +43003 天草群 AMAKUSA +43004 宇土群* +43005 上益城群 KAMIMASIKI +43006 鹿本群* +43007 菊池群 KIKUCI +43008 球磨群 KUMA +43009 下益城群 SIMOMASIKI +43010 玉名群 TAMANA +43011 飽託群* +43012 八代群 YATUSIRO +44 % OITA +4401 大分市 OITA +4402 別府市 BEPPU +4403 中津市 NAKATU +4404 日田市 HITA +4405 佐伯市 SAIKI +4406 臼杵市 USUKI +4407 津久見市 TUKUMI +4408 竹田市 TAKETA +4409 鶴崎市* +4410 豊後高田市 BUNGOTAKADA +4411 杵築市 KITUKI +4412 宇佐市 USA +4413 豊後大野市 BUNGOONO +4414 由布市 YUFU +4415 国東市 KUNISAKI +44001 宇佐群* +44002 大分群* +44003 大野群* +44004 北海部群* +44005 玖珠群 KUSU +44006 下毛群* +44007 直入群* +44008 西国東群* +44009 速見群 HAYAMI +44010 東国東群 HIGASIKUNISAKI +44011 日田群* +44012 南海部群* +45 % MIYAZAKI +4501 宮崎市 MIYAZAKI +4502 都城市 MIYAKONOJO +4503 延岡市 NOBEOKA +4504 日南市 NICINAN +4505 小林市 KOBAYASI +4506 日向市 HYUGA +4507 串間市 KUSIMA +4508 西都市 SAITO +4509 えびの市 EBINO +45001 北諸県群 KITAMOROKATA +45002 児湯群 KOYU +45003 西臼杵群 NISIUSUKI +45004 西諸県群 NISIMOROKATA +45005 東臼杵群 HIGASIUSUKI +45006 東諸県群 HIGASIMOROKATA +45007 南那珂群* +45008 宮崎群* +46 % KAGOSIMA +4601 鹿児島市 KAGOSIMA +4602 川内市* +4603 鹿屋市 KANOYA +4604 枕崎市 MAKURAZAKI +4605 串木野市* +4606 阿久根市 AKUNE +4607 出水市 IZUMI +4608 名瀬市* +4609 大口市* +4610 指宿市 IBUSUKI +4611 加世田市* +4612 国分市* +4613 谷山市* +4614 西之表市 NISINOOMOTE +4615 垂水市 TARUMIZU +4616 薩摩川内市 SATUMASENDAI +4617 日置市 HIOKI +4618 曽於市 SOO +4619 霧島市 KIRISIMA +4620 いちき串木野市 ICIKIKUSIKINO +4621 南さつま市 MINAMISATUMA +4622 志布志市 SIBUSI +4623 奄美市 AMAMI +4624 南九州市 MINAMIKYUSHU +4625 伊佐市 ISA +4626 姶良市 AIRA +46001 姶良群 AIRA +46002 伊佐群* +46003 出水群 IZUMI +46004 揖宿群* +46005 大島群 OSIMA +46006 鹿児島群 KAGOSIMA +46007 川辺群* +46008 肝属群 KIMOTUKI +46009 熊毛群 KUMAGE +46010 薩摩群 SATUMA +46011 曽於群 SOO +46012 日置群* +47 % OKINAWA +4701 那覇市 NAHA +4702 石川市* +4703 平良市* +4704 石垣市 ISIGAKI +4705 コザ市* +4706 宜野湾市 GINOWAN +4707 具志川市* +4708 名護市 NAGO +4709 浦添市 URASOE +4710 糸満市 ITOMAN +4711 沖縄市 OKINAWA +4712 豊見城市 TOMIGUSUKU +4713 うるま市 URUMA +4714 宮古島市 MIYAKOJIMA +4715 南城市 NANJO +47001 国頭群 KUNIGAMI +47002 島尻群 SIMAJIRI +47003 中頭群 NAKAGAMI +47004 宮古群 MIYAKO +47005 八重山群 YAEYAMA diff --git a/MMSSTV.TXT b/MMSSTV.TXT new file mode 100644 index 0000000..8291037 --- /dev/null +++ b/MMSSTV.TXT @@ -0,0 +1,804 @@ +「MMSSTVソフトウエア基本マニュアル」 + + 初版 2001.02.08 Mako, JE3HHT + 改定 2002.06.26 Mako, JE3HHT + + Ver1.01以降の情報は「バージョンアップ情報」に記載してあります。そちらも参照して下さい。 + +========== +◎はじめに +========== + このプログラムはサウンドカードを使ったSSTV送受信ソフトウエアです。元々はPSK31用のサウンドカードのクロック較正用のユーティリティプログラムにするつもりだったのですが、途中から方針を変更してSSTVのプログラムになってしまいました。 + + 私自身が少なくとも1度はこのプログラムで実際にQSOして実績を作ってからVer1.00としてリリースしようと考えていましたが、しばらく趣味の時間がとれなくなる可能性があり、また既にこのプログラムをお使いの方もおられるようですので、今回Ver1.00としてリリースすることにしました。 + + +======================== +◎アンインストールの方法 +======================== + このプログラムはWindowsのレジストリを一切書き換えません。アンインストールする際は、MMSSTVをインストールしたフォルダを丸ごと削除すればOKです。 + + +========== +◎動作環境 +========== + OS Windows95, 98, 98SE, ME + WindowsNT, Windows2000 + サウンドカード 16bit 11025Hz または 22050Hz + ビデオアダプタ 256色以上(16bitまたは24bitカラーが望ましい) + RAM 32MB以上 + + 私が持っているPentium100MHzクラスのディスクトップパソコンでも何とか動作しましたが、できればCPUのクロックは早いほうがFBです。 + + MMSSTVの動作速度はビデオアダプタの性能に大きく依存しますので、例え同じCPUクロックのパソコンでもビデオカードが異なる場合は動作状況が違います。特に256色アダプタをお使いの場合は、パレット演算にCPU時間を消費する傾向がありますので、可能ならば16Bitまたは24Bitカラーを選択することをお勧めします。ビデオアダプタに256色をお使いの場合は、実現される色はそのアダプタのパレット演算能力に依存します。 + + + 動作が厳しい場合は以下の設定を行って下さい。 + + [オプションメニュー -> MMSSTV設定画面] + ・「受信バッファ」をFILEまたはOFFにする + ・サウンドカードのFIFOの数を増やす + ・RxBPFをOFFにする + ・TxBPFのチェックを外す + [表示メニュー] + ・WaterFallをOFFにする + + デフォルトではLoopbackはOFFに設定されています。もしこれを内部または外部に設定すると、送信時に受信動作も同時に行いますので、CPU負荷はそれだけ増大します。動作が厳しい場合は必ずLoopbackはOFFに設定して下さい。 + +--- 重要 --- + 設定画面の「受信」ページの「受信バッファ」は傾き補正や位相ずれ補正を行った際に、受信中または直前に受信した画像を再表示させるのに使います。この領域には約270秒分のサウンドデータを記憶しており、RAMを選択している場合、物理メモリが少ないパソコンでは画像受信中にスワップが発生し、同期ズレを起こしてしまいますので、その場合はFILEまたはOFFを選択すると良いでしょう。 + 特にサンプリング周波数を高く設定している場合は、受信バッファはあなたの予想以上に大きなサイズになります。「自動傾き調整」を使わないのであれば、受信バッファをOFFにしても運用上の大きな不便はないと思います。 + + +=========================== +◎サウンドカードとRigの接続 +=========================== + PSK31やRTTYとまったく同じインターフェースが利用できます。 + + 基本的にはサウンドカードのLine入力にRigのスピーカ出力を、またサウンドカードのOutputをRigのMicまたはData入力に接続します。この時、RigのDataまたはMicラインにはATTを入れてレベルを下げる事をお勧めします。ATTなしで接続した場合はRigのマイクゲインの調整がクリチカルで、送信電波の質も悪くなります。 + + サウンドカード RIG + + Line(or Mic) <---------------- Speaker Out + + Output ------ ATT -----> Rig Data or Mic + +*サウンドカードのMic入力に入れる場合は、ここにもATTを入れる方が良いでしょう。 + + ATTは次のような簡単な構成でOKです。 + + Output ------ R1 ------+---- Data/Mic + | +SoundCard側 R2 Rig側 + | + GND ----------------+---- GND + + Data R1 = 1K, R2 = 100 + Mic R1 = 10K, R2 = 100 + +*上記の回路図には記載していませんが、回り込み防止のために適当なパスコンやフェライトビーズで処理する事をお勧めします。 +*お使いになるRigによって抵抗値を若干調整する必要があるかも知れません。 +*半固定で調整できるようにしておくとRigやソフトの組み合わせが変わっても、レベルを簡単に調整できるのでより便利だと思います。 + + +========= +◎PTT制御 +========= + RigのMic入力にトーンを入れる場合は、Rig側にVOXが備わっていれば、とりあえずそれを使っても良いと思います(ただしメッセージボックスが表示された時にポーンという音が出て一瞬だけ送信状態になる可能性はあります。)。 + + RigのData入力にトーンを入れた場合はVOXが使用できませんので、PTT制御を行う必要が生じます。 + MMSSTVはPTT制御として、RS232C回線のRTSまたはDTRを使用することができます。両方同じ論理でON/OFFしますのでいずれに接続してもOKです。 + +*PTT制御の回線はオプションメニューの設定画面の「送信」のところで設定します。ドロップリストではCOM1〜COM8しか選択できませんが、例えばキーボードからCOM9と入力して任意のポート名を設定する事もできます。 + +*「占有使用」のチェックを付けると、ポートはMMSSTVが占有し続けます。 + +*「RTS while Scan」のチェックを付けると、画像受信中(スキャン中)にもRTS信号をアクティブにします。また画像受信中はTxDをブレーク状態に保ちます。 + + PTT制御回路は例えば一つのトランジスタを使った次のような回路で構成できます。 + + (C)---+---- Rig PTT + Com-DTR -- R1-+---+-(B)< | + (RTS) | | (E) | + D R2 | D + | | | | + Com-GND ------+---+------+----+---- Rig GND + + R1=4.7K, R2=47K + D=1S1588, 1N914, 4148, etc... + Tr=2SC1815, 2N2222, etc... + + Dsub(9pin) RTS(7), DTR(4), GND(5), TXD(3) + Dsub(25pin) RTS(4), DTR(20), GND(7), TXD(2) + +*上記の回路図には記載していませんが、回り込み防止のために適当なパスコンやフェライトビーズで処理する事をお勧めします。 + + お使いのRigがRadio CommandによるPTT制御をサポートしている場合、DTR/RTSラインを使わずに、Radio Commandを使用してPTT制御を行うこともできます。この場合USBアダプタなどのDTR/RTS制御を持たないポートでもPTT制御を利用することができるようになります。詳細は「Radio Command」の項を参照して下さい。 + + +============== +◎SSTVのモード +============== + MMSSTVが準拠対応するSSTVモードは下記の通りです。 + + 名称 時間(s) サイズ 方式 + --------------------------------------------------- + Robot B/W 8 8 160x120 モノトーン + Robot B/W 12 12 160x120 モノトーン + Robot 24 24 160x120 色差 + Robot 36 36 320x240 色差 + Robot 72 72 320x240 色差 + AVT 90 90 320x240 RGB(同期パルスなし) + Scottie 1 110 320x256 RGB + Scottie 2 71 320x256 RGB + Scottie DX 269 320x256 RGB + Martin 1 114 320x256 RGB + Martin 2 58 320x256 RGB + SC2-180 182 320x256 RGB + SC2-120 122 320x256 RGB + SC2-60 62 320x256 RGB + PD50 50 320x256 色差 + PD90 90 320x256 色差 + PD120 126 640x496 色差 + PD160 161 512x400 色差 + PD180 187 640x496 色差 + PD240 248 640x496 色差 + PD290 289 800x616 色差 + P3 203 640x496 RGB + P5 305 640x496 RGB + P7 406 640x496 RGB + +* 日本では私が観察した限り、ほとんどすべての信号が「Scottie 1」です。 +* USでは「Scottie 1」と「Scottie 2」が多く使われているようです。 +* EUでは「Martin 1」と「Martin 2」が多く使われているようです。 + +また以下のモードは現在実験中です。 + + MP73 73 320x256 色差 + MP115 115 320x256 色差 + MP140 140 320x256 色差 + MP175 175 320x256 色差 + MR73 73 320x256 色差 + MR90 90 320x256 色差 + MR115 115 320x256 色差 + MR140 140 320x256 色差 + MR175 175 320x256 色差 + ML180 180 640x496 色差 + ML240 240 640x496 色差 + ML280 280 640x496 色差 + ML320 320 640x496 色差 + +MPモード + PDモードと同じ方式の色差方式のモードで、20mでのマルチパス/ジッタ対策のために設けました。ピクセル当たりのスキャン時間は同一伝送時間の他のモードよりも長いですが、垂直方向の色情報が圧縮されています。 + +MR/MLモード + Robot24/72モードと同じ方式の色差方式のモードで、比較的良好なCondx下で見た目の解像度を得るのが狙いです。水平方向の色情報が圧縮されています。 + + + いずれも方式は新しいものではありませんが、適当な伝送時間と画像サイズを作成しました。新しい試みとして、VIS信号を16ビットに拡張してあります。 + これらのフォーマットの詳細は付属の「mode.txt」を参照して下さい。 + + +================== +◎SSTVの呼出周波数 +================== + 日本では7033(LSB)が良く使われているようです。国際的には下記の周波数が習慣的に使われています。 + + 14.230MHz USB + 21.340MHz USB + 28.680MHz USB + + 私が観察した限り、これら3つの周波数は常に混雑しているようです。従って一旦相手局と連絡を取り合った後は、上下の周波数にQSYしてQSOを楽しまれることをお勧めします。呼び出し周波数でそのままQSOを続行しても、QRMであまり良い結果が得られないと思います。 + + 7033の場合は、QSYするのが困難ですので、そのままQSOが行われています。 + + +====== +◎受信 +====== + +1.トーン周波数 +~~~~~~~~~~~~~~ + SSTVのトーン周波数は次のように定義されています。 + Syncパルス 1200Hz + 画像Lowレベル 1500Hz + 画像Highレベル 2300Hz + + MMSSTVのスペクトラム表示にある4本のマーカーラインの周波数は左から次の順番で表示されます。 + + 一番左(緑) 1200Hz Syncパルス + その次(黄) 1500Hz 画像Lowレベル + その次(黄点線) 1900Hz 画像中間レベル + 一番右(黄) 2300Hz 画像Highレベル + + 周波数を合わせる場合は、スペクトラム表示またはWaterFallを見ながら、信号のエネルギーが1500Hzマーカーと2300Hzマーカーの範囲内に収まるように調整して下さい。またSyncパルスが1200Hzマーカーの上に丁度重なるように合わせてもOKです。ただしSyncパルスは非常に短い信号ですので、馴れるまでは少し見つけ難いかも知れません。 + + 一般のSSTVの運用では、ほとんど固定された周波数でQSOが行われているようですので、一旦周波数を合わせてしまえば、後はRigのダイアルを触る必要はほとんどないと思います。 + +2.自動スタート +~~~~~~~~~~~~~~ + メイン画面のRxModeの「Auto」ボタンをONにしておくと、起動信号を受信して自動的に画像の受信を開始するようになります。 + 起動信号はVIS信号と呼ばれ、1200HzのマーカーとSSTVモードを表すコードが1100Hzと1300HzのFSK(7ビット+Evenパリティ)で送信されます。MMSSTVはこの信号を共振器型のFSKデモジュレータを使用して受信し、MMSSTVが受信可能な画像モードの場合はそのモードで受信を開始します。 + + 設定画面の「自動スタート」で「VIS or Sync」を選択している場合、MMSSTVは1200HzのSyncパルスの時間間隔を計測し、その時間がそれぞれのモードと一致した場合も、そのモードで強制的にスタートします(デフォルトは「VIS or Sync」になっています)。 + + +3.手動スタート +~~~~~~~~~~~~~~ + 運悪く自動スタートできなかった場合、または途中から信号を受信した場合は、メイン画面のRxModeの、いずれかのボタンを押して、手動で画像受信を開始することができます。 + この場合、日本、韓国およびUSでは「Scottie 1」をまずは選択してみると良いでしょう。EUでは「Martin 1」をまずは選択してみます。確率的にそれらのモードが良く運用されているからです。 + + +4.自動停止,自動再スタート,自動再同期 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + 設定画面(または受信画面でマウス右ボタンを押す)の「自動停止」をONに設定すると、MMSSTVは画像受信中に同期信号を見失った際に自動的に停止します(AVT90モードを除く)。 + + 設定画面(または受信画面でマウス右ボタンを押す)の「自動再スタート」をONにすると、画像受信中にVIS信号を検出した場合に、再度先頭から受信開始を行います。ただしこの場合のVIS信号の判定はRxBPFの影響を受けて少し厳しくなります。 + + 設定画面(または受信画面でマウス右ボタンを押す)の「自動再同期」をONにすると、途中でタイミングがずれた場合に、そのタイミングで再同期を取ります。ただしこの場合、数本の情報は古いタイミングで表示されますので、タイミングがずれている領域が帯状に表示されます。 + + +5.傾き調整 +~~~~~~~~~~ + MMSSTVはサウンドカードのクロックタイミングでSSTV信号のタイミングを測ります。したがってサウンドカードのクロックがずれている場合や、相手局の信号のタイミングがズレている場合には、受信した画像に傾きが起こります。これを補正するには以下の3つの方法があります。 + + - 高精度傾き調整 + - 自動傾き調整 + - 手動操作による傾き調整 + + 「高精度傾き調整」および「自動傾き調整」は、受信信号のタイミングを解析し自動的に補正します。しかしDX局などの弱い信号やマルチパスで同期信号のタイミングがジッタを含む場合、またQRMがある場合などは、必ずしもあなたの期待通りにはならないかも知れません。 + + なおいずれの方法でも、同期画面の「記憶」ボタンを押さなければ、調整した結果のサンプリング周波数は現在受信中または直前に受信した画像にしか適用されず、次の受信または送信時に元の設定値に戻ります。その周波数を次回の受信時にも適用したい場合は、「記憶」ボタンを押す必要があります。 + + +===[高精度傾き調整]=== + 高精度傾き調整は、現在受信中または直前に受信した信号の、同期位置の直線方程式の解を最小二乗法で求め補正します。受信信号の質が良好な場合、誤差は概ね2ppm以内に収まります。 + + 高精度傾き調整を行うには、同期画面のニコニコボタンを押すか、同期画面または受信画面でマウスの右ボタンをクリックし、ポップアップメニューの中の「高精度傾き調整」を実行します。この機能を使うには少なくとも16掃引分の信号を受信していなければなりません。また掃引数が多くなるほど精度は良くなります。 + +* 受信バッファをOFFにしている場合、高精度傾き調整機能は使用できません。 + +===[自動傾き調整]=== + 自動傾き調整は、受信中の信号の同期間隔を定期的に観測し、そのズレを自動的に検出して補正します。この機能をONにしておくと受信中に勝手に補正されていきますが、高精度傾き調整と比較して精度が少し悪いです。 + + 設定画面の受信ページの「自動傾き調整」のチェックを付けるか、または、メインウインドウの受信画面のマウスの右ボタンを押し、ポップアップメニューの中の「自動傾き調整」のチェックを付けておきます。 + +* 受信バッファをOFFにしている場合、自動傾き調整機能は使用できません。 + +===[手動操作による傾き調整]=== + メイン画面の同期ページを選択し、次の手順を行います。 + 1.「傾き」ボタンを押します + 2.同期信号(白の縦帯)の上右側をクリックします。 + 3.同期信号(白の縦帯)の下右側をクリックします。 + + 同期信号はある程度の幅を持ちますので、2回のクリックでは同じ側をクリックしなければなりません。1回目のクリックの後、補助カーソルが表示されますので、同期信号の帯とその補助カーソルが平行になるようにすると良いでしょう。 + + MMSSTVは上記の操作により得られた傾斜に従って、サウンドカードのサンプリング周波数を計算し、現在受信中または直前に受信した画像を再表示します。もし1回の操作で満足いく結果が得られない場合は、上記の手順を繰り返して下さい。 + + また傾きが小さい状態では、表示メニューの「受信画面を常に表示」のチェックを付け、別の受信画面を表示させた状態で、同期画面上の周波数の横にあるアップダウンボタンを押して画像の傾斜を確認しながら除々に追いこむこともできます。 + +* 受信バッファをOFFにしている場合、傾き調整をした結果の画像を再描画することができません。 + + +6.同期位置の調整 +~~~~~~~~~~~~~~~~ + MMSSTVはAVT90以外のモードでは、手動スタートした場合でも、概ね自動で正しい同期位置に合わせますが、受信信号の状態が悪いと稀に失敗する場合もあります。同期ズレが発生した場合、単に画像がずれるだけではなく、画像の色もおかしくなりますのですぐに判ります。 + + もし同期ズレが発生した場合は、メイン画面のSyncページを選択し、次の手順を行います。 + 1.「位相」ボタンを押します + 2.同期信号(白の縦帯)の左側のすぐ横をクリックします。 + + MMSSTVは指定された位置が一番左端になるように、受信中または受信した画像を再表示します。もし1回の操作で満足いく結果が得られない場合は、上記の手順を繰り返して下さい。 + + AVT90は画像データ内に同期信号が存在しないため、Syncページでは画像の白黒イメージしか表示されませんが、その切れ目(3箇所存在します)をクリックします。受信画面で正常な色が得られない場合は他の切れ目を試すと良いでしょう。 + +* 受信バッファをOFFにしている場合、同期位置調整をした結果の画像を再描画することができません。 + + +========== +◎受信履歴 +========== + MMSSTVは過去に受信した最新の画像を最大で256枚保持することができます。デフォルトではこの数は32枚に制限されていますので、MMSSTV設定画面の「その他」ページの「履歴画像の数」を好みの数に設定して下さい。記録する画像が設定した数を超えた場合、古いものが消えて新しいものが追加されます。 + ただしデフォルトのビットマップフォーマットでは1枚あたり約160から240KBのディスクスペースを消費しますので、256枚を設定すると最大で約50MBの領域がハードディスク上に必要になります。 + ディスク領域をセーブしたい場合は、JPEGフォーマットに変更すると良いでしょう。JPEGフォーマットへの変更はマウス右ボタンを押し、ポップアップメニューの「JPEGフォーマットを使う」を選択します。 + + 受信履歴はあくまで一時的に記憶する目的で設計されていますので、必ず古い画像が削除されます。もしあなたが受信した画像を別のフォルダに自動的に保存したい場合は、右ボタンのポップアップメニューの「他のフォルダに自動的にコピー」のチェックを付けて、「コピー先のフォルダ名の定義」でフォルダ名を指定しておくと良いでしょう。 + + 履歴画像を手動で別のフォルダにコピーしたい場合、履歴ウインドウの画像をドラッグし、ログウインドウのQSLボックスにドロップします。ただしこのドラッグ&ドロップ操作は「コピー先のフォルダ名の定義」であらかじめフォルダ名を指定しておかなければ使用できません。 + 自動コピー機能をONにしているか、またはQSLボックスに履歴画像をドロップした場合、MMSSTVはログのQSLフィールドにそのインデックスを自動的に記録します。あなたがMMSSTVのログを使用してQSOデータを記録している場合、データ表示画面から「画像」ボタンを押して、その画像をいつでも参照することができます。 + + +====== +◎送信 +====== + 送信する場合は、メイン画面の送信ページタブをクリックします。現在送信画面に表示されているイメージがそのまま送信されます。送信する前に、Rigのマイクゲインを適切に調整して下さい。 + + スピーチプロセッサは絶対にONにしないで下さい。 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +1.送信画像の準備 +~~~~~~~~~~~~~~~~ + 送信する画像は、以下の方法でMMSSTVの送信画面にロードすることができます。 + + 1.メイン画面下側のストック画像ギャラリからドラッグ&ドロップ + 2.フォルダのサムネイル画面(表示メニュー)からドラッグ&ドロップ + 3.Windowsファイルマネージャからドラッグ&ドロップ + 4.他の編集ソフトからドラッグ&ドロップ + (そのソフトがドラッグオペレーションをサポートしている場合) + 5.他の編集ソフトからクリップボード経由で貼り付け + + またあらかじめ準備してあるテンプレートを、ロードした画像と重ね合わせて送信画像を作成することもできます。テンプレートの作成方法については後で解説します。 + + 送信画面をマウスの右ボタンでクリックすると、クリップボード操作やファイルのロード・セーブに関するポップアップメニューが表示されます。 + + +2.モードの選択 +~~~~~~~~~~~~~~ + 送信したいSSTVモードをTxModeから選びます。 + +* 設定画面の「送信」ページにある「SSTV Mode」の「固定」のチェックを外すと、既に画像を受信している場合は、最後に受信した時のモードが自動的に送信モードに設定されるようになります。 + + +3.送信 +~~~~~~ + 送信画面の左下にある「TX」ボタンを押すと送信を開始します。画像が送信されるに従って送信位置のマーカーが下がって行きます。 + 全画像を送信すると自動的に受信に戻ります。送信を途中で中止したい場合は再度「TX」ボタンを押します。 + + MMSSTVは12秒の送信サウンドバッファを持ちます。これは通常は充分なサイズだと思いますが、お使いのパソコンの速度が遅い場合は、送信中はあまり他の操作をしないほうが良いかも知れません。 + また送信中にタイミングをロストした場合、MMSSTVは送信完了後に警告メッセージを表示します。この場合、設定画面の「その他」ページのサウンド処理のFIFOの数を増やすと問題が解決するかも知れません。 + + +4.送信画像の傾きの調整 +~~~~~~~~~~~~~~~~~~~~~~ + 一部のサウンドカード(特に最近のPCIカードのもの)は録音と再生動作でサンプリング周波数が微妙に異なる場合があります。このような場合、受信でクロックが正しく較正されていても、送信時の画像が相手局で受信した時に傾く場合があります。 + MMSSTVはこのような場合のために、送信時に適用するサウンドカードクロックのオフセット周波数を設定できるようになっています。調整方法の詳細についてはサウンドカードの項(本書の最後)を参照して下さい。 + + +5.TuneボタンとCWID +~~~~~~~~~~~~~~~~~~ + 送信画面の「Tune」ボタンを押すとデフォルトで1750Hzのトーンを送信します。この機能はUSのリピータのために存在します。 + また設定画面の「CWIDを使う」にチェックを入れると画像送信後にCWIDを送信することができます。この機能はEUの友人のために存在します。 + + +============== +◎テンプレート +============== + 送信画面に重ね合わせる簡単な図を作成することができます。例えばQSO相手のコールサインをマクロコマンドを使用して自動的に展開することも可能です。 + + 操作はDraw系ソフトの基本操作にほぼ準拠していますが、現状ではグループ化はサポートしていません。 + + 画面下側にあるツールボタンを操作し、アイテムを作成します。ツールボタンは左から次の順番で並んでいます。 + +矢印ボタン 選択モードのON/OFFをします。 +直線ボタン 直線モードを選択します。 +四角ボタン ボックスモードを選択します。 +四角塗りつぶしボタン ボックス塗りつぶしモードを選択します。 +Tボタン 文字モードを選択します。 +絵ボタン 絵または履歴画像の挿入モードを選択します。 +カラーバーボタン カラーバーモードを選択します。 +文字列リスト 定義済みの文字列を選択します。 +はさみボタン 選択中のアイテムをカットします。 +ペーストボタン カットしたアイテムをペーストします。 +色変更ボタン 選択中のアイテムの色を変更します。 +Lボタン 選択中のアイテムのペンを変更します。 +fボタン 選択中のアイテムのフォントを変更します。 + + 例えばマクロテキストを使用するには、Tボタンを押した後に、画面上の任意の点をマウスでクリックします。すると文字入力画面が表示されますので、Macroボタンを押して例えば「%c」を選択するとそこに相手局のコールサインが展開されるようになります。 + 一旦作成したアイテムの位置を変更するには、矢印ボタンを押した後、画面上のそのアイテムをドラッグして移動先にドロップします。またそのアイテムを再編集するにはそのアイテムをダブルクリックします。 + テンプレートのアイテム同士の重なりを制御するには、そのアイテムを選択状態にし、マウスの右ボタンを押して、「前面に移動」または「背面に移動」を選択します。 + + 操作方法の詳細は省略しますが、DRAWソフトの感覚に似ています。適当に操作してみてください。 + +* エクスプローラ等のファイルマネージャから画像(BMP,JPG)ファイルをテンプレートにドロップすると、その画像がその位置に展開されます。 + + +========================================== +◎テンプレートの送信画像への重ね合わせ動作 +========================================== + MMSSTVはテンプレートを送信画像に重ねる際、透過ポイントで指定されている位置の色以外をすべて送信画像に重ねます。透過ポイントはデフォルトでは画面右下になっていますが、マウス右ボタンを押してポップアップメニューを開き、「透過ポイントの設定」を選択して、自由に画面内の好きな位置に設定できます。あなたは必ずテンプレートアイテムが存在しない位置に透過ポイントを設定しなければなりません。特に画面右下にテンプレートアイテムを配置した場合は注意が必要です。 + +* Ver0.21以降のMMSSTVは透過ポイントを自動的に調整する機能がデフォルトでONになっています。従って、テンプレートアイテムの位置を変更した場合でも、透過ポイントはアイテムと重ならない位置に自動的に調整されます。 + + またテンプレートの背景色も「背景(透過)色の設定」で自由に選択できます。実は送信画像重ね合わせ動作において、テンプレートの背景色は極めて重要です。あなたは必ずテンプレート内で使わなかった色をテンプレート背景色に設定しなければなりません。 + ただし画像およびカラーバーをテンプレート内に描画している場合、その部分のみテンプレートの背景色は関係なくなり送信画像は透過しません。 + +* テンプレート上でマウス右ボタンを押し、ポップアップメニュー内の「ユニークな背景色を探す」というメニューを実行すると、自動的にテンプレート内で使っていない色を探し出し背景色に設定することができます。 + + + もしあなたがQSO中に、送信画像そのものを編集したいのであれば、他のSSTV用の画像編集ソフトを使うことをお勧めします。それらはMMSSTVよりも、より多くの素晴らしい文字効果や画像効果を提供しています。 + MMSSTVのテンプレートは、主に相手局のコールサイン、RSVリポートやコンテストナンバなどをマクロコマンドによりログから自動的に展開する用途で設計されています。したがってログ機能を使わないのであれば、テンプレートを使うメリットはないかも知れません。 + + +====================== +◎画像サイズとヘッダー +====================== + RobotやAVTモードの走査線は240本で、ScottieやMartinモードは256本です。これは元々は家庭用テレビの方式の違いに起因しています。 + RobotやAVTはUSで生まれたフォーマットで、走査線の数もNTSCに合わせて240本になりました。しかしScottieやMartinはUKで生まれたフォーマットで、走査線は256本あります。この場合、240本との互換を取るために先頭の16本はヘッダーにして画像を送信しないという習慣を持つようになったものと推測します。 + 相手局がスキャンコンバータを使ってNTSC方式のテレビで受信している場合は、恐らく240本しか映らないはずですから、(映らなくても良い)ヘッダーを入れるようにします。 + + しかしPCを使った設備の場合、この16本のヘッダーは無駄だと思います。それもデザインの一部と割り切れれば良いですが、せっかく16本余分に送信時間をかけるのですから、その部分も素材画像の一部として取り扱っても良いと思います。 + + MMSSTVの場合この違いを吸収するために、ヘッダーはテンプレートアイテムで自由に定義できるようにし、以下の送信方法を提供しています。 + +○素材画像が縦240ピクセルで256本モード(Scotti等)で送信する場合 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + 1)テンプレートにヘッダーを定義しておきます。 + 2)送信画面の「上マージンシフト」ボタンを押しこみ、素材画像のみを下にシフトさせます。 + または + 2)画像クリッパーで上マージンを確保して送信画面に取りこみます。 + +○素材画像が縦256ピクセルで256本モード(Scotti等)で送信する場合 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ヘッダーの有無はあなたの好みに依存します。ただし相手局の受信設備により、先頭の16ピクセルは映らない可能性があることを考慮しなければなりません。 + ヘッダーを使っている場合に送信画面の「上マージン調整」ボタンを押しこむと素材画像の上側16ピクセルがヘッダーに隠れることはありませんが、アスペクト比は変化します。 + +○素材画像が縦240ピクセルで240本モード(Robot等)で送信する場合 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ヘッダーなしのテンプレートを定義してそのまま送信します。 + +○素材画像が縦256ピクセルで240本モード(Robot等)で送信する場合 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + 1)テンプレートにヘッダーを定義しておきます。 + 2)送信画面の「下マージンシフト」ボタンを押しこみ、素材画像とテンプレートを上にシフトさせます。素材画像の上側16ピクセルは送信されません。 + または + ヘッダーなしのテンプレートを定義してそのまま送信します。素材画像の下側16ピクセルは送信されません。「下マージン調整」ボタンを押しこむと、素材画像の下側16ピクセルを失うことはありませんが、アスペクト比は変化します。 + + +============== +◎ストック画像 +============== + MMSSTVは最大300枚のストック領域を持ちます。このストック領域にはそれぞれ、画像データとテンプレートの情報を保持することができます。 + またストック領域をマウスの右ボタンでクリックするとポップアップメニューが表示され、その領域に関して、クリップボード操作、ファイルロード・セーブ機能を使うことができます。 + + ディスク領域をセーブしたい場合は、ストック画像の保存フォーマットをJPEGフォーマットに変更すると良いでしょう。JPEGフォーマットへの変更はマウス右ボタンを押し、ポップアップメニューの「JPEGフォーマットを使う」を選択します。 + + テンプレートは送信画像と組み合わせてあらかじめ作成しておくと良いでしょう。ストック領域は画像とテンプレートを独立して格納することができますが、ストック画像をドラッグ&ドロップで送信画面にロードすると、ストック画像コントロールバー内の「テンプレート合成表示」のチェックが付いている場合、それに付属するテンプレートも同時にロードできるように設計されています。 + 画像とテンプレートを個々に転送したい場合は、「テンプレート合成表示」のチェックを外してドラッグ&ドロップ操作を行います。 + 以下にストック画像およびストックテンプレートと、送信画面、テンプレート画面間のコピー動作の規則を示します。 + +[テンプレート合成表示のチェックが付いている場合] +ドラッグ元 ドラッグ先 動作 +--------------------------------------------------------- +ストック画像 送信画面 画像とテンプレートを同時にコピー +ストックテンプレート テンプレート画面 テンプレートのみをコピー +送信画面 ストック画像 画像とテンプレートを同時にコピー +テンプレート画面 ストックテンプレート テンプレートのみをコピー + +[テンプレート合成表示のチェックが付いていない場合] +ドラッグ元 ドラッグ先 動作 +--------------------------------------------------------- +ストック画像 送信画面 画像のみをコピー +ストックテンプレート テンプレート画面 テンプレートのみをコピー +送信画面 ストック画像 画像のみをコピー +テンプレート画面 ストックテンプレート テンプレートのみをコピー + + ストック画像にファイルからビットマップまたはJPEGファイルをロードする場合は、エクスプローラやマイコンピュータ画面上でそのファイルをドラッグし、そのままストック画面にドロップしてもOKです。 + + テンプレートの文字効果の展開は若干時間がかかります。このためストック画像領域でテンプレートを合成表示した場合、ウインドウ再描画が遅くなります。もしこれに不満を感じるならば、ストック画像コントロールバー内の「高速描画」のチェックを付けると良いかも知れません。 + またストック画像の保存フォーマットにJPEGを選択している場合、ストック画像のページを変更すると、ファイルの読みなおしに若干時間がかかる場合があります。 + +* ストック画像ウインドウの上に、フォルダのサムネイルウインドウを表示すると、MMSSTVはそのサムネイルウインドウをストック画像の代用として使用すると判断し、ストックテンプレートに切り替えた際に、フォルダのサムネイルウインドウを一時的に消します。 + + +==================== +◎プログラムメニュー +==================== + あなたが良く使うプログラムをMMSSTVのプログラムメニューに登録し、メニューから起動することができます。 + + プログラムメニューの上から8つのメニューに、画像編集ソフトや、PSK31、RTTY、MFSK16などの普段お使いのプログラムを登録しておくと良いでしょう。 + + プログラムを登録する際、サスペンドのチェックを付けると、他のサウンドカードやComポートを利用するプログラムを動作させるために、MMSSTVはサスペンド状態になります。この場合、MMSSTVはCom回線とサウンドカードのリソースを放棄し自身を最小化状態にした後、登録されているプログラムを実行します。 + MMSSTVを復帰させるには、そのプログラムを終了した後、Windowsタスクバーの「Mmsstv」アイコンをクリックして最小化を解除します。 + + メニューに登録していない(サウンドカードを利用する)プログラムを実行させたい場合は「サスペンド」を選択すると良いでしょう。MMSSTVはCom回線とサウンドカードのリソースを放棄し、自身を最小化状態にします。 + + 他のサウンドカードやCom回線を利用するプログラムが動作中に、MMSSTVの最小化を解除すると、MMSSTVでサウンドカードおよびCom回線のオープンエラーメッセージが表示されます。 + この場合、MMSSTVは自動で自身を再度最小化しません。MMSSTVを復帰させるには、他のプログラムを終了した後、MMSSTVを手動で再表示させるか、またはプログラムメニュー内の「サスペンドの解除」を選択すると良いでしょう。 + +* 画像編集ソフトを登録する場合は、サスペンドのチェックを付ける必要はありません。 + + +=============== +◎Radio Command +=============== + MMSSTVはDTR/RTS制御によるPTT以外に、Radio CommandによりPTTを切り替えることができます。お使いのRigによりこのコマンドは異なりますが、送出するコマンドとディレイを自由に定義することができますので、Radio Commandが使用できるほぼ全てのRigで利用することができると思います。 + + RadioCommandを使う場合、オプションメニューの設定画面を開き、送信設定で「Radio command」ボタンを押します。この画面でポート名を設定すると、そのポートがRadio Commandポートとして働くようになります。 + + 定義できるイベントは以下の通りです。 + Init 回線を初期化した直後に送信されます。 + Rx 受信に切り替える時に送信されます。 + Tx 送信に切り替える時に送信されます。 + + これらのイベントには、デフォルトでYAESUのFT-1000MPのコマンドが定義してありますが、以下のキーワードを使ってコマンドを自由に変更できます。 + + \$##... ##=00-FF, 送信する複数バイトを16進数で定義する + (例:\$FE55AA -> FEh,55h,AAh) + \x## ##=00-FF, 送信する1バイトを16進数で定義する + (例:\xFE\x55\xAA -> FEh, 55h, AAh) + \w## ##=00-99, ディレイ時間を10ms単位の10進数で定義する + (例:\w05 -> wait 50ms) + \r キャリッジリターンを送信する + \n ラインフィードを送信する + \c.... 以降はすべてコメント + \\ '\'文字を送信する + その他 その文字列を送信する + + 16進数の代わりにxxを記述すると、その部分はxx入力ボックスで定義した16進数に置き換わります。この変換はICOMの機種アドレスを指定する場合に便利かも知れません。 + \$FEFExxE01C0001FD (xxの部分が定義内容に置き換わる) + + 特定のイベントでコマンドを送出したくない場合、そこには何もコマンドを定義しないで下さい。 + 各イベントの定義コマンドは「Save」ボタンを押してファイルに保存できます。また「Load」ボタンを押して保存したファイルから読み込むことができます。 + +* ディレイ時間はTx定義の一番最後に定義します。デフォルトでは\w10(100ms)になっています。MMSSTVはこのディレイ以外にも、常に送信切り替え時に僅かなディレイ時間を確保しますので、RigによってはこのTx定義でのディレイは不要かも知れません。 + + 「VFO polling」を設定すると、RadioCommand経由でRigの周波数を取りこみ、ログのバンド情報を自動的に更新することができます。現状ではすべてのRigをサポートしているわけではありませんが、未サポートのもにに関しては将来コマンドが判明した時点で追加したいと思います。 + + ICOMおよびTenTec Omni-VIの場合、「Scan addr.」のチェックを付けると自動的にRigのアドレスを探します。マルチドロップで多数のRigを接続をしている場合、最初に見つけたRigのアドレスで停止します。 + + Radio Commandで使用するポートは、通常のDTR/RTS制御のPTTポートとはまったく独立して存在します。従ってRadio CommandポートではVFOポーリングのみを行い、PTT制御は別のポートでDTR/RTSラインを使用することも可能です。 + + +==================== +◎復調器の構成と調整 +==================== + + DSPの基本的な解説はMMTTYのDigital.txtを参照して下さい。ここではMMSSTVに関する解説のみ行います。 + + +1.復調器の構成 +~~~~~~~~~~~~~~ + MMSSTVの復調器の構成を以下に示します。 + +Sound --> BPF(FIR) -+--> BPF1100(IIR) --> Vis symbol '1' + | + +--> BPF1300(IIR) --> Vis symbol '0' + | + +--> BPF1200(IIR) --> Sync + | + ---> Zero cross det. --> Pciture data + (1500 to 2300) + または + | + ---> PLL(1500 to 2300) --> Picture data + または + | + ---> Hilbert(1500 to 2300) --> Picture data + + + 以下にゼロクロス方式の構成図を示します。 + + ---> 微分器 ---> カウンタ ----> Out LPF ----> Pic. data + + + 以下にPLL方式の構成図を示します。 + + (位相検波器) + ---> Phase det. ---> Loop LPF ---> Out LPF --> Pic. data + | | + <---- VCO <------------- + + 以下にヒルベルト変換方式の構成図を示します。このアイデアはJA6UHL西村さんに教えて頂きました(MNI TNX to JA6UHL)。 + + --+-> Delay(N) -> Real + | |==> ATAN --> 微分器 --> LPF --> Pic. data + --> FIR(2N) --> Image + + + 各方式について私が実験した限りでは、概ね以下のような違い(一長一短)があるようです。しかし受信信号の質によって異なる評価になる場合もあります。どの方式を使うかは皆さん自身で実験して選択して下さい。 + +デコード方式 ゼロクロス PLL ヒルベルト変換 +変換色精度 △ ○ ○ +解像度 △ △ ○ +QSB ○ △ ○ +CPU負荷 ○ ○ △ +サンプリング 高いほうが良い 高いほうが良い ---- + + + ゼロクロス方式およびPLL方式は、サンプリング周波数を高くするとOut LPFのカットオフ周波数を高く設定することができます。 + + ヒルベルト変換方式は、サンプリング周波数を高くするとそのままでは位相微分の精度が悪くなります。MMSSTVは変換精度が得られるように内部でデシメート処理(サブサンプリング)を行いますが、この方式の場合はむしろデフォルト通りの11025Hzサンプリングを使ったほうがFBです。 + + +2.ゼロクロス検波のパラメータ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +[Out LPF] + このフィルタはカウンタで得られた周波数成分をスムージングします。シャープな画像が欲しい場合はこのカットオフ周波数を高く設定します。ノイズの少ない画像が欲しい場合はこのカットオフ周波数を低く設定します。 + フィルタはIIR型とFIR型のいずれかを選択できますが、いずれの方式を選択しても変化がないようです。低いサンプリング周波数の場合はFIR型のほうがCPU負荷は小さいと思います。 + + +3.PLLのパラメータ +~~~~~~~~~~~~~~~~~ +[VCO Gain] + VCO GainはPLLの応答特性に大きく影響します。VCOゲインを大きくすると応答が速くなり、小さくすると応答が遅くなります。あまりゲインを上げ過ぎると復調信号の振動が大きくなります。 + +[Loop LPF] + VCOと共にループのダンピングファクタを決定ずける重要なパラメータです。このフィルタには必ず1次フィルタを使って下さい。このカットオフ周波数を上げると復調信号の振動が大きくなります。 + +[Out LPF] + このフィルタはPLLのループ外にありますので、応答特性には影響しません。しかし画像の質は大きく変化します。シャープな画像が欲しい場合はこのカットオフ周波数を高く設定します。ノイズの少ない画像が欲しい場合はこのカットオフ周波数を低く設定します。この選択はあなたの好みに完全に依存します。 + + +4.微分処理 +~~~~~~~~~~ + 微分処理のチェックを入れると、MMSSTVは信号の周波数の変化を若干強調させてフィルタ部での信号のなまりを補正しますが、ノイズに少し弱くなる欠点を持ちます。 + 横にあるスライダで補正具合を調整できますので、好みの画質になるように調整してみてください。右にするほどエッジが急峻になります。 + +* この微分処理はゼロクロス方式やヒルベルト変換方式の微分器とは関係しません。 + + +5.レベル変換 +~~~~~~~~~~~~ + 復調器で得られた周波数値をカラー(輝度)値に変換する際、レベル変換器を使います。このレベル変換は、設定画面の「受信」ページで次の2つの方法を選択できます。 + +- 直線変換(多項式を使うのチェックを外す) + 復調器で得られた周波数値とレベルの関係が直線であると仮定して、1次変換を行います。この方法は処理が簡単ですが復調器の周波数特性が直線である必要があります。 + +- 多項式変換(多項式を使うのチェックを入れる) + 復調器で得られた周波数値を17次の多項式で曲線近似して変換します。復調器の周波数特性が直線でない場合はこちらを使用すると良いかもしれません。なお、高速に変換するために、あらかじめ多項式を計算したテーブルを作成して変換を行いますのでCPU負荷はほとんど変化しないと思います。 + + 11025Hzでゼロクロス検波を使用した場合、2200Hzから2300Hz(高輝度側)の直線性が少し悪くなりますので、「多項式を使う」にチェックを付けたほうが良いかも知れません(サンプリング周波数が高くなるに従い、変換結果は直線に近くなるはずです)。ただ実際には11025Hzの場合でも、その変換誤差は2/256〜3/256の範囲ですので、画像での見た目はほとんどわからないと思います。 + + 設定画面の「受信」ページで、「較正」ボタンを押すとMMSSTVは自動較正を開始します。較正には約20秒ほど必要です。 + 較正を終了すると1500Hzから2300Hzまでの周波数特性グラフを表示しますので、それが右下がりの直線になっている場合は、「多項式を使う」のチェックを外してもOKです。 + + +=============== +◎プロファイル +=============== + MMSSTVのデフォルトの復調パラメータは、私が実験した結果、無難と思われる値が設定されていますが、実験期間が短く受信した信号サンプルが少ないため、それがベストであるとは思えません。あなたが伝統的なアマチュア無線家であるならば、恐らくこれらのパラメータは既により適した値に変更されているはずです。 + + プロファイルメニューを使うと、8個の異なるメニュースロットに、あなたが良く使う復調パラメータを一括して名前を付けて登録でき、またそれを好きなときに呼び出すことができますので、実験がやり易くなると思います。 + + プロファイル機能を使う場合、最も重要な点は、まず現状のあなたが気に入っている復調パラメータを「MyDefault」のような名前で登録しておくことです。こうしておけば、パラメータの組み合わせが判らなくなった場合でも、その状態に復帰させることができます。 + + またMMSSTVは変更(登録)できない「MMSSTV Default」というプロファイルを持ちます。このメニューを選択するとあなたが一番最初にMMSSTVをインストールした時のMMSSTVのデフォルトの復調パラメータに戻すことができます。 + +*プロファイルで記憶できるパラメータはPLLとゼロクロス検波のパラメータに限られます。 + +==================== +◎受信用補助フィルタ +==================== + MMSSTVには3つの受信用補助フィルタがあります。 + + Sound ---> Notch ---> LMS -+-> BPF ---> Demodulator + | + --> Spectrum display + +[Notch] + 単純なFIR型のBEFです。このフィルタはスペクトラムまたはウォータフォールでマウス左ボタンを押すと、その周波数でONになり、マウス右ボタンを押すとOFFになります。 + ビート混信除去の目的で使用することができますが、画像帯域内にノッチフィルタを設定した場合、受信画像は若干劣化します。また同期信号周波数にノッチを設けた場合、「自動停止」をONにしていると弱い信号では画像受信が停止する場合があります。 + +[LMS] + 「Leaky LMS(Least Mean Square)法」による適応フィルタです。このフィルタはメイン画面のDSPパネルにON/OFFスイッチがあります。デフォルトはノイズスムージングになっていますが、オートノッチを選択することもできます(マウス右ボタンで動作を選択します)。 + オートノッチは画質への影響を軽減するため応答を遅めにしてありますが、それでも画材によって著しく画質が劣化する場合があります。 + +[BPF] + 単純なFIR型のBPFです。このフィルタは、オプションメニューの設定画面の「受信」ページで特性を選択できます。このフィルタを鋭くすると水平解像度は悪化しますが、近接信号のQRMには強くなります。 + + +================ +◎送信用フィルタ +================ + MMSSTVの送信信号は以下のような系統で出力されます。 + +Picture data ---> LPF ---> VCO ---> BPF ---> D/A ---> Sound data + ON/OFF ON/OFF + + LPFおよびBPFはデジタル出力の帯域を制限するための保険の意味で設けてあります。送信時のCPU負荷が重い場合は、これらのフィルタをOFF(設定画面の送信ページでチェックを外す)にすると良いでしょう。 + しかしCWIDをONにしている場合は、BPFにチェックを付けておくことをお勧めします。 + +[LPF] + このフィルタをONにすると画像信号を周波数に変換する際、滑らかに変化するように働きます。結果として帯域は大きく制限されますが、送信画像の水平方向の解像度は少し悪くなります。 + +[BPF] + このフィルタをONにすると送信信号そのものの帯域を制限します。CWIDをONにしている場合にキャリアの断続部分でのスペクトラムの広がりを抑えることができます。 + + +================ +◎サウンドカード +================ + +1.サンプリング周波数の選択 +~~~~~~~~~~~~~~~~~~~~~~~~~~ + MMSSTVでは8000Hzから44100Hzまで以下のように動作サンプリング周波数を選択することができます。 + + 8000Hz 準サウンドカード標準周波数 + 11025Hz サウンドカード標準周波数 + 12000Hz + 14000Hz + 16000Hz + 18000Hz + 22050Hz サウンドカード標準周波数 + 24000Hz + 44100Hz サウンドカード標準周波数 + + 復調器にゼロクロス方式、PLL方式を使っている場合は、サンプリング周波数を高くし、Out LPFのカットオフ周波数を高くすると画質が良くなります。しかし復調器にヒルベルト変換方式を使っている場合は、デフォルトの11025Hzを選択したほうがFBです。 + + 11025Hz,22050Hz,44100Hz以外の周波数でサウンドカードが動作するかどうかは、そのカードに依存します。 + また高いサンプリング周波数は低いサンプリング周波数と比較して、よりCPUパワーを消費し、またメモリも消費しますので、それらが使用可能かどうかはお使いのパソコンのスペックに大きく依存します。 + +* MMSSTVのFFTは常に2048ポイントで計算します。必要な周波数分解能を得るために、18000Hz以上を選択した場合、FFTのみ1/2の周波数で動作します。同様に44100Hzを選択した場合、1/4の周波数で動作します。 + + +2.クロックの較正 +~~~~~~~~~~~~~~~~ + SSTVではサンプリング周波数のズレは画像の傾斜となって現れます。MMSSTVの場合、サウンドカードの絶対的な精度は必要はなく、その実際の周波数をMMSSTVが正確に知っていることのみが重要です。 + + 受信した画像によってSync画面で傾斜を調整した場合、その信号が正確なタイミングを持っているならば、比較的正確な精度でクロックの較正が完了したことになり、通常はそれでも充分だと思います。 + + しかしあなたが絶対的な精度でタイミングを調整したい場合は、時報標準電波またはFAX放送を受信して、サウンドカードのクロック周波数を計測することができます。 + + 1) MMSSTV設定画面の「その他」のページの「Adj」ボタンを押します。 + 2) 時報標準電波(WWV, JJY等)を受信します。 + 3) 時報チック音の周波数を合わせます。 + 4) しばらく受信するとチック音が縦のラインとなって表示されます。 + 5) その縦のラインの上の点をクリックします。 + 6) 次にそのラインの下の点をクリックすると較正は終了します。 + + クリックする2点間の距離が長いほど正確に較正できますので、周波数を合わせた後は画面を最大化したほうが良いでしょう。 + またクリックする縦のラインは幅を持ちますので、その同じ位置をクリックすることが重要です。1点目をクリックした後は補助ラインが表示されますので、その補助ラインが縦のラインと平行になるようにすればOKです。 + + 残念ながら日本の時報標準電波(JJY)は2001年の3月で停波しますが、時報標準電波の代わりにFAX放送を受信しても同様の調整ができます。ただし受信しているFAX信号が正確なタイミングを持っている必要があります。 + またNTTテレホンサービスの時報信号も時報標準電波と同じように使うことができます。 + + +3.送信時のサンプリング周波数のオフセットの調整 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + 受信時と送信時でサウンドカードのサンプリング周波数が異なる場合、以下の手順で送信時のオフセット周波数を調整します。 + + 1) まず受信で傾き調整が完了している状態であることが前提条件です。 + 2) 設定画面の「送信」ページのループバックを「外部(衛星通信用)」にします。 + 3) サウンドカードのLineOutとLineInを接続します。 + 4) Martin 1で画像を送信します。 + 5) 外部ループバックにより送信画像が自動受信されるはずです。 + 6) 受信が完了したら「同期」ページに行き、傾きの調整を行います。 + - 同期画面のニコニコマークを押し「高精度傾き調整」を + 実行すると良いでしょう + - 「記憶」ボタンは押さないで下さい。 + 7) 傾きがなくなったら同期画面の「TX」ボタンを押します。 + 8) 以上で送信オフセット周波数の調整は完了です。念の為に再度送信し、 + 傾きがなくなっていることを確認して下さい。もし傾きが残留している + 場合は、再度(6)以降の手順を繰り返します。 + + サウンドカードのLineOutとLineInを接続する代わりに、ミキサープログラムのLoopBackを選択しても構いません。 + なお、この操作はFull-Duplex(再生・録音同時動作)をサポートするサウンドカードでしか行うことができませんが、Full-Duplexをサポートしないサウンドカードでは、もともと送受のサンプリング周波数が異なるようなことはありませんのでこの調整は不要なはずです。 + + もし送信画像が大きく傾くというリポートを貰った場合は、サウンドカードをモノラル動作ではなく、ステレオ動作に変更してみて下さい(設定画面の「Source」)。 + また一部のカードはFull-Duplex動作時とそうでない場合でもサンプリング周波数が異なる場合があるようです。当然、そのような場合は外部ループバックによるオフセット調整を行っても意味がありません。この場合、常にループバックを外部(衛星通信用)の状態で使用するか、または相手局からのリポートに頼る必要があります。 + + +4.設定画面のサウンドカード設定 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +[FIFO] + 低レベルサウンド処理のFIFOバッファの数を設定します。FIFOバッファの数を多くするとサウンド処理のマージンが増え、タイミングをロストする確立が減少します。 + + 受信時にタイミングをロストする場合、RX FIFOの数を増やします。また送信時にタイミングをロストする場合はTX FIFOの数を増やすと良いでしょう。 + + +[処理の優先度] + 低レベルサウンド処理に与える処理の優先順位を設定します。受信中または送信中にサウンドをロストする場合、優先順位を高く設定すると良いでしょう。逆にメニュー操作の応答が遅い場合は優先順位を下げると良いでしょう。 + +[DeviceID] + 使用するサウンドカードのID番号を指定します。サウンドカードが1枚しか存在しない場合は-1または0を設定して下さい。-1はデフォルトのサウンドカードを使います。 + サウンドカードのID番号は、通常0から順番に暗黙に割り当てられます。したがってパソコン上に複数枚のサウンドカードが存在し、例えば2枚目のカードを使用したい場合は1を設定すると良いでしょう。 + +[入力チャンネル] + サウンドカードの使用チャンネルを指定します。「モノラル」を選択するとモノラル動作になります。「左 ch.」または「右 ch.」を指定するとステレオ動作で指定したチャンネルからのデータを入力信号として使用します。いずれの場合も送信時は常に両方のチャンネルに信号が出力されます。 + +[Clock] + MMSSTVの処理サンプリング周波数を設定します。詳細は前項の「サンプリング周波数の選択」および「クロックの較正」を参照して下さい。 + + +======== +◎最後に +======== + このプログラムはアマチュア無線用フリーソフトウエアです。あなたの裁量において自由に使用し配布することができます。 + より詳細な情報が必要な場合は、以下のリフレクタ(メーリングリスト)または掲示板に参加すると良いかも知れません。 + + http://www.egroups.co.jp/group/mmhamsoft/ + + +* MMSSTVのJPEGファイルコンバータは「Independent JPEG Group」のフリーソースファイル「IJG code」がベースになっています。 + +73, Mako \ No newline at end of file diff --git a/MMlink.cpp b/MMlink.cpp new file mode 100644 index 0000000..3dbba5b --- /dev/null +++ b/MMlink.cpp @@ -0,0 +1,408 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "MMLink.h" +//--------------------------------------------------------------------------- +__fastcall CMMList::CMMList(void) +{ + m_pList = NULL; +} +//--------------------------------------------------------------------------- +__fastcall CMMList::~CMMList() +{ + delete m_pList; +} +//--------------------------------------------------------------------------- +int __fastcall CMMList::QueryList(LPCSTR pFilter) +{ + if( m_pList == NULL ) m_pList = new TStringList; + m_pList->Clear(); + m_FilterLen = strlen(pFilter); + + HANDLE hFind; + WIN32_FIND_DATA fd; + + char Name[MAX_PATH]; + sprintf(Name, "%s*.%s", BgnDir, pFilter); + hFind = ::FindFirstFile(Name, &fd); + if( hFind != INVALID_HANDLE_VALUE ){ + while(1){ + m_pList->Add(fd.cFileName); + if( !FindNextFile(hFind, &fd) ) break; + } + ::FindClose(hFind); + } + return m_pList->Count; +} +//--------------------------------------------------------------------------- +LPCSTR __fastcall CMMList::GetItemName(int n) +{ + if( n < 0 ) return NULL; + if( n >= m_pList->Count ) return NULL; + + m_Name = m_pList->Strings[n].c_str(); + LPSTR p = lastp(m_Name.c_str()); + p -= m_FilterLen; + *p = 0; + return m_Name.c_str(); +} +//--------------------------------------------------------------------------- +LPCSTR __fastcall CMMList::GetFileName(int n) +{ + if( n < 0 ) return NULL; + if( n >= m_pList->Count ) return NULL; + + m_Name = m_pList->Strings[n]; + return m_Name.c_str(); +} +//--------------------------------------------------------------------------- +int __fastcall CMMList::IndexOf(LPCSTR pKey) +{ + for( int i = 0; i < m_pList->Count; i++ ){ + if( !strcmpi(GetItemName(i), pKey) ) return i; + } + return -1; +} +//*************************************************************************** +// CMMLink class +//--------------------------------------------------------------------------- +__fastcall CMMLink::CMMLink(HWND hWnd, UINT uMsg) +{ + m_hLib = NULL; + m_hWnd = hWnd; + m_uMsg = uMsg; + m_Caps = 0; +} +//--------------------------------------------------------------------------- +__fastcall CMMLink::~CMMLink() +{ + Close(); +} +//--------------------------------------------------------------------------- +void __fastcall CMMLink::FreeLib(void) +{ + if( m_hLib ){ + FreeLibrary(m_hLib); + m_hLib = NULL; + } +} +//--------------------------------------------------------------------------- +FARPROC __fastcall CMMLink::GetProc(LPCSTR pName) +{ + if( !m_hLib ) return NULL; + + FARPROC fn = ::GetProcAddress(m_hLib, pName+1); + if( fn == NULL ){ + fn = ::GetProcAddress(m_hLib, pName); + if( fn == NULL ) FreeLib(); + } + return fn; +} +//--------------------------------------------------------------------------- +void __fastcall CMMLink::Close(void) +{ + if( IsLib() ){ + fmmlClose(); + FreeLib(); + } + m_Connected = FALSE; +} +//--------------------------------------------------------------------------- +BOOL __fastcall CMMLink::Open(LPCSTR pItemName) +{ + Close(); + + m_ItemName = pItemName; + m_SessionName = m_ItemName; + char LibName[MAX_PATH]; + if( !*GetEXT(pItemName) ){ + sprintf(LibName, "%s.mml", pItemName); + pItemName = LibName; + } + + m_hLib = ::LoadLibrary(pItemName); + if( m_hLib ){ + + fmmlOpen = (tmmlOpen)GetProc("_mmlOpen"); + fmmlClose = (tmmlClose)GetProc("_mmlClose"); + fmmlSetHandle = (tmmlSetHandle)GetProc("_mmlSetHandle"); + fmmlIsCap = (tmmlIsCap)GetProc("_mmlIsCap"); + fmmlIsConnected = (tmmlIsConnected)GetProc("_mmlIsConnected"); + fmmlGetSessionName = (tmmlGetSessionName)GetProc("_mmlGetSessionName"); + fmmlQuery = (tmmlQuery)GetProc("_mmlQuery"); + fmmlSetFreq = (tmmlSetFreq)GetProc("_mmlSetFreq"); + fmmlLog = (tmmlLog)GetProc("_mmlLog"); + fmmlLogClear = (tmmlLogClear)GetProc("_mmlLogClear"); + fmmlSetPTT = (tmmlSetPTT)GetProc("_mmlSetPTT"); + fmmlOnCopyData = (tmmlOnCopyData)GetProc("_mmlOnCopyData"); + fmmlEventVFO = (tmmlEventVFO)GetProc("_mmlEventVFO"); + + if( m_hLib ){ + if( fmmlOpen(m_hWnd, m_uMsg) ){ + m_Caps = fmmlIsCap(); + } + else { + FreeLib(); + } + } + } + return IsLib(); +} +//--------------------------------------------------------------------------- +void __fastcall CMMLink::SetHandle(HWND hWnd, UINT uMsg) +{ + m_hWnd = hWnd; + m_uMsg = uMsg; + if( !IsLib() ) return; + fmmlSetHandle(hWnd, m_uMsg); +} +//--------------------------------------------------------------------------- +void __fastcall CMMLink::NotifySession(LPCSTR pSession) +{ + if( pSession ){ + m_Connected = TRUE; + m_SessionName = pSession; + } + else { + m_Connected = FALSE; + } +} +//--------------------------------------------------------------------------- +BOOL __fastcall CMMLink::IsConnected(void) +{ + if( !IsLib() ) return FALSE; + if( m_Caps & capNOTIFYSESSION ) return m_Connected; + return fmmlIsConnected(); +} +//--------------------------------------------------------------------------- +LPCSTR __fastcall CMMLink::GetSessionName(void) +{ + if( !IsLib() ) return NULL; + if( m_Caps & capNOTIFYSESSION ) return m_SessionName.c_str(); + return fmmlGetSessionName(); +} +//--------------------------------------------------------------------------- +void __fastcall CMMLink::Query(LPCSTR pCall) +{ + if( !IsLib() ) return; + fmmlQuery(pCall); +} +//--------------------------------------------------------------------------- +void __fastcall CMMLink::SetFreq(LPCSTR pFreq) +{ + if( !IsLib() ) return; + fmmlSetFreq(pFreq); +} +//--------------------------------------------------------------------------- +void __fastcall CMMLink::SetPTT(int ptt) +{ + if( !IsLib() ) return; + fmmlSetPTT(ptt); +} +//--------------------------------------------------------------------------- +void __fastcall CMMLink::LogWrite(SDMMLOG *sp, int sw) +{ + if( !IsLib() ) return; + mmLOGDATA ml; + ConvFormat(&ml, sp); + fmmlLog(&ml, sw); +} +//--------------------------------------------------------------------------- +void __fastcall CMMLink::Clear(void) +{ + if( !IsLib() ) return; + fmmlLogClear(); +} +//--------------------------------------------------------------------------- +void __fastcall CMMLink::EventVFO(void) +{ + if( !IsLib() ) return; + fmmlEventVFO(); +} +//--------------------------------------------------------------------------- +LONG __fastcall CMMLink::OnCopyData(HWND hSender, const COPYDATASTRUCT *pcds) +{ + if( !IsLib() ) return FALSE; + if( !(m_Caps & capWMCOPYDATA) ) return FALSE; + return fmmlOnCopyData(hSender, pcds); +} +//--------------------------------------------------------------------------- +void __fastcall CMMLink::SetTime(SYSTEMTIME *tp, int sw) +{ + if( sw ){ + m_TimeLogOFF = *tp; + } + else { + m_TimeLogON = *tp; + } +} +//--------------------------------------------------------------------------- +void __fastcall CMMLink::ConvFormat(mmLOGDATA *pLog, const SDMMLOG *sp) +{ + memset(pLog, 0, sizeof(mmLOGDATA)); + + if( sp->btime ) pLog->m_TimeLogON = m_TimeLogON; + if( sp->etime ) pLog->m_TimeLogOFF = m_TimeLogOFF; + StrCopy(pLog->m_Call, sp->call, sizeof(pLog->m_Call)- 1); + strcpy(pLog->m_Mode, Log.GetModeString(sp->mode)); + strcpy(pLog->m_Freq, Log.GetFreqString(sp->band, sp->fq)); + memcpy(pLog->m_His, sp->ur, sizeof(pLog->m_His)); + memcpy(pLog->m_My, sp->my, sizeof(pLog->m_My)); + StrCopy(pLog->m_Name, sp->name, sizeof(pLog->m_Name)- 1); + StrCopy(pLog->m_QTH, sp->qth, sizeof(pLog->m_QTH)- 1); + StrCopy(pLog->m_Pow, sp->pow, sizeof(pLog->m_Pow)- 1); + StrCopy(pLog->m_Note, sp->rem, sizeof(pLog->m_Note)- 1); + StrCopy(pLog->m_QSL, sp->qsl, sizeof(pLog->m_QSL)- 1); + StrCopy(pLog->m_DXCC, sp->opt1, sizeof(pLog->m_DXCC)- 1); + StrCopy(pLog->m_Cont, sp->opt2, sizeof(pLog->m_Cont)- 1); + pLog->m_QSLS = sp->send; + pLog->m_QSLR = sp->recv; +} + + +//*************************************************************************** +// CMMRadio class +//--------------------------------------------------------------------------- +__fastcall CMMRadio::CMMRadio(HWND hWnd, UINT uMsg) +{ + m_hLib = NULL; + m_hWnd = hWnd; + m_uMsg = uMsg; +} +//--------------------------------------------------------------------------- +__fastcall CMMRadio::~CMMRadio() +{ + Close(); +} +//--------------------------------------------------------------------------- +void __fastcall CMMRadio::FreeLib(void) +{ + if( m_hLib ){ + FreeLibrary(m_hLib); + m_hLib = NULL; + } +} +//--------------------------------------------------------------------------- +FARPROC __fastcall CMMRadio::GetProc(LPCSTR pName) +{ + if( !m_hLib ) return NULL; + + FARPROC fn = ::GetProcAddress(m_hLib, pName+1); + if( fn == NULL ){ + fn = ::GetProcAddress(m_hLib, pName); + if( fn == NULL ) FreeLib(); + } + return fn; +} +//--------------------------------------------------------------------------- +void __fastcall CMMRadio::Close(void) +{ + if( IsLib() ){ + fmmrpClose(); + FreeLib(); + } +} +//--------------------------------------------------------------------------- +BOOL __fastcall CMMRadio::Open(LPCSTR pItemName) +{ + Close(); + + m_ItemName = pItemName; + char LibName[MAX_PATH]; + if( !*GetEXT(pItemName) ){ + sprintf(LibName, "%s.mmr", pItemName); + pItemName = LibName; + } + m_hLib = ::LoadLibrary(pItemName); + if( m_hLib ){ + + fmmrpOpen = PROC(mmrpOpen); + fmmrpClose = PROC(mmrpClose); + fmmrpSetHandle = PROC(mmrpSetHandle); + fmmrpGetStatus = PROC(mmrpGetStatus); + fmmrpSetPTT = PROC(mmrpSetPTT); + fmmrpPutChar = PROC(mmrpPutChar); + fmmrpGetChar = PROC(mmrpGetChar); + fmmrpPolling = PROC(mmrpPolling); + fmmrpGetFreq = PROC(mmrpGetFreq); + fmmrpGetDefCommand = PROC(mmrpGetDefCommand); + + if( m_hLib ){ + if( !fmmrpOpen(m_hWnd, m_uMsg) ){ + FreeLib(); + } + } + } + return IsLib(); +} +//--------------------------------------------------------------------------- +void __fastcall CMMRadio::SetHandle(HWND hWnd, UINT uMsg) +{ + m_hWnd = hWnd; + m_uMsg = uMsg; + if( !IsLib() ) return; + fmmrpSetHandle(hWnd, uMsg); +} +//--------------------------------------------------------------------------- +void __fastcall CMMRadio::SetPTT(int ptt) +{ + if( !IsLib() ) return; + fmmrpSetPTT(ptt); +} +//--------------------------------------------------------------------------- +void __fastcall CMMRadio::PutChar(BYTE c) +{ + if( !IsLib() ) return; + fmmrpPutChar(c); +} +//--------------------------------------------------------------------------- +BYTE __fastcall CMMRadio::GetChar(void) +{ + if( !IsLib() ) return 0; + return fmmrpGetChar(); +} +//--------------------------------------------------------------------------- +DWORD __fastcall CMMRadio::GetStatus(void) +{ + if( !IsLib() ) return 0; + return fmmrpGetStatus(); +} +//--------------------------------------------------------------------------- +void __fastcall CMMRadio::Polling(void) +{ + if( !IsLib() ) return; + fmmrpPolling(); +} +//--------------------------------------------------------------------------- +DWORD __fastcall CMMRadio::GetFreq(void) +{ + if( !IsLib() ) return 0; + return fmmrpGetFreq(); +} +//--------------------------------------------------------------------------- +DWORD __fastcall CMMRadio::GetDefCommand(void) +{ + if( !IsLib() ) return 0; + return fmmrpGetDefCommand(); +} + diff --git a/MMlink.h b/MMlink.h new file mode 100644 index 0000000..f836ef5 --- /dev/null +++ b/MMlink.h @@ -0,0 +1,152 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + + +#ifndef MMLinkH +#define MMLinkH + +#include "ComLib.h" +#include "LogConv.h" +#include "mml.h" +#include "mmrp.h" + +#define PROC(Key) ((t##Key)GetProc("_" #Key)) + +class CMMList +{ +private: + TStringList *m_pList; + AnsiString m_Name; + int m_FilterLen; +public: + __fastcall CMMList(void); + __fastcall ~CMMList(); +public: // List functions + int __fastcall QueryList(LPCSTR pFilter); + int __fastcall GetCount(void){return m_pList->Count;}; + LPCSTR __fastcall GetItemName(int n); + LPCSTR __fastcall GetFileName(int n); + int __fastcall IndexOf(LPCSTR pKey); + inline BOOL __fastcall IsQuery(void){return m_pList != NULL;}; +}; + +class CMMLink +{ +private: + AnsiString m_ItemName; + + HWND m_hWnd; + UINT m_uMsg; + + HINSTANCE m_hLib; //ja7ude 0521 + DWORD m_Caps; + + int m_Connected; + AnsiString m_SessionName; + + SYSTEMTIME m_TimeLogON; + SYSTEMTIME m_TimeLogOFF; +private: + tmmlOpen fmmlOpen; + tmmlClose fmmlClose; + tmmlSetHandle fmmlSetHandle; + tmmlIsCap fmmlIsCap; + tmmlIsConnected fmmlIsConnected; + tmmlGetSessionName fmmlGetSessionName; + tmmlQuery fmmlQuery; + tmmlSetFreq fmmlSetFreq; + tmmlLog fmmlLog; + tmmlLogClear fmmlLogClear; + tmmlSetPTT fmmlSetPTT; + tmmlOnCopyData fmmlOnCopyData; + tmmlEventVFO fmmlEventVFO; +private: + void __fastcall FreeLib(void); + FARPROC __fastcall GetProc(LPCSTR pName); + void __fastcall ConvFormat(mmLOGDATA *pLog, const SDMMLOG *sp); +public: + __fastcall CMMLink(HWND hWnd, UINT uMsg); + __fastcall ~CMMLink(); +public: // LogLink functions + BOOL __fastcall Open(LPCSTR pLibName); + void __fastcall Close(void); + void __fastcall SetHandle(HWND hWnd, UINT uMsg); + inline BOOL __fastcall IsLib(void){ return (m_hLib != NULL);}; + inline LPCSTR __fastcall GetItemName(void){return m_ItemName.c_str();}; + + void __fastcall NotifySession(LPCSTR pSession); + + BOOL __fastcall IsConnected(void); + LPCSTR __fastcall GetSessionName(void); + void __fastcall Query(LPCSTR pCall); + void __fastcall SetFreq(LPCSTR pFreq); + void __fastcall SetPTT(int ptt); + void __fastcall LogWrite(SDMMLOG *sp, int sw); + void __fastcall Clear(void); + void __fastcall EventVFO(void); + LONG __fastcall OnCopyData(HWND hSender, const COPYDATASTRUCT *pcds); + inline DWORD __fastcall GetCaps(void){return m_Caps;}; + void __fastcall SetTime(SYSTEMTIME *tp, int sw); + +}; + + +class CMMRadio +{ +private: + AnsiString m_ItemName; + + HINSTANCE m_hLib; //ja7ude 0521 + HWND m_hWnd; + UINT m_uMsg; + +private: + tmmrpSetHandle fmmrpSetHandle; + tmmrpOpen fmmrpOpen; + tmmrpClose fmmrpClose; + tmmrpGetStatus fmmrpGetStatus; + tmmrpSetPTT fmmrpSetPTT; + tmmrpPutChar fmmrpPutChar; + tmmrpGetChar fmmrpGetChar; + tmmrpPolling fmmrpPolling; + tmmrpGetFreq fmmrpGetFreq; + tmmrpGetDefCommand fmmrpGetDefCommand; + +private: + void __fastcall FreeLib(void); + FARPROC __fastcall GetProc(LPCSTR pName); +public: + __fastcall CMMRadio(HWND hWnd, UINT uMsg); + __fastcall ~CMMRadio(); +public: + void __fastcall SetHandle(HWND hWnd, UINT uMsg); + BOOL __fastcall Open(LPCSTR pLibName); + void __fastcall Close(void); + inline BOOL __fastcall IsLib(void){ return (m_hLib != NULL);}; + inline LPCSTR __fastcall GetItemName(void){return m_ItemName.c_str();}; + + void __fastcall SetPTT(int ptt); + void __fastcall PutChar(BYTE c); + BYTE __fastcall GetChar(void); + DWORD __fastcall GetStatus(void); + void __fastcall Polling(void); + DWORD __fastcall GetFreq(void); + DWORD __fastcall GetDefCommand(void); +}; +#endif diff --git a/MacroKey.cpp b/MacroKey.cpp new file mode 100644 index 0000000..dc6f401 --- /dev/null +++ b/MacroKey.cpp @@ -0,0 +1,162 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "MacroKey.h" +#include "ComLib.h" +//--------------------------------------------------------------------- +#pragma resource "*.dfm" +//TMacroKeyDlg *MacroKeyDlg; +MACKEY mackeycom[]={ + {1, "%m","My callsign", NULL}, + {1, "%c","His/her callsign", NULL}, + {1, "%r","His/her RSV", NULL}, + {1, "%n","His/her name", NULL}, + {2, "%J","His/her name (+サン)", NULL}, + {1, "%q","His/her QTH", NULL}, + {1, "%s","My RSV", NULL}, + {1, "%R","His/her RSVのRSV部分のみ","Only the RSV part of his/her RSV"}, + {1, "%N","His/her RSVのコンテストナンバ部分のみ","Only the contest number part of his/her RSV"}, + {1, "%M","My RSVのコンテストナンバ部分のみ","Only the contest number part of my RSV"}, + {1, "%g","GOOD MORNING/AFTERNOON/EVENING", NULL}, + {1, "%f","GM/GA/GE", NULL}, + {1, "%D","UTC date (e.g., 2000-SEP-05)", NULL}, + {1, "%T","UTC time (e.g., 12:34)", NULL}, + {1, "%t","UTC time (e.g., 1234)", NULL}, + {1, "%L","Local date (e.g., 2000-SEP-05)", NULL}, + {1, "%U","Local time (e.g., 12:34)", NULL}, + {1, "%u","Local time (e.g., 1234)", NULL}, + {1, "%B","周波数", "frequency"}, + {1, "%b","バンド", "band"}, + {1, "%o","Note", NULL}, + {1, "%X","Receipt time(UTC) of the current image", NULL}, + {1, "%v","MMSSTV version", NULL}, + {1, "%V","Beta version", NULL}, + {0, NULL, NULL}, +}; +static int intPos; //ja7ude 0521 +static int TopPos; +//--------------------------------------------------------------------- +__fastcall TMacroKeyDlg::TMacroKeyDlg(TComponent* AOwner) + : TForm(AOwner) +{ + FormStyle = ((TForm *)AOwner)->FormStyle; + Font->Name = ((TForm *)AOwner)->Font->Name; + Font->Charset = ((TForm *)AOwner)->Font->Charset; + if( MsgEng ){ + CancelBtn->Caption = "Cancel"; + OKBtn->Caption = "Insert"; + } +} +//--------------------------------------------------------------------- +void __fastcall TMacroKeyDlg::UpdateUI(int row) +{ + int r = row - 1; + if( r >= 0 ){ + OKBtn->Enabled = TRUE; + } + else { + OKBtn->Enabled = FALSE; + } +} +//--------------------------------------------------------------------- +int __fastcall TMacroKeyDlg::AddMacKey(MACKEY *mp, int n) +{ + for( ; mp->r; mp++){ + if( (mp->r == 2) && MsgEng ) continue; + mackey[n] = *mp; + n++; + } + return n; +} +//--------------------------------------------------------------------- +int __fastcall TMacroKeyDlg::Execute(AnsiString &as) +{ + int n = 0; + n = AddMacKey(mackeycom, n); + Grid->RowCount = 1 + n; + if( (intPos > 0) && (intPos < Grid->RowCount) ){ //ja7ude 0521 + Grid->Row = intPos; + Grid->TopRow = TopPos; + } + UpdateUI(Grid->Row); + int r = ShowModal(); + intPos = Grid->Row; //ja7ude 0521 + TopPos = Grid->TopRow; + if( r == IDOK ){ + if( intPos ){ //ja7ude 0521 + r = intPos - 1; + as = mackey[r].pKey; + return TRUE; + } + } + return FALSE; +} +//--------------------------------------------------------------------- +void __fastcall TMacroKeyDlg::GridDrawCell(TObject *Sender, int Col, + int Row, TRect &Rect, TGridDrawState State) +{ + char bf[256]; + + Grid->Canvas->FillRect(Rect); + int X = Rect.Left + 4; + int Y = Rect.Top + 2; + + if( Row ){ + Row--; + bf[0] = 0; + LPCSTR pCom; + switch(Col){ + case 0: + strcpy(bf, mackey[Row].pKey); + break; + case 1: + if( MsgEng ){ + pCom = mackey[Row].pEng; + if( pCom == NULL ){ + pCom = mackey[Row].pJpn; + } + } + else { + pCom = mackey[Row].pJpn; + } + strcpy(bf, pCom); + break; + } + Grid->Canvas->TextOut(X, Y, bf); + } + else { // タイトル + LPCSTR _tt[]={ + "Key","Comments", + }; + Grid->Canvas->TextOut(X, Y, _tt[Col]); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMacroKeyDlg::GridSelectCell(TObject *Sender, int Col, + int Row, bool &CanSelect) +{ + UpdateUI(Row); +} +//--------------------------------------------------------------------------- + + diff --git a/MacroKey.dfm b/MacroKey.dfm new file mode 100644 index 0000000..c4cd276 Binary files /dev/null and b/MacroKey.dfm differ diff --git a/MacroKey.h b/MacroKey.h new file mode 100644 index 0000000..3d14c01 --- /dev/null +++ b/MacroKey.h @@ -0,0 +1,67 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//---------------------------------------------------------------------------- +#ifndef MacroKeyH +#define MacroKeyH +//---------------------------------------------------------------------------- +//ja7ude 0428 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//---------------------------------------------------------------------------- +typedef struct { + int r; + LPCSTR pKey; + LPCSTR pJpn; + LPCSTR pEng; +}MACKEY; + +class TMacroKeyDlg : public TForm +{ +__published: + TButton *OKBtn; + TButton *CancelBtn; + TStringGrid *Grid; + void __fastcall GridDrawCell(TObject *Sender, int Col, int Row, + TRect &Rect, TGridDrawState State); + void __fastcall GridSelectCell(TObject *Sender, int Col, int Row, + bool &CanSelect); +private: + MACKEY mackey[32]; + int __fastcall AddMacKey(MACKEY *mp, int n); + void __fastcall UpdateUI(int row); + +public: + virtual __fastcall TMacroKeyDlg(TComponent* AOwner); + + int __fastcall Execute(AnsiString &as); +}; +//---------------------------------------------------------------------------- +//extern TMacroKeyDlg *MacroKeyDlg; +//---------------------------------------------------------------------------- +#endif diff --git a/Main.cpp b/Main.cpp new file mode 100644 index 0000000..be5e3f0 --- /dev/null +++ b/Main.cpp @@ -0,0 +1,14464 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------------- +#include +#pragma hdrstop + +#include +#include +#include "Clipbrd.hpp" +#include "Main.h" +#include "Scope.h" +#include "PlayDlg.h" +#include "Option.h" +#include "LogFile.h" +#include "LogList.h" +#include "LogConv.h" +#include "LogLink.h" +#include "country.h" +#include "Qsodlg.h" +#include "Mmcg.h" +#include "VerDsp.h" +#include "LogSet.h" +#include "PicRect.h" +#include "ZoomView.h" +#include "TextEdit.h" +#include "ListText.h" +#include "PicFilte.h" +#include "ExtCmd.h" +#include "PerSpect.h" +#include "RepSet.h" +#include "MmcgDlg.h" +#include "radioset.h" +#include "RMenuDlg.h" +//--------------------------------------------------------------------------- +#pragma package(smart_init) +#pragma resource "*.dfm" +TMmsstv *Mmsstv; +#define MEASCWSPEED FALSE + +#define FSKIDMAX 32 +//ウインドウメッセージのハンドラ--------------------------------------------- +void __fastcall TMmsstv::WndProc(TMessage &Message) +{ + switch(Message.Msg){ + case WM_COPYDATA: + WndCopyData(Message); + break; + default: + TForm::WndProc(Message); + break; + } +} +//--------------------------------------------------------------------------- +// WM_COPYDATAの処理 +void __fastcall TMmsstv::WndCopyData(TMessage &Message) +{ + COPYDATASTRUCT *cp = (COPYDATASTRUCT *)Message.LParam; + if( LogLink.IsCopyData() ){ + Message.Result = LogLink.m_pLink->OnCopyData(HWND(Message.WParam), cp); + return; + } + switch(cp->dwData){ + case 0: + case 1: // Hamlogからの返信 + if( sys.m_LogLink != 1 ) return; + switch(LogLink.AnaData(&Log.m_sd, cp)){ + case 115: + UpdateTextData(); + break; + case 106: + LogFreq->Text = Log.GetFreqString(Log.m_sd.band, Log.m_sd.fq); + break; + } + Message.Result = TRUE; + break; + case 0x80001212: // 周波数データの指定 + if( cp->cbData && (cp->lpData != NULL) ){ + char bf[16]; + int len = cp->cbData; + if( len > 15 ) len = 15; + memcpy(bf, cp->lpData, len); + bf[len] = 0; + LogFreq->Text = bf; + } + Message.Result = TRUE; + break; + case 0x80001213: // クリップボードからのロード + KESClick(NULL); + Message.Result = TRUE; + break; + case 0x80001214: // 画像サイズの問い合わせ + Message.Result = m_TXW + (m_TXH << 16); + break; + case 0x80001215: // 履歴画像のコピー + SBCopyClick(NULL); + Message.Result = TRUE; + break; + case 0x80001216: // 受信画像のコピー + KERClick(NULL); + Message.Result = TRUE; + break; + case 0x80001217: // 送信/受信の切り替え + if( cp->cbData && (cp->lpData != NULL) ){ + if( *(const BYTE *)(cp->lpData) ){ + if( !SBTX->Down ){ + AdjustPage(pgTX); + ToTX(); + } + } + else if( SBTX->Down ){ + ToRX(); + } + } + Message.Result = TRUE; + break; + case 0x80001218: + m_ChangeTemp = 1; + SBULog->Enabled = TRUE; + UpdateUI(); + Message.Result = TRUE; + break; + case 0x80001219: // REMデータの指定 + if( cp->cbData && (cp->lpData != NULL) ){ + EditNote->Text = (LPCSTR)cp->lpData; + EditNoteChange(NULL); + } + Message.Result = TRUE; + break; + case 0x8000121a: // PTT + if( cp->cbData && (cp->lpData != NULL) ){ + BOOL bPTT = *(const BYTE *)(cp->lpData); + if( pRadio != NULL ) pRadio->SetPTT(bPTT); + if( pComm != NULL ) pComm->SetPTT(bPTT); + } + break; + case 0x8000121b: // status + { + DWORD dw = SBTX->Down ? 1 : 0; + dw |= SBTune->Down ? 2 : 0; + dw |= pDem->m_Sync ? 4 : 0; + Message.Result = dw; + } + break; + default: + Message.Result = FALSE; + break; + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::OnMSG(tagMSG &Msg, bool &Handled) +{ +/* +Msg.hwnd := Handle; +Msg.message := WM_KEYDOWN; +Msg.wParam := Message.WParam; +Msg.lParam := Message.LParam; +*/ + if( Msg.message != WM_DROPFILES ) return; + + DropFile(Msg); + Handled = true; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::OnMini(TObject *Sender) +{ + if( pSound != NULL ){ + if( pSound->m_susp ){ + pSound->m_susp = 1; + } + } +} +//--------------------------------------------------------------------------- +// アプリケーション例外 +void __fastcall TMmsstv::AppException(TObject *Sender, Exception *E) +{ + if( m_AppErr < 3 ){ + m_AppErr++; + ErrorMB(MsgEng? + "The indistinct error was detected.": + "原因不明のエラーが発生しました." + ); + } + ResDisPaint(); +} +//--------------------------------------------------------------------------- +__fastcall TMmsstv::TMmsstv(TComponent* Owner) + : TForm(Owner) +{ + ::VirtualLock(this, sizeof(TMmsstv)); + ::VirtualLock(&sys, sizeof(sys)); + + m_AppErr = 0; + m_InitFirst = TRUE; + m_DisEvent = 1; + SampFreq = 11025.0; + pDraw = NULL; + pPaste = NULL; + pRxView = NULL; + pSyncView = NULL; + pHistView = NULL; + pPreView = NULL; + pCalibration = NULL; + pUndo = NULL; + pCtrBtn = NULL; + pStockView = NULL; + pWaterView = NULL; + pLogView = NULL; + + int i; + for( i = 0; i < 8; i++ ){ + pFileView[i] = NULL; + } + m_TimerRXV = 0; + m_TimerRXS = 0; + m_FileViewClose = 0; + m_ClientHeight[0] = m_ClientHeight[1] = 0; + m_ClientWidth[0] = m_ClientWidth[1] = 0; + m_SpecDown = 0; + + m_dwVersion = ::GetVersion(); + if( m_dwVersion < 0x80000000 ){ + WinNT = TRUE; // NT,2000,XP,Vista + + OSVERSIONINFO osvi; + + ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + + GetVersionEx(&osvi); + if (osvi.dwMajorVersion == 5) { + WinVista=FALSE; + } + else { + WinVista=TRUE; + } + } + else { // win95/98/ME + WinNT = FALSE; + WinVista=FALSE; + } + +#if 0 +// Get major and minor version numbers of Windows +dwWindowsMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion))); +dwWindowsMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion))); +// Get build numbers for Windows NT or Win32s +if (dwVersion < 0x80000000) // Windows NT + dwBuild = (DWORD)(HIWORD(dwVersion)); +else if (dwWindowsMajorVersion < 4) // Win32s + dwBuild = (DWORD)(HIWORD(dwVersion) & ~0x8000); +else // Windows 95 -- No build numbers provided + dwBuild = 0; +#endif + + InitFFT(); + + EntryAlign(); + lcid = GetThreadLocale() & 0x00ff; + if( lcid != LANG_JAPANESE ){ // English + sys.m_WinFontName = "Times New Roman"; + sys.m_WinFontCharset = ANSI_CHARSET; + Log.m_LogSet.m_TimeZone = 'Z'; + sys.m_LogLink = 0; + MsgEng = 1; + } + else { // Japanese + sys.m_WinFontName = "MS Pゴシック"; + sys.m_WinFontCharset = SHIFTJIS_CHARSET; + sys.m_LogLink = 1; + MsgEng = 0; + } + SetMBCP(); + sys.m_WinFontStyle = 0; + LogLink.SetHandle(Handle, CM_CMML); + + sys.m_BitPixel = ::GetDeviceCaps(Canvas->Handle, BITSPIXEL); + sys.m_Palette = sys.m_BitPixel < 16 ? 1 : 0; + sys.m_DivMode = 0; + sys.m_UseB24 = 0; + sys.m_DisFontSmooth = WinNT; + sys.m_TempDelay = 3; + + pBitmapNearest = NULL; + if( sys.m_BitPixel < 24 ){ + pBitmapNearest = new Graphics::TBitmap; + pBitmapNearest->Width = 1; + pBitmapNearest->Height = 1; + } + + pBitmapFFT = new Graphics::TBitmap(); + pBitmapFFT->Width = PBoxFFT->Width; + pBitmapFFT->Height = PBoxFFT->Height; + + pBitmapWater = new Graphics::TBitmap(); + pBitmapWater->PixelFormat = pf24bit; + pBitmapWater->Width = PBoxWater->Width; + pBitmapWater->Height = PBoxWater->Height; + + PBoxRX->Width = 320; + PBoxRX->Height = 256; + PBoxHist->Width = 320; + PBoxHist->Height = 256; + PBoxTX->Width = 320; + PBoxTX->Height = 256; + PBoxTemp->Width = 320; + PBoxTemp->Height = 256; + + pBitmapSS = NULL; + for( i = 0; i < STOCKPAGE; i++ ){ + pBitmapST[i] = NULL; + } + + m_TXW = m_RXW = 320; m_TXH = m_TXPH = m_RXH = m_RXPH = 256; + m_SMax = 6; + + pBitmapD12 = CreateBitmap(PBoxD12->Width, PBoxD12->Height, pf24bit); + + pBitmapLvl = new Graphics::TBitmap(); + pBitmapLvl->Width = PBoxLvl->Width; + pBitmapLvl->Height = PBoxLvl->Height; + + SBDPaste->Glyph->Assign(SBPaste->Glyph); + SBRView->Glyph->Assign(SBHView->Glyph); + SBTView->Glyph->Assign(SBHView->Glyph); + SBTXFil->Glyph->Assign(SBHistFil->Glyph); + SBRXFil->Glyph->Assign(SBHistFil->Glyph); + m_Slant = 0; +// m_Timer1S = 0; + m_DSEL = 0; + m_Dupe = 0; + m_DrawTrans = 0; +// m_DrawCmd = -1; + m_DrawCmd = CM_SELECT; + SBDSel->Down = TRUE; + m_DragNo = 0; + m_DragDataNo = 0; + m_DragPMax = 50; + m_TxSPage = -1; + m_PSPage = m_APSPage = 0; + for( i = 0; i < STOCKPAGE; i++ ){ + m_TSPage[i] = m_ATSPage[i] = 0; + } + m_ReqSampChg = 0; + m_TuneTimer = 0; + m_pRowBuf = NULL; + m_ReqHistF = 0; + m_SyncAccuracy = 1; + + m_TempTimer = 0; + m_TempHold = 0; + m_SuspMinimized = 0; + + InitProfile(); + + for( i = 0; i < 9; i++ ){ + m_ModeAssignTX[i] = m_ModeAssignRX[i] = i; + } + for( i = 0; i < 8; i++ ){ + sys.m_ExtMode[i] = 0; + sys.m_ExtName[i] = ""; + sys.m_ExtCmd[i] = ""; + } + char bf[256]; + ::GetWindowsDirectory(bf, sizeof(bf)); + char drv = bf[0]; + sprintf(bf, "%c:\\Program Files\\SSTV-PAL\\SSTV-Pal.exe", drv); + sys.m_ExtName[0] = "SSTV-PAL"; + sys.m_ExtCmd[0] = bf; + sys.m_ExtMode[0] = 1; + + sprintf(bf, "%c:\\Program Files\\MMTTY\\MMTTY.EXE", drv); + if( !IsFile(bf) ){ + sprintf(bf, "%c:\\MMTTY\\MMTTY.EXE", drv); + } + sys.m_ExtName[7] = "MMTTY"; + sys.m_ExtCmd[7] = bf; + sys.m_ExtMode[7] = 2; + + pComm = NULL; + pRadio = NULL; + +#if 1 + StartOption(); +#else + if( ParamCount() >= 0 ){ + SetDirName(BgnDir, ParamStr(0).c_str()); + } + else { + SetCurDir(BgnDir, sizeof(BgnDir)); + } + strcpy(BitmapDir, BgnDir); + strcpy(SBitmapDir, BgnDir); + strcpy(TemplateDir, BgnDir); + strcpy(RecDir, BgnDir); + strcpy(ExtLogDir, BgnDir); + sprintf(HistDir, "%sHistory\\", BgnDir); + sprintf(StockDir, "%sStock\\", BgnDir); +#endif + + Caption = VERTTL2; + InitSampType(); + InitCOMMPara(); + InitRADIOPara(); + sys.m_Priority = 0; + sys.m_SoundFifoRX = 12; + sys.m_SoundFifoTX = 8; + sys.m_SoundPriority = 1; + sys.m_SoundDevice = "-1"; + sys.m_SoundStereo = 0; + sys.m_StereoTX = 0; + sys.m_FFTType = 2; + sys.m_FFTGain = 5; + sys.m_FFTResp = 0; + sys.m_FFTStg = 1; + sys.m_FFTAGC = 1; + sys.m_FFTWidth = 1; + sys.m_FFTPriority = 0; + sys.m_Call = "NOCALL"; + sys.m_TxRxName = "NONE"; + sys.m_TxRxLock = 1; + sys.m_RTSonRX = 0; + + sys.m_ColorLow = clBlack; + sys.m_ColorHigh = clWhite; + sys.m_ColorFFTB = TColor(4227327); + sys.m_ColorFFT = clYellow; + sys.m_ColorFFTStg = clBlue; + sys.m_ColorFFTSync = clLime; + sys.m_ColorFFTFreq = clYellow; + sys.m_LogName = "Temp.mdt"; + sys.m_WindowState = wsNormal; + sys.m_TestDem = 0; + sys.m_TuneTXTime = -1; + sys.m_TuneSat = 0; + sys.m_ColorRXB = clWhite; + + sys.m_HDDSize = 2; + + sys.m_VOX = 0; +// sys.m_VOXSound = "1100,300,1500,100,1900,200,1500,200"; + sys.m_VOXSound = "1500,100,1700,100,2300,100,2100,100,1900,100,1500,100"; + + sys.m_Sharp2D = 0; + sys.m_Differentiator = 0; + sys.m_DiffLevelP = 1.0; + sys.m_DiffLevelM = sys.m_DiffLevelP / 3; + + sys.m_ColText[0] = TColor(255); + sys.m_ColText[1] = TColor(16711935); + sys.m_ColText[2] = TColor(65535); + sys.m_ColText[3] = TColor(16776960); + sys.m_ColText[4] = clBlack; + sys.m_ColText[5] = clBlack; + + sys.m_TextGrade = 0; + sys.m_TextShadow = 2; + sys.m_TextZero = 0; + sys.m_TextRot = 0; + sys.m_TextVert = 0; + sys.m_TextVertH = -6; + sys.m_TextStack = 0x0000fc04; + + sys.m_PicShape = 0; + sys.m_PicAdjust = 0; + sys.m_PicLineStyle = 5; + sys.m_PicLineColor = clWhite; + + sys.m_ColBar[0] = clBlack; + sys.m_ColBar[1] = TColor(0x00f0f0f0); + sys.m_ColBar[2] = clRed; + sys.m_ColBar[3] = clGreen; + + sys.m_PicSelCurCol = clWhite; + sys.m_PicSelSmooz = 0; + sys.m_PicSelRTM = 1; + + const DWORD _tbl[]={ + 16776960, 65535, 16711935, 255, + 255, 16711935, 65535, 16776960, + 12615935, 8454143, 16776960, 65280, + 16776960, 4259584, 65535, 16711935, + 255, 16711935, 65535, 65280, + 255, 4227327, 65535, 16777088, + 16776960, 65535, 4227327, 255, + 65280, 65535, 33023, 255, + }; + + for( i = 0; i < 32; i++ ){ + sys.m_ColorSet[i] = TColor(_tbl[i]); + } + + sys.m_DemOff = 0; + sys.m_DemWhite = 128.0/16384.0; + sys.m_DemBlack = 128.0/16384.0; + sys.m_DemCalibration = 0; + + for( i = 0; i < 17; i++ ){ + sys.m_Dem17[i] = m_DemPro[8].Dem17[i]; + } + + sys.m_ShowSizeRX = 0; + sys.m_ShowSizeHist = 0; + sys.m_ShowSizeTX = 0; + sys.m_ShowSizeTemp = 0; + sys.m_ShowSizeStock = 0; + + sys.m_PicClipType = 0; + sys.m_PicClipRatio = 1; + sys.m_PicClipMode = 0; + sys.m_PicClipView = 1; + sys.m_PicClipColor = clBlack; + + sys.m_Way240 = 1; + + sys.m_HistMax = 32; + sys.m_UseRxBuff = 1; + sys.m_AutoStop = 0; + sys.m_AutoSync = 1; + sys.m_CWID = 0; + sys.m_TXFSKID = 0; + sys.m_CWIDSpeed = 10; + sys.m_CWIDWPM = 28; + sys.m_CWIDText = "DE %m"; + sys.m_CWIDFreq = 1000; + sys.m_MMVID = ""; + sys.m_UseJPEG = 0; + sys.m_JPEGQuality = 80; + sys.m_CWText = "%m"; + + sys.m_nCWMenu = 7; + sys.m_CWMenu[0] = "QSL 73 TU"; + sys.m_CWMenu[1] = "NR? AGN"; + sys.m_CWMenu[2] = "QRZ?"; + sys.m_CWMenu[3] = "UR %N %N"; + sys.m_CWMenu[4] = "%c de %m"; + sys.m_CWMenu[5] = "73 TU"; + sys.m_CWMenu[6] = "VVV"; + + sys.m_FixedTxMode = 1; + + sys.m_TextList[0] = "CQ SSTV"; + sys.m_TextList[1] = "%c"; + sys.m_TextList[2] = "ur %r"; + sys.m_TextList[3] = "ur %R-%N"; + sys.m_TextList[4] = "73"; + sys.m_TextList[5] = "de %m"; + sys.m_TextList[6] = "%D %tZ"; + sys.m_TextList[7] = "%L %u Local"; + + for( i = 0; i < 4; i++ ) sys.m_RegFont[i].m_Height = 0; + + sys.m_Temp24 = TRUE; + + sys.m_MaskUserPage = 0; + sys.m_MaskCol1 = clYellow; + sys.m_MaskCol2 = clBlack; + + m_nRadioMenu = 5; + m_RadioMenu[0].strTTL = "7.033 LSB (FT847)"; + m_RadioMenu[0].strCMD = "\\$0070330001\\w10\\$0000000007\\w10"; + m_RadioMenu[1].strTTL = "14.230 USB (FT847)"; + m_RadioMenu[1].strCMD = "\\$0142300001\\w10\\$0100000007\\w10"; + m_RadioMenu[2].strTTL = "21.340 USB (FT847)"; + m_RadioMenu[2].strCMD = "\\$0213400001\\w10\\$0100000007\\w10"; + m_RadioMenu[3].strTTL = "28.680 USB (FT847)"; + m_RadioMenu[3].strCMD = "\\$0286800001\\w10\\$0100000007\\w10"; + m_RadioMenu[4].strTTL = "144.450 USB (FT847)"; + m_RadioMenu[4].strCMD = "\\$1444500001\\w10\\$0100000007\\w10"; + + ReadSampFreq(); + pSound = NULL; + pSound = new TSound(TRUE); + pDem = &pSound->SSTVDEM; + pMod = &pSound->SSTVMOD; + + pMod->m_vco.SetSampleFreq(sys.m_SampFreq + sys.m_TxSampOff); + pSound->fftIN.m_Handle = Handle; + ReadRegister(); + + pBitmapRX = CreateBitmap(PBoxRX->Width, PBoxRX->Height, pf24bit); + + pBitmapHist = CreateBitmap(PBoxHist->Width, PBoxHist->Height, -1); + pBitmapHistF = pBitmapHist; + pBitmapTemp = CreateBitmap(PBoxTemp->Width, PBoxTemp->Height, -1); + pBitmapTX = CreateBitmap(PBoxTX->Width, PBoxTX->Height, -1); + pBitmapTXM = CreateBitmap(PBoxTX->Width, PBoxTX->Height, -1); + + PanelFFT->Color = sys.m_ColorFFTB; + PanelWater->Color = sys.m_ColorLow; + FillBitmap(pBitmapRX, sys.m_ColorRXB); + FillBitmap(pBitmapHist, sys.m_ColorRXB); + + sprintf(bf, "%s"HISTNAME, HistDir); + if( !IsFile(bf) ){ + strcpy(bf, HistDir); + if( *lastp(bf) == '\\' ) *lastp(bf) = 0; + mkdir(bf); + } + sprintf(bf, "%sCurrent.bmp", StockDir); + if( !IsFile(bf) ){ + strcpy(bf, StockDir); + if( *lastp(bf) == '\\' ) *lastp(bf) = 0; + mkdir(bf); + } + + UpdateSystemFont(); + + InitColorTable(sys.m_ColorLow, sys.m_ColorHigh); + DrawFFT(1); + if( KVW->Checked ) DrawWater(1); + UpdateRecentMenu(); + UpdateModeBtn(); + DispSyncStat(); + RxHist.Open(); + UpdateHist(); + UpdateTxClip(); + Application->OnMessage = OnMSG; + Application->OnMinimize = OnMini; +#if !DEBUG + Application->OnException = AppException; +#endif + m_DisEvent = 0; + if( int(WindowState) != sys.m_WindowState ) WindowState = TWindowState(sys.m_WindowState); + pSound->fftIN.m_Handle = Handle; + SBTX->Font->Color = clRed; + + sprintf(bf, "%sMmsstv.chm", BgnDir); + if( IsFile(bf) ){ + JanHelp = "MMSSTV.CHM"; + } + else { + sprintf(bf, "%sMmsstv.hlp", BgnDir); + if( IsFile(bf) ) JanHelp = "MMSSTV.HLP"; + } + if( !JanHelp.IsEmpty() ){ + TMenuItem *pm = new TMenuItem (this); + sprintf(bf, "MMSSTV &Help (%s)", JanHelp.c_str()); + pm->Caption = bf; + pm->OnClick = KHlpMainClick; + KHelp->Insert(0, pm); + } + UpdateProFileMenu(); + ::DragAcceptFiles(PanelTX->Handle, TRUE); + ::DragAcceptFiles(PanelTemp->Handle, TRUE); + m_hClipNext = ::SetClipboardViewer(Handle); + MakeCalibrationTable(); + m_FFTWINDOW = (3010 * FFT_SIZE / FFTSamp); + + m_OrgTop = Top; + m_OrgLeft = Left; + + DivControl(sys.m_DivMode); + + m_RepBeaconCount = 0; + m_RepBeaconPos = m_RepTXPos = 0; + if( sys.m_Repeater ) SetBeaconTick(); + if( sys.m_Priority ) UpdatePriority(); + + LoadCurrentTemp(); + ChangeTxMode(SSTVSET.m_TxMode); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::StartOption(void) +{ + AnsiString as; + if( ParamCount() >= 0 ){ + as = ParamStr(0).c_str(); + SetDirName(BgnDir, as.c_str()); + } + else { + SetCurDir(BgnDir, sizeof(BgnDir)); + } + strcpy(BitmapDir, BgnDir); + strcpy(SBitmapDir, BgnDir); + strcpy(TemplateDir, BgnDir); + strcpy(MMLogDir, BgnDir); + strcpy(RecDir, BgnDir); + strcpy(ExtLogDir, BgnDir); + sprintf(HistDir, "%sHistory\\", BgnDir); + sprintf(StockDir, "%sStock\\", BgnDir); + + sys.m_bCQ100 = FALSE; + g_dblToneOffset = 0.0; + + sys.m_Repeater = 0; + for( int i = 0; i <= ParamCount(); i++ ){ + as = ParamStr(i); + if( as == "-r" ){ + sys.m_Repeater = 1; + } + else if( as == "-i" ){ + sys.m_bCQ100 = TRUE; + g_dblToneOffset = -1000.0; + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::FormCloseQuery(TObject *Sender, bool &CanClose) +{ + Application->OnException = NULL; + ::DragAcceptFiles(PanelS->Handle, FALSE); //ja7ude 0521 + ::DragAcceptFiles(PanelTX->Handle, FALSE); //ja7ude 0521 + ::ChangeClipboardChain(Handle, m_hClipNext); + + if( SBTX->Down ) ToRX(); + Timer->Enabled = FALSE; + Application->OnIdle = NULL; + if( pRadio != NULL ){ + pRadio->ReqClose(); + } + + int DivMode = sys.m_DivMode; + KVSDClick(NULL); + DivControl(0); + sys.m_DivMode = DivMode; + + KVR->Checked = pRxView != NULL; + if( pRxView != NULL ){ + pRxView->GetViewPos(sys.m_RxViewLeft, sys.m_RxViewTop, sys.m_RxViewWidth, sys.m_RxViewHeight); + delete pRxView; + pRxView = NULL; + } + KVS->Checked = pSyncView != NULL; + if( pSyncView != NULL ){ + pSyncView->GetViewPos(sys.m_SyncViewLeft, sys.m_SyncViewTop, sys.m_SyncViewWidth, sys.m_SyncViewHeight); + delete pSyncView; + pSyncView = NULL; + } + KVH->Checked = pHistView != NULL; + if( pHistView != NULL ){ + CloseHistView(); + } + KVC->Checked = pCtrBtn != NULL; + if( pCtrBtn != NULL ){ + if( pCtrBtn->SBLock->Down ){ + pCtrBtn->SBLock->Down = FALSE; + pCtrBtn->SBLockClick(NULL); + } + pCtrBtn->GetViewPos(sys.m_CtrBtnLeft, sys.m_CtrBtnTop, sys.m_CtrBtnWidth, sys.m_CtrBtnHeight); + delete pCtrBtn; + pCtrBtn = NULL; + } + int i; + for( i = 0; i < 8; i++ ){ + if( pFileView[i] != NULL ){ + int Flag = (pFileView[i]->Visible || pFileView[i]->m_Suspend) ? pFileView[i]->m_TitleBar ? 1 : 2 : 0; + CloseFileView(i); + sys.m_FileViewFlag[i] = Flag; + } + else { + sys.m_FileViewFlag[i] = 0; + } + } + if( pSound != NULL ){ + pSound->ReqStop(); + Log.Close(); + WriteRegister(); + WaveStg.Close(); + Log.DoBackup(); + } + DeleteUndo(); + DrawMain.FreeItem(); + DrawText.FreeItem(); + DrawPara.FreeItem(); + DrawTemp.FreeItem(); + + delete pBitmapFFT; + pBitmapFFT = NULL; + + if( pBitmapWater != NULL ){ + delete pBitmapWater; + pBitmapWater = NULL; + } + + if( pBitmapSS != NULL ){ + delete pBitmapSS; + pBitmapSS = NULL; + } + for( i = 0; i < STOCKPAGE; i++ ){ + if( pBitmapST[i] != NULL ){ + delete pBitmapST[i]; + pBitmapST[i] = NULL; + } + } + + delete pBitmapRX; + pBitmapRX = NULL; + + if( (pBitmapHistF != NULL) && (pBitmapHistF != pBitmapHist) ){ + delete pBitmapHistF; + pBitmapHistF = NULL; + } + delete pBitmapHist; + pBitmapHist = NULL; + + delete pBitmapTX; + pBitmapTX = NULL; + delete pBitmapTXM; + pBitmapTXM = NULL; + delete pBitmapTemp; + pBitmapTemp = NULL; + + delete pBitmapD12; + pBitmapD12 = NULL; + + delete pBitmapLvl; + pBitmapLvl = NULL; + + if( pBitmapNearest != NULL ) delete pBitmapNearest; + + if( pPaste != NULL ){ + delete pPaste; + pPaste = NULL; + } + if( pComm != NULL ){ + pComm->SetScan(0); + pComm->Close(); + delete pComm; + pComm = NULL; + } + if( pCalibration != NULL ){ + delete pCalibration; + pCalibration = NULL; + } + ::VirtualUnlock(&sys, sizeof(sys)); + ::VirtualUnlock(this, sizeof(TMmsstv)); + CanClose = TRUE; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::FormDestroy(TObject *Sender) +{ + if( pSound != NULL ){ + pSound->WaitStop(); + delete pSound; + pSound = NULL; + } + if( pRadio != NULL ){ + pRadio->WaitClose(); + delete pRadio; + pRadio = NULL; + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::UpdateToneFreq(void) +{ + int fq = pMod->m_TuneFreq; + char bf[128]; + sprintf(bf, MsgEng ? "Send %uHz tone" : "%uHzトーンの送信", fq); + SBTune->Hint = bf; + SBTune->Caption = fq; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::UpdateSystemFont(void) +{ + TFontStyles fsw = Code2FontStyle(sys.m_WinFontStyle); + if( (sys.m_WinFontName != Font->Name)|| + (sys.m_WinFontCharset != Font->Charset)|| + (fsw != Font->Style) + ){ + Font->Name = sys.m_WinFontName; + Font->Charset = sys.m_WinFontCharset; + Font->Style = fsw; + GBMode->Font->Name = sys.m_WinFontName; + GBMode->Font->Charset = sys.m_WinFontCharset; + GBMode->Font->Style = fsw; + GB1->Font->Name = sys.m_WinFontName; + GB1->Font->Charset = sys.m_WinFontCharset; + GB1->Font->Style = fsw; + GBLog->Font->Name = sys.m_WinFontName; + GBLog->Font->Charset = sys.m_WinFontCharset; + GBLog->Font->Style = fsw; + AlignPCS.NewFont(sys.m_WinFontName, sys.m_WinFontCharset, fsw); + SBTX->Font->Name = sys.m_WinFontName; + SBTX->Font->Charset = sys.m_WinFontCharset; + SBTX->Font->Style = fsw; + } + if( Font->Charset != SHIFTJIS_CHARSET ){ + MsgEng = 1; + KFile->Caption = "&File"; + KView->Caption = "&View"; + KOpt->Caption = "&Option"; +// KExtCmd->Caption = "Program(&P)"; + KHelp->Caption = "&Help"; +// File Nenu for english + KLogOpen->Caption = "Open &Log file..."; + KLogFlush->Caption = "Save data now(&F)"; + KFRecTim->Caption = "Record sound to the file with a time stamp(&A)"; + KFRec->Caption = "Record sound to the file(&W)..."; + KFPlay->Caption = "&Play sound from the file..."; + KFPlayPos->Caption = "Play positsion"; + KFRecRew->Caption = "Rewind"; + KFRecStop->Caption = "Close Record / Play"; + KExit->Caption = "Exit MMSSTV(&X)"; + + KEdit->Caption = "&Edit"; + KEC->Caption = "&Copy from history window"; + KEE->Caption = "&Edit TX image..."; + KER->Caption = "Copy from &RX window"; + KEA->Caption = "&Auto copy"; + KEP->Caption = "&Paste to TX window..."; + KES->Caption = "&Stretch paste to TX window"; + KEX->Caption = "Paste via Clipper..."; + KEW->Caption = "Handling of 320x240"; + KEW1->Caption = "Vertical stretching"; + KEW2->Caption = "Auto stretching"; + KEW3->Caption = "No stretching"; + KEW4->Caption = "Shift picture for the header"; + + KVR->Caption = "Always show RX viewer"; + KVS->Caption = "Always show Sync viewer"; + KVH->Caption = "Always show thumbnails of history"; + KVF->Caption = "Always show thumbnails of files folder"; + KVC->Caption = "Always show control buttons"; + KVSD->Caption = "Design"; + KVSD1->Caption = "Standard"; + KVSD2->Caption = "Separate stock view"; + KVSD3->Caption = "Separate all views"; + KRCD->Caption = "Child of a desktop window"; + KVL->Caption = "Level indicator"; + KVLSG->Caption = "Receipt signals"; + KVLSY->Caption = "Sync signals"; + KVSE1->Caption = "Stock view"; + KVSE2->Caption = "Tuning view"; + KVSE3->Caption = "Log view"; + + KS->Caption = "Spectral display"; + KSFQ->Caption = "FM demodulator"; + KFFTW->Caption = "Spectral display range"; + KFFTS->Caption = "Spectral trail"; + KFSQ->Caption = "Quick"; + KFSS->Caption = "Short"; + KFSL->Caption = "Long"; + KF->Caption = "Spectral sensitivity"; + KR->Caption = "Spectral response"; + KRS->Caption = "Slow"; + KRM->Caption = "Medium"; + KRF->Caption = "Fast"; + KFTD->Caption = "Calculation priority"; + KFTD1->Caption = "Lower"; + KFTD2->Caption = "Normal"; + KFTD3->Caption = "A little higher"; + KFTD4->Caption = "Higher"; + KFTD5->Caption = "Highest"; + KOSC->Caption = "&Oscilloscope..."; + KVOut->Caption = "Soundcard output level(&V)..."; + KVIn->Caption = "Soundcard &Input level..."; + KORep->Caption = "Setup repeater..."; + KOL->Caption = "Setup &Logging..."; + KOM->Caption = "Setup MMSSTV(&O)..."; + + KP->Caption = "P&Rofiles"; + KPDef->Caption = "MMSSTV Default"; + KPInit->Caption = "Initialize all menus as MMSSTV default"; + KPA->Caption = "Assign profile"; + KPD->Caption = "Delete profile"; + + KX->Caption = "&Program"; + KXP->Caption = "MS &Paint"; + KXA->Caption = "Assign program"; + KXD->Caption = "Delete program"; + KXR->Caption = "Restore"; + KXS->Caption = "&Suspend"; + KXSM->Caption = "Suspend+&Minimize"; + + KRadio->Caption = "Radio&Command"; + KRadioS->Caption = "Edit menu"; + KRLoad->Caption = "&Load..."; + KRSet->Caption = "&Setup..."; + KRadioAdd->Caption = "&Add menu..."; + + KHlpUp->Caption = "Version-up information..."; + KHlpPad->Caption = "Use NotePad"; + KHJ->Caption = "JASTA Activity Contest (August)"; + KHN->Caption = "NVCG Contest (July)"; + KVer->Caption = "Version information(&A)..."; + + TabSync->Caption = "Sync"; + TabRX->Caption = "RX"; + TabHist->Caption = "History"; + TabTX->Caption = "TX"; + TabTemp->Caption = "Template"; + SBPhase->Caption = "Phase"; + SBSlant->Caption = "Slant"; + SBSampSet->Caption = "Mem"; + TabS->Tabs->Strings[0] = "S.pix"; + TabS->Tabs->Strings[1] = "S.templates 1"; + + CBSTemp->Caption = "Show with template"; + CBSDraft->Caption = "Draft"; + + KRFS->Caption = "ReSync"; + KRC->Caption = "&Copy"; + KRCC->Caption = "Clear"; + KRCS->Caption = "High accuracy slant adjustment"; + KRCR->Caption = "High accuracy re-sync"; + KRSR->Caption = "Return to the settings sampling frequency"; + KRI->Caption = "Accuracy of initial sync"; + KRI1->Caption = "Normal"; + KRI2->Caption = "Higher"; + KRI3->Caption = "Highest"; + KRAS->Caption = "Auto stop"; + KRAR->Caption = "Auto restart"; + KRASY->Caption = "Auto resync"; + KRSW->Caption = "Auto switch to RX window"; + KRSA->Caption = "Auto slant adjustment"; + KRH->Caption = "Copy to the history"; + KRR->Caption = "Resize to RX size"; + KRRC->Caption = "Resize to 320x256"; + KRB->Caption = "Background color..."; + KRCan->Caption = "Cancel"; + KRD->Caption = "Auto clear"; + + KSP->Caption = "&Paste"; + KSD->Caption = "&Delete"; + KSL->Caption = "&Load from file..."; + KSS->Caption = "&Save to file..."; + KSE->Caption = "&Edit image..."; + KSCD->Caption = "&Move folder..."; + KSFJ->Caption = "Use JPEG format"; + KSFB->Caption = "Use Windows bitmap format"; + KSMS->Caption = "Create a catalog image"; + KSTP->Caption = "Test pattern"; + KSAI->Caption = "Image adjustment..."; + KSAM->Caption = "Auto margin"; + KSIS->Caption = "Stretch TX image by different size"; + KSRR->Caption = "Auto switch to RX window"; + KSCan->Caption = KRCan->Caption; + KSF->Caption = "High quality resizing with pasted thumbnail"; + KSA->Caption = "Add the items to the template"; + + KTPA->Caption = KSAI->Caption; + KTPI->Caption = "Paste image"; + KTPB->Caption = "Bitmap"; + KTPO->Caption = "Overlay"; + KTKA->Caption = "Keep aspect ratio"; + KTOS->Caption = "Resize to the original size"; + KTU->Caption = "&Undo"; + KTC->Caption = "&Cut"; + KTP->Caption = "&Paste"; + KTD->Caption = "&Delete"; + KTO->Caption = "&Object"; + KTOI->Caption = "&Insert..."; + KTCI->Caption = "Insert custom item"; + KTOCB->Caption = "Copy as bitmap"; + KTOB->Caption = "Stretch as bitmap"; + KTOR->Caption = "Properties"; + KTE->Caption = "Add text to the list..."; + KTB->Caption = "Go to &Back"; + KTF->Caption = "Go to &Front"; + KTTD->Caption = "Show transparent point"; + KTT->Caption = "&Transparent point"; + KTAP->Caption = "Auto transparent point"; + KTTC->Caption = "Back&Ground (transparent) color..."; + KTAC->Caption = "Find unique color as background"; + KTLI->Caption = "Items"; + KTSA->Caption = "All"; + KTSI->Caption = "Selected item"; + KTA->Caption = "&All delete"; + KTDF->Caption = "Samples"; + KTMD->Caption = "Draw dummy text of macro"; + KTBT->Caption = "Show TX picture"; + KTSZ->Caption = "Size"; + KTSZT->Caption = "Adapt with TX image"; + KTSD->Caption = "Show size"; + KTX->Caption = "Options"; + KTFS->Caption = "Disable font smoothing"; + KTH->Caption = "Use fast code"; + KTCan->Caption = KRCan->Caption; + + KHCD->Caption = "&Move folder..."; + KHAP->Caption = KTPA->Caption; + KHS->Caption = "&Save to file..."; + KHT->Caption = "Save to file with &Time stamp..."; + KHD->Caption = "&Delete"; + KHDA->Caption = "All delete"; + KHFJ->Caption = KSFJ->Caption; + KHFB->Caption = KSFB->Caption; + KHAC->Caption = "Auto copy to the another folder"; + KHACD->Caption = "Assign another folder name..."; + KHACT->Caption = "Write time stamp in the copied picture"; + KHACJ->Caption = "Copy as JPEG format"; + KHDS->Caption = "Drag && Drop size"; + KHTB->Caption = "Show title bar"; + KHVS->Caption = "Thumbnail size"; + KHCan->Caption = KRCan->Caption; + + KHWeb->Caption = "MMSSTV Web site"; + KHRef->Caption = "MMSSTV Reflector"; + + KCWM->Caption = "Edit menu"; + KCWCancel->Caption = "Cancel"; + KCWS->Caption = "Speed"; + KCWADD->Caption = "Add menu..."; + + SBPL->Hint = "Shift left"; + SBPR->Hint = "Shift right"; + SBPhase->Hint = "Manual sync adjustment"; + SBSlant->Hint = "Manual slant adjustment"; + CBASave->Caption = "Auto history"; + CBASave->Hint = "Auto save to the history"; + SBSampSet->Hint = "Memory sampling freq."; + SBTO->Hint = "Memory TX offset"; + SBLK->Caption = "Lock"; + SBLK->Hint = "Lock RX"; + SBWHist->Hint = "Save to the history"; + SBRView->Hint = "Picture viewer"; + SBCopy->Hint = "Copy"; + SBHView->Hint = "Picture viewer"; + + SBCW->Hint = "Output CW (Right click for CW menu)"; + SBUseTemp->Hint = "Use template"; + SBUS240->Hint = "Shift picture and template for 240 line mode"; + SBDS240->Hint = "Shift picture for the header color bar"; + SBUA240->Hint = "Adjustment picture and template for 240 line mode"; + SBDA240->Hint = "Adjustment picture for the header color bar"; + SBPaste->Hint = "Paste"; + SBTView->Hint = "Picture viewer"; + SBDSel->Hint = "Select item"; + SBDline->Hint = "Draw line"; + SBDBox->Hint = "Draw box"; + SBDBoxS->Hint = "Draw filled box"; + SBDText->Hint = "Draw text"; + SBDPic->Hint = "Draw picture"; + SBDHead->Hint = "Draw Color bar"; + SBDList->Hint = "Draw text from defined list"; + SBDDel->Hint = "Cut"; + SBDPaste->Hint = "Paste"; + SBDCol->Hint = "Set color"; + SBDLineset->Hint = "Set line style"; + SBDFont->Hint = "Set font"; + + SBQSO->Hint = "Start/End QSO"; + SBData->Hint = "Data window"; + SBFind->Hint = "Find callsign"; + SBInit->Hint = "Clear data"; + SBList->Hint = "Log list window"; + SBULog->Hint = "Update template"; + + SBHistFil->Hint = "Image adjustment"; + SBRXID->Hint = "Decode FSKID"; + SBTXID->Hint = "Encode FSKID"; + SBAdj->Hint = "High accuracy slant adjustment (Right click for Sync adjustment)"; + } + else { + MsgEng = 0; + } + KHMT->Caption = KSMS->Caption; + KHC->Caption = KRC->Caption; + KHE->Caption = KSE->Caption; + KSC->Caption = KRC->Caption; + KTOC->Caption = KRC->Caption; + KTOE->Caption = KEdit->Caption; + KTOP->Caption = KTP->Caption; + KTOT->Caption = KTPO->Caption; + KSB->Caption = KRB->Caption; + KSTS->Caption = CBSTemp->Caption; + KSTD->Caption = CBSDraft->Caption; + KSSZ->Caption = KTSZ->Caption; + KSS1->Caption = KTSZ1->Caption; + KSS2->Caption = KTSZ2->Caption; + KSS3->Caption = KTSZ3->Caption; + KSS4->Caption = KTSZ4->Caption; + SBTXFil->Hint = SBHistFil->Hint; + SBRXFil->Hint = SBHistFil->Hint; + KSSD->Caption = KTSD->Caption; + KHSD->Caption = KTSD->Caption; + KRSD->Caption = KTSD->Caption; + KTL->Caption = KSL->Caption; + KTLA->Caption = KTSA->Caption; + KTS->Caption = KSS->Caption; + SBFS->Caption = KRFS->Caption; + KORep->Enabled = sys.m_Repeater; + UpdateToneFreq(); +} +//--------------------------------------------------------------------------- +// ファイルメニューの更新 +void __fastcall TMmsstv::KFileClick(TObject *Sender) +{ + if( pSound != NULL ){ + KFRecTim->Enabled = pSound->m_playmode ? FALSE : TRUE; + KFRec->Enabled = KFRecTim->Enabled; + KFPlay->Enabled = KFRecTim->Enabled; + KFRecRew->Enabled = !KFRecTim->Enabled; + KFRecStop->Enabled = KFRecRew->Enabled; + KFPlayPos->Enabled = (pSound->m_playmode == 1) ? TRUE : FALSE; + if(pSound->WaveFile.m_mode != 2){ + KFRec->Checked = FALSE; + KFRecTim->Checked = FALSE; + } + MultProc(); + } + if( Log.IsOpen() ){ + KLogFlush->Enabled = Log.IsEdit(); + } +} +//--------------------------------------------------------------------------- +//void __fastcall TMmsstv::OnIdle(TObject *Sender, bool &Done) +// アイドル処理 +void __fastcall TMmsstv::UpdateUI(void) +{ + if( sys.m_AutoStop || pDem->m_SyncRestart || sys.m_AutoSync ){ + SBLK->Down = FALSE; + } + else { + SBLK->Down = TRUE; + } + if( Log.IsOpen() ){ + if( Log.m_CurChg ){ + Log.SetLastPos(); + UpdateTextData(); + Log.m_CurChg = 0; + SBQSO->Down = Log.m_sd.btime ? 1 : 0; + } + + SBQSO->Enabled = !HisCall->Text.IsEmpty(); + SBData->Enabled = TRUE; + SBFind->Enabled = SBQSO->Enabled; + SBInit->Enabled = TRUE; + SBList->Enabled = TRUE; + } + else { + SBQSO->Enabled = FALSE; + SBData->Enabled = FALSE; + SBFind->Enabled = FALSE; + SBInit->Enabled = FALSE; + SBList->Enabled = FALSE; + } +} +//--------------------------------------------------------------------------- +// レジストリからの読み出し +void __fastcall TMmsstv::ReadSampFreq(void) +{ + char bf[256]; + AnsiString as, ws; + + sprintf(bf, "%sMmsstv.ini", BgnDir); + TMemIniFile *pIniFile = new TMemIniFile(bf); + + SampFreq = ReadDoubleIniFile(pIniFile, "SoundCard", "SampFreq", SampFreq); + if( (SampFreq > CLOCKMAX) || (SampFreq < 5000.0) ) SampFreq = 11025.0; + sys.m_TxSampOff = ReadDoubleIniFile(pIniFile, "SoundCard", "TxSampOffset", 0.0); + InitSampType(); + sys.m_SampFreq = SampFreq; + SSTVSET.m_SampFreq = SampFreq; + SSTVSET.m_TxSampFreq = SampFreq + sys.m_TxSampOff; + SSTVSET.InitIntervalPara(); + delete pIniFile; + + m_ASLmt[0] = 25.0 * SampFreq / 11025; + m_ASLmt[1] = 10.0 * SampFreq / 11025; + m_ASLmt[2] = 2.0 * SampFreq / 11025; + m_ASLmt[3] = 0.5 * SampFreq / 11025; // 64 + m_ASLmt[4] = 0.2 * SampFreq / 11025; // 128 + m_ASLmt[5] = 0.2 * SampFreq / 11025; // 160 + m_ASLmt[6] = 0.08 * SampFreq / 11025; // 220 +} +//--------------------------------------------------------------------------- +// レジストリからの読み出し +void __fastcall TMmsstv::ReadCombList(TMemIniFile *tp, AnsiString &as, LPCSTR pKey, LPCSTR pDef) +{ + as = tp->ReadString("ComboList", pKey, pDef); + if( as.IsEmpty() ) as = pDef; +} +#define INIVER 2 +#define PROVER 1 +#define LCVER 2 +#define PLLVER 2 +//--------------------------------------------------------------------------- +// レジストリからの読み出し +void __fastcall TMmsstv::ReadRegister(void) +{ + char bf[256]; + int i; + AnsiString as, ws; + + sprintf(bf, "%sMmsstv.ini", BgnDir); + TMemIniFile *pIniFile = new TMemIniFile(bf); + + int IniVer = pIniFile->ReadInteger("Version", "INI", 0); + ReadCombList(pIniFile, as, "LogFreq", ( lcid != LANG_JAPANESE ) ? + "1.8,3.5,3.8,7,10,14,14.230,18,21,21.340,24,28,28.680,50,144,220,430,1200,2400": + "1.8,3.5,3.8,7,7.033,10,14,14.230,18,21,21.340,24,28,28.680,50,144,430,1200,2400" + ); + SetComboBox(LogFreq, as.c_str()); + ReadCombList(pIniFile, as, "LogRST", "595,575,555,594,574,554,444,333"); + SetComboBox(HisRST, as.c_str()); + SetComboBox(MyRST, as.c_str()); + + sys.m_WindowState = pIniFile->ReadInteger("Window", "WindowState", sys.m_WindowState); + sys.m_MemWindow = pIniFile->ReadInteger("Window", "MemoryWindow", sys.m_MemWindow); + sys.m_UseB24 = pIniFile->ReadInteger("Window", "UseB24", sys.m_UseB24); + if( sys.m_MemWindow ){ + Top = pIniFile->ReadInteger("Window", "Top", Top); + Left = pIniFile->ReadInteger("Window", "Left", Left); + Width = pIniFile->ReadInteger("Window", "Width", Width); + Height = pIniFile->ReadInteger("Window", "Height", Height); + } + sys.m_RxViewTop = pIniFile->ReadInteger("Window", "RxViewTop", 0); + sys.m_RxViewLeft = pIniFile->ReadInteger("Window", "RxViewLeft", 0); + sys.m_RxViewWidth = pIniFile->ReadInteger("Window", "RxViewWidth", PBoxRX->Width); + sys.m_RxViewHeight = pIniFile->ReadInteger("Window", "RxViewHeight", PBoxRX->Height); + KVR->Checked = pIniFile->ReadInteger("Window", "RxView", 0); + KRCD->Checked = pIniFile->ReadInteger("Window", "RxViewInd", 0); + + sys.m_SyncViewTop = pIniFile->ReadInteger("Window", "SyncViewTop", 0); + sys.m_SyncViewLeft = pIniFile->ReadInteger("Window", "SyncViewLeft", 0); + sys.m_SyncViewWidth = pIniFile->ReadInteger("Window", "SyncViewWidth", PBoxD12->Width); + sys.m_SyncViewHeight = pIniFile->ReadInteger("Window", "SyncViewHeight", PBoxD12->Height); + KVS->Checked = pIniFile->ReadInteger("Window", "SyncView", 0); + sys.m_HistViewTB = pIniFile->ReadInteger("Window", "HistViewTB", 1); + sys.m_HistViewTop = pIniFile->ReadInteger("Window", "HistViewTop", 0); + sys.m_HistViewLeft = pIniFile->ReadInteger("Window", "HistViewLeft", 0); + sys.m_HistViewWidth = pIniFile->ReadInteger("Window", "HistViewWidth", 516); + sys.m_HistViewHeight = pIniFile->ReadInteger("Window", "HistViewHeight", 70); + sys.m_HistViewSize = pIniFile->ReadInteger("Window", "HistViewSize", 2); + KVH->Checked = pIniFile->ReadInteger("Window", "HistView", 0); + + sys.m_StockViewTop = pIniFile->ReadInteger("Window", "StockViewTop", Top+TabS->Top); + sys.m_StockViewLeft = pIniFile->ReadInteger("Window", "StockViewLeft", Left); + sys.m_StockViewWidth = pIniFile->ReadInteger("Window", "StockViewWidth", 470); + sys.m_StockViewHeight = pIniFile->ReadInteger("Window", "StockViewHeight", 156); + + sys.m_WaterViewTop = pIniFile->ReadInteger("Window", "WaterViewTop", 0); + sys.m_WaterViewLeft = pIniFile->ReadInteger("Window", "WaterViewLeft", GBLog->Left); + sys.m_WaterViewWidth = pIniFile->ReadInteger("Window", "WaterViewWidth", GBLog->Width); + sys.m_WaterViewHeight = pIniFile->ReadInteger("Window", "WaterViewHeight", PanelLvl->Height); + + sys.m_LogViewTop = pIniFile->ReadInteger("Window", "LogViewTop", GBLog->Top); + sys.m_LogViewLeft = pIniFile->ReadInteger("Window", "LogViewLeft", GBLog->Left); + sys.m_LogViewWidth = pIniFile->ReadInteger("Window", "LogViewWidth", GBLog->Width); + sys.m_LogViewHeight = pIniFile->ReadInteger("Window", "LogViewHeight", GBLog->Height); + + sys.m_DivMode = pIniFile->ReadInteger("Window", "DivMode", sys.m_DivMode); + i = pIniFile->ReadInteger("Window", "DivSW", 7); + KVSE1->Checked = i & 1; + KVSE2->Checked = (i >> 1) & 1; + KVSE3->Checked = (i >> 2) & 1; + + sys.m_CtrBtnTop = pIniFile->ReadInteger("Window", "CtrBtnTop", 0); + sys.m_CtrBtnLeft = pIniFile->ReadInteger("Window", "CtrBtnLeft", 0); + sys.m_CtrBtnWidth = pIniFile->ReadInteger("Window", "CtrBtnWidth", 128); + sys.m_CtrBtnHeight = pIniFile->ReadInteger("Window", "CtrBtnHeight", 198); + KVC->Checked = pIniFile->ReadInteger("Window", "CtrBtn", 0); + + sys.m_FileViewShowSize = pIniFile->ReadInteger("FileView", "ShowSize", 0); + sys.m_FileViewKeep = pIniFile->ReadInteger("FileView", "KeepA", 0); + for( i = 0; i < 8; i++ ){ + sprintf(bf, "FileView%d", i+1); + sys.m_FileViewFlag[i] = pIniFile->ReadInteger(bf, "Flag", 0); + sys.m_FileViewSize[i] = pIniFile->ReadInteger(bf, "Size", 2); + sys.m_FileViewMode[i] = pIniFile->ReadInteger(bf, "Mode", 1); + sys.m_FileViewTop[i] = pIniFile->ReadInteger(bf, "Top", 0); + sys.m_FileViewLeft[i] = pIniFile->ReadInteger(bf, "Left", 0); + sys.m_FileViewWidth[i] = pIniFile->ReadInteger(bf, "Width", 516); + sys.m_FileViewHeight[i] = pIniFile->ReadInteger(bf, "Height", 70); + sys.m_FileViewMaxPage[i] = pIniFile->ReadInteger(bf, "MaxPage", 1); + sys.m_FileViewCurPage[i] = pIniFile->ReadInteger(bf, "CurPage", 0); + if( sys.m_FileViewMaxPage[i] > FPAGEMAX ) sys.m_FileViewMaxPage[i] = 10; + if( sys.m_FileViewMaxPage[i] < 1 ) sys.m_FileViewMaxPage[i] = 1; + for( int j = 0; j < sys.m_FileViewMaxPage[i]; j++ ){ + char bff[32]; + sprintf(bff, "FMPage%u", j+1); + sys.m_FileViewFMPage[i][j] = pIniFile->ReadInteger(bf, bff, 0x80000000); + sprintf(bff, j ? "Folder%u" : "Folder", j+1); + sys.m_FileViewFolder[i][j] = pIniFile->ReadString(bf, bff, ""); + sprintf(bff, "Name%u", j+1); + sys.m_FileViewName[i][j] = pIniFile->ReadString(bf, bff, ""); + } + } + sys.m_PreViewTop = pIniFile->ReadInteger("Window", "PreViewTop", 0); + sys.m_PreViewLeft = pIniFile->ReadInteger("Window", "PreViewLeft", 0); + sys.m_PreViewWidth = pIniFile->ReadInteger("Window", "PreViewWidth", 160); + sys.m_PreViewHeight = pIniFile->ReadInteger("Window", "PreViewHeight", 128); + + m_MainPage = pIniFile->ReadInteger("Window", "MainPage", pgRX); + Page->ActivePage = Page->Pages[m_MainPage]; + + TabS->TabIndex = pIniFile->ReadInteger("Window", "StockPage", 0); + m_PSPage = pIniFile->ReadInteger("Window", "StockPicPosition", m_PSPage); + for( i = 0; i < STOCKPAGE; i++ ){ + sprintf(bf, "StockTempPos%u", i + 1); + m_TSPage[i] = pIniFile->ReadInteger("Window", bf, m_TSPage[i]); + } + UDStock->Position = short(TabS->TabIndex ? m_TSPage[TabS->TabIndex-1] : m_PSPage); + KSF->Checked = pIniFile->ReadInteger("Window", "HQResizing", KSF->Checked); + SBUseTemp->Down = pIniFile->ReadInteger("Window", "UseTemplate", SBUseTemp->Down); + CBSTemp->Checked = pIniFile->ReadInteger("Window", "ShowSuperimpos", 0); + CBSDraft->Checked = pIniFile->ReadInteger("Window", "DraftSuperimpos", CBSDraft->Checked); + sys.m_ShowSizeRX = pIniFile->ReadInteger("Window", "ShowSizeRX", sys.m_ShowSizeRX); + sys.m_ShowSizeHist = pIniFile->ReadInteger("Window", "ShowSizeHist", sys.m_ShowSizeHist); + sys.m_ShowSizeTX = pIniFile->ReadInteger("Window", "ShowSizeTX", sys.m_ShowSizeTX); + sys.m_ShowSizeTemp = pIniFile->ReadInteger("Window", "ShowSizeTemp", sys.m_ShowSizeTemp); + sys.m_ShowSizeStock = pIniFile->ReadInteger("Window", "ShowSizeStock", sys.m_ShowSizeStock); + KSIS->Checked = pIniFile->ReadInteger("Window", "StretchTXimage", KSIS->Checked); + KSRR->Checked = pIniFile->ReadInteger("Window", "SwitchRX", KSRR->Checked); + + sys.m_PicClipType = pIniFile->ReadInteger("Window", "PicClipType", sys.m_PicClipType); + sys.m_PicClipRatio = pIniFile->ReadInteger("Window", "PicClipRatio", sys.m_PicClipRatio); + sys.m_PicClipMode = pIniFile->ReadInteger("Window", "PicClipMode", sys.m_PicClipMode); + sys.m_PicClipView = pIniFile->ReadInteger("Window", "PicClipView", sys.m_PicClipView); + sys.m_PicClipColor = (TColor)pIniFile->ReadInteger("Window", "PicClipColor", sys.m_PicClipColor); + sys.m_Way240 = pIniFile->ReadInteger("Window", "Way240", sys.m_Way240); + + sys.m_Priority = pIniFile->ReadInteger("Window", "Priority", sys.m_Priority); + + KSAM->Checked = pIniFile->ReadInteger("Window", "AutoMargin", TRUE); + m_TxClipType = pIniFile->ReadInteger("Window", "TxClipType", m_TxClipType); + sys.m_HistMax = pIniFile->ReadInteger("Window", "HistMax", sys.m_HistMax); + KRD->Checked = pIniFile->ReadInteger("Window", "AutoRxClear", 1); + CBASave->Checked = pIniFile->ReadInteger("Window", "AutoRxSave", CBASave->Checked); + KEA->Checked = pIniFile->ReadInteger("Window", "AutoCopy", KEA->Checked); + KTBT->Checked = pIniFile->ReadInteger("Window", "TempSuperimpos", KTBT->Checked); + KTMD->Checked = pIniFile->ReadInteger("Window", "DummyMacro", KTMD->Checked); + KTTD->Checked = pIniFile->ReadInteger("Window", "ShowTransPoint", KTTD->Checked); + KTAP->Checked = pIniFile->ReadInteger("Window", "AutoTransPoint", KTAP->Checked); + sys.m_HDDSize = pIniFile->ReadInteger("Window", "HistDDSize", sys.m_HDDSize); + + sys.m_WinFontName = pIniFile->ReadString("WindowFont", "Name", sys.m_WinFontName); + sys.m_WinFontCharset = (BYTE)pIniFile->ReadInteger("WindowFont", "Charset", sys.m_WinFontCharset); + sys.m_WinFontStyle = pIniFile->ReadInteger("WindowFont", "Style", sys.m_WinFontStyle); + sys.m_FontAdjSize = pIniFile->ReadInteger("WindowFont", "Adjust", sys.m_FontAdjSize); + sys.m_FFTType = pIniFile->ReadInteger("Define", "FFTType", sys.m_FFTType); + sys.m_FFTGain = pIniFile->ReadInteger("Define", "FFTGain", sys.m_FFTGain); + sys.m_FFTResp = pIniFile->ReadInteger("Define", "FFTResp", sys.m_FFTResp); + sys.m_FFTStg = pIniFile->ReadInteger("Define", "FFTStgv", sys.m_FFTStg); + sys.m_FFTWidth = pIniFile->ReadInteger("Define", "FFTWidth", sys.m_FFTWidth); + sys.m_FFTAGC = pIniFile->ReadInteger("Define", "FFTAGC", sys.m_FFTAGC); + sys.m_FFTPriority = pIniFile->ReadInteger("Define", "FFTPriority", sys.m_FFTPriority); + KVW->Checked = pIniFile->ReadInteger("Define", "WaterSW", KVW->Checked); + pDem->m_LevelType = pIniFile->ReadInteger("Define", "LevelType", pDem->m_LevelType); + + sys.m_HelpNotePad = pIniFile->ReadInteger("Help", "UseNotePad", sys.m_HelpNotePad); + KHlpPad->Checked = sys.m_HelpNotePad; + + sys.m_Sharp2D = pIniFile->ReadInteger("ImageAdj", "Sharp2D", sys.m_Sharp2D); + + sys.m_ColorLow = (TColor)pIniFile->ReadInteger("Color", "WaterLow", sys.m_ColorLow); + sys.m_ColorHigh = (TColor)pIniFile->ReadInteger("Color", "WaterHigh", sys.m_ColorHigh); + sys.m_ColorFFTB = (TColor)pIniFile->ReadInteger("Color", "FFTB", sys.m_ColorFFTB); + sys.m_ColorFFT = (TColor)pIniFile->ReadInteger("Color", "FFT", sys.m_ColorFFT); + sys.m_ColorFFTStg = (TColor)pIniFile->ReadInteger("Color", "FFTStg", sys.m_ColorFFTStg); + sys.m_ColorFFTSync = (TColor)pIniFile->ReadInteger("Color", "FFTSync", sys.m_ColorFFTSync); + sys.m_ColorFFTFreq = (TColor)pIniFile->ReadInteger("Color", "FFTFreq", sys.m_ColorFFTFreq); + + sys.m_ColorRXB = (TColor)pIniFile->ReadInteger("Color", "RxWindow", sys.m_ColorRXB); + PanelRX->Color = sys.m_ColorRXB; + PanelHist->Color = sys.m_ColorRXB; + + sys.m_echo = pIniFile->ReadInteger("Define", "TXLoopBack", sys.m_echo); + + sys.m_UseRxBuff = pIniFile->ReadInteger("Define", "UseRxBuff", sys.m_UseRxBuff); + pDem->m_bpf = pIniFile->ReadInteger("Define", "DEMBPF", pDem->m_bpf); + pDem->m_MSync = pIniFile->ReadInteger("Define", "SyncStart", pDem->m_MSync); + pDem->m_SyncRestart = pIniFile->ReadInteger("Define", "SyncReStart", pDem->m_SyncRestart); + pDem->CalcBPF(); + sys.m_AutoStop = pIniFile->ReadInteger("Define", "AutoStop", sys.m_AutoStop); + sys.m_AutoSync = pIniFile->ReadInteger("Define", "AutoSync", sys.m_AutoSync); + m_SyncAccuracy = pIniFile->ReadInteger("Define", "SyncAccuracy", m_SyncAccuracy); + KRSW->Checked = pIniFile->ReadInteger("Define", "AutoSwirchRX", KRSW->Checked); + KRSA->Checked = pIniFile->ReadInteger("Define", "AutoSlant", KRSA->Checked); + + pDem->m_SenseLvl = pIniFile->ReadInteger("Define", "DEMSLVL", pDem->m_SenseLvl); + pDem->SetSenseLvl(); + sys.m_Differentiator = pIniFile->ReadInteger("Define", "Differentiator", sys.m_Differentiator); + sys.m_DiffLevelP = ReadDoubleIniFile(pIniFile, "Define", "DiffLevel", sys.m_DiffLevelP); + sys.m_DiffLevelM = sys.m_DiffLevelP / 3.0; + + sys.m_FixedTxMode = pIniFile->ReadInteger("Define", "FixedTxMode", sys.m_FixedTxMode); + SSTVSET.m_TxMode = pIniFile->ReadInteger("Define", "SSTVMode", SSTVSET.m_TxMode); + SSTVSET.SetMode(SSTVSET.m_TxMode); + SSTVSET.SetTxMode(SSTVSET.m_TxMode); + for( i = 0; i < 9; i++ ){ + sprintf(bf, "Button%d", i); + m_ModeAssignTX[i] = pIniFile->ReadInteger("Mode", bf, m_ModeAssignTX[i]); + m_ModeAssignRX[i] = m_ModeAssignTX[i]; + } + pDem->m_fskdecode = pIniFile->ReadInteger("Define", "RXFSKID", pDem->m_fskdecode); + SBRXID->Down = pDem->m_fskdecode; + sys.m_TXFSKID = pIniFile->ReadInteger("Define", "TXFSKID", sys.m_TXFSKID); + SBTXID->Down = sys.m_TXFSKID; + sys.m_CWID = pIniFile->ReadInteger("Define", "CWID", sys.m_CWID); + sys.m_CWIDWPM = pIniFile->ReadInteger("Define", "CWIDWPM", 0); + if( sys.m_CWIDWPM <= 0 ){ + sys.m_CWIDSpeed = pIniFile->ReadInteger("Define", "CWIDSpeed", sys.m_CWIDSpeed); + sys.m_CWIDWPM = (1110.0 / (sys.m_CWIDSpeed + 30)) + 0.5; + } + sys.m_CWIDFreq = pIniFile->ReadInteger("Define", "CWIDFreq", sys.m_CWIDFreq); + sys.m_CWIDText = pIniFile->ReadString("Define", "CWIDText", sys.m_CWIDText); + sys.m_MMVID = pIniFile->ReadString("Define", "MMVID", sys.m_MMVID); + pMod->m_TuneFreq = pIniFile->ReadInteger("Define", "TuneFreq", pMod->m_TuneFreq); + sys.m_TuneTXTime = pIniFile->ReadInteger("Define", "TuneTime", sys.m_TuneTXTime); + sys.m_TuneSat = pIniFile->ReadInteger("Define", "TuneSat", sys.m_TuneSat); + sys.m_CWText = pIniFile->ReadString("Define", "CWText", sys.m_CWText); + sys.m_VOX = pIniFile->ReadInteger("Define", "VOX", sys.m_VOX); + as = pIniFile->ReadString("Define", "VOXTone", sys.m_VOXSound); + Yen2CrLf(sys.m_VOXSound, as); + + pMod->m_VariOut = pIniFile->ReadInteger("Vari", "Enabled", 0); + pMod->m_VariOut = 0; + pMod->m_VariR = pIniFile->ReadInteger("Vari", "R", 298); + pMod->m_VariG = pIniFile->ReadInteger("Vari", "G", 588); + pMod->m_VariB = pIniFile->ReadInteger("Vari", "B", 110); + if( pMod->m_VariB == 11 ) pMod->m_VariB = 110; + + pMod->m_outgain = pIniFile->ReadInteger("Define", "TXGAIN", pMod->m_outgain); + pMod->InitGain(); + pMod->m_bpf = pIniFile->ReadInteger("Define", "TXBPF", pMod->m_bpf); + pMod->m_lpf = pIniFile->ReadInteger("Define", "TXLPF", pMod->m_lpf); + pMod->m_bpftap = pIniFile->ReadInteger("Define", "TXBPFTAP", pMod->m_bpftap); + pMod->m_lpffq = pIniFile->ReadInteger("Define", "TXLPFFQ", pMod->m_lpffq); + pMod->CalcFilter(); + + pDem->m_afc = pIniFile->ReadInteger("Define", "RXAFC", pDem->m_afc); + SBAFC->Down = pDem->m_afc; + pSound->m_lms = pIniFile->ReadInteger("Define", "RXLMS", pSound->m_lms); + pSound->m_lms_AN = pIniFile->ReadInteger("Define", "RXLMSAN", pSound->m_lms_AN); + pSound->lms.SetAN(pSound->m_lms_AN); + UpdateLMS(); + + sys.m_SoundFifoRX = pIniFile->ReadInteger("Define", "SoundFifoRX", sys.m_SoundFifoRX); + sys.m_SoundFifoTX = pIniFile->ReadInteger("Define", "SoundFifoTX", sys.m_SoundFifoTX); + if( sys.m_SoundFifoRX > WAVE_FIFO_MAX ) sys.m_SoundFifoRX = WAVE_FIFO_MAX; + if( sys.m_SoundFifoTX > WAVE_FIFO_MAX ) sys.m_SoundFifoTX = WAVE_FIFO_MAX; + sys.m_SoundPriority = pIniFile->ReadInteger("Define", "SoundPriority", sys.m_SoundPriority); + sys.m_SoundDevice = pIniFile->ReadString("Define", "SoundDevice", sys.m_SoundDevice); + sys.m_SoundMMW = pIniFile->ReadString("Define", "SoundMMW", sys.m_SoundMMW); + pSound->m_FifoSizeRX = sys.m_SoundFifoRX; + pSound->m_FifoSizeTX = sys.m_SoundFifoTX; + pSound->SetDeviceID(); + sys.m_SoundStereo = pIniFile->ReadInteger("Define", "SoundStereo", sys.m_SoundStereo); + sys.m_StereoTX = pIniFile->ReadInteger("Define", "StereoTX", sys.m_StereoTX); + pSound->InitWFX(); + + pDem->m_Type = pIniFile->ReadInteger("Define", "DemType", pDem->m_Type); + pDem->m_fqc.m_outOrder = pIniFile->ReadInteger("Define", "fqcOutOrder", pDem->m_fqc.m_outOrder); + pDem->m_fqc.m_outFC = ReadDoubleIniFile(pIniFile, "Define", "fqcOutFC", pDem->m_fqc.m_outFC); + pDem->m_fqc.m_Type = pIniFile->ReadInteger("Define", "fqcType", pDem->m_fqc.m_Type); + pDem->m_fqc.m_SmoozFq = ReadDoubleIniFile(pIniFile, "Define", "fqcSmooth", pDem->m_fqc.m_SmoozFq); + pDem->m_fqc.CalcLPF(); + + int LCVer = pIniFile->ReadInteger("Version", "LinearCalibration", 0); + int PLLVer = pIniFile->ReadInteger("Version", "PLL", 0); + sys.m_DemOff = pIniFile->ReadInteger("Define", "ColorOffset", sys.m_DemOff); + sys.m_DemWhite = ReadDoubleIniFile(pIniFile, "Define", "ColorWhite", sys.m_DemWhite); + sys.m_DemBlack = ReadDoubleIniFile(pIniFile, "Define", "ColorBlack", sys.m_DemBlack); + sys.m_DemCalibration = pIniFile->ReadInteger("Define", "ColorCalibration", sys.m_DemCalibration); + for( i = 0; i < 17; i++ ){ + sprintf(bf, "Value%d", i); + sys.m_Dem17[i] = ReadDoubleIniFile(pIniFile, "Polynomial", bf, sys.m_Dem17[i]); + } + + pDem->m_pll.SetVcoGain(ReadDoubleIniFile(pIniFile, "Define", "pllVcoGain", pDem->m_pll.m_vcogain)); + pDem->m_pll.m_loopOrder = pIniFile->ReadInteger("Define", "pllLoopOrder", pDem->m_pll.m_loopOrder); + pDem->m_pll.m_loopFC = ReadDoubleIniFile(pIniFile, "Define", "pllLoopFC", pDem->m_pll.m_loopFC); + pDem->m_pll.m_outOrder = pIniFile->ReadInteger("Define", "pllOutOrder", pDem->m_pll.m_outOrder); + pDem->m_pll.m_outFC = ReadDoubleIniFile(pIniFile, "Define", "pllOutFC", pDem->m_pll.m_outFC); + pDem->m_pll.MakeLoopLPF(); + pDem->m_pll.MakeOutLPF(); + + sys.m_TxRxName = pIniFile->ReadString("Define", "PTT", sys.m_TxRxName); + sys.m_TxRxLock = pIniFile->ReadInteger("Define", "PTTLock", sys.m_TxRxLock); + sys.m_RTSonRX = pIniFile->ReadInteger("Define", "RTSonRX", sys.m_RTSonRX); + + sys.m_Call = pIniFile->ReadString("Define", "Call", sys.m_Call); + + sys.m_TempDelay = pIniFile->ReadInteger("Log", "TempDelay", sys.m_TempDelay); + sys.m_AutoTimeOffset = pIniFile->ReadInteger("Log", "AutoUTCOffset", sys.m_AutoTimeOffset); + sys.m_TimeOffset = pIniFile->ReadInteger("Log", "UTCOffset", sys.m_TimeOffset); + sys.m_TimeOffsetMin = pIniFile->ReadInteger("Log", "UTCOffsetMin", sys.m_TimeOffsetMin); + sys.m_LogLink = pIniFile->ReadInteger("Log", "LogLink", sys.m_LogLink); + LogLink.LoadMMLink(pIniFile); + LogLink.SetPolling(pIniFile->ReadInteger("Log", "LinkPoll", 0)); + LogLink.SetPTTEnabled(pIniFile->ReadInteger("Log", "LinkPTT", FALSE)); + Log.m_FileName = pIniFile->ReadString("LogFile", "Name", Log.m_FileName); + Log.MakeName(Log.m_FileName.c_str()); + + sys.m_JPEGQuality = pIniFile->ReadInteger("Window", "JPEG", sys.m_JPEGQuality); + + RxHist.m_UseJPEG = pIniFile->ReadInteger("Dir", "HistoryFormat", RxHist.m_UseJPEG); + as = pIniFile->ReadString("Dir", "History", HistDir); + strcpy(HistDir, as.c_str()); + sys.m_UseJPEG = pIniFile->ReadInteger("Dir", "StockFormat", sys.m_UseJPEG); + as = pIniFile->ReadString("Dir", "Stock", StockDir); + strcpy(StockDir, as.c_str()); + as = pIniFile->ReadString("Dir", "RecSound", RecDir); + strcpy(RecDir, as.c_str()); + as = pIniFile->ReadString("Dir", "Bitmap", BitmapDir); + strcpy(BitmapDir, as.c_str()); + as = pIniFile->ReadString("Dir", "SaveBitmap", SBitmapDir); + strcpy(SBitmapDir, as.c_str()); + as = pIniFile->ReadString("Dir", "Template", TemplateDir); + strcpy(TemplateDir, as.c_str()); + sys.m_AutoSaveDir = pIniFile->ReadString("Dir", "AutoSaveDir", sys.m_AutoSaveDir); +// PBoxHist->DragMode = sys.m_AutoSaveDir.IsEmpty() ? dmManual : dmAutomatic; + KHAC->Checked = pIniFile->ReadInteger("Dir", "AutoSave", KHAC->Checked); + KHACT->Checked = pIniFile->ReadInteger("Dir", "AutoSaveTime", KHACT->Checked); + KHACJ->Checked = pIniFile->ReadInteger("Dir", "AutoSaveFormat", KHACJ->Checked); + + as = pIniFile->ReadString("Dir", "ExtLog", ExtLogDir); + strcpy(ExtLogDir, as.c_str()); + for( i = 0; i < TEXTCONVMAX; i++ ){ + sprintf(bf, "WDEF%d", i+1); + LogText.m_tConv[i].Key = pIniFile->ReadString("ExtConv", bf, LogText.m_tConv[i].Key); + sprintf(bf, "WLEN%d", i+1); + LogText.m_tConv[i].w = pIniFile->ReadInteger("ExtConv", bf, LogText.m_tConv[i].w); + } + for( i = 0; i < TEXTCONVMAX; i++ ){ + sprintf(bf, "RDEF%d", i+1); + LogText.m_rConv[i].Key = pIniFile->ReadString("ExtConv", bf, LogText.m_rConv[i].Key); + sprintf(bf, "RLEN%d", i+1); + LogText.m_rConv[i].w = pIniFile->ReadInteger("ExtConv", bf, LogText.m_rConv[i].w); + } + for( i = 0; i < 8; i++ ){ + sprintf(bf, "Program%d", i+1); + sys.m_ExtMode[i] = pIniFile->ReadInteger(bf, "Flag", sys.m_ExtMode[i]); + sys.m_ExtName[i] = pIniFile->ReadString(bf, "Name", sys.m_ExtName[i]); + sys.m_ExtCmd[i] = pIniFile->ReadString(bf, "File", sys.m_ExtCmd[i]); + } + + for( i = 0; i < RECMENUMAX; i++ ){ + sprintf(bf, "File%d", i + 1); + as = pIniFile->ReadString("Recent File", bf, ""); + RecentMenu.SetItemText(i, as.c_str()); + } + Log.ReadIniFile("LogSet", pIniFile); + + LoadRADIOSetup(pIniFile); + + for( i = 0; i < 6; i++ ){ + sprintf(bf, "Color%d", i+1); + sys.m_ColText[i] = (TColor)pIniFile->ReadInteger("DrawText", bf, sys.m_ColText[i]); + } + for( i = 0; i < 4; i++ ){ + sprintf(bf, "Color%d", i+1); + sys.m_ColBar[i] = (TColor)pIniFile->ReadInteger("DrawBar", bf, sys.m_ColBar[i]); + } + for( i = 0; i < 32; i++ ){ + sprintf(bf, "Color%d", i+1); + sys.m_ColorSet[i] = (TColor)pIniFile->ReadInteger("ColorSet", bf, sys.m_ColorSet[i]); + } + + for( i = 0; i < 16; i++ ){ + sprintf(bf, "Text%d", i+1); + sys.m_TextList[i] = pIniFile->ReadString("TextList", bf, sys.m_TextList[i]); + } + + sys.m_TextGrade = pIniFile->ReadInteger("Text", "Grade", sys.m_TextGrade); + sys.m_TextShadow = pIniFile->ReadInteger("Text", "Shadow", sys.m_TextShadow); + sys.m_TextZero = pIniFile->ReadInteger("Text", "Zero", sys.m_TextZero); + sys.m_TextRot = pIniFile->ReadInteger("Text", "Rot", sys.m_TextRot); + sys.m_TextVert = pIniFile->ReadInteger("Text", "Vert", sys.m_TextVert); + sys.m_TextVertH = pIniFile->ReadInteger("Text", "VertH", sys.m_TextVertH); + sys.m_TextStack = pIniFile->ReadInteger("Text", "3D", sys.m_TextStack); + as = pIniFile->ReadString("Text", "MSG", sys.m_Msg); + Yen2CrLf(sys.m_Msg, as); + sys.m_DisFontSmooth = pIniFile->ReadInteger("Text", "DisFontSmooth", sys.m_DisFontSmooth); + i = pIniFile->ReadInteger("Text", "Temp24", sys.m_Temp24); + if( (i >> 16) != sys.m_BitPixel ){ + sys.m_Temp24 = (sys.m_BitPixel >= 24); + } + else { + sys.m_Temp24 = i & 1; + } + + sys.m_PicShape = pIniFile->ReadInteger("Pic", "Shape", sys.m_PicShape); + sys.m_PicAdjust = pIniFile->ReadInteger("Pic", "Adjust", sys.m_PicAdjust); + sys.m_PicLineStyle = pIniFile->ReadInteger("Pic", "LineStyle", sys.m_PicLineStyle); + sys.m_PicLineColor = (TColor)pIniFile->ReadInteger("Pic", "LineColor", sys.m_PicLineColor); + + sys.m_PicSelRTM = pIniFile->ReadInteger("PicSel", "RTM", sys.m_PicSelRTM); + sys.m_PicSelSmooz = pIniFile->ReadInteger("PicSel", "Smooz", sys.m_PicSelSmooz); + sys.m_PicSelCurCol = (TColor)pIniFile->ReadInteger("PicSel", "Color", sys.m_PicSelCurCol); + + int ProVER = pIniFile->ReadInteger("ProFile", "Version", 0); + PRODEM *pPD = m_DemPro; + for( i = 0; i < 8; i++, pPD++ ){ + sprintf(bf, "ProFile%d", i+1); + as = pIniFile->ReadString(bf, "Name", pPD->Name); + if( as.IsEmpty() ) continue; + + pPD->Name = as.c_str(); + pPD->VCOGain = ReadDoubleIniFile(pIniFile, bf, "VcoGain", pPD->VCOGain); + pPD->loopOrder = pIniFile->ReadInteger(bf, "loopOrder", pPD->loopOrder); + pPD->loopFC = ReadDoubleIniFile(pIniFile, bf, "loopFC", pPD->loopFC); + pPD->OutOrder = pIniFile->ReadInteger(bf, "OutOrder", pPD->OutOrder); + pPD->OutFC = ReadDoubleIniFile(pIniFile, bf, "OutFC", pPD->OutFC); + + pPD->Type = pIniFile->ReadInteger(bf, "DemType", pPD->Type); + pPD->crossOutOrder = pIniFile->ReadInteger(bf, "fqcOutOrder", pPD->crossOutOrder); + pPD->crossOutFC = ReadDoubleIniFile(pIniFile, bf, "fqcOutFC", pPD->crossOutFC); + + pPD->crossType = pIniFile->ReadInteger(bf, "fqcType", pPD->crossType); + pPD->crossSmooz = ReadDoubleIniFile(pIniFile, bf, "fqcSmooth", pPD->crossSmooz); + + pPD->DemOff = ReadDoubleIniFile(pIniFile, bf, "DemOff", pPD->DemOff); + pPD->DemWhite = ReadDoubleIniFile(pIniFile, bf, "DemWhite", pPD->DemWhite); + pPD->DemBlack = ReadDoubleIniFile(pIniFile, bf, "DemBlack", pPD->DemBlack); + pPD->DemCalibration = pIniFile->ReadInteger(bf, "DemCalibration", pPD->DemCalibration); + char bff[64]; + double *dp = pPD->Dem17; + for( int j = 0; j < 17; j++, dp++ ){ + sprintf(bff, "DemPolynomial%d", j); + *dp = ReadDoubleIniFile(pIniFile, bf, bff, *dp); + } + pPD->Differentiator = pIniFile->ReadInteger(bf, "Differentiator", pPD->Differentiator); + pPD->DiffLevel = ReadDoubleIniFile(pIniFile, bf, "DiffLevel", pPD->DiffLevel); + } + if( (ProVER < PROVER) || (LCVer < LCVER) || (PLLVer < PLLVER) ){ + InitProfile(); + SetProFile(8); + } + for( i = 0; i < FSKIDMAX; i++ ){ + sprintf(bf, "Item%d", i+1); + as = pIniFile->ReadString("Calls", bf, ""); + if( as.IsEmpty() ) break; + LPSTR p; + for( p = as.c_str(); *p; p++ ){ + if( *p == '_' ) *p = '\t'; + } + TMenuItem *pm = new TMenuItem(this); + pm->Caption = as.c_str(); + pm->RadioItem = FALSE; + pm->OnClick = KCClick; + pm->Checked = FALSE; + pm->Enabled = TRUE; + PopupC->Items->Add(pm); + } + for( i = 0; i < 4; i++ ){ + sprintf(bf, "Font.%d", i+1); + sys.m_RegFont[i].m_Name = pIniFile->ReadString(bf, "Name", sys.m_RegFont[i].m_Name); + sys.m_RegFont[i].m_Charset = (BYTE)pIniFile->ReadInteger(bf, "Charset", sys.m_RegFont[i].m_Charset); + sys.m_RegFont[i].m_Height = pIniFile->ReadInteger(bf, "Height", sys.m_RegFont[i].m_Height); + sys.m_RegFont[i].m_Style = pIniFile->ReadInteger(bf, "Style", sys.m_RegFont[i].m_Style); + } +//CWMenu + sys.m_nCWMenu = pIniFile->ReadInteger("CWMenu", "Menus", sys.m_nCWMenu); + for( i = 0; i < sys.m_nCWMenu; i++ ){ + sprintf(bf, "M%d", i+1); + sys.m_CWMenu[i] = pIniFile->ReadString("CWMenu", bf, sys.m_CWMenu[i]); + } +//RadioMenu + m_nRadioMenu = pIniFile->ReadInteger("RadioMenu", "Menus", m_nRadioMenu); + for( i = 0; i < m_nRadioMenu; i++ ){ + sprintf(bf, "Cap%d", i+1); + m_RadioMenu[i].strTTL = pIniFile->ReadString("RadioMenu", bf, m_RadioMenu[i].strTTL); + sprintf(bf, "Cmd%d", i+1); + m_RadioMenu[i].strCMD = pIniFile->ReadString("RadioMenu", bf, m_RadioMenu[i].strCMD); + } + +// リピータ + if( sys.m_Repeater ){ + pDem->m_Repeater = pIniFile->ReadInteger("Repeater", "Enabled", 0); + + pDem->m_RepTone = pIniFile->ReadInteger("Repeater", "Tone", 1750); + pDem->InitRepeater(); + pDem->m_RepSQ = pIniFile->ReadInteger("Repeater", "SQLVL", 6000); + + sys.m_RepSenseLvl = pIniFile->ReadInteger("Repeater", "Sense", 2); + pDem->SetRepSenseLvl(); + sys.m_RepTimeA = pIniFile->ReadInteger("Repeater", "TimeA", 1500); + sys.m_RepTimeB = pIniFile->ReadInteger("Repeater", "TimeB", 500); + sys.m_RepTimeC = pIniFile->ReadInteger("Repeater", "TimeC", 10000); + sys.m_RepTimeD = pIniFile->ReadInteger("Repeater", "TimeD", 2000); + sys.m_RepAnsCW = pIniFile->ReadString("Repeater", "AnsCW", "%m K"); + + sys.m_RepBeacon = pIniFile->ReadInteger("Repeater", "Beacon", 0); + sys.m_RepBeaconMode = pIniFile->ReadInteger("Repeater", "BeaconMode", smSCT1); + sys.m_RepBeaconFilter = pIniFile->ReadInteger("Repeater", "BeaconFilter", 1); + sys.m_RepTempTX = pIniFile->ReadString("Repeater", "TempReplay", "0"); + sys.m_RepTempBeacon = pIniFile->ReadString("Repeater", "TempBeacon", "0"); + sys.m_RepBottomAdj = pIniFile->ReadInteger("Repeater", "BottomAdj", 1); + sys.m_RepQuietnessTime = pIniFile->ReadInteger("Repeater", "QuietnessTime", 300); + sys.m_RepFolder = pIniFile->ReadString("Repeater", "Folder", ""); + } + else { + pDem->m_Repeater = 0; + } + delete pIniFile; + if( IniVer < INIVER ){ + sys.m_PicClipView = 1; + sys.m_PicClipColor = clBlack; + } +} +//--------------------------------------------------------------------------- +// レジストリへの書き込み +void __fastcall TMmsstv::WriteRegister(void) +{ + CWaitCursor wait; + int i; + char bf[256]; + sprintf(bf, "%sMmsstv.ini", BgnDir); + + try{ + TMemIniFile *pIniFile = new TMemIniFile(bf); + + WriteDoubleIniFile(pIniFile, "SoundCard", "SampFreq", sys.m_SampFreq); + WriteDoubleIniFile(pIniFile, "SoundCard", "TxSampOffset", sys.m_TxSampOff); + + AnsiString as; + GetComboBox(as, LogFreq); + if( !as.IsEmpty() ) pIniFile->WriteString("ComboList", "LogFreq", as); + GetComboBox(as, HisRST); + if( !as.IsEmpty() ) pIniFile->WriteString("ComboList", "LogRST", as); + + pIniFile->WriteInteger("Version", "INI", INIVER); + pIniFile->WriteInteger("Version", "LinearCalibration", LCVER); + pIniFile->WriteInteger("Version", "PLL", PLLVER); + + pIniFile->WriteInteger("Window", "Priority", sys.m_Priority); + pIniFile->WriteInteger("Window", "WindowState", WindowState); + pIniFile->WriteInteger("Window", "MemoryWindow", sys.m_MemWindow); + pIniFile->WriteInteger("Window", "UseB24", sys.m_UseB24); + if( (WindowState == wsNormal) && sys.m_MemWindow ){ + pIniFile->WriteInteger("Window", "Top", Top); + pIniFile->WriteInteger("Window", "Left", Left); + if( sys.m_DivMode != 2 ){ + pIniFile->WriteInteger("Window", "Width", Width); + } + if( !sys.m_DivMode ){ + pIniFile->WriteInteger("Window", "Height", Height); + } + } + pIniFile->WriteInteger("Window", "RxViewInd", KRCD->Checked); + pIniFile->WriteInteger("Window", "RxView", KVR->Checked); + pIniFile->WriteInteger("Window", "RxViewTop", sys.m_RxViewTop); + pIniFile->WriteInteger("Window", "RxViewLeft", sys.m_RxViewLeft); + pIniFile->WriteInteger("Window", "RxViewWidth", sys.m_RxViewWidth); + pIniFile->WriteInteger("Window", "RxViewHeight", sys.m_RxViewHeight); + pIniFile->WriteInteger("Window", "SyncView", KVS->Checked); + pIniFile->WriteInteger("Window", "SyncViewTop", sys.m_SyncViewTop); + pIniFile->WriteInteger("Window", "SyncViewLeft", sys.m_SyncViewLeft); + pIniFile->WriteInteger("Window", "SyncViewWidth", sys.m_SyncViewWidth); + pIniFile->WriteInteger("Window", "SyncViewHeight", sys.m_SyncViewHeight); + pIniFile->WriteInteger("Window", "HistView", KVH->Checked); + pIniFile->WriteInteger("Window", "HistViewTB", sys.m_HistViewTB); + pIniFile->WriteInteger("Window", "HistViewTop", sys.m_HistViewTop); + pIniFile->WriteInteger("Window", "HistViewLeft", sys.m_HistViewLeft); + pIniFile->WriteInteger("Window", "HistViewWidth", sys.m_HistViewWidth); + pIniFile->WriteInteger("Window", "HistViewHeight", sys.m_HistViewHeight); + pIniFile->WriteInteger("Window", "HistViewSize", sys.m_HistViewSize); + + pIniFile->WriteInteger("Window", "CtrBtn", KVC->Checked); + pIniFile->WriteInteger("Window", "CtrBtnTop", sys.m_CtrBtnTop); + pIniFile->WriteInteger("Window", "CtrBtnLeft", sys.m_CtrBtnLeft); + pIniFile->WriteInteger("Window", "CtrBtnWidth", sys.m_CtrBtnWidth); + pIniFile->WriteInteger("Window", "CtrBtnHeight", sys.m_CtrBtnHeight); + + pIniFile->WriteInteger("Window", "StockViewTop", sys.m_StockViewTop); + pIniFile->WriteInteger("Window", "StockViewLeft", sys.m_StockViewLeft); + pIniFile->WriteInteger("Window", "StockViewWidth", sys.m_StockViewWidth); + pIniFile->WriteInteger("Window", "StockViewHeight", sys.m_StockViewHeight); + + pIniFile->WriteInteger("Window", "WaterViewTop", sys.m_WaterViewTop); + pIniFile->WriteInteger("Window", "WaterViewLeft", sys.m_WaterViewLeft); + pIniFile->WriteInteger("Window", "WaterViewWidth", sys.m_WaterViewWidth); + pIniFile->WriteInteger("Window", "WaterViewHeight", sys.m_WaterViewHeight); + + pIniFile->WriteInteger("Window", "LogViewTop", sys.m_LogViewTop); + pIniFile->WriteInteger("Window", "LogViewLeft", sys.m_LogViewLeft); + pIniFile->WriteInteger("Window", "LogViewWidth", sys.m_LogViewWidth); + pIniFile->WriteInteger("Window", "LogViewHeight", sys.m_LogViewHeight); + + pIniFile->WriteInteger("Window", "DivMode", sys.m_DivMode); + pIniFile->WriteInteger("Window", "DivSW", KVSE1->Checked | (KVSE2->Checked << 1) | (KVSE3->Checked << 2) ); + + pIniFile->WriteInteger("FileView", "ShowSize", sys.m_FileViewShowSize); + pIniFile->WriteInteger("FileView", "KeepA", sys.m_FileViewKeep); + for( i = 0; i < 8; i++ ){ + sprintf(bf, "FileView%d", i+1); + pIniFile->WriteInteger(bf, "Flag", sys.m_FileViewFlag[i]); + pIniFile->WriteInteger(bf, "Mode", sys.m_FileViewMode[i]); + pIniFile->WriteInteger(bf, "Size", sys.m_FileViewSize[i]); + pIniFile->WriteInteger(bf, "Top", sys.m_FileViewTop[i]); + pIniFile->WriteInteger(bf, "Left", sys.m_FileViewLeft[i]); + pIniFile->WriteInteger(bf, "Width", sys.m_FileViewWidth[i]); + pIniFile->WriteInteger(bf, "Height", sys.m_FileViewHeight[i]); + pIniFile->WriteInteger(bf, "MaxPage", sys.m_FileViewMaxPage[i]); + pIniFile->WriteInteger(bf, "CurPage", sys.m_FileViewCurPage[i]); + for( int j = 0; j < sys.m_FileViewMaxPage[i]; j++ ){ + char bff[32]; + sprintf(bff, "FMPage%u", j+1); + pIniFile->WriteInteger(bf, bff, sys.m_FileViewFMPage[i][j]); + sprintf(bff, j ? "Folder%u" : "Folder", j+1); + pIniFile->WriteString(bf, bff, sys.m_FileViewFolder[i][j]); + sprintf(bff, "Name%u", j+1); + pIniFile->WriteString(bf, bff, sys.m_FileViewName[i][j]); + } + } + + pIniFile->WriteInteger("Window", "PreViewTop", sys.m_PreViewTop); + pIniFile->WriteInteger("Window", "PreViewLeft", sys.m_PreViewLeft); + pIniFile->WriteInteger("Window", "PreViewWidth", sys.m_PreViewWidth); + pIniFile->WriteInteger("Window", "PreViewHeight", sys.m_PreViewHeight); + + pIniFile->WriteInteger("Window", "StayOnTop", sys.m_StayOnTop); + pIniFile->WriteInteger("Window", "MainPage", m_MainPage); + pIniFile->WriteInteger("Window", "StockPage", TabS->TabIndex); + pIniFile->WriteInteger("Window", "StockPicPosition", m_PSPage); + for( i = 0; i < STOCKPAGE; i++ ){ + sprintf(bf, "StockTempPos%u", i + 1); + pIniFile->WriteInteger("Window", bf, m_TSPage[i]); + } + pIniFile->WriteInteger("Window", "HQResizing", KSF->Checked); + pIniFile->WriteInteger("Window", "UseTemplate", SBUseTemp->Down); + pIniFile->WriteInteger("Window", "ShowSuperimpos", CBSTemp->Checked); + pIniFile->WriteInteger("Window", "DraftSuperimpos", CBSDraft->Checked); + pIniFile->WriteInteger("Window", "PicClipType", sys.m_PicClipType); + pIniFile->WriteInteger("Window", "PicClipRatio", sys.m_PicClipRatio); + pIniFile->WriteInteger("Window", "PicClipMode", sys.m_PicClipMode); + pIniFile->WriteInteger("Window", "PicClipView", sys.m_PicClipView); + pIniFile->WriteInteger("Window", "PicClipColor", sys.m_PicClipColor); + pIniFile->WriteInteger("Window", "Way240", sys.m_Way240); + pIniFile->WriteInteger("Window", "AutoMargin", KSAM->Checked); + pIniFile->WriteInteger("Window", "TxClipType", m_TxClipType); + pIniFile->WriteInteger("Window", "HistMax", sys.m_HistMax); + pIniFile->WriteInteger("Window", "AutoRxClear", KRD->Checked); + pIniFile->WriteInteger("Window", "AutoRxSave", CBASave->Checked); + pIniFile->WriteInteger("Window", "AutoCopy", KEA->Checked); + pIniFile->WriteInteger("Window", "JPEG", sys.m_JPEGQuality); + pIniFile->WriteInteger("Window", "TempSuperimpos", KTBT->Checked); + pIniFile->WriteInteger("Window", "DummyMacro", KTMD->Checked); + pIniFile->WriteInteger("Window", "ShowTransPoint", KTTD->Checked); + pIniFile->WriteInteger("Window", "AutoTransPoint", KTAP->Checked); + pIniFile->WriteInteger("Window", "HistDDSize", sys.m_HDDSize); + pIniFile->WriteInteger("Window", "ShowSizeRX", sys.m_ShowSizeRX); + pIniFile->WriteInteger("Window", "ShowSizeHist", sys.m_ShowSizeHist); + pIniFile->WriteInteger("Window", "ShowSizeTX", sys.m_ShowSizeTX); + pIniFile->WriteInteger("Window", "ShowSizeTemp", sys.m_ShowSizeTemp); + pIniFile->WriteInteger("Window", "ShowSizeStock", sys.m_ShowSizeStock); + pIniFile->WriteInteger("Window", "StretchTXimage", KSIS->Checked); + pIniFile->WriteInteger("Window", "SwitchRX", KSRR->Checked); + + pIniFile->WriteString("WindowFont", "Name", sys.m_WinFontName); + pIniFile->WriteInteger("WindowFont", "Charset", sys.m_WinFontCharset); + pIniFile->WriteInteger("WindowFont", "Style", sys.m_WinFontStyle); + pIniFile->WriteInteger("WindowFont", "Adjust", sys.m_FontAdjSize); + + pIniFile->WriteInteger("Help", "UseNotePad", sys.m_HelpNotePad); + pIniFile->WriteInteger("ImageAdj", "Sharp2D", sys.m_Sharp2D); + + pIniFile->WriteInteger("Define", "FFTType", sys.m_FFTType); + pIniFile->WriteInteger("Define", "FFTGain", sys.m_FFTGain); + pIniFile->WriteInteger("Define", "FFTResp", sys.m_FFTResp); + pIniFile->WriteInteger("Define", "FFTStgv", sys.m_FFTStg); + pIniFile->WriteInteger("Define", "FFTWidth", sys.m_FFTWidth); + pIniFile->WriteInteger("Define", "FFTAGC", sys.m_FFTAGC); + pIniFile->WriteInteger("Define", "FFTPriority", sys.m_FFTPriority); + pIniFile->WriteInteger("Define", "WaterSW", KVW->Checked); + pIniFile->WriteInteger("Define", "LevelType", pDem->m_LevelType); + + pIniFile->WriteInteger("Color", "WaterLow", sys.m_ColorLow); + pIniFile->WriteInteger("Color", "WaterHigh", sys.m_ColorHigh); + pIniFile->WriteInteger("Color", "FFTB", sys.m_ColorFFTB); + pIniFile->WriteInteger("Color", "FFT", sys.m_ColorFFT); + pIniFile->WriteInteger("Color", "FFTStg", sys.m_ColorFFTStg); + pIniFile->WriteInteger("Color", "FFTSync", sys.m_ColorFFTSync); + pIniFile->WriteInteger("Color", "FFTFreq", sys.m_ColorFFTFreq); + pIniFile->WriteInteger("Color", "RxWindow", sys.m_ColorRXB); + + pIniFile->WriteInteger("Define", "UseRxBuff", sys.m_UseRxBuff); + + pIniFile->WriteInteger("Define", "SoundFifoRX", sys.m_SoundFifoRX); + pIniFile->WriteInteger("Define", "SoundFifoTX", sys.m_SoundFifoTX); + pIniFile->WriteInteger("Define", "SoundPriority", sys.m_SoundPriority); + pIniFile->WriteString("Define", "SoundDevice", sys.m_SoundDevice); + pIniFile->WriteInteger("Define", "SoundStereo", sys.m_SoundStereo); + pIniFile->WriteInteger("Define", "StereoTX", sys.m_StereoTX); + pIniFile->WriteString("Define", "SoundMMW", sys.m_SoundMMW); + + pIniFile->WriteString("Define", "PTT", sys.m_TxRxName); + pIniFile->WriteInteger("Define", "PTTLock", sys.m_TxRxLock); + pIniFile->WriteInteger("Define", "RTSonRX", sys.m_RTSonRX); + + pIniFile->WriteInteger("Define", "TXLoopBack", sys.m_echo); + + pIniFile->WriteInteger("Define", "ColorOffset", sys.m_DemOff); + WriteDoubleIniFile(pIniFile, "Define", "ColorWhite", sys.m_DemWhite); + WriteDoubleIniFile(pIniFile, "Define", "ColorBlack", sys.m_DemBlack); + pIniFile->WriteInteger("Define", "ColorCalibration", sys.m_DemCalibration); + for( i = 0; i < 17; i++ ){ + sprintf(bf, "Value%d", i); + WriteDoubleIniFile(pIniFile, "Polynomial", bf, sys.m_Dem17[i]); + } + + pIniFile->WriteInteger("Define", "FixedTxMode", sys.m_FixedTxMode); + pIniFile->WriteInteger("Define", "SSTVMode", SSTVSET.m_TxMode); + for( i = 0; i < 9; i++ ){ + sprintf(bf, "Button%d", i); + pIniFile->WriteInteger("Mode", bf, m_ModeAssignTX[i]); + } + pIniFile->WriteInteger("Define", "RXFSKID", pDem->m_fskdecode); + pIniFile->WriteInteger("Define", "TXFSKID", sys.m_TXFSKID); + pIniFile->WriteInteger("Define", "CWID", sys.m_CWID); + pIniFile->WriteInteger("Define", "CWIDWPM", sys.m_CWIDWPM); + pIniFile->WriteInteger("Define", "CWIDFreq", sys.m_CWIDFreq); + pIniFile->WriteString("Define", "CWIDText", sys.m_CWIDText); + pIniFile->WriteString("Define", "MMVID", sys.m_MMVID); + pIniFile->WriteInteger("Define", "TuneFreq", pMod->m_TuneFreq); + pIniFile->WriteInteger("Define", "TuneTime", sys.m_TuneTXTime); + pIniFile->WriteInteger("Define", "TuneSat", sys.m_TuneSat); + pIniFile->WriteString("Define", "CWText", sys.m_CWText); + + pIniFile->WriteInteger("Define", "VOX", sys.m_VOX); + CrLf2Yen(as, sys.m_VOXSound); + pIniFile->WriteString("Define", "VOXTone", as); + + pIniFile->WriteInteger("Vari", "Enabled", pMod->m_VariOut); + pIniFile->WriteInteger("Vari", "R", pMod->m_VariR); + pIniFile->WriteInteger("Vari", "G", pMod->m_VariG); + pIniFile->WriteInteger("Vari", "B", pMod->m_VariB); + + pIniFile->WriteInteger("Define", "TXGAIN", pMod->m_outgain); + pIniFile->WriteInteger("Define", "TXBPF", pMod->m_bpf); + pIniFile->WriteInteger("Define", "TXLPF", pMod->m_lpf); + pIniFile->WriteInteger("Define", "TXBPFTAP", pMod->m_bpftap); + pIniFile->WriteInteger("Define", "TXLPFFQ", pMod->m_lpffq); + pIniFile->WriteInteger("Define", "DEMSLVL", pDem->m_SenseLvl); + pIniFile->WriteInteger("Define", "Differentiator", sys.m_Differentiator); + WriteDoubleIniFile(pIniFile, "Define", "DiffLevel", sys.m_DiffLevelP); + + pIniFile->WriteInteger("Define", "RXAFC", pDem->m_afc); + pIniFile->WriteInteger("Define", "RXLMS", pSound->m_lms); + pIniFile->WriteInteger("Define", "RXLMSAN", pSound->m_lms_AN); + pIniFile->WriteInteger("Define", "DEMBPF", pDem->m_bpf); + pIniFile->WriteInteger("Define", "SyncStart", pDem->m_MSync); + pIniFile->WriteInteger("Define", "SyncReStart", pDem->m_SyncRestart); + pIniFile->WriteInteger("Define", "AutoStop", sys.m_AutoStop); + pIniFile->WriteInteger("Define", "AutoSync", sys.m_AutoSync); + pIniFile->WriteInteger("Define", "SyncAccuracy", m_SyncAccuracy); + pIniFile->WriteInteger("Define", "AutoSwirchRX", KRSW->Checked); + pIniFile->WriteInteger("Define", "AutoSlant", KRSA->Checked); + + pIniFile->WriteInteger("Define", "DemType", pDem->m_Type); + pIniFile->WriteInteger("Define", "fqcOutOrder", pDem->m_fqc.m_outOrder); + WriteDoubleIniFile(pIniFile, "Define", "fqcOutFC", pDem->m_fqc.m_outFC); + pIniFile->WriteInteger("Define", "fqcType", pDem->m_fqc.m_Type); + WriteDoubleIniFile(pIniFile, "Define", "fqcSmooth", pDem->m_fqc.m_SmoozFq); + + WriteDoubleIniFile(pIniFile, "Define", "pllVcoGain", pDem->m_pll.m_vcogain); + pIniFile->WriteInteger("Define", "pllLoopOrder", pDem->m_pll.m_loopOrder); + WriteDoubleIniFile(pIniFile, "Define", "pllLoopFC", pDem->m_pll.m_loopFC); + pIniFile->WriteInteger("Define", "pllOutOrder", pDem->m_pll.m_outOrder); + WriteDoubleIniFile(pIniFile, "Define", "pllOutFC", pDem->m_pll.m_outFC); + + pIniFile->WriteString("Define", "Call", sys.m_Call); + + pIniFile->WriteInteger("Log", "TempDelay", sys.m_TempDelay); + pIniFile->WriteInteger("Log", "AutoUTCOffset", sys.m_AutoTimeOffset); + pIniFile->WriteInteger("Log", "UTCOffset", sys.m_TimeOffset); + pIniFile->WriteInteger("Log", "UTCOffsetMin", sys.m_TimeOffsetMin); + pIniFile->WriteInteger("Log", "LogLink", sys.m_LogLink); + pIniFile->WriteInteger("Log", "LinkPoll", LogLink.IsPolling()); + pIniFile->WriteInteger("Log", "LinkPTT", LogLink.GetPTTEnabled()); + LogLink.SaveMMLink(pIniFile); + + pIniFile->WriteString("LogFile", "Name", Log.m_FileName); + + for( i = 0; i < 8; i++ ){ + sprintf(bf, "Program%d", i+1); + pIniFile->WriteInteger(bf, "Flag", sys.m_ExtMode[i]); + pIniFile->WriteString(bf, "Name", sys.m_ExtName[i]); + pIniFile->WriteString(bf, "File", sys.m_ExtCmd[i]); + } + + pIniFile->WriteInteger("Dir", "HistoryFormat", RxHist.m_UseJPEG); + pIniFile->WriteString("Dir", "History", HistDir); + pIniFile->WriteInteger("Dir", "StockFormat", sys.m_UseJPEG); + pIniFile->WriteString("Dir", "Stock", StockDir); + pIniFile->WriteString("Dir", "RecSound", RecDir); + pIniFile->WriteString("Dir", "Bitmap", BitmapDir); + pIniFile->WriteString("Dir", "SaveBitmap", SBitmapDir); + pIniFile->WriteString("Dir", "Template", TemplateDir); + pIniFile->WriteString("Dir", "AutoSaveDir", sys.m_AutoSaveDir); + pIniFile->WriteInteger("Dir", "AutoSave", KHAC->Checked); + pIniFile->WriteInteger("Dir", "AutoSaveTime", KHACT->Checked); + pIniFile->WriteInteger("Dir", "AutoSaveFormat", KHACJ->Checked); + + pIniFile->WriteString("Dir", "ExtLog", ExtLogDir); + for( i = 0; i < TEXTCONVMAX; i++ ){ + sprintf(bf, "WDEF%d", i+1); + pIniFile->WriteString("ExtConv", bf, LogText.m_tConv[i].Key); + sprintf(bf, "WLEN%d", i+1); + pIniFile->WriteInteger("ExtConv", bf, LogText.m_tConv[i].w); + } + for( i = 0; i < TEXTCONVMAX; i++ ){ + sprintf(bf, "RDEF%d", i+1); + pIniFile->WriteString("ExtConv", bf, LogText.m_rConv[i].Key); + sprintf(bf, "RLEN%d", i+1); + pIniFile->WriteInteger("ExtConv", bf, LogText.m_rConv[i].w); + } + + for( i = 0; i < RecentMenu.GetCount(); i++ ){ + sprintf(bf, "File%d", i + 1); + pIniFile->WriteString("Recent File", bf, RecentMenu.GetItemText(i)); + } + Log.WriteIniFile("LogSet", pIniFile); + + SaveRADIOSetup(pIniFile); + + for( i = 0; i < 6; i++ ){ + sprintf(bf, "Color%d", i+1); + pIniFile->WriteInteger("DrawText", bf, sys.m_ColText[i]); + } + for( i = 0; i < 4; i++ ){ + sprintf(bf, "Color%d", i+1); + pIniFile->WriteInteger("DrawBar", bf, sys.m_ColBar[i]); + } + for( i = 0; i < 32; i++ ){ + sprintf(bf, "Color%d", i+1); + pIniFile->WriteInteger("ColorSet", bf, sys.m_ColorSet[i]); + } + + for( i = 0; i < 16; i++ ){ + sprintf(bf, "Text%d", i+1); + pIniFile->WriteString("TextList", bf, sys.m_TextList[i]); + } + + pIniFile->WriteInteger("Text", "Grade", sys.m_TextGrade); + pIniFile->WriteInteger("Text", "Shadow", sys.m_TextShadow); + pIniFile->WriteInteger("Text", "Zero", sys.m_TextZero); + pIniFile->WriteInteger("Text", "Rot", sys.m_TextRot); + pIniFile->WriteInteger("Text", "Vert", sys.m_TextVert); + pIniFile->WriteInteger("Text", "VertH", sys.m_TextVertH); + pIniFile->WriteInteger("Text", "3D", sys.m_TextStack); + CrLf2Yen(as, sys.m_Msg); + pIniFile->WriteString("Text", "MSG", as); + pIniFile->WriteInteger("Text", "DisFontSmooth", sys.m_DisFontSmooth); + pIniFile->WriteInteger("Text", "Temp24", sys.m_Temp24 | (sys.m_BitPixel << 16)); + + pIniFile->WriteInteger("Pic", "Shape", sys.m_PicShape); + pIniFile->WriteInteger("Pic", "Adjust", sys.m_PicAdjust); + pIniFile->WriteInteger("Pic", "LineStyle", sys.m_PicLineStyle); + pIniFile->WriteInteger("Pic", "LineColor", sys.m_PicLineColor); + + pIniFile->WriteInteger("PicSel", "RTM", sys.m_PicSelRTM); + pIniFile->WriteInteger("PicSel", "Smooz", sys.m_PicSelSmooz); + pIniFile->WriteInteger("PicSel", "Color", sys.m_PicSelCurCol); + + pIniFile->WriteInteger("ProFile", "Version", PROVER); + PRODEM *pPD = m_DemPro; + for( i = 0; i < 8; i++, pPD++ ){ + sprintf(bf, "ProFile%d", i+1); + pIniFile->WriteString(bf, "Name", pPD->Name); + WriteDoubleIniFile(pIniFile, bf, "VcoGain", pPD->VCOGain); + pIniFile->WriteInteger(bf, "loopOrder", pPD->loopOrder); + WriteDoubleIniFile(pIniFile, bf, "loopFC", pPD->loopFC); + pIniFile->WriteInteger(bf, "OutOrder", pPD->OutOrder); + WriteDoubleIniFile(pIniFile, bf, "OutFC", pPD->OutFC); + pIniFile->WriteInteger(bf, "DemType", pPD->Type); + pIniFile->WriteInteger(bf, "fqcOutOrder", pPD->crossOutOrder); + WriteDoubleIniFile(pIniFile, bf, "fqcOutFC", pPD->crossOutFC); + pIniFile->WriteInteger(bf, "fqcType", pPD->crossType); + WriteDoubleIniFile(pIniFile, bf, "fqcSmooth", pPD->crossSmooz); + + WriteDoubleIniFile(pIniFile, bf, "DemOff", pPD->DemOff); + WriteDoubleIniFile(pIniFile, bf, "DemWhite", pPD->DemWhite); + WriteDoubleIniFile(pIniFile, bf, "DemBlack", pPD->DemBlack); + + pIniFile->WriteInteger(bf, "DemCalibration", pPD->DemCalibration); + char bff[64]; + double *dp = pPD->Dem17; + for( int j = 0; j < 17; j++ ){ + sprintf(bff, "DemPolynomial%d", j); + WriteDoubleIniFile(pIniFile, bf, bff, *dp++); + } + + pIniFile->WriteInteger(bf, "Differentiator", pPD->Differentiator); + WriteDoubleIniFile(pIniFile, bf, "DiffLevel", pPD->DiffLevel); + } + for( i = 0; i < PopupC->Items->Count; i++ ){ + sprintf(bf, "Item%d", i+1); + char bbf[64]; + StrCopy(bbf, AnsiString(PopupC->Items->Items[i]->Caption).c_str(), 63); //ja7ude 0428 + LPSTR p; + for( p = bbf; *p; p++ ){ + if( *p == '\t' ) *p = '_'; + } + pIniFile->WriteString("Calls", bf, bbf); + } +// Fonts + for( i = 0; i < 4; i++ ){ + sprintf(bf, "Font.%d", i+1); + if( sys.m_RegFont[i].m_Height ){ + pIniFile->WriteString(bf, "Name", sys.m_RegFont[i].m_Name); + pIniFile->WriteInteger(bf, "Charset", sys.m_RegFont[i].m_Charset); + pIniFile->WriteInteger(bf, "Height", sys.m_RegFont[i].m_Height); + pIniFile->WriteInteger(bf, "Style", sys.m_RegFont[i].m_Style); + } + } +//CWMenu + try{ + pIniFile->EraseSection("CWMenu"); + } + catch(...){ + } + pIniFile->WriteInteger("CWMenu", "Menus", sys.m_nCWMenu); + for( i = 0; i < sys.m_nCWMenu; i++ ){ + sprintf(bf, "M%d", i+1); + pIniFile->WriteString("CWMenu", bf, sys.m_CWMenu[i]); + } + +//RadioMenu + try{ + pIniFile->EraseSection("RadioMenu"); + } + catch(...){ + } + pIniFile->WriteInteger("RadioMenu", "Menus", m_nRadioMenu); + for( i = 0; i < m_nRadioMenu; i++ ){ + sprintf(bf, "Cap%d", i+1); + pIniFile->WriteString("RadioMenu", bf, m_RadioMenu[i].strTTL); + sprintf(bf, "Cmd%d", i+1); + pIniFile->WriteString("RadioMenu", bf, m_RadioMenu[i].strCMD); + } + +// リピータ + if( sys.m_Repeater ){ + pIniFile->WriteInteger("Repeater", "Enabled", pDem->m_Repeater); + pIniFile->WriteInteger("Repeater", "Tone", pDem->m_RepTone); + pIniFile->WriteInteger("Repeater", "SQLVL", pDem->m_RepSQ); + pIniFile->WriteInteger("Repeater", "Sense", sys.m_RepSenseLvl); + pIniFile->WriteInteger("Repeater", "TimeA", sys.m_RepTimeA); + pIniFile->WriteInteger("Repeater", "TimeB", sys.m_RepTimeB); + pIniFile->WriteInteger("Repeater", "TimeC", sys.m_RepTimeC); + pIniFile->WriteInteger("Repeater", "TimeD", sys.m_RepTimeD); + pIniFile->WriteString("Repeater", "AnsCW", sys.m_RepAnsCW); + pIniFile->WriteInteger("Repeater", "Beacon", sys.m_RepBeacon); + pIniFile->WriteInteger("Repeater", "BeaconMode", sys.m_RepBeaconMode); + pIniFile->WriteInteger("Repeater", "BeaconFilter", sys.m_RepBeaconFilter); + pIniFile->WriteString("Repeater", "TempReplay", sys.m_RepTempTX); + pIniFile->WriteString("Repeater", "TempBeacon", sys.m_RepTempBeacon); + pIniFile->WriteInteger("Repeater", "BottomAdj", sys.m_RepBottomAdj); + pIniFile->WriteInteger("Repeater", "QuietnessTime", sys.m_RepQuietnessTime); + pIniFile->WriteString("Repeater", "Folder", sys.m_RepFolder); + } + pIniFile->UpdateFile(); + delete pIniFile; + + } + catch(...){ + ErrorMB(MsgEng?"Cannot update MMSSTV.INI":"MMSSTV.INIを更新できません."); + } + sprintf(bf, "%s"TEMPV106C, StockDir); + SaveTemplate(&DrawMain, bf); + sprintf(bf, "%s"TEMPV106L, StockDir); + SaveTemplate(&DrawText, bf); + sprintf(bf, "%sCurrent.bmp", StockDir); + SaveBitmap(pBitmapTXM, bf); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::UpdateTitle(void) +{ + char bbf[64]; + char bf[512]; + bf[0] = 0; + if( IsCall(sys.m_Call.c_str()) ){ + sprintf(bf, "%s (%s) - ", sys.m_Call.c_str(), Log.GetName() ); + } + strcat(bf, "MMSSTV "); + if( sys.m_Repeater && (pSound != NULL) && pDem->m_Repeater ){ + strcat(bf, "Repeater "); + } + strcat(bf, VERID VERBETA); + if( SampType ){ + sprintf(bbf, " [based on %.lfHz]", SampBase); + strcat(bf, bbf); + } + if( sys.m_BitPixel < 24 ){ + sprintf(bbf, " [%u colors]", int(pow(2, sys.m_BitPixel))); + strcat(bf, bbf); + } + if( sys.m_bCQ100 ){ + strcat(bf, " for Internet"); + } + Caption = bf; + UpdateCallsign(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::UpdateLMS(void) +{ + SBLMS->Down = pSound->m_lms; + int an = pSound->m_lms_AN; + if( an ){ + SBLMS->Caption = (an == 1) ? "ANF" : "ANS"; + } + else { + SBLMS->Caption = "LMS"; + } + SBLMS->Font->Color = an ? clRed : clBlack; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::AdjustFocus(void) +{ + Page->SetFocus(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::FormPaint(TObject *Sender) +{ + if( m_InitFirst ){ + m_InitFirst = 0; + int f1stInst = FALSE; + if( (sys.m_Call == "NOCALL") || sys.m_Call.IsEmpty() ){ + f1stInst = TRUE; + AnsiString as = ""; + if( sys.m_Call != "NOCALL" ){ + as = sys.m_Call; + } + if( InputMB("MMSSTV", MsgEng ? "Please enter your callsign":"あなたのコールサインを入力して下さい.", as) == TRUE ){ + if( !as.IsEmpty() ){ + char bf[MLCALL+1]; + StrCopy(bf, as.c_str(), MLCALL); + jstrupr(bf); + sys.m_Call = bf; + Log.MakePathName(ClipCall(bf)); + } + } + } + char bf[256]; + sprintf(bf, "%sARRL.DX", BgnDir); + Cty.Load(bf); + sprintf(bf, "%sMMCG.DEF", BgnDir); + mmcg.LoadDef(bf); + + if( !f1stInst ) Log.DoBackup(); + Log.Open(NULL, !f1stInst); + LogLink.UpdateLink(sys.m_LogLink); + UpdateTextData(); + if( Log.m_sd.btime ) SBQSO->Down = TRUE; + UpdateTitle(); + OpenCloseCom(); + if( sys.m_UseRxBuff == 2 ){ + WaveStg.Open(); + } + if( pSound != NULL ){ + pDem->OpenCloseRxBuff(); + pSound->Resume(); + } + sprintf(bf, "%sCurrent.bmp", StockDir); + if( IsFile(bf) ){ + LoadBitmap(pBitmapTXM, bf); + pBitmapTX->Width = pBitmapTXM->Width; + pBitmapTX->Height = pBitmapTXM->Height; + } + else { + FillBitmap(pBitmapTXM, sys.m_PicClipColor); + } + ChangeTxMode(SSTVSET.m_TxMode); + if( m_TxSPage == -1 ) TabSChange(NULL); + m_ChangeTemp = 1; + SBULog->Enabled = TRUE; + UpdatePic(); + UpdateUI(); + if( KVS->Checked ) KVSClick(NULL); + for( int i = 0; i < 8; i++ ){ + if( sys.m_FileViewFlag[i] ){ + ShowFileView(i, 1); + } + } + if( KVH->Checked ) KVHClick(NULL); + if( KVR->Checked ) KVRClick(NULL); + if( KVC->Checked ) KVCClick(NULL); + if( KSF->Checked ) m_ReqHistF = 10; + DisPaint = 0; + AdjustFocus(); + } + else if( pSound != NULL ){ + if( (pSound->m_susp == 1) && m_SuspMinimized ) KXRClick(NULL); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::EntryAlign(void) +{ + RECT rc; + rc.left = 0; + rc.top = 0; + rc.right = 792-1; + rc.bottom = 548-1; + + AlignFix.EntryControl(GBMode, &rc, GBMode->Font); + AlignFix.EntryControl(GB1, &rc, GB1->Font); + AlignFix.EntryControl(PanelLvl, &rc, NULL); + AlignFix.EntryControl(PanelFFT, &rc, NULL); + AlignFix.EntryControl(PanelWater, &rc, NULL); + AlignFix.EntryControl(GBLog, &rc, GBLog->Font); + + AlignMode.EntryControl(SBAuto, GBMode, NULL); + AlignMode.EntryControl(SBM1, GBMode, NULL); + AlignMode.EntryControl(SBM2, GBMode, NULL); + AlignMode.EntryControl(SBM3, GBMode, NULL); + AlignMode.EntryControl(SBM4, GBMode, NULL); + AlignMode.EntryControl(SBM5, GBMode, NULL); + AlignMode.EntryControl(SBM6, GBMode, NULL); + AlignMode.EntryControl(SBM7, GBMode, NULL); + AlignMode.EntryControl(SBM8, GBMode, NULL); + AlignMode.EntryControl(SBM9, GBMode, NULL); + + AlignDsp.EntryControl(SBAFC, GB1, NULL); + AlignDsp.EntryControl(SBLMS, GB1, NULL); + + AlignLog.EntryControl(L1, GBLog, NULL); + AlignLog.EntryControl(L2, GBLog, NULL); + AlignLog.EntryControl(L3, GBLog, NULL); + AlignLog.EntryControl(L4, GBLog, NULL); + AlignLog.EntryControl(L5, GBLog, NULL); + AlignLog.EntryControl(L6, GBLog, NULL); + AlignLog.EntryControl(L7, GBLog, NULL); + AlignLog.EntryControl(HisCall, GBLog, NULL); + AlignLog.EntryControl(HisRST, GBLog, NULL); + AlignLog.EntryControl(MyRST, GBLog, NULL); + AlignLog.EntryControl(HisName, GBLog, NULL); + AlignLog.EntryControl(HisQTH, GBLog, NULL); + AlignLog.EntryControl(EditNote, GBLog, NULL); + AlignLog.EntryControl(EditQSL, GBLog, NULL); + AlignLog.EntryControl(SBULog, GBLog, NULL); + AlignLog.EntryControl(SBRXID, GBLog, NULL); + AlignLog.EntryControl(SBTXID, GBLog, NULL); + AlignLog.EntryControl(SBQSO, GBLog, NULL); + AlignLog.EntryControl(SBData, GBLog, NULL); + AlignLog.EntryControl(SBFind, GBLog, NULL); + AlignLog.EntryControl(SBInit, GBLog, NULL); + AlignLog.EntryControl(SBList, GBLog, NULL); + AlignLog.EntryControl(LogFreq, GBLog, NULL); + + AlignPCS.EntryControl(CBSTemp, PCS, CBSTemp->Font); + AlignPCS.EntryControl(CBSDraft, PCS, CBSDraft->Font); + AlignPCS.EntryControl(LS, PCS, LS->Font); + AlignPCS.EntryControl(UDStock, PCS, NULL); + + int CX = ::GetSystemMetrics(SM_CXFULLSCREEN); + int CY = ::GetSystemMetrics(SM_CYFULLSCREEN); +// int CX = ::GetSystemMetrics(SM_CXSCREEN); +// int CY = ::GetSystemMetrics(SM_CYSCREEN); + if( (CX < Width)||(CY < Height) ){ + Top = 0; + Left = 0; + Width = CX; + Height = CY; + } + if( CY < 500 ){ + TabS->TabHeight = 20; + } + FormCenter(this, CX, CY); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::AdjustStockView(void) +{ + if( pStockView == NULL ){ + TabS->Height = ClientHeight - Page->Height; + PCS->Left = GBMode->Left; + PCS->Top = TabS->Top; + PCS->Height = TabS->TabHeight; + PCS->Width = ClientWidth - PCS->Left; + AlignPCS.NewAlign(PCS); + } + else { + if( !pStockView->Visible ) return; + PCS->Left = pStockView->ClientWidth - PCS->Width; +// AlignPCS.NewAlign(PCS); + } + MultProc(); + double h = PBoxS->ClientHeight; + double w = PBoxS->ClientWidth; + double k = w / h; + int smax = m_SMax; + if( k < 3.2 ){ + m_SMax = 18; + } + else if( k < 6.0 ){ + m_SMax = 12; + } + else { + m_SMax = 6; + } + MultProc(); + if( pBitmapSS != NULL ){ + delete pBitmapSS; + pBitmapSS = NULL; + } + for( int i = 0; i < STOCKPAGE; i++ ){ + if( pBitmapST[i] != NULL ){ + delete pBitmapST[i]; + pBitmapST[i] = NULL; + } + } + if( smax != m_SMax ){ + m_DragPMax = STOCKMAX / m_SMax; + if( STOCKMAX % m_SMax ) m_DragPMax++; + if( UDStock->Position >= m_DragPMax ){ + UDStock->Position = 0; + } + UDStock->Max = SHORT(m_DragPMax - 1); + if( !m_InitFirst ){ + m_TxSPage = -1; + TabSChange(NULL); + } + } + char bf[64]; + sprintf(bf, "%u/%u", UDStock->Position + 1, m_DragPMax); + LS->Caption = bf; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::FormResize(TObject *Sender) +{ + if( Timer->Enabled == FALSE ) return; + + if( WindowState != wsMinimized ){ + int n = (WindowState == wsNormal) ? 0 : 1; + if( pStockView != NULL ){ + if( !m_ClientHeight[n] ){ + m_ClientHeight[n] = ClientHeight; + } + if( ClientHeight != Page->Height ){ + ClientHeight = Page->Height; + } + } + else if( m_ClientHeight[n] ){ + ClientHeight = m_ClientHeight[n]; + m_ClientHeight[n] = 0; + } + + if( pWaterView != NULL ){ + if( !m_ClientWidth[n] ){ + m_ClientWidth[n] = ClientWidth; + } + if( ClientWidth != GBMode->Left + GBMode->Width ){ + ClientWidth = GBMode->Left + GBMode->Width; + } + } + else if( m_ClientWidth[n] ){ + ClientWidth = m_ClientWidth[n]; + m_ClientWidth[n] = 0; + } + } + + CWaitCursor wait; + if( pWaterView == NULL ){ + AlignFix.NewFixAlign(this, GBMode->Left); MultProc(); + } + else { + PanelLvl->Left = 0; + int w = 30; + PanelLvl->Width = w; + PanelFFT->Left = w; + PanelWater->Left = w; + w = pWaterView->ClientWidth - PanelLvl->Width; + PanelFFT->Width = w; + PanelWater->Width = w; + + w = pWaterView->ClientHeight - PBoxG->Height; + PanelLvl->Height = w; + PanelFFT->Height = w * 24 / 35; + PanelWater->Top = PanelFFT->Top + PanelFFT->Height; + PanelWater->Height = pWaterView->ClientHeight - PanelFFT->Height - PanelFFT->Top; + HisCall->ParentFont = TRUE; + } + AlignMode.NewAlign(GBMode); MultProc(); + AlignDsp.NewAlign(GB1); MultProc(); + AlignLog.NewAlign(GBLog); MultProc(); +// UDStock->Left = PCS->Width - UDStock->Width; +// LS->Left = UDStock->Left - LS->Width - 5; + PanelFFT->Height = KVW->Checked ? PanelLvl->Height - PanelWater->Height : PanelLvl->Height; + if( pBitmapLvl != NULL ){ + delete pBitmapLvl; + pBitmapLvl = new Graphics::TBitmap(); + pBitmapLvl->Width = PBoxLvl->Width; + pBitmapLvl->Height = PBoxLvl->Height; + MultProc(); + delete pBitmapFFT; + pBitmapFFT = new Graphics::TBitmap(); + pBitmapFFT->Width = PBoxFFT->Width > DFFTSIZE ? DFFTSIZE : PBoxFFT->Width; + pBitmapFFT->Height = PBoxFFT->Height; + delete pBitmapWater; + MultProc(); + pBitmapWater = NULL; + if( KVW->Checked ){ + pBitmapWater = CreateBitmap(PBoxWater->Width > DFFTSIZE ? DFFTSIZE : PBoxWater->Width, PBoxWater->Height, pf24bit); + PanelWater->Visible = TRUE; + } + else { + PanelWater->Visible = FALSE; + } + if( pSound != NULL ){ + MultProc(); + InitDrawFFT(); + DrawFFT(1); + if( KVW->Checked ) DrawWater(1); + } + } + PBoxG->Width = PBoxFFT->Width; + PBoxG->Left = PanelFFT->Left + (PanelFFT->Width - PBoxFFT->Width)/2; + PBoxG->Top = 0; + PBoxG->Height = PanelFFT->Top - 1; + + if( pStockView != NULL ) pStockView->Visible = KVSE1->Checked; + if( pWaterView != NULL ) pWaterView->Visible = KVSE2->Checked; + if( pLogView != NULL ) pLogView->Visible = KVSE3->Checked; + + AdjustStockView(); + m_MW = Height - ClientHeight; +} +//--------------------------------------------------------------------------- +// 現在の論理パレットを返す(TControl::GetPaletteのオーバライド関数) +HPALETTE __fastcall TMmsstv::GetPalette(void) +{ + sys.m_Palette = 1; + switch(m_MainPage){ + case pgRX: + return pBitmapRX->Palette; + case pgHist: + return pBitmapHist->Palette; + case pgTX: + return pBitmapTX->Palette; + case pgTemp: + return pBitmapTemp->Palette; + default: + return NULL; + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::CloseFileView(int i) +{ + TFileViewDlg *fp = pFileView[i]; + sys.m_FileViewMaxPage[i] = fp->m_MaxPage; + sys.m_FileViewCurPage[i] = fp->m_CurPage; + for( int j = 0; j < fp->m_MaxPage; j++ ){ + CFILEV *cp = fp->pFileV[j]; + sys.m_FileViewFolder[i][j] = cp->m_Folder.c_str(); + sys.m_FileViewName[i][j] = cp->m_Name.c_str(); + sys.m_FileViewFMPage[i][j] = cp->m_CurPage | (cp->m_UseIndex ? 0x80000000 : 0) | (cp->m_Type << 16); + } + sys.m_FileViewFlag[i] = 0; + sys.m_FileViewSize[i] = fp->m_SSize | (fp->KBP->Checked ? 0x00010000 : 0); + sys.m_FileViewMode[i] = fp->SBMode->Down; + fp->GetViewPos(sys.m_FileViewLeft[i], sys.m_FileViewTop[i], sys.m_FileViewWidth[i], sys.m_FileViewHeight[i]); + delete fp; + pFileView[i] = NULL; + MultProc(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::AdjustFileView(void) +{ + int i; + int f = FALSE; + for( i = 0; i < 8; i++ ){ + if( (pFileView[i] != NULL) && (!pFileView[i]->Visible) && (!pFileView[i]->m_Suspend) ){ + CloseFileView(i); + } + if( pFileView[i] == NULL ) f = TRUE; + } + KVF->Enabled = f; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::LoadAllFileView(void) +{ + for( int i = 0; i < 8; i++ ){ + if( pFileView[i] != NULL ){ + pFileView[i]->Reset(); + pFileView[i]->LoadImage(); + MultProc(); + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::ReOpenFileView(TFileViewDlg *pView) +{ + for( int i = 0; i < 8; i++ ){ + if( pFileView[i] == pView ){ + CWaitCursor w; + CloseFileView(i); + ShowFileView(i, 0); + break; + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::InitDrawFFT(void) +{ + GetFFTRect(m_FM, m_low); + + m_XW = pBitmapFFT->Width; + if( m_XW > DFFTSIZE ) m_XW = DFFTSIZE; + m_FX[0] = int(((1900-m_low)*FFT_SIZE*double(m_XW)/double(FFTSamp*m_FM)) + 0.5); + m_FX[1] = int(((1500-m_low)*FFT_SIZE*double(m_XW)/double(FFTSamp*m_FM)) + 0.5); + m_FX[2] = int(((2300-m_low)*FFT_SIZE*double(m_XW)/double(FFTSamp*m_FM)) + 0.5); + m_FX[3] = int(((1201-m_low)*FFT_SIZE*double(m_XW)/double(FFTSamp*m_FM)) + 0.5); + m_FX[6] = int(((2044-m_low)*FFT_SIZE*double(m_XW)/double(FFTSamp*m_FM)) + 0.5); + if( pSound != NULL ){ + int fq; + if( sys.m_Repeater ){ + fq = pDem->m_RepTone; + m_FX[4] = int(((fq-m_low)*FFT_SIZE*double(m_XW)/double(FFTSamp*m_FM)) + 0.5); + } + fq = pSound->notch.m_freq; + m_FX[5] = int(((fq-m_low)*FFT_SIZE*double(m_XW)/double(FFTSamp*m_FM)) + 0.5); + } + m_of = m_low * FFT_SIZE / FFTSamp; + InitFFT(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::InitFFT(void) +{ + memset(m_FFTMAX, 0, sizeof(m_FFTMAX)); + memset(m_fft, 0, sizeof(m_fft)); + + m_FFTMax = 512; + m_FFTSumMax = m_FFTMax*4; + + m_WaterMax = 128; + m_WaterSumMax = m_WaterMax*8; + m_WaterMin = 0; + + m_FFTFlag = 0; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::CalcFFT(void) +{ + CFFT *fp = &pSound->fftIN; + if( fp->IsData() ){ + switch(sys.m_FFTGain){ + case 0: + fp->CalcFFT(m_FFTWINDOW, 30.0, sys.m_FFTResp); + break; + case 1: + fp->CalcFFT(m_FFTWINDOW, 34.0, sys.m_FFTResp); + break; + case 2: + fp->CalcFFT(m_FFTWINDOW, 42.0, sys.m_FFTResp); + break; + case 3: + fp->CalcFFT(m_FFTWINDOW, 54.0, sys.m_FFTResp); + break; + default: + if( sys.m_FFTType == 2 ){ + fp->CalcFFT(m_FFTWINDOW, 10.0, sys.m_FFTResp); + } + else { + fp->CalcFFT(m_FFTWINDOW, (SBTX->Down && (sys.m_echo != 2)) ? 0.5 : 10.0, sys.m_FFTResp); + } + break; + } + int *ip = m_fft; + int i, d; + if( (sys.m_FFTType == 1) && (g_dblToneOffset < -10.0) ){ + int of = (m_low + g_dblToneOffset) * FFT_SIZE / FFTSamp; + int n; + for( i = 0; i < m_XW; i++, ip++ ){ + n = (i * m_FM)/m_XW + of; + if( n >= 0 ){ + d = fp->m_fft[n]; + } + else { + d = 0; + } + if( !sys.m_FFTPriority || (d > *ip) ){ + *ip = d; + } + } + } + else { + if( sys.m_FFTPriority ){ + for( i = 0; i < m_XW; i++, ip++ ){ + d = fp->m_fft[(i * m_FM)/m_XW + m_of]; + if( d > *ip ) *ip = d; + } + } + else { + for( i = 0; i < m_XW; i++, ip++ ){ + *ip = fp->m_fft[(i * m_FM)/m_XW + m_of]; + } + } + } + m_FFTFlag++; + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::DrawFFT(int sw) +{ + TCanvas *tp = pBitmapFFT->Canvas; + TRect rc; + int XR = pBitmapFFT->Width - 1; + int YB = pBitmapFFT->Height - 1; + rc.Left = 0; + rc.Top = 0; + rc.Right = XR; + rc.Bottom = pBitmapFFT->Height; + tp->Brush->Color = sys.m_ColorFFTB; + tp->FillRect(rc); + + int i, x; + char bf[64]; + if( pSound->m_Err || pDem->m_OverFlow ){ + if( pSound->m_Err || !SBTX->Down ){ + tp->Font->Color = clWhite; + tp->Font->Height = -16; + strcpy(bf, pSound->m_Err ? "Lost sound" : "Overflow"); + x = tp->TextWidth(bf); + tp->TextOut(XR - x - 3, 0, bf); + } + pDem->m_OverFlow = 0; + if( pSound->m_Err ) pSound->m_Err--; + } + else if( pSound->WaveFile.m_mode ){ + tp->Font->Color = clWhite; + tp->Font->Height = -16; + LPCSTR p = ""; + if( pSound->WaveFile.m_pause ){ + p = "Pause"; + } + else { + switch(pSound->WaveFile.m_mode){ + case 1: + p = "Play"; + break; + case 2: + p = "Rec."; + break; + } + } + if( *p ){ + x = tp->TextWidth(p); + tp->TextOut(XR - x - 3, 0, p); + } + } + if( pDem->m_Tick ){ + tp->Pen->Color = clLime; + x = int(((pDem->m_TickFreq-m_low)*FFT_SIZE*double(m_XW)/double(FFTSamp*m_FM)) + 0.5); + tp->MoveTo(x, 0); + tp->LineTo(x, YB); + } + else { + int fNarrow = FALSE; + if( SBTX->Down ){ + fNarrow = SSTVSET.m_fTxNarrow; + } + else if( pDem->m_Sync ){ + fNarrow = pDem->m_fNarrow; + } + if( fNarrow ){ + tp->Pen->Color = sys.m_ColorFFTSync; + tp->Pen->Style = psSolid; + tp->MoveTo(m_FX[0], 0); // 1900 + tp->LineTo(m_FX[0], YB); + tp->Pen->Color = sys.m_ColorFFTFreq; + tp->Pen->Style = psDot; + tp->MoveTo(m_FX[3], 0); // 1200 + tp->LineTo(m_FX[3], YB); + tp->MoveTo(m_FX[1], 0); // 1500 + tp->LineTo(m_FX[1], YB); + tp->MoveTo(m_FX[6], 0); // 2044 + tp->LineTo(m_FX[6], YB); + } + else { + tp->Pen->Color = sys.m_ColorFFTSync; + tp->Pen->Style = psSolid; + tp->MoveTo(m_FX[3], 0); // 1200 + tp->LineTo(m_FX[3], YB); + tp->Pen->Color = sys.m_ColorFFTFreq; + tp->Pen->Style = psDot; + tp->MoveTo(m_FX[0], 0); // 1900 + tp->LineTo(m_FX[0], YB); + tp->Pen->Style = psSolid; + tp->MoveTo(m_FX[1], 0); // 1500 + tp->LineTo(m_FX[1], YB); + } + tp->Pen->Style = psSolid; + tp->MoveTo(m_FX[2], 0); // 2300 + tp->LineTo(m_FX[2], YB); + if( sys.m_Repeater ){ + tp->Pen->Style = psDot; + tp->MoveTo(m_FX[4], 0); + tp->LineTo(m_FX[4], YB); + tp->Pen->Style = psSolid; + } + } + if( pDem->m_Sync && pDem->m_afc ){ + tp->Pen->Color = clWhite; + tp->Pen->Style = psSolid; +#if NARROW_SYNC == 1200 + int fq = 1200 + pDem->m_AFCFQ; +#else + int fq = (pDem->m_fNarrow ? NARROW_SYNC : 1200) + pDem->m_AFCFQ; +#endif + TPoint ary[3]; + x = int(((fq-m_low)*FFT_SIZE*double(m_XW)/double(FFTSamp*m_FM)) + 0.5); + ary[0].x = x, ary[0].y = 0; + ary[1].x = x-3, ary[1].y = 7; + ary[2].x = x+3, ary[2].y = 7; + tp->Brush->Color = pDem->m_AFCFlag ? clBlue : clRed; + tp->Polygon(ary, 2); + if( pDem->m_AFCFlag ) pDem->m_AFCFlag--; + } + if( sw || (!sys.m_FFTType) ) return; + + + tp->Pen->Color = sys.m_ColorFFT; + + int d; + double k = double(YB)/256.0; + if( sys.m_FFTAGC ){ + if( sys.m_FFTType == 1 ){ + switch(sys.m_FFTGain){ + case 0: + case 1: + case 2: + case 3: + k = k * 64 / m_FFTMax; + break; + case 4: + k = k * 80 / m_FFTMax; + break; + case 5: + k = k * 128 / m_FFTMax; + break; + case 6: + k = k * 384 / m_FFTMax; + break; + case 7: + k = k * 768 / m_FFTMax; + break; + } + } + else { + k = k * 128 / m_FFTMax; + } + } + else if( sys.m_FFTGain >= 4 ){ + k = k * 0.25; + } + int max = 0; + int *mp = &m_fft[1]; + int *wp = &m_FFTMAX[1]; + for( i = 1; i < m_XW; i++, mp++, wp++ ){ + d = *mp * k; + if( d > max ) max = d; + if( d >= YB ) d = YB - 1; + if( *wp < d ) *wp = d; + if( i > 1 ){ + tp->LineTo(i, YB-d); + } + else { + tp->MoveTo(i, YB-d); + } + } + if( sys.m_FFTAGC ){ + m_FFTSumMax -= m_FFTMax; + m_FFTSumMax += max; + switch(sys.m_FFTGain){ + case 4: + if( m_FFTSumMax < 2048 ) m_FFTSumMax = 2048; + break; + case 5: + if( m_FFTSumMax < 1024 ) m_FFTSumMax = 1024; + break; + case 6: + if( m_FFTSumMax < 256 ) m_FFTSumMax = 256; + break; + case 7: + if( m_FFTSumMax < 128 ) m_FFTSumMax = 128; + break; + default: + if( m_FFTSumMax < 160 ) m_FFTSumMax = 160; + break; + } + m_FFTMax = m_FFTSumMax / 4; + } + + if( sys.m_FFTStg ){ + tp->Pen->Color = sys.m_ColorFFTStg; + + mp = &m_FFTMAX[1]; + for( i = 1; i < XR; i++, mp++ ){ + d = *mp; + if( i > 1 ){ + tp->LineTo(i, YB-d); + } + else { + tp->MoveTo(i, YB-d); + } + + switch(sys.m_FFTStg){ + case 1: + (*mp) -= 8; + if( *mp < 0 ) *mp = 0; + break; + case 2: + (*mp) -= 4; + if( *mp < 0 ) *mp = 0; + break; + case 3: + (*mp) -= 2; + if( *mp < 0 ) *mp = 0; + break; + } + } + } + if( pSound->m_notch ){ +// tp->Brush->Color = sys.m_ColorFFTB; + tp->Font->Color = clWhite; + tp->Font->Height = -16; + int tm = ::SetBkMode(tp->Handle, TRANSPARENT); + tp->TextOut(0, 0, "Notch"); + ::SetBkMode(tp->Handle, tm); + tp->Pen->Color = clWhite; + tp->Pen->Style = psSolid; + TPoint ary[3]; + x = m_FX[5]; + ary[0].x = x, ary[0].y = YB; + ary[1].x = x-5, ary[1].y = YB-9; + ary[2].x = x+5, ary[2].y = YB-9; + tp->Brush->Color = clRed; + tp->Polygon(ary, 2); + } +#if SHOWAFCFQ + else if( pDem->m_Sync && pDem->m_AFCFlag ){ + tp->Font->Color = clWhite; + tp->Font->Height = -16; + int tm = ::SetBkMode(tp->Handle, TRANSPARENT); + int fq = (pDem->m_fNarrow ? NARROW_SYNC : 1200) + pDem->m_AFCFQ; + sprintf(bf, "%u", fq); + tp->TextOut(0, 0, bf); + ::SetBkMode(tp->Handle, tm); + } +#endif +} +//--------------------------------------------------------------------------- +// スレッド内でコールしてはいけない +void __fastcall TMmsstv::DrawWater(int sw) +{ + TCanvas *tp = pBitmapWater->Canvas; + TRect rc; + int XR = pBitmapWater->Width - 1; + int YB = pBitmapWater->Height - 1; + rc.Left = 0; + rc.Top = 0; + rc.Right = XR; + rc.Bottom = YB+1; + if( sw ){ + tp->Brush->Color = sys.m_ColorLow; + tp->FillRect(rc); + return; + } + int i; + + TRect src(rc); + src.Bottom--; + rc.Top++; + tp->CopyRect(rc, tp, src); + + int d; + int mx = -MAXINT; + int mi = 0; + int micnt = 0; + double k1 = 128.0/double(m_WaterMax - m_WaterMin); + BYTE *bp = (BYTE *)pBitmapWater->ScanLine[0]; + BYTE *cp; + for( i = 0; i < m_XW; i++ ){ + if( sys.m_FFTStg ){ + d = m_FFTMAX[i] * 2; + } + else { + d = m_fft[i] / 2; + } + if( mx < d ) mx = d; + mi += d; + micnt++; + + d -= m_WaterMin; + d = double(d) * k1; + + if( d >= 128 ) d = 127; + if( d < 0 ) d = 0; + + cp = ((BYTE *)&ColorTable[127-d]) + 2; + *bp++ = *cp--; + *bp++ = *cp--; + *bp++ = *cp; + } + if( sys.m_FFTGain < 4 ){ + m_WaterSumMax -= m_WaterMax; + m_WaterSumMax += mx; + if( m_WaterSumMax < 64 ) m_WaterSumMax = 64; + m_WaterMax = m_WaterSumMax / 4; + if( micnt ){ + m_WaterMin = mi/micnt; + } + if( m_WaterMin >= (m_WaterMax - 16) ) m_WaterMax = m_WaterMin + 16; + } + else if( sys.m_FFTStg ){ + m_WaterMin = 0; + m_WaterMax = 48; + } + else { + m_WaterMin = 0; + m_WaterMax = 64; + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::CMfft(TMessage *Message) +{ + if( pSound != NULL ){ + CalcFFT(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::TimerTimer(TObject *Sender) +{ + if( pSound != NULL ){ + if( !pSound->IsBusy() && sys.m_FFTType && !DisPaint ){ + if( !sys.m_FFTPriority ){ + CalcFFT(); + } + if( m_FFTFlag ){ + DrawFFT(0); + PBoxFFT->Canvas->Draw(0, 0, pBitmapFFT); + if( KVW->Checked ){ + DrawWater(0); + PBoxWater->Canvas->Draw(0, 0, pBitmapWater); + } + if( sys.m_FFTPriority ) memset(m_fft, 0, sizeof(m_fft)); + m_FFTFlag = 0; + } + } + SendSSTV(); + DrawSSTV(); + DrawLvl(); + + if( pSound->IsBusy() ) return; + + if( pDem->m_Sync && m_SyncAccuracy && !m_ReqSampChg && (SSTVSET.m_Mode != smAVT) ){ + if( (m_SyncAccuracy == 2) && !(m_SyncAccuracyN & 2) && (m_AY >= 32) ){ + m_SyncAccuracyN = 3; + RedrawSampFreq(FALSE); + } + else if( !(m_SyncAccuracyN & 1) && (m_AY >= 16) ){ + m_SyncAccuracyN = 1; + RedrawSampFreq(FALSE); + } + } +#if 0 + if( (m_MainPage == pgTX) && (!SBTX->Down) ){ + if( !m_Timer1S ){ + m_Timer1S = 20; + UpdateUI(); + } + m_Timer1S--; + } +#endif + if( pRxView != NULL ){ + if( pRxView->Visible ){ + if( !SBTX->Down || sys.m_echo ){ + if( !m_TimerRXV ){ + m_TimerRXV = 5; + pRxView->PBoxPaint(NULL); + } + m_TimerRXV--; + } +// ::SetWindowPos(pRxView->Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE ); + } + else { + pRxView->GetViewPos(sys.m_RxViewLeft, sys.m_RxViewTop, sys.m_RxViewWidth, sys.m_RxViewHeight); + delete pRxView; + pRxView = NULL; + } + } + if( pSyncView != NULL ){ + if( pSyncView->Visible ){ + if( !m_TimerRXS ){ + m_TimerRXS = 5; + pSyncView->PBoxPaint(NULL); + } + m_TimerRXS--; + } + else { + pSyncView->GetViewPos(sys.m_SyncViewLeft, sys.m_SyncViewTop, sys.m_SyncViewWidth, sys.m_SyncViewHeight); + delete pSyncView; + pSyncView = NULL; + } + } + if( m_FileViewClose ){ + m_FileViewClose = 0; + AdjustFileView(); + if( pHistView != NULL ){ + if( !pHistView->Visible ){ + CloseHistView(); + } + } + } + if( (pCtrBtn != NULL) && !pCtrBtn->Visible ){ + pCtrBtn->GetViewPos(sys.m_CtrBtnLeft, sys.m_CtrBtnTop, sys.m_CtrBtnWidth, sys.m_CtrBtnHeight); + delete pCtrBtn; + pCtrBtn = NULL; + } + + if( pDem->m_fskrec ){ + pDem->m_fskrec = 0; + if( pDem->m_Sync && ((pCtrBtn == NULL) || (!pCtrBtn->SBLock->Down)) ){ // 強制停止 + if( pDem->m_LoopBack != 1 ){ + pDem->m_SyncMode = 0; + RxAutoPush(TRUE); +// SBAuto->Down = TRUE; +// SBAutoClick(NULL); + } + } + if( strcmp(sys.m_Call.c_str(), pDem->m_fskcall) ){ + AddCall(pDem->m_fskcall); + if( !SBTX->Down && (!SBQSO->Down || HisCall->Text.IsEmpty()) ){ + if( strcmp(AnsiString(HisCall->Text).c_str(), pDem->m_fskcall) ){ //ja7ude 0428 + HisCall->Text = pDem->m_fskcall; + FindCall(); + HisCallChange(NULL); + } + } + } + } + if( pDem->m_fskNRrec ){ + pDem->m_fskNRrec = 0; +#if DEBUGFSKID + if( (!SBQSO->Down || (strlen(MyRST->Text.c_str()) <= 3)) ){ +#else + if( !SBTX->Down && (!SBQSO->Down || (strlen(AnsiString(MyRST->Text).c_str()) <= 3) || !strcmp(AnsiString(HisCall->Text).c_str(), pDem->m_fskcall)) ){ //ja7ude 0428 +#endif + char bf[MLRST+1]; + sprintf(bf, "595%s", pDem->m_fskNRS); + if( strcmp(AnsiString(MyRST->Text).c_str(), bf) ){ //ja7ude 0428 + MyRST->Text = bf; + HisCallChange(NULL); + } + } + } + } + if( pRadio != NULL ){ + pRadio->Timer(SBTX->Down, Timer->Interval); + if( pRadio->IsFreqChange(AnsiString(LogFreq->Text).c_str()) ){ //ja7ude 0428 + LogFreq->Text = pRadio->GetFreq(); + LogFreqChange(NULL); + } + } + if( m_ChangeTemp && !SBTX->Down && (SBUseTemp->Down || (KTBT->Checked && (m_MainPage == pgTemp)) ) ){ + m_ChangeTemp--; + if( !m_ChangeTemp ){ + m_ChangeTemp = 1; + UpdatePic(); + } + } + if( m_ReqSampChg ){ + if( m_ReqSampChg < 0 ){ + m_ReqSampChg = 0; + RedrawSampFreq(FALSE); + } + else { + m_ReqSampChg--; + if( !m_ReqSampChg ){ + RedrawSampFreq(TRUE); + } + } + } + if( m_ReqHistF && !SBTX->Down && !m_TempHold && ((m_MainPage == pgTX) || (m_MainPage == pgTemp)) ){ + m_ReqHistF--; + if( !m_ReqHistF ){ + AdjustHistF(); + UpdatePic(); + } + } + if( m_TuneTimer && SBTune->Down ){ + if( ::GetTickCount() >= m_TuneTimer ){ + m_TuneTimer = 0; + if( sys.m_TuneSat && (sys.m_TuneTXTime >= 0) ){ + ToTX(); + } + else { + ToRX(); + } + } + } + if( m_TempTimer ) m_TempTimer--; + + if( LogLink.IsEnabled() ){ + if( LogLink.TimerLogLink() ){ + UpdateLogLink(); + } + if( LogLink.IsPolling() && LogLink.IsLink() && !SBTX->Down && !pDem->m_Sync ){ + LogLink.EventGetFreq(); + } + } + + if( sys.m_Repeater && !SBTX->Down && pDem->m_Repeater ){ + Repeater(); + } + g_ExecPB.Timer(); +#if 0 + CSSTVDEM *dp = &pSound->SSTVDEM; + CSYNCINT *si = &dp->m_sint2; + char bf[128]; + sprintf(bf, "%d, %d, %d, %d", si->m_MSyncList[5], si->m_MSyncList[4], si->m_MSyncList[3], si->m_MSyncList[2]); +// sprintf(bf, "%d, %d, %s, %s", pDem->m_fskmode, pDem->m_fskcnt, pDem->m_fskdata, pDem->m_fskcall); +// sprintf(bf, "%d", pDem->m_VisTrig); +// sprintf(bf, "%d", dp->m_repsig); + EditNote->Text = bf; +#endif +#if 0 + char bf[128]; + sprintf(bf, "%d,%d,%d", m_SyncMax, m_SyncRPos, int(SSTVSET.m_OFP)); + EditNote->Text = bf; +#endif +#if 0 + char bf[128]; + sprintf(bf, "%d", _getmbcp()); + EditNote->Text = bf; +// _setmbcp(932); +#endif +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::UpdateLogLink(void) +{ + LogLink.UpdateLink(sys.m_LogLink); + char bf[256]; + if( LogLink.IsLink() ){ + sprintf(bf, "Log [Link to %s]", LogLink.GetSessionName()); + GBLog->Caption = bf; + } + else { + GBLog->Caption = "Log"; + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SyncSSTV(void) +{ + CSSTVDEM *dp = pDem; + if( SSTVSET.m_Mode == smAVT ){ + SSTVSET.m_IOFS = SSTVSET.m_OFS = 0; + dp->m_wBgn = 0; + return; + } + int e = 4; + if( m_SyncAccuracy && sys.m_UseRxBuff && (SSTVSET.m_TW >= SSTVSET.m_SampFreq) ) e = 3; + if( dp->m_wLine >= e ){ + int i, pg, x; + int n = 0; + int wd = int(SSTVSET.m_TW) + 2; + int *bp = new int[wd]; + memset(bp, 0, sizeof(int)*(wd)); + for( pg = 0; pg < e; pg++ ){ + short *sp = &dp->m_B12[pg * dp->m_BWidth]; + for( i = 0; i < SSTVSET.m_WD; i++, sp++ ){ + x = fmod(n, SSTVSET.m_TW); + bp[x] += *sp; + n++; + } + } + n = 0; + int max = 0; + for( i = 0; i < wd; i++ ){ + if( max < bp[i] ){ + max = bp[i]; + n = i; + } + } + n -= SSTVSET.m_OFP; + n = -n; + switch(SSTVSET.m_Mode){ + case smSCT1: + case smSCT2: + case smSCTDX: + if( n < 0 ) n += SSTVSET.m_WD; + break; + default: + break; + } + if( dp->m_Type == 2 ) n -= dp->m_hill.m_htap/4; + SSTVSET.m_IOFS = SSTVSET.m_OFS = dp->m_rBase = n; + delete bp; + dp->m_wBgn = 0; + } +} + +void __fastcall TMmsstv::InitAutoStop(void) +{ + memset(m_AutoStopAPos, 0, sizeof(m_AutoStopAPos)); + m_AutoStopCnt = 0; + m_AutoStopACnt = 0; + m_AutoStopPos = 0; + m_ASBgnPos = 0x7fffffff; + m_ASDis = 0; + m_ASBitMask = 0; + m_ASAvg.SetCount(16); + m_Z[0] = m_Z[1] = m_Z[2] = 0; + m_ASPos[0] = 64; + m_ASPos[1] = 128; + m_ASPos[2] = 160; + m_ASPos[3] = (SSTVSET.m_L - 36); + switch(SSTVSET.m_Mode){ + case smPD50: + case smPD90: // Max 128 + case smMP73: + case smMP115: + case smMP140: + case smMP175: + case smR24: + case smRM8: + case smRM12: + case smMN73: + case smMN110: + case smMN140: + m_ASPos[0] = 48; + m_ASPos[1] = 64; + m_ASPos[2] = 72; + m_ASPos[3] = 110; + break; + case smPD160: // Max 200 + m_ASPos[0] = 48; + m_ASPos[1] = 80; + m_ASPos[2] = 126; + m_ASPos[3] = 160; + break; + case smPD290: // Max 308 Limit 288 + m_ASPos[3] = 240; + break; + case smP3: // Max496 + m_ASPos[1] = 200; + m_ASPos[2] = 360; + m_ASPos[3] = 496-48; + break; + case smP5: // Max496 Limit 439 + m_ASPos[1] = 200; + m_ASPos[2] = 300; + m_ASPos[3] = 380; + break; + case smP7: // Max496 Limit 330 + m_ASPos[1] = 128; + m_ASPos[2] = 220; + m_ASPos[3] = 280; + break; + } + m_AutoSyncPos = 0x7fffffff; + m_Mult = int(SSTVSET.m_TW / 320.0); + m_AutoSyncDiff = m_Mult * 3; + if( m_AutoSyncDiff > (45 * SampBase / 11025) ) m_AutoSyncDiff = (45 * SampBase / 11025); +} + +//--------------------------------------------------------------------------- +// 最小2乗近似 +int __fastcall TMmsstv::GetSqerrPos(int n) +{ + double T, L, TT, TL; + T = L = TT = TL = 0; + for( int i = 0; i < n; i++ ){ + T += i; + int l = m_AutoStopAPos[15-i]; + L += l; + TT += i * i; + TL += i * l; + } + double l0 = (L * TT - T * TL) / (n * TT - T*T); +// double k0 = (5 * TL - L * T) / (5 * TT - T*T); + return l0; +} + +//--------------------------------------------------------------------------- +int __fastcall TMmsstv::AutoStopJob(void) +{ + if( (sys.m_AutoStop || sys.m_AutoSync || KRSA->Checked) && (SSTVSET.m_Mode != smAVT) ){ // 自動停止のチェック + m_AutoStopPos = m_SyncPos - int(SSTVSET.m_OFP); + int h = SSTVSET.m_TW/2; + m_AutoStopPos = m_AutoStopPos > h ? m_AutoStopPos - SSTVSET.m_TW : m_AutoStopPos; + if( m_AutoStopACnt >= 8 ){ + int i, n; + for( n = i = 0; i < 16; i++ ){ + int df = ABS(m_AutoStopPos - m_AutoStopAPos[i]); + if( m_AutoStopACnt >= 16 ){ + if( df <= (14*m_Mult) ) n++; + } + else { + if( df <= (10*m_Mult) ) n++; + } + } +#if 0 + char bf[128]; + sprintf(bf, "%d, %d", m_AutoStopPos, m_SyncMax - m_SyncMin); + EditNote->Text = bf; +#endif + if( n < 4 ){ + if( sys.m_AutoSync && !m_ASDis && (n >= 2) && (m_AutoSyncPos != 0x7fffffff) && !m_AutoSyncCount && sys.m_UseRxBuff ){ + if( (m_SyncMax - m_SyncMin) > 5000 ){ + int df = m_AutoStopPos - m_AutoStopAPos[15]; + if( ABS(df) <= ((KRSA->Checked ? 5 : 2)*m_Mult) ){ + if( m_AutoSyncCount || !sys.m_UseRxBuff ){ + df = m_AutoStopPos; + } + else { + df = m_AutoStopPos - m_AutoSyncPos; + } + if( ABS(df) >= ((KRSA->Checked ? 5 : 2)*m_Mult) ){ + df = m_AutoStopPos; + if( df < 0 ) df += SSTVSET.m_TW; + pDem->m_Skip = df; + m_SyncPos = m_SyncRPos = -1; + m_AutoSyncPos = 0x7fffffff; + m_AutoSyncDis = 6; + m_AutoSyncCount++; + if( m_AutoStopCnt ) m_AutoStopCnt--; + } + } + } + } + if( (n < 2) || ((m_SyncMax - m_SyncMin) < 8192) ){ + m_AutoStopCnt++; + } + if( sys.m_AutoStop && !m_ASDis && (m_AutoStopCnt >= 8) ){ + RxAutoPush(TRUE); +// SBAuto->Down = TRUE; +// SBAutoClick(NULL); + return TRUE; + } + } + else { + m_AutoSyncPos = m_AutoStopPos; + m_AutoStopCnt -= 2; + if( m_AutoStopCnt < 0 ) m_AutoStopCnt = 0; + } + if( sys.m_AutoSync && !m_ASDis && (!m_AutoSyncDis) && (m_AutoSyncPos != 0x7fffffff) && (m_AutoSyncCount || !sys.m_UseRxBuff) ){ + if( (m_SyncMax - m_SyncMin) > 5000 ){ + int df = m_AutoStopPos - m_AutoStopAPos[15]; + if( ABS(df) <= m_AutoSyncDiff ){ + df = m_AutoStopPos; + if( ABS(df) >= m_AutoSyncDiff ){ + if( df < 0 ) df += SSTVSET.m_TW; + pDem->m_Skip = df; + m_SyncPos = m_SyncRPos = -1; + m_AutoSyncPos = 0x7fffffff; + m_AutoSyncDis = 6; + m_AutoSyncCount++; + if( m_AutoStopCnt ) m_AutoStopCnt--; + } + } + } + } + } + if( m_AutoSyncDis ) m_AutoSyncDis--; + m_AutoStopACnt++; + memcpy(m_AutoStopAPos, &m_AutoStopAPos[1], sizeof(m_AutoStopAPos) - sizeof(int)); + m_AutoStopAPos[15] = m_AutoStopPos; + + if( KRSA->Checked && !m_AutoSyncCount && (!SBTX->Down || (sys.m_echo == 2) || sys.m_TxSampOff) ){ + if( m_AutoStopACnt >= 5 ){ + int df, cf; + df = ABS(m_AutoStopAPos[15] - m_AutoStopAPos[14]); + cf = ABS(m_AutoStopAPos[14] - m_AutoStopAPos[13]); + if( df < cf ) df = cf; + cf = ABS(m_AutoStopAPos[13] - m_AutoStopAPos[12]); + if( df < cf ) df = cf; + cf = ABS(m_AutoStopAPos[12] - m_AutoStopAPos[11]); + if( df < cf ) df = cf; + cf = ABS(m_AutoStopAPos[11] - m_AutoStopAPos[10]); + if( df < cf ) df = cf; + int pos; + if( df < (8*m_Mult) ){ +// pos = m_AutoStopAPos[15]; + pos = GetSqerrPos(5); +#if 0 + char bf[64]; + sprintf(bf, "%d, %d", pos, m_AutoStopAPos[15]); + EditNote->Text = bf; +#endif + if( m_ASBgnPos == 0x7fffffff ){ + m_ASBgnPos = pos; + m_ASCurY = 0; + } + else if( m_ASCurY >= 3){ + double d = (m_ASBgnPos - pos) * SSTVSET.m_SampFreq / SSTVSET.m_TW; + d /= m_ASCurY; + double smp = m_ASAvg.Avg(SSTVSET.m_SampFreq - d); + d = SSTVSET.m_SampFreq - smp; + if( (!(m_ASBitMask & 1) && (ABS(d) >= m_ASLmt[0]) )|| + (!(m_ASBitMask & 1) && (m_ASCurY >= 16) && (ABS(d) >= m_ASLmt[1]))|| + (!(m_ASBitMask & 1) && (m_ASCurY >= 32) && (ABS(d) >= m_ASLmt[2]))|| + (!(m_ASBitMask & 2) && (m_ASCurY >= m_ASPos[0]) && (ABS(d) >= m_ASLmt[3]))|| + (!(m_ASBitMask & 4) && (m_ASCurY >= m_ASPos[1]) && (ABS(d) >= m_ASLmt[4]))|| + (!(m_ASBitMask & 8) && (m_ASCurY >= m_ASPos[2]) && (ABS(d) >= m_ASLmt[5]))|| + (!(m_ASBitMask & 16) && (m_ASCurY >= m_ASPos[3]) && (ABS(d) >= m_ASLmt[6])) + ){ + if( m_ASCurY >= 32 ) m_ASBitMask |= 1; + if( m_ASCurY >= m_ASPos[0] ) m_ASBitMask |= 2; + if( m_ASCurY >= m_ASPos[1] ) m_ASBitMask |= 4; + if( m_ASCurY >= m_ASPos[2] ) m_ASBitMask |= 8; + if( m_ASCurY >= m_ASPos[3] ) m_ASBitMask |= 16; + if( !m_ASDis ){ + if( smp > (SampFreq * 1100/1060) ){ + smp = SampFreq * 1100/1060; + } + SSTVSET.m_SampFreq = NormalSampFreq(smp, 50); + m_ReqSampChg = 1; + } + } +#if 0 + if( !m_ASDis && (m_AutoStopACnt >= 16) ){ + char bf[32]; + sprintf(bf, "%8.2lf", NormalSampFreq(smp, 50)); + pBitmapD12->Canvas->Brush->Color = clBlack; + pBitmapD12->Canvas->Font->Color = clWhite; + pBitmapD12->Canvas->TextOut(250, 3, bf); + } +#endif + } + } + } + } + m_ASCurY++; + } + return FALSE; +} + +//--------------------------------------------------------------------------- +int __fastcall TMmsstv::GetPixelLevel(short *ip) +{ + if( sys.m_DemCalibration && (pCalibration != NULL) ){ + int d = (*ip / 8) + 2048; + if( d < 0 ) d = 0; + if( d > 4096 ) d = 4096; + return pCalibration[d]; + } + else { + int d = (*ip - sys.m_DemOff); + if( d >= 0 ){ + d *= sys.m_DemWhite; + } + else { + d *= sys.m_DemBlack; + } + return d; + } +} +//--------------------------------------------------------------------------- +int __fastcall TMmsstv::GetPictureLevel(short *ip) +{ + int d; + if( sys.m_UseRxBuff != 2 ){ + if( *ip < *(ip+SSTVSET.m_KSB) ){ + d = GetPixelLevel(ip+SSTVSET.m_KSB); + } + else { + d = GetPixelLevel(ip); + } + } + else { + d = GetPixelLevel(ip); + } + return d; +} +//--------------------------------------------------------------------------- +int __fastcall TMmsstv::GetPictureLevelDiff(short *ip) +{ + int d; + if( sys.m_UseRxBuff != 2 ){ + if( *ip < *(ip+SSTVSET.m_KSB) ){ + d = GetPixelLevel(ip+SSTVSET.m_KSB); + } + else { + d = GetPixelLevel(ip); + } + } + else { + d = GetPixelLevel(ip); + } + double o = (d * -0.5 + m_Z[0] + m_Z[1] * -0.5); + if( o > 0.0 ){ + o *= sys.m_DiffLevelP; + } + else { + o *= sys.m_DiffLevelM; + } + o += m_Z[2]; + m_Z[1] = m_Z[0]; + m_Z[2] = m_Z[0] = d; + return o; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::MultProc(void) +{ + if( pSound == NULL ) return; + + if( pDem->m_Sync || pSound->m_Tx ){ + if( pSound->m_Tx && IsSR() ) SendSSTV(); + ::Sleep(pSound->IsBusy() ? 100 : 1); + DrawSSTV(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::DrawSSTV(short *ip, short *sp) +{ + if( sys.m_Differentiator && (SSTVSET.m_Mode != smSCTDX) ){ + DrawSSTVDiff(ip, sp); + } + else { + DrawSSTVNormal(ip, sp); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::DrawSSTVNormal(short *ip, short *sp) +{ + CSSTVDEM *dp = pDem; + BYTE *gp = NULL; + BYTE *bp = NULL; + BYTE *wp; + BYTE *gp2 = NULL; + int R,G,B; + int i, n; + int bx = -1; + n = dp->m_rBase; + + int ay = -5; + for( i = 0; i < SSTVSET.m_WD; i++, ip++, sp++, n++ ){ + if( n < 0 ) continue; + double ps = fmod(double(n), SSTVSET.m_TW); + int y = int(double(n)/SSTVSET.m_TW); + if( ay != y ){ + m_AY = ay = y; + if( (SSTVSET.m_Mode == smSCT1)||(SSTVSET.m_Mode == smSCT2)||(SSTVSET.m_Mode == smSCTDX) ){ + if( (y > 0) && (y <= 256) ){ + gp = (BYTE *)pBitmapRX->ScanLine[y-1]; + } + else { + gp = NULL; + } + } + else if( ((SSTVSET.m_Mode >= smPD50)&&(SSTVSET.m_Mode <= smPD290)) || + ((SSTVSET.m_Mode >= smMP73)&&(SSTVSET.m_Mode <= smMP175)) || + ((SSTVSET.m_Mode >= smMN73)&&(SSTVSET.m_Mode <= smMN140)) || + ((SSTVSET.m_Mode >= smR24)&&(SSTVSET.m_Mode <= smRM12)) + ){ + if( (y >= 0) && (y < SSTVSET.m_L) ){ + R = y * 2; + gp = (BYTE *)pBitmapRX->ScanLine[R]; + gp2 = (BYTE *)pBitmapRX->ScanLine[R+1]; + } + else { + gp = NULL; + gp2 = NULL; + } + } + else if( (y >= 0) && (y < pBitmapRX->Height) ){ + gp = (BYTE *)pBitmapRX->ScanLine[y]; + } + else { + gp = NULL; + } + if( (y >= 0) && (y < 256) ){ + bp = (BYTE *)pBitmapD12->ScanLine[y]; + } + else { + bp = NULL; + } + } + if( !int(ps) ){ + if( (sys.m_AutoStop || sys.m_AutoSync || KRSA->Checked) && dp->m_Sync && (m_SyncPos != -1) ){ + AutoStopJob(); + } + m_SyncMin = m_SyncMax = *sp; + m_SyncRPos = m_SyncPos; + } + else if( m_SyncMax < *sp ){ + m_SyncMax = *sp; + m_SyncPos = ps; + } + else if( m_SyncMin > *sp ){ + m_SyncMin = *sp; + } + int d, x; + x = ps * pBitmapD12->Width / SSTVSET.m_TW; + if( (x != bx) && (x < pBitmapD12->Width) && (x >= 0) ){ + if( bp != NULL ){ + d = (*sp * 256) / 4096; + d = Limit256(d); + wp = bp + (x * 3); + *wp++ = BYTE(d); + *wp++ = BYTE(d); + *wp = BYTE(d); + } + bx = x; + } + if( ps >= SSTVSET.m_OF ){ + ps -= SSTVSET.m_OF; + switch(SSTVSET.m_Mode){ + case smSCT1: + case smSCT2: + case smSCTDX: + if( ps < SSTVSET.m_KS ){ // R + x = ps * pBitmapRX->Width / SSTVSET.m_KSS; + if( (x != m_AX) && (x >= 0) && (x < 320) ){ + m_AX = x; + if( SSTVSET.m_Mode == smSCTDX ){ + d = GetPixelLevel(ip); + } + else { + d = GetPictureLevel(ip); + } + d += 128; + d = Limit256(d); + if( gp != NULL ){ + wp = gp + (x * 3); + *wp++ = BYTE(m_D36[1][x]); // B + *wp++ = BYTE(m_D36[0][x]); // G + *wp = BYTE(d); // R + } + } + } + else if( ps < SSTVSET.m_CG ){ // G + ps -= SSTVSET.m_SG; + x = ps * pBitmapRX->Width / SSTVSET.m_KSS; + if( (x != m_AX) && (x >= 0) && (x < 320) ){ + m_AX = x; + if( SSTVSET.m_Mode == smSCTDX ){ + d = GetPixelLevel(ip); + } + else { + d = GetPictureLevel(ip); + } + d += 128; + d = Limit256(d); + m_D36[0][x] = short(d); + } + } + else if( ps < SSTVSET.m_CB ){ // B + ps -= SSTVSET.m_SB; + x = ps * pBitmapRX->Width / SSTVSET.m_KSS; + if( (x != m_AX) && (x >= 0) && (x < 320) ){ + m_AX = x; + if( SSTVSET.m_Mode == smSCTDX ){ + d = GetPixelLevel(ip); + } + else { + d = GetPictureLevel(ip); + } + d += 128; + d = Limit256(d); + m_D36[1][x] = short(d); + } + } + break; + case smR36: + if( ps < SSTVSET.m_KS ){ // 輝度 + x = ps * pBitmapRX->Width / SSTVSET.m_KSS; + if( (m_AX != x) && (x >= 0) && (x < 320) ){ + m_AX = x; + d = GetPictureLevel(ip); + d += 128; + d = Limit256(d); + m_Y36[x] = short(d); + } + } + else if( ps < SSTVSET.m_CG ){ // TCS + ps -= SSTVSET.m_SG; + if( ps >= 0 ){ + d = GetPixelLevel(ip); + if( (d >= 64) || (d < -64) ){ + m_DSEL = (d >= 0) ? 1 : 0; // RY=1500 m_D36[0], BY=2300 m_D36[1] + } + else { + m_DSEL = m_DSEL ? 0 : 1; + } + } + } + else if( ps < SSTVSET.m_CB ){ // 色差 + ps -= SSTVSET.m_SB; + x = ps * pBitmapRX->Width / SSTVSET.m_KS2S; + if( (m_AX != x) && (x >= 0) && (x < 320) && (y < 240) ){ + m_AX = x; + d = GetPixelLevel(ip); + m_D36[m_DSEL][x] = short(d); + YCtoRGB(R, G, B, m_Y36[x], m_D36[0][x], m_D36[1][x]); + if( gp != NULL ){ + wp = gp + (x * 3); + *wp++ = BYTE(B); // B + *wp++ = BYTE(G); // G + *wp = BYTE(R); // R + } + } + } + break; + case smR24: + case smR72: + case smMR73: + case smMR90: + case smMR115: + case smMR140: + case smMR175: + case smML180: + case smML240: + case smML280: + case smML320: + if( ps < SSTVSET.m_KS ){ // 輝度 + x = ps * pBitmapRX->Width / SSTVSET.m_KSS; + if( (m_AX != x) && (x >= 0) && (x < pBitmapRX->Width) ){ + m_AX = x; + d = GetPictureLevel(ip); + d += 128; + d = Limit256(d); + m_Y36[x] = short(d); + } + } + else if( ps < SSTVSET.m_CG ){ // R-Y + ps -= SSTVSET.m_SG; + x = ps * pBitmapRX->Width / SSTVSET.m_KS2S; + if( (m_AX != x) && (x >= 0) && (x < pBitmapRX->Width) ){ + m_AX = x; + d = GetPixelLevel(ip); + m_D36[1][x] = short(d); + } + } + else if( ps < SSTVSET.m_CB ){ // B-Y + ps -= SSTVSET.m_SB; + x = ps * pBitmapRX->Width / SSTVSET.m_KS2S; + if( (m_AX != x) && (x >= 0) && (x < pBitmapRX->Width) && (y < SSTVSET.m_L) ){ + m_AX = x; + d = GetPixelLevel(ip); + YCtoRGB(R, G, B, m_Y36[x], m_D36[1][x], d); + if( gp != NULL ){ + wp = gp + (x * 3); + *wp++ = BYTE(B); // B + *wp++ = BYTE(G); // G + *wp = BYTE(R); // R + if( SSTVSET.m_Mode == smR24 ){ + wp = gp2 + (x * 3); + *wp++ = BYTE(B); // B + *wp++ = BYTE(G); // G + *wp = BYTE(R); // R + } + } + } + } + break; + case smPD50: + case smPD90: + case smPD120: + case smPD160: + case smPD180: + case smPD240: + case smPD290: + case smMP73: + case smMP115: + case smMP140: + case smMP175: + case smMN73: + case smMN110: + case smMN140: + if( ps < SSTVSET.m_KS ){ // 輝度 + x = ps * pBitmapRX->Width / SSTVSET.m_KSS; + if( (m_AX != x) && (x >= 0) && (x < pBitmapRX->Width) ){ + m_AX = x; + d = GetPictureLevel(ip); + d += 128; + d = Limit256(d); + m_Y36[x] = short(d); + } + } + else if( ps < SSTVSET.m_CG ){ // R-Y + ps -= SSTVSET.m_SG; + x = ps * pBitmapRX->Width / SSTVSET.m_KSS; + if( (m_AX != x) && (x >= 0) && (x < pBitmapRX->Width) ){ + m_AX = x; + d = GetPixelLevel(ip); + m_D36[1][x] = short(d); + } + } + else if( ps < SSTVSET.m_CB ){ // B-Y + ps -= SSTVSET.m_SB; + x = ps * pBitmapRX->Width / SSTVSET.m_KSS; + if( (m_AX != x) && (x >= 0) && (x < pBitmapRX->Width) ){ + m_AX = x; + d = GetPixelLevel(ip); + m_D36[0][x] = short(d); + } + } + else if( ps < (SSTVSET.m_CB + SSTVSET.m_KS) ){ // Y(even) + ps -= SSTVSET.m_CB; + x = ps * pBitmapRX->Width / SSTVSET.m_KSS; + if( (m_AX != x) && (x >= 0) && (x < pBitmapRX->Width) && (y < SSTVSET.m_L) ){ + m_AX = x; + if( gp != NULL ){ + YCtoRGB(R, G, B, m_Y36[x], m_D36[1][x], m_D36[0][x]); + wp = gp + (x * 3); + *wp++ = BYTE(B); // B + *wp++ = BYTE(G); // G + *wp = BYTE(R); // R + d = GetPictureLevel(ip); + d += 128; + YCtoRGB(R, G, B, d, m_D36[1][x], m_D36[0][x]); + wp = gp2 + (x * 3); + *wp++ = BYTE(B); // B + *wp++ = BYTE(G); // G + *wp = BYTE(R); // R + } + } + } + break; + case smRM8: + case smRM12: + if( ps < SSTVSET.m_KS ){ // 輝度 + x = ps * pBitmapRX->Width / SSTVSET.m_KSS; + if( (m_AX != x) && (x >= 0) && (x < pBitmapRX->Width) && (y < SSTVSET.m_L) ){ + m_AX = x; + d = GetPictureLevel(ip); + d *= (256.0 / (256.0 - 32.0)); + d += 128; + d = Limit256(d); + if( gp != NULL ){ + wp = gp + (x * 3); + *wp++ = BYTE(d); // B + *wp++ = BYTE(d); // G + *wp = BYTE(d); // R + wp = gp2 + (x * 3); + *wp++ = BYTE(d); // B + *wp++ = BYTE(d); // G + *wp = BYTE(d); // R + } + } + } + break; + default: + if( ps < SSTVSET.m_KS ){ // R or G(MRT) + x = ps * pBitmapRX->Width / SSTVSET.m_KSS; + if( (x != m_AX) && (x >= 0) && (x < pBitmapRX->Width) ){ + m_AX = x; + d = GetPictureLevel(ip); + d += 128; + d = Limit256(d); + m_D36[0][x] = short(d); + } + } + else if( ps < SSTVSET.m_CG ){ // G or B(MRT) + ps -= SSTVSET.m_SG; + x = ps * pBitmapRX->Width / SSTVSET.m_KSS; + if( (x != m_AX) && (x >= 0) && (x < pBitmapRX->Width) ){ + m_AX = x; + d = GetPictureLevel(ip); + d += 128; + d = Limit256(d); + m_D36[1][x] = short(d); + } + } + else if( ps < SSTVSET.m_CB ){ // B or R(MRT) + ps -= SSTVSET.m_SB; + x = ps * pBitmapRX->Width / SSTVSET.m_KSS; + if( (x != m_AX) && (x >= 0) && (x < pBitmapRX->Width) ){ + m_AX = x; + d = GetPictureLevel(ip); + d += 128; + d = Limit256(d); + if( (SSTVSET.m_Mode == smMRT1)||(SSTVSET.m_Mode == smMRT2) ){ + if( gp != NULL ){ + wp = gp + (x * 3); + *wp++ = BYTE(m_D36[1][x]); // B + *wp++ = BYTE(m_D36[0][x]); // G + *wp = BYTE(d); // R + } + } + else { + if( gp != NULL ){ + wp = gp + (x * 3); + *wp++ = BYTE(d); // B + *wp++ = BYTE(m_D36[1][x]); // G + *wp = BYTE(m_D36[0][x]); // R + } + } + } + } + break; + } + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::DrawSSTVDiff(short *ip, short *sp) +{ + CSSTVDEM *dp = pDem; + BYTE *gp = NULL; + BYTE *bp = NULL; + BYTE *wp; + BYTE *gp2 = NULL; + int R,G,B; + int i, n; + int bx = -1; + n = dp->m_rBase; + + int ay = -5; + for( i = 0; i < SSTVSET.m_WD; i++, ip++, sp++, n++ ){ + if( n < 0 ) continue; + double ps = fmod(double(n), SSTVSET.m_TW); + int y = int(double(n)/SSTVSET.m_TW); + if( ay != y ){ + m_AY = ay = y; + if( (SSTVSET.m_Mode == smSCT1)||(SSTVSET.m_Mode == smSCT2)||(SSTVSET.m_Mode == smSCTDX) ){ + if( (y > 0) && (y <= 256) ){ + gp = (BYTE *)pBitmapRX->ScanLine[y-1]; + } + else { + gp = NULL; + } + } + else if( ((SSTVSET.m_Mode >= smPD50)&&(SSTVSET.m_Mode <= smPD290)) || + ((SSTVSET.m_Mode >= smMP73)&&(SSTVSET.m_Mode <= smMP175)) || + ((SSTVSET.m_Mode >= smMN73)&&(SSTVSET.m_Mode <= smMN140)) || + ((SSTVSET.m_Mode >= smR24)&&(SSTVSET.m_Mode <= smRM12)) + ){ + if( (y >= 0) && (y < SSTVSET.m_L) ){ + R = y * 2; + gp = (BYTE *)pBitmapRX->ScanLine[R]; + gp2 = (BYTE *)pBitmapRX->ScanLine[R+1]; + } + else { + gp = NULL; + gp2 = NULL; + } + } + else if( (y >= 0) && (y < pBitmapRX->Height) ){ + gp = (BYTE *)pBitmapRX->ScanLine[y]; + } + else { + gp = NULL; + } + if( (y >= 0) && (y < 256) ){ + bp = (BYTE *)pBitmapD12->ScanLine[y]; + } + else { + bp = NULL; + } + } + if( !int(ps) ){ + if( (sys.m_AutoStop || sys.m_AutoSync || KRSA->Checked) && dp->m_Sync && (m_SyncPos != -1) ){ + AutoStopJob(); + } + m_SyncMin = m_SyncMax = *sp; + m_SyncRPos = m_SyncPos; + } + else if( m_SyncMax < *sp ){ + m_SyncMax = *sp; + m_SyncPos = ps; + } + else if( m_SyncMin > *sp ){ + m_SyncMin = *sp; + } + int d, x; + x = ps * pBitmapD12->Width / SSTVSET.m_TW; + if( (x != bx) && (x < pBitmapD12->Width) && (x >= 0) ){ + if( bp != NULL ){ + d = (*sp * 256) / 4096; + d = Limit256(d); + wp = bp + (x * 3); + *wp++ = BYTE(d); + *wp++ = BYTE(d); + *wp = BYTE(d); + } + bx = x; + } + if( ps >= SSTVSET.m_OF ){ + ps -= SSTVSET.m_OF; + switch(SSTVSET.m_Mode){ + case smSCT1: + case smSCT2: + if( ps < SSTVSET.m_KS ){ // R + x = ps * pBitmapRX->Width / SSTVSET.m_KSS; + if( (x != m_AX) && (x >= 0) && (x < 321) ){ + m_AX = x; + x = x ? x - 1 : 0; + d = GetPictureLevelDiff(ip); + if( m_AX ){ + d += 128; + d = Limit256(d); + if( gp != NULL ){ + wp = gp + (x * 3); + *wp++ = BYTE(m_D36[1][x]); // B + *wp++ = BYTE(m_D36[0][x]); // G + *wp = BYTE(d); // R + } + } + } + } + else if( ps < SSTVSET.m_CG ){ // G + ps -= SSTVSET.m_SG; + x = ps * pBitmapRX->Width / SSTVSET.m_KSS; + if( (x != m_AX) && (x >= 0) && (x < 321) ){ + m_AX = x; + x = x ? x - 1 : 0; + d = GetPictureLevelDiff(ip); + d += 128; + d = Limit256(d); + m_D36[0][x] = short(d); + } + } + else if( ps < SSTVSET.m_CB ){ // B + ps -= SSTVSET.m_SB; + x = ps * pBitmapRX->Width / SSTVSET.m_KSS; + if( (x != m_AX) && (x >= 0) && (x < 321) ){ + m_AX = x; + x = x ? x - 1 : 0; + d = GetPictureLevelDiff(ip); + d += 128; + d = Limit256(d); + m_D36[1][x] = short(d); + } + } + break; + case smR36: + if( ps < SSTVSET.m_KS ){ // 輝度 + x = ps * pBitmapRX->Width / SSTVSET.m_KSS; + if( (m_AX != x) && (x >= 0) && (x < 321) ){ + m_AX = x; + x = x ? x - 1 : 0; + d = GetPictureLevelDiff(ip); + d += 128; + d = Limit256(d); + m_Y36[x] = short(d); + } + } + else if( ps < SSTVSET.m_CG ){ // TCS + ps -= SSTVSET.m_SG; + if( ps >= 0 ){ + d = GetPixelLevel(ip); + if( (d >= 64) || (d < -64) ){ + m_DSEL = (d >= 0) ? 1 : 0; // RY=1500 m_D36[0], BY=2300 m_D36[1] + } + else { + m_DSEL = m_DSEL ? 0 : 1; + } + } + } + else if( ps < SSTVSET.m_CB ){ // 色差 + ps -= SSTVSET.m_SB; + x = ps * pBitmapRX->Width / SSTVSET.m_KS2S; + if( (m_AX != x) && (x >= 0) && (x < 320) && (y < 240) ){ + m_AX = x; + d = GetPixelLevel(ip); + m_D36[m_DSEL][x] = short(d); + YCtoRGB(R, G, B, m_Y36[x], m_D36[0][x], m_D36[1][x]); + if( gp != NULL ){ + wp = gp + (x * 3); + *wp++ = BYTE(B); // B + *wp++ = BYTE(G); // G + *wp = BYTE(R); // R + } + } + } + break; + case smR24: + case smR72: + case smMR73: + case smMR90: + case smMR115: + case smMR140: + case smMR175: + case smML180: + case smML240: + case smML280: + case smML320: + if( ps < SSTVSET.m_KS ){ // 輝度 + x = ps * pBitmapRX->Width / SSTVSET.m_KSS; + if( (m_AX != x) && (x >= 0) && (x <= pBitmapRX->Width) ){ + m_AX = x; + x = x ? x - 1 : 0; + d = GetPictureLevelDiff(ip); + d += 128; + d = Limit256(d); + m_Y36[x] = short(d); + } + } + else if( ps < SSTVSET.m_CG ){ // R-Y + ps -= SSTVSET.m_SG; + x = ps * pBitmapRX->Width / SSTVSET.m_KS2S; + if( (m_AX != x) && (x >= 0) && (x < pBitmapRX->Width) ){ + m_AX = x; + d = GetPixelLevel(ip); + m_D36[1][x] = short(d); + } + } + else if( ps < SSTVSET.m_CB ){ // B-Y + ps -= SSTVSET.m_SB; + x = ps * pBitmapRX->Width / SSTVSET.m_KS2S; + if( (m_AX != x) && (x >= 0) && (x < pBitmapRX->Width) && (y < SSTVSET.m_L) ){ + m_AX = x; + d = GetPixelLevel(ip); + YCtoRGB(R, G, B, m_Y36[x], m_D36[1][x], d); + if( gp != NULL ){ + wp = gp + (x * 3); + *wp++ = BYTE(B); // B + *wp++ = BYTE(G); // G + *wp = BYTE(R); // R + if( SSTVSET.m_Mode == smR24 ){ + wp = gp2 + (x * 3); + *wp++ = BYTE(B); // B + *wp++ = BYTE(G); // G + *wp = BYTE(R); // R + } + } + } + } + break; + case smPD50: + case smPD90: + case smPD120: + case smPD180: + case smPD240: + case smPD290: + case smMP73: + case smMP115: + case smMP140: + case smMP175: + case smMN73: + case smMN110: + case smMN140: + if( ps < SSTVSET.m_KS ){ // 輝度 + x = ps * pBitmapRX->Width / SSTVSET.m_KSS; + if( (m_AX != x) && (x >= 0) && (x < (pBitmapRX->Width + 1)) ){ + m_AX = x; + x = x ? x - 1 : 0; + d = GetPictureLevelDiff(ip); + d += 128; + d = Limit256(d); + m_Y36[x] = short(d); + } + } + else if( ps < SSTVSET.m_CG ){ // R-Y + ps -= SSTVSET.m_SG; + x = ps * pBitmapRX->Width / SSTVSET.m_KSS; + if( (m_AX != x) && (x >= 0) && (x < pBitmapRX->Width) ){ + m_AX = x; + d = GetPixelLevel(ip); + m_D36[1][x] = short(d); + } + } + else if( ps < SSTVSET.m_CB ){ // B-Y + ps -= SSTVSET.m_SB; + x = ps * pBitmapRX->Width / SSTVSET.m_KSS; + if( (m_AX != x) && (x >= 0) && (x < pBitmapRX->Width) ){ + m_AX = x; + d = GetPixelLevel(ip); + m_D36[0][x] = short(d); + } + } + else if( ps < (SSTVSET.m_CB + SSTVSET.m_KS) ){ // Y(even) + ps -= SSTVSET.m_CB; + x = ps * pBitmapRX->Width / SSTVSET.m_KSS; + if( (m_AX != x) && (x >= 0) && (x < (pBitmapRX->Width + 1)) && (y < SSTVSET.m_L) ){ + m_AX = x; + x = x ? x - 1 : 0; + if( gp != NULL ){ + YCtoRGB(R, G, B, m_Y36[x], m_D36[1][x], m_D36[0][x]); + wp = gp + (x * 3); + *wp++ = BYTE(B); // B + *wp++ = BYTE(G); // G + *wp = BYTE(R); // R + d = GetPictureLevelDiff(ip); + d += 128; + YCtoRGB(R, G, B, d, m_D36[1][x], m_D36[0][x]); + wp = gp2 + (x * 3); + *wp++ = BYTE(B); // B + *wp++ = BYTE(G); // G + *wp = BYTE(R); // R + } + } + } + break; + case smRM8: + case smRM12: + if( ps < SSTVSET.m_KS ){ // 輝度 + x = ps * pBitmapRX->Width / SSTVSET.m_KSS; + if( (m_AX != x) && (x >= 0) && (x < (pBitmapRX->Width + 1)) && (y < SSTVSET.m_L) ){ + m_AX = x; + x = x ? x - 1 : 0; + d = GetPictureLevelDiff(ip); + d *= (256.0 / (256.0 - 32.0)); + d += 128; + d = Limit256(d); + if( gp != NULL ){ + wp = gp + (x * 3); + *wp++ = BYTE(d); // B + *wp++ = BYTE(d); // G + *wp = BYTE(d); // R + wp = gp2 + (x * 3); + *wp++ = BYTE(d); // B + *wp++ = BYTE(d); // G + *wp = BYTE(d); // R + } + } + } + break; + default: + if( ps < SSTVSET.m_KS ){ // R or G(MRT) + x = ps * pBitmapRX->Width / SSTVSET.m_KSS; + if( (x != m_AX) && (x >= 0) && (x < (pBitmapRX->Width + 1)) ){ + m_AX = x; + x = x ? x - 1 : 0; + d = GetPictureLevelDiff(ip); + d += 128; + d = Limit256(d); + m_D36[0][x] = short(d); + } + } + else if( ps < SSTVSET.m_CG ){ // G or B(MRT) + ps -= SSTVSET.m_SG; + x = ps * pBitmapRX->Width / SSTVSET.m_KSS; + if( (x != m_AX) && (x >= 0) && (x < (pBitmapRX->Width + 1)) ){ + m_AX = x; + x = x ? x - 1 : 0; + d = GetPictureLevelDiff(ip); + d += 128; + d = Limit256(d); + m_D36[1][x] = short(d); + } + } + else if( ps < SSTVSET.m_CB ){ // B or R(MRT) + ps -= SSTVSET.m_SB; + x = ps * pBitmapRX->Width / SSTVSET.m_KSS; + if( (x != m_AX) && (x >= 0) && (x < (pBitmapRX->Width + 1)) ){ + m_AX = x; + x = x ? x - 1 : 0; + d = GetPictureLevelDiff(ip); + if( m_AX ){ + d += 128; + d = Limit256(d); + if( (SSTVSET.m_Mode == smMRT1)||(SSTVSET.m_Mode == smMRT2) ){ + if( gp != NULL ){ + wp = gp + (x * 3); + *wp++ = BYTE(m_D36[1][x]); // B + *wp++ = BYTE(m_D36[0][x]); // G + *wp = BYTE(d); // R + } + } + else { + if( gp != NULL ){ + wp = gp + (x * 3); + *wp++ = BYTE(d); // B + *wp++ = BYTE(m_D36[1][x]); // G + *wp = BYTE(m_D36[0][x]); // R + } + } + } + } + } + break; + } + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::WriteHistory(int sw) +{ + if( !pDem->m_Sync ){ + PBoxRXPaint(NULL); + DrawSync(); + } + if( pComm != NULL ) pComm->SetScan(0); + int f = sw; + if( m_AY > (SSTVSET.m_L * 65/100) ){ + f = 1; + TrackTxMode(0); + } + if( f && KEA->Checked ){ + CopyBitmap(pBitmapRX); + } + if( CBASave->Checked && f ){ + SBWHistClick(NULL); // Write history + } + else { + SBWHist->Enabled = TRUE; + } + if( sys.m_Repeater ){ + SetBeaconTick(); + if( f ) MakeReplay(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::TrackTxMode(int sw) +{ + if( (!sys.m_FixedTxMode) && (!SBTX->Down) && (SSTVSET.m_Mode != SSTVSET.m_TxMode) ){ + if( (m_RXW == pBitmapTX->Width) || sw ){ + ChangeTxMode(SSTVSET.m_Mode); + UpdateModeBtn(); + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::DrawSSTV(void) +{ + CSSTVDEM *dp = pDem; + if( dp->m_Sync && (dp->m_wPage != dp->m_rPage) ){ + while( dp->m_Sync && (dp->m_wPage != dp->m_rPage) ){ + if( dp->m_wBgn ){ + if( dp->m_wBgn != 1 ){ + m_SyncRPos = m_SyncPos = -1; + m_SyncAccuracyN = 0; + SBTO->Enabled = FALSE; + dp->m_fskcall[0] = 0; + m_DSEL = 0; + m_AX = -1; + m_AY = -5; + if( dp->m_ReqSave ){ + dp->m_ReqSave = 0; + WriteHistory(1); + } + SSTVSET.GetPictureSize(m_RXW, m_RXH, m_RXPH, SSTVSET.m_Mode); + if( KRSW->Checked ){ + if( pRxView != NULL ){ + if( pRxView->Handle != ::GetForegroundWindow() ){ + ::SetForegroundWindow(pRxView->Handle); + } + } + else if( m_MainPage != pgRX ){ + AdjustPage(pgRX); + } + } + if( pBitmapRX->Width != m_RXW ){ + pBitmapRX->Width = m_RXW; + pBitmapRX->Height = m_RXH; + PBoxRX->Invalidate(); + } + UpdateModeBtn(); + dp->m_LoopBack = SBTX->Down ? sys.m_echo : 0; + ::GetUTC(&m_StartTime); + dp->m_SyncAVT = 0; + WaveStg.WInit(); + RxHist.ClearAddFlag(); + dp->m_wStgLine = 0; + DispSyncStat(); + SBWHist->Enabled = FALSE; + KRH->Enabled = FALSE; + int rf = 0; + if( sys.m_Repeater && dp->m_Repeater ){ + dp->m_repRX++; + SetBeaconTick(); + if( dp->m_repmode == 5 ){ + dp->m_repmode++; + dp->m_repRLY++; + rf = 1; + } + else if( dp->m_repmode <= 2 ){ + dp->m_repmode = 0; + } + } + if( pRxView != NULL ){ + pRxView->UpdateTitle(SSTVSET.m_Mode, rf); + } + if( pComm != NULL ) pComm->SetScan(pDem->m_Sync); + } + dp->m_wBgn = 1; + SyncSSTV(); + if( dp->m_wBgn ) return; + m_HistM = SSTVSET.m_Mode; + if( KRD->Checked ){ + ClearDraw(pBitmapRX, PBoxRX, sys.m_ColorRXB); + } + ClearDraw(pBitmapD12, PBoxD12, clWhite); + InitAutoStop(); + m_AutoSyncCount = m_AutoSyncDis = 0; + } + short *ip = &dp->m_Buf[dp->m_rPage * dp->m_BWidth]; + short *sp = &dp->m_B12[dp->m_rPage * dp->m_BWidth]; + if( dp->m_StgBuf ){ + if( ((dp->m_wStgLine + 1) * SSTVSET.m_WD) < dp->m_RxBufAllocSize ){ + memcpy(&dp->m_StgBuf[dp->m_wStgLine * SSTVSET.m_WD], ip, SSTVSET.m_WD*sizeof(short)); + memcpy(&dp->m_StgB12[dp->m_wStgLine * SSTVSET.m_WD], sp, SSTVSET.m_WD*sizeof(short)); + dp->m_wStgLine++; + if( dp->m_wStgLine == 16 ) UpdateSBTO(); + } + } + else if( WaveStg.IsOpen() ){ + WaveStg.Write(ip, SSTVSET.m_WD*sizeof(short)); + WaveStg.Write(sp, SSTVSET.m_WD*sizeof(short)); + dp->m_wStgLine++; + if( dp->m_wStgLine == 16 ) UpdateSBTO(); + } + DrawSSTV(ip, sp); + dp->m_rBase += SSTVSET.m_WD; + if( m_AY > SSTVSET.m_L ){ + if( dp->m_Sync ){ + int lost = dp->m_Lost; + dp->Stop(); + if( dp->m_LoopBack != 1 ){ + WriteHistory(1); + } + else { + SBWHist->Enabled = TRUE; + } + TrackTxMode(0); + UpdateModeBtn(); + if( lost ) InfoRxLost(); + UpdateUI(); + } + break; + } + dp->m_rPage++; + if( dp->m_rPage >= SSTVDEMBUFMAX ){ + dp->m_rPage = 0; + } + } + if( !pSound->IsBusy() ){ + PBoxRXPaint(NULL); + DrawSync(); + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::InfoRxLost(void) +{ + InfoMB( MsgEng ? + "MMSSTV lost some sound during the receiving by the CPU overload.\r\n\r\n" + "Do increase FIFO on sound in the Misc page of Setup MMSSTV." : + "受信中にCPU過負荷によりサウンドを一部欠落しました.\r\n\r\n" + "設定画面の「その他」ページのサウンドカードのFIFOを増やして下さい" + ); +} +void __fastcall TMmsstv::InfoTxLost(void) +{ + InfoMB( MsgEng ? + "MMSSTV lost some sound during the transmission by the CPU overload.\r\n\r\n" + "Do increase FIFO on sound in the Misc page of Setup MMSSTV." : + "送信中にCPU過負荷によりサウンドを一部欠落しました.\r\n\r\n" + "設定画面の「その他」ページのサウンドカードのFIFOを増やして下さい" + ); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::PBoxFFTPaint(TObject *Sender) +{ + PBoxFFT->Canvas->Draw(0, 0, pBitmapFFT); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::PBoxWaterPaint(TObject *Sender) +{ + if( KVW->Checked ) PBoxWater->Canvas->Draw(0, 0, pBitmapWater); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::PBoxRXPaint(TObject *Sender) +{ + if( m_MainPage != pgRX ) return; + + DrawBitmap(PBoxRX, pBitmapRX); + if( sys.m_ShowSizeRX ){ + ShowSize(PBoxRX, m_RXW, m_RXPH, 12, clGreen); + } +#if 0 + if( sys.m_Repeater ){ + CSSTVDEM *dp = pDem; + if( dp->m_Repeater && (dp->m_repmode == 6) ){ + PBoxRX->Canvas->Brush->Color = clBlue; + PBoxRX->Canvas->Font->Color = clWhite; + PBoxRX->Canvas->Font->Height = -12; + LPCSTR dp = "Repeater"; + int fw = PBoxRX->Canvas->TextWidth(dp); + int fh = PBoxRX->Canvas->TextHeight(dp); + PBoxRX->Canvas->TextOut(PBoxRX->Width - fw, PBoxRX->Height - fh, dp); + } + } +#endif +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KFRecTimClick(TObject *Sender) +{ + if( pSound == NULL ) return; + SYSTEMTIME now; + GetLocal(&now); + + char bf[256]; + sprintf(bf, "%s%02u%02u%02u%02u.mmv", RecDir, now.wMonth, now.wDay, now.wHour, now.wMinute); + pSound->WaveFile.Rec(bf); + if( pSound->WaveFile.m_mode == 2 ){ + KFRecTim->Checked = TRUE; + RecentAdd(pSound->WaveFile.m_FileName.c_str(), TRUE); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KFRecClick(TObject *Sender) +{ + if( pSound == NULL ) return; + if( MsgEng ){ + SaveDialog->Title = "Record MMSSTV Sound file"; + SaveDialog->Filter = "MMSSTV Sound Files(*.mmv)|*.mmv|"; + } + else { + SaveDialog->Title = "MMSSTVサウンドファイルの作成"; + SaveDialog->Filter = "MMSSTVサウンドファイル(*.mmv)|*.mmv|"; + } + SaveDialog->FileName = "Recv.mmv"; + SaveDialog->DefaultExt = "mmv"; + SaveDialog->InitialDir = RecDir; + SetDisPaint(); + NormalWindow(this); + if( SaveDialog->Execute() == TRUE ){ + pSound->WaveFile.Rec(AnsiString(SaveDialog->FileName).c_str()); //ja7ude 0428 + if( pSound->WaveFile.m_mode == 2 ){ + KFRec->Checked = TRUE; + RecentAdd(pSound->WaveFile.m_FileName.c_str(), TRUE); + } + SetDirName(RecDir, AnsiString(SaveDialog->FileName).c_str()); //ja7ude 0428 + } + TopWindow(this); + ResDisPaint(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KFPlayClick(TObject *Sender) +{ + if( pSound == NULL ) return; + OpenDialog->Options >> ofCreatePrompt; + OpenDialog->Options << ofFileMustExist; + if( MsgEng ){ + OpenDialog->Title = "Play MMSSTV Sound file"; + OpenDialog->Filter = "MMSSTV Sound Files(*.mmv)|*.mmv|"; + } + else { + OpenDialog->Title = "MMSSTVサウンドファイルの再生"; + OpenDialog->Filter = "MMSSTVサウンドファイル(*.mmv)|*.mmv|"; + } + OpenDialog->FileName = ""; + OpenDialog->DefaultExt = "mmv"; + OpenDialog->InitialDir = RecDir; + SetDisPaint(); + NormalWindow(this); + if( OpenDialogExecute(FALSE) == TRUE ){ + pSound->WaveFile.Play(AnsiString(OpenDialog->FileName).c_str()); //ja7ude 0428 + SetDirName(RecDir, AnsiString(OpenDialog->FileName).c_str()); //ja7ude 0428 + } + ResDisPaint(); + if( pSound->WaveFile.m_mode == 1 ){ + KFPlayPosClick(NULL); + RecentAdd(pSound->WaveFile.m_FileName.c_str(), TRUE); + } + TopWindow(this); +} +//--------------------------------------------------------------------------- +// Recent Menu Click +void __fastcall TMmsstv::OnRecentClick(TObject *Sender) +{ + if( pSound == NULL ) return; + LPCSTR pName = RecentMenu.FindItemText((TMenuItem *)Sender); + if( pName != NULL ){ + char bf[256]; + strcpy(bf, pName); + RecentAdd(bf, pSound->WaveFile.Play(bf)); + if( pSound->WaveFile.m_mode == 1 ){ + KFPlayPosClick(NULL); + } + } +} +//--------------------------------------------------------------------------- +// Recent Menu Click +void __fastcall TMmsstv::RecentAdd(LPCSTR pNew, int f) +{ + if( RecentMenu.IsAdd(pNew) ){ + RecentMenu.Delete(); + if( f != FALSE ){ + RecentMenu.Add(pNew); + } + else { + RecentMenu.Delete(pNew); + } + RecentMenu.Insert(NULL, OnRecentClick); + } +} +//--------------------------------------------------------------------------- +// Recent Menu Update +void __fastcall TMmsstv::UpdateRecentMenu(void) +{ + RecentMenu.Delete(); + RecentMenu.Init(KExit, KFile, RECMENUMAX); + RecentMenu.ExtFilter("MMV"); + RecentMenu.Insert(NULL, OnRecentClick); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KFPlayPosClick(TObject *Sender) +{ + if( pSound == NULL ) return; + TPlayDlgBox *pBox = new TPlayDlgBox(this); + + pBox->Execute(&pSound->WaveFile); + delete pBox; + TopWindow(this); +} +//--------------------------------------------------------------------------- + +void __fastcall TMmsstv::KFRecRewClick(TObject *Sender) +{ + if( pSound == NULL ) return; + pSound->WaveFile.Rewind(); +} +//--------------------------------------------------------------------------- + +void __fastcall TMmsstv::KFRecStopClick(TObject *Sender) +{ + if( pSound == NULL ) return; + pSound->WaveFile.FileClose(); +} + +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::CopyStgBuf(void) +{ + CSSTVDEM *dp = pDem; + + while( dp->m_rPage != dp->m_wPage ){ + short *ip = &dp->m_Buf[dp->m_rPage * dp->m_BWidth]; + short *sp = &dp->m_B12[dp->m_rPage * dp->m_BWidth]; + if( dp->m_StgBuf != NULL ){ + if( ((dp->m_wStgLine + 1) * SSTVSET.m_WD) < dp->m_RxBufAllocSize ){ + memcpy(&dp->m_StgBuf[dp->m_wStgLine * SSTVSET.m_WD], ip, SSTVSET.m_WD*sizeof(short)); + memcpy(&dp->m_StgB12[dp->m_wStgLine * SSTVSET.m_WD], sp, SSTVSET.m_WD*sizeof(short)); + dp->m_wStgLine++; + } + else { + break; + } + } + else if( WaveStg.IsOpen() ){ + WaveStg.Write(ip, SSTVSET.m_WD*sizeof(short)); + WaveStg.Write(sp, SSTVSET.m_WD*sizeof(short)); + dp->m_wStgLine++; + } + if( dp->m_wStgLine == 16 ) UpdateSBTO(); + dp->m_rPage++; + if( dp->m_rPage >= SSTVDEMBUFMAX ){ + dp->m_rPage = 0; + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::CorrectSlant(void) +{ + CSSTVDEM *dp = pDem; + if( ((dp->m_StgBuf != NULL) || WaveStg.IsOpen()) && (dp->m_wStgLine >= 16) && (SSTVSET.m_Mode != smAVT) ){ + if( (dp->m_StgBuf != NULL) && (((dp->m_wStgLine + 1) * SSTVSET.m_WD) >= dp->m_RxBufAllocSize) ){ + return; + } + CWaitCursor w; + double StartSamp = SSTVSET.m_SampFreq; + int LW = SSTVSET.m_TW * 0.1; // 10%の揺れを許容 + int z; + for( z = 0; z < 5; z++ ){ + // 基準位置を探す + WaveStg.RInit(); + int i, j; + int wd = int(SSTVSET.m_TW); + int *bp = new int[wd]; + memset(bp, 0, sizeof(int) * wd); + short *sp; + int n = 0; + for( i = 0; i < dp->m_wStgLine && (i < 32); i++ ){ + if( dp->m_StgBuf != NULL ){ + sp = &dp->m_StgB12[i * SSTVSET.m_WD]; + } + else { + WaveStg.Read(WaveStg.pData, SSTVSET.m_WD*sizeof(short)); + WaveStg.Read(WaveStg.pSync, SSTVSET.m_WD*sizeof(short)); + sp = WaveStg.pSync; + } + for( j = 0; j < SSTVSET.m_WD; j++, sp++ ){ + bp[n] += *sp; + n++; + if( n >= wd ) n = 0; + } + if( dp->m_Sync ) ::Sleep(pSound->IsBusy() ? 100 : 1); + if( SBTX->Down && IsSR() ) SendSSTV(); + } + double bpos = 0; + int max = 0; + for( i = 0; i < wd; i++ ){ + if( max < bp[i] ){ + max = bp[i]; + bpos = i; + } + } + delete bp; + + // 傾き調整 + WaveStg.RInit(); + int base = 0; + int yy; + int y = 0; + max = 0; + int min = 16384; + n = 0; + int m = 0; + double xx; + double ps = 0; + double T, L, TT, TL; + T = L = TT = TL = 0; + for( i = 0; i < dp->m_wStgLine; i++ ){ + if( dp->m_StgBuf != NULL ){ + sp = &dp->m_StgB12[i * SSTVSET.m_WD]; + } + else { + WaveStg.Read(WaveStg.pData, SSTVSET.m_WD*sizeof(short)); + WaveStg.Read(WaveStg.pSync, SSTVSET.m_WD*sizeof(short)); + sp = WaveStg.pSync; + } + for( j = 0; j < SSTVSET.m_WD; j++, sp++, base++ ){ + yy = base / SSTVSET.m_TW; + xx = fmod(base, SSTVSET.m_TW); + if( yy != y ){ + if( bpos < 0 ){ + if( ps >= (SSTVSET.m_TW/4) ){ // 左方向への周りこみ + ps -= SSTVSET.m_TW; + } + else if( ps >= (SSTVSET.m_TW/8) ){ + goto _nx; + } + } + else if( bpos >= SSTVSET.m_TW ){ // 右方向への周りこみ + if( ps < (SSTVSET.m_TW*3/4) ){ + ps += SSTVSET.m_TW; + } + else if( ps < (SSTVSET.m_TW*7/8) ){ + goto _nx; + } + } + else if( bpos >= (SSTVSET.m_TW*3/4) ){ // 右側 + if( (ps < SSTVSET.m_TW/4) ){ + ps += SSTVSET.m_TW; + } + } + else if( bpos <= (SSTVSET.m_TW/4) ){ // 左側 + if( ps >= (SSTVSET.m_TW*3/4) ){ + ps -= SSTVSET.m_TW; + } + } + if( (y >= 0) && ((max - min) >= 4800) && (ABS(ps - bpos) <= LW) ){ + bpos = ps; + if( n >= 2 ){ + T += y; + L += ps; + TT += y * y; + TL += y * ps; + m++; + } + n++; + if( n >= dp->m_wStgLine ) goto _nx; + } + y = yy; + max = 0; + min = 16384; + ps = 0; + } + if( max < *sp ){ + max = *sp; + ps = xx; + } + if( min > *sp ){ + min = *sp; + } + } + if( dp->m_Sync ) ::Sleep(pSound->IsBusy() ? 100 : 1); + if( SBTX->Down && IsSR() ) SendSSTV(); + } +_nx:; + double fq = SSTVSET.m_SampFreq; + if( m >= 6 ){ + double k0 = (m * TL - L * T) / (m * TT - T*T); + fq = SSTVSET.m_SampFreq + (k0 * SSTVSET.m_SampFreq / SSTVSET.m_TW); +#if 0 + char bf[64]; + sprintf(bf, "%lf, %lf", fq, k0 ); + EditNote->Text = bf; +#endif + fq = NormalSampFreq(fq, 100); + } + if( fabs(fq-SSTVSET.m_SampFreq) < (0.1/11025.0 * SSTVSET.m_SampFreq) ){ + SSTVSET.m_SampFreq = fq; + SSTVSET.SetSampFreq(); + break; + } + SSTVSET.m_SampFreq = StartSamp; + SSTVSET.SetSampFreq(); + MultProc(); + SSTVSET.m_SampFreq = fq; + SSTVSET.SetSampFreq(); + LW *= 0.5; + } + if( (SSTVSET.m_SampFreq != StartSamp) && + ( (dp->m_StgBuf == NULL)||(((dp->m_wStgLine + 32) * SSTVSET.m_WD) < dp->m_RxBufAllocSize) ) + ){ + RedrawSampFreq(FALSE); + } + else if( SSTVSET.m_SampFreq != StartSamp ){ + SSTVSET.m_SampFreq = StartSamp; + SSTVSET.SetSampFreq(); + } + DrawSlantInfo(); + } +} +//--------------------------------------------------------------------------- +int __fastcall TMmsstv::AdjustSyncPos(int n) +{ + n -= SSTVSET.m_OFP; + n = -n; + switch(SSTVSET.m_Mode){ + case smSCT1: + case smSCT2: + case smSCTDX: + if( n < 0 ) n += int(SSTVSET.m_TW); + break; + case smMRT1: // 原因不明のタイミングズレを補正 + case smSC2_180: + case smSC2_120: + case smP3: + case smP5: + case smP7: + case smMC110: + case smMC140: + case smMC180: + n += (0.45/1000.0) * SSTVSET.m_SampFreq; + break; + case smMRT2: + case smSC2_60: + if( pDem->m_wStgLine < 20 ){ + n += (0.30/1000.0) * SSTVSET.m_SampFreq; + } + else { + n += (0.40/1000.0) * SSTVSET.m_SampFreq; + } + break; + case smR36: + case smR72: + n += (0.16/1000.0) * SSTVSET.m_SampFreq; + break; + case smMP73: + case smMP115: + case smMP140: + case smMP175: + case smMN73: + case smMN110: + case smMN140: + case smMR73: + case smMR90: + case smMR115: + case smMR140: + case smMR175: + case smML180: + case smML240: + case smML280: + case smML320: + n += (0.2/1000.0) * SSTVSET.m_SampFreq; + break; + case smR24: + case smRM8: + case smRM12: + n += (0.5/1000.0) * SSTVSET.m_SampFreq; + break; + default: + break; + } + return n; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::ReSyncSSTV(void) +{ + CSSTVDEM *dp = pDem; + SSTVSET.SetSampFreq(); + if( (dp->m_StgBuf != NULL) || WaveStg.IsOpen() ){ +// int ZS = SSTVSET.m_OFS; + WaveStg.RInit(); + int i; + int wd = int(SSTVSET.m_TW); + int *bp = new int[wd+2]; + memset(bp, 0, sizeof(int) * (wd+2)); + short *sp; + int n = 0; + for( i = 0; i < dp->m_wStgLine && (i < 32); i++ ){ + if( dp->m_StgBuf != NULL ){ + sp = &dp->m_StgB12[i * SSTVSET.m_WD]; + } + else { + WaveStg.Read(WaveStg.pData, SSTVSET.m_WD*sizeof(short)); + WaveStg.Read(WaveStg.pSync, SSTVSET.m_WD*sizeof(short)); + sp = WaveStg.pSync; + } + for( int j = 0; j < SSTVSET.m_WD; j++, sp++ ){ + int x = fmod(n, SSTVSET.m_TW); + bp[x] += *sp; + n++; + } + } + n = 0; + int max = 0; + for( i = 0; i < wd; i++ ){ + if( max < bp[i] ){ + max = bp[i]; + n = i; + } + } + n = AdjustSyncPos(n); + if( dp->m_Type == 2 ) n -= dp->m_hill.m_htap/4; + SSTVSET.m_IOFS = SSTVSET.m_OFS = dp->m_rBase = n; + delete bp; +#if 0 + char bf[64]; + sprintf(bf, "%d, %d", ZS, SSTVSET.m_OFS); + EditNote->Text = bf; +#endif + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::DrawSlantInfo(void) +{ + double df = SSTVSET.m_SampFreq - sys.m_SampFreq; + double m = (SSTVSET.m_SampFreq - sys.m_SampFreq) * 1000000.0 / sys.m_SampFreq; + char bf[64]; + sprintf(bf, "%+.2lfHz (%+.0lfppm)", df, m); + pBitmapD12->Canvas->Font->Height = -16; + int fw = pBitmapD12->Canvas->TextWidth(bf) + 1; + int fh = pBitmapD12->Canvas->TextHeight(bf) + 4; + int xw = 200; + TRect rc; + int xl = pBitmapD12->Width - xw; + int xr = pBitmapD12->Width - 1; + int yt = 1; + int yb = fh + 1; + if( (m_AY >= 0) && (m_AY < yb) ) return; + pBitmapD12->Canvas->Pen->Color = clBlack; + pBitmapD12->Canvas->RoundRect(xl, yt, xr, yb, 10, 5); + pBitmapD12->Canvas->TextOut(xl + (xw - fw)/2, yt + 2, bf); + if( m_MainPage == pgSync) PBoxD12->Invalidate(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::DrawShiftInfo(void) +{ + int td = SSTVSET.m_IOFS - SSTVSET.m_OFS; + char bf[32]; + sprintf(bf, "%.2lfms", td * 1000.0 / SampFreq); + pBitmapD12->Canvas->Font->Height = -16; + int fw = pBitmapD12->Canvas->TextWidth(bf) + 1; + int fh = pBitmapD12->Canvas->TextHeight(bf) + 4; + int xw = fw + 16; + int xl = pBitmapD12->Width - xw; + int xr = pBitmapD12->Width - 1; + int yt = 1; + int yb = fh + 1; + if( (m_AY >= 0) && (m_AY < yb) ) return; + pBitmapD12->Canvas->Pen->Color = clBlack; + pBitmapD12->Canvas->RoundRect(xl, yt, xr, yb, 10, 5); + pBitmapD12->Canvas->TextOut(xl + (xw - fw)/2, yt + 2, bf); + if( m_MainPage == pgSync) PBoxD12->Invalidate(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::RedrawSampFreq(int sw) +{ + CWaitCursor w; + + UpdateSampFreq(); + SSTVSET.SetSampFreq(); + DispSyncStat(); + DrawSSTV(); + if( !pDem->m_Sync ) PBoxRXPaint(NULL); + if( sw ) DrawSlantInfo(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::UpdateSampFreq(void) +{ + CSSTVDEM *dp = pDem; + SSTVSET.SetSampFreq(); + if( (dp->m_StgBuf != NULL) || WaveStg.IsOpen() ){ + ReSyncSSTV(); + WaveStg.RInit(); + InitAutoStop(); + m_ASDis = 1; + dp->m_rBase = SSTVSET.m_OFS; + for( int i = 0; i < dp->m_wStgLine; i++ ){ + if( dp->m_StgBuf != NULL ){ + DrawSSTV(&dp->m_StgBuf[i * SSTVSET.m_WD], &dp->m_StgB12[i * SSTVSET.m_WD]); + } + else { + WaveStg.Read(WaveStg.pData, SSTVSET.m_WD*sizeof(short)); + WaveStg.Read(WaveStg.pSync, SSTVSET.m_WD*sizeof(short)); + DrawSSTV(WaveStg.pData, WaveStg.pSync); + } + dp->m_rBase += SSTVSET.m_WD; + if( dp->m_Sync ){ + ::Sleep(pSound->IsBusy() ? 100 : 1); + CopyStgBuf(); + } + if( SBTX->Down && IsSR() ) SendSSTV(); + } + if( (!dp->m_Sync) && RxHist.IsAddFlag() ){ + RxHist.Update(pBitmapRX); + ::CopyBitmap(pBitmapHist, pBitmapRX); + TrigHistF(); + UpdatePic(); + } + DrawSync(); + pSound->fftIN.TrigFFT(); + m_ASDis = 0; + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SBAdjMouseDown(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( Button == mbRight ){ + RedrawAdjustSync(); + } +} +//--------------------------------------------------------------------------- +#define MAKEPOSLOG FALSE +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::RedrawAdjustSync(void) +{ + CWaitCursor wc; + + CSSTVDEM *dp = pDem; + if( (dp->m_StgBuf != NULL) || WaveStg.IsOpen() ){ + int pos, w, n, j; + SSTVSET.GetBitmapSize(w, n, SSTVSET.m_Mode); +#if MAKEPOSLOG + FILE *fp = fopen("\\mmsstv\\zzz.txt", "wt"); + fprintf(fp, "PixelDots=%.1lf\n", SSTVSET.m_KS / double(w) + 0.5); +#endif + double k = 0.5; + switch(SSTVSET.m_Mode){ + case smPD50: + case smPD120: + k = 3.0; + break; + case smPD160: + k = 2.0; + break; + case smRM8: + k = 1.5; + break; + case smRM12: + case smR24: + case smPD90: + case smSCT2: + case smMRT2: + k = 1.0; + break; + default: + break; + } + w = SSTVSET.m_KS * k / double(w) + 0.5; + short *pData, *pSync, *sp; + short max; + ReSyncSSTV(); + InitAutoStop(); + m_ASDis = 1; + WaveStg.RInit(); + dp->m_rBase = SSTVSET.m_OFS; + for( int i = 0; i < dp->m_wStgLine; i++ ){ + if( dp->m_StgBuf != NULL ){ + pData = &dp->m_StgBuf[i * SSTVSET.m_WD]; + pSync = &dp->m_StgB12[i * SSTVSET.m_WD]; + } + else { + WaveStg.Read(WaveStg.pData, SSTVSET.m_WD*sizeof(short)); + WaveStg.Read(WaveStg.pSync, SSTVSET.m_WD*sizeof(short)); + pData = WaveStg.pData; + pSync = WaveStg.pSync; + } + pos = 0; + max = 0; + n = dp->m_rBase; + if( n >= 0 ){ + sp = pSync; + for( j = 0; j < SSTVSET.m_WD; j++, n++, sp++ ){ + if( *sp > max ){ + max = *sp; + pos = fmod(n, SSTVSET.m_TW); + } + } + pos = AdjustSyncPos(pos); + if( pos >= (int(SSTVSET.m_TW)/2) ) pos -= int(SSTVSET.m_TW); +#if MAKEPOSLOG + fprintf(fp, "%d\n", pos); +#endif + } + DrawSSTV(pData, pSync); + dp->m_rBase += SSTVSET.m_WD; + if( (m_AY >= 2) && (ABS(pos) > w) ) dp->m_rBase += pos; + if( dp->m_Sync ){ + ::Sleep(pSound->IsBusy() ? 100 : 1); + CopyStgBuf(); + } + } +#if MAKEPOSLOG + fclose(fp); +#endif + m_ASDis = 0; + DrawSync(); + if( (!dp->m_Sync) && RxHist.IsAddFlag() ){ + RxHist.Update(pBitmapRX); + ::CopyBitmap(pBitmapHist, pBitmapRX); + TrigHistF(); + UpdatePic(); + } + DrawSSTV(); + if( SSTVSET.m_SampFreq != sys.m_SampFreq ) DrawSlantInfo(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::RedrawSSTV(void) +{ + CWaitCursor w; + + CSSTVDEM *dp = pDem; + if( (dp->m_StgBuf != NULL) || WaveStg.IsOpen() ){ + InitAutoStop(); + m_ASDis = 1; + WaveStg.RInit(); + dp->m_rBase = SSTVSET.m_OFS; + for( int i = 0; i < dp->m_wStgLine; i++ ){ + if( dp->m_StgBuf != NULL ){ + DrawSSTV(&dp->m_StgBuf[i * SSTVSET.m_WD], &dp->m_StgB12[i * SSTVSET.m_WD]); + } + else { + WaveStg.Read(WaveStg.pData, SSTVSET.m_WD*sizeof(short)); + WaveStg.Read(WaveStg.pSync, SSTVSET.m_WD*sizeof(short)); + DrawSSTV(WaveStg.pData, WaveStg.pSync); + } + dp->m_rBase += SSTVSET.m_WD; + if( dp->m_Sync ){ + ::Sleep(pSound->IsBusy() ? 100 : 1); + CopyStgBuf(); + } + } + m_ASDis = 0; + DrawSync(); + if( (!dp->m_Sync) && RxHist.IsAddFlag() ){ + RxHist.Update(pBitmapRX); + ::CopyBitmap(pBitmapHist, pBitmapRX); + TrigHistF(); + UpdatePic(); + } + DrawSSTV(); + if( SSTVSET.m_OFS != SSTVSET.m_IOFS ) DrawShiftInfo(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::ShiftSSTV(TObject *Sender, int step) +{ + if( !step ) step++; + + if( Sender == SBPL ){ + SSTVSET.m_OFS -= step; + } + else { + SSTVSET.m_OFS += step; + } + int e = 0; + switch(SSTVSET.m_Mode){ + case smSCT1: + case smSCT2: + case smSCTDX: + e = SSTVSET.m_WD; + break; + default: + break; + } + while( (SSTVSET.m_OFS + SSTVSET.m_WD) < e ){ + SSTVSET.m_OFS += SSTVSET.m_WD; + } + RedrawSSTV(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SBPLClick(TObject *Sender) +{ + int h, w; + SSTVSET.GetBitmapSize(w, h, SSTVSET.m_Mode); + ShiftSSTV(Sender, (SSTVSET.m_KS / double(w)) + 0.5); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SBPLMouseDown(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( Button == mbRight ){ + ShiftSSTV(Sender, 1); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::PBoxD12MouseDown(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( pSound == NULL ) return; + if( m_ReqSampChg ){ // サンプリング周波数変更要求中 + m_ReqSampChg = 0; + RedrawSampFreq(FALSE); + return; + } + CSSTVDEM *dp = pDem; + if( SBPhase->Down ){ + if( Button != mbLeft ) return; + CWaitCursor wait; + SSTVSET.m_OFS -= (X * SSTVSET.m_TW / PBoxD12->Width); + int e = 0; + switch(SSTVSET.m_Mode){ + case smSCT1: + case smSCT2: + case smSCTDX: + e = SSTVSET.m_WD; + break; + default: + break; + } + while( (SSTVSET.m_OFS + SSTVSET.m_WD) < e ){ + SSTVSET.m_OFS += SSTVSET.m_WD; + } + if( (dp->m_StgBuf != NULL) || WaveStg.IsOpen() ){ +#if 1 + RedrawSSTV(); +#else + InitAutoStop(); + m_ASDis = 1; + WaveStg.RInit(); + dp->m_rBase = SSTVSET.m_OFS; + for( int i = 0; i < dp->m_wStgLine; i++ ){ + if( dp->m_StgBuf != NULL ){ + DrawSSTV(&dp->m_StgBuf[i * SSTVSET.m_WD], &dp->m_StgB12[i * SSTVSET.m_WD]); + } + else { + WaveStg.Read(WaveStg.pData, SSTVSET.m_WD*sizeof(short)); + WaveStg.Read(WaveStg.pSync, SSTVSET.m_WD*sizeof(short)); + DrawSSTV(WaveStg.pData, WaveStg.pSync); + } + dp->m_rBase += SSTVSET.m_WD; + if( dp->m_Sync ){ + ::Sleep(pSound->IsBusy() ? 100 : 1); + CopyStgBuf(); + } + } + m_ASDis = 0; + DrawSync(); + if( (!dp->m_Sync) && RxHist.IsAddFlag() ){ + RxHist.Update(pBitmapRX); + ::CopyBitmap(pBitmapHist, pBitmapRX); + TrigHistF(); + UpdatePic(); + } + DrawSSTV(); + if( SSTVSET.m_SampFreq != sys.m_SampFreq ) DrawSlantInfo(); +#endif + } + else { + int n = (X * SSTVSET.m_TW / PBoxD12->Width); + while( n >= SSTVSET.m_WD ){ + n -= SSTVSET.m_WD; + } + while( n < 0 ){ + n += SSTVSET.m_WD; + } + dp->m_Skip = n; + } + } + else if( SBSlant->Down ){ + if( Button == mbRight ){ + if( m_Slant ){ + m_Slant = 0; + DrawSync(); + DispSyncStat(); + } + } + else if( m_Slant ){ + CWaitCursor wait; + m_Slant = 0; + double samp = GetSyncSamp(X, Y); + if( samp != SSTVSET.m_SampFreq ){ + SSTVSET.m_SampFreq = samp; + UpdateSampFreq(); + } + SSTVSET.SetSampFreq(); + DispSyncStat(); + DrawSSTV(); + DrawSlantInfo(); + } + else { + m_SlantX = X; + m_SlantY = Y; + m_Slant++; + } + } +} +//--------------------------------------------------------------------------- + +void __fastcall TMmsstv::PBoxD12Paint(TObject *Sender) +{ + DrawSync(); +} +//--------------------------------------------------------------------------- +TSpeedButton *__fastcall TMmsstv::GetModeBtn(int n) +{ + TSpeedButton *tp[]={ + SBM1, SBM2, SBM3, SBM4, SBM5, SBM6, SBM7, SBM8, SBM9, + }; + return tp[n]; +} +//--------------------------------------------------------------------------- +int __fastcall TMmsstv::GetButtonNo(TSpeedButton *tp) +{ + for( int i = 0; i < 9; i++ ){ + if( GetModeBtn(i) == tp ){ + return i; + } + } + return 8; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::UpdateModeCaption(void) +{ + int *ip = ((m_MainPage == pgTX)||(m_MainPage == pgTemp)) ? m_ModeAssignTX : m_ModeAssignRX; + int i; + for( i = 0; i < 9; i++, ip++ ){ + TSpeedButton *tp = GetModeBtn(i); + if( tp->Caption != SSTVModeList[*ip] ){ + tp->Caption = SSTVModeList[*ip]; + } + } +} +//--------------------------------------------------------------------------- +int __fastcall TMmsstv::FindModeAssign(int *ip, int m) +{ + int f = -1; + for( int i = 0; i < 9; i++, ip++ ){ + if( *ip == m ){ + f = i; + break; + } + } + return f; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::UpdateModeBtn(void) +{ + if( pSound == NULL ) return; + + int i, f; + if( (m_MainPage == pgTX)||(m_MainPage == pgTemp) ){ + GBMode->Caption = "TX Mode"; + GBMode->Font->Color = clBlue; +// SBAuto->Enabled = FALSE; + SBAuto->GroupIndex = 1; + SBAuto->Down = !sys.m_FixedTxMode; + f = FindModeAssign(m_ModeAssignTX, SSTVSET.m_TxMode); + if( f < 0 ){ + m_ModeAssignTX[8] = SSTVSET.m_TxMode; + f = 8; + } + GetModeBtn(f)->Down = TRUE; + AdjustPBoxSize((m_TXPH == 240) ? 240 : 256); + } + else { + GBMode->Caption = "RX Mode"; + GBMode->Font->Color = clBlack; +// SBAuto->Enabled = TRUE; + SBAuto->GroupIndex = 2; + SBAuto->Down = (pDem->m_SyncMode >= 0); + if( pDem->m_Sync ){ + f = FindModeAssign(m_ModeAssignRX, SSTVSET.m_Mode); + if( f < 0 ){ + m_ModeAssignRX[8] = SSTVSET.m_Mode; + f = 8; + } + GetModeBtn(f)->Down = TRUE; + } + else if( pDem->m_SyncMode < 0 ){ + for( i = 0; i < 9; i++ ){ + GetModeBtn(i)->Down = FALSE; + } + } + else { + SBAuto->Down = TRUE; + } + } + UpdateModeCaption(); + if( pCtrBtn != NULL ) pCtrBtn->UpdateBtn(); + SBFS->Enabled = pDem->m_Sync && (SSTVSET.m_Mode != smAVT) ? TRUE : FALSE; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SBAFCClick(TObject *Sender) +{ + pDem->m_afc = SBAFC->Down; + if( !pDem->m_afc ){ + pDem->InitAFC(); + } +} +//--------------------------------------------------------------------------- +int __fastcall TMmsstv::GetLMSDelay(void) +{ + if( !pSound->m_lms || pSound->m_lms_AN ) return 0; + return pSound->lms.m_Tap / 2; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SBLMSClick(TObject *Sender) +{ +#if 1 + // Tap数を増やした場合の処理 + // 2003/11/28に実験し、結果Tap数は従来通りの4に戻した + // のでこの処理をキャンセルした + int d = GetLMSDelay(); + pSound->m_lms = SBLMS->Down; + if( pSound->m_lms && pSound->m_lms_AN ) pSound->lms.SetAN(pSound->m_lms_AN); + if( pDem->m_Sync ) pDem->m_Skip = GetLMSDelay() - d; +#else + pSound->m_lms = SBLMS->Down; + if( pSound->m_lms && pSound->m_lms_AN ) pSound->lms.SetAN(pSound->m_lms_AN); +#endif +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::RxAutoPush(int sw) +{ + if( pSound == NULL ) return; + + int sc = pDem->m_Sync; + pDem->Stop(); + if( sc ) WriteHistory(0); + if( !sw ){ + pDem->m_SyncMode = -1; + } + else { + pDem->m_SyncMode = 0; + } + if( (m_MainPage != pgTX) && (m_MainPage != pgTemp) ){ + SBAuto->Down = sw; + } + UpdateModeBtn(); + UpdateUI(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SBAutoClick(TObject *Sender) +{ + if( pSound == NULL ) return; + + if( (m_MainPage == pgTX)||(m_MainPage == pgTemp) ){ + sys.m_FixedTxMode = !SBAuto->Down; + TrackTxMode(0); + } + else { + RxAutoPush(SBAuto->Down); + } +#if 0 + int sc = pDem->m_Sync; + pDem->Stop(); + if( sc ) WriteHistory(0); + if( !SBAuto->Down ){ + pDem->m_SyncMode = -1; + } + else { + pDem->m_SyncMode = 0; + } + UpdateModeBtn(); + UpdateUI(); +#endif +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::AdjustPBoxSize(int l) +{ + if( (l <= 256) && (l != PBoxTX->Height) ){ + PBoxTX->Height = l; + PBoxTX->Invalidate(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SBMClick(TObject *Sender) +{ + if( pSound == NULL ) return; + + TSpeedButton *tp = (TSpeedButton *)Sender; + if( !SBTX->Down && !tp->Down && ((m_MainPage == pgTX)||(m_MainPage == pgTemp)) ){ + tp->Down = TRUE; + m_ExtMode = GetButtonNo(tp); + PopupM->Popup(Left + GBMode->Left + tp->Left + tp->Width/2, Top + GBMode->Top + tp->Top + tp->Height); + return; + } + if( !SBTX->Down || (sys.m_echo == 2) ){ + m_ExtMode = GetButtonNo(tp); + if( ((m_MainPage == pgTX)||(m_MainPage == pgTemp)) ){ + if( !SBTX->Down ){ + ChangeTxMode(m_ModeAssignTX[m_ExtMode]); + } + } + else if( !pDem->m_Sync || (SSTVSET.m_Mode != m_ModeAssignRX[m_ExtMode] ) ){ + if( pDem->m_Sync ) WriteHistory(0); + int mode = m_ModeAssignRX[m_ExtMode]; + pDem->Start(mode, tp->Down); + } + } + UpdateModeBtn(); + UpdateUI(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::ClearDraw(Graphics::TBitmap *pBitmap, TPaintBox *pBox, TColor col) +{ + FillBitmap(pBitmap, col); + if( pBox == NULL ) return; + + if( pBox == PBoxRX ){ + if( m_MainPage != pgRX ) return; + } + else if( pBox == PBoxD12 ){ + if( m_MainPage != pgSync ) return; + } + else if( pBox == PBoxHist ){ + if( m_MainPage != pgHist ) return; + } + pBox->Canvas->Draw(0, 0, pBitmap); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::DrawLvl(void) +{ + if( pSound == NULL ) return; + if( DisPaint ) return; + + TCanvas *pCanvas = pBitmapLvl->Canvas; + + TRect rc; + int XL = 0; + int XR = pBitmapLvl->Width - 1; + int YT = 0; + int YB = pBitmapLvl->Height - 1; + rc.Left = XL; + rc.Right = XR; + rc.Top = YT; + rc.Bottom = YB+1; + pCanvas->Brush->Color = clBlack; + pCanvas->FillRect(rc); + + double k; + pDem->m_lvl.Fix(); + if( pDem->m_LevelType ){ + pDem->m_SyncLvl.Fix(); + k = double(YB) / 16384.0; + rc.Top = YB - (pDem->m_SyncLvl.m_Lvl * k); + } + else { + k = double(YB) / 24578.0; + rc.Top = YB - (pDem->m_lvl.m_CurMax * k); + } + if( pSound->m_Tx ){ + pCanvas->Brush->Color = pDem->m_Sync ? TColor(0x00ffff00) : clYellow; + } + else if( pDem->m_lvl.m_CurMax >= 24578 ){ + pCanvas->Brush->Color = clRed; + } + else if( pDem->m_Sync ){ + pCanvas->Brush->Color = clLime; + } + else { + pCanvas->Brush->Color = clGray; + } + if( rc.Top < 0 ) rc.Top = 0; + pCanvas->FillRect(rc); + if( !pDem->m_LevelType ){ + rc.Top = YB - (pDem->m_lvl.m_PeakMax * k); + if( rc.Top < 0 ) rc.Top = 0; + rc.Bottom = rc.Top + 1; + if( pSound->m_Tx ){ + pCanvas->Brush->Color = clWhite; + } + else if( pDem->m_lvl.m_PeakMax < 24578 ){ + pCanvas->Brush->Color = clWhite; + } + else { + pCanvas->Brush->Color = clRed; + } + pCanvas->FillRect(rc); + } + PBoxLvl->Canvas->Draw(0, 0, pBitmapLvl); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::DispHistStat(void) +{ + if( UDHist->Position < RxHist.m_Head.m_Cnt ){ + char bf1[128], bf2[128]; + char bbf[64]; + char tm[2]; + tm[0] = 'Z'; + tm[1] = 0; + SYSTEMTIME tim = RxHist.m_File[RxHist.m_CurRead].m_UTC; + if( Log.m_LogSet.m_TimeZone == 'I' ){ + UTCtoJST(&tim); + tm[0] = 0; + } + int mm = RxHist.m_File[RxHist.m_CurRead].m_Flag >> 16; + if( mm ){ + mm--; + int dm, w, h; + SSTVSET.GetPictureSize(w, dm, h, mm); + if( ((mm >= smR24) && (mm <= smRM12)) ){ + w /= 2; + h /= 2; + } + sprintf(bbf, "%s (%ux%u)", SSTVModeList[mm], w, h); + mm++; + } + else { + strcpy(bbf, "???"); + } + + sprintf(bf1, "%s\r\n%u %04u/%02u/%02u %02u%02u%s", + bbf, + UDHist->Position + 1, + tim.wYear, + tim.wMonth, + tim.wDay, + tim.wHour, + tim.wMinute, + tm + ); + sprintf(bf2, "%u %04u/%02u/%02u %02u%02u%s", + UDHist->Position + 1, + tim.wYear, + tim.wMonth, + tim.wDay, + tim.wHour, + tim.wMinute, + tm + ); + HistStat->Caption = bf1; + if( pHistView != NULL ){ + if( mm ) sprintf(&bf2[strlen(bf2)], " %s", bbf); + pHistView->UpdateTitle(pHistView->Active ? bf2 : NULL); + } + } + else { + HistStat->Caption = "No data"; + if( pHistView != NULL ) pHistView->UpdateTitle(NULL); + } + SBLatest->Enabled = UDHist->Position ? TRUE : FALSE; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::DispSyncStat(void) +{ + char bf[128]; + sprintf(bf, "%.2lfHz", SSTVSET.m_SampFreq); + SyncStat->Caption = bf; + SBSampSet->Enabled = (sys.m_SampFreq != SSTVSET.m_SampFreq) ? TRUE : FALSE; + UpdateSBTO(); + if( pSyncView != NULL ) pSyncView->UpdateSyncTitle(SSTVSET.m_SampFreq); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::UpdateHist(void) +{ + if( UDHist->Position < RxHist.m_Head.m_Cnt ){ + int n = (RxHist.m_Head.m_wPnt - 1) - UDHist->Position; + if( n < 0 ) n += RxHist.m_Head.m_Max; + if( n >= RxHist.m_Head.m_Max ) n -= RxHist.m_Head.m_Max; + RxHist.Read(pBitmapHist, n); + } + else { + ClearDraw(pBitmapHist, PBoxHist, sys.m_ColorRXB); + } + TrigHistF(); + UpdatePic(); + DispHistStat(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::UDHistClick(TObject *Sender, TUDBtnType Button) +{ + if( m_DisEvent ) return; + + if( UDHist->Position < RxHist.m_Head.m_Cnt ){ + UpdateHist(); + } + else { + UDHist->Position--; + } +} +//--------------------------------------------------------------------------- +// ヒストリの削除 +void __fastcall TMmsstv::KHDClick(TObject *Sender) +{ + if( UDHist->Position < RxHist.m_Head.m_Cnt ){ + if( YesNoMB( MsgEng ? "Delete the picture, are you sure?" : "ほんまに消しますか?" ) == IDYES ){ + RxHist.Delete(UDHist->Position); + if( UDHist->Position >= RxHist.m_Head.m_Cnt ) UDHist->Position--; + UpdateHist(); + if( pHistView != NULL ){ + pHistView->LoadHist(0); + } + } + } +} +//--------------------------------------------------------------------------- +// 全ヒストリの削除 +void __fastcall TMmsstv::KHDAClick(TObject *Sender) +{ + if( RxHist.m_Head.m_Cnt ){ + if( YesNoMB( MsgEng ? "Delete all pictures, are you sure?" : "全ての履歴を削除します." ) == IDYES ){ + RxHist.DeleteAll(); + UDHist->Position = 0; + UpdateHist(); + if( pHistView != NULL ) pHistView->LoadHist(0); + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::DateBitmap(Graphics::TBitmap *pBitmap, SYSTEMTIME &tim) +{ + pBitmap->Canvas->Font->Name = Font->Name; + pBitmap->Canvas->Font->Charset = Font->Charset; + pBitmap->Canvas->Font->Size = 8; + pBitmap->Canvas->Font->Color = clWhite; + pBitmap->Canvas->Brush->Color = clBlack; + char bf[64]; + switch(Log.m_LogSet.m_DateType){ + case 2: + case 3: + sprintf(bf, "%02u-%s-%04u %02u%02u", tim.wDay, MONT1[tim.wMonth], tim.wYear, tim.wHour, tim.wMinute); + break; + case 4: + case 5: + sprintf(bf, "%s-%02u-%04u %02u%02u", MONT1[tim.wMonth], tim.wDay, tim.wYear, tim.wHour, tim.wMinute); + break; + default: + sprintf(bf, "%04u-%s-%02u %02u%02u", tim.wYear, MONT1[tim.wMonth], tim.wDay, tim.wHour, tim.wMinute); + break; + } + int y = pBitmap->Height - pBitmap->Canvas->TextHeight(bf) - 1; + pBitmap->Canvas->TextOut(0, y, bf); +} +//--------------------------------------------------------------------------- +// ヒストリのファイルへのセーブ +void __fastcall TMmsstv::KHSClick(TObject *Sender) +{ + char bf[128]; + bf[0] = 0; + if( UDHist->Position < RxHist.m_Head.m_Cnt ){ + SYSTEMTIME tim = RxHist.m_File[RxHist.m_CurRead].m_UTC; + if( Log.m_LogSet.m_TimeZone == 'I' ){ + UTCtoJST(&tim); + } + sprintf(bf, "%04u%02u%02u%02u%02u", + tim.wYear, + tim.wMonth, + tim.wDay, + tim.wHour, + tim.wMinute + ); + if( Sender == KHT ){ + Graphics::TBitmap *pBitmap = DupeBitmap(pBitmapHist, pf24bit); + DateBitmap(pBitmap, tim); + SaveBitmapMenu(pBitmap, bf, NULL); + delete pBitmap; + } + else { + SaveBitmapMenu(pBitmapHist, bf, NULL); + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::PBoxHistPaint(TObject *Sender) +{ + DrawBitmap(PBoxHist, pBitmapHist); + if( sys.m_ShowSizeHist ){ + ShowSize(PBoxHist, pBitmapHist->Width, pBitmapHist->Height, 12, clGreen); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SBLatestClick(TObject *Sender) +{ + if( UDHist->Position ){ + UDHist->Position = 0; + UpdateHist(); + } +} +//--------------------------------------------------------------------------- +double __fastcall TMmsstv::GetSyncSamp(int X, int Y) +{ + if( m_SlantY == Y ) return SSTVSET.m_SampFreq; + double d = (X - m_SlantX); + d = d * SSTVSET.m_SampFreq / pBitmapD12->Width; + d /= (m_SlantY - Y); + d = SSTVSET.m_SampFreq - d; + d = NormalSampFreq(d, 10); + if( d > (SampFreq * 1100/1060) ){ + d = SampFreq * 1100/1060; + } + return d; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::DrawSync(void) +{ + if( m_MainPage != pgSync ) return; + + PBoxD12->Canvas->Draw(0, 0, pBitmapD12); + if( m_Slant ){ + PBoxD12->Canvas->Pen->Color = clBlue; + PBoxD12->Canvas->Pen->Style = psSolid; + PBoxD12->Canvas->MoveTo(m_SlantX, m_SlantY); + int Sop = ::SetROP2(PBoxD12->Canvas->Handle, R2_MERGEPENNOT); + PBoxD12->Canvas->LineTo(m_SlantX2, m_SlantY2); + ::SetROP2(PBoxD12->Canvas->Handle, Sop); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::PBoxD12MouseMove(TObject *Sender, + TShiftState Shift, int X, int Y) +{ + if( m_Slant ){ + m_SlantX2 = X; + m_SlantY2 = Y; + DrawSync(); + char bf[32]; + sprintf(bf, "%.2lfHz", GetSyncSamp(X, Y)); + SyncStat->Caption = bf; + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SBSampSetClick(TObject *Sender) +{ + sys.m_SampFreq = SSTVSET.m_SampFreq; + SBSampSet->Enabled = FALSE; + InfoSampFreq(); + SSTVSET.InitIntervalPara(); + UpdateSBTO(); + DrawSlantInfo(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SBPasteClick(TObject *Sender) +{ + if( PasteBitmap(pBitmapTXM, (Sender == KEX) ? 2 : 0) == TRUE ){ + AdjustPage(pgTX); + MakeTxBitmap(0); + PBoxTXPaint(NULL); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::ShowSize(TPaintBox *pBox, int w, int h, int fs, TColor col) +{ + pBox->Canvas->Brush->Color = col; + pBox->Canvas->Font->Color = clWhite; + pBox->Canvas->Font->Height = -fs; + char bf[64]; + sprintf(bf, "%ux%u", w, h); + int fh = pBox->Canvas->TextHeight(bf); + pBox->Canvas->TextOut(0, pBox->Height - fh, bf); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::ShowSize(Graphics::TBitmap *pBitmap, int x, int y, int w, int h, int fs, TColor col) +{ + pBitmap->Canvas->Brush->Color = col; + pBitmap->Canvas->Font->Color = clWhite; + pBitmap->Canvas->Font->Height = -fs; + char bf[64]; + sprintf(bf, "%ux%u", w, h); + int fh = pBitmap->Canvas->TextHeight(bf); + pBitmap->Canvas->TextOut(x, y - fh, bf); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::ShowNo(Graphics::TBitmap *pBitmap, int x, int y, int n, int fs, TColor col) +{ + pBitmap->Canvas->Brush->Color = col; + pBitmap->Canvas->Font->Color = clBlack; + pBitmap->Canvas->Font->Height = -fs; + char bf[64]; + sprintf(bf, "%u", n); + pBitmap->Canvas->TextOut(x+1, y+1, bf); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::PBoxTXPaint(TObject *Sender) +{ + if( m_MainPage != pgTX ) return; + + DrawBitmap(PBoxTX, pBitmapTX); + m_SendY = -1; + if( sys.m_ShowSizeTX ){ + ShowSize(PBoxTX, m_TXW, m_TXPH, 12, clGreen); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SBCopyClick(TObject *Sender) +{ + CopyBitmap(pBitmapHist); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KRCCClick(TObject *Sender) +{ + ClearDraw(pBitmapRX, PBoxRX, sys.m_ColorRXB); + ClearDraw(pBitmapD12, PBoxD12, clWhite); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::LineR24(CSSTVMOD *mp) +{ + int x; + int Y, RY[320], BY[320]; + mp->Write(1200, 6); + mp->Write(1500, 2); + for( x = 0; x < 320; x++ ){ // Y + GetRY(Y, RY[x], BY[x], pBitmapTX->Canvas->Pixels[x][mp->m_wLine]); + mp->Write(short(ColorToFreq(Y)), 92.0/320.0); + } + mp->Write(1500, 3.0); + mp->Write(1900, 1.0); + for( x = 0; x < 320; x++ ){ // R-Y + mp->Write(short(ColorToFreq(RY[x])), 46.0/320.0); + } + mp->Write(2300, 3.0); + mp->Write(1900, 1.0); + for( x = 0; x < 320; x++ ){ // B-Y + mp->Write(short(ColorToFreq(BY[x])), 46.0/320.0); + } + mp->m_wLine++; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::LineR36(CSSTVMOD *mp) +{ + int x; + int Y, RY[320], BY[320]; + mp->Write(1200, 9); + mp->Write(1500, 3); + for( x = 0; x < 320; x++ ){ // Y + GetRY(Y, RY[x], BY[x], pBitmapTX->Canvas->Pixels[x][mp->m_wLine]); + mp->Write(short(ColorToFreq(Y)), 88.0/320.0); + } + mp->Write(short(mp->m_wLine & 1 ? 2300 : 1500), 4.5); // RY=1500, BY=2300 + mp->Write(1900, 1.5); + for( x = 0; x < 320; x++ ){ // DeffColor + if( !(mp->m_wLine & 1) ){ // R-Y + Y = RY[x]; + } + else { // B-Y + Y = BY[x]; + } + mp->Write(short(ColorToFreq(Y)), 44.0/320.0); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::LineR72(CSSTVMOD *mp) +{ + int x; + int Y, RY[320], BY[320]; + mp->Write(1200, 9); + mp->Write(1500, 3); + for( x = 0; x < 320; x++ ){ // Y + GetRY(Y, RY[x], BY[x], pBitmapTX->Canvas->Pixels[x][mp->m_wLine]); + mp->Write(short(ColorToFreq(Y)), 138.0/320.0); + } + mp->Write(1500, 4.5); + mp->Write(1900, 1.5); + for( x = 0; x < 320; x++ ){ // R-Y + mp->Write(short(ColorToFreq(RY[x])), 69.0/320.0); + } + mp->Write(2300, 4.5); + mp->Write(1900, 1.5); + for( x = 0; x < 320; x++ ){ // B-Y + mp->Write(short(ColorToFreq(BY[x])), 69.0/320.0); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::LineAVT(CSSTVMOD *mp) +{ + int x; + COLD col[320]; + COLD *cp; + for( cp = col, x = 0; x < 320; x++, cp++ ){ // R + cp->c = pBitmapTX->Canvas->Pixels[x][mp->m_wLine]; + mp->Write(short(ColorToFreq(cp->b.r)+0x1000), 125.0/320.0); + } + for( cp = col, x = 0; x < 320; x++, cp++ ){ // G + mp->Write(short(ColorToFreq(cp->b.g)+0x2000), 125.0/320.0); + } + for( cp = col, x = 0; x < 320; x++, cp++ ){ // B + mp->Write(short(ColorToFreq(cp->b.b)+0x3000), 125.0/320.0); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::LineSCT(CSSTVMOD *mp, double tw) +{ + int x; + COLD col[320]; + COLD *cp; + mp->Write(1500+0x2000, 1.5); + tw /= 320.0; + for( cp = col, x = 0; x < 320; x++, cp++ ){ // G + cp->c = pBitmapTX->Canvas->Pixels[x][mp->m_wLine]; + mp->Write(short(ColorToFreq(cp->b.g)+0x2000), tw); + } + mp->Write(1500+0x3000, 1.5); + for( cp = col, x = 0; x < 320; x++, cp++ ){ // B + mp->Write(short(ColorToFreq(cp->b.b)+0x3000), tw); + } + mp->Write(1200, 9); + mp->Write(1500+0x1000, 1.5); + for( cp = col, x = 0; x < 320; x++, cp++ ){ // R + mp->Write(short(ColorToFreq(cp->b.r)+0x1000), tw); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::LineMRT(CSSTVMOD *mp, double tw) +{ + int x; + COLD col[320]; + COLD *cp; + mp->Write(1200, 4.862); + mp->Write(1500+0x2000, 0.572); + tw /= 320.0; + for( cp = col, x = 0; x < 320; x++, cp++ ){ // G + cp->c = pBitmapTX->Canvas->Pixels[x][mp->m_wLine]; + mp->Write(short(ColorToFreq(cp->b.g)+0x2000), tw); + } + mp->Write(1500+0x3000, 0.572); + for( cp = col, x = 0; x < 320; x++, cp++ ){ // B + mp->Write(short(ColorToFreq(cp->b.b)+0x3000), tw); + } + mp->Write(1500+0x1000, 0.572); + for( cp = col, x = 0; x < 320; x++, cp++ ){ // R + mp->Write(short(ColorToFreq(cp->b.r)+0x1000), tw); + } + mp->Write(1500, 0.572); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::LineSC2180(CSSTVMOD *mp, double S, double tw) +{ +// 0.711043693634973869144258914710309 + int x; + COLD col[320]; + COLD *cp; + mp->Write(1200, S); + mp->Write(1500+0x1000, 0.5); + tw /= 320.0; + for( cp = col, x = 0; x < 320; x++, cp++ ){ // R + cp->c = pBitmapTX->Canvas->Pixels[x][mp->m_wLine]; + mp->Write(short(ColorToFreq(cp->b.r)+0x1000), tw); + } + for( cp = col, x = 0; x < 320; x++, cp++ ){ // G + mp->Write(short(ColorToFreq(cp->b.g)+0x2000), tw); + } + for( cp = col, x = 0; x < 320; x++, cp++ ){ // B + mp->Write(short(ColorToFreq(cp->b.b)+0x3000), tw); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::LinePD(CSSTVMOD *mp, double tw) +{ + int x; + int Y, RY[800], BY[800]; + mp->Write(1200, 20.000); + mp->Write(1500, 2.080); + tw /= double(pBitmapTX->Width); + for( x = 0; x < pBitmapTX->Width; x++ ){ // Y(odd) + GetRY(Y, RY[x], BY[x], pBitmapTX->Canvas->Pixels[x][mp->m_wLine]); + mp->Write(short(ColorToFreq(Y)), tw); + } + for( x = 0; x < pBitmapTX->Width; x++ ){ // R-Y + mp->Write(short(ColorToFreq(RY[x])), tw); + } + for( x = 0; x < pBitmapTX->Width; x++ ){ // B-Y + mp->Write(short(ColorToFreq(BY[x])), tw); + } + mp->m_wLine++; + for( x = 0; x < pBitmapTX->Width; x++ ){ // Y(even) + GetRY(Y, RY[0], BY[0], pBitmapTX->Canvas->Pixels[x][mp->m_wLine]); + mp->Write(short(ColorToFreq(Y)), tw); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::LineP(CSSTVMOD *mp, double S, double P, double C) +{ + int x; + COLD col[640]; + COLD *cp; + mp->Write(1200, S); + mp->Write(1500+0x1000, P); + double tw = C / 640.0; + for( cp = col, x = 0; x < 640; x++, cp++ ){ // R + cp->c = pBitmapTX->Canvas->Pixels[x][mp->m_wLine]; + mp->Write(short(ColorToFreq(cp->b.r)+0x1000), tw); + } + mp->Write(1500+0x2000, P); + for( cp = col, x = 0; x < 640; x++, cp++ ){ // G + mp->Write(short(ColorToFreq(cp->b.g)+0x2000), tw); + } + mp->Write(1500+0x3000, P); + for( cp = col, x = 0; x < 640; x++, cp++ ){ // B + mp->Write(short(ColorToFreq(cp->b.b)+0x3000), tw); + } + mp->Write(1500, P); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::LineMP(CSSTVMOD *mp, double tw) +{ + int x; + int Y, RY[320], BY[320]; + mp->Write(1200, 9.000); + mp->Write(1500, 1.000); + tw /= double(pBitmapTX->Width); + for( x = 0; x < pBitmapTX->Width; x++ ){ // Y(odd) + GetRY(Y, RY[x], BY[x], pBitmapTX->Canvas->Pixels[x][mp->m_wLine]); + mp->Write(short(ColorToFreq(Y)), tw); + } + for( x = 0; x < pBitmapTX->Width; x++ ){ // R-Y + mp->Write(short(ColorToFreq(RY[x])), tw); + } + for( x = 0; x < pBitmapTX->Width; x++ ){ // B-Y + mp->Write(short(ColorToFreq(BY[x])), tw); + } + mp->m_wLine++; + for( x = 0; x < pBitmapTX->Width; x++ ){ // Y(even) + GetRY(Y, RY[0], BY[0], pBitmapTX->Canvas->Pixels[x][mp->m_wLine]); + mp->Write(short(ColorToFreq(Y)), tw); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::LineMR(CSSTVMOD *mp, double tw) +{ + int x; + int Y, RY[640], BY[640]; + int TXW = pBitmapTX->Width; + mp->Write(1200, 9); + mp->Write(1500, 1); + double ty = tw / double(TXW); + double tc = ty / 2.0; + short d; + for( x = 0; x < TXW; x++ ){ // Y + GetRY(Y, RY[x], BY[x], pBitmapTX->Canvas->Pixels[x][mp->m_wLine]); + d = short(ColorToFreq(Y)); + mp->Write(d, ty); + } + mp->Write(d, 0.1); + for( x = 0; x < TXW; x++ ){ // R-Y + d = short(ColorToFreq(RY[x])); + mp->Write(d, tc); + } + mp->Write(d, 0.1); + for( x = 0; x < TXW; x++ ){ // B-Y + d = short(ColorToFreq(BY[x])); + mp->Write(d, tc); + } + mp->Write(d, 0.1); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::LineRM(CSSTVMOD *mp, double ts, double tw) +{ + int x; + int Y[320], YY, RY, BY; + mp->Write(1200, ts); + mp->Write(1500, ts/3.0); + tw /= 320.0; + for( x = 0; x < 320; x++ ){ // Y + GetRY(Y[x], RY, BY, pBitmapTX->Canvas->Pixels[x][mp->m_wLine]); + } + mp->m_wLine++; + for( x = 0; x < 320; x++ ){ // Y + GetRY(YY, RY, BY, pBitmapTX->Canvas->Pixels[x][mp->m_wLine]); + YY = (YY + Y[x]) / 2; + mp->Write(short(ColorToFreq(YY)), tw); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::LineMN(CSSTVMOD *mp, double tw) +{ + int x; + int Y, RY[320], BY[320]; + mp->Write(NARROW_SYNC, 9.000); + mp->Write(NARROW_LOW, 1.000); + tw /= double(pBitmapTX->Width); + for( x = 0; x < pBitmapTX->Width; x++ ){ // Y(odd) + GetRY(Y, RY[x], BY[x], pBitmapTX->Canvas->Pixels[x][mp->m_wLine]); + mp->Write(short(ColorToFreqNarrow(Y)), tw); + } + for( x = 0; x < pBitmapTX->Width; x++ ){ // R-Y + mp->Write(short(ColorToFreqNarrow(RY[x])), tw); + } + for( x = 0; x < pBitmapTX->Width; x++ ){ // B-Y + mp->Write(short(ColorToFreqNarrow(BY[x])), tw); + } + mp->m_wLine++; + for( x = 0; x < pBitmapTX->Width; x++ ){ // Y(even) + GetRY(Y, RY[0], BY[0], pBitmapTX->Canvas->Pixels[x][mp->m_wLine]); + mp->Write(short(ColorToFreqNarrow(Y)), tw); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::LineMC(CSSTVMOD *mp, double tw) +{ + int x; + COLD col[320]; + COLD *cp; + mp->Write(NARROW_SYNC, 8.0); + mp->Write(NARROW_LOW, 0.5); + tw /= 320.0; + for( cp = col, x = 0; x < 320; x++, cp++ ){ // R + cp->c = pBitmapTX->Canvas->Pixels[x][mp->m_wLine]; + mp->Write(short(ColorToFreqNarrow(cp->b.r)), tw); + } + for( cp = col, x = 0; x < 320; x++, cp++ ){ // G + mp->Write(short(ColorToFreqNarrow(cp->b.g)), tw); + } + for( cp = col, x = 0; x < 320; x++, cp++ ){ // B + mp->Write(short(ColorToFreqNarrow(cp->b.b)), tw); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::OutputMMV(void) +{ + CSSTVMOD *mp = pMod; + if( mp->GetRowCnt() ) return; + CWaitCursor wait; + BYTE head[4]; + + FILE *fp = fopen(sys.m_MMVID.c_str(), "rb"); + if( fp != NULL ){ + int len = filelength(fileno(fp)); + if( (len >= 4) && (fread(head, 1, 4, fp) == 4) ){ + int Samp; + if( (head[0] == 0x55) && (head[1] == 0xaa) ){ + len -= 4; + Samp = head[2]; + if( Samp > 8 ) Samp = 0; + } + else { + fseek(fp, 0L, SEEK_SET); + Samp = head[0]; + } + if( m_pRowBuf != NULL ) delete m_pRowBuf; + BYTE *bp = new BYTE[len+2]; + int pos = 0; + while(len > 0){ + int rlen = fread(&bp[pos], 1, 16384, fp); + len -= rlen; + pos += rlen; + if( rlen < 16384 ) break; + } + if( Samp != SampType ){ + double sfq = SampTable[Samp]; + len = int(double(pos) * SampBase / sfq); + len &= 0xfffffffe; + m_pRowBuf = new BYTE[len+2]; + short *tp = (short *)m_pRowBuf; + short *sp = (short *)bp; + len /= 2; + int i, r; + CIIR iir; + iir.MakeIIR(2700, SampBase, 4, 0, 0); + for( i = 0; i < len; i++ ){ + r = int(double(i) * sfq / SampBase); + *tp++ = iir.Do(sp[r]); + } + pos = len * 2; + delete bp; + } + else { + m_pRowBuf = bp; + } + mp->SetRow((short *)m_pRowBuf, pos/2); + } + fclose(fp); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::OutputFSKID(void) +{ + CSSTVMOD *mp = pMod; + CWaitCursor wait; + + char bf[128]; + LPSTR p; + strcpy(bf, sys.m_Call.c_str()); p = bf; + mp->Write(FSKSPACE, FSKGARD); + mp->Write(1900, FSKINTVAL); + mp->WriteFSK(0x2a); // STX + BYTE s = 0; + BYTE c; + for(; *p; p++ ){ + while(mp->GetBufCnt() >= ((mp->m_TXBufLen-2) * SampFreq)) ::Sleep(1000); + c = BYTE((*p) - 0x20); + s = BYTE(c ^ s); + mp->WriteFSK(c); + } + mp->WriteFSK(0x01); // EOT + mp->WriteFSK(s); // check sum + + if( Log.m_LogSet.m_FSKNR ){ + char ubf[256]; + strcpy(ubf, AnsiString(HisRST->Text).c_str()); //ja7ude 0428 + LPCSTR sp = ubf; + for(p = bf; *sp; *sp++ ){ + if( *sp >= '0' ) *p++ = *sp; + } + *p = 0; + p = bf; + while(mp->GetBufCnt() >= ((mp->m_TXBufLen-2) * SampFreq)) ::Sleep(1000); + if( strlen(p) > 3 ){ + p += 3; + int l = strlen(p); + int d; + if( !IsAlphas(p) && (l >= 3) && (sscanf(p, "%u", &d) == 1) && (d < 4096) && ((l < 4)||(d >= 1000)) ){ + s = 0x02; + mp->WriteFSK(s); + c = BYTE((d >> 6) & 0x3f); + s = s ^ c; + mp->WriteFSK(c); + c = BYTE(d & 0x3f); + s = s ^ c; + mp->WriteFSK(c); + } + else { + jstrupr(p); + s = 0; + for(; *p; p++ ){ + while(mp->GetBufCnt() >= ((mp->m_TXBufLen-2) * SampFreq)) ::Sleep(1000); + c = BYTE((*p) - 0x20); + s = BYTE(c ^ s); + mp->WriteFSK(c); + } + mp->WriteFSK(0x01); // EOT + } + mp->WriteFSK(s); // check sum + } + } + mp->Write(FSKSPACE, FSKGARD); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::OutputCWID(void) +{ + if( !sys.m_CWIDText.IsEmpty() ){ + CWaitCursor wait; + CSSTVMOD *mp = pMod; + char bf[80]; + bf[0] = '@'; + MacroText(&bf[1], sys.m_CWIDText.c_str(), sizeof(bf)-2); + LPCSTR p = bf; + for(; *p; p++ ){ + while(mp->GetBufCnt() >= ((mp->m_TXBufLen-2) * SampFreq)) ::Sleep(1000); + mp->WriteCWID(*p); + } + } +} +//--------------------------------------------------------------------------- +int __fastcall TMmsstv::IsSR(void) +{ + return pMod->GetBufCnt() < ((pMod->m_TXBufLen-2) * SampFreq); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SendSSTV(void) +{ + if( !SBTX->Down ) return; + + CSSTVMOD *mp = pMod; + if( IsSR() ){ + if( mp->m_wLine >= SSTVSET.m_TL ){ + if( mp->m_wLine == SSTVSET.m_TL ){ + // MMSSTV フッター + if( !sys.m_TXFSKID ){ // FSKIDなし + double tw = SampFreq/2; + if( !sys.m_VOX && !SSTVSET.m_fTxNarrow ){ + mp->WriteC(1500, SSTVSET.m_TW > tw ? tw : SSTVSET.m_TW); + mp->Write(1900, 100); + mp->Write(1500, 100); + mp->Write(1900, 100); + mp->Write(1500, 100); + } + else { + mp->WriteC(1900, SSTVSET.m_TW > tw ? tw : SSTVSET.m_TW); + } + } + else { // FSKIDあり + mp->Write(WORD(SSTVSET.m_fTxNarrow ? 1900 : 1500), 300); + } + mp->m_wLine++; + } + else if( mp->m_wLine == (SSTVSET.m_TL + 1) ){ + if( mp->GetBufCnt() < (2 * SampFreq) ){ + if( sys.m_TXFSKID && !sys.m_Call.IsEmpty() ){ + OutputFSKID(); + } + if( sys.m_CWID == 1 ){ + OutputCWID(); + } + else if( (sys.m_CWID == 2) && !sys.m_MMVID.IsEmpty() ){ + OutputMMV(); + } + mp->m_wLine++; + } + } + else if( mp->m_wLine == (SSTVSET.m_TL + 2) ){ + if( !mp->m_Cnt && !mp->m_RowCnt ){ + pSound->TrigBCC(); + mp->m_wLine++; + } + } + else if( pSound->GetBCC() < 0 ){ + int lost = mp->m_Lost; + ToRX(); + if( lost ) InfoTxLost(); + if( KSRR->Checked && (m_MainPage == pgTX) ){ + AdjustPage(pgRX); + } + return; + } +#if 0 + else if( !mp->m_Cnt && !mp->m_RowCnt ){ + int lost = mp->m_Lost; +// ::Sleep( (pSound->m_BuffSize * pSound->m_FifoSize * 1000) / SSTVSET.m_TxSampFreq ); // バッファ送信完了待ち + ToRX(); + if( lost ) InfoTxLost(); + return; + } +#endif + } + else { + while( (mp->GetBufCnt() < ((mp->m_TXBufLen-2) * SampFreq)) && (mp->m_wLine < SSTVSET.m_TL) ){ + switch(SSTVSET.m_TxMode){ + case smR36: + LineR36(mp); + break; + case smR72: + LineR72(mp); + break; + case smAVT: + LineAVT(mp); + break; + case smSCT1: + LineSCT(mp, 138.24); + break; + case smSCT2: + LineSCT(mp, 88.064); + break; + case smSCTDX: + LineSCT(mp, 345.6); + break; + case smMRT1: + LineMRT(mp, 146.432); + break; + case smMRT2: + LineMRT(mp, 73.216); + break; + case smSC2_180: + LineSC2180(mp, 5.5437, 235.0); + break; + case smSC2_120: + LineSC2180(mp, 5.52248, 156.5); + break; + case smSC2_60: + LineSC2180(mp, 5.5006, 78.128); // 6.0006 + break; + case smPD50: + LinePD(mp, 91.520); + break; + case smPD90: + LinePD(mp, 170.240); + break; + case smPD120: + LinePD(mp, 121.600); + break; + case smPD160: + LinePD(mp, 195.584); + break; + case smPD180: + LinePD(mp, 183.040); + break; + case smPD240: + LinePD(mp, 244.480); + break; + case smPD290: + LinePD(mp, 228.800); + break; + case smP3: + LineP(mp, 5.208, 1.042, 133.333); + break; + case smP5: + LineP(mp, 7.813, 1.562375, 200.000); + break; + case smP7: + LineP(mp, 10.417, 2.083, 266.667); + break; + case smMR73: + LineMR(mp, 138.0); + break; + case smMR90: + LineMR(mp, 171.0); + break; + case smMR115: + LineMR(mp, 220.0); + break; + case smMR140: + LineMR(mp, 269.0); + break; + case smMR175: + LineMR(mp, 337.0); + break; + case smMP73: + LineMP(mp, 140.0); + break; + case smMP115: + LineMP(mp, 223.0); + break; + case smMP140: + LineMP(mp, 270.0); + break; + case smMP175: + LineMP(mp, 340.0); + break; + case smML180: + LineMR(mp, 176.5); + break; + case smML240: + LineMR(mp, 236.5); + break; + case smML280: + LineMR(mp, 277.5); + break; + case smML320: + LineMR(mp, 317.5); + break; + case smR24: + LineR24(mp); + break; + case smRM8: + LineRM(mp, 6.0, 58.89709); + break; + case smRM12: + LineRM(mp, 6.0, 92.0); + break; + case smMN73: + LineMN(mp, 140.0); + break; + case smMN110: + LineMN(mp, 212.0); + break; + case smMN140: + LineMN(mp, 270.0); + break; + case smMC110: + LineMC(mp, 140.0); + break; + case smMC140: + LineMC(mp, 180.0); + break; + case smMC180: + LineMC(mp, 232.0); + break; + } + mp->m_wLine++; + } + } + } + // 送信位置マーカー + if( mp->m_sCnt < mp->m_rCnt ){ + int l = mp->m_rCnt - mp->m_sCnt; + if( mp->m_wLine >= (SSTVSET.m_TL + 3) ){ + l -= pSound->GetOutCount(1); + } + else { + l -= pSound->GetOutCount(0); + } + l /= SSTVSET.m_TWD; +// int l = (mp->m_rCnt - mp->m_sCnt - ) / SSTVSET.m_TWD; + switch(SSTVSET.m_TxMode){ + case smR24: + case smRM8: + case smRM12: + case smPD50: + case smPD90: + case smMP73: + case smMP115: + case smMP140: + case smMP175: + case smMN73: + case smMN110: + case smMN140: + l *= 2; + break; + case smPD120: + case smPD180: + case smPD240: + l = l * 512 / 496; + if( l > 256 ) l = 256; + break; + case smPD160: + l = l * 512 / 400; + if( l > 256 ) l = 256; + break; + case smPD290: + l = l * 512 / 616; + if( l > 256 ) l = 256; + break; + case smP3: + case smP5: + case smP7: + case smML180: + case smML240: + case smML280: + case smML320: + l = l * 256 / 496; + if( l > 256 ) l = 256; + break; + } + if( l > SSTVSET.m_TL ) l = SSTVSET.m_TL; + if( l < 0 ) l = 0; + DrawTXCursor(l); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::UpdateTXUI(void) +{ + int f = SBTX->Down ? FALSE : TRUE; + SBTune->Enabled = f; + SBCW->Enabled = f; +// SBUseTemp->Enabled = f; + SBUA240->Enabled = (m_TXW == 320) ? f : FALSE; + SBUS240->Enabled = (m_TXW == 320) ? f : FALSE; + SBDA240->Enabled = f; + SBDS240->Enabled = f; + SBTXFil->Enabled = f; + SBPaste->Enabled = f && ::IsClipboardFormatAvailable(CF_BITMAP); + if( pCtrBtn != NULL ) pCtrBtn->UpdateBtn(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::OutHEAD(void) +{ + CSSTVMOD *mp = pMod; + + switch(sys.m_VOX){ + case 0: + if( SSTVSET.m_fTxNarrow ){ + mp->Write(1900, 100); + mp->Write(2300, 100); + mp->Write(1900, 100); + mp->Write(2300, 100); + } + else { + mp->Write(1900, 100); + mp->Write(1500, 100); + mp->Write(1900, 100); + mp->Write(1500, 100); + mp->Write(2300, 100); + mp->Write(1500, 100); + mp->Write(2300, 100); + mp->Write(1500, 100); + } + break; + case 1: + if( !sys.m_VOXSound.IsEmpty() ){ + CTextString cs(sys.m_VOXSound.c_str()); + char bf[1024]; + if( cs.LoadText(bf, sizeof(bf)-1) ){ + DeleteComment(bf); + if( bf[0] == '#' ){ + if( !strcmp(&bf[1], "id") ){ + mp->Write(WORD(SSTVSET.m_fTxNarrow ? 1900 : 1500), 300); + OutputFSKID(); + break; + } + else if( !strcmp(&bf[1], "cw") ){ + OutputCWID(); + break; + } + else { + int n = atoin(&bf[1], -1); + while(n--){ + if( !cs.LoadText(bf, sizeof(bf)-1) ) break; + } + DeleteComment(bf); + } + } + LPSTR t, p; + p = bf; + int ttm = 0; + int lmt = (SSTVSET.m_TxMode == smAVT) ? 1800 : 8000; + while(*p){ + p = StrDlm(t, p); + if( *t ){ + int fq = atoin(t, -1); + if( fq < 0 ) fq = 0; + if( fq > 2800 ) fq = 2800; + p = StrDlm(t, p); + int tm = atoin(t, -1); + if( tm <= 0 ) tm = 100; + ttm += tm; + if( ttm > lmt ){ + ttm -= tm; + tm = lmt - ttm; + if( tm > 0 ) mp->Write(short(fq), tm); + break; + } + else { + mp->Write(short(fq), tm); + } + } + else { + break; + } + } + } + } + break; + default: + break; + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::ToTX(void) +{ + CWaitCursor wait; + + m_TuneTimer = 0; + if( !sys.m_echo ){ + int f = pDem->m_Sync; + pDem->Stop(); + pDem->FreeRxBuff(); + if( f ) WriteHistory(0); + } + if( m_ReqHistF || m_ChangeTemp || DrawMain.IsTimeMacro() ){ + if( m_ReqHistF ) AdjustHistF(); + UpdatePic(); + } + int rep = (sys.m_Repeater && pDem->m_Repeater) ? 1 : 0; + if( SBUseTemp->Down && DrawMain.m_Cnt && (pBitmapTXM->Width != DrawMain.m_SX) && (!rep) ){ + SBTX->Down = FALSE; + if( + YesNoMB( MsgEng ? + "The template image quality is no good, because the size of template is different from the TX image.\r\n\r\nContinue processing?" : + "テンプレートのサイズが送信画像と異なるためテンプレートの画質は良くありません.\r\n\r\nこのまま送信しますか?" ) == IDNO + ){ + return; + } + SBTX->Down = TRUE; + } + + m_SendY = -1; + SBTX->Down = 1; + UpdateTXUI(); + CSSTVMOD *mp = pMod; + SSTVSET.SetTxMode(SSTVSET.m_TxMode); + + mp->OpenTXBuf(10); + mp->InitTXBuf(); + + // MMSSTV ヘッダー + OutHEAD(); + // VIS + if( SSTVSET.m_fTxNarrow ){ // 狭帯域モードの送信 + mp->Write(1900, 300); + mp->Write(FSKSPACE, FSKGARD); + mp->Write(1900, FSKINTVAL); + mp->WriteFSK(0x2d); // STX + mp->WriteFSK(0x15); // STX + BYTE d = 0; + switch(SSTVSET.m_TxMode){ + case smMN73: + d = 0x02; + break; + case smMN110: + d = 0x04; + break; + case smMN140: + d = 0x05; + break; + case smMC110: + d = 0x14; + break; + case smMC140: + d = 0x15; + break; + case smMC180: + d = 0x16; + break; + } + mp->WriteFSK(d); + mp->WriteFSK(BYTE(d^0x15)); +// mp->Write(FSKSPACE, FSKGARD); + } + else { + int i; + int n; + int d; + int e = (SSTVSET.m_TxMode == smAVT) ? 3 : 1; + for( n = 0; n < e; n++ ){ + mp->Write(1900, 300); + mp->Write(1200, 10); + mp->Write(1900, 300); + mp->Write(1200, 30); + switch(SSTVSET.m_TxMode){ + case smR36: + d = 0x88; + break; + case smR72: + d = 0x0c; + break; + case smAVT: + d = 0x44; + break; + case smSCT1: + d = 0x3c; + break; + case smSCT2: + d = 0xb8; + break; + case smSCTDX: + d = 0xcc; + break; + case smMRT1: + d = 0xac; + break; + case smMRT2: + d = 0x28; + break; + case smSC2_180: + d = 0xb7; + break; + case smSC2_120: + d = 0x3f; + break; + case smSC2_60: + d = 0xbb; + break; + case smPD50: + d = 0xdd; + break; + case smPD90: + d = 0x63; + break; + case smPD120: + d = 0x5f; + break; + case smPD160: + d = 0xe2; + break; + case smPD180: + d = 0x60; + break; + case smPD240: + d = 0xe1; + break; + case smPD290: + d = 0xde; + break; + case smP3: + d = 0x71; + break; + case smP5: + d = 0x72; + break; + case smP7: + d = 0xf3; + break; + case smMR73: + d = 0x4523; + break; + case smMR90: + d = 0x4623; + break; + case smMR115: + d = 0x4923; + break; + case smMR140: + d = 0x4a23; + break; + case smMR175: + d = 0x4c23; + break; + case smMP73: + d = 0x2523; + break; + case smMP115: + d = 0x2923; + break; + case smMP140: + d = 0x2a23; + break; + case smMP175: + d = 0x2c23; + break; + case smML180: + d = 0x8523; + break; + case smML240: + d = 0x8623; + break; + case smML280: + d = 0x8923; + break; + case smML320: + d = 0x8a23; + break; + case smR24: + d = 0x84; + break; + case smRM8: + d = 0x82; + break; + case smRM12: + d = 0x86; + break; + } + if( d >= 0x100 ){ + for( i = 0; i < 16; i++ ){ + mp->Write(short(d & 0x0001 ? 1100 : 1300), 30); + d = d >> 1; + } + } + else { + for( i = 0; i < 8; i++ ){ + mp->Write(short(d & 0x0001 ? 1100 : 1300), 30); + d = d >> 1; + } + } + mp->Write(1200, 30); + } + if( SSTVSET.m_TxMode == smAVT ){ // 同期信号 + int sd = 0x5fa0; + for( i = 0; i < 32; i++ ){ + mp->Write(1900, 9.7646); + d = sd; + for( n = 0; n < 16; n++ ){ + mp->Write(short(d & 0x8000 ? 1600 : 2200), 9.7646); + d = d << 1; + } + sd = ((sd & 0xff00) - 0x0100) | ((sd & 0x00ff) + 0x0001); + } + mp->Write(0, 0.30514375); + } + else if( (SSTVSET.m_TxMode == smSCT1) || (SSTVSET.m_TxMode == smSCT2) || (SSTVSET.m_TxMode == smSCTDX) ){ + mp->Write(1200, 9.0); + } + } + mp->m_sCnt = mp->m_Cnt; + SendSSTV(); + if( pRadio != NULL ) pRadio->SetPTT(1); + if( pComm != NULL ){ + pComm->SetPTT(1); + pComm->SetScan(pDem->m_Sync); + } + LogLink.SetPTT(1); + ::Sleep(10); // 10msのウエイト + pSound->m_ReqTx = 1; + pMod->m_tune = 0; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::ToRX(void) +{ + CWaitCursor w; + + m_TuneTimer = 0; + CSSTVDEM *dp = pDem; + if( sys.m_Repeater ){ + if( dp->m_repmode >= 6 ){ + dp->m_repmode = 0; + } + SetBeaconTick(); + } + if( (dp->m_LoopBack == 1 ) && dp->m_Sync && +// (pDem->m_rBase < (SSTVSET.m_LM * 90/100)) ){ + (m_AY < (SSTVSET.m_L * 90/100)) ){ + dp->Stop(); + dp->m_SyncMode = 0; + } + pSound->m_ReqTx = 0; + int tout = (pSound->m_BuffSize * pSound->m_FifoSizeTX * 10) / SSTVSET.m_TxSampFreq; + tout += 10; + int lost = pDem->m_Lost; + for( int i = 0; i < tout; i++ ){ + if( !pSound->m_Tx ) break; + DrawSSTV(); + ::Sleep(100); + } + if( !lost ) pDem->m_Lost = 0; + pMod->SetRow(NULL, 0); + if( m_pRowBuf != NULL ){ + delete m_pRowBuf; + m_pRowBuf = NULL; + } + if( !sys.m_echo ){ + pDem->OpenCloseRxBuff(); + } + pMod->m_tune = 0; + if( pRadio != NULL ) pRadio->SetPTT(0); + if( pComm != NULL ){ + pComm->SetScan(dp->m_Sync); + pComm->SetPTT(0); + } + LogLink.SetPTT(0); + SBTX->Down = 0; + SBTune->Down = 0; + UpdateTXUI(); + DeleteTXCursor(); + pMod->CloseTXBuf(); + UpdateSBTO(); + UpdateModeBtn(); + UpdateUI(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SBTXClick(TObject *Sender) +{ + if( SBTX->Down ){ + ToTX(); + } + else { + ToRX(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SBTuneClick(TObject *Sender) +{ + if( SBTune->Down ){ + SBCW->Enabled = FALSE; + if( pRadio != NULL ) pRadio->SetPTT(1); + if( pComm != NULL ) pComm->SetPTT(1); + LogLink.SetPTT(1); + pMod->m_tune = 1; + pSound->m_ReqTx = 1; + for( int i = 0; i < 20; i++ ){ + if( pSound->m_Tx ) break; + ::Sleep(100); + } + m_TuneTimer = ::GetTickCount(); + if( sys.m_TuneTXTime >= 0 ){ + m_TuneTimer += sys.m_TuneTXTime * 1000; + } + else { + m_TuneTimer += 30 * 1000; + } + } + else { + ToRX(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SBCWClick(TObject *Sender) +{ + if( SBCW->Down ){ + SendCWID(sys.m_CWText.c_str()); + Application->ProcessMessages(); + SBCW->Down = FALSE; + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::DrawTXCursor_(int y) +{ + if( m_MainPage != pgTX ) return; + + PBoxTX->Canvas->MoveTo(0, y); + int Sop = ::SetROP2(PBoxTX->Canvas->Handle, R2_NOT); + PBoxTX->Canvas->LineTo(320, y); + ::SetROP2(PBoxTX->Canvas->Handle, Sop); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::DrawTXCursor(int y) +{ + if( m_SendY == -1 ){ + PBoxTXPaint(NULL); + } + if( y != m_SendY ){ + DeleteTXCursor(); + m_SendY = y; + DrawTXCursor_(m_SendY); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::DeleteTXCursor(void) +{ + if( m_SendY >= 0 ){ + DrawTXCursor_(m_SendY); + m_SendY = -1; + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::PageChange(TObject *Sender) +{ + m_MainPage = GetActiveIndex(Page); + MultProc(); + m_TempHold = 0; + UpdateModeBtn(); + if( (m_MainPage == pgTX) && (!SBTX->Down) ){ + MultProc(); + UpdateTemp(); + MakeTxBitmap(0); + } + if( m_MainPage == pgTemp ) UpdateUITemp(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::UpdateTxClip(void) +{ + switch(m_TxClipType){ + case 0: + SBDS240->Down = FALSE; + SBUS240->Down = FALSE; + SBDA240->Down = FALSE; + SBUA240->Down = FALSE; + break; + case 1: // DS + SBDS240->Down = TRUE; + break; + case 2: // US + SBUS240->Down = TRUE; + break; + case 3: // DA + SBDA240->Down = TRUE; + break; + case 4: // UA + SBUA240->Down = TRUE; + break; + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SBDS240Click(TObject *Sender) +{ + m_TxClipType = SBDS240->Down ? 1 : 0; + UpdatePic(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SBUS240Click(TObject *Sender) +{ + m_TxClipType = SBUS240->Down ? 2 : 0; + UpdatePic(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SBDA240Click(TObject *Sender) +{ + m_TxClipType = SBDA240->Down ? 3 : 0; + UpdatePic(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SBUA240Click(TObject *Sender) +{ + m_TxClipType = SBUA240->Down ? 4 : 0; + UpdatePic(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::MakeTxBitmap(int sw) +{ + if( !sw && pSound->m_Tx && !SBTune->Down ) return; + CWaitCursor wait; + + int sf = pBitmapTX->Width != pBitmapTemp->Width ? 1 : 0; + int Sop; + FillBitmap(pBitmapTX, sys.m_PicClipColor); + TRect rc; + int rep = 0; + if( sys.m_Repeater && pDem->m_Repeater ){ + rep = 1; + } + switch(m_TxClipType){ + case 0: +_n1:; + pBitmapTX->Canvas->Draw(0, 0, pBitmapTXM); + break; + case 1: // DS + if( rep ) goto _n1; + pBitmapTX->Canvas->Draw(0, 16, pBitmapTXM); + break; + case 2: // US + if( sf || rep ) goto _n1; + pBitmapTX->Canvas->Draw(0, -16, pBitmapTXM); + break; + case 3: // DA + if( rep ) goto _n1; + rc.Left = 0; rc.Right = pBitmapTX->Width; + rc.Top = 16; rc.Bottom = pBitmapTX->Height; + Sop = ::SetStretchBltMode(pBitmapTX->Canvas->Handle, HALFTONE); + pBitmapTX->Canvas->StretchDraw(rc, pBitmapTXM); + ::SetStretchBltMode(pBitmapTX->Canvas->Handle, Sop); + break; + case 4: // UA + if( sf || rep ) goto _n1; + rc.Left = 0; rc.Right = pBitmapTX->Width; + rc.Top = 0; rc.Bottom = pBitmapTX->Height - 16; + Sop = ::SetStretchBltMode(pBitmapTX->Canvas->Handle, HALFTONE); + pBitmapTX->Canvas->StretchDraw(rc, pBitmapTXM); + ::SetStretchBltMode(pBitmapTX->Canvas->Handle, Sop); + break; + } + if( SBUseTemp->Down || (m_MainPage == pgTemp) ){ + pBitmapTemp->Transparent = TRUE; + pBitmapTemp->TransparentMode = tmFixed; + pBitmapTemp->TransparentColor = pBitmapTemp->Canvas->Pixels[DrawMain.m_TransX][DrawMain.m_TransY]; + if( rep && sys.m_RepBottomAdj ){ // 伸縮なし + DrawMain.FillPic(pBitmapTX->Canvas, pBitmapTemp->TransparentColor, -1, 1.0, 1.0, m_TXPH - pBitmapTemp->Height); + pBitmapTX->Canvas->Draw(0, m_TXPH - pBitmapTemp->Height, pBitmapTemp); + } + else { + DrawMain.FillPic(pBitmapTX->Canvas, pBitmapTemp->TransparentColor, m_TxClipType, double(m_TXW)/double(DrawMain.m_SX), double(m_TXH)/double(DrawMain.m_SY), 0); + switch(m_TxClipType){ + case 2: + if( sf ) goto _n2; + pBitmapTX->Canvas->Draw(0, -16, pBitmapTemp); + break; + case 4: + if( sf ) goto _n2; + rc.Left = 0; rc.Right = pBitmapTX->Width; + rc.Top = 0; rc.Bottom = pBitmapTX->Height - 16; + Sop = ::SetStretchBltMode(pBitmapTX->Canvas->Handle, HALFTONE); + pBitmapTX->Canvas->StretchDraw(rc, pBitmapTemp); + ::SetStretchBltMode(pBitmapTX->Canvas->Handle, Sop); + break; + default: +_n2:; + if( sf ){ + StretchCopy(pBitmapTX, pBitmapTemp, HALFTONE); + } + else { + pBitmapTX->Canvas->Draw(0, 0, pBitmapTemp); + } + break; + } + } + pBitmapTemp->Transparent = FALSE; + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SBUseTempClick(TObject *Sender) +{ + if( pSound->m_Tx && !SBTune->Down && !SBUseTemp->Down ){ + SBUseTemp->Down = TRUE; + } + if( m_ReqHistF ) AdjustHistF(); + UpdateTemp(); + MakeTxBitmap(1); + PBoxTXPaint(NULL); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KOSCClick(TObject *Sender) +{ + if( pSound == NULL ) return; + TTScope *pBox = new TTScope(this); + pBox->Execute(pDem); + delete pBox; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KOLClick(TObject *Sender) +{ + TLogSetDlg *pBox = new TLogSetDlg(this); + pBox->Execute(); + delete pBox; + UpdateLogLink(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::InfoSampFreq(void) +{ + if( fabs(sys.m_SampFreq - SampFreq) >= 50.0 ){ + if( (pSound != NULL) && (sys.m_SampFreq > (SampFreq * 1100/1060)) ){ + pDem->Start(smSCT1, 0); + UpdateModeBtn(); + GBMode->Enabled = FALSE; + } + InfoMB( + MsgEng ? + "Restart MMSSTV for the new sampling rate.\r\n(Does not have to restart your PC)\r\n\r\n" + "Now MMSSTV is running on %.2lfHz, and was requested to change to %.2lfHz." + " This difference are too large for the DSP of MMSSTV." : + "新しいサンプリングレートを適用します。MMSSTVを再起動して下さい\r\n" + "(パソコンを再起動する必要はありません)\r\n\r\n" + "現在MMSSTVは%.2lfHzで動作しており、%.2lfHzへの変更を要請されています。" + " 再起動しないと正常な動作を維持することができません。" + , SampFreq, sys.m_SampFreq + ); + } + else { + GBMode->Enabled = TRUE; + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KOMClick(TObject *Sender) +{ + TOptionDlg *pBox = new TOptionDlg(this); + int stereo = sys.m_SoundStereo; + int stereoTX = sys.m_StereoTX; + int fontadj = sys.m_FontAdjSize; + int cal = sys.m_DemCalibration; + int AppPriority = sys.m_Priority; + AnsiString DevID = sys.m_SoundDevice; + AnsiString MMW = sys.m_SoundMMW; + if( Sender == NULL ) pBox->SetPageIndex(1); + if( pBox->Execute(pDem, pMod) == TRUE ){ + if( cal != sys.m_DemCalibration ) MakeCalibrationTable(); + if( (sys.m_UseRxBuff == 2) && !WaveStg.IsOpen() ) WaveStg.Open(); + if( (sys.m_UseRxBuff != 2) && WaveStg.IsOpen() ) WaveStg.Close(); + + if( !SBTX->Down ){ + pMod->m_vco.SetSampleFreq(sys.m_SampFreq + sys.m_TxSampOff); + } + UpdateSystemFont(); + InitColorTable(sys.m_ColorLow, sys.m_ColorHigh); + if( (pSound->m_FifoSizeTX != sys.m_SoundFifoTX) || + (pSound->m_FifoSizeRX != sys.m_SoundFifoRX) || + (DevID != sys.m_SoundDevice) || + (MMW != sys.m_SoundMMW) || + (stereo != sys.m_SoundStereo) || + (stereoTX != sys.m_StereoTX) ){ +// pSound->m_IDDevice = sys.m_SoundDevice; + pSound->InitSound(); + } + DispSyncStat(); + InfoSampFreq(); + UpdateTitle(); + if( sys.m_HistMax != RxHist.m_Head.m_Max ){ + RxHist.ChangeMax(sys.m_HistMax); + m_DisEvent++; + UDHist->Position = 0; + UpdateHist(); + m_DisEvent--; + } + if( fontadj != sys.m_FontAdjSize ){ + FormResize(NULL); + } + SBRXID->Down = pDem->m_fskdecode; + SBTXID->Down = sys.m_TXFSKID; + if( AppPriority != sys.m_Priority ) UpdatePriority(); + } + if( COMM.change || RADIO.change ){ + OpenCloseCom(); + } + delete pBox; + UpdateModeBtn(); + UpdateUI(); + if( pCtrBtn != NULL ) pCtrBtn->UpdateBtn(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::OpenCloseCom(void) +{ + if( pComm != NULL ){ + delete pComm; + pComm = NULL; + } + if( pRadio != NULL ){ + delete pRadio; + pRadio = NULL; + } + if( strcmpi(sys.m_TxRxName.c_str(), "NONE") ){ + pComm = new CComm(); + pComm->Open(sys.m_TxRxName.c_str()); + if( !pComm->IsOpen() ){ + if( sys.m_TxRxLock ){ + delete pComm; + pComm = NULL; + ErrorMB( "Could not open '%s' for the PTT controls", sys.m_TxRxName.c_str()); + } + } + if( pComm != NULL ){ + pComm->SetPTT(SBTX->Down); + pComm->SetScan(pDem->m_Sync); + } +// if( !sys.m_TxRxLock ) pComm->Close(); + } + RADIO.change = 0; + if( strcmp(RADIO.StrPort, "NONE" ) ){ + pRadio = new CCradio(TRUE); + pRadio->Open(&RADIO, Handle, CM_CMMR, CM_CRADIO); + if( pRadio->m_CreateON != TRUE ){ + delete pRadio; + pRadio = NULL; + ErrorMB( MsgEng ? "Could not open '%s' for Radio commands":"Radioコマンドポート'%s'がオープンできません.", RADIO.StrPort); + } + else { + pRadio->SendCommand(RADIO.CmdInit.c_str()); + if( RADIO.PollScan ){ + m_DisEvent++; + LogFreq->Text = "???"; + m_DisEvent--; + RADIO.Cmdxx = 0x00; + pRadio->m_ScanAddr = 1; + } + } + } + RADIO.change = COMM.change = 0; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KExitClick(TObject *Sender) +{ + Close(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SBListClick(TObject *Sender) +{ + TLogListDlg *pBox = new TLogListDlg(this); + MultProc(); + pBox->Execute(); +// Application->OnIdle = NULL; + delete pBox; + AutoLogSave(); + UpdateLogLink(); + UpdateTitle(); + AdjustFocus(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::UpdateCallsign(void) +{ + if( HisCall->Text.IsEmpty() ) m_Dupe = 0; + HisCall->Font->Color = m_Dupe ? clRed : clBlack; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::UpdateLogData(void) +{ + StrCopy(Log.m_sd.call, AnsiString(HisCall->Text).c_str(), MLCALL); //ja7ude 0428 + clipsp(Log.m_sd.call); + jstrupr(Log.m_sd.call); + StrCopy(Log.m_sd.name, AnsiString(HisName->Text).c_str(), MLNAME); //ja7ude 0428 + StrCopy(Log.m_sd.qth, AnsiString(HisQTH->Text).c_str(), MLQTH); //ja7ude 0428 + StrCopy(Log.m_sd.my, AnsiString(MyRST->Text).c_str(), MLRST); //ja7ude 0428 + jstrupr(Log.m_sd.my); + StrCopy(Log.m_sd.ur, AnsiString(HisRST->Text).c_str(), MLRST); //ja7ude 0428 + jstrupr(Log.m_sd.ur); + StrCopy(Log.m_sd.rem, AnsiString(EditNote->Text).c_str(), MLREM); //ja7ude 0428 + StrCopy(Log.m_sd.qsl, AnsiString(EditQSL->Text).c_str(), MLQSL); //ja7ude 0428 + Log.SetFreq(&Log.m_sd, AnsiString(LogFreq->Text).c_str()); //ja7ude 0428 +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::UpdateTextData(void) +{ + HisCall->Text = Log.m_sd.call; + HisName->Text = Log.m_sd.name; + HisQTH->Text = Log.m_sd.qth; + HisRST->Text = Log.m_sd.ur; + MyRST->Text = Log.m_sd.my; + EditNote->Text = Log.m_sd.rem; + EditQSL->Text = Log.m_sd.qsl; + LogFreq->Text = Log.GetFreqString(Log.m_sd.band, Log.m_sd.fq); + Log.m_CurChg = 0; + UpdateUI(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::FindCall(void) +{ + CWaitCursor w; + m_Dupe = 0; + StrCopy(Log.m_sd.call, AnsiString(HisCall->Text).c_str(), MLCALL); //ja7ude 0428 + clipsp(Log.m_sd.call); + + if( IsCall(Log.m_sd.call) ) AddCall(Log.m_sd.call); + + AnsiString His = HisRST->Text; + if( Log.FindSet(&Log.m_Find, Log.m_sd.call) ){ // 見つかった時 + MultProc(); + Log.SetFreq(&Log.m_sd, AnsiString(LogFreq->Text).c_str()); //ja7ude 0428 + SDMMLOG sd; + Log.GetData(&sd, Log.m_Find.pFindTbl[0]); // 一番最新のデータ + if( Log.m_Find.m_FindCmp1Max ){ + switch(Log.m_LogSet.m_CheckBand){ + case 1: + if( Log.FindSameBand() ) m_Dupe = 1; + break; + case 2: + if( Log.FindSameDate() ) m_Dupe = 1; + break; + default: + m_Dupe = 1; + break; + } + } +#if 0 + if( Log.m_Find.m_FindCmp1Max && ((!Log.m_LogSet.m_CheckBand) || Log.FindSameBand()) ){ + m_Dupe = 1; + } + else { + m_Dupe = 0; + } +#endif + if( (!SBQSO->Down || !Log.m_sd.name[0] ) && Log.m_LogSet.m_CopyName ) strcpy(Log.m_sd.name, sd.name); + if( (!SBQSO->Down || !Log.m_sd.qth[0] ) && Log.m_LogSet.m_CopyQTH ) strcpy(Log.m_sd.qth, sd.qth); + if( (!SBQSO->Down || !Log.m_sd.rem[0] ) && Log.m_LogSet.m_CopyREM ) strcpy(Log.m_sd.rem, sd.rem); + if( (!SBQSO->Down || !Log.m_sd.qsl[0] ) && Log.m_LogSet.m_CopyQSL ) strcpy(Log.m_sd.qsl, sd.qsl); + UpdateTextData(); + if( SBQSO->Down ){ + Log.m_Find.Ins(Log.m_CurNo); + UpdateTextData(); + Log.PutData(&Log.m_sd, Log.m_CurNo); + } + } + else { // 見つからなかった時 + if( !SBQSO->Down && Log.m_LogSet.m_CopyName ) Log.m_sd.name[0] = 0; + if( !SBQSO->Down && Log.m_LogSet.m_CopyQTH ) Log.m_sd.qth[0] = 0; + if( !SBQSO->Down && Log.m_LogSet.m_CopyREM ) Log.m_sd.rem[0] = 0; + if( !SBQSO->Down && Log.m_LogSet.m_CopyQSL ) Log.m_sd.qsl[0] = 0; + UpdateTextData(); + } + LPCSTR pCC = ClipCC(Log.m_sd.call); + Log.SetOptStr(0, &Log.m_sd, Cty.GetCountry(pCC)); + Log.SetOptStr(1, &Log.m_sd, Cty.GetCont(pCC)); + if( !His.IsEmpty() ) HisRST->Text = His; + UpdateCallsign(); + UpdateUI(); + if( !SBQSO->Down ){ + LogLink.SetMode("SSTV"); + LogLink.SetFreq(AnsiString(LogFreq->Text).c_str()); //ja7ude 0428 + LogLink.FindCall(Log.m_sd.call); + } + else { + LogLink.Write(&Log.m_sd, 1); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SBFindClick(TObject *Sender) +{ + if( !Log.IsOpen() ){ + if( Log.Open(NULL, TRUE) == FALSE ){ + UpdateUI(); + return; + } + } + FindCall(); + TQSODlgBox *pBox = new TQSODlgBox(this); + pBox->ShowFind(&Log.m_Find); + delete pBox; + AutoLogSave(); + TopWindow(this); + UpdateUI(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SBFindMouseDown(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( Button == mbRight ){ + AnsiString as; + if( InputMB("MMSSTV", "Callsign", as) == TRUE ){ + jstrupr(as.c_str()); + CLogFind find; + Log.FindSet(&find, as.c_str() ); + TQSODlgBox *pBox = new TQSODlgBox(this); + pBox->ShowFind(&find); + delete pBox; + TopWindow(this); + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SBDataClick(TObject *Sender) +{ + SDMMLOG sd; + + UpdateLogData(); + if( strcmp(Log.m_Find.GetText(), Log.m_sd.call) ){ + CWaitCursor w; + Log.FindSet(&Log.m_Find, Log.m_sd.call); + } + TQSODlgBox *pBox = new TQSODlgBox(this); + MultProc(); + memcpy(&sd, &Log.m_sd, sizeof(sd)); + if( pBox->Execute(&Log.m_Find, &Log.m_sd, Log.m_CurNo) == TRUE ){ + if( memcmp(&sd, &Log.m_sd, sizeof(sd)) ){ + AdjustFocus(); + UpdateTextData(); + HisCallChange(NULL); + LogLink.Write(&Log.m_sd, 0); + } + } + delete pBox; + TopWindow(this); + AdjustFocus(); + UpdateUI(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SBDataMouseDown(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( Button == mbRight ){ + int n = Log.m_CurNo - 1; + if( n < 0 ){ + SBDataClick(NULL); + return; + } + + TQSODlgBox *pBox = new TQSODlgBox(this); + SDMMLOG sd; + Log.GetData(&sd, n); + CLogFind Find; + + Log.FindSet(&Find, sd.call); + + pBox->Execute(&Find, &sd, n); + delete pBox; + TopWindow(this); + if( !SBQSO->Down && Log.m_CurNo && Log.IsEdit() ){ + Log.SetLastPos(); + UpdateTextData(); + } + AutoLogSave(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SBInitClick(TObject *Sender) +{ + AdjustFocus(); + AnsiString as = LogFreq->Text; + if( SBQSO->Down ){ + Log.DeleteLast(); + Log.m_Find.Clear(); + Log.InitCur(); + SBQSO->Down = FALSE; + UpdateTextData(); + } + else { + Log.InitCur(); + Log.m_sd.call[0] = 0; + Log.m_sd.name[0] = 0; + Log.m_sd.qth[0] = 0; + UpdateTextData(); + UpdateCallsign(); + } + if( !as.IsEmpty() ){ + LogFreq->Text = as; + Log.SetFreq(&Log.m_sd, as.c_str()); + } + HisCallChange(NULL); + LogLink.Clear(); + if( HisCall->CanFocus() ) HisCall->SetFocus(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::TempDelay(void) +{ + int delay; + switch(sys.m_TempDelay){ + case 0: + delay = 500; + break; + case 1: + delay = 1000; + break; + case 2: + delay = 2000; + break; + default: + delay = 3000; + break; + } + m_ChangeTemp = delay / Timer->Interval; +} +//--------------------------------------------------------------------------- +// バンドの変更 +void __fastcall TMmsstv::LogFreqChange(TObject *Sender) +{ + if( m_DisEvent ) return; + + Log.SetFreq(&Log.m_sd, AnsiString(LogFreq->Text).c_str()); //ja7ude 0428 + LogLink.SetFreq(AnsiString(LogFreq->Text).c_str()); //ja7ude 0428 +#if 0 + if( !HisCall->Text.IsEmpty() ){ + FindCall(); + } +#endif + if( DrawMain.IsMacro("%b") || DrawMain.IsMacro("%B") ){ + TempDelay(); + SBULog->Enabled = TRUE; + UpdateUI(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::HisCallKeyPress(TObject *Sender, char &Key) +{ + if( Key == VK_RETURN ){ + Key = 0; + } + else { + Key = char(toupper(Key)); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::HisNameKeyPress(TObject *Sender, char &Key) +{ + if( Key == VK_RETURN ){ + Key = 0; + if( (Sender == HisQTH) && IsJA(AnsiString(HisCall->Text).c_str()) ){ + TMmcgDlgBox *pBox = new TMmcgDlgBox(this); + + AnsiString qth = HisQTH->Text; + AnsiString opt = Log.m_sd.opt1; + AnsiString hc = HisCall->Text; + if( pBox->Execute(hc, qth, opt) == TRUE ){ //ja7ude 0521 + HisQTH->Text = qth; + StrCopy(Log.m_sd.opt1, opt.c_str(), MLOPT); + } + delete pBox; + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SBQSOClick(TObject *Sender) +{ + UpdateLogData(); + SYSTEMTIME now; + GetUTC(&now); + int Year = now.wYear % 100; + int Month = now.wMonth; + int Day = now.wDay; + int Hour = now.wHour; + UTCtoJST(Year, Month, Day, Hour); + +// Log.m_sd.cq = m_Running ? 'A' : 'C'; + if( SBQSO->Down ){ // Start QSO + LogLink.SetTime(&now, 0); + Log.m_sd.year = char(Year % 100); + Log.m_sd.date = WORD(Month * 100 + Day); + Log.m_sd.btime = WORD((Hour * 60 + now.wMinute) * 30 + now.wSecond/2); + if( !Log.m_sd.btime ) Log.m_sd.btime++; + CWaitCursor w; + if( Log.FindSet(&Log.m_Find, Log.m_sd.call) ){ + MultProc(); + SDMMLOG sd; + Log.GetData(&sd, Log.m_Find.pFindTbl[0]); // 一番最新のデータ + if( !Log.m_sd.name[0] && Log.m_LogSet.m_CopyName ) strcpy(Log.m_sd.name, sd.name); + if( !Log.m_sd.qth[0] && Log.m_LogSet.m_CopyQTH ) strcpy(Log.m_sd.qth, sd.qth); + if( !Log.m_sd.rem[0] && Log.m_LogSet.m_CopyREM ) strcpy(Log.m_sd.rem, sd.rem); + if( !Log.m_sd.qsl[0] && Log.m_LogSet.m_CopyQSL ) strcpy(Log.m_sd.qsl, sd.qsl); + } + Log.CopyAF(); + if( Log.m_sd.call[0] ){ + LPCSTR pCC = ClipCC(Log.m_sd.call); + Log.SetOptStr(0, &Log.m_sd, Cty.GetCountry(pCC)); + Log.SetOptStr(1, &Log.m_sd, Cty.GetCont(pCC)); + } + UpdateTextData(); + if( Log.PutData(&Log.m_sd, Log.m_CurNo) == FALSE ){ + SBQSO->Down = FALSE; + } + + if( Log.m_Find.m_FindCmp1Max && ((!Log.m_LogSet.m_CheckBand) || Log.FindSameBand()) ){ + m_Dupe = 1; + } + else { + m_Dupe = 0; + } + Log.m_Find.Ins(Log.m_CurNo); + Log.m_CurChg = 0; + LogLink.Write(&Log.m_sd, 1); + if( HisName->CanFocus() ) HisName->SetFocus(); + } + else { // Finish QSO + LogLink.SetTime(&now, 1); + Log.m_sd.etime = WORD((Hour * 60 + now.wMinute) * 30 + now.wSecond/2); + if( !Log.m_sd.etime ) Log.m_sd.etime++; + if( !Log.m_sd.ur[0] ){ + strcpy(Log.m_sd.ur, "595"); + } + if( !Log.m_sd.my[0] ){ + strcpy(Log.m_sd.my, "595"); + } + Log.PutData(&Log.m_sd, Log.m_CurNo); + LogLink.Write(&Log.m_sd, 2); + + memcpy(&Log.m_asd, &Log.m_sd, sizeof(Log.m_asd)); + Log.m_CurNo++; + Log.m_CurChg = 0; + Log.m_Find.Clear(); + Log.InitCur(); + UpdateTextData(); + AutoLogSave(); + if( HisCall->CanFocus() ) HisCall->SetFocus(); + } + UpdateUI(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::AutoLogSave(void) +{ + if( Log.IsOpen() && Log.m_LogSet.m_AutoSave && Log.IsEdit() ) KLogFlushClick(NULL); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KLogFlushClick(TObject *Sender) +{ + Log.Close(); + Log.Open(NULL, TRUE); + UpdateUI(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KLogOpenClick(TObject *Sender) +{ + OpenDialog->Options >> ofCreatePrompt; + OpenDialog->Options >> ofFileMustExist; + if( MsgEng ){ + OpenDialog->Title = "Open LogData File"; + OpenDialog->Filter = "MMLOG Data Files(*.mdt)|*.mdt|"; + } + else { + OpenDialog->Title = "ログファイルのオープン"; + OpenDialog->Filter = "MMLOGデータファイル(*.mdt)|*.mdt|"; + } + OpenDialog->FileName = ""; + OpenDialog->DefaultExt = "mdt"; + OpenDialog->InitialDir = MMLogDir; + NormalWindow(this); + if( OpenDialogExecute(FALSE) == TRUE ){ + Log.Close(); + Log.DoBackup(); + Log.MakeName(AnsiString(OpenDialog->FileName).c_str()); + Log.Open(NULL, TRUE); + UpdateTextData(); + UpdateTitle(); + } + TopWindow(this); + UpdateUI(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KVerClick(TObject *Sender) +{ + TVerDspDlg *pBox = new TVerDspDlg(this); + pBox->ShowModal(); + delete pBox; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::PBoxTempCursor(int X, int Y) +{ + int cr = crDefault; + if( m_DrawTrans ){ + cr = crCross; + } + else if( m_DrawCmd == CM_SELECT ){ + if( DrawMain.pSel != NULL ){ + switch(DrawMain.pSel->HitTest(X, Y)){ + case HT_LT: + case HT_RB: + cr = crSizeNWSE; + break; + case HT_T: + case HT_B: + cr = crSizeNS; + break; + case HT_RT: + case HT_LB: + cr = crSizeNESW; + break; + case HT_R: + case HT_L: + cr = crSizeWE; + break; + case HT_NONE: + break; + default: + cr = crHandPoint; + break; + } + } + } + else if( m_DrawCmd != -1 ) { + cr = crCross; + } + if( PBoxTemp->Cursor != cr ) PBoxTemp->Cursor = (TCursor)cr; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::AdjustTempSC(int &X, int &Y) +{ + if( ((DrawMain.m_SX != 320) || (DrawMain.m_SY != 320)) ){ + X = X * DrawMain.m_SX / 320; + Y = Y * DrawMain.m_SY / 256; + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::PBoxTempMouseDown(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ +// AdjustFocus(); + if( Button == mbRight ){ + m_TempX = X; + m_TempY = Y; + return; + } + + m_TempHold = 1; + + SetDrawSize(DrawMain.m_SX, DrawMain.m_SY); + AdjustTempSC(X, Y); + if( m_DrawTrans ){ + SaveUndo(); + KTAP->Checked = FALSE; + m_DrawTrans = 0; + DrawMain.m_TransX = X; + DrawMain.m_TransY = Y; + UpdateTemp(); + } + else if( m_DrawCmd == CM_SELECT ){ + m_TempTimer = 2; // 0.4[s] + m_TempX = X; + m_TempY = Y; + CDraw *pSel = DrawMain.pSel; + if( (DrawMain.pSel == NULL) || ((DrawMain.m_Hit = DrawMain.pSel->HitTest(X, Y)) == HT_NONE) ){ + DrawMain.pSel = DrawMain.SelectItem(X, Y); + } + if( pSel != DrawMain.pSel ) UpdateTemp(); + if( DrawMain.pSel != NULL ){ + AdjustTempView(1); + DrawMain.pSel->StartMove(PBoxTemp->Canvas, X, Y, DrawMain.m_Hit); + AdjustTempView(0); + PBoxTempCursor(X, Y); + } +#if 0 + else { + PBoxTemp->BeginDrag(TRUE); + } +#endif + } + else if( m_DrawCmd != CM_TLIST ){ + pDraw = DrawMain.MakeItem(m_DrawCmd); + if( pDraw != NULL ){ + AdjustTempView(1); + pDraw->Start(PBoxTemp->Canvas, X, Y); + AdjustTempView(0); + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::PBoxTempMouseMove(TObject *Sender, + TShiftState Shift, int X, int Y) +{ + AdjustTempSC(X, Y); + + TShiftState sc1, sc2; + sc1 << ssLeft; + sc2 << ssLeft; + sc1 *= Shift; + if( sc1 == sc2 ){ // Left button + AdjustTempView(1); + if( pDraw != NULL ){ // 新規作成中 + pDraw->Making(X, Y); + } + else if( DrawMain.pSel != NULL ){ // 移動/サイズ変更中 + if( !m_TempTimer || (ABS(X-m_TempX)+ABS(Y-m_TempY)) > 5 ){ + m_TempTimer =0; + DrawMain.pSel->Moving(X, Y); + } + } + else if( !PBoxTemp->Dragging() ){ // ドラッグ + //PBoxTemp->BeginDrag(TRUE); + PBoxTemp->BeginDrag(true,0); + } + AdjustTempView(0); + } + else { + PBoxTempCursor(X, Y); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::PBoxTempMouseUp(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( Button == mbRight ) return; + + m_TempHold = 0; + AdjustTempSC(X, Y); + if( pDraw != NULL ){ // アイテム作成中 + if( pDraw->Finish(X, Y) ){ + TMemoryStream *ps = SaveUndo(NULL); + DrawMain.AddItem(pDraw); + DrawMain.pSel = pDraw; + m_DrawCmd = CM_SELECT; + SBDSel->Down = TRUE; + if( (DrawMain.pSel->m_Command == CM_PIC) || (DrawMain.pSel->m_Command == CM_TITLE) ){ + KTBClick(NULL); + } + if( KTAP->Checked ) DrawMain.AdjustTransPoint(); + UpdateUndo(ps); + } + else { + delete pDraw; + } + pDraw = NULL; + UpdateTemp(); + } + else if( m_DrawCmd == CM_TLIST ){ + TListTextDlg *pBox = new TListTextDlg(this); + pDraw = pBox->Execute(&DrawText, 0); + delete pBox; + if( pDraw != NULL ){ + SaveUndo(); + DrawMain.pSel = DrawMain.AddItemCopy(pDraw); + pDraw = DrawMain.pSel; + int xw = pDraw->m_X2 - pDraw->m_X1; + int yw = pDraw->m_Y2 - pDraw->m_Y1; + pDraw->m_X1 = X; + pDraw->m_Y1 = Y; + pDraw->m_X2 = X + xw; + pDraw->m_Y2 = Y + yw; +// TempGrid.Align(pDraw); + pDraw->UpdateText(); + pDraw = NULL; + m_DrawCmd = CM_SELECT; + SBDSel->Down = TRUE; + if( KTAP->Checked ) DrawMain.AdjustTransPoint(); + UpdateTemp(); + } + } + else if( DrawMain.pSel != NULL ){ // 移動/サイズ変更中 + if( DrawMain.pSel->IsMove() && !m_TempTimer ){ + SaveUndo(); + DrawMain.pSel->Move(X, Y); +// TempGrid.Align(DrawMain.pSel); + if( (DrawMain.pSel->m_Command == CM_PIC) && (DrawMain.m_Hit != HT_I) ){ +// DrawMain.pSel->UpdatePic(pBitmapHistF); + TShiftState sc1, sc2; + sc1 << ssShift; + sc2 << ssShift; + sc1 *= Shift; + if( sc1 == sc2 ){ // +Shift key + ((CDrawPic *)DrawMain.pSel)->KeepAspect(); + } + } + if( KTAP->Checked ) DrawMain.AdjustTransPoint(); + UpdateTemp(); + } + } + UpdateUITemp(); + PBoxTempCursor(X, Y); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::DeleteUndo(void) +{ + if( pUndo != NULL ){ + delete pUndo; + pUndo = NULL; + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::UpdateUndo(TMemoryStream *ps) +{ + if( pUndo != ps ){ + if( pUndo != NULL ) delete pUndo; + pUndo = ps; + } +} +//--------------------------------------------------------------------------- +TMemoryStream *__fastcall TMmsstv::SaveUndo(TMemoryStream *ps) +{ + if( ps == NULL ){ + ps = new TMemoryStream; + } + ps->Seek(0, soFromBeginning); + DrawMain.SaveToStream(ps); + return ps; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SaveUndo(void) +{ + pUndo = SaveUndo(pUndo); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::PBoxTempPaint(TObject *Sender) +{ + UpdateTemp(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SBDSelClick(TObject *Sender) +{ + m_DrawCmd = SBDSel->Down ? CM_SELECT : -1; + DrawMain.pSel = NULL; + UpdateTemp(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SBDlineClick(TObject *Sender) +{ + m_DrawCmd = SBDline->Down ? CM_LINE : -1; + DrawMain.pSel = NULL; + UpdateTemp(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SBDBoxClick(TObject *Sender) +{ + m_DrawCmd = SBDBox->Down ? CM_BOX : -1; + DrawMain.pSel = NULL; + UpdateTemp(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SBDBoxSClick(TObject *Sender) +{ + m_DrawCmd = SBDBoxS->Down ? CM_BOXS : -1; + DrawMain.pSel = NULL; + UpdateTemp(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SBDTextClick(TObject *Sender) +{ + m_DrawCmd = SBDText->Down ? CM_TEXT : -1; + DrawMain.pSel = NULL; + UpdateTemp(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SBDPicClick(TObject *Sender) +{ + m_DrawCmd = SBDPic->Down ? CM_PIC : -1; + DrawMain.pSel = NULL; + UpdateTemp(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SBDHeadClick(TObject *Sender) +{ + m_DrawCmd = SBDHead->Down ? CM_TITLE : -1; + DrawMain.pSel = NULL; + UpdateTemp(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SBDListClick(TObject *Sender) +{ + m_DrawCmd = SBDList->Down ? CM_TLIST : -1; + DrawMain.pSel = NULL; + UpdateTemp(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SBDDelClick(TObject *Sender) +{ + if( DrawMain.pSel != NULL ){ + SaveUndo(); + if( pPaste != NULL ){ + delete pPaste; + } + pPaste = DrawMain.pSel; + DrawMain.ReleaseItem(DrawMain.pSel); + DrawMain.pSel = DrawMain.GetLastItem(); + UpdateTemp(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SBDPasteClick(TObject *Sender) +{ + if( pPaste != NULL ){ + SaveUndo(); + DrawMain.pSel = DrawMain.AddItemCopy(pPaste); + UpdateTemp(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KTFXClick(TObject *Sender) +{ +#if 1 + SaveUndo(); + DrawMain.ConvBitmap(DrawMain.pSel); + UpdateTemp(); +#else + if( (DrawMain.pSel != NULL) && (DrawMain.pSel->m_Command == CM_PIC) ){ + SaveUndo(); + CDrawPic *pI = (CDrawPic *)DrawMain.pSel; + pI->m_Type = 1; + UpdateTemp(); + } +#endif +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KTDClick(TObject *Sender) +{ + if( DrawMain.pSel != NULL ){ + SaveUndo(); + DrawMain.ReleaseItem(DrawMain.pSel); + delete DrawMain.pSel; + DrawMain.pSel = NULL; + UpdateTemp(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KTEClick(TObject *Sender) +{ + if( DrawMain.pSel == NULL ) return; + + DrawText.AddItemCopy(DrawMain.pSel); + CDraw *pItem = DrawText.GetLastItem(); + TListTextDlg *pBox = new TListTextDlg(this); + if( pBox->Execute(&DrawText, -1) == NULL ){ + DrawText.DeleteItem(pItem); + } + delete pBox; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KTBClick(TObject *Sender) +{ + if( DrawMain.pSel != NULL ){ + SaveUndo(); + DrawMain.BackItem(DrawMain.pSel); + UpdateTemp(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KTFClick(TObject *Sender) +{ + if( DrawMain.pSel != NULL ){ + SaveUndo(); + DrawMain.FrontItem(DrawMain.pSel); + UpdateTemp(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KTTDClick(TObject *Sender) +{ + InvMenu(KTTD); + UpdateTemp(); +} +//--------------------------------------------------------------------------- +// テンプレート 透過ポイントの指定 +void __fastcall TMmsstv::KTTClick(TObject *Sender) +{ + m_DrawTrans = 1; + UpdateUITemp(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KTTCClick(TObject *Sender) +{ + InitCustomColor(ColorDialog); + AddCustomColor(ColorDialog, DrawMain.m_TransCol); + ColorDialog->Color = DrawMain.m_TransCol; + SetDisPaint(); + if( ColorDialog->Execute() == TRUE ){ + SaveUndo(); + DrawMain.m_TransCol = ColorDialog->Color; +#if 0 + FillBitmap(pBitmapTemp, DrawMain.m_TransCol); + DrawMain.m_TransCol = pBitmapTemp->Canvas->Pixels[0][0]; +#else + DrawMain.m_TransCol = GetNearestColor(DrawMain.m_TransCol); +#endif + DrawMain.UpdateText(); + DrawMain.UpdatePic(pBitmapHistF); + UpdateTemp(); + } + ResDisPaint(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KTMDClick(TObject *Sender) +{ + if( m_DisEvent ) return; + + InvMenu(KTMD); + DrawMain.UpdateText(); + UpdateTemp(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KTBTClick(TObject *Sender) +{ + InvMenu(KTBT); + UpdateTemp(); +} +//--------------------------------------------------------------------------- +// テンプレート のロード +void __fastcall TMmsstv::KTLClick(TObject *Sender) +{ + if( LoadTemplateMenu(&DrawMain, 0) == TRUE ){ + DrawMain.pSel = NULL; + if( !DrawMain.m_Cnt ){ + DrawMain.m_SX = m_TXW; + DrawMain.m_SY = m_TXH; + } + UpdateTemp(); + } +} +//--------------------------------------------------------------------------- +// テンプレート アイテムのロード +void __fastcall TMmsstv::AddTemplate(CDrawGroup *pGroup) +{ + SaveUndo(); + CDraw *pItem = NULL; + while(pGroup->m_Cnt){ + pItem = pGroup->pBase[0]; + DrawMain.AddItem(pItem); + pGroup->ReleaseItem(pItem); + MultProc(); + } + if( pItem != NULL ){ + DrawMain.pSel = pItem; + } + pGroup->FreeItem(); +} +//--------------------------------------------------------------------------- +// テンプレート アイテムのロード +void __fastcall TMmsstv::KTLIClick(TObject *Sender) +{ + if( LoadTemplateMenu(&DrawTemp, 1) == TRUE ){ + AddTemplate(&DrawTemp); + UpdateTemp(); + } + MultProc(); + DrawTemp.FreeItem(); +} +//--------------------------------------------------------------------------- +// テンプレート 全部のセーブ +void __fastcall TMmsstv::KTSAClick(TObject *Sender) +{ + SaveTemplateMenu(&DrawMain, 0); +} +//--------------------------------------------------------------------------- +// テンプレート アイテムのセーブ +void __fastcall TMmsstv::KTSIClick(TObject *Sender) +{ + if( DrawMain.pSel != NULL ){ + DrawTemp.m_TransCol = DrawMain.m_TransCol; + DrawTemp.AddItemCopy(DrawMain.pSel); + SaveTemplateMenu(&DrawTemp, 1); + DrawTemp.FreeItem(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KTAClick(TObject *Sender) +{ + DrawMain.FreeItem(); + DrawMain.m_SX = m_TXW; + DrawMain.m_SY = m_TXH; + UpdateTemp(); +} +//--------------------------------------------------------------------------- +// テンプレート画面のUI更新処理 +void __fastcall TMmsstv::UpdateUITemp(void) +{ + int cmd = DrawMain.pSel != NULL ? DrawMain.pSel->m_Command : 0; + SBDDel->Enabled = cmd; + SBDPaste->Enabled = pPaste != NULL; + SBDFont->Enabled = (cmd == CM_TEXT) || ((cmd == CM_LIB)&&((((CDrawLib *)DrawMain.pSel)->m_Type & 0x0003)==2) ); + SBDCol->Enabled = cmd; + if( cmd && (cmd != CM_TITLE) ){ + if( ( (cmd == CM_TEXT) && (((CDrawText *)DrawMain.pSel)->m_Shadow != 1)&&(((CDrawText *)DrawMain.pSel)->m_Shadow != 6) )|| + ((cmd == CM_PIC) && (((CDrawPic *)DrawMain.pSel)->m_Type == 2)) + ){ + SBDLineset->Enabled = FALSE; + } + else { + SBDLineset->Enabled = TRUE; + } + } + else { + SBDLineset->Enabled = FALSE; + } + TDragMode dm; + if( ((m_DrawCmd != -1) || m_DrawTrans) ){ + dm = dmManual; + } + else { + dm = dmAutomatic; + } + if( PBoxTemp->DragMode != dm ) PBoxTemp->DragMode = dm; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::AdjustTempView(int sw) +{ + if( pBitmapTemp->Width == 320 ) return; + if( sw ){ + ::SetMapMode(PBoxTemp->Canvas->Handle, MM_ANISOTROPIC); + ::SetWindowExtEx(PBoxTemp->Canvas->Handle, pBitmapTemp->Width, pBitmapTemp->Height, NULL); + ::SetViewportExtEx(PBoxTemp->Canvas->Handle, 320, 256, NULL); + } + else { + ::SetMapMode(PBoxTemp->Canvas->Handle, MM_TEXT); + ::SetWindowExtEx(PBoxTemp->Canvas->Handle, 320, 256, NULL); + ::SetViewportExtEx(PBoxTemp->Canvas->Handle, 320, 256, NULL); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::UpdateTemp(void) +{ + if( (pBitmapTemp->Width != DrawMain.m_SX)||(pBitmapTemp->Height != DrawMain.m_SY) ){ + pBitmapTemp->Width = DrawMain.m_SX; + pBitmapTemp->Height = DrawMain.m_SY; + } + TRect rc; + rc.Left = 0; + rc.Top = 0; + rc.Right = pBitmapTemp->Width; + rc.Bottom = pBitmapTemp->Height; + pBitmapTemp->Canvas->Brush->Style = bsSolid; + pBitmapTemp->Canvas->Brush->Color = DrawMain.m_TransCol; + pBitmapTemp->Canvas->Pen->Color = DrawMain.m_TransCol; + pBitmapTemp->Canvas->FillRect(rc); + + MultProc(); + if( m_ChangeTemp ){ + DrawMain.UpdateText(); + m_ChangeTemp = 0; + SBULog->Enabled = FALSE; + } + else { + DrawMain.UpdateTimeText(); + } + MultProc(); +// DrawMain.UpdatePic(pBitmapHistF); + if( KTAP->Checked ) DrawMain.AdjustTransPoint(); + if( m_MainPage == pgTemp ){ + DrawMain.DrawNotSel(pBitmapTemp->Canvas); + if( DrawMain.pSel != NULL ) DrawMain.pSel->DrawSel(pBitmapTemp->Canvas, 0); + } + else { + DrawMain.Draw(pBitmapTemp->Canvas); + } + MultProc(); + if( KTBT->Checked && !SBTX->Down ){ + int sv = m_TxClipType; + if( (m_TxClipType == 4) || (m_TxClipType == 2) ) m_TxClipType = 0; + MakeTxBitmap(0); + m_TxClipType = sv; + DrawBitmap(PBoxTemp, pBitmapTX); + if( DrawMain.pSel != NULL ){ + AdjustTempView(1); + DrawMain.pSel->DrawSel(PBoxTemp->Canvas, KTBT->Checked); + AdjustTempView(0); + } + } + else { + DrawBitmap(PBoxTemp, pBitmapTemp); +// PBoxTemp->Canvas->Draw(0, 0, pBitmapTemp); + } + + MultProc(); + rc.Right = PBoxTemp->Width; + rc.Bottom = PBoxTemp->Height; + PBoxTemp->Canvas->Brush->Color = clGreen; + PBoxTemp->Canvas->FrameRect(rc); + if( KTTD->Checked ){ + AdjustTempView(1); + DrawMain.DrawTrans(PBoxTemp->Canvas); + AdjustTempView(0); + } +#if 0 + if( m_MainPage == pgTemp ){ + TempGrid.Draw(PBoxTemp->Canvas, DrawMain.m_SX, DrawMain.m_SY); + } +#endif + if( sys.m_ShowSizeTemp ){ + TColor col = (DrawMain.m_SX != pBitmapTXM->Width) ? clRed : clGreen; + ShowSize(PBoxTemp, DrawMain.m_SX, DrawMain.m_SY, 12, col); + } + UpdateUITemp(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SBULogClick(TObject *Sender) +{ + if( m_ReqHistF ) AdjustHistF(); + UpdatePic(1); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::UpdatePic(void) +{ + UpdatePic(0); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::UpdatePic(int sw) +{ + if( m_MainPage == pgHist ){ + PBoxHist->Invalidate(); + } + UpdateTemp(); + MakeTxBitmap(sw); + PBoxTXPaint(NULL); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::PBoxTempDblClick(TObject *Sender) +{ + if( DrawMain.pSel != NULL ){ + TMemoryStream *sp = SaveUndo(NULL); + if( DrawMain.pSel->Edit() == TRUE ){ + if( KTAP->Checked ) DrawMain.AdjustTransPoint(); + UpdateTemp(); + UpdateUndo(sp); + } + else { + delete sp; + } + } + if( PBoxTemp->Dragging() ) PBoxTemp->EndDrag(FALSE); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SBDFontClick(TObject *Sender) +{ + if( DrawMain.pSel != NULL ){ + if( DrawMain.pSel->m_Command == CM_TEXT ){ + CDrawText *pText = (CDrawText *)(DrawMain.pSel); + FontDialog->Font->Assign(pText->pFont); + FontDialog->Font->Color = pText->m_Col1; + SetDisPaint(); + TMemoryStream *sp = SaveUndo(NULL); + if( FontDialog->Execute() == TRUE ){ + pText->m_Col1 = FontDialog->Font->Color; + pText->UpdateFont(FontDialog->Font); + if( KTAP->Checked ) DrawMain.AdjustTransPoint(); + UpdateTemp(); + UpdateUndo(sp); + } + else { + delete sp; + } + ResDisPaint(); + } + else if( DrawMain.pSel->m_Command == CM_LIB ){ + CDrawLib *pLib = (CDrawLib *)DrawMain.pSel; + TMemoryStream *sp = SaveUndo(NULL); + if( pLib->Font() ){ + UpdateTemp(); + UpdateUndo(sp); + } + else { + delete sp; + } + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SBDLinesetClick(TObject *Sender) +{ + if( DrawMain.pSel != NULL ){ + TMemoryStream *sp = SaveUndo(NULL); + if( DrawMain.pSel->CDraw::Edit() == TRUE ){ + if( DrawMain.pSel->m_Command == CM_TEXT ){ + DrawMain.pSel->UpdateText(); + } + else if( DrawMain.pSel->m_Command == CM_PIC ){ + CDrawPic *pPic = (CDrawPic *)DrawMain.pSel; + if( pPic->m_Shape != 5 ){ + sys.m_PicLineStyle = pPic->m_LineStyle; + sys.m_PicLineColor = pPic->m_LineColor; + } + } + if( KTAP->Checked ) DrawMain.AdjustTransPoint(); + UpdateTemp(); + UpdateUndo(sp); + } + else { + delete sp; + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SBDColClick(TObject *Sender) +{ + if( DrawMain.pSel != NULL ){ + TMemoryStream *sp = SaveUndo(NULL); + if( DrawMain.pSel->Color() == TRUE ){ + if( KTAP->Checked ) DrawMain.AdjustTransPoint(); + UpdateTemp(); + UpdateUndo(sp); + } + else { + delete sp; + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::PBoxTXDragOver(TObject *Sender, TObject *Source, + int X, int Y, TDragState State, bool &Accept) +{ + Accept = FALSE; + if( Source == PBoxS ){ + if( SBTX->Down ) return; + if( (m_MainPage != pgTemp ) && TabS->TabIndex ){ + AdjustPage(pgTemp); + } + else if( (m_MainPage != pgTX) && !TabS->TabIndex ){ + AdjustPage(pgTX); + } + Accept = TRUE; + } + else if( (pHistView != NULL) && (pHistView->IsPBox(Source) >= 0) ){ + AdjustPage(pgTemp); + Accept = TRUE; + } + else { + if( SBTX->Down ) return; + for( int i = 0; i < 8; i++ ){ + TFileViewDlg *fp = pFileView[i]; + if( (fp != NULL) && (fp->IsPBox(Source) >= 0) ){ + AdjustPage(fp->pCurPage->m_Type ? pgTemp : -1); + Accept = TRUE; + break; + } + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::GetTempHistSize(int &x, int &y) +{ + switch(sys.m_HDDSize){ + case 0: // 1/16 + x += (80-1); + y += (64-1); + break; + case 1: // 1/12 + x += (92-1); + y += (74-1); + break; + case 2: // 1/9 + x += (107-1); + y += (85-1); + break; + case 3: // 1/6 + x += (131-1); + y += (105-1); + break; + case 4: // 1/4 + x += (160-1); + y += (128-1); + break; + default: // 1/3 + x += (185-1); + y += (148-1); + break; + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::PBoxTXDragDrop(TObject *Sender, TObject *Source, + int X, int Y) +{ + CWaitCursor w; + + if( Source == PBoxS ){ + if( m_DragNo >= 0 ){ + if( CBSTemp->Checked || TabS->TabIndex ){ + SaveUndo(); + LoadStockTemp(&DrawMain, m_DragDataNo, NULL); + if( !KSIS->Checked || !DrawMain.m_Cnt ){ + if( !sys.m_Repeater || !pDem->m_Repeater){ + DrawMain.m_SX = m_TXW; + DrawMain.m_SY = m_TXH; + } + } + } + if( !TabS->TabIndex ){ + Graphics::TBitmap *pBitmap = LoadBitmapS(m_DragNo); + pBitmapTXM = RemakeBitmap(pBitmapTXM, -1); + if( KSIS->Checked ){ + StretchCopyBitmapHW(pBitmapTXM, pBitmap); + } + else { + FillBitmap(pBitmapTXM, sys.m_PicClipColor); + pBitmapTXM->Canvas->Draw(0, 0, pBitmap); + } + delete pBitmap; + } + UpdatePic(); + } + } + else if( (pHistView != NULL) && (pHistView->IsPBox(Source) >= 0) ){ + CDrawPic *pDraw = (CDrawPic *)DrawMain.MakeItem(CM_PIC); + if( pDraw != NULL ){ + AdjustTempSC(X, Y); + AdjustTempView(1); + pDraw->Start(PBoxTemp->Canvas, X, Y); + GetTempHistSize(X, Y); + pDraw->Making(X, Y); + if( pDraw->FinishR(X, Y) ){ +#if 0 + SaveUndo(); + DrawMain.AddItem(pDraw); + DrawMain.pSel = pDraw; + m_DrawCmd = CM_SELECT; + SBDSel->Down = TRUE; + KTBClick(NULL); + if( KTAP->Checked ) DrawMain.AdjustTransPoint(); +#else + AddItem(pDraw, 0); +#endif + } + else { + delete pDraw; + } + AdjustTempView(0); + UpdateTemp(); + } + } + else { + for( int i = 0; i < 8; i++ ){ + TFileViewDlg *fp = pFileView[i]; + if( (fp != NULL) && (fp->IsPBox(Source) >= 0) ){ + if( fp->pCurPage->m_Type ){ + AnsiString as; + fp->GetCurFileName(as); + switch(fp->pCurPage->m_Type){ + case 2: + LoadTemplate(&DrawTemp, as.c_str(), NULL); + AddTemplate(&DrawTemp); + break; + case 3: + DropLib(X, Y, as.c_str()); + break; + case 4: + DropOle(X, Y, as.c_str(), 1); + break; + default: + SaveUndo(); + LoadTemplate(&DrawMain, as.c_str(), NULL); + break; + } + UpdateTemp(); + } + else if( m_MainPage == pgTX ){ + pBitmapTXM = RemakeBitmap(pBitmapTXM, -1); + if( pFileView[i]->CopyBitmap(pBitmapTXM) == TRUE ){ + UpdatePic(); + } + } + else { + int w, h; + pFileView[i]->GetSize(w, h); + Graphics::TBitmap *pBitmap = CreateBitmap(w, h, -1); + if( pFileView[i]->CopyBitmap(pBitmap) == TRUE ){ + DropPic(X, Y, pBitmap, pFileView[i]->GetType()); + } + delete pBitmap; + } + break; + } + } + } + AdjustFocus(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::PBoxSDragDrop(TObject *Sender, + TObject *Source, int X, int Y) +{ + if( (Source == PBoxTemp) || (Source == PBoxTX) ){ + int n = GetStockNo(X, Y); + int nn = n + UDStock->Position * m_SMax; + if( (n >= 0) && (nn < STOCKMAX) ){ + int Off = m_StockOff; + if( !TabS->TabIndex ) Off = 0; + if( CBSTemp->Checked || (Source == PBoxTemp) ){ + SaveStockTemp(&DrawMain, nn + Off); + } + if( !TabS->TabIndex ){ + SaveBitmapS(pBitmapTXM, n); + } + UpdateTabS(); + } + } + else { + for( int i = 0; i < 8; i++ ){ + TFileViewDlg *fp = pFileView[i]; + if( (fp != NULL) && (fp->IsPBox(Source) >= 0) ){ + if( !TabS->TabIndex ){ + int n = GetStockNo(X, Y); + int nn = n + UDStock->Position * m_SMax; + if( (n >= 0) && (nn < STOCKMAX) ){ + Graphics::TBitmap *pBitmap = CreateBitmap(m_PSSize[n] & 0x0000ffff, m_PSSize[n]>>16, -1); + if( fp->CopyBitmap(pBitmap) == TRUE ){ + SaveBitmapS(pBitmap, n); + UpdateTabS(); + } + delete pBitmap; + } + } + break; + } + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::PBoxSDragOver(TObject *Sender, + TObject *Source, int X, int Y, TDragState State, bool &Accept) +{ + Accept = FALSE; + if( GetStockNo(X, Y) >= 0 ){ + if( Source == PBoxTemp ){ + if( !TabS->TabIndex ){ + TabS->TabIndex = 1; + TabSChange(NULL); + PBoxS->Invalidate(); + } + Accept = TRUE; + } + else if( Source == PBoxTX ){ + if( TabS->TabIndex ){ + TabS->TabIndex = 0; + TabSChange(NULL); + PBoxS->Invalidate(); + } + Accept = TRUE; + } + else { + for( int i = 0; i < 8; i++ ){ + TFileViewDlg *fp = pFileView[i]; + if( (fp != NULL) && (fp->IsPBox(Source) >= 0) && !fp->pCurPage->m_Type ){ + if( TabS->TabIndex ){ + TabS->TabIndex = 0; + TabSChange(NULL); + PBoxS->Invalidate(); + } + Accept = TRUE; + break; + } + } + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::PBoxSMouseDown(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + m_DragNo = GetStockNo(X, Y); + m_DragDataNo = UDStock->Position * m_SMax + m_DragNo; + if( m_DragDataNo >= STOCKMAX ){ + m_DragNo = -1; + m_DragDataNo = 0; + } + else if( TabS->TabIndex ){ + m_DragDataNo += m_StockOff; + } + if( Button == mbLeft ){ + m_TabSXX = X; + m_TabSYY = Y; + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::PBoxSMouseMove(TObject *Sender, TShiftState Shift, + int X, int Y) +{ + TShiftState sc1, sc2; + sc1 << ssLeft; + sc2 << ssLeft; + sc1 *= Shift; + if( sc1 == sc2 ){ // Left button + if( (ABS(m_TabSXX-X) + ABS(m_TabSYY-Y)) >= 10 ){ + if( m_DragNo >= 0 ) PBoxS->BeginDrag(TRUE,0); + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::PBoxSDblClick(TObject *Sender) +{ + if( m_DragNo >= 0 ){ + if( TabS->TabIndex || !SBTX->Down ){ + AdjustPage( TabS->TabIndex ? pgTemp : pgTX); + PBoxTXDragDrop(Sender, PBoxS, 0, 0); + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::GetStockXY(int &X1, int &Y1, int &X2, int &Y2, int n) +{ + int mm = m_SMax / 6; + if( !mm ) mm++; + int xw = (PBoxS->Width / 6) - 4; + int yw = (PBoxS->Height / mm) - 4; + + X1 = (((n % 6) * PBoxS->Width) / 6) + 2; + X2 = X1 + xw; + Y1 = (((n / 6) * PBoxS->Height) / mm) + 2; + Y2 = Y1 + yw; +} +//--------------------------------------------------------------------------- +int __fastcall TMmsstv::GetStockNo(int X, int Y) +{ + int i, x1, y1, x2, y2; + for( i = 0; i < m_SMax; i++ ){ + GetStockXY(x1, y1, x2, y2, i); + if( (X > x1)&&(X < x2)&&(Y > y1)&&(Y < y2) ) return i; + } + return -1; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::UpdateTabS(void) +{ + if( (pStockView != NULL) && !pStockView->Visible ) return; + + CWaitCursor wait; + + m_DisEvent++; + + Graphics::TBitmap *pBitmap = new Graphics::TBitmap(); + AdjustBitmapFormat(pBitmap); + MultProc(); + + int ktmd = KTMD->Checked; + KTMD->Checked = TRUE; + + TRect rc; + TRect sc; + int x1, x2, y1, y2; + int n; + if( TabS->TabIndex ){ // テンプレート + m_StockPage = TabS->TabIndex - 1; + m_StockOff = m_StockPage * STOCKMAX; + n = m_TSPage[m_StockPage] * m_SMax; + Graphics::TBitmap *pBmpStock = pBitmapST[m_StockPage]; + if( pBmpStock == NULL ){ + pBmpStock = new Graphics::TBitmap(); + AdjustBitmapFormat(pBmpStock); + pBitmapST[m_StockPage] = pBmpStock; + } + pBmpStock->Width = PBoxS->Width; + pBmpStock->Height = PBoxS->Height; + FillBitmap(pBmpStock, clWhite); + pBmpStock->Canvas->Brush->Color = clBlack; + pBmpStock->Canvas->Pen->Color = clBlack; + MultProc(); + for( int i = 0; i < m_SMax; i++, n++ ){ + if( n >= STOCKMAX ) break; + + GetStockXY(x1, y1, x2, y2, i); + rc.Top = y1; rc.Left = x1; rc.Right = x2; rc.Bottom = y2; + LoadStockTemp(&DrawTemp, n + m_StockOff, pBitmap->Canvas); + if( DrawTemp.m_Cnt ){ + pBitmap->Width = DrawTemp.m_SX; + pBitmap->Height = DrawTemp.m_SY; + FillBitmap(pBitmap, DrawTemp.m_TransCol); +// DrawTemp.UpdatePic(pBitmapHistF); + MultProc(); + if( CBSDraft->Checked ){ + DrawTemp.DrawFast(pBitmap->Canvas); + } + else { + DrawTemp.Draw(pBitmap->Canvas); + } + MultProc(); + pBmpStock->Canvas->StretchDraw(rc, (TGraphic*)pBitmap); + if( sys.m_ShowSizeStock ){ + TColor col = (DrawTemp.m_SX != pBitmapTXM->Width) ? clRed : clGreen; + ShowSize(pBmpStock, x1, y2, DrawTemp.m_SX, DrawTemp.m_SY, 11, col); + pBmpStock->Canvas->Brush->Color = clBlack; + } + if( sys.m_Repeater ){ + ShowNo(pBmpStock, x1, y1, n+m_StockOff+1, 11, clYellow); + pBmpStock->Canvas->Brush->Color = clBlack; + } + } + pBmpStock->Canvas->FrameRect(rc); + MultProc(); + } + m_ATSPage[m_StockPage] = m_TSPage[m_StockPage]; + } + else { + n = m_PSPage * m_SMax; + if( pBitmapSS == NULL ){ + pBitmapSS = new Graphics::TBitmap(); + AdjustBitmapFormat(pBitmapSS); + } + pBitmapSS->Width = PBoxS->Width; + pBitmapSS->Height = PBoxS->Height; + FillBitmap(pBitmapSS, clWhite); + pBitmapSS->Canvas->Brush->Color = clBlack; + pBitmapSS->Canvas->Pen->Color = clBlack; + MultProc(); + + pBitmap->Transparent = TRUE; + pBitmap->TransparentMode = tmFixed; + + Graphics::TBitmap *pBitmapSV = CreateBitmap(PBoxTX->Width, PBoxTX->Height, -1); + MultProc(); + + for( int i = 0; i < m_SMax; i++, n++ ){ + if( n >= STOCKMAX ) break; + Graphics::TBitmap *pBitmapPic = LoadBitmapS(i); + m_PSSize[i] = pBitmapPic->Width + (pBitmapPic->Height << 16); + + GetStockXY(x1, y1, x2, y2, i); + rc.Top = y1; rc.Left = x1; rc.Right = x2; rc.Bottom = y2; + + if( CBSTemp->Checked ){ + LoadStockTemp(&DrawTemp, n, pBitmap->Canvas); + } + if( !pBitmapPic->Modified ){ + if( CBSTemp->Checked && DrawTemp.m_Cnt ){ + FillBitmap(pBitmapSV, clWhite); + } + else { + pBitmapSS->Canvas->FrameRect(rc); + delete pBitmapPic; + continue; + } + } + else if( pBitmapPic->Width != pBitmapSV->Width ){ + StretchCopy(pBitmapSV, pBitmapPic, HALFTONE); + } + else { + pBitmapSV->Canvas->Draw(0, 0, pBitmapPic); + } + if( CBSTemp->Checked && DrawTemp.m_Cnt ){ + MultProc(); + pBitmap->Width = DrawTemp.m_SX; + pBitmap->Height = DrawTemp.m_SY; + FillBitmap(pBitmap, DrawTemp.m_TransCol); + DrawTemp.UpdatePic(pBitmapHistF); + MultProc(); + if( CBSDraft->Checked ){ + DrawTemp.DrawFast(pBitmap->Canvas); + } + else { + DrawTemp.Draw(pBitmap->Canvas); + } + MultProc(); + pBitmap->TransparentColor = pBitmap->Canvas->Pixels[DrawTemp.m_TransX][DrawTemp.m_TransY]; + if( pBitmapSV->Width != pBitmap->Width ){ + StretchCopy(pBitmapSV, pBitmap, HALFTONE); + } + else { + pBitmapSV->Canvas->Draw(0, 0, pBitmap); + } + } + pBitmapSS->Canvas->StretchDraw(rc, pBitmapSV); + pBitmapSS->Canvas->FrameRect(rc); + if( sys.m_ShowSizeStock && pBitmapPic->Modified ){ + TColor col = (pBitmapPic->Width != pBitmapTXM->Width) ? clRed : clGreen; + ShowSize(pBitmapSS, x1, y2, pBitmapPic->Width, pBitmapPic->Height, 11, col); + pBitmapSS->Canvas->Brush->Color = clBlack; + } + if( sys.m_Repeater ){ + ShowNo(pBitmapSS, x1, y1, n+1, 11, clYellow); + pBitmapSS->Canvas->Brush->Color = clBlack; + } + MultProc(); + delete pBitmapPic; + } + delete pBitmapSV; + MultProc(); + m_APSPage = m_PSPage; + } + DrawTemp.FreeItem(); + delete pBitmap; + KTMD->Checked = ktmd; + m_DisEvent--; + PBoxSPaint(NULL); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::PBoxSPaint(TObject *Sender) +{ + if( TabS->TabIndex ){ // テンプレート + m_StockPage = TabS->TabIndex - 1; + m_StockOff = m_StockPage * STOCKMAX; + if( pBitmapST[m_StockPage] == NULL ){ + UpdateTabS(); + } + else { + PBoxS->Canvas->Draw(0, 0, pBitmapST[m_StockPage]); + } + } + else { // ストック画像 + if( pBitmapSS == NULL ){ + UpdateTabS(); + } + else { + PBoxS->Canvas->Draw(0, 0, pBitmapSS); + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KSTPClick(TObject *Sender) +{ + CWaitCursor wait; + int x, y, n, l; + + const TColor bc[]={ + clBlack, clWhite, + clGreen, clBlue, + clBlue, clRed, + clRed, clYellow, + clYellow, clLime, + clLime, clPurple, + clPurple, clOlive, + clOlive, clBlack, + }; + pBitmapTXM = RemakeBitmap(pBitmapTXM, -1); + TColor col; + int XW = pBitmapTXM->Width / 16; + int YW = pBitmapTXM->Height / 8; + for( n = l = 0; n < 16; n += 2, l += YW ){ + for( y = l; y < (l + YW); y++ ){ + for( x = 0; x < (pBitmapTXM->Width / 2); x++ ){ + col = GetCol(bc[n], bc[n+1], x, (pBitmapTXM->Width / 2)); + pBitmapTXM->Canvas->Pixels[x][y] = col; + } + } + } + l = pBitmapTXM->Width / 2; + for( n = 0; n < 16; n += 2, l += XW ){ + for( x = l; x < (l + XW); x++ ){ + for( y = 0; y < pBitmapTXM->Height; y++ ){ + col = GetCol(bc[n], bc[n+1], y, pBitmapTXM->Height); + pBitmapTXM->Canvas->Pixels[x][y] = col; + } + } + } + UpdatePic(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KSAIClick(TObject *Sender) +{ + if( PopupS->PopupComponent == PBoxTX ){ + SBTXFilClick(NULL); + return; + } + if( m_DragNo < 0 ) return; + if( !TabS->TabIndex ){ // ビットマップ + TPicFilterDlg *pBox = new TPicFilterDlg(this); + Graphics::TBitmap *pBitmap = LoadBitmapS(m_DragNo); + if( pBox->Execute(pBitmap) == TRUE ){ + SaveBitmapS(pBitmap, m_DragNo); + UpdateTabS(); + } + delete pBitmap; + delete pBox; + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::TabSChange(TObject *Sender) +{ + if( m_DisEvent ) return; + if( (pStockView != NULL) && !pStockView->Visible ) return; + + int i; + if( TabS->TabIndex == 0 ){ + if( !CBSTemp->Checked ) UDStock->Position = short(m_PSPage); + if( UDStock->Position != m_TxSPage ){ + CWaitCursor wait; + m_TxSPage = UDStock->Position; + } + ::DragAcceptFiles(PanelS->Handle, TRUE); + CBSTemp->Enabled = TRUE; + CBSDraft->Enabled = CBSTemp->Checked; + int f = 0; + for( i = 0; i < 8; i++ ){ + if( (pFileView[i] != NULL) && pFileView[i]->m_Overlap ){ + pFileView[i]->Visible = TRUE; + pFileView[i]->m_Suspend = 0; + f++; + MultProc(); + } + } + if( f && (pRxView != NULL) && (pRxView->Handle != ::GetForegroundWindow()) ){ + ::SetForegroundWindow(pRxView->Handle); + } + if( m_PSPage != m_APSPage ) UpdateTabS(); + } + else { + m_StockPage = TabS->TabIndex - 1; + if( !CBSTemp->Checked ) UDStock->Position = short(m_TSPage[m_StockPage]); + ::DragAcceptFiles(PanelS->Handle, FALSE); + CBSTemp->Enabled = FALSE; + CBSDraft->Enabled = TRUE; + for( i = 0; i < 8; i++ ){ + if( (pFileView[i] != NULL) && pFileView[i]->m_Overlap ){ + pFileView[i]->Visible = FALSE; + pFileView[i]->m_Suspend = 1; + MultProc(); + } + } + if( m_TSPage[m_StockPage] != m_ATSPage[m_StockPage] ) UpdateTabS(); + } + char bf[64]; + sprintf(bf, "%u/%u", UDStock->Position + 1, m_DragPMax); + LS->Caption = bf; + PBoxS->Invalidate(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::UDStockClick(TObject *Sender, TUDBtnType Button) +{ + if( TabS->TabIndex ){ + m_TSPage[m_StockPage] = UDStock->Position; + if( CBSTemp->Checked && (TabS->TabIndex == 1) ) m_PSPage = m_TSPage[0]; + } + else { + m_PSPage = UDStock->Position; + if( CBSTemp->Checked ) m_TSPage[0] = m_PSPage; + } + TabSChange(NULL); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::CopyBitmap(Graphics::TBitmap *pBitmap) +{ + //int DataHandle; //ja7ude 0521 + NativeUInt DataHandle; + HPALETTE APalette; + //unsigned short MyFormat; //ja7ude 0521 + System::Word MyFormat; //ja7ude 0521 + pBitmap->SaveToClipboardFormat(MyFormat, DataHandle, APalette); + Clipboard()->SetAsHandle(MyFormat,DataHandle); +// SBPaste->Enabled = TRUE; +} +//--------------------------------------------------------------------------- +int __fastcall TMmsstv::PasteBitmap(Graphics::TBitmap *pBitmap, int rs) +{ + int r = FALSE; + TClipboard *pCB = Clipboard(); + if (pCB->HasFormat(CF_BITMAP)){ + TPicRectDlg *pBox = new TPicRectDlg(this); + try + { + pBox->pBitmap->LoadFromClipboardFormat(CF_BITMAP, pCB->GetAsHandle(CF_BITMAP), 0); + if( rs == 2 ){ + r = pBox->Execute(pBitmap); + } + else if( rs ){ + ::CopyBitmap(pBitmap, pBox->pBitmap); + r = TRUE; + } + else if( pBox->Copy(pBitmap) == TRUE ){ + r = TRUE; + } + } + catch (...) + { + ErrorMB( "Clipboard error." ); + } + delete pBox; + } + return r; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SaveBitmapS(Graphics::TBitmap *pBitmap, int n) +{ + SaveBitmapSN(pBitmap, m_PSPage * m_SMax + n + 1); +} +//--------------------------------------------------------------------------- +Graphics::TBitmap* __fastcall TMmsstv::LoadBitmapS(int n) +{ + Graphics::TBitmap *pBitmap = new Graphics::TBitmap; + LoadBitmapSN(pBitmap, m_PSPage * m_SMax + n + 1); + return pBitmap; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SaveBitmapSN(Graphics::TBitmap *pBitmap, int n) +{ + CWaitCursor wait; + char bf[256]; + sprintf(bf, sys.m_UseJPEG ? "%sTxStock%u.jpg":"%sTxStock%u.bmp", StockDir, n); + if( sys.m_UseJPEG ){ + SaveJPEG(pBitmap, bf); + } + else { + SaveBitmap(pBitmap, bf); + } + MultProc(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::LoadBitmapSN(Graphics::TBitmap *pBitmap, int n) +{ + CWaitCursor wait; + MultProc(); + char bf[256]; + sprintf(bf, sys.m_UseJPEG ? "%sTxStock%u.jpg" : "%sTxStock%u.bmp", StockDir, n); + if( IsFile(bf) ){ + MultProc(); + if( sys.m_UseJPEG ){ + LoadJPEG(pBitmap, bf); + } + else { + LoadBitmap(pBitmap, bf); + } + pBitmap->Modified = TRUE; + } + else { + pBitmap->Width = 320; + pBitmap->Height = 256; + FillBitmap(pBitmap, clWhite); + pBitmap->Modified = FALSE; + } +} +//--------------------------------------------------------------------------- +// ファイルからロード +int __fastcall TMmsstv::LoadBitmapMenu(Graphics::TBitmap *pBitmap, int rs) +{ + int r = FALSE; + + OpenDialog->Options >> ofCreatePrompt; + OpenDialog->Options << ofFileMustExist; + if( MsgEng ){ + OpenDialog->Title = "Load picture from file"; + } + else { + OpenDialog->Title = "画像のロード"; + } + OpenDialog->Filter = GetPicFilter(); + OpenDialog->FileName = ""; + OpenDialog->DefaultExt = "jpg"; + OpenDialog->InitialDir = BitmapDir; + SetDisPaint(); + NormalWindow(this); + if( OpenDialogExecute(TRUE) == TRUE ){ + SetDirName(BitmapDir, AnsiString(OpenDialog->FileName).c_str()); + TPicRectDlg *pBox = new TPicRectDlg(this); + if( LoadImage(pBox->pBitmap, AnsiString(OpenDialog->FileName).c_str()) == TRUE ){ + if( rs ){ + ::CopyBitmap(pBitmap, pBox->pBitmap); + r = TRUE; + } + else if( pBox->Execute(pBitmap) == TRUE ){ + r = TRUE; + } + } + delete pBox; + } + ResDisPaint(); + TopWindow(this); + return r; +} + +int __fastcall TMmsstv::SaveBitmapMenu(Graphics::TBitmap *pBitmap, LPCSTR pName, LPCSTR pFolder) +{ + int r = FALSE; + + if( MsgEng ){ + SaveDialog->Title = "Save picture"; + } + else { + SaveDialog->Title = "画像をセーブ"; + } + SaveDialog->Filter = "JPEG files(*.jpg)|*.jpg|Bitmap files(*.bmp)|*.bmp|"; + SaveDialog->FileName = pName != NULL ? pName : "Picture"; + SaveDialog->DefaultExt = "jpg"; + SaveDialog->InitialDir = pFolder != NULL ? pFolder : SBitmapDir; + SetDisPaint(); + NormalWindow(this); + if( SaveDialog->Execute() == TRUE ){ + if( pFolder == NULL ){ + SetDirName(SBitmapDir, AnsiString(SaveDialog->FileName).c_str()); + } + if( SaveImage(pBitmap, AnsiString(SaveDialog->FileName).c_str()) == TRUE ){ + r = TRUE; + } + } + TopWindow(this); + ResDisPaint(); + return r; +} +//--------------------------------------------------------------------------- +// ファイルからロード +int __fastcall TMmsstv::LoadTemplateMenu(CDrawGroup *pItem, int isw) +{ + MultProc(); + int r = FALSE; + OpenDialog->Options >> ofCreatePrompt; + OpenDialog->Options << ofFileMustExist; + if( MsgEng ){ + OpenDialog->Title = "Load template from file"; + } + else { + OpenDialog->Title = "テンプレートファイルのロード"; + } + if( isw ){ + char bf[256]; + sprintf(bf, "%s|%s", GetTempIFilter(), GetTempMFilter()); + OpenDialog->Filter = bf; + OpenDialog->DefaultExt = "mti"; + } + else { + OpenDialog->Filter = GetTempMFilter(); + OpenDialog->DefaultExt = "mtm"; + } + OpenDialog->FileName = ""; + OpenDialog->InitialDir = TemplateDir; + SetDisPaint(); + MultProc(); + NormalWindow(this); + if( OpenDialogExecute(TRUE) == TRUE ){ + MultProc(); + SetDirName(TemplateDir, AnsiString(OpenDialog->FileName).c_str()); //ja7ude 0521 + SaveUndo(); + r = LoadTemplate(pItem, AnsiString(OpenDialog->FileName).c_str(), NULL); //ja7ude 0521 + } + ResDisPaint(); + TopWindow(this); + MultProc(); + return r; +} +//--------------------------------------------------------------------------- +int __fastcall TMmsstv::SaveTemplateMenu(CDrawGroup *pItem, int isw) +{ + return SaveTemplateMenu(pItem, NULL, NULL, isw); +} +//--------------------------------------------------------------------------- +int __fastcall TMmsstv::SaveTemplateMenu(CDrawGroup *pItem, LPCSTR pName, LPCSTR pFolder, int isw) +{ + MultProc(); + int r = FALSE; + if( MsgEng ){ + SaveDialog->Title = "Save template"; + } + else { + SaveDialog->Title = "テンプレートをセーブ"; + } + if( isw ){ + SaveDialog->Filter = GetTempIFilter(); + SaveDialog->FileName = pName != NULL ? pName : "Item"; + SaveDialog->DefaultExt = "mti"; + } + else { + SaveDialog->Filter = GetTempFilter(); + SaveDialog->FileName = pName != NULL ? pName : "Template"; + SaveDialog->DefaultExt = "mtm"; + SaveDialog->FilterIndex = 1; + } + SaveDialog->InitialDir = pFolder != NULL ? pFolder : TemplateDir; + SetDisPaint(); + MultProc(); + NormalWindow(this); + if( SaveDialog->Execute() == TRUE ){ + MultProc(); + if( pFolder == NULL ){ + SetDirName(TemplateDir, AnsiString(SaveDialog->FileName).c_str()); //ja7ude 0521 + } + r = SaveTemplate(pItem, AnsiString(SaveDialog->FileName).c_str()); //ja7ude 0521 + } + TopWindow(this); + ResDisPaint(); + MultProc(); + return r; +} +//--------------------------------------------------------------------------- +// ファイルからロード +void __fastcall TMmsstv::KSLClick(TObject *Sender) +{ + if( PopupS->PopupComponent == PBoxTX ){ + if( LoadBitmapMenu(pBitmapTXM, 0) == TRUE ){ + SBUseTempClick(NULL); + } + return; + } + if( m_DragNo < 0 ) return; + if( TabS->TabIndex ){ // テンプレート + if( LoadTemplateMenu(&DrawTemp, 0) == TRUE ){ + SaveStockTemp(&DrawTemp, m_DragDataNo); + UpdateTabS(); + } + DrawTemp.FreeItem(); + } + else { // ビットマップ + Graphics::TBitmap *pBitmap = CreateBitmap(m_PSSize[m_DragNo] & 0x0000ffff, m_PSSize[m_DragNo]>>16, -1); +// Graphics::TBitmap *pBitmap = LoadBitmapS(m_DragNo); + if( LoadBitmapMenu(pBitmap, 0) == TRUE ){ + SaveBitmapS(pBitmap, m_DragNo); + UpdateTabS(); + } + delete pBitmap; + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KSSClick(TObject *Sender) +{ + if( PopupS->PopupComponent == PBoxTX ){ + Graphics::TBitmap *pBitmap = pBitmapTX; + if( m_TXPH == 240 ){ + pBitmap = CreateBitmap(m_TXW, m_TXPH, pf24bit); + pBitmap->Canvas->Draw(0, 0, pBitmapTX); + } + SaveBitmapMenu(pBitmap, NULL, NULL); + if( pBitmap != pBitmapTX ) delete pBitmap; + return; + } + if( m_DragNo < 0 ) return; + if( TabS->TabIndex ){ // テンプレート + LoadStockTemp(&DrawTemp, m_DragDataNo, NULL); + SaveTemplateMenu(&DrawTemp, 0); + DrawTemp.FreeItem(); + } + else { // ビットマップ + Graphics::TBitmap *pBitmap = LoadBitmapS(m_DragNo); + SaveBitmapMenu(pBitmap, NULL, NULL); + delete pBitmap; + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KSCClick(TObject *Sender) +{ + if( PopupS->PopupComponent == PBoxTX ){ + Graphics::TBitmap *pBitmap = pBitmapTX; + if( m_TXPH == 240 ){ + pBitmap = CreateBitmap(m_TXW, m_TXPH, pf24bit); + pBitmap->Canvas->Draw(0, 0, pBitmapTX); + } + CopyBitmap(pBitmap); + if( pBitmap != pBitmapTX ) delete pBitmap; + return; + } + if( m_DragNo < 0 ) return; + if( !TabS->TabIndex ){ // ビットマップ + Graphics::TBitmap *pBitmap = LoadBitmapS(m_DragNo); + CopyBitmap(pBitmap); + delete pBitmap; + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KSPClick(TObject *Sender) +{ + if( PopupS->PopupComponent == PBoxTX ){ + if( PasteBitmap(pBitmapTXM, 0) == TRUE ){ + SBUseTempClick(NULL); + } + return; + } + if( m_DragNo < 0 ) return; + if( !TabS->TabIndex ){ // ビットマップ + Graphics::TBitmap *pBitmap = CreateBitmap(m_PSSize[m_DragNo] & 0x0000ffff, m_PSSize[m_DragNo]>>16, -1); +// Graphics::TBitmap *pBitmap = LoadBitmapS(m_DragNo); + if( PasteBitmap(pBitmap, 0) == TRUE ){ + SaveBitmapS(pBitmap, m_DragNo); + UpdateTabS(); + } + delete pBitmap; + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KSDClick(TObject *Sender) +{ + if( PopupS->PopupComponent == PBoxTX ){ + pBitmapTXM = RemakeBitmap(pBitmapTXM, -1); + FillBitmap(pBitmapTXM, sys.m_PicClipColor); + SBUseTempClick(NULL); + return; + } + if( m_DragNo < 0 ) return; + if( TabS->TabIndex ){ // テンプレート + DeleteStockTemp(m_DragDataNo); + UpdateTabS(); + } + else { // ビットマップ + CWaitCursor wait; + char bf[256]; + sprintf(bf, sys.m_UseJPEG ? "%sTxStock%u.jpg" : "%sTxStock%u.bmp", StockDir, m_DragDataNo + 1); + unlink(bf); + UpdateTabS(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KSSZClick(TObject *Sender) +{ + if( PopupS->PopupComponent == PBoxTX ) return; + if( m_DragNo < 0 ) return; + if( !TabS->TabIndex ){ // テンプレート + int w, h; + if( Sender == KSS1 ){ + w = 320; h = 256; + } + else if( Sender == KSS2 ){ + w = 512; h = 400; + } + else if( Sender == KSS3 ){ + w = 640; h = 496; + } + else { + w = 800; h = 616; + } + Graphics::TBitmap *pBitmap = LoadBitmapS(m_DragNo); + ReSizeBitmap(pBitmap, w, h); + SaveBitmapS(pBitmap, m_DragNo); + delete pBitmap; + UpdateTabS(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::PopupSPopup(TObject *Sender) +{ + MultProc(); + SBPaste->Enabled = ::IsClipboardFormatAvailable(CF_BITMAP); + KSTD->Checked = CBSDraft->Checked; + if( PopupS->PopupComponent == PBoxTX ){ // Tx Window + KSF->Enabled = TRUE; + KSB->Enabled = TRUE; + KSCD->Enabled = FALSE; + KSTP->Enabled = TRUE; + KSAM->Enabled = TRUE; + KSIS->Enabled = TRUE; + KSRR->Enabled = TRUE; + KSSD->Checked = sys.m_ShowSizeTX; + KSTS->Enabled = SBUseTemp->Enabled; + KSTD->Enabled = FALSE; + KSTS->Checked = SBUseTemp->Down; + } + else { + KSF->Enabled = FALSE; + KSB->Enabled = FALSE; + KSCD->Enabled = TRUE; + KSTP->Enabled = FALSE; + KSAM->Enabled = FALSE; + KSIS->Enabled = FALSE; + KSRR->Enabled = FALSE; + KSSD->Checked = sys.m_ShowSizeStock; + KSTS->Enabled = CBSTemp->Enabled; + KSTD->Enabled = CBSDraft->Enabled; + KSTS->Checked = CBSTemp->Checked; + } + MultProc(); + if( PopupS->PopupComponent == PBoxTX ){ // Tx Window + KSC->Enabled = TRUE; + KSP->Enabled = SBPaste->Enabled; + KSFJ->Enabled = FALSE; + KSFB->Enabled = FALSE; + KSAI->Enabled = TRUE; + KSSZ->Enabled = FALSE; + KSMS->Enabled = FALSE; + KSA->Enabled = FALSE; + KSE->Enabled = TRUE; + } + else if( TabS->TabIndex ){ // テンプレート + KSC->Enabled = FALSE; + KSP->Enabled = FALSE; + KSFJ->Enabled = FALSE; + KSFB->Enabled = FALSE; + KSAI->Enabled = FALSE; + KSSZ->Enabled = FALSE; + KSMS->Enabled = FALSE; + KSA->Enabled = TRUE; + KSE->Enabled = FALSE; + } + else { // ビットマップ + KSC->Enabled = TRUE; + KSP->Enabled = SBPaste->Enabled; + KSFJ->Enabled = !sys.m_UseJPEG; + KSFB->Enabled = sys.m_UseJPEG; + KSAI->Enabled = TRUE; + KSMS->Enabled = TRUE; + KSA->Enabled = FALSE; + if( m_DragNo >= 0 ){ + KSSZ->Enabled = TRUE; + switch(m_PSSize[m_DragNo] & 0x0000ffff){ + case 512: + KSS2->Checked = TRUE; + break; + case 640: + KSS3->Checked = TRUE; + break; + case 800: + KSS4->Checked = TRUE; + break; + default: + KSS1->Checked = TRUE; + break; + } + } + else { + KSSZ->Enabled = FALSE; + } + KSE->Enabled = TRUE; + } + MultProc(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::PopupHPopup(TObject *Sender) +{ + KHD->Enabled = UDHist->Position < RxHist.m_Head.m_Cnt; + KHDA->Enabled = RxHist.m_Head.m_Cnt; + KHFB->Enabled = RxHist.m_UseJPEG; + KHFJ->Enabled = !RxHist.m_UseJPEG; + switch(sys.m_HDDSize){ + case 0: + KHDS1->Checked = TRUE; + break; + case 1: + KHDS2->Checked = TRUE; + break; + case 2: + KHDS3->Checked = TRUE; + break; + case 3: + KHDS4->Checked = TRUE; + break; + case 4: + KHDS5->Checked = TRUE; + break; + default: + KHDS6->Checked = TRUE; + break; + } + KHTB->Checked = sys.m_HistViewTB; + if( PopupH->PopupComponent != PBoxHist ){ + KHDS->Enabled = TRUE; + KHTB->Enabled = TRUE; + KHSD->Enabled = FALSE; + KHVS->Enabled = TRUE; + } + else { + KHDS->Enabled = FALSE; + KHTB->Enabled = FALSE; + KHSD->Enabled = TRUE; + KHVS->Enabled = FALSE; + } + KHSD->Checked = sys.m_ShowSizeHist; + switch(sys.m_HistViewSize){ + case 0: + KHVS1->Checked = TRUE; + break; + case 1: + KHVS2->Checked = TRUE; + break; + case 2: + KHVS3->Checked = TRUE; + break; + default: + KHVS4->Checked = TRUE; + break; + } + MultProc(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::PopupTPopup(TObject *Sender) +{ + MultProc(); + int cmd = DrawMain.pSel ? DrawMain.pSel->m_Command : 0; + KTU->Enabled = pUndo != NULL ? TRUE : FALSE; + KTC->Enabled = cmd; + KTPA->Enabled = (cmd == CM_PIC); + if( cmd != CM_PIC ){ + KTFX->Caption = MsgEng ? "Convert to image item" : "画像アイテムに変換"; + } + else { + KTFX->Caption = MsgEng ? "Convert to bitmap" : "ビットマップに変換"; + } + KTFX->Enabled = DrawMain.IsConvBitmap(DrawMain.pSel); + KTD->Enabled = SBDDel->Enabled; + KTE->Enabled = (cmd == CM_TEXT)||((cmd == CM_LIB)&&((((CDrawLib *)DrawMain.pSel)->m_Type & 3)==2)); + KTB->Enabled = SBDDel->Enabled; + KTF->Enabled = SBDDel->Enabled; + KTP->Enabled = pPaste != NULL; + KTS->Enabled = DrawMain.m_Cnt ? TRUE : FALSE; + KTSI->Enabled = cmd ? TRUE : FALSE; + KTA->Enabled = KTS->Enabled; + KTBT->Enabled = !SBTX->Down; + KTPI->Enabled = Clipboard()->HasFormat(CF_BITMAP); + switch(DrawMain.m_SX){ + case 512: + KTSZ2->Checked = TRUE; + break; + case 640: + KTSZ3->Checked = TRUE; + break; + case 800: + KTSZ4->Checked = TRUE; + break; + default: + KTSZ1->Checked = TRUE; + break; + } + KTSZT->Enabled = pBitmapTemp->Width != pBitmapTXM->Width; + KTSD->Checked = sys.m_ShowSizeTemp; + KTKA->Enabled = cmd && (!DrawMain.pSel->IsOrgSize()); + KTOS->Enabled = KTKA->Enabled; + KTFS->Checked = sys.m_DisFontSmooth; + KTH->Checked = sys.m_Temp24; + MultProc(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KTOClick(TObject *Sender) +{ + int cmd = DrawMain.pSel ? DrawMain.pSel->m_Command : 0; + int fole = (cmd == CM_OLE); + int flib = (cmd == CM_LIB); + CDrawOle *pOle = (CDrawOle *)DrawMain.pSel; + if( fole ) fole = (pOle->pContainer != NULL); + KTOT->Enabled = fole; + KTOC->Enabled = fole; + KTOCB->Enabled = fole || flib; + KTOE->Enabled = fole; + KTOB->Enabled = fole; + KTOR->Enabled = fole || flib; + if( fole ){ + KTOT->Checked = pOle->m_Trans; + KTOB->Checked = pOle->m_Stretch; + } + TOleContainer *pO = new TOleContainer(this); + KTOP->Enabled = pO->CanPaste || ::IsClipboardFormatAvailable(CF_BITMAP); + delete pO; + MultProc(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KTOIClick(TObject *Sender) +{ + AdjustTempSC(m_TempX, m_TempY); + MultProc(); + CDrawOle *pDraw = (CDrawOle *)DrawMain.MakeItem(CM_OLE); + pDraw->Start(PBoxTemp->Canvas, m_TempX, m_TempY); + pDraw->Making(m_TempX, m_TempY); + if( pDraw->Finish(m_TempX+160, m_TempY + 128) ){ + AddItem(pDraw, 0); + } + else { + delete pDraw; + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KTCIClick(TObject *Sender) +{ + AdjustTempSC(m_TempX, m_TempY); + MultProc(); + CDrawLib *pDraw = (CDrawLib *)DrawMain.MakeItem(CM_LIB); + pDraw->Start(PBoxTemp->Canvas, m_TempX, m_TempY); + pDraw->Making(m_TempX, m_TempY); + if( pDraw->Finish(m_TempX+160, m_TempY + 128) ){ + AddItem(pDraw, 0); + } + else { + delete pDraw; + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KTOCClick(TObject *Sender) +{ + if( DrawMain.pSel == NULL ) return; +// if( DrawMain.pSel->m_Command != CM_OLE ) return; + CWaitCursor w; + CDrawOle *pDraw = (CDrawOle *)DrawMain.pSel; + if( Sender == KTOC ){ + pDraw->pContainer->Copy(); + } + else if( Sender == KTOE ){ + pDraw->DoPrimary(); + UpdateTemp(); + } + else if( Sender == KTOB ){ + pDraw->m_Stretch = pDraw->m_Stretch ? 0 : 1; + UpdateTemp(); + } + else if( Sender == KTOT ){ + pDraw->m_Trans = pDraw->m_Trans ? 0 : 1; + UpdateTemp(); + } + else if( Sender == KTOCB ){ + if( pDraw->m_Command == CM_OLE ){ + Graphics::TBitmap *pBitmap = pDraw->MakeBitmap(); + CopyBitmap(pBitmap); + delete pBitmap; + } + else { + CDrawLib *pLib = (CDrawLib *)DrawMain.pSel; + CopyBitmap(pLib->pBitmap); + } + } + else if( Sender == KTOR ){ + if( pDraw->m_Command == CM_OLE ){ + if( pDraw->ObjectProperties() ){ + UpdateTemp(); + } + } + else { + CDrawLib *pLib = (CDrawLib *)DrawMain.pSel; + pLib->ObjectProperties(); + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::AddItem(CDraw *pItem, int b) +{ + MultProc(); + SaveUndo(); + DrawMain.AddItem(pItem); + DrawMain.pSel = pItem; + m_DrawCmd = CM_SELECT; + SBDSel->Down = TRUE; + if( b ) KTBClick(NULL); + if( KTAP->Checked ) DrawMain.AdjustTransPoint(); + UpdateTemp(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KTOPClick(TObject *Sender) +{ + CDrawOle *pDraw = (CDrawOle *)DrawMain.MakeItem(CM_OLE); + TOleContainer *pO = new TOleContainer(this); + int f = pO->CanPaste; + delete pO; + pDraw->m_X1 = m_TempX; pDraw->m_Y1 = m_TempY; + if( f ){ + if( !pDraw->Paste() ){ + delete pDraw; + pDraw = NULL; + } + } + else { + Graphics::TBitmap *pBitmap = new Graphics::TBitmap; + TClipboard *pCB = Clipboard(); + try{ + pBitmap->LoadFromClipboardFormat(CF_BITMAP, pCB->GetAsHandle(CF_BITMAP), 0); + pDraw->LoadFromBitmap(m_TempX, m_TempY, pBitmap); + } + catch(...){ + delete pDraw; + pDraw = NULL; + } + delete pBitmap; + } + if( pDraw != NULL ) AddItem(pDraw, 0); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KTUClick(TObject *Sender) +{ + if( pUndo != NULL ){ + pUndo->Seek(0, soFromBeginning); + DrawMain.LoadFromStream(PBoxTemp->Canvas, pUndo); + UpdateTemp(); + DeleteUndo(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SetGreetingString(LPSTR t, LPCSTR pCall, int type) +{ + strcpy(t, type ? "Hi" : "HELLO"); + if( !Cty.IsData() ) return; + LPCSTR p = ClipCC(pCall); + if( *p ){ + int n; + if( (n = Cty.GetNoP(p))!=0 ){ + CTL *cp = Cty.GetCTL(n-1); + if( cp->TD != NULL ){ + SYSTEMTIME now; + GetUTC(&now); + + WORD tim = WORD((now.wHour * 60 + now.wMinute) * 30 + now.wSecond/2); + tim = AdjustRolTimeUTC(tim, *cp->TD); + if( tim ){ + tim /= WORD(30); + if( tim < 12*60 ){ + strcpy(t, type ? "GM" : "Good morning"); + } + else if( tim < 18*60 ){ + strcpy(t, type ? "GA" : "Good afternoon"); + } + else { + strcpy(t, type ? "GE" : "Good evening"); + } + } + } + } + + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::MacroDate(LPSTR t, SYSTEMTIME &now) +{ + switch(Log.m_LogSet.m_DateType){ + case 2: + case 3: + sprintf(t, "%02u-%s-%04u", now.wDay, MONT1[now.wMonth], now.wYear); + break; + case 4: + case 5: + sprintf(t, "%s-%02u-%04u", MONT1[now.wMonth], now.wDay, now.wYear); + break; + default: + sprintf(t, "%04u-%s-%02u", now.wYear, MONT1[now.wMonth], now.wDay); + break; + } +} +//--------------------------------------------------------------------------- +int __fastcall TMmsstv::MacroText(LPSTR t, LPCSTR p, int size) +{ + int r = 0; + int n, l; + char bf[256]; + SYSTEMTIME now; + int f = KTMD->Checked; + + for( n = 0;*p; p++ ){ + if( *p == '%' ){ + p++; + switch(*p){ + case 'm': + strcpy(t, sys.m_Call.c_str()); + break; + case 'C': + case 'c': + strcpy(t, HisCall->Text.IsEmpty() ? "ToCall" : AnsiString(HisCall->Text).c_str()); //ja7ude 0521 + if( *p == 'C' ) strlwr(t); + break; + case 'n': + strcpy(t, (f && HisName->Text.IsEmpty()) ? "OM" : AnsiString(HisName->Text).c_str()); //ja7ude 0521 + break; + case 'J': + if( !HisName->Text.IsEmpty() ){ + strcpy(bf, AnsiString(HisName->Text).c_str()); //ja7ude 0521 + LPSTR tt; + StrDlm(tt, bf); + if( IsJA(AnsiString(HisCall->Text).c_str()) || (*tt < 0) ){ //ja7ude 0521 + sprintf(t, "%sさん", tt); + } + else { + strcpy(t, tt); + } + } + else { + *t = 0; + } + break; + case 'q': + strcpy(t, (f && HisQTH->Text.IsEmpty()) ? "His/Her QTH" : AnsiString(HisQTH->Text).c_str()); //ja7ude 0521 + break; + case 'r': + strcpy(t, (f && HisRST->Text.IsEmpty()) ? "RSV" : AnsiString(HisRST->Text).c_str()); //ja7ude 0521 + break; + case 's': + strcpy(t, (f && MyRST->Text.IsEmpty()) ? "RSV" : AnsiString(MyRST->Text).c_str()); //ja7ude 0521 + break; + case 'R': + strcpy(bf, (f && HisRST->Text.IsEmpty()) ? "RST" : AnsiString(HisRST->Text).c_str()); //ja7ude 0521 + if( strlen(bf) >= 3 ){ + StrCopy(t, bf, 3); + } + else { + strcpy(t, "595"); + } + break; + case 'N': + strcpy(bf, (f && HisRST->Text.IsEmpty()) ? "RSVNR" : AnsiString(HisRST->Text).c_str()); //ja7ude 0521 + if( strlen(bf) > 3 ){ + strcpy(t, &bf[3]); + } + else { + *t = 0; + } + break; + case 'M': + strcpy(bf, (f && MyRST->Text.IsEmpty()) ? "RSV" : AnsiString(MyRST->Text).c_str()); + if( strlen(bf) > 3 ){ + strcpy(t, &bf[3]); + } + else { + *t = 0; + } + break; + case 'g': + SetGreetingString(t, AnsiString(HisCall->Text).c_str(), 0); //ja7ude 0521 + r = 1; + break; + case 'f': + SetGreetingString(t, AnsiString(HisCall->Text).c_str(), 1); //ja7ude 0521 + r = 1; + break; + case 'D': + GetUTC(&now); + MacroDate(t, now); + r = 1; + break; + case 'L': + ::GetLocalTime(&now); + MacroDate(t, now); + r = 1; + break; + case 'T': + GetUTC(&now); + sprintf(t, "%02u:%02u", now.wHour, now.wMinute); + r = 1; + break; + case 't': + GetUTC(&now); + sprintf(t, "%02u%02u", now.wHour, now.wMinute); + r = 1; + break; + case 'U': + ::GetLocalTime(&now); + sprintf(t, "%02u:%02u", now.wHour, now.wMinute); + r = 1; + break; + case 'u': + ::GetLocalTime(&now); + sprintf(t, "%02u%02u", now.wHour, now.wMinute); + r = 1; + break; + case 'v': + strcpy(t, VERID); + break; + case 'V': + strcpy(t, VERBETA); + break; + case 'B': + strcpy(t, (f && LogFreq->Text.IsEmpty()) ? "Freq" : AnsiString(LogFreq->Text).c_str()); //ja7ude 0521 + break; + case 'b': + strcpy(t, (f && LogFreq->Text.IsEmpty()) ? "Band" : _BandText[Log.m_sd.band]); + break; + case 'o': + { + AnsiString ws; + Yen2CrLf(ws, EditNote->Text); + strcpy(t, (f && EditNote->Text.IsEmpty()) ? "Note" : ws.c_str()); + } + break; + case 'X': + now = RxHist.m_File[RxHist.m_CurRead].m_UTC; + MacroDate(t, now); + sprintf(t+strlen(t), " %02u%02u", now.wHour, now.wMinute); + r = 1; + break; + default: + strcpy(t, "%%"); + break; + } + l = strlen(t); + t += l; + n += l; + } + else { + *t++ = *p; + n++; + } + if( n >= (size - 1) ) break; + } + *t = 0; + return r; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::HisCallChange(TObject *Sender) +{ + TempDelay(); + SBULog->Enabled = TRUE; + UpdateUI(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::CBSTempClick(TObject *Sender) +{ + if( m_DisEvent ) return; + + if( Sender == KSTS ){ + if( PopupS->PopupComponent == PBoxTX ){ // Tx Window + SBUseTemp->Down = SBUseTemp->Down ? FALSE : TRUE; + SBUseTempClick(NULL); + return; + } + else { + m_DisEvent++; + CBSTemp->Checked = CBSTemp->Checked ? FALSE : TRUE; + m_DisEvent--; + } + } + else if( Sender == KSTD ){ + m_DisEvent++; + CBSDraft->Checked = CBSDraft->Checked ? FALSE : TRUE; + m_DisEvent--; + } + if( CBSTemp->Checked ){ + m_PSPage = m_TSPage[0] = UDStock->Position; + } + UpdateTabS(); + if( TabS->TabIndex ){ + CBSTemp->Enabled = FALSE; + CBSDraft->Enabled = TRUE; + } + else { + CBSTemp->Enabled = TRUE; + CBSDraft->Enabled = CBSTemp->Checked; + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SBHViewClick(TObject *Sender) +{ + TZoomViewDlg *pBox = new TZoomViewDlg(this); + pBox->Execute(pBitmapHist, FALSE); + delete pBox; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SBRViewClick(TObject *Sender) +{ + TZoomViewDlg *pBox = new TZoomViewDlg(this); + pBox->Execute(pBitmapRX, TRUE); + delete pBox; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SBTViewClick(TObject *Sender) +{ + TZoomViewDlg *pBox = new TZoomViewDlg(this); + pBox->Execute(pBitmapTX, FALSE); + delete pBox; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SBLKClick(TObject *Sender) +{ + sys.m_AutoStop = !SBLK->Down; + if( SBLK->Down ){ + sys.m_AutoSync = 0; + } + else { + sys.m_AutoSync = TRUE; + } + pDem->m_SyncRestart = !SBLK->Down; + pDem->CalcBPF(); + if( pCtrBtn != NULL ) pCtrBtn->UpdateBtn(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::AutoCopyJob(SYSTEMTIME tim, Graphics::TBitmap *pSource) +{ + if( Log.m_LogSet.m_TimeZone == 'I' ){ + UTCtoJST(&tim); + } + char fname[256]; + char abf[2]; + abf[0] = abf[1] = 0; + if( LastC(sys.m_AutoSaveDir.c_str()) != '\\' ) abf[0] = '\\'; + sprintf(fname, "%s%s%04u%02u%02u%02u%02u", sys.m_AutoSaveDir.c_str(), abf, + tim.wYear, + tim.wMonth, + tim.wDay, + tim.wHour, + tim.wMinute + ); + if( KHACJ->Checked ){ + strcat(fname, ".jpg"); + } + else { + strcat(fname, ".bmp"); + } + int r; + if( KHACT->Checked ){ + Graphics::TBitmap *pBitmap = DupeBitmap(pSource, pf24bit); + DateBitmap(pBitmap, tim); + if( KHACJ->Checked ){ + r = SaveJPEG(pBitmap, fname); + } + else { + r = SaveBitmap24(pBitmap, fname); + } + delete pBitmap; + } + else { + if( KHACJ->Checked ){ + r = SaveJPEG(pSource, fname); + } + else { + r = SaveBitmap24(pSource, fname); + } + } + if( r ){ + char bf[256]; + sprintf(bf, "%02u%02u%02u%02u%02u", + tim.wYear % 100, + tim.wMonth, + tim.wDay, + tim.wHour, + tim.wMinute + ); + AnsiString as = EditQSL->Text; + if( SBQSO->Down ){ + if( !strstr(as.c_str(), bf) ){ + if( !as.IsEmpty() ) as += ","; + as += bf; + } + } + else { + as = bf; + } + EditQSL->Text = as; + StrCopy(Log.m_sd.qsl, AnsiString(EditQSL->Text).c_str(), MLQSL); //ja7ude 0521 + } +} +//--------------------------------------------------------------------------- +// ヒストリに書きこみ +void __fastcall TMmsstv::SBWHistClick(TObject *Sender) +{ + m_DisEvent++; + RxHist.Add(pBitmapRX, &m_StartTime, m_HistM); + if( pHistView != NULL ) pHistView->Add(pBitmapRX); + UDHist->Position = 0; + AdjustBitmapFormat(pBitmapHist); + ::CopyBitmap(pBitmapHist, pBitmapRX); + TrigHistF(); + UpdatePic(1); + DispHistStat(); + SBWHist->Enabled = FALSE; + if( KHAC->Checked ){ + AutoCopyJob(m_StartTime, pBitmapHist); + } + m_DisEvent--; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::PBoxTXMouseDown(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( Button == mbLeft ){ + PBoxTX->BeginDrag(TRUE,0); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KHlpMainClick(TObject *Sender) +{ + if( Sender == KHlpMain ){ + ShowHelp(this, MsgEng ? "EMMSSTV.TXT":"MMSSTV.TXT"); + } + else { + ShowHelp(-1); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KHlpUpClick(TObject *Sender) +{ + ShowHelp(this, MsgEng ? "EUPDATE.TXT":"UPDATE.TXT"); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KHlpPadClick(TObject *Sender) +{ + sys.m_HelpNotePad = InvMenu(KHlpPad); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::DropFile(tagMSG &Msg) +{ + HDROP hDrop = (HDROP)Msg.wParam; + POINT N; + char fname[256]; + if( Msg.hwnd == PanelS->Handle ){ + if( ::DragQueryPoint(hDrop, &N) ){ + m_DragNo = GetStockNo(N.x, N.y); + if( m_DragNo >= 0 ){ + m_DragDataNo = UDStock->Position * m_SMax + m_DragNo; + if( ::DragQueryFile(hDrop, 0, fname, sizeof(fname)) ){ + ::SetForegroundWindow(Handle); + LPCSTR pExt = GetEXT(fname); + if( IsPic(pExt) ){ + int r; + TPicRectDlg *pBox = new TPicRectDlg(this); + r = ::LoadImage(pBox->pBitmap, fname); + if( r == TRUE ){ + Graphics::TBitmap *pBitmap = CreateBitmap(m_PSSize[m_DragNo] & 0x0000ffff, m_PSSize[m_DragNo]>>16, -1); +// Graphics::TBitmap *pBitmap = LoadBitmapS(m_DragNo); + if( pBox->Copy(pBitmap) == TRUE ){ + SaveBitmapS(pBitmap, m_DragNo); + UpdateTabS(); + } + delete pBitmap; + } + delete pBox; + } + else { + ErrorMB("'%s' is not supported.", fname); + } + } + } + } + ::DragFinish(hDrop); + } + else if( Msg.hwnd == PanelTX->Handle ){ // 送信画面へのドロップ + if( ::DragQueryFile(hDrop, 0, fname, sizeof(fname)) ){ + ::SetForegroundWindow(Handle); + LPCSTR pExt = GetEXT(fname); + if( IsPic(pExt) ){ + int r; + TPicRectDlg *pBox = new TPicRectDlg(this); + r = ::LoadImage(pBox->pBitmap, fname); + if( r == TRUE ){ + if( pBox->Copy(pBitmapTXM) == TRUE ){ + MakeTxBitmap(0); + PBoxTXPaint(NULL); + } + } + delete pBox; + } + else { + AdjustPage(pgTemp); + goto _tdrop; +// ErrorMB("'%s' is not supported.", fname); + } + } + ::DragFinish(hDrop); + } + else if( Msg.hwnd == PanelTemp->Handle ){ // テンプレートへのドロップ +_tdrop:; + if( ::DragQueryPoint(hDrop, &N) ){ + if( ::DragQueryFile(hDrop, 0, fname, sizeof(fname)) ){ + ::SetForegroundWindow(Handle); + LPCSTR pExt = GetEXT(fname); + int b; + if( ((b = !strcmpi(pExt, "BMP")) != 0) || IsPic(pExt) ){ + Graphics::TBitmap *pBitmap = new Graphics::TBitmap; + if( ::LoadImage(pBitmap, fname) == TRUE ){ + DropPic(N.x, N.y, pBitmap, b ? 2 : 1); + } + delete pBitmap; + } + else if( !strcmpi(pExt, "MTM") ){ + SaveUndo(); + LoadTemplate(&DrawMain, fname, NULL); + UpdateTemp(); + } + else if( !strcmpi(pExt, "MTI") ){ + LoadTemplate(&DrawTemp, fname, NULL); + AddTemplate(&DrawTemp); + UpdateTemp(); + } + else if( !strcmpi(pExt, "DLL") ){ + DropLib(N.x, N.y, fname); + } + else { + DropOle(N.x, N.y, fname, 1); + } + } + } + ::DragFinish(hDrop); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::LoadDefTemp(void) +{ + char fname[256]; + int i; + for( i = 0; i < 5; i++ ){ + sprintf(fname, "%sdef%d.mtm", BgnDir, i+1); + if( LoadTemplate(&DrawTemp, fname, NULL) != TRUE ) break; + SaveStockTemp(&DrawTemp, i); + if( i == 0 ) DrawMain.Copy(&DrawTemp); + } + DrawTemp.FreeItem(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KFL1Click(TObject *Sender) +{ + sys.m_FFTGain = 0; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KFM1Click(TObject *Sender) +{ + sys.m_FFTGain = 1; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KFH1Click(TObject *Sender) +{ + sys.m_FFTGain = 2; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KFT1Click(TObject *Sender) +{ + sys.m_FFTGain = 3; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KFL2Click(TObject *Sender) +{ + sys.m_FFTGain = 4; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KFM2Click(TObject *Sender) +{ + sys.m_FFTGain = 5; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KFH2Click(TObject *Sender) +{ + sys.m_FFTGain = 6; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KFT2Click(TObject *Sender) +{ + sys.m_FFTGain = 7; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KRSClick(TObject *Sender) +{ + sys.m_FFTResp = 2; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KRMClick(TObject *Sender) +{ + sys.m_FFTResp = 1; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KRFClick(TObject *Sender) +{ + sys.m_FFTResp = 0; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KViewClick(TObject *Sender) +{ + switch(sys.m_FFTType){ + case 0: + KSOFF->Checked = TRUE; + break; + case 1: + KSFFT->Checked = TRUE; + break; + default: + KSFQ->Checked = TRUE; + break; + } + switch(sys.m_FFTWidth){ + case 0: + KFW30->Checked = TRUE; + break; + case 1: + KFW20->Checked = TRUE; + break; + default: + KFW15->Checked = TRUE; + break; + } + switch(sys.m_FFTResp){ + case 2: + KRS->Checked = TRUE; + break; + case 1: + KRM->Checked = TRUE; + break; + case 0: + KRF->Checked = TRUE; + break; + } + switch(sys.m_FFTGain){ + case 0: + KFL1->Checked = TRUE; + break; + case 1: + KFM1->Checked = TRUE; + break; + case 2: + KFH1->Checked = TRUE; + break; + case 3: + KFT1->Checked = TRUE; + break; + case 4: + KFL2->Checked = TRUE; + break; + case 5: + KFM2->Checked = TRUE; + break; + case 6: + KFH2->Checked = TRUE; + break; + case 7: + KFT2->Checked = TRUE; + break; + } + KFTA->Checked = sys.m_FFTAGC; + switch(sys.m_FFTStg){ + case 0: + KFSOF->Checked = TRUE; + break; + case 1: + KFSQ->Checked = TRUE; + break; + case 2: + KFSS->Checked = TRUE; + break; + case 3: + KFSL->Checked = TRUE; + break; + } + switch(sys.m_FFTPriority){ + case 0: + KFTD1->Checked = TRUE; + break; + case 1: + KFTD2->Checked = TRUE; + break; + case 2: + KFTD3->Checked = TRUE; + break; + case 3: + KFTD4->Checked = TRUE; + break; + default: + KFTD5->Checked = TRUE; + break; + } + if(pDem->m_LevelType){ + KVLSY->Checked = TRUE; + } + else { + KVLSG->Checked = TRUE; + } + KVR->Checked = pRxView != NULL ? TRUE : FALSE; + KVS->Checked = pSyncView != NULL ? TRUE : FALSE; + KVH->Checked = pHistView != NULL ? TRUE : FALSE; + KVC->Checked = pCtrBtn != NULL ? TRUE : FALSE; + switch(sys.m_DivMode){ + case 1: + KVSD2->Checked = TRUE; + break; + case 2: + KVSD3->Checked = TRUE; + break; + default: + KVSD1->Checked = TRUE; + break; + } + AdjustFileView(); + MultProc(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::FormKeyDown(TObject *Sender, WORD &Key, + TShiftState Shift) +{ + if( m_MainPage == pgTemp ){ + if( DrawMain.pSel != NULL ){ + TShiftState sf1, sf2; + sf1 << ssShift; + sf2 << ssShift; + sf1 *= Shift; + int sft = (sf1 == sf2) ? TRUE : FALSE; + CDrawText *pText = NULL; + if( sft && (DrawMain.pSel->m_Command == CM_TEXT) ) pText = (CDrawText *)DrawMain.pSel; + switch(Key){ + case VK_UP: + AdjustTempView(1); + if( pText != NULL ){ + pText->pFont->Height++; + pText->UpdateText(); + } + else { + DrawMain.pSel->StartMove(PBoxTemp->Canvas, 0, 0, sft ? HT_B : HT_I); + DrawMain.pSel->Moving(0, -1); + DrawMain.pSel->Move(0, -1); + } + AdjustTempView(0); + if( KTAP->Checked ) DrawMain.AdjustTransPoint(); + UpdateTemp(); + Key = 0; + break; + case VK_DOWN: + AdjustTempView(1); + if( pText != NULL ){ + pText->pFont->Height--; + pText->UpdateText(); + } + else { + DrawMain.pSel->StartMove(PBoxTemp->Canvas, 0, 0, sft ? HT_B : HT_I); + DrawMain.pSel->Moving(0, 1); + DrawMain.pSel->Move(0, 1); + } + AdjustTempView(0); + if( KTAP->Checked ) DrawMain.AdjustTransPoint(); + UpdateTemp(); + Key = 0; + break; + case VK_LEFT: + AdjustTempView(1); + if( pText != NULL ){ + pText->pFont->Height++; + pText->UpdateText(); + } + else { + DrawMain.pSel->StartMove(PBoxTemp->Canvas, 0, 0, sft ? HT_R : HT_I); + DrawMain.pSel->Moving(-1, 0); + DrawMain.pSel->Move(-1, 0); + } + AdjustTempView(0); + if( KTAP->Checked ) DrawMain.AdjustTransPoint(); + UpdateTemp(); + Key = 0; + break; + case VK_RIGHT: + AdjustTempView(1); + if( pText != NULL ){ + pText->pFont->Height--; + pText->UpdateText(); + } + else { + DrawMain.pSel->StartMove(PBoxTemp->Canvas, 0, 0, sft ? HT_R : HT_I); + DrawMain.pSel->Moving(1, 0); + DrawMain.pSel->Move(1, 0); + } + AdjustTempView(0); + if( KTAP->Checked ) DrawMain.AdjustTransPoint(); + UpdateTemp(); + Key = 0; + break; + } + } + } + else if( m_MainPage == pgTX ){ + TShiftState sa1, sa2; + + sa1 << ssAlt; + sa2 << ssAlt; + sa1 *= Shift; + if( sa1 == sa2 ){ // ALT+Any + switch(Key){ + case 'T': + if( SBTX->Enabled ){ + SBTX->Down = SBTX->Down ? 0 : 1; + SBTXClick(NULL); + Key = 0; + } + break; + case 'U': + if( SBTune->Enabled ){ + SBTune->Down = SBTune->Down ? 0 : 1; + SBTuneClick(NULL); + Key = 0; + } + break; + } + } + } + if( pCtrBtn != NULL ){ + if( Key == VK_F9 ){ + pCtrBtn->SBTXClick(NULL); + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::FormKeyUp(TObject *Sender, WORD &Key, + TShiftState Shift) +{ + TShiftState sa1, sa2; + + sa1 << ssAlt; + sa2 << ssAlt; + sa1 *= Shift; + if( sa1 == sa2 ){ // ALT+Any + switch(Key){ + case 'C': + if( HisCall->CanFocus() ) HisCall->SetFocus(); + Key = 0; + break; + case 'N': + if( HisName->CanFocus() ) HisName->SetFocus(); + Key = 0; + break; + case 'Q': + if( HisQTH->CanFocus() ) HisQTH->SetFocus(); + Key = 0; + break; + case 'L': + SBListClick(NULL); + Key = 0; + break; + } + } + else if( Key == VK_RETURN ){ + if( ActiveControl == HisCall ){ + if( !HisCall->Text.IsEmpty() ){ + FindCall(); + MultProc(); + SBULogClick(NULL); + } + Key = 0; + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KVOutClick(TObject *Sender) +{ + HWND hWnd = ::FindWindow("Volume Control", NULL); + if( hWnd != NULL ){ + ::PostMessage(hWnd, WM_CLOSE, 0, 0); + ::Sleep(200); + MultProc(); + } + char cmd[128]; + + if( WinVista ){ + if( Sender != KVOut ){ + strcpy(cmd, "control.exe mmsys.cpl,,1"); + } + else { + strcpy(cmd, "sndvol.exe"); + } + } + else { + strcpy(cmd, "SNDVOL32.EXE"); + if( WinNT && (Sender != KVOut) ) strcat(cmd, " /R"); + } + + WinExec(cmd, SW_SHOW); + MultProc(); + if( !WinNT && (Sender != KVOut) ){ + CWaitCursor w; + int i; + for( i = 0; i < 30; i++ ){ + ::Sleep(100); + hWnd = ::FindWindow("Volume Control", NULL); + if( hWnd != NULL ) break; + MultProc(); + } + if( i < 30 ){ + ::SetForegroundWindow(hWnd); + ::Sleep(100); + const short _tt[]={ + VK_MENU, 'P', 'P'|0x8000, VK_MENU|0x8000, + 'R', 'R'|0x8000, VK_TAB, VK_TAB|0x8000, + VK_DOWN, VK_DOWN|0x8000, VK_RETURN, VK_RETURN|0x8000, + 0 + }; + KeyEvent(_tt); + } + } +} +//--------------------------------------------------------------------------- +// 周波数範囲情報の取得 +void __fastcall TMmsstv::GetFFTRect(int &FM, int &low) +{ + switch(sys.m_FFTWidth){ + case 0: // 3K + FM = 3000 * FFT_SIZE / FFTSamp; + low = 0; + break; + case 1: // 2K + FM = 2000 * FFT_SIZE / FFTSamp; + low = 700; + break; + case 2: // 1.5K + FM = 1500 * FFT_SIZE / FFTSamp; + low = 1000; + break; + } +} +//--------------------------------------------------------------------------- +// 周波数ゲージの表示 +void __fastcall TMmsstv::PBoxGPaint(TObject *Sender) +{ + if( pSound == NULL ) return; + + TCanvas *tp = PBoxG->Canvas; + if( Width < 760 ){ + tp->Font->Size = 7; + } + else { + tp->Font->Size = 8; + } + tp->Font->Color = clBlack; + + int FM; + int low; + GetFFTRect(FM, low); + int fq = pDem->m_Tick ? pDem->m_TickFreq : 1200; + char bf[32]; + int x = int(((fq - low)*FFT_SIZE*double(PBoxG->Width)/double(FFTSamp*FM)) + 0.5); + sprintf(bf, "%u", int(fq + g_dblToneOffset)); + int FH = tp->TextHeight(bf); + int y = PBoxG->Height - FH; + int FW = tp->TextWidth(bf); + x -= FW/2; + tp->TextOut(x, y, bf); + if( pDem->m_Tick ) return; + + x = m_FX[1]; + sprintf(bf, "%u", int(1500 + g_dblToneOffset)); + FW = tp->TextWidth(bf); + x -= FW/2; + tp->TextOut(x, y, bf); + x = m_FX[0]; + sprintf(bf, "%u", int(1900 + g_dblToneOffset)); + x -= FW/2; + tp->TextOut(x, y, bf); + x = m_FX[2]; + sprintf(bf, "%u", int(2300 + g_dblToneOffset)); + x -= FW/2; + tp->TextOut(x, y, bf); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KFSOFClick(TObject *Sender) +{ + sys.m_FFTStg = 0; + InitFFT(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KFSQClick(TObject *Sender) +{ + sys.m_FFTStg = 1; + InitFFT(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KFSSClick(TObject *Sender) +{ + sys.m_FFTStg = 2; + InitFFT(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KFSLClick(TObject *Sender) +{ + sys.m_FFTStg = 3; + InitFFT(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::UDSampClick(TObject *Sender, TUDBtnType Button) +{ + if( Button == btNext ){ + SSTVSET.m_SampFreq += 0.02; + } + else { + SSTVSET.m_SampFreq -= 0.02; + } + SSTVSET.m_SampFreq = NormalSampFreq(SSTVSET.m_SampFreq, 50); + if( (pDem->m_StgBuf != NULL) || WaveStg.IsOpen() ){ + m_ReqSampChg = 5; + } + else { // No buffer + UpdateSampFreq(); + } + DispSyncStat(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SBPhaseClick(TObject *Sender) +{ + if( SBPhase->Down || SBSlant->Down ){ + PBoxD12->Cursor = crCross; + } + else { + PBoxD12->Cursor = crDefault; + } +} +//--------------------------------------------------------------------------- +// フォルダの変更 +void __fastcall TMmsstv::KHCDClick(TObject *Sender) +{ + if( MsgEng ){ + SaveDialog->Title = "Move history files folder"; + } + else { + SaveDialog->Title = "履歴ファイルのフォルダを変更"; + } + SaveDialog->Filter = ""; + SaveDialog->FileName = "History.bin"; + SaveDialog->DefaultExt = "bin"; + SaveDialog->InitialDir = HistDir; + SetDisPaint(); + NormalWindow(this); + if( SaveDialog->Execute() == TRUE ){ + char bf[256]; + SetDirName(bf, AnsiString(SaveDialog->FileName).c_str()); //ja7ude 0521 + if( strcmp(bf, HistDir) ){ + if( YesNoMB( "%s >>> %s, are you sure?", HistDir, bf ) == IDYES ){ + RxHist.MoveDir(bf); + } + } + } + TopWindow(this); + ResDisPaint(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KSCDClick(TObject *Sender) +{ + if( MsgEng ){ + SaveDialog->Title = "Move stock files folder"; + } + else { + SaveDialog->Title = "ストックファイルのフォルダを変更"; + } + SaveDialog->Filter = ""; + SaveDialog->FileName = TEMPV106C; + SaveDialog->DefaultExt = "mtm"; + SaveDialog->InitialDir = StockDir; + SetDisPaint(); + NormalWindow(this); + if( SaveDialog->Execute() == TRUE ){ + char bf[256]; + SetDirName(bf, AnsiString(SaveDialog->FileName).c_str()); + if( strcmp(bf, StockDir) ){ + if( YesNoMB( "%s >>> %s, are you sure?", StockDir, bf ) == IDYES ){ + MoveStockDir(bf); + } + } + } + TopWindow(this); + ResDisPaint(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::MoveStockDir(LPCSTR pNewDir) +{ + if( !strcmp(pNewDir, StockDir) ) return; + + CWaitCursor wait; + char tname[256]; + char sname[256]; + + sprintf(sname, "%s"TEMPV106C, StockDir); + sprintf(tname, "%s"TEMPV106C, pNewDir); + if( CopyFile(sname, tname, FALSE) == FALSE ){ + ErrorMB( "Copy fail..." ); + return; + } + int i; + for( i = 0; i < (STOCKMAX*STOCKPAGE); i++ ){ + sprintf(sname, "%st%d.mtm", StockDir, i + 1); + sprintf(tname, "%st%d.mtm", pNewDir, i + 1); + CopyFile(sname, tname, FALSE); + unlink(sname); + + sprintf(sname, sys.m_UseJPEG ? "%sTxStock%u.jpg" : "%sTxStock%u.bmp", StockDir, i + 1); + sprintf(tname, sys.m_UseJPEG ? "%sTxStock%u.jpg" : "%sTxStock%u.bmp", pNewDir, i + 1); + CopyFile(sname, tname, FALSE); + unlink(sname); + } + sprintf(sname, "%sCurrent.bmp", StockDir); + unlink(sname); + sprintf(sname, "%s"TEMPV106C, StockDir); + unlink(sname); + sprintf(sname, "%s"TEMPV106L, StockDir); + unlink(sname); + + if( *lastp(StockDir) == '\\' ) *lastp(StockDir) = 0; + _rmdir(StockDir); + strcpy(StockDir, pNewDir); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::ChangeStockFormat(int sw) +{ + if( sw == sys.m_UseJPEG ) return; + + CWaitCursor wait; + Graphics::TBitmap *pBitmap = new Graphics::TBitmap(); + AdjustBitmapFormat(pBitmap); + + char tname[256]; + char sname[256]; + int i; + for( i = 0; i < STOCKMAX; i++ ){ + sprintf(sname, sw ? "%sTxStock%u.bmp" : "%sTxStock%u.jpg", StockDir, i + 1); + sprintf(tname, sw ? "%sTxStock%u.jpg" : "%sTxStock%u.bmp", StockDir, i + 1); + if( IsFile(sname) ){ + if( sw ){ + LoadBitmap(pBitmap, sname); + SaveJPEG(pBitmap, tname); + } + else { + LoadJPEG(pBitmap, sname); + SaveBitmap(pBitmap, tname); + } + unlink(sname); + } + } + delete pBitmap; + sys.m_UseJPEG = sw; +} + +void __fastcall TMmsstv::SBTuneMouseDown(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( Button == mbRight ){ + AnsiString as = pMod->m_TuneFreq; + if( InputMB("MMSSTV", MsgEng?"Enter tone frequency (Hz)":"トーン周波数(Hz)を入力", as) == TRUE ){ + int d; + sscanf(as.c_str(), "%u", &d); + if( (d >= 100) && (d <= 3000) ){ + pMod->m_TuneFreq = d; + UpdateToneFreq(); + } + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KEditClick(TObject *Sender) +{ + BOOL f = ::IsClipboardFormatAvailable(CF_BITMAP); + SBPaste->Enabled = f; + KEP->Enabled = f; + KES->Enabled = f; + KEX->Enabled = f; + switch(sys.m_Way240){ + case 0: + KEW1->Checked = TRUE; + break; + case 1: + KEW2->Checked = TRUE; + break; + case 2: + KEW3->Checked = TRUE; + break; + default: + KEW4->Checked = TRUE; + break; + } + MultProc(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KERClick(TObject *Sender) +{ + CopyBitmap(pBitmapRX); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KESClick(TObject *Sender) +{ +// + TClipboard *pCB = Clipboard(); + if (pCB->HasFormat(CF_BITMAP)){ + Graphics::TBitmap *pBitmap = new Graphics::TBitmap(); + AdjustBitmapFormat(pBitmap); + try + { + pBitmap->LoadFromClipboardFormat(CF_BITMAP, pCB->GetAsHandle(CF_BITMAP), 0); + + MultProc(); + pBitmapTXM = RemakeBitmap(pBitmapTXM, -1); + MultProc(); + CopyAutoSize(pBitmapTXM, pBitmap); + MultProc(); + } + catch (...) + { + ErrorMB( "Clipboard error." ); + } + delete pBitmap; + AdjustPage(pgTX); + MakeTxBitmap(0); + PBoxTXPaint(NULL); + } + AdjustFocus(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KHFJClick(TObject *Sender) +{ + if( RxHist.m_UseJPEG ) return; + + int r = IDYES; + if( RxHist.m_Head.m_Cnt ){ + r = YesNoMB( MsgEng ? "MMSSTV will convert the format in all the files which were stored already.\r\n\rThis processing may take a long time, are you sure?" : "既存のファイルのフォーマットを変更します.\r\n\r\nこの処理は時間がかかる可能性があります. ほんまに変換しますか?" ); + } + if( r == IDYES ){ + RxHist.ChangeFormat(1); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KHFBClick(TObject *Sender) +{ + if( !RxHist.m_UseJPEG ) return; + + int r = IDYES; + if( RxHist.m_Head.m_Cnt ){ + r = YesNoMB( MsgEng ? "MMSSTV will convert the format in all the files which were stored already.\r\n\rThis processing may take a long time, are you sure?" : "既存のファイルのフォーマットを変更します.\r\n\r\nこの処理は時間がかかる可能性があります. ほんまに変換しますか?" ); + } + if( r == IDYES ){ + RxHist.ChangeFormat(0); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KSFJClick(TObject *Sender) +{ + if( sys.m_UseJPEG ) return; + + int r = YesNoMB( MsgEng ? "MMSSTV will convert the format in all the files which were stored already.\r\n\rThis processing may take a long time, are you sure?" : "既存のファイルのフォーマットを変更します.\r\n\r\nこの処理は時間がかかる可能性があります. ほんまに変換しますか?" ); + if( r == IDYES ){ + ChangeStockFormat(1); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KSFBClick(TObject *Sender) +{ + if( !sys.m_UseJPEG ) return; + + int r = YesNoMB( MsgEng ? "MMSSTV will convert the format in all the files which were stored already.\r\n\rThis processing may take a long time, are you sure?" : "既存のファイルのフォーマットを変更します.\r\n\r\nこの処理は時間がかかる可能性があります. ほんまに変換しますか?" ); + if( r == IDYES ){ + ChangeStockFormat(0); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KRASClick(TObject *Sender) +{ + sys.m_AutoStop = sys.m_AutoStop ? 0 : 1; + UpdateUI(); + if( pCtrBtn != NULL ) pCtrBtn->UpdateBtn(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KRASYClick(TObject *Sender) +{ + sys.m_AutoSync = sys.m_AutoSync ? 0 : 1; + UpdateUI(); + if( pCtrBtn != NULL ) pCtrBtn->UpdateBtn(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KRARClick(TObject *Sender) +{ + pDem->m_SyncRestart = pDem->m_SyncRestart ? 0 : 1; + pDem->CalcBPF(); + UpdateUI(); + if( pCtrBtn != NULL ) pCtrBtn->UpdateBtn(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::PopupRPopup(TObject *Sender) +{ + CSSTVDEM *dp = pDem; + int f1 = (pRxView != NULL) && (PopupR->PopupComponent == pRxView->PBox); + int f2 = (pSyncView != NULL) && (PopupR->PopupComponent == pSyncView->PBox); + int f3 = (PopupR->PopupComponent == PBoxD12 ); + KRFS->Enabled = dp->m_Sync && (SSTVSET.m_Mode != smAVT); + KRAS->Checked = sys.m_AutoStop; + KRAR->Checked = dp->m_SyncRestart; + KRH->Enabled = SBWHist->Enabled; + KRSA->Enabled = sys.m_UseRxBuff ? TRUE : FALSE; + KRASY->Checked = sys.m_AutoSync; + KRCS->Enabled = ( ((dp->m_StgBuf != NULL) || WaveStg.IsOpen()) && (dp->m_wStgLine >= 16) && (SSTVSET.m_Mode != smAVT) ) ? TRUE : FALSE; + KRCR->Enabled = KRCS->Enabled; + KRSR->Enabled = (sys.m_SampFreq != SSTVSET.m_SampFreq); + + if( f1 ){ // 常時受信画面 + if( (pRxView->ClientWidth != pBitmapRX->Width) || + (pRxView->ClientHeight != pBitmapRX->Height) + ){ + KRR->Enabled = TRUE; + } + else { + KRR->Enabled = FALSE; + } + if( (pRxView->ClientWidth != 320) || + (pRxView->ClientHeight != 256) + ){ + KRRC->Enabled = TRUE; + } + else { + KRRC->Enabled = FALSE; + } + KRC->Enabled = TRUE; + KRSW->Enabled = TRUE; + KRSD->Enabled = FALSE; + KRB->Enabled = TRUE; + KRCD->Enabled = TRUE; + } + else if( f2 ){ // 常時Sync画面 + if( (pSyncView->ClientWidth != pBitmapD12->Width) || + (pSyncView->ClientHeight != pBitmapD12->Height) + ){ + KRRC->Enabled = TRUE; + } + else { + KRRC->Enabled = FALSE; + } + KRR->Enabled = FALSE; + KRC->Enabled = FALSE; + KRH->Enabled = FALSE; + KRSW->Enabled = FALSE; + KRSD->Enabled = FALSE; + KRB->Enabled = FALSE; + KRCD->Enabled = FALSE; + } + else if( f3 ){ // 同期画面 + KRR->Enabled = FALSE; + KRRC->Enabled = FALSE; + KRC->Enabled = FALSE; + KRH->Enabled = FALSE; + KRSW->Enabled = FALSE; + KRSD->Enabled = FALSE; + KRB->Enabled = FALSE; + KRCD->Enabled = FALSE; + } + else { // 受信画面 + KRR->Enabled = FALSE; + KRRC->Enabled = FALSE; + KRC->Enabled = TRUE; + KRSW->Enabled = TRUE; + KRSD->Enabled = TRUE; + KRB->Enabled = TRUE; + KRCD->Enabled = FALSE; + } + KRSD->Checked = sys.m_ShowSizeRX; + switch(m_SyncAccuracy){ + case 0: + KRI1->Checked = TRUE; + break; + case 1: + KRI2->Checked = TRUE; + break; + default: + KRI3->Checked = TRUE; + break; + } + KRI->Enabled = KRSA->Enabled; + MultProc(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KRRClick(TObject *Sender) +{ + if( pRxView != NULL ){ + if( PopupR->PopupComponent == pRxView->PBox ){ + pRxView->ClientWidth = pBitmapRX->Width; + pRxView->ClientHeight = pBitmapRX->Height; + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KRRCClick(TObject *Sender) +{ + if( pRxView != NULL ){ + if( PopupR->PopupComponent == pRxView->PBox ){ + pRxView->ClientWidth = 320; + pRxView->ClientHeight = 256; + } + } + if( pSyncView != NULL ){ + if( PopupR->PopupComponent == pSyncView->PBox ){ + pSyncView->ClientWidth = pBitmapD12->Width; + pSyncView->ClientHeight = pBitmapD12->Height; + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KVRClick(TObject *Sender) +{ + if( pRxView == NULL ){ + if( KRCD->Checked ){ + pRxView = new TRxViewDlg(NULL); + pRxView->ParentWindow = GetDesktopWindow(); + } + else { + pRxView = new TRxViewDlg(this); + } + pRxView->PBox->PopupMenu = PopupR; + pRxView->SetViewPos(sys.m_RxViewLeft, sys.m_RxViewTop, sys.m_RxViewWidth, sys.m_RxViewHeight, pBitmapRX); + if( (pSound != NULL) && pDem->m_Sync ){ + pRxView->UpdateTitle(SSTVSET.m_Mode, 0); + } + else { + pRxView->UpdateTitle(-1, 0); + } + pRxView->Visible = TRUE; + m_TimerRXV = 0; + } + else { + pRxView->GetViewPos(sys.m_RxViewLeft, sys.m_RxViewTop, sys.m_RxViewWidth, sys.m_RxViewHeight); + delete pRxView; + pRxView = NULL; + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KVSClick(TObject *Sender) +{ + if( pSyncView == NULL ){ + pSyncView = new TRxViewDlg(this); + pSyncView->UpdateSyncTitle(SSTVSET.m_SampFreq); + pSyncView->PBox->PopupMenu = PopupR; + pSyncView->SetViewPos(sys.m_SyncViewLeft, sys.m_SyncViewTop, sys.m_SyncViewWidth, sys.m_SyncViewHeight, pBitmapD12); + pSyncView->Visible = TRUE; + m_TimerRXS = 0; + } + else { + pSyncView->GetViewPos(sys.m_SyncViewLeft, sys.m_SyncViewTop, sys.m_SyncViewWidth, sys.m_SyncViewHeight); + delete pSyncView; + pSyncView = NULL; + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KVHClick(TObject *Sender) +{ + if( pHistView == NULL ){ + OpenHistView(); + } + else { + sys.m_HistViewTB = pHistView->m_TitleBar; + CloseHistView(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KVCClick(TObject *Sender) +{ + if( pCtrBtn == NULL ){ + pCtrBtn = new TCtrBtnWnd(this); + pCtrBtn->SetViewPos(sys.m_CtrBtnLeft, sys.m_CtrBtnTop, sys.m_CtrBtnWidth, sys.m_CtrBtnHeight); + pCtrBtn->UpdateBtn(); + pCtrBtn->Visible = TRUE; + } + else { + pCtrBtn->GetViewPos(sys.m_CtrBtnLeft, sys.m_CtrBtnTop, sys.m_CtrBtnWidth, sys.m_CtrBtnHeight); + delete pCtrBtn; + pCtrBtn = NULL; + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::ShowFileView(int i, int ttl) +{ + CWaitCursor w; + + MultProc(); + TFileViewDlg *fp = pFileView[i] = new TFileViewDlg(this); + fp->m_MyIndex = i; + int MaxPage = sys.m_FileViewMaxPage[i]; + fp->m_MaxPage = MaxPage; + fp->MakeFileV(); + MultProc(); + fp->m_SSize = sys.m_FileViewSize[i] & 0x00000003; + fp->KBP->Checked = sys.m_FileViewSize[i] >> 16; + fp->UpdateSize(0); + MultProc(); + fp->m_CurPage = sys.m_FileViewCurPage[i]; + fp->SetCurPage(); + for( int j = 0; j < MaxPage; j++ ){ + CFILEV *cp = fp->pFileV[j]; + cp->m_Folder = sys.m_FileViewFolder[i][j].c_str(); + cp->m_Name = sys.m_FileViewName[i][j].c_str(); + cp->m_CurPage = sys.m_FileViewFMPage[i][j]; + cp->m_UseIndex = cp->m_CurPage & 0x80000000 ? 1 : 0; + cp->m_Type = (cp->m_CurPage >> 16) & 7; + cp->m_CurPage &= 0x0000ffff; + } + if( ttl ){ + fp->m_TitleBar = (sys.m_FileViewFlag[i] == 1) ? 1 : 0; + } + fp->SBMode->Down = sys.m_FileViewMode[i]; + fp->UD->Max = SHORT(pFileView[i]->pCurPage->m_CurPage + 1); + fp->UD->Position = SHORT(pFileView[i]->pCurPage->m_CurPage); + fp->SetViewPos(sys.m_FileViewLeft[i], sys.m_FileViewTop[i], sys.m_FileViewWidth[i], sys.m_FileViewHeight[i]); + if( ttl ){ + if( !fp->m_TitleBar ) fp->UpdateTitlebar(); + } + MultProc(); + pFileView[i] = fp; + if( ttl && TabS->TabIndex && fp->m_Overlap && + ((pStockView == NULL) || pStockView->Visible) + ){ + fp->Visible = FALSE; + fp->m_Suspend = 1; + } + else { + fp->Visible = TRUE; + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KVFClick(TObject *Sender) +{ + int i; + for( i = 0; i < 8; i++ ){ + if( pFileView[i] == NULL ){ + ShowFileView(i, 0); + break; + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KHACDClick(TObject *Sender) +{ + AnsiString as; + + as = sys.m_AutoSaveDir; + if( InputMB("MMSSTV", MsgEng ? + "Please enter a copy folder name": + "コピー先のフォルダ名を入力して下さい.", as) == TRUE + ){ + jstrupr(as.c_str()); + sys.m_AutoSaveDir = as; + PBoxHist->DragMode = sys.m_AutoSaveDir.IsEmpty() ? dmManual : dmAutomatic; + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KHWebClick(TObject *Sender) +{ + WebRef.ShowHTML("http://mmhamsoft.amateur-radio.ca/"); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KHRefClick(TObject *Sender) +{ + WebRef.ShowHTML(MsgEng ? "http://groups.yahoo.com/group/MM-SSTV/" : "http://www.egroups.co.jp/group/mmhamsoft/"); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::EditQSLDragOver(TObject *Sender, TObject *Source, + int X, int Y, TDragState State, bool &Accept) +{ + Accept = FALSE; + if( sys.m_AutoSaveDir.IsEmpty() ) return; + + if( Source == PBoxHist ){ + if( UDHist->Position < RxHist.m_Head.m_Cnt ){ + Accept = TRUE; + } + } + else if( Source == PBoxTX ){ + Accept = TRUE; + } + else if( (pHistView != NULL) && (pHistView->IsPBox(Source) >= 0) ){ + if( UDHist->Position < RxHist.m_Head.m_Cnt ){ + Accept = TRUE; + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::EditQSLDragDrop(TObject *Sender, TObject *Source, + int X, int Y) +{ + if( (Source == PBoxHist) || + ((pHistView != NULL) && (pHistView->IsPBox(Source) >= 0)) + ){ + if( UDHist->Position < RxHist.m_Head.m_Cnt ){ + SYSTEMTIME tim = RxHist.m_File[RxHist.m_CurRead].m_UTC; + AutoCopyJob(tim, pBitmapHist); + } + } + else if( Source == PBoxTX ){ + SYSTEMTIME tim; + GetUTC(&tim); + AutoCopyJob(tim, pBitmapTX); + } +} + +void __fastcall TMmsstv::InitProfile(void) +{ + int i; + PRODEM *mp = m_DemPro; + for( i = 0; i <= 8; i++, mp++ ){ + mp->Name = ""; + mp->VCOGain = 1.0; + mp->loopOrder = 1; + mp->loopFC = 1500; + mp->OutOrder = 3; + mp->OutFC = 900; + mp->Type = 2; + mp->crossOutOrder = 3; + mp->crossOutFC = 900; + mp->crossType = 0; + mp->crossSmooz = 2200; + mp->DemOff = 0; + mp->DemWhite = 128.0/16384.0; + mp->DemBlack = 128.0/16384.0; + mp->Differentiator = 0; + mp->DiffLevel = 0.8; + mp->DemCalibration = 0; + double *dp = mp->Dem17; + *dp++ = -1.636467e+04; + *dp++ = -1.428800e+04; + *dp++ = -1.223433e+04; + *dp++ = -1.019400e+04; + *dp++ = -8.179333e+03; + *dp++ = -6.145000e+03; + *dp++ = -4.088667e+03; + *dp++ = -2.063000e+03; + *dp++ = -1.233333e+01; + *dp++ = 2.050000e+03; + *dp++ = 4.105000e+03; + *dp++ = 6.209000e+03; + *dp++ = 8.332667e+03; + *dp++ = 1.045133e+04; + *dp++ = 1.256500e+04; + *dp++ = 1.463267e+04; + *dp = 1.663133e+04; + } + + mp = m_DemPro; + mp->Name = MsgEng ? "Hilbert transform" : "ヒルベルト変換"; + mp->Type = 2; + + mp++; + mp->Name = MsgEng ? "Zero crossing" : "ゼロクロス検波"; + mp->Type = 1; + mp->crossOutOrder = 3; + mp->crossOutFC = 900; + mp->DemCalibration = 1; + + mp++; + mp->Name = MsgEng ? "Zero crossing with Differentiator" : "ゼロクロス検波+微分処理"; + mp->Type = 1; + mp->crossOutOrder = 3; + mp->crossOutFC = 900; + mp->Differentiator = 1; + mp->DemCalibration = 1; + + m_DemPro[8].Type = 2; + m_DemPro[8].DemCalibration = 0; +} + +//--------------------------------------------------------------------------- +TMenuItem *__fastcall TMmsstv::GetKP(int n) +{ + TMenuItem *tbl[]={ + KP1, KP2, KP3, KP4, KP5, KP6, KP7, KP8, + }; + return tbl[n]; +} +//--------------------------------------------------------------------------- +TMenuItem *__fastcall TMmsstv::GetKPA(int n) +{ + TMenuItem *tbl[]={ + KPA1, KPA2, KPA3, KPA4, KPA5, KPA6, KPA7, KPA8, + }; + return tbl[n]; +} +//--------------------------------------------------------------------------- +TMenuItem *__fastcall TMmsstv::GetKPD(int n) +{ + TMenuItem *tbl[]={ + KPD1, KPD2, KPD3, KPD4, KPD5, KPD6, KPD7, KPD8, + }; + return tbl[n]; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::UpdateProFileMenu(void) +{ + int i; + for( i = 0; i < 8; i++ ){ + TMenuItem *tp = GetKP(i); + TMenuItem *dp = GetKPD(i); + if( m_DemPro[i].Name.IsEmpty() ){ + char bf[32]; + sprintf(bf, "Profile%d", i + 1); + tp->Caption = bf; + tp->Enabled = FALSE; + dp->Caption = bf; + dp->Enabled = FALSE; + } + else { + tp->Caption = m_DemPro[i].Name; + tp->Enabled = TRUE; + dp->Caption = tp->Caption; + dp->Enabled = TRUE; + } + GetKPA(i)->Caption = tp->Caption; + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KPAClick(TObject *Sender) +{ + if( pSound == NULL ) return; + int i; + for( i = 0; i < 8; i++ ){ + TMenuItem *tp = GetKPA(i); + if( Sender == tp ){ + AnsiString as = tp->Caption; + if( InputMB(MsgEng ? "Assign profile" : "プロファイルの登録", (Font->Charset != SHIFTJIS_CHARSET) ? "Enter name" : "名前を入力", as) == TRUE ){ + m_DemPro[i].Name = as; + m_DemPro[i].VCOGain = pDem->m_pll.m_vcogain; + m_DemPro[i].loopOrder = pDem->m_pll.m_loopOrder; + m_DemPro[i].loopFC = pDem->m_pll.m_loopFC; + m_DemPro[i].OutOrder = pDem->m_pll.m_outOrder; + m_DemPro[i].OutFC = pDem->m_pll.m_outFC; + m_DemPro[i].Type = pDem->m_Type; + m_DemPro[i].crossOutOrder = pDem->m_fqc.m_outOrder; + m_DemPro[i].crossOutFC = pDem->m_fqc.m_outFC; + + m_DemPro[i].crossType = pDem->m_fqc.m_Type; + m_DemPro[i].crossSmooz = pDem->m_fqc.m_SmoozFq; + + m_DemPro[i].DemOff = sys.m_DemOff; + m_DemPro[i].DemWhite = sys.m_DemWhite; + m_DemPro[i].DemBlack = sys.m_DemBlack; + m_DemPro[i].DemCalibration = sys.m_DemCalibration; + for( int j = 0; j < 17; j++ ){ + m_DemPro[i].Dem17[j] = sys.m_Dem17[j]; + } + m_DemPro[i].Differentiator = sys.m_Differentiator; + m_DemPro[i].DiffLevel = sys.m_DiffLevelP; + UpdateProFileMenu(); + } + break; + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KPDClick(TObject *Sender) +{ + if( pSound == NULL ) return; + int i; + for( i = 0; i < 8; i++ ){ + if( Sender == GetKPD(i) ){ + m_DemPro[i].Name = ""; + UpdateProFileMenu(); + break; + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SetProFile(int n) +{ + pDem->m_pll.SetVcoGain(m_DemPro[n].VCOGain); + pDem->m_pll.m_loopOrder = m_DemPro[n].loopOrder; + pDem->m_pll.m_loopFC = m_DemPro[n].loopFC; + pDem->m_pll.m_outOrder = m_DemPro[n].OutOrder; + pDem->m_pll.m_outFC = m_DemPro[n].OutFC; + pDem->m_pll.MakeLoopLPF(); + pDem->m_pll.MakeOutLPF(); + pDem->m_Type = m_DemPro[n].Type; + pDem->m_fqc.m_outOrder = m_DemPro[n].crossOutOrder; + pDem->m_fqc.m_outFC = m_DemPro[n].crossOutFC; + pDem->m_fqc.m_Type = m_DemPro[n].crossType; + pDem->m_fqc.m_SmoozFq = m_DemPro[n].crossSmooz; + pDem->m_fqc.CalcLPF(); + + sys.m_DemOff = m_DemPro[n].DemOff; + sys.m_DemWhite = m_DemPro[n].DemWhite; + sys.m_DemBlack = m_DemPro[n].DemBlack; + sys.m_DemCalibration = m_DemPro[n].DemCalibration; + for( int j = 0; j < 17; j++ ){ + sys.m_Dem17[j] = m_DemPro[n].Dem17[j]; + } + MakeCalibrationTable(); + + sys.m_Differentiator = m_DemPro[n].Differentiator; + sys.m_DiffLevelP = m_DemPro[n].DiffLevel; + sys.m_DiffLevelM = sys.m_DiffLevelP / 3.0; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KP1Click(TObject *Sender) +{ + if( pSound == NULL ) return; + int i; + for( i = 0; i < 8; i++ ){ + if( Sender == GetKP(i) ){ + SetProFile(i); + break; + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KPDefClick(TObject *Sender) +{ + SetProFile(8); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KPInitClick(TObject *Sender) +{ + InitProfile(); + SetProFile(8); + UpdateProFileMenu(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KPClick(TObject *Sender) +{ + int i; + for( i = 0; i < 8; i++ ){ + int f = 0; + if(GetKP(i)->Enabled ){ + if( m_DemPro[i].VCOGain != pDem->m_pll.m_vcogain ) f++; + if( m_DemPro[i].loopOrder != pDem->m_pll.m_loopOrder ) f++; + if( m_DemPro[i].loopFC != pDem->m_pll.m_loopFC) f++; + if( m_DemPro[i].OutOrder != pDem->m_pll.m_outOrder) f++; + if( m_DemPro[i].OutFC != pDem->m_pll.m_outFC ) f++; + if( m_DemPro[i].Type != pDem->m_Type ) f++; + if( m_DemPro[i].crossOutOrder != pDem->m_fqc.m_outOrder ) f++; + if( m_DemPro[i].crossOutFC != pDem->m_fqc.m_outFC ) f++; + + if( m_DemPro[i].crossType != pDem->m_fqc.m_Type ) f++; + if( m_DemPro[i].crossSmooz != pDem->m_fqc.m_SmoozFq ) f++; + + if( m_DemPro[i].DemOff != sys.m_DemOff ) f++; + if( m_DemPro[i].DemWhite != sys.m_DemWhite ) f++; + if( m_DemPro[i].DemBlack != sys.m_DemBlack ) f++; + if( m_DemPro[i].DemCalibration != sys.m_DemCalibration ) f++; + + if( m_DemPro[i].Differentiator != sys.m_Differentiator ) f++; + if( m_DemPro[i].DiffLevel != sys.m_DiffLevelP ) f++; + + GetKP(i)->Checked = f ? FALSE : TRUE; + } + else { + GetKP(i)->Checked = FALSE; + } + } + MultProc(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::HisNameChange(TObject *Sender) +{ + if( DrawMain.IsMacro("%n")||DrawMain.IsMacro("%J") ){ + TempDelay(); + SBULog->Enabled = TRUE; + UpdateUI(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::HisQTHChange(TObject *Sender) +{ + if( DrawMain.IsMacro("%q") ){ + TempDelay(); + SBULog->Enabled = TRUE; + UpdateUI(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::EditNoteChange(TObject *Sender) +{ + if( DrawMain.IsMacro("%o") ){ + TempDelay(); + SBULog->Enabled = TRUE; + UpdateUI(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SBTXFilClick(TObject *Sender) +{ + TPicFilterDlg *pBox = new TPicFilterDlg(this); + if( pBox->Execute(pBitmapTXM) == TRUE ){ + MakeTxBitmap(0); + PBoxTXPaint(NULL); + } + delete pBox; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SBHistFilClick(TObject *Sender) +{ + TPicFilterDlg *pBox = new TPicFilterDlg(this); + if( pBox->Execute(pBitmapHist) == TRUE ){ + PBoxHistPaint(NULL); + DrawMain.UpdatePic(pBitmapHistF); + UpdatePic(); + } + delete pBox; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KFW30Click(TObject *Sender) +{ + sys.m_FFTWidth = 0; + InitDrawFFT(); + PBoxG->Invalidate(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KFW20Click(TObject *Sender) +{ + sys.m_FFTWidth = 1; + InitDrawFFT(); + PBoxG->Invalidate(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KFW15Click(TObject *Sender) +{ + sys.m_FFTWidth = 2; + InitDrawFFT(); + PBoxG->Invalidate(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KRBClick(TObject *Sender) +{ + InitCustomColor(ColorDialog); + AddCustomColor(ColorDialog, sys.m_ColorRXB); + ColorDialog->Color = sys.m_ColorRXB; + SetDisPaint(); + if( ColorDialog->Execute() == TRUE ){ + sys.m_ColorRXB = ColorDialog->Color; + PanelRX->Color = sys.m_ColorRXB; + PanelHist->Color = sys.m_ColorRXB; + } + ResDisPaint(); +} +#if 0 +///---------------------------------------------------------------- +/// 多項式計算を行う +double Teira(double x, const double *p, int n) +{ + double y = *p++; + int i; + for( i = 1; i < n; i++, p++ ){ + y += pow(x, i)*(*p); + } + return y; +} +#endif +//--------------------------------------------------------------------------- +// 多項式変換テーブルを作成する +void __fastcall TMmsstv::MakeCalibrationTable(void) +{ + if( sys.m_DemCalibration ){ + if( pCalibration == NULL ){ + pCalibration = new short[4097]; + } + short *wp = pCalibration; + int i; +// FILE *fp = fopen("F:\\Color.TXT", "wt"); + for( i = 0; i <= 4096; i++, wp++ ){ + int d = (i - 2048) * 8; + int f = 0; + int c = -128; + int j; + for( j = 1; j <= 16; j++, c += 16 ){ + if( d < sys.m_Dem17[j] ){ + *wp = c + (d - sys.m_Dem17[j-1]) * (16.0 / (sys.m_Dem17[j] - sys.m_Dem17[j-1])); + f++; + break; + } + } + if( !f ){ + *wp = 128; + } +// fprintf(fp, "%4u:%d\n", i, *wp); + } +// fclose(fp); + } + else { + if( pCalibration != NULL ){ + delete pCalibration; + pCalibration = NULL; + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KHDS1Click(TObject *Sender) +{ + sys.m_HDDSize = 0; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KHDS2Click(TObject *Sender) +{ + sys.m_HDDSize = 1; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KHDS3Click(TObject *Sender) +{ + sys.m_HDDSize = 2; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KHDS4Click(TObject *Sender) +{ + sys.m_HDDSize = 3; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KHDS5Click(TObject *Sender) +{ + sys.m_HDDSize = 4; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KHDS6Click(TObject *Sender) +{ + sys.m_HDDSize = 5; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KVWClick(TObject *Sender) +{ + InvMenu(KVW); + FormResize(NULL); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KFTAClick(TObject *Sender) +{ + sys.m_FFTAGC = sys.m_FFTAGC ? 0 : 1; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KFTD1Click(TObject *Sender) +{ + sys.m_FFTPriority = 0; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KFTD2Click(TObject *Sender) +{ + sys.m_FFTPriority = 1; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KFTD3Click(TObject *Sender) +{ + sys.m_FFTPriority = 2; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KFTD4Click(TObject *Sender) +{ + sys.m_FFTPriority = 3; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KFTD5Click(TObject *Sender) +{ + sys.m_FFTPriority = 4; +} +//--------------------------------------------------------------------------- +TMenuItem *__fastcall TMmsstv::GetKX(int n) +{ + TMenuItem *tbl[]={ + KX1, KX2, KX3, KX4, KX5, KX6, KX7, KX8, + }; + return tbl[n]; +} +//--------------------------------------------------------------------------- +TMenuItem *__fastcall TMmsstv::GetKXA(int n) +{ + TMenuItem *tbl[]={ + KXA1, KXA2, KXA3, KXA4, KXA5, KXA6, KXA7, KXA8, + }; + return tbl[n]; +} +//--------------------------------------------------------------------------- +TMenuItem *__fastcall TMmsstv::GetKXD(int n) +{ + TMenuItem *tbl[]={ + KXD1, KXD2, KXD3, KXD4, KXD5, KXD6, KXD7, KXD8, + }; + return tbl[n]; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::UpdateProgramMenu(void) +{ + int i; + for( i = 0; i < 8; i++ ){ + TMenuItem *tp = GetKX(i); + TMenuItem *dp = GetKXD(i); + if( sys.m_ExtName[i].IsEmpty() ){ + char bf[32]; + sprintf(bf, "Program%d", i + 1); + tp->Caption = bf; + dp->Caption = bf; + } + else { + tp->Caption = sys.m_ExtName[i]; + dp->Caption = sys.m_ExtName[i]; + } + if( sys.m_ExtMode[i] ){ + tp->Enabled = TRUE; + dp->Enabled = TRUE; + } + else { + tp->Enabled = FALSE; + dp->Enabled = FALSE; + } + GetKXA(i)->Caption = tp->Caption; + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::ExecExtCmd(int n) +{ + if( sys.m_ExtCmd[n].IsEmpty() || !IsFile(sys.m_ExtCmd[n].c_str()) ){ + if( !AssignExtCmd(n) ) return; + } + if( sys.m_ExtMode[n] == 2 ){ + KXSClick(NULL); + } + char bf[256]; + SetDirName(bf, sys.m_ExtCmd[n].c_str()); + ::SetCurrentDirectory(bf); + ::WinExec(sys.m_ExtCmd[n].c_str(), SW_SHOWDEFAULT); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KXRClick(TObject *Sender) +{ + CWaitCursor wait; + pDem->OpenCloseRxBuff(); + pSound->fftIN.TrigFFT(); + pSound->m_suspack = 0; + pSound->m_susp = 0; + for( int i = 0; (i < 20) && !pSound->m_suspack; i++ ) ::Sleep(100); + if( pSound->m_susp ){ // 解除に失敗 + m_SuspMinimized = FALSE; + return; + } + COMM.change = 1; + RADIO.change = 1; + OpenCloseCom(); + ::SetCurrentDirectory(BgnDir); + Log.Close(); + Log.Open(NULL, TRUE); + RxHist.Open(); + UpdateHist(); + UpdateModeBtn(); + DisPaint = FALSE; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KXSClick(TObject *Sender) +{ + CWaitCursor wait; + if( SBTX->Down ){ + ToRX(); + } + if( pDem->m_Sync ){ + pDem->Stop(); + } + pSound->m_suspack = 0; + pSound->m_susp = 1; + if( pComm != NULL ){ + delete pComm; + pComm = NULL; + } + if( pRadio != NULL ){ + delete pRadio; + pRadio = NULL; + } + Log.Close(); + Log.Open(NULL, TRUE); + RxHist.Close(); + int i; + for( i = 0; (i < 20) && !pSound->m_suspack; i++ ) ::Sleep(100); + pSound->m_suspack = 0; + pDem->FreeRxBuff(); + DisPaint = TRUE; + m_SuspMinimized = (Sender != KXS); + if( m_SuspMinimized ) Application->Minimize(); +} +//--------------------------------------------------------------------------- +int __fastcall TMmsstv::AssignExtCmd(int n) +{ + int r = FALSE; + int Susp = sys.m_ExtMode[n] == 2 ? 1 : 0; + TExtCmdDlg *pBox = new TExtCmdDlg(this); + if( pBox->Execute(sys.m_ExtName[n], sys.m_ExtCmd[n], Susp) == TRUE ){ + sys.m_ExtMode[n] = Susp + 1; + r = TRUE; + } + delete pBox; + return r; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KX1Click(TObject *Sender) +{ + int i; + for( i = 0; i < 8; i++ ){ + if( Sender == GetKX(i) ){ + ExecExtCmd(i); + break; + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KXA1Click(TObject *Sender) +{ + int i; + for( i = 0; i < 8; i++ ){ + if( Sender == GetKXA(i) ){ + AssignExtCmd(i); + break; + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KXD1Click(TObject *Sender) +{ + int i; + for( i = 0; i < 8; i++ ){ + if( Sender == GetKXD(i) ){ + sys.m_ExtName[i] = ""; + sys.m_ExtMode[i] = 0; + break; + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KXClick(TObject *Sender) +{ + KXR->Enabled = pSound->m_susp ? TRUE : FALSE; + KXS->Enabled = pSound->m_susp ? FALSE : TRUE; + KXSM->Enabled = KXS->Enabled; + UpdateProgramMenu(); + MultProc(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KTAPClick(TObject *Sender) +{ + InvMenu(KTAP); + if( KTAP->Checked ){ + DrawMain.AdjustTransPoint(); + UpdateTemp(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KTACClick(TObject *Sender) +{ + SaveUndo(); + DrawMain.AdjustTransColor(pBitmapTemp); + DrawMain.UpdatePic(pBitmapHistF); + UpdateTemp(); +} +//--------------------------------------------------------------------------- + +void __fastcall TMmsstv::KVLSGClick(TObject *Sender) +{ + pDem->m_LevelType = 0; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KVLSYClick(TObject *Sender) +{ + pDem->m_LevelType = 1; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KHTBClick(TObject *Sender) +{ + if( pHistView != NULL ){ + pHistView->m_TitleBar = pHistView->m_TitleBar ? 0 : 1; + sys.m_HistViewTB = pHistView->m_TitleBar; + pHistView->UpdateTitlebar(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::OnMove(TMessage *Message) +{ + if( (pHistView != NULL) && !pHistView->m_TitleBar ){ + pHistView->Top += (Top - m_OrgTop); + pHistView->Left += (Left - m_OrgLeft); + } + for( int i = 0; i < 8; i++ ){ + if( pFileView[i] != NULL && !pFileView[i]->m_TitleBar ){ + pFileView[i]->Top += (Top - m_OrgTop); + pFileView[i]->Left += (Left - m_OrgLeft); + } + } + m_OrgTop = Top; + m_OrgLeft = Left; +} +//--------------------------------------------------------------------------- +int __fastcall TMmsstv::OpenDialogExecute(int sw) +{ + MultProc(); + m_PreViewFlag = sw; + int r = OpenDialog->Execute(); + MultProc(); + return r; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::OpenDialogSelectionChange(TObject *Sender) +{ + if( !m_PreViewFlag ) return; + + MultProc(); + char fname[256]; + StrCopy(fname, AnsiString(OpenDialog->FileName).c_str(), 255); //ja7ude 0521 + LPCSTR pExt = GetEXT(fname); + int f = 0; + if( IsPic(pExt) ){ + if( IsFile(fname) ){ + f = 1; + } + } + else if( !strcmpi(pExt, "MTM") || !strcmpi(pExt, "MTI") ){ + if( IsFile(fname) ){ + f = 2; + } + } + MultProc(); + if( f ){ + CWaitCursor w; + if( pPreView == NULL ){ + pPreView = new TPrevViewBox(NULL); + pPreView->SetViewPos(sys.m_PreViewLeft, sys.m_PreViewTop, sys.m_PreViewWidth, sys.m_PreViewHeight); + } + if( f == 2 ){ + CDrawGroup *pGroup = new CDrawGroup; + if( LoadTemplate(pGroup, fname, pPreView->pBitmap->Canvas) == TRUE ){ + pPreView->pBitmap->Width = pGroup->m_SX; + pPreView->pBitmap->Height = pGroup->m_SY; + FillBitmap(pPreView->pBitmap, pGroup->m_TransCol); + MultProc(); + pGroup->Draw(pPreView->pBitmap->Canvas); + } + pGroup->FreeItem(); + delete pGroup; + } + else { + ::LoadImage(pPreView->pBitmap, fname); + } + MultProc(); + pPreView->UpdateTitle(fname); + pPreView->Show(); + pPreView->Invalidate(); + MultProc(); + } + else { + OpenDialogClose(NULL); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::OpenDialogClose(TObject *Sender) +{ + if( pPreView != NULL ){ + pPreView->GetViewPos(sys.m_PreViewLeft, sys.m_PreViewTop, sys.m_PreViewWidth, sys.m_PreViewHeight); + delete pPreView; + pPreView = NULL; + } +} +//--------------------------------------------------------------------------- + +void __fastcall TMmsstv::KTPAClick(TObject *Sender) +{ + if(DrawMain.pSel->m_Command == CM_PIC){ + CDrawPic *pPic = (CDrawPic *)DrawMain.pSel; + if( !pPic->m_Type ){ + SBHistFilClick(NULL); + } + else { + TPicFilterDlg *pBox = new TPicFilterDlg(this); + if( pBox->Execute(pPic->pBitmap) == TRUE ){ + UpdatePic(); + DeleteUndo(); + } + delete pBox; + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::PopupMPopup(TObject *Sender) +{ + int *ip = ((m_MainPage == pgTX)||(m_MainPage == pgTemp)) ? m_ModeAssignTX : m_ModeAssignRX; + int n = 0; + int m = ip[m_ExtMode]; + int i; + int w, h; + char bf[128]; + TMenuItem *pm; + for( i = 0; i < smEND; i++ ){ + if( n < PopupM->Items->Count ){ + pm = PopupM->Items->Items[n]; + } + else { + pm = new TMenuItem (this); + } + int mm = SSTVModeOdr[i]; + int dm; + SSTVSET.GetPictureSize(w, dm, h, mm); + double tw = SSTVSET.GetTiming(mm); + if( ((mm >= smPD50) && (mm <= smPD290)) || ((mm >= smMP73) && (mm <= smMP175)) || ((mm >= smMN73) && (mm <= smMN140)) || ((mm >= smR24) && (mm <= smRM12))) tw *= 0.5; + tw = ((tw * h) / 1000.0) + 0.5; + if( ((mm >= smR24) && (mm <= smRM12)) ){ + w /= 2; + h /= 2; + } + sprintf(bf, "%s\t(%dx%d %us)", SSTVModeList[mm], w, h, int(tw)); +// pm->Break = mm == smMP73 ? mbBarBreak : mbNone; + pm->Caption = bf; + pm->RadioItem = TRUE; + pm->OnClick = KMClick; + pm->Checked = (m == mm) ? TRUE : FALSE; + pm->Enabled = ((m == mm) || (FindModeAssign(ip, mm) < 0)) ? TRUE : FALSE; + if( n >= PopupM->Items->Count ){ + PopupM->Items->Insert(n, pm); + } + n++; + } + MultProc(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KMClick(TObject *Sender) +{ + int i; + for( i = 0; i < PopupM->Items->Count; i++ ){ + if( PopupM->Items->Items[i] == Sender ){ + int mode = SSTVModeOdr[i]; + if( ((m_MainPage == pgTX)||(m_MainPage == pgTemp)) ){ + m_ModeAssignTX[m_ExtMode] = mode; + if( GetModeBtn(m_ExtMode)->Down ){ + ChangeTxMode(mode); + } + if( !pDem->m_Sync || (SSTVSET.m_Mode != m_ModeAssignRX[m_ExtMode]) ){ + m_ModeAssignRX[m_ExtMode] = mode; + } + } + else { + m_ModeAssignRX[m_ExtMode] = mode; + if( !SBTX->Down || (SSTVSET.m_TxMode != m_ModeAssignTX[m_ExtMode]) ){ + if( SSTVSET.m_TxMode == m_ModeAssignTX[m_ExtMode] ){ + m_ModeAssignTX[m_ExtMode] = mode; + ChangeTxMode(mode); + } + else { + m_ModeAssignTX[m_ExtMode] = mode; + } + } + } + break; + } + } + UpdateModeBtn(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SBMMouseUp(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( Button == mbRight ){ + TSpeedButton *tp = (TSpeedButton *)Sender; + m_ExtMode = GetButtonNo(tp); + if( tp->Down ){ + if( SBTX->Down ) return; + } + PopupM->Popup(Left + GBMode->Left + tp->Left + tp->Width/2, Top + GBMode->Top + tp->Top + tp->Height); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::ChangeTxMode(int mode) +{ + SSTVSET.GetPictureSize(m_TXW, m_TXH, m_TXPH, mode); + UpdateTXUI(); + int rep = (sys.m_Repeater && pDem->m_Repeater) ? 1 : 0; + if( (pBitmapTXM->Width != m_TXW) || (pBitmapTXM->Height != m_TXH) ){ + if( KSIS->Checked || rep ){ + ReSizeBitmap(pBitmapTXM, m_TXW, m_TXH); + } + else { + pBitmapTXM->Width = m_TXW; + pBitmapTXM->Height = m_TXH; + } + pBitmapTX->Width = m_TXW; + pBitmapTX->Height = m_TXH; + if( !KSIS->Checked || !DrawMain.m_Cnt ){ + if( !rep ){ + DrawMain.m_SX = m_TXW; + DrawMain.m_SY = m_TXH; + } + } + UpdatePic(); + if( sys.m_ShowSizeStock ){ + UpdateTabS(); + } + } + else if( sys.m_Repeater && pDem->m_Repeater ){ + UpdatePic(); + } + if( (SSTVSET.m_TxMode != mode) && KSAM->Checked && !rep ){ + m_TxClipType = (m_TXPH == 240) ? 2 : 0; + UpdateTxClip(); + UpdatePic(); + } + SSTVSET.m_TxMode = mode; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KSSDClick(TObject *Sender) +{ + if( PopupS->PopupComponent == PBoxTX ){ + sys.m_ShowSizeTX = sys.m_ShowSizeTX ? FALSE : TRUE; + PBoxTX->Invalidate(); + } + else { + sys.m_ShowSizeStock = sys.m_ShowSizeStock ? FALSE : TRUE; + UpdateTabS(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KTSZClick(TObject *Sender) +{ + int w, h; + + if( Sender == KTSZ1 ){ + w = 320; h = 256; + } + else if( Sender == KTSZ2 ){ + w = 512; h = 400; + } + else if( Sender == KTSZ3 ){ + w = 640; h = 496; + } + else if( Sender == KTSZ4 ){ + w = 800; h = 616; + } + else { + w = m_TXW; h = m_TXH; + } + SaveUndo(); + DrawMain.m_SX = w; + DrawMain.m_SY = h; + UpdatePic(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KTSDClick(TObject *Sender) +{ + sys.m_ShowSizeTemp = sys.m_ShowSizeTemp ? FALSE : TRUE; + UpdateTemp(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KHSDClick(TObject *Sender) +{ + sys.m_ShowSizeHist = sys.m_ShowSizeHist ? FALSE : TRUE; + PBoxHist->Invalidate(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KRSDClick(TObject *Sender) +{ + sys.m_ShowSizeRX = sys.m_ShowSizeRX ? FALSE : TRUE; + PBoxRX->Invalidate(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::UpdateSBTO(void) +{ + SBTO->Enabled = (!SBTX->Down && (pDem->m_LoopBack == 2) && (SSTVSET.m_SampFreq != sys.m_SampFreq)) ? TRUE : FALSE; + CSSTVDEM *dp = pDem; + BOOL f = ( ((dp->m_StgBuf != NULL) || WaveStg.IsOpen()) && (dp->m_wStgLine >= 16) && (SSTVSET.m_Mode != smAVT) ) ? TRUE : FALSE; + SBAdj->Enabled = f; + SBPL->Enabled = f; + SBPR->Enabled = f; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SBTOClick(TObject *Sender) +{ + double r = (sys.m_SampFreq * SSTVSET.m_TxSampFreq)/ SSTVSET.m_SampFreq; + r -= sys.m_SampFreq; + r = NormalSampFreq(r, 100); + sys.m_TxSampOff = r; + pMod->m_vco.SetSampleFreq(sys.m_SampFreq + sys.m_TxSampOff); + SBTO->Enabled = FALSE; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KRCSClick(TObject *Sender) +{ + CorrectSlant(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KRCRClick(TObject *Sender) +{ + RedrawAdjustSync(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KRSRClick(TObject *Sender) +{ + if( sys.m_SampFreq != SSTVSET.m_SampFreq ){ + CWaitCursor w; + + SSTVSET.m_SampFreq = sys.m_SampFreq; + RedrawSampFreq(FALSE); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SBRXIDClick(TObject *Sender) +{ + pDem->m_fskdecode = SBRXID->Down; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KSOFFClick(TObject *Sender) +{ + int type = sys.m_FFTType; + pSound->fftIN.TrigFFT(); + if( Sender == KSOFF ){ + sys.m_FFTType = 0; + } + else if( Sender == KSFFT ){ + sys.m_FFTType = 1; + } + else { + sys.m_FFTType = 2; + } + if( !sys.m_FFTType ){ + DrawFFT(1); + PBoxFFT->Invalidate(); + if( KVW->Checked ){ + DrawWater(1); + PBoxWater->Invalidate(); + } + } + else if( type != sys.m_FFTType ){ + switch(sys.m_FFTType){ + case 1: + if( sys.m_FFTGain >= 4 ) sys.m_FFTGain = 1; + break; + case 2: + if( sys.m_FFTGain < 4 ) sys.m_FFTGain = 5; + break; + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SBRXIDMouseUp(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( Button == mbRight ){ + if( PopupC->Items->Count ){ + TControl *tp = (TControl *)Sender; + PopupC->Popup(Left + GBLog->Left + tp->Left + SBRXID->Width/2, m_MW + Top + GBLog->Top + tp->Top); + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KCClick(TObject *Sender) +{ + TMenuItem *pm = (TMenuItem *)Sender; + if( strcmp(AnsiString(HisCall->Text).c_str(), (AnsiString(pm->Caption).c_str()+6)) ){ + HisCall->Text = pm->Caption.c_str() + 6; + FindCall(); + m_ChangeTemp = 2; + SBULog->Enabled = TRUE; + UpdateUI(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::AddCall(LPCSTR p) +{ + SYSTEMTIME now; + GetLocal(&now); + char bf[128]; + sprintf(bf, "%02u:%02u\t%s", now.wHour, now.wMinute, p); + + int i; + TMenuItem *pm; + for( i = 0; i < PopupC->Items->Count; i++ ){ + pm = PopupC->Items->Items[i]; + if( !strcmp(AnsiString(pm->Caption).c_str() + 6, p) ){ + if( !i ){ + pm->Caption = bf; + return; + } + else { + PopupC->Items->Delete(i); + break; + } + } + } + pm = new TMenuItem (this); + pm->Caption = bf; + pm->RadioItem = FALSE; + pm->OnClick = KCClick; + pm->Checked = FALSE; + pm->Enabled = TRUE; + if( (i >= PopupC->Items->Count) && (PopupC->Items->Count == FSKIDMAX) ){ + PopupC->Items->Delete(FSKIDMAX-1); + } + PopupC->Items->Insert(0, pm); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::DeleteHistF(void) +{ + if( (pBitmapHistF != NULL) && (pBitmapHistF != pBitmapHist) ){ + delete pBitmapHistF; + } + pBitmapHistF = pBitmapHist; + DrawMain.UpdatePic(pBitmapHistF); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::AdjustHistF(void) +{ + m_ReqHistF = 0; + if( KSF->Checked ){ + if( pBitmapHistF == pBitmapHist ) pBitmapHistF = NULL; + pBitmapHistF = MFilter(pBitmapHistF, pBitmapHist, 1); + DrawMain.UpdatePic(pBitmapHistF); + } + else { + DeleteHistF(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::TrigHistF(void) +{ + if( KSF->Checked ){ + DeleteHistF(); + m_ReqHistF = 10; + } + else { + DrawMain.UpdatePic(pBitmapHistF); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KSFClick(TObject *Sender) +{ + InvMenu(KSF); + AdjustHistF(); + UpdatePic(1); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KTF1Click(TObject *Sender) +{ + CWaitCursor w; + + SaveUndo(); + char fname[256]; + int n; + if( Sender == KTF1 ){ + n = 1; + } + else if( Sender == KTF2 ){ + n = 2; + } + else if( Sender == KTF3 ){ + n = 3; + } + else if( Sender == KTF4 ){ + n = 4; + } + else { + n = 5; + } + sprintf(fname, "%sdef%d.mtm", BgnDir, n); + LoadTemplate(&DrawMain, fname, NULL); + UpdateTemp(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KTKAClick(TObject *Sender) +{ + if( DrawMain.pSel != NULL ){ + SaveUndo(); + DrawMain.pSel->KeepAspect(); + UpdateTemp(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KTOSClick(TObject *Sender) +{ + if( DrawMain.pSel != NULL ){ + SaveUndo(); + DrawMain.pSel->SetOrgSize(); + UpdateTemp(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::UDStockMouseDown(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( Button == mbRight ){ + int n = UDStock->Position; + int w = UDStock->Width/2; + int m = n % 5; + if( X >= w ){ + n += (5 - m); + } + else if( m ){ + n -= m; + } + else { + n -= 5; + } + int max = UDStock->Max + 1; + if( n < 0 ) n += max; + if( n >= max ) n -= max; + n = n - (n % 5); + UDStock->Position = SHORT(n); + UDStockClick(NULL, btNext); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KRI1Click(TObject *Sender) +{ + if( Sender == KRI1 ){ + m_SyncAccuracy = 0; + } + else if( Sender == KRI2 ){ + m_SyncAccuracy = 1; + } + else { + m_SyncAccuracy = 2; + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KRCDClick(TObject *Sender) +{ + InvMenu(KRCD); + if( pRxView != NULL ){ + KVRClick(NULL); + if( !KRCD->Checked ) Application->Restore(); + KVRClick(NULL); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KORepClick(TObject *Sender) +{ + TRepSetDlg *pBox = new TRepSetDlg(this); + int r = pBox->Execute(); + if( r != mrCancel ){ + InitDrawFFT(); + PBoxG->Invalidate(); + UpdateTitle(); + if( (r == 1024) && pDem->m_Repeater ){ + SendBeacon(); + } + } + delete pBox; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KEWClick(TObject *Sender) +{ + if( Sender == KEW1 ){ + sys.m_Way240 = 0; + } + else if( Sender == KEW2 ){ + sys.m_Way240 = 1; + } + else if( Sender == KEW3 ){ + sys.m_Way240 = 2; + } + else { + sys.m_Way240 = 3; + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::AdjustPage(int sw) +{ + switch(sw){ + case pgRX: + if( m_MainPage != pgRX ){ + m_MainPage = pgRX; + Page->ActivePage = TabRX; + PageChange(NULL); + } + break; + case pgHist: + if( m_MainPage != pgHist ){ + m_MainPage = pgHist; + Page->ActivePage = TabHist; + PageChange(NULL); + } + break; + case pgTX: + if( m_MainPage != pgTX ){ + m_MainPage = pgTX; + Page->ActivePage = TabTX; + PageChange(NULL); + } + break; + case pgTemp: + if( m_MainPage != pgTemp ){ + m_MainPage = pgTemp; + Page->ActivePage = TabTemp; + PageChange(NULL); + } + break; + default: + if( (m_MainPage != pgTX) && (m_MainPage != pgTemp) ){ + m_MainPage = pgTX; + Page->ActivePage = TabTX; + PageChange(NULL); + } + break; + } +} +// +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::Repeater(void) +{ + CSSTVDEM *dp = pDem; + switch(dp->m_repmode){ + case 3: + SetBeaconDelay(); + dp->m_repANS++; + SendCWID(sys.m_RepAnsCW.c_str()); + if( dp->m_SyncMode < 0 /* !SBAuto->Down*/ ){ + dp->Stop(); + dp->m_SyncMode = 0; + UpdateModeBtn(); + UpdateUI(); + } + dp->m_repmode++; + break; + case 9: + SetBeaconTick(); + if( !sys.m_RepFolder.IsEmpty() ){ + SYSTEMTIME tim; + ::GetUTC(&tim); + if( Log.m_LogSet.m_TimeZone == 'I' ){ + UTCtoJST(&tim); + } + char fname[256]; + char abf[2]; + abf[0] = abf[1] = 0; + if( LastC(sys.m_RepFolder.c_str()) != '\\' ) abf[0] = '\\'; + sprintf(fname, "%s%s%04u%02u%02u%02u%02u.jpg", sys.m_RepFolder.c_str(), abf, + tim.wYear, + tim.wMonth, + tim.wDay, + tim.wHour, + tim.wMinute + ); + SaveJPEG(pBitmapTX, fname); + } + AdjustPage(pgTX); + ToTX(); + dp->m_repTX++; + dp->m_repmode++; + m_RepTXPos++; + break; + } + if( sys.m_RepBeacon ){ + DWORD NTick = ::GetTickCount(); + DWORD CTick = m_RepTick + (sys.m_RepBeacon * 1000); + if( dp->m_RepSQ && (dp->m_repsig > dp->m_RepSQ) ){ // 信号検出中 + if( CTick < (NTick + sys.m_RepQuietnessTime*1000) ){ // 300s前の時は延長 + m_RepTick = NTick - ((sys.m_RepBeacon - sys.m_RepQuietnessTime) * 1000); + } + } + else if( (CTick < NTick) && !dp->m_repmode ){ + m_RepTick = NTick; + SendBeacon(); + } + } +} +//--------------------------------------------------------------------------- +int __fastcall TMmsstv::LoadRepTemplate(LPCSTR pList, int &Pos) +{ + char bf[256]; + StrCopy(bf, pList, sizeof(bf)-1); + LPSTR t, p; + int max, n; + for( max = 0, p = bf; *p; max++ ){ + p = StrDlm(t, p); + if( !*SkipSpace(t) ) break; + } + if( Pos >= max ) Pos = 0; + StrCopy(bf, pList, sizeof(bf)-1); + for( n = 0, p = bf; n < Pos; n++ ){ + p = StrDlm(t, p); + } + StrDlm(t, p); + t = SkipSpace(t); + clipsp(t); + int gf = 0; + if( *t ){ + if( *t == '#' ){ + t++; + gf = 1; + } + n = atoin(t, -1); + if( (n >= 1) && (n <= STOCKMAX) ){ + if( gf ) gf = n; + + LoadStockTemp(&DrawMain, n-1, NULL); + if( !DrawMain.m_Cnt ){ + DrawMain.m_SX = m_TXW; + DrawMain.m_SY = m_TXH; + } + if( !SBUseTemp->Down ){ + SBUseTemp->Down = TRUE; + SBUseTempClick(NULL); + } + } + else { + gf = 0; + } + } + return gf; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SendBeacon(void) +{ + if( pDem->m_repmode >= 2 ) return; + if( SBTX->Down ) ToRX(); + ChangeTxMode(sys.m_RepBeaconMode); + UpdateModeBtn(); + int gf = LoadRepTemplate(sys.m_RepTempBeacon.c_str(), m_RepBeaconPos); + if( gf ){ // 画像のロード + Graphics::TBitmap *pBitmap = new Graphics::TBitmap(); + LoadBitmapSN(pBitmap, gf); + pBitmapTXM = RemakeBitmap(pBitmapTXM, -1); + StretchCopyBitmapHW(pBitmapTXM, pBitmap); + UpdatePic(); + delete pBitmap; + } + else { + MakeBeacon(0, sys.m_RepBeaconFilter, 0); + } + AdjustPage(pgTX); + SetBeaconTick(); + if( pDem->m_repmode >= 2 ) return; + m_RepBeaconCount++; + ToTX(); + m_RepBeaconPos++; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SetBeaconTick(void) +{ + m_RepTick = ::GetTickCount(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SetBeaconDelay(void) +{ + DWORD NTick = ::GetTickCount(); + DWORD CTick = m_RepTick + (sys.m_RepBeacon * 1000); + int qtime = sys.m_RepQuietnessTime; + if( qtime < 300 ) qtime = 300; + if( CTick < (NTick + qtime*1000) ){ // 300s前の時は延長 + m_RepTick = NTick - ((sys.m_RepBeacon - qtime) * 1000); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::GetBeaconBitmap(Graphics::TBitmap *pBitmap, int n) +{ + n = (RxHist.m_Head.m_wPnt - 1) - n; + if( n < 0 ) n += RxHist.m_Head.m_Max; + if( n >= RxHist.m_Head.m_Max ) n -= RxHist.m_Head.m_Max; + RxHist.Read(pBitmap, n); +} +//--------------------------------------------------------------------------- +// 0 : 4 pix -> TX +// 1 : 3 pix -> TX +void __fastcall TMmsstv::MakeBeacon(int sw, int fsw, int nn) +{ + if( nn < RxHist.m_Head.m_Cnt ){ + Graphics::TBitmap *pBTX = NULL; + if( sw ) pBTX = DupeBitmap(pBitmapTXM, -1); + pBitmapTXM = RemakeBitmap(pBitmapTXM, -1); + FillBitmap(pBitmapTXM, sys.m_PicClipColor); + Graphics::TBitmap *pBitmap = new Graphics::TBitmap(); + Graphics::TBitmap *pBitmapQ = new Graphics::TBitmap(); + + int Y1 = 0; +// int Y2 = pBitmapTXM->Height; + int Y2 = m_TXPH; + if( SBUseTemp->Down && DrawMain.m_Cnt ){ + DrawMain.GetColorBarPos(Y1, Y2); + } + int XW = pBitmapTXM->Width / 2; + int YW = (Y2-Y1) / 2; + pBitmapQ->Width = XW; + pBitmapQ->Height = YW; + int x, y, i; + for( i = 3; i >= 0; i-- ){ + x = (i & 1) ? XW : 0; + y = Y1 + ((i / 2) ? YW : 0); + if( !sw || (i < 3) ){ + if( (i + nn) < RxHist.m_Head.m_Cnt ){ + GetBeaconBitmap(pBitmap, i + nn); + } + else { + GetBeaconBitmap(pBitmap, RxHist.m_Head.m_Cnt - 1); + } + if( fsw && (XW <= (pBitmap->Width / 2)) ){ + Graphics::TBitmap *pBitmapF = MFilter(NULL, pBitmap, 1); + delete pBitmap; + pBitmap = pBitmapF; + } + } + else { + ::CopyBitmap(pBitmap, pBTX); + } + MultProc(); + StretchCopyBitmap(pBitmapQ, pBitmap); + pBitmapTXM->Canvas->Draw(x, y, pBitmapQ); + MultProc(); + } + delete pBitmapQ; + delete pBitmap; + UpdatePic(); + if( pBTX != NULL ) delete pBTX; + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::MakeReplay(void) +{ + CSSTVDEM *dp = pDem; + if( dp->m_repmode == 6 ){ + if( !CBASave->Checked ) SBWHistClick(NULL); + TrackTxMode(1); + StretchCopyBitmap(pBitmapTXM, pBitmapRX); + int gf = LoadRepTemplate(sys.m_RepTempTX.c_str(), m_RepTXPos); + if( gf ){ // 画像のロード + Graphics::TBitmap *pBitmap = new Graphics::TBitmap(); + LoadBitmapSN(pBitmap, gf); + pBitmapTXM = RemakeBitmap(pBitmapTXM, -1); + StretchCopyBitmapHW(pBitmapTXM, pBitmap); + delete pBitmap; + } + UpdatePic(); + dp->m_repmode++; + } + else { + dp->m_repmode = 0; + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SendCWID(LPCSTR p) +{ + if( !p || !*p ) return; + CWaitCursor w; + + sys.m_CWIDSpeed = (1110.0 / sys.m_CWIDWPM) - 30.0 + 0.5; + if( pRadio != NULL ) pRadio->SetPTT(1); + if( pComm != NULL ) pComm->SetPTT(1); + LogLink.SetPTT(1); + CSSTVMOD *mp = pMod; + SBTX->Down = TRUE; + SBTX->Update(); + if( pCtrBtn != NULL ) pCtrBtn->UpdateBtn(); + + char bf[256]; + MacroText(bf, p, sizeof(bf)-1); + +#if MEASCWSPEED +DWORD dwBgn = ::GetTickCount(); +#endif + + mp->OpenTXBuf(10); + mp->InitTXBuf(); + for( p = bf; *p; p++ ){ + if( mp->GetBufCnt() >= (9*SampFreq) ){ + break; + } + else { + mp->WriteCWID(*p); + } + } + pSound->m_ReqTx = 1; + for( int i = 0; i < 200; i++ ){ + if( pSound->m_Tx ) break; + ::Sleep(10); + } + while(*p){ // 残留テキストの送出 + if( mp->GetBufCnt() < (3*SampFreq) ){ + mp->WriteCWID(*p); + p++; + } + DrawLvl(); PBoxLvl->Update(); + ::Sleep(200); + if( !pSound->Wave.IsOutOpen() ) break; + } + while( mp->GetBufCnt() ){ + DrawLvl(); PBoxLvl->Update(); + ::Sleep(200); + if( !pSound->Wave.IsOutOpen() ) break; + } + pSound->TrigBCC(); + while( pSound->GetBCC() >= 0 ){ + DrawLvl(); PBoxLvl->Update(); + if( !pSound->Wave.IsOutOpen() ) break; + ::Sleep(200); + } +#if MEASCWSPEED +char bbf[128]; +dwBgn = ::GetTickCount() - dwBgn; +p = bf; +int l; +for(l = 0; *p; p++ ){ + if( *p != ' ' ) l++; +} +double cp = double(l)*60.0*1000.0/double(dwBgn); +double wp = 10.0*60.0*1000.0/double(dwBgn); +sprintf(bbf, "%d, %.3lfcpm, %.3lfwpm, %.3lf", sys.m_CWIDSpeed, cp, wp, wp * (sys.m_CWIDSpeed+30.0)); +Caption = bbf; +#endif + pSound->m_ReqTx = 0; + int tout = (pSound->m_BuffSize * pSound->m_FifoSizeTX * 10) / SSTVSET.m_TxSampFreq; + tout += 10; + for( int i = 0; i < tout; i++ ){ + if( !pSound->m_Tx ) break; + DrawLvl(); PBoxLvl->Update(); + ::Sleep(100); + } + if( pRadio != NULL ) pRadio->SetPTT(0); + if( pComm != NULL ) pComm->SetPTT(0); + LogLink.SetPTT(0); + pMod->CloseTXBuf(); + SBTX->Down = 0; + if( pCtrBtn != NULL ) pCtrBtn->UpdateBtn(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::HisCallDblClick(TObject *Sender) +{ + TShiftState Shift; + SBRXIDMouseUp(Sender, mbRight, Shift, 0, 0); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::HisQTHDblClick(TObject *Sender) +{ + char Key = VK_RETURN; + HisNameKeyPress(HisQTH, Key); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::MoveParent(TWinControl *pNew, TWinControl *pOld, TWinControl *pCtr) +{ + pOld->RemoveControl(pCtr); + pNew->InsertControl(pCtr); + pCtr->Parent = pNew; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::DivStockView(void) +{ + if( pStockView == NULL ){ + pStockView = new TStockView(this); + pStockView->SetViewPos(sys.m_StockViewLeft, sys.m_StockViewTop, sys.m_StockViewWidth, sys.m_StockViewHeight); + pStockView->Caption = KVSE1->Caption; + MultProc(); + MoveParent(pStockView, this, TabS); + TabS->Align = alClient; + MultProc(); + MoveParent(pStockView, this, PCS); + MultProc(); + PCS->Top = 0; + CBSTemp->Visible = FALSE; + CBSDraft->Visible = FALSE; + PCS->Width = 100; + UDStock->Left = PCS->Width - UDStock->Width; + LS->Left = UDStock->Left - 4 - LS->Width; + pStockView->Visible = KVSE1->Checked; + } + else { + pStockView->GetViewPos(sys.m_StockViewLeft, sys.m_StockViewTop, sys.m_StockViewWidth, sys.m_StockViewHeight); + MoveParent(this, pStockView, TabS); + TabS->Align = alBottom; + MoveParent(this, pStockView, PCS); + MultProc(); + CBSTemp->Visible = TRUE; + CBSDraft->Visible = TRUE; + + MultProc(); + delete pStockView; + pStockView = NULL; + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::DivWaterView(void) +{ + if( pWaterView == NULL ){ + pWaterView = new TStockView(this); + pWaterView->SetViewPos(sys.m_WaterViewLeft, sys.m_WaterViewTop, sys.m_WaterViewWidth, sys.m_WaterViewHeight); + pWaterView->Caption = KVSE2->Caption; + MultProc(); + PBoxG->Parent = pWaterView; + MoveParent(pWaterView, this, PanelLvl); + MoveParent(pWaterView, this, PanelFFT); + MoveParent(pWaterView, this, PanelWater); + + pLogView = new TStockView(this); + pLogView->SetViewPos(sys.m_LogViewLeft, sys.m_LogViewTop, sys.m_LogViewWidth, sys.m_LogViewHeight); + pLogView->Caption = KVSE3->Caption; + MultProc(); + MoveParent(pLogView, this, GBLog); + GBLog->Align = alClient; + + AlignFix.Resume(GBLog); + pLogView->AlignList.EntryControl(GBLog, 367, 164, GBLog->Font); + AlignFix.Resume(GBMode); + AlignFix.Resume(GB1); + pWaterView->Visible = KVSE2->Checked; + pLogView->Visible = KVSE3->Checked; + } + else { + pWaterView->GetViewPos(sys.m_WaterViewLeft, sys.m_WaterViewTop, sys.m_WaterViewWidth, sys.m_WaterViewHeight); + pLogView->GetViewPos(sys.m_LogViewLeft, sys.m_LogViewTop, sys.m_LogViewWidth, sys.m_LogViewHeight); + + PBoxG->Parent = this; + MoveParent(this, pWaterView, PanelLvl); + MoveParent(this, pWaterView, PanelFFT); + MoveParent(this, pWaterView, PanelWater); + + MoveParent(this, pLogView, GBLog); + GBLog->Align = alNone; + + delete pWaterView; + pWaterView = NULL; + delete pLogView; + pLogView = NULL; + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::DivControl(int sw) +{ + switch(sw){ + case 1: // ストック画面のみ分離 + if( pWaterView != NULL ) DivWaterView(); + if( pStockView == NULL ) DivStockView(); + break; + case 2: // すべて分離 + if( pStockView == NULL ) DivStockView(); + if( pWaterView == NULL ) DivWaterView(); + break; + default: // すべて合体 + if( pWaterView != NULL ) DivWaterView(); + if( pStockView != NULL ) DivStockView(); + break; + } + sys.m_DivMode = sw; + FormResize(NULL); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KVSD1Click(TObject *Sender) +{ + if( Sender == KVSD2 ){ + sys.m_DivMode = 1; + } + else if( Sender == KVSD3 ){ + sys.m_DivMode = 2; + } + else { + sys.m_DivMode = 0; + } + DivControl(sys.m_DivMode); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::OpenHistView(void) +{ + MultProc(); + pHistView = new THistViewDlg(this); + MultProc(); + pHistView->m_TitleBar = sys.m_HistViewTB; + pHistView->UpdateTitle(NULL); + pHistView->SetViewPos(sys.m_HistViewLeft, sys.m_HistViewTop, sys.m_HistViewWidth, sys.m_HistViewHeight); + if( !pHistView->m_TitleBar ) pHistView->UpdateTitlebar(); + pHistView->LoadHist(0); + MultProc(); + pHistView->SetPopup(PopupH); + MultProc(); + pHistView->Visible = TRUE; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::CloseHistView(void) +{ + if( pHistView != NULL ){ + pHistView->GetViewPos(sys.m_HistViewLeft, sys.m_HistViewTop, sys.m_HistViewWidth, sys.m_HistViewHeight); + delete pHistView; + pHistView = NULL; + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KHVSClick(TObject *Sender) +{ + if( Sender == KHVS1 ){ + sys.m_HistViewSize = 0; + } + else if( Sender == KHVS2 ){ + sys.m_HistViewSize = 1; + } + else if( Sender == KHVS3 ){ + sys.m_HistViewSize = 2; + } + else { + sys.m_HistViewSize = 3; + } + if( pHistView != NULL ){ + CloseHistView(); + OpenHistView(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KRFSClick(TObject *Sender) +{ + CSSTVDEM *dp = pDem; + if( dp->m_Sync && (SSTVSET.m_Mode != smAVT) && (m_SyncRPos >= 0) ){ + if( ABS(m_SyncPos - int(SSTVSET.m_OFP)) >= 5 ){ + int Skip = m_SyncRPos - int(SSTVSET.m_OFP); + if( Skip < 0 ) Skip += int(SSTVSET.m_TW); + dp->m_Skip = Skip; + m_SyncPos = m_SyncRPos = -1; + m_AutoSyncPos = 0x7fffffff; + m_AutoStopCnt = 0; + m_AutoStopACnt = 0; + m_AutoSyncDis = 6; + m_AutoSyncCount++; + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KSBClick(TObject *Sender) +{ + InitCustomColor(ColorDialog); + AddCustomColor(ColorDialog, sys.m_PicClipColor); + ColorDialog->Color = sys.m_PicClipColor; + SetDisPaint(); + if( ColorDialog->Execute() == TRUE ){ + sys.m_PicClipColor = ColorDialog->Color; + } + if( Sender == KSB ){ + MultProc(); + MakeTxBitmap(1); + PBoxTX->Invalidate(); + } + ResDisPaint(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::UpdatePriority(void) +{ + switch(sys.m_Priority){ + case 1: + ::SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS); + break; + case 2: + ::SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS); + break; + default: + ::SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS); + break; + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KHMT3Click(TObject *Sender) +{ + MakeBeacon(Sender == KHMT3 ? 1 : 0, 1, UDHist->Position); + AdjustPage(pgTX); +} + +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::MakeThImage(int mm) +{ + if( m_DragNo < 0 ) return; + + pBitmapTXM = RemakeBitmap(pBitmapTXM, -1); + FillBitmap(pBitmapTXM, sys.m_PicClipColor); + Graphics::TBitmap *pBitmap = new Graphics::TBitmap(); + Graphics::TBitmap *pBitmapQ = new Graphics::TBitmap(); + + int Y1 = 0; +// int Y2 = pBitmapTXM->Height; + int Y2 = m_TXPH; + int X2 = pBitmapTXM->Width; + if( SBUseTemp->Down && DrawMain.m_Cnt ){ + DrawMain.GetColorBarPos(Y1, Y2); + } + int XW = pBitmapTXM->Width / mm; + int YW = (Y2-Y1) / mm; + int x, y, i; + int n = m_DragDataNo; + int m = 0; + for( i = 0; i < STOCKMAX; i++, n++ ){ + MultProc(); + if( n >= STOCKMAX ) n = 0; + LoadBitmapSN(pBitmap, n+1); + if( pBitmap->Modified != FALSE ){ + x = (m % mm) * XW; + y = Y1 + ((m / mm) * YW); + if( ((m % mm) == (mm - 1)) && (x + XW) != X2 ){ + pBitmapQ->Width = X2 - x; + } + else { + pBitmapQ->Width = XW; + } + if( ((m / mm) == (mm - 1)) && (y + YW) != Y2 ){ + pBitmapQ->Height = Y2 - y; + } + else { + pBitmapQ->Height = YW; + } + MultProc(); + StretchCopyBitmapHW(pBitmapQ, pBitmap); + pBitmapTXM->Canvas->Draw(x, y, pBitmapQ); + MultProc(); + m++; + if( m >= (mm*mm) ) break; + } + } + delete pBitmapQ; + delete pBitmap; + UpdatePic(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KSMS4Click(TObject *Sender) +{ + int n; + if( Sender == KSMS4 ){ + n = 2; + } + else if( Sender == KSMS9 ){ + n = 3; + } + else { + n = 4; + } + MakeThImage(n); + AdjustPage(pgTX); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KHelpClick(TObject *Sender) +{ + MultProc(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::DropOle(int X, int Y, LPCSTR pName, int trans) +{ + CDrawOle *pDraw = (CDrawOle *)DrawMain.MakeItem(CM_OLE); + if( pDraw != NULL ){ + if( X >= 0 ) AdjustTempSC(X, Y); + pDraw->m_Trans = trans; + if( pDraw->LoadFromFile(X, Y, pName) ){ + AddItem(pDraw, 0); + } + else { + delete pDraw; + } + UpdateTemp(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::DropLib(int X, int Y, LPCSTR pName) +{ + AdjustPage(pgTemp); + MultProc(); + CDrawLib *pDraw = (CDrawLib *)DrawMain.MakeItem(CM_LIB); + if( pDraw != NULL ){ + AdjustTempSC(X, Y); + if( X < 0 ){ + X = (DrawMain.m_SX - 160) / 2; + Y = (DrawMain.m_SY - 128) / 2; + } + pDraw->m_X1 = X; pDraw->m_Y1 = Y; + pDraw->m_X2 = X + 160; pDraw->m_Y2 = Y + 128; + if( pDraw->MakeR(pName) ){ + AddItem(pDraw, 0); + } + else { + delete pDraw; + } + UpdateTemp(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::DropPic(int X, int Y, Graphics::TBitmap *pSrc, int type) +{ + AdjustPage(pgTemp); + MultProc(); + CDrawPic *pDraw = (CDrawPic *)DrawMain.MakeItem(CM_PIC); + MultProc(); + if( pDraw != NULL ){ + AdjustTempSC(X, Y); + int lx = DrawMain.m_SX; + int ly = DrawMain.m_SY; + int w = pSrc->Width; + int h = pSrc->Height; + if( (w > lx) || (h > ly) ){ + KeepAspect(lx, ly, w, h); + w = lx; h = ly; + } + if( X < 0 ){ + X = (DrawMain.m_SX - w) / 2; + Y = (DrawMain.m_SY - h) / 2; + } + w++; h++; + AdjustTempView(1); + pDraw->Start(PBoxTemp->Canvas, X, Y); + AdjustTempView(0); + X += w; + Y += h; + pDraw->Making(X, Y); + if( pDraw->FinishR(X, Y) ){ + pDraw->m_Type = type; + pDraw->m_Shape = 0; + pDraw->m_LineStyle = TPenStyle(-1); + ::StretchCopy(pDraw->pBitmap, pSrc, type == 2 ? COLORONCOLOR : HALFTONE); + AddItem(pDraw, 1); + } + else { + delete pDraw; + } + UpdateTemp(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KTPBClick(TObject *Sender) +{ + TClipboard *pCB = Clipboard(); + if(pCB->HasFormat(CF_BITMAP)){ + Graphics::TBitmap *pBitmap = new Graphics::TBitmap; + try + { + pBitmap->LoadFromClipboardFormat(CF_BITMAP, pCB->GetAsHandle(CF_BITMAP), 0); + DropPic(-1, 0, pBitmap, (Sender == KTPB) ? 1 : 2); + } + catch (...) + { + } + delete pBitmap; + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::LoadStockTemp(CDrawGroup *pItem, int n, TCanvas *tp) +{ + char tname[256]; + sprintf(tname, "%st%d.mtm", StockDir, n+1); + if( IsFile(tname) ){ + LoadTemplate(pItem, tname, tp); + } + else { + pItem->FreeItem(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SaveStockTemp(CDrawGroup *pItem, int n) +{ + char tname[256]; + sprintf(tname, "%st%d.mtm", StockDir, n+1); + SaveTemplate(pItem, tname); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::DeleteStockTemp(int n) +{ + char tname[256]; + sprintf(tname, "%st%d.mtm", StockDir, n+1); + unlink(tname); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::LoadCurrentTemp(void) +{ + char bf[256]; + sprintf(bf, "%s"TEMPV106C, StockDir); // Current.mtm + if( IsFile(bf) ){ // Ver1.06 + LoadTemplate(&DrawMain, bf, NULL); + sprintf(bf, "%s"TEMPV106L, StockDir); // StrList.mtl + LoadTemplate(&DrawText, bf, NULL); + return; + } + sprintf(bf, "%s"TEMPV105, StockDir); // CurTemp.bin + if( IsFile(bf) ){ // Ver1.05 + try { + char fname[256]; + TFileStream *tp = new TFileStream(bf, fmOpenRead); + if( DrawMain.LoadFromStream(PBoxTemp->Canvas, tp) == TRUE ){ + int i; + for( i = 0; i < STOCKMAX; i++ ){ + if( DrawTemp.LoadFromStream(PBoxTemp->Canvas, tp) == FALSE ) break; + if( DrawTemp.m_Cnt ){ + sprintf(fname, "%st%d.mtm", StockDir, i+1); + if( SaveTemplate(&DrawTemp, fname) == FALSE ) break; + } + } + if( i >= STOCKMAX ){ + DrawText.LoadFromStream(PBoxTemp->Canvas, tp); + } + } + delete tp; + sprintf(fname, "%s"TEMPV105B, StockDir); // CurTemp.105 + chmod(bf, S_IREAD|S_IWRITE); + rename(bf, fname); // CurTemp.bin -> CurTemp.bak + unlink(bf); + DrawTemp.FreeItem(); + } + catch(...){ + } + return; + } + else { // 初期起動 + LoadDefTemp(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SBRXFilClick(TObject *Sender) +{ + Graphics::TBitmap *pBitmap = DupeBitmap(pBitmapRX, pf24bit); + TPicFilterDlg *pBox = new TPicFilterDlg(this); + pBox->OKBtn->Enabled = FALSE; + pBox->Execute(pBitmap); + delete pBox; + delete pBitmap; +} +//--------------------------------------------------------------------------- + +void __fastcall TMmsstv::UDHistMouseDown(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( Button == mbRight ){ + if( !RxHist.m_Head.m_Cnt ) return; + int n = UDHist->Position; + int w = UDHist->Width/2; + if( X < w ){ + n += 5; + } + else { + n -= 5; + } + int max = RxHist.m_Head.m_Cnt - 1; + if( n < 0 ) n = 0; + if( n >= max ) n = max; + UDHist->Position = SHORT(n); + UDHistClick(NULL, btNext); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::IMenuClick(TObject *Sender) +{ + InvMenu((TMenuItem *)Sender); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KVSDClick(TObject *Sender) +{ + KVSE1->Enabled = (pStockView != NULL) ? TRUE : FALSE; + KVSE1->Checked = (pStockView == NULL) || pStockView->Visible ? TRUE : FALSE; + KVSE2->Enabled = (pWaterView != NULL) ? TRUE : FALSE; + KVSE2->Checked = (pWaterView == NULL) || pWaterView->Visible ? TRUE : FALSE; + KVSE3->Enabled = (pLogView != NULL) ? TRUE : FALSE; + KVSE3->Checked = (pLogView == NULL) || pLogView->Visible ? TRUE : FALSE; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KVSE1Click(TObject *Sender) +{ + IMenuClick(Sender); + FormResize(NULL); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::PBoxFFTMouseDown(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + int notch = pSound->m_notch; + if( Button == mbLeft ){ +// m_FX[4] = int(((fq-m_low)*FFT_SIZE*double(m_XW)/double(FFTSamp*m_FM)) + 0.5); + m_FX[5] = X; + double f = X * double(FFTSamp*m_FM) / (FFT_SIZE*double(m_XW)); + pSound->notch.SetNotchFreq(f + m_low); + pSound->m_notch = 1; + m_SpecDown = 1; + } + else { + pSound->m_notch = pSound->m_notch ? 0 : 1; + } + if( (notch != pSound->m_notch) && pDem->m_Sync ){ + int delay = pSound->notch.m_tap / 2; + if( notch ) delay = -delay; + pDem->m_Skip = delay; + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::PBoxFFTMouseMove(TObject *Sender, + TShiftState Shift, int X, int Y) +{ + if( m_SpecDown && pSound->m_notch ){ + m_FX[5] = X; + double f = X * double(FFTSamp*m_FM) / (FFT_SIZE*double(m_XW)); + pSound->notch.SetNotchFreq(f + m_low); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::PBoxFFTMouseUp(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + m_SpecDown = 0; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SBTXMouseDown(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( Button == mbRight ){ + KOMClick(NULL); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SBLMSMouseDown(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( Button == mbRight ){ + switch(pSound->m_lms_AN){ + case 1: + KLM2->Checked = TRUE; + break; + case 2: + KLM3->Checked = TRUE; + break; + default: + KLM1->Checked = TRUE; + break; + } + PopupL->Popup(Left + GB1->Left + SBLMS->Left + X + 4, m_MW + Top + GB1->Top + SBLMS->Top); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KLM1Click(TObject *Sender) +{ + int d = GetLMSDelay(); + int n = 0; + if( Sender == KLM2 ){ + n = 1; + } + else if( Sender == KLM3 ){ + n = 2; + } + pSound->lms.SetAN(n); + pSound->m_lms_AN = n; + if( pDem->m_Sync ) pDem->m_Skip = GetLMSDelay() - d; + UpdateLMS(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KSAClick(TObject *Sender) +{ + if( m_DragNo >= 0 ){ + AdjustPage(pgTemp); + LoadStockTemp(&DrawTemp, m_DragDataNo, NULL); + AddTemplate(&DrawTemp); + UpdateTemp(); + } +// +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KTFSClick(TObject *Sender) +{ + sys.m_DisFontSmooth = sys.m_DisFontSmooth ? FALSE : TRUE; + m_ChangeTemp = 1; + UpdateTemp(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::CMMML(TMessage Message) +{ + if( sys.m_LogLink != 2 ) return; + if( LogLink.m_pLink == NULL ) return; + + switch(Message.WParam){ + case MML_NOTIFYSESSION: + LogLink.NotifySession((LPCSTR)Message.LParam); + UpdateLogLink(); + break; + case MML_QRETURN: + if( !LogLink.IsLink() ) return; + if( LogLink.QReturn(&Log.m_sd, (const mmLOGDATA *)Message.LParam) ){ + UpdateTextData(); + } + break; + case MML_VFO: + if( !LogLink.IsLink() ) return; + if( Message.LParam ){ + LogFreq->Text = (LPCSTR)Message.LParam; + } + break; + } + Message.Result = TRUE; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::CMMMR(TMessage Message) +{ + if( pRadio == NULL ) return; + + switch(Message.WParam){ + case MMR_DEFCOMMAND: + { + LPCSTR p; + switch(Message.LParam){ + case 1: + p = RADIO.CmdRx.c_str(); + break; + case 2: + p = RADIO.CmdTx.c_str(); + break; + default: + p = RADIO.CmdInit.c_str(); + break; + } + pRadio->SendCommand(p); + } + break; + case MMR_VFO: + pRadio->UpdateFreq(double(Message.LParam)/10000.0); + break; + } + Message.Result = TRUE; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::OnDrawClipboard(TMessage Message) +{ + SBPaste->Enabled = !SBTX->Down && ::IsClipboardFormatAvailable(CF_BITMAP); + if( m_hClipNext ) ::SendMessage(m_hClipNext, WM_DRAWCLIPBOARD, Message.WParam, Message.LParam); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::OnChangeCbChain(TMessage Message) +{ + if( (HWND)Message.WParam == m_hClipNext ){ + m_hClipNext = (HWND)Message.LParam; + } + if( m_hClipNext ) ::SendMessage(m_hClipNext, WM_CHANGECBCHAIN, Message.WParam, Message.LParam); + Message.Result = 0; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KHJClick(TObject *Sender) +{ + ShowHelp(this, "JASTA.TXT", MsgEng); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KHNClick(TObject *Sender) +{ + ShowHelp(this, "NVCG.TXT", MsgEng); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SBCWMouseDown(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( Button == mbRight ){ +#if 1 + RECT rc; + ::GetWindowRect(TabTX->Handle, &rc); + PopupCW->Popup(rc.left + SBCW->Left + SBCW->Width/2, rc.top + SBCW->Top + SBCW->Height/2); +#else + AnsiString as = sys.m_CWText; + if( InputMB("MMSSTV", MsgEng ? "Enter text" : "テキストを入力", as, TRUE) == TRUE ){ + sys.m_CWText = as; + } +#endif + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KSAMClick(TObject *Sender) +{ + KSAM->Checked = !KSAM->Checked; + if( KSAM->Checked ) ChangeTxMode(SSTVSET.m_TxMode); +} +//--------------------------------------------------------------------------- + +void __fastcall TMmsstv::SBListMouseDown(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( Button == mbRight ) KOLClick(NULL); +} +//--------------------------------------------------------------------------- + +void __fastcall TMmsstv::PBoxLvlMouseDown(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( Button == mbLeft ){ + KVOutClick(NULL); + } + else { + KVOutClick(KVOut); + } +} +//--------------------------------------------------------------------------- + +void __fastcall TMmsstv::SBTXIDClick(TObject *Sender) +{ + sys.m_TXFSKID = SBTXID->Down; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::SBDFontMouseDown(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( Button == mbRight ){ + if( DrawMain.pSel != NULL ){ + if( DrawMain.pSel->m_Command == CM_TEXT ){ + SaveUndo(); + CDrawText *pText = (CDrawText *)(DrawMain.pSel); + FontDialog->Font->Assign(pText->pFont); + InvFontCharset(FontDialog->Font); + pText->UpdateFont(FontDialog->Font); + if( KTAP->Checked ) DrawMain.AdjustTransPoint(); + UpdateTemp(); + } + else if( DrawMain.pSel->m_Command == CM_LIB ){ + CDrawLib *pLib = (CDrawLib *)DrawMain.pSel; + LOGFONT lf; + TMemoryStream *sp = SaveUndo(NULL); + if( pLib->GetFont(&lf) ){ + lf.lfCharSet = InvFontCharset(lf.lfCharSet); + pLib->SetFont(&lf); + UpdateTemp(); + UpdateUndo(sp); + } + else { + delete sp; + } + } + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KTHClick(TObject *Sender) +{ + sys.m_Temp24 = !sys.m_Temp24; + m_ChangeTemp = 1; + UpdatePic(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KEEClick(TObject *Sender) +{ + g_ExecPB.Exec(pBitmapTXM, (HWND)Handle, CM_EDITEXIT, 0); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::OnEditExit(TMessage Message) +{ + if( Message.LParam & 0x40000000 ){ + if( g_ExecPB.IsChanged() ){ + int no = (Message.LParam & 0x00007fff); + if( no == UDHist->Position ){ + if( g_ExecPB.LoadBitmap(pBitmapHist, FALSE) ){ + PBoxHistPaint(NULL); + DrawMain.UpdatePic(pBitmapHistF); + UpdatePic(); + } + } + } + } + else if( Message.LParam & 0x80000000 ){ + if( g_ExecPB.IsChanged() ){ + int no = (Message.LParam & 0x00007fff) + 1; + Graphics::TBitmap *pBitmap = new Graphics::TBitmap; + LoadBitmapSN(pBitmap, no); + if( g_ExecPB.LoadBitmap(pBitmap, FALSE) ){ + SaveBitmapSN(pBitmap, no); + UpdateTabS(); + } + delete pBitmap; + } + } + else if( g_ExecPB.LoadBitmap(pBitmapTXM, FALSE) ){ + AdjustPage(pgTX); + MakeTxBitmap(0); + PBoxTXPaint(NULL); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KSEClick(TObject *Sender) +{ + if( PopupS->PopupComponent == PBoxTX ){ + KEEClick(NULL); + } + else { + if( m_DragNo < 0 ) return; + Graphics::TBitmap *pBitmap = LoadBitmapS(m_DragNo); + g_ExecPB.Exec(pBitmap, (HWND)Handle, CM_EDITEXIT, 0x80000000 + m_DragDataNo); + delete pBitmap; + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KXPClick(TObject *Sender) +{ + ExecPB(NULL); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KHEClick(TObject *Sender) +{ + g_ExecPB.Exec(pBitmapHist, (HWND)Handle, CM_EDITEXIT, 0x40000000 + UDHist->Position); +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::AdjustCWMenu(void) +{ + int max = PopupCW->Items->IndexOf(NCW); + TMenuItem *pm; + AnsiString as; + int i; + for( i = 0; i < sys.m_nCWMenu; i++ ){ + if( i >= max ){ + TMenuItem *pm = new TMenuItem (this); + PopupCW->Items->Insert(i, pm); + max++; + } + pm = PopupCW->Items->Items[i]; + char bf[256]; + MacroText(bf, sys.m_CWMenu[i].c_str(), sizeof(bf)-1); + as = bf; + if( pm->Caption != as ){ + pm->Caption = as; + } + pm->OnClick = KCWSendClick; + } + int N = i; + for( ; i < max; i++ ){ + PopupCW->Items->Delete(N); + } + + max = KCWM->IndexOf(NCWE); + for( i = 0; i < sys.m_nCWMenu; i++ ){ + if( i >= max ){ + TMenuItem *pm = new TMenuItem (this); + KCWM->Insert(i, pm); + max++; + } + pm = KCWM->Items[i]; + if( pm->Caption != sys.m_CWMenu[i] ){ + pm->Caption = sys.m_CWMenu[i]; + } + pm->OnClick = KCWEditClick; + } + N = i; + for( ; i < max; i++ ){ + KCWM->Delete(N); + } + BOOL f = sys.m_nCWMenu != 0; + NCW->Visible = f; + NCWE->Visible = f; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KCWClick(TObject *Sender) +{ + AnsiString as = sys.m_CWText; + if( InputMB(MsgEng ? "CW button" : "CWボタン", MsgEng ? "Enter text" : "テキストを入力", as, TRUE) == TRUE ){ + sys.m_CWText = as; + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::PopupCWPopup(TObject *Sender) +{ + AdjustCWMenu(); + KCWADD->Enabled = sys.m_nCWMenu < CWMENUMAX; + + char bf[256]; + MacroText(bf, sys.m_CWText.c_str(), sizeof(bf)-1); + AnsiString as = MsgEng ? "Set button text... (" : "ボタンの送信テキストの設定... ("; + as += bf; + as += ")"; + KCW->Caption = as; + + switch(sys.m_CWIDWPM){ + case 28: + KCWSH->Checked = TRUE; + break; + case 24: + KCWSM->Checked = TRUE; + break; + case 20: + KCWSL->Checked = TRUE; + break; + case 18: + KCWSLL->Checked = TRUE; + break; + default: + KCWSI->Checked = TRUE; + break; + } + if( KCWSI->Checked ){ + as = sys.m_CWIDWPM; + as += " WPM "; + } + else { + as = ""; + } + as += MsgEng ? "Enter PARIS speed..." : "PARIS速度で入力..."; + KCWSI->Caption = as; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KCWADDClick(TObject *Sender) +{ + if( sys.m_nCWMenu >= CWMENUMAX ) return; + + AnsiString as; + if( InputMB(MsgEng ? "Add CW menu" : "CWメニュー追加", MsgEng ? "Enter text" : "テキストを入力", as, TRUE) == TRUE ){ + if( !as.IsEmpty() ){ + sys.m_CWMenu[sys.m_nCWMenu++] = as; + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KCWSendClick(TObject *Sender) +{ + int n = PopupCW->Items->IndexOf((TMenuItem *)Sender); + if( (n >= 0) && (n < sys.m_nCWMenu) ){ + SendCWID(sys.m_CWMenu[n].c_str()); + Application->ProcessMessages(); + SBCW->Down = FALSE; + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KCWEditClick(TObject *Sender) +{ + int n = KCWM->IndexOf((TMenuItem *)Sender); + if( (n >= 0) && (n < sys.m_nCWMenu) ){ + AnsiString as = sys.m_CWMenu[n]; + if( InputMB(MsgEng ? "Edit CW menu" : "CWメニュー編集", MsgEng ? "Enter text (NULL for delete)" : "テキストを入力(NULLでメニューを削除)", as, TRUE) == TRUE ){ + if( as.IsEmpty() ){ + for( int i = n; i < (sys.m_nCWMenu - 1); i++ ){ + sys.m_CWMenu[i] = sys.m_CWMenu[i+1]; + } + sys.m_nCWMenu--; + } + else { + sys.m_CWMenu[n] = as; + } + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KCWSHClick(TObject *Sender) +{ + sys.m_CWIDWPM = 28; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KCWSMClick(TObject *Sender) +{ + sys.m_CWIDWPM = 24; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KCWSLClick(TObject *Sender) +{ + sys.m_CWIDWPM = 20; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KCWSLLClick(TObject *Sender) +{ + sys.m_CWIDWPM = 18; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KCWSIClick(TObject *Sender) +{ + AnsiString as = sys.m_CWIDWPM; + if( InputMB("MMSSTV", "CW Speed (PARIS 10 - 50 WPM)", as, FALSE) == TRUE ){ + int d; + if( sscanf(as.c_str(), "%d", &d) == 1 ){ + if( (d >= 10) && (d <= 50) ){ + sys.m_CWIDWPM = d; + } + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KRSetClick(TObject *Sender) +{ + TRADIOSetDlg *pBox = new TRADIOSetDlg(this); + + if( (sys.m_TxRxName != "NONE") && !strcmp(sys.m_TxRxName.c_str(), RADIO.StrPort) ){ + strcpy(RADIO.StrPort, "NONE"); + RADIO.change = 1; + } + if( pBox->Execute() == TRUE ){ + if( (sys.m_TxRxName != "NONE") && !strcmp(sys.m_TxRxName.c_str(), RADIO.StrPort) ){ + sys.m_TxRxName = "NONE"; + COMM.change = 1; + } + } + delete pBox; + if( COMM.change || RADIO.change ){ + OpenCloseCom(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::LoadRadioDef(LPCSTR pName) +{ + CWaitCursor w; + try { + TMemIniFile *pIniFile = new TMemIniFile(pName); + RADIO.CmdInit = pIniFile->ReadString("RADIO", "CmdInit", RADIO.CmdInit); + RADIO.CmdRx = pIniFile->ReadString("RADIO", "CmdRx", RADIO.CmdRx); + RADIO.CmdTx = pIniFile->ReadString("RADIO", "CmdTx", RADIO.CmdTx); + char bf[32]; + sprintf( bf, "%02X", RADIO.Cmdxx); + AnsiString as = pIniFile->ReadString("RADIO", "Cmdxx", bf); + int d; + sscanf(as.c_str(), "%X", &d); + RADIO.Cmdxx = d; + RADIO.PollType = pIniFile->ReadInteger("RADIO", "PollType", 0); + RADIO.PollInterval = pIniFile->ReadInteger("RADIO", "PollInterval", 0); + delete pIniFile; + OpenCloseCom(); + } + catch(...){ + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KRLoadClick(TObject *Sender) +{ + TOpenDialog *pBox = Mmsstv->OpenDialog; + pBox->Options >> ofCreatePrompt; + pBox->Options << ofFileMustExist; + if( MsgEng ){ + pBox->Title = "Open command file"; + pBox->Filter = "Command files(*.rcm)|*.rcm|"; + } + else { + pBox->Title = "コマンド定義ファイルを開く"; + pBox->Filter = "コマンド定義ファイル(*.rcm)|*.rcm|"; + } + pBox->FileName = ""; + pBox->DefaultExt = "rcm"; + pBox->InitialDir = BgnDir; + NormalWindow(this); + if( pBox->Execute() == TRUE ){ + LoadRadioDef(AnsiString(pBox->FileName).c_str()); + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::AdjustRadioMenu(void) +{ + int max = KRadio->IndexOf(NRadio); + TMenuItem *pm; + int i; + for( i = 0; i < m_nRadioMenu; i++ ){ + if( i >= max ){ + TMenuItem *pm = new TMenuItem (this); + KRadio->Insert(i, pm); + max++; + } + pm = KRadio->Items[i]; + if( pm->Caption != m_RadioMenu[i].strTTL ){ + pm->Caption = m_RadioMenu[i].strTTL; + } + pm->OnClick = KRadioCmdClick; + pm->Enabled = pRadio != NULL; + } + int N = i; + for( ; i < max; i++ ){ + KRadio->Delete(N); + } + + max = KRadioS->IndexOf(NRadioE); + for( i = 0; i < m_nRadioMenu; i++ ){ + if( i >= max ){ + TMenuItem *pm = new TMenuItem (this); + KRadioS->Insert(i, pm); + max++; + } + pm = KRadioS->Items[i]; + if( pm->Caption != m_RadioMenu[i].strTTL ){ + pm->Caption = m_RadioMenu[i].strTTL; + } + pm->OnClick = KRadioEditClick; + } + N = i; + for( ; i < max; i++ ){ + KRadioS->Delete(N); + } + BOOL f = m_nRadioMenu != 0; + NRadio->Visible = f; + NRadioE->Visible = f; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KRadioCmdClick(TObject *Sender) +{ + if( !pRadio ) return; + + int n = KRadio->IndexOf((TMenuItem *)Sender); + if( (n >= 0) && (n < RADIOMENUMAX) ){ + LPCSTR p = m_RadioMenu[n].strCMD.c_str(); + if( CheckEXT(p, "RCM") && IsFile(p) ){ + LoadRadioDef(p); + } + else { + pRadio->SendCommand(p); + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KRadioEditClick(TObject *Sender) +{ + int n = KRadioS->IndexOf((TMenuItem *)Sender); + if( (n >= 0) && (n < RADIOMENUMAX) ){ + AnsiString strTTL = m_RadioMenu[n].strTTL; + AnsiString strCMD = m_RadioMenu[n].strCMD; + + TRMenuDialog *pBox = new TRMenuDialog(this); + int r = pBox->Execute(strTTL, strCMD); + BOOL fNull = strTTL.IsEmpty() && strCMD.IsEmpty(); + if( (r == IDOK) && !fNull ){ + if( !strCMD.IsEmpty() ){ + if( strTTL.IsEmpty() ){ + char bf[64]; + sprintf(bf, "Radio command #d", n + 1); + strTTL = bf; + } + m_RadioMenu[n].strTTL = strTTL; + m_RadioMenu[n].strCMD = strCMD; + AdjustRadioMenu(); + } + } + else if( (r == 1024) || fNull ){ + for( int i = n; i < (m_nRadioMenu - 1); i++ ){ + m_RadioMenu[i].strTTL = m_RadioMenu[i+1].strTTL; + m_RadioMenu[i].strCMD = m_RadioMenu[i+1].strCMD; + } + m_nRadioMenu--; + AdjustRadioMenu(); + } + else if( r == 1025 ){ + if( m_nRadioMenu < RADIOMENUMAX ){ + for( int i = m_nRadioMenu; i > n; i-- ){ + m_RadioMenu[i].strTTL = m_RadioMenu[i-1].strTTL; + m_RadioMenu[i].strCMD = m_RadioMenu[i-1].strCMD; + } + m_RadioMenu[n].strTTL = strTTL; + m_RadioMenu[n].strCMD = strCMD; + m_nRadioMenu++; + AdjustRadioMenu(); + } + } + delete pBox; + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KRadioAddClick(TObject *Sender) +{ + if( m_nRadioMenu >= RADIOMENUMAX ) return; + + AnsiString strTTL, strCMD; + + TRMenuDialog *pBox = new TRMenuDialog(this); + if( pBox->Execute(strTTL, strCMD, TRUE) ){ + if( !strCMD.IsEmpty() ){ + if( strTTL.IsEmpty() ){ + char bf[64]; + sprintf(bf, "Radio command #d", m_nRadioMenu + 1); + strTTL = bf; + } + m_RadioMenu[m_nRadioMenu].strTTL = strTTL; + m_RadioMenu[m_nRadioMenu].strCMD = strCMD; + m_nRadioMenu++; + AdjustRadioMenu(); + } + } + delete pBox; +} +//--------------------------------------------------------------------------- +void __fastcall TMmsstv::KRadioClick(TObject *Sender) +{ + AdjustRadioMenu(); + KRadioAdd->Enabled = m_nRadioMenu < RADIOMENUMAX; +} +//--------------------------------------------------------------------------- + diff --git a/Main.dfm b/Main.dfm new file mode 100644 index 0000000..079a853 Binary files /dev/null and b/Main.dfm differ diff --git a/Main.h b/Main.h new file mode 100644 index 0000000..a888c8d --- /dev/null +++ b/Main.h @@ -0,0 +1,1435 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------------- +#ifndef MainH +#define MainH +//--------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include +//--------------------------------------------------------------------------- +#include "Sound.h" +#include "Comm.h" +#include "CRadio.h" +#include "Draw.h" +#include "InputWin.h" +#include "RxView.h" +#include "HistView.h" +#include "FileView.h" +#include "PrevView.h" +#include "CtrBtn.h" +#include "StockVew.h" +//#include +#define STOCKPAGE 4 +#define STOCKMAX 300 +#define DFFTSIZE 768 +//--------------------------------------------------------------------------- +class TMmsstv : public TForm +{ +__published: // IDE 管理のコンポーネント + TPageControl *Page; + TMainMenu *MainMenu; + TMenuItem *KFile; + TTabSheet *TabRX; + TTabSheet *TabHist; + TPanel *PanelRX; + TPaintBox *PBoxRX; + TPanel *PanelFFT; + TPanel *PanelWater; + TTimer *Timer; + TPaintBox *PBoxFFT; + TPaintBox *PBoxWater; + TMenuItem *KOpt; + TMenuItem *KHelp; + TMenuItem *KFRecTim; + TMenuItem *KFRec; + TMenuItem *KFPlay; + TOpenDialog *OpenDialog; + TSaveDialog *SaveDialog; + TMenuItem *N1; + TMenuItem *KExit; + TMenuItem *KFPlayPos; + TMenuItem *KFRecRew; + TMenuItem *KFRecStop; + TTabSheet *TabSync; + TPanel *PanelSync; + TPaintBox *PBoxD12; + TGroupBox *GBMode; + TSpeedButton *SBAuto; + TSpeedButton *SBM1; + TSpeedButton *SBM2; + TSpeedButton *SBM3; + TSpeedButton *SBM4; + TSpeedButton *SBM7; + TSpeedButton *SBLK; + TPanel *PanelLvl; + TPaintBox *PBoxLvl; + TPanel *PanelHist; + TPaintBox *PBoxHist; + TUpDown *UDHist; + TSpeedButton *SBLatest; + TLabel *HistStat; + TSpeedButton *SBPhase; + TSpeedButton *SBSlant; + TSpeedButton *SBSampSet; + TTabSheet *TabTX; + TTabSheet *TabTemp; + TPanel *PanelTX; + TPaintBox *PBoxTX; + TPanel *PanelTemp; + TPaintBox *PBoxTemp; + TSpeedButton *SBPaste; + TSpeedButton *SBCopy; + TSpeedButton *SBTX; + TMenuItem *KOSC; + TMenuItem *KView; + TMenuItem *KOM; + TGroupBox *GBLog; + TEdit *HisCall; + TLabel *L1; + TLabel *L2; + TEdit *HisName; + TLabel *L3; + TComboBox *HisRST; + TLabel *L4; + TComboBox *MyRST; + TLabel *L5; + TEdit *HisQTH; + TLabel *L6; + TEdit *EditNote; + TSpeedButton *SBQSO; + TSpeedButton *SBData; + TSpeedButton *SBFind; + TSpeedButton *SBList; + TComboBox *LogFreq; + TSpeedButton *SBInit; + TMenuItem *N2; + TMenuItem *KLogFlush; + TMenuItem *KLogOpen; + TMenuItem *KVer; + TSpeedButton *SBDSel; + TSpeedButton *SBDline; + TSpeedButton *SBDBox; + TSpeedButton *SBDDel; + TSpeedButton *SBDText; + TSpeedButton *SBDPic; + TSpeedButton *SBDPaste; + TSpeedButton *SBDFont; + TFontDialog *FontDialog; + TGroupBox *GB1; + TSpeedButton *SBAFC; + TTabControl *TabS; + TPanel *PanelS; + TPaintBox *PBoxS; + TSpeedButton *SBTune; + TPanel *PCS; + TUpDown *UDStock; + TLabel *LS; + TEdit *EditQSL; + TLabel *L7; + TColorDialog *ColorDialog; + TSpeedButton *SBDLineset; + TSpeedButton *SBDCol; + TPopupMenu *PopupS; + TMenuItem *KSL; + TMenuItem *KSC; + TMenuItem *KSP; + TMenuItem *N3; + TMenuItem *KSS; + TMenuItem *KSCan; + TMenuItem *N4; + TMenuItem *KSD; + TSpeedButton *SBDBoxS; + TCheckBox *CBSTemp; + TMenuItem *KOL; + TPopupMenu *PopupT; + TMenuItem *KTC; + TMenuItem *KTP; + TMenuItem *KTD; + TMenuItem *N5; + TMenuItem *KTB; + TMenuItem *KTF; + TMenuItem *N6; + TMenuItem *KTCan; + TSpeedButton *SBDHead; + TSpeedButton *SBM5; + TSpeedButton *SBM6; + TSpeedButton *SBM8; + TSpeedButton *SBM9; + TMenuItem *KTT; + TMenuItem *KTTC; + TSpeedButton *SBHView; + TSpeedButton *SBRView; + TSpeedButton *SBTView; + TSpeedButton *SBDS240; + TMenuItem *N8; + TMenuItem *KHlpMain; + TMenuItem *N9; + TMenuItem *KHlpPad; + TMenuItem *N10; + TMenuItem *KS; + TMenuItem *KF; + TMenuItem *KR; + TMenuItem *KFL1; + TMenuItem *KFM1; + TMenuItem *KFH1; + TMenuItem *KFT1; + TMenuItem *N11; + TMenuItem *KFL2; + TMenuItem *KFM2; + TMenuItem *KFH2; + TMenuItem *KFT2; + TMenuItem *KRS; + TMenuItem *KRM; + TMenuItem *KRF; + TSpeedButton *SBWHist; + TMenuItem *N12; + TSpeedButton *SBUseTemp; + TSpeedButton *SBDA240; + TSpeedButton *SBUS240; + TSpeedButton *SBUA240; + TMenuItem *N13; + TMenuItem *KTL; + TMenuItem *KTS; + TPaintBox *PBoxG; + TMenuItem *KFFTS; + TMenuItem *KFSOF; + TMenuItem *KFSS; + TMenuItem *KFSL; + TUpDown *UDSamp; + TLabel *SyncStat; + TPopupMenu *PopupH; + TMenuItem *KHCD; + TOpenDialog *DirDialog; + TMenuItem *N14; + TMenuItem *KSCD; + TMenuItem *KHD; + TMenuItem *N15; + TMenuItem *KHS; + TMenuItem *KEdit; + TMenuItem *KER; + TMenuItem *KEC; + TMenuItem *KEP; + TMenuItem *KES; + TMenuItem *N17; + TMenuItem *KEA; + TMenuItem *N16; + TMenuItem *KHCan; + TMenuItem *N18; + TMenuItem *KHT; + TMenuItem *KHFJ; + TMenuItem *KHFB; + TMenuItem *KSFJ; + TMenuItem *KSFB; + TPopupMenu *PopupR; + TMenuItem *KRAS; + TMenuItem *KRAR; + TMenuItem *N19; + TMenuItem *KRCan; + TMenuItem *N20; + TMenuItem *KRC; + TMenuItem *KRSW; + TMenuItem *KTA; + TMenuItem *N21; + TMenuItem *KVR; + TMenuItem *N22; + TMenuItem *KRR; + TMenuItem *N23; + TMenuItem *KTBT; + TCheckBox *CBASave; + TMenuItem *N24; + TMenuItem *KHACD; + TMenuItem *KHAC; + TCheckBox *CBSDraft; + TMenuItem *KRH; + TSpeedButton *SBULog; + TMenuItem *KHDA; + TMenuItem *N25; + TMenuItem *KHWeb; + TMenuItem *KHRef; + TMenuItem *KHACT; + TMenuItem *KVS; + TMenuItem *KFSQ; + TMenuItem *KP; + TMenuItem *KP1; + TMenuItem *KP2; + TMenuItem *KP3; + TMenuItem *KP4; + TMenuItem *KP5; + TMenuItem *KP6; + TMenuItem *KP7; + TMenuItem *KP8; + TMenuItem *N26; + TMenuItem *KPA; + TMenuItem *KPD; + TMenuItem *N27; + TMenuItem *KPDef; + TMenuItem *KPA1; + TMenuItem *KPA2; + TMenuItem *KPA3; + TMenuItem *KPA4; + TMenuItem *KPA5; + TMenuItem *KPA6; + TMenuItem *KPA7; + TMenuItem *KPA8; + TMenuItem *KPD1; + TMenuItem *KPD2; + TMenuItem *KPD3; + TMenuItem *KPD4; + TMenuItem *KPD5; + TMenuItem *KPD6; + TMenuItem *KPD7; + TMenuItem *KPD8; + TMenuItem *KHACJ; + TMenuItem *KVH; + TSpeedButton *SBDList; + TMenuItem *N28; + TMenuItem *KTE; + TMenuItem *KTTD; + TMenuItem *N29; + TMenuItem *KRSA; + TSpeedButton *SBTXFil; + TSpeedButton *SBHistFil; + TMenuItem *N30; + TMenuItem *KSTP; + TMenuItem *KVF; + TMenuItem *KRASY; + TMenuItem *N31; + TMenuItem *KFFTW; + TMenuItem *KFW30; + TMenuItem *KFW20; + TMenuItem *KFW15; + TMenuItem *N32; + TMenuItem *KTFX; + TMenuItem *N33; + TMenuItem *KRB; + TMenuItem *N34; + TMenuItem *KHDS; + TMenuItem *KHDS1; + TMenuItem *KHDS2; + TMenuItem *KHDS3; + TMenuItem *KHDS4; + TMenuItem *KHDS5; + TMenuItem *KHDS6; + TMenuItem *N35; + TMenuItem *KVW; + TMenuItem *N36; + TMenuItem *KFTA; + TMenuItem *N37; + TMenuItem *KFTD; + TMenuItem *KFTD1; + TMenuItem *KFTD2; + TMenuItem *KFTD3; + TMenuItem *KFTD4; + TMenuItem *KX; + TMenuItem *KX1; + TMenuItem *KX2; + TMenuItem *KX3; + TMenuItem *KX4; + TMenuItem *KX5; + TMenuItem *KX6; + TMenuItem *KX7; + TMenuItem *KX8; + TMenuItem *N38; + TMenuItem *KXA; + TMenuItem *KXD; + TMenuItem *N40; + TMenuItem *KXR; + TMenuItem *KXSM; + TMenuItem *KXA1; + TMenuItem *KXA2; + TMenuItem *KXA3; + TMenuItem *KXA4; + TMenuItem *KXA5; + TMenuItem *KXA6; + TMenuItem *KXA7; + TMenuItem *KXA8; + TMenuItem *KXD1; + TMenuItem *KXD2; + TMenuItem *KXD3; + TMenuItem *KXD4; + TMenuItem *KXD5; + TMenuItem *KXD6; + TMenuItem *KXD7; + TMenuItem *KXD8; + TMenuItem *KFTD5; + TMenuItem *KTAP; + TMenuItem *KTAC; + TMenuItem *N39; + TSpeedButton *SBLMS; + TMenuItem *KPInit; + TMenuItem *KVL; + TMenuItem *KVLSG; + TMenuItem *KVLSY; + TMenuItem *KTPA; + TMenuItem *KHTB; + TMenuItem *N42; + TMenuItem *KHAP; + TMenuItem *N43; + TMenuItem *KSAI; + TPopupMenu *PopupM; + TMenuItem *KRRC; + TMenuItem *KSSZ; + TMenuItem *KSS1; + TMenuItem *KSS2; + TMenuItem *KSS3; + TMenuItem *KSS4; + TMenuItem *KHlpUp; + TMenuItem *KSSD; + TMenuItem *N41; + TMenuItem *KTSZ; + TMenuItem *KTSZ1; + TMenuItem *KTSZ2; + TMenuItem *KTSZ3; + TMenuItem *KTSZ4; + TMenuItem *N45; + TMenuItem *KTSZT; + TMenuItem *KSIS; + TMenuItem *KTSD; + TMenuItem *KHSD; + TMenuItem *KRSD; + TSpeedButton *SBTO; + TMenuItem *KVOut; + TMenuItem *KVIn; + TMenuItem *N44; + TMenuItem *KRCS; + TMenuItem *KRSR; + TSpeedButton *SBAdj; + TMenuItem *KTU; + TSpeedButton *SBRXID; + TMenuItem *KSOFF; + TMenuItem *KSFFT; + TMenuItem *KSFQ; + TPopupMenu *PopupC; + TMenuItem *N46; + TMenuItem *KSF; + TMenuItem *KTDF; + TMenuItem *KTF1; + TMenuItem *KTF3; + TMenuItem *KTKA; + TMenuItem *KRI; + TMenuItem *KRI1; + TMenuItem *KRI2; + TMenuItem *KRI3; + TMenuItem *KVC; + TMenuItem *KRCD; + TMenuItem *KORep; + TMenuItem *KTMD; + TMenuItem *KEW; + TMenuItem *KEW2; + TMenuItem *KEW3; + TMenuItem *KEW4; + TMenuItem *KEW1; + TMenuItem *KVSD; + TMenuItem *KSTD; + TMenuItem *KSTS; + TMenuItem *KVSD1; + TMenuItem *KVSD2; + TMenuItem *KVSD3; + TMenuItem *N47; + TMenuItem *KHVS; + TMenuItem *KHVS1; + TMenuItem *KHVS2; + TMenuItem *KHVS3; + TMenuItem *KHVS4; + TMenuItem *N48; + TMenuItem *KRFS; + TMenuItem *KSB; + TMenuItem *KHC; + TMenuItem *N49; + TMenuItem *KSRR; + TMenuItem *KHMT; + TMenuItem *KHMT3; + TMenuItem *KHMT4; + TMenuItem *KSMS; + TMenuItem *KSMS4; + TMenuItem *KSMS9; + TMenuItem *KSMSX; + TMenuItem *KTF4; + TMenuItem *KTSA; + TMenuItem *KTSI; + TMenuItem *KTLA; + TMenuItem *KTLI; + TMenuItem *KTPI; + TMenuItem *KTPB; + TMenuItem *KTPO; + TMenuItem *KTF2; + TMenuItem *Report31; + TMenuItem *KRD; + TSpeedButton *SBRXFil; + TSpeedButton *SBFS; + TMenuItem *KTO; + TMenuItem *KTOI; + TMenuItem *KTOT; + TMenuItem *KTOP; + TMenuItem *KTOC; + TMenuItem *KTOE; + TMenuItem *KTOS; + TMenuItem *KTOB; + TMenuItem *N50; + TMenuItem *KTOCB; + TMenuItem *KTOR; + TMenuItem *KTX; + TMenuItem *N51; + TMenuItem *KVSE1; + TMenuItem *KVSE2; + TMenuItem *KVSE3; + TMenuItem *KTCI; + TPopupMenu *PopupL; + TMenuItem *KLM1; + TMenuItem *KLM2; + TMenuItem *KLM3; + TMenuItem *N52; + TMenuItem *KSA; + TMenuItem *KTFS; + TMenuItem *N7; + TMenuItem *KHN; + TMenuItem *KHJ; + TSpeedButton *SBCW; + TMenuItem *KSAM; + TMenuItem *KXS; + TMenuItem *KEX; + TSpeedButton *SBTXID; + TMenuItem *KTH; + TMenuItem *N53; + TMenuItem *KEE; + TMenuItem *KSE; + TMenuItem *N54; + TMenuItem *KXP; + TMenuItem *KHE; + TMenuItem *KRCC; + TSpeedButton *SBPL; + TSpeedButton *SBPR; + TMenuItem *KRCR; + TPopupMenu *PopupCW; + TMenuItem *KCW; + TMenuItem *KCWM; + TMenuItem *NCW; + TMenuItem *N55; + TMenuItem *KCWCancel; + TMenuItem *KCWS; + TMenuItem *KCWSH; + TMenuItem *KCWSM; + TMenuItem *KCWSL; + TMenuItem *KCWSLL; + TMenuItem *N57; + TMenuItem *KCWSI; + TMenuItem *KRadio; + TMenuItem *KRSet; + TMenuItem *KRLoad; + TMenuItem *N58; + TMenuItem *NRadio; + TMenuItem *KRadioS; + TMenuItem *KRadioAdd; + TMenuItem *NRadioE; + TMenuItem *NCWE; + TMenuItem *KCWADD; + void __fastcall FormPaint(TObject *Sender); + + void __fastcall TimerTimer(TObject *Sender); + void __fastcall PBoxFFTPaint(TObject *Sender); + void __fastcall PBoxWaterPaint(TObject *Sender); + void __fastcall FormCloseQuery(TObject *Sender, bool &CanClose); + void __fastcall PBoxRXPaint(TObject *Sender); + void __fastcall KFRecTimClick(TObject *Sender); + void __fastcall KFRecClick(TObject *Sender); + void __fastcall KFPlayClick(TObject *Sender); + void __fastcall KFPlayPosClick(TObject *Sender); + void __fastcall KFRecRewClick(TObject *Sender); + void __fastcall KFRecStopClick(TObject *Sender); + + + void __fastcall PBoxD12MouseDown(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + void __fastcall PBoxD12Paint(TObject *Sender); + void __fastcall SBAutoClick(TObject *Sender); + void __fastcall UDHistClick(TObject *Sender, TUDBtnType Button); + void __fastcall PBoxHistPaint(TObject *Sender); + void __fastcall SBLatestClick(TObject *Sender); + void __fastcall PBoxD12MouseMove(TObject *Sender, TShiftState Shift, + int X, int Y); + void __fastcall SBSampSetClick(TObject *Sender); + void __fastcall SBPasteClick(TObject *Sender); + void __fastcall PBoxTXPaint(TObject *Sender); + void __fastcall SBCopyClick(TObject *Sender); + void __fastcall SBTXClick(TObject *Sender); + void __fastcall PageChange(TObject *Sender); + void __fastcall PBoxTempPaint(TObject *Sender); + void __fastcall KOSCClick(TObject *Sender); + void __fastcall KOMClick(TObject *Sender); + + void __fastcall KExitClick(TObject *Sender); + void __fastcall SBListClick(TObject *Sender); + void __fastcall SBFindClick(TObject *Sender); + void __fastcall SBFindMouseDown(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + void __fastcall SBDataClick(TObject *Sender); + void __fastcall SBDataMouseDown(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + void __fastcall SBInitClick(TObject *Sender); + void __fastcall TempDelay(void); + void __fastcall LogFreqChange(TObject *Sender); + void __fastcall HisCallKeyPress(TObject *Sender, char &Key); + void __fastcall SBQSOClick(TObject *Sender); + void __fastcall KLogOpenClick(TObject *Sender); + void __fastcall KLogFlushClick(TObject *Sender); + void __fastcall KVerClick(TObject *Sender); + void __fastcall PBoxTempMouseDown(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + void __fastcall PBoxTempMouseMove(TObject *Sender, TShiftState Shift, + int X, int Y); + void __fastcall PBoxTempMouseUp(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + void __fastcall SBDlineClick(TObject *Sender); + void __fastcall SBDBoxClick(TObject *Sender); + void __fastcall SBDSelClick(TObject *Sender); + void __fastcall SBDDelClick(TObject *Sender); + void __fastcall SBDTextClick(TObject *Sender); + void __fastcall SBDPicClick(TObject *Sender); + void __fastcall SBDPasteClick(TObject *Sender); + void __fastcall PBoxTempDblClick(TObject *Sender); + void __fastcall SBDFontClick(TObject *Sender); + void __fastcall PBoxSDragDrop(TObject *Sender, TObject *Source, + int X, int Y); + void __fastcall PBoxSDragOver(TObject *Sender, TObject *Source, + int X, int Y, TDragState State, bool &Accept); + void __fastcall PBoxSPaint(TObject *Sender); + void __fastcall SBAFCClick(TObject *Sender); + + + + + + void __fastcall PBoxSMouseDown(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y); + void __fastcall TabSChange(TObject *Sender); + void __fastcall PBoxTXDragOver(TObject *Sender, TObject *Source, int X, + int Y, TDragState State, bool &Accept); + void __fastcall PBoxTXDragDrop(TObject *Sender, TObject *Source, int X, + int Y); + void __fastcall UDStockClick(TObject *Sender, TUDBtnType Button); + void __fastcall SBTuneClick(TObject *Sender); + void __fastcall SBDLinesetClick(TObject *Sender); + void __fastcall SBDColClick(TObject *Sender); + + void __fastcall KSLClick(TObject *Sender); + void __fastcall KSSClick(TObject *Sender); + void __fastcall KSCClick(TObject *Sender); + + void __fastcall KSPClick(TObject *Sender); + void __fastcall KSDClick(TObject *Sender); + void __fastcall PopupSPopup(TObject *Sender); + void __fastcall SBDBoxSClick(TObject *Sender); + void __fastcall FormResize(TObject *Sender); + void __fastcall HisCallChange(TObject *Sender); + void __fastcall CBSTempClick(TObject *Sender); + void __fastcall KOLClick(TObject *Sender); + void __fastcall KTDClick(TObject *Sender); + void __fastcall KTBClick(TObject *Sender); + void __fastcall KTFClick(TObject *Sender); + void __fastcall SBDHeadClick(TObject *Sender); + void __fastcall SBMClick(TObject *Sender); + void __fastcall KTTClick(TObject *Sender); + void __fastcall KTTCClick(TObject *Sender); + void __fastcall SBHViewClick(TObject *Sender); + void __fastcall SBRViewClick(TObject *Sender); + void __fastcall SBTViewClick(TObject *Sender); + void __fastcall SBDS240Click(TObject *Sender); + void __fastcall SBLKClick(TObject *Sender); + void __fastcall PopupTPopup(TObject *Sender); + void __fastcall PBoxTXMouseDown(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + void __fastcall KHlpMainClick(TObject *Sender); + void __fastcall KHlpPadClick(TObject *Sender); + void __fastcall KFileClick(TObject *Sender); + void __fastcall KFL1Click(TObject *Sender); + void __fastcall KFM1Click(TObject *Sender); + void __fastcall KFH1Click(TObject *Sender); + void __fastcall KFT1Click(TObject *Sender); + void __fastcall KFL2Click(TObject *Sender); + void __fastcall KFM2Click(TObject *Sender); + void __fastcall KFH2Click(TObject *Sender); + void __fastcall KFT2Click(TObject *Sender); + void __fastcall KRSClick(TObject *Sender); + void __fastcall KRMClick(TObject *Sender); + void __fastcall KRFClick(TObject *Sender); + void __fastcall KViewClick(TObject *Sender); + void __fastcall FormKeyDown(TObject *Sender, WORD &Key, + TShiftState Shift); + void __fastcall FormKeyUp(TObject *Sender, WORD &Key, + TShiftState Shift); + void __fastcall SBWHistClick(TObject *Sender); + void __fastcall KVOutClick(TObject *Sender); + + void __fastcall SBUseTempClick(TObject *Sender); + void __fastcall SBDA240Click(TObject *Sender); + void __fastcall SBUS240Click(TObject *Sender); + void __fastcall SBUA240Click(TObject *Sender); + void __fastcall KTLClick(TObject *Sender); + void __fastcall KTSAClick(TObject *Sender); + void __fastcall PBoxGPaint(TObject *Sender); + + void __fastcall KFSOFClick(TObject *Sender); + void __fastcall KFSSClick(TObject *Sender); + void __fastcall KFSLClick(TObject *Sender); + + void __fastcall UDSampClick(TObject *Sender, TUDBtnType Button); + void __fastcall SBPhaseClick(TObject *Sender); + void __fastcall KHCDClick(TObject *Sender); + void __fastcall KSCDClick(TObject *Sender); + + void __fastcall SBTuneMouseDown(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + void __fastcall KHDClick(TObject *Sender); + void __fastcall KHSClick(TObject *Sender); + void __fastcall KEditClick(TObject *Sender); + void __fastcall KERClick(TObject *Sender); + void __fastcall KESClick(TObject *Sender); + void __fastcall PopupHPopup(TObject *Sender); + void __fastcall KHFJClick(TObject *Sender); + void __fastcall KHFBClick(TObject *Sender); + void __fastcall KSFJClick(TObject *Sender); + void __fastcall KSFBClick(TObject *Sender); + void __fastcall KRASClick(TObject *Sender); + void __fastcall KRARClick(TObject *Sender); + void __fastcall PopupRPopup(TObject *Sender); + void __fastcall KTAClick(TObject *Sender); + void __fastcall KVRClick(TObject *Sender); + void __fastcall KRRClick(TObject *Sender); + void __fastcall KTBTClick(TObject *Sender); + + void __fastcall KHACDClick(TObject *Sender); + void __fastcall SBULogClick(TObject *Sender); + void __fastcall KHDAClick(TObject *Sender); + void __fastcall KHWebClick(TObject *Sender); + void __fastcall KHRefClick(TObject *Sender); + void __fastcall KVSClick(TObject *Sender); + + void __fastcall KFSQClick(TObject *Sender); + void __fastcall EditQSLDragDrop(TObject *Sender, TObject *Source, + int X, int Y); + void __fastcall EditQSLDragOver(TObject *Sender, TObject *Source, + int X, int Y, TDragState State, bool &Accept); + void __fastcall KPAClick(TObject *Sender); + void __fastcall KPDClick(TObject *Sender); + void __fastcall KP1Click(TObject *Sender); + + void __fastcall KPDefClick(TObject *Sender); + void __fastcall KPClick(TObject *Sender); + void __fastcall KVHClick(TObject *Sender); + void __fastcall SBDListClick(TObject *Sender); + void __fastcall KTEClick(TObject *Sender); + void __fastcall KTTDClick(TObject *Sender); + void __fastcall HisNameChange(TObject *Sender); + void __fastcall HisQTHChange(TObject *Sender); + void __fastcall EditNoteChange(TObject *Sender); + void __fastcall SBTXFilClick(TObject *Sender); + void __fastcall SBHistFilClick(TObject *Sender); + void __fastcall KSTPClick(TObject *Sender); + void __fastcall KVFClick(TObject *Sender); + void __fastcall KRASYClick(TObject *Sender); + void __fastcall KFW30Click(TObject *Sender); + void __fastcall KFW20Click(TObject *Sender); + void __fastcall KFW15Click(TObject *Sender); + void __fastcall KTFXClick(TObject *Sender); + void __fastcall KRBClick(TObject *Sender); + + void __fastcall KHDS1Click(TObject *Sender); + void __fastcall KHDS2Click(TObject *Sender); + void __fastcall KHDS3Click(TObject *Sender); + void __fastcall KHDS4Click(TObject *Sender); + void __fastcall KHDS5Click(TObject *Sender); + void __fastcall KHDS6Click(TObject *Sender); + void __fastcall KVWClick(TObject *Sender); + void __fastcall KFTAClick(TObject *Sender); + void __fastcall KFTD1Click(TObject *Sender); + void __fastcall KFTD2Click(TObject *Sender); + void __fastcall KFTD3Click(TObject *Sender); + void __fastcall KFTD4Click(TObject *Sender); + void __fastcall KXRClick(TObject *Sender); + void __fastcall KXSClick(TObject *Sender); + void __fastcall KX1Click(TObject *Sender); + void __fastcall KXA1Click(TObject *Sender); + void __fastcall KXD1Click(TObject *Sender); + void __fastcall KXClick(TObject *Sender); + void __fastcall KFTD5Click(TObject *Sender); + void __fastcall KTAPClick(TObject *Sender); + void __fastcall KTACClick(TObject *Sender); + void __fastcall SBLMSClick(TObject *Sender); + void __fastcall KPInitClick(TObject *Sender); + void __fastcall KVLSGClick(TObject *Sender); + void __fastcall KVLSYClick(TObject *Sender); + void __fastcall KHTBClick(TObject *Sender); + void __fastcall OpenDialogSelectionChange(TObject *Sender); + void __fastcall KTPAClick(TObject *Sender); + + void __fastcall KSAIClick(TObject *Sender); + void __fastcall PopupMPopup(TObject *Sender); + + void __fastcall SBMMouseUp(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + void __fastcall KRRCClick(TObject *Sender); + void __fastcall KSSZClick(TObject *Sender); + void __fastcall KHlpUpClick(TObject *Sender); + void __fastcall KSSDClick(TObject *Sender); + void __fastcall KTSZClick(TObject *Sender); + void __fastcall KTSDClick(TObject *Sender); + void __fastcall KHSDClick(TObject *Sender); + void __fastcall KRSDClick(TObject *Sender); + void __fastcall SBTOClick(TObject *Sender); + void __fastcall KRCSClick(TObject *Sender); + void __fastcall KRSRClick(TObject *Sender); + + void __fastcall KTUClick(TObject *Sender); + + void __fastcall SBRXIDClick(TObject *Sender); + void __fastcall KSOFFClick(TObject *Sender); + void __fastcall SBRXIDMouseUp(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + void __fastcall KSFClick(TObject *Sender); + void __fastcall KTF1Click(TObject *Sender); + void __fastcall KTKAClick(TObject *Sender); + void __fastcall UDStockMouseDown(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + void __fastcall KRI1Click(TObject *Sender); + + void __fastcall HisNameKeyPress(TObject *Sender, char &Key); + void __fastcall KVCClick(TObject *Sender); + void __fastcall KRCDClick(TObject *Sender); + void __fastcall KORepClick(TObject *Sender); + void __fastcall KTMDClick(TObject *Sender); + void __fastcall KEWClick(TObject *Sender); + void __fastcall PBoxSMouseMove(TObject *Sender, TShiftState Shift, + int X, int Y); + void __fastcall PBoxSDblClick(TObject *Sender); + void __fastcall HisCallDblClick(TObject *Sender); + void __fastcall HisQTHDblClick(TObject *Sender); + + void __fastcall KVSD1Click(TObject *Sender); + void __fastcall KHVSClick(TObject *Sender); + void __fastcall KRFSClick(TObject *Sender); + void __fastcall KSBClick(TObject *Sender); + void __fastcall KSMS4Click(TObject *Sender); + + void __fastcall KHMT3Click(TObject *Sender); + + void __fastcall KHelpClick(TObject *Sender); + void __fastcall OpenDialogClose(TObject *Sender); + void __fastcall KTSIClick(TObject *Sender); + void __fastcall KTLIClick(TObject *Sender); + void __fastcall KTPBClick(TObject *Sender); + + + void __fastcall SBRXFilClick(TObject *Sender); + + void __fastcall UDHistMouseDown(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + + void __fastcall KTOIClick(TObject *Sender); + void __fastcall KTOClick(TObject *Sender); + void __fastcall KTOPClick(TObject *Sender); + void __fastcall KTOCClick(TObject *Sender); + + + + + + + + + + + + + void __fastcall IMenuClick(TObject *Sender); + void __fastcall KVSDClick(TObject *Sender); + void __fastcall KVSE1Click(TObject *Sender); + void __fastcall KTCIClick(TObject *Sender); + void __fastcall KTOSClick(TObject *Sender); + void __fastcall FormDestroy(TObject *Sender); + void __fastcall PBoxFFTMouseDown(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + void __fastcall PBoxFFTMouseMove(TObject *Sender, TShiftState Shift, + int X, int Y); + void __fastcall PBoxFFTMouseUp(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + void __fastcall SBTXMouseDown(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + void __fastcall SBLMSMouseDown(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + void __fastcall KLM1Click(TObject *Sender); + + void __fastcall KSAClick(TObject *Sender); + void __fastcall KTFSClick(TObject *Sender); + void __fastcall KHNClick(TObject *Sender); + void __fastcall KHJClick(TObject *Sender); + void __fastcall SBCWClick(TObject *Sender); + void __fastcall SBCWMouseDown(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + + + void __fastcall KSAMClick(TObject *Sender); + + void __fastcall SBListMouseDown(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + + void __fastcall PBoxLvlMouseDown(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + void __fastcall SBTXIDClick(TObject *Sender); + void __fastcall SBDFontMouseDown(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + void __fastcall KTHClick(TObject *Sender); + void __fastcall KEEClick(TObject *Sender); + void __fastcall KSEClick(TObject *Sender); + void __fastcall KXPClick(TObject *Sender); + void __fastcall KHEClick(TObject *Sender); + void __fastcall KRCCClick(TObject *Sender); + + void __fastcall SBPLClick(TObject *Sender); + + + + + void __fastcall SBPLMouseDown(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + + void __fastcall SBAdjMouseDown(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + void __fastcall KRCRClick(TObject *Sender); + void __fastcall KCWClick(TObject *Sender); + void __fastcall PopupCWPopup(TObject *Sender); + void __fastcall KCWSHClick(TObject *Sender); + void __fastcall KCWSMClick(TObject *Sender); + void __fastcall KCWSLClick(TObject *Sender); + void __fastcall KCWSLLClick(TObject *Sender); + void __fastcall KCWSIClick(TObject *Sender); + void __fastcall KRSetClick(TObject *Sender); + void __fastcall KRLoadClick(TObject *Sender); + + void __fastcall KRadioAddClick(TObject *Sender); + void __fastcall KRadioClick(TObject *Sender); + void __fastcall KCWADDClick(TObject *Sender); +private: // ユーザー宣言 + int m_InitFirst; + int m_DisEvent; +// int m_Timer1S; + int m_ChangeTemp; + + int m_SMax; + + short m_Y36[800]; + short m_D36[2][800]; + int m_DSEL; + + CAlignList AlignFix; + CAlignList AlignMode; + CAlignList AlignDsp; + CAlignList AlignLog; + CAlignList AlignPCS; + void __fastcall EntryAlign(void); + void __fastcall StartOption(void); + + void __fastcall UpdateLogLink(void); + void __fastcall UpdateTitle(void); + void __fastcall UpdateLMS(void); + void __fastcall AdjustFocus(void); + + void __fastcall UpdateSBTO(void); + void __fastcall UpdateUI(void); + void __fastcall UpdateUITemp(void); + +// void __fastcall OnIdle(TObject *Sender, bool &Done); + void __fastcall UpdateToneFreq(void); + void __fastcall UpdateSystemFont(void); + void __fastcall ReadSampFreq(void); + void __fastcall ReadCombList(TMemIniFile *tp, AnsiString &as, LPCSTR pKey, LPCSTR pDef); + void __fastcall ReadRegister(void); + void __fastcall WriteRegister(void); + + void __fastcall UpdateModeBtn(void); + + void __fastcall ClearDraw(Graphics::TBitmap *pBitmap, TPaintBox *pBox, TColor col); + void __fastcall SyncSSTV(void); + int __fastcall GetPixelLevel(short *ip); + int __fastcall GetPictureLevel(short *ip); + int __fastcall GetPictureLevelDiff(short *ip); + void __fastcall DrawSSTV(short *ip, short *sp); + void __fastcall DrawSSTVNormal(short *ip, short *sp); + void __fastcall DrawSSTVDiff(short *ip, short *sp); + void __fastcall InfoRxLost(void); + void __fastcall InfoTxLost(void); + void __fastcall TrackTxMode(int sw); + void __fastcall WriteHistory(int sw); + void __fastcall DrawSSTV(void); + void __fastcall DrawLvl(void); + void __fastcall AdjustPBoxSize(int l); + void __fastcall KMClick(TObject *Sender); + +public: + Graphics::TBitmap *pBitmapFFT; + Graphics::TBitmap *pBitmapWater; + Graphics::TBitmap *pBitmapRX; + Graphics::TBitmap *pBitmapD12; + Graphics::TBitmap *pBitmapLvl; + Graphics::TBitmap *pBitmapHist; + Graphics::TBitmap *pBitmapHistF; + Graphics::TBitmap *pBitmapTX; + Graphics::TBitmap *pBitmapTXM; + Graphics::TBitmap *pBitmapTemp; + Graphics::TBitmap *pBitmapNearest; + + Graphics::TBitmap *pBitmapSS; + Graphics::TBitmap *pBitmapST[STOCKPAGE]; + + int m_MW; // タイトルバーとメニューバーの幅 + int m_ReqHistF; + void __fastcall DeleteHistF(void); + void __fastcall AdjustHistF(void); + void __fastcall TrigHistF(void); + +private: + CRecentMenu RecentMenu; + void __fastcall OnRecentClick(TObject *Sender); + void __fastcall RecentAdd(LPCSTR pNew, int f); + void __fastcall UpdateRecentMenu(void); + + int m_Slant; + int m_SlantX, m_SlantY; + int m_SlantX2, m_SlantY2; + void __fastcall DispSyncStat(void); + double __fastcall GetSyncSamp(int X, int Y); + void __fastcall DrawSync(void); + +// void __fastcall GetRY(int &Y, int &RY, int &BY, TColor col); + void __fastcall LineR24(CSSTVMOD *mp); + void __fastcall LineR36(CSSTVMOD *mp); + void __fastcall LineR72(CSSTVMOD *mp); + void __fastcall LineAVT(CSSTVMOD *mp); + void __fastcall LineSCT(CSSTVMOD *mp, double tw); + void __fastcall LineMRT(CSSTVMOD *mp, double tw); + void __fastcall LineSC2180(CSSTVMOD *mp, double S, double tw); + void __fastcall LinePD(CSSTVMOD *mp, double tw); + void __fastcall LineP(CSSTVMOD *mp, double S, double P, double C); + void __fastcall LineMP(CSSTVMOD *mp, double tw); + void __fastcall LineMR(CSSTVMOD *mp, double tw); + void __fastcall LineRM(CSSTVMOD *mp, double ts, double tw); + void __fastcall LineMN(CSSTVMOD *mp, double tw); + void __fastcall LineMC(CSSTVMOD *mp, double tw); + + BYTE *m_pRowBuf; + void __fastcall OutputMMV(void); + void __fastcall OutputFSKID(void); + void __fastcall OutputCWID(void); + int __fastcall IsSR(void); + void __fastcall SendSSTV(void); + void __fastcall OutHEAD(void); + + int m_SendY; + void __fastcall DrawTXCursor_(int y); + void __fastcall DrawTXCursor(int y); + void __fastcall DeleteTXCursor(void); + void __fastcall MakeTxBitmap(int sw); + + void __fastcall AutoCopyJob(SYSTEMTIME tim, Graphics::TBitmap *pSource); + + void __fastcall UpdateTxClip(void); + int m_TxClipType; +//calibration + short *pCalibration; +public: + void __fastcall MakeCalibrationTable(void); + +//Hist + CBitmapHist RxHist; + void __fastcall UpdateHist(void); + void __fastcall DispHistStat(void); + void __fastcall GetTempHistSize(int &x, int &y); +public: +//Mode + int m_ExtMode; + int m_HistM; + int m_RXW, m_RXH, m_RXPH; + int m_TXW, m_TXH, m_TXPH; + int m_ModeAssignTX[9]; + int m_ModeAssignRX[9]; +private: + TSpeedButton *__fastcall GetModeBtn(int n); + int __fastcall GetButtonNo(TSpeedButton *tp); + void __fastcall UpdateModeCaption(void); + void __fastcall ChangeTxMode(int mode); + int __fastcall FindModeAssign(int *ip, int m); + void __fastcall AdjustTempSC(int &X, int &Y); + void __fastcall AdjustTempView(int sw); + void __fastcall ShowSize(TPaintBox *pBox, int w, int h, int fs, TColor col); + void __fastcall ShowSize(Graphics::TBitmap *pBitmap, int x, int y, int w, int h, int fs, TColor col); + void __fastcall ShowNo(Graphics::TBitmap *pBitmap, int x, int y, int n, int fs, TColor col); + +//Recv +public: + SYSTEMTIME m_StartTime; +private: + double m_Z[3]; + int m_AX, m_AY; +//Tune + DWORD m_TuneTimer; + int m_TuneTX; +//Susp + int m_SuspMinimized; +//Sync + void __fastcall CopyStgBuf(void); + void __fastcall InfoSampFreq(void); + CWaveStrage WaveStg; + int m_ReqSampChg; + double m_SampFreq; + void __fastcall DrawSlantInfo(void); + void __fastcall DrawShiftInfo(void); + void __fastcall CorrectSlant(void); + int __fastcall AdjustSyncPos(int n); + void __fastcall ReSyncSSTV(void); + void __fastcall RedrawSampFreq(int sw); + void __fastcall UpdateSampFreq(void); + void __fastcall RedrawSSTV(void); + void __fastcall RedrawAdjustSync(void); + void __fastcall ShiftSSTV(TObject *Sender, int step); + +//FFT + void __fastcall InitDrawFFT(void); + void __fastcall CalcFFT(void); + void __fastcall DrawFFT(int sw); + void __fastcall DrawWater(int sw); +public: + void __fastcall InitFFT(void); +private: + int m_FFTWINDOW; + int m_XW; + int m_FM; + int m_low; + int m_of; + int m_FX[7]; + int m_fft[DFFTSIZE]; + + int m_FFTFlag; + + int m_FFTMax; + int m_FFTSumMax; + + int m_FFTMAX[DFFTSIZE]; + + int m_WaterMax; + int m_WaterSumMax; + int m_WaterMin; + + int m_MainPage; +//Log + void __fastcall AddCall(LPCSTR p); + void __fastcall KCClick(TObject *Sender); + int m_Dupe; + void __fastcall UpdateCallsign(void); + void __fastcall UpdateLogData(void); + void __fastcall UpdateTextData(void); + void __fastcall FindCall(void); + void __fastcall AutoLogSave(void); + void __fastcall SetGreetingString(LPSTR t, LPCSTR pCall, int type); + + void __fastcall DateBitmap(Graphics::TBitmap *pBitmap, SYSTEMTIME &tim); + +// Draw + int m_TempHold; + int m_TempTimer; + int m_TempX, m_TempY; + int m_DrawTrans; + int m_DrawCmd; + CDraw *pDraw; + CDraw *pPaste; +public: + CDrawGroup DrawMain; + CDrawGroup DrawText; + CDrawGroup DrawTemp; + TMemoryStream *pUndo; +// CGrid TempGrid; +private: + void __fastcall DeleteUndo(void); + void __fastcall SaveUndo(void); + TMemoryStream *__fastcall SaveUndo(TMemoryStream *ps); + void __fastcall UpdateUndo(TMemoryStream *ps); + void __fastcall PBoxTempCursor(int X, int Y); + + +public: + void __fastcall RxAutoPush(int sw); + void __fastcall UpdateTemp(void); + void __fastcall UpdatePic(void); + void __fastcall UpdatePic(int sw); + void __fastcall DropOle(int X, int Y, LPCSTR pName, int trans); + void __fastcall DropLib(int X, int Y, LPCSTR pName); + void __fastcall DropPic(int X, int Y, Graphics::TBitmap *pSrc, int type); +private: +// Stock + void __fastcall GetStockXY(int &X1, int &Y1, int &X2, int &Y2, int n); + int __fastcall TMmsstv::GetStockNo(int X, int Y); + int m_DragNo; + int m_DragDataNo; + int m_DragPMax; + int m_TabSXX, m_TabSYY; + + int m_TxSPage; + int m_PSPage; + int m_TSPage[STOCKPAGE]; + int m_APSPage; + int m_ATSPage[STOCKPAGE]; + DWORD m_PSSize[18]; + + int m_StockPage; + int m_StockOff; + + void __fastcall UpdateTabS(void); + void __fastcall SaveBitmapS(Graphics::TBitmap *pBitmap, int n); + void __fastcall SaveBitmapSN(Graphics::TBitmap *pBitmap, int n); + Graphics::TBitmap* __fastcall LoadBitmapS(int n); + void __fastcall LoadBitmapSN(Graphics::TBitmap *pBitmap, int n); + +public: + int __fastcall LoadBitmapMenu(Graphics::TBitmap *pBitmap, int rs); + int __fastcall SaveBitmapMenu(Graphics::TBitmap *pBitmap, LPCSTR pName, LPCSTR pFolder); + int __fastcall LoadTemplateMenu(CDrawGroup *pItem, int isw); + int __fastcall SaveTemplateMenu(CDrawGroup *pItem, int isw); + int __fastcall SaveTemplateMenu(CDrawGroup *pItem, LPCSTR pName, LPCSTR pFolder, int isw); + void __fastcall AddTemplate(CDrawGroup *pGroup); + void __fastcall AddItem(CDraw *pItem, int b); + + void __fastcall LoadCurrentTemp(void); + void __fastcall LoadStockTemp(CDrawGroup *pItem, int n, TCanvas *tp); + void __fastcall SaveStockTemp(CDrawGroup *pItem, int n); + void __fastcall DeleteStockTemp(int n); + +private: + + void __fastcall LoadDefTemp(void); + void __fastcall MoveStockDir(LPCSTR pNewDir); + void __fastcall ChangeStockFormat(int sw); + void __fastcall ReleaseStockResource(void); + + int m_SyncAccuracy; + int m_SyncAccuracyN; + + void __fastcall InitAutoStop(void); + int __fastcall GetSqerrPos(int n); + int __fastcall AutoStop(int x, short *sp); + int __fastcall AutoStopJob(void); + + int m_SpecDown; +//Auto + int m_Mult; +//AutoStop + int m_AutoStopPos; + int m_AutoStopAPos[16]; + int m_AutoStopCnt; + int m_AutoStopACnt; +//AutoSync + int m_AutoSyncCount; + int m_AutoSyncPos; + int m_AutoSyncDis; + int m_AutoSyncDiff; +//AutoSlant + int m_ASBgnPos; + int m_ASCurY; + int m_ASDis; + int m_ASBitMask; + double m_ASLmt[7]; + int m_ASPos[4]; + CSmooz m_ASAvg; +//Palette + DYNAMIC HPALETTE __fastcall GetPalette(void); +//RxView + int m_TimerRXV; + int m_TimerRXS; + TRxViewDlg *pRxView; + TRxViewDlg *pSyncView; +//HistView + THistViewDlg *pHistView; + void __fastcall OpenHistView(void); + void __fastcall CloseHistView(void); + +//ImageView + void __fastcall AdjustFileView(void); + void __fastcall ShowFileView(int i, int ttl); + void __fastcall CloseFileView(int n); + +public: + void __fastcall ReOpenFileView(TFileViewDlg *pView); + void __fastcall LoadAllFileView(void); + TFileViewDlg *pFileView[8]; + int m_FileViewClose; +//Preview + int m_PreViewFlag; + TPrevViewBox *pPreView; + int __fastcall OpenDialogExecute(int sw); +private: +//PROFILE + PRODEM m_DemPro[9]; + TMenuItem *__fastcall GetKP(int n); + TMenuItem *__fastcall GetKPA(int n); + TMenuItem *__fastcall GetKPD(int n); + void __fastcall UpdateProFileMenu(void); + void __fastcall SetProFile(int n); + void __fastcall InitProfile(void); + +//PROGRAM + TMenuItem *__fastcall GetKX(int n); + TMenuItem *__fastcall GetKXA(int n); + TMenuItem *__fastcall GetKXD(int n); + void __fastcall UpdateProgramMenu(void); + void __fastcall ExecExtCmd(int n); + int __fastcall AssignExtCmd(int n); + +//LMSDelay + int __fastcall GetLMSDelay(void); + +// WebRef + CWebRef WebRef; + +// Comm + void __fastcall OpenCloseCom(void); + + CComm *pComm; + CCradio *pRadio; + +//コントロールWnd + TCtrBtnWnd *pCtrBtn; + + int m_SyncPos, m_SyncRPos; + int m_SyncMax, m_SyncMin; +public: // ユーザー宣言 + __fastcall TMmsstv(TComponent* Owner); + + TSound *pSound; + CSSTVDEM *pDem; + CSSTVMOD *pMod; + void __fastcall MacroDate(LPSTR t, SYSTEMTIME &now); + int __fastcall MacroText(LPSTR t, LPCSTR p, int size); + + void __fastcall WndProc(TMessage &Message); + void __fastcall WndCopyData(TMessage &Message); + void __fastcall OnMini(TObject *Sender); + void __fastcall OnMSG(tagMSG &Msg, bool &Handled); + void __fastcall AppException(TObject *Sender, Exception *E); + void __fastcall DropFile(tagMSG &Msg); + + void __fastcall UpdateTXUI(void); + void __fastcall ToTX(void); + void __fastcall ToRX(void); + + void __fastcall CopyBitmap(Graphics::TBitmap *pBitmap); + int __fastcall PasteBitmap(Graphics::TBitmap *pBitmap, int rs); + + void __fastcall GetFFTRect(int &FM, int &low); + void __fastcall MultProc(void); + void __fastcall AdjustPage(int sw); + + + DWORD m_RepTick; + int m_RepBeaconCount; + int m_RepBeaconPos; + int m_RepTXPos; + + void __fastcall Repeater(void); + void __fastcall SendCWID(LPCSTR p); + int __fastcall LoadRepTemplate(LPCSTR pList, int &Pos); + void __fastcall SendBeacon(void); + void __fastcall SetBeaconTick(void); + void __fastcall SetBeaconDelay(void); + void __fastcall GetBeaconBitmap(Graphics::TBitmap *pBitmap, int n); + void __fastcall MakeBeacon(int sw, int fsw, int nn); + void __fastcall MakeReplay(void); + void __fastcall MakeThImage(int mm); + + int m_OrgTop; + int m_OrgLeft; + DWORD m_dwVersion; + +//ウインドウの分離 + int m_ClientHeight[2]; + int m_ClientWidth[2]; + TStockView *pStockView; + TStockView *pWaterView; + TStockView *pLogView; + void __fastcall DivStockView(void); + void __fastcall AdjustStockView(void); + void __fastcall MoveParent(TWinControl *pNew, TWinControl *pOld, TWinControl *pCtr); + void __fastcall DivWaterView(void); + void __fastcall DivControl(int sw); + + void __fastcall UpdatePriority(void); + + int m_AppErr; + + HWND m_hClipNext; +//CWMenu + void __fastcall AdjustCWMenu(void); + void __fastcall KCWSendClick(TObject *Sender); + void __fastcall KCWEditClick(TObject *Sender); + +//RadioMenu +public: + int m_nRadioMenu; +private: + RADIOMENU m_RadioMenu[RADIOMENUMAX]; + + void __fastcall LoadRadioDef(LPCSTR pName); + void __fastcall AdjustRadioMenu(void); + void __fastcall KRadioCmdClick(TObject *Sender); + void __fastcall KRadioEditClick(TObject *Sender); + +//#define CM_FFT WM_USER+403 +#define CM_CRADIO WM_USER+400 +#define CM_CMML WM_USER+401 +#define CM_CMMR WM_USER+402 +#define CM_EDITEXIT WM_USER+404 +protected: + void __fastcall CMfft(TMessage *Message); + void __fastcall OnMove(TMessage *Message); + void __fastcall CMMML(TMessage Message); + void __fastcall CMMMR(TMessage Message); + void __fastcall OnEditExit(TMessage Message); + void __fastcall OnDrawClipboard(TMessage Message); + void __fastcall OnChangeCbChain(TMessage Message); + +BEGIN_MESSAGE_MAP + MESSAGE_HANDLER(CM_FFT, TMessage*, CMfft) + MESSAGE_HANDLER(WM_MOVE, TMessage*, OnMove) + MESSAGE_HANDLER(CM_CMML, TMessage, CMMML) + MESSAGE_HANDLER(CM_CMMR, TMessage, CMMMR) + MESSAGE_HANDLER(CM_EDITEXIT, TMessage, OnEditExit) + MESSAGE_HANDLER(WM_DRAWCLIPBOARD, TMessage, OnDrawClipboard) + MESSAGE_HANDLER(WM_CHANGECBCHAIN, TMessage, OnChangeCbChain) +END_MESSAGE_MAP(TForm) +}; +//--------------------------------------------------------------------------- +extern PACKAGE TMmsstv *Mmsstv; +//--------------------------------------------------------------------------- +#endif + + diff --git a/Mmcg.cpp b/Mmcg.cpp new file mode 100644 index 0000000..83a1194 --- /dev/null +++ b/Mmcg.cpp @@ -0,0 +1,1521 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +/************************************************************************ + MMCG + + Copyright (C) JE3HHT 1993. + Modifed on 2000 for MMTTY by JE3HHT +************************************************************************/ +#include //ja7ude 0521 +#pragma hdrstop + +#include "ComLib.h" +#include "Mmcg.h" +#include "string.h" +#include "stdlib.h" +#include "Country.h" + +CMMCG mmcg; + +static LPCSTR ptbl[]={ + "", + "北海道", "青森県","岩手県","秋田県","山形県","宮城県","福島県","新潟県", + "長野県", "東京都","神奈川県","千葉県","埼玉県","茨城県","栃木県","群馬県", + "山梨県","静岡県","岐阜県","愛知県","三重県","京都府","滋賀県","奈良県", + "大阪府","和歌山県","兵庫県","富山県","福井県","石川県","岡山県","島根県", + "山口県","鳥取県","広島県","香川県","徳島県","愛媛県","高知県","福岡県", + "佐賀県","長崎県","熊本県","大分県","宮崎県","鹿児島県","沖縄県" +}; + +static LPCSTR ptbleng[]={ + "", + "Hokkaido", "Aomori","Iwate","Akita","Yamagata","Miyazaki","Fukushima","Nigata", + "Nagano", "Tokyo","Kanagawa","Chiba","Saitama","Ibaragi","Tochigi","Gunma", + "Yamanashi","Shizuoka","Gifu","Aichi","Mie","Kyoto","Shiga","Nara", + "Osaka","Wakayama","Hyogo","Toyama","Fukui","Ishikawa","Okayama","Shimane", + "Yamaguchi","Tottri","Hiroshima","Kagawa","Tokushima","Ehime","Kochi","Fukuoka", + "Saga","Nagasaki","Kumamoto","Oita","Miyazaki","Kagoshima","Okinawa" +}; + +CMMCG::CMMCG() +{ + m_bp = NULL; + m_Max = 0; + m_Cnt = 0; + m_sinc = 0; + m_mask = -1; +} + +CMMCG::~CMMCG() +{ + Free(); +} + +void CMMCG::Free(void) +{ + if( m_bp != NULL ){ + int i; + MMCG *mp; + + for( mp = m_bp, i = 0; i < m_Cnt; i++, mp++ ){ + if( mp->Code != NULL ) delete mp->Code; + if( mp->QTH != NULL ) delete mp->QTH; + if( mp->Key != NULL ) delete mp->Key; + } + m_bp = NULL; + } + if( m_fp != NULL ){ + delete m_fp; + m_fp = NULL; + } + m_Max = m_Cnt = m_FindCnt = 0; +} + +void CMMCG::Alloc(int n) +{ + if( n >= m_Max ){ + int max = m_Max ? m_Max * 2 : 256; + MMCG *np = (MMCG *)new BYTE[sizeof(MMCG) * max]; + if( m_bp != NULL ){ + memcpy(np, m_bp, sizeof(MMCG) * m_Cnt); + delete m_bp; + } + m_bp = np; + m_Max = max; + } +} + +/*#$% +====================================================== + ローマ綴りを調整する +------------------------------------------------------ +------------------------------------------------------ +------------------------------------------------------ +====================================================== +*/ +LPSTR CMMCG::adjspl(LPSTR p) +{ + static char bf[50]; + LPCSTR tp[]={ + "TSU","TU", + "CHA","CYA", + "CHI","CI", + "CHU","CYU", + "CHO","CYO", + "JYA","JA", + "JYU","JU", + "JYO","JO", + "SHA","SYA", + "SHI","SI", + "SHU","SYU", + "SHE","SYE", + "SHO","SYO", + }; + int i, f; + char *t; + + for( t = bf; *p;){ + for( f = 0, i = 0; i < AN(tp); i+=2 ){ + if( !strncmp(p, tp[i], strlen(tp[i])) ){ + strcpy(t, tp[i+1]); + t += strlen(t); + p += strlen(tp[i]); + f++; + break; + } + } + if( !f ){ + *t++ = *p++; + } + } + *t = 0; + return(bf); +} + +/*#$% +====================================================== + 最後のローマ綴りで検索起動を断念する +------------------------------------------------------ +------------------------------------------------------ +------------------------------------------------------ +====================================================== +*/ +int CMMCG::chkspl(LPCSTR p) +{ + static char *tp[]={ + "TS","CH","JY","SH", + }; + int i; + + i = strlen(p); + if( i >= 2 ){ + p += (i-2); + for( i = 0; i < AN(tp); i++ ){ + if( !strcmp(tp[i], p) ) return 0; + } + } + return 1; +} + +/*#$% +====================================================== + 文字列の最後の一致を調べる +------------------------------------------------------ +------------------------------------------------------ +------------------------------------------------------ +====================================================== +*/ +int CMMCG::LastMatch(LPSTR t, LPSTR s) +{ + t = lastp(t) - strlen(s) + 1; + return !strcmp(t, s); +} + +/*#$% +====================================================== + 入力されたQTHを正規化する +------------------------------------------------------ +------------------------------------------------------ +------------------------------------------------------ +====================================================== +*/ +int CMMCG::NormQth(LPSTR p) +{ + int i; + LPCSTR *cp; + + for( i = 1, cp = &ptbl[1]; i < AN(ptbl); i++, cp++ ){ + if( !strncmp(p, *cp, strlen(*cp)) ){ + if( *(p + strlen(*cp)) ){ + strcpy(p, p + strlen(*cp)); + return 1; + } + } + } + return 0; +} + +/*#$% +====================================================== + エリアマスクを設定する +------------------------------------------------------ +------------------------------------------------------ +------------------------------------------------------ +====================================================== +*/ +void CMMCG::SetMask(void) +{ + LPCSTR p; + + m_mask = -1; + if( m_Call[0] ){ /* エリアマスク */ + p = m_Call; + if( (m_Call[0] == '7') && (m_Call[1] != 'J') ){ + m_mask = 1; + p += 3; + } + for( ; *p; p++ ){ + if( isdigit(*(LPUSTR)p) ) m_mask = ((*p) & 0x0f); + } + } +} + +/*#$% +====================================================== + コードから検索対象にするかどうか調べる +------------------------------------------------------ + p : コードのポインタ +------------------------------------------------------ +------------------------------------------------------ +====================================================== +*/ +int CMMCG::isfind(LPCSTR p) +{ + const char _tt[]={ + -1, + 8, /* 01 */ + 7, 7, 7, 7, 7, 7, /* 02-07 */ + 0, 0, /* 08-09 */ + 1, 1, 1, 1, 1, 1, 1, 1, /* 10-17 */ + 2, 2, 2, 2, /* 18-21 */ + 3, 3, 3, 3, 3, 3, /* 22-27 */ + 9, 9, 9, /* 28-30 */ + 4, 4, 4, 4, 4, /* 31-35 */ + 5, 5, 5, 5, /* 36-39 */ + 6, 6, 6, 6, 6, 6, 6, 6, /* 40-47 */ + }; + + if( m_mask == -1 ){ + return 1; + } + else { + return( (_tt[atoin(p, 2)] == m_mask) ? 1 : 0 ); + } +} + + +/*#$% +====================================================== + 指定位置の文字の種類を得る +------------------------------------------------------ + p : バッファのポインタ + x : 位置 +------------------------------------------------------ +------------------------------------------------------ +====================================================== +*/ +int CMMCG::_ischrtyp(char *p, int x) +{ + int xx, jis; + + for( jis = xx = 0; xx < x; xx++, p++ ){ + if( jis ){ + jis = 0; + } + else if( _mbsbtype((unsigned char *)p, 0) == _MBC_LEAD ){ + jis = 1; + } + } + if( jis ){ /* KANJI2 */ + return 2; + } + else if( _mbsbtype((unsigned char *)p, 0) == _MBC_LEAD ){ /* KANJI1 */ + return 1; + } + else { /* ANK */ + return 0; + } +} + +/*#$% +====================================================== + データファイルを読み込む +------------------------------------------------------ +------------------------------------------------------ +------------------------------------------------------ +====================================================== +*/ +void CMMCG::LoadDef(LPCSTR pFileName) +{ + FILE *fp; + char hbf[512]; + LPSTR t, p; + + Free(); + if( (fp = fopen(pFileName, "rt"))!=NULL ){ + while( !feof(fp) ){ + if( fgets(hbf, 512, fp)!=NULL ){ + if( hbf[0] == '$' ) break; + ClipLF(hbf); + if( hbf[0] != '!' ){ + p = StrDlm(t, hbf, TAB); + clipsp(t); + Alloc(m_Cnt); + m_bp[m_Cnt].Code = StrDupe(t); + if( p != NULL ){ + p = StrDlm(t, p, TAB); + if( *t == '%' ) *t = 0; + clipsp(t); + m_bp[m_Cnt].QTH = StrDupe(SkipSpace(t)); + } + else { + m_bp[m_Cnt].QTH = StrDupe(""); + } + if( p != NULL ){ + clipsp(p); + m_bp[m_Cnt].Key = StrDupe(SkipSpace(p)); + } + else { + m_bp[m_Cnt].Key = StrDupe(""); + } + m_Cnt++; + } + } + } + fclose(fp); + m_fp = (MMCG **)new BYTE[sizeof(MMCG*)*m_Cnt]; + } + else { + WarningMB(MsgEng ? "'%s' was not found.\r\n\r\nYou cannot use a JCC/JCG list function.\r\nThis is not a problem if you do not need it":"'%s'が見つかりません.", pFileName); + } +} + +/*#$% +====================================================== + コードから県名を得る +------------------------------------------------------ + code : コードのポインタ +------------------------------------------------------ + 県名のポインタ +------------------------------------------------------ +====================================================== +*/ +LPCSTR CMMCG::getprf(LPCSTR pCode) +{ + int n; + + n = atoin(pCode, 2); + return(MsgEng ? ptbleng[n] : ptbl[n]); +} + +/*#$% +====================================================== + 郡名を得る +------------------------------------------------------ + p : 町村コードのポインタ +------------------------------------------------------ + QTHのポインタ +------------------------------------------------------ +====================================================== +*/ +void CMMCG::GetGun(LPSTR t, LPCSTR pCode) +{ + strcpy(wbf, pCode); + wbf[5] = 0; + MMCG *mp = m_bp; + int i; + for( i = 0; i < m_Cnt; i++, mp++ ){ + if( !strcmp(mp->Code, wbf) ){ + strcpy(t, mp->QTH); + return; + } + } + *t = 0; +} + +/*#$% +====================================================== + QTHの文字列を得る +------------------------------------------------------ + cp : データのポインタ +------------------------------------------------------ + QTHのポインタ +------------------------------------------------------ +====================================================== +*/ +LPCSTR CMMCG::GetQTH(MMCG *mp) +{ + char bf[512]; + + if( MsgEng ){ + char qth[128]; + strcpy(qth, mp->Key); + LPSTR t; + LPSTR p = qth; + while(*p){ + p = StrDlm(t, p, ','); + } + if( strlen(mp->Code) == 6 ){ + if( isalpha((unsigned char)LastC(mp->Code)) ){ /* 町村コード */ + strcpy(bf, t); + strcat(bf, ","); + GetGun(qth, mp->Code); + strcat(bf, qth); + } + else { /* 政令指定都市 */ + strcpy(bf, t); + } + } + else { /* 都道府県を追加 */ + if( *t ){ + sprintf( bf, "%s,%s", t, getprf(mp->Code)); + } + else { + sprintf( bf, "%s", getprf(mp->Code)); + } + } + } + else { + if( strlen(mp->Code) == 6 ){ + if( isalpha((unsigned char)LastC(mp->Code)) ){ /* 町村コード */ + GetGun(bf, mp->Code); + strcat(bf, mp->QTH); + } + else { /* 政令指定都市 */ + strcpy(bf, mp->QTH); + } + } + else { /* 都道府県を追加 */ + sprintf( bf, "%s%s", getprf(mp->Code), mp->QTH); + } + } + bf[MLQTH] = 0; + m_QTH = bf; + return m_QTH.c_str(); + + +} + + +/*#$% +====================================================== + データの検索を行う(すべて) +------------------------------------------------------ +------------------------------------------------------ +------------------------------------------------------ +====================================================== +*/ +void CMMCG::FindAll(void) +{ + MMCG *mp; + int i; + + m_FindCnt = 0; + mp = m_bp; + for( i = 0; i < m_Cnt; i++, mp++ ){ + if( isfind(mp->Code) ){ + m_fp[m_FindCnt] = mp; + m_FindCnt++; + } + } +} + +/*#$% +====================================================== + 同一データが存在するか調べる +------------------------------------------------------ +------------------------------------------------------ +------------------------------------------------------ +====================================================== +*/ +int CMMCG::isEnt(MMCG *mp) +{ + int i; + + for( i = 0; i < m_FindCnt; i++ ){ + if( m_fp[i] == mp ) return 1; + } + return 0; +} + +/*#$% +====================================================== + データの検索を行う +------------------------------------------------------ +------------------------------------------------------ +------------------------------------------------------ +====================================================== +*/ +void CMMCG::FindQTH(LPSTR pKey) +{ + MMCG *mp; + int i; + int len, kj; + LPSTR t, p; + + kj = _mbsbtype((unsigned char *)pKey, 0) == _MBC_LEAD ? 1 : 0; + if( kj ) NormQth(pKey); + len = strlen(pKey); + m_FindCnt = 0; + mp = m_bp; + char bf[256]; + for( i = 0; i < m_Cnt; i++, mp++ ){ + if( isfind(mp->Code) ){ + if( kj ){ + if( strstr(mp->QTH, pKey) != NULL ){ + m_fp[m_FindCnt] = mp; + m_FindCnt++; + goto _nx; + } + } + strcpy(bf, mp->Key); + for( p = bf; *p; ){ + p = StrDlm(t, p, ','); + if( (!strncmp(t, pKey, len)) || (m_sinc && (strstr(t, pKey)!=NULL)) ){ + m_fp[m_FindCnt] = mp; + m_FindCnt++; + break; + } + } +_nx:; + } + } +} + +/*#$% +====================================================== + データの検索を行う +------------------------------------------------------ +------------------------------------------------------ +------------------------------------------------------ +====================================================== +*/ +void CMMCG::FindNumb(LPSTR pKey) +{ + MMCG *mp; + int i; + int len; + + m_FindCnt = 0; + len = strlen(pKey); + mp = m_bp; + for( i = 0; i < m_Cnt; i++, mp++ ){ + if( (!strncmp(mp->Code, pKey, len)) || (m_sinc && (strstr(mp->Code, pKey)!=NULL)) ){ + m_fp[m_FindCnt] = mp; + m_FindCnt++; + } + } +} + +/*#$% +====================================================== + データの検索を行う +------------------------------------------------------ +------------------------------------------------------ +------------------------------------------------------ +====================================================== +*/ +void CMMCG::Find(LPSTR p) +{ + if( *p ){ + if( isdigit(*(LPUSTR)p) ){ + FindNumb(p); + } + else { + jstrupr(p); + if( chkspl(p) ) FindQTH(adjspl(p)); + } + } + else { + FindAll(); + } +} + +#if 0 +/*#$% +====================================================== + 定義領域を確保する +------------------------------------------------------ +------------------------------------------------------ +------------------------------------------------------ +====================================================== +*/ +int allocdef(int blk) +{ + if( cseg == 0 ){ + if( (cseg=__malloc(blk))!=0 ){ /* メモリの確保 */ + return(NOERR); + } + return(ERR); + } + return(NOERR); +} + +/*#$% +====================================================== + 定義領域を開放する +------------------------------------------------------ +------------------------------------------------------ +------------------------------------------------------ +====================================================== +*/ +void freedef(void) +{ + if( cseg ){ + __free(cseg); + cseg = 0; + } +} + +#define XW 60 +#define YW 16 +/*#$% +====================================================== + 検索データのメニュー表示をオープンする +------------------------------------------------------ +------------------------------------------------------ +------------------------------------------------------ +====================================================== +*/ +VEWP *opencc(void) +{ + cc.xw = XW-1; + cc.yw = YW-1; + cc.x = (crt.hmax-cc.xw+2)/2; + cc.y = (crt.vmax-cc.yw+2)/2; + cc.yt = cc.y; + cc.ye = cc.y + cc.yw; + cc.tb = cc.cy = 0; + cc.xe = cc.x + cc.xw - 1; + if( (cc.vp=openvew(cc.x, cc.y, cc.x+cc.xw, cc.ye, _menuwcol))!=NULL ){ + _dprintf( cc.x, cc.yt, " 検索>" ); + cc.x++; + cc.y++; +/* _dprintf( cc.x, cc.ye, "中止, 決定, <↓><↑>選択, クリア, エリア/ALL" );*/ + _dprintf( cc.x, cc.ye, "中止,決定,クリア,検索方法,エリア/ALL" ); + } + return(cc.vp); +} + +/*#$% +====================================================== + 検索データのメニュー表示をクローズする +------------------------------------------------------ +------------------------------------------------------ +------------------------------------------------------ +====================================================== +*/ +void closecc(void) +{ + if( cc.vp ){ + closevew(cc.vp); + cc.vp = NULL; + } +} + +/*#$% +====================================================== + 1行の表示を行う +------------------------------------------------------ + y : 表示位置 + tp: テーブル番号 +------------------------------------------------------ +------------------------------------------------------ +====================================================== +*/ +static void near dspone(int y, int tp) +{ + CD cd; + int l; + uchar bf[60]; + +/*0123456789012345678901234567890123456789012345678901234567*/ +/*250119__ 大阪府__ 大阪市阿倍野区______ ABENO______________*/ +/*12345678 12345678 12345678901234567890 1234567890123456789*/ + + _fills(cc.x, y, cc.xe, y); + if( tp < cc.fn ){ + getdat(cc.ctbl[tp], &cd); + l = strlen(cd.code); + _dprintf(cc.x, y, "%-.8s", cd.code ); + _dprintf(cc.x+9, y, "%-.8s", getprf(cd.code)); + if( l == 6 ){ + if( isalpha(lastc(cd.code)) ){ /* 町村 */ + GetGun(bf, cd.code); + } + else { /* 制令 */ + bf[0] = 0; + } + strcat(bf, cd.qth); + _dprintf(cc.x+18, y, "%-.20s", bf ); + } + else { + _dprintf(cc.x+18, y, "%-.20s", cd.qth ); + } + _dprintf(cc.x+39, y, "%-.19s", cd.key ); + } +} + +/*#$% +====================================================== + 検索データの表示をする +------------------------------------------------------ +------------------------------------------------------ +------------------------------------------------------ +====================================================== +*/ +static void near dspcc(void) +{ + int y, cp; + CD cd; + + for( cp = cc.tb, y = cc.y; y < cc.ye; y++, cp++ ){ + dspone(y, cp); + } +} + +/*#$% +====================================================== + カーソルの表示 +------------------------------------------------------ + sw : 0-OFF, 1-ON +------------------------------------------------------ +------------------------------------------------------ +====================================================== +*/ +static void near ecursor(int sw) +{ + int at; + + at = sw ? _menuccol : CRT_ATTR_NORMAL; + _afill(cc.x, cc.y + cc.cy, cc.xe, cc.y + cc.cy, at ); +} + +/*#$% +====================================================== + カーソルのアップ +------------------------------------------------------ +------------------------------------------------------ +------------------------------------------------------ +====================================================== +*/ +static void near cup(void) +{ + if( cc.cy ){ + cc.cy--; + } + else if( cc.tb ){ + cc.tb--; + _scrdwn(cc.x, cc.y, cc.xe, cc.ye-1); + dspone(cc.y, cc.tb); + } +} + +/*#$% +====================================================== + カーソルのダウン +------------------------------------------------------ +------------------------------------------------------ +------------------------------------------------------ +====================================================== +*/ +static void near cdown(void) +{ + if( (cc.tb + cc.cy) < (cc.fn - 1) ){ + if( cc.cy < (cc.yw - 2) ){ + cc.cy++; + } + else { + cc.tb++; + _scrup(cc.x, cc.y, cc.xe, cc.ye-1); + dspone(cc.ye-1, cc.tb+cc.cy); + } + } +} + +/*#$% +====================================================== + 指定位置へのSEEK +------------------------------------------------------ +------------------------------------------------------ +------------------------------------------------------ +====================================================== +*/ +static void near cdseek(int tp) +{ + if( tp >= cc.fn ) tp = cc.fn - 1; + if( tp < 0 ) tp = 0; + cc.tb = tp; + cc.cy = 0; + dspcc(); +} + +/*#$% +====================================================== + ページアップ +------------------------------------------------------ +------------------------------------------------------ +------------------------------------------------------ +====================================================== +*/ +static void near pup(void) +{ + CD cd; + int tp, m; + + tp = cc.tb + cc.cy; + getdat(cc.ctbl[tp], &cd); + m = atoin(cd.code, 2); + for( tp--; tp >= 0; tp-- ){ + getdat(cc.ctbl[tp], &cd); + if( m != atoin(cd.code, 2) ){ + cdseek(tp); + return; + } + } + cdseek(0); +} + +/*#$% +====================================================== + ページダウン +------------------------------------------------------ +------------------------------------------------------ +------------------------------------------------------ +====================================================== +*/ +static void near pdown(void) +{ + CD cd; + int tp, m; + + tp = cc.tb + cc.cy; + getdat(cc.ctbl[tp], &cd); + m = atoin(cd.code, 2); + for( tp++; tp < cc.fn; tp++ ){ + getdat(cc.ctbl[tp], &cd); + if( m != atoin(cd.code, 2) ){ + cdseek(tp); + return; + } + } + cdseek(32767); +} + +/*#$% +====================================================== + バッファ内容の表示 +------------------------------------------------------ +------------------------------------------------------ +------------------------------------------------------ +====================================================== +*/ +static void near dspbf(void) +{ + _dprintf(cc.x+5, cc.yt, "%-40s", kbf ); + _dprintf(cc.xe - 15, cc.yt, sinc ? "含み":"先頭"); + _dprintf(cc.xe - 10, cc.yt, (m_mask != -1) ? "%uエリア" : "ALL ", m_mask ); + _dprintf(cc.xe-4, cc.yt, "%4u", cc.fn ); +} + +/*#$% +====================================================== + MMCGの処理を行う +------------------------------------------------------ +------------------------------------------------------ +------------------------------------------------------ +====================================================== +*/ +void mmcg(void) +{ + int c; + int xx; + + loaddat(); + if( nosel == 1 ){ + strcpy(kbf, _dspopt(optnmb, &cc.sd)); + findnosel(jstrupr(kbf)); + setdat(); + return; + } + if( opencc() == NULL ) return; + find1st(); + if( nosel == 2 ){ + if( cc.fn == 1 ) setdat(); + closecc(); + return; + } + dspcc(); + xx = strlen(kbf); + _cursor(ON); + while(1){ + dspbf(); + _locate(cc.x+5 + xx, cc.yt); + ecursor(ON); + c = _bgetch(); + ecursor(OFF); + switch(c){ + case K_RU: + pdown(); + break; + case K_RD: + pup(); + break; + case K_UP: + cup(); + break; + case K_DOWN: + cdown(); + break; + case ESC: + goto _ex; + case K_CR: + setdat(); + goto _ex; + case K_BS: + if( xx ){ + xx--; + if( xx && (_ischrtyp(kbf, xx)==2) ) xx--; + kbf[xx] = 0; + find(kbf); + dspcc(); + } + break; + case ' ': + kbf[0] = 0; + xx = 0; + findall(); + dspcc(); + break; + case K_F1: + sinc = sinc ? 0 : 1; + find(kbf); + dspcc(); + break; + case K_F2: + case K_HOME: + if( mask == -1 ){ + setmask(); + } + else { + mask = -1; + } + find(kbf); + dspcc(); + break; + default: + if( (c > 0x0020) && (c <= 0x00ff) ){ + if( xx < 40 ){ + kbf[xx] = c; + xx++; + kbf[xx] = 0; + if( _ischrtyp(kbf, xx-1) != 1 ){ + finds(kbf); + } + dspcc(); + } + } + break; + } + } +_ex:; + closecc(); +} + +/*#$% +====================================================== + データの検索を行う(すべて) +------------------------------------------------------ +------------------------------------------------------ +------------------------------------------------------ +====================================================== +*/ +void findall(void) +{ + CD cd; + int cp, np; + + cc.tb = cc.cy = cc.fn = 0; + for( cp = 0; cp < cc.cwp; cp = np){ + np = getdat(cp, &cd); + if( isfind(cd.code) ){ + cc.ctbl[cc.fn] = cp; + cc.fn++; + if( cc.fn >= CTMAX ) break; + } + } +} + +/*#$% +====================================================== + 同一データが存在するか調べる +------------------------------------------------------ +------------------------------------------------------ +------------------------------------------------------ +====================================================== +*/ +int isEnt(int n) +{ + int i; + + for( i = 0; i < cc.fn; i++ ){ + if( cc.ctbl[i] == n ){ + return(ON); + } + } + return(OFF); +} + +/*#$% +====================================================== + データの検索を行う +------------------------------------------------------ +------------------------------------------------------ +------------------------------------------------------ +====================================================== +*/ +void findqth(uchar *key) +{ + CD cd; + int cp, np; + int len, kj; + uchar *t, *p; + + if( (kj = iskanji(*key))!=0 ) NormQth(key); + len = strlen(key); + cc.tb = cc.cy = cc.fn = 0; + for( cp = 0; cp < cc.cwp; cp = np){ + np = getdat(cp, &cd); + if( isfind(cd.code) ){ + if( kj ){ + if( jstrstr(cd.qth, key) != NULL ){ + cc.ctbl[cc.fn] = cp; + cc.fn++; + goto _nx; + } + } + for( p = cd.key; *p; ){ + p = strdm(&t, p); + if( (!strncmp(t, key, len)) || (sinc && (strstr(t, key)!=NULL)) ){ + cc.ctbl[cc.fn] = cp; + cc.fn++; + break; + } + } +_nx:; + if( cc.fn >= CTMAX ) break; + } + if( _bkbhit() ) break; + } +} + +/*#$% +====================================================== + データの検索を行う +------------------------------------------------------ +------------------------------------------------------ +------------------------------------------------------ +====================================================== +*/ +void findqths(uchar *key) +{ + CD cd; + int cp; + int len, fn, nn, f, kj; + uchar *t, *p; + + if( (kj = iskanji(*key))!=0 ){ + if( NormQth(key) ){ + findqth(key); + return; + } + } + len = strlen(key); + fn = cc.fn; + cc.tb = cc.cy = cc.fn = 0; + f = OFF; + if( lastc(key) == '\\' ){ + f = ON; + *lastp(key) = 0; + } + for( nn = 0; nn < fn; nn++){ + cp = cc.ctbl[nn]; + getdat(cp, &cd); + if( kj ){ + if( jstrstr(cd.qth, key) != NULL ){ + cc.ctbl[cc.fn] = cp; + cc.fn++; + goto _nx; + } + } + for( p = cd.key; *p; ){ + p = strdm(&t, p); + if( f ){ + if( (!strcmp(t, key)) || (sinc && (LastMatch(t,key))) ){ + cc.ctbl[cc.fn] = cp; + cc.fn++; + break; + } + } + else { + if( (!strncmp(t, key, len)) || (sinc && (strstr(t, key)!=NULL)) ){ + cc.ctbl[cc.fn] = cp; + cc.fn++; + break; + } + } + } +_nx:; + if( cc.fn >= CTMAX ) break; + } +} + +/*#$% +====================================================== + データの検索を行う +------------------------------------------------------ +------------------------------------------------------ +------------------------------------------------------ +====================================================== +*/ +void findnmb(uchar *key) +{ + CD cd; + int cp, np; + int len; + + cc.tb = cc.cy = cc.fn = 0; + len = strlen(key); + for( cp = 0; cp < cc.cwp; cp = np){ + np = getdat(cp, &cd); + if( (!strncmp(cd.code, key, len)) || (sinc && (strstr(cd.code, key)!=NULL)) ){ + cc.ctbl[cc.fn] = cp; + cc.fn++; + if( cc.fn >= CTMAX ) break; + } + } +} + +/*#$% +====================================================== + データの検索を行う +------------------------------------------------------ +------------------------------------------------------ +------------------------------------------------------ +====================================================== +*/ +void findnmbs(uchar *key) +{ + CD cd; + int cp; + int len, fn, nn, f; + + fn = cc.fn; + cc.tb = cc.cy = cc.fn = 0; + f = OFF; + if( lastc(key) == '\\' ){ + f = ON; + *lastp(key) = 0; + } + len = strlen(key); + for( nn = 0; nn < fn; nn++){ + cp = cc.ctbl[nn]; + getdat(cp, &cd); + if( f ){ + if( (!strcmp(cd.code, key)) || (sinc && LastMatch(cd.code, key)) ){ + cc.ctbl[cc.fn] = cp; + cc.fn++; + } + } + else { + if( (!strncmp(cd.code, key, len)) || (sinc && (strstr(cd.code, key)!=NULL)) ){ + cc.ctbl[cc.fn] = cp; + cc.fn++; + } + } + } + if( f ) strcat(key, "\\"); +} + +/*#$% +====================================================== + データの検索を行う +------------------------------------------------------ +------------------------------------------------------ +------------------------------------------------------ +====================================================== +*/ +void findnosel(uchar *key) +{ + CD cd; + int cp, np; + + cc.tb = cc.cy = cc.fn = 0; + for( cp = 0; cp < cc.cwp; cp = np){ + np = getdat(cp, &cd); + if( !strcmp(cd.code, key) ){ + cc.ctbl[cc.fn] = cp; + cc.fn++; + break; + } + } +} + +/*#$% +====================================================== + データの検索を行う +------------------------------------------------------ +------------------------------------------------------ +------------------------------------------------------ +====================================================== +*/ +void find(uchar *p) +{ + dspbf(); + if( *p ){ + if( isdigit(*p) ){ + findnmb(p); + } + else { + jstrupr(p); + if( chkspl(p) ) findqth(adjspl(p)); + } + } + else { + findall(); + } +} + +/*#$% +====================================================== + データの検索を行う +------------------------------------------------------ +------------------------------------------------------ +------------------------------------------------------ +====================================================== +*/ +void finds(uchar *p) +{ + dspbf(); + if( *p ){ + if( isdigit(*p) ){ + findnmbs(p); + if( !cc.fn ) findnmb(p); + } + else { + jstrupr(p); + if( chkspl(p) ) findqths(adjspl(p)); + } + } + else { + findall(); + } +} + +/*#$% +====================================================== + 最初の検索を行う +------------------------------------------------------ +------------------------------------------------------ +------------------------------------------------------ +====================================================== +*/ +void find1st(void) +{ + uchar *p; + uchar far *s; + + setmask(); + kbf[0] = 0; + if( setmac ){ + if( dtname[0] && (ishex(dtname)==NOERR) ){ + s = (uchar far *)htoln(dtname, -1); + for( p = kbf; *s; s++, p++ ){ + *p = *s; + } + *p = 0; + } + } + else { + p = _dspopt(optnmb, &cc.sd); + if( *p && isdigit(*p) ){ + strcpy(kbf, p); + } + else if( cc.sd.qth[0] ){ + strcpy(kbf, cc.sd.qth); + } + } + find(jstrupr(kbf)); +} + +/*#$% +====================================================== + データをセットする +------------------------------------------------------ +------------------------------------------------------ +------------------------------------------------------ +====================================================== +*/ +void setdat(void) +{ + CD cd; + uchar far *t; + uchar *p; + + if( cc.fn ){ + if( !dtname[0] ) return; + getdat(cc.ctbl[cc.tb+cc.cy], &cd); + if( setmac ){ + if( ishex(dtname)!=NOERR ) return; + t = (uchar far *)htoln(dtname,-1); + if( ocpy ){ + for( p = cd.code; *p; p++, t++ ){ + *t = *p; + } + *t = 0; + } + if( qcpy ){ + for( p = getqth(&cd); *p; p++, t++ ){ + *t = *p; + } + *t = 0; + } + } + else { + if( ocpy ) strcpy(_ptropt(optnmb, &cc.sd), cd.code); + if( qcpy ) strcpy(cc.sd.qth, getqth(&cd)); + savedat(); + } + } +} + +/*#$% +================================================================ + 1行のアスキーセーブの処理を行う +---------------------------------------------------------------- + fp : ファイルポインタ + sp : データのポインタ +---------------------------------------------------------------- + ERR +---------------------------------------------------------------- +================================================================ +*/ +void _sputdat(uchar *bf, SD *sp) +{ + sinit(bf); + sputf("\042%s\042,\042%s\042,\042%s\042,\042%s\042,\042%s\042,\042%s\042,", + _strydate(sp->year, sp->date), _strtimes(sp->btime), sp->call, sp->ur, sp->my, _strband(sp->band, sp->fq)); + sputf("\042%s\042,\042%s\042,\042%s\042,\042%s\042,\042%s\042,\042%s\042,", + _strmode(sp->mode), sp->pow, sp->name, sp->qth, sp->rem, sp->qsl ); + sputf("\042%s\042,\042%.1s\042,\042%.1s\042,\042%.1s\042,\042%u\042,", _strtime(sp->etime), &sp->send, &sp->recv, &sp->cq, sp->env); + sputf("\042%s\042,\042%s\042,", sp->opt1, sp->opt2 ); + sputf("\042%s\042,", _dspopt(2, sp)); + sputf("\042%s\042", _dspopt(3, sp)); +} + +/*#$% +================================================================ + 1行のアスキーセーブの処理を行う +---------------------------------------------------------------- + fp : ファイルポインタ + sp : データのポインタ +---------------------------------------------------------------- + ERR +---------------------------------------------------------------- +================================================================ +*/ +int _fputdat(FILE *fp, SD *sp) +{ + _sputdat(hbf, sp); + fputs(hbf, fp); + fputs("\r\n", fp); + return(ferror(fp)); +} + +/*#$% +================================================================ + アスキーデータを登録する +---------------------------------------------------------------- + p : バッファのポインタ +---------------------------------------------------------------- + ERR +---------------------------------------------------------------- +================================================================ +*/ +int _aputdat(uchar *p, SD *sp) +{ + uchar *t; + int y, m, d; + + _fillmem(sp, sizeof(SD), 0); + p = strdm(&t, p); /* DATE */ + if( sscanf(t, "%u.%u.%u", &y, &m, &d )!=3 ) return(ERR); + sp->year = y; + sp->date = (m * 100) + d; + p = strdm(&t, p); /* BGN */ + if( sscanf(t, "%u.%u", &d, &y) != 2 ){ + d = atoin(t, -1); + y = 0; + } + m = d / 100; + d = d % 100; + y /= 2; + sp->btime = (((m * 60) + d) * 30) + y; + p = strdm(&t, p); /* CALL */ + strcpy(sp->call, t); + p = strdm(&t, p); /* UR */ + strcpy(sp->ur, t); + p = strdm(&t, p); /* MY */ + strcpy(sp->my, t); + p = strdm(&t, p); /* BAND */ + sp->band = _bandno(&sp->fq, t); + p = strdm(&t, p); /* MODE */ + sp->mode = _modeno(t); + p = strdm(&t, p); /* POW */ + strcpy(sp->pow, t); + p = strdm(&t, p); /* NAME */ + strcpy(sp->name, t); + p = strdm(&t, p); /* QTH */ + strcpy(sp->qth, t); + p = strdm(&t, p); /* REM */ + strcpy(sp->rem, t); + p = strdm(&t, p); /* QSL */ + strcpy(sp->qsl, t); + p = strdm(&t, p); /* ETIME*/ + d = atoin(t, -1); + m = d / 100; + d = d % 100; + sp->etime = ((m * 60) + d) * 30; + p = strdm(&t, p); /* S */ + sp->send = *t; + p = strdm(&t, p); /* R */ + sp->recv = *t; + p = strdm(&t, p); /* M */ + sp->cq = *t; + p = strdm(&t, p); /* ENV */ + sp->env = atoin(t, -1); + p = strdm(&t, p); /* OPT1 */ + strcpy(sp->opt1, t); + p = strdm(&t, p); /* OPT2 */ + strcpy(sp->opt2, t); + p = strdm(&t, p); /* USR1 */ + if( *t ) strcpy(_ptropt(2,sp), t); + p = strdm(&t, p); /* USR2 */ + if( *t ) strcpy(_ptropt(3,sp), t); + return(NOERR); +} + +/*#$% +================================================================ + 引渡データを読み込む +---------------------------------------------------------------- +---------------------------------------------------------------- +---------------------------------------------------------------- +================================================================ +*/ +int loaddat(void) +{ + int r; + FILE *fp; + + r = ERR; + _fillmem(&cc.sd, sizeof(SD), 0); + if( !dtname[0] ) return(NOERR); + if( setmac ) return(NOERR); + if( (fp = fopen(dtname, "rt"))!=NULL ){ + if( (fgets(hbf, 256, fp))!=NULL ){ + cliplf(hbf); + _aputdat(hbf, &cc.sd); + r = NOERR; + } + fclose(fp); + } + return(r); +} + +/*#$% +================================================================ + 指定のデータを書き込む +---------------------------------------------------------------- +---------------------------------------------------------------- +---------------------------------------------------------------- +================================================================ +*/ +void savedat(void) +{ + FILE *fp; + + if( (fp = fopen(dtname, "wb"))!=NULL ){ + _fputdat(fp, &cc.sd); + fclose(fp); + } +} +#endif + diff --git a/Mmcg.h b/Mmcg.h new file mode 100644 index 0000000..4c62bf9 --- /dev/null +++ b/Mmcg.h @@ -0,0 +1,81 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +#ifndef MmcgH +#define MmcgH +#include "LogFile.h" + +#ifndef LPCUSTR +typedef const unsigned char * LPCUSTR; +typedef unsigned char * LPUSTR; +#endif + +typedef struct { + LPSTR Code; + LPSTR QTH; + LPSTR Key; +}MMCG; + +class CMMCG +{ +private: + int m_Max; // 現在確保しているスロット数 + int m_Cnt; // 現在記憶しているスロット数 + MMCG *m_bp; // MMCGの配列 + + + char wbf[512]; + +public: + int m_mask; + int m_sinc; + int m_FindCnt; + MMCG **m_fp; + + AnsiString m_QTH; + char m_Call[MLCALL+1]; +private: + void Free(void); + void Alloc(int n); + LPSTR adjspl(LPSTR p); + int chkspl(LPCSTR p); + int LastMatch(LPSTR t, LPSTR s); + int NormQth(LPSTR p); + int isfind(LPCSTR p); + int _ischrtyp(char *p, int x); + LPCSTR getprf(LPCSTR pCode); + void GetGun(LPSTR t, LPCSTR pCode); + int isEnt(MMCG *mp); + +public: + CMMCG(); + ~CMMCG(); + + void LoadDef(LPCSTR pFileName); + void FindAll(void); + void FindQTH(LPSTR pKey); + void FindNumb(LPSTR pKey); + void Find(LPSTR p); + void SetMask(void); + + LPCSTR GetQTH(MMCG *mp); +}; + +extern CMMCG mmcg; +#endif diff --git a/MmcgDlg.cpp b/MmcgDlg.cpp new file mode 100644 index 0000000..1df884b --- /dev/null +++ b/MmcgDlg.cpp @@ -0,0 +1,245 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "MmcgDlg.h" +//--------------------------------------------------------------------- +#pragma resource "*.dfm" +//TMmcgDlgBox *MmcgDlgBox; +//--------------------------------------------------------------------- +__fastcall TMmcgDlgBox::TMmcgDlgBox(TComponent* AOwner) + : TForm(AOwner) +{ + FormStyle = ((TForm *)AOwner)->FormStyle; + Font->Name = ((TForm *)AOwner)->Font->Name; + Font->Charset = ((TForm *)AOwner)->Font->Charset; + + if( MsgEng ){ + SBInc->Caption = "String"; + SBMask->Caption = "Area"; + CancelBtn->Caption = "Cancel"; + } + + m_DisEvent = 0; +} +//--------------------------------------------------------------------- +void __fastcall TMmcgDlgBox::UpdateCaption(void) +{ + char bf[256]; + + if( MsgEng ){ + if( mmcg.m_Call[0] ){ + sprintf(bf, "MMCG [%s] Find: %d", mmcg.m_Call, mmcg.m_FindCnt); + } + else { + sprintf(bf, "MMCG Find: %d", mmcg.m_FindCnt); + } + } + else { + if( mmcg.m_Call[0] ){ + sprintf(bf, "MMCG [%s] 候補 : %d", mmcg.m_Call, mmcg.m_FindCnt); + } + else { + sprintf(bf, "MMCG 候補: %d", mmcg.m_FindCnt); + } + } + Caption = bf; +} + +//--------------------------------------------------------------------- +int __fastcall TMmcgDlgBox::Execute(AnsiString &call, AnsiString &qth, AnsiString &op) +{ + StrCopy(mmcg.m_Call, call.c_str(), MLCALL); + mmcg.SetMask(); + SBMask->Down = TRUE; + if( mmcg.m_mask == -1 ) SBMask->Enabled = FALSE; + + char bf[256]; + + bf[0] = 0; + if( isdigit(*op.c_str()) ){ + strcpy(bf, op.c_str()); + } + else if( !qth.IsEmpty() ){ + strcpy(bf, qth.c_str()); + } + m_DisEvent++; + EditYomi->Text = bf; + mmcg.Find(bf); + UpdateCaption(); + m_DisEvent--; + Grid->RowCount = mmcg.m_FindCnt ? mmcg.m_FindCnt + 1 : 2; + if( ShowModal() == IDOK ){ + int n = Grid->Row - 1; + if( (n >= 0)&&(n < mmcg.m_FindCnt) ){ + qth = mmcg.GetQTH(mmcg.m_fp[n]); + op = mmcg.m_fp[n]->Code; + return TRUE; + } + } + return FALSE; +} +//--------------------------------------------------------------------------- +void __fastcall TMmcgDlgBox::GridDrawCell(TObject *Sender, int Col, + int Row, TRect &Rect, TGridDrawState State) +{ + char bf[256]; + MMCG *mp; + + Grid->Canvas->FillRect(Rect); + int X = Rect.Left + 4; + int Y = Rect.Top + 2; + + if( Row ){ + Row--; + bf[0] = 0; + if( Row < mmcg.m_FindCnt ){ + mp = mmcg.m_fp[Row]; + } + else { + mp = NULL; + } + switch(Col){ + case 0: // Code + if( mp != NULL ) strcpy(bf, mp->Code); + break; + case 1: // QTH + if( mp != NULL ) strcpy(bf, mmcg.GetQTH(mp)); + break; + case 2: // Key + if( mp != NULL ) strcpy(bf, mp->Key); + break; + } + Grid->Canvas->TextOut(X, Y, bf); + } + else { // タイトル + LPCSTR _tt[]={ + "Code","QTH","Key", + }; + Grid->Canvas->TextOut(X, Y, _tt[Col]); + } + +} +//--------------------------------------------------------------------------- +void __fastcall TMmcgDlgBox::EditYomiChange(TObject *Sender) +{ + if( m_DisEvent ) return; + + char bf[256]; + + strcpy(bf, AnsiString(EditYomi->Text).c_str()); //ja7ude 0428 + mmcg.Find(bf); + UpdateCaption(); + Grid->RowCount = mmcg.m_FindCnt ? mmcg.m_FindCnt + 1 : 2; + Grid->Invalidate(); +} +//--------------------------------------------------------------------------- +void __fastcall TMmcgDlgBox::EditYomiKeyPress(TObject *Sender, char &Key) +{ + if( Key == 0x20 ){ + EditYomi->Text = ""; + Key = 0; + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmcgDlgBox::EditYomiKeyDown(TObject *Sender, WORD &Key, + TShiftState Shift) +{ + switch(Key){ + case VK_UP: + if( Grid->Row >= 2 ) Grid->Row--; + Key = 0; + break; + case VK_DOWN: + if( Grid->Row < Grid->RowCount - 1 ) Grid->Row++; + Key = 0; + break; + case VK_HOME: + Grid->Row = 1; + Key = 0; + break; + case VK_END: + Grid->Row = Grid->RowCount - 1; + Key = 0; + break; + case VK_F1: + SBInc->Down = SBInc->Down ? 0 : 1; + SBIncClick(NULL); + Key = 0; + break; + case VK_F2: + SBMask->Down = SBMask->Down ? 0 : 1; + SBMaskClick(NULL); + Key = 0; + break; + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmcgDlgBox::EditYomiKeyUp(TObject *Sender, WORD &Key, + TShiftState Shift) +{ + switch(Key){ + case VK_UP: + Key = 0; + break; + case VK_DOWN: + Key = 0; + break; + case VK_HOME: + Key = 0; + break; + case VK_END: + Key = 0; + break; + case VK_F1: + Key = 0; + break; + case VK_F2: + Key = 0; + break; + } +} +//--------------------------------------------------------------------------- +void __fastcall TMmcgDlgBox::SBMaskClick(TObject *Sender) +{ + if( SBMask->Down ){ + mmcg.SetMask(); + } + else { + mmcg.m_mask = -1; + } + EditYomiChange(NULL); +} +//--------------------------------------------------------------------------- +void __fastcall TMmcgDlgBox::SBIncClick(TObject *Sender) +{ + if( SBInc->Down ){ + mmcg.m_sinc = 1; + } + else { + mmcg.m_sinc = 0; + } + EditYomiChange(NULL); +} +//--------------------------------------------------------------------------- + + diff --git a/MmcgDlg.dfm b/MmcgDlg.dfm new file mode 100644 index 0000000..ef39597 Binary files /dev/null and b/MmcgDlg.dfm differ diff --git a/MmcgDlg.h b/MmcgDlg.h new file mode 100644 index 0000000..5c84561 --- /dev/null +++ b/MmcgDlg.h @@ -0,0 +1,71 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//---------------------------------------------------------------------------- +#ifndef MmcgDlgH +#define MmcgDlgH +//---------------------------------------------------------------------------- +//ja7ude 0428 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//---------------------------------------------------------------------------- +#include "Mmcg.h" +//---------------------------------------------------------------------------- +class TMmcgDlgBox : public TForm +{ +__published: + TButton *OKBtn; + TButton *CancelBtn; + TStringGrid *Grid; + TEdit *EditYomi; + TSpeedButton *SBMask; + TSpeedButton *SBInc;void __fastcall EditYomiChange(TObject *Sender); + + + + + void __fastcall EditYomiKeyDown(TObject *Sender, WORD &Key, TShiftState Shift); + void __fastcall EditYomiKeyUp(TObject *Sender, WORD &Key, TShiftState Shift); + void __fastcall SBMaskClick(TObject *Sender); + void __fastcall SBIncClick(TObject *Sender); + void __fastcall EditYomiKeyPress(TObject *Sender, char &Key); + void __fastcall GridDrawCell(TObject *Sender, int Col, int Row, + TRect &Rect, TGridDrawState State); +private: + int m_DisEvent; + + void __fastcall UpdateCaption(void); +public: + virtual __fastcall TMmcgDlgBox(TComponent* AOwner); + + int __fastcall Execute(AnsiString &call, AnsiString &qth, AnsiString &op); +}; +//---------------------------------------------------------------------------- +//extern TMmcgDlgBox *MmcgDlgBox; +//---------------------------------------------------------------------------- +#endif diff --git a/Mmsstv English.ini b/Mmsstv English.ini new file mode 100644 index 0000000..371c3d8 --- /dev/null +++ b/Mmsstv English.ini @@ -0,0 +1,1118 @@ +[SoundCard] +SampFreq=1.102500e+04 +TxSampOffset=0.000000e+00 + +[ComboList] +LogFreq=1.8,3.5,3.8,7,7.033,10,14,14.230,18,21,21.340,24,28,28.680,50,144,430,1200,2400 +LogRST=595,575,555,594,574,554,444,333 + +[Version] +INI=2 +LinearCalibration=2 +PLL=2 + +[Window] +Priority=0 +WindowState=0 +MemoryWindow=0 +UseB24=0 +RxViewInd=0 +RxView=0 +RxViewTop=0 +RxViewLeft=0 +RxViewWidth=320 +RxViewHeight=256 +SyncView=0 +SyncViewTop=0 +SyncViewLeft=0 +SyncViewWidth=326 +SyncViewHeight=259 +HistView=0 +HistViewTB=1 +HistViewTop=0 +HistViewLeft=0 +HistViewWidth=516 +HistViewHeight=70 +HistViewSize=2 +CtrBtn=0 +CtrBtnTop=0 +CtrBtnLeft=0 +CtrBtnWidth=128 +CtrBtnHeight=198 +StockViewTop=592 +StockViewLeft=556 +StockViewWidth=470 +StockViewHeight=156 +WaterViewTop=0 +WaterViewLeft=424 +WaterViewWidth=367 +WaterViewHeight=138 +LogViewTop=162 +LogViewLeft=424 +LogViewWidth=367 +LogViewHeight=164 +DivMode=0 +DivSW=7 +PreViewTop=0 +PreViewLeft=0 +PreViewWidth=160 +PreViewHeight=128 +StayOnTop=0 +MainPage=3 +StockPage=1 +StockPicPosition=0 +StockTempPos1=0 +StockTempPos2=0 +StockTempPos3=0 +StockTempPos4=0 +HQResizing=0 +UseTemplate=1 +ShowSuperimpos=0 +DraftSuperimpos=1 +PicClipType=0 +PicClipRatio=1 +PicClipMode=0 +PicClipView=1 +PicClipColor=0 +Way240=1 +AutoMargin=1 +TxClipType=0 +HistMax=32 +AutoRxClear=1 +AutoRxSave=1 +AutoCopy=1 +JPEG=80 +TempSuperimpos=1 +DummyMacro=1 +ShowTransPoint=0 +AutoTransPoint=1 +HistDDSize=2 +ShowSizeRX=0 +ShowSizeHist=0 +ShowSizeTX=0 +ShowSizeTemp=0 +ShowSizeStock=0 +StretchTXimage=0 +SwitchRX=0 + +[FileView] +ShowSize=0 +KeepA=0 + +[FileView1] +Flag=0 +Mode=1 +Size=2 +Top=0 +Left=0 +Width=516 +Height=70 +MaxPage=1 +CurPage=0 +FMPage1=-2147483648 +Folder= +Name1= + +[FileView2] +Flag=0 +Mode=1 +Size=2 +Top=0 +Left=0 +Width=516 +Height=70 +MaxPage=1 +CurPage=0 +FMPage1=-2147483648 +Folder= +Name1= + +[FileView3] +Flag=0 +Mode=1 +Size=2 +Top=0 +Left=0 +Width=516 +Height=70 +MaxPage=1 +CurPage=0 +FMPage1=-2147483648 +Folder= +Name1= + +[FileView4] +Flag=0 +Mode=1 +Size=2 +Top=0 +Left=0 +Width=516 +Height=70 +MaxPage=1 +CurPage=0 +FMPage1=-2147483648 +Folder= +Name1= + +[FileView5] +Flag=0 +Mode=1 +Size=2 +Top=0 +Left=0 +Width=516 +Height=70 +MaxPage=1 +CurPage=0 +FMPage1=-2147483648 +Folder= +Name1= + +[FileView6] +Flag=0 +Mode=1 +Size=2 +Top=0 +Left=0 +Width=516 +Height=70 +MaxPage=1 +CurPage=0 +FMPage1=-2147483648 +Folder= +Name1= + +[FileView7] +Flag=0 +Mode=1 +Size=2 +Top=0 +Left=0 +Width=516 +Height=70 +MaxPage=1 +CurPage=0 +FMPage1=-2147483648 +Folder= +Name1= + +[FileView8] +Flag=0 +Mode=1 +Size=2 +Top=0 +Left=0 +Width=516 +Height=70 +MaxPage=1 +CurPage=0 +FMPage1=-2147483648 +Folder= +Name1= + +[WindowFont] +Name=Arial +Charset=0 +Style=0 +Adjust=0 + +[Help] +UseNotePad=0 + +[ImageAdj] +Sharp2D=0 + +[Define] +FFTType=2 +FFTGain=5 +FFTResp=0 +FFTStgv=1 +FFTWidth=1 +FFTAGC=1 +FFTPriority=0 +WaterSW=1 +LevelType=0 +UseRxBuff=1 +SoundFifoRX=12 +SoundFifoTX=8 +SoundPriority=1 +SoundDevice=-1 +SoundStereo=0 +StereoTX=0 +SoundMMW= +PTT=NONE +PTTLock=1 +RTSonRX=0 +TXLoopBack=0 +ColorOffset=0 +ColorWhite=7.812500e-03 +ColorBlack=7.812500e-03 +ColorCalibration=0 +FixedTxMode=1 +SSTVMode=3 +RXFSKID=0 +TXFSKID=0 +CWID=0 +CWIDWPM=28 +CWIDFreq=1000 +CWIDText=DE %m +MMVID= +TuneFreq=1750 +TuneTime=-1 +TuneSat=0 +CWText=%m +VOX=0 +VOXTone="1500,100,1700,100,2300,100,2100,100,1900,100,1500,100" +TXGAIN=24578 +TXBPF=1 +TXLPF=0 +TXBPFTAP=24 +TXLPFFQ=2000 +DEMSLVL=1 +Differentiator=0 +DiffLevel=8.000000e-01 +RXAFC=1 +RXLMS=0 +RXLMSAN=0 +DEMBPF=1 +SyncStart=1 +SyncReStart=1 +AutoStop=0 +AutoSync=1 +SyncAccuracy=1 +AutoSwirchRX=0 +AutoSlant=0 +DemType=2 +fqcOutOrder=3 +fqcOutFC=9.000000e+02 +fqcType=0 +fqcSmooth=2.200000e+03 +pllVcoGain=1.000000e+00 +pllLoopOrder=1 +pllLoopFC=1.500000e+03 +pllOutOrder=3 +pllOutFC=9.000000e+02 +Call= + +[Color] +WaterLow=0 +WaterHigh=16777215 +FFTB=4227327 +FFT=65535 +FFTStg=16711680 +FFTSync=65280 +FFTFreq=65535 +RxWindow=16777215 + +[Polynomial] +Value0=-1.636467e+04 +Value1=-1.428800e+04 +Value2=-1.223433e+04 +Value3=-1.019400e+04 +Value4=-8.179333e+03 +Value5=-6.145000e+03 +Value6=-4.088667e+03 +Value7=-2.063000e+03 +Value8=-1.233333e+01 +Value9=2.050000e+03 +Value10=4.105000e+03 +Value11=6.209000e+03 +Value12=8.332667e+03 +Value13=1.045133e+04 +Value14=1.256500e+04 +Value15=1.463267e+04 +Value16=1.663133e+04 + +[Mode] +Button0=0 +Button1=1 +Button2=2 +Button3=3 +Button4=4 +Button5=5 +Button6=6 +Button7=7 +Button8=8 + +[Vari] +Enabled=0 +R=298 +G=588 +B=110 + +[Log] +TempDelay=3 +AutoUTCOffset=0 +UTCOffset=0 +UTCOffsetMin=0 +LogLink=1 +LinkPoll=0 +LinkPTT=0 + +[MMLink] +Name= + +[LogFile] +Name= + +[Program1] +Flag=1 +Name=SSTV-PAL +File=C:\Program Files\SSTV-PAL\SSTV-Pal.exe + +[Program2] +Flag=0 +Name= +File= + +[Program3] +Flag=0 +Name= +File= + +[Program4] +Flag=0 +Name= +File= + +[Program5] +Flag=0 +Name= +File= + +[Program6] +Flag=0 +Name= +File= + +[Program7] +Flag=0 +Name= +File= + +[Program8] +Flag=2 +Name=MMTTY +File=C:\MMTTY\MMTTY.EXE + +[Dir] +HistoryFormat=0 +History= +StockFormat=0 +Stock= +RecSound= +Bitmap= +SaveBitmap= +Template= +AutoSaveDir= +AutoSave=0 +AutoSaveTime=1 +AutoSaveFormat=1 +ExtLog= + +[ExtConv] +WDEF1=%YYYY-MM-DD +WLEN1=0 +WDEF2=%HHMM +WLEN2=0 +WDEF3=%EHHMM +WLEN3=0 +WDEF4=%CALL +WLEN4=0 +WDEF5=%HIS +WLEN5=0 +WDEF6=%MY +WLEN6=0 +WDEF7=%FREQ +WLEN7=0 +WDEF8=%MODE +WLEN8=0 +WDEF9=%POWER +WLEN9=0 +WDEF10=%NAME +WLEN10=0 +WDEF11=%QTH +WLEN11=0 +WDEF12=%REM +WLEN12=0 +WDEF13=%QSL +WLEN13=0 +WDEF14=%S +WLEN14=0 +WDEF15=%R +WLEN15=0 +WDEF16=%EOD +WLEN16=0 +WDEF17= +WLEN17=0 +WDEF18= +WLEN18=0 +WDEF19= +WLEN19=0 +WDEF20= +WLEN20=0 +WDEF21= +WLEN21=0 +WDEF22= +WLEN22=0 +WDEF23= +WLEN23=0 +WDEF24= +WLEN24=0 +WDEF25= +WLEN25=0 +WDEF26= +WLEN26=0 +WDEF27= +WLEN27=0 +WDEF28= +WLEN28=0 +WDEF29= +WLEN29=0 +WDEF30= +WLEN30=0 +WDEF31= +WLEN31=0 +WDEF32= +WLEN32=0 +WDEF33= +WLEN33=0 +WDEF34= +WLEN34=0 +WDEF35= +WLEN35=0 +WDEF36= +WLEN36=0 +WDEF37= +WLEN37=0 +WDEF38= +WLEN38=0 +WDEF39= +WLEN39=0 +WDEF40= +WLEN40=0 +WDEF41= +WLEN41=0 +WDEF42= +WLEN42=0 +WDEF43= +WLEN43=0 +WDEF44= +WLEN44=0 +WDEF45= +WLEN45=0 +WDEF46= +WLEN46=0 +WDEF47= +WLEN47=0 +WDEF48= +WLEN48=0 +WDEF49= +WLEN49=0 +WDEF50= +WLEN50=0 +WDEF51= +WLEN51=0 +WDEF52= +WLEN52=0 +WDEF53= +WLEN53=0 +WDEF54= +WLEN54=0 +WDEF55= +WLEN55=0 +WDEF56= +WLEN56=0 +WDEF57= +WLEN57=0 +WDEF58= +WLEN58=0 +WDEF59= +WLEN59=0 +WDEF60= +WLEN60=0 +WDEF61= +WLEN61=0 +WDEF62= +WLEN62=0 +WDEF63= +WLEN63=0 +WDEF64= +WLEN64=0 +RDEF1=%YYYY-MM-DD +RLEN1=0 +RDEF2=%HHMM +RLEN2=0 +RDEF3=%EHHMM +RLEN3=0 +RDEF4=%CALL +RLEN4=0 +RDEF5=%HIS +RLEN5=0 +RDEF6=%MY +RLEN6=0 +RDEF7=%FREQ +RLEN7=0 +RDEF8=%MODE +RLEN8=0 +RDEF9=%POWER +RLEN9=0 +RDEF10=%NAME +RLEN10=0 +RDEF11=%QTH +RLEN11=0 +RDEF12=%REM +RLEN12=0 +RDEF13=%QSL +RLEN13=0 +RDEF14=%S +RLEN14=0 +RDEF15=%R +RLEN15=0 +RDEF16=%EOD +RLEN16=0 +RDEF17= +RLEN17=0 +RDEF18= +RLEN18=0 +RDEF19= +RLEN19=0 +RDEF20= +RLEN20=0 +RDEF21= +RLEN21=0 +RDEF22= +RLEN22=0 +RDEF23= +RLEN23=0 +RDEF24= +RLEN24=0 +RDEF25= +RLEN25=0 +RDEF26= +RLEN26=0 +RDEF27= +RLEN27=0 +RDEF28= +RLEN28=0 +RDEF29= +RLEN29=0 +RDEF30= +RLEN30=0 +RDEF31= +RLEN31=0 +RDEF32= +RLEN32=0 +RDEF33= +RLEN33=0 +RDEF34= +RLEN34=0 +RDEF35= +RLEN35=0 +RDEF36= +RLEN36=0 +RDEF37= +RLEN37=0 +RDEF38= +RLEN38=0 +RDEF39= +RLEN39=0 +RDEF40= +RLEN40=0 +RDEF41= +RLEN41=0 +RDEF42= +RLEN42=0 +RDEF43= +RLEN43=0 +RDEF44= +RLEN44=0 +RDEF45= +RLEN45=0 +RDEF46= +RLEN46=0 +RDEF47= +RLEN47=0 +RDEF48= +RLEN48=0 +RDEF49= +RLEN49=0 +RDEF50= +RLEN50=0 +RDEF51= +RLEN51=0 +RDEF52= +RLEN52=0 +RDEF53= +RLEN53=0 +RDEF54= +RLEN54=0 +RDEF55= +RLEN55=0 +RDEF56= +RLEN56=0 +RDEF57= +RLEN57=0 +RDEF58= +RLEN58=0 +RDEF59= +RLEN59=0 +RDEF60= +RLEN60=0 +RDEF61= +RLEN61=0 +RDEF62= +RLEN62=0 +RDEF63= +RLEN63=0 +RDEF64= +RLEN64=0 + +[LogSet] +TimeZone=73 +DateType=0 +UpperName=0 +UpperQTH=0 +UpperREM=0 +UpperQSL=0 +DefMyRST=0 +CopyFreq=1 +CopyHis=0 +CopyName=1 +CopyQTH=1 +CopyREM=0 +CopyQSL=0 +CopyREMB4=0 +CheckBand=1 +AutoSave=1 +THRTTY=RTY +THSSTV=STV +THTZ=0 +ClipRSTADIF=1 +FSKNR=1 +Backup=1 +TH5Fields=3,3,7,4,12,28,54 + +[RADIO] +PortName=NONE +BaudRate=4800 +BitLen=1 +Stop=1 +Parity=0 +flwXON=0 +flwCTS=0 +usePTT=0 +ByteWait=0 +Cmdxx=0 +CmdInit= +CmdRx=\$000000000F +CmdTx=\$000000010F\w10 +FileGNR= +OpenGNR=0 +PollType=0 +PollInterval=5 + +[DrawText] +Color1=255 +Color2=16711935 +Color3=65535 +Color4=16776960 +Color5=0 +Color6=0 + +[DrawBar] +Color1=0 +Color2=15790320 +Color3=255 +Color4=32768 + +[ColorSet] +Color1=16776960 +Color2=65535 +Color3=16711935 +Color4=255 +Color5=255 +Color6=16711935 +Color7=65535 +Color8=16776960 +Color9=12615935 +Color10=8454143 +Color11=16776960 +Color12=65280 +Color13=16776960 +Color14=4259584 +Color15=65535 +Color16=16711935 +Color17=255 +Color18=16711935 +Color19=65535 +Color20=65280 +Color21=255 +Color22=4227327 +Color23=65535 +Color24=16777088 +Color25=16776960 +Color26=65535 +Color27=4227327 +Color28=255 +Color29=65280 +Color30=65535 +Color31=33023 +Color32=255 + +[TextList] +Text1=CQ SSTV +Text2=%c +Text3=ur %r +Text4=ur %R-%N +Text5=73 +Text6=de %m +Text7=%D %tZ +Text8=%L %u Local +Text9= +Text10= +Text11= +Text12= +Text13= +Text14= +Text15= +Text16= + +[Text] +Grade=0 +Shadow=2 +Zero=0 +Rot=0 +Vert=0 +VertH=-6 +3D=64516 +MSG="" +DisFontSmooth=1 +Temp24=2097153 + +[Pic] +Shape=0 +Adjust=0 +LineStyle=5 +LineColor=16777215 + +[PicSel] +RTM=1 +Smooz=0 +Color=16777215 + +[ProFile] +Version=1 + +[ProFile1] +Name=ヒルベルト変換 +VcoGain=1.000000e+00 +loopOrder=1 +loopFC=1.500000e+03 +OutOrder=3 +OutFC=9.000000e+02 +DemType=2 +fqcOutOrder=3 +fqcOutFC=9.000000e+02 +fqcType=0 +fqcSmooth=2.200000e+03 +DemOff=0.000000e+00 +DemWhite=7.812500e-03 +DemBlack=7.812500e-03 +DemCalibration=0 +DemPolynomial0=-1.636467e+04 +DemPolynomial1=-1.428800e+04 +DemPolynomial2=-1.223433e+04 +DemPolynomial3=-1.019400e+04 +DemPolynomial4=-8.179333e+03 +DemPolynomial5=-6.145000e+03 +DemPolynomial6=-4.088667e+03 +DemPolynomial7=-2.063000e+03 +DemPolynomial8=-1.233333e+01 +DemPolynomial9=2.050000e+03 +DemPolynomial10=4.105000e+03 +DemPolynomial11=6.209000e+03 +DemPolynomial12=8.332667e+03 +DemPolynomial13=1.045133e+04 +DemPolynomial14=1.256500e+04 +DemPolynomial15=1.463267e+04 +DemPolynomial16=1.663133e+04 +Differentiator=0 +DiffLevel=8.000000e-01 + +[ProFile2] +Name=ゼロクロス検波 +VcoGain=1.000000e+00 +loopOrder=1 +loopFC=1.500000e+03 +OutOrder=3 +OutFC=9.000000e+02 +DemType=1 +fqcOutOrder=3 +fqcOutFC=9.000000e+02 +fqcType=0 +fqcSmooth=2.200000e+03 +DemOff=0.000000e+00 +DemWhite=7.812500e-03 +DemBlack=7.812500e-03 +DemCalibration=1 +DemPolynomial0=-1.636467e+04 +DemPolynomial1=-1.428800e+04 +DemPolynomial2=-1.223433e+04 +DemPolynomial3=-1.019400e+04 +DemPolynomial4=-8.179333e+03 +DemPolynomial5=-6.145000e+03 +DemPolynomial6=-4.088667e+03 +DemPolynomial7=-2.063000e+03 +DemPolynomial8=-1.233333e+01 +DemPolynomial9=2.050000e+03 +DemPolynomial10=4.105000e+03 +DemPolynomial11=6.209000e+03 +DemPolynomial12=8.332667e+03 +DemPolynomial13=1.045133e+04 +DemPolynomial14=1.256500e+04 +DemPolynomial15=1.463267e+04 +DemPolynomial16=1.663133e+04 +Differentiator=0 +DiffLevel=8.000000e-01 + +[ProFile3] +Name=ゼロクロス検波+微分処理 +VcoGain=1.000000e+00 +loopOrder=1 +loopFC=1.500000e+03 +OutOrder=3 +OutFC=9.000000e+02 +DemType=1 +fqcOutOrder=3 +fqcOutFC=9.000000e+02 +fqcType=0 +fqcSmooth=2.200000e+03 +DemOff=0.000000e+00 +DemWhite=7.812500e-03 +DemBlack=7.812500e-03 +DemCalibration=1 +DemPolynomial0=-1.636467e+04 +DemPolynomial1=-1.428800e+04 +DemPolynomial2=-1.223433e+04 +DemPolynomial3=-1.019400e+04 +DemPolynomial4=-8.179333e+03 +DemPolynomial5=-6.145000e+03 +DemPolynomial6=-4.088667e+03 +DemPolynomial7=-2.063000e+03 +DemPolynomial8=-1.233333e+01 +DemPolynomial9=2.050000e+03 +DemPolynomial10=4.105000e+03 +DemPolynomial11=6.209000e+03 +DemPolynomial12=8.332667e+03 +DemPolynomial13=1.045133e+04 +DemPolynomial14=1.256500e+04 +DemPolynomial15=1.463267e+04 +DemPolynomial16=1.663133e+04 +Differentiator=1 +DiffLevel=8.000000e-01 + +[ProFile4] +Name= +VcoGain=1.000000e+00 +loopOrder=1 +loopFC=1.500000e+03 +OutOrder=3 +OutFC=9.000000e+02 +DemType=2 +fqcOutOrder=3 +fqcOutFC=9.000000e+02 +fqcType=0 +fqcSmooth=2.200000e+03 +DemOff=0.000000e+00 +DemWhite=7.812500e-03 +DemBlack=7.812500e-03 +DemCalibration=0 +DemPolynomial0=-1.636467e+04 +DemPolynomial1=-1.428800e+04 +DemPolynomial2=-1.223433e+04 +DemPolynomial3=-1.019400e+04 +DemPolynomial4=-8.179333e+03 +DemPolynomial5=-6.145000e+03 +DemPolynomial6=-4.088667e+03 +DemPolynomial7=-2.063000e+03 +DemPolynomial8=-1.233333e+01 +DemPolynomial9=2.050000e+03 +DemPolynomial10=4.105000e+03 +DemPolynomial11=6.209000e+03 +DemPolynomial12=8.332667e+03 +DemPolynomial13=1.045133e+04 +DemPolynomial14=1.256500e+04 +DemPolynomial15=1.463267e+04 +DemPolynomial16=1.663133e+04 +Differentiator=0 +DiffLevel=8.000000e-01 + +[ProFile5] +Name= +VcoGain=1.000000e+00 +loopOrder=1 +loopFC=1.500000e+03 +OutOrder=3 +OutFC=9.000000e+02 +DemType=2 +fqcOutOrder=3 +fqcOutFC=9.000000e+02 +fqcType=0 +fqcSmooth=2.200000e+03 +DemOff=0.000000e+00 +DemWhite=7.812500e-03 +DemBlack=7.812500e-03 +DemCalibration=0 +DemPolynomial0=-1.636467e+04 +DemPolynomial1=-1.428800e+04 +DemPolynomial2=-1.223433e+04 +DemPolynomial3=-1.019400e+04 +DemPolynomial4=-8.179333e+03 +DemPolynomial5=-6.145000e+03 +DemPolynomial6=-4.088667e+03 +DemPolynomial7=-2.063000e+03 +DemPolynomial8=-1.233333e+01 +DemPolynomial9=2.050000e+03 +DemPolynomial10=4.105000e+03 +DemPolynomial11=6.209000e+03 +DemPolynomial12=8.332667e+03 +DemPolynomial13=1.045133e+04 +DemPolynomial14=1.256500e+04 +DemPolynomial15=1.463267e+04 +DemPolynomial16=1.663133e+04 +Differentiator=0 +DiffLevel=8.000000e-01 + +[ProFile6] +Name= +VcoGain=1.000000e+00 +loopOrder=1 +loopFC=1.500000e+03 +OutOrder=3 +OutFC=9.000000e+02 +DemType=2 +fqcOutOrder=3 +fqcOutFC=9.000000e+02 +fqcType=0 +fqcSmooth=2.200000e+03 +DemOff=0.000000e+00 +DemWhite=7.812500e-03 +DemBlack=7.812500e-03 +DemCalibration=0 +DemPolynomial0=-1.636467e+04 +DemPolynomial1=-1.428800e+04 +DemPolynomial2=-1.223433e+04 +DemPolynomial3=-1.019400e+04 +DemPolynomial4=-8.179333e+03 +DemPolynomial5=-6.145000e+03 +DemPolynomial6=-4.088667e+03 +DemPolynomial7=-2.063000e+03 +DemPolynomial8=-1.233333e+01 +DemPolynomial9=2.050000e+03 +DemPolynomial10=4.105000e+03 +DemPolynomial11=6.209000e+03 +DemPolynomial12=8.332667e+03 +DemPolynomial13=1.045133e+04 +DemPolynomial14=1.256500e+04 +DemPolynomial15=1.463267e+04 +DemPolynomial16=1.663133e+04 +Differentiator=0 +DiffLevel=8.000000e-01 + +[ProFile7] +Name= +VcoGain=1.000000e+00 +loopOrder=1 +loopFC=1.500000e+03 +OutOrder=3 +OutFC=9.000000e+02 +DemType=2 +fqcOutOrder=3 +fqcOutFC=9.000000e+02 +fqcType=0 +fqcSmooth=2.200000e+03 +DemOff=0.000000e+00 +DemWhite=7.812500e-03 +DemBlack=7.812500e-03 +DemCalibration=0 +DemPolynomial0=-1.636467e+04 +DemPolynomial1=-1.428800e+04 +DemPolynomial2=-1.223433e+04 +DemPolynomial3=-1.019400e+04 +DemPolynomial4=-8.179333e+03 +DemPolynomial5=-6.145000e+03 +DemPolynomial6=-4.088667e+03 +DemPolynomial7=-2.063000e+03 +DemPolynomial8=-1.233333e+01 +DemPolynomial9=2.050000e+03 +DemPolynomial10=4.105000e+03 +DemPolynomial11=6.209000e+03 +DemPolynomial12=8.332667e+03 +DemPolynomial13=1.045133e+04 +DemPolynomial14=1.256500e+04 +DemPolynomial15=1.463267e+04 +DemPolynomial16=1.663133e+04 +Differentiator=0 +DiffLevel=8.000000e-01 + +[ProFile8] +Name= +VcoGain=1.000000e+00 +loopOrder=1 +loopFC=1.500000e+03 +OutOrder=3 +OutFC=9.000000e+02 +DemType=2 +fqcOutOrder=3 +fqcOutFC=9.000000e+02 +fqcType=0 +fqcSmooth=2.200000e+03 +DemOff=0.000000e+00 +DemWhite=7.812500e-03 +DemBlack=7.812500e-03 +DemCalibration=0 +DemPolynomial0=-1.636467e+04 +DemPolynomial1=-1.428800e+04 +DemPolynomial2=-1.223433e+04 +DemPolynomial3=-1.019400e+04 +DemPolynomial4=-8.179333e+03 +DemPolynomial5=-6.145000e+03 +DemPolynomial6=-4.088667e+03 +DemPolynomial7=-2.063000e+03 +DemPolynomial8=-1.233333e+01 +DemPolynomial9=2.050000e+03 +DemPolynomial10=4.105000e+03 +DemPolynomial11=6.209000e+03 +DemPolynomial12=8.332667e+03 +DemPolynomial13=1.045133e+04 +DemPolynomial14=1.256500e+04 +DemPolynomial15=1.463267e+04 +DemPolynomial16=1.663133e+04 +Differentiator=0 +DiffLevel=8.000000e-01 + +[CWMenu] +Menus=7 +M1=QSL 73 TU +M2=NR? AGN +M3=QRZ? +M4=UR %N %N +M5=%c de %m +M6=73 TU +M7=VVV + +[RadioMenu] +Menus=5 +Cap1=7.033 LSB (FT847) +Cmd1=\$0070330001\w10\$0000000007\w10 +Cap2=14.230 USB (FT847) +Cmd2=\$0142300001\w10\$0100000007\w10 +Cap3=21.340 USB (FT847) +Cmd3=\$0213400001\w10\$0100000007\w10 +Cap4=28.680 USB (FT847) +Cmd4=\$0286800001\w10\$0100000007\w10 +Cap5=144.450 USB (FT847) +Cmd5=\$1444500001\w10\$0100000007\w10 + diff --git a/Mmsstv Japanese.ini b/Mmsstv Japanese.ini new file mode 100644 index 0000000..b82008f --- /dev/null +++ b/Mmsstv Japanese.ini @@ -0,0 +1,1118 @@ +[SoundCard] +SampFreq=1.102500e+04 +TxSampOffset=0.000000e+00 + +[ComboList] +LogFreq=1.8,3.5,3.8,7,7.033,10,14,14.230,18,21,21.340,24,28,28.680,50,144,430,1200,2400 +LogRST=595,575,555,594,574,554,444,333 + +[Version] +INI=2 +LinearCalibration=2 +PLL=2 + +[Window] +Priority=0 +WindowState=0 +MemoryWindow=0 +UseB24=0 +RxViewInd=0 +RxView=0 +RxViewTop=0 +RxViewLeft=0 +RxViewWidth=320 +RxViewHeight=256 +SyncView=0 +SyncViewTop=0 +SyncViewLeft=0 +SyncViewWidth=326 +SyncViewHeight=259 +HistView=0 +HistViewTB=1 +HistViewTop=0 +HistViewLeft=0 +HistViewWidth=516 +HistViewHeight=70 +HistViewSize=2 +CtrBtn=0 +CtrBtnTop=0 +CtrBtnLeft=0 +CtrBtnWidth=128 +CtrBtnHeight=198 +StockViewTop=592 +StockViewLeft=556 +StockViewWidth=470 +StockViewHeight=156 +WaterViewTop=0 +WaterViewLeft=424 +WaterViewWidth=367 +WaterViewHeight=138 +LogViewTop=162 +LogViewLeft=424 +LogViewWidth=367 +LogViewHeight=164 +DivMode=0 +DivSW=7 +PreViewTop=0 +PreViewLeft=0 +PreViewWidth=160 +PreViewHeight=128 +StayOnTop=0 +MainPage=3 +StockPage=1 +StockPicPosition=0 +StockTempPos1=0 +StockTempPos2=0 +StockTempPos3=0 +StockTempPos4=0 +HQResizing=0 +UseTemplate=1 +ShowSuperimpos=0 +DraftSuperimpos=1 +PicClipType=0 +PicClipRatio=1 +PicClipMode=0 +PicClipView=1 +PicClipColor=0 +Way240=1 +AutoMargin=1 +TxClipType=0 +HistMax=32 +AutoRxClear=1 +AutoRxSave=1 +AutoCopy=1 +JPEG=80 +TempSuperimpos=1 +DummyMacro=1 +ShowTransPoint=0 +AutoTransPoint=1 +HistDDSize=2 +ShowSizeRX=0 +ShowSizeHist=0 +ShowSizeTX=0 +ShowSizeTemp=0 +ShowSizeStock=0 +StretchTXimage=0 +SwitchRX=0 + +[FileView] +ShowSize=0 +KeepA=0 + +[FileView1] +Flag=0 +Mode=1 +Size=2 +Top=0 +Left=0 +Width=516 +Height=70 +MaxPage=1 +CurPage=0 +FMPage1=-2147483648 +Folder= +Name1= + +[FileView2] +Flag=0 +Mode=1 +Size=2 +Top=0 +Left=0 +Width=516 +Height=70 +MaxPage=1 +CurPage=0 +FMPage1=-2147483648 +Folder= +Name1= + +[FileView3] +Flag=0 +Mode=1 +Size=2 +Top=0 +Left=0 +Width=516 +Height=70 +MaxPage=1 +CurPage=0 +FMPage1=-2147483648 +Folder= +Name1= + +[FileView4] +Flag=0 +Mode=1 +Size=2 +Top=0 +Left=0 +Width=516 +Height=70 +MaxPage=1 +CurPage=0 +FMPage1=-2147483648 +Folder= +Name1= + +[FileView5] +Flag=0 +Mode=1 +Size=2 +Top=0 +Left=0 +Width=516 +Height=70 +MaxPage=1 +CurPage=0 +FMPage1=-2147483648 +Folder= +Name1= + +[FileView6] +Flag=0 +Mode=1 +Size=2 +Top=0 +Left=0 +Width=516 +Height=70 +MaxPage=1 +CurPage=0 +FMPage1=-2147483648 +Folder= +Name1= + +[FileView7] +Flag=0 +Mode=1 +Size=2 +Top=0 +Left=0 +Width=516 +Height=70 +MaxPage=1 +CurPage=0 +FMPage1=-2147483648 +Folder= +Name1= + +[FileView8] +Flag=0 +Mode=1 +Size=2 +Top=0 +Left=0 +Width=516 +Height=70 +MaxPage=1 +CurPage=0 +FMPage1=-2147483648 +Folder= +Name1= + +[WindowFont] +Name=MS Pゴシック +Charset=128 +Style=0 +Adjust=0 + +[Help] +UseNotePad=0 + +[ImageAdj] +Sharp2D=0 + +[Define] +FFTType=2 +FFTGain=5 +FFTResp=0 +FFTStgv=1 +FFTWidth=1 +FFTAGC=1 +FFTPriority=0 +WaterSW=1 +LevelType=0 +UseRxBuff=1 +SoundFifoRX=12 +SoundFifoTX=8 +SoundPriority=1 +SoundDevice=-1 +SoundStereo=0 +StereoTX=0 +SoundMMW= +PTT=NONE +PTTLock=1 +RTSonRX=0 +TXLoopBack=0 +ColorOffset=0 +ColorWhite=7.812500e-03 +ColorBlack=7.812500e-03 +ColorCalibration=0 +FixedTxMode=1 +SSTVMode=3 +RXFSKID=0 +TXFSKID=0 +CWID=0 +CWIDWPM=28 +CWIDFreq=1000 +CWIDText=DE %m +MMVID= +TuneFreq=1750 +TuneTime=-1 +TuneSat=0 +CWText=%m +VOX=0 +VOXTone="1500,100,1700,100,2300,100,2100,100,1900,100,1500,100" +TXGAIN=24578 +TXBPF=1 +TXLPF=0 +TXBPFTAP=24 +TXLPFFQ=2000 +DEMSLVL=1 +Differentiator=0 +DiffLevel=8.000000e-01 +RXAFC=1 +RXLMS=0 +RXLMSAN=0 +DEMBPF=1 +SyncStart=1 +SyncReStart=1 +AutoStop=0 +AutoSync=1 +SyncAccuracy=1 +AutoSwirchRX=0 +AutoSlant=0 +DemType=2 +fqcOutOrder=3 +fqcOutFC=9.000000e+02 +fqcType=0 +fqcSmooth=2.200000e+03 +pllVcoGain=1.000000e+00 +pllLoopOrder=1 +pllLoopFC=1.500000e+03 +pllOutOrder=3 +pllOutFC=9.000000e+02 +Call=NOCALL + +[Color] +WaterLow=0 +WaterHigh=16777215 +FFTB=4227327 +FFT=65535 +FFTStg=16711680 +FFTSync=65280 +FFTFreq=65535 +RxWindow=16777215 + +[Polynomial] +Value0=-1.636467e+04 +Value1=-1.428800e+04 +Value2=-1.223433e+04 +Value3=-1.019400e+04 +Value4=-8.179333e+03 +Value5=-6.145000e+03 +Value6=-4.088667e+03 +Value7=-2.063000e+03 +Value8=-1.233333e+01 +Value9=2.050000e+03 +Value10=4.105000e+03 +Value11=6.209000e+03 +Value12=8.332667e+03 +Value13=1.045133e+04 +Value14=1.256500e+04 +Value15=1.463267e+04 +Value16=1.663133e+04 + +[Mode] +Button0=0 +Button1=1 +Button2=2 +Button3=3 +Button4=4 +Button5=5 +Button6=6 +Button7=7 +Button8=8 + +[Vari] +Enabled=0 +R=298 +G=588 +B=110 + +[Log] +TempDelay=3 +AutoUTCOffset=0 +UTCOffset=0 +UTCOffsetMin=0 +LogLink=1 +LinkPoll=0 +LinkPTT=0 + +[MMLink] +Name= + +[LogFile] +Name= + +[Program1] +Flag=1 +Name=SSTV-PAL +File=C:\Program Files\SSTV-PAL\SSTV-Pal.exe + +[Program2] +Flag=0 +Name= +File= + +[Program3] +Flag=0 +Name= +File= + +[Program4] +Flag=0 +Name= +File= + +[Program5] +Flag=0 +Name= +File= + +[Program6] +Flag=0 +Name= +File= + +[Program7] +Flag=0 +Name= +File= + +[Program8] +Flag=2 +Name=MMTTY +File=C:\MMTTY\MMTTY.EXE + +[Dir] +HistoryFormat=0 +History= +StockFormat=0 +Stock= +RecSound= +Bitmap= +SaveBitmap= +Template= +AutoSaveDir= +AutoSave=0 +AutoSaveTime=1 +AutoSaveFormat=1 +ExtLog= + +[ExtConv] +WDEF1=%YYYY-MM-DD +WLEN1=0 +WDEF2=%HHMM +WLEN2=0 +WDEF3=%EHHMM +WLEN3=0 +WDEF4=%CALL +WLEN4=0 +WDEF5=%HIS +WLEN5=0 +WDEF6=%MY +WLEN6=0 +WDEF7=%FREQ +WLEN7=0 +WDEF8=%MODE +WLEN8=0 +WDEF9=%POWER +WLEN9=0 +WDEF10=%NAME +WLEN10=0 +WDEF11=%QTH +WLEN11=0 +WDEF12=%REM +WLEN12=0 +WDEF13=%QSL +WLEN13=0 +WDEF14=%S +WLEN14=0 +WDEF15=%R +WLEN15=0 +WDEF16=%EOD +WLEN16=0 +WDEF17= +WLEN17=0 +WDEF18= +WLEN18=0 +WDEF19= +WLEN19=0 +WDEF20= +WLEN20=0 +WDEF21= +WLEN21=0 +WDEF22= +WLEN22=0 +WDEF23= +WLEN23=0 +WDEF24= +WLEN24=0 +WDEF25= +WLEN25=0 +WDEF26= +WLEN26=0 +WDEF27= +WLEN27=0 +WDEF28= +WLEN28=0 +WDEF29= +WLEN29=0 +WDEF30= +WLEN30=0 +WDEF31= +WLEN31=0 +WDEF32= +WLEN32=0 +WDEF33= +WLEN33=0 +WDEF34= +WLEN34=0 +WDEF35= +WLEN35=0 +WDEF36= +WLEN36=0 +WDEF37= +WLEN37=0 +WDEF38= +WLEN38=0 +WDEF39= +WLEN39=0 +WDEF40= +WLEN40=0 +WDEF41= +WLEN41=0 +WDEF42= +WLEN42=0 +WDEF43= +WLEN43=0 +WDEF44= +WLEN44=0 +WDEF45= +WLEN45=0 +WDEF46= +WLEN46=0 +WDEF47= +WLEN47=0 +WDEF48= +WLEN48=0 +WDEF49= +WLEN49=0 +WDEF50= +WLEN50=0 +WDEF51= +WLEN51=0 +WDEF52= +WLEN52=0 +WDEF53= +WLEN53=0 +WDEF54= +WLEN54=0 +WDEF55= +WLEN55=0 +WDEF56= +WLEN56=0 +WDEF57= +WLEN57=0 +WDEF58= +WLEN58=0 +WDEF59= +WLEN59=0 +WDEF60= +WLEN60=0 +WDEF61= +WLEN61=0 +WDEF62= +WLEN62=0 +WDEF63= +WLEN63=0 +WDEF64= +WLEN64=0 +RDEF1=%YYYY-MM-DD +RLEN1=0 +RDEF2=%HHMM +RLEN2=0 +RDEF3=%EHHMM +RLEN3=0 +RDEF4=%CALL +RLEN4=0 +RDEF5=%HIS +RLEN5=0 +RDEF6=%MY +RLEN6=0 +RDEF7=%FREQ +RLEN7=0 +RDEF8=%MODE +RLEN8=0 +RDEF9=%POWER +RLEN9=0 +RDEF10=%NAME +RLEN10=0 +RDEF11=%QTH +RLEN11=0 +RDEF12=%REM +RLEN12=0 +RDEF13=%QSL +RLEN13=0 +RDEF14=%S +RLEN14=0 +RDEF15=%R +RLEN15=0 +RDEF16=%EOD +RLEN16=0 +RDEF17= +RLEN17=0 +RDEF18= +RLEN18=0 +RDEF19= +RLEN19=0 +RDEF20= +RLEN20=0 +RDEF21= +RLEN21=0 +RDEF22= +RLEN22=0 +RDEF23= +RLEN23=0 +RDEF24= +RLEN24=0 +RDEF25= +RLEN25=0 +RDEF26= +RLEN26=0 +RDEF27= +RLEN27=0 +RDEF28= +RLEN28=0 +RDEF29= +RLEN29=0 +RDEF30= +RLEN30=0 +RDEF31= +RLEN31=0 +RDEF32= +RLEN32=0 +RDEF33= +RLEN33=0 +RDEF34= +RLEN34=0 +RDEF35= +RLEN35=0 +RDEF36= +RLEN36=0 +RDEF37= +RLEN37=0 +RDEF38= +RLEN38=0 +RDEF39= +RLEN39=0 +RDEF40= +RLEN40=0 +RDEF41= +RLEN41=0 +RDEF42= +RLEN42=0 +RDEF43= +RLEN43=0 +RDEF44= +RLEN44=0 +RDEF45= +RLEN45=0 +RDEF46= +RLEN46=0 +RDEF47= +RLEN47=0 +RDEF48= +RLEN48=0 +RDEF49= +RLEN49=0 +RDEF50= +RLEN50=0 +RDEF51= +RLEN51=0 +RDEF52= +RLEN52=0 +RDEF53= +RLEN53=0 +RDEF54= +RLEN54=0 +RDEF55= +RLEN55=0 +RDEF56= +RLEN56=0 +RDEF57= +RLEN57=0 +RDEF58= +RLEN58=0 +RDEF59= +RLEN59=0 +RDEF60= +RLEN60=0 +RDEF61= +RLEN61=0 +RDEF62= +RLEN62=0 +RDEF63= +RLEN63=0 +RDEF64= +RLEN64=0 + +[LogSet] +TimeZone=73 +DateType=0 +UpperName=0 +UpperQTH=0 +UpperREM=0 +UpperQSL=0 +DefMyRST=0 +CopyFreq=1 +CopyHis=0 +CopyName=1 +CopyQTH=1 +CopyREM=0 +CopyQSL=0 +CopyREMB4=0 +CheckBand=1 +AutoSave=1 +THRTTY=RTY +THSSTV=STV +THTZ=0 +ClipRSTADIF=1 +FSKNR=1 +Backup=1 +TH5Fields=3,3,7,4,12,28,54 + +[RADIO] +PortName=NONE +BaudRate=4800 +BitLen=1 +Stop=1 +Parity=0 +flwXON=0 +flwCTS=0 +usePTT=0 +ByteWait=0 +Cmdxx=0 +CmdInit= +CmdRx=\$000000000F +CmdTx=\$000000010F\w10 +FileGNR= +OpenGNR=0 +PollType=0 +PollInterval=5 + +[DrawText] +Color1=255 +Color2=16711935 +Color3=65535 +Color4=16776960 +Color5=0 +Color6=0 + +[DrawBar] +Color1=0 +Color2=15790320 +Color3=255 +Color4=32768 + +[ColorSet] +Color1=16776960 +Color2=65535 +Color3=16711935 +Color4=255 +Color5=255 +Color6=16711935 +Color7=65535 +Color8=16776960 +Color9=12615935 +Color10=8454143 +Color11=16776960 +Color12=65280 +Color13=16776960 +Color14=4259584 +Color15=65535 +Color16=16711935 +Color17=255 +Color18=16711935 +Color19=65535 +Color20=65280 +Color21=255 +Color22=4227327 +Color23=65535 +Color24=16777088 +Color25=16776960 +Color26=65535 +Color27=4227327 +Color28=255 +Color29=65280 +Color30=65535 +Color31=33023 +Color32=255 + +[TextList] +Text1=CQ SSTV +Text2=%c +Text3=ur %r +Text4=ur %R-%N +Text5=73 +Text6=de %m +Text7=%D %tZ +Text8=%L %u Local +Text9= +Text10= +Text11= +Text12= +Text13= +Text14= +Text15= +Text16= + +[Text] +Grade=0 +Shadow=2 +Zero=0 +Rot=0 +Vert=0 +VertH=-6 +3D=64516 +MSG="" +DisFontSmooth=1 +Temp24=2097153 + +[Pic] +Shape=0 +Adjust=0 +LineStyle=5 +LineColor=16777215 + +[PicSel] +RTM=1 +Smooz=0 +Color=16777215 + +[ProFile] +Version=1 + +[ProFile1] +Name=ヒルベルト変換 +VcoGain=1.000000e+00 +loopOrder=1 +loopFC=1.500000e+03 +OutOrder=3 +OutFC=9.000000e+02 +DemType=2 +fqcOutOrder=3 +fqcOutFC=9.000000e+02 +fqcType=0 +fqcSmooth=2.200000e+03 +DemOff=0.000000e+00 +DemWhite=7.812500e-03 +DemBlack=7.812500e-03 +DemCalibration=0 +DemPolynomial0=-1.636467e+04 +DemPolynomial1=-1.428800e+04 +DemPolynomial2=-1.223433e+04 +DemPolynomial3=-1.019400e+04 +DemPolynomial4=-8.179333e+03 +DemPolynomial5=-6.145000e+03 +DemPolynomial6=-4.088667e+03 +DemPolynomial7=-2.063000e+03 +DemPolynomial8=-1.233333e+01 +DemPolynomial9=2.050000e+03 +DemPolynomial10=4.105000e+03 +DemPolynomial11=6.209000e+03 +DemPolynomial12=8.332667e+03 +DemPolynomial13=1.045133e+04 +DemPolynomial14=1.256500e+04 +DemPolynomial15=1.463267e+04 +DemPolynomial16=1.663133e+04 +Differentiator=0 +DiffLevel=8.000000e-01 + +[ProFile2] +Name=ゼロクロス検波 +VcoGain=1.000000e+00 +loopOrder=1 +loopFC=1.500000e+03 +OutOrder=3 +OutFC=9.000000e+02 +DemType=1 +fqcOutOrder=3 +fqcOutFC=9.000000e+02 +fqcType=0 +fqcSmooth=2.200000e+03 +DemOff=0.000000e+00 +DemWhite=7.812500e-03 +DemBlack=7.812500e-03 +DemCalibration=1 +DemPolynomial0=-1.636467e+04 +DemPolynomial1=-1.428800e+04 +DemPolynomial2=-1.223433e+04 +DemPolynomial3=-1.019400e+04 +DemPolynomial4=-8.179333e+03 +DemPolynomial5=-6.145000e+03 +DemPolynomial6=-4.088667e+03 +DemPolynomial7=-2.063000e+03 +DemPolynomial8=-1.233333e+01 +DemPolynomial9=2.050000e+03 +DemPolynomial10=4.105000e+03 +DemPolynomial11=6.209000e+03 +DemPolynomial12=8.332667e+03 +DemPolynomial13=1.045133e+04 +DemPolynomial14=1.256500e+04 +DemPolynomial15=1.463267e+04 +DemPolynomial16=1.663133e+04 +Differentiator=0 +DiffLevel=8.000000e-01 + +[ProFile3] +Name=ゼロクロス検波+微分処理 +VcoGain=1.000000e+00 +loopOrder=1 +loopFC=1.500000e+03 +OutOrder=3 +OutFC=9.000000e+02 +DemType=1 +fqcOutOrder=3 +fqcOutFC=9.000000e+02 +fqcType=0 +fqcSmooth=2.200000e+03 +DemOff=0.000000e+00 +DemWhite=7.812500e-03 +DemBlack=7.812500e-03 +DemCalibration=1 +DemPolynomial0=-1.636467e+04 +DemPolynomial1=-1.428800e+04 +DemPolynomial2=-1.223433e+04 +DemPolynomial3=-1.019400e+04 +DemPolynomial4=-8.179333e+03 +DemPolynomial5=-6.145000e+03 +DemPolynomial6=-4.088667e+03 +DemPolynomial7=-2.063000e+03 +DemPolynomial8=-1.233333e+01 +DemPolynomial9=2.050000e+03 +DemPolynomial10=4.105000e+03 +DemPolynomial11=6.209000e+03 +DemPolynomial12=8.332667e+03 +DemPolynomial13=1.045133e+04 +DemPolynomial14=1.256500e+04 +DemPolynomial15=1.463267e+04 +DemPolynomial16=1.663133e+04 +Differentiator=1 +DiffLevel=8.000000e-01 + +[ProFile4] +Name= +VcoGain=1.000000e+00 +loopOrder=1 +loopFC=1.500000e+03 +OutOrder=3 +OutFC=9.000000e+02 +DemType=2 +fqcOutOrder=3 +fqcOutFC=9.000000e+02 +fqcType=0 +fqcSmooth=2.200000e+03 +DemOff=0.000000e+00 +DemWhite=7.812500e-03 +DemBlack=7.812500e-03 +DemCalibration=0 +DemPolynomial0=-1.636467e+04 +DemPolynomial1=-1.428800e+04 +DemPolynomial2=-1.223433e+04 +DemPolynomial3=-1.019400e+04 +DemPolynomial4=-8.179333e+03 +DemPolynomial5=-6.145000e+03 +DemPolynomial6=-4.088667e+03 +DemPolynomial7=-2.063000e+03 +DemPolynomial8=-1.233333e+01 +DemPolynomial9=2.050000e+03 +DemPolynomial10=4.105000e+03 +DemPolynomial11=6.209000e+03 +DemPolynomial12=8.332667e+03 +DemPolynomial13=1.045133e+04 +DemPolynomial14=1.256500e+04 +DemPolynomial15=1.463267e+04 +DemPolynomial16=1.663133e+04 +Differentiator=0 +DiffLevel=8.000000e-01 + +[ProFile5] +Name= +VcoGain=1.000000e+00 +loopOrder=1 +loopFC=1.500000e+03 +OutOrder=3 +OutFC=9.000000e+02 +DemType=2 +fqcOutOrder=3 +fqcOutFC=9.000000e+02 +fqcType=0 +fqcSmooth=2.200000e+03 +DemOff=0.000000e+00 +DemWhite=7.812500e-03 +DemBlack=7.812500e-03 +DemCalibration=0 +DemPolynomial0=-1.636467e+04 +DemPolynomial1=-1.428800e+04 +DemPolynomial2=-1.223433e+04 +DemPolynomial3=-1.019400e+04 +DemPolynomial4=-8.179333e+03 +DemPolynomial5=-6.145000e+03 +DemPolynomial6=-4.088667e+03 +DemPolynomial7=-2.063000e+03 +DemPolynomial8=-1.233333e+01 +DemPolynomial9=2.050000e+03 +DemPolynomial10=4.105000e+03 +DemPolynomial11=6.209000e+03 +DemPolynomial12=8.332667e+03 +DemPolynomial13=1.045133e+04 +DemPolynomial14=1.256500e+04 +DemPolynomial15=1.463267e+04 +DemPolynomial16=1.663133e+04 +Differentiator=0 +DiffLevel=8.000000e-01 + +[ProFile6] +Name= +VcoGain=1.000000e+00 +loopOrder=1 +loopFC=1.500000e+03 +OutOrder=3 +OutFC=9.000000e+02 +DemType=2 +fqcOutOrder=3 +fqcOutFC=9.000000e+02 +fqcType=0 +fqcSmooth=2.200000e+03 +DemOff=0.000000e+00 +DemWhite=7.812500e-03 +DemBlack=7.812500e-03 +DemCalibration=0 +DemPolynomial0=-1.636467e+04 +DemPolynomial1=-1.428800e+04 +DemPolynomial2=-1.223433e+04 +DemPolynomial3=-1.019400e+04 +DemPolynomial4=-8.179333e+03 +DemPolynomial5=-6.145000e+03 +DemPolynomial6=-4.088667e+03 +DemPolynomial7=-2.063000e+03 +DemPolynomial8=-1.233333e+01 +DemPolynomial9=2.050000e+03 +DemPolynomial10=4.105000e+03 +DemPolynomial11=6.209000e+03 +DemPolynomial12=8.332667e+03 +DemPolynomial13=1.045133e+04 +DemPolynomial14=1.256500e+04 +DemPolynomial15=1.463267e+04 +DemPolynomial16=1.663133e+04 +Differentiator=0 +DiffLevel=8.000000e-01 + +[ProFile7] +Name= +VcoGain=1.000000e+00 +loopOrder=1 +loopFC=1.500000e+03 +OutOrder=3 +OutFC=9.000000e+02 +DemType=2 +fqcOutOrder=3 +fqcOutFC=9.000000e+02 +fqcType=0 +fqcSmooth=2.200000e+03 +DemOff=0.000000e+00 +DemWhite=7.812500e-03 +DemBlack=7.812500e-03 +DemCalibration=0 +DemPolynomial0=-1.636467e+04 +DemPolynomial1=-1.428800e+04 +DemPolynomial2=-1.223433e+04 +DemPolynomial3=-1.019400e+04 +DemPolynomial4=-8.179333e+03 +DemPolynomial5=-6.145000e+03 +DemPolynomial6=-4.088667e+03 +DemPolynomial7=-2.063000e+03 +DemPolynomial8=-1.233333e+01 +DemPolynomial9=2.050000e+03 +DemPolynomial10=4.105000e+03 +DemPolynomial11=6.209000e+03 +DemPolynomial12=8.332667e+03 +DemPolynomial13=1.045133e+04 +DemPolynomial14=1.256500e+04 +DemPolynomial15=1.463267e+04 +DemPolynomial16=1.663133e+04 +Differentiator=0 +DiffLevel=8.000000e-01 + +[ProFile8] +Name= +VcoGain=1.000000e+00 +loopOrder=1 +loopFC=1.500000e+03 +OutOrder=3 +OutFC=9.000000e+02 +DemType=2 +fqcOutOrder=3 +fqcOutFC=9.000000e+02 +fqcType=0 +fqcSmooth=2.200000e+03 +DemOff=0.000000e+00 +DemWhite=7.812500e-03 +DemBlack=7.812500e-03 +DemCalibration=0 +DemPolynomial0=-1.636467e+04 +DemPolynomial1=-1.428800e+04 +DemPolynomial2=-1.223433e+04 +DemPolynomial3=-1.019400e+04 +DemPolynomial4=-8.179333e+03 +DemPolynomial5=-6.145000e+03 +DemPolynomial6=-4.088667e+03 +DemPolynomial7=-2.063000e+03 +DemPolynomial8=-1.233333e+01 +DemPolynomial9=2.050000e+03 +DemPolynomial10=4.105000e+03 +DemPolynomial11=6.209000e+03 +DemPolynomial12=8.332667e+03 +DemPolynomial13=1.045133e+04 +DemPolynomial14=1.256500e+04 +DemPolynomial15=1.463267e+04 +DemPolynomial16=1.663133e+04 +Differentiator=0 +DiffLevel=8.000000e-01 + +[CWMenu] +Menus=7 +M1=QSL 73 TU +M2=NR? AGN +M3=QRZ? +M4=UR %N %N +M5=%c de %m +M6=73 TU +M7=VVV + +[RadioMenu] +Menus=5 +Cap1=7.033 LSB (FT847) +Cmd1=\$0070330001\w10\$0000000007\w10 +Cap2=14.230 USB (FT847) +Cmd2=\$0142300001\w10\$0100000007\w10 +Cap3=21.340 USB (FT847) +Cmd3=\$0213400001\w10\$0100000007\w10 +Cap4=28.680 USB (FT847) +Cmd4=\$0286800001\w10\$0100000007\w10 +Cap5=144.450 USB (FT847) +Cmd5=\$1444500001\w10\$0100000007\w10 + diff --git a/Mmsstv.bpr b/Mmsstv.bpr new file mode 100644 index 0000000..3747cb2 --- /dev/null +++ b/Mmsstv.bpr @@ -0,0 +1,127 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +[Version Info] +IncludeVerInfo=0 +AutoIncBuild=0 +MajorVer=1 +MinorVer=0 +Release=0 +Build=0 +Debug=0 +PreRelease=0 +Special=0 +Private=0 +DLL=0 +Locale=1041 +CodePage=932 + +[Version Info Keys] +CompanyName= +FileDescription= +FileVersion=1.0.0.0 +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion=1.0.0.0 +Comments= + +[HistoryLists\hlRunParameters] +Count=1 +Item0=-r + +[Debugging] +DebugSourceDirs=$(BCB)\source\vcl + +[Parameters] +RunParams= +HostApplication= +RemoteHost= +RemotePath= +RemoteDebug=0 + +[Compiler] +ShowInfoMsgs=0 +LinkDebugVcl=0 +LinkCGLIB=0 + +[Language] +ActiveLang= +ProjectLang= +RootDir= + + \ No newline at end of file diff --git a/Mmsstv.cbproj b/Mmsstv.cbproj new file mode 100644 index 0000000..4921daa --- /dev/null +++ b/Mmsstv.cbproj @@ -0,0 +1,784 @@ +サソ + + {A96F1C7C-EA53-4893-AAB3-9F1974AE105E} + CppVCLApplication + Mmsstv.cpp + True + Debug + 14.6 + Application + VCL + Win32 + 1 + + + true + + + true + Base + true + + + true + Base + true + + + true + Base + true + + + true + Cfg_1 + true + true + + + true + Cfg_1 + true + true + + + true + Base + true + + + true + Cfg_2 + true + true + + + true + Cfg_2 + true + true + + + CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments= + 1041 + Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace) + rtl.lib;vcl.lib;inet.lib + jpeg\;$(IncludePath) + vclx.bpi;rtl.bpi;vcl.bpi;dbrtl.bpi;vcldb.bpi;bdertl.bpi;vcldbx.bpi;bcbsmp.bpi;teeui.bpi;vclsmp.bpi;teedb.bpi;tee.bpi;ibsmp.bpi;inetdb.bpi;inet.bpi;$(PackageImports) + .\;$(BDS)\lib;$(BDS)\lib\obj;$(DCC_UnitSearchPath) + Windows + true + c:\program files\borland\cbuilder3\projects;jpeg;$(BDS)\include;$(BDS)\include\vcl;$(BRCC_IncludePath) + true + jpeg;$(BDS)\include;$(BCC_IncludePath) + .\;$(BDS)\lib;$(BDS)\lib\obj;$(DCC_IncludePath) + c:\program files\borland\cbuilder3\projects;jpeg;$(BDS)\include;$(BDS)\include\vcl;$(TASM_IncludePath) + . + true + rtl.lib;vcl.lib;inet.lib + None + /w2 + exe + JPHNE + -M + jpeg\;c:\program files\borland\cbuilder3\projects;jpeg;$(BDS)\lib\obj;$(BDS)\lib;$(BDS)\lib\psdk;$(ILINK_LibraryPath) + + + Mmsstv_Icon.ico + true + 1033 + -tWM -Tkh30000 -Vx -d -Ve + $(BDS)\bin\default_app.manifest + Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) + $(BDSINCLUDE)\windows\vcl;$(IncludePath) + + + Mmsstv_Icon.ico + $(BDSINCLUDE)\windows\vcl;$(IncludePath) + + + $(BDS)\lib\debug;$(ILINK_LibraryPath);$(ILINK_LibraryPath) + DEBUG;$(DCC_Define);$(DCC_Define) + true + Debug_Build + true + true + true + true + Full + -M -V + true + true + false + + + _DEBUG;$(BCC_Defines);$(BCC_Defines) + -tWM -Tkh30000 -Vx -d -Ve -k + 1033 + true + None + false + true + true + true + + + _DEBUG;$(BCC_Defines);$(BCC_Defines) + + + Release_Build + -M -$O+ + $(BDS)\lib\release;$(ILINK_LibraryPath);$(ILINK_LibraryPath) + + + -tWM -Tkh30000 -Vx -d -Ve -r + NDEBUG;$(BCC_Defines);$(BCC_Defines) + + + NDEBUG;$(BCC_Defines);$(BCC_Defines) + + + + 94 +
BitMaskDlg
+ BitMask.h + 30 +
+ + 86 +
ClockAdjDlg
+ ClockAdj.h + 42 +
+ + 88 +
ColorBarDlg
+ ColorBar.h + 50 +
+ + 62 +
ColorSetDlg
+ ColorSet.h + 24 +
+ + 8 + ComLib.h + 78 + + + 74 + Comm.h + 10 + + + 82 +
ConvDefDlg
+ ConvDef.h + 44 +
+ + 99 + country.h + 29 + + + 75 + cradio.h + 11 + + + 55 +
CtrBtnWnd
+ CtrBtn.h + 17 +
+ + 9 + Draw.h + 79 + + + 95 +
ExtCmdDlg
+ ExtCmd.h + 31 +
+ + 77 + Fft.h + 7 + + + 54 +
FileViewDlg
+ fileview.h + 16 +
+ + 68 + fir.h + 4 + + + 90 +
FreqDispDlg
+ FreqDisp.h + 52 +
+ + 35 + Hamlog5.h + 105 + + + 59 +
HistViewDlg
+ HistView.h + 15 +
+ + 87 +
InputWinDlg
+ InputWin.h + 46 +
+ + 76 + 12 + + + 96 + 32 + + + 33 + 100 + + + 34 + 104 + + + 35 + 105 + + + 36 + jpeg\Jchuff.h + 106 + + + 37 + 101 + + + 38 + 102 + + + 39 + 103 + + + 84 + 40 + + + 85 + 41 + + + 86 + 42 + + + 81 + 43 + + + 82 + 44 + + + 83 + 45 + + + 87 + 46 + + + 91 + 47 + + + 92 + 48 + + + 93 + 49 + + + 88 + 50 + + + 89 + 51 + + + 90 + 52 + + + 53 + + + 54 + jpeg\Jdhuff.h + 16 + + + 55 + 17 + + + 56 + 18 + + + 57 + 13 + + + 58 + 14 + + + 59 + 15 + + + 60 + 19 + + + 61 + 23 + + + 62 + 24 + + + 63 + 25 + + + 64 + jpeg\Jerror.h + 20 + + + 65 + 21 + + + 66 + 22 + + + 67 + 3 + + + 77 + jpeg\jhandle.h + 7 + + + 68 + 4 + + + 69 + 5 + + + 70 + 0 + + + 71 + 1 + + + 72 + 2 + + + 73 + 6 + + + 74 + 10 + + + 75 + 11 + + + 95 + 31 + + + 89 +
LinearDspDlg
+ LinearDs.h + 51 +
+ + 63 +
LineSetDlg
+ LineSet.h + 25 +
+ + 60 +
ListTextDlg
+ ListText.h + 19 +
+ + 84 + LogConv.h + 40 + + + 97 + LogFile.h + 27 + + + 98 + Loglink.h + 28 + + + 9 +
LogListDlg
+ LogList.h + 79 +
+ + 93 +
LogPicDlg
+ LogPic.h + 49 +
+ + 80 +
LogSetDlg
+ LogSet.h + 26 +
+ + 61 +
MacroKeyDlg
+ MacroKey.h + 23 +
+ + 72 +
Mmsstv
+ Main.h + 2 +
+ + 94 + Mmcg.h + 30 + + + 83 +
MmcgDlgBox
+ MmcgDlg.h + 45 +
+ + 37 + 101 + + + 33 + MMlink.h + 100 + + + 38 + 102 + + + -1 + 0 + + + -1 + 1 + + + 39 + 103 + + + 58 +
OptionDlg
+ Option.h + 14 +
+ + 96 +
PerSpectDlg
+ PerSpect.h + 32 +
+ + 64 +
PicFilterDlg
+ PicFilte.h + 20 +
+ + 80 +
PicRectDlg
+ PicRect.h + 26 +
+ + 66 +
PicSelDlg
+ PicSel.h + 22 +
+ + 99 +
PlayDlgBox
+ PlayDlg.h + 29 +
+ + 8 +
PrevViewBox
+ PrevView.h + 78 +
+ + 81 +
QSODlgBox
+ Qsodlg.h + 43 +
+ + 91 +
RADIOSetDlg
+ RadioSet.h + 47 +
+ + 97 +
RepSetDlg
+ RepSet.h + 27 +
+ + 36 +
RMenuDialog
+ RMenuDlg.h + 106 +
+ + 57 +
RxViewDlg
+ RxView.h + 13 +
+ + 98 +
TScope
+ Scope.h + 28 +
+ + 67 + Sound.h + 3 + + + 69 + sstv.h + 5 + + + 65 +
StockView
+ StockVew.h + 21 +
+ + 92 +
TextEditDlg
+ TextEdit.h + 48 +
+ + 76 +
TextInDlg
+ TextIn.h + 12 +
+ + 34 +
TH5LenDlg
+ TH5Len.h + 104 +
+ + 85 +
VerDspDlg
+ VerDsp.h + 41 +
+ + 73 + Wave.h + 6 + + + 56 +
ZoomViewDlg
+ ZoomView.h + 18 +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Cfg_2 + Base + + + Base + + + Cfg_1 + Base + +
+ + + + CPlusPlusBuilder.Personality.12 + CppVCLApplication + + + + False + False + 1 + 0 + 0 + 0 + False + False + False + False + False + 1041 + 932 + + + + + 1.0.0.0 + + + + + + 1.0.0.0 + + + + 1 + -r + + + $(BCB)\source\vcl + + + + + 0 + + + 0 + 0 + 0 + + + False + True + True + + + Mmsstv.cpp + + + + True + False + + + 12 + +
diff --git a/Mmsstv.cbproj.local b/Mmsstv.cbproj.local new file mode 100644 index 0000000..b3811b7 --- /dev/null +++ b/Mmsstv.cbproj.local @@ -0,0 +1,2 @@ +サソ + diff --git a/Mmsstv.cpp b/Mmsstv.cpp new file mode 100644 index 0000000..7103cd7 --- /dev/null +++ b/Mmsstv.cpp @@ -0,0 +1,156 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------------- +#include +#pragma hdrstop +USERES("Mmsstv.res"); +USEFORM("Main.cpp", Mmsstv); +USEUNIT("Sound.cpp"); +USEUNIT("fir.cpp"); +USEUNIT("sstv.cpp"); +USEUNIT("Wave.cpp"); +USEUNIT("Fft.cpp"); +USEUNIT("ComLib.cpp"); +USEUNIT("Draw.cpp"); +USEUNIT("Comm.cpp"); +USEUNIT("cradio.cpp"); +USEFORM("TextIn.cpp", TextInDlg); +USEFORM("RxView.cpp", RxViewDlg); +USEFORM("Option.cpp", OptionDlg); +USEFORM("HistView.cpp", HistViewDlg); +USEFORM("fileview.cpp", FileViewDlg); +USEFORM("CtrBtn.cpp", CtrBtnWnd); +USEFORM("ZoomView.cpp", ZoomViewDlg); +USEFORM("ListText.cpp", ListTextDlg); +USEFORM("PicFilte.cpp", PicFilterDlg); +USEFORM("StockVew.cpp", StockView); +USEFORM("PicSel.cpp", PicSelDlg); +USEFORM("MacroKey.cpp", MacroKeyDlg); +USEFORM("ColorSet.cpp", ColorSetDlg); +USEFORM("LineSet.cpp", LineSetDlg); +USEFORM("PicRect.cpp", PicRectDlg); +USEUNIT("LogFile.cpp"); +USEUNIT("Loglink.cpp"); +USEUNIT("country.cpp"); +USEUNIT("Mmcg.cpp"); +USEUNIT("jpeg\Jutils.c"); +USEUNIT("jpeg\Jcapistd.c"); +USEUNIT("jpeg\Jccoefct.c"); +USEUNIT("jpeg\Jccolor.c"); +USEUNIT("jpeg\Jcdctmgr.c"); +USEUNIT("jpeg\Jchuff.c"); +USEUNIT("jpeg\Jcinit.c"); +USEUNIT("jpeg\Jcmainct.c"); +USEUNIT("jpeg\Jcmarker.c"); +USEUNIT("jpeg\Jcmaster.c"); +USEUNIT("jpeg\Jcomapi.c"); +USEUNIT("jpeg\Jcparam.c"); +USEUNIT("jpeg\Jcphuff.c"); +USEUNIT("jpeg\Jcprepct.c"); +USEUNIT("jpeg\Jcsample.c"); +USEUNIT("jpeg\Jctrans.c"); +USEUNIT("jpeg\Jdapimin.c"); +USEUNIT("jpeg\Jdapistd.c"); +USEUNIT("jpeg\Jdatadst.c"); +USEUNIT("jpeg\Jdatasrc.c"); +USEUNIT("jpeg\Jdcoefct.c"); +USEUNIT("jpeg\Jdcolor.c"); +USEUNIT("jpeg\Jddctmgr.c"); +USEUNIT("jpeg\Jdhuff.c"); +USEUNIT("jpeg\Jdinput.c"); +USEUNIT("jpeg\Jdmainct.c"); +USEUNIT("jpeg\Jdmarker.c"); +USEUNIT("jpeg\Jdmaster.c"); +USEUNIT("jpeg\Jdmerge.c"); +USEUNIT("jpeg\Jdphuff.c"); +USEUNIT("jpeg\Jdpostct.c"); +USEUNIT("jpeg\Jdsample.c"); +USEUNIT("jpeg\Jdtrans.c"); +USEUNIT("jpeg\Jerror.c"); +USEUNIT("jpeg\Jfdctflt.c"); +USEUNIT("jpeg\Jfdctfst.c"); +USEUNIT("jpeg\Jfdctint.c"); +USEUNIT("jpeg\Jidctflt.c"); +USEUNIT("jpeg\Jidctfst.c"); +USEUNIT("jpeg\Jidctint.c"); +USEUNIT("jpeg\Jidctred.c"); +USEUNIT("jpeg\Jmemmgr.c"); +USEUNIT("jpeg\Jmemnobs.c"); +USEUNIT("jpeg\Jquant1.c"); +USEUNIT("jpeg\Jquant2.c"); +USEUNIT("jpeg\Jcapimin.c"); +USEUNIT("jpeg\jhandle.C"); +USEFORM("PrevView.cpp", PrevViewBox); +USEFORM("LogList.cpp", LogListDlg); +USEFORM("LogSet.cpp", LogSetDlg); +USEFORM("Qsodlg.cpp", QSODlgBox); +USEFORM("ConvDef.cpp", ConvDefDlg); +USEFORM("MmcgDlg.cpp", MmcgDlgBox); +USEUNIT("LogConv.cpp"); +USEFORM("VerDsp.cpp", VerDspDlg); +USEFORM("ClockAdj.cpp", ClockAdjDlg); +USEFORM("InputWin.cpp", InputWinDlg); +USEFORM("ColorBar.cpp", ColorBarDlg); +USEFORM("LinearDs.cpp", LinearDspDlg); +USEFORM("FreqDisp.cpp", FreqDispDlg); +USEFORM("RadioSet.cpp", RADIOSetDlg); +USEFORM("TextEdit.cpp", TextEditDlg); +USEFORM("LogPic.cpp", LogPicDlg); +USEFORM("BitMask.cpp", BitMaskDlg); +USEFORM("ExtCmd.cpp", ExtCmdDlg); +USEFORM("PerSpect.cpp", PerSpectDlg); +USEFORM("RepSet.cpp", RepSetDlg); +USEFORM("Scope.cpp", TScope); +USEFORM("PlayDlg.cpp", PlayDlgBox); +USEUNIT("MMlink.cpp"); +USEFILE("mml.h"); +USEFILE("mmrp.h"); +USEFILE("mmw.h"); +USEFORM("TH5Len.cpp", TH5LenDlg); +USEUNIT("Hamlog5.cpp"); +USEFORM("RMenuDlg.cpp", RMenuDialog); +//--------------------------------------------------------------------------- +WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) +{ + LPSTR pCmd = GetCommandLine(); + if( strstr(pCmd, "-Z") == NULL ){ + HWND hWnd = ::FindWindow("TMmsstv", NULL); + if( hWnd != NULL ){ + hWnd = ::FindWindow("TAppBuilder", NULL); + if( hWnd == NULL ){ + return 0; + } + } + } + + try + { + Application->Initialize(); + Application->CreateForm(__classid(TMmsstv), &Mmsstv); + Application->Run(); + } + catch (Exception &exception) + { + Application->ShowException(&exception); + } + return 0; +} +//--------------------------------------------------------------------------- + diff --git a/Mmsstv.ini b/Mmsstv.ini new file mode 100644 index 0000000..371c3d8 --- /dev/null +++ b/Mmsstv.ini @@ -0,0 +1,1118 @@ +[SoundCard] +SampFreq=1.102500e+04 +TxSampOffset=0.000000e+00 + +[ComboList] +LogFreq=1.8,3.5,3.8,7,7.033,10,14,14.230,18,21,21.340,24,28,28.680,50,144,430,1200,2400 +LogRST=595,575,555,594,574,554,444,333 + +[Version] +INI=2 +LinearCalibration=2 +PLL=2 + +[Window] +Priority=0 +WindowState=0 +MemoryWindow=0 +UseB24=0 +RxViewInd=0 +RxView=0 +RxViewTop=0 +RxViewLeft=0 +RxViewWidth=320 +RxViewHeight=256 +SyncView=0 +SyncViewTop=0 +SyncViewLeft=0 +SyncViewWidth=326 +SyncViewHeight=259 +HistView=0 +HistViewTB=1 +HistViewTop=0 +HistViewLeft=0 +HistViewWidth=516 +HistViewHeight=70 +HistViewSize=2 +CtrBtn=0 +CtrBtnTop=0 +CtrBtnLeft=0 +CtrBtnWidth=128 +CtrBtnHeight=198 +StockViewTop=592 +StockViewLeft=556 +StockViewWidth=470 +StockViewHeight=156 +WaterViewTop=0 +WaterViewLeft=424 +WaterViewWidth=367 +WaterViewHeight=138 +LogViewTop=162 +LogViewLeft=424 +LogViewWidth=367 +LogViewHeight=164 +DivMode=0 +DivSW=7 +PreViewTop=0 +PreViewLeft=0 +PreViewWidth=160 +PreViewHeight=128 +StayOnTop=0 +MainPage=3 +StockPage=1 +StockPicPosition=0 +StockTempPos1=0 +StockTempPos2=0 +StockTempPos3=0 +StockTempPos4=0 +HQResizing=0 +UseTemplate=1 +ShowSuperimpos=0 +DraftSuperimpos=1 +PicClipType=0 +PicClipRatio=1 +PicClipMode=0 +PicClipView=1 +PicClipColor=0 +Way240=1 +AutoMargin=1 +TxClipType=0 +HistMax=32 +AutoRxClear=1 +AutoRxSave=1 +AutoCopy=1 +JPEG=80 +TempSuperimpos=1 +DummyMacro=1 +ShowTransPoint=0 +AutoTransPoint=1 +HistDDSize=2 +ShowSizeRX=0 +ShowSizeHist=0 +ShowSizeTX=0 +ShowSizeTemp=0 +ShowSizeStock=0 +StretchTXimage=0 +SwitchRX=0 + +[FileView] +ShowSize=0 +KeepA=0 + +[FileView1] +Flag=0 +Mode=1 +Size=2 +Top=0 +Left=0 +Width=516 +Height=70 +MaxPage=1 +CurPage=0 +FMPage1=-2147483648 +Folder= +Name1= + +[FileView2] +Flag=0 +Mode=1 +Size=2 +Top=0 +Left=0 +Width=516 +Height=70 +MaxPage=1 +CurPage=0 +FMPage1=-2147483648 +Folder= +Name1= + +[FileView3] +Flag=0 +Mode=1 +Size=2 +Top=0 +Left=0 +Width=516 +Height=70 +MaxPage=1 +CurPage=0 +FMPage1=-2147483648 +Folder= +Name1= + +[FileView4] +Flag=0 +Mode=1 +Size=2 +Top=0 +Left=0 +Width=516 +Height=70 +MaxPage=1 +CurPage=0 +FMPage1=-2147483648 +Folder= +Name1= + +[FileView5] +Flag=0 +Mode=1 +Size=2 +Top=0 +Left=0 +Width=516 +Height=70 +MaxPage=1 +CurPage=0 +FMPage1=-2147483648 +Folder= +Name1= + +[FileView6] +Flag=0 +Mode=1 +Size=2 +Top=0 +Left=0 +Width=516 +Height=70 +MaxPage=1 +CurPage=0 +FMPage1=-2147483648 +Folder= +Name1= + +[FileView7] +Flag=0 +Mode=1 +Size=2 +Top=0 +Left=0 +Width=516 +Height=70 +MaxPage=1 +CurPage=0 +FMPage1=-2147483648 +Folder= +Name1= + +[FileView8] +Flag=0 +Mode=1 +Size=2 +Top=0 +Left=0 +Width=516 +Height=70 +MaxPage=1 +CurPage=0 +FMPage1=-2147483648 +Folder= +Name1= + +[WindowFont] +Name=Arial +Charset=0 +Style=0 +Adjust=0 + +[Help] +UseNotePad=0 + +[ImageAdj] +Sharp2D=0 + +[Define] +FFTType=2 +FFTGain=5 +FFTResp=0 +FFTStgv=1 +FFTWidth=1 +FFTAGC=1 +FFTPriority=0 +WaterSW=1 +LevelType=0 +UseRxBuff=1 +SoundFifoRX=12 +SoundFifoTX=8 +SoundPriority=1 +SoundDevice=-1 +SoundStereo=0 +StereoTX=0 +SoundMMW= +PTT=NONE +PTTLock=1 +RTSonRX=0 +TXLoopBack=0 +ColorOffset=0 +ColorWhite=7.812500e-03 +ColorBlack=7.812500e-03 +ColorCalibration=0 +FixedTxMode=1 +SSTVMode=3 +RXFSKID=0 +TXFSKID=0 +CWID=0 +CWIDWPM=28 +CWIDFreq=1000 +CWIDText=DE %m +MMVID= +TuneFreq=1750 +TuneTime=-1 +TuneSat=0 +CWText=%m +VOX=0 +VOXTone="1500,100,1700,100,2300,100,2100,100,1900,100,1500,100" +TXGAIN=24578 +TXBPF=1 +TXLPF=0 +TXBPFTAP=24 +TXLPFFQ=2000 +DEMSLVL=1 +Differentiator=0 +DiffLevel=8.000000e-01 +RXAFC=1 +RXLMS=0 +RXLMSAN=0 +DEMBPF=1 +SyncStart=1 +SyncReStart=1 +AutoStop=0 +AutoSync=1 +SyncAccuracy=1 +AutoSwirchRX=0 +AutoSlant=0 +DemType=2 +fqcOutOrder=3 +fqcOutFC=9.000000e+02 +fqcType=0 +fqcSmooth=2.200000e+03 +pllVcoGain=1.000000e+00 +pllLoopOrder=1 +pllLoopFC=1.500000e+03 +pllOutOrder=3 +pllOutFC=9.000000e+02 +Call= + +[Color] +WaterLow=0 +WaterHigh=16777215 +FFTB=4227327 +FFT=65535 +FFTStg=16711680 +FFTSync=65280 +FFTFreq=65535 +RxWindow=16777215 + +[Polynomial] +Value0=-1.636467e+04 +Value1=-1.428800e+04 +Value2=-1.223433e+04 +Value3=-1.019400e+04 +Value4=-8.179333e+03 +Value5=-6.145000e+03 +Value6=-4.088667e+03 +Value7=-2.063000e+03 +Value8=-1.233333e+01 +Value9=2.050000e+03 +Value10=4.105000e+03 +Value11=6.209000e+03 +Value12=8.332667e+03 +Value13=1.045133e+04 +Value14=1.256500e+04 +Value15=1.463267e+04 +Value16=1.663133e+04 + +[Mode] +Button0=0 +Button1=1 +Button2=2 +Button3=3 +Button4=4 +Button5=5 +Button6=6 +Button7=7 +Button8=8 + +[Vari] +Enabled=0 +R=298 +G=588 +B=110 + +[Log] +TempDelay=3 +AutoUTCOffset=0 +UTCOffset=0 +UTCOffsetMin=0 +LogLink=1 +LinkPoll=0 +LinkPTT=0 + +[MMLink] +Name= + +[LogFile] +Name= + +[Program1] +Flag=1 +Name=SSTV-PAL +File=C:\Program Files\SSTV-PAL\SSTV-Pal.exe + +[Program2] +Flag=0 +Name= +File= + +[Program3] +Flag=0 +Name= +File= + +[Program4] +Flag=0 +Name= +File= + +[Program5] +Flag=0 +Name= +File= + +[Program6] +Flag=0 +Name= +File= + +[Program7] +Flag=0 +Name= +File= + +[Program8] +Flag=2 +Name=MMTTY +File=C:\MMTTY\MMTTY.EXE + +[Dir] +HistoryFormat=0 +History= +StockFormat=0 +Stock= +RecSound= +Bitmap= +SaveBitmap= +Template= +AutoSaveDir= +AutoSave=0 +AutoSaveTime=1 +AutoSaveFormat=1 +ExtLog= + +[ExtConv] +WDEF1=%YYYY-MM-DD +WLEN1=0 +WDEF2=%HHMM +WLEN2=0 +WDEF3=%EHHMM +WLEN3=0 +WDEF4=%CALL +WLEN4=0 +WDEF5=%HIS +WLEN5=0 +WDEF6=%MY +WLEN6=0 +WDEF7=%FREQ +WLEN7=0 +WDEF8=%MODE +WLEN8=0 +WDEF9=%POWER +WLEN9=0 +WDEF10=%NAME +WLEN10=0 +WDEF11=%QTH +WLEN11=0 +WDEF12=%REM +WLEN12=0 +WDEF13=%QSL +WLEN13=0 +WDEF14=%S +WLEN14=0 +WDEF15=%R +WLEN15=0 +WDEF16=%EOD +WLEN16=0 +WDEF17= +WLEN17=0 +WDEF18= +WLEN18=0 +WDEF19= +WLEN19=0 +WDEF20= +WLEN20=0 +WDEF21= +WLEN21=0 +WDEF22= +WLEN22=0 +WDEF23= +WLEN23=0 +WDEF24= +WLEN24=0 +WDEF25= +WLEN25=0 +WDEF26= +WLEN26=0 +WDEF27= +WLEN27=0 +WDEF28= +WLEN28=0 +WDEF29= +WLEN29=0 +WDEF30= +WLEN30=0 +WDEF31= +WLEN31=0 +WDEF32= +WLEN32=0 +WDEF33= +WLEN33=0 +WDEF34= +WLEN34=0 +WDEF35= +WLEN35=0 +WDEF36= +WLEN36=0 +WDEF37= +WLEN37=0 +WDEF38= +WLEN38=0 +WDEF39= +WLEN39=0 +WDEF40= +WLEN40=0 +WDEF41= +WLEN41=0 +WDEF42= +WLEN42=0 +WDEF43= +WLEN43=0 +WDEF44= +WLEN44=0 +WDEF45= +WLEN45=0 +WDEF46= +WLEN46=0 +WDEF47= +WLEN47=0 +WDEF48= +WLEN48=0 +WDEF49= +WLEN49=0 +WDEF50= +WLEN50=0 +WDEF51= +WLEN51=0 +WDEF52= +WLEN52=0 +WDEF53= +WLEN53=0 +WDEF54= +WLEN54=0 +WDEF55= +WLEN55=0 +WDEF56= +WLEN56=0 +WDEF57= +WLEN57=0 +WDEF58= +WLEN58=0 +WDEF59= +WLEN59=0 +WDEF60= +WLEN60=0 +WDEF61= +WLEN61=0 +WDEF62= +WLEN62=0 +WDEF63= +WLEN63=0 +WDEF64= +WLEN64=0 +RDEF1=%YYYY-MM-DD +RLEN1=0 +RDEF2=%HHMM +RLEN2=0 +RDEF3=%EHHMM +RLEN3=0 +RDEF4=%CALL +RLEN4=0 +RDEF5=%HIS +RLEN5=0 +RDEF6=%MY +RLEN6=0 +RDEF7=%FREQ +RLEN7=0 +RDEF8=%MODE +RLEN8=0 +RDEF9=%POWER +RLEN9=0 +RDEF10=%NAME +RLEN10=0 +RDEF11=%QTH +RLEN11=0 +RDEF12=%REM +RLEN12=0 +RDEF13=%QSL +RLEN13=0 +RDEF14=%S +RLEN14=0 +RDEF15=%R +RLEN15=0 +RDEF16=%EOD +RLEN16=0 +RDEF17= +RLEN17=0 +RDEF18= +RLEN18=0 +RDEF19= +RLEN19=0 +RDEF20= +RLEN20=0 +RDEF21= +RLEN21=0 +RDEF22= +RLEN22=0 +RDEF23= +RLEN23=0 +RDEF24= +RLEN24=0 +RDEF25= +RLEN25=0 +RDEF26= +RLEN26=0 +RDEF27= +RLEN27=0 +RDEF28= +RLEN28=0 +RDEF29= +RLEN29=0 +RDEF30= +RLEN30=0 +RDEF31= +RLEN31=0 +RDEF32= +RLEN32=0 +RDEF33= +RLEN33=0 +RDEF34= +RLEN34=0 +RDEF35= +RLEN35=0 +RDEF36= +RLEN36=0 +RDEF37= +RLEN37=0 +RDEF38= +RLEN38=0 +RDEF39= +RLEN39=0 +RDEF40= +RLEN40=0 +RDEF41= +RLEN41=0 +RDEF42= +RLEN42=0 +RDEF43= +RLEN43=0 +RDEF44= +RLEN44=0 +RDEF45= +RLEN45=0 +RDEF46= +RLEN46=0 +RDEF47= +RLEN47=0 +RDEF48= +RLEN48=0 +RDEF49= +RLEN49=0 +RDEF50= +RLEN50=0 +RDEF51= +RLEN51=0 +RDEF52= +RLEN52=0 +RDEF53= +RLEN53=0 +RDEF54= +RLEN54=0 +RDEF55= +RLEN55=0 +RDEF56= +RLEN56=0 +RDEF57= +RLEN57=0 +RDEF58= +RLEN58=0 +RDEF59= +RLEN59=0 +RDEF60= +RLEN60=0 +RDEF61= +RLEN61=0 +RDEF62= +RLEN62=0 +RDEF63= +RLEN63=0 +RDEF64= +RLEN64=0 + +[LogSet] +TimeZone=73 +DateType=0 +UpperName=0 +UpperQTH=0 +UpperREM=0 +UpperQSL=0 +DefMyRST=0 +CopyFreq=1 +CopyHis=0 +CopyName=1 +CopyQTH=1 +CopyREM=0 +CopyQSL=0 +CopyREMB4=0 +CheckBand=1 +AutoSave=1 +THRTTY=RTY +THSSTV=STV +THTZ=0 +ClipRSTADIF=1 +FSKNR=1 +Backup=1 +TH5Fields=3,3,7,4,12,28,54 + +[RADIO] +PortName=NONE +BaudRate=4800 +BitLen=1 +Stop=1 +Parity=0 +flwXON=0 +flwCTS=0 +usePTT=0 +ByteWait=0 +Cmdxx=0 +CmdInit= +CmdRx=\$000000000F +CmdTx=\$000000010F\w10 +FileGNR= +OpenGNR=0 +PollType=0 +PollInterval=5 + +[DrawText] +Color1=255 +Color2=16711935 +Color3=65535 +Color4=16776960 +Color5=0 +Color6=0 + +[DrawBar] +Color1=0 +Color2=15790320 +Color3=255 +Color4=32768 + +[ColorSet] +Color1=16776960 +Color2=65535 +Color3=16711935 +Color4=255 +Color5=255 +Color6=16711935 +Color7=65535 +Color8=16776960 +Color9=12615935 +Color10=8454143 +Color11=16776960 +Color12=65280 +Color13=16776960 +Color14=4259584 +Color15=65535 +Color16=16711935 +Color17=255 +Color18=16711935 +Color19=65535 +Color20=65280 +Color21=255 +Color22=4227327 +Color23=65535 +Color24=16777088 +Color25=16776960 +Color26=65535 +Color27=4227327 +Color28=255 +Color29=65280 +Color30=65535 +Color31=33023 +Color32=255 + +[TextList] +Text1=CQ SSTV +Text2=%c +Text3=ur %r +Text4=ur %R-%N +Text5=73 +Text6=de %m +Text7=%D %tZ +Text8=%L %u Local +Text9= +Text10= +Text11= +Text12= +Text13= +Text14= +Text15= +Text16= + +[Text] +Grade=0 +Shadow=2 +Zero=0 +Rot=0 +Vert=0 +VertH=-6 +3D=64516 +MSG="" +DisFontSmooth=1 +Temp24=2097153 + +[Pic] +Shape=0 +Adjust=0 +LineStyle=5 +LineColor=16777215 + +[PicSel] +RTM=1 +Smooz=0 +Color=16777215 + +[ProFile] +Version=1 + +[ProFile1] +Name=ヒルベルト変換 +VcoGain=1.000000e+00 +loopOrder=1 +loopFC=1.500000e+03 +OutOrder=3 +OutFC=9.000000e+02 +DemType=2 +fqcOutOrder=3 +fqcOutFC=9.000000e+02 +fqcType=0 +fqcSmooth=2.200000e+03 +DemOff=0.000000e+00 +DemWhite=7.812500e-03 +DemBlack=7.812500e-03 +DemCalibration=0 +DemPolynomial0=-1.636467e+04 +DemPolynomial1=-1.428800e+04 +DemPolynomial2=-1.223433e+04 +DemPolynomial3=-1.019400e+04 +DemPolynomial4=-8.179333e+03 +DemPolynomial5=-6.145000e+03 +DemPolynomial6=-4.088667e+03 +DemPolynomial7=-2.063000e+03 +DemPolynomial8=-1.233333e+01 +DemPolynomial9=2.050000e+03 +DemPolynomial10=4.105000e+03 +DemPolynomial11=6.209000e+03 +DemPolynomial12=8.332667e+03 +DemPolynomial13=1.045133e+04 +DemPolynomial14=1.256500e+04 +DemPolynomial15=1.463267e+04 +DemPolynomial16=1.663133e+04 +Differentiator=0 +DiffLevel=8.000000e-01 + +[ProFile2] +Name=ゼロクロス検波 +VcoGain=1.000000e+00 +loopOrder=1 +loopFC=1.500000e+03 +OutOrder=3 +OutFC=9.000000e+02 +DemType=1 +fqcOutOrder=3 +fqcOutFC=9.000000e+02 +fqcType=0 +fqcSmooth=2.200000e+03 +DemOff=0.000000e+00 +DemWhite=7.812500e-03 +DemBlack=7.812500e-03 +DemCalibration=1 +DemPolynomial0=-1.636467e+04 +DemPolynomial1=-1.428800e+04 +DemPolynomial2=-1.223433e+04 +DemPolynomial3=-1.019400e+04 +DemPolynomial4=-8.179333e+03 +DemPolynomial5=-6.145000e+03 +DemPolynomial6=-4.088667e+03 +DemPolynomial7=-2.063000e+03 +DemPolynomial8=-1.233333e+01 +DemPolynomial9=2.050000e+03 +DemPolynomial10=4.105000e+03 +DemPolynomial11=6.209000e+03 +DemPolynomial12=8.332667e+03 +DemPolynomial13=1.045133e+04 +DemPolynomial14=1.256500e+04 +DemPolynomial15=1.463267e+04 +DemPolynomial16=1.663133e+04 +Differentiator=0 +DiffLevel=8.000000e-01 + +[ProFile3] +Name=ゼロクロス検波+微分処理 +VcoGain=1.000000e+00 +loopOrder=1 +loopFC=1.500000e+03 +OutOrder=3 +OutFC=9.000000e+02 +DemType=1 +fqcOutOrder=3 +fqcOutFC=9.000000e+02 +fqcType=0 +fqcSmooth=2.200000e+03 +DemOff=0.000000e+00 +DemWhite=7.812500e-03 +DemBlack=7.812500e-03 +DemCalibration=1 +DemPolynomial0=-1.636467e+04 +DemPolynomial1=-1.428800e+04 +DemPolynomial2=-1.223433e+04 +DemPolynomial3=-1.019400e+04 +DemPolynomial4=-8.179333e+03 +DemPolynomial5=-6.145000e+03 +DemPolynomial6=-4.088667e+03 +DemPolynomial7=-2.063000e+03 +DemPolynomial8=-1.233333e+01 +DemPolynomial9=2.050000e+03 +DemPolynomial10=4.105000e+03 +DemPolynomial11=6.209000e+03 +DemPolynomial12=8.332667e+03 +DemPolynomial13=1.045133e+04 +DemPolynomial14=1.256500e+04 +DemPolynomial15=1.463267e+04 +DemPolynomial16=1.663133e+04 +Differentiator=1 +DiffLevel=8.000000e-01 + +[ProFile4] +Name= +VcoGain=1.000000e+00 +loopOrder=1 +loopFC=1.500000e+03 +OutOrder=3 +OutFC=9.000000e+02 +DemType=2 +fqcOutOrder=3 +fqcOutFC=9.000000e+02 +fqcType=0 +fqcSmooth=2.200000e+03 +DemOff=0.000000e+00 +DemWhite=7.812500e-03 +DemBlack=7.812500e-03 +DemCalibration=0 +DemPolynomial0=-1.636467e+04 +DemPolynomial1=-1.428800e+04 +DemPolynomial2=-1.223433e+04 +DemPolynomial3=-1.019400e+04 +DemPolynomial4=-8.179333e+03 +DemPolynomial5=-6.145000e+03 +DemPolynomial6=-4.088667e+03 +DemPolynomial7=-2.063000e+03 +DemPolynomial8=-1.233333e+01 +DemPolynomial9=2.050000e+03 +DemPolynomial10=4.105000e+03 +DemPolynomial11=6.209000e+03 +DemPolynomial12=8.332667e+03 +DemPolynomial13=1.045133e+04 +DemPolynomial14=1.256500e+04 +DemPolynomial15=1.463267e+04 +DemPolynomial16=1.663133e+04 +Differentiator=0 +DiffLevel=8.000000e-01 + +[ProFile5] +Name= +VcoGain=1.000000e+00 +loopOrder=1 +loopFC=1.500000e+03 +OutOrder=3 +OutFC=9.000000e+02 +DemType=2 +fqcOutOrder=3 +fqcOutFC=9.000000e+02 +fqcType=0 +fqcSmooth=2.200000e+03 +DemOff=0.000000e+00 +DemWhite=7.812500e-03 +DemBlack=7.812500e-03 +DemCalibration=0 +DemPolynomial0=-1.636467e+04 +DemPolynomial1=-1.428800e+04 +DemPolynomial2=-1.223433e+04 +DemPolynomial3=-1.019400e+04 +DemPolynomial4=-8.179333e+03 +DemPolynomial5=-6.145000e+03 +DemPolynomial6=-4.088667e+03 +DemPolynomial7=-2.063000e+03 +DemPolynomial8=-1.233333e+01 +DemPolynomial9=2.050000e+03 +DemPolynomial10=4.105000e+03 +DemPolynomial11=6.209000e+03 +DemPolynomial12=8.332667e+03 +DemPolynomial13=1.045133e+04 +DemPolynomial14=1.256500e+04 +DemPolynomial15=1.463267e+04 +DemPolynomial16=1.663133e+04 +Differentiator=0 +DiffLevel=8.000000e-01 + +[ProFile6] +Name= +VcoGain=1.000000e+00 +loopOrder=1 +loopFC=1.500000e+03 +OutOrder=3 +OutFC=9.000000e+02 +DemType=2 +fqcOutOrder=3 +fqcOutFC=9.000000e+02 +fqcType=0 +fqcSmooth=2.200000e+03 +DemOff=0.000000e+00 +DemWhite=7.812500e-03 +DemBlack=7.812500e-03 +DemCalibration=0 +DemPolynomial0=-1.636467e+04 +DemPolynomial1=-1.428800e+04 +DemPolynomial2=-1.223433e+04 +DemPolynomial3=-1.019400e+04 +DemPolynomial4=-8.179333e+03 +DemPolynomial5=-6.145000e+03 +DemPolynomial6=-4.088667e+03 +DemPolynomial7=-2.063000e+03 +DemPolynomial8=-1.233333e+01 +DemPolynomial9=2.050000e+03 +DemPolynomial10=4.105000e+03 +DemPolynomial11=6.209000e+03 +DemPolynomial12=8.332667e+03 +DemPolynomial13=1.045133e+04 +DemPolynomial14=1.256500e+04 +DemPolynomial15=1.463267e+04 +DemPolynomial16=1.663133e+04 +Differentiator=0 +DiffLevel=8.000000e-01 + +[ProFile7] +Name= +VcoGain=1.000000e+00 +loopOrder=1 +loopFC=1.500000e+03 +OutOrder=3 +OutFC=9.000000e+02 +DemType=2 +fqcOutOrder=3 +fqcOutFC=9.000000e+02 +fqcType=0 +fqcSmooth=2.200000e+03 +DemOff=0.000000e+00 +DemWhite=7.812500e-03 +DemBlack=7.812500e-03 +DemCalibration=0 +DemPolynomial0=-1.636467e+04 +DemPolynomial1=-1.428800e+04 +DemPolynomial2=-1.223433e+04 +DemPolynomial3=-1.019400e+04 +DemPolynomial4=-8.179333e+03 +DemPolynomial5=-6.145000e+03 +DemPolynomial6=-4.088667e+03 +DemPolynomial7=-2.063000e+03 +DemPolynomial8=-1.233333e+01 +DemPolynomial9=2.050000e+03 +DemPolynomial10=4.105000e+03 +DemPolynomial11=6.209000e+03 +DemPolynomial12=8.332667e+03 +DemPolynomial13=1.045133e+04 +DemPolynomial14=1.256500e+04 +DemPolynomial15=1.463267e+04 +DemPolynomial16=1.663133e+04 +Differentiator=0 +DiffLevel=8.000000e-01 + +[ProFile8] +Name= +VcoGain=1.000000e+00 +loopOrder=1 +loopFC=1.500000e+03 +OutOrder=3 +OutFC=9.000000e+02 +DemType=2 +fqcOutOrder=3 +fqcOutFC=9.000000e+02 +fqcType=0 +fqcSmooth=2.200000e+03 +DemOff=0.000000e+00 +DemWhite=7.812500e-03 +DemBlack=7.812500e-03 +DemCalibration=0 +DemPolynomial0=-1.636467e+04 +DemPolynomial1=-1.428800e+04 +DemPolynomial2=-1.223433e+04 +DemPolynomial3=-1.019400e+04 +DemPolynomial4=-8.179333e+03 +DemPolynomial5=-6.145000e+03 +DemPolynomial6=-4.088667e+03 +DemPolynomial7=-2.063000e+03 +DemPolynomial8=-1.233333e+01 +DemPolynomial9=2.050000e+03 +DemPolynomial10=4.105000e+03 +DemPolynomial11=6.209000e+03 +DemPolynomial12=8.332667e+03 +DemPolynomial13=1.045133e+04 +DemPolynomial14=1.256500e+04 +DemPolynomial15=1.463267e+04 +DemPolynomial16=1.663133e+04 +Differentiator=0 +DiffLevel=8.000000e-01 + +[CWMenu] +Menus=7 +M1=QSL 73 TU +M2=NR? AGN +M3=QRZ? +M4=UR %N %N +M5=%c de %m +M6=73 TU +M7=VVV + +[RadioMenu] +Menus=5 +Cap1=7.033 LSB (FT847) +Cmd1=\$0070330001\w10\$0000000007\w10 +Cap2=14.230 USB (FT847) +Cmd2=\$0142300001\w10\$0100000007\w10 +Cap3=21.340 USB (FT847) +Cmd3=\$0213400001\w10\$0100000007\w10 +Cap4=28.680 USB (FT847) +Cmd4=\$0286800001\w10\$0100000007\w10 +Cap5=144.450 USB (FT847) +Cmd5=\$1444500001\w10\$0100000007\w10 + diff --git a/Mmsstv.map b/Mmsstv.map new file mode 100644 index 0000000..9619249 --- /dev/null +++ b/Mmsstv.map @@ -0,0 +1,6 @@ + + Start Length Name Class + 0001:00401000 0003CAF44H _TEXT CODE + 0002:007CC000 000048450H _DATA DATA + 0003:00814450 000022B74H _BSS BSS + 0004:00000000 0000000F8H _TLS TLS diff --git a/Mmsstv.res b/Mmsstv.res new file mode 100644 index 0000000..66d13f0 Binary files /dev/null and b/Mmsstv.res differ diff --git a/Mmsstv.tds b/Mmsstv.tds new file mode 100644 index 0000000..984692b Binary files /dev/null and b/Mmsstv.tds differ diff --git a/Mmsstv_Icon.ico b/Mmsstv_Icon.ico new file mode 100644 index 0000000..8559817 Binary files /dev/null and b/Mmsstv_Icon.ico differ diff --git a/NVCG.txt b/NVCG.txt new file mode 100644 index 0000000..913c95e --- /dev/null +++ b/NVCG.txt @@ -0,0 +1,86 @@ +The NVCG SSTV contest is sponsored by NVCG , Nishi Nippon Visual Communication Group. The chief organizer of the contest is JA6AP, the president of NVCG . + + See http://www.tim.hi-ho.ne.jp/ja6ap/english/index.html + + +%%%Japanese ========================================== + 第12回西日本画像通信グループ(NVCG)主催SSTVコンテスト規約 + + http://www.tim.hi-ho.ne.jp/ja6ap/nvcg/index.htm + +主催 +~~~~~ + 西日本画像通信グループ (主催者 JI6LTS 金子孝憲) + +実施期間 +~~~~~~~~~~ + 2010 年:日本時間 7 月10 日(土)09:00〜7 月19 日(月)09:00 まで暦日10 日間 + 国際標準時 UTC 7 月10 日(土)00:00〜7 月18 日(日)24:00 UTC まで 9 日間 + +1) 参加資格 +~~~~~~~~~~~~~ + アマチュア無線の資格を持ち、SSTV の電波型式の免許を受けている国内外のアマチュア無線局 + +運用周波数 +~~~~~~~~~~~~ + 自局に免許された3.5MHz〜50MHz の周波数帯(電波法及び総務省令に定められた周波数帯) + +2) コンテストナンバー +~~~~~~~~~~~~~~~~~~~~~~ + ・西日本画像通信グループのメンバー局(NVCG の登録会員局)は「RSV」に「M」を付加する。 + ・メンバー以外の局は通常の「RSV」のみを相互に送る。 + ・ポイント:NVCG メンバー局との交信は2 点 一般局の交信は1 点とする。 + 注)イ、NVCG メンバー局と一般局の交信: NVCG メンバー局…1 点 一般局…2 点 +   ロ、一般局相互の交信:ともに…1 点 +   ハ、NVCG メンバー局相互の交信:NVCG メンバー局、ともに…2 点 + +3) コンテスト期間を通じて、すべての相手局は1 交信のみ有効とする。 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +4) マルチ +~~~~~~~~~ + 周波数帯に関係なく以下の項目をマルチとしてカウントする。 + ・すべてのプリフィックスの異なる局と交信した最初の1局をマルチとしてカウントする。 +  得点: 総ポイント×マルチポイント=総得点数 + +5) エントリー部門 +~~~~~~~~~~~~~~~~~~ + 国内局部門・海外局部門 の2部門とする。 + +6) 入賞 +~~~~~~~~ + ・国内部門:1〜3 位に 楯を贈る。 + ・海外部門 : 1〜3 位に楯を贈る。 + +7) LOG & SUMMARY +~~~~~~~~~~~~~~~~~~~~~~ +ア、 NVCG が推奨しているログとサマリーのフォーマット記録様式のもの。(記録の集計を自動的に行うのでたいへん便利です) + ダウンロードはつぎのところから +    http://www.roy.hi-ho.ne.jp/shimamura/ + +イ、その他の様式 +    JASTA,JARL の形式のものでもよい。 + +8) 提出先 +~~~~~~~~~~ + E-Mail は sstv-contest-nvcg@wak.bbiq.jp + + 郵送は 〒814-0003 福岡県福岡市早良区城西3-1-6 JA6GN 徳安 進 + +9) 締切り +~~~~~~~~~ + 2010年8月31日(日)暦日内に発信のE-Mail または郵便消印のもの。 + +10)注意事項 +~~~~~~~~~~~~~ +イ、コンテストルール違反、サマリーシートおよびマルチに計上する交信ログの不備は失格。 +ロ、 同一局との交信は周波数帯を問わずコンテスト期間中1 交信のみ有効。 +ハ、 クロスバンドおよびラウンドQSO による得点は無効。 +ニ、 同時に2 波以上の電波の発射による交信での得点は無効。 +ホ、コンテストに使用する画像は特に指定はしない。 + +11)結果の発表 +~~~~~~~~~~~~~~~ + NVCG,QTC Japan のホームページ及びCQ 誌、JASTA 等で発表する。 + + +上記の通りコンテストを実施いたしますので、奮ってご参加下さい。 diff --git a/Option.cpp b/Option.cpp new file mode 100644 index 0000000..91a735b --- /dev/null +++ b/Option.cpp @@ -0,0 +1,1231 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "Option.h" +#include "Main.h" +#include "FreqDisp.h" +#include "radioset.h" +#include "LogFile.h" +#include "ClockAdj.h" +#include "LinearDs.h" +#include "MacroKey.h" +#include "TextEdit.h" +//--------------------------------------------------------------------- +#pragma resource "*.dfm" +int PageIndex = 0; +//--------------------------------------------------------------------- +__fastcall TOptionDlg::TOptionDlg(TComponent* AOwner) + : TForm(AOwner) +{ + m_DisEvent = 1; + FormStyle = ((TForm *)AOwner)->FormStyle; + Font->Name = ((TForm *)AOwner)->Font->Name; + Font->Charset = ((TForm *)AOwner)->Font->Charset; + pDem = NULL; + if( MsgEng ){ + Caption = "Setup MMSSTV"; + TabDem->Caption = "RX"; + TabTx->Caption = "TX"; + TabMisc->Caption = "Misc"; + CancelBtn->Caption = "Cancel"; + + RGDemType->Caption = "Demodulating method"; + RGDemType->Items->Strings[1] = "Zero crossing"; + RGDemType->Items->Strings[2] = "Hilbert T.F."; + + GBCROSS->Caption = "Zero crossing"; + LCORDER->Caption = "Order"; + + CBDiff->Caption = "Differentiator"; + LLoopOrder->Caption = "Order"; + LOutOrder->Caption = "Order"; + RGRBuf->Caption = "Rx buffer"; + GBTemp->Caption = "Template"; + GBOut->Caption = "Digital output level"; + GrpCard->Caption = "Sound Card"; + GBHMax->Caption = "History max."; + LFFTB->Caption = "Background"; + LFFT->Caption = "Signals"; + LFFTT->Caption = "Trails"; + LFFTS->Caption = "Sync marker"; + LFFTF->Caption = "Freq marker"; + RGMSync->Caption = "Auto start"; + CBAStop->Caption = "Auto stop"; + CBARestart->Caption = "Auto restart"; + CBASync->Caption = "Auto resync"; + CBASlant->Caption = "Auto slant"; + CBTxFixed->Caption = "Fixed mode"; + GB2->Caption = "Level converter"; + CBCalWay->Caption = "Polynomial"; + SBTest->Caption = "Calibration"; + LJPEGQ->Caption = "Quality"; + RGSLvl->Caption = "Squelch level"; + RGSLvl->Items->Strings[0] = "Lowest"; + RGSLvl->Items->Strings[1] = "Lower"; + RGSLvl->Items->Strings[2] = "Higher"; + RGSLvl->Items->Strings[3] = "Highest"; + IDDEC->Caption = "Decode FSKID"; + IDFSK->Caption = "Encode FSKID"; + PTTLock->Caption = "Exclusive lock"; + + RGLoopBack->Caption = "Loop back"; +// RGLoopBack->Items->Strings[0] = "OFF"; + RGLoopBack->Items->Strings[1] = "Internal"; + RGLoopBack->Items->Strings[2] = "External (full-duplex)"; + + RGRxBPF->Items->Strings[1] = "Broad"; + RGRxBPF->Items->Strings[2] = "Sharp"; + RGRxBPF->Items->Strings[3] = "Very sharp"; + + SoundPriority->Caption = "Priority"; + SoundPriority->Items->Strings[0] = "Normal"; + SoundPriority->Items->Strings[1] = "Higher"; + SoundPriority->Items->Strings[2] = "Highest"; + SoundPriority->Items->Strings[3] = "Critical"; + + Source->Caption = "Source"; + Source->Items->Strings[0] = "Mono"; + Source->Items->Strings[1] = "Left"; + Source->Items->Strings[2] = "Right"; + MemWin->Caption = "Save window location"; + + AppPriority->Caption = "Priority of MMSSTV"; + AppPriority->Items->Strings[0] = "Normal"; + AppPriority->Items->Strings[1] = "Higher"; + + CB24->Caption = "Always use DIB"; +// AppPriority->Items->Strings[2] = "Highest"; + } + TxFifo->Items->Assign(RxFifo->Items); + CWIDFreq->Items->Assign(TuneFreq->Items); + pllOutFC->Items->Assign(pllLoopFC->Items); + crossOutFC->Items->Assign(pllLoopFC->Items); + m_TestMode = 0; + m_BuffCal = 1.0; + + CWave *pWave = &Mmsstv->pSound->Wave; + pWave->GetDeviceName(); + for( int i = 0; i < pWave->m_InDevs; i++ ){ + if( !pWave->m_tInDevName[i].IsEmpty() ){ + DevNo->Items->Add(pWave->m_tInDevName[i]); + } + } + for( int i = 0; i < pWave->m_OutDevs; i++ ){ + if( !pWave->m_tOutDevName[i].IsEmpty() ){ + DevNoOut->Items->Add(pWave->m_tOutDevName[i]); + } + } + + m_MMListW.QueryList("MMW"); + for( int i = 0; i < m_MMListW.GetCount(); i++ ){ + DevNo->Items->Add(m_MMListW.GetItemName(i)); + } + DevNo->DropDownCount = DevNo->Items->Count; + DevNoOut->DropDownCount = DevNoOut->Items->Count; +} +//--------------------------------------------------------------------------- +int __fastcall TOptionDlg::IsMMW(LPCSTR p) +{ + if( !p ) return -1; + + for( int i = 0; i < m_MMListW.GetCount(); i++ ){ + if( !strcmp(p, m_MMListW.GetItemName(i)) ) return i; + } + return -1; +} +//--------------------------------------------------------------------------- +void __fastcall TOptionDlg::SetPageIndex(int n) +{ + PageIndex = n; +} +//--------------------------------------------------------------------------- +void __fastcall TOptionDlg::UpdateUI(void) +{ + char bf[128]; + + sprintf(bf, "%.2lf", m_TxSampOff); + TxSampOff->Text = bf; + switch(RGDemType->ItemIndex){ + case 0: + GBPLL->Visible = TRUE; + GBCROSS->Visible = FALSE; + GBPLL->Enabled = TRUE; + SetGroupEnabled(GBPLL); + break; + case 1: + GBPLL->Visible = FALSE; + GBCROSS->Visible = TRUE; + break; + default: + GBPLL->Visible = TRUE; + GBCROSS->Visible = FALSE; + GBPLL->Enabled = FALSE; + SetGroupEnabled(GBPLL); + break; + } + switch(RGcrossType->ItemIndex){ + case 0: + GBCOI->Enabled = TRUE; + GBCOF->Enabled = FALSE; + break; + case 1: + GBCOI->Enabled = FALSE; + GBCOF->Enabled = TRUE; + break; + default: + GBCOI->Enabled = FALSE; + GBCOF->Enabled = FALSE; + break; + } + SetGroupEnabled(GBCOI); + SetGroupEnabled(GBCOF); + int f = CBCalWay->Checked ? FALSE : TRUE; + LOff->Enabled = f; + L1500->Enabled = f; + L2300->Enabled = f; + Off1900->Enabled = f; + Max1500->Enabled = f; + Max2300->Enabled = f; + + VEdit->Visible = (RGV->ItemIndex == 1) ? TRUE : FALSE; + CBASlant->Enabled = RGRBuf->ItemIndex ? TRUE : FALSE; + TxBpfTap->Enabled = CBTXBPF->Checked; + DispTxBpf->Enabled = CBTXBPF->Checked; + TxLpfFreq->Enabled = CBTXLPF->Checked; + + f = IsMMW(AnsiString(DevNo->Text).c_str()) < 0; //ja7ude 0428 + GB1->Enabled = f; + SetGroupEnabled(GB1); + Source->Enabled = f; + Label6->Enabled = f; + DevNoOut->Enabled = f; + + CBSTX->Visible = (Source->ItemIndex != 0); +} + +int __fastcall TOptionDlg::Execute(CSSTVDEM *fp, CSSTVMOD *mp) +{ + pDem = fp; + m_ColorChange = 0; + + RGDemType->ItemIndex = fp->m_Type; + char bf[128]; + sprintf(bf, "%.2lf", sys.m_SampFreq); + EditSamp->Text = bf; + m_TxSampOff = sys.m_TxSampOff; + WinFont->Text = sys.m_WinFontName; + m_WinFontCharset = sys.m_WinFontCharset; + m_WinFontStyle = sys.m_WinFontStyle; + MemWin->Checked = sys.m_MemWindow; + FontAdj->Text = sys.m_FontAdjSize; + + CBDiff->Checked = sys.m_Differentiator; + TBDiff->Position = ((sys.m_DiffLevelP * 10) + 0.5); + pllVCOGain->Text = fp->m_pll.m_vcogain; + pllLoopOrder->Text = fp->m_pll.m_loopOrder; + pllLoopFC->Text = fp->m_pll.m_loopFC; + pllOutOrder->Text = fp->m_pll.m_outOrder; + pllOutFC->Text = fp->m_pll.m_outFC; + + RGcrossType->ItemIndex = fp->m_fqc.m_Type; + crossSmooz->Text = fp->m_fqc.m_SmoozFq; + crossOutOrder->Text = fp->m_fqc.m_outOrder; + crossOutFC->Text = fp->m_fqc.m_outFC; + + RGRxBPF->ItemIndex = fp->m_bpf; + RGSLvl->ItemIndex = fp->m_SenseLvl; + + PCLow->Color = sys.m_ColorLow; + PCHigh->Color = sys.m_ColorHigh; + PCFFTB->Color = sys.m_ColorFFTB; + PCFFT->Color = sys.m_ColorFFT; + PCFFTStg->Color = sys.m_ColorFFTStg; + PCSync->Color = sys.m_ColorFFTSync; + PCFreq->Color = sys.m_ColorFFTFreq; + + PortName->Text = sys.m_TxRxName; + PTTLock->Checked = sys.m_TxRxLock; + CBRTS->Checked = sys.m_RTSonRX; + + EditCall->Text = sys.m_Call; + RGLoopBack->ItemIndex = sys.m_echo; + + CBTXBPF->Checked = mp->m_bpf; + CBTXLPF->Checked = mp->m_lpf; + TxLpfFreq->Text = mp->m_lpffq; + + TxBpfTap->Text = mp->m_bpftap; + + TBOutLvl->Position = int(mp->m_outgain*64.0/30000.0); + m_OutGain = Mmsstv->pMod->m_outgain; + + RxFifo->Text = sys.m_SoundFifoRX; + TxFifo->Text = sys.m_SoundFifoTX; + SoundPriority->ItemIndex = sys.m_SoundPriority; + + { + AnsiString as = sys.m_SoundDevice.c_str(); + LPSTR p, t; + + p = StrDlm(t, as.c_str()); + int dd; + if( ATOI(dd, t) ){ + switch(dd){ + case -1: + DevNo->Text = "Default"; + break; + case -2: + break; + default: + DevNo->Text = t; + break; + } + } + else { + DevNo->Text = t; + } + + p = SkipSpace(p); + if( *p ) StrDlm(t, p); + + if( ATOI(dd, t) ){ + switch(dd){ + case -1: + DevNoOut->Text = "Default"; + break; + case -2: + break; + default: + DevNoOut->Text = t; + break; + } + } + else if( IsMMW(t) < 0 ){ + DevNoOut->Text = t; + } + else { + DevNoOut->Text = ""; + } + } + + Source->ItemIndex = sys.m_SoundStereo; + CBSTX->Checked = sys.m_StereoTX; + RGMSync->ItemIndex = fp->m_MSync; + CBAStop->Checked = sys.m_AutoStop; + CBARestart->Checked = fp->m_SyncRestart; + CBASync->Checked = sys.m_AutoSync; + CBASlant->Checked = Mmsstv->KRSA->Checked; + JPEGQ->Text = sys.m_JPEGQuality; + CBVari->Checked = mp->m_VariOut; + CB24->Checked = sys.m_UseB24; + + if( (PageIndex >= 0) && (PageIndex < Page->PageCount) ){ + if( Page->Pages[PageIndex]->TabVisible == FALSE ){ + PageIndex = 0; + } + Page->ActivePage = Page->Pages[PageIndex]; + } + Off1900->Text = sys.m_DemOff; + if( sys.m_DemBlack > 0.000001 ){ + Max1500->Text = int((128 / sys.m_DemBlack)+0.5); + } + else { + Max1500->Text = 16384; + } + if( sys.m_DemWhite > 0.000001 ){ + Max2300->Text = -int((128 / sys.m_DemWhite)+0.5); + } + else { + Max2300->Text = 16384; + } + CBCalWay->Checked = sys.m_DemCalibration; + + HistMax->Text = sys.m_HistMax; + RGRBuf->ItemIndex = sys.m_UseRxBuff; + TuneFreq->Text = mp->m_TuneFreq; + TrigTXTime->Text = sys.m_TuneTXTime; + CBAT->Checked = sys.m_TuneSat; + + switch(sys.m_CWID){ + case 0: + IDOFF->Checked = TRUE; + break; + case 1: + IDCW->Checked = TRUE; + break; + case 2: + IDMMV->Checked = TRUE; + break; + } + TBCW->Position = sys.m_CWIDWPM - 10; + CWIDFreq->Text = sys.m_CWIDFreq; + CWIDText->Text = sys.m_CWIDText; + MMVID->Text = sys.m_MMVID; + IDOFFClick(NULL); + + IDDEC->Checked = fp->m_fskdecode; + IDFSK->Checked = sys.m_TXFSKID; + CBTxFixed->Checked = sys.m_FixedTxMode; + + RGV->ItemIndex = sys.m_VOX; + m_VOXSound = sys.m_VOXSound.c_str(); + + AppPriority->ItemIndex = sys.m_Priority; + + UpdateUI(); + m_DisEvent = 0; + int r = ShowModal(); + if( sys.m_TestDem ){ + mp->m_outgain = m_OutGain; + sys.m_TestDem = 0; + mp->m_vco.SetSampleFreq(sys.m_SampFreq+sys.m_TxSampOff); + fp->m_SyncMode = 0; + } + if( r == IDOK ){ + double d; + int dd; + + sys.m_UseB24 = CB24->Checked; + + sscanf(AnsiString(EditSamp->Text).c_str(), "%lf", &d); //ja7ude 0428 + if( (d >= 5000.0) && (d <= CLOCKMAX) ){ + sys.m_SampFreq = d; + } + sys.m_TxSampOff = m_TxSampOff; + + sys.m_WinFontName = WinFont->Text; + sys.m_WinFontCharset = m_WinFontCharset; + sys.m_WinFontStyle = m_WinFontStyle; + + if( sscanf(AnsiString(FontAdj->Text).c_str(), "%ld", &dd) == 1 ){ //ja7ude 0428 + sys.m_FontAdjSize = dd; + } + + sys.m_echo = RGLoopBack->ItemIndex; + + + sys.m_RTSonRX = CBRTS->Checked; + sys.m_TxRxLock = PTTLock->Checked; + sys.m_TxRxName = PortName->Text; + if( (PortName->Text != "NONE") && !strcmp(AnsiString(PortName->Text).c_str(), RADIO.StrPort) ){ //ja7ude 0428 + strcpy(RADIO.StrPort, "NONE"); + } + + char bf[MLCALL+1]; + StrCopy(bf, AnsiString(EditCall->Text).c_str(), MLCALL); //ja7ude 0428 + jstrupr(bf); clipsp(bf); + sys.m_Call = SkipSpace(bf); + + mp->m_bpf = CBTXBPF->Checked; + mp->m_lpf = CBTXLPF->Checked; + sscanf(AnsiString(TxLpfFreq->Text).c_str(), "%lf", &d); //ja7ude 0428 + if( (d >= 100.0) && (d <= 3000.0) ){ + mp->m_lpffq = d; + } + sscanf(AnsiString(TxBpfTap->Text).c_str(), "%u", &dd); //ja7ude 0428 + if( (dd >= 2) && (dd <= TAPMAX) ){ + mp->m_bpftap = dd; + } + mp->CalcFilter(); + mp->m_outgain = TBOutLvl->Position*30000.0/64.0; + if( mp->m_outgain >= 30000 ) mp->m_outgain = 30000; + mp->InitGain(); + mp->m_VariOut = CBVari->Checked; + + if( sscanf(AnsiString(RxFifo->Text).c_str(), "%u", &dd) == 1 ){ //ja7ude 0428 + if( (dd >= 4) && (dd <= WAVE_FIFO_MAX) ){ + sys.m_SoundFifoRX = dd; + } + } + if( sscanf(AnsiString(TxFifo->Text).c_str(), "%u", &dd) == 1 ){ //ja7ude 0428 + if( (dd >= 4) && (dd <= WAVE_FIFO_MAX) ){ + sys.m_SoundFifoTX = dd; + } + } + sys.m_SoundPriority = SoundPriority->ItemIndex; + AnsiString in = DevNo->Text.c_str(); + if( !strcmpi(in.c_str(), "default") ) in = "-1"; + AnsiString out = DevNoOut->Text.c_str(); + if( !strcmpi(out.c_str(), "default") ) out = "-1"; + if( in != out ){ + AnsiString as; + if( IsMMW(in.c_str()) < 0 ){ + as += "\x22"; + as += in; + as += "\x22,\x22"; + as += out; + as += "\x22"; + } + else { + as += "\x22"; + as += in; + as += "\x22"; + } + sys.m_SoundDevice = as; + } + else { + AnsiString as; + as += "\x22"; + as += in; + as += "\x22"; + sys.m_SoundDevice = as; + } + + sys.m_SoundStereo = Source->ItemIndex; + sys.m_StereoTX = CBSTX->Checked; + + sys.m_Differentiator = CBDiff->Checked; + sys.m_DiffLevelP = double(TBDiff->Position)/10.0; + sys.m_DiffLevelM = sys.m_DiffLevelP / 3.0; + if( sscanf(AnsiString(pllVCOGain->Text).c_str(), "%lf", &d) == 1 ){ //ja7ude 0428 + if( d > 0.0 ) fp->m_pll.SetVcoGain(d); + } + if( sscanf(AnsiString(pllLoopOrder->Text).c_str(), "%u", &dd) == 1 ){ //ja7ude 0428 + if( (dd > 0) && (dd <= 32) ) fp->m_pll.m_loopOrder = dd; + } + if( sscanf(AnsiString(pllLoopFC->Text).c_str(), "%lf", &d) == 1 ){ //ja7ude 0428 + if( d > 0.0 ) fp->m_pll.m_loopFC = d; + } + if( sscanf(AnsiString(pllOutOrder->Text).c_str(), "%u", &dd) == 1 ){ //ja7ude 0428 + if( (dd > 0) && (dd <= 32) ) fp->m_pll.m_outOrder = dd; + } + if( sscanf(AnsiString(pllOutFC->Text).c_str(), "%lf", &d) == 1 ){ //ja7ude 0428 + if( d > 0.0 ) fp->m_pll.m_outFC = d; + } + fp->m_pll.MakeLoopLPF(); + fp->m_pll.MakeOutLPF(); + + if( sscanf(AnsiString(crossOutOrder->Text).c_str(), "%u", &dd) == 1 ){ //ja7ude 0428 + if( (dd > 0) && (dd <= 32) ) fp->m_fqc.m_outOrder = dd; + } + if( sscanf(AnsiString(crossOutFC->Text).c_str(), "%lf", &d) == 1 ){ //ja7ude 0428 + if( d > 0.0 ) fp->m_fqc.m_outFC = d; + } + fp->m_fqc.m_Type = RGcrossType->ItemIndex; + if( sscanf(AnsiString(crossSmooz->Text).c_str(), "%lf", &d) == 1 ){ //ja7ude 0428 + if( (d >= 500.0) && (d <= 8000.0) ){ + fp->m_fqc.m_SmoozFq = d; + } + } + fp->m_fqc.CalcLPF(); + fp->m_Type = RGDemType->ItemIndex; + + if( sscanf(AnsiString(Off1900->Text).c_str(), "%u", &dd) == 1 ){ //ja7ude 0428 + sys.m_DemOff = dd; + } + if( sscanf(AnsiString(Max1500->Text).c_str(), "%lf", &d) == 1 ){ //ja7ude 0428 + if( d > 0.000001 ){ + sys.m_DemBlack = 128.0 / d; + } + } + if( sscanf(AnsiString(Max2300->Text).c_str(), "%lf", &d) == 1 ){ //ja7ude 0428 + d = -d; + if( d > 0.000001 ){ + sys.m_DemWhite = 128.0 / d; + } + } + sys.m_DemCalibration = CBCalWay->Checked; + + if( sscanf(AnsiString(HistMax->Text).c_str(), "%u", &dd) == 1 ){ //ja7ude 0428 + if( (dd > 1) && (dd <= 256) ){ + sys.m_HistMax = dd; + } + } + if( sscanf(AnsiString(TuneFreq->Text).c_str(), "%u", &dd) == 1 ){ //ja7ude 0428 + if( (dd >= 100) && (dd <= 3000) ){ + mp->m_TuneFreq = dd; + } + } + if( sscanf(AnsiString(TrigTXTime->Text).c_str(), "%d", &dd) == 1 ){ //ja7ude 0428 + sys.m_TuneTXTime = dd; + } + sys.m_TuneSat = CBAT->Checked; + + sys.m_UseRxBuff = RGRBuf->ItemIndex; + fp->OpenCloseRxBuff(); + sys.m_ColorLow = PCLow->Color; + sys.m_ColorHigh = PCHigh->Color; + sys.m_ColorFFTB = PCFFTB->Color; + sys.m_ColorFFT = PCFFT->Color; + sys.m_ColorFFTStg = PCFFTStg->Color; + sys.m_ColorFFTSync = PCSync->Color; + sys.m_ColorFFTFreq = PCFreq->Color; + + if( IDCW->Checked ){ + sys.m_CWID = 1; + } + else if( IDMMV->Checked ){ + sys.m_CWID = 2; + } + else { + sys.m_CWID = 0; + } + sys.m_CWIDWPM = TBCW->Position + 10; + sys.m_CWIDText = CWIDText->Text.c_str(); + sys.m_MMVID = MMVID->Text.c_str(); + if( sscanf(AnsiString(CWIDFreq->Text).c_str(), "%u", &dd) == 1 ){ //ja7ude 0521 + sys.m_CWIDFreq = dd; + } + sys.m_TXFSKID = IDFSK->Checked; + fp->m_fskdecode = IDDEC->Checked; + + if( sscanf(AnsiString(JPEGQ->Text).c_str(), "%u", &dd) == 1 ){ //ja7ude 0521 + if( (dd >= 0) && (dd <= 100) ){ + sys.m_JPEGQuality = dd; + } + } + + fp->SetBPF(RGRxBPF->ItemIndex); + fp->m_MSync = RGMSync->ItemIndex; + fp->m_SyncRestart = CBARestart->Checked; + fp->m_SenseLvl = RGSLvl->ItemIndex; + fp->SetSenseLvl(); + Mmsstv->KRSA->Checked = CBASlant->Checked; + + sys.m_MemWindow = MemWin->Checked; + sys.m_AutoStop = CBAStop->Checked; + sys.m_AutoSync = CBASync->Checked; + sys.m_FixedTxMode = CBTxFixed->Checked; + + sys.m_VOX = RGV->ItemIndex; + sys.m_VOXSound = m_VOXSound.c_str(); + + sys.m_Priority = AppPriority->ItemIndex; + } + else { + r = FALSE; + } + PageIndex = GetActiveIndex(Page); + return r; +} +//--------------------------------------------------------------------------- +void __fastcall TOptionDlg::DispTxBpfClick(TObject *Sender) +{ + double HBPF[TAPMAX+1]; + + int tap; + sscanf(AnsiString(TxBpfTap->Text).c_str(), "%u", &tap); //ja7ude 0521 + if( !tap ) tap = 2; + + int lfq = 700 + g_dblToneOffset; + int hfq = 2700 + g_dblToneOffset; + if( lfq < 100 ){ + MakeFilter(HBPF, tap, ffLPF, SampFreq, hfq, hfq, 40, 1.0); + } + else { + MakeFilter(HBPF, tap, ffBPF, SampFreq, lfq, hfq, 40, 1.0); + } + + TFreqDispDlg *pBox = new TFreqDispDlg(this); + pBox->Execute(HBPF, tap, 1); + delete pBox; +} +//--------------------------------------------------------------------------- +void __fastcall TOptionDlg::DispLoopLPFClick(TObject *Sender) +{ + int order; + double fc; + + sscanf(AnsiString(pllLoopFC->Text).c_str(), "%lf", &fc); //ja7ude 0521 + if( fc > 0.0 ){ + sscanf(AnsiString(pllLoopOrder->Text).c_str(), "%u", &order); //ja7ude 0521 + if( (order >= 1) && (order <= 32) ){ + CIIR iir; + iir.MakeIIR(fc, SampFreq, order, 0, 1.0); + TFreqDispDlg *pBox = new TFreqDispDlg(this); + pBox->Execute(&iir, DemOver+1, 4000); + delete pBox; + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TOptionDlg::DispOutLPFClick(TObject *Sender) +{ + int order; + double fc; + + sscanf(AnsiString(pllOutFC->Text).c_str(), "%lf", &fc); //ja7ude 0521 + if( fc > 0.0 ){ + sscanf(AnsiString(pllOutOrder->Text).c_str(), "%u", &order); //ja7ude 0521 + if( (order >= 1) && (order <= 32) ){ + CIIR iir; + iir.MakeIIR(fc, SampFreq, order, 0, 1.0); + TFreqDispDlg *pBox = new TFreqDispDlg(this); + pBox->Execute(&iir, DemOver+1, 4000); + delete pBox; + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TOptionDlg::DispCrossOutLPFClick(TObject *Sender) +{ + int order; + double fc; + + sscanf(AnsiString(crossOutFC->Text).c_str(), "%lf", &fc); //ja7ude 0521 + if( fc > 0.0 ){ + sscanf(AnsiString(crossOutOrder->Text).c_str(), "%u", &order); //ja7ude 0521 + if( (order >= 1) && (order <= 32) ){ + CIIR iir; + iir.MakeIIR(fc, SampFreq, order, 0, 1.0); + TFreqDispDlg *pBox = new TFreqDispDlg(this); + pBox->Execute(&iir, DemOver+1, 4000); + delete pBox; + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TOptionDlg::SetCustomColor(void) +{ + TColorDialog *pDialog = Mmsstv->ColorDialog; + InitCustomColor(pDialog); + AddCustomColor(pDialog, PCLow->Color); + AddCustomColor(pDialog, PCHigh->Color); + AddCustomColor(pDialog, PCFFTB->Color); + AddCustomColor(pDialog, PCFFT->Color); + AddCustomColor(pDialog, PCFFTStg->Color); + AddCustomColor(pDialog, PCSync->Color); + AddCustomColor(pDialog, PCFreq->Color); +} +//--------------------------------------------------------------------------- +void __fastcall TOptionDlg::PortNameChange(TObject *Sender) +{ + if( m_DisEvent ) return; + + COMM.change = 1; +} +//--------------------------------------------------------------------------- +void __fastcall TOptionDlg::WinFontBtnClick(TObject *Sender) +{ + TFontDialog *pDialog = Mmsstv->FontDialog; + pDialog->Font->Name = WinFont->Text; + pDialog->Font->Charset = m_WinFontCharset; + TFontStyles fs = Code2FontStyle(m_WinFontStyle); + pDialog->Font->Style = fs; + NormalWindow(this); + SetDisPaint(); + if( pDialog->Execute() == TRUE ){ + WinFont->Text = pDialog->Font->Name; + m_WinFontCharset = pDialog->Font->Charset; + fs = pDialog->Font->Style; + m_WinFontStyle = FontStyle2Code(fs); + } + ResDisPaint(); + TopWindow(this); +} +//--------------------------------------------------------------------------- +void __fastcall TOptionDlg::JaBtnClick(TObject *Sender) +{ + WinFont->Text = "MS Pゴシック"; + m_WinFontCharset = SHIFTJIS_CHARSET; + m_WinFontStyle = 0; + if( MsgEng ){ + Application->MessageBox(L"MMSSTVを再起動すると日本語モードになります.\r\n(Please restart MMSSTV for Japanese mode)", L"MMSSTV", MB_ICONINFORMATION|MB_OK); //ja7ude 0521 + } +} +//--------------------------------------------------------------------------- +void __fastcall TOptionDlg::EngBtnClick(TObject *Sender) +{ + WinFont->Text = "Times New Roman"; + m_WinFontCharset = ANSI_CHARSET; + m_WinFontStyle = 0; +} +//--------------------------------------------------------------------------- +void __fastcall TOptionDlg::RadioBtnClick(TObject *Sender) +{ + // ラジオコントロール + TRADIOSetDlg *pBox = new TRADIOSetDlg(this); + + if( (PortName->Text != "NONE") && !strcmp(AnsiString(PortName->Text).c_str(), RADIO.StrPort) ){ //ja7ude 0521 + strcpy(RADIO.StrPort, "NONE"); + RADIO.change = 1; + } + if( pBox->Execute() == TRUE ){ + if( (PortName->Text != "NONE") && !strcmp(AnsiString(PortName->Text).c_str(), RADIO.StrPort) ){ //ja7ude 0521 + PortName->Text = "NONE"; + } + } + delete pBox; +} +//--------------------------------------------------------------------------- +void __fastcall TOptionDlg::SBClockAdjClick(TObject *Sender) +{ + double d; + sscanf(AnsiString(EditSamp->Text).c_str(), "%lf", &d); + if( (d < 5000.0) || (d > CLOCKMAX) ){ + d = sys.m_SampFreq; + } + + TClockAdjDlg *pBox = new TClockAdjDlg(this); + if( pBox->Execute(Mmsstv->pSound, d) == TRUE ){ + char bf[128]; + sprintf(bf, "%.2lf", d); + EditSamp->Text = bf; + } + delete pBox; +} +#if 0 +///---------------------------------------------------------------- +/// 多項式計算を行う +void MakeTeira(double *T, double *X, double *Y, int N) +{ + if( N > 17 ) N = 17; + double Z[20][20]; + + int i, i0, i1, i2, i3; + int n0, n1; + double w; + + for( i = 0; i < N; i++ ){ + Z[i][0] = 1; + } + for( i1 = 0; i1 < N; i1++ ){ + for( i2 = 1; i2 < N; i2++ ){ + w = 1; + for( i3 = 0; i3 < i2; i3++ ){ + w = w * X[i1]; + } + Z[i1][i2] = w; + } + } + for( i1 = 0; i1 < N; i1++ ){ + w = 0; + for( i2 = i1; i2 < N; i2++ ){ + if( ABS(Z[i2][i1]) >= w ){ + w = ABS(Z[i2][i1]); + i0 = i2; + } + } + if( i0 != N ){ + for( i2 = i1; i2 < N; i2++ ){ + w = Z[i1][i2]; + Z[i1][i2] = Z[i0][i2]; + Z[i0][i2] = w; + } + w = Y[i1]; + Y[i1] = Y[i0]; + Y[i0] = w; + } + w = Z[i1][i1]; + if( w ){ + for( i2 = i1; i2 < N; i2++ ){ + Z[i1][i2] = Z[i1][i2]/w; + } + Y[i1] = Y[i1]/w; + } + if( i1 == N ) break; + n1 = i1 + 1; + for( i2 = n1; i2 < N; i2++ ){ + w = Z[i2][i1]; + for( i3 = n1; i3 < N; i3++ ){ + Z[i2][i3] = Z[i2][i3] - w*Z[i1][i3]; + } + Y[i2] = Y[i2] - w * Y[i1]; + } + } + if( N > 1 ){ + for( n1 = N - 1; n1 >= 1; n1-- ){ + n0 = n1 - 1; + for( i2 = n1; i2 < N; i2++ ){ + Y[n0] = Y[n0] - Y[i2] * Z[n0][i2]; + } + } + } + for( i = 0; i < N; i++ ){ + T[i] = Y[i]; + } +} +#endif +//--------------------------------------------------------------------------- +void __fastcall TOptionDlg::TimerTimer(TObject *Sender) +{ + if( SBTest->Down ){ + int d = Mmsstv->pDem->m_CurSig; + switch(m_TestMode){ + case 0: + m_TestCnt--; + if( !m_TestCnt ){ + m_TestMode++; + m_TestCnt = 30 * m_BuffCal; + m_Avg.SetCount(30); + } + break; + case 1: // 1900Hzの計測 + m_Off = int(m_Avg.Avg(d) + 0.5); + Off1900->Text = m_Off; + m_TestCnt--; + if( !m_TestCnt ){ + m_TestMode++; + m_TestCnt = 5 * m_BuffCal; + sys.m_TestDem = 1500; + } + break; + case 2: + m_TestCnt--; + if( !m_TestCnt ){ + m_TestMode++; + m_TestCnt = 30 * m_BuffCal; + m_Avg.SetCount(30); + } + break; + case 3: // 1500Hzの計測 + m_Max1500 = int(m_Avg.Avg(d) + 0.5) - m_Off; + Max1500->Text = m_Max1500; + m_TestCnt--; + if( !m_TestCnt ){ + m_TestMode++; + m_TestCnt = 5 * m_BuffCal; + sys.m_TestDem = 2300; + } + break; + case 4: + m_TestCnt--; + if( !m_TestCnt ){ + m_TestMode++; + m_TestCnt = 30 * m_BuffCal; + m_Avg.SetCount(30); + } + break; + case 5: // 2300Hzの計測 + m_Max2300 = int(m_Avg.Avg(d) + 0.5) - m_Off; + Max2300->Text = m_Max2300; + m_TestCnt--; + if( !m_TestCnt ){ + m_TestMode++; + sys.m_TestDem = 1500; + m_TestCnt = 2 * m_BuffCal; + } + break; + case 6: + m_TestCnt--; + if( !m_TestCnt ){ + m_TestMode++; + m_TestCnt = 5 * m_BuffCal; + m_Avg.SetCount(3); + m_SubCnt = 0; + } + break; + case 7: + m_DataList[m_SubCnt] = m_Avg.Avg(d - m_Off); + sys.m_Dem17[m_SubCnt] = -m_DataList[m_SubCnt]; + m_TestCnt--; + if( !m_TestCnt ){ + m_TestCnt = 5 * m_BuffCal; + m_SubCnt++; + if( m_SubCnt > 16 ){ + m_TestMode++; + } + else { + sys.m_TestDem += 50; + } + } + break; + case 8: + m_TestCnt--; + if( !m_TestCnt ){ + Timer->Enabled = FALSE; + sys.m_TestDem = 0; + SBTest->Down = 0; + Mmsstv->pDem->m_SyncMode = 0; + Mmsstv->pMod->m_outgain = m_OutGain; + Screen->Cursor = crDefault; + Page->Enabled = TRUE; + OKBtn->Enabled = TRUE; + + TLinearDspDlg *pBox = new TLinearDspDlg(this); + pBox->Execute(m_DataList); + delete pBox; + ModalResult = mrOk; + } + break; + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TOptionDlg::SBTestClick(TObject *Sender) +{ + if( SBTest->Down ){ // テストの開始 + if( Mmsstv->SBTX->Down || Mmsstv->SBTune->Down ) Mmsstv->ToRX(); + double d; + int dd; + if( sscanf(AnsiString(pllVCOGain->Text).c_str(), "%lf", &d) == 1 ){ //ja7ude 0521 + if( d > 0.0 ) pDem->m_pll.SetVcoGain(d); + } + if( sscanf(AnsiString(pllLoopOrder->Text).c_str(), "%u", &dd) == 1 ){ //ja7ude 0521 + if( (dd > 0) && (dd < 32) ) pDem->m_pll.m_loopOrder = dd; + } + if( sscanf(AnsiString(pllLoopFC->Text).c_str(), "%lf", &d) == 1 ){ //ja7ude 0521 + if( d > 0.0 ) pDem->m_pll.m_loopFC = d; + } + if( sscanf(AnsiString(pllOutOrder->Text).c_str(), "%u", &dd) == 1 ){ //ja7ude 0521 + if( (dd > 0) && (dd < 32) ) pDem->m_pll.m_outOrder = dd; + } + if( sscanf(AnsiString(pllOutFC->Text).c_str(), "%lf", &d) == 1 ){ //ja7ude 0521 + if( d > 0.0 ) pDem->m_pll.m_outFC = d; + } + pDem->m_pll.MakeLoopLPF(); + pDem->m_pll.MakeOutLPF(); + if( sscanf(AnsiString(crossOutOrder->Text).c_str(), "%u", &dd) == 1 ){ //ja7ude 0521 + if( (dd > 0) && (dd < 32) ) pDem->m_fqc.m_outOrder = dd; + } + if( sscanf(AnsiString(crossOutFC->Text).c_str(), "%lf", &d) == 1 ){ //ja7ude 0521 + if( d > 0.0 ) pDem->m_fqc.m_outFC = d; + } + pDem->m_fqc.CalcLPF(); + pDem->m_Type = RGDemType->ItemIndex; + + m_BuffCal = (Mmsstv->pSound->m_BuffSize / SampFreq) / (2048.0/11025.0); + m_TestMode = 0; + m_TestCnt = 5; + Mmsstv->pDem->Stop(); + Mmsstv->pDem->SetWidth(0); + Mmsstv->pDem->m_SyncMode = 255; + Mmsstv->pMod->m_outgain = 8192.0; + Mmsstv->pMod->m_vco.SetSampleFreq(sys.m_SampFreq); + sys.m_TestDem = 1900; + Timer->Enabled = TRUE; + Screen->Cursor = crHourGlass; + OKBtn->Enabled = FALSE; + Page->Enabled = FALSE; + } +} +//--------------------------------------------------------------------------- + +void __fastcall TOptionDlg::RxBpfBtnClick(TObject *Sender) +{ + if( !RGRxBPF->ItemIndex ) return; + + double HBPF1[TAPMAX+1]; + double HBPF2[TAPMAX+1]; + double HBPF3[TAPMAX+1]; + + int tap; + pDem->CalcBPF(HBPF1, HBPF2, HBPF3, tap, RGRxBPF->ItemIndex, SSTVSET.m_TxMode); + + TFreqDispDlg *pBox = new TFreqDispDlg(this); + pBox->Execute(IsNarrowMode(SSTVSET.m_TxMode) ? HBPF3 : HBPF1, tap, 1); + delete pBox; +} +//--------------------------------------------------------------------------- +void __fastcall TOptionDlg::PCFFTClick(TObject *Sender) +{ + if( m_DisEvent ) return; + TPanel *tp = (TPanel *)Sender; + + TColorDialog *pDialog = Mmsstv->ColorDialog; + pDialog->Color = tp->Color; + SetCustomColor(); + NormalWindow(this); + SetDisPaint(); + if( pDialog->Execute() == TRUE ){ + tp->Color = pDialog->Color; + m_ColorChange = 1; + } + ResDisPaint(); + TopWindow(this); +} +//--------------------------------------------------------------------------- +void __fastcall TOptionDlg::UDTxSampClick(TObject *Sender, + TUDBtnType Button) +{ + if( m_DisEvent ) return; + if( Button == btNext ){ + m_TxSampOff += 0.02; + } + else { + m_TxSampOff -= 0.02; + } + if( m_TxSampOff < 0.0 ){ + m_TxSampOff = -m_TxSampOff; + m_TxSampOff = NormalSampFreq(m_TxSampOff, 50); + m_TxSampOff = -m_TxSampOff; + } + else { + m_TxSampOff = NormalSampFreq(m_TxSampOff, 50); + } + UpdateUI(); +} +//--------------------------------------------------------------------------- +void __fastcall TOptionDlg::CWIDMacClick(TObject *Sender) +{ + if( m_DisEvent ) return; + if( IDMMV->Checked ){ + TOpenDialog *pDialog = Mmsstv->OpenDialog; + pDialog->Options >> ofCreatePrompt; + pDialog->Options << ofFileMustExist; + if( MsgEng ){ + pDialog->Title = "Choose MMSSTV Sound file"; + pDialog->Filter = "MMSSTV Sound Files(*.mmv)|*.mmv|"; + } + else { + pDialog->Title = "MMSSTVサウンドファイルの選択"; + pDialog->Filter = "MMSSTVサウンドファイル(*.mmv)|*.mmv|"; + } + pDialog->FileName = ""; + pDialog->DefaultExt = "mmv"; + pDialog->InitialDir = BgnDir; + SetDisPaint(); + NormalWindow(this); + if( Mmsstv->OpenDialogExecute(FALSE) == TRUE ){ + MMVID->Text = pDialog->FileName.c_str(); + } + ResDisPaint(); + TopWindow(this); + } + else { + TMacroKeyDlg *pBox = new TMacroKeyDlg(this); + AnsiString as = CWIDText->Text; + if( pBox->Execute(as) > 0 ){ + CWIDText->SetFocus(); + CWIDText->SelStart = strlen(AnsiString(CWIDText->Text).c_str()); //ja7ude 0521 + CWIDText->SelLength = 0; + for( LPCSTR p = as.c_str(); *p; p++ ){ + ::PostMessage(CWIDText->Handle, WM_CHAR, *p, 0); + } + } + delete pBox; + } +} +//--------------------------------------------------------------------------- +void __fastcall TOptionDlg::RGDemTypeClick(TObject *Sender) +{ + if( m_DisEvent ) return; + CBCalWay->Checked = ((RGDemType->ItemIndex == 1) && (SampBase < 15000.0)) ? TRUE : FALSE; + UpdateUI(); +} +//--------------------------------------------------------------------------- +void __fastcall TOptionDlg::TxSampOffChange(TObject *Sender) +{ + if( m_DisEvent ) return; + double d; + + if( sscanf(AnsiString(TxSampOff->Text).c_str(), "%lf", &d) == 1 ){ //ja7ude 0521 + if( (d >= -1500.0) && (d <= 1500.0 ) ){ + m_TxSampOff = d; + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TOptionDlg::CBCalWayClick(TObject *Sender) +{ + if( m_DisEvent ) return; + + UpdateUI(); +} +//--------------------------------------------------------------------------- +void __fastcall TOptionDlg::IDOFFClick(TObject *Sender) +{ + if( m_DisEvent ) return; + if( IDMMV->Checked ){ + L7->Visible = FALSE; + L8->Visible = FALSE; + TBCW->Visible = FALSE; + CWIDFreq->Visible = FALSE; + L15->Visible = FALSE; + CWIDText->Visible = FALSE; + MMVID->Visible = TRUE; + CWIDMac->Caption = "Ref"; + } + else { + L7->Visible = TRUE; + L8->Visible = TRUE; + TBCW->Visible = TRUE; + CWIDFreq->Visible = TRUE; + L15->Visible = TRUE; + CWIDText->Visible = TRUE; + MMVID->Visible = FALSE; + CWIDMac->Caption = "Macro"; + } +} +//--------------------------------------------------------------------------- +void __fastcall TOptionDlg::VEditClick(TObject *Sender) +{ + TTextEditDlg *pBox = new TTextEditDlg(this); + pBox->Execute(m_VOXSound, TRUE, "VOX tone freq(Hz), time(ms), ..."); + delete pBox; +} +//--------------------------------------------------------------------------- +void __fastcall TOptionDlg::CBATClick(TObject *Sender) +{ + if( m_DisEvent ) return; + + if( CBAT->Checked ){ + int dd = 0; + sscanf(AnsiString(TrigTXTime->Text).c_str(), "%d", &dd); //ja7ude 0521 + if( dd < 0 ) TrigTXTime->Text = 5; + TuneFreq->Text = 1200; + } + else { + TuneFreq->Text = 1750; + TrigTXTime->Text = -1; + } +} +//--------------------------------------------------------------------------- +void __fastcall TOptionDlg::PortNameDropDown(TObject *Sender) +{ + if( m_DisEvent ) return; + + if( !m_MMList.IsQuery() ){ + m_MMList.QueryList("FSK"); + for( int i = 0; i < m_MMList.GetCount(); i++ ){ + PortName->Items->Add(m_MMList.GetItemName(i)); + } + PortName->DropDownCount = m_MMList.GetCount() + 18; + } +} +//--------------------------------------------------------------------------- +void __fastcall TOptionDlg::SourceClick(TObject *Sender) +{ + UpdateUI(); +} +//--------------------------------------------------------------------------- +// RxBPF=Most, TxBPF=24 +// Value = 7170 Celeron 1.06GHz 2003/10/22 +void __fastcall TOptionDlg::SBTestMouseDown(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( Button == mbRight ){ + CWaitCursor w; + TSound *pSound = Mmsstv->pSound; + if( pSound->m_ReqSpeedTest ) return; + pSound->m_ReqSpeedTest = 1; + while(pSound->m_ReqSpeedTest) ::Sleep(100); + InfoMB("Speed coefficient=%u (Sample=5117)", pSound->m_SpeedValue); + } +} +//--------------------------------------------------------------------------- +void __fastcall TOptionDlg::DevNoChange(TObject *Sender) +{ + if( m_DisEvent ) return; + + m_DisEvent++; + if( IsMMW(AnsiString(DevNo->Text).c_str()) >= 0 ){ //ja7ude 0521 + DevNoOut->Text = ""; + } + else if( IsMMW(AnsiString(DevNoOut->Text).c_str()) >= 0 ){ //ja7ude 0521 + DevNoOut->Text = "-1"; + } + m_DisEvent--; + CBCalWayClick(Sender); +} +//--------------------------------------------------------------------------- diff --git a/Option.dfm b/Option.dfm new file mode 100644 index 0000000..ee23c37 Binary files /dev/null and b/Option.dfm differ diff --git a/Option.h b/Option.h new file mode 100644 index 0000000..f150cd4 --- /dev/null +++ b/Option.h @@ -0,0 +1,287 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//---------------------------------------------------------------------------- +#ifndef OptionH +#define OptionH +//---------------------------------------------------------------------------- + //ja7ude 0428 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "sstv.h" +#include "MMLink.h" +//---------------------------------------------------------------------------- +class TOptionDlg : public TForm +{ +__published: + TButton *OKBtn; + TButton *CancelBtn; + TPageControl *Page; + TTabSheet *TabTx; + TGroupBox *GPTT; + TComboBox *PortName; + TLabel *Label13; + TGroupBox *GroupBox10; + TCheckBox *CBTXBPF; + TLabel *Label25; + TComboBox *TxBpfTap; + TTabSheet *TabMisc; + TCheckBox *CBTXLPF; + TComboBox *TxLpfFreq; + TLabel *Label28; + TLabel *Label29; + TSpeedButton *DispTxBpf; + TTabSheet *TabDem; + TGroupBox *GBPLL; + TLabel *Label1; + TGroupBox *GroupBox17; + TLabel *LLoopOrder; + TComboBox *pllVCOGain; + TComboBox *pllLoopOrder; + TLabel *Label3; + TComboBox *pllLoopFC; + TLabel *Label4; + TGroupBox *GroupBox18; + TLabel *LOutOrder; + TLabel *Label44; + TLabel *Label45; + TComboBox *pllOutOrder; + TComboBox *pllOutFC; + TGroupBox *GSFont; + TEdit *WinFont; + TButton *WinFontBtn; + TLabel *Label46; + TButton *JaBtn; + TButton *EngBtn; + TComboBox *FontAdj; + TSpeedButton *DispLoopLPF; + TSpeedButton *DispOutLPF; + TGroupBox *GrpCard; + TRadioGroup *SoundPriority; + TGroupBox *GroupBox3; + TSpeedButton *SBClockAdj; + TLabel *Label5; + TCheckBox *MemWin; + TComboBox *DevNo; + TLabel *Label11; + TButton *RadioBtn; + TComboBox *EditSamp; + TRadioGroup *Source; + TGroupBox *GBW; + TLabel *Label37; + TLabel *Label38; + TPanel *PCLow; + TPanel *PCHigh; + TGroupBox *GBOut; + TTrackBar *TBOutLvl; + TGroupBox *GBTemp; + TEdit *EditCall; + TLabel *Label2; + TTimer *Timer; + TGroupBox *GB2; + TSpeedButton *SBTest; + TEdit *Max1500; + TEdit *Max2300; + TEdit *Off1900; + TLabel *LOff; + TLabel *L1500; + TLabel *L2300; + TGroupBox *GBHMax; + TComboBox *HistMax; + TRadioGroup *RGRBuf; + TRadioGroup *RGMSync; + TRadioGroup *RGRxBPF; + TButton *RxBpfBtn; + TUpDown *UDTxSamp; + TRadioGroup *RGLoopBack; + TGroupBox *GB4; + TCheckBox *CBAStop; + TCheckBox *CBARestart; + TGroupBox *GroupBox4; + TLabel *Label9; + TComboBox *TuneFreq; + TLabel *Label10; + TComboBox *TrigTXTime; + TLabel *Label12; + TLabel *Label14; + TGroupBox *GB5; + TEdit *CWIDText; + TComboBox *CWIDFreq; + TLabel *L15; + TButton *CWIDMac; + TGroupBox *GB6; + TComboBox *JPEGQ; + TLabel *Label16; + TLabel *LJPEGQ; + TGroupBox *GB7; + TCheckBox *CBTxFixed; + TRadioGroup *RGSLvl; + TRadioGroup *RGDemType; + TGroupBox *GBCROSS; + TGroupBox *GBCOI; + TLabel *LCORDER; + TLabel *Label18; + TLabel *Label19; + TSpeedButton *DispCrossOutLPF; + TComboBox *crossOutOrder; + TComboBox *crossOutFC; + TCheckBox *CBASlant; + TRadioGroup *RGcrossType; + TGroupBox *GBCOF; + TComboBox *crossSmooz; + TLabel *Label17; + TLabel *Label20; + TCheckBox *CBDiff; + TTrackBar *TBDiff; + TCheckBox *CBASync; + TEdit *TxSampOff; + TLabel *L21; + TLabel *Label21; + TCheckBox *CBCalWay; + TGroupBox *GBS; + TLabel *LFFTB; + TLabel *LFFT; + TLabel *LFFTT; + TLabel *LFFTS; + TLabel *LFFTF; + TPanel *PCFFTB; + TPanel *PCFFT; + TPanel *PCFFTStg; + TPanel *PCSync; + TPanel *PCFreq; + TTrackBar *TBCW; + TLabel *L7; + TLabel *L8; + TCheckBox *PTTLock; + TRadioButton *IDOFF; + TRadioButton *IDCW; + TRadioButton *IDMMV; + TEdit *MMVID; + TCheckBox *CBVari; + TCheckBox *IDFSK; + TCheckBox *IDDEC; + TGroupBox *GB1; + TLabel *L27; + TComboBox *RxFifo; + TComboBox *TxFifo; + TLabel *L6; + TRadioGroup *AppPriority; + TRadioGroup *RGV; + TButton *VEdit; + TLabel *L17; + TCheckBox *CBAT; + TCheckBox *CBRTS; + TCheckBox *CB24; + TCheckBox *CBSTX; + TLabel *Label6; + TComboBox *DevNoOut; + void __fastcall DispTxBpfClick(TObject *Sender); + void __fastcall PortNameChange(TObject *Sender); + + void __fastcall WinFontBtnClick(TObject *Sender); + void __fastcall JaBtnClick(TObject *Sender); + void __fastcall EngBtnClick(TObject *Sender); + + + + + void __fastcall DispLoopLPFClick(TObject *Sender); + void __fastcall DispOutLPFClick(TObject *Sender); + void __fastcall RadioBtnClick(TObject *Sender); + + + + + void __fastcall SBClockAdjClick(TObject *Sender); + void __fastcall TimerTimer(TObject *Sender); + + void __fastcall SBTestClick(TObject *Sender); + + + void __fastcall RxBpfBtnClick(TObject *Sender); + void __fastcall PCFFTClick(TObject *Sender); + void __fastcall UDTxSampClick(TObject *Sender, TUDBtnType Button); + void __fastcall CWIDMacClick(TObject *Sender); + void __fastcall RGDemTypeClick(TObject *Sender); + void __fastcall DispCrossOutLPFClick(TObject *Sender); + void __fastcall TxSampOffChange(TObject *Sender); + void __fastcall CBCalWayClick(TObject *Sender); + void __fastcall IDOFFClick(TObject *Sender); + void __fastcall VEditClick(TObject *Sender); + + void __fastcall CBATClick(TObject *Sender); + void __fastcall PortNameDropDown(TObject *Sender); + void __fastcall SourceClick(TObject *Sender); + void __fastcall SBTestMouseDown(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + void __fastcall DevNoChange(TObject *Sender); +private: + int m_DisEvent; + + CSSTVDEM *pDem; + double m_TxSampOff; + + void __fastcall UpdateUI(void); + void __fastcall SetCustomColor(void); + + + BYTE m_WinFontCharset; + int m_WinFontStyle; + + int m_TestMode; + int m_TestCnt; + int m_SubCnt; + CSmooz m_Avg; + double m_DataList[17]; + double m_DataList2[17]; + int m_Off; + int m_Max1500; + int m_Max2300; + double m_OutGain; + double m_BuffCal; + + AnsiString m_VOXSound; + CMMList m_MMList; + CMMList m_MMListW; +private: + int __fastcall IsMMW(LPCSTR p); + +public: + virtual __fastcall TOptionDlg(TComponent* AOwner); + + int __fastcall Execute(CSSTVDEM *fp, CSSTVMOD *mp); + int m_ColorChange; + void __fastcall SetPageIndex(int n); +}; +//---------------------------------------------------------------------------- +//extern TAgcSetDlg *AgcSetDlg; +extern int PageIndex; +//---------------------------------------------------------------------------- +#endif diff --git a/PerSpect.cpp b/PerSpect.cpp new file mode 100644 index 0000000..0e511dd --- /dev/null +++ b/PerSpect.cpp @@ -0,0 +1,151 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "PerSpect.h" +#include "Main.h" +//--------------------------------------------------------------------- +#pragma resource "*.dfm" +//TPerSpectDlg *PerSpectDlg; +//--------------------------------------------------------------------- +__fastcall TPerSpectDlg::TPerSpectDlg(TComponent* AOwner) + : TForm(AOwner) +{ + FormStyle = ((TForm *)AOwner)->FormStyle; + Font->Name = ((TForm *)AOwner)->Font->Name; + Font->Charset = ((TForm *)AOwner)->Font->Charset; + if( MsgEng ){ + Caption = "Perspective transformation"; + CancelBtn->Caption = "Cancel"; + DefBtn->Caption = "Default"; + } + memset(&m_S, 0, sizeof(m_S)); + m_S.v = 10.0; m_S.s = 5.0; + pBitmap = new Graphics::TBitmap; + pBitmap->Width = PBox->Width; + pBitmap->Height = PBox->Height; + pBitmap->PixelFormat = pf24bit; +} + +__fastcall TPerSpectDlg::~TPerSpectDlg() +{ + delete pBitmap; +} + +int __fastcall TPerSpectDlg::Execute(CDrawText *pItem) +{ + m_Text.Start(PBox->Canvas, 0, 0); // キャンバスのセット + m_Text.Copy(pItem); + m_Text.m_PerSpect = 0; + m_Text.UpdateText(); + if( m_Text.pBitmap != NULL ){ + m_Back = m_Text.pBitmap->Canvas->Pixels[0][0]; + m_Text.pBitmap->Transparent = FALSE; + } + + TBAX->Position = pItem->m_sperspect.ax * 20.0; + TBAY->Position = pItem->m_sperspect.ay * 20.0; + TBPX->Position = pItem->m_sperspect.px * 40.0; + TBPY->Position = pItem->m_sperspect.py * 40.0; + TBPZ->Position = pItem->m_sperspect.pz * 40.0; + TBRX->Position = pItem->m_sperspect.rx; + TBRY->Position = pItem->m_sperspect.ry; + TBRZ->Position = pItem->m_sperspect.rz; + TBS->Position = pItem->m_sperspect.s * 10.0; + RGTF->ItemIndex = pItem->m_PerSpect; + + UpdateBitmap(); + if( ShowModal() == IDOK ){ + pItem->m_sperspect.ax = double(TBAX->Position)/20.0; + pItem->m_sperspect.ay = double(TBAY->Position)/20.0; + pItem->m_sperspect.px = double(TBPX->Position)/40.0; + pItem->m_sperspect.py = double(TBPY->Position)/40.0; + pItem->m_sperspect.pz = double(TBPZ->Position)/40.0; + pItem->m_sperspect.rx = TBRX->Position; + pItem->m_sperspect.ry = TBRY->Position; + pItem->m_sperspect.rz = TBRZ->Position; + pItem->m_sperspect.s = double(TBS->Position)/10.0; + pItem->m_PerSpect = RGTF->ItemIndex; + return TRUE; + } + return FALSE; +} +//--------------------------------------------------------------------- +void __fastcall TPerSpectDlg::UpdateBitmap(void) +{ + if( m_Text.pBitmap == NULL ) return; + + m_Text.m_sperspect.ax = double(TBAX->Position)/20.0; + m_Text.m_sperspect.ay = double(TBAY->Position)/20.0; + + m_Text.m_sperspect.px = double(TBPX->Position)/40.0; + m_Text.m_sperspect.py = double(TBPY->Position)/40.0; + m_Text.m_sperspect.pz = double(TBPZ->Position)/40.0; + + m_Text.m_sperspect.rx = TBRX->Position; + m_Text.m_sperspect.ry = TBRY->Position; + m_Text.m_sperspect.rz = TBRZ->Position; + m_Text.m_sperspect.s = double(TBS->Position)/10.0; + pBitmap->Width = m_Text.pBitmap->Width; + pBitmap->Height = m_Text.pBitmap->Height; + Perspect(m_Text.pBitmap, pBitmap, &m_Text.m_sperspect, m_Back); + MultProc(); +} +//--------------------------------------------------------------------- +void __fastcall TPerSpectDlg::PBoxPaint(TObject *Sender) +{ + if( RGTF->ItemIndex ){ + PBox->Canvas->Draw(0, 0, pBitmap); + } + else { + PBox->Canvas->Draw(0, 0, m_Text.pBitmap); + } +} +//--------------------------------------------------------------------------- +void __fastcall TPerSpectDlg::TBAXChange(TObject *Sender) +{ + RGTF->ItemIndex = 1; + UpdateBitmap(); + PBox->Canvas->Draw(0, 0, pBitmap); +} +//--------------------------------------------------------------------------- +void __fastcall TPerSpectDlg::DefBtnClick(TObject *Sender) +{ + TBAX->Position = 40; + TBAY->Position = 120; + TBPX->Position = 2; + TBPY->Position = 0; + TBPZ->Position = 0; + TBRX->Position = -70; + TBRY->Position = 0; + TBRZ->Position = -180; + TBS->Position = 49; + RGTF->ItemIndex = 1; + TBAXChange(NULL); +} +//--------------------------------------------------------------------------- +void __fastcall TPerSpectDlg::RGTFClick(TObject *Sender) +{ + PBox->Invalidate(); +} +//--------------------------------------------------------------------------- + diff --git a/PerSpect.dfm b/PerSpect.dfm new file mode 100644 index 0000000..c808920 Binary files /dev/null and b/PerSpect.dfm differ diff --git a/PerSpect.h b/PerSpect.h new file mode 100644 index 0000000..5bc8e8f --- /dev/null +++ b/PerSpect.h @@ -0,0 +1,90 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//---------------------------------------------------------------------------- +#ifndef PerSpectDlgH +#define PerSpectDlgH +//---------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//---------------------------------------------------------------------------- +#include "ComLib.h" +#include "Draw.h" +//#define SPERSPECTMAX 16 +//---------------------------------------------------------------------------- +class TPerSpectDlg : public TForm +{ +__published: + TButton *OKBtn; + TButton *CancelBtn; + TTrackBar *TBAX; + TTrackBar *TBAY; + TTrackBar *TBRX; + TTrackBar *TBRY; + TTrackBar *TBRZ; + TPaintBox *PBox; + TTrackBar *TBS; + TTrackBar *TBPX; + TTrackBar *TBPY; + TTrackBar *TBPZ; + TLabel *L1; + TLabel *L2; + TLabel *L3; + TLabel *L4; + TLabel *L5; + TLabel *L6; + TLabel *L7; + TLabel *L8; + TLabel *L9; + TButton *DefBtn; + TRadioGroup *RGTF; + void __fastcall PBoxPaint(TObject *Sender); + void __fastcall TBAXChange(TObject *Sender); + void __fastcall DefBtnClick(TObject *Sender); + void __fastcall RGTFClick(TObject *Sender); + +private: + Graphics::TBitmap *pBitmap; + SPERSPECT m_S; + CDrawText m_Text; + TColor m_Back; + void __fastcall UpdateBitmap(void); + +// AnsiString m_ListName[SPERSPECTMAX]; +// SPERSPECT m_ListPara[SPERSPECTMAX]; + +public: + virtual __fastcall TPerSpectDlg(TComponent* AOwner); + __fastcall ~TPerSpectDlg(); + + int __fastcall Execute(CDrawText *pItem); +}; +//---------------------------------------------------------------------------- +//extern PACKAGE TPerSpectDlg *PerSpectDlg; +//---------------------------------------------------------------------------- +#endif diff --git a/PicFilte.cpp b/PicFilte.cpp new file mode 100644 index 0000000..a213e2b --- /dev/null +++ b/PicFilte.cpp @@ -0,0 +1,667 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "Main.h" +#include "ComLIb.h" +#include "PicFilte.h" +#include "math.h" +#ifndef PI +#define PI 3.1415926535897932384626433832795 +#endif +#ifndef PI2 +#define PI2 (PI*2) +#endif +//--------------------------------------------------------------------- +#pragma resource "*.dfm" +//--------------------------------------------------------------------- +__fastcall TPicFilterDlg::TPicFilterDlg(TComponent* AOwner) + : TForm(AOwner) +{ + m_DisEvent = 1; + FormStyle = ((TForm *)AOwner)->FormStyle; + Font->Name = ((TForm *)AOwner)->Font->Name; + Font->Charset = ((TForm *)AOwner)->Font->Charset; + if( MsgEng ){ + CancelBtn->Caption = "Cancel"; + L1->Caption = "Brightness"; + L2->Caption = "Contrast"; + L3->Caption = "Sharpness"; + L4->Caption = "Hue"; + L5->Caption = "Saturation"; + GBFilt->Caption = "Noise filter"; + SBST->Caption = "Stretch"; + AutoBtn->Caption = "Auto"; + ResBtn->Caption = "Reset"; + SBEdit->Caption = "Edit"; + SBBRR->Hint = "Reset"; + SBCTR->Hint = "Reset"; + SBSPR->Hint = "Reset"; + SBCPR->Hint = "Reset"; + SBCOR->Hint = "Reset"; + } + else { + SBBRR->Hint = "解除"; + SBCTR->Hint = "解除"; + SBSPR->Hint = "解除"; + SBCPR->Hint = "解除"; + SBCOR->Hint = "解除"; + } + m_XW = 320; + m_YW = 256; + MultProc(); + pBitmap = new Graphics::TBitmap(); + pBitmap->PixelFormat = pf24bit; + pBitmap->Width = 320; + pBitmap->Height = 256; + + pBitmapS = new Graphics::TBitmap(); + pBitmapS->PixelFormat = pf24bit; + pBitmapS->Width = 320; + pBitmapS->Height = 256; + pBitmapD = new Graphics::TBitmap(); + pBitmapD->PixelFormat = pf24bit; + pBitmapD->Width = 320; + pBitmapD->Height = 256; + + pH = NULL; + pS = NULL; + m_Make = 0; + m_Sync = 0; + MultProc(); +} +//--------------------------------------------------------------------- +__fastcall TPicFilterDlg::~TPicFilterDlg() +{ + delete pBitmap; + delete pBitmapD; + delete pBitmapS; + if( pS != NULL ){ + delete pS; + delete pH; + pS = NULL; + pH = NULL; + } + MultProc(); + g_ExecPB.Cancel(); +} +//--------------------------------------------------------------------- +void __fastcall TPicFilterDlg::UpdateBtn(void) +{ + SBBRR->Enabled = (TBBright->Position != 10) ? TRUE : FALSE; + SBCTR->Enabled = (TBCont->Position != 10) ? TRUE : FALSE; + SBSPR->Enabled = (TBShape->Position != 10) ? TRUE : FALSE; + SBCPR->Enabled = (TBH->Position != 10) ? TRUE : FALSE; + SBCOR->Enabled = (TBS->Position != 10) ? TRUE : FALSE; + ResBtn->Enabled = SBBRR->Enabled || SBCTR->Enabled || SBSPR->Enabled || SBCPR->Enabled || SBCOR->Enabled || !SBFN->Down; + if( !OKBtn->Enabled ){ + Timer->Interval = ResBtn->Enabled ? 5000 : 1500; + } +} +//--------------------------------------------------------------------- +int __fastcall TPicFilterDlg::Execute(Graphics::TBitmap *pBmp) +{ + CWaitCursor w; + MultProc(); + m_XW = pBmp->Width; + m_YW = pBmp->Height; + char bf[128]; + sprintf(bf, "%s - Source:%ux%u", MsgEng ? "Image adjustment" : "画像調整", m_XW, m_YW); + Caption = bf; + pBitmap->Width = m_XW; + pBitmap->Height = m_YW; + pBitmapS->Width = m_XW; + pBitmapS->Height = m_YW; + pBitmapD->Width = m_XW; + pBitmapD->Height = m_YW; + pBitmap->Canvas->Draw(0, 0, pBmp); + pBitmapS->Canvas->Draw(0, 0, pBmp); + pBitmapD->Canvas->Draw(0, 0, pBmp); + CB2D->Checked = sys.m_Sharp2D; + if( (m_XW <= 320) && (m_YW <= 256) ){ + SBST->Visible = FALSE; + } + UpdateBtn(); + w.Delete(); + m_DisEvent = 0; + MultProc(); + int r = ShowModal(); + MultProc(); + sys.m_Sharp2D = CB2D->Checked; + if( r == IDOK ){ + pBmp->Canvas->Draw(0, 0, pBitmapD); + return TRUE; + } + else { + return FALSE; + } +} +//--------------------------------------------------------------------- +void __fastcall TPicFilterDlg::PBoxPaint(TObject *Sender) +{ + if( ((m_XW <= 320) && (m_YW <= 256)) ){ + PBox->Canvas->Draw(0, 0, pBitmapD); + } + else if( SBST->Down ){ + TRect tc; + tc.Left = 0; tc.Top = 0; + double sx = m_XW / 320.0; + double sy = m_YW / 256.0; + if( sx > sy ){ + tc.Right = 320; + tc.Bottom = m_YW / sx; + } + else { + tc.Bottom = 256; + tc.Right = m_XW / sy; + } + ::SetStretchBltMode(PBox->Canvas->Handle, HALFTONE); + PBox->Canvas->StretchDraw(tc, pBitmapD); + } + else { + int x = (320 - m_XW) / 2; + int y = (256 - m_YW) / 2; + PBox->Canvas->Draw(x, y, pBitmapD); + } +} +//--------------------------------------------------------------------- +void __fastcall TPicFilterDlg::Filt(int sw) +{ + MFilter(pBitmapS, pBitmap, sw); +} +//--------------------------------------------------------------------- +void __fastcall TPicFilterDlg::AdjustColor(int x, int y, double &RY, double &BY) +{ + double H, S; + + if( pS == NULL ){ + pS = new double[(m_XW + 1) * (m_YW + 1)]; + pH = new double[(m_XW + 1) * (m_YW + 1)]; + m_Make = 1; + } + if( (RY != 0.0) || (BY != 0.0) ){ + if( TBS->Position ){ + if( m_Make ){ + S = sqrt(RY*RY + BY*BY); + H = atan2(RY, BY); + pS[y*m_XW+x] = S; + pH[y*m_XW+x] = H; + } + else { + S = pS[y*m_XW+x]; + H = pH[y*m_XW+x]; + } + + H += (TBH->Position - 10) * PI2 * 0.01; + S *= 1.0 + (TBS->Position - 10) * 0.1; + + RY = S * sin(H); + BY = S * cos(H); + } + else { + RY = BY = 0; + } + } + else { + pS[y*m_XW+x] = 0; + pH[y*m_XW+x] = 0; + } +} +//--------------------------------------------------------------------- +void __fastcall TPicFilterDlg::Bright(void) +{ + MultProc(); + + int y, x; + double B, G, R, Y, RY, BY; + double k1, k2; + if( TBCont->Position > 10 ){ + k1 = double(1.0 + (TBCont->Position - 10)*0.1); + } + else { + k1 = double(1.0 + (TBCont->Position - 10)*0.05); + } + if( TBBright->Position > 10 ){ + k2 = double((TBBright->Position - 10) * 6.0); + } + else { + k2 = double((TBBright->Position - 10) * 2.0); + } + BYTE *sp; + BYTE *tp; + if( TBShape->Position == 10 ){ + for( y = 0; y < m_YW; y++ ){ + sp = (BYTE*)pBitmapS->ScanLine[y]; + tp = (BYTE*)pBitmapD->ScanLine[y]; + for( x = 0; x < m_XW; x++ ){ + B = *sp++; + G = *sp++; + R = *sp++; + Y = 0.3 * R + 0.59 * G + 0.11 * B; + RY = 0.7 * R - 0.59 * G - 0.11 * B; + BY = -0.3 * R - 0.59 * G + 0.89 * B; + + if( (TBH->Position != 10) || (TBS->Position != 10) ){ + AdjustColor(x, y, RY, BY); + } + + Y = ((Y - 128) * k1) + 128; + Y += k2; + + R = Y + RY; + G = Y - 0.3 * RY / 0.59 - 0.11 * BY / 0.59; + B = Y + BY; + if( R > 255 ) R = 255; + if( R < 0 ) R = 0; + if( G > 255 ) G = 255; + if( G < 0 ) G = 0; + if( B > 255 ) B = 255; + if( B < 0 ) B = 0; + *tp++ = B; + *tp++ = G; + *tp++ = R; + } + MultProcA(); + } + } + else { + double a, d; + double Z1, Z2, Z3; + if( CB2D->Checked ){ + a = TBShape->Position - 10; + if( a > 0 ){ + a *= 0.2; + } + else { + a *= 0.1; + } + double *ZV0 = new double[m_XW+1]; + double *ZV1 = new double[m_XW+1]; + double *ZV2 = new double[m_XW+1]; + memset(ZV0, 0, sizeof(double) * (m_XW+1)); + memset(ZV1, 0, sizeof(double) * (m_XW+1)); + memset(ZV2, 0, sizeof(double) * (m_XW+1)); + for( y = 0; y < (m_YW+1); y++ ){ + sp = (BYTE*)pBitmapS->ScanLine[y < m_YW ? y : y - 1]; + tp = (BYTE*)pBitmapD->ScanLine[y ? y - 1 : y]; + Z1 = Z2 = Z3 = 0; + for( x = 0; x < (m_XW+1); x++ ){ + if( x < m_XW ){ + B = *sp++; + G = *sp++; + R = *sp++; + } + else { + sp -= 3; + B = *sp++; + G = *sp++; + R = *sp++; + } + Y = 0.3 * R + 0.59 * G + 0.11 * B; + RY = 0.7 * R - 0.59 * G - 0.11 * B; + BY = -0.3 * R - 0.59 * G + 0.89 * B; + + if( (TBH->Position != 10) || (TBS->Position != 10) ){ + AdjustColor(x, y, RY, BY); + } + + Y = ((Y - 128) * k1) + 128; + Y += k2; + + d = Z3 + ((Y * -0.5 + Z1 + Z2 * -0.5) * a); + Z2 = Z1; + Z3 = Z1 = Y; + Y = d; + + d = ZV2[x] + ((Y * -0.5 + ZV0[x] + ZV1[x] * -0.5) * a); + ZV1[x] = ZV0[x]; + ZV2[x] = ZV0[x] = Y; + Y = d; + + R = Y + RY; + G = Y - 0.3 * RY / 0.59 - 0.11 * BY / 0.59; + B = Y + BY; + if( R > 255 ) R = 255; + if( R < 0 ) R = 0; + if( G > 255 ) G = 255; + if( G < 0 ) G = 0; + if( B > 255 ) B = 255; + if( B < 0 ) B = 0; + if( (x > 0) && (y > 0) ){ + *tp++ = B; + *tp++ = G; + *tp++ = R; + } + } + MultProcA(); + } + delete ZV0; + delete ZV1; + delete ZV2; + } + else { + a = TBShape->Position - 10; + if( a > 0 ){ + a *= 0.3; + } + else { + a *= 0.1; + } + for( y = 0; y < m_YW; y++ ){ + sp = (BYTE*)pBitmapS->ScanLine[y]; + tp = (BYTE*)pBitmapD->ScanLine[y]; + Z1 = Z2 = Z3 = 0; + for( x = 0; x < (m_XW+1); x++ ){ + if( x < m_XW ){ + B = *sp++; + G = *sp++; + R = *sp++; + } + else { + sp -= 3; + B = *sp++; + G = *sp++; + R = *sp++; + } + Y = 0.3 * R + 0.59 * G + 0.11 * B; + RY = 0.7 * R - 0.59 * G - 0.11 * B; + BY = -0.3 * R - 0.59 * G + 0.89 * B; + + if( (TBH->Position != 10) || (TBS->Position != 10) ){ + AdjustColor(x, y, RY, BY); + } + + Y = ((Y - 128) * k1) + 128; + Y += k2; + + d = Z3 + ((Y * -0.5 + Z1 + Z2 * -0.5) * a); + Z2 = Z1; + Z3 = Z1 = Y; + Y = d; + + R = Y + RY; + G = Y - 0.3 * RY / 0.59 - 0.11 * BY / 0.59; + B = Y + BY; + if( R > 255 ) R = 255; + if( R < 0 ) R = 0; + if( G > 255 ) G = 255; + if( G < 0 ) G = 0; + if( B > 255 ) B = 255; + if( B < 0 ) B = 0; + if( x > 0 ){ + *tp++ = B; + *tp++ = G; + *tp++ = R; + } + } + MultProcA(); + } + } + } + m_Make = 0; +} +//--------------------------------------------------------------------------- +void __fastcall TPicFilterDlg::TBBrightChange(TObject *Sender) +{ + if( m_DisEvent ) return; + + Bright(); + PBoxPaint(NULL); + UpdateBtn(); +} +//--------------------------------------------------------------------------- +void __fastcall TPicFilterDlg::SBFNClick(TObject *Sender) +{ + MultProc(); + CWaitCursor w; + + pBitmapS->Canvas->Draw(0, 0, pBitmap); + if( SBFA->Down ){ + Filt(0); + } + else if( SBFB->Down ){ + Filt(1); + } + if( pS != NULL ){ + delete pS; + delete pH; + pS = NULL; + pH = NULL; + } + TBBrightChange(NULL); + UpdateBtn(); +} +//--------------------------------------------------------------------------- +void __fastcall TPicFilterDlg::ResBtnClick(TObject *Sender) +{ + m_DisEvent++; + TBBright->Position = 10; + TBCont->Position = 10; + TBShape->Position = 10; + TBH->Position = 10; + TBS->Position = 10; + SBFN->Down = TRUE; + if( pS != NULL ){ + delete pS; + delete pH; + pS = NULL; + pH = NULL; + } + m_DisEvent--; + if( !OKBtn->Enabled ) ::CopyBitmap(pBitmap, Mmsstv->pBitmapRX); + pBitmapS->Canvas->Draw(0, 0, pBitmap); + pBitmapD->Canvas->Draw(0, 0, pBitmap); + PBox->Invalidate(); + UpdateBtn(); +} +//--------------------------------------------------------------------------- +void __fastcall TPicFilterDlg::SBBRRClick(TObject *Sender) +{ + if( TBBright->Position != 10 ){ + m_DisEvent++; + TBBright->Position = 10; + Bright(); + PBox->Invalidate(); + UpdateBtn(); + m_DisEvent--; + } +} +//--------------------------------------------------------------------------- +void __fastcall TPicFilterDlg::SBCTRClick(TObject *Sender) +{ + if( TBCont->Position != 10 ){ + m_DisEvent++; + TBCont->Position = 10; + Bright(); + PBox->Invalidate(); + UpdateBtn(); + m_DisEvent--; + } +} +//--------------------------------------------------------------------------- +void __fastcall TPicFilterDlg::SBSPRClick(TObject *Sender) +{ + if( TBShape->Position != 10 ){ + m_DisEvent++; + TBShape->Position = 10; + Bright(); + PBox->Invalidate(); + UpdateBtn(); + m_DisEvent--; + } +} +//--------------------------------------------------------------------------- +void __fastcall TPicFilterDlg::SBCPRClick(TObject *Sender) +{ + if( TBH->Position != 10 ){ + m_DisEvent++; + TBH->Position = 10; + Bright(); + PBox->Invalidate(); + UpdateBtn(); + m_DisEvent--; + } +} +//--------------------------------------------------------------------------- +void __fastcall TPicFilterDlg::SBCORClick(TObject *Sender) +{ + if( TBS->Position != 10 ){ + m_DisEvent++; + TBS->Position = 10; + Bright(); + PBox->Invalidate(); + UpdateBtn(); + m_DisEvent--; + } +} +//--------------------------------------------------------------------------- +void __fastcall TPicFilterDlg::SBSTClick(TObject *Sender) +{ + PBox->Invalidate(); +} +//---------------------------------------------------------------------------#if 0 +void __fastcall TPicFilterDlg::AutoBtnClick(TObject *Sender) +{ + MultProc(); + CWaitCursor w; + + int B, G, R, Y, BY, RY; + int x, y; + BYTE *sp; + + int Hind[256]; + memset(Hind, 0, sizeof(Hind)); + int S = 0; + for( y = 0; y < m_YW; y++ ){ + sp = (BYTE*)pBitmapS->ScanLine[y]; + for( x = 0; x < m_XW; x++ ){ + B = *sp++; + G = *sp++; + R = *sp++; + Y = Limit256(0.3 * R + 0.59 * G + 0.11 * B); + Hind[Y]++; + RY = 0.7 * R - 0.59 * G - 0.11 * B; + BY = -0.3 * R - 0.59 * G + 0.89 * B; + Y = sqrt(RY*RY + BY*BY); + if( Y > S ) S = Y; + } + MultProcA(); + } +#if 0 + int max = 0; + for( x = 0; x < 256; x++ ){ + if( max < Hind[x] ){ + max = Hind[x]; + } + } + FILE *fp = fopen("F:\\TEST.TXT", "wt"); + for( x = 0; x < 256; x++ ){ + int e = Hind[x] * 65 / max; + for( int j = 0; j < e; j++ ) fprintf(fp, "*"); + fprintf(fp, "(%d)\n", Hind[x]); + } + fclose(fp); +#endif + int lmt = m_XW * m_YW / 2560; + int ml = 256; + int mh = 0; + for( x = 0; x < 256; x++ ){ + if( Hind[x] > lmt ){ + ml = x; + break; + } + } + for( x = 255; x >= 0; x-- ){ + if( Hind[x] > lmt ){ + mh = x; + break; + } + } + if( mh > ml ){ + m_DisEvent++; + int b = 128 - (mh + ml)/2; + double c = 230.4 / (mh - ml); + if( c < 1.0 ) c = 1.0; +// c = c - 1.0 - (b / 128.0); + c = c - 1.0; + c = c * (c > 1.0 ? 10 : 20); + b = b / (b > 0 ? 6 : 2); + TBBright->Position = b + 10; + TBCont->Position = c + 10; + TBShape->Position = 10; + if( S ){ + S = (((256.0 / double(S)) - 1.0) * 2.0) + 10; + } + if( S < 10 ) S = 10; + TBS->Position = S; + TBH->Position = 10; + m_DisEvent--; + TBBrightChange(NULL); + } +} +//--------------------------------------------------------------------------- +void __fastcall TPicFilterDlg::TimerTimer(TObject *Sender) +{ + if( !OKBtn->Enabled && (m_Sync || Mmsstv->pDem->m_Sync) ){ + if( Mmsstv->pSound->IsBusy() ) return; + m_Sync = Mmsstv->pDem->m_Sync; + + if( pS != NULL ){ + delete pS; + delete pH; + pS = NULL; + pH = NULL; + } + ::CopyBitmap(pBitmap, Mmsstv->pBitmapRX); + MultProcA(); + if( ResBtn->Enabled ){ + CWaitCursor w; + if( !SBFN->Down ){ + SBFNClick(NULL); + } + else { + pBitmapS->Canvas->Draw(0, 0, pBitmap); + TBBrightChange(NULL); + } + } + else { + pBitmapS->Canvas->Draw(0, 0, pBitmap); + pBitmapD->Canvas->Draw(0, 0, pBitmap); + PBoxPaint(NULL); + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TPicFilterDlg::SBEditClick(TObject *Sender) +{ + g_ExecPB.Exec(pBitmapD, (HWND)Handle, CM_EDITEXIT, 0); +} +//--------------------------------------------------------------------------- +void __fastcall TPicFilterDlg::OnEditExit(TMessage Message) +{ + if( Message.LParam ) return; + + if( g_ExecPB.LoadBitmap(pBitmap, FALSE) ){ + ResBtnClick(NULL); + } +} +//--------------------------------------------------------------------------- diff --git a/PicFilte.dfm b/PicFilte.dfm new file mode 100644 index 0000000..32e35f5 Binary files /dev/null and b/PicFilte.dfm differ diff --git a/PicFilte.h b/PicFilte.h new file mode 100644 index 0000000..292fd41 --- /dev/null +++ b/PicFilte.h @@ -0,0 +1,118 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//---------------------------------------------------------------------------- +#ifndef PicFilteH +#define PicFilteH +//---------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//---------------------------------------------------------------------------- +class TPicFilterDlg : public TForm +{ +__published: + TButton *OKBtn; + TButton *CancelBtn; + TPanel *Panel; + TPaintBox *PBox; + TTrackBar *TBBright; + TLabel *L1; + TTrackBar *TBCont; + TLabel *L2; + TTrackBar *TBShape; + TLabel *L3; + TGroupBox *GBFilt; + TSpeedButton *SBFN; + TSpeedButton *SBFA; + TSpeedButton *SBFB; + TCheckBox *CB2D; + TLabel *L4; + TTrackBar *TBH; + TLabel *L5; + TTrackBar *TBS; + TButton *ResBtn; + TSpeedButton *SBBRR; + TSpeedButton *SBCTR; + TSpeedButton *SBSPR; + TSpeedButton *SBCPR; + TSpeedButton *SBCOR; + TSpeedButton *SBST; + TButton *AutoBtn; + TTimer *Timer; + TSpeedButton *SBEdit; + void __fastcall PBoxPaint(TObject *Sender); + void __fastcall TBBrightChange(TObject *Sender); + void __fastcall SBFNClick(TObject *Sender); + + void __fastcall ResBtnClick(TObject *Sender); + void __fastcall SBBRRClick(TObject *Sender); + void __fastcall SBCTRClick(TObject *Sender); + void __fastcall SBSPRClick(TObject *Sender); + void __fastcall SBCPRClick(TObject *Sender); + void __fastcall SBCORClick(TObject *Sender); + void __fastcall SBSTClick(TObject *Sender); + + void __fastcall AutoBtnClick(TObject *Sender); + void __fastcall TimerTimer(TObject *Sender); + void __fastcall SBEditClick(TObject *Sender); +private: + int m_DisEvent; + + Graphics::TBitmap *pBitmap; + Graphics::TBitmap *pBitmapS; + Graphics::TBitmap *pBitmapD; + + int m_Make; + double *pH; + double *pS; + + int m_XW; + int m_YW; + int m_Sync; + + void __fastcall UpdateBtn(void); + void __fastcall AdjustColor(int x, int y, double &RY, double &BY); + void __fastcall Filt(int sw); + void __fastcall Bright(void); +public: + virtual __fastcall TPicFilterDlg(TComponent* AOwner); + __fastcall TPicFilterDlg::~TPicFilterDlg(); + + int __fastcall TPicFilterDlg::Execute(Graphics::TBitmap *pBmp); + +#define CM_EDITEXIT WM_USER+404 +protected: + void __fastcall OnEditExit(TMessage Message); + +BEGIN_MESSAGE_MAP + MESSAGE_HANDLER(CM_EDITEXIT, TMessage, OnEditExit) +END_MESSAGE_MAP(TForm) +}; +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +#endif diff --git a/PicRect.cpp b/PicRect.cpp new file mode 100644 index 0000000..1934948 --- /dev/null +++ b/PicRect.cpp @@ -0,0 +1,1256 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "Clipbrd.hpp" +#include "PicRect.h" +#include "PicFilte.h" +#include "Main.h" +//--------------------------------------------------------------------- +#pragma resource "*.dfm" +//--------------------------------------------------------------------- +#define MARGIN 4 +#define MARGINW (MARGIN+MARGIN) +//--------------------------------------------------------------------- +__fastcall TPicRectDlg::TPicRectDlg(TComponent* AOwner) + : TForm(AOwner) +{ + FormStyle = ((TForm *)AOwner)->FormStyle; + EntryAlignControl(); + Font->Name = ((TForm *)AOwner)->Font->Name; + Font->Charset = ((TForm *)AOwner)->Font->Charset; + if( MsgEng ){ + CancelBtn->Caption = "Cancel"; + Label1->Caption = "Stretch mode"; + SBRatio->Hint = "Keep aspect ratio"; + SBStrach->Hint = "Stretching"; + SBNStrach->Hint = "No stretching"; + + SBRL->Hint = "Rotates left"; + SBRR->Hint = "Rotates right"; + SBMIR->Hint = "Right and left turning over"; + + KFS->Caption = "&Save..."; + KFSC->Caption = "Save clipping image..."; + KEC->Caption = "&Copy"; + KECC->Caption = "Copy clipping image"; + KVAS->Caption = "Show image as true size"; + + KEFC->Caption = "Choose space color"; + KEFCP->Caption = "Point"; + KEFCM->Caption = "Manual..."; + KEE->Caption = "&Edit image..."; + KEF->Caption = "Make space"; + KEFD->Caption = "Delete space"; + KER->Caption = "Rotation..."; + KEMC->Caption = "Centering"; + KEMM->Caption = "Clipping by maximum range"; + } + KF->Caption = Mmsstv->KFile->Caption; + KE->Caption = Mmsstv->KEdit->Caption; + KV->Caption = Mmsstv->KView->Caption; + KEP->Caption = Mmsstv->SBPaste->Hint; + KEU->Caption = Mmsstv->KTU->Caption; + SBC->Hint = KEF->Caption; + SBMax->Hint = KEMM->Caption; + SBFil->Hint = Mmsstv->SBTXFil->Hint; + SBRot->Hint = KER->Caption; + pBitmap = new Graphics::TBitmap(); + AdjustBitmapFormat(pBitmap); + m_Stretch = 0; + m_Cursor = 0; + m_MouseCapture = 0; + PBoxM->Left = 0; + PBoxM->Top = 0; + PBox->Left = MARGIN; + PBox->Top = MARGIN; + SBFil->Glyph->Assign(Mmsstv->SBHistFil->Glyph); + pBmpSrc = NULL; + m_Space = 0; + m_MouseColor = 0; + m_RotFlag = 0; + m_RotDeg = 0; +} + +__fastcall TPicRectDlg::~TPicRectDlg() +{ + g_ExecPB.Cancel(); + if( pBmpSrc != NULL ){ + delete pBmpSrc; + pBmpSrc = NULL; + } + if( pBitmap != NULL ){ + delete pBitmap; + pBitmap = NULL; + } +} + +//--------------------------------------------------------------------------- +// サイズ変更コントロールの登録 +void __fastcall TPicRectDlg::EntryAlignControl(void) +{ + RECT rc; + rc.left = 0; + rc.top = 0; + rc.right = 792-1; +// rc.bottom = 569-1; + rc.bottom = 546-1; + + AlignList.EntryControl(OKBtn, &rc, OKBtn->Font); + AlignList.EntryControl(CancelBtn, &rc, CancelBtn->Font); + AlignList.EntryControl(Panel, &rc, NULL); + AlignList.EntryControl(SB256, &rc, NULL); + AlignList.EntryControl(SB240T, &rc, NULL); + AlignList.EntryControl(SB240B, &rc, NULL); + AlignList.EntryControl(SBRatio, &rc, NULL); + AlignList.EntryControl(SBStrach, &rc, NULL); + AlignList.EntryControl(SBNStrach, &rc, NULL); + + AlignList.EntryControl(SBC, &rc, NULL); + AlignList.EntryControl(SBMax, &rc, NULL); + + AlignList.EntryControl(Label1, &rc, NULL); + AlignList.EntryControl(SMode, &rc, SMode->Font); + + AlignList.EntryControl(SBRL, &rc, NULL); + AlignList.EntryControl(SBRR, &rc, NULL); + AlignList.EntryControl(SBMIR, &rc, NULL); + AlignList.EntryControl(SBRot, &rc, NULL); + AlignList.EntryControl(SBFil, &rc, NULL); + + int CX = ::GetSystemMetrics(SM_CXFULLSCREEN); + int CY = ::GetSystemMetrics(SM_CYFULLSCREEN); +// int CX = ::GetSystemMetrics(SM_CXSCREEN); +// int CY = ::GetSystemMetrics(SM_CYSCREEN); + if( (CX < Width)||(CY < Height) ){ + Top = 0; + Left = 0; + Width = CX; + Height = CY; + } + FormCenter(this, CX, CY); + if( Owner != NULL ){ + WindowState = ((TForm *)Owner)->WindowState; + } +} +//--------------------------------------------------------------------------- +void __fastcall TPicRectDlg::AdjustRatio(void) +{ + double XW = pwBmp->Width; + double YW = pwBmp->Height; + if( (YW >= 256) && (SB240T->Down || SB240B->Down) ) YW -= 16; + + if( SBRatio->Down ){ + double xw = m_X2 - m_X1 + 1; + double yw = m_Y2 - m_Y1 + 1; + + if( (xw != XW) || (yw != YW) ){ + double xv = (xw * XW) / pBitmap->Width; + double yv = (yw * YW) / pBitmap->Height; + if( yv < xv ){ + yw = xw * YW / XW; + } + else { + xw = yw * XW / YW; + } +#if 0 + int xx = ABS(m_X2 - (m_X1 + xw)); + int yy = ABS(m_Y2 - (m_Y1 + yw)); + if( (xx <= 1) && (yy <= 1) ) return; +#endif + m_X2 = m_X1 + xw; + m_Y2 = m_Y1 + yw; + if( m_X2 >= pBitmap->Width ){ + int w = m_X2 - pBitmap->Width; + m_Y2 -= w * YW / XW; + } + if( m_Y2 >= pBitmap->Height ){ + int w = m_Y2 - pBitmap->Height; + m_X2 -= w * XW / YW; + } + if( m_X2 >= pBitmap->Width ) m_X2 = pBitmap->Width - 1; + if( m_Y2 >= pBitmap->Height ) m_Y2 = pBitmap->Height - 1; + } + } + else if( SBStrach->Down ){ + if( m_X2 >= pBitmap->Width ) m_X2 = pBitmap->Width - 1; + if( m_Y2 >= pBitmap->Height ) m_Y2 = pBitmap->Height - 1; + } + else { + m_X2 = m_X1 + XW - 1; + m_Y2 = m_Y1 + YW - 1; + } +} +//--------------------------------------------------------------------------- +void __fastcall TPicRectDlg::AdjustXY(int &X, int &Y) +{ + if( m_Stretch ){ + X /= m_sc; + Y /= m_sc; + } +} +//--------------------------------------------------------------------------- +void __fastcall TPicRectDlg::SetPBoxSize(void) +{ + if( (!KVAS->Checked) && ( + ((pBitmap->Height + MARGINW) > Panel->ClientHeight) || + ((pBitmap->Height + MARGINW) > Panel->ClientHeight) ) + ){ + m_Stretch = 1; + PBox->Width = Panel->ClientWidth - MARGINW; + PBox->Height = Panel->ClientHeight - MARGINW; + + m_Src.Left = 0; m_Src.Top = 0; + m_sx = double(pBitmap->Width) / double(PBox->Width); + m_sy = double(pBitmap->Height) / double(PBox->Height); + if( m_sx > m_sy ){ + m_Src.Right = PBox->Width; + m_Src.Bottom = pBitmap->Height / m_sx; + m_sc = 1.0/m_sx; + } + else { + m_Src.Bottom = PBox->Height; + m_Src.Right = pBitmap->Width / m_sy; + m_sc = 1.0/m_sy; + } + + SBH->Position = 0; + SBH->Enabled = FALSE; + SBH->Visible = FALSE; + SBV->Position = 0; + SBV->Enabled = FALSE; + SBV->Visible = FALSE; + } + else { + m_Stretch = 0; + int max; + if( (pBitmap->Width + MARGINW) > Panel->ClientWidth ){ + if( (pBitmap->Height + MARGINW) > Panel->ClientHeight ){ + PBox->Width = SBV->Left - MARGINW; + max = pBitmap->Width + MARGINW - SBV->Left - 1; + } + else { + PBox->Width = Panel->ClientWidth - MARGINW; + max = pBitmap->Width + MARGINW - Panel->ClientWidth - 1; + } + if( max < 0 ) max = 0; + SBH->Max = max; + SBH->Enabled = TRUE; + SBH->Visible = TRUE; + } + else { + PBox->Width = pBitmap->Width; + SBH->Position = 0; + SBH->Enabled = FALSE; + SBH->Visible = FALSE; + } + if( (pBitmap->Height + MARGINW) > Panel->ClientHeight ){ + if( SBH->Enabled == TRUE ){ + PBox->Height = SBH->Top - MARGINW; + max = pBitmap->Height + MARGINW - SBH->Top; + } + else { + PBox->Height = Panel->ClientHeight - MARGINW; + max = pBitmap->Height + MARGINW - Panel->ClientHeight; + } + if( max < 0 ) max = 0; + SBV->Max = max; + SBV->Enabled = TRUE; + SBV->Visible = TRUE; + } + else { + PBox->Height = pBitmap->Height; + SBV->Position = 0; + SBV->Enabled = FALSE; + SBV->Visible = FALSE; + } + } + PBoxM->Height = PBox->Height + MARGINW; + PBoxM->Width = PBox->Width + MARGINW; + UpdateTitle(); +} + +//--------------------------------------------------------------------------- +void __fastcall TPicRectDlg::FormResize(TObject *Sender) +{ + if( pBitmap == NULL ) return; + + CWaitCursor tw; + SBH->Position = 0; + SBV->Position = 0; + AlignList.NewAlign(this); + SetPBoxSize(); +// PBoxPaint(NULL); + PBox->Invalidate(); +} +//--------------------------------------------------------------------- +void __fastcall TPicRectDlg::UpdateTitle(void) +{ + if( pBitmap == NULL ) return; + if( pwBmp == NULL ) return; + char bf[128]; + int h = pwBmp->Height; + if( (h >= 256) && (SB240T->Down || SB240B->Down) ) h -= 16; + sprintf(bf, "%s - Source:%ux%u, Target:%ux%u", MsgEng ? "Picture clipper" : "画像クリッパー", pBitmap->Width, pBitmap->Height, pwBmp->Width, h); + Caption = bf; +} +//--------------------------------------------------------------------- +int __fastcall TPicRectDlg::Copy(Graphics::TBitmap *pbmp) +{ + if( (pBitmap->Width == pbmp->Width) && (pBitmap->Height == pbmp->Height) ){ + ::CopyBitmap(pbmp, pBitmap); + return TRUE; + } + else { + return Execute(pbmp); + } +} +//--------------------------------------------------------------------- +int __fastcall TPicRectDlg::Execute(Graphics::TBitmap *pbmp) +{ + MultProc(); + pwBmp = pbmp; + if( pwBmp->Height < 256 ){ + SB256->Enabled = FALSE; + SB240T->Enabled = FALSE; + SB240B->Enabled = FALSE; + } + KVAS->Checked = !sys.m_PicClipView; + SetPBoxSize(); + m_X1 = 0; + m_Y1 = 0; + m_X2 = pBitmap->Width - 1; + m_Y2 = pBitmap->Height - 1; + switch(sys.m_PicClipType){ + case 0: + SB256->Down = TRUE; + break; + case 1: + SB240T->Down = TRUE; + break; + case 2: + SB240B->Down = TRUE; + break; + } + SMode->ItemIndex = sys.m_PicClipMode; + switch(sys.m_PicClipRatio){ + case 0: + SBStrach->Down = 1; + break; + case 1: + SBRatio->Down = 1; + break; + default: + SBNStrach->Down = 1; + break; + } + AdjustRatio(); + + if( SBRatio->Down ) SBMaxClick(NULL); + MultProc(); + int r = ShowModal(); + MultProc(); + sys.m_PicClipView = !KVAS->Checked; + if( SBRatio->Down ){ + sys.m_PicClipRatio = 1; + } + else if( SBStrach->Down ){ + sys.m_PicClipRatio = 0; + } + else { + sys.m_PicClipRatio = 2; + } + if( SB240T->Down ){ + sys.m_PicClipType = 1; + } + else if( SB240B->Down ){ + sys.m_PicClipType = 2; + } + else { + sys.m_PicClipType = 0; + } + sys.m_PicClipMode = SMode->ItemIndex; + if( r == IDOK ){ + TRect rc; + FillBitmap(pwBmp, sys.m_PicClipColor); + if( pwBmp->Height >= 256 ){ + rc.Left = 0; rc.Top = SB240B->Down ? 16 : 0; + rc.Right = pwBmp->Width; + rc.Bottom = SB240T->Down ? pwBmp->Height - 16 : pwBmp->Height; + } + else { + rc.Left = 0; rc.Top = 0; + rc.Right = pwBmp->Width; + rc.Bottom = pwBmp->Height; + } + TRect sc; + sc.Left = m_X1; + sc.Top = m_Y1; + sc.Right = m_X2 + 1; + sc.Bottom = m_Y2 + 1; + if( SBNStrach->Down ){ + if( sc.Right > pBitmap->Width ){ + int w = sc.Right - pBitmap->Width; + sc.Right -= w; + rc.Right -= w; + } + if( sc.Bottom > pBitmap->Height ){ + int w = sc.Bottom - pBitmap->Height; + sc.Bottom -= w; + rc.Bottom -= w; + } + } + pwBmp->Canvas->CopyMode = cmSrcCopy; + int Sop; + if( (sys.m_PicClipMode == 0) || SBNStrach->Down ){ + Sop = ::SetStretchBltMode(pwBmp->Canvas->Handle, HALFTONE); + } + else if( sys.m_PicClipMode == 1 ){ + Sop = ::SetStretchBltMode(pwBmp->Canvas->Handle, WHITEONBLACK); + } + else if( sys.m_PicClipMode == 2 ){ + Sop = ::SetStretchBltMode(pwBmp->Canvas->Handle, COLORONCOLOR); + } + else if( sys.m_PicClipMode == 3 ){ + Sop = ::SetStretchBltMode(pwBmp->Canvas->Handle, BLACKONWHITE); + } + else { + NormalRect(&sc); //ja7ude 0521 + ::StretchCopy(pwBmp, &rc, pBitmap, &sc); + MultProc(); + return TRUE; + } + MultProc(); + pwBmp->Canvas->CopyRect(rc, pBitmap->Canvas, sc); + ::SetStretchBltMode(pwBmp->Canvas->Handle, Sop); + MultProc(); + return TRUE; + } + return FALSE; +} +//--------------------------------------------------------------------- +void __fastcall TPicRectDlg::PBoxPaint(TObject *Sender) +{ + if( m_Stretch ){ + ::SetStretchBltMode(PBox->Canvas->Handle, HALFTONE); + PBox->Canvas->StretchDraw(m_Src, pBitmap); + } + else { + PBox->Canvas->Draw(-SBH->Position, -SBV->Position, pBitmap); + } + DrawCursor(); + m_Cursor = 1; + if( m_RotFlag ){ + PBox->Canvas->Brush->Color = clWhite; + PBox->Canvas->Font->Size = 16; + PBox->Canvas->TextOut(0, 0, MsgEng ? "[Rotation] Draw a base line" : "[回転] ベースラインを引いてください"); + } +} +//--------------------------------------------------------------------------- +void __fastcall TPicRectDlg::DrawCursor(void) +{ + int X1 = (m_RotFlag ? m_RotX1 : m_X1) - SBH->Position; + int Y1 = (m_RotFlag ? m_RotY1 : m_Y1) - SBV->Position; + int X2 = (m_RotFlag ? m_RotX2 : m_X2) - SBH->Position; + int Y2 = (m_RotFlag ? m_RotY2 : m_Y2) - SBV->Position; + + if( m_Stretch ){ + X1 *= m_sc; + Y1 *= m_sc; + X2 *= m_sc; + Y2 *= m_sc; + } + PBox->Canvas->Pen->Style = psDot; + PBox->Canvas->Pen->Color = clYellow; + PBox->Canvas->Pen->Width = 2; + PBox->Canvas->MoveTo(X1, Y1); + int Sop = ::SetROP2(PBox->Canvas->Handle, R2_NOT); + if( m_RotFlag ){ + PBox->Canvas->LineTo(X2, Y2); + } + else { + PBox->Canvas->LineTo(X2, Y1); + PBox->Canvas->LineTo(X2, Y2); + PBox->Canvas->LineTo(X1, Y2); + PBox->Canvas->LineTo(X1, Y1); + } + ::SetROP2(PBox->Canvas->Handle, Sop); +} +//--------------------------------------------------------------------------- +void __fastcall TPicRectDlg::PBoxMouseDown(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( Button == mbLeft ){ + AdjustXY(X, Y); + if( m_RotFlag ){ + if( m_Cursor ) DrawCursor(); + + m_RotX1 = m_RotX2 = X - MARGIN + SBH->Position; + m_RotY1 = m_RotY2 = Y - MARGIN + SBV->Position; + m_MouseCapture = 1; + } + else if( m_MouseColor ){ + X = X - MARGIN + SBH->Position; + Y = Y - MARGIN + SBV->Position; + m_MouseColor = 0; + if( X < 0 ) X = 0; + if( X >= pBitmap->Width ) X = pBitmap->Width - 1; + if( Y < 0 ) Y = 0; + if( Y >= pBitmap->Height ) Y = pBitmap->Height - 1; + sys.m_PicClipColor = pBitmap->Canvas->Pixels[X][Y]; + KEFClick(NULL); + } + else { + m_CW = m_X2 - m_X1; + m_CH = m_Y2 - m_Y1; + if( m_Cursor ) DrawCursor(); + + m_X1 = X - MARGIN + SBH->Position; + m_Y1 = Y - MARGIN + SBV->Position; + if( m_X1 < 0 ) m_X1 = 0; + if( m_Y1 < 0 ) m_Y1 = 0; + m_Cursor = 0; + if( !SBNStrach->Down ){ + m_X2 = m_X1; + m_Y2 = m_Y1; + m_MouseCapture = 1; + } + else { + m_X2 = m_X1 + pwBmp->Width - 1; + m_Y2 = m_Y1 + pwBmp->Height - 1; + if( (pwBmp->Height == 256) && !SB256->Down ) m_Y2 -= 16; + PBoxPaint(NULL); + } + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TPicRectDlg::PBoxMouseMove(TObject *Sender, + TShiftState Shift, int X, int Y) +{ + if( !m_MouseCapture ) return; + + AdjustXY(X, Y); + m_MouseCapture = 2; + if( m_RotFlag ){ + if( m_Cursor ) DrawCursor(); + m_RotX2 = X + SBH->Position; + m_RotY2 = Y + SBV->Position; + DrawCursor(); + m_Cursor = 1; + } + else if( !m_Stretch && ( + (X > PBox->Width) || + (Y > PBox->Height) || + (X < 0) || + (Y < 0) ) + ){ + m_X2 = X - MARGIN + SBH->Position; + m_Y2 = Y - MARGIN + SBV->Position; + if( X >= PBox->Width + MARGIN ){ + if( SBH->Enabled ){ + SBH->Position = m_X2 - PBox->Width; + } + else { + m_X2 = pBitmap->Width; + } + } + else if( X < 0 ){ + if( SBH->Enabled && SBH->Position ){ + int x = SBH->Position + X; + if( x < 0 ) x = 0; + SBH->Position = x; + } + else { + m_X2 = 0; + } + } + if( Y >= PBox->Height + MARGIN ){ + if( SBV->Enabled ){ + SBV->Position = m_Y2 - PBox->Height; + } + else { + m_Y2 = pBitmap->Height; + } + } + else if( Y < 0 ){ + if( SBV->Enabled && SBV->Position ){ + int y = SBV->Position + Y; + if( y < 0 ) y = 0; + SBV->Position = y; + } + else { + m_Y2 = 0; + } + } + if( m_X2 < 0 ) m_X2 = 0; + if( m_Y2 < 0 ) m_Y2 = 0; + if( m_X2 >= pBitmap->Width ) m_X2 = pBitmap->Width - 1; + if( m_Y2 >= pBitmap->Height ) m_Y2 = pBitmap->Height - 1; + AdjustRatio(); + PBoxPaint(NULL); + } + else { + if( m_Cursor ) DrawCursor(); + m_X2 = X + SBH->Position; + m_Y2 = Y + SBV->Position; + if( m_X2 < 0 ) m_X2 = 0; + if( m_Y2 < 0 ) m_Y2 = 0; + if( m_X2 >= pBitmap->Width ) m_X2 = pBitmap->Width - 1; + if( m_Y2 >= pBitmap->Height ) m_Y2 = pBitmap->Height - 1; + AdjustRatio(); + DrawCursor(); + m_Cursor = 1; + } +} +//--------------------------------------------------------------------------- +void __fastcall TPicRectDlg::PBoxMouseUp(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( m_MouseCapture ){ + AdjustXY(X, Y); + m_MouseCapture = 0; + if( m_RotFlag ){ + m_RotX2 = X + SBH->Position; + m_RotY2 = Y + SBV->Position; + RotPic(-atan2(m_RotY2 - m_RotY1, m_RotX2 - m_RotX1) * 180.0 / PI); + } + else if( (ABS(m_X1-m_X2)<4) || (ABS(m_Y1-m_Y2)<4) ){ + m_X2 = m_X1 + m_CW; + m_Y2 = m_Y2 + m_CH; + if( !SBNStrach->Down ){ + AdjustRatio(); + } + } + PBoxPaint(NULL); + } +} +//--------------------------------------------------------------------------- +void __fastcall TPicRectDlg::SBVChange(TObject *Sender) +{ + PBoxPaint(NULL); +} +//--------------------------------------------------------------------------- +void __fastcall TPicRectDlg::SBRatioClick(TObject *Sender) +{ + if( SBRatio->Down ){ + if( m_X2 >= pBitmap->Width ) m_X2 = pBitmap->Width - 1; + if( m_Y2 >= pBitmap->Height ) m_Y2 = pBitmap->Height - 1; + } + AdjustRatio(); + UpdateTitle(); + PBoxPaint(NULL); +} +//--------------------------------------------------------------------------- +void __fastcall TPicRectDlg::SBRLClick(TObject *Sender) +{ + if( pBitmap == NULL ) return; + + CWaitCursor w; + pBitmap = Bitmap24bit(pBitmap); + Graphics::TBitmap *pBmp = new Graphics::TBitmap(); + pBmp->PixelFormat = pBitmap->PixelFormat; + pBmp->Height = pBitmap->Width; + pBmp->Width = pBitmap->Height; + int x, y; + BYTE *sp, *tp; + for( y = 0; y < pBitmap->Height; y++ ){ + sp = (BYTE *)pBitmap->ScanLine[y]; + for( x = 0; x < pBitmap->Width; x++ ){ + tp = (BYTE *)pBmp->ScanLine[pBitmap->Width - x - 1]; + tp += (y * 3); + *tp++ = *sp++; + *tp++ = *sp++; + *tp = *sp++; + } + } + delete pBitmap; + pBitmap = pBmp; + SetPBoxSize(); + AdjustRatio(); + PBox->Invalidate(); +} +//--------------------------------------------------------------------------- +void __fastcall TPicRectDlg::SBRRClick(TObject *Sender) +{ + if( pBitmap == NULL ) return; + + CWaitCursor w; + pBitmap = Bitmap24bit(pBitmap); + Graphics::TBitmap *pBmp = new Graphics::TBitmap(); + pBmp->PixelFormat = pBitmap->PixelFormat; + pBmp->Height = pBitmap->Width; + pBmp->Width = pBitmap->Height; + int x, y; + BYTE *sp, *tp; + for( y = 0; y < pBitmap->Height; y++ ){ + sp = (BYTE *)pBitmap->ScanLine[y]; + for( x = 0; x < pBitmap->Width; x++ ){ + tp = (BYTE *)pBmp->ScanLine[x]; + tp += ((pBitmap->Height - y - 1) * 3); + *tp++ = *sp++; + *tp++ = *sp++; + *tp = *sp++; + } + } + delete pBitmap; + pBitmap = pBmp; + SetPBoxSize(); + AdjustRatio(); + PBox->Invalidate(); +} +//--------------------------------------------------------------------------- +void __fastcall TPicRectDlg::SBMIRClick(TObject *Sender) +{ + if( pBitmap == NULL ) return; + + CWaitCursor w; + pBitmap = Bitmap24bit(pBitmap); + Graphics::TBitmap *pBmp = new Graphics::TBitmap(); + pBmp->PixelFormat = pBitmap->PixelFormat; + pBmp->Height = pBitmap->Height; + pBmp->Width = pBitmap->Width; + int x, y; + BYTE *sp, *tp; + for( y = 0; y < pBitmap->Height; y++ ){ + sp = (BYTE *)pBitmap->ScanLine[y]; + tp = (BYTE *)pBmp->ScanLine[y]; + tp += ((pBitmap->Width - 1) * 3); + for( x = 0; x < pBitmap->Width; x++ ){ + *tp++ = *sp++; + *tp++ = *sp++; + *tp = *sp++; + tp -= 5; + } + } + delete pBitmap; + pBitmap = pBmp; + SetPBoxSize(); + AdjustRatio(); + PBox->Invalidate(); +} +//--------------------------------------------------------------------------- +void __fastcall TPicRectDlg::SBFilClick(TObject *Sender) +{ + TPicFilterDlg *pBox = new TPicFilterDlg(this); + if( pBox->Execute(pBitmap) == TRUE ){ + PBox->Invalidate(); + } + delete pBox; +} +//--------------------------------------------------------------------------- +void __fastcall TPicRectDlg::KFClick(TObject *Sender) +{ + KECC->Enabled = m_Cursor; + KFSC->Enabled = m_Cursor; + KEF->Enabled = !m_Space; + KEFD->Enabled = m_Space; + KEP->Enabled = ::IsClipboardFormatAvailable(CF_BITMAP); + KEU->Enabled = pBmpSrc != NULL; +} +//--------------------------------------------------------------------------- +void __fastcall TPicRectDlg::KEFCMClick(TObject *Sender) +{ + TColor col = sys.m_PicClipColor; + Mmsstv->KSBClick(NULL); + if( col != sys.m_PicClipColor ){ + MultProc(); + KEFClick(NULL); + } +} +//--------------------------------------------------------------------------- +void __fastcall TPicRectDlg::KEFClick(TObject *Sender) +{ + CWaitCursor w; + SaveSrc(); + if( pBmpSrc != NULL ){ + m_RotDeg = 0; + pBitmap->PixelFormat = pf24bit; + int W = pwBmp->Width > pBmpSrc->Width ? pwBmp->Width : pBmpSrc->Width; + int H = pwBmp->Height > pBmpSrc->Height ? pwBmp->Height : pBmpSrc->Height; + pBitmap->Width = (W * 5)/2; + pBitmap->Height = (H * 5)/2; + FillBitmap(pBitmap, sys.m_PicClipColor); + MultProc(); + int x = (pBitmap->Width - pBmpSrc->Width) / 2; + int y = (pBitmap->Height - pBmpSrc->Height) / 2; + pBitmap->Canvas->Draw(x, y, pBmpSrc); + m_Space = 1; SBC->Down = TRUE; + SetPBoxSize(); + SetCenter(); + if( SBV->Visible ) SBV->Position = SBV->Max / 2; + if( SBH->Visible ) SBH->Position = SBH->Max / 2; + } +} +//--------------------------------------------------------------------------- +void __fastcall TPicRectDlg::KEFDClick(TObject *Sender) +{ + if( pBmpSrc != NULL ){ + m_RotDeg = 0; + delete pBitmap; + pBitmap = pBmpSrc; + pBmpSrc = NULL; + m_Space = 0; SBC->Down = FALSE; + m_RotFlag = 0; SBRot->Down = FALSE; + SetPBoxSize(); + SBMaxClick(NULL); + SetCenter(); + } +} +//--------------------------------------------------------------------------- +Graphics::TBitmap * __fastcall TPicRectDlg::GetClipBitmap(void) +{ + int x1 = m_X1; + int x2 = m_X2; + int y1 = m_Y1; + int y2 = m_Y2; + NormalRect(x1, y1, x2, y2); + int xw = x2 - x1 + 1; + int yw = y2 - y1; + Graphics::TBitmap *pBmp = new Graphics::TBitmap(); + pBmp->PixelFormat = pf24bit; + pBmp->Width = xw; + pBmp->Height = yw; + TRect rc; + TRect sc; + rc.Left = 0; rc.Top = 0; + rc.Right = xw; + rc.Bottom = yw; + sc.Left = x1; sc.Top = y1; + sc.Right = x1 + xw; + sc.Bottom = y1 + yw; + pBmp->Canvas->CopyRect(rc, pBitmap->Canvas, sc); + return pBmp; +} +//--------------------------------------------------------------------------- +void __fastcall TPicRectDlg::KECClick(TObject *Sender) +{ + Mmsstv->CopyBitmap(pBitmap); +} +//--------------------------------------------------------------------------- +void __fastcall TPicRectDlg::KECCClick(TObject *Sender) +{ + Graphics::TBitmap *pBmp = GetClipBitmap(); + Mmsstv->CopyBitmap(pBmp); + delete pBmp; +} +//--------------------------------------------------------------------------- +void __fastcall TPicRectDlg::KFSClick(TObject *Sender) +{ + Mmsstv->SaveBitmapMenu(pBitmap, "Image", NULL); +} +//--------------------------------------------------------------------------- +void __fastcall TPicRectDlg::KFSCClick(TObject *Sender) +{ + Graphics::TBitmap *pBmp = GetClipBitmap(); + Mmsstv->SaveBitmapMenu(pBmp, "Image", NULL); + delete pBmp; +} +//--------------------------------------------------------------------------- +void __fastcall TPicRectDlg::SetCenter(void) +{ +#if 0 + int xw = ABS(m_X2 - m_X1 + 1); + int yw = ABS(m_Y2 - m_Y1 + 1); +#else + int xw = ABS(m_X2 - m_X1 + 1); + int yw = ABS(m_Y2 - m_Y1 + 1); + if( m_Space && (pBmpSrc != NULL) ){ + if( xw < pBmpSrc->Width ){ + yw = yw * pBmpSrc->Width / xw; + xw = pBmpSrc->Width; + } + else if( yw < pBmpSrc->Height ){ + xw = xw * pBmpSrc->Height / yw; + yw = pBmpSrc->Height; + } + } +#endif + m_X1 = (pBitmap->Width - xw) / 2; + m_Y1 = (pBitmap->Height - yw) / 2; + if( m_X1 < 0 ) m_X1 = 0; + if( m_Y1 < 0 ) m_Y1 = 0; + m_X2 = m_X1 + xw - 1; + m_Y2 = m_Y1 + yw - 1; + AdjustRatio(); + PBox->Invalidate(); +} +//--------------------------------------------------------------------------- +void __fastcall TPicRectDlg::KEMCClick(TObject *Sender) +{ + SetCenter(); +} +//--------------------------------------------------------------------------- +void __fastcall TPicRectDlg::KEMMClick(TObject *Sender) +{ + m_X1 = 0; + m_Y1 = 0; + m_X2 = pBitmap->Width - 1; + m_Y2 = pBitmap->Height - 1; + AdjustRatio(); + PBoxPaint(NULL); +} +//--------------------------------------------------------------------------- +void __fastcall TPicRectDlg::SBMaxClick(TObject *Sender) +{ + KEMMClick(NULL); + KEMCClick(NULL); +} +//--------------------------------------------------------------------------- +void __fastcall TPicRectDlg::KVASClick(TObject *Sender) +{ + InvMenu(KVAS); + SetPBoxSize(); + PBox->Invalidate(); +} +//--------------------------------------------------------------------------- +void __fastcall TPicRectDlg::KEFCPClick(TObject *Sender) +{ + m_MouseColor = 1; +} +//--------------------------------------------------------------------------- +void __fastcall TPicRectDlg::FormKeyDown(TObject *Sender, WORD &Key, + TShiftState Shift) +{ + if( Key == 0 ) return; + + TShiftState sf1, sf2; + + sf1 << ssShift; + sf2 << ssShift; + sf1 *= Shift; + if( m_Cursor ) DrawCursor(); + if( sf1 == sf2 ){ // Shift+Any + switch(Key){ + case VK_UP: + m_Y2 -= 1; + Key = 0; + break; + case VK_DOWN: + m_Y2 += 1; + Key = 0; + break; + case VK_LEFT: + m_X2 -= 1; + Key = 0; + break; + case VK_RIGHT: + m_X2 += 1; + Key = 0; + break; + } + if( Key == 0 && !(SBStrach->Down) ){ + SBStrach->Down = TRUE; + } + } + else { + TShiftState ct1, ct2; + ct1 << ssCtrl; + ct2 << ssCtrl; + ct1 *= Shift; + int d = (ct1 == ct2) ? 16 : 1; + switch(Key){ + case VK_UP: + m_Y1 -= d; + m_Y2 -= d; + Key = 0; + break; + case VK_DOWN: + m_Y1 += d; + m_Y2 += d; + Key = 0; + break; + case VK_LEFT: + m_X1 -= d; + m_X2 -= d; + Key = 0; + break; + case VK_RIGHT: + m_X1 += d; + m_X2 += d; + Key = 0; + break; + } + if( !m_Space ){ + if( m_X1 < 0 ){ d = -m_X1; m_X1 += d; m_X2 += d; } + if( m_Y1 < 0 ){ d = -m_Y1; m_Y1 += d; m_Y2 += d; } + if( m_X2 > pBitmap->Width ){ d = m_X2 - pBitmap->Width; m_X1 -= d; m_X2 -= d; } + if( m_Y2 > pBitmap->Height ){ d = m_Y2 - pBitmap->Height; m_Y1 -= d; m_Y2 -= d; } + } + } + if( m_Cursor ) DrawCursor(); +} +//--------------------------------------------------------------------------- +void __fastcall TPicRectDlg::SBCClick(TObject *Sender) +{ + if( SBC->Down ){ + KEFClick(NULL); + } + else { + KEFDClick(NULL); + } +} +//--------------------------------------------------------------------------- +void __fastcall TPicRectDlg::SBCMouseDown(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( Button == mbRight ) KEFCMClick(NULL); +} +//--------------------------------------------------------------------------- +void __fastcall TPicRectDlg::SBMaxMouseDown(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( Button == mbRight ) KEMCClick(NULL); +} +//--------------------------------------------------------------------------- +void __fastcall TPicRectDlg::KEPClick(TObject *Sender) +{ + CWaitCursor w; + TClipboard *pCB = Clipboard(); + if (pCB->HasFormat(CF_BITMAP)){ + if( pBmpSrc != NULL ){ + delete pBmpSrc; + pBmpSrc = NULL; + } + Graphics::TBitmap *pBmp = new Graphics::TBitmap(); + try + { + pBmp->LoadFromClipboardFormat(CF_BITMAP, pCB->GetAsHandle(CF_BITMAP), 0); + delete pBitmap; + pBitmap = pBmp; + m_RotDeg = 0; + SetPBoxSize(); + SBMaxClick(NULL); +// AdjustRatio(); + PBox->Invalidate(); + } + catch (...) + { + } + } +} +//--------------------------------------------------------------------------- +// Rot pic +static void __fastcall RotPic(Graphics::TBitmap *pSrc, Graphics::TBitmap *pTer, double deg, TColor back) +{ + deg *= PI / 180.0; + double sinx = sin(deg); + double cosx = cos(deg); + + if( (pSrc->Width < 2) || (pSrc->Height < 2) ){ + CopyBitmap(pTer, pSrc); + } + else { + Graphics::TBitmap *pS = DupeBitmap(pSrc, pf24bit); + Graphics::TBitmap *pT = new Graphics::TBitmap; + pT->PixelFormat = pf24bit; + pT->Width = pTer->Width; + pT->Height = pTer->Height; + if( pT->Width & 1 ) pT->Width--; + if( pT->Height & 1 ) pT->Height--; + int i, j, m, n; + double x, y, p, q; + int xs = pT->Width / 2; + int ys = pT->Height / 2; + BYTE *sp1, *sp2; + BYTE *tp; + BYTE br = (BYTE)(back >> 16); + BYTE bg = (BYTE)(back >> 8); + BYTE bb = (BYTE)back; + int r, g, b; + for( i = -ys; i < ys; i++ ){ + tp = (BYTE *)pT->ScanLine[i+ys]; + for( j = -xs; j < xs; j++ ){ + x = cosx * j + sinx * i; + y = -sinx * j + cosx * i; + if( y > 0 ){ m = int(y); } else { m = int(y-1); } + if( x > 0 ){ n = int(x); } else { n = int(x-1); } + q = y - m; + p = x - n; + double pp = 1.0 - p; + double qq = 1.0 - q; + if( (m >= -ys) && (m < ys-1) && (n >= -xs) && (n < xs-1) ){ + sp1 = (BYTE *)pS->ScanLine[m+ys] + (n+xs)*3; + sp2 = (BYTE *)pS->ScanLine[m+ys+1] + (n+xs)*3; + if( (*sp1 != *sp2) || (*sp1 != *(sp1+3)) || (*sp1 != *(sp2+3)) ){ + r = (int)(qq*(pp*(*sp1) + p*(*(sp1+3))) + + q * (pp*(*sp2) + p*(*(sp2+3)))); + } + else { + r = *sp1; + } + sp1++; sp2++; + if( (*sp1 != *sp2) || (*sp1 != *(sp1+3)) || (*sp1 != *(sp2+3)) ){ + g = (int)(qq*(pp*(*sp1) + p*(*(sp1+3))) + + q * (pp*(*sp2) + p*(*(sp2+3)))); + } + else { + g = *sp1; + } + sp1++; sp2++; + if( (*sp1 != *sp2) || (*sp1 != *(sp1+3)) || (*sp1 != *(sp2+3)) ){ + b = (int)(qq*(pp*(*sp1) + p*(*(sp1+3))) + + q * (pp*(*sp2) + p*(*(sp2+3)))); + } + else { + b = *sp1; + } + if( r < 0 ) r = 0; + if( r > 255 ) r = 255; + if( g < 0 ) g = 0; + if( g > 255 ) g = 255; + if( b < 0 ) b = 0; + if( b > 255 ) b = 255; + *tp++ = BYTE(r); + *tp++ = BYTE(g); + *tp++ = BYTE(b); + } + else { + *tp++ = br; + *tp++ = bg; + *tp++ = bb; + } + } + } + pTer->Width = pT->Width; + pTer->Height = pT->Height; + pTer->Palette = NULL; + pTer->Canvas->Draw(0, 0, pT); + delete pT; + delete pS; + } +} +//--------------------------------------------------------------------------- +void __fastcall TPicRectDlg::RotPic(double deg) +{ + CWaitCursor w; + if( m_Space ) KEFDClick(NULL); + SaveSrc(); + if( pBmpSrc != NULL ){ + deg += m_RotDeg; + m_RotDeg = deg; + double rdeg = deg * PI/180.0; + double sinx = sin(rdeg); + double cosx = cos(rdeg); + int x = pBmpSrc->Width / 2; + int y = pBmpSrc->Height / 2; + POINT P[4]; + P[0].x = -x * cosx + y * sinx; + P[0].y = -x * sinx - y * cosx; + P[1].x = x * cosx + y * sinx; + P[1].y = x * sinx - y * cosx; + P[2].x = x * cosx - y * sinx; + P[2].y = x * sinx + y * cosx; + P[3].x = -x * cosx - y * sinx; + P[3].y = -x * sinx + y * cosx; + int xmin = P[0].x; + int ymin = P[0].y; + int xmax = xmin; + int ymax = ymin; + for( int i = 1; i < 4; i++ ){ + if( xmin > P[i].x ) xmin = P[i].x; + if( ymin > P[i].y ) ymin = P[i].y; + if( xmax < P[i].x ) xmax = P[i].x; + if( ymax < P[i].y ) ymax = P[i].y; + } + Graphics::TBitmap *pSrc = new Graphics::TBitmap; + int xw = xmax - xmin; + int yw = ymax - ymin; + if( xw < pBmpSrc->Width ) xw = pBmpSrc->Width; + if( yw < pBmpSrc->Height ) yw = pBmpSrc->Height; + pBitmap->Width = xw; + pBitmap->Height = yw; + pSrc->Width = xw; + pSrc->Height = yw; + FillBitmap(pSrc, sys.m_PicClipColor); + x = (pSrc->Width - pBmpSrc->Width) / 2; + y = (pSrc->Height - pBmpSrc->Height) / 2; + pSrc->Canvas->Draw(x, y, pBmpSrc); + MultProc(); + ::RotPic(pSrc, pBitmap, deg, sys.m_PicClipColor); + delete pSrc; + SetPBoxSize(); + SetCenter(); + if( SBV->Visible ) SBV->Position = SBV->Max / 2; + if( SBH->Visible ) SBH->Position = SBH->Max / 2; + } + m_RotFlag = 0; + SBRot->Down = FALSE; +} +//--------------------------------------------------------------------------- +void __fastcall TPicRectDlg::KERClick(TObject *Sender) +{ + AnsiString as; + if( InputMB(NULL, MsgEng ? "Enter rotation degree" : "回転角(°)を入力", as) == IDOK ){ + double deg; + if( sscanf(as.c_str(), "%lf", °) != 1 ) return; + RotPic(deg); + } +} +//--------------------------------------------------------------------------- +void __fastcall TPicRectDlg::SBRotClick(TObject *Sender) +{ + m_RotFlag = SBRot->Down; + m_RotX1 = m_RotX2 = m_RotY1 = m_RotY2 = -1; + PBoxPaint(NULL); +} +//--------------------------------------------------------------------------- +void __fastcall TPicRectDlg::SBRotMouseDown(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( Button == mbRight ) KERClick(NULL); +} +//--------------------------------------------------------------------------- +void __fastcall TPicRectDlg::KEUClick(TObject *Sender) +{ + KEFDClick(NULL); +} +//--------------------------------------------------------------------------- +void __fastcall TPicRectDlg::SaveSrc(void) +{ + if( pBmpSrc == NULL ){ + pBmpSrc = DupeBitmap(pBitmap, pf24bit); + MultProc(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TPicRectDlg::KEEClick(TObject *Sender) +{ + g_ExecPB.Exec(pBitmap, (HWND)Handle, CM_EDITEXIT, 0); +} +//--------------------------------------------------------------------------- +void __fastcall TPicRectDlg::OnEditExit(TMessage Message) +{ + if( Message.LParam ) return; + + if( g_ExecPB.LoadBitmap(pBitmap, TRUE) ){ + if( pBmpSrc != NULL ){ + delete pBmpSrc; + pBmpSrc = NULL; + } + m_RotDeg = 0; + SetPBoxSize(); + SBMaxClick(NULL); + PBox->Invalidate(); + } +} +//--------------------------------------------------------------------------- diff --git a/PicRect.dfm b/PicRect.dfm new file mode 100644 index 0000000..122c38d Binary files /dev/null and b/PicRect.dfm differ diff --git a/PicRect.h b/PicRect.h new file mode 100644 index 0000000..8ff87eb --- /dev/null +++ b/PicRect.h @@ -0,0 +1,188 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//---------------------------------------------------------------------------- +#ifndef PicRectH +#define PicRectH +//---------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ComLib.h" +#include +//---------------------------------------------------------------------------- +class TPicRectDlg : public TForm +{ +__published: + TButton *OKBtn; + TButton *CancelBtn; + TPanel *Panel; + TScrollBar *SBH; + TScrollBar *SBV; + TPaintBox *PBox; + TSpeedButton *SB256; + TSpeedButton *SB240T; + TSpeedButton *SB240B; + TPaintBox *PBoxM; + TSpeedButton *SBRatio; + TLabel *Label1; + TSpeedButton *SBRL; + TSpeedButton *SBRR; + TSpeedButton *SBMIR; + TSpeedButton *SBFil; + TSpeedButton *SBStrach; + TComboBox *SMode; + TSpeedButton *SBNStrach; + TSpeedButton *SBMax; + TSpeedButton *SBC; + TMainMenu *MMenu; + TMenuItem *KF; + TMenuItem *KE; + TMenuItem *KV; + TMenuItem *KFS; + TMenuItem *KFSC; + TMenuItem *KEC; + TMenuItem *KECC; + TMenuItem *KEP; + TMenuItem *KVAS; + TMenuItem *N7; + TMenuItem *KEFC; + TMenuItem *KEFCM; + TMenuItem *KEFCP; + TMenuItem *KEF; + TMenuItem *KEFD; + TMenuItem *N8; + TMenuItem *KEMC; + TMenuItem *KEMM; + TMenuItem *N1; + TMenuItem *KER; + TSpeedButton *SBRot; + TMenuItem *N2; + TMenuItem *KEU; + TMenuItem *N3; + TMenuItem *KEE; + void __fastcall PBoxPaint(TObject *Sender); + void __fastcall PBoxMouseDown(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + void __fastcall PBoxMouseUp(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + void __fastcall PBoxMouseMove(TObject *Sender, TShiftState Shift, + int X, int Y); + void __fastcall FormResize(TObject *Sender); + void __fastcall SBVChange(TObject *Sender); + + void __fastcall SBRatioClick(TObject *Sender); + void __fastcall SBRLClick(TObject *Sender); + void __fastcall SBRRClick(TObject *Sender); + void __fastcall SBMIRClick(TObject *Sender); + void __fastcall SBFilClick(TObject *Sender); + void __fastcall KEFCMClick(TObject *Sender); + void __fastcall KEFClick(TObject *Sender); + void __fastcall KECClick(TObject *Sender); + void __fastcall KECCClick(TObject *Sender); + void __fastcall KFSClick(TObject *Sender); + void __fastcall KFSCClick(TObject *Sender); + void __fastcall KEFDClick(TObject *Sender); + void __fastcall KEMCClick(TObject *Sender); + void __fastcall KEMMClick(TObject *Sender); + void __fastcall SBMaxClick(TObject *Sender); + void __fastcall KVASClick(TObject *Sender); + void __fastcall KEFCPClick(TObject *Sender); + void __fastcall FormKeyDown(TObject *Sender, WORD &Key, + TShiftState Shift); + + + void __fastcall SBCClick(TObject *Sender); + void __fastcall SBCMouseDown(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + void __fastcall SBMaxMouseDown(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + + void __fastcall KEPClick(TObject *Sender); + + void __fastcall KFClick(TObject *Sender); + void __fastcall KERClick(TObject *Sender); + + void __fastcall SBRotClick(TObject *Sender); + void __fastcall SBRotMouseDown(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + void __fastcall KEUClick(TObject *Sender); + void __fastcall KEEClick(TObject *Sender); + +private: + Graphics::TBitmap *pwBmp; + Graphics::TBitmap *pBmpSrc; + + CAlignList AlignList; + void __fastcall EntryAlignControl(void); + void __fastcall UpdateTitle(void); + + void __fastcall AdjustRatio(void); + + int m_X1, m_Y1; + int m_X2, m_Y2; + int m_CW, m_CH; + int m_Cursor; + int m_MouseCapture; + int m_MouseColor; + int m_Space; + void __fastcall DrawCursor(void); + void __fastcall SetPBoxSize(void); + Graphics::TBitmap * __fastcall GetClipBitmap(void); + + TRect m_Src; + double m_sx, m_sy; + double m_sc; + int m_Stretch; + void __fastcall AdjustXY(int &X, int &Y); + void __fastcall SetCenter(void); + void __fastcall RotPic(double deg); + void __fastcall SaveSrc(void); + + double m_RotDeg; + int m_RotFlag; + int m_RotX1, m_RotY1, m_RotX2, m_RotY2; + +public: + virtual __fastcall TPicRectDlg(TComponent* AOwner); + __fastcall ~TPicRectDlg(); + + int __fastcall Execute(Graphics::TBitmap *pbmp); + int __fastcall Copy(Graphics::TBitmap *pbmp); + + Graphics::TBitmap *pBitmap; + +#define CM_EDITEXIT WM_USER+404 +protected: + void __fastcall OnEditExit(TMessage Message); + +BEGIN_MESSAGE_MAP + MESSAGE_HANDLER(CM_EDITEXIT, TMessage, OnEditExit) +END_MESSAGE_MAP(TForm) +}; +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +#endif diff --git a/PicRectDlg.cpp b/PicRectDlg.cpp new file mode 100644 index 0000000..4c16b05 --- /dev/null +++ b/PicRectDlg.cpp @@ -0,0 +1,33 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "PicRectDlg.h" +//--------------------------------------------------------------------- +#pragma resource "*.dfm" +TOKBottomDlg *OKBottomDlg; +//--------------------------------------------------------------------- +__fastcall TOKBottomDlg::TOKBottomDlg(TComponent* AOwner) + : TForm(AOwner) +{ +} +//--------------------------------------------------------------------- diff --git a/PicRectDlg.dfm b/PicRectDlg.dfm new file mode 100644 index 0000000..0f53298 Binary files /dev/null and b/PicRectDlg.dfm differ diff --git a/PicRectDlg.h b/PicRectDlg.h new file mode 100644 index 0000000..d7ed0ef --- /dev/null +++ b/PicRectDlg.h @@ -0,0 +1,48 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//---------------------------------------------------------------------------- +#ifndef OCBH +#define OCBH +//---------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//---------------------------------------------------------------------------- +class TOKBottomDlg : public TForm +{ +__published: + TButton *OKBtn; + TButton *CancelBtn; + TPanel *Panel; +private: +public: + virtual __fastcall TOKBottomDlg(TComponent* AOwner); +}; +//---------------------------------------------------------------------------- +extern PACKAGE TOKBottomDlg *OKBottomDlg; +//---------------------------------------------------------------------------- +#endif diff --git a/PicSel.cpp b/PicSel.cpp new file mode 100644 index 0000000..c3f4316 --- /dev/null +++ b/PicSel.cpp @@ -0,0 +1,821 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "Clipbrd.hpp" +#include "PicSel.h" +#include "Main.h" +#include "PicRect.h" +//--------------------------------------------------------------------- +#pragma resource "*.dfm" +//--------------------------------------------------------------------- +__fastcall TPicSelDlg::TPicSelDlg(TComponent* AOwner) + : TForm(AOwner) +{ + MultProc(); + m_DisEvent = 1; + m_hClipNext = NULL; + FormStyle = ((TForm *)AOwner)->FormStyle; + Font->Name = ((TForm *)AOwner)->Font->Name; + Font->Charset = ((TForm *)AOwner)->Font->Charset; + if( MsgEng ){ + CancelBtn->Caption = "Cancel"; + Caption = "Choose picture"; + RGType->Caption = "Source"; + RGType->Items->Strings[0] = "Refer to the History"; + RGType->Items->Strings[1] = "Loaded image"; + RGType->Items->Strings[2] = "Overlay"; + CBASize->Caption = "Auto stretch"; + RGShape->Caption = "Shape"; +#if 0 + RGShape->Items->Strings[0] = "Rectangle"; + RGShape->Items->Strings[1] = "Round Rect 1"; + RGShape->Items->Strings[2] = "Round Rect 2"; + RGShape->Items->Strings[3] = "Round Rect 3"; + RGShape->Items->Strings[4] = "Ellipse"; + RGShape->Items->Strings[5] = "Polygon"; +#endif + LineBtn->Caption = "Frame"; + L1->Caption = "Clipping"; + L2->Caption = "Guide"; + CBSmz->Caption = "Mouse Smoothing"; + CBR->Caption = "Update realtime"; + GBT->Caption = "Color smoothing"; + L3->Caption = "Threshold"; + CTBtn->Caption = "Do"; + CTRBtn->Caption = "Undo"; + ClipBtn->Caption = "Clipper"; + EditBtn->Caption = "Edit"; + } + LPCSTR *pTbl = MsgEng ? _ShapePIC[0] : _ShapePIC[1]; + while(*pTbl){ + RGShape->Items->Add(*pTbl++); + } + MultProc(); + GBC->Caption = L1->Caption; + SBRect->Glyph->Assign(Mmsstv->SBDBox->Glyph); + PCW->Color = clWhite; + PCB->Color = clBlack; + PCR->Color = clRed; + PCG->Color = TColor(0x00ff00); + pItem = NULL; + pBitmap = NULL; + pBitmapS = NULL; + m_ReqLineStyle = 0; + CBR->Checked = sys.m_PicSelRTM; + m_Count = 3; + m_Sync = 0; + CBT->Text = 8; + CTRBtn->Enabled = FALSE; + MultProc(); +} +//--------------------------------------------------------------------- +__fastcall TPicSelDlg::~TPicSelDlg() +{ + g_ExecPB.Cancel(); + MultProc(); + sys.m_PicSelRTM = CBR->Checked; + if( pBitmap != NULL ){ + delete pBitmap; + pBitmap = NULL; + } + if( pBitmapS != NULL ){ + delete pBitmapS; + pBitmapS = NULL; + } + MultProc(); +} +//--------------------------------------------------------------------- +void __fastcall TPicSelDlg::UpdateBtn(void) +{ + m_DisEvent++; + ClipBtn->Enabled = RGType->ItemIndex ? TRUE : FALSE; + EditBtn->Enabled = ClipBtn->Enabled; + if( RGType->ItemIndex == 2 ){ + GBC->Visible = FALSE; + GBT->Visible = TRUE; + RGShape->ItemIndex = 0; + RGShape->Enabled = FALSE; + LineBtn->Enabled = FALSE; + CBASize->Enabled = FALSE; + OKBtn->Enabled = TRUE; + m_DisEvent--; + return; + } + else { + GBT->Visible = FALSE; + GBC->Visible = TRUE; + RGShape->Enabled = TRUE; + LineBtn->Enabled = TRUE; + } + if( (RGShape->ItemIndex == 5) && (m_Polygon.Cnt < 3) ){ + OKBtn->Enabled = FALSE; + } + else { + OKBtn->Enabled = TRUE; + } + if( RGShape->ItemIndex == 5 ){ + if( m_Make ){ + PBox->Cursor = crCross; + } + else { + PBox->Cursor = crDefault; + } + CBASize->Enabled = FALSE; + GBC->Enabled = TRUE; + } + else { + CBASize->Enabled = RGType->ItemIndex ? FALSE : TRUE; + GBC->Enabled = FALSE; + } + SetGroupEnabled(GBC); + if( GBC->Enabled ) CBR->Enabled = !RGType->ItemIndex; + m_DisEvent--; +} +//--------------------------------------------------------------------- +int __fastcall TPicSelDlg::Execute(CDrawPic *pt) +{ + MultProc(); + pItem = pt; + RGType->ItemIndex = pt->m_Type; + RGShape->ItemIndex = pt->m_Shape; + CBASize->Checked = pt->m_Adjust; +// PasteBtn->Enabled = RGType->ItemIndex && Clipboard()->HasFormat(CF_BITMAP); +// PstRBtn->Enabled = PasteBtn->Enabled; + if( pItem->pBitmap != NULL ){ + pBitmap = new Graphics::TBitmap(); + AdjustBitmapFormat(pBitmap); + pBitmap->Assign(pItem->pBitmap); + MultProc(); + } + m_XW = pt->m_X2 - pt->m_X1 - 1; + m_YW = pt->m_Y2 - pt->m_Y1 - 1; + m_Polygon.Copy(&pt->m_Polygon); + m_Polygon.XW = PBox->Width; + m_Polygon.YW = PBox->Height; + switch(m_Polygon.Cnt){ + case 4: + SBRect->Down = TRUE; + break; + case 8: + SBRRect->Down = TRUE; + break; + case 64: + SBElip->Down = TRUE; + break; + default: + SBFree->Down = TRUE; + break; + } + L2->Color = sys.m_PicSelCurCol; + CBSmz->Checked = sys.m_PicSelSmooz; + m_TPX = pt->m_TransPoint & 0x0000ffff; + m_TPY = pt->m_TransPoint >> 16; + if( pt->m_TransPoint && (pt->pLoadBitmap != NULL) ){ + m_TPX = m_TPX * pBitmap->Width / pt->pLoadBitmap->Width; + m_TPY = m_TPY * pBitmap->Height / pt->pLoadBitmap->Height; + } + UpdateBtn(); + MultProc(); + m_DisEvent = 0; + m_hClipNext = ::SetClipboardViewer(Handle); + int r = ShowModal(); + ::ChangeClipboardChain(Handle, m_hClipNext); + if( r == IDOK ){ + MultProc(); + pt->m_Type = RGType->ItemIndex; + pt->m_Shape = (pt->m_Type == 2) ? 0 : RGShape->ItemIndex; + pt->m_Adjust = CBASize->Checked; + pt->m_TransPoint = m_TPX | (m_TPY << 16); + if( RGType->ItemIndex ){ + pBitmap->Transparent = FALSE; + pt->m_X2 = pt->m_X1 + m_XW + 1; + pt->m_Y2 = pt->m_Y1 + m_YW + 1; + pItem->pBitmap->Assign(pBitmap); + pItem->SetLoadBitmap(pBitmap); + } + pt->m_Polygon.Copy(&m_Polygon); + pt->m_DrawPolygon.Copy(&m_Polygon); + pt->m_DrawPolygon.XW = pt->pBitmap->Width; + pt->m_DrawPolygon.YW = pt->pBitmap->Height; + pt->m_DrawPolygon.Stretch(m_Polygon); + if( m_ReqLineStyle ) pt->m_LineStyle = TPenStyle(m_ReqLineStyle); + MultProc(); + return TRUE; + } + return FALSE; +} +//--------------------------------------------------------------------- +void __fastcall TPicSelDlg::PBoxPaint(TObject *Sender) +{ + TRect rc; + rc.Left = 0; + rc.Top = 0; + rc.Right = PBox->Width; + rc.Bottom = PBox->Height; + if( !RGType->ItemIndex && (RGShape->ItemIndex != 5) ){ + PBox->Canvas->Pen->Color = Panel->Color; + PBox->Canvas->Brush->Color = Panel->Color; + PBox->Canvas->FillRect(rc); + } + else { + if( !RGType->ItemIndex ){ + ::SetStretchBltMode(PBox->Canvas->Handle, HALFTONE); + Graphics::TBitmap *pBmp; + if( CBR->Checked && Mmsstv->pDem->m_Sync && (m_Sync != 2) ){ + pBmp = Mmsstv->pBitmapRX; + } + else { + pBmp = Mmsstv->pBitmapHist; + } + PBox->Canvas->StretchDraw(rc, (TGraphic*)(pBmp)); + } + else { + if( pBitmap == NULL ) return; + + if( RGType->ItemIndex == 2 ){ + if( sys.m_BitPixel == 16 ){ + Graphics::TBitmap *pbmp = DupeBitmap(pBitmap, -1); + delete pBitmap; + pBitmap = pbmp; + } + pBitmap->Transparent = TRUE; + pBitmap->TransparentMode = tmFixed; + pBitmap->TransparentColor = pBitmap->Canvas->Pixels[m_TPX][m_TPY]; + } + else { + pBitmap->Transparent = FALSE; + } + ::SetStretchBltMode(PBox->Canvas->Handle, HALFTONE); + PBox->Canvas->StretchDraw(rc, (TGraphic*)(pBitmap)); + pBitmap->Transparent = FALSE; + + if( RGType->ItemIndex == 2 ) DrawTransPoint(); + } + } + if( RGShape->ItemIndex == 5 ){ + if( !m_Make ) m_Polygon.Draw(PBox->Canvas, 1); + } +} +//--------------------------------------------------------------------------- +void __fastcall TPicSelDlg::RGTypeClick(TObject *Sender) +{ + LoadBtn->Enabled = RGType->ItemIndex ? TRUE : FALSE; + LdRBtn->Enabled = LoadBtn->Enabled; + PasteBtn->Enabled = RGType->ItemIndex && Clipboard()->HasFormat(CF_BITMAP); + PstRBtn->Enabled = PasteBtn->Enabled; + PBox->Invalidate(); + UpdateBtn(); +} +//--------------------------------------------------------------------------- +void __fastcall TPicSelDlg::AdjustSize(void) +{ + MultProc(); + int lx = Mmsstv->DrawMain.m_SX; + int ly = Mmsstv->DrawMain.m_SY; + m_XW = pBitmap->Width; + m_YW = pBitmap->Height; + if( (m_XW > lx) || (m_YW > ly) ){ + KeepAspect(lx, ly, m_XW, m_YW); + m_XW = lx; m_YW = ly; + MultProc(); + Graphics::TBitmap *pBmp = new Graphics::TBitmap(); + pBmp->PixelFormat = pBitmap->PixelFormat; + pBmp->Width = m_XW; + pBmp->Height = m_YW; + StretchCopy(pBmp, pBitmap, RGType->ItemIndex == 2 ? COLORONCOLOR : HALFTONE); + delete pBitmap; + pBitmap = pBmp; + } +} +//--------------------------------------------------------------------------- +void __fastcall TPicSelDlg::PasteBtnClick(TObject *Sender) +{ + if( pBitmap == NULL ) return; + + if( Mmsstv->PasteBitmap(pBitmap, 0) == TRUE ){ + PBox->Invalidate(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TPicSelDlg::PstRBtnClick(TObject *Sender) +{ + if( pBitmap == NULL ) return; + + if( Mmsstv->PasteBitmap(pBitmap, 1) == TRUE ){ + AdjustSize(); + PBox->Invalidate(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TPicSelDlg::LoadBtnClick(TObject *Sender) +{ + if( Mmsstv->LoadBitmapMenu(pBitmap, 0) == TRUE ){ + PBox->Invalidate(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TPicSelDlg::LdRBtnClick(TObject *Sender) +{ + if( Mmsstv->LoadBitmapMenu(pBitmap, 1) == TRUE ){ + AdjustSize(); + PBox->Invalidate(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TPicSelDlg::TimerTimer(TObject *Sender) +{ + MultProc(); + + if( !m_Count ){ + m_Count = 2000 / Timer->Interval; + if( CBR->Checked ){ + if( !RGType->ItemIndex && (RGShape->ItemIndex == 5) ){ + if( Mmsstv->pDem->m_Sync && (m_Sync != 2) ){ +_ld:; + PBoxPaint(NULL); + if( m_Make ){ + m_Polygon.Draw(PBox->Canvas, 0); + DrawCursor(); + m_Sync = 1; + } + } + else if( m_Sync == 1 ){ + m_Sync = 2; + goto _ld; + } + } + } + } + m_Count--; + if( m_Move && m_Make && CBSmz->Checked ){ + if( Timer->Interval != 50 ){ + m_Count = 2000 / 50; + Timer->Interval = 50; + } + int X = m_SmX.Avg(m_FX); + int Y = m_SmY.Avg(m_FY); + if( (m_AX != X) || (m_AY != Y) ){ + m_Polygon.AddPoint(X, Y); + m_Polygon.Draw(PBox->Canvas, 0); + m_AX = X; + m_AY = Y; + m_CX = m_AX; + m_CY = m_AY; + UpdateBtn(); + } + } + else if( m_Del ){ + if( Timer->Interval != 50 ){ + m_Count = 2000 / 50; + Timer->Interval = 50; + } + TShiftState Shift; + PBoxMouseDown(this, TMouseButton(mbRight), Shift, m_CX, m_CY); + } + else { + if( Timer->Interval != 1000 ){ + m_Count = 2; + Timer->Interval = 1000; + } +// PasteBtn->Enabled = RGType->ItemIndex && Clipboard()->HasFormat(CF_BITMAP); +// PstRBtn->Enabled = PasteBtn->Enabled; + } +} +//--------------------------------------------------------------------------- +void __fastcall TPicSelDlg::PBoxMouseDown(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + m_Move = 0; + m_MoveCnt = ::GetTickCount(); + if( RGType->ItemIndex == 2 ){ + X = X * pBitmap->Width / PBox->Width; + Y = Y * pBitmap->Height / PBox->Height; + if( Button == mbRight ){ + MakeBackup(); + CopyColor(X, Y); + } + else { + m_TPX = X; + m_TPY = Y; + } + PBox->Invalidate(); + } + else if( RGShape->ItemIndex == 5 ){ // 多角形作成モード + if( !SBFree->Down ){ + if( Button == mbRight ) return; + if( !m_Make ){ + m_Polygon.Clear(); + m_Make++; + PBox->Invalidate(); + } + m_AX = m_CX = X; + m_AY = m_CY = Y; + } + else { + if( m_Make ) DrawCursor(); + m_ReqLineStyle = -1; +// m_Polygon.Draw(PBox->Canvas, 0); + if( Button == mbRight ){ + if( m_Polygon.Cnt ){ + m_Polygon.Cnt--; + if( m_Polygon.Cnt ){ + int n = m_Polygon.Cnt - 1; + m_AX = m_Polygon.pBase[n].x; + m_AY = m_Polygon.pBase[n].y; + m_CX = X; + m_CY = Y; + m_Make = 1; + PBoxPaint(NULL); + m_Polygon.Draw(PBox->Canvas, 0); + DrawCursor(); + m_Del = 1; + return; + } + else { + m_Make = 0; + PBox->Invalidate(); + } + } + } + else { + if( !m_Make ){ + m_Polygon.Clear(); + m_Make++; + PBox->Invalidate(); + } + if( (ABS(m_AX-X)<2) && (ABS(m_AY-Y)<2) ){ + m_Make = 0; + if( CBSmz->Checked ) Smooz(); + PBox->Invalidate(); + } + else { + m_Polygon.AddPoint(X, Y); + m_Polygon.Draw(PBox->Canvas, 0); + } + m_FX = m_AX = X; + m_FY = m_AY = Y; + m_SmX.SetCount(6); + m_SmY.SetCount(6); + } + m_CX = m_AX; + m_CY = m_AY; + } + UpdateBtn(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TPicSelDlg::DrawCursor(void) +{ + if( (m_AX == m_CX) && (m_AY == m_CY) ) return; + + PBox->Canvas->MoveTo(m_AX, m_AY); + int rop = ::SetROP2(PBox->Canvas->Handle, R2_NOT); + if( !SBFree->Down ){ + PBox->Canvas->LineTo(m_CX, m_AY); + PBox->Canvas->LineTo(m_CX, m_CY); + PBox->Canvas->LineTo(m_AX, m_CY); + PBox->Canvas->LineTo(m_AX, m_AY); + } + else { + PBox->Canvas->LineTo(m_CX, m_CY); + } + ::SetROP2(PBox->Canvas->Handle, rop); +} +//--------------------------------------------------------------------------- +void __fastcall TPicSelDlg::DrawTransPoint(void) +{ + int x = m_TPX * PBox->Width / pBitmap->Width; + int y = m_TPY * PBox->Height / pBitmap->Height; + + DrawTrans(PBox->Canvas, x, y); +} +//--------------------------------------------------------------------------- +void __fastcall TPicSelDlg::PBoxMouseMove(TObject *Sender, + TShiftState Shift, int X, int Y) +{ + if( !m_Make ) return; + + if( RGShape->ItemIndex == 5 ){ // 多角形作成モード + TShiftState sc1, sc2; + sc1 << ssLeft; + sc2 << ssLeft; + sc1 *= Shift; + if( SBFree->Down && (sc1 == sc2) ){ // Left button + if( CBSmz->Checked ){ + m_FX = X; + m_FY = Y; + m_Move = 1; + if( Timer->Interval != 50 ){ + m_Count = 2000 / 50; + Timer->Interval = 50; + } + } + else if( ((m_AX != X) || (m_AY != Y)) && (DWORD(m_MoveCnt + 200) < ::GetTickCount()) ){ + m_Polygon.AddPoint(X, Y); + m_Polygon.Draw(PBox->Canvas, 0); + m_AX = X; + m_AY = Y; + m_CX = m_AX; + m_CY = m_AY; + UpdateBtn(); + m_Move = 1; + } + } + else { + DrawCursor(); + m_CX = X; + m_CY = Y; + DrawCursor(); + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TPicSelDlg::PBoxMouseUp(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + m_Del = 0; + if( RGShape->ItemIndex == 5 ){ // 多角形作成モード + if( !m_Make ) return; + if( Button == mbRight ) return; + if( !SBFree->Down ){ + m_Polygon.Clear(); + if( (m_AX != m_CX) || (m_AY != m_CY) ){ + if( SBRect->Down ){ + m_Polygon.AddPoint(m_AX, m_AY); + m_Polygon.AddPoint(m_CX, m_AY); + m_Polygon.AddPoint(m_CX, m_CY); + m_Polygon.AddPoint(m_AX, m_CY); + } + else if( SBRRect->Down ){ + int w = (m_CX - m_AX + 1)/8; + int h = (m_CY - m_AY + 1)/8; + m_Polygon.AddPoint(m_AX+w, m_AY); + m_Polygon.AddPoint(m_CX-w, m_AY); + m_Polygon.AddPoint(m_CX, m_AY+h); + m_Polygon.AddPoint(m_CX, m_CY-h); + m_Polygon.AddPoint(m_CX-w, m_CY); + m_Polygon.AddPoint(m_AX+w, m_CY); + m_Polygon.AddPoint(m_AX, m_CY-h); + m_Polygon.AddPoint(m_AX, m_AY+h); + } + else { // 楕円 + double A = (ABS(m_CX - m_AX) + 1) * 0.5; + double B = (ABS(m_CY - m_AY) + 1) * 0.5; + double XC = (m_CX + m_AX) * 0.5; + double YC = (m_CY + m_AY) * 0.5; + double deg, x, y; + int i; + for( i = 0, deg = 0; i < 64; i++, deg += PI/32){ + x = A * cos(deg); + y = B * sin(deg); + m_Polygon.AddPoint(XC + x, YC + y); + } + } + } + m_Make = 0; + PBox->Invalidate(); + UpdateBtn(); + } + else if( m_Move && (m_Polygon.Cnt >= 3) && (DWORD(m_MoveCnt + 1000) < ::GetTickCount()) ){ + m_Make = 0; + PBox->Invalidate(); + UpdateBtn(); + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TPicSelDlg::RGShapeClick(TObject *Sender) +{ + m_Make = 0; + PBox->Invalidate(); + UpdateBtn(); +} +//--------------------------------------------------------------------------- +void __fastcall TPicSelDlg::LineBtnClick(TObject *Sender) +{ + int shape = pItem->m_Shape; + pItem->m_Shape = RGShape->ItemIndex; + if( pItem->CDraw::Edit() == TRUE ){ + m_ReqLineStyle = 0; + if( RGShape->ItemIndex != pItem->m_Shape ){ + RGShape->ItemIndex = pItem->m_Shape; + RGShapeClick(NULL); + } + } + pItem->m_Shape = shape; +} +//--------------------------------------------------------------------------- +void __fastcall TPicSelDlg::SBRectClick(TObject *Sender) +{ + if( m_Make ){ + m_Make = 0; + PBox->Invalidate(); + UpdateBtn(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TPicSelDlg::CBSmzClick(TObject *Sender) +{ + sys.m_PicSelSmooz = CBSmz->Checked; +} +//--------------------------------------------------------------------------- +void __fastcall TPicSelDlg::L2Click(TObject *Sender) +{ + TColorDialog *pDialog = Mmsstv->ColorDialog; + InitCustomColor(pDialog); + AddCustomColor(pDialog, sys.m_PicSelCurCol); + pDialog->Color = sys.m_PicSelCurCol; + SetDisPaint(); + if( pDialog->Execute() == TRUE ){ + sys.m_PicSelCurCol = pDialog->Color; + L2->Color = sys.m_PicSelCurCol; + m_Polygon.Draw(PBox->Canvas, 0); + } + ResDisPaint(); +} +//--------------------------------------------------------------------------- +void __fastcall TPicSelDlg::PCWClick(TObject *Sender) +{ + sys.m_PicSelCurCol = ((TPanel *)Sender)->Color; + L2->Color = sys.m_PicSelCurCol; + m_Polygon.Draw(PBox->Canvas, 1); +} +//--------------------------------------------------------------------------- +void __fastcall TPicSelDlg::Smooz(void) +{ + if( m_Polygon.Cnt < 3 ) return; + + CPolygon Pol; + int i, j, N; + int AX = 0; + int AY = 0; + double xx, yy, d; + POINT *pt = m_Polygon.pBase; + for( i = 0; i <= m_Polygon.Cnt; i++, pt++ ){ + if( i == m_Polygon.Cnt ) pt = m_Polygon.pBase; + if( i ){ + xx = pt->x - AX; + yy = pt->y - AY; + d = (xx*xx) + (yy*yy); + if( d > 0.0) d = sqrt(d); + if( d > 8.0 ){ + N = d / 8; + for( j = 1; j < N; j++ ){ + Pol.AddPoint(AX + (xx*j/N), AY + (yy*j/N)); + } + } + } + if( i == m_Polygon.Cnt ) break; + Pol.AddPoint(pt->x, pt->y); + AX = pt->x; AY = pt->y; + } + int XC, YC; + m_Polygon.GetCenter(XC, YC); + + double x, y, ax, ay; + ax = ay = 0; + pt = Pol.pBase; + for( i = 0; i <= Pol.Cnt; i++, pt++ ){ + if( i == Pol.Cnt ) pt = Pol.pBase; + x = pt->x - XC; + y = pt->y - YC; + if( i ){ + x = (x + ax)/2.0; + y = (y + ay)/2.0; + pt->x = XC + x + 0.5; + pt->y = YC + y + 0.5; + } + ax = x; ay = y; + } + m_Polygon.Copy(&Pol); +} +//--------------------------------------------------------------------------- +void __fastcall TPicSelDlg::CBRClick(TObject *Sender) +{ + if( m_DisEvent ) return; + PBox->Invalidate(); + m_Sync = 0; +} +//--------------------------------------------------------------------------- +void __fastcall TPicSelDlg::CopyColor(int x, int y) +{ + CWaitCursor w; + + TColor bcol = pBitmap->Canvas->Pixels[x][y]; + TColor ccol = pBitmap->Canvas->Pixels[m_TPX][m_TPY]; + for( y = 0; y < pBitmap->Height; y++ ){ + MultProc(); + for( x = 0; x < pBitmap->Width; x++ ){ + if( pBitmap->Canvas->Pixels[x][y] == bcol ){ + pBitmap->Canvas->Pixels[x][y] = ccol; + } + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TPicSelDlg::MakeBackup(void) +{ + if( pBitmapS == NULL ){ + MultProc(); + pBitmapS = DupeBitmap(pBitmap, pBitmap->PixelFormat); + CTRBtn->Enabled = TRUE; + } +} +//--------------------------------------------------------------------------- +void __fastcall TPicSelDlg::CTBtnClick(TObject *Sender) +{ + if( RGType->ItemIndex == 2 ){ + int lm; + sscanf(AnsiString(CBT->Text).c_str(), "%u", &lm); //ja7ude 0521 + lm = Limit256(lm); + if( lm ){ + MakeBackup(); + DownColor(pBitmap, pBitmap->Canvas->Pixels[m_TPX][m_TPY], lm); + PBox->Invalidate(); + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TPicSelDlg::CTRBtnClick(TObject *Sender) +{ + if( RGType->ItemIndex == 2 ){ + pBitmap->Assign(pBitmapS); + MultProc(); + delete pBitmapS; + pBitmapS = NULL; + CTRBtn->Enabled = FALSE; + PBox->Invalidate(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TPicSelDlg::ClipBtnClick(TObject *Sender) +{ + if( pBitmap == NULL ) return; + if( !RGType->ItemIndex ) return; + + TPicRectDlg *pBox = new TPicRectDlg(this); + AdjustBitmapFormat(pBox->pBitmap); + pBox->pBitmap->Width = pBitmap->Width; + pBox->pBitmap->Height = pBitmap->Height; + pBox->pBitmap->Canvas->Draw(0, 0, pBitmap); + if( pBox->Execute(pBitmap) == TRUE ){ + PBox->Invalidate(); + } + delete pBox; +} +//--------------------------------------------------------------------------- +void __fastcall TPicSelDlg::EditBtnClick(TObject *Sender) +{ + if( pBitmap == NULL ) return; + if( !RGType->ItemIndex ) return; + + g_ExecPB.Exec(pBitmap, (HWND)Handle, CM_EDITEXIT, 0); +} +//--------------------------------------------------------------------------- +void __fastcall TPicSelDlg::OnEditExit(TMessage Message) +{ + if( Message.LParam ) return; + + if( g_ExecPB.LoadBitmap(pBitmap, TRUE) ){ + AdjustSize(); + PBox->Invalidate(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TPicSelDlg::OnDrawClipboard(TMessage Message) +{ + PasteBtn->Enabled = RGType->ItemIndex && ::IsClipboardFormatAvailable(CF_BITMAP); + PstRBtn->Enabled = PasteBtn->Enabled; + if( m_hClipNext ) ::SendMessage(m_hClipNext, WM_DRAWCLIPBOARD, Message.WParam, Message.LParam); +} +//--------------------------------------------------------------------------- +void __fastcall TPicSelDlg::OnChangeCbChain(TMessage Message) +{ + if( (HWND)Message.WParam == m_hClipNext ){ + m_hClipNext = (HWND)Message.LParam; + } + if( m_hClipNext ) ::SendMessage(m_hClipNext, WM_CHANGECBCHAIN, Message.WParam, Message.LParam); + Message.Result = 0; +} +//--------------------------------------------------------------------------- + diff --git a/PicSel.dfm b/PicSel.dfm new file mode 100644 index 0000000..079b9f8 Binary files /dev/null and b/PicSel.dfm differ diff --git a/PicSel.h b/PicSel.h new file mode 100644 index 0000000..839e77f --- /dev/null +++ b/PicSel.h @@ -0,0 +1,157 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//---------------------------------------------------------------------------- +#ifndef PicSelH +#define PicSelH +//---------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//---------------------------------------------------------------------------- +#include "Draw.h" +#include "sstv.h" +//---------------------------------------------------------------------------- +class TPicSelDlg : public TForm +{ +__published: + TButton *OKBtn; + TButton *CancelBtn; + TRadioGroup *RGType; + TPanel *Panel; + TPaintBox *PBox; + TButton *PasteBtn; + TButton *LoadBtn; + TTimer *Timer; + TRadioGroup *RGShape; + TButton *LineBtn; + TCheckBox *CBASize; + TGroupBox *GBC; + TLabel *L1; + TSpeedButton *SBFree; + TSpeedButton *SBRect; + TSpeedButton *SBRRect; + TSpeedButton *SBElip; + TLabel *L2; + TCheckBox *CBSmz; + TPanel *PCW; + TPanel *PCB; + TPanel *PCR; + TPanel *PCG; + TCheckBox *CBR; + TGroupBox *GBT; + TComboBox *CBT; + TLabel *L3; + TButton *CTBtn; + TButton *CTRBtn; + TButton *LdRBtn; + TButton *PstRBtn; + TButton *ClipBtn; + TButton *EditBtn; + void __fastcall PBoxPaint(TObject *Sender); + void __fastcall RGTypeClick(TObject *Sender); + void __fastcall PasteBtnClick(TObject *Sender); + void __fastcall LoadBtnClick(TObject *Sender); + void __fastcall TimerTimer(TObject *Sender); + void __fastcall PBoxMouseDown(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + void __fastcall RGShapeClick(TObject *Sender); + void __fastcall PBoxMouseMove(TObject *Sender, TShiftState Shift, + int X, int Y); + void __fastcall LineBtnClick(TObject *Sender); + void __fastcall PBoxMouseUp(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + + void __fastcall SBRectClick(TObject *Sender); + + + void __fastcall CBSmzClick(TObject *Sender); + void __fastcall L2Click(TObject *Sender); + void __fastcall PCWClick(TObject *Sender); + void __fastcall CBRClick(TObject *Sender); + void __fastcall CTBtnClick(TObject *Sender); + void __fastcall CTRBtnClick(TObject *Sender); + + void __fastcall LdRBtnClick(TObject *Sender); + void __fastcall PstRBtnClick(TObject *Sender); + void __fastcall ClipBtnClick(TObject *Sender); + void __fastcall EditBtnClick(TObject *Sender); +private: + CDrawPic *pItem; + Graphics::TBitmap *pBitmap; + Graphics::TBitmap *pBitmapS; + CPolygon m_Polygon; + int m_Make; + int m_Move; + int m_Del; + DWORD m_MoveCnt; + int m_AX; + int m_AY; + int m_CX; + int m_CY; + int m_FX; + int m_FY; + int m_ReqLineStyle; + int m_Count; + int m_DisEvent; + void __fastcall DrawCursor(void); + CSmooz m_SmX; + CSmooz m_SmY; + void __fastcall UpdateBtn(void); + void __fastcall Smooz(void); +// void __fastcall DownColor(Graphics::TBitmap *pbmp, int lm); + void __fastcall CopyColor(int x, int y); + void __fastcall DrawTransPoint(void); + int m_TPX; + int m_TPY; + int m_Sync; + DYNAMIC void __fastcall AdjustSize(void); + int m_XW; + int m_YW; + void __fastcall MakeBackup(void); +public: + virtual __fastcall TPicSelDlg(TComponent* AOwner); + __fastcall ~TPicSelDlg(); + + int __fastcall TPicSelDlg::Execute(CDrawPic *pt); + + HWND m_hClipNext; +#define CM_EDITEXIT WM_USER+404 +protected: + void __fastcall OnDrawClipboard(TMessage Message); + void __fastcall OnChangeCbChain(TMessage Message); + void __fastcall OnEditExit(TMessage Message); + +BEGIN_MESSAGE_MAP + MESSAGE_HANDLER(WM_DRAWCLIPBOARD, TMessage, OnDrawClipboard) + MESSAGE_HANDLER(WM_CHANGECBCHAIN, TMessage, OnChangeCbChain) + MESSAGE_HANDLER(CM_EDITEXIT, TMessage, OnEditExit) +END_MESSAGE_MAP(TForm) +}; +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +#endif + diff --git a/PlayDlg.cpp b/PlayDlg.cpp new file mode 100644 index 0000000..1d3bb8d --- /dev/null +++ b/PlayDlg.cpp @@ -0,0 +1,102 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "PlayDlg.h" +//--------------------------------------------------------------------- +#pragma resource "*.dfm" +//TPlayDlgBox *PlayDlgBox; +//--------------------------------------------------------------------- +__fastcall TPlayDlgBox::TPlayDlgBox(TComponent* AOwner) + : TForm(AOwner) +{ + FormStyle = ((TForm *)AOwner)->FormStyle; + Font->Name = ((TForm *)AOwner)->Font->Name; + Font->Charset = ((TForm *)AOwner)->Font->Charset; + + pWave = NULL; + m_DisEvent = 0; + + if( MsgEng ){ + Caption = "Adjust Play position"; + OKBtn->Caption = "Hide"; + StopBtn->Caption = "Stop"; + LRec->Caption = "RecTime"; + LNow->Caption = "NowTime"; + } +} +//--------------------------------------------------------------------- +void __fastcall TPlayDlgBox::UpdateItem(void) +{ + char bf[32]; + + sprintf(bf, "%u[s]", int(pWave->m_length * 0.5 / SampFreq)); + LTime->Caption = bf; + sprintf(bf, "%u[s]", int(pWave->GetPos() * 0.5 / SampFreq)); + LPos->Caption = bf; + m_DisEvent++; + ScrollBar->Max = int(pWave->m_length * 0.5 / SampFreq); + ScrollBar->Position = int(pWave->GetPos() * 0.5 / SampFreq); + CheckPause->Checked = pWave->m_pause; + m_DisEvent--; +} +//--------------------------------------------------------------------- +void __fastcall TPlayDlgBox::Execute(CWaveFile *wp) +{ + pWave = wp; + pWave->m_autopause = 1; + LName->Caption = pWave->m_FileName; + UpdateItem(); + ShowModal(); + pWave->m_autopause = 0; +} +//--------------------------------------------------------------------- +void __fastcall TPlayDlgBox::TimerTimer(TObject *Sender) +{ + UpdateItem(); +} +//--------------------------------------------------------------------------- +void __fastcall TPlayDlgBox::ScrollBarChange(TObject *Sender) +{ + if( m_DisEvent ) return; + + int pos = ScrollBar->Position; + pWave->Seek(pos * SampFreq*2); + if( !CheckPause->Checked ) pWave->m_pause = 0; + char bf[32]; + sprintf(bf, "%u[s]", pos); + LPos->Caption = bf; +} +//--------------------------------------------------------------------------- +void __fastcall TPlayDlgBox::CheckPauseClick(TObject *Sender) +{ + if( m_DisEvent ) return; + + pWave->m_pause = CheckPause->Checked; +} +//--------------------------------------------------------------------------- +void __fastcall TPlayDlgBox::StopBtnClick(TObject *Sender) +{ + pWave->FileClose(); + ModalResult = mrOk; +} +//--------------------------------------------------------------------------- diff --git a/PlayDlg.dfm b/PlayDlg.dfm new file mode 100644 index 0000000..b2ca5a2 Binary files /dev/null and b/PlayDlg.dfm differ diff --git a/PlayDlg.h b/PlayDlg.h new file mode 100644 index 0000000..2489c4d --- /dev/null +++ b/PlayDlg.h @@ -0,0 +1,69 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//---------------------------------------------------------------------------- +#ifndef PlayDlgH +#define PlayDlgH +//---------------------------------------------------------------------------- +//ja7ude 0428 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Sound.h" +//---------------------------------------------------------------------------- +class TPlayDlgBox : public TForm +{ +__published: + TButton *OKBtn; + TScrollBar *ScrollBar; + TLabel *LRec; + TLabel *LNow; + TLabel *LTime; + TLabel *LPos; + TTimer *Timer; + TLabel *LName; + TCheckBox *CheckPause; + TButton *StopBtn; + void __fastcall TimerTimer(TObject *Sender); + void __fastcall ScrollBarChange(TObject *Sender); + void __fastcall CheckPauseClick(TObject *Sender); + void __fastcall StopBtnClick(TObject *Sender); +private: + CWaveFile *pWave; + + int m_DisEvent; +public: + virtual __fastcall TPlayDlgBox(TComponent* AOwner); + + void __fastcall Execute(CWaveFile *wp); + void __fastcall UpdateItem(void); + +}; +//---------------------------------------------------------------------------- +//extern TPlayDlgBox *PlayDlgBox; +//---------------------------------------------------------------------------- +#endif diff --git a/PrevView.cpp b/PrevView.cpp new file mode 100644 index 0000000..c1751d8 --- /dev/null +++ b/PrevView.cpp @@ -0,0 +1,96 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "ComLib.h" +#include "PrevView.h" +//--------------------------------------------------------------------------- +#pragma package(smart_init) +#pragma resource "*.dfm" +//TPrevViewBox *PrevViewBox; +//--------------------------------------------------------------------------- +__fastcall TPrevViewBox::TPrevViewBox(TComponent* Owner) + : TForm(Owner) +{ +// if( sys.m_WinFontCharset != SHIFTJIS_CHARSET ){ +// Caption = "Preview"; +// } +// Font->Name = sys.m_WinFontName; +// Font->Charset = sys.m_WinFontCharset; + pBitmap = new Graphics::TBitmap; +} +//--------------------------------------------------------------------------- +__fastcall TPrevViewBox::~TPrevViewBox() +{ + if( pBitmap != NULL ){ + delete pBitmap; + } +} +//--------------------------------------------------------------------------- +void __fastcall TPrevViewBox::UpdateTitle(LPCSTR pName) +{ + if( pBitmap == NULL ) return; + + char bf[512]; + + sprintf(bf, "%ux%u %s", pBitmap->Width, pBitmap->Height, pName); + Caption = bf; +} +//--------------------------------------------------------------------------- +void __fastcall TPrevViewBox::FormPaint(TObject *Sender) +{ + if( pBitmap == NULL ) return; + + if( ((pBitmap->Width <= ClientWidth) && (pBitmap->Height <= ClientHeight)) ){ + Canvas->Draw(0, 0, pBitmap); + } + else { +#if 0 + TRect tc; + tc.Left = tc.Top = 0; + double sx = double(pBitmap->Width) / ClientWidth; + double sy = double(pBitmap->Height) / ClientHeight; + if( sx > sy ){ + tc.Right = ClientWidth; + tc.Bottom = pBitmap->Height / sx; + } + else { + tc.Bottom = ClientHeight; + tc.Right = pBitmap->Width / sy; + } + ::SetStretchBltMode(Canvas->Handle, HALFTONE); + Canvas->StretchDraw(tc, pBitmap); +#else + KeepAspectDraw(Canvas, ClientWidth, ClientHeight, pBitmap); +#endif + } +} +//--------------------------------------------------------------------------- +void __fastcall TPrevViewBox::FormResize(TObject *Sender) +{ + if( ClientWidth < 24 ) ClientWidth = 24; + if( ClientHeight < 24 ) ClientHeight = 24; + Invalidate(); +} +//--------------------------------------------------------------------------- + + diff --git a/PrevView.dfm b/PrevView.dfm new file mode 100644 index 0000000..1132cfe Binary files /dev/null and b/PrevView.dfm differ diff --git a/PrevView.h b/PrevView.h new file mode 100644 index 0000000..dc52231 --- /dev/null +++ b/PrevView.h @@ -0,0 +1,58 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------------- +#ifndef PrevViewH +#define PrevViewH +//--------------------------------------------------------------------------- +#include +#include +#include +#include +//--------------------------------------------------------------------------- +class TPrevViewBox : public TForm +{ +__published: // IDE 管理のコンポーネント + void __fastcall FormPaint(TObject *Sender); + void __fastcall FormResize(TObject *Sender); +private: // ユーザー宣言 +public: // ユーザー宣言 + __fastcall TPrevViewBox(TComponent* Owner); + __fastcall ~TPrevViewBox(); + void __fastcall GetViewPos(int &x, int &y, int &w, int &h){ + x = Left; + y = Top; + w = ClientWidth; + h = ClientHeight; + }; + void __fastcall SetViewPos(int x, int y, int w, int h){ + Left = x; + Top = y; + ClientWidth = w; + ClientHeight = h; + }; + void __fastcall UpdateTitle(LPCSTR pName); + + Graphics::TBitmap *pBitmap; +}; +//--------------------------------------------------------------------------- +//extern PACKAGE TPrevViewBox *PrevViewBox; +//--------------------------------------------------------------------------- +#endif + diff --git a/Qsodlg.cpp b/Qsodlg.cpp new file mode 100644 index 0000000..d4ae4da --- /dev/null +++ b/Qsodlg.cpp @@ -0,0 +1,548 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "QsoDlg.h" +#include "Country.h" +#include "MmcgDlg.h" +#include "Main.h" +#include "TextEdit.h" +#include "LogPic.h" +//--------------------------------------------------------------------- +#pragma resource "*.dfm" +//TQSODlgBox *QSODlgBox; +//--------------------------------------------------------------------- +__fastcall TQSODlgBox::TQSODlgBox(TComponent* AOwner) + : TForm(AOwner) +{ + FormStyle = ((TForm *)AOwner)->FormStyle; + Font->Name = ((TForm *)AOwner)->Font->Name; + Font->Charset = ((TForm *)AOwner)->Font->Charset; + LStat->Font->Name = ((TForm *)AOwner)->Font->Name; + LStat->Font->Charset = ((TForm *)AOwner)->Font->Charset; + m_fp = NULL; + + EditHis->Items->Assign(Mmsstv->HisRST->Items); + EditMy->Items->Assign(Mmsstv->MyRST->Items); + if( MsgEng ){ + Grid->Font->Name = ((TForm *)AOwner)->Font->Name; + Grid->Font->Charset = ((TForm *)AOwner)->Font->Charset; + Caption = "QSO Data"; + LogPicBtn->Caption = "Pic."; + CancelBtn->Caption = "Close"; + OKBtn->Caption = "Write"; + } + switch(Log.m_LogSet.m_TimeZone){ + case 'I': + if( lcid == LANG_KOREAN ){ + LTimeZone->Caption = "KST"; + } + else { + LTimeZone->Caption = "JST"; + } + break; + default: + LTimeZone->Caption = "UTC"; + break; + } + if( Log.m_LogSet.m_DateType & 1 ){ + Grid->ColWidths[0] = (Grid->ColWidths[0] * 10) / 8; + } + m_EditFlag = 0; +} + +void __fastcall TQSODlgBox::UpdateBtn(void) +{ + OKBtn->Enabled = m_EditFlag; + LogPicBtn->Enabled = !EditQSL->Text.IsEmpty() && !sys.m_AutoSaveDir.IsEmpty() && IsLogPic(AnsiString(EditQSL->Text).c_str()); //ja7ude 0428 +} + +void __fastcall TQSODlgBox::SetCountry(void) +{ + m_Country = ""; + + if( !Cty.IsData() ) return; + LPCSTR p = ClipCC(m_fp->GetText()); + if( !(*p) ) return; + + SYSTEMTIME now; + GetUTC(&now); + + WORD tim = WORD((now.wHour * 60 + now.wMinute) * 30 + now.wSecond/2); + + int n; + if( (n = Cty.GetNoP(p))!=0 ){ + CTL *cp = Cty.GetCTL(n-1); + char bf[256]; + char tbf[5]; + tbf[0] = 0; + if( cp->TD != NULL ){ + tim = AdjustRolTimeUTC(tim, *cp->TD); + if( tim ){ + tim /= WORD(30); + sprintf(tbf, "%02u%02u%c", tim / 60, tim % 60, *cp->TD); + } + } + sprintf(bf, " %s/%s %s %s", + (cp->Name!=NULL) ? cp->Name : "", + (cp->Cont!=NULL) ? cp->Cont : "", + tbf, + (cp->QTH!=NULL) ? cp->QTH : "" + ); + m_Country = bf; + } +} + +int __fastcall TQSODlgBox::Execute(CLogFind *fp, SDMMLOG *sp, int n) +{ + m_fp = fp; + UpdateTextData(sp, n); + Grid->RowCount = fp->GetCount() ? fp->GetCount() + 1 : 2; +// Grid->TopRow = 1; + Grid->Row = 1; + Grid->Enabled = FALSE; + for( int i = 0; i < fp->GetCount(); i++ ){ + if( n == fp->pFindTbl[i] ){ + Grid->Enabled = TRUE; + Grid->Row = i + 1; + Grid->TopRow = (i > 4) ? Grid->Row - 4 : 1; + break; + } + } + SetCountry(); + char bf[512]; + strcpy(bf, MsgEng ? "Initial Data":"QSOデータ初期値"); + if( Grid->Enabled == TRUE ){ + if( sp->btime ){ + sprintf(bf, "[%s]", fp->GetText()); + strcat(bf, m_Country.c_str()); + } + else if( *fp->GetText() ){ + sprintf(bf, "[%s]", fp->GetText()); + strcat(bf, m_Country.c_str()); + } + } + Caption = bf; + UpdateStat(); + m_EditFlag = 0; + UpdateBtn(); + m_CurNo = n; + if( ShowModal() == IDOK ){ + if( m_EditFlag ){ + UpdateCurData(&m_sd); + Log.PutData(&m_sd, m_CurNo); + } + } + if( m_CurNo == n ){ + memcpy(sp, &m_sd, sizeof(SDMMLOG)); + } + else { + Log.GetData(sp, n); + } + return TRUE; +} + +int __fastcall TQSODlgBox::ShowFind(CLogFind *fp) +{ + m_fp = fp; + if( fp->GetCount() ){ + Log.GetData(&m_sd, fp->pFindTbl[0]); + m_CurNo = fp->pFindTbl[0]; + } + else { + memset(&m_sd, 0, sizeof(SDMMLOG)); + OKBtn->Enabled = FALSE; + } + SetCountry(); + char bf[512]; + UpdateTextData(&m_sd, fp->pFindTbl[0]); + Grid->RowCount = fp->GetCount() ? fp->GetCount() + 1 : 2; + Grid->TopRow = 1; + Grid->Row = 1; + sprintf(bf, "[%s]", fp->GetText()); + strcat(bf, m_Country.c_str()); + Caption = bf; + UpdateStat(); + m_EditFlag = 0; + UpdateBtn(); + if( ShowModal() == IDOK ){ + if( m_EditFlag ){ + UpdateCurData(&m_sd); + Log.PutData(&m_sd, m_CurNo); + } + return TRUE; + } + else { + return FALSE; + } +} + +void __fastcall TQSODlgBox::UpdateTextData(SDMMLOG *sp, int n) +{ + m_CurNo = n; + memcpy(&m_sd, sp, sizeof(SDMMLOG)); + UpdateTextData(&m_sd); +} + +void __fastcall TQSODlgBox::UpdateTextData(SDMMLOG *sp) +{ + SDMMLOG sd; + memcpy(&sd, sp, sizeof(SDMMLOG)); + if( Log.m_LogSet.m_TimeZone != 'I' ){ + JSTtoUTC(&sd); + } + EditDate->Text = Log.GetDateString(&sd); + EditBgn->Text = Log.GetTimeString(sd.btime); + EditEnd->Text = Log.GetTimeString(sd.etime); + EditCall->Text = sp->call; + EditName->Text = sp->name; + EditQTH->Text = sp->qth; + EditHis->Text = sp->ur; + EditMy->Text = sp->my; + EditBand->Text = Log.GetFreqString(sp->band, sp->fq); + EditMode->Text = Log.GetModeString(sp->mode); + EditRem->Text = sp->rem; + EditQSL->Text = sp->qsl; + if( sp->env ){ + EditEnv->Text = sp->env; + } + else { + EditEnv->Text = ""; + } + EditOpt1->Text = Log.GetOptStr(0, sp); + EditOpt2->Text = Log.GetOptStr(1, sp); + EditUsr1->Text = Log.GetOptStr(2, sp); + EditUsr2->Text = Log.GetOptStr(3, sp); + EditS->Text = sp->send; + EditR->Text = sp->recv; + EditM->Text = sp->cq; + EditPow->Text = sp->pow; + m_EditFlag = 0; + UpdateBtn(); +} + +void __fastcall TQSODlgBox::UpdateCurData(SDMMLOG *sp) +{ + int y, m, d, h; + + switch(Log.m_LogSet.m_DateType){ + case 2: // dd-mm-yy + case 3: // dd-mm-yyyy + if( sscanf(AnsiString(EditDate->Text).c_str(), "%u.%u.%u", &d, &m, &y) == 3 ){ //ja7ude 0428 + sp->year = BYTE(y % 100); + sp->date = WORD(m * 100 + d); + } + break; + case 4: // mm-dd-yy + case 5: // mm-dd-yyyy + if( sscanf(AnsiString(EditDate->Text).c_str(), "%u.%u.%u", &m, &d, &y) == 3 ){ //ja7ude 0428 + sp->year = BYTE(y % 100); + sp->date = WORD(m * 100 + d); + } + break; + default: // yy-mm-dd, yyyy-mm-dd + if( sscanf(AnsiString(EditDate->Text).c_str(), "%u.%u.%u", &y, &m, &d) == 3 ){ //ja7ude 0428 + sp->year = BYTE(y % 100); + sp->date = WORD(m * 100 + d); + } + break; + } + if( !EditBgn->Text.IsEmpty() ){ + if( sscanf(AnsiString(EditBgn->Text).c_str(), "%u", &d) == 1){ //ja7ude 0428 + h = d / 100; + m = d % 100; + if( (sp->btime / 30) != (h * 60 + m) ){ + sp->btime = WORD((h * 60 + m) * 30 + 1); + } + } + } + if( !EditEnd->Text.IsEmpty() ){ + if( sscanf(AnsiString(EditEnd->Text).c_str(), "%u", &d) == 1){ //ja7ude 0428 + h = d / 100; + m = d % 100; + if( (sp->etime / 30) != (h * 60 + m) ){ + sp->etime = WORD((h * 60 + m) * 30 + 1); + } + } + } + StrCopy(sp->call, AnsiString(EditCall->Text).c_str(), MLCALL); //ja7ude 0428 + jstrupr(sp->call); + StrCopy(sp->name, AnsiString(EditName->Text).c_str(), MLNAME); //ja7ude 0428 + if( Log.m_LogSet.m_UpperName ) jstrupr(sp->name); + StrCopy(sp->qth, AnsiString(EditQTH->Text).c_str(), MLQTH); //ja7ude 0428 + if( Log.m_LogSet.m_UpperQTH ) jstrupr(sp->qth); + StrCopy(sp->ur, AnsiString(EditHis->Text).c_str(), MLRST); //ja7ude 0428 + jstrupr(sp->ur); + StrCopy(sp->my, AnsiString(EditMy->Text).c_str(), MLRST); //ja7ude 0428 + jstrupr(sp->my); + Log.SetFreq(sp, AnsiString(EditBand->Text).c_str()); //ja7ude 0428 + Log.SetMode(sp, AnsiString(EditMode->Text).c_str()); //ja7ude 0428 + StrCopy(sp->rem, AnsiString(EditRem->Text).c_str(), MLREM); //ja7ude 0428 + if( Log.m_LogSet.m_UpperREM ) jstrupr(sp->rem); + StrCopy(sp->qsl, AnsiString(EditQSL->Text).c_str(), MLQSL); //ja7ude 0428 + if( Log.m_LogSet.m_UpperQSL ) jstrupr(sp->qsl); + if( sscanf(AnsiString(EditEnv->Text).c_str(), "%u", &d) == 1){ //ja7ude 0428 + sp->env = WORD(d); + } + else { + sp->env = 0; + } + Log.SetOptStr(0, sp, AnsiString(EditOpt1->Text).c_str()); //ja7ude 0428 + Log.SetOptStr(1, sp, AnsiString(EditOpt2->Text).c_str()); //ja7ude 0428 + Log.SetOptStr(2, sp, AnsiString(EditUsr1->Text).c_str()); //ja7ude 0428 + Log.SetOptStr(3, sp, AnsiString(EditUsr2->Text).c_str()); //ja7ude 0428 + sp->send = *EditS->Text.c_str(); + sp->recv = *EditR->Text.c_str(); + sp->cq = *EditM->Text.c_str(); + sp->cq = char(toupper(sp->cq)); + StrCopy(sp->pow, AnsiString(EditPow->Text).c_str(), MLPOW); //ja7ude 0428 + jstrupr(sp->pow); + if( Log.m_LogSet.m_TimeZone != 'I' ){ + UTCtoJST(sp); + } +} +//--------------------------------------------------------------------- +void __fastcall TQSODlgBox::UpdateStat(void) +{ + char bf[256]; + + int cmp1max = m_fp->m_FindCmp1Max; + int cmp2max = m_fp->m_FindCmp2Max; + if( cmp2max && (m_fp->pFindTbl[0] == Log.m_CurNo) ){ + cmp1max--; + cmp2max--; + } + if( MsgEng ){ + if( !cmp2max ){ + strcpy(bf, "No Data"); + } + else if( cmp1max != cmp2max ){ + sprintf(bf, "Perfect: %u SameCall: %u", cmp1max, cmp2max - cmp1max); + } + else { + sprintf(bf, "Perfect: %u", cmp1max ); + } + } + else { + if( !cmp2max ){ + strcpy(bf, "一致なし"); + } + else if( cmp1max != cmp2max ){ + sprintf(bf, "完全一致: %u件 同一コール: %u件", cmp1max, cmp2max - cmp1max); + } + else { + sprintf(bf, "完全一致: %u件", cmp1max ); + } + } + LStat->Caption = bf; +} +//---------------------------------------------------------------------#if 0 +void __fastcall TQSODlgBox::GridDrawCell(TObject *Sender, int Col, int Row, + TRect &Rect, TGridDrawState State) +{ + char bf[256]; + SDMMLOG sd; + + Grid->Canvas->FillRect(Rect); + int X = Rect.Left + 4; + int Y = Rect.Top + 2; + + if( Row ){ + Row--; + bf[0] = 0; + if( Row < m_fp->GetCount() ){ + Log.GetData(&sd, m_fp->pFindTbl[Row]); + if( ((Row+1) != Grid->Row)||(Col != Grid->Col) ){ + if( m_fp->pFindTbl[Row] == Log.m_CurNo ){ + Grid->Canvas->Font->Color = clLtGray; + } + else if( Row < m_fp->m_FindCmp1Max ){ + Grid->Canvas->Font->Color = clRed; + } + else if( Row < m_fp->m_FindCmp2Max ){ + Grid->Canvas->Font->Color = clGreen; + } + } + if( Log.m_LogSet.m_TimeZone != 'I' ){ + JSTtoUTC(&sd); + } + } + else { + memset(&sd, 0, sizeof(SDMMLOG)); + } + switch(Col){ + case 0: // Date + strcpy(bf, Log.GetDateString(&sd)); + break; + case 1: // Time + strcpy(bf, Log.GetTimeString(sd.btime)); + break; + case 2: // Call + strcpy(bf, sd.call); + break; + case 3: // M + bf[0] = sd.cq; + bf[1] = 0; + break; + case 4: // HisRST + strcpy(bf, sd.ur); + break; + case 5: // MyRST + strcpy(bf, sd.my); + break; + case 6: // Band + strcpy(bf, Log.GetFreqString(sd.band, sd.fq)); + break; + case 7: // Mode + strcpy(bf, Log.GetModeString(sd.mode)); + break; + case 8: // Pow + strcpy(bf, sd.pow); + break; + case 9: // Name + strcpy(bf, sd.name); + break; + case 10: // QTH + strcpy(bf, sd.qth); + break; + case 11: // S + bf[0] = sd.send; + bf[1] = 0; + break; + case 12: // R + bf[0] = sd.recv; + bf[1] = 0; + break; + case 13: // REM + strcpy(bf, sd.rem); + break; + case 14: // QSL + strcpy(bf, sd.qsl); + break; + case 15: // etime; + strcpy(bf, Log.GetTimeString(sd.etime)); + break; + case 16: // Env + if( sd.env ) sprintf(bf, "%u", sd.env); + break; + case 17: // Opt1 + strcpy(bf, sd.opt1); + break; + case 18: // Opt2 + strcpy(bf, sd.opt2); + break; + case 19: // Usr1 + break; + case 20: // Usr2 + break; + } + Grid->Canvas->TextRect(Rect, X, Y, bf); + } + else { // タイトル + LPCSTR _tt[]={ + "Date","JST","Call","M", "His","My","Band","Mode","Pow","Name","QTH","S","R", + "Note","QSL", "End", "Env", "Opt1", "Opt2", "Usr1", "Usr2", + }; + if( Col == 1 ){ + Grid->Canvas->TextRect(Rect, X, Y, LTimeZone->Caption); + } + else { + Grid->Canvas->TextRect(Rect, X, Y, _tt[Col]); + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TQSODlgBox::GridSelectCell(TObject *Sender, int Col, + int Row, bool &CanSelect) +{ + int n = Row - 1; + if( n < m_fp->GetCount() ){ + if( m_CurNo != m_fp->pFindTbl[n] ){ + if( m_EditFlag ){ + UpdateCurData(&m_sd); + Log.PutData(&m_sd, m_CurNo); + m_EditFlag = 0; + } + m_CurNo = m_fp->pFindTbl[n]; + Log.GetData(&m_sd, m_CurNo); + UpdateTextData(&m_sd, m_CurNo); + Grid->Invalidate(); + UpdateBtn(); + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TQSODlgBox::SBMMCGClick(TObject *Sender) +{ + TMmcgDlgBox *pBox = new TMmcgDlgBox(this); + + AnsiString qth = EditQTH->Text; + AnsiString opt = EditOpt1->Text; + AnsiString call = EditCall->Text; + if( pBox->Execute(call, qth, opt) == TRUE ){ //ja7ude 0428 + EditQTH->Text = qth; + EditOpt1->Text = opt; + } + delete pBox; +} +//--------------------------------------------------------------------------- +void __fastcall TQSODlgBox::FormKeyDown(TObject *Sender, WORD &Key, + TShiftState Shift) +{ + if( Key == VK_F7 ){ + Key = 0; + } +} +//--------------------------------------------------------------------------- +void __fastcall TQSODlgBox::FormKeyUp(TObject *Sender, WORD &Key, + TShiftState Shift) +{ + if( Key == VK_F7 ){ + SBMMCGClick(NULL); + Key = 0; + } +} +//--------------------------------------------------------------------------- +void __fastcall TQSODlgBox::EditDateChange(TObject *Sender) +{ + m_EditFlag = 1; + UpdateBtn(); +} +//--------------------------------------------------------------------------- +void __fastcall TQSODlgBox::LogPicBtnClick(TObject *Sender) +{ + TLogPicDlg *pBox = new TLogPicDlg(this); + if( !EditCall->Text.IsEmpty() ){ + char bf[128]; + sprintf(bf, "%s on %s %s", + EditCall->Text.c_str(), + EditDate->Text.c_str(), + EditBgn->Text.c_str() + ); + pBox->Caption = bf; + } + pBox->Execute(AnsiString(EditQSL->Text).c_str()); //ja7ude 0428 + delete pBox; +} +//--------------------------------------------------------------------------- + + diff --git a/Qsodlg.dfm b/Qsodlg.dfm new file mode 100644 index 0000000..42d916e Binary files /dev/null and b/Qsodlg.dfm differ diff --git a/Qsodlg.h b/Qsodlg.h new file mode 100644 index 0000000..d9a27de --- /dev/null +++ b/Qsodlg.h @@ -0,0 +1,132 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//---------------------------------------------------------------------------- +#ifndef QsoDlgH +#define QsoDlgH +//---------------------------------------------------------------------------- +/* JA7UDE 0428 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +*/ +#include +//---------------------------------------------------------------------------- +#include "LogFile.h" +#include +#include +#include +#include +//---------------------------------------------------------------------------- +class TQSODlgBox : public TForm +{ +__published: + TButton *OKBtn; + TButton *CancelBtn; + TGroupBox *GroupBox1; + TStringGrid *Grid; + TLabel *Label1; + TEdit *EditDate; + TLabel *LTimeZone; + TEdit *EditBgn; + TLabel *Label3; + TEdit *EditEnd; + TLabel *Label4; + TEdit *EditCall; + TLabel *Label5; + TEdit *EditName; + TLabel *Label6; + TEdit *EditQTH; + TLabel *Label7; + TComboBox *EditMy; + TLabel *Label8; + TComboBox *EditHis; + TLabel *Label9; + TComboBox *EditBand; + TLabel *Label10; + TComboBox *EditMode; + TLabel *Label11; + TEdit *EditRem; + TLabel *Label12; + TEdit *EditQSL; + TLabel *Label13; + TLabel *Label14; + TLabel *Label15; + TEdit *EditEnv; + TLabel *Label16; + TEdit *EditOpt1; + TLabel *Label17; + TEdit *EditOpt2; + TLabel *Label18; + TComboBox *EditM; + TComboBox *EditS; + TComboBox *EditR; + TLabel *Label19; + TComboBox *EditPow; + TLabel *LStat; + TLabel *Label20; + TEdit *EditUsr1; + TLabel *Label21; + TEdit *EditUsr2; + TSpeedButton *SBMMCG; + TButton *LogPicBtn; + void __fastcall SBMMCGClick(TObject *Sender); + void __fastcall FormKeyDown(TObject *Sender, WORD &Key, TShiftState Shift); + void __fastcall FormKeyUp(TObject *Sender, WORD &Key, TShiftState Shift); + void __fastcall EditDateChange(TObject *Sender); + void __fastcall GridSelectCell(TObject *Sender, int Col, int Row, + bool &CanSelect); + void __fastcall GridDrawCell(TObject *Sender, int Col, int Row, + TRect &Rect, TGridDrawState State); + + void __fastcall LogPicBtnClick(TObject *Sender); +private: + CLogFind *m_fp; + int m_EditFlag; + + int m_CurNo; + SDMMLOG m_sd; + + AnsiString m_Country; + void __fastcall UpdateBtn(void); + void __fastcall SetCountry(void); + +// CAlignList AlignList; +// void __fastcall EntryAlignControl(void); + void __fastcall UpdateStat(void); + + void __fastcall UpdateTextData(SDMMLOG *sp, int n); + void __fastcall UpdateTextData(SDMMLOG *sp); + void __fastcall UpdateCurData(SDMMLOG *sp); +public: + virtual __fastcall TQSODlgBox(TComponent* AOwner); + int __fastcall Execute(CLogFind *fp, SDMMLOG *sp, int n); + int __fastcall ShowFind(CLogFind *fp); +}; +//---------------------------------------------------------------------------- +//extern TQSODlgBox *QSODlgBox; +//---------------------------------------------------------------------------- +#endif diff --git a/RMenuDlg.cpp b/RMenuDlg.cpp new file mode 100644 index 0000000..cf11aca --- /dev/null +++ b/RMenuDlg.cpp @@ -0,0 +1,145 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "RMenuDlg.h" +#include "Main.h" +//--------------------------------------------------------------------- +#pragma resource "*.dfm" +//TRMenuDialog *RMenuDialog; +static LPCSTR g_help={ +"コマンド\r\n" +"\r\n" +"\\$##... ##=00-FF, 送信する複数バイトを16進数で定義する\r\n" +" (例:\\$FE55AA -> FEh,55h,AAh)\r\n" +"\\x## ##=00-FF, 送信する1バイトを16進数で定義する\r\n" +" (例:\\xFE\\x55\\xAA -> FEh, 55h, AAh)\r\n" +"\\w## ##=00-99, ディレイ時間を10ms単位の10進数で定義する\r\n" +" (例:\\w05 -> wait 50ms)\r\n" +"\\r キャリッジリターンを送信する\r\n" +"\\n ラインフィードを送信する\r\n" +"\\c.... 以降はすべてコメント\r\n" +"\\\\ '\\'文字を送信する\r\n" +"その他 その文字列を送信する\r\n" +"\r\n" +"##の代わりにxxを記述すると、その部分はxx入力ボックスで定義した16進数に置き換わります。\r\n" +"この変換はICOMの機種アドレスを指定する場合に使用します。\r\n" +" 例:\\$FEFExxE01C0001FD (xxの部分が定義内容に置き換わる)" +}; +static LPCSTR g_helpeng={ +" This command sends a radio command to the rig. It will work for any rig. Use the following keyword to specify byte data in hexadecimal number.\r\n" +"\r\n" +"\\$##... ##=00-FF, Specify the byte data string in the hexadecimal format\r\n" +" (Example: \\$FE55AA -> $FE,$55,$AA)\r\n" +" ICOM CI-V address can be expressed by xx\r\n" +"\\x## ##=00-FF, Specify one byte in the hexadecimal format\r\n" +" (Example: \\xFE\\x55\\xAA -> $FE, $55, $AA)\r\n" +"\\w## ##=00-99, Specify the delay time\r\n" +" (Example: \\w05 -> wait 50ms)\r\n" +"\\r Send a carriage return\r\n" +"\\n Send a line feed\r\n" +"\\c.... Comment\r\n" +"\\\\ '\\' send character\r\n" +"Others Send the character as is" +}; + +//--------------------------------------------------------------------- +__fastcall TRMenuDialog::TRMenuDialog(TComponent* AOwner) + : TForm(AOwner) +{ + FormStyle = ((TForm *)AOwner)->FormStyle; + Font->Name = ((TForm *)AOwner)->Font->Name; + Font->Charset = ((TForm *)AOwner)->Font->Charset; + + if( MsgEng ){ + LH->Font->Name = "Arial"; + LH->Font->Charset = ((TForm *)AOwner)->Font->Charset; + + L1->Caption = "Caption"; + L2->Caption = "Command"; + Caption = "Edit menu"; + SBDel->Caption = "Delete this menu"; + SBIns->Caption = "Insert this menu"; + CancelBtn->Caption = "Cancel"; + LH->Caption = g_helpeng; + } + else { + LH->Caption = g_help; + } +} +//--------------------------------------------------------------------- +void __fastcall TRMenuDialog::UpdateUI(void) +{ + if( SBIns->Visible ){ + SBIns->Enabled = Mmsstv->m_nRadioMenu < RADIOMENUMAX; + } +} +//--------------------------------------------------------------------- +int __fastcall TRMenuDialog::Execute(AnsiString &strTTL, AnsiString &strCMD, int fAdd) +{ + if( fAdd ){ + Caption = MsgEng ? "Add menu" : "メニューの追加"; + SBDel->Visible = FALSE; + SBIns->Visible = FALSE; + } + ETTL->Text = strTTL; + ECMD->Text = strCMD; + UpdateUI(); + int r = ShowModal(); + strTTL = ETTL->Text; + strCMD = ECMD->Text; + return r; +} +//--------------------------------------------------------------------- +void __fastcall TRMenuDialog::SBDelClick(TObject *Sender) +{ + ModalResult = 1024; +} +//--------------------------------------------------------------------------- +void __fastcall TRMenuDialog::SBInsClick(TObject *Sender) +{ + ModalResult = 1025; +} +//--------------------------------------------------------------------------- +void __fastcall TRMenuDialog::SBRefClick(TObject *Sender) +{ + TOpenDialog *pBox = new TOpenDialog(this); + pBox->Options >> ofCreatePrompt; + pBox->Options << ofFileMustExist; + if( MsgEng ){ + pBox->Title = "Open command file"; + pBox->Filter = "Command files(*.rcm)|*.rcm|"; + } + else { + pBox->Title = "コマンド定義ファイルを開く"; + pBox->Filter = "コマンド定義ファイル(*.rcm)|*.rcm|"; + } + pBox->FileName = ""; + pBox->DefaultExt = "rcm"; + pBox->InitialDir = BgnDir; + if( pBox->Execute() == TRUE ){ + ECMD->Text = pBox->FileName.c_str(); + } + delete pBox; +} +//--------------------------------------------------------------------------- + diff --git a/RMenuDlg.dfm b/RMenuDlg.dfm new file mode 100644 index 0000000..a9440d8 Binary files /dev/null and b/RMenuDlg.dfm differ diff --git a/RMenuDlg.h b/RMenuDlg.h new file mode 100644 index 0000000..192ef41 --- /dev/null +++ b/RMenuDlg.h @@ -0,0 +1,63 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//---------------------------------------------------------------------------- +#ifndef RMenuDlgH +#define RMenuDlgH +//---------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//---------------------------------------------------------------------------- +#include "ComLib.h" +//---------------------------------------------------------------------------- +class TRMenuDialog : public TForm +{ +__published: + TButton *OKBtn; + TButton *CancelBtn; + TLabel *L1; + TLabel *L2; + TEdit *ETTL; + TEdit *ECMD; + TSpeedButton *SBDel; + TLabel *LH; + TSpeedButton *SBIns; + void __fastcall SBDelClick(TObject *Sender); + void __fastcall SBInsClick(TObject *Sender); + + void __fastcall SBRefClick(TObject *Sender); +private: + void __fastcall UpdateUI(void); +public: + virtual __fastcall TRMenuDialog(TComponent* AOwner); + + int __fastcall Execute(AnsiString &strTTL, AnsiString &strCMD, int fAdd = FALSE); +}; +//---------------------------------------------------------------------------- +//extern PACKAGE TRMenuDialog *RMenuDialog; +//---------------------------------------------------------------------------- +#endif diff --git a/RadioSet.cpp b/RadioSet.cpp new file mode 100644 index 0000000..8969c2c --- /dev/null +++ b/RadioSet.cpp @@ -0,0 +1,555 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "RadioSet.h" +#include "Main.h" +//--------------------------------------------------------------------- +#pragma resource "*.dfm" +LPCSTR __MK[]={ + "YAESU FT-1000D, 1000MP, 920", //AA6YQ 1.66 cosmetic, MakerIndex=0 + "YAESU FT-9000, 2000, 950, 450", //AA6YQ 1.66 , MakerIndex=1 + "YAESU FT-736, 817, 847, 857, 897", //AA6YQ 1.66 cosmetic, MakerIndex=2 + "Icom xx=addr 01-7F", // , MakerIndex=3 + "Ten-Tec Omni VI xx=addr 00-64", // , MakerIndex=4 + "Kenwood, Elecraft ", // , MakerIndex=5 + "JRC JST-245", // , MakerIndex=6 + "Clear", // , MakerIndex=6 + NULL, // , MakerIndex=8 +}; +LPCSTR __MT[][3]={ + {"", "\\$000000000F", "\\$000000010F\\w10" }, + {"", "TX0;", "TX1;\\w10" }, //AA6YQ 1.66 + {"\\$0000000000", "\\$0000000088", "\\$0000000008\\w10" }, + {"", "\\$FEFExxE01C0000FD", "\\$FEFExxE01C0001FD\\w10" }, + {"", "\\$FEFExxE01602FD", "\\$FEFExxE01601FD\\w10" }, + {"", "RX;", "TX;\\w10" }, + {"", "H1\\rX0\\rH0\\r", "H1\\rX1\\rH0\\r\\w10" }, + {"", "", "" }, +}; + +#define MAKER_UNKNOWN 7 + +typedef struct { + LPCSTR pKey; + int r; +}POLLDEF; + +const POLLDEF __VT0[]={ + { "NONE", 0 }, + { "FT-1000MP", RADIO_POLLYAESUHF }, + { "FT-1000D", RADIO_POLLFT1000D }, + { "FT-920", RADIO_POLLFT920 }, + { NULL, 0 }, +}; +const POLLDEF __VT1[]={ + { "NONE", 0 }, + { "FT-9000", RADIO_POLLFT9000 }, //1.66B AA6YQ + { "FT-2000", RADIO_POLLFT2000 }, //1.66B AA6YQ + { "FT-950", RADIO_POLLFT950 }, //1.66B AA6YQ + { "FT-450", RADIO_POLLFT450 }, //1.66B AA6YQ + { NULL, 0 }, +}; +const POLLDEF __VT2[]={ + { "NONE", 0 }, + { "FT-817, 847, 857, 897", RADIO_POLLYAESUVU }, + { NULL, 0 }, +}; +const POLLDEF __VT3[]={ + { "NONE", 0 }, + { "ICOM CI-V", RADIO_POLLICOM }, + { "ICOM CI-V (no inquiry)", RADIO_POLLICOMN }, + { NULL, 0 }, +}; +const POLLDEF __VT4[]={ + { "NONE", 0 }, + { "Ten-Tec Omni VI", RADIO_POLLOMNIVI }, + { "Ten-Tec Omni VI (no inquiry)", RADIO_POLLOMNIVIN }, + { NULL, 0 }, +}; +const POLLDEF __VT5[]={ + { "NONE", 0 }, + { "KENWOOD", RADIO_POLLKENWOOD }, + { "KENWOOD (use auto info)", RADIO_POLLKENWOODN }, + { NULL, 0 }, +}; +const POLLDEF __VT6[]={ + { "NONE", 0 }, + { "JST245", RADIO_POLLJST245 }, + { "JST245 (use auto info)", RADIO_POLLJST245N }, + { NULL, 0 }, +}; +const POLLDEF __VTUNKNOWN[]={ + { "NONE", 0 }, + { "YAESU FT-1000MP", RADIO_POLLYAESUHF }, + { "YAESU FT-1000D", RADIO_POLLFT1000D }, + { "YAESU FT-920", RADIO_POLLFT920 }, + { "YAESU FT-817, 847, 857, 897", RADIO_POLLYAESUVU }, + { "YAESU FT-9000", RADIO_POLLFT9000 }, //1.66B AA6YQ + { "YAESU FT-2000", RADIO_POLLFT2000 }, //1.66B AA6YQ + { "YAESU FT-950", RADIO_POLLFT950 }, //1.66B AA6YQ + { "YAESU FT-450", RADIO_POLLFT450 }, //1.66B AA6YQ + { "ICOM CI-V", RADIO_POLLICOM }, + { "ICOM CI-V (no inquiry)", RADIO_POLLICOMN }, + { "Ten-Tec Omni VI", RADIO_POLLOMNIVI }, + { "Ten-Tec Omni VI (no inquiry)", RADIO_POLLOMNIVIN }, + { "KENWOOD", RADIO_POLLKENWOOD }, + { "KENWOOD (use auto info)", RADIO_POLLKENWOODN }, + { "JST245", RADIO_POLLJST245 }, + { "JST245 (use auto info)", RADIO_POLLJST245N }, + { NULL, 0 }, +}; +const POLLDEF *__VL[]={ + __VT0, __VT1, __VT2, __VT3, __VT4, __VT5, __VT6, __VTUNKNOWN, NULL, +}; +//--------------------------------------------------------------------- +__fastcall TRADIOSetDlg::TRADIOSetDlg(TComponent* AOwner) + : TForm(AOwner) +{ + FormStyle = ((TForm *)AOwner)->FormStyle; + Font->Name = ((TForm *)AOwner)->Font->Name; + Font->Charset = ((TForm *)AOwner)->Font->Charset; + if( MsgEng ){ + CancelBtn->Caption = "Cancel"; + } + else { + Caption = "リグコントロール(Radio command)"; + GB1->Caption = "ポートの設定"; + } + int i; + for( i = 0; __MK[i] != NULL; i++ ){ + Maker->Items->Add(__MK[i]); + } + m_InitWidth = CmdInit->Width; + m_PollType = 0; + m_Maker = 0; + m_MMList.QueryList("MMR"); + for( int i = 0; i < m_MMList.GetCount(); i++ ){ + PortName->Items->Insert(1, m_MMList.GetItemName(i)); + } + PortName->DropDownCount = PortName->Items->Count; + m_DisEvent = 0; +} +//--------------------------------------------------------------------- +void __fastcall TRADIOSetDlg::UpdateUI(void) +{ + int f; + if( !strcmpi(AnsiString(PortName->Text).c_str(), "PSKGNR")|| //ja7ude 0428 + !strcmpi(AnsiString(PortName->Text).c_str(), "WD5GNR")|| //ja7ude 0428 + !strcmpi(AnsiString(PortName->Text).c_str(), "LOGGER") ){ //ja7ude 0428 + GCmd->Visible = FALSE; + if( !strcmpi(AnsiString(PortName->Text).c_str(), "LOGGER") ){ //ja7ude 0428 + GGNR->Visible = FALSE; +// LTNX->Caption = "Thanks to Bob Furzer (K4CY) who is releasing the fine programs."; + } + else { + GGNR->Visible = TRUE; +// LTNX->Caption = "Thanks to Al Williams (WD5GNR) who is releasing the fine programs."; + } + LGNR->Visible = OpenGNR->Checked; + CmdGNR->Visible = OpenGNR->Checked; + RefBtn->Visible = OpenGNR->Checked; + LPTT->Visible = OpenGNR->Checked; + Maker->Visible = FALSE; + LoadBtn->Visible = FALSE; + SaveBtn->Visible = FALSE; + f = FALSE; + } + else { + GGNR->Visible = FALSE; + GCmd->Visible = TRUE; + Maker->Visible = TRUE; + LoadBtn->Visible = TRUE; + SaveBtn->Visible = TRUE; + f = IsXX(); + Lxx->Visible = f; + Cmdxx->Visible = f; + AddrScan->Visible = f && m_PollType; + if( f ){ + CmdInit->Width = m_InitWidth; + } + else { + CmdInit->Width = CmdRx->Width; + } + f = (m_MMList.IndexOf(AnsiString(PortName->Text).c_str()) < 0) ? TRUE : FALSE; //ja7ude 0428 + } + Label2->Enabled = f; + Baud->Enabled = f; + BitLen->Enabled = f; + Stop->Enabled = f; + Parity->Enabled = f; + GroupBox3->Enabled = f; + flwXON->Enabled = f; + flwCTS->Enabled = f && !CBPTT->Checked; + CBPTT->Enabled = f; + Label3->Enabled = f; + ByteWait->Enabled = f; + Label8->Enabled = f; + f = TRUE; + LVFO->Visible = f; + VFOType->Visible = f; + LInt->Visible = f; + LInts->Visible = f; + PollInt->Visible = f; + LVFO->Enabled = f; + VFOType->Enabled = f; + LInt->Enabled = f; + LInts->Enabled = f; + PollInt->Enabled = f; +} +//--------------------------------------------------------------------- +int __fastcall TRADIOSetDlg::Execute(void) +{ + PortName->Text = RADIO.StrPort; + Baud->Text = RADIO.BaudRate; + BitLen->ItemIndex = RADIO.BitLen; + Parity->ItemIndex = RADIO.Parity; + Stop->ItemIndex = RADIO.Stop; + flwXON->Checked = RADIO.flwXON; + flwCTS->Checked = RADIO.flwCTS; + CBPTT->Checked = RADIO.usePTT; + + ByteWait->Text = int(RADIO.ByteWait); + + char bf[32]; + sprintf( bf, "%02X", RADIO.Cmdxx); + Cmdxx->Text = bf; + CmdInit->Text = RADIO.CmdInit; + CmdRx->Text = RADIO.CmdRx; + CmdTx->Text = RADIO.CmdTx; + + CmdGNR->Text = RADIO.cmdGNR; + OpenGNR->Checked = RADIO.openGNR; + m_PollType = RADIO.PollType; + PollInt->Text = (RADIO.PollInterval + 5)/10.0; + AddrScan->Checked = RADIO.PollScan; + SetMaker(); + UpdateUI(); + if( ShowModal() == IDOK ){ + StrCopy(RADIO.StrPort, AnsiString(PortName->Text).c_str(), 31); //ja7ude 0428 + int dd; + if( sscanf(AnsiString(Baud->Text).c_str(), "%u", &dd) == 1 ){ //ja7ude 0428 + RADIO.BaudRate = dd; + } + RADIO.BitLen = BitLen->ItemIndex; + RADIO.Parity = Parity->ItemIndex; + RADIO.Stop = Stop->ItemIndex; + RADIO.flwXON = flwXON->Checked; + RADIO.flwCTS = flwCTS->Checked; + RADIO.usePTT = CBPTT->Checked; + + if( sscanf(AnsiString(ByteWait->Text).c_str(), "%u", &dd) == 1 ){ //ja7ude 0428 + if( (dd >= 0) && (dd <= 1000) ){ + RADIO.ByteWait = dd; + } + } + if( sscanf(AnsiString(Cmdxx->Text).c_str(), "%X", &dd) == 1 ){ //ja7ude 0428 + RADIO.Cmdxx = dd & 0x000000ff; + } + RADIO.CmdInit = CmdInit->Text; + RADIO.CmdRx = CmdRx->Text; + RADIO.CmdTx = CmdTx->Text; + + RADIO.cmdGNR = CmdGNR->Text; + RADIO.openGNR = OpenGNR->Checked; + + RADIO.PollType = m_PollType; + double d; + if( sscanf(AnsiString(PollInt->Text).c_str(), "%lf", &d) == 1 ){ //ja7ude 0428 + if( d >= 0.5 ){ + RADIO.PollInterval = int((d * 10.0) - 5); + if( RADIO.PollInterval < 0 ) RADIO.PollInterval = 0; + } + } + RADIO.PollScan = AddrScan->Checked; + RADIO.change = 1; + return TRUE; + } + else { + return FALSE; + } +} +//--------------------------------------------------------------------------- +void __fastcall TRADIOSetDlg::LoadBtnClick(TObject *Sender) +{ +// + TOpenDialog *pBox = Mmsstv->OpenDialog; + pBox->Options >> ofCreatePrompt; + pBox->Options << ofFileMustExist; + if( MsgEng ){ + pBox->Title = "Open command file"; + pBox->Filter = "Command files(*.rcm)|*.rcm|"; + } + else { + pBox->Title = "コマンド定義ファイルを開く"; + pBox->Filter = "コマンド定義ファイル(*.rcm)|*.rcm|"; + } + pBox->FileName = ""; + pBox->DefaultExt = "rcm"; + pBox->InitialDir = BgnDir; + NormalWindow(this); + if( pBox->Execute() == TRUE ){ + CWaitCursor w; + TMemIniFile *pIniFile = new TMemIniFile(pBox->FileName); + CmdInit->Text = pIniFile->ReadString("RADIO", "CmdInit", CmdInit->Text); + CmdRx->Text = pIniFile->ReadString("RADIO", "CmdRx", CmdRx->Text); + CmdTx->Text = pIniFile->ReadString("RADIO", "CmdTx", CmdTx->Text); + Cmdxx->Text = pIniFile->ReadString("RADIO", "Cmdxx", Cmdxx->Text); + m_PollType = pIniFile->ReadInteger("RADIO", "PollType", 0); + PollInt->Text = (pIniFile->ReadInteger("RADIO", "PollInterval", 0) + 5)/10.0; + AddrScan->Checked = 0; + delete pIniFile; + SetMaker(); + UpdateUI(); + } + TopWindow(this); +} +//--------------------------------------------------------------------------- +void __fastcall TRADIOSetDlg::SaveBtnClick(TObject *Sender) +{ + TSaveDialog *pBox = Mmsstv->SaveDialog; + if( MsgEng ){ + pBox->Title = "Save command file"; + pBox->Filter = "Command files(*.rcm)|*.rcm|"; + } + else { + pBox->Title = "コマンド定義ファイルの作成"; + pBox->Filter = "コマンド定義ファイル(*.rcm)|*.rcm|"; + } + pBox->FileName = "MyRIG.rcm"; + pBox->DefaultExt = "rcm"; + pBox->InitialDir = BgnDir; + NormalWindow(this); + if( pBox->Execute() == TRUE ){ + CWaitCursor w; + TMemIniFile *pIniFile = new TMemIniFile(pBox->FileName); + pIniFile->WriteString("RADIO", "CmdInit", CmdInit->Text); + pIniFile->WriteString("RADIO", "CmdRx", CmdRx->Text); + pIniFile->WriteString("RADIO", "CmdTx", CmdTx->Text); + pIniFile->WriteString("RADIO", "Cmdxx", Cmdxx->Text); + pIniFile->WriteInteger("RADIO", "PollType", m_PollType); + double d; + int dd = 5; + if( sscanf(AnsiString(PollInt->Text).c_str(), "%lf", &d) == 1 ){ //ja7ude 0428 + if( d >= 0.5 ){ + dd = int((d * 10.0) - 5); + if( dd < 0 ) dd = 0; + } + } + pIniFile->WriteInteger("RADIO", "PollInterval", dd); + pIniFile->UpdateFile(); + delete pIniFile; + } + TopWindow(this); +} +//--------------------------------------------------------------------------- +int __fastcall TRADIOSetDlg::IsXX(void) +{ + if( strstr(AnsiString(Maker->Text).c_str(), "xx") != NULL ) return 1; //ja7ude 0428 + if( m_PollType == RADIO_POLLICOM ) return 1; + if( m_PollType == RADIO_POLLICOMN ) return 1; + if( m_PollType == RADIO_POLLOMNIVI ) return 1; + if( m_PollType == RADIO_POLLOMNIVIN ) return 1; + return 0; +} +//--------------------------------------------------------------------------- +int __fastcall TRADIOSetDlg::IsCompatible(int PollType, int MakerIndex) +{ + + if (MakerIndex == 5) { //MakerIndex 5 is Kenwood + if (PollType == 0){ + return 1; + } + else if (PollType == RADIO_POLLKENWOOD) { + return 1; + } + else if (PollType == RADIO_POLLKENWOODN) { + return 1; + } + else { + return 0; + } + } + else if (MakerIndex == 1) { //MakerIndex 1 is Yaesu FT-9000 et al + if (PollType == 0){ + return 1; + } + else if (PollType == RADIO_POLLFT9000) { + return 1; + } + else if (PollType == RADIO_POLLFT2000) { + return 1; + } + else if (PollType == RADIO_POLLFT950) { + return 1; + } + else if (PollType == RADIO_POLLFT450) { + return 1; + } + else { + return 0; + } + + } + else { + return 1; + } +} +//--------------------------------------------------------------------------- +int __fastcall TRADIOSetDlg::IsSame(LPCSTR t, LPCSTR v) +{ + for( ; *v && *t; v++, t++ ){ + if( (*v=='x')&&(*(v+1)=='x') ){ + t++; + v++; + } + else if( (*t == '\\')&&(*(t+1) == 'w') ){ + return 1; + } + else if( (*v == '\\')&&(*(v+1) == 'w') ){ + return 1; + } + else if( *t != *v ){ + return 0; + } + } + return *t != *v ? 0 : 1; +} +//--------------------------------------------------------------------------- +int __fastcall TRADIOSetDlg::GetVFOType(LPCSTR pKey) +{ + for( int i = 0; __VL[i] != NULL; i++ ){ + const POLLDEF *p = __VL[i]; + for( ; p->pKey != NULL; p++ ){ + if( !strcmp(p->pKey, pKey) ) return p->r; + } + } + return 0; +} +//--------------------------------------------------------------------------- +LPCSTR __fastcall TRADIOSetDlg::GetVFOName(int r) +{ + for( int i = 0; __VL[i] != NULL; i++ ){ + const POLLDEF *p = __VL[i]; + for( ; p->pKey != NULL; p++ ){ + if( p->r == r ) return p->pKey; + } + } + return "NONE"; +} +//--------------------------------------------------------------------------- +void __fastcall TRADIOSetDlg::SetVFOList(void) +{ + m_DisEvent++; + const POLLDEF *p = __VL[m_Maker]; + VFOType->Items->Clear(); + for( ; p->pKey != NULL; p++ ){ + VFOType->Items->Add(p->pKey); + } + VFOType->Text = GetVFOName(m_PollType); + m_DisEvent--; +} +//--------------------------------------------------------------------------- +void __fastcall TRADIOSetDlg::SetMaker(void) +{ + int i; + for( i = 0; __MK[i] != NULL; i++ ){ + if( IsSame(AnsiString(CmdRx->Text).c_str(), __MT[i][1]) && IsSame(AnsiString(CmdTx->Text).c_str(), __MT[i][2]) && IsCompatible (m_PollType,i)){ //AA6YQ 1.66 //ja7ude 0428 + m_DisEvent++; + Maker->Text = __MK[i]; + m_DisEvent--; + m_Maker = i; + SetVFOList(); + return; + } + } + m_Maker = MAKER_UNKNOWN; + m_DisEvent++; + Maker->Text = "Unknown"; + SetVFOList(); + m_DisEvent--; +} + +void __fastcall TRADIOSetDlg::MakerChange(TObject *Sender) +{ + if( m_DisEvent ) return; + + m_PollType = 0; + VFOType->Text = "NONE"; + PollInt->Text = "1"; + AddrScan->Checked = 0; + for( int i = 0; __MK[i] != NULL; i++ ){ + if( Maker->Text == __MK[i] ){ + CmdInit->Text = __MT[i][0]; + CmdRx->Text = __MT[i][1]; + CmdTx->Text = __MT[i][2]; + m_Maker = i; + if( m_Maker == 3 ){ // Ten-Tec Omni-VI + Cmdxx->Text = "04"; + } + SetVFOList(); + break; + } + } + UpdateUI(); +} +//--------------------------------------------------------------------------- +void __fastcall TRADIOSetDlg::PortNameChange(TObject *Sender) +{ + if( m_DisEvent ) return; + + UpdateUI(); +} +//--------------------------------------------------------------------------- +void __fastcall TRADIOSetDlg::RefBtnClick(TObject *Sender) +{ + TOpenDialog *pBox = Mmsstv->OpenDialog; + pBox->Options >> ofCreatePrompt; + pBox->Options << ofFileMustExist; + if( MsgEng ){ + pBox->Title = "Program file"; + pBox->Filter = "Program files(*.exe;*.lnk)|*.exe;*.lnk|"; + } + else { + pBox->Title = "プログラムファイル"; + pBox->Filter = "プログラムファイル(*.exe;*.lnk)|*.exe;*.lnk|"; + } + pBox->FileName = CmdGNR->Text.c_str(); + pBox->DefaultExt = "exe"; + char bf[256]; + SetDirName(bf, AnsiString(CmdGNR->Text).c_str()); //ja7ude 0428 + pBox->InitialDir = bf; + NormalWindow(this); + if( pBox->Execute() == TRUE ){ + CmdGNR->Text = pBox->FileName.c_str(); + } + TopWindow(this); +} +//--------------------------------------------------------------------------- +void __fastcall TRADIOSetDlg::VFOTypeChange(TObject *Sender) +{ + if( m_DisEvent ) return; + + m_PollType = GetVFOType(AnsiString(VFOType->Text).c_str()); //ja7ude 0428 + UpdateUI(); +} +//--------------------------------------------------------------------------- diff --git a/RadioSet.dfm b/RadioSet.dfm new file mode 100644 index 0000000..cc93d01 Binary files /dev/null and b/RadioSet.dfm differ diff --git a/RadioSet.h b/RadioSet.h new file mode 100644 index 0000000..a3ec1f9 --- /dev/null +++ b/RadioSet.h @@ -0,0 +1,114 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//---------------------------------------------------------------------------- +#ifndef RadioSetH +#define RadioSetH +//---------------------------------------------------------------------------- +//ja7ude 0428 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//---------------------------------------------------------------------------- +#include "Cradio.h" +#include +#include +//---------------------------------------------------------------------------- +class TRADIOSetDlg : public TForm +{ +__published: + TButton *OKBtn; + TButton *CancelBtn; + TGroupBox *GB1; + TComboBox *PortName; + TLabel *Label1; + TLabel *Label2; + TComboBox *Baud; + TRadioGroup *BitLen; + TRadioGroup *Stop; + TRadioGroup *Parity; + TGroupBox *GroupBox3; + TCheckBox *flwXON; + TCheckBox *flwCTS; + TLabel *Label3; + TComboBox *ByteWait; + TLabel *Label8; + TButton *LoadBtn; + TButton *SaveBtn; + TComboBox *Maker; + TGroupBox *GGNR; + TLabel *LGNR; + TEdit *CmdGNR; + TButton *RefBtn; + TCheckBox *OpenGNR; + TLabel *LPTT; + TGroupBox *GCmd; + TLabel *Label4; + TLabel *Label5; + TLabel *Label6; + TLabel *Lxx; + TLabel *LVFO; + TEdit *CmdInit; + TEdit *CmdRx; + TEdit *CmdTx; + TEdit *Cmdxx; + TComboBox *VFOType; + TComboBox *PollInt; + TLabel *LInt; + TLabel *LInts; + TCheckBox *AddrScan; + TGroupBox *GB2; + TCheckBox *CBPTT; + void __fastcall LoadBtnClick(TObject *Sender); + void __fastcall SaveBtnClick(TObject *Sender); + void __fastcall MakerChange(TObject *Sender); + void __fastcall PortNameChange(TObject *Sender); + void __fastcall RefBtnClick(TObject *Sender); + + void __fastcall VFOTypeChange(TObject *Sender); + + +private: + int m_DisEvent; + int __fastcall IsXX(void); + int __fastcall IsCompatible(int PollType, int MakerIndex); + int __fastcall IsSame(LPCSTR v, LPCSTR t); + void __fastcall SetMaker(void); + void __fastcall UpdateUI(void); + void __fastcall SetVFOList(void); + int __fastcall GetVFOType(LPCSTR pKey); + LPCSTR __fastcall GetVFOName(int r); + int m_Maker; + int m_PollType; + int m_InitWidth; + CMMList m_MMList; +public: + virtual __fastcall TRADIOSetDlg(TComponent* AOwner); + int __fastcall Execute(void); +}; +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +#endif diff --git a/RepSet.cpp b/RepSet.cpp new file mode 100644 index 0000000..f0c919a --- /dev/null +++ b/RepSet.cpp @@ -0,0 +1,228 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "RepSet.h" +#include "Main.h" +#include "MacroKey.h" +#include "TextEdit.h" +//--------------------------------------------------------------------- +#pragma resource "*.dfm" +//TRepSetDlg *RepSetDlg; +const int _ToneTbl[]={750, 1000, 1477, 1500, 1633, 1750, 2100, 2300, 0}; +//--------------------------------------------------------------------- +__fastcall TRepSetDlg::TRepSetDlg(TComponent* AOwner) + : TForm(AOwner) +{ + Font->Name = ((TForm *)AOwner)->Font->Name; + Font->Charset = ((TForm *)AOwner)->Font->Charset; + if( MsgEng ){ + CancelBtn->Caption = "Cancel"; + } + int i; + CBTone->Items->Clear(); + for( i = 0; _ToneTbl[i]; i++ ){ + char bf[32]; + sprintf(bf, "%u", _ToneTbl[i]); + CBTone->Items->Add(bf); + } + CBMode->Items->Clear(); + for( i = 0; i < smEND; i++ ){ + CBMode->Items->Add(SSTVModeList[i]); + } +} +//--------------------------------------------------------------------- +void __fastcall TRepSetDlg::UpdateBtn(void) +{ + BBtn->Enabled = CBEnb->Checked; +} +//--------------------------------------------------------------------- +void __fastcall TRepSetDlg::UpdateStat(void) +{ + CSSTVDEM *dp = Mmsstv->pDem; + char bf[256]; + + sprintf(bf, "State\t%u\tAns\t%u\r\nRX\t%u/%u\tTX\t%u\r\n", + dp->m_repmode, + dp->m_repANS, + dp->m_repRLY, + dp->m_repRX, + dp->m_repTX + ); + if( dp->m_RepSQ && !dp->m_Sync && !Mmsstv->SBTX->Down ){ + char bbf[64]; + sprintf(bbf, "Level\t%d\t", dp->m_repsig ); + strcat(bf, bbf); + } + if( sys.m_RepBeacon && dp->m_Repeater ){ + char bbf[64]; + sprintf(bbf, "Beacon\t%d, %ds", + Mmsstv->m_RepBeaconCount, + sys.m_RepBeacon - ((::GetTickCount() - Mmsstv->m_RepTick)/1000) + ); + strcat(bf, bbf); + } + LS->Caption = bf; +} +//--------------------------------------------------------------------- +int __fastcall TRepSetDlg::Execute(void) +{ + CBEnb->Checked = Mmsstv->pDem->m_Repeater; + LS->Enabled = CBEnb->Checked; + + AnsCW->Text = sys.m_RepAnsCW; + TA->Text = sys.m_RepTimeA; + TB->Text = sys.m_RepTimeB; + TC->Text = sys.m_RepTimeC; + TD->Text = sys.m_RepTimeD; + RGS->ItemIndex = sys.m_RepSenseLvl; + ETempT->Text = sys.m_RepTempTX; + ETempB->Text = sys.m_RepTempBeacon; + EFD->Text = sys.m_RepFolder; + + CBMode->ItemIndex = sys.m_RepBeaconMode; + ESQ->Text = Mmsstv->pDem->m_RepSQ; + CBQT->Text = sys.m_RepQuietnessTime / 60; + CBTone->Text = Mmsstv->pDem->m_RepTone; + CBAS->Checked = sys.m_RepBottomAdj; + CBFLT->Checked = sys.m_RepBeaconFilter; + for( int i = 0; _ToneTbl[i]; i++ ){ + if( _ToneTbl[i] == Mmsstv->pDem->m_RepTone ){ + CBTone->ItemIndex = i; + break; + } + } + UpdateBtn(); + switch(sys.m_RepBeacon){ + case 10*60: + CGB->ItemIndex = 1; + break; + case 20*60: + CGB->ItemIndex = 2; + break; + case 30*60: + CGB->ItemIndex = 3; + break; + case 60*60: + CGB->ItemIndex = 4; + break; + case 120*60: + CGB->ItemIndex = 5; + break; + default: + CGB->ItemIndex = 0; + } + UpdateStat(); + int r = ShowModal(); + if( r != mrCancel ){ + int d; + sscanf(AnsiString(TA->Text).c_str(), "%u", &d); //ja7ude 0428 + if( d >= 100 ) sys.m_RepTimeA = d; + sscanf(AnsiString(TB->Text).c_str(), "%u", &d); //ja7ude 0428 + if( d >= 100 ) sys.m_RepTimeB = d; + sscanf(AnsiString(TC->Text).c_str(), "%u", &d); //ja7ude 0428 + if( d >= 100 ) sys.m_RepTimeC = d; + sscanf(AnsiString(TD->Text).c_str(), "%u", &d); //ja7ude 0428 + if( d >= 100 ) sys.m_RepTimeD = d; + sys.m_RepAnsCW = AnsCW->Text; + sys.m_RepSenseLvl = RGS->ItemIndex; + Mmsstv->pDem->SetRepSenseLvl(); + + sys.m_RepTempTX = ETempT->Text; + sys.m_RepTempBeacon = ETempB->Text; + sys.m_RepFolder = EFD->Text; + + sscanf(AnsiString(ESQ->Text).c_str(), "%u", &d); //ja7ude 0428 + if( (d >= 0) && (d <= 32767) ) Mmsstv->pDem->m_RepSQ = d; + + sscanf(AnsiString(CBQT->Text).c_str(), "%u", &d); //ja7ude 0428 + if( (d >= 0) && (d <= 20) ) sys.m_RepQuietnessTime = d * 60; + switch(CGB->ItemIndex){ + case 1: + sys.m_RepBeacon = 10*60; + break; + case 2: + sys.m_RepBeacon = 20*60; + break; + case 3: + sys.m_RepBeacon = 30*60; + break; + case 4: + sys.m_RepBeacon = 60*60; + break; + case 5: + sys.m_RepBeacon = 120*60; + break; + default: + sys.m_RepBeacon = 0; + break; + } + sys.m_RepBeaconMode = CBMode->ItemIndex; + sys.m_RepBottomAdj = CBAS->Checked; + sys.m_RepBeaconFilter = CBFLT->Checked; + sscanf(AnsiString(CBTone->Text).c_str(), "%u", &d); //ja7ude 0428 + if( (d >= 100) && (d < 2700) ){ + Mmsstv->pDem->m_RepTone = d; + } + Mmsstv->pDem->InitRepeater(); + Mmsstv->pDem->SetRepeater(CBEnb->Checked); + } + return r; +} +//--------------------------------------------------------------------- +void __fastcall TRepSetDlg::MBtnClick(TObject *Sender) +{ + TMacroKeyDlg *pBox = new TMacroKeyDlg(this); + AnsiString as = AnsCW->Text; + if( pBox->Execute(as) > 0 ){ + AnsCW->SetFocus(); + AnsCW->SelStart = strlen(AnsiString(AnsCW->Text).c_str()); //ja7ude 0428 + AnsCW->SelLength = 0; + for( LPCSTR p = as.c_str(); *p; p++ ){ + ::PostMessage(AnsCW->Handle, WM_CHAR, *p, 0); + } + } + delete pBox; +} +//--------------------------------------------------------------------------- +void __fastcall TRepSetDlg::TimerTimer(TObject *Sender) +{ + UpdateStat(); +} +//--------------------------------------------------------------------------- +void __fastcall TRepSetDlg::BBtnClick(TObject *Sender) +{ + ModalResult = 1024; +} +//--------------------------------------------------------------------------- +void __fastcall TRepSetDlg::CBEnbClick(TObject *Sender) +{ + UpdateBtn(); +} +//--------------------------------------------------------------------------- +void __fastcall TRepSetDlg::HBtnClick(TObject *Sender) +{ + ShowHelp(this, "Repeater.txt"); +} +//--------------------------------------------------------------------------- + + diff --git a/RepSet.dfm b/RepSet.dfm new file mode 100644 index 0000000..657e707 Binary files /dev/null and b/RepSet.dfm differ diff --git a/RepSet.h b/RepSet.h new file mode 100644 index 0000000..d86b0d6 --- /dev/null +++ b/RepSet.h @@ -0,0 +1,104 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//---------------------------------------------------------------------------- +#ifndef RepSetH +#define RepSetH +//---------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//---------------------------------------------------------------------------- +class TRepSetDlg : public TForm +{ +__published: + TButton *OKBtn; + TButton *CancelBtn; + TEdit *AnsCW; + TLabel *L1; + TGroupBox *GB1; + TLabel *L2; + TLabel *L3; + TLabel *L4; + TLabel *L5; + TEdit *TA; + TEdit *TB; + TEdit *TC; + TEdit *TD; + TLabel *L6; + TLabel *L7; + TLabel *L8; + TLabel *L9; + TButton *MBtn; + TCheckBox *CBEnb; + TTimer *Timer; + TGroupBox *GB2; + TLabel *LS; + TRadioGroup *RGS; + TGroupBox *GB3; + TLabel *L11; + TLabel *L12; + TEdit *ETempT; + TEdit *ETempB; + TButton *BBtn; + TGroupBox *GB4; + TLabel *L10; + TComboBox *CBMode; + TEdit *ESQ; + TLabel *L13; + TLabel *L14; + TComboBox *CBQT; + TLabel *L15; + TLabel *L16; + TComboBox *CBTone; + TLabel *L17; + TButton *HBtn; + TComboBox *CGB; + TLabel *L18; + TLabel *L19; + TCheckBox *CBFLT; + TLabel *L20; + TEdit *EFD; + TCheckBox *CBAS; + void __fastcall MBtnClick(TObject *Sender); + void __fastcall TimerTimer(TObject *Sender); + + void __fastcall BBtnClick(TObject *Sender); + void __fastcall CBEnbClick(TObject *Sender); + void __fastcall HBtnClick(TObject *Sender); +private: + void __fastcall UpdateBtn(void); + void __fastcall UpdateStat(void); + +public: + virtual __fastcall TRepSetDlg(TComponent* AOwner); + + int __fastcall Execute(void); +}; +//---------------------------------------------------------------------------- +//extern PACKAGE TRepSetDlg *RepSetDlg; +//---------------------------------------------------------------------------- +#endif diff --git a/Repeater.txt b/Repeater.txt new file mode 100644 index 0000000..fc066f5 --- /dev/null +++ b/Repeater.txt @@ -0,0 +1,289 @@ +MMSSTV repeater mode + + 2001.9.11 JE3HHT Makoto Mori + Translated into English by JA7UDE Oba + +========== +Run MMSSTV as a repeater +========== +To run MMSSTV in the repeater mode, add "-r" option: + +MMSSTV.EXE -r + +While MMSSTV is running in the repeater mode, all the standard functions are still operational. Enjoy SSTV as you usually do. + + If you want to add your call sign and/or the time stamp to the beacon or replay pictures, use templates. You can specify various templates for these purposes. + + You can change the transmission mode of the replay picture in accordance with the mode of the received picture. Uncheck "Fixed mode" in the TX tab of the MMSSTV Setup Option. MMSSTV uses the same mode as the received picture. + + It is recommended to use Hilbert transform for the FM demodulator for better image quality. Turn on or off "Auto stop," "Auto restart," and "Auto resync" options as you prefer. + + + +==================== +Introduction of the repeater function +==================== +MMSSTV repeater function works as follows: + +1. MMSSTV returns CW ID after receiving a tone signal for a while. The default frequency of the tone is 1750Hz. +2. When MMSSTV starts receiving a picture in the specified time (default is 10 seconds) after the CW ID, it receives and resends the picture. +3. MMSSTV optionally sends a beacon picture periodically. + +MMSSTV keeps watch on the squelch status before starting the TX operation. When the squelch is open, MMSSTV will not start TX. Refer to Squelch section of this document for more details. + + + +================== +Setup repeater options +================== +Click on "Option" and select "Setup repeater" to open the repeater setup window. + +If you have changed the following options, you must push the OK button to make them into effect. + +[Enabled] + Check this box to enable the MMSSTV repeater function. + +[SQ level] + This specifies the squelch level of the auto-correlator. When the output level of the auto-correlator exceeds this threshold, MMSSTV does not start TX. If you put 0 to SQ level, the auto-correlator is turned off and MMSSTV will start TX irrespective of the RX signals. THIS IS NOT RECOMMENDED, HOWEVER. + + Debug pane displays the output level of the auto-correlator. Seeing the pane, put an appropriate value, which should be slightly higher than the noise level, to the SQ level box. It should be noted that MMSSTV never starts TX when it is receiving a picture. The auto-correlator will not work while MMSSTV is receiving a picture. + + +[Answer] +Put the CW ID, which MMSSTV transmits in response to the tone signal received, to this box. The frequency and speed of the CW ID are specified in the MMSSTV Setup window. + +[Tone] + Tone frequency for accessing the repeater. The default is 1750Hz, but you have to use a different frequency if you have another repeater on the same channel. The tone frequency is displayed as a dotted line in the spectrum window. + +[Tone det.] + Tone detection time (msec). To access the repeater, you have to continuously transmit the access tone for at least the time period specified here. + +[Answer wait] + Wait time (msec) for CW ID. When MMSSTV detects an access tone, it waits for the time specified here and then starts transmitting the CW ID. + +[RX timeout] + Time out time for receiving a picture. If MMSSTV does not receive a picture before this timer expires, MMSSTV goes back to the tone waiting state. + +[Replay wait] + Wait to for the replay. MMSSTV waits for the time specified here after the completion of RX, and then it starts the replay TX operation. + +[Tone sensitivity] + Tone detection sensitivity. Highest is the most sensitive, Lower is the least sensitive. + +[Folder] + If you specify a folder name here, the TX pictures are automatically saved in the folder. The folder must pre-exist. The pictures are stored in the JPEG format. + +[Template No.] + Select the template numbers for replay and beacon pictures. Template number 0 inhibits the template loading. + + In the repeater mode, MMSSTV displays a small number at the top left corner of each picture in Stocked pictures and Stocked templates window. + + You can use multiple selections for Template No. In this case, MMSSTV uses the templates in the specified order. + + Example: 25,26,27 - Use Template 25, 26, 27, 25, 26, 27, .... + + For the beacon pictures, you can add # in front of the number to send the stocked picture of the same number, with the template superimposed. + + Example: 26,#27,26,#28 - 27 and 28 are sent with 27-th and 28-th pictures, respectively. + + If you do not add #, the beacon pictures are loaded from the latest four pictures in the history. + If you do not want to use a template, specify a number of any empty templates. + +[Beacon-Interval] + Beacon interval. "OFF" disables the beacon. The timer is reset if MMSSTV receives a picture. + +[Beacon-Silence time] + MMSSTV keeps watch on the frequency for the specified time before transmitting the beacon. + +[Beacon-SSTV MODE] + SSTV mode for the beacon picture. + +[Beacon-Use image filter] + When the beacon pictures are composed from the latest four images in the history, you can use an image filter. The filter slightly degrades the image resolution, but it dissolves the folding error caused in the scale-down operation. + +[Beacon button] + Send the beacon immediately. + + +========== +Squelch +========== + Squelch works as follows: + +1. Cancel the CW ID response + If the squelch is not closed 10 seconds after the detection of the access tone, MMSSTV cancels the tone detection and will not transmit the CW ID. + +2. Cancel the replay picture + If the squelch is not closed 20 seconds after the picture received, MMSSTV will not replay the picture. + +3. Suspend the beacon + If the squelch is opened in the period of "Silence time," MMSSTV postpones the beacon transmission. In other words, MMSSTV does not send the beacon at least the band is continuously clear for "Silence time." + + The repeater would cause QRM. The beacon in particular is automatically transmitted without notice, and thus it is likely to cause QRM. Pay special attention to the squelch threshold (do not set it too high). + + +========== +Debug pane +========== +The debug pane displays the following values for supervising the repeater operation. + + +State: + 0 - Waiting for the access tone + 1 - Detected the access tone + 2 - Waiting for the CW ID transmission + 5 - Waiting for the picture receive + 6 - Receiving the replay picture + 8 - Waiting for the picture transmission + 10 - Transmitting the replay picture + +Ans: Number of CW ID transmitted +RX: Number of pictures received +TX: Number of pictures transmitted +Level: Output level of the auto-correlator +Beacon: Number of beacons transmitted and the beacon timer value + +73, Mako + +* +* +********** Japanese ************************************************* +MMSSTVのリピータ動作 + + 2001.9.11 JE3HHT Makoto.Mori + +========== +◎起動方法 +========== + MMSSTVは通常の起動方法ではリピータとして動作しないようになっています。リピータとして動作させるには、起動する際にオプション「-r」を付加しなければなりません。 + +MMSSTV.EXE -r + + リピータ動作時もMMSSTVの通常のセットアップはすべて有効です。あなたの好みの設定で運用してください。 + + リピータ動作時に送信するリプレイ画像やビーコン画像に、あなたのコールサインや受信タイムスタンプ等を入れたい場合は、テンプレートを利用して下さい。それぞれで使用するテンプレートを個別に複数指定することができます。 + また受信したSSTVモードでリプレイ画像を送信するには、MMSSTV設定画面の送信ページで「モード固定」のチェックを外します。 + 画像受信用のFM復調器は、可能ならば「ヒルベルト変換」を使用すると良いでしょう。「自動停止」、「自動再スタート」、「自動再同期」などはあなたの好みの状態に設定すると良いでしょう。 + + +==================== +◎リピータ動作の概要 +==================== + SSTVリピータは以下のプロトコルで働きます。 + +1.トーン信号(デフォルト1750Hz)を一定期間受信するとCWIDを返送します。 +2.CWID送信終了後、一定期間(デフォルト10秒)以内に画像の受信を開始 + すると、受信終了時にその画像を返送します。 +3.定期的にビーコン画像を送信することができます。 + + MMSSTVは自動運転中に送信動作に入る場合、スケルチの状態を監視します。もしスケルチが開いている場合、送信は保留または禁止されます。この動作の詳細についてはこのドキュメント内の「スケルチ」の項を参照して下さい。 + + +================== +◎リピータ設定画面 +================== + オプションメニューの「リピータ設定画面」を選択するとリピータ設定画面が開きます。 + + 以下の項目を設定変更した場合、「OK」ボタンを押した時点からその設定内容が有効になります。 + +[Enabled] + これにチェックを付けるとMMSSTVはリピータとして動作します。 + +[SQ level] + 自己相関器(Auto Correlator)によるスケルチの検出閾値を設定します。相関器の出力レベルが、ここで設定した値を超えた場合、何らかの信号が存在すると認識されて送信が禁止されます。例外値として0を設定すると、相関器はOFFになり送信が禁止されることはありません(この動作はお勧めできません)。 + + Debug枠に表示されるLevelが相関器の出力レベルを表しますので、あなたの受信環境でのノイズレベルよりも大きな値を設定して下さい。なお画像受信中は無条件に送信禁止状態になりますので相関器は働きません。 + +[Answer] + トーンを検出した際に返送するCWIDの文字列を設定します。CWIDのトーン周波数および送信速度は、MMSSTV設定画面のCWIDオプションの設定の影響を受けます。 + +[Tone] + リピータ起動トーンの周波数を選択します。通常は1750Hzを使いますが、同一周波数に他のリピータが存在する場合は異なる周波数を選択しなければなりません。なお設定したトーン周波数はスペクトラム表示画面に点線で表示されます。 + +[Tone det.] + トーン検出時間をms単位で設定します。少なくともこの値の期間、トーンは連続して受信されなければなりません。 + +[Answer wait] + トーン検出後、CWIDを送出するまでの最小ウエイト時間をms単位で設定します。 + +[RX timeout] + CWID送出後、リプレイ画像を受信するまでのタイムアウトをms単位で設定します。この時間を経過しても画像が受信できない場合、リピータはトーン待ち状態に戻ります。 + +[Replay wait] + 画像受信終了後、リプレイ画像を送信するまでの最小ウエイト時間をms単位で設定します。 + +[Tone sensitivity] + トーン検出の感度を設定します。「Highest」は最も感度が高く、「Lower」は感度が低くなります。 + +[Folder] + ここにフォルダ名を定義すると、リプレイ画像を送信する際に、その送信画像をそのフォルダに保存することができます。指定したフォルダは必ず存在しなければなりません。保存されるファイルは必ずJPEGフォーマットになります。 + +[Template No.] + リプレイ画像およびビーコン画像を送信する場合にロードするそれぞれのストックテンプレートの枠番号を設定します。この値を0に設定した場合、テンプレートのロードは行われません。 + 「-r」オプションを付加して起動された場合、MMSSTVはストック画像およびストックテンプレートの各枠の左上にその枠番号を表示しますので、その番号をそのまま指定すると良いでしょう。 + + それぞれの設定にはカンマで区切って複数の番号を指定することができます。この場合、MMSSTVは送信する度に、ロードするテンプレートを指定順に変更します。 + + e.g. 25,26,27 3つのテンプレートを循環させる + + またビーコンの設定については、番号の先頭に#を付けると、同じ枠番号に存在するストック画像から送信画像を同時にロードすることもできます。 + + e.g. 26,#27,26,#28 27,28は画像も同時にロード + + #を付けない場合、ビーコン時に送信する画像は、履歴に存在する最新の4画像から自動的に作成されます。 + テンプレートを使いたくない場合、空のストックテンプレート番号を指定して下さい。 + +[Beacon-Interval] + ビーコンを送信する時間間隔を設定します。OFFを選択するとビーコンの送信は行われません。なおビーコン送出用のタイマーは、画像受信状態になった場合は無条件にリトリガされます。 + +[Beacon-Silence time] + ビーコン送信前にバンドがクリアかどうかを監視する時間を分単位で設定します。 + +[Beacon-SSTV MODE] + ビーコンを送信する際に使用するSSTVモードを選択します。 + +[Beacon-Use image filter] + 履歴に存在する最新の4画像からビーコン画像を作成する際、伸縮処理で画像フィルタを使うかどうかを設定します。フィルタを使うと若干解像度を損ないますが、縮小による折り返し歪みが解消されます。 + +[Beacon]ボタン + 強制的にビーコンを送信します。 + + +========== +◎スケルチ +========== + スケルチの動作は以下の通りです。 + +1.応答CWID送信の無効化 + トーンの検出終了後10秒間スケルチが閉じない場合、そのトーン検出は無効になりCWIDの送信は行われません。 + +2.リプレイ画像送信の無効化 + 画像受信終了後20秒間スケルチが閉じない場合、リプレイ画像の送信は行われません。 + +3.ビーコンの保留 + ビーコン送信時刻以前の「Silence time」で設定される期間にスケルチが開くと、ビーコン送信時刻が延期されます。したがってビーコンは、少なくとも「Silence time」の期間バンドがクリアな状態を維持していなければ送信されないことになります。 + + リピータはQRMの原因になる場合があります。特にビーコンは手続きなしで送信されるために他者へ混信を与えがちです。ビーコンを使う場合は、スケルチの閾値にあまり大きな値を設定しないようにして下さい。 + + +========== +◎Debug枠 +========== + リピータ設定画面のDebug枠には、リピータ動作を監視するために以下の数値が表示されます。 + +State リピータ動作を管理する状態変数 + 0 - トーン待ち中 + 1 - トーン検出開始 + 2 - Answer CWID送信待ち中 + 5 - Replay画像受信待ち中 + 6 - Replay画像受信中 + 8 - Replay画像送信待ち中 + 10 - Replay画像送信中 + +Ans CWIDを送信した回数 +RX 画像を受信した回数 +TX リプレイ画像を送信した回数 +Level 相関器の出力レベル +Beacon ビーコンを送信した回数と現在のタイマ値 + +73, Mako diff --git a/RxView.cpp b/RxView.cpp new file mode 100644 index 0000000..b6c3fa8 --- /dev/null +++ b/RxView.cpp @@ -0,0 +1,205 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "ComLib.h" +#include "RxView.h" +#include "sstv.h" +#include "Main.h" +//--------------------------------------------------------------------------- +#pragma package(smart_init) +#pragma resource "*.dfm" +//--------------------------------------------------------------------------- +__fastcall TRxViewDlg::TRxViewDlg(TComponent* Owner) + : TForm(Owner) +{ + Font->Name = sys.m_WinFontName; + Font->Charset = sys.m_WinFontCharset; + m_DisEvent = 1; + pBitmap = NULL; + ClientWidth = 320; + ClientHeight = 256; + m_MaxX = ::GetSystemMetrics(SM_CXSCREEN); + m_MaxY = ::GetSystemMetrics(SM_CYSCREEN); + m_rc.Left = 0; + m_rc.Top = 0; + m_rc.Right = PBox->Width; + m_rc.Bottom = PBox->Height; + m_DisEvent = 0; + m_Mode = -1; + m_RF = -1; +} + +//--------------------------------------------------------------------------- +void __fastcall TRxViewDlg::SetViewPos(int &x, int &y, int w, int h, Graphics::TBitmap *pbmp) +{ + pBitmap = pbmp; + m_DisEvent++; + ClientWidth = w; + ClientHeight = h; + + if( y < 0 ){ + y = 0; + } + else if( y > (m_MaxY - Height) ){ + y = m_MaxY - Height; + } + if( x < 0 ){ + x = 0; + } + else if( x > (m_MaxX - Width) ){ + x = m_MaxX - Width; + } + Top = y; + Left = x; + + m_rc.Left = 0; + m_rc.Top = 0; + m_rc.Right = PBox->Width; + m_rc.Bottom = PBox->Height; + m_DisEvent--; +} + +//--------------------------------------------------------------------------- +void __fastcall TRxViewDlg::GetViewPos(int &x, int &y, int &w, int &h) +{ + y = Top; + x = Left; + w = ClientWidth; + h = ClientHeight; +} +//--------------------------------------------------------------------------- +void __fastcall TRxViewDlg::UpdateSyncTitle(double fq) +{ + char bf[128]; + char bbf[64]; + if( sys.m_SampFreq != fq ){ + sprintf(bbf, "%.2lfHz (%.2lf)", fq, (fq - sys.m_SampFreq)); + } + else { + sprintf(bbf, "%.2lfHz", fq); + } + sprintf(bf, "%s - %s", MsgEng ? "Sync Viewer" : "同期画面", bbf ); + Caption = bf; +} +//--------------------------------------------------------------------------- +void __fastcall TRxViewDlg::UpdateTitle(int mode, int rf) +{ + if( mode >= 0 ){ +// if( (mode != m_Mode) || (rf != m_RF) ){ + m_Mode = mode; + m_RF = rf; + char bf[128]; + sprintf(bf, "%s - %s", MsgEng ? "RX Viewer" : "受信画面", SSTVModeList[mode]); + if( rf ){ + strcat(bf, " (Rep)"); + } + else { + SYSTEMTIME tim = Mmsstv->m_StartTime; + if( Log.m_LogSet.m_TimeZone == 'I' ) UTCtoJST(&tim); + sprintf(&bf[strlen(bf)], " (%02u%02u)", tim.wHour, tim.wMinute); + } + Caption = bf; +// } + } + else { + m_Mode = -1; + m_RF = -1; + Caption = MsgEng ? "RX Viewer" : "受信画面"; + } +} +//--------------------------------------------------------------------------- +void __fastcall TRxViewDlg::PBoxPaint(TObject *Sender) +{ + if( pBitmap == NULL ) return; + + if( (pBitmap->Width == PBox->Width)&& + (pBitmap->Height == PBox->Height) + ){ + PBox->Canvas->Draw(0, 0, pBitmap); + } + else { + int Sop = ::SetStretchBltMode(PBox->Canvas->Handle, HALFTONE); + PBox->Canvas->StretchDraw(m_rc, (TGraphic*)pBitmap); + ::SetStretchBltMode(PBox->Canvas->Handle, Sop); + } +} +//--------------------------------------------------------------------------- +void __fastcall TRxViewDlg::FormResize(TObject *Sender) +{ + if( pBitmap == NULL ) return; + + if( (pBitmap->Width != PBox->Width)|| + (pBitmap->Height != PBox->Height) + ){ + if( m_DisEvent ) return; + m_DisEvent++; + if( ClientHeight < 100 ) ClientHeight = 100; + if( ClientWidth < 100 ) ClientWidth = 100; + + double XW = 320; + double YW = 256; + double xw = ClientWidth; + double yw = ClientHeight; + if( Width > m_MaxX ) xw = m_MaxX; + if( Height > m_MaxY ) yw = m_MaxY; + + double xv = (xw / Width) * XW; + double yv = (yw / Height) * YW; + if( yv < xv ){ + yw = xw * YW / XW; + } + else { + xw = yw * XW / YW; + } + if( ABS(xw - ClientWidth) >= 2 ) ClientWidth = xw; + if( ABS(yw - ClientHeight) >= 2 ) ClientHeight = yw; + m_DisEvent--; + } + m_rc.Left = 0; + m_rc.Top = 0; + m_rc.Right = PBox->Width; + m_rc.Bottom = PBox->Height; +} +//--------------------------------------------------------------------------- +void __fastcall TRxViewDlg::PBoxClick(TObject *Sender) +{ + ::SetWindowPos(Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); +} +//--------------------------------------------------------------------------- + + +void __fastcall TRxViewDlg::FormKeyDown(TObject *Sender, WORD &Key, + TShiftState Shift) +{ + Mmsstv->FormKeyDown(Sender, Key, Shift); +} +//--------------------------------------------------------------------------- + +void __fastcall TRxViewDlg::FormKeyUp(TObject *Sender, WORD &Key, + TShiftState Shift) +{ + Mmsstv->FormKeyUp(Sender, Key, Shift); +} +//--------------------------------------------------------------------------- + + diff --git a/RxView.dfm b/RxView.dfm new file mode 100644 index 0000000..208f1d8 Binary files /dev/null and b/RxView.dfm differ diff --git a/RxView.h b/RxView.h new file mode 100644 index 0000000..b132cfe --- /dev/null +++ b/RxView.h @@ -0,0 +1,60 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------------- +#ifndef RxViewH +#define RxViewH +//--------------------------------------------------------------------------- +#include +#include +#include +#include +#include +//--------------------------------------------------------------------------- +class TRxViewDlg : public TForm +{ +__published: // IDE 管理のコンポーネント + TPaintBox *PBox; + void __fastcall PBoxPaint(TObject *Sender); + void __fastcall FormResize(TObject *Sender); + void __fastcall PBoxClick(TObject *Sender); + + void __fastcall FormKeyDown(TObject *Sender, WORD &Key, + TShiftState Shift); + void __fastcall FormKeyUp(TObject *Sender, WORD &Key, + TShiftState Shift); +private: // ユーザー宣言 + Graphics::TBitmap *pBitmap; + TRect m_rc; + int m_MaxX; + int m_MaxY; + int m_DisEvent; + int m_Mode; + int m_RF; +public: // ユーザー宣言 + __fastcall TRxViewDlg(TComponent* Owner); + + void __fastcall SetViewPos(int &x, int &y, int w, int h, Graphics::TBitmap *pbmp); + void __fastcall GetViewPos(int &x, int &y, int &w, int &h); + void __fastcall UpdateSyncTitle(double fq); + void __fastcall UpdateTitle(int mode, int rf); +}; +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- +#endif diff --git a/Scope.cpp b/Scope.cpp new file mode 100644 index 0000000..d3cb502 --- /dev/null +++ b/Scope.cpp @@ -0,0 +1,365 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "Scope.h" +#include "Main.h" +//--------------------------------------------------------------------- +#pragma resource "*.dfm" +//TTScope *TScope; +static int m_XW = 2048; +static int m_XOFF = (8192 - m_XW)/2; +static int m_CursorX = m_XOFF+(m_XW/2); +static double m_Gain = 2.0; +//--------------------------------------------------------------------- +__fastcall TTScope::TTScope(TComponent* AOwner) + : TForm(AOwner) +{ + FormStyle = ((TForm *)AOwner)->FormStyle; + Font->Name = ((TForm *)AOwner)->Font->Name; + Font->Charset = ((TForm *)AOwner)->Font->Charset; + if( MsgEng ){ + Caption = "MMSSTV Digital Scope"; + OKBtn->Caption = "Close"; + SBUpDown->Caption = "+-"; + UpBtn->Caption = "+"; + DownBtn->Caption = "-"; + LeftBtn->Caption = "<-"; + RightBtn->Caption = "->"; + } + + pBitmap = new Graphics::TBitmap(); + pBitmap->Width = PaintBox->Width; + pBitmap->Height = PaintBox->Height; + + TRect rc; + rc.Top = 0; + rc.Bottom = pBitmap->Height; + rc.Left = 0; + rc.Right = pBitmap->Width; + pBitmap->Canvas->Brush->Color = clBlack; + pBitmap->Canvas->FillRect(rc); + + pDem = NULL; + pScope = NULL; +// m_XW = 2048; +// m_Gain = 1.0; +} +//--------------------------------------------------------------------- +__fastcall TTScope::~TTScope() +{ + delete pBitmap; +} +//--------------------------------------------------------------------- +void __fastcall TTScope::Execute(CSSTVDEM *pd) +{ + pDem = pd; + pScope = pd->m_Scope; + pScope[0].InitMem(); + pScope[1].InitMem(); + UpdateBtn(); + ShowModal(); +} + +void __fastcall TTScope::TrigNext(void) +{ + pDem->m_ScopeFlag = 0; + pScope[0].Collect(SCOPESIZE); + pScope[1].Collect(SCOPESIZE); + pDem->m_ScopeFlag = 1; +} + +#define GAGEWIDTH 5 + +void __fastcall TTScope::PaintPosition(void) +{ + TCanvas *pCanvas = pBitmap->Canvas; + + TRect rc; + rc.Top = 0; + rc.Bottom = GAGEWIDTH; + rc.Left = 0; + rc.Right = pBitmap->Width; + + pCanvas->Brush->Color = clBlack; + pCanvas->FillRect(rc); + + int xw = (m_XW * rc.Right) / pScope->m_ScopeSize; + int x = (m_XOFF * rc.Right) / pScope->m_ScopeSize; + int xc = (m_CursorX * rc.Right) / pScope->m_ScopeSize; + pCanvas->Brush->Color = clGreen; + rc.Left = x; + rc.Right = x + xw; + pCanvas->FillRect(rc); + + pCanvas->Pen->Color = clYellow; + pCanvas->Pen->Style = psSolid; + pCanvas->MoveTo(xc, rc.Top); + pCanvas->LineTo(xc, rc.Bottom); + + pCanvas->Font->Color = clWhite; + pCanvas->Font->Size = 8; + char bf[32]; + sprintf(bf, "Gain:%.1lf", m_Gain); + ::SetBkMode(pCanvas->Handle, TRANSPARENT); + pCanvas->TextOut(0, 0, bf); +} + +void __fastcall TTScope::PaintScope(CScope *sp, int n) +{ + TRect rc; + + int YW = (pBitmap->Height - GAGEWIDTH) / 2; + rc.Top = (YW * n) + GAGEWIDTH; + rc.Bottom = rc.Top + YW; + rc.Left = 0; + rc.Right = pBitmap->Width; + + TCanvas *pCanvas = pBitmap->Canvas; + + pCanvas->Brush->Color = clBlack; + pCanvas->FillRect(rc); + + if( !sp->GetFlag() ) return; + + if( n < 2 ){ + pCanvas->Pen->Color = clWhite; + pBitmap->Canvas->Pen->Style = psDot; + pCanvas->MoveTo(rc.Left, rc.Top + YW/2); + pCanvas->LineTo(rc.Right, rc.Top + YW/2); + } + + pCanvas->Pen->Color = clWhite; + pBitmap->Canvas->Pen->Style = psSolid; + double d; + int x, y, xx, xe; + for( x = 0; x < rc.Right; x++ ){ + xx = (x * m_XW / rc.Right) + m_XOFF; + xe = xx + (m_XW / rc.Right); + if( xe >= sp->m_ScopeSize ) xe = sp->m_ScopeSize - 1; + double *dp = &sp->pScopeData[xx]; + for( ; xx <= xe; xx++, dp++ ){ + d = *dp; + if( n < 1 ){ + y = rc.Bottom - int(d * YW * m_Gain/16384.0) - 1; + } + else { + y = rc.Bottom - int(d * YW * m_Gain/32768.0) - YW/2; + } + if( y < rc.Top ) y = rc.Top; + if( y > rc.Bottom ) y = rc.Bottom; + if( x ){ + pCanvas->LineTo(x, y); + } + else { + pCanvas->MoveTo(x, y); + } + } + } +} + +void __fastcall TTScope::PaintCursor(void) +{ + int x = (m_CursorX - m_XOFF) * PaintBox->Width / m_XW; + if( (x >= 0) && (x < PaintBox->Width) ){ + PaintBox->Canvas->Pen->Color = clLime; + PaintBox->Canvas->Pen->Style = psDot; + PaintBox->Canvas->MoveTo(x, 5); + PaintBox->Canvas->LineTo(x, pBitmap->Height - GAGEWIDTH - 5); + } +} + +void __fastcall TTScope::PaintBoxPaint(TObject *Sender) +{ + if( pDem == NULL ) return; + + PaintScope(pScope, 0); + PaintScope(pScope+1, 1); + PaintPosition(); + PaintBox->Canvas->Draw(0, 0, (TGraphic*)pBitmap); + PaintCursor(); +} +//--------------------------------------------------------------------------- +void __fastcall TTScope::TimerTimer(TObject *Sender) +{ + if( pDem == NULL ) return; + + if( pScope->GetFlag() ){ + PaintBoxPaint(NULL); + if( SBTrig->Down ){ + SBTrig->Down = FALSE; + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TTScope::SBTrigClick(TObject *Sender) +{ + TrigNext(); +} +//--------------------------------------------------------------------------- +void __fastcall TTScope::UpdateBtn(void) +{ + if( m_XW <= (pScope->m_ScopeSize - 512) ){ + SBUpW->Enabled = TRUE; + } + else { + SBUpW->Enabled = FALSE; + } + if( m_XW >= 64 ){ + SBDownW->Enabled = TRUE; + } + else { + SBDownW->Enabled = FALSE; + } + if( m_XOFF ){ + LeftBtn->Enabled = TRUE; + } + else { + LeftBtn->Enabled = FALSE; + } + if( (m_XOFF + m_XW) < pScope->m_ScopeSize ){ + RightBtn->Enabled = TRUE; + } + else { + RightBtn->Enabled = FALSE; + } +} +//--------------------------------------------------------------------------- +void __fastcall TTScope::LeftBtnClick(TObject *Sender) +{ + if( m_XOFF ){ + m_XOFF -= m_XW/4; + if( m_XOFF < 0 ) m_XOFF = 0; + } + UpdateBtn(); +} +//--------------------------------------------------------------------------- +void __fastcall TTScope::RightBtnClick(TObject *Sender) +{ + m_XOFF += m_XW/4; + if( (m_XOFF + m_XW) >= pScope->m_ScopeSize ){ + m_XOFF = pScope->m_ScopeSize - m_XW; + } + UpdateBtn(); +} +//--------------------------------------------------------------------------- +void __fastcall TTScope::AdjXoff(int x) +{ + if( (x >= 0) && (x < PaintBox->Width) ){ + int xoff = x * m_XW / PaintBox->Width + m_XOFF + 1; + m_XOFF += (m_CursorX - xoff); + if( m_XOFF < 0 ){ + m_XOFF = 0; + } + else if( (m_XOFF + m_XW) > pScope->m_ScopeSize ){ + m_XOFF = pScope->m_ScopeSize - m_XW; + } + } + else if( (m_XOFF + m_XW) > pScope->m_ScopeSize ){ + m_XOFF = pScope->m_ScopeSize - m_XW; + } +} +//--------------------------------------------------------------------------- +void __fastcall TTScope::SBDownWClick(TObject *Sender) +{ + int x = (m_CursorX - m_XOFF) * PaintBox->Width / m_XW; + if( m_XW >= 1024 ){ + m_XW -= 512; + AdjXoff(x); + PaintBoxPaint(NULL); + } + else if( m_XW >= 64 ){ + m_XW -= 32; + AdjXoff(x); + PaintBoxPaint(NULL); + } + UpdateBtn(); +} +//--------------------------------------------------------------------------- +void __fastcall TTScope::SBUpWClick(TObject *Sender) +{ + int x = (m_CursorX - m_XOFF) * PaintBox->Width / m_XW; + if( m_XW < 512 ){ + m_XW += 32; + AdjXoff(x); + PaintBoxPaint(NULL); + } + else if( m_XW <= (pScope->m_ScopeSize - 512) ){ + m_XW += 512; + AdjXoff(x); + PaintBoxPaint(NULL); + } + UpdateBtn(); +} +//--------------------------------------------------------------------------- +void __fastcall TTScope::UpBtnClick(TObject *Sender) +{ + m_Gain *= 1.2; + PaintBoxPaint(NULL); +} +//--------------------------------------------------------------------------- +void __fastcall TTScope::DownBtnClick(TObject *Sender) +{ + m_Gain /= 1.2; + PaintBoxPaint(NULL); +} +//--------------------------------------------------------------------------- +void __fastcall TTScope::PaintBoxMouseDown(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y) +{ + m_CursorX = (X * m_XW / pBitmap->Width) + m_XOFF; + PaintBox->Canvas->Draw(0, 0, (TGraphic*)pBitmap); + PaintCursor(); +} +//--------------------------------------------------------------------------- +void __fastcall TTScope::SBUpDownClick(TObject *Sender) +{ + int x; + double d, peak; + peak = 0; + double *dp = &pScope[1].pScopeData[m_XOFF]; + for( x = m_XOFF; x < (m_XOFF + m_XW); x++, dp++ ){ + d = fabs(*dp); + if( peak < d ) peak = d; + } + if( peak ){ + m_Gain = 16384.0 * 0.8 / peak; + } + PaintBoxPaint(NULL); +} +//--------------------------------------------------------------------------- +void __fastcall TTScope::SBSetClick(TObject *Sender) +{ + Mmsstv->KOMClick(NULL); +} +//--------------------------------------------------------------------------- +void __fastcall TTScope::SBPlayClick(TObject *Sender) +{ + if( Mmsstv->pSound->WaveFile.m_mode == 1 ){ + Mmsstv->KFPlayPosClick(NULL); + } + else { + Mmsstv->KFPlayClick(NULL); + } +} +//--------------------------------------------------------------------------- + diff --git a/Scope.dfm b/Scope.dfm new file mode 100644 index 0000000..e4c7218 Binary files /dev/null and b/Scope.dfm differ diff --git a/Scope.h b/Scope.h new file mode 100644 index 0000000..8d07f45 --- /dev/null +++ b/Scope.h @@ -0,0 +1,96 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//---------------------------------------------------------------------------- +#ifndef ScopeH +#define ScopeH +//---------------------------------------------------------------------------- +/* ja7ude 0428 */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//---------------------------------------------------------------------------- +#include "sstv.h" +class TTScope : public TForm +{ +__published: + TButton *OKBtn; + TPanel *Panel1; + TPaintBox *PaintBox; + TTimer *Timer; + TSpeedButton *SBTrig; + TButton *LeftBtn; + TButton *RightBtn; + TButton *UpBtn; + TButton *DownBtn; + TButton *SBDownW; + TButton *SBUpW; + TSpeedButton *SBSet; + TButton *SBUpDown; + TSpeedButton *SBPlay; + void __fastcall PaintBoxPaint(TObject *Sender); + void __fastcall TimerTimer(TObject *Sender); + void __fastcall SBTrigClick(TObject *Sender); + void __fastcall LeftBtnClick(TObject *Sender); + void __fastcall RightBtnClick(TObject *Sender); + void __fastcall UpBtnClick(TObject *Sender); + void __fastcall DownBtnClick(TObject *Sender); + + + void __fastcall SBDownWClick(TObject *Sender); + void __fastcall SBUpWClick(TObject *Sender); + + void __fastcall PaintBoxMouseDown(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + + void __fastcall SBUpDownClick(TObject *Sender); + + void __fastcall SBSetClick(TObject *Sender); + void __fastcall SBPlayClick(TObject *Sender); +private: + CSSTVDEM *pDem; + CScope *pScope; + + Graphics::TBitmap *pBitmap; + + void __fastcall UpdateBtn(void); + void __fastcall TrigNext(void); + void __fastcall PaintCursor(void); + void __fastcall AdjXoff(int x); + + +public: + virtual __fastcall TTScope(TComponent* AOwner); + virtual __fastcall ~TTScope(); + + void __fastcall Execute(CSSTVDEM *pd); + void __fastcall PaintPosition(void); + void __fastcall PaintScope(CScope *sp, int n); +}; +//---------------------------------------------------------------------------- +//extern TTScope *TScope; +//---------------------------------------------------------------------------- +#endif diff --git a/Sound.cpp b/Sound.cpp new file mode 100644 index 0000000..31f3f13 --- /dev/null +++ b/Sound.cpp @@ -0,0 +1,911 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------------- +#include //ja7ude 0521 +#pragma hdrstop + +#include + +#include "Sound.h" +#include "Main.h" +//--------------------------------------------------------------------------- +// 注意: VCL オブジェクトのメソッドとプロパティを使用するには, Synchronize +// を使ったメソッド呼び出しでなければなりません。次に例を示します。 +// +// Synchronize(UpdateCaption); +// +// ここで, UpdateCaption は次のように記述できます。 +// +// void __fastcall TSound::UpdateCaption() +// { +// Form1->Caption = "スレッドから書き換えました"; +// } +//--------------------------------------------------------------------------- +__fastcall TSound::TSound(bool CreateSuspended) + : TThread(CreateSuspended) +{ + ::VirtualLock(this, sizeof(TSound)); + m_BuffSize = SampSize; + m_ReqFifoSize = 0; + m_FifoSizeRX = 12; + m_FifoSizeTX = 8; + m_Stop = TRUE; + + m_IDDevice = WAVE_MAPPER; + m_IDTXDevice = WAVE_MAPPER; + m_playmode = 0; + m_susp = 0; + m_suspack = 0; + + InitWFX(); + m_lms = 0; + m_lms_AN = 0; + m_notch = 0; + m_Tx = m_ReqTx = 0; + m_ReqSpeedTest = 0; + Wave.GetDeviceName(); +} + +__fastcall TSound::~TSound() +{ + ::VirtualUnlock(this, sizeof(TSound)); +} + +void __fastcall TSound::InitWFX(void) +{ + m_WFX.wFormatTag = WAVE_FORMAT_PCM; + m_WFX.nChannels = WORD(sys.m_SoundStereo ? 2 : 1); + m_WFX.wBitsPerSample = 16; + m_WFX.nSamplesPerSec = int(SampBase); + m_WFX.nBlockAlign = WORD(m_WFX.nChannels *(m_WFX.wBitsPerSample/8)); + m_WFX.nAvgBytesPerSec = m_WFX.nBlockAlign * m_WFX.nSamplesPerSec; + m_WFX.cbSize = 0; + Wave.m_SoundStereo = sys.m_SoundStereo; + Wave.m_StereoTX = sys.m_StereoTX; +} + +void __fastcall TSound::Stop(void) +{ + if( !m_Stop ){ + Priority = tpNormal; + Terminate(); +#if 0 + DWORD tim = GetTickCount(); + while( GetTickCount() < (tim + 1000) ){ // 1[s]のウエイト + if( m_Stop == TRUE ) break; + ::Sleep(0); + } +#else + WaitFor(); +#endif + } +} + +void __fastcall TSound::ReqStop(void) +{ + if( m_Stop == FALSE ){ + Priority = tpNormal; + Terminate(); + } +} + +void __fastcall TSound::WaitStop(void) +{ +#if 0 + DWORD tim = GetTickCount(); + while( GetTickCount() < (tim + 1000) ){ // 1[s]のウエイト + if( m_Stop == TRUE ) break; + ::Sleep(0); + } +#else + if( !m_Stop ) WaitFor(); +#endif +} + +void __fastcall TSound::InitSound(void) +{ + Suspend(); + InitWFX(); + m_ReqFifoSize = 1; + Resume(); +} +//--------------------------------------------------------------------------- +void __fastcall TSound::ErrorMsg(void) +{ + if( m_IDDevice == -2 ){ + InfoMB("Sound I/O failed in the MMW (%s)", sys.m_SoundMMW.c_str()); + } + else { + ErrorMB(MsgEng?"Can't open Sound card (%d)":"サウンドカードがオープンできません.", m_Tx ? m_IDTXDevice : m_IDDevice); + } +} +//--------------------------------------------------------------------------- +BOOL __fastcall TSound::ReInitSound(int sw) +{ + int r = TRUE; + if( Terminated == TRUE ) return r; + if( sw ){ + Wave.OutAbort(); + } + else { + Wave.InClose(); + } + InitWFX(); + if( sw ){ + if( Wave.OutOpen(&m_WFX, m_IDTXDevice, m_BuffSize) != TRUE ){ + ::Sleep(200); + if( Wave.OutOpen(&m_WFX, m_IDTXDevice, m_BuffSize) != TRUE ){ + r = FALSE; + } + } + } + else { + if( Wave.InOpen(&m_WFX, m_IDDevice, m_BuffSize) != TRUE ){ + ::Sleep(200); + if( Wave.InOpen(&m_WFX, m_IDDevice, m_BuffSize) != TRUE ){ + r = FALSE; + } + } + } + return r; +} + +void __fastcall TSound::TaskPriority(void) +{ + switch(sys.m_SoundPriority){ + case 0: + if( Priority != tpNormal ){ + Priority = tpNormal; //スレッドは通常の優先度である + } + break; + case 1: + if( Priority != tpHigher ){ + Priority = tpHigher; //スレッドの優先度は通常よりも 1 ポイント高い + } + break; + case 2: + if( Priority != tpHighest ){ + Priority = tpHighest; //スレッドの優先度は通常よりも 2 ポイント高い + } + break; + default: + if( Priority != tpTimeCritical ){ + Priority = tpTimeCritical; //スレッドはもっとも高い優先度を取得する + } + break; + } +} +//--------------------------------------------------------------------------- +void __fastcall TSound::SetDeviceID(void) +{ + LPSTR t, p; + AnsiString as = sys.m_SoundDevice.c_str(); + p = StrDlm(t, as.c_str()); + int dd; + if( ATOI(dd, t) ){ + m_IDDevice = dd; + } + else { + BOOL f = FALSE; + + int i; + for( i = 0; i < Wave.m_InDevs; i++ ){ + if( !strcmp(t, Wave.m_tInDevName[i].c_str()) ){ + m_IDDevice = i; + f = TRUE; + break; + } + } + if( !f ){ // MMW device + m_IDDevice = -2; + m_IDTXDevice = -2; + sys.m_SoundMMW = t; + return; + } + } + + if( *p ) StrDlm(t, p); + + if( ATOI(dd, t) ){ + m_IDTXDevice = dd; + } + else { + BOOL f = FALSE; + int i; + for( i = 0; i < Wave.m_OutDevs; i++ ){ + if( !strcmp(t, Wave.m_tOutDevName[i].c_str()) ){ + m_IDTXDevice = i; + f = TRUE; + break; + } + } + if( !f ){ + m_IDTXDevice = m_IDDevice; + } + } +} +//--------------------------------------------------------------------------- +int __fastcall TSound::UpdateFifoSize(void) +{ + int r = 2; + if( !m_ReqFifoSize ) return 1; + + int fi = Wave.IsInOpen(); + int fo = Wave.IsOutOpen(); + if( fi ) Wave.InClose(); + if( fo ) Wave.OutAbort(); + m_FifoSizeRX = sys.m_SoundFifoRX; + m_FifoSizeTX = sys.m_SoundFifoTX; + Wave.m_InFifoSize = m_FifoSizeRX; + Wave.m_OutFifoSize = m_FifoSizeTX; + + SetDeviceID(); + + Wave.UpdateDevice(m_IDDevice); + if( fi ){ + if( !Wave.InOpen(&m_WFX, m_IDDevice, m_BuffSize) ) r = FALSE; + } + if( fo ){ + if( !Wave.OutOpen(&m_WFX, m_IDTXDevice, m_BuffSize) ) r = FALSE; + } + TaskPriority(); + m_ReqFifoSize = 0; + return r; +} + +//--------------------------------------------------------------------------- +void __fastcall TSound::Execute() +{ + m_Stop = FALSE; + memset(Buff, 0, sizeof(Buff)); + TaskPriority(); + ::Sleep(200); // 200ms + Wave.m_InFifoSize = m_FifoSizeRX; + Wave.m_OutFifoSize = m_FifoSizeTX; + SetDeviceID(); + Wave.UpdateDevice(m_IDDevice); +_init:; + Wave.InClose(); + if( Wave.InOpen(&m_WFX, m_IDDevice, m_BuffSize) != TRUE ){ + int timeout = Wave.GetTimeout() / 200; + for( int i = 0; i < timeout; i++ ){ + ::Sleep(200); + if( Terminated == TRUE ) goto _ex; + if( UpdateFifoSize() == 2 ) goto _init; + if( Wave.InOpen(&m_WFX, m_IDDevice, m_BuffSize) == TRUE ) break; + } + if( Wave.IsInOpen() != TRUE ){ + if( timeout ) ErrorMsg(); + if( Terminated == TRUE ) goto _ex; + int Count = 3000/50; + while(1){ // 擬似実行 + if( Terminated == TRUE ) goto _ex; + ::Sleep(50); + Wave.PumpMessages(); + if( (m_Tx != m_ReqTx) || m_ReqFifoSize || !Count ){ + Count = 3000/50; + if( UpdateFifoSize() == 2 ) goto _init; + m_Tx = m_ReqTx; + if( m_Tx ){ + if( Wave.OutOpen(&m_WFX, m_IDTXDevice, m_BuffSize) == TRUE ) break; + } + else { + if( Wave.InOpen(&m_WFX, m_IDDevice, m_BuffSize) == TRUE ) break; + } + } + else if( m_susp ){ + JobSuspend(); break; + } + Count--; + } + m_Tx = 0; + } + } + m_Tx = 0; + Wave.OutAbort(); + double *lp; + int i; + while(1){ + if( Terminated == TRUE ) break; + if( Wave.IsInOpen() == TRUE ){ + if( Wave.InRead(Buff, m_BuffSize) == FALSE ){ + m_Err = 10; + SSTVDEM.m_Lost++; + if( !ReInitSound(0) ) goto _init; + } + } + if( m_playmode && (!m_Tx || (m_playmode != 1))) WaveFile.ReadWrite(Buff, m_BuffSize); + if( Terminated == TRUE ) break; + if( sys.m_TestDem ){ + for( i = 0, lp = Buff; i < m_BuffSize; i++, lp++ ){ + *lp = SSTVMOD.Do(); + } + } + if( !m_Tx || sys.m_echo ){ + if( m_lms || m_notch ){ + for( i = 0, lp = Buff; i < m_BuffSize; i++, lp++ ){ +#if VARITEST + *lp += ns.GetNoise(); +#endif + if( m_notch ) *lp = notch.Do(*lp); + if( m_lms ){ + if( m_lms_AN ){ + *lp = lms.DoN(*lp); + } + else { + *lp = lms.Do(*lp); + } + } + SSTVDEM.Do(*lp); + } + } + else { + for( i = 0, lp = Buff; i < m_BuffSize; i++, lp++ ){ +#if VARITEST + *lp += ns.GetNoise(); +#endif + SSTVDEM.Do(*lp); + } + } + } + fftIN.CollectFFT(Buff, m_BuffSize); +_skip1:; + if( m_Tx ){ + if( (sys.m_echo == 2) && Wave.IsInBufCritical() && Wave.IsInOpen() ) goto _skip2; + for( i = 0, lp = Buff; i < m_BuffSize; i++, lp++ ){ + *lp = SSTVMOD.Do(); + if( !sys.m_echo ) SSTVDEM.Idle(*lp); + } + } + if( Wave.IsOutOpen() == TRUE ){ + if( Wave.OutWrite(Buff, m_BuffSize) != TRUE ){ + m_Err = 10; + SSTVMOD.m_Lost++; + ReInitSound(1); + if( Wave.OutWrite(Buff, m_BuffSize) != TRUE ){ + if( !ReInitSound(1) ) goto _init; + } + } + if( (sys.m_echo == 2) && m_Tx && Wave.IsInBufNull() && !Wave.IsOutBufFull() ) goto _skip1; + } +_skip2:; + if( m_ReqFifoSize ){ + if( !UpdateFifoSize() ) goto _init; + } + if( m_Tx != m_ReqTx ){ + if( m_ReqTx ){ + if( sys.m_echo != 2 ){ + Wave.InClose(); + Mmsstv->InitFFT(); + fftIN.TrigFFT(); + SSTVDEM.m_lvl.Init(); + } + if( m_playmode != 1 ){ // 再生中でない時 + if( sys.m_echo == 2 ){ + switch(Priority){ // 優先順位を1つ上げる + case tpNormal: + Priority = tpHigher; + break; + case tpHigher: + Priority = tpHighest; + break; + case tpHighest: + Priority = tpTimeCritical; + break; + } + } + Wave.OutOpen(&m_WFX, m_IDTXDevice, m_BuffSize); + if( !Wave.IsOutOpen() ){ + m_susp = 2; + goto _susp; + } + if( sys.m_echo == 2 ){ // 最初のデータを溜める + for( int j = 0; (j < (m_FifoSizeTX - 1)) && !Wave.IsOutBufFull(); j++ ){ + for( i = 0, lp = Buff; i < m_BuffSize; i++, lp++ ){ + *lp = SSTVMOD.Do(); + } + if( Wave.OutWrite(Buff, m_BuffSize) != TRUE ){ + break; + } + } + } + } + SSTVDEM.m_OverFlow = 0; + SSTVMOD.m_Lost = 0; + SSTVDEM.m_Lost = 0; + m_Tx = m_ReqTx; + Wave.SetPTT(m_Tx); + } + else { + Wave.OutAbort(); + if( sys.m_echo != 2 ){ + Mmsstv->InitFFT(); + fftIN.TrigFFT(); + for( i = 0; i < SSTVDEM.m_bpftap; i++ ) SSTVDEM.Do(1); + SSTVDEM.m_OverFlow = 0; + SSTVDEM.m_lvl.Init(); + SSTVDEM.m_Lost = 0; + } + m_Tx = m_ReqTx; + Wave.SetPTT(m_Tx); + TaskPriority(); + if( !Wave.IsInOpen() ){ + Wave.InOpen(&m_WFX, m_IDDevice, m_BuffSize); + if( !Wave.IsInOpen() ){ + m_susp = 2; + goto _susp; + } + } + } + if( m_playmode == 1 ) m_playmode = 0; + } + if( (!m_Tx) && (WaveFile.m_mode != m_playmode) ){ + if( WaveFile.m_mode == 1 ){ + Wave.InClose(); + Wave.OutOpen(&m_WFX, m_IDTXDevice, m_BuffSize); + SSTVDEM.m_OverFlow = 0; + } + else if( m_playmode == 1 ){ + Wave.OutClose(); + Wave.InOpen(&m_WFX, m_IDDevice, m_BuffSize); + SSTVDEM.m_OverFlow = 0; + } + m_playmode = WaveFile.m_mode; + } +_susp:; + if( m_susp ){ + JobSuspend(); + } + if( m_ReqSpeedTest ){ + JobSpeedTest(); + } + } +_ex:; + Wave.InClose(); + Wave.OutAbort(); + Wave.UpdateDevice(-1); + m_Stop = TRUE; +} +//--------------------------------------------------------------------------- +void __fastcall TSound::JobSuspend(void) +{ + Wave.InClose(); + Wave.OutAbort(); + m_suspack = 1; + Priority = tpNormal; + while(1){ + if( Terminated == TRUE ){ + m_Stop = TRUE; + return; + } + if( m_Tx != m_ReqTx ){ + m_Tx = m_ReqTx; + if( m_Tx && (m_susp == 2) ){ + m_susp = 0; + } + } + Sleep(100); + Wave.PumpMessages(); + if( !m_susp ){ + UpdateFifoSize(); + for( int i = 0; i < 5; i++ ){ + if( m_Tx ){ + if( Wave.OutOpen(&m_WFX, m_IDTXDevice, m_BuffSize) == TRUE ) break; + } + else { + if( Wave.InOpen(&m_WFX, m_IDDevice, m_BuffSize) == TRUE ) break; + } + ::Sleep(100); + Wave.PumpMessages(); + } + if( !m_Tx && Wave.IsInOpen() ){ + m_suspack = 1; + break; + } + else if( m_Tx && Wave.IsOutOpen() ){ + m_suspack = 1; + break; + } + else { + m_susp = 2; + m_suspack = 1; + ErrorMsg(); + } + } + } + TaskPriority(); + if( m_Tx ){ + Wave.OutAbort(); + m_Tx = 0; + } + m_playmode = 0; + DisPaint = FALSE; +} + +//--------------------------------------------------------------------------- +int __fastcall TSound::IsBusy() +{ + if( Wave.IsInOpen() && Wave.IsInBufCritical() ) return TRUE; + if( Wave.IsOutOpen() && Wave.IsOutBufCritical() ) return TRUE; + return FALSE; +} +//--------------------------------------------------------------------------- +void __fastcall TSound::JobSpeedTest() +{ + DWORD tc = ::GetTickCount(); + SSTVMOD.InitTXBuf(); + SSTVDEM.Stop(); + for( int i = 0; i < 2000000; i++ ){ + SSTVMOD.Do(); + SSTVDEM.Do(0); + } + m_SpeedValue = ::GetTickCount() - tc; + m_ReqSpeedTest = 0; +} +//--------------------------------------------------------------------------- +// CWaveFileクラス +void __fastcall CWaveFile::ReadWrite(double *s, int size) +{ + SHORT d; + + if( m_Handle != NULL ){ + if( m_mode == 2 ){ // 書きこみ + if( !m_pause ){ + for( ; size; s++, size-- ){ + d = SHORT(*s); + if( mmioWrite(m_Handle, (const char*)&d, 2) != 2 ){ + mmioClose(m_Handle, 0); + m_Handle = 0; + m_mode = 0; + break; + } + else { + m_pos += 2; + } + } + } + } + else { // 読み出し + if( m_pause || m_dis ){ + memset(s, 0, sizeof(double)*size); + } + else { + for( ; size; s++, size-- ){ + if( mmioRead(m_Handle, (char *)&d, 2) == 2 ){ + *s = d; + m_pos += 2; + } + else if( m_autopause ){ + m_pause = 1; + break; + } + else { + mmioClose(m_Handle, 0); + m_Handle = 0; + m_mode = 0; + break; + } + } + for( ; size; s++, size-- ){ + *s = 0; + } + } + } + } +} + +__fastcall CWaveFile::CWaveFile() +{ + m_mode = 0; + m_pause = 0; + m_Handle = NULL; + m_dis = 0; + m_autopause = 0; +} + +__fastcall CWaveFile::~CWaveFile() +{ + FileClose(); +} + +void __fastcall CWaveFile::FileClose(void) +{ + m_mode = 0; + m_pause = 0; + if( m_Handle != NULL ){ + mmioClose(m_Handle, 0); + m_Handle = 0; + } +} + +void __fastcall CWaveFile::Rec(LPCSTR pName) +{ + FileClose(); + m_FileName = pName; + m_Handle = mmioOpen(m_FileName.c_str(), NULL, MMIO_CREATE|MMIO_WRITE|MMIO_ALLOCBUF); + if( m_Handle == NULL ){ + ErrorMB( MsgEng?"Can't open '%s'":"'%s'を作成できません.", pName); + return; + } + m_Head[0] = 0x55; + m_Head[1] = 0xaa; + m_Head[2] = char(SampType); + m_Head[3] = 0; + mmioWrite(m_Handle, (const char *)m_Head, 4); + m_pos = 4; + m_mode = 2; + m_pause = 0; + m_dis = 0; +} + +BOOL __fastcall CWaveFile::Play(LPCSTR pName) +{ + FileClose(); + FILE *fp = fopen(pName, "rb"); + if( fp == NULL ){ + ErrorMB( MsgEng?"Can't open '%s'":"'%s'をオープンできません.", pName); + return FALSE; + } + m_length = filelength(fileno(fp)); + m_FileName = pName; + fclose(fp); + m_Handle = mmioOpen(m_FileName.c_str(), NULL, MMIO_READ|MMIO_ALLOCBUF); + if( m_Handle == NULL ){ + ErrorMB( MsgEng?"Can't open '%s'":"'%s'をオープンできません.", pName); + return FALSE; + } + m_pos = 0; + if( mmioRead(m_Handle, (char *)m_Head, 4) == 4 ){ + int type = 0; + if( (m_Head[0] == 0x55)&&(m_Head[1] == 0xaa) ){ + type = m_Head[2]; + m_pos = 4; + m_length -= 4; + } + if( type > 9 ) type = 0; + if( type != SampType ){ + if( YesNoMB( + MsgEng + ? "%s\r\n\r\nThis file has been recorded based on %uHz, play it with sampling conversion?" + : "%s\r\n\r\nこのファイルは %uHz ベースで記録されています. 周波数変換して再生しますか?", + m_FileName.c_str(), SampTable[type] ) == IDNO ){ + mmioClose(m_Handle, 0); + m_Handle = 0; + return TRUE; + } + else { + mmioClose(m_Handle, 0); + m_Handle = 0; + char bf[1024]; + strcpy(bf, pName); + SetEXT(bf, ""); + char wName[1024]; + sprintf(wName, "%s_%u.MMV", bf, int(SampBase)); + if( ChangeSampFreq(wName, pName, SampTable[type]) == TRUE ){ + Play(wName); + } + } + } + } + m_mode = 1; + m_pause = 0; + m_dis = 0; + return TRUE; +} + +int __fastcall CWaveFile::ChangeSampFreq(LPCSTR tName, LPCSTR pName, int sSamp) +{ + int rr = FALSE; + FILE *fp = fopen(pName, "rb"); + if( fp != NULL ){ + CWaitCursor w; + BYTE head[4]; + memset(head, 0, sizeof(head)); + head[0] = 0x55; + head[1] = 0xaa; + head[2] = char(SampType); + head[3] = 0; + FILE *wfp = fopen(tName, "wb"); + if( wfp != NULL ){ + fwrite(head, 1, 4, wfp); + + int rsize = 16384; + int wsize = rsize * SampBase/double(sSamp); + short *rp = new short[rsize]; + short *wp = new short[wsize]; + short *ip = new short[rsize*4]; + CIIR riir; + riir.MakeIIR(2800, sSamp*4, 8, 1, 0.3); + CIIR wiir; + wiir.MakeIIR(2800, SampBase, 16, 1, 0.3); + int rlen, wlen; + short *sp, *tp; + int i, r; + double k; + while(1){ + rlen = fread(rp, 1, rsize * 2, fp); + if( !rlen ) break; + rlen /= 2; + if( SampBase < sSamp ){ // デシメーション + sp = rp; + tp = ip; + for( i = 0; i < rlen; i++, sp++ ){ // 一旦4倍にする + *tp++ = riir.Do(*sp); + *tp++ = riir.Do(*sp); + *tp++ = riir.Do(*sp); + *tp++ = riir.Do(*sp); + } + k = double(sSamp*4) / double(SampBase); + tp = wp; + wlen = rlen * SampBase / sSamp; + if( wlen > wsize ) wlen = wsize; + for( i = 0; i < wlen; i++ ){ + r = int((double(i) * k) + 0.5); + if( r >= (rlen*4) ) r = (rlen*4) - 1; + *tp++ = wiir.Do(ip[r]); + } + } + else { + k = double(sSamp) / double(SampBase); + tp = wp; + wlen = rlen * SampBase / sSamp; + if( wlen > wsize ) wlen = wsize; + for( i = 0; i < wlen; i++ ){ + r = int((double(i) * k) + 0.5); + if( r >= rlen ) r = rlen - 1; + *tp++ = wiir.Do(rp[r]); + } + } + if( fwrite(wp, 1, wlen * 2, wfp) != size_t(wlen * 2) ) break; + } + if( !fclose(wfp) ) rr = TRUE; + delete rp; + delete wp; + } + fclose(fp); + } + return rr; +} + +void __fastcall CWaveFile::Rewind(void) +{ + if( m_Handle != NULL ){ + m_dis++; + if( m_mode == 2 ){ + mmioSeek(m_Handle, 4, SEEK_SET); + m_pos = 4; + } + else { + mmioSeek(m_Handle, 0, SEEK_SET); + m_pos = 0; + } + m_dis--; + } +} + +void __fastcall CWaveFile::Seek(int n) +{ + if( m_Handle != NULL ){ + m_dis++; + if( (m_Head[0] == 0x55)&&(m_Head[1] == 0xaa) ){ + mmioSeek(m_Handle, n + 4, SEEK_SET); + m_pos = n + 4; + } + else { + mmioSeek(m_Handle, n, SEEK_SET); + m_pos = n; + } + m_dis--; + } +} + +long __fastcall CWaveFile::GetPos(void) +{ + if( (m_Head[0] == 0x55)&&(m_Head[1] == 0xaa) ){ + long n = m_pos - 4; + if( n < 0 ) n = 0; + return n; + } + else { + return m_pos; + } +} + +//--------------------------------------------------------------------------- +// CWaveStrageクラス + +__fastcall CWaveStrage::CWaveStrage() +{ + m_Handle = NULL; + + m_pos = m_rpos = m_wpos = 0; + pData = pSync = NULL; +} + +void __fastcall CWaveStrage::Close(void) +{ + if( m_Handle != NULL ){ + mmioClose(m_Handle, 0); + m_Handle = 0; + unlink(m_FileName.c_str()); + } + if( pData != NULL ){ + delete pData; + pData = NULL; + } + if( pSync != NULL ){ + delete pSync; + pSync = NULL; + } +} + +void __fastcall CWaveStrage::Open(void) +{ + Close(); + char bf[256]; + sprintf(bf, "%sSound.tmp", BgnDir); + m_FileName = bf; + m_Handle = mmioOpen(bf, NULL, MMIO_READWRITE|MMIO_CREATE|MMIO_ALLOCBUF); + m_wpos = m_rpos = m_pos = 0; + pData = new short[1400*SampFreq/1000]; + pSync = new short[1400*SampFreq/1000]; +} + +void __fastcall CWaveStrage::RInit(void) +{ + m_rpos = 0; +} + +void __fastcall CWaveStrage::WInit(void) +{ + m_wpos = 0; +} + +void __fastcall CWaveStrage::Seek(int n) +{ + mmioSeek(m_Handle, n, SEEK_SET); + m_pos = n; +} + +void __fastcall CWaveStrage::Read(short *sp, int size) +{ + if( m_pos != m_rpos ){ + Seek(m_rpos); + } + mmioRead(m_Handle, (char *)sp, size); + m_rpos += size; + m_pos = m_rpos; +} + +void __fastcall CWaveStrage::Write(short *sp, int size) +{ + if( m_pos != m_wpos ){ + Seek(m_wpos); + } + mmioWrite(m_Handle, (char *)sp, size); + m_wpos += size; + m_pos = m_wpos; +} + + + + + + diff --git a/Sound.h b/Sound.h new file mode 100644 index 0000000..0a9485e --- /dev/null +++ b/Sound.h @@ -0,0 +1,176 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------------- +#ifndef FilterH +#define FilterH +//--------------------------------------------------------------------------- +#include //JA7UDE 0428 + +#include "Wave.h" +#include "fft.h" +#include "sstv.h" +//--------------------------------------------------------------------------- +class CWaveFile +{ +private: + HMMIO m_Handle; + int m_dis; + BYTE m_Head[4]; +public: + long m_length; + long m_pos; + int m_mode; + int m_pause; + int m_autopause; + AnsiString m_FileName; + + __fastcall CWaveFile(); + __fastcall ~CWaveFile(); + void __fastcall FileClose(void); + void __fastcall Rec(LPCSTR pName); + BOOL __fastcall Play(LPCSTR pName); + void __fastcall Rewind(void); + void __fastcall ReadWrite(double *s, int size); + long __fastcall GetPos(void); + void __fastcall Seek(int n); + int __fastcall ChangeSampFreq(LPCSTR tName, LPCSTR pName, int sSamp); +}; + + +class TSound : public TThread +{ +private: + BOOL m_Stop; + WAVEFORMATEX m_WFX; + + double Buff[8192]; + + void __fastcall ErrorMsg(void); + double __fastcall GetScopeRange(double &low, double center, double shift); + void __fastcall ReadWrite(double *s, int size); + + int __fastcall UpdateFifoSize(void); + void __fastcall JobSuspend(void); + BOOL __fastcall ReInitSound(int sw); +public: + CWave Wave; + +protected: + void __fastcall Execute(); + + +public: + __fastcall TSound(bool CreateSuspended); + __fastcall ~TSound(); + + void __fastcall SetDeviceID(void); + void __fastcall Stop(void); + void __fastcall ReqStop(void); + void __fastcall WaitStop(void); + void __fastcall TimingWait(void); + + void __fastcall InitSound(void); + void __fastcall SetTXRX(int sw); + + void __fastcall TaskPriority(void); + + int m_lms; + int m_lms_AN; + CLMS lms; +#if VARITEST + CNoise ns; +#endif + int m_notch; + CNotch notch; + CSSTVDEM SSTVDEM; + CSSTVMOD SSTVMOD; + + CWaveFile WaveFile; + + + void __fastcall FileClose(void); + void __fastcall Rec(LPCSTR pName); + void __fastcall Play(LPCSTR pName); + void __fastcall Rewind(void); + + void __fastcall InitWFX(void); + + //UINT m_IDDevice; //ja7ude 0525 + //UINT m_IDTXDevice; + int m_IDDevice; + int m_IDTXDevice; + + int m_playmode; + int m_susp; + int m_suspack; + + int m_Tx; + int m_ReqTx; + int m_ReqSpeedTest; + DWORD m_SpeedValue; + void __fastcall JobSpeedTest(); + + CFFT fftIN; + + int m_Err; + int m_BuffSize; + int m_FifoSizeRX; + int m_FifoSizeTX; + int m_ReqFifoSize; + inline int __fastcall GetOutCount(int sw){ + return (sw ? Wave.GetOutBCC() : Wave.GetOutBC()) * m_BuffSize; + } + inline void __fastcall TrigBCC(void){ + Wave.SetOutBCC(Wave.GetOutBC()); + } + inline int __fastcall GetBCC(void){ + return Wave.GetOutBCC(); + } + int __fastcall IsBusy(void); +}; + +//--------------------------------------------------------------------------- +class CWaveStrage +{ +private: + HMMIO m_Handle; + AnsiString m_FileName; + +public: + long m_pos; + long m_wpos; + long m_rpos; + short *pData; + short *pSync; + + __fastcall CWaveStrage(); + __fastcall ~CWaveStrage(){Close();}; + void __fastcall Close(void); + void __fastcall Open(void); + void __fastcall RInit(void); + void __fastcall WInit(void); + int __fastcall IsOpen(void){return m_Handle != NULL ? TRUE : FALSE;}; + void __fastcall Read(short *sp, int size); + void __fastcall Write(short *sp, int size); + void __fastcall Seek(int n); +}; +//--------------------------------------------------------------------------- +#endif + diff --git a/Stock/Current.bmp b/Stock/Current.bmp new file mode 100644 index 0000000..edb928c Binary files /dev/null and b/Stock/Current.bmp differ diff --git a/Stock/Current.mtm b/Stock/Current.mtm new file mode 100644 index 0000000..c4ab73a Binary files /dev/null and b/Stock/Current.mtm differ diff --git a/Stock/List.mtm b/Stock/List.mtm new file mode 100644 index 0000000..940a4be Binary files /dev/null and b/Stock/List.mtm differ diff --git a/Stock/t1.mtm b/Stock/t1.mtm new file mode 100644 index 0000000..5c15d41 Binary files /dev/null and b/Stock/t1.mtm differ diff --git a/Stock/t2.mtm b/Stock/t2.mtm new file mode 100644 index 0000000..fce136f Binary files /dev/null and b/Stock/t2.mtm differ diff --git a/Stock/t3.mtm b/Stock/t3.mtm new file mode 100644 index 0000000..ff97914 Binary files /dev/null and b/Stock/t3.mtm differ diff --git a/Stock/t4.mtm b/Stock/t4.mtm new file mode 100644 index 0000000..886d8e0 Binary files /dev/null and b/Stock/t4.mtm differ diff --git a/Stock/t5.mtm b/Stock/t5.mtm new file mode 100644 index 0000000..f66921f Binary files /dev/null and b/Stock/t5.mtm differ diff --git a/StockVew.cpp b/StockVew.cpp new file mode 100644 index 0000000..c5b81ab --- /dev/null +++ b/StockVew.cpp @@ -0,0 +1,68 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "StockVew.h" +#include "Main.h" +//--------------------------------------------------------------------------- +#pragma package(smart_init) +#pragma resource "*.dfm" +//TStockView *StockView; +//--------------------------------------------------------------------------- +__fastcall TStockView::TStockView(TComponent* Owner) + : TForm(Owner) +{ + Font->Name = ((TForm *)Owner)->Font->Name; + Font->Charset = ((TForm *)Owner)->Font->Charset; +} +//--------------------------------------------------------------------------- +void __fastcall TStockView::FormResize(TObject *Sender) +{ + if( Visible ){ + if( this == Mmsstv->pStockView ){ + Mmsstv->AdjustStockView(); + } + else { + AlignList.NewAlign(this); + Mmsstv->FormResize(NULL); + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TStockView::FormKeyDown(TObject *Sender, WORD &Key, + TShiftState Shift) +{ + Mmsstv->FormKeyDown(Sender, Key, Shift); +} +//--------------------------------------------------------------------------- +void __fastcall TStockView::FormKeyUp(TObject *Sender, WORD &Key, + TShiftState Shift) +{ + Mmsstv->FormKeyUp(Sender, Key, Shift); +} +//--------------------------------------------------------------------------- +void __fastcall TStockView::FormHide(TObject *Sender) +{ + if( Mmsstv->Timer->Enabled ) Mmsstv->KVSDClick(NULL); +} +//--------------------------------------------------------------------------- + diff --git a/StockVew.dfm b/StockVew.dfm new file mode 100644 index 0000000..b428f72 Binary files /dev/null and b/StockVew.dfm differ diff --git a/StockVew.h b/StockVew.h new file mode 100644 index 0000000..9948f9f --- /dev/null +++ b/StockVew.h @@ -0,0 +1,65 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------------- +#ifndef StockVewH +#define StockVewH +//--------------------------------------------------------------------------- +#include +#include +#include +#include +//--------------------------------------------------------------------------- +#include "ComLib.h" +//--------------------------------------------------------------------------- +class TStockView : public TForm +{ +__published: // IDE 管理のコンポーネント + void __fastcall FormResize(TObject *Sender); + + void __fastcall FormKeyDown(TObject *Sender, WORD &Key, + TShiftState Shift); + void __fastcall FormKeyUp(TObject *Sender, WORD &Key, + TShiftState Shift); + + + void __fastcall FormHide(TObject *Sender); +private: // ユーザー宣言 +public: // ユーザー宣言 + __fastcall TStockView(TComponent* Owner); + + void __fastcall GetViewPos(int &x, int &y, int &w, int &h){ + x = Left; + y = Top; + w = ClientWidth; + h = ClientHeight; + }; + void __fastcall SetViewPos(int x, int y, int w, int h){ + Left = x; + Top = y; + ClientWidth = w; + ClientHeight = h; + }; + + CAlignList AlignList; +}; +//--------------------------------------------------------------------------- +//extern PACKAGE TStockView *StockView; +//--------------------------------------------------------------------------- +#endif diff --git a/TEMP.MDT b/TEMP.MDT new file mode 100644 index 0000000..e8d15f3 Binary files /dev/null and b/TEMP.MDT differ diff --git a/TEMP_BAK.MDT b/TEMP_BAK.MDT new file mode 100644 index 0000000..e8d15f3 Binary files /dev/null and b/TEMP_BAK.MDT differ diff --git a/TH5Len.cpp b/TH5Len.cpp new file mode 100644 index 0000000..19ef081 --- /dev/null +++ b/TH5Len.cpp @@ -0,0 +1,62 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "TH5Len.h" +#include "ComLib.h" +#include "Hamlog5.h" +//--------------------------------------------------------------------- +#pragma resource "*.dfm" +//TTH5LenDlg *TH5LenDlg; +//--------------------------------------------------------------------- +__fastcall TTH5LenDlg::TTH5LenDlg(TComponent* AOwner) + : TForm(AOwner) +{ + Caption = MsgEng ? "Set fields length" : "フィールド長の設定"; +} +//--------------------------------------------------------------------- +int __fastcall TTH5LenDlg::Execute(void) +{ + UHis->Position = Log.m_LogSet.m_Hamlog5Len[8]; + UMy->Position = Log.m_LogSet.m_Hamlog5Len[9]; + UFreq->Position = Log.m_LogSet.m_Hamlog5Len[10]; + UMode->Position = Log.m_LogSet.m_Hamlog5Len[11]; + UName->Position = Log.m_LogSet.m_Hamlog5Len[12]; + UQTH->Position = Log.m_LogSet.m_Hamlog5Len[13]; + URem->Position = Log.m_LogSet.m_Hamlog5Len[14]; + if( ShowModal() == IDOK ){ + Log.m_LogSet.m_Hamlog5Len[8] = UHis->Position; + Log.m_LogSet.m_Hamlog5Len[9] = UMy->Position; + Log.m_LogSet.m_Hamlog5Len[10] = UFreq->Position; + Log.m_LogSet.m_Hamlog5Len[11] = UMode->Position; + Log.m_LogSet.m_Hamlog5Len[12] = UName->Position; + Log.m_LogSet.m_Hamlog5Len[13] = UQTH->Position; + Log.m_LogSet.m_Hamlog5Len[14] = URem->Position; + Log.m_LogSet.m_Hamlog5Len[15] = Log.m_LogSet.m_Hamlog5Len[14]; + return TRUE; + } + else { + return FALSE; + } +} +//--------------------------------------------------------------------- + diff --git a/TH5Len.dfm b/TH5Len.dfm new file mode 100644 index 0000000..6457467 Binary files /dev/null and b/TH5Len.dfm differ diff --git a/TH5Len.h b/TH5Len.h new file mode 100644 index 0000000..d04e4a4 --- /dev/null +++ b/TH5Len.h @@ -0,0 +1,71 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//---------------------------------------------------------------------------- +#ifndef OCBH +#define OCBH +//---------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//---------------------------------------------------------------------------- +class TTH5LenDlg : public TForm +{ +__published: + TButton *OKBtn; + TButton *CancelBtn; + TLabel *L1; + TLabel *L2; + TLabel *L3; + TLabel *L4; + TLabel *L5; + TLabel *L6; + TLabel *L7; + TEdit *EHis; + TEdit *EMy; + TEdit *EFreq; + TEdit *EMode; + TEdit *EName; + TEdit *EQTH; + TEdit *ERem; + TUpDown *UHis; + TUpDown *UMy; + TUpDown *UFreq; + TUpDown *UMode; + TUpDown *UName; + TUpDown *UQTH; + TUpDown *URem; +private: +public: + virtual __fastcall TTH5LenDlg(TComponent* AOwner); + + int __fastcall Execute(void); +}; +//---------------------------------------------------------------------------- +//extern PACKAGE TTH5LenDlg *TH5LenDlg; +//---------------------------------------------------------------------------- +#endif diff --git a/TextEdit.cpp b/TextEdit.cpp new file mode 100644 index 0000000..eb2e516 --- /dev/null +++ b/TextEdit.cpp @@ -0,0 +1,185 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "ComLib.h" +#include "TextEdit.h" +#include "Main.h" +//--------------------------------------------------------------------- +#pragma resource "*.dfm" +//TTextEditDlg *TextEditDlg; +//--------------------------------------------------------------------- +__fastcall TTextEditDlg::TTextEditDlg(TComponent* AOwner) + : TForm(AOwner) +{ + FormStyle = ((TForm *)AOwner)->FormStyle; + ap = NULL; + Memo->Font->Pitch = fpFixed; + EntryAlignControl(); + Font->Name = ((TForm *)AOwner)->Font->Name; + Font->Charset = ((TForm *)AOwner)->Font->Charset; + if( MsgEng ){ + CancelBtn->Caption = "Cancel"; + FontBtn->Caption = "Font"; + Memo->Font->Name = "Courier New"; + Memo->Font->Charset = 0; + } +} +//--------------------------------------------------------------------- +int __fastcall TTextEditDlg::Execute(AnsiString &as, int flag, LPCSTR pTitle /* = NULL*/) +{ + CWaitCursor tw; + ap = as.c_str(); + if( flag != TRUE ){ + OKBtn->Visible = FALSE; + CancelBtn->Caption = MsgEng ? "Close":"閉じる"; + Memo->ReadOnly = TRUE; + } + if( pTitle != NULL ){ + Caption = pTitle; + } + tw.Delete(); + MultProc(); + int r = ShowModal(); + if( r == IDOK ){ + if( Memo->Modified == FALSE ) return FALSE; + if( flag == TRUE ){ + as = Memo->Text; + } + return TRUE; + } + return FALSE; +} + +void __fastcall TTextEditDlg::FontBtnClick(TObject *Sender) +{ + FontDialog->Font->Assign(Memo->Font); + NormalWindow(this); + SetDisPaint(); + if( FontDialog->Execute() == TRUE ){ + CWaitCursor tw; + Memo->Font->Assign(FontDialog->Font); + Memo->Update(); + } + ResDisPaint(); + TopWindow(this); +} +//--------------------------------------------------------------------------- +// サイズ変更コントロールの登録 +void __fastcall TTextEditDlg::EntryAlignControl(void) +{ + RECT rc; + rc.left = 0; + rc.top = 0; + rc.right = 792-1; + rc.bottom = 572-1; + + AlignList.EntryControl(OKBtn, &rc, OKBtn->Font); + AlignList.EntryControl(CancelBtn, &rc, CancelBtn->Font); + AlignList.EntryControl(FontBtn, &rc, FontBtn->Font); + AlignList.EntryControl(Memo, &rc, Memo->Font); + + int CX = ::GetSystemMetrics(SM_CXFULLSCREEN); + int CY = ::GetSystemMetrics(SM_CYFULLSCREEN); +// int CX = ::GetSystemMetrics(SM_CXSCREEN); +// int CY = ::GetSystemMetrics(SM_CYSCREEN); + if( (CX < Width)||(CY < Height) ){ + Top = 0; + Left = 0; + Width = CX; + Height = CY; + } + FormCenter(this, CX, CY); + if( Owner != NULL ){ + WindowState = ((TForm *)Owner)->WindowState; + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextEditDlg::FormResize(TObject *Sender) +{ + CWaitCursor tw; + AlignList.NewAlign(this); +} +//--------------------------------------------------------------------------- +void __fastcall TTextEditDlg::FormPaint(TObject *Sender) +{ + if( ap == NULL ) return; + CWaitCursor tw; + Memo->Text = ap; + ap = NULL; + MultProc(); + Memo->Update(); +} +//--------------------------------------------------------------------------- +// テキストヘルプの表示 +void __fastcall ShowHelp(TForm *pForm, LPCSTR pName, int sw) +{ + char bf[2048]; + char Name[256]; + FILE *fp; + BOOL f = sw; + + sprintf(Name, "%s%s", BgnDir, pName); + CWaitCursor w; + if( (fp = fopen(Name, "rt"))!=NULL ){ + MultProc(); + if( sys.m_HelpNotePad ){ + fclose(fp); + sprintf( bf, "NOTEPAD.EXE %s", Name); + WinExec(bf, SW_SHOWDEFAULT); + } + else { + AnsiString in; + int n = 0; + while(!feof(fp)){ + if( fgets(bf, 2048, fp) != NULL ){ + ClipLF(bf); + if( (sw >= 0) && !memcmp(bf, "%%%Ja", 5) ){ + f = !sw; + } + else if( (sw < 0) || f ){ + in += bf; + in += "\r\n"; + n++; + if( !(n % 64) ) MultProc(); + } + } + } + fclose(fp); + MultProc(); + TTextEditDlg *Box = new TTextEditDlg(pForm); + Box->Execute(in, FALSE, pName); + delete Box; + } + } + else { + ErrorMB( MsgEng ? "'%s' was not found.\r\n\r\nProbably this file will be provided in the future." : "'%s'が見つかりません.", Name); + } +} +//--------------------------------------------------------------------------- +// テキストヘルプの表示 +void __fastcall ShowHelp(TForm *pForm, LPCSTR pName) +{ + ShowHelp(pForm, pName, -1); +} +//--------------------------------------------------------------------------- + diff --git a/TextEdit.dfm b/TextEdit.dfm new file mode 100644 index 0000000..d5fadf0 Binary files /dev/null and b/TextEdit.dfm differ diff --git a/TextEdit.h b/TextEdit.h new file mode 100644 index 0000000..9d5d615 --- /dev/null +++ b/TextEdit.h @@ -0,0 +1,77 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//---------------------------------------------------------------------------- +#ifndef TextEditH +#define TextEditH +#include +#include +#include +#include +//---------------------------------------------------------------------------- +/* JA7UDE 0428 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +*/ +enum TFontPitch { fpDefault, fpVariable, fpFixed }; //ja7ude 0521 +//---------------------------------------------------------------------------- +class TTextEditDlg : public TForm +{ +__published: + TButton *OKBtn; + TButton *CancelBtn; + TMemo *Memo; + TButton *FontBtn; + TFontDialog *FontDialog; + void __fastcall FontBtnClick(TObject *Sender); + void __fastcall FormResize(TObject *Sender); + + + + + void __fastcall FormPaint(TObject *Sender); + + +private: + int InitFlag; + LPCSTR ap; + + CAlignList AlignList; + void __fastcall EntryAlignControl(void); +public: + virtual __fastcall TTextEditDlg(TComponent* AOwner); + + int __fastcall Execute(AnsiString &as, int flag, LPCSTR pTitle = NULL); +}; +//---------------------------------------------------------------------------- +//extern TTextEditDlg *TextEditDlg; + +extern void __fastcall ShowHelp(TForm *pForm, LPCSTR pName); +extern void __fastcall ShowHelp(TForm *pForm, LPCSTR pName, int sw); +//---------------------------------------------------------------------------- +#endif diff --git a/TextIn.cpp b/TextIn.cpp new file mode 100644 index 0000000..65fec83 --- /dev/null +++ b/TextIn.cpp @@ -0,0 +1,924 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "TextIn.h" +#include "Main.h" +#include "MacroKey.h" +#include "ColorSet.h" +#include "BitMask.h" +#include "PerSpect.h" +//--------------------------------------------------------------------- +#pragma resource "*.dfm" +#define PARANAME "PARALIST.BIN" +//TTextInDlg *TextInDlg; +int DrawParaF = 0; +//--------------------------------------------------------------------- +__fastcall TTextInDlg::TTextInDlg(TComponent* AOwner) + : TForm(AOwner) +{ + m_DisEvent = 1; + FormStyle = ((TForm *)AOwner)->FormStyle; + Font->Name = ((TForm *)AOwner)->Font->Name; + Font->Charset = ((TForm *)AOwner)->Font->Charset; + m_pFontDialog = Mmsstv->FontDialog; + if( MsgEng ){ + Caption = "Text & Colors"; + CancelBtn->Caption = "Cancel"; + CmdBtn->Caption = "Macro"; + Ltext->Caption = "Text"; + GBEf->Caption = ""; + RGGrade->Caption = "Gradation"; + RGGrade->Items->Strings[0] = "NONE"; + RGGrade->Items->Strings[1] = "Horizontal"; + RGGrade->Items->Strings[2] = "Vertical"; + RGGrade->Items->Strings[3] = "Bitmap mask"; + RGShadow->Caption = "Shadow"; + RGShadow->Items->Strings[0] = "NONE"; + RGShadow->Items->Strings[1] = "Siege"; + RGShadow->Items->Strings[2] = "Shadow 1"; + RGShadow->Items->Strings[3] = "Shadow 2"; + RGShadow->Items->Strings[4] = "Shadow 3"; + RGShadow->Items->Strings[5] = "Shadow 4"; + RGShadow->Items->Strings[6] = "Shadow 5"; + RGShadow->Items->Strings[7] = "Shadow 6"; + TblBtn->Caption = "Components"; + MaskBtn->Caption = "Bitmap"; + if( Font->Charset == HANGEUL_CHARSET ){ + CBZero->Caption = "Slash zero (\xa8\xaa)"; + } + else { + CBZero->Caption = "Slash zero (リ)"; + } + LRot->Caption = "Rotation"; + CBRA->Caption = "Right justify"; + CBTF->Caption = "Perspective"; + GBP->Caption = "Style profiles"; + MemBtn->Caption = "Add"; + DelBtn->Caption = "Del"; + CBFont->Caption = "Save font"; + CBV->Caption = "Vert"; + FontBtn->Caption = "Font"; + FontBtn->Hint = "Choose font"; + SBFD->Hint = "Make the font smaller"; + SBFI->Hint = "Make the font bigger"; + SBB->Hint = "Bold"; + SBI->Hint = "Italic"; + SBMSG->Hint = "Show messages list"; + } + LineBtn->Caption = RGShadow->Items->Strings[1]; + TFBtn->Caption = CBTF->Caption; + EditText->Items->Clear(); + for( int i = 0; i < 16; i++ ){ + if( sys.m_TextList[i].IsEmpty() ) break; + EditText->Items->Add(sys.m_TextList[i]); + } + pBrushBitmap = new Graphics::TBitmap(); + AdjustBitmapFormat(pBrushBitmap); + pBrushBitmap->Width = 8; + pBrushBitmap->Height = 8; + pItem = NULL; + m_ReqChange = 0; + m_DropText = 0; + m_DropProfile = 0; + m_MouseHold = 0; + + if( !DrawParaF ){ + DrawParaF++; + char bf[256]; + sprintf(bf, "%s"PARANAME, StockDir); + if( IsFile(bf) ){ + MultProc(); + LoadTemplate(&DrawPara, bf, PBox->Canvas); + } + } + m_tSBF[0] = SBF1; + m_tSBF[1] = SBF2; + m_tSBF[2] = SBF3; + m_tSBF[3] = SBF4; + UpdateSBF(); + InitCMB(); + MultProc(); + Memo->Visible = FALSE; + ShowHint = WinNT; +} +//--------------------------------------------------------------------- +__fastcall TTextInDlg::~TTextInDlg() +{ + delete pBrushBitmap; +} +//--------------------------------------------------------------------- +void __fastcall TTextInDlg::UpdateBoxFont(void) +{ + BYTE cs; + switch(m_pFontDialog->Font->Charset){ + case SHIFTJIS_CHARSET: + case HANGEUL_CHARSET: + case CHINESEBIG5_CHARSET: // + case 134: // 簡略 + cs = m_pFontDialog->Font->Charset; + break; + default: + cs = Font->Charset; + break; + } + if( EditText->Font->Charset != cs ){ + EditText->Font->Charset = cs; + } + TFontStyles ts = m_pFontDialog->Font->Style; + m_Style = FontStyle2Code(ts); + SBB->Down = m_Style & FSBOLD; + SBI->Down = m_Style & FSITALIC; +} +//--------------------------------------------------------------------- +void __fastcall TTextInDlg::AddTextList(LPCSTR pStr) +{ + int i, j; + for( i = 0; i < 16; i++ ){ + if( !strcmp(sys.m_TextList[i].c_str(), pStr) ){ + break; + } + } + if( i ){ + if( i >= 16 ) i--; + for( j = i; j > 0; j-- ){ + sys.m_TextList[j] = sys.m_TextList[j-1].c_str(); + } + sys.m_TextList[0] = pStr; + } +} +//--------------------------------------------------------------------- +void __fastcall TTextInDlg::UpdateUI(void) +{ + int f = RGGrade->ItemIndex ? TRUE : FALSE; + if( RGGrade->ItemIndex == 3 ){ + f = FALSE; + PC1->Visible = f; + TblBtn->Enabled = f; + PC2->Visible = f; + PC3->Visible = f; + PC4->Visible = f; + MaskBtn->Enabled = TRUE; + } + else { + TblBtn->Enabled = f; + PC1->Visible = TRUE; + PC2->Visible = f; + PC3->Visible = f; + PC4->Visible = f; + MaskBtn->Enabled = FALSE; + } + PCS->Visible = RGShadow->ItemIndex; + PCB->Visible = RGShadow->ItemIndex >= 4 ? TRUE : FALSE; + OKBtn->Enabled = !EditText->Text.IsEmpty(); + TFBtn->Enabled = CBTF->Checked; + LineBtn->Enabled = (RGShadow->ItemIndex == 1)||(RGShadow->ItemIndex==6) ? TRUE : FALSE; + f = CBStack->Checked; + L1->Enabled = f; + L2->Enabled = f; + UDSX->Enabled = f; + UDSY->Enabled = f; + SEX->Enabled = f; + SEY->Enabled = f; + f = !CBV->Checked; + Rot->Enabled = f; + UDRot->Enabled = f; + UDV->Enabled = !f; + EV->Enabled = !f; + Memo->Visible = SBMSG->Down; + + MemBtn->Enabled = !CMBPro->Text.IsEmpty(); + DelBtn->Enabled = (!CMBPro->Text.IsEmpty()) && (CMBPro->Items->IndexOf(CMBPro->Text) >= 0); +} +//--------------------------------------------------------------------- +void __fastcall TTextInDlg::UpdateItem(CDrawText *pm, int fsw) +{ + m_DisEvent++; + if( fsw ){ + m_pFontDialog->Font->Assign(pm->pFont); + UpdateBoxFont(); + } + RGGrade->ItemIndex = pm->m_Grade; + RGShadow->ItemIndex = pm->m_Shadow; + CBZero->Checked = pm->m_Zero; + EditText->Text = pm->m_Text; + PC1->Color = pm->m_Col1; + PC2->Color = pm->m_Col2; + PC3->Color = pm->m_Col3; + PC4->Color = pm->m_Col4; + PCS->Color = pm->m_ColS; + PCB->Color = pm->m_ColB; +// Rot->Text = pItem->m_Rot; + UDRot->Position = SHORT(pm->m_Rot); + CBRA->Checked = pm->m_RightAdj; + CBTF->Checked = pm->m_PerSpect; + CBStack->Checked = pm->m_Stack; + UDSX->Position = char(pm->m_StackPara & 0x000000ff); + UDSY->Position = char((pm->m_StackPara>>8) & 0x000000ff); + CBV->Checked = pm->m_Vert; + UDV->Position = short(pm->m_VertH); + UpdateUI(); + if( pm->pBrushBitmap != NULL ){ + pBrushBitmap->Width = pm->pBrushBitmap->Width; + pBrushBitmap->Height = pm->pBrushBitmap->Height; + pBrushBitmap->Canvas->Draw(0, 0, pm->pBrushBitmap); + } + else { + MakeBitmapPtn(pBrushBitmap, 1024, 0, pm->m_Col1, clWhite); + } + m_DisEvent--; +} +//--------------------------------------------------------------------- +void __fastcall TTextInDlg::UpdatePara(CDrawText *pm) +{ + pm->m_Rot = UDRot->Position; + pm->m_Grade = RGGrade->ItemIndex; + pm->m_Shadow = RGShadow->ItemIndex; + pm->m_Zero = CBZero->Checked; + pm->m_Text = EditText->Text.IsEmpty() ? "TEXT" : AnsiString(EditText->Text).c_str(); //ja7ude 0521 + pm->m_Col1 = PC1->Color; + pm->m_Col2 = PC2->Color; + pm->m_Col3 = PC3->Color; + pm->m_Col4 = PC4->Color; + pm->m_ColS = PCS->Color; + pm->m_ColB = PCB->Color; + pm->m_Stack = CBStack->Checked; + pm->m_StackPara = UDSX->Position & 0x000000ff; + pm->m_StackPara |= (UDSY->Position << 8) & 0x0000ff00; + pm->pFont->Assign(m_pFontDialog->Font); + if( pm->m_Grade == 3 ){ + if( pm->pBrushBitmap != NULL ){ + delete pm->pBrushBitmap; + } + pm->pBrushBitmap = DupeBitmap(pBrushBitmap, -1); + } + else if( pItem->pBrushBitmap != NULL ){ + delete pItem->pBrushBitmap; + pItem->pBrushBitmap = NULL; + } + pm->m_RightAdj = CBRA->Checked; + pm->m_PerSpect = CBTF->Checked; + if( pm != &m_Text ){ + memcpy(&pm->m_sperspect, &m_Text.m_sperspect, sizeof(pm->m_sperspect)); + pm->m_LineWidth = m_Text.m_LineWidth; + pm->m_LineColor = m_Text.m_LineColor; + } + pm->m_Vert = CBV->Checked; + pm->m_VertH = UDV->Position; +} +//--------------------------------------------------------------------- +int __fastcall TTextInDlg::Execute(CDrawText *p) +{ + pItem = p; + + m_Text.Start(PBox->Canvas, 0, 0); // キャンバスのセット + m_Text.Copy(pItem, 0); +// m_Text.UpdateText(); + + MultProc(); + UpdateItem(pItem, TRUE); + UpdateBitmap(); + MultProc(); + m_DisEvent = 0; + int r = ShowModal(); + MultProc(); + if( Memo->Modified ) sys.m_Msg = Memo->Text; + if( r == IDOK ){ + if( EditText->Text.IsEmpty() ){ + return FALSE; + } + else { + UpdatePara(pItem); + AddTextList(pItem->m_Text.c_str()); + MultProc(); + return TRUE; + } + } + return FALSE; +} +//--------------------------------------------------------------------- +void __fastcall TTextInDlg::RBGradeClick(TObject *Sender) +{ + if( m_DisEvent ) return; + + UpdateUI(); + UpdateSample(); +} +//--------------------------------------------------------------------------- +void __fastcall TTextInDlg::PCClick(TObject *Sender) +{ + TPanel *tp = (TPanel *)Sender; + TColorDialog *pDialog = Mmsstv->ColorDialog; + InitCustomColor(pDialog); + AddCustomColor(pDialog, PC1->Color); + AddCustomColor(pDialog, PC2->Color); + AddCustomColor(pDialog, PC3->Color); + AddCustomColor(pDialog, PC4->Color); + AddCustomColor(pDialog, PCS->Color); + AddCustomColor(pDialog, PCB->Color); + AddCustomColor(pDialog, Mmsstv->DrawMain.m_TransCol); + pDialog->Color = tp->Color; + SetDisPaint(); + if( pDialog->Execute() == TRUE ){ + tp->Color = pDialog->Color; + if( (Sender == PC1)|| + (Sender == PC2)|| + (Sender == PC3)|| + (Sender == PC4) + ){ + if( (PC1->Color == PC2->Color) && (PC3->Color == PC4->Color) ){ + if( YesNoMB(MsgEng ? "Change to two colors gradation?" : "2色のグラデーションに変更しますか?" ) == IDYES ){ + PC2->Color = GetCol(PC1->Color, PC4->Color, 2, 4); + PC3->Color = GetCol(PC1->Color, PC4->Color, 3, 4); + } + } + } + UpdateSample(); + } + ResDisPaint(); +} +//--------------------------------------------------------------------------- + +void __fastcall TTextInDlg::FontBtnClick(TObject *Sender) +{ + m_pFontDialog->Font->Color = PC1->Color; + SetDisPaint(); + if( m_pFontDialog->Execute() == TRUE ){ + PC1->Color = m_pFontDialog->Font->Color; + UpdateSample(); + UpdateBoxFont(); + } + ResDisPaint(); +} +//--------------------------------------------------------------------------- + +void __fastcall TTextInDlg::CmdBtnClick(TObject *Sender) +{ + TMacroKeyDlg *pBox = new TMacroKeyDlg(this); + AnsiString as = EditText->Text; + if( pBox->Execute(as) > 0 ){ + HWND hWnd; + if( SBMSG->Down ){ + Memo->SetFocus(); + Memo->SelLength = 0; + hWnd = Memo->Handle; + } + else { + EditText->SetFocus(); + EditText->SelStart = strlen(AnsiString(EditText->Text).c_str()); //ja7ude 0521 + EditText->SelLength = 0; + hWnd = EditText->Handle; + } + for( LPCSTR p = as.c_str(); *p; p++ ){ + ::PostMessage(hWnd, WM_CHAR, *p, 0); + } +// m_ReqChange = 5; + } + delete pBox; +} +//--------------------------------------------------------------------------- +void __fastcall TTextInDlg::TblBtnClick(TObject *Sender) +{ + TColorSetDlg *pBox = new TColorSetDlg(this); + TColor col[4]; + col[0] = PC1->Color; + col[1] = PC2->Color; + col[2] = PC3->Color; + col[3] = PC4->Color; + if( pBox->Execute(col) == TRUE ){ + PC1->Color = col[0]; + PC2->Color = col[1]; + PC3->Color = col[2]; + PC4->Color = col[3]; + UpdateSample(); + } + delete pBox; +} +//--------------------------------------------------------------------------- +void __fastcall TTextInDlg::EditTextDropDown(TObject *Sender) +{ + m_DropText = 1; +} +//--------------------------------------------------------------------------- +void __fastcall TTextInDlg::EditTextKeyPress(TObject *Sender, char &Key) +{ + m_DropText = 0; +} +//--------------------------------------------------------------------------- +void __fastcall TTextInDlg::EditTextChange(TObject *Sender) +{ + UpdateUI(); + if( m_DropText ){ + UpdateSample(); + } + else { + m_ReqChange = 5; + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextInDlg::MaskBtnClick(TObject *Sender) +{ + TBitMaskDlg *pBox = new TBitMaskDlg(this); + pBox->Execute(pBrushBitmap, &m_Text); + delete pBox; + UpdateSample(); +} +//--------------------------------------------------------------------------- +void __fastcall TTextInDlg::TFBtnClick(TObject *Sender) +{ + m_Text.m_PerSpect = CBTF->Checked; + TPerSpectDlg *pBox = new TPerSpectDlg(this); + int r = pBox->Execute(&m_Text); + delete pBox; + if( r == TRUE ){ + CBTF->Checked = m_Text.m_PerSpect; + UpdateSample(); + } +} +//--------------------------------------------------------------------- +void __fastcall TTextInDlg::UpdateSample(void) +{ + UpdateBitmap(); + PBox->Invalidate(); + m_ReqChange = 0; + m_DropText = 0; +} +//--------------------------------------------------------------------- +void __fastcall TTextInDlg::UpdateBitmap(void) +{ + if( m_Text.pBitmap == NULL ) return; + + UpdatePara(&m_Text); + m_Text.UpdateText(); + MultProc(); +} +//--------------------------------------------------------------------------- +void __fastcall TTextInDlg::PBoxPaint(TObject *Sender) +{ +#if 0 + if( CBStack->Checked && (UDSX->Position || UDSY->Position) && (RGShadow->ItemIndex < 4) ){ + int ax = UDSX->Position; + int ay = UDSY->Position; + int m = ABS(ax); + if( ABS(ax) < ABS(ay) ) m = ABS(ay); + int i; + for( i = 0; i < m; i++ ){ + PBox->Canvas->Draw(i*ax/m, i*ay/m, m_Text.pBitmap); + } + } + else { + PBox->Canvas->Draw(0, 0, m_Text.pBitmap); + } +#else + PBox->Canvas->Draw(0, 0, m_Text.pBitmap); +#endif + if( m_MouseHold ){ + PBox->Canvas->Pen->Color = clBlue; + PBox->Canvas->MoveTo(0, m_MouseYC); + PBox->Canvas->LineTo(PBox->Width, m_MouseYC); + PBox->Canvas->MoveTo(m_MouseXC, 0); + PBox->Canvas->LineTo(m_MouseXC, PBox->Height); + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextInDlg::CBZeroClick(TObject *Sender) +{ + UpdateSample(); +} +//--------------------------------------------------------------------------- +void __fastcall TTextInDlg::TimerTimer(TObject *Sender) +{ + if( m_ReqChange ){ + m_ReqChange--; + if( !m_ReqChange ){ + UpdateSample(); + } + } +// MemBtn->Enabled = !CMBPro->Text.IsEmpty(); +// DelBtn->Enabled = MemBtn->Enabled; +} +//--------------------------------------------------------------------------- +void __fastcall TTextInDlg::LineBtnClick(TObject *Sender) +{ + if( RGShadow->ItemIndex == 6 ){ + m_Text.m_ColS = PCS->Color; + } + if( m_Text.CDraw::Edit() == TRUE ){ + if( RGShadow->ItemIndex !=6 ){ + PCS->Color = m_Text.m_ColS; + } + UpdateSample(); + } +} +//--------------------------------------------------------------------------- +/* + int d; + + sscanf(Rot->Text.c_str(), "%d", &d); + if( (d >= -360) && (d < 360) ){ + if( d < 0 ) d += 360; + pm->m_Rot = d; + } +*/ +void __fastcall TTextInDlg::UDRotClick(TObject *Sender, TUDBtnType Button) +{ + UpdateSample(); +} +//--------------------------------------------------------------------------- +void __fastcall TTextInDlg::InitCMB(void) +{ + CMBPro->Items->Clear(); + for( int i = 0; i < DrawPara.m_Cnt; i++ ){ + CDrawText *pt = (CDrawText *)DrawPara.pBase[i]; + CMBPro->Items->Add(pt->m_Text); + } + CMBPro->Text = MsgEng ? "Untitled" : "無題"; + CBFont->Checked = DrawPara.m_SX & 1; +} +//--------------------------------------------------------------------------- +void __fastcall TTextInDlg::SaveCMB(void) +{ + DrawPara.m_SX = CBFont->Checked; + char bf[256]; + sprintf(bf, "%s"PARANAME, StockDir); + SaveTemplate(&DrawPara, bf); + UpdateUI(); +} +//--------------------------------------------------------------------------- +void __fastcall TTextInDlg::MemBtnClick(TObject *Sender) +{ + CDrawText text; + text.Copy(&m_Text); + text.m_Text = CMBPro->Text.c_str(); + int f = 1; + for( int i = 0; i < DrawPara.m_Cnt; i++ ){ + CDrawText *pt = (CDrawText *)DrawPara.pBase[i]; + if( pt->m_Text == text.m_Text ){ + DrawPara.DeleteItem(pt); + f = 0; + break; + } + } + DrawPara.AddItemCopy(&text); + if( f ) CMBPro->Items->Add(CMBPro->Text); + SaveCMB(); +} +//--------------------------------------------------------------------------- +void __fastcall TTextInDlg::CMBProChange(TObject *Sender) +{ + if( m_DisEvent ) return; + if( !m_DropProfile ){ + UpdateUI(); + return; + } + m_DropProfile = 0; + + int i; + + for( i = 0; i < DrawPara.m_Cnt; i++ ){ + CDrawText *pt = (CDrawText *)DrawPara.pBase[i]; + if( pt->m_Text == CMBPro->Text ){ + AnsiString text = EditText->Text.c_str(); + memcpy(&m_Text.m_sperspect, &pt->m_sperspect, sizeof(pt->m_sperspect)); + m_Text.m_LineWidth = pt->m_LineWidth; + m_Text.m_LineColor = pt->m_LineColor; + UpdateItem(pt, CBFont->Checked); + EditText->Text = text.c_str(); + UpdateSample(); + break; + } + } + UpdateUI(); +} +//--------------------------------------------------------------------------- +void __fastcall TTextInDlg::DelBtnClick(TObject *Sender) +{ + for( int i = 0; i < DrawPara.m_Cnt; i++ ){ + CDrawText *pt = (CDrawText *)DrawPara.pBase[i]; + if( pt->m_Text == CMBPro->Text ){ + DrawPara.DeleteItem(pt); + InitCMB(); + SaveCMB(); + return; + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextInDlg::CMBProDropDown(TObject *Sender) +{ + m_DropProfile = 1; +} +//--------------------------------------------------------------------------- +void __fastcall TTextInDlg::CMBProKeyPress(TObject *Sender, char &Key) +{ + m_DropProfile = 0; +} +//--------------------------------------------------------------------------- +void __fastcall TTextInDlg::UDSXClick(TObject *Sender, TUDBtnType Button) +{ + RBGradeClick(NULL); +} +//--------------------------------------------------------------------------- +void __fastcall TTextInDlg::CBVClick(TObject *Sender) +{ + if( m_DisEvent ) return; + + if( CBV->Checked ){ + UDRot->Position = 0; + ClearCodeErr(); + } + UpdateUI(); + UpdateSample(); +} +//--------------------------------------------------------------------------- +void __fastcall TTextInDlg::CBFontClick(TObject *Sender) +{ + if( m_DisEvent ) return; + + if( CBFont->Checked ){ + m_DropProfile = 1; + CMBProChange(NULL); + } + SaveCMB(); +} +//--------------------------------------------------------------------------- +void __fastcall TTextInDlg::PBoxMouseDown(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + m_MouseHold = 0; + if( m_DisEvent ) return; + + m_DisEvent++; + if( Button == mbRight ){ + CBStack->Checked = !CBStack->Checked; + } + else { + CBStack->Checked = TRUE; + if( m_Text.pBitmap == NULL ) return; + m_MouseHold = TRUE; + int XW = m_Text.pBitmap->Width; + int YW = m_Text.pBitmap->Height; + m_MouseXC = XW/2; + m_MouseYC = YW/2; + X = m_MouseXC - X; + Y = m_MouseYC - Y; + X = X * 64 / XW; + UDSX->Position = short(X); + UDSY->Position = short(Y); + Screen->Cursor = crSizeAll; + } + m_DisEvent--; + RBGradeClick(NULL); +} +//--------------------------------------------------------------------------- +void __fastcall TTextInDlg::PBoxMouseMove(TObject *Sender, + TShiftState Shift, int X, int Y) +{ + if( m_MouseHold ){ + X = m_MouseXC - X; + Y = m_MouseYC - Y; + short UX = UDSX->Position; + short UY = UDSY->Position; + m_DisEvent++; + UDSX->Position = short(X); + UDSY->Position = short(Y); + m_DisEvent--; + if( (UX != UDSX->Position) || (UY != UDSY->Position) ){ + RBGradeClick(NULL); + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextInDlg::PBoxMouseUp(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( m_MouseHold ){ + m_MouseHold = 0; + PBox->Invalidate(); + } + Screen->Cursor = crDefault; +} +//--------------------------------------------------------------------------- +void __fastcall TTextInDlg::SBMSGClick(TObject *Sender) +{ + Memo->Visible = SBMSG->Down; + if( SBMSG->Down ){ + Memo->Text = sys.m_Msg; + Memo->Modified = FALSE; + Memo->SelLength = 0; + Memo->SetFocus(); + } + else { + if( Memo->Modified ){ + sys.m_Msg = Memo->Text; + Memo->Modified = FALSE; + } + EditText->SetFocus(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextInDlg::MemoDblClick(TObject *Sender) +{ + if( Memo->Lines->Count ){ + int e = Memo->SelStart; + LPCSTR p = AnsiString(Memo->Text).c_str(); //ja7ude 0521 + int n = 0; + for( int i = 0; i < e; i++, p++ ){ + if( *p == LF ) n++; + } + if( n > Memo->Lines->Count ) n = Memo->Lines->Count - 1; + EditText->Text = Memo->Lines->Strings[n]; + } + else { + EditText->Text = ""; + } + SBMSG->Down = FALSE; + SBMSGClick(NULL); + MultProc(); + UpdateSample(); +} +//--------------------------------------------------------------------------- + +void __fastcall TTextInDlg::FontBtnMouseDown(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( Button == mbRight ){ + InvFontCharset(m_pFontDialog->Font); + UpdateSample(); + UpdateBoxFont(); + } +} +//--------------------------------------------------------------------------- +// SBFのインデックスを得る +int __fastcall TTextInDlg::GetSBFIndex(TObject *Sender) +{ + for( int i = 0; i < 4; i++ ){ + if( Sender == m_tSBF[i] ) return i; + } + return 0; +} +//--------------------------------------------------------------------------- +// 登録フォントの呼び出し +void __fastcall TTextInDlg::SBFClick(TObject *Sender) +{ + int N = GetSBFIndex(Sender); + FONTDATA *pData = &sys.m_RegFont[N]; + if( !pData->m_Height ) return; + + m_pFontDialog->Font->Name = pData->m_Name; + m_pFontDialog->Font->Charset = pData->m_Charset; +// m_pFontDialog->Font->Height = pData->m_Height; + TFontStyles ts = Code2FontStyle(pData->m_Style); + m_pFontDialog->Font->Style = ts; + UpdateSample(); + UpdateBoxFont(); +} +//--------------------------------------------------------------------------- +// フォントの登録 +void __fastcall TTextInDlg::SBFMouseDown(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( Button == mbRight ){ + int N = GetSBFIndex(Sender); + m_pFontDialog->Font->Color = clBlack; + SetDisPaint(); + TFont *pBakFont = new TFont; + pBakFont->Assign(m_pFontDialog->Font); + if( m_pFontDialog->Execute() == TRUE ){ + FONTDATA *pData = &sys.m_RegFont[N]; + pData->m_Name = m_pFontDialog->Font->Name; + pData->m_Charset = m_pFontDialog->Font->Charset; + pData->m_Height = m_pFontDialog->Font->Height; + TFontStyles ts = m_pFontDialog->Font->Style; + pData->m_Style = FontStyle2Code(ts); + } + ResDisPaint(); + m_pFontDialog->Font->Assign(pBakFont); + delete pBakFont; + UpdateSBF(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextInDlg::UpdateSBF(void) +{ + AnsiString as; + FONTDATA *pData = sys.m_RegFont; + for( int i = 0; i < 4; i++, pData++ ){ + if( pData->m_Height ){ + as = pData->m_Name; + AddStyle(as, pData->m_Charset, pData->m_Style); + } + else { + as = MsgEng ? "Load registered font" : "登録フォントの読み出し"; + } + as += MsgEng ? " (Registration = Right button)" : " (登録=右ボタン)"; + TSpeedButton *pButton = m_tSBF[i]; + pButton->Hint = as; + pButton->Font->Color = pData->m_Height ? clBlack : clGrayText; + } +} +//--------------------------------------------------------------------------- +void __fastcall TTextInDlg::AddStyle(AnsiString &as, BYTE charset, DWORD style) +{ + switch(charset){ + case ANSI_CHARSET: + as += MsgEng ? "/ANSI" : "/欧文"; + break; + case SHIFTJIS_CHARSET: + as += MsgEng ? "/Japanese" : "/日本語"; + break; + case HANGEUL_CHARSET: + as += MsgEng ? "/Korean(Hangul)" : "/ハングル"; + break; + case CHINESEBIG5_CHARSET: // 台湾 + as += MsgEng ? "/Chinese" : "/中国語(台湾)"; + break; + case 134: // 中国語簡略 + as += MsgEng ? "/Chinese" : "/中国語(簡略)"; + break; + default: + break; + } + if( style & FSBOLD ) as += MsgEng ? "/Bold" : "/太字"; + if( style & FSITALIC ) as += MsgEng ? "/Italic" : "/斜体"; + if( style & FSUNDERLINE ) as += MsgEng ? "/UnderLine" : "/下線"; + if( style & FSSTRIKEOUT ) as += MsgEng ? "/StrikeOut" : "/取消し線"; +} +//--------------------------------------------------------------------------- +void __fastcall TTextInDlg::SBIClick(TObject *Sender) +{ + if( SBI->Down ){ + m_Style |= FSITALIC; + } + else { + m_Style &= ~FSITALIC; + } + TFontStyles ts; + ts = Code2FontStyle(m_Style); + m_pFontDialog->Font->Style = ts; + UpdateSample(); + UpdateBoxFont(); +} +//--------------------------------------------------------------------------- +void __fastcall TTextInDlg::SBBClick(TObject *Sender) +{ + if( SBB->Down ){ + m_Style |= FSBOLD; + } + else { + m_Style &= ~FSBOLD; + } + TFontStyles ts; + ts = Code2FontStyle(m_Style); + m_pFontDialog->Font->Style = ts; + UpdateSample(); + UpdateBoxFont(); +} +//--------------------------------------------------------------------------- +void __fastcall TTextInDlg::SBFDMouseDown(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + int ad = 0; + int h = m_pFontDialog->Font->Height; + if( Button == mbLeft ){ + if( Sender == SBFD ){ + if( h < -2 ) ad = 1; + } + else { + ad = -1; + } + } + else if( Button == mbRight ){ + if( Sender == SBFD ){ + if( h < -6 ) ad = 4; + } + else { + ad = -4; + } + } + if( ad ){ + m_pFontDialog->Font->Height = h + ad; + UpdateSample(); + UpdateBoxFont(); + } +} +//--------------------------------------------------------------------------- diff --git a/TextIn.dfm b/TextIn.dfm new file mode 100644 index 0000000..b727596 Binary files /dev/null and b/TextIn.dfm differ diff --git a/TextIn.h b/TextIn.h new file mode 100644 index 0000000..6245e13 --- /dev/null +++ b/TextIn.h @@ -0,0 +1,181 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//---------------------------------------------------------------------------- +#ifndef TextInH +#define TextInH +//---------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//---------------------------------------------------------------------------- +#include "Draw.h" +//---------------------------------------------------------------------------- +class TTextInDlg : public TForm +{ +__published: + TButton *OKBtn; + TButton *CancelBtn; + TLabel *Ltext; + TGroupBox *GBEf; + TRadioGroup *RGShadow; + TPanel *PCS; + TButton *FontBtn; + TRadioGroup *RGGrade; + TPanel *PC1; + TPanel *PC2; + TPanel *PC3; + TPanel *PC4; + TButton *CmdBtn; + TButton *TblBtn; + TComboBox *EditText; + TCheckBox *CBZero; + TLabel *LRot; + TComboBox *Rot; + TButton *MaskBtn; + TPanel *PCB; + TCheckBox *CBRA; + TPaintBox *PBox; + TTimer *Timer; + TUpDown *UDRot; + TCheckBox *CBTF; + TGroupBox *GBP; + TComboBox *CMBPro; + TButton *MemBtn; + TButton *DelBtn; + TButton *LineBtn; + TButton *TFBtn; + TCheckBox *CBStack; + TEdit *SEX; + TLabel *L1; + TUpDown *UDSX; + TLabel *L2; + TEdit *SEY; + TUpDown *UDSY; + TCheckBox *CBV; + TEdit *EV; + TUpDown *UDV; + TCheckBox *CBFont; + TMemo *Memo; + TSpeedButton *SBMSG; + TSpeedButton *SBFI; + TSpeedButton *SBFD; + TSpeedButton *SBF1; + TSpeedButton *SBF2; + TSpeedButton *SBF3; + TSpeedButton *SBF4; + TSpeedButton *SBB; + TSpeedButton *SBI; + void __fastcall RBGradeClick(TObject *Sender); + void __fastcall PCClick(TObject *Sender); + void __fastcall FontBtnClick(TObject *Sender); + void __fastcall CmdBtnClick(TObject *Sender); + void __fastcall TblBtnClick(TObject *Sender); + void __fastcall EditTextChange(TObject *Sender); + void __fastcall MaskBtnClick(TObject *Sender); + + void __fastcall TFBtnClick(TObject *Sender); + void __fastcall PBoxPaint(TObject *Sender); + void __fastcall CBZeroClick(TObject *Sender); + void __fastcall TimerTimer(TObject *Sender); + + void __fastcall UDRotClick(TObject *Sender, TUDBtnType Button); + void __fastcall MemBtnClick(TObject *Sender); + void __fastcall CMBProChange(TObject *Sender); + + void __fastcall DelBtnClick(TObject *Sender); + void __fastcall LineBtnClick(TObject *Sender); + + void __fastcall CMBProDropDown(TObject *Sender); + void __fastcall CMBProKeyPress(TObject *Sender, char &Key); + void __fastcall EditTextDropDown(TObject *Sender); + void __fastcall EditTextKeyPress(TObject *Sender, char &Key); + void __fastcall UDSXClick(TObject *Sender, TUDBtnType Button); + void __fastcall CBVClick(TObject *Sender); + void __fastcall CBFontClick(TObject *Sender); + void __fastcall PBoxMouseDown(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + + + void __fastcall SBMSGClick(TObject *Sender); + void __fastcall MemoDblClick(TObject *Sender); + + void __fastcall PBoxMouseMove(TObject *Sender, TShiftState Shift, int X, + int Y); + void __fastcall PBoxMouseUp(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + void __fastcall FontBtnMouseDown(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + void __fastcall SBFClick(TObject *Sender); + void __fastcall SBFMouseDown(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + void __fastcall SBIClick(TObject *Sender); + void __fastcall SBBClick(TObject *Sender); + void __fastcall SBFDMouseDown(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + + +private: + int m_DisEvent; + TFont *pFont; + CDrawText *pItem; + Graphics::TBitmap *pBrushBitmap; + int m_DropText; + int m_ReqChange; + CDrawText m_Text; + int m_DropProfile; + + int m_MouseXC, m_MouseYC, m_MouseHold; + + TFontDialog *m_pFontDialog; + void __fastcall UpdateBoxFont(void); + void __fastcall UpdateUI(void); + void __fastcall UpdateItem(CDrawText *pm, int fsw); + void __fastcall UpdatePara(CDrawText *pm); + void __fastcall AddTextList(LPCSTR pStr); + void __fastcall UpdateBitmap(void); + void __fastcall UpdateSample(void); + void __fastcall InitCMB(void); + void __fastcall SaveCMB(void); + + int __fastcall GetSBFIndex(TObject *Sender); + void __fastcall UpdateSBF(void); + void __fastcall AddStyle(AnsiString &as, BYTE charset, DWORD style); + TSpeedButton *m_tSBF[4]; + + DWORD m_Style; +public: + virtual __fastcall TTextInDlg(TComponent* AOwner); + __fastcall ~TTextInDlg(); + + int __fastcall Execute(CDrawText *p); +}; +//---------------------------------------------------------------------------- +//extern PACKAGE TTextInDlg *TextInDlg; +//---------------------------------------------------------------------------- +#endif diff --git a/UPDATE.TXT b/UPDATE.TXT new file mode 100644 index 0000000..05cb631 --- /dev/null +++ b/UPDATE.TXT @@ -0,0 +1,621 @@ +MMSSTVのバージョンアップ情報 + +*********************************************************************** +更新履歴 Ver1.13 -> Ver1.13A +*********************************************************************** +◎サウンドカード指定不具合の修正 +◎その他の細かい点の改善 + +*********************************************************************** +更新履歴 Ver1.12 -> Ver1.13 +*********************************************************************** +◎Ver1.12でカスタムサウンドが使えなくなっていたので修正 +◎英語版Webのホームページアドレスの変更 +◎JASTAコンテストの紹介(英語版)の修正 +◎COM8〜COM16を選択に追加 +◎CWメニューの追加(CWボタンでマウス右クリック) +◎リグコントロールメニューの追加 +◎トーン周波数を1000Hz下げるオプションの追加(起動オプション -i) + +*********************************************************************** +更新履歴 Ver1.11G -> Ver1.12 +*********************************************************************** +◎JASTAコンテスト重複チェックの修正 +◎サウンドカード指定方法の改善 + +*********************************************************************** +更新履歴 Ver1.11 -> Ver1.11G +*********************************************************************** +◎英語モード時のヘルプファイルの取り扱いにCHMファイルを追加 +◎ログファイルのフォルダを起動時に固定するようにした +◎受信画面のクリアを受信画面のポップアップメニューに追加 +◎Turbo HAMLOG/Win Ver5への対応 (Tnx to JG1MOU) +◎実験用モードの追加(MP-N, MC-N) +◎パッケージ内にFSKID.TXT(仕様)を追加 +◎狭帯域モードのAFCの改善 +◎英語モード時のメニューメッセージのtypoの修正 + +============================ +◎「同期ズレ補正」機能の追加 +============================ + ニコニコボタンを右クリックすると「同期ズレ補正」機能が働きます。従来の受信中の自動再同期で補正しきれなかった画像ズレも、この機能を使うと補正できます。この機能は画像受信中または画像受信終了後、いつでも実行することができます。 + +※1ライン毎に同期信号位置を計算補正して、受信信号を再描画しますので、小さなスラントも同時に補正することができます。 + + +*********************************************************************** +更新履歴 Ver1.10 -> Ver1.11 +*********************************************************************** +◎FSKID(コンテストNR)のバグを修正 + +*********************************************************************** +更新履歴 Ver1.09 -> Ver1.10 +*********************************************************************** +◎NVCG, JASTAコンテストの紹介をヘルプメニューに追加 +◎送信画面にCWボタンを追加 + - マウス右ボタンで送信するテキストを設定できる +◎FSKIDでコンテストNRを送出する機能を追加 + - ログ設定画面(その他)に「FSKIDにコンテストNRを含める」 + のチェックボックスを追加 +◎テンプレートのカラーバーに「サウンド」の項目を追加 +◎サウンド出力チャンネルを設定可能にした + - MMSSTV設定画面「その他」で入力チャンネルを「右」または「左」 + にするとTxCHのチェックボックスを表示 + - TxCHのチェックをONにすると、入力チャンネルと同じチャンネルにのみ + 信号を出力する +◎TxID(FSKIDの送信)ボタンをメイン画面のログウインドウに表示 + - 無意味なFSKIDの送出を簡単に抑止できるようにするため +◎受信画面の「消去」ボタンを廃止し「ロック」ボタンに変更 + - ロックをONにすると、QRMやQSBでもスキャン(画像受信)は停止しない +◎ログのバックアップ機能を追加 + - ログ設定画面(その他)に「バックアップ作成」のチェックボックスを追加 + - バックアップは「xxxx_BAK.MDT」の名前で自動的に生成される +◎画像クリッパ画面の機能/操作性の改善 + - ポップアップメニューを廃止しメインメニューに変更 + - 「余白を作る」ボタンを追加 + - 「回転」ボタンを追加 +◎テンプレート「テキストと色の設定」画面の操作性を改善 + - フォントサイズ拡大/縮小ボタンを追加 + - 太字(B)、斜体(I)ボタンを追加 + - 登録フォントボタン(F1-F4)を追加(右クリックでフォント登録) +◎テンプレートの文字展開コードの高速化 + - テンプレートのポップアップメニュー(右クリック)のオプションに + 「高速文字展開」を追加 +◎NVCGコンテストの規約を改訂 +◎Toneボタンの周波数精度を高精度に変更 +◎48KHzクロック系の動作を追加 + - 光デジタルI/F用(サブサンプリングしてないので重いかも...) +◎DSP計算の一部高速化 +◎小さなバグの修正およびその他の細かい点の改善 + + +*********************************************************************** +更新履歴 Ver1.08 -> Ver1.09 +*********************************************************************** +◎プログラム終了速度を改善 +◎テンプレートでのフォントスムージングの無効化 +◎EXTPTTポート(要 EXTFSK.DLL)の追加 +◎カスタムログリンクの実装 +◎カスタムRadioCommandの実装 +◎カスタムサウンドの実装 +◎小さなバグの修正およびその他の細かい点の改善 + +============================== +◎フォントスムージングの無効化 +============================== + Windowsの画面効果設定で、「スクリーンフォントの縁を滑らかにする」 オプションが有効になっている場合、MMSSTVのテンプレート画面で文字フォントの縁にテンプレートの背景色が漏れる場合があります。 + + この問題は、以下のいずれかの方法で解決できます。 + +1.Windowsの画面効果設定を変更する。 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + 「視覚効果」の「スクリーンフォントの縁を滑らかにする」 オプションを無効にします。この項目は、Windowsコントロールパネル内の以下の場所にあります。 + WindowsXP システム-詳細設定-視覚効果 + Windows2000 画面-効果 + Windows98/ME 画面-効果 + +2.MMSSTVのテンプレートオプションを変更する。 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + MMSSTVのテンプレート画面を右クリックし、「オプション」->「フォントスムージングの無効化」にチェックを入れます。この方法の場合、MMSSTVのテンプレート上だけWindowsの「スクリーンフォントの縁を滑らかにする」 は無効になります。 + + +==================== +◎EXTPTTポートの追加 +==================== + JA7UDE大庭さんの発案による、USBポートを利用した外部FSKユニットでPTT信号を作成する場合に使用します。このポートを利用する場合、MMSSTV設定画面のPTTポート名に「EXTPTT」を選択します。また「EXTFSK.DLL」がMMSSTVフォルダ内に必要です。詳細は以下のURLを参照して下さい。 + +http://www.archi.is.tohoku.ac.jp/~ooba/ja7ude/japanese_frametop.htm + + +*********************************************************************** +更新履歴 Ver1.07 -> Ver1.08 +*********************************************************************** +◎ノッチフィルタの追加 +◎フィルタ切り替え時の画像ズレを補正 +◎「テキストの色と設定」画面にMSGボタンを追加 +◎ストックテンプレート画面のページ数を4ページに変更 +◎重複チェックにJASTAコンテストオプションを追加 +◎LMSフィルタの動作選択の追加 +◎小さなバグの修正およびその他の細かい点の改善 + +================ +◎ノッチフィルタ +================ + 受信部に(FIR型)ノッチフィルタを設けました。スペクトラムまたはウォータフォール表示の枠内でマウス左ボタンをクリックすると、その周波数にノッチフィルタが設定されます。この時、スペクトラム下側に三角印のマーカーが表示されます。ノッチをOFFにするにはマウスの右ボタンをクリックします。 + ビート混信除去の目的で使用することができますが、画像帯域内にノッチフィルタを設定した場合、受信画像は若干劣化します。また同期信号周波数にノッチを設けた場合、「自動停止」をONにしていると弱い信号では画像受信が停止する場合があります。 + + Sound ---> Notch ---> LMS -+-> BPF ---> Demodulator + | + --> Spectrum display + +============================================= +◎「テキストの色と設定」画面にMSGボタンを追加 +============================================= + テンプレートの「テキストと色の設定」画面でMSGボタンを追加しました。 + MSGボタンを押すと一覧表が表示されますので、ここに定型の文字列をあらかじめ入力しておきます。文字列内にはマクロキーワードを使う事もできます。 + 行をダブルクリックすると、その行の文字列がテキストボックスにコピーされます。 + +=================================================== +◎重複チェックに「JASTAコンテスト」オプションを追加 +=================================================== + ログ設定画面の「その他」ページの重複チェックに「JASTAコンテスト」の選択を設けました。重複チェックにヒットするとメイン画面のLog枠のコールサインが赤色で表示されます。ヒットする条件は以下の通りです。 + +「コールサインのみ」 + 同じコールサインを見つけた時(バンド・モード関係なし) +「同一バンドでヒット」 +  同一バンドでヒットした時(モード関係なし) +「JASTAコンテスト」 +  14MHz以上のバンドで同じ日付(UTC)でSSTVモードでヒットした時 + + +============================= +◎LMSフィルタの動作選択の追加 +============================= + メインウインドウのDSP枠内のLMSボタンをマウスの右ボタンでクリックするとLMSフィルタの動作を選択できます。 + - Noise smoothing 従来動作(デフォルト) + - Auto notch (fast) 応答の速いオートノッチ + - Auto notch (slow) 応答の遅いオートノッチ + + オートノッチは画質への影響を軽減するため応答を遅めにしてありますが、それでも画材によって著しく画質が劣化する場合があります。 + + +*********************************************************************** +更新履歴 Ver1.06 -> Ver1.07 +*********************************************************************** +◎フォルダのサムネイルのマルチページ化 +◎フォルダのサムネイルの表示高速化 +◎OLEのサポート +◎小さなバグの修正およびその他の細かい点の改善 + +====================================== +◎フォルダのサムネイルのマルチページ化 +====================================== + フォルダのサムネイルをマルチページにすることができます。これにより複数のフォルダを1つのサムネイルウインドウで利用することができます。 + マルチページにするには、フォルダのサムネイルの上でマウスの右ボタンを押し、「オプション」->「新規ページの作成」を選択します。またページの名前(タブに表示される名前)を変更するには「ページの名前」を選択します。 + 1つのフォルダのサムネイルについて最大10ページを作成することができます。 + + +================================== +◎フォルダのサムネイルの表示高速化 +================================== + フォルダのサムネイルに大きなJPEG画像やテンプレートを表示した場合、ファイルのロードに時間がかかりすぎて操作性が著しく悪化します。 + Ver1.07では、サムネイルのインデックスを作成することにより、一旦表示したサムネイルについては2回目以降の表示を高速化するように改善してあります。 + + MMSSTVはインデックスをMMSSTVフォルダ内の「FIndex」というフォルダに作成します。インデックスはファイルの一覧情報(IDX)とサムネイルのビットマップ(BMP)で構成されます。これらのファイルによりハードディスク上のスペースを若干消費しますが、メモリやリソースの消費を最小限に抑えることができます。 + + フォルダのサムネイルの上でマウスの右ボタンを押し、「オプション」->「インデックスによる高速参照」のチェックを外すとインデックスの作成は行われず従来と同じ動作になります(フォルダ毎にON/OFFを設定する事ができます)。 + +*MMSSTVは参照対象のフォルダにいかなるファイルも作成しません。 + + +=============== +◎OLEのサポート +=============== + MMSSTVはOLE(Object Linking and Embedding)をサポートします。オブジェクトをテンプレートに埋めこむ(またはリンクする)と、そのオブジェクトが持つ様々な機能をテンプレート上で直接利用することができます。 + +*オブジェクトとは他のアプリケーションのドキュメントの一部または全部です。 + +*どのようなオブジェクトが利用できるかは、インストールされているOLEアプリケーションに依存します。例えばワープロソフトをインストールしていると、そのドキュメントそれ自体や、付属している文字効果/図形加工などのオブジェクトがすべて利用できます。 + + +1.オブジェクトの作成 +~~~~~~~~~~~~~~~~~~~~ + オブジェクトをテンプレートに作成するには、以下の5つの方法のうちのいずれかを実行します。 + +・テンプレート画面でマウスの右ボタンを押し「オブジェクト」->「挿入」を実行し、挿入するオブジェクトを一覧表から選んで新規に作成します。または既存のファイルから埋めこみまたはリンクで作成します。 + +・他のアプリケーションでオブジェクトをコピーした後、MMSSTVのテンプレート画面でマウスの右ボタンを押し「オブジェクト」->「貼り付け」を実行します。 + +・エクスプローラやマイコンピュータ等からMMSSTVのテンプレートに埋めこみたいファイルをドロップします。ただしBMP,JPG,WMF,MTM,MTI,DLLファイルは、MMSSTVの組み込み機構でドロップされるためOLEオブジェクトにはなりません。 + +・フォルダのサムネイルを開き、対象画像のサムネイルでマウスの右ボタンを押し、「テンプレートにOLEで埋めこみ」を実行します。この場合、埋めこまれる画像は必ずOLEのビットマップオブジェクトになります。 + +・フォルダのサムネイルのファイルの種類を「OLE objects」にして開き、対象のサムネイルをダブルクリックするか、テンプレートにドロップします。 + + +2.オブジェクトの編集 +~~~~~~~~~~~~~~~~~~~~ + テンプレート内に存在するオブジェクトを編集するには、そのアイテムをダブルクリックするか、またはそのアイテムを選択状態にしてテンプレートツールボタンの「色の設定」ボタンを押します。もしこれらの操作でサーバーアプリケーションが起動できない場合、「オブジェクト」->「編集」を選択します。 + オブジェクトの編集操作はそのオブジェクトのサーバーアプリケーションから提供されます。それぞれのアプリケーションのヘルプを参照して下さい。例えばビットマップオブジェクトの場合はWindowsペイントが標準で起動されます。 + + +3.オブジェクトの表示と伸縮 +~~~~~~~~~~~~~~~~~~~~~~~~~~ + MMSSTVはデフォルトではオブジェクトをオーバーレイモードで表示します。もし背景を透過にする必要がない場合、そのアイテムを選択状態にして「オブジェクト」->「オーバーレイ」のチェックを外して下さい。 + + 「オブジェクト」->「ビットマップ伸縮」にチェックを付けると、MMSSTVはメタファイルの伸縮コードを使わずにビットマップの伸縮コードを使います。一般的に特殊効果文字オブジェクトのような線画を表示する場合、メタファイル伸縮コードのほうが綺麗に表示されます。しかし写真などのイメージオブジェクトを表示する場合、ビットマップの伸縮コードを使ったほうが綺麗な場合があります。 + + +4.カスタムアイテム +~~~~~~~~~~~~~~~~~~ + MMSSTVの組み込みアイテムや一般的なOLEオブジェクトの動作に満足できない場合、自分で作成したカスタムアイテムを埋めこむこともできます。 + カスタムアイテムを埋めこむには「オブジェクト」->「カスタムアイテムの挿入」を実行し、埋めこむアイテムを選択します。またはフォルダのサムネイルのファイルの種類を「カスタムアイテム」にして開き、対象のサムネイルをダブルクリックするか、テンプレートにドロップします。 + + カスタムアイテムの実装方法については別に公開するカスタムアイテムのサンプル「PerImg」内の「Custom.txt」を参照して下さい。 + + +*********************************************************************** +更新履歴 Ver1.05 -> Ver1.06 +*********************************************************************** +◎VFOポーリングにJST245を追加 +◎ハングルフォントでの斜線付き0を処理 +◎いくつかのSSTVモードの追加 +◎自動再同期の処理修正 +◎B/W 8secモードのタイミングをRobot1200Cに合わせた +◎東アジア言語の処理を修正 +◎サウンドロストの対策 +◎オーバーレイ機能の追加 +◎小さなバグの修正およびその他の細かい点の改善 + +========================== +◎東アジア言語の処理を修正 +========================== + テンプレートでの東アジア言語の取り扱いを修正しました。ただし、あなたのPCのデフォルト言語と異なる言語を取り扱う場合、そのPCに目的とする言語のフォントとコードページがインストールされていなければなりません。フォントのみをインストールした場合、一部の機能(文字列の垂直展開など)がそのコードページの文字では旨く働きません。 + + MMSSTVが特別に処理する東アジア言語のコードページは以下の通りです。 + 932 日本語 確認済み + 949 韓国語 確認済み + 950 中国語(BIG5) 未確認 + 936 中国語(GB2312) 未確認 + + +====================== +◎サウンドロストの対策 +====================== + 一部のサウンドカードデバイスドライバではサウンドをロストしやすい(画像の同期がずれる)という問題があるようです。今回その状態にできるだけならないようにするコードを追加しました。それなりの効果はあるようですが、完全にこの問題が解消されたわけではありません。可能ならば最新のデバイスドライバをインストールされることをお勧めします。 + + なおサウンドロストが発生する場合、MMSSTV設定画面の「送信」ページの「ループバック」は必ずOFFにし、「その他」ページの「FIFO」の数を増やしてください。 + +================ +◎MP/MR/MLモード +================ +MPモード + PDモードと同じ方式の色差方式のモードで、20mでのマルチパス/ジッタ対策のために設けました。ピクセル当たりのスキャン時間は同一伝送時間の他のモードよりも長いですが、垂直方向の色情報が圧縮されています。 + +MR/MLモード + Robot24/72モードと同じ方式の色差方式のモードで、比較的良好なCondx下で見た目の解像度を得るのが狙いです。水平方向の色情報が圧縮されています。 + + + いずれも方式は新しいものではありませんが、適当な伝送時間と画像サイズを作成しました。新しい試みとして、VIS信号を16ビットに拡張してあります。 + フォーマットの詳細は付属の「Mode.txt」を参照して下さい。 + +================ +◎B/W 8secモード +================ + B/W 8secモードは昔のモノクロ時代を含めて、装置によりアスペクト比やタイミングが複数存在しているようです。 + MMSSTVではRobot1200C(スキャンコンバータ)を一応の標準として、そのタイミングに合わせてあります。異なるタイミングの信号を受信する場合は自動傾き調整をONにするか、同期画面の「ニコニコ」ボタンを押すと良いでしょう。 + +================ +◎RTS while scan +================ + 「MMSSTV設定画面」のPTTに「RTS while scan」のチェックを設けました。COMポートの各信号はそれぞれ以下のようになります。 + +[RTS while scan = OFF] + RX TX SCAN(画像受信中) + DTR OFF ON OFF + RTS OFF ON OFF + TXD --- --- --- (制御なし) +[RTS while scan = ON] + RX TX SCAN(画像受信中) + DTR OFF ON OFF + RTS OFF ON ON + TXD NoBreak NoBreak Break + +========== +◎VOX tone +========== + もしあなたがCOMポートでPTTを切り替えているか、または応答の良いVOXインターフェースを使っているならば、MMSSTV設定画面の「送信」ページの「VOX tone」を「User defined」にし、「Edit」ボタンを押して既存の定義をすべて削除してください。VOX起動用のトーンを出力しないようにできます。 + +============== +◎オーバーレイ +============== + テンプレート上に画像をオーバーレイすることができます。オーバーレイした場合、透過ポイント(デフォルト左上)で指定される色はすべて透明になります。この機能は画像ソースがイラスト画などの背景が均一な色の場合に有効です。 + + 「挿入画像の選択」画面で「オーバーレイ」を選択した場合、画像部分をマウス左ボタンでクリックすると透過ポイントをその位置に変更できます。またマウス右ボタンでクリックすると、その位置の色と同じすべてのポイントを、現在の透過ポイントの色で置き換えます。 + + 画像ソースがJPEGフォーマットで保存されていた場合、その背景色は圧縮効果により完全に均一にならず、それをオーバーレイした場合に色漏れ現象が起こります。この場合「挿入画像の選択」画面で「透過色平坦化」を実行して背景色を均一にすると色漏れが改善される場合があります。 + + テンプレート上でオーバーレイ画像のサイズを変更した場合、MMSSTVはその画質よりも色の均一性を保つことを優先します。サイズ変更の結果、満足する画質が得られない場合、まずビットマップの状態でサイズを変更した後、オーバーレイに変更すると良いでしょう。ただしビットマップの状態でのサイズ変更は画質が優先されるために、色の均一性が損なわれる可能性があります。この場合、「透過色平坦化」を実行して色漏れを改善することができます。 + + +*********************************************************************** +更新履歴 Ver1.04 -> Ver1.05 +*********************************************************************** +◎Turbo HAMLOG/Winとのリアルタイムリンク機能の追加 +◎画面のデザインを選択できるオプションの追加 +◎制御ボタンウインドウの追加 +◎受信専用画面をデスクトップの子ウインドウにするオプションの追加 +◎ストック画像/テンプレート、フォルダのサムネイルでの + ダブルクリック操作の追加 +◎320x240画像の取り扱い方法の追加 +◎SSTVリピータ機能の追加 +◎Win95/98系でリソース不足になるバグの修正 +◎小さなバグの修正およびその他の細かい点の改善 + +========================== +Turbo HAMLOG/Winとのリンク +========================== + JG1MOU 浜田さんが作成されたTurbo HAMLOG/Win(以下Hamlog)とリアルタイムにリンクを行うことができます。この機能を使用するにはHamlogのバージョンが4.48e以降でMMSSTVと同時に実行状態になければなりません。 + MMSSTVはHamlogの検出に成功するとメイン画面のLog枠に「Link to Turbo HAMLOG/Win」を表示します。 + + この機能を利用する場合、Hamlogの「環境設定」の「設定1」の「交信履歴表示で一旦停止」のチェックは必ず外して下さい。 + + 現在以下の機能が利用できます。 + +◎検索 + MMSSTVのLog枠のCallボックスでコールサインを入れてEntキーを押すとHamlogの検索が同時に働きます。IDの自動受信によっても同様の動作になります。 + +◎記録 + MMSSTVのQSOボタンによる通常のログ操作を行うことにより、Hamlogにも同じデータが同時に記録されます。 + +◎周波数ポーリング + Hamlogのカレント周波数データを定期的にポーリングすることができます。この機能を使用する場合、MMSSTVの「ログ設定画面」の「変換」ページで「Link-Frequency polling」のチェックを入れて下さい。 + + + Hamlogとのリンク機能を使用したくない場合は、MMSSTVの「ログ設定画面」の「変換」ページの「Link-Application」をOFFに設定して下さい。 + + この機能は関ハムで浜田さんと偶然お会いすることができ実現しました。今回、浜田さんには大変お世話になりました。有難うございました。 + + +============ +画面デザイン +============ + 表示メニューの「デザイン」で画面のデザインを選択できます。 + +[標準] + MMSSTVの標準のデザインです。1つのウインドウに表示されます。 + +[ストック画面を分離] + メイン画面からストック画面を分離します。 + +[すべて分離] + すべての画面を分離します。 + + いずれの場合も、分離した画面は個々に位置とサイズを調整することができます。 + + +==================== +制御ボタンウインドウ +==================== + 表示メニューの「制御ボタンを常に表示」にチェックを付けると、制御ボタンのウインドウを常に表示します。表示されるボタンは以下の5つです。 + +[受信停止] + 画像受信を強制的に中止し、待機状態(Auto)にします。 + +[再同期] + 強制的に再同期を取ります。 + +[受信ロック] + このボタンを押しこむと「自動停止」と「自動再起動」が共にOFFになり、QRMやQSBなどでもスキャンは停止しません。押しこみを解除すると「自動停止」と「自動再起動」は共にONになります。 + +[履歴にコピー] + 履歴に受信画像がコピーされない場合、このボタンを押すと強制的にコピーされます。 + +[送信(F9)] + 送信画面の「TX」ボタンと同じです。「F9」キーを押しても送受のON/OFFを切り換えることができます。 + +============================================== +受信専用画面をデスクトップの子ウインドウにする +============================================== + 表示メニューの「受信画面を常に表示」にチェックを付けた状態で表示される受信専用画面について、そのウインドウをデスクトップの子ウインドウにするかどうかを選択できます。 + 受信専用画面をマウスの右ボタンでクリックするとポップアップメニューが表示されます。そのメニューの「デスクトップの子ウインドウ」にチェックを付けると、受信専用画面はMMSSTVメイン画面から分離されてデスクトップの直属ウインドウになります。 + この状態ではMMSSTVメイン画面を最小化しても、受信専用画面はデスクトップ上に残すことができます。 + +========================= +320x240画像の取り扱い方法 +========================= + 画像ソースが320x240の場合、その画像をどのように送信画面に取りこむかを「編集」メニューの「320x240の取り扱い」で選択できます。ソース画像が640x480で、送信モードが640x496の場合も同様の動作になります。 + +[縦を伸縮] + 縦方向のみ256ラインに拡大して取りこみます。アスペクト比は崩れます。 + +[自動伸縮] + アスペクト比を保ちながら320x256に伸縮して取りこみます。ソース画像の左右を少し失います。これは従来のバージョンの動作と同じです。 + +[伸縮なし] + そのままのサイズで取りこみます。送信画面の下側16ラインに隙間ができます。 + +[上マージンの確保] + そのままのサイズで上マージンを確保して取りこみます。送信画面の上側16ラインに隙間ができます。 + + なお、画像クリッパを経由して取り込む場合このメニュー選択は関係せず、画像クリッパでの操作に依存します。 + +================ +SSTVリピータ機能 +================ + MMSSTVをSSTVリピータとして動作させることができます。詳細は「Repeater.txt」を参照して下さい。 + + +*********************************************************************** +更新履歴 Ver1.03 -> Ver1.04 +*********************************************************************** +◎テンプレートの文字入力画面の改善 +◎バグの修正およびその他の細かい点の改善 + +*********************************************************************** +更新履歴 Ver1.02 -> Ver1.03 +*********************************************************************** +◎スペクトラム表示に「FM復調器」方式を追加 +◎AFCボタンを追加 +◎テンプレートのポップアップメニューに「元に戻す」を追加 +◎バグの修正およびその他の細かい点の改善 + +================ +スペクトラム表示 +================ + 表示メニューの「スペクトラム表示」のところでOFF,FFT,FM復調器を選択できます。デフォルトを今回追加したFM復調器にしましたので、従来のFFTを使いたい場合はこのメニューで変更して下さい。 + + *PY4ZBZ氏が作成したプログラムでMMSSTVのWaterFallにCMT-HELLを描く場合はFFTを選択しなければなりません。 + + FM復調方式は、広帯域のFM復調器(画像復調用とは別の復調器)を使い、その復調信号から個々の周波数の出現頻度をグラフに描きます。処理はFFTよりも遥かに簡単ですのでCPU負荷は小さく、同期信号のような短いパルスに対する反応も良いようですが、振幅が信号のレベルに無関係になってしまいます。 + + いずれの方式でもフィルタ帯域外の様子を見ることができるように、SSTV用のBPFフィルタを通過する前の信号を観測します。 + + --- Sound in --+--> SSTV demodulator + | + ---> Spectral (FFT / FM demodulator) + + +============== +AFC +============== + メイン画面のDSP枠にあるAFCボタンを押しこむと画像受信中にAFCが働きます(デフォルトはONです)。 + + AFCがロックしている時、スペクトラム画面の同期信号の位置に△印のマーカーが青色で表示されます。AFCのロックが外れると△印のマーカーは赤色で表示されます(その間、周波数ズレに対する応答は遅れます)。 + +*従来のバージョンにあったAGCボタンは効果がなかったので削除しました。 + + +*********************************************************************** +更新履歴 Ver1.01 -> Ver1.02 +*********************************************************************** +◎FM復調方式にヒルベルト(hilbert)変換方式を追加 +◎低レベルサウンドバッファ処理を改善 +◎同期画面にTX(TX offset)ボタンを追加 +◎高精度傾き調整機能の追加 +◎Vari SSTV機能の追加 +◎自動起動処理の誤動作改善 +◎バグの修正および細かい点の改善 + + +================================== +FM復調器にヒルベルト変換方式を追加 +================================== + 以下にヒルベルト変換方式の構成図を示します。このアイデアはJA6UHL西村さんに教えて頂きました(MNI TNX to JA6UHL)。 + + --+-> Delay(N) -> Real + | |==> ATAN --> 微分器 --> LPF --> Pic. data + --> FIR(2N) --> Image + + +======================== +低レベルサウンドバッファ +======================== + 低レベルサウンドバッファ処理を改善し、バッファの循環数(FIFO)を設定画面で設定できるようにしました。また送信と受信で異なるFIFOの数を割り当てることが可能です。 + + サウンドをロスト(同期ずれをおこす)しやすい場合、受信の場合はRX FIFO、送信の場合はTX FIFOの数を増やすと効果があります。また処理の優先度を高くするのも効果的です。 + + +============== +高精度傾き調整 +============== + 高精度傾き調整は、現在受信中または直前に受信した信号の、同期位置の直線方程式の解を最小二乗法で求め補正します。受信信号の質が良好な場合、誤差は概ね2ppm以内に収まります。 + + 高精度傾き調整を行うには、同期画面のニコニコボタンを押すか、同期画面または受信画面でマウスの右ボタンをクリックし、ポップアップメニューの中の「高精度傾き調整」を実行します。この機能を使うには少なくとも16掃引分の信号を受信していなければなりません。また掃引数が多くなるほど精度は良くなります。 + + +=============== +TX offsetの調整 +=============== + 受信時のクロックが調整されている状態で、外部ループバックで送信し、その信号を自分自身で受信します。 + 受信した画像を傾きがない状態に調整(ニコニコボタンを押す)した後、同期画面の「TX」ボタンを押すと、Tx offset周波数が自動的に設定されます。 + + +======== +VariSSTV +======== + VariSSTVはSamuel Hunt氏が提案する終段デバイスの保護の方法です。画像の輝度が色によって異なるために、R,G,Bのそれぞれについて以下のように送信出力を抑えると、送信機側で一意に抑えるよりもノイズの影響が少ないと彼は提案しています。 + + 同期信号 100% + 赤色 29.8% + 緑色 58.8% + 青色 11% + + 詳細は「http://www.supersam.co.uk/sstvpwer.htm」を参照して下さい。 + + VariSSTVの効果の程は私には判りません。皆さんで個々に実験して下さい。MMSSTV設定画面の送信ページの「デジタル出力レベル」で「VariSSTV」のチェックを付けると働きます(Robot36, Robot72モードを除く)。 + + +*********************************************************************** +更新履歴 Ver1.00 -> Ver1.01 +*********************************************************************** +◎いくつかのSSTVモードの追加 +◎画像クリッパーの機能改善 +◎ファイル選択時のプレビューの表示 +◎バグの修正および細かい点の改善 + + +================ +SSTVモードの追加 +================ + 以下のSSTVモードを追加しました。 + + 名称 時間(s) サイズ 方式 + --------------------------------------------------- + SC2-120 122 320x256 RGB + SC2-60 62 320x256 RGB + PD50 50 320x256 色差 + PD90 90 320x256 色差 + PD120 126 640x496 色差 + PD160 161 512x400 色差 + PD180 187 640x496 色差 + PD240 248 640x496 色差 + PD290 289 800x616 色差 + P3 203 640x496 RGB + P5 305 640x496 RGB + P7 406 640x496 RGB + + + これらの追加されたSSTVモードを選択するには、送信または受信のモードボタンをマウスの右ボタンでクリックしてメニューを開きボタンの割り当てを変更します。 + + PD120〜PD290およびP3〜P5は、320x256よりも大きなサイズの画像を扱います(以下ハイリゾリューションモード)。MMSSTVのメイン画面の画像ビューポートは320x256用に設計されているために、これらのハイリゾリューション画像を表示する際は、その画像をビューポート内に縮小して表示します。つまりハイリゾリューションモードの場合は、受信した画像や送信する画像の大きさとMMSSTVの画面の大きさは必ずしも一致しません。 + + 受信したハイリゾリューション画像を本来のサイズで表示したい場合、受信画面または履歴画面の「虫メガネ」ボタンを押すか、または「受信画面を常に表示」で表示している、独立受信画面のポップアップメニューにある「受信サイズに戻す」を選択します。 + 送信するハイリゾリューション画像を本来のサイズで表示したい場合、送信画面の「虫メガネ」ボタンを押します。 + + + 送信モードを異なる画像サイズに変更した場合、送信画面に既に存在する画像に関して、デフォルトではそのサイズを自動的に伸縮しません。もし自動的に伸縮させたい場合には、送信画面のポップアップメニューの「異なるサイズで画像を伸縮」のチェックを付けて下さい。ただしこの場合、小さな画像モードから大きな画像モードに変更する場合に、送信画像が拡大コピーされるために、そのモード本来の伝達解像度を得られない場合があります。またモードによりアスペクト比が微妙に異なる場合もあります。 + いずれにせよ送信画像のサイズが変更された場合、再度送信画面に画像をロードしなおすことをお勧めします。 + + MMSSTVのテンプレートもいくつかのサイズを持ちます。良好なテンプレートの画質を得るには送信する画像と同じサイズのテンプレートを使用するのが良いでしょう。デフォルトではテンプレートのサイズは送信画像のサイズに常に一致させます。しかしこの場合、異なるサイズで設計したテンプレートを合成した場合、その配置デザインは崩れます。 + テンプレート画面のポップアップメニューの「サイズ」を変更するとテンプレートのサイズを任意に変更できます。送信画面と異なるサイズに設定した場合、MMSSTVはテンプレート画像を一旦伸縮して送信画像に合わせた後合成します。この場合テンプレートの画質は悪化しますが、異なるサイズで設計したテンプレートをそのまま流用することができます。 + + ストック画像領域の画像サイズはデフォルトで320x256に設定されていますが、ハイリゾリューションモード用の画像をストック画像に準備したい場合、ポップアップメニュー内の「サイズ」を選択する事により、そのスロットのサイズを変更する事ができます。 + また送信画像からストック画像にドラッグ&ドロップした場合は、送信画像のサイズがそのままそのストック画像のサイズに適用されます。 + + + 自動傾き調整用のメモリに「RAM」を選択している場合、PD290,P5,P7の各モードではすべてのサウンドデータが格納されません。従ってこれらのモードでは画像を受信した後の傾き調整や位相調整を行う場合に途中までしか行われません。これを回避するには受信バッファを「FILE」にしておくと良いでしょう。 + + +======================== +画像クリッパーの機能改善 +======================== + 以下の機能を追加しました。 + + ・伸縮しないでコピーする動作の追加 + ・ソース画像の90度の回転 + ・画像調整 + ・クリップボードへのコピー + ・ファイルへのセーブ + + 画像クリッパー画面で、マウスの右ボタンを押すとポップアップメニューが表示されます。 + + +================================ +ファイル選択時のプレビューの表示 +================================ + 画像ファイルをロードする際のファイル選択ダイアログボックスで、ファイル名をクリックするとその画像ファイルのプレビューを表示します。 + プレビュー画面はデフォルトでは画面左上になっていますが、サイズと位置を自由に変更することができます。 + + +73, Mako diff --git a/VerDsp.cpp b/VerDsp.cpp new file mode 100644 index 0000000..b7659f1 --- /dev/null +++ b/VerDsp.cpp @@ -0,0 +1,52 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "VerDsp.h" +#include "ComLib.h" +//--------------------------------------------------------------------- +#pragma resource "*.dfm" +//TVerDspDlg *VerDspDlg; +//--------------------------------------------------------------------- +__fastcall TVerDspDlg::TVerDspDlg(TComponent* AOwner) + : TForm(AOwner) +{ + IconImage->Picture->Assign(Application->Icon); + FormStyle = ((TForm *)AOwner)->FormStyle; + Font->Name = ((TForm *)AOwner)->Font->Name; + Font->Charset = ((TForm *)AOwner)->Font->Charset; + LFree->Font->Name = ((TForm *)AOwner)->Font->Name; + LFree->Font->Charset = ((TForm *)AOwner)->Font->Charset; + if( MsgEng ){ + Caption = "Version Information"; + LFree->Caption = "Free Software"; + } + Version->Caption = VERTTL; + LInfo->Caption = + "I would like to thank my friends in both groups\r\n\r\n" + " MM-SSTV@yahoogroups.com\r\n" + " mmhamsoft@egroups.co.jp\r\n\r\n" + "I do not list all those names, for fear that I would forget one.\r\n" + "And too small space in the window for writing all the name..." + ; +} +//--------------------------------------------------------------------- diff --git a/VerDsp.dfm b/VerDsp.dfm new file mode 100644 index 0000000..8eb11c1 Binary files /dev/null and b/VerDsp.dfm differ diff --git a/VerDsp.h b/VerDsp.h new file mode 100644 index 0000000..83dcdb9 --- /dev/null +++ b/VerDsp.h @@ -0,0 +1,50 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//---------------------------------------------------------------------------- +#ifndef VerDspH +#define VerDspH +//---------------------------------------------------------------------------- +#include //ja7ude 0428 +#include +#include +#include +#include +#include +#include +#include +#include +#include +//---------------------------------------------------------------------------- +class TVerDspDlg : public TForm +{ +__published: + TButton *OKBtn; + TLabel *Version; + TImage *IconImage; + TLabel *LFree; + TLabel *LInfo; +private: +public: + virtual __fastcall TVerDspDlg(TComponent* AOwner); +}; +//---------------------------------------------------------------------------- +//extern TVerDspDlg *VerDspDlg; +//---------------------------------------------------------------------------- +#endif diff --git a/Wave.cpp b/Wave.cpp new file mode 100644 index 0000000..b2d9998 --- /dev/null +++ b/Wave.cpp @@ -0,0 +1,892 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +#include //ja7ude 0521 +#pragma hdrstop + +#include "Wave.h" +//--------------------------------------------------------------------------- +// 初期化 +__fastcall CWave::CWave(void) +{ + m_Error = 0; + m_InOpen = m_OutOpen = FALSE; + m_hin = NULL; + m_hout = NULL; + m_InEvent = NULL; + m_OutEvent = NULL; + for( int i = 0; i < WAVE_FIFO_MAX; i++ ){ + m_pInBuff[i] = m_pOutBuff[i] = NULL; + } + m_pOutBase = m_pInBase = NULL; + m_InBuffSize = 1024; + m_OutBuffSize = 1024; + m_OutFirst = FALSE; + m_InFifoSize = 12; + m_OutFifoSize = 4; + m_SoundStereo = 1; + m_StereoTX = 0; + m_pDLL = NULL; + ::InitializeCriticalSection(&m_InCS); + ::InitializeCriticalSection(&m_OutCS); +} + +//--------------------------------------------------------------------------- +// 終了時実行ルーチン +__fastcall CWave::~CWave() +{ + ::DeleteCriticalSection(&m_InCS); + ::DeleteCriticalSection(&m_OutCS); + if( m_pDLL ){ + delete m_pDLL; + m_pDLL = NULL; + } +} +//--------------------------------------------------------------------------- +// サウンドカードの名前を得る +void __fastcall CWave::GetDeviceName(void) +{ + m_InDevs = 0; + m_OutDevs = 0; + + WAVEINCAPS incaps; + for( unsigned int i = 0; i < AN(m_tInDevName); i++ ){ + if( !waveInGetDevCaps(i, &incaps, sizeof(incaps)) ){ + m_tInDevName[i] = incaps.szPname; + m_InDevs = i + 1; + } + else { + m_tInDevName[i] = ""; + } + } + WAVEOUTCAPS outcaps; + for( unsigned int i = 0; i < AN(m_tOutDevName); i++ ){ + if( !waveOutGetDevCaps(i, &outcaps, sizeof(outcaps)) ){ + m_tOutDevName[i] = outcaps.szPname; + m_OutDevs = i + 1; + } + else { + m_tOutDevName[i] = ""; + } + } +} +#if 0 +//--------------------------------------------------------------------------- +// サウンドカードの問い合わせ +BOOL __fastcall CWave::IsFormatSupported(LPWAVEFORMATEX pWFX, UINT IDDevice) +{ + return (::waveOutOpen( + NULL, // ptr can be NULL for query + IDDevice, // the device identifier + pWFX, // defines requested format + NULL, // no callback + NULL, // no instance data + WAVE_FORMAT_QUERY // query only, do not open device + ) ? FALSE : TRUE); +} +#endif +//--------------------------------------------------------------------------- +// サウンドカードの入力でのオープン +// WFX.wFormatTag = WAVE_FORMAT_PCM; +// WFX.nChannels = 1; +// WFX.wBitsPerSample = 16; +// WFX.nSamplesPerSec = 11025; +// WFX.nBlockAlign = WORD(WFX.nChannels *(WFX.wBitsPerSample/8)); +// WFX.nAvgBytesPerSec = WFX.nBlockAlign * WFX.nSamplesPerSec; +// WFX.cbSize = 0; +BOOL __fastcall CWave::InOpen(LPWAVEFORMATEX pWFX, UINT IDDevice, DWORD Size) +{ + if( m_pDLL ){ + m_InOpen = m_pDLL->InOpen(pWFX->nSamplesPerSec, Size); + if( !m_InOpen ) PumpMessages(); + return m_InOpen; + } + int i; + + if( m_InOpen ) InClose(); + m_Error = 0; + m_InWait = m_InOver = FALSE; + m_InWP = m_InRP = m_InBC = 0; + m_IWFX = *pWFX; + m_InBuffSize = Size * (m_IWFX.wBitsPerSample/8) * m_IWFX.nChannels; + m_InMemSize = sizeof(WAVEHDR) + m_InBuffSize; + if( m_InMemSize & 3 ) m_InMemSize += 4 - (m_InMemSize & 3); + m_InAllocSize = m_InMemSize * m_InFifoSize; + m_InEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL); + // サウンドカードのオープン + if( (m_Error = ::waveInOpen( &m_hin, IDDevice, pWFX, (DWORD)WaveInProc, (DWORD)this, CALLBACK_FUNCTION ) ) != MMSYSERR_NOERROR ){ + InClose(); + return FALSE; + } + // バッファの準備 + m_pInBase = new char[m_InAllocSize]; + ::VirtualLock(m_pInBase, m_InAllocSize); + memset(m_pInBase, 0, m_InAllocSize); + LPSTR p = m_pInBase; + for( i=0; i < m_InFifoSize; i++, p += m_InMemSize ){ + m_pInBuff[i] = (WAVEHDR *)p; + ((WAVEHDR *)p)->dwBufferLength = m_InBuffSize; + ((WAVEHDR *)p)->dwFlags = 0; + ((WAVEHDR *)p)->dwUser = NULL; + ((WAVEHDR *)p)->dwBytesRecorded = NULL; + ((WAVEHDR *)p)->lpData = p + sizeof(WAVEHDR); + if( (m_Error = ::waveInPrepareHeader(m_hin, (WAVEHDR *)p, sizeof(WAVEHDR)) ) != MMSYSERR_NOERROR ){ + InClose(); + return FALSE; + } + if( (m_Error = ::waveInAddBuffer(m_hin, (WAVEHDR *)p, sizeof(WAVEHDR)) ) != MMSYSERR_NOERROR ){ + InClose(); + return FALSE; + } + } + // 取りこみの開始 + if( (m_Error = ::waveInStart(m_hin) ) != MMSYSERR_NOERROR ){ + InClose(); + return FALSE; + } + m_InOpen = TRUE; + return TRUE; +} +//--------------------------------------------------------------------------- +void __fastcall CWave::InClose() +{ + if( m_pDLL ){ + m_pDLL->InClose(); + m_InOpen = FALSE; + PumpMessages(); + return; + } + int i; + + if(NULL != m_hin){ + ::waveInReset(m_hin); + if( m_pInBase != NULL ){ + for( i=0; i < m_InFifoSize; i++ ){ + if( m_pInBuff[i] != NULL ){ + if( m_pInBuff[i]->dwFlags & WHDR_PREPARED ){ + ::waveInUnprepareHeader(m_hin, m_pInBuff[i], sizeof(WAVEHDR)); + } + } + } + } + ::waveInClose(m_hin); + m_hin = NULL; + if( m_pInBase != NULL ){ + ::VirtualUnlock(m_pInBase, m_InAllocSize); + delete m_pInBase; + m_pInBase = NULL; + } + } + if(m_InEvent != NULL){ + ::CloseHandle(m_InEvent); + m_InEvent = NULL; + } + m_InOpen = FALSE; +} +//--------------------------------------------------------------------------- +BOOL __fastcall CWave::InRead(double* pData, int Len) +{ + if( m_pDLL ){ + return m_pDLL->InRead(pData, Len); + } + int i; + + if( !m_InOpen ){ + m_Error = 1; + return FALSE; + } + if( m_InOver ){ + m_Error = 1; + InClose(); + return FALSE; + } + + ::EnterCriticalSection(&m_InCS); + if( !m_InBC ){ // まだデータが存在しない時 + m_InWait++; + ::LeaveCriticalSection(&m_InCS); + // バッファにデータが溜まるまで待つ + if( ::WaitForSingleObject( m_InEvent, WAVE_TIMEOUT_EVENT ) != WAIT_OBJECT_0 ){ + m_Error = 1; + InClose(); + return FALSE; + } + } + else { + ::LeaveCriticalSection(&m_InCS); + } + // データを浮動少数点に変換 + LPWAVEHDR hp = m_pInBuff[m_InRP]; + if( m_IWFX.wBitsPerSample == 16 ){ // 16bits + SHORT *rp = (SHORT *)hp->lpData; + if( m_IWFX.nChannels == 2 ){ + if( m_SoundStereo == 1 ){ // Left + for( i = 0; i < Len; i++, pData++ ){ + *pData = double(*rp++); + rp++; + } + } + else { // Right + for( i = 0; i < Len; i++, pData++ ){ + rp++; + *pData = double(*rp++); + } + } + } + else { + for( i = 0; i < Len; i++, pData++ ){ + *pData = double(*rp++); + } + } + } + else { // 8bits + union { + struct { + BYTE low; + BYTE high; + }bd; + SHORT wd; + }data; + data.bd.low = 0; + BYTE *rp = (BYTE *)hp->lpData; + if( m_IWFX.nChannels == 2 ){ + if( m_SoundStereo == 1 ){ // Left + for( i = 0; i < Len; i++, pData++ ){ + data.bd.high = BYTE((*rp++) - 128); + *pData = double(data.wd); + rp++; + } + } + else { // Right + for( i = 0; i < Len; i++, pData++ ){ + rp++; + data.bd.high = BYTE((*rp++) - 128); + *pData = double(data.wd); + } + } + } + else { + for( i = 0; i < Len; i++, pData++ ){ + data.bd.high = BYTE((*rp++) - 128); + *pData = double(data.wd); + } + } + } + hp->dwBytesRecorded = NULL; + ::waveInAddBuffer(m_hin, hp, sizeof(WAVEHDR)); + m_InBC--; // 1命令で展開されるので CriticalSection は不要 + m_InRP++; + if( m_InRP >= m_InFifoSize){ + m_InRP = 0; + } + return TRUE; +} +//--------------------------------------------------------------------------- +//void CALLBACK WaveProc(hWave, uMsg, dwInstance, dwParam1, dwParam2) +// +//HWAVE hWave; /* ウェーブフォーム デバイスのハンドル */ +//UINT uMsg; /* 送るメッセージ */ +//DWORD dwInstance; /* インスタンス データ */ +//DWORD dwParam1; /* アプリケーション定義のパラメータ */ +//DWORD dwParam2; /* アプリケーション定義のパラメータ */ +void CALLBACK WaveInProc(HWAVE m_hin, UINT uMsg, CWave* pWave, DWORD dwParam1, DWORD dwParam2 ) +{ + if( uMsg == MM_WIM_DATA ){ + ::EnterCriticalSection(&pWave->m_InCS); + pWave->m_InBC++; + pWave->m_InWP++; + if( pWave->m_InWP >= pWave->m_InFifoSize ) pWave->m_InWP = 0; + if( pWave->m_InBC > pWave->m_InFifoSize ) pWave->m_InOver = TRUE; + if(pWave->m_InWait){ + pWave->m_InWait--; + ::SetEvent(pWave->m_InEvent); + } + ::LeaveCriticalSection(&pWave->m_InCS); + } +} +//--------------------------------------------------------------------------- +// サウンドカードの出力でのオープン +// WFX.wFormatTag = WAVE_FORMAT_PCM; +// WFX.nChannels = 1; +// WFX.wBitsPerSample = 16; +// WFX.nSamplesPerSec = 11025; +// WFX.nBlockAlign = WORD(WFX.nChannels *(WFX.wBitsPerSample/8)); +// WFX.nAvgBytesPerSec = WFX.nBlockAlign * WFX.nSamplesPerSec; +// WFX.cbSize = 0; +BOOL __fastcall CWave::OutOpen(LPWAVEFORMATEX pWFX, UINT IDDevice, DWORD Size) +{ + if( m_pDLL ){ + m_OutOpen = m_pDLL->OutOpen(pWFX->nSamplesPerSec, Size); + if( !m_OutOpen ) PumpMessages(); + return m_OutOpen; + } + if( m_OutOpen ) OutAbort(); + m_Error = 0; + m_OutBCC = 0x7fffffff; + m_OutWait = FALSE; + m_OutUnder = FALSE; + m_OutWP = m_OutRP = m_OutBC = 0; + m_OWFX = *pWFX; + m_OutBuffSize = Size * (m_OWFX.wBitsPerSample/8) * m_OWFX.nChannels; + m_OutMemSize = sizeof(WAVEHDR) + m_OutBuffSize; + if( m_OutMemSize & 3 ) m_OutMemSize += 4 - (m_OutMemSize & 3); + m_OutAllocSize = m_OutMemSize * m_OutFifoSize; + m_OutEvent = ::CreateEvent(NULL, FALSE,FALSE,NULL); + if( (m_Error = ::waveOutOpen( &m_hout, IDDevice , pWFX, (DWORD)WaveOutProc, (DWORD)this, CALLBACK_FUNCTION ) ) != MMSYSERR_NOERROR ){ + OutAbort(); + return FALSE; + } + if( (m_Error = ::waveOutPause(m_hout))!= MMSYSERR_NOERROR ){ + OutAbort(); + return FALSE; + } + // バッファーの準備 + m_pOutBase = new char[m_OutAllocSize]; + ::VirtualLock(m_pOutBase, m_OutAllocSize); + memset(m_pOutBase, 0, m_OutAllocSize); + LPSTR p = m_pOutBase; + for(int i = 0; i < m_OutFifoSize; i++, p += m_OutMemSize ){ + m_pOutBuff[i] = (WAVEHDR *)p; + ((WAVEHDR *)p)->dwBufferLength = m_OutBuffSize; + ((WAVEHDR *)p)->dwFlags = 0; + ((WAVEHDR *)p)->dwUser = NULL; + ((WAVEHDR *)p)->dwLoops = NULL; + ((WAVEHDR *)p)->lpData = p + sizeof(WAVEHDR); + if( (m_Error = ::waveOutPrepareHeader(m_hout, (WAVEHDR *)p, sizeof(WAVEHDR)) ) != MMSYSERR_NOERROR ){ + OutAbort(); + return FALSE; + } + } + m_OutOpen = TRUE; + m_OutFirst = TRUE; + return TRUE; +} +#if 0 +//--------------------------------------------------------------------------- +DWORD __fastcall CWave::GetOutVolume(void) +{ + if( !m_OutOpen ){ + return 0x8000; + } + DWORD vol; + ::waveOutGetVolume(m_hout, &vol); + return vol; +} +//--------------------------------------------------------------------------- +BOOL __fastcall CWave::SetOutVolume(DWORD vol) +{ + if( !m_OutOpen ){ + return FALSE; + } + ::waveOutSetVolume(m_hout, vol); + return TRUE; +} +#endif +//--------------------------------------------------------------------------- +BOOL __fastcall CWave::OutWrite(double *pData, int Len) +{ + if( m_pDLL ){ + return m_pDLL->OutWrite(pData, Len); + } + if( !Len ) return 0; + int i; + if( !m_OutOpen ){ + m_Error = 1; + return FALSE; + } + if( m_OutUnder ){ + m_Error = 1; + OutAbort(); + return FALSE; + } + + // 送信バッファ空き待ち + EnterCriticalSection(&m_OutCS); + if( m_OutBC >= m_OutFifoSize ){ + m_OutWait++; + ::LeaveCriticalSection(&m_OutCS); + if( ::WaitForSingleObject( m_OutEvent, WAVE_TIMEOUT_EVENT ) != WAIT_OBJECT_0 ){ + m_Error = 2; + OutAbort(); + return FALSE; + } + } + else { + ::LeaveCriticalSection(&m_OutCS); + } + + // データの変換 + LPWAVEHDR hp = m_pOutBuff[m_OutWP]; + if(m_OWFX.wBitsPerSample == 16){ // 16bits + SHORT *wp = (SHORT *)hp->lpData; + if( m_OWFX.nChannels == 2 ){ + if( m_StereoTX ){ + if( m_SoundStereo == 1 ){ // Left + for( i = 0; i < Len; i++, pData++ ){ + *wp++ = (SHORT)(*pData); + *wp++ = 0; + } + } + else { // Right + for( i = 0; i < Len; i++, pData++ ){ + *wp++ = 0; + *wp++ = (SHORT)(*pData); + } + } + } + else { + for( i = 0; i < Len; i++, pData++ ){ + *wp++ = (SHORT)(*pData); + *wp++ = (SHORT)(*pData); + } + } + } + else { + for( i = 0; i < Len; i++, pData++ ){ + *wp++ = (SHORT)(*pData); + } + } + } + else { // 8bits + BYTE *wp = (BYTE *)hp->lpData; + union { + struct { + BYTE low; + BYTE high; + }bd; + SHORT wd; + }data; + if( m_OWFX.nChannels == 2 ){ + for( i = 0; i < Len; i++, pData++ ){ + data.wd = (SHORT)((*pData) + 32768); + *wp++ = data.bd.high; + *wp++ = data.bd.high; + } + } + else { + for( i = 0; i < Len; i++, pData++ ){ + data.wd = (SHORT)((*pData) + 32768); + *wp++ = data.bd.high; + } + } + } + ::waveOutWrite(m_hout, hp, sizeof(WAVEHDR) ); + m_OutBC++; // 1命令で展開されるので CriticalSection は不要 + if( m_OutFirst ){ + if( (m_OutBC >= 8) || (m_OutBC >= (m_OutFifoSize-1)) ){ + m_OutFirst = FALSE; + ::waveOutRestart( m_hout ); + } + } + m_OutWP++; + if( m_OutWP >= m_OutFifoSize){ + m_OutWP = 0; + } + return TRUE; +} +//--------------------------------------------------------------------------- +void __fastcall CWave::OutFlush() +{ + if( m_pDLL ){ + m_pDLL->OutFlush(); + return; + } + if(m_hout != NULL){ + // バッファ送信待ち + while(1){ + ::EnterCriticalSection(&m_OutCS); + if( m_OutBC > 0 ){ // 未送出データが存在する場合 + m_OutWait++; + ::LeaveCriticalSection(&m_OutCS); + if( ::WaitForSingleObject( m_OutEvent, WAVE_TIMEOUT_EVENT ) != WAIT_OBJECT_0 ){ + m_Error = 2; + break; + } + } + else { + ::LeaveCriticalSection(&m_OutCS); + break; + } + } + } +} +//--------------------------------------------------------------------------- +void __fastcall CWave::OutAbort() +{ + if( m_pDLL ){ + m_pDLL->OutAbort(); + m_OutOpen = FALSE; + PumpMessages(); + return; + } + if(m_hout != NULL){ + ::waveOutReset(m_hout); + ::Sleep(1); // for the timing + // バッファの解放 + if( m_pOutBase != NULL ){ + for(int i = 0; i < m_OutFifoSize; i++ ){ + if( m_pOutBuff[i] != NULL ){ + if( m_pOutBuff[i]->dwFlags & WHDR_PREPARED ){ + ::waveOutUnprepareHeader(m_hout, m_pOutBuff[i], sizeof(WAVEHDR)); + } + } + } + } + ::waveOutClose(m_hout); + m_hout = NULL; + if( m_pOutBase != NULL ){ + ::VirtualUnlock(m_pOutBase, m_OutAllocSize); + delete m_pOutBase; + m_pOutBase = NULL; + } + } + if(m_OutEvent != NULL){ + ::CloseHandle(m_OutEvent); + m_OutEvent = NULL; + } + m_OutOpen = FALSE; +} +//--------------------------------------------------------------------------- +//void CALLBACK WaveProc(hWave, uMsg, dwInstance, dwParam1, dwParam2) +// +//HWAVE hWave; /* ウェーブフォーム デバイスのハンドル */ +//UINT uMsg; /* 送るメッセージ */ +//DWORD dwInstance; /* インスタンス データ */ +//DWORD dwParam1; /* アプリケーション定義のパラメータ */ +//DWORD dwParam2; /* アプリケーション定義のパラメータ */ +void CALLBACK WaveOutProc(HWAVE m_hout, UINT uMsg, CWave* pWave, DWORD dwParam1, DWORD dwParam2 ) +{ + if( uMsg == WOM_DONE ){ + EnterCriticalSection(&pWave->m_OutCS); + pWave->m_OutBCC--; + pWave->m_OutBC--; + pWave->m_OutRP++; + if( pWave->m_OutRP >= pWave->m_OutFifoSize) pWave->m_OutRP = 0; + if( !pWave->m_OutBC ) pWave->m_OutUnder = TRUE; + if(pWave->m_OutWait){ + pWave->m_OutWait--; + SetEvent(pWave->m_OutEvent); + } + LeaveCriticalSection(&pWave->m_OutCS); + } +} + +//--------------------------------------------------------------------------- +int __fastcall CWave::GetInBC(void) +{ + if( m_pDLL ){ + return m_pDLL->GetInBC(); + } + else { + return m_InBC; + } +} +//--------------------------------------------------------------------------- +int __fastcall CWave::GetOutBC(void) +{ + if( m_pDLL ){ + return m_pDLL->GetOutBC(); + } + else { + return m_OutBC; + } +} +//--------------------------------------------------------------------------- +int __fastcall CWave::GetOutBCC(void) +{ + if( m_pDLL ){ + return m_pDLL->GetOutBCC(); + } + else { + return m_OutBCC; + } +} +//--------------------------------------------------------------------------- +void __fastcall CWave::SetOutBCC(int count) +{ + if( m_pDLL ){ + m_pDLL->SetOutBCC(count); + } + else { + m_OutBCC = count; + } +} +//--------------------------------------------------------------------------- +int __fastcall CWave::IsInBufCritical(void) +{ + if( m_pDLL ){ + return m_pDLL->IsInBufCritical(); + } + else { + return ( m_InBC >= (m_InFifoSize/2) ) ? 1 : 0; + } +} +//--------------------------------------------------------------------------- +int __fastcall CWave::IsOutBufCritical(void) +{ + if( m_pDLL ){ + return m_pDLL->IsOutBufCritical(); + } + else { + return (m_OutBC <= (m_OutFifoSize/2)) ? 1 : 0; + } +} +//--------------------------------------------------------------------------- +int __fastcall CWave::IsOutBufFull(void) +{ + if( m_pDLL ){ + return m_pDLL->IsOutBufFull(); + } + else { + return (m_OutBC >= m_OutFifoSize) ? 1 : 0; + } +} +//--------------------------------------------------------------------------- +void __fastcall CWave::SetPTT(LONG tx) +{ + if( m_pDLL ) m_pDLL->SetPTT(tx); +} +//--------------------------------------------------------------------------- +int __fastcall CWave::GetTimeout(void) +{ + if( m_pDLL ){ + return m_pDLL->GetTimeout(); + } + else { + return 5000; + } +} +//--------------------------------------------------------------------------- +void __fastcall CWave::UpdateDevice(int ID) +{ + if( ID == -2 ){ + if( (m_pDLL == NULL) || m_pDLL->IsNameChange() ){ + if( m_pDLL ) delete m_pDLL; + m_pDLL = new CXWave(sys.m_SoundMMW.c_str()); + } + } + else if( m_pDLL != NULL ){ + delete m_pDLL; + m_pDLL = NULL; + } +} +//--------------------------------------------------------------------------- +void __fastcall CWave::PumpMessages(void) +{ + if( m_pDLL ){ + m_pDLL->PumpMessages(); + } +} +//*************************************************************************** +// CXWave class +//--------------------------------------------------------------------------- +__fastcall CXWave::CXWave(LPCSTR pName) +{ + m_ItemName = pName; + + char Name[MAX_PATH]; + if( !*GetEXT(pName) ){ + wsprintf(Name, "%s.mmw", pName); + pName = Name; + } + + m_hLib = ::LoadLibrary(pName); + if( m_hLib ){ + + fmmwPumpMessages = PROC(mmwPumpMessages); + fmmwSetPTT = PROC(mmwSetPTT); + fmmwGetTimeout = PROC(mmwGetTimeout); + + fmmwInOpen = PROC(mmwInOpen); + fmmwInClose = PROC(mmwInClose); + fmmwInRead = PROC(mmwInRead); + + fmmwGetInExist = PROC(mmwGetInExist); + fmmwIsInCritical = PROC(mmwIsInCritical); + + fmmwOutOpen = PROC(mmwOutOpen); + fmmwOutAbort = PROC(mmwOutAbort); + fmmwOutFlush = PROC(mmwOutFlush); + fmmwOutWrite = PROC(mmwOutWrite); + + fmmwIsOutCritical = PROC(mmwIsOutCritical); + fmmwIsOutFull = PROC(mmwIsOutFull); + fmmwGetOutRemaining = PROC(mmwGetOutRemaining); + fmmwGetOutCounter = PROC(mmwGetOutCounter); + fmmwSetOutCounter = PROC(mmwSetOutCounter); + + + if( !m_hLib ){ + FreeLib(); + } + } +} +//--------------------------------------------------------------------------- +__fastcall CXWave::~CXWave(void) +{ + if( m_hLib ){ + fmmwOutAbort(); + fmmwInClose(); + } + FreeLib(); +} +//--------------------------------------------------------------------------- +FARPROC __fastcall CXWave::GetProc(LPCSTR pName) +{ + if( !m_hLib ) return NULL; + + FARPROC fn = ::GetProcAddress(m_hLib, pName+1); //ja7ude 0521 + if( fn == NULL ){ + fn = ::GetProcAddress(m_hLib, pName); + if( fn == NULL ) FreeLib(); + } + return fn; +} +//--------------------------------------------------------------------------- +void __fastcall CXWave::FreeLib(void) +{ + if( m_hLib ){ + FreeLibrary(m_hLib); + m_hLib = NULL; + } +} +//--------------------------------------------------------------------------- +BOOL __fastcall CXWave::IsNameChange(void) +{ + return strcmpi(m_ItemName.c_str(), sys.m_SoundMMW.c_str()); +} +//--------------------------------------------------------------------------- +void __fastcall CXWave::PumpMessages(void) +{ + if( !IsLib() ) return; + + fmmwPumpMessages(); +} +//--------------------------------------------------------------------------- +BOOL __fastcall CXWave::InOpen(int sampfreq, int size) +{ + if( !IsLib() ) return FALSE; + + return fmmwInOpen(sampfreq, size); +} +//--------------------------------------------------------------------------- +void __fastcall CXWave::InClose(void) +{ + if( !IsLib() ) return; + + fmmwInClose(); +} +//--------------------------------------------------------------------------- +BOOL __fastcall CXWave::InRead(double *p, int len) +{ + if( !IsLib() ) return FALSE; + + int r = fmmwInRead(m_InBuff); + if( r ){ + SHORT *s = m_InBuff; + for( int i = 0; i < len; i++ ){ + *p++ = *s++; + } + } + return r; +} +//--------------------------------------------------------------------------- +int __fastcall CXWave::GetInBC(void) +{ + if( !IsLib() ) return 0; + return fmmwGetInExist(); +} +//--------------------------------------------------------------------------- +int __fastcall CXWave::IsInBufCritical(void) +{ + if( !IsLib() ) return 0; + return fmmwIsInCritical(); +} +//--------------------------------------------------------------------------- +BOOL __fastcall CXWave::OutOpen(int sampfreq, int size) +{ + if( !IsLib() ) return FALSE; + return fmmwOutOpen(sampfreq, size); +} +//--------------------------------------------------------------------------- +void __fastcall CXWave::OutFlush(void) +{ + if( !IsLib() ) return; + fmmwOutFlush(); +} +//--------------------------------------------------------------------------- +void __fastcall CXWave::OutAbort(void) +{ + if( !IsLib() ) return; + fmmwOutAbort(); +} +//--------------------------------------------------------------------------- +BOOL __fastcall CXWave::OutWrite(double *p, int len) +{ + if( !IsLib() ) return FALSE; + SHORT *t = m_OutBuff; + for( int i = 0; i < len; i++ ){ + *t++ = *p++; + } + return fmmwOutWrite(m_OutBuff); +} +//--------------------------------------------------------------------------- +int __fastcall CXWave::GetOutBC(void) +{ + if( !IsLib() ) return 0; + return fmmwGetOutRemaining(); +} +//--------------------------------------------------------------------------- +int __fastcall CXWave::GetOutBCC(void) +{ + if( !IsLib() ) return 0; + return fmmwGetOutCounter(); +} +//--------------------------------------------------------------------------- +void __fastcall CXWave::SetOutBCC(int count) +{ + if( !IsLib() ) return; + fmmwSetOutCounter(count); +} +//--------------------------------------------------------------------------- +int __fastcall CXWave::IsOutBufCritical(void) +{ + if( !IsLib() ) return 0; + return fmmwIsOutCritical(); +} +//--------------------------------------------------------------------------- +int __fastcall CXWave::IsOutBufFull(void) +{ + if( !IsLib() ) return 0; + return fmmwIsOutFull(); +} +//--------------------------------------------------------------------------- +void __fastcall CXWave::SetPTT(int tx) +{ + if( !IsLib() ) return; + fmmwSetPTT(tx); +} +//--------------------------------------------------------------------------- +int __fastcall CXWave::GetTimeout(void) +{ + if( !IsLib() ) return 200; + return fmmwGetTimeout(); +} +//--------------------------------------------------------------------------- + diff --git a/Wave.h b/Wave.h new file mode 100644 index 0000000..f21fe66 --- /dev/null +++ b/Wave.h @@ -0,0 +1,196 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +#ifndef WAVE_H +#define WAVE_H +//--------------------------------------------------------------------------- +#include +#include "mmw.h" +#include "ComLib.h" +//--------------------------------------------------------------------------- +#ifndef PROC +#define PROC(Key) ((t##Key)GetProc("_" #Key)) +#endif +//--------------------------------------------------------------------------- +class CXWave +{ +private: + AnsiString m_ItemName; + //HANDLE m_hLib; //ja7ude 0521 + HINSTANCE m_hLib; + + SHORT m_InBuff[8192]; + SHORT m_OutBuff[8192]; + + tmmwPumpMessages fmmwPumpMessages; + tmmwGetTimeout fmmwGetTimeout; + tmmwSetPTT fmmwSetPTT; + + tmmwInOpen fmmwInOpen; + tmmwInClose fmmwInClose; + tmmwInRead fmmwInRead; + + tmmwGetInExist fmmwGetInExist; + tmmwIsInCritical fmmwIsInCritical; + + tmmwOutOpen fmmwOutOpen; + tmmwOutAbort fmmwOutAbort; + tmmwOutFlush fmmwOutFlush; + tmmwOutWrite fmmwOutWrite; + + tmmwIsOutCritical fmmwIsOutCritical; + tmmwIsOutFull fmmwIsOutFull; + tmmwGetOutRemaining fmmwGetOutRemaining; + tmmwGetOutCounter fmmwGetOutCounter; + tmmwSetOutCounter fmmwSetOutCounter; + +private: + FARPROC __fastcall GetProc(LPCSTR pName); + void __fastcall FreeLib(void); + +public: + __fastcall CXWave(LPCSTR pName); + __fastcall ~CXWave(void); + inline BOOL __fastcall IsLib(void){return m_hLib != NULL;}; + BOOL __fastcall IsNameChange(void); +public: + BOOL __fastcall InOpen(int sampfreq, int size); + void __fastcall InClose(void); + BOOL __fastcall InRead(double *p, int len); + + int __fastcall GetInBC(void); + int __fastcall IsInBufCritical(void); + + BOOL __fastcall OutOpen(int sampfreq, int size); + void __fastcall OutFlush(void); + void __fastcall OutAbort(void); + BOOL __fastcall OutWrite(double *p, int len); +// inline void __fastcall OutClose(void){OutFlush(); OutAbort();}; + + int __fastcall GetOutBC(void); + int __fastcall GetOutBCC(void); + void __fastcall SetOutBCC(int count); + int __fastcall IsOutBufCritical(void); + int __fastcall IsOutBufFull(void); + + void __fastcall SetPTT(int tx); + int __fastcall GetTimeout(void); + void __fastcall PumpMessages(void); +}; +//--------------------------------------------------------------------------- +#define WAVE_TIMEOUT_EVENT 2000 // バッファリクエストのタイムアウト +#define WAVE_FIFO_MAX 32 // 循環バッファの最大個数 +//--------------------------------------------------------------------------- +class CWave +{ + friend void CALLBACK WaveInProc(HWAVE m_hin, UINT uMsg, CWave* pWave, DWORD dwParam1, DWORD dwParam2 ); + friend void CALLBACK WaveOutProc(HWAVE m_hout, UINT uMsg, CWave* pWave, DWORD dwParam1, DWORD dwParam2 ); + +public: + int m_InFifoSize; + int m_OutFifoSize; + int m_SoundStereo; + int m_StereoTX; + + int m_InDevs; + int m_OutDevs; + AnsiString m_tInDevName[16]; + AnsiString m_tOutDevName[16]; +private: + LPWAVEHDR m_pInBuff[WAVE_FIFO_MAX]; // 入力バッファ + LPWAVEHDR m_pOutBuff[WAVE_FIFO_MAX]; // 出力バッファ + WAVEFORMATEX m_OWFX; // 出力フォーマット + WAVEFORMATEX m_IWFX; // 入力フォーマット + + CRITICAL_SECTION m_InCS; + CRITICAL_SECTION m_OutCS; + + HANDLE m_InEvent; + HANDLE m_OutEvent; + BOOL m_InWait; + BOOL m_InOver; + BOOL m_OutWait; + BOOL m_OutUnder; + + int m_InWP; + int m_InRP; + + int m_OutWP; + int m_OutRP; + + int m_Error; + BOOL m_InOpen; + BOOL m_OutOpen; + + LPSTR m_pInBase; + LPSTR m_pOutBase; + int m_InBuffSize; + int m_InMemSize; + int m_InAllocSize; + int m_OutBuffSize; + int m_OutMemSize; + int m_OutAllocSize; + BOOL m_OutFirst; + //HWAVE m_hin; //ja7ude 0521 + //HWAVE m_hout; //ja7ude 0521 + HWAVEIN m_hin; + HWAVEOUT m_hout; + + volatile int m_InBC; + volatile int m_OutBC; + volatile int m_OutBCC; + + CXWave *m_pDLL; +public: + __fastcall CWave(void); + __fastcall ~CWave(); +// BOOL __fastcall IsFormatSupported(LPWAVEFORMATEX pWFX, UINT IDDevice); + BOOL __fastcall InOpen(LPWAVEFORMATEX pWFX, UINT IDDevice, DWORD Size); + inline __fastcall BOOL IsInOpen(){return m_InOpen;}; + BOOL __fastcall InRead(double *pData, int Len); + void __fastcall InClose(); + BOOL __fastcall OutOpen(LPWAVEFORMATEX pWFX, UINT IDDevice, DWORD Size); + inline __fastcall BOOL IsOutOpen(){return m_OutOpen;}; + BOOL __fastcall OutWrite( double *pData, int Len); + void __fastcall OutFlush(); + void __fastcall OutAbort(); + void __fastcall OutClose(){OutFlush();OutAbort();}; +// DWORD __fastcall GetOutVolume(void); +// BOOL __fastcall SetOutVolume(DWORD vol); + + int __fastcall GetInBC(void); + int __fastcall GetOutBC(void); + int __fastcall GetOutBCC(void); + void __fastcall SetOutBCC(int count); + + inline int __fastcall IsInBufNull(void){return !GetInBC();}; + int __fastcall IsInBufCritical(void); + int __fastcall IsOutBufCritical(void); + int __fastcall IsOutBufFull(void); + + void __fastcall SetPTT(LONG tx); + int __fastcall GetTimeout(void); + void __fastcall UpdateDevice(int ID); + void __fastcall PumpMessages(void); + + void __fastcall GetDeviceName(void); +}; +//--------------------------------------------------------------------------- +#endif + diff --git a/ZoomView.cpp b/ZoomView.cpp new file mode 100644 index 0000000..d853a8e --- /dev/null +++ b/ZoomView.cpp @@ -0,0 +1,208 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "ZoomView.h" +#include "ComLib.h" +//--------------------------------------------------------------------- +#pragma resource "*.dfm" +//--------------------------------------------------------------------- +__fastcall TZoomViewDlg::TZoomViewDlg(TComponent* AOwner) + : TForm(AOwner) +{ + FormStyle = ((TForm *)AOwner)->FormStyle; + Font->Name = ((TForm *)AOwner)->Font->Name; + Font->Charset = ((TForm *)AOwner)->Font->Charset; + pBitmap = NULL; + pBitmapS = NULL; + + m_MaxX = ::GetSystemMetrics(SM_CXFULLSCREEN); + m_MaxY = ::GetSystemMetrics(SM_CYFULLSCREEN); + m_DisEvent = 0; +} +//--------------------------------------------------------------------- +__fastcall TZoomViewDlg::~TZoomViewDlg() +{ + if( pBitmapS != NULL ){ + delete pBitmapS; + } +} +//--------------------------------------------------------------------- +void __fastcall TZoomViewDlg::SetInitSize(int xw, int yw) +{ + m_DisEvent++; + ClientWidth = xw; + ClientHeight = yw; + m_DisEvent--; +} +//--------------------------------------------------------------------- +void __fastcall TZoomViewDlg::UpdateTitle(void) +{ + if( pBitmap == NULL ) return; + + char bf[256]; + + strcpy(bf, MsgEng ? "Picture viewer" : "画像表示"); + + char bbf[64]; + sprintf(bbf, " - Source:%dx%d", pBitmap->Width, pBitmap->Height); + strcat(bf, bbf); + if( (pBitmap->Width != m_ViewXW) || (pBitmap->Height != m_ViewYW) ){ + sprintf(bbf, ", View:%dx%d", m_ViewXW, m_ViewYW); + strcat(bf, bbf); + if( pBitmapS != NULL ) strcat(bf, " (Smoothing)"); + } + Caption = bf; +} +//--------------------------------------------------------------------- +void __fastcall TZoomViewDlg::Execute(Graphics::TBitmap *pbmp, int sw) +{ + pBitmap = pbmp; + if( pbmp->Width != 320 ){ + int xw = pbmp->Width; + int yw = pbmp->Height; + if( (xw > m_MaxX) || (yw > m_MaxY) ){ + if( xw > m_MaxX ) xw = m_MaxX; + if( yw > m_MaxY ) yw = m_MaxY; + KeepAspect(xw, yw, pbmp->Width, pbmp->Height); + } + m_DisEvent++; + ClientWidth = xw; + ClientHeight = yw; + m_DisEvent--; +// ClientWidth = pbmp->Width; +// ClientHeight = pbmp->Height; + } + Timer->Enabled = sw; + UpdateViewSize(); + UpdateTitle(); + ShowModal(); + Timer->Enabled = FALSE; +} +//--------------------------------------------------------------------- +void __fastcall TZoomViewDlg::FormPaint(TObject *Sender) +{ + if( pBitmap == NULL ) return; + if( pBitmapS != NULL ){ + int x = (ClientWidth - pBitmapS->Width)/2; + int y = (ClientHeight - pBitmapS->Height)/2; + Canvas->Draw(x, y, pBitmapS); + } + else { + UpdateViewSize(); + TRect rc; + rc.Left = (ClientWidth - m_ViewXW)/2; + rc.Top = (ClientHeight - m_ViewYW)/2; + rc.Right = rc.Left + m_ViewXW; + rc.Bottom = rc.Top + m_ViewYW; + ::SetStretchBltMode(Canvas->Handle, HALFTONE); + Canvas->StretchDraw(rc, (TGraphic*)pBitmap); + } +#if 0 + char bf[256]; + sprintf(bf, "%ux%u", ClientWidth, ClientHeight); + Canvas->Font->Color = clBlack; + Canvas->TextOut(0, 0, bf); +#endif +} +//--------------------------------------------------------------------- +void __fastcall TZoomViewDlg::TimerTimer(TObject *Sender) +{ + if( (Visible == TRUE) && (pBitmapS == NULL) ) FormPaint(NULL); +} +//--------------------------------------------------------------------------- +void __fastcall TZoomViewDlg::FormResize(TObject *Sender) +{ + if( m_DisEvent ) return; + m_DisEvent++; + if( ClientHeight < 100 ) ClientHeight = 100; + if( ClientWidth < 100 ) ClientWidth = 100; + + if( (ClientWidth != pBitmap->Width) || (ClientHeight != pBitmap->Height) ){ + double XW = pBitmap->Width; + double YW = pBitmap->Height; + double xw = ClientWidth; + double yw = ClientHeight; + if( Width > m_MaxX ) xw = m_MaxX; + if( Height > m_MaxY ) yw = m_MaxY; + + double xv = (xw / Width) * XW; + double yv = (yw / Height) * YW; + if( yv < xv ){ + yw = xw * YW / XW; + } + else { + xw = yw * XW / YW; + } + if( ABS(xw - ClientWidth) >= 2 ) ClientWidth = xw; + if( ABS(yw - ClientHeight) >= 2 ) ClientHeight = yw; + UpdateViewSize(); + } + else { + delete pBitmapS; + pBitmapS = NULL; + UpdateTitle(); + } + if( pBitmapS != NULL ){ + StretchCopy(pBitmap); + } + Invalidate(); + m_DisEvent--; + UpdateTitle(); +} +//--------------------------------------------------------------------------- +// 高度な伸縮コピー +void __fastcall TZoomViewDlg::StretchCopy(Graphics::TBitmap *pbmp) +{ + if( pBitmapS == NULL ){ + pBitmapS = new Graphics::TBitmap; + } + pBitmapS->PixelFormat = pf24bit; + pBitmapS->Width = m_ViewXW; + pBitmapS->Height = m_ViewYW; + ::StretchCopy(pBitmapS, NULL, pbmp, NULL); +} +//--------------------------------------------------------------------------- +void __fastcall TZoomViewDlg::FormClick(TObject *Sender) +{ + if( (pBitmap->Width == ClientWidth) && (pBitmap->Height == ClientHeight) ) return; + if( pBitmapS != NULL ){ + delete pBitmapS; + pBitmapS = NULL; + } + else { + StretchCopy(pBitmap); + } + UpdateTitle(); + Invalidate(); +} +//--------------------------------------------------------------------------- +void __fastcall TZoomViewDlg::UpdateViewSize(void) +{ + m_ViewXW = ClientWidth; + m_ViewYW = ClientHeight; + if( WindowState == wsMaximized ){ + KeepAspect(m_ViewXW, m_ViewYW, pBitmap->Width, pBitmap->Height); + } +} + + diff --git a/ZoomView.dfm b/ZoomView.dfm new file mode 100644 index 0000000..a73351a Binary files /dev/null and b/ZoomView.dfm differ diff --git a/ZoomView.h b/ZoomView.h new file mode 100644 index 0000000..6c72462 --- /dev/null +++ b/ZoomView.h @@ -0,0 +1,63 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//---------------------------------------------------------------------------- +#ifndef ZoomViewH +#define ZoomViewH +//---------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//---------------------------------------------------------------------------- +class TZoomViewDlg : public TForm +{ +__published: + TTimer *Timer;void __fastcall TimerTimer(TObject *Sender); + void __fastcall FormResize(TObject *Sender); + void __fastcall FormPaint(TObject *Sender); + void __fastcall FormClick(TObject *Sender); +private: + Graphics::TBitmap *pBitmap; + Graphics::TBitmap *pBitmapS; + + int m_MaxX; + int m_MaxY; + int m_ViewXW; + int m_ViewYW; + int m_DisEvent; + void __fastcall UpdateTitle(void); + void __fastcall UpdateViewSize(void); +public: + virtual __fastcall TZoomViewDlg(TComponent* AOwner); + __fastcall ~TZoomViewDlg(); + + void __fastcall Execute(Graphics::TBitmap *pbmp, int sw); + void __fastcall StretchCopy(Graphics::TBitmap *pbmp); + void __fastcall SetInitSize(int xw, int yw); +}; +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +#endif diff --git a/country.cpp b/country.cpp new file mode 100644 index 0000000..77bb694 --- /dev/null +++ b/country.cpp @@ -0,0 +1,351 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +/************************************************************************ + カントリ識別処理モジュール + + Copyright (C) JE3HHT 1993-2000. +************************************************************************/ +//--------------------------------------------------------------------------- +#include //ja7ude 0521 +#pragma hdrstop + +#include "ComLib.h" +#include "Country.h" +#include "string.h" +#include "stdlib.h" + +CCountry Cty; +/*#$% +======================================================== + 文字列から指定の文字をクリップする +-------------------------------------------------------- + s : 文字列のポインタ +-------------------------------------------------------- +-------------------------------------------------------- +======================================================== +*/ +static char *_delchr(char *s, char c) +{ + char *p; + + for( p = s; *p; p++ ){ + if( *p == c ){ + strcpy(p, p+1); + p--; + } + } + return(s); +} + +/*#$% +====================================================== + 異なる文字列のポインタを返す +------------------------------------------------------ + n : 範囲数の格納位置のポインタ + t : プリフィックスのポインタ + p : プリフィックスのポインタ +------------------------------------------------------ +------------------------------------------------------ +====================================================== +*/ +static LPSTR lcmpp(int *n, LPSTR s, LPSTR p) +{ + LPSTR t; + + for( t = s; *p && *t; p++, t++ ){ + if( *p != *t ){ + *n = (*p - *t) + 1; + if( *n > 26 ) *n = 26; + return(t); + } + } + *n = 0; + return(s); +} + +/*#$% +====================================================== + 文字列の比較を行う +------------------------------------------------------ + t : 対象文字列 + s : 基準文字列 +------------------------------------------------------ +------------------------------------------------------ +====================================================== +*/ +static int strcmpv(LPCSTR t, LPCSTR s) +{ + for( ; *s; s++, t++ ){ + if( *t != *s ) return(1); + } + return(0); +} + +static int svf; /* 完全一致フラグ */ +/*#$% +================================================================ + プリフィックス検索用文字列比較 +---------------------------------------------------------------- +---------------------------------------------------------------- +---------------------------------------------------------------- +================================================================ +*/ +static int _strcmp(LPCSTR t, LPCSTR v) +{ +/* printf( "<%s>-<%s>\n", v, t ); */ + for( ; *v; v++, t++ ){ + if( *v == '*' ){ + for( v++; *t && strcmpv(t, v); t++ ); + if( !*t ) return(1); + } + else if( *v == '\\' ){ + if( *t ) return(1); + } + else if( (*v!='?') && (*v != *t) ){ + return(1); + } + } + if( svf && *t ) return(1); + return(0); +} + +/*#$% +====================================================== + コンストラクター +------------------------------------------------------ +------------------------------------------------------ +------------------------------------------------------ +====================================================== +*/ +CCountry::CCountry() +{ + Init(); +} + +CCountry::~CCountry(void) +{ + Free(); +} + +/*#$% +====================================================== + DXCC定義領域を開放する +------------------------------------------------------ +------------------------------------------------------ +------------------------------------------------------ +====================================================== +*/ +void CCountry::Init(void) +{ + cmax = 0; + memset(ctl, 0, sizeof(ctl)); +} + +/*#$% +====================================================== + DXCC定義領域を開放する +------------------------------------------------------ +------------------------------------------------------ +------------------------------------------------------ +====================================================== +*/ +void CCountry::Free(void) +{ + int i; + CTL *cp; + + for( cp = ctl, i = 0; i < cmax; i++, cp++ ){ + if( cp->Name != NULL ) delete cp->Name; + if( cp->Code != NULL ) delete cp->Code; + if( cp->QTH != NULL ) delete cp->QTH; + if( cp->Cont != NULL ) delete cp->Cont; + if( cp->TD != NULL ) delete cp->TD; + } + Init(); +} + + +/*#$% +====================================================== + プリフィックスからカントリコードを得る +------------------------------------------------------ + p : プリフィックスのポインタ +------------------------------------------------------ + カントリコード +------------------------------------------------------ +====================================================== +*/ +int CCountry::GetNo(LPCSTR s) +{ + LPSTR p, pb, t, pp; + int i; + int j; + + if( !*s ) return(0); + for( i = 0; i < cmax; i++ ){ + strcpy(wbf, ctl[i].Code); + for( p = wbf; *p; ){ + p = StrDlm(pb, p, ','); + if( (t = strchr(pb, '-')) != NULL ){ + *t = 0; + t++; + if( (*pb == *s) || (*pb != *t) ){ + for( pp = lcmpp(&j, pb, t); j; (*pp)++, j-- ){ + if( !_strcmp(s, pb) ) return(i+1); + } + } + } + else { + if( !_strcmp(s, pb) ) return(i+1); + } + } + } + return(0); +} + +/*#$% +====================================================== + コールサインからポインタを得る +------------------------------------------------------ + p : コールサインのポインタ +------------------------------------------------------ + ポインタ +------------------------------------------------------ +====================================================== +*/ +int CCountry::GetNoP(LPCSTR p) +{ + int n; + + svf = 1; + if( (n = GetNo(p))!=0 ) return(n); + svf = 0; + if( (n = GetNo(p))!=0 ) return(n); + return(0); +} + +/*#$% +====================================================== + コールサインからカントリ名を得る +------------------------------------------------------ + p : コールサインのポインタ +------------------------------------------------------ + カントリ名のポインタ +------------------------------------------------------ +====================================================== +*/ +LPCSTR CCountry::GetCountry(LPCSTR p) +{ + if( !cmax ) return ""; + int n; + + if( !(*p) ) return("?"); + if( ((n = GetNoP(p))!=0) && (ctl[n-1].Name != NULL) ){ + strcpy(wbf, ctl[n-1].Name); + return(wbf); + } + else { + return("?"); + } +} + +/*#$% +====================================================== + コールサインから大陸名を得る +------------------------------------------------------ + p : コールサインのポインタ +------------------------------------------------------ + カントリ名のポインタ +------------------------------------------------------ +====================================================== +*/ +LPCSTR CCountry::GetCont(LPCSTR p) +{ + if( !cmax ) return ""; + int n; + + if( !(*p) ) return("?"); + if( ((n = GetNoP(p))!=0) && (ctl[n-1].Cont != NULL) ){ + strcpy(wbf, ctl[n-1].Cont); + return(wbf); + } + else { + return("?"); + } +} + +/*#$% +====================================================== + DXCC定義ファイルを読み込む +------------------------------------------------------ + fm : ファイル名のポインタ +------------------------------------------------------ +------------------------------------------------------ +====================================================== +*/ +void CCountry::Load(LPCSTR fm) +{ + FILE *fp; + LPCSTR p; + char hbf[512]; + + Free(); + if( (fp = fopen(fm, "rt"))!=NULL ){ + while( !feof(fp) ){ + if( fgets(hbf, 512, fp)!=NULL ){ + if( hbf[0] == '$' ) break; + ClipLF(hbf); + _delchr(hbf, TAB); + if( hbf[0] != '!' ){ + p = StrDlmCpy(wbf, hbf, ';', 512); + clipsp(wbf); + ctl[cmax].Name = StrDupe(wbf); + if( p != NULL ){ + p = StrDlmCpy(wbf, p, ';', 512); + clipsp(wbf); + ctl[cmax].Code = StrDupe(wbf); + } + if( p != NULL ){ + p = StrDlmCpy(wbf, p, ';', 512); + clipsp(wbf); + ctl[cmax].QTH = StrDupe(wbf); + } + if( p != NULL ){ + p = StrDlmCpy(wbf, p, ';', 512); + clipsp(wbf); + ctl[cmax].Cont = StrDupe(wbf); + } + if( p != NULL ){ + StrDlmCpy(wbf, p, ';', 512); + clipsp(wbf); + ctl[cmax].TD = StrDupe(wbf); + } + cmax++; + if( cmax >= CTMAX ) break; + } + } + } + fclose(fp); + } + else { + WarningMB(MsgEng ? "'ARRL.DX' was not found.\r\n\r\nYou cannot use a DXCC function.\r\nThis is not a problem if you do not need it":"'ARRL.DX'が見つかりません.\r\n\r\nDXエンティティの自動判定機能は使用できません."); + } +} + diff --git a/country.h b/country.h new file mode 100644 index 0000000..b9f25cc --- /dev/null +++ b/country.h @@ -0,0 +1,60 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +#ifndef CountryH +#define CountryH + +extern LPSTR StrDupe(LPCSTR s); + +#define CTMAX 512 +typedef struct { + LPSTR Name; + LPSTR Code; + LPSTR QTH; + LPSTR Cont; + LPSTR TD; +}CTL; + +class CCountry +{ +private: + int cmax; + CTL ctl[CTMAX]; + + char wbf[512]; +public: + CCountry(); + ~CCountry(void); + + inline CTL *GetCTL(int n){ return &ctl[n];}; + void Init(void); + void Free(void); + int GetNo(LPCSTR s); + int GetNoP(LPCSTR p); + LPCSTR GetCountry(LPCSTR p); + LPCSTR GetCont(LPCSTR p); + void Load(LPCSTR fm); + inline int IsData(void){ + return cmax; + }; +}; + +extern CCountry Cty; +#endif + diff --git a/cradio.cpp b/cradio.cpp new file mode 100644 index 0000000..8f72b53 --- /dev/null +++ b/cradio.cpp @@ -0,0 +1,1058 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------------- +#include //ja7ude 0521 +#pragma hdrstop + +#include "Cradio.h" +#include "ComLib.h" + +#define WAITSTAT 0 + +CRADIOPARA RADIO; +void InitRADIOPara(void) +{ + RADIO.change = 1; + strcpy(RADIO.StrPort, "NONE"); // ポートの名前 + RADIO.BaudRate = 4800; // ボーレート + RADIO.BitLen = 1; // 0-7Bit, 1-8Bit + RADIO.Stop = 1; // 0-1Bit, 1-2Bit + RADIO.Parity = 0; // 0-PN, 1-PE, 2-PO + RADIO.flwXON = 0; // Xon/Xoff ON + RADIO.flwCTS = 0; // CTS-RTS ON + RADIO.usePTT = 0; + RADIO.Cmdxx = 0; + RADIO.CmdInit = ""; + RADIO.CmdRx = "\\$000000000F"; + RADIO.CmdTx = "\\$000000010F\\w10"; + RADIO.ByteWait = 0; + RADIO.cmdGNR = ""; + RADIO.openGNR = 0; + + RADIO.PollType = 0; + RADIO.PollInterval = 5; + RADIO.PollScan = 0; +} + +void LoadRADIOSetup(TMemIniFile *pIniFile) +{ + AnsiString as = RADIO.StrPort; + as = pIniFile->ReadString("RADIO", "PortName", as); + StrCopy(RADIO.StrPort, as.c_str(), 31); + RADIO.BaudRate = pIniFile->ReadInteger("RADIO", "BaudRate", RADIO.BaudRate); + RADIO.BitLen = pIniFile->ReadInteger("RADIO", "BitLen", RADIO.BitLen); + RADIO.Stop = pIniFile->ReadInteger("RADIO", "Stop", RADIO.Stop); + RADIO.Parity = pIniFile->ReadInteger("RADIO", "Parity", RADIO.Parity); + RADIO.flwXON = pIniFile->ReadInteger("RADIO", "flwXON", RADIO.flwXON); + RADIO.flwCTS = pIniFile->ReadInteger("RADIO", "flwCTS", RADIO.flwCTS); + RADIO.usePTT = pIniFile->ReadInteger("RADIO", "usePTT", RADIO.usePTT); + + RADIO.ByteWait = pIniFile->ReadInteger("RADIO", "ByteWait", RADIO.ByteWait); + + RADIO.Cmdxx = pIniFile->ReadInteger("RADIO", "Cmdxx", RADIO.Cmdxx); + RADIO.CmdInit = pIniFile->ReadString("RADIO", "CmdInit", RADIO.CmdInit); + RADIO.CmdRx = pIniFile->ReadString("RADIO", "CmdRx", RADIO.CmdRx); + RADIO.CmdTx = pIniFile->ReadString("RADIO", "CmdTx", RADIO.CmdTx); + + RADIO.cmdGNR = pIniFile->ReadString("RADIO", "FileGNR", RADIO.cmdGNR); + RADIO.openGNR = pIniFile->ReadInteger("RADIO", "OpenGNR", RADIO.openGNR); + + RADIO.PollType = pIniFile->ReadInteger("RADIO", "PollType", RADIO.PollType); + RADIO.PollInterval = pIniFile->ReadInteger("RADIO", "PollInterval", RADIO.PollInterval); +} +void SaveRADIOSetup(TMemIniFile *pIniFile) +{ + pIniFile->WriteString("RADIO", "PortName", RADIO.StrPort); + pIniFile->WriteInteger("RADIO", "BaudRate", RADIO.BaudRate); + pIniFile->WriteInteger("RADIO", "BitLen", RADIO.BitLen); + pIniFile->WriteInteger("RADIO", "Stop", RADIO.Stop); + pIniFile->WriteInteger("RADIO", "Parity", RADIO.Parity); + pIniFile->WriteInteger("RADIO", "flwXON", RADIO.flwXON); + pIniFile->WriteInteger("RADIO", "flwCTS", RADIO.flwCTS); + pIniFile->WriteInteger("RADIO", "usePTT", RADIO.usePTT); + + pIniFile->WriteInteger("RADIO", "ByteWait", RADIO.ByteWait); + + pIniFile->WriteInteger("RADIO", "Cmdxx", RADIO.Cmdxx); + pIniFile->WriteString("RADIO", "CmdInit", RADIO.CmdInit); + pIniFile->WriteString("RADIO", "CmdRx", RADIO.CmdRx); + pIniFile->WriteString("RADIO", "CmdTx", RADIO.CmdTx); + + pIniFile->WriteString("RADIO", "FileGNR", RADIO.cmdGNR); + pIniFile->WriteInteger("RADIO", "OpenGNR", RADIO.openGNR); + + pIniFile->WriteInteger("RADIO", "PollType", RADIO.PollType); + pIniFile->WriteInteger("RADIO", "PollInterval", RADIO.PollInterval); +} +//--------------------------------------------------------------------------- +// 注意: VCL オブジェクトのメソッドとプロパティを使用するには, Synchronize +// を使ったメソッド呼び出しでなければなりません。次に例を示します。 +// +// Synchronize(UpdateCaption); +// +// ここで, UpdateCaption は次のように記述できます。 +// +// void __fastcall CCradio::UpdateCaption() +// { +// Form1->Caption = "スレッドから書き換えました"; +// } +//--------------------------------------------------------------------------- +__fastcall CCradio::CCradio(bool CreateSuspended) + : TThread(CreateSuspended) +{ + m_CreateON = FALSE; // クリエイトフラグ + m_fHnd = NULL; // ファイルハンドル + m_wHnd = NULL; // 親のウインドウハンドル + m_uMsg = WM_USER; + m_ID = 0; // メッセージのID番号 + m_Command = 0; // スレッドへのコマンド + m_TxAbort = 0; // 送信中止フラグ + m_txwp = m_txrp = m_txcnt = 0; + m_PSKGNRId = 0; + m_OpenGNR = 0; + + m_PollCnt = 0; + m_rxcnt = 0; + m_FreqEvent = 0; + m_Freq[0] = 0; + + m_ScanAddr = 0; + m_pRadio = NULL; +} + +//--------------------------------------------------------------------------- +void __fastcall CCradio::Execute() +{ + //---- スレッドのコードをここに記述 ---- +// Priority = tpLower; + while(1){ + if( Terminated == TRUE ){ + return; + } + if( m_Command == CRADIO_CLOSE ){ + m_Command = 0; + return; + } + if( m_CreateON == TRUE ){ + if( m_txcnt ){ + if( m_pRadio != NULL ){ + if( !(m_pRadio->GetStatus() & mmrpstatusTXBUSY) ){ + m_pRadio->PutChar(m_txbuf[m_txrp]); + m_txrp++; + if( m_txrp >= RADIO_TXBUFSIZE ){ + m_txrp = 0; + } + m_txcnt--; + } + } + else if( !TxBusy() ){ + DWORD size=0; + ::WriteFile( m_fHnd, &m_txbuf[m_txrp], 1, &size, NULL ); + if( size ){ + m_txrp++; + if( m_txrp >= RADIO_TXBUFSIZE ){ + m_txrp = 0; + } + m_txcnt--; + } + if( RADIO.ByteWait ) ::Sleep(RADIO.ByteWait); + } + ::Sleep(1); + } + else if( m_pRadio != NULL ){ + if( m_pRadio->GetStatus() & mmrpstatusFREQ ){ + long fq = m_pRadio->GetFreq(); + if( fq ) UpdateFreq(double(fq)/1e4); + } + while(m_pRadio->GetStatus() & mmrpstatusRX){ + CatchPoll(m_pRadio->GetChar()); + } + ::Sleep(10); + } + else { + BYTE dmy[256]; + while(1){ + int len = RecvLen(); + if( !len ) break; + if( len >= (int)sizeof(dmy) ) len = (int)sizeof(dmy); + Read(dmy, len); + if( RADIO.PollType ){ + BYTE *p = dmy; + for( ; len; p++, len-- ){ + CatchPoll(*p); + } + } + } + ::Sleep(10); + } + } + else { + ::Sleep(10); + } + } +} +//--------------------------------------------------------------------------- +/*#$% +============================================================== + 通信回線をオープンしスレッドをアクティブにする +-------------------------------------------------------------- +PortName : 回線の名前 +pCP : COMMPARAのポインタ(ヌルの時はデフォルトで初期化) +pWnd : メッセージ送信先のウインドウクラスのポインタ(ヌルの時はメインフレームウインドウ) +nID : データ受信時のメッセージID +RBufSize : 受信バッファのサイズ(default=2048) +TBufSize : 送信バッファのサイズ(default=2048) +-------------------------------------------------------------- +TRUE/FALSE +-------------------------------------------------------------- +============================================================== +*/ +BOOL CCradio::Open(CRADIOPARA *cp, HWND hwnd, UINT uMsg, UINT nID) +{ + if( m_CreateON == TRUE ) Close(); + m_TxAbort = FALSE; + m_PSKGNRId = 0; + m_OpenGNR = 0; + if( !strcmpi(cp->StrPort, "PSKGNR") || !strcmpi(cp->StrPort, "WD5GNR") || !strcmpi(cp->StrPort, "LOGGER")){ + m_PSKGNRId = ::RegisterWindowMessage("PSKGNRFUNC"); + m_CreateON = TRUE; + if( RADIO.openGNR && (!RADIO.cmdGNR.IsEmpty()) && (strcmpi(cp->StrPort, "LOGGER")) ){ + if( FindWindow("ThunderRT6Main", NULL) == NULL ){ + ::WinExec(RADIO.cmdGNR.c_str(), SW_HIDE); + m_OpenGNR = 1; + } + } + return m_CreateON; + } + m_fHnd = ::CreateFile(cp->StrPort, GENERIC_READ | GENERIC_WRITE, + 0, NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL + ); + if( m_fHnd == INVALID_HANDLE_VALUE ){ + AnsiString as = "\\\\.\\"; + as += cp->StrPort; + m_fHnd = ::CreateFile(as.c_str(), GENERIC_READ | GENERIC_WRITE, + 0, NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL + ); + } + m_wHnd = hwnd; + m_uMsg = uMsg; + m_ID = nID; + if( m_fHnd == INVALID_HANDLE_VALUE ) goto _mmr; + // setup device buffers + if( ::SetupComm( m_fHnd, DWORD(RADIO_COMBUFSIZE), DWORD(RADIO_COMBUFSIZE) ) == FALSE ){ + ::CloseHandle(m_fHnd); +_mmr:; + m_pRadio = new CMMRadio(hwnd, uMsg); + if( m_pRadio->Open(cp->StrPort) ){ + m_CreateON = TRUE; + Priority = tpLower; + Resume(); // スレッドの実行 + return TRUE; + } + else { + delete m_pRadio; + m_pRadio = NULL; + return FALSE; + } + } + + // purge any information in the buffer + ::PurgeComm( m_fHnd, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR ); + + // set up for overlapped I/O + COMMTIMEOUTS TimeOut; + + TimeOut.ReadIntervalTimeout = 0xffffffff; + TimeOut.ReadTotalTimeoutMultiplier = 0; + TimeOut.ReadTotalTimeoutConstant = 0; + TimeOut.WriteTotalTimeoutMultiplier = 0; + TimeOut.WriteTotalTimeoutConstant = 20000; +// TimeOut.WriteTotalTimeoutConstant = 1; + if( !::SetCommTimeouts( m_fHnd, &TimeOut ) ){ + ::CloseHandle( m_fHnd ); + return FALSE; + } + ::GetCommState( m_fHnd, &m_dcb ); + m_dcb.BaudRate = cp->BaudRate; + m_dcb.fBinary = TRUE; + m_dcb.ByteSize = USHORT(cp->BitLen ? 8 : 7); + const UCHAR _tp[]={NOPARITY, EVENPARITY, ODDPARITY}; + m_dcb.Parity = _tp[cp->Parity]; + const UCHAR _ts[]={ONESTOPBIT,TWOSTOPBITS}; + m_dcb.StopBits = _ts[cp->Stop]; + if( cp->usePTT ){ + m_dcb.fRtsControl = RTS_CONTROL_DISABLE; // 送信禁止 + m_dcb.fDtrControl = DTR_CONTROL_DISABLE; // 送信禁止 + } + else { + m_dcb.fRtsControl = RTS_CONTROL_ENABLE; + } + m_dcb.fOutxCtsFlow = (cp->flwCTS && !cp->usePTT) ? TRUE : FALSE; + m_dcb.fInX = m_dcb.fOutX = cp->flwXON ? TRUE : FALSE; + m_dcb.XonChar = 0x11; + m_dcb.XoffChar = 0x13; + m_dcb.fParity = FALSE; + m_dcb.EvtChar = 0x0d; // dummy setting +// m_dcb.fTXContinueOnXoff = TRUE; + m_dcb.XonLim = USHORT(RADIO_COMBUFSIZE/4); // 1/4 of RBufSize + m_dcb.XoffLim = USHORT(RADIO_COMBUFSIZE*3/4); // 3/4 of RBufSize + m_dcb.DCBlength = sizeof( DCB ); + if( !::SetCommState( m_fHnd, &m_dcb ) ){ + ::CloseHandle( m_fHnd ); + return FALSE; + } + // get any early notifications + if( !::SetCommMask( m_fHnd, EV_RXFLAG ) ){ + ::CloseHandle(m_fHnd); + return FALSE; + } + m_CreateON = TRUE; + Priority = tpLower; + Resume(); // スレッドの実行 + return TRUE; +} +/*#$% +============================================================== + 通信回線をクローズする +-------------------------------------------------------------- +-------------------------------------------------------------- +-------------------------------------------------------------- + スレッドが終了するまで待つ +============================================================== +*/ +void CCradio::Close(void) +{ + if( m_CreateON == TRUE ){ + if( m_PSKGNRId ){ + if( (m_OpenGNR || RADIO.change) && RADIO.openGNR ) ::SendMessage(HWND_BROADCAST, m_PSKGNRId, 1 , 0); + m_PSKGNRId = 0; + } + else { + if( m_ID ){ + m_Command = CRADIO_CLOSE; // スレッド終了コマンド + Priority = tpNormal; //スレッドは通常の優先度である + WaitFor(); + } + if( m_pRadio != NULL ){ + delete m_pRadio; + m_pRadio = NULL; + } + else { + ::CloseHandle(m_fHnd); + } + } + } + m_CreateON = FALSE; + m_TxAbort = TRUE; +} +void CCradio::ReqClose(void) +{ + if( m_CreateON == TRUE ){ + if( m_PSKGNRId ){ + return; + } + else { + if( m_ID ){ + m_Command = CRADIO_CLOSE; // スレッド終了コマンド + Priority = tpNormal; //スレッドは通常の優先度である + } + } + } +} +void CCradio::WaitClose(void) +{ + if( m_CreateON == TRUE ){ + if( m_PSKGNRId ){ + if( (m_OpenGNR || RADIO.change) && RADIO.openGNR ) ::SendMessage(HWND_BROADCAST, m_PSKGNRId, 1 , 0); + m_PSKGNRId = 0; + } + else { + if( m_ID && m_Command ){ + WaitFor(); + } + if( m_pRadio != NULL ){ + delete m_pRadio; + m_pRadio = NULL; + } + else { + ::CloseHandle(m_fHnd); + } + } + m_CreateON = FALSE; + } + m_TxAbort = TRUE; +} +/*#$% +============================================================== + 受信バッファ内の格納データ長を得る +-------------------------------------------------------------- +-------------------------------------------------------------- + データの長さ +-------------------------------------------------------------- +============================================================== +*/ +DWORD CCradio::RecvLen(void) +{ + COMSTAT ComStat; + DWORD dwErrorFlags; + + ::ClearCommError( m_fHnd, &dwErrorFlags, &ComStat ); + return ComStat.cbInQue; +} + +/*#$% +============================================================== + 送信ビジーかどうか調べる +-------------------------------------------------------------- +-------------------------------------------------------------- + : 送信ビジー状態 +-------------------------------------------------------------- +============================================================== +*/ +int CCradio::TxBusy(void) +{ +#if 0 + COMSTAT ComStat; + DWORD dwErrorFlags; + + if( m_TxAbort ) return FALSE; + ClearCommError( m_fHnd, &dwErrorFlags, &ComStat ); + int f = ComStat.fRlsdHold; + if( f ) return TRUE; + if( m_dcb.fOutxCtsFlow ){ + f |= ComStat.fCtsHold; + } + if( m_dcb.fOutX ){ + f |= ComStat.fXoffHold; + } + return f ? TRUE : FALSE; +#else + COMSTAT ComStat; + DWORD dwErrorFlags; + + ::ClearCommError( m_fHnd, &dwErrorFlags, &ComStat ); + return ComStat.cbOutQue; +#endif +} + +/*#$% +============================================================== + 通信回線からデータを取り出す +-------------------------------------------------------------- +p : バッファのポインタ +len : バッファのサイズ +-------------------------------------------------------------- +実際に受信したサイズ +-------------------------------------------------------------- +============================================================== +*/ +DWORD CCradio::Read(BYTE *p, DWORD len) +{ + DWORD size=0; + + if( m_CreateON == TRUE ){ + ::ReadFile( m_fHnd, p, len, &size, NULL ); + } + return size; +} + +/*#$% +============================================================== + 通信回線にデータを送信する +-------------------------------------------------------------- +-------------------------------------------------------------- +-------------------------------------------------------------- +============================================================== +*/ +void CCradio::PutChar(char c) +{ + if( m_CreateON == TRUE ){ + if( m_PSKGNRId ) return; + if( m_txcnt < RADIO_TXBUFSIZE ){ + m_txbuf[m_txwp] = c; + m_txwp++; + if( m_txwp >= RADIO_TXBUFSIZE ) m_txwp = 0; + m_txcnt++; + } + } +} + +/*#$% +============================================================== + 通信回線にデータを送信する +-------------------------------------------------------------- +p : バッファのポインタ +len : 送信するサイズ +-------------------------------------------------------------- +実際に送信したサイズ +-------------------------------------------------------------- +============================================================== +*/ +void CCradio::Write(void *s, DWORD len) +{ + if( m_CreateON == TRUE ){ + if( m_PSKGNRId ) return; + char *p; + for( p = (char *)s; len; len--, p++ ){ + PutChar(*p); + } + } +} + +/*#$% +============================================================== + 通信回線にデータを送信する +-------------------------------------------------------------- +p : バッファのポインタ +len : 送信するサイズ +-------------------------------------------------------------- +実際に送信したサイズ +-------------------------------------------------------------- +============================================================== +*/ +void CCradio::OutStr(LPCSTR fmt, ...) +{ + va_list pp; + char bf[1024]; + + va_start(pp, fmt); + vsprintf( bf, fmt, pp ); + va_end(pp); + Write(bf, strlen(bf)); +} + +void CCradio::OutLine(LPCSTR fmt, ...) +{ + va_list pp; + char bf[1024]; + + va_start(pp, fmt); + vsprintf( bf, fmt, pp ); + va_end(pp); + Write(bf, strlen(bf)); + strcat( bf, "\r" ); //ja7ude 0521 + Write(bf, 1); //ja7ude 0521 +} + +void CCradio::SendCommand(LPCSTR p) +{ + int c; + int f; + + for(f = 0; *p; p++){ + if( *p == '\\' ){ + f = 0; + p++; + switch(*p){ + case '$': + f = 1; + continue; + case 'x': + case 'X': + p++; + if( *p == 'x' ){ + c = RADIO.Cmdxx; + } + else { + c = htoin(p, 2); + } + p++; + break; + case 'r': + c = CR; + break; + case 'n': + c = LF; + break; + case 'w': + p++; + c = atoin(p, 2); + if( (c < 0) || (c >= 100) ) c = 100; + if( c ) ::Sleep(c * 10); + p++; + continue; + case '\\': + c = '\\'; + break; + case 'c': // comment + return; + } + } + else if( f ){ + p = SkipSpace(p); + if( *p == 'x' ){ + c = RADIO.Cmdxx; + } + else { + c = htoin(p, 2); + } + p++; + } + else { + c = *p; + } + PutChar(BYTE(c)); + } +} + +void CCradio::SetPTT(int sw) +{ + if( m_PSKGNRId ){ + ::SendMessage(HWND_BROADCAST, m_PSKGNRId, 0 , sw ? 1 : 0); + if( sw ) ::Sleep(50); + } + else { + if( sw ){ + if( m_pRadio != NULL ){ + m_pRadio->SetPTT(sw); + } + else if( RADIO.usePTT ){ + ::EscapeCommFunction(m_fHnd, SETRTS); + ::EscapeCommFunction(m_fHnd, SETDTR); + } + SendCommand(RADIO.CmdTx.c_str()); + } + else { + if( m_pRadio != NULL ){ + m_pRadio->SetPTT(sw); + } + else if( RADIO.usePTT ){ + ::EscapeCommFunction(m_fHnd, CLRRTS); + ::EscapeCommFunction(m_fHnd, CLRDTR); + } + SendCommand(RADIO.CmdRx.c_str()); + } + } +} + +//-------------------------------------------------------- +// 周波数が変化しているかどうか調べる +int CCradio::IsFreqChange(LPCSTR pFreq) +{ + if( RADIO.PollType ){ + if( m_FreqEvent ) return 1; + if( m_Freq[0] ){ + if( strcmp(m_Freq, pFreq) ) return 1; + } + } + return 0; +} + +//-------------------------------------------------------- +// タイマー処理 +void CCradio::Timer(int tx, int interval) +{ + if( m_CreateON == TRUE ){ + if( m_PSKGNRId ) return; + if( m_pRadio != NULL ){ + if( m_pRadio->GetStatus() & mmrpstatusDEFCMD ){ + LPCSTR p; + switch(m_pRadio->GetDefCommand()){ + case 1: + p = RADIO.CmdTx.c_str(); + break; + case 2: + p = RADIO.CmdRx.c_str(); + break; + default: + p = RADIO.CmdInit.c_str(); + break; + } + SendCommand(p); + m_PollCnt = (5 + RADIO.PollInterval); + } + } + if( (!tx) && RADIO.PollType ){ + if( !m_PollCnt ){ + if( m_pRadio != NULL ) m_pRadio->Polling(); + if( m_ScanAddr ){ // アドレススキャン + m_PollCnt = 4; + if( m_ScanAddr <= 3 ){ + m_ScanAddr++; + } + else { + RADIO.Cmdxx++; + if( RADIO.Cmdxx >= 0x80 ){ + RADIO.Cmdxx = 0; + } + } + } + else { + m_PollCnt = (5 + RADIO.PollInterval); + } + if( interval ){ + m_PollCnt = m_PollCnt * 100 / interval; + } + switch(RADIO.PollType){ + case RADIO_POLLYAESUHF: + case RADIO_POLLFT1000D: + case RADIO_POLLFT920: + m_rxcnt = 0; + SendCommand("\\$0000000210"); + break; + case RADIO_POLLYAESUVU: + m_rxcnt = 0; + SendCommand("\\$0000000003"); + break; + case RADIO_POLLICOM: + case RADIO_POLLOMNIVI: + m_rxcnt = 0; + SendCommand("\\$FEFExxE003FD"); + break; + case RADIO_POLLICOMN: + case RADIO_POLLOMNIVIN: + if( !m_Freq[0] || m_ScanAddr ){ + m_rxcnt = 0; + SendCommand("\\$FEFExxE003FD"); + } + break; + case RADIO_POLLKENWOOD: + m_rxcnt = 0; + SendCommand("IF;"); + break; + case RADIO_POLLKENWOODN: + if( !m_Freq[0] ){ + m_rxcnt = 0; + SendCommand("AI1;"); + } + break; + case RADIO_POLLJST245: + m_rxcnt = 0; + SendCommand("I\r\n"); + break; + case RADIO_POLLJST245N: + if( !m_Freq[0] ){ + m_rxcnt = 0; + SendCommand("I1\r\nL\r\n"); + } + break; + //1.66B AA6YQ + case RADIO_POLLFT9000: + case RADIO_POLLFT2000: + case RADIO_POLLFT950: + case RADIO_POLLFT450: + m_rxcnt = 0; + SendCommand("IF;"); + break; + default: + break; + } + } + m_PollCnt--; + } + } +} + +//-------------------------------------------------------- +// 周波数ポーリングデータの受信 +void CCradio::CatchPoll(BYTE c) +{ + switch(RADIO.PollType){ + case RADIO_POLLYAESUHF: + case RADIO_POLLFT1000D: + case RADIO_POLLFT920: + if( m_rxcnt < 5 ){ + m_rxbuf[m_rxcnt] = c; + m_rxcnt++; + if( m_rxcnt == 5 ){ + FreqYaesuHF(); + } + } + break; + case RADIO_POLLYAESUVU: + if( m_rxcnt < 5 ){ + m_rxbuf[m_rxcnt] = c; + m_rxcnt++; + if( m_rxcnt == 5 ){ + FreqYaesuVU(); + } + } + break; + case RADIO_POLLICOM: + case RADIO_POLLICOMN: + case RADIO_POLLOMNIVI: + case RADIO_POLLOMNIVIN: + switch(m_rxcnt){ + case 0: + if( c == 0xfe ){ + m_rxbuf[m_rxcnt] = c; // プリアンブル + m_rxcnt++; + } + break; + case 1: + if( c != 0xfe ){ + m_rxbuf[m_rxcnt] = c; // PC-Addr + m_rxcnt++; + } + break; + case 2: + if( (c == RADIO.Cmdxx) || + (m_ScanAddr && c) ){ + m_rxbuf[m_rxcnt] = c; // Radio-Addr + m_rxcnt++; + } + else { + m_rxcnt = 0; + } + break; + case 3: + if( (c == 0x03) || ((c == 0x00)&&((RADIO.PollType == RADIO_POLLICOMN)||(RADIO.PollType == RADIO_POLLOMNIVIN))) ){ + m_rxbuf[m_rxcnt] = c; // Respons-command + m_rxcnt++; + } + else { + m_rxcnt = 0; + } + break; + default: + if( m_rxcnt < (int)sizeof(m_rxbuf) ){ + m_rxbuf[m_rxcnt] = c; // Data + m_rxcnt++; + if( c == 0xfd ){ + if( m_rxcnt >= 9 ){ + FreqICOM(); + if( m_ScanAddr && m_rxbuf[2] ){ + RADIO.Cmdxx = m_rxbuf[2]; + RADIO.PollScan = 0; + m_ScanAddr = 0; + } + } + m_rxcnt = 0; + } + } + else { + m_rxcnt = 0; + } + break; + } + break; + case RADIO_POLLKENWOOD: + case RADIO_POLLKENWOODN: + if( m_rxcnt < (int)sizeof(m_rxbuf) ){ + if( (c != 0x0d) && (c != 0x0f) ){ + if( (c != ' ') || m_rxcnt ){ + m_rxbuf[m_rxcnt] = c; // Data + m_rxcnt++; + if( c == ';' ){ + if( (m_rxbuf[0] == 'I') && (m_rxbuf[1]=='F') ){ + if( m_rxcnt >= 13 ) FreqKenwood(); + } + m_rxcnt = 0; + } + } + } + } + else { + m_rxcnt = 0; + } + break; + case RADIO_POLLJST245: + case RADIO_POLLJST245N: + if( m_rxcnt < (int)sizeof(m_rxbuf) ){ + if( (c == 'I') || m_rxcnt ){ + m_rxbuf[m_rxcnt] = c; // Data + m_rxcnt++; + if( (c == 0x0d) || (c == 0x0f) ){ + if( m_rxcnt >= 12 ) FreqJST245(); + m_rxcnt = 0; + } + } + } + else { + m_rxcnt = 0; + } + break; + //1.66B AA6YQ + case RADIO_POLLFT9000: + case RADIO_POLLFT2000: + case RADIO_POLLFT950: + case RADIO_POLLFT450: + if( m_rxcnt < (int)sizeof(m_rxbuf) ){ + if( (c != 0x0d) && (c != 0x0f) ){ + if( (c != ' ') || m_rxcnt ){ + m_rxbuf[m_rxcnt] = c; // Data + m_rxcnt++; + if( c == ';' ){ + if( (m_rxbuf[0] == 'I') && (m_rxbuf[1]=='F') ){ + if( m_rxcnt >= 13 ) FreqYaesu9K2K(); + } + m_rxcnt = 0; + } + } + } + } + else { + m_rxcnt = 0; + } + break; + default: + break; + } +} +//---------------------------------------------------------- +// 周波数の更新 (freq=MHz) +// +void CCradio::UpdateFreq(double freq) +{ + if( freq < 0.001 ) return; + + char bf[32]; + sprintf(bf, "%.3lf", freq); + if( strcmp(m_Freq, bf) ){ + strcpy(m_Freq, bf); + m_FreqEvent = 1; + } +} + +void CCradio::FreqYaesuHF(void) +{ + ULONG fq; + fq = m_rxbuf[1]; + fq = fq << 8; + fq |= m_rxbuf[2]; + fq = fq << 8; + fq |= m_rxbuf[3]; + fq = fq << 8; + fq |= m_rxbuf[4]; + + double f; + switch(RADIO.PollType){ + case RADIO_POLLFT1000D: // FT1000D + f = 25600000.0; + break; + case RADIO_POLLFT920: // FT920 + f = 1000000.0; + break; + default: // FT1000MP + f = 1600000.0; + break; + } + + UpdateFreq(double(fq)/f); +} + +void CCradio::FreqYaesuVU(void) +{ + ULONG fq; + fq = m_rxbuf[0] >> 4; + fq *= 10; + fq += m_rxbuf[0] & 0x0f; + fq *= 10; + fq += m_rxbuf[1] >> 4; + fq *= 10; + fq += m_rxbuf[1] & 0x0f; + fq *= 10; + fq += m_rxbuf[2] >> 4; + fq *= 10; + fq += m_rxbuf[2] & 0x0f; + + UpdateFreq( double(fq) / 1000.0 ); +} + +void CCradio::FreqICOM(void) +{ +// 0 1 2 3 4 5 6 7 8 9 +// fe e0 40 03 90 09 02 07 00 fd +// fe e0 40 03 90 09 02 07 fd + + ULONG fq = 0; + if( m_rxbuf[8] != 0xfd ){ + fq = (m_rxbuf[8] >> 4); + fq *= 10; + fq += (m_rxbuf[8] & 0x0f); + } + fq *= 10; + fq += m_rxbuf[7] >> 4; + fq *= 10; + fq += m_rxbuf[7] & 0x0f; + fq *= 10; + fq += m_rxbuf[6] >> 4; + fq *= 10; + fq += m_rxbuf[6] & 0x0f; + fq *= 10; + fq += m_rxbuf[5] >> 4; + fq *= 10; + fq += m_rxbuf[5] & 0x0f; + fq *= 10; + fq += m_rxbuf[4] >> 4; + fq *= 10; + fq += m_rxbuf[4] & 0x0f; + + UpdateFreq(double(fq)/1e6); +} + +void CCradio::FreqKenwood(void) +{ +//0123456789012 +//IF00021155000 +001000 0002000008 ; +//abcdefghijklmnopqrstuvwxyz1234567890 <---- 桁位置 +//c - m 周波数 21.155MHz + + ULONG fq = 0; + + m_rxbuf[13] = 0; + if( sscanf((LPCSTR)&m_rxbuf[2], "%lu", &fq) == 1 ){ + if( fq ) UpdateFreq(double(fq)/1e6); + } +} + +void CCradio::FreqJST245(void) +{ +// 0 1 2 3 4 5 6 7 8 9 10 11 12 +// ”Iabdffffffffg” +//  I:ヘッダー記号 +//  a:使用アンテナ1桁(1〜3) +//  b:バンド幅1桁(0〜2) +//  d:モード1桁(0〜5) +//  f:送受信周波数8桁(00100000〜53999998) +//  g:AGC1桁(0〜2) + + ULONG fq = 0; + + m_rxbuf[12] = 0; + LPCSTR p = (LPCSTR)&m_rxbuf[4]; + for( ; *p; p++ ) if( !isdigit(*p) ) return; + if( sscanf((LPCSTR)&m_rxbuf[4], "%lu", &fq) == 1 ){ + if( fq ) UpdateFreq(double(fq)/1e6); + } +} + +//AA6YQ 1.66B +void CCradio::FreqYaesu9K2K(void) +{ +//0123456789012 +//IF00021155000 +001000 0002000008 ; +//abcdefghijklmnopqrstuvwxyz1234567890 <---- 桁位置 +//f - m 周波数 21.155MHz + + ULONG fq = 0; + + m_rxbuf[13] = 0; + if( sscanf((LPCSTR)&m_rxbuf[5], "%lu", &fq) == 1 ){ + if( fq ) UpdateFreq(double(fq)/1e6); + } +} + diff --git a/cradio.h b/cradio.h new file mode 100644 index 0000000..bbf6caa --- /dev/null +++ b/cradio.h @@ -0,0 +1,173 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +///---------------------------------------------------------- +/// Radioコミニュケーションクラス +/// +/// (C) JE3HHT Makoto.Mori +/// +//--------------------------------------------------------------------------- +#ifndef CradioH +#define CradioH +#include "ComLib.h" +#include "MMlink.h" +//--------------------------------------------------------------------------- +#include //JA7UDE 0428 +typedef struct { + int change; + + char StrPort[32]; // ポートの名前 + int BaudRate; // ボーレート + int BitLen; // 0-7Bit, 1-8Bit + int Stop; // 0-1Bit, 1-2Bit + int Parity; // 0-PN, 1-PE, 2-PO + int flwXON; // Xon/Xoff ON + int flwCTS; // CTS-RTS ON + int usePTT; // PTT control + + long ByteWait; // バイト間の送信ウエイト + + int Cmdxx; + + AnsiString CmdInit; + AnsiString CmdRx; + AnsiString CmdTx; + + AnsiString cmdGNR; + int openGNR; + + int PollType; + int PollInterval; + + int PollScan; +}CRADIOPARA; +extern CRADIOPARA RADIO; +#define RADIOMENUMAX 128 +typedef struct { + AnsiString strTTL; + AnsiString strCMD; +}RADIOMENU; +//--------------------------------------------------------------------------- +void LoadRADIOSetup(TMemIniFile *pIniFile); +void SaveRADIOSetup(TMemIniFile *pIniFile); +//#define CR 0x0d +//#define LF 0x0a +#define CRADIO_CLOSE 1 +#define RADIO_COMBUFSIZE 4096 +#define RADIO_TXBUFSIZE 256 +#define RADIO_RXBUFSIZE 256 + +enum { + RADIO_POLLNULL, + RADIO_POLLYAESUHF, + RADIO_POLLYAESUVU, + RADIO_POLLICOM, + RADIO_POLLICOMN, + RADIO_POLLOMNIVI, + RADIO_POLLOMNIVIN, + RADIO_POLLKENWOOD, + RADIO_POLLKENWOODN, + RADIO_POLLFT1000D, + RADIO_POLLFT920, + RADIO_POLLJST245, + RADIO_POLLJST245N, + RADIO_POLLFT9000, //1.66B AA6YQ add new radios at end of list as this value is stored in mmtty.ini + RADIO_POLLFT2000, //1.66B AA6YQ + RADIO_POLLFT950, //1.66B AA6YQ + RADIO_POLLFT450, //1.66B AA6YQ +}; + +class CCradio : public TThread +{ +public: + BOOL m_CreateON; // クリエイトフラグ + DCB m_dcb; // DCB + HANDLE m_fHnd; // ファイルハンドル + HWND m_wHnd; // 親のウインドウハンドル + UINT m_uMsg; + UINT m_ID; // メッセージのID番号 + volatile int m_Command; // スレッドへのコマンド + BOOL m_TxAbort; // 送信中止フラグ + AnsiString Name; + CMMRadio *m_pRadio; + + int m_PSKGNRId; + int m_OpenGNR; + + char m_txbuf[RADIO_TXBUFSIZE]; + int m_txcnt; + int m_txwp; + int m_txrp; + + int m_PollCnt; + int m_PollTimer; + unsigned char m_rxbuf[RADIO_RXBUFSIZE]; + int m_rxcnt; + int m_FreqEvent; + char m_Freq[32]; + + int m_ScanAddr; +protected: + void virtual __fastcall Execute(); + BOOL OpenPipe(CRADIOPARA *cp, HWND hwnd, UINT nID); + void CatchPoll(BYTE c); + void FreqYaesuHF(void); + void FreqYaesuVU(void); + void FreqICOM(void); + void FreqKenwood(void); + void FreqJST245(void); + void FreqYaesu9K2K(void); + +public: + __fastcall CCradio(bool CreateSuspended); + __fastcall ~CCradio(){ + Close(); + }; + inline BOOL IsOpen(void){ + return m_CreateON; + }; + inline void UpdateHandle(HWND hwnd, UINT uMsg){ + m_wHnd = hwnd; m_uMsg = uMsg; + }; + BOOL Open(CRADIOPARA *cp, HWND hwnd, UINT uMsg, UINT nID); + void Close(void); + void ReqClose(void); + void WaitClose(void); + DWORD RecvLen(void); + int TxBusy(void); + DWORD Read(BYTE *p, DWORD len); + void Write(void *p, DWORD len); + void PutChar(char c); + void OutStr(LPCSTR fmt, ...); + void OutLine(LPCSTR fmt, ...); + void SendCommand(LPCSTR p); + void SetPTT(int sw); + void Timer(int tx, int interval); + + inline LPCSTR GetFreq(void){ + m_FreqEvent = 0; + return m_Freq; + }; + int IsFreqChange(LPCSTR p); + void UpdateFreq(double freq); +}; + +void InitRADIOPara(void); +#endif + diff --git a/def1.mtm b/def1.mtm new file mode 100644 index 0000000..fe536ac Binary files /dev/null and b/def1.mtm differ diff --git a/def2.mtm b/def2.mtm new file mode 100644 index 0000000..fce136f Binary files /dev/null and b/def2.mtm differ diff --git a/def3.mtm b/def3.mtm new file mode 100644 index 0000000..ff61e4c Binary files /dev/null and b/def3.mtm differ diff --git a/def4.mtm b/def4.mtm new file mode 100644 index 0000000..886d8e0 Binary files /dev/null and b/def4.mtm differ diff --git a/def5.mtm b/def5.mtm new file mode 100644 index 0000000..f66921f Binary files /dev/null and b/def5.mtm differ diff --git a/emmsstv.cnt b/emmsstv.cnt new file mode 100644 index 0000000..410afb2 --- /dev/null +++ b/emmsstv.cnt @@ -0,0 +1,56 @@ +:Base mmsstv.hlp +1 MMSSTV +2 Description=IDH_910 +2 Main Screen=IDH_6310 +2 History=IDH_1110 +2 System Requirements=IDH_1310 +2 Modes=IDH_1410 +1 Receive +2 Frequencies=IDH_1510 +2 Tones=IDH_1610 +2 Auto start=IDH_1710 +2 Manual start=IDH_1810 +2 Auto start & restart=IDH_1910 +1 Slant Adjust +2 Manual=IDH_2110 +2 Auto=IDH_2210 +2 Sync Point=IDH_2310 +1 Receive history +2 Images=IDH_2510 +1 Transmission +2 Basics=IDH_2710 +2 Image preparation=IDH_2810 +2 Mode Selection=IDH_2910 +2 Transmission=IDH_3110 +2 Tx Slant=IDH_3210 +2 Tune/ Cw ID=IDH_3310 +1 Templates +2 Functions=IDH_3510 +2 Superimpose=IDH_3610 +1 Stock Area +2 Functions=IDH_3810 +1 Radio Commands +2 Commands=IDH_4010 +1 Demodulator +2 Config=IDH_4210 +2 Zero Cross=IDH_4410 +2 PLL=IDH_4510 +2 VCO Gain=IDH_4610 +2 Loop LPF=IDH_4710 +2 Limiter=IDH_4910 +2 Differentiator=IDH_6410 +2 Out LPF=IDH_4810 +2 Linear Calibration=IDH_5010 +2 Level Converter=IDH_6510 +2 Profile=IDH_5110 +1 Sampling Frequencies +2 Frequencies=IDH_5310 +1 Sound card clock +2 Calibration=IDH_5510 +1 Setup Misc +2 Buffer=IDH_5710 +2 Priority=IDH_5810 +2 Device ID=IDH_5910 +2 Source=IDH_6010 +2 Clock=IDH_6110 +1 Closing Remarks=IDH_6210 diff --git a/emstvlog.txt b/emstvlog.txt new file mode 100644 index 0000000..a9578d7 --- /dev/null +++ b/emstvlog.txt @@ -0,0 +1,290 @@ +MMSSTV logging utility + +First version - February 20, 2001 JE3HHT Makoto Mori +Translated into English by JA7UDE Nobuyuki Oba + +* This document was written based on the logging utility of MMTTY. + + +---------- +MMSSTV logging utility +---------- + +MMSSTV logging utility offers only limited functions, such as the call sign +search. + +The current log file is the file that was most recently opened by MMSSTV. +The name of the current log file is displayed at the MMSSTV title bar. The +extension of the file name is "MDT." + +To change the current log file, select "Open log file" in the File menu. +Most common file name would be your_call_sign.mdt. + + +---------- +Basic operations +---------- + +1) Input his/her callsign in the Call box of the log panel. +2) Push the Find button to see if you have made QSO before. +3) Call him/her. If he/she replies to you, push the QSO button. At this +timing, MMSSTV records the starting time in the log. +4) During the QSO, input other information in other boxes, such as his/her +RST, my RST, and QTH. You can input more information by pushing the Data +button. +5) After the QSO is completed, push the QSO button again. MMSSTV records +the ending time in the log. + + +QSO data editing window + +During the QSO, push the Data button to open the data editing window. The +title bar at the top of the window has: +[Searched callsign] Entity/Continent Local_time QTH. + +At the bottom half of the window, the search results are shown. + +For the JA stations, you can push the JCC/JCG button (or F7 key) and open +the JCC/JCG/AJA selection window. You can incrementally input the QTH in +Rome-ji. + +The search results are shown in four different colors: +Gray: the callsign being input +Red: perfect match +Green: callsign match +Black: partial match + +[Example] +Search by KH0/JI3IVL + KH0/JI3IVL Red + KH0/JI3IVL/P Green + JI3IVL Green + JI3IVL/3 Green +Search by IVL + KH0/JI3IVL Black + JI3IVL Black + JI3IVL/3 Black + + +Log list + +The log list can be shown by pushing the List button. If you want to update +the data, double click the target row or hit the return key to open the QSO +data editing window. + +The QSO data list window has the following functions: + +[File menu] + +- Open log file +It is the same as "Open log file" in the File menu of the main window. Use +this function to change the log file. + +- Save data now +It is the same as "Save data now" in the File menu of the main window. +MMSSTV writes the data to the log file, closes the log file, and reopens the +log file. It is used to keep the disk updated so as not to lose the log +data in case, for instance, power outage. + +- Make index +It rebuilds the callsign index. Under normal operations, it is not likely +to break the index. However, if you cannot search the callsign, try this +function. + +- Load MMLOG TextFile +It reloads the log data in MMLOG text format into the log (comment by +JA7UDE, MMLOG is a logging utility also made by Mori san). + +- Save selected range to MMLOG TextFile +It saves the selected range to the file in MMLOG text format. + +* Use Shift + Up_arrow_key or Shift + Down_arrow_key to select the rows. + +- Import +MMSSTV can import the log data in the following formats: + Text + ADIF + LOG200 (L2) + Turbo HAMLOG (DBS, DBR) +(Comment by JA7UDE, LOG200 and Turbo HAMLOG are Japanese logging programs; +there are no English version as of April 08, 2001) + +- Export selected range +MMSSTV can export the selected data in the following formats: + Text + ADIF + LOG200 (L2) + Turbo HAMLOG (DBS, DBR) + +- Return to MMSSTV +It closes the log list window and returns to the MMSSTV main manu. + + +[Edit menu] + +- Cut +Copy the row to the clipboard and delete it from the log. + +- Insert +Insert a row and paste the content of the clipboard to it. + +- Select all +Select all the log entries. + +- Delete selected range +Delete the selected rows. + +- Sort (Date/Time) +Sort the selected rows in Date/Time order. + +[Find menu] + +- Move top +Move the cursor to the top of the list. + +- Move last +Move the cursor to the bottom of the list. + +- Search forward +Search the callsign forward + +- Search backward +Search the callsign backward + +- Search forward again +Search the callsign forward again + +- Search backward again +Search the callsign backward again + + +---------- +Contest operation +---------- + +I have experimentally had the contest functions built into MMSSTV, but I am +not sure we have SSTV contests. + +- Preparation +Open a new file with a unique file name for each contest. +Push Option and select Setup logging. +Choose the RSV contest number format. + +595 %N macro gives the same contest number. If you need another number than +595, put it in the HisRSV field of the very first data. For example, put +5952509 in the first HisRSV field manually. + +595+001 %N macro gives the RSV followed by the serial number. You must put +the initial value (595001) in the HisRSV field of the very first data. +MMSSTV automatically increments the serial number after it has made a QSO. + + +---------- +Export log to the text file +---------- + +You can export the log to a text file. Push File and select Export selected +range. MMSSTV supports three formats for the text file. + + Comma separated text file (CSV) + Tab separated text file + Plain text file + +MMSSTV has a translation facility of the data fields. The translation +macros supported are as follows: + +%NULL No translation is made. +%EOD All the macros after this macro are ignored. +%YYYY-MM-DD Date in 2000-07-10 format +%YY-MM-DD Date in 00-07-10 format +%YYYY/MM/DD Date in 2000/07/10 format +%YY/MM/DD Date in 00/07/10 format +%YY Year in 00 format +%YYYY Year in 2000 format +%MM Month in 07 format +%MON Month in JAN, FEB, MAR format +%MON2 Month in Jan., Feb., Mar. format +%DD Day in 10 format +%HHMM Starting time in 1234 format +%HH:MM Starting time in 12:34 format +%EHHMM Ending time in 1234 format +%EHH:MM Ending time in 12:34 format +%CALL Call sign +%M Call mark +%MY MyRST +%HIS HisRST +%MYRST MyRST (adjusted its length according to the mode) +%HISRST HisRST (adjusted its length according to the mode) +%FREQ Freqency in MHz +%MBAND Frequency in band +%KHZ Frequency in KHz +%MODE Operation mode +%POWER Power +%NAME Name +%QTH QTH +%REM Remark +%QSL QSL information +%S QSL sent mark +%R QSL received mark +%ENV Environment variables +%OPT1 Optional field 1 +%OPT2 Optional field 2 +%USR1 User field 1 +%USR2 User field 2 + +Any other texts are copied "as is." If you specify Max, the length of each +row is limited by Max. If you specify Max=0, the length of each row is not +limited. + +Check UTC if you want to output the date and time in UTC. +Check Double if you want to quote each field with ". + +---------- +Import from text +---------- + +MMSSTV can import the log data from a text file. Push File and select +Import. The text file imported to MMSSTV must have one QSO in one row. +Three formats below are supported: + + Comma separated text (CSV) + Tab separated text + Plain text + +The translation facility stated in the export section can be used for the +file import as well. + +Check UTC if you want to read the date and time in UTC. MMSSTV converts +them in JST. + + +---------- +Log data +---------- + +Date - Predefined (e.g., 95.12.23) +JST (Stating time) - Predefined (e.g., 2104) +END (Ending time) - Predefined (e.g., 2104) +Call - Up to 16 characters +M (call mark) - One arbitrary character +RST (His, My) - Up to 20 characters +Band - Predefined (14.025 is OK) +Mode - Predefined (CW, SSB, AM, FM, RTTY, etc) +Pow - Up to 4 characters +Name - Up to 16 characters +QTH - Up to 28 characters +Rem - Up to 56 characters +QSL - Up to 54 characters +S (QSL Send) - One arbitrary character +R (QSL Recv) - One arbitrary character +Env - Natural number 1 to 65535 +Opt1 - Up to 8 characters +Opt2 - Up to 8 characters +Usr1 - Up to 8 characters (shared with HisRST) +Usr2 - Up to 8 characters (shared with MyRST) + + + + +73 de JE3HHT Makoto Mori + diff --git a/erepeate.txt b/erepeate.txt new file mode 100644 index 0000000..52f56cf --- /dev/null +++ b/erepeate.txt @@ -0,0 +1,146 @@ +MMSSTV repeater mode + + 2001.9.11 JE3HHT Makoto Mori + Translated into English by JA7UDE Oba + +========== +Run MMSSTV as a repeater +========== +To run MMSSTV in the repeater mode, add "-r" option: + +MMSSTV.EXE -r + +While MMSSTV is running in the repeater mode, all the standard functions are still operational. Enjoy SSTV as you usually do. + + If you want to add your call sign and/or the time stamp to the beacon or replay pictures, use templates. You can specify various templates for these purposes. + + You can change the transmission mode of the replay picture in accordance with the mode of the received picture. Uncheck "Fixed mode" in the TX tab of the MMSSTV Setup Option. MMSSTV uses the same mode as the received picture. + + It is recommended to use Hilbert transform for the FM demodulator for better image quality. Turn on or off "Auto stop," "Auto restart," and "Auto resync" options as you prefer. + + + +==================== +Introduction of the repeater function +==================== +MMSSTV repeater function works as follows: + +1. MMSSTV returns CW ID after receiving a tone signal for a while. The default frequency of the tone is 1750Hz. +2. When MMSSTV starts receiving a picture in the specified time (default is 10 seconds) after the CW ID, it receives and resends the picture. +3. MMSSTV optionally sends a beacon picture periodically. + +MMSSTV keeps watch on the squelch status before starting the TX operation. When the squelch is open, MMSSTV will not start TX. Refer to Squelch section of this document for more details. + + + +================== +Setup repeater options +================== +Click on "Option" and select "Setup repeater" to open the repeater setup window. + +If you have changed the following options, you must push the OK button to make them into effect. + +[Enabled] + Check this box to enable the MMSSTV repeater function. + +[SQ level] + This specifies the squelch level of the auto-correlator. When the output level of the auto-correlator exceeds this threshold, MMSSTV does not start TX. If you put 0 to SQ level, the auto-correlator is turned off and MMSSTV will start TX irrespective of the RX signals. THIS IS NOT RECOMMENDED, HOWEVER. + + Debug pane displays the output level of the auto-correlator. Seeing the pane, put an appropriate value, which should be slightly higher than the noise level, to the SQ level box. It should be noted that MMSSTV never starts TX when it is receiving a picture. The auto-correlator will not work while MMSSTV is receiving a picture. + + +[Answer] +Put the CW ID, which MMSSTV transmits in response to the tone signal received, to this box. The frequency and speed of the CW ID are specified in the MMSSTV Setup window. + +[Tone] + Tone frequency for accessing the repeater. The default is 1750Hz, but you have to use a different frequency if you have another repeater on the same channel. The tone frequency is displayed as a dotted line in the spectrum window. + +[Tone det.] + Tone detection time (msec). To access the repeater, you have to continuously transmit the access tone for at least the time period specified here. + +[Answer wait] + Wait time (msec) for CW ID. When MMSSTV detects an access tone, it waits for the time specified here and then starts transmitting the CW ID. + +[RX timeout] + Time out time for receiving a picture. If MMSSTV does not receive a picture before this timer expires, MMSSTV goes back to the tone waiting state. + +[Replay wait] + Wait to for the replay. MMSSTV waits for the time specified here after the completion of RX, and then it starts the replay TX operation. + +[Tone sensitivity] + Tone detection sensitivity. Highest is the most sensitive, Lower is the least sensitive. + +[Folder] + If you specify a folder name here, the TX pictures are automatically saved in the folder. The folder must pre-exist. The pictures are stored in the JPEG format. + +[Template No.] + Select the template numbers for replay and beacon pictures. Template number 0 inhibits the template loading. + + In the repeater mode, MMSSTV displays a small number at the top left corner of each picture in Stocked pictures and Stocked templates window. + + You can use multiple selections for Template No. In this case, MMSSTV uses the templates in the specified order. + + Example: 25,26,27 - Use Template 25, 26, 27, 25, 26, 27, .... + + For the beacon pictures, you can add # in front of the number to send the stocked picture of the same number, with the template superimposed. + + Example: 26,#27,26,#28 - 27 and 28 are sent with 27-th and 28-th pictures, respectively. + + If you do not add #, the beacon pictures are loaded from the latest four pictures in the history. + If you do not want to use a template, specify a number of any empty templates. + +[Beacon-Interval] + Beacon interval. "OFF" disables the beacon. The timer is reset if MMSSTV receives a picture. + +[Beacon-Silence time] + MMSSTV keeps watch on the frequency for the specified time before transmitting the beacon. + +[Beacon-SSTV MODE] + SSTV mode for the beacon picture. + +[Beacon-Use image filter] + When the beacon pictures are composed from the latest four images in the history, you can use an image filter. The filter slightly degrades the image resolution, but it dissolves the folding error caused in the scale-down operation. + +[Beacon button] + Send the beacon immediately. + + +========== +Squelch +========== + Squelch works as follows: + +1. Cancel the CW ID response + If the squelch is not closed 10 seconds after the detection of the access tone, MMSSTV cancels the tone detection and will not transmit the CW ID. + +2. Cancel the replay picture + If the squelch is not closed 20 seconds after the picture received, MMSSTV will not replay the picture. + +3. Suspend the beacon + If the squelch is opened in the period of "Silence time," MMSSTV postpones the beacon transmission. In other words, MMSSTV does not send the beacon at least the band is continuously clear for "Silence time." + + The repeater would cause QRM. The beacon in particular is automatically transmitted without notice, and thus it is likely to cause QRM. Pay special attention to the squelch threshold (do not set it too high). + + +========== +Debug pane +========== +The debug pane displays the following values for supervising the repeater operation. + + +State: + 0 - Waiting for the access tone + 1 - Detected the access tone + 2 - Waiting for the CW ID transmission + 5 - Waiting for the picture receive + 6 - Receiving the replay picture + 8 - Waiting for the picture transmission + 10 - Transmitting the replay picture + +Ans: Number of CW ID transmitted +RX: Number of pictures received +TX: Number of pictures transmitted +Level: Output level of the auto-correlator +Beacon: Number of beacons transmitted and the beacon timer value + +73, Mako diff --git a/fileview.cpp b/fileview.cpp new file mode 100644 index 0000000..b7a1f28 --- /dev/null +++ b/fileview.cpp @@ -0,0 +1,1674 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "Main.h" +#include "FileView.h" +#include "PicRect.h" +#include "ZoomView.h" +//--------------------------------------------------------------------------- +#pragma package(smart_init) +#pragma resource "*.dfm" +//--------------------------------------------------------------------------- +__fastcall TFileViewDlg::TFileViewDlg(TComponent* Owner) + : TForm(Owner) +{ + pTabS = NULL; + Font->Name = sys.m_WinFontName; + Font->Charset = sys.m_WinFontCharset; + if( MsgEng ){ + SBNew->Hint = "Change folder"; + SBUpdate->Hint = "Update recent files"; + SBMode->Hint = "Stretch copy"; + + KTXS->Caption = "&Stretch copy to TX window"; + KTX->Caption = "Copy to TX window (via Clipper)..."; + KPO->Caption = "Overlay to Template"; + KPOL->Caption = "Embed to Template as OLE"; +// KPE->Caption = "&Edit..."; + KTT->Caption = "Show title bar"; + KTK->Caption = "Show the image as keeping aspect ratio"; + KNP->Caption = "Create new page"; + KDP->Caption = "Delete page"; + KRP->Caption = "Rename page"; + KBP->Caption = "Bottom tab"; + KPI->Caption = "Fast access with index"; + } + KC->Caption = Mmsstv->KRC->Caption; + KPC->Caption = Mmsstv->KTP->Caption; + KD->Caption = Mmsstv->KTD->Caption; + KV->Caption = Mmsstv->KView->Caption; + KTS->Caption = Mmsstv->KTSD->Caption; + KT->Caption = Mmsstv->KSMS->Caption; + KS->Caption = Mmsstv->KHVS->Caption; + KS1->Caption = Mmsstv->KHVS1->Caption; + KS2->Caption = Mmsstv->KHVS2->Caption; + KS3->Caption = Mmsstv->KHVS3->Caption; + KS4->Caption = Mmsstv->KHVS4->Caption; + KPP->Caption = Mmsstv->KTX->Caption; + KPE->Caption = Mmsstv->KSE->Caption; + + for( int i = 0; i < AHDMAX; i++ ){ + pPanel[i] = NULL; + pBox[i] = NULL; + } + pPopup = NULL; + m_Col = 6; + m_Line = 1; + m_SSize = 2; + m_RectS.Left = 0; + m_RectS.Top = 0; + m_RectS.Right = 80; + m_RectS.Bottom = 64; + m_TitleBar = 1; + m_Max = m_Col = m_Line = 0; + m_MaxPage = 1; + m_CurPage = 0; + m_MyIndex = 0; + for( int i = 0; i < FPAGEMAX; i++ ){ + pFileV[i] = NULL; + } + pFileV[0] = new CFILEV; + pCurPage = pFileV[0]; + m_CurFile = -1; + m_Overlap = 0; + m_Name = ""; + m_DisEvent = 0; +} +//--------------------------------------------------------------------------- +__fastcall TFileViewDlg::~TFileViewDlg() +{ + g_ExecPB.Cancel(); + for( int i = 0; i < FPAGEMAX; i++ ){ + if( pFileV[i] != NULL ){ + pFileV[i]->m_Thumb.CloseFolder(); + delete pFileV[i]; + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TFileViewDlg::UpdateTitlebar(void) +{ + if( m_TitleBar ){ + BorderStyle = bsSizeable; + } + else { + BorderStyle = bsNone; + } +} +//--------------------------------------------------------------------------- +void __fastcall TFileViewDlg::CheckOverlap(void) +{ + RECT rc; + + ::GetWindowRect(Mmsstv->TabS->Handle, &rc); + rc.top += Mmsstv->TabS->TabHeight; + int yw = (rc.bottom - rc.top) / 8; + rc.bottom -= yw; + m_Overlap = 0; + if( ((Left > rc.left) && (Left < rc.right)) || (((Left+Width) > rc.left) && ((Left+Width) < rc.right))){ + if( (Top > rc.top) && (Top < rc.bottom) ){ + m_Overlap = 1; + } + if( ((Top+Height) > rc.top) && ((Top+Height) < rc.bottom) ){ + m_Overlap = 1; + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TFileViewDlg::OnMove(TMessage *Message) +{ + CheckOverlap(); +} +//--------------------------------------------------------------------------- +void __fastcall TFileViewDlg::MakeFileV(void) +{ + for( int i = 0; i < m_MaxPage; i++ ){ + if( pFileV[i] == NULL ){ + pFileV[i] = new CFILEV; + } + } +} +//--------------------------------------------------------------------------- +int __fastcall TFileViewDlg::GetCH(int ch) +{ + if( pTabS != NULL ){ + return ch + Panel->Height + pTabS->TabHeight + 3; + } + else { + return ch + Panel->Height; + } +} +//--------------------------------------------------------------------------- +void __fastcall TFileViewDlg::GetRect(TRect &rc, int n) +{ + int xw = m_RectS.Right; + int x = n * xw; + rc.Left = x; rc.Top = 0; + rc.Right = x + xw; rc.Bottom = m_RectS.Bottom; +} +//--------------------------------------------------------------------------- +void __fastcall TFileViewDlg::SetBitmapSize(void) +{ + CFILEV *cp = pCurPage; + if( cp->pBitmapS == NULL ){ + cp->pBitmapS = new Graphics::TBitmap(); + AdjustBitmapFormat(cp->pBitmapS); + } + cp->pBitmapS->Width = m_Max * m_RectS.Right; + cp->pBitmapS->Height = m_RectS.Bottom; +} +//--------------------------------------------------------------------------- +void __fastcall TFileViewDlg::FormResize(TObject *Sender) +{ + if( m_DisEvent ) return; + + int WW = m_RectS.Right + 6; + int HH = m_RectS.Bottom + 6; + if( BorderStyle == bsNone ){ + int ch = m_Line * HH; + int cw = m_Col * WW; + m_DisEvent++; + ClientHeight = GetCH(ch); + ClientWidth = cw; + m_DisEvent--; + return; + } + int OldMax = m_Max; + int h = (pTabS != NULL) ? ClientHeight - pTabS->TabHeight - 6 : ClientHeight; + h = int((double(h - Panel->Height)/ HH) + 0.5); + if( !h ) h = 1; + int w = int((double(ClientWidth)/ WW) + 0.5); + if( !w ) w = 1; + while( (h * w) > AHDMAX ){ + if( w > 1 ){ + w--; + } + else if( h > 1 ){ + h--; + } + } + int ch = h * HH; + int cw = w * WW; + if( cw < (UD->Left + UD->Width) ){ + w++; + cw += WW; + } + m_Col = w; + m_Line = h; + m_Max = h * w; + SetBitmapSize(); + TWinControl *pCtr = this; + if( (m_MaxPage > 1) && (pTabS == NULL) ){ + Panel->Align = alNone; + RemoveControl(Panel); + pTabS = new TTabControl(this); + pTabS->Width = ClientWidth; + pTabS->Height = ClientHeight; + pTabS->TabPosition = KBP->Checked ? tpBottom : tpTop; + InsertControl(pTabS); + pTabS->Parent = this; + pTabS->Align = alClient; + for( int j = 0; j < m_MaxPage; j++ ){ + AnsiString as; + GetPageName(as, j); + pTabS->Tabs->Add(as); + } + pTabS->Font->Height = -16; + pTabS->TabHeight = 20; + pTabS->InsertControl(Panel); + Panel->Parent = pTabS; + if( KBP->Checked ){ + Panel->Top = 0; + } + else { + Panel->Top = pTabS->TabHeight + 3; + } + pTabS->TabIndex = m_CurPage; + pTabS->OnChange = TabSChange; + pCtr = pTabS; + } + pCurPage = pFileV[m_CurPage]; + if( UD->Max < pCurPage->m_CurPage ) UD->Max = SHORT(pCurPage->m_CurPage + 1); + UD->Position = SHORT(pCurPage->m_CurPage); + int i; + for( i = 0; i < m_Max; i++ ){ + if( pPanel[i] == NULL ){ + pPanel[i] = new TPanel(this); + TPanel *pn = pPanel[i]; + pn->BorderStyle = bsSingle; + pn->Width = WW; + pn->Height = HH; + pCtr->InsertControl(pn); + pn->Parent = pCtr; + pBox[i] = new TPaintBox(this); + TPaintBox *pb = pBox[i]; + pn->InsertControl(pb); + pb->Parent = pn; + pb->Align = alClient; + pb->OnPaint = PBPaint; + pb->OnMouseDown = PBMouseDown; + pb->OnMouseMove = PBMouseMove; + pb->OnDblClick = PBDblClick; + pb->OnDragOver = PanelDragOver; + pb->OnDragDrop = PanelDragDrop; + pb->PopupMenu = pPopup; + } + else { + pPanel[i]->Visible = FALSE; + pPanel[i]->Width = WW; + pPanel[i]->Height = HH; + } + MultProc(); + } + for( ; i < AHDMAX; i++ ){ + if( pPanel[i] != NULL ){ + pPanel[i]->Visible = FALSE; + } + MultProc(); + } + m_DisEvent++; + ClientHeight = GetCH(ch); + ClientWidth = cw; + for( i = 0; i < m_Max; i++ ){ + pPanel[i]->Left = (i % m_Col) * WW; + pPanel[i]->Top = Panel->Top + Panel->Height + (i / m_Col) * HH; + pPanel[i]->Visible = TRUE; + } + if( pTabS != NULL ) Panel->Width = pTabS->ClientWidth; + m_DisEvent--; + if( m_Max != OldMax ){ + for( i = 0; i < m_MaxPage; i++ ){ + if( i != m_CurPage ){ + delete pFileV[i]->pList; + pFileV[i]->pList = NULL; + } + } + LoadImage(); + } + SetPopup(Popup); +} +//--------------------------------------------------------------------------- +int __fastcall TFileViewDlg::IsPBox(TObject *Sender) +{ + for( int i = 0; i < m_Max; i++ ){ + if( Sender == pBox[i] ) return i; + } + return -1; +} +//--------------------------------------------------------------------------- +void __fastcall TFileViewDlg::UpdateBitmap(void) +{ + for( int i = 0; i < m_Max; i++ ){ + pBox[i]->Invalidate(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TFileViewDlg::SetPopup(TPopupMenu *tp) +{ + pPopup = tp; + for( int i = 0; i < m_Max; i++ ){ + pBox[i]->PopupMenu = tp; + } +} +//--------------------------------------------------------------------------- +void __fastcall TFileViewDlg::GetSize(int &w, int &h) +{ + int n = m_CurFile - (pCurPage->m_CurPage * m_Max); + w = pCurPage->m_Size[n] & 0x00007fff; + h = pCurPage->m_Size[n] >> 16; +} +//--------------------------------------------------------------------------- +int __fastcall TFileViewDlg::GetType(void) +{ + if( (m_CurFile >= pCurPage->pList->Count) || (m_CurFile < 0) ) return 0; + LPCSTR pExt = GetEXT(pCurPage->pList->Get(m_CurFile)); + if( strcmpi(pExt, "JPG") ) return 2; // bmp, wmf + return 1; // jepg +} +//--------------------------------------------------------------------------- +void __fastcall TFileViewDlg::UpdateTitle(void) +{ + char bf[256]; + + AnsiString Size; + LPCSTR pName; + if( (pCurPage->pList != NULL) && (m_CurFile < pCurPage->pList->Count) && (m_CurFile >= 0) ){ + pName = pCurPage->pList->Get(m_CurFile); + if( sys.m_FileViewShowSize ){ + int w, h; + GetSize(w, h); + sprintf(bf, "%ux%u ", w, h); + Size = bf; + } + } + else { + pName = ""; + } + sprintf(bf, "%s%s%s", Size.c_str(), pCurPage->m_Folder.c_str(), pName); + Caption = bf; + SBMode->Enabled = pCurPage->m_Type ? FALSE : TRUE; +} +//--------------------------------------------------------------------------- +void __fastcall TFileViewDlg::UpdateStat(void) +{ + char bf[64]; + pCurPage->m_MaxPage = 0; + int FileCnt = 0; + if( (pCurPage->pList != NULL) && m_Max ){ + FileCnt = pCurPage->pList->Count; + pCurPage->m_MaxPage = (FileCnt + m_Max - 1) / m_Max; + UD->Max = SHORT(pCurPage->m_MaxPage-1); + if( pCurPage->m_CurPage > UD->Max ) pCurPage->m_CurPage = UD->Max; + if( pCurPage->m_CurPage < 0 ) pCurPage->m_CurPage = 0; + if( !m_Name.IsEmpty() ){ + for( int i = 0; i < FileCnt; i++ ){ + if( !strcmpi(m_Name.c_str(), pCurPage->pList->Get(i)) ){ + pCurPage->m_CurPage = i / m_Max; + break; + } + } + m_Name = ""; + } + UD->Position = SHORT(pCurPage->m_CurPage); + UD->Enabled = TRUE; + UD->Repaint(); + } + else { + UD->Enabled = FALSE; + } + sprintf(bf, "%u/%u (%u files)", UD->Position + 1, pCurPage->m_MaxPage, FileCnt); + LPage->Caption = bf; + UpdateTitle(); +} +//--------------------------------------------------------------------------- +USHORT CalcCRC(USHORT crc, BYTE c) +{ + int i; + + crc = USHORT(crc ^ (c << 8)); + for( i = 0; i < 8; i++ ){ + if( crc & 0x8000 ){ + crc = USHORT((crc << 1) ^ 0x1021); + } + else { + crc = USHORT(crc << 1); + } + } + return crc; +} +//--------------------------------------------------------------------------- +USHORT __fastcall AddCRC(USHORT d, const BYTE *p, int n) +{ + for( ; n; n--, p++ ){ + d = CalcCRC(d, *p); + } + return d; +} +//--------------------------------------------------------------------------- +USHORT __fastcall GetCRC(LPCSTR p) +{ + USHORT d = 0; + for( ; *p; p++ ){ + d = CalcCRC(d, *p); + } + if( !d ) d++; + return d; +} +//--------------------------------------------------------------------------- +USHORT __fastcall GetCRC(WIN32_FIND_DATA *fp) +{ + USHORT d = GetCRC(fp->cFileName); + d = AddCRC(d, (const BYTE *)&fp->ftLastWriteTime, sizeof(FILETIME)); + d = AddCRC(d, (const BYTE *)&fp->nFileSizeLow, sizeof(DWORD)); + if( !d ) d++; + return d; +} +//--------------------------------------------------------------------------- +void __fastcall TFileViewDlg::LoadFileList(void) +{ + if( pCurPage->pList == NULL ){ + pCurPage->pList = new CFILEL; + } + pCurPage->pList->Delete(); + + WIN32_FIND_DATA FileData; + HANDLE hSearch; + + MultProc(); + if( pCurPage->m_Folder.IsEmpty() || (::SetCurrentDirectory(pCurPage->m_Folder.c_str()) != TRUE) ){ + if( NewFolder() == TRUE ){ + if( ::SetCurrentDirectory(pCurPage->m_Folder.c_str()) != TRUE ){ + pCurPage->m_Folder = "\\"; + ::SetCurrentDirectory(pCurPage->m_Folder.c_str()); + } + } + else { + pCurPage->m_Folder = "\\"; + ::SetCurrentDirectory(pCurPage->m_Folder.c_str()); + } + } + MultProc(); + + hSearch = FindFirstFile("*.*", &FileData); + if(hSearch == INVALID_HANDLE_VALUE){ + UpdateStat(); + return; + } + + MultProc(); + while(1){ + LPCSTR pExt = GetEXT(FileData.cFileName); + int f = 0; + switch(pCurPage->m_Type){ + case 0: + if( IsPic(pExt) ) f = 1; + break; + case 1: + if( !strcmpi(pExt, "MTM") ) f = 1; + break; + case 2: + if( !strcmpi(pExt, "MTI") ) f = 1; + break; + case 3: + if( !strcmpi(pExt, "DLL") ) f = 1; + break; + case 4: + if( !(FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ){ + if( *pExt && strcmpi(pExt, "DLL") && strcmpi(pExt, "EXE") ) f = 1; + } + break; + } + if( f ){ + pCurPage->pList->Add(FileData.cFileName, GetCRC(&FileData)); + } + if(!FindNextFile(hSearch, &FileData)) break; + MultProcA(); + } + FindClose(hSearch); + pCurPage->pList->Sort(); + if( pCurPage->m_UseIndex && pCurPage->pList->Count ){ + pCurPage->m_Thumb.OpenFolder(m_MyIndex, m_CurPage, pCurPage->pList->Count, GetCRC(pCurPage->m_Folder.c_str())); + pCurPage->m_Thumb.SetSize(m_RectS.Right, m_RectS.Bottom); + } + UpdateStat(); + MultProc(); +} +//--------------------------------------------------------------------------- +void __fastcall TFileViewDlg::LoadFile(Graphics::TBitmap *pBitmap, LPCSTR pName) +{ + if( pCurPage->m_Type >= 3 ){ + int xw = m_RectS.Right; + int yw = m_RectS.Bottom; + pBitmap->Width = xw; + pBitmap->Height = yw; + FillBitmap(pBitmap, clBtnFace); + WORD Icon = 0; + HICON hIcon = ::ExtractAssociatedIcon(HInstance, (LPSTR)pName, &Icon); + if( hIcon != NULL ){ + TIcon *pIcon = new TIcon; + pIcon->Handle = hIcon; + pBitmap->Canvas->Draw((xw - pIcon->Width)/2, (yw >= 64) ? (yw - pIcon->Height)/2 : 0, pIcon); + delete pIcon; + } + pBitmap->Canvas->Font->Height = -12; + int fw = pBitmap->Canvas->TextWidth(pName); + int fh = pBitmap->Canvas->TextHeight(pName); + int tm = ::SetBkMode(pBitmap->Canvas->Handle, TRANSPARENT); + int x = (xw - fw) / 2; + if( x < 0 ) x = 0; + pBitmap->Canvas->TextOut(x, hIcon != NULL ? yw - fh : (yw - fh)/2, pName); + ::SetBkMode(pBitmap->Canvas->Handle, tm); + } + else if( pCurPage->m_Type ){ + CDrawGroup *pGroup = new CDrawGroup; + if( LoadTemplate(pGroup, pName, pBitmap->Canvas) == TRUE ){ + pBitmap->Width = pGroup->m_SX; + pBitmap->Height = pGroup->m_SY; + FillBitmap(pBitmap, pGroup->m_TransCol); + MultProc(); + pGroup->Draw(pBitmap->Canvas); + } + pGroup->FreeItem(); + delete pGroup; + } + else { + ::LoadImage(pBitmap, pName); + } +} +//--------------------------------------------------------------------------- +void __fastcall TFileViewDlg::LoadImage(void) +{ + if( !m_Max ) return; + if( pCurPage->pList == NULL ) LoadFileList(); + m_CurFile = -1; + UpdateStat(); + + CWaitCursor wait; + MultProc(); + SetCurrentDirectory(pCurPage->m_Folder.c_str()); + Graphics::TBitmap *pBitmap = new Graphics::TBitmap(); + pBitmap->PixelFormat = pf24bit; + pBitmap->Width = 16; + pBitmap->Height = 16; + + MultProc(); + int i; + int n = pCurPage->m_CurPage * m_Max; + SetBitmapSize(); + for( i = 0; i < m_Max; i++, n++ ){ + TRect rc; + GetRect(rc, i); + if( n < pCurPage->pList->Count ){ + USHORT crc; + LPCSTR pn = pCurPage->pList->Get(crc, n); + if( !pCurPage->m_Thumb.LoadThumb(n, pCurPage->pBitmapS, rc, crc, pCurPage->m_Size[i]) ){ + LoadFile(pBitmap, pn); + pCurPage->m_Size[i] = (pBitmap->Height << 16) + pBitmap->Width; + Graphics::TBitmap *pBitmapT = CreateBitmap(m_RectS.Right, m_RectS.Bottom, -1); + ::SetStretchBltMode(pBitmapT->Canvas->Handle, HALFTONE); + MultProcA(); + if( sys.m_FileViewKeep ){ + FillBitmap(pBitmapT, clGray); + if( ((pBitmap->Width <= pBitmapT->Width) && (pBitmap->Height <= pBitmapT->Height)) ){ + pBitmapT->Canvas->Draw(0, 0, pBitmap); + } + else { + KeepAspectDraw(pBitmapT->Canvas, pBitmapT->Width, pBitmapT->Height, pBitmap); + } + } + else { + pBitmapT->Canvas->StretchDraw(m_RectS, pBitmap); + } + pCurPage->m_Thumb.SaveThumb(n, pBitmapT, m_RectS, crc, pCurPage->m_Size[i]); + pCurPage->pBitmapS->Canvas->CopyRect(rc, pBitmapT->Canvas, m_RectS); + if( pBox[i] != NULL ){ + pBox[i]->Canvas->Draw(0, 0, pBitmapT); + } + delete pBitmapT; + } + } + else { + pCurPage->pBitmapS->Canvas->Brush->Style = bsSolid; + pCurPage->pBitmapS->Canvas->Brush->Color = clWhite; + pCurPage->pBitmapS->Canvas->FillRect(rc); + } + MultProc(); + } + delete pBitmap; + UpdateBitmap(); +} +//--------------------------------------------------------------------------- +int __fastcall TFileViewDlg::CopyStretchBitmap(Graphics::TBitmap *pBitmap) +{ + Graphics::TBitmap *pBmp = MakeCurrentBitmap(); + CopyAutoSize(pBitmap, pBmp); + delete pBmp; + return TRUE; +} +//--------------------------------------------------------------------------- +int __fastcall TFileViewDlg::CopyRectBitmap(Graphics::TBitmap *pBitmap) +{ + int r = TRUE; + + TPicRectDlg *pBox = new TPicRectDlg(this); + LoadCurrentBitmap(pBox->pBitmap); + if( pBox->Execute(pBitmap) != TRUE ){ + r = FALSE; + } + delete pBox; + return r; +} +//--------------------------------------------------------------------------- +int __fastcall TFileViewDlg::CopyBitmap(Graphics::TBitmap *pBitmap) +{ + if( SBMode->Down ){ + return CopyStretchBitmap(pBitmap); + } + else { + return CopyRectBitmap(pBitmap); + } +} +//--------------------------------------------------------------------------- +void __fastcall TFileViewDlg::LoadCurrentBitmap(Graphics::TBitmap *pBitmap) +{ + if( (m_CurFile < pCurPage->pList->Count) && (pCurPage->pList != NULL) ){ + MultProc(); + SetCurrentDirectory(pCurPage->m_Folder.c_str()); + MultProc(); + if( ::LoadImage(pBitmap, pCurPage->pList->Get(m_CurFile)) == FALSE ){ + FillBitmap(pBitmap, clWhite); + } + } + else { + FillBitmap(pBitmap, clWhite); + } +} +//--------------------------------------------------------------------------- +Graphics::TBitmap* __fastcall TFileViewDlg::MakeCurrentBitmap(void) +{ + Graphics::TBitmap *pBmp = new Graphics::TBitmap(); + pBmp->PixelFormat = pf24bit; + pBmp->Width = 320; + pBmp->Height = 256; + LoadCurrentBitmap(pBmp); + return pBmp; +} +//--------------------------------------------------------------------------- +int __fastcall TFileViewDlg::IsDrag(void) +{ + for( int i = 0; i < m_Max; i++ ){ + if( pBox[i]->Dragging() ) return TRUE; + } + return FALSE; +} +//--------------------------------------------------------------------------- +void __fastcall TFileViewDlg::PBPaint(TObject *Sender) +{ + if( pCurPage == NULL ) return; + if( pCurPage->pBitmapS == NULL ) return; + + int r = IsPBox(Sender); + if( r >= 0 ){ + TRect sc; + GetRect(sc, r); + pBox[r]->Canvas->CopyRect(m_RectS, pCurPage->pBitmapS->Canvas, sc); + } +} +//--------------------------------------------------------------------------- +void __fastcall TFileViewDlg::PBClick(int n) +{ + m_CurFile = n + (pCurPage->m_CurPage * m_Max); + UpdateTitle(); +} +//--------------------------------------------------------------------------- +void __fastcall TFileViewDlg::PBMouseDown(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( pCurPage->pList == NULL ) return; + + int r = IsPBox(Sender); + if( r >= 0 ){ + PBClick(r); + if( (Button == mbLeft) && (m_CurFile < pCurPage->pList->Count) ){ + m_XX = X; m_YY = Y; + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TFileViewDlg::PBMouseMove(TObject *Sender, + TShiftState Shift, int X, int Y) +{ + if( pCurPage->pList == NULL ) return; + if( m_CurFile >= pCurPage->pList->Count ) return; + + TShiftState sc1, sc2; + sc1 << ssLeft; + sc2 << ssLeft; + sc1 *= Shift; + if( sc1 == sc2 ){ // Left button + if( (ABS(m_XX-X) + ABS(m_YY-Y)) >= 10 ){ + ((TPaintBox *)Sender)->BeginDrag(TRUE,0); + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TFileViewDlg::PBDblClick(TObject *Sender) +{ + if( pCurPage->pList == NULL ) return; + if( m_CurFile >= pCurPage->pList->Count ) return; + if( Mmsstv->SBTX->Down ) return; + + if( pCurPage->m_Type ){ // テンプレート + CWaitCursor w; + Mmsstv->AdjustPage(pgTemp); + AnsiString as; + GetCurFileName(as); + if( pCurPage->m_Type == 4 ){ + Mmsstv->DropOle(-1, 0, as.c_str(), (Sender == KP) ? 0 : 1); + } + else if( pCurPage->m_Type == 3 ){ // DLL + Mmsstv->DropLib(-1, 0, as.c_str()); + } + else if( pCurPage->m_Type == 2 ){ + CDrawGroup Group; + LoadTemplate(&Group, as.c_str(), NULL); + Mmsstv->AddTemplate(&Group); + } + else { + LoadTemplate(&Mmsstv->DrawMain, as.c_str(), NULL); + } + Mmsstv->UpdatePic(); + } + else if( SBMode->Down ){ + KTXSClick(Sender); + } + else { + KTXClick(Sender); + } +#if 0 + if( Sender->ClassNameIs("TPaintBox") ){ + TPaintBox *pBox = (TPaintBox *)Sender; + if( pBox->Dragging() ) pBox->EndDrag(FALSE); + } +#endif +} +//--------------------------------------------------------------------------- +void __fastcall TFileViewDlg::PanelDragOver(TObject *Sender, + TObject *Source, int X, int Y, TDragState State, bool &Accept) +{ + Accept = FALSE; + switch(pCurPage->m_Type){ + case 0: // 画像 + if( (Source == Mmsstv->PBoxTX)||(Source == Mmsstv->PBoxHist) ) Accept = TRUE; + break; + case 1: // テンプレート + case 2: + if( Source == Mmsstv->PBoxTemp ) Accept = TRUE; + break; + } +} +//--------------------------------------------------------------------------- +void __fastcall TFileViewDlg::PanelDragDrop(TObject *Sender, + TObject *Source, int X, int Y) +{ + int n = IsPBox(Sender); + if( n >= 0 ){ + n += (pCurPage->m_CurPage * m_Max); + } + AnsiString Name; + GetWriteFileName(Name, n); + switch(pCurPage->m_Type){ + case 0: + { + Graphics::TBitmap *pBitmap = NULL; + if( Source == Mmsstv->PBoxTX ){ + pBitmap = Mmsstv->pBitmapTXM; + } + else if( Source == Mmsstv->PBoxHist ){ + pBitmap = Mmsstv->pBitmapHist; + } + if( pBitmap != NULL ){ + if( Mmsstv->SaveBitmapMenu(pBitmap, Name.c_str(), pCurPage->m_Folder.c_str()) == TRUE ){ + UpdateList(); + } + } + } + break; + case 1: + case 2: + if( Source == Mmsstv->PBoxTemp ){ + if( Mmsstv->SaveTemplateMenu(&Mmsstv->DrawMain, Name.c_str(), pCurPage->m_Folder.c_str(), (pCurPage->m_Type == 2) ? 1 : 0) == TRUE ){ + UpdateList(); + } + } + break; + } +} +//--------------------------------------------------------------------------- +void __fastcall TFileViewDlg::UDClick(TObject *Sender, TUDBtnType Button) +{ + pCurPage->m_CurPage = UD->Position; + LoadImage(); + UpdateBitmap(); +} +//--------------------------------------------------------------------------- +void __fastcall TFileViewDlg::UDMouseDown(TObject *Sender, + TMouseButton Button, TShiftState Shift, int X, int Y) +{ + if( Button == mbRight ){ + int n = UD->Position; + int w = UD->Width/2; + int m = n % 5; + if( X >= w ){ + n += (5 - m); + } + else if( m ){ + n -= m; + } + else { + n -= 5; + } + int max = UD->Max + 1; + while( n < 0 ) n += max; + while( n >= max ) n -= max; + n = n - (n % 5); + UD->Position = SHORT(n); + UDClick(NULL, btNext); + } +} +//--------------------------------------------------------------------------- +void __fastcall TFileViewDlg::UpdateList(void) +{ + LoadFileList(); + LoadImage(); + UpdateBitmap(); +} +//--------------------------------------------------------------------------- +void __fastcall TFileViewDlg::SBUpdateClick(TObject *Sender) +{ + if( pCurPage->m_Thumb.IsOpen() ) pCurPage->m_Thumb.Reset(); + UpdateList(); +} +//--------------------------------------------------------------------------- +int __fastcall TFileViewDlg::NewFolder(void) +{ + int r = FALSE; + + TOpenDialog *pDialog = Mmsstv->OpenDialog; + pDialog->Options >> ofCreatePrompt; + pDialog->Options >> ofFileMustExist; + if( MsgEng ){ + pDialog->Title = "Set folder"; + } + else { + pDialog->Title = "フォルダの選択"; + } + char bf[512]; + sprintf(bf, "%s|%s|%s|%s", GetPicFilter(), GetTempFilter(), GetLibFilter(), "OLE objects(*.*)|*.*"); + pDialog->Filter = bf; + pDialog->FileName = "Dummy"; + pDialog->DefaultExt = "jpg"; + pDialog->InitialDir = pCurPage->m_Folder.c_str(); + pDialog->FilterIndex = pCurPage->m_Type + 1; + SetDisPaint(); + NormalWindow(Mmsstv); + if( Mmsstv->OpenDialogExecute(TRUE) == TRUE ){ + SetDirName(bf, AnsiString(pDialog->FileName).c_str()); //ja7ude 0428 + pCurPage->m_Folder = bf; + char drive[_MAX_DRIVE]; + char dir[_MAX_DIR]; + char name[_MAX_FNAME]; + char ext[_MAX_EXT]; + AnsiString Name; + ::_splitpath( AnsiString(pDialog->FileName).c_str(), drive, dir, name, ext ); + m_Name = name; + m_Name += ext; +#if 1 + pCurPage->m_Type = pDialog->FilterIndex - 1; +#else + LPCSTR pExt = GetEXT(m_Name.c_str()); + if( !strcmpi(pExt, "MTI") ){ + pCurPage->m_Type = 2; + } + else if( !strcmpi(pExt, "MTM") ){ + pCurPage->m_Type = 1; + } + else if( !strcmpi(pExt, "DLL") ){ + pCurPage->m_Type = 3; + } + else if( IsPic(pExt) ){ + pCurPage->m_Type = 0; + } + else { + pCurPage->m_Type = 4; + } +#endif + r = TRUE; + } + ResDisPaint(); + TopWindow(Mmsstv); + return r; +} +//--------------------------------------------------------------------------- +void __fastcall TFileViewDlg::SBNewClick(TObject *Sender) +{ + if( NewFolder() == TRUE ){ + UpdateList(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TFileViewDlg::FormClose(TObject *Sender, + TCloseAction &Action) +{ + Mmsstv->m_FileViewClose = 1; +} +//--------------------------------------------------------------------------- +void __fastcall TFileViewDlg::KTXSClick(TObject *Sender) +{ + Mmsstv->pBitmapTXM = RemakeBitmap(Mmsstv->pBitmapTXM, -1); + if( CopyStretchBitmap(Mmsstv->pBitmapTXM) == TRUE ){ + Mmsstv->AdjustPage(-1); + Mmsstv->UpdatePic(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TFileViewDlg::KTXClick(TObject *Sender) +{ + if( CopyRectBitmap(Mmsstv->pBitmapTXM) == TRUE ){ + Mmsstv->AdjustPage(-1); + Mmsstv->UpdatePic(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TFileViewDlg::KCClick(TObject *Sender) +{ + Graphics::TBitmap *pBmp = MakeCurrentBitmap(); + Mmsstv->CopyBitmap(pBmp); + delete pBmp; +} +//--------------------------------------------------------------------------- +int __fastcall TFileViewDlg::GetWriteFileName(AnsiString &as, int no) +{ + if( (no >= 0) && (no < pCurPage->pList->Count) ){ + as = pCurPage->pList->Get(no); + return TRUE; + } + else { + SYSTEMTIME tim; + GetLocal(&tim); + char bf[128]; + sprintf(bf, "%02u%02u%02u%02u%02u%02u", + tim.wYear % 100, + tim.wMonth, + tim.wDay, + tim.wHour, + tim.wMinute, + tim.wSecond + ); + as = bf; + return FALSE; + } +} +//--------------------------------------------------------------------------- +void __fastcall TFileViewDlg::KPCClick(TObject *Sender) +{ + if( m_CurFile < 0 ) return; + + AnsiString Name; + GetWriteFileName(Name, m_CurFile); + Graphics::TBitmap *pBmp = new Graphics::TBitmap(); + if( Mmsstv->PasteBitmap(pBmp, 1) == TRUE ){ + if( Mmsstv->SaveBitmapMenu(pBmp, Name.c_str(), pCurPage->m_Folder.c_str()) == TRUE ){ + UpdateList(); + } + } + delete pBmp; +} +//--------------------------------------------------------------------------- +void __fastcall TFileViewDlg::KTTClick(TObject *Sender) +{ + m_TitleBar = m_TitleBar ? 0 : 1; + UpdateTitlebar(); +} +//--------------------------------------------------------------------------- +void __fastcall TFileViewDlg::PopupPopup(TObject *Sender) +{ + KTT->Checked = m_TitleBar; + KTS->Checked = sys.m_FileViewShowSize; + KTK->Checked = sys.m_FileViewKeep; + switch(m_SSize){ + case 0: + KS1->Checked = TRUE; + break; + case 1: + KS2->Checked = TRUE; + break; + case 2: + KS3->Checked = TRUE; + break; + default: + KS4->Checked = TRUE; + break; + } + KS->Enabled = m_TitleBar; + KT->Enabled = pCurPage->pList->Count && (!pCurPage->m_Type); + int f = GetType(); + KD->Enabled = f; + KP->Enabled = f; + switch(pCurPage->m_Type){ + case 1: + KP->Caption = MsgEng ? "Copy to Template" : "テンプレートにコピー"; + break; + default: + KP->Caption = MsgEng ? "Paste to Template" : "テンプレートに貼り付け"; + break; + } + KPO->Enabled = f && (!pCurPage->m_Type || (pCurPage->m_Type == 4)); + f = (f && !pCurPage->m_Type) ? 1 : 0; + KC->Enabled = f; + KV->Enabled = f; + KPOL->Enabled = f; + KPE->Enabled = f; + if( f ) f = !Mmsstv->SBTX->Down; + KTX->Enabled = f; + KTXS->Enabled = f; + KNP->Enabled = (m_MaxPage < FPAGEMAX) ? TRUE : FALSE; + KDP->Enabled = (m_MaxPage >= 2) ? TRUE : FALSE; + KRP->Enabled = KDP->Enabled; + KPI->Checked = pCurPage->m_UseIndex; + KPC->Enabled = !pCurPage->m_Type && ::IsClipboardFormatAvailable(CF_BITMAP); +} +//--------------------------------------------------------------------------- +void __fastcall TFileViewDlg::FormKeyDown(TObject *Sender, WORD &Key, + TShiftState Shift) +{ + Mmsstv->FormKeyDown(Sender, Key, Shift); +} +//--------------------------------------------------------------------------- +void __fastcall TFileViewDlg::FormKeyUp(TObject *Sender, WORD &Key, + TShiftState Shift) +{ + Mmsstv->FormKeyUp(Sender, Key, Shift); +} +//--------------------------------------------------------------------------- +void __fastcall TFileViewDlg::KTKClick(TObject *Sender) +{ + sys.m_FileViewKeep = sys.m_FileViewKeep ? FALSE : TRUE; + Mmsstv->LoadAllFileView(); +} +//--------------------------------------------------------------------------- +void __fastcall TFileViewDlg::FormDeactivate(TObject *Sender) +{ + if( !IsDrag() ){ + m_CurFile = -1; + UpdateTitle(); + } +} +//--------------------------------------------------------------------------- +void __fastcall TFileViewDlg::KTSClick(TObject *Sender) +{ + sys.m_FileViewShowSize = sys.m_FileViewShowSize ? FALSE : TRUE; + UpdateTitle(); +} +//--------------------------------------------------------------------------- +void __fastcall TFileViewDlg::UpdateSize(int sw) +{ + SetThumbnailSize(m_RectS, m_SSize); + if( sw ){ + for( int i = 0; i < m_MaxPage; i++ ){ + CFILEV *cp = pFileV[i]; + if( cp->m_Thumb.IsOpen() ){ + cp->m_Thumb.SetSize(m_RectS.Right, m_RectS.Bottom); + } + delete cp->pBitmapS; + cp->pBitmapS = NULL; + } + FormResize(NULL); + } +} +//--------------------------------------------------------------------------- +void __fastcall TFileViewDlg::KSClick(TObject *Sender) +{ + if( Sender == KS1 ){ + m_SSize = 0; + } + else if( Sender == KS2 ){ + m_SSize = 1; + } + else if( Sender == KS3 ){ + m_SSize = 2; + } + else { + m_SSize = 3; + } + UpdateSize(1); +} +//--------------------------------------------------------------------------- +void __fastcall TFileViewDlg::MakeThImage(int mm) +{ + int mc = mm*mm; + if( (m_CurFile < 0) || (pCurPage->pList == NULL) ) return; + + Mmsstv->pBitmapTXM = RemakeBitmap(Mmsstv->pBitmapTXM, -1); + FillBitmap(Mmsstv->pBitmapTXM, sys.m_PicClipColor); + Graphics::TBitmap *pBitmap = new Graphics::TBitmap(); + Graphics::TBitmap *pBitmapQ = new Graphics::TBitmap(); + + MultProc(); + SetCurrentDirectory(pCurPage->m_Folder.c_str()); + MultProc(); + int Y1 = 0; +// int Y2 = Mmsstv->pBitmapTXM->Height; + int Y2 = Mmsstv->m_TXPH; + int X2 = Mmsstv->pBitmapTXM->Width; + if( Mmsstv->SBUseTemp->Down && Mmsstv->DrawMain.m_Cnt ){ + Mmsstv->DrawMain.GetColorBarPos(Y1, Y2); + } + int XW = X2 / mm; + int YW = (Y2-Y1) / mm; + int x, y, i; + int n = m_CurFile; + for( i = 0; i < mc; i++, n++ ){ + MultProc(); + if( n >= pCurPage->pList->Count ) n = 0; + ::LoadImage(pBitmap, pCurPage->pList->Get(n)); + x = (i % mm) * XW; + y = Y1 + ((i / mm) * YW); + if( ((i % mm) == (mm - 1)) && (x + XW) != X2 ){ + pBitmapQ->Width = X2 - x; + } + else { + pBitmapQ->Width = XW; + } + if( ((i / mm) == (mm - 1)) && (y + YW) != Y2 ){ + pBitmapQ->Height = Y2 - y; + } + else { + pBitmapQ->Height = YW; + } + MultProc(); + StretchCopyBitmapHW(pBitmapQ, pBitmap); + Mmsstv->pBitmapTXM->Canvas->Draw(x, y, pBitmapQ); + MultProc(); + } + delete pBitmapQ; + delete pBitmap; + Mmsstv->UpdatePic(); +} +//--------------------------------------------------------------------------- +void __fastcall TFileViewDlg::KT4Click(TObject *Sender) +{ + int n; + if( Sender == KT4 ){ + n = 2; + } + else if( Sender == KT9 ){ + n = 3; + } + else { + n = 4; + } + MakeThImage(n); + Mmsstv->AdjustPage(pgTX); +} +//--------------------------------------------------------------------------- +void __fastcall TFileViewDlg::KDClick(TObject *Sender) +{ + if( (m_CurFile < 0) || (pCurPage->pList == NULL) ) return; + + SetCurrentDirectory(pCurPage->m_Folder.c_str()); + AnsiString as; + GetCurFileName(as); + if( YesNoMB( ( Font->Charset != SHIFTJIS_CHARSET )?"Delete '%s'":"'%s'を消去します", as.c_str() ) == IDYES ){ + if( unlink(as.c_str()) ){ + ErrorFWrite(as.c_str()); + } + else { + UpdateList(); + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TFileViewDlg::KVClick(TObject *Sender) +{ + Graphics::TBitmap *pBmp = MakeCurrentBitmap(); + TZoomViewDlg *pBox = new TZoomViewDlg(this); + pBox->SetInitSize(pBmp->Width, pBmp->Height); + pBox->Execute(pBmp, FALSE); + delete pBox; + delete pBmp; +} +//--------------------------------------------------------------------------- +void __fastcall TFileViewDlg::KPClick(TObject *Sender) +{ + if( pCurPage->m_Type ){ + PBDblClick(Sender); + } + else { + Graphics::TBitmap *pBmp = MakeCurrentBitmap(); + Mmsstv->DropPic(-1, 0, pBmp, (Sender == KP) ? 1 : 2); + delete pBmp; + } +} +//--------------------------------------------------------------------------- +void __fastcall TFileViewDlg::KPOLClick(TObject *Sender) +{ + if( (m_CurFile < 0) || (pCurPage->pList == NULL) ) return; + + Mmsstv->AdjustPage(pgTemp); + AnsiString as; + GetCurFileName(as); + if( IsFile(as.c_str()) ){ + CDrawOle *pDraw = (CDrawOle *)Mmsstv->DrawMain.MakeItem(CM_OLE); + LPCSTR pExt = GetEXT(as.c_str()); + if( !strcmpi(pExt, "BMP")){ + pDraw->LoadFromFile(-1, 0, as.c_str()); + } + else { + Graphics::TBitmap *pBmp = MakeCurrentBitmap(); + pDraw->LoadFromBitmap(-1, 0, pBmp); + if( !strcmpi(pExt, "JPG") ){ + pDraw->m_Trans = 0; + pDraw->m_Stretch = 1; + } + delete pBmp; + } + Mmsstv->AddItem(pDraw, 0); + } +} +//--------------------------------------------------------------------------- +void __fastcall TFileViewDlg::KPEClick(TObject *Sender) +{ + if( (m_CurFile < 0) || (pCurPage->pList == NULL) ) return; + + char fname[256]; + + sprintf(fname, "%s%s", pCurPage->m_Folder.c_str(), pCurPage->pList->Get(m_CurFile)); + g_ExecPB.Exec(fname, (HWND)Handle, CM_EDITEXIT, m_CurPage); +} +//--------------------------------------------------------------------------- +void __fastcall TFileViewDlg::OnEditExit(TMessage Message) +{ + if( g_ExecPB.IsChanged() ) SBUpdateClick(NULL); +} +//--------------------------------------------------------------------------- +void __fastcall TFileViewDlg::TabSChange(TObject *Sender) +{ + if( m_DisEvent ) return; + + m_DisEvent++; + m_CurFile = -1; + m_CurPage = pTabS->TabIndex; + pCurPage = pFileV[m_CurPage]; + UD->Max = SHORT(pCurPage->m_MaxPage-1); + UD->Position = SHORT(pCurPage->m_CurPage); + if( (pCurPage->pList == NULL) || (pCurPage->pBitmapS == NULL) ){ + LoadImage(); + } + UpdateBitmap(); + UpdateStat(); + m_DisEvent--; +} +//--------------------------------------------------------------------------- +void __fastcall TFileViewDlg::GetCurFileName(AnsiString &as) +{ + if( m_CurFile >= 0 ){ + as = pCurPage->m_Folder.c_str(); + as += pCurPage->pList->Get(m_CurFile); + } +} +//--------------------------------------------------------------------------- +// 新規ページの作成 +void __fastcall TFileViewDlg::KNPClick(TObject *Sender) +{ + if( m_MaxPage < FPAGEMAX ){ + m_CurFile = -1; + CFILEV *cp = new CFILEV; + pFileV[m_MaxPage] = cp; + m_MaxPage++; + if( m_MaxPage <= 2 ){ + Mmsstv->ReOpenFileView(this); + } + else { + AnsiString as; + GetPageName(as, m_MaxPage - 1); + pTabS->Tabs->Add(as); + } + } +} +//--------------------------------------------------------------------------- +// ページの名前を得る +void __fastcall TFileViewDlg::GetPageName(AnsiString &as, int n) +{ + CFILEV *cp = pFileV[n]; + if( cp->m_Name.IsEmpty() ){ + char bf[32]; + sprintf(bf, "P%u", n + 1); + as = bf; + } + else { + as = cp->m_Name; + } +} +//--------------------------------------------------------------------------- +// ページの削除 +void __fastcall TFileViewDlg::KDPClick(TObject *Sender) +{ + if( m_MaxPage <= 1 ) return; + + AnsiString as; + GetPageName(as, m_CurPage); + if( YesNoMB( MsgEng ? "Delete '%s', are you sure?" : "'%s'を削除します. よろしいですか?", as.c_str()) != IDYES ) return; + + m_CurFile = -1; + pFileV[m_CurPage]->Delete(); + if( m_CurPage < (m_MaxPage - 1) ){ // 途中のページ + int i; + for( i = m_CurPage; i < (m_MaxPage - 1); i++ ){ + pFileV[i] = pFileV[i+1]; + } + pFileV[i] = NULL; + } + else { // 最後のページ + pFileV[m_CurPage] = NULL; + m_CurPage--; + } + m_MaxPage--; + pCurPage = pFileV[m_CurPage]; + Mmsstv->ReOpenFileView(this); +} +//--------------------------------------------------------------------------- +void __fastcall TFileViewDlg::KRPClick(TObject *Sender) +{ + AnsiString as = pCurPage->m_Name; + if( InputMB(NULL, MsgEng ? "Enter page name" : "名前を入力", as) == TRUE ){ + pCurPage->m_Name = as.c_str(); + GetPageName(as, m_CurPage); + pTabS->Tabs->Strings[m_CurPage] = as; + } +} +//--------------------------------------------------------------------------- +void __fastcall TFileViewDlg::KBPClick(TObject *Sender) +{ + InvMenu(KBP); + if( pTabS != NULL ){ + pTabS->TabPosition = KBP->Checked ? tpBottom : tpTop; + Mmsstv->ReOpenFileView(this); + } +} +//--------------------------------------------------------------------------- +void __fastcall TFileViewDlg::Reset(void) +{ + for( int i = 0; i < m_MaxPage; i++ ){ + if( pFileV[i]->m_Thumb.IsOpen() ){ + pFileV[i]->m_Thumb.Reset(); + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TFileViewDlg::KPIClick(TObject *Sender) +{ + pCurPage->m_UseIndex = pCurPage->m_UseIndex ? 0 : 1; + if( pCurPage->m_UseIndex ){ + LoadFileList(); + } + else if( pCurPage->m_Thumb.IsOpen() ){ + pCurPage->m_Thumb.CloseFolder(); + } +} +// +// +//*************************************************************************** +//CFILEVクラス +//*************************************************************************** +// +// +__fastcall CFILEV::CFILEV() +{ + pBitmapS = NULL; + pList = NULL; + m_CurPage = 0; + m_MaxPage = 1; + m_UseIndex = 1; + m_Name = ""; + m_Type = 0; +} +//--------------------------------------------------------------------------- +void __fastcall CFILEV::Delete(void) +{ + if( pBitmapS != NULL ) delete pBitmapS; + delete pList; + pList = NULL; +} +// +// +//*************************************************************************** +//CThumbクラス +//*************************************************************************** +// +// +__fastcall CThumb::CThumb() +{ + m_UpdateBmp = 0; + pBitmap = NULL; + pITBL = NULL; + m_Top = -1; +} +//--------------------------------------------------------------------------- +void __fastcall CThumb::SetSize(int sx, int sy) +{ + m_SizeX = sx; + m_SizeY = sy; + m_XW = m_SizeX * THUMBWIND; + if( pBitmap != NULL ) delete pBitmap; + pBitmap = new Graphics::TBitmap; + AdjustBitmapFormat(pBitmap); + pBitmap->Width = m_XW; + pBitmap->Height = m_SizeY; + m_Top = -1; + m_UpdateBmp = 0; +} +//--------------------------------------------------------------------------- +void __fastcall CThumb::OpenFolder(int index, int page, int size, USHORT crc) +{ + CloseFolder(); + if( !size ) return; + m_FolderIndex = index * 10 + page; + m_FileCount = size; + size++; + pITBL = new DIND[size]; + memset(pITBL, 0, sizeof(DIND)*size); + char name[256]; + sprintf(name, "%sFindex\\I%02u.idx", BgnDir, m_FolderIndex); + FILE *fp = fopen(name, "rb"); + MultProc(); + if( fp != NULL ){ + fread(pITBL, sizeof(DIND), size, fp); + fclose(fp); + if( (pITBL[0].crc != crc) || (pITBL[0].size != THUMBFID) ){ + memset(pITBL, 0, sizeof(DIND)*size); + } + } + else { + sprintf(name, "%sFindex", BgnDir); + mkdir(name); + } + pITBL[0].crc = crc; + pITBL[0].size = THUMBFID; + m_UpdateIdx = 0; + m_Top = -1; + MultProc(); +} +//--------------------------------------------------------------------------- +void __fastcall CThumb::CloseFolder(void) +{ + if( pBitmap != NULL ){ + CloseBitmap(); + delete pBitmap; + pBitmap = NULL; + } + if( pITBL != NULL ){ + MultProc(); + if( m_UpdateIdx ){ + char name[256]; + sprintf(name, "%sFindex\\I%02u.idx", BgnDir, m_FolderIndex); + FILE *fp = fopen(name, "wb"); + if( fp != NULL ){ + fwrite(pITBL, sizeof(DIND), m_FileCount+1, fp); + fclose(fp); + } + else { + ErrorFWrite(name); + } + m_UpdateIdx = 0; + } + delete pITBL; + pITBL = NULL; + MultProc(); + } +} +//--------------------------------------------------------------------------- +void __fastcall CThumb::CloseBitmap(void) +{ + if( m_UpdateBmp && (pBitmap != NULL) ){ + if( m_Top >= 0 ){ + MultProc(); + char name[256]; + sprintf(name, "%sFindex\\B%02u%u.bmp", BgnDir, m_FolderIndex, m_Top); + ::SaveBitmap(pBitmap, name); + MultProc(); + } + m_UpdateBmp = 0; + } +} +//--------------------------------------------------------------------------- +int __fastcall CThumb::UpdateBitmap(int n) +{ + if( pBitmap == NULL ) return FALSE; + + CloseBitmap(); + n /= THUMBWIND; + if( n == m_Top ) return TRUE; + m_Top = n; + char name[256]; + sprintf(name, "%sFindex\\B%02u%u.bmp", BgnDir, m_FolderIndex, n); + MultProc(); + int r = FALSE; + m_UpdateBmp = 1; + if( IsFile(name) ){ + ::LoadBitmap(pBitmap, name); + MultProc(); + if( (pBitmap->Width != m_XW) || (pBitmap->Height != m_SizeY) ){ + pBitmap->Width = m_XW; + pBitmap->Height = m_SizeY; + } + else { + m_UpdateBmp = 0; + r = TRUE; + } + } + if( r == FALSE ){ + n *= THUMBWIND; + for( int i = n; i < (n + THUMBWIND); i++ ){ + if( i < m_FileCount ) pITBL[i+1].crc = 0; + } + } + MultProc(); + return r; +} +//--------------------------------------------------------------------------- +void __fastcall CThumb::SaveThumb(int n, Graphics::TBitmap *pbmp, TRect rc, USHORT crc, int size) +{ + if( pITBL == NULL ) return; + if( pBitmap == NULL ) return; + if( n < m_FileCount ){ + if( (n / THUMBWIND) != m_Top ) UpdateBitmap(n); + int x = (n % THUMBWIND) * m_SizeX; + TRect tc; + tc.Left = x; tc.Top = 0; + tc.Right = x + m_SizeX; tc.Bottom = m_SizeY; + pBitmap->Canvas->CopyRect(tc, pbmp->Canvas, rc); + n++; + pITBL[n].crc = crc; + pITBL[n].size = size; + m_UpdateBmp = 1; + m_UpdateIdx = 1; + } +} +//--------------------------------------------------------------------------- +int __fastcall CThumb::LoadThumb(int n, Graphics::TBitmap *pbmp, TRect rc, USHORT crc, int &size) +{ + if( pITBL == NULL ) return FALSE; + if( pBitmap == NULL ) return FALSE; +// if( rc.Bottom != m_SizeY ) return FALSE; + if( (n < m_FileCount) && UpdateBitmap(n) ){ + if( crc == pITBL[n+1].crc ){ + int x = (n % THUMBWIND) * m_SizeX; + TRect sc; + sc.Left = x; sc.Top = 0; + sc.Right = x + m_SizeX; sc.Bottom = m_SizeY; + pbmp->Canvas->CopyRect(rc, pBitmap->Canvas, sc); + size = pITBL[n+1].size; + return TRUE; + } + } + return FALSE; +} +//--------------------------------------------------------------------------- +void __fastcall CThumb::Reset(void) +{ + if( pITBL != NULL ){ + memset(&pITBL[1], 0, sizeof(DIND)*m_FileCount); + m_UpdateIdx = 1; + } +} +// +// +//*************************************************************************** +//CFILELクラス +//*************************************************************************** +// +// +//--------------------------------------------------------------------------- +void __fastcall CFILEL::Alloc(void) +{ + int am = AMax ? (AMax * 2) : 64; + CFD *pN = new CFD[am]; + if( pBase != NULL ){ + memcpy(pN, pBase, sizeof(CFD)*Count); + delete pBase; + } + pBase = pN; + AMax = am; +} +//--------------------------------------------------------------------------- +void __fastcall CFILEL::Delete(void) +{ + if( pBase != NULL ){ + CFD *cp = pBase; + for( int i = 0; i < Count; i++, cp++ ) delete cp->pName; + delete pBase; + } + pBase = NULL; + AMax = 0; + Count = 0; +} +//--------------------------------------------------------------------------- +void __fastcall CFILEL::Add(LPCSTR pn, USHORT crc) +{ + if( Count >= AMax ) Alloc(); + CFD *cp = &pBase[Count]; + cp->pName = StrDupe(pn); + cp->crc = crc; + Count++; +} +//--------------------------------------------------------------------------- +LPCSTR __fastcall CFILEL::Get(USHORT &crc, int n) +{ + if( n >= Count ) return NULL; + CFD *cp = &pBase[n]; + crc = cp->crc; + return cp->pName; +} +//--------------------------------------------------------------------------- +LPCSTR __fastcall CFILEL::Get(int n) +{ + if( n >= Count ) return NULL; + return pBase[n].pName; +} +//--------------------------------------------------------------------------- +static int _cmp(const void *s, const void *t) +{ + CFD *sp = (CFD *)s; + CFD *tp = (CFD *)t; + return strcmp(sp->pName, tp->pName); +} +//--------------------------------------------------------------------------- +void __fastcall CFILEL::Sort(void) +{ + if( Count < 2 ) return; + + qsort(pBase, Count, sizeof(CFD), _cmp); +} +//--------------------------------------------------------------------------- + diff --git a/fileview.dfm b/fileview.dfm new file mode 100644 index 0000000..b926df0 Binary files /dev/null and b/fileview.dfm differ diff --git a/fileview.h b/fileview.h new file mode 100644 index 0000000..c839b6e --- /dev/null +++ b/fileview.h @@ -0,0 +1,306 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------------- +#ifndef FileViewH +#define FileViewH +//--------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ComLib.h" +//--------------------------------------------------------------------------- +#define THUMBFID 0x9055aa01 +#define THUMBWIND 8 +#pragma option -a- // パックの指示 +typedef struct { + USHORT crc; + int size; +}DIND; +#pragma option -a // パック解除 +class CThumb { +public: + int m_UpdateBmp; // アップデートフラグ + int m_UpdateIdx; + int m_FolderIndex; + int m_FileCount; + int m_Top; + int m_SizeX; + int m_SizeY; + int m_XW; + DIND *pITBL; // インデックスのテーブル + Graphics::TBitmap *pBitmap; // ビットマップ +public: + __fastcall CThumb(); + __fastcall ~CThumb(){ + CloseFolder(); + }; + void __fastcall SetSize(int sx, int sy); + void __fastcall OpenFolder(int index, int page, int size, USHORT crc); + void __fastcall CloseFolder(void); + void __fastcall CloseBitmap(void); + int __fastcall UpdateBitmap(int n); + void __fastcall SaveThumb(int n, Graphics::TBitmap *pbmp, TRect rc, USHORT crc, int size); + int __fastcall LoadThumb(int n, Graphics::TBitmap *pbmp, TRect rc, USHORT crc, int &size); + void __fastcall Reset(void); + int __fastcall IsOpen(void){return pITBL != NULL;}; +}; +//--------------------------------------------------------------------------- +#pragma option -a- // パックの指示 +typedef struct { + LPCSTR pName; + USHORT crc; +}CFD; +#pragma option -a // パック解除 +class CFILEL { +public: + int AMax; + int Count; + CFD *pBase; +private: + void __fastcall Alloc(void); +public: + CFILEL(){ + pBase = NULL; + Delete(); + }; + ~CFILEL(){ + Delete(); + }; + void __fastcall Delete(void); + void __fastcall Add(LPCSTR pn, USHORT crc); + LPCSTR __fastcall Get(USHORT &crc, int n); + LPCSTR __fastcall Get(int n); + void __fastcall Sort(void); +}; +//--------------------------------------------------------------------------- +#define AHDMAX 64 +class CFILEV { +public: + int m_Type; + AnsiString m_Folder; // フォルダ名 + AnsiString m_Name; // ページの名前 + int m_Size[AHDMAX]; // 画像サイズの配列 + int m_CurPage; // 現在のページ番号 + int m_MaxPage; // 最大ページ数 + int m_UseIndex; // インデックスを使う + CFILEL *pList; // ファイル名のリスト + Graphics::TBitmap *pBitmapS; // Col x Lineのビットマップ + CThumb m_Thumb; +public: + __fastcall CFILEV(); + inline __fastcall ~CFILEV(){ + Delete(); + }; + void __fastcall Delete(void); +}; +//--------------------------------------------------------------------------- +class TFileViewDlg : public TForm +{ +__published: // IDE 管理のコンポーネント + TPanel *Panel; + TSpeedButton *SBNew; + TUpDown *UD; + TLabel *LPage; + TSpeedButton *SBMode; + TSpeedButton *SBUpdate; + TPopupMenu *Popup; + TMenuItem *KTXS; + TMenuItem *KTX; + TMenuItem *N2; + TMenuItem *KC; + TMenuItem *N1; + TMenuItem *KTT; + TMenuItem *KTK; + TMenuItem *KTS; + TMenuItem *KS; + TMenuItem *KS1; + TMenuItem *KS2; + TMenuItem *KS3; + TMenuItem *KS4; + TMenuItem *KT; + TMenuItem *KT4; + TMenuItem *KT9; + TMenuItem *KT16; + TMenuItem *N3; + TMenuItem *KP; + TMenuItem *KPO; + TMenuItem *KPE; + TMenuItem *KPP; + TMenuItem *KNP; + TMenuItem *KDP; + TMenuItem *KRP; + TMenuItem *N4; + TMenuItem *KPI; + TMenuItem *KPC; + TMenuItem *KBP; + TMenuItem *KPOL; + TMenuItem *KD; + TMenuItem *KV; + void __fastcall FormResize(TObject *Sender); + void __fastcall UDClick(TObject *Sender, TUDBtnType Button); + void __fastcall SBNewClick(TObject *Sender); + void __fastcall SBUpdateClick(TObject *Sender); + void __fastcall FormClose(TObject *Sender, TCloseAction &Action); + void __fastcall KTXSClick(TObject *Sender); + void __fastcall KTXClick(TObject *Sender); + void __fastcall KCClick(TObject *Sender); + void __fastcall KTTClick(TObject *Sender); + void __fastcall PopupPopup(TObject *Sender); + void __fastcall FormKeyDown(TObject *Sender, WORD &Key, + TShiftState Shift); + void __fastcall FormKeyUp(TObject *Sender, WORD &Key, + TShiftState Shift); + + void __fastcall KTKClick(TObject *Sender); + void __fastcall FormDeactivate(TObject *Sender); + void __fastcall KTSClick(TObject *Sender); + void __fastcall KSClick(TObject *Sender); + void __fastcall KT4Click(TObject *Sender); + + void __fastcall KPClick(TObject *Sender); + void __fastcall KPEClick(TObject *Sender); + void __fastcall KNPClick(TObject *Sender); + void __fastcall KDPClick(TObject *Sender); + void __fastcall KRPClick(TObject *Sender); + void __fastcall KPIClick(TObject *Sender); + void __fastcall KPCClick(TObject *Sender); + void __fastcall UDMouseDown(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + + void __fastcall PanelDragOver(TObject *Sender, TObject *Source, int X, + int Y, TDragState State, bool &Accept); + void __fastcall PanelDragDrop(TObject *Sender, TObject *Source, int X, + int Y); + void __fastcall KBPClick(TObject *Sender); + void __fastcall KPOLClick(TObject *Sender); + void __fastcall KDClick(TObject *Sender); + void __fastcall KVClick(TObject *Sender); +private: // ユーザー宣言 + TPanel *pPanel[AHDMAX]; + TPaintBox *pBox[AHDMAX]; + TPopupMenu *pPopup; + TRect m_RectS; + + int m_Max; // 表示可能なサムネイルの数 + int m_Col; // 表示可能なサムネイルのカラム数 + int m_Line; // 表示可能なサムネイルの行数 + int m_DisEvent; + + int __fastcall GetCH(int ch); + int __fastcall IsDrag(void); + void __fastcall PBClick(int n); + void __fastcall PBPaint(TObject *Sender); + void __fastcall PBMouseDown(TObject *Sender, TMouseButton Button, + TShiftState Shift, int X, int Y); + void __fastcall PBMouseMove(TObject *Sender, + TShiftState Shift, int X, int Y); + void __fastcall PBDblClick(TObject *Sender); + + int m_XX, m_YY; + + int m_CurFile; + void __fastcall UpdateTitle(void); + void __fastcall UpdateStat(void); + + int __fastcall NewFolder(void); + void __fastcall MakeThImage(int mm); + + void __fastcall TabSChange(TObject *Sender); + void __fastcall LoadFile(Graphics::TBitmap *pBitmap, LPCSTR pName); + void __fastcall GetRect(TRect &rc, int n); + void __fastcall SetBitmapSize(void); + +public: + int m_MyIndex; + int m_Overlap; // ウインドウの重なりを調べる + int m_Suspend; // 表示の一時的な停止 + int m_TitleBar; + CFILEV *pFileV[FPAGEMAX]; + + int m_MaxPage; + int m_CurPage; + CFILEV *pCurPage; + + AnsiString m_Name; + void __fastcall CheckOverlap(void); + int m_SSize; // サムネイルの形状サイズ + void __fastcall UpdateSize(int sw); + + TTabControl *pTabS; + int __fastcall GetWriteFileName(AnsiString &as, int no); + +public: // ユーザー宣言 + __fastcall TFileViewDlg(TComponent* Owner); + __fastcall ~TFileViewDlg(); + + void __fastcall UpdateList(void); + void __fastcall LoadFileList(void); + void __fastcall LoadImage(void); + int __fastcall CopyStretchBitmap(Graphics::TBitmap *pBitmap); + int __fastcall CopyRectBitmap(Graphics::TBitmap *pBitmap); + int __fastcall CopyBitmap(Graphics::TBitmap *pBitmap); + void __fastcall LoadCurrentBitmap(Graphics::TBitmap *pBitmap); + Graphics::TBitmap* __fastcall MakeCurrentBitmap(void); + void __fastcall GetViewPos(int &x, int &y, int &w, int &h){ + x = Left; + y = Top; + w = ClientWidth; + h = ClientHeight; + }; + void __fastcall SetViewPos(int x, int y, int w, int h){ + Left = x; + Top = y; + ClientWidth = w; + ClientHeight = h; + CheckOverlap(); + }; + void __fastcall UpdateBitmap(void); + int __fastcall IsPBox(TObject *Sender); + void __fastcall SetPopup(TPopupMenu *tp); + void __fastcall UpdateTitlebar(void); + void __fastcall GetSize(int &w, int &h); + int __fastcall GetType(void); + void __fastcall MakeFileV(void); + void __fastcall Reset(void); + void __fastcall SetCurPage(void){ + pCurPage = pFileV[m_CurPage]; + }; + void __fastcall GetPageName(AnsiString &as, int n); + void __fastcall GetCurFileName(AnsiString &as); + +#define CM_EDITEXIT WM_USER+404 +protected: + void __fastcall OnMove(TMessage *Message); + void __fastcall OnEditExit(TMessage Message); +BEGIN_MESSAGE_MAP + MESSAGE_HANDLER(WM_MOVE, TMessage*, OnMove) + MESSAGE_HANDLER(CM_EDITEXIT, TMessage, OnEditExit) +END_MESSAGE_MAP(TForm) +}; +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- +#endif + diff --git a/fir.cpp b/fir.cpp new file mode 100644 index 0000000..d1146c1 --- /dev/null +++ b/fir.cpp @@ -0,0 +1,1171 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------------- +#include //ja7ude 0521 +#pragma hdrstop + +#include +#include "fir.h" + +//------------------------------------------------- +// FIRフィルタのたたき込み演算 +double __fastcall DoFIR(double *hp, double *zp, double d, int tap) +{ + memcpy(zp, &zp[1], sizeof(double)*tap); + zp[tap] = d; + d = 0.0; + for( int i = 0; i <= tap; i++, hp++, zp++ ){ + d += (*zp) * (*hp); + } + return d; +} +//--------------------------------------------------------------------------- +CIIRTANK::CIIRTANK() +{ + b1 = b2 = a0 = z1 = z2 = 0; + SetFreq(2000.0, SampFreq, 50.0); +} +//--------------------------------------------------------------------------- +void CIIRTANK::SetFreq(double f, double smp, double bw) +{ + double lb1, lb2, la0; + lb1 = 2 * exp(-PI * bw/smp) * cos(2 * PI * f / smp); + lb2 = -exp(-2*PI*bw/smp); + if( bw ){ +#if 0 + const double _gt[]={18.0, 26.0, 20.0, 20.0}; + la0 = sin(2 * PI * f/smp) / (_gt[SampType] * 50 / bw); +#else + la0 = sin(2 * PI * f/smp) / ((smp/6.0) / bw); +#endif + } + else { + la0 = sin(2 * PI * f/smp); + } + b1 = lb1; b2 = lb2; a0 = la0; +} +//--------------------------------------------------------------------------- +double CIIRTANK::Do(double d) +{ + d *= a0; + d += (z1 * b1); + d += (z2 * b2); + z2 = z1; + if( fabs(d) < 1e-37 ) d = 0.0; + z1 = d; + return d; +} +//--------------------------------------------------------------------------- +CLMS::CLMS() +{ + Z = new double[LMSTAP+1]; + H = new double[LMSTAP+1]; + D = new double[LMSTAP+1]; + memset(Z, 0, sizeof(double[LMSTAP+1])); + memset(H, 0, sizeof(double[LMSTAP+1])); + memset(D, 0, sizeof(double[LMSTAP+1])); + + m_D = 0; + + m_lmsADJSC = 1.0 / double(32768 * 32768); // スケール調整値 + m_lmsErr = m_lmsMErr = 0; + + m_Tap = int((4 * SampBase/11025) + 0.5); +// m_Tap = int((8 * SampBase/11025) + 0.5); + if( m_Tap > LMSTAP ) m_Tap = LMSTAP; + m_lmsMU2 = 0.003; // LMS 2μ + m_lmsGM = 0.9999; // LMS γ + + m_Tap_N = int((48 * SampBase/11025) + 0.5); + if( m_Tap_N > LMSTAP ) m_Tap_N = LMSTAP; +// m_lmsMU2_N = 0.00018; // LMS 2μ +// m_lmsGM_N = 0.999999; // LMS γ + m_lmsMU2_N = 0.00018; // LMS 2μ + m_lmsGM_N = 0.999999; // LMS γ + m_lmsDelay_N = int((12 * SampBase/11025) + 0.5); + if( m_lmsDelay_N > LMSTAP ) m_lmsDelay_N = LMSTAP; +} + +CLMS::~CLMS() +{ + delete D; + delete H; + delete Z; +} + +//------------------------------------------------- +// 適応フィルタの演算 +double CLMS::Do(double d) +{ + double a = 0.0; + int i; + double *zp = Z; + double *hp = H; + + // トランスバーサルフィルタ + memcpy(Z, &Z[1], sizeof(double)*m_Tap); +#if 0 + Z[m_Tap] = D[0]; +#else + Z[m_Tap] = m_D; +#endif + for( i = 0; i <= m_Tap; i++, zp++, hp++ ){ + a += (*zp) * (*hp); + } + // 誤差計算 + m_lmsErr = d - a; + m_lmsMErr = m_lmsErr * m_lmsMU2 * m_lmsADJSC; // lmsADJSC = 1/(32768 * 32768) スケーリング調整値 + + // 遅延器の移動 +#if 0 + if( m_lmsDelay ) memcpy(D, &D[1], sizeof(double)*m_lmsDelay); + D[m_lmsDelay] = d; +#else + m_D = d; +#endif + // 係数更新 + zp = Z; + hp = H; + double sum = 0; + for( i = 0; i <= m_Tap; i++, zp++, hp++ ){ + *hp = (m_lmsMErr * (*zp)) + (*hp * m_lmsGM); + if( *hp >= 0 ){ + sum += *hp; + } + else { + sum -= *hp; + } + } + if( sum > 0 ) a /= sum; + return a; +} + +//------------------------------------------------- +// 適応フィルタの演算 +double CLMS::DoN(double d) +{ + double a = 0.0; + int i; + double *zp = Z; + double *hp = H; + + // トランスバーサルフィルタ + memcpy(Z, &Z[1], sizeof(double)*m_Tap_N); + Z[m_Tap_N] = D[0]; + for( i = 0; i <= m_Tap_N; i++, zp++, hp++ ){ + a += (*zp) * (*hp); + } + // 誤差計算 + m_lmsErr = d - a; + m_lmsMErr = m_lmsErr * m_lmsMU2_N * m_lmsADJSC; // lmsADJSC = 1/(32768 * 32768) スケーリング調整値 + + // 遅延器の移動 + memcpy(D, &D[1], sizeof(double)*m_lmsDelay_N); + D[m_lmsDelay_N] = d; + + // 係数更新 + zp = Z; + hp = H; + for( i = 0; i <= m_Tap_N; i++, zp++, hp++ ){ + *hp = (m_lmsMErr * (*zp)) + (*hp * m_lmsGM_N); + } + return m_lmsErr; +} + +//------------------------------------------------- +// 適応フィルタの演算 +void CLMS::SetAN(int sw) +{ + m_Tap_N = int((48 * SampBase/11025) + 0.5); + if( m_Tap_N > LMSTAP ) m_Tap_N = LMSTAP; + m_lmsDelay_N = int((12 * SampBase/11025) + 0.5); + if( m_lmsDelay_N > LMSTAP ) m_lmsDelay_N = LMSTAP; + memset(Z, 0, sizeof(double[LMSTAP+1])); + memset(H, 0, sizeof(double[LMSTAP+1])); + memset(D, 0, sizeof(double[LMSTAP+1])); + switch(sw){ + case 1: + m_lmsMU2_N = 0.00018; // LMS 2μ + m_lmsGM_N = 0.999998; // LMS γ + break; + default: + m_lmsMU2_N = 0.00005; // LMS 2μ + m_lmsGM_N = 0.9999985; // LMS γ + break; + } +} + +//------------------------------------------------- +// 相関計算の演算 +int CLMS::Sig(double d) +{ + double a = 0.0; + int i; + double *zp = Z; + double *hp = H; + + // トランスバーサルフィルタ + memcpy(Z, &Z[1], sizeof(double)*m_Tap); +#if 0 + Z[m_Tap] = D[0]; +#else + Z[m_Tap] = m_D; +#endif + for( i = 0; i <= m_Tap; i++, zp++, hp++ ){ + a += (*zp) * (*hp); + } + // 誤差計算 + m_lmsErr = d - a; + m_lmsMErr = m_lmsErr * m_lmsMU2 * m_lmsADJSC; // lmsADJSC = 1/(32768 * 32768) スケーリング調整値 + + // 遅延器の移動 +#if 0 + if( m_lmsDelay ) memcpy(D, &D[1], sizeof(double)*m_lmsDelay); + D[m_lmsDelay] = d; +#else + m_D = d; +#endif + // 係数更新 + zp = Z; + hp = H; + double sum = 0; + for( i = 0; i <= m_Tap; i++, zp++, hp++ ){ + *hp = (m_lmsMErr * (*zp)) + (*hp * m_lmsGM); + if( *hp >= 0 ){ + sum += *hp; + } + else { + sum -= *hp; + } + } + return sum * 32768.0; +} + +//--------------------------------------------------------------------------- +// ノッチフィルタ +__fastcall CNotch::CNotch() +{ +// m_pZ = new double[NOTCHTAPMAX+1]; +// m_pH = new double[NOTCHTAPMAX+1]; +// memset(m_pZ, 0, sizeof(double)*NOTCHTAPMAX+1); + m_tap = 96 * SampBase / 11025.0; + if( m_tap & 1 ) m_tap++; + if( m_tap >= NOTCHTAPMAX ) m_tap = NOTCHTAPMAX; + SetNotchFreq(2400); +} + +__fastcall CNotch::~CNotch() +{ +// delete m_pZ; +// delete m_pH; +} + +void __fastcall CNotch::SetNotchFreq(double fq) +{ + m_freq = fq; + double fl, fh; + if( (fq < 1050.0) || (fq > 2350) ){ + fl = fq - 30; + fh = fq + 30; + } + else { + fl = fq - 15; + fh = fq + 15; + } + m_Notch.Create(m_tap, ffBEF, SampFreq, fl, fh, 10, 1.0); +// MakeFilter(m_pH, m_tap, ffBEF, SampFreq, fl, fh, 10, 1.0); +} + +double __fastcall CNotch::Do(double d) +{ + return m_Notch.Do(d); +// return DoFIR( m_pH, m_pZ, d, m_tap); +} + +/********************************************************************** + FIRフィルタ設計関数 +**********************************************************************/ +/* +==================================================== + ベッセル関数 +==================================================== +*/ +static double I0(double x) +{ + double sum, xj; + int j; + + sum = 1.0; + xj = 1.0; + j = 1; + while(1){ + xj *= ((0.5 * x) / (double)j); + sum += (xj*xj); + j++; + if( ((0.00000001 * sum) - (xj*xj)) > 0 ) break; + } + return(sum); +} + +/* +==================================================== + FIRフィルタの設計 +==================================================== +*/ +void MakeFilter(double *HP, int tap, int type, double fs, double fcl, double fch, double att, double gain) +{ + FIR fir; + + fir.typ = type; + fir.n = tap; + fir.fs = fs; + fir.fcl = fcl; + fir.fch = fch; + fir.att = att; + fir.gain = gain; + MakeFilter(HP, &fir); +} + +void MakeFilter(double *HP, FIR *fp) +{ + int j, m; + double alpha, win, fm, w0, sum; + double *hp; + + if( fp->typ == ffHPF ){ + fp->fc = 0.5*fp->fs - fp->fcl; + } + else if( fp->typ != ffLPF ){ + fp->fc = (fp->fch - fp->fcl)/2.0; + } + else { + fp->fc = fp->fcl; + } + if( fp->att >= 50.0 ){ + alpha = 0.1102 * (fp->att - 8.7); + } + else if( fp->att >= 21 ){ + alpha = (0.5842 * pow(fp->att - 21.0, 0.4)) + (0.07886 * (fp->att - 21.0)); + } + else { + alpha = 0.0; + } + + hp = fp->hp; + sum = PI*2.0*fp->fc/fp->fs; + if( fp->att >= 21 ){ // インパルス応答と窓関数を計算 + for( j = 0; j <= (fp->n/2); j++, hp++ ){ + fm = (double)(2 * j)/(double)fp->n; + win = I0(alpha * sqrt(1.0-(fm*fm)))/I0(alpha); + if( !j ){ + *hp = fp->fc * 2.0/fp->fs; + } + else { + *hp = (1.0/(PI*(double)j))*sin((double)j*sum)*win; + } + } + } + else { // インパルス応答のみ計算 + for( j = 0; j <= (fp->n/2); j++, hp++ ){ + if( !j ){ + *hp = fp->fc * 2.0/fp->fs; + } + else { + *hp = (1.0/(PI*(double)j))*sin((double)j*sum); + } + } + } + hp = fp->hp; + sum = *hp++; + for( j = 1; j <= (fp->n/2); j++, hp++ ) sum += 2.0 * (*hp); + hp = fp->hp; + if( sum > 0.0 ){ + for( j = 0; j <= (fp->n/2); j++, hp++ ) (*hp) /= sum; + } + + // 周波数変換 + + if( fp->typ == ffHPF ){ + hp = fp->hp; + for( j = 0; j <= (fp->n/2); j++, hp++ ) (*hp) *= cos((double)j*PI); + } + else if( fp->typ != ffLPF ){ + w0 = PI * (fp->fcl + fp->fch) / fp->fs; + if( fp->typ == ffBPF ){ + hp = fp->hp; + for( j = 0; j <= (fp->n/2); j++, hp++ ) (*hp) *= 2.0*cos((double)j*w0); + } + else { + hp = fp->hp; + *hp = 1.0 - (2.0 * (*hp)); + for( hp++, j = 1; j <= (fp->n/2); j++, hp++ ) (*hp) *= -2.0*cos((double)j*w0); + } + } + for( m = fp->n/2, hp = &fp->hp[m], j = m; j >= 0; j--, hp-- ){ + *HP++ = (*hp) * fp->gain; + } + for( hp = &fp->hp[1], j = 1; j <= (fp->n/2); j++, hp++ ){ + *HP++ = (*hp) * fp->gain; + } +} + +//--------------------------------------------------------------------------- +//FIRフィルタ(ヒルベルト変換フィルタ)の設計 +// +void MakeHilbert(double *H, int N, double fs, double fc1, double fc2) +{ + int L = N / 2; + double T = 1.0 / fs; + + double W1 = 2 * PI * fc1; + double W2 = 2 * PI * fc2; + + // 2*fc2*T*SA((n-L)*W2*T) - 2*fc1*T*SA((n-L)*W1*T) + + double w; + int n; + double x1, x2; + for( n = 0; n <= N; n++ ){ + if( n == L ){ + x1 = x2 = 0.0; + } + else if( (n - L) ){ + x1 = ((n - L) * W1 * T); + x1 = cos(x1) / x1; + x2 = ((n - L) * W2 * T); + x2 = cos(x2) / x2; + } + else { + x1 = x2 = 1.0; + } + w = 0.54 - 0.46 * cos(2*PI*n/(N)); + H[n] = -(2 * fc2 * T * x2 - 2 * fc1 * T * x1) * w; + } + + if( N < 8 ){ + w = 0; + for( n = 0; n <= N; n++ ){ + w += fabs(H[n]); + } + if( w ){ + w = 1.0 / w; + for( n = 0; n <= N; n++ ){ + H[n] *= w; + } + } + } +} + +//--------------------------------------------------------------------- +// 周波数特性グラフ(フィルタスレッド内でコールしてはいけない) +// +// H(ejωT) = [Σ0]Hm cos(mωT) - j[Σ1]Hm sin(mωT) +// +void DrawGraph(Graphics::TBitmap *pBitmap, const double *H, int Tap, int Over, int &nmax, int init, TColor col) +{ + int k, x, y; + double f, gdb, g, pi2t, fs; + double max; + char bf[80]; + + TCanvas *tp = pBitmap->Canvas; + TRect rc; + rc.Left = 0; + rc.Right = pBitmap->Width; + rc.Top = 0; + rc.Bottom = pBitmap->Height; + if( init ){ + tp->Brush->Color = clWhite; + tp->FillRect(rc); + } + int LM; // 周波数表示のあるライン数 + int DM; // 内部線の数 + int MM; // 実線の間隔 + switch(Over){ + case 2: + max = 3000; + fs = SampFreq/2.0; + break; + case 3: + max = 2000; + fs = SampFreq/3.0; + break; + default: + max = 4000; + fs = SampFreq; + break; + } + if( nmax ){ + max = nmax; + } + else { + nmax = max; + } + switch(nmax){ + case 3000: + LM = 3; + DM = 14; + MM = 5; + break; + case 100: + case 200: + case 2000: + LM = 4; + DM = 19; + MM = 5; + break; + case 400: + case 800: + case 4000: + LM = 4; + DM = 19; + MM = 5; + break; + default: // 6000 + LM = 3; + DM = 11; + MM = 4; + break; + } + int XL = 32; + int XR = pBitmap->Width - 16; + int YT = 16; + int YB = pBitmap->Height - 24; + + int i; + if( init ){ + tp->Pen->Color = clBlack; + tp->Font->Size = 8; + tp->MoveTo(XL, YT); tp->LineTo(XR, YT); tp->LineTo(XR, YB); tp->LineTo(XL, YB); tp->LineTo(XL, YT); + tp->Pen->Color = clGray; + for( i = 0; i < 7; i++ ){ + tp->Pen->Style = (i & 1) ? psSolid : psDot; + y = (int)(double(i + 1) * double(YB - YT)/8.0 + YT); + tp->MoveTo(XL, y); tp->LineTo(XR, y); + } + for( i = 1; i < 5; i++ ){ + y = (int)(double(i) * double(YB - YT)/4.0 + YT); + sprintf( bf, "-%2u", (80 / 4)*i ); + ::SetBkMode(tp->Handle, TRANSPARENT); + tp->TextOut(XL - 6 - tp->TextWidth(bf), y - (tp->TextHeight(bf)/2), bf); + } + strcpy(bf, "dB"); + tp->TextOut(XL - 6 - tp->TextWidth(bf), YT-(tp->TextHeight(bf)/2), bf); + for( i = 1; i <= DM; i++ ){ + tp->Pen->Style = (i % MM) ? psDot : psSolid; + x = (int)(double(i) * double(XR - XL)/double(DM+1) + XL); + tp->MoveTo(x, YT); tp->LineTo(x, YB); + } + for( i = 0; i <= LM; i++ ){ + x = (int)(double(i) * double(XR - XL)/double(LM) + XL); + sprintf(bf, "%4.0lf", (max*i)/LM); + ::SetBkMode(tp->Handle, TRANSPARENT); + tp->TextOut(x - (tp->TextWidth(bf)/2), YB + 6, bf); + } + tp->Pen->Color = clRed; + tp->Pen->Style = psDot; + x = (int)(XL + (fs/2) * (double(XR-XL)/max)); + tp->MoveTo(x, YT); tp->LineTo(x, YB); + + tp->Pen->Color = clBlue; + tp->Pen->Style = psSolid; + } + int ay = 0; + double ra, im; + pi2t = 2.0 * PI / fs; + tp->Pen->Color = col; + for( x = XL, f = 0.0; x < XR; x++, f += (max/double(XR-XL)) ){ + if( Tap ){ + ra = im = 0.0; + for( k = 0; k <= Tap; k++ ){ + ra += H[k] * cos(pi2t*f*k); + if( k ) im -= H[k] * sin(pi2t*f*k); + } + if( ra * im ){ + g = sqrt(ra * ra + im * im); + } + else { + g = 0.0; + } + } + else { + g = 1.0; + } + if( g == 0 ) g = 1.0e-38; + gdb = 20*0.4342944*log(fabs(g)) + 80.0; + if( gdb < 0.0 ) gdb = 0.0; + gdb = (gdb * double(YB-YT))/80.0; + y = YB - (int)gdb; + if( x == XL ){ + tp->MoveTo(x, y); + tp->LineTo(x, y); + } + else { + tp->MoveTo(x-1, ay); + tp->LineTo(x, y); + } + ay = y; + } +} + + +//--------------------------------------------------------------------- +// 周波数特性グラフ(フィルタスレッド内でコールしてはいけない) +// +// +void DrawGraphIIR(Graphics::TBitmap *pBitmap, double a0, double a1, double a2, double b1, double b2, int Over, int &nmax, int init, TColor col) +{ + int x, y; + double f, gdb, g, pi2t, pi4t, fs; + double max; + char bf[80]; + + TCanvas *tp = pBitmap->Canvas; + TRect rc; + rc.Left = 0; + rc.Right = pBitmap->Width; + rc.Top = 0; + rc.Bottom = pBitmap->Height; + if( init ){ + tp->Brush->Color = clWhite; + tp->FillRect(rc); + } + int LM; // 周波数表示のあるライン数 + int DM; // 内部線の数 + int MM; // 実線の間隔 + switch(Over){ + case 2: + max = 3000; + fs = SampFreq/2.0; + break; + case 3: + max = 2000; + fs = SampFreq/3.0; + break; + default: + max = 4000; + fs = SampFreq; + break; + } + if( nmax ){ + max = nmax; + } + else { + nmax = max; + } + switch(nmax){ + case 3000: + LM = 3; + DM = 14; + MM = 5; + break; + case 100: + case 200: + case 2000: + LM = 4; + DM = 19; + MM = 5; + break; + case 400: + case 800: + case 4000: + LM = 4; + DM = 19; + MM = 5; + break; + default: // 6000 + LM = 3; + DM = 11; + MM = 4; + break; + } + int XL = 32; + int XR = pBitmap->Width - 16; + int YT = 16; + int YB = pBitmap->Height - 24; + + int i; + if( init ){ + tp->Pen->Color = clBlack; + tp->Font->Size = 8; + tp->MoveTo(XL, YT); tp->LineTo(XR, YT); tp->LineTo(XR, YB); tp->LineTo(XL, YB); tp->LineTo(XL, YT); + tp->Pen->Color = clGray; + for( i = 0; i < 5; i++ ){ + tp->Pen->Style = (i & 1) ? psSolid : psDot; + y = (int)(double(i + 1) * double(YB - YT)/6.0 + YT); + tp->MoveTo(XL, y); tp->LineTo(XR, y); + } + for( i = 1; i < 4; i++ ){ + y = (int)(double(i) * double(YB - YT)/3.0 + YT); + sprintf( bf, "-%2u", (60 / 3)*i ); + ::SetBkMode(tp->Handle, TRANSPARENT); + tp->TextOut(XL - 6 - tp->TextWidth(bf), y - (tp->TextHeight(bf)/2), bf); + } + strcpy(bf, "dB"); + tp->TextOut(XL - 6 - tp->TextWidth(bf), YT-(tp->TextHeight(bf)/2), bf); + for( i = 1; i <= DM; i++ ){ + tp->Pen->Style = (i % MM) ? psDot : psSolid; + x = (int)(double(i) * double(XR - XL)/double(DM+1) + XL); + tp->MoveTo(x, YT); tp->LineTo(x, YB); + } + for( i = 0; i <= LM; i++ ){ + x = (int)(double(i) * double(XR - XL)/double(LM) + XL); + sprintf(bf, "%4.0lf", (max*i)/LM); + ::SetBkMode(tp->Handle, TRANSPARENT); + tp->TextOut(x - (tp->TextWidth(bf)/2), YB + 6, bf); + } + tp->Pen->Color = clRed; + tp->Pen->Style = psDot; + x = (int)(XL + (fs/2) * (double(XR-XL)/max)); + tp->MoveTo(x, YT); tp->LineTo(x, YB); + + tp->Pen->Color = clBlue; + tp->Pen->Style = psSolid; + } + int ay = 0; + pi2t = 2.0 * PI / fs; + pi4t = 2.0 * pi2t; + tp->Pen->Color = col; + double A, B, C, D, P, R; + double cosw, sinw, cos2w, sin2w; + for( x = XL, f = 0.0; x < XR; x++, f += (max/double(XR-XL)) ){ + cosw = cos(pi2t*f); + sinw = sin(pi2t*f); + cos2w = cos(pi4t*f); + sin2w = sin(pi4t*f); + A = a0 + a1 * cosw + a2 * cos2w; + B = 1 + b1 * cosw + b2 * cos2w; + C = a1 * sinw + a2 * sin2w; + D = b1 * sinw + b2 * sin2w; + P = A*A + C*C; + R = B*B + D*D; + g = sqrt(P/R); + if( g == 0 ) g = 1.0e-38; + gdb = 20*0.4342944*log(fabs(g)) + 60.0; + if( gdb < 0.0 ) gdb = 0.0; + gdb = (gdb * double(YB-YT))/60.0; + y = YB - (int)gdb; + if( x == XL ){ + tp->MoveTo(x, y); + tp->LineTo(x, y); + } + else { + tp->MoveTo(x-1, ay); + tp->LineTo(x, y); + } + ay = y; + } +} + +//--------------------------------------------------------------------- +// 周波数特性グラフ(フィルタスレッド内でコールしてはいけない) +// +// +void DrawGraphIIR(Graphics::TBitmap *pBitmap, CIIR *ip, int Over, int &nmax, int init, TColor col) +{ + int x, y; + double f, gdb, g, pi2t, pi4t, fs; + double max; + char bf[80]; + + TCanvas *tp = pBitmap->Canvas; + TRect rc; + rc.Left = 0; + rc.Right = pBitmap->Width; + rc.Top = 0; + rc.Bottom = pBitmap->Height; + if( init ){ + tp->Brush->Color = clWhite; + tp->FillRect(rc); + } + int LM; // 周波数表示のあるライン数 + int DM; // 内部線の数 + int MM; // 実線の間隔 + switch(Over){ + case 2: + max = 3000; + fs = SampFreq/2.0; + break; + case 3: + max = 2000; + fs = SampFreq/3.0; + break; + default: + max = 4000; + fs = SampFreq; + break; + } + if( nmax ){ + max = nmax; + } + else { + nmax = max; + } + switch(nmax){ + case 3000: + LM = 3; + DM = 14; + MM = 5; + break; + case 100: + case 200: + case 2000: + LM = 4; + DM = 19; + MM = 5; + break; + case 400: + case 800: + case 4000: + LM = 4; + DM = 19; + MM = 5; + break; + default: // 6000 + LM = 3; + DM = 11; + MM = 4; + break; + } + int XL = 32; + int XR = pBitmap->Width - 16; + int YT = 16; + int YB = pBitmap->Height - 24; + + int i; + if( init ){ + tp->Pen->Color = clBlack; + tp->Font->Size = 8; + tp->MoveTo(XL, YT); tp->LineTo(XR, YT); tp->LineTo(XR, YB); tp->LineTo(XL, YB); tp->LineTo(XL, YT); + tp->Pen->Color = clGray; + for( i = 0; i < 5; i++ ){ + tp->Pen->Style = (i & 1) ? psSolid : psDot; + y = (int)(double(i + 1) * double(YB - YT)/6.0 + YT); + tp->MoveTo(XL, y); tp->LineTo(XR, y); + } + for( i = 1; i < 4; i++ ){ + y = (int)(double(i) * double(YB - YT)/3.0 + YT); + sprintf( bf, "-%2u", (60 / 3)*i ); + ::SetBkMode(tp->Handle, TRANSPARENT); + tp->TextOut(XL - 6 - tp->TextWidth(bf), y - (tp->TextHeight(bf)/2), bf); + } + strcpy(bf, "dB"); + tp->TextOut(XL - 6 - tp->TextWidth(bf), YT-(tp->TextHeight(bf)/2), bf); + for( i = 1; i <= DM; i++ ){ + tp->Pen->Style = (i % MM) ? psDot : psSolid; + x = (int)(double(i) * double(XR - XL)/double(DM+1) + XL); + tp->MoveTo(x, YT); tp->LineTo(x, YB); + } + for( i = 0; i <= LM; i++ ){ + x = (int)(double(i) * double(XR - XL)/double(LM) + XL); + sprintf(bf, "%4.0lf", (max*i)/LM); + ::SetBkMode(tp->Handle, TRANSPARENT); + tp->TextOut(x - (tp->TextWidth(bf)/2), YB + 6, bf); + } + tp->Pen->Color = clRed; + tp->Pen->Style = psDot; + x = (int)(XL + (fs/2) * (double(XR-XL)/max)); + tp->MoveTo(x, YT); tp->LineTo(x, YB); + + tp->Pen->Color = clBlue; + tp->Pen->Style = psSolid; + } + int ay = 0; + pi2t = 2.0 * PI / fs; + pi4t = 2.0 * pi2t; + tp->Pen->Color = col; + double A, B, C, D, P, R; + double cosw, sinw, cos2w, sin2w; + for( x = XL, f = 0.0; x < XR; x++, f += (max/double(XR-XL)) ){ + cosw = cos(pi2t*f); + sinw = sin(pi2t*f); + cos2w = cos(pi4t*f); + sin2w = sin(pi4t*f); + g = 1.0; + double *ap = ip->A; + double *bp = ip->B; + for( i = 0; i < ip->m_order/2; i++, ap += 3, bp += 2 ){ +/* + A = a0 + a1 * cosw + a2 * cos2w; + B = 1 + b1 * cosw + b2 * cos2w; + C = a1 * sinw + a2 * sin2w; + D = b1 * sinw + b2 * sin2w; +*/ + A = bp[0] + bp[1] * cosw + bp[0] * cos2w; + B = 1 + -ap[1] * cosw + -ap[2] * cos2w; + C = bp[1] * sinw + bp[0] * sin2w; + D = -ap[1] * sinw + -ap[2] * sin2w; + P = A*A + C*C; + R = B*B + D*D; + g *= sqrt(P/R); + } + if( ip->m_order & 1 ){ + A = bp[0] + bp[1] * cosw; + B = 1 + -ap[1] * cosw; + C = bp[1] * sinw; + D = -ap[1] * sinw; + P = A*A + C*C; + R = B*B + D*D; + g *= sqrt(P/R); + } + if( g == 0 ) g = 1.0e-38; + gdb = 20*0.4342944*log(fabs(g)) + 60.0; + if( gdb < 0.0 ) gdb = 0.0; + gdb = (gdb * double(YB-YT))/60.0; + y = YB - (int)gdb; + if( x == XL ){ + tp->MoveTo(x, y); + tp->LineTo(x, y); + } + else { + tp->MoveTo(x-1, ay); + tp->LineTo(x, y); + } + ay = y; + } +} + +double asinh(double x) +{ + return log(x + sqrt(x*x+1.0)); +} + +//------------------------------------------------------------------ +// bc : 0-バターワース, 1-チェビシフ +// rp : 通過域のリップル +void MakeIIR(double *A, double *B, double fc, double fs, int order, int bc, double rp) +{ + double w0, wa, u, zt, x; + int j, n; + + if( bc ){ // チェビシフ + u = 1.0/double(order) * asinh(1.0/sqrt(pow(10.0,0.1*rp)-1.0)); + } + wa = tan(PI*fc/fs); + w0 = 1.0; + n = (order & 1) + 1; + double *pA = A; + double *pB = B; + double d1, d2; + for( j = 1; j <= order/2; j++, pA+=3, pB+=2 ){ + if( bc ){ // チェビシフ + d1 = sinh(u)*cos(n*PI/(2*order)); + d2 = cosh(u)*sin(n*PI/(2*order)); + w0 = sqrt(d1 * d1 + d2 * d2); + zt = sinh(u)*cos(n*PI/(2*order))/w0; + } + else { // バターワース + w0 = 1.0; + zt = cos(n*PI/(2*order)); + } + pA[0] = 1 + wa*w0*2*zt + wa*w0*wa*w0; + pA[1] = -2 * (wa*w0*wa*w0 - 1)/pA[0]; + pA[2] = -(1.0 - wa*w0*2*zt + wa*w0*wa*w0)/pA[0]; + pB[0] = wa*w0*wa*w0 / pA[0]; + pB[1] = 2*pB[0]; + n += 2; + } + if( bc && !(order & 1) ){ + x = pow( 1.0/pow(10.0,rp/20.0), 1/double(order/2) ); + pB = B; + for( j = 1; j <= order/2; j++, pB+=2 ){ + pB[0] *= x; + pB[1] *= x; + } + } + if( order & 1 ){ + if( bc ) w0 = sinh(u); + j = (order / 2); + pA = A + (j*3); + pB = B + (j*2); + pA[0] = 1 + wa*w0; + pA[1] = -(wa*w0 - 1)/pA[0]; + pB[0] = wa*w0/pA[0]; + pB[1] = pB[0]; + } +} + +//--------------------------------------------------------------------------- +CIIR::CIIR() +{ + m_order = 0; + A = new double[IIRMAX*3]; + B = new double[IIRMAX*2]; + Z = new double[IIRMAX*2]; + memset(A, 0, sizeof(double[IIRMAX*3])); + memset(B, 0, sizeof(double[IIRMAX*2])); + memset(Z, 0, sizeof(double[IIRMAX*2])); +} + +CIIR::~CIIR() +{ + if( A != NULL ) delete A; + if( B != NULL ) delete B; + if( Z != NULL ) delete Z; +} + +void CIIR::Clear(void) +{ + memset(Z, 0, sizeof(double[IIRMAX*2])); +} + +void CIIR::MakeIIR(double fc, double fs, int order, int bc, double rp) +{ + m_order = order; + m_bc = bc; + m_rp = rp; + ::MakeIIR(A, B, fc, fs, order, bc, rp); +} + +double CIIR::Do(double d) +{ + double *pA = A; + double *pB = B; + double *pZ = Z; + double o; + for( int i = 0; i < m_order/2; i++, pA+=3, pB+=2, pZ+=2 ){ + d += pZ[0] * pA[1] + pZ[1] * pA[2]; + o = d * pB[0] + pZ[0] * pB[1] + pZ[1] * pB[0]; + pZ[1] = pZ[0]; + if( fabs(d) < 1e-37 ) d = 0.0; + pZ[0] = d; + d = o; + } + if( m_order & 1 ){ + d += pZ[0] * pA[1]; + o = d * pB[0] + pZ[0] * pB[0]; + if( fabs(d) < 1e-37 ) d = 0.0; + pZ[0] = d; + d = o; + } + return d; +} + +//--------------------------------------------------------------------------- +// CFIR2クラス +CFIR2::CFIR2() +{ + m_pZ = NULL; + m_pH = NULL; + m_pZP = NULL; + m_W = 0; + m_Tap = 0; +} + +//--------------------------------------------------------------------------- +CFIR2::~CFIR2() +{ + if( m_pZ ) delete m_pZ; + if( m_pH ) delete m_pH; +} +//--------------------------------------------------------------------------- +void __fastcall CFIR2::Create(int tap) +{ + if( !tap ){ + if( m_pZ ) delete m_pZ; + m_pZ = NULL; + } + else if( (m_Tap != tap) || !m_pZ ){ + if( m_pZ ) delete m_pZ; + m_pZ = new double[(tap+1)*2]; + memset(m_pZ, 0, sizeof(double)*(tap+1)*2); + m_W = 0; + } + m_Tap = tap; + m_TapHalf = tap/2; +} +//--------------------------------------------------------------------------- +void __fastcall CFIR2::Create(int tap, int type, double fs, double fcl, double fch, double att, double gain) +{ + if( (m_Tap != tap) || !m_pZ || !m_pH ){ + if( m_pZ ) delete m_pZ; + m_pZ = new double[(tap+1)*2]; + memset(m_pZ, 0, sizeof(double)*(tap+1)*2); + if( m_pH ) delete m_pH; + m_pH = new double[tap+1]; + m_W = 0; + } + m_Tap = tap; + m_TapHalf = tap/2; + ::MakeFilter(m_pH, tap, type, fs, fcl, fch, att, gain); +} +//--------------------------------------------------------------------------- +void __fastcall CFIR2::Clear(void) +{ + if( m_pZ ) memset(m_pZ, 0, sizeof(double)*(m_Tap+1)*2); +} +//--------------------------------------------------------------------------- +double __fastcall CFIR2::Do(double d) +{ + double *dp1 = &m_pZ[m_W+m_Tap+1]; + m_pZP = dp1; + *dp1 = d; + m_pZ[m_W] = d; + d = 0; + double *hp = m_pH; + for( int i = 0; i <= m_Tap; i++ ){ + d += (*dp1--) * (*hp++); + } + m_W++; + if( m_W > m_Tap ) m_W = 0; + return d; +} +//--------------------------------------------------------------------------- +double __fastcall CFIR2::Do(double d, double *hp) +{ + double *dp1 = &m_pZ[m_W+m_Tap+1]; + m_pZP = dp1; + *dp1 = d; + m_pZ[m_W] = d; + d = 0; + for( int i = 0; i <= m_Tap; i++ ){ + d += (*dp1--) * (*hp++); + } + m_W++; + if( m_W > m_Tap ) m_W = 0; + return d; +} +//--------------------------------------------------------------------------- +double __fastcall CFIR2::Do(double *hp) +{ + double d = 0; + double *dp = m_pZP; + for( int i = 0; i <= m_Tap; i++ ){ + d += (*dp--) * (*hp++); + } + return d; +} +//--------------------------------------------------------------------------- +void __fastcall CFIR2::Do(double &d, double &j, double *hp) +{ + double *dp1 = &m_pZ[m_W+m_Tap+1]; + m_pZP = dp1; + *dp1 = d; + m_pZ[m_W] = d; + double dd = 0; + for( int i = 0; i <= m_Tap; i++ ){ + dd += (*dp1--) * (*hp++); + } + j = dd; + d= m_pZ[m_W+m_TapHalf+1]; + m_W++; + if( m_W > m_Tap ) m_W = 0; +} + diff --git a/fir.h b/fir.h new file mode 100644 index 0000000..9b3327a --- /dev/null +++ b/fir.h @@ -0,0 +1,173 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------------- +#ifndef firH +#define firH +#include //JA7UDE 0428 + +//--------------------------------------------------------------------------- +#include "ComLib.h" +#define TAPMAX 512 + +#pragma pack(push, 4) +#define PI 3.1415926535897932384626433832795 + +enum { + ffLPF, + ffHPF, + ffBPF, + ffBEF, + ffUSER, + ffLMS, +}; + +typedef struct { + int n; + int typ; + double fs; + double fcl; + double fch; + double att; + double gain; + double fc; + double hp[TAPMAX+1]; /* 係数配列 */ +}FIR; +void MakeFilter(double *HP, int tap, int type, double fs, double fcl, double fch, double att, double gain); +void MakeFilter(double *HP, FIR *fp); +void MakeHilbert(double *H, int N, double fs, double fc1, double fc2); +void DrawGraph(Graphics::TBitmap *pBitmap, const double *H, int Tap, int Over, int &nmax, int init, TColor col); +void DrawGraphIIR(Graphics::TBitmap *pBitmap, double a0, double a1, double a2, double b1, double b2, int Over, int &nmax, int init, TColor col); + +double __fastcall DoFIR(double *hp, double *zp, double d, int tap); + +//--------------------------------------------------------------------------- +// ダブルバッファによるFIRフィルタ +class CFIR2 +{ +private: + int m_Tap; + double *m_pZ; + double *m_pH; + double *m_pZP; + + int m_W; + int m_TapHalf; +public: + CFIR2(); + ~CFIR2(); + void __fastcall Create(int tap, int type, double fs, double fcl, double fch, double att, double gain); + void __fastcall Clear(void); + void __fastcall Create(int tap); + double __fastcall Do(double d); + double __fastcall Do(double d, double *hp); + double __fastcall Do(double *hp); + void __fastcall Do(double &d, double &j, double *hp); + + inline double GetHD(int n){return m_pH[n];}; + inline double *GetHP(void){return m_pH;}; + inline int GetTap(void){return m_Tap;}; +}; + +#define LMSTAP 192 +class CLMS +{ +private: + double *Z; // FIR Z Application + double *D; // LMS Delay; + + double m_lmsADJSC; // スケール調整値 + double m_lmsErr; // LMS 誤差データ + double m_lmsMErr; // LMS 誤差データ(×2μ) + double m_D; +public: + int m_Tap; +// int m_lmsInv; // LMS InvOutput +// int m_lmsDelay; // LMS Delay + int m_lmsAGC; // LMS AGC + double m_lmsMU2; // LMS 2μ + double m_lmsGM; // LMS γ + double *H; // アプリケーションフィルタの係数 + + int m_Tap_N; + int m_lmsDelay_N; + double m_lmsMU2_N; + double m_lmsGM_N; +public: + CLMS(); + ~CLMS(); + + double Do(double d); + double DoN(double d); + void SetAN(int sw); + int Sig(double d); +}; + +#define NOTCHTAPMAX 256 +class CNotch +{ +public: + CFIR2 m_Notch; +// double *m_pZ; // FIR Z Application +// double *m_pH; // FIR K Application + int m_tap; +public: + double m_freq; +public: + __fastcall CNotch(); + __fastcall ~CNotch(); + void __fastcall SetNotchFreq(double fq); + double __fastcall Do(double d); +}; + +class CIIRTANK +{ +private: + double z1, z2; +public: + double a0; + double b1, b2; +public: + CIIRTANK(); + void SetFreq(double f, double smp, double bw); + double Do(double d); +}; + +#define IIRMAX 16 +class CIIR +{ +private: + double *Z; +public: + double *A; + double *B; + int m_order; + int m_bc; + double m_rp; + CIIR(); + ~CIIR(); + void MakeIIR(double fc, double fs, int order, int bc, double rp); + double Do(double d); + void Clear(void); +}; +#pragma pack(pop) + +void DrawGraphIIR(Graphics::TBitmap *pBitmap, CIIR *ip, int Over, int &nmax, int init, TColor col); +#endif + diff --git a/fskid.txt b/fskid.txt new file mode 100644 index 0000000..c5b5a39 --- /dev/null +++ b/fskid.txt @@ -0,0 +1,106 @@ +MMSSTV FSKID + +[Code composition] + +The FSKID used in MMSSTV is sent by using 45.45 baudot FSK. One symbol is composed of 6 bits (B5-B0). + + 1500Hz 300ms (1900Hz in a narrow mode) + 2100Hz 100ms + 1900Hz 22ms start bit + B5 22ms (1=1900Hz, 0=2100Hz) + B4 22ms : + B3 22ms : + B2 22ms + B1 22ms + B0 22ms + B5 22ms + : + B0 22ms + B5 22ms + : + B0 22ms + : + +[Call sign] + + $2A C1 C2 ... CN $01 XSUM + XSUM = C1 xor C2 xor ... xor CN + + C1 to CN are modified ASCII code. Code symbols $20 to $5F are represented by $00 to $3F in Cx (x = 1 to N). + +[Contest number (3 digits or 4 digits and less than 4096)] +Following the call sign, MMSSTV sends the contest number as follows: + + $02 HH LL XSUM + HH = Upper 6 bits of the number + LL = Lower 6 bits of the number + XSUM = $02 xor HH xor LL + +[Contest number (any string)] +Following the call sign, MMSSTV sends the contest number as follows: + + S1 S2 ... SN $01 XSUM + XSUM = S1 xor S2 xor ... xor SN +Si (i = 1 to N) is ASCII code minus $20. The original code symbols $30 to $5F are represented by $10 to $3F. + +[Notice] +You can freely use the MMSSTV compatible FSKID in your program. You do not have to notify me in any case. + +73, Mako + + +******************** Japanese ******************** + +MMSSTVのFSKID + + MMSSTVのFSKIDは6bits(B5-B0)を1シンボルとする以下のようなFSK(45.45bps)で伝送します。 + + 1500Hz 300ms (狭帯域モード時は1900Hz) + 2100Hz 100ms + 1900Hz 22ms start bit + B5 22ms (1=1900Hz, 0=2100Hz) + B4 22ms : + B3 22ms : + B2 22ms + B1 22ms + B0 22ms + B5 22ms + : + B0 22ms + B5 22ms + : + B0 22ms + : + +コールサイン +~~~~~~~~~~~~ + 以下のように伝送します。 + + $2A C1 C2 ... CN $01 XSUM + XSUM = C1 〜 CNまでのXOR値 + + C1-CNのコールサインはASCIIコード$20〜$5Fまでを$00〜$3Fに変換して伝送します。 + +コンテストNR(3桁または4桁の数値で値が4095以下の場合) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + コールサインに続けて以下のように伝送します。 + + $02 HH LL XSUM + HH = NRの上位6bits + LL = NRの下位6bits + XSUM = $02 〜 MMまでのXOR値 + +コンテストNR(任意の文字列の場合) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + コールサインに続けて以下のように伝送します。 + + S1 S2 ... SN $01 XSUM + XSUM = S1 〜 SNまでのXOR値 + + S1-SNの文字列はASCIIコード$30〜$5Fまでを$10〜$3Fに変換して伝送します。 + +その他 +~~~~~~ + MMSSTVコンパチブルのFSKIDを他の装置に組み込むことは完全に自由です。私への連絡は一切必要ありません。 + +73, Mako \ No newline at end of file diff --git a/jpeg/JCAPIMIN.C b/jpeg/JCAPIMIN.C new file mode 100644 index 0000000..5d4ddda --- /dev/null +++ b/jpeg/JCAPIMIN.C @@ -0,0 +1,280 @@ +/* + * jcapimin.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains application interface code for the compression half + * of the JPEG library. These are the "minimum" API routines that may be + * needed in either the normal full-compression case or the transcoding-only + * case. + * + * Most of the routines intended to be called directly by an application + * are in this file or in jcapistd.c. But also see jcparam.c for + * parameter-setup helper routines, jcomapi.c for routines shared by + * compression and decompression, and jctrans.c for the transcoding case. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* + * Initialization of a JPEG compression object. + * The error manager must already be set up (in case memory manager fails). + */ + +GLOBAL(void) +jpeg_CreateCompress (j_compress_ptr cinfo, int version, size_t structsize) +{ + int i; + + /* Guard against version mismatches between library and caller. */ + cinfo->mem = NULL; /* so jpeg_destroy knows mem mgr not called */ + if (version != JPEG_LIB_VERSION) + ERREXIT2(cinfo, JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version); + if (structsize != SIZEOF(struct jpeg_compress_struct)) + ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE, + (int) SIZEOF(struct jpeg_compress_struct), (int) structsize); + + /* For debugging purposes, we zero the whole master structure. + * But the application has already set the err pointer, and may have set + * client_data, so we have to save and restore those fields. + * Note: if application hasn't set client_data, tools like Purify may + * complain here. + */ + { + struct jpeg_error_mgr * err = cinfo->err; + void * client_data = cinfo->client_data; /* ignore Purify complaint here */ + MEMZERO(cinfo, SIZEOF(struct jpeg_compress_struct)); + cinfo->err = err; + cinfo->client_data = client_data; + } + cinfo->is_decompressor = FALSE; + + /* Initialize a memory manager instance for this object */ + jinit_memory_mgr((j_common_ptr) cinfo); + + /* Zero out pointers to permanent structures. */ + cinfo->progress = NULL; + cinfo->dest = NULL; + + cinfo->comp_info = NULL; + + for (i = 0; i < NUM_QUANT_TBLS; i++) + cinfo->quant_tbl_ptrs[i] = NULL; + + for (i = 0; i < NUM_HUFF_TBLS; i++) { + cinfo->dc_huff_tbl_ptrs[i] = NULL; + cinfo->ac_huff_tbl_ptrs[i] = NULL; + } + + cinfo->script_space = NULL; + + cinfo->input_gamma = 1.0; /* in case application forgets */ + + /* OK, I'm ready */ + cinfo->global_state = CSTATE_START; +} + + +/* + * Destruction of a JPEG compression object + */ + +GLOBAL(void) +jpeg_destroy_compress (j_compress_ptr cinfo) +{ + jpeg_destroy((j_common_ptr) cinfo); /* use common routine */ +} + + +/* + * Abort processing of a JPEG compression operation, + * but don't destroy the object itself. + */ + +GLOBAL(void) +jpeg_abort_compress (j_compress_ptr cinfo) +{ + jpeg_abort((j_common_ptr) cinfo); /* use common routine */ +} + + +/* + * Forcibly suppress or un-suppress all quantization and Huffman tables. + * Marks all currently defined tables as already written (if suppress) + * or not written (if !suppress). This will control whether they get emitted + * by a subsequent jpeg_start_compress call. + * + * This routine is exported for use by applications that want to produce + * abbreviated JPEG datastreams. It logically belongs in jcparam.c, but + * since it is called by jpeg_start_compress, we put it here --- otherwise + * jcparam.o would be linked whether the application used it or not. + */ + +GLOBAL(void) +jpeg_suppress_tables (j_compress_ptr cinfo, boolean suppress) +{ + int i; + JQUANT_TBL * qtbl; + JHUFF_TBL * htbl; + + for (i = 0; i < NUM_QUANT_TBLS; i++) { + if ((qtbl = cinfo->quant_tbl_ptrs[i]) != NULL) + qtbl->sent_table = suppress; + } + + for (i = 0; i < NUM_HUFF_TBLS; i++) { + if ((htbl = cinfo->dc_huff_tbl_ptrs[i]) != NULL) + htbl->sent_table = suppress; + if ((htbl = cinfo->ac_huff_tbl_ptrs[i]) != NULL) + htbl->sent_table = suppress; + } +} + + +/* + * Finish JPEG compression. + * + * If a multipass operating mode was selected, this may do a great deal of + * work including most of the actual output. + */ + +GLOBAL(void) +jpeg_finish_compress (j_compress_ptr cinfo) +{ + JDIMENSION iMCU_row; + + if (cinfo->global_state == CSTATE_SCANNING || + cinfo->global_state == CSTATE_RAW_OK) { + /* Terminate first pass */ + if (cinfo->next_scanline < cinfo->image_height) + ERREXIT(cinfo, JERR_TOO_LITTLE_DATA); + (*cinfo->master->finish_pass) (cinfo); + } else if (cinfo->global_state != CSTATE_WRCOEFS) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + /* Perform any remaining passes */ + while (! cinfo->master->is_last_pass) { + (*cinfo->master->prepare_for_pass) (cinfo); + for (iMCU_row = 0; iMCU_row < cinfo->total_iMCU_rows; iMCU_row++) { + if (cinfo->progress != NULL) { + cinfo->progress->pass_counter = (long) iMCU_row; + cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows; + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + } + /* We bypass the main controller and invoke coef controller directly; + * all work is being done from the coefficient buffer. + */ + if (! (*cinfo->coef->compress_data) (cinfo, (JSAMPIMAGE) NULL)) + ERREXIT(cinfo, JERR_CANT_SUSPEND); + } + (*cinfo->master->finish_pass) (cinfo); + } + /* Write EOI, do final cleanup */ + (*cinfo->marker->write_file_trailer) (cinfo); + (*cinfo->dest->term_destination) (cinfo); + /* We can use jpeg_abort to release memory and reset global_state */ + jpeg_abort((j_common_ptr) cinfo); +} + + +/* + * Write a special marker. + * This is only recommended for writing COM or APPn markers. + * Must be called after jpeg_start_compress() and before + * first call to jpeg_write_scanlines() or jpeg_write_raw_data(). + */ + +GLOBAL(void) +jpeg_write_marker (j_compress_ptr cinfo, int marker, + const JOCTET *dataptr, unsigned int datalen) +{ + JMETHOD(void, write_marker_byte, (j_compress_ptr info, int val)); + + if (cinfo->next_scanline != 0 || + (cinfo->global_state != CSTATE_SCANNING && + cinfo->global_state != CSTATE_RAW_OK && + cinfo->global_state != CSTATE_WRCOEFS)) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + (*cinfo->marker->write_marker_header) (cinfo, marker, datalen); + write_marker_byte = cinfo->marker->write_marker_byte; /* copy for speed */ + while (datalen--) { + (*write_marker_byte) (cinfo, *dataptr); + dataptr++; + } +} + +/* Same, but piecemeal. */ + +GLOBAL(void) +jpeg_write_m_header (j_compress_ptr cinfo, int marker, unsigned int datalen) +{ + if (cinfo->next_scanline != 0 || + (cinfo->global_state != CSTATE_SCANNING && + cinfo->global_state != CSTATE_RAW_OK && + cinfo->global_state != CSTATE_WRCOEFS)) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + (*cinfo->marker->write_marker_header) (cinfo, marker, datalen); +} + +GLOBAL(void) +jpeg_write_m_byte (j_compress_ptr cinfo, int val) +{ + (*cinfo->marker->write_marker_byte) (cinfo, val); +} + + +/* + * Alternate compression function: just write an abbreviated table file. + * Before calling this, all parameters and a data destination must be set up. + * + * To produce a pair of files containing abbreviated tables and abbreviated + * image data, one would proceed as follows: + * + * initialize JPEG object + * set JPEG parameters + * set destination to table file + * jpeg_write_tables(cinfo); + * set destination to image file + * jpeg_start_compress(cinfo, FALSE); + * write data... + * jpeg_finish_compress(cinfo); + * + * jpeg_write_tables has the side effect of marking all tables written + * (same as jpeg_suppress_tables(..., TRUE)). Thus a subsequent start_compress + * will not re-emit the tables unless it is passed write_all_tables=TRUE. + */ + +GLOBAL(void) +jpeg_write_tables (j_compress_ptr cinfo) +{ + if (cinfo->global_state != CSTATE_START) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + /* (Re)initialize error mgr and destination modules */ + (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); + (*cinfo->dest->init_destination) (cinfo); + /* Initialize the marker writer ... bit of a crock to do it here. */ + jinit_marker_writer(cinfo); + /* Write them tables! */ + (*cinfo->marker->write_tables_only) (cinfo); + /* And clean up. */ + (*cinfo->dest->term_destination) (cinfo); + /* + * In library releases up through v6a, we called jpeg_abort() here to free + * any working memory allocated by the destination manager and marker + * writer. Some applications had a problem with that: they allocated space + * of their own from the library memory manager, and didn't want it to go + * away during write_tables. So now we do nothing. This will cause a + * memory leak if an app calls write_tables repeatedly without doing a full + * compression cycle or otherwise resetting the JPEG object. However, that + * seems less bad than unexpectedly freeing memory in the normal case. + * An app that prefers the old behavior can call jpeg_abort for itself after + * each call to jpeg_write_tables(). + */ +} diff --git a/jpeg/JCAPISTD.C b/jpeg/JCAPISTD.C new file mode 100644 index 0000000..f49e8e2 --- /dev/null +++ b/jpeg/JCAPISTD.C @@ -0,0 +1,161 @@ +/* + * jcapistd.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains application interface code for the compression half + * of the JPEG library. These are the "standard" API routines that are + * used in the normal full-compression case. They are not used by a + * transcoding-only application. Note that if an application links in + * jpeg_start_compress, it will end up linking in the entire compressor. + * We thus must separate this file from jcapimin.c to avoid linking the + * whole compression library into a transcoder. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* + * Compression initialization. + * Before calling this, all parameters and a data destination must be set up. + * + * We require a write_all_tables parameter as a failsafe check when writing + * multiple datastreams from the same compression object. Since prior runs + * will have left all the tables marked sent_table=TRUE, a subsequent run + * would emit an abbreviated stream (no tables) by default. This may be what + * is wanted, but for safety's sake it should not be the default behavior: + * programmers should have to make a deliberate choice to emit abbreviated + * images. Therefore the documentation and examples should encourage people + * to pass write_all_tables=TRUE; then it will take active thought to do the + * wrong thing. + */ + +GLOBAL(void) +jpeg_start_compress (j_compress_ptr cinfo, boolean write_all_tables) +{ + if (cinfo->global_state != CSTATE_START) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + if (write_all_tables) + jpeg_suppress_tables(cinfo, FALSE); /* mark all tables to be written */ + + /* (Re)initialize error mgr and destination modules */ + (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); + (*cinfo->dest->init_destination) (cinfo); + /* Perform master selection of active modules */ + jinit_compress_master(cinfo); + /* Set up for the first pass */ + (*cinfo->master->prepare_for_pass) (cinfo); + /* Ready for application to drive first pass through jpeg_write_scanlines + * or jpeg_write_raw_data. + */ + cinfo->next_scanline = 0; + cinfo->global_state = (cinfo->raw_data_in ? CSTATE_RAW_OK : CSTATE_SCANNING); +} + + +/* + * Write some scanlines of data to the JPEG compressor. + * + * The return value will be the number of lines actually written. + * This should be less than the supplied num_lines only in case that + * the data destination module has requested suspension of the compressor, + * or if more than image_height scanlines are passed in. + * + * Note: we warn about excess calls to jpeg_write_scanlines() since + * this likely signals an application programmer error. However, + * excess scanlines passed in the last valid call are *silently* ignored, + * so that the application need not adjust num_lines for end-of-image + * when using a multiple-scanline buffer. + */ + +GLOBAL(JDIMENSION) +jpeg_write_scanlines (j_compress_ptr cinfo, JSAMPARRAY scanlines, + JDIMENSION num_lines) +{ + JDIMENSION row_ctr, rows_left; + + if (cinfo->global_state != CSTATE_SCANNING) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + if (cinfo->next_scanline >= cinfo->image_height) + WARNMS(cinfo, JWRN_TOO_MUCH_DATA); + + /* Call progress monitor hook if present */ + if (cinfo->progress != NULL) { + cinfo->progress->pass_counter = (long) cinfo->next_scanline; + cinfo->progress->pass_limit = (long) cinfo->image_height; + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + } + + /* Give master control module another chance if this is first call to + * jpeg_write_scanlines. This lets output of the frame/scan headers be + * delayed so that application can write COM, etc, markers between + * jpeg_start_compress and jpeg_write_scanlines. + */ + if (cinfo->master->call_pass_startup) + (*cinfo->master->pass_startup) (cinfo); + + /* Ignore any extra scanlines at bottom of image. */ + rows_left = cinfo->image_height - cinfo->next_scanline; + if (num_lines > rows_left) + num_lines = rows_left; + + row_ctr = 0; + (*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, num_lines); + cinfo->next_scanline += row_ctr; + return row_ctr; +} + + +/* + * Alternate entry point to write raw data. + * Processes exactly one iMCU row per call, unless suspended. + */ + +GLOBAL(JDIMENSION) +jpeg_write_raw_data (j_compress_ptr cinfo, JSAMPIMAGE data, + JDIMENSION num_lines) +{ + JDIMENSION lines_per_iMCU_row; + + if (cinfo->global_state != CSTATE_RAW_OK) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + if (cinfo->next_scanline >= cinfo->image_height) { + WARNMS(cinfo, JWRN_TOO_MUCH_DATA); + return 0; + } + + /* Call progress monitor hook if present */ + if (cinfo->progress != NULL) { + cinfo->progress->pass_counter = (long) cinfo->next_scanline; + cinfo->progress->pass_limit = (long) cinfo->image_height; + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + } + + /* Give master control module another chance if this is first call to + * jpeg_write_raw_data. This lets output of the frame/scan headers be + * delayed so that application can write COM, etc, markers between + * jpeg_start_compress and jpeg_write_raw_data. + */ + if (cinfo->master->call_pass_startup) + (*cinfo->master->pass_startup) (cinfo); + + /* Verify that at least one iMCU row has been passed. */ + lines_per_iMCU_row = cinfo->max_v_samp_factor * DCTSIZE; + if (num_lines < lines_per_iMCU_row) + ERREXIT(cinfo, JERR_BUFFER_SIZE); + + /* Directly compress the row. */ + if (! (*cinfo->coef->compress_data) (cinfo, data)) { + /* If compressor did not consume the whole row, suspend processing. */ + return 0; + } + + /* OK, we processed one iMCU row. */ + cinfo->next_scanline += lines_per_iMCU_row; + return lines_per_iMCU_row; +} diff --git a/jpeg/JCCOEFCT.C b/jpeg/JCCOEFCT.C new file mode 100644 index 0000000..dd76a57 --- /dev/null +++ b/jpeg/JCCOEFCT.C @@ -0,0 +1,449 @@ +/* + * jccoefct.c + * + * Copyright (C) 1994-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the coefficient buffer controller for compression. + * This controller is the top level of the JPEG compressor proper. + * The coefficient buffer lies between forward-DCT and entropy encoding steps. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* We use a full-image coefficient buffer when doing Huffman optimization, + * and also for writing multiple-scan JPEG files. In all cases, the DCT + * step is run during the first pass, and subsequent passes need only read + * the buffered coefficients. + */ +#ifdef ENTROPY_OPT_SUPPORTED +#define FULL_COEF_BUFFER_SUPPORTED +#else +#ifdef C_MULTISCAN_FILES_SUPPORTED +#define FULL_COEF_BUFFER_SUPPORTED +#endif +#endif + + +/* Private buffer controller object */ + +typedef struct { + struct jpeg_c_coef_controller pub; /* public fields */ + + JDIMENSION iMCU_row_num; /* iMCU row # within image */ + JDIMENSION mcu_ctr; /* counts MCUs processed in current row */ + int MCU_vert_offset; /* counts MCU rows within iMCU row */ + int MCU_rows_per_iMCU_row; /* number of such rows needed */ + + /* For single-pass compression, it's sufficient to buffer just one MCU + * (although this may prove a bit slow in practice). We allocate a + * workspace of C_MAX_BLOCKS_IN_MCU coefficient blocks, and reuse it for each + * MCU constructed and sent. (On 80x86, the workspace is FAR even though + * it's not really very big; this is to keep the module interfaces unchanged + * when a large coefficient buffer is necessary.) + * In multi-pass modes, this array points to the current MCU's blocks + * within the virtual arrays. + */ + JBLOCKROW MCU_buffer[C_MAX_BLOCKS_IN_MCU]; + + /* In multi-pass modes, we need a virtual block array for each component. */ + jvirt_barray_ptr whole_image[MAX_COMPONENTS]; +} my_coef_controller; + +typedef my_coef_controller * my_coef_ptr; + + +/* Forward declarations */ +METHODDEF(boolean) compress_data + JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf)); +#ifdef FULL_COEF_BUFFER_SUPPORTED +METHODDEF(boolean) compress_first_pass + JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf)); +METHODDEF(boolean) compress_output + JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf)); +#endif + + +LOCAL(void) +start_iMCU_row (j_compress_ptr cinfo) +/* Reset within-iMCU-row counters for a new row */ +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + + /* In an interleaved scan, an MCU row is the same as an iMCU row. + * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows. + * But at the bottom of the image, process only what's left. + */ + if (cinfo->comps_in_scan > 1) { + coef->MCU_rows_per_iMCU_row = 1; + } else { + if (coef->iMCU_row_num < (cinfo->total_iMCU_rows-1)) + coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor; + else + coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height; + } + + coef->mcu_ctr = 0; + coef->MCU_vert_offset = 0; +} + + +/* + * Initialize for a processing pass. + */ + +METHODDEF(void) +start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode) +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + + coef->iMCU_row_num = 0; + start_iMCU_row(cinfo); + + switch (pass_mode) { + case JBUF_PASS_THRU: + if (coef->whole_image[0] != NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + coef->pub.compress_data = compress_data; + break; +#ifdef FULL_COEF_BUFFER_SUPPORTED + case JBUF_SAVE_AND_PASS: + if (coef->whole_image[0] == NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + coef->pub.compress_data = compress_first_pass; + break; + case JBUF_CRANK_DEST: + if (coef->whole_image[0] == NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + coef->pub.compress_data = compress_output; + break; +#endif + default: + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + break; + } +} + + +/* + * Process some data in the single-pass case. + * We process the equivalent of one fully interleaved MCU row ("iMCU" row) + * per call, ie, v_samp_factor block rows for each component in the image. + * Returns TRUE if the iMCU row is completed, FALSE if suspended. + * + * NB: input_buf contains a plane for each component in image, + * which we index according to the component's SOF position. + */ + +METHODDEF(boolean) +compress_data (j_compress_ptr cinfo, JSAMPIMAGE input_buf) +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + JDIMENSION MCU_col_num; /* index of current MCU within row */ + JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1; + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + int blkn, bi, ci, yindex, yoffset, blockcnt; + JDIMENSION ypos, xpos; + jpeg_component_info *compptr; + + /* Loop to write as much as one whole iMCU row */ + for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; + yoffset++) { + for (MCU_col_num = coef->mcu_ctr; MCU_col_num <= last_MCU_col; + MCU_col_num++) { + /* Determine where data comes from in input_buf and do the DCT thing. + * Each call on forward_DCT processes a horizontal row of DCT blocks + * as wide as an MCU; we rely on having allocated the MCU_buffer[] blocks + * sequentially. Dummy blocks at the right or bottom edge are filled in + * specially. The data in them does not matter for image reconstruction, + * so we fill them with values that will encode to the smallest amount of + * data, viz: all zeroes in the AC entries, DC entries equal to previous + * block's DC value. (Thanks to Thomas Kinsman for this idea.) + */ + blkn = 0; + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width + : compptr->last_col_width; + xpos = MCU_col_num * compptr->MCU_sample_width; + ypos = yoffset * DCTSIZE; /* ypos == (yoffset+yindex) * DCTSIZE */ + for (yindex = 0; yindex < compptr->MCU_height; yindex++) { + if (coef->iMCU_row_num < last_iMCU_row || + yoffset+yindex < compptr->last_row_height) { + (*cinfo->fdct->forward_DCT) (cinfo, compptr, + input_buf[compptr->component_index], + coef->MCU_buffer[blkn], + ypos, xpos, (JDIMENSION) blockcnt); + if (blockcnt < compptr->MCU_width) { + /* Create some dummy blocks at the right edge of the image. */ + jzero_far((void FAR *) coef->MCU_buffer[blkn + blockcnt], + (compptr->MCU_width - blockcnt) * SIZEOF(JBLOCK)); + for (bi = blockcnt; bi < compptr->MCU_width; bi++) { + coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn+bi-1][0][0]; + } + } + } else { + /* Create a row of dummy blocks at the bottom of the image. */ + jzero_far((void FAR *) coef->MCU_buffer[blkn], + compptr->MCU_width * SIZEOF(JBLOCK)); + for (bi = 0; bi < compptr->MCU_width; bi++) { + coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn-1][0][0]; + } + } + blkn += compptr->MCU_width; + ypos += DCTSIZE; + } + } + /* Try to write the MCU. In event of a suspension failure, we will + * re-DCT the MCU on restart (a bit inefficient, could be fixed...) + */ + if (! (*cinfo->entropy->encode_mcu) (cinfo, coef->MCU_buffer)) { + /* Suspension forced; update state counters and exit */ + coef->MCU_vert_offset = yoffset; + coef->mcu_ctr = MCU_col_num; + return FALSE; + } + } + /* Completed an MCU row, but perhaps not an iMCU row */ + coef->mcu_ctr = 0; + } + /* Completed the iMCU row, advance counters for next one */ + coef->iMCU_row_num++; + start_iMCU_row(cinfo); + return TRUE; +} + + +#ifdef FULL_COEF_BUFFER_SUPPORTED + +/* + * Process some data in the first pass of a multi-pass case. + * We process the equivalent of one fully interleaved MCU row ("iMCU" row) + * per call, ie, v_samp_factor block rows for each component in the image. + * This amount of data is read from the source buffer, DCT'd and quantized, + * and saved into the virtual arrays. We also generate suitable dummy blocks + * as needed at the right and lower edges. (The dummy blocks are constructed + * in the virtual arrays, which have been padded appropriately.) This makes + * it possible for subsequent passes not to worry about real vs. dummy blocks. + * + * We must also emit the data to the entropy encoder. This is conveniently + * done by calling compress_output() after we've loaded the current strip + * of the virtual arrays. + * + * NB: input_buf contains a plane for each component in image. All + * components are DCT'd and loaded into the virtual arrays in this pass. + * However, it may be that only a subset of the components are emitted to + * the entropy encoder during this first pass; be careful about looking + * at the scan-dependent variables (MCU dimensions, etc). + */ + +METHODDEF(boolean) +compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf) +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + JDIMENSION blocks_across, MCUs_across, MCUindex; + int bi, ci, h_samp_factor, block_row, block_rows, ndummy; + JCOEF lastDC; + jpeg_component_info *compptr; + JBLOCKARRAY buffer; + JBLOCKROW thisblockrow, lastblockrow; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Align the virtual buffer for this component. */ + buffer = (*cinfo->mem->access_virt_barray) + ((j_common_ptr) cinfo, coef->whole_image[ci], + coef->iMCU_row_num * compptr->v_samp_factor, + (JDIMENSION) compptr->v_samp_factor, TRUE); + /* Count non-dummy DCT block rows in this iMCU row. */ + if (coef->iMCU_row_num < last_iMCU_row) + block_rows = compptr->v_samp_factor; + else { + /* NB: can't use last_row_height here, since may not be set! */ + block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor); + if (block_rows == 0) block_rows = compptr->v_samp_factor; + } + blocks_across = compptr->width_in_blocks; + h_samp_factor = compptr->h_samp_factor; + /* Count number of dummy blocks to be added at the right margin. */ + ndummy = (int) (blocks_across % h_samp_factor); + if (ndummy > 0) + ndummy = h_samp_factor - ndummy; + /* Perform DCT for all non-dummy blocks in this iMCU row. Each call + * on forward_DCT processes a complete horizontal row of DCT blocks. + */ + for (block_row = 0; block_row < block_rows; block_row++) { + thisblockrow = buffer[block_row]; + (*cinfo->fdct->forward_DCT) (cinfo, compptr, + input_buf[ci], thisblockrow, + (JDIMENSION) (block_row * DCTSIZE), + (JDIMENSION) 0, blocks_across); + if (ndummy > 0) { + /* Create dummy blocks at the right edge of the image. */ + thisblockrow += blocks_across; /* => first dummy block */ + jzero_far((void FAR *) thisblockrow, ndummy * SIZEOF(JBLOCK)); + lastDC = thisblockrow[-1][0]; + for (bi = 0; bi < ndummy; bi++) { + thisblockrow[bi][0] = lastDC; + } + } + } + /* If at end of image, create dummy block rows as needed. + * The tricky part here is that within each MCU, we want the DC values + * of the dummy blocks to match the last real block's DC value. + * This squeezes a few more bytes out of the resulting file... + */ + if (coef->iMCU_row_num == last_iMCU_row) { + blocks_across += ndummy; /* include lower right corner */ + MCUs_across = blocks_across / h_samp_factor; + for (block_row = block_rows; block_row < compptr->v_samp_factor; + block_row++) { + thisblockrow = buffer[block_row]; + lastblockrow = buffer[block_row-1]; + jzero_far((void FAR *) thisblockrow, + (size_t) (blocks_across * SIZEOF(JBLOCK))); + for (MCUindex = 0; MCUindex < MCUs_across; MCUindex++) { + lastDC = lastblockrow[h_samp_factor-1][0]; + for (bi = 0; bi < h_samp_factor; bi++) { + thisblockrow[bi][0] = lastDC; + } + thisblockrow += h_samp_factor; /* advance to next MCU in row */ + lastblockrow += h_samp_factor; + } + } + } + } + /* NB: compress_output will increment iMCU_row_num if successful. + * A suspension return will result in redoing all the work above next time. + */ + + /* Emit data to the entropy encoder, sharing code with subsequent passes */ + return compress_output(cinfo, input_buf); +} + + +/* + * Process some data in subsequent passes of a multi-pass case. + * We process the equivalent of one fully interleaved MCU row ("iMCU" row) + * per call, ie, v_samp_factor block rows for each component in the scan. + * The data is obtained from the virtual arrays and fed to the entropy coder. + * Returns TRUE if the iMCU row is completed, FALSE if suspended. + * + * NB: input_buf is ignored; it is likely to be a NULL pointer. + */ + +METHODDEF(boolean) +compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf) +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + JDIMENSION MCU_col_num; /* index of current MCU within row */ + int blkn, ci, xindex, yindex, yoffset; + JDIMENSION start_col; + JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN]; + JBLOCKROW buffer_ptr; + jpeg_component_info *compptr; + + /* Align the virtual buffers for the components used in this scan. + * NB: during first pass, this is safe only because the buffers will + * already be aligned properly, so jmemmgr.c won't need to do any I/O. + */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + buffer[ci] = (*cinfo->mem->access_virt_barray) + ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index], + coef->iMCU_row_num * compptr->v_samp_factor, + (JDIMENSION) compptr->v_samp_factor, FALSE); + } + + /* Loop to process one whole iMCU row */ + for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; + yoffset++) { + for (MCU_col_num = coef->mcu_ctr; MCU_col_num < cinfo->MCUs_per_row; + MCU_col_num++) { + /* Construct list of pointers to DCT blocks belonging to this MCU */ + blkn = 0; /* index of current DCT block within MCU */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + start_col = MCU_col_num * compptr->MCU_width; + for (yindex = 0; yindex < compptr->MCU_height; yindex++) { + buffer_ptr = buffer[ci][yindex+yoffset] + start_col; + for (xindex = 0; xindex < compptr->MCU_width; xindex++) { + coef->MCU_buffer[blkn++] = buffer_ptr++; + } + } + } + /* Try to write the MCU. */ + if (! (*cinfo->entropy->encode_mcu) (cinfo, coef->MCU_buffer)) { + /* Suspension forced; update state counters and exit */ + coef->MCU_vert_offset = yoffset; + coef->mcu_ctr = MCU_col_num; + return FALSE; + } + } + /* Completed an MCU row, but perhaps not an iMCU row */ + coef->mcu_ctr = 0; + } + /* Completed the iMCU row, advance counters for next one */ + coef->iMCU_row_num++; + start_iMCU_row(cinfo); + return TRUE; +} + +#endif /* FULL_COEF_BUFFER_SUPPORTED */ + + +/* + * Initialize coefficient buffer controller. + */ + +GLOBAL(void) +jinit_c_coef_controller (j_compress_ptr cinfo, boolean need_full_buffer) +{ + my_coef_ptr coef; + + coef = (my_coef_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_coef_controller)); + cinfo->coef = (struct jpeg_c_coef_controller *) coef; + coef->pub.start_pass = start_pass_coef; + + /* Create the coefficient buffer. */ + if (need_full_buffer) { +#ifdef FULL_COEF_BUFFER_SUPPORTED + /* Allocate a full-image virtual array for each component, */ + /* padded to a multiple of samp_factor DCT blocks in each direction. */ + int ci; + jpeg_component_info *compptr; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + coef->whole_image[ci] = (*cinfo->mem->request_virt_barray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, + (JDIMENSION) jround_up((long) compptr->width_in_blocks, + (long) compptr->h_samp_factor), + (JDIMENSION) jround_up((long) compptr->height_in_blocks, + (long) compptr->v_samp_factor), + (JDIMENSION) compptr->v_samp_factor); + } +#else + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); +#endif + } else { + /* We only need a single-MCU buffer. */ + JBLOCKROW buffer; + int i; + + buffer = (JBLOCKROW) + (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, + C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); + for (i = 0; i < C_MAX_BLOCKS_IN_MCU; i++) { + coef->MCU_buffer[i] = buffer + i; + } + coef->whole_image[0] = NULL; /* flag for no virtual arrays */ + } +} diff --git a/jpeg/JCCOLOR.C b/jpeg/JCCOLOR.C new file mode 100644 index 0000000..381e45b --- /dev/null +++ b/jpeg/JCCOLOR.C @@ -0,0 +1,459 @@ +/* + * jccolor.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains input colorspace conversion routines. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Private subobject */ + +typedef struct { + struct jpeg_color_converter pub; /* public fields */ + + /* Private state for RGB->YCC conversion */ + INT32 * rgb_ycc_tab; /* => table for RGB to YCbCr conversion */ +} my_color_converter; + +typedef my_color_converter * my_cconvert_ptr; + + +/**************** RGB -> YCbCr conversion: most common case **************/ + +/* + * YCbCr is defined per CCIR 601-1, except that Cb and Cr are + * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. + * The conversion equations to be implemented are therefore + * Y = 0.29900 * R + 0.58700 * G + 0.11400 * B + * Cb = -0.16874 * R - 0.33126 * G + 0.50000 * B + CENTERJSAMPLE + * Cr = 0.50000 * R - 0.41869 * G - 0.08131 * B + CENTERJSAMPLE + * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.) + * Note: older versions of the IJG code used a zero offset of MAXJSAMPLE/2, + * rather than CENTERJSAMPLE, for Cb and Cr. This gave equal positive and + * negative swings for Cb/Cr, but meant that grayscale values (Cb=Cr=0) + * were not represented exactly. Now we sacrifice exact representation of + * maximum red and maximum blue in order to get exact grayscales. + * + * To avoid floating-point arithmetic, we represent the fractional constants + * as integers scaled up by 2^16 (about 4 digits precision); we have to divide + * the products by 2^16, with appropriate rounding, to get the correct answer. + * + * For even more speed, we avoid doing any multiplications in the inner loop + * by precalculating the constants times R,G,B for all possible values. + * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table); + * for 12-bit samples it is still acceptable. It's not very reasonable for + * 16-bit samples, but if you want lossless storage you shouldn't be changing + * colorspace anyway. + * The CENTERJSAMPLE offsets and the rounding fudge-factor of 0.5 are included + * in the tables to save adding them separately in the inner loop. + */ + +#define SCALEBITS 16 /* speediest right-shift on some machines */ +#define CBCR_OFFSET ((INT32) CENTERJSAMPLE << SCALEBITS) +#define ONE_HALF ((INT32) 1 << (SCALEBITS-1)) +#define FIX(x) ((INT32) ((x) * (1L< Y section */ +#define G_Y_OFF (1*(MAXJSAMPLE+1)) /* offset to G => Y section */ +#define B_Y_OFF (2*(MAXJSAMPLE+1)) /* etc. */ +#define R_CB_OFF (3*(MAXJSAMPLE+1)) +#define G_CB_OFF (4*(MAXJSAMPLE+1)) +#define B_CB_OFF (5*(MAXJSAMPLE+1)) +#define R_CR_OFF B_CB_OFF /* B=>Cb, R=>Cr are the same */ +#define G_CR_OFF (6*(MAXJSAMPLE+1)) +#define B_CR_OFF (7*(MAXJSAMPLE+1)) +#define TABLE_SIZE (8*(MAXJSAMPLE+1)) + + +/* + * Initialize for RGB->YCC colorspace conversion. + */ + +METHODDEF(void) +rgb_ycc_start (j_compress_ptr cinfo) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + INT32 * rgb_ycc_tab; + INT32 i; + + /* Allocate and fill in the conversion tables. */ + cconvert->rgb_ycc_tab = rgb_ycc_tab = (INT32 *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (TABLE_SIZE * SIZEOF(INT32))); + + for (i = 0; i <= MAXJSAMPLE; i++) { + rgb_ycc_tab[i+R_Y_OFF] = FIX(0.29900) * i; + rgb_ycc_tab[i+G_Y_OFF] = FIX(0.58700) * i; + rgb_ycc_tab[i+B_Y_OFF] = FIX(0.11400) * i + ONE_HALF; + rgb_ycc_tab[i+R_CB_OFF] = (-FIX(0.16874)) * i; + rgb_ycc_tab[i+G_CB_OFF] = (-FIX(0.33126)) * i; + /* We use a rounding fudge-factor of 0.5-epsilon for Cb and Cr. + * This ensures that the maximum output will round to MAXJSAMPLE + * not MAXJSAMPLE+1, and thus that we don't have to range-limit. + */ + rgb_ycc_tab[i+B_CB_OFF] = FIX(0.50000) * i + CBCR_OFFSET + ONE_HALF-1; +/* B=>Cb and R=>Cr tables are the same + rgb_ycc_tab[i+R_CR_OFF] = FIX(0.50000) * i + CBCR_OFFSET + ONE_HALF-1; +*/ + rgb_ycc_tab[i+G_CR_OFF] = (-FIX(0.41869)) * i; + rgb_ycc_tab[i+B_CR_OFF] = (-FIX(0.08131)) * i; + } +} + + +/* + * Convert some rows of samples to the JPEG colorspace. + * + * Note that we change from the application's interleaved-pixel format + * to our internal noninterleaved, one-plane-per-component format. + * The input buffer is therefore three times as wide as the output buffer. + * + * A starting row offset is provided only for the output buffer. The caller + * can easily adjust the passed input_buf value to accommodate any row + * offset required on that side. + */ + +METHODDEF(void) +rgb_ycc_convert (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + register int r, g, b; + register INT32 * ctab = cconvert->rgb_ycc_tab; + register JSAMPROW inptr; + register JSAMPROW outptr0, outptr1, outptr2; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->image_width; + + while (--num_rows >= 0) { + inptr = *input_buf++; + outptr0 = output_buf[0][output_row]; + outptr1 = output_buf[1][output_row]; + outptr2 = output_buf[2][output_row]; + output_row++; + for (col = 0; col < num_cols; col++) { + r = GETJSAMPLE(inptr[RGB_RED]); + g = GETJSAMPLE(inptr[RGB_GREEN]); + b = GETJSAMPLE(inptr[RGB_BLUE]); + inptr += RGB_PIXELSIZE; + /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations + * must be too; we do not need an explicit range-limiting operation. + * Hence the value being shifted is never negative, and we don't + * need the general RIGHT_SHIFT macro. + */ + /* Y */ + outptr0[col] = (JSAMPLE) + ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) + >> SCALEBITS); + /* Cb */ + outptr1[col] = (JSAMPLE) + ((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF]) + >> SCALEBITS); + /* Cr */ + outptr2[col] = (JSAMPLE) + ((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF]) + >> SCALEBITS); + } + } +} + + +/**************** Cases other than RGB -> YCbCr **************/ + + +/* + * Convert some rows of samples to the JPEG colorspace. + * This version handles RGB->grayscale conversion, which is the same + * as the RGB->Y portion of RGB->YCbCr. + * We assume rgb_ycc_start has been called (we only use the Y tables). + */ + +METHODDEF(void) +rgb_gray_convert (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + register int r, g, b; + register INT32 * ctab = cconvert->rgb_ycc_tab; + register JSAMPROW inptr; + register JSAMPROW outptr; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->image_width; + + while (--num_rows >= 0) { + inptr = *input_buf++; + outptr = output_buf[0][output_row]; + output_row++; + for (col = 0; col < num_cols; col++) { + r = GETJSAMPLE(inptr[RGB_RED]); + g = GETJSAMPLE(inptr[RGB_GREEN]); + b = GETJSAMPLE(inptr[RGB_BLUE]); + inptr += RGB_PIXELSIZE; + /* Y */ + outptr[col] = (JSAMPLE) + ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) + >> SCALEBITS); + } + } +} + + +/* + * Convert some rows of samples to the JPEG colorspace. + * This version handles Adobe-style CMYK->YCCK conversion, + * where we convert R=1-C, G=1-M, and B=1-Y to YCbCr using the same + * conversion as above, while passing K (black) unchanged. + * We assume rgb_ycc_start has been called. + */ + +METHODDEF(void) +cmyk_ycck_convert (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + register int r, g, b; + register INT32 * ctab = cconvert->rgb_ycc_tab; + register JSAMPROW inptr; + register JSAMPROW outptr0, outptr1, outptr2, outptr3; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->image_width; + + while (--num_rows >= 0) { + inptr = *input_buf++; + outptr0 = output_buf[0][output_row]; + outptr1 = output_buf[1][output_row]; + outptr2 = output_buf[2][output_row]; + outptr3 = output_buf[3][output_row]; + output_row++; + for (col = 0; col < num_cols; col++) { + r = MAXJSAMPLE - GETJSAMPLE(inptr[0]); + g = MAXJSAMPLE - GETJSAMPLE(inptr[1]); + b = MAXJSAMPLE - GETJSAMPLE(inptr[2]); + /* K passes through as-is */ + outptr3[col] = inptr[3]; /* don't need GETJSAMPLE here */ + inptr += 4; + /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations + * must be too; we do not need an explicit range-limiting operation. + * Hence the value being shifted is never negative, and we don't + * need the general RIGHT_SHIFT macro. + */ + /* Y */ + outptr0[col] = (JSAMPLE) + ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) + >> SCALEBITS); + /* Cb */ + outptr1[col] = (JSAMPLE) + ((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF]) + >> SCALEBITS); + /* Cr */ + outptr2[col] = (JSAMPLE) + ((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF]) + >> SCALEBITS); + } + } +} + + +/* + * Convert some rows of samples to the JPEG colorspace. + * This version handles grayscale output with no conversion. + * The source can be either plain grayscale or YCbCr (since Y == gray). + */ + +METHODDEF(void) +grayscale_convert (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows) +{ + register JSAMPROW inptr; + register JSAMPROW outptr; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->image_width; + int instride = cinfo->input_components; + + while (--num_rows >= 0) { + inptr = *input_buf++; + outptr = output_buf[0][output_row]; + output_row++; + for (col = 0; col < num_cols; col++) { + outptr[col] = inptr[0]; /* don't need GETJSAMPLE() here */ + inptr += instride; + } + } +} + + +/* + * Convert some rows of samples to the JPEG colorspace. + * This version handles multi-component colorspaces without conversion. + * We assume input_components == num_components. + */ + +METHODDEF(void) +null_convert (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows) +{ + register JSAMPROW inptr; + register JSAMPROW outptr; + register JDIMENSION col; + register int ci; + int nc = cinfo->num_components; + JDIMENSION num_cols = cinfo->image_width; + + while (--num_rows >= 0) { + /* It seems fastest to make a separate pass for each component. */ + for (ci = 0; ci < nc; ci++) { + inptr = *input_buf; + outptr = output_buf[ci][output_row]; + for (col = 0; col < num_cols; col++) { + outptr[col] = inptr[ci]; /* don't need GETJSAMPLE() here */ + inptr += nc; + } + } + input_buf++; + output_row++; + } +} + + +/* + * Empty method for start_pass. + */ + +METHODDEF(void) +null_method (j_compress_ptr cinfo) +{ + /* no work needed */ +} + + +/* + * Module initialization routine for input colorspace conversion. + */ + +GLOBAL(void) +jinit_color_converter (j_compress_ptr cinfo) +{ + my_cconvert_ptr cconvert; + + cconvert = (my_cconvert_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_color_converter)); + cinfo->cconvert = (struct jpeg_color_converter *) cconvert; + /* set start_pass to null method until we find out differently */ + cconvert->pub.start_pass = null_method; + + /* Make sure input_components agrees with in_color_space */ + switch (cinfo->in_color_space) { + case JCS_GRAYSCALE: + if (cinfo->input_components != 1) + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + break; + + case JCS_RGB: +#if RGB_PIXELSIZE != 3 + if (cinfo->input_components != RGB_PIXELSIZE) + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + break; +#endif /* else share code with YCbCr */ + + case JCS_YCbCr: + if (cinfo->input_components != 3) + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + break; + + case JCS_CMYK: + case JCS_YCCK: + if (cinfo->input_components != 4) + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + break; + + default: /* JCS_UNKNOWN can be anything */ + if (cinfo->input_components < 1) + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + break; + } + + /* Check num_components, set conversion method based on requested space */ + switch (cinfo->jpeg_color_space) { + case JCS_GRAYSCALE: + if (cinfo->num_components != 1) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + if (cinfo->in_color_space == JCS_GRAYSCALE) + cconvert->pub.color_convert = grayscale_convert; + else if (cinfo->in_color_space == JCS_RGB) { + cconvert->pub.start_pass = rgb_ycc_start; + cconvert->pub.color_convert = rgb_gray_convert; + } else if (cinfo->in_color_space == JCS_YCbCr) + cconvert->pub.color_convert = grayscale_convert; + else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + case JCS_RGB: + if (cinfo->num_components != 3) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + if (cinfo->in_color_space == JCS_RGB && RGB_PIXELSIZE == 3) + cconvert->pub.color_convert = null_convert; + else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + case JCS_YCbCr: + if (cinfo->num_components != 3) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + if (cinfo->in_color_space == JCS_RGB) { + cconvert->pub.start_pass = rgb_ycc_start; + cconvert->pub.color_convert = rgb_ycc_convert; + } else if (cinfo->in_color_space == JCS_YCbCr) + cconvert->pub.color_convert = null_convert; + else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + case JCS_CMYK: + if (cinfo->num_components != 4) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + if (cinfo->in_color_space == JCS_CMYK) + cconvert->pub.color_convert = null_convert; + else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + case JCS_YCCK: + if (cinfo->num_components != 4) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + if (cinfo->in_color_space == JCS_CMYK) { + cconvert->pub.start_pass = rgb_ycc_start; + cconvert->pub.color_convert = cmyk_ycck_convert; + } else if (cinfo->in_color_space == JCS_YCCK) + cconvert->pub.color_convert = null_convert; + else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + default: /* allow null conversion of JCS_UNKNOWN */ + if (cinfo->jpeg_color_space != cinfo->in_color_space || + cinfo->num_components != cinfo->input_components) + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + cconvert->pub.color_convert = null_convert; + break; + } +} diff --git a/jpeg/JCHUFF.H b/jpeg/JCHUFF.H new file mode 100644 index 0000000..81c0555 --- /dev/null +++ b/jpeg/JCHUFF.H @@ -0,0 +1,47 @@ +/* + * jchuff.h + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains declarations for Huffman entropy encoding routines + * that are shared between the sequential encoder (jchuff.c) and the + * progressive encoder (jcphuff.c). No other modules need to see these. + */ + +/* The legal range of a DCT coefficient is + * -1024 .. +1023 for 8-bit data; + * -16384 .. +16383 for 12-bit data. + * Hence the magnitude should always fit in 10 or 14 bits respectively. + */ + +#if BITS_IN_JSAMPLE == 8 +#define MAX_COEF_BITS 10 +#else +#define MAX_COEF_BITS 14 +#endif + +/* Derived data constructed for each Huffman table */ + +typedef struct { + unsigned int ehufco[256]; /* code for each symbol */ + char ehufsi[256]; /* length of code for each symbol */ + /* If no code has been allocated for a symbol S, ehufsi[S] contains 0 */ +} c_derived_tbl; + +/* Short forms of external names for systems with brain-damaged linkers. */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jpeg_make_c_derived_tbl jMkCDerived +#define jpeg_gen_optimal_table jGenOptTbl +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + +/* Expand a Huffman table definition into the derived format */ +EXTERN(void) jpeg_make_c_derived_tbl + JPP((j_compress_ptr cinfo, boolean isDC, int tblno, + c_derived_tbl ** pdtbl)); + +/* Generate an optimal table definition given the specified counts */ +EXTERN(void) jpeg_gen_optimal_table + JPP((j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[])); diff --git a/jpeg/JCINIT.C b/jpeg/JCINIT.C new file mode 100644 index 0000000..dde9a7a --- /dev/null +++ b/jpeg/JCINIT.C @@ -0,0 +1,72 @@ +/* + * jcinit.c + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains initialization logic for the JPEG compressor. + * This routine is in charge of selecting the modules to be executed and + * making an initialization call to each one. + * + * Logically, this code belongs in jcmaster.c. It's split out because + * linking this routine implies linking the entire compression library. + * For a transcoding-only application, we want to be able to use jcmaster.c + * without linking in the whole library. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* + * Master selection of compression modules. + * This is done once at the start of processing an image. We determine + * which modules will be used and give them appropriate initialization calls. + */ + +GLOBAL(void) +jinit_compress_master (j_compress_ptr cinfo) +{ + /* Initialize master control (includes parameter checking/processing) */ + jinit_c_master_control(cinfo, FALSE /* full compression */); + + /* Preprocessing */ + if (! cinfo->raw_data_in) { + jinit_color_converter(cinfo); + jinit_downsampler(cinfo); + jinit_c_prep_controller(cinfo, FALSE /* never need full buffer here */); + } + /* Forward DCT */ + jinit_forward_dct(cinfo); + /* Entropy encoding: either Huffman or arithmetic coding. */ + if (cinfo->arith_code) { + ERREXIT(cinfo, JERR_ARITH_NOTIMPL); + } else { + if (cinfo->progressive_mode) { +#ifdef C_PROGRESSIVE_SUPPORTED + jinit_phuff_encoder(cinfo); +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else + jinit_huff_encoder(cinfo); + } + + /* Need a full-image coefficient buffer in any multi-pass mode. */ + jinit_c_coef_controller(cinfo, + (boolean) (cinfo->num_scans > 1 || cinfo->optimize_coding)); + jinit_c_main_controller(cinfo, FALSE /* never need full buffer here */); + + jinit_marker_writer(cinfo); + + /* We can now tell the memory manager to allocate virtual arrays. */ + (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); + + /* Write the datastream header (SOI) immediately. + * Frame and scan headers are postponed till later. + * This lets application insert special markers after the SOI. + */ + (*cinfo->marker->write_file_header) (cinfo); +} diff --git a/jpeg/JCMAINCT.C b/jpeg/JCMAINCT.C new file mode 100644 index 0000000..dd38689 --- /dev/null +++ b/jpeg/JCMAINCT.C @@ -0,0 +1,293 @@ +/* + * jcmainct.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the main buffer controller for compression. + * The main buffer lies between the pre-processor and the JPEG + * compressor proper; it holds downsampled data in the JPEG colorspace. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Note: currently, there is no operating mode in which a full-image buffer + * is needed at this step. If there were, that mode could not be used with + * "raw data" input, since this module is bypassed in that case. However, + * we've left the code here for possible use in special applications. + */ +#undef FULL_MAIN_BUFFER_SUPPORTED + + +/* Private buffer controller object */ + +typedef struct { + struct jpeg_c_main_controller pub; /* public fields */ + + JDIMENSION cur_iMCU_row; /* number of current iMCU row */ + JDIMENSION rowgroup_ctr; /* counts row groups received in iMCU row */ + boolean suspended; /* remember if we suspended output */ + J_BUF_MODE pass_mode; /* current operating mode */ + + /* If using just a strip buffer, this points to the entire set of buffers + * (we allocate one for each component). In the full-image case, this + * points to the currently accessible strips of the virtual arrays. + */ + JSAMPARRAY buffer[MAX_COMPONENTS]; + +#ifdef FULL_MAIN_BUFFER_SUPPORTED + /* If using full-image storage, this array holds pointers to virtual-array + * control blocks for each component. Unused if not full-image storage. + */ + jvirt_sarray_ptr whole_image[MAX_COMPONENTS]; +#endif +} my_main_controller; + +typedef my_main_controller * my_main_ptr; + + +/* Forward declarations */ +METHODDEF(void) process_data_simple_main + JPP((j_compress_ptr cinfo, JSAMPARRAY input_buf, + JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail)); +#ifdef FULL_MAIN_BUFFER_SUPPORTED +METHODDEF(void) process_data_buffer_main + JPP((j_compress_ptr cinfo, JSAMPARRAY input_buf, + JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail)); +#endif + + +/* + * Initialize for a processing pass. + */ + +METHODDEF(void) +start_pass_main (j_compress_ptr cinfo, J_BUF_MODE pass_mode) +{ + my_main_ptr main = (my_main_ptr) cinfo->main; + + /* Do nothing in raw-data mode. */ + if (cinfo->raw_data_in) + return; + + main->cur_iMCU_row = 0; /* initialize counters */ + main->rowgroup_ctr = 0; + main->suspended = FALSE; + main->pass_mode = pass_mode; /* save mode for use by process_data */ + + switch (pass_mode) { + case JBUF_PASS_THRU: +#ifdef FULL_MAIN_BUFFER_SUPPORTED + if (main->whole_image[0] != NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); +#endif + main->pub.process_data = process_data_simple_main; + break; +#ifdef FULL_MAIN_BUFFER_SUPPORTED + case JBUF_SAVE_SOURCE: + case JBUF_CRANK_DEST: + case JBUF_SAVE_AND_PASS: + if (main->whole_image[0] == NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + main->pub.process_data = process_data_buffer_main; + break; +#endif + default: + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + break; + } +} + + +/* + * Process some data. + * This routine handles the simple pass-through mode, + * where we have only a strip buffer. + */ + +METHODDEF(void) +process_data_simple_main (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail) +{ + my_main_ptr main = (my_main_ptr) cinfo->main; + + while (main->cur_iMCU_row < cinfo->total_iMCU_rows) { + /* Read input data if we haven't filled the main buffer yet */ + if (main->rowgroup_ctr < DCTSIZE) + (*cinfo->prep->pre_process_data) (cinfo, + input_buf, in_row_ctr, in_rows_avail, + main->buffer, &main->rowgroup_ctr, + (JDIMENSION) DCTSIZE); + + /* If we don't have a full iMCU row buffered, return to application for + * more data. Note that preprocessor will always pad to fill the iMCU row + * at the bottom of the image. + */ + if (main->rowgroup_ctr != DCTSIZE) + return; + + /* Send the completed row to the compressor */ + if (! (*cinfo->coef->compress_data) (cinfo, main->buffer)) { + /* If compressor did not consume the whole row, then we must need to + * suspend processing and return to the application. In this situation + * we pretend we didn't yet consume the last input row; otherwise, if + * it happened to be the last row of the image, the application would + * think we were done. + */ + if (! main->suspended) { + (*in_row_ctr)--; + main->suspended = TRUE; + } + return; + } + /* We did finish the row. Undo our little suspension hack if a previous + * call suspended; then mark the main buffer empty. + */ + if (main->suspended) { + (*in_row_ctr)++; + main->suspended = FALSE; + } + main->rowgroup_ctr = 0; + main->cur_iMCU_row++; + } +} + + +#ifdef FULL_MAIN_BUFFER_SUPPORTED + +/* + * Process some data. + * This routine handles all of the modes that use a full-size buffer. + */ + +METHODDEF(void) +process_data_buffer_main (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail) +{ + my_main_ptr main = (my_main_ptr) cinfo->main; + int ci; + jpeg_component_info *compptr; + boolean writing = (main->pass_mode != JBUF_CRANK_DEST); + + while (main->cur_iMCU_row < cinfo->total_iMCU_rows) { + /* Realign the virtual buffers if at the start of an iMCU row. */ + if (main->rowgroup_ctr == 0) { + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + main->buffer[ci] = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, main->whole_image[ci], + main->cur_iMCU_row * (compptr->v_samp_factor * DCTSIZE), + (JDIMENSION) (compptr->v_samp_factor * DCTSIZE), writing); + } + /* In a read pass, pretend we just read some source data. */ + if (! writing) { + *in_row_ctr += cinfo->max_v_samp_factor * DCTSIZE; + main->rowgroup_ctr = DCTSIZE; + } + } + + /* If a write pass, read input data until the current iMCU row is full. */ + /* Note: preprocessor will pad if necessary to fill the last iMCU row. */ + if (writing) { + (*cinfo->prep->pre_process_data) (cinfo, + input_buf, in_row_ctr, in_rows_avail, + main->buffer, &main->rowgroup_ctr, + (JDIMENSION) DCTSIZE); + /* Return to application if we need more data to fill the iMCU row. */ + if (main->rowgroup_ctr < DCTSIZE) + return; + } + + /* Emit data, unless this is a sink-only pass. */ + if (main->pass_mode != JBUF_SAVE_SOURCE) { + if (! (*cinfo->coef->compress_data) (cinfo, main->buffer)) { + /* If compressor did not consume the whole row, then we must need to + * suspend processing and return to the application. In this situation + * we pretend we didn't yet consume the last input row; otherwise, if + * it happened to be the last row of the image, the application would + * think we were done. + */ + if (! main->suspended) { + (*in_row_ctr)--; + main->suspended = TRUE; + } + return; + } + /* We did finish the row. Undo our little suspension hack if a previous + * call suspended; then mark the main buffer empty. + */ + if (main->suspended) { + (*in_row_ctr)++; + main->suspended = FALSE; + } + } + + /* If get here, we are done with this iMCU row. Mark buffer empty. */ + main->rowgroup_ctr = 0; + main->cur_iMCU_row++; + } +} + +#endif /* FULL_MAIN_BUFFER_SUPPORTED */ + + +/* + * Initialize main buffer controller. + */ + +GLOBAL(void) +jinit_c_main_controller (j_compress_ptr cinfo, boolean need_full_buffer) +{ + my_main_ptr main; + int ci; + jpeg_component_info *compptr; + + main = (my_main_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_main_controller)); + cinfo->main = (struct jpeg_c_main_controller *) main; + main->pub.start_pass = start_pass_main; + + /* We don't need to create a buffer in raw-data mode. */ + if (cinfo->raw_data_in) + return; + + /* Create the buffer. It holds downsampled data, so each component + * may be of a different size. + */ + if (need_full_buffer) { +#ifdef FULL_MAIN_BUFFER_SUPPORTED + /* Allocate a full-image virtual array for each component */ + /* Note we pad the bottom to a multiple of the iMCU height */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + main->whole_image[ci] = (*cinfo->mem->request_virt_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, + compptr->width_in_blocks * DCTSIZE, + (JDIMENSION) jround_up((long) compptr->height_in_blocks, + (long) compptr->v_samp_factor) * DCTSIZE, + (JDIMENSION) (compptr->v_samp_factor * DCTSIZE)); + } +#else + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); +#endif + } else { +#ifdef FULL_MAIN_BUFFER_SUPPORTED + main->whole_image[0] = NULL; /* flag for no virtual arrays */ +#endif + /* Allocate a strip buffer for each component */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + main->buffer[ci] = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + compptr->width_in_blocks * DCTSIZE, + (JDIMENSION) (compptr->v_samp_factor * DCTSIZE)); + } + } +} diff --git a/jpeg/JCMARKER.C b/jpeg/JCMARKER.C new file mode 100644 index 0000000..5171eb0 --- /dev/null +++ b/jpeg/JCMARKER.C @@ -0,0 +1,664 @@ +/* + * jcmarker.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains routines to write JPEG datastream markers. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +typedef enum { /* JPEG marker codes */ + M_SOF0 = 0xc0, + M_SOF1 = 0xc1, + M_SOF2 = 0xc2, + M_SOF3 = 0xc3, + + M_SOF5 = 0xc5, + M_SOF6 = 0xc6, + M_SOF7 = 0xc7, + + M_JPG = 0xc8, + M_SOF9 = 0xc9, + M_SOF10 = 0xca, + M_SOF11 = 0xcb, + + M_SOF13 = 0xcd, + M_SOF14 = 0xce, + M_SOF15 = 0xcf, + + M_DHT = 0xc4, + + M_DAC = 0xcc, + + M_RST0 = 0xd0, + M_RST1 = 0xd1, + M_RST2 = 0xd2, + M_RST3 = 0xd3, + M_RST4 = 0xd4, + M_RST5 = 0xd5, + M_RST6 = 0xd6, + M_RST7 = 0xd7, + + M_SOI = 0xd8, + M_EOI = 0xd9, + M_SOS = 0xda, + M_DQT = 0xdb, + M_DNL = 0xdc, + M_DRI = 0xdd, + M_DHP = 0xde, + M_EXP = 0xdf, + + M_APP0 = 0xe0, + M_APP1 = 0xe1, + M_APP2 = 0xe2, + M_APP3 = 0xe3, + M_APP4 = 0xe4, + M_APP5 = 0xe5, + M_APP6 = 0xe6, + M_APP7 = 0xe7, + M_APP8 = 0xe8, + M_APP9 = 0xe9, + M_APP10 = 0xea, + M_APP11 = 0xeb, + M_APP12 = 0xec, + M_APP13 = 0xed, + M_APP14 = 0xee, + M_APP15 = 0xef, + + M_JPG0 = 0xf0, + M_JPG13 = 0xfd, + M_COM = 0xfe, + + M_TEM = 0x01, + + M_ERROR = 0x100 +} JPEG_MARKER; + + +/* Private state */ + +typedef struct { + struct jpeg_marker_writer pub; /* public fields */ + + unsigned int last_restart_interval; /* last DRI value emitted; 0 after SOI */ +} my_marker_writer; + +typedef my_marker_writer * my_marker_ptr; + + +/* + * Basic output routines. + * + * Note that we do not support suspension while writing a marker. + * Therefore, an application using suspension must ensure that there is + * enough buffer space for the initial markers (typ. 600-700 bytes) before + * calling jpeg_start_compress, and enough space to write the trailing EOI + * (a few bytes) before calling jpeg_finish_compress. Multipass compression + * modes are not supported at all with suspension, so those two are the only + * points where markers will be written. + */ + +LOCAL(void) +emit_byte (j_compress_ptr cinfo, int val) +/* Emit a byte */ +{ + struct jpeg_destination_mgr * dest = cinfo->dest; + + *(dest->next_output_byte)++ = (JOCTET) val; + if (--dest->free_in_buffer == 0) { + if (! (*dest->empty_output_buffer) (cinfo)) + ERREXIT(cinfo, JERR_CANT_SUSPEND); + } +} + + +LOCAL(void) +emit_marker (j_compress_ptr cinfo, JPEG_MARKER mark) +/* Emit a marker code */ +{ + emit_byte(cinfo, 0xFF); + emit_byte(cinfo, (int) mark); +} + + +LOCAL(void) +emit_2bytes (j_compress_ptr cinfo, int value) +/* Emit a 2-byte integer; these are always MSB first in JPEG files */ +{ + emit_byte(cinfo, (value >> 8) & 0xFF); + emit_byte(cinfo, value & 0xFF); +} + + +/* + * Routines to write specific marker types. + */ + +LOCAL(int) +emit_dqt (j_compress_ptr cinfo, int index) +/* Emit a DQT marker */ +/* Returns the precision used (0 = 8bits, 1 = 16bits) for baseline checking */ +{ + JQUANT_TBL * qtbl = cinfo->quant_tbl_ptrs[index]; + int prec; + int i; + + if (qtbl == NULL) + ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, index); + + prec = 0; + for (i = 0; i < DCTSIZE2; i++) { + if (qtbl->quantval[i] > 255) + prec = 1; + } + + if (! qtbl->sent_table) { + emit_marker(cinfo, M_DQT); + + emit_2bytes(cinfo, prec ? DCTSIZE2*2 + 1 + 2 : DCTSIZE2 + 1 + 2); + + emit_byte(cinfo, index + (prec<<4)); + + for (i = 0; i < DCTSIZE2; i++) { + /* The table entries must be emitted in zigzag order. */ + unsigned int qval = qtbl->quantval[jpeg_natural_order[i]]; + if (prec) + emit_byte(cinfo, (int) (qval >> 8)); + emit_byte(cinfo, (int) (qval & 0xFF)); + } + + qtbl->sent_table = TRUE; + } + + return prec; +} + + +LOCAL(void) +emit_dht (j_compress_ptr cinfo, int index, boolean is_ac) +/* Emit a DHT marker */ +{ + JHUFF_TBL * htbl; + int length, i; + + if (is_ac) { + htbl = cinfo->ac_huff_tbl_ptrs[index]; + index += 0x10; /* output index has AC bit set */ + } else { + htbl = cinfo->dc_huff_tbl_ptrs[index]; + } + + if (htbl == NULL) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, index); + + if (! htbl->sent_table) { + emit_marker(cinfo, M_DHT); + + length = 0; + for (i = 1; i <= 16; i++) + length += htbl->bits[i]; + + emit_2bytes(cinfo, length + 2 + 1 + 16); + emit_byte(cinfo, index); + + for (i = 1; i <= 16; i++) + emit_byte(cinfo, htbl->bits[i]); + + for (i = 0; i < length; i++) + emit_byte(cinfo, htbl->huffval[i]); + + htbl->sent_table = TRUE; + } +} + + +LOCAL(void) +emit_dac (j_compress_ptr cinfo) +/* Emit a DAC marker */ +/* Since the useful info is so small, we want to emit all the tables in */ +/* one DAC marker. Therefore this routine does its own scan of the table. */ +{ +#ifdef C_ARITH_CODING_SUPPORTED + char dc_in_use[NUM_ARITH_TBLS]; + char ac_in_use[NUM_ARITH_TBLS]; + int length, i; + jpeg_component_info *compptr; + + for (i = 0; i < NUM_ARITH_TBLS; i++) + dc_in_use[i] = ac_in_use[i] = 0; + + for (i = 0; i < cinfo->comps_in_scan; i++) { + compptr = cinfo->cur_comp_info[i]; + dc_in_use[compptr->dc_tbl_no] = 1; + ac_in_use[compptr->ac_tbl_no] = 1; + } + + length = 0; + for (i = 0; i < NUM_ARITH_TBLS; i++) + length += dc_in_use[i] + ac_in_use[i]; + + emit_marker(cinfo, M_DAC); + + emit_2bytes(cinfo, length*2 + 2); + + for (i = 0; i < NUM_ARITH_TBLS; i++) { + if (dc_in_use[i]) { + emit_byte(cinfo, i); + emit_byte(cinfo, cinfo->arith_dc_L[i] + (cinfo->arith_dc_U[i]<<4)); + } + if (ac_in_use[i]) { + emit_byte(cinfo, i + 0x10); + emit_byte(cinfo, cinfo->arith_ac_K[i]); + } + } +#endif /* C_ARITH_CODING_SUPPORTED */ +} + + +LOCAL(void) +emit_dri (j_compress_ptr cinfo) +/* Emit a DRI marker */ +{ + emit_marker(cinfo, M_DRI); + + emit_2bytes(cinfo, 4); /* fixed length */ + + emit_2bytes(cinfo, (int) cinfo->restart_interval); +} + + +LOCAL(void) +emit_sof (j_compress_ptr cinfo, JPEG_MARKER code) +/* Emit a SOF marker */ +{ + int ci; + jpeg_component_info *compptr; + + emit_marker(cinfo, code); + + emit_2bytes(cinfo, 3 * cinfo->num_components + 2 + 5 + 1); /* length */ + + /* Make sure image isn't bigger than SOF field can handle */ + if ((long) cinfo->image_height > 65535L || + (long) cinfo->image_width > 65535L) + ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) 65535); + + emit_byte(cinfo, cinfo->data_precision); + emit_2bytes(cinfo, (int) cinfo->image_height); + emit_2bytes(cinfo, (int) cinfo->image_width); + + emit_byte(cinfo, cinfo->num_components); + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + emit_byte(cinfo, compptr->component_id); + emit_byte(cinfo, (compptr->h_samp_factor << 4) + compptr->v_samp_factor); + emit_byte(cinfo, compptr->quant_tbl_no); + } +} + + +LOCAL(void) +emit_sos (j_compress_ptr cinfo) +/* Emit a SOS marker */ +{ + int i, td, ta; + jpeg_component_info *compptr; + + emit_marker(cinfo, M_SOS); + + emit_2bytes(cinfo, 2 * cinfo->comps_in_scan + 2 + 1 + 3); /* length */ + + emit_byte(cinfo, cinfo->comps_in_scan); + + for (i = 0; i < cinfo->comps_in_scan; i++) { + compptr = cinfo->cur_comp_info[i]; + emit_byte(cinfo, compptr->component_id); + td = compptr->dc_tbl_no; + ta = compptr->ac_tbl_no; + if (cinfo->progressive_mode) { + /* Progressive mode: only DC or only AC tables are used in one scan; + * furthermore, Huffman coding of DC refinement uses no table at all. + * We emit 0 for unused field(s); this is recommended by the P&M text + * but does not seem to be specified in the standard. + */ + if (cinfo->Ss == 0) { + ta = 0; /* DC scan */ + if (cinfo->Ah != 0 && !cinfo->arith_code) + td = 0; /* no DC table either */ + } else { + td = 0; /* AC scan */ + } + } + emit_byte(cinfo, (td << 4) + ta); + } + + emit_byte(cinfo, cinfo->Ss); + emit_byte(cinfo, cinfo->Se); + emit_byte(cinfo, (cinfo->Ah << 4) + cinfo->Al); +} + + +LOCAL(void) +emit_jfif_app0 (j_compress_ptr cinfo) +/* Emit a JFIF-compliant APP0 marker */ +{ + /* + * Length of APP0 block (2 bytes) + * Block ID (4 bytes - ASCII "JFIF") + * Zero byte (1 byte to terminate the ID string) + * Version Major, Minor (2 bytes - major first) + * Units (1 byte - 0x00 = none, 0x01 = inch, 0x02 = cm) + * Xdpu (2 bytes - dots per unit horizontal) + * Ydpu (2 bytes - dots per unit vertical) + * Thumbnail X size (1 byte) + * Thumbnail Y size (1 byte) + */ + + emit_marker(cinfo, M_APP0); + + emit_2bytes(cinfo, 2 + 4 + 1 + 2 + 1 + 2 + 2 + 1 + 1); /* length */ + + emit_byte(cinfo, 0x4A); /* Identifier: ASCII "JFIF" */ + emit_byte(cinfo, 0x46); + emit_byte(cinfo, 0x49); + emit_byte(cinfo, 0x46); + emit_byte(cinfo, 0); + emit_byte(cinfo, cinfo->JFIF_major_version); /* Version fields */ + emit_byte(cinfo, cinfo->JFIF_minor_version); + emit_byte(cinfo, cinfo->density_unit); /* Pixel size information */ + emit_2bytes(cinfo, (int) cinfo->X_density); + emit_2bytes(cinfo, (int) cinfo->Y_density); + emit_byte(cinfo, 0); /* No thumbnail image */ + emit_byte(cinfo, 0); +} + + +LOCAL(void) +emit_adobe_app14 (j_compress_ptr cinfo) +/* Emit an Adobe APP14 marker */ +{ + /* + * Length of APP14 block (2 bytes) + * Block ID (5 bytes - ASCII "Adobe") + * Version Number (2 bytes - currently 100) + * Flags0 (2 bytes - currently 0) + * Flags1 (2 bytes - currently 0) + * Color transform (1 byte) + * + * Although Adobe TN 5116 mentions Version = 101, all the Adobe files + * now in circulation seem to use Version = 100, so that's what we write. + * + * We write the color transform byte as 1 if the JPEG color space is + * YCbCr, 2 if it's YCCK, 0 otherwise. Adobe's definition has to do with + * whether the encoder performed a transformation, which is pretty useless. + */ + + emit_marker(cinfo, M_APP14); + + emit_2bytes(cinfo, 2 + 5 + 2 + 2 + 2 + 1); /* length */ + + emit_byte(cinfo, 0x41); /* Identifier: ASCII "Adobe" */ + emit_byte(cinfo, 0x64); + emit_byte(cinfo, 0x6F); + emit_byte(cinfo, 0x62); + emit_byte(cinfo, 0x65); + emit_2bytes(cinfo, 100); /* Version */ + emit_2bytes(cinfo, 0); /* Flags0 */ + emit_2bytes(cinfo, 0); /* Flags1 */ + switch (cinfo->jpeg_color_space) { + case JCS_YCbCr: + emit_byte(cinfo, 1); /* Color transform = 1 */ + break; + case JCS_YCCK: + emit_byte(cinfo, 2); /* Color transform = 2 */ + break; + default: + emit_byte(cinfo, 0); /* Color transform = 0 */ + break; + } +} + + +/* + * These routines allow writing an arbitrary marker with parameters. + * The only intended use is to emit COM or APPn markers after calling + * write_file_header and before calling write_frame_header. + * Other uses are not guaranteed to produce desirable results. + * Counting the parameter bytes properly is the caller's responsibility. + */ + +METHODDEF(void) +write_marker_header (j_compress_ptr cinfo, int marker, unsigned int datalen) +/* Emit an arbitrary marker header */ +{ + if (datalen > (unsigned int) 65533) /* safety check */ + ERREXIT(cinfo, JERR_BAD_LENGTH); + + emit_marker(cinfo, (JPEG_MARKER) marker); + + emit_2bytes(cinfo, (int) (datalen + 2)); /* total length */ +} + +METHODDEF(void) +write_marker_byte (j_compress_ptr cinfo, int val) +/* Emit one byte of marker parameters following write_marker_header */ +{ + emit_byte(cinfo, val); +} + + +/* + * Write datastream header. + * This consists of an SOI and optional APPn markers. + * We recommend use of the JFIF marker, but not the Adobe marker, + * when using YCbCr or grayscale data. The JFIF marker should NOT + * be used for any other JPEG colorspace. The Adobe marker is helpful + * to distinguish RGB, CMYK, and YCCK colorspaces. + * Note that an application can write additional header markers after + * jpeg_start_compress returns. + */ + +METHODDEF(void) +write_file_header (j_compress_ptr cinfo) +{ + my_marker_ptr marker = (my_marker_ptr) cinfo->marker; + + emit_marker(cinfo, M_SOI); /* first the SOI */ + + /* SOI is defined to reset restart interval to 0 */ + marker->last_restart_interval = 0; + + if (cinfo->write_JFIF_header) /* next an optional JFIF APP0 */ + emit_jfif_app0(cinfo); + if (cinfo->write_Adobe_marker) /* next an optional Adobe APP14 */ + emit_adobe_app14(cinfo); +} + + +/* + * Write frame header. + * This consists of DQT and SOFn markers. + * Note that we do not emit the SOF until we have emitted the DQT(s). + * This avoids compatibility problems with incorrect implementations that + * try to error-check the quant table numbers as soon as they see the SOF. + */ + +METHODDEF(void) +write_frame_header (j_compress_ptr cinfo) +{ + int ci, prec; + boolean is_baseline; + jpeg_component_info *compptr; + + /* Emit DQT for each quantization table. + * Note that emit_dqt() suppresses any duplicate tables. + */ + prec = 0; + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + prec += emit_dqt(cinfo, compptr->quant_tbl_no); + } + /* now prec is nonzero iff there are any 16-bit quant tables. */ + + /* Check for a non-baseline specification. + * Note we assume that Huffman table numbers won't be changed later. + */ + if (cinfo->arith_code || cinfo->progressive_mode || + cinfo->data_precision != 8) { + is_baseline = FALSE; + } else { + is_baseline = TRUE; + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + if (compptr->dc_tbl_no > 1 || compptr->ac_tbl_no > 1) + is_baseline = FALSE; + } + if (prec && is_baseline) { + is_baseline = FALSE; + /* If it's baseline except for quantizer size, warn the user */ + TRACEMS(cinfo, 0, JTRC_16BIT_TABLES); + } + } + + /* Emit the proper SOF marker */ + if (cinfo->arith_code) { + emit_sof(cinfo, M_SOF9); /* SOF code for arithmetic coding */ + } else { + if (cinfo->progressive_mode) + emit_sof(cinfo, M_SOF2); /* SOF code for progressive Huffman */ + else if (is_baseline) + emit_sof(cinfo, M_SOF0); /* SOF code for baseline implementation */ + else + emit_sof(cinfo, M_SOF1); /* SOF code for non-baseline Huffman file */ + } +} + + +/* + * Write scan header. + * This consists of DHT or DAC markers, optional DRI, and SOS. + * Compressed data will be written following the SOS. + */ + +METHODDEF(void) +write_scan_header (j_compress_ptr cinfo) +{ + my_marker_ptr marker = (my_marker_ptr) cinfo->marker; + int i; + jpeg_component_info *compptr; + + if (cinfo->arith_code) { + /* Emit arith conditioning info. We may have some duplication + * if the file has multiple scans, but it's so small it's hardly + * worth worrying about. + */ + emit_dac(cinfo); + } else { + /* Emit Huffman tables. + * Note that emit_dht() suppresses any duplicate tables. + */ + for (i = 0; i < cinfo->comps_in_scan; i++) { + compptr = cinfo->cur_comp_info[i]; + if (cinfo->progressive_mode) { + /* Progressive mode: only DC or only AC tables are used in one scan */ + if (cinfo->Ss == 0) { + if (cinfo->Ah == 0) /* DC needs no table for refinement scan */ + emit_dht(cinfo, compptr->dc_tbl_no, FALSE); + } else { + emit_dht(cinfo, compptr->ac_tbl_no, TRUE); + } + } else { + /* Sequential mode: need both DC and AC tables */ + emit_dht(cinfo, compptr->dc_tbl_no, FALSE); + emit_dht(cinfo, compptr->ac_tbl_no, TRUE); + } + } + } + + /* Emit DRI if required --- note that DRI value could change for each scan. + * We avoid wasting space with unnecessary DRIs, however. + */ + if (cinfo->restart_interval != marker->last_restart_interval) { + emit_dri(cinfo); + marker->last_restart_interval = cinfo->restart_interval; + } + + emit_sos(cinfo); +} + + +/* + * Write datastream trailer. + */ + +METHODDEF(void) +write_file_trailer (j_compress_ptr cinfo) +{ + emit_marker(cinfo, M_EOI); +} + + +/* + * Write an abbreviated table-specification datastream. + * This consists of SOI, DQT and DHT tables, and EOI. + * Any table that is defined and not marked sent_table = TRUE will be + * emitted. Note that all tables will be marked sent_table = TRUE at exit. + */ + +METHODDEF(void) +write_tables_only (j_compress_ptr cinfo) +{ + int i; + + emit_marker(cinfo, M_SOI); + + for (i = 0; i < NUM_QUANT_TBLS; i++) { + if (cinfo->quant_tbl_ptrs[i] != NULL) + (void) emit_dqt(cinfo, i); + } + + if (! cinfo->arith_code) { + for (i = 0; i < NUM_HUFF_TBLS; i++) { + if (cinfo->dc_huff_tbl_ptrs[i] != NULL) + emit_dht(cinfo, i, FALSE); + if (cinfo->ac_huff_tbl_ptrs[i] != NULL) + emit_dht(cinfo, i, TRUE); + } + } + + emit_marker(cinfo, M_EOI); +} + + +/* + * Initialize the marker writer module. + */ + +GLOBAL(void) +jinit_marker_writer (j_compress_ptr cinfo) +{ + my_marker_ptr marker; + + /* Create the subobject */ + marker = (my_marker_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_marker_writer)); + cinfo->marker = (struct jpeg_marker_writer *) marker; + /* Initialize method pointers */ + marker->pub.write_file_header = write_file_header; + marker->pub.write_frame_header = write_frame_header; + marker->pub.write_scan_header = write_scan_header; + marker->pub.write_file_trailer = write_file_trailer; + marker->pub.write_tables_only = write_tables_only; + marker->pub.write_marker_header = write_marker_header; + marker->pub.write_marker_byte = write_marker_byte; + /* Initialize private state */ + marker->last_restart_interval = 0; +} diff --git a/jpeg/JCMASTER.C b/jpeg/JCMASTER.C new file mode 100644 index 0000000..10b3652 --- /dev/null +++ b/jpeg/JCMASTER.C @@ -0,0 +1,590 @@ +/* + * jcmaster.c + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains master control logic for the JPEG compressor. + * These routines are concerned with parameter validation, initial setup, + * and inter-pass control (determining the number of passes and the work + * to be done in each pass). + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Private state */ + +typedef enum { + main_pass, /* input data, also do first output step */ + huff_opt_pass, /* Huffman code optimization pass */ + output_pass /* data output pass */ +} c_pass_type; + +typedef struct { + struct jpeg_comp_master pub; /* public fields */ + + c_pass_type pass_type; /* the type of the current pass */ + + int pass_number; /* # of passes completed */ + int total_passes; /* total # of passes needed */ + + int scan_number; /* current index in scan_info[] */ +} my_comp_master; + +typedef my_comp_master * my_master_ptr; + + +/* + * Support routines that do various essential calculations. + */ + +LOCAL(void) +initial_setup (j_compress_ptr cinfo) +/* Do computations that are needed before master selection phase */ +{ + int ci; + jpeg_component_info *compptr; + long samplesperrow; + JDIMENSION jd_samplesperrow; + + /* Sanity check on image dimensions */ + if (cinfo->image_height <= 0 || cinfo->image_width <= 0 + || cinfo->num_components <= 0 || cinfo->input_components <= 0) + ERREXIT(cinfo, JERR_EMPTY_IMAGE); + + /* Make sure image isn't bigger than I can handle */ + if ((long) cinfo->image_height > (long) JPEG_MAX_DIMENSION || + (long) cinfo->image_width > (long) JPEG_MAX_DIMENSION) + ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION); + + /* Width of an input scanline must be representable as JDIMENSION. */ + samplesperrow = (long) cinfo->image_width * (long) cinfo->input_components; + jd_samplesperrow = (JDIMENSION) samplesperrow; + if ((long) jd_samplesperrow != samplesperrow) + ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); + + /* For now, precision must match compiled-in value... */ + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + + /* Check that number of components won't exceed internal array sizes */ + if (cinfo->num_components > MAX_COMPONENTS) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, + MAX_COMPONENTS); + + /* Compute maximum sampling factors; check factor validity */ + cinfo->max_h_samp_factor = 1; + cinfo->max_v_samp_factor = 1; + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR || + compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR) + ERREXIT(cinfo, JERR_BAD_SAMPLING); + cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor, + compptr->h_samp_factor); + cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor, + compptr->v_samp_factor); + } + + /* Compute dimensions of components */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Fill in the correct component_index value; don't rely on application */ + compptr->component_index = ci; + /* For compression, we never do DCT scaling. */ + compptr->DCT_scaled_size = DCTSIZE; + /* Size in DCT blocks */ + compptr->width_in_blocks = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, + (long) (cinfo->max_h_samp_factor * DCTSIZE)); + compptr->height_in_blocks = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, + (long) (cinfo->max_v_samp_factor * DCTSIZE)); + /* Size in samples */ + compptr->downsampled_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, + (long) cinfo->max_h_samp_factor); + compptr->downsampled_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, + (long) cinfo->max_v_samp_factor); + /* Mark component needed (this flag isn't actually used for compression) */ + compptr->component_needed = TRUE; + } + + /* Compute number of fully interleaved MCU rows (number of times that + * main controller will call coefficient controller). + */ + cinfo->total_iMCU_rows = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, + (long) (cinfo->max_v_samp_factor*DCTSIZE)); +} + + +#ifdef C_MULTISCAN_FILES_SUPPORTED + +LOCAL(void) +validate_script (j_compress_ptr cinfo) +/* Verify that the scan script in cinfo->scan_info[] is valid; also + * determine whether it uses progressive JPEG, and set cinfo->progressive_mode. + */ +{ + const jpeg_scan_info * scanptr; + int scanno, ncomps, ci, coefi, thisi; + int Ss, Se, Ah, Al; + boolean component_sent[MAX_COMPONENTS]; +#ifdef C_PROGRESSIVE_SUPPORTED + int * last_bitpos_ptr; + int last_bitpos[MAX_COMPONENTS][DCTSIZE2]; + /* -1 until that coefficient has been seen; then last Al for it */ +#endif + + if (cinfo->num_scans <= 0) + ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, 0); + + /* For sequential JPEG, all scans must have Ss=0, Se=DCTSIZE2-1; + * for progressive JPEG, no scan can have this. + */ + scanptr = cinfo->scan_info; + if (scanptr->Ss != 0 || scanptr->Se != DCTSIZE2-1) { +#ifdef C_PROGRESSIVE_SUPPORTED + cinfo->progressive_mode = TRUE; + last_bitpos_ptr = & last_bitpos[0][0]; + for (ci = 0; ci < cinfo->num_components; ci++) + for (coefi = 0; coefi < DCTSIZE2; coefi++) + *last_bitpos_ptr++ = -1; +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else { + cinfo->progressive_mode = FALSE; + for (ci = 0; ci < cinfo->num_components; ci++) + component_sent[ci] = FALSE; + } + + for (scanno = 1; scanno <= cinfo->num_scans; scanptr++, scanno++) { + /* Validate component indexes */ + ncomps = scanptr->comps_in_scan; + if (ncomps <= 0 || ncomps > MAX_COMPS_IN_SCAN) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, ncomps, MAX_COMPS_IN_SCAN); + for (ci = 0; ci < ncomps; ci++) { + thisi = scanptr->component_index[ci]; + if (thisi < 0 || thisi >= cinfo->num_components) + ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno); + /* Components must appear in SOF order within each scan */ + if (ci > 0 && thisi <= scanptr->component_index[ci-1]) + ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno); + } + /* Validate progression parameters */ + Ss = scanptr->Ss; + Se = scanptr->Se; + Ah = scanptr->Ah; + Al = scanptr->Al; + if (cinfo->progressive_mode) { +#ifdef C_PROGRESSIVE_SUPPORTED + /* The JPEG spec simply gives the ranges 0..13 for Ah and Al, but that + * seems wrong: the upper bound ought to depend on data precision. + * Perhaps they really meant 0..N+1 for N-bit precision. + * Here we allow 0..10 for 8-bit data; Al larger than 10 results in + * out-of-range reconstructed DC values during the first DC scan, + * which might cause problems for some decoders. + */ +#if BITS_IN_JSAMPLE == 8 +#define MAX_AH_AL 10 +#else +#define MAX_AH_AL 13 +#endif + if (Ss < 0 || Ss >= DCTSIZE2 || Se < Ss || Se >= DCTSIZE2 || + Ah < 0 || Ah > MAX_AH_AL || Al < 0 || Al > MAX_AH_AL) + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + if (Ss == 0) { + if (Se != 0) /* DC and AC together not OK */ + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + } else { + if (ncomps != 1) /* AC scans must be for only one component */ + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + } + for (ci = 0; ci < ncomps; ci++) { + last_bitpos_ptr = & last_bitpos[scanptr->component_index[ci]][0]; + if (Ss != 0 && last_bitpos_ptr[0] < 0) /* AC without prior DC scan */ + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + for (coefi = Ss; coefi <= Se; coefi++) { + if (last_bitpos_ptr[coefi] < 0) { + /* first scan of this coefficient */ + if (Ah != 0) + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + } else { + /* not first scan */ + if (Ah != last_bitpos_ptr[coefi] || Al != Ah-1) + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + } + last_bitpos_ptr[coefi] = Al; + } + } +#endif + } else { + /* For sequential JPEG, all progression parameters must be these: */ + if (Ss != 0 || Se != DCTSIZE2-1 || Ah != 0 || Al != 0) + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + /* Make sure components are not sent twice */ + for (ci = 0; ci < ncomps; ci++) { + thisi = scanptr->component_index[ci]; + if (component_sent[thisi]) + ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno); + component_sent[thisi] = TRUE; + } + } + } + + /* Now verify that everything got sent. */ + if (cinfo->progressive_mode) { +#ifdef C_PROGRESSIVE_SUPPORTED + /* For progressive mode, we only check that at least some DC data + * got sent for each component; the spec does not require that all bits + * of all coefficients be transmitted. Would it be wiser to enforce + * transmission of all coefficient bits?? + */ + for (ci = 0; ci < cinfo->num_components; ci++) { + if (last_bitpos[ci][0] < 0) + ERREXIT(cinfo, JERR_MISSING_DATA); + } +#endif + } else { + for (ci = 0; ci < cinfo->num_components; ci++) { + if (! component_sent[ci]) + ERREXIT(cinfo, JERR_MISSING_DATA); + } + } +} + +#endif /* C_MULTISCAN_FILES_SUPPORTED */ + + +LOCAL(void) +select_scan_parameters (j_compress_ptr cinfo) +/* Set up the scan parameters for the current scan */ +{ + int ci; + +#ifdef C_MULTISCAN_FILES_SUPPORTED + if (cinfo->scan_info != NULL) { + /* Prepare for current scan --- the script is already validated */ + my_master_ptr master = (my_master_ptr) cinfo->master; + const jpeg_scan_info * scanptr = cinfo->scan_info + master->scan_number; + + cinfo->comps_in_scan = scanptr->comps_in_scan; + for (ci = 0; ci < scanptr->comps_in_scan; ci++) { + cinfo->cur_comp_info[ci] = + &cinfo->comp_info[scanptr->component_index[ci]]; + } + cinfo->Ss = scanptr->Ss; + cinfo->Se = scanptr->Se; + cinfo->Ah = scanptr->Ah; + cinfo->Al = scanptr->Al; + } + else +#endif + { + /* Prepare for single sequential-JPEG scan containing all components */ + if (cinfo->num_components > MAX_COMPS_IN_SCAN) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, + MAX_COMPS_IN_SCAN); + cinfo->comps_in_scan = cinfo->num_components; + for (ci = 0; ci < cinfo->num_components; ci++) { + cinfo->cur_comp_info[ci] = &cinfo->comp_info[ci]; + } + cinfo->Ss = 0; + cinfo->Se = DCTSIZE2-1; + cinfo->Ah = 0; + cinfo->Al = 0; + } +} + + +LOCAL(void) +per_scan_setup (j_compress_ptr cinfo) +/* Do computations that are needed before processing a JPEG scan */ +/* cinfo->comps_in_scan and cinfo->cur_comp_info[] are already set */ +{ + int ci, mcublks, tmp; + jpeg_component_info *compptr; + + if (cinfo->comps_in_scan == 1) { + + /* Noninterleaved (single-component) scan */ + compptr = cinfo->cur_comp_info[0]; + + /* Overall image size in MCUs */ + cinfo->MCUs_per_row = compptr->width_in_blocks; + cinfo->MCU_rows_in_scan = compptr->height_in_blocks; + + /* For noninterleaved scan, always one block per MCU */ + compptr->MCU_width = 1; + compptr->MCU_height = 1; + compptr->MCU_blocks = 1; + compptr->MCU_sample_width = DCTSIZE; + compptr->last_col_width = 1; + /* For noninterleaved scans, it is convenient to define last_row_height + * as the number of block rows present in the last iMCU row. + */ + tmp = (int) (compptr->height_in_blocks % compptr->v_samp_factor); + if (tmp == 0) tmp = compptr->v_samp_factor; + compptr->last_row_height = tmp; + + /* Prepare array describing MCU composition */ + cinfo->blocks_in_MCU = 1; + cinfo->MCU_membership[0] = 0; + + } else { + + /* Interleaved (multi-component) scan */ + if (cinfo->comps_in_scan <= 0 || cinfo->comps_in_scan > MAX_COMPS_IN_SCAN) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->comps_in_scan, + MAX_COMPS_IN_SCAN); + + /* Overall image size in MCUs */ + cinfo->MCUs_per_row = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width, + (long) (cinfo->max_h_samp_factor*DCTSIZE)); + cinfo->MCU_rows_in_scan = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, + (long) (cinfo->max_v_samp_factor*DCTSIZE)); + + cinfo->blocks_in_MCU = 0; + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* Sampling factors give # of blocks of component in each MCU */ + compptr->MCU_width = compptr->h_samp_factor; + compptr->MCU_height = compptr->v_samp_factor; + compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height; + compptr->MCU_sample_width = compptr->MCU_width * DCTSIZE; + /* Figure number of non-dummy blocks in last MCU column & row */ + tmp = (int) (compptr->width_in_blocks % compptr->MCU_width); + if (tmp == 0) tmp = compptr->MCU_width; + compptr->last_col_width = tmp; + tmp = (int) (compptr->height_in_blocks % compptr->MCU_height); + if (tmp == 0) tmp = compptr->MCU_height; + compptr->last_row_height = tmp; + /* Prepare array describing MCU composition */ + mcublks = compptr->MCU_blocks; + if (cinfo->blocks_in_MCU + mcublks > C_MAX_BLOCKS_IN_MCU) + ERREXIT(cinfo, JERR_BAD_MCU_SIZE); + while (mcublks-- > 0) { + cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci; + } + } + + } + + /* Convert restart specified in rows to actual MCU count. */ + /* Note that count must fit in 16 bits, so we provide limiting. */ + if (cinfo->restart_in_rows > 0) { + long nominal = (long) cinfo->restart_in_rows * (long) cinfo->MCUs_per_row; + cinfo->restart_interval = (unsigned int) MIN(nominal, 65535L); + } +} + + +/* + * Per-pass setup. + * This is called at the beginning of each pass. We determine which modules + * will be active during this pass and give them appropriate start_pass calls. + * We also set is_last_pass to indicate whether any more passes will be + * required. + */ + +METHODDEF(void) +prepare_for_pass (j_compress_ptr cinfo) +{ + my_master_ptr master = (my_master_ptr) cinfo->master; + + switch (master->pass_type) { + case main_pass: + /* Initial pass: will collect input data, and do either Huffman + * optimization or data output for the first scan. + */ + select_scan_parameters(cinfo); + per_scan_setup(cinfo); + if (! cinfo->raw_data_in) { + (*cinfo->cconvert->start_pass) (cinfo); + (*cinfo->downsample->start_pass) (cinfo); + (*cinfo->prep->start_pass) (cinfo, JBUF_PASS_THRU); + } + (*cinfo->fdct->start_pass) (cinfo); + (*cinfo->entropy->start_pass) (cinfo, cinfo->optimize_coding); + (*cinfo->coef->start_pass) (cinfo, + (master->total_passes > 1 ? + JBUF_SAVE_AND_PASS : JBUF_PASS_THRU)); + (*cinfo->main->start_pass) (cinfo, JBUF_PASS_THRU); + if (cinfo->optimize_coding) { + /* No immediate data output; postpone writing frame/scan headers */ + master->pub.call_pass_startup = FALSE; + } else { + /* Will write frame/scan headers at first jpeg_write_scanlines call */ + master->pub.call_pass_startup = TRUE; + } + break; +#ifdef ENTROPY_OPT_SUPPORTED + case huff_opt_pass: + /* Do Huffman optimization for a scan after the first one. */ + select_scan_parameters(cinfo); + per_scan_setup(cinfo); + if (cinfo->Ss != 0 || cinfo->Ah == 0 || cinfo->arith_code) { + (*cinfo->entropy->start_pass) (cinfo, TRUE); + (*cinfo->coef->start_pass) (cinfo, JBUF_CRANK_DEST); + master->pub.call_pass_startup = FALSE; + break; + } + /* Special case: Huffman DC refinement scans need no Huffman table + * and therefore we can skip the optimization pass for them. + */ + master->pass_type = output_pass; + master->pass_number++; + /*FALLTHROUGH*/ +#endif + case output_pass: + /* Do a data-output pass. */ + /* We need not repeat per-scan setup if prior optimization pass did it. */ + if (! cinfo->optimize_coding) { + select_scan_parameters(cinfo); + per_scan_setup(cinfo); + } + (*cinfo->entropy->start_pass) (cinfo, FALSE); + (*cinfo->coef->start_pass) (cinfo, JBUF_CRANK_DEST); + /* We emit frame/scan headers now */ + if (master->scan_number == 0) + (*cinfo->marker->write_frame_header) (cinfo); + (*cinfo->marker->write_scan_header) (cinfo); + master->pub.call_pass_startup = FALSE; + break; + default: + ERREXIT(cinfo, JERR_NOT_COMPILED); + } + + master->pub.is_last_pass = (master->pass_number == master->total_passes-1); + + /* Set up progress monitor's pass info if present */ + if (cinfo->progress != NULL) { + cinfo->progress->completed_passes = master->pass_number; + cinfo->progress->total_passes = master->total_passes; + } +} + + +/* + * Special start-of-pass hook. + * This is called by jpeg_write_scanlines if call_pass_startup is TRUE. + * In single-pass processing, we need this hook because we don't want to + * write frame/scan headers during jpeg_start_compress; we want to let the + * application write COM markers etc. between jpeg_start_compress and the + * jpeg_write_scanlines loop. + * In multi-pass processing, this routine is not used. + */ + +METHODDEF(void) +pass_startup (j_compress_ptr cinfo) +{ + cinfo->master->call_pass_startup = FALSE; /* reset flag so call only once */ + + (*cinfo->marker->write_frame_header) (cinfo); + (*cinfo->marker->write_scan_header) (cinfo); +} + + +/* + * Finish up at end of pass. + */ + +METHODDEF(void) +finish_pass_master (j_compress_ptr cinfo) +{ + my_master_ptr master = (my_master_ptr) cinfo->master; + + /* The entropy coder always needs an end-of-pass call, + * either to analyze statistics or to flush its output buffer. + */ + (*cinfo->entropy->finish_pass) (cinfo); + + /* Update state for next pass */ + switch (master->pass_type) { + case main_pass: + /* next pass is either output of scan 0 (after optimization) + * or output of scan 1 (if no optimization). + */ + master->pass_type = output_pass; + if (! cinfo->optimize_coding) + master->scan_number++; + break; + case huff_opt_pass: + /* next pass is always output of current scan */ + master->pass_type = output_pass; + break; + case output_pass: + /* next pass is either optimization or output of next scan */ + if (cinfo->optimize_coding) + master->pass_type = huff_opt_pass; + master->scan_number++; + break; + } + + master->pass_number++; +} + + +/* + * Initialize master compression control. + */ + +GLOBAL(void) +jinit_c_master_control (j_compress_ptr cinfo, boolean transcode_only) +{ + my_master_ptr master; + + master = (my_master_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_comp_master)); + cinfo->master = (struct jpeg_comp_master *) master; + master->pub.prepare_for_pass = prepare_for_pass; + master->pub.pass_startup = pass_startup; + master->pub.finish_pass = finish_pass_master; + master->pub.is_last_pass = FALSE; + + /* Validate parameters, determine derived values */ + initial_setup(cinfo); + + if (cinfo->scan_info != NULL) { +#ifdef C_MULTISCAN_FILES_SUPPORTED + validate_script(cinfo); +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else { + cinfo->progressive_mode = FALSE; + cinfo->num_scans = 1; + } + + if (cinfo->progressive_mode) /* TEMPORARY HACK ??? */ + cinfo->optimize_coding = TRUE; /* assume default tables no good for progressive mode */ + + /* Initialize my private state */ + if (transcode_only) { + /* no main pass in transcoding */ + if (cinfo->optimize_coding) + master->pass_type = huff_opt_pass; + else + master->pass_type = output_pass; + } else { + /* for normal compression, first pass is always this type: */ + master->pass_type = main_pass; + } + master->scan_number = 0; + master->pass_number = 0; + if (cinfo->optimize_coding) + master->total_passes = cinfo->num_scans * 2; + else + master->total_passes = cinfo->num_scans; +} diff --git a/jpeg/JCOMAPI.C b/jpeg/JCOMAPI.C new file mode 100644 index 0000000..f6ecc1d --- /dev/null +++ b/jpeg/JCOMAPI.C @@ -0,0 +1,106 @@ +/* + * jcomapi.c + * + * Copyright (C) 1994-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains application interface routines that are used for both + * compression and decompression. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* + * Abort processing of a JPEG compression or decompression operation, + * but don't destroy the object itself. + * + * For this, we merely clean up all the nonpermanent memory pools. + * Note that temp files (virtual arrays) are not allowed to belong to + * the permanent pool, so we will be able to close all temp files here. + * Closing a data source or destination, if necessary, is the application's + * responsibility. + */ + +GLOBAL(void) +jpeg_abort (j_common_ptr cinfo) +{ + int pool; + + /* Do nothing if called on a not-initialized or destroyed JPEG object. */ + if (cinfo->mem == NULL) + return; + + /* Releasing pools in reverse order might help avoid fragmentation + * with some (brain-damaged) malloc libraries. + */ + for (pool = JPOOL_NUMPOOLS-1; pool > JPOOL_PERMANENT; pool--) { + (*cinfo->mem->free_pool) (cinfo, pool); + } + + /* Reset overall state for possible reuse of object */ + if (cinfo->is_decompressor) { + cinfo->global_state = DSTATE_START; + /* Try to keep application from accessing now-deleted marker list. + * A bit kludgy to do it here, but this is the most central place. + */ + ((j_decompress_ptr) cinfo)->marker_list = NULL; + } else { + cinfo->global_state = CSTATE_START; + } +} + + +/* + * Destruction of a JPEG object. + * + * Everything gets deallocated except the master jpeg_compress_struct itself + * and the error manager struct. Both of these are supplied by the application + * and must be freed, if necessary, by the application. (Often they are on + * the stack and so don't need to be freed anyway.) + * Closing a data source or destination, if necessary, is the application's + * responsibility. + */ + +GLOBAL(void) +jpeg_destroy (j_common_ptr cinfo) +{ + /* We need only tell the memory manager to release everything. */ + /* NB: mem pointer is NULL if memory mgr failed to initialize. */ + if (cinfo->mem != NULL) + (*cinfo->mem->self_destruct) (cinfo); + cinfo->mem = NULL; /* be safe if jpeg_destroy is called twice */ + cinfo->global_state = 0; /* mark it destroyed */ +} + + +/* + * Convenience routines for allocating quantization and Huffman tables. + * (Would jutils.c be a more reasonable place to put these?) + */ + +GLOBAL(JQUANT_TBL *) +jpeg_alloc_quant_table (j_common_ptr cinfo) +{ + JQUANT_TBL *tbl; + + tbl = (JQUANT_TBL *) + (*cinfo->mem->alloc_small) (cinfo, JPOOL_PERMANENT, SIZEOF(JQUANT_TBL)); + tbl->sent_table = FALSE; /* make sure this is false in any new table */ + return tbl; +} + + +GLOBAL(JHUFF_TBL *) +jpeg_alloc_huff_table (j_common_ptr cinfo) +{ + JHUFF_TBL *tbl; + + tbl = (JHUFF_TBL *) + (*cinfo->mem->alloc_small) (cinfo, JPOOL_PERMANENT, SIZEOF(JHUFF_TBL)); + tbl->sent_table = FALSE; /* make sure this is false in any new table */ + return tbl; +} diff --git a/jpeg/JCPHUFF.C b/jpeg/JCPHUFF.C new file mode 100644 index 0000000..9f6fb94 --- /dev/null +++ b/jpeg/JCPHUFF.C @@ -0,0 +1,833 @@ +/* + * jcphuff.c + * + * Copyright (C) 1995-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains Huffman entropy encoding routines for progressive JPEG. + * + * We do not support output suspension in this module, since the library + * currently does not allow multiple-scan files to be written with output + * suspension. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jchuff.h" /* Declarations shared with jchuff.c */ + +#ifdef C_PROGRESSIVE_SUPPORTED + +/* Expanded entropy encoder object for progressive Huffman encoding. */ + +typedef struct { + struct jpeg_entropy_encoder pub; /* public fields */ + + /* Mode flag: TRUE for optimization, FALSE for actual data output */ + boolean gather_statistics; + + /* Bit-level coding status. + * next_output_byte/free_in_buffer are local copies of cinfo->dest fields. + */ + JOCTET * next_output_byte; /* => next byte to write in buffer */ + size_t free_in_buffer; /* # of byte spaces remaining in buffer */ + INT32 put_buffer; /* current bit-accumulation buffer */ + int put_bits; /* # of bits now in it */ + j_compress_ptr cinfo; /* link to cinfo (needed for dump_buffer) */ + + /* Coding status for DC components */ + int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ + + /* Coding status for AC components */ + int ac_tbl_no; /* the table number of the single component */ + unsigned int EOBRUN; /* run length of EOBs */ + unsigned int BE; /* # of buffered correction bits before MCU */ + char * bit_buffer; /* buffer for correction bits (1 per char) */ + /* packing correction bits tightly would save some space but cost time... */ + + unsigned int restarts_to_go; /* MCUs left in this restart interval */ + int next_restart_num; /* next restart number to write (0-7) */ + + /* Pointers to derived tables (these workspaces have image lifespan). + * Since any one scan codes only DC or only AC, we only need one set + * of tables, not one for DC and one for AC. + */ + c_derived_tbl * derived_tbls[NUM_HUFF_TBLS]; + + /* Statistics tables for optimization; again, one set is enough */ + long * count_ptrs[NUM_HUFF_TBLS]; +} phuff_entropy_encoder; + +typedef phuff_entropy_encoder * phuff_entropy_ptr; + +/* MAX_CORR_BITS is the number of bits the AC refinement correction-bit + * buffer can hold. Larger sizes may slightly improve compression, but + * 1000 is already well into the realm of overkill. + * The minimum safe size is 64 bits. + */ + +#define MAX_CORR_BITS 1000 /* Max # of correction bits I can buffer */ + +/* IRIGHT_SHIFT is like RIGHT_SHIFT, but works on int rather than INT32. + * We assume that int right shift is unsigned if INT32 right shift is, + * which should be safe. + */ + +#ifdef RIGHT_SHIFT_IS_UNSIGNED +#define ISHIFT_TEMPS int ishift_temp; +#define IRIGHT_SHIFT(x,shft) \ + ((ishift_temp = (x)) < 0 ? \ + (ishift_temp >> (shft)) | ((~0) << (16-(shft))) : \ + (ishift_temp >> (shft))) +#else +#define ISHIFT_TEMPS +#define IRIGHT_SHIFT(x,shft) ((x) >> (shft)) +#endif + +/* Forward declarations */ +METHODDEF(boolean) encode_mcu_DC_first JPP((j_compress_ptr cinfo, + JBLOCKROW *MCU_data)); +METHODDEF(boolean) encode_mcu_AC_first JPP((j_compress_ptr cinfo, + JBLOCKROW *MCU_data)); +METHODDEF(boolean) encode_mcu_DC_refine JPP((j_compress_ptr cinfo, + JBLOCKROW *MCU_data)); +METHODDEF(boolean) encode_mcu_AC_refine JPP((j_compress_ptr cinfo, + JBLOCKROW *MCU_data)); +METHODDEF(void) finish_pass_phuff JPP((j_compress_ptr cinfo)); +METHODDEF(void) finish_pass_gather_phuff JPP((j_compress_ptr cinfo)); + + +/* + * Initialize for a Huffman-compressed scan using progressive JPEG. + */ + +METHODDEF(void) +start_pass_phuff (j_compress_ptr cinfo, boolean gather_statistics) +{ + phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; + boolean is_DC_band; + int ci, tbl; + jpeg_component_info * compptr; + + entropy->cinfo = cinfo; + entropy->gather_statistics = gather_statistics; + + is_DC_band = (cinfo->Ss == 0); + + /* We assume jcmaster.c already validated the scan parameters. */ + + /* Select execution routines */ + if (cinfo->Ah == 0) { + if (is_DC_band) + entropy->pub.encode_mcu = encode_mcu_DC_first; + else + entropy->pub.encode_mcu = encode_mcu_AC_first; + } else { + if (is_DC_band) + entropy->pub.encode_mcu = encode_mcu_DC_refine; + else { + entropy->pub.encode_mcu = encode_mcu_AC_refine; + /* AC refinement needs a correction bit buffer */ + if (entropy->bit_buffer == NULL) + entropy->bit_buffer = (char *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + MAX_CORR_BITS * SIZEOF(char)); + } + } + if (gather_statistics) + entropy->pub.finish_pass = finish_pass_gather_phuff; + else + entropy->pub.finish_pass = finish_pass_phuff; + + /* Only DC coefficients may be interleaved, so cinfo->comps_in_scan = 1 + * for AC coefficients. + */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* Initialize DC predictions to 0 */ + entropy->last_dc_val[ci] = 0; + /* Get table index */ + if (is_DC_band) { + if (cinfo->Ah != 0) /* DC refinement needs no table */ + continue; + tbl = compptr->dc_tbl_no; + } else { + entropy->ac_tbl_no = tbl = compptr->ac_tbl_no; + } + if (gather_statistics) { + /* Check for invalid table index */ + /* (make_c_derived_tbl does this in the other path) */ + if (tbl < 0 || tbl >= NUM_HUFF_TBLS) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tbl); + /* Allocate and zero the statistics tables */ + /* Note that jpeg_gen_optimal_table expects 257 entries in each table! */ + if (entropy->count_ptrs[tbl] == NULL) + entropy->count_ptrs[tbl] = (long *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + 257 * SIZEOF(long)); + MEMZERO(entropy->count_ptrs[tbl], 257 * SIZEOF(long)); + } else { + /* Compute derived values for Huffman table */ + /* We may do this more than once for a table, but it's not expensive */ + jpeg_make_c_derived_tbl(cinfo, is_DC_band, tbl, + & entropy->derived_tbls[tbl]); + } + } + + /* Initialize AC stuff */ + entropy->EOBRUN = 0; + entropy->BE = 0; + + /* Initialize bit buffer to empty */ + entropy->put_buffer = 0; + entropy->put_bits = 0; + + /* Initialize restart stuff */ + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num = 0; +} + + +/* Outputting bytes to the file. + * NB: these must be called only when actually outputting, + * that is, entropy->gather_statistics == FALSE. + */ + +/* Emit a byte */ +#define emit_byte(entropy,val) \ + { *(entropy)->next_output_byte++ = (JOCTET) (val); \ + if (--(entropy)->free_in_buffer == 0) \ + dump_buffer(entropy); } + + +LOCAL(void) +dump_buffer (phuff_entropy_ptr entropy) +/* Empty the output buffer; we do not support suspension in this module. */ +{ + struct jpeg_destination_mgr * dest = entropy->cinfo->dest; + + if (! (*dest->empty_output_buffer) (entropy->cinfo)) + ERREXIT(entropy->cinfo, JERR_CANT_SUSPEND); + /* After a successful buffer dump, must reset buffer pointers */ + entropy->next_output_byte = dest->next_output_byte; + entropy->free_in_buffer = dest->free_in_buffer; +} + + +/* Outputting bits to the file */ + +/* Only the right 24 bits of put_buffer are used; the valid bits are + * left-justified in this part. At most 16 bits can be passed to emit_bits + * in one call, and we never retain more than 7 bits in put_buffer + * between calls, so 24 bits are sufficient. + */ + +INLINE +LOCAL(void) +emit_bits (phuff_entropy_ptr entropy, unsigned int code, int size) +/* Emit some bits, unless we are in gather mode */ +{ + /* This routine is heavily used, so it's worth coding tightly. */ + register INT32 put_buffer = (INT32) code; + register int put_bits = entropy->put_bits; + + /* if size is 0, caller used an invalid Huffman table entry */ + if (size == 0) + ERREXIT(entropy->cinfo, JERR_HUFF_MISSING_CODE); + + if (entropy->gather_statistics) + return; /* do nothing if we're only getting stats */ + + put_buffer &= (((INT32) 1)<put_buffer; /* and merge with old buffer contents */ + + while (put_bits >= 8) { + int c = (int) ((put_buffer >> 16) & 0xFF); + + emit_byte(entropy, c); + if (c == 0xFF) { /* need to stuff a zero byte? */ + emit_byte(entropy, 0); + } + put_buffer <<= 8; + put_bits -= 8; + } + + entropy->put_buffer = put_buffer; /* update variables */ + entropy->put_bits = put_bits; +} + + +LOCAL(void) +flush_bits (phuff_entropy_ptr entropy) +{ + emit_bits(entropy, 0x7F, 7); /* fill any partial byte with ones */ + entropy->put_buffer = 0; /* and reset bit-buffer to empty */ + entropy->put_bits = 0; +} + + +/* + * Emit (or just count) a Huffman symbol. + */ + +INLINE +LOCAL(void) +emit_symbol (phuff_entropy_ptr entropy, int tbl_no, int symbol) +{ + if (entropy->gather_statistics) + entropy->count_ptrs[tbl_no][symbol]++; + else { + c_derived_tbl * tbl = entropy->derived_tbls[tbl_no]; + emit_bits(entropy, tbl->ehufco[symbol], tbl->ehufsi[symbol]); + } +} + + +/* + * Emit bits from a correction bit buffer. + */ + +LOCAL(void) +emit_buffered_bits (phuff_entropy_ptr entropy, char * bufstart, + unsigned int nbits) +{ + if (entropy->gather_statistics) + return; /* no real work */ + + while (nbits > 0) { + emit_bits(entropy, (unsigned int) (*bufstart), 1); + bufstart++; + nbits--; + } +} + + +/* + * Emit any pending EOBRUN symbol. + */ + +LOCAL(void) +emit_eobrun (phuff_entropy_ptr entropy) +{ + register int temp, nbits; + + if (entropy->EOBRUN > 0) { /* if there is any pending EOBRUN */ + temp = entropy->EOBRUN; + nbits = 0; + while ((temp >>= 1)) + nbits++; + /* safety check: shouldn't happen given limited correction-bit buffer */ + if (nbits > 14) + ERREXIT(entropy->cinfo, JERR_HUFF_MISSING_CODE); + + emit_symbol(entropy, entropy->ac_tbl_no, nbits << 4); + if (nbits) + emit_bits(entropy, entropy->EOBRUN, nbits); + + entropy->EOBRUN = 0; + + /* Emit any buffered correction bits */ + emit_buffered_bits(entropy, entropy->bit_buffer, entropy->BE); + entropy->BE = 0; + } +} + + +/* + * Emit a restart marker & resynchronize predictions. + */ + +LOCAL(void) +emit_restart (phuff_entropy_ptr entropy, int restart_num) +{ + int ci; + + emit_eobrun(entropy); + + if (! entropy->gather_statistics) { + flush_bits(entropy); + emit_byte(entropy, 0xFF); + emit_byte(entropy, JPEG_RST0 + restart_num); + } + + if (entropy->cinfo->Ss == 0) { + /* Re-initialize DC predictions to 0 */ + for (ci = 0; ci < entropy->cinfo->comps_in_scan; ci++) + entropy->last_dc_val[ci] = 0; + } else { + /* Re-initialize all AC-related fields to 0 */ + entropy->EOBRUN = 0; + entropy->BE = 0; + } +} + + +/* + * MCU encoding for DC initial scan (either spectral selection, + * or first pass of successive approximation). + */ + +METHODDEF(boolean) +encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; + register int temp, temp2; + register int nbits; + int blkn, ci; + int Al = cinfo->Al; + JBLOCKROW block; + jpeg_component_info * compptr; + ISHIFT_TEMPS + + entropy->next_output_byte = cinfo->dest->next_output_byte; + entropy->free_in_buffer = cinfo->dest->free_in_buffer; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) + if (entropy->restarts_to_go == 0) + emit_restart(entropy, entropy->next_restart_num); + + /* Encode the MCU data blocks */ + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + block = MCU_data[blkn]; + ci = cinfo->MCU_membership[blkn]; + compptr = cinfo->cur_comp_info[ci]; + + /* Compute the DC value after the required point transform by Al. + * This is simply an arithmetic right shift. + */ + temp2 = IRIGHT_SHIFT((int) ((*block)[0]), Al); + + /* DC differences are figured on the point-transformed values. */ + temp = temp2 - entropy->last_dc_val[ci]; + entropy->last_dc_val[ci] = temp2; + + /* Encode the DC coefficient difference per section G.1.2.1 */ + temp2 = temp; + if (temp < 0) { + temp = -temp; /* temp is abs value of input */ + /* For a negative input, want temp2 = bitwise complement of abs(input) */ + /* This code assumes we are on a two's complement machine */ + temp2--; + } + + /* Find the number of bits needed for the magnitude of the coefficient */ + nbits = 0; + while (temp) { + nbits++; + temp >>= 1; + } + /* Check for out-of-range coefficient values. + * Since we're encoding a difference, the range limit is twice as much. + */ + if (nbits > MAX_COEF_BITS+1) + ERREXIT(cinfo, JERR_BAD_DCT_COEF); + + /* Count/emit the Huffman-coded symbol for the number of bits */ + emit_symbol(entropy, compptr->dc_tbl_no, nbits); + + /* Emit that number of bits of the value, if positive, */ + /* or the complement of its magnitude, if negative. */ + if (nbits) /* emit_bits rejects calls with size 0 */ + emit_bits(entropy, (unsigned int) temp2, nbits); + } + + cinfo->dest->next_output_byte = entropy->next_output_byte; + cinfo->dest->free_in_buffer = entropy->free_in_buffer; + + /* Update restart-interval state too */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + return TRUE; +} + + +/* + * MCU encoding for AC initial scan (either spectral selection, + * or first pass of successive approximation). + */ + +METHODDEF(boolean) +encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; + register int temp, temp2; + register int nbits; + register int r, k; + int Se = cinfo->Se; + int Al = cinfo->Al; + JBLOCKROW block; + + entropy->next_output_byte = cinfo->dest->next_output_byte; + entropy->free_in_buffer = cinfo->dest->free_in_buffer; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) + if (entropy->restarts_to_go == 0) + emit_restart(entropy, entropy->next_restart_num); + + /* Encode the MCU data block */ + block = MCU_data[0]; + + /* Encode the AC coefficients per section G.1.2.2, fig. G.3 */ + + r = 0; /* r = run length of zeros */ + + for (k = cinfo->Ss; k <= Se; k++) { + if ((temp = (*block)[jpeg_natural_order[k]]) == 0) { + r++; + continue; + } + /* We must apply the point transform by Al. For AC coefficients this + * is an integer division with rounding towards 0. To do this portably + * in C, we shift after obtaining the absolute value; so the code is + * interwoven with finding the abs value (temp) and output bits (temp2). + */ + if (temp < 0) { + temp = -temp; /* temp is abs value of input */ + temp >>= Al; /* apply the point transform */ + /* For a negative coef, want temp2 = bitwise complement of abs(coef) */ + temp2 = ~temp; + } else { + temp >>= Al; /* apply the point transform */ + temp2 = temp; + } + /* Watch out for case that nonzero coef is zero after point transform */ + if (temp == 0) { + r++; + continue; + } + + /* Emit any pending EOBRUN */ + if (entropy->EOBRUN > 0) + emit_eobrun(entropy); + /* if run length > 15, must emit special run-length-16 codes (0xF0) */ + while (r > 15) { + emit_symbol(entropy, entropy->ac_tbl_no, 0xF0); + r -= 16; + } + + /* Find the number of bits needed for the magnitude of the coefficient */ + nbits = 1; /* there must be at least one 1 bit */ + while ((temp >>= 1)) + nbits++; + /* Check for out-of-range coefficient values */ + if (nbits > MAX_COEF_BITS) + ERREXIT(cinfo, JERR_BAD_DCT_COEF); + + /* Count/emit Huffman symbol for run length / number of bits */ + emit_symbol(entropy, entropy->ac_tbl_no, (r << 4) + nbits); + + /* Emit that number of bits of the value, if positive, */ + /* or the complement of its magnitude, if negative. */ + emit_bits(entropy, (unsigned int) temp2, nbits); + + r = 0; /* reset zero run length */ + } + + if (r > 0) { /* If there are trailing zeroes, */ + entropy->EOBRUN++; /* count an EOB */ + if (entropy->EOBRUN == 0x7FFF) + emit_eobrun(entropy); /* force it out to avoid overflow */ + } + + cinfo->dest->next_output_byte = entropy->next_output_byte; + cinfo->dest->free_in_buffer = entropy->free_in_buffer; + + /* Update restart-interval state too */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + return TRUE; +} + + +/* + * MCU encoding for DC successive approximation refinement scan. + * Note: we assume such scans can be multi-component, although the spec + * is not very clear on the point. + */ + +METHODDEF(boolean) +encode_mcu_DC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; + register int temp; + int blkn; + int Al = cinfo->Al; + JBLOCKROW block; + + entropy->next_output_byte = cinfo->dest->next_output_byte; + entropy->free_in_buffer = cinfo->dest->free_in_buffer; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) + if (entropy->restarts_to_go == 0) + emit_restart(entropy, entropy->next_restart_num); + + /* Encode the MCU data blocks */ + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + block = MCU_data[blkn]; + + /* We simply emit the Al'th bit of the DC coefficient value. */ + temp = (*block)[0]; + emit_bits(entropy, (unsigned int) (temp >> Al), 1); + } + + cinfo->dest->next_output_byte = entropy->next_output_byte; + cinfo->dest->free_in_buffer = entropy->free_in_buffer; + + /* Update restart-interval state too */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + return TRUE; +} + + +/* + * MCU encoding for AC successive approximation refinement scan. + */ + +METHODDEF(boolean) +encode_mcu_AC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; + register int temp; + register int r, k; + int EOB; + char *BR_buffer; + unsigned int BR; + int Se = cinfo->Se; + int Al = cinfo->Al; + JBLOCKROW block; + int absvalues[DCTSIZE2]; + + entropy->next_output_byte = cinfo->dest->next_output_byte; + entropy->free_in_buffer = cinfo->dest->free_in_buffer; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) + if (entropy->restarts_to_go == 0) + emit_restart(entropy, entropy->next_restart_num); + + /* Encode the MCU data block */ + block = MCU_data[0]; + + /* It is convenient to make a pre-pass to determine the transformed + * coefficients' absolute values and the EOB position. + */ + EOB = 0; + for (k = cinfo->Ss; k <= Se; k++) { + temp = (*block)[jpeg_natural_order[k]]; + /* We must apply the point transform by Al. For AC coefficients this + * is an integer division with rounding towards 0. To do this portably + * in C, we shift after obtaining the absolute value. + */ + if (temp < 0) + temp = -temp; /* temp is abs value of input */ + temp >>= Al; /* apply the point transform */ + absvalues[k] = temp; /* save abs value for main pass */ + if (temp == 1) + EOB = k; /* EOB = index of last newly-nonzero coef */ + } + + /* Encode the AC coefficients per section G.1.2.3, fig. G.7 */ + + r = 0; /* r = run length of zeros */ + BR = 0; /* BR = count of buffered bits added now */ + BR_buffer = entropy->bit_buffer + entropy->BE; /* Append bits to buffer */ + + for (k = cinfo->Ss; k <= Se; k++) { + if ((temp = absvalues[k]) == 0) { + r++; + continue; + } + + /* Emit any required ZRLs, but not if they can be folded into EOB */ + while (r > 15 && k <= EOB) { + /* emit any pending EOBRUN and the BE correction bits */ + emit_eobrun(entropy); + /* Emit ZRL */ + emit_symbol(entropy, entropy->ac_tbl_no, 0xF0); + r -= 16; + /* Emit buffered correction bits that must be associated with ZRL */ + emit_buffered_bits(entropy, BR_buffer, BR); + BR_buffer = entropy->bit_buffer; /* BE bits are gone now */ + BR = 0; + } + + /* If the coef was previously nonzero, it only needs a correction bit. + * NOTE: a straight translation of the spec's figure G.7 would suggest + * that we also need to test r > 15. But if r > 15, we can only get here + * if k > EOB, which implies that this coefficient is not 1. + */ + if (temp > 1) { + /* The correction bit is the next bit of the absolute value. */ + BR_buffer[BR++] = (char) (temp & 1); + continue; + } + + /* Emit any pending EOBRUN and the BE correction bits */ + emit_eobrun(entropy); + + /* Count/emit Huffman symbol for run length / number of bits */ + emit_symbol(entropy, entropy->ac_tbl_no, (r << 4) + 1); + + /* Emit output bit for newly-nonzero coef */ + temp = ((*block)[jpeg_natural_order[k]] < 0) ? 0 : 1; + emit_bits(entropy, (unsigned int) temp, 1); + + /* Emit buffered correction bits that must be associated with this code */ + emit_buffered_bits(entropy, BR_buffer, BR); + BR_buffer = entropy->bit_buffer; /* BE bits are gone now */ + BR = 0; + r = 0; /* reset zero run length */ + } + + if (r > 0 || BR > 0) { /* If there are trailing zeroes, */ + entropy->EOBRUN++; /* count an EOB */ + entropy->BE += BR; /* concat my correction bits to older ones */ + /* We force out the EOB if we risk either: + * 1. overflow of the EOB counter; + * 2. overflow of the correction bit buffer during the next MCU. + */ + if (entropy->EOBRUN == 0x7FFF || entropy->BE > (MAX_CORR_BITS-DCTSIZE2+1)) + emit_eobrun(entropy); + } + + cinfo->dest->next_output_byte = entropy->next_output_byte; + cinfo->dest->free_in_buffer = entropy->free_in_buffer; + + /* Update restart-interval state too */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + return TRUE; +} + + +/* + * Finish up at the end of a Huffman-compressed progressive scan. + */ + +METHODDEF(void) +finish_pass_phuff (j_compress_ptr cinfo) +{ + phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; + + entropy->next_output_byte = cinfo->dest->next_output_byte; + entropy->free_in_buffer = cinfo->dest->free_in_buffer; + + /* Flush out any buffered data */ + emit_eobrun(entropy); + flush_bits(entropy); + + cinfo->dest->next_output_byte = entropy->next_output_byte; + cinfo->dest->free_in_buffer = entropy->free_in_buffer; +} + + +/* + * Finish up a statistics-gathering pass and create the new Huffman tables. + */ + +METHODDEF(void) +finish_pass_gather_phuff (j_compress_ptr cinfo) +{ + phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; + boolean is_DC_band; + int ci, tbl; + jpeg_component_info * compptr; + JHUFF_TBL **htblptr; + boolean did[NUM_HUFF_TBLS]; + + /* Flush out buffered data (all we care about is counting the EOB symbol) */ + emit_eobrun(entropy); + + is_DC_band = (cinfo->Ss == 0); + + /* It's important not to apply jpeg_gen_optimal_table more than once + * per table, because it clobbers the input frequency counts! + */ + MEMZERO(did, SIZEOF(did)); + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + if (is_DC_band) { + if (cinfo->Ah != 0) /* DC refinement needs no table */ + continue; + tbl = compptr->dc_tbl_no; + } else { + tbl = compptr->ac_tbl_no; + } + if (! did[tbl]) { + if (is_DC_band) + htblptr = & cinfo->dc_huff_tbl_ptrs[tbl]; + else + htblptr = & cinfo->ac_huff_tbl_ptrs[tbl]; + if (*htblptr == NULL) + *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); + jpeg_gen_optimal_table(cinfo, *htblptr, entropy->count_ptrs[tbl]); + did[tbl] = TRUE; + } + } +} + + +/* + * Module initialization routine for progressive Huffman entropy encoding. + */ + +GLOBAL(void) +jinit_phuff_encoder (j_compress_ptr cinfo) +{ + phuff_entropy_ptr entropy; + int i; + + entropy = (phuff_entropy_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(phuff_entropy_encoder)); + cinfo->entropy = (struct jpeg_entropy_encoder *) entropy; + entropy->pub.start_pass = start_pass_phuff; + + /* Mark tables unallocated */ + for (i = 0; i < NUM_HUFF_TBLS; i++) { + entropy->derived_tbls[i] = NULL; + entropy->count_ptrs[i] = NULL; + } + entropy->bit_buffer = NULL; /* needed only in AC refinement scan */ +} + +#endif /* C_PROGRESSIVE_SUPPORTED */ diff --git a/jpeg/JCPREPCT.C b/jpeg/JCPREPCT.C new file mode 100644 index 0000000..da4df5d --- /dev/null +++ b/jpeg/JCPREPCT.C @@ -0,0 +1,354 @@ +/* + * jcprepct.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the compression preprocessing controller. + * This controller manages the color conversion, downsampling, + * and edge expansion steps. + * + * Most of the complexity here is associated with buffering input rows + * as required by the downsampler. See the comments at the head of + * jcsample.c for the downsampler's needs. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* At present, jcsample.c can request context rows only for smoothing. + * In the future, we might also need context rows for CCIR601 sampling + * or other more-complex downsampling procedures. The code to support + * context rows should be compiled only if needed. + */ +#ifdef INPUT_SMOOTHING_SUPPORTED +#define CONTEXT_ROWS_SUPPORTED +#endif + + +/* + * For the simple (no-context-row) case, we just need to buffer one + * row group's worth of pixels for the downsampling step. At the bottom of + * the image, we pad to a full row group by replicating the last pixel row. + * The downsampler's last output row is then replicated if needed to pad + * out to a full iMCU row. + * + * When providing context rows, we must buffer three row groups' worth of + * pixels. Three row groups are physically allocated, but the row pointer + * arrays are made five row groups high, with the extra pointers above and + * below "wrapping around" to point to the last and first real row groups. + * This allows the downsampler to access the proper context rows. + * At the top and bottom of the image, we create dummy context rows by + * copying the first or last real pixel row. This copying could be avoided + * by pointer hacking as is done in jdmainct.c, but it doesn't seem worth the + * trouble on the compression side. + */ + + +/* Private buffer controller object */ + +typedef struct { + struct jpeg_c_prep_controller pub; /* public fields */ + + /* Downsampling input buffer. This buffer holds color-converted data + * until we have enough to do a downsample step. + */ + JSAMPARRAY color_buf[MAX_COMPONENTS]; + + JDIMENSION rows_to_go; /* counts rows remaining in source image */ + int next_buf_row; /* index of next row to store in color_buf */ + +#ifdef CONTEXT_ROWS_SUPPORTED /* only needed for context case */ + int this_row_group; /* starting row index of group to process */ + int next_buf_stop; /* downsample when we reach this index */ +#endif +} my_prep_controller; + +typedef my_prep_controller * my_prep_ptr; + + +/* + * Initialize for a processing pass. + */ + +METHODDEF(void) +start_pass_prep (j_compress_ptr cinfo, J_BUF_MODE pass_mode) +{ + my_prep_ptr prep = (my_prep_ptr) cinfo->prep; + + if (pass_mode != JBUF_PASS_THRU) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + + /* Initialize total-height counter for detecting bottom of image */ + prep->rows_to_go = cinfo->image_height; + /* Mark the conversion buffer empty */ + prep->next_buf_row = 0; +#ifdef CONTEXT_ROWS_SUPPORTED + /* Preset additional state variables for context mode. + * These aren't used in non-context mode, so we needn't test which mode. + */ + prep->this_row_group = 0; + /* Set next_buf_stop to stop after two row groups have been read in. */ + prep->next_buf_stop = 2 * cinfo->max_v_samp_factor; +#endif +} + + +/* + * Expand an image vertically from height input_rows to height output_rows, + * by duplicating the bottom row. + */ + +LOCAL(void) +expand_bottom_edge (JSAMPARRAY image_data, JDIMENSION num_cols, + int input_rows, int output_rows) +{ + register int row; + + for (row = input_rows; row < output_rows; row++) { + jcopy_sample_rows(image_data, input_rows-1, image_data, row, + 1, num_cols); + } +} + + +/* + * Process some data in the simple no-context case. + * + * Preprocessor output data is counted in "row groups". A row group + * is defined to be v_samp_factor sample rows of each component. + * Downsampling will produce this much data from each max_v_samp_factor + * input rows. + */ + +METHODDEF(void) +pre_process_data (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail, + JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr, + JDIMENSION out_row_groups_avail) +{ + my_prep_ptr prep = (my_prep_ptr) cinfo->prep; + int numrows, ci; + JDIMENSION inrows; + jpeg_component_info * compptr; + + while (*in_row_ctr < in_rows_avail && + *out_row_group_ctr < out_row_groups_avail) { + /* Do color conversion to fill the conversion buffer. */ + inrows = in_rows_avail - *in_row_ctr; + numrows = cinfo->max_v_samp_factor - prep->next_buf_row; + numrows = (int) MIN((JDIMENSION) numrows, inrows); + (*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr, + prep->color_buf, + (JDIMENSION) prep->next_buf_row, + numrows); + *in_row_ctr += numrows; + prep->next_buf_row += numrows; + prep->rows_to_go -= numrows; + /* If at bottom of image, pad to fill the conversion buffer. */ + if (prep->rows_to_go == 0 && + prep->next_buf_row < cinfo->max_v_samp_factor) { + for (ci = 0; ci < cinfo->num_components; ci++) { + expand_bottom_edge(prep->color_buf[ci], cinfo->image_width, + prep->next_buf_row, cinfo->max_v_samp_factor); + } + prep->next_buf_row = cinfo->max_v_samp_factor; + } + /* If we've filled the conversion buffer, empty it. */ + if (prep->next_buf_row == cinfo->max_v_samp_factor) { + (*cinfo->downsample->downsample) (cinfo, + prep->color_buf, (JDIMENSION) 0, + output_buf, *out_row_group_ctr); + prep->next_buf_row = 0; + (*out_row_group_ctr)++; + } + /* If at bottom of image, pad the output to a full iMCU height. + * Note we assume the caller is providing a one-iMCU-height output buffer! + */ + if (prep->rows_to_go == 0 && + *out_row_group_ctr < out_row_groups_avail) { + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + expand_bottom_edge(output_buf[ci], + compptr->width_in_blocks * DCTSIZE, + (int) (*out_row_group_ctr * compptr->v_samp_factor), + (int) (out_row_groups_avail * compptr->v_samp_factor)); + } + *out_row_group_ctr = out_row_groups_avail; + break; /* can exit outer loop without test */ + } + } +} + + +#ifdef CONTEXT_ROWS_SUPPORTED + +/* + * Process some data in the context case. + */ + +METHODDEF(void) +pre_process_context (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail, + JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr, + JDIMENSION out_row_groups_avail) +{ + my_prep_ptr prep = (my_prep_ptr) cinfo->prep; + int numrows, ci; + int buf_height = cinfo->max_v_samp_factor * 3; + JDIMENSION inrows; + + while (*out_row_group_ctr < out_row_groups_avail) { + if (*in_row_ctr < in_rows_avail) { + /* Do color conversion to fill the conversion buffer. */ + inrows = in_rows_avail - *in_row_ctr; + numrows = prep->next_buf_stop - prep->next_buf_row; + numrows = (int) MIN((JDIMENSION) numrows, inrows); + (*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr, + prep->color_buf, + (JDIMENSION) prep->next_buf_row, + numrows); + /* Pad at top of image, if first time through */ + if (prep->rows_to_go == cinfo->image_height) { + for (ci = 0; ci < cinfo->num_components; ci++) { + int row; + for (row = 1; row <= cinfo->max_v_samp_factor; row++) { + jcopy_sample_rows(prep->color_buf[ci], 0, + prep->color_buf[ci], -row, + 1, cinfo->image_width); + } + } + } + *in_row_ctr += numrows; + prep->next_buf_row += numrows; + prep->rows_to_go -= numrows; + } else { + /* Return for more data, unless we are at the bottom of the image. */ + if (prep->rows_to_go != 0) + break; + /* When at bottom of image, pad to fill the conversion buffer. */ + if (prep->next_buf_row < prep->next_buf_stop) { + for (ci = 0; ci < cinfo->num_components; ci++) { + expand_bottom_edge(prep->color_buf[ci], cinfo->image_width, + prep->next_buf_row, prep->next_buf_stop); + } + prep->next_buf_row = prep->next_buf_stop; + } + } + /* If we've gotten enough data, downsample a row group. */ + if (prep->next_buf_row == prep->next_buf_stop) { + (*cinfo->downsample->downsample) (cinfo, + prep->color_buf, + (JDIMENSION) prep->this_row_group, + output_buf, *out_row_group_ctr); + (*out_row_group_ctr)++; + /* Advance pointers with wraparound as necessary. */ + prep->this_row_group += cinfo->max_v_samp_factor; + if (prep->this_row_group >= buf_height) + prep->this_row_group = 0; + if (prep->next_buf_row >= buf_height) + prep->next_buf_row = 0; + prep->next_buf_stop = prep->next_buf_row + cinfo->max_v_samp_factor; + } + } +} + + +/* + * Create the wrapped-around downsampling input buffer needed for context mode. + */ + +LOCAL(void) +create_context_buffer (j_compress_ptr cinfo) +{ + my_prep_ptr prep = (my_prep_ptr) cinfo->prep; + int rgroup_height = cinfo->max_v_samp_factor; + int ci, i; + jpeg_component_info * compptr; + JSAMPARRAY true_buffer, fake_buffer; + + /* Grab enough space for fake row pointers for all the components; + * we need five row groups' worth of pointers for each component. + */ + fake_buffer = (JSAMPARRAY) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (cinfo->num_components * 5 * rgroup_height) * + SIZEOF(JSAMPROW)); + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Allocate the actual buffer space (3 row groups) for this component. + * We make the buffer wide enough to allow the downsampler to edge-expand + * horizontally within the buffer, if it so chooses. + */ + true_buffer = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) (((long) compptr->width_in_blocks * DCTSIZE * + cinfo->max_h_samp_factor) / compptr->h_samp_factor), + (JDIMENSION) (3 * rgroup_height)); + /* Copy true buffer row pointers into the middle of the fake row array */ + MEMCOPY(fake_buffer + rgroup_height, true_buffer, + 3 * rgroup_height * SIZEOF(JSAMPROW)); + /* Fill in the above and below wraparound pointers */ + for (i = 0; i < rgroup_height; i++) { + fake_buffer[i] = true_buffer[2 * rgroup_height + i]; + fake_buffer[4 * rgroup_height + i] = true_buffer[i]; + } + prep->color_buf[ci] = fake_buffer + rgroup_height; + fake_buffer += 5 * rgroup_height; /* point to space for next component */ + } +} + +#endif /* CONTEXT_ROWS_SUPPORTED */ + + +/* + * Initialize preprocessing controller. + */ + +GLOBAL(void) +jinit_c_prep_controller (j_compress_ptr cinfo, boolean need_full_buffer) +{ + my_prep_ptr prep; + int ci; + jpeg_component_info * compptr; + + if (need_full_buffer) /* safety check */ + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + + prep = (my_prep_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_prep_controller)); + cinfo->prep = (struct jpeg_c_prep_controller *) prep; + prep->pub.start_pass = start_pass_prep; + + /* Allocate the color conversion buffer. + * We make the buffer wide enough to allow the downsampler to edge-expand + * horizontally within the buffer, if it so chooses. + */ + if (cinfo->downsample->need_context_rows) { + /* Set up to provide context rows */ +#ifdef CONTEXT_ROWS_SUPPORTED + prep->pub.pre_process_data = pre_process_context; + create_context_buffer(cinfo); +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else { + /* No context, just make it tall enough for one row group */ + prep->pub.pre_process_data = pre_process_data; + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + prep->color_buf[ci] = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) (((long) compptr->width_in_blocks * DCTSIZE * + cinfo->max_h_samp_factor) / compptr->h_samp_factor), + (JDIMENSION) cinfo->max_v_samp_factor); + } + } +} diff --git a/jpeg/JCSAMPLE.C b/jpeg/JCSAMPLE.C new file mode 100644 index 0000000..71e3249 --- /dev/null +++ b/jpeg/JCSAMPLE.C @@ -0,0 +1,519 @@ +/* + * jcsample.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains downsampling routines. + * + * Downsampling input data is counted in "row groups". A row group + * is defined to be max_v_samp_factor pixel rows of each component, + * from which the downsampler produces v_samp_factor sample rows. + * A single row group is processed in each call to the downsampler module. + * + * The downsampler is responsible for edge-expansion of its output data + * to fill an integral number of DCT blocks horizontally. The source buffer + * may be modified if it is helpful for this purpose (the source buffer is + * allocated wide enough to correspond to the desired output width). + * The caller (the prep controller) is responsible for vertical padding. + * + * The downsampler may request "context rows" by setting need_context_rows + * during startup. In this case, the input arrays will contain at least + * one row group's worth of pixels above and below the passed-in data; + * the caller will create dummy rows at image top and bottom by replicating + * the first or last real pixel row. + * + * An excellent reference for image resampling is + * Digital Image Warping, George Wolberg, 1990. + * Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7. + * + * The downsampling algorithm used here is a simple average of the source + * pixels covered by the output pixel. The hi-falutin sampling literature + * refers to this as a "box filter". In general the characteristics of a box + * filter are not very good, but for the specific cases we normally use (1:1 + * and 2:1 ratios) the box is equivalent to a "triangle filter" which is not + * nearly so bad. If you intend to use other sampling ratios, you'd be well + * advised to improve this code. + * + * A simple input-smoothing capability is provided. This is mainly intended + * for cleaning up color-dithered GIF input files (if you find it inadequate, + * we suggest using an external filtering program such as pnmconvol). When + * enabled, each input pixel P is replaced by a weighted sum of itself and its + * eight neighbors. P's weight is 1-8*SF and each neighbor's weight is SF, + * where SF = (smoothing_factor / 1024). + * Currently, smoothing is only supported for 2h2v sampling factors. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Pointer to routine to downsample a single component */ +typedef JMETHOD(void, downsample1_ptr, + (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY output_data)); + +/* Private subobject */ + +typedef struct { + struct jpeg_downsampler pub; /* public fields */ + + /* Downsampling method pointers, one per component */ + downsample1_ptr methods[MAX_COMPONENTS]; +} my_downsampler; + +typedef my_downsampler * my_downsample_ptr; + + +/* + * Initialize for a downsampling pass. + */ + +METHODDEF(void) +start_pass_downsample (j_compress_ptr cinfo) +{ + /* no work for now */ +} + + +/* + * Expand a component horizontally from width input_cols to width output_cols, + * by duplicating the rightmost samples. + */ + +LOCAL(void) +expand_right_edge (JSAMPARRAY image_data, int num_rows, + JDIMENSION input_cols, JDIMENSION output_cols) +{ + register JSAMPROW ptr; + register JSAMPLE pixval; + register int count; + int row; + int numcols = (int) (output_cols - input_cols); + + if (numcols > 0) { + for (row = 0; row < num_rows; row++) { + ptr = image_data[row] + input_cols; + pixval = ptr[-1]; /* don't need GETJSAMPLE() here */ + for (count = numcols; count > 0; count--) + *ptr++ = pixval; + } + } +} + + +/* + * Do downsampling for a whole row group (all components). + * + * In this version we simply downsample each component independently. + */ + +METHODDEF(void) +sep_downsample (j_compress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION in_row_index, + JSAMPIMAGE output_buf, JDIMENSION out_row_group_index) +{ + my_downsample_ptr downsample = (my_downsample_ptr) cinfo->downsample; + int ci; + jpeg_component_info * compptr; + JSAMPARRAY in_ptr, out_ptr; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + in_ptr = input_buf[ci] + in_row_index; + out_ptr = output_buf[ci] + (out_row_group_index * compptr->v_samp_factor); + (*downsample->methods[ci]) (cinfo, compptr, in_ptr, out_ptr); + } +} + + +/* + * Downsample pixel values of a single component. + * One row group is processed per call. + * This version handles arbitrary integral sampling ratios, without smoothing. + * Note that this version is not actually used for customary sampling ratios. + */ + +METHODDEF(void) +int_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY output_data) +{ + int inrow, outrow, h_expand, v_expand, numpix, numpix2, h, v; + JDIMENSION outcol, outcol_h; /* outcol_h == outcol*h_expand */ + JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; + JSAMPROW inptr, outptr; + INT32 outvalue; + + h_expand = cinfo->max_h_samp_factor / compptr->h_samp_factor; + v_expand = cinfo->max_v_samp_factor / compptr->v_samp_factor; + numpix = h_expand * v_expand; + numpix2 = numpix/2; + + /* Expand input data enough to let all the output samples be generated + * by the standard loop. Special-casing padded output would be more + * efficient. + */ + expand_right_edge(input_data, cinfo->max_v_samp_factor, + cinfo->image_width, output_cols * h_expand); + + inrow = 0; + for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { + outptr = output_data[outrow]; + for (outcol = 0, outcol_h = 0; outcol < output_cols; + outcol++, outcol_h += h_expand) { + outvalue = 0; + for (v = 0; v < v_expand; v++) { + inptr = input_data[inrow+v] + outcol_h; + for (h = 0; h < h_expand; h++) { + outvalue += (INT32) GETJSAMPLE(*inptr++); + } + } + *outptr++ = (JSAMPLE) ((outvalue + numpix2) / numpix); + } + inrow += v_expand; + } +} + + +/* + * Downsample pixel values of a single component. + * This version handles the special case of a full-size component, + * without smoothing. + */ + +METHODDEF(void) +fullsize_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY output_data) +{ + /* Copy the data */ + jcopy_sample_rows(input_data, 0, output_data, 0, + cinfo->max_v_samp_factor, cinfo->image_width); + /* Edge-expand */ + expand_right_edge(output_data, cinfo->max_v_samp_factor, + cinfo->image_width, compptr->width_in_blocks * DCTSIZE); +} + + +/* + * Downsample pixel values of a single component. + * This version handles the common case of 2:1 horizontal and 1:1 vertical, + * without smoothing. + * + * A note about the "bias" calculations: when rounding fractional values to + * integer, we do not want to always round 0.5 up to the next integer. + * If we did that, we'd introduce a noticeable bias towards larger values. + * Instead, this code is arranged so that 0.5 will be rounded up or down at + * alternate pixel locations (a simple ordered dither pattern). + */ + +METHODDEF(void) +h2v1_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY output_data) +{ + int outrow; + JDIMENSION outcol; + JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; + register JSAMPROW inptr, outptr; + register int bias; + + /* Expand input data enough to let all the output samples be generated + * by the standard loop. Special-casing padded output would be more + * efficient. + */ + expand_right_edge(input_data, cinfo->max_v_samp_factor, + cinfo->image_width, output_cols * 2); + + for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { + outptr = output_data[outrow]; + inptr = input_data[outrow]; + bias = 0; /* bias = 0,1,0,1,... for successive samples */ + for (outcol = 0; outcol < output_cols; outcol++) { + *outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr) + GETJSAMPLE(inptr[1]) + + bias) >> 1); + bias ^= 1; /* 0=>1, 1=>0 */ + inptr += 2; + } + } +} + + +/* + * Downsample pixel values of a single component. + * This version handles the standard case of 2:1 horizontal and 2:1 vertical, + * without smoothing. + */ + +METHODDEF(void) +h2v2_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY output_data) +{ + int inrow, outrow; + JDIMENSION outcol; + JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; + register JSAMPROW inptr0, inptr1, outptr; + register int bias; + + /* Expand input data enough to let all the output samples be generated + * by the standard loop. Special-casing padded output would be more + * efficient. + */ + expand_right_edge(input_data, cinfo->max_v_samp_factor, + cinfo->image_width, output_cols * 2); + + inrow = 0; + for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { + outptr = output_data[outrow]; + inptr0 = input_data[inrow]; + inptr1 = input_data[inrow+1]; + bias = 1; /* bias = 1,2,1,2,... for successive samples */ + for (outcol = 0; outcol < output_cols; outcol++) { + *outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]) + + bias) >> 2); + bias ^= 3; /* 1=>2, 2=>1 */ + inptr0 += 2; inptr1 += 2; + } + inrow += 2; + } +} + + +#ifdef INPUT_SMOOTHING_SUPPORTED + +/* + * Downsample pixel values of a single component. + * This version handles the standard case of 2:1 horizontal and 2:1 vertical, + * with smoothing. One row of context is required. + */ + +METHODDEF(void) +h2v2_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY output_data) +{ + int inrow, outrow; + JDIMENSION colctr; + JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; + register JSAMPROW inptr0, inptr1, above_ptr, below_ptr, outptr; + INT32 membersum, neighsum, memberscale, neighscale; + + /* Expand input data enough to let all the output samples be generated + * by the standard loop. Special-casing padded output would be more + * efficient. + */ + expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2, + cinfo->image_width, output_cols * 2); + + /* We don't bother to form the individual "smoothed" input pixel values; + * we can directly compute the output which is the average of the four + * smoothed values. Each of the four member pixels contributes a fraction + * (1-8*SF) to its own smoothed image and a fraction SF to each of the three + * other smoothed pixels, therefore a total fraction (1-5*SF)/4 to the final + * output. The four corner-adjacent neighbor pixels contribute a fraction + * SF to just one smoothed pixel, or SF/4 to the final output; while the + * eight edge-adjacent neighbors contribute SF to each of two smoothed + * pixels, or SF/2 overall. In order to use integer arithmetic, these + * factors are scaled by 2^16 = 65536. + * Also recall that SF = smoothing_factor / 1024. + */ + + memberscale = 16384 - cinfo->smoothing_factor * 80; /* scaled (1-5*SF)/4 */ + neighscale = cinfo->smoothing_factor * 16; /* scaled SF/4 */ + + inrow = 0; + for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { + outptr = output_data[outrow]; + inptr0 = input_data[inrow]; + inptr1 = input_data[inrow+1]; + above_ptr = input_data[inrow-1]; + below_ptr = input_data[inrow+2]; + + /* Special case for first column: pretend column -1 is same as column 0 */ + membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]); + neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) + + GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + + GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[2]) + + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[2]); + neighsum += neighsum; + neighsum += GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[2]) + + GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[2]); + membersum = membersum * memberscale + neighsum * neighscale; + *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); + inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2; + + for (colctr = output_cols - 2; colctr > 0; colctr--) { + /* sum of pixels directly mapped to this output element */ + membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]); + /* sum of edge-neighbor pixels */ + neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) + + GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + + GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[2]) + + GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[2]); + /* The edge-neighbors count twice as much as corner-neighbors */ + neighsum += neighsum; + /* Add in the corner-neighbors */ + neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[2]) + + GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[2]); + /* form final output scaled up by 2^16 */ + membersum = membersum * memberscale + neighsum * neighscale; + /* round, descale and output it */ + *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); + inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2; + } + + /* Special case for last column */ + membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]); + neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) + + GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + + GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[1]) + + GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[1]); + neighsum += neighsum; + neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[1]) + + GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[1]); + membersum = membersum * memberscale + neighsum * neighscale; + *outptr = (JSAMPLE) ((membersum + 32768) >> 16); + + inrow += 2; + } +} + + +/* + * Downsample pixel values of a single component. + * This version handles the special case of a full-size component, + * with smoothing. One row of context is required. + */ + +METHODDEF(void) +fullsize_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr, + JSAMPARRAY input_data, JSAMPARRAY output_data) +{ + int outrow; + JDIMENSION colctr; + JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; + register JSAMPROW inptr, above_ptr, below_ptr, outptr; + INT32 membersum, neighsum, memberscale, neighscale; + int colsum, lastcolsum, nextcolsum; + + /* Expand input data enough to let all the output samples be generated + * by the standard loop. Special-casing padded output would be more + * efficient. + */ + expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2, + cinfo->image_width, output_cols); + + /* Each of the eight neighbor pixels contributes a fraction SF to the + * smoothed pixel, while the main pixel contributes (1-8*SF). In order + * to use integer arithmetic, these factors are multiplied by 2^16 = 65536. + * Also recall that SF = smoothing_factor / 1024. + */ + + memberscale = 65536L - cinfo->smoothing_factor * 512L; /* scaled 1-8*SF */ + neighscale = cinfo->smoothing_factor * 64; /* scaled SF */ + + for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { + outptr = output_data[outrow]; + inptr = input_data[outrow]; + above_ptr = input_data[outrow-1]; + below_ptr = input_data[outrow+1]; + + /* Special case for first column */ + colsum = GETJSAMPLE(*above_ptr++) + GETJSAMPLE(*below_ptr++) + + GETJSAMPLE(*inptr); + membersum = GETJSAMPLE(*inptr++); + nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) + + GETJSAMPLE(*inptr); + neighsum = colsum + (colsum - membersum) + nextcolsum; + membersum = membersum * memberscale + neighsum * neighscale; + *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); + lastcolsum = colsum; colsum = nextcolsum; + + for (colctr = output_cols - 2; colctr > 0; colctr--) { + membersum = GETJSAMPLE(*inptr++); + above_ptr++; below_ptr++; + nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) + + GETJSAMPLE(*inptr); + neighsum = lastcolsum + (colsum - membersum) + nextcolsum; + membersum = membersum * memberscale + neighsum * neighscale; + *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); + lastcolsum = colsum; colsum = nextcolsum; + } + + /* Special case for last column */ + membersum = GETJSAMPLE(*inptr); + neighsum = lastcolsum + (colsum - membersum) + colsum; + membersum = membersum * memberscale + neighsum * neighscale; + *outptr = (JSAMPLE) ((membersum + 32768) >> 16); + + } +} + +#endif /* INPUT_SMOOTHING_SUPPORTED */ + + +/* + * Module initialization routine for downsampling. + * Note that we must select a routine for each component. + */ + +GLOBAL(void) +jinit_downsampler (j_compress_ptr cinfo) +{ + my_downsample_ptr downsample; + int ci; + jpeg_component_info * compptr; + boolean smoothok = TRUE; + + downsample = (my_downsample_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_downsampler)); + cinfo->downsample = (struct jpeg_downsampler *) downsample; + downsample->pub.start_pass = start_pass_downsample; + downsample->pub.downsample = sep_downsample; + downsample->pub.need_context_rows = FALSE; + + if (cinfo->CCIR601_sampling) + ERREXIT(cinfo, JERR_CCIR601_NOTIMPL); + + /* Verify we can handle the sampling factors, and set up method pointers */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + if (compptr->h_samp_factor == cinfo->max_h_samp_factor && + compptr->v_samp_factor == cinfo->max_v_samp_factor) { +#ifdef INPUT_SMOOTHING_SUPPORTED + if (cinfo->smoothing_factor) { + downsample->methods[ci] = fullsize_smooth_downsample; + downsample->pub.need_context_rows = TRUE; + } else +#endif + downsample->methods[ci] = fullsize_downsample; + } else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor && + compptr->v_samp_factor == cinfo->max_v_samp_factor) { + smoothok = FALSE; + downsample->methods[ci] = h2v1_downsample; + } else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor && + compptr->v_samp_factor * 2 == cinfo->max_v_samp_factor) { +#ifdef INPUT_SMOOTHING_SUPPORTED + if (cinfo->smoothing_factor) { + downsample->methods[ci] = h2v2_smooth_downsample; + downsample->pub.need_context_rows = TRUE; + } else +#endif + downsample->methods[ci] = h2v2_downsample; + } else if ((cinfo->max_h_samp_factor % compptr->h_samp_factor) == 0 && + (cinfo->max_v_samp_factor % compptr->v_samp_factor) == 0) { + smoothok = FALSE; + downsample->methods[ci] = int_downsample; + } else + ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL); + } + +#ifdef INPUT_SMOOTHING_SUPPORTED + if (cinfo->smoothing_factor && !smoothok) + TRACEMS(cinfo, 0, JTRC_SMOOTH_NOTIMPL); +#endif +} diff --git a/jpeg/JCTRANS.C b/jpeg/JCTRANS.C new file mode 100644 index 0000000..215dc99 --- /dev/null +++ b/jpeg/JCTRANS.C @@ -0,0 +1,388 @@ +/* + * jctrans.c + * + * Copyright (C) 1995-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains library routines for transcoding compression, + * that is, writing raw DCT coefficient arrays to an output JPEG file. + * The routines in jcapimin.c will also be needed by a transcoder. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Forward declarations */ +LOCAL(void) transencode_master_selection + JPP((j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays)); +LOCAL(void) transencode_coef_controller + JPP((j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays)); + + +/* + * Compression initialization for writing raw-coefficient data. + * Before calling this, all parameters and a data destination must be set up. + * Call jpeg_finish_compress() to actually write the data. + * + * The number of passed virtual arrays must match cinfo->num_components. + * Note that the virtual arrays need not be filled or even realized at + * the time write_coefficients is called; indeed, if the virtual arrays + * were requested from this compression object's memory manager, they + * typically will be realized during this routine and filled afterwards. + */ + +GLOBAL(void) +jpeg_write_coefficients (j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays) +{ + if (cinfo->global_state != CSTATE_START) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + /* Mark all tables to be written */ + jpeg_suppress_tables(cinfo, FALSE); + /* (Re)initialize error mgr and destination modules */ + (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); + (*cinfo->dest->init_destination) (cinfo); + /* Perform master selection of active modules */ + transencode_master_selection(cinfo, coef_arrays); + /* Wait for jpeg_finish_compress() call */ + cinfo->next_scanline = 0; /* so jpeg_write_marker works */ + cinfo->global_state = CSTATE_WRCOEFS; +} + + +/* + * Initialize the compression object with default parameters, + * then copy from the source object all parameters needed for lossless + * transcoding. Parameters that can be varied without loss (such as + * scan script and Huffman optimization) are left in their default states. + */ + +GLOBAL(void) +jpeg_copy_critical_parameters (j_decompress_ptr srcinfo, + j_compress_ptr dstinfo) +{ + JQUANT_TBL ** qtblptr; + jpeg_component_info *incomp, *outcomp; + JQUANT_TBL *c_quant, *slot_quant; + int tblno, ci, coefi; + + /* Safety check to ensure start_compress not called yet. */ + if (dstinfo->global_state != CSTATE_START) + ERREXIT1(dstinfo, JERR_BAD_STATE, dstinfo->global_state); + /* Copy fundamental image dimensions */ + dstinfo->image_width = srcinfo->image_width; + dstinfo->image_height = srcinfo->image_height; + dstinfo->input_components = srcinfo->num_components; + dstinfo->in_color_space = srcinfo->jpeg_color_space; + /* Initialize all parameters to default values */ + jpeg_set_defaults(dstinfo); + /* jpeg_set_defaults may choose wrong colorspace, eg YCbCr if input is RGB. + * Fix it to get the right header markers for the image colorspace. + */ + jpeg_set_colorspace(dstinfo, srcinfo->jpeg_color_space); + dstinfo->data_precision = srcinfo->data_precision; + dstinfo->CCIR601_sampling = srcinfo->CCIR601_sampling; + /* Copy the source's quantization tables. */ + for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) { + if (srcinfo->quant_tbl_ptrs[tblno] != NULL) { + qtblptr = & dstinfo->quant_tbl_ptrs[tblno]; + if (*qtblptr == NULL) + *qtblptr = jpeg_alloc_quant_table((j_common_ptr) dstinfo); + MEMCOPY((*qtblptr)->quantval, + srcinfo->quant_tbl_ptrs[tblno]->quantval, + SIZEOF((*qtblptr)->quantval)); + (*qtblptr)->sent_table = FALSE; + } + } + /* Copy the source's per-component info. + * Note we assume jpeg_set_defaults has allocated the dest comp_info array. + */ + dstinfo->num_components = srcinfo->num_components; + if (dstinfo->num_components < 1 || dstinfo->num_components > MAX_COMPONENTS) + ERREXIT2(dstinfo, JERR_COMPONENT_COUNT, dstinfo->num_components, + MAX_COMPONENTS); + for (ci = 0, incomp = srcinfo->comp_info, outcomp = dstinfo->comp_info; + ci < dstinfo->num_components; ci++, incomp++, outcomp++) { + outcomp->component_id = incomp->component_id; + outcomp->h_samp_factor = incomp->h_samp_factor; + outcomp->v_samp_factor = incomp->v_samp_factor; + outcomp->quant_tbl_no = incomp->quant_tbl_no; + /* Make sure saved quantization table for component matches the qtable + * slot. If not, the input file re-used this qtable slot. + * IJG encoder currently cannot duplicate this. + */ + tblno = outcomp->quant_tbl_no; + if (tblno < 0 || tblno >= NUM_QUANT_TBLS || + srcinfo->quant_tbl_ptrs[tblno] == NULL) + ERREXIT1(dstinfo, JERR_NO_QUANT_TABLE, tblno); + slot_quant = srcinfo->quant_tbl_ptrs[tblno]; + c_quant = incomp->quant_table; + if (c_quant != NULL) { + for (coefi = 0; coefi < DCTSIZE2; coefi++) { + if (c_quant->quantval[coefi] != slot_quant->quantval[coefi]) + ERREXIT1(dstinfo, JERR_MISMATCHED_QUANT_TABLE, tblno); + } + } + /* Note: we do not copy the source's Huffman table assignments; + * instead we rely on jpeg_set_colorspace to have made a suitable choice. + */ + } + /* Also copy JFIF version and resolution information, if available. + * Strictly speaking this isn't "critical" info, but it's nearly + * always appropriate to copy it if available. In particular, + * if the application chooses to copy JFIF 1.02 extension markers from + * the source file, we need to copy the version to make sure we don't + * emit a file that has 1.02 extensions but a claimed version of 1.01. + * We will *not*, however, copy version info from mislabeled "2.01" files. + */ + if (srcinfo->saw_JFIF_marker) { + if (srcinfo->JFIF_major_version == 1) { + dstinfo->JFIF_major_version = srcinfo->JFIF_major_version; + dstinfo->JFIF_minor_version = srcinfo->JFIF_minor_version; + } + dstinfo->density_unit = srcinfo->density_unit; + dstinfo->X_density = srcinfo->X_density; + dstinfo->Y_density = srcinfo->Y_density; + } +} + + +/* + * Master selection of compression modules for transcoding. + * This substitutes for jcinit.c's initialization of the full compressor. + */ + +LOCAL(void) +transencode_master_selection (j_compress_ptr cinfo, + jvirt_barray_ptr * coef_arrays) +{ + /* Although we don't actually use input_components for transcoding, + * jcmaster.c's initial_setup will complain if input_components is 0. + */ + cinfo->input_components = 1; + /* Initialize master control (includes parameter checking/processing) */ + jinit_c_master_control(cinfo, TRUE /* transcode only */); + + /* Entropy encoding: either Huffman or arithmetic coding. */ + if (cinfo->arith_code) { + ERREXIT(cinfo, JERR_ARITH_NOTIMPL); + } else { + if (cinfo->progressive_mode) { +#ifdef C_PROGRESSIVE_SUPPORTED + jinit_phuff_encoder(cinfo); +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else + jinit_huff_encoder(cinfo); + } + + /* We need a special coefficient buffer controller. */ + transencode_coef_controller(cinfo, coef_arrays); + + jinit_marker_writer(cinfo); + + /* We can now tell the memory manager to allocate virtual arrays. */ + (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); + + /* Write the datastream header (SOI, JFIF) immediately. + * Frame and scan headers are postponed till later. + * This lets application insert special markers after the SOI. + */ + (*cinfo->marker->write_file_header) (cinfo); +} + + +/* + * The rest of this file is a special implementation of the coefficient + * buffer controller. This is similar to jccoefct.c, but it handles only + * output from presupplied virtual arrays. Furthermore, we generate any + * dummy padding blocks on-the-fly rather than expecting them to be present + * in the arrays. + */ + +/* Private buffer controller object */ + +typedef struct { + struct jpeg_c_coef_controller pub; /* public fields */ + + JDIMENSION iMCU_row_num; /* iMCU row # within image */ + JDIMENSION mcu_ctr; /* counts MCUs processed in current row */ + int MCU_vert_offset; /* counts MCU rows within iMCU row */ + int MCU_rows_per_iMCU_row; /* number of such rows needed */ + + /* Virtual block array for each component. */ + jvirt_barray_ptr * whole_image; + + /* Workspace for constructing dummy blocks at right/bottom edges. */ + JBLOCKROW dummy_buffer[C_MAX_BLOCKS_IN_MCU]; +} my_coef_controller; + +typedef my_coef_controller * my_coef_ptr; + + +LOCAL(void) +start_iMCU_row (j_compress_ptr cinfo) +/* Reset within-iMCU-row counters for a new row */ +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + + /* In an interleaved scan, an MCU row is the same as an iMCU row. + * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows. + * But at the bottom of the image, process only what's left. + */ + if (cinfo->comps_in_scan > 1) { + coef->MCU_rows_per_iMCU_row = 1; + } else { + if (coef->iMCU_row_num < (cinfo->total_iMCU_rows-1)) + coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor; + else + coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height; + } + + coef->mcu_ctr = 0; + coef->MCU_vert_offset = 0; +} + + +/* + * Initialize for a processing pass. + */ + +METHODDEF(void) +start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode) +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + + if (pass_mode != JBUF_CRANK_DEST) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + + coef->iMCU_row_num = 0; + start_iMCU_row(cinfo); +} + + +/* + * Process some data. + * We process the equivalent of one fully interleaved MCU row ("iMCU" row) + * per call, ie, v_samp_factor block rows for each component in the scan. + * The data is obtained from the virtual arrays and fed to the entropy coder. + * Returns TRUE if the iMCU row is completed, FALSE if suspended. + * + * NB: input_buf is ignored; it is likely to be a NULL pointer. + */ + +METHODDEF(boolean) +compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf) +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + JDIMENSION MCU_col_num; /* index of current MCU within row */ + JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1; + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + int blkn, ci, xindex, yindex, yoffset, blockcnt; + JDIMENSION start_col; + JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN]; + JBLOCKROW MCU_buffer[C_MAX_BLOCKS_IN_MCU]; + JBLOCKROW buffer_ptr; + jpeg_component_info *compptr; + + /* Align the virtual buffers for the components used in this scan. */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + buffer[ci] = (*cinfo->mem->access_virt_barray) + ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index], + coef->iMCU_row_num * compptr->v_samp_factor, + (JDIMENSION) compptr->v_samp_factor, FALSE); + } + + /* Loop to process one whole iMCU row */ + for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; + yoffset++) { + for (MCU_col_num = coef->mcu_ctr; MCU_col_num < cinfo->MCUs_per_row; + MCU_col_num++) { + /* Construct list of pointers to DCT blocks belonging to this MCU */ + blkn = 0; /* index of current DCT block within MCU */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + start_col = MCU_col_num * compptr->MCU_width; + blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width + : compptr->last_col_width; + for (yindex = 0; yindex < compptr->MCU_height; yindex++) { + if (coef->iMCU_row_num < last_iMCU_row || + yindex+yoffset < compptr->last_row_height) { + /* Fill in pointers to real blocks in this row */ + buffer_ptr = buffer[ci][yindex+yoffset] + start_col; + for (xindex = 0; xindex < blockcnt; xindex++) + MCU_buffer[blkn++] = buffer_ptr++; + } else { + /* At bottom of image, need a whole row of dummy blocks */ + xindex = 0; + } + /* Fill in any dummy blocks needed in this row. + * Dummy blocks are filled in the same way as in jccoefct.c: + * all zeroes in the AC entries, DC entries equal to previous + * block's DC value. The init routine has already zeroed the + * AC entries, so we need only set the DC entries correctly. + */ + for (; xindex < compptr->MCU_width; xindex++) { + MCU_buffer[blkn] = coef->dummy_buffer[blkn]; + MCU_buffer[blkn][0][0] = MCU_buffer[blkn-1][0][0]; + blkn++; + } + } + } + /* Try to write the MCU. */ + if (! (*cinfo->entropy->encode_mcu) (cinfo, MCU_buffer)) { + /* Suspension forced; update state counters and exit */ + coef->MCU_vert_offset = yoffset; + coef->mcu_ctr = MCU_col_num; + return FALSE; + } + } + /* Completed an MCU row, but perhaps not an iMCU row */ + coef->mcu_ctr = 0; + } + /* Completed the iMCU row, advance counters for next one */ + coef->iMCU_row_num++; + start_iMCU_row(cinfo); + return TRUE; +} + + +/* + * Initialize coefficient buffer controller. + * + * Each passed coefficient array must be the right size for that + * coefficient: width_in_blocks wide and height_in_blocks high, + * with unitheight at least v_samp_factor. + */ + +LOCAL(void) +transencode_coef_controller (j_compress_ptr cinfo, + jvirt_barray_ptr * coef_arrays) +{ + my_coef_ptr coef; + JBLOCKROW buffer; + int i; + + coef = (my_coef_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_coef_controller)); + cinfo->coef = (struct jpeg_c_coef_controller *) coef; + coef->pub.start_pass = start_pass_coef; + coef->pub.compress_data = compress_output; + + /* Save pointer to virtual arrays */ + coef->whole_image = coef_arrays; + + /* Allocate and pre-zero space for dummy DCT blocks. */ + buffer = (JBLOCKROW) + (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, + C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); + jzero_far((void FAR *) buffer, C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); + for (i = 0; i < C_MAX_BLOCKS_IN_MCU; i++) { + coef->dummy_buffer[i] = buffer + i; + } +} diff --git a/jpeg/JDAPIMIN.C b/jpeg/JDAPIMIN.C new file mode 100644 index 0000000..504f55b --- /dev/null +++ b/jpeg/JDAPIMIN.C @@ -0,0 +1,395 @@ +/* + * jdapimin.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains application interface code for the decompression half + * of the JPEG library. These are the "minimum" API routines that may be + * needed in either the normal full-decompression case or the + * transcoding-only case. + * + * Most of the routines intended to be called directly by an application + * are in this file or in jdapistd.c. But also see jcomapi.c for routines + * shared by compression and decompression, and jdtrans.c for the transcoding + * case. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* + * Initialization of a JPEG decompression object. + * The error manager must already be set up (in case memory manager fails). + */ + +GLOBAL(void) +jpeg_CreateDecompress (j_decompress_ptr cinfo, int version, size_t structsize) +{ + int i; + + /* Guard against version mismatches between library and caller. */ + cinfo->mem = NULL; /* so jpeg_destroy knows mem mgr not called */ + if (version != JPEG_LIB_VERSION) + ERREXIT2(cinfo, JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version); + if (structsize != SIZEOF(struct jpeg_decompress_struct)) + ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE, + (int) SIZEOF(struct jpeg_decompress_struct), (int) structsize); + + /* For debugging purposes, we zero the whole master structure. + * But the application has already set the err pointer, and may have set + * client_data, so we have to save and restore those fields. + * Note: if application hasn't set client_data, tools like Purify may + * complain here. + */ + { + struct jpeg_error_mgr * err = cinfo->err; + void * client_data = cinfo->client_data; /* ignore Purify complaint here */ + MEMZERO(cinfo, SIZEOF(struct jpeg_decompress_struct)); + cinfo->err = err; + cinfo->client_data = client_data; + } + cinfo->is_decompressor = TRUE; + + /* Initialize a memory manager instance for this object */ + jinit_memory_mgr((j_common_ptr) cinfo); + + /* Zero out pointers to permanent structures. */ + cinfo->progress = NULL; + cinfo->src = NULL; + + for (i = 0; i < NUM_QUANT_TBLS; i++) + cinfo->quant_tbl_ptrs[i] = NULL; + + for (i = 0; i < NUM_HUFF_TBLS; i++) { + cinfo->dc_huff_tbl_ptrs[i] = NULL; + cinfo->ac_huff_tbl_ptrs[i] = NULL; + } + + /* Initialize marker processor so application can override methods + * for COM, APPn markers before calling jpeg_read_header. + */ + cinfo->marker_list = NULL; + jinit_marker_reader(cinfo); + + /* And initialize the overall input controller. */ + jinit_input_controller(cinfo); + + /* OK, I'm ready */ + cinfo->global_state = DSTATE_START; +} + + +/* + * Destruction of a JPEG decompression object + */ + +GLOBAL(void) +jpeg_destroy_decompress (j_decompress_ptr cinfo) +{ + jpeg_destroy((j_common_ptr) cinfo); /* use common routine */ +} + + +/* + * Abort processing of a JPEG decompression operation, + * but don't destroy the object itself. + */ + +GLOBAL(void) +jpeg_abort_decompress (j_decompress_ptr cinfo) +{ + jpeg_abort((j_common_ptr) cinfo); /* use common routine */ +} + + +/* + * Set default decompression parameters. + */ + +LOCAL(void) +default_decompress_parms (j_decompress_ptr cinfo) +{ + /* Guess the input colorspace, and set output colorspace accordingly. */ + /* (Wish JPEG committee had provided a real way to specify this...) */ + /* Note application may override our guesses. */ + switch (cinfo->num_components) { + case 1: + cinfo->jpeg_color_space = JCS_GRAYSCALE; + cinfo->out_color_space = JCS_GRAYSCALE; + break; + + case 3: + if (cinfo->saw_JFIF_marker) { + cinfo->jpeg_color_space = JCS_YCbCr; /* JFIF implies YCbCr */ + } else if (cinfo->saw_Adobe_marker) { + switch (cinfo->Adobe_transform) { + case 0: + cinfo->jpeg_color_space = JCS_RGB; + break; + case 1: + cinfo->jpeg_color_space = JCS_YCbCr; + break; + default: + WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform); + cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */ + break; + } + } else { + /* Saw no special markers, try to guess from the component IDs */ + int cid0 = cinfo->comp_info[0].component_id; + int cid1 = cinfo->comp_info[1].component_id; + int cid2 = cinfo->comp_info[2].component_id; + + if (cid0 == 1 && cid1 == 2 && cid2 == 3) + cinfo->jpeg_color_space = JCS_YCbCr; /* assume JFIF w/out marker */ + else if (cid0 == 82 && cid1 == 71 && cid2 == 66) + cinfo->jpeg_color_space = JCS_RGB; /* ASCII 'R', 'G', 'B' */ + else { + TRACEMS3(cinfo, 1, JTRC_UNKNOWN_IDS, cid0, cid1, cid2); + cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */ + } + } + /* Always guess RGB is proper output colorspace. */ + cinfo->out_color_space = JCS_RGB; + break; + + case 4: + if (cinfo->saw_Adobe_marker) { + switch (cinfo->Adobe_transform) { + case 0: + cinfo->jpeg_color_space = JCS_CMYK; + break; + case 2: + cinfo->jpeg_color_space = JCS_YCCK; + break; + default: + WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform); + cinfo->jpeg_color_space = JCS_YCCK; /* assume it's YCCK */ + break; + } + } else { + /* No special markers, assume straight CMYK. */ + cinfo->jpeg_color_space = JCS_CMYK; + } + cinfo->out_color_space = JCS_CMYK; + break; + + default: + cinfo->jpeg_color_space = JCS_UNKNOWN; + cinfo->out_color_space = JCS_UNKNOWN; + break; + } + + /* Set defaults for other decompression parameters. */ + cinfo->scale_num = 1; /* 1:1 scaling */ + cinfo->scale_denom = 1; + cinfo->output_gamma = 1.0; + cinfo->buffered_image = FALSE; + cinfo->raw_data_out = FALSE; + cinfo->dct_method = JDCT_DEFAULT; + cinfo->do_fancy_upsampling = TRUE; + cinfo->do_block_smoothing = TRUE; + cinfo->quantize_colors = FALSE; + /* We set these in case application only sets quantize_colors. */ + cinfo->dither_mode = JDITHER_FS; +#ifdef QUANT_2PASS_SUPPORTED + cinfo->two_pass_quantize = TRUE; +#else + cinfo->two_pass_quantize = FALSE; +#endif + cinfo->desired_number_of_colors = 256; + cinfo->colormap = NULL; + /* Initialize for no mode change in buffered-image mode. */ + cinfo->enable_1pass_quant = FALSE; + cinfo->enable_external_quant = FALSE; + cinfo->enable_2pass_quant = FALSE; +} + + +/* + * Decompression startup: read start of JPEG datastream to see what's there. + * Need only initialize JPEG object and supply a data source before calling. + * + * This routine will read as far as the first SOS marker (ie, actual start of + * compressed data), and will save all tables and parameters in the JPEG + * object. It will also initialize the decompression parameters to default + * values, and finally return JPEG_HEADER_OK. On return, the application may + * adjust the decompression parameters and then call jpeg_start_decompress. + * (Or, if the application only wanted to determine the image parameters, + * the data need not be decompressed. In that case, call jpeg_abort or + * jpeg_destroy to release any temporary space.) + * If an abbreviated (tables only) datastream is presented, the routine will + * return JPEG_HEADER_TABLES_ONLY upon reaching EOI. The application may then + * re-use the JPEG object to read the abbreviated image datastream(s). + * It is unnecessary (but OK) to call jpeg_abort in this case. + * The JPEG_SUSPENDED return code only occurs if the data source module + * requests suspension of the decompressor. In this case the application + * should load more source data and then re-call jpeg_read_header to resume + * processing. + * If a non-suspending data source is used and require_image is TRUE, then the + * return code need not be inspected since only JPEG_HEADER_OK is possible. + * + * This routine is now just a front end to jpeg_consume_input, with some + * extra error checking. + */ + +GLOBAL(int) +jpeg_read_header (j_decompress_ptr cinfo, boolean require_image) +{ + int retcode; + + if (cinfo->global_state != DSTATE_START && + cinfo->global_state != DSTATE_INHEADER) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + retcode = jpeg_consume_input(cinfo); + + switch (retcode) { + case JPEG_REACHED_SOS: + retcode = JPEG_HEADER_OK; + break; + case JPEG_REACHED_EOI: + if (require_image) /* Complain if application wanted an image */ + ERREXIT(cinfo, JERR_NO_IMAGE); + /* Reset to start state; it would be safer to require the application to + * call jpeg_abort, but we can't change it now for compatibility reasons. + * A side effect is to free any temporary memory (there shouldn't be any). + */ + jpeg_abort((j_common_ptr) cinfo); /* sets state = DSTATE_START */ + retcode = JPEG_HEADER_TABLES_ONLY; + break; + case JPEG_SUSPENDED: + /* no work */ + break; + } + + return retcode; +} + + +/* + * Consume data in advance of what the decompressor requires. + * This can be called at any time once the decompressor object has + * been created and a data source has been set up. + * + * This routine is essentially a state machine that handles a couple + * of critical state-transition actions, namely initial setup and + * transition from header scanning to ready-for-start_decompress. + * All the actual input is done via the input controller's consume_input + * method. + */ + +GLOBAL(int) +jpeg_consume_input (j_decompress_ptr cinfo) +{ + int retcode = JPEG_SUSPENDED; + + /* NB: every possible DSTATE value should be listed in this switch */ + switch (cinfo->global_state) { + case DSTATE_START: + /* Start-of-datastream actions: reset appropriate modules */ + (*cinfo->inputctl->reset_input_controller) (cinfo); + /* Initialize application's data source module */ + (*cinfo->src->init_source) (cinfo); + cinfo->global_state = DSTATE_INHEADER; + /*FALLTHROUGH*/ + case DSTATE_INHEADER: + retcode = (*cinfo->inputctl->consume_input) (cinfo); + if (retcode == JPEG_REACHED_SOS) { /* Found SOS, prepare to decompress */ + /* Set up default parameters based on header data */ + default_decompress_parms(cinfo); + /* Set global state: ready for start_decompress */ + cinfo->global_state = DSTATE_READY; + } + break; + case DSTATE_READY: + /* Can't advance past first SOS until start_decompress is called */ + retcode = JPEG_REACHED_SOS; + break; + case DSTATE_PRELOAD: + case DSTATE_PRESCAN: + case DSTATE_SCANNING: + case DSTATE_RAW_OK: + case DSTATE_BUFIMAGE: + case DSTATE_BUFPOST: + case DSTATE_STOPPING: + retcode = (*cinfo->inputctl->consume_input) (cinfo); + break; + default: + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + } + return retcode; +} + + +/* + * Have we finished reading the input file? + */ + +GLOBAL(boolean) +jpeg_input_complete (j_decompress_ptr cinfo) +{ + /* Check for valid jpeg object */ + if (cinfo->global_state < DSTATE_START || + cinfo->global_state > DSTATE_STOPPING) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + return cinfo->inputctl->eoi_reached; +} + + +/* + * Is there more than one scan? + */ + +GLOBAL(boolean) +jpeg_has_multiple_scans (j_decompress_ptr cinfo) +{ + /* Only valid after jpeg_read_header completes */ + if (cinfo->global_state < DSTATE_READY || + cinfo->global_state > DSTATE_STOPPING) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + return cinfo->inputctl->has_multiple_scans; +} + + +/* + * Finish JPEG decompression. + * + * This will normally just verify the file trailer and release temp storage. + * + * Returns FALSE if suspended. The return value need be inspected only if + * a suspending data source is used. + */ + +GLOBAL(boolean) +jpeg_finish_decompress (j_decompress_ptr cinfo) +{ + if ((cinfo->global_state == DSTATE_SCANNING || + cinfo->global_state == DSTATE_RAW_OK) && ! cinfo->buffered_image) { + /* Terminate final pass of non-buffered mode */ + if (cinfo->output_scanline < cinfo->output_height) + ERREXIT(cinfo, JERR_TOO_LITTLE_DATA); + (*cinfo->master->finish_output_pass) (cinfo); + cinfo->global_state = DSTATE_STOPPING; + } else if (cinfo->global_state == DSTATE_BUFIMAGE) { + /* Finishing after a buffered-image operation */ + cinfo->global_state = DSTATE_STOPPING; + } else if (cinfo->global_state != DSTATE_STOPPING) { + /* STOPPING = repeat call after a suspension, anything else is error */ + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + } + /* Read until EOI */ + while (! cinfo->inputctl->eoi_reached) { + if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED) + return FALSE; /* Suspend, come back later */ + } + /* Do final cleanup */ + (*cinfo->src->term_source) (cinfo); + /* We can use jpeg_abort to release memory and reset global_state */ + jpeg_abort((j_common_ptr) cinfo); + return TRUE; +} diff --git a/jpeg/JDAPISTD.C b/jpeg/JDAPISTD.C new file mode 100644 index 0000000..9c63ca2 --- /dev/null +++ b/jpeg/JDAPISTD.C @@ -0,0 +1,275 @@ +/* + * jdapistd.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains application interface code for the decompression half + * of the JPEG library. These are the "standard" API routines that are + * used in the normal full-decompression case. They are not used by a + * transcoding-only application. Note that if an application links in + * jpeg_start_decompress, it will end up linking in the entire decompressor. + * We thus must separate this file from jdapimin.c to avoid linking the + * whole decompression library into a transcoder. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Forward declarations */ +LOCAL(boolean) output_pass_setup JPP((j_decompress_ptr cinfo)); + + +/* + * Decompression initialization. + * jpeg_read_header must be completed before calling this. + * + * If a multipass operating mode was selected, this will do all but the + * last pass, and thus may take a great deal of time. + * + * Returns FALSE if suspended. The return value need be inspected only if + * a suspending data source is used. + */ + +GLOBAL(boolean) +jpeg_start_decompress (j_decompress_ptr cinfo) +{ + if (cinfo->global_state == DSTATE_READY) { + /* First call: initialize master control, select active modules */ + jinit_master_decompress(cinfo); + if (cinfo->buffered_image) { + /* No more work here; expecting jpeg_start_output next */ + cinfo->global_state = DSTATE_BUFIMAGE; + return TRUE; + } + cinfo->global_state = DSTATE_PRELOAD; + } + if (cinfo->global_state == DSTATE_PRELOAD) { + /* If file has multiple scans, absorb them all into the coef buffer */ + if (cinfo->inputctl->has_multiple_scans) { +#ifdef D_MULTISCAN_FILES_SUPPORTED + for (;;) { + int retcode; + /* Call progress monitor hook if present */ + if (cinfo->progress != NULL) + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + /* Absorb some more input */ + retcode = (*cinfo->inputctl->consume_input) (cinfo); + if (retcode == JPEG_SUSPENDED) + return FALSE; + if (retcode == JPEG_REACHED_EOI) + break; + /* Advance progress counter if appropriate */ + if (cinfo->progress != NULL && + (retcode == JPEG_ROW_COMPLETED || retcode == JPEG_REACHED_SOS)) { + if (++cinfo->progress->pass_counter >= cinfo->progress->pass_limit) { + /* jdmaster underestimated number of scans; ratchet up one scan */ + cinfo->progress->pass_limit += (long) cinfo->total_iMCU_rows; + } + } + } +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif /* D_MULTISCAN_FILES_SUPPORTED */ + } + cinfo->output_scan_number = cinfo->input_scan_number; + } else if (cinfo->global_state != DSTATE_PRESCAN) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + /* Perform any dummy output passes, and set up for the final pass */ + return output_pass_setup(cinfo); +} + + +/* + * Set up for an output pass, and perform any dummy pass(es) needed. + * Common subroutine for jpeg_start_decompress and jpeg_start_output. + * Entry: global_state = DSTATE_PRESCAN only if previously suspended. + * Exit: If done, returns TRUE and sets global_state for proper output mode. + * If suspended, returns FALSE and sets global_state = DSTATE_PRESCAN. + */ + +LOCAL(boolean) +output_pass_setup (j_decompress_ptr cinfo) +{ + if (cinfo->global_state != DSTATE_PRESCAN) { + /* First call: do pass setup */ + (*cinfo->master->prepare_for_output_pass) (cinfo); + cinfo->output_scanline = 0; + cinfo->global_state = DSTATE_PRESCAN; + } + /* Loop over any required dummy passes */ + while (cinfo->master->is_dummy_pass) { +#ifdef QUANT_2PASS_SUPPORTED + /* Crank through the dummy pass */ + while (cinfo->output_scanline < cinfo->output_height) { + JDIMENSION last_scanline; + /* Call progress monitor hook if present */ + if (cinfo->progress != NULL) { + cinfo->progress->pass_counter = (long) cinfo->output_scanline; + cinfo->progress->pass_limit = (long) cinfo->output_height; + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + } + /* Process some data */ + last_scanline = cinfo->output_scanline; + (*cinfo->main->process_data) (cinfo, (JSAMPARRAY) NULL, + &cinfo->output_scanline, (JDIMENSION) 0); + if (cinfo->output_scanline == last_scanline) + return FALSE; /* No progress made, must suspend */ + } + /* Finish up dummy pass, and set up for another one */ + (*cinfo->master->finish_output_pass) (cinfo); + (*cinfo->master->prepare_for_output_pass) (cinfo); + cinfo->output_scanline = 0; +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif /* QUANT_2PASS_SUPPORTED */ + } + /* Ready for application to drive output pass through + * jpeg_read_scanlines or jpeg_read_raw_data. + */ + cinfo->global_state = cinfo->raw_data_out ? DSTATE_RAW_OK : DSTATE_SCANNING; + return TRUE; +} + + +/* + * Read some scanlines of data from the JPEG decompressor. + * + * The return value will be the number of lines actually read. + * This may be less than the number requested in several cases, + * including bottom of image, data source suspension, and operating + * modes that emit multiple scanlines at a time. + * + * Note: we warn about excess calls to jpeg_read_scanlines() since + * this likely signals an application programmer error. However, + * an oversize buffer (max_lines > scanlines remaining) is not an error. + */ + +GLOBAL(JDIMENSION) +jpeg_read_scanlines (j_decompress_ptr cinfo, JSAMPARRAY scanlines, + JDIMENSION max_lines) +{ + JDIMENSION row_ctr; + + if (cinfo->global_state != DSTATE_SCANNING) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + if (cinfo->output_scanline >= cinfo->output_height) { + WARNMS(cinfo, JWRN_TOO_MUCH_DATA); + return 0; + } + + /* Call progress monitor hook if present */ + if (cinfo->progress != NULL) { + cinfo->progress->pass_counter = (long) cinfo->output_scanline; + cinfo->progress->pass_limit = (long) cinfo->output_height; + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + } + + /* Process some data */ + row_ctr = 0; + (*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, max_lines); + cinfo->output_scanline += row_ctr; + return row_ctr; +} + + +/* + * Alternate entry point to read raw data. + * Processes exactly one iMCU row per call, unless suspended. + */ + +GLOBAL(JDIMENSION) +jpeg_read_raw_data (j_decompress_ptr cinfo, JSAMPIMAGE data, + JDIMENSION max_lines) +{ + JDIMENSION lines_per_iMCU_row; + + if (cinfo->global_state != DSTATE_RAW_OK) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + if (cinfo->output_scanline >= cinfo->output_height) { + WARNMS(cinfo, JWRN_TOO_MUCH_DATA); + return 0; + } + + /* Call progress monitor hook if present */ + if (cinfo->progress != NULL) { + cinfo->progress->pass_counter = (long) cinfo->output_scanline; + cinfo->progress->pass_limit = (long) cinfo->output_height; + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + } + + /* Verify that at least one iMCU row can be returned. */ + lines_per_iMCU_row = cinfo->max_v_samp_factor * cinfo->min_DCT_scaled_size; + if (max_lines < lines_per_iMCU_row) + ERREXIT(cinfo, JERR_BUFFER_SIZE); + + /* Decompress directly into user's buffer. */ + if (! (*cinfo->coef->decompress_data) (cinfo, data)) + return 0; /* suspension forced, can do nothing more */ + + /* OK, we processed one iMCU row. */ + cinfo->output_scanline += lines_per_iMCU_row; + return lines_per_iMCU_row; +} + + +/* Additional entry points for buffered-image mode. */ + +#ifdef D_MULTISCAN_FILES_SUPPORTED + +/* + * Initialize for an output pass in buffered-image mode. + */ + +GLOBAL(boolean) +jpeg_start_output (j_decompress_ptr cinfo, int scan_number) +{ + if (cinfo->global_state != DSTATE_BUFIMAGE && + cinfo->global_state != DSTATE_PRESCAN) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + /* Limit scan number to valid range */ + if (scan_number <= 0) + scan_number = 1; + if (cinfo->inputctl->eoi_reached && + scan_number > cinfo->input_scan_number) + scan_number = cinfo->input_scan_number; + cinfo->output_scan_number = scan_number; + /* Perform any dummy output passes, and set up for the real pass */ + return output_pass_setup(cinfo); +} + + +/* + * Finish up after an output pass in buffered-image mode. + * + * Returns FALSE if suspended. The return value need be inspected only if + * a suspending data source is used. + */ + +GLOBAL(boolean) +jpeg_finish_output (j_decompress_ptr cinfo) +{ + if ((cinfo->global_state == DSTATE_SCANNING || + cinfo->global_state == DSTATE_RAW_OK) && cinfo->buffered_image) { + /* Terminate this pass. */ + /* We do not require the whole pass to have been completed. */ + (*cinfo->master->finish_output_pass) (cinfo); + cinfo->global_state = DSTATE_BUFPOST; + } else if (cinfo->global_state != DSTATE_BUFPOST) { + /* BUFPOST = repeat call after a suspension, anything else is error */ + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + } + /* Read markers looking for SOS or EOI */ + while (cinfo->input_scan_number <= cinfo->output_scan_number && + ! cinfo->inputctl->eoi_reached) { + if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED) + return FALSE; /* Suspend, come back later */ + } + cinfo->global_state = DSTATE_BUFIMAGE; + return TRUE; +} + +#endif /* D_MULTISCAN_FILES_SUPPORTED */ diff --git a/jpeg/JDATADST.C b/jpeg/JDATADST.C new file mode 100644 index 0000000..73e730d --- /dev/null +++ b/jpeg/JDATADST.C @@ -0,0 +1,151 @@ +/* + * jdatadst.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains compression data destination routines for the case of + * emitting JPEG data to a file (or any stdio stream). While these routines + * are sufficient for most applications, some will want to use a different + * destination manager. + * IMPORTANT: we assume that fwrite() will correctly transcribe an array of + * JOCTETs into 8-bit-wide elements on external storage. If char is wider + * than 8 bits on your machine, you may need to do some tweaking. + */ + +/* this is not a core library module, so it doesn't define JPEG_INTERNALS */ +#include "jinclude.h" +#include "jpeglib.h" +#include "jerror.h" + + +/* Expanded data destination object for stdio output */ + +typedef struct { + struct jpeg_destination_mgr pub; /* public fields */ + + FILE * outfile; /* target stream */ + JOCTET * buffer; /* start of buffer */ +} my_destination_mgr; + +typedef my_destination_mgr * my_dest_ptr; + +#define OUTPUT_BUF_SIZE 4096 /* choose an efficiently fwrite'able size */ + + +/* + * Initialize destination --- called by jpeg_start_compress + * before any data is actually written. + */ + +METHODDEF(void) +init_destination (j_compress_ptr cinfo) +{ + my_dest_ptr dest = (my_dest_ptr) cinfo->dest; + + /* Allocate the output buffer --- it will be released when done with image */ + dest->buffer = (JOCTET *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + OUTPUT_BUF_SIZE * SIZEOF(JOCTET)); + + dest->pub.next_output_byte = dest->buffer; + dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; +} + + +/* + * Empty the output buffer --- called whenever buffer fills up. + * + * In typical applications, this should write the entire output buffer + * (ignoring the current state of next_output_byte & free_in_buffer), + * reset the pointer & count to the start of the buffer, and return TRUE + * indicating that the buffer has been dumped. + * + * In applications that need to be able to suspend compression due to output + * overrun, a FALSE return indicates that the buffer cannot be emptied now. + * In this situation, the compressor will return to its caller (possibly with + * an indication that it has not accepted all the supplied scanlines). The + * application should resume compression after it has made more room in the + * output buffer. Note that there are substantial restrictions on the use of + * suspension --- see the documentation. + * + * When suspending, the compressor will back up to a convenient restart point + * (typically the start of the current MCU). next_output_byte & free_in_buffer + * indicate where the restart point will be if the current call returns FALSE. + * Data beyond this point will be regenerated after resumption, so do not + * write it out when emptying the buffer externally. + */ + +METHODDEF(boolean) +empty_output_buffer (j_compress_ptr cinfo) +{ + my_dest_ptr dest = (my_dest_ptr) cinfo->dest; + + if (JFWRITE(dest->outfile, dest->buffer, OUTPUT_BUF_SIZE) != + (size_t) OUTPUT_BUF_SIZE) + ERREXIT(cinfo, JERR_FILE_WRITE); + + dest->pub.next_output_byte = dest->buffer; + dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; + + return TRUE; +} + + +/* + * Terminate destination --- called by jpeg_finish_compress + * after all data has been written. Usually needs to flush buffer. + * + * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding + * application must deal with any cleanup that should happen even + * for error exit. + */ + +METHODDEF(void) +term_destination (j_compress_ptr cinfo) +{ + my_dest_ptr dest = (my_dest_ptr) cinfo->dest; + size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer; + + /* Write any data remaining in the buffer */ + if (datacount > 0) { + if (JFWRITE(dest->outfile, dest->buffer, datacount) != datacount) + ERREXIT(cinfo, JERR_FILE_WRITE); + } + fflush(dest->outfile); + /* Make sure we wrote the output file OK */ + if (ferror(dest->outfile)) + ERREXIT(cinfo, JERR_FILE_WRITE); +} + + +/* + * Prepare for output to a stdio stream. + * The caller must have already opened the stream, and is responsible + * for closing it after finishing compression. + */ + +GLOBAL(void) +jpeg_stdio_dest (j_compress_ptr cinfo, FILE * outfile) +{ + my_dest_ptr dest; + + /* The destination object is made permanent so that multiple JPEG images + * can be written to the same file without re-executing jpeg_stdio_dest. + * This makes it dangerous to use this manager and a different destination + * manager serially with the same JPEG object, because their private object + * sizes may be different. Caveat programmer. + */ + if (cinfo->dest == NULL) { /* first time for this JPEG object? */ + cinfo->dest = (struct jpeg_destination_mgr *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + SIZEOF(my_destination_mgr)); + } + + dest = (my_dest_ptr) cinfo->dest; + dest->pub.init_destination = init_destination; + dest->pub.empty_output_buffer = empty_output_buffer; + dest->pub.term_destination = term_destination; + dest->outfile = outfile; +} diff --git a/jpeg/JDATASRC.C b/jpeg/JDATASRC.C new file mode 100644 index 0000000..4b90a76 --- /dev/null +++ b/jpeg/JDATASRC.C @@ -0,0 +1,212 @@ +/* + * jdatasrc.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains decompression data source routines for the case of + * reading JPEG data from a file (or any stdio stream). While these routines + * are sufficient for most applications, some will want to use a different + * source manager. + * IMPORTANT: we assume that fread() will correctly transcribe an array of + * JOCTETs from 8-bit-wide elements on external storage. If char is wider + * than 8 bits on your machine, you may need to do some tweaking. + */ + +/* this is not a core library module, so it doesn't define JPEG_INTERNALS */ +#include "jinclude.h" +#include "jpeglib.h" +#include "jerror.h" + + +/* Expanded data source object for stdio input */ + +typedef struct { + struct jpeg_source_mgr pub; /* public fields */ + + FILE * infile; /* source stream */ + JOCTET * buffer; /* start of buffer */ + boolean start_of_file; /* have we gotten any data yet? */ +} my_source_mgr; + +typedef my_source_mgr * my_src_ptr; + +#define INPUT_BUF_SIZE 4096 /* choose an efficiently fread'able size */ + + +/* + * Initialize source --- called by jpeg_read_header + * before any data is actually read. + */ + +METHODDEF(void) +init_source (j_decompress_ptr cinfo) +{ + my_src_ptr src = (my_src_ptr) cinfo->src; + + /* We reset the empty-input-file flag for each image, + * but we don't clear the input buffer. + * This is correct behavior for reading a series of images from one source. + */ + src->start_of_file = TRUE; +} + + +/* + * Fill the input buffer --- called whenever buffer is emptied. + * + * In typical applications, this should read fresh data into the buffer + * (ignoring the current state of next_input_byte & bytes_in_buffer), + * reset the pointer & count to the start of the buffer, and return TRUE + * indicating that the buffer has been reloaded. It is not necessary to + * fill the buffer entirely, only to obtain at least one more byte. + * + * There is no such thing as an EOF return. If the end of the file has been + * reached, the routine has a choice of ERREXIT() or inserting fake data into + * the buffer. In most cases, generating a warning message and inserting a + * fake EOI marker is the best course of action --- this will allow the + * decompressor to output however much of the image is there. However, + * the resulting error message is misleading if the real problem is an empty + * input file, so we handle that case specially. + * + * In applications that need to be able to suspend compression due to input + * not being available yet, a FALSE return indicates that no more data can be + * obtained right now, but more may be forthcoming later. In this situation, + * the decompressor will return to its caller (with an indication of the + * number of scanlines it has read, if any). The application should resume + * decompression after it has loaded more data into the input buffer. Note + * that there are substantial restrictions on the use of suspension --- see + * the documentation. + * + * When suspending, the decompressor will back up to a convenient restart point + * (typically the start of the current MCU). next_input_byte & bytes_in_buffer + * indicate where the restart point will be if the current call returns FALSE. + * Data beyond this point must be rescanned after resumption, so move it to + * the front of the buffer rather than discarding it. + */ + +METHODDEF(boolean) +fill_input_buffer (j_decompress_ptr cinfo) +{ + my_src_ptr src = (my_src_ptr) cinfo->src; + size_t nbytes; + + nbytes = JFREAD(src->infile, src->buffer, INPUT_BUF_SIZE); + + if (nbytes <= 0) { + if (src->start_of_file) /* Treat empty input file as fatal error */ + ERREXIT(cinfo, JERR_INPUT_EMPTY); + WARNMS(cinfo, JWRN_JPEG_EOF); + /* Insert a fake EOI marker */ + src->buffer[0] = (JOCTET) 0xFF; + src->buffer[1] = (JOCTET) JPEG_EOI; + nbytes = 2; + } + + src->pub.next_input_byte = src->buffer; + src->pub.bytes_in_buffer = nbytes; + src->start_of_file = FALSE; + + return TRUE; +} + + +/* + * Skip data --- used to skip over a potentially large amount of + * uninteresting data (such as an APPn marker). + * + * Writers of suspendable-input applications must note that skip_input_data + * is not granted the right to give a suspension return. If the skip extends + * beyond the data currently in the buffer, the buffer can be marked empty so + * that the next read will cause a fill_input_buffer call that can suspend. + * Arranging for additional bytes to be discarded before reloading the input + * buffer is the application writer's problem. + */ + +METHODDEF(void) +skip_input_data (j_decompress_ptr cinfo, long num_bytes) +{ + my_src_ptr src = (my_src_ptr) cinfo->src; + + /* Just a dumb implementation for now. Could use fseek() except + * it doesn't work on pipes. Not clear that being smart is worth + * any trouble anyway --- large skips are infrequent. + */ + if (num_bytes > 0) { + while (num_bytes > (long) src->pub.bytes_in_buffer) { + num_bytes -= (long) src->pub.bytes_in_buffer; + (void) fill_input_buffer(cinfo); + /* note we assume that fill_input_buffer will never return FALSE, + * so suspension need not be handled. + */ + } + src->pub.next_input_byte += (size_t) num_bytes; + src->pub.bytes_in_buffer -= (size_t) num_bytes; + } +} + + +/* + * An additional method that can be provided by data source modules is the + * resync_to_restart method for error recovery in the presence of RST markers. + * For the moment, this source module just uses the default resync method + * provided by the JPEG library. That method assumes that no backtracking + * is possible. + */ + + +/* + * Terminate source --- called by jpeg_finish_decompress + * after all data has been read. Often a no-op. + * + * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding + * application must deal with any cleanup that should happen even + * for error exit. + */ + +METHODDEF(void) +term_source (j_decompress_ptr cinfo) +{ + /* no work necessary here */ +} + + +/* + * Prepare for input from a stdio stream. + * The caller must have already opened the stream, and is responsible + * for closing it after finishing decompression. + */ + +GLOBAL(void) +jpeg_stdio_src (j_decompress_ptr cinfo, FILE * infile) +{ + my_src_ptr src; + + /* The source object and input buffer are made permanent so that a series + * of JPEG images can be read from the same file by calling jpeg_stdio_src + * only before the first one. (If we discarded the buffer at the end of + * one image, we'd likely lose the start of the next one.) + * This makes it unsafe to use this manager and a different source + * manager serially with the same JPEG object. Caveat programmer. + */ + if (cinfo->src == NULL) { /* first time for this JPEG object? */ + cinfo->src = (struct jpeg_source_mgr *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + SIZEOF(my_source_mgr)); + src = (my_src_ptr) cinfo->src; + src->buffer = (JOCTET *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + INPUT_BUF_SIZE * SIZEOF(JOCTET)); + } + + src = (my_src_ptr) cinfo->src; + src->pub.init_source = init_source; + src->pub.fill_input_buffer = fill_input_buffer; + src->pub.skip_input_data = skip_input_data; + src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */ + src->pub.term_source = term_source; + src->infile = infile; + src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */ + src->pub.next_input_byte = NULL; /* until buffer loaded */ +} diff --git a/jpeg/JDCOEFCT.C b/jpeg/JDCOEFCT.C new file mode 100644 index 0000000..946d6a8 --- /dev/null +++ b/jpeg/JDCOEFCT.C @@ -0,0 +1,736 @@ +/* + * jdcoefct.c + * + * Copyright (C) 1994-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the coefficient buffer controller for decompression. + * This controller is the top level of the JPEG decompressor proper. + * The coefficient buffer lies between entropy decoding and inverse-DCT steps. + * + * In buffered-image mode, this controller is the interface between + * input-oriented processing and output-oriented processing. + * Also, the input side (only) is used when reading a file for transcoding. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + +/* Block smoothing is only applicable for progressive JPEG, so: */ +#ifndef D_PROGRESSIVE_SUPPORTED +#undef BLOCK_SMOOTHING_SUPPORTED +#endif + +/* Private buffer controller object */ + +typedef struct { + struct jpeg_d_coef_controller pub; /* public fields */ + + /* These variables keep track of the current location of the input side. */ + /* cinfo->input_iMCU_row is also used for this. */ + JDIMENSION MCU_ctr; /* counts MCUs processed in current row */ + int MCU_vert_offset; /* counts MCU rows within iMCU row */ + int MCU_rows_per_iMCU_row; /* number of such rows needed */ + + /* The output side's location is represented by cinfo->output_iMCU_row. */ + + /* In single-pass modes, it's sufficient to buffer just one MCU. + * We allocate a workspace of D_MAX_BLOCKS_IN_MCU coefficient blocks, + * and let the entropy decoder write into that workspace each time. + * (On 80x86, the workspace is FAR even though it's not really very big; + * this is to keep the module interfaces unchanged when a large coefficient + * buffer is necessary.) + * In multi-pass modes, this array points to the current MCU's blocks + * within the virtual arrays; it is used only by the input side. + */ + JBLOCKROW MCU_buffer[D_MAX_BLOCKS_IN_MCU]; + +#ifdef D_MULTISCAN_FILES_SUPPORTED + /* In multi-pass modes, we need a virtual block array for each component. */ + jvirt_barray_ptr whole_image[MAX_COMPONENTS]; +#endif + +#ifdef BLOCK_SMOOTHING_SUPPORTED + /* When doing block smoothing, we latch coefficient Al values here */ + int * coef_bits_latch; +#define SAVED_COEFS 6 /* we save coef_bits[0..5] */ +#endif +} my_coef_controller; + +typedef my_coef_controller * my_coef_ptr; + +/* Forward declarations */ +METHODDEF(int) decompress_onepass + JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf)); +#ifdef D_MULTISCAN_FILES_SUPPORTED +METHODDEF(int) decompress_data + JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf)); +#endif +#ifdef BLOCK_SMOOTHING_SUPPORTED +LOCAL(boolean) smoothing_ok JPP((j_decompress_ptr cinfo)); +METHODDEF(int) decompress_smooth_data + JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf)); +#endif + + +LOCAL(void) +start_iMCU_row (j_decompress_ptr cinfo) +/* Reset within-iMCU-row counters for a new row (input side) */ +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + + /* In an interleaved scan, an MCU row is the same as an iMCU row. + * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows. + * But at the bottom of the image, process only what's left. + */ + if (cinfo->comps_in_scan > 1) { + coef->MCU_rows_per_iMCU_row = 1; + } else { + if (cinfo->input_iMCU_row < (cinfo->total_iMCU_rows-1)) + coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor; + else + coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height; + } + + coef->MCU_ctr = 0; + coef->MCU_vert_offset = 0; +} + + +/* + * Initialize for an input processing pass. + */ + +METHODDEF(void) +start_input_pass (j_decompress_ptr cinfo) +{ + cinfo->input_iMCU_row = 0; + start_iMCU_row(cinfo); +} + + +/* + * Initialize for an output processing pass. + */ + +METHODDEF(void) +start_output_pass (j_decompress_ptr cinfo) +{ +#ifdef BLOCK_SMOOTHING_SUPPORTED + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + + /* If multipass, check to see whether to use block smoothing on this pass */ + if (coef->pub.coef_arrays != NULL) { + if (cinfo->do_block_smoothing && smoothing_ok(cinfo)) + coef->pub.decompress_data = decompress_smooth_data; + else + coef->pub.decompress_data = decompress_data; + } +#endif + cinfo->output_iMCU_row = 0; +} + + +/* + * Decompress and return some data in the single-pass case. + * Always attempts to emit one fully interleaved MCU row ("iMCU" row). + * Input and output must run in lockstep since we have only a one-MCU buffer. + * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. + * + * NB: output_buf contains a plane for each component in image, + * which we index according to the component's SOF position. + */ + +METHODDEF(int) +decompress_onepass (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + JDIMENSION MCU_col_num; /* index of current MCU within row */ + JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1; + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + int blkn, ci, xindex, yindex, yoffset, useful_width; + JSAMPARRAY output_ptr; + JDIMENSION start_col, output_col; + jpeg_component_info *compptr; + inverse_DCT_method_ptr inverse_DCT; + + /* Loop to process as much as one whole iMCU row */ + for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; + yoffset++) { + for (MCU_col_num = coef->MCU_ctr; MCU_col_num <= last_MCU_col; + MCU_col_num++) { + /* Try to fetch an MCU. Entropy decoder expects buffer to be zeroed. */ + jzero_far((void FAR *) coef->MCU_buffer[0], + (size_t) (cinfo->blocks_in_MCU * SIZEOF(JBLOCK))); + if (! (*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) { + /* Suspension forced; update state counters and exit */ + coef->MCU_vert_offset = yoffset; + coef->MCU_ctr = MCU_col_num; + return JPEG_SUSPENDED; + } + /* Determine where data should go in output_buf and do the IDCT thing. + * We skip dummy blocks at the right and bottom edges (but blkn gets + * incremented past them!). Note the inner loop relies on having + * allocated the MCU_buffer[] blocks sequentially. + */ + blkn = 0; /* index of current DCT block within MCU */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* Don't bother to IDCT an uninteresting component. */ + if (! compptr->component_needed) { + blkn += compptr->MCU_blocks; + continue; + } + inverse_DCT = cinfo->idct->inverse_DCT[compptr->component_index]; + useful_width = (MCU_col_num < last_MCU_col) ? compptr->MCU_width + : compptr->last_col_width; + output_ptr = output_buf[compptr->component_index] + + yoffset * compptr->DCT_scaled_size; + start_col = MCU_col_num * compptr->MCU_sample_width; + for (yindex = 0; yindex < compptr->MCU_height; yindex++) { + if (cinfo->input_iMCU_row < last_iMCU_row || + yoffset+yindex < compptr->last_row_height) { + output_col = start_col; + for (xindex = 0; xindex < useful_width; xindex++) { + (*inverse_DCT) (cinfo, compptr, + (JCOEFPTR) coef->MCU_buffer[blkn+xindex], + output_ptr, output_col); + output_col += compptr->DCT_scaled_size; + } + } + blkn += compptr->MCU_width; + output_ptr += compptr->DCT_scaled_size; + } + } + } + /* Completed an MCU row, but perhaps not an iMCU row */ + coef->MCU_ctr = 0; + } + /* Completed the iMCU row, advance counters for next one */ + cinfo->output_iMCU_row++; + if (++(cinfo->input_iMCU_row) < cinfo->total_iMCU_rows) { + start_iMCU_row(cinfo); + return JPEG_ROW_COMPLETED; + } + /* Completed the scan */ + (*cinfo->inputctl->finish_input_pass) (cinfo); + return JPEG_SCAN_COMPLETED; +} + + +/* + * Dummy consume-input routine for single-pass operation. + */ + +METHODDEF(int) +dummy_consume_data (j_decompress_ptr cinfo) +{ + return JPEG_SUSPENDED; /* Always indicate nothing was done */ +} + + +#ifdef D_MULTISCAN_FILES_SUPPORTED + +/* + * Consume input data and store it in the full-image coefficient buffer. + * We read as much as one fully interleaved MCU row ("iMCU" row) per call, + * ie, v_samp_factor block rows for each component in the scan. + * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. + */ + +METHODDEF(int) +consume_data (j_decompress_ptr cinfo) +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + JDIMENSION MCU_col_num; /* index of current MCU within row */ + int blkn, ci, xindex, yindex, yoffset; + JDIMENSION start_col; + JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN]; + JBLOCKROW buffer_ptr; + jpeg_component_info *compptr; + + /* Align the virtual buffers for the components used in this scan. */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + buffer[ci] = (*cinfo->mem->access_virt_barray) + ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index], + cinfo->input_iMCU_row * compptr->v_samp_factor, + (JDIMENSION) compptr->v_samp_factor, TRUE); + /* Note: entropy decoder expects buffer to be zeroed, + * but this is handled automatically by the memory manager + * because we requested a pre-zeroed array. + */ + } + + /* Loop to process one whole iMCU row */ + for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; + yoffset++) { + for (MCU_col_num = coef->MCU_ctr; MCU_col_num < cinfo->MCUs_per_row; + MCU_col_num++) { + /* Construct list of pointers to DCT blocks belonging to this MCU */ + blkn = 0; /* index of current DCT block within MCU */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + start_col = MCU_col_num * compptr->MCU_width; + for (yindex = 0; yindex < compptr->MCU_height; yindex++) { + buffer_ptr = buffer[ci][yindex+yoffset] + start_col; + for (xindex = 0; xindex < compptr->MCU_width; xindex++) { + coef->MCU_buffer[blkn++] = buffer_ptr++; + } + } + } + /* Try to fetch the MCU. */ + if (! (*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) { + /* Suspension forced; update state counters and exit */ + coef->MCU_vert_offset = yoffset; + coef->MCU_ctr = MCU_col_num; + return JPEG_SUSPENDED; + } + } + /* Completed an MCU row, but perhaps not an iMCU row */ + coef->MCU_ctr = 0; + } + /* Completed the iMCU row, advance counters for next one */ + if (++(cinfo->input_iMCU_row) < cinfo->total_iMCU_rows) { + start_iMCU_row(cinfo); + return JPEG_ROW_COMPLETED; + } + /* Completed the scan */ + (*cinfo->inputctl->finish_input_pass) (cinfo); + return JPEG_SCAN_COMPLETED; +} + + +/* + * Decompress and return some data in the multi-pass case. + * Always attempts to emit one fully interleaved MCU row ("iMCU" row). + * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. + * + * NB: output_buf contains a plane for each component in image. + */ + +METHODDEF(int) +decompress_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + JDIMENSION block_num; + int ci, block_row, block_rows; + JBLOCKARRAY buffer; + JBLOCKROW buffer_ptr; + JSAMPARRAY output_ptr; + JDIMENSION output_col; + jpeg_component_info *compptr; + inverse_DCT_method_ptr inverse_DCT; + + /* Force some input to be done if we are getting ahead of the input. */ + while (cinfo->input_scan_number < cinfo->output_scan_number || + (cinfo->input_scan_number == cinfo->output_scan_number && + cinfo->input_iMCU_row <= cinfo->output_iMCU_row)) { + if ((*cinfo->inputctl->consume_input)(cinfo) == JPEG_SUSPENDED) + return JPEG_SUSPENDED; + } + + /* OK, output from the virtual arrays. */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Don't bother to IDCT an uninteresting component. */ + if (! compptr->component_needed) + continue; + /* Align the virtual buffer for this component. */ + buffer = (*cinfo->mem->access_virt_barray) + ((j_common_ptr) cinfo, coef->whole_image[ci], + cinfo->output_iMCU_row * compptr->v_samp_factor, + (JDIMENSION) compptr->v_samp_factor, FALSE); + /* Count non-dummy DCT block rows in this iMCU row. */ + if (cinfo->output_iMCU_row < last_iMCU_row) + block_rows = compptr->v_samp_factor; + else { + /* NB: can't use last_row_height here; it is input-side-dependent! */ + block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor); + if (block_rows == 0) block_rows = compptr->v_samp_factor; + } + inverse_DCT = cinfo->idct->inverse_DCT[ci]; + output_ptr = output_buf[ci]; + /* Loop over all DCT blocks to be processed. */ + for (block_row = 0; block_row < block_rows; block_row++) { + buffer_ptr = buffer[block_row]; + output_col = 0; + for (block_num = 0; block_num < compptr->width_in_blocks; block_num++) { + (*inverse_DCT) (cinfo, compptr, (JCOEFPTR) buffer_ptr, + output_ptr, output_col); + buffer_ptr++; + output_col += compptr->DCT_scaled_size; + } + output_ptr += compptr->DCT_scaled_size; + } + } + + if (++(cinfo->output_iMCU_row) < cinfo->total_iMCU_rows) + return JPEG_ROW_COMPLETED; + return JPEG_SCAN_COMPLETED; +} + +#endif /* D_MULTISCAN_FILES_SUPPORTED */ + + +#ifdef BLOCK_SMOOTHING_SUPPORTED + +/* + * This code applies interblock smoothing as described by section K.8 + * of the JPEG standard: the first 5 AC coefficients are estimated from + * the DC values of a DCT block and its 8 neighboring blocks. + * We apply smoothing only for progressive JPEG decoding, and only if + * the coefficients it can estimate are not yet known to full precision. + */ + +/* Natural-order array positions of the first 5 zigzag-order coefficients */ +#define Q01_POS 1 +#define Q10_POS 8 +#define Q20_POS 16 +#define Q11_POS 9 +#define Q02_POS 2 + +/* + * Determine whether block smoothing is applicable and safe. + * We also latch the current states of the coef_bits[] entries for the + * AC coefficients; otherwise, if the input side of the decompressor + * advances into a new scan, we might think the coefficients are known + * more accurately than they really are. + */ + +LOCAL(boolean) +smoothing_ok (j_decompress_ptr cinfo) +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + boolean smoothing_useful = FALSE; + int ci, coefi; + jpeg_component_info *compptr; + JQUANT_TBL * qtable; + int * coef_bits; + int * coef_bits_latch; + + if (! cinfo->progressive_mode || cinfo->coef_bits == NULL) + return FALSE; + + /* Allocate latch area if not already done */ + if (coef->coef_bits_latch == NULL) + coef->coef_bits_latch = (int *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + cinfo->num_components * + (SAVED_COEFS * SIZEOF(int))); + coef_bits_latch = coef->coef_bits_latch; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* All components' quantization values must already be latched. */ + if ((qtable = compptr->quant_table) == NULL) + return FALSE; + /* Verify DC & first 5 AC quantizers are nonzero to avoid zero-divide. */ + if (qtable->quantval[0] == 0 || + qtable->quantval[Q01_POS] == 0 || + qtable->quantval[Q10_POS] == 0 || + qtable->quantval[Q20_POS] == 0 || + qtable->quantval[Q11_POS] == 0 || + qtable->quantval[Q02_POS] == 0) + return FALSE; + /* DC values must be at least partly known for all components. */ + coef_bits = cinfo->coef_bits[ci]; + if (coef_bits[0] < 0) + return FALSE; + /* Block smoothing is helpful if some AC coefficients remain inaccurate. */ + for (coefi = 1; coefi <= 5; coefi++) { + coef_bits_latch[coefi] = coef_bits[coefi]; + if (coef_bits[coefi] != 0) + smoothing_useful = TRUE; + } + coef_bits_latch += SAVED_COEFS; + } + + return smoothing_useful; +} + + +/* + * Variant of decompress_data for use when doing block smoothing. + */ + +METHODDEF(int) +decompress_smooth_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + JDIMENSION block_num, last_block_column; + int ci, block_row, block_rows, access_rows; + JBLOCKARRAY buffer; + JBLOCKROW buffer_ptr, prev_block_row, next_block_row; + JSAMPARRAY output_ptr; + JDIMENSION output_col; + jpeg_component_info *compptr; + inverse_DCT_method_ptr inverse_DCT; + boolean first_row, last_row; + JBLOCK workspace; + int *coef_bits; + JQUANT_TBL *quanttbl; + INT32 Q00,Q01,Q02,Q10,Q11,Q20, num; + int DC1,DC2,DC3,DC4,DC5,DC6,DC7,DC8,DC9; + int Al, pred; + + /* Force some input to be done if we are getting ahead of the input. */ + while (cinfo->input_scan_number <= cinfo->output_scan_number && + ! cinfo->inputctl->eoi_reached) { + if (cinfo->input_scan_number == cinfo->output_scan_number) { + /* If input is working on current scan, we ordinarily want it to + * have completed the current row. But if input scan is DC, + * we want it to keep one row ahead so that next block row's DC + * values are up to date. + */ + JDIMENSION delta = (cinfo->Ss == 0) ? 1 : 0; + if (cinfo->input_iMCU_row > cinfo->output_iMCU_row+delta) + break; + } + if ((*cinfo->inputctl->consume_input)(cinfo) == JPEG_SUSPENDED) + return JPEG_SUSPENDED; + } + + /* OK, output from the virtual arrays. */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Don't bother to IDCT an uninteresting component. */ + if (! compptr->component_needed) + continue; + /* Count non-dummy DCT block rows in this iMCU row. */ + if (cinfo->output_iMCU_row < last_iMCU_row) { + block_rows = compptr->v_samp_factor; + access_rows = block_rows * 2; /* this and next iMCU row */ + last_row = FALSE; + } else { + /* NB: can't use last_row_height here; it is input-side-dependent! */ + block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor); + if (block_rows == 0) block_rows = compptr->v_samp_factor; + access_rows = block_rows; /* this iMCU row only */ + last_row = TRUE; + } + /* Align the virtual buffer for this component. */ + if (cinfo->output_iMCU_row > 0) { + access_rows += compptr->v_samp_factor; /* prior iMCU row too */ + buffer = (*cinfo->mem->access_virt_barray) + ((j_common_ptr) cinfo, coef->whole_image[ci], + (cinfo->output_iMCU_row - 1) * compptr->v_samp_factor, + (JDIMENSION) access_rows, FALSE); + buffer += compptr->v_samp_factor; /* point to current iMCU row */ + first_row = FALSE; + } else { + buffer = (*cinfo->mem->access_virt_barray) + ((j_common_ptr) cinfo, coef->whole_image[ci], + (JDIMENSION) 0, (JDIMENSION) access_rows, FALSE); + first_row = TRUE; + } + /* Fetch component-dependent info */ + coef_bits = coef->coef_bits_latch + (ci * SAVED_COEFS); + quanttbl = compptr->quant_table; + Q00 = quanttbl->quantval[0]; + Q01 = quanttbl->quantval[Q01_POS]; + Q10 = quanttbl->quantval[Q10_POS]; + Q20 = quanttbl->quantval[Q20_POS]; + Q11 = quanttbl->quantval[Q11_POS]; + Q02 = quanttbl->quantval[Q02_POS]; + inverse_DCT = cinfo->idct->inverse_DCT[ci]; + output_ptr = output_buf[ci]; + /* Loop over all DCT blocks to be processed. */ + for (block_row = 0; block_row < block_rows; block_row++) { + buffer_ptr = buffer[block_row]; + if (first_row && block_row == 0) + prev_block_row = buffer_ptr; + else + prev_block_row = buffer[block_row-1]; + if (last_row && block_row == block_rows-1) + next_block_row = buffer_ptr; + else + next_block_row = buffer[block_row+1]; + /* We fetch the surrounding DC values using a sliding-register approach. + * Initialize all nine here so as to do the right thing on narrow pics. + */ + DC1 = DC2 = DC3 = (int) prev_block_row[0][0]; + DC4 = DC5 = DC6 = (int) buffer_ptr[0][0]; + DC7 = DC8 = DC9 = (int) next_block_row[0][0]; + output_col = 0; + last_block_column = compptr->width_in_blocks - 1; + for (block_num = 0; block_num <= last_block_column; block_num++) { + /* Fetch current DCT block into workspace so we can modify it. */ + jcopy_block_row(buffer_ptr, (JBLOCKROW) workspace, (JDIMENSION) 1); + /* Update DC values */ + if (block_num < last_block_column) { + DC3 = (int) prev_block_row[1][0]; + DC6 = (int) buffer_ptr[1][0]; + DC9 = (int) next_block_row[1][0]; + } + /* Compute coefficient estimates per K.8. + * An estimate is applied only if coefficient is still zero, + * and is not known to be fully accurate. + */ + /* AC01 */ + if ((Al=coef_bits[1]) != 0 && workspace[1] == 0) { + num = 36 * Q00 * (DC4 - DC6); + if (num >= 0) { + pred = (int) (((Q01<<7) + num) / (Q01<<8)); + if (Al > 0 && pred >= (1< 0 && pred >= (1<= 0) { + pred = (int) (((Q10<<7) + num) / (Q10<<8)); + if (Al > 0 && pred >= (1< 0 && pred >= (1<= 0) { + pred = (int) (((Q20<<7) + num) / (Q20<<8)); + if (Al > 0 && pred >= (1< 0 && pred >= (1<= 0) { + pred = (int) (((Q11<<7) + num) / (Q11<<8)); + if (Al > 0 && pred >= (1< 0 && pred >= (1<= 0) { + pred = (int) (((Q02<<7) + num) / (Q02<<8)); + if (Al > 0 && pred >= (1< 0 && pred >= (1<DCT_scaled_size; + } + output_ptr += compptr->DCT_scaled_size; + } + } + + if (++(cinfo->output_iMCU_row) < cinfo->total_iMCU_rows) + return JPEG_ROW_COMPLETED; + return JPEG_SCAN_COMPLETED; +} + +#endif /* BLOCK_SMOOTHING_SUPPORTED */ + + +/* + * Initialize coefficient buffer controller. + */ + +GLOBAL(void) +jinit_d_coef_controller (j_decompress_ptr cinfo, boolean need_full_buffer) +{ + my_coef_ptr coef; + + coef = (my_coef_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_coef_controller)); + cinfo->coef = (struct jpeg_d_coef_controller *) coef; + coef->pub.start_input_pass = start_input_pass; + coef->pub.start_output_pass = start_output_pass; +#ifdef BLOCK_SMOOTHING_SUPPORTED + coef->coef_bits_latch = NULL; +#endif + + /* Create the coefficient buffer. */ + if (need_full_buffer) { +#ifdef D_MULTISCAN_FILES_SUPPORTED + /* Allocate a full-image virtual array for each component, */ + /* padded to a multiple of samp_factor DCT blocks in each direction. */ + /* Note we ask for a pre-zeroed array. */ + int ci, access_rows; + jpeg_component_info *compptr; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + access_rows = compptr->v_samp_factor; +#ifdef BLOCK_SMOOTHING_SUPPORTED + /* If block smoothing could be used, need a bigger window */ + if (cinfo->progressive_mode) + access_rows *= 3; +#endif + coef->whole_image[ci] = (*cinfo->mem->request_virt_barray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, TRUE, + (JDIMENSION) jround_up((long) compptr->width_in_blocks, + (long) compptr->h_samp_factor), + (JDIMENSION) jround_up((long) compptr->height_in_blocks, + (long) compptr->v_samp_factor), + (JDIMENSION) access_rows); + } + coef->pub.consume_data = consume_data; + coef->pub.decompress_data = decompress_data; + coef->pub.coef_arrays = coef->whole_image; /* link to virtual arrays */ +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else { + /* We only need a single-MCU buffer. */ + JBLOCKROW buffer; + int i; + + buffer = (JBLOCKROW) + (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, + D_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); + for (i = 0; i < D_MAX_BLOCKS_IN_MCU; i++) { + coef->MCU_buffer[i] = buffer + i; + } + coef->pub.consume_data = dummy_consume_data; + coef->pub.decompress_data = decompress_onepass; + coef->pub.coef_arrays = NULL; /* flag for no virtual arrays */ + } +} diff --git a/jpeg/JDCOLOR.C b/jpeg/JDCOLOR.C new file mode 100644 index 0000000..635af80 --- /dev/null +++ b/jpeg/JDCOLOR.C @@ -0,0 +1,396 @@ +/* + * jdcolor.c + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains output colorspace conversion routines. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Private subobject */ + +typedef struct { + struct jpeg_color_deconverter pub; /* public fields */ + + /* Private state for YCC->RGB conversion */ + int * Cr_r_tab; /* => table for Cr to R conversion */ + int * Cb_b_tab; /* => table for Cb to B conversion */ + INT32 * Cr_g_tab; /* => table for Cr to G conversion */ + INT32 * Cb_g_tab; /* => table for Cb to G conversion */ +} my_color_deconverter; + +typedef my_color_deconverter * my_cconvert_ptr; + + +/**************** YCbCr -> RGB conversion: most common case **************/ + +/* + * YCbCr is defined per CCIR 601-1, except that Cb and Cr are + * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. + * The conversion equations to be implemented are therefore + * R = Y + 1.40200 * Cr + * G = Y - 0.34414 * Cb - 0.71414 * Cr + * B = Y + 1.77200 * Cb + * where Cb and Cr represent the incoming values less CENTERJSAMPLE. + * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.) + * + * To avoid floating-point arithmetic, we represent the fractional constants + * as integers scaled up by 2^16 (about 4 digits precision); we have to divide + * the products by 2^16, with appropriate rounding, to get the correct answer. + * Notice that Y, being an integral input, does not contribute any fraction + * so it need not participate in the rounding. + * + * For even more speed, we avoid doing any multiplications in the inner loop + * by precalculating the constants times Cb and Cr for all possible values. + * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table); + * for 12-bit samples it is still acceptable. It's not very reasonable for + * 16-bit samples, but if you want lossless storage you shouldn't be changing + * colorspace anyway. + * The Cr=>R and Cb=>B values can be rounded to integers in advance; the + * values for the G calculation are left scaled up, since we must add them + * together before rounding. + */ + +#define SCALEBITS 16 /* speediest right-shift on some machines */ +#define ONE_HALF ((INT32) 1 << (SCALEBITS-1)) +#define FIX(x) ((INT32) ((x) * (1L<RGB colorspace conversion. + */ + +LOCAL(void) +build_ycc_rgb_table (j_decompress_ptr cinfo) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + int i; + INT32 x; + SHIFT_TEMPS + + cconvert->Cr_r_tab = (int *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(int)); + cconvert->Cb_b_tab = (int *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(int)); + cconvert->Cr_g_tab = (INT32 *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(INT32)); + cconvert->Cb_g_tab = (INT32 *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(INT32)); + + for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) { + /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */ + /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */ + /* Cr=>R value is nearest int to 1.40200 * x */ + cconvert->Cr_r_tab[i] = (int) + RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS); + /* Cb=>B value is nearest int to 1.77200 * x */ + cconvert->Cb_b_tab[i] = (int) + RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS); + /* Cr=>G value is scaled-up -0.71414 * x */ + cconvert->Cr_g_tab[i] = (- FIX(0.71414)) * x; + /* Cb=>G value is scaled-up -0.34414 * x */ + /* We also add in ONE_HALF so that need not do it in inner loop */ + cconvert->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF; + } +} + + +/* + * Convert some rows of samples to the output colorspace. + * + * Note that we change from noninterleaved, one-plane-per-component format + * to interleaved-pixel format. The output buffer is therefore three times + * as wide as the input buffer. + * A starting row offset is provided only for the input buffer. The caller + * can easily adjust the passed output_buf value to accommodate any row + * offset required on that side. + */ + +METHODDEF(void) +ycc_rgb_convert (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + register int y, cb, cr; + register JSAMPROW outptr; + register JSAMPROW inptr0, inptr1, inptr2; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->output_width; + /* copy these pointers into registers if possible */ + register JSAMPLE * range_limit = cinfo->sample_range_limit; + register int * Crrtab = cconvert->Cr_r_tab; + register int * Cbbtab = cconvert->Cb_b_tab; + register INT32 * Crgtab = cconvert->Cr_g_tab; + register INT32 * Cbgtab = cconvert->Cb_g_tab; + SHIFT_TEMPS + + while (--num_rows >= 0) { + inptr0 = input_buf[0][input_row]; + inptr1 = input_buf[1][input_row]; + inptr2 = input_buf[2][input_row]; + input_row++; + outptr = *output_buf++; + for (col = 0; col < num_cols; col++) { + y = GETJSAMPLE(inptr0[col]); + cb = GETJSAMPLE(inptr1[col]); + cr = GETJSAMPLE(inptr2[col]); + /* Range-limiting is essential due to noise introduced by DCT losses. */ + outptr[RGB_RED] = range_limit[y + Crrtab[cr]]; + outptr[RGB_GREEN] = range_limit[y + + ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], + SCALEBITS))]; + outptr[RGB_BLUE] = range_limit[y + Cbbtab[cb]]; + outptr += RGB_PIXELSIZE; + } + } +} + + +/**************** Cases other than YCbCr -> RGB **************/ + + +/* + * Color conversion for no colorspace change: just copy the data, + * converting from separate-planes to interleaved representation. + */ + +METHODDEF(void) +null_convert (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) +{ + register JSAMPROW inptr, outptr; + register JDIMENSION count; + register int num_components = cinfo->num_components; + JDIMENSION num_cols = cinfo->output_width; + int ci; + + while (--num_rows >= 0) { + for (ci = 0; ci < num_components; ci++) { + inptr = input_buf[ci][input_row]; + outptr = output_buf[0] + ci; + for (count = num_cols; count > 0; count--) { + *outptr = *inptr++; /* needn't bother with GETJSAMPLE() here */ + outptr += num_components; + } + } + input_row++; + output_buf++; + } +} + + +/* + * Color conversion for grayscale: just copy the data. + * This also works for YCbCr -> grayscale conversion, in which + * we just copy the Y (luminance) component and ignore chrominance. + */ + +METHODDEF(void) +grayscale_convert (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) +{ + jcopy_sample_rows(input_buf[0], (int) input_row, output_buf, 0, + num_rows, cinfo->output_width); +} + + +/* + * Convert grayscale to RGB: just duplicate the graylevel three times. + * This is provided to support applications that don't want to cope + * with grayscale as a separate case. + */ + +METHODDEF(void) +gray_rgb_convert (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) +{ + register JSAMPROW inptr, outptr; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->output_width; + + while (--num_rows >= 0) { + inptr = input_buf[0][input_row++]; + outptr = *output_buf++; + for (col = 0; col < num_cols; col++) { + /* We can dispense with GETJSAMPLE() here */ + outptr[RGB_RED] = outptr[RGB_GREEN] = outptr[RGB_BLUE] = inptr[col]; + outptr += RGB_PIXELSIZE; + } + } +} + + +/* + * Adobe-style YCCK->CMYK conversion. + * We convert YCbCr to R=1-C, G=1-M, and B=1-Y using the same + * conversion as above, while passing K (black) unchanged. + * We assume build_ycc_rgb_table has been called. + */ + +METHODDEF(void) +ycck_cmyk_convert (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + register int y, cb, cr; + register JSAMPROW outptr; + register JSAMPROW inptr0, inptr1, inptr2, inptr3; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->output_width; + /* copy these pointers into registers if possible */ + register JSAMPLE * range_limit = cinfo->sample_range_limit; + register int * Crrtab = cconvert->Cr_r_tab; + register int * Cbbtab = cconvert->Cb_b_tab; + register INT32 * Crgtab = cconvert->Cr_g_tab; + register INT32 * Cbgtab = cconvert->Cb_g_tab; + SHIFT_TEMPS + + while (--num_rows >= 0) { + inptr0 = input_buf[0][input_row]; + inptr1 = input_buf[1][input_row]; + inptr2 = input_buf[2][input_row]; + inptr3 = input_buf[3][input_row]; + input_row++; + outptr = *output_buf++; + for (col = 0; col < num_cols; col++) { + y = GETJSAMPLE(inptr0[col]); + cb = GETJSAMPLE(inptr1[col]); + cr = GETJSAMPLE(inptr2[col]); + /* Range-limiting is essential due to noise introduced by DCT losses. */ + outptr[0] = range_limit[MAXJSAMPLE - (y + Crrtab[cr])]; /* red */ + outptr[1] = range_limit[MAXJSAMPLE - (y + /* green */ + ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], + SCALEBITS)))]; + outptr[2] = range_limit[MAXJSAMPLE - (y + Cbbtab[cb])]; /* blue */ + /* K passes through unchanged */ + outptr[3] = inptr3[col]; /* don't need GETJSAMPLE here */ + outptr += 4; + } + } +} + + +/* + * Empty method for start_pass. + */ + +METHODDEF(void) +start_pass_dcolor (j_decompress_ptr cinfo) +{ + /* no work needed */ +} + + +/* + * Module initialization routine for output colorspace conversion. + */ + +GLOBAL(void) +jinit_color_deconverter (j_decompress_ptr cinfo) +{ + my_cconvert_ptr cconvert; + int ci; + + cconvert = (my_cconvert_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_color_deconverter)); + cinfo->cconvert = (struct jpeg_color_deconverter *) cconvert; + cconvert->pub.start_pass = start_pass_dcolor; + + /* Make sure num_components agrees with jpeg_color_space */ + switch (cinfo->jpeg_color_space) { + case JCS_GRAYSCALE: + if (cinfo->num_components != 1) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + break; + + case JCS_RGB: + case JCS_YCbCr: + if (cinfo->num_components != 3) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + break; + + case JCS_CMYK: + case JCS_YCCK: + if (cinfo->num_components != 4) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + break; + + default: /* JCS_UNKNOWN can be anything */ + if (cinfo->num_components < 1) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + break; + } + + /* Set out_color_components and conversion method based on requested space. + * Also clear the component_needed flags for any unused components, + * so that earlier pipeline stages can avoid useless computation. + */ + + switch (cinfo->out_color_space) { + case JCS_GRAYSCALE: + cinfo->out_color_components = 1; + if (cinfo->jpeg_color_space == JCS_GRAYSCALE || + cinfo->jpeg_color_space == JCS_YCbCr) { + cconvert->pub.color_convert = grayscale_convert; + /* For color->grayscale conversion, only the Y (0) component is needed */ + for (ci = 1; ci < cinfo->num_components; ci++) + cinfo->comp_info[ci].component_needed = FALSE; + } else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + case JCS_RGB: + cinfo->out_color_components = RGB_PIXELSIZE; + if (cinfo->jpeg_color_space == JCS_YCbCr) { + cconvert->pub.color_convert = ycc_rgb_convert; + build_ycc_rgb_table(cinfo); + } else if (cinfo->jpeg_color_space == JCS_GRAYSCALE) { + cconvert->pub.color_convert = gray_rgb_convert; + } else if (cinfo->jpeg_color_space == JCS_RGB && RGB_PIXELSIZE == 3) { + cconvert->pub.color_convert = null_convert; + } else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + case JCS_CMYK: + cinfo->out_color_components = 4; + if (cinfo->jpeg_color_space == JCS_YCCK) { + cconvert->pub.color_convert = ycck_cmyk_convert; + build_ycc_rgb_table(cinfo); + } else if (cinfo->jpeg_color_space == JCS_CMYK) { + cconvert->pub.color_convert = null_convert; + } else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + default: + /* Permit null conversion to same output space */ + if (cinfo->out_color_space == cinfo->jpeg_color_space) { + cinfo->out_color_components = cinfo->num_components; + cconvert->pub.color_convert = null_convert; + } else /* unsupported non-null conversion */ + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + } + + if (cinfo->quantize_colors) + cinfo->output_components = 1; /* single colormapped output component */ + else + cinfo->output_components = cinfo->out_color_components; +} diff --git a/jpeg/JDCT.H b/jpeg/JDCT.H new file mode 100644 index 0000000..5858d28 --- /dev/null +++ b/jpeg/JDCT.H @@ -0,0 +1,176 @@ +/* + * jdct.h + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This include file contains common declarations for the forward and + * inverse DCT modules. These declarations are private to the DCT managers + * (jcdctmgr.c, jddctmgr.c) and the individual DCT algorithms. + * The individual DCT algorithms are kept in separate files to ease + * machine-dependent tuning (e.g., assembly coding). + */ + + +/* + * A forward DCT routine is given a pointer to a work area of type DCTELEM[]; + * the DCT is to be performed in-place in that buffer. Type DCTELEM is int + * for 8-bit samples, INT32 for 12-bit samples. (NOTE: Floating-point DCT + * implementations use an array of type FAST_FLOAT, instead.) + * The DCT inputs are expected to be signed (range +-CENTERJSAMPLE). + * The DCT outputs are returned scaled up by a factor of 8; they therefore + * have a range of +-8K for 8-bit data, +-128K for 12-bit data. This + * convention improves accuracy in integer implementations and saves some + * work in floating-point ones. + * Quantization of the output coefficients is done by jcdctmgr.c. + */ + +#if BITS_IN_JSAMPLE == 8 +typedef int DCTELEM; /* 16 or 32 bits is fine */ +#else +typedef INT32 DCTELEM; /* must have 32 bits */ +#endif + +typedef JMETHOD(void, forward_DCT_method_ptr, (DCTELEM * data)); +typedef JMETHOD(void, float_DCT_method_ptr, (FAST_FLOAT * data)); + + +/* + * An inverse DCT routine is given a pointer to the input JBLOCK and a pointer + * to an output sample array. The routine must dequantize the input data as + * well as perform the IDCT; for dequantization, it uses the multiplier table + * pointed to by compptr->dct_table. The output data is to be placed into the + * sample array starting at a specified column. (Any row offset needed will + * be applied to the array pointer before it is passed to the IDCT code.) + * Note that the number of samples emitted by the IDCT routine is + * DCT_scaled_size * DCT_scaled_size. + */ + +/* typedef inverse_DCT_method_ptr is declared in jpegint.h */ + +/* + * Each IDCT routine has its own ideas about the best dct_table element type. + */ + +typedef MULTIPLIER ISLOW_MULT_TYPE; /* short or int, whichever is faster */ +#if BITS_IN_JSAMPLE == 8 +typedef MULTIPLIER IFAST_MULT_TYPE; /* 16 bits is OK, use short if faster */ +#define IFAST_SCALE_BITS 2 /* fractional bits in scale factors */ +#else +typedef INT32 IFAST_MULT_TYPE; /* need 32 bits for scaled quantizers */ +#define IFAST_SCALE_BITS 13 /* fractional bits in scale factors */ +#endif +typedef FAST_FLOAT FLOAT_MULT_TYPE; /* preferred floating type */ + + +/* + * Each IDCT routine is responsible for range-limiting its results and + * converting them to unsigned form (0..MAXJSAMPLE). The raw outputs could + * be quite far out of range if the input data is corrupt, so a bulletproof + * range-limiting step is required. We use a mask-and-table-lookup method + * to do the combined operations quickly. See the comments with + * prepare_range_limit_table (in jdmaster.c) for more info. + */ + +#define IDCT_range_limit(cinfo) ((cinfo)->sample_range_limit + CENTERJSAMPLE) + +#define RANGE_MASK (MAXJSAMPLE * 4 + 3) /* 2 bits wider than legal samples */ + + +/* Short forms of external names for systems with brain-damaged linkers. */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jpeg_fdct_islow jFDislow +#define jpeg_fdct_ifast jFDifast +#define jpeg_fdct_float jFDfloat +#define jpeg_idct_islow jRDislow +#define jpeg_idct_ifast jRDifast +#define jpeg_idct_float jRDfloat +#define jpeg_idct_4x4 jRD4x4 +#define jpeg_idct_2x2 jRD2x2 +#define jpeg_idct_1x1 jRD1x1 +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + +/* Extern declarations for the forward and inverse DCT routines. */ + +EXTERN(void) jpeg_fdct_islow JPP((DCTELEM * data)); +EXTERN(void) jpeg_fdct_ifast JPP((DCTELEM * data)); +EXTERN(void) jpeg_fdct_float JPP((FAST_FLOAT * data)); + +EXTERN(void) jpeg_idct_islow + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_ifast + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_float + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_4x4 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_2x2 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_1x1 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); + + +/* + * Macros for handling fixed-point arithmetic; these are used by many + * but not all of the DCT/IDCT modules. + * + * All values are expected to be of type INT32. + * Fractional constants are scaled left by CONST_BITS bits. + * CONST_BITS is defined within each module using these macros, + * and may differ from one module to the next. + */ + +#define ONE ((INT32) 1) +#define CONST_SCALE (ONE << CONST_BITS) + +/* Convert a positive real constant to an integer scaled by CONST_SCALE. + * Caution: some C compilers fail to reduce "FIX(constant)" at compile time, + * thus causing a lot of useless floating-point operations at run time. + */ + +#define FIX(x) ((INT32) ((x) * CONST_SCALE + 0.5)) + +/* Descale and correctly round an INT32 value that's scaled by N bits. + * We assume RIGHT_SHIFT rounds towards minus infinity, so adding + * the fudge factor is correct for either sign of X. + */ + +#define DESCALE(x,n) RIGHT_SHIFT((x) + (ONE << ((n)-1)), n) + +/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result. + * This macro is used only when the two inputs will actually be no more than + * 16 bits wide, so that a 16x16->32 bit multiply can be used instead of a + * full 32x32 multiply. This provides a useful speedup on many machines. + * Unfortunately there is no way to specify a 16x16->32 multiply portably + * in C, but some C compilers will do the right thing if you provide the + * correct combination of casts. + */ + +#ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */ +#define MULTIPLY16C16(var,const) (((INT16) (var)) * ((INT16) (const))) +#endif +#ifdef SHORTxLCONST_32 /* known to work with Microsoft C 6.0 */ +#define MULTIPLY16C16(var,const) (((INT16) (var)) * ((INT32) (const))) +#endif + +#ifndef MULTIPLY16C16 /* default definition */ +#define MULTIPLY16C16(var,const) ((var) * (const)) +#endif + +/* Same except both inputs are variables. */ + +#ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */ +#define MULTIPLY16V16(var1,var2) (((INT16) (var1)) * ((INT16) (var2))) +#endif + +#ifndef MULTIPLY16V16 /* default definition */ +#define MULTIPLY16V16(var1,var2) ((var1) * (var2)) +#endif diff --git a/jpeg/JDDCTMGR.C b/jpeg/JDDCTMGR.C new file mode 100644 index 0000000..cceb208 --- /dev/null +++ b/jpeg/JDDCTMGR.C @@ -0,0 +1,269 @@ +/* + * jddctmgr.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the inverse-DCT management logic. + * This code selects a particular IDCT implementation to be used, + * and it performs related housekeeping chores. No code in this file + * is executed per IDCT step, only during output pass setup. + * + * Note that the IDCT routines are responsible for performing coefficient + * dequantization as well as the IDCT proper. This module sets up the + * dequantization multiplier table needed by the IDCT routine. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jdct.h" /* Private declarations for DCT subsystem */ + + +/* + * The decompressor input side (jdinput.c) saves away the appropriate + * quantization table for each component at the start of the first scan + * involving that component. (This is necessary in order to correctly + * decode files that reuse Q-table slots.) + * When we are ready to make an output pass, the saved Q-table is converted + * to a multiplier table that will actually be used by the IDCT routine. + * The multiplier table contents are IDCT-method-dependent. To support + * application changes in IDCT method between scans, we can remake the + * multiplier tables if necessary. + * In buffered-image mode, the first output pass may occur before any data + * has been seen for some components, and thus before their Q-tables have + * been saved away. To handle this case, multiplier tables are preset + * to zeroes; the result of the IDCT will be a neutral gray level. + */ + + +/* Private subobject for this module */ + +typedef struct { + struct jpeg_inverse_dct pub; /* public fields */ + + /* This array contains the IDCT method code that each multiplier table + * is currently set up for, or -1 if it's not yet set up. + * The actual multiplier tables are pointed to by dct_table in the + * per-component comp_info structures. + */ + int cur_method[MAX_COMPONENTS]; +} my_idct_controller; + +typedef my_idct_controller * my_idct_ptr; + + +/* Allocated multiplier tables: big enough for any supported variant */ + +typedef union { + ISLOW_MULT_TYPE islow_array[DCTSIZE2]; +#ifdef DCT_IFAST_SUPPORTED + IFAST_MULT_TYPE ifast_array[DCTSIZE2]; +#endif +#ifdef DCT_FLOAT_SUPPORTED + FLOAT_MULT_TYPE float_array[DCTSIZE2]; +#endif +} multiplier_table; + + +/* The current scaled-IDCT routines require ISLOW-style multiplier tables, + * so be sure to compile that code if either ISLOW or SCALING is requested. + */ +#ifdef DCT_ISLOW_SUPPORTED +#define PROVIDE_ISLOW_TABLES +#else +#ifdef IDCT_SCALING_SUPPORTED +#define PROVIDE_ISLOW_TABLES +#endif +#endif + + +/* + * Prepare for an output pass. + * Here we select the proper IDCT routine for each component and build + * a matching multiplier table. + */ + +METHODDEF(void) +start_pass (j_decompress_ptr cinfo) +{ + my_idct_ptr idct = (my_idct_ptr) cinfo->idct; + int ci, i; + jpeg_component_info *compptr; + int method = 0; + inverse_DCT_method_ptr method_ptr = NULL; + JQUANT_TBL * qtbl; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Select the proper IDCT routine for this component's scaling */ + switch (compptr->DCT_scaled_size) { +#ifdef IDCT_SCALING_SUPPORTED + case 1: + method_ptr = jpeg_idct_1x1; + method = JDCT_ISLOW; /* jidctred uses islow-style table */ + break; + case 2: + method_ptr = jpeg_idct_2x2; + method = JDCT_ISLOW; /* jidctred uses islow-style table */ + break; + case 4: + method_ptr = jpeg_idct_4x4; + method = JDCT_ISLOW; /* jidctred uses islow-style table */ + break; +#endif + case DCTSIZE: + switch (cinfo->dct_method) { +#ifdef DCT_ISLOW_SUPPORTED + case JDCT_ISLOW: + method_ptr = jpeg_idct_islow; + method = JDCT_ISLOW; + break; +#endif +#ifdef DCT_IFAST_SUPPORTED + case JDCT_IFAST: + method_ptr = jpeg_idct_ifast; + method = JDCT_IFAST; + break; +#endif +#ifdef DCT_FLOAT_SUPPORTED + case JDCT_FLOAT: + method_ptr = jpeg_idct_float; + method = JDCT_FLOAT; + break; +#endif + default: + ERREXIT(cinfo, JERR_NOT_COMPILED); + break; + } + break; + default: + ERREXIT1(cinfo, JERR_BAD_DCTSIZE, compptr->DCT_scaled_size); + break; + } + idct->pub.inverse_DCT[ci] = method_ptr; + /* Create multiplier table from quant table. + * However, we can skip this if the component is uninteresting + * or if we already built the table. Also, if no quant table + * has yet been saved for the component, we leave the + * multiplier table all-zero; we'll be reading zeroes from the + * coefficient controller's buffer anyway. + */ + if (! compptr->component_needed || idct->cur_method[ci] == method) + continue; + qtbl = compptr->quant_table; + if (qtbl == NULL) /* happens if no data yet for component */ + continue; + idct->cur_method[ci] = method; + switch (method) { +#ifdef PROVIDE_ISLOW_TABLES + case JDCT_ISLOW: + { + /* For LL&M IDCT method, multipliers are equal to raw quantization + * coefficients, but are stored as ints to ensure access efficiency. + */ + ISLOW_MULT_TYPE * ismtbl = (ISLOW_MULT_TYPE *) compptr->dct_table; + for (i = 0; i < DCTSIZE2; i++) { + ismtbl[i] = (ISLOW_MULT_TYPE) qtbl->quantval[i]; + } + } + break; +#endif +#ifdef DCT_IFAST_SUPPORTED + case JDCT_IFAST: + { + /* For AA&N IDCT method, multipliers are equal to quantization + * coefficients scaled by scalefactor[row]*scalefactor[col], where + * scalefactor[0] = 1 + * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 + * For integer operation, the multiplier table is to be scaled by + * IFAST_SCALE_BITS. + */ + IFAST_MULT_TYPE * ifmtbl = (IFAST_MULT_TYPE *) compptr->dct_table; +#define CONST_BITS 14 + static const INT16 aanscales[DCTSIZE2] = { + /* precomputed values scaled up by 14 bits */ + 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, + 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270, + 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906, + 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315, + 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, + 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552, + 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446, + 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247 + }; + SHIFT_TEMPS + + for (i = 0; i < DCTSIZE2; i++) { + ifmtbl[i] = (IFAST_MULT_TYPE) + DESCALE(MULTIPLY16V16((INT32) qtbl->quantval[i], + (INT32) aanscales[i]), + CONST_BITS-IFAST_SCALE_BITS); + } + } + break; +#endif +#ifdef DCT_FLOAT_SUPPORTED + case JDCT_FLOAT: + { + /* For float AA&N IDCT method, multipliers are equal to quantization + * coefficients scaled by scalefactor[row]*scalefactor[col], where + * scalefactor[0] = 1 + * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 + */ + FLOAT_MULT_TYPE * fmtbl = (FLOAT_MULT_TYPE *) compptr->dct_table; + int row, col; + static const double aanscalefactor[DCTSIZE] = { + 1.0, 1.387039845, 1.306562965, 1.175875602, + 1.0, 0.785694958, 0.541196100, 0.275899379 + }; + + i = 0; + for (row = 0; row < DCTSIZE; row++) { + for (col = 0; col < DCTSIZE; col++) { + fmtbl[i] = (FLOAT_MULT_TYPE) + ((double) qtbl->quantval[i] * + aanscalefactor[row] * aanscalefactor[col]); + i++; + } + } + } + break; +#endif + default: + ERREXIT(cinfo, JERR_NOT_COMPILED); + break; + } + } +} + + +/* + * Initialize IDCT manager. + */ + +GLOBAL(void) +jinit_inverse_dct (j_decompress_ptr cinfo) +{ + my_idct_ptr idct; + int ci; + jpeg_component_info *compptr; + + idct = (my_idct_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_idct_controller)); + cinfo->idct = (struct jpeg_inverse_dct *) idct; + idct->pub.start_pass = start_pass; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Allocate and pre-zero a multiplier table for each component */ + compptr->dct_table = + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(multiplier_table)); + MEMZERO(compptr->dct_table, SIZEOF(multiplier_table)); + /* Mark multiplier table not yet set up for any method */ + idct->cur_method[ci] = -1; + } +} diff --git a/jpeg/JDHUFF.C b/jpeg/JDHUFF.C new file mode 100644 index 0000000..e973c24 --- /dev/null +++ b/jpeg/JDHUFF.C @@ -0,0 +1,651 @@ +/* + * jdhuff.c + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains Huffman entropy decoding routines. + * + * Much of the complexity here has to do with supporting input suspension. + * If the data source module demands suspension, we want to be able to back + * up to the start of the current MCU. To do this, we copy state variables + * into local working storage, and update them back to the permanent + * storage only upon successful completion of an MCU. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jdhuff.h" /* Declarations shared with jdphuff.c */ + + +/* + * Expanded entropy decoder object for Huffman decoding. + * + * The savable_state subrecord contains fields that change within an MCU, + * but must not be updated permanently until we complete the MCU. + */ + +typedef struct { + int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ +} savable_state; + +/* This macro is to work around compilers with missing or broken + * structure assignment. You'll need to fix this code if you have + * such a compiler and you change MAX_COMPS_IN_SCAN. + */ + +#ifndef NO_STRUCT_ASSIGN +#define ASSIGN_STATE(dest,src) ((dest) = (src)) +#else +#if MAX_COMPS_IN_SCAN == 4 +#define ASSIGN_STATE(dest,src) \ + ((dest).last_dc_val[0] = (src).last_dc_val[0], \ + (dest).last_dc_val[1] = (src).last_dc_val[1], \ + (dest).last_dc_val[2] = (src).last_dc_val[2], \ + (dest).last_dc_val[3] = (src).last_dc_val[3]) +#endif +#endif + + +typedef struct { + struct jpeg_entropy_decoder pub; /* public fields */ + + /* These fields are loaded into local variables at start of each MCU. + * In case of suspension, we exit WITHOUT updating them. + */ + bitread_perm_state bitstate; /* Bit buffer at start of MCU */ + savable_state saved; /* Other state at start of MCU */ + + /* These fields are NOT loaded into local working state. */ + unsigned int restarts_to_go; /* MCUs left in this restart interval */ + + /* Pointers to derived tables (these workspaces have image lifespan) */ + d_derived_tbl * dc_derived_tbls[NUM_HUFF_TBLS]; + d_derived_tbl * ac_derived_tbls[NUM_HUFF_TBLS]; + + /* Precalculated info set up by start_pass for use in decode_mcu: */ + + /* Pointers to derived tables to be used for each block within an MCU */ + d_derived_tbl * dc_cur_tbls[D_MAX_BLOCKS_IN_MCU]; + d_derived_tbl * ac_cur_tbls[D_MAX_BLOCKS_IN_MCU]; + /* Whether we care about the DC and AC coefficient values for each block */ + boolean dc_needed[D_MAX_BLOCKS_IN_MCU]; + boolean ac_needed[D_MAX_BLOCKS_IN_MCU]; +} huff_entropy_decoder; + +typedef huff_entropy_decoder * huff_entropy_ptr; + + +/* + * Initialize for a Huffman-compressed scan. + */ + +METHODDEF(void) +start_pass_huff_decoder (j_decompress_ptr cinfo) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + int ci, blkn, dctbl, actbl; + jpeg_component_info * compptr; + + /* Check that the scan parameters Ss, Se, Ah/Al are OK for sequential JPEG. + * This ought to be an error condition, but we make it a warning because + * there are some baseline files out there with all zeroes in these bytes. + */ + if (cinfo->Ss != 0 || cinfo->Se != DCTSIZE2-1 || + cinfo->Ah != 0 || cinfo->Al != 0) + WARNMS(cinfo, JWRN_NOT_SEQUENTIAL); + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + dctbl = compptr->dc_tbl_no; + actbl = compptr->ac_tbl_no; + /* Compute derived values for Huffman tables */ + /* We may do this more than once for a table, but it's not expensive */ + jpeg_make_d_derived_tbl(cinfo, TRUE, dctbl, + & entropy->dc_derived_tbls[dctbl]); + jpeg_make_d_derived_tbl(cinfo, FALSE, actbl, + & entropy->ac_derived_tbls[actbl]); + /* Initialize DC predictions to 0 */ + entropy->saved.last_dc_val[ci] = 0; + } + + /* Precalculate decoding info for each block in an MCU of this scan */ + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + ci = cinfo->MCU_membership[blkn]; + compptr = cinfo->cur_comp_info[ci]; + /* Precalculate which table to use for each block */ + entropy->dc_cur_tbls[blkn] = entropy->dc_derived_tbls[compptr->dc_tbl_no]; + entropy->ac_cur_tbls[blkn] = entropy->ac_derived_tbls[compptr->ac_tbl_no]; + /* Decide whether we really care about the coefficient values */ + if (compptr->component_needed) { + entropy->dc_needed[blkn] = TRUE; + /* we don't need the ACs if producing a 1/8th-size image */ + entropy->ac_needed[blkn] = (compptr->DCT_scaled_size > 1); + } else { + entropy->dc_needed[blkn] = entropy->ac_needed[blkn] = FALSE; + } + } + + /* Initialize bitread state variables */ + entropy->bitstate.bits_left = 0; + entropy->bitstate.get_buffer = 0; /* unnecessary, but keeps Purify quiet */ + entropy->pub.insufficient_data = FALSE; + + /* Initialize restart counter */ + entropy->restarts_to_go = cinfo->restart_interval; +} + + +/* + * Compute the derived values for a Huffman table. + * This routine also performs some validation checks on the table. + * + * Note this is also used by jdphuff.c. + */ + +GLOBAL(void) +jpeg_make_d_derived_tbl (j_decompress_ptr cinfo, boolean isDC, int tblno, + d_derived_tbl ** pdtbl) +{ + JHUFF_TBL *htbl; + d_derived_tbl *dtbl; + int p, i, l, si, numsymbols; + int lookbits, ctr; + char huffsize[257]; + unsigned int huffcode[257]; + unsigned int code; + + /* Note that huffsize[] and huffcode[] are filled in code-length order, + * paralleling the order of the symbols themselves in htbl->huffval[]. + */ + + /* Find the input Huffman table */ + if (tblno < 0 || tblno >= NUM_HUFF_TBLS) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno); + htbl = + isDC ? cinfo->dc_huff_tbl_ptrs[tblno] : cinfo->ac_huff_tbl_ptrs[tblno]; + if (htbl == NULL) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno); + + /* Allocate a workspace if we haven't already done so. */ + if (*pdtbl == NULL) + *pdtbl = (d_derived_tbl *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(d_derived_tbl)); + dtbl = *pdtbl; + dtbl->pub = htbl; /* fill in back link */ + + /* Figure C.1: make table of Huffman code length for each symbol */ + + p = 0; + for (l = 1; l <= 16; l++) { + i = (int) htbl->bits[l]; + if (i < 0 || p + i > 256) /* protect against table overrun */ + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + while (i--) + huffsize[p++] = (char) l; + } + huffsize[p] = 0; + numsymbols = p; + + /* Figure C.2: generate the codes themselves */ + /* We also validate that the counts represent a legal Huffman code tree. */ + + code = 0; + si = huffsize[0]; + p = 0; + while (huffsize[p]) { + while (((int) huffsize[p]) == si) { + huffcode[p++] = code; + code++; + } + /* code is now 1 more than the last code used for codelength si; but + * it must still fit in si bits, since no code is allowed to be all ones. + */ + if (((INT32) code) >= (((INT32) 1) << si)) + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + code <<= 1; + si++; + } + + /* Figure F.15: generate decoding tables for bit-sequential decoding */ + + p = 0; + for (l = 1; l <= 16; l++) { + if (htbl->bits[l]) { + /* valoffset[l] = huffval[] index of 1st symbol of code length l, + * minus the minimum code of length l + */ + dtbl->valoffset[l] = (INT32) p - (INT32) huffcode[p]; + p += htbl->bits[l]; + dtbl->maxcode[l] = huffcode[p-1]; /* maximum code of length l */ + } else { + dtbl->maxcode[l] = -1; /* -1 if no codes of this length */ + } + } + dtbl->maxcode[17] = 0xFFFFFL; /* ensures jpeg_huff_decode terminates */ + + /* Compute lookahead tables to speed up decoding. + * First we set all the table entries to 0, indicating "too long"; + * then we iterate through the Huffman codes that are short enough and + * fill in all the entries that correspond to bit sequences starting + * with that code. + */ + + MEMZERO(dtbl->look_nbits, SIZEOF(dtbl->look_nbits)); + + p = 0; + for (l = 1; l <= HUFF_LOOKAHEAD; l++) { + for (i = 1; i <= (int) htbl->bits[l]; i++, p++) { + /* l = current code's length, p = its index in huffcode[] & huffval[]. */ + /* Generate left-justified code followed by all possible bit sequences */ + lookbits = huffcode[p] << (HUFF_LOOKAHEAD-l); + for (ctr = 1 << (HUFF_LOOKAHEAD-l); ctr > 0; ctr--) { + dtbl->look_nbits[lookbits] = l; + dtbl->look_sym[lookbits] = htbl->huffval[p]; + lookbits++; + } + } + } + + /* Validate symbols as being reasonable. + * For AC tables, we make no check, but accept all byte values 0..255. + * For DC tables, we require the symbols to be in range 0..15. + * (Tighter bounds could be applied depending on the data depth and mode, + * but this is sufficient to ensure safe decoding.) + */ + if (isDC) { + for (i = 0; i < numsymbols; i++) { + int sym = htbl->huffval[i]; + if (sym < 0 || sym > 15) + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + } + } +} + + +/* + * Out-of-line code for bit fetching (shared with jdphuff.c). + * See jdhuff.h for info about usage. + * Note: current values of get_buffer and bits_left are passed as parameters, + * but are returned in the corresponding fields of the state struct. + * + * On most machines MIN_GET_BITS should be 25 to allow the full 32-bit width + * of get_buffer to be used. (On machines with wider words, an even larger + * buffer could be used.) However, on some machines 32-bit shifts are + * quite slow and take time proportional to the number of places shifted. + * (This is true with most PC compilers, for instance.) In this case it may + * be a win to set MIN_GET_BITS to the minimum value of 15. This reduces the + * average shift distance at the cost of more calls to jpeg_fill_bit_buffer. + */ + +#ifdef SLOW_SHIFT_32 +#define MIN_GET_BITS 15 /* minimum allowable value */ +#else +#define MIN_GET_BITS (BIT_BUF_SIZE-7) +#endif + + +GLOBAL(boolean) +jpeg_fill_bit_buffer (bitread_working_state * state, + register bit_buf_type get_buffer, register int bits_left, + int nbits) +/* Load up the bit buffer to a depth of at least nbits */ +{ + /* Copy heavily used state fields into locals (hopefully registers) */ + register const JOCTET * next_input_byte = state->next_input_byte; + register size_t bytes_in_buffer = state->bytes_in_buffer; + j_decompress_ptr cinfo = state->cinfo; + + /* Attempt to load at least MIN_GET_BITS bits into get_buffer. */ + /* (It is assumed that no request will be for more than that many bits.) */ + /* We fail to do so only if we hit a marker or are forced to suspend. */ + + if (cinfo->unread_marker == 0) { /* cannot advance past a marker */ + while (bits_left < MIN_GET_BITS) { + register int c; + + /* Attempt to read a byte */ + if (bytes_in_buffer == 0) { + if (! (*cinfo->src->fill_input_buffer) (cinfo)) + return FALSE; + next_input_byte = cinfo->src->next_input_byte; + bytes_in_buffer = cinfo->src->bytes_in_buffer; + } + bytes_in_buffer--; + c = GETJOCTET(*next_input_byte++); + + /* If it's 0xFF, check and discard stuffed zero byte */ + if (c == 0xFF) { + /* Loop here to discard any padding FF's on terminating marker, + * so that we can save a valid unread_marker value. NOTE: we will + * accept multiple FF's followed by a 0 as meaning a single FF data + * byte. This data pattern is not valid according to the standard. + */ + do { + if (bytes_in_buffer == 0) { + if (! (*cinfo->src->fill_input_buffer) (cinfo)) + return FALSE; + next_input_byte = cinfo->src->next_input_byte; + bytes_in_buffer = cinfo->src->bytes_in_buffer; + } + bytes_in_buffer--; + c = GETJOCTET(*next_input_byte++); + } while (c == 0xFF); + + if (c == 0) { + /* Found FF/00, which represents an FF data byte */ + c = 0xFF; + } else { + /* Oops, it's actually a marker indicating end of compressed data. + * Save the marker code for later use. + * Fine point: it might appear that we should save the marker into + * bitread working state, not straight into permanent state. But + * once we have hit a marker, we cannot need to suspend within the + * current MCU, because we will read no more bytes from the data + * source. So it is OK to update permanent state right away. + */ + cinfo->unread_marker = c; + /* See if we need to insert some fake zero bits. */ + goto no_more_bytes; + } + } + + /* OK, load c into get_buffer */ + get_buffer = (get_buffer << 8) | c; + bits_left += 8; + } /* end while */ + } else { + no_more_bytes: + /* We get here if we've read the marker that terminates the compressed + * data segment. There should be enough bits in the buffer register + * to satisfy the request; if so, no problem. + */ + if (nbits > bits_left) { + /* Uh-oh. Report corrupted data to user and stuff zeroes into + * the data stream, so that we can produce some kind of image. + * We use a nonvolatile flag to ensure that only one warning message + * appears per data segment. + */ + if (! cinfo->entropy->insufficient_data) { + WARNMS(cinfo, JWRN_HIT_MARKER); + cinfo->entropy->insufficient_data = TRUE; + } + /* Fill the buffer with zero bits */ + get_buffer <<= MIN_GET_BITS - bits_left; + bits_left = MIN_GET_BITS; + } + } + + /* Unload the local registers */ + state->next_input_byte = next_input_byte; + state->bytes_in_buffer = bytes_in_buffer; + state->get_buffer = get_buffer; + state->bits_left = bits_left; + + return TRUE; +} + + +/* + * Out-of-line code for Huffman code decoding. + * See jdhuff.h for info about usage. + */ + +GLOBAL(int) +jpeg_huff_decode (bitread_working_state * state, + register bit_buf_type get_buffer, register int bits_left, + d_derived_tbl * htbl, int min_bits) +{ + register int l = min_bits; + register INT32 code; + + /* HUFF_DECODE has determined that the code is at least min_bits */ + /* bits long, so fetch that many bits in one swoop. */ + + CHECK_BIT_BUFFER(*state, l, return -1); + code = GET_BITS(l); + + /* Collect the rest of the Huffman code one bit at a time. */ + /* This is per Figure F.16 in the JPEG spec. */ + + while (code > htbl->maxcode[l]) { + code <<= 1; + CHECK_BIT_BUFFER(*state, 1, return -1); + code |= GET_BITS(1); + l++; + } + + /* Unload the local registers */ + state->get_buffer = get_buffer; + state->bits_left = bits_left; + + /* With garbage input we may reach the sentinel value l = 17. */ + + if (l > 16) { + WARNMS(state->cinfo, JWRN_HUFF_BAD_CODE); + return 0; /* fake a zero as the safest result */ + } + + return htbl->pub->huffval[ (int) (code + htbl->valoffset[l]) ]; +} + + +/* + * Figure F.12: extend sign bit. + * On some machines, a shift and add will be faster than a table lookup. + */ + +#ifdef AVOID_TABLES + +#define HUFF_EXTEND(x,s) ((x) < (1<<((s)-1)) ? (x) + (((-1)<<(s)) + 1) : (x)) + +#else + +#define HUFF_EXTEND(x,s) ((x) < extend_test[s] ? (x) + extend_offset[s] : (x)) + +static const int extend_test[16] = /* entry n is 2**(n-1) */ + { 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, + 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 }; + +static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */ + { 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1, + ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1, + ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1, + ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 }; + +#endif /* AVOID_TABLES */ + + +/* + * Check for a restart marker & resynchronize decoder. + * Returns FALSE if must suspend. + */ + +LOCAL(boolean) +process_restart (j_decompress_ptr cinfo) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + int ci; + + /* Throw away any unused bits remaining in bit buffer; */ + /* include any full bytes in next_marker's count of discarded bytes */ + cinfo->marker->discarded_bytes += entropy->bitstate.bits_left / 8; + entropy->bitstate.bits_left = 0; + + /* Advance past the RSTn marker */ + if (! (*cinfo->marker->read_restart_marker) (cinfo)) + return FALSE; + + /* Re-initialize DC predictions to 0 */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) + entropy->saved.last_dc_val[ci] = 0; + + /* Reset restart counter */ + entropy->restarts_to_go = cinfo->restart_interval; + + /* Reset out-of-data flag, unless read_restart_marker left us smack up + * against a marker. In that case we will end up treating the next data + * segment as empty, and we can avoid producing bogus output pixels by + * leaving the flag set. + */ + if (cinfo->unread_marker == 0) + entropy->pub.insufficient_data = FALSE; + + return TRUE; +} + + +/* + * Decode and return one MCU's worth of Huffman-compressed coefficients. + * The coefficients are reordered from zigzag order into natural array order, + * but are not dequantized. + * + * The i'th block of the MCU is stored into the block pointed to by + * MCU_data[i]. WE ASSUME THIS AREA HAS BEEN ZEROED BY THE CALLER. + * (Wholesale zeroing is usually a little faster than retail...) + * + * Returns FALSE if data source requested suspension. In that case no + * changes have been made to permanent state. (Exception: some output + * coefficients may already have been assigned. This is harmless for + * this module, since we'll just re-assign them on the next call.) + */ + +METHODDEF(boolean) +decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + int blkn; + BITREAD_STATE_VARS; + savable_state state; + + /* Process restart marker if needed; may have to suspend */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! process_restart(cinfo)) + return FALSE; + } + + /* If we've run out of data, just leave the MCU set to zeroes. + * This way, we return uniform gray for the remainder of the segment. + */ + if (! entropy->pub.insufficient_data) { + + /* Load up working state */ + BITREAD_LOAD_STATE(cinfo,entropy->bitstate); + ASSIGN_STATE(state, entropy->saved); + + /* Outer loop handles each block in the MCU */ + + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + JBLOCKROW block = MCU_data[blkn]; + d_derived_tbl * dctbl = entropy->dc_cur_tbls[blkn]; + d_derived_tbl * actbl = entropy->ac_cur_tbls[blkn]; + register int s, k, r; + + /* Decode a single block's worth of coefficients */ + + /* Section F.2.2.1: decode the DC coefficient difference */ + HUFF_DECODE(s, br_state, dctbl, return FALSE, label1); + if (s) { + CHECK_BIT_BUFFER(br_state, s, return FALSE); + r = GET_BITS(s); + s = HUFF_EXTEND(r, s); + } + + if (entropy->dc_needed[blkn]) { + /* Convert DC difference to actual value, update last_dc_val */ + int ci = cinfo->MCU_membership[blkn]; + s += state.last_dc_val[ci]; + state.last_dc_val[ci] = s; + /* Output the DC coefficient (assumes jpeg_natural_order[0] = 0) */ + (*block)[0] = (JCOEF) s; + } + + if (entropy->ac_needed[blkn]) { + + /* Section F.2.2.2: decode the AC coefficients */ + /* Since zeroes are skipped, output area must be cleared beforehand */ + for (k = 1; k < DCTSIZE2; k++) { + HUFF_DECODE(s, br_state, actbl, return FALSE, label2); + + r = s >> 4; + s &= 15; + + if (s) { + k += r; + CHECK_BIT_BUFFER(br_state, s, return FALSE); + r = GET_BITS(s); + s = HUFF_EXTEND(r, s); + /* Output coefficient in natural (dezigzagged) order. + * Note: the extra entries in jpeg_natural_order[] will save us + * if k >= DCTSIZE2, which could happen if the data is corrupted. + */ + (*block)[jpeg_natural_order[k]] = (JCOEF) s; + } else { + if (r != 15) + break; + k += 15; + } + } + + } else { + + /* Section F.2.2.2: decode the AC coefficients */ + /* In this path we just discard the values */ + for (k = 1; k < DCTSIZE2; k++) { + HUFF_DECODE(s, br_state, actbl, return FALSE, label3); + + r = s >> 4; + s &= 15; + + if (s) { + k += r; + CHECK_BIT_BUFFER(br_state, s, return FALSE); + DROP_BITS(s); + } else { + if (r != 15) + break; + k += 15; + } + } + + } + } + + /* Completed MCU, so update state */ + BITREAD_SAVE_STATE(cinfo,entropy->bitstate); + ASSIGN_STATE(entropy->saved, state); + } + + /* Account for restart interval (no-op if not using restarts) */ + entropy->restarts_to_go--; + + return TRUE; +} + + +/* + * Module initialization routine for Huffman entropy decoding. + */ + +GLOBAL(void) +jinit_huff_decoder (j_decompress_ptr cinfo) +{ + huff_entropy_ptr entropy; + int i; + + entropy = (huff_entropy_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(huff_entropy_decoder)); + cinfo->entropy = (struct jpeg_entropy_decoder *) entropy; + entropy->pub.start_pass = start_pass_huff_decoder; + entropy->pub.decode_mcu = decode_mcu; + + /* Mark tables unallocated */ + for (i = 0; i < NUM_HUFF_TBLS; i++) { + entropy->dc_derived_tbls[i] = entropy->ac_derived_tbls[i] = NULL; + } +} diff --git a/jpeg/JDHUFF.H b/jpeg/JDHUFF.H new file mode 100644 index 0000000..6bbea4c --- /dev/null +++ b/jpeg/JDHUFF.H @@ -0,0 +1,201 @@ +/* + * jdhuff.h + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains declarations for Huffman entropy decoding routines + * that are shared between the sequential decoder (jdhuff.c) and the + * progressive decoder (jdphuff.c). No other modules need to see these. + */ + +/* Short forms of external names for systems with brain-damaged linkers. */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jpeg_make_d_derived_tbl jMkDDerived +#define jpeg_fill_bit_buffer jFilBitBuf +#define jpeg_huff_decode jHufDecode +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + + +/* Derived data constructed for each Huffman table */ + +#define HUFF_LOOKAHEAD 8 /* # of bits of lookahead */ + +typedef struct { + /* Basic tables: (element [0] of each array is unused) */ + INT32 maxcode[18]; /* largest code of length k (-1 if none) */ + /* (maxcode[17] is a sentinel to ensure jpeg_huff_decode terminates) */ + INT32 valoffset[17]; /* huffval[] offset for codes of length k */ + /* valoffset[k] = huffval[] index of 1st symbol of code length k, less + * the smallest code of length k; so given a code of length k, the + * corresponding symbol is huffval[code + valoffset[k]] + */ + + /* Link to public Huffman table (needed only in jpeg_huff_decode) */ + JHUFF_TBL *pub; + + /* Lookahead tables: indexed by the next HUFF_LOOKAHEAD bits of + * the input data stream. If the next Huffman code is no more + * than HUFF_LOOKAHEAD bits long, we can obtain its length and + * the corresponding symbol directly from these tables. + */ + int look_nbits[1< 32 bits on your machine, and shifting/masking longs is + * reasonably fast, making bit_buf_type be long and setting BIT_BUF_SIZE + * appropriately should be a win. Unfortunately we can't define the size + * with something like #define BIT_BUF_SIZE (sizeof(bit_buf_type)*8) + * because not all machines measure sizeof in 8-bit bytes. + */ + +typedef struct { /* Bitreading state saved across MCUs */ + bit_buf_type get_buffer; /* current bit-extraction buffer */ + int bits_left; /* # of unused bits in it */ +} bitread_perm_state; + +typedef struct { /* Bitreading working state within an MCU */ + /* Current data source location */ + /* We need a copy, rather than munging the original, in case of suspension */ + const JOCTET * next_input_byte; /* => next byte to read from source */ + size_t bytes_in_buffer; /* # of bytes remaining in source buffer */ + /* Bit input buffer --- note these values are kept in register variables, + * not in this struct, inside the inner loops. + */ + bit_buf_type get_buffer; /* current bit-extraction buffer */ + int bits_left; /* # of unused bits in it */ + /* Pointer needed by jpeg_fill_bit_buffer. */ + j_decompress_ptr cinfo; /* back link to decompress master record */ +} bitread_working_state; + +/* Macros to declare and load/save bitread local variables. */ +#define BITREAD_STATE_VARS \ + register bit_buf_type get_buffer; \ + register int bits_left; \ + bitread_working_state br_state + +#define BITREAD_LOAD_STATE(cinfop,permstate) \ + br_state.cinfo = cinfop; \ + br_state.next_input_byte = cinfop->src->next_input_byte; \ + br_state.bytes_in_buffer = cinfop->src->bytes_in_buffer; \ + get_buffer = permstate.get_buffer; \ + bits_left = permstate.bits_left; + +#define BITREAD_SAVE_STATE(cinfop,permstate) \ + cinfop->src->next_input_byte = br_state.next_input_byte; \ + cinfop->src->bytes_in_buffer = br_state.bytes_in_buffer; \ + permstate.get_buffer = get_buffer; \ + permstate.bits_left = bits_left + +/* + * These macros provide the in-line portion of bit fetching. + * Use CHECK_BIT_BUFFER to ensure there are N bits in get_buffer + * before using GET_BITS, PEEK_BITS, or DROP_BITS. + * The variables get_buffer and bits_left are assumed to be locals, + * but the state struct might not be (jpeg_huff_decode needs this). + * CHECK_BIT_BUFFER(state,n,action); + * Ensure there are N bits in get_buffer; if suspend, take action. + * val = GET_BITS(n); + * Fetch next N bits. + * val = PEEK_BITS(n); + * Fetch next N bits without removing them from the buffer. + * DROP_BITS(n); + * Discard next N bits. + * The value N should be a simple variable, not an expression, because it + * is evaluated multiple times. + */ + +#define CHECK_BIT_BUFFER(state,nbits,action) \ + { if (bits_left < (nbits)) { \ + if (! jpeg_fill_bit_buffer(&(state),get_buffer,bits_left,nbits)) \ + { action; } \ + get_buffer = (state).get_buffer; bits_left = (state).bits_left; } } + +#define GET_BITS(nbits) \ + (((int) (get_buffer >> (bits_left -= (nbits)))) & ((1<<(nbits))-1)) + +#define PEEK_BITS(nbits) \ + (((int) (get_buffer >> (bits_left - (nbits)))) & ((1<<(nbits))-1)) + +#define DROP_BITS(nbits) \ + (bits_left -= (nbits)) + +/* Load up the bit buffer to a depth of at least nbits */ +EXTERN(boolean) jpeg_fill_bit_buffer + JPP((bitread_working_state * state, register bit_buf_type get_buffer, + register int bits_left, int nbits)); + + +/* + * Code for extracting next Huffman-coded symbol from input bit stream. + * Again, this is time-critical and we make the main paths be macros. + * + * We use a lookahead table to process codes of up to HUFF_LOOKAHEAD bits + * without looping. Usually, more than 95% of the Huffman codes will be 8 + * or fewer bits long. The few overlength codes are handled with a loop, + * which need not be inline code. + * + * Notes about the HUFF_DECODE macro: + * 1. Near the end of the data segment, we may fail to get enough bits + * for a lookahead. In that case, we do it the hard way. + * 2. If the lookahead table contains no entry, the next code must be + * more than HUFF_LOOKAHEAD bits long. + * 3. jpeg_huff_decode returns -1 if forced to suspend. + */ + +#define HUFF_DECODE(result,state,htbl,failaction,slowlabel) \ +{ register int nb, look; \ + if (bits_left < HUFF_LOOKAHEAD) { \ + if (! jpeg_fill_bit_buffer(&state,get_buffer,bits_left, 0)) {failaction;} \ + get_buffer = state.get_buffer; bits_left = state.bits_left; \ + if (bits_left < HUFF_LOOKAHEAD) { \ + nb = 1; goto slowlabel; \ + } \ + } \ + look = PEEK_BITS(HUFF_LOOKAHEAD); \ + if ((nb = htbl->look_nbits[look]) != 0) { \ + DROP_BITS(nb); \ + result = htbl->look_sym[look]; \ + } else { \ + nb = HUFF_LOOKAHEAD+1; \ +slowlabel: \ + if ((result=jpeg_huff_decode(&state,get_buffer,bits_left,htbl,nb)) < 0) \ + { failaction; } \ + get_buffer = state.get_buffer; bits_left = state.bits_left; \ + } \ +} + +/* Out-of-line case for Huffman code fetching */ +EXTERN(int) jpeg_huff_decode + JPP((bitread_working_state * state, register bit_buf_type get_buffer, + register int bits_left, d_derived_tbl * htbl, int min_bits)); diff --git a/jpeg/JDINPUT.C b/jpeg/JDINPUT.C new file mode 100644 index 0000000..3b151d9 --- /dev/null +++ b/jpeg/JDINPUT.C @@ -0,0 +1,381 @@ +/* + * jdinput.c + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains input control logic for the JPEG decompressor. + * These routines are concerned with controlling the decompressor's input + * processing (marker reading and coefficient decoding). The actual input + * reading is done in jdmarker.c, jdhuff.c, and jdphuff.c. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Private state */ + +typedef struct { + struct jpeg_input_controller pub; /* public fields */ + + boolean inheaders; /* TRUE until first SOS is reached */ +} my_input_controller; + +typedef my_input_controller * my_inputctl_ptr; + + +/* Forward declarations */ +METHODDEF(int) consume_markers JPP((j_decompress_ptr cinfo)); + + +/* + * Routines to calculate various quantities related to the size of the image. + */ + +LOCAL(void) +initial_setup (j_decompress_ptr cinfo) +/* Called once, when first SOS marker is reached */ +{ + int ci; + jpeg_component_info *compptr; + + /* Make sure image isn't bigger than I can handle */ + if ((long) cinfo->image_height > (long) JPEG_MAX_DIMENSION || + (long) cinfo->image_width > (long) JPEG_MAX_DIMENSION) + ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION); + + /* For now, precision must match compiled-in value... */ + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + + /* Check that number of components won't exceed internal array sizes */ + if (cinfo->num_components > MAX_COMPONENTS) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, + MAX_COMPONENTS); + + /* Compute maximum sampling factors; check factor validity */ + cinfo->max_h_samp_factor = 1; + cinfo->max_v_samp_factor = 1; + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR || + compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR) + ERREXIT(cinfo, JERR_BAD_SAMPLING); + cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor, + compptr->h_samp_factor); + cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor, + compptr->v_samp_factor); + } + + /* We initialize DCT_scaled_size and min_DCT_scaled_size to DCTSIZE. + * In the full decompressor, this will be overridden by jdmaster.c; + * but in the transcoder, jdmaster.c is not used, so we must do it here. + */ + cinfo->min_DCT_scaled_size = DCTSIZE; + + /* Compute dimensions of components */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + compptr->DCT_scaled_size = DCTSIZE; + /* Size in DCT blocks */ + compptr->width_in_blocks = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, + (long) (cinfo->max_h_samp_factor * DCTSIZE)); + compptr->height_in_blocks = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, + (long) (cinfo->max_v_samp_factor * DCTSIZE)); + /* downsampled_width and downsampled_height will also be overridden by + * jdmaster.c if we are doing full decompression. The transcoder library + * doesn't use these values, but the calling application might. + */ + /* Size in samples */ + compptr->downsampled_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, + (long) cinfo->max_h_samp_factor); + compptr->downsampled_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, + (long) cinfo->max_v_samp_factor); + /* Mark component needed, until color conversion says otherwise */ + compptr->component_needed = TRUE; + /* Mark no quantization table yet saved for component */ + compptr->quant_table = NULL; + } + + /* Compute number of fully interleaved MCU rows. */ + cinfo->total_iMCU_rows = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, + (long) (cinfo->max_v_samp_factor*DCTSIZE)); + + /* Decide whether file contains multiple scans */ + if (cinfo->comps_in_scan < cinfo->num_components || cinfo->progressive_mode) + cinfo->inputctl->has_multiple_scans = TRUE; + else + cinfo->inputctl->has_multiple_scans = FALSE; +} + + +LOCAL(void) +per_scan_setup (j_decompress_ptr cinfo) +/* Do computations that are needed before processing a JPEG scan */ +/* cinfo->comps_in_scan and cinfo->cur_comp_info[] were set from SOS marker */ +{ + int ci, mcublks, tmp; + jpeg_component_info *compptr; + + if (cinfo->comps_in_scan == 1) { + + /* Noninterleaved (single-component) scan */ + compptr = cinfo->cur_comp_info[0]; + + /* Overall image size in MCUs */ + cinfo->MCUs_per_row = compptr->width_in_blocks; + cinfo->MCU_rows_in_scan = compptr->height_in_blocks; + + /* For noninterleaved scan, always one block per MCU */ + compptr->MCU_width = 1; + compptr->MCU_height = 1; + compptr->MCU_blocks = 1; + compptr->MCU_sample_width = compptr->DCT_scaled_size; + compptr->last_col_width = 1; + /* For noninterleaved scans, it is convenient to define last_row_height + * as the number of block rows present in the last iMCU row. + */ + tmp = (int) (compptr->height_in_blocks % compptr->v_samp_factor); + if (tmp == 0) tmp = compptr->v_samp_factor; + compptr->last_row_height = tmp; + + /* Prepare array describing MCU composition */ + cinfo->blocks_in_MCU = 1; + cinfo->MCU_membership[0] = 0; + + } else { + + /* Interleaved (multi-component) scan */ + if (cinfo->comps_in_scan <= 0 || cinfo->comps_in_scan > MAX_COMPS_IN_SCAN) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->comps_in_scan, + MAX_COMPS_IN_SCAN); + + /* Overall image size in MCUs */ + cinfo->MCUs_per_row = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width, + (long) (cinfo->max_h_samp_factor*DCTSIZE)); + cinfo->MCU_rows_in_scan = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, + (long) (cinfo->max_v_samp_factor*DCTSIZE)); + + cinfo->blocks_in_MCU = 0; + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* Sampling factors give # of blocks of component in each MCU */ + compptr->MCU_width = compptr->h_samp_factor; + compptr->MCU_height = compptr->v_samp_factor; + compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height; + compptr->MCU_sample_width = compptr->MCU_width * compptr->DCT_scaled_size; + /* Figure number of non-dummy blocks in last MCU column & row */ + tmp = (int) (compptr->width_in_blocks % compptr->MCU_width); + if (tmp == 0) tmp = compptr->MCU_width; + compptr->last_col_width = tmp; + tmp = (int) (compptr->height_in_blocks % compptr->MCU_height); + if (tmp == 0) tmp = compptr->MCU_height; + compptr->last_row_height = tmp; + /* Prepare array describing MCU composition */ + mcublks = compptr->MCU_blocks; + if (cinfo->blocks_in_MCU + mcublks > D_MAX_BLOCKS_IN_MCU) + ERREXIT(cinfo, JERR_BAD_MCU_SIZE); + while (mcublks-- > 0) { + cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci; + } + } + + } +} + + +/* + * Save away a copy of the Q-table referenced by each component present + * in the current scan, unless already saved during a prior scan. + * + * In a multiple-scan JPEG file, the encoder could assign different components + * the same Q-table slot number, but change table definitions between scans + * so that each component uses a different Q-table. (The IJG encoder is not + * currently capable of doing this, but other encoders might.) Since we want + * to be able to dequantize all the components at the end of the file, this + * means that we have to save away the table actually used for each component. + * We do this by copying the table at the start of the first scan containing + * the component. + * The JPEG spec prohibits the encoder from changing the contents of a Q-table + * slot between scans of a component using that slot. If the encoder does so + * anyway, this decoder will simply use the Q-table values that were current + * at the start of the first scan for the component. + * + * The decompressor output side looks only at the saved quant tables, + * not at the current Q-table slots. + */ + +LOCAL(void) +latch_quant_tables (j_decompress_ptr cinfo) +{ + int ci, qtblno; + jpeg_component_info *compptr; + JQUANT_TBL * qtbl; + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* No work if we already saved Q-table for this component */ + if (compptr->quant_table != NULL) + continue; + /* Make sure specified quantization table is present */ + qtblno = compptr->quant_tbl_no; + if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS || + cinfo->quant_tbl_ptrs[qtblno] == NULL) + ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno); + /* OK, save away the quantization table */ + qtbl = (JQUANT_TBL *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(JQUANT_TBL)); + MEMCOPY(qtbl, cinfo->quant_tbl_ptrs[qtblno], SIZEOF(JQUANT_TBL)); + compptr->quant_table = qtbl; + } +} + + +/* + * Initialize the input modules to read a scan of compressed data. + * The first call to this is done by jdmaster.c after initializing + * the entire decompressor (during jpeg_start_decompress). + * Subsequent calls come from consume_markers, below. + */ + +METHODDEF(void) +start_input_pass (j_decompress_ptr cinfo) +{ + per_scan_setup(cinfo); + latch_quant_tables(cinfo); + (*cinfo->entropy->start_pass) (cinfo); + (*cinfo->coef->start_input_pass) (cinfo); + cinfo->inputctl->consume_input = cinfo->coef->consume_data; +} + + +/* + * Finish up after inputting a compressed-data scan. + * This is called by the coefficient controller after it's read all + * the expected data of the scan. + */ + +METHODDEF(void) +finish_input_pass (j_decompress_ptr cinfo) +{ + cinfo->inputctl->consume_input = consume_markers; +} + + +/* + * Read JPEG markers before, between, or after compressed-data scans. + * Change state as necessary when a new scan is reached. + * Return value is JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI. + * + * The consume_input method pointer points either here or to the + * coefficient controller's consume_data routine, depending on whether + * we are reading a compressed data segment or inter-segment markers. + */ + +METHODDEF(int) +consume_markers (j_decompress_ptr cinfo) +{ + my_inputctl_ptr inputctl = (my_inputctl_ptr) cinfo->inputctl; + int val; + + if (inputctl->pub.eoi_reached) /* After hitting EOI, read no further */ + return JPEG_REACHED_EOI; + + val = (*cinfo->marker->read_markers) (cinfo); + + switch (val) { + case JPEG_REACHED_SOS: /* Found SOS */ + if (inputctl->inheaders) { /* 1st SOS */ + initial_setup(cinfo); + inputctl->inheaders = FALSE; + /* Note: start_input_pass must be called by jdmaster.c + * before any more input can be consumed. jdapimin.c is + * responsible for enforcing this sequencing. + */ + } else { /* 2nd or later SOS marker */ + if (! inputctl->pub.has_multiple_scans) + ERREXIT(cinfo, JERR_EOI_EXPECTED); /* Oops, I wasn't expecting this! */ + start_input_pass(cinfo); + } + break; + case JPEG_REACHED_EOI: /* Found EOI */ + inputctl->pub.eoi_reached = TRUE; + if (inputctl->inheaders) { /* Tables-only datastream, apparently */ + if (cinfo->marker->saw_SOF) + ERREXIT(cinfo, JERR_SOF_NO_SOS); + } else { + /* Prevent infinite loop in coef ctlr's decompress_data routine + * if user set output_scan_number larger than number of scans. + */ + if (cinfo->output_scan_number > cinfo->input_scan_number) + cinfo->output_scan_number = cinfo->input_scan_number; + } + break; + case JPEG_SUSPENDED: + break; + } + + return val; +} + + +/* + * Reset state to begin a fresh datastream. + */ + +METHODDEF(void) +reset_input_controller (j_decompress_ptr cinfo) +{ + my_inputctl_ptr inputctl = (my_inputctl_ptr) cinfo->inputctl; + + inputctl->pub.consume_input = consume_markers; + inputctl->pub.has_multiple_scans = FALSE; /* "unknown" would be better */ + inputctl->pub.eoi_reached = FALSE; + inputctl->inheaders = TRUE; + /* Reset other modules */ + (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); + (*cinfo->marker->reset_marker_reader) (cinfo); + /* Reset progression state -- would be cleaner if entropy decoder did this */ + cinfo->coef_bits = NULL; +} + + +/* + * Initialize the input controller module. + * This is called only once, when the decompression object is created. + */ + +GLOBAL(void) +jinit_input_controller (j_decompress_ptr cinfo) +{ + my_inputctl_ptr inputctl; + + /* Create subobject in permanent pool */ + inputctl = (my_inputctl_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + SIZEOF(my_input_controller)); + cinfo->inputctl = (struct jpeg_input_controller *) inputctl; + /* Initialize method pointers */ + inputctl->pub.consume_input = consume_markers; + inputctl->pub.reset_input_controller = reset_input_controller; + inputctl->pub.start_input_pass = start_input_pass; + inputctl->pub.finish_input_pass = finish_input_pass; + /* Initialize state: can't use reset_input_controller since we don't + * want to try to reset other modules yet. + */ + inputctl->pub.has_multiple_scans = FALSE; /* "unknown" would be better */ + inputctl->pub.eoi_reached = FALSE; + inputctl->inheaders = TRUE; +} diff --git a/jpeg/JDMAINCT.C b/jpeg/JDMAINCT.C new file mode 100644 index 0000000..e410de1 --- /dev/null +++ b/jpeg/JDMAINCT.C @@ -0,0 +1,512 @@ +/* + * jdmainct.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the main buffer controller for decompression. + * The main buffer lies between the JPEG decompressor proper and the + * post-processor; it holds downsampled data in the JPEG colorspace. + * + * Note that this code is bypassed in raw-data mode, since the application + * supplies the equivalent of the main buffer in that case. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* + * In the current system design, the main buffer need never be a full-image + * buffer; any full-height buffers will be found inside the coefficient or + * postprocessing controllers. Nonetheless, the main controller is not + * trivial. Its responsibility is to provide context rows for upsampling/ + * rescaling, and doing this in an efficient fashion is a bit tricky. + * + * Postprocessor input data is counted in "row groups". A row group + * is defined to be (v_samp_factor * DCT_scaled_size / min_DCT_scaled_size) + * sample rows of each component. (We require DCT_scaled_size values to be + * chosen such that these numbers are integers. In practice DCT_scaled_size + * values will likely be powers of two, so we actually have the stronger + * condition that DCT_scaled_size / min_DCT_scaled_size is an integer.) + * Upsampling will typically produce max_v_samp_factor pixel rows from each + * row group (times any additional scale factor that the upsampler is + * applying). + * + * The coefficient controller will deliver data to us one iMCU row at a time; + * each iMCU row contains v_samp_factor * DCT_scaled_size sample rows, or + * exactly min_DCT_scaled_size row groups. (This amount of data corresponds + * to one row of MCUs when the image is fully interleaved.) Note that the + * number of sample rows varies across components, but the number of row + * groups does not. Some garbage sample rows may be included in the last iMCU + * row at the bottom of the image. + * + * Depending on the vertical scaling algorithm used, the upsampler may need + * access to the sample row(s) above and below its current input row group. + * The upsampler is required to set need_context_rows TRUE at global selection + * time if so. When need_context_rows is FALSE, this controller can simply + * obtain one iMCU row at a time from the coefficient controller and dole it + * out as row groups to the postprocessor. + * + * When need_context_rows is TRUE, this controller guarantees that the buffer + * passed to postprocessing contains at least one row group's worth of samples + * above and below the row group(s) being processed. Note that the context + * rows "above" the first passed row group appear at negative row offsets in + * the passed buffer. At the top and bottom of the image, the required + * context rows are manufactured by duplicating the first or last real sample + * row; this avoids having special cases in the upsampling inner loops. + * + * The amount of context is fixed at one row group just because that's a + * convenient number for this controller to work with. The existing + * upsamplers really only need one sample row of context. An upsampler + * supporting arbitrary output rescaling might wish for more than one row + * group of context when shrinking the image; tough, we don't handle that. + * (This is justified by the assumption that downsizing will be handled mostly + * by adjusting the DCT_scaled_size values, so that the actual scale factor at + * the upsample step needn't be much less than one.) + * + * To provide the desired context, we have to retain the last two row groups + * of one iMCU row while reading in the next iMCU row. (The last row group + * can't be processed until we have another row group for its below-context, + * and so we have to save the next-to-last group too for its above-context.) + * We could do this most simply by copying data around in our buffer, but + * that'd be very slow. We can avoid copying any data by creating a rather + * strange pointer structure. Here's how it works. We allocate a workspace + * consisting of M+2 row groups (where M = min_DCT_scaled_size is the number + * of row groups per iMCU row). We create two sets of redundant pointers to + * the workspace. Labeling the physical row groups 0 to M+1, the synthesized + * pointer lists look like this: + * M+1 M-1 + * master pointer --> 0 master pointer --> 0 + * 1 1 + * ... ... + * M-3 M-3 + * M-2 M + * M-1 M+1 + * M M-2 + * M+1 M-1 + * 0 0 + * We read alternate iMCU rows using each master pointer; thus the last two + * row groups of the previous iMCU row remain un-overwritten in the workspace. + * The pointer lists are set up so that the required context rows appear to + * be adjacent to the proper places when we pass the pointer lists to the + * upsampler. + * + * The above pictures describe the normal state of the pointer lists. + * At top and bottom of the image, we diddle the pointer lists to duplicate + * the first or last sample row as necessary (this is cheaper than copying + * sample rows around). + * + * This scheme breaks down if M < 2, ie, min_DCT_scaled_size is 1. In that + * situation each iMCU row provides only one row group so the buffering logic + * must be different (eg, we must read two iMCU rows before we can emit the + * first row group). For now, we simply do not support providing context + * rows when min_DCT_scaled_size is 1. That combination seems unlikely to + * be worth providing --- if someone wants a 1/8th-size preview, they probably + * want it quick and dirty, so a context-free upsampler is sufficient. + */ + + +/* Private buffer controller object */ + +typedef struct { + struct jpeg_d_main_controller pub; /* public fields */ + + /* Pointer to allocated workspace (M or M+2 row groups). */ + JSAMPARRAY buffer[MAX_COMPONENTS]; + + boolean buffer_full; /* Have we gotten an iMCU row from decoder? */ + JDIMENSION rowgroup_ctr; /* counts row groups output to postprocessor */ + + /* Remaining fields are only used in the context case. */ + + /* These are the master pointers to the funny-order pointer lists. */ + JSAMPIMAGE xbuffer[2]; /* pointers to weird pointer lists */ + + int whichptr; /* indicates which pointer set is now in use */ + int context_state; /* process_data state machine status */ + JDIMENSION rowgroups_avail; /* row groups available to postprocessor */ + JDIMENSION iMCU_row_ctr; /* counts iMCU rows to detect image top/bot */ +} my_main_controller; + +typedef my_main_controller * my_main_ptr; + +/* context_state values: */ +#define CTX_PREPARE_FOR_IMCU 0 /* need to prepare for MCU row */ +#define CTX_PROCESS_IMCU 1 /* feeding iMCU to postprocessor */ +#define CTX_POSTPONED_ROW 2 /* feeding postponed row group */ + + +/* Forward declarations */ +METHODDEF(void) process_data_simple_main + JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf, + JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); +METHODDEF(void) process_data_context_main + JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf, + JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); +#ifdef QUANT_2PASS_SUPPORTED +METHODDEF(void) process_data_crank_post + JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf, + JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); +#endif + + +LOCAL(void) +alloc_funny_pointers (j_decompress_ptr cinfo) +/* Allocate space for the funny pointer lists. + * This is done only once, not once per pass. + */ +{ + my_main_ptr main = (my_main_ptr) cinfo->main; + int ci, rgroup; + int M = cinfo->min_DCT_scaled_size; + jpeg_component_info *compptr; + JSAMPARRAY xbuf; + + /* Get top-level space for component array pointers. + * We alloc both arrays with one call to save a few cycles. + */ + main->xbuffer[0] = (JSAMPIMAGE) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + cinfo->num_components * 2 * SIZEOF(JSAMPARRAY)); + main->xbuffer[1] = main->xbuffer[0] + cinfo->num_components; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) / + cinfo->min_DCT_scaled_size; /* height of a row group of component */ + /* Get space for pointer lists --- M+4 row groups in each list. + * We alloc both pointer lists with one call to save a few cycles. + */ + xbuf = (JSAMPARRAY) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + 2 * (rgroup * (M + 4)) * SIZEOF(JSAMPROW)); + xbuf += rgroup; /* want one row group at negative offsets */ + main->xbuffer[0][ci] = xbuf; + xbuf += rgroup * (M + 4); + main->xbuffer[1][ci] = xbuf; + } +} + + +LOCAL(void) +make_funny_pointers (j_decompress_ptr cinfo) +/* Create the funny pointer lists discussed in the comments above. + * The actual workspace is already allocated (in main->buffer), + * and the space for the pointer lists is allocated too. + * This routine just fills in the curiously ordered lists. + * This will be repeated at the beginning of each pass. + */ +{ + my_main_ptr main = (my_main_ptr) cinfo->main; + int ci, i, rgroup; + int M = cinfo->min_DCT_scaled_size; + jpeg_component_info *compptr; + JSAMPARRAY buf, xbuf0, xbuf1; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) / + cinfo->min_DCT_scaled_size; /* height of a row group of component */ + xbuf0 = main->xbuffer[0][ci]; + xbuf1 = main->xbuffer[1][ci]; + /* First copy the workspace pointers as-is */ + buf = main->buffer[ci]; + for (i = 0; i < rgroup * (M + 2); i++) { + xbuf0[i] = xbuf1[i] = buf[i]; + } + /* In the second list, put the last four row groups in swapped order */ + for (i = 0; i < rgroup * 2; i++) { + xbuf1[rgroup*(M-2) + i] = buf[rgroup*M + i]; + xbuf1[rgroup*M + i] = buf[rgroup*(M-2) + i]; + } + /* The wraparound pointers at top and bottom will be filled later + * (see set_wraparound_pointers, below). Initially we want the "above" + * pointers to duplicate the first actual data line. This only needs + * to happen in xbuffer[0]. + */ + for (i = 0; i < rgroup; i++) { + xbuf0[i - rgroup] = xbuf0[0]; + } + } +} + + +LOCAL(void) +set_wraparound_pointers (j_decompress_ptr cinfo) +/* Set up the "wraparound" pointers at top and bottom of the pointer lists. + * This changes the pointer list state from top-of-image to the normal state. + */ +{ + my_main_ptr main = (my_main_ptr) cinfo->main; + int ci, i, rgroup; + int M = cinfo->min_DCT_scaled_size; + jpeg_component_info *compptr; + JSAMPARRAY xbuf0, xbuf1; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) / + cinfo->min_DCT_scaled_size; /* height of a row group of component */ + xbuf0 = main->xbuffer[0][ci]; + xbuf1 = main->xbuffer[1][ci]; + for (i = 0; i < rgroup; i++) { + xbuf0[i - rgroup] = xbuf0[rgroup*(M+1) + i]; + xbuf1[i - rgroup] = xbuf1[rgroup*(M+1) + i]; + xbuf0[rgroup*(M+2) + i] = xbuf0[i]; + xbuf1[rgroup*(M+2) + i] = xbuf1[i]; + } + } +} + + +LOCAL(void) +set_bottom_pointers (j_decompress_ptr cinfo) +/* Change the pointer lists to duplicate the last sample row at the bottom + * of the image. whichptr indicates which xbuffer holds the final iMCU row. + * Also sets rowgroups_avail to indicate number of nondummy row groups in row. + */ +{ + my_main_ptr main = (my_main_ptr) cinfo->main; + int ci, i, rgroup, iMCUheight, rows_left; + jpeg_component_info *compptr; + JSAMPARRAY xbuf; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Count sample rows in one iMCU row and in one row group */ + iMCUheight = compptr->v_samp_factor * compptr->DCT_scaled_size; + rgroup = iMCUheight / cinfo->min_DCT_scaled_size; + /* Count nondummy sample rows remaining for this component */ + rows_left = (int) (compptr->downsampled_height % (JDIMENSION) iMCUheight); + if (rows_left == 0) rows_left = iMCUheight; + /* Count nondummy row groups. Should get same answer for each component, + * so we need only do it once. + */ + if (ci == 0) { + main->rowgroups_avail = (JDIMENSION) ((rows_left-1) / rgroup + 1); + } + /* Duplicate the last real sample row rgroup*2 times; this pads out the + * last partial rowgroup and ensures at least one full rowgroup of context. + */ + xbuf = main->xbuffer[main->whichptr][ci]; + for (i = 0; i < rgroup * 2; i++) { + xbuf[rows_left + i] = xbuf[rows_left-1]; + } + } +} + + +/* + * Initialize for a processing pass. + */ + +METHODDEF(void) +start_pass_main (j_decompress_ptr cinfo, J_BUF_MODE pass_mode) +{ + my_main_ptr main = (my_main_ptr) cinfo->main; + + switch (pass_mode) { + case JBUF_PASS_THRU: + if (cinfo->upsample->need_context_rows) { + main->pub.process_data = process_data_context_main; + make_funny_pointers(cinfo); /* Create the xbuffer[] lists */ + main->whichptr = 0; /* Read first iMCU row into xbuffer[0] */ + main->context_state = CTX_PREPARE_FOR_IMCU; + main->iMCU_row_ctr = 0; + } else { + /* Simple case with no context needed */ + main->pub.process_data = process_data_simple_main; + } + main->buffer_full = FALSE; /* Mark buffer empty */ + main->rowgroup_ctr = 0; + break; +#ifdef QUANT_2PASS_SUPPORTED + case JBUF_CRANK_DEST: + /* For last pass of 2-pass quantization, just crank the postprocessor */ + main->pub.process_data = process_data_crank_post; + break; +#endif + default: + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + break; + } +} + + +/* + * Process some data. + * This handles the simple case where no context is required. + */ + +METHODDEF(void) +process_data_simple_main (j_decompress_ptr cinfo, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +{ + my_main_ptr main = (my_main_ptr) cinfo->main; + JDIMENSION rowgroups_avail; + + /* Read input data if we haven't filled the main buffer yet */ + if (! main->buffer_full) { + if (! (*cinfo->coef->decompress_data) (cinfo, main->buffer)) + return; /* suspension forced, can do nothing more */ + main->buffer_full = TRUE; /* OK, we have an iMCU row to work with */ + } + + /* There are always min_DCT_scaled_size row groups in an iMCU row. */ + rowgroups_avail = (JDIMENSION) cinfo->min_DCT_scaled_size; + /* Note: at the bottom of the image, we may pass extra garbage row groups + * to the postprocessor. The postprocessor has to check for bottom + * of image anyway (at row resolution), so no point in us doing it too. + */ + + /* Feed the postprocessor */ + (*cinfo->post->post_process_data) (cinfo, main->buffer, + &main->rowgroup_ctr, rowgroups_avail, + output_buf, out_row_ctr, out_rows_avail); + + /* Has postprocessor consumed all the data yet? If so, mark buffer empty */ + if (main->rowgroup_ctr >= rowgroups_avail) { + main->buffer_full = FALSE; + main->rowgroup_ctr = 0; + } +} + + +/* + * Process some data. + * This handles the case where context rows must be provided. + */ + +METHODDEF(void) +process_data_context_main (j_decompress_ptr cinfo, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +{ + my_main_ptr main = (my_main_ptr) cinfo->main; + + /* Read input data if we haven't filled the main buffer yet */ + if (! main->buffer_full) { + if (! (*cinfo->coef->decompress_data) (cinfo, + main->xbuffer[main->whichptr])) + return; /* suspension forced, can do nothing more */ + main->buffer_full = TRUE; /* OK, we have an iMCU row to work with */ + main->iMCU_row_ctr++; /* count rows received */ + } + + /* Postprocessor typically will not swallow all the input data it is handed + * in one call (due to filling the output buffer first). Must be prepared + * to exit and restart. This switch lets us keep track of how far we got. + * Note that each case falls through to the next on successful completion. + */ + switch (main->context_state) { + case CTX_POSTPONED_ROW: + /* Call postprocessor using previously set pointers for postponed row */ + (*cinfo->post->post_process_data) (cinfo, main->xbuffer[main->whichptr], + &main->rowgroup_ctr, main->rowgroups_avail, + output_buf, out_row_ctr, out_rows_avail); + if (main->rowgroup_ctr < main->rowgroups_avail) + return; /* Need to suspend */ + main->context_state = CTX_PREPARE_FOR_IMCU; + if (*out_row_ctr >= out_rows_avail) + return; /* Postprocessor exactly filled output buf */ + /*FALLTHROUGH*/ + case CTX_PREPARE_FOR_IMCU: + /* Prepare to process first M-1 row groups of this iMCU row */ + main->rowgroup_ctr = 0; + main->rowgroups_avail = (JDIMENSION) (cinfo->min_DCT_scaled_size - 1); + /* Check for bottom of image: if so, tweak pointers to "duplicate" + * the last sample row, and adjust rowgroups_avail to ignore padding rows. + */ + if (main->iMCU_row_ctr == cinfo->total_iMCU_rows) + set_bottom_pointers(cinfo); + main->context_state = CTX_PROCESS_IMCU; + /*FALLTHROUGH*/ + case CTX_PROCESS_IMCU: + /* Call postprocessor using previously set pointers */ + (*cinfo->post->post_process_data) (cinfo, main->xbuffer[main->whichptr], + &main->rowgroup_ctr, main->rowgroups_avail, + output_buf, out_row_ctr, out_rows_avail); + if (main->rowgroup_ctr < main->rowgroups_avail) + return; /* Need to suspend */ + /* After the first iMCU, change wraparound pointers to normal state */ + if (main->iMCU_row_ctr == 1) + set_wraparound_pointers(cinfo); + /* Prepare to load new iMCU row using other xbuffer list */ + main->whichptr ^= 1; /* 0=>1 or 1=>0 */ + main->buffer_full = FALSE; + /* Still need to process last row group of this iMCU row, */ + /* which is saved at index M+1 of the other xbuffer */ + main->rowgroup_ctr = (JDIMENSION) (cinfo->min_DCT_scaled_size + 1); + main->rowgroups_avail = (JDIMENSION) (cinfo->min_DCT_scaled_size + 2); + main->context_state = CTX_POSTPONED_ROW; + } +} + + +/* + * Process some data. + * Final pass of two-pass quantization: just call the postprocessor. + * Source data will be the postprocessor controller's internal buffer. + */ + +#ifdef QUANT_2PASS_SUPPORTED + +METHODDEF(void) +process_data_crank_post (j_decompress_ptr cinfo, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +{ + (*cinfo->post->post_process_data) (cinfo, (JSAMPIMAGE) NULL, + (JDIMENSION *) NULL, (JDIMENSION) 0, + output_buf, out_row_ctr, out_rows_avail); +} + +#endif /* QUANT_2PASS_SUPPORTED */ + + +/* + * Initialize main buffer controller. + */ + +GLOBAL(void) +jinit_d_main_controller (j_decompress_ptr cinfo, boolean need_full_buffer) +{ + my_main_ptr main; + int ci, rgroup, ngroups; + jpeg_component_info *compptr; + + main = (my_main_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_main_controller)); + cinfo->main = (struct jpeg_d_main_controller *) main; + main->pub.start_pass = start_pass_main; + + if (need_full_buffer) /* shouldn't happen */ + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + + /* Allocate the workspace. + * ngroups is the number of row groups we need. + */ + if (cinfo->upsample->need_context_rows) { + if (cinfo->min_DCT_scaled_size < 2) /* unsupported, see comments above */ + ERREXIT(cinfo, JERR_NOTIMPL); + alloc_funny_pointers(cinfo); /* Alloc space for xbuffer[] lists */ + ngroups = cinfo->min_DCT_scaled_size + 2; + } else { + ngroups = cinfo->min_DCT_scaled_size; + } + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) / + cinfo->min_DCT_scaled_size; /* height of a row group of component */ + main->buffer[ci] = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + compptr->width_in_blocks * compptr->DCT_scaled_size, + (JDIMENSION) (rgroup * ngroups)); + } +} diff --git a/jpeg/JDMASTER.C b/jpeg/JDMASTER.C new file mode 100644 index 0000000..d8a93a0 --- /dev/null +++ b/jpeg/JDMASTER.C @@ -0,0 +1,557 @@ +/* + * jdmaster.c + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains master control logic for the JPEG decompressor. + * These routines are concerned with selecting the modules to be executed + * and with determining the number of passes and the work to be done in each + * pass. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Private state */ + +typedef struct { + struct jpeg_decomp_master pub; /* public fields */ + + int pass_number; /* # of passes completed */ + + boolean using_merged_upsample; /* TRUE if using merged upsample/cconvert */ + + /* Saved references to initialized quantizer modules, + * in case we need to switch modes. + */ + struct jpeg_color_quantizer * quantizer_1pass; + struct jpeg_color_quantizer * quantizer_2pass; +} my_decomp_master; + +typedef my_decomp_master * my_master_ptr; + + +/* + * Determine whether merged upsample/color conversion should be used. + * CRUCIAL: this must match the actual capabilities of jdmerge.c! + */ + +LOCAL(boolean) +use_merged_upsample (j_decompress_ptr cinfo) +{ +#ifdef UPSAMPLE_MERGING_SUPPORTED + /* Merging is the equivalent of plain box-filter upsampling */ + if (cinfo->do_fancy_upsampling || cinfo->CCIR601_sampling) + return FALSE; + /* jdmerge.c only supports YCC=>RGB color conversion */ + if (cinfo->jpeg_color_space != JCS_YCbCr || cinfo->num_components != 3 || + cinfo->out_color_space != JCS_RGB || + cinfo->out_color_components != RGB_PIXELSIZE) + return FALSE; + /* and it only handles 2h1v or 2h2v sampling ratios */ + if (cinfo->comp_info[0].h_samp_factor != 2 || + cinfo->comp_info[1].h_samp_factor != 1 || + cinfo->comp_info[2].h_samp_factor != 1 || + cinfo->comp_info[0].v_samp_factor > 2 || + cinfo->comp_info[1].v_samp_factor != 1 || + cinfo->comp_info[2].v_samp_factor != 1) + return FALSE; + /* furthermore, it doesn't work if we've scaled the IDCTs differently */ + if (cinfo->comp_info[0].DCT_scaled_size != cinfo->min_DCT_scaled_size || + cinfo->comp_info[1].DCT_scaled_size != cinfo->min_DCT_scaled_size || + cinfo->comp_info[2].DCT_scaled_size != cinfo->min_DCT_scaled_size) + return FALSE; + /* ??? also need to test for upsample-time rescaling, when & if supported */ + return TRUE; /* by golly, it'll work... */ +#else + return FALSE; +#endif +} + + +/* + * Compute output image dimensions and related values. + * NOTE: this is exported for possible use by application. + * Hence it mustn't do anything that can't be done twice. + * Also note that it may be called before the master module is initialized! + */ + +GLOBAL(void) +jpeg_calc_output_dimensions (j_decompress_ptr cinfo) +/* Do computations that are needed before master selection phase */ +{ +#ifdef IDCT_SCALING_SUPPORTED + int ci; + jpeg_component_info *compptr; +#endif + + /* Prevent application from calling me at wrong times */ + if (cinfo->global_state != DSTATE_READY) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + +#ifdef IDCT_SCALING_SUPPORTED + + /* Compute actual output image dimensions and DCT scaling choices. */ + if (cinfo->scale_num * 8 <= cinfo->scale_denom) { + /* Provide 1/8 scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width, 8L); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, 8L); + cinfo->min_DCT_scaled_size = 1; + } else if (cinfo->scale_num * 4 <= cinfo->scale_denom) { + /* Provide 1/4 scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width, 4L); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, 4L); + cinfo->min_DCT_scaled_size = 2; + } else if (cinfo->scale_num * 2 <= cinfo->scale_denom) { + /* Provide 1/2 scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width, 2L); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, 2L); + cinfo->min_DCT_scaled_size = 4; + } else { + /* Provide 1/1 scaling */ + cinfo->output_width = cinfo->image_width; + cinfo->output_height = cinfo->image_height; + cinfo->min_DCT_scaled_size = DCTSIZE; + } + /* In selecting the actual DCT scaling for each component, we try to + * scale up the chroma components via IDCT scaling rather than upsampling. + * This saves time if the upsampler gets to use 1:1 scaling. + * Note this code assumes that the supported DCT scalings are powers of 2. + */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + int ssize = cinfo->min_DCT_scaled_size; + while (ssize < DCTSIZE && + (compptr->h_samp_factor * ssize * 2 <= + cinfo->max_h_samp_factor * cinfo->min_DCT_scaled_size) && + (compptr->v_samp_factor * ssize * 2 <= + cinfo->max_v_samp_factor * cinfo->min_DCT_scaled_size)) { + ssize = ssize * 2; + } + compptr->DCT_scaled_size = ssize; + } + + /* Recompute downsampled dimensions of components; + * application needs to know these if using raw downsampled data. + */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Size in samples, after IDCT scaling */ + compptr->downsampled_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * + (long) (compptr->h_samp_factor * compptr->DCT_scaled_size), + (long) (cinfo->max_h_samp_factor * DCTSIZE)); + compptr->downsampled_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * + (long) (compptr->v_samp_factor * compptr->DCT_scaled_size), + (long) (cinfo->max_v_samp_factor * DCTSIZE)); + } + +#else /* !IDCT_SCALING_SUPPORTED */ + + /* Hardwire it to "no scaling" */ + cinfo->output_width = cinfo->image_width; + cinfo->output_height = cinfo->image_height; + /* jdinput.c has already initialized DCT_scaled_size to DCTSIZE, + * and has computed unscaled downsampled_width and downsampled_height. + */ + +#endif /* IDCT_SCALING_SUPPORTED */ + + /* Report number of components in selected colorspace. */ + /* Probably this should be in the color conversion module... */ + switch (cinfo->out_color_space) { + case JCS_GRAYSCALE: + cinfo->out_color_components = 1; + break; + case JCS_RGB: +#if RGB_PIXELSIZE != 3 + cinfo->out_color_components = RGB_PIXELSIZE; + break; +#endif /* else share code with YCbCr */ + case JCS_YCbCr: + cinfo->out_color_components = 3; + break; + case JCS_CMYK: + case JCS_YCCK: + cinfo->out_color_components = 4; + break; + default: /* else must be same colorspace as in file */ + cinfo->out_color_components = cinfo->num_components; + break; + } + cinfo->output_components = (cinfo->quantize_colors ? 1 : + cinfo->out_color_components); + + /* See if upsampler will want to emit more than one row at a time */ + if (use_merged_upsample(cinfo)) + cinfo->rec_outbuf_height = cinfo->max_v_samp_factor; + else + cinfo->rec_outbuf_height = 1; +} + + +/* + * Several decompression processes need to range-limit values to the range + * 0..MAXJSAMPLE; the input value may fall somewhat outside this range + * due to noise introduced by quantization, roundoff error, etc. These + * processes are inner loops and need to be as fast as possible. On most + * machines, particularly CPUs with pipelines or instruction prefetch, + * a (subscript-check-less) C table lookup + * x = sample_range_limit[x]; + * is faster than explicit tests + * if (x < 0) x = 0; + * else if (x > MAXJSAMPLE) x = MAXJSAMPLE; + * These processes all use a common table prepared by the routine below. + * + * For most steps we can mathematically guarantee that the initial value + * of x is within MAXJSAMPLE+1 of the legal range, so a table running from + * -(MAXJSAMPLE+1) to 2*MAXJSAMPLE+1 is sufficient. But for the initial + * limiting step (just after the IDCT), a wildly out-of-range value is + * possible if the input data is corrupt. To avoid any chance of indexing + * off the end of memory and getting a bad-pointer trap, we perform the + * post-IDCT limiting thus: + * x = range_limit[x & MASK]; + * where MASK is 2 bits wider than legal sample data, ie 10 bits for 8-bit + * samples. Under normal circumstances this is more than enough range and + * a correct output will be generated; with bogus input data the mask will + * cause wraparound, and we will safely generate a bogus-but-in-range output. + * For the post-IDCT step, we want to convert the data from signed to unsigned + * representation by adding CENTERJSAMPLE at the same time that we limit it. + * So the post-IDCT limiting table ends up looking like this: + * CENTERJSAMPLE,CENTERJSAMPLE+1,...,MAXJSAMPLE, + * MAXJSAMPLE (repeat 2*(MAXJSAMPLE+1)-CENTERJSAMPLE times), + * 0 (repeat 2*(MAXJSAMPLE+1)-CENTERJSAMPLE times), + * 0,1,...,CENTERJSAMPLE-1 + * Negative inputs select values from the upper half of the table after + * masking. + * + * We can save some space by overlapping the start of the post-IDCT table + * with the simpler range limiting table. The post-IDCT table begins at + * sample_range_limit + CENTERJSAMPLE. + * + * Note that the table is allocated in near data space on PCs; it's small + * enough and used often enough to justify this. + */ + +LOCAL(void) +prepare_range_limit_table (j_decompress_ptr cinfo) +/* Allocate and fill in the sample_range_limit table */ +{ + JSAMPLE * table; + int i; + + table = (JSAMPLE *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (5 * (MAXJSAMPLE+1) + CENTERJSAMPLE) * SIZEOF(JSAMPLE)); + table += (MAXJSAMPLE+1); /* allow negative subscripts of simple table */ + cinfo->sample_range_limit = table; + /* First segment of "simple" table: limit[x] = 0 for x < 0 */ + MEMZERO(table - (MAXJSAMPLE+1), (MAXJSAMPLE+1) * SIZEOF(JSAMPLE)); + /* Main part of "simple" table: limit[x] = x */ + for (i = 0; i <= MAXJSAMPLE; i++) + table[i] = (JSAMPLE) i; + table += CENTERJSAMPLE; /* Point to where post-IDCT table starts */ + /* End of simple table, rest of first half of post-IDCT table */ + for (i = CENTERJSAMPLE; i < 2*(MAXJSAMPLE+1); i++) + table[i] = MAXJSAMPLE; + /* Second half of post-IDCT table */ + MEMZERO(table + (2 * (MAXJSAMPLE+1)), + (2 * (MAXJSAMPLE+1) - CENTERJSAMPLE) * SIZEOF(JSAMPLE)); + MEMCOPY(table + (4 * (MAXJSAMPLE+1) - CENTERJSAMPLE), + cinfo->sample_range_limit, CENTERJSAMPLE * SIZEOF(JSAMPLE)); +} + + +/* + * Master selection of decompression modules. + * This is done once at jpeg_start_decompress time. We determine + * which modules will be used and give them appropriate initialization calls. + * We also initialize the decompressor input side to begin consuming data. + * + * Since jpeg_read_header has finished, we know what is in the SOF + * and (first) SOS markers. We also have all the application parameter + * settings. + */ + +LOCAL(void) +master_selection (j_decompress_ptr cinfo) +{ + my_master_ptr master = (my_master_ptr) cinfo->master; + boolean use_c_buffer; + long samplesperrow; + JDIMENSION jd_samplesperrow; + + /* Initialize dimensions and other stuff */ + jpeg_calc_output_dimensions(cinfo); + prepare_range_limit_table(cinfo); + + /* Width of an output scanline must be representable as JDIMENSION. */ + samplesperrow = (long) cinfo->output_width * (long) cinfo->out_color_components; + jd_samplesperrow = (JDIMENSION) samplesperrow; + if ((long) jd_samplesperrow != samplesperrow) + ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); + + /* Initialize my private state */ + master->pass_number = 0; + master->using_merged_upsample = use_merged_upsample(cinfo); + + /* Color quantizer selection */ + master->quantizer_1pass = NULL; + master->quantizer_2pass = NULL; + /* No mode changes if not using buffered-image mode. */ + if (! cinfo->quantize_colors || ! cinfo->buffered_image) { + cinfo->enable_1pass_quant = FALSE; + cinfo->enable_external_quant = FALSE; + cinfo->enable_2pass_quant = FALSE; + } + if (cinfo->quantize_colors) { + if (cinfo->raw_data_out) + ERREXIT(cinfo, JERR_NOTIMPL); + /* 2-pass quantizer only works in 3-component color space. */ + if (cinfo->out_color_components != 3) { + cinfo->enable_1pass_quant = TRUE; + cinfo->enable_external_quant = FALSE; + cinfo->enable_2pass_quant = FALSE; + cinfo->colormap = NULL; + } else if (cinfo->colormap != NULL) { + cinfo->enable_external_quant = TRUE; + } else if (cinfo->two_pass_quantize) { + cinfo->enable_2pass_quant = TRUE; + } else { + cinfo->enable_1pass_quant = TRUE; + } + + if (cinfo->enable_1pass_quant) { +#ifdef QUANT_1PASS_SUPPORTED + jinit_1pass_quantizer(cinfo); + master->quantizer_1pass = cinfo->cquantize; +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } + + /* We use the 2-pass code to map to external colormaps. */ + if (cinfo->enable_2pass_quant || cinfo->enable_external_quant) { +#ifdef QUANT_2PASS_SUPPORTED + jinit_2pass_quantizer(cinfo); + master->quantizer_2pass = cinfo->cquantize; +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } + /* If both quantizers are initialized, the 2-pass one is left active; + * this is necessary for starting with quantization to an external map. + */ + } + + /* Post-processing: in particular, color conversion first */ + if (! cinfo->raw_data_out) { + if (master->using_merged_upsample) { +#ifdef UPSAMPLE_MERGING_SUPPORTED + jinit_merged_upsampler(cinfo); /* does color conversion too */ +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else { + jinit_color_deconverter(cinfo); + jinit_upsampler(cinfo); + } + jinit_d_post_controller(cinfo, cinfo->enable_2pass_quant); + } + /* Inverse DCT */ + jinit_inverse_dct(cinfo); + /* Entropy decoding: either Huffman or arithmetic coding. */ + if (cinfo->arith_code) { + ERREXIT(cinfo, JERR_ARITH_NOTIMPL); + } else { + if (cinfo->progressive_mode) { +#ifdef D_PROGRESSIVE_SUPPORTED + jinit_phuff_decoder(cinfo); +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else + jinit_huff_decoder(cinfo); + } + + /* Initialize principal buffer controllers. */ + use_c_buffer = cinfo->inputctl->has_multiple_scans || cinfo->buffered_image; + jinit_d_coef_controller(cinfo, use_c_buffer); + + if (! cinfo->raw_data_out) + jinit_d_main_controller(cinfo, FALSE /* never need full buffer here */); + + /* We can now tell the memory manager to allocate virtual arrays. */ + (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); + + /* Initialize input side of decompressor to consume first scan. */ + (*cinfo->inputctl->start_input_pass) (cinfo); + +#ifdef D_MULTISCAN_FILES_SUPPORTED + /* If jpeg_start_decompress will read the whole file, initialize + * progress monitoring appropriately. The input step is counted + * as one pass. + */ + if (cinfo->progress != NULL && ! cinfo->buffered_image && + cinfo->inputctl->has_multiple_scans) { + int nscans; + /* Estimate number of scans to set pass_limit. */ + if (cinfo->progressive_mode) { + /* Arbitrarily estimate 2 interleaved DC scans + 3 AC scans/component. */ + nscans = 2 + 3 * cinfo->num_components; + } else { + /* For a nonprogressive multiscan file, estimate 1 scan per component. */ + nscans = cinfo->num_components; + } + cinfo->progress->pass_counter = 0L; + cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows * nscans; + cinfo->progress->completed_passes = 0; + cinfo->progress->total_passes = (cinfo->enable_2pass_quant ? 3 : 2); + /* Count the input pass as done */ + master->pass_number++; + } +#endif /* D_MULTISCAN_FILES_SUPPORTED */ +} + + +/* + * Per-pass setup. + * This is called at the beginning of each output pass. We determine which + * modules will be active during this pass and give them appropriate + * start_pass calls. We also set is_dummy_pass to indicate whether this + * is a "real" output pass or a dummy pass for color quantization. + * (In the latter case, jdapistd.c will crank the pass to completion.) + */ + +METHODDEF(void) +prepare_for_output_pass (j_decompress_ptr cinfo) +{ + my_master_ptr master = (my_master_ptr) cinfo->master; + + if (master->pub.is_dummy_pass) { +#ifdef QUANT_2PASS_SUPPORTED + /* Final pass of 2-pass quantization */ + master->pub.is_dummy_pass = FALSE; + (*cinfo->cquantize->start_pass) (cinfo, FALSE); + (*cinfo->post->start_pass) (cinfo, JBUF_CRANK_DEST); + (*cinfo->main->start_pass) (cinfo, JBUF_CRANK_DEST); +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif /* QUANT_2PASS_SUPPORTED */ + } else { + if (cinfo->quantize_colors && cinfo->colormap == NULL) { + /* Select new quantization method */ + if (cinfo->two_pass_quantize && cinfo->enable_2pass_quant) { + cinfo->cquantize = master->quantizer_2pass; + master->pub.is_dummy_pass = TRUE; + } else if (cinfo->enable_1pass_quant) { + cinfo->cquantize = master->quantizer_1pass; + } else { + ERREXIT(cinfo, JERR_MODE_CHANGE); + } + } + (*cinfo->idct->start_pass) (cinfo); + (*cinfo->coef->start_output_pass) (cinfo); + if (! cinfo->raw_data_out) { + if (! master->using_merged_upsample) + (*cinfo->cconvert->start_pass) (cinfo); + (*cinfo->upsample->start_pass) (cinfo); + if (cinfo->quantize_colors) + (*cinfo->cquantize->start_pass) (cinfo, master->pub.is_dummy_pass); + (*cinfo->post->start_pass) (cinfo, + (master->pub.is_dummy_pass ? JBUF_SAVE_AND_PASS : JBUF_PASS_THRU)); + (*cinfo->main->start_pass) (cinfo, JBUF_PASS_THRU); + } + } + + /* Set up progress monitor's pass info if present */ + if (cinfo->progress != NULL) { + cinfo->progress->completed_passes = master->pass_number; + cinfo->progress->total_passes = master->pass_number + + (master->pub.is_dummy_pass ? 2 : 1); + /* In buffered-image mode, we assume one more output pass if EOI not + * yet reached, but no more passes if EOI has been reached. + */ + if (cinfo->buffered_image && ! cinfo->inputctl->eoi_reached) { + cinfo->progress->total_passes += (cinfo->enable_2pass_quant ? 2 : 1); + } + } +} + + +/* + * Finish up at end of an output pass. + */ + +METHODDEF(void) +finish_output_pass (j_decompress_ptr cinfo) +{ + my_master_ptr master = (my_master_ptr) cinfo->master; + + if (cinfo->quantize_colors) + (*cinfo->cquantize->finish_pass) (cinfo); + master->pass_number++; +} + + +#ifdef D_MULTISCAN_FILES_SUPPORTED + +/* + * Switch to a new external colormap between output passes. + */ + +GLOBAL(void) +jpeg_new_colormap (j_decompress_ptr cinfo) +{ + my_master_ptr master = (my_master_ptr) cinfo->master; + + /* Prevent application from calling me at wrong times */ + if (cinfo->global_state != DSTATE_BUFIMAGE) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + if (cinfo->quantize_colors && cinfo->enable_external_quant && + cinfo->colormap != NULL) { + /* Select 2-pass quantizer for external colormap use */ + cinfo->cquantize = master->quantizer_2pass; + /* Notify quantizer of colormap change */ + (*cinfo->cquantize->new_color_map) (cinfo); + master->pub.is_dummy_pass = FALSE; /* just in case */ + } else + ERREXIT(cinfo, JERR_MODE_CHANGE); +} + +#endif /* D_MULTISCAN_FILES_SUPPORTED */ + + +/* + * Initialize master decompression control and select active modules. + * This is performed at the start of jpeg_start_decompress. + */ + +GLOBAL(void) +jinit_master_decompress (j_decompress_ptr cinfo) +{ + my_master_ptr master; + + master = (my_master_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_decomp_master)); + cinfo->master = (struct jpeg_decomp_master *) master; + master->pub.prepare_for_output_pass = prepare_for_output_pass; + master->pub.finish_output_pass = finish_output_pass; + + master->pub.is_dummy_pass = FALSE; + + master_selection(cinfo); +} diff --git a/jpeg/JDMERGE.C b/jpeg/JDMERGE.C new file mode 100644 index 0000000..915633f --- /dev/null +++ b/jpeg/JDMERGE.C @@ -0,0 +1,400 @@ +/* + * jdmerge.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains code for merged upsampling/color conversion. + * + * This file combines functions from jdsample.c and jdcolor.c; + * read those files first to understand what's going on. + * + * When the chroma components are to be upsampled by simple replication + * (ie, box filtering), we can save some work in color conversion by + * calculating all the output pixels corresponding to a pair of chroma + * samples at one time. In the conversion equations + * R = Y + K1 * Cr + * G = Y + K2 * Cb + K3 * Cr + * B = Y + K4 * Cb + * only the Y term varies among the group of pixels corresponding to a pair + * of chroma samples, so the rest of the terms can be calculated just once. + * At typical sampling ratios, this eliminates half or three-quarters of the + * multiplications needed for color conversion. + * + * This file currently provides implementations for the following cases: + * YCbCr => RGB color conversion only. + * Sampling ratios of 2h1v or 2h2v. + * No scaling needed at upsample time. + * Corner-aligned (non-CCIR601) sampling alignment. + * Other special cases could be added, but in most applications these are + * the only common cases. (For uncommon cases we fall back on the more + * general code in jdsample.c and jdcolor.c.) + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + +#ifdef UPSAMPLE_MERGING_SUPPORTED + + +/* Private subobject */ + +typedef struct { + struct jpeg_upsampler pub; /* public fields */ + + /* Pointer to routine to do actual upsampling/conversion of one row group */ + JMETHOD(void, upmethod, (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, + JSAMPARRAY output_buf)); + + /* Private state for YCC->RGB conversion */ + int * Cr_r_tab; /* => table for Cr to R conversion */ + int * Cb_b_tab; /* => table for Cb to B conversion */ + INT32 * Cr_g_tab; /* => table for Cr to G conversion */ + INT32 * Cb_g_tab; /* => table for Cb to G conversion */ + + /* For 2:1 vertical sampling, we produce two output rows at a time. + * We need a "spare" row buffer to hold the second output row if the + * application provides just a one-row buffer; we also use the spare + * to discard the dummy last row if the image height is odd. + */ + JSAMPROW spare_row; + boolean spare_full; /* T if spare buffer is occupied */ + + JDIMENSION out_row_width; /* samples per output row */ + JDIMENSION rows_to_go; /* counts rows remaining in image */ +} my_upsampler; + +typedef my_upsampler * my_upsample_ptr; + +#define SCALEBITS 16 /* speediest right-shift on some machines */ +#define ONE_HALF ((INT32) 1 << (SCALEBITS-1)) +#define FIX(x) ((INT32) ((x) * (1L<RGB colorspace conversion. + * This is taken directly from jdcolor.c; see that file for more info. + */ + +LOCAL(void) +build_ycc_rgb_table (j_decompress_ptr cinfo) +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + int i; + INT32 x; + SHIFT_TEMPS + + upsample->Cr_r_tab = (int *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(int)); + upsample->Cb_b_tab = (int *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(int)); + upsample->Cr_g_tab = (INT32 *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(INT32)); + upsample->Cb_g_tab = (INT32 *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(INT32)); + + for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) { + /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */ + /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */ + /* Cr=>R value is nearest int to 1.40200 * x */ + upsample->Cr_r_tab[i] = (int) + RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS); + /* Cb=>B value is nearest int to 1.77200 * x */ + upsample->Cb_b_tab[i] = (int) + RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS); + /* Cr=>G value is scaled-up -0.71414 * x */ + upsample->Cr_g_tab[i] = (- FIX(0.71414)) * x; + /* Cb=>G value is scaled-up -0.34414 * x */ + /* We also add in ONE_HALF so that need not do it in inner loop */ + upsample->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF; + } +} + + +/* + * Initialize for an upsampling pass. + */ + +METHODDEF(void) +start_pass_merged_upsample (j_decompress_ptr cinfo) +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + + /* Mark the spare buffer empty */ + upsample->spare_full = FALSE; + /* Initialize total-height counter for detecting bottom of image */ + upsample->rows_to_go = cinfo->output_height; +} + + +/* + * Control routine to do upsampling (and color conversion). + * + * The control routine just handles the row buffering considerations. + */ + +METHODDEF(void) +merged_2v_upsample (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +/* 2:1 vertical sampling case: may need a spare row. */ +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + JSAMPROW work_ptrs[2]; + JDIMENSION num_rows; /* number of rows returned to caller */ + + if (upsample->spare_full) { + /* If we have a spare row saved from a previous cycle, just return it. */ + jcopy_sample_rows(& upsample->spare_row, 0, output_buf + *out_row_ctr, 0, + 1, upsample->out_row_width); + num_rows = 1; + upsample->spare_full = FALSE; + } else { + /* Figure number of rows to return to caller. */ + num_rows = 2; + /* Not more than the distance to the end of the image. */ + if (num_rows > upsample->rows_to_go) + num_rows = upsample->rows_to_go; + /* And not more than what the client can accept: */ + out_rows_avail -= *out_row_ctr; + if (num_rows > out_rows_avail) + num_rows = out_rows_avail; + /* Create output pointer array for upsampler. */ + work_ptrs[0] = output_buf[*out_row_ctr]; + if (num_rows > 1) { + work_ptrs[1] = output_buf[*out_row_ctr + 1]; + } else { + work_ptrs[1] = upsample->spare_row; + upsample->spare_full = TRUE; + } + /* Now do the upsampling. */ + (*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr, work_ptrs); + } + + /* Adjust counts */ + *out_row_ctr += num_rows; + upsample->rows_to_go -= num_rows; + /* When the buffer is emptied, declare this input row group consumed */ + if (! upsample->spare_full) + (*in_row_group_ctr)++; +} + + +METHODDEF(void) +merged_1v_upsample (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +/* 1:1 vertical sampling case: much easier, never need a spare row. */ +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + + /* Just do the upsampling. */ + (*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr, + output_buf + *out_row_ctr); + /* Adjust counts */ + (*out_row_ctr)++; + (*in_row_group_ctr)++; +} + + +/* + * These are the routines invoked by the control routines to do + * the actual upsampling/conversion. One row group is processed per call. + * + * Note: since we may be writing directly into application-supplied buffers, + * we have to be honest about the output width; we can't assume the buffer + * has been rounded up to an even width. + */ + + +/* + * Upsample and color convert for the case of 2:1 horizontal and 1:1 vertical. + */ + +METHODDEF(void) +h2v1_merged_upsample (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, + JSAMPARRAY output_buf) +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + register int y, cred, cgreen, cblue; + int cb, cr; + register JSAMPROW outptr; + JSAMPROW inptr0, inptr1, inptr2; + JDIMENSION col; + /* copy these pointers into registers if possible */ + register JSAMPLE * range_limit = cinfo->sample_range_limit; + int * Crrtab = upsample->Cr_r_tab; + int * Cbbtab = upsample->Cb_b_tab; + INT32 * Crgtab = upsample->Cr_g_tab; + INT32 * Cbgtab = upsample->Cb_g_tab; + SHIFT_TEMPS + + inptr0 = input_buf[0][in_row_group_ctr]; + inptr1 = input_buf[1][in_row_group_ctr]; + inptr2 = input_buf[2][in_row_group_ctr]; + outptr = output_buf[0]; + /* Loop for each pair of output pixels */ + for (col = cinfo->output_width >> 1; col > 0; col--) { + /* Do the chroma part of the calculation */ + cb = GETJSAMPLE(*inptr1++); + cr = GETJSAMPLE(*inptr2++); + cred = Crrtab[cr]; + cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); + cblue = Cbbtab[cb]; + /* Fetch 2 Y values and emit 2 pixels */ + y = GETJSAMPLE(*inptr0++); + outptr[RGB_RED] = range_limit[y + cred]; + outptr[RGB_GREEN] = range_limit[y + cgreen]; + outptr[RGB_BLUE] = range_limit[y + cblue]; + outptr += RGB_PIXELSIZE; + y = GETJSAMPLE(*inptr0++); + outptr[RGB_RED] = range_limit[y + cred]; + outptr[RGB_GREEN] = range_limit[y + cgreen]; + outptr[RGB_BLUE] = range_limit[y + cblue]; + outptr += RGB_PIXELSIZE; + } + /* If image width is odd, do the last output column separately */ + if (cinfo->output_width & 1) { + cb = GETJSAMPLE(*inptr1); + cr = GETJSAMPLE(*inptr2); + cred = Crrtab[cr]; + cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); + cblue = Cbbtab[cb]; + y = GETJSAMPLE(*inptr0); + outptr[RGB_RED] = range_limit[y + cred]; + outptr[RGB_GREEN] = range_limit[y + cgreen]; + outptr[RGB_BLUE] = range_limit[y + cblue]; + } +} + + +/* + * Upsample and color convert for the case of 2:1 horizontal and 2:1 vertical. + */ + +METHODDEF(void) +h2v2_merged_upsample (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, + JSAMPARRAY output_buf) +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + register int y, cred, cgreen, cblue; + int cb, cr; + register JSAMPROW outptr0, outptr1; + JSAMPROW inptr00, inptr01, inptr1, inptr2; + JDIMENSION col; + /* copy these pointers into registers if possible */ + register JSAMPLE * range_limit = cinfo->sample_range_limit; + int * Crrtab = upsample->Cr_r_tab; + int * Cbbtab = upsample->Cb_b_tab; + INT32 * Crgtab = upsample->Cr_g_tab; + INT32 * Cbgtab = upsample->Cb_g_tab; + SHIFT_TEMPS + + inptr00 = input_buf[0][in_row_group_ctr*2]; + inptr01 = input_buf[0][in_row_group_ctr*2 + 1]; + inptr1 = input_buf[1][in_row_group_ctr]; + inptr2 = input_buf[2][in_row_group_ctr]; + outptr0 = output_buf[0]; + outptr1 = output_buf[1]; + /* Loop for each group of output pixels */ + for (col = cinfo->output_width >> 1; col > 0; col--) { + /* Do the chroma part of the calculation */ + cb = GETJSAMPLE(*inptr1++); + cr = GETJSAMPLE(*inptr2++); + cred = Crrtab[cr]; + cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); + cblue = Cbbtab[cb]; + /* Fetch 4 Y values and emit 4 pixels */ + y = GETJSAMPLE(*inptr00++); + outptr0[RGB_RED] = range_limit[y + cred]; + outptr0[RGB_GREEN] = range_limit[y + cgreen]; + outptr0[RGB_BLUE] = range_limit[y + cblue]; + outptr0 += RGB_PIXELSIZE; + y = GETJSAMPLE(*inptr00++); + outptr0[RGB_RED] = range_limit[y + cred]; + outptr0[RGB_GREEN] = range_limit[y + cgreen]; + outptr0[RGB_BLUE] = range_limit[y + cblue]; + outptr0 += RGB_PIXELSIZE; + y = GETJSAMPLE(*inptr01++); + outptr1[RGB_RED] = range_limit[y + cred]; + outptr1[RGB_GREEN] = range_limit[y + cgreen]; + outptr1[RGB_BLUE] = range_limit[y + cblue]; + outptr1 += RGB_PIXELSIZE; + y = GETJSAMPLE(*inptr01++); + outptr1[RGB_RED] = range_limit[y + cred]; + outptr1[RGB_GREEN] = range_limit[y + cgreen]; + outptr1[RGB_BLUE] = range_limit[y + cblue]; + outptr1 += RGB_PIXELSIZE; + } + /* If image width is odd, do the last output column separately */ + if (cinfo->output_width & 1) { + cb = GETJSAMPLE(*inptr1); + cr = GETJSAMPLE(*inptr2); + cred = Crrtab[cr]; + cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); + cblue = Cbbtab[cb]; + y = GETJSAMPLE(*inptr00); + outptr0[RGB_RED] = range_limit[y + cred]; + outptr0[RGB_GREEN] = range_limit[y + cgreen]; + outptr0[RGB_BLUE] = range_limit[y + cblue]; + y = GETJSAMPLE(*inptr01); + outptr1[RGB_RED] = range_limit[y + cred]; + outptr1[RGB_GREEN] = range_limit[y + cgreen]; + outptr1[RGB_BLUE] = range_limit[y + cblue]; + } +} + + +/* + * Module initialization routine for merged upsampling/color conversion. + * + * NB: this is called under the conditions determined by use_merged_upsample() + * in jdmaster.c. That routine MUST correspond to the actual capabilities + * of this module; no safety checks are made here. + */ + +GLOBAL(void) +jinit_merged_upsampler (j_decompress_ptr cinfo) +{ + my_upsample_ptr upsample; + + upsample = (my_upsample_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_upsampler)); + cinfo->upsample = (struct jpeg_upsampler *) upsample; + upsample->pub.start_pass = start_pass_merged_upsample; + upsample->pub.need_context_rows = FALSE; + + upsample->out_row_width = cinfo->output_width * cinfo->out_color_components; + + if (cinfo->max_v_samp_factor == 2) { + upsample->pub.upsample = merged_2v_upsample; + upsample->upmethod = h2v2_merged_upsample; + /* Allocate a spare row buffer */ + upsample->spare_row = (JSAMPROW) + (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (size_t) (upsample->out_row_width * SIZEOF(JSAMPLE))); + } else { + upsample->pub.upsample = merged_1v_upsample; + upsample->upmethod = h2v1_merged_upsample; + /* No spare row needed */ + upsample->spare_row = NULL; + } + + build_ycc_rgb_table(cinfo); +} + +#endif /* UPSAMPLE_MERGING_SUPPORTED */ diff --git a/jpeg/JDPHUFF.C b/jpeg/JDPHUFF.C new file mode 100644 index 0000000..400584c --- /dev/null +++ b/jpeg/JDPHUFF.C @@ -0,0 +1,668 @@ +/* + * jdphuff.c + * + * Copyright (C) 1995-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains Huffman entropy decoding routines for progressive JPEG. + * + * Much of the complexity here has to do with supporting input suspension. + * If the data source module demands suspension, we want to be able to back + * up to the start of the current MCU. To do this, we copy state variables + * into local working storage, and update them back to the permanent + * storage only upon successful completion of an MCU. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jdhuff.h" /* Declarations shared with jdhuff.c */ + + +#ifdef D_PROGRESSIVE_SUPPORTED + +/* + * Expanded entropy decoder object for progressive Huffman decoding. + * + * The savable_state subrecord contains fields that change within an MCU, + * but must not be updated permanently until we complete the MCU. + */ + +typedef struct { + unsigned int EOBRUN; /* remaining EOBs in EOBRUN */ + int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ +} savable_state; + +/* This macro is to work around compilers with missing or broken + * structure assignment. You'll need to fix this code if you have + * such a compiler and you change MAX_COMPS_IN_SCAN. + */ + +#ifndef NO_STRUCT_ASSIGN +#define ASSIGN_STATE(dest,src) ((dest) = (src)) +#else +#if MAX_COMPS_IN_SCAN == 4 +#define ASSIGN_STATE(dest,src) \ + ((dest).EOBRUN = (src).EOBRUN, \ + (dest).last_dc_val[0] = (src).last_dc_val[0], \ + (dest).last_dc_val[1] = (src).last_dc_val[1], \ + (dest).last_dc_val[2] = (src).last_dc_val[2], \ + (dest).last_dc_val[3] = (src).last_dc_val[3]) +#endif +#endif + + +typedef struct { + struct jpeg_entropy_decoder pub; /* public fields */ + + /* These fields are loaded into local variables at start of each MCU. + * In case of suspension, we exit WITHOUT updating them. + */ + bitread_perm_state bitstate; /* Bit buffer at start of MCU */ + savable_state saved; /* Other state at start of MCU */ + + /* These fields are NOT loaded into local working state. */ + unsigned int restarts_to_go; /* MCUs left in this restart interval */ + + /* Pointers to derived tables (these workspaces have image lifespan) */ + d_derived_tbl * derived_tbls[NUM_HUFF_TBLS]; + + d_derived_tbl * ac_derived_tbl; /* active table during an AC scan */ +} phuff_entropy_decoder; + +typedef phuff_entropy_decoder * phuff_entropy_ptr; + +/* Forward declarations */ +METHODDEF(boolean) decode_mcu_DC_first JPP((j_decompress_ptr cinfo, + JBLOCKROW *MCU_data)); +METHODDEF(boolean) decode_mcu_AC_first JPP((j_decompress_ptr cinfo, + JBLOCKROW *MCU_data)); +METHODDEF(boolean) decode_mcu_DC_refine JPP((j_decompress_ptr cinfo, + JBLOCKROW *MCU_data)); +METHODDEF(boolean) decode_mcu_AC_refine JPP((j_decompress_ptr cinfo, + JBLOCKROW *MCU_data)); + + +/* + * Initialize for a Huffman-compressed scan. + */ + +METHODDEF(void) +start_pass_phuff_decoder (j_decompress_ptr cinfo) +{ + phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; + boolean is_DC_band, bad; + int ci, coefi, tbl; + int *coef_bit_ptr; + jpeg_component_info * compptr; + + is_DC_band = (cinfo->Ss == 0); + + /* Validate scan parameters */ + bad = FALSE; + if (is_DC_band) { + if (cinfo->Se != 0) + bad = TRUE; + } else { + /* need not check Ss/Se < 0 since they came from unsigned bytes */ + if (cinfo->Ss > cinfo->Se || cinfo->Se >= DCTSIZE2) + bad = TRUE; + /* AC scans may have only one component */ + if (cinfo->comps_in_scan != 1) + bad = TRUE; + } + if (cinfo->Ah != 0) { + /* Successive approximation refinement scan: must have Al = Ah-1. */ + if (cinfo->Al != cinfo->Ah-1) + bad = TRUE; + } + if (cinfo->Al > 13) /* need not check for < 0 */ + bad = TRUE; + /* Arguably the maximum Al value should be less than 13 for 8-bit precision, + * but the spec doesn't say so, and we try to be liberal about what we + * accept. Note: large Al values could result in out-of-range DC + * coefficients during early scans, leading to bizarre displays due to + * overflows in the IDCT math. But we won't crash. + */ + if (bad) + ERREXIT4(cinfo, JERR_BAD_PROGRESSION, + cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al); + /* Update progression status, and verify that scan order is legal. + * Note that inter-scan inconsistencies are treated as warnings + * not fatal errors ... not clear if this is right way to behave. + */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + int cindex = cinfo->cur_comp_info[ci]->component_index; + coef_bit_ptr = & cinfo->coef_bits[cindex][0]; + if (!is_DC_band && coef_bit_ptr[0] < 0) /* AC without prior DC scan */ + WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, 0); + for (coefi = cinfo->Ss; coefi <= cinfo->Se; coefi++) { + int expected = (coef_bit_ptr[coefi] < 0) ? 0 : coef_bit_ptr[coefi]; + if (cinfo->Ah != expected) + WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, coefi); + coef_bit_ptr[coefi] = cinfo->Al; + } + } + + /* Select MCU decoding routine */ + if (cinfo->Ah == 0) { + if (is_DC_band) + entropy->pub.decode_mcu = decode_mcu_DC_first; + else + entropy->pub.decode_mcu = decode_mcu_AC_first; + } else { + if (is_DC_band) + entropy->pub.decode_mcu = decode_mcu_DC_refine; + else + entropy->pub.decode_mcu = decode_mcu_AC_refine; + } + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* Make sure requested tables are present, and compute derived tables. + * We may build same derived table more than once, but it's not expensive. + */ + if (is_DC_band) { + if (cinfo->Ah == 0) { /* DC refinement needs no table */ + tbl = compptr->dc_tbl_no; + jpeg_make_d_derived_tbl(cinfo, TRUE, tbl, + & entropy->derived_tbls[tbl]); + } + } else { + tbl = compptr->ac_tbl_no; + jpeg_make_d_derived_tbl(cinfo, FALSE, tbl, + & entropy->derived_tbls[tbl]); + /* remember the single active table */ + entropy->ac_derived_tbl = entropy->derived_tbls[tbl]; + } + /* Initialize DC predictions to 0 */ + entropy->saved.last_dc_val[ci] = 0; + } + + /* Initialize bitread state variables */ + entropy->bitstate.bits_left = 0; + entropy->bitstate.get_buffer = 0; /* unnecessary, but keeps Purify quiet */ + entropy->pub.insufficient_data = FALSE; + + /* Initialize private state variables */ + entropy->saved.EOBRUN = 0; + + /* Initialize restart counter */ + entropy->restarts_to_go = cinfo->restart_interval; +} + + +/* + * Figure F.12: extend sign bit. + * On some machines, a shift and add will be faster than a table lookup. + */ + +#ifdef AVOID_TABLES + +#define HUFF_EXTEND(x,s) ((x) < (1<<((s)-1)) ? (x) + (((-1)<<(s)) + 1) : (x)) + +#else + +#define HUFF_EXTEND(x,s) ((x) < extend_test[s] ? (x) + extend_offset[s] : (x)) + +static const int extend_test[16] = /* entry n is 2**(n-1) */ + { 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, + 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 }; + +static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */ + { 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1, + ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1, + ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1, + ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 }; + +#endif /* AVOID_TABLES */ + + +/* + * Check for a restart marker & resynchronize decoder. + * Returns FALSE if must suspend. + */ + +LOCAL(boolean) +process_restart (j_decompress_ptr cinfo) +{ + phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; + int ci; + + /* Throw away any unused bits remaining in bit buffer; */ + /* include any full bytes in next_marker's count of discarded bytes */ + cinfo->marker->discarded_bytes += entropy->bitstate.bits_left / 8; + entropy->bitstate.bits_left = 0; + + /* Advance past the RSTn marker */ + if (! (*cinfo->marker->read_restart_marker) (cinfo)) + return FALSE; + + /* Re-initialize DC predictions to 0 */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) + entropy->saved.last_dc_val[ci] = 0; + /* Re-init EOB run count, too */ + entropy->saved.EOBRUN = 0; + + /* Reset restart counter */ + entropy->restarts_to_go = cinfo->restart_interval; + + /* Reset out-of-data flag, unless read_restart_marker left us smack up + * against a marker. In that case we will end up treating the next data + * segment as empty, and we can avoid producing bogus output pixels by + * leaving the flag set. + */ + if (cinfo->unread_marker == 0) + entropy->pub.insufficient_data = FALSE; + + return TRUE; +} + + +/* + * Huffman MCU decoding. + * Each of these routines decodes and returns one MCU's worth of + * Huffman-compressed coefficients. + * The coefficients are reordered from zigzag order into natural array order, + * but are not dequantized. + * + * The i'th block of the MCU is stored into the block pointed to by + * MCU_data[i]. WE ASSUME THIS AREA IS INITIALLY ZEROED BY THE CALLER. + * + * We return FALSE if data source requested suspension. In that case no + * changes have been made to permanent state. (Exception: some output + * coefficients may already have been assigned. This is harmless for + * spectral selection, since we'll just re-assign them on the next call. + * Successive approximation AC refinement has to be more careful, however.) + */ + +/* + * MCU decoding for DC initial scan (either spectral selection, + * or first pass of successive approximation). + */ + +METHODDEF(boolean) +decode_mcu_DC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; + int Al = cinfo->Al; + register int s, r; + int blkn, ci; + JBLOCKROW block; + BITREAD_STATE_VARS; + savable_state state; + d_derived_tbl * tbl; + jpeg_component_info * compptr; + + /* Process restart marker if needed; may have to suspend */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! process_restart(cinfo)) + return FALSE; + } + + /* If we've run out of data, just leave the MCU set to zeroes. + * This way, we return uniform gray for the remainder of the segment. + */ + if (! entropy->pub.insufficient_data) { + + /* Load up working state */ + BITREAD_LOAD_STATE(cinfo,entropy->bitstate); + ASSIGN_STATE(state, entropy->saved); + + /* Outer loop handles each block in the MCU */ + + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + block = MCU_data[blkn]; + ci = cinfo->MCU_membership[blkn]; + compptr = cinfo->cur_comp_info[ci]; + tbl = entropy->derived_tbls[compptr->dc_tbl_no]; + + /* Decode a single block's worth of coefficients */ + + /* Section F.2.2.1: decode the DC coefficient difference */ + HUFF_DECODE(s, br_state, tbl, return FALSE, label1); + if (s) { + CHECK_BIT_BUFFER(br_state, s, return FALSE); + r = GET_BITS(s); + s = HUFF_EXTEND(r, s); + } + + /* Convert DC difference to actual value, update last_dc_val */ + s += state.last_dc_val[ci]; + state.last_dc_val[ci] = s; + /* Scale and output the coefficient (assumes jpeg_natural_order[0]=0) */ + (*block)[0] = (JCOEF) (s << Al); + } + + /* Completed MCU, so update state */ + BITREAD_SAVE_STATE(cinfo,entropy->bitstate); + ASSIGN_STATE(entropy->saved, state); + } + + /* Account for restart interval (no-op if not using restarts) */ + entropy->restarts_to_go--; + + return TRUE; +} + + +/* + * MCU decoding for AC initial scan (either spectral selection, + * or first pass of successive approximation). + */ + +METHODDEF(boolean) +decode_mcu_AC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; + int Se = cinfo->Se; + int Al = cinfo->Al; + register int s, k, r; + unsigned int EOBRUN; + JBLOCKROW block; + BITREAD_STATE_VARS; + d_derived_tbl * tbl; + + /* Process restart marker if needed; may have to suspend */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! process_restart(cinfo)) + return FALSE; + } + + /* If we've run out of data, just leave the MCU set to zeroes. + * This way, we return uniform gray for the remainder of the segment. + */ + if (! entropy->pub.insufficient_data) { + + /* Load up working state. + * We can avoid loading/saving bitread state if in an EOB run. + */ + EOBRUN = entropy->saved.EOBRUN; /* only part of saved state we need */ + + /* There is always only one block per MCU */ + + if (EOBRUN > 0) /* if it's a band of zeroes... */ + EOBRUN--; /* ...process it now (we do nothing) */ + else { + BITREAD_LOAD_STATE(cinfo,entropy->bitstate); + block = MCU_data[0]; + tbl = entropy->ac_derived_tbl; + + for (k = cinfo->Ss; k <= Se; k++) { + HUFF_DECODE(s, br_state, tbl, return FALSE, label2); + r = s >> 4; + s &= 15; + if (s) { + k += r; + CHECK_BIT_BUFFER(br_state, s, return FALSE); + r = GET_BITS(s); + s = HUFF_EXTEND(r, s); + /* Scale and output coefficient in natural (dezigzagged) order */ + (*block)[jpeg_natural_order[k]] = (JCOEF) (s << Al); + } else { + if (r == 15) { /* ZRL */ + k += 15; /* skip 15 zeroes in band */ + } else { /* EOBr, run length is 2^r + appended bits */ + EOBRUN = 1 << r; + if (r) { /* EOBr, r > 0 */ + CHECK_BIT_BUFFER(br_state, r, return FALSE); + r = GET_BITS(r); + EOBRUN += r; + } + EOBRUN--; /* this band is processed at this moment */ + break; /* force end-of-band */ + } + } + } + + BITREAD_SAVE_STATE(cinfo,entropy->bitstate); + } + + /* Completed MCU, so update state */ + entropy->saved.EOBRUN = EOBRUN; /* only part of saved state we need */ + } + + /* Account for restart interval (no-op if not using restarts) */ + entropy->restarts_to_go--; + + return TRUE; +} + + +/* + * MCU decoding for DC successive approximation refinement scan. + * Note: we assume such scans can be multi-component, although the spec + * is not very clear on the point. + */ + +METHODDEF(boolean) +decode_mcu_DC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; + int p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */ + int blkn; + JBLOCKROW block; + BITREAD_STATE_VARS; + + /* Process restart marker if needed; may have to suspend */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! process_restart(cinfo)) + return FALSE; + } + + /* Not worth the cycles to check insufficient_data here, + * since we will not change the data anyway if we read zeroes. + */ + + /* Load up working state */ + BITREAD_LOAD_STATE(cinfo,entropy->bitstate); + + /* Outer loop handles each block in the MCU */ + + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + block = MCU_data[blkn]; + + /* Encoded data is simply the next bit of the two's-complement DC value */ + CHECK_BIT_BUFFER(br_state, 1, return FALSE); + if (GET_BITS(1)) + (*block)[0] |= p1; + /* Note: since we use |=, repeating the assignment later is safe */ + } + + /* Completed MCU, so update state */ + BITREAD_SAVE_STATE(cinfo,entropy->bitstate); + + /* Account for restart interval (no-op if not using restarts) */ + entropy->restarts_to_go--; + + return TRUE; +} + + +/* + * MCU decoding for AC successive approximation refinement scan. + */ + +METHODDEF(boolean) +decode_mcu_AC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; + int Se = cinfo->Se; + int p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */ + int m1 = (-1) << cinfo->Al; /* -1 in the bit position being coded */ + register int s, k, r; + unsigned int EOBRUN; + JBLOCKROW block; + JCOEFPTR thiscoef; + BITREAD_STATE_VARS; + d_derived_tbl * tbl; + int num_newnz; + int newnz_pos[DCTSIZE2]; + + /* Process restart marker if needed; may have to suspend */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! process_restart(cinfo)) + return FALSE; + } + + /* If we've run out of data, don't modify the MCU. + */ + if (! entropy->pub.insufficient_data) { + + /* Load up working state */ + BITREAD_LOAD_STATE(cinfo,entropy->bitstate); + EOBRUN = entropy->saved.EOBRUN; /* only part of saved state we need */ + + /* There is always only one block per MCU */ + block = MCU_data[0]; + tbl = entropy->ac_derived_tbl; + + /* If we are forced to suspend, we must undo the assignments to any newly + * nonzero coefficients in the block, because otherwise we'd get confused + * next time about which coefficients were already nonzero. + * But we need not undo addition of bits to already-nonzero coefficients; + * instead, we can test the current bit to see if we already did it. + */ + num_newnz = 0; + + /* initialize coefficient loop counter to start of band */ + k = cinfo->Ss; + + if (EOBRUN == 0) { + for (; k <= Se; k++) { + HUFF_DECODE(s, br_state, tbl, goto undoit, label3); + r = s >> 4; + s &= 15; + if (s) { + if (s != 1) /* size of new coef should always be 1 */ + WARNMS(cinfo, JWRN_HUFF_BAD_CODE); + CHECK_BIT_BUFFER(br_state, 1, goto undoit); + if (GET_BITS(1)) + s = p1; /* newly nonzero coef is positive */ + else + s = m1; /* newly nonzero coef is negative */ + } else { + if (r != 15) { + EOBRUN = 1 << r; /* EOBr, run length is 2^r + appended bits */ + if (r) { + CHECK_BIT_BUFFER(br_state, r, goto undoit); + r = GET_BITS(r); + EOBRUN += r; + } + break; /* rest of block is handled by EOB logic */ + } + /* note s = 0 for processing ZRL */ + } + /* Advance over already-nonzero coefs and r still-zero coefs, + * appending correction bits to the nonzeroes. A correction bit is 1 + * if the absolute value of the coefficient must be increased. + */ + do { + thiscoef = *block + jpeg_natural_order[k]; + if (*thiscoef != 0) { + CHECK_BIT_BUFFER(br_state, 1, goto undoit); + if (GET_BITS(1)) { + if ((*thiscoef & p1) == 0) { /* do nothing if already set it */ + if (*thiscoef >= 0) + *thiscoef += p1; + else + *thiscoef += m1; + } + } + } else { + if (--r < 0) + break; /* reached target zero coefficient */ + } + k++; + } while (k <= Se); + if (s) { + int pos = jpeg_natural_order[k]; + /* Output newly nonzero coefficient */ + (*block)[pos] = (JCOEF) s; + /* Remember its position in case we have to suspend */ + newnz_pos[num_newnz++] = pos; + } + } + } + + if (EOBRUN > 0) { + /* Scan any remaining coefficient positions after the end-of-band + * (the last newly nonzero coefficient, if any). Append a correction + * bit to each already-nonzero coefficient. A correction bit is 1 + * if the absolute value of the coefficient must be increased. + */ + for (; k <= Se; k++) { + thiscoef = *block + jpeg_natural_order[k]; + if (*thiscoef != 0) { + CHECK_BIT_BUFFER(br_state, 1, goto undoit); + if (GET_BITS(1)) { + if ((*thiscoef & p1) == 0) { /* do nothing if already changed it */ + if (*thiscoef >= 0) + *thiscoef += p1; + else + *thiscoef += m1; + } + } + } + } + /* Count one block completed in EOB run */ + EOBRUN--; + } + + /* Completed MCU, so update state */ + BITREAD_SAVE_STATE(cinfo,entropy->bitstate); + entropy->saved.EOBRUN = EOBRUN; /* only part of saved state we need */ + } + + /* Account for restart interval (no-op if not using restarts) */ + entropy->restarts_to_go--; + + return TRUE; + +undoit: + /* Re-zero any output coefficients that we made newly nonzero */ + while (num_newnz > 0) + (*block)[newnz_pos[--num_newnz]] = 0; + + return FALSE; +} + + +/* + * Module initialization routine for progressive Huffman entropy decoding. + */ + +GLOBAL(void) +jinit_phuff_decoder (j_decompress_ptr cinfo) +{ + phuff_entropy_ptr entropy; + int *coef_bit_ptr; + int ci, i; + + entropy = (phuff_entropy_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(phuff_entropy_decoder)); + cinfo->entropy = (struct jpeg_entropy_decoder *) entropy; + entropy->pub.start_pass = start_pass_phuff_decoder; + + /* Mark derived tables unallocated */ + for (i = 0; i < NUM_HUFF_TBLS; i++) { + entropy->derived_tbls[i] = NULL; + } + + /* Create progression status table */ + cinfo->coef_bits = (int (*)[DCTSIZE2]) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + cinfo->num_components*DCTSIZE2*SIZEOF(int)); + coef_bit_ptr = & cinfo->coef_bits[0][0]; + for (ci = 0; ci < cinfo->num_components; ci++) + for (i = 0; i < DCTSIZE2; i++) + *coef_bit_ptr++ = -1; +} + +#endif /* D_PROGRESSIVE_SUPPORTED */ diff --git a/jpeg/JDPOSTCT.C b/jpeg/JDPOSTCT.C new file mode 100644 index 0000000..c71cc5d --- /dev/null +++ b/jpeg/JDPOSTCT.C @@ -0,0 +1,290 @@ +/* + * jdpostct.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the decompression postprocessing controller. + * This controller manages the upsampling, color conversion, and color + * quantization/reduction steps; specifically, it controls the buffering + * between upsample/color conversion and color quantization/reduction. + * + * If no color quantization/reduction is required, then this module has no + * work to do, and it just hands off to the upsample/color conversion code. + * An integrated upsample/convert/quantize process would replace this module + * entirely. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Private buffer controller object */ + +typedef struct { + struct jpeg_d_post_controller pub; /* public fields */ + + /* Color quantization source buffer: this holds output data from + * the upsample/color conversion step to be passed to the quantizer. + * For two-pass color quantization, we need a full-image buffer; + * for one-pass operation, a strip buffer is sufficient. + */ + jvirt_sarray_ptr whole_image; /* virtual array, or NULL if one-pass */ + JSAMPARRAY buffer; /* strip buffer, or current strip of virtual */ + JDIMENSION strip_height; /* buffer size in rows */ + /* for two-pass mode only: */ + JDIMENSION starting_row; /* row # of first row in current strip */ + JDIMENSION next_row; /* index of next row to fill/empty in strip */ +} my_post_controller; + +typedef my_post_controller * my_post_ptr; + + +/* Forward declarations */ +METHODDEF(void) post_process_1pass + JPP((j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); +#ifdef QUANT_2PASS_SUPPORTED +METHODDEF(void) post_process_prepass + JPP((j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); +METHODDEF(void) post_process_2pass + JPP((j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); +#endif + + +/* + * Initialize for a processing pass. + */ + +METHODDEF(void) +start_pass_dpost (j_decompress_ptr cinfo, J_BUF_MODE pass_mode) +{ + my_post_ptr post = (my_post_ptr) cinfo->post; + + switch (pass_mode) { + case JBUF_PASS_THRU: + if (cinfo->quantize_colors) { + /* Single-pass processing with color quantization. */ + post->pub.post_process_data = post_process_1pass; + /* We could be doing buffered-image output before starting a 2-pass + * color quantization; in that case, jinit_d_post_controller did not + * allocate a strip buffer. Use the virtual-array buffer as workspace. + */ + if (post->buffer == NULL) { + post->buffer = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, post->whole_image, + (JDIMENSION) 0, post->strip_height, TRUE); + } + } else { + /* For single-pass processing without color quantization, + * I have no work to do; just call the upsampler directly. + */ + post->pub.post_process_data = cinfo->upsample->upsample; + } + break; +#ifdef QUANT_2PASS_SUPPORTED + case JBUF_SAVE_AND_PASS: + /* First pass of 2-pass quantization */ + if (post->whole_image == NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + post->pub.post_process_data = post_process_prepass; + break; + case JBUF_CRANK_DEST: + /* Second pass of 2-pass quantization */ + if (post->whole_image == NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + post->pub.post_process_data = post_process_2pass; + break; +#endif /* QUANT_2PASS_SUPPORTED */ + default: + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + break; + } + post->starting_row = post->next_row = 0; +} + + +/* + * Process some data in the one-pass (strip buffer) case. + * This is used for color precision reduction as well as one-pass quantization. + */ + +METHODDEF(void) +post_process_1pass (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +{ + my_post_ptr post = (my_post_ptr) cinfo->post; + JDIMENSION num_rows, max_rows; + + /* Fill the buffer, but not more than what we can dump out in one go. */ + /* Note we rely on the upsampler to detect bottom of image. */ + max_rows = out_rows_avail - *out_row_ctr; + if (max_rows > post->strip_height) + max_rows = post->strip_height; + num_rows = 0; + (*cinfo->upsample->upsample) (cinfo, + input_buf, in_row_group_ctr, in_row_groups_avail, + post->buffer, &num_rows, max_rows); + /* Quantize and emit data. */ + (*cinfo->cquantize->color_quantize) (cinfo, + post->buffer, output_buf + *out_row_ctr, (int) num_rows); + *out_row_ctr += num_rows; +} + + +#ifdef QUANT_2PASS_SUPPORTED + +/* + * Process some data in the first pass of 2-pass quantization. + */ + +METHODDEF(void) +post_process_prepass (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +{ + my_post_ptr post = (my_post_ptr) cinfo->post; + JDIMENSION old_next_row, num_rows; + + /* Reposition virtual buffer if at start of strip. */ + if (post->next_row == 0) { + post->buffer = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, post->whole_image, + post->starting_row, post->strip_height, TRUE); + } + + /* Upsample some data (up to a strip height's worth). */ + old_next_row = post->next_row; + (*cinfo->upsample->upsample) (cinfo, + input_buf, in_row_group_ctr, in_row_groups_avail, + post->buffer, &post->next_row, post->strip_height); + + /* Allow quantizer to scan new data. No data is emitted, */ + /* but we advance out_row_ctr so outer loop can tell when we're done. */ + if (post->next_row > old_next_row) { + num_rows = post->next_row - old_next_row; + (*cinfo->cquantize->color_quantize) (cinfo, post->buffer + old_next_row, + (JSAMPARRAY) NULL, (int) num_rows); + *out_row_ctr += num_rows; + } + + /* Advance if we filled the strip. */ + if (post->next_row >= post->strip_height) { + post->starting_row += post->strip_height; + post->next_row = 0; + } +} + + +/* + * Process some data in the second pass of 2-pass quantization. + */ + +METHODDEF(void) +post_process_2pass (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +{ + my_post_ptr post = (my_post_ptr) cinfo->post; + JDIMENSION num_rows, max_rows; + + /* Reposition virtual buffer if at start of strip. */ + if (post->next_row == 0) { + post->buffer = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, post->whole_image, + post->starting_row, post->strip_height, FALSE); + } + + /* Determine number of rows to emit. */ + num_rows = post->strip_height - post->next_row; /* available in strip */ + max_rows = out_rows_avail - *out_row_ctr; /* available in output area */ + if (num_rows > max_rows) + num_rows = max_rows; + /* We have to check bottom of image here, can't depend on upsampler. */ + max_rows = cinfo->output_height - post->starting_row; + if (num_rows > max_rows) + num_rows = max_rows; + + /* Quantize and emit data. */ + (*cinfo->cquantize->color_quantize) (cinfo, + post->buffer + post->next_row, output_buf + *out_row_ctr, + (int) num_rows); + *out_row_ctr += num_rows; + + /* Advance if we filled the strip. */ + post->next_row += num_rows; + if (post->next_row >= post->strip_height) { + post->starting_row += post->strip_height; + post->next_row = 0; + } +} + +#endif /* QUANT_2PASS_SUPPORTED */ + + +/* + * Initialize postprocessing controller. + */ + +GLOBAL(void) +jinit_d_post_controller (j_decompress_ptr cinfo, boolean need_full_buffer) +{ + my_post_ptr post; + + post = (my_post_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_post_controller)); + cinfo->post = (struct jpeg_d_post_controller *) post; + post->pub.start_pass = start_pass_dpost; + post->whole_image = NULL; /* flag for no virtual arrays */ + post->buffer = NULL; /* flag for no strip buffer */ + + /* Create the quantization buffer, if needed */ + if (cinfo->quantize_colors) { + /* The buffer strip height is max_v_samp_factor, which is typically + * an efficient number of rows for upsampling to return. + * (In the presence of output rescaling, we might want to be smarter?) + */ + post->strip_height = (JDIMENSION) cinfo->max_v_samp_factor; + if (need_full_buffer) { + /* Two-pass color quantization: need full-image storage. */ + /* We round up the number of rows to a multiple of the strip height. */ +#ifdef QUANT_2PASS_SUPPORTED + post->whole_image = (*cinfo->mem->request_virt_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, + cinfo->output_width * cinfo->out_color_components, + (JDIMENSION) jround_up((long) cinfo->output_height, + (long) post->strip_height), + post->strip_height); +#else + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); +#endif /* QUANT_2PASS_SUPPORTED */ + } else { + /* One-pass color quantization: just make a strip buffer. */ + post->buffer = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + cinfo->output_width * cinfo->out_color_components, + post->strip_height); + } + } +} diff --git a/jpeg/JDSAMPLE.C b/jpeg/JDSAMPLE.C new file mode 100644 index 0000000..7018062 --- /dev/null +++ b/jpeg/JDSAMPLE.C @@ -0,0 +1,478 @@ +/* + * jdsample.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains upsampling routines. + * + * Upsampling input data is counted in "row groups". A row group + * is defined to be (v_samp_factor * DCT_scaled_size / min_DCT_scaled_size) + * sample rows of each component. Upsampling will normally produce + * max_v_samp_factor pixel rows from each row group (but this could vary + * if the upsampler is applying a scale factor of its own). + * + * An excellent reference for image resampling is + * Digital Image Warping, George Wolberg, 1990. + * Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Pointer to routine to upsample a single component */ +typedef JMETHOD(void, upsample1_ptr, + (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)); + +/* Private subobject */ + +typedef struct { + struct jpeg_upsampler pub; /* public fields */ + + /* Color conversion buffer. When using separate upsampling and color + * conversion steps, this buffer holds one upsampled row group until it + * has been color converted and output. + * Note: we do not allocate any storage for component(s) which are full-size, + * ie do not need rescaling. The corresponding entry of color_buf[] is + * simply set to point to the input data array, thereby avoiding copying. + */ + JSAMPARRAY color_buf[MAX_COMPONENTS]; + + /* Per-component upsampling method pointers */ + upsample1_ptr methods[MAX_COMPONENTS]; + + int next_row_out; /* counts rows emitted from color_buf */ + JDIMENSION rows_to_go; /* counts rows remaining in image */ + + /* Height of an input row group for each component. */ + int rowgroup_height[MAX_COMPONENTS]; + + /* These arrays save pixel expansion factors so that int_expand need not + * recompute them each time. They are unused for other upsampling methods. + */ + UINT8 h_expand[MAX_COMPONENTS]; + UINT8 v_expand[MAX_COMPONENTS]; +} my_upsampler; + +typedef my_upsampler * my_upsample_ptr; + + +/* + * Initialize for an upsampling pass. + */ + +METHODDEF(void) +start_pass_upsample (j_decompress_ptr cinfo) +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + + /* Mark the conversion buffer empty */ + upsample->next_row_out = cinfo->max_v_samp_factor; + /* Initialize total-height counter for detecting bottom of image */ + upsample->rows_to_go = cinfo->output_height; +} + + +/* + * Control routine to do upsampling (and color conversion). + * + * In this version we upsample each component independently. + * We upsample one row group into the conversion buffer, then apply + * color conversion a row at a time. + */ + +METHODDEF(void) +sep_upsample (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + int ci; + jpeg_component_info * compptr; + JDIMENSION num_rows; + + /* Fill the conversion buffer, if it's empty */ + if (upsample->next_row_out >= cinfo->max_v_samp_factor) { + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Invoke per-component upsample method. Notice we pass a POINTER + * to color_buf[ci], so that fullsize_upsample can change it. + */ + (*upsample->methods[ci]) (cinfo, compptr, + input_buf[ci] + (*in_row_group_ctr * upsample->rowgroup_height[ci]), + upsample->color_buf + ci); + } + upsample->next_row_out = 0; + } + + /* Color-convert and emit rows */ + + /* How many we have in the buffer: */ + num_rows = (JDIMENSION) (cinfo->max_v_samp_factor - upsample->next_row_out); + /* Not more than the distance to the end of the image. Need this test + * in case the image height is not a multiple of max_v_samp_factor: + */ + if (num_rows > upsample->rows_to_go) + num_rows = upsample->rows_to_go; + /* And not more than what the client can accept: */ + out_rows_avail -= *out_row_ctr; + if (num_rows > out_rows_avail) + num_rows = out_rows_avail; + + (*cinfo->cconvert->color_convert) (cinfo, upsample->color_buf, + (JDIMENSION) upsample->next_row_out, + output_buf + *out_row_ctr, + (int) num_rows); + + /* Adjust counts */ + *out_row_ctr += num_rows; + upsample->rows_to_go -= num_rows; + upsample->next_row_out += num_rows; + /* When the buffer is emptied, declare this input row group consumed */ + if (upsample->next_row_out >= cinfo->max_v_samp_factor) + (*in_row_group_ctr)++; +} + + +/* + * These are the routines invoked by sep_upsample to upsample pixel values + * of a single component. One row group is processed per call. + */ + + +/* + * For full-size components, we just make color_buf[ci] point at the + * input buffer, and thus avoid copying any data. Note that this is + * safe only because sep_upsample doesn't declare the input row group + * "consumed" until we are done color converting and emitting it. + */ + +METHODDEF(void) +fullsize_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) +{ + *output_data_ptr = input_data; +} + + +/* + * This is a no-op version used for "uninteresting" components. + * These components will not be referenced by color conversion. + */ + +METHODDEF(void) +noop_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) +{ + *output_data_ptr = NULL; /* safety check */ +} + + +/* + * This version handles any integral sampling ratios. + * This is not used for typical JPEG files, so it need not be fast. + * Nor, for that matter, is it particularly accurate: the algorithm is + * simple replication of the input pixel onto the corresponding output + * pixels. The hi-falutin sampling literature refers to this as a + * "box filter". A box filter tends to introduce visible artifacts, + * so if you are actually going to use 3:1 or 4:1 sampling ratios + * you would be well advised to improve this code. + */ + +METHODDEF(void) +int_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + JSAMPARRAY output_data = *output_data_ptr; + register JSAMPROW inptr, outptr; + register JSAMPLE invalue; + register int h; + JSAMPROW outend; + int h_expand, v_expand; + int inrow, outrow; + + h_expand = upsample->h_expand[compptr->component_index]; + v_expand = upsample->v_expand[compptr->component_index]; + + inrow = outrow = 0; + while (outrow < cinfo->max_v_samp_factor) { + /* Generate one output row with proper horizontal expansion */ + inptr = input_data[inrow]; + outptr = output_data[outrow]; + outend = outptr + cinfo->output_width; + while (outptr < outend) { + invalue = *inptr++; /* don't need GETJSAMPLE() here */ + for (h = h_expand; h > 0; h--) { + *outptr++ = invalue; + } + } + /* Generate any additional output rows by duplicating the first one */ + if (v_expand > 1) { + jcopy_sample_rows(output_data, outrow, output_data, outrow+1, + v_expand-1, cinfo->output_width); + } + inrow++; + outrow += v_expand; + } +} + + +/* + * Fast processing for the common case of 2:1 horizontal and 1:1 vertical. + * It's still a box filter. + */ + +METHODDEF(void) +h2v1_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) +{ + JSAMPARRAY output_data = *output_data_ptr; + register JSAMPROW inptr, outptr; + register JSAMPLE invalue; + JSAMPROW outend; + int inrow; + + for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) { + inptr = input_data[inrow]; + outptr = output_data[inrow]; + outend = outptr + cinfo->output_width; + while (outptr < outend) { + invalue = *inptr++; /* don't need GETJSAMPLE() here */ + *outptr++ = invalue; + *outptr++ = invalue; + } + } +} + + +/* + * Fast processing for the common case of 2:1 horizontal and 2:1 vertical. + * It's still a box filter. + */ + +METHODDEF(void) +h2v2_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) +{ + JSAMPARRAY output_data = *output_data_ptr; + register JSAMPROW inptr, outptr; + register JSAMPLE invalue; + JSAMPROW outend; + int inrow, outrow; + + inrow = outrow = 0; + while (outrow < cinfo->max_v_samp_factor) { + inptr = input_data[inrow]; + outptr = output_data[outrow]; + outend = outptr + cinfo->output_width; + while (outptr < outend) { + invalue = *inptr++; /* don't need GETJSAMPLE() here */ + *outptr++ = invalue; + *outptr++ = invalue; + } + jcopy_sample_rows(output_data, outrow, output_data, outrow+1, + 1, cinfo->output_width); + inrow++; + outrow += 2; + } +} + + +/* + * Fancy processing for the common case of 2:1 horizontal and 1:1 vertical. + * + * The upsampling algorithm is linear interpolation between pixel centers, + * also known as a "triangle filter". This is a good compromise between + * speed and visual quality. The centers of the output pixels are 1/4 and 3/4 + * of the way between input pixel centers. + * + * A note about the "bias" calculations: when rounding fractional values to + * integer, we do not want to always round 0.5 up to the next integer. + * If we did that, we'd introduce a noticeable bias towards larger values. + * Instead, this code is arranged so that 0.5 will be rounded up or down at + * alternate pixel locations (a simple ordered dither pattern). + */ + +METHODDEF(void) +h2v1_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) +{ + JSAMPARRAY output_data = *output_data_ptr; + register JSAMPROW inptr, outptr; + register int invalue; + register JDIMENSION colctr; + int inrow; + + for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) { + inptr = input_data[inrow]; + outptr = output_data[inrow]; + /* Special case for first column */ + invalue = GETJSAMPLE(*inptr++); + *outptr++ = (JSAMPLE) invalue; + *outptr++ = (JSAMPLE) ((invalue * 3 + GETJSAMPLE(*inptr) + 2) >> 2); + + for (colctr = compptr->downsampled_width - 2; colctr > 0; colctr--) { + /* General case: 3/4 * nearer pixel + 1/4 * further pixel */ + invalue = GETJSAMPLE(*inptr++) * 3; + *outptr++ = (JSAMPLE) ((invalue + GETJSAMPLE(inptr[-2]) + 1) >> 2); + *outptr++ = (JSAMPLE) ((invalue + GETJSAMPLE(*inptr) + 2) >> 2); + } + + /* Special case for last column */ + invalue = GETJSAMPLE(*inptr); + *outptr++ = (JSAMPLE) ((invalue * 3 + GETJSAMPLE(inptr[-1]) + 1) >> 2); + *outptr++ = (JSAMPLE) invalue; + } +} + + +/* + * Fancy processing for the common case of 2:1 horizontal and 2:1 vertical. + * Again a triangle filter; see comments for h2v1 case, above. + * + * It is OK for us to reference the adjacent input rows because we demanded + * context from the main buffer controller (see initialization code). + */ + +METHODDEF(void) +h2v2_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) +{ + JSAMPARRAY output_data = *output_data_ptr; + register JSAMPROW inptr0, inptr1, outptr; +#if BITS_IN_JSAMPLE == 8 + register int thiscolsum, lastcolsum, nextcolsum; +#else + register INT32 thiscolsum, lastcolsum, nextcolsum; +#endif + register JDIMENSION colctr; + int inrow, outrow, v; + + inrow = outrow = 0; + while (outrow < cinfo->max_v_samp_factor) { + for (v = 0; v < 2; v++) { + /* inptr0 points to nearest input row, inptr1 points to next nearest */ + inptr0 = input_data[inrow]; + if (v == 0) /* next nearest is row above */ + inptr1 = input_data[inrow-1]; + else /* next nearest is row below */ + inptr1 = input_data[inrow+1]; + outptr = output_data[outrow++]; + + /* Special case for first column */ + thiscolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++); + nextcolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++); + *outptr++ = (JSAMPLE) ((thiscolsum * 4 + 8) >> 4); + *outptr++ = (JSAMPLE) ((thiscolsum * 3 + nextcolsum + 7) >> 4); + lastcolsum = thiscolsum; thiscolsum = nextcolsum; + + for (colctr = compptr->downsampled_width - 2; colctr > 0; colctr--) { + /* General case: 3/4 * nearer pixel + 1/4 * further pixel in each */ + /* dimension, thus 9/16, 3/16, 3/16, 1/16 overall */ + nextcolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++); + *outptr++ = (JSAMPLE) ((thiscolsum * 3 + lastcolsum + 8) >> 4); + *outptr++ = (JSAMPLE) ((thiscolsum * 3 + nextcolsum + 7) >> 4); + lastcolsum = thiscolsum; thiscolsum = nextcolsum; + } + + /* Special case for last column */ + *outptr++ = (JSAMPLE) ((thiscolsum * 3 + lastcolsum + 8) >> 4); + *outptr++ = (JSAMPLE) ((thiscolsum * 4 + 7) >> 4); + } + inrow++; + } +} + + +/* + * Module initialization routine for upsampling. + */ + +GLOBAL(void) +jinit_upsampler (j_decompress_ptr cinfo) +{ + my_upsample_ptr upsample; + int ci; + jpeg_component_info * compptr; + boolean need_buffer, do_fancy; + int h_in_group, v_in_group, h_out_group, v_out_group; + + upsample = (my_upsample_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_upsampler)); + cinfo->upsample = (struct jpeg_upsampler *) upsample; + upsample->pub.start_pass = start_pass_upsample; + upsample->pub.upsample = sep_upsample; + upsample->pub.need_context_rows = FALSE; /* until we find out differently */ + + if (cinfo->CCIR601_sampling) /* this isn't supported */ + ERREXIT(cinfo, JERR_CCIR601_NOTIMPL); + + /* jdmainct.c doesn't support context rows when min_DCT_scaled_size = 1, + * so don't ask for it. + */ + do_fancy = cinfo->do_fancy_upsampling && cinfo->min_DCT_scaled_size > 1; + + /* Verify we can handle the sampling factors, select per-component methods, + * and create storage as needed. + */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Compute size of an "input group" after IDCT scaling. This many samples + * are to be converted to max_h_samp_factor * max_v_samp_factor pixels. + */ + h_in_group = (compptr->h_samp_factor * compptr->DCT_scaled_size) / + cinfo->min_DCT_scaled_size; + v_in_group = (compptr->v_samp_factor * compptr->DCT_scaled_size) / + cinfo->min_DCT_scaled_size; + h_out_group = cinfo->max_h_samp_factor; + v_out_group = cinfo->max_v_samp_factor; + upsample->rowgroup_height[ci] = v_in_group; /* save for use later */ + need_buffer = TRUE; + if (! compptr->component_needed) { + /* Don't bother to upsample an uninteresting component. */ + upsample->methods[ci] = noop_upsample; + need_buffer = FALSE; + } else if (h_in_group == h_out_group && v_in_group == v_out_group) { + /* Fullsize components can be processed without any work. */ + upsample->methods[ci] = fullsize_upsample; + need_buffer = FALSE; + } else if (h_in_group * 2 == h_out_group && + v_in_group == v_out_group) { + /* Special cases for 2h1v upsampling */ + if (do_fancy && compptr->downsampled_width > 2) + upsample->methods[ci] = h2v1_fancy_upsample; + else + upsample->methods[ci] = h2v1_upsample; + } else if (h_in_group * 2 == h_out_group && + v_in_group * 2 == v_out_group) { + /* Special cases for 2h2v upsampling */ + if (do_fancy && compptr->downsampled_width > 2) { + upsample->methods[ci] = h2v2_fancy_upsample; + upsample->pub.need_context_rows = TRUE; + } else + upsample->methods[ci] = h2v2_upsample; + } else if ((h_out_group % h_in_group) == 0 && + (v_out_group % v_in_group) == 0) { + /* Generic integral-factors upsampling method */ + upsample->methods[ci] = int_upsample; + upsample->h_expand[ci] = (UINT8) (h_out_group / h_in_group); + upsample->v_expand[ci] = (UINT8) (v_out_group / v_in_group); + } else + ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL); + if (need_buffer) { + upsample->color_buf[ci] = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) jround_up((long) cinfo->output_width, + (long) cinfo->max_h_samp_factor), + (JDIMENSION) cinfo->max_v_samp_factor); + } + } +} diff --git a/jpeg/JDTRANS.C b/jpeg/JDTRANS.C new file mode 100644 index 0000000..078b57a --- /dev/null +++ b/jpeg/JDTRANS.C @@ -0,0 +1,143 @@ +/* + * jdtrans.c + * + * Copyright (C) 1995-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains library routines for transcoding decompression, + * that is, reading raw DCT coefficient arrays from an input JPEG file. + * The routines in jdapimin.c will also be needed by a transcoder. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Forward declarations */ +LOCAL(void) transdecode_master_selection JPP((j_decompress_ptr cinfo)); + + +/* + * Read the coefficient arrays from a JPEG file. + * jpeg_read_header must be completed before calling this. + * + * The entire image is read into a set of virtual coefficient-block arrays, + * one per component. The return value is a pointer to the array of + * virtual-array descriptors. These can be manipulated directly via the + * JPEG memory manager, or handed off to jpeg_write_coefficients(). + * To release the memory occupied by the virtual arrays, call + * jpeg_finish_decompress() when done with the data. + * + * An alternative usage is to simply obtain access to the coefficient arrays + * during a buffered-image-mode decompression operation. This is allowed + * after any jpeg_finish_output() call. The arrays can be accessed until + * jpeg_finish_decompress() is called. (Note that any call to the library + * may reposition the arrays, so don't rely on access_virt_barray() results + * to stay valid across library calls.) + * + * Returns NULL if suspended. This case need be checked only if + * a suspending data source is used. + */ + +GLOBAL(jvirt_barray_ptr *) +jpeg_read_coefficients (j_decompress_ptr cinfo) +{ + if (cinfo->global_state == DSTATE_READY) { + /* First call: initialize active modules */ + transdecode_master_selection(cinfo); + cinfo->global_state = DSTATE_RDCOEFS; + } + if (cinfo->global_state == DSTATE_RDCOEFS) { + /* Absorb whole file into the coef buffer */ + for (;;) { + int retcode; + /* Call progress monitor hook if present */ + if (cinfo->progress != NULL) + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + /* Absorb some more input */ + retcode = (*cinfo->inputctl->consume_input) (cinfo); + if (retcode == JPEG_SUSPENDED) + return NULL; + if (retcode == JPEG_REACHED_EOI) + break; + /* Advance progress counter if appropriate */ + if (cinfo->progress != NULL && + (retcode == JPEG_ROW_COMPLETED || retcode == JPEG_REACHED_SOS)) { + if (++cinfo->progress->pass_counter >= cinfo->progress->pass_limit) { + /* startup underestimated number of scans; ratchet up one scan */ + cinfo->progress->pass_limit += (long) cinfo->total_iMCU_rows; + } + } + } + /* Set state so that jpeg_finish_decompress does the right thing */ + cinfo->global_state = DSTATE_STOPPING; + } + /* At this point we should be in state DSTATE_STOPPING if being used + * standalone, or in state DSTATE_BUFIMAGE if being invoked to get access + * to the coefficients during a full buffered-image-mode decompression. + */ + if ((cinfo->global_state == DSTATE_STOPPING || + cinfo->global_state == DSTATE_BUFIMAGE) && cinfo->buffered_image) { + return cinfo->coef->coef_arrays; + } + /* Oops, improper usage */ + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + return NULL; /* keep compiler happy */ +} + + +/* + * Master selection of decompression modules for transcoding. + * This substitutes for jdmaster.c's initialization of the full decompressor. + */ + +LOCAL(void) +transdecode_master_selection (j_decompress_ptr cinfo) +{ + /* This is effectively a buffered-image operation. */ + cinfo->buffered_image = TRUE; + + /* Entropy decoding: either Huffman or arithmetic coding. */ + if (cinfo->arith_code) { + ERREXIT(cinfo, JERR_ARITH_NOTIMPL); + } else { + if (cinfo->progressive_mode) { +#ifdef D_PROGRESSIVE_SUPPORTED + jinit_phuff_decoder(cinfo); +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else + jinit_huff_decoder(cinfo); + } + + /* Always get a full-image coefficient buffer. */ + jinit_d_coef_controller(cinfo, TRUE); + + /* We can now tell the memory manager to allocate virtual arrays. */ + (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); + + /* Initialize input side of decompressor to consume first scan. */ + (*cinfo->inputctl->start_input_pass) (cinfo); + + /* Initialize progress monitoring. */ + if (cinfo->progress != NULL) { + int nscans; + /* Estimate number of scans to set pass_limit. */ + if (cinfo->progressive_mode) { + /* Arbitrarily estimate 2 interleaved DC scans + 3 AC scans/component. */ + nscans = 2 + 3 * cinfo->num_components; + } else if (cinfo->inputctl->has_multiple_scans) { + /* For a nonprogressive multiscan file, estimate 1 scan per component. */ + nscans = cinfo->num_components; + } else { + nscans = 1; + } + cinfo->progress->pass_counter = 0L; + cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows * nscans; + cinfo->progress->completed_passes = 0; + cinfo->progress->total_passes = 1; + } +} diff --git a/jpeg/JERROR.C b/jpeg/JERROR.C new file mode 100644 index 0000000..4878bc3 --- /dev/null +++ b/jpeg/JERROR.C @@ -0,0 +1,252 @@ +/* + * jerror.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains simple error-reporting and trace-message routines. + * These are suitable for Unix-like systems and others where writing to + * stderr is the right thing to do. Many applications will want to replace + * some or all of these routines. + * + * If you define USE_WINDOWS_MESSAGEBOX in jconfig.h or in the makefile, + * you get a Windows-specific hack to display error messages in a dialog box. + * It ain't much, but it beats dropping error messages into the bit bucket, + * which is what happens to output to stderr under most Windows C compilers. + * + * These routines are used by both the compression and decompression code. + */ + +/* this is not a core library module, so it doesn't define JPEG_INTERNALS */ +#include "jinclude.h" +#include "jpeglib.h" +#include "jversion.h" +#include "jerror.h" + +#ifdef USE_WINDOWS_MESSAGEBOX +#include +#endif + +#ifndef EXIT_FAILURE /* define exit() codes if not provided */ +#define EXIT_FAILURE 1 +#endif + + +/* + * Create the message string table. + * We do this from the master message list in jerror.h by re-reading + * jerror.h with a suitable definition for macro JMESSAGE. + * The message table is made an external symbol just in case any applications + * want to refer to it directly. + */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jpeg_std_message_table jMsgTable +#endif + +#define JMESSAGE(code,string) string , + +const char * const jpeg_std_message_table[] = { +#include "jerror.h" + NULL +}; + + +/* + * Error exit handler: must not return to caller. + * + * Applications may override this if they want to get control back after + * an error. Typically one would longjmp somewhere instead of exiting. + * The setjmp buffer can be made a private field within an expanded error + * handler object. Note that the info needed to generate an error message + * is stored in the error object, so you can generate the message now or + * later, at your convenience. + * You should make sure that the JPEG object is cleaned up (with jpeg_abort + * or jpeg_destroy) at some point. + */ + +METHODDEF(void) +error_exit (j_common_ptr cinfo) +{ + /* Always display the message */ + (*cinfo->err->output_message) (cinfo); + + /* Let the memory manager delete any temp files before we die */ + jpeg_destroy(cinfo); + + exit(EXIT_FAILURE); +} + + +/* + * Actual output of an error or trace message. + * Applications may override this method to send JPEG messages somewhere + * other than stderr. + * + * On Windows, printing to stderr is generally completely useless, + * so we provide optional code to produce an error-dialog popup. + * Most Windows applications will still prefer to override this routine, + * but if they don't, it'll do something at least marginally useful. + * + * NOTE: to use the library in an environment that doesn't support the + * C stdio library, you may have to delete the call to fprintf() entirely, + * not just not use this routine. + */ + +METHODDEF(void) +output_message (j_common_ptr cinfo) +{ + char buffer[JMSG_LENGTH_MAX]; + + /* Create the message */ + (*cinfo->err->format_message) (cinfo, buffer); + +#ifdef USE_WINDOWS_MESSAGEBOX + /* Display it in a message dialog box */ + MessageBox(GetActiveWindow(), buffer, "JPEG Library Error", + MB_OK | MB_ICONERROR); +#else + /* Send it to stderr, adding a newline */ + fprintf(stderr, "%s\n", buffer); +#endif +} + + +/* + * Decide whether to emit a trace or warning message. + * msg_level is one of: + * -1: recoverable corrupt-data warning, may want to abort. + * 0: important advisory messages (always display to user). + * 1: first level of tracing detail. + * 2,3,...: successively more detailed tracing messages. + * An application might override this method if it wanted to abort on warnings + * or change the policy about which messages to display. + */ + +METHODDEF(void) +emit_message (j_common_ptr cinfo, int msg_level) +{ + struct jpeg_error_mgr * err = cinfo->err; + + if (msg_level < 0) { + /* It's a warning message. Since corrupt files may generate many warnings, + * the policy implemented here is to show only the first warning, + * unless trace_level >= 3. + */ + if (err->num_warnings == 0 || err->trace_level >= 3) + (*err->output_message) (cinfo); + /* Always count warnings in num_warnings. */ + err->num_warnings++; + } else { + /* It's a trace message. Show it if trace_level >= msg_level. */ + if (err->trace_level >= msg_level) + (*err->output_message) (cinfo); + } +} + + +/* + * Format a message string for the most recent JPEG error or message. + * The message is stored into buffer, which should be at least JMSG_LENGTH_MAX + * characters. Note that no '\n' character is added to the string. + * Few applications should need to override this method. + */ + +METHODDEF(void) +format_message (j_common_ptr cinfo, char * buffer) +{ + struct jpeg_error_mgr * err = cinfo->err; + int msg_code = err->msg_code; + const char * msgtext = NULL; + const char * msgptr; + char ch; + boolean isstring; + + /* Look up message string in proper table */ + if (msg_code > 0 && msg_code <= err->last_jpeg_message) { + msgtext = err->jpeg_message_table[msg_code]; + } else if (err->addon_message_table != NULL && + msg_code >= err->first_addon_message && + msg_code <= err->last_addon_message) { + msgtext = err->addon_message_table[msg_code - err->first_addon_message]; + } + + /* Defend against bogus message number */ + if (msgtext == NULL) { + err->msg_parm.i[0] = msg_code; + msgtext = err->jpeg_message_table[0]; + } + + /* Check for string parameter, as indicated by %s in the message text */ + isstring = FALSE; + msgptr = msgtext; + while ((ch = *msgptr++) != '\0') { + if (ch == '%') { + if (*msgptr == 's') isstring = TRUE; + break; + } + } + + /* Format the message into the passed buffer */ + if (isstring) + sprintf(buffer, msgtext, err->msg_parm.s); + else + sprintf(buffer, msgtext, + err->msg_parm.i[0], err->msg_parm.i[1], + err->msg_parm.i[2], err->msg_parm.i[3], + err->msg_parm.i[4], err->msg_parm.i[5], + err->msg_parm.i[6], err->msg_parm.i[7]); +} + + +/* + * Reset error state variables at start of a new image. + * This is called during compression startup to reset trace/error + * processing to default state, without losing any application-specific + * method pointers. An application might possibly want to override + * this method if it has additional error processing state. + */ + +METHODDEF(void) +reset_error_mgr (j_common_ptr cinfo) +{ + cinfo->err->num_warnings = 0; + /* trace_level is not reset since it is an application-supplied parameter */ + cinfo->err->msg_code = 0; /* may be useful as a flag for "no error" */ +} + + +/* + * Fill in the standard error-handling methods in a jpeg_error_mgr object. + * Typical call is: + * struct jpeg_compress_struct cinfo; + * struct jpeg_error_mgr err; + * + * cinfo.err = jpeg_std_error(&err); + * after which the application may override some of the methods. + */ + +GLOBAL(struct jpeg_error_mgr *) +jpeg_std_error (struct jpeg_error_mgr * err) +{ + err->error_exit = error_exit; + err->emit_message = emit_message; + err->output_message = output_message; + err->format_message = format_message; + err->reset_error_mgr = reset_error_mgr; + + err->trace_level = 0; /* default = no tracing */ + err->num_warnings = 0; /* no warnings emitted yet */ + err->msg_code = 0; /* may be useful as a flag for "no error" */ + + /* Initialize message table pointers */ + err->jpeg_message_table = jpeg_std_message_table; + err->last_jpeg_message = (int) JMSG_LASTMSGCODE - 1; + + err->addon_message_table = NULL; + err->first_addon_message = 0; /* for safety */ + err->last_addon_message = 0; + + return err; +} diff --git a/jpeg/JERROR.H b/jpeg/JERROR.H new file mode 100644 index 0000000..fc2fffe --- /dev/null +++ b/jpeg/JERROR.H @@ -0,0 +1,291 @@ +/* + * jerror.h + * + * Copyright (C) 1994-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file defines the error and message codes for the JPEG library. + * Edit this file to add new codes, or to translate the message strings to + * some other language. + * A set of error-reporting macros are defined too. Some applications using + * the JPEG library may wish to include this file to get the error codes + * and/or the macros. + */ + +/* + * To define the enum list of message codes, include this file without + * defining macro JMESSAGE. To create a message string table, include it + * again with a suitable JMESSAGE definition (see jerror.c for an example). + */ +#ifndef JMESSAGE +#ifndef JERROR_H +/* First time through, define the enum list */ +#define JMAKE_ENUM_LIST +#else +/* Repeated inclusions of this file are no-ops unless JMESSAGE is defined */ +#define JMESSAGE(code,string) +#endif /* JERROR_H */ +#endif /* JMESSAGE */ + +#ifdef JMAKE_ENUM_LIST + +typedef enum { + +#define JMESSAGE(code,string) code , + +#endif /* JMAKE_ENUM_LIST */ + +JMESSAGE(JMSG_NOMESSAGE, "Bogus message code %d") /* Must be first entry! */ + +/* For maintenance convenience, list is alphabetical by message code name */ +JMESSAGE(JERR_ARITH_NOTIMPL, + "Sorry, there are legal restrictions on arithmetic coding") +JMESSAGE(JERR_BAD_ALIGN_TYPE, "ALIGN_TYPE is wrong, please fix") +JMESSAGE(JERR_BAD_ALLOC_CHUNK, "MAX_ALLOC_CHUNK is wrong, please fix") +JMESSAGE(JERR_BAD_BUFFER_MODE, "Bogus buffer control mode") +JMESSAGE(JERR_BAD_COMPONENT_ID, "Invalid component ID %d in SOS") +JMESSAGE(JERR_BAD_DCT_COEF, "DCT coefficient out of range") +JMESSAGE(JERR_BAD_DCTSIZE, "IDCT output block size %d not supported") +JMESSAGE(JERR_BAD_HUFF_TABLE, "Bogus Huffman table definition") +JMESSAGE(JERR_BAD_IN_COLORSPACE, "Bogus input colorspace") +JMESSAGE(JERR_BAD_J_COLORSPACE, "Bogus JPEG colorspace") +JMESSAGE(JERR_BAD_LENGTH, "Bogus marker length") +JMESSAGE(JERR_BAD_LIB_VERSION, + "Wrong JPEG library version: library is %d, caller expects %d") +JMESSAGE(JERR_BAD_MCU_SIZE, "Sampling factors too large for interleaved scan") +JMESSAGE(JERR_BAD_POOL_ID, "Invalid memory pool code %d") +JMESSAGE(JERR_BAD_PRECISION, "Unsupported JPEG data precision %d") +JMESSAGE(JERR_BAD_PROGRESSION, + "Invalid progressive parameters Ss=%d Se=%d Ah=%d Al=%d") +JMESSAGE(JERR_BAD_PROG_SCRIPT, + "Invalid progressive parameters at scan script entry %d") +JMESSAGE(JERR_BAD_SAMPLING, "Bogus sampling factors") +JMESSAGE(JERR_BAD_SCAN_SCRIPT, "Invalid scan script at entry %d") +JMESSAGE(JERR_BAD_STATE, "Improper call to JPEG library in state %d") +JMESSAGE(JERR_BAD_STRUCT_SIZE, + "JPEG parameter struct mismatch: library thinks size is %u, caller expects %u") +JMESSAGE(JERR_BAD_VIRTUAL_ACCESS, "Bogus virtual array access") +JMESSAGE(JERR_BUFFER_SIZE, "Buffer passed to JPEG library is too small") +JMESSAGE(JERR_CANT_SUSPEND, "Suspension not allowed here") +JMESSAGE(JERR_CCIR601_NOTIMPL, "CCIR601 sampling not implemented yet") +JMESSAGE(JERR_COMPONENT_COUNT, "Too many color components: %d, max %d") +JMESSAGE(JERR_CONVERSION_NOTIMPL, "Unsupported color conversion request") +JMESSAGE(JERR_DAC_INDEX, "Bogus DAC index %d") +JMESSAGE(JERR_DAC_VALUE, "Bogus DAC value 0x%x") +JMESSAGE(JERR_DHT_INDEX, "Bogus DHT index %d") +JMESSAGE(JERR_DQT_INDEX, "Bogus DQT index %d") +JMESSAGE(JERR_EMPTY_IMAGE, "Empty JPEG image (DNL not supported)") +JMESSAGE(JERR_EMS_READ, "Read from EMS failed") +JMESSAGE(JERR_EMS_WRITE, "Write to EMS failed") +JMESSAGE(JERR_EOI_EXPECTED, "Didn't expect more than one scan") +JMESSAGE(JERR_FILE_READ, "Input file read error") +JMESSAGE(JERR_FILE_WRITE, "Output file write error --- out of disk space?") +JMESSAGE(JERR_FRACT_SAMPLE_NOTIMPL, "Fractional sampling not implemented yet") +JMESSAGE(JERR_HUFF_CLEN_OVERFLOW, "Huffman code size table overflow") +JMESSAGE(JERR_HUFF_MISSING_CODE, "Missing Huffman code table entry") +JMESSAGE(JERR_IMAGE_TOO_BIG, "Maximum supported image dimension is %u pixels") +JMESSAGE(JERR_INPUT_EMPTY, "Empty input file") +JMESSAGE(JERR_INPUT_EOF, "Premature end of input file") +JMESSAGE(JERR_MISMATCHED_QUANT_TABLE, + "Cannot transcode due to multiple use of quantization table %d") +JMESSAGE(JERR_MISSING_DATA, "Scan script does not transmit all data") +JMESSAGE(JERR_MODE_CHANGE, "Invalid color quantization mode change") +JMESSAGE(JERR_NOTIMPL, "Not implemented yet") +JMESSAGE(JERR_NOT_COMPILED, "Requested feature was omitted at compile time") +JMESSAGE(JERR_NO_BACKING_STORE, "Backing store not supported") +JMESSAGE(JERR_NO_HUFF_TABLE, "Huffman table 0x%02x was not defined") +JMESSAGE(JERR_NO_IMAGE, "JPEG datastream contains no image") +JMESSAGE(JERR_NO_QUANT_TABLE, "Quantization table 0x%02x was not defined") +JMESSAGE(JERR_NO_SOI, "Not a JPEG file: starts with 0x%02x 0x%02x") +JMESSAGE(JERR_OUT_OF_MEMORY, "Insufficient memory (case %d)") +JMESSAGE(JERR_QUANT_COMPONENTS, + "Cannot quantize more than %d color components") +JMESSAGE(JERR_QUANT_FEW_COLORS, "Cannot quantize to fewer than %d colors") +JMESSAGE(JERR_QUANT_MANY_COLORS, "Cannot quantize to more than %d colors") +JMESSAGE(JERR_SOF_DUPLICATE, "Invalid JPEG file structure: two SOF markers") +JMESSAGE(JERR_SOF_NO_SOS, "Invalid JPEG file structure: missing SOS marker") +JMESSAGE(JERR_SOF_UNSUPPORTED, "Unsupported JPEG process: SOF type 0x%02x") +JMESSAGE(JERR_SOI_DUPLICATE, "Invalid JPEG file structure: two SOI markers") +JMESSAGE(JERR_SOS_NO_SOF, "Invalid JPEG file structure: SOS before SOF") +JMESSAGE(JERR_TFILE_CREATE, "Failed to create temporary file %s") +JMESSAGE(JERR_TFILE_READ, "Read failed on temporary file") +JMESSAGE(JERR_TFILE_SEEK, "Seek failed on temporary file") +JMESSAGE(JERR_TFILE_WRITE, + "Write failed on temporary file --- out of disk space?") +JMESSAGE(JERR_TOO_LITTLE_DATA, "Application transferred too few scanlines") +JMESSAGE(JERR_UNKNOWN_MARKER, "Unsupported marker type 0x%02x") +JMESSAGE(JERR_VIRTUAL_BUG, "Virtual array controller messed up") +JMESSAGE(JERR_WIDTH_OVERFLOW, "Image too wide for this implementation") +JMESSAGE(JERR_XMS_READ, "Read from XMS failed") +JMESSAGE(JERR_XMS_WRITE, "Write to XMS failed") +JMESSAGE(JMSG_COPYRIGHT, JCOPYRIGHT) +JMESSAGE(JMSG_VERSION, JVERSION) +JMESSAGE(JTRC_16BIT_TABLES, + "Caution: quantization tables are too coarse for baseline JPEG") +JMESSAGE(JTRC_ADOBE, + "Adobe APP14 marker: version %d, flags 0x%04x 0x%04x, transform %d") +JMESSAGE(JTRC_APP0, "Unknown APP0 marker (not JFIF), length %u") +JMESSAGE(JTRC_APP14, "Unknown APP14 marker (not Adobe), length %u") +JMESSAGE(JTRC_DAC, "Define Arithmetic Table 0x%02x: 0x%02x") +JMESSAGE(JTRC_DHT, "Define Huffman Table 0x%02x") +JMESSAGE(JTRC_DQT, "Define Quantization Table %d precision %d") +JMESSAGE(JTRC_DRI, "Define Restart Interval %u") +JMESSAGE(JTRC_EMS_CLOSE, "Freed EMS handle %u") +JMESSAGE(JTRC_EMS_OPEN, "Obtained EMS handle %u") +JMESSAGE(JTRC_EOI, "End Of Image") +JMESSAGE(JTRC_HUFFBITS, " %3d %3d %3d %3d %3d %3d %3d %3d") +JMESSAGE(JTRC_JFIF, "JFIF APP0 marker: version %d.%02d, density %dx%d %d") +JMESSAGE(JTRC_JFIF_BADTHUMBNAILSIZE, + "Warning: thumbnail image size does not match data length %u") +JMESSAGE(JTRC_JFIF_EXTENSION, + "JFIF extension marker: type 0x%02x, length %u") +JMESSAGE(JTRC_JFIF_THUMBNAIL, " with %d x %d thumbnail image") +JMESSAGE(JTRC_MISC_MARKER, "Miscellaneous marker 0x%02x, length %u") +JMESSAGE(JTRC_PARMLESS_MARKER, "Unexpected marker 0x%02x") +JMESSAGE(JTRC_QUANTVALS, " %4u %4u %4u %4u %4u %4u %4u %4u") +JMESSAGE(JTRC_QUANT_3_NCOLORS, "Quantizing to %d = %d*%d*%d colors") +JMESSAGE(JTRC_QUANT_NCOLORS, "Quantizing to %d colors") +JMESSAGE(JTRC_QUANT_SELECTED, "Selected %d colors for quantization") +JMESSAGE(JTRC_RECOVERY_ACTION, "At marker 0x%02x, recovery action %d") +JMESSAGE(JTRC_RST, "RST%d") +JMESSAGE(JTRC_SMOOTH_NOTIMPL, + "Smoothing not supported with nonstandard sampling ratios") +JMESSAGE(JTRC_SOF, "Start Of Frame 0x%02x: width=%u, height=%u, components=%d") +JMESSAGE(JTRC_SOF_COMPONENT, " Component %d: %dhx%dv q=%d") +JMESSAGE(JTRC_SOI, "Start of Image") +JMESSAGE(JTRC_SOS, "Start Of Scan: %d components") +JMESSAGE(JTRC_SOS_COMPONENT, " Component %d: dc=%d ac=%d") +JMESSAGE(JTRC_SOS_PARAMS, " Ss=%d, Se=%d, Ah=%d, Al=%d") +JMESSAGE(JTRC_TFILE_CLOSE, "Closed temporary file %s") +JMESSAGE(JTRC_TFILE_OPEN, "Opened temporary file %s") +JMESSAGE(JTRC_THUMB_JPEG, + "JFIF extension marker: JPEG-compressed thumbnail image, length %u") +JMESSAGE(JTRC_THUMB_PALETTE, + "JFIF extension marker: palette thumbnail image, length %u") +JMESSAGE(JTRC_THUMB_RGB, + "JFIF extension marker: RGB thumbnail image, length %u") +JMESSAGE(JTRC_UNKNOWN_IDS, + "Unrecognized component IDs %d %d %d, assuming YCbCr") +JMESSAGE(JTRC_XMS_CLOSE, "Freed XMS handle %u") +JMESSAGE(JTRC_XMS_OPEN, "Obtained XMS handle %u") +JMESSAGE(JWRN_ADOBE_XFORM, "Unknown Adobe color transform code %d") +JMESSAGE(JWRN_BOGUS_PROGRESSION, + "Inconsistent progression sequence for component %d coefficient %d") +JMESSAGE(JWRN_EXTRANEOUS_DATA, + "Corrupt JPEG data: %u extraneous bytes before marker 0x%02x") +JMESSAGE(JWRN_HIT_MARKER, "Corrupt JPEG data: premature end of data segment") +JMESSAGE(JWRN_HUFF_BAD_CODE, "Corrupt JPEG data: bad Huffman code") +JMESSAGE(JWRN_JFIF_MAJOR, "Warning: unknown JFIF revision number %d.%02d") +JMESSAGE(JWRN_JPEG_EOF, "Premature end of JPEG file") +JMESSAGE(JWRN_MUST_RESYNC, + "Corrupt JPEG data: found marker 0x%02x instead of RST%d") +JMESSAGE(JWRN_NOT_SEQUENTIAL, "Invalid SOS parameters for sequential JPEG") +JMESSAGE(JWRN_TOO_MUCH_DATA, "Application transferred too many scanlines") + +#ifdef JMAKE_ENUM_LIST + + JMSG_LASTMSGCODE +} J_MESSAGE_CODE; + +#undef JMAKE_ENUM_LIST +#endif /* JMAKE_ENUM_LIST */ + +/* Zap JMESSAGE macro so that future re-inclusions do nothing by default */ +#undef JMESSAGE + + +#ifndef JERROR_H +#define JERROR_H + +/* Macros to simplify using the error and trace message stuff */ +/* The first parameter is either type of cinfo pointer */ + +/* Fatal errors (print message and exit) */ +#define ERREXIT(cinfo,code) \ + ((cinfo)->err->msg_code = (code), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT1(cinfo,code,p1) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT2(cinfo,code,p1,p2) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT3(cinfo,code,p1,p2,p3) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (cinfo)->err->msg_parm.i[2] = (p3), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT4(cinfo,code,p1,p2,p3,p4) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (cinfo)->err->msg_parm.i[2] = (p3), \ + (cinfo)->err->msg_parm.i[3] = (p4), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXITS(cinfo,code,str) \ + ((cinfo)->err->msg_code = (code), \ + strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) + +#define MAKESTMT(stuff) do { stuff } while (0) + +/* Nonfatal errors (we can keep going, but the data is probably corrupt) */ +#define WARNMS(cinfo,code) \ + ((cinfo)->err->msg_code = (code), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) +#define WARNMS1(cinfo,code,p1) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) +#define WARNMS2(cinfo,code,p1,p2) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) + +/* Informational/debugging messages */ +#define TRACEMS(cinfo,lvl,code) \ + ((cinfo)->err->msg_code = (code), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) +#define TRACEMS1(cinfo,lvl,code,p1) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) +#define TRACEMS2(cinfo,lvl,code,p1,p2) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) +#define TRACEMS3(cinfo,lvl,code,p1,p2,p3) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMS4(cinfo,lvl,code,p1,p2,p3,p4) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMS5(cinfo,lvl,code,p1,p2,p3,p4,p5) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + _mp[4] = (p5); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMS8(cinfo,lvl,code,p1,p2,p3,p4,p5,p6,p7,p8) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + _mp[4] = (p5); _mp[5] = (p6); _mp[6] = (p7); _mp[7] = (p8); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMSS(cinfo,lvl,code,str) \ + ((cinfo)->err->msg_code = (code), \ + strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) + +#endif /* JERROR_H */ diff --git a/jpeg/JFDCTFLT.C b/jpeg/JFDCTFLT.C new file mode 100644 index 0000000..f001394 --- /dev/null +++ b/jpeg/JFDCTFLT.C @@ -0,0 +1,168 @@ +/* + * jfdctflt.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains a floating-point implementation of the + * forward DCT (Discrete Cosine Transform). + * + * This implementation should be more accurate than either of the integer + * DCT implementations. However, it may not give the same results on all + * machines because of differences in roundoff behavior. Speed will depend + * on the hardware's floating point capacity. + * + * A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT + * on each column. Direct algorithms are also available, but they are + * much more complex and seem not to be any faster when reduced to code. + * + * This implementation is based on Arai, Agui, and Nakajima's algorithm for + * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in + * Japanese, but the algorithm is described in the Pennebaker & Mitchell + * JPEG textbook (see REFERENCES section in file README). The following code + * is based directly on figure 4-8 in P&M. + * While an 8-point DCT cannot be done in less than 11 multiplies, it is + * possible to arrange the computation so that many of the multiplies are + * simple scalings of the final outputs. These multiplies can then be + * folded into the multiplications or divisions by the JPEG quantization + * table entries. The AA&N method leaves only 5 multiplies and 29 adds + * to be done in the DCT itself. + * The primary disadvantage of this method is that with a fixed-point + * implementation, accuracy is lost due to imprecise representation of the + * scaled quantization values. However, that problem does not arise if + * we use floating point arithmetic. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jdct.h" /* Private declarations for DCT subsystem */ + +#ifdef DCT_FLOAT_SUPPORTED + + +/* + * This module is specialized to the case DCTSIZE = 8. + */ + +#if DCTSIZE != 8 + Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ +#endif + + +/* + * Perform the forward DCT on one block of samples. + */ + +GLOBAL(void) +jpeg_fdct_float (FAST_FLOAT * data) +{ + FAST_FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + FAST_FLOAT tmp10, tmp11, tmp12, tmp13; + FAST_FLOAT z1, z2, z3, z4, z5, z11, z13; + FAST_FLOAT *dataptr; + int ctr; + + /* Pass 1: process rows. */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + tmp0 = dataptr[0] + dataptr[7]; + tmp7 = dataptr[0] - dataptr[7]; + tmp1 = dataptr[1] + dataptr[6]; + tmp6 = dataptr[1] - dataptr[6]; + tmp2 = dataptr[2] + dataptr[5]; + tmp5 = dataptr[2] - dataptr[5]; + tmp3 = dataptr[3] + dataptr[4]; + tmp4 = dataptr[3] - dataptr[4]; + + /* Even part */ + + tmp10 = tmp0 + tmp3; /* phase 2 */ + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + dataptr[0] = tmp10 + tmp11; /* phase 3 */ + dataptr[4] = tmp10 - tmp11; + + z1 = (tmp12 + tmp13) * ((FAST_FLOAT) 0.707106781); /* c4 */ + dataptr[2] = tmp13 + z1; /* phase 5 */ + dataptr[6] = tmp13 - z1; + + /* Odd part */ + + tmp10 = tmp4 + tmp5; /* phase 2 */ + tmp11 = tmp5 + tmp6; + tmp12 = tmp6 + tmp7; + + /* The rotator is modified from fig 4-8 to avoid extra negations. */ + z5 = (tmp10 - tmp12) * ((FAST_FLOAT) 0.382683433); /* c6 */ + z2 = ((FAST_FLOAT) 0.541196100) * tmp10 + z5; /* c2-c6 */ + z4 = ((FAST_FLOAT) 1.306562965) * tmp12 + z5; /* c2+c6 */ + z3 = tmp11 * ((FAST_FLOAT) 0.707106781); /* c4 */ + + z11 = tmp7 + z3; /* phase 5 */ + z13 = tmp7 - z3; + + dataptr[5] = z13 + z2; /* phase 6 */ + dataptr[3] = z13 - z2; + dataptr[1] = z11 + z4; + dataptr[7] = z11 - z4; + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; + tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; + tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; + tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; + tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; + tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; + tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; + tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; + + /* Even part */ + + tmp10 = tmp0 + tmp3; /* phase 2 */ + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + dataptr[DCTSIZE*0] = tmp10 + tmp11; /* phase 3 */ + dataptr[DCTSIZE*4] = tmp10 - tmp11; + + z1 = (tmp12 + tmp13) * ((FAST_FLOAT) 0.707106781); /* c4 */ + dataptr[DCTSIZE*2] = tmp13 + z1; /* phase 5 */ + dataptr[DCTSIZE*6] = tmp13 - z1; + + /* Odd part */ + + tmp10 = tmp4 + tmp5; /* phase 2 */ + tmp11 = tmp5 + tmp6; + tmp12 = tmp6 + tmp7; + + /* The rotator is modified from fig 4-8 to avoid extra negations. */ + z5 = (tmp10 - tmp12) * ((FAST_FLOAT) 0.382683433); /* c6 */ + z2 = ((FAST_FLOAT) 0.541196100) * tmp10 + z5; /* c2-c6 */ + z4 = ((FAST_FLOAT) 1.306562965) * tmp12 + z5; /* c2+c6 */ + z3 = tmp11 * ((FAST_FLOAT) 0.707106781); /* c4 */ + + z11 = tmp7 + z3; /* phase 5 */ + z13 = tmp7 - z3; + + dataptr[DCTSIZE*5] = z13 + z2; /* phase 6 */ + dataptr[DCTSIZE*3] = z13 - z2; + dataptr[DCTSIZE*1] = z11 + z4; + dataptr[DCTSIZE*7] = z11 - z4; + + dataptr++; /* advance pointer to next column */ + } +} + +#endif /* DCT_FLOAT_SUPPORTED */ diff --git a/jpeg/JFDCTFST.C b/jpeg/JFDCTFST.C new file mode 100644 index 0000000..12bf805 --- /dev/null +++ b/jpeg/JFDCTFST.C @@ -0,0 +1,224 @@ +/* + * jfdctfst.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains a fast, not so accurate integer implementation of the + * forward DCT (Discrete Cosine Transform). + * + * A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT + * on each column. Direct algorithms are also available, but they are + * much more complex and seem not to be any faster when reduced to code. + * + * This implementation is based on Arai, Agui, and Nakajima's algorithm for + * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in + * Japanese, but the algorithm is described in the Pennebaker & Mitchell + * JPEG textbook (see REFERENCES section in file README). The following code + * is based directly on figure 4-8 in P&M. + * While an 8-point DCT cannot be done in less than 11 multiplies, it is + * possible to arrange the computation so that many of the multiplies are + * simple scalings of the final outputs. These multiplies can then be + * folded into the multiplications or divisions by the JPEG quantization + * table entries. The AA&N method leaves only 5 multiplies and 29 adds + * to be done in the DCT itself. + * The primary disadvantage of this method is that with fixed-point math, + * accuracy is lost due to imprecise representation of the scaled + * quantization values. The smaller the quantization table entry, the less + * precise the scaled value, so this implementation does worse with high- + * quality-setting files than with low-quality ones. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jdct.h" /* Private declarations for DCT subsystem */ + +#ifdef DCT_IFAST_SUPPORTED + + +/* + * This module is specialized to the case DCTSIZE = 8. + */ + +#if DCTSIZE != 8 + Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ +#endif + + +/* Scaling decisions are generally the same as in the LL&M algorithm; + * see jfdctint.c for more details. However, we choose to descale + * (right shift) multiplication products as soon as they are formed, + * rather than carrying additional fractional bits into subsequent additions. + * This compromises accuracy slightly, but it lets us save a few shifts. + * More importantly, 16-bit arithmetic is then adequate (for 8-bit samples) + * everywhere except in the multiplications proper; this saves a good deal + * of work on 16-bit-int machines. + * + * Again to save a few shifts, the intermediate results between pass 1 and + * pass 2 are not upscaled, but are represented only to integral precision. + * + * A final compromise is to represent the multiplicative constants to only + * 8 fractional bits, rather than 13. This saves some shifting work on some + * machines, and may also reduce the cost of multiplication (since there + * are fewer one-bits in the constants). + */ + +#define CONST_BITS 8 + + +/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus + * causing a lot of useless floating-point operations at run time. + * To get around this we use the following pre-calculated constants. + * If you change CONST_BITS you may want to add appropriate values. + * (With a reasonable C compiler, you can just rely on the FIX() macro...) + */ + +#if CONST_BITS == 8 +#define FIX_0_382683433 ((INT32) 98) /* FIX(0.382683433) */ +#define FIX_0_541196100 ((INT32) 139) /* FIX(0.541196100) */ +#define FIX_0_707106781 ((INT32) 181) /* FIX(0.707106781) */ +#define FIX_1_306562965 ((INT32) 334) /* FIX(1.306562965) */ +#else +#define FIX_0_382683433 FIX(0.382683433) +#define FIX_0_541196100 FIX(0.541196100) +#define FIX_0_707106781 FIX(0.707106781) +#define FIX_1_306562965 FIX(1.306562965) +#endif + + +/* We can gain a little more speed, with a further compromise in accuracy, + * by omitting the addition in a descaling shift. This yields an incorrectly + * rounded result half the time... + */ + +#ifndef USE_ACCURATE_ROUNDING +#undef DESCALE +#define DESCALE(x,n) RIGHT_SHIFT(x, n) +#endif + + +/* Multiply a DCTELEM variable by an INT32 constant, and immediately + * descale to yield a DCTELEM result. + */ + +#define MULTIPLY(var,const) ((DCTELEM) DESCALE((var) * (const), CONST_BITS)) + + +/* + * Perform the forward DCT on one block of samples. + */ + +GLOBAL(void) +jpeg_fdct_ifast (DCTELEM * data) +{ + DCTELEM tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + DCTELEM tmp10, tmp11, tmp12, tmp13; + DCTELEM z1, z2, z3, z4, z5, z11, z13; + DCTELEM *dataptr; + int ctr; + SHIFT_TEMPS + + /* Pass 1: process rows. */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + tmp0 = dataptr[0] + dataptr[7]; + tmp7 = dataptr[0] - dataptr[7]; + tmp1 = dataptr[1] + dataptr[6]; + tmp6 = dataptr[1] - dataptr[6]; + tmp2 = dataptr[2] + dataptr[5]; + tmp5 = dataptr[2] - dataptr[5]; + tmp3 = dataptr[3] + dataptr[4]; + tmp4 = dataptr[3] - dataptr[4]; + + /* Even part */ + + tmp10 = tmp0 + tmp3; /* phase 2 */ + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + dataptr[0] = tmp10 + tmp11; /* phase 3 */ + dataptr[4] = tmp10 - tmp11; + + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781); /* c4 */ + dataptr[2] = tmp13 + z1; /* phase 5 */ + dataptr[6] = tmp13 - z1; + + /* Odd part */ + + tmp10 = tmp4 + tmp5; /* phase 2 */ + tmp11 = tmp5 + tmp6; + tmp12 = tmp6 + tmp7; + + /* The rotator is modified from fig 4-8 to avoid extra negations. */ + z5 = MULTIPLY(tmp10 - tmp12, FIX_0_382683433); /* c6 */ + z2 = MULTIPLY(tmp10, FIX_0_541196100) + z5; /* c2-c6 */ + z4 = MULTIPLY(tmp12, FIX_1_306562965) + z5; /* c2+c6 */ + z3 = MULTIPLY(tmp11, FIX_0_707106781); /* c4 */ + + z11 = tmp7 + z3; /* phase 5 */ + z13 = tmp7 - z3; + + dataptr[5] = z13 + z2; /* phase 6 */ + dataptr[3] = z13 - z2; + dataptr[1] = z11 + z4; + dataptr[7] = z11 - z4; + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; + tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; + tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; + tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; + tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; + tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; + tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; + tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; + + /* Even part */ + + tmp10 = tmp0 + tmp3; /* phase 2 */ + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + dataptr[DCTSIZE*0] = tmp10 + tmp11; /* phase 3 */ + dataptr[DCTSIZE*4] = tmp10 - tmp11; + + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781); /* c4 */ + dataptr[DCTSIZE*2] = tmp13 + z1; /* phase 5 */ + dataptr[DCTSIZE*6] = tmp13 - z1; + + /* Odd part */ + + tmp10 = tmp4 + tmp5; /* phase 2 */ + tmp11 = tmp5 + tmp6; + tmp12 = tmp6 + tmp7; + + /* The rotator is modified from fig 4-8 to avoid extra negations. */ + z5 = MULTIPLY(tmp10 - tmp12, FIX_0_382683433); /* c6 */ + z2 = MULTIPLY(tmp10, FIX_0_541196100) + z5; /* c2-c6 */ + z4 = MULTIPLY(tmp12, FIX_1_306562965) + z5; /* c2+c6 */ + z3 = MULTIPLY(tmp11, FIX_0_707106781); /* c4 */ + + z11 = tmp7 + z3; /* phase 5 */ + z13 = tmp7 - z3; + + dataptr[DCTSIZE*5] = z13 + z2; /* phase 6 */ + dataptr[DCTSIZE*3] = z13 - z2; + dataptr[DCTSIZE*1] = z11 + z4; + dataptr[DCTSIZE*7] = z11 - z4; + + dataptr++; /* advance pointer to next column */ + } +} + +#endif /* DCT_IFAST_SUPPORTED */ diff --git a/jpeg/JFDCTINT.C b/jpeg/JFDCTINT.C new file mode 100644 index 0000000..0455734 --- /dev/null +++ b/jpeg/JFDCTINT.C @@ -0,0 +1,283 @@ +/* + * jfdctint.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains a slow-but-accurate integer implementation of the + * forward DCT (Discrete Cosine Transform). + * + * A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT + * on each column. Direct algorithms are also available, but they are + * much more complex and seem not to be any faster when reduced to code. + * + * This implementation is based on an algorithm described in + * C. Loeffler, A. Ligtenberg and G. Moschytz, "Practical Fast 1-D DCT + * Algorithms with 11 Multiplications", Proc. Int'l. Conf. on Acoustics, + * Speech, and Signal Processing 1989 (ICASSP '89), pp. 988-991. + * The primary algorithm described there uses 11 multiplies and 29 adds. + * We use their alternate method with 12 multiplies and 32 adds. + * The advantage of this method is that no data path contains more than one + * multiplication; this allows a very simple and accurate implementation in + * scaled fixed-point arithmetic, with a minimal number of shifts. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jdct.h" /* Private declarations for DCT subsystem */ + +#ifdef DCT_ISLOW_SUPPORTED + + +/* + * This module is specialized to the case DCTSIZE = 8. + */ + +#if DCTSIZE != 8 + Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ +#endif + + +/* + * The poop on this scaling stuff is as follows: + * + * Each 1-D DCT step produces outputs which are a factor of sqrt(N) + * larger than the true DCT outputs. The final outputs are therefore + * a factor of N larger than desired; since N=8 this can be cured by + * a simple right shift at the end of the algorithm. The advantage of + * this arrangement is that we save two multiplications per 1-D DCT, + * because the y0 and y4 outputs need not be divided by sqrt(N). + * In the IJG code, this factor of 8 is removed by the quantization step + * (in jcdctmgr.c), NOT in this module. + * + * We have to do addition and subtraction of the integer inputs, which + * is no problem, and multiplication by fractional constants, which is + * a problem to do in integer arithmetic. We multiply all the constants + * by CONST_SCALE and convert them to integer constants (thus retaining + * CONST_BITS bits of precision in the constants). After doing a + * multiplication we have to divide the product by CONST_SCALE, with proper + * rounding, to produce the correct output. This division can be done + * cheaply as a right shift of CONST_BITS bits. We postpone shifting + * as long as possible so that partial sums can be added together with + * full fractional precision. + * + * The outputs of the first pass are scaled up by PASS1_BITS bits so that + * they are represented to better-than-integral precision. These outputs + * require BITS_IN_JSAMPLE + PASS1_BITS + 3 bits; this fits in a 16-bit word + * with the recommended scaling. (For 12-bit sample data, the intermediate + * array is INT32 anyway.) + * + * To avoid overflow of the 32-bit intermediate results in pass 2, we must + * have BITS_IN_JSAMPLE + CONST_BITS + PASS1_BITS <= 26. Error analysis + * shows that the values given below are the most effective. + */ + +#if BITS_IN_JSAMPLE == 8 +#define CONST_BITS 13 +#define PASS1_BITS 2 +#else +#define CONST_BITS 13 +#define PASS1_BITS 1 /* lose a little precision to avoid overflow */ +#endif + +/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus + * causing a lot of useless floating-point operations at run time. + * To get around this we use the following pre-calculated constants. + * If you change CONST_BITS you may want to add appropriate values. + * (With a reasonable C compiler, you can just rely on the FIX() macro...) + */ + +#if CONST_BITS == 13 +#define FIX_0_298631336 ((INT32) 2446) /* FIX(0.298631336) */ +#define FIX_0_390180644 ((INT32) 3196) /* FIX(0.390180644) */ +#define FIX_0_541196100 ((INT32) 4433) /* FIX(0.541196100) */ +#define FIX_0_765366865 ((INT32) 6270) /* FIX(0.765366865) */ +#define FIX_0_899976223 ((INT32) 7373) /* FIX(0.899976223) */ +#define FIX_1_175875602 ((INT32) 9633) /* FIX(1.175875602) */ +#define FIX_1_501321110 ((INT32) 12299) /* FIX(1.501321110) */ +#define FIX_1_847759065 ((INT32) 15137) /* FIX(1.847759065) */ +#define FIX_1_961570560 ((INT32) 16069) /* FIX(1.961570560) */ +#define FIX_2_053119869 ((INT32) 16819) /* FIX(2.053119869) */ +#define FIX_2_562915447 ((INT32) 20995) /* FIX(2.562915447) */ +#define FIX_3_072711026 ((INT32) 25172) /* FIX(3.072711026) */ +#else +#define FIX_0_298631336 FIX(0.298631336) +#define FIX_0_390180644 FIX(0.390180644) +#define FIX_0_541196100 FIX(0.541196100) +#define FIX_0_765366865 FIX(0.765366865) +#define FIX_0_899976223 FIX(0.899976223) +#define FIX_1_175875602 FIX(1.175875602) +#define FIX_1_501321110 FIX(1.501321110) +#define FIX_1_847759065 FIX(1.847759065) +#define FIX_1_961570560 FIX(1.961570560) +#define FIX_2_053119869 FIX(2.053119869) +#define FIX_2_562915447 FIX(2.562915447) +#define FIX_3_072711026 FIX(3.072711026) +#endif + + +/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result. + * For 8-bit samples with the recommended scaling, all the variable + * and constant values involved are no more than 16 bits wide, so a + * 16x16->32 bit multiply can be used instead of a full 32x32 multiply. + * For 12-bit samples, a full 32-bit multiplication will be needed. + */ + +#if BITS_IN_JSAMPLE == 8 +#define MULTIPLY(var,const) MULTIPLY16C16(var,const) +#else +#define MULTIPLY(var,const) ((var) * (const)) +#endif + + +/* + * Perform the forward DCT on one block of samples. + */ + +GLOBAL(void) +jpeg_fdct_islow (DCTELEM * data) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + INT32 tmp10, tmp11, tmp12, tmp13; + INT32 z1, z2, z3, z4, z5; + DCTELEM *dataptr; + int ctr; + SHIFT_TEMPS + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT; */ + /* furthermore, we scale the results by 2**PASS1_BITS. */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + tmp0 = dataptr[0] + dataptr[7]; + tmp7 = dataptr[0] - dataptr[7]; + tmp1 = dataptr[1] + dataptr[6]; + tmp6 = dataptr[1] - dataptr[6]; + tmp2 = dataptr[2] + dataptr[5]; + tmp5 = dataptr[2] - dataptr[5]; + tmp3 = dataptr[3] + dataptr[4]; + tmp4 = dataptr[3] - dataptr[4]; + + /* Even part per LL&M figure 1 --- note that published figure is faulty; + * rotator "sqrt(2)*c1" should be "sqrt(2)*c6". + */ + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + dataptr[0] = (DCTELEM) ((tmp10 + tmp11) << PASS1_BITS); + dataptr[4] = (DCTELEM) ((tmp10 - tmp11) << PASS1_BITS); + + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); + dataptr[2] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865), + CONST_BITS-PASS1_BITS); + dataptr[6] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp12, - FIX_1_847759065), + CONST_BITS-PASS1_BITS); + + /* Odd part per figure 8 --- note paper omits factor of sqrt(2). + * cK represents cos(K*pi/16). + * i0..i3 in the paper are tmp4..tmp7 here. + */ + + z1 = tmp4 + tmp7; + z2 = tmp5 + tmp6; + z3 = tmp4 + tmp6; + z4 = tmp5 + tmp7; + z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ + + tmp4 = MULTIPLY(tmp4, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ + tmp5 = MULTIPLY(tmp5, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ + tmp6 = MULTIPLY(tmp6, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ + tmp7 = MULTIPLY(tmp7, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ + z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ + z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ + z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ + z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ + + z3 += z5; + z4 += z5; + + dataptr[7] = (DCTELEM) DESCALE(tmp4 + z1 + z3, CONST_BITS-PASS1_BITS); + dataptr[5] = (DCTELEM) DESCALE(tmp5 + z2 + z4, CONST_BITS-PASS1_BITS); + dataptr[3] = (DCTELEM) DESCALE(tmp6 + z2 + z3, CONST_BITS-PASS1_BITS); + dataptr[1] = (DCTELEM) DESCALE(tmp7 + z1 + z4, CONST_BITS-PASS1_BITS); + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; + tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; + tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; + tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; + tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; + tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; + tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; + tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; + + /* Even part per LL&M figure 1 --- note that published figure is faulty; + * rotator "sqrt(2)*c1" should be "sqrt(2)*c6". + */ + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(tmp10 + tmp11, PASS1_BITS); + dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(tmp10 - tmp11, PASS1_BITS); + + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); + dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865), + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp12, - FIX_1_847759065), + CONST_BITS+PASS1_BITS); + + /* Odd part per figure 8 --- note paper omits factor of sqrt(2). + * cK represents cos(K*pi/16). + * i0..i3 in the paper are tmp4..tmp7 here. + */ + + z1 = tmp4 + tmp7; + z2 = tmp5 + tmp6; + z3 = tmp4 + tmp6; + z4 = tmp5 + tmp7; + z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ + + tmp4 = MULTIPLY(tmp4, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ + tmp5 = MULTIPLY(tmp5, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ + tmp6 = MULTIPLY(tmp6, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ + tmp7 = MULTIPLY(tmp7, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ + z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ + z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ + z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ + z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ + + z3 += z5; + z4 += z5; + + dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp4 + z1 + z3, + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp5 + z2 + z4, + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp6 + z2 + z3, + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp7 + z1 + z4, + CONST_BITS+PASS1_BITS); + + dataptr++; /* advance pointer to next column */ + } +} + +#endif /* DCT_ISLOW_SUPPORTED */ diff --git a/jpeg/JIDCTFLT.C b/jpeg/JIDCTFLT.C new file mode 100644 index 0000000..a926f53 --- /dev/null +++ b/jpeg/JIDCTFLT.C @@ -0,0 +1,242 @@ +/* + * jidctflt.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains a floating-point implementation of the + * inverse DCT (Discrete Cosine Transform). In the IJG code, this routine + * must also perform dequantization of the input coefficients. + * + * This implementation should be more accurate than either of the integer + * IDCT implementations. However, it may not give the same results on all + * machines because of differences in roundoff behavior. Speed will depend + * on the hardware's floating point capacity. + * + * A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT + * on each row (or vice versa, but it's more convenient to emit a row at + * a time). Direct algorithms are also available, but they are much more + * complex and seem not to be any faster when reduced to code. + * + * This implementation is based on Arai, Agui, and Nakajima's algorithm for + * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in + * Japanese, but the algorithm is described in the Pennebaker & Mitchell + * JPEG textbook (see REFERENCES section in file README). The following code + * is based directly on figure 4-8 in P&M. + * While an 8-point DCT cannot be done in less than 11 multiplies, it is + * possible to arrange the computation so that many of the multiplies are + * simple scalings of the final outputs. These multiplies can then be + * folded into the multiplications or divisions by the JPEG quantization + * table entries. The AA&N method leaves only 5 multiplies and 29 adds + * to be done in the DCT itself. + * The primary disadvantage of this method is that with a fixed-point + * implementation, accuracy is lost due to imprecise representation of the + * scaled quantization values. However, that problem does not arise if + * we use floating point arithmetic. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jdct.h" /* Private declarations for DCT subsystem */ + +#ifdef DCT_FLOAT_SUPPORTED + + +/* + * This module is specialized to the case DCTSIZE = 8. + */ + +#if DCTSIZE != 8 + Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ +#endif + + +/* Dequantize a coefficient by multiplying it by the multiplier-table + * entry; produce a float result. + */ + +#define DEQUANTIZE(coef,quantval) (((FAST_FLOAT) (coef)) * (quantval)) + + +/* + * Perform dequantization and inverse DCT on one block of coefficients. + */ + +GLOBAL(void) +jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + FAST_FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + FAST_FLOAT tmp10, tmp11, tmp12, tmp13; + FAST_FLOAT z5, z10, z11, z12, z13; + JCOEFPTR inptr; + FLOAT_MULT_TYPE * quantptr; + FAST_FLOAT * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + FAST_FLOAT workspace[DCTSIZE2]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (FLOAT_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = DCTSIZE; ctr > 0; ctr--) { + /* Due to quantization, we will usually find that many of the input + * coefficients are zero, especially the AC terms. We can exploit this + * by short-circuiting the IDCT calculation for any column in which all + * the AC terms are zero. In that case each output is equal to the + * DC coefficient (with scale factor as needed). + * With typical images and quantization tables, half or more of the + * column DCT calculations can be simplified this way. + */ + + if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && + inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && + inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && + inptr[DCTSIZE*7] == 0) { + /* AC terms all zero */ + FAST_FLOAT dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + + wsptr[DCTSIZE*0] = dcval; + wsptr[DCTSIZE*1] = dcval; + wsptr[DCTSIZE*2] = dcval; + wsptr[DCTSIZE*3] = dcval; + wsptr[DCTSIZE*4] = dcval; + wsptr[DCTSIZE*5] = dcval; + wsptr[DCTSIZE*6] = dcval; + wsptr[DCTSIZE*7] = dcval; + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + continue; + } + + /* Even part */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + tmp3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + tmp10 = tmp0 + tmp2; /* phase 3 */ + tmp11 = tmp0 - tmp2; + + tmp13 = tmp1 + tmp3; /* phases 5-3 */ + tmp12 = (tmp1 - tmp3) * ((FAST_FLOAT) 1.414213562) - tmp13; /* 2*c4 */ + + tmp0 = tmp10 + tmp13; /* phase 2 */ + tmp3 = tmp10 - tmp13; + tmp1 = tmp11 + tmp12; + tmp2 = tmp11 - tmp12; + + /* Odd part */ + + tmp4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + tmp5 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + tmp6 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + tmp7 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + + z13 = tmp6 + tmp5; /* phase 6 */ + z10 = tmp6 - tmp5; + z11 = tmp4 + tmp7; + z12 = tmp4 - tmp7; + + tmp7 = z11 + z13; /* phase 5 */ + tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562); /* 2*c4 */ + + z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */ + tmp10 = ((FAST_FLOAT) 1.082392200) * z12 - z5; /* 2*(c2-c6) */ + tmp12 = ((FAST_FLOAT) -2.613125930) * z10 + z5; /* -2*(c2+c6) */ + + tmp6 = tmp12 - tmp7; /* phase 2 */ + tmp5 = tmp11 - tmp6; + tmp4 = tmp10 + tmp5; + + wsptr[DCTSIZE*0] = tmp0 + tmp7; + wsptr[DCTSIZE*7] = tmp0 - tmp7; + wsptr[DCTSIZE*1] = tmp1 + tmp6; + wsptr[DCTSIZE*6] = tmp1 - tmp6; + wsptr[DCTSIZE*2] = tmp2 + tmp5; + wsptr[DCTSIZE*5] = tmp2 - tmp5; + wsptr[DCTSIZE*4] = tmp3 + tmp4; + wsptr[DCTSIZE*3] = tmp3 - tmp4; + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + } + + /* Pass 2: process rows from work array, store into output array. */ + /* Note that we must descale the results by a factor of 8 == 2**3. */ + + wsptr = workspace; + for (ctr = 0; ctr < DCTSIZE; ctr++) { + outptr = output_buf[ctr] + output_col; + /* Rows of zeroes can be exploited in the same way as we did with columns. + * However, the column calculation has created many nonzero AC terms, so + * the simplification applies less often (typically 5% to 10% of the time). + * And testing floats for zero is relatively expensive, so we don't bother. + */ + + /* Even part */ + + tmp10 = wsptr[0] + wsptr[4]; + tmp11 = wsptr[0] - wsptr[4]; + + tmp13 = wsptr[2] + wsptr[6]; + tmp12 = (wsptr[2] - wsptr[6]) * ((FAST_FLOAT) 1.414213562) - tmp13; + + tmp0 = tmp10 + tmp13; + tmp3 = tmp10 - tmp13; + tmp1 = tmp11 + tmp12; + tmp2 = tmp11 - tmp12; + + /* Odd part */ + + z13 = wsptr[5] + wsptr[3]; + z10 = wsptr[5] - wsptr[3]; + z11 = wsptr[1] + wsptr[7]; + z12 = wsptr[1] - wsptr[7]; + + tmp7 = z11 + z13; + tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562); + + z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */ + tmp10 = ((FAST_FLOAT) 1.082392200) * z12 - z5; /* 2*(c2-c6) */ + tmp12 = ((FAST_FLOAT) -2.613125930) * z10 + z5; /* -2*(c2+c6) */ + + tmp6 = tmp12 - tmp7; + tmp5 = tmp11 - tmp6; + tmp4 = tmp10 + tmp5; + + /* Final output stage: scale down by a factor of 8 and range-limit */ + + outptr[0] = range_limit[(int) DESCALE((INT32) (tmp0 + tmp7), 3) + & RANGE_MASK]; + outptr[7] = range_limit[(int) DESCALE((INT32) (tmp0 - tmp7), 3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) DESCALE((INT32) (tmp1 + tmp6), 3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) DESCALE((INT32) (tmp1 - tmp6), 3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) DESCALE((INT32) (tmp2 + tmp5), 3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) DESCALE((INT32) (tmp2 - tmp5), 3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) DESCALE((INT32) (tmp3 + tmp4), 3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) DESCALE((INT32) (tmp3 - tmp4), 3) + & RANGE_MASK]; + + wsptr += DCTSIZE; /* advance pointer to next row */ + } +} + +#endif /* DCT_FLOAT_SUPPORTED */ diff --git a/jpeg/JIDCTFST.C b/jpeg/JIDCTFST.C new file mode 100644 index 0000000..fb563ca --- /dev/null +++ b/jpeg/JIDCTFST.C @@ -0,0 +1,368 @@ +/* + * jidctfst.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains a fast, not so accurate integer implementation of the + * inverse DCT (Discrete Cosine Transform). In the IJG code, this routine + * must also perform dequantization of the input coefficients. + * + * A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT + * on each row (or vice versa, but it's more convenient to emit a row at + * a time). Direct algorithms are also available, but they are much more + * complex and seem not to be any faster when reduced to code. + * + * This implementation is based on Arai, Agui, and Nakajima's algorithm for + * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in + * Japanese, but the algorithm is described in the Pennebaker & Mitchell + * JPEG textbook (see REFERENCES section in file README). The following code + * is based directly on figure 4-8 in P&M. + * While an 8-point DCT cannot be done in less than 11 multiplies, it is + * possible to arrange the computation so that many of the multiplies are + * simple scalings of the final outputs. These multiplies can then be + * folded into the multiplications or divisions by the JPEG quantization + * table entries. The AA&N method leaves only 5 multiplies and 29 adds + * to be done in the DCT itself. + * The primary disadvantage of this method is that with fixed-point math, + * accuracy is lost due to imprecise representation of the scaled + * quantization values. The smaller the quantization table entry, the less + * precise the scaled value, so this implementation does worse with high- + * quality-setting files than with low-quality ones. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jdct.h" /* Private declarations for DCT subsystem */ + +#ifdef DCT_IFAST_SUPPORTED + + +/* + * This module is specialized to the case DCTSIZE = 8. + */ + +#if DCTSIZE != 8 + Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ +#endif + + +/* Scaling decisions are generally the same as in the LL&M algorithm; + * see jidctint.c for more details. However, we choose to descale + * (right shift) multiplication products as soon as they are formed, + * rather than carrying additional fractional bits into subsequent additions. + * This compromises accuracy slightly, but it lets us save a few shifts. + * More importantly, 16-bit arithmetic is then adequate (for 8-bit samples) + * everywhere except in the multiplications proper; this saves a good deal + * of work on 16-bit-int machines. + * + * The dequantized coefficients are not integers because the AA&N scaling + * factors have been incorporated. We represent them scaled up by PASS1_BITS, + * so that the first and second IDCT rounds have the same input scaling. + * For 8-bit JSAMPLEs, we choose IFAST_SCALE_BITS = PASS1_BITS so as to + * avoid a descaling shift; this compromises accuracy rather drastically + * for small quantization table entries, but it saves a lot of shifts. + * For 12-bit JSAMPLEs, there's no hope of using 16x16 multiplies anyway, + * so we use a much larger scaling factor to preserve accuracy. + * + * A final compromise is to represent the multiplicative constants to only + * 8 fractional bits, rather than 13. This saves some shifting work on some + * machines, and may also reduce the cost of multiplication (since there + * are fewer one-bits in the constants). + */ + +#if BITS_IN_JSAMPLE == 8 +#define CONST_BITS 8 +#define PASS1_BITS 2 +#else +#define CONST_BITS 8 +#define PASS1_BITS 1 /* lose a little precision to avoid overflow */ +#endif + +/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus + * causing a lot of useless floating-point operations at run time. + * To get around this we use the following pre-calculated constants. + * If you change CONST_BITS you may want to add appropriate values. + * (With a reasonable C compiler, you can just rely on the FIX() macro...) + */ + +#if CONST_BITS == 8 +#define FIX_1_082392200 ((INT32) 277) /* FIX(1.082392200) */ +#define FIX_1_414213562 ((INT32) 362) /* FIX(1.414213562) */ +#define FIX_1_847759065 ((INT32) 473) /* FIX(1.847759065) */ +#define FIX_2_613125930 ((INT32) 669) /* FIX(2.613125930) */ +#else +#define FIX_1_082392200 FIX(1.082392200) +#define FIX_1_414213562 FIX(1.414213562) +#define FIX_1_847759065 FIX(1.847759065) +#define FIX_2_613125930 FIX(2.613125930) +#endif + + +/* We can gain a little more speed, with a further compromise in accuracy, + * by omitting the addition in a descaling shift. This yields an incorrectly + * rounded result half the time... + */ + +#ifndef USE_ACCURATE_ROUNDING +#undef DESCALE +#define DESCALE(x,n) RIGHT_SHIFT(x, n) +#endif + + +/* Multiply a DCTELEM variable by an INT32 constant, and immediately + * descale to yield a DCTELEM result. + */ + +#define MULTIPLY(var,const) ((DCTELEM) DESCALE((var) * (const), CONST_BITS)) + + +/* Dequantize a coefficient by multiplying it by the multiplier-table + * entry; produce a DCTELEM result. For 8-bit data a 16x16->16 + * multiplication will do. For 12-bit data, the multiplier table is + * declared INT32, so a 32-bit multiply will be used. + */ + +#if BITS_IN_JSAMPLE == 8 +#define DEQUANTIZE(coef,quantval) (((IFAST_MULT_TYPE) (coef)) * (quantval)) +#else +#define DEQUANTIZE(coef,quantval) \ + DESCALE((coef)*(quantval), IFAST_SCALE_BITS-PASS1_BITS) +#endif + + +/* Like DESCALE, but applies to a DCTELEM and produces an int. + * We assume that int right shift is unsigned if INT32 right shift is. + */ + +#ifdef RIGHT_SHIFT_IS_UNSIGNED +#define ISHIFT_TEMPS DCTELEM ishift_temp; +#if BITS_IN_JSAMPLE == 8 +#define DCTELEMBITS 16 /* DCTELEM may be 16 or 32 bits */ +#else +#define DCTELEMBITS 32 /* DCTELEM must be 32 bits */ +#endif +#define IRIGHT_SHIFT(x,shft) \ + ((ishift_temp = (x)) < 0 ? \ + (ishift_temp >> (shft)) | ((~((DCTELEM) 0)) << (DCTELEMBITS-(shft))) : \ + (ishift_temp >> (shft))) +#else +#define ISHIFT_TEMPS +#define IRIGHT_SHIFT(x,shft) ((x) >> (shft)) +#endif + +#ifdef USE_ACCURATE_ROUNDING +#define IDESCALE(x,n) ((int) IRIGHT_SHIFT((x) + (1 << ((n)-1)), n)) +#else +#define IDESCALE(x,n) ((int) IRIGHT_SHIFT(x, n)) +#endif + + +/* + * Perform dequantization and inverse DCT on one block of coefficients. + */ + +GLOBAL(void) +jpeg_idct_ifast (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + DCTELEM tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + DCTELEM tmp10, tmp11, tmp12, tmp13; + DCTELEM z5, z10, z11, z12, z13; + JCOEFPTR inptr; + IFAST_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[DCTSIZE2]; /* buffers data between passes */ + SHIFT_TEMPS /* for DESCALE */ + ISHIFT_TEMPS /* for IDESCALE */ + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (IFAST_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = DCTSIZE; ctr > 0; ctr--) { + /* Due to quantization, we will usually find that many of the input + * coefficients are zero, especially the AC terms. We can exploit this + * by short-circuiting the IDCT calculation for any column in which all + * the AC terms are zero. In that case each output is equal to the + * DC coefficient (with scale factor as needed). + * With typical images and quantization tables, half or more of the + * column DCT calculations can be simplified this way. + */ + + if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && + inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && + inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && + inptr[DCTSIZE*7] == 0) { + /* AC terms all zero */ + int dcval = (int) DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + + wsptr[DCTSIZE*0] = dcval; + wsptr[DCTSIZE*1] = dcval; + wsptr[DCTSIZE*2] = dcval; + wsptr[DCTSIZE*3] = dcval; + wsptr[DCTSIZE*4] = dcval; + wsptr[DCTSIZE*5] = dcval; + wsptr[DCTSIZE*6] = dcval; + wsptr[DCTSIZE*7] = dcval; + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + continue; + } + + /* Even part */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + tmp3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + tmp10 = tmp0 + tmp2; /* phase 3 */ + tmp11 = tmp0 - tmp2; + + tmp13 = tmp1 + tmp3; /* phases 5-3 */ + tmp12 = MULTIPLY(tmp1 - tmp3, FIX_1_414213562) - tmp13; /* 2*c4 */ + + tmp0 = tmp10 + tmp13; /* phase 2 */ + tmp3 = tmp10 - tmp13; + tmp1 = tmp11 + tmp12; + tmp2 = tmp11 - tmp12; + + /* Odd part */ + + tmp4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + tmp5 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + tmp6 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + tmp7 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + + z13 = tmp6 + tmp5; /* phase 6 */ + z10 = tmp6 - tmp5; + z11 = tmp4 + tmp7; + z12 = tmp4 - tmp7; + + tmp7 = z11 + z13; /* phase 5 */ + tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */ + + z5 = MULTIPLY(z10 + z12, FIX_1_847759065); /* 2*c2 */ + tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5; /* 2*(c2-c6) */ + tmp12 = MULTIPLY(z10, - FIX_2_613125930) + z5; /* -2*(c2+c6) */ + + tmp6 = tmp12 - tmp7; /* phase 2 */ + tmp5 = tmp11 - tmp6; + tmp4 = tmp10 + tmp5; + + wsptr[DCTSIZE*0] = (int) (tmp0 + tmp7); + wsptr[DCTSIZE*7] = (int) (tmp0 - tmp7); + wsptr[DCTSIZE*1] = (int) (tmp1 + tmp6); + wsptr[DCTSIZE*6] = (int) (tmp1 - tmp6); + wsptr[DCTSIZE*2] = (int) (tmp2 + tmp5); + wsptr[DCTSIZE*5] = (int) (tmp2 - tmp5); + wsptr[DCTSIZE*4] = (int) (tmp3 + tmp4); + wsptr[DCTSIZE*3] = (int) (tmp3 - tmp4); + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + } + + /* Pass 2: process rows from work array, store into output array. */ + /* Note that we must descale the results by a factor of 8 == 2**3, */ + /* and also undo the PASS1_BITS scaling. */ + + wsptr = workspace; + for (ctr = 0; ctr < DCTSIZE; ctr++) { + outptr = output_buf[ctr] + output_col; + /* Rows of zeroes can be exploited in the same way as we did with columns. + * However, the column calculation has created many nonzero AC terms, so + * the simplification applies less often (typically 5% to 10% of the time). + * On machines with very fast multiplication, it's possible that the + * test takes more time than it's worth. In that case this section + * may be commented out. + */ + +#ifndef NO_ZERO_ROW_TEST + if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && wsptr[4] == 0 && + wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) { + /* AC terms all zero */ + JSAMPLE dcval = range_limit[IDESCALE(wsptr[0], PASS1_BITS+3) + & RANGE_MASK]; + + outptr[0] = dcval; + outptr[1] = dcval; + outptr[2] = dcval; + outptr[3] = dcval; + outptr[4] = dcval; + outptr[5] = dcval; + outptr[6] = dcval; + outptr[7] = dcval; + + wsptr += DCTSIZE; /* advance pointer to next row */ + continue; + } +#endif + + /* Even part */ + + tmp10 = ((DCTELEM) wsptr[0] + (DCTELEM) wsptr[4]); + tmp11 = ((DCTELEM) wsptr[0] - (DCTELEM) wsptr[4]); + + tmp13 = ((DCTELEM) wsptr[2] + (DCTELEM) wsptr[6]); + tmp12 = MULTIPLY((DCTELEM) wsptr[2] - (DCTELEM) wsptr[6], FIX_1_414213562) + - tmp13; + + tmp0 = tmp10 + tmp13; + tmp3 = tmp10 - tmp13; + tmp1 = tmp11 + tmp12; + tmp2 = tmp11 - tmp12; + + /* Odd part */ + + z13 = (DCTELEM) wsptr[5] + (DCTELEM) wsptr[3]; + z10 = (DCTELEM) wsptr[5] - (DCTELEM) wsptr[3]; + z11 = (DCTELEM) wsptr[1] + (DCTELEM) wsptr[7]; + z12 = (DCTELEM) wsptr[1] - (DCTELEM) wsptr[7]; + + tmp7 = z11 + z13; /* phase 5 */ + tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */ + + z5 = MULTIPLY(z10 + z12, FIX_1_847759065); /* 2*c2 */ + tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5; /* 2*(c2-c6) */ + tmp12 = MULTIPLY(z10, - FIX_2_613125930) + z5; /* -2*(c2+c6) */ + + tmp6 = tmp12 - tmp7; /* phase 2 */ + tmp5 = tmp11 - tmp6; + tmp4 = tmp10 + tmp5; + + /* Final output stage: scale down by a factor of 8 and range-limit */ + + outptr[0] = range_limit[IDESCALE(tmp0 + tmp7, PASS1_BITS+3) + & RANGE_MASK]; + outptr[7] = range_limit[IDESCALE(tmp0 - tmp7, PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[IDESCALE(tmp1 + tmp6, PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[IDESCALE(tmp1 - tmp6, PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[IDESCALE(tmp2 + tmp5, PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[IDESCALE(tmp2 - tmp5, PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[IDESCALE(tmp3 + tmp4, PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[IDESCALE(tmp3 - tmp4, PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += DCTSIZE; /* advance pointer to next row */ + } +} + +#endif /* DCT_IFAST_SUPPORTED */ diff --git a/jpeg/JIDCTINT.C b/jpeg/JIDCTINT.C new file mode 100644 index 0000000..15fd6de --- /dev/null +++ b/jpeg/JIDCTINT.C @@ -0,0 +1,389 @@ +/* + * jidctint.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains a slow-but-accurate integer implementation of the + * inverse DCT (Discrete Cosine Transform). In the IJG code, this routine + * must also perform dequantization of the input coefficients. + * + * A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT + * on each row (or vice versa, but it's more convenient to emit a row at + * a time). Direct algorithms are also available, but they are much more + * complex and seem not to be any faster when reduced to code. + * + * This implementation is based on an algorithm described in + * C. Loeffler, A. Ligtenberg and G. Moschytz, "Practical Fast 1-D DCT + * Algorithms with 11 Multiplications", Proc. Int'l. Conf. on Acoustics, + * Speech, and Signal Processing 1989 (ICASSP '89), pp. 988-991. + * The primary algorithm described there uses 11 multiplies and 29 adds. + * We use their alternate method with 12 multiplies and 32 adds. + * The advantage of this method is that no data path contains more than one + * multiplication; this allows a very simple and accurate implementation in + * scaled fixed-point arithmetic, with a minimal number of shifts. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jdct.h" /* Private declarations for DCT subsystem */ + +#ifdef DCT_ISLOW_SUPPORTED + + +/* + * This module is specialized to the case DCTSIZE = 8. + */ + +#if DCTSIZE != 8 + Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ +#endif + + +/* + * The poop on this scaling stuff is as follows: + * + * Each 1-D IDCT step produces outputs which are a factor of sqrt(N) + * larger than the true IDCT outputs. The final outputs are therefore + * a factor of N larger than desired; since N=8 this can be cured by + * a simple right shift at the end of the algorithm. The advantage of + * this arrangement is that we save two multiplications per 1-D IDCT, + * because the y0 and y4 inputs need not be divided by sqrt(N). + * + * We have to do addition and subtraction of the integer inputs, which + * is no problem, and multiplication by fractional constants, which is + * a problem to do in integer arithmetic. We multiply all the constants + * by CONST_SCALE and convert them to integer constants (thus retaining + * CONST_BITS bits of precision in the constants). After doing a + * multiplication we have to divide the product by CONST_SCALE, with proper + * rounding, to produce the correct output. This division can be done + * cheaply as a right shift of CONST_BITS bits. We postpone shifting + * as long as possible so that partial sums can be added together with + * full fractional precision. + * + * The outputs of the first pass are scaled up by PASS1_BITS bits so that + * they are represented to better-than-integral precision. These outputs + * require BITS_IN_JSAMPLE + PASS1_BITS + 3 bits; this fits in a 16-bit word + * with the recommended scaling. (To scale up 12-bit sample data further, an + * intermediate INT32 array would be needed.) + * + * To avoid overflow of the 32-bit intermediate results in pass 2, we must + * have BITS_IN_JSAMPLE + CONST_BITS + PASS1_BITS <= 26. Error analysis + * shows that the values given below are the most effective. + */ + +#if BITS_IN_JSAMPLE == 8 +#define CONST_BITS 13 +#define PASS1_BITS 2 +#else +#define CONST_BITS 13 +#define PASS1_BITS 1 /* lose a little precision to avoid overflow */ +#endif + +/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus + * causing a lot of useless floating-point operations at run time. + * To get around this we use the following pre-calculated constants. + * If you change CONST_BITS you may want to add appropriate values. + * (With a reasonable C compiler, you can just rely on the FIX() macro...) + */ + +#if CONST_BITS == 13 +#define FIX_0_298631336 ((INT32) 2446) /* FIX(0.298631336) */ +#define FIX_0_390180644 ((INT32) 3196) /* FIX(0.390180644) */ +#define FIX_0_541196100 ((INT32) 4433) /* FIX(0.541196100) */ +#define FIX_0_765366865 ((INT32) 6270) /* FIX(0.765366865) */ +#define FIX_0_899976223 ((INT32) 7373) /* FIX(0.899976223) */ +#define FIX_1_175875602 ((INT32) 9633) /* FIX(1.175875602) */ +#define FIX_1_501321110 ((INT32) 12299) /* FIX(1.501321110) */ +#define FIX_1_847759065 ((INT32) 15137) /* FIX(1.847759065) */ +#define FIX_1_961570560 ((INT32) 16069) /* FIX(1.961570560) */ +#define FIX_2_053119869 ((INT32) 16819) /* FIX(2.053119869) */ +#define FIX_2_562915447 ((INT32) 20995) /* FIX(2.562915447) */ +#define FIX_3_072711026 ((INT32) 25172) /* FIX(3.072711026) */ +#else +#define FIX_0_298631336 FIX(0.298631336) +#define FIX_0_390180644 FIX(0.390180644) +#define FIX_0_541196100 FIX(0.541196100) +#define FIX_0_765366865 FIX(0.765366865) +#define FIX_0_899976223 FIX(0.899976223) +#define FIX_1_175875602 FIX(1.175875602) +#define FIX_1_501321110 FIX(1.501321110) +#define FIX_1_847759065 FIX(1.847759065) +#define FIX_1_961570560 FIX(1.961570560) +#define FIX_2_053119869 FIX(2.053119869) +#define FIX_2_562915447 FIX(2.562915447) +#define FIX_3_072711026 FIX(3.072711026) +#endif + + +/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result. + * For 8-bit samples with the recommended scaling, all the variable + * and constant values involved are no more than 16 bits wide, so a + * 16x16->32 bit multiply can be used instead of a full 32x32 multiply. + * For 12-bit samples, a full 32-bit multiplication will be needed. + */ + +#if BITS_IN_JSAMPLE == 8 +#define MULTIPLY(var,const) MULTIPLY16C16(var,const) +#else +#define MULTIPLY(var,const) ((var) * (const)) +#endif + + +/* Dequantize a coefficient by multiplying it by the multiplier-table + * entry; produce an int result. In this module, both inputs and result + * are 16 bits or less, so either int or short multiply will work. + */ + +#define DEQUANTIZE(coef,quantval) (((ISLOW_MULT_TYPE) (coef)) * (quantval)) + + +/* + * Perform dequantization and inverse DCT on one block of coefficients. + */ + +GLOBAL(void) +jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3; + INT32 tmp10, tmp11, tmp12, tmp13; + INT32 z1, z2, z3, z4, z5; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[DCTSIZE2]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + /* Note results are scaled up by sqrt(8) compared to a true IDCT; */ + /* furthermore, we scale the results by 2**PASS1_BITS. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = DCTSIZE; ctr > 0; ctr--) { + /* Due to quantization, we will usually find that many of the input + * coefficients are zero, especially the AC terms. We can exploit this + * by short-circuiting the IDCT calculation for any column in which all + * the AC terms are zero. In that case each output is equal to the + * DC coefficient (with scale factor as needed). + * With typical images and quantization tables, half or more of the + * column DCT calculations can be simplified this way. + */ + + if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && + inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && + inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && + inptr[DCTSIZE*7] == 0) { + /* AC terms all zero */ + int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS; + + wsptr[DCTSIZE*0] = dcval; + wsptr[DCTSIZE*1] = dcval; + wsptr[DCTSIZE*2] = dcval; + wsptr[DCTSIZE*3] = dcval; + wsptr[DCTSIZE*4] = dcval; + wsptr[DCTSIZE*5] = dcval; + wsptr[DCTSIZE*6] = dcval; + wsptr[DCTSIZE*7] = dcval; + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + continue; + } + + /* Even part: reverse the even part of the forward DCT. */ + /* The rotator is sqrt(2)*c(-6). */ + + z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + z1 = MULTIPLY(z2 + z3, FIX_0_541196100); + tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065); + tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865); + + z2 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + z3 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + + tmp0 = (z2 + z3) << CONST_BITS; + tmp1 = (z2 - z3) << CONST_BITS; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + /* Odd part per figure 8; the matrix is unitary and hence its + * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. + */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + tmp1 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + tmp2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + tmp3 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + + z1 = tmp0 + tmp3; + z2 = tmp1 + tmp2; + z3 = tmp0 + tmp2; + z4 = tmp1 + tmp3; + z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ + + tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ + tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ + tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ + tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ + z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ + z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ + z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ + z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ + + z3 += z5; + z4 += z5; + + tmp0 += z1 + z3; + tmp1 += z2 + z4; + tmp2 += z2 + z3; + tmp3 += z1 + z4; + + /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ + + wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp3, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*7] = (int) DESCALE(tmp10 - tmp3, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*1] = (int) DESCALE(tmp11 + tmp2, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*6] = (int) DESCALE(tmp11 - tmp2, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*2] = (int) DESCALE(tmp12 + tmp1, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*5] = (int) DESCALE(tmp12 - tmp1, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*3] = (int) DESCALE(tmp13 + tmp0, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*4] = (int) DESCALE(tmp13 - tmp0, CONST_BITS-PASS1_BITS); + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + } + + /* Pass 2: process rows from work array, store into output array. */ + /* Note that we must descale the results by a factor of 8 == 2**3, */ + /* and also undo the PASS1_BITS scaling. */ + + wsptr = workspace; + for (ctr = 0; ctr < DCTSIZE; ctr++) { + outptr = output_buf[ctr] + output_col; + /* Rows of zeroes can be exploited in the same way as we did with columns. + * However, the column calculation has created many nonzero AC terms, so + * the simplification applies less often (typically 5% to 10% of the time). + * On machines with very fast multiplication, it's possible that the + * test takes more time than it's worth. In that case this section + * may be commented out. + */ + +#ifndef NO_ZERO_ROW_TEST + if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && wsptr[4] == 0 && + wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) { + /* AC terms all zero */ + JSAMPLE dcval = range_limit[(int) DESCALE((INT32) wsptr[0], PASS1_BITS+3) + & RANGE_MASK]; + + outptr[0] = dcval; + outptr[1] = dcval; + outptr[2] = dcval; + outptr[3] = dcval; + outptr[4] = dcval; + outptr[5] = dcval; + outptr[6] = dcval; + outptr[7] = dcval; + + wsptr += DCTSIZE; /* advance pointer to next row */ + continue; + } +#endif + + /* Even part: reverse the even part of the forward DCT. */ + /* The rotator is sqrt(2)*c(-6). */ + + z2 = (INT32) wsptr[2]; + z3 = (INT32) wsptr[6]; + + z1 = MULTIPLY(z2 + z3, FIX_0_541196100); + tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065); + tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865); + + tmp0 = ((INT32) wsptr[0] + (INT32) wsptr[4]) << CONST_BITS; + tmp1 = ((INT32) wsptr[0] - (INT32) wsptr[4]) << CONST_BITS; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + /* Odd part per figure 8; the matrix is unitary and hence its + * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. + */ + + tmp0 = (INT32) wsptr[7]; + tmp1 = (INT32) wsptr[5]; + tmp2 = (INT32) wsptr[3]; + tmp3 = (INT32) wsptr[1]; + + z1 = tmp0 + tmp3; + z2 = tmp1 + tmp2; + z3 = tmp0 + tmp2; + z4 = tmp1 + tmp3; + z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ + + tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ + tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ + tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ + tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ + z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ + z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ + z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ + z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ + + z3 += z5; + z4 += z5; + + tmp0 += z1 + z3; + tmp1 += z2 + z4; + tmp2 += z2 + z3; + tmp3 += z1 + z4; + + /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ + + outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp3, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[7] = range_limit[(int) DESCALE(tmp10 - tmp3, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) DESCALE(tmp11 + tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) DESCALE(tmp11 - tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) DESCALE(tmp12 + tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) DESCALE(tmp12 - tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) DESCALE(tmp13 + tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) DESCALE(tmp13 - tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += DCTSIZE; /* advance pointer to next row */ + } +} + +#endif /* DCT_ISLOW_SUPPORTED */ diff --git a/jpeg/JIDCTRED.C b/jpeg/JIDCTRED.C new file mode 100644 index 0000000..6414b9b --- /dev/null +++ b/jpeg/JIDCTRED.C @@ -0,0 +1,398 @@ +/* + * jidctred.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains inverse-DCT routines that produce reduced-size output: + * either 4x4, 2x2, or 1x1 pixels from an 8x8 DCT block. + * + * The implementation is based on the Loeffler, Ligtenberg and Moschytz (LL&M) + * algorithm used in jidctint.c. We simply replace each 8-to-8 1-D IDCT step + * with an 8-to-4 step that produces the four averages of two adjacent outputs + * (or an 8-to-2 step producing two averages of four outputs, for 2x2 output). + * These steps were derived by computing the corresponding values at the end + * of the normal LL&M code, then simplifying as much as possible. + * + * 1x1 is trivial: just take the DC coefficient divided by 8. + * + * See jidctint.c for additional comments. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jdct.h" /* Private declarations for DCT subsystem */ + +#ifdef IDCT_SCALING_SUPPORTED + + +/* + * This module is specialized to the case DCTSIZE = 8. + */ + +#if DCTSIZE != 8 + Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ +#endif + + +/* Scaling is the same as in jidctint.c. */ + +#if BITS_IN_JSAMPLE == 8 +#define CONST_BITS 13 +#define PASS1_BITS 2 +#else +#define CONST_BITS 13 +#define PASS1_BITS 1 /* lose a little precision to avoid overflow */ +#endif + +/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus + * causing a lot of useless floating-point operations at run time. + * To get around this we use the following pre-calculated constants. + * If you change CONST_BITS you may want to add appropriate values. + * (With a reasonable C compiler, you can just rely on the FIX() macro...) + */ + +#if CONST_BITS == 13 +#define FIX_0_211164243 ((INT32) 1730) /* FIX(0.211164243) */ +#define FIX_0_509795579 ((INT32) 4176) /* FIX(0.509795579) */ +#define FIX_0_601344887 ((INT32) 4926) /* FIX(0.601344887) */ +#define FIX_0_720959822 ((INT32) 5906) /* FIX(0.720959822) */ +#define FIX_0_765366865 ((INT32) 6270) /* FIX(0.765366865) */ +#define FIX_0_850430095 ((INT32) 6967) /* FIX(0.850430095) */ +#define FIX_0_899976223 ((INT32) 7373) /* FIX(0.899976223) */ +#define FIX_1_061594337 ((INT32) 8697) /* FIX(1.061594337) */ +#define FIX_1_272758580 ((INT32) 10426) /* FIX(1.272758580) */ +#define FIX_1_451774981 ((INT32) 11893) /* FIX(1.451774981) */ +#define FIX_1_847759065 ((INT32) 15137) /* FIX(1.847759065) */ +#define FIX_2_172734803 ((INT32) 17799) /* FIX(2.172734803) */ +#define FIX_2_562915447 ((INT32) 20995) /* FIX(2.562915447) */ +#define FIX_3_624509785 ((INT32) 29692) /* FIX(3.624509785) */ +#else +#define FIX_0_211164243 FIX(0.211164243) +#define FIX_0_509795579 FIX(0.509795579) +#define FIX_0_601344887 FIX(0.601344887) +#define FIX_0_720959822 FIX(0.720959822) +#define FIX_0_765366865 FIX(0.765366865) +#define FIX_0_850430095 FIX(0.850430095) +#define FIX_0_899976223 FIX(0.899976223) +#define FIX_1_061594337 FIX(1.061594337) +#define FIX_1_272758580 FIX(1.272758580) +#define FIX_1_451774981 FIX(1.451774981) +#define FIX_1_847759065 FIX(1.847759065) +#define FIX_2_172734803 FIX(2.172734803) +#define FIX_2_562915447 FIX(2.562915447) +#define FIX_3_624509785 FIX(3.624509785) +#endif + + +/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result. + * For 8-bit samples with the recommended scaling, all the variable + * and constant values involved are no more than 16 bits wide, so a + * 16x16->32 bit multiply can be used instead of a full 32x32 multiply. + * For 12-bit samples, a full 32-bit multiplication will be needed. + */ + +#if BITS_IN_JSAMPLE == 8 +#define MULTIPLY(var,const) MULTIPLY16C16(var,const) +#else +#define MULTIPLY(var,const) ((var) * (const)) +#endif + + +/* Dequantize a coefficient by multiplying it by the multiplier-table + * entry; produce an int result. In this module, both inputs and result + * are 16 bits or less, so either int or short multiply will work. + */ + +#define DEQUANTIZE(coef,quantval) (((ISLOW_MULT_TYPE) (coef)) * (quantval)) + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a reduced-size 4x4 output block. + */ + +GLOBAL(void) +jpeg_idct_4x4 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp2, tmp10, tmp12; + INT32 z1, z2, z3, z4; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[DCTSIZE*4]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = DCTSIZE; ctr > 0; inptr++, quantptr++, wsptr++, ctr--) { + /* Don't bother to process column 4, because second pass won't use it */ + if (ctr == DCTSIZE-4) + continue; + if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && + inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*5] == 0 && + inptr[DCTSIZE*6] == 0 && inptr[DCTSIZE*7] == 0) { + /* AC terms all zero; we need not examine term 4 for 4x4 output */ + int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS; + + wsptr[DCTSIZE*0] = dcval; + wsptr[DCTSIZE*1] = dcval; + wsptr[DCTSIZE*2] = dcval; + wsptr[DCTSIZE*3] = dcval; + + continue; + } + + /* Even part */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp0 <<= (CONST_BITS+1); + + z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + tmp2 = MULTIPLY(z2, FIX_1_847759065) + MULTIPLY(z3, - FIX_0_765366865); + + tmp10 = tmp0 + tmp2; + tmp12 = tmp0 - tmp2; + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + z2 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + z3 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + z4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + + tmp0 = MULTIPLY(z1, - FIX_0_211164243) /* sqrt(2) * (c3-c1) */ + + MULTIPLY(z2, FIX_1_451774981) /* sqrt(2) * (c3+c7) */ + + MULTIPLY(z3, - FIX_2_172734803) /* sqrt(2) * (-c1-c5) */ + + MULTIPLY(z4, FIX_1_061594337); /* sqrt(2) * (c5+c7) */ + + tmp2 = MULTIPLY(z1, - FIX_0_509795579) /* sqrt(2) * (c7-c5) */ + + MULTIPLY(z2, - FIX_0_601344887) /* sqrt(2) * (c5-c1) */ + + MULTIPLY(z3, FIX_0_899976223) /* sqrt(2) * (c3-c7) */ + + MULTIPLY(z4, FIX_2_562915447); /* sqrt(2) * (c1+c3) */ + + /* Final output stage */ + + wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp2, CONST_BITS-PASS1_BITS+1); + wsptr[DCTSIZE*3] = (int) DESCALE(tmp10 - tmp2, CONST_BITS-PASS1_BITS+1); + wsptr[DCTSIZE*1] = (int) DESCALE(tmp12 + tmp0, CONST_BITS-PASS1_BITS+1); + wsptr[DCTSIZE*2] = (int) DESCALE(tmp12 - tmp0, CONST_BITS-PASS1_BITS+1); + } + + /* Pass 2: process 4 rows from work array, store into output array. */ + + wsptr = workspace; + for (ctr = 0; ctr < 4; ctr++) { + outptr = output_buf[ctr] + output_col; + /* It's not clear whether a zero row test is worthwhile here ... */ + +#ifndef NO_ZERO_ROW_TEST + if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && + wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) { + /* AC terms all zero */ + JSAMPLE dcval = range_limit[(int) DESCALE((INT32) wsptr[0], PASS1_BITS+3) + & RANGE_MASK]; + + outptr[0] = dcval; + outptr[1] = dcval; + outptr[2] = dcval; + outptr[3] = dcval; + + wsptr += DCTSIZE; /* advance pointer to next row */ + continue; + } +#endif + + /* Even part */ + + tmp0 = ((INT32) wsptr[0]) << (CONST_BITS+1); + + tmp2 = MULTIPLY((INT32) wsptr[2], FIX_1_847759065) + + MULTIPLY((INT32) wsptr[6], - FIX_0_765366865); + + tmp10 = tmp0 + tmp2; + tmp12 = tmp0 - tmp2; + + /* Odd part */ + + z1 = (INT32) wsptr[7]; + z2 = (INT32) wsptr[5]; + z3 = (INT32) wsptr[3]; + z4 = (INT32) wsptr[1]; + + tmp0 = MULTIPLY(z1, - FIX_0_211164243) /* sqrt(2) * (c3-c1) */ + + MULTIPLY(z2, FIX_1_451774981) /* sqrt(2) * (c3+c7) */ + + MULTIPLY(z3, - FIX_2_172734803) /* sqrt(2) * (-c1-c5) */ + + MULTIPLY(z4, FIX_1_061594337); /* sqrt(2) * (c5+c7) */ + + tmp2 = MULTIPLY(z1, - FIX_0_509795579) /* sqrt(2) * (c7-c5) */ + + MULTIPLY(z2, - FIX_0_601344887) /* sqrt(2) * (c5-c1) */ + + MULTIPLY(z3, FIX_0_899976223) /* sqrt(2) * (c3-c7) */ + + MULTIPLY(z4, FIX_2_562915447); /* sqrt(2) * (c1+c3) */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp2, + CONST_BITS+PASS1_BITS+3+1) + & RANGE_MASK]; + outptr[3] = range_limit[(int) DESCALE(tmp10 - tmp2, + CONST_BITS+PASS1_BITS+3+1) + & RANGE_MASK]; + outptr[1] = range_limit[(int) DESCALE(tmp12 + tmp0, + CONST_BITS+PASS1_BITS+3+1) + & RANGE_MASK]; + outptr[2] = range_limit[(int) DESCALE(tmp12 - tmp0, + CONST_BITS+PASS1_BITS+3+1) + & RANGE_MASK]; + + wsptr += DCTSIZE; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a reduced-size 2x2 output block. + */ + +GLOBAL(void) +jpeg_idct_2x2 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp10, z1; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[DCTSIZE*2]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = DCTSIZE; ctr > 0; inptr++, quantptr++, wsptr++, ctr--) { + /* Don't bother to process columns 2,4,6 */ + if (ctr == DCTSIZE-2 || ctr == DCTSIZE-4 || ctr == DCTSIZE-6) + continue; + if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*3] == 0 && + inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*7] == 0) { + /* AC terms all zero; we need not examine terms 2,4,6 for 2x2 output */ + int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS; + + wsptr[DCTSIZE*0] = dcval; + wsptr[DCTSIZE*1] = dcval; + + continue; + } + + /* Even part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp10 = z1 << (CONST_BITS+2); + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + tmp0 = MULTIPLY(z1, - FIX_0_720959822); /* sqrt(2) * (c7-c5+c3-c1) */ + z1 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + tmp0 += MULTIPLY(z1, FIX_0_850430095); /* sqrt(2) * (-c1+c3+c5+c7) */ + z1 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + tmp0 += MULTIPLY(z1, - FIX_1_272758580); /* sqrt(2) * (-c1+c3-c5-c7) */ + z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + tmp0 += MULTIPLY(z1, FIX_3_624509785); /* sqrt(2) * (c1+c3+c5+c7) */ + + /* Final output stage */ + + wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp0, CONST_BITS-PASS1_BITS+2); + wsptr[DCTSIZE*1] = (int) DESCALE(tmp10 - tmp0, CONST_BITS-PASS1_BITS+2); + } + + /* Pass 2: process 2 rows from work array, store into output array. */ + + wsptr = workspace; + for (ctr = 0; ctr < 2; ctr++) { + outptr = output_buf[ctr] + output_col; + /* It's not clear whether a zero row test is worthwhile here ... */ + +#ifndef NO_ZERO_ROW_TEST + if (wsptr[1] == 0 && wsptr[3] == 0 && wsptr[5] == 0 && wsptr[7] == 0) { + /* AC terms all zero */ + JSAMPLE dcval = range_limit[(int) DESCALE((INT32) wsptr[0], PASS1_BITS+3) + & RANGE_MASK]; + + outptr[0] = dcval; + outptr[1] = dcval; + + wsptr += DCTSIZE; /* advance pointer to next row */ + continue; + } +#endif + + /* Even part */ + + tmp10 = ((INT32) wsptr[0]) << (CONST_BITS+2); + + /* Odd part */ + + tmp0 = MULTIPLY((INT32) wsptr[7], - FIX_0_720959822) /* sqrt(2) * (c7-c5+c3-c1) */ + + MULTIPLY((INT32) wsptr[5], FIX_0_850430095) /* sqrt(2) * (-c1+c3+c5+c7) */ + + MULTIPLY((INT32) wsptr[3], - FIX_1_272758580) /* sqrt(2) * (-c1+c3-c5-c7) */ + + MULTIPLY((INT32) wsptr[1], FIX_3_624509785); /* sqrt(2) * (c1+c3+c5+c7) */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp0, + CONST_BITS+PASS1_BITS+3+2) + & RANGE_MASK]; + outptr[1] = range_limit[(int) DESCALE(tmp10 - tmp0, + CONST_BITS+PASS1_BITS+3+2) + & RANGE_MASK]; + + wsptr += DCTSIZE; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a reduced-size 1x1 output block. + */ + +GLOBAL(void) +jpeg_idct_1x1 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + int dcval; + ISLOW_MULT_TYPE * quantptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + SHIFT_TEMPS + + /* We hardly need an inverse DCT routine for this: just take the + * average pixel value, which is one-eighth of the DC coefficient. + */ + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + dcval = DEQUANTIZE(coef_block[0], quantptr[0]); + dcval = (int) DESCALE((INT32) dcval, 3); + + output_buf[0][output_col] = range_limit[dcval & RANGE_MASK]; +} + +#endif /* IDCT_SCALING_SUPPORTED */ diff --git a/jpeg/JINCLUDE.H b/jpeg/JINCLUDE.H new file mode 100644 index 0000000..0a4f151 --- /dev/null +++ b/jpeg/JINCLUDE.H @@ -0,0 +1,91 @@ +/* + * jinclude.h + * + * Copyright (C) 1991-1994, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file exists to provide a single place to fix any problems with + * including the wrong system include files. (Common problems are taken + * care of by the standard jconfig symbols, but on really weird systems + * you may have to edit this file.) + * + * NOTE: this file is NOT intended to be included by applications using the + * JPEG library. Most applications need only include jpeglib.h. + */ + + +/* Include auto-config file to find out which system include files we need. */ + +#include "jconfig.h" /* auto configuration options */ +#define JCONFIG_INCLUDED /* so that jpeglib.h doesn't do it again */ + +/* + * We need the NULL macro and size_t typedef. + * On an ANSI-conforming system it is sufficient to include . + * Otherwise, we get them from or ; we may have to + * pull in as well. + * Note that the core JPEG library does not require ; + * only the default error handler and data source/destination modules do. + * But we must pull it in because of the references to FILE in jpeglib.h. + * You can remove those references if you want to compile without . + */ + +#ifdef HAVE_STDDEF_H +#include +#endif + +#ifdef HAVE_STDLIB_H +#include +#endif + +#ifdef NEED_SYS_TYPES_H +#include +#endif + +#include + +/* + * We need memory copying and zeroing functions, plus strncpy(). + * ANSI and System V implementations declare these in . + * BSD doesn't have the mem() functions, but it does have bcopy()/bzero(). + * Some systems may declare memset and memcpy in . + * + * NOTE: we assume the size parameters to these functions are of type size_t. + * Change the casts in these macros if not! + */ + +#ifdef NEED_BSD_STRINGS + +#include +#define MEMZERO(target,size) bzero((void *)(target), (size_t)(size)) +#define MEMCOPY(dest,src,size) bcopy((const void *)(src), (void *)(dest), (size_t)(size)) + +#else /* not BSD, assume ANSI/SysV string lib */ + +#include +#define MEMZERO(target,size) memset((void *)(target), 0, (size_t)(size)) +#define MEMCOPY(dest,src,size) memcpy((void *)(dest), (const void *)(src), (size_t)(size)) + +#endif + +/* + * In ANSI C, and indeed any rational implementation, size_t is also the + * type returned by sizeof(). However, it seems there are some irrational + * implementations out there, in which sizeof() returns an int even though + * size_t is defined as long or unsigned long. To ensure consistent results + * we always use this SIZEOF() macro in place of using sizeof() directly. + */ + +#define SIZEOF(object) ((size_t) sizeof(object)) + +/* + * The modules that use fread() and fwrite() always invoke them through + * these macros. On some systems you may need to twiddle the argument casts. + * CAUTION: argument order is different from underlying functions! + */ + +#define JFREAD(file,buf,sizeofbuf) \ + ((size_t) fread((void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file))) +#define JFWRITE(file,buf,sizeofbuf) \ + ((size_t) fwrite((const void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file))) diff --git a/jpeg/JMEMMGR.C b/jpeg/JMEMMGR.C new file mode 100644 index 0000000..ce5b291 --- /dev/null +++ b/jpeg/JMEMMGR.C @@ -0,0 +1,1118 @@ +/* + * jmemmgr.c + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the JPEG system-independent memory management + * routines. This code is usable across a wide variety of machines; most + * of the system dependencies have been isolated in a separate file. + * The major functions provided here are: + * * pool-based allocation and freeing of memory; + * * policy decisions about how to divide available memory among the + * virtual arrays; + * * control logic for swapping virtual arrays between main memory and + * backing storage. + * The separate system-dependent file provides the actual backing-storage + * access code, and it contains the policy decision about how much total + * main memory to use. + * This file is system-dependent in the sense that some of its functions + * are unnecessary in some systems. For example, if there is enough virtual + * memory so that backing storage will never be used, much of the virtual + * array control logic could be removed. (Of course, if you have that much + * memory then you shouldn't care about a little bit of unused code...) + */ + +#define JPEG_INTERNALS +#define AM_MEMORY_MANAGER /* we define jvirt_Xarray_control structs */ +#include "jinclude.h" +#include "jpeglib.h" +#include "jmemsys.h" /* import the system-dependent declarations */ + +#ifndef NO_GETENV +#ifndef HAVE_STDLIB_H /* should declare getenv() */ +extern char * getenv JPP((const char * name)); +#endif +#endif + + +/* + * Some important notes: + * The allocation routines provided here must never return NULL. + * They should exit to error_exit if unsuccessful. + * + * It's not a good idea to try to merge the sarray and barray routines, + * even though they are textually almost the same, because samples are + * usually stored as bytes while coefficients are shorts or ints. Thus, + * in machines where byte pointers have a different representation from + * word pointers, the resulting machine code could not be the same. + */ + + +/* + * Many machines require storage alignment: longs must start on 4-byte + * boundaries, doubles on 8-byte boundaries, etc. On such machines, malloc() + * always returns pointers that are multiples of the worst-case alignment + * requirement, and we had better do so too. + * There isn't any really portable way to determine the worst-case alignment + * requirement. This module assumes that the alignment requirement is + * multiples of sizeof(ALIGN_TYPE). + * By default, we define ALIGN_TYPE as double. This is necessary on some + * workstations (where doubles really do need 8-byte alignment) and will work + * fine on nearly everything. If your machine has lesser alignment needs, + * you can save a few bytes by making ALIGN_TYPE smaller. + * The only place I know of where this will NOT work is certain Macintosh + * 680x0 compilers that define double as a 10-byte IEEE extended float. + * Doing 10-byte alignment is counterproductive because longwords won't be + * aligned well. Put "#define ALIGN_TYPE long" in jconfig.h if you have + * such a compiler. + */ + +#ifndef ALIGN_TYPE /* so can override from jconfig.h */ +#define ALIGN_TYPE double +#endif + + +/* + * We allocate objects from "pools", where each pool is gotten with a single + * request to jpeg_get_small() or jpeg_get_large(). There is no per-object + * overhead within a pool, except for alignment padding. Each pool has a + * header with a link to the next pool of the same class. + * Small and large pool headers are identical except that the latter's + * link pointer must be FAR on 80x86 machines. + * Notice that the "real" header fields are union'ed with a dummy ALIGN_TYPE + * field. This forces the compiler to make SIZEOF(small_pool_hdr) a multiple + * of the alignment requirement of ALIGN_TYPE. + */ + +typedef union small_pool_struct * small_pool_ptr; + +typedef union small_pool_struct { + struct { + small_pool_ptr next; /* next in list of pools */ + size_t bytes_used; /* how many bytes already used within pool */ + size_t bytes_left; /* bytes still available in this pool */ + } hdr; + ALIGN_TYPE dummy; /* included in union to ensure alignment */ +} small_pool_hdr; + +typedef union large_pool_struct FAR * large_pool_ptr; + +typedef union large_pool_struct { + struct { + large_pool_ptr next; /* next in list of pools */ + size_t bytes_used; /* how many bytes already used within pool */ + size_t bytes_left; /* bytes still available in this pool */ + } hdr; + ALIGN_TYPE dummy; /* included in union to ensure alignment */ +} large_pool_hdr; + + +/* + * Here is the full definition of a memory manager object. + */ + +typedef struct { + struct jpeg_memory_mgr pub; /* public fields */ + + /* Each pool identifier (lifetime class) names a linked list of pools. */ + small_pool_ptr small_list[JPOOL_NUMPOOLS]; + large_pool_ptr large_list[JPOOL_NUMPOOLS]; + + /* Since we only have one lifetime class of virtual arrays, only one + * linked list is necessary (for each datatype). Note that the virtual + * array control blocks being linked together are actually stored somewhere + * in the small-pool list. + */ + jvirt_sarray_ptr virt_sarray_list; + jvirt_barray_ptr virt_barray_list; + + /* This counts total space obtained from jpeg_get_small/large */ + long total_space_allocated; + + /* alloc_sarray and alloc_barray set this value for use by virtual + * array routines. + */ + JDIMENSION last_rowsperchunk; /* from most recent alloc_sarray/barray */ +} my_memory_mgr; + +typedef my_memory_mgr * my_mem_ptr; + + +/* + * The control blocks for virtual arrays. + * Note that these blocks are allocated in the "small" pool area. + * System-dependent info for the associated backing store (if any) is hidden + * inside the backing_store_info struct. + */ + +struct jvirt_sarray_control { + JSAMPARRAY mem_buffer; /* => the in-memory buffer */ + JDIMENSION rows_in_array; /* total virtual array height */ + JDIMENSION samplesperrow; /* width of array (and of memory buffer) */ + JDIMENSION maxaccess; /* max rows accessed by access_virt_sarray */ + JDIMENSION rows_in_mem; /* height of memory buffer */ + JDIMENSION rowsperchunk; /* allocation chunk size in mem_buffer */ + JDIMENSION cur_start_row; /* first logical row # in the buffer */ + JDIMENSION first_undef_row; /* row # of first uninitialized row */ + boolean pre_zero; /* pre-zero mode requested? */ + boolean dirty; /* do current buffer contents need written? */ + boolean b_s_open; /* is backing-store data valid? */ + jvirt_sarray_ptr next; /* link to next virtual sarray control block */ + backing_store_info b_s_info; /* System-dependent control info */ +}; + +struct jvirt_barray_control { + JBLOCKARRAY mem_buffer; /* => the in-memory buffer */ + JDIMENSION rows_in_array; /* total virtual array height */ + JDIMENSION blocksperrow; /* width of array (and of memory buffer) */ + JDIMENSION maxaccess; /* max rows accessed by access_virt_barray */ + JDIMENSION rows_in_mem; /* height of memory buffer */ + JDIMENSION rowsperchunk; /* allocation chunk size in mem_buffer */ + JDIMENSION cur_start_row; /* first logical row # in the buffer */ + JDIMENSION first_undef_row; /* row # of first uninitialized row */ + boolean pre_zero; /* pre-zero mode requested? */ + boolean dirty; /* do current buffer contents need written? */ + boolean b_s_open; /* is backing-store data valid? */ + jvirt_barray_ptr next; /* link to next virtual barray control block */ + backing_store_info b_s_info; /* System-dependent control info */ +}; + + +#ifdef MEM_STATS /* optional extra stuff for statistics */ + +LOCAL(void) +print_mem_stats (j_common_ptr cinfo, int pool_id) +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + small_pool_ptr shdr_ptr; + large_pool_ptr lhdr_ptr; + + /* Since this is only a debugging stub, we can cheat a little by using + * fprintf directly rather than going through the trace message code. + * This is helpful because message parm array can't handle longs. + */ + fprintf(stderr, "Freeing pool %d, total space = %ld\n", + pool_id, mem->total_space_allocated); + + for (lhdr_ptr = mem->large_list[pool_id]; lhdr_ptr != NULL; + lhdr_ptr = lhdr_ptr->hdr.next) { + fprintf(stderr, " Large chunk used %ld\n", + (long) lhdr_ptr->hdr.bytes_used); + } + + for (shdr_ptr = mem->small_list[pool_id]; shdr_ptr != NULL; + shdr_ptr = shdr_ptr->hdr.next) { + fprintf(stderr, " Small chunk used %ld free %ld\n", + (long) shdr_ptr->hdr.bytes_used, + (long) shdr_ptr->hdr.bytes_left); + } +} + +#endif /* MEM_STATS */ + + +LOCAL(void) +out_of_memory (j_common_ptr cinfo, int which) +/* Report an out-of-memory error and stop execution */ +/* If we compiled MEM_STATS support, report alloc requests before dying */ +{ +#ifdef MEM_STATS + cinfo->err->trace_level = 2; /* force self_destruct to report stats */ +#endif + ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, which); +} + + +/* + * Allocation of "small" objects. + * + * For these, we use pooled storage. When a new pool must be created, + * we try to get enough space for the current request plus a "slop" factor, + * where the slop will be the amount of leftover space in the new pool. + * The speed vs. space tradeoff is largely determined by the slop values. + * A different slop value is provided for each pool class (lifetime), + * and we also distinguish the first pool of a class from later ones. + * NOTE: the values given work fairly well on both 16- and 32-bit-int + * machines, but may be too small if longs are 64 bits or more. + */ + +static const size_t first_pool_slop[JPOOL_NUMPOOLS] = +{ + 1600, /* first PERMANENT pool */ + 16000 /* first IMAGE pool */ +}; + +static const size_t extra_pool_slop[JPOOL_NUMPOOLS] = +{ + 0, /* additional PERMANENT pools */ + 5000 /* additional IMAGE pools */ +}; + +#define MIN_SLOP 50 /* greater than 0 to avoid futile looping */ + + +METHODDEF(void *) +alloc_small (j_common_ptr cinfo, int pool_id, size_t sizeofobject) +/* Allocate a "small" object */ +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + small_pool_ptr hdr_ptr, prev_hdr_ptr; + char * data_ptr; + size_t odd_bytes, min_request, slop; + + /* Check for unsatisfiable request (do now to ensure no overflow below) */ + if (sizeofobject > (size_t) (MAX_ALLOC_CHUNK-SIZEOF(small_pool_hdr))) + out_of_memory(cinfo, 1); /* request exceeds malloc's ability */ + + /* Round up the requested size to a multiple of SIZEOF(ALIGN_TYPE) */ + odd_bytes = sizeofobject % SIZEOF(ALIGN_TYPE); + if (odd_bytes > 0) + sizeofobject += SIZEOF(ALIGN_TYPE) - odd_bytes; + + /* See if space is available in any existing pool */ + if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS) + ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ + prev_hdr_ptr = NULL; + hdr_ptr = mem->small_list[pool_id]; + while (hdr_ptr != NULL) { + if (hdr_ptr->hdr.bytes_left >= sizeofobject) + break; /* found pool with enough space */ + prev_hdr_ptr = hdr_ptr; + hdr_ptr = hdr_ptr->hdr.next; + } + + /* Time to make a new pool? */ + if (hdr_ptr == NULL) { + /* min_request is what we need now, slop is what will be leftover */ + min_request = sizeofobject + SIZEOF(small_pool_hdr); + if (prev_hdr_ptr == NULL) /* first pool in class? */ + slop = first_pool_slop[pool_id]; + else + slop = extra_pool_slop[pool_id]; + /* Don't ask for more than MAX_ALLOC_CHUNK */ + if (slop > (size_t) (MAX_ALLOC_CHUNK-min_request)) + slop = (size_t) (MAX_ALLOC_CHUNK-min_request); + /* Try to get space, if fail reduce slop and try again */ + for (;;) { + hdr_ptr = (small_pool_ptr) jpeg_get_small(cinfo, min_request + slop); + if (hdr_ptr != NULL) + break; + slop /= 2; + if (slop < MIN_SLOP) /* give up when it gets real small */ + out_of_memory(cinfo, 2); /* jpeg_get_small failed */ + } + mem->total_space_allocated += min_request + slop; + /* Success, initialize the new pool header and add to end of list */ + hdr_ptr->hdr.next = NULL; + hdr_ptr->hdr.bytes_used = 0; + hdr_ptr->hdr.bytes_left = sizeofobject + slop; + if (prev_hdr_ptr == NULL) /* first pool in class? */ + mem->small_list[pool_id] = hdr_ptr; + else + prev_hdr_ptr->hdr.next = hdr_ptr; + } + + /* OK, allocate the object from the current pool */ + data_ptr = (char *) (hdr_ptr + 1); /* point to first data byte in pool */ + data_ptr += hdr_ptr->hdr.bytes_used; /* point to place for object */ + hdr_ptr->hdr.bytes_used += sizeofobject; + hdr_ptr->hdr.bytes_left -= sizeofobject; + + return (void *) data_ptr; +} + + +/* + * Allocation of "large" objects. + * + * The external semantics of these are the same as "small" objects, + * except that FAR pointers are used on 80x86. However the pool + * management heuristics are quite different. We assume that each + * request is large enough that it may as well be passed directly to + * jpeg_get_large; the pool management just links everything together + * so that we can free it all on demand. + * Note: the major use of "large" objects is in JSAMPARRAY and JBLOCKARRAY + * structures. The routines that create these structures (see below) + * deliberately bunch rows together to ensure a large request size. + */ + +METHODDEF(void FAR *) +alloc_large (j_common_ptr cinfo, int pool_id, size_t sizeofobject) +/* Allocate a "large" object */ +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + large_pool_ptr hdr_ptr; + size_t odd_bytes; + + /* Check for unsatisfiable request (do now to ensure no overflow below) */ + if (sizeofobject > (size_t) (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr))) + out_of_memory(cinfo, 3); /* request exceeds malloc's ability */ + + /* Round up the requested size to a multiple of SIZEOF(ALIGN_TYPE) */ + odd_bytes = sizeofobject % SIZEOF(ALIGN_TYPE); + if (odd_bytes > 0) + sizeofobject += SIZEOF(ALIGN_TYPE) - odd_bytes; + + /* Always make a new pool */ + if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS) + ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ + + hdr_ptr = (large_pool_ptr) jpeg_get_large(cinfo, sizeofobject + + SIZEOF(large_pool_hdr)); + if (hdr_ptr == NULL) + out_of_memory(cinfo, 4); /* jpeg_get_large failed */ + mem->total_space_allocated += sizeofobject + SIZEOF(large_pool_hdr); + + /* Success, initialize the new pool header and add to list */ + hdr_ptr->hdr.next = mem->large_list[pool_id]; + /* We maintain space counts in each pool header for statistical purposes, + * even though they are not needed for allocation. + */ + hdr_ptr->hdr.bytes_used = sizeofobject; + hdr_ptr->hdr.bytes_left = 0; + mem->large_list[pool_id] = hdr_ptr; + + return (void FAR *) (hdr_ptr + 1); /* point to first data byte in pool */ +} + + +/* + * Creation of 2-D sample arrays. + * The pointers are in near heap, the samples themselves in FAR heap. + * + * To minimize allocation overhead and to allow I/O of large contiguous + * blocks, we allocate the sample rows in groups of as many rows as possible + * without exceeding MAX_ALLOC_CHUNK total bytes per allocation request. + * NB: the virtual array control routines, later in this file, know about + * this chunking of rows. The rowsperchunk value is left in the mem manager + * object so that it can be saved away if this sarray is the workspace for + * a virtual array. + */ + +METHODDEF(JSAMPARRAY) +alloc_sarray (j_common_ptr cinfo, int pool_id, + JDIMENSION samplesperrow, JDIMENSION numrows) +/* Allocate a 2-D sample array */ +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + JSAMPARRAY result; + JSAMPROW workspace; + JDIMENSION rowsperchunk, currow, i; + long ltemp; + + /* Calculate max # of rows allowed in one allocation chunk */ + ltemp = (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) / + ((long) samplesperrow * SIZEOF(JSAMPLE)); + if (ltemp <= 0) + ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); + if (ltemp < (long) numrows) + rowsperchunk = (JDIMENSION) ltemp; + else + rowsperchunk = numrows; + mem->last_rowsperchunk = rowsperchunk; + + /* Get space for row pointers (small object) */ + result = (JSAMPARRAY) alloc_small(cinfo, pool_id, + (size_t) (numrows * SIZEOF(JSAMPROW))); + + /* Get the rows themselves (large objects) */ + currow = 0; + while (currow < numrows) { + rowsperchunk = MIN(rowsperchunk, numrows - currow); + workspace = (JSAMPROW) alloc_large(cinfo, pool_id, + (size_t) ((size_t) rowsperchunk * (size_t) samplesperrow + * SIZEOF(JSAMPLE))); + for (i = rowsperchunk; i > 0; i--) { + result[currow++] = workspace; + workspace += samplesperrow; + } + } + + return result; +} + + +/* + * Creation of 2-D coefficient-block arrays. + * This is essentially the same as the code for sample arrays, above. + */ + +METHODDEF(JBLOCKARRAY) +alloc_barray (j_common_ptr cinfo, int pool_id, + JDIMENSION blocksperrow, JDIMENSION numrows) +/* Allocate a 2-D coefficient-block array */ +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + JBLOCKARRAY result; + JBLOCKROW workspace; + JDIMENSION rowsperchunk, currow, i; + long ltemp; + + /* Calculate max # of rows allowed in one allocation chunk */ + ltemp = (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) / + ((long) blocksperrow * SIZEOF(JBLOCK)); + if (ltemp <= 0) + ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); + if (ltemp < (long) numrows) + rowsperchunk = (JDIMENSION) ltemp; + else + rowsperchunk = numrows; + mem->last_rowsperchunk = rowsperchunk; + + /* Get space for row pointers (small object) */ + result = (JBLOCKARRAY) alloc_small(cinfo, pool_id, + (size_t) (numrows * SIZEOF(JBLOCKROW))); + + /* Get the rows themselves (large objects) */ + currow = 0; + while (currow < numrows) { + rowsperchunk = MIN(rowsperchunk, numrows - currow); + workspace = (JBLOCKROW) alloc_large(cinfo, pool_id, + (size_t) ((size_t) rowsperchunk * (size_t) blocksperrow + * SIZEOF(JBLOCK))); + for (i = rowsperchunk; i > 0; i--) { + result[currow++] = workspace; + workspace += blocksperrow; + } + } + + return result; +} + + +/* + * About virtual array management: + * + * The above "normal" array routines are only used to allocate strip buffers + * (as wide as the image, but just a few rows high). Full-image-sized buffers + * are handled as "virtual" arrays. The array is still accessed a strip at a + * time, but the memory manager must save the whole array for repeated + * accesses. The intended implementation is that there is a strip buffer in + * memory (as high as is possible given the desired memory limit), plus a + * backing file that holds the rest of the array. + * + * The request_virt_array routines are told the total size of the image and + * the maximum number of rows that will be accessed at once. The in-memory + * buffer must be at least as large as the maxaccess value. + * + * The request routines create control blocks but not the in-memory buffers. + * That is postponed until realize_virt_arrays is called. At that time the + * total amount of space needed is known (approximately, anyway), so free + * memory can be divided up fairly. + * + * The access_virt_array routines are responsible for making a specific strip + * area accessible (after reading or writing the backing file, if necessary). + * Note that the access routines are told whether the caller intends to modify + * the accessed strip; during a read-only pass this saves having to rewrite + * data to disk. The access routines are also responsible for pre-zeroing + * any newly accessed rows, if pre-zeroing was requested. + * + * In current usage, the access requests are usually for nonoverlapping + * strips; that is, successive access start_row numbers differ by exactly + * num_rows = maxaccess. This means we can get good performance with simple + * buffer dump/reload logic, by making the in-memory buffer be a multiple + * of the access height; then there will never be accesses across bufferload + * boundaries. The code will still work with overlapping access requests, + * but it doesn't handle bufferload overlaps very efficiently. + */ + + +METHODDEF(jvirt_sarray_ptr) +request_virt_sarray (j_common_ptr cinfo, int pool_id, boolean pre_zero, + JDIMENSION samplesperrow, JDIMENSION numrows, + JDIMENSION maxaccess) +/* Request a virtual 2-D sample array */ +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + jvirt_sarray_ptr result; + + /* Only IMAGE-lifetime virtual arrays are currently supported */ + if (pool_id != JPOOL_IMAGE) + ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ + + /* get control block */ + result = (jvirt_sarray_ptr) alloc_small(cinfo, pool_id, + SIZEOF(struct jvirt_sarray_control)); + + result->mem_buffer = NULL; /* marks array not yet realized */ + result->rows_in_array = numrows; + result->samplesperrow = samplesperrow; + result->maxaccess = maxaccess; + result->pre_zero = pre_zero; + result->b_s_open = FALSE; /* no associated backing-store object */ + result->next = mem->virt_sarray_list; /* add to list of virtual arrays */ + mem->virt_sarray_list = result; + + return result; +} + + +METHODDEF(jvirt_barray_ptr) +request_virt_barray (j_common_ptr cinfo, int pool_id, boolean pre_zero, + JDIMENSION blocksperrow, JDIMENSION numrows, + JDIMENSION maxaccess) +/* Request a virtual 2-D coefficient-block array */ +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + jvirt_barray_ptr result; + + /* Only IMAGE-lifetime virtual arrays are currently supported */ + if (pool_id != JPOOL_IMAGE) + ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ + + /* get control block */ + result = (jvirt_barray_ptr) alloc_small(cinfo, pool_id, + SIZEOF(struct jvirt_barray_control)); + + result->mem_buffer = NULL; /* marks array not yet realized */ + result->rows_in_array = numrows; + result->blocksperrow = blocksperrow; + result->maxaccess = maxaccess; + result->pre_zero = pre_zero; + result->b_s_open = FALSE; /* no associated backing-store object */ + result->next = mem->virt_barray_list; /* add to list of virtual arrays */ + mem->virt_barray_list = result; + + return result; +} + + +METHODDEF(void) +realize_virt_arrays (j_common_ptr cinfo) +/* Allocate the in-memory buffers for any unrealized virtual arrays */ +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + long space_per_minheight, maximum_space, avail_mem; + long minheights, max_minheights; + jvirt_sarray_ptr sptr; + jvirt_barray_ptr bptr; + + /* Compute the minimum space needed (maxaccess rows in each buffer) + * and the maximum space needed (full image height in each buffer). + * These may be of use to the system-dependent jpeg_mem_available routine. + */ + space_per_minheight = 0; + maximum_space = 0; + for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) { + if (sptr->mem_buffer == NULL) { /* if not realized yet */ + space_per_minheight += (long) sptr->maxaccess * + (long) sptr->samplesperrow * SIZEOF(JSAMPLE); + maximum_space += (long) sptr->rows_in_array * + (long) sptr->samplesperrow * SIZEOF(JSAMPLE); + } + } + for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) { + if (bptr->mem_buffer == NULL) { /* if not realized yet */ + space_per_minheight += (long) bptr->maxaccess * + (long) bptr->blocksperrow * SIZEOF(JBLOCK); + maximum_space += (long) bptr->rows_in_array * + (long) bptr->blocksperrow * SIZEOF(JBLOCK); + } + } + + if (space_per_minheight <= 0) + return; /* no unrealized arrays, no work */ + + /* Determine amount of memory to actually use; this is system-dependent. */ + avail_mem = jpeg_mem_available(cinfo, space_per_minheight, maximum_space, + mem->total_space_allocated); + + /* If the maximum space needed is available, make all the buffers full + * height; otherwise parcel it out with the same number of minheights + * in each buffer. + */ + if (avail_mem >= maximum_space) + max_minheights = 1000000000L; + else { + max_minheights = avail_mem / space_per_minheight; + /* If there doesn't seem to be enough space, try to get the minimum + * anyway. This allows a "stub" implementation of jpeg_mem_available(). + */ + if (max_minheights <= 0) + max_minheights = 1; + } + + /* Allocate the in-memory buffers and initialize backing store as needed. */ + + for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) { + if (sptr->mem_buffer == NULL) { /* if not realized yet */ + minheights = ((long) sptr->rows_in_array - 1L) / sptr->maxaccess + 1L; + if (minheights <= max_minheights) { + /* This buffer fits in memory */ + sptr->rows_in_mem = sptr->rows_in_array; + } else { + /* It doesn't fit in memory, create backing store. */ + sptr->rows_in_mem = (JDIMENSION) (max_minheights * sptr->maxaccess); + jpeg_open_backing_store(cinfo, & sptr->b_s_info, + (long) sptr->rows_in_array * + (long) sptr->samplesperrow * + (long) SIZEOF(JSAMPLE)); + sptr->b_s_open = TRUE; + } + sptr->mem_buffer = alloc_sarray(cinfo, JPOOL_IMAGE, + sptr->samplesperrow, sptr->rows_in_mem); + sptr->rowsperchunk = mem->last_rowsperchunk; + sptr->cur_start_row = 0; + sptr->first_undef_row = 0; + sptr->dirty = FALSE; + } + } + + for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) { + if (bptr->mem_buffer == NULL) { /* if not realized yet */ + minheights = ((long) bptr->rows_in_array - 1L) / bptr->maxaccess + 1L; + if (minheights <= max_minheights) { + /* This buffer fits in memory */ + bptr->rows_in_mem = bptr->rows_in_array; + } else { + /* It doesn't fit in memory, create backing store. */ + bptr->rows_in_mem = (JDIMENSION) (max_minheights * bptr->maxaccess); + jpeg_open_backing_store(cinfo, & bptr->b_s_info, + (long) bptr->rows_in_array * + (long) bptr->blocksperrow * + (long) SIZEOF(JBLOCK)); + bptr->b_s_open = TRUE; + } + bptr->mem_buffer = alloc_barray(cinfo, JPOOL_IMAGE, + bptr->blocksperrow, bptr->rows_in_mem); + bptr->rowsperchunk = mem->last_rowsperchunk; + bptr->cur_start_row = 0; + bptr->first_undef_row = 0; + bptr->dirty = FALSE; + } + } +} + + +LOCAL(void) +do_sarray_io (j_common_ptr cinfo, jvirt_sarray_ptr ptr, boolean writing) +/* Do backing store read or write of a virtual sample array */ +{ + long bytesperrow, file_offset, byte_count, rows, thisrow, i; + + bytesperrow = (long) ptr->samplesperrow * SIZEOF(JSAMPLE); + file_offset = ptr->cur_start_row * bytesperrow; + /* Loop to read or write each allocation chunk in mem_buffer */ + for (i = 0; i < (long) ptr->rows_in_mem; i += ptr->rowsperchunk) { + /* One chunk, but check for short chunk at end of buffer */ + rows = MIN((long) ptr->rowsperchunk, (long) ptr->rows_in_mem - i); + /* Transfer no more than is currently defined */ + thisrow = (long) ptr->cur_start_row + i; + rows = MIN(rows, (long) ptr->first_undef_row - thisrow); + /* Transfer no more than fits in file */ + rows = MIN(rows, (long) ptr->rows_in_array - thisrow); + if (rows <= 0) /* this chunk might be past end of file! */ + break; + byte_count = rows * bytesperrow; + if (writing) + (*ptr->b_s_info.write_backing_store) (cinfo, & ptr->b_s_info, + (void FAR *) ptr->mem_buffer[i], + file_offset, byte_count); + else + (*ptr->b_s_info.read_backing_store) (cinfo, & ptr->b_s_info, + (void FAR *) ptr->mem_buffer[i], + file_offset, byte_count); + file_offset += byte_count; + } +} + + +LOCAL(void) +do_barray_io (j_common_ptr cinfo, jvirt_barray_ptr ptr, boolean writing) +/* Do backing store read or write of a virtual coefficient-block array */ +{ + long bytesperrow, file_offset, byte_count, rows, thisrow, i; + + bytesperrow = (long) ptr->blocksperrow * SIZEOF(JBLOCK); + file_offset = ptr->cur_start_row * bytesperrow; + /* Loop to read or write each allocation chunk in mem_buffer */ + for (i = 0; i < (long) ptr->rows_in_mem; i += ptr->rowsperchunk) { + /* One chunk, but check for short chunk at end of buffer */ + rows = MIN((long) ptr->rowsperchunk, (long) ptr->rows_in_mem - i); + /* Transfer no more than is currently defined */ + thisrow = (long) ptr->cur_start_row + i; + rows = MIN(rows, (long) ptr->first_undef_row - thisrow); + /* Transfer no more than fits in file */ + rows = MIN(rows, (long) ptr->rows_in_array - thisrow); + if (rows <= 0) /* this chunk might be past end of file! */ + break; + byte_count = rows * bytesperrow; + if (writing) + (*ptr->b_s_info.write_backing_store) (cinfo, & ptr->b_s_info, + (void FAR *) ptr->mem_buffer[i], + file_offset, byte_count); + else + (*ptr->b_s_info.read_backing_store) (cinfo, & ptr->b_s_info, + (void FAR *) ptr->mem_buffer[i], + file_offset, byte_count); + file_offset += byte_count; + } +} + + +METHODDEF(JSAMPARRAY) +access_virt_sarray (j_common_ptr cinfo, jvirt_sarray_ptr ptr, + JDIMENSION start_row, JDIMENSION num_rows, + boolean writable) +/* Access the part of a virtual sample array starting at start_row */ +/* and extending for num_rows rows. writable is true if */ +/* caller intends to modify the accessed area. */ +{ + JDIMENSION end_row = start_row + num_rows; + JDIMENSION undef_row; + + /* debugging check */ + if (end_row > ptr->rows_in_array || num_rows > ptr->maxaccess || + ptr->mem_buffer == NULL) + ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); + + /* Make the desired part of the virtual array accessible */ + if (start_row < ptr->cur_start_row || + end_row > ptr->cur_start_row+ptr->rows_in_mem) { + if (! ptr->b_s_open) + ERREXIT(cinfo, JERR_VIRTUAL_BUG); + /* Flush old buffer contents if necessary */ + if (ptr->dirty) { + do_sarray_io(cinfo, ptr, TRUE); + ptr->dirty = FALSE; + } + /* Decide what part of virtual array to access. + * Algorithm: if target address > current window, assume forward scan, + * load starting at target address. If target address < current window, + * assume backward scan, load so that target area is top of window. + * Note that when switching from forward write to forward read, will have + * start_row = 0, so the limiting case applies and we load from 0 anyway. + */ + if (start_row > ptr->cur_start_row) { + ptr->cur_start_row = start_row; + } else { + /* use long arithmetic here to avoid overflow & unsigned problems */ + long ltemp; + + ltemp = (long) end_row - (long) ptr->rows_in_mem; + if (ltemp < 0) + ltemp = 0; /* don't fall off front end of file */ + ptr->cur_start_row = (JDIMENSION) ltemp; + } + /* Read in the selected part of the array. + * During the initial write pass, we will do no actual read + * because the selected part is all undefined. + */ + do_sarray_io(cinfo, ptr, FALSE); + } + /* Ensure the accessed part of the array is defined; prezero if needed. + * To improve locality of access, we only prezero the part of the array + * that the caller is about to access, not the entire in-memory array. + */ + if (ptr->first_undef_row < end_row) { + if (ptr->first_undef_row < start_row) { + if (writable) /* writer skipped over a section of array */ + ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); + undef_row = start_row; /* but reader is allowed to read ahead */ + } else { + undef_row = ptr->first_undef_row; + } + if (writable) + ptr->first_undef_row = end_row; + if (ptr->pre_zero) { + size_t bytesperrow = (size_t) ptr->samplesperrow * SIZEOF(JSAMPLE); + undef_row -= ptr->cur_start_row; /* make indexes relative to buffer */ + end_row -= ptr->cur_start_row; + while (undef_row < end_row) { + jzero_far((void FAR *) ptr->mem_buffer[undef_row], bytesperrow); + undef_row++; + } + } else { + if (! writable) /* reader looking at undefined data */ + ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); + } + } + /* Flag the buffer dirty if caller will write in it */ + if (writable) + ptr->dirty = TRUE; + /* Return address of proper part of the buffer */ + return ptr->mem_buffer + (start_row - ptr->cur_start_row); +} + + +METHODDEF(JBLOCKARRAY) +access_virt_barray (j_common_ptr cinfo, jvirt_barray_ptr ptr, + JDIMENSION start_row, JDIMENSION num_rows, + boolean writable) +/* Access the part of a virtual block array starting at start_row */ +/* and extending for num_rows rows. writable is true if */ +/* caller intends to modify the accessed area. */ +{ + JDIMENSION end_row = start_row + num_rows; + JDIMENSION undef_row; + + /* debugging check */ + if (end_row > ptr->rows_in_array || num_rows > ptr->maxaccess || + ptr->mem_buffer == NULL) + ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); + + /* Make the desired part of the virtual array accessible */ + if (start_row < ptr->cur_start_row || + end_row > ptr->cur_start_row+ptr->rows_in_mem) { + if (! ptr->b_s_open) + ERREXIT(cinfo, JERR_VIRTUAL_BUG); + /* Flush old buffer contents if necessary */ + if (ptr->dirty) { + do_barray_io(cinfo, ptr, TRUE); + ptr->dirty = FALSE; + } + /* Decide what part of virtual array to access. + * Algorithm: if target address > current window, assume forward scan, + * load starting at target address. If target address < current window, + * assume backward scan, load so that target area is top of window. + * Note that when switching from forward write to forward read, will have + * start_row = 0, so the limiting case applies and we load from 0 anyway. + */ + if (start_row > ptr->cur_start_row) { + ptr->cur_start_row = start_row; + } else { + /* use long arithmetic here to avoid overflow & unsigned problems */ + long ltemp; + + ltemp = (long) end_row - (long) ptr->rows_in_mem; + if (ltemp < 0) + ltemp = 0; /* don't fall off front end of file */ + ptr->cur_start_row = (JDIMENSION) ltemp; + } + /* Read in the selected part of the array. + * During the initial write pass, we will do no actual read + * because the selected part is all undefined. + */ + do_barray_io(cinfo, ptr, FALSE); + } + /* Ensure the accessed part of the array is defined; prezero if needed. + * To improve locality of access, we only prezero the part of the array + * that the caller is about to access, not the entire in-memory array. + */ + if (ptr->first_undef_row < end_row) { + if (ptr->first_undef_row < start_row) { + if (writable) /* writer skipped over a section of array */ + ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); + undef_row = start_row; /* but reader is allowed to read ahead */ + } else { + undef_row = ptr->first_undef_row; + } + if (writable) + ptr->first_undef_row = end_row; + if (ptr->pre_zero) { + size_t bytesperrow = (size_t) ptr->blocksperrow * SIZEOF(JBLOCK); + undef_row -= ptr->cur_start_row; /* make indexes relative to buffer */ + end_row -= ptr->cur_start_row; + while (undef_row < end_row) { + jzero_far((void FAR *) ptr->mem_buffer[undef_row], bytesperrow); + undef_row++; + } + } else { + if (! writable) /* reader looking at undefined data */ + ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); + } + } + /* Flag the buffer dirty if caller will write in it */ + if (writable) + ptr->dirty = TRUE; + /* Return address of proper part of the buffer */ + return ptr->mem_buffer + (start_row - ptr->cur_start_row); +} + + +/* + * Release all objects belonging to a specified pool. + */ + +METHODDEF(void) +free_pool (j_common_ptr cinfo, int pool_id) +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + small_pool_ptr shdr_ptr; + large_pool_ptr lhdr_ptr; + size_t space_freed; + + if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS) + ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ + +#ifdef MEM_STATS + if (cinfo->err->trace_level > 1) + print_mem_stats(cinfo, pool_id); /* print pool's memory usage statistics */ +#endif + + /* If freeing IMAGE pool, close any virtual arrays first */ + if (pool_id == JPOOL_IMAGE) { + jvirt_sarray_ptr sptr; + jvirt_barray_ptr bptr; + + for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) { + if (sptr->b_s_open) { /* there may be no backing store */ + sptr->b_s_open = FALSE; /* prevent recursive close if error */ + (*sptr->b_s_info.close_backing_store) (cinfo, & sptr->b_s_info); + } + } + mem->virt_sarray_list = NULL; + for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) { + if (bptr->b_s_open) { /* there may be no backing store */ + bptr->b_s_open = FALSE; /* prevent recursive close if error */ + (*bptr->b_s_info.close_backing_store) (cinfo, & bptr->b_s_info); + } + } + mem->virt_barray_list = NULL; + } + + /* Release large objects */ + lhdr_ptr = mem->large_list[pool_id]; + mem->large_list[pool_id] = NULL; + + while (lhdr_ptr != NULL) { + large_pool_ptr next_lhdr_ptr = lhdr_ptr->hdr.next; + space_freed = lhdr_ptr->hdr.bytes_used + + lhdr_ptr->hdr.bytes_left + + SIZEOF(large_pool_hdr); + jpeg_free_large(cinfo, (void FAR *) lhdr_ptr, space_freed); + mem->total_space_allocated -= space_freed; + lhdr_ptr = next_lhdr_ptr; + } + + /* Release small objects */ + shdr_ptr = mem->small_list[pool_id]; + mem->small_list[pool_id] = NULL; + + while (shdr_ptr != NULL) { + small_pool_ptr next_shdr_ptr = shdr_ptr->hdr.next; + space_freed = shdr_ptr->hdr.bytes_used + + shdr_ptr->hdr.bytes_left + + SIZEOF(small_pool_hdr); + jpeg_free_small(cinfo, (void *) shdr_ptr, space_freed); + mem->total_space_allocated -= space_freed; + shdr_ptr = next_shdr_ptr; + } +} + + +/* + * Close up shop entirely. + * Note that this cannot be called unless cinfo->mem is non-NULL. + */ + +METHODDEF(void) +self_destruct (j_common_ptr cinfo) +{ + int pool; + + /* Close all backing store, release all memory. + * Releasing pools in reverse order might help avoid fragmentation + * with some (brain-damaged) malloc libraries. + */ + for (pool = JPOOL_NUMPOOLS-1; pool >= JPOOL_PERMANENT; pool--) { + free_pool(cinfo, pool); + } + + /* Release the memory manager control block too. */ + jpeg_free_small(cinfo, (void *) cinfo->mem, SIZEOF(my_memory_mgr)); + cinfo->mem = NULL; /* ensures I will be called only once */ + + jpeg_mem_term(cinfo); /* system-dependent cleanup */ +} + + +/* + * Memory manager initialization. + * When this is called, only the error manager pointer is valid in cinfo! + */ + +GLOBAL(void) +jinit_memory_mgr (j_common_ptr cinfo) +{ + my_mem_ptr mem; + long max_to_use; + int pool; + size_t test_mac; + + cinfo->mem = NULL; /* for safety if init fails */ + + /* Check for configuration errors. + * SIZEOF(ALIGN_TYPE) should be a power of 2; otherwise, it probably + * doesn't reflect any real hardware alignment requirement. + * The test is a little tricky: for X>0, X and X-1 have no one-bits + * in common if and only if X is a power of 2, ie has only one one-bit. + * Some compilers may give an "unreachable code" warning here; ignore it. + */ + if ((SIZEOF(ALIGN_TYPE) & (SIZEOF(ALIGN_TYPE)-1)) != 0) + ERREXIT(cinfo, JERR_BAD_ALIGN_TYPE); + /* MAX_ALLOC_CHUNK must be representable as type size_t, and must be + * a multiple of SIZEOF(ALIGN_TYPE). + * Again, an "unreachable code" warning may be ignored here. + * But a "constant too large" warning means you need to fix MAX_ALLOC_CHUNK. + */ + test_mac = (size_t) MAX_ALLOC_CHUNK; + if ((long) test_mac != MAX_ALLOC_CHUNK || + (MAX_ALLOC_CHUNK % SIZEOF(ALIGN_TYPE)) != 0) + ERREXIT(cinfo, JERR_BAD_ALLOC_CHUNK); + + max_to_use = jpeg_mem_init(cinfo); /* system-dependent initialization */ + + /* Attempt to allocate memory manager's control block */ + mem = (my_mem_ptr) jpeg_get_small(cinfo, SIZEOF(my_memory_mgr)); + + if (mem == NULL) { + jpeg_mem_term(cinfo); /* system-dependent cleanup */ + ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 0); + } + + /* OK, fill in the method pointers */ + mem->pub.alloc_small = alloc_small; + mem->pub.alloc_large = alloc_large; + mem->pub.alloc_sarray = alloc_sarray; + mem->pub.alloc_barray = alloc_barray; + mem->pub.request_virt_sarray = request_virt_sarray; + mem->pub.request_virt_barray = request_virt_barray; + mem->pub.realize_virt_arrays = realize_virt_arrays; + mem->pub.access_virt_sarray = access_virt_sarray; + mem->pub.access_virt_barray = access_virt_barray; + mem->pub.free_pool = free_pool; + mem->pub.self_destruct = self_destruct; + + /* Make MAX_ALLOC_CHUNK accessible to other modules */ + mem->pub.max_alloc_chunk = MAX_ALLOC_CHUNK; + + /* Initialize working state */ + mem->pub.max_memory_to_use = max_to_use; + + for (pool = JPOOL_NUMPOOLS-1; pool >= JPOOL_PERMANENT; pool--) { + mem->small_list[pool] = NULL; + mem->large_list[pool] = NULL; + } + mem->virt_sarray_list = NULL; + mem->virt_barray_list = NULL; + + mem->total_space_allocated = SIZEOF(my_memory_mgr); + + /* Declare ourselves open for business */ + cinfo->mem = & mem->pub; + + /* Check for an environment variable JPEGMEM; if found, override the + * default max_memory setting from jpeg_mem_init. Note that the + * surrounding application may again override this value. + * If your system doesn't support getenv(), define NO_GETENV to disable + * this feature. + */ +#ifndef NO_GETENV + { char * memenv; + + if ((memenv = getenv("JPEGMEM")) != NULL) { + char ch = 'x'; + + if (sscanf(memenv, "%ld%c", &max_to_use, &ch) > 0) { + if (ch == 'm' || ch == 'M') + max_to_use *= 1000L; + mem->pub.max_memory_to_use = max_to_use * 1000L; + } + } + } +#endif + +} diff --git a/jpeg/JMEMNOBS.C b/jpeg/JMEMNOBS.C new file mode 100644 index 0000000..4ea5e2c --- /dev/null +++ b/jpeg/JMEMNOBS.C @@ -0,0 +1,109 @@ +/* + * jmemnobs.c + * + * Copyright (C) 1992-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file provides a really simple implementation of the system- + * dependent portion of the JPEG memory manager. This implementation + * assumes that no backing-store files are needed: all required space + * can be obtained from malloc(). + * This is very portable in the sense that it'll compile on almost anything, + * but you'd better have lots of main memory (or virtual memory) if you want + * to process big images. + * Note that the max_memory_to_use option is ignored by this implementation. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jmemsys.h" /* import the system-dependent declarations */ + +#ifndef HAVE_STDLIB_H /* should declare malloc(),free() */ +extern void * malloc JPP((size_t size)); +extern void free JPP((void *ptr)); +#endif + + +/* + * Memory allocation and freeing are controlled by the regular library + * routines malloc() and free(). + */ + +GLOBAL(void *) +jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject) +{ + return (void *) malloc(sizeofobject); +} + +GLOBAL(void) +jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject) +{ + free(object); +} + + +/* + * "Large" objects are treated the same as "small" ones. + * NB: although we include FAR keywords in the routine declarations, + * this file won't actually work in 80x86 small/medium model; at least, + * you probably won't be able to process useful-size images in only 64KB. + */ + +GLOBAL(void FAR *) +jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject) +{ + return (void FAR *) malloc(sizeofobject); +} + +GLOBAL(void) +jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject) +{ + free(object); +} + + +/* + * This routine computes the total memory space available for allocation. + * Here we always say, "we got all you want bud!" + */ + +GLOBAL(long) +jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed, + long max_bytes_needed, long already_allocated) +{ + return max_bytes_needed; +} + + +/* + * Backing store (temporary file) management. + * Since jpeg_mem_available always promised the moon, + * this should never be called and we can just error out. + */ + +GLOBAL(void) +jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info, + long total_bytes_needed) +{ + ERREXIT(cinfo, JERR_NO_BACKING_STORE); +} + + +/* + * These routines take care of any system-dependent initialization and + * cleanup required. Here, there isn't any. + */ + +GLOBAL(long) +jpeg_mem_init (j_common_ptr cinfo) +{ + return 0; /* just set max_memory_to_use to 0 */ +} + +GLOBAL(void) +jpeg_mem_term (j_common_ptr cinfo) +{ + /* no work */ +} diff --git a/jpeg/JMEMSYS.H b/jpeg/JMEMSYS.H new file mode 100644 index 0000000..03f3bd1 --- /dev/null +++ b/jpeg/JMEMSYS.H @@ -0,0 +1,198 @@ +/* + * jmemsys.h + * + * Copyright (C) 1992-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This include file defines the interface between the system-independent + * and system-dependent portions of the JPEG memory manager. No other + * modules need include it. (The system-independent portion is jmemmgr.c; + * there are several different versions of the system-dependent portion.) + * + * This file works as-is for the system-dependent memory managers supplied + * in the IJG distribution. You may need to modify it if you write a + * custom memory manager. If system-dependent changes are needed in + * this file, the best method is to #ifdef them based on a configuration + * symbol supplied in jconfig.h, as we have done with USE_MSDOS_MEMMGR + * and USE_MAC_MEMMGR. + */ + + +/* Short forms of external names for systems with brain-damaged linkers. */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jpeg_get_small jGetSmall +#define jpeg_free_small jFreeSmall +#define jpeg_get_large jGetLarge +#define jpeg_free_large jFreeLarge +#define jpeg_mem_available jMemAvail +#define jpeg_open_backing_store jOpenBackStore +#define jpeg_mem_init jMemInit +#define jpeg_mem_term jMemTerm +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + + +/* + * These two functions are used to allocate and release small chunks of + * memory. (Typically the total amount requested through jpeg_get_small is + * no more than 20K or so; this will be requested in chunks of a few K each.) + * Behavior should be the same as for the standard library functions malloc + * and free; in particular, jpeg_get_small must return NULL on failure. + * On most systems, these ARE malloc and free. jpeg_free_small is passed the + * size of the object being freed, just in case it's needed. + * On an 80x86 machine using small-data memory model, these manage near heap. + */ + +EXTERN(void *) jpeg_get_small JPP((j_common_ptr cinfo, size_t sizeofobject)); +EXTERN(void) jpeg_free_small JPP((j_common_ptr cinfo, void * object, + size_t sizeofobject)); + +/* + * These two functions are used to allocate and release large chunks of + * memory (up to the total free space designated by jpeg_mem_available). + * The interface is the same as above, except that on an 80x86 machine, + * far pointers are used. On most other machines these are identical to + * the jpeg_get/free_small routines; but we keep them separate anyway, + * in case a different allocation strategy is desirable for large chunks. + */ + +EXTERN(void FAR *) jpeg_get_large JPP((j_common_ptr cinfo, + size_t sizeofobject)); +EXTERN(void) jpeg_free_large JPP((j_common_ptr cinfo, void FAR * object, + size_t sizeofobject)); + +/* + * The macro MAX_ALLOC_CHUNK designates the maximum number of bytes that may + * be requested in a single call to jpeg_get_large (and jpeg_get_small for that + * matter, but that case should never come into play). This macro is needed + * to model the 64Kb-segment-size limit of far addressing on 80x86 machines. + * On those machines, we expect that jconfig.h will provide a proper value. + * On machines with 32-bit flat address spaces, any large constant may be used. + * + * NB: jmemmgr.c expects that MAX_ALLOC_CHUNK will be representable as type + * size_t and will be a multiple of sizeof(align_type). + */ + +#ifndef MAX_ALLOC_CHUNK /* may be overridden in jconfig.h */ +#define MAX_ALLOC_CHUNK 1000000000L +#endif + +/* + * This routine computes the total space still available for allocation by + * jpeg_get_large. If more space than this is needed, backing store will be + * used. NOTE: any memory already allocated must not be counted. + * + * There is a minimum space requirement, corresponding to the minimum + * feasible buffer sizes; jmemmgr.c will request that much space even if + * jpeg_mem_available returns zero. The maximum space needed, enough to hold + * all working storage in memory, is also passed in case it is useful. + * Finally, the total space already allocated is passed. If no better + * method is available, cinfo->mem->max_memory_to_use - already_allocated + * is often a suitable calculation. + * + * It is OK for jpeg_mem_available to underestimate the space available + * (that'll just lead to more backing-store access than is really necessary). + * However, an overestimate will lead to failure. Hence it's wise to subtract + * a slop factor from the true available space. 5% should be enough. + * + * On machines with lots of virtual memory, any large constant may be returned. + * Conversely, zero may be returned to always use the minimum amount of memory. + */ + +EXTERN(long) jpeg_mem_available JPP((j_common_ptr cinfo, + long min_bytes_needed, + long max_bytes_needed, + long already_allocated)); + + +/* + * This structure holds whatever state is needed to access a single + * backing-store object. The read/write/close method pointers are called + * by jmemmgr.c to manipulate the backing-store object; all other fields + * are private to the system-dependent backing store routines. + */ + +#define TEMP_NAME_LENGTH 64 /* max length of a temporary file's name */ + + +#ifdef USE_MSDOS_MEMMGR /* DOS-specific junk */ + +typedef unsigned short XMSH; /* type of extended-memory handles */ +typedef unsigned short EMSH; /* type of expanded-memory handles */ + +typedef union { + short file_handle; /* DOS file handle if it's a temp file */ + XMSH xms_handle; /* handle if it's a chunk of XMS */ + EMSH ems_handle; /* handle if it's a chunk of EMS */ +} handle_union; + +#endif /* USE_MSDOS_MEMMGR */ + +#ifdef USE_MAC_MEMMGR /* Mac-specific junk */ +#include +#endif /* USE_MAC_MEMMGR */ + + +typedef struct backing_store_struct * backing_store_ptr; + +typedef struct backing_store_struct { + /* Methods for reading/writing/closing this backing-store object */ + JMETHOD(void, read_backing_store, (j_common_ptr cinfo, + backing_store_ptr info, + void FAR * buffer_address, + long file_offset, long byte_count)); + JMETHOD(void, write_backing_store, (j_common_ptr cinfo, + backing_store_ptr info, + void FAR * buffer_address, + long file_offset, long byte_count)); + JMETHOD(void, close_backing_store, (j_common_ptr cinfo, + backing_store_ptr info)); + + /* Private fields for system-dependent backing-store management */ +#ifdef USE_MSDOS_MEMMGR + /* For the MS-DOS manager (jmemdos.c), we need: */ + handle_union handle; /* reference to backing-store storage object */ + char temp_name[TEMP_NAME_LENGTH]; /* name if it's a file */ +#else +#ifdef USE_MAC_MEMMGR + /* For the Mac manager (jmemmac.c), we need: */ + short temp_file; /* file reference number to temp file */ + FSSpec tempSpec; /* the FSSpec for the temp file */ + char temp_name[TEMP_NAME_LENGTH]; /* name if it's a file */ +#else + /* For a typical implementation with temp files, we need: */ + FILE * temp_file; /* stdio reference to temp file */ + char temp_name[TEMP_NAME_LENGTH]; /* name of temp file */ +#endif +#endif +} backing_store_info; + + +/* + * Initial opening of a backing-store object. This must fill in the + * read/write/close pointers in the object. The read/write routines + * may take an error exit if the specified maximum file size is exceeded. + * (If jpeg_mem_available always returns a large value, this routine can + * just take an error exit.) + */ + +EXTERN(void) jpeg_open_backing_store JPP((j_common_ptr cinfo, + backing_store_ptr info, + long total_bytes_needed)); + + +/* + * These routines take care of any system-dependent initialization and + * cleanup required. jpeg_mem_init will be called before anything is + * allocated (and, therefore, nothing in cinfo is of use except the error + * manager pointer). It should return a suitable default value for + * max_memory_to_use; this may subsequently be overridden by the surrounding + * application. (Note that max_memory_to_use is only important if + * jpeg_mem_available chooses to consult it ... no one else will.) + * jpeg_mem_term may assume that all requested memory has been freed and that + * all opened backing-store objects have been closed. + */ + +EXTERN(long) jpeg_mem_init JPP((j_common_ptr cinfo)); +EXTERN(void) jpeg_mem_term JPP((j_common_ptr cinfo)); diff --git a/jpeg/JMORECFG.H b/jpeg/JMORECFG.H new file mode 100644 index 0000000..54a7d1c --- /dev/null +++ b/jpeg/JMORECFG.H @@ -0,0 +1,363 @@ +/* + * jmorecfg.h + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains additional configuration options that customize the + * JPEG software for special applications or support machine-dependent + * optimizations. Most users will not need to touch this file. + */ + + +/* + * Define BITS_IN_JSAMPLE as either + * 8 for 8-bit sample values (the usual setting) + * 12 for 12-bit sample values + * Only 8 and 12 are legal data precisions for lossy JPEG according to the + * JPEG standard, and the IJG code does not support anything else! + * We do not support run-time selection of data precision, sorry. + */ + +#define BITS_IN_JSAMPLE 8 /* use 8 or 12 */ + + +/* + * Maximum number of components (color channels) allowed in JPEG image. + * To meet the letter of the JPEG spec, set this to 255. However, darn + * few applications need more than 4 channels (maybe 5 for CMYK + alpha + * mask). We recommend 10 as a reasonable compromise; use 4 if you are + * really short on memory. (Each allowed component costs a hundred or so + * bytes of storage, whether actually used in an image or not.) + */ + +#define MAX_COMPONENTS 10 /* maximum number of image components */ + + +/* + * Basic data types. + * You may need to change these if you have a machine with unusual data + * type sizes; for example, "char" not 8 bits, "short" not 16 bits, + * or "long" not 32 bits. We don't care whether "int" is 16 or 32 bits, + * but it had better be at least 16. + */ + +/* Representation of a single sample (pixel element value). + * We frequently allocate large arrays of these, so it's important to keep + * them small. But if you have memory to burn and access to char or short + * arrays is very slow on your hardware, you might want to change these. + */ + +#if BITS_IN_JSAMPLE == 8 +/* JSAMPLE should be the smallest type that will hold the values 0..255. + * You can use a signed char by having GETJSAMPLE mask it with 0xFF. + */ + +#ifdef HAVE_UNSIGNED_CHAR + +typedef unsigned char JSAMPLE; +#define GETJSAMPLE(value) ((int) (value)) + +#else /* not HAVE_UNSIGNED_CHAR */ + +typedef char JSAMPLE; +#ifdef CHAR_IS_UNSIGNED +#define GETJSAMPLE(value) ((int) (value)) +#else +#define GETJSAMPLE(value) ((int) (value) & 0xFF) +#endif /* CHAR_IS_UNSIGNED */ + +#endif /* HAVE_UNSIGNED_CHAR */ + +#define MAXJSAMPLE 255 +#define CENTERJSAMPLE 128 + +#endif /* BITS_IN_JSAMPLE == 8 */ + + +#if BITS_IN_JSAMPLE == 12 +/* JSAMPLE should be the smallest type that will hold the values 0..4095. + * On nearly all machines "short" will do nicely. + */ + +typedef short JSAMPLE; +#define GETJSAMPLE(value) ((int) (value)) + +#define MAXJSAMPLE 4095 +#define CENTERJSAMPLE 2048 + +#endif /* BITS_IN_JSAMPLE == 12 */ + + +/* Representation of a DCT frequency coefficient. + * This should be a signed value of at least 16 bits; "short" is usually OK. + * Again, we allocate large arrays of these, but you can change to int + * if you have memory to burn and "short" is really slow. + */ + +typedef short JCOEF; + + +/* Compressed datastreams are represented as arrays of JOCTET. + * These must be EXACTLY 8 bits wide, at least once they are written to + * external storage. Note that when using the stdio data source/destination + * managers, this is also the data type passed to fread/fwrite. + */ + +#ifdef HAVE_UNSIGNED_CHAR + +typedef unsigned char JOCTET; +#define GETJOCTET(value) (value) + +#else /* not HAVE_UNSIGNED_CHAR */ + +typedef char JOCTET; +#ifdef CHAR_IS_UNSIGNED +#define GETJOCTET(value) (value) +#else +#define GETJOCTET(value) ((value) & 0xFF) +#endif /* CHAR_IS_UNSIGNED */ + +#endif /* HAVE_UNSIGNED_CHAR */ + + +/* These typedefs are used for various table entries and so forth. + * They must be at least as wide as specified; but making them too big + * won't cost a huge amount of memory, so we don't provide special + * extraction code like we did for JSAMPLE. (In other words, these + * typedefs live at a different point on the speed/space tradeoff curve.) + */ + +/* UINT8 must hold at least the values 0..255. */ + +#ifdef HAVE_UNSIGNED_CHAR +typedef unsigned char UINT8; +#else /* not HAVE_UNSIGNED_CHAR */ +#ifdef CHAR_IS_UNSIGNED +typedef char UINT8; +#else /* not CHAR_IS_UNSIGNED */ +typedef short UINT8; +#endif /* CHAR_IS_UNSIGNED */ +#endif /* HAVE_UNSIGNED_CHAR */ + +/* UINT16 must hold at least the values 0..65535. */ + +#ifdef HAVE_UNSIGNED_SHORT +typedef unsigned short UINT16; +#else /* not HAVE_UNSIGNED_SHORT */ +typedef unsigned int UINT16; +#endif /* HAVE_UNSIGNED_SHORT */ + +/* INT16 must hold at least the values -32768..32767. */ + +#ifndef XMD_H /* X11/xmd.h correctly defines INT16 */ +typedef short INT16; +#endif + +/* INT32 must hold at least signed 32-bit values. */ + +#ifndef XMD_H /* X11/xmd.h correctly defines INT32 */ +typedef long INT32; +#endif + +/* Datatype used for image dimensions. The JPEG standard only supports + * images up to 64K*64K due to 16-bit fields in SOF markers. Therefore + * "unsigned int" is sufficient on all machines. However, if you need to + * handle larger images and you don't mind deviating from the spec, you + * can change this datatype. + */ + +typedef unsigned int JDIMENSION; + +#define JPEG_MAX_DIMENSION 65500L /* a tad under 64K to prevent overflows */ + + +/* These macros are used in all function definitions and extern declarations. + * You could modify them if you need to change function linkage conventions; + * in particular, you'll need to do that to make the library a Windows DLL. + * Another application is to make all functions global for use with debuggers + * or code profilers that require it. + */ + +/* a function called through method pointers: */ +#define METHODDEF(type) static type +/* a function used only in its module: */ +#define LOCAL(type) static type +/* a function referenced thru EXTERNs: */ +#define GLOBAL(type) type +/* a reference to a GLOBAL function: */ +#define EXTERN(type) extern type + + +/* This macro is used to declare a "method", that is, a function pointer. + * We want to supply prototype parameters if the compiler can cope. + * Note that the arglist parameter must be parenthesized! + * Again, you can customize this if you need special linkage keywords. + */ + +#ifdef HAVE_PROTOTYPES +#define JMETHOD(type,methodname,arglist) type (*methodname) arglist +#else +#define JMETHOD(type,methodname,arglist) type (*methodname) () +#endif + + +/* Here is the pseudo-keyword for declaring pointers that must be "far" + * on 80x86 machines. Most of the specialized coding for 80x86 is handled + * by just saying "FAR *" where such a pointer is needed. In a few places + * explicit coding is needed; see uses of the NEED_FAR_POINTERS symbol. + */ + +#ifdef NEED_FAR_POINTERS +#define FAR far +#else +#define FAR +#endif + + +/* + * On a few systems, type boolean and/or its values FALSE, TRUE may appear + * in standard header files. Or you may have conflicts with application- + * specific header files that you want to include together with these files. + * Defining HAVE_BOOLEAN before including jpeglib.h should make it work. + */ + +#ifndef HAVE_BOOLEAN +typedef int boolean; +#endif +#ifndef FALSE /* in case these macros already exist */ +#define FALSE 0 /* values of boolean */ +#endif +#ifndef TRUE +#define TRUE 1 +#endif + + +/* + * The remaining options affect code selection within the JPEG library, + * but they don't need to be visible to most applications using the library. + * To minimize application namespace pollution, the symbols won't be + * defined unless JPEG_INTERNALS or JPEG_INTERNAL_OPTIONS has been defined. + */ + +#ifdef JPEG_INTERNALS +#define JPEG_INTERNAL_OPTIONS +#endif + +#ifdef JPEG_INTERNAL_OPTIONS + + +/* + * These defines indicate whether to include various optional functions. + * Undefining some of these symbols will produce a smaller but less capable + * library. Note that you can leave certain source files out of the + * compilation/linking process if you've #undef'd the corresponding symbols. + * (You may HAVE to do that if your compiler doesn't like null source files.) + */ + +/* Arithmetic coding is unsupported for legal reasons. Complaints to IBM. */ + +/* Capability options common to encoder and decoder: */ + +#define DCT_ISLOW_SUPPORTED /* slow but accurate integer algorithm */ +#define DCT_IFAST_SUPPORTED /* faster, less accurate integer method */ +#define DCT_FLOAT_SUPPORTED /* floating-point: accurate, fast on fast HW */ + +/* Encoder capability options: */ + +#undef C_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ +#define C_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ +#define C_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ +#define ENTROPY_OPT_SUPPORTED /* Optimization of entropy coding parms? */ +/* Note: if you selected 12-bit data precision, it is dangerous to turn off + * ENTROPY_OPT_SUPPORTED. The standard Huffman tables are only good for 8-bit + * precision, so jchuff.c normally uses entropy optimization to compute + * usable tables for higher precision. If you don't want to do optimization, + * you'll have to supply different default Huffman tables. + * The exact same statements apply for progressive JPEG: the default tables + * don't work for progressive mode. (This may get fixed, however.) + */ +#define INPUT_SMOOTHING_SUPPORTED /* Input image smoothing option? */ + +/* Decoder capability options: */ + +#undef D_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ +#define D_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ +#define D_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ +#define SAVE_MARKERS_SUPPORTED /* jpeg_save_markers() needed? */ +#define BLOCK_SMOOTHING_SUPPORTED /* Block smoothing? (Progressive only) */ +#define IDCT_SCALING_SUPPORTED /* Output rescaling via IDCT? */ +#undef UPSAMPLE_SCALING_SUPPORTED /* Output rescaling at upsample stage? */ +#define UPSAMPLE_MERGING_SUPPORTED /* Fast path for sloppy upsampling? */ +#define QUANT_1PASS_SUPPORTED /* 1-pass color quantization? */ +#define QUANT_2PASS_SUPPORTED /* 2-pass color quantization? */ + +/* more capability options later, no doubt */ + + +/* + * Ordering of RGB data in scanlines passed to or from the application. + * If your application wants to deal with data in the order B,G,R, just + * change these macros. You can also deal with formats such as R,G,B,X + * (one extra byte per pixel) by changing RGB_PIXELSIZE. Note that changing + * the offsets will also change the order in which colormap data is organized. + * RESTRICTIONS: + * 1. The sample applications cjpeg,djpeg do NOT support modified RGB formats. + * 2. These macros only affect RGB<=>YCbCr color conversion, so they are not + * useful if you are using JPEG color spaces other than YCbCr or grayscale. + * 3. The color quantizer modules will not behave desirably if RGB_PIXELSIZE + * is not 3 (they don't understand about dummy color components!). So you + * can't use color quantization if you change that value. + */ + +#define RGB_RED 0 /* Offset of Red in an RGB scanline element */ +#define RGB_GREEN 1 /* Offset of Green */ +#define RGB_BLUE 2 /* Offset of Blue */ +#define RGB_PIXELSIZE 3 /* JSAMPLEs per RGB scanline element */ + + +/* Definitions for speed-related optimizations. */ + + +/* If your compiler supports inline functions, define INLINE + * as the inline keyword; otherwise define it as empty. + */ + +#ifndef INLINE +#ifdef __GNUC__ /* for instance, GNU C knows about inline */ +#define INLINE __inline__ +#endif +#ifndef INLINE +#define INLINE /* default is to define it as empty */ +#endif +#endif + + +/* On some machines (notably 68000 series) "int" is 32 bits, but multiplying + * two 16-bit shorts is faster than multiplying two ints. Define MULTIPLIER + * as short on such a machine. MULTIPLIER must be at least 16 bits wide. + */ + +#ifndef MULTIPLIER +#define MULTIPLIER int /* type for fastest integer multiply */ +#endif + + +/* FAST_FLOAT should be either float or double, whichever is done faster + * by your compiler. (Note that this type is only used in the floating point + * DCT routines, so it only matters if you've defined DCT_FLOAT_SUPPORTED.) + * Typically, float is faster in ANSI C compilers, while double is faster in + * pre-ANSI compilers (because they insist on converting to double anyway). + * The code below therefore chooses float if we have ANSI-style prototypes. + */ + +#ifndef FAST_FLOAT +#ifdef HAVE_PROTOTYPES +#define FAST_FLOAT float +#else +#define FAST_FLOAT double +#endif +#endif + +#endif /* JPEG_INTERNAL_OPTIONS */ diff --git a/jpeg/JPEGINT.H b/jpeg/JPEGINT.H new file mode 100644 index 0000000..559c476 --- /dev/null +++ b/jpeg/JPEGINT.H @@ -0,0 +1,392 @@ +/* + * jpegint.h + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file provides common declarations for the various JPEG modules. + * These declarations are considered internal to the JPEG library; most + * applications using the library shouldn't need to include this file. + */ + + +/* Declarations for both compression & decompression */ + +typedef enum { /* Operating modes for buffer controllers */ + JBUF_PASS_THRU, /* Plain stripwise operation */ + /* Remaining modes require a full-image buffer to have been created */ + JBUF_SAVE_SOURCE, /* Run source subobject only, save output */ + JBUF_CRANK_DEST, /* Run dest subobject only, using saved data */ + JBUF_SAVE_AND_PASS /* Run both subobjects, save output */ +} J_BUF_MODE; + +/* Values of global_state field (jdapi.c has some dependencies on ordering!) */ +#define CSTATE_START 100 /* after create_compress */ +#define CSTATE_SCANNING 101 /* start_compress done, write_scanlines OK */ +#define CSTATE_RAW_OK 102 /* start_compress done, write_raw_data OK */ +#define CSTATE_WRCOEFS 103 /* jpeg_write_coefficients done */ +#define DSTATE_START 200 /* after create_decompress */ +#define DSTATE_INHEADER 201 /* reading header markers, no SOS yet */ +#define DSTATE_READY 202 /* found SOS, ready for start_decompress */ +#define DSTATE_PRELOAD 203 /* reading multiscan file in start_decompress*/ +#define DSTATE_PRESCAN 204 /* performing dummy pass for 2-pass quant */ +#define DSTATE_SCANNING 205 /* start_decompress done, read_scanlines OK */ +#define DSTATE_RAW_OK 206 /* start_decompress done, read_raw_data OK */ +#define DSTATE_BUFIMAGE 207 /* expecting jpeg_start_output */ +#define DSTATE_BUFPOST 208 /* looking for SOS/EOI in jpeg_finish_output */ +#define DSTATE_RDCOEFS 209 /* reading file in jpeg_read_coefficients */ +#define DSTATE_STOPPING 210 /* looking for EOI in jpeg_finish_decompress */ + + +/* Declarations for compression modules */ + +/* Master control module */ +struct jpeg_comp_master { + JMETHOD(void, prepare_for_pass, (j_compress_ptr cinfo)); + JMETHOD(void, pass_startup, (j_compress_ptr cinfo)); + JMETHOD(void, finish_pass, (j_compress_ptr cinfo)); + + /* State variables made visible to other modules */ + boolean call_pass_startup; /* True if pass_startup must be called */ + boolean is_last_pass; /* True during last pass */ +}; + +/* Main buffer control (downsampled-data buffer) */ +struct jpeg_c_main_controller { + JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); + JMETHOD(void, process_data, (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail)); +}; + +/* Compression preprocessing (downsampling input buffer control) */ +struct jpeg_c_prep_controller { + JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); + JMETHOD(void, pre_process_data, (j_compress_ptr cinfo, + JSAMPARRAY input_buf, + JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail, + JSAMPIMAGE output_buf, + JDIMENSION *out_row_group_ctr, + JDIMENSION out_row_groups_avail)); +}; + +/* Coefficient buffer control */ +struct jpeg_c_coef_controller { + JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); + JMETHOD(boolean, compress_data, (j_compress_ptr cinfo, + JSAMPIMAGE input_buf)); +}; + +/* Colorspace conversion */ +struct jpeg_color_converter { + JMETHOD(void, start_pass, (j_compress_ptr cinfo)); + JMETHOD(void, color_convert, (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows)); +}; + +/* Downsampling */ +struct jpeg_downsampler { + JMETHOD(void, start_pass, (j_compress_ptr cinfo)); + JMETHOD(void, downsample, (j_compress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION in_row_index, + JSAMPIMAGE output_buf, + JDIMENSION out_row_group_index)); + + boolean need_context_rows; /* TRUE if need rows above & below */ +}; + +/* Forward DCT (also controls coefficient quantization) */ +struct jpeg_forward_dct { + JMETHOD(void, start_pass, (j_compress_ptr cinfo)); + /* perhaps this should be an array??? */ + JMETHOD(void, forward_DCT, (j_compress_ptr cinfo, + jpeg_component_info * compptr, + JSAMPARRAY sample_data, JBLOCKROW coef_blocks, + JDIMENSION start_row, JDIMENSION start_col, + JDIMENSION num_blocks)); +}; + +/* Entropy encoding */ +struct jpeg_entropy_encoder { + JMETHOD(void, start_pass, (j_compress_ptr cinfo, boolean gather_statistics)); + JMETHOD(boolean, encode_mcu, (j_compress_ptr cinfo, JBLOCKROW *MCU_data)); + JMETHOD(void, finish_pass, (j_compress_ptr cinfo)); +}; + +/* Marker writing */ +struct jpeg_marker_writer { + JMETHOD(void, write_file_header, (j_compress_ptr cinfo)); + JMETHOD(void, write_frame_header, (j_compress_ptr cinfo)); + JMETHOD(void, write_scan_header, (j_compress_ptr cinfo)); + JMETHOD(void, write_file_trailer, (j_compress_ptr cinfo)); + JMETHOD(void, write_tables_only, (j_compress_ptr cinfo)); + /* These routines are exported to allow insertion of extra markers */ + /* Probably only COM and APPn markers should be written this way */ + JMETHOD(void, write_marker_header, (j_compress_ptr cinfo, int marker, + unsigned int datalen)); + JMETHOD(void, write_marker_byte, (j_compress_ptr cinfo, int val)); +}; + + +/* Declarations for decompression modules */ + +/* Master control module */ +struct jpeg_decomp_master { + JMETHOD(void, prepare_for_output_pass, (j_decompress_ptr cinfo)); + JMETHOD(void, finish_output_pass, (j_decompress_ptr cinfo)); + + /* State variables made visible to other modules */ + boolean is_dummy_pass; /* True during 1st pass for 2-pass quant */ +}; + +/* Input control module */ +struct jpeg_input_controller { + JMETHOD(int, consume_input, (j_decompress_ptr cinfo)); + JMETHOD(void, reset_input_controller, (j_decompress_ptr cinfo)); + JMETHOD(void, start_input_pass, (j_decompress_ptr cinfo)); + JMETHOD(void, finish_input_pass, (j_decompress_ptr cinfo)); + + /* State variables made visible to other modules */ + boolean has_multiple_scans; /* True if file has multiple scans */ + boolean eoi_reached; /* True when EOI has been consumed */ +}; + +/* Main buffer control (downsampled-data buffer) */ +struct jpeg_d_main_controller { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)); + JMETHOD(void, process_data, (j_decompress_ptr cinfo, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); +}; + +/* Coefficient buffer control */ +struct jpeg_d_coef_controller { + JMETHOD(void, start_input_pass, (j_decompress_ptr cinfo)); + JMETHOD(int, consume_data, (j_decompress_ptr cinfo)); + JMETHOD(void, start_output_pass, (j_decompress_ptr cinfo)); + JMETHOD(int, decompress_data, (j_decompress_ptr cinfo, + JSAMPIMAGE output_buf)); + /* Pointer to array of coefficient virtual arrays, or NULL if none */ + jvirt_barray_ptr *coef_arrays; +}; + +/* Decompression postprocessing (color quantization buffer control) */ +struct jpeg_d_post_controller { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)); + JMETHOD(void, post_process_data, (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, + JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, + JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); +}; + +/* Marker reading & parsing */ +struct jpeg_marker_reader { + JMETHOD(void, reset_marker_reader, (j_decompress_ptr cinfo)); + /* Read markers until SOS or EOI. + * Returns same codes as are defined for jpeg_consume_input: + * JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI. + */ + JMETHOD(int, read_markers, (j_decompress_ptr cinfo)); + /* Read a restart marker --- exported for use by entropy decoder only */ + jpeg_marker_parser_method read_restart_marker; + + /* State of marker reader --- nominally internal, but applications + * supplying COM or APPn handlers might like to know the state. + */ + boolean saw_SOI; /* found SOI? */ + boolean saw_SOF; /* found SOF? */ + int next_restart_num; /* next restart number expected (0-7) */ + unsigned int discarded_bytes; /* # of bytes skipped looking for a marker */ +}; + +/* Entropy decoding */ +struct jpeg_entropy_decoder { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); + JMETHOD(boolean, decode_mcu, (j_decompress_ptr cinfo, + JBLOCKROW *MCU_data)); + + /* This is here to share code between baseline and progressive decoders; */ + /* other modules probably should not use it */ + boolean insufficient_data; /* set TRUE after emitting warning */ +}; + +/* Inverse DCT (also performs dequantization) */ +typedef JMETHOD(void, inverse_DCT_method_ptr, + (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col)); + +struct jpeg_inverse_dct { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); + /* It is useful to allow each component to have a separate IDCT method. */ + inverse_DCT_method_ptr inverse_DCT[MAX_COMPONENTS]; +}; + +/* Upsampling (note that upsampler must also call color converter) */ +struct jpeg_upsampler { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); + JMETHOD(void, upsample, (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, + JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, + JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); + + boolean need_context_rows; /* TRUE if need rows above & below */ +}; + +/* Colorspace conversion */ +struct jpeg_color_deconverter { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); + JMETHOD(void, color_convert, (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows)); +}; + +/* Color quantization or color precision reduction */ +struct jpeg_color_quantizer { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo, boolean is_pre_scan)); + JMETHOD(void, color_quantize, (j_decompress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPARRAY output_buf, + int num_rows)); + JMETHOD(void, finish_pass, (j_decompress_ptr cinfo)); + JMETHOD(void, new_color_map, (j_decompress_ptr cinfo)); +}; + + +/* Miscellaneous useful macros */ + +#undef MAX +#define MAX(a,b) ((a) > (b) ? (a) : (b)) +#undef MIN +#define MIN(a,b) ((a) < (b) ? (a) : (b)) + + +/* We assume that right shift corresponds to signed division by 2 with + * rounding towards minus infinity. This is correct for typical "arithmetic + * shift" instructions that shift in copies of the sign bit. But some + * C compilers implement >> with an unsigned shift. For these machines you + * must define RIGHT_SHIFT_IS_UNSIGNED. + * RIGHT_SHIFT provides a proper signed right shift of an INT32 quantity. + * It is only applied with constant shift counts. SHIFT_TEMPS must be + * included in the variables of any routine using RIGHT_SHIFT. + */ + +#ifdef RIGHT_SHIFT_IS_UNSIGNED +#define SHIFT_TEMPS INT32 shift_temp; +#define RIGHT_SHIFT(x,shft) \ + ((shift_temp = (x)) < 0 ? \ + (shift_temp >> (shft)) | ((~((INT32) 0)) << (32-(shft))) : \ + (shift_temp >> (shft))) +#else +#define SHIFT_TEMPS +#define RIGHT_SHIFT(x,shft) ((x) >> (shft)) +#endif + + +/* Short forms of external names for systems with brain-damaged linkers. */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jinit_compress_master jICompress +#define jinit_c_master_control jICMaster +#define jinit_c_main_controller jICMainC +#define jinit_c_prep_controller jICPrepC +#define jinit_c_coef_controller jICCoefC +#define jinit_color_converter jICColor +#define jinit_downsampler jIDownsampler +#define jinit_forward_dct jIFDCT +#define jinit_huff_encoder jIHEncoder +#define jinit_phuff_encoder jIPHEncoder +#define jinit_marker_writer jIMWriter +#define jinit_master_decompress jIDMaster +#define jinit_d_main_controller jIDMainC +#define jinit_d_coef_controller jIDCoefC +#define jinit_d_post_controller jIDPostC +#define jinit_input_controller jIInCtlr +#define jinit_marker_reader jIMReader +#define jinit_huff_decoder jIHDecoder +#define jinit_phuff_decoder jIPHDecoder +#define jinit_inverse_dct jIIDCT +#define jinit_upsampler jIUpsampler +#define jinit_color_deconverter jIDColor +#define jinit_1pass_quantizer jI1Quant +#define jinit_2pass_quantizer jI2Quant +#define jinit_merged_upsampler jIMUpsampler +#define jinit_memory_mgr jIMemMgr +#define jdiv_round_up jDivRound +#define jround_up jRound +#define jcopy_sample_rows jCopySamples +#define jcopy_block_row jCopyBlocks +#define jzero_far jZeroFar +#define jpeg_zigzag_order jZIGTable +#define jpeg_natural_order jZAGTable +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + + +/* Compression module initialization routines */ +EXTERN(void) jinit_compress_master JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_c_master_control JPP((j_compress_ptr cinfo, + boolean transcode_only)); +EXTERN(void) jinit_c_main_controller JPP((j_compress_ptr cinfo, + boolean need_full_buffer)); +EXTERN(void) jinit_c_prep_controller JPP((j_compress_ptr cinfo, + boolean need_full_buffer)); +EXTERN(void) jinit_c_coef_controller JPP((j_compress_ptr cinfo, + boolean need_full_buffer)); +EXTERN(void) jinit_color_converter JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_downsampler JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_forward_dct JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_huff_encoder JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_phuff_encoder JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_marker_writer JPP((j_compress_ptr cinfo)); +/* Decompression module initialization routines */ +EXTERN(void) jinit_master_decompress JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_d_main_controller JPP((j_decompress_ptr cinfo, + boolean need_full_buffer)); +EXTERN(void) jinit_d_coef_controller JPP((j_decompress_ptr cinfo, + boolean need_full_buffer)); +EXTERN(void) jinit_d_post_controller JPP((j_decompress_ptr cinfo, + boolean need_full_buffer)); +EXTERN(void) jinit_input_controller JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_marker_reader JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_huff_decoder JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_phuff_decoder JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_inverse_dct JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_upsampler JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_color_deconverter JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_1pass_quantizer JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_2pass_quantizer JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_merged_upsampler JPP((j_decompress_ptr cinfo)); +/* Memory manager initialization */ +EXTERN(void) jinit_memory_mgr JPP((j_common_ptr cinfo)); + +/* Utility routines in jutils.c */ +EXTERN(long) jdiv_round_up JPP((long a, long b)); +EXTERN(long) jround_up JPP((long a, long b)); +EXTERN(void) jcopy_sample_rows JPP((JSAMPARRAY input_array, int source_row, + JSAMPARRAY output_array, int dest_row, + int num_rows, JDIMENSION num_cols)); +EXTERN(void) jcopy_block_row JPP((JBLOCKROW input_row, JBLOCKROW output_row, + JDIMENSION num_blocks)); +EXTERN(void) jzero_far JPP((void FAR * target, size_t bytestozero)); +/* Constant tables in jutils.c */ +#if 0 /* This table is not actually needed in v6a */ +extern const int jpeg_zigzag_order[]; /* natural coef order to zigzag order */ +#endif +extern const int jpeg_natural_order[]; /* zigzag coef order to natural order */ + +/* Suppress undefined-structure complaints if necessary. */ + +#ifdef INCOMPLETE_TYPES_BROKEN +#ifndef AM_MEMORY_MANAGER /* only jmemmgr.c defines these */ +struct jvirt_sarray_control { long dummy; }; +struct jvirt_barray_control { long dummy; }; +#endif +#endif /* INCOMPLETE_TYPES_BROKEN */ diff --git a/jpeg/JPEGLIB.H b/jpeg/JPEGLIB.H new file mode 100644 index 0000000..a9781cc --- /dev/null +++ b/jpeg/JPEGLIB.H @@ -0,0 +1,1096 @@ +/* + * jpeglib.h + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file defines the application interface for the JPEG library. + * Most applications using the library need only include this file, + * and perhaps jerror.h if they want to know the exact error codes. + */ + +#ifndef JPEGLIB_H +#define JPEGLIB_H + +/* + * First we include the configuration files that record how this + * installation of the JPEG library is set up. jconfig.h can be + * generated automatically for many systems. jmorecfg.h contains + * manual configuration options that most people need not worry about. + */ + +#ifndef JCONFIG_INCLUDED /* in case jinclude.h already did */ +#include "jconfig.h" /* widely used configuration options */ +#endif +#include "jmorecfg.h" /* seldom changed options */ + + +/* Version ID for the JPEG library. + * Might be useful for tests like "#if JPEG_LIB_VERSION >= 60". + */ + +#define JPEG_LIB_VERSION 62 /* Version 6b */ + + +/* Various constants determining the sizes of things. + * All of these are specified by the JPEG standard, so don't change them + * if you want to be compatible. + */ + +#define DCTSIZE 8 /* The basic DCT block is 8x8 samples */ +#define DCTSIZE2 64 /* DCTSIZE squared; # of elements in a block */ +#define NUM_QUANT_TBLS 4 /* Quantization tables are numbered 0..3 */ +#define NUM_HUFF_TBLS 4 /* Huffman tables are numbered 0..3 */ +#define NUM_ARITH_TBLS 16 /* Arith-coding tables are numbered 0..15 */ +#define MAX_COMPS_IN_SCAN 4 /* JPEG limit on # of components in one scan */ +#define MAX_SAMP_FACTOR 4 /* JPEG limit on sampling factors */ +/* Unfortunately, some bozo at Adobe saw no reason to be bound by the standard; + * the PostScript DCT filter can emit files with many more than 10 blocks/MCU. + * If you happen to run across such a file, you can up D_MAX_BLOCKS_IN_MCU + * to handle it. We even let you do this from the jconfig.h file. However, + * we strongly discourage changing C_MAX_BLOCKS_IN_MCU; just because Adobe + * sometimes emits noncompliant files doesn't mean you should too. + */ +#define C_MAX_BLOCKS_IN_MCU 10 /* compressor's limit on blocks per MCU */ +#ifndef D_MAX_BLOCKS_IN_MCU +#define D_MAX_BLOCKS_IN_MCU 10 /* decompressor's limit on blocks per MCU */ +#endif + + +/* Data structures for images (arrays of samples and of DCT coefficients). + * On 80x86 machines, the image arrays are too big for near pointers, + * but the pointer arrays can fit in near memory. + */ + +typedef JSAMPLE FAR *JSAMPROW; /* ptr to one image row of pixel samples. */ +typedef JSAMPROW *JSAMPARRAY; /* ptr to some rows (a 2-D sample array) */ +typedef JSAMPARRAY *JSAMPIMAGE; /* a 3-D sample array: top index is color */ + +typedef JCOEF JBLOCK[DCTSIZE2]; /* one block of coefficients */ +typedef JBLOCK FAR *JBLOCKROW; /* pointer to one row of coefficient blocks */ +typedef JBLOCKROW *JBLOCKARRAY; /* a 2-D array of coefficient blocks */ +typedef JBLOCKARRAY *JBLOCKIMAGE; /* a 3-D array of coefficient blocks */ + +typedef JCOEF FAR *JCOEFPTR; /* useful in a couple of places */ + + +/* Types for JPEG compression parameters and working tables. */ + + +/* DCT coefficient quantization tables. */ + +typedef struct { + /* This array gives the coefficient quantizers in natural array order + * (not the zigzag order in which they are stored in a JPEG DQT marker). + * CAUTION: IJG versions prior to v6a kept this array in zigzag order. + */ + UINT16 quantval[DCTSIZE2]; /* quantization step for each coefficient */ + /* This field is used only during compression. It's initialized FALSE when + * the table is created, and set TRUE when it's been output to the file. + * You could suppress output of a table by setting this to TRUE. + * (See jpeg_suppress_tables for an example.) + */ + boolean sent_table; /* TRUE when table has been output */ +} JQUANT_TBL; + + +/* Huffman coding tables. */ + +typedef struct { + /* These two fields directly represent the contents of a JPEG DHT marker */ + UINT8 bits[17]; /* bits[k] = # of symbols with codes of */ + /* length k bits; bits[0] is unused */ + UINT8 huffval[256]; /* The symbols, in order of incr code length */ + /* This field is used only during compression. It's initialized FALSE when + * the table is created, and set TRUE when it's been output to the file. + * You could suppress output of a table by setting this to TRUE. + * (See jpeg_suppress_tables for an example.) + */ + boolean sent_table; /* TRUE when table has been output */ +} JHUFF_TBL; + + +/* Basic info about one component (color channel). */ + +typedef struct { + /* These values are fixed over the whole image. */ + /* For compression, they must be supplied by parameter setup; */ + /* for decompression, they are read from the SOF marker. */ + int component_id; /* identifier for this component (0..255) */ + int component_index; /* its index in SOF or cinfo->comp_info[] */ + int h_samp_factor; /* horizontal sampling factor (1..4) */ + int v_samp_factor; /* vertical sampling factor (1..4) */ + int quant_tbl_no; /* quantization table selector (0..3) */ + /* These values may vary between scans. */ + /* For compression, they must be supplied by parameter setup; */ + /* for decompression, they are read from the SOS marker. */ + /* The decompressor output side may not use these variables. */ + int dc_tbl_no; /* DC entropy table selector (0..3) */ + int ac_tbl_no; /* AC entropy table selector (0..3) */ + + /* Remaining fields should be treated as private by applications. */ + + /* These values are computed during compression or decompression startup: */ + /* Component's size in DCT blocks. + * Any dummy blocks added to complete an MCU are not counted; therefore + * these values do not depend on whether a scan is interleaved or not. + */ + JDIMENSION width_in_blocks; + JDIMENSION height_in_blocks; + /* Size of a DCT block in samples. Always DCTSIZE for compression. + * For decompression this is the size of the output from one DCT block, + * reflecting any scaling we choose to apply during the IDCT step. + * Values of 1,2,4,8 are likely to be supported. Note that different + * components may receive different IDCT scalings. + */ + int DCT_scaled_size; + /* The downsampled dimensions are the component's actual, unpadded number + * of samples at the main buffer (preprocessing/compression interface), thus + * downsampled_width = ceil(image_width * Hi/Hmax) + * and similarly for height. For decompression, IDCT scaling is included, so + * downsampled_width = ceil(image_width * Hi/Hmax * DCT_scaled_size/DCTSIZE) + */ + JDIMENSION downsampled_width; /* actual width in samples */ + JDIMENSION downsampled_height; /* actual height in samples */ + /* This flag is used only for decompression. In cases where some of the + * components will be ignored (eg grayscale output from YCbCr image), + * we can skip most computations for the unused components. + */ + boolean component_needed; /* do we need the value of this component? */ + + /* These values are computed before starting a scan of the component. */ + /* The decompressor output side may not use these variables. */ + int MCU_width; /* number of blocks per MCU, horizontally */ + int MCU_height; /* number of blocks per MCU, vertically */ + int MCU_blocks; /* MCU_width * MCU_height */ + int MCU_sample_width; /* MCU width in samples, MCU_width*DCT_scaled_size */ + int last_col_width; /* # of non-dummy blocks across in last MCU */ + int last_row_height; /* # of non-dummy blocks down in last MCU */ + + /* Saved quantization table for component; NULL if none yet saved. + * See jdinput.c comments about the need for this information. + * This field is currently used only for decompression. + */ + JQUANT_TBL * quant_table; + + /* Private per-component storage for DCT or IDCT subsystem. */ + void * dct_table; +} jpeg_component_info; + + +/* The script for encoding a multiple-scan file is an array of these: */ + +typedef struct { + int comps_in_scan; /* number of components encoded in this scan */ + int component_index[MAX_COMPS_IN_SCAN]; /* their SOF/comp_info[] indexes */ + int Ss, Se; /* progressive JPEG spectral selection parms */ + int Ah, Al; /* progressive JPEG successive approx. parms */ +} jpeg_scan_info; + +/* The decompressor can save APPn and COM markers in a list of these: */ + +typedef struct jpeg_marker_struct FAR * jpeg_saved_marker_ptr; + +struct jpeg_marker_struct { + jpeg_saved_marker_ptr next; /* next in list, or NULL */ + UINT8 marker; /* marker code: JPEG_COM, or JPEG_APP0+n */ + unsigned int original_length; /* # bytes of data in the file */ + unsigned int data_length; /* # bytes of data saved at data[] */ + JOCTET FAR * data; /* the data contained in the marker */ + /* the marker length word is not counted in data_length or original_length */ +}; + +/* Known color spaces. */ + +typedef enum { + JCS_UNKNOWN, /* error/unspecified */ + JCS_GRAYSCALE, /* monochrome */ + JCS_RGB, /* red/green/blue */ + JCS_YCbCr, /* Y/Cb/Cr (also known as YUV) */ + JCS_CMYK, /* C/M/Y/K */ + JCS_YCCK /* Y/Cb/Cr/K */ +} J_COLOR_SPACE; + +/* DCT/IDCT algorithm options. */ + +typedef enum { + JDCT_ISLOW, /* slow but accurate integer algorithm */ + JDCT_IFAST, /* faster, less accurate integer method */ + JDCT_FLOAT /* floating-point: accurate, fast on fast HW */ +} J_DCT_METHOD; + +#ifndef JDCT_DEFAULT /* may be overridden in jconfig.h */ +#define JDCT_DEFAULT JDCT_ISLOW +#endif +#ifndef JDCT_FASTEST /* may be overridden in jconfig.h */ +#define JDCT_FASTEST JDCT_IFAST +#endif + +/* Dithering options for decompression. */ + +typedef enum { + JDITHER_NONE, /* no dithering */ + JDITHER_ORDERED, /* simple ordered dither */ + JDITHER_FS /* Floyd-Steinberg error diffusion dither */ +} J_DITHER_MODE; + + +/* Common fields between JPEG compression and decompression master structs. */ + +#define jpeg_common_fields \ + struct jpeg_error_mgr * err; /* Error handler module */\ + struct jpeg_memory_mgr * mem; /* Memory manager module */\ + struct jpeg_progress_mgr * progress; /* Progress monitor, or NULL if none */\ + void * client_data; /* Available for use by application */\ + boolean is_decompressor; /* So common code can tell which is which */\ + int global_state /* For checking call sequence validity */ + +/* Routines that are to be used by both halves of the library are declared + * to receive a pointer to this structure. There are no actual instances of + * jpeg_common_struct, only of jpeg_compress_struct and jpeg_decompress_struct. + */ +struct jpeg_common_struct { + jpeg_common_fields; /* Fields common to both master struct types */ + /* Additional fields follow in an actual jpeg_compress_struct or + * jpeg_decompress_struct. All three structs must agree on these + * initial fields! (This would be a lot cleaner in C++.) + */ +}; + +typedef struct jpeg_common_struct * j_common_ptr; +typedef struct jpeg_compress_struct * j_compress_ptr; +typedef struct jpeg_decompress_struct * j_decompress_ptr; + + +/* Master record for a compression instance */ + +struct jpeg_compress_struct { + jpeg_common_fields; /* Fields shared with jpeg_decompress_struct */ + + /* Destination for compressed data */ + struct jpeg_destination_mgr * dest; + + /* Description of source image --- these fields must be filled in by + * outer application before starting compression. in_color_space must + * be correct before you can even call jpeg_set_defaults(). + */ + + JDIMENSION image_width; /* input image width */ + JDIMENSION image_height; /* input image height */ + int input_components; /* # of color components in input image */ + J_COLOR_SPACE in_color_space; /* colorspace of input image */ + + double input_gamma; /* image gamma of input image */ + + /* Compression parameters --- these fields must be set before calling + * jpeg_start_compress(). We recommend calling jpeg_set_defaults() to + * initialize everything to reasonable defaults, then changing anything + * the application specifically wants to change. That way you won't get + * burnt when new parameters are added. Also note that there are several + * helper routines to simplify changing parameters. + */ + + int data_precision; /* bits of precision in image data */ + + int num_components; /* # of color components in JPEG image */ + J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ + + jpeg_component_info * comp_info; + /* comp_info[i] describes component that appears i'th in SOF */ + + JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]; + /* ptrs to coefficient quantization tables, or NULL if not defined */ + + JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; + JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; + /* ptrs to Huffman coding tables, or NULL if not defined */ + + UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ + UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ + UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ + + int num_scans; /* # of entries in scan_info array */ + const jpeg_scan_info * scan_info; /* script for multi-scan file, or NULL */ + /* The default value of scan_info is NULL, which causes a single-scan + * sequential JPEG file to be emitted. To create a multi-scan file, + * set num_scans and scan_info to point to an array of scan definitions. + */ + + boolean raw_data_in; /* TRUE=caller supplies downsampled data */ + boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ + boolean optimize_coding; /* TRUE=optimize entropy encoding parms */ + boolean CCIR601_sampling; /* TRUE=first samples are cosited */ + int smoothing_factor; /* 1..100, or 0 for no input smoothing */ + J_DCT_METHOD dct_method; /* DCT algorithm selector */ + + /* The restart interval can be specified in absolute MCUs by setting + * restart_interval, or in MCU rows by setting restart_in_rows + * (in which case the correct restart_interval will be figured + * for each scan). + */ + unsigned int restart_interval; /* MCUs per restart, or 0 for no restart */ + int restart_in_rows; /* if > 0, MCU rows per restart interval */ + + /* Parameters controlling emission of special markers. */ + + boolean write_JFIF_header; /* should a JFIF marker be written? */ + UINT8 JFIF_major_version; /* What to write for the JFIF version number */ + UINT8 JFIF_minor_version; + /* These three values are not used by the JPEG code, merely copied */ + /* into the JFIF APP0 marker. density_unit can be 0 for unknown, */ + /* 1 for dots/inch, or 2 for dots/cm. Note that the pixel aspect */ + /* ratio is defined by X_density/Y_density even when density_unit=0. */ + UINT8 density_unit; /* JFIF code for pixel size units */ + UINT16 X_density; /* Horizontal pixel density */ + UINT16 Y_density; /* Vertical pixel density */ + boolean write_Adobe_marker; /* should an Adobe marker be written? */ + + /* State variable: index of next scanline to be written to + * jpeg_write_scanlines(). Application may use this to control its + * processing loop, e.g., "while (next_scanline < image_height)". + */ + + JDIMENSION next_scanline; /* 0 .. image_height-1 */ + + /* Remaining fields are known throughout compressor, but generally + * should not be touched by a surrounding application. + */ + + /* + * These fields are computed during compression startup + */ + boolean progressive_mode; /* TRUE if scan script uses progressive mode */ + int max_h_samp_factor; /* largest h_samp_factor */ + int max_v_samp_factor; /* largest v_samp_factor */ + + JDIMENSION total_iMCU_rows; /* # of iMCU rows to be input to coef ctlr */ + /* The coefficient controller receives data in units of MCU rows as defined + * for fully interleaved scans (whether the JPEG file is interleaved or not). + * There are v_samp_factor * DCTSIZE sample rows of each component in an + * "iMCU" (interleaved MCU) row. + */ + + /* + * These fields are valid during any one scan. + * They describe the components and MCUs actually appearing in the scan. + */ + int comps_in_scan; /* # of JPEG components in this scan */ + jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; + /* *cur_comp_info[i] describes component that appears i'th in SOS */ + + JDIMENSION MCUs_per_row; /* # of MCUs across the image */ + JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ + + int blocks_in_MCU; /* # of DCT blocks per MCU */ + int MCU_membership[C_MAX_BLOCKS_IN_MCU]; + /* MCU_membership[i] is index in cur_comp_info of component owning */ + /* i'th block in an MCU */ + + int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */ + + /* + * Links to compression subobjects (methods and private variables of modules) + */ + struct jpeg_comp_master * master; + struct jpeg_c_main_controller * main; + struct jpeg_c_prep_controller * prep; + struct jpeg_c_coef_controller * coef; + struct jpeg_marker_writer * marker; + struct jpeg_color_converter * cconvert; + struct jpeg_downsampler * downsample; + struct jpeg_forward_dct * fdct; + struct jpeg_entropy_encoder * entropy; + jpeg_scan_info * script_space; /* workspace for jpeg_simple_progression */ + int script_space_size; +}; + + +/* Master record for a decompression instance */ + +struct jpeg_decompress_struct { + jpeg_common_fields; /* Fields shared with jpeg_compress_struct */ + + /* Source of compressed data */ + struct jpeg_source_mgr * src; + + /* Basic description of image --- filled in by jpeg_read_header(). */ + /* Application may inspect these values to decide how to process image. */ + + JDIMENSION image_width; /* nominal image width (from SOF marker) */ + JDIMENSION image_height; /* nominal image height */ + int num_components; /* # of color components in JPEG image */ + J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ + + /* Decompression processing parameters --- these fields must be set before + * calling jpeg_start_decompress(). Note that jpeg_read_header() initializes + * them to default values. + */ + + J_COLOR_SPACE out_color_space; /* colorspace for output */ + + unsigned int scale_num, scale_denom; /* fraction by which to scale image */ + + double output_gamma; /* image gamma wanted in output */ + + boolean buffered_image; /* TRUE=multiple output passes */ + boolean raw_data_out; /* TRUE=downsampled data wanted */ + + J_DCT_METHOD dct_method; /* IDCT algorithm selector */ + boolean do_fancy_upsampling; /* TRUE=apply fancy upsampling */ + boolean do_block_smoothing; /* TRUE=apply interblock smoothing */ + + boolean quantize_colors; /* TRUE=colormapped output wanted */ + /* the following are ignored if not quantize_colors: */ + J_DITHER_MODE dither_mode; /* type of color dithering to use */ + boolean two_pass_quantize; /* TRUE=use two-pass color quantization */ + int desired_number_of_colors; /* max # colors to use in created colormap */ + /* these are significant only in buffered-image mode: */ + boolean enable_1pass_quant; /* enable future use of 1-pass quantizer */ + boolean enable_external_quant;/* enable future use of external colormap */ + boolean enable_2pass_quant; /* enable future use of 2-pass quantizer */ + + /* Description of actual output image that will be returned to application. + * These fields are computed by jpeg_start_decompress(). + * You can also use jpeg_calc_output_dimensions() to determine these values + * in advance of calling jpeg_start_decompress(). + */ + + JDIMENSION output_width; /* scaled image width */ + JDIMENSION output_height; /* scaled image height */ + int out_color_components; /* # of color components in out_color_space */ + int output_components; /* # of color components returned */ + /* output_components is 1 (a colormap index) when quantizing colors; + * otherwise it equals out_color_components. + */ + int rec_outbuf_height; /* min recommended height of scanline buffer */ + /* If the buffer passed to jpeg_read_scanlines() is less than this many rows + * high, space and time will be wasted due to unnecessary data copying. + * Usually rec_outbuf_height will be 1 or 2, at most 4. + */ + + /* When quantizing colors, the output colormap is described by these fields. + * The application can supply a colormap by setting colormap non-NULL before + * calling jpeg_start_decompress; otherwise a colormap is created during + * jpeg_start_decompress or jpeg_start_output. + * The map has out_color_components rows and actual_number_of_colors columns. + */ + int actual_number_of_colors; /* number of entries in use */ + JSAMPARRAY colormap; /* The color map as a 2-D pixel array */ + + /* State variables: these variables indicate the progress of decompression. + * The application may examine these but must not modify them. + */ + + /* Row index of next scanline to be read from jpeg_read_scanlines(). + * Application may use this to control its processing loop, e.g., + * "while (output_scanline < output_height)". + */ + JDIMENSION output_scanline; /* 0 .. output_height-1 */ + + /* Current input scan number and number of iMCU rows completed in scan. + * These indicate the progress of the decompressor input side. + */ + int input_scan_number; /* Number of SOS markers seen so far */ + JDIMENSION input_iMCU_row; /* Number of iMCU rows completed */ + + /* The "output scan number" is the notional scan being displayed by the + * output side. The decompressor will not allow output scan/row number + * to get ahead of input scan/row, but it can fall arbitrarily far behind. + */ + int output_scan_number; /* Nominal scan number being displayed */ + JDIMENSION output_iMCU_row; /* Number of iMCU rows read */ + + /* Current progression status. coef_bits[c][i] indicates the precision + * with which component c's DCT coefficient i (in zigzag order) is known. + * It is -1 when no data has yet been received, otherwise it is the point + * transform (shift) value for the most recent scan of the coefficient + * (thus, 0 at completion of the progression). + * This pointer is NULL when reading a non-progressive file. + */ + int (*coef_bits)[DCTSIZE2]; /* -1 or current Al value for each coef */ + + /* Internal JPEG parameters --- the application usually need not look at + * these fields. Note that the decompressor output side may not use + * any parameters that can change between scans. + */ + + /* Quantization and Huffman tables are carried forward across input + * datastreams when processing abbreviated JPEG datastreams. + */ + + JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]; + /* ptrs to coefficient quantization tables, or NULL if not defined */ + + JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; + JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; + /* ptrs to Huffman coding tables, or NULL if not defined */ + + /* These parameters are never carried across datastreams, since they + * are given in SOF/SOS markers or defined to be reset by SOI. + */ + + int data_precision; /* bits of precision in image data */ + + jpeg_component_info * comp_info; + /* comp_info[i] describes component that appears i'th in SOF */ + + boolean progressive_mode; /* TRUE if SOFn specifies progressive mode */ + boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ + + UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ + UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ + UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ + + unsigned int restart_interval; /* MCUs per restart interval, or 0 for no restart */ + + /* These fields record data obtained from optional markers recognized by + * the JPEG library. + */ + boolean saw_JFIF_marker; /* TRUE iff a JFIF APP0 marker was found */ + /* Data copied from JFIF marker; only valid if saw_JFIF_marker is TRUE: */ + UINT8 JFIF_major_version; /* JFIF version number */ + UINT8 JFIF_minor_version; + UINT8 density_unit; /* JFIF code for pixel size units */ + UINT16 X_density; /* Horizontal pixel density */ + UINT16 Y_density; /* Vertical pixel density */ + boolean saw_Adobe_marker; /* TRUE iff an Adobe APP14 marker was found */ + UINT8 Adobe_transform; /* Color transform code from Adobe marker */ + + boolean CCIR601_sampling; /* TRUE=first samples are cosited */ + + /* Aside from the specific data retained from APPn markers known to the + * library, the uninterpreted contents of any or all APPn and COM markers + * can be saved in a list for examination by the application. + */ + jpeg_saved_marker_ptr marker_list; /* Head of list of saved markers */ + + /* Remaining fields are known throughout decompressor, but generally + * should not be touched by a surrounding application. + */ + + /* + * These fields are computed during decompression startup + */ + int max_h_samp_factor; /* largest h_samp_factor */ + int max_v_samp_factor; /* largest v_samp_factor */ + + int min_DCT_scaled_size; /* smallest DCT_scaled_size of any component */ + + JDIMENSION total_iMCU_rows; /* # of iMCU rows in image */ + /* The coefficient controller's input and output progress is measured in + * units of "iMCU" (interleaved MCU) rows. These are the same as MCU rows + * in fully interleaved JPEG scans, but are used whether the scan is + * interleaved or not. We define an iMCU row as v_samp_factor DCT block + * rows of each component. Therefore, the IDCT output contains + * v_samp_factor*DCT_scaled_size sample rows of a component per iMCU row. + */ + + JSAMPLE * sample_range_limit; /* table for fast range-limiting */ + + /* + * These fields are valid during any one scan. + * They describe the components and MCUs actually appearing in the scan. + * Note that the decompressor output side must not use these fields. + */ + int comps_in_scan; /* # of JPEG components in this scan */ + jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; + /* *cur_comp_info[i] describes component that appears i'th in SOS */ + + JDIMENSION MCUs_per_row; /* # of MCUs across the image */ + JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ + + int blocks_in_MCU; /* # of DCT blocks per MCU */ + int MCU_membership[D_MAX_BLOCKS_IN_MCU]; + /* MCU_membership[i] is index in cur_comp_info of component owning */ + /* i'th block in an MCU */ + + int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */ + + /* This field is shared between entropy decoder and marker parser. + * It is either zero or the code of a JPEG marker that has been + * read from the data source, but has not yet been processed. + */ + int unread_marker; + + /* + * Links to decompression subobjects (methods, private variables of modules) + */ + struct jpeg_decomp_master * master; + struct jpeg_d_main_controller * main; + struct jpeg_d_coef_controller * coef; + struct jpeg_d_post_controller * post; + struct jpeg_input_controller * inputctl; + struct jpeg_marker_reader * marker; + struct jpeg_entropy_decoder * entropy; + struct jpeg_inverse_dct * idct; + struct jpeg_upsampler * upsample; + struct jpeg_color_deconverter * cconvert; + struct jpeg_color_quantizer * cquantize; +}; + + +/* "Object" declarations for JPEG modules that may be supplied or called + * directly by the surrounding application. + * As with all objects in the JPEG library, these structs only define the + * publicly visible methods and state variables of a module. Additional + * private fields may exist after the public ones. + */ + + +/* Error handler object */ + +struct jpeg_error_mgr { + /* Error exit handler: does not return to caller */ + JMETHOD(void, error_exit, (j_common_ptr cinfo)); + /* Conditionally emit a trace or warning message */ + JMETHOD(void, emit_message, (j_common_ptr cinfo, int msg_level)); + /* Routine that actually outputs a trace or error message */ + JMETHOD(void, output_message, (j_common_ptr cinfo)); + /* Format a message string for the most recent JPEG error or message */ + JMETHOD(void, format_message, (j_common_ptr cinfo, char * buffer)); +#define JMSG_LENGTH_MAX 200 /* recommended size of format_message buffer */ + /* Reset error state variables at start of a new image */ + JMETHOD(void, reset_error_mgr, (j_common_ptr cinfo)); + + /* The message ID code and any parameters are saved here. + * A message can have one string parameter or up to 8 int parameters. + */ + int msg_code; +#define JMSG_STR_PARM_MAX 80 + union { + int i[8]; + char s[JMSG_STR_PARM_MAX]; + } msg_parm; + + /* Standard state variables for error facility */ + + int trace_level; /* max msg_level that will be displayed */ + + /* For recoverable corrupt-data errors, we emit a warning message, + * but keep going unless emit_message chooses to abort. emit_message + * should count warnings in num_warnings. The surrounding application + * can check for bad data by seeing if num_warnings is nonzero at the + * end of processing. + */ + long num_warnings; /* number of corrupt-data warnings */ + + /* These fields point to the table(s) of error message strings. + * An application can change the table pointer to switch to a different + * message list (typically, to change the language in which errors are + * reported). Some applications may wish to add additional error codes + * that will be handled by the JPEG library error mechanism; the second + * table pointer is used for this purpose. + * + * First table includes all errors generated by JPEG library itself. + * Error code 0 is reserved for a "no such error string" message. + */ + const char * const * jpeg_message_table; /* Library errors */ + int last_jpeg_message; /* Table contains strings 0..last_jpeg_message */ + /* Second table can be added by application (see cjpeg/djpeg for example). + * It contains strings numbered first_addon_message..last_addon_message. + */ + const char * const * addon_message_table; /* Non-library errors */ + int first_addon_message; /* code for first string in addon table */ + int last_addon_message; /* code for last string in addon table */ +}; + + +/* Progress monitor object */ + +struct jpeg_progress_mgr { + JMETHOD(void, progress_monitor, (j_common_ptr cinfo)); + + long pass_counter; /* work units completed in this pass */ + long pass_limit; /* total number of work units in this pass */ + int completed_passes; /* passes completed so far */ + int total_passes; /* total number of passes expected */ +}; + + +/* Data destination object for compression */ + +struct jpeg_destination_mgr { + JOCTET * next_output_byte; /* => next byte to write in buffer */ + size_t free_in_buffer; /* # of byte spaces remaining in buffer */ + + JMETHOD(void, init_destination, (j_compress_ptr cinfo)); + JMETHOD(boolean, empty_output_buffer, (j_compress_ptr cinfo)); + JMETHOD(void, term_destination, (j_compress_ptr cinfo)); +}; + + +/* Data source object for decompression */ + +struct jpeg_source_mgr { + const JOCTET * next_input_byte; /* => next byte to read from buffer */ + size_t bytes_in_buffer; /* # of bytes remaining in buffer */ + + JMETHOD(void, init_source, (j_decompress_ptr cinfo)); + JMETHOD(boolean, fill_input_buffer, (j_decompress_ptr cinfo)); + JMETHOD(void, skip_input_data, (j_decompress_ptr cinfo, long num_bytes)); + JMETHOD(boolean, resync_to_restart, (j_decompress_ptr cinfo, int desired)); + JMETHOD(void, term_source, (j_decompress_ptr cinfo)); +}; + + +/* Memory manager object. + * Allocates "small" objects (a few K total), "large" objects (tens of K), + * and "really big" objects (virtual arrays with backing store if needed). + * The memory manager does not allow individual objects to be freed; rather, + * each created object is assigned to a pool, and whole pools can be freed + * at once. This is faster and more convenient than remembering exactly what + * to free, especially where malloc()/free() are not too speedy. + * NB: alloc routines never return NULL. They exit to error_exit if not + * successful. + */ + +#define JPOOL_PERMANENT 0 /* lasts until master record is destroyed */ +#define JPOOL_IMAGE 1 /* lasts until done with image/datastream */ +#define JPOOL_NUMPOOLS 2 + +typedef struct jvirt_sarray_control * jvirt_sarray_ptr; +typedef struct jvirt_barray_control * jvirt_barray_ptr; + + +struct jpeg_memory_mgr { + /* Method pointers */ + JMETHOD(void *, alloc_small, (j_common_ptr cinfo, int pool_id, + size_t sizeofobject)); + JMETHOD(void FAR *, alloc_large, (j_common_ptr cinfo, int pool_id, + size_t sizeofobject)); + JMETHOD(JSAMPARRAY, alloc_sarray, (j_common_ptr cinfo, int pool_id, + JDIMENSION samplesperrow, + JDIMENSION numrows)); + JMETHOD(JBLOCKARRAY, alloc_barray, (j_common_ptr cinfo, int pool_id, + JDIMENSION blocksperrow, + JDIMENSION numrows)); + JMETHOD(jvirt_sarray_ptr, request_virt_sarray, (j_common_ptr cinfo, + int pool_id, + boolean pre_zero, + JDIMENSION samplesperrow, + JDIMENSION numrows, + JDIMENSION maxaccess)); + JMETHOD(jvirt_barray_ptr, request_virt_barray, (j_common_ptr cinfo, + int pool_id, + boolean pre_zero, + JDIMENSION blocksperrow, + JDIMENSION numrows, + JDIMENSION maxaccess)); + JMETHOD(void, realize_virt_arrays, (j_common_ptr cinfo)); + JMETHOD(JSAMPARRAY, access_virt_sarray, (j_common_ptr cinfo, + jvirt_sarray_ptr ptr, + JDIMENSION start_row, + JDIMENSION num_rows, + boolean writable)); + JMETHOD(JBLOCKARRAY, access_virt_barray, (j_common_ptr cinfo, + jvirt_barray_ptr ptr, + JDIMENSION start_row, + JDIMENSION num_rows, + boolean writable)); + JMETHOD(void, free_pool, (j_common_ptr cinfo, int pool_id)); + JMETHOD(void, self_destruct, (j_common_ptr cinfo)); + + /* Limit on memory allocation for this JPEG object. (Note that this is + * merely advisory, not a guaranteed maximum; it only affects the space + * used for virtual-array buffers.) May be changed by outer application + * after creating the JPEG object. + */ + long max_memory_to_use; + + /* Maximum allocation request accepted by alloc_large. */ + long max_alloc_chunk; +}; + + +/* Routine signature for application-supplied marker processing methods. + * Need not pass marker code since it is stored in cinfo->unread_marker. + */ +typedef JMETHOD(boolean, jpeg_marker_parser_method, (j_decompress_ptr cinfo)); + + +/* Declarations for routines called by application. + * The JPP macro hides prototype parameters from compilers that can't cope. + * Note JPP requires double parentheses. + */ + +#ifdef HAVE_PROTOTYPES +#define JPP(arglist) arglist +#else +#define JPP(arglist) () +#endif + + +/* Short forms of external names for systems with brain-damaged linkers. + * We shorten external names to be unique in the first six letters, which + * is good enough for all known systems. + * (If your compiler itself needs names to be unique in less than 15 + * characters, you are out of luck. Get a better compiler.) + */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jpeg_std_error jStdError +#define jpeg_CreateCompress jCreaCompress +#define jpeg_CreateDecompress jCreaDecompress +#define jpeg_destroy_compress jDestCompress +#define jpeg_destroy_decompress jDestDecompress +#define jpeg_stdio_dest jStdDest +#define jpeg_stdio_src jStdSrc +#define jpeg_set_defaults jSetDefaults +#define jpeg_set_colorspace jSetColorspace +#define jpeg_default_colorspace jDefColorspace +#define jpeg_set_quality jSetQuality +#define jpeg_set_linear_quality jSetLQuality +#define jpeg_add_quant_table jAddQuantTable +#define jpeg_quality_scaling jQualityScaling +#define jpeg_simple_progression jSimProgress +#define jpeg_suppress_tables jSuppressTables +#define jpeg_alloc_quant_table jAlcQTable +#define jpeg_alloc_huff_table jAlcHTable +#define jpeg_start_compress jStrtCompress +#define jpeg_write_scanlines jWrtScanlines +#define jpeg_finish_compress jFinCompress +#define jpeg_write_raw_data jWrtRawData +#define jpeg_write_marker jWrtMarker +#define jpeg_write_m_header jWrtMHeader +#define jpeg_write_m_byte jWrtMByte +#define jpeg_write_tables jWrtTables +#define jpeg_read_header jReadHeader +#define jpeg_start_decompress jStrtDecompress +#define jpeg_read_scanlines jReadScanlines +#define jpeg_finish_decompress jFinDecompress +#define jpeg_read_raw_data jReadRawData +#define jpeg_has_multiple_scans jHasMultScn +#define jpeg_start_output jStrtOutput +#define jpeg_finish_output jFinOutput +#define jpeg_input_complete jInComplete +#define jpeg_new_colormap jNewCMap +#define jpeg_consume_input jConsumeInput +#define jpeg_calc_output_dimensions jCalcDimensions +#define jpeg_save_markers jSaveMarkers +#define jpeg_set_marker_processor jSetMarker +#define jpeg_read_coefficients jReadCoefs +#define jpeg_write_coefficients jWrtCoefs +#define jpeg_copy_critical_parameters jCopyCrit +#define jpeg_abort_compress jAbrtCompress +#define jpeg_abort_decompress jAbrtDecompress +#define jpeg_abort jAbort +#define jpeg_destroy jDestroy +#define jpeg_resync_to_restart jResyncRestart +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + + +/* Default error-management setup */ +EXTERN(struct jpeg_error_mgr *) jpeg_std_error + JPP((struct jpeg_error_mgr * err)); + +/* Initialization of JPEG compression objects. + * jpeg_create_compress() and jpeg_create_decompress() are the exported + * names that applications should call. These expand to calls on + * jpeg_CreateCompress and jpeg_CreateDecompress with additional information + * passed for version mismatch checking. + * NB: you must set up the error-manager BEFORE calling jpeg_create_xxx. + */ +#define jpeg_create_compress(cinfo) \ + jpeg_CreateCompress((cinfo), JPEG_LIB_VERSION, \ + (size_t) sizeof(struct jpeg_compress_struct)) +#define jpeg_create_decompress(cinfo) \ + jpeg_CreateDecompress((cinfo), JPEG_LIB_VERSION, \ + (size_t) sizeof(struct jpeg_decompress_struct)) +EXTERN(void) jpeg_CreateCompress JPP((j_compress_ptr cinfo, + int version, size_t structsize)); +EXTERN(void) jpeg_CreateDecompress JPP((j_decompress_ptr cinfo, + int version, size_t structsize)); +/* Destruction of JPEG compression objects */ +EXTERN(void) jpeg_destroy_compress JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_destroy_decompress JPP((j_decompress_ptr cinfo)); + +/* Standard data source and destination managers: stdio streams. */ +/* Caller is responsible for opening the file before and closing after. */ +EXTERN(void) jpeg_stdio_dest JPP((j_compress_ptr cinfo, FILE * outfile)); +EXTERN(void) jpeg_stdio_src JPP((j_decompress_ptr cinfo, FILE * infile)); + +/* Default parameter setup for compression */ +EXTERN(void) jpeg_set_defaults JPP((j_compress_ptr cinfo)); +/* Compression parameter setup aids */ +EXTERN(void) jpeg_set_colorspace JPP((j_compress_ptr cinfo, + J_COLOR_SPACE colorspace)); +EXTERN(void) jpeg_default_colorspace JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_set_quality JPP((j_compress_ptr cinfo, int quality, + boolean force_baseline)); +EXTERN(void) jpeg_set_linear_quality JPP((j_compress_ptr cinfo, + int scale_factor, + boolean force_baseline)); +EXTERN(void) jpeg_add_quant_table JPP((j_compress_ptr cinfo, int which_tbl, + const unsigned int *basic_table, + int scale_factor, + boolean force_baseline)); +EXTERN(int) jpeg_quality_scaling JPP((int quality)); +EXTERN(void) jpeg_simple_progression JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_suppress_tables JPP((j_compress_ptr cinfo, + boolean suppress)); +EXTERN(JQUANT_TBL *) jpeg_alloc_quant_table JPP((j_common_ptr cinfo)); +EXTERN(JHUFF_TBL *) jpeg_alloc_huff_table JPP((j_common_ptr cinfo)); + +/* Main entry points for compression */ +EXTERN(void) jpeg_start_compress JPP((j_compress_ptr cinfo, + boolean write_all_tables)); +EXTERN(JDIMENSION) jpeg_write_scanlines JPP((j_compress_ptr cinfo, + JSAMPARRAY scanlines, + JDIMENSION num_lines)); +EXTERN(void) jpeg_finish_compress JPP((j_compress_ptr cinfo)); + +/* Replaces jpeg_write_scanlines when writing raw downsampled data. */ +EXTERN(JDIMENSION) jpeg_write_raw_data JPP((j_compress_ptr cinfo, + JSAMPIMAGE data, + JDIMENSION num_lines)); + +/* Write a special marker. See libjpeg.doc concerning safe usage. */ +EXTERN(void) jpeg_write_marker + JPP((j_compress_ptr cinfo, int marker, + const JOCTET * dataptr, unsigned int datalen)); +/* Same, but piecemeal. */ +EXTERN(void) jpeg_write_m_header + JPP((j_compress_ptr cinfo, int marker, unsigned int datalen)); +EXTERN(void) jpeg_write_m_byte + JPP((j_compress_ptr cinfo, int val)); + +/* Alternate compression function: just write an abbreviated table file */ +EXTERN(void) jpeg_write_tables JPP((j_compress_ptr cinfo)); + +/* Decompression startup: read start of JPEG datastream to see what's there */ +EXTERN(int) jpeg_read_header JPP((j_decompress_ptr cinfo, + boolean require_image)); +/* Return value is one of: */ +#define JPEG_SUSPENDED 0 /* Suspended due to lack of input data */ +#define JPEG_HEADER_OK 1 /* Found valid image datastream */ +#define JPEG_HEADER_TABLES_ONLY 2 /* Found valid table-specs-only datastream */ +/* If you pass require_image = TRUE (normal case), you need not check for + * a TABLES_ONLY return code; an abbreviated file will cause an error exit. + * JPEG_SUSPENDED is only possible if you use a data source module that can + * give a suspension return (the stdio source module doesn't). + */ + +/* Main entry points for decompression */ +EXTERN(boolean) jpeg_start_decompress JPP((j_decompress_ptr cinfo)); +EXTERN(JDIMENSION) jpeg_read_scanlines JPP((j_decompress_ptr cinfo, + JSAMPARRAY scanlines, + JDIMENSION max_lines)); +EXTERN(boolean) jpeg_finish_decompress JPP((j_decompress_ptr cinfo)); + +/* Replaces jpeg_read_scanlines when reading raw downsampled data. */ +EXTERN(JDIMENSION) jpeg_read_raw_data JPP((j_decompress_ptr cinfo, + JSAMPIMAGE data, + JDIMENSION max_lines)); + +/* Additional entry points for buffered-image mode. */ +EXTERN(boolean) jpeg_has_multiple_scans JPP((j_decompress_ptr cinfo)); +EXTERN(boolean) jpeg_start_output JPP((j_decompress_ptr cinfo, + int scan_number)); +EXTERN(boolean) jpeg_finish_output JPP((j_decompress_ptr cinfo)); +EXTERN(boolean) jpeg_input_complete JPP((j_decompress_ptr cinfo)); +EXTERN(void) jpeg_new_colormap JPP((j_decompress_ptr cinfo)); +EXTERN(int) jpeg_consume_input JPP((j_decompress_ptr cinfo)); +/* Return value is one of: */ +/* #define JPEG_SUSPENDED 0 Suspended due to lack of input data */ +#define JPEG_REACHED_SOS 1 /* Reached start of new scan */ +#define JPEG_REACHED_EOI 2 /* Reached end of image */ +#define JPEG_ROW_COMPLETED 3 /* Completed one iMCU row */ +#define JPEG_SCAN_COMPLETED 4 /* Completed last iMCU row of a scan */ + +/* Precalculate output dimensions for current decompression parameters. */ +EXTERN(void) jpeg_calc_output_dimensions JPP((j_decompress_ptr cinfo)); + +/* Control saving of COM and APPn markers into marker_list. */ +EXTERN(void) jpeg_save_markers + JPP((j_decompress_ptr cinfo, int marker_code, + unsigned int length_limit)); + +/* Install a special processing method for COM or APPn markers. */ +EXTERN(void) jpeg_set_marker_processor + JPP((j_decompress_ptr cinfo, int marker_code, + jpeg_marker_parser_method routine)); + +/* Read or write raw DCT coefficients --- useful for lossless transcoding. */ +EXTERN(jvirt_barray_ptr *) jpeg_read_coefficients JPP((j_decompress_ptr cinfo)); +EXTERN(void) jpeg_write_coefficients JPP((j_compress_ptr cinfo, + jvirt_barray_ptr * coef_arrays)); +EXTERN(void) jpeg_copy_critical_parameters JPP((j_decompress_ptr srcinfo, + j_compress_ptr dstinfo)); + +/* If you choose to abort compression or decompression before completing + * jpeg_finish_(de)compress, then you need to clean up to release memory, + * temporary files, etc. You can just call jpeg_destroy_(de)compress + * if you're done with the JPEG object, but if you want to clean it up and + * reuse it, call this: + */ +EXTERN(void) jpeg_abort_compress JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_abort_decompress JPP((j_decompress_ptr cinfo)); + +/* Generic versions of jpeg_abort and jpeg_destroy that work on either + * flavor of JPEG object. These may be more convenient in some places. + */ +EXTERN(void) jpeg_abort JPP((j_common_ptr cinfo)); +EXTERN(void) jpeg_destroy JPP((j_common_ptr cinfo)); + +/* Default restart-marker-resync procedure for use by data source modules */ +EXTERN(boolean) jpeg_resync_to_restart JPP((j_decompress_ptr cinfo, + int desired)); + + +/* These marker codes are exported since applications and data source modules + * are likely to want to use them. + */ + +#define JPEG_RST0 0xD0 /* RST0 marker code */ +#define JPEG_EOI 0xD9 /* EOI marker code */ +#define JPEG_APP0 0xE0 /* APP0 marker code */ +#define JPEG_COM 0xFE /* COM marker code */ + + +/* If we have a brain-damaged compiler that emits warnings (or worse, errors) + * for structure definitions that are never filled in, keep it quiet by + * supplying dummy definitions for the various substructures. + */ + +#ifdef INCOMPLETE_TYPES_BROKEN +#ifndef JPEG_INTERNALS /* will be defined in jpegint.h */ +struct jvirt_sarray_control { long dummy; }; +struct jvirt_barray_control { long dummy; }; +struct jpeg_comp_master { long dummy; }; +struct jpeg_c_main_controller { long dummy; }; +struct jpeg_c_prep_controller { long dummy; }; +struct jpeg_c_coef_controller { long dummy; }; +struct jpeg_marker_writer { long dummy; }; +struct jpeg_color_converter { long dummy; }; +struct jpeg_downsampler { long dummy; }; +struct jpeg_forward_dct { long dummy; }; +struct jpeg_entropy_encoder { long dummy; }; +struct jpeg_decomp_master { long dummy; }; +struct jpeg_d_main_controller { long dummy; }; +struct jpeg_d_coef_controller { long dummy; }; +struct jpeg_d_post_controller { long dummy; }; +struct jpeg_input_controller { long dummy; }; +struct jpeg_marker_reader { long dummy; }; +struct jpeg_entropy_decoder { long dummy; }; +struct jpeg_inverse_dct { long dummy; }; +struct jpeg_upsampler { long dummy; }; +struct jpeg_color_deconverter { long dummy; }; +struct jpeg_color_quantizer { long dummy; }; +#endif /* JPEG_INTERNALS */ +#endif /* INCOMPLETE_TYPES_BROKEN */ + + +/* + * The JPEG library modules define JPEG_INTERNALS before including this file. + * The internal structure declarations are read only when that is true. + * Applications using the library should not include jpegint.h, but may wish + * to include jerror.h. + */ + +#ifdef JPEG_INTERNALS +#include "jpegint.h" /* fetch private declarations */ +#include "jerror.h" /* fetch error codes too */ +#endif + +#endif /* JPEGLIB_H */ diff --git a/jpeg/JQUANT1.C b/jpeg/JQUANT1.C new file mode 100644 index 0000000..dbf6c34 --- /dev/null +++ b/jpeg/JQUANT1.C @@ -0,0 +1,856 @@ +/* + * jquant1.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains 1-pass color quantization (color mapping) routines. + * These routines provide mapping to a fixed color map using equally spaced + * color values. Optional Floyd-Steinberg or ordered dithering is available. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + +#ifdef QUANT_1PASS_SUPPORTED + + +/* + * The main purpose of 1-pass quantization is to provide a fast, if not very + * high quality, colormapped output capability. A 2-pass quantizer usually + * gives better visual quality; however, for quantized grayscale output this + * quantizer is perfectly adequate. Dithering is highly recommended with this + * quantizer, though you can turn it off if you really want to. + * + * In 1-pass quantization the colormap must be chosen in advance of seeing the + * image. We use a map consisting of all combinations of Ncolors[i] color + * values for the i'th component. The Ncolors[] values are chosen so that + * their product, the total number of colors, is no more than that requested. + * (In most cases, the product will be somewhat less.) + * + * Since the colormap is orthogonal, the representative value for each color + * component can be determined without considering the other components; + * then these indexes can be combined into a colormap index by a standard + * N-dimensional-array-subscript calculation. Most of the arithmetic involved + * can be precalculated and stored in the lookup table colorindex[]. + * colorindex[i][j] maps pixel value j in component i to the nearest + * representative value (grid plane) for that component; this index is + * multiplied by the array stride for component i, so that the + * index of the colormap entry closest to a given pixel value is just + * sum( colorindex[component-number][pixel-component-value] ) + * Aside from being fast, this scheme allows for variable spacing between + * representative values with no additional lookup cost. + * + * If gamma correction has been applied in color conversion, it might be wise + * to adjust the color grid spacing so that the representative colors are + * equidistant in linear space. At this writing, gamma correction is not + * implemented by jdcolor, so nothing is done here. + */ + + +/* Declarations for ordered dithering. + * + * We use a standard 16x16 ordered dither array. The basic concept of ordered + * dithering is described in many references, for instance Dale Schumacher's + * chapter II.2 of Graphics Gems II (James Arvo, ed. Academic Press, 1991). + * In place of Schumacher's comparisons against a "threshold" value, we add a + * "dither" value to the input pixel and then round the result to the nearest + * output value. The dither value is equivalent to (0.5 - threshold) times + * the distance between output values. For ordered dithering, we assume that + * the output colors are equally spaced; if not, results will probably be + * worse, since the dither may be too much or too little at a given point. + * + * The normal calculation would be to form pixel value + dither, range-limit + * this to 0..MAXJSAMPLE, and then index into the colorindex table as usual. + * We can skip the separate range-limiting step by extending the colorindex + * table in both directions. + */ + +#define ODITHER_SIZE 16 /* dimension of dither matrix */ +/* NB: if ODITHER_SIZE is not a power of 2, ODITHER_MASK uses will break */ +#define ODITHER_CELLS (ODITHER_SIZE*ODITHER_SIZE) /* # cells in matrix */ +#define ODITHER_MASK (ODITHER_SIZE-1) /* mask for wrapping around counters */ + +typedef int ODITHER_MATRIX[ODITHER_SIZE][ODITHER_SIZE]; +typedef int (*ODITHER_MATRIX_PTR)[ODITHER_SIZE]; + +static const UINT8 base_dither_matrix[ODITHER_SIZE][ODITHER_SIZE] = { + /* Bayer's order-4 dither array. Generated by the code given in + * Stephen Hawley's article "Ordered Dithering" in Graphics Gems I. + * The values in this array must range from 0 to ODITHER_CELLS-1. + */ + { 0,192, 48,240, 12,204, 60,252, 3,195, 51,243, 15,207, 63,255 }, + { 128, 64,176,112,140, 76,188,124,131, 67,179,115,143, 79,191,127 }, + { 32,224, 16,208, 44,236, 28,220, 35,227, 19,211, 47,239, 31,223 }, + { 160, 96,144, 80,172,108,156, 92,163, 99,147, 83,175,111,159, 95 }, + { 8,200, 56,248, 4,196, 52,244, 11,203, 59,251, 7,199, 55,247 }, + { 136, 72,184,120,132, 68,180,116,139, 75,187,123,135, 71,183,119 }, + { 40,232, 24,216, 36,228, 20,212, 43,235, 27,219, 39,231, 23,215 }, + { 168,104,152, 88,164,100,148, 84,171,107,155, 91,167,103,151, 87 }, + { 2,194, 50,242, 14,206, 62,254, 1,193, 49,241, 13,205, 61,253 }, + { 130, 66,178,114,142, 78,190,126,129, 65,177,113,141, 77,189,125 }, + { 34,226, 18,210, 46,238, 30,222, 33,225, 17,209, 45,237, 29,221 }, + { 162, 98,146, 82,174,110,158, 94,161, 97,145, 81,173,109,157, 93 }, + { 10,202, 58,250, 6,198, 54,246, 9,201, 57,249, 5,197, 53,245 }, + { 138, 74,186,122,134, 70,182,118,137, 73,185,121,133, 69,181,117 }, + { 42,234, 26,218, 38,230, 22,214, 41,233, 25,217, 37,229, 21,213 }, + { 170,106,154, 90,166,102,150, 86,169,105,153, 89,165,101,149, 85 } +}; + + +/* Declarations for Floyd-Steinberg dithering. + * + * Errors are accumulated into the array fserrors[], at a resolution of + * 1/16th of a pixel count. The error at a given pixel is propagated + * to its not-yet-processed neighbors using the standard F-S fractions, + * ... (here) 7/16 + * 3/16 5/16 1/16 + * We work left-to-right on even rows, right-to-left on odd rows. + * + * We can get away with a single array (holding one row's worth of errors) + * by using it to store the current row's errors at pixel columns not yet + * processed, but the next row's errors at columns already processed. We + * need only a few extra variables to hold the errors immediately around the + * current column. (If we are lucky, those variables are in registers, but + * even if not, they're probably cheaper to access than array elements are.) + * + * The fserrors[] array is indexed [component#][position]. + * We provide (#columns + 2) entries per component; the extra entry at each + * end saves us from special-casing the first and last pixels. + * + * Note: on a wide image, we might not have enough room in a PC's near data + * segment to hold the error array; so it is allocated with alloc_large. + */ + +#if BITS_IN_JSAMPLE == 8 +typedef INT16 FSERROR; /* 16 bits should be enough */ +typedef int LOCFSERROR; /* use 'int' for calculation temps */ +#else +typedef INT32 FSERROR; /* may need more than 16 bits */ +typedef INT32 LOCFSERROR; /* be sure calculation temps are big enough */ +#endif + +typedef FSERROR FAR *FSERRPTR; /* pointer to error array (in FAR storage!) */ + + +/* Private subobject */ + +#define MAX_Q_COMPS 4 /* max components I can handle */ + +typedef struct { + struct jpeg_color_quantizer pub; /* public fields */ + + /* Initially allocated colormap is saved here */ + JSAMPARRAY sv_colormap; /* The color map as a 2-D pixel array */ + int sv_actual; /* number of entries in use */ + + JSAMPARRAY colorindex; /* Precomputed mapping for speed */ + /* colorindex[i][j] = index of color closest to pixel value j in component i, + * premultiplied as described above. Since colormap indexes must fit into + * JSAMPLEs, the entries of this array will too. + */ + boolean is_padded; /* is the colorindex padded for odither? */ + + int Ncolors[MAX_Q_COMPS]; /* # of values alloced to each component */ + + /* Variables for ordered dithering */ + int row_index; /* cur row's vertical index in dither matrix */ + ODITHER_MATRIX_PTR odither[MAX_Q_COMPS]; /* one dither array per component */ + + /* Variables for Floyd-Steinberg dithering */ + FSERRPTR fserrors[MAX_Q_COMPS]; /* accumulated errors */ + boolean on_odd_row; /* flag to remember which row we are on */ +} my_cquantizer; + +typedef my_cquantizer * my_cquantize_ptr; + + +/* + * Policy-making subroutines for create_colormap and create_colorindex. + * These routines determine the colormap to be used. The rest of the module + * only assumes that the colormap is orthogonal. + * + * * select_ncolors decides how to divvy up the available colors + * among the components. + * * output_value defines the set of representative values for a component. + * * largest_input_value defines the mapping from input values to + * representative values for a component. + * Note that the latter two routines may impose different policies for + * different components, though this is not currently done. + */ + + +LOCAL(int) +select_ncolors (j_decompress_ptr cinfo, int Ncolors[]) +/* Determine allocation of desired colors to components, */ +/* and fill in Ncolors[] array to indicate choice. */ +/* Return value is total number of colors (product of Ncolors[] values). */ +{ + int nc = cinfo->out_color_components; /* number of color components */ + int max_colors = cinfo->desired_number_of_colors; + int total_colors, iroot, i, j; + boolean changed; + long temp; + static const int RGB_order[3] = { RGB_GREEN, RGB_RED, RGB_BLUE }; + + /* We can allocate at least the nc'th root of max_colors per component. */ + /* Compute floor(nc'th root of max_colors). */ + iroot = 1; + do { + iroot++; + temp = iroot; /* set temp = iroot ** nc */ + for (i = 1; i < nc; i++) + temp *= iroot; + } while (temp <= (long) max_colors); /* repeat till iroot exceeds root */ + iroot--; /* now iroot = floor(root) */ + + /* Must have at least 2 color values per component */ + if (iroot < 2) + ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, (int) temp); + + /* Initialize to iroot color values for each component */ + total_colors = 1; + for (i = 0; i < nc; i++) { + Ncolors[i] = iroot; + total_colors *= iroot; + } + /* We may be able to increment the count for one or more components without + * exceeding max_colors, though we know not all can be incremented. + * Sometimes, the first component can be incremented more than once! + * (Example: for 16 colors, we start at 2*2*2, go to 3*2*2, then 4*2*2.) + * In RGB colorspace, try to increment G first, then R, then B. + */ + do { + changed = FALSE; + for (i = 0; i < nc; i++) { + j = (cinfo->out_color_space == JCS_RGB ? RGB_order[i] : i); + /* calculate new total_colors if Ncolors[j] is incremented */ + temp = total_colors / Ncolors[j]; + temp *= Ncolors[j]+1; /* done in long arith to avoid oflo */ + if (temp > (long) max_colors) + break; /* won't fit, done with this pass */ + Ncolors[j]++; /* OK, apply the increment */ + total_colors = (int) temp; + changed = TRUE; + } + } while (changed); + + return total_colors; +} + + +LOCAL(int) +output_value (j_decompress_ptr cinfo, int ci, int j, int maxj) +/* Return j'th output value, where j will range from 0 to maxj */ +/* The output values must fall in 0..MAXJSAMPLE in increasing order */ +{ + /* We always provide values 0 and MAXJSAMPLE for each component; + * any additional values are equally spaced between these limits. + * (Forcing the upper and lower values to the limits ensures that + * dithering can't produce a color outside the selected gamut.) + */ + return (int) (((INT32) j * MAXJSAMPLE + maxj/2) / maxj); +} + + +LOCAL(int) +largest_input_value (j_decompress_ptr cinfo, int ci, int j, int maxj) +/* Return largest input value that should map to j'th output value */ +/* Must have largest(j=0) >= 0, and largest(j=maxj) >= MAXJSAMPLE */ +{ + /* Breakpoints are halfway between values returned by output_value */ + return (int) (((INT32) (2*j + 1) * MAXJSAMPLE + maxj) / (2*maxj)); +} + + +/* + * Create the colormap. + */ + +LOCAL(void) +create_colormap (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + JSAMPARRAY colormap; /* Created colormap */ + int total_colors; /* Number of distinct output colors */ + int i,j,k, nci, blksize, blkdist, ptr, val; + + /* Select number of colors for each component */ + total_colors = select_ncolors(cinfo, cquantize->Ncolors); + + /* Report selected color counts */ + if (cinfo->out_color_components == 3) + TRACEMS4(cinfo, 1, JTRC_QUANT_3_NCOLORS, + total_colors, cquantize->Ncolors[0], + cquantize->Ncolors[1], cquantize->Ncolors[2]); + else + TRACEMS1(cinfo, 1, JTRC_QUANT_NCOLORS, total_colors); + + /* Allocate and fill in the colormap. */ + /* The colors are ordered in the map in standard row-major order, */ + /* i.e. rightmost (highest-indexed) color changes most rapidly. */ + + colormap = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) total_colors, (JDIMENSION) cinfo->out_color_components); + + /* blksize is number of adjacent repeated entries for a component */ + /* blkdist is distance between groups of identical entries for a component */ + blkdist = total_colors; + + for (i = 0; i < cinfo->out_color_components; i++) { + /* fill in colormap entries for i'th color component */ + nci = cquantize->Ncolors[i]; /* # of distinct values for this color */ + blksize = blkdist / nci; + for (j = 0; j < nci; j++) { + /* Compute j'th output value (out of nci) for component */ + val = output_value(cinfo, i, j, nci-1); + /* Fill in all colormap entries that have this value of this component */ + for (ptr = j * blksize; ptr < total_colors; ptr += blkdist) { + /* fill in blksize entries beginning at ptr */ + for (k = 0; k < blksize; k++) + colormap[i][ptr+k] = (JSAMPLE) val; + } + } + blkdist = blksize; /* blksize of this color is blkdist of next */ + } + + /* Save the colormap in private storage, + * where it will survive color quantization mode changes. + */ + cquantize->sv_colormap = colormap; + cquantize->sv_actual = total_colors; +} + + +/* + * Create the color index table. + */ + +LOCAL(void) +create_colorindex (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + JSAMPROW indexptr; + int i,j,k, nci, blksize, val, pad; + + /* For ordered dither, we pad the color index tables by MAXJSAMPLE in + * each direction (input index values can be -MAXJSAMPLE .. 2*MAXJSAMPLE). + * This is not necessary in the other dithering modes. However, we + * flag whether it was done in case user changes dithering mode. + */ + if (cinfo->dither_mode == JDITHER_ORDERED) { + pad = MAXJSAMPLE*2; + cquantize->is_padded = TRUE; + } else { + pad = 0; + cquantize->is_padded = FALSE; + } + + cquantize->colorindex = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) (MAXJSAMPLE+1 + pad), + (JDIMENSION) cinfo->out_color_components); + + /* blksize is number of adjacent repeated entries for a component */ + blksize = cquantize->sv_actual; + + for (i = 0; i < cinfo->out_color_components; i++) { + /* fill in colorindex entries for i'th color component */ + nci = cquantize->Ncolors[i]; /* # of distinct values for this color */ + blksize = blksize / nci; + + /* adjust colorindex pointers to provide padding at negative indexes. */ + if (pad) + cquantize->colorindex[i] += MAXJSAMPLE; + + /* in loop, val = index of current output value, */ + /* and k = largest j that maps to current val */ + indexptr = cquantize->colorindex[i]; + val = 0; + k = largest_input_value(cinfo, i, 0, nci-1); + for (j = 0; j <= MAXJSAMPLE; j++) { + while (j > k) /* advance val if past boundary */ + k = largest_input_value(cinfo, i, ++val, nci-1); + /* premultiply so that no multiplication needed in main processing */ + indexptr[j] = (JSAMPLE) (val * blksize); + } + /* Pad at both ends if necessary */ + if (pad) + for (j = 1; j <= MAXJSAMPLE; j++) { + indexptr[-j] = indexptr[0]; + indexptr[MAXJSAMPLE+j] = indexptr[MAXJSAMPLE]; + } + } +} + + +/* + * Create an ordered-dither array for a component having ncolors + * distinct output values. + */ + +LOCAL(ODITHER_MATRIX_PTR) +make_odither_array (j_decompress_ptr cinfo, int ncolors) +{ + ODITHER_MATRIX_PTR odither; + int j,k; + INT32 num,den; + + odither = (ODITHER_MATRIX_PTR) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(ODITHER_MATRIX)); + /* The inter-value distance for this color is MAXJSAMPLE/(ncolors-1). + * Hence the dither value for the matrix cell with fill order f + * (f=0..N-1) should be (N-1-2*f)/(2*N) * MAXJSAMPLE/(ncolors-1). + * On 16-bit-int machine, be careful to avoid overflow. + */ + den = 2 * ODITHER_CELLS * ((INT32) (ncolors - 1)); + for (j = 0; j < ODITHER_SIZE; j++) { + for (k = 0; k < ODITHER_SIZE; k++) { + num = ((INT32) (ODITHER_CELLS-1 - 2*((int)base_dither_matrix[j][k]))) + * MAXJSAMPLE; + /* Ensure round towards zero despite C's lack of consistency + * about rounding negative values in integer division... + */ + odither[j][k] = (int) (num<0 ? -((-num)/den) : num/den); + } + } + return odither; +} + + +/* + * Create the ordered-dither tables. + * Components having the same number of representative colors may + * share a dither table. + */ + +LOCAL(void) +create_odither_tables (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + ODITHER_MATRIX_PTR odither; + int i, j, nci; + + for (i = 0; i < cinfo->out_color_components; i++) { + nci = cquantize->Ncolors[i]; /* # of distinct values for this color */ + odither = NULL; /* search for matching prior component */ + for (j = 0; j < i; j++) { + if (nci == cquantize->Ncolors[j]) { + odither = cquantize->odither[j]; + break; + } + } + if (odither == NULL) /* need a new table? */ + odither = make_odither_array(cinfo, nci); + cquantize->odither[i] = odither; + } +} + + +/* + * Map some rows of pixels to the output colormapped representation. + */ + +METHODDEF(void) +color_quantize (j_decompress_ptr cinfo, JSAMPARRAY input_buf, + JSAMPARRAY output_buf, int num_rows) +/* General case, no dithering */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + JSAMPARRAY colorindex = cquantize->colorindex; + register int pixcode, ci; + register JSAMPROW ptrin, ptrout; + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + register int nc = cinfo->out_color_components; + + for (row = 0; row < num_rows; row++) { + ptrin = input_buf[row]; + ptrout = output_buf[row]; + for (col = width; col > 0; col--) { + pixcode = 0; + for (ci = 0; ci < nc; ci++) { + pixcode += GETJSAMPLE(colorindex[ci][GETJSAMPLE(*ptrin++)]); + } + *ptrout++ = (JSAMPLE) pixcode; + } + } +} + + +METHODDEF(void) +color_quantize3 (j_decompress_ptr cinfo, JSAMPARRAY input_buf, + JSAMPARRAY output_buf, int num_rows) +/* Fast path for out_color_components==3, no dithering */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + register int pixcode; + register JSAMPROW ptrin, ptrout; + JSAMPROW colorindex0 = cquantize->colorindex[0]; + JSAMPROW colorindex1 = cquantize->colorindex[1]; + JSAMPROW colorindex2 = cquantize->colorindex[2]; + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + + for (row = 0; row < num_rows; row++) { + ptrin = input_buf[row]; + ptrout = output_buf[row]; + for (col = width; col > 0; col--) { + pixcode = GETJSAMPLE(colorindex0[GETJSAMPLE(*ptrin++)]); + pixcode += GETJSAMPLE(colorindex1[GETJSAMPLE(*ptrin++)]); + pixcode += GETJSAMPLE(colorindex2[GETJSAMPLE(*ptrin++)]); + *ptrout++ = (JSAMPLE) pixcode; + } + } +} + + +METHODDEF(void) +quantize_ord_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, + JSAMPARRAY output_buf, int num_rows) +/* General case, with ordered dithering */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + register JSAMPROW input_ptr; + register JSAMPROW output_ptr; + JSAMPROW colorindex_ci; + int * dither; /* points to active row of dither matrix */ + int row_index, col_index; /* current indexes into dither matrix */ + int nc = cinfo->out_color_components; + int ci; + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + + for (row = 0; row < num_rows; row++) { + /* Initialize output values to 0 so can process components separately */ + jzero_far((void FAR *) output_buf[row], + (size_t) (width * SIZEOF(JSAMPLE))); + row_index = cquantize->row_index; + for (ci = 0; ci < nc; ci++) { + input_ptr = input_buf[row] + ci; + output_ptr = output_buf[row]; + colorindex_ci = cquantize->colorindex[ci]; + dither = cquantize->odither[ci][row_index]; + col_index = 0; + + for (col = width; col > 0; col--) { + /* Form pixel value + dither, range-limit to 0..MAXJSAMPLE, + * select output value, accumulate into output code for this pixel. + * Range-limiting need not be done explicitly, as we have extended + * the colorindex table to produce the right answers for out-of-range + * inputs. The maximum dither is +- MAXJSAMPLE; this sets the + * required amount of padding. + */ + *output_ptr += colorindex_ci[GETJSAMPLE(*input_ptr)+dither[col_index]]; + input_ptr += nc; + output_ptr++; + col_index = (col_index + 1) & ODITHER_MASK; + } + } + /* Advance row index for next row */ + row_index = (row_index + 1) & ODITHER_MASK; + cquantize->row_index = row_index; + } +} + + +METHODDEF(void) +quantize3_ord_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, + JSAMPARRAY output_buf, int num_rows) +/* Fast path for out_color_components==3, with ordered dithering */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + register int pixcode; + register JSAMPROW input_ptr; + register JSAMPROW output_ptr; + JSAMPROW colorindex0 = cquantize->colorindex[0]; + JSAMPROW colorindex1 = cquantize->colorindex[1]; + JSAMPROW colorindex2 = cquantize->colorindex[2]; + int * dither0; /* points to active row of dither matrix */ + int * dither1; + int * dither2; + int row_index, col_index; /* current indexes into dither matrix */ + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + + for (row = 0; row < num_rows; row++) { + row_index = cquantize->row_index; + input_ptr = input_buf[row]; + output_ptr = output_buf[row]; + dither0 = cquantize->odither[0][row_index]; + dither1 = cquantize->odither[1][row_index]; + dither2 = cquantize->odither[2][row_index]; + col_index = 0; + + for (col = width; col > 0; col--) { + pixcode = GETJSAMPLE(colorindex0[GETJSAMPLE(*input_ptr++) + + dither0[col_index]]); + pixcode += GETJSAMPLE(colorindex1[GETJSAMPLE(*input_ptr++) + + dither1[col_index]]); + pixcode += GETJSAMPLE(colorindex2[GETJSAMPLE(*input_ptr++) + + dither2[col_index]]); + *output_ptr++ = (JSAMPLE) pixcode; + col_index = (col_index + 1) & ODITHER_MASK; + } + row_index = (row_index + 1) & ODITHER_MASK; + cquantize->row_index = row_index; + } +} + + +METHODDEF(void) +quantize_fs_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, + JSAMPARRAY output_buf, int num_rows) +/* General case, with Floyd-Steinberg dithering */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + register LOCFSERROR cur; /* current error or pixel value */ + LOCFSERROR belowerr; /* error for pixel below cur */ + LOCFSERROR bpreverr; /* error for below/prev col */ + LOCFSERROR bnexterr; /* error for below/next col */ + LOCFSERROR delta; + register FSERRPTR errorptr; /* => fserrors[] at column before current */ + register JSAMPROW input_ptr; + register JSAMPROW output_ptr; + JSAMPROW colorindex_ci; + JSAMPROW colormap_ci; + int pixcode; + int nc = cinfo->out_color_components; + int dir; /* 1 for left-to-right, -1 for right-to-left */ + int dirnc; /* dir * nc */ + int ci; + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + JSAMPLE *range_limit = cinfo->sample_range_limit; + SHIFT_TEMPS + + for (row = 0; row < num_rows; row++) { + /* Initialize output values to 0 so can process components separately */ + jzero_far((void FAR *) output_buf[row], + (size_t) (width * SIZEOF(JSAMPLE))); + for (ci = 0; ci < nc; ci++) { + input_ptr = input_buf[row] + ci; + output_ptr = output_buf[row]; + if (cquantize->on_odd_row) { + /* work right to left in this row */ + input_ptr += (width-1) * nc; /* so point to rightmost pixel */ + output_ptr += width-1; + dir = -1; + dirnc = -nc; + errorptr = cquantize->fserrors[ci] + (width+1); /* => entry after last column */ + } else { + /* work left to right in this row */ + dir = 1; + dirnc = nc; + errorptr = cquantize->fserrors[ci]; /* => entry before first column */ + } + colorindex_ci = cquantize->colorindex[ci]; + colormap_ci = cquantize->sv_colormap[ci]; + /* Preset error values: no error propagated to first pixel from left */ + cur = 0; + /* and no error propagated to row below yet */ + belowerr = bpreverr = 0; + + for (col = width; col > 0; col--) { + /* cur holds the error propagated from the previous pixel on the + * current line. Add the error propagated from the previous line + * to form the complete error correction term for this pixel, and + * round the error term (which is expressed * 16) to an integer. + * RIGHT_SHIFT rounds towards minus infinity, so adding 8 is correct + * for either sign of the error value. + * Note: errorptr points to *previous* column's array entry. + */ + cur = RIGHT_SHIFT(cur + errorptr[dir] + 8, 4); + /* Form pixel value + error, and range-limit to 0..MAXJSAMPLE. + * The maximum error is +- MAXJSAMPLE; this sets the required size + * of the range_limit array. + */ + cur += GETJSAMPLE(*input_ptr); + cur = GETJSAMPLE(range_limit[cur]); + /* Select output value, accumulate into output code for this pixel */ + pixcode = GETJSAMPLE(colorindex_ci[cur]); + *output_ptr += (JSAMPLE) pixcode; + /* Compute actual representation error at this pixel */ + /* Note: we can do this even though we don't have the final */ + /* pixel code, because the colormap is orthogonal. */ + cur -= GETJSAMPLE(colormap_ci[pixcode]); + /* Compute error fractions to be propagated to adjacent pixels. + * Add these into the running sums, and simultaneously shift the + * next-line error sums left by 1 column. + */ + bnexterr = cur; + delta = cur * 2; + cur += delta; /* form error * 3 */ + errorptr[0] = (FSERROR) (bpreverr + cur); + cur += delta; /* form error * 5 */ + bpreverr = belowerr + cur; + belowerr = bnexterr; + cur += delta; /* form error * 7 */ + /* At this point cur contains the 7/16 error value to be propagated + * to the next pixel on the current line, and all the errors for the + * next line have been shifted over. We are therefore ready to move on. + */ + input_ptr += dirnc; /* advance input ptr to next column */ + output_ptr += dir; /* advance output ptr to next column */ + errorptr += dir; /* advance errorptr to current column */ + } + /* Post-loop cleanup: we must unload the final error value into the + * final fserrors[] entry. Note we need not unload belowerr because + * it is for the dummy column before or after the actual array. + */ + errorptr[0] = (FSERROR) bpreverr; /* unload prev err into array */ + } + cquantize->on_odd_row = (cquantize->on_odd_row ? FALSE : TRUE); + } +} + + +/* + * Allocate workspace for Floyd-Steinberg errors. + */ + +LOCAL(void) +alloc_fs_workspace (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + size_t arraysize; + int i; + + arraysize = (size_t) ((cinfo->output_width + 2) * SIZEOF(FSERROR)); + for (i = 0; i < cinfo->out_color_components; i++) { + cquantize->fserrors[i] = (FSERRPTR) + (*cinfo->mem->alloc_large)((j_common_ptr) cinfo, JPOOL_IMAGE, arraysize); + } +} + + +/* + * Initialize for one-pass color quantization. + */ + +METHODDEF(void) +start_pass_1_quant (j_decompress_ptr cinfo, boolean is_pre_scan) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + size_t arraysize; + int i; + + /* Install my colormap. */ + cinfo->colormap = cquantize->sv_colormap; + cinfo->actual_number_of_colors = cquantize->sv_actual; + + /* Initialize for desired dithering mode. */ + switch (cinfo->dither_mode) { + case JDITHER_NONE: + if (cinfo->out_color_components == 3) + cquantize->pub.color_quantize = color_quantize3; + else + cquantize->pub.color_quantize = color_quantize; + break; + case JDITHER_ORDERED: + if (cinfo->out_color_components == 3) + cquantize->pub.color_quantize = quantize3_ord_dither; + else + cquantize->pub.color_quantize = quantize_ord_dither; + cquantize->row_index = 0; /* initialize state for ordered dither */ + /* If user changed to ordered dither from another mode, + * we must recreate the color index table with padding. + * This will cost extra space, but probably isn't very likely. + */ + if (! cquantize->is_padded) + create_colorindex(cinfo); + /* Create ordered-dither tables if we didn't already. */ + if (cquantize->odither[0] == NULL) + create_odither_tables(cinfo); + break; + case JDITHER_FS: + cquantize->pub.color_quantize = quantize_fs_dither; + cquantize->on_odd_row = FALSE; /* initialize state for F-S dither */ + /* Allocate Floyd-Steinberg workspace if didn't already. */ + if (cquantize->fserrors[0] == NULL) + alloc_fs_workspace(cinfo); + /* Initialize the propagated errors to zero. */ + arraysize = (size_t) ((cinfo->output_width + 2) * SIZEOF(FSERROR)); + for (i = 0; i < cinfo->out_color_components; i++) + jzero_far((void FAR *) cquantize->fserrors[i], arraysize); + break; + default: + ERREXIT(cinfo, JERR_NOT_COMPILED); + break; + } +} + + +/* + * Finish up at the end of the pass. + */ + +METHODDEF(void) +finish_pass_1_quant (j_decompress_ptr cinfo) +{ + /* no work in 1-pass case */ +} + + +/* + * Switch to a new external colormap between output passes. + * Shouldn't get to this module! + */ + +METHODDEF(void) +new_color_map_1_quant (j_decompress_ptr cinfo) +{ + ERREXIT(cinfo, JERR_MODE_CHANGE); +} + + +/* + * Module initialization routine for 1-pass color quantization. + */ + +GLOBAL(void) +jinit_1pass_quantizer (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize; + + cquantize = (my_cquantize_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_cquantizer)); + cinfo->cquantize = (struct jpeg_color_quantizer *) cquantize; + cquantize->pub.start_pass = start_pass_1_quant; + cquantize->pub.finish_pass = finish_pass_1_quant; + cquantize->pub.new_color_map = new_color_map_1_quant; + cquantize->fserrors[0] = NULL; /* Flag FS workspace not allocated */ + cquantize->odither[0] = NULL; /* Also flag odither arrays not allocated */ + + /* Make sure my internal arrays won't overflow */ + if (cinfo->out_color_components > MAX_Q_COMPS) + ERREXIT1(cinfo, JERR_QUANT_COMPONENTS, MAX_Q_COMPS); + /* Make sure colormap indexes can be represented by JSAMPLEs */ + if (cinfo->desired_number_of_colors > (MAXJSAMPLE+1)) + ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXJSAMPLE+1); + + /* Create the colormap and color index table. */ + create_colormap(cinfo); + create_colorindex(cinfo); + + /* Allocate Floyd-Steinberg workspace now if requested. + * We do this now since it is FAR storage and may affect the memory + * manager's space calculations. If the user changes to FS dither + * mode in a later pass, we will allocate the space then, and will + * possibly overrun the max_memory_to_use setting. + */ + if (cinfo->dither_mode == JDITHER_FS) + alloc_fs_workspace(cinfo); +} + +#endif /* QUANT_1PASS_SUPPORTED */ diff --git a/jpeg/JQUANT2.C b/jpeg/JQUANT2.C new file mode 100644 index 0000000..8dc506a --- /dev/null +++ b/jpeg/JQUANT2.C @@ -0,0 +1,1310 @@ +/* + * jquant2.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains 2-pass color quantization (color mapping) routines. + * These routines provide selection of a custom color map for an image, + * followed by mapping of the image to that color map, with optional + * Floyd-Steinberg dithering. + * It is also possible to use just the second pass to map to an arbitrary + * externally-given color map. + * + * Note: ordered dithering is not supported, since there isn't any fast + * way to compute intercolor distances; it's unclear that ordered dither's + * fundamental assumptions even hold with an irregularly spaced color map. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + +#ifdef QUANT_2PASS_SUPPORTED + + +/* + * This module implements the well-known Heckbert paradigm for color + * quantization. Most of the ideas used here can be traced back to + * Heckbert's seminal paper + * Heckbert, Paul. "Color Image Quantization for Frame Buffer Display", + * Proc. SIGGRAPH '82, Computer Graphics v.16 #3 (July 1982), pp 297-304. + * + * In the first pass over the image, we accumulate a histogram showing the + * usage count of each possible color. To keep the histogram to a reasonable + * size, we reduce the precision of the input; typical practice is to retain + * 5 or 6 bits per color, so that 8 or 4 different input values are counted + * in the same histogram cell. + * + * Next, the color-selection step begins with a box representing the whole + * color space, and repeatedly splits the "largest" remaining box until we + * have as many boxes as desired colors. Then the mean color in each + * remaining box becomes one of the possible output colors. + * + * The second pass over the image maps each input pixel to the closest output + * color (optionally after applying a Floyd-Steinberg dithering correction). + * This mapping is logically trivial, but making it go fast enough requires + * considerable care. + * + * Heckbert-style quantizers vary a good deal in their policies for choosing + * the "largest" box and deciding where to cut it. The particular policies + * used here have proved out well in experimental comparisons, but better ones + * may yet be found. + * + * In earlier versions of the IJG code, this module quantized in YCbCr color + * space, processing the raw upsampled data without a color conversion step. + * This allowed the color conversion math to be done only once per colormap + * entry, not once per pixel. However, that optimization precluded other + * useful optimizations (such as merging color conversion with upsampling) + * and it also interfered with desired capabilities such as quantizing to an + * externally-supplied colormap. We have therefore abandoned that approach. + * The present code works in the post-conversion color space, typically RGB. + * + * To improve the visual quality of the results, we actually work in scaled + * RGB space, giving G distances more weight than R, and R in turn more than + * B. To do everything in integer math, we must use integer scale factors. + * The 2/3/1 scale factors used here correspond loosely to the relative + * weights of the colors in the NTSC grayscale equation. + * If you want to use this code to quantize a non-RGB color space, you'll + * probably need to change these scale factors. + */ + +#define R_SCALE 2 /* scale R distances by this much */ +#define G_SCALE 3 /* scale G distances by this much */ +#define B_SCALE 1 /* and B by this much */ + +/* Relabel R/G/B as components 0/1/2, respecting the RGB ordering defined + * in jmorecfg.h. As the code stands, it will do the right thing for R,G,B + * and B,G,R orders. If you define some other weird order in jmorecfg.h, + * you'll get compile errors until you extend this logic. In that case + * you'll probably want to tweak the histogram sizes too. + */ + +#if RGB_RED == 0 +#define C0_SCALE R_SCALE +#endif +#if RGB_BLUE == 0 +#define C0_SCALE B_SCALE +#endif +#if RGB_GREEN == 1 +#define C1_SCALE G_SCALE +#endif +#if RGB_RED == 2 +#define C2_SCALE R_SCALE +#endif +#if RGB_BLUE == 2 +#define C2_SCALE B_SCALE +#endif + + +/* + * First we have the histogram data structure and routines for creating it. + * + * The number of bits of precision can be adjusted by changing these symbols. + * We recommend keeping 6 bits for G and 5 each for R and B. + * If you have plenty of memory and cycles, 6 bits all around gives marginally + * better results; if you are short of memory, 5 bits all around will save + * some space but degrade the results. + * To maintain a fully accurate histogram, we'd need to allocate a "long" + * (preferably unsigned long) for each cell. In practice this is overkill; + * we can get by with 16 bits per cell. Few of the cell counts will overflow, + * and clamping those that do overflow to the maximum value will give close- + * enough results. This reduces the recommended histogram size from 256Kb + * to 128Kb, which is a useful savings on PC-class machines. + * (In the second pass the histogram space is re-used for pixel mapping data; + * in that capacity, each cell must be able to store zero to the number of + * desired colors. 16 bits/cell is plenty for that too.) + * Since the JPEG code is intended to run in small memory model on 80x86 + * machines, we can't just allocate the histogram in one chunk. Instead + * of a true 3-D array, we use a row of pointers to 2-D arrays. Each + * pointer corresponds to a C0 value (typically 2^5 = 32 pointers) and + * each 2-D array has 2^6*2^5 = 2048 or 2^6*2^6 = 4096 entries. Note that + * on 80x86 machines, the pointer row is in near memory but the actual + * arrays are in far memory (same arrangement as we use for image arrays). + */ + +#define MAXNUMCOLORS (MAXJSAMPLE+1) /* maximum size of colormap */ + +/* These will do the right thing for either R,G,B or B,G,R color order, + * but you may not like the results for other color orders. + */ +#define HIST_C0_BITS 5 /* bits of precision in R/B histogram */ +#define HIST_C1_BITS 6 /* bits of precision in G histogram */ +#define HIST_C2_BITS 5 /* bits of precision in B/R histogram */ + +/* Number of elements along histogram axes. */ +#define HIST_C0_ELEMS (1<cquantize; + register JSAMPROW ptr; + register histptr histp; + register hist3d histogram = cquantize->histogram; + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + + for (row = 0; row < num_rows; row++) { + ptr = input_buf[row]; + for (col = width; col > 0; col--) { + /* get pixel value and index into the histogram */ + histp = & histogram[GETJSAMPLE(ptr[0]) >> C0_SHIFT] + [GETJSAMPLE(ptr[1]) >> C1_SHIFT] + [GETJSAMPLE(ptr[2]) >> C2_SHIFT]; + /* increment, check for overflow and undo increment if so. */ + if (++(*histp) <= 0) + (*histp)--; + ptr += 3; + } + } +} + + +/* + * Next we have the really interesting routines: selection of a colormap + * given the completed histogram. + * These routines work with a list of "boxes", each representing a rectangular + * subset of the input color space (to histogram precision). + */ + +typedef struct { + /* The bounds of the box (inclusive); expressed as histogram indexes */ + int c0min, c0max; + int c1min, c1max; + int c2min, c2max; + /* The volume (actually 2-norm) of the box */ + INT32 volume; + /* The number of nonzero histogram cells within this box */ + long colorcount; +} box; + +typedef box * boxptr; + + +LOCAL(boxptr) +find_biggest_color_pop (boxptr boxlist, int numboxes) +/* Find the splittable box with the largest color population */ +/* Returns NULL if no splittable boxes remain */ +{ + register boxptr boxp; + register int i; + register long maxc = 0; + boxptr which = NULL; + + for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) { + if (boxp->colorcount > maxc && boxp->volume > 0) { + which = boxp; + maxc = boxp->colorcount; + } + } + return which; +} + + +LOCAL(boxptr) +find_biggest_volume (boxptr boxlist, int numboxes) +/* Find the splittable box with the largest (scaled) volume */ +/* Returns NULL if no splittable boxes remain */ +{ + register boxptr boxp; + register int i; + register INT32 maxv = 0; + boxptr which = NULL; + + for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) { + if (boxp->volume > maxv) { + which = boxp; + maxv = boxp->volume; + } + } + return which; +} + + +LOCAL(void) +update_box (j_decompress_ptr cinfo, boxptr boxp) +/* Shrink the min/max bounds of a box to enclose only nonzero elements, */ +/* and recompute its volume and population */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + hist3d histogram = cquantize->histogram; + histptr histp; + int c0,c1,c2; + int c0min,c0max,c1min,c1max,c2min,c2max; + INT32 dist0,dist1,dist2; + long ccount; + + c0min = boxp->c0min; c0max = boxp->c0max; + c1min = boxp->c1min; c1max = boxp->c1max; + c2min = boxp->c2min; c2max = boxp->c2max; + + if (c0max > c0min) + for (c0 = c0min; c0 <= c0max; c0++) + for (c1 = c1min; c1 <= c1max; c1++) { + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) + if (*histp++ != 0) { + boxp->c0min = c0min = c0; + goto have_c0min; + } + } + have_c0min: + if (c0max > c0min) + for (c0 = c0max; c0 >= c0min; c0--) + for (c1 = c1min; c1 <= c1max; c1++) { + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) + if (*histp++ != 0) { + boxp->c0max = c0max = c0; + goto have_c0max; + } + } + have_c0max: + if (c1max > c1min) + for (c1 = c1min; c1 <= c1max; c1++) + for (c0 = c0min; c0 <= c0max; c0++) { + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) + if (*histp++ != 0) { + boxp->c1min = c1min = c1; + goto have_c1min; + } + } + have_c1min: + if (c1max > c1min) + for (c1 = c1max; c1 >= c1min; c1--) + for (c0 = c0min; c0 <= c0max; c0++) { + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) + if (*histp++ != 0) { + boxp->c1max = c1max = c1; + goto have_c1max; + } + } + have_c1max: + if (c2max > c2min) + for (c2 = c2min; c2 <= c2max; c2++) + for (c0 = c0min; c0 <= c0max; c0++) { + histp = & histogram[c0][c1min][c2]; + for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS) + if (*histp != 0) { + boxp->c2min = c2min = c2; + goto have_c2min; + } + } + have_c2min: + if (c2max > c2min) + for (c2 = c2max; c2 >= c2min; c2--) + for (c0 = c0min; c0 <= c0max; c0++) { + histp = & histogram[c0][c1min][c2]; + for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS) + if (*histp != 0) { + boxp->c2max = c2max = c2; + goto have_c2max; + } + } + have_c2max: + + /* Update box volume. + * We use 2-norm rather than real volume here; this biases the method + * against making long narrow boxes, and it has the side benefit that + * a box is splittable iff norm > 0. + * Since the differences are expressed in histogram-cell units, + * we have to shift back to JSAMPLE units to get consistent distances; + * after which, we scale according to the selected distance scale factors. + */ + dist0 = ((c0max - c0min) << C0_SHIFT) * C0_SCALE; + dist1 = ((c1max - c1min) << C1_SHIFT) * C1_SCALE; + dist2 = ((c2max - c2min) << C2_SHIFT) * C2_SCALE; + boxp->volume = dist0*dist0 + dist1*dist1 + dist2*dist2; + + /* Now scan remaining volume of box and compute population */ + ccount = 0; + for (c0 = c0min; c0 <= c0max; c0++) + for (c1 = c1min; c1 <= c1max; c1++) { + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++, histp++) + if (*histp != 0) { + ccount++; + } + } + boxp->colorcount = ccount; +} + + +LOCAL(int) +median_cut (j_decompress_ptr cinfo, boxptr boxlist, int numboxes, + int desired_colors) +/* Repeatedly select and split the largest box until we have enough boxes */ +{ + int n,lb; + int c0,c1,c2,cmax; + register boxptr b1,b2; + + while (numboxes < desired_colors) { + /* Select box to split. + * Current algorithm: by population for first half, then by volume. + */ + if (numboxes*2 <= desired_colors) { + b1 = find_biggest_color_pop(boxlist, numboxes); + } else { + b1 = find_biggest_volume(boxlist, numboxes); + } + if (b1 == NULL) /* no splittable boxes left! */ + break; + b2 = &boxlist[numboxes]; /* where new box will go */ + /* Copy the color bounds to the new box. */ + b2->c0max = b1->c0max; b2->c1max = b1->c1max; b2->c2max = b1->c2max; + b2->c0min = b1->c0min; b2->c1min = b1->c1min; b2->c2min = b1->c2min; + /* Choose which axis to split the box on. + * Current algorithm: longest scaled axis. + * See notes in update_box about scaling distances. + */ + c0 = ((b1->c0max - b1->c0min) << C0_SHIFT) * C0_SCALE; + c1 = ((b1->c1max - b1->c1min) << C1_SHIFT) * C1_SCALE; + c2 = ((b1->c2max - b1->c2min) << C2_SHIFT) * C2_SCALE; + /* We want to break any ties in favor of green, then red, blue last. + * This code does the right thing for R,G,B or B,G,R color orders only. + */ +#if RGB_RED == 0 + cmax = c1; n = 1; + if (c0 > cmax) { cmax = c0; n = 0; } + if (c2 > cmax) { n = 2; } +#else + cmax = c1; n = 1; + if (c2 > cmax) { cmax = c2; n = 2; } + if (c0 > cmax) { n = 0; } +#endif + /* Choose split point along selected axis, and update box bounds. + * Current algorithm: split at halfway point. + * (Since the box has been shrunk to minimum volume, + * any split will produce two nonempty subboxes.) + * Note that lb value is max for lower box, so must be < old max. + */ + switch (n) { + case 0: + lb = (b1->c0max + b1->c0min) / 2; + b1->c0max = lb; + b2->c0min = lb+1; + break; + case 1: + lb = (b1->c1max + b1->c1min) / 2; + b1->c1max = lb; + b2->c1min = lb+1; + break; + case 2: + lb = (b1->c2max + b1->c2min) / 2; + b1->c2max = lb; + b2->c2min = lb+1; + break; + } + /* Update stats for boxes */ + update_box(cinfo, b1); + update_box(cinfo, b2); + numboxes++; + } + return numboxes; +} + + +LOCAL(void) +compute_color (j_decompress_ptr cinfo, boxptr boxp, int icolor) +/* Compute representative color for a box, put it in colormap[icolor] */ +{ + /* Current algorithm: mean weighted by pixels (not colors) */ + /* Note it is important to get the rounding correct! */ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + hist3d histogram = cquantize->histogram; + histptr histp; + int c0,c1,c2; + int c0min,c0max,c1min,c1max,c2min,c2max; + long count; + long total = 0; + long c0total = 0; + long c1total = 0; + long c2total = 0; + + c0min = boxp->c0min; c0max = boxp->c0max; + c1min = boxp->c1min; c1max = boxp->c1max; + c2min = boxp->c2min; c2max = boxp->c2max; + + for (c0 = c0min; c0 <= c0max; c0++) + for (c1 = c1min; c1 <= c1max; c1++) { + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) { + if ((count = *histp++) != 0) { + total += count; + c0total += ((c0 << C0_SHIFT) + ((1<>1)) * count; + c1total += ((c1 << C1_SHIFT) + ((1<>1)) * count; + c2total += ((c2 << C2_SHIFT) + ((1<>1)) * count; + } + } + } + + cinfo->colormap[0][icolor] = (JSAMPLE) ((c0total + (total>>1)) / total); + cinfo->colormap[1][icolor] = (JSAMPLE) ((c1total + (total>>1)) / total); + cinfo->colormap[2][icolor] = (JSAMPLE) ((c2total + (total>>1)) / total); +} + + +LOCAL(void) +select_colors (j_decompress_ptr cinfo, int desired_colors) +/* Master routine for color selection */ +{ + boxptr boxlist; + int numboxes; + int i; + + /* Allocate workspace for box list */ + boxlist = (boxptr) (*cinfo->mem->alloc_small) + ((j_common_ptr) cinfo, JPOOL_IMAGE, desired_colors * SIZEOF(box)); + /* Initialize one box containing whole space */ + numboxes = 1; + boxlist[0].c0min = 0; + boxlist[0].c0max = MAXJSAMPLE >> C0_SHIFT; + boxlist[0].c1min = 0; + boxlist[0].c1max = MAXJSAMPLE >> C1_SHIFT; + boxlist[0].c2min = 0; + boxlist[0].c2max = MAXJSAMPLE >> C2_SHIFT; + /* Shrink it to actually-used volume and set its statistics */ + update_box(cinfo, & boxlist[0]); + /* Perform median-cut to produce final box list */ + numboxes = median_cut(cinfo, boxlist, numboxes, desired_colors); + /* Compute the representative color for each box, fill colormap */ + for (i = 0; i < numboxes; i++) + compute_color(cinfo, & boxlist[i], i); + cinfo->actual_number_of_colors = numboxes; + TRACEMS1(cinfo, 1, JTRC_QUANT_SELECTED, numboxes); +} + + +/* + * These routines are concerned with the time-critical task of mapping input + * colors to the nearest color in the selected colormap. + * + * We re-use the histogram space as an "inverse color map", essentially a + * cache for the results of nearest-color searches. All colors within a + * histogram cell will be mapped to the same colormap entry, namely the one + * closest to the cell's center. This may not be quite the closest entry to + * the actual input color, but it's almost as good. A zero in the cache + * indicates we haven't found the nearest color for that cell yet; the array + * is cleared to zeroes before starting the mapping pass. When we find the + * nearest color for a cell, its colormap index plus one is recorded in the + * cache for future use. The pass2 scanning routines call fill_inverse_cmap + * when they need to use an unfilled entry in the cache. + * + * Our method of efficiently finding nearest colors is based on the "locally + * sorted search" idea described by Heckbert and on the incremental distance + * calculation described by Spencer W. Thomas in chapter III.1 of Graphics + * Gems II (James Arvo, ed. Academic Press, 1991). Thomas points out that + * the distances from a given colormap entry to each cell of the histogram can + * be computed quickly using an incremental method: the differences between + * distances to adjacent cells themselves differ by a constant. This allows a + * fairly fast implementation of the "brute force" approach of computing the + * distance from every colormap entry to every histogram cell. Unfortunately, + * it needs a work array to hold the best-distance-so-far for each histogram + * cell (because the inner loop has to be over cells, not colormap entries). + * The work array elements have to be INT32s, so the work array would need + * 256Kb at our recommended precision. This is not feasible in DOS machines. + * + * To get around these problems, we apply Thomas' method to compute the + * nearest colors for only the cells within a small subbox of the histogram. + * The work array need be only as big as the subbox, so the memory usage + * problem is solved. Furthermore, we need not fill subboxes that are never + * referenced in pass2; many images use only part of the color gamut, so a + * fair amount of work is saved. An additional advantage of this + * approach is that we can apply Heckbert's locality criterion to quickly + * eliminate colormap entries that are far away from the subbox; typically + * three-fourths of the colormap entries are rejected by Heckbert's criterion, + * and we need not compute their distances to individual cells in the subbox. + * The speed of this approach is heavily influenced by the subbox size: too + * small means too much overhead, too big loses because Heckbert's criterion + * can't eliminate as many colormap entries. Empirically the best subbox + * size seems to be about 1/512th of the histogram (1/8th in each direction). + * + * Thomas' article also describes a refined method which is asymptotically + * faster than the brute-force method, but it is also far more complex and + * cannot efficiently be applied to small subboxes. It is therefore not + * useful for programs intended to be portable to DOS machines. On machines + * with plenty of memory, filling the whole histogram in one shot with Thomas' + * refined method might be faster than the present code --- but then again, + * it might not be any faster, and it's certainly more complicated. + */ + + +/* log2(histogram cells in update box) for each axis; this can be adjusted */ +#define BOX_C0_LOG (HIST_C0_BITS-3) +#define BOX_C1_LOG (HIST_C1_BITS-3) +#define BOX_C2_LOG (HIST_C2_BITS-3) + +#define BOX_C0_ELEMS (1<actual_number_of_colors; + int maxc0, maxc1, maxc2; + int centerc0, centerc1, centerc2; + int i, x, ncolors; + INT32 minmaxdist, min_dist, max_dist, tdist; + INT32 mindist[MAXNUMCOLORS]; /* min distance to colormap entry i */ + + /* Compute true coordinates of update box's upper corner and center. + * Actually we compute the coordinates of the center of the upper-corner + * histogram cell, which are the upper bounds of the volume we care about. + * Note that since ">>" rounds down, the "center" values may be closer to + * min than to max; hence comparisons to them must be "<=", not "<". + */ + maxc0 = minc0 + ((1 << BOX_C0_SHIFT) - (1 << C0_SHIFT)); + centerc0 = (minc0 + maxc0) >> 1; + maxc1 = minc1 + ((1 << BOX_C1_SHIFT) - (1 << C1_SHIFT)); + centerc1 = (minc1 + maxc1) >> 1; + maxc2 = minc2 + ((1 << BOX_C2_SHIFT) - (1 << C2_SHIFT)); + centerc2 = (minc2 + maxc2) >> 1; + + /* For each color in colormap, find: + * 1. its minimum squared-distance to any point in the update box + * (zero if color is within update box); + * 2. its maximum squared-distance to any point in the update box. + * Both of these can be found by considering only the corners of the box. + * We save the minimum distance for each color in mindist[]; + * only the smallest maximum distance is of interest. + */ + minmaxdist = 0x7FFFFFFFL; + + for (i = 0; i < numcolors; i++) { + /* We compute the squared-c0-distance term, then add in the other two. */ + x = GETJSAMPLE(cinfo->colormap[0][i]); + if (x < minc0) { + tdist = (x - minc0) * C0_SCALE; + min_dist = tdist*tdist; + tdist = (x - maxc0) * C0_SCALE; + max_dist = tdist*tdist; + } else if (x > maxc0) { + tdist = (x - maxc0) * C0_SCALE; + min_dist = tdist*tdist; + tdist = (x - minc0) * C0_SCALE; + max_dist = tdist*tdist; + } else { + /* within cell range so no contribution to min_dist */ + min_dist = 0; + if (x <= centerc0) { + tdist = (x - maxc0) * C0_SCALE; + max_dist = tdist*tdist; + } else { + tdist = (x - minc0) * C0_SCALE; + max_dist = tdist*tdist; + } + } + + x = GETJSAMPLE(cinfo->colormap[1][i]); + if (x < minc1) { + tdist = (x - minc1) * C1_SCALE; + min_dist += tdist*tdist; + tdist = (x - maxc1) * C1_SCALE; + max_dist += tdist*tdist; + } else if (x > maxc1) { + tdist = (x - maxc1) * C1_SCALE; + min_dist += tdist*tdist; + tdist = (x - minc1) * C1_SCALE; + max_dist += tdist*tdist; + } else { + /* within cell range so no contribution to min_dist */ + if (x <= centerc1) { + tdist = (x - maxc1) * C1_SCALE; + max_dist += tdist*tdist; + } else { + tdist = (x - minc1) * C1_SCALE; + max_dist += tdist*tdist; + } + } + + x = GETJSAMPLE(cinfo->colormap[2][i]); + if (x < minc2) { + tdist = (x - minc2) * C2_SCALE; + min_dist += tdist*tdist; + tdist = (x - maxc2) * C2_SCALE; + max_dist += tdist*tdist; + } else if (x > maxc2) { + tdist = (x - maxc2) * C2_SCALE; + min_dist += tdist*tdist; + tdist = (x - minc2) * C2_SCALE; + max_dist += tdist*tdist; + } else { + /* within cell range so no contribution to min_dist */ + if (x <= centerc2) { + tdist = (x - maxc2) * C2_SCALE; + max_dist += tdist*tdist; + } else { + tdist = (x - minc2) * C2_SCALE; + max_dist += tdist*tdist; + } + } + + mindist[i] = min_dist; /* save away the results */ + if (max_dist < minmaxdist) + minmaxdist = max_dist; + } + + /* Now we know that no cell in the update box is more than minmaxdist + * away from some colormap entry. Therefore, only colors that are + * within minmaxdist of some part of the box need be considered. + */ + ncolors = 0; + for (i = 0; i < numcolors; i++) { + if (mindist[i] <= minmaxdist) + colorlist[ncolors++] = (JSAMPLE) i; + } + return ncolors; +} + + +LOCAL(void) +find_best_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2, + int numcolors, JSAMPLE colorlist[], JSAMPLE bestcolor[]) +/* Find the closest colormap entry for each cell in the update box, + * given the list of candidate colors prepared by find_nearby_colors. + * Return the indexes of the closest entries in the bestcolor[] array. + * This routine uses Thomas' incremental distance calculation method to + * find the distance from a colormap entry to successive cells in the box. + */ +{ + int ic0, ic1, ic2; + int i, icolor; + register INT32 * bptr; /* pointer into bestdist[] array */ + JSAMPLE * cptr; /* pointer into bestcolor[] array */ + INT32 dist0, dist1; /* initial distance values */ + register INT32 dist2; /* current distance in inner loop */ + INT32 xx0, xx1; /* distance increments */ + register INT32 xx2; + INT32 inc0, inc1, inc2; /* initial values for increments */ + /* This array holds the distance to the nearest-so-far color for each cell */ + INT32 bestdist[BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS]; + + /* Initialize best-distance for each cell of the update box */ + bptr = bestdist; + for (i = BOX_C0_ELEMS*BOX_C1_ELEMS*BOX_C2_ELEMS-1; i >= 0; i--) + *bptr++ = 0x7FFFFFFFL; + + /* For each color selected by find_nearby_colors, + * compute its distance to the center of each cell in the box. + * If that's less than best-so-far, update best distance and color number. + */ + + /* Nominal steps between cell centers ("x" in Thomas article) */ +#define STEP_C0 ((1 << C0_SHIFT) * C0_SCALE) +#define STEP_C1 ((1 << C1_SHIFT) * C1_SCALE) +#define STEP_C2 ((1 << C2_SHIFT) * C2_SCALE) + + for (i = 0; i < numcolors; i++) { + icolor = GETJSAMPLE(colorlist[i]); + /* Compute (square of) distance from minc0/c1/c2 to this color */ + inc0 = (minc0 - GETJSAMPLE(cinfo->colormap[0][icolor])) * C0_SCALE; + dist0 = inc0*inc0; + inc1 = (minc1 - GETJSAMPLE(cinfo->colormap[1][icolor])) * C1_SCALE; + dist0 += inc1*inc1; + inc2 = (minc2 - GETJSAMPLE(cinfo->colormap[2][icolor])) * C2_SCALE; + dist0 += inc2*inc2; + /* Form the initial difference increments */ + inc0 = inc0 * (2 * STEP_C0) + STEP_C0 * STEP_C0; + inc1 = inc1 * (2 * STEP_C1) + STEP_C1 * STEP_C1; + inc2 = inc2 * (2 * STEP_C2) + STEP_C2 * STEP_C2; + /* Now loop over all cells in box, updating distance per Thomas method */ + bptr = bestdist; + cptr = bestcolor; + xx0 = inc0; + for (ic0 = BOX_C0_ELEMS-1; ic0 >= 0; ic0--) { + dist1 = dist0; + xx1 = inc1; + for (ic1 = BOX_C1_ELEMS-1; ic1 >= 0; ic1--) { + dist2 = dist1; + xx2 = inc2; + for (ic2 = BOX_C2_ELEMS-1; ic2 >= 0; ic2--) { + if (dist2 < *bptr) { + *bptr = dist2; + *cptr = (JSAMPLE) icolor; + } + dist2 += xx2; + xx2 += 2 * STEP_C2 * STEP_C2; + bptr++; + cptr++; + } + dist1 += xx1; + xx1 += 2 * STEP_C1 * STEP_C1; + } + dist0 += xx0; + xx0 += 2 * STEP_C0 * STEP_C0; + } + } +} + + +LOCAL(void) +fill_inverse_cmap (j_decompress_ptr cinfo, int c0, int c1, int c2) +/* Fill the inverse-colormap entries in the update box that contains */ +/* histogram cell c0/c1/c2. (Only that one cell MUST be filled, but */ +/* we can fill as many others as we wish.) */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + hist3d histogram = cquantize->histogram; + int minc0, minc1, minc2; /* lower left corner of update box */ + int ic0, ic1, ic2; + register JSAMPLE * cptr; /* pointer into bestcolor[] array */ + register histptr cachep; /* pointer into main cache array */ + /* This array lists the candidate colormap indexes. */ + JSAMPLE colorlist[MAXNUMCOLORS]; + int numcolors; /* number of candidate colors */ + /* This array holds the actually closest colormap index for each cell. */ + JSAMPLE bestcolor[BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS]; + + /* Convert cell coordinates to update box ID */ + c0 >>= BOX_C0_LOG; + c1 >>= BOX_C1_LOG; + c2 >>= BOX_C2_LOG; + + /* Compute true coordinates of update box's origin corner. + * Actually we compute the coordinates of the center of the corner + * histogram cell, which are the lower bounds of the volume we care about. + */ + minc0 = (c0 << BOX_C0_SHIFT) + ((1 << C0_SHIFT) >> 1); + minc1 = (c1 << BOX_C1_SHIFT) + ((1 << C1_SHIFT) >> 1); + minc2 = (c2 << BOX_C2_SHIFT) + ((1 << C2_SHIFT) >> 1); + + /* Determine which colormap entries are close enough to be candidates + * for the nearest entry to some cell in the update box. + */ + numcolors = find_nearby_colors(cinfo, minc0, minc1, minc2, colorlist); + + /* Determine the actually nearest colors. */ + find_best_colors(cinfo, minc0, minc1, minc2, numcolors, colorlist, + bestcolor); + + /* Save the best color numbers (plus 1) in the main cache array */ + c0 <<= BOX_C0_LOG; /* convert ID back to base cell indexes */ + c1 <<= BOX_C1_LOG; + c2 <<= BOX_C2_LOG; + cptr = bestcolor; + for (ic0 = 0; ic0 < BOX_C0_ELEMS; ic0++) { + for (ic1 = 0; ic1 < BOX_C1_ELEMS; ic1++) { + cachep = & histogram[c0+ic0][c1+ic1][c2]; + for (ic2 = 0; ic2 < BOX_C2_ELEMS; ic2++) { + *cachep++ = (histcell) (GETJSAMPLE(*cptr++) + 1); + } + } + } +} + + +/* + * Map some rows of pixels to the output colormapped representation. + */ + +METHODDEF(void) +pass2_no_dither (j_decompress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows) +/* This version performs no dithering */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + hist3d histogram = cquantize->histogram; + register JSAMPROW inptr, outptr; + register histptr cachep; + register int c0, c1, c2; + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + + for (row = 0; row < num_rows; row++) { + inptr = input_buf[row]; + outptr = output_buf[row]; + for (col = width; col > 0; col--) { + /* get pixel value and index into the cache */ + c0 = GETJSAMPLE(*inptr++) >> C0_SHIFT; + c1 = GETJSAMPLE(*inptr++) >> C1_SHIFT; + c2 = GETJSAMPLE(*inptr++) >> C2_SHIFT; + cachep = & histogram[c0][c1][c2]; + /* If we have not seen this color before, find nearest colormap entry */ + /* and update the cache */ + if (*cachep == 0) + fill_inverse_cmap(cinfo, c0,c1,c2); + /* Now emit the colormap index for this cell */ + *outptr++ = (JSAMPLE) (*cachep - 1); + } + } +} + + +METHODDEF(void) +pass2_fs_dither (j_decompress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows) +/* This version performs Floyd-Steinberg dithering */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + hist3d histogram = cquantize->histogram; + register LOCFSERROR cur0, cur1, cur2; /* current error or pixel value */ + LOCFSERROR belowerr0, belowerr1, belowerr2; /* error for pixel below cur */ + LOCFSERROR bpreverr0, bpreverr1, bpreverr2; /* error for below/prev col */ + register FSERRPTR errorptr; /* => fserrors[] at column before current */ + JSAMPROW inptr; /* => current input pixel */ + JSAMPROW outptr; /* => current output pixel */ + histptr cachep; + int dir; /* +1 or -1 depending on direction */ + int dir3; /* 3*dir, for advancing inptr & errorptr */ + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + JSAMPLE *range_limit = cinfo->sample_range_limit; + int *error_limit = cquantize->error_limiter; + JSAMPROW colormap0 = cinfo->colormap[0]; + JSAMPROW colormap1 = cinfo->colormap[1]; + JSAMPROW colormap2 = cinfo->colormap[2]; + SHIFT_TEMPS + + for (row = 0; row < num_rows; row++) { + inptr = input_buf[row]; + outptr = output_buf[row]; + if (cquantize->on_odd_row) { + /* work right to left in this row */ + inptr += (width-1) * 3; /* so point to rightmost pixel */ + outptr += width-1; + dir = -1; + dir3 = -3; + errorptr = cquantize->fserrors + (width+1)*3; /* => entry after last column */ + cquantize->on_odd_row = FALSE; /* flip for next time */ + } else { + /* work left to right in this row */ + dir = 1; + dir3 = 3; + errorptr = cquantize->fserrors; /* => entry before first real column */ + cquantize->on_odd_row = TRUE; /* flip for next time */ + } + /* Preset error values: no error propagated to first pixel from left */ + cur0 = cur1 = cur2 = 0; + /* and no error propagated to row below yet */ + belowerr0 = belowerr1 = belowerr2 = 0; + bpreverr0 = bpreverr1 = bpreverr2 = 0; + + for (col = width; col > 0; col--) { + /* curN holds the error propagated from the previous pixel on the + * current line. Add the error propagated from the previous line + * to form the complete error correction term for this pixel, and + * round the error term (which is expressed * 16) to an integer. + * RIGHT_SHIFT rounds towards minus infinity, so adding 8 is correct + * for either sign of the error value. + * Note: errorptr points to *previous* column's array entry. + */ + cur0 = RIGHT_SHIFT(cur0 + errorptr[dir3+0] + 8, 4); + cur1 = RIGHT_SHIFT(cur1 + errorptr[dir3+1] + 8, 4); + cur2 = RIGHT_SHIFT(cur2 + errorptr[dir3+2] + 8, 4); + /* Limit the error using transfer function set by init_error_limit. + * See comments with init_error_limit for rationale. + */ + cur0 = error_limit[cur0]; + cur1 = error_limit[cur1]; + cur2 = error_limit[cur2]; + /* Form pixel value + error, and range-limit to 0..MAXJSAMPLE. + * The maximum error is +- MAXJSAMPLE (or less with error limiting); + * this sets the required size of the range_limit array. + */ + cur0 += GETJSAMPLE(inptr[0]); + cur1 += GETJSAMPLE(inptr[1]); + cur2 += GETJSAMPLE(inptr[2]); + cur0 = GETJSAMPLE(range_limit[cur0]); + cur1 = GETJSAMPLE(range_limit[cur1]); + cur2 = GETJSAMPLE(range_limit[cur2]); + /* Index into the cache with adjusted pixel value */ + cachep = & histogram[cur0>>C0_SHIFT][cur1>>C1_SHIFT][cur2>>C2_SHIFT]; + /* If we have not seen this color before, find nearest colormap */ + /* entry and update the cache */ + if (*cachep == 0) + fill_inverse_cmap(cinfo, cur0>>C0_SHIFT,cur1>>C1_SHIFT,cur2>>C2_SHIFT); + /* Now emit the colormap index for this cell */ + { register int pixcode = *cachep - 1; + *outptr = (JSAMPLE) pixcode; + /* Compute representation error for this pixel */ + cur0 -= GETJSAMPLE(colormap0[pixcode]); + cur1 -= GETJSAMPLE(colormap1[pixcode]); + cur2 -= GETJSAMPLE(colormap2[pixcode]); + } + /* Compute error fractions to be propagated to adjacent pixels. + * Add these into the running sums, and simultaneously shift the + * next-line error sums left by 1 column. + */ + { register LOCFSERROR bnexterr, delta; + + bnexterr = cur0; /* Process component 0 */ + delta = cur0 * 2; + cur0 += delta; /* form error * 3 */ + errorptr[0] = (FSERROR) (bpreverr0 + cur0); + cur0 += delta; /* form error * 5 */ + bpreverr0 = belowerr0 + cur0; + belowerr0 = bnexterr; + cur0 += delta; /* form error * 7 */ + bnexterr = cur1; /* Process component 1 */ + delta = cur1 * 2; + cur1 += delta; /* form error * 3 */ + errorptr[1] = (FSERROR) (bpreverr1 + cur1); + cur1 += delta; /* form error * 5 */ + bpreverr1 = belowerr1 + cur1; + belowerr1 = bnexterr; + cur1 += delta; /* form error * 7 */ + bnexterr = cur2; /* Process component 2 */ + delta = cur2 * 2; + cur2 += delta; /* form error * 3 */ + errorptr[2] = (FSERROR) (bpreverr2 + cur2); + cur2 += delta; /* form error * 5 */ + bpreverr2 = belowerr2 + cur2; + belowerr2 = bnexterr; + cur2 += delta; /* form error * 7 */ + } + /* At this point curN contains the 7/16 error value to be propagated + * to the next pixel on the current line, and all the errors for the + * next line have been shifted over. We are therefore ready to move on. + */ + inptr += dir3; /* Advance pixel pointers to next column */ + outptr += dir; + errorptr += dir3; /* advance errorptr to current column */ + } + /* Post-loop cleanup: we must unload the final error values into the + * final fserrors[] entry. Note we need not unload belowerrN because + * it is for the dummy column before or after the actual array. + */ + errorptr[0] = (FSERROR) bpreverr0; /* unload prev errs into array */ + errorptr[1] = (FSERROR) bpreverr1; + errorptr[2] = (FSERROR) bpreverr2; + } +} + + +/* + * Initialize the error-limiting transfer function (lookup table). + * The raw F-S error computation can potentially compute error values of up to + * +- MAXJSAMPLE. But we want the maximum correction applied to a pixel to be + * much less, otherwise obviously wrong pixels will be created. (Typical + * effects include weird fringes at color-area boundaries, isolated bright + * pixels in a dark area, etc.) The standard advice for avoiding this problem + * is to ensure that the "corners" of the color cube are allocated as output + * colors; then repeated errors in the same direction cannot cause cascading + * error buildup. However, that only prevents the error from getting + * completely out of hand; Aaron Giles reports that error limiting improves + * the results even with corner colors allocated. + * A simple clamping of the error values to about +- MAXJSAMPLE/8 works pretty + * well, but the smoother transfer function used below is even better. Thanks + * to Aaron Giles for this idea. + */ + +LOCAL(void) +init_error_limit (j_decompress_ptr cinfo) +/* Allocate and fill in the error_limiter table */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + int * table; + int in, out; + + table = (int *) (*cinfo->mem->alloc_small) + ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE*2+1) * SIZEOF(int)); + table += MAXJSAMPLE; /* so can index -MAXJSAMPLE .. +MAXJSAMPLE */ + cquantize->error_limiter = table; + +#define STEPSIZE ((MAXJSAMPLE+1)/16) + /* Map errors 1:1 up to +- MAXJSAMPLE/16 */ + out = 0; + for (in = 0; in < STEPSIZE; in++, out++) { + table[in] = out; table[-in] = -out; + } + /* Map errors 1:2 up to +- 3*MAXJSAMPLE/16 */ + for (; in < STEPSIZE*3; in++, out += (in&1) ? 0 : 1) { + table[in] = out; table[-in] = -out; + } + /* Clamp the rest to final out value (which is (MAXJSAMPLE+1)/8) */ + for (; in <= MAXJSAMPLE; in++) { + table[in] = out; table[-in] = -out; + } +#undef STEPSIZE +} + + +/* + * Finish up at the end of each pass. + */ + +METHODDEF(void) +finish_pass1 (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + + /* Select the representative colors and fill in cinfo->colormap */ + cinfo->colormap = cquantize->sv_colormap; + select_colors(cinfo, cquantize->desired); + /* Force next pass to zero the color index table */ + cquantize->needs_zeroed = TRUE; +} + + +METHODDEF(void) +finish_pass2 (j_decompress_ptr cinfo) +{ + /* no work */ +} + + +/* + * Initialize for each processing pass. + */ + +METHODDEF(void) +start_pass_2_quant (j_decompress_ptr cinfo, boolean is_pre_scan) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + hist3d histogram = cquantize->histogram; + int i; + + /* Only F-S dithering or no dithering is supported. */ + /* If user asks for ordered dither, give him F-S. */ + if (cinfo->dither_mode != JDITHER_NONE) + cinfo->dither_mode = JDITHER_FS; + + if (is_pre_scan) { + /* Set up method pointers */ + cquantize->pub.color_quantize = prescan_quantize; + cquantize->pub.finish_pass = finish_pass1; + cquantize->needs_zeroed = TRUE; /* Always zero histogram */ + } else { + /* Set up method pointers */ + if (cinfo->dither_mode == JDITHER_FS) + cquantize->pub.color_quantize = pass2_fs_dither; + else + cquantize->pub.color_quantize = pass2_no_dither; + cquantize->pub.finish_pass = finish_pass2; + + /* Make sure color count is acceptable */ + i = cinfo->actual_number_of_colors; + if (i < 1) + ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, 1); + if (i > MAXNUMCOLORS) + ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXNUMCOLORS); + + if (cinfo->dither_mode == JDITHER_FS) { + size_t arraysize = (size_t) ((cinfo->output_width + 2) * + (3 * SIZEOF(FSERROR))); + /* Allocate Floyd-Steinberg workspace if we didn't already. */ + if (cquantize->fserrors == NULL) + cquantize->fserrors = (FSERRPTR) (*cinfo->mem->alloc_large) + ((j_common_ptr) cinfo, JPOOL_IMAGE, arraysize); + /* Initialize the propagated errors to zero. */ + jzero_far((void FAR *) cquantize->fserrors, arraysize); + /* Make the error-limit table if we didn't already. */ + if (cquantize->error_limiter == NULL) + init_error_limit(cinfo); + cquantize->on_odd_row = FALSE; + } + + } + /* Zero the histogram or inverse color map, if necessary */ + if (cquantize->needs_zeroed) { + for (i = 0; i < HIST_C0_ELEMS; i++) { + jzero_far((void FAR *) histogram[i], + HIST_C1_ELEMS*HIST_C2_ELEMS * SIZEOF(histcell)); + } + cquantize->needs_zeroed = FALSE; + } +} + + +/* + * Switch to a new external colormap between output passes. + */ + +METHODDEF(void) +new_color_map_2_quant (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + + /* Reset the inverse color map */ + cquantize->needs_zeroed = TRUE; +} + + +/* + * Module initialization routine for 2-pass color quantization. + */ + +GLOBAL(void) +jinit_2pass_quantizer (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize; + int i; + + cquantize = (my_cquantize_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_cquantizer)); + cinfo->cquantize = (struct jpeg_color_quantizer *) cquantize; + cquantize->pub.start_pass = start_pass_2_quant; + cquantize->pub.new_color_map = new_color_map_2_quant; + cquantize->fserrors = NULL; /* flag optional arrays not allocated */ + cquantize->error_limiter = NULL; + + /* Make sure jdmaster didn't give me a case I can't handle */ + if (cinfo->out_color_components != 3) + ERREXIT(cinfo, JERR_NOTIMPL); + + /* Allocate the histogram/inverse colormap storage */ + cquantize->histogram = (hist3d) (*cinfo->mem->alloc_small) + ((j_common_ptr) cinfo, JPOOL_IMAGE, HIST_C0_ELEMS * SIZEOF(hist2d)); + for (i = 0; i < HIST_C0_ELEMS; i++) { + cquantize->histogram[i] = (hist2d) (*cinfo->mem->alloc_large) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + HIST_C1_ELEMS*HIST_C2_ELEMS * SIZEOF(histcell)); + } + cquantize->needs_zeroed = TRUE; /* histogram is garbage now */ + + /* Allocate storage for the completed colormap, if required. + * We do this now since it is FAR storage and may affect + * the memory manager's space calculations. + */ + if (cinfo->enable_2pass_quant) { + /* Make sure color count is acceptable */ + int desired = cinfo->desired_number_of_colors; + /* Lower bound on # of colors ... somewhat arbitrary as long as > 0 */ + if (desired < 8) + ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, 8); + /* Make sure colormap indexes can be represented by JSAMPLEs */ + if (desired > MAXNUMCOLORS) + ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXNUMCOLORS); + cquantize->sv_colormap = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo,JPOOL_IMAGE, (JDIMENSION) desired, (JDIMENSION) 3); + cquantize->desired = desired; + } else + cquantize->sv_colormap = NULL; + + /* Only F-S dithering or no dithering is supported. */ + /* If user asks for ordered dither, give him F-S. */ + if (cinfo->dither_mode != JDITHER_NONE) + cinfo->dither_mode = JDITHER_FS; + + /* Allocate Floyd-Steinberg workspace if necessary. + * This isn't really needed until pass 2, but again it is FAR storage. + * Although we will cope with a later change in dither_mode, + * we do not promise to honor max_memory_to_use if dither_mode changes. + */ + if (cinfo->dither_mode == JDITHER_FS) { + cquantize->fserrors = (FSERRPTR) (*cinfo->mem->alloc_large) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (size_t) ((cinfo->output_width + 2) * (3 * SIZEOF(FSERROR)))); + /* Might as well create the error-limiting table too. */ + init_error_limit(cinfo); + } +} + +#endif /* QUANT_2PASS_SUPPORTED */ diff --git a/jpeg/JUTILS.C b/jpeg/JUTILS.C new file mode 100644 index 0000000..f5f8850 --- /dev/null +++ b/jpeg/JUTILS.C @@ -0,0 +1,179 @@ +/* + * jutils.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains tables and miscellaneous utility routines needed + * for both compression and decompression. + * Note we prefix all global names with "j" to minimize conflicts with + * a surrounding application. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* + * jpeg_zigzag_order[i] is the zigzag-order position of the i'th element + * of a DCT block read in natural order (left to right, top to bottom). + */ + +#if 0 /* This table is not actually needed in v6a */ + +const int jpeg_zigzag_order[DCTSIZE2] = { + 0, 1, 5, 6, 14, 15, 27, 28, + 2, 4, 7, 13, 16, 26, 29, 42, + 3, 8, 12, 17, 25, 30, 41, 43, + 9, 11, 18, 24, 31, 40, 44, 53, + 10, 19, 23, 32, 39, 45, 52, 54, + 20, 22, 33, 38, 46, 51, 55, 60, + 21, 34, 37, 47, 50, 56, 59, 61, + 35, 36, 48, 49, 57, 58, 62, 63 +}; + +#endif + +/* + * jpeg_natural_order[i] is the natural-order position of the i'th element + * of zigzag order. + * + * When reading corrupted data, the Huffman decoders could attempt + * to reference an entry beyond the end of this array (if the decoded + * zero run length reaches past the end of the block). To prevent + * wild stores without adding an inner-loop test, we put some extra + * "63"s after the real entries. This will cause the extra coefficient + * to be stored in location 63 of the block, not somewhere random. + * The worst case would be a run-length of 15, which means we need 16 + * fake entries. + */ + +const int jpeg_natural_order[DCTSIZE2+16] = { + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, + 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, + 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, + 53, 60, 61, 54, 47, 55, 62, 63, + 63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */ + 63, 63, 63, 63, 63, 63, 63, 63 +}; + + +/* + * Arithmetic utilities + */ + +GLOBAL(long) +jdiv_round_up (long a, long b) +/* Compute a/b rounded up to next integer, ie, ceil(a/b) */ +/* Assumes a >= 0, b > 0 */ +{ + return (a + b - 1L) / b; +} + + +GLOBAL(long) +jround_up (long a, long b) +/* Compute a rounded up to next multiple of b, ie, ceil(a/b)*b */ +/* Assumes a >= 0, b > 0 */ +{ + a += b - 1L; + return a - (a % b); +} + + +/* On normal machines we can apply MEMCOPY() and MEMZERO() to sample arrays + * and coefficient-block arrays. This won't work on 80x86 because the arrays + * are FAR and we're assuming a small-pointer memory model. However, some + * DOS compilers provide far-pointer versions of memcpy() and memset() even + * in the small-model libraries. These will be used if USE_FMEM is defined. + * Otherwise, the routines below do it the hard way. (The performance cost + * is not all that great, because these routines aren't very heavily used.) + */ + +#ifndef NEED_FAR_POINTERS /* normal case, same as regular macros */ +#define FMEMCOPY(dest,src,size) MEMCOPY(dest,src,size) +#define FMEMZERO(target,size) MEMZERO(target,size) +#else /* 80x86 case, define if we can */ +#ifdef USE_FMEM +#define FMEMCOPY(dest,src,size) _fmemcpy((void FAR *)(dest), (const void FAR *)(src), (size_t)(size)) +#define FMEMZERO(target,size) _fmemset((void FAR *)(target), 0, (size_t)(size)) +#endif +#endif + + +GLOBAL(void) +jcopy_sample_rows (JSAMPARRAY input_array, int source_row, + JSAMPARRAY output_array, int dest_row, + int num_rows, JDIMENSION num_cols) +/* Copy some rows of samples from one place to another. + * num_rows rows are copied from input_array[source_row++] + * to output_array[dest_row++]; these areas may overlap for duplication. + * The source and destination arrays must be at least as wide as num_cols. + */ +{ + register JSAMPROW inptr, outptr; +#ifdef FMEMCOPY + register size_t count = (size_t) (num_cols * SIZEOF(JSAMPLE)); +#else + register JDIMENSION count; +#endif + register int row; + + input_array += source_row; + output_array += dest_row; + + for (row = num_rows; row > 0; row--) { + inptr = *input_array++; + outptr = *output_array++; +#ifdef FMEMCOPY + FMEMCOPY(outptr, inptr, count); +#else + for (count = num_cols; count > 0; count--) + *outptr++ = *inptr++; /* needn't bother with GETJSAMPLE() here */ +#endif + } +} + + +GLOBAL(void) +jcopy_block_row (JBLOCKROW input_row, JBLOCKROW output_row, + JDIMENSION num_blocks) +/* Copy a row of coefficient blocks from one place to another. */ +{ +#ifdef FMEMCOPY + FMEMCOPY(output_row, input_row, num_blocks * (DCTSIZE2 * SIZEOF(JCOEF))); +#else + register JCOEFPTR inptr, outptr; + register long count; + + inptr = (JCOEFPTR) input_row; + outptr = (JCOEFPTR) output_row; + for (count = (long) num_blocks * DCTSIZE2; count > 0; count--) { + *outptr++ = *inptr++; + } +#endif +} + + +GLOBAL(void) +jzero_far (void FAR * target, size_t bytestozero) +/* Zero out a chunk of FAR memory. */ +/* This might be sample-array data, block-array data, or alloc_large data. */ +{ +#ifdef FMEMZERO + FMEMZERO(target, bytestozero); +#else + register char FAR * ptr = (char FAR *) target; + register size_t count; + + for (count = bytestozero; count > 0; count--) { + *ptr++ = 0; + } +#endif +} diff --git a/jpeg/JVERSION.H b/jpeg/JVERSION.H new file mode 100644 index 0000000..6472c58 --- /dev/null +++ b/jpeg/JVERSION.H @@ -0,0 +1,14 @@ +/* + * jversion.h + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains software version identification. + */ + + +#define JVERSION "6b 27-Mar-1998" + +#define JCOPYRIGHT "Copyright (C) 1998, Thomas G. Lane" diff --git a/jpeg/Jcdctmgr.c b/jpeg/Jcdctmgr.c new file mode 100644 index 0000000..07a3ad5 --- /dev/null +++ b/jpeg/Jcdctmgr.c @@ -0,0 +1,387 @@ +/* + * jcdctmgr.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the forward-DCT management logic. + * This code selects a particular DCT implementation to be used, + * and it performs related housekeeping chores including coefficient + * quantization. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jdct.h" /* Private declarations for DCT subsystem */ + + +/* Private subobject for this module */ + +typedef struct { + struct jpeg_forward_dct pub; /* public fields */ + + /* Pointer to the DCT routine actually in use */ + forward_DCT_method_ptr do_dct; + + /* The actual post-DCT divisors --- not identical to the quant table + * entries, because of scaling (especially for an unnormalized DCT). + * Each table is given in normal array order. + */ + DCTELEM * divisors[NUM_QUANT_TBLS]; + +#ifdef DCT_FLOAT_SUPPORTED + /* Same as above for the floating-point case. */ + float_DCT_method_ptr do_float_dct; + FAST_FLOAT * float_divisors[NUM_QUANT_TBLS]; +#endif +} my_fdct_controller; + +typedef my_fdct_controller * my_fdct_ptr; + + +/* + * Initialize for a processing pass. + * Verify that all referenced Q-tables are present, and set up + * the divisor table for each one. + * In the current implementation, DCT of all components is done during + * the first pass, even if only some components will be output in the + * first scan. Hence all components should be examined here. + */ + +METHODDEF(void) +start_pass_fdctmgr (j_compress_ptr cinfo) +{ + my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct; + int ci, qtblno, i; + jpeg_component_info *compptr; + JQUANT_TBL * qtbl; + DCTELEM * dtbl; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + qtblno = compptr->quant_tbl_no; + /* Make sure specified quantization table is present */ + if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS || + cinfo->quant_tbl_ptrs[qtblno] == NULL) + ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno); + qtbl = cinfo->quant_tbl_ptrs[qtblno]; + /* Compute divisors for this quant table */ + /* We may do this more than once for same table, but it's not a big deal */ + switch (cinfo->dct_method) { +#ifdef DCT_ISLOW_SUPPORTED + case JDCT_ISLOW: + /* For LL&M IDCT method, divisors are equal to raw quantization + * coefficients multiplied by 8 (to counteract scaling). + */ + if (fdct->divisors[qtblno] == NULL) { + fdct->divisors[qtblno] = (DCTELEM *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + DCTSIZE2 * SIZEOF(DCTELEM)); + } + dtbl = fdct->divisors[qtblno]; + for (i = 0; i < DCTSIZE2; i++) { + dtbl[i] = ((DCTELEM) qtbl->quantval[i]) << 3; + } + break; +#endif +#ifdef DCT_IFAST_SUPPORTED + case JDCT_IFAST: + { + /* For AA&N IDCT method, divisors are equal to quantization + * coefficients scaled by scalefactor[row]*scalefactor[col], where + * scalefactor[0] = 1 + * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 + * We apply a further scale factor of 8. + */ +#define CONST_BITS 14 + static const INT16 aanscales[DCTSIZE2] = { + /* precomputed values scaled up by 14 bits */ + 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, + 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270, + 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906, + 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315, + 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, + 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552, + 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446, + 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247 + }; + SHIFT_TEMPS + + if (fdct->divisors[qtblno] == NULL) { + fdct->divisors[qtblno] = (DCTELEM *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + DCTSIZE2 * SIZEOF(DCTELEM)); + } + dtbl = fdct->divisors[qtblno]; + for (i = 0; i < DCTSIZE2; i++) { + dtbl[i] = (DCTELEM) + DESCALE(MULTIPLY16V16((INT32) qtbl->quantval[i], + (INT32) aanscales[i]), + CONST_BITS-3); + } + } + break; +#endif +#ifdef DCT_FLOAT_SUPPORTED + case JDCT_FLOAT: + { + /* For float AA&N IDCT method, divisors are equal to quantization + * coefficients scaled by scalefactor[row]*scalefactor[col], where + * scalefactor[0] = 1 + * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 + * We apply a further scale factor of 8. + * What's actually stored is 1/divisor so that the inner loop can + * use a multiplication rather than a division. + */ + FAST_FLOAT * fdtbl; + int row, col; + static const double aanscalefactor[DCTSIZE] = { + 1.0, 1.387039845, 1.306562965, 1.175875602, + 1.0, 0.785694958, 0.541196100, 0.275899379 + }; + + if (fdct->float_divisors[qtblno] == NULL) { + fdct->float_divisors[qtblno] = (FAST_FLOAT *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + DCTSIZE2 * SIZEOF(FAST_FLOAT)); + } + fdtbl = fdct->float_divisors[qtblno]; + i = 0; + for (row = 0; row < DCTSIZE; row++) { + for (col = 0; col < DCTSIZE; col++) { + fdtbl[i] = (FAST_FLOAT) + (1.0 / (((double) qtbl->quantval[i] * + aanscalefactor[row] * aanscalefactor[col] * 8.0))); + i++; + } + } + } + break; +#endif + default: + ERREXIT(cinfo, JERR_NOT_COMPILED); + break; + } + } +} + + +/* + * Perform forward DCT on one or more blocks of a component. + * + * The input samples are taken from the sample_data[] array starting at + * position start_row/start_col, and moving to the right for any additional + * blocks. The quantized coefficients are returned in coef_blocks[]. + */ + +METHODDEF(void) +forward_DCT (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY sample_data, JBLOCKROW coef_blocks, + JDIMENSION start_row, JDIMENSION start_col, + JDIMENSION num_blocks) +/* This version is used for integer DCT implementations. */ +{ + /* This routine is heavily used, so it's worth coding it tightly. */ + my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct; + forward_DCT_method_ptr do_dct = fdct->do_dct; + DCTELEM * divisors = fdct->divisors[compptr->quant_tbl_no]; + DCTELEM workspace[DCTSIZE2]; /* work area for FDCT subroutine */ + JDIMENSION bi; + + sample_data += start_row; /* fold in the vertical offset once */ + + for (bi = 0; bi < num_blocks; bi++, start_col += DCTSIZE) { + /* Load data into workspace, applying unsigned->signed conversion */ + { register DCTELEM *workspaceptr; + register JSAMPROW elemptr; + register int elemr; + + workspaceptr = workspace; + for (elemr = 0; elemr < DCTSIZE; elemr++) { + elemptr = sample_data[elemr] + start_col; +#if DCTSIZE == 8 /* unroll the inner loop */ + *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; + *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; + *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; + *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; + *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; + *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; + *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; + *workspaceptr++ = GETJSAMPLE(*elemptr) - CENTERJSAMPLE; +#else + { register int elemc; + for (elemc = DCTSIZE; elemc > 0; elemc--) { + *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; + } + } +#endif + } + } + + /* Perform the DCT */ + (*do_dct) (workspace); + + /* Quantize/descale the coefficients, and store into coef_blocks[] */ + { register DCTELEM temp, qval; + register int i; + register JCOEFPTR output_ptr = coef_blocks[bi]; + + for (i = 0; i < DCTSIZE2; i++) { + qval = divisors[i]; + temp = workspace[i]; + /* Divide the coefficient value by qval, ensuring proper rounding. + * Since C does not specify the direction of rounding for negative + * quotients, we have to force the dividend positive for portability. + * + * In most files, at least half of the output values will be zero + * (at default quantization settings, more like three-quarters...) + * so we should ensure that this case is fast. On many machines, + * a comparison is enough cheaper than a divide to make a special test + * a win. Since both inputs will be nonnegative, we need only test + * for a < b to discover whether a/b is 0. + * If your machine's division is fast enough, define FAST_DIVIDE. + */ +#ifdef FAST_DIVIDE +#define DIVIDE_BY(a,b) a /= b +#else +#define DIVIDE_BY(a,b) if (a >= b) a /= b; else a = 0 +#endif + if (temp < 0) { + temp = -temp; + temp += qval>>1; /* for rounding */ + DIVIDE_BY(temp, qval); + temp = -temp; + } else { + temp += qval>>1; /* for rounding */ + DIVIDE_BY(temp, qval); + } + output_ptr[i] = (JCOEF) temp; + } + } + } +} + + +#ifdef DCT_FLOAT_SUPPORTED + +METHODDEF(void) +forward_DCT_float (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY sample_data, JBLOCKROW coef_blocks, + JDIMENSION start_row, JDIMENSION start_col, + JDIMENSION num_blocks) +/* This version is used for floating-point DCT implementations. */ +{ + /* This routine is heavily used, so it's worth coding it tightly. */ + my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct; + float_DCT_method_ptr do_dct = fdct->do_float_dct; + FAST_FLOAT * divisors = fdct->float_divisors[compptr->quant_tbl_no]; + FAST_FLOAT workspace[DCTSIZE2]; /* work area for FDCT subroutine */ + JDIMENSION bi; + + sample_data += start_row; /* fold in the vertical offset once */ + + for (bi = 0; bi < num_blocks; bi++, start_col += DCTSIZE) { + /* Load data into workspace, applying unsigned->signed conversion */ + { register FAST_FLOAT *workspaceptr; + register JSAMPROW elemptr; + register int elemr; + + workspaceptr = workspace; + for (elemr = 0; elemr < DCTSIZE; elemr++) { + elemptr = sample_data[elemr] + start_col; +#if DCTSIZE == 8 /* unroll the inner loop */ + *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr) - CENTERJSAMPLE); +#else + { register int elemc; + for (elemc = DCTSIZE; elemc > 0; elemc--) { + *workspaceptr++ = (FAST_FLOAT) + (GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); + } + } +#endif + } + } + + /* Perform the DCT */ + (*do_dct) (workspace); + + /* Quantize/descale the coefficients, and store into coef_blocks[] */ + { register FAST_FLOAT temp; + register int i; + register JCOEFPTR output_ptr = coef_blocks[bi]; + + for (i = 0; i < DCTSIZE2; i++) { + /* Apply the quantization and scaling factor */ + temp = workspace[i] * divisors[i]; + /* Round to nearest integer. + * Since C does not specify the direction of rounding for negative + * quotients, we have to force the dividend positive for portability. + * The maximum coefficient size is +-16K (for 12-bit data), so this + * code should work for either 16-bit or 32-bit ints. + */ + output_ptr[i] = (JCOEF) ((int) (temp + (FAST_FLOAT) 16384.5) - 16384); + } + } + } +} + +#endif /* DCT_FLOAT_SUPPORTED */ + + +/* + * Initialize FDCT manager. + */ + +GLOBAL(void) +jinit_forward_dct (j_compress_ptr cinfo) +{ + my_fdct_ptr fdct; + int i; + + fdct = (my_fdct_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_fdct_controller)); + cinfo->fdct = (struct jpeg_forward_dct *) fdct; + fdct->pub.start_pass = start_pass_fdctmgr; + + switch (cinfo->dct_method) { +#ifdef DCT_ISLOW_SUPPORTED + case JDCT_ISLOW: + fdct->pub.forward_DCT = forward_DCT; + fdct->do_dct = jpeg_fdct_islow; + break; +#endif +#ifdef DCT_IFAST_SUPPORTED + case JDCT_IFAST: + fdct->pub.forward_DCT = forward_DCT; + fdct->do_dct = jpeg_fdct_ifast; + break; +#endif +#ifdef DCT_FLOAT_SUPPORTED + case JDCT_FLOAT: + fdct->pub.forward_DCT = forward_DCT_float; + fdct->do_float_dct = jpeg_fdct_float; + break; +#endif + default: + ERREXIT(cinfo, JERR_NOT_COMPILED); + break; + } + + /* Mark divisor tables unallocated */ + for (i = 0; i < NUM_QUANT_TBLS; i++) { + fdct->divisors[i] = NULL; +#ifdef DCT_FLOAT_SUPPORTED + fdct->float_divisors[i] = NULL; +#endif + } +} diff --git a/jpeg/Jchuff.c b/jpeg/Jchuff.c new file mode 100644 index 0000000..2f956c3 --- /dev/null +++ b/jpeg/Jchuff.c @@ -0,0 +1,909 @@ +/* + * jchuff.c + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains Huffman entropy encoding routines. + * + * Much of the complexity here has to do with supporting output suspension. + * If the data destination module demands suspension, we want to be able to + * back up to the start of the current MCU. To do this, we copy state + * variables into local working storage, and update them back to the + * permanent JPEG objects only upon successful completion of an MCU. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jchuff.h" /* Declarations shared with jcphuff.c */ + + +/* Expanded entropy encoder object for Huffman encoding. + * + * The savable_state subrecord contains fields that change within an MCU, + * but must not be updated permanently until we complete the MCU. + */ + +typedef struct { + INT32 put_buffer; /* current bit-accumulation buffer */ + int put_bits; /* # of bits now in it */ + int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ +} savable_state; + +/* This macro is to work around compilers with missing or broken + * structure assignment. You'll need to fix this code if you have + * such a compiler and you change MAX_COMPS_IN_SCAN. + */ + +#ifndef NO_STRUCT_ASSIGN +#define ASSIGN_STATE(dest,src) ((dest) = (src)) +#else +#if MAX_COMPS_IN_SCAN == 4 +#define ASSIGN_STATE(dest,src) \ + ((dest).put_buffer = (src).put_buffer, \ + (dest).put_bits = (src).put_bits, \ + (dest).last_dc_val[0] = (src).last_dc_val[0], \ + (dest).last_dc_val[1] = (src).last_dc_val[1], \ + (dest).last_dc_val[2] = (src).last_dc_val[2], \ + (dest).last_dc_val[3] = (src).last_dc_val[3]) +#endif +#endif + + +typedef struct { + struct jpeg_entropy_encoder pub; /* public fields */ + + savable_state saved; /* Bit buffer & DC state at start of MCU */ + + /* These fields are NOT loaded into local working state. */ + unsigned int restarts_to_go; /* MCUs left in this restart interval */ + int next_restart_num; /* next restart number to write (0-7) */ + + /* Pointers to derived tables (these workspaces have image lifespan) */ + c_derived_tbl * dc_derived_tbls[NUM_HUFF_TBLS]; + c_derived_tbl * ac_derived_tbls[NUM_HUFF_TBLS]; + +#ifdef ENTROPY_OPT_SUPPORTED /* Statistics tables for optimization */ + long * dc_count_ptrs[NUM_HUFF_TBLS]; + long * ac_count_ptrs[NUM_HUFF_TBLS]; +#endif +} huff_entropy_encoder; + +typedef huff_entropy_encoder * huff_entropy_ptr; + +/* Working state while writing an MCU. + * This struct contains all the fields that are needed by subroutines. + */ + +typedef struct { + JOCTET * next_output_byte; /* => next byte to write in buffer */ + size_t free_in_buffer; /* # of byte spaces remaining in buffer */ + savable_state cur; /* Current bit buffer & DC state */ + j_compress_ptr cinfo; /* dump_buffer needs access to this */ +} working_state; + + +/* Forward declarations */ +METHODDEF(boolean) encode_mcu_huff JPP((j_compress_ptr cinfo, + JBLOCKROW *MCU_data)); +METHODDEF(void) finish_pass_huff JPP((j_compress_ptr cinfo)); +#ifdef ENTROPY_OPT_SUPPORTED +METHODDEF(boolean) encode_mcu_gather JPP((j_compress_ptr cinfo, + JBLOCKROW *MCU_data)); +METHODDEF(void) finish_pass_gather JPP((j_compress_ptr cinfo)); +#endif + + +/* + * Initialize for a Huffman-compressed scan. + * If gather_statistics is TRUE, we do not output anything during the scan, + * just count the Huffman symbols used and generate Huffman code tables. + */ + +METHODDEF(void) +start_pass_huff (j_compress_ptr cinfo, boolean gather_statistics) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + int ci, dctbl, actbl; + jpeg_component_info * compptr; + + if (gather_statistics) { +#ifdef ENTROPY_OPT_SUPPORTED + entropy->pub.encode_mcu = encode_mcu_gather; + entropy->pub.finish_pass = finish_pass_gather; +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else { + entropy->pub.encode_mcu = encode_mcu_huff; + entropy->pub.finish_pass = finish_pass_huff; + } + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + dctbl = compptr->dc_tbl_no; + actbl = compptr->ac_tbl_no; + if (gather_statistics) { +#ifdef ENTROPY_OPT_SUPPORTED + /* Check for invalid table indexes */ + /* (make_c_derived_tbl does this in the other path) */ + if (dctbl < 0 || dctbl >= NUM_HUFF_TBLS) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, dctbl); + if (actbl < 0 || actbl >= NUM_HUFF_TBLS) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, actbl); + /* Allocate and zero the statistics tables */ + /* Note that jpeg_gen_optimal_table expects 257 entries in each table! */ + if (entropy->dc_count_ptrs[dctbl] == NULL) + entropy->dc_count_ptrs[dctbl] = (long *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + 257 * SIZEOF(long)); + MEMZERO(entropy->dc_count_ptrs[dctbl], 257 * SIZEOF(long)); + if (entropy->ac_count_ptrs[actbl] == NULL) + entropy->ac_count_ptrs[actbl] = (long *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + 257 * SIZEOF(long)); + MEMZERO(entropy->ac_count_ptrs[actbl], 257 * SIZEOF(long)); +#endif + } else { + /* Compute derived values for Huffman tables */ + /* We may do this more than once for a table, but it's not expensive */ + jpeg_make_c_derived_tbl(cinfo, TRUE, dctbl, + & entropy->dc_derived_tbls[dctbl]); + jpeg_make_c_derived_tbl(cinfo, FALSE, actbl, + & entropy->ac_derived_tbls[actbl]); + } + /* Initialize DC predictions to 0 */ + entropy->saved.last_dc_val[ci] = 0; + } + + /* Initialize bit buffer to empty */ + entropy->saved.put_buffer = 0; + entropy->saved.put_bits = 0; + + /* Initialize restart stuff */ + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num = 0; +} + + +/* + * Compute the derived values for a Huffman table. + * This routine also performs some validation checks on the table. + * + * Note this is also used by jcphuff.c. + */ + +GLOBAL(void) +jpeg_make_c_derived_tbl (j_compress_ptr cinfo, boolean isDC, int tblno, + c_derived_tbl ** pdtbl) +{ + JHUFF_TBL *htbl; + c_derived_tbl *dtbl; + int p, i, l, lastp, si, maxsymbol; + char huffsize[257]; + unsigned int huffcode[257]; + unsigned int code; + + /* Note that huffsize[] and huffcode[] are filled in code-length order, + * paralleling the order of the symbols themselves in htbl->huffval[]. + */ + + /* Find the input Huffman table */ + if (tblno < 0 || tblno >= NUM_HUFF_TBLS) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno); + htbl = + isDC ? cinfo->dc_huff_tbl_ptrs[tblno] : cinfo->ac_huff_tbl_ptrs[tblno]; + if (htbl == NULL) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno); + + /* Allocate a workspace if we haven't already done so. */ + if (*pdtbl == NULL) + *pdtbl = (c_derived_tbl *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(c_derived_tbl)); + dtbl = *pdtbl; + + /* Figure C.1: make table of Huffman code length for each symbol */ + + p = 0; + for (l = 1; l <= 16; l++) { + i = (int) htbl->bits[l]; + if (i < 0 || p + i > 256) /* protect against table overrun */ + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + while (i--) + huffsize[p++] = (char) l; + } + huffsize[p] = 0; + lastp = p; + + /* Figure C.2: generate the codes themselves */ + /* We also validate that the counts represent a legal Huffman code tree. */ + + code = 0; + si = huffsize[0]; + p = 0; + while (huffsize[p]) { + while (((int) huffsize[p]) == si) { + huffcode[p++] = code; + code++; + } + /* code is now 1 more than the last code used for codelength si; but + * it must still fit in si bits, since no code is allowed to be all ones. + */ + if (((INT32) code) >= (((INT32) 1) << si)) + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + code <<= 1; + si++; + } + + /* Figure C.3: generate encoding tables */ + /* These are code and size indexed by symbol value */ + + /* Set all codeless symbols to have code length 0; + * this lets us detect duplicate VAL entries here, and later + * allows emit_bits to detect any attempt to emit such symbols. + */ + MEMZERO(dtbl->ehufsi, SIZEOF(dtbl->ehufsi)); + + /* This is also a convenient place to check for out-of-range + * and duplicated VAL entries. We allow 0..255 for AC symbols + * but only 0..15 for DC. (We could constrain them further + * based on data depth and mode, but this seems enough.) + */ + maxsymbol = isDC ? 15 : 255; + + for (p = 0; p < lastp; p++) { + i = htbl->huffval[p]; + if (i < 0 || i > maxsymbol || dtbl->ehufsi[i]) + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + dtbl->ehufco[i] = huffcode[p]; + dtbl->ehufsi[i] = huffsize[p]; + } +} + + +/* Outputting bytes to the file */ + +/* Emit a byte, taking 'action' if must suspend. */ +#define emit_byte(state,val,action) \ + { *(state)->next_output_byte++ = (JOCTET) (val); \ + if (--(state)->free_in_buffer == 0) \ + if (! dump_buffer(state)) \ + { action; } } + + +LOCAL(boolean) +dump_buffer (working_state * state) +/* Empty the output buffer; return TRUE if successful, FALSE if must suspend */ +{ + struct jpeg_destination_mgr * dest = state->cinfo->dest; + + if (! (*dest->empty_output_buffer) (state->cinfo)) + return FALSE; + /* After a successful buffer dump, must reset buffer pointers */ + state->next_output_byte = dest->next_output_byte; + state->free_in_buffer = dest->free_in_buffer; + return TRUE; +} + + +/* Outputting bits to the file */ + +/* Only the right 24 bits of put_buffer are used; the valid bits are + * left-justified in this part. At most 16 bits can be passed to emit_bits + * in one call, and we never retain more than 7 bits in put_buffer + * between calls, so 24 bits are sufficient. + */ + +INLINE +LOCAL(boolean) +emit_bits (working_state * state, unsigned int code, int size) +/* Emit some bits; return TRUE if successful, FALSE if must suspend */ +{ + /* This routine is heavily used, so it's worth coding tightly. */ + register INT32 put_buffer = (INT32) code; + register int put_bits = state->cur.put_bits; + + /* if size is 0, caller used an invalid Huffman table entry */ + if (size == 0) + ERREXIT(state->cinfo, JERR_HUFF_MISSING_CODE); + + put_buffer &= (((INT32) 1)<cur.put_buffer; /* and merge with old buffer contents */ + + while (put_bits >= 8) { + int c = (int) ((put_buffer >> 16) & 0xFF); + + emit_byte(state, c, return FALSE); + if (c == 0xFF) { /* need to stuff a zero byte? */ + emit_byte(state, 0, return FALSE); + } + put_buffer <<= 8; + put_bits -= 8; + } + + state->cur.put_buffer = put_buffer; /* update state variables */ + state->cur.put_bits = put_bits; + + return TRUE; +} + + +LOCAL(boolean) +flush_bits (working_state * state) +{ + if (! emit_bits(state, 0x7F, 7)) /* fill any partial byte with ones */ + return FALSE; + state->cur.put_buffer = 0; /* and reset bit-buffer to empty */ + state->cur.put_bits = 0; + return TRUE; +} + + +/* Encode a single block's worth of coefficients */ + +LOCAL(boolean) +encode_one_block (working_state * state, JCOEFPTR block, int last_dc_val, + c_derived_tbl *dctbl, c_derived_tbl *actbl) +{ + register int temp, temp2; + register int nbits; + register int k, r, i; + + /* Encode the DC coefficient difference per section F.1.2.1 */ + + temp = temp2 = block[0] - last_dc_val; + + if (temp < 0) { + temp = -temp; /* temp is abs value of input */ + /* For a negative input, want temp2 = bitwise complement of abs(input) */ + /* This code assumes we are on a two's complement machine */ + temp2--; + } + + /* Find the number of bits needed for the magnitude of the coefficient */ + nbits = 0; + while (temp) { + nbits++; + temp >>= 1; + } + /* Check for out-of-range coefficient values. + * Since we're encoding a difference, the range limit is twice as much. + */ + if (nbits > MAX_COEF_BITS+1) + ERREXIT(state->cinfo, JERR_BAD_DCT_COEF); + + /* Emit the Huffman-coded symbol for the number of bits */ + if (! emit_bits(state, dctbl->ehufco[nbits], dctbl->ehufsi[nbits])) + return FALSE; + + /* Emit that number of bits of the value, if positive, */ + /* or the complement of its magnitude, if negative. */ + if (nbits) /* emit_bits rejects calls with size 0 */ + if (! emit_bits(state, (unsigned int) temp2, nbits)) + return FALSE; + + /* Encode the AC coefficients per section F.1.2.2 */ + + r = 0; /* r = run length of zeros */ + + for (k = 1; k < DCTSIZE2; k++) { + if ((temp = block[jpeg_natural_order[k]]) == 0) { + r++; + } else { + /* if run length > 15, must emit special run-length-16 codes (0xF0) */ + while (r > 15) { + if (! emit_bits(state, actbl->ehufco[0xF0], actbl->ehufsi[0xF0])) + return FALSE; + r -= 16; + } + + temp2 = temp; + if (temp < 0) { + temp = -temp; /* temp is abs value of input */ + /* This code assumes we are on a two's complement machine */ + temp2--; + } + + /* Find the number of bits needed for the magnitude of the coefficient */ + nbits = 1; /* there must be at least one 1 bit */ + while ((temp >>= 1)) + nbits++; + /* Check for out-of-range coefficient values */ + if (nbits > MAX_COEF_BITS) + ERREXIT(state->cinfo, JERR_BAD_DCT_COEF); + + /* Emit Huffman symbol for run length / number of bits */ + i = (r << 4) + nbits; + if (! emit_bits(state, actbl->ehufco[i], actbl->ehufsi[i])) + return FALSE; + + /* Emit that number of bits of the value, if positive, */ + /* or the complement of its magnitude, if negative. */ + if (! emit_bits(state, (unsigned int) temp2, nbits)) + return FALSE; + + r = 0; + } + } + + /* If the last coef(s) were zero, emit an end-of-block code */ + if (r > 0) + if (! emit_bits(state, actbl->ehufco[0], actbl->ehufsi[0])) + return FALSE; + + return TRUE; +} + + +/* + * Emit a restart marker & resynchronize predictions. + */ + +LOCAL(boolean) +emit_restart (working_state * state, int restart_num) +{ + int ci; + + if (! flush_bits(state)) + return FALSE; + + emit_byte(state, 0xFF, return FALSE); + emit_byte(state, JPEG_RST0 + restart_num, return FALSE); + + /* Re-initialize DC predictions to 0 */ + for (ci = 0; ci < state->cinfo->comps_in_scan; ci++) + state->cur.last_dc_val[ci] = 0; + + /* The restart counter is not updated until we successfully write the MCU. */ + + return TRUE; +} + + +/* + * Encode and output one MCU's worth of Huffman-compressed coefficients. + */ + +METHODDEF(boolean) +encode_mcu_huff (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + working_state state; + int blkn, ci; + jpeg_component_info * compptr; + + /* Load up working state */ + state.next_output_byte = cinfo->dest->next_output_byte; + state.free_in_buffer = cinfo->dest->free_in_buffer; + ASSIGN_STATE(state.cur, entropy->saved); + state.cinfo = cinfo; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! emit_restart(&state, entropy->next_restart_num)) + return FALSE; + } + + /* Encode the MCU data blocks */ + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + ci = cinfo->MCU_membership[blkn]; + compptr = cinfo->cur_comp_info[ci]; + if (! encode_one_block(&state, + MCU_data[blkn][0], state.cur.last_dc_val[ci], + entropy->dc_derived_tbls[compptr->dc_tbl_no], + entropy->ac_derived_tbls[compptr->ac_tbl_no])) + return FALSE; + /* Update last_dc_val */ + state.cur.last_dc_val[ci] = MCU_data[blkn][0][0]; + } + + /* Completed MCU, so update state */ + cinfo->dest->next_output_byte = state.next_output_byte; + cinfo->dest->free_in_buffer = state.free_in_buffer; + ASSIGN_STATE(entropy->saved, state.cur); + + /* Update restart-interval state too */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + return TRUE; +} + + +/* + * Finish up at the end of a Huffman-compressed scan. + */ + +METHODDEF(void) +finish_pass_huff (j_compress_ptr cinfo) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + working_state state; + + /* Load up working state ... flush_bits needs it */ + state.next_output_byte = cinfo->dest->next_output_byte; + state.free_in_buffer = cinfo->dest->free_in_buffer; + ASSIGN_STATE(state.cur, entropy->saved); + state.cinfo = cinfo; + + /* Flush out the last data */ + if (! flush_bits(&state)) + ERREXIT(cinfo, JERR_CANT_SUSPEND); + + /* Update state */ + cinfo->dest->next_output_byte = state.next_output_byte; + cinfo->dest->free_in_buffer = state.free_in_buffer; + ASSIGN_STATE(entropy->saved, state.cur); +} + + +/* + * Huffman coding optimization. + * + * We first scan the supplied data and count the number of uses of each symbol + * that is to be Huffman-coded. (This process MUST agree with the code above.) + * Then we build a Huffman coding tree for the observed counts. + * Symbols which are not needed at all for the particular image are not + * assigned any code, which saves space in the DHT marker as well as in + * the compressed data. + */ + +#ifdef ENTROPY_OPT_SUPPORTED + + +/* Process a single block's worth of coefficients */ + +LOCAL(void) +htest_one_block (j_compress_ptr cinfo, JCOEFPTR block, int last_dc_val, + long dc_counts[], long ac_counts[]) +{ + register int temp; + register int nbits; + register int k, r; + + /* Encode the DC coefficient difference per section F.1.2.1 */ + + temp = block[0] - last_dc_val; + if (temp < 0) + temp = -temp; + + /* Find the number of bits needed for the magnitude of the coefficient */ + nbits = 0; + while (temp) { + nbits++; + temp >>= 1; + } + /* Check for out-of-range coefficient values. + * Since we're encoding a difference, the range limit is twice as much. + */ + if (nbits > MAX_COEF_BITS+1) + ERREXIT(cinfo, JERR_BAD_DCT_COEF); + + /* Count the Huffman symbol for the number of bits */ + dc_counts[nbits]++; + + /* Encode the AC coefficients per section F.1.2.2 */ + + r = 0; /* r = run length of zeros */ + + for (k = 1; k < DCTSIZE2; k++) { + if ((temp = block[jpeg_natural_order[k]]) == 0) { + r++; + } else { + /* if run length > 15, must emit special run-length-16 codes (0xF0) */ + while (r > 15) { + ac_counts[0xF0]++; + r -= 16; + } + + /* Find the number of bits needed for the magnitude of the coefficient */ + if (temp < 0) + temp = -temp; + + /* Find the number of bits needed for the magnitude of the coefficient */ + nbits = 1; /* there must be at least one 1 bit */ + while ((temp >>= 1)) + nbits++; + /* Check for out-of-range coefficient values */ + if (nbits > MAX_COEF_BITS) + ERREXIT(cinfo, JERR_BAD_DCT_COEF); + + /* Count Huffman symbol for run length / number of bits */ + ac_counts[(r << 4) + nbits]++; + + r = 0; + } + } + + /* If the last coef(s) were zero, emit an end-of-block code */ + if (r > 0) + ac_counts[0]++; +} + + +/* + * Trial-encode one MCU's worth of Huffman-compressed coefficients. + * No data is actually output, so no suspension return is possible. + */ + +METHODDEF(boolean) +encode_mcu_gather (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + int blkn, ci; + jpeg_component_info * compptr; + + /* Take care of restart intervals if needed */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + /* Re-initialize DC predictions to 0 */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) + entropy->saved.last_dc_val[ci] = 0; + /* Update restart state */ + entropy->restarts_to_go = cinfo->restart_interval; + } + entropy->restarts_to_go--; + } + + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + ci = cinfo->MCU_membership[blkn]; + compptr = cinfo->cur_comp_info[ci]; + htest_one_block(cinfo, MCU_data[blkn][0], entropy->saved.last_dc_val[ci], + entropy->dc_count_ptrs[compptr->dc_tbl_no], + entropy->ac_count_ptrs[compptr->ac_tbl_no]); + entropy->saved.last_dc_val[ci] = MCU_data[blkn][0][0]; + } + + return TRUE; +} + + +/* + * Generate the best Huffman code table for the given counts, fill htbl. + * Note this is also used by jcphuff.c. + * + * The JPEG standard requires that no symbol be assigned a codeword of all + * one bits (so that padding bits added at the end of a compressed segment + * can't look like a valid code). Because of the canonical ordering of + * codewords, this just means that there must be an unused slot in the + * longest codeword length category. Section K.2 of the JPEG spec suggests + * reserving such a slot by pretending that symbol 256 is a valid symbol + * with count 1. In theory that's not optimal; giving it count zero but + * including it in the symbol set anyway should give a better Huffman code. + * But the theoretically better code actually seems to come out worse in + * practice, because it produces more all-ones bytes (which incur stuffed + * zero bytes in the final file). In any case the difference is tiny. + * + * The JPEG standard requires Huffman codes to be no more than 16 bits long. + * If some symbols have a very small but nonzero probability, the Huffman tree + * must be adjusted to meet the code length restriction. We currently use + * the adjustment method suggested in JPEG section K.2. This method is *not* + * optimal; it may not choose the best possible limited-length code. But + * typically only very-low-frequency symbols will be given less-than-optimal + * lengths, so the code is almost optimal. Experimental comparisons against + * an optimal limited-length-code algorithm indicate that the difference is + * microscopic --- usually less than a hundredth of a percent of total size. + * So the extra complexity of an optimal algorithm doesn't seem worthwhile. + */ + +GLOBAL(void) +jpeg_gen_optimal_table (j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[]) +{ +#define MAX_CLEN 32 /* assumed maximum initial code length */ + UINT8 bits[MAX_CLEN+1]; /* bits[k] = # of symbols with code length k */ + int codesize[257]; /* codesize[k] = code length of symbol k */ + int others[257]; /* next symbol in current branch of tree */ + int c1, c2; + int p, i, j; + long v; + + /* This algorithm is explained in section K.2 of the JPEG standard */ + + MEMZERO(bits, SIZEOF(bits)); + MEMZERO(codesize, SIZEOF(codesize)); + for (i = 0; i < 257; i++) + others[i] = -1; /* init links to empty */ + + freq[256] = 1; /* make sure 256 has a nonzero count */ + /* Including the pseudo-symbol 256 in the Huffman procedure guarantees + * that no real symbol is given code-value of all ones, because 256 + * will be placed last in the largest codeword category. + */ + + /* Huffman's basic algorithm to assign optimal code lengths to symbols */ + + for (;;) { + /* Find the smallest nonzero frequency, set c1 = its symbol */ + /* In case of ties, take the larger symbol number */ + c1 = -1; + v = 1000000000L; + for (i = 0; i <= 256; i++) { + if (freq[i] && freq[i] <= v) { + v = freq[i]; + c1 = i; + } + } + + /* Find the next smallest nonzero frequency, set c2 = its symbol */ + /* In case of ties, take the larger symbol number */ + c2 = -1; + v = 1000000000L; + for (i = 0; i <= 256; i++) { + if (freq[i] && freq[i] <= v && i != c1) { + v = freq[i]; + c2 = i; + } + } + + /* Done if we've merged everything into one frequency */ + if (c2 < 0) + break; + + /* Else merge the two counts/trees */ + freq[c1] += freq[c2]; + freq[c2] = 0; + + /* Increment the codesize of everything in c1's tree branch */ + codesize[c1]++; + while (others[c1] >= 0) { + c1 = others[c1]; + codesize[c1]++; + } + + others[c1] = c2; /* chain c2 onto c1's tree branch */ + + /* Increment the codesize of everything in c2's tree branch */ + codesize[c2]++; + while (others[c2] >= 0) { + c2 = others[c2]; + codesize[c2]++; + } + } + + /* Now count the number of symbols of each code length */ + for (i = 0; i <= 256; i++) { + if (codesize[i]) { + /* The JPEG standard seems to think that this can't happen, */ + /* but I'm paranoid... */ + if (codesize[i] > MAX_CLEN) + ERREXIT(cinfo, JERR_HUFF_CLEN_OVERFLOW); + + bits[codesize[i]]++; + } + } + + /* JPEG doesn't allow symbols with code lengths over 16 bits, so if the pure + * Huffman procedure assigned any such lengths, we must adjust the coding. + * Here is what the JPEG spec says about how this next bit works: + * Since symbols are paired for the longest Huffman code, the symbols are + * removed from this length category two at a time. The prefix for the pair + * (which is one bit shorter) is allocated to one of the pair; then, + * skipping the BITS entry for that prefix length, a code word from the next + * shortest nonzero BITS entry is converted into a prefix for two code words + * one bit longer. + */ + + for (i = MAX_CLEN; i > 16; i--) { + while (bits[i] > 0) { + j = i - 2; /* find length of new prefix to be used */ + while (bits[j] == 0) + j--; + + bits[i] -= (UINT8)2; /* remove two symbols */ + bits[i-1]++; /* one goes in this length */ + bits[j+1] += (UINT8)2; /* two new symbols in this length */ + bits[j]--; /* symbol of this length is now a prefix */ + } + } + + /* Remove the count for the pseudo-symbol 256 from the largest codelength */ + while (bits[i] == 0) /* find largest codelength still in use */ + i--; + bits[i]--; + + /* Return final symbol counts (only for lengths 0..16) */ + MEMCOPY(htbl->bits, bits, SIZEOF(htbl->bits)); + + /* Return a list of the symbols sorted by code length */ + /* It's not real clear to me why we don't need to consider the codelength + * changes made above, but the JPEG spec seems to think this works. + */ + p = 0; + for (i = 1; i <= MAX_CLEN; i++) { + for (j = 0; j <= 255; j++) { + if (codesize[j] == i) { + htbl->huffval[p] = (UINT8) j; + p++; + } + } + } + + /* Set sent_table FALSE so updated table will be written to JPEG file. */ + htbl->sent_table = FALSE; +} + + +/* + * Finish up a statistics-gathering pass and create the new Huffman tables. + */ + +METHODDEF(void) +finish_pass_gather (j_compress_ptr cinfo) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + int ci, dctbl, actbl; + jpeg_component_info * compptr; + JHUFF_TBL **htblptr; + boolean did_dc[NUM_HUFF_TBLS]; + boolean did_ac[NUM_HUFF_TBLS]; + + /* It's important not to apply jpeg_gen_optimal_table more than once + * per table, because it clobbers the input frequency counts! + */ + MEMZERO(did_dc, SIZEOF(did_dc)); + MEMZERO(did_ac, SIZEOF(did_ac)); + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + dctbl = compptr->dc_tbl_no; + actbl = compptr->ac_tbl_no; + if (! did_dc[dctbl]) { + htblptr = & cinfo->dc_huff_tbl_ptrs[dctbl]; + if (*htblptr == NULL) + *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); + jpeg_gen_optimal_table(cinfo, *htblptr, entropy->dc_count_ptrs[dctbl]); + did_dc[dctbl] = TRUE; + } + if (! did_ac[actbl]) { + htblptr = & cinfo->ac_huff_tbl_ptrs[actbl]; + if (*htblptr == NULL) + *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); + jpeg_gen_optimal_table(cinfo, *htblptr, entropy->ac_count_ptrs[actbl]); + did_ac[actbl] = TRUE; + } + } +} + + +#endif /* ENTROPY_OPT_SUPPORTED */ + + +/* + * Module initialization routine for Huffman entropy encoding. + */ + +GLOBAL(void) +jinit_huff_encoder (j_compress_ptr cinfo) +{ + huff_entropy_ptr entropy; + int i; + + entropy = (huff_entropy_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(huff_entropy_encoder)); + cinfo->entropy = (struct jpeg_entropy_encoder *) entropy; + entropy->pub.start_pass = start_pass_huff; + + /* Mark tables unallocated */ + for (i = 0; i < NUM_HUFF_TBLS; i++) { + entropy->dc_derived_tbls[i] = entropy->ac_derived_tbls[i] = NULL; +#ifdef ENTROPY_OPT_SUPPORTED + entropy->dc_count_ptrs[i] = entropy->ac_count_ptrs[i] = NULL; +#endif + } +} diff --git a/jpeg/Jcparam.c b/jpeg/Jcparam.c new file mode 100644 index 0000000..a8fbf82 --- /dev/null +++ b/jpeg/Jcparam.c @@ -0,0 +1,610 @@ +/* + * jcparam.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains optional default-setting code for the JPEG compressor. + * Applications do not have to use this file, but those that don't use it + * must know a lot more about the innards of the JPEG code. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* + * Quantization table setup routines + */ + +GLOBAL(void) +jpeg_add_quant_table (j_compress_ptr cinfo, int which_tbl, + const unsigned int *basic_table, + int scale_factor, boolean force_baseline) +/* Define a quantization table equal to the basic_table times + * a scale factor (given as a percentage). + * If force_baseline is TRUE, the computed quantization table entries + * are limited to 1..255 for JPEG baseline compatibility. + */ +{ + JQUANT_TBL ** qtblptr; + int i; + long temp; + + /* Safety check to ensure start_compress not called yet. */ + if (cinfo->global_state != CSTATE_START) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + if (which_tbl < 0 || which_tbl >= NUM_QUANT_TBLS) + ERREXIT1(cinfo, JERR_DQT_INDEX, which_tbl); + + qtblptr = & cinfo->quant_tbl_ptrs[which_tbl]; + + if (*qtblptr == NULL) + *qtblptr = jpeg_alloc_quant_table((j_common_ptr) cinfo); + + for (i = 0; i < DCTSIZE2; i++) { + temp = ((long) basic_table[i] * scale_factor + 50L) / 100L; + /* limit the values to the valid range */ + if (temp <= 0L) temp = 1L; + if (temp > 32767L) temp = 32767L; /* max quantizer needed for 12 bits */ + if (force_baseline && temp > 255L) + temp = 255L; /* limit to baseline range if requested */ + (*qtblptr)->quantval[i] = (UINT16) temp; + } + + /* Initialize sent_table FALSE so table will be written to JPEG file. */ + (*qtblptr)->sent_table = FALSE; +} + + +GLOBAL(void) +jpeg_set_linear_quality (j_compress_ptr cinfo, int scale_factor, + boolean force_baseline) +/* Set or change the 'quality' (quantization) setting, using default tables + * and a straight percentage-scaling quality scale. In most cases it's better + * to use jpeg_set_quality (below); this entry point is provided for + * applications that insist on a linear percentage scaling. + */ +{ + /* These are the sample quantization tables given in JPEG spec section K.1. + * The spec says that the values given produce "good" quality, and + * when divided by 2, "very good" quality. + */ + static const unsigned int std_luminance_quant_tbl[DCTSIZE2] = { + 16, 11, 10, 16, 24, 40, 51, 61, + 12, 12, 14, 19, 26, 58, 60, 55, + 14, 13, 16, 24, 40, 57, 69, 56, + 14, 17, 22, 29, 51, 87, 80, 62, + 18, 22, 37, 56, 68, 109, 103, 77, + 24, 35, 55, 64, 81, 104, 113, 92, + 49, 64, 78, 87, 103, 121, 120, 101, + 72, 92, 95, 98, 112, 100, 103, 99 + }; + static const unsigned int std_chrominance_quant_tbl[DCTSIZE2] = { + 17, 18, 24, 47, 99, 99, 99, 99, + 18, 21, 26, 66, 99, 99, 99, 99, + 24, 26, 56, 99, 99, 99, 99, 99, + 47, 66, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99 + }; + + /* Set up two quantization tables using the specified scaling */ + jpeg_add_quant_table(cinfo, 0, std_luminance_quant_tbl, + scale_factor, force_baseline); + jpeg_add_quant_table(cinfo, 1, std_chrominance_quant_tbl, + scale_factor, force_baseline); +} + + +GLOBAL(int) +jpeg_quality_scaling (int quality) +/* Convert a user-specified quality rating to a percentage scaling factor + * for an underlying quantization table, using our recommended scaling curve. + * The input 'quality' factor should be 0 (terrible) to 100 (very good). + */ +{ + /* Safety limit on quality factor. Convert 0 to 1 to avoid zero divide. */ + if (quality <= 0) quality = 1; + if (quality > 100) quality = 100; + + /* The basic table is used as-is (scaling 100) for a quality of 50. + * Qualities 50..100 are converted to scaling percentage 200 - 2*Q; + * note that at Q=100 the scaling is 0, which will cause jpeg_add_quant_table + * to make all the table entries 1 (hence, minimum quantization loss). + * Qualities 1..50 are converted to scaling percentage 5000/Q. + */ + if (quality < 50) + quality = 5000 / quality; + else + quality = 200 - quality*2; + + return quality; +} + + +GLOBAL(void) +jpeg_set_quality (j_compress_ptr cinfo, int quality, boolean force_baseline) +/* Set or change the 'quality' (quantization) setting, using default tables. + * This is the standard quality-adjusting entry point for typical user + * interfaces; only those who want detailed control over quantization tables + * would use the preceding three routines directly. + */ +{ + /* Convert user 0-100 rating to percentage scaling */ + quality = jpeg_quality_scaling(quality); + + /* Set up standard quality tables */ + jpeg_set_linear_quality(cinfo, quality, force_baseline); +} + + +/* + * Huffman table setup routines + */ + +LOCAL(void) +add_huff_table (j_compress_ptr cinfo, + JHUFF_TBL **htblptr, const UINT8 *bits, const UINT8 *val) +/* Define a Huffman table */ +{ + int nsymbols, len; + + if (*htblptr == NULL) + *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); + + /* Copy the number-of-symbols-of-each-code-length counts */ + MEMCOPY((*htblptr)->bits, bits, SIZEOF((*htblptr)->bits)); + + /* Validate the counts. We do this here mainly so we can copy the right + * number of symbols from the val[] array, without risking marching off + * the end of memory. jchuff.c will do a more thorough test later. + */ + nsymbols = 0; + for (len = 1; len <= 16; len++) + nsymbols += bits[len]; + if (nsymbols < 1 || nsymbols > 256) + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + + MEMCOPY((*htblptr)->huffval, val, nsymbols * SIZEOF(UINT8)); + + /* Initialize sent_table FALSE so table will be written to JPEG file. */ + (*htblptr)->sent_table = FALSE; +} + + +LOCAL(void) +std_huff_tables (j_compress_ptr cinfo) +/* Set up the standard Huffman tables (cf. JPEG standard section K.3) */ +/* IMPORTANT: these are only valid for 8-bit data precision! */ +{ + static const UINT8 bits_dc_luminance[17] = + { /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }; + static const UINT8 val_dc_luminance[] = + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; + + static const UINT8 bits_dc_chrominance[17] = + { /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 }; + static const UINT8 val_dc_chrominance[] = + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; + + static const UINT8 bits_ac_luminance[17] = + { /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d }; + static const UINT8 val_ac_luminance[] = + { 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, + 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, + 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, + 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, + 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, + 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, + 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, + 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, + 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, + 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, + 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, + 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, + 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, + 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, + 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, + 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, + 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, + 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, + 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, + 0xf9, 0xfa }; + + static const UINT8 bits_ac_chrominance[17] = + { /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 }; + static const UINT8 val_ac_chrominance[] = + { 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, + 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, + 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, + 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, + 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, + 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, + 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, + 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, + 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, + 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, + 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, + 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, + 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, + 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, + 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, + 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, + 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, + 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, + 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, + 0xf9, 0xfa }; + + add_huff_table(cinfo, &cinfo->dc_huff_tbl_ptrs[0], + bits_dc_luminance, val_dc_luminance); + add_huff_table(cinfo, &cinfo->ac_huff_tbl_ptrs[0], + bits_ac_luminance, val_ac_luminance); + add_huff_table(cinfo, &cinfo->dc_huff_tbl_ptrs[1], + bits_dc_chrominance, val_dc_chrominance); + add_huff_table(cinfo, &cinfo->ac_huff_tbl_ptrs[1], + bits_ac_chrominance, val_ac_chrominance); +} + + +/* + * Default parameter setup for compression. + * + * Applications that don't choose to use this routine must do their + * own setup of all these parameters. Alternately, you can call this + * to establish defaults and then alter parameters selectively. This + * is the recommended approach since, if we add any new parameters, + * your code will still work (they'll be set to reasonable defaults). + */ + +GLOBAL(void) +jpeg_set_defaults (j_compress_ptr cinfo) +{ + int i; + + /* Safety check to ensure start_compress not called yet. */ + if (cinfo->global_state != CSTATE_START) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + /* Allocate comp_info array large enough for maximum component count. + * Array is made permanent in case application wants to compress + * multiple images at same param settings. + */ + if (cinfo->comp_info == NULL) + cinfo->comp_info = (jpeg_component_info *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + MAX_COMPONENTS * SIZEOF(jpeg_component_info)); + + /* Initialize everything not dependent on the color space */ + + cinfo->data_precision = BITS_IN_JSAMPLE; + /* Set up two quantization tables using default quality of 75 */ + jpeg_set_quality(cinfo, 75, TRUE); + /* Set up two Huffman tables */ + std_huff_tables(cinfo); + + /* Initialize default arithmetic coding conditioning */ + for (i = 0; i < NUM_ARITH_TBLS; i++) { + cinfo->arith_dc_L[i] = 0; + cinfo->arith_dc_U[i] = 1; + cinfo->arith_ac_K[i] = 5; + } + + /* Default is no multiple-scan output */ + cinfo->scan_info = NULL; + cinfo->num_scans = 0; + + /* Expect normal source image, not raw downsampled data */ + cinfo->raw_data_in = FALSE; + + /* Use Huffman coding, not arithmetic coding, by default */ + cinfo->arith_code = FALSE; + + /* By default, don't do extra passes to optimize entropy coding */ + cinfo->optimize_coding = FALSE; + /* The standard Huffman tables are only valid for 8-bit data precision. + * If the precision is higher, force optimization on so that usable + * tables will be computed. This test can be removed if default tables + * are supplied that are valid for the desired precision. + */ + if (cinfo->data_precision > 8) + cinfo->optimize_coding = TRUE; + + /* By default, use the simpler non-cosited sampling alignment */ + cinfo->CCIR601_sampling = FALSE; + + /* No input smoothing */ + cinfo->smoothing_factor = 0; + + /* DCT algorithm preference */ + cinfo->dct_method = JDCT_DEFAULT; + + /* No restart markers */ + cinfo->restart_interval = 0; + cinfo->restart_in_rows = 0; + + /* Fill in default JFIF marker parameters. Note that whether the marker + * will actually be written is determined by jpeg_set_colorspace. + * + * By default, the library emits JFIF version code 1.01. + * An application that wants to emit JFIF 1.02 extension markers should set + * JFIF_minor_version to 2. We could probably get away with just defaulting + * to 1.02, but there may still be some decoders in use that will complain + * about that; saying 1.01 should minimize compatibility problems. + */ + cinfo->JFIF_major_version = 1; /* Default JFIF version = 1.01 */ + cinfo->JFIF_minor_version = 1; + cinfo->density_unit = 0; /* Pixel size is unknown by default */ + cinfo->X_density = 1; /* Pixel aspect ratio is square by default */ + cinfo->Y_density = 1; + + /* Choose JPEG colorspace based on input space, set defaults accordingly */ + + jpeg_default_colorspace(cinfo); +} + + +/* + * Select an appropriate JPEG colorspace for in_color_space. + */ + +GLOBAL(void) +jpeg_default_colorspace (j_compress_ptr cinfo) +{ + switch (cinfo->in_color_space) { + case JCS_GRAYSCALE: + jpeg_set_colorspace(cinfo, JCS_GRAYSCALE); + break; + case JCS_RGB: + jpeg_set_colorspace(cinfo, JCS_YCbCr); + break; + case JCS_YCbCr: + jpeg_set_colorspace(cinfo, JCS_YCbCr); + break; + case JCS_CMYK: + jpeg_set_colorspace(cinfo, JCS_CMYK); /* By default, no translation */ + break; + case JCS_YCCK: + jpeg_set_colorspace(cinfo, JCS_YCCK); + break; + case JCS_UNKNOWN: + jpeg_set_colorspace(cinfo, JCS_UNKNOWN); + break; + default: + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + } +} + + +/* + * Set the JPEG colorspace, and choose colorspace-dependent default values. + */ + +GLOBAL(void) +jpeg_set_colorspace (j_compress_ptr cinfo, J_COLOR_SPACE colorspace) +{ + jpeg_component_info * compptr; + int ci; + +#define SET_COMP(index,id,hsamp,vsamp,quant,dctbl,actbl) \ + (compptr = &cinfo->comp_info[index], \ + compptr->component_id = (id), \ + compptr->h_samp_factor = (hsamp), \ + compptr->v_samp_factor = (vsamp), \ + compptr->quant_tbl_no = (quant), \ + compptr->dc_tbl_no = (dctbl), \ + compptr->ac_tbl_no = (actbl) ) + + /* Safety check to ensure start_compress not called yet. */ + if (cinfo->global_state != CSTATE_START) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + /* For all colorspaces, we use Q and Huff tables 0 for luminance components, + * tables 1 for chrominance components. + */ + + cinfo->jpeg_color_space = colorspace; + + cinfo->write_JFIF_header = FALSE; /* No marker for non-JFIF colorspaces */ + cinfo->write_Adobe_marker = FALSE; /* write no Adobe marker by default */ + + switch (colorspace) { + case JCS_GRAYSCALE: + cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */ + cinfo->num_components = 1; + /* JFIF specifies component ID 1 */ + SET_COMP(0, 1, 1,1, 0, 0,0); + break; + case JCS_RGB: + cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag RGB */ + cinfo->num_components = 3; + SET_COMP(0, 0x52 /* 'R' */, 1,1, 0, 0,0); + SET_COMP(1, 0x47 /* 'G' */, 1,1, 0, 0,0); + SET_COMP(2, 0x42 /* 'B' */, 1,1, 0, 0,0); + break; + case JCS_YCbCr: + cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */ + cinfo->num_components = 3; + /* JFIF specifies component IDs 1,2,3 */ + /* We default to 2x2 subsamples of chrominance */ + SET_COMP(0, 1, 2,2, 0, 0,0); + SET_COMP(1, 2, 1,1, 1, 1,1); + SET_COMP(2, 3, 1,1, 1, 1,1); + break; + case JCS_CMYK: + cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag CMYK */ + cinfo->num_components = 4; + SET_COMP(0, 0x43 /* 'C' */, 1,1, 0, 0,0); + SET_COMP(1, 0x4D /* 'M' */, 1,1, 0, 0,0); + SET_COMP(2, 0x59 /* 'Y' */, 1,1, 0, 0,0); + SET_COMP(3, 0x4B /* 'K' */, 1,1, 0, 0,0); + break; + case JCS_YCCK: + cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag YCCK */ + cinfo->num_components = 4; + SET_COMP(0, 1, 2,2, 0, 0,0); + SET_COMP(1, 2, 1,1, 1, 1,1); + SET_COMP(2, 3, 1,1, 1, 1,1); + SET_COMP(3, 4, 2,2, 0, 0,0); + break; + case JCS_UNKNOWN: + cinfo->num_components = cinfo->input_components; + if (cinfo->num_components < 1 || cinfo->num_components > MAX_COMPONENTS) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, + MAX_COMPONENTS); + for (ci = 0; ci < cinfo->num_components; ci++) { + SET_COMP(ci, ci, 1,1, 0, 0,0); + } + break; + default: + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + } +} + + +#ifdef C_PROGRESSIVE_SUPPORTED + +LOCAL(jpeg_scan_info *) +fill_a_scan (jpeg_scan_info * scanptr, int ci, + int Ss, int Se, int Ah, int Al) +/* Support routine: generate one scan for specified component */ +{ + scanptr->comps_in_scan = 1; + scanptr->component_index[0] = ci; + scanptr->Ss = Ss; + scanptr->Se = Se; + scanptr->Ah = Ah; + scanptr->Al = Al; + scanptr++; + return scanptr; +} + +LOCAL(jpeg_scan_info *) +fill_scans (jpeg_scan_info * scanptr, int ncomps, + int Ss, int Se, int Ah, int Al) +/* Support routine: generate one scan for each component */ +{ + int ci; + + for (ci = 0; ci < ncomps; ci++) { + scanptr->comps_in_scan = 1; + scanptr->component_index[0] = ci; + scanptr->Ss = Ss; + scanptr->Se = Se; + scanptr->Ah = Ah; + scanptr->Al = Al; + scanptr++; + } + return scanptr; +} + +LOCAL(jpeg_scan_info *) +fill_dc_scans (jpeg_scan_info * scanptr, int ncomps, int Ah, int Al) +/* Support routine: generate interleaved DC scan if possible, else N scans */ +{ + int ci; + + if (ncomps <= MAX_COMPS_IN_SCAN) { + /* Single interleaved DC scan */ + scanptr->comps_in_scan = ncomps; + for (ci = 0; ci < ncomps; ci++) + scanptr->component_index[ci] = ci; + scanptr->Ss = scanptr->Se = 0; + scanptr->Ah = Ah; + scanptr->Al = Al; + scanptr++; + } else { + /* Noninterleaved DC scan for each component */ + scanptr = fill_scans(scanptr, ncomps, 0, 0, Ah, Al); + } + return scanptr; +} + + +/* + * Create a recommended progressive-JPEG script. + * cinfo->num_components and cinfo->jpeg_color_space must be correct. + */ + +GLOBAL(void) +jpeg_simple_progression (j_compress_ptr cinfo) +{ + int ncomps = cinfo->num_components; + int nscans; + jpeg_scan_info * scanptr; + + /* Safety check to ensure start_compress not called yet. */ + if (cinfo->global_state != CSTATE_START) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + /* Figure space needed for script. Calculation must match code below! */ + if (ncomps == 3 && cinfo->jpeg_color_space == JCS_YCbCr) { + /* Custom script for YCbCr color images. */ + nscans = 10; + } else { + /* All-purpose script for other color spaces. */ + if (ncomps > MAX_COMPS_IN_SCAN) + nscans = 6 * ncomps; /* 2 DC + 4 AC scans per component */ + else + nscans = 2 + 4 * ncomps; /* 2 DC scans; 4 AC scans per component */ + } + + /* Allocate space for script. + * We need to put it in the permanent pool in case the application performs + * multiple compressions without changing the settings. To avoid a memory + * leak if jpeg_simple_progression is called repeatedly for the same JPEG + * object, we try to re-use previously allocated space, and we allocate + * enough space to handle YCbCr even if initially asked for grayscale. + */ + if (cinfo->script_space == NULL || cinfo->script_space_size < nscans) { + cinfo->script_space_size = MAX(nscans, 10); + cinfo->script_space = (jpeg_scan_info *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + cinfo->script_space_size * SIZEOF(jpeg_scan_info)); + } + scanptr = cinfo->script_space; + cinfo->scan_info = scanptr; + cinfo->num_scans = nscans; + + if (ncomps == 3 && cinfo->jpeg_color_space == JCS_YCbCr) { + /* Custom script for YCbCr color images. */ + /* Initial DC scan */ + scanptr = fill_dc_scans(scanptr, ncomps, 0, 1); + /* Initial AC scan: get some luma data out in a hurry */ + scanptr = fill_a_scan(scanptr, 0, 1, 5, 0, 2); + /* Chroma data is too small to be worth expending many scans on */ + scanptr = fill_a_scan(scanptr, 2, 1, 63, 0, 1); + scanptr = fill_a_scan(scanptr, 1, 1, 63, 0, 1); + /* Complete spectral selection for luma AC */ + scanptr = fill_a_scan(scanptr, 0, 6, 63, 0, 2); + /* Refine next bit of luma AC */ + scanptr = fill_a_scan(scanptr, 0, 1, 63, 2, 1); + /* Finish DC successive approximation */ + scanptr = fill_dc_scans(scanptr, ncomps, 1, 0); + /* Finish AC successive approximation */ + scanptr = fill_a_scan(scanptr, 2, 1, 63, 1, 0); + scanptr = fill_a_scan(scanptr, 1, 1, 63, 1, 0); + /* Luma bottom bit comes last since it's usually largest scan */ + fill_a_scan(scanptr, 0, 1, 63, 1, 0); + } else { + /* All-purpose script for other color spaces. */ + /* Successive approximation first pass */ + scanptr = fill_dc_scans(scanptr, ncomps, 0, 1); + scanptr = fill_scans(scanptr, ncomps, 1, 5, 0, 2); + scanptr = fill_scans(scanptr, ncomps, 6, 63, 0, 2); + /* Successive approximation second pass */ + scanptr = fill_scans(scanptr, ncomps, 1, 63, 2, 1); + /* Successive approximation final pass */ + scanptr = fill_dc_scans(scanptr, ncomps, 1, 0); + fill_scans(scanptr, ncomps, 1, 63, 1, 0); + } +} + +#endif /* C_PROGRESSIVE_SUPPORTED */ diff --git a/jpeg/Jdmarker.c b/jpeg/Jdmarker.c new file mode 100644 index 0000000..c03509a --- /dev/null +++ b/jpeg/Jdmarker.c @@ -0,0 +1,1360 @@ +/* + * jdmarker.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains routines to decode JPEG datastream markers. + * Most of the complexity arises from our desire to support input + * suspension: if not all of the data for a marker is available, + * we must exit back to the application. On resumption, we reprocess + * the marker. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +typedef enum { /* JPEG marker codes */ + M_SOF0 = 0xc0, + M_SOF1 = 0xc1, + M_SOF2 = 0xc2, + M_SOF3 = 0xc3, + + M_SOF5 = 0xc5, + M_SOF6 = 0xc6, + M_SOF7 = 0xc7, + + M_JPG = 0xc8, + M_SOF9 = 0xc9, + M_SOF10 = 0xca, + M_SOF11 = 0xcb, + + M_SOF13 = 0xcd, + M_SOF14 = 0xce, + M_SOF15 = 0xcf, + + M_DHT = 0xc4, + + M_DAC = 0xcc, + + M_RST0 = 0xd0, + M_RST1 = 0xd1, + M_RST2 = 0xd2, + M_RST3 = 0xd3, + M_RST4 = 0xd4, + M_RST5 = 0xd5, + M_RST6 = 0xd6, + M_RST7 = 0xd7, + + M_SOI = 0xd8, + M_EOI = 0xd9, + M_SOS = 0xda, + M_DQT = 0xdb, + M_DNL = 0xdc, + M_DRI = 0xdd, + M_DHP = 0xde, + M_EXP = 0xdf, + + M_APP0 = 0xe0, + M_APP1 = 0xe1, + M_APP2 = 0xe2, + M_APP3 = 0xe3, + M_APP4 = 0xe4, + M_APP5 = 0xe5, + M_APP6 = 0xe6, + M_APP7 = 0xe7, + M_APP8 = 0xe8, + M_APP9 = 0xe9, + M_APP10 = 0xea, + M_APP11 = 0xeb, + M_APP12 = 0xec, + M_APP13 = 0xed, + M_APP14 = 0xee, + M_APP15 = 0xef, + + M_JPG0 = 0xf0, + M_JPG13 = 0xfd, + M_COM = 0xfe, + + M_TEM = 0x01, + + M_ERROR = 0x100 +} JPEG_MARKER; + + +/* Private state */ + +typedef struct { + struct jpeg_marker_reader pub; /* public fields */ + + /* Application-overridable marker processing methods */ + jpeg_marker_parser_method process_COM; + jpeg_marker_parser_method process_APPn[16]; + + /* Limit on marker data length to save for each marker type */ + unsigned int length_limit_COM; + unsigned int length_limit_APPn[16]; + + /* Status of COM/APPn marker saving */ + jpeg_saved_marker_ptr cur_marker; /* NULL if not processing a marker */ + unsigned int bytes_read; /* data bytes read so far in marker */ + /* Note: cur_marker is not linked into marker_list until it's all read. */ +} my_marker_reader; + +typedef my_marker_reader * my_marker_ptr; + + +/* + * Macros for fetching data from the data source module. + * + * At all times, cinfo->src->next_input_byte and ->bytes_in_buffer reflect + * the current restart point; we update them only when we have reached a + * suitable place to restart if a suspension occurs. + */ + +/* Declare and initialize local copies of input pointer/count */ +#define INPUT_VARS(cinfo) \ + struct jpeg_source_mgr * datasrc = (cinfo)->src; \ + const JOCTET * next_input_byte = datasrc->next_input_byte; \ + size_t bytes_in_buffer = datasrc->bytes_in_buffer + +/* Unload the local copies --- do this only at a restart boundary */ +#define INPUT_SYNC(cinfo) \ + ( datasrc->next_input_byte = next_input_byte, \ + datasrc->bytes_in_buffer = bytes_in_buffer ) + +/* Reload the local copies --- used only in MAKE_BYTE_AVAIL */ +#define INPUT_RELOAD(cinfo) \ + ( next_input_byte = datasrc->next_input_byte, \ + bytes_in_buffer = datasrc->bytes_in_buffer ) + +/* Internal macro for INPUT_BYTE and INPUT_2BYTES: make a byte available. + * Note we do *not* do INPUT_SYNC before calling fill_input_buffer, + * but we must reload the local copies after a successful fill. + */ +#define MAKE_BYTE_AVAIL(cinfo,action) \ + if (bytes_in_buffer == 0) { \ + if (! (*datasrc->fill_input_buffer) (cinfo)) \ + { action; } \ + INPUT_RELOAD(cinfo); \ + } + +/* Read a byte into variable V. + * If must suspend, take the specified action (typically "return FALSE"). + */ +#define INPUT_BYTE(cinfo,V,action) \ + MAKESTMT( MAKE_BYTE_AVAIL(cinfo,action); \ + bytes_in_buffer--; \ + V = GETJOCTET(*next_input_byte++); ) + +/* As above, but read two bytes interpreted as an unsigned 16-bit integer. + * V should be declared unsigned int or perhaps INT32. + */ +#define INPUT_2BYTES(cinfo,V,action) \ + MAKESTMT( MAKE_BYTE_AVAIL(cinfo,action); \ + bytes_in_buffer--; \ + V = ((unsigned int) GETJOCTET(*next_input_byte++)) << 8; \ + MAKE_BYTE_AVAIL(cinfo,action); \ + bytes_in_buffer--; \ + V += GETJOCTET(*next_input_byte++); ) + + +/* + * Routines to process JPEG markers. + * + * Entry condition: JPEG marker itself has been read and its code saved + * in cinfo->unread_marker; input restart point is just after the marker. + * + * Exit: if return TRUE, have read and processed any parameters, and have + * updated the restart point to point after the parameters. + * If return FALSE, was forced to suspend before reaching end of + * marker parameters; restart point has not been moved. Same routine + * will be called again after application supplies more input data. + * + * This approach to suspension assumes that all of a marker's parameters + * can fit into a single input bufferload. This should hold for "normal" + * markers. Some COM/APPn markers might have large parameter segments + * that might not fit. If we are simply dropping such a marker, we use + * skip_input_data to get past it, and thereby put the problem on the + * source manager's shoulders. If we are saving the marker's contents + * into memory, we use a slightly different convention: when forced to + * suspend, the marker processor updates the restart point to the end of + * what it's consumed (ie, the end of the buffer) before returning FALSE. + * On resumption, cinfo->unread_marker still contains the marker code, + * but the data source will point to the next chunk of marker data. + * The marker processor must retain internal state to deal with this. + * + * Note that we don't bother to avoid duplicate trace messages if a + * suspension occurs within marker parameters. Other side effects + * require more care. + */ + + +LOCAL(boolean) +get_soi (j_decompress_ptr cinfo) +/* Process an SOI marker */ +{ + int i; + + TRACEMS(cinfo, 1, JTRC_SOI); + + if (cinfo->marker->saw_SOI) + ERREXIT(cinfo, JERR_SOI_DUPLICATE); + + /* Reset all parameters that are defined to be reset by SOI */ + + for (i = 0; i < NUM_ARITH_TBLS; i++) { + cinfo->arith_dc_L[i] = 0; + cinfo->arith_dc_U[i] = 1; + cinfo->arith_ac_K[i] = 5; + } + cinfo->restart_interval = 0; + + /* Set initial assumptions for colorspace etc */ + + cinfo->jpeg_color_space = JCS_UNKNOWN; + cinfo->CCIR601_sampling = FALSE; /* Assume non-CCIR sampling??? */ + + cinfo->saw_JFIF_marker = FALSE; + cinfo->JFIF_major_version = 1; /* set default JFIF APP0 values */ + cinfo->JFIF_minor_version = 1; + cinfo->density_unit = 0; + cinfo->X_density = 1; + cinfo->Y_density = 1; + cinfo->saw_Adobe_marker = FALSE; + cinfo->Adobe_transform = 0; + + cinfo->marker->saw_SOI = TRUE; + + return TRUE; +} + + +LOCAL(boolean) +get_sof (j_decompress_ptr cinfo, boolean is_prog, boolean is_arith) +/* Process a SOFn marker */ +{ + INT32 length; + int c, ci; + jpeg_component_info * compptr; + INPUT_VARS(cinfo); + + cinfo->progressive_mode = is_prog; + cinfo->arith_code = is_arith; + + INPUT_2BYTES(cinfo, length, return FALSE); + + INPUT_BYTE(cinfo, cinfo->data_precision, return FALSE); + INPUT_2BYTES(cinfo, cinfo->image_height, return FALSE); + INPUT_2BYTES(cinfo, cinfo->image_width, return FALSE); + INPUT_BYTE(cinfo, cinfo->num_components, return FALSE); + + length -= 8; + + TRACEMS4(cinfo, 1, JTRC_SOF, cinfo->unread_marker, + (int) cinfo->image_width, (int) cinfo->image_height, + cinfo->num_components); + + if (cinfo->marker->saw_SOF) + ERREXIT(cinfo, JERR_SOF_DUPLICATE); + + /* We don't support files in which the image height is initially specified */ + /* as 0 and is later redefined by DNL. As long as we have to check that, */ + /* might as well have a general sanity check. */ + if (cinfo->image_height <= 0 || cinfo->image_width <= 0 + || cinfo->num_components <= 0) + ERREXIT(cinfo, JERR_EMPTY_IMAGE); + + if (length != (cinfo->num_components * 3)) + ERREXIT(cinfo, JERR_BAD_LENGTH); + + if (cinfo->comp_info == NULL) /* do only once, even if suspend */ + cinfo->comp_info = (jpeg_component_info *) (*cinfo->mem->alloc_small) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + cinfo->num_components * SIZEOF(jpeg_component_info)); + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + compptr->component_index = ci; + INPUT_BYTE(cinfo, compptr->component_id, return FALSE); + INPUT_BYTE(cinfo, c, return FALSE); + compptr->h_samp_factor = (c >> 4) & 15; + compptr->v_samp_factor = (c ) & 15; + INPUT_BYTE(cinfo, compptr->quant_tbl_no, return FALSE); + + TRACEMS4(cinfo, 1, JTRC_SOF_COMPONENT, + compptr->component_id, compptr->h_samp_factor, + compptr->v_samp_factor, compptr->quant_tbl_no); + } + + cinfo->marker->saw_SOF = TRUE; + + INPUT_SYNC(cinfo); + return TRUE; +} + + +LOCAL(boolean) +get_sos (j_decompress_ptr cinfo) +/* Process a SOS marker */ +{ + INT32 length; + int i, ci, n, c, cc; + jpeg_component_info * compptr; + INPUT_VARS(cinfo); + + if (! cinfo->marker->saw_SOF) + ERREXIT(cinfo, JERR_SOS_NO_SOF); + + INPUT_2BYTES(cinfo, length, return FALSE); + + INPUT_BYTE(cinfo, n, return FALSE); /* Number of components */ + + TRACEMS1(cinfo, 1, JTRC_SOS, n); + + if (length != (n * 2 + 6) || n < 1 || n > MAX_COMPS_IN_SCAN) + ERREXIT(cinfo, JERR_BAD_LENGTH); + + cinfo->comps_in_scan = n; + + /* Collect the component-spec parameters */ + + for (i = 0; i < n; i++) { + INPUT_BYTE(cinfo, cc, return FALSE); + INPUT_BYTE(cinfo, c, return FALSE); + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + if (cc == compptr->component_id) + goto id_found; + } + + ERREXIT1(cinfo, JERR_BAD_COMPONENT_ID, cc); + + id_found: + + cinfo->cur_comp_info[i] = compptr; + compptr->dc_tbl_no = (c >> 4) & 15; + compptr->ac_tbl_no = (c ) & 15; + + TRACEMS3(cinfo, 1, JTRC_SOS_COMPONENT, cc, + compptr->dc_tbl_no, compptr->ac_tbl_no); + } + + /* Collect the additional scan parameters Ss, Se, Ah/Al. */ + INPUT_BYTE(cinfo, c, return FALSE); + cinfo->Ss = c; + INPUT_BYTE(cinfo, c, return FALSE); + cinfo->Se = c; + INPUT_BYTE(cinfo, c, return FALSE); + cinfo->Ah = (c >> 4) & 15; + cinfo->Al = (c ) & 15; + + TRACEMS4(cinfo, 1, JTRC_SOS_PARAMS, cinfo->Ss, cinfo->Se, + cinfo->Ah, cinfo->Al); + + /* Prepare to scan data & restart markers */ + cinfo->marker->next_restart_num = 0; + + /* Count another SOS marker */ + cinfo->input_scan_number++; + + INPUT_SYNC(cinfo); + return TRUE; +} + + +#ifdef D_ARITH_CODING_SUPPORTED + +LOCAL(boolean) +get_dac (j_decompress_ptr cinfo) +/* Process a DAC marker */ +{ + INT32 length; + int index, val; + INPUT_VARS(cinfo); + + INPUT_2BYTES(cinfo, length, return FALSE); + length -= 2; + + while (length > 0) { + INPUT_BYTE(cinfo, index, return FALSE); + INPUT_BYTE(cinfo, val, return FALSE); + + length -= 2; + + TRACEMS2(cinfo, 1, JTRC_DAC, index, val); + + if (index < 0 || index >= (2*NUM_ARITH_TBLS)) + ERREXIT1(cinfo, JERR_DAC_INDEX, index); + + if (index >= NUM_ARITH_TBLS) { /* define AC table */ + cinfo->arith_ac_K[index-NUM_ARITH_TBLS] = (UINT8) val; + } else { /* define DC table */ + cinfo->arith_dc_L[index] = (UINT8) (val & 0x0F); + cinfo->arith_dc_U[index] = (UINT8) (val >> 4); + if (cinfo->arith_dc_L[index] > cinfo->arith_dc_U[index]) + ERREXIT1(cinfo, JERR_DAC_VALUE, val); + } + } + + if (length != 0) + ERREXIT(cinfo, JERR_BAD_LENGTH); + + INPUT_SYNC(cinfo); + return TRUE; +} + +#else /* ! D_ARITH_CODING_SUPPORTED */ + +#define get_dac(cinfo) skip_variable(cinfo) + +#endif /* D_ARITH_CODING_SUPPORTED */ + + +LOCAL(boolean) +get_dht (j_decompress_ptr cinfo) +/* Process a DHT marker */ +{ + INT32 length; + UINT8 bits[17]; + UINT8 huffval[256]; + int i, index, count; + JHUFF_TBL **htblptr; + INPUT_VARS(cinfo); + + INPUT_2BYTES(cinfo, length, return FALSE); + length -= 2; + + while (length > 16) { + INPUT_BYTE(cinfo, index, return FALSE); + + TRACEMS1(cinfo, 1, JTRC_DHT, index); + + bits[0] = 0; + count = 0; + for (i = 1; i <= 16; i++) { + INPUT_BYTE(cinfo, bits[i], return FALSE); + count += bits[i]; + } + + length -= 1 + 16; + + TRACEMS8(cinfo, 2, JTRC_HUFFBITS, + bits[1], bits[2], bits[3], bits[4], + bits[5], bits[6], bits[7], bits[8]); + TRACEMS8(cinfo, 2, JTRC_HUFFBITS, + bits[9], bits[10], bits[11], bits[12], + bits[13], bits[14], bits[15], bits[16]); + + /* Here we just do minimal validation of the counts to avoid walking + * off the end of our table space. jdhuff.c will check more carefully. + */ + if (count > 256 || ((INT32) count) > length) + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + + for (i = 0; i < count; i++) + INPUT_BYTE(cinfo, huffval[i], return FALSE); + + length -= count; + + if (index & 0x10) { /* AC table definition */ + index -= 0x10; + htblptr = &cinfo->ac_huff_tbl_ptrs[index]; + } else { /* DC table definition */ + htblptr = &cinfo->dc_huff_tbl_ptrs[index]; + } + + if (index < 0 || index >= NUM_HUFF_TBLS) + ERREXIT1(cinfo, JERR_DHT_INDEX, index); + + if (*htblptr == NULL) + *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); + + MEMCOPY((*htblptr)->bits, bits, SIZEOF((*htblptr)->bits)); + MEMCOPY((*htblptr)->huffval, huffval, SIZEOF((*htblptr)->huffval)); + } + + if (length != 0) + ERREXIT(cinfo, JERR_BAD_LENGTH); + + INPUT_SYNC(cinfo); + return TRUE; +} + + +LOCAL(boolean) +get_dqt (j_decompress_ptr cinfo) +/* Process a DQT marker */ +{ + INT32 length; + int n, i, prec; + unsigned int tmp; + JQUANT_TBL *quant_ptr; + INPUT_VARS(cinfo); + + INPUT_2BYTES(cinfo, length, return FALSE); + length -= 2; + + while (length > 0) { + INPUT_BYTE(cinfo, n, return FALSE); + prec = n >> 4; + n &= 0x0F; + + TRACEMS2(cinfo, 1, JTRC_DQT, n, prec); + + if (n >= NUM_QUANT_TBLS) + ERREXIT1(cinfo, JERR_DQT_INDEX, n); + + if (cinfo->quant_tbl_ptrs[n] == NULL) + cinfo->quant_tbl_ptrs[n] = jpeg_alloc_quant_table((j_common_ptr) cinfo); + quant_ptr = cinfo->quant_tbl_ptrs[n]; + + for (i = 0; i < DCTSIZE2; i++) { + if (prec) + INPUT_2BYTES(cinfo, tmp, return FALSE); + else + INPUT_BYTE(cinfo, tmp, return FALSE); + /* We convert the zigzag-order table to natural array order. */ + quant_ptr->quantval[jpeg_natural_order[i]] = (UINT16) tmp; + } + + if (cinfo->err->trace_level >= 2) { + for (i = 0; i < DCTSIZE2; i += 8) { + TRACEMS8(cinfo, 2, JTRC_QUANTVALS, + quant_ptr->quantval[i], quant_ptr->quantval[i+1], + quant_ptr->quantval[i+2], quant_ptr->quantval[i+3], + quant_ptr->quantval[i+4], quant_ptr->quantval[i+5], + quant_ptr->quantval[i+6], quant_ptr->quantval[i+7]); + } + } + + length -= DCTSIZE2+1; + if (prec) length -= DCTSIZE2; + } + + if (length != 0) + ERREXIT(cinfo, JERR_BAD_LENGTH); + + INPUT_SYNC(cinfo); + return TRUE; +} + + +LOCAL(boolean) +get_dri (j_decompress_ptr cinfo) +/* Process a DRI marker */ +{ + INT32 length; + unsigned int tmp; + INPUT_VARS(cinfo); + + INPUT_2BYTES(cinfo, length, return FALSE); + + if (length != 4) + ERREXIT(cinfo, JERR_BAD_LENGTH); + + INPUT_2BYTES(cinfo, tmp, return FALSE); + + TRACEMS1(cinfo, 1, JTRC_DRI, tmp); + + cinfo->restart_interval = tmp; + + INPUT_SYNC(cinfo); + return TRUE; +} + + +/* + * Routines for processing APPn and COM markers. + * These are either saved in memory or discarded, per application request. + * APP0 and APP14 are specially checked to see if they are + * JFIF and Adobe markers, respectively. + */ + +#define APP0_DATA_LEN 14 /* Length of interesting data in APP0 */ +#define APP14_DATA_LEN 12 /* Length of interesting data in APP14 */ +#define APPN_DATA_LEN 14 /* Must be the largest of the above!! */ + + +LOCAL(void) +examine_app0 (j_decompress_ptr cinfo, JOCTET FAR * data, + unsigned int datalen, INT32 remaining) +/* Examine first few bytes from an APP0. + * Take appropriate action if it is a JFIF marker. + * datalen is # of bytes at data[], remaining is length of rest of marker data. + */ +{ + INT32 totallen = (INT32) datalen + remaining; + + if (datalen >= APP0_DATA_LEN && + GETJOCTET(data[0]) == 0x4A && + GETJOCTET(data[1]) == 0x46 && + GETJOCTET(data[2]) == 0x49 && + GETJOCTET(data[3]) == 0x46 && + GETJOCTET(data[4]) == 0) { + /* Found JFIF APP0 marker: save info */ + cinfo->saw_JFIF_marker = TRUE; + cinfo->JFIF_major_version = GETJOCTET(data[5]); + cinfo->JFIF_minor_version = GETJOCTET(data[6]); + cinfo->density_unit = GETJOCTET(data[7]); + cinfo->X_density = (GETJOCTET(data[8]) << 8) + GETJOCTET(data[9]); + cinfo->Y_density = (GETJOCTET(data[10]) << 8) + GETJOCTET(data[11]); + /* Check version. + * Major version must be 1, anything else signals an incompatible change. + * (We used to treat this as an error, but now it's a nonfatal warning, + * because some bozo at Hijaak couldn't read the spec.) + * Minor version should be 0..2, but process anyway if newer. + */ + if (cinfo->JFIF_major_version != 1) + WARNMS2(cinfo, JWRN_JFIF_MAJOR, + cinfo->JFIF_major_version, cinfo->JFIF_minor_version); + /* Generate trace messages */ + TRACEMS5(cinfo, 1, JTRC_JFIF, + cinfo->JFIF_major_version, cinfo->JFIF_minor_version, + cinfo->X_density, cinfo->Y_density, cinfo->density_unit); + /* Validate thumbnail dimensions and issue appropriate messages */ + if (GETJOCTET(data[12]) | GETJOCTET(data[13])) + TRACEMS2(cinfo, 1, JTRC_JFIF_THUMBNAIL, + GETJOCTET(data[12]), GETJOCTET(data[13])); + totallen -= APP0_DATA_LEN; + if (totallen != + ((INT32)GETJOCTET(data[12]) * (INT32)GETJOCTET(data[13]) * (INT32) 3)) + TRACEMS1(cinfo, 1, JTRC_JFIF_BADTHUMBNAILSIZE, (int) totallen); + } else if (datalen >= 6 && + GETJOCTET(data[0]) == 0x4A && + GETJOCTET(data[1]) == 0x46 && + GETJOCTET(data[2]) == 0x58 && + GETJOCTET(data[3]) == 0x58 && + GETJOCTET(data[4]) == 0) { + /* Found JFIF "JFXX" extension APP0 marker */ + /* The library doesn't actually do anything with these, + * but we try to produce a helpful trace message. + */ + switch (GETJOCTET(data[5])) { + case 0x10: + TRACEMS1(cinfo, 1, JTRC_THUMB_JPEG, (int) totallen); + break; + case 0x11: + TRACEMS1(cinfo, 1, JTRC_THUMB_PALETTE, (int) totallen); + break; + case 0x13: + TRACEMS1(cinfo, 1, JTRC_THUMB_RGB, (int) totallen); + break; + default: + TRACEMS2(cinfo, 1, JTRC_JFIF_EXTENSION, + GETJOCTET(data[5]), (int) totallen); + break; + } + } else { + /* Start of APP0 does not match "JFIF" or "JFXX", or too short */ + TRACEMS1(cinfo, 1, JTRC_APP0, (int) totallen); + } +} + + +LOCAL(void) +examine_app14 (j_decompress_ptr cinfo, JOCTET FAR * data, + unsigned int datalen, INT32 remaining) +/* Examine first few bytes from an APP14. + * Take appropriate action if it is an Adobe marker. + * datalen is # of bytes at data[], remaining is length of rest of marker data. + */ +{ + unsigned int version, flags0, flags1, transform; + + if (datalen >= APP14_DATA_LEN && + GETJOCTET(data[0]) == 0x41 && + GETJOCTET(data[1]) == 0x64 && + GETJOCTET(data[2]) == 0x6F && + GETJOCTET(data[3]) == 0x62 && + GETJOCTET(data[4]) == 0x65) { + /* Found Adobe APP14 marker */ + version = (GETJOCTET(data[5]) << 8) + GETJOCTET(data[6]); + flags0 = (GETJOCTET(data[7]) << 8) + GETJOCTET(data[8]); + flags1 = (GETJOCTET(data[9]) << 8) + GETJOCTET(data[10]); + transform = GETJOCTET(data[11]); + TRACEMS4(cinfo, 1, JTRC_ADOBE, version, flags0, flags1, transform); + cinfo->saw_Adobe_marker = TRUE; + cinfo->Adobe_transform = (UINT8) transform; + } else { + /* Start of APP14 does not match "Adobe", or too short */ + TRACEMS1(cinfo, 1, JTRC_APP14, (int) (datalen + remaining)); + } +} + + +METHODDEF(boolean) +get_interesting_appn (j_decompress_ptr cinfo) +/* Process an APP0 or APP14 marker without saving it */ +{ + INT32 length; + JOCTET b[APPN_DATA_LEN]; + unsigned int i, numtoread; + INPUT_VARS(cinfo); + + INPUT_2BYTES(cinfo, length, return FALSE); + length -= 2; + + /* get the interesting part of the marker data */ + if (length >= APPN_DATA_LEN) + numtoread = APPN_DATA_LEN; + else if (length > 0) + numtoread = (unsigned int) length; + else + numtoread = 0; + for (i = 0; i < numtoread; i++) + INPUT_BYTE(cinfo, b[i], return FALSE); + length -= numtoread; + + /* process it */ + switch (cinfo->unread_marker) { + case M_APP0: + examine_app0(cinfo, (JOCTET FAR *) b, numtoread, length); + break; + case M_APP14: + examine_app14(cinfo, (JOCTET FAR *) b, numtoread, length); + break; + default: + /* can't get here unless jpeg_save_markers chooses wrong processor */ + ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, cinfo->unread_marker); + break; + } + + /* skip any remaining data -- could be lots */ + INPUT_SYNC(cinfo); + if (length > 0) + (*cinfo->src->skip_input_data) (cinfo, (long) length); + + return TRUE; +} + + +#ifdef SAVE_MARKERS_SUPPORTED + +METHODDEF(boolean) +save_marker (j_decompress_ptr cinfo) +/* Save an APPn or COM marker into the marker list */ +{ + my_marker_ptr marker = (my_marker_ptr) cinfo->marker; + jpeg_saved_marker_ptr cur_marker = marker->cur_marker; + unsigned int bytes_read, data_length; + JOCTET FAR * data; + INT32 length = 0; + INPUT_VARS(cinfo); + + if (cur_marker == NULL) { + /* begin reading a marker */ + INPUT_2BYTES(cinfo, length, return FALSE); + length -= 2; + if (length >= 0) { /* watch out for bogus length word */ + /* figure out how much we want to save */ + unsigned int limit; + if (cinfo->unread_marker == (int) M_COM) + limit = marker->length_limit_COM; + else + limit = marker->length_limit_APPn[cinfo->unread_marker - (int) M_APP0]; + if ((unsigned int) length < limit) + limit = (unsigned int) length; + /* allocate and initialize the marker item */ + cur_marker = (jpeg_saved_marker_ptr) + (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(struct jpeg_marker_struct) + limit); + cur_marker->next = NULL; + cur_marker->marker = (UINT8) cinfo->unread_marker; + cur_marker->original_length = (unsigned int) length; + cur_marker->data_length = limit; + /* data area is just beyond the jpeg_marker_struct */ + data = cur_marker->data = (JOCTET FAR *) (cur_marker + 1); + marker->cur_marker = cur_marker; + marker->bytes_read = 0; + bytes_read = 0; + data_length = limit; + } else { + /* deal with bogus length word */ + bytes_read = data_length = 0; + data = NULL; + } + } else { + /* resume reading a marker */ + bytes_read = marker->bytes_read; + data_length = cur_marker->data_length; + data = cur_marker->data + bytes_read; + } + + while (bytes_read < data_length) { + INPUT_SYNC(cinfo); /* move the restart point to here */ + marker->bytes_read = bytes_read; + /* If there's not at least one byte in buffer, suspend */ + MAKE_BYTE_AVAIL(cinfo, return FALSE); + /* Copy bytes with reasonable rapidity */ + while (bytes_read < data_length && bytes_in_buffer > 0) { + *data++ = *next_input_byte++; + bytes_in_buffer--; + bytes_read++; + } + } + + /* Done reading what we want to read */ + if (cur_marker != NULL) { /* will be NULL if bogus length word */ + /* Add new marker to end of list */ + if (cinfo->marker_list == NULL) { + cinfo->marker_list = cur_marker; + } else { + jpeg_saved_marker_ptr prev = cinfo->marker_list; + while (prev->next != NULL) + prev = prev->next; + prev->next = cur_marker; + } + /* Reset pointer & calc remaining data length */ + data = cur_marker->data; + length = cur_marker->original_length - data_length; + } + /* Reset to initial state for next marker */ + marker->cur_marker = NULL; + + /* Process the marker if interesting; else just make a generic trace msg */ + switch (cinfo->unread_marker) { + case M_APP0: + examine_app0(cinfo, data, data_length, length); + break; + case M_APP14: + examine_app14(cinfo, data, data_length, length); + break; + default: + TRACEMS2(cinfo, 1, JTRC_MISC_MARKER, cinfo->unread_marker, + (int) (data_length + length)); + break; + } + + /* skip any remaining data -- could be lots */ + INPUT_SYNC(cinfo); /* do before skip_input_data */ + if (length > 0) + (*cinfo->src->skip_input_data) (cinfo, (long) length); + + return TRUE; +} + +#endif /* SAVE_MARKERS_SUPPORTED */ + + +METHODDEF(boolean) +skip_variable (j_decompress_ptr cinfo) +/* Skip over an unknown or uninteresting variable-length marker */ +{ + INT32 length; + INPUT_VARS(cinfo); + + INPUT_2BYTES(cinfo, length, return FALSE); + length -= 2; + + TRACEMS2(cinfo, 1, JTRC_MISC_MARKER, cinfo->unread_marker, (int) length); + + INPUT_SYNC(cinfo); /* do before skip_input_data */ + if (length > 0) + (*cinfo->src->skip_input_data) (cinfo, (long) length); + + return TRUE; +} + + +/* + * Find the next JPEG marker, save it in cinfo->unread_marker. + * Returns FALSE if had to suspend before reaching a marker; + * in that case cinfo->unread_marker is unchanged. + * + * Note that the result might not be a valid marker code, + * but it will never be 0 or FF. + */ + +LOCAL(boolean) +next_marker (j_decompress_ptr cinfo) +{ + int c; + INPUT_VARS(cinfo); + + for (;;) { + INPUT_BYTE(cinfo, c, return FALSE); + /* Skip any non-FF bytes. + * This may look a bit inefficient, but it will not occur in a valid file. + * We sync after each discarded byte so that a suspending data source + * can discard the byte from its buffer. + */ + while (c != 0xFF) { + cinfo->marker->discarded_bytes++; + INPUT_SYNC(cinfo); + INPUT_BYTE(cinfo, c, return FALSE); + } + /* This loop swallows any duplicate FF bytes. Extra FFs are legal as + * pad bytes, so don't count them in discarded_bytes. We assume there + * will not be so many consecutive FF bytes as to overflow a suspending + * data source's input buffer. + */ + do { + INPUT_BYTE(cinfo, c, return FALSE); + } while (c == 0xFF); + if (c != 0) + break; /* found a valid marker, exit loop */ + /* Reach here if we found a stuffed-zero data sequence (FF/00). + * Discard it and loop back to try again. + */ + cinfo->marker->discarded_bytes += 2; + INPUT_SYNC(cinfo); + } + + if (cinfo->marker->discarded_bytes != 0) { + WARNMS2(cinfo, JWRN_EXTRANEOUS_DATA, cinfo->marker->discarded_bytes, c); + cinfo->marker->discarded_bytes = 0; + } + + cinfo->unread_marker = c; + + INPUT_SYNC(cinfo); + return TRUE; +} + + +LOCAL(boolean) +first_marker (j_decompress_ptr cinfo) +/* Like next_marker, but used to obtain the initial SOI marker. */ +/* For this marker, we do not allow preceding garbage or fill; otherwise, + * we might well scan an entire input file before realizing it ain't JPEG. + * If an application wants to process non-JFIF files, it must seek to the + * SOI before calling the JPEG library. + */ +{ + int c, c2; + INPUT_VARS(cinfo); + + INPUT_BYTE(cinfo, c, return FALSE); + INPUT_BYTE(cinfo, c2, return FALSE); + if (c != 0xFF || c2 != (int) M_SOI) + ERREXIT2(cinfo, JERR_NO_SOI, c, c2); + + cinfo->unread_marker = c2; + + INPUT_SYNC(cinfo); + return TRUE; +} + + +/* + * Read markers until SOS or EOI. + * + * Returns same codes as are defined for jpeg_consume_input: + * JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI. + */ + +METHODDEF(int) +read_markers (j_decompress_ptr cinfo) +{ + /* Outer loop repeats once for each marker. */ + for (;;) { + /* Collect the marker proper, unless we already did. */ + /* NB: first_marker() enforces the requirement that SOI appear first. */ + if (cinfo->unread_marker == 0) { + if (! cinfo->marker->saw_SOI) { + if (! first_marker(cinfo)) + return JPEG_SUSPENDED; + } else { + if (! next_marker(cinfo)) + return JPEG_SUSPENDED; + } + } + /* At this point cinfo->unread_marker contains the marker code and the + * input point is just past the marker proper, but before any parameters. + * A suspension will cause us to return with this state still true. + */ + switch (cinfo->unread_marker) { + case M_SOI: + if (! get_soi(cinfo)) + return JPEG_SUSPENDED; + break; + + case M_SOF0: /* Baseline */ + case M_SOF1: /* Extended sequential, Huffman */ + if (! get_sof(cinfo, FALSE, FALSE)) + return JPEG_SUSPENDED; + break; + + case M_SOF2: /* Progressive, Huffman */ + if (! get_sof(cinfo, TRUE, FALSE)) + return JPEG_SUSPENDED; + break; + + case M_SOF9: /* Extended sequential, arithmetic */ + if (! get_sof(cinfo, FALSE, TRUE)) + return JPEG_SUSPENDED; + break; + + case M_SOF10: /* Progressive, arithmetic */ + if (! get_sof(cinfo, TRUE, TRUE)) + return JPEG_SUSPENDED; + break; + + /* Currently unsupported SOFn types */ + case M_SOF3: /* Lossless, Huffman */ + case M_SOF5: /* Differential sequential, Huffman */ + case M_SOF6: /* Differential progressive, Huffman */ + case M_SOF7: /* Differential lossless, Huffman */ + case M_JPG: /* Reserved for JPEG extensions */ + case M_SOF11: /* Lossless, arithmetic */ + case M_SOF13: /* Differential sequential, arithmetic */ + case M_SOF14: /* Differential progressive, arithmetic */ + case M_SOF15: /* Differential lossless, arithmetic */ + ERREXIT1(cinfo, JERR_SOF_UNSUPPORTED, cinfo->unread_marker); + break; + + case M_SOS: + if (! get_sos(cinfo)) + return JPEG_SUSPENDED; + cinfo->unread_marker = 0; /* processed the marker */ + return JPEG_REACHED_SOS; + + case M_EOI: + TRACEMS(cinfo, 1, JTRC_EOI); + cinfo->unread_marker = 0; /* processed the marker */ + return JPEG_REACHED_EOI; + + case M_DAC: + if (! get_dac(cinfo)) + return JPEG_SUSPENDED; + break; + + case M_DHT: + if (! get_dht(cinfo)) + return JPEG_SUSPENDED; + break; + + case M_DQT: + if (! get_dqt(cinfo)) + return JPEG_SUSPENDED; + break; + + case M_DRI: + if (! get_dri(cinfo)) + return JPEG_SUSPENDED; + break; + + case M_APP0: + case M_APP1: + case M_APP2: + case M_APP3: + case M_APP4: + case M_APP5: + case M_APP6: + case M_APP7: + case M_APP8: + case M_APP9: + case M_APP10: + case M_APP11: + case M_APP12: + case M_APP13: + case M_APP14: + case M_APP15: + if (! (*((my_marker_ptr) cinfo->marker)->process_APPn[ + cinfo->unread_marker - (int) M_APP0]) (cinfo)) + return JPEG_SUSPENDED; + break; + + case M_COM: + if (! (*((my_marker_ptr) cinfo->marker)->process_COM) (cinfo)) + return JPEG_SUSPENDED; + break; + + case M_RST0: /* these are all parameterless */ + case M_RST1: + case M_RST2: + case M_RST3: + case M_RST4: + case M_RST5: + case M_RST6: + case M_RST7: + case M_TEM: + TRACEMS1(cinfo, 1, JTRC_PARMLESS_MARKER, cinfo->unread_marker); + break; + + case M_DNL: /* Ignore DNL ... perhaps the wrong thing */ + if (! skip_variable(cinfo)) + return JPEG_SUSPENDED; + break; + + default: /* must be DHP, EXP, JPGn, or RESn */ + /* For now, we treat the reserved markers as fatal errors since they are + * likely to be used to signal incompatible JPEG Part 3 extensions. + * Once the JPEG 3 version-number marker is well defined, this code + * ought to change! + */ + ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, cinfo->unread_marker); + break; + } + /* Successfully processed marker, so reset state variable */ + cinfo->unread_marker = 0; + } /* end loop */ +} + + +/* + * Read a restart marker, which is expected to appear next in the datastream; + * if the marker is not there, take appropriate recovery action. + * Returns FALSE if suspension is required. + * + * This is called by the entropy decoder after it has read an appropriate + * number of MCUs. cinfo->unread_marker may be nonzero if the entropy decoder + * has already read a marker from the data source. Under normal conditions + * cinfo->unread_marker will be reset to 0 before returning; if not reset, + * it holds a marker which the decoder will be unable to read past. + */ + +METHODDEF(boolean) +read_restart_marker (j_decompress_ptr cinfo) +{ + /* Obtain a marker unless we already did. */ + /* Note that next_marker will complain if it skips any data. */ + if (cinfo->unread_marker == 0) { + if (! next_marker(cinfo)) + return FALSE; + } + + if (cinfo->unread_marker == + ((int) M_RST0 + cinfo->marker->next_restart_num)) { + /* Normal case --- swallow the marker and let entropy decoder continue */ + TRACEMS1(cinfo, 3, JTRC_RST, cinfo->marker->next_restart_num); + cinfo->unread_marker = 0; + } else { + /* Uh-oh, the restart markers have been messed up. */ + /* Let the data source manager determine how to resync. */ + if (! (*cinfo->src->resync_to_restart) (cinfo, + cinfo->marker->next_restart_num)) + return FALSE; + } + + /* Update next-restart state */ + cinfo->marker->next_restart_num = (cinfo->marker->next_restart_num + 1) & 7; + + return TRUE; +} + + +/* + * This is the default resync_to_restart method for data source managers + * to use if they don't have any better approach. Some data source managers + * may be able to back up, or may have additional knowledge about the data + * which permits a more intelligent recovery strategy; such managers would + * presumably supply their own resync method. + * + * read_restart_marker calls resync_to_restart if it finds a marker other than + * the restart marker it was expecting. (This code is *not* used unless + * a nonzero restart interval has been declared.) cinfo->unread_marker is + * the marker code actually found (might be anything, except 0 or FF). + * The desired restart marker number (0..7) is passed as a parameter. + * This routine is supposed to apply whatever error recovery strategy seems + * appropriate in order to position the input stream to the next data segment. + * Note that cinfo->unread_marker is treated as a marker appearing before + * the current data-source input point; usually it should be reset to zero + * before returning. + * Returns FALSE if suspension is required. + * + * This implementation is substantially constrained by wanting to treat the + * input as a data stream; this means we can't back up. Therefore, we have + * only the following actions to work with: + * 1. Simply discard the marker and let the entropy decoder resume at next + * byte of file. + * 2. Read forward until we find another marker, discarding intervening + * data. (In theory we could look ahead within the current bufferload, + * without having to discard data if we don't find the desired marker. + * This idea is not implemented here, in part because it makes behavior + * dependent on buffer size and chance buffer-boundary positions.) + * 3. Leave the marker unread (by failing to zero cinfo->unread_marker). + * This will cause the entropy decoder to process an empty data segment, + * inserting dummy zeroes, and then we will reprocess the marker. + * + * #2 is appropriate if we think the desired marker lies ahead, while #3 is + * appropriate if the found marker is a future restart marker (indicating + * that we have missed the desired restart marker, probably because it got + * corrupted). + * We apply #2 or #3 if the found marker is a restart marker no more than + * two counts behind or ahead of the expected one. We also apply #2 if the + * found marker is not a legal JPEG marker code (it's certainly bogus data). + * If the found marker is a restart marker more than 2 counts away, we do #1 + * (too much risk that the marker is erroneous; with luck we will be able to + * resync at some future point). + * For any valid non-restart JPEG marker, we apply #3. This keeps us from + * overrunning the end of a scan. An implementation limited to single-scan + * files might find it better to apply #2 for markers other than EOI, since + * any other marker would have to be bogus data in that case. + */ + +GLOBAL(boolean) +jpeg_resync_to_restart (j_decompress_ptr cinfo, int desired) +{ + int marker = cinfo->unread_marker; + int action = 1; + + /* Always put up a warning. */ + WARNMS2(cinfo, JWRN_MUST_RESYNC, marker, desired); + + /* Outer loop handles repeated decision after scanning forward. */ + for (;;) { + if (marker < (int) M_SOF0) + action = 2; /* invalid marker */ + else if (marker < (int) M_RST0 || marker > (int) M_RST7) + action = 3; /* valid non-restart marker */ + else { + if (marker == ((int) M_RST0 + ((desired+1) & 7)) || + marker == ((int) M_RST0 + ((desired+2) & 7))) + action = 3; /* one of the next two expected restarts */ + else if (marker == ((int) M_RST0 + ((desired-1) & 7)) || + marker == ((int) M_RST0 + ((desired-2) & 7))) + action = 2; /* a prior restart, so advance */ + else + action = 1; /* desired restart or too far away */ + } + TRACEMS2(cinfo, 4, JTRC_RECOVERY_ACTION, marker, action); + switch (action) { + case 1: + /* Discard marker and let entropy decoder resume processing. */ + cinfo->unread_marker = 0; + return TRUE; + case 2: + /* Scan to the next marker, and repeat the decision loop. */ + if (! next_marker(cinfo)) + return FALSE; + marker = cinfo->unread_marker; + break; + case 3: + /* Return without advancing past this marker. */ + /* Entropy decoder will be forced to process an empty segment. */ + return TRUE; + } + } /* end loop */ +} + + +/* + * Reset marker processing state to begin a fresh datastream. + */ + +METHODDEF(void) +reset_marker_reader (j_decompress_ptr cinfo) +{ + my_marker_ptr marker = (my_marker_ptr) cinfo->marker; + + cinfo->comp_info = NULL; /* until allocated by get_sof */ + cinfo->input_scan_number = 0; /* no SOS seen yet */ + cinfo->unread_marker = 0; /* no pending marker */ + marker->pub.saw_SOI = FALSE; /* set internal state too */ + marker->pub.saw_SOF = FALSE; + marker->pub.discarded_bytes = 0; + marker->cur_marker = NULL; +} + + +/* + * Initialize the marker reader module. + * This is called only once, when the decompression object is created. + */ + +GLOBAL(void) +jinit_marker_reader (j_decompress_ptr cinfo) +{ + my_marker_ptr marker; + int i; + + /* Create subobject in permanent pool */ + marker = (my_marker_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + SIZEOF(my_marker_reader)); + cinfo->marker = (struct jpeg_marker_reader *) marker; + /* Initialize public method pointers */ + marker->pub.reset_marker_reader = reset_marker_reader; + marker->pub.read_markers = read_markers; + marker->pub.read_restart_marker = read_restart_marker; + /* Initialize COM/APPn processing. + * By default, we examine and then discard APP0 and APP14, + * but simply discard COM and all other APPn. + */ + marker->process_COM = skip_variable; + marker->length_limit_COM = 0; + for (i = 0; i < 16; i++) { + marker->process_APPn[i] = skip_variable; + marker->length_limit_APPn[i] = 0; + } + marker->process_APPn[0] = get_interesting_appn; + marker->process_APPn[14] = get_interesting_appn; + /* Reset marker processing state */ + reset_marker_reader(cinfo); +} + + +/* + * Control saving of COM and APPn markers into marker_list. + */ + +#ifdef SAVE_MARKERS_SUPPORTED + +GLOBAL(void) +jpeg_save_markers (j_decompress_ptr cinfo, int marker_code, + unsigned int length_limit) +{ + my_marker_ptr marker = (my_marker_ptr) cinfo->marker; + long maxlength; + jpeg_marker_parser_method processor; + + /* Length limit mustn't be larger than what we can allocate + * (should only be a concern in a 16-bit environment). + */ + maxlength = cinfo->mem->max_alloc_chunk - SIZEOF(struct jpeg_marker_struct); + if (((long) length_limit) > maxlength) + length_limit = (unsigned int) maxlength; + + /* Choose processor routine to use. + * APP0/APP14 have special requirements. + */ + if (length_limit) { + processor = save_marker; + /* If saving APP0/APP14, save at least enough for our internal use. */ + if (marker_code == (int) M_APP0 && length_limit < APP0_DATA_LEN) + length_limit = APP0_DATA_LEN; + else if (marker_code == (int) M_APP14 && length_limit < APP14_DATA_LEN) + length_limit = APP14_DATA_LEN; + } else { + processor = skip_variable; + /* If discarding APP0/APP14, use our regular on-the-fly processor. */ + if (marker_code == (int) M_APP0 || marker_code == (int) M_APP14) + processor = get_interesting_appn; + } + + if (marker_code == (int) M_COM) { + marker->process_COM = processor; + marker->length_limit_COM = length_limit; + } else if (marker_code >= (int) M_APP0 && marker_code <= (int) M_APP15) { + marker->process_APPn[marker_code - (int) M_APP0] = processor; + marker->length_limit_APPn[marker_code - (int) M_APP0] = length_limit; + } else + ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, marker_code); +} + +#endif /* SAVE_MARKERS_SUPPORTED */ + + +/* + * Install a special processing method for COM or APPn markers. + */ + +GLOBAL(void) +jpeg_set_marker_processor (j_decompress_ptr cinfo, int marker_code, + jpeg_marker_parser_method routine) +{ + my_marker_ptr marker = (my_marker_ptr) cinfo->marker; + + if (marker_code == (int) M_COM) + marker->process_COM = routine; + else if (marker_code >= (int) M_APP0 && marker_code <= (int) M_APP15) + marker->process_APPn[marker_code - (int) M_APP0] = routine; + else + ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, marker_code); +} diff --git a/jpeg/jconfig.h b/jpeg/jconfig.h new file mode 100644 index 0000000..c6c53ff --- /dev/null +++ b/jpeg/jconfig.h @@ -0,0 +1,48 @@ +/* jconfig.bcc --- jconfig.h for Borland C (Turbo C) on MS-DOS or OS/2. */ +/* see jconfig.doc for explanations */ + +#define HAVE_PROTOTYPES +#define HAVE_UNSIGNED_CHAR +#define HAVE_UNSIGNED_SHORT +/* #define void char */ +/* #define const */ +#undef CHAR_IS_UNSIGNED +#define HAVE_STDDEF_H +#define HAVE_STDLIB_H +#undef NEED_BSD_STRINGS +#undef NEED_SYS_TYPES_H +#ifdef __MSDOS__ +#define NEED_FAR_POINTERS /* for small or medium memory model */ +#endif +#undef NEED_SHORT_EXTERNAL_NAMES +#undef INCOMPLETE_TYPES_BROKEN /* this assumes you have -w-stu in CFLAGS */ + +#ifdef JPEG_INTERNALS + +#undef RIGHT_SHIFT_IS_UNSIGNED + +#ifdef __MSDOS__ +#define USE_MSDOS_MEMMGR /* Define this if you use jmemdos.c */ +#define MAX_ALLOC_CHUNK 65520L /* Maximum request to malloc() */ +#define USE_FMEM /* Borland has _fmemcpy() and _fmemset() */ +#endif + +#endif /* JPEG_INTERNALS */ + +#ifdef JPEG_CJPEG_DJPEG + +#define BMP_SUPPORTED /* BMP image file format */ +#define GIF_SUPPORTED /* GIF image file format */ +#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ +#undef RLE_SUPPORTED /* Utah RLE image file format */ +#define TARGA_SUPPORTED /* Targa image file format */ + +#define TWO_FILE_COMMANDLINE +#define USE_SETMODE /* Borland has setmode() */ +#ifdef __MSDOS__ +#define NEED_SIGNAL_CATCHER /* Define this if you use jmemdos.c */ +#endif +#undef DONT_USE_B_MODE +#undef PROGRESS_REPORT /* optional */ + +#endif /* JPEG_CJPEG_DJPEG */ diff --git a/jpeg/jhandle.C b/jpeg/jhandle.C new file mode 100644 index 0000000..b9b4e5c --- /dev/null +++ b/jpeg/jhandle.C @@ -0,0 +1,443 @@ +/* + * example.c + * + * This file illustrates how to use the IJG code as a subroutine library + * to read or write JPEG image files. You should look at this code in + * conjunction with the documentation file libjpeg.doc. + * + * This code will not do anything useful as-is, but it may be helpful as a + * skeleton for constructing routines that call the JPEG library. + * + * We present these routines in the same coding style used in the JPEG code + * (ANSI function definitions, etc); but you are of course free to code your + * routines in a different style if you prefer. + */ + +#include + +/* + * Include file for users of JPEG library. + * You will need to have included system headers that define at least + * the typedefs FILE and size_t before you can include jpeglib.h. + * (stdio.h is sufficient on ANSI-conforming systems.) + * You may also wish to include "jerror.h". + */ + +#include "jpeglib.h" + +/* + * is used for the optional error recovery mechanism shown in + * the second part of the example. + */ + +#include + + + +/******************** JPEG COMPRESSION SAMPLE INTERFACE *******************/ + +/* This half of the example shows how to feed data into the JPEG compressor. + * We present a minimal version that does not worry about refinements such + * as error recovery (the JPEG code will just exit() if it gets an error). + */ + + +/* + * IMAGE DATA FORMATS: + * + * The standard input image format is a rectangular array of pixels, with + * each pixel having the same number of "component" values (color channels). + * Each pixel row is an array of JSAMPLEs (which typically are unsigned chars). + * If you are working with color data, then the color values for each pixel + * must be adjacent in the row; for example, R,G,B,R,G,B,R,G,B,... for 24-bit + * RGB color. + * + * For this example, we'll assume that this data structure matches the way + * our application has stored the image in memory, so we can just pass a + * pointer to our image buffer. In particular, let's say that the image is + * RGB color and is described by: + */ + +JSAMPLE * image_buffer; /* Points to large array of R,G,B-order data */ +int image_height; /* Number of rows in image */ +int image_width; /* Number of columns in image */ + + +/* + * Sample routine for JPEG compression. We assume that the target file name + * and a compression quality factor are passed in. + */ + +//GLOBAL(void) +int write_JPEG_file(char * filename, int quality) +{ + /* This struct contains the JPEG compression parameters and pointers to + * working space (which is allocated as needed by the JPEG library). + * It is possible to have several such structures, representing multiple + * compression/decompression processes, in existence at once. We refer + * to any one struct (and its associated working data) as a "JPEG object". + */ + struct jpeg_compress_struct cinfo; + /* This struct represents a JPEG error handler. It is declared separately + * because applications often want to supply a specialized error handler + * (see the second half of this file for an example). But here we just + * take the easy way out and use the standard error handler, which will + * print a message on stderr and call exit() if compression fails. + * Note that this struct must live as long as the main JPEG parameter + * struct, to avoid dangling-pointer problems. + */ + struct jpeg_error_mgr jerr; + /* More stuff */ + FILE * outfile; /* target file */ + JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */ + int row_stride; /* physical row width in image buffer */ + + if ((outfile = fopen(filename, "wb")) == NULL) { + return 0; + } + setvbuf(outfile, NULL, _IOFBF, 65536); + + /* Step 1: allocate and initialize JPEG compression object */ + + /* We have to set up the error handler first, in case the initialization + * step fails. (Unlikely, but it could happen if you are out of memory.) + * This routine fills in the contents of struct jerr, and returns jerr's + * address which we place into the link field in cinfo. + */ + cinfo.err = jpeg_std_error(&jerr); + /* Now we can initialize the JPEG compression object. */ + jpeg_create_compress(&cinfo); + + /* Step 2: specify data destination (eg, a file) */ + /* Note: steps 2 and 3 can be done in either order. */ + + /* Here we use the library-supplied code to send compressed data to a + * stdio stream. You can also write your own code to do something else. + * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that + * requires it in order to write binary files. + */ + jpeg_stdio_dest(&cinfo, outfile); + + /* Step 3: set parameters for compression */ + + /* First we supply a description of the input image. + * Four fields of the cinfo struct must be filled in: + */ + cinfo.image_width = image_width; /* image width and height, in pixels */ + cinfo.image_height = image_height; + cinfo.input_components = 3; /* # of color components per pixel */ + cinfo.in_color_space = JCS_RGB; /* colorspace of input image */ + /* Now use the library's routine to set default compression parameters. + * (You must set at least cinfo.in_color_space before calling this, + * since the defaults depend on the source color space.) + */ + jpeg_set_defaults(&cinfo); + /* Now you can set any non-default parameters you wish to. + * Here we just illustrate the use of quality (quantization table) scaling: + */ + jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */); + + /* Step 4: Start compressor */ + + /* TRUE ensures that we will write a complete interchange-JPEG file. + * Pass TRUE unless you are very sure of what you're doing. + */ + jpeg_start_compress(&cinfo, TRUE); + + /* Step 5: while (scan lines remain to be written) */ + /* jpeg_write_scanlines(...); */ + + /* Here we use the library's state variable cinfo.next_scanline as the + * loop counter, so that we don't have to keep track ourselves. + * To keep things simple, we pass one scanline per call; you can pass + * more if you wish, though. + */ + row_stride = image_width * 3; /* JSAMPLEs per row in image_buffer */ + + while (cinfo.next_scanline < cinfo.image_height) { + /* jpeg_write_scanlines expects an array of pointers to scanlines. + * Here the array is only one element long, but you could pass + * more than one scanline at a time if that's more convenient. + */ + row_pointer[0] = & image_buffer[cinfo.next_scanline * row_stride]; + (void) jpeg_write_scanlines(&cinfo, row_pointer, 1); + } + + /* Step 6: Finish compression */ + + jpeg_finish_compress(&cinfo); + /* After finish_compress, we can close the output file. */ + fclose(outfile); + + /* Step 7: release JPEG compression object */ + + /* This is an important step since it will release a good deal of memory. */ + jpeg_destroy_compress(&cinfo); + + /* And we're done! */ + return 1; +} + + +/* + * SOME FINE POINTS: + * + * In the above loop, we ignored the return value of jpeg_write_scanlines, + * which is the number of scanlines actually written. We could get away + * with this because we were only relying on the value of cinfo.next_scanline, + * which will be incremented correctly. If you maintain additional loop + * variables then you should be careful to increment them properly. + * Actually, for output to a stdio stream you needn't worry, because + * then jpeg_write_scanlines will write all the lines passed (or else exit + * with a fatal error). Partial writes can only occur if you use a data + * destination module that can demand suspension of the compressor. + * (If you don't know what that's for, you don't need it.) + * + * If the compressor requires full-image buffers (for entropy-coding + * optimization or a multi-scan JPEG file), it will create temporary + * files for anything that doesn't fit within the maximum-memory setting. + * (Note that temp files are NOT needed if you use the default parameters.) + * On some systems you may need to set up a signal handler to ensure that + * temporary files are deleted if the program is interrupted. See libjpeg.doc. + * + * Scanlines MUST be supplied in top-to-bottom order if you want your JPEG + * files to be compatible with everyone else's. If you cannot readily read + * your data in that order, you'll need an intermediate array to hold the + * image. See rdtarga.c or rdbmp.c for examples of handling bottom-to-top + * source data using the JPEG code's internal virtual-array mechanisms. + */ + + + +/******************** JPEG DECOMPRESSION SAMPLE INTERFACE *******************/ + +/* This half of the example shows how to read data from the JPEG decompressor. + * It's a bit more refined than the above, in that we show: + * (a) how to modify the JPEG library's standard error-reporting behavior; + * (b) how to allocate workspace using the library's memory manager. + * + * Just to make this example a little different from the first one, we'll + * assume that we do not intend to put the whole image into an in-memory + * buffer, but to send it line-by-line someplace else. We need a one- + * scanline-high JSAMPLE array as a work buffer, and we will let the JPEG + * memory manager allocate it for us. This approach is actually quite useful + * because we don't need to remember to deallocate the buffer separately: it + * will go away automatically when the JPEG object is cleaned up. + */ + + +/* + * ERROR HANDLING: + * + * The JPEG library's standard error handler (jerror.c) is divided into + * several "methods" which you can override individually. This lets you + * adjust the behavior without duplicating a lot of code, which you might + * have to update with each future release. + * + * Our example here shows how to override the "error_exit" method so that + * control is returned to the library's caller when a fatal error occurs, + * rather than calling exit() as the standard error_exit method does. + * + * We use C's setjmp/longjmp facility to return control. This means that the + * routine which calls the JPEG library must first execute a setjmp() call to + * establish the return point. We want the replacement error_exit to do a + * longjmp(). But we need to make the setjmp buffer accessible to the + * error_exit routine. To do this, we make a private extension of the + * standard JPEG error handler object. (If we were using C++, we'd say we + * were making a subclass of the regular error handler.) + * + * Here's the extended error handler struct: + */ + +struct my_error_mgr { + struct jpeg_error_mgr pub; /* "public" fields */ + + jmp_buf setjmp_buffer; /* for return to caller */ +}; + +typedef struct my_error_mgr * my_error_ptr; + +/* + * Here's the routine that will replace the standard error_exit method: + */ + +METHODDEF(void) +my_error_exit (j_common_ptr cinfo) +{ + /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */ + my_error_ptr myerr = (my_error_ptr) cinfo->err; + + /* Always display the message. */ + /* We could postpone this until after returning, if we chose. */ + (*cinfo->err->output_message) (cinfo); + + /* Return control to the setjmp point */ + longjmp(myerr->setjmp_buffer, 1); +} + + +/* + * Sample routine for JPEG decompression. We assume that the source file name + * is passed in. We want to return 1 on success, 0 on error. + */ + + +void SetJPEGSize(int height, int width, int plane); +void SetJPEGImage(void *p, int line); + +//GLOBAL(int) +int read_JPEG_file (char * filename) +{ + /* This struct contains the JPEG decompression parameters and pointers to + * working space (which is allocated as needed by the JPEG library). + */ + struct jpeg_decompress_struct cinfo; + /* We use our private extension JPEG error handler. + * Note that this struct must live as long as the main JPEG parameter + * struct, to avoid dangling-pointer problems. + */ + struct my_error_mgr jerr; + /* More stuff */ + FILE * infile; /* source file */ + JSAMPARRAY buffer; /* Output row buffer */ + int row_stride; /* physical row width in output buffer */ + + /* In this example we want to open the input file before doing anything else, + * so that the setjmp() error recovery below can assume the file is open. + * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that + * requires it in order to read binary files. + */ + + if ((infile = fopen(filename, "rb")) == NULL) { + return 0; + } + setvbuf(infile, NULL, _IOFBF, 65536); + + + /* Step 1: allocate and initialize JPEG decompression object */ + + /* We set up the normal JPEG error routines, then override error_exit. */ + cinfo.err = jpeg_std_error(&jerr.pub); + jerr.pub.error_exit = my_error_exit; + /* Establish the setjmp return context for my_error_exit to use. */ + if (setjmp(jerr.setjmp_buffer)) { + /* If we get here, the JPEG code has signaled an error. + * We need to clean up the JPEG object, close the input file, and return. + */ + jpeg_destroy_decompress(&cinfo); + fclose(infile); + return 0; + } + /* Now we can initialize the JPEG decompression object. */ + jpeg_create_decompress(&cinfo); + + /* Step 2: specify data source (eg, a file) */ + + jpeg_stdio_src(&cinfo, infile); + + /* Step 3: read file parameters with jpeg_read_header() */ + + (void) jpeg_read_header(&cinfo, TRUE); + /* We can ignore the return value from jpeg_read_header since + * (a) suspension is not possible with the stdio data source, and + * (b) we passed TRUE to reject a tables-only JPEG file as an error. + * See libjpeg.doc for more info. + */ + + /* Step 4: set parameters for decompression */ + + /* In this example, we don't need to change any of the defaults set by + * jpeg_read_header(), so we do nothing here. + */ + + /* Step 5: Start decompressor */ + + (void) jpeg_start_decompress(&cinfo); + /* We can ignore the return value since suspension is not possible + * with the stdio data source. + */ + + /* We may need to do some setup of our own at this point before reading + * the data. After jpeg_start_decompress() we have the correct scaled + * output image dimensions available, as well as the output colormap + * if we asked for color quantization. + * In this example, we need to make an output work buffer of the right size. + */ + /* JSAMPLEs per row in output buffer */ + row_stride = cinfo.output_width * cinfo.output_components; + /* Make a one-row-high sample array that will go away when done with image */ + buffer = (*cinfo.mem->alloc_sarray) + ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1); + + /* Step 6: while (scan lines remain to be read) */ + /* jpeg_read_scanlines(...); */ + + /* Here we use the library's state variable cinfo.output_scanline as the + * loop counter, so that we don't have to keep track ourselves. + */ + SetJPEGSize(cinfo.output_height, cinfo.output_width, cinfo.output_components); + + while (cinfo.output_scanline < cinfo.output_height) { + /* jpeg_read_scanlines expects an array of pointers to scanlines. + * Here the array is only one element long, but you could ask for + * more than one scanline at a time if that's more convenient. + */ + (void) jpeg_read_scanlines(&cinfo, buffer, 1); + /* Assume put_scanline_someplace wants a pointer and sample count. */ +// memcpy(&image_buffer[cinfo.output_scanline*row_stride], buffer[0], row_stride); +// put_scanline_someplace(buffer[0], row_stride); <<<<<<<<<<<<------------- have to make + SetJPEGImage(buffer[0], cinfo.output_scanline); + } + + /* Step 7: Finish decompression */ + + (void) jpeg_finish_decompress(&cinfo); + /* We can ignore the return value since suspension is not possible + * with the stdio data source. + */ + + /* Step 8: Release JPEG decompression object */ + + /* This is an important step since it will release a good deal of memory. */ + jpeg_destroy_decompress(&cinfo); + + /* After finish_decompress, we can close the input file. + * Here we postpone it until after no more JPEG errors are possible, + * so as to simplify the setjmp error logic above. (Actually, I don't + * think that jpeg_destroy can do an error exit, but why assume anything...) + */ + fclose(infile); + + /* At this point you may want to check to see whether any corrupt-data + * warnings occurred (test whether jerr.pub.num_warnings is nonzero). + */ + + /* And we're done! */ + return 1; +} + + +/* + * SOME FINE POINTS: + * + * In the above code, we ignored the return value of jpeg_read_scanlines, + * which is the number of scanlines actually read. We could get away with + * this because we asked for only one line at a time and we weren't using + * a suspending data source. See libjpeg.doc for more info. + * + * We cheated a bit by calling alloc_sarray() after jpeg_start_decompress(); + * we should have done it beforehand to ensure that the space would be + * counted against the JPEG max_memory setting. In some systems the above + * code would risk an out-of-memory error. However, in general we don't + * know the output image dimensions before jpeg_start_decompress(), unless we + * call jpeg_calc_output_dimensions(). See libjpeg.doc for more about this. + * + * Scanlines are returned in the same order as they appear in the JPEG file, + * which is standardly top-to-bottom. If you must emit data bottom-to-top, + * you can use one of the virtual arrays provided by the JPEG memory manager + * to invert the data. See wrbmp.c for an example. + * + * As with compression, some operating modes may require temporary files. + * On some systems you may need to set up a signal handler to ensure that + * temporary files are deleted if the program is interrupted. See libjpeg.doc. + */ diff --git a/jpeg/jhandle.h b/jpeg/jhandle.h new file mode 100644 index 0000000..63c89af --- /dev/null +++ b/jpeg/jhandle.h @@ -0,0 +1,12 @@ +#ifndef JHANDLE_H +#define JHANDLE_H +extern BYTE *image_buffer; /* Points to large array of R,G,B-order data */ +extern int image_height; /* Number of rows in image */ +extern int image_width; /* Number of columns in image */ + +extern "C" int write_JPEG_file (const char *filename, int quality); +extern "C" int read_JPEG_file (const char * filename); + +extern "C" void SetJPEGSize(int height, int width, int plane); +extern "C" void SetJPEGImage(BYTE *p, int line); +#endif diff --git a/jpeg/log b/jpeg/log new file mode 100644 index 0000000..ee178c2 --- /dev/null +++ b/jpeg/log @@ -0,0 +1,53 @@ +=====ファイル JCAPIMIN.C の行数 = 280 +=====ファイル JCAPISTD.C の行数 = 161 +=====ファイル JDAPIMIN.C の行数 = 395 +=====ファイル JDAPISTD.C の行数 = 275 +=====ファイル JCOMAPI.C の行数 = 106 +=====ファイル JCTRANS.C の行数 = 388 +=====ファイル JDTRANS.C の行数 = 143 +=====ファイル JCINIT.C の行数 = 72 +=====ファイル JCMASTER.C の行数 = 590 +=====ファイル JCMAINCT.C の行数 = 293 +=====ファイル JCPREPCT.C の行数 = 354 +=====ファイル JCCOEFCT.C の行数 = 449 +=====ファイル JCCOLOR.C の行数 = 459 +=====ファイル JCSAMPLE.C の行数 = 519 +=====ファイル JFDCTINT.C の行数 = 283 +=====ファイル JFDCTFST.C の行数 = 224 +=====ファイル JFDCTFLT.C の行数 = 168 +=====ファイル JCPHUFF.C の行数 = 833 +=====ファイル JCMARKER.C の行数 = 664 +=====ファイル JDATADST.C の行数 = 151 +=====ファイル JDMASTER.C の行数 = 557 +=====ファイル JDINPUT.C の行数 = 381 +=====ファイル JDMAINCT.C の行数 = 512 +=====ファイル JDCOEFCT.C の行数 = 736 +=====ファイル JDPOSTCT.C の行数 = 290 +=====ファイル JDHUFF.C の行数 = 651 +=====ファイル JDPHUFF.C の行数 = 668 +=====ファイル JDDCTMGR.C の行数 = 269 +=====ファイル JIDCTINT.C の行数 = 389 +=====ファイル JIDCTFST.C の行数 = 368 +=====ファイル JIDCTFLT.C の行数 = 242 +=====ファイル JIDCTRED.C の行数 = 398 +=====ファイル JDSAMPLE.C の行数 = 478 +=====ファイル JDCOLOR.C の行数 = 396 +=====ファイル JDMERGE.C の行数 = 400 +=====ファイル JQUANT1.C の行数 = 856 +=====ファイル JQUANT2.C の行数 = 1310 +=====ファイル JDATASRC.C の行数 = 212 +JERROR.C 31: #ifndef EXIT_FAILURE /* define exit() codes if not provided */ +JERROR.C 78: exit(EXIT_FAILURE); +=====ファイル JERROR.C の行数 = 252 +=====ファイル JMEMMGR.C の行数 = 1118 +=====ファイル JUTILS.C の行数 = 179 +=====ファイル JMEMNOBS.C の行数 = 109 +JHANDLE.C 41: * as error recovery (the JPEG code will just exit() if it gets an error). +JHANDLE.C 85: * print a message on stderr and call exit() if compression fails. +JHANDLE.C 239: * rather than calling exit() as the standard error_exit method does. +=====ファイル JHANDLE.C の行数 = 443 +=====ファイル JCHUFF.C の行数 = 909 +=====ファイル JCDCTMGR.C の行数 = 387 +=====ファイル JDMARKER.C の行数 = 1360 +=====ファイル JCPARAM.C の行数 = 610 +=====該当ファイルの総行数 = 21287 diff --git a/mml.h b/mml.h new file mode 100644 index 0000000..642c979 --- /dev/null +++ b/mml.h @@ -0,0 +1,67 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +#ifndef MML_H +#define MML_H + +#define capNOTIFYSESSION 0x0001 +#define capWMCOPYDATA 0x0002 + +enum { + MML_NOTIFYSESSION, + MML_QRETURN, + MML_VFO, +}; + +#pragma pack(push, 1) +typedef struct { + SYSTEMTIME m_TimeLogON; + SYSTEMTIME m_TimeLogOFF; + char m_Call[16+1]; + char m_Mode[6+1]; // Name of the mode (eg. "RTTY", "SSTV") + char m_Freq[16+1]; // MHz (eg. "14.080") + char m_His[20+1]; // His/Her RST(V) and contest number. + char m_My[20+1]; + char m_Name[16+1]; // His/Her name + char m_QTH[28+1]; // His/Her QTH + char m_Pow[4+1]; + char m_Note[56+1]; // Note + char m_QSL[54+1]; // Note or QSL information + BYTE m_QSLS; // QSL sent + BYTE m_QSLR; // QSL rcvd + char m_DXCC[8+1]; // DXCC keyword (eg. JA, W, VK, etc...) + char m_Cont[8+1]; // The continental keyword (AS/OC/NA/SA/EU/AF) +}mmLOGDATA; +#pragma pack(pop) + + +typedef BOOL (__stdcall *tmmlOpen)(HWND hWnd, UINT uMsg); +typedef void (__stdcall *tmmlClose)(void); +typedef void (__stdcall *tmmlSetHandle)(HWND hWnd, UINT uMsg); +typedef DWORD (__stdcall *tmmlIsCap)(void); +typedef BOOL (__stdcall *tmmlIsConnected)(void); +typedef LPCSTR (__stdcall *tmmlGetSessionName)(void); +typedef void (__stdcall *tmmlQuery)(LPCSTR pCall); +typedef void (__stdcall *tmmlSetFreq)(LPCSTR pFreq); +typedef void (__stdcall *tmmlLog)(const mmLOGDATA *pLog, int sw); +typedef void (__stdcall *tmmlLogClear)(void); +typedef void (__stdcall *tmmlSetPTT)(LONG sw); +typedef LONG (__stdcall *tmmlOnCopyData)(HWND hSender, const COPYDATASTRUCT *pcds); +typedef void (__stdcall *tmmlEventVFO)(void); +#endif diff --git a/mmrp.h b/mmrp.h new file mode 100644 index 0000000..53af24f --- /dev/null +++ b/mmrp.h @@ -0,0 +1,43 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +#ifndef MMRP_H +#define MMRP_H + +enum { + MMR_DEFCOMMAND, + MMR_VFO, +}; +#define mmrpstatusRX 0x0001 +#define mmrpstatusTXBUSY 0x0002 +#define mmrpstatusFREQ 0x0004 +#define mmrpstatusDEFCMD 0x0008 + +typedef void (__stdcall *tmmrpSetHandle)(HWND hWnd, UINT uMsg); +typedef LONG (__stdcall *tmmrpOpen)(HWND hWnd, UINT uMsg); +typedef void (__stdcall *tmmrpClose)(void); +typedef DWORD (__stdcall *tmmrpGetStatus)(void); +typedef void (__stdcall *tmmrpSetPTT)(LONG tx); +typedef void (__stdcall *tmmrpPutChar)(BYTE c); +typedef BYTE (__stdcall *tmmrpGetChar)(void); +typedef void (__stdcall *tmmrpPolling)(void); +typedef LONG (__stdcall *tmmrpGetFreq)(void); +typedef LONG (__stdcall *tmmrpGetDefCommand)(void); + +#endif diff --git a/mmsstv.cnt b/mmsstv.cnt new file mode 100644 index 0000000..410afb2 --- /dev/null +++ b/mmsstv.cnt @@ -0,0 +1,56 @@ +:Base mmsstv.hlp +1 MMSSTV +2 Description=IDH_910 +2 Main Screen=IDH_6310 +2 History=IDH_1110 +2 System Requirements=IDH_1310 +2 Modes=IDH_1410 +1 Receive +2 Frequencies=IDH_1510 +2 Tones=IDH_1610 +2 Auto start=IDH_1710 +2 Manual start=IDH_1810 +2 Auto start & restart=IDH_1910 +1 Slant Adjust +2 Manual=IDH_2110 +2 Auto=IDH_2210 +2 Sync Point=IDH_2310 +1 Receive history +2 Images=IDH_2510 +1 Transmission +2 Basics=IDH_2710 +2 Image preparation=IDH_2810 +2 Mode Selection=IDH_2910 +2 Transmission=IDH_3110 +2 Tx Slant=IDH_3210 +2 Tune/ Cw ID=IDH_3310 +1 Templates +2 Functions=IDH_3510 +2 Superimpose=IDH_3610 +1 Stock Area +2 Functions=IDH_3810 +1 Radio Commands +2 Commands=IDH_4010 +1 Demodulator +2 Config=IDH_4210 +2 Zero Cross=IDH_4410 +2 PLL=IDH_4510 +2 VCO Gain=IDH_4610 +2 Loop LPF=IDH_4710 +2 Limiter=IDH_4910 +2 Differentiator=IDH_6410 +2 Out LPF=IDH_4810 +2 Linear Calibration=IDH_5010 +2 Level Converter=IDH_6510 +2 Profile=IDH_5110 +1 Sampling Frequencies +2 Frequencies=IDH_5310 +1 Sound card clock +2 Calibration=IDH_5510 +1 Setup Misc +2 Buffer=IDH_5710 +2 Priority=IDH_5810 +2 Device ID=IDH_5910 +2 Source=IDH_6010 +2 Clock=IDH_6110 +1 Closing Remarks=IDH_6210 diff --git a/mmw.h b/mmw.h new file mode 100644 index 0000000..ed17b76 --- /dev/null +++ b/mmw.h @@ -0,0 +1,46 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +#ifndef MMW_H +#define MMW_H + +typedef void (__stdcall *tmmwPumpMessages)(void); +typedef LONG (__stdcall *tmmwGetTimeout)(void); +typedef void (__stdcall *tmmwSetPTT)(LONG tx); + +typedef LONG (__stdcall *tmmwInOpen)(DWORD sampfreq, DWORD size); +typedef void (__stdcall *tmmwInClose)(void); +typedef BOOL (__stdcall *tmmwInRead)(SHORT *buf); + +typedef LONG (__stdcall *tmmwGetInExist)(void); +typedef BOOL (__stdcall *tmmwIsInCritical)(void); + +typedef LONG (__stdcall *tmmwOutOpen)(DWORD sampfreq, DWORD size); +typedef void (__stdcall *tmmwOutAbort)(void); +typedef void (__stdcall *tmmwOutFlush)(void); +typedef BOOL (__stdcall *tmmwOutWrite)(const SHORT *buf); + +typedef BOOL (__stdcall *tmmwIsOutCritical)(void); +typedef BOOL (__stdcall *tmmwIsOutFull)(void); +typedef LONG (__stdcall *tmmwGetOutRemaining)(void); +typedef LONG (__stdcall *tmmwGetOutCounter)(void); +typedef void (__stdcall *tmmwSetOutCounter)(LONG count); + +#endif + diff --git a/mode.txt b/mode.txt new file mode 100644 index 0000000..a605dc2 --- /dev/null +++ b/mode.txt @@ -0,0 +1,288 @@ +New SSTV modes added in MMSSTV + +Written by JE3HHT Makoto Mori +Translated into English by JA7UDE Nob Oba + + +1. VIS code + + All the even-parity codes in the VIS have already been used now. If I use the remaining odd-parity codes for defining new modes, it is a matter of time to run out of them. For this reason, I have extended the VIS code to 16 bits as follows: + + + 1900 300ms + 1200 10ms + 1900 300ms + 1200 30ms + d0 30ms + d1 30ms + : : + d15 30ms + 1200 30ms + + (d0-d15 : 1-1100Hz, 0-1300Hz) + +When you assign a code to your new mode, it is a good idea to use an odd parity code, which is not in use now, in the least 8 bits (d0-d7), so as not to get the conventional 8-bit VIS decoder confused. For this reason, MMSSTV uses VIS code 23H in d0-d7. If you add a code for your new mode, I would recommend you to assign some code other than 23H in d0-d7, so that you can make full use of upper 8 bits to represent up to 256 modes. + + +2. MP mode + +MP mode is based on the color difference scheme used in PD mode. I have added this mode for alleviating multi-path/jitter effects on the 20-meter band. To increase the scan time for each pixel, the color information is compressed along the vertical axis. + + +Mode Size VIS TW [ms] +MP73 320x256 2523h 140.000 +MP115 320x256 2923h 223.000 +MP140 320x256 2a23h 270.000 +MP175 320x256 2c23h 340.000 + + + 1200Hz 9.000ms + 1500Hz 1.000ms + Y(odd) TW + R-Y TW + B-Y TW + Y(even) TW + (Repeat 128 scans) + + +3. MR/ML mode + +MR/ML mode is based on the color difference scheme used in Robot 24/72 mode. It is aimed to provide good resolution under good condx. The color information is compressed along the horizontal axis. + +Mode Size VIS TW [ms] +MR73 320x256 4523h 138.000 +MR90 320x256 4623h 171.000 +MR115 320x256 4923h 220.000 +MR140 320x256 4a23h 269.000 +MR175 320x256 4c23h 337.000 +ML180 640x496 8523h 176.500 +ML240 640x496 8623h 236.500 +ML280 640x496 8923h 277.500 +ML320 640x496 8a23h 317.500 + + 1200Hz 9.000ms + 1500Hz 1.000ms + Y TW + LP 0.100ms + R-Y TW/2 + LP 0.100ms + B-Y TW/2 + LP 0.100ms + (Repeat 256 or 496 scans) + + LP = output the last pixel signal + +4.MP-Nモード + This is a narrow band version of the MP mode. The scan signals occupy 2044Hz to 2300Hz. + +Mode Size N-VIS TW[ms] +MP73-N 320x256 02h 140.000 +MP110-N 320x256 04h 212.000 +MP140-N 320x256 05h 270.000 + + 1900Hz 9.000ms + 2044Hz 1.000ms + Y(odd) TW + R-Y TW + B-Y TW + Y(even) TW + (Repeat 128 scans) + +5.MC-Nモード + This is a narrow bande version of the RGB mode. The scan signals occupy 2044Hz to 2300Hz. + +Mode Size N-VIS TW[ms] +MC110-N 320x256 14h 143.000 +MC140-N 320x256 15h 180.000 +MC180-N 320x256 16h 232.000 + + 1900Hz 8.000ms + 2044Hz 0.500ms + R TW + G TW + B TW + (Repeat 256 scans) + +7.N-VISコード + The VIS code of the narrow band modes are defined by the 24-bit FSK as follows. One symbol consists of 6 bits. + + 1900Hz 300ms + 2100Hz 100ms + 1900Hz 22ms start bit + D05 22ms (1=1900Hz, 0=2100Hz) + D04 22ms : + D03 22ms : + D02 22ms + D01 22ms + D00 22ms + D15 22ms + D14 22ms + D13 22ms + D12 22ms + D11 22ms + D10 22ms + D25 22ms + D24 22ms + D23 22ms + D22 22ms + D21 22ms + D20 22ms + D35 22ms + D34 22ms + D33 22ms + D32 22ms + D31 22ms + D30 22ms + + D0(D05-D00) = 101101 + D1(D15-D10) = 010101 + D2(D25-D20) = N-VIS + D3(D35-D30) = 010101 .xor. N-VIS + + e.g. MP73-N = 101101 010101 000010 010111 + +It is free to use these modes in any kind of software or equipment. You do not have to inform me. Feel free to do it. + +73 Mako + + +* +* +********** Japanese ************************************************* +MMSSTVで追加したモード + +1.VISコード + 現在偶数パリティのVISコードは既に一杯であり、残りの奇数パリティをそのまま使えばすぐに満杯になるのは時間の問題です。そこでMMSSTVで追加したモードでは以下のようにVISコードを16ビットに拡張してあります。 + + 1900 300ms + 1200 10ms + 1900 300ms + 1200 30ms + d0 30ms + d1 30ms + : : + d15 30ms + 1200 30ms + + (d0-d15 : 1-1100Hz, 0-1300Hz) + + 新規にコードを割り当てる場合、d0-d7までの下位8ビットは現在空きの奇数パリティ部分を使い、既存の8ビットVISデコーダーに対して影響を与えないようにするのが望ましいと思います。 + MMSSTVはこの目的のためにVISコード23Hをd0-d7部分に使用していますが、もしあなたが新規にモードを作成する場合、23H以外の空きのVISコードを使うことをお勧めします。そうすれば上位8ビット分(256種類)をまるまるあなたのモードで埋め尽くすことができます。 + + +2.MPモード + PDモードと同じ方式の色差方式のモードで、20mでのマルチパス/ジッタ対策のために設けました。ピクセル当たりのスキャン時間を長くするために垂直方向の色情報が圧縮されています。 + +Mode Size VIS TW[ms] +MP73 320x256 2523h 140.000 +MP115 320x256 2923h 223.000 +MP140 320x256 2a23h 270.000 +MP175 320x256 2c23h 340.000 + + + 1200Hz 9.000ms + 1500Hz 1.000ms + Y(odd) TW + R-Y TW + B-Y TW + Y(even) TW + (Repeat 128 scans) + +3.MR/MLモード + Robot24/72モードと同じ方式の色差方式のモードで、比較的良好なCondx下で見た目の解像度を得るのが狙いです。水平方向の色情報が圧縮されています。 + +Mode Size VIS TW[ms] +MR73 320x256 4523h 138.000 +MR90 320x256 4623h 171.000 +MR115 320x256 4923h 220.000 +MR140 320x256 4a23h 269.000 +MR175 320x256 4c23h 337.000 +ML180 640x496 8523h 176.500 +ML240 640x496 8623h 236.500 +ML280 640x496 8923h 277.500 +ML320 640x496 8a23h 317.500 + + 1200Hz 9.000ms + 1500Hz 1.000ms + Y TW + LP 0.100ms + R-Y TW/2 + LP 0.100ms + B-Y TW/2 + LP 0.100ms + (Repeat 256 or 496 scans) + + LP=最終ピクセルの信号を出力 + +4.MP-Nモード + MPモードと同じ方式の狭帯域版です。スキャン信号は2044Hz〜2300Hzの範囲に収めます。 + +Mode Size N-VIS TW[ms] +MP73-N 320x256 02h 140.000 +MP110-N 320x256 04h 212.000 +MP140-N 320x256 05h 270.000 + + 1900Hz 9.000ms + 2044Hz 1.000ms + Y(odd) TW + R-Y TW + B-Y TW + Y(even) TW + (Repeat 128 scans) + +5.MC-Nモード + RGBモードの狭帯域版です。スキャン信号は2044Hz〜2300Hzの範囲に収めます。 + +Mode Size N-VIS TW[ms] +MC110-N 320x256 14h 143.000 +MC140-N 320x256 15h 180.000 +MC180-N 320x256 16h 232.000 + + 1900Hz 8.000ms + 2044Hz 0.500ms + R TW + G TW + B TW + (Repeat 256 scans) + +7.N-VISコード + 狭帯域モード用のVISコード(N-VIS)を以下のような24bitsのFSKで定義します。6bitsを1シンボルとして取り扱います。 + + 1900Hz 300ms + 2100Hz 100ms + 1900Hz 22ms start bit + D05 22ms (1=1900Hz, 0=2100Hz) + D04 22ms : + D03 22ms : + D02 22ms + D01 22ms + D00 22ms + D15 22ms + D14 22ms + D13 22ms + D12 22ms + D11 22ms + D10 22ms + D25 22ms + D24 22ms + D23 22ms + D22 22ms + D21 22ms + D20 22ms + D35 22ms + D34 22ms + D33 22ms + D32 22ms + D31 22ms + D30 22ms + + D0(D05-D00) = 101101 + D1(D15-D10) = 010101 + D2(D25-D20) = N-VIS + D3(D35-D30) = 010101 .xor. N-VIS + + e.g. MP73-N = 101101 010101 000010 010111 + + これらのモードを他の装置に組み込むことは完全に自由です。その際、私への連絡は一切必要ありません。 + +73, Mako \ No newline at end of file diff --git a/mstvlog.txt b/mstvlog.txt new file mode 100644 index 0000000..7868f5e --- /dev/null +++ b/mstvlog.txt @@ -0,0 +1,620 @@ +MMSSTV ログ機能マニュアル + + 初版 2001.02.20 JE3HHT 森 誠 + 改定 2001.09.25 JE3HHT 森 誠 + +* 本書はMMTTYのログ機能マニュアルを元に作成しました。一部完全には修正されていない可能性もあります。 + +------------------------------ +○MMSSTVのログ機能について +------------------------------ + 現状ではMMSSTVに装備されているログ機能はコールサイン検索などログとしての最低限に限られています。 + + MMSSTVのカレントログファイルは常に前回オープンしたログファイルです。MMSSTVのタイトルバーに表示されている拡張子が「MDT」の名前がカレントログファイルの名前です。 + このファイルを変更するには、ファイルメニューの「新しいログファイルのオープン」を選択して名前を入力します。普通はあなたのコールサインを名前にしておくと良いでしょう。 + +---------------- +○ログの基本操作 +---------------- + +1)相手局のコールサインをログパネルの「Call」の位置に入力します。 + +2)画面上の「Find」ボタンを押して、過去のQSO記録を調べます。 + +3)相手局を呼び出し、応答があった場合は「QSO」ボタンを押します。これでログに開始時刻が設定されます。 + +4)QSO中にメイン画面ログパネルにある他の項目、また「Data」ボタンを押して「QSOデータ編集画面」を呼び出し必要な項目を入力します。 + +5)QSOが終了したら、「QSO」ボタンを再度押します。これで終了時刻が設定されて1つのQSOが終了します。 + + +------------------- +○QSOデータ編集画面 +------------------- + QSO中にメイン画面の「Data」ボタンを押すとQSOデータ編集画面を表示します。 + + 画面の一番上のタイトル行には + +[検索コールサイン] エンティティ名/大陸名 ローカル時刻 QTH + +の順で表示されています。 + + 画面下側には検索した結果が一覧表で表示されています。 + + また「JCC/JCG」ボタン(またはF7キー)を押すと、JCC/JCG/AJAの選択入力画面が表示されますので、日本の国内局に関しては、ローマ字綴りを入力して候補を絞ってQTHの選択入力を行うこともできます。 + + 画面下側の検索結果は、現在入力中のデータがグレー、完全に一致したものが赤色、基本コールサインが一致したものが緑色、不完全な状態で一致しているものが黒色で表示されます。 + +[例] + 検索したコールサインが KH0/JI3IVL の場合 + KH0/JI3IVL 赤色 + KH0/JI3IVL/P 緑色 + JI3IVL 緑色 + JI3IVL/3 緑色 + 検索したコールサインが IVL の場合 + KH0/JI3IVL 黒色 + JI3IVL 黒色 + JI3IVL/3 黒色 + + +-------------- +○ログ一覧表示 +-------------- + メイン画面のログパネルの「List」ボタンを押すと、現在のログに記録されているQSOデータの一覧表を表示します。 + 過去のデータを修正する場合は、その行をマウスでダブルクリックするか、またはリターンキーを押して「QSOデータ編集画面」を呼び出します。 + + ログ一覧表示画面にもメニューがあり、現状では以下の機能が定義されています。 + + +[ファイルメニュー] +・新しいログファイルのオープン + メイン画面のファイルメニューの「新しいログファイルのオープン」と同じです。ログファイルを変更する場合に選択します。 + +・ディスクのフラッシュ + メイン画面のファイルメニューの「ディスクのフラッシュ」と同じです。編集中の内容をディスクに書き込み、一旦クローズした後再度オープンします。このメニューを時々実行して、停電などで編集内容を失うのを防止します。 + +・インデックス再構築 + 検索用のコールサインインデックスを再構築します。普通はインデックスが壊れることはありませんが、検索が旨く行えない場合は実行してみてください。 + +・MMLOGテキストファイルのロード + MMLOGテキスト形式のファイル(拡張子はLOG)を読みこみます。 + +・選択範囲をMMLOGテキストファイルに書き込み + MMLOGテキスト形式のファイルを作成して、現在選択中の範囲の内容を書き込みます。 + +*選択操作は「Shift+↑」、「Shift+↑」キーで操作します。 + +・インポート + 以下の形式のファイルを読みこみます。 + ・テキスト形式 + ・ADIF形式 + ・LOG200データファイル(L2) + ・Turbo HAMLOGデータファイル(DBS, DBR) + +・選択範囲をエクスポート + 現在選択中の範囲を、以下の形式のファイルに出力します。 + ・テキスト形式 + ・ADIF形式 + ・LOG200データファイル(L2) + ・Turbo HAMLOGデータファイル(DBS, DBR) + + +・MMSSTVに戻る + ログ一覧表を終了し、MMSSTVメイン画面に戻ります。 + + +[編集メニュー] + +・カーソル行の切り取り + 現在のカーソル位置の行をペーストバッファに保存し、ログ上から削除します。 + + +・カーソル行に挿入 + 現在のカーソル位置に1つ行を挿入し、ペーストバッファの内容をコピーします。 + +・すべて選択 + ログをすべて選択状態にします。 + +・選択範囲を削除 + 現在選択中の範囲をすべて削除します。削除したデータを復元することはできませんので、注意して下さい。 + +・選択範囲を日付で並び替え + 現在選択中の範囲を日付/時刻順に並び替えます。 + +[検索メニュー] +・先頭行に移動 + カーソルをログの一番最初に移動します。 + +・最終行に移動 + カーソルをログの一番最後に移動します。 + +・↓方向検索開始 + ログの最終行の方向に向かって指定したコールサインの検索を開始します。 + +・↑方向検索開始 + ログの先頭行の方向に向かって指定したコールサインの検索を開始します。 + +・↓方向検索 + ログの最終行の方向に向かって前回のコールサインで検索します。 + +・↑方向検索開始 + ログの先頭行の方向に向かって前回のコールサインで検索します。 + + +------------------ +○コンテストの場合 +------------------ + 一応コンテストに関連する機能も組み込んでありますが、果たしてSSTVにコンテストが存在するのか不明です。 + +・準備 + ログファイルはコンテスト毎に別の名前にして新しいファイルをオープンします。 + + ログ設定画面を開き、以下の設定をします。 + +  入力設定 + HisRSV コンテストナンバの形式 + + HisRSVで「595」を選択した場合、常に同じナンバーが「%N」マクロにより展開されるようになります。この場合一番最初のデータのHisRSVに「5952509」のようにコンテストナンバーを入れておかなければなりません。 + HisRSVで「595+001」を選択すると、一連番号のコンテンストナンバが「%N」マクロで展開されるようになります。この場合一番最初のHisRSVに「595001」のように初期値を設定しておきます。MMSSTVはQSOを完了する度に番号をインクリメントします。 + + +---------------------------- +○Turbo HAMLOG/Winとのリンク +---------------------------- + JG1MOU 浜田さんが作成されたTurbo HAMLOG/Win(以下Hamlog)とリアルタイムにリンクを行うことができます。この機能を使用するにはHamlogのバージョンが4.48e以降でMMSSTVと同時に実行状態になければなりません。 + MMSSTVはHamlogの検出に成功するとメイン画面のLog枠に「Link to Turbo HAMLOG/Win」を表示します。 + + この機能を利用する場合、Hamlogの「環境設定」の「設定1」の「交信履歴表示で一旦停止」のチェックは必ず外して下さい。 + + 現在以下の機能が利用できます。 + +◎検索 + MMSSTVのLog枠のCallボックスでコールサインを入れてEntキーを押すとHamlogの検索が同時に働きます。IDの自動受信によっても同様の動作になります。 + +◎記録 + MMSSTVのQSOボタンによる通常のログ操作を行うことにより、Hamlogにも同じデータが同時に記録されます。 + +◎周波数ポーリング + Hamlogのカレント周波数データを定期的にポーリングすることができます。この機能を使用する場合、MMSSTVの「ログ設定画面」の「変換」ページで「Link-Frequency polling」のチェックを入れて下さい。 + + + Hamlogとのリンク機能を使用したくない場合は、MMSSTVの「ログ設定画面」の「変換」ページの「Link-Application」をOFFに設定して下さい。 + + この機能は関ハムで浜田さんと偶然お会いすることができ実現しました。浜田さんには大変お世話になりました。有難うございました。 + + +------------------------------------ +○LOG200データファイル(L2)との変換 +------------------------------------ + MMSSTVは、JH3GBD 堀野さん作成のLOG200のデータファイル(L2)との相互変換機能を持っています。ただし細かい点でのフォーマットの相違により、一部の項目が完全に相互変換できない場合がありますので、以下の手順で示すようにMMSSTVでQSOしたデータだけをLOG200ファイルに戻すことを強くお勧めします。 + + LOG200 → MMSSTV 検索操作のために全部変換する + + LOG200 ← MMSSTV MMSSTVでQSOしたものだけ既存のログに追加する + +*LOG200ファイルとの変換は、「ログ一覧表示画面」のファイルメニューの「インポート」および「エクスポート」を選択します。 + +*インポートの際は「追加しますか?」のメッセージに対して「いいえ」を選択します。 + +*「エクスポート」する際、あらかじめ一覧表で、マウスの左ボタンを押しながら上下させるか、または「Shift+↓」,「Shift+↑」キーで操作して、書き込むデータを選択しておきます。MMSSTVは選択されているデータを無条件に指定されたログファイルに追加します。 + + LOG200データファイル(L2)とMMLOGデータファイル(MDT)の仕様の違いにより、変換上以下の制約があります。 + +[MMSSTV -> LOG200] + 全ての情報を失わずに変換できます。MMSSTVの以下の項目はLOG200のリマーク欄にLOG200キー(サブフィールド)に変換して格納されます。 + + CALL CALL[...] コールサインが15文字を超える場合のみ + M M[.] + Env ENV[...] + Pow POW[...] + Opt1 OPT1[...] + Opt2 OPT2[...] + Usr1 USR1[...] + Usr2 USR2[...] + QSL MQSL[...] + +*最新のLOG200(β版)ではコールサインの記録可能な長さが従来の11文字から15文字に拡張されています。 + + またMMSSTVの項目QSL内に以下のLOG200キーがあるとき、それぞれLOG200の該当する項目にキー内の文字列が格納されます。 + + RIG[...] RIG + MyQTH[...] MyQTH + MyRIG[...] MyRIG + TEST[...] CONTEST + + +[LOG200 -> MMSSTV] + 記録されているデータがMMLOGデータファイルの制限を越える場合、その項目の一部の情報を失う可能性があります。特にLOG200のREMARKS欄は任意長の記録が可能なために情報を失う可能性が高く、またsQSLとrQSLも先頭の文字以外を失います。 + + 以下の項目はMMSSTVの項目QSLに、LOG200キーに変換して格納されます。 + + RIG RIG[...] + MyQTH MyQTH[...] + MyRIG MyRIG[...] + CONTEST TEST[...] + + またLOG200のREMARKS欄に以下のLOG200キーがあるとき、それぞれMMSSTVの該当する項目にキー内の文字列が格納されます。 + + CALL[...] CALL + M[.] M + ENV[...] Env + POW[...] Pow + OPT1[...] Opt1 + OPT2[...] Opt2 + USR1[...] Usr1 + USR2[...] Usr2 + MQSL[...] QSL + + +------------------------------------------------ +○Turbo HAMLOGデータファイル(DBS, DBR)との変換 +------------------------------------------------ + MMSSTVは、JG1MOU 浜田さん作成のTurbo Hamlog(以下Hamlog)のデータファイル(DBS, DBR)との相互変換機能を持っています。 + + 一応Hamlogの場合、全ての情報を損なわずに変換できますが、念の為に以下の手順で示すようにMMSSTVでQSOしたデータだけをHamlogファイルに戻すことを強くお勧めします。 + + Hamlog → MMSSTV 検索操作のために全部変換する + + Hamlog ← MMSSTV MMSSTVでQSOしたものだけ既存のログに追加する + +*Hamlogファイルとの変換は、「ログ一覧表示画面」のファイルメニューの「インポート」および「エクスポート」を選択します。 + +*インポートの際は「追加しますか?」のメッセージに対して「いいえ」を選択します。 + +*「エクスポート」する際、あらかじめ一覧表で、マウスの左ボタンを押しながら上下させるか、または「Shift+↓」,「Shift+↑」キーで操作して、書き込むデータを選択しておきます。MMSSTVは選択されているデータを無条件に指定されたログファイルに追加します。 + + Hamlogデータファイル(DBS, DBR)とMMLOGデータファイル(MDT)の仕様の違いにより、変換上以下の制約があります。 + +[MMSSTV -> Hamlog] + MMSSTVの以下の項目はHamlogのリマーク欄にLOG200キー(サブフィールド)に変換して格納されます。 + + CALL ToRadio[...] コールサインが7+3で表現できない場合のみ + M M[.] + Env ENV[...] + Pow POW[...] + End END[...] + + コールサインが「KH0/JI3IVL」のような形式の場合、Hamlogには「JI3IVL/KH0」の形式で格納し、リマーク欄のいずれかに「$DX」の文字列を追加します。 + 相手局がDX局の場合、日付と時刻は常にUTCに変換して格納します。 + + またMMSSTVの項目Usr1に以下のLOG200キーがあるとき、それをHamlogのQSL情報の3文字(M, Send, Rcv)に格納します。 + + QSL[...] MSR + + その他以下の項目の変換を行います。 + + QSL REM2 + Opt1 Code + Opt2 Grid + + MMSSTVのUsr1とUsr2の情報はすべて失います。また以下のMMSSTVの項目は後半の一部を失う可能性があります(括弧内は変換による長さの変化)。 + + MyRST (20->3) + HisRST (20->3) + Name (16->12) + REM (56->54) + Opt1 (8->6) + Opt2 (8->6) + + +[Hamlog -> MMSSTV] + すべての情報を失わずに変換できます。HamlogのREMARKS欄に以下のLOG200キーがあるとき、それぞれMMSSTVの該当する項目にキー内の文字列が格納されます。 + + CALL[...] CALL + ToRadio[...] CALL + M[.] M + ENV[...] Env + POW[...] Pow + END[...] End + + HamlogのQSL情報3文字はMMSSTVのUsr1に以下の形式で格納されます。 + + MSR QSL[MSR] + + Hamlogのリマーク欄のいずれかに「$DX」の文字列が存在し、コールサインが「JI3IVL/KH0」の形式の場合、MMSSTVには「KH0/JI3IVL」の形式で格納されます。 + + その他以下の項目の変換を行います。 + + Code Opt1 + Grid Opt2 + REM2 QSL + +---------------------------------- +○テキストファイルへのエクスポート +---------------------------------- + ファイルメニューの「選択範囲をエクスポート」を選択すると、現在選択中の範囲をテキストファイルに出力します。 + 作成するテキストファイルの書式は次の3つのうちのいずれかです。 + + ・カンマ区切りテキストファイル(CSV形式) + ・TAB区切りテキストファイル + ・区切りなしテキストファイル + + また最大64個のフィールドについて、それぞれのフィールドをどのように変換するかを以下の変換式で定義できます。 + +%NULL このフィールドは変換されない +%EOD この変換式以降のフィールド定義は無視される + +%YYYY-MM-DD 年月日を2000-07-10の形式で展開する +%YY-MM-DD 年月日を00-07-10の形式で展開する +%YYYY/MM/DD 年月日を2000/07/10の形式で展開する +%YY/MM/DD 年月日を00/07/10の形式で展開する +%YY 年を00の形式で展開する +%YYYY 年を2000の形式で展開する +%MM 月を07の形式で展開する +%MON 月をJAN,FEB,MAR, ...の形式で展開する +%MON2 月をJan.,Feb.,Mar., ...の形式で展開する +%DD 日を10の形式で展開する +%HHMM 開始時刻を1234の形式で展開する +%HH:MM 開始時刻を12:34の形式で展開する +%EHHMM 終了時刻を1234の形式で展開する +%EHH:MM 終了時刻を12:34の形式で展開する +%CALL コールサインを展開する +%M 呼び出しマークを展開する +%MY MyRSTを展開する +%HIS HisRSTを展開する +%MYRST MyRSTをモードにより長さ調整して展開する +%HISRST HisRSTをモードにより長さ調整して展開する +%FREQ 周波数をMHz単位の文字列で展開する +%MBAND 周波数をメーターバンドで展開する +%KHZ 周波数をKHz単位の文字列で展開する +%MODE モードを展開する +%POWER 電力を展開する +%NAME 名前を展開する +%QTH QTHを展開する +%REM リマークを展開する +%QSL QSL情報を展開する +%S QSL発送マークを展開する +%R QSL受領マークを展開する +%ENV 自局環境変数を展開する +%OPT1 Opt1を展開する +%OPT2 Opt2を展開する +%USR1 Usr1を展開する +%USR2 Usr2を展開する + +上記以外の文字列はその文字列がそのまま展開されます。 + + Maxを指定すると展開する文字列はその長さで制限されます。区切りなしテキストの場合はMaxの幅で固定されます。 + Max=0の場合は、文字列の長さの制限はなくなります。区切りなしテキストの場合、展開される文字列の幅は固定されなくなります。 + + 「UTC」のチェックを付けると日付と時刻はUTCで出力されます。 + 「”で囲む」にチェックを付けるとすべての項目がダブル文字で囲まれます。 + +---------------------------------- +○テキストファイルからのインポート +---------------------------------- + ファイルメニューの「インポート」を選択すると、ログデータが記載されたテキストファイルをロードします(1行には1QSO分のデータが記載されていなければなりません)。 + ロードするテキストファイルの書式は次の3つのうちのいずれかです。 + + ・カンマ区切りテキストファイル(CSV形式) + ・TAB区切りテキストファイル + ・区切りなしテキストファイル + + また最大64個のフィールドについて、それぞれのフィールドをどのように変換するかを「エクスポート」で解説したのと同じ変換式で定義できます。 + + 「UTC」のチェックを付けると日付と時刻はUTCとしてJSTに変換して読みこまれます。 + + +------------------- +○MMLOGの記録データ +------------------- + + MMLOGデータフォーマットが扱うことのできるQSOデータは以下の通りです。 + + Date - 規格化されている(例えば95.12.23) + JST(開始時刻) - 規格化されている(例えば2104) + END(終了時刻) - 規格化されている(例えば2104) + Call - 16 任意の文字列 + M(呼出しマーク) - 1 文字コード + RST(His,My) - 20 任意の文字列 + Band - 規格化されている(14.025のような入力は可能) + Mode - 規格化されている(CW,SSB,AM,FM,RTTY等) + Pow - 4 文字列 + Name - 16 任意の文字列 + QTH - 28 任意の文字列 + Rem - 56 任意の文字列 + QSL - 54 任意の文字列 + S(QSL Send) - 1 文字コード + R(QSL Recv) - 1 文字コード + Env(自局環境) - 1〜65535までの数値 + Opt1 - 8 任意の文字列 + Opt2 - 8 任意の文字列 + Usr1 - 8 任意の文字列(HisRSTと共用) + Usr2 - 8 任意の文字列(MyRSTと共用) + + + 各データについて解説します。 + +1.日付(Date) +~~~~~~~~~~~~ + 日付を入力します。「QSO」ボタンを押すと自動的に日付は設定されますので、手動で入力する必要はほとんどありません。 + 入力する日付は、「yy.mm.dd」の形式です。 + +95.11.10 1995年、11月、10日 + + ログ設定画面でTimeZoneを「Japan」にしている場合、日付は例え相手局がDXであっても常にJSTで入力して下さい。またTimeZoneを「UTC」にしている場合は +常にUTCで入力して下さい。 + いずれの場合でもMMQSLは相手局がDXの場合自動的にUTCに調整した日付を印刷することができます。 + + +2.開始時刻(JST) +~~~~~~~~~~~~~~~ + 開始時刻を入力します。「QSO」ボタンを押すと自動的に日付は設定されますので、手動で入力する必要はほとんどありません。 + 入力する時刻は、「hhmm」の形式です。 + +2134 21時34分 + + + ログ設定画面でTimeZoneを「Japan」にしている場合、時刻は例え相手局がDXであっても常にJSTで入力して下さい。またTimeZoneを「UTC」にしている場合は +常にUTCで入力して下さい。 + いずれの場合でもMMQSLは相手局がDXの場合自動的にUTCに調整した日付を印刷することができます。 + + +3.コールサイン(Call) +~~~~~~~~~~~~~~~~~~~~ + 相手局のコールサインを入力します。受信画面のコールサイン部分をクリックすると自動的に入力されますので、手動で入力する必要はほとんどないでしょう。 + + 入力するコールサインは以下の例に示すようにどのような形式でも構いません。最大16文字まで入力することができます。 + + JI3IVL + JI3IVL/M + JI3IVL/MM + JI3IVL/3 + JI3IVL/P + JI3IVL/QRP + JI3IVL/JD1 + KH0/JI3IVL + SV/JI3IVL/A + R1/JI3IVL/FJL + JI3IVL/JE3HHT + JI3IVL/MAKO + JI3IVL/MAKO/3 + + コールサインは必ず大文字(アッパーケース)に変換されます。 + + +4.呼出しマーク(M) +~~~~~~~~~~~~~~~~~ + 自局が相手局を呼び出したか、自局が相手局からの呼出しに応答したかを記号で入力します。記号には何を使用しても構いませんが、MMSSTVが自動設定するのは以下の通りです。 + + C 自局が相手局を呼び出した(Runningモードの時) + A 相手局が自局を呼び出した(S&Pモードの時) + + この情報は必要がなければ入力する必要はありませんし、他の整理マークとして使用しても構いません。 + + +5.相手局のRST(His) +~~~~~~~~~~~~~~~~~~~~~ + 相手局の信号強度をRSTで入力します。コンテストを考慮して最大20文字まで入力できます。 + + +6.自局のRST(My) +~~~~~~~~~~~~~~~~~~ + (相手局から伝えられた)自局の信号強度をRSTで入力します。コンテストを考慮して最大20文字まで入力できます。 + + +7.バンドまたは周波数(Band) +~~~~~~~~~~~~~~~~~~~~~~~~~~ + バンドまたは周波数を入力します。以下のバンドコードまたは周波数範囲を入力する事ができます。 + + アマチュアバンド バンドコード 入力可能周波数範囲 + + 1.9MHz帯 1.9 or 1.8 1.000〜1.999 + 3.5MHz帯 3.5 3.000〜3.699 + 3.8MHz帯 3.8 3.700〜3.999 + 7MHz帯 7 7.000〜7.999 + 10MHz帯 10 10.000〜10.999 + 14MHz帯 14 14.000〜14.999 + 18MHz帯 18 18.000〜18.999 + 21MHz帯 21 21.000〜21.999 + 24MHz帯 24 24.000〜24.999 + 28MHz帯 28 28.000〜29.999 + 50MHz帯 50 50.000〜53.999 + 144MHz帯 144 144.000〜149.999 + 430MHz帯 430 430.000〜439.999 + 1200MHz帯 1200 1240.00〜1299.99 + 2400MHz帯 2400 2350.00〜2449.99 + 5600MHz帯 5600 + 10.1GHz帯 10.1G + 10.4GHz帯 10.4G + 24GHz帯 24G + 47GHz帯 47G + 75GHz帯 75G + 142GHz帯 142G + 248GHz帯 248G + 4630KHz 4630 + + 周波数を入力する場合は、上記に示す範囲で「14.025」のように入力します。私の場合は、普通はバンドのみを入力していますが、相手が珍局等の場合は後日の参考のために周波数まで入力しています。 + + クロスバンド(衛星)の場合は、<21/144>のように入力して下さい。この場合バンドコードのみの組み合わせしか入力できません。 + + +8.モード(Mode) +~~~~~~~~~~~~~ + モード(電波形式)を次のようなキーワードで入力します。MMSSTVでは常にデフォルトはSSTVになっています。 + + CW,SSB,AM,FM,RTTY,PAC,FAX,SSTV,ATV,TV,FSTV, + A1,A2,A3,A3A,A3H,A3J,A4,A5,A5C,A5J,A9,A9C, + F1,F2,F3,F4,F5,F9, + P0,P1,P2D,P2E,P2F,P3D,P3E,P3F,P9, + PSK, BPSK, QPSK, HELL, MFSK + + +9.相手局の名前(Name) +~~~~~~~~~~~~~~~~~~~~ + 相手局の名前を入力します。最大16文字まで入力できます。この項目は受信画面内の該当する文字列をマウスでクリックして入力することもできます。 + + +10.相手局のQTH(QTH) +~~~~~~~~~~~~~~~~~~~~~~ + 相手局のQTHを入力します。最大28文字まで入力できます。この項目は受信画面内の該当する文字列をマウスでクリックして入力することもできます。 + +*受信画面のクリック入力は、デフォルトはNAMEを入力する状態になっていますので、QTHをクリック入力する場合は、受信画面のすぐ上の'Name'の文字をクリックして取りこみ先を切り替えてください。 + + +11.備考(Rem) +~~~~~~~~~~~~ + 相手局に紹介してもらったWXやRIG、その他の交信中の特殊な情報等を入力します。最大56文字まで入力できます。 + + +12.QSL情報(QSL) +~~~~~~~~~~~~~~~~~~ + QSLマネージャのコールサインや、相手局が指定してきた住所などのQSL情報を入力します。最大54文字まで入力できます。ビューロ経由でQSLマネージャ宛にカードを送付したい場合は、QSLマネージャのコールサインの先頭に<@>を付加して入力して下さい。MMQSLはこのフィールドに<@>コードがある場合、それに続くコールサインを転送枠に印字するように解読します。また、このフィールドに<$>,<~>,<^>コードで囲まれた文字列がある場合、それぞれの文字列を任意の位置に展開することもできます(MMQSLはKey[...]形式の表記も扱うことができます。詳細はMMQSLのマニュアルの「LOG200キー」を参照して下さい)。 + + 私の場合は以下のように記述して整理しています。 + + @JI3IVL ビューロ経由でマネージャJI3IVLに転送 + JI3IVL JI3IVLの住所に送付 + BOX88,MOSCOW,USSR 記載された住所に送付 + CBA95 95年度版コールブックの住所に送付 + +※ QSL情報に限らず、備考としても使用できます。 + + +13.終了時刻(End) +~~~~~~~~~~~~~~~~ + 終了時刻を入力します。入力する時刻は開始時刻と同じ形式です。この項目はQSOボタンを押すと自動的に設定されますので手動で入力する必要はありません。 + + +14.QSL発行マーク(S) +~~~~~~~~~~~~~~~~~~~~~~ + QSLを発行したかどうかをチェックするマークです。記号はみなさの自由ですが、私の場合は以下のようにしています。 + + N NO QSL + - ビューロ経由で転送済み + p ペンディング(QSLマネージャ不明等) + d ダイレクトで送付する予定 + s SASEまたはSAEで請求する予定 + D ダイレクトで送付済み + S SASEまたはSAEで請求済み + (何も入力しない場合はビューロ経由で転送予定として扱っています。) + + +15.QSL受領マーク(R) +~~~~~~~~~~~~~~~~~~~~~~ + QSLを受領したかどうかをチェックするマークです。記号はみなさんの自由です。私の場合は、以下のような記号でチェックしています。 + + - ビューロ経由で受領 + D ダイレクトで受領 + S SASEまたはSAEで請求された + I 無効なカード(DXCCにクレジットされない等) + + +16.自局環境コード(Env) +~~~~~~~~~~~~~~~~~~~~~~ + 自局の運用環境を1〜65535の範囲の数値で入力します。例えば私の場合は、阿倍野から高槻に引っ越したので、阿倍野時代は1、高槻からは2のように記録し、移動運用の際には、その移動地のJCC・JCG番号を記録しています。またコンテスト等で別の番号を割り振るのも良いかもしれません。結婚などで自分の名前が変わった場合も、この番号を変更すると良いでしょう。 + + +17.オプション1(Opt1)/オプション2(Opt2) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + 主にコンテストの際にマルチや得点を転記するフィールドとして使用します。現状のMMSSTVはにDXエンティティ名、に大陸名を転記するだけで、コンテストナンバ等を自動的に転記する機能は組み込まれていません。 + + +18.ユーザ1(Usr1)/ユーザ2(Usr2) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + この項目は(ユーザ2の場合は)の最後の8文字の領域を共用で使用する特別な項目です。この項目にデータを入力した後、項目)に11文字以上の入力を行うと、この項目の内容は失われます。 + また項目)に11文字以上の記載がある場合に、この項目にデータを入力すると、)の11文字目以降を失います。 + + この項目は最大8文字まで入力できます。 + + 主にコンテストの際にマルチや得点を転記するフィールドとして使用します。現状のMMSSTVはこのフィールドに自動的に転記する機能が組み込まれていません. + \ No newline at end of file diff --git a/onkai.txt b/onkai.txt new file mode 100644 index 0000000..8c6754e --- /dev/null +++ b/onkai.txt @@ -0,0 +1,30 @@ +A 440 423 +B 494 475 +C 523 503 +D 587 564 +E 659 634 +F 698 671 + 711 +G 784 754 + 799 +A 880 846 + 896 +B 988 950 +C 1047 1007 + 1067 +D 1175 1130 + 1197 +E 1319 1268 +F 1397 1343 + 1422 +G 1568 1508 + 1597 +A 1760 1692 + 1792 +B 1976 1900 +C 2093 2013 + 2132 +D 2349 2259 + 2393 +E 2637 2536 +F 2794 2686 diff --git a/res/App.ico b/res/App.ico new file mode 100644 index 0000000..8559817 Binary files /dev/null and b/res/App.ico differ diff --git a/res/SB240B.bmp b/res/SB240B.bmp new file mode 100644 index 0000000..ddba66f Binary files /dev/null and b/res/SB240B.bmp differ diff --git a/res/SB240T.bmp b/res/SB240T.bmp new file mode 100644 index 0000000..43e0498 Binary files /dev/null and b/res/SB240T.bmp differ diff --git a/res/SB256.bmp b/res/SB256.bmp new file mode 100644 index 0000000..2a9854a Binary files /dev/null and b/res/SB256.bmp differ diff --git a/res/SBAHist.bmp b/res/SBAHist.bmp new file mode 100644 index 0000000..c092077 Binary files /dev/null and b/res/SBAHist.bmp differ diff --git a/res/SBAdj.bmp b/res/SBAdj.bmp new file mode 100644 index 0000000..f2fbf4d Binary files /dev/null and b/res/SBAdj.bmp differ diff --git a/res/SBBoxS.bmp b/res/SBBoxS.bmp new file mode 100644 index 0000000..abbb5a4 Binary files /dev/null and b/res/SBBoxS.bmp differ diff --git a/res/SBCBar.bmp b/res/SBCBar.bmp new file mode 100644 index 0000000..1bbb101 Binary files /dev/null and b/res/SBCBar.bmp differ diff --git a/res/SBCW.bmp b/res/SBCW.bmp new file mode 100644 index 0000000..f7027da Binary files /dev/null and b/res/SBCW.bmp differ diff --git a/res/SBCol.bmp b/res/SBCol.bmp new file mode 100644 index 0000000..8eae1b3 Binary files /dev/null and b/res/SBCol.bmp differ diff --git a/res/SBCopy.bmp b/res/SBCopy.bmp new file mode 100644 index 0000000..3ebde5b Binary files /dev/null and b/res/SBCopy.bmp differ diff --git a/res/SBCut.bmp b/res/SBCut.bmp new file mode 100644 index 0000000..132945c Binary files /dev/null and b/res/SBCut.bmp differ diff --git a/res/SBD.bmp b/res/SBD.bmp new file mode 100644 index 0000000..1c74fe6 Binary files /dev/null and b/res/SBD.bmp differ diff --git a/res/SBDA240.bmp b/res/SBDA240.bmp new file mode 100644 index 0000000..23d8b58 Binary files /dev/null and b/res/SBDA240.bmp differ diff --git a/res/SBDList.bmp b/res/SBDList.bmp new file mode 100644 index 0000000..94beff2 Binary files /dev/null and b/res/SBDList.bmp differ diff --git a/res/SBDS240.bmp b/res/SBDS240.bmp new file mode 100644 index 0000000..6ff6df7 Binary files /dev/null and b/res/SBDS240.bmp differ diff --git a/res/SBElip.bmp b/res/SBElip.bmp new file mode 100644 index 0000000..ef01346 Binary files /dev/null and b/res/SBElip.bmp differ diff --git a/res/SBFolder.bmp b/res/SBFolder.bmp new file mode 100644 index 0000000..40e3dc6 Binary files /dev/null and b/res/SBFolder.bmp differ diff --git a/res/SBFree.bmp b/res/SBFree.bmp new file mode 100644 index 0000000..6fe2061 Binary files /dev/null and b/res/SBFree.bmp differ diff --git a/res/SBI.bmp b/res/SBI.bmp new file mode 100644 index 0000000..c162a1f Binary files /dev/null and b/res/SBI.bmp differ diff --git a/res/SBLine.bmp b/res/SBLine.bmp new file mode 100644 index 0000000..0bf55d1 Binary files /dev/null and b/res/SBLine.bmp differ diff --git a/res/SBLoop.bmp b/res/SBLoop.bmp new file mode 100644 index 0000000..8ca66a3 Binary files /dev/null and b/res/SBLoop.bmp differ diff --git a/res/SBMIR.bmp b/res/SBMIR.bmp new file mode 100644 index 0000000..640b251 Binary files /dev/null and b/res/SBMIR.bmp differ diff --git a/res/SBMargin.bmp b/res/SBMargin.bmp new file mode 100644 index 0000000..c0c96b5 Binary files /dev/null and b/res/SBMargin.bmp differ diff --git a/res/SBNSize.bmp b/res/SBNSize.bmp new file mode 100644 index 0000000..82cbe43 Binary files /dev/null and b/res/SBNSize.bmp differ diff --git a/res/SBOrg.bmp b/res/SBOrg.bmp new file mode 100644 index 0000000..9a2a1f4 Binary files /dev/null and b/res/SBOrg.bmp differ diff --git a/res/SBPaste.bmp b/res/SBPaste.bmp new file mode 100644 index 0000000..8ff5a9f Binary files /dev/null and b/res/SBPaste.bmp differ diff --git a/res/SBPic.bmp b/res/SBPic.bmp new file mode 100644 index 0000000..71e7eed Binary files /dev/null and b/res/SBPic.bmp differ diff --git a/res/SBRL.bmp b/res/SBRL.bmp new file mode 100644 index 0000000..4c46dc5 Binary files /dev/null and b/res/SBRL.bmp differ diff --git a/res/SBRR.bmp b/res/SBRR.bmp new file mode 100644 index 0000000..80c600f Binary files /dev/null and b/res/SBRR.bmp differ diff --git a/res/SBRRect.bmp b/res/SBRRect.bmp new file mode 100644 index 0000000..2035b96 Binary files /dev/null and b/res/SBRRect.bmp differ diff --git a/res/SBRatio.bmp b/res/SBRatio.bmp new file mode 100644 index 0000000..1b18d97 Binary files /dev/null and b/res/SBRatio.bmp differ diff --git a/res/SBRot.bmp b/res/SBRot.bmp new file mode 100644 index 0000000..17401e4 Binary files /dev/null and b/res/SBRot.bmp differ diff --git a/res/SBSAdj.bmp b/res/SBSAdj.bmp new file mode 100644 index 0000000..75f8de1 Binary files /dev/null and b/res/SBSAdj.bmp differ diff --git a/res/SBSel.bmp b/res/SBSel.bmp new file mode 100644 index 0000000..17eac10 Binary files /dev/null and b/res/SBSel.bmp differ diff --git a/res/SBStrch.bmp b/res/SBStrch.bmp new file mode 100644 index 0000000..a908eeb Binary files /dev/null and b/res/SBStrch.bmp differ diff --git a/res/SBTest.bmp b/res/SBTest.bmp new file mode 100644 index 0000000..3b04d7f Binary files /dev/null and b/res/SBTest.bmp differ diff --git a/res/SBText.bmp b/res/SBText.bmp new file mode 100644 index 0000000..ac77312 Binary files /dev/null and b/res/SBText.bmp differ diff --git a/res/SBUA240.bmp b/res/SBUA240.bmp new file mode 100644 index 0000000..d86fb86 Binary files /dev/null and b/res/SBUA240.bmp differ diff --git a/res/SBULog.bmp b/res/SBULog.bmp new file mode 100644 index 0000000..3fafb64 Binary files /dev/null and b/res/SBULog.bmp differ diff --git a/res/SBUS240.bmp b/res/SBUS240.bmp new file mode 100644 index 0000000..3416daa Binary files /dev/null and b/res/SBUS240.bmp differ diff --git a/res/SBUTemp.bmp b/res/SBUTemp.bmp new file mode 100644 index 0000000..e319710 Binary files /dev/null and b/res/SBUTemp.bmp differ diff --git a/res/SBUdate.bmp b/res/SBUdate.bmp new file mode 100644 index 0000000..6cbc57f Binary files /dev/null and b/res/SBUdate.bmp differ diff --git a/res/SBView.bmp b/res/SBView.bmp new file mode 100644 index 0000000..7156250 Binary files /dev/null and b/res/SBView.bmp differ diff --git a/res/SBWHist.bmp b/res/SBWHist.bmp new file mode 100644 index 0000000..8f89773 Binary files /dev/null and b/res/SBWHist.bmp differ diff --git a/res/SBZoom.bmp b/res/SBZoom.bmp new file mode 100644 index 0000000..5b23950 Binary files /dev/null and b/res/SBZoom.bmp differ diff --git a/res/copy.bmp b/res/copy.bmp new file mode 100644 index 0000000..7c54ca4 Binary files /dev/null and b/res/copy.bmp differ diff --git a/res/cut.bmp b/res/cut.bmp new file mode 100644 index 0000000..ac0fe53 Binary files /dev/null and b/res/cut.bmp differ diff --git a/res/paste.bmp b/res/paste.bmp new file mode 100644 index 0000000..0437ea5 Binary files /dev/null and b/res/paste.bmp differ diff --git a/sstv.cpp b/sstv.cpp new file mode 100644 index 0000000..5d248c4 --- /dev/null +++ b/sstv.cpp @@ -0,0 +1,3088 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------------- +#include //ja7ude 0521 +#pragma hdrstop + +#include "sstv.h" + +double g_dblToneOffset = 0.0; +//--------------------------------------------------------------------------- +// VCOクラス +CTICK::CTICK() +{ + ptbl[0] = new int[CLOCKMAX]; + memset(ptbl[0], 0, sizeof(int[CLOCKMAX])); + ptbl[1] = new int[CLOCKMAX]; + memset(ptbl[1], 0, sizeof(int[CLOCKMAX])); +} +CTICK::~CTICK() +{ + delete ptbl[0]; + delete ptbl[1]; +} + +void CTICK::Init(void) +{ + m_wsel = 0; + m_wp = ptbl[0]; + m_wcnt = 0; + m_Trig = 0; +} +void CTICK::Write(double d) +{ + *m_wp = int(d); + m_wp++; + m_wcnt++; + if( m_wcnt >= m_Samp ){ + m_wcnt = 0; + m_wsel++; + m_wsel &= 1; + m_wp = ptbl[m_wsel]; + m_Trig = 1; + } +} +int *CTICK::GetData(void) +{ + if( !m_Trig ) return NULL; + m_Trig = 0; + int sel = m_wsel + 1; + sel &= 1; + return ptbl[sel]; +} +//--------------------------------------------------------------------------- +// VCOクラス +CVCO::CVCO() +{ + m_vlock = 0; + m_SampleFreq = SampFreq; + m_FreeFreq = 1900.0 + g_dblToneOffset; + m_TableSize = int(SampFreq*2); + pSinTbl = new double[m_TableSize]; + m_c1 = m_TableSize/16.0; + m_c2 = int( double(m_TableSize) * m_FreeFreq / m_SampleFreq ); + m_z = 0; + double pi2t = 2 * PI / double(m_TableSize); + for( int i = 0; i < m_TableSize; i++ ){ + pSinTbl[i] = sin(double(i) * pi2t); + } +} + +CVCO::~CVCO() +{ + if( m_vlock ) ::VirtualUnlock(pSinTbl, sizeof(double)*m_TableSize); + delete pSinTbl; +} + +void CVCO::SetGain(double gain) +{ + m_c1 = double(m_TableSize) * gain / m_SampleFreq; +} + +void CVCO::VirtualLock(void) +{ + if( !m_vlock ){ + ::VirtualLock(pSinTbl, sizeof(double)*m_TableSize); + m_vlock = 1; + } +} + +void CVCO::SetSampleFreq(double f) +{ + m_SampleFreq = f; + int size = int(m_SampleFreq*2); + if( m_TableSize != size ){ + if( pSinTbl != NULL ){ + if( m_vlock ) ::VirtualUnlock(pSinTbl, sizeof(double)*m_TableSize); + delete pSinTbl; + } + m_TableSize = size; + pSinTbl = new double[m_TableSize]; + if( m_vlock ) ::VirtualLock(pSinTbl, sizeof(double)*m_TableSize); + double pi2t = 2 * PI / double(m_TableSize); + for( int i = 0; i < m_TableSize; i++ ){ + pSinTbl[i] = sin(double(i) * pi2t); + } + } + SetFreeFreq(m_FreeFreq); +} + +void CVCO::SetFreeFreq(double f) +{ + m_FreeFreq = f; + m_c2 = double(m_TableSize) * m_FreeFreq / m_SampleFreq; +} + +void CVCO::InitPhase(void) +{ + m_z = 0; +} + +double CVCO::Do(double d) +{ // -1 to 1 + m_z += (d * m_c1 + m_c2); + while( m_z >= m_TableSize ){ + m_z -= m_TableSize; + } + while( m_z < 0 ){ + m_z += m_TableSize; + } + return pSinTbl[int(m_z)]; +} + + + +//-------------------------------------------------------- +// CScopeクラス +CScope::CScope() +{ + m_ScopeSize = SCOPESIZE; + m_DataFlag = 1; + + pScopeData = NULL; + m_wp = 0; +} + +CScope::~CScope() +{ + m_DataFlag = 1; + if( pScopeData != NULL ){ + delete pScopeData; + pScopeData = NULL; + } +} + +void CScope::InitMem(void) +{ + if( pScopeData == NULL ){ + pScopeData = new double[m_ScopeSize]; + memset(pScopeData, 0, sizeof(double)*m_ScopeSize); + } +} + +void CScope::WriteData(double d) +{ + if( !m_DataFlag ){ + if( m_wp < m_ScopeSize ){ + pScopeData[m_wp] = d; + m_wp++; + if( m_wp >= m_ScopeSize ){ + m_DataFlag = 1; + } + } + } +} + +void CScope::UpdateData(double d) +{ + if( !m_DataFlag ){ + if( m_wp ){ + pScopeData[m_wp-1] = d; + } + } +} + +void CScope::Collect(int size) +{ + m_DataFlag = 1; + InitMem(); + m_ScopeSize = size; + m_wp = 0; + m_DataFlag = 0; +} + + + +//-------------------------------------------------------- +// CNoiseクラス +CNoise::CNoise() +{ + reg = 0x12345; + + memset(Z, 0, sizeof(Z)); + MakeFilter(H, NOISEBPFTAP, ffLPF, SampFreq, 3000.0, 3000.0, 60, 1.0); +}; + +double CNoise::GetNoise(void) +{ + DWORD r = reg >> 1; + if( (reg ^ r) & 1 ){ + r |= 0xffe00000; + } + else { + r &= 0x001fffff; + } + reg = r; + double d = double(reg) / 1000000.0; +// return d; + return DoFIR(H, Z, d, NOISEBPFTAP); // 帯域制限 +} + + +//-------------------------------------------------------- +// CPLLクラス +CPLL::CPLL() +{ + m_err = 0; + m_out = 0; + m_vcoout = 0; + m_vcogain = 1.0; + m_outgain = 32768.0 * m_vcogain; + m_SampleFreq = SampFreq; +// m_Shift = 800.0; +// m_FreeFreq = (1500 + 2300)/2; + m_loopOrder = 1; + m_loopFC = 1500.0; + m_outOrder = 3; + m_outFC = 900.0; + SetWidth(0); +// SetFreeFreq(1500, 2300); + SetSampleFreq(m_SampleFreq); + + m_Max = 1.0; + m_Min = -1.0; + m_d = 0; + m_agc = 1.0; + m_agca = 0.0; +} + +void CPLL::SetWidth(int fNarrow) +{ + if( fNarrow ){ + m_Shift = NARROW_BW; + m_FreeFreq = NARROW_CENTER; + SetFreeFreq(NARROW_LOW, NARROW_HIGH); + } + else { + m_Shift = 800.0; + m_FreeFreq = (1500 + 2300)*0.5; + SetFreeFreq(1500, 2300); + } + SetVcoGain(m_vcogain); +} + +void CPLL::SetVcoGain(double g) +{ + m_vcogain = g; + vco.SetGain(-m_Shift * g); + m_outgain = 32768.0 * m_vcogain; +} + +void CPLL::MakeLoopLPF(void) +{ + loopLPF.MakeIIR(m_loopFC, m_SampleFreq, m_loopOrder, 0, 0); +} + +void CPLL::MakeOutLPF(void) +{ + outLPF.MakeIIR(m_outFC, m_SampleFreq, m_outOrder, 0, 0); +} + +void CPLL::SetFreeFreq(double f1, double f2) +{ + m_FreeFreq = (f1 + f2)/2.0; + m_Shift = (f2 - f1); + vco.SetFreeFreq(m_FreeFreq + g_dblToneOffset); + vco.SetGain(-m_Shift * m_vcogain); +} + +void CPLL::SetSampleFreq(double f) +{ + m_SampleFreq = f; + vco.SetSampleFreq(f); + vco.SetFreeFreq(m_FreeFreq + g_dblToneOffset); + SetVcoGain(1.0); + MakeLoopLPF(); + MakeOutLPF(); +} + +double CPLL::Do(double d) +{ + if( m_Max < d ) m_Max = d; + if( m_Min > d ) m_Min = d; + if( (d >= 0) && (m_d < 0) ){ + m_agc = m_Max - m_Min; + m_d = (5.0/m_agc); + m_agc = (m_agca + m_d) * 0.5; + m_agca = m_d; + m_Max = 1.0; + m_Min = -1.0; + } + m_d = d; + d *= m_agc; +// Loop Filter + m_out = loopLPF.Do(m_err); + if( m_out > 1.5 ){ + m_out = 1.5; + } + else if( m_out < -1.5 ){ + m_out = -1.5; + } +// VCO + m_vcoout = vco.Do(m_out); +// 位相比較 + m_err = m_vcoout * d; + return outLPF.Do(m_out) * m_outgain; +} + +//-------------------------------------------------------- +// CFQCクラス +CFQC::CFQC() +{ + m_Type = 0; + + m_Limit = 1; + m_d = 0; + m_Count = 0; + m_ACount = 0; + m_fq = ZEROFQ; + m_d = 0; + m_out = 0; + m_outOrder = 3; + m_outFC = 900; + m_SmoozFq = 2200; + m_SampFreq = SampFreq; + m_Timer = m_STimer = int(m_SampFreq); + SetWidth(0); + CalcLPF(); +} + +void CFQC::SetWidth(int fNarrow) +{ + if( fNarrow ){ + m_BWH = NARROW_BWH; + m_CenterFQ = NARROW_CENTER + g_dblToneOffset; + m_HighFQ = 2400.0 + g_dblToneOffset; + m_LowFQ = NARROW_AFCLOW + g_dblToneOffset; + } + else { + m_BWH = 400.0; + m_CenterFQ = 1900.0 + g_dblToneOffset; + m_HighFQ = 2400.0 + g_dblToneOffset; + m_LowFQ = 1000.0 + g_dblToneOffset; + } + m_HighVal = (m_HighFQ - m_CenterFQ) / m_BWH; + m_LowVal = (m_LowFQ - m_CenterFQ) / m_BWH; +} + +void CFQC::Clear(void) +{ + m_d = 0; + m_Count = 0; + m_ACount = 0; + m_fq = ZEROFQ; + m_d = 0; + m_out = 0; + m_Timer = m_STimer; +} + +void CFQC::SetSampFreq(double fq) +{ + m_SampFreq = fq; + CalcLPF(); + m_STimer = int(m_SampFreq); +} + +void CFQC::CalcLPF(void) +{ + m_iir.MakeIIR(m_outFC, m_SampFreq, m_outOrder, 0, 0); + if( m_SmoozFq < 500 ) m_SmoozFq = 500.0; + m_fir.SetCount(m_SampFreq/m_SmoozFq); +} + +double CFQC::Do(double d) +{ + double count; + double offset; + + if( d >= 0 ){ + if( m_d < 0 ){ + count = m_Count - m_ACount; + offset = d/(d - m_d); + m_ACount = m_Count - offset; + count -= offset; + if( count >= 1.0 ){ + m_fq = m_SampFreq * 0.5 / count; + if( m_Limit ){ + if( m_fq > m_HighFQ ){ + m_fq = m_HighVal; + } + else if( m_fq < m_LowFQ ){ + m_fq = m_LowVal; + } + else { + m_fq -= m_CenterFQ; + m_fq /= m_BWH; + } + } + else { + m_fq -= m_CenterFQ; + m_fq /= m_BWH; + m_Timer = m_STimer; + } + } + } + } + else { + if( m_d >= 0 ){ + count = m_Count - m_ACount; + offset = d/(d - m_d); + m_ACount = m_Count - offset; + count -= offset; + if( count >= 1.0 ){ + m_fq = m_SampFreq * 0.5 / count; + if( m_Limit ){ + if( m_fq > m_HighFQ ){ + m_fq = m_HighVal; + } + else if( m_fq < m_LowFQ ){ + m_fq = m_LowVal; + } + else { + m_fq -= m_CenterFQ; + m_fq /= m_BWH; + } + } + else { + m_fq -= m_CenterFQ; + m_fq /= m_BWH; + m_Timer = m_STimer; + } + } + } + } + if( !m_Limit && m_Timer ){ + m_Timer--; + if( !m_Timer ) m_fq = -m_CenterFQ/m_BWH; + } + switch(m_Type){ + case 0: // IIR + m_out = m_iir.Do(m_fq); + break; + case 1: // FIR + m_out = m_fir.Avg(m_fq); + break; + default: // OFF + m_out = m_fq; + break; + } + m_d = d; + m_Count++; + return -(m_out * 16384); +} + + +CSSTVSET SSTVSET; +LPCSTR SSTVModeList[]={ + "Robot 36", "Robot 72", "AVT 90", "Scottie 1", "Scottie 2", "ScottieDX", + "Martin 1", "Martin 2", "SC2 180", "SC2 120", "SC2 60", + "PD50", "PD90", "PD120", "PD160", "PD180", "PD240", "PD290", + "P3", "P5", "P7", + "MR73", "MR90", "MR115", "MR140", "MR175", + "MP73", "MP115", "MP140", "MP175", + "ML180", "ML240", "ML280", "ML320", + "Robot 24", "B/W 8", "B/W 12", + "MP73-N", "MP110-N", "MP140-N","MC110-N","MC140-N","MC180-N", +}; +const BYTE SSTVModeOdr[]={ + smRM8, + smRM12, + smR24, + smR36, + smR72, + smAVT, + smSCT1, + smSCT2, + smSCTDX, + smMRT1, + smMRT2, + smSC2_180, + smSC2_120, + smSC2_60, + smPD50, + smPD90, + smPD120, + smPD160, + smPD180, + smPD240, + smPD290, + smP3, + smP5, + smP7, + smMP73, + smMP115, + smMP140, + smMP175, + smMR73, + smMR90, + smMR115, + smMR140, + smMR175, + smML180, + smML240, + smML280, + smML320, + smMN73, + smMN110, + smMN140, + smMC110, + smMC140, + smMC180, +}; +//-------------------------------------------------------- +BOOL __fastcall IsNarrowMode(int mode) +{ + switch(mode){ + case smMN73: + case smMN110: + case smMN140: + case smMC110: + case smMC140: + case smMC180: + return TRUE; + default: + return FALSE; + } +} +//-------------------------------------------------------- +// CSSTVDEMクラス +CSSTVSET::CSSTVSET() +{ + m_fNarrow = m_fTxNarrow = 0; + m_TxMode = smSCT1; + SetMode(smSCT1); + InitIntervalPara(); +} + +void CSSTVSET::InitIntervalPara(void) +{ + for( int i = 0; i < smEND; i++ ){ + m_MS[i] = GetTiming(i) * m_SampFreq / 1000.0; + } + m_MS[2] = 0; // AVT +// m_MSLL = 100.0 * m_SampFreq / 1000.0; // Lowest +// m_MSL = 147.0 * m_SampFreq / 1000.0; // Lowest +// m_MSH = 1050.0 * 3 * m_SampFreq / 1000.0; // Highest + m_MSLL = 50.0 * m_SampFreq / 1000.0; // Lowest + m_MSL = 63.0 * m_SampFreq / 1000.0; // Lowest + m_MSH = 1390.0 * 3 * m_SampFreq / 1000.0; // Highest +} + +void CSSTVSET::SetMode(int mode) +{ + m_SampFreq = sys.m_SampFreq; + m_Mode = mode; + m_fNarrow = IsNarrowMode(mode); + SetSampFreq(); + m_WD = int(m_TW); + m_LM = int(m_TW * m_L) + 1; +} + +void CSSTVSET::SetTxMode(int mode) +{ + m_TxSampFreq = sys.m_SampFreq + sys.m_TxSampOff; + m_TxMode = mode; + m_fTxNarrow = IsNarrowMode(mode); + SetTxSampFreq(); + m_TWD = int(m_TTW); +} + +void CSSTVSET::GetBitmapSize(int &w, int &h, int mode) +{ + switch(mode){ + case smPD120: + case smPD180: + case smPD240: + case smP3: + case smP5: + case smP7: + case smML180: + case smML240: + case smML280: + case smML320: + w = 640; + h = 496; + break; + case smPD160: + w = 512; + h = 400; + break; + case smPD290: + w = 800; + h = 616; + break; + default: // SCT1 + w = 320; + h = 256; + break; + } +} + +void CSSTVSET::GetPictureSize(int &w, int &h, int &hp, int mode) +{ + GetBitmapSize(w, h, mode); + switch(mode){ + case smRM8: + case smRM12: + case smR24: + case smR36: + case smR72: + case smAVT: + hp = 240; + break; + default: + hp = h; + } +} + +void CSSTVSET::SetSampFreq(void) +{ + switch(m_Mode){ + case smR36: + m_KS = 88.0 * m_SampFreq / 1000.0; + m_KS2 = 44.0 * m_SampFreq / 1000.0; + m_OF = 12.0 * m_SampFreq / 1000.0; +// m_OFP = 10.8 * m_SampFreq / 1000.0; + m_OFP = 10.7 * m_SampFreq / 1000.0; + m_SG = (88.0 + 1.25) * m_SampFreq / 1000.0; + m_CG = (88.0 + 3.5) * SampFreq/1000.0; + m_SB = 94.0 * m_SampFreq / 1000.0; + m_CB = m_SB + m_KS2; + m_L = 240; + break; + case smR72: + m_KS = 138.0 * m_SampFreq / 1000.0; + m_KS2 = 69.0 * m_SampFreq / 1000.0; + m_OF = 12.0 * m_SampFreq / 1000.0; + m_OFP = 10.7 * m_SampFreq / 1000.0; + m_SG = 144.0 * m_SampFreq / 1000.0; + m_CG = m_SG + m_KS2; + m_SB = 219.0 * m_SampFreq / 1000.0; + m_CB = m_SB + m_KS2; + m_L = 240; + break; + case smAVT: + m_KS = 125.0 * m_SampFreq / 1000.0; + m_OF = 0.0 * m_SampFreq / 1000.0; + m_OFP = 0.0 * m_SampFreq / 1000.0; + m_SG = m_KS; + m_CG = m_KS + m_SG; + m_SB = m_SG + m_SG; + m_CB = m_KS + m_SB; + m_L = 240; + break; + case smSCT2: + m_KS = 88.064 * m_SampFreq / 1000.0; + m_OF = 10.5 * m_SampFreq / 1000.0; + m_OFP = 10.8 * m_SampFreq / 1000.0; + m_SG = 89.564 * m_SampFreq / 1000.0; + m_CG = m_KS + m_SG; + m_SB = m_SG + m_SG; + m_CB = m_KS + m_SB; + m_L = 256; + break; + case smSCTDX: + m_KS = 345.6 * m_SampFreq / 1000.0; + m_OF = 10.5 * m_SampFreq / 1000.0; +// m_OFP = 9.5 * m_SampFreq / 1000.0; + m_OFP = 10.2 * m_SampFreq / 1000.0; + m_SG = 347.1 * m_SampFreq / 1000.0; + m_CG = m_KS + m_SG; + m_SB = m_SG + m_SG; + m_CB = m_KS + m_SB; + m_L = 256; + break; + case smMRT1: + m_KS = 146.432 * m_SampFreq / 1000.0; + m_OF = 5.434 * m_SampFreq / 1000.0; +// m_OFP = 7.3 * m_SampFreq / 1000.0; + m_OFP = 7.2 * m_SampFreq / 1000.0; + m_SG = 147.004 * m_SampFreq / 1000.0; + m_CG = m_KS + m_SG; + m_SB = m_SG + m_SG; + m_CB = m_KS + m_SB; + m_L = 256; + break; + case smMRT2: + m_KS = 73.216 * m_SampFreq / 1000.0; + m_OF = 5.434 * m_SampFreq / 1000.0; + m_OFP = 7.4 * m_SampFreq / 1000.0; + m_SG = 73.788 * m_SampFreq / 1000.0; + m_CG = m_KS + m_SG; + m_SB = m_SG + m_SG; + m_CB = m_KS + m_SB; + m_L = 256; + break; + case smSC2_180: + m_KS = 235.0 * m_SampFreq / 1000.0; + m_OF = 6.0437 * m_SampFreq / 1000.0; +// m_OFP = 7.5 * m_SampFreq / 1000.0; + m_OFP = 7.8 * m_SampFreq / 1000.0; + m_SG = m_KS; + m_CG = m_KS + m_SG; + m_SB = m_SG + m_SG; + m_CB = m_KS + m_SB; + m_L = 256; + break; + case smSC2_120: + m_KS = 156.5 * m_SampFreq / 1000.0; + m_OF = 6.02248 * m_SampFreq / 1000.0; + m_OFP = 7.5 * m_SampFreq / 1000.0; + m_SG = m_KS; + m_CG = m_KS + m_SG; + m_SB = m_SG + m_SG; + m_CB = m_KS + m_SB; + m_L = 256; + break; + case smSC2_60: + m_KS = 78.128 * m_SampFreq / 1000.0; + m_OF = 6.0006 * m_SampFreq / 1000.0; + m_OFP = 7.9 * m_SampFreq / 1000.0; + m_SG = m_KS; + m_CG = m_KS + m_SG; + m_SB = m_SG + m_SG; + m_CB = m_KS + m_SB; + m_L = 256; + break; + case smPD50: + m_KS = 91.520 * m_SampFreq / 1000.0; + m_OF = 22.080 * m_SampFreq / 1000.0; + m_OFP = 19.300 * m_SampFreq / 1000.0; + m_SG = m_KS; + m_CG = m_KS + m_SG; + m_SB = m_SG + m_SG; + m_CB = m_KS + m_SB; + m_L = 128; + break; + case smPD90: + m_KS = 170.240 * m_SampFreq / 1000.0; + m_OF = 22.080 * m_SampFreq / 1000.0; + m_OFP = 18.900 * m_SampFreq / 1000.0; + m_SG = m_KS; + m_CG = m_KS + m_SG; + m_SB = m_SG + m_SG; + m_CB = m_KS + m_SB; + m_L = 128; + break; + case smPD120: + m_KS = 121.600 * m_SampFreq / 1000.0; + m_OF = 22.080 * m_SampFreq / 1000.0; + m_OFP = 19.400 * m_SampFreq / 1000.0; + m_SG = m_KS; + m_CG = m_KS + m_SG; + m_SB = m_SG + m_SG; + m_CB = m_KS + m_SB; + m_L = 248; + break; + case smPD160: + m_KS = 195.584 * m_SampFreq / 1000.0; + m_OF = 22.080 * m_SampFreq / 1000.0; + m_OFP = 18.900 * m_SampFreq / 1000.0; + m_SG = m_KS; + m_CG = m_KS + m_SG; + m_SB = m_SG + m_SG; + m_CB = m_KS + m_SB; + m_L = 200; + break; + case smPD180: + m_KS = 183.04 * m_SampFreq / 1000.0; + m_OF = 22.080 * m_SampFreq / 1000.0; + m_OFP = 18.900 * m_SampFreq / 1000.0; + m_SG = m_KS; + m_CG = m_KS + m_SG; + m_SB = m_SG + m_SG; + m_CB = m_KS + m_SB; + m_L = 248; + break; + case smPD240: + m_KS = 244.48 * m_SampFreq / 1000.0; + m_OF = 22.080 * m_SampFreq / 1000.0; + m_OFP = 18.900 * m_SampFreq / 1000.0; + m_SG = m_KS; + m_CG = m_KS + m_SG; + m_SB = m_SG + m_SG; + m_CB = m_KS + m_SB; + m_L = 248; + break; + case smPD290: + m_KS = 228.80 * m_SampFreq / 1000.0; + m_OF = 22.080 * m_SampFreq / 1000.0; + m_OFP = 18.900 * m_SampFreq / 1000.0; + m_SG = m_KS; + m_CG = m_KS + m_SG; + m_SB = m_SG + m_SG; + m_CB = m_KS + m_SB; + m_L = 616/2; + break; + case smP3: + m_KS = 133.333 * m_SampFreq / 1000.0; + m_OF = (5.208 + 1.042) * m_SampFreq / 1000.0; + m_OFP = 7.80 * m_SampFreq / 1000.0; + m_SG = (133.333 + 1.042) * m_SampFreq / 1000.0; + m_CG = m_KS + m_SG; + m_SB = m_SG + m_SG; + m_CB = m_KS + m_SB; + m_L = 496; + break; + case smP5: + m_KS = 200.000 * m_SampFreq / 1000.0; + m_OF = (7.813 + 1.562375) * m_SampFreq / 1000.0; + m_OFP = 9.20 * m_SampFreq / 1000.0; + m_SG = (200.000 + 1.562375) * m_SampFreq / 1000.0; + m_CG = m_KS + m_SG; + m_SB = m_SG + m_SG; + m_CB = m_KS + m_SB; + m_L = 496; + break; + case smP7: + m_KS = 266.667 * m_SampFreq / 1000.0; + m_OF = (10.417 + 2.083) * m_SampFreq / 1000.0; + m_OFP = 11.50 * m_SampFreq / 1000.0; + m_SG = (266.667 + 2.083) * m_SampFreq / 1000.0; + m_CG = m_KS + m_SG; + m_SB = m_SG + m_SG; + m_CB = m_KS + m_SB; + m_L = 496; + break; + case smMR73: + //|--KS--|--KS2--|--KS2--| + // SG CG=SB CB + m_KS = 138.0 * m_SampFreq / 1000.0; + m_KS2 = m_KS * 0.5; + m_OF = 10.0 * m_SampFreq / 1000.0; + m_OFP = 10.6 * m_SampFreq / 1000.0; + m_SG = m_KS + 0.1; + m_CG = m_SG + m_KS2; + m_SB = m_CG + 0.1; + m_CB = m_SB + m_KS2; + m_L = 256; + break; + case smMR90: + m_KS = 171.0 * m_SampFreq / 1000.0; + m_KS2 = m_KS * 0.5; + m_OF = 10.0 * m_SampFreq / 1000.0; + m_OFP = 10.6 * m_SampFreq / 1000.0; + m_SG = m_KS + 0.1; + m_CG = m_SG + m_KS2; + m_SB = m_CG + 0.1; + m_CB = m_SB + m_KS2; + m_L = 256; + break; + case smMR115: + m_KS = 220.0 * m_SampFreq / 1000.0; + m_KS2 = m_KS * 0.5; + m_OF = 10.0 * m_SampFreq / 1000.0; + m_OFP = 10.6 * m_SampFreq / 1000.0; + m_SG = m_KS + 0.1; + m_CG = m_SG + m_KS2; + m_SB = m_CG + 0.1; + m_CB = m_SB + m_KS2; + m_L = 256; + break; + case smMR140: + m_KS = 269.0 * m_SampFreq / 1000.0; + m_KS2 = m_KS * 0.5; + m_OF = 10.0 * m_SampFreq / 1000.0; + m_OFP = 10.6 * m_SampFreq / 1000.0; + m_SG = m_KS + 0.1; + m_CG = m_SG + m_KS2; + m_SB = m_CG + 0.1; + m_CB = m_SB + m_KS2; + m_L = 256; + break; + case smMR175: + m_KS = 337.0 * m_SampFreq / 1000.0; + m_KS2 = m_KS * 0.5; + m_OF = 10.0 * m_SampFreq / 1000.0; + m_OFP = 10.6 * m_SampFreq / 1000.0; + m_SG = m_KS + 0.1; + m_CG = m_SG + m_KS2; + m_SB = m_CG + 0.1; + m_CB = m_SB + m_KS2; + m_L = 256; + break; + case smMP73: + m_KS = 140.0 * m_SampFreq / 1000.0; + m_OF = 10.0 * m_SampFreq / 1000.0; + m_OFP = 10.5 * m_SampFreq / 1000.0; + m_SG = m_KS; + m_CG = m_KS + m_SG; + m_SB = m_SG + m_SG; + m_CB = m_KS + m_SB; + m_L = 128; + break; + case smMP115: + m_KS = 223.0 * m_SampFreq / 1000.0; + m_OF = 10.0 * m_SampFreq / 1000.0; + m_OFP = 10.5 * m_SampFreq / 1000.0; + m_SG = m_KS; + m_CG = m_KS + m_SG; + m_SB = m_SG + m_SG; + m_CB = m_KS + m_SB; + m_L = 128; + break; + case smMP140: + m_KS = 270.0 * m_SampFreq / 1000.0; + m_OF = 10.0 * m_SampFreq / 1000.0; + m_OFP = 10.5 * m_SampFreq / 1000.0; + m_SG = m_KS; + m_CG = m_KS + m_SG; + m_SB = m_SG + m_SG; + m_CB = m_KS + m_SB; + m_L = 128; + break; + case smMP175: + m_KS = 340.0 * m_SampFreq / 1000.0; + m_OF = 10.0 * m_SampFreq / 1000.0; + m_OFP = 10.5 * m_SampFreq / 1000.0; + m_SG = m_KS; + m_CG = m_KS + m_SG; + m_SB = m_SG + m_SG; + m_CB = m_KS + m_SB; + m_L = 128; + break; + case smML180: + m_KS = 176.5 * m_SampFreq / 1000.0; + m_KS2 = m_KS * 0.5; + m_OF = 10.0 * m_SampFreq / 1000.0; + m_OFP = 10.6 * m_SampFreq / 1000.0; + m_SG = m_KS + 0.1; + m_CG = m_SG + m_KS2; + m_SB = m_CG + 0.1; + m_CB = m_SB + m_KS2; + m_L = 496; + break; + case smML240: + m_KS = 236.5 * m_SampFreq / 1000.0; + m_KS2 = m_KS * 0.5; + m_OF = 10.0 * m_SampFreq / 1000.0; + m_OFP = 10.6 * m_SampFreq / 1000.0; + m_SG = m_KS + 0.1; + m_CG = m_SG + m_KS2; + m_SB = m_CG + 0.1; + m_CB = m_SB + m_KS2; + m_L = 496; + break; + case smML280: + m_KS = 277.5 * m_SampFreq / 1000.0; + m_KS2 = m_KS * 0.5; + m_OF = 10.0 * m_SampFreq / 1000.0; + m_OFP = 10.6 * m_SampFreq / 1000.0; + m_SG = m_KS + 0.1; + m_CG = m_SG + m_KS2; + m_SB = m_CG + 0.1; + m_CB = m_SB + m_KS2; + m_L = 496; + break; + case smML320: + m_KS = 317.5 * m_SampFreq / 1000.0; + m_KS2 = m_KS * 0.5; + m_OF = 10.0 * m_SampFreq / 1000.0; + m_OFP = 10.6 * m_SampFreq / 1000.0; + m_SG = m_KS + 0.1; + m_CG = m_SG + m_KS2; + m_SB = m_CG + 0.1; + m_CB = m_SB + m_KS2; + m_L = 496; + break; + case smR24: + m_KS = 92.0 * m_SampFreq / 1000.0; + m_KS2 = 46.0 * m_SampFreq / 1000.0; + m_OF = 8.0 * m_SampFreq / 1000.0; + m_OFP = 8.1 * m_SampFreq / 1000.0; + m_SG = m_KS + 4.0 * m_SampFreq / 1000.0; + m_CG = m_SG + m_KS2; + m_SB = m_CG + 4.0 * m_SampFreq / 1000.0; + m_CB = m_SB + m_KS2; + m_L = 120; + break; + case smRM8: + m_KS = 58.89709 * m_SampFreq / 1000.0; + m_OF = 8.0 * m_SampFreq / 1000.0; + m_OFP = 8.2 * m_SampFreq / 1000.0; + m_SG = m_KS; + m_CG = m_KS + m_SG; + m_SB = m_SG + m_SG; + m_CB = m_KS + m_SB; + m_L = 120; + break; + case smRM12: + m_KS = 92.0 * m_SampFreq / 1000.0; + m_OF = 8.0 * m_SampFreq / 1000.0; + m_OFP = 8.0 * m_SampFreq / 1000.0; + m_SG = m_KS; + m_CG = m_KS + m_SG; + m_SB = m_SG + m_SG; + m_CB = m_KS + m_SB; + m_L = 120; + break; + case smMN73: + m_KS = 140.0 * m_SampFreq / 1000.0; + m_OF = 10.0 * m_SampFreq / 1000.0; + m_OFP = 10.5 * m_SampFreq / 1000.0; + m_SG = m_KS; + m_CG = m_KS + m_SG; + m_SB = m_SG + m_SG; + m_CB = m_KS + m_SB; + m_L = 128; + break; + case smMN110: + m_KS = 212.0 * m_SampFreq / 1000.0; + m_OF = 10.0 * m_SampFreq / 1000.0; + m_OFP = 10.5 * m_SampFreq / 1000.0; + m_SG = m_KS; + m_CG = m_KS + m_SG; + m_SB = m_SG + m_SG; + m_CB = m_KS + m_SB; + m_L = 128; + break; + case smMN140: + m_KS = 270.0 * m_SampFreq / 1000.0; + m_OF = 10.0 * m_SampFreq / 1000.0; + m_OFP = 10.5 * m_SampFreq / 1000.0; + m_SG = m_KS; + m_CG = m_KS + m_SG; + m_SB = m_SG + m_SG; + m_CB = m_KS + m_SB; + m_L = 128; + break; + case smMC110: + m_KS = 140.0 * m_SampFreq / 1000.0; + m_OF = 8.0 * m_SampFreq / 1000.0; + m_OFP = 8.95 * m_SampFreq / 1000.0; + m_SG = m_KS; + m_CG = m_KS + m_SG; + m_SB = m_SG + m_SG; + m_CB = m_KS + m_SB; + m_L = 256; + break; + case smMC140: + m_KS = 180.0 * m_SampFreq / 1000.0; + m_OF = 8.0 * m_SampFreq / 1000.0; + m_OFP = 8.75 * m_SampFreq / 1000.0; + m_SG = m_KS; + m_CG = m_KS + m_SG; + m_SB = m_SG + m_SG; + m_CB = m_KS + m_SB; + m_L = 256; + break; + case smMC180: + m_KS = 232.0 * m_SampFreq / 1000.0; + m_OF = 8.0 * m_SampFreq / 1000.0; + m_OFP = 8.75 * m_SampFreq / 1000.0; + m_SG = m_KS; + m_CG = m_KS + m_SG; + m_SB = m_SG + m_SG; + m_CB = m_KS + m_SB; + m_L = 256; + break; + +// case smSCT1: + default: // SCT1 + m_KS = 138.24 * m_SampFreq / 1000.0; + m_OF = 10.5 * m_SampFreq / 1000.0; + m_OFP = 10.7 * m_SampFreq / 1000.0; + m_SG = 139.74 * m_SampFreq / 1000.0; + m_CG = m_KS + m_SG; + m_SB = m_SG + m_SG; + m_CB = m_KS + m_SB; + m_L = 256; + break; + } + m_TW = GetTiming(m_Mode) * m_SampFreq / 1000.0; + switch(m_Mode){ + case smPD120: + case smPD160: + case smPD180: + case smPD240: + case smPD290: + case smP3: + case smP5: + case smP7: + m_KSS = (m_KS - m_KS/480.0); // TW for Y or RGB mode + m_KS2S = (m_KS2 - m_KS2/480.0); // TW for Ry, By + m_KSB = (m_KSS / 1280.0); // TW for black adjutment + break; + case smMP73: + case smMN73: + case smSCTDX: + m_KSS = (m_KS - m_KS/1280.0); // TW for Y or RGB mode + m_KS2S = (m_KS2 - m_KS2/1280.0); // TW for Ry, By + m_KSB = m_KSS / 1280.0; + break; + case smSC2_180: + case smMP115: + case smMP140: + case smMP175: + case smMR90: + case smMR115: + case smMR140: + case smMR175: + case smML180: + case smML240: + case smML280: + case smML320: + case smMN110: + case smMN140: + case smMC110: + case smMC140: + case smMC180: + m_KSS = m_KS; // TW for Y or RGB mode + m_KS2S = m_KS2; // TW for Ry, By + m_KSB = m_KSS / 1280.0; + break; + case smMR73: + m_KSS = (m_KS - m_KS/640.0); // TW for Y or RGB mode + m_KS2S = (m_KS2 - m_KS2/1024.0); // TW for Ry, By + m_KSB = m_KSS / 1024.0; + break; + default: + m_KSS = (m_KS - m_KS/240.0); // TW for Y or RGB mode + m_KS2S = (m_KS2 - m_KS2/240.0); // TW for Ry, By + m_KSB = (m_KSS / 640.0); // TW for black adjutment + break; + } + switch(m_Mode){ + case smMRT1: + case smMRT2: + case smSC2_60: + case smSC2_120: + case smSC2_180: + case smMC110: + case smMC140: + case smMC180: + m_AFCW = 2.0 * SampFreq / 1000.0; + m_AFCB = 1.0 * SampFreq / 1000.0; + break; + default: + m_AFCW = 3.0 * SampFreq / 1000.0; + m_AFCB = 1.5 * SampFreq / 1000.0; + break; + } + if( !m_KSB ) m_KSB++; + + if( sys.m_bCQ100 ){ + double d = m_OFP * 1000.0 / SampFreq; + m_OFP = (d + (1100.0/g_dblToneOffset)) * SampFreq / 1000.0; + } + m_AFCE = m_AFCB + m_AFCW; +} + +double CSSTVSET::GetTiming(int mode) +{ + switch(mode){ + case smR36: + return 150.0; + case smR72: + return 300.0; + case smAVT: + return 375; + case smSCT2: + return 277.692; + case smSCTDX: + return 1050.3; + case smMRT1: + return 446.446; + case smMRT2: + return 226.798; + case smSC2_180: + return 711.0437; + case smSC2_120: + return 475.52248; + case smSC2_60: + return 240.3846; + case smPD50: + return 388.160; + case smPD90: + return 703.040; + case smPD120: + return 508.480; + case smPD160: + return 804.416; + case smPD180: + return 754.24; + case smPD240: + return 1000.00; + case smPD290: + return 937.28; + case smP3: + return 409.375; + case smP5: + return 614.0625; + case smP7: + return 818.75; + case smMR73: + return 286.3; + case smMR90: + return 352.3; + case smMR115: + return 450.3; + case smMR140: + return 548.3; //269*2 + 10; + case smMR175: + return 684.3; //337*2 + 10; + case smMP73: + return 570.0; + case smMP115: + return 902.0; + case smMP140: + return 1090.0; + case smMP175: + return 1370.0; + case smML180: + return 363.3; + case smML240: + return 483.3; + case smML280: + return 565.3; + case smML320: + return 645.3; + case smR24: + return 200.0; + case smRM8: + return 66.89709; + case smRM12: + return 100.0; + case smMN73: + return 570.0; + case smMN110: + return 858.0; + case smMN140: + return 1090.0; + case smMC110: + return 428.5; + case smMC140: + return 548.5; + case smMC180: + return 704.5; + default: // smSCT1 + return 428.22; + } +} + +void CSSTVSET::SetTxSampFreq(void) +{ + int dm1, dm2; + GetPictureSize(dm1, dm2, m_TL, m_TxMode); + m_TTW = GetTiming(m_TxMode) * m_TxSampFreq / 1000.0; +} + + +//-------------------------------------------------------- +// CSSTVDEMクラス +int CSYNCINT::SyncCheckSub(int am) +{ + int i = MSYNCLINE-1; + + int e; + switch(am){ + case smSC2_60: + case smSC2_120: + return 0; + case smR24: + case smR36: + case smMRT2: + case smPD50: + case smPD240: + if( m_fNarrow ) return 0; + e = MSYNCLINE - 4; + break; + case smRM8: + case smRM12: + if( m_fNarrow ) return 0; + e = 0; + break; + case smMN73: + case smMN110: + case smMN140: + case smMC110: + case smMC140: + case smMC180: + if( !m_fNarrow ) return 0; + e = MSYNCLINE - 5; + break; + default: + if( m_fNarrow ) return 0; + e = MSYNCLINE - 3; + break; + } + DWORD deff = (3 * SampFreq) / 1000; + DWORD cml = SSTVSET.m_MS[am]; + DWORD cmh = cml + deff; + cml -= deff; + DWORD w; + for( i--; i >= e; i-- ){ + w = m_MSyncList[i]; + int f = 0; + if( w > SSTVSET.m_MSL ){ + if( m_fNarrow ){ + for( int k = 1; k <= 2; k++ ){ + DWORD ww = w / k; + if( (ww > cml) && (ww < cmh) ) f = 1; + } + } + else { + for( int k = 1; k <= 3; k++ ){ + DWORD ww = w / k; + if( (ww > cml) && (ww < cmh) ) f = 1; + } + } + } + if( !f ) return 0; + } + return 1; +} + +int CSYNCINT::SyncCheck(void) +{ + DWORD deff = (3 * SampFreq) / 1000; + + DWORD w = m_MSyncList[MSYNCLINE-1]; + for( int k = 1; k <= 3; k++ ){ + DWORD ww = w / k; + if( (ww > SSTVSET.m_MSL) && (ww < SSTVSET.m_MSH) ){ + for( int i = 0; i < smEND; i++ ){ + if( SSTVSET.m_MS[i] && (ww > (SSTVSET.m_MS[i]-deff)) && (ww < (SSTVSET.m_MS[i]+deff)) ){ + if( SyncCheckSub(i) ){ + return i + 1; + } + } + } + } + else { + break; + } + } + return 0; +} + +void CSYNCINT::SyncInc(void) +{ + m_MSyncCnt++; +} + +void CSYNCINT::SyncTrig(int d) +{ + m_MSyncIntMax = d; + m_MSyncIntPos = m_MSyncCnt; +} + +void CSYNCINT::SyncMax(int d) +{ + if( m_MSyncIntMax < d ){ + m_MSyncIntMax = d; + m_MSyncIntPos = m_MSyncCnt; + } +} + +int CSYNCINT::SyncStart(void) +{ + int ss = 0; + if( m_MSyncIntMax ){ + if( (m_MSyncIntPos - m_MSyncACnt) > SSTVSET.m_MSLL ){ + m_MSyncACnt = m_MSyncIntPos - m_MSyncACnt; + memcpy(m_MSyncList, &m_MSyncList[1], sizeof(int) * (MSYNCLINE - 1)); + m_MSyncList[MSYNCLINE - 1] = m_MSyncACnt; + if( m_MSyncACnt > SSTVSET.m_MSL ){ + ss = SyncCheck(); + } + m_MSyncACnt = m_MSyncIntPos; + } + m_MSyncIntMax = 0; + } + return ss; +} +//-------------------------------------------------------- +// CSSTVDEMクラス +CSSTVDEM::CSSTVDEM() +{ + m_bpf = 1; // wide + m_ad = 0; + + m_StgBuf = NULL; + m_StgB12 = NULL; + m_BWidth = 1400 * SampFreq / 1000; + int n = SSTVDEMBUFMAX * m_BWidth; + m_Buf = new short[n]; + m_B12 = new short[n]; + ::VirtualLock(m_Buf, n); + ::VirtualLock(m_B12, n); + memset(m_Buf, 0, n); + memset(m_B12, 0, n); + + m_pll.SetSampleFreq(SampFreq); + m_pll.SetVcoGain(1.0); + m_pll.SetFreeFreq(1500, 2300); + m_pll.m_loopOrder = 1; + m_pll.m_loopFC = 1500; + m_pll.m_outOrder = 3; + m_pll.m_outFC = 900; + m_pll.MakeLoopLPF(); + m_pll.MakeOutLPF(); + + memset(HBPF, 0, sizeof(HBPF)); + memset(HBPFS, 0, sizeof(HBPFS)); + memset(HBPFN, 0, sizeof(HBPFN)); +// memset(Z, 0, sizeof(Z)); + CalcBPF(); + + m_iir11.SetFreq(1080 + g_dblToneOffset, SampFreq, 80.0); + m_iir12.SetFreq(1200 + g_dblToneOffset, SampFreq, 100.0); + m_iir13.SetFreq(1320 + g_dblToneOffset, SampFreq, 80.0); + m_iir19.SetFreq(1900 + g_dblToneOffset, SampFreq, 100.0); + m_iirfsk.SetFreq(FSKSPACE + g_dblToneOffset, SampFreq, 100.0); + m_lpf11.MakeIIR(50, SampFreq, 2, 0, 0); + m_lpf12.MakeIIR(50, SampFreq, 2, 0, 0); + m_lpf13.MakeIIR(50, SampFreq, 2, 0, 0); + m_lpf19.MakeIIR(50, SampFreq, 2, 0, 0); + m_lpffsk.MakeIIR(50, SampFreq, 2, 0, 0); + + pRep = NULL; + + m_wPage = m_rPage = 0; + m_wBase = 0; + m_wCnt = 0; + m_rBase = 0; + m_Skip = 0; + m_Sync = 0; + m_SyncMode = 0; + m_ScopeFlag = 0; + m_LoopBack = 0; + m_Lost = 0; + + m_lvl.m_agcfast = 1; + m_afc = 1; + + m_Tick = 0; + pTick = NULL; + m_Avg.SetCount(2.5*SampFreq/1000.0); + m_AFCAVG.SetCount(15); + m_AFCFQ = 0; + m_AFCInt = 100 * SampFreq / 1000.0; + m_AFCDis = 0; + + m_sint1.Reset(); + m_sint2.Reset(); + m_sint3.m_fNarrow = TRUE; + m_sint3.Reset(); + m_MSync = 1; // Sync remote start ON + m_SyncRestart = 1; + m_SyncAVT = 0; + + m_SenseLvl = 1; + SetSenseLvl(); + + m_Type = 2; + m_ReqSave = 0; + m_LevelType = 0; + + m_fskrec = 0; + m_fskNRrec = 0; + m_fskdecode = 0; + m_fskmode = 0; + + m_Repeater = 0; + m_RepSQ = 6000; + m_RepTone = 1750; + m_repmode = 0; + m_repANS = m_repRLY = m_repRX = m_repTX = 0; + InitRepeater(); + SetRepSenseLvl(); +} + +CSSTVDEM::~CSSTVDEM() +{ + ::VirtualUnlock(m_Buf, SSTVDEMBUFMAX * m_BWidth); + ::VirtualUnlock(m_B12, SSTVDEMBUFMAX * m_BWidth); + delete m_B12; + delete m_Buf; + FreeRxBuff(); + if( pRep != NULL ){ + delete pRep; + } +} + +void CSSTVDEM::CalcBPF(double *H1, double *H2, double *H3, int &bpftap, int bpf, int mode) +{ + int lfq = (m_SyncRestart ? 1100 : 1200) + g_dblToneOffset; + int lfq2 = 400 + g_dblToneOffset; + if( lfq2 < 50 ) lfq2 = 50; + switch(bpf){ + case 1: // Wide + bpftap = 24 * SampFreq / 11025.0; + MakeFilter(H1, bpftap, ffBPF, SampFreq, lfq, 2600 + g_dblToneOffset, 20, 1.0); + MakeFilter(H2, bpftap, ffBPF, SampFreq, lfq2, 2500 + g_dblToneOffset, 20, 1.0); +// MakeFilter(H3, bpftap, ffBPF, SampFreq, NARROW_BPFLOW-200, NARROW_BPFHIGH, 20, 1.0); + break; + case 2: // Narrow + bpftap = 64 * SampFreq / 11025.0; + MakeFilter(H1, bpftap, ffBPF, SampFreq, lfq, 2500 + g_dblToneOffset, 40, 1.0); + MakeFilter(H2, bpftap, ffBPF, SampFreq, lfq2, 2500 + g_dblToneOffset, 20, 1.0); +// MakeFilter(H3, bpftap, ffBPF, SampFreq, NARROW_BPFLOW-100, NARROW_BPFHIGH, 40, 1.0); + break; + case 3: // Very Narrow + bpftap = 96 * SampFreq / 11025.0; + MakeFilter(H1, bpftap, ffBPF, SampFreq, lfq, 2400 + g_dblToneOffset, 50, 1.0); + MakeFilter(H2, bpftap, ffBPF, SampFreq, lfq2, 2500 + g_dblToneOffset, 20, 1.0); +// MakeFilter(H3, bpftap, ffBPF, SampFreq, NARROW_BPFLOW, NARROW_BPFHIGH, 50, 1.0); + break; + default: + bpftap = 0; + break; + } + CalcNarrowBPF(H3, bpftap, bpf, mode); +} + +void CSSTVDEM::CalcNarrowBPF(double *H3, int bpftap, int bpf, int mode) +{ + int low, high; + switch(mode){ + case smMN73: + low = 1600; high = 2500; + break; + case smMN110: + low = 1600; high = 2500; + break; + case smMN140: + low = 1700; high = 2400; + break; + case smMC110: + low = 1600; high = 2500; + break; + case smMC140: + low = 1650; high = 2500; + break; + case smMC180: + low = 1700; high = 2400; + break; + default: + low = 1600; high = 2500; + break; + } + low += g_dblToneOffset; + high += g_dblToneOffset; + switch(bpf){ + case 1: // Wide + MakeFilter(H3, bpftap, ffBPF, SampFreq, low-200, high, 20, 1.0); + break; + case 2: // Narrow + MakeFilter(H3, bpftap, ffBPF, SampFreq, low-100, high, 40, 1.0); + break; + case 3: // Very Narrow + MakeFilter(H3, bpftap, ffBPF, SampFreq, low, high, 50, 1.0); + break; + default: + break; + } +} + +void CSSTVDEM::CalcBPF(void) +{ + CalcBPF(HBPF, HBPFS, HBPFN, m_bpftap, m_bpf, SSTVSET.m_Mode); + m_BPF.Create(m_bpftap); +} + +void CSSTVDEM::SetBPF(int bpf) +{ + if( bpf != m_bpf ){ + int delay = m_bpftap; + m_bpf = bpf; + CalcBPF(); + if( m_Sync ){ + delay = (m_bpftap - delay) / 2; + m_Skip = delay; + } + } +} + +void CSSTVDEM::FreeRxBuff(void) +{ + if( m_StgBuf != NULL ){ + delete m_StgB12; + delete m_StgBuf; + m_StgBuf = NULL; + m_StgB12 = NULL; + m_wStgLine = 0; + } +} + +void CSSTVDEM::OpenCloseRxBuff(void) +{ + if( m_Sync ) return; + + if( sys.m_UseRxBuff == 1 ){ + if( m_StgBuf == NULL ){ + int n = 257 * 1100 * SampFreq / 1000; + m_StgBuf = new short[n]; + m_StgB12 = new short[n]; + memset(m_StgBuf, 0, n); + memset(m_StgB12, 0, n); + m_RxBufAllocSize = n; + m_wStgLine = 0; + } + } + else { + FreeRxBuff(); + } +} + +void CSSTVDEM::Idle(double d) +{ + if( !sys.m_TestDem ) m_lvl.Do(d); +} + +void CSSTVDEM::SetTickFreq(int f) +{ + if( !f ) f = 1200; + m_iir12.SetFreq(f + g_dblToneOffset, SampFreq, 100.0); + m_TickFreq = f; +} + +void CSSTVDEM::InitAFC(void) +{ + m_AFCAVG.SetCount(m_AFCAVG.Max); + if( m_fNarrow ){ + m_AFCData = m_AFCLock = (NARROW_CENTER-NARROW_SYNC)*16384/NARROW_BWH; + } + else { + m_AFCData = m_AFCLock = ((1900-1200)*16384)/400.0; + } + m_AFCFlag = 0; + m_AFCDiff = 0.0; + m_AFCGard = 10; + m_AFCCount = 0; + m_AFCDis = 0; + InitTone(0); + if( m_fNarrow ){ + m_AFC_LowVal = (NARROW_CENTER - NARROW_AFCLOW) * 16384.0 / NARROW_BWH; // (Center - SyncLow) * 16384 / BWH + m_AFC_HighVal = (NARROW_CENTER - NARROW_AFCHIGH) * 16384.0 / NARROW_BWH; // (Center - SyncHigh) * 16384 / BWH + m_AFC_SyncVal = (NARROW_CENTER - NARROW_SYNC) * 16384.0 / NARROW_BWH; // (Center - Sync) * 16384 / BWH + m_AFC_BWH = NARROW_BWH / 16384.0; // BWH / 16384.0; + if( sys.m_bCQ100 ){ + m_AFC_LowVal = (NARROW_CENTER - NARROW_SYNC - 50) * 16384.0 / NARROW_BWH; // (Center - SyncLow) * 16384 / BWH + m_AFC_HighVal = (NARROW_CENTER - NARROW_SYNC + 50) * 16384.0 / NARROW_BWH; // (Center - SyncHigh) * 16384 / BWH + } + } + else { + m_AFC_LowVal = (1900 - 1000) * 16384.0 / 400; // (Center - SyncLow) * 16384 / BWH + m_AFC_HighVal = (1900 - 1325) * 16384.0 / 400; // (Center - SyncHigh) * 16384 / BWH + m_AFC_SyncVal = (1900 - 1200) * 16384.0 / 400; // (Center - Sync) * 16384 / BWH + m_AFC_BWH = 400 / 16384.0; // BWH / 16384.0; + if( sys.m_bCQ100 ){ + m_AFC_LowVal = (1900 - 1200 - 50) * 16384.0 / 400; // (Center - SyncLow) * 16384 / BWH + m_AFC_HighVal = (1900 - 1200 + 50) * 16384.0 / 400; // (Center - SyncHigh) * 16384 / BWH + } + } +} + +void CSSTVDEM::InitTone(int dfq) +{ + if( m_AFCFQ != dfq ){ + m_iir11.SetFreq(1080+dfq + g_dblToneOffset, SampFreq, 80.0); + m_iir12.SetFreq(1200+dfq + g_dblToneOffset, SampFreq, 100.0); + m_iir13.SetFreq(1320+dfq + g_dblToneOffset, SampFreq, 80.0); + m_iir19.SetFreq(1900+dfq + g_dblToneOffset, SampFreq, 100.0); + m_iirfsk.SetFreq(FSKSPACE+dfq + g_dblToneOffset, SampFreq, 100.0); + m_AFCFQ = dfq; + } +} + +void CSSTVDEM::SetWidth(int fNarrow) +{ + if( m_fNarrow != fNarrow ){ + m_fNarrow = fNarrow; + m_hill.SetWidth(fNarrow); + m_fqc.SetWidth(fNarrow); + m_pll.SetWidth(fNarrow); + } +} + +void CSSTVDEM::Start(void) +{ + SetWidth(IsNarrowMode(SSTVSET.m_Mode)); + + InitAFC(); + m_fqc.Clear(); + m_SyncMode = -1; + m_Sync = 0; + m_Skip = 0; + m_wPage = m_rPage = 0; + m_wBase = 0; + m_wLine = 0; + m_wCnt = 0; + m_rBase = 0; + OpenCloseRxBuff(); + m_wBgn = 2; + m_Lost = 0; + + int eg = SSTVSET.m_WD + SSTVSET.m_KSB + SSTVSET.m_KSB; + int i, j; + for( i = 0; i < SSTVDEMBUFMAX; i++ ){ + for( j = SSTVSET.m_WD; j < eg; j++ ){ + m_Buf[i*m_BWidth + j] = -16384; + } + } + + m_Sync = 1; + m_SyncMode = 0; + SetWidth(m_fNarrow); + if( m_fNarrow ) CalcNarrowBPF(HBPFN, m_bpftap, m_bpf, SSTVSET.m_Mode); +} + +void CSSTVDEM::Start(int mode, int f) +{ + m_fqc.Clear(); + m_sint1.Reset(); + m_sint2.Reset(); + m_sint3.Reset(); + m_wBgn = 0; + m_rBase = 0; + m_SyncMode = 0; + SSTVSET.SetMode(mode); + m_Sync = 0; + SetWidth(IsNarrowMode(mode)); + if( f ){ + Start(); + } + else { + m_SyncMode = -1; + } +} + +void CSSTVDEM::Stop(void) +{ + if( m_AFCFQ ){ + if( m_fskdecode ){ + m_iir11.SetFreq(1080 + g_dblToneOffset, SampFreq, 80.0); + m_iir12.SetFreq(1200 + g_dblToneOffset, SampFreq, 100.0); + m_iir13.SetFreq(1320 + g_dblToneOffset, SampFreq, 80.0); + } + else { + InitTone(0); + } + } + m_fqc.Clear(); + m_sint1.Reset(); + m_sint2.Reset(); + m_sint3.Reset(); + m_wBgn = 0; + m_SyncMode = 512; + m_Sync = 0; + m_SyncAVT = 0; + m_Skip = 0; + SetWidth(0); +} + +void CSSTVDEM::SetSenseLvl(void) +{ + switch(m_SenseLvl){ + case 1: + m_SLvl = 3500; + m_SLvl2 = m_SLvl * 0.5; + m_SLvl3 = 5700; + break; + case 2: + m_SLvl = 4800; + m_SLvl2 = m_SLvl * 0.5; + m_SLvl3 = 6800; + break; + case 3: + m_SLvl = 6000; + m_SLvl2 = m_SLvl * 0.5; + m_SLvl3 = 8000; + break; + default: + m_SLvl = 2400; + m_SLvl2 = m_SLvl * 0.5; + m_SLvl3 = 5000; + break; + } +} + +void CSSTVDEM::Do(double s) +{ + if( (s > 24578.0) || (s < -24578.0) ){ + m_OverFlow = 1; + } + double d = (s + m_ad) * 0.5; // LPF + m_ad = s; + if( m_bpf ){ + if( m_Sync || (m_SyncMode >= 3) ){ + d = m_BPF.Do(d, m_fNarrow ? HBPFN : HBPF); + } + else { + d = m_BPF.Do(d, HBPFS); + } + } + m_lvl.Do(d); + double ad = m_lvl.AGC(d); + + d = ad * 32; + if( d > 16384.0 ) d = 16384.0; + if( d < -16384.0 ) d = -16384.0; + + double d11; + double d12; + double d13; + double d19; + double dsp; + + d12 = m_iir12.Do(d); + if( d12 < 0.0 ) d12 = -d12; + d12 = m_lpf12.Do(d12); + + d19 = m_iir19.Do(d); + if( d19 < 0.0 ) d19 = -d19; + d19 = m_lpf19.Do(d19); + + dsp = m_iirfsk.Do(d); + if( dsp < 0.0 ) dsp = -dsp; + dsp = m_lpffsk.Do(dsp); + DecodeFSK(int(d19), int(dsp)); + + if( m_Repeater && !m_Sync && (pRep != NULL) ){ + double dsp; + dsp = pRep->m_iirrep.Do(d); + if( dsp < 0.0 ) dsp = -dsp; + dsp = pRep->m_lpfrep.Do(dsp); + if( m_RepSQ ){ + m_repsig = pRep->m_lmsrep.Sig(m_ad); + } + Repeater(int(dsp), int(d12), int(d19)); + } + + if( m_fNarrow ){ + if( m_ScopeFlag ){ + m_Scope[0].WriteData(d19); + } + if( m_LevelType ) m_SyncLvl.Do(d19); + } + else { + if( m_ScopeFlag ){ + m_Scope[0].WriteData(d12); + } + if( m_LevelType ) m_SyncLvl.Do(d12); + + } + if( m_Tick && (pTick != NULL) ){ + pTick->Write(d12); + return; + } + + if( !m_Sync || m_SyncRestart || m_SyncAVT ){ + m_sint1.SyncInc(); + m_sint2.SyncInc(); + m_sint3.SyncInc(); + d11 = m_iir11.Do(d); + if( d11 < 0.0 ) d11 = -d11; + d11 = m_lpf11.Do(d11); + + switch(m_SyncMode){ + case 0: // 自動開始 + if( !m_Sync && m_MSync ){ + m_VisData = m_sint1.SyncStart(); + if( m_VisData > 0 ){ + SSTVSET.SetMode(m_VisData-1); + Start(); + } + else if( (d12 > d19) && (d12 > m_SLvl2) && ((d12-d19) >= m_SLvl2) ){ + m_sint2.SyncMax(d12); + } + else { + m_VisData = m_sint2.SyncStart(); + if( m_VisData > 0 ){ + m_VisData--; + switch(m_VisData){ + case smSCT1: + case smMRT1: + case smMRT2: + case smSC2_180: + SSTVSET.SetMode(m_VisData); + Start(); + break; + default: + break; + } + } + } +#if NARROW_SYNC == 1900 + if( (d19 > d12) && (d19 > dsp) && (d19 > m_SLvl3) && ((d19-d12) >= m_SLvl3) && ((d19-dsp) >= m_SLvl) ){ + if( m_sint3.m_SyncPhase ){ + m_sint3.SyncMax(d19); + } + else { + m_sint3.SyncTrig(d19); + m_sint3.m_SyncPhase++; + } + } + else if( m_sint3.m_SyncPhase ){ + m_sint3.m_SyncPhase = 0; + m_VisData = m_sint3.SyncStart(); + if( m_VisData > 0 ){ + m_VisData--; + SSTVSET.SetMode(m_VisData); + Start(); + } + } +#endif + } + if( (d12 > d19) && (d12 > m_SLvl) && ((d12-d19) >= m_SLvl) ){ + m_SyncMode++; + m_SyncTime = 15 * sys.m_SampFreq/1000; + if( !m_Sync && m_MSync ) m_sint1.SyncTrig(d12); + } + break; + case 1: // 1200Hz(30ms)の継続チェック + if( !m_Sync && m_MSync ){ + if( (d12 > d19) && (d12 > m_SLvl2) && ((d12-d19) >= m_SLvl2) ){ + m_sint2.SyncMax(d12); + } + } + if( (d12 > d19) && (d12 > m_SLvl) && ((d12-d19) >= m_SLvl) ){ + if( !m_Sync && m_MSync ){ + m_sint1.SyncMax(d12); + } + m_SyncTime--; + if( !m_SyncTime ){ + m_SyncMode++; + m_SyncTime = 30 * sys.m_SampFreq/1000; + m_VisData = 0; + m_VisCnt = 8; + } + } + else { + m_SyncMode = 0; + } + break; + case 2: // Vis decode + case 9: + d13 = m_iir13.Do(d); + if( d13 < 0.0 ) d13 = -d13; + d13 = m_lpf13.Do(d13); + m_SyncTime--; + if( !m_SyncTime ){ + if( ((d11 < d19) && (d13 < d19)) || + (fabs(d11-d13) < (m_SLvl2)) ){ + m_SyncMode = 0; + } + else { + m_SyncTime = 30 * sys.m_SampFreq/1000; + m_VisData = m_VisData >> 1; + if( d11 > d13 ) m_VisData |= 0x0080; + m_VisCnt--; + if( !m_VisCnt ){ + if( m_SyncMode == 2 ){ + m_SyncMode++; + switch(m_VisData){ + case 0x82: // RM8 + m_NextMode = smRM8; + break; + case 0x86: // RM12 + m_NextMode = smRM12; + break; + case 0x84: // R24 + m_NextMode = smR24; + break; + case 0x88: // R36 + m_NextMode = smR36; + break; + case 0x0c: // R72 + m_NextMode = smR72; + break; + case 0x44: // AVT + m_NextMode = smAVT; + break; + case 0x3c: // SCT1 + m_NextMode = smSCT1; + break; + case 0xb8: // SCT2 + m_NextMode = smSCT2; + break; + case 0xcc: // SCTDX + m_NextMode = smSCTDX; + break; + case 0xac: // MRT1 + m_NextMode = smMRT1; + break; + case 0x28: // MRT2 + m_NextMode = smMRT2; + break; + case 0xb7: // SC2-180 $37 00110111 + m_NextMode = smSC2_180; + break; + case 0x3f: // SC2-120 $3f 00111111 + m_NextMode = smSC2_120; + break; + case 0xbb: // SC2-60 $3b 10111011 + m_NextMode = smSC2_60; + break; + case 0xdd: // PD50 $5d 01011101 + m_NextMode = smPD50; + break; + case 0x63: // PD90 $63 01100011 + m_NextMode = smPD90; + break; + case 0x5f: // PD120 $5f 01011111 + m_NextMode = smPD120; + break; + case 0xe2: // PD160 $62 11100010 + m_NextMode = smPD160; + break; + case 0x60: // PD180 $60 01100000 + m_NextMode = smPD180; + break; + case 0xe1: // PD240 $61 11100001 + m_NextMode = smPD240; + break; + case 0xde: // PD290 $5e 11011110 + m_NextMode = smPD290; + break; + case 0x71: // P3 $71 01110001 + m_NextMode = smP3; + break; + case 0x72: // P5 $71 01110010 + m_NextMode = smP5; + break; + case 0xf3: // P7 $73 11110011 + m_NextMode = smP7; + break; + case 0x23: // MM 拡張 VIS + m_SyncMode = 9; + m_VisData = 0; + m_VisCnt = 8; + break; + default: + m_SyncMode = 0; + break; + } + } + else { // 拡張 VIS + m_SyncMode = 3; + switch(m_VisData){ + case 0x45: // MR73 + m_NextMode = smMR73; + break; + case 0x46: // MR90 + m_NextMode = smMR90; + break; + case 0x49: // MR115 + m_NextMode = smMR115; + break; + case 0x4a: // MR140 + m_NextMode = smMR140; + break; + case 0x4c: // MR175 + m_NextMode = smMR175; + break; + case 0x25: // MP73 + m_NextMode = smMP73; + break; + case 0x29: // MP115 + m_NextMode = smMP115; + break; + case 0x2a: // MP140 + m_NextMode = smMP140; + break; + case 0x2c: // MP175 + m_NextMode = smMP175; + break; + case 0x85: // ML180 + m_NextMode = smML180; + break; + case 0x86: // ML240 + m_NextMode = smML240; + break; + case 0x89: // ML280 + m_NextMode = smML280; + break; + case 0x8a: // ML320 + m_NextMode = smML320; + break; + default: + m_SyncMode = 0; + break; + } + } + } + } + } + break; + case 3: // 1200Hz(30ms)のチェック + if( !m_Sync ){ + m_pll.Do(ad); + } + m_SyncTime--; + if( !m_SyncTime ){ + if( (d12 > d19) &&(d12 > m_SLvl) ){ + if( m_Sync ){ + if( m_rBase >= (SSTVSET.m_LM * 65/100) ){ + m_ReqSave = 1; + } + } + if( m_NextMode == smAVT ){ + m_SyncTime = ((9 + 910 + 910 + 5311.9424 + 0.30514375) * sys.m_SampFreq / 1000.0); + m_SyncMode++; + m_SyncAVT = 1; + m_Sync = 0; + } + else { + m_SyncMode = 256; + } + SSTVSET.SetMode(m_NextMode); + } + else { + m_SyncMode = 0; + } + } + break; + case 4: // AVTの1900Hz信号待ち + m_SyncTime--; + if( !m_SyncTime ){ m_SyncMode = 256; break;} + + d = m_pll.Do(ad); + if( (d >= -1000) && (d <= 1000) ){ // First atack + m_SyncMode++; + m_SyncATime = 9.7646 * 0.5 * sys.m_SampFreq / 1000; + } + break; + case 5: + m_SyncTime--; + if( !m_SyncTime ){ m_SyncMode = 256; break;} + + d = m_pll.Do(ad); + if( (d >= -800) && (d <= 800) ){ // 2nd atack + m_SyncATime--; + if( !m_SyncATime ){ + m_SyncMode++; + m_SyncATime = 9.7646 * sys.m_SampFreq / 1000; + m_VisData = 0; + m_VisCnt = 16; + } + } + else { + m_SyncMode = 4; + } + break; + case 6: + m_SyncTime--; + if( !m_SyncTime ){ m_SyncMode = 256; break;} + + d = m_pll.Do(ad); + m_SyncATime--; + if( !m_SyncATime ){ + if( (d >= 8000)||(d < -8000) ){ + m_SyncATime = 9.7646 * sys.m_SampFreq / 1000; + m_VisData = m_VisData << 1; + if( d > 0 ) m_VisData |= 0x00000001; + m_VisCnt--; + if( !m_VisCnt ){ + int l = m_VisData & 0x00ff; + int h = (m_VisData >> 8) & 0x00ff; + if( ((l + h) == 0x00ff) && (l >= 0xa0) && (l <= 0xbf) && (h >= 0x40) && (h <= 0x5f) ){ + if( h != 0x40 ){ + m_SyncATime = 9.7646 * 0.7 * sys.m_SampFreq / 1000; + m_SyncTime = ((double(h - 0x40) * 165.9982) - 0.8) * sys.m_SampFreq / 1000; + m_SyncMode++; + } + else { + if( !m_SyncTime || (m_SyncTime >= 9.7646 * SampFreq / 1000) ){ + m_SyncTime = ((9.7646 * 0.5) - 0.8) * sys.m_SampFreq / 1000; + } + m_SyncMode = 8; + } + } + else { + m_SyncMode = 4; + } + } + } + else { + m_SyncMode = 4; + } + } + break; + case 7: // 同期 + d = m_pll.Do(ad); + if( (d >= -1000) && (d <= 1000) ){ // First atack + m_SyncMode = 5; + m_SyncATime = 9.7646 * 0.5 * sys.m_SampFreq / 1000; + } + else { + m_SyncATime--; + if( !m_SyncATime ){ + m_SyncMode = 4; + } + } + break; + case 8: + m_SyncMode--; + if( !m_SyncMode ){ + Start(); + } + break; + case 256: // 強制開始 + Start(); + break; + case 512: // 0.5sのウエイト + m_SyncTime = SampFreq * 0.5; + m_SyncMode++; + break; + case 513: + m_SyncTime--; + if( !m_SyncTime ){ + m_SyncMode = 0; + } + break; + } + } + if( m_Sync ){ + switch(m_Type){ + case 0: // PLL + if( m_afc && (m_lvl.m_CurMax > 16) && (SSTVSET.m_Mode != smAVT) ) SyncFreq(m_fqc.Do(m_lvl.m_Cur)); + d = m_pll.Do(m_lvl.m_Cur); + break; + case 1: // Zero-crossing + d = m_fqc.Do(m_lvl.m_Cur); + if( m_afc && (m_lvl.m_CurMax > 16) && (SSTVSET.m_Mode != smAVT) ) SyncFreq(d); + break; + default: // Hilbert + d = m_hill.Do(m_lvl.m_Cur); + if( m_afc && (m_lvl.m_CurMax > 16) && (SSTVSET.m_Mode != smAVT) ) SyncFreq(d); + break; + } + if( m_afc ) d += m_AFCDiff; + if( m_Skip ){ + if( m_Skip > 0 ){ + m_Skip--; + } + else { + for( ; m_Skip; m_Skip++ ){ + int n = m_wBase + m_wCnt; + m_Buf[n] = -d; + m_B12[n] = 0; + IncWP(); + } + } + } + else { + if( m_ScopeFlag ){ + m_Scope[1].WriteData(d); + } + int n = m_wBase + m_wCnt; + m_Buf[n] = -d; + +#if NARROW_SYNC == 1200 + if( SSTVSET.m_Mode != smAVT ){ + m_B12[n] = d12; + } +#else + if( m_fNarrow ){ + m_B12[n] = d19; + } + else if( SSTVSET.m_Mode != smAVT ){ + m_B12[n] = d12; + } +#endif + else { + m_B12[n] = (d + 16384) * 0.25; + } + IncWP(); + } + } + else if( sys.m_TestDem ){ + switch(m_Type){ + case 0: + m_CurSig = m_Avg.Avg(m_pll.Do(m_lvl.m_Cur)); + break; + case 1: + m_CurSig = m_Avg.Avg(m_fqc.Do(m_lvl.m_Cur)); + break; + default: + m_CurSig = m_Avg.Avg(m_hill.Do(m_lvl.m_Cur)); + break; + } + } +} + +void CSSTVDEM::IncWP(void) +{ + m_wCnt++; + if( m_wCnt >= SSTVSET.m_WD ){ + m_wCnt = 0; + m_wPage++; + m_wLine++; + m_wBase += m_BWidth; + if( m_wPage >= SSTVDEMBUFMAX ){ + m_wPage = 0; + m_wBase = 0; + } + } +} + +void CSSTVDEM::SyncFreq(double d) +{ +/* + double m_AFC_LowVal; // (Center - SyncLow) * 16384 / BWH + double m_AFC_HighVal; // (Center - SyncHigh) * 16384 / BWH + double m_AFC_SyncVal; // (Center - Sync) * 16384 / BWH + double m_AFC_BWH; // BWH / 16384.0; +*/ + d -= 128; + + if( (d <= m_AFC_LowVal) && (d >= m_AFC_HighVal) ){ + if( !m_AFCDis && (m_AFCCount >= SSTVSET.m_AFCB) && (m_AFCCount <= SSTVSET.m_AFCE) ){ + m_AFCData = m_Avg.Avg(d); + if( m_AFCCount == SSTVSET.m_AFCE ){ + if( m_AFCGard ){ + m_AFCLock = m_AFCAVG.SetData(m_AFCData); + m_AFCGard = 0; + } + else { + m_AFCLock = m_AFCAVG.Avg(m_AFCData); + } + m_AFCDiff = m_AFC_SyncVal - m_AFCLock; + m_AFCFlag = 15; + InitTone(m_AFCDiff * m_AFC_BWH); + m_AFCDis = m_AFCInt; + } + } + m_AFCCount++; + } + else { + if( (m_AFCCount >= SSTVSET.m_AFCB) && m_AFCGard ){ + m_AFCGard--; + if( !m_AFCGard ) m_AFCAVG.SetData(m_AFCLock); + } + m_AFCCount = 0; + if( m_AFCDis ) m_AFCDis--; + } +} + +void CSSTVDEM::DecodeFSK(int m, int s) +{ + int d; + switch(m_fskmode){ + case 0: // スペースキャリア検出 + d = ABS(m - s); + if( (s > m) && (d >= 2048) ){ + m_fsktime = (FSKGARD/2) * SSTVSET.m_SampFreq/1000; + m_fskmode++; + } + break; + case 1: // スペースキャリア検出(連続) + d = ABS(m - s); + if( (s > m) && (d >= 2048) ){ + m_fsktime--; + if( !m_fsktime ){ + m_fsktime = FSKGARD * SSTVSET.m_SampFreq/1000; + m_fskmode++; + } + } + else { + m_fskmode = 0; + } + break; + case 2: // スタートビットの検出 + d = ABS(m - s); + m_fsktime--; + if( !m_fsktime ){ + m_fskmode = 0; + } + else if( (m > s) && (d >= 2048) ){ + m_fsktime = (FSKINTVAL/2) * SSTVSET.m_SampFreq/1000; + m_fskmode++; + } + break; + case 3: // スタートビットの検出(中間点) + m_fsktime--; + if( !m_fsktime ){ + d = ABS(m - s); + if( (m > s) && (d >= 2048) ){ + m_fsktime = 0; + m_fsknextd = double(FSKINTVAL)/1000.0 * SSTVSET.m_SampFreq; + m_fsknexti = m_fsknextd; + m_fskbcnt = 0; + m_fskc = 0; + m_fskmode++; + } + else { + m_fskmode = 0; + } + } + break; + default: + m_fsktime++; + if( m_fsktime >= m_fsknexti ){ + d = ABS(m - s); + if( d < 2048 ){ + m_fskmode = 0; + } + else { + m_fsknextd += double(FSKINTVAL)/1000.0 * SSTVSET.m_SampFreq; + m_fsknexti = m_fsknextd; + m_fskc = BYTE(m_fskc >> 1); + if( m > s ) m_fskc |= 0x20; + m_fskbcnt++; + if( m_fskbcnt >= 6 ){ + m_fskbcnt = 0; + switch(m_fskmode){ + case 4: // First SYNC 0x2A + if( m_fskc == 0x2a ){ + m_fskcnt = 0; + m_fskbcnt = 0; + m_fsks = 0; + m_fskc = 0; + m_fskmode++; + } + else if( m_fskc == 0x2d ){ + m_fskcnt = 0; + m_fskbcnt = 0; + m_fsks = 0; + m_fskc = 0; + m_fskmode = 16; + } + else { + m_fskmode = 0; + } + break; + case 5: // Store data + if( m_fskc == 0x01 ){ + if( m_fskcnt >= 1 ){ + m_fskmode++; + } + else { + m_fskmode = 0; + } + } + else { + m_fsks = m_fskc ^ m_fsks; + m_fskdata[m_fskcnt] = BYTE(m_fskc + 0x20); + m_fskcnt++; + if( m_fskcnt >= 17 ){ + m_fskmode = 0; + } + } + break; + case 6: // Check XOR + m_fsks &= 0x3f; + if( (m_fskc == m_fsks) && m_fskdecode ){ + m_fskdata[m_fskcnt] = 0; + StrCopy(m_fskcall, SkipSpace(LPCSTR(m_fskdata)), 16); + clipsp(m_fskcall); + m_fskrec = 1; + m_fskmode++; + + m_fskcnt = 0; + m_fsks = 0; + m_fskc = 0; + } + else { + m_fskmode = 0; + } + break; + case 7: // Store data + if( m_fskc == 0x01 ){ + if( m_fskcnt >= 1 ){ + m_fskmode++; + } + else { + m_fskmode = 0; + } + } + else if( m_fskc == 0x02 ){ + m_fsks = 0x02; + m_fskNR = 0; + m_fskmode = 9; + } + else if( m_fskc >= 0x10 ){ + m_fsks = m_fskc ^ m_fsks; + m_fskNRS[m_fskcnt] = BYTE(m_fskc + 0x20); + m_fskcnt++; + if( m_fskcnt >= 9 ){ + m_fskmode = 0; + } + } + else { + m_fskmode = 0; + } + break; + case 8: // Check XOR + m_fsks &= 0x3f; + if( (m_fskc == m_fsks) && m_fskdecode ){ + m_fskNRS[m_fskcnt] = 0; + clipsp(m_fskNRS); + m_fskNRrec = 1; + } + m_fskmode = 0; + break; + case 9: + m_fsks = m_fskc ^ m_fsks; + m_fskNR = m_fskNR << 6; + m_fskNR += m_fskc; + m_fskcnt++; + if( m_fskcnt >= 2 ){ + m_fskmode++; + } + break; + case 10: + m_fsks &= 0x3f; + if( m_fskc == m_fsks ){ + sprintf(m_fskNRS, "%03u", m_fskNR); + m_fskNRrec = 1; + } + m_fskmode = 0; + break; + case 16: + m_fsks = m_fskc ^ m_fsks; + if( m_fskc == 0x15 ){ + m_fskmode++; + } + else { + m_fskmode = 0; + } + break; + case 17: + m_fsks = m_fskc ^ m_fsks; + m_fskdata[0] = m_fskc; + m_fskmode++; + break; + case 18: + m_fsks &= 0x3f; + if( m_fskc == m_fsks ){ + switch(m_fskdata[0]){ + case 0x02: + m_NextMode = smMN73; + break; + case 0x04: + m_NextMode = smMN110; + break; + case 0x05: + m_NextMode = smMN140; + break; + case 0x14: + m_NextMode = smMC110; + break; + case 0x15: + m_NextMode = smMC140; + break; + case 0x16: + m_NextMode = smMC180; + break; + default: + m_NextMode = 0; + break; + } + if( (m_SyncRestart || !m_Sync) && m_NextMode && (m_SyncMode >= 0) ){ + SSTVSET.SetMode(m_NextMode); + Start(); + } + } + m_fskmode = 0; + break; + } + m_fskc = 0; + } + } + } + break; + } +} +//-------------------------------------------------------- +// リピータ変数の初期化 +void CSSTVDEM::InitRepeater(void) +{ + if( sys.m_Repeater ){ + if( pRep == NULL ) pRep = new REPSET; + pRep->m_iirrep.SetFreq(m_RepTone + g_dblToneOffset, SampFreq, 100.0); + pRep->m_lpfrep.MakeIIR(50, SampFreq, 2, 0, 0); + } + else { + pRep = NULL; + } +} +//-------------------------------------------------------- +// リピータのON/OFF +void CSSTVDEM::SetRepeater(int sw) +{ + if( sw != m_Repeater ){ + m_repmode = 0; + m_Repeater = sw; + } +} +//-------------------------------------------------------- +// リピータトーンの検出感度設定 +void CSSTVDEM::SetRepSenseLvl(void) +{ + switch(sys.m_RepSenseLvl){ + case 0: + m_RSLvl = 3072; + break; + case 1: + m_RSLvl = 4096; + break; + case 2: + m_RSLvl = 6144; + break; + default: + m_RSLvl = 8192; + break; + } + m_RSLvl2 = m_RSLvl / 2; +} +//-------------------------------------------------------- +// リピータトーンの検出処理 +void CSSTVDEM::Repeater(int d17, int d12, int d19) +{ + int d1 = ABS(d17 - d12); + int d2 = ABS(d17 - d19); +#if 0 + m_repD1 = d1; + m_repD2 = d2; +#endif + switch(m_repmode){ + case 0: // トーン検出のトリガ + if( (d1 > m_RSLvl) && (d2 > m_RSLvl2) ){ + m_reptime = sys.m_RepTimeA * SSTVSET.m_SampFreq / 1000; + m_repmode++; + } + break; + case 1: // トーンの持続のチェック + if( (d1 > m_RSLvl) && (d2 > m_RSLvl2) ){ + m_reptime--; + if( !m_reptime ){ + m_repmode++; + m_repcount = 10000 * SSTVSET.m_SampFreq / 1000; + } + } + else { + m_repmode = 0; + } + break; + case 2: // トーンの終了の検出 + m_repcount--; + if( !m_repcount ){ + m_repmode = 0; + } + if( (d1 > m_RSLvl) && (d2 > m_RSLvl2) ){ + m_reptime = sys.m_RepTimeB * SSTVSET.m_SampFreq / 1000; + m_repcount = 10000 * SSTVSET.m_SampFreq / 1000; + if( !m_reptime ) m_reptime++; + } + else if( m_RepSQ && (m_repsig > m_RepSQ) ){ + m_reptime = sys.m_RepTimeB * SSTVSET.m_SampFreq / 1000; + if( !m_reptime ) m_reptime++; + } + else { + m_reptime--; + if( !m_reptime ){ + m_repmode++; + } + } + break; +// case 3: // 'K'の送信待ち +// break; + case 4: + m_reptime = sys.m_RepTimeC * SSTVSET.m_SampFreq / 1000; + m_repcount = sys.m_RepTimeA * SSTVSET.m_SampFreq / 1000; + m_repmode++; + break; + case 5: // 10[s]のタイムアウト待ち + m_reptime--; + if( !m_reptime ){ // タイムアウトによる待機 + m_repmode = 0; + } + else if( (d1 > m_RSLvl) && (d2 > m_RSLvl2) ){ + m_repcount--; + if( !m_repcount ){ + m_repmode = 2; + } + } + else { + m_repcount = sys.m_RepTimeA * SSTVSET.m_SampFreq / 1000; + } + break; +// case 6: // 受信中 +// break; + case 7: + m_reptime = sys.m_RepTimeD * SSTVSET.m_SampFreq / 1000; + m_repcount = 20000 * SSTVSET.m_SampFreq / 1000; + if( !m_reptime ) m_reptime++; + m_repmode++; + break; + case 8: // リプレイ送信前のタイマ + m_repcount--; + if( !m_repcount ){ + m_repmode = 0; + } + if( m_RepSQ && (m_repsig > m_RepSQ) ){ + m_reptime = sys.m_RepTimeD * SSTVSET.m_SampFreq / 1000; + if( !m_reptime ) m_reptime++; + } + else { + m_reptime--; + if( !m_reptime ){ + m_repmode++; + } + } + break; +// case 9: // 送信トリガ +// break; +// case 10: // リプレイ送信中 +// break; + default: + break; + } +} +//-------------------------------------------------------- +// CSSTVMODクラス +CSSTVMOD::CSSTVMOD() +{ + m_TXBuf = NULL; + + m_bpf = 1; + m_lpf = 0; + m_lpffq = 2000; +// memset(HBPF, 0, sizeof(HBPF)); +// memset(Z, 0, sizeof(Z)); + m_bpftap = 24; +// MakeFilter(HBPF, m_bpftap, ffBPF, SampFreq, 700, 2800, 40, 1.0); + int lfq = 700 + g_dblToneOffset; + if( lfq < 100 ){ + m_BPF.Create(m_bpftap, ffLPF, SampFreq, 2800 + g_dblToneOffset, 2800 + g_dblToneOffset, 40, 1.0); + } + else { + m_BPF.Create(m_bpftap, ffBPF, SampFreq, lfq, 2800 + g_dblToneOffset, 40, 1.0); + } + m_outgain = 24578.0; + InitGain(); + m_vco.SetSampleFreq(SampFreq); + m_vco.VirtualLock(); + m_vco.SetFreeFreq(1100 + g_dblToneOffset); + m_vco.SetGain(2300 - 1100); + InitTXBuf(); + m_tune = 0; + m_Lost = 0; + m_TuneFreq = 1750; + m_VariOut = 0; + m_VariR = 298; + m_VariG = 588; + m_VariB = 110; +} + +CSSTVMOD::~CSSTVMOD() +{ + CloseTXBuf(); +} + +void CSSTVMOD::OpenTXBuf(int s) +{ + if( (s != m_TXBufLen) || (m_TXBuf == NULL) ){ + if( m_TXBuf != NULL ) delete m_TXBuf; + if( s < 5 ) s = 5; + if( s > 14 ) s = 14; + m_TXBufLen = s; + m_TXMax = m_TXBufLen * SampFreq; + m_TXBuf = new short[m_TXMax]; + } +} + +void CSSTVMOD::CloseTXBuf(void) +{ + if( m_TXBuf != NULL ){ + delete m_TXBuf; + m_TXBuf = NULL; + } +} + +void CSSTVMOD::InitTXBuf(void) +{ + m_rPnt = m_wPnt = 0; + m_Cnt = 0; + m_rCnt = 0; + + m_iPos = 0; + m_dPos = 0; + + m_wLine = 0; + + m_RowCnt = 0; + pRow = NULL; + m_BPF.Clear(); +// memset(Z, 0, sizeof(Z)); +} + +void CSSTVMOD::Write(short fq) +{ +#if DEBUG_AFC + fq += DEBUG_AFC; +#endif + m_TXBuf[m_wPnt] = fq; + m_wPnt++; + m_Cnt++; + if( m_wPnt >= m_TXMax ) m_wPnt = 0; +} + +void CSSTVMOD::Write(short fq, double tim) +{ + m_dPos += (tim * SSTVSET.m_TxSampFreq)/1000.0; + for( ; m_iPos < int(m_dPos); m_iPos++ ) Write(fq); +} + +void CSSTVMOD::WriteC(short fq, double cnt) +{ + m_dPos += cnt; + for( ; m_iPos < int(m_dPos); m_iPos++ ) Write(fq); +} + +double CSSTVMOD::Do(void) +{ + double d; + if( sys.m_TestDem ){ + d = m_vco.Do(double(sys.m_TestDem - 1100)/double(2300-1100)); + d *= m_outgain; + } + else if( m_tune ){ + d = m_vco.Do((m_TuneFreq - 1100)/1200.0); + d *= m_outgain; + } + else if( m_Cnt ){ + int f = m_TXBuf[m_rPnt]; + if( f > 0 ){ + d = double((f & 0x0fff) - 1100)/double(2300-1100); + if( m_lpf ) d = avgLPF.Avg(d); + d = m_vco.Do(d); + } + else { + d = 0; + } + m_Cnt--; + m_rCnt++; + m_rPnt++; + if( m_rPnt >= m_TXMax ) m_rPnt = 0; + if( m_VariOut ){ + switch(f & 0xf000){ + case 0x1000: + d *= m_outgainR; + break; + case 0x2000: + d *= m_outgainG; + break; + case 0x3000: + d *= m_outgainB; + break; + default: + d *= m_outgain; + break; + } + } + else { +#if VARITEST + d *= m_outgain/3; +#else + d *= m_outgain; +#endif + } + } + else if( m_RowCnt ){ + d = (double)(*pRow++); + m_RowCnt--; + m_rCnt++; + } + else { + d = double(1500-1100)/double(2300-1100); + d *= m_outgain; +// m_rCnt++; + } +// if( m_bpf ) d = DoFIR(HBPF, Z, d, m_bpftap); + if( m_bpf ) d = m_BPF.Do(d); + return d; +} + +void CSSTVMOD::CalcFilter(void) +{ + if( m_bpftap ){ + int lfq = 700 + g_dblToneOffset; + if( lfq < 100 ){ + m_BPF.Create(m_bpftap, ffLPF, SampFreq, 2800 + g_dblToneOffset, 2800 + g_dblToneOffset, 40, 1.0); + } + else { + m_BPF.Create(m_bpftap, ffBPF, SampFreq, lfq, 2800 + g_dblToneOffset, 40, 1.0); + } + } + avgLPF.SetCount(int(SampFreq/m_lpffq + 0.5)); +} + +void CSSTVMOD::InitGain(void) +{ + if( m_VariR > 1000 ) m_VariR = 1000; + if( m_VariG > 1000 ) m_VariG = 1000; + if( m_VariB > 1000 ) m_VariB = 1000; + m_outgainR = m_outgain * double(m_VariR) * 0.001; + m_outgainG = m_outgain * double(m_VariG) * 0.001; + m_outgainB = m_outgain * double(m_VariB) * 0.001; +} + +void CSSTVMOD::WriteFSK(BYTE c) +{ + int i; + for( i = 0; i < 6; i++ ){ + Write(short(c & 0x01 ? 1900 : FSKSPACE), FSKINTVAL); + c = BYTE(c >> 1); + } +} + +void CSSTVMOD::WriteCWID(char c) +{ + const USHORT _tbl[]={ + // 0 1 2 3 4 5 6 7 + 0x0005, 0x8005, 0xc005, 0xe005, 0xf005, 0xf805, 0x7805, 0x3805, // 0-7 + // 8 9 : ; < = > ? + 0x1805, 0x0805, 0x0000, 0x0000, 0x0000, 0x7005, 0xA805, 0xcc06, // 8 + // @ A B C D E F G + 0x0000, 0x8002, 0x7004, 0x5004, 0x6003, 0x8001, 0xd004, 0x2003, // @-G + // H I J K L M N O + 0xf004, 0xc002, 0x8004, 0x4003, 0xb004, 0x0002, 0x4002, 0x0003, // H-O + // P Q R S T U V W + 0x9004, 0x2004, 0xa003, 0xe003, 0x0001, 0xc003, 0xe004, 0x8003, // P-W + // X Y Z + 0x6004, 0x4004, 0x3004, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // X-Z + }; + int dot = sys.m_CWIDSpeed + 30; +// int dot = sys.m_CWIDSlow ? 40 : 30; + c = char(toupper(c)); + c &= 0x7f; + int d; + if( c == '.' ) c = 'R'; + if( c == '/' ){ + d = 0x6805; + } + else if( c == '@' ){ + Write(0, 250); + return; + } + else if( (c >= '0') && (c <= 'Z') ){ + c -= '0'; + d = _tbl[c]; + } + else { + d = 0; + } + int n = d & 0x00ff; + if( !d ){ + Write(0, dot*7); + return; + } + for(int i = 0; i < n; i++ ){ + if( d & 0x8000 ){ + Write(short(sys.m_CWIDFreq), dot); + } + else { + Write(short(sys.m_CWIDFreq), dot*3); + } + Write(0, dot); + d = d << 1; + } + Write(0, dot*2); +} + +CHILL::CHILL() +{ +// memset(Z, 0, sizeof(Z)); + SetWidth(0); +#if HILLDOUBLEBUF + m_FIR.Create(m_tap); +#endif + + m_htap = m_tap / 2; + MakeHilbert(H, m_tap, SampFreq, 100, SampFreq/2 - 100); + m_A[0] = m_A[1] = m_A[2] = m_A[3] = 0; + m_iir.MakeIIR(1800, SampFreq, 3, 0, 0); +#if !HILLDOUBLEBUF + m_ph = &Z[m_htap]; +#endif +} + +void __fastcall CHILL::SetWidth(int fNarrow) +{ + if( fNarrow ){ + m_OFF = (2 * PI * (NARROW_CENTER + g_dblToneOffset)) / SampFreq; + m_OUT = 32768.0 * SampFreq / (2 * PI * NARROW_BW); + } + else { + m_OFF = (2 * PI * (1900 + g_dblToneOffset)) / SampFreq; + m_OUT = 32768.0 * SampFreq / (2 * PI * 800); + } + if( SampBase >= 40000 ){ + m_OFF *= 4; + m_OUT *= 0.25; + m_tap = 48; //48 + m_df = 2; + } + else if( SampBase >= 16000 ){ + m_OFF *= 2; + m_OUT *= 0.5; + m_tap = 24; //24 + m_df = 1; + } + else { + m_tap = 12; //12 + m_df = 0; + } + if( sys.m_bCQ100 ){ + m_tap *= 3; + } +} + +double CHILL::Do(double d) +{ +#if HILLDOUBLEBUF + double a; + m_FIR.Do(d, a, H); +#else + d = DoFIR(H, Z, d, m_tap); + double a = *m_ph; +#endif + if( a ) a = atan2(d, a); + d = a - m_A[0]; + switch(m_df){ + case 1: + m_A[0] = m_A[1]; + m_A[1] = a; + break; + case 2: + m_A[0] = m_A[1]; + m_A[1] = m_A[2]; + m_A[2] = m_A[3]; + m_A[3] = a; + break; + default: + m_A[0] = a; + break; + } + if( d >= PI ){ + d = d - PI*2; + } + else if( d <= -PI ){ + d = d + PI*2; + } + d += m_OFF; + return m_iir.Do(d * m_OUT); +} + diff --git a/sstv.h b/sstv.h new file mode 100644 index 0000000..59faae5 --- /dev/null +++ b/sstv.h @@ -0,0 +1,853 @@ +//Copyright+LGPL + +//----------------------------------------------------------------------------------------------------------------------------------------------- +// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba +//----------------------------------------------------------------------------------------------------------------------------------------------- +// This file is part of MMSSTV. + +// MMSSTV is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +// MMSSTV 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 Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see +// . +//----------------------------------------------------------------------------------------------------------------------------------------------- + + + +//--------------------------------------------------------------------------- +#ifndef SstvH +#define SstvH +//--------------------------------------------------------------------------- +#include "Fir.h" + +#define BITDEBUG 0 // キャラクタ長の測定 +#define TXDDEBUG 0 // FSKのキャラクタ長の測定 +#define FSKDEBUG 0 // FSKのデバッグモード +#define DEBUG_AFC 0 // AFCのテスト(+/-の周波数) + +extern double g_dblToneOffset; + +#pragma pack(push, 4) + +#ifndef SampFreq +extern double SampFreq; +#endif + +class CTICK +{ +public: + int *ptbl[2]; + int m_wsel; + int *m_wp; + int m_wcnt; + int m_Trig; + int m_Samp; +public: + CTICK(); + ~CTICK(); + void Init(void); + void Write(double d); + inline int GetTrig(void){return m_Trig;}; + int *GetData(void); +}; + +class CVCO +{ +private: + double m_c1; // VCOの利得 + double m_c2; // フリーランニング周波数 + double m_z; + + int m_TableSize; + double *pSinTbl; + double m_FreeFreq; + double m_SampleFreq; + int m_vlock; +public: + CVCO(); + ~CVCO(); + void VirtualLock(void); + void InitPhase(void); + void SetGain(double gain); + void SetSampleFreq(double f); + void SetFreeFreq(double f); + double Do(double d); +}; + +class CSmooz{ +private: + double *bp; + int Wp; +public: + int Max; + int Cnt; +private: + inline void IncWp(void){ + Wp++; + if( Wp >= Max ) Wp = 0; + }; + inline double Avg(void){ + double d = 0.0; + int i; + for( i = 0; i < Cnt; i++ ){ + d += bp[i]; + } + if( Cnt ){ + return d/double(Cnt); + } + else { + return 0; + } + }; +public: + inline CSmooz(int max = 2){ + Max = max; + bp = new double[max]; + Cnt = 0; + Wp = 0; + }; + inline ~CSmooz(void){ + delete bp; + }; + inline void SetCount(int n){ + if( !n ) n = 1; + if( Max != n ){ + double *np = new double[n]; + Max = n; + Cnt = Wp = 0; + double *op = bp; + bp = np; + delete op; + } + else { + Cnt = Wp = 0; + } + }; + inline double SetData(double d){ + for( int i = 0; i < Max; i++ ){ + bp[i] = d; + } + Wp = 0; + Cnt = Max; + return d; + }; + inline double Avg(double d){ + bp[Wp] = d; + IncWp(); + if( Cnt < Max ){ + Cnt++; + } + return Avg(); + }; +}; + +class CPLL +{ +private: + CIIR loopLPF; + CIIR outLPF; + + double m_err; + double m_out; + double m_vcoout; + double m_SampleFreq; + double m_FreeFreq; + double m_Shift; + + double m_Max; + double m_Min; + double m_d; + double m_agc, m_agca; +public: + int m_loopOrder; + double m_loopFC; + int m_outOrder; + double m_outFC; + double m_vcogain; + double m_outgain; +public: + CVCO vco; + CPLL(); + void SetWidth(int fNarrow); + void SetVcoGain(double g); + void MakeLoopLPF(void); + void MakeOutLPF(void); + void SetFreeFreq(double f1, double f2); + void SetSampleFreq(double f); + double Do(double d); + inline double GetErr(void){return m_err*32768;}; // Phase Det + inline double GetOut(void){return m_out*32768;}; // Phase Det + inline double GetVco(void){return m_vcoout;}; +}; + + +#define SCOPESIZE 8192 +class CScope +{ +private: + int m_DataFlag; + + int m_wp; + +public: + int m_ScopeSize; + double *pScopeData; + +public: + CScope(); + ~CScope(); + void InitMem(void); + void WriteData(double d); + void UpdateData(double d); + inline int GetFlag(void){m_DataFlag && (pScopeData != NULL); return 0;}; //ja7ude 0521 + void Collect(int size); +}; + +#define NOISEBPFTAP 12 +class CNoise // M系列ノイズ N=22 (Tap=1) +{ +private: + double H[NOISEBPFTAP+1]; + double Z[NOISEBPFTAP+1]; + + DWORD reg; + +public: + CNoise(); + double GetNoise(void); +}; + +class CLVL +{ +public: + double m_Cur; + + double m_PeakMax; + double m_PeakAGC; + double m_Peak; + double m_CurMax; + double m_Max; + double m_agc; + int m_CntPeak; + int m_agcfast; + + int m_Cnt; + int m_CntMax; +public: + CLVL(){ + m_agcfast = 0; + m_CntMax = SampFreq * 100 / 1000.0; + Init(); + }; + void Init(void){ + m_PeakMax = 0; + m_PeakAGC = 0; + m_Peak = 0; + m_Cur = 0; + m_CurMax = 0.0; + m_Max = 0; + m_agc = 1.0; + m_CntPeak = 0; + m_Cnt = 0; + }; + void Do(double d ){ + m_Cur = d; + if( d < 0.0 ) d = -d; + if( m_Max < d ) m_Max = d; + m_Cnt++; + }; + void Fix(void){ + if( m_Cnt < m_CntMax ) return; // did not store yet + m_Cnt = 0; + m_CntPeak++; + if( m_Peak < m_Max ) m_Peak = m_Max; + if( m_CntPeak >= 5 ){ + m_CntPeak = 0; + m_PeakMax = m_Max; + m_PeakAGC = (m_PeakAGC + m_Max) * 0.5; + m_Peak = 0; + if( !m_agcfast ){ + if( (m_PeakAGC > 32) && m_PeakMax ){ + m_agc = 16384.0 / m_PeakMax; + } + else { + m_agc = 16384.0 / 32.0; + } + } + } + else { + if( m_PeakMax < m_Max ) m_PeakMax = m_Max; + } + m_CurMax = m_Max; + if( m_agcfast ){ + if( m_CurMax > 32 ){ + m_agc = 16384.0 / m_CurMax; + } + else { + m_agc = 16384.0 / 32.0; + } + } + m_Max = 0; + }; + double AGC(double d){ + return d * m_agc; + }; +}; + +class CSLVL +{ +public: + double m_Max; + double m_Min; + double m_Lvl; + + int m_Cnt; + int m_CntMax; +public: + CSLVL(){ + m_CntMax = SampFreq * 100 / 1000.0; + Init(); + }; + void Init(void){ + m_Max = 0; + m_Min = 16384; + m_Lvl = 0; + m_CntMax = 0; + m_Cnt = 0; + }; + void Do(double d){ + if( m_Max < d ) m_Max = d; + if( m_Min > d ) m_Min = d; + m_Cnt++; + }; + void Fix(void){ + if( m_Cnt < m_CntMax ) return; // did not store yet + m_Cnt = 0; + m_Lvl = m_Max - m_Min; + m_Max = 0; + m_Min = 16384; + }; + double GetLvl(void){ + return m_Lvl; + }; +}; + +#if 0 +class CAGC +{ +public: + double m_CurMax; + double m_Max; + int m_Cnt; + int m_CntMax; + CSmooz m_sm; +public: + CAGC(){ + m_Max = 0; + m_CurMax = 1.0; + m_Cnt = 0; + m_CntMax = 100 * SampFreq / 1000.0; + m_sm.SetCount(5); + }; + double Do(double d){ + double sd = d; + if( d < 0.0 ) d = -d; + if( m_Max < d ) m_Max = d; + if( m_Cnt >= m_CntMax ){ + m_CurMax = m_sm.Avg(m_Max); + if( m_CurMax > 0.0 ){ + m_CurMax = 16384.0 / m_CurMax; + } + m_Max = 0; + m_Cnt = 0; + } + return sd * m_CurMax; + }; +}; +#endif + +#define HILLDOUBLEBUF FALSE // 速度が速いほうを選択 +#define HILLTAP 48 +class CHILL +{ +public: +#if HILLDOUBLEBUF + CFIR2 m_FIR; +#else + double Z[HILLTAP+1]; +#endif + double H[HILLTAP+1]; + double m_A[4]; + double m_OFF; + double m_OUT; + double *m_ph; + int m_htap; + int m_df; + int m_tap; + CIIR m_iir; +public: + CHILL(); + void __fastcall SetWidth(int fNarrow); + double Do(double d); +}; + +#define ZEROFQ (-1900.0/400.0) + +class CFQC { +public: + int m_Mode; + int m_Count; + double m_ACount; + double m_d; + double m_fq; + double m_out; + double m_SampFreq; + + double m_CenterFQ; + double m_HighFQ; + double m_LowFQ; + + double m_HighVal; + double m_LowVal; + double m_BWH; +public: + int m_Type; + int m_Limit; + CIIR m_iir; + + double m_SmoozFq; + CSmooz m_fir; + + int m_outOrder; + double m_outFC; + + int m_Timer; + int m_STimer; + + void CalcLPF(void); + void Clear(void); + void SetSampFreq(double fq); + +public: + CFQC(); + void SetWidth(int fNarrow); + double Do(double s); +}; + +#define NARROW_SYNC 1900 +#define NARROW_LOW 2044 +#define NARROW_HIGH 2300 +#define NARROW_CENTER ((NARROW_HIGH+NARROW_LOW)/2) +#define NARROW_BW (NARROW_HIGH - NARROW_LOW) +#define NARROW_BWH (NARROW_BW/2) +#define NARROW_BPFLOW 1600 +#define NARROW_BPFHIGH 2500 +#define NARROW_AFCLOW 1800 +#define NARROW_AFCHIGH 1950 +enum { + smR36, + smR72, + smAVT, + smSCT1, + smSCT2, + smSCTDX, + smMRT1, + smMRT2, + smSC2_180, + smSC2_120, + smSC2_60, + smPD50, + smPD90, + smPD120, + smPD160, + smPD180, + smPD240, + smPD290, + smP3, + smP5, + smP7, + smMR73, + smMR90, + smMR115, + smMR140, + smMR175, + smMP73, + smMP115, + smMP140, + smMP175, + smML180, + smML240, + smML280, + smML320, + smR24, + smRM8, + smRM12, + smMN73, + smMN110, + smMN140, + smMC110, + smMC140, + smMC180, + smEND, +}; +extern BOOL __fastcall IsNarrowMode(int mode); +extern LPCSTR SSTVModeList[]; +extern const BYTE SSTVModeOdr[]; + +class CSSTVSET { +private: +public: + int m_Mode; + int m_TxMode; + double m_TW; + double m_KS; + double m_KS2; + double m_OF; + double m_OFP; + double m_CG; + double m_CB; + double m_SG; + double m_SB; + int m_WD; + int m_L; + int m_LM; + int m_OFS; + int m_IOFS; + double m_SampFreq; + + double m_KSS; + double m_KS2S; + int m_KSB; + + int m_TWD; + int m_TL; + double m_TTW; + double m_TxSampFreq; + + DWORD m_MS[smEND]; + DWORD m_MSLL; + DWORD m_MSL; + DWORD m_MSH; + + int m_AFCW; + int m_AFCB; + int m_AFCE; + + int m_fNarrow; + int m_fTxNarrow; +public: + CSSTVSET(); + void SetMode(int mode); + void SetTxMode(int mode); + void SetSampFreq(void); + void SetTxSampFreq(void); + void InitIntervalPara(void); + void GetBitmapSize(int &w, int &h, int mode); + void GetPictureSize(int &w, int &h, int &hp, int mode); + double GetTiming(int mode); +}; +extern CSSTVSET SSTVSET; + +typedef struct { // リピータ用の設定 + CIIRTANK m_iirrep; + CIIR m_lpfrep; + CLMS m_lmsrep; +}REPSET; + +#define MSYNCLINE 8 +class CSYNCINT { +public: + DWORD m_MSyncList[MSYNCLINE]; + DWORD m_MSyncCnt; + DWORD m_MSyncACnt; + int m_MSyncTime; + int m_MSyncIntPos; + int m_MSyncIntMax; + BOOL m_fNarrow; + int m_SyncPhase; +public: + CSYNCINT(){ + m_fNarrow = 0; + Reset(); + }; + void Reset(void){ + memset(m_MSyncList, 0, sizeof(m_MSyncList)); + m_MSyncACnt = m_MSyncCnt = 0; + m_MSyncIntMax = 0; + m_MSyncIntPos = 0; + m_SyncPhase = 0; + }; + + int SyncCheckSub(int am); + int SyncCheck(void); + void SyncInc(void); + void SyncTrig(int d); + void SyncMax(int d); + int SyncStart(void); +}; + +#define SSTVDEMBUFMAX 24 +class CSSTVDEM +{ +private: + double HBPF[TAPMAX+1]; + double HBPFS[TAPMAX+1]; + double HBPFN[TAPMAX+1]; +// double Z[TAPMAX+1]; + CFIR2 m_BPF; +public: + double m_ad; + int m_OverFlow; + int m_bpf; + int m_bpftap; + int m_Type; + int m_LevelType; + + CIIRTANK m_iir11; + CIIRTANK m_iir12; + CIIRTANK m_iir13; + CIIRTANK m_iir19; + CIIRTANK m_iirfsk; + CIIR m_lpf11; + CIIR m_lpf12; + CIIR m_lpf13; + CIIR m_lpf19; + CIIR m_lpffsk; + CPLL m_pll; + CFQC m_fqc; + CLVL m_lvl; + CSLVL m_SyncLvl; + CHILL m_hill; + + REPSET *pRep; + + int m_Skip; + int m_Sync; + int m_SyncRestart; + int m_SyncMode; + int m_SyncTime; + int m_SyncATime; + int m_VisData; + int m_VisCnt; + int m_VisTrig; + int m_SyncErr; + int m_NextMode; + int m_SyncAVT; + + int m_wBase; + int m_wPage; + int m_rPage; + int m_wCnt; + int m_wLine; + int m_wBgn; + int m_rBase; + + int m_ReqSave; + int m_LoopBack; + + int m_wStgPage; + int m_wStgLine; + + int m_Lost; +public: + int m_BWidth; + short *m_Buf; + short *m_B12; + + int m_RxBufAllocSize; + short *m_StgBuf; + short *m_StgB12; +public: + void SetSenseLvl(void); + int m_SenseLvl; + double m_SLvl; + double m_SLvl2; + double m_SLvl3; + + int m_ScopeFlag; + CScope m_Scope[2]; + + CTICK *pTick; + int m_Tick; + int m_TickFreq; + void SetTickFreq(int f); + + double m_CurSig; + CSmooz m_Avg; + CSmooz m_AFCAVG; + int m_afc; + int m_AFCCount; + double m_AFCData; + double m_AFCLock; + double m_AFCDiff; + int m_AFCFQ; + int m_AFCFlag; + int m_AFCGard; + int m_AFCDis; + int m_AFCInt; + + double m_AFC_LowVal; // (Center - SyncLow) * 16384 / BWH + double m_AFC_HighVal; // (Center - SyncHigh) * 16384 / BWH + double m_AFC_SyncVal; // (Center - Sync) * 16384 / BWH + double m_AFC_BWH; // BWH / 16384.0; + + double m_AFC_OFFSET; // 128 +public: + int m_MSync; + CSYNCINT m_sint1; + CSYNCINT m_sint2; + CSYNCINT m_sint3; + +public: +#define FSKGARD 100 +#define FSKINTVAL 22 +#define FSKSPACE 2100 + int m_fskdecode; + int m_fskrec; + int m_fskmode; + int m_fsktime; + int m_fskcnt; + int m_fskbcnt; + int m_fsknexti; + double m_fsknextd; + BYTE m_fsks; + BYTE m_fskc; + BYTE m_fskdata[20]; + char m_fskcall[20]; + int m_fskNRrec; + int m_fskNR; + char m_fskNRS[20]; + + //------ リピータ + int m_Repeater; + int m_RepSQ; + int m_RepTone; + int m_repmode; + int m_reptime; + int m_repcount; + int m_repsig; + int m_repANS; + int m_repRLY; + int m_repRX; + int m_repTX; + + int m_RSLvl; + int m_RSLvl2; + + int m_fNarrow; +#if 0 + int m_repD1, m_repD2; +#endif + void Repeater(int d17, int d12, int d19); + void SetRepeater(int sw); + void SetRepSenseLvl(void); + void InitRepeater(void); + +public: + CSSTVDEM(); + ~CSSTVDEM(); + void Start(void); + void Start(int mode, int f); + void Stop(void); + void Do(double d); + void IncWP(void); + void Idle(double d); + void CalcBPF(double *H1, double *H2, double *H3, int &bpftap, int bpf, int mode); + void CalcNarrowBPF(double *H3, int bpftap, int bpf, int mode); + void CalcBPF(void); + void SetBPF(int bpf); + void FreeRxBuff(void); + void OpenCloseRxBuff(void); + void SyncFreq(double d); + void DecodeFSK(int m, int s); + void InitAFC(void); + void InitTone(int dfq); + void SetWidth(int fNarrow); + + double m_d; + double m_dd; + int m_n; +}; + +class CSSTVMOD +{ +public: + int m_wLine; + + int m_wPnt; + int m_rPnt; + int m_Cnt; + int m_rCnt; + + int m_iPos; + double m_dPos; + + int m_sCnt; + + CVCO m_vco; + + int m_bpf; + int m_bpftap; + int m_lpf; + double m_lpffq; + double m_outgain; + double m_outgainG; + double m_outgainB; + double m_outgainR; + int m_TuneFreq; + + int m_tune; + int m_Lost; +public: + CFIR2 m_BPF; +// double HBPF[TAPMAX+1]; +// double Z[TAPMAX+1]; + + int m_TXBufLen; + int m_TXMax; + short *m_TXBuf; + CSmooz avgLPF; + + int m_RowCnt; + short *pRow; + + int m_VariOut; + UINT m_VariR; + UINT m_VariG; + UINT m_VariB; +public: + CSSTVMOD(); + ~CSSTVMOD(); + + void InitTXBuf(void); + void Write(short fq); + void Write(short fq, double tim); + void WriteC(short fq, double cnt); + double Do(void); + void CalcFilter(void); + inline int GetBufCnt(void){return m_Cnt;}; + void WriteCWID(char c); + void WriteFSK(BYTE c); + void OpenTXBuf(int s); + void CloseTXBuf(void); + inline void SetRow(short *p, int len){ + if( p != NULL ){ + pRow = p; + m_RowCnt = len; + } + else { + m_RowCnt = 0; + pRow = NULL; + } + }; + inline int GetRowCnt(void){ + return m_RowCnt; + }; + void InitGain(void); +}; +#pragma pack(pop) +#endif + diff --git a/temp.txt b/temp.txt new file mode 100644 index 0000000..8f8e77c --- /dev/null +++ b/temp.txt @@ -0,0 +1,190 @@ +//--------------------------------------------------------------------- +#include +#pragma hdrstop + +#include "ZoomView.h" +#include "ComLib.h" +//--------------------------------------------------------------------- +#pragma resource "*.dfm" +//--------------------------------------------------------------------- +__fastcall TZoomViewDlg::TZoomViewDlg(TComponent* AOwner) + : TForm(AOwner) +{ + FormStyle = ((TForm *)AOwner)->FormStyle; + Font->Name = ((TForm *)AOwner)->Font->Name; + Font->Charset = ((TForm *)AOwner)->Font->Charset; + pBitmap = NULL; + pBitmapS = NULL; + + m_MaxX = ::GetSystemMetrics(SM_CXFULLSCREEN); + m_MaxY = ::GetSystemMetrics(SM_CYFULLSCREEN); + m_DisEvent = 0; +} +//--------------------------------------------------------------------- +__fastcall TZoomViewDlg::~TZoomViewDlg() +{ + if( pBitmapS != NULL ){ + delete pBitmapS; + } +} +//--------------------------------------------------------------------- +void __fastcall TZoomViewDlg::SetInitSize(int xw, int yw) +{ + m_DisEvent++; + ClientWidth = xw; + ClientHeight = yw; + m_DisEvent--; +} +//--------------------------------------------------------------------- +void __fastcall TZoomViewDlg::UpdateTitle(void) +{ + if( pBitmap == NULL ) return; + + char bf[256]; + + strcpy(bf, MsgEng ? "Picture viewer" : "画像表示"); + + char bbf[64]; + sprintf(bbf, " - Source:%dx%d", pBitmap->Width, pBitmap->Height); + strcat(bf, bbf); + if( (pBitmap->Width != m_ViewXW) || (pBitmap->Height != m_ViewYW) ){ + sprintf(bbf, ", View:%dx%d", m_ViewXW, m_ViewYW); + strcat(bf, bbf); + if( pBitmapS != NULL ) strcat(bf, " (Smoothing)"); + } + Caption = bf; +} +//--------------------------------------------------------------------- +void __fastcall TZoomViewDlg::Execute(Graphics::TBitmap *pbmp, int sw) +{ + pBitmap = pbmp; + if( pbmp->Width != 320 ){ + int xw = pbmp->Width; + int yw = pbmp->Height; + if( (xw > m_MaxX) || (yw > m_MaxY) ){ + if( xw > m_MaxX ) xw = m_MaxX; + if( yw > m_MaxY ) yw = m_MaxY; + KeepAspect(xw, yw, pbmp->Width, pbmp->Height); + } + m_DisEvent++; + ClientWidth = xw; + ClientHeight = yw; + m_DisEvent--; +// ClientWidth = pbmp->Width; +// ClientHeight = pbmp->Height; + } + Timer->Enabled = sw; + UpdateViewSize(); + UpdateTitle(); + ShowModal(); + Timer->Enabled = FALSE; +} +//--------------------------------------------------------------------- +void __fastcall TZoomViewDlg::FormPaint(TObject *Sender) +{ + if( pBitmap == NULL ) return; + if( pBitmapS != NULL ){ + int x = (ClientWidth - pBitmapS->Width)/2; + int y = (ClientHeight - pBitmapS->Height)/2; + Canvas->Draw(x, y, pBitmapS); + } + else { + UpdateViewSize(); + TRect rc; + rc.Left = (ClientWidth - m_ViewXW)/2; + rc.Top = (ClientHeight - m_ViewYW)/2; + rc.Right = rc.Left + m_ViewXW; + rc.Bottom = rc.Top + m_ViewYW; + ::SetStretchBltMode(Canvas->Handle, HALFTONE); + Canvas->StretchDraw(rc, (TGraphic*)pBitmap); + } +#if 0 + char bf[256]; + sprintf(bf, "%ux%u", ClientWidth, ClientHeight); + Canvas->Font->Color = clBlack; + Canvas->TextOut(0, 0, bf); +#endif +} +//--------------------------------------------------------------------- +void __fastcall TZoomViewDlg::TimerTimer(TObject *Sender) +{ + if( (Visible == TRUE) && (pBitmapS == NULL) ) FormPaint(NULL); +} +//--------------------------------------------------------------------------- +void __fastcall TZoomViewDlg::FormResize(TObject *Sender) +{ + if( m_DisEvent ) return; + m_DisEvent++; + if( ClientHeight < 100 ) ClientHeight = 100; + if( ClientWidth < 100 ) ClientWidth = 100; + + if( (ClientWidth != pBitmap->Width) || (ClientHeight != pBitmap->Height) ){ + double XW = pBitmap->Width; + double YW = pBitmap->Height; + double xw = ClientWidth; + double yw = ClientHeight; + if( Width > m_MaxX ) xw = m_MaxX; + if( Height > m_MaxY ) yw = m_MaxY; + + double xv = (xw / Width) * XW; + double yv = (yw / Height) * YW; + if( yv < xv ){ + yw = xw * YW / XW; + } + else { + xw = yw * XW / YW; + } + if( ABS(xw - ClientWidth) >= 2 ) ClientWidth = xw; + if( ABS(yw - ClientHeight) >= 2 ) ClientHeight = yw; + UpdateViewSize(); + } + else { + delete pBitmapS; + pBitmapS = NULL; + UpdateTitle(); + } + if( pBitmapS != NULL ){ + StretchCopy(pBitmap); + } + Invalidate(); + m_DisEvent--; + UpdateTitle(); +} +//--------------------------------------------------------------------------- +// 高度な伸縮コピー +void __fastcall TZoomViewDlg::StretchCopy(Graphics::TBitmap *pbmp) +{ + if( pBitmapS == NULL ){ + pBitmapS = new Graphics::TBitmap; + } + pBitmapS->PixelFormat = pf24bit; + pBitmapS->Width = m_ViewXW; + pBitmapS->Height = m_ViewYW; + ::StretchCopy(pBitmapS, NULL, pbmp, NULL); +} +//--------------------------------------------------------------------------- +void __fastcall TZoomViewDlg::FormClick(TObject *Sender) +{ + if( (pBitmap->Width == ClientWidth) && (pBitmap->Height == ClientHeight) ) return; + if( pBitmapS != NULL ){ + delete pBitmapS; + pBitmapS = NULL; + } + else { + StretchCopy(pBitmap); + } + UpdateTitle(); + Invalidate(); +} +//--------------------------------------------------------------------------- +void __fastcall TZoomViewDlg::UpdateViewSize(void) +{ + m_ViewXW = ClientWidth; + m_ViewYW = ClientHeight; + if( WindowState == wsMaximized ){ + KeepAspect(m_ViewXW, m_ViewYW, pBitmap->Width, pBitmap->Height); + } +} + + + \ No newline at end of file